1 line
961 KiB
JavaScript
1 line
961 KiB
JavaScript
(self.webpackChunktimetrex=self.webpackChunktimetrex||[]).push([["attendance-timesheet-TimeSheetViewController","filebrowser-TImage"],{1469:(__unused_webpack_module,__unused_webpack_exports,__webpack_require__)=>{eval("/* provided dependency */ var jQuery = __webpack_require__(9755);\n( function( $ ) {\n\n\t$.fn.TImage = function( options ) {\n\n\t\tGlobal.addCss( 'global/widgets/filebrowser/TImageBrowser.css' );\n\t\tvar opts = $.extend( {}, $.fn.TImage.defaults, options );\n\n\t\tvar $this = this;\n\t\tvar field;\n\n\t\tthis.clearErrorStyle = function() {\n\n\t\t};\n\n\t\tthis.getField = function() {\n\t\t\treturn field;\n\t\t};\n\n\t\tthis.getValue = function() {\n\t\t\treturn null;\n\t\t};\n\n\t\tthis.setValue = function( val ) {\n\t\t\tif ( !val ) {\n\t\t\t\tthis.attr( 'src', '' );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar d = new Date();\n\t\t\tthis.attr( 'src', val + '&t=' + d.getTime() );\n\n\t\t};\n\n\t\tthis.each( function() {\n\n\t\t\tvar o = $.meta ? $.extend( {}, opts, $( this ).data() ) : opts;\n\n\t\t\tfield = o.field;\n\n\t\t} );\n\n\t\treturn this;\n\n\t};\n\n\t$.fn.TImage.defaults = {};\n\n\t$( document ).on( 'mouseover', '.file-browser img', function( e ) {\n\t\tvar $this_image_widget = $( e.target ).parents( '.file-browser' );\n\n\t\tif ( !$( '.file_browser_overlay' )[0] && $( e.target ).attr( 'enable-delete' ) == 1 ) {\n\t\t\tvar height = $( e.target ).height();\n\t\t\tvar top = ( height - 32 ) / 2;\n\t\t\tvar left = top;\n\n\t\t\tvar file_browser_overlay = $( '<div class=\"file_browser_overlay\"><img src=\"theme/default/images/delete-512.png\" style=\"position:absolute;width:32px;height:32px;top:' + top + 'px;left:' + left + 'px;\"></div>' );\n\t\t\tfile_browser_overlay.css( 'position', 'absolute' );\n\t\t\tfile_browser_overlay.css( 'top', '0px' );\n\t\t\tfile_browser_overlay.css( 'left', '0' );\n\t\t\tfile_browser_overlay.css( 'cursor', 'pointer' );\n\t\t\tfile_browser_overlay.css( 'height', height + 'px' );\n\t\t\tfile_browser_overlay.css( 'width', '100%' );\n\t\t\tfile_browser_overlay.css( 'background', 'rgba(255,255,255,0.85)' );\n\n\t\t\t$( e.target ).parents( '.file-browser' ).append( file_browser_overlay );\n\n\t\t\t$( document ).on( 'click', '.file_browser_overlay', function( e ) {\n\t\t\t\tvar img_src = $( e.target ).parent().find( 'img' ).attr( 'src' );\n\t\t\t\tTAlertManager.showConfirmAlert( $.i18n._( 'This will permanently delete the image. Are you sure?' ), '', function( flag ) {\n\t\t\t\t\tif ( flag ) {\n\t\t\t\t\t\tvar e = { type: 'deleteClick', message: 'Delete image clicked.', time: new Date() };\n\t\t\t\t\t\t$this_image_widget.trigger( e );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t} );\n\n\t\t\t$( document ).on( 'mouseleave', '.file-browser', function() {\n\t\t\t\t$( document ).off( 'click', '.file_browser_overlay' );\n\t\t\t\tif ( $( '.file_browser_overlay' )[0] ) {\n\t\t\t\t\tvar file_browser_overlay = $( this ).find( '.file_browser_overlay' );\n\t\t\t\t\tfile_browser_overlay.off().remove();\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t} );\n\n} )( jQuery );//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTQ2OS5qcyIsIm1hcHBpbmdzIjoiO0FBQUE7O0FBRUE7O0FBRUE7QUFDQSx5QkFBeUI7O0FBRXpCO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQSxnQ0FBZ0M7O0FBRWhDOztBQUVBLElBQUk7O0FBRUo7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw0SUFBNEksV0FBVyxZQUFZLGtCQUFrQixvQkFBb0I7QUFDek07QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBLE1BQU07QUFDTixLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEdBQUc7O0FBRUgsRUFBRSxHQUFHLE1BQU0iLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9pbnRlcmZhY2UvaHRtbDUvZ2xvYmFsL3dpZGdldHMvZmlsZWJyb3dzZXIvVEltYWdlLmpzPzllOTIiXSwic291cmNlc0NvbnRlbnQiOlsiKCBmdW5jdGlvbiggJCApIHtcblxuXHQkLmZuLlRJbWFnZSA9IGZ1bmN0aW9uKCBvcHRpb25zICkge1xuXG5cdFx0R2xvYmFsLmFkZENzcyggJ2dsb2JhbC93aWRnZXRzL2ZpbGVicm93c2VyL1RJbWFnZUJyb3dzZXIuY3NzJyApO1xuXHRcdHZhciBvcHRzID0gJC5leHRlbmQoIHt9LCAkLmZuLlRJbWFnZS5kZWZhdWx0cywgb3B0aW9ucyApO1xuXG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgZmllbGQ7XG5cblx0XHR0aGlzLmNsZWFyRXJyb3JTdHlsZSA9IGZ1bmN0aW9uKCkge1xuXG5cdFx0fTtcblxuXHRcdHRoaXMuZ2V0RmllbGQgPSBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiBmaWVsZDtcblx0XHR9O1xuXG5cdFx0dGhpcy5nZXRWYWx1ZSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0fTtcblxuXHRcdHRoaXMuc2V0VmFsdWUgPSBmdW5jdGlvbiggdmFsICkge1xuXHRcdFx0aWYgKCAhdmFsICkge1xuXHRcdFx0XHR0aGlzLmF0dHIoICdzcmMnLCAnJyApO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0XHR2YXIgZCA9IG5ldyBEYXRlKCk7XG5cdFx0XHR0aGlzLmF0dHIoICdzcmMnLCB2YWwgKyAnJnQ9JyArIGQuZ2V0VGltZSgpICk7XG5cblx0XHR9O1xuXG5cdFx0dGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyIG8gPSAkLm1ldGEgPyAkLmV4dGVuZCgge30sIG9wdHMsICQoIHRoaXMgKS5kYXRhKCkgKSA6IG9wdHM7XG5cblx0XHRcdGZpZWxkID0gby5maWVsZDtcblxuXHRcdH0gKTtcblxuXHRcdHJldHVybiB0aGlzO1xuXG5cdH07XG5cblx0JC5mbi5USW1hZ2UuZGVmYXVsdHMgPSB7fTtcblxuXHQkKCBkb2N1bWVudCApLm9uKCAnbW91c2VvdmVyJywgJy5maWxlLWJyb3dzZXIgaW1nJywgZnVuY3Rpb24oIGUgKSB7XG5cdFx0dmFyICR0aGlzX2ltYWdlX3dpZGdldCA9ICQoIGUudGFyZ2V0ICkucGFyZW50cyggJy5maWxlLWJyb3dzZXInICk7XG5cblx0XHRpZiAoICEkKCAnLmZpbGVfYnJvd3Nlcl9vdmVybGF5JyApWzBdICYmICQoIGUudGFyZ2V0ICkuYXR0ciggJ2VuYWJsZS1kZWxldGUnICkgPT0gMSApIHtcblx0XHRcdHZhciBoZWlnaHQgPSAkKCBlLnRhcmdldCApLmhlaWdodCgpO1xuXHRcdFx0dmFyIHRvcCA9ICggaGVpZ2h0IC0gMzIgKSAvIDI7XG5cdFx0XHR2YXIgbGVmdCA9IHRvcDtcblxuXHRcdFx0dmFyIGZpbGVfYnJvd3Nlcl9vdmVybGF5ID0gJCggJzxkaXYgY2xhc3M9XCJmaWxlX2Jyb3dzZXJfb3ZlcmxheVwiPjxpbWcgc3JjPVwidGhlbWUvZGVmYXVsdC9pbWFnZXMvZGVsZXRlLTUxMi5wbmdcIiBzdHlsZT1cInBvc2l0aW9uOmFic29sdXRlO3dpZHRoOjMycHg7aGVpZ2h0OjMycHg7dG9wOicgKyB0b3AgKyAncHg7bGVmdDonICsgbGVmdCArICdweDtcIj48L2Rpdj4nICk7XG5cdFx0XHRmaWxlX2Jyb3dzZXJfb3ZlcmxheS5jc3MoICdwb3NpdGlvbicsICdhYnNvbHV0ZScgKTtcblx0XHRcdGZpbGVfYnJvd3Nlcl9vdmVybGF5LmNzcyggJ3RvcCcsICcwcHgnICk7XG5cdFx0XHRmaWxlX2Jyb3dzZXJfb3ZlcmxheS5jc3MoICdsZWZ0JywgJzAnICk7XG5cdFx0XHRmaWxlX2Jyb3dzZXJfb3ZlcmxheS5jc3MoICdjdXJzb3InLCAncG9pbnRlcicgKTtcblx0XHRcdGZpbGVfYnJvd3Nlcl9vdmVybGF5LmNzcyggJ2hlaWdodCcsIGhlaWdodCArICdweCcgKTtcblx0XHRcdGZpbGVfYnJvd3Nlcl9vdmVybGF5LmNzcyggJ3dpZHRoJywgJzEwMCUnICk7XG5cdFx0XHRmaWxlX2Jyb3dzZXJfb3ZlcmxheS5jc3MoICdiYWNrZ3JvdW5kJywgJ3JnYmEoMjU1LDI1NSwyNTUsMC44NSknICk7XG5cblx0XHRcdCQoIGUudGFyZ2V0ICkucGFyZW50cyggJy5maWxlLWJyb3dzZXInICkuYXBwZW5kKCBmaWxlX2Jyb3dzZXJfb3ZlcmxheSApO1xuXG5cdFx0XHQkKCBkb2N1bWVudCApLm9uKCAnY2xpY2snLCAnLmZpbGVfYnJvd3Nlcl9vdmVybGF5JywgZnVuY3Rpb24oIGUgKSB7XG5cdFx0XHRcdHZhciBpbWdfc3JjID0gJCggZS50YXJnZXQgKS5wYXJlbnQoKS5maW5kKCAnaW1nJyApLmF0dHIoICdzcmMnICk7XG5cdFx0XHRcdFRBbGVydE1hbmFnZXIuc2hvd0NvbmZpcm1BbGVydCggJC5pMThuLl8oICdUaGlzIHdpbGwgcGVybWFuZW50bHkgZGVsZXRlIHRoZSBpbWFnZS4gQXJlIHlvdSBzdXJlPycgKSwgJycsIGZ1bmN0aW9uKCBmbGFnICkge1xuXHRcdFx0XHRcdGlmICggZmxhZyApIHtcblx0XHRcdFx0XHRcdHZhciBlID0geyB0eXBlOiAnZGVsZXRlQ2xpY2snLCBtZXNzYWdlOiAnRGVsZXRlIGltYWdlIGNsaWNrZWQuJywgdGltZTogbmV3IERhdGUoKSB9O1xuXHRcdFx0XHRcdFx0JHRoaXNfaW1hZ2Vfd2lkZ2V0LnRyaWdnZXIoIGUgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKTtcblx0XHRcdH0gKTtcblxuXHRcdFx0JCggZG9jdW1lbnQgKS5vbiggJ21vdXNlbGVhdmUnLCAnLmZpbGUtYnJvd3NlcicsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQkKCBkb2N1bWVudCApLm9mZiggJ2NsaWNrJywgJy5maWxlX2Jyb3dzZXJfb3ZlcmxheScgKTtcblx0XHRcdFx0aWYgKCAkKCAnLmZpbGVfYnJvd3Nlcl9vdmVybGF5JyApWzBdICkge1xuXHRcdFx0XHRcdHZhciBmaWxlX2Jyb3dzZXJfb3ZlcmxheSA9ICQoIHRoaXMgKS5maW5kKCAnLmZpbGVfYnJvd3Nlcl9vdmVybGF5JyApO1xuXHRcdFx0XHRcdGZpbGVfYnJvd3Nlcl9vdmVybGF5Lm9mZigpLnJlbW92ZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cdFx0fVxuXHR9ICk7XG5cbn0gKSggalF1ZXJ5ICk7Il0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///1469\n")},2693:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("// ESM COMPAT FLAG\n__webpack_require__.r(__webpack_exports__);\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n \"TimeSheetViewController\": () => (/* binding */ TimeSheetViewController)\n});\n\n// EXTERNAL MODULE: ./interface/html5/global/widgets/filebrowser/TImage.js\nvar TImage = __webpack_require__(1469);\n// EXTERNAL MODULE: ./interface/html5/services/TTVueUtils.js\nvar TTVueUtils = __webpack_require__(4966);\n// EXTERNAL MODULE: ./node_modules/vue/dist/vue.esm-bundler.js + 6 modules\nvar vue_esm_bundler = __webpack_require__(5166);\n;// CONCATENATED MODULE: ./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[1]!./node_modules/vue-loader/dist/index.js??ruleSet[1].rules[6].use[0]!./interface/html5/components/timesheet/TimeSheetControlBar.vue?vue&type=template&id=71fa0b53&scoped=true\n\n\nconst _withScopeId = n => (_pushScopeId(\"data-v-71fa0b53\"),n=n(),_popScopeId(),n)\nconst _hoisted_1 = { class: \"tt-horizontal-vue-bar\" }\nconst _hoisted_2 = /*#__PURE__*/(0,vue_esm_bundler/* createStaticVNode */.uE)(\"<div class=\\\"bar-column left\\\" data-v-71fa0b53></div><div class=\\\"bar-column center\\\" data-v-71fa0b53><div class=\\\"bar-column date-chooser-div\\\" data-v-71fa0b53></div><div class=\\\"bar-column employee-nav-div\\\" data-v-71fa0b53><span class=\\\"navigation-label\\\" data-v-71fa0b53></span><img class=\\\"left-click\\\" data-v-71fa0b53><div class=\\\"navigation-widget-div\\\" data-v-71fa0b53></div><img class=\\\"right-click\\\" data-v-71fa0b53></div></div>\", 2)\nconst _hoisted_4 = { class: \"bar-column right\" }\nconst _hoisted_5 = { class: \"bar-column punch-manual\" }\nconst _hoisted_6 = { class: \"bar-column menu-item\" }\n\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n const _component_SelectButton = (0,vue_esm_bundler/* resolveComponent */.up)(\"SelectButton\")\n const _component_TTContextButton = (0,vue_esm_bundler/* resolveComponent */.up)(\"TTContextButton\")\n\n return ((0,vue_esm_bundler/* openBlock */.wg)(), (0,vue_esm_bundler/* createElementBlock */.iD)(\"div\", _hoisted_1, [\n _hoisted_2,\n (0,vue_esm_bundler/* createElementVNode */._)(\"div\", _hoisted_4, [\n (0,vue_esm_bundler/* createElementVNode */._)(\"div\", _hoisted_5, [\n (0,vue_esm_bundler/* createVNode */.Wm)(_component_SelectButton, {\n modelValue: $data.punch_mode_selected,\n \"onUpdate:modelValue\": _cache[0] || (_cache[0] = $event => (($data.punch_mode_selected) = $event)),\n options: $data.punch_modes,\n optionLabel: \"label\",\n optionValue: \"value\",\n onClick: _cache[1] || (_cache[1] = $event => {this.onPunchModeChange();})\n }, null, 8 /* PROPS */, [\"modelValue\", \"options\"])\n ]),\n (0,vue_esm_bundler/* createElementVNode */._)(\"div\", _hoisted_6, [\n (0,vue_esm_bundler/* createVNode */.Wm)(_component_TTContextButton, {\n class: (0,vue_esm_bundler/* normalizeClass */.C_)(['no-wrap']),\n items: $data.timesheet_settings_options\n }, null, 8 /* PROPS */, [\"items\"])\n ])\n ])\n ]))\n}\n;// CONCATENATED MODULE: ./interface/html5/components/timesheet/TimeSheetControlBar.vue?vue&type=template&id=71fa0b53&scoped=true\n\n// EXTERNAL MODULE: ./node_modules/primevue/selectbutton/selectbutton.esm.js\nvar selectbutton_esm = __webpack_require__(1109);\n// EXTERNAL MODULE: ./interface/html5/components/context_menu/TTContextButton.vue + 24 modules\nvar TTContextButton = __webpack_require__(777);\n;// CONCATENATED MODULE: ./node_modules/vue-loader/dist/index.js??ruleSet[1].rules[6].use[0]!./interface/html5/components/timesheet/TimeSheetControlBar.vue?vue&type=script&lang=js\n/* provided dependency */ var $ = __webpack_require__(9755);\n\n\n\n\n/* harmony default export */ const TimeSheetControlBarvue_type_script_lang_js = ({\n name: \"TimeSheetControlBar\",\n props: {\n component_id: { // passed in via root props from TimeSheetViewController\n type: String,\n default: null\n },\n onPunchModeChange: { // passed in via root props from TimeSheetViewController\n type: Function,\n default: null\n },\n onShowWageClick: { // passed in via root props from TimeSheetViewController\n type: Function,\n default: null\n },\n onTimezoneClick: { // passed in via root props from TimeSheetViewController\n type: Function,\n default: null\n }\n },\n data() {\n return {\n punch_mode_selected: 'punch',\n punch_modes: [\n { label: $.i18n._( 'Punch' ), value: 'punch' },\n { label: $.i18n._( 'Manual' ), value: 'manual' },\n ],\n timesheet_settings_options: [\n {\n label: $.i18n._( 'Show Wages' ),\n id: 'show_wages',\n no_group_label: true,\n vue_icon: 'tticon tticon-settings_black_24dp',\n action_group: 'timesheet_settings',\n multi_select_group: 1,\n visible: PermissionManager.checkTopLevelPermission( 'Wage' ),\n command: () => {\n if( this.onShowWageClick && typeof this.onShowWageClick === 'function' ) {\n this.onShowWageClick( this.timesheet_settings_options[0].active );\n }\n }\n },\n {\n label: $.i18n._( 'Use Employee Timezone' ),\n id: 'use_employee_timezone',\n no_group_label: true,\n vue_icon: 'tticon tticon-settings_black_24dp',\n action_group: 'timesheet_settings',\n multi_select_group: 2,\n visible: ( PermissionManager.validate( 'punch', 'view' ) || PermissionManager.validate( 'punch', 'view_child' ) ),\n command: () => {\n if( this.onTimezoneClick && typeof this.onTimezoneClick === 'function' ) {\n this.onTimezoneClick( this.timesheet_settings_options[1].active );\n }\n }\n },\n ]\n }\n },\n // watch: {\n // punch_mode_selected: function ( val ) {\n // if( this.onPunchModeChange && typeof this.onPunchModeChange === 'function' ) {\n // this.onPunchModeChange( val, false );\n // }\n // },\n // },\n computed: {\n getPunchMode() { // This way the value is cached if it doesnt change.\n return this.punch_mode_selected;\n }\n },\n methods: {\n setPunchMode( new_value ) {\n if ( new_value === 'punch' || new_value === 'manual' ) { // validate the input potentially coming from outside Vue.\n this.punch_mode_selected = new_value;\n return true;\n } else {\n Debug.Error( 'Invalid parameters passed to function: ', 'TimeSheetControlBar.vue', 'TimeSheetControlBar', 'setPunchMode', 1 );\n return false;\n }\n },\n getTimesheetSettingsState( item_id ) {\n var item = this.timesheet_settings_options.find( element => element.id === item_id );\n if( item ) {\n return item.active;\n } else {\n Debug.Error( 'Item not found ('+ item_id +'). Check supplied id.', 'TimeSheetControlBar.vue', 'TimeSheetControlBar', 'getTimesheetSettingsState', 1 );\n return undefined;\n }\n },\n setTimesheetSettingsState( item_id, value ) {\n var item = this.timesheet_settings_options.find( element => element.id === item_id );\n if( item ) {\n item.active = value;\n } else {\n Debug.Error( 'Item not found ('+ item_id +'). Check supplied id.', 'TimeSheetControlBar.vue', 'TimeSheetControlBar', 'setTimesheetSettingsState', 1 );\n }\n }\n },\n components: {\n SelectButton: selectbutton_esm/* default */.Z,\n TTContextButton: TTContextButton/* default */.Z\n }\n});\n\n;// CONCATENATED MODULE: ./interface/html5/components/timesheet/TimeSheetControlBar.vue?vue&type=script&lang=js\n \n// EXTERNAL MODULE: ./node_modules/vue-loader/dist/exportHelper.js\nvar exportHelper = __webpack_require__(3744);\n;// CONCATENATED MODULE: ./interface/html5/components/timesheet/TimeSheetControlBar.vue\n\n\n\n\n;\n\n\nconst __exports__ = /*#__PURE__*/(0,exportHelper/* default */.Z)(TimeSheetControlBarvue_type_script_lang_js, [['render',render],['__scopeId',\"data-v-71fa0b53\"]])\n\n/* harmony default export */ const TimeSheetControlBar = (__exports__);\n// EXTERNAL MODULE: ./interface/html5/global/TTUUID.js\nvar TTUUID = __webpack_require__(4936);\n// EXTERNAL MODULE: ./interface/html5/global/Global.js\nvar Global = __webpack_require__(9490);\n;// CONCATENATED MODULE: ./interface/html5/views/attendance/timesheet/TimeSheetViewController.js\n/* provided dependency */ var _ = __webpack_require__(9050);\n/* provided dependency */ var TimeSheetViewController_$ = __webpack_require__(9755);\n\n\n\n\n\n\nclass TimeSheetViewController extends BaseViewController {\n\tconstructor( options = {} ) {\n\t\t_.defaults( options, {\n\t\t\tel: '#timesheet_view_container', //Must set el here and can only set string, so events can work\n\t\t\t// _required_files: {\n\t\t\t// \t10: ['TImage'],\n\t\t\t// \t15: ['leaflet-timetrex']\n\t\t\t// },\n\t\t\tstatus_array: null,\n\t\t\ttype_array: null,\n\t\t\temployee_nav: null,\n\t\t\tstart_date_picker: null,\n\t\t\tfull_timesheet_data: null, //full timesheet data\n\t\t\tfull_format: 'ddd-MMM-DD-YYYY',\n\t\t\tweekly_format: 'ddd, MMM DD',\n\t\t\tday_format: 'ddd',\n\t\t\tdate_format: 'MMM DD',\n\t\t\tstart_date: null,\n\t\t\tend_date: null,\n\t\t\tselect_cells_Array: [], //Timesheet grid\n\t\t\tselect_punches_array: [], //Timesheet grid.\n\t\t\tabsence_select_cells_Array: [], //Absence grid\n\t\t\taccumulated_time_cells_array: [],\n\t\t\tpremium_cells_array: [],\n\t\t\ttimesheet_data_source: null,\n\t\t\taccumulated_time_source: null,\n\t\t\taccumulated_time_grid: null,\n\t\t\taccumulated_time_source_map: null,\n\t\t\tbranch_grid: null,\n\t\t\tbranch_source_map: null,\n\t\t\tbranch_source: null,\n\t\t\tdepartment_grid: null,\n\t\t\tdepartment_source_map: null,\n\t\t\tdepartment_source: null,\n\t\t\tjob_grid: null,\n\t\t\tjob_source_map: null,\n\t\t\tjob_source: null,\n\t\t\tjob_item_grid: null,\n\t\t\tjob_item_source_map: null,\n\t\t\tjob_item_source: null,\n\t\t\tpunch_tag_source_map: null,\n\t\t\tpunch_tag_source: null,\n\t\t\tpremium_grid: null,\n\t\t\tpremium_source_map: null,\n\t\t\tpremium_source: null,\n\t\t\tabsence_grid: null,\n\t\t\tabsence_source: null,\n\t\t\tabsence_original_source: null,\n\t\t\taccumulated_total_grid: null,\n\t\t\taccumulated_total_grid_source_map: null,\n\t\t\taccumulated_total_grid_source: null,\n\t\t\tpunch_note_grid: null,\n\t\t\tpunch_note_grid_source: null,\n\t\t\tverification_grid: null,\n\t\t\tverification_grid_source: null,\n\t\t\tgrid_dic: null,\n\t\t\tpay_period_map: null,\n\t\t\tpay_period_data: null,\n\t\t\ttimesheet_verify_data: null,\n\t\t\tapi_timesheet: null,\n\t\t\tapi_user_date_total: null,\n\t\t\tapi_date: null,\n\t\t\tapi_station: null,\n\t\t\tapi_punch: null,\n\t\t\tabsence_model: false,\n\t\t\tselect_drag_menu_id: '', //Do drag move or copy\n\t\t\tis_mass_adding: false,\n\t\t\tdepartment_cell_count: 0,\n\t\t\tbranch_cell_count: 0,\n\t\t\tpremium_cell_count: 0,\n\t\t\tjob_cell_count: 0,\n\t\t\ttask_cell_count: 0,\n\t\t\tpunch_tag_cell_count: 0,\n\t\t\tabsence_cell_count: 0,\n\t\t\tpunch_note_account: 0,\n\t\t\tshow_navigation_box: true,\n\t\t\tstation: null,\n\t\t\tscroll_position: 0,\n\t\t\tjob_api: null,\n\t\t\tjob_item_api: null,\n\t\t\tuser_group_id: null,\n\t\t\tpunch_tag_api: null,\n\t\t\tuser_api: null,\n\t\t\tdepartment_api: null,\n\t\t\tdefault_punch_tag: [],\n\t\t\tprevious_punch_tag_selection: [],\n\t\t\tapi_absence_policy: null,\n\t\t\tpre_total_time: null,\n\t\t\tabsence_available_balance_dataList: {},\n\t\t\tavailable_balance_info: null,\n\t\t\tshow_job_ui: false,\n\t\t\tshow_job_item_ui: false,\n\t\t\tshow_punch_tag_ui: false,\n\t\t\tshow_branch_ui: false,\n\t\t\tshow_department_ui: false,\n\t\t\tshow_good_quantity_ui: false,\n\t\t\tshow_bad_quantity_ui: false,\n\t\t\tshow_note_ui: false,\n\t\t\tshow_station_ui: false,\n\t\t\tshow_absence_job_ui: false,\n\t\t\tshow_absence_job_item_ui: false,\n\t\t\tshow_absence_punch_tag_ui: false,\n\t\t\tshow_absence_branch_ui: false,\n\t\t\tshow_absence_department_ui: false,\n\t\t\tholiday_data_dic: {},\n\t\t\tgrid_div: null,\n\t\t\tactual_time_label: null,\n\t\t\tcolumn_maps: null,\n\t\t\taccmulated_order_map: {},\n\t\t\turl_args_before_set_date_url: {},\n\t\t\tallow_auto_switch: true,\n\t\t\tvue_control_bar_id: '',\n\t\t\tprevious_absence_policy_id: false,\n\t\t\tevents: {},\n\t\t\t//Issue #3286 - Users without permission to display \"Current View\" dropdown still need to load select layout from user generic data\n\t\t\t//This is to ensure the API attempts to update the current layout and not create a new one causing a validation error.\n\t\t\tforce_get_select_layout: true\n\t\t} );\n\n\t\tsuper( options );\n\t}\n\n\tinit( options ) {\n\t\t////this._super('initialize', options );\n\t\tthis.permission_id = 'punch';\n\t\tthis.viewId = 'TimeSheet';\n\t\tthis.script_name = 'TimeSheetView';\n\t\tthis.context_menu_name = TimeSheetViewController_$.i18n._( 'TimeSheet' );\n\t\tthis.navigation_label = TimeSheetViewController_$.i18n._( 'TimeSheet' );\n\t\tthis.api = TTAPI.APIPunch;\n\t\tthis.api_timesheet = TTAPI.APITimeSheet;\n\t\tthis.api_user_date_total = TTAPI.APIUserDateTotal;\n\t\tthis.api_date = TTAPI.APITTDate;\n\t\tthis.api_station = TTAPI.APIStation;\n\t\tthis.api_punch = TTAPI.APIPunch;\n\t\tif ( ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ) {\n\t\t\tthis.job_api = TTAPI.APIJob;\n\t\t\tthis.job_item_api = TTAPI.APIJobItem;\n\t\t\tthis.punch_tag_api = TTAPI.APIPunchTag;\n\t\t\tthis.department_api = TTAPI.APIDepartment;\n\t\t}\n\t\tthis.api_absence_policy = TTAPI.APIAbsencePolicy;\n\t\tthis.scroll_position = 0;\n\t\tthis.grid_dic = {};\n\t\t// this.event_bus = new TTEventBus({ view_id: this.viewId }); // TimeSheet does not use TTEventBus yet, its currently using direct access to the Vue component by reference, as a proof of concept. Best to use TTEventBus for future work though.\n\n\t\tthis.initPermission();\n\t\tthis.render();\n\t\tthis.buildContextMenu();\n\t\tthis.initData();\n\t}\n\n\tinitEditView() {\n\t\tTTPromise.resolve( 'TimeSheetViewController', 'addclick' );\n\t\tsuper.initEditView();\n\t}\n\n\tonSubViewRemoved( is_cancel ) {\n\t\tif ( !is_cancel ) {\n\t\t\tthis.search();\n\t\t}\n\n\t\tif ( !this.edit_view ) {\n\t\t\tthis.setDefaultMenu();\n\t\t} else {\n\t\t\tthis.setEditMenu();\n\t\t}\n\t}\n\n\tsetScrollPosition() {\n\t\tif ( this.scroll_position > 0 ) {\n\t\t\tthis.grid_div.scrollTop( this.scroll_position );\n\t\t}\n\t}\n\n\tpunchModeValidate( p_id ) {\n\t\tif ( !p_id ) {\n\t\t\tp_id = 'punch';\n\t\t}\n\n\t\tif ( PermissionManager.validate( p_id, 'punch_timesheet' ) &&\n\t\t\tPermissionManager.validate( p_id, 'manual_timesheet' ) ) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tgetPunchPermissionType() {\n\t\treturn this.absence_model ? 'absence' : 'punch';\n\t}\n\n\tjobUIValidate( p_id ) {\n\n\t\tif ( !p_id ) {\n\t\t\tp_id = 'punch';\n\t\t}\n\n\t\tif (Global/* Global.getProductEdition */.x.getProductEdition() >= 20 && PermissionManager.validate( 'job', 'enabled' ) &&\n\t\t\tPermissionManager.validate( p_id, 'edit_job' ) ) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tjobItemUIValidate( p_id ) {\n\n\t\tif ( !p_id ) {\n\t\t\tp_id = 'punch';\n\t\t}\n\n\t\tif (Global/* Global.getProductEdition */.x.getProductEdition() >= 20 && PermissionManager.validate( p_id, 'edit_job_item' ) ) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpunchTagUIValidate( p_id ) {\n\n\t\tif ( !p_id ) {\n\t\t\tp_id = 'punch';\n\t\t}\n\n\t\tif (Global/* Global.getProductEdition */.x.getProductEdition() >= 20 && PermissionManager.validate( p_id, 'edit_punch_tag' ) ) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t//Refresh to clear warnning messages after saving from employee edit view\n\tupdateSelectUserAndRefresh( new_item ) {\n\n\t\tthis.employee_nav.updateSelectItem( new_item );\n\n\t\tthis.search();\n\t}\n\n\tbranchUIValidate( p_id ) {\n\n\t\tif ( !p_id ) {\n\t\t\tp_id = 'punch';\n\t\t}\n\n\t\tif ( PermissionManager.validate( p_id, 'edit_branch' ) ) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tdepartmentUIValidate( p_id ) {\n\n\t\tif ( !p_id ) {\n\t\t\tp_id = 'punch';\n\t\t}\n\n\t\tif ( PermissionManager.validate( p_id, 'edit_department' ) ) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tgoodQuantityUIValidate( p_id ) {\n\n\t\tif ( !p_id ) {\n\t\t\tp_id = 'punch';\n\t\t}\n\n\t\tif ( PermissionManager.validate( p_id, 'edit_quantity' ) ) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tbadQuantityUIValidate( p_id ) {\n\n\t\tif ( !p_id ) {\n\t\t\tp_id = 'punch';\n\t\t}\n\n\t\tif ( PermissionManager.validate( p_id, 'edit_quantity' ) &&\n\t\t\tPermissionManager.validate( p_id, 'edit_bad_quantity' ) ) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tlocationUIValidate( p_id ) {\n\n\t\tif ( !p_id ) {\n\t\t\tp_id = 'punch';\n\t\t}\n\n\t\tif ( PermissionManager.validate( p_id, 'edit_location' ) ) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tnoteUIValidate( p_id ) {\n\n\t\tif ( !p_id ) {\n\t\t\tp_id = 'punch';\n\t\t}\n\n\t\tif ( PermissionManager.validate( p_id, 'edit_note' ) ) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tstationValidate() {\n\t\tif ( PermissionManager.validate( 'station', 'enabled' ) ) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/* jshint ignore:start */\n\n\t//Special permission check for views, need override\n\tinitPermission() {\n\t\tsuper.initPermission();\n\n\t\tif ( !PermissionManager.validate( 'punch', 'view' ) && !PermissionManager.validate( 'punch', 'view_child' ) ) {\n\t\t\tthis.show_navigation_box = false;\n\t\t\tthis.show_search_tab = false;\n\t\t} else {\n\t\t\tthis.show_navigation_box = true;\n\t\t\tthis.show_search_tab = true;\n\t\t}\n\n\t\tif ( this.punchModeValidate() ) {\n\t\t\tthis.show_punch_mode_ui = true;\n\t\t} else {\n\t\t\tthis.show_punch_mode_ui = false;\n\t\t}\n\n\t\tthis.allow_auto_switch && this.show_punch_mode_ui && ( this.is_auto_switch = true );\n\n\t\tif ( this.jobUIValidate() ) {\n\t\t\tthis.show_job_ui = true;\n\t\t} else {\n\t\t\tthis.show_job_ui = false;\n\t\t}\n\n\t\tif ( this.jobItemUIValidate() ) {\n\t\t\tthis.show_job_item_ui = true;\n\t\t} else {\n\t\t\tthis.show_job_item_ui = false;\n\t\t}\n\n\n\t\tif ( this.punchTagUIValidate() ) {\n\t\t\tthis.show_punch_tag_ui = true;\n\t\t} else {\n\t\t\tthis.show_punch_tag_ui = false;\n\t\t}\n\n\t\tif ( this.branchUIValidate() ) {\n\t\t\tthis.show_branch_ui = true;\n\t\t} else {\n\t\t\tthis.show_branch_ui = false;\n\t\t}\n\n\t\tif ( this.departmentUIValidate() ) {\n\t\t\tthis.show_department_ui = true;\n\t\t} else {\n\t\t\tthis.show_department_ui = false;\n\t\t}\n\n\t\tif ( this.goodQuantityUIValidate() ) {\n\t\t\tthis.show_good_quantity_ui = true;\n\t\t} else {\n\t\t\tthis.show_good_quantity_ui = false;\n\t\t}\n\n\t\tif ( this.badQuantityUIValidate() ) {\n\t\t\tthis.show_bad_quantity_ui = true;\n\t\t} else {\n\t\t\tthis.show_bad_quantity_ui = false;\n\t\t}\n\n\t\tif ( this.noteUIValidate() ) {\n\t\t\tthis.show_note_ui = true;\n\t\t} else {\n\t\t\tthis.show_note_ui = false;\n\t\t}\n\n\t\tif ( this.locationUIValidate() ) {\n\t\t\tthis.show_location_ui = true;\n\t\t} else {\n\t\t\tthis.show_location_ui = false;\n\t\t}\n\n\t\tif ( this.stationValidate() ) {\n\t\t\tthis.show_station_ui = true;\n\t\t} else {\n\t\t\tthis.show_station_ui = false;\n\t\t}\n\n\t\tif ( this.jobUIValidate( 'absence' ) ) {\n\t\t\tthis.show_absence_job_ui = true;\n\t\t} else {\n\t\t\tthis.show_absence_job_ui = false;\n\t\t}\n\n\t\tif ( this.jobItemUIValidate( 'absence' ) ) {\n\t\t\tthis.show_absence_job_item_ui = true;\n\t\t} else {\n\t\t\tthis.show_absence_job_item_ui = false;\n\t\t}\n\n\t\tif ( this.punchTagUIValidate( 'absence' ) ) {\n\t\t\tthis.show_absence_punch_tag_ui = true;\n\t\t} else {\n\t\t\tthis.show_absence_punch_tag_ui = false;\n\t\t}\n\n\t\tif ( this.branchUIValidate( 'absence' ) ) {\n\t\t\tthis.show_absence_branch_ui = true;\n\t\t} else {\n\t\t\tthis.show_absence_branch_ui = false;\n\t\t}\n\n\t\tif ( this.departmentUIValidate( 'absence' ) ) {\n\t\t\tthis.show_absence_department_ui = true;\n\t\t} else {\n\t\t\tthis.show_absence_department_ui = false;\n\t\t}\n\t}\n\n\t/* jshint ignore:end */\n\n\townerOrChildPermissionValidate( p_id, permission_name, selected_item ) {\n\t\tvar field;\n\t\tif ( permission_name && permission_name.indexOf( 'child' ) > -1 ) {\n\t\t\tfield = 'is_child';\n\t\t} else {\n\t\t\tfield = 'is_owner';\n\t\t}\n\n\t\tvar user = this.getSelectEmployee( true );\n\n\t\tif ( PermissionManager.validate( p_id, permission_name ) && ( !user || !Global/* Global.isSet */.x.isSet( user[field] ) || ( user && user[field] ) ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tinitOptions() {\n\t\tvar options = [\n\t\t\t{ option_name: 'type', api: this.api },\n\t\t\t{ option_name: 'status', api: this.api },\n\t\t];\n\n\t\tthis.initDropDownOptions( options);\n\t}\n\tgetCustomContextMenuModel() {\n\t\tvar context_menu_model = {\n\t\t\tgroups: {\n\t\t\t\tdrag_and_drop: {\n\t\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Drag & Drop' ),\n\t\t\t\t\tid: this.viewId + 'drag_and_drop'\n\t\t\t\t}\n\t\t\t},\n\t\t\texclude: [\n\t\t\t\t'export_excel',\n\t\t\t\t'add',\n\t\t\t\t'copy',\n\t\t\t\t'copy_as_new'\n\t\t\t],\n\t\t\tinclude: [\n\t\t\t\t{\n\t\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'New Punch' ),\n\t\t\t\t\tid: 'add_punch',\n\t\t\t\t\taction_group: 'new',\n\t\t\t\t\tgroup: 'editor',\n\t\t\t\t\tvue_icon: 'tticon tticon-add_black_24dp',\n\t\t\t\t\tshow_on_right_click: true,\n\t\t\t\t\tsort_order: 910\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'New Absence' ),\n\t\t\t\t\tid: 'add_absence',\n\t\t\t\t\taction_group: 'new',\n\t\t\t\t\tgroup: 'editor',\n\t\t\t\t\tvue_icon: 'tticon tticon-add_black_24dp',\n\t\t\t\t\tshow_on_right_click: true,\n\t\t\t\t\tsort_order: 920\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'In/Out' ),\n\t\t\t\t\tid: 'in_out',\n\t\t\t\t\taction_group: 'in_out',\n\t\t\t\t\tgroup: 'editor',\n\t\t\t\t\tvue_icon: 'tticon tticon-timer_black_24dp',\n\t\t\t\t\tshow_on_right_click: true,\n\t\t\t\t\tsort_order: 1050\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Drag & Drop: Move' ),\n\t\t\t\t\tid: 'move',\n\t\t\t\t\tmenu_align: 'right',\n\t\t\t\t\taction_group: 'move_copy',\n\t\t\t\t\tmulti_select_group: 1\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Drag & Drop: Copy' ),\n\t\t\t\t\tid: 'drag_copy',\n\t\t\t\t\tmenu_align: 'right',\n\t\t\t\t\taction_group: 'move_copy',\n\t\t\t\t\tmulti_select_group: 1\n\t\t\t\t},\n\t\t\t]\n\t\t};\n\n\t\tif ( PermissionManager.validate( 'request', 'add' ) ) {\n\t\t\tcontext_menu_model.include.push( {\n\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Add Request' ),\n\t\t\t\tid: 'AddRequest',\n\t\t\t\tvue_icon: 'tticon tticon-post_add_black_24dp',\n\t\t\t\tmenu_align: 'right',\n\t\t\t\tpermission_result: true,\n\t\t\t\tpermission: true,\n\t\t\t\tshow_on_right_click: true,\n\t\t\t\tsort_order: 1000\n\t\t\t} );\n\t\t}\n\n\t\tif ( ( Global/* Global.getProductEdition */.x.getProductEdition() >= 15 ) ) {\n\t\t\tcontext_menu_model.include.push(\n\t\t\t\t{\n\t\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Map' ),\n\t\t\t\t\tid: 'map',\n\t\t\t\t\tmenu_align: 'right',\n\t\t\t\t\tvue_icon: 'tticon tticon-map_black_24dp',\n\t\t\t\t\tshow_on_right_click: true,\n\t\t\t\t\tsort_order: 2000,\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\n\t\tcontext_menu_model.include.push(\n\t\t\t{\n\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Print' ),\n\t\t\t\tid: 'print',\n\t\t\t\taction_group_header: true,\n\t\t\t\taction_group: 'print_menu',\n\t\t\t\tsort_order: 7000,\n\t\t\t\tmenu_align: 'right',\n\t\t\t\ttype: 2,\n\t\t\t\tpermission_result: true,\n\t\t\t\tpermission: true\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Summary' ),\n\t\t\t\tid: 'print_summary',\n\t\t\t\taction_group: 'print_menu',\n\t\t\t\tsort_order: 7000,\n\t\t\t\tmenu_align: 'right'\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Detailed' ),\n\t\t\t\tid: 'print_detailed',\n\t\t\t\taction_group: 'print_menu',\n\t\t\t\tsort_order: 7000,\n\t\t\t\tmenu_align: 'right'\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Jump To' ),\n\t\t\t\tid: 'jump_to_header',\n\t\t\t\tmenu_align: 'right',\n\t\t\t\taction_group: 'jump_to',\n\t\t\t\tsort_order: 8000,\n\t\t\t\taction_group_header: true,\n\t\t\t\tpermission_result: false // to hide it in legacy context menu and avoid errors in legacy parsers.\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Schedules' ),\n\t\t\t\tid: 'schedule',\n\t\t\t\tmenu_align: 'right',\n\t\t\t\taction_group: 'jump_to',\n\t\t\t\tsort_order: 8000\n\t\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Pay Stubs' ),\n\t\t\t\tid: 'pay_stub',\n\t\t\t\tmenu_align: 'right',\n\t\t\t\taction_group: 'jump_to',\n\t\t\t\tsort_order: 8000\n\t\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Edit Employee' ),\n\t\t\t\tid: 'edit_employee',\n\t\t\t\tmenu_align: 'right',\n\t\t\t\taction_group: 'jump_to',\n\t\t\t\tsort_order: 8000\n\t\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Edit Pay Period' ),\n\t\t\t\tid: 'edit_pay_period',\n\t\t\t\tmenu_align: 'right',\n\t\t\t\taction_group: 'jump_to',\n\t\t\t\tsort_order: 8000\n\t\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Accumulated Time' ),\n\t\t\t\tid: 'accumulated_time',\n\t\t\t\tmenu_align: 'right',\n\t\t\t\taction_group: 'jump_to',\n\t\t\t\tsort_order: 8000\n\t\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: '', //Empty label. vue_icon is displayed instead of text.\n\t\t\t\tid: 'other_header',\n\t\t\t\tmenu_align: 'right',\n\t\t\t\taction_group: 'other',\n\t\t\t\taction_group_header: true,\n\t\t\t\tvue_icon: 'tticon tticon-more_vert_black_24dp',\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'ReCalculate TimeSheet' ),\n\t\t\t\tid: 're_calculate_timesheet',\n\t\t\t\tmenu_align: 'right',\n\t\t\t\taction_group: 'other',\n\t\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Generate Pay Stub' ),\n\t\t\t\tid: 'generate_pay_stub',\n\t\t\t\tmenu_align: 'right',\n\t\t\t\taction_group: 'other',\n\t\t\t\t},\n\t\t);\n\n\t\treturn context_menu_model;\n\t}\n\n\tparseCustomContextModelForEditViews( context_menu_model ) {\n\n\t\tcontext_menu_model = super.parseCustomContextModelForEditViews( context_menu_model );\n\n\t\tif( this.determineContextMenuMountAttributes().menu_type === 'editview_contextmenu' ) {\n\t\t\tcontext_menu_model.exclude.push(\n\t\t\t\t'move',\n\t\t\t\t'drag_copy',\n\t\t\t\t're_calculate_timesheet',\n\t\t\t\t'generate_pay_stub',\n\t\t\t\t'print',\n\t\t\t\t'print_detailed',\n\t\t\t\t'print_summary',\n\t\t\t)\n\t\t}\n\n\t\treturn context_menu_model;\n\t}\n\n\topenEditView() {\n\t\t//#2295 - Re-initialize previous_absence_policy_id to ensure that previously saved values are passed correctly into the estimation of projected available balance.\n\t\tthis.previous_absence_policy_id = false;\n\n\t\tGlobal/* Global.setUINotready */.x.setUINotready();\n\t\tTTPromise.add( 'init', 'init' );\n\t\tTTPromise.wait();\n\t\tif ( !this.edit_view ) {\n\t\t\tthis.is_edit = true;\n\t\t\tthis.initEditViewUI( 'TimeSheet', 'TimeSheetEditView.html' );\n\t\t}\n\t}\n\n\t/* jshint ignore:start */\n\n\t//set widget disablebility if view mode or edit mode\n\tsetEditViewWidgetsMode() {\n\t\tvar did_clean = false;\n\t\tfor ( var key in this.edit_view_ui_dic ) {\n\t\t\tif ( !this.edit_view_ui_dic.hasOwnProperty( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvar widget = this.edit_view_ui_dic[key];\n\t\t\tvar widgetContainer = this.edit_view_form_item_dic[key];\n\t\t\tvar column = widget.parent().parent().parent();\n\t\t\tif ( !column.hasClass( 'v-box' ) ) {\n\t\t\t\tif ( !did_clean ) {\n\t\t\t\t\tdid_clean = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( this.absence_model ) {\n\t\t\t\tswitch ( key ) {\n\t\t\t\t\tcase 'punch_date':\n\t\t\t\t\tcase 'punch_time':\n\t\t\t\t\tcase 'status_id':\n\t\t\t\t\tcase 'type_id':\n\t\t\t\t\tcase 'quantity':\n\t\t\t\t\tcase 'station_id':\n\t\t\t\t\tcase 'has_image':\n\t\t\t\t\tcase 'latitude':\n\t\t\t\t\tcase 'split_punch_control':\n\t\t\t\t\t\tthis.detachElement( key );\n\t\t\t\t\t\twidget.css( 'opacity', 0 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'punch_dates':\n\t\t\t\t\t\tif ( this.is_mass_adding ) {\n\t\t\t\t\t\t\tthis.attachElement( key );\n\t\t\t\t\t\t\twidget.css( 'opacity', 1 );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.detachElement( key );\n\t\t\t\t\t\t\twidget.css( 'opacity', 0 );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'date_stamp':\n\t\t\t\t\t\tif ( this.is_mass_adding ) {\n\t\t\t\t\t\t\tthis.detachElement( key );\n\t\t\t\t\t\t\twidget.css( 'opacity', 0 );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.attachElement( key );\n\t\t\t\t\t\t\twidget.css( 'opacity', 1 );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'total_time':\n\t\t\t\t\tcase 'src_object_id':\n\t\t\t\t\tcase 'override':\n\t\t\t\t\t\tthis.attachElement( key );\n\t\t\t\t\t\twidget.css( 'opacity', 1 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'available_balance':\n\t\t\t\t\t\tthis.detachElement( key );\n\t\t\t\t\t\twidget.css( 'opacity', 1 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\twidget.css( 'opacity', 1 );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tswitch ( key ) {\n\t\t\t\t\tcase 'punch_dates':\n\t\t\t\t\t\tif ( this.is_mass_adding ) {\n\t\t\t\t\t\t\tthis.attachElement( key );\n\t\t\t\t\t\t\twidget.css( 'opacity', 1 );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.detachElement( key );\n\t\t\t\t\t\t\twidget.css( 'opacity', 0 );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'punch_date':\n\t\t\t\t\t\tif ( this.is_mass_adding ) {\n\t\t\t\t\t\t\tthis.detachElement( key );\n\t\t\t\t\t\t\twidget.css( 'opacity', 0 );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.attachElement( key );\n\t\t\t\t\t\t\twidget.css( 'opacity', 1 );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'quantity':\n\t\t\t\t\t\tif ( this.show_good_quantity_ui && this.show_bad_quantity_ui ) {\n\t\t\t\t\t\t\tthis.attachElement( key );\n\t\t\t\t\t\t\twidget.css( 'opacity', 1 );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'station':\n\t\t\t\t\t\tthis.attachElement( key );\n\t\t\t\t\t\twidget.css( 'opacity', 1 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'punch_time':\n\t\t\t\t\tcase 'status_id':\n\t\t\t\t\tcase 'type_id':\n\t\t\t\t\tcase 'has_image':\n\t\t\t\t\tcase 'latitude':\n\t\t\t\t\t\tthis.attachElement( key );\n\t\t\t\t\t\twidget.css( 'opacity', 1 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'date_stamp':\n\t\t\t\t\tcase 'total_time':\n\t\t\t\t\tcase 'src_object_id':\n\t\t\t\t\tcase 'override':\n\t\t\t\t\t\tthis.detachElement( key );\n\t\t\t\t\t\twidget.css( 'opacity', 0 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\twidget.css( 'opacity', 1 );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( this.is_viewing ) {\n\t\t\t\tif ( Global/* Global.isSet */.x.isSet( widget.setEnabled ) ) {\n\t\t\t\t\twidget.setEnabled( false );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ( Global/* Global.isSet */.x.isSet( widget.setEnabled ) ) {\n\t\t\t\t\twidget.setEnabled( true );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tgetCustomFieldReferenceField() {\n\t\treturn 'note';\n\t}\n\n\tsetCustomFields() {\n\t\t//Custom fields are only shown on punch types and not on absence types.\n\t\tif ( this.getPunchPermissionType() === 'punch' ) {\n\t\t\tsuper.setCustomFields();\n\t\t}\n\t}\n\n\tbuildEditViewUI() {\n\t\tsuper.buildEditViewUI();\n\n\t\tvar $this = this;\n\n\t\tvar tab_model = {\n\t\t\t'tab_punch': {\n\t\t\t\t'label': this.absence_model ? TimeSheetViewController_$.i18n._( 'Absence' ) : TimeSheetViewController_$.i18n._( 'Punch' )\n\t\t\t},\n\t\t\t'tab_audit': true,\n\t\t};\n\t\tthis.setTabModel( tab_model );\n\n\t\tvar form_item_input;\n\t\tvar widgetContainer;\n\n\t\t//Tab 0 start\n\n\t\tvar tab_punch = this.edit_view_tab.find( '#tab_punch' );\n\n\t\tvar tab_punch_column1 = tab_punch.find( '.first-column' );\n\n\t\t//Employee\n\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT );\n\t\tform_item_input.TText( { field: 'first_last_name' } );\n\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Employee' ), form_item_input, tab_punch_column1, '' );\n\n\t\t//Time\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TIME_PICKER );\n\t\tform_item_input.TTimePicker( { field: 'punch_time', validation_field: 'time_stamp' } );\n\t\twidgetContainer = TimeSheetViewController_$( '<div class=\\'widget-h-box\\'></div>' );\n\t\tthis.actual_time_label = TimeSheetViewController_$( '<span class=\\'widget-right-label\\'></span>' );\n\t\twidgetContainer.append( form_item_input );\n\t\twidgetContainer.append( this.actual_time_label );\n\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Time' ), form_item_input, tab_punch_column1, '', widgetContainer, true );\n\n\t\t//Absence Model\n\t\t//Absence Policy Type\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.AWESOME_BOX );\n\n\t\tform_item_input.AComboBox( {\n\t\t\tapi_class: TTAPI.APIAbsencePolicy,\n\t\t\tallow_multiple_selection: false,\n\t\t\tlayout_name: 'global_absences',\n\t\t\tshow_search_inputs: true,\n\t\t\tset_empty: true,\n\t\t\tfield: 'src_object_id',\n\t\t\tvalidation_field: 'absence_policy_id'\n\t\t} );\n\n\t\tform_item_input.customSearchFilter = function( filter ) {\n\t\t\treturn $this.setAbsencePolicyFilter( filter );\n\t\t};\n\n\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Absence Policy' ), form_item_input, tab_punch_column1, '', null, true );\n\n\t\t//Available Balance\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT );\n\t\tform_item_input.TText( { field: 'available_balance' } );\n\n\t\twidgetContainer = TimeSheetViewController_$( '<div class=\\'widget-h-box available-balance-h-box\\'></div>' );\n\t\tthis.available_balance_info = TimeSheetViewController_$( '<span class=\"available-balance-info tticon tticon-info_black_24dp\"></span>' );\n\n\t\twidgetContainer.append( form_item_input );\n\t\twidgetContainer.append( this.available_balance_info );\n\n\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Available Balance' ), [form_item_input], tab_punch_column1, '', widgetContainer, true );\n\n\t\t//Date\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.DATE_PICKER );\n\t\tform_item_input.TDatePicker( { field: 'punch_date', validation_field: 'date_stamp' } );\n\n\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Date' ), form_item_input, tab_punch_column1, '', null, true );\n\n\t\t//Mass Add Date\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.DATE_PICKER );\n\n\t\tform_item_input.TRangePicker( { field: 'punch_dates', validation_field: 'date_stamp' } );\n\n\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Date' ), form_item_input, tab_punch_column1, '', null, true );\n\n\t\t//Absence Model\n\t\t//Date\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.DATE_PICKER );\n\t\tform_item_input.TDatePicker( { field: 'date_stamp' } );\n\n\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Date' ), form_item_input, tab_punch_column1, '', null, true );\n\n\t\t//Absence Model\n\t\t//Time\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT_INPUT );\n\t\tform_item_input.TTextInput( { field: 'total_time', mode: 'time_unit' } );\n\n\t\tvar widgetContainer = TimeSheetViewController_$( '<div class=\\'widget-h-box\\'></div>' );\n\t\tvar release_balance_button = TimeSheetViewController_$( '<input id=\\'release-balance-button\\' class=\\'t-button\\' style=\\'margin-left: 5px\\' type=\\'button\\' value=\\'' + TimeSheetViewController_$.i18n._( 'Available Balance' ) + '\\'>' );\n\t\trelease_balance_button.css( 'display', 'none' );\n\n\t\trelease_balance_button.click( function() {\n\t\t\t$this.getAvailableBalance( true );\n\t\t} );\n\n\t\twidgetContainer.append( form_item_input );\n\t\twidgetContainer.append( release_balance_button );\n\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Time' ), form_item_input, tab_punch_column1, '', widgetContainer, true );\n\n\t\t//Punch Type\n\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.COMBO_BOX );\n\t\tform_item_input.TComboBox( { field: 'type_id' } );\n\t\tform_item_input.setSourceData( $this.type_array );\n\n\t\twidgetContainer = TimeSheetViewController_$( '<div class=\\'widget-h-box\\'></div>' );\n\n\t\tvar check_box = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.CHECKBOX );\n\t\tcheck_box.TCheckbox( { field: 'disable_rounding' } );\n\n\t\tvar label = TimeSheetViewController_$( '<span class=\\'widget-right-label\\'>' + TimeSheetViewController_$.i18n._( 'Disable Rounding' ) + '</span>' );\n\n\t\twidgetContainer.append( form_item_input );\n\n\t\t// Check if view only mode. To prevent option appearing but disabled, as disabled checkboxes are not very clear - same in PunchViewController\n\t\tif ( this.is_viewing ) {\n\t\t\t// dev-note: not sure if we need to pass widgetContainer here, or if we can omit if its only one element now (due to the if is_viewing).\n\t\t\t// to be safe, will continue to use widgetContainer for this case. We only want to affect viewing mode (hide rounding checkbox), less risk of regression to keep widget container in.\n\t\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Punch Type' ), form_item_input, tab_punch_column1, '', widgetContainer, true );\n\t\t} else {\n\t\t\twidgetContainer.append( label );\n\t\t\twidgetContainer.append( check_box );\n\t\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Punch Type' ), [form_item_input, check_box], tab_punch_column1, '', widgetContainer, true );\n\t\t}\n\n\t\t//In Out (Status)\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.COMBO_BOX );\n\n\t\tform_item_input.TComboBox( { field: 'status_id' } );\n\t\tform_item_input.setSourceData( $this.status_array );\n\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'In/Out' ), form_item_input, tab_punch_column1, '', null, true );\n\n\t\t//Default Branch\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.AWESOME_BOX );\n\n\t\tform_item_input.AComboBox( {\n\t\t\tapi_class: TTAPI.APIBranch,\n\t\t\tallow_multiple_selection: false,\n\t\t\tlayout_name: 'global_branch',\n\t\t\tshow_search_inputs: true,\n\t\t\tset_empty: true,\n\t\t\tfield: 'branch_id'\n\t\t} );\n\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Branch' ), form_item_input, tab_punch_column1, '', null, true );\n\n\t\tif ( !this.absence_model ) {\n\t\t\tif ( !this.show_branch_ui ) {\n\t\t\t\tthis.detachElement( 'branch_id' );\n\t\t\t}\n\t\t} else {\n\t\t\tif ( !this.show_absence_branch_ui ) {\n\t\t\t\tthis.detachElement( 'branch_id' );\n\t\t\t}\n\t\t}\n\n\t\t//Department\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.AWESOME_BOX );\n\n\t\tform_item_input.AComboBox( {\n\t\t\tapi_class: TTAPI.APIDepartment,\n\t\t\tallow_multiple_selection: false,\n\t\t\tlayout_name: 'global_department',\n\t\t\tshow_search_inputs: true,\n\t\t\tset_empty: true,\n\t\t\tfield: 'department_id'\n\t\t} );\n\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Department' ), form_item_input, tab_punch_column1, '', null, true );\n\n\t\tif ( !this.absence_model ) {\n\t\t\tif ( !this.show_department_ui ) {\n\t\t\t\tthis.detachElement( 'department_id' );\n\t\t\t}\n\t\t} else {\n\t\t\tif ( !this.show_absence_department_ui ) {\n\t\t\t\tthis.detachElement( 'department_id' );\n\t\t\t}\n\t\t}\n\n\t\tif ( ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ) {\n\n\t\t\t//Job\n\t\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.AWESOME_BOX );\n\n\t\t\tform_item_input.AComboBox( {\n\t\t\t\tapi_class: TTAPI.APIJob,\n\t\t\t\tallow_multiple_selection: false,\n\t\t\t\tlayout_name: 'global_job',\n\t\t\t\tshow_search_inputs: true,\n\t\t\t\tset_empty: true,\n\t\t\t\tsetRealValueCallBack: ( function( val ) {\n\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\tjob_coder.setValue( val.manual_id );\n\t\t\t\t\t}\n\t\t\t\t} ),\n\t\t\t\tfield: 'job_id'\n\t\t\t} );\n\n\t\t\twidgetContainer = TimeSheetViewController_$( '<div class=\\'widget-h-box\\'></div>' );\n\n\t\t\tvar job_coder = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT_INPUT );\n\t\t\tjob_coder.TTextInput( { field: 'job_quick_search', disable_keyup_event: true } );\n\t\t\tjob_coder.addClass( 'job-coder' );\n\n\t\t\twidgetContainer.append( job_coder );\n\t\t\twidgetContainer.append( form_item_input );\n\t\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Job' ), [form_item_input, job_coder], tab_punch_column1, '', widgetContainer, true );\n\n\t\t\tif ( !this.absence_model ) {\n\t\t\t\tif ( !this.show_job_ui ) {\n\t\t\t\t\tthis.detachElement( 'job_id' );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ( !this.show_absence_job_ui ) {\n\t\t\t\t\tthis.detachElement( 'job_id' );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//Job Item\n\t\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.AWESOME_BOX );\n\n\t\t\tform_item_input.AComboBox( {\n\t\t\t\tapi_class: TTAPI.APIJobItem,\n\t\t\t\tallow_multiple_selection: false,\n\t\t\t\tlayout_name: 'global_job_item',\n\t\t\t\tshow_search_inputs: true,\n\t\t\t\tset_empty: true,\n\t\t\t\tsetRealValueCallBack: ( function( val ) {\n\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\tjob_item_coder.setValue( val.manual_id );\n\t\t\t\t\t}\n\t\t\t\t} ),\n\t\t\t\tfield: 'job_item_id'\n\t\t\t} );\n\n\t\t\twidgetContainer = TimeSheetViewController_$( '<div class=\\'widget-h-box\\'></div>' );\n\n\t\t\tvar job_item_coder = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT_INPUT );\n\t\t\tjob_item_coder.TTextInput( { field: 'job_item_quick_search', disable_keyup_event: true } );\n\t\t\tjob_item_coder.addClass( 'job-coder' );\n\n\t\t\twidgetContainer.append( job_item_coder );\n\t\t\twidgetContainer.append( form_item_input );\n\t\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Task' ), [form_item_input, job_item_coder], tab_punch_column1, '', widgetContainer, true );\n\n\t\t\tif ( !this.absence_model ) {\n\t\t\t\tif ( !this.show_job_item_ui ) {\n\t\t\t\t\tthis.detachElement( 'job_item_id' );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ( !this.show_absence_job_item_ui ) {\n\t\t\t\t\tthis.detachElement( 'job_item_id' );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//Punch Tag\n\n\t\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.AWESOME_BOX );\n\n\t\t\tform_item_input.AComboBox( {\n\t\t\t\tapi_class: TTAPI.APIPunchTag,\n\t\t\t\tallow_multiple_selection: true,\n\t\t\t\tlayout_name: 'global_punch_tag',\n\t\t\t\tshow_search_inputs: true,\n\t\t\t\tset_empty: true,\n\t\t\t\tget_real_data_on_multi: true,\n\t\t\t\tsetRealValueCallBack: ( ( punch_tags, get_real_data ) => {\n\t\t\t\t\tif ( punch_tags ) {\n\t\t\t\t\t\tthis.setPunchTagQuickSearchManualIds( punch_tags, get_real_data );\n\t\t\t\t\t}\n\t\t\t\t} ),\n\t\t\t\tfield: 'punch_tag_id'\n\t\t\t} );\n\n\t\t\twidgetContainer = TimeSheetViewController_$( '<div class=\\'widget-h-box\\'></div>' );\n\n\t\t\tvar punch_tag_coder = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT_INPUT );\n\t\t\tpunch_tag_coder.TTextInput( { field: 'punch_tag_quick_search', disable_keyup_event: true } );\n\t\t\tpunch_tag_coder.addClass( 'job-coder' );\n\n\t\t\twidgetContainer.append( punch_tag_coder );\n\t\t\twidgetContainer.append( form_item_input );\n\t\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Tags' ), [form_item_input, punch_tag_coder], tab_punch_column1, '', widgetContainer, true );\n\n\t\t\tif ( !this.absence_model ) {\n\t\t\t\tif ( !this.show_punch_tag_ui ) {\n\t\t\t\t\tthis.detachElement( 'punch_tag_id' );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ( !this.show_absence_punch_tag_ui ) {\n\t\t\t\t\tthis.detachElement( 'punch_tag_id' );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ) {\n\n\t\t\t//Quanitity\n\n\t\t\tvar good = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT_INPUT );\n\t\t\tgood.TTextInput( { field: 'quantity' } );\n\t\t\tgood.addClass( 'quantity-input' );\n\n\t\t\tvar good_label = TimeSheetViewController_$( '<span class=\\'widget-right-label\\'>' + TimeSheetViewController_$.i18n._( 'Good' ) + ': </span>' );\n\n\t\t\tvar bad = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT_INPUT );\n\t\t\tbad.TTextInput( { field: 'bad_quantity' } );\n\t\t\tbad.addClass( 'quantity-input' );\n\n\t\t\tvar bad_label = TimeSheetViewController_$( '<span class=\\'widget-right-label\\'>/ ' + TimeSheetViewController_$.i18n._( 'Bad' ) + ': </span>' );\n\n\t\t\twidgetContainer = TimeSheetViewController_$( '<div class=\\'widget-h-box\\'></div>' );\n\n\t\t\twidgetContainer.append( good_label );\n\t\t\twidgetContainer.append( good );\n\t\t\twidgetContainer.append( bad_label );\n\t\t\twidgetContainer.append( bad );\n\n\t\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Quantity' ), [good, bad], tab_punch_column1, '', widgetContainer, true );\n\n\t\t\tif ( !this.show_bad_quantity_ui && !this.show_good_quantity_ui ) {\n\t\t\t\tthis.detachElement( 'quantity' );\n\t\t\t} else {\n\t\t\t\tif ( !this.show_bad_quantity_ui ) {\n\t\t\t\t\tbad_label.hide();\n\t\t\t\t\tbad.hide();\n\t\t\t\t}\n\n\t\t\t\tif ( !this.show_good_quantity_ui ) {\n\t\t\t\t\tgood_label.hide();\n\t\t\t\t\tgood.hide();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//Note\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT_AREA );\n\t\tform_item_input.TTextArea( { field: 'note', width: '100%' } );\n\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Note' ), form_item_input, tab_punch_column1, '', null, true, true );\n\t\tform_item_input.parent().width( '45%' );\n\n\t\tif ( !this.show_note_ui ) {\n\t\t\tthis.detachElement( 'note' );\n\t\t}\n\n\t\t//Absence Mode\n\t\t//Override\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.CHECKBOX );\n\t\tform_item_input.TCheckbox( { field: 'override' } );\n\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Override' ), form_item_input, tab_punch_column1, '', null, true, true );\n\n\t\t//Location\n\t\tif ( Global/* Global.getProductEdition */.x.getProductEdition() >= 15 ) {\n\n\t\t\tvar latitude = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT );\n\t\t\tlatitude.TText( { field: 'latitude' } );\n\t\t\tvar longitude = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT );\n\t\t\tlongitude.TText( { field: 'longitude' } );\n\t\t\twidgetContainer = TimeSheetViewController_$( '<div class=\\'widget-h-box link-widget-box\\'></div>' );\n\t\t\tvar accuracy = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT );\n\t\t\taccuracy.TText( { field: 'position_accuracy' } );\n\t\t\tlabel = TimeSheetViewController_$( '<span class=\\'widget-right-label\\'>' + TimeSheetViewController_$.i18n._( 'Accuracy' ) + ':</span>' );\n\n\t\t\tvar map_icon = TimeSheetViewController_$( '<img class=\"widget-h-box-mapIcon\" src=\"framework/leaflet/images/marker-icon-red.png\" >' );\n\n\t\t\tthis.location_wrapper = TimeSheetViewController_$( '<div class=\"widget-h-box-mapLocationWrapper\"></div>' );\n\t\t\twidgetContainer.append( map_icon );\n\t\t\twidgetContainer.append( this.location_wrapper );\n\t\t\tthis.location_wrapper.append( latitude );\n\t\t\tthis.location_wrapper.append( TimeSheetViewController_$( '<span>, </span>' ) );\n\t\t\tthis.location_wrapper.append( longitude );\n\t\t\tthis.location_wrapper.append( label );\n\t\t\tthis.location_wrapper.append( accuracy );\n\t\t\tthis.location_wrapper.append( TimeSheetViewController_$( '<span>m</span>' ) );\n\t\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Location' ), [latitude, longitude, accuracy], tab_punch_column1, '', widgetContainer, true );\n\t\t\twidgetContainer.click( function() {\n\t\t\t\t$this.onMapClick();\n\t\t\t} );\n\n\t\t\t// #2117 - Manual location only supported in edit because we need a punch record to append the data to.\n\t\t\tif ( ( !this.is_edit && !this.is_viewing ) || !this.show_location_ui ) {\n\t\t\t\twidgetContainer.parents( '.edit-view-form-item-div' ).hide();\n\t\t\t}\n\t\t}\n\n\t\t//Station\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT );\n\t\tform_item_input.TText( { field: 'station_id' } );\n\n\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Station' ), form_item_input, tab_punch_column1, '', null, true, true );\n\n\t\tform_item_input.click( function() {\n\t\t\tif ( $this.current_edit_record.station_id && $this.show_station_ui ) {\n\t\t\t\tIndexViewController.openEditView( $this, 'Station', $this.current_edit_record.station_id );\n\t\t\t}\n\n\t\t} );\n\n\t\t//Split Punch Control\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.CHECKBOX );\n\t\tform_item_input.TCheckbox( { field: 'split_punch_control' } );\n\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Split Existing Punches' ), form_item_input, tab_punch_column1, '', null, true, true );\n\t\tif ( this.is_mass_adding == false ) {\n\t\t\tthis.detachElement( 'split_punch_control' );\n\t\t}\n\n\t\t//Punch Image\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.IMAGE );\n\t\tform_item_input.TImage( { field: 'punch_image' } );\n\t\tthis.addEditFieldToColumn( TimeSheetViewController_$.i18n._( 'Image' ), form_item_input, tab_punch_column1, '', null, true, true );\n\t}\n\n\t/* jshint ignore:end */\n\n\tonEditStationDone() {\n\t\tthis.setStation();\n\t}\n\n\tsetAbsencePolicyFilter( filter ) {\n\t\tif ( !filter.filter_data ) {\n\t\t\tfilter.filter_data = {};\n\t\t}\n\n\t\tfilter.filter_data.user_id = this.current_edit_record.user_id;\n\n\t\tif ( filter.filter_columns ) {\n\t\t\tfilter.filter_columns.absence_policy = true;\n\t\t}\n\n\t\treturn filter;\n\t}\n\n\tonSetSearchFilterFinished() {\n\t}\n\n\tonBuildBasicUIFinished() {\n\t}\n\n\tonBuildAdvUIFinished() {\n\t}\n\n\tparserDatesRange( date ) {\n\t\tvar dates = date.split( ' - ' );\n\t\tvar resultArray = [];\n\t\tvar beginDate = Global/* Global.strToDate */.x.strToDate( dates[0] );\n\t\tvar endDate = Global/* Global.strToDate */.x.strToDate( dates[1] );\n\n\t\tvar nextDate = beginDate;\n\n\t\twhile ( nextDate.getTime() < endDate.getTime() ) {\n\t\t\tresultArray.push( nextDate.format() );\n\t\t\tnextDate = new Date( new Date( nextDate.getTime() ).setDate( nextDate.getDate() + 1 ) );\n\t\t}\n\n\t\tresultArray.push( dates[1] );\n\n\t\treturn resultArray;\n\t}\n\n\tvalidate() {\n\t\tvar $this = this;\n\t\tvar record = this.current_edit_record;\n\t\tvar i;\n\t\tif ( this.is_mass_editing ) {\n\t\t\trecord = [];\n\t\t\tvar len = this.mass_edit_record_ids.length;\n\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\tvar temp_item = Global/* Global.clone */.x.clone( this.current_edit_record );\n\t\t\t\ttemp_item.id = this.mass_edit_record_ids[i];\n\t\t\t\trecord.push( temp_item );\n\t\t\t}\n\t\t}\n\n\t\tif ( this.is_mass_adding ) {\n\n\t\t\trecord = [];\n\t\t\tvar dates_array = this.current_edit_record.punch_dates;\n\n\t\t\tif ( dates_array && dates_array.indexOf( ' - ' ) > 0 ) {\n\t\t\t\tdates_array = this.parserDatesRange( dates_array );\n\t\t\t}\n\n\t\t\tfor ( var i = 0; i < dates_array.length; i++ ) {\n\t\t\t\tvar common_record = Global/* Global.clone */.x.clone( this.current_edit_record );\n\t\t\t\tdelete common_record.punch_dates;\n\t\t\t\tif ( this.absence_model ) {\n\t\t\t\t\tcommon_record.date_stamp = dates_array[i];\n\t\t\t\t} else {\n\t\t\t\t\tcommon_record.punch_date = dates_array[i];\n\t\t\t\t}\n\n\t\t\t\trecord.push( common_record );\n\t\t\t}\n\t\t}\n\n\t\tif ( !this.absence_model ) {\n\n\t\t\tthis.api['validate' + this.api.key_name]( record, {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t$this.validateResult( result );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t} else {\n\n\t\t\tthis.api_user_date_total['validate' + this.api_user_date_total.key_name]( record, {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t$this.clearErrorTips(); //Always clear error\n\n\t\t\t\t\tif ( result.isValid() ) {\n\t\t\t\t\t\t$this.setEditMenu();\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$this.setErrorMenu();\n\t\t\t\t\t\t$this.setErrorTips( result );\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t} );\n\n\t\t}\n\t}\n\n\t/* jshint ignore:start */\n\tonFormItemChange( target, doNotValidate ) {\n\t\tvar $this = this;\n\t\tthis.setIsChanged( target );\n\t\tthis.setMassEditingFieldsWhenFormChange( target );\n\t\tvar key = target.getField();\n\t\tvar c_value = target.getValue();\n\t\t// Error: TypeError: this.current_edit_record is null in interface/html5/framework/jquery.min.js?v=9.0.5-20151222-094938 line 2 > eval line 1409\n\t\tif ( !this.current_edit_record ) {\n\t\t\treturn;\n\t\t}\n\t\tthis.current_edit_record[key] = c_value;\n\t\tswitch ( key ) {\n\t\t\tcase 'job_id':\n\t\t\t\tif ( ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ) {\n\t\t\t\t\tthis.edit_view_ui_dic['job_quick_search'].setValue( target.getValue( true ) ? ( target.getValue( true ).manual_id ? target.getValue( true ).manual_id : '' ) : '' );\n\t\t\t\t\tthis.setJobItemValueWhenJobChanged( target.getValue( true ), 'job_item_id', {\n\t\t\t\t\t\tstatus_id: 10,\n\t\t\t\t\t\tjob_id: this.current_edit_record.job_id\n\t\t\t\t\t} );\n\t\t\t\t\tthis.edit_view_ui_dic['job_quick_search'].setCheckBox( true );\n\t\t\t\t\tthis.setPunchTagValuesWhenCriteriaChanged( this.getPunchTagFilterData(), 'punch_tag_id' );\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\tcase 'job_item_id':\n\t\t\t\tif ( ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ) {\n\t\t\t\t\tthis.edit_view_ui_dic['job_item_quick_search'].setValue( target.getValue( true ) ? ( target.getValue( true ).manual_id ? target.getValue( true ).manual_id : '' ) : '' );\n\t\t\t\t\tthis.edit_view_ui_dic['job_item_quick_search'].setCheckBox( true );\n\t\t\t\t\tthis.setPunchTagValuesWhenCriteriaChanged( this.getPunchTagFilterData(), 'punch_tag_id' );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'punch_tag_id':\n\t\t\t\tif ( ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ) {\n\t\t\t\t\tif ( c_value !== TTUUID/* TTUUID.zero_id */.d.zero_id && c_value !== false && c_value.length > 0 ) {\n\t\t\t\t\t\tthis.setPunchTagQuickSearchManualIds( target.getSelectItems() );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.edit_view_ui_dic['punch_tag_quick_search'].setValue( '' );\n\t\t\t\t\t}\n\t\t\t\t\t$this.previous_punch_tag_selection = c_value;\n\t\t\t\t\t//Reset source data to make sure correct punch tags are always shown.\n\t\t\t\t\tthis.edit_view_ui_dic['punch_tag_id'].setSourceData( null );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'branch_id':\n\t\t\t\tif ( ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ) {\n\t\t\t\t\tthis.setPunchTagValuesWhenCriteriaChanged( this.getPunchTagFilterData(), 'punch_tag_id' );\n\t\t\t\t\tthis.setJobValueWhenCriteriaChanged( 'job_id', {\n\t\t\t\t\t\tstatus_id: 10,\n\t\t\t\t\t\tuser_id: this.current_edit_record.user_id,\n\t\t\t\t\t\tpunch_branch_id: this.current_edit_record.branch_id,\n\t\t\t\t\t\tpunch_department_id: this.current_edit_record.department_id\n\t\t\t\t\t} );\n\t\t\t\t\tthis.setDepartmentValueWhenBranchChanged( target.getValue( true ), 'department_id', {\n\t\t\t\t\t\tbranch_id: this.current_edit_record.branch_id,\n\t\t\t\t\t\tuser_id: this.current_edit_record.user_id\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'user_id':\n\t\t\tcase 'department_id':\n\t\t\t\tif ( ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ) {\n\t\t\t\t\tthis.setPunchTagValuesWhenCriteriaChanged( this.getPunchTagFilterData(), 'punch_tag_id' );\n\t\t\t\t\tthis.setJobValueWhenCriteriaChanged( 'job_id', {\n\t\t\t\t\t\tstatus_id: 10,\n\t\t\t\t\t\tuser_id: this.current_edit_record.user_id,\n\t\t\t\t\t\tpunch_branch_id: this.current_edit_record.branch_id,\n\t\t\t\t\t\tpunch_department_id: this.current_edit_record.department_id\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'job_quick_search':\n\t\t\tcase 'job_item_quick_search':\n\t\t\t\tif ( ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ) {\n\t\t\t\t\tthis.onJobQuickSearch( key, c_value );\n\t\t\t\t\tTTPromise.wait( 'BaseViewController', 'onJobQuickSearch', function() {\n\t\t\t\t\t\t$this.setPunchTagValuesWhenCriteriaChanged( $this.getPunchTagFilterData(), 'punch_tag_id' );\n\t\t\t\t\t} );\n\t\t\t\t\t//Don't validate immediately as onJobQuickSearch is doing async API calls, and it would cause a guaranteed validation failure.\n\t\t\t\t\tdoNotValidate = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'punch_tag_quick_search':\n\t\t\t\tif ( ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ) {\n\t\t\t\t\tthis.onPunchTagQuickSearch( c_value, this.getPunchTagFilterData(), 'punch_tag_id' );\n\n\t\t\t\t\t//Don't validate immediately as onJobQuickSearch is doing async API calls, and it would cause a guaranteed validation failure.\n\t\t\t\t\tdoNotValidate = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'punch_dates':\n\t\t\t\tthis.setEditMenu();\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\tif ( this.absence_model ) {\n\t\t\tif ( key === 'total_time' ) {\n\n\t\t\t\tif ( this.current_edit_record ) {\n\t\t\t\t\tthis.current_edit_record[key] = Global/* Global.parseTimeUnit */.x.parseTimeUnit( c_value );\n\t\t\t\t\t// parsed_total_time_obj = this.api_date.parseTimeUnit( c_value, { async: false } );\n\t\t\t\t\t// if ( parsed_total_time_obj ) {\n\t\t\t\t\t// \tthis.current_edit_record[key] = parsed_total_time_obj.getResult();\n\t\t\t\t\t// }\n\n\t\t\t\t\t//When handling absences, always remove the start/end time stamps otherwise they may be incorrect and trigger a validation error, as the user doesn't see them anyways.\n\t\t\t\t\t// The API will automatically calculated these on save anyways.\n\t\t\t\t\tthis.current_edit_record['start_time_stamp'] = false;\n\t\t\t\t\tthis.current_edit_record['end_time_stamp'] = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( key !== 'override' && this.edit_view_ui_dic['override'] ) {\n\t\t\t\tthis.edit_view_ui_dic['override'].setValue( true );\n\t\t\t\tthis.current_edit_record['override'] = true;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.current_edit_record[key] = c_value;\n\t\t}\n\n\t\tif ( !doNotValidate ) {\n\t\t\tif ( this.absence_model ) {\n\t\t\t\tif ( key === 'total_time' ||\n\t\t\t\t\tkey === 'date_stamp' ||\n\t\t\t\t\tkey === 'punch_dates' ||\n\t\t\t\t\tkey === 'src_object_id' ) {\n\t\t\t\t\tthis.onAvailableBalanceChange();\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.validate();\n\t\t}\n\t}\n\n\t/* jshint ignore:end */\n\n\tbuildSearchAndLayoutUI() {\n\t\tvar layout_div = this.search_panel.find( 'div #saved_layout_content_div' );\n\n\t\tvar form_item = TimeSheetViewController_$( TimeSheetViewController_$.fn.SearchPanel.html.form_item );\n\t\tvar form_item_label = form_item.find( '.form-item-label' );\n\t\tvar form_item_input_div = form_item.find( '.form-item-input-div' );\n\n\t\tform_item_label.text( TimeSheetViewController_$.i18n._( 'Save Search As' ) );\n\n\t\tthis.save_search_as_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT_INPUT );\n\t\tthis.save_search_as_input.TTextInput();\n\n\t\tvar save_btn = TimeSheetViewController_$( '<button class=\"tt-button p-button p-component small-search-panel-button\" type=\"button\">\\n' +\n\t\t\t'<span class=\"tticon tticon-save_black_24dp\"></span>\\n' +\n\t\t\t'<span class=\"p-button-label\">' + TimeSheetViewController_$.i18n._( 'Save' ) + '</span>\\n' +\n\t\t\t'</button>' );\n\n\t\tform_item_input_div.append( this.save_search_as_input );\n\t\tform_item_input_div.append( save_btn );\n\n\t\tvar $this = this;\n\t\tsave_btn.click( function() {\n\t\t\t$this.onSaveNewLayout();\n\t\t} );\n\n\t\t//Previous Saved Layout\n\n\t\tthis.previous_saved_layout_div = TimeSheetViewController_$( '<div class=\\'previous-saved-layout-div\\'></div>' );\n\n\t\tform_item_input_div.append( this.previous_saved_layout_div );\n\n\t\tform_item_label = TimeSheetViewController_$( '<span style=\\'margin-left: 5px\\' >' + TimeSheetViewController_$.i18n._( 'Previous Saved Searches' ) + ':</span>' );\n\t\tthis.previous_saved_layout_div.append( form_item_label );\n\n\t\tthis.previous_saved_layout_selector = TimeSheetViewController_$( '<select style=\\'margin-left: 5px\\' class=\\'t-select\\'>' );\n\t\tvar update_btn = TimeSheetViewController_$( '<button class=\"tt-button p-button p-component small-search-panel-button\" type=\"button\">\\n' +\n\t\t\t'<span class=\"tticon tticon-save_black_24dp\"></span>\\n' +\n\t\t\t'<span class=\"p-button-label\">' + TimeSheetViewController_$.i18n._( 'Update' ) + '</span>\\n' +\n\t\t\t'</button>' );\n\n\t\tvar del_btn = TimeSheetViewController_$( '<button class=\"tt-button p-button p-component small-search-panel-button\" type=\"button\">\\n' +\n\t\t\t'<span class=\"tticon tticon-delete_black_24dp\"></span>\\n' +\n\t\t\t'<span class=\"p-button-label\">' + TimeSheetViewController_$.i18n._( 'Delete' ) + '</span>\\n' +\n\t\t\t'</button>' );\n\n\t\tupdate_btn.click( function() {\n\t\t\t$this.onUpdateLayout();\n\t\t} );\n\n\t\tdel_btn.click( function() {\n\t\t\t$this.onDeleteLayout();\n\t\t} );\n\n\t\tthis.previous_saved_layout_div.append( this.previous_saved_layout_selector );\n\t\tthis.previous_saved_layout_div.append( update_btn );\n\t\tthis.previous_saved_layout_div.append( del_btn );\n\n\t\tlayout_div.append( form_item );\n\n\t\tthis.previous_saved_layout_div.css( 'display', 'none' );\n\t}\n\n\tcheckTimesheetData() {\n\t\tif ( this.full_timesheet_data === true ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\trender() {\n\n\t\tvar $this = this;\n\t\tsuper.render();\n\n\t\t// Init Vue control bar\n\t\tthis.vue_control_bar_id = 'vue-timesheet-control-bar';\n\n\t\t// Add callbacks here to inject into Vue, for button/menu interactions from Vue back to TT.\n\t\tvar root_props = {\n\t\t\tonPunchModeChange: function() {\n\t\t\t\t$this.onWageOrModeChange( 'manual' );\n\t\t\t\t$this.onSearch( true );\n\t\t\t},\n\t\t\tonShowWageClick: function() {\n\t\t\t\t$this.onWageOrModeChange( 'wage' );\n\t\t\t\t$this.onSearch( true );\n\t\t\t},\n\t\t\tonTimezoneClick: function() {\n\t\t\t\t$this.onWageOrModeChange( 'timezone' );\n\t\t\t\t$this.onSearch( true );\n\t\t\t}\n\t\t};\n\n\t\t// Proof of concept. Future work should use TTEventBus instead of vue_return, as passing by reference and direct access like this is a Vue anti-pattern.\n\t\t// Carefully use the return objects in vue_return, as interactions between Vue and legacy should be carefully controlled to avoid spagetti code / vue anti patterns.\n\t\tvar vue_return = TTVueUtils/* default.mountComponent */.Z.mountComponent( this.vue_control_bar_id, TimeSheetControlBar, root_props );\n\n\t\tvar date_chooser_div = TimeSheetViewController_$( '.time-sheet-view .date-chooser-div' );\n\t\tvar employee_nav_div = TimeSheetViewController_$( '.time-sheet-view .employee-nav-div' );\n\n\t\t//Issue #3097 - TypeError: Cannot read properties of undefined (reading 'getPunchMode')\n\t\t//The Vue TimeSheetControlBar may already contain dom elements from previous renders (cached?) and needs to be removed.\n\t\t//The parent div needs all children removed to prevent multiple date pickers from being added.\n\t\tdate_chooser_div.empty();\n\n\t\tif ( !this.show_navigation_box ) {\n\t\t\temployee_nav_div.css( 'display', 'none' );\n\t\t} else {\n\t\t\temployee_nav_div.css( 'display', '' );\n\t\t}\n\n\t\tthis.wage_btn = {\n\t\t\tid: this.vue_control_bar_id, // TODO: Do we need this still?\n\t\t\tshow: function() {},\n\t\t\thide: function() {},\n\t\t\tgetValue: function() {\n\t\t\t\tif ( vue_return && vue_return._vue_component_instance ) {\n\t\t\t\t\treturn vue_return._vue_component_instance.getTimesheetSettingsState( 'show_wages' );\n\t\t\t\t}\n\t\t\t},\n\t\t\tsetValue: function( new_value ) {\n\t\t\t\tif ( vue_return && vue_return._vue_component_instance ) {\n\t\t\t\t\tvue_return._vue_component_instance.setTimesheetSettingsState( 'show_wages', new_value );\n\t\t\t\t}\n\t\t\t},\n\t\t\t// TODO Cant use this as a remove, as it would remove the whole control bar. We only want to hide/remove the toggle buttons for mode.\n\t\t\tremove: function() {\n\t\t\t\t// return TTVueUtils.unmountComponent( this.vue_control_bar_id )\n\t\t\t}\n\t\t};\n\n\t\tthis.timezone_btn = {\n\t\t\tid: this.vue_control_bar_id,\n\t\t\tshow: function() {},\n\t\t\thide: function() {},\n\t\t\tgetValue: function() {\n\t\t\t\tif ( vue_return && vue_return._vue_component_instance ) {\n\t\t\t\t\treturn vue_return._vue_component_instance.getTimesheetSettingsState( 'use_employee_timezone' );\n\t\t\t\t}\n\t\t\t},\n\t\t\tsetValue: function( new_value ) {\n\t\t\t\tif ( vue_return && vue_return._vue_component_instance ) {\n\t\t\t\t\tvue_return._vue_component_instance.setTimesheetSettingsState( 'use_employee_timezone', new_value );\n\t\t\t\t}\n\t\t\t},\n\t\t\t// TODO Cant use this as a remove, as it would remove the whole control bar. We only want to hide/remove the toggle buttons for mode.\n\t\t\tremove: function() {\n\t\t\t\t// return TTVueUtils.unmountComponent( this.vue_control_bar_id )\n\t\t\t}\n\t\t};\n\n\t\t//Create Start Date Picker\n\t\tthis.start_date_picker = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.DATE_PICKER );\n\t\tthis.start_date_picker.TDatePicker( { field: 'start_date' } );\n\t\tvar date_chooser = TimeSheetViewController_$( '<span class=\\'label\\'>' + TimeSheetViewController_$.i18n._( 'Date' ) + ':</span>' +\n\t\t\t'<img class=\\'left-arrow arrow\\' src=' + Global/* Global.getRealImagePath */.x.getRealImagePath( 'images/left_arrow.svg' ) + '>' +\n\t\t\t'<div class=\\'date-picker-div\\'></div>' +\n\t\t\t'<img class=\\'right-arrow arrow\\' src=' + Global/* Global.getRealImagePath */.x.getRealImagePath( 'images/right_arrow.svg' ) + '>' );\n\n\t\tdate_chooser_div.append( date_chooser );\n\t\tdate_chooser_div.find( '.date-picker-div' ).append( this.start_date_picker );\n\n\t\tvar date_left_arrow = date_chooser_div.find( '.left-arrow' );\n\t\tvar date_right_arrow = date_chooser_div.find( '.right-arrow' );\n\n\t\tdate_left_arrow.bind( 'click', function() {\n\t\t\t//Error: TypeError: $this.timesheet_columns is undefined in /interface/html5/framework/jquery.min.js?v=8.0.0-20141230-125919 line 2 > eval line 1569\n\t\t\tif ( !$this.checkTimesheetData() || !$this.timesheet_columns ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar select_date = Global/* Global.strToDate */.x.strToDate( ( ( $this.getSelectDate() ) ? $this.getSelectDate() : new Date().format() ) );\n\t\t\tvar new_date = new Date( new Date( select_date.getTime() ).setDate( select_date.getDate() - 7 ) ).format();\n\t\t\t$this.first_build = true;\n\t\t\tcontinueChangeDate( new_date );\n\n\t\t\t//see #2224 Cannot read property 'date' of undefined\n\t\t\t$this.setDefaultMenu();\n\t\t} );\n\n\t\tdate_right_arrow.bind( 'click', function() {\n\t\t\t//Error: TypeError: $this.timesheet_columns is undefined in /interface/html5/framework/jquery.min.js?v=8.0.0-20141230-125919 line 2 > eval line 1569\n\t\t\tif ( !$this.checkTimesheetData() || !$this.timesheet_columns ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar select_date = Global/* Global.strToDate */.x.strToDate( ( ( $this.getSelectDate() ) ? $this.getSelectDate() : new Date().format() ) );\n\t\t\tvar new_date = new Date( new Date( select_date.getTime() ).setDate( select_date.getDate() + 7 ) ).format();\n\t\t\t$this.first_build = true;\n\t\t\tcontinueChangeDate( new_date );\n\n\t\t\t//see #2224 Cannot read property 'date' of undefined\n\t\t\t$this.setDefaultMenu();\n\t\t} );\n\n\t\tthis.start_date_picker.bind( 'formItemChange', function() {\n\t\t\tvar select_date = $this.getSelectDate() ? $this.getSelectDate() : new Date().format();\n\t\t\t$this.first_build = true;\n\t\t\tcontinueChangeDate( select_date );\n\t\t} );\n\n\t\tfunction continueChangeDate( new_date ) {\n\t\t\t$this.doNextIfNoValueChangeInManualGrid( doNext, reset );\n\n\t\t\tfunction reset() {\n\t\t\t\t$this.setDatePickerValue( LocalCacheData.last_timesheet_selected_date );\n\t\t\t}\n\n\t\t\tfunction doNext() {\n\t\t\t\t$this.setDatePickerValue( new_date );\n\t\t\t\t$this.search();\n\t\t\t}\n\t\t}\n\n\t\t//Create Employee Navigation\n\n\t\tvar label = employee_nav_div.find( '.navigation-label' );\n\t\tvar left_click = employee_nav_div.find( '.left-click' );\n\t\tvar right_click = employee_nav_div.find( '.right-click' );\n\t\tvar navigation_widget_div = employee_nav_div.find( '.navigation-widget-div' );\n\n\t\t//Issue #3097 - TypeError: Cannot read properties of undefined (reading 'getPunchMode')\n\t\t//The Vue TimeSheetControlBar may already contain dom elements from previous renders (cached?) and needs to be removed.\n\t\t//The parent div needs all children removed to prevent multiple employee selectors from being added to the dom.\n\t\tnavigation_widget_div.empty();\n\n\t\tthis.employee_nav = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.AWESOME_BOX );\n\t\tvar default_args = { permission_section: 'punch' };\n\t\tthis.employee_nav = this.employee_nav.AComboBox( {\n\t\t\tid: 'employee_navigation',\n\t\t\tapi_class: TTAPI.APIUser,\n\t\t\tallow_multiple_selection: false,\n\t\t\tlayout_name: 'global_user',\n\t\t\tinit_data_immediately: true,\n\t\t\tdefault_args: default_args,\n\t\t\tshow_search_inputs: true,\n\t\t\talways_include_columns: ['default_branch_id', 'default_department_id', 'default_job_id', 'default_job_item_id', 'default_punch_tag_id'],\n\t\t\twidth: 200,\n\t\t\tis_static_width: true, //Use static width so the left/right navigation arrows don't move around based on the length of the employees name.\n\t\t\tsetRealValueCallBack: ( function( val ) {\n\t\t\t\t$this.userValueSet( val );\n\t\t\t} )\n\t\t} );\n\n\t\tnavigation_widget_div.append( this.employee_nav );\n\t\tnavigation_widget_div.bind( 'onClose', () => {\n\t\t\tthis.setEmployeeNavArrowsStatus();\n\t\t} );\n\t\tthis.employee_nav.bind( 'formItemChange', function() {\n\t\t\t$this.doNextIfNoValueChangeInManualGrid( doNext, reset );\n\t\t\tGlobal/* Global.triggerAnalyticsEditViewNavigation */.x.triggerAnalyticsEditViewNavigation( 'navigation', $this.viewId );\n\n\t\t\tfunction doNext() {\n\t\t\t\tvar selected_user_id = $this.getSelectEmployee();\n\t\t\t\tif ( !$this.edit_view ) {\n\t\t\t\t\t$this.reSetURL();\n\t\t\t\t}\n\t\t\t\t$this.allow_auto_switch && ( $this.is_auto_switch = true );\n\t\t\t\t$this.first_build = true;\n\t\t\t\t/* jshint ignore:start */\n\t\t\t\tif ( LocalCacheData.last_timesheet_selected_user != selected_user_id ) {\n\t\t\t\t\t$this.search();\n\t\t\t\t}\n\t\t\t\t/* jshint ignore:end */\n\t\t\t\t$this.absence_model = false;\n\t\t\t\t$this.setDefaultMenu();\n\t\t\t}\n\n\t\t\tfunction reset() {\n\t\t\t\t$this.employee_nav.setValue( LocalCacheData.last_timesheet_selected_user );\n\t\t\t}\n\t\t} );\n\n\t\tthis.employee_nav.bind( 'initSourceComplete', function() {\n\t\t\t$this.setEmployeeNavArrowsStatus();\n\t\t} );\n\n\t\tleft_click.attr( 'src', Global/* Global.getRealImagePath */.x.getRealImagePath( 'images/left_arrow.svg' ) );\n\t\tright_click.attr( 'src', Global/* Global.getRealImagePath */.x.getRealImagePath( 'images/right_arrow.svg' ) );\n\t\tright_click.click( function() {\n\t\t\tif ( right_click.hasClass( 'disabled' ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t$this.doNextIfNoValueChangeInManualGrid( doNext );\n\t\t\tGlobal/* Global.triggerAnalyticsEditViewNavigation */.x.triggerAnalyticsEditViewNavigation( 'right-arrow', $this.viewId );\n\n\t\t\tfunction doNext() {\n\t\t\t\tvar selected_index = $this.employee_nav.getSelectIndex();\n\t\t\t\tvar source_data = $this.employee_nav.getSourceData();\n\t\t\t\tvar current_open_page = $this.employee_nav.getCurrentOpenPage();\n\t\t\t\tvar next_select_item;\n\t\t\t\tif ( source_data && selected_index < ( source_data.length - 1 ) ) {\n\t\t\t\t\tnext_select_item = $this.employee_nav.getItemByIndex( ( selected_index + 1 ) );\n\t\t\t\t\t$this.employee_nav.setValue( next_select_item );\n\t\t\t\t\tdoNextDone();\n\t\t\t\t} else if ( source_data && selected_index === source_data.length - 1 ) {\n\t\t\t\t\t//onADropDownSearch() makes async calls, so we need to have a doNextDone() callback to trigger to avoid race conditions.\n\t\t\t\t\t$this.employee_nav.onADropDownSearch( 'unselect_grid', ( current_open_page + 1 ), 'first', doNextDone, false ); //Skip triggering FormItemChange as we call search() ourself below anyways, and doing both can cause race conditions and incorrect data to be displayed.\n\t\t\t\t} else {\n\t\t\t\t\tnext_select_item = $this.employee_nav.getItemByIndex( 0 );\n\t\t\t\t\t$this.employee_nav.setValue( next_select_item );\n\t\t\t\t\tdoNextDone();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction doNextDone() {\n\t\t\t\tif ( !$this.edit_view ) {\n\t\t\t\t\t$this.reSetURL();\n\t\t\t\t}\n\t\t\t\t$this.allow_auto_switch && ( $this.is_auto_switch = true );\n\t\t\t\t$this.first_build = true;\n\t\t\t\t$this.search();\n\t\t\t\t$this.setEmployeeNavArrowsStatus();\n\t\t\t}\n\n\t\t} );\n\n\t\tleft_click.click( function() {\n\t\t\tif ( left_click.hasClass( 'disabled' ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t$this.doNextIfNoValueChangeInManualGrid( doNext );\n\t\t\tGlobal/* Global.triggerAnalyticsEditViewNavigation */.x.triggerAnalyticsEditViewNavigation( 'left-arrow', $this.viewId );\n\n\t\t\tfunction doNext() {\n\t\t\t\tvar selected_index = $this.employee_nav.getSelectIndex();\n\t\t\t\t//var source_data = $this.employee_nav.getSourceData();\n\t\t\t\tvar current_open_page = $this.employee_nav.getCurrentOpenPage();\n\t\t\t\tvar next_select_item;\n\t\t\t\tif ( selected_index > 0 ) {\n\t\t\t\t\tnext_select_item = $this.employee_nav.getItemByIndex( ( selected_index - 1 ) );\n\t\t\t\t\t$this.employee_nav.setValue( next_select_item );\n\t\t\t\t\tdoNextDone();\n\t\t\t\t} else if ( current_open_page > 1 ) {\n\t\t\t\t\t//onADropDownSearch() makes async calls, so we need to have a doNextDone() callback to trigger to avoid race conditions.\n\t\t\t\t\t$this.employee_nav.onADropDownSearch( 'unselect_grid', ( current_open_page - 1 ), 'last', doNextDone, false ); //Skip triggering FormItemChange as we call search() ourself below anyways, and doing both can cause race conditions and incorrect data to be displayed.\n\t\t\t\t} else {\n\t\t\t\t\t// Error: TypeError: source_data is null in /interface/html5/framework/jquery.min.js?v=8.0.6-20150417-084000 line 2 > eval line 1691\n\t\t\t\t\tnext_select_item = $this.employee_nav.getItemByIndex( 0 );\n\t\t\t\t\t$this.employee_nav.setValue( next_select_item );\n\t\t\t\t\tdoNextDone();\n\t\t\t\t}\n\n\t\t\t\tfunction doNextDone() {\n\t\t\t\t\tif ( !$this.edit_view ) {\n\t\t\t\t\t\t$this.reSetURL();\n\t\t\t\t\t}\n\t\t\t\t\t$this.allow_auto_switch && ( $this.is_auto_switch = true );\n\t\t\t\t\t$this.first_build = true;\n\t\t\t\t\t$this.search();\n\t\t\t\t\t$this.setEmployeeNavArrowsStatus();\n\t\t\t\t}\n\t\t\t}\n\n\t\t} );\n\n\t\tlabel.text( TimeSheetViewController_$.i18n._( 'Employee' ) );\n\n\t\t// Create Vue timesheet mode toggle buttons\n\n\t\tif( this.show_punch_mode_ui ) {\n\t\t\t// Create pseudo element to pose as jQuery object but is actually just an interface for the Vue component.\n\t\t\t// TODO: Once more/view component has been converted to Vue, we want to refactor this toggle button logic to make use of more streamlined Vue data features like two way binding.\n\n\t\t\tthis.toggle_button = {\n\t\t\t\tid: this.vue_control_bar_id,\n\t\t\t\tgetValue: function() {\n\t\t\t\t\tif ( vue_return && vue_return._vue_component_instance ) {\n\t\t\t\t\t\treturn vue_return._vue_component_instance.getPunchMode; // its done as a getter function on the Vue side, so no need for brackets.\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tsetValue: function( new_value ) {\n\t\t\t\t\tif ( vue_return && vue_return._vue_component_instance ) {\n\t\t\t\t\t\tvue_return._vue_component_instance.setPunchMode( new_value );\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t// TODO Cant use this as a remove, as it would remove the whole control bar. We only want to hide/remove the toggle buttons for mode.\n\t\t\t\tremove: function() {\n\t\t\t\t\treturn TTVueUtils/* default.unmountComponent */.Z.unmountComponent( this.vue_control_bar_id )\n\t\t\t\t}\n\t\t\t};\n\t\t} else {\n\n\t\t\tlet mode = 'punch';\n\n\t\t\tconst toggle_div = document.querySelector( '.punch-manual' );\n\n\t\t\tif ( toggle_div ) {\n\t\t\t\ttoggle_div.style.display = 'none'; //Hide toggle mode button\n\t\t\t}\n\n\t\t\t//If they have manual permission, show manual mode otherwise punch\n\t\t\tif ( Global/* Global.getProductEdition */.x.getProductEdition() >= 15 && PermissionManager.validate( this.permission_id, 'manual_timesheet' ) ) {\n\t\t\t\tmode = 'manual';\n\t\t\t}\n\n\t\t\tthis.toggle_button = {\n\t\t\t\tgetValue: () => mode, //Always return the mode the user has permission to view.\n\t\t\t\tsetValue: function( new_value ) {\n\t\t\t\t\t//User without permissions cannot change punch mode.\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\n\tdoNextIfNoValueChangeInManualGrid( doNext, reset, mode ) {\n\t\t!mode && ( mode = 'manual' );\n\t\tvar $this = this;\n\t\tif ( this.getPunchMode() === mode && this.editor ) {\n\t\t\tvar records = this.editor.getValue();\n\t\t\tif ( records.length > 0 ) {\n\t\t\t\tTAlertManager.showConfirmAlert( Global/* Global.modify_alert_message */.x.modify_alert_message, '', function( flag ) {\n\t\t\t\t\tif ( flag ) {\n\t\t\t\t\t\t$this.wait_auto_save && clearTimeout( $this.wait_auto_save );\n\t\t\t\t\t\tdoNext();\n\t\t\t\t\t} else {\n\t\t\t\t\t\treset && reset();\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\tdoNext();\n\t\t\t}\n\t\t} else {\n\t\t\tdoNext();\n\t\t}\n\t}\n\n\tgetPunchMode() {\n\t\t//Mode toggle does not exist if the user doesn't have access to it.\n\t\tif ( this.toggle_button ) {\n\t\t\treturn this.toggle_button.getValue();\n\t\t} else {\n\t\t\treturn 'punch';\n\t\t}\n\t}\n\n\thandleOverrideUserPreferenceCookie( user_id ) {\n\t\tif ( this.timezone_btn.getValue() == true ) {\n\t\t\tsetCookie( 'OverrideUserPreference', window.btoa( '{ \"user_id\": \"' + user_id + '\"}' ) ); //Base64 encode.\n\t\t} else {\n\t\t\tdeleteCookie( 'OverrideUserPreference' );\n\t\t}\n\t}\n\n\tonWageOrModeChange( id ) {\n\t\tthis.first_build = true;\n\t\tvar $this = this;\n\t\tif ( id === 'wage' ) {\n\t\t\tthis.doNextIfNoValueChangeInManualGrid( doNext, resetWage );\n\t\t} else if ( id === 'timezone' ) {\n\t\t\tthis.handleOverrideUserPreferenceCookie( this.getSelectEmployee() );\n\t\t\tthis.doNextIfNoValueChangeInManualGrid( doNext, resetTimeZone );\n\t\t} else if ( id === 'manual' ) {\n\t\t\tthis.doNextIfNoValueChangeInManualGrid( doNext, resetManual, 'punch' );\n\t\t}\n\n\t\tfunction resetWage() {\n\t\t\t$this.wage_btn.setValue( !$this.wage_btn.getValue( true ) );\n\t\t}\n\n\t\tfunction resetTimeZone() {\n\t\t\t$this.timezone_btn.setValue( !$this.timezone_btn.getValue( true ) );\n\t\t}\n\n\t\tfunction resetManual() {\n\t\t\t$this.toggle_button.setValue( 'manual' );\n\t\t}\n\n\t\tfunction doNext() {\n\t\t\tif ( !$this.edit_view ) {\n\t\t\t\t$this.reSetURL();\n\t\t\t}\n\t\t\t$this.search();\n\t\t\t$this.setDefaultMenu();\n\t\t}\n\t}\n\n\tsetEmployeeNavArrowsStatus() {\n\t\tvar $this = this;\n\t\tvar employee_nav_div = TimeSheetViewController_$( this.el ).find( '.employee-nav-div' );\n\t\tvar left_click = employee_nav_div.find( '.left-click' );\n\t\tvar right_click = employee_nav_div.find( '.right-click' );\n\t\tvar selected_index = $this.employee_nav.getSelectIndex();\n\t\tvar source_data = $this.employee_nav.getSourceData();\n\n\t\tright_click.removeClass( 'disabled' );\n\t\tleft_click.removeClass( 'disabled' );\n\n\t\tvar pager_data = $this.employee_nav.getPagerData();\n\t\tvar current_open_page = $this.employee_nav.getCurrentOpenPage();\n\n\t\t//Error: Uncaught TypeError: Cannot read property 'length' of null in /interface/html5/#!m=TimeSheet&date=20150102&user_id=null line 1698\n\t\tif ( !source_data || ( selected_index === source_data.length - 1 && current_open_page === pager_data.last_page_number ) ) {\n\t\t\tright_click.addClass( 'disabled' );\n\t\t}\n\n\t\tif ( !source_data || ( selected_index === 0 && current_open_page === 1 ) ) {\n\t\t\tleft_click.addClass( 'disabled' );\n\t\t}\n\t}\n\n\tonClearSearch() {\n\t\tvar do_update = false;\n\t\tvar default_layout_id;\n\t\tif ( this.search_panel.getLayoutsArray() && this.search_panel.getLayoutsArray().length > 0 ) {\n\t\t\tdefault_layout_id = TimeSheetViewController_$( this.previous_saved_layout_selector ).children( 'option:contains(\\'' + BaseViewController.default_layout_name + '\\')' ).attr( 'value' );\n\t\t\tvar layout_name = BaseViewController.default_layout_name;\n\t\t\tthis.clearSearchPanel();\n\t\t\tthis.filter_data = null;\n\t\t\tthis.temp_adv_filter_data = null;\n\t\t\tthis.temp_basic_filter_data = null;\n\t\t\tdo_update = true;\n\n\t\t} else {\n\n\t\t\tthis.clearSearchPanel();\n\t\t\tthis.filter_data = null;\n\t\t\tthis.temp_adv_filter_data = null;\n\t\t\tthis.temp_basic_filter_data = null;\n\n\t\t\t//Error: Uncaught TypeError: Cannot read property 'setSelectGridData' of null in /interface/html5/#!m=TimeSheet&date=20141213&user_id=29715 line 1738\n\t\t\tif ( this.column_selector ) {\n\t\t\t\tthis.column_selector.setSelectGridData( this.default_display_columns );\n\t\t\t}\n\n\t\t\t//Error: Uncaught TypeError: Cannot read property 'setValue' of null in /interface/html5/#!m=TimeSheet&date=20150125&user_id=53288 line 1742\n\t\t\tif ( this.sort_by_selector ) {\n\t\t\t\tthis.sort_by_selector.setValue( null );\n\t\t\t}\n\n\t\t\tthis.onSaveNewLayout( BaseViewController.default_layout_name );\n\t\t\treturn;\n\n\t\t}\n\n\t\tvar filter_data = this.getValidSearchFilter();\n\n\t\tvar args;\n\t\tif ( do_update ) {\n\t\t\targs = {};\n\t\t\targs.id = default_layout_id;\n\t\t\targs.data = {};\n\t\t\targs.data.filter_data = filter_data;\n\n\t\t}\n\n\t\tvar $this = this;\n\t\tthis.user_generic_data_api.setUserGenericData( args, {\n\t\t\tonResult: function( res ) {\n\n\t\t\t\tif ( res.isValid() ) {\n\t\t\t\t\t$this.clearViewLayoutCache();\n\t\t\t\t\t$this.need_select_layout_name = layout_name;\n\t\t\t\t\t$this.initLayout();\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tonUpdateLayout() {\n\n\t\tvar selectId = TimeSheetViewController_$( this.previous_saved_layout_selector ).children( 'option:selected' ).attr( 'value' );\n\t\tvar layout_name = TimeSheetViewController_$( this.previous_saved_layout_selector ).children( 'option:selected' ).text();\n\n\t\tvar filter_data = this.getValidSearchFilter();\n\n\t\tvar args = {};\n\t\targs.id = selectId;\n\t\targs.data = {};\n\t\targs.data.filter_data = filter_data;\n\t\targs.data.mode = this.toggle_button.getValue();\n\t\targs.data.show_wage = this.wage_btn.getValue();\n\t\targs.data.use_employee_timezone = this.timezone_btn.getValue();\n\n\t\tvar $this = this;\n\t\tthis.user_generic_data_api.setUserGenericData( args, {\n\t\t\tonResult: function( res ) {\n\t\t\t\tif ( res.isValid() ) {\n\t\t\t\t\t$this.clearViewLayoutCache();\n\t\t\t\t\t$this.need_select_layout_name = layout_name;\n\t\t\t\t\t$this.initLayout();\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tonSaveNewLayout( default_layout_name ) {\n\t\tvar layout_name;\n\t\tif ( Global/* Global.isSet */.x.isSet( default_layout_name ) ) {\n\t\t\tlayout_name = default_layout_name;\n\t\t} else {\n\t\t\tlayout_name = this.save_search_as_input.getValue();\n\t\t}\n\n\t\tif ( !layout_name || layout_name.length < 1 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar filter_data = this.getValidSearchFilter();\n\n\t\tvar args = {};\n\t\targs.script = this.script_name;\n\t\targs.name = layout_name;\n\t\targs.is_default = false;\n\t\targs.data = {};\n\t\targs.data.filter_data = filter_data;\n\t\targs.data.mode = this.toggle_button.getValue();\n\t\targs.data.show_wage = this.wage_btn.getValue();\n\t\targs.data.use_employee_timezone = this.timezone_btn.getValue();\n\n\t\tvar $this = this;\n\t\tthis.user_generic_data_api.setUserGenericData( args, {\n\t\t\tonResult: function( res ) {\n\n\t\t\t\tif ( res.isValid() ) {\n\t\t\t\t\t$this.clearViewLayoutCache();\n\t\t\t\t\t$this.need_select_layout_name = layout_name;\n\t\t\t\t\t$this.initLayout();\n\t\t\t\t} else {\n\t\t\t\t\tTAlertManager.showErrorAlert( res );\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tonSearch( save_only ) {\n\t\tGlobal/* Global.setUINotready */.x.setUINotready();\n\t\tTTPromise.add( 'init', 'init' );\n\t\tTTPromise.wait();\n\n\t\tthis.temp_adv_filter_data = null;\n\t\tthis.temp_basic_filter_data = null;\n\n\t\tthis.getSearchPanelFilter();\n\t\tvar default_layout_id;\n\t\tvar layout_name;\n\t\tif ( this.search_panel.getLayoutsArray() && this.search_panel.getLayoutsArray().length > 0 ) {\n\t\t\tdefault_layout_id = TimeSheetViewController_$( this.previous_saved_layout_selector ).children( 'option:contains(\\'' + BaseViewController.default_layout_name + '\\')' ).attr( 'value' );\n\t\t\tlayout_name = BaseViewController.default_layout_name;\n\n\t\t\tif ( !default_layout_id ) {\n\t\t\t\tthis.onSaveNewLayout( BaseViewController.default_layout_name );\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.onSaveNewLayout( BaseViewController.default_layout_name );\n\t\t\treturn;\n\t\t}\n\n\t\tvar filter_data = this.getValidSearchFilter();\n\n\t\tvar args = {};\n\t\targs.id = default_layout_id;\n\t\targs.data = {};\n\t\targs.data.filter_data = filter_data;\n\t\targs.data.mode = this.toggle_button.getValue();\n\t\targs.data.show_wage = this.wage_btn.getValue();\n\t\targs.data.use_employee_timezone = this.timezone_btn.getValue();\n\n\t\tProgressBar.showOverlay();\n\t\tvar $this = this;\n\t\tthis.user_generic_data_api.setUserGenericData( args, {\n\t\t\tonResult: function( res ) {\n\n\t\t\t\tif ( res.isValid() ) {\n\t\t\t\t\t$this.clearViewLayoutCache();\n\t\t\t\t\t$this.need_select_layout_name = layout_name;\n\t\t\t\t\tif ( !save_only ) {\n $this.initLayout();\n }\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tupdateManualGrid() {\n\t\tvar $this = this;\n\t\tvar start_date_string = this.start_date_picker.getValue();\n\t\tvar user_id = this.getSelectEmployee();\n\t\tProgressBar.noProgressForNextCall();\n\n\t\t$this.handleOverrideUserPreferenceCookie( user_id );\n\t\t$this.api_timesheet.getTimeSheetData( user_id, start_date_string, {\n\t\t\tonResult: function( result ) {\n\t\t\t\tProgressBar.removeNanobar();\n\t\t\t\t$this.full_timesheet_data = result.getResult();\n\t\t\t\tif ( $this.full_timesheet_data === true || !$this.full_timesheet_data.hasOwnProperty( 'timesheet_dates' ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t$this.full_timesheet_data = $this.mergeJobQueueIntoTimeSheetData( $this.full_timesheet_data );\n\t\t\t\t$this.start_date = Global/* Global.strToDate */.x.strToDate( $this.full_timesheet_data.timesheet_dates.start_display_date );\n\t\t\t\t$this.end_date = Global/* Global.strToDate */.x.strToDate( $this.full_timesheet_data.timesheet_dates.end_display_date );\n\t\t\t\t$this.setDefaultMenu();\n\t\t\t\t$this.initInsideEditorData( true );\n\t\t\t\t$this.accumulated_time_source_map = {};\n\t\t\t\t$this.branch_source_map = {};\n\t\t\t\t$this.department_source_map = {};\n\t\t\t\t$this.job_source_map = {};\n\t\t\t\t$this.job_item_source_map = {};\n\t\t\t\t$this.punch_tag_source_map = {};\n\t\t\t\t$this.premium_source_map = {};\n\t\t\t\t$this.accumulated_total_grid_source_map = {};\n\t\t\t\t$this.accumulated_time_source = [];\n\t\t\t\t$this.branch_source = [];\n\t\t\t\t$this.department_source = [];\n\t\t\t\t$this.job_source = [];\n\t\t\t\t$this.job_item_source = [];\n\t\t\t\t$this.punch_tag_source = [];\n\t\t\t\t$this.premium_source = [];\n\t\t\t\t$this.accumulated_total_grid_source = [];\n\t\t\t\t$this.verification_grid_source = [];\n\t\t\t\t$this.onReloadSubGridResult( result );\n\t\t\t}\n\t\t} );\n\t}\n\n\t// Dev Note: TODO/REFACTOR: search() params here differ from BaseViewController.search() this could cause confusion or issues,\n\t// Currently means any search() calls in baseview using the callback param will not work here in TimeSheet.\n\tsearch( setDefaultMenu, force ) {\n\n\t\tthis.accumulated_time_cells_array = []; //reset array since the select cell is clean\n\t\tthis.premium_cells_array = []; //reset array since the select cell is clean\n\t\tthis.accumulated_time_source_map = {};\n\t\tthis.branch_source_map = {};\n\t\tthis.department_source_map = {};\n\t\tthis.job_source_map = {};\n\t\tthis.job_item_source_map = {};\n\t\tthis.punch_tag_source_map = {};\n\t\tthis.premium_source_map = {};\n\t\tthis.accumulated_total_grid_source_map = {};\n\t\tthis.accumulated_time_source = [];\n\t\tthis.branch_source = [];\n\t\tthis.department_source = [];\n\t\tthis.job_source = [];\n\t\tthis.job_item_source = [];\n\t\tthis.punch_tag_source = [];\n\t\tthis.premium_source = [];\n\t\tthis.absence_source = [];\n\t\tthis.accumulated_total_grid_source = [];\n\t\tthis.punch_note_grid_source = [];\n\t\tthis.verification_grid_source = [];\n\t\tthis.select_cells_Array = [];\n\t\tthis.select_punches_array = [];\n\t\tthis.branch_cell_count = 0;\n\t\tthis.department_cell_count = 0;\n\t\tthis.premium_cell_count = 0;\n\t\tthis.job_cell_count = 0;\n\t\tthis.task_cell_count = 0;\n\t\tthis.punch_tag_cell_count = 0;\n\t\tthis.absence_cell_count = 0;\n\t\tthis.punch_note_account = 0;\n\t\tthis.select_punches_array = [];\n\n\t\tvar $this = this;\n\t\tvar filter_data = Global/* Global.convertLayoutFilterToAPIFilter */.x.convertLayoutFilterToAPIFilter( this.select_layout );\n\t\tvar start_date_string = ( this.start_date_picker ) ? this.start_date_picker.getValue() : '';\n\t\tvar user_id = this.getSelectEmployee();\n\t\tif ( !force ) {\n\t\t\tthis.doNextIfNoValueChangeInManualGrid( doNext, reset );\n\t\t} else {\n\t\t\tdoNext();\n\t\t}\n\n\t\tfunction reset() {\n\t\t\tTimeSheetViewController_$( '.button-rotate' ).removeClass( 'button-rotate' );\n\t\t}\n\n\t\tfunction doNext() {\n\t\t\tLocalCacheData.last_timesheet_selected_date = start_date_string;\n\t\t\tLocalCacheData.last_timesheet_selected_user = $this.getSelectEmployee();\n\n\t\t\tif ( LocalCacheData.last_timesheet_selected_user ) {\n\t\t\t\tLocalCacheData.last_timesheet_selected_show_wage = ( $this.wage_btn ) ? $this.wage_btn.getValue( true ) : false;\n\t\t\t\tLocalCacheData.last_timesheet_selected_timezone = ( $this.timezone_btn ) ? $this.timezone_btn.getValue( true ) : false;\n\t\t\t\tif ( $this.toggle_button ) {\n\t\t\t\t\tLocalCacheData.last_timesheet_selected_punch_mode = $this.toggle_button.getValue();\n\t\t\t\t}\n\t\t\t\tvar args = { filter_data: filter_data };\n\t\t\t\tProgressBar.showOverlay();\n\t\t\t\t//Error: TypeError: this.api_timesheet.getTimeSheetData is not a function in /interface/html5/framework/jquery.min.js?v=8.0.0-20141117-155153 line 2 > eval line 1885\n\t\t\t\tif ( !$this.api_timesheet || !$this.api_timesheet || typeof ( $this.api_timesheet.getTimeSheetData ) !== 'function' ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( user_id ) {\n\t\t\t\t\t$this.handleOverrideUserPreferenceCookie( user_id );\n\t\t\t\t\t$this.api_timesheet.getTimeSheetData( user_id, start_date_string, args, {\n\t\t\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t\t\t$this.full_timesheet_data = result.getResult();\n\t\t\t\t\t\t\tif ( $this.full_timesheet_data === true || !$this.full_timesheet_data.hasOwnProperty( 'timesheet_dates' ) ) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t$this.full_timesheet_data = $this.mergeJobQueueIntoTimeSheetData( $this.full_timesheet_data );\n\t\t\t\t\t\t\t$this.start_date = Global/* Global.strToDate */.x.strToDate( $this.full_timesheet_data.timesheet_dates.start_display_date );\n\t\t\t\t\t\t\t$this.end_date = Global/* Global.strToDate */.x.strToDate( $this.full_timesheet_data.timesheet_dates.end_display_date );\n\n\t\t\t\t\t\t\t$this.buildCalendars();\n\n\t\t\t\t\t\t\tif ( setDefaultMenu ) {\n\t\t\t\t\t\t\t\t$this.setDefaultMenu( true );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t$this.searchDone();\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tbuildVerificationGrid() {\n\t\tvar $this = this;\n\n\t\tvar columns = [];\n\t\tif ( !Global/* Global.isSet */.x.isSet( this.verification_grid ) ) {\n\t\t\tvar grid = TimeSheetViewController_$( this.el ).find( '#verification_grid' );\n\t\t\tgrid.attr( 'id', this.ui_id + '_verification_grid' ); //Grid's id is ScriptName + _grid\n\t\t}\n\t\tvar grid_id = this.ui_id + '_verification_grid';\n\n\t\tvar column = {\n\t\t\tname: 'pay_period',\n\t\t\tindex: 'pay_period',\n\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Pay Period' ),\n\t\t\twidth: 100,\n\t\t\tsortable: false,\n\t\t\ttitle: false\n\t\t};\n\t\tcolumns.push( column );\n\n\t\tcolumn = {\n\t\t\tname: 'verification',\n\t\t\tindex: 'verification',\n\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Window' ),\n\t\t\twidth: 100,\n\t\t\tsortable: false,\n\t\t\ttitle: false\n\t\t};\n\t\tcolumns.push( column );\n\n\t\tif ( this.verification_grid ) {\n\t\t\tthis.verification_grid.unload();\n\t\t\tthis.verification_grid = null;\n\t\t\tthis.grid_dic.verification_grid = null;\n\t\t}\n\n\t\tthis.verification_grid = this.grid_dic.verification_grid = new TTGrid( grid_id, {\n\t\t\thoverrows: false,\n\t\t\tmultiselectPosition: 'none',\n\t\t\tverticalResize: false,\n\t\t\tonResizeGrid: false,\n\t\t\theight: 0,\n\t\t}, columns );\n\t}\n\n\tbuildPunchNoteGrid() {\n\t\tvar $this = this;\n\n\t\tvar columns = [];\n\t\tif ( !Global/* Global.isSet */.x.isSet( this.punch_note_grid ) ) {\n\t\t\tvar grid = TimeSheetViewController_$( this.el ).find( '#punch_note_grid' );\n\n\t\t\t//Grid's id is ScriptName + _grid\n\t\t\tgrid.attr( 'id', this.ui_id + '_punch_note_grid' );\n\t\t}\n\n\t\t//if only put one column in grid. There is a UI bug\n\t\tvar first_column = {\n\t\t\tname: 'invisible_column',\n\t\t\tindex: 'invisible_column',\n\t\t\tlabel: ' ',\n\t\t\twidth: 1,\n\t\t\tsortable: false,\n\t\t\ttitle: false,\n\t\t\thidden: true\n\t\t};\n\t\tcolumns.push( first_column );\n\n\t\tvar second_column = {\n\t\t\tname: 'note',\n\t\t\tindex: 'note',\n\t\t\tlabel: ' ',\n\t\t\twidth: 100,\n\t\t\tsortable: false,\n\t\t\ttitle: false,\n\t\t\tcellattr: function( index, value ) {\n\t\t\t\treturn 'title=\"' + value + '\"';\n\t\t\t}\n\t\t};\n\t\tcolumns.push( second_column );\n\t\tvar grid_id = this.ui_id + '_punch_note_grid';\n\t\tif ( this.punch_note_grid ) {\n\t\t\tthis.punch_note_grid.unload();\n\t\t\tthis.punch_note_grid = null;\n\t\t\tthis.grid_dic.punch_note_grid = null;\n\t\t}\n\n\t\tthis.punch_note_grid = this.grid_dic.punch_note_grid = new TTGrid( grid_id, {\n\t\t\thoverrows: false,\n\t\t\tmultiselectPosition: 'none',\n\t\t\tverticalResize: false,\n\t\t\theight: 0,\n\t\t\tonResizeGrid: function() {\n\t\t\t\t$this.setPunchNoteGridWidth();\n\t\t\t}\n\t\t}, columns );\n\n\t\tthis.setGridHeaderBar( 'punch_note_grid', 'Punch Notes' );\n\n\t\t// setGridHeaderBar() sets the width to 100vw (and sets grid title), but this causes issue as the grid is not full width of the screen unlike the others. Therefore, overide the default width of 100vw with 100%.\n\t\t// Related to issue #2712, and (via bisect) appears to be caused by 4e92c7ab463d9b3418735c0db302a50efc43e8bf when jquery.jqgrid.extend.js was removed in a JS upgrade fix.\n\t\tvar table = TimeSheetViewController_$( this.grid_dic.punch_note_grid.grid ).parents( '.ui-jqgrid-view' ).find( '.ui-jqgrid-hbox table' ); //grab the hbox\n\t\ttable.css( 'width', '100%' );\n\t}\n\n\tgetAccumulatedTotalGridPayperiodHeader() {\n\t\tthis.pay_period_header = TimeSheetViewController_$.i18n._( 'No Pay Period' );\n\n\t\tvar pay_period_id = this.timesheet_verify_data.pay_period_id;\n\n\t\tif ( pay_period_id && this.pay_period_data ) {\n\n\t\t\tfor ( var key in this.pay_period_data ) {\n\t\t\t\tvar pay_period = this.pay_period_data[key];\n\t\t\t\tif ( pay_period.id === pay_period_id ) {\n\t\t\t\t\tvar start_date = Global/* Global.strToDate */.x.strToDate( pay_period.start_date ).format();\n\t\t\t\t\tvar end_date = Global/* Global.strToDate */.x.strToDate( pay_period.end_date ).format();\n\t\t\t\t\tthis.pay_period_header = start_date + ' ' + TimeSheetViewController_$.i18n._( 'to' ) + ' ' + end_date;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tbuildAccumulatedTotalGrid() {\n\t\tvar $this = this;\n\n\t\tvar columns = [];\n\n\t\tif ( !Global/* Global.isSet */.x.isSet( this.accumulated_total_grid ) ) {\n\t\t\tvar grid = TimeSheetViewController_$( this.el ).find( '#accumulated_total_grid' );\n\n\t\t\tgrid.attr( 'id', this.ui_id + '_accumulated_total_grid' );\t//Grid's id is ScriptName + _grid\n\n\t\t\tgrid = TimeSheetViewController_$( this.el ).find( '#' + this.ui_id + '_accumulated_total_grid' );\n\t\t}\n\n\t\tvar width = 500;\n\t\tif ( this.wage_btn.getValue( true ) ) {\n\t\t\twidth = 600;\n\t\t}\n\n\t\tvar punch_column_width = 100;\n\t\tif ( this.wage_btn.getValue( true ) ) {\n\t\t\tpunch_column_width = null;\n\t\t}\n\n\t\tvar punch_in_out_column = {\n\t\t\tname: 'punch_info',\n\t\t\tindex: 'punch_info',\n\t\t\tlabel: ' ',\n\t\t\twidth: punch_column_width,\n\t\t\tsortable: false,\n\t\t\ttitle: false,\n\t\t\tformatter: this.onCellFormat\n\t\t};\n\t\tcolumns.push( punch_in_out_column );\n\n\t\tvar start_date_str = this.start_date.format( Global/* Global.getLoginUserDateFormat */.x.getLoginUserDateFormat() );\n\t\tvar end_date_str = this.end_date.format( Global/* Global.getLoginUserDateFormat */.x.getLoginUserDateFormat() );\n\n\t\tthis.getAccumulatedTotalGridPayperiodHeader();\n\n\t\tvar column_width = 100;\n\t\tif ( this.wage_btn.getValue( true ) ) {\n\t\t\tcolumn_width = 150;\n\t\t}\n\t\tvar column_1 = {\n\t\t\tname: 'week',\n\t\t\tindex: 'week',\n\t\t\tlabel: start_date_str + ' ' + TimeSheetViewController_$.i18n._( 'to' ) + ' ' + end_date_str,\n\t\t\twidth: column_width,\n\t\t\tsortable: false,\n\t\t\ttitle: false,\n\t\t\tformatter: this.onCellFormat\n\t\t};\n\t\tvar column_2 = {\n\t\t\tname: 'pay_period',\n\t\t\tindex: 'pay_period',\n\t\t\tlabel: this.pay_period_header,\n\t\t\twidth: column_width,\n\t\t\tsortable: false,\n\t\t\ttitle: false,\n\t\t\tformatter: this.onCellFormat\n\t\t};\n\n\t\tcolumns.push( column_1 );\n\t\tcolumns.push( column_2 );\n\n\t\tvar grid_id = this.ui_id + '_accumulated_total_grid';\n\t\tif ( Global/* Global.isSet */.x.isSet( this.accumulated_total_grid ) == true ) {\n\t\t\tthis.accumulated_total_grid.unload();\n\t\t\tthis.accumulated_total_grid = null;\n\t\t\tthis.grid_dic.accumulated_total_grid = null;\n\t\t}\n\n\t\tthis.accumulated_total_grid = this.grid_dic.accumulated_total_grid = new TTGrid( grid_id, {\n\t\t\thoverrows: false,\n\t\t\tmultiselectPosition: 'none',\n\t\t\tverticalResize: false,\n\t\t\tonResizeGrid: false,\n\t\t\twidth: width,\n\t\t\theight: 0,\n\t\t}, columns );\n\n\t\tvar accumulated_total_grid_title = TimeSheetViewController_$( this.el ).find( '.accumulated-total-grid-title' );\n\t\taccumulated_total_grid_title.css( 'display', 'block' );\n\t\tthis.setAccumulatedTotalGridPayPeriodHeaders( width );\n\t}\n\n\t//Override and disable as bindTimeSheetGridColumnEvents() is used at a different point instead.\n\tbindGridColumnEvents() {\n\t}\n\n\t//Bind column click event to change sort type and save columns to t_grid_header_array to use to set column style (asc or desc)\n\tbindTimeSheetGridColumnEvents() {\n\t\tvar display_columns = this.grid.getGridParam( 'colModel' );\n\n\t\t//Exception taht display column not existed, not sure when this will happen, but may there will be a second time load if this happen\n\t\tif ( !display_columns ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar len = display_columns.length;\n\n\t\tthis.t_grid_header_array = [];\n\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar column_info = display_columns[i];\n\t\t\tvar column_header = TimeSheetViewController_$( TimeSheetViewController_$( this.el ).find( '#gbox_' + this.ui_id + '_grid' ).find( 'div #jqgh_' + this.ui_id + '_grid_' + column_info.name ) );\n\n\t\t\tthis.t_grid_header_array.push( column_header.TGridHeader() );\n\t\t\tcolumn_header.bind( 'click', onColumnHeaderClick );\n\t\t}\n\n\t\tvar $this = this;\n\n\t\tfunction onColumnHeaderClick( e ) {\n\t\t\tvar field = TimeSheetViewController_$( this ).attr( 'id' );\n\t\t\tfield = field.substring( 10 + $this.ui_id.length + 1, field.length );\n\n\t\t\tif ( field === 'cb' || field === 'punch_info' ) { //first column, check box column.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar date = Global/* Global.strToDate */.x.strToDate( field, $this.full_format );\n\n\t\t\tif ( date && date.getYear() > 0 ) {\n\t\t\t\t$this.setDatePickerValue( date.format( Global/* Global.getLoginUserDateFormat */.x.getLoginUserDateFormat() ) );\n\t\t\t\t$this.highLightSelectDay();\n\t\t\t\t//reLoadSubGridsSource() calls getTimeSheetTotalData and would cause duplicate API requests.\n\t\t\t\t//The reLoadSubGridsSource call is not needed required here, because it will be called in onCellSelect() which is triggered from the click event below.\n\t\t\t\t// $this.reLoadSubGridsSource();\n\t\t\t\t//select first punch cell when clicking the header row\n\t\t\t\tTimeSheetViewController_$( TimeSheetViewController_$( '.timesheet-grid tr#1 td' )[TimeSheetViewController_$( 'th.highlight-header' ).index()] ).click();\n\t\t\t}\n\n\t\t}\n\t}\n\n\tcheckIsSelectedAbsenceCell( row_id, cell_index ) {\n\t\tfor ( var i = 0, m = this.absence_select_cells_Array.length; i < m; i++ ) {\n\t\t\tvar cell = this.absence_select_cells_Array[i];\n\t\t\tif ( cell.row_id == row_id && cell.cell_index === cell_index ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tbuildAbsenceGrid() {\n\t\tvar $this = this;\n\n\t\tvar grid_id = 'absence_grid';\n\t\tvar title = TimeSheetViewController_$.i18n._( 'Absence' );\n\n\t\tif ( this[grid_id] ) {\n\t\t\tthis[grid_id].unload();\n\t\t\tthis[grid_id] = null;\n\t\t\tthis.grid_dic[grid_id] = null;\n\t\t} else {\n\t\t\tvar grid = TimeSheetViewController_$( this.el ).find( '#absence_grid' );\n\n\t\t\tgrid.attr( 'id', this.ui_id + '_absence_grid' ); //Grid's id is ScriptName + _grid\n\n\t\t\tgrid = TimeSheetViewController_$( this.el ).find( '#' + this.ui_id + '_absence_grid' );\n\t\t}\n\n\t\tthis[grid_id] = this.grid_dic[grid_id] = new TTGrid( this.ui_id + '_absence_grid', {\n\t\t\tsortable: false,\n\t\t\thoverrows: false,\n\t\t\theight: 0, //Start the grid height at 0 instead of parent height to avoid transient scrollbars from causing the width to be inconsistent across tables.\n\t\t\tondblClickRow: function() {\n\t\t\t\t$this.onGridDblClickRow( 'absence' );\n\t\t\t},\n\t\t\tonRightClickRow: function( row_id, iRow, cell_index, e ) {\n\t\t\t\tif ( !$this.checkIsSelectedAbsenceCell( row_id, cell_index ) ) {\n\t\t\t\t\tvar cell_val = TimeSheetViewController_$( e.target ).closest( 'td,th' ).html();\n\t\t\t\t\t$this.onCellSelect( 'absence_grid', row_id, cell_index, cell_val, this, e );\n\t\t\t\t\t$this.onSelectRow( 'absence_grid', row_id, this );\n\n\t\t\t\t\tif ( TimeSheetViewController_$( '.edit-view:visible' ).length == 0 ) {\n\t\t\t\t\t\t$this.setDefaultMenu();\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$this.setEditMenu();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tonCellSelect: function( row_id, cell_index, cell_val, e ) {\n\t\t\t\tif ( TimeSheetViewController_$( '.edit-view:visible' ).length == 0 ) {\n\t\t\t\t\t$this.setDefaultMenu();\n\t\t\t\t} else {\n\t\t\t\t\t$this.setEditMenu();\n\t\t\t\t}\n\t\t\t},\n\t\t\tonResizeGrid: function() {\n\t\t\t\tif ( $this.absence_grid && $this.absence_grid.getGridWidth() != $this.getTimeSheetWidth() ) {\n\t\t\t\t\t$this.absence_grid.setGridWidth( $this.getTimeSheetWidth() );\n\t\t\t\t}\n\t\t\t},\n\t\t\tbeforeSelectRow: function( row_id, e ) {\n\t\t\t\te.preventDefault();\n\n\t\t\t\tvar cell_index = 0;\n\t\t\t\tif ( TimeSheetViewController_$( e.target ).attr( 'role' ) == 'gridcell' ) {\n\t\t\t\t\tcell_index = TimeSheetViewController_$( e.target ).index();\n\t\t\t\t} else {\n\t\t\t\t\tcell_index = TimeSheetViewController_$( e.target ).parents( 'td' ).index();\n\t\t\t\t}\n\n\t\t\t\tvar cell_val = TimeSheetViewController_$( e.target ).text();\n\n\t\t\t\t$this.onCellSelect( 'absence_grid', row_id, cell_index, cell_val, this, e );\n\t\t\t\t$this.onSelectRow( 'absence_grid', row_id, this );\n\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tmultiselectPosition: 'none',\n\t\t\twinMultiSelect: false,\n\t\t\tverticalResize: false\n\n\t\t}, this.timesheet_columns, TimeSheetViewController_$.i18n._( 'Absence' ) );\n\n\t\tthis.bindTimeSheetGridColumnEvents();\n\t\tthis.setGridHeaderBar( grid_id, title );\n\n\t\tif ( this.grid_dic[grid_id] && this.grid_dic[grid_id].grid ) {\n\t\t\tthis.grid_dic.absence_grid.grid.setGridWidth( this.getTimeSheetWidth() );\n\t\t}\n\t}\n\n\tcheckIsSelectedPunchCell( row_id, cell_index ) {\n\t\tfor ( var i = 0, m = this.select_cells_Array.length; i < m; i++ ) {\n\t\t\tvar cell = this.select_cells_Array[i];\n\t\t\tif ( cell.row_id == row_id && cell.cell_index == cell_index ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Paired secondary row coloring for timesheet\n\t */\n\tcolorTimeSheetRows() {\n\t\tvar $trs = TimeSheetViewController_$( '.timesheet-grid-div .timesheet-grid tr' );\n\t\tvar skips = 0;\n\t\tvar colored = 0;\n\t\tfor ( var i = 1; i < $trs.length - 1; i++ ) {\n\t\t\tif ( skips == 2 && colored < 2 ) {\n\t\t\t\tTimeSheetViewController_$( $trs[i] ).addClass( 'ui-priority-secondary' );\n\t\t\t\tcolored++;\n\t\t\t} else if ( colored == 2 ) {\n\t\t\t\tskips = 1; //Resets to 1 because we're skipping this iteration.\n\t\t\t\tcolored = 0;\n\t\t\t} else {\n\t\t\t\tskips++;\n\t\t\t}\n\t\t}\n\t}\n\n\tbuildTimeSheetGrid() {\n\t\tvar grid_id = this.ui_id + '_grid';\n\t\tvar $this = this;\n\n\t\tif ( this.timesheet_grid && !this.first_build ) {\n\t\t\tTimeSheetViewController_$.jgrid.guid = 1;\n\t\t} else {\n\t\t\tif ( this.timesheet_grid ) {\n\t\t\t\tthis.timesheet_grid.unload();\n\t\t\t\tthis.timesheet_grid = null;\n\t\t\t\tTimeSheetViewController_$.jgrid.guid = 1;\n\t\t\t}\n\t\t\tvar grid = TimeSheetViewController_$( this.el ).find( '#timesheet_grid' );\n\t\t\tgrid.attr( 'id', grid_id );\t//Grid's id is ScriptName + _grid\n\n\t\t\tvar grid_setup_data = {\n\t\t\t\tcontainer_selector: '.context-border',\n\t\t\t\taltRows: false,\n\t\t\t\tsortable: false,\n\t\t\t\thoverrows: false,\n\t\t\t\theight: 0, //Start the grid height at 0 instead of parent height to avoid transient scrollbars from causing the width to be inconsistent across tables.\n\t\t\t\tondblClickRow: function( row_id, row_index, cell_index, e ) {\n\t\t\t\t\tvar row = $this.getRowData( 'timesheet_grid', row_id );\n\n\t\t\t\t\t//Make sure double click event doesn't get triggered on a request row (authorized/pending/declined)\n\t\t\t\t\t// as we are already in the process of navigating to that view, so it causes edit view and navigation operations to occur at the same time.\n\t\t\t\t\tif ( row.type !== TimeSheetViewController.REQUEST_ROW ) {\n\t\t\t\t\t\t$this.onGridDblClickRow();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonRightClickRow: function( row_id, iRow, cell_index, e ) {\n\t\t\t\t\tif ( !$this.checkIsSelectedPunchCell( row_id, cell_index ) ) {\n\t\t\t\t\t\tvar cell_val = TimeSheetViewController_$( e.target ).closest( 'td,th' ).html();\n\t\t\t\t\t\t$this.onCellSelect( 'timesheet_grid', row_id, cell_index, cell_val, this, e );\n\t\t\t\t\t\t$this.onSelectRow( 'timesheet_grid', row_id, this );\n\n\t\t\t\t\t\tif ( TimeSheetViewController_$( '.edit-view:visible' ).length == 0 ) {\n\t\t\t\t\t\t\t$this.setDefaultMenu();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$this.setEditMenu();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonCellSelect: function( row_id, cell_index, cell_val, e ) {\n\t\t\t\t\tif ( TimeSheetViewController_$( '.edit-view:visible' ).length == 0 ) {\n\t\t\t\t\t\t$this.setDefaultMenu();\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$this.setEditMenu();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonResizeGrid: function() {\n\t\t\t\t\tif ( $this.getPunchMode() === 'manual' ) {\n\t\t\t\t\t\tif ( $this.editor ) {\n\t\t\t\t\t\t\t$this.setManualTimeSheetGridSize();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t$this.setGridSize();\n\t\t\t\t\t$this.setTimeSheetGridPayPeriodHeaders();\n\t\t\t\t\t$this.setTimeSheetGridHolidayHeaders();\n\t\t\t\t},\n\t\t\t\tgridComplete: function() {\n\t\t\t\t\t$this.colorTimeSheetRows();\n\t\t\t\t},\n\t\t\t\tbeforeSelectRow: function( row_id, e ) {\n\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\tvar cell_index = 0;\n\t\t\t\t\tif ( TimeSheetViewController_$( e.target ).attr( 'role' ) == 'gridcell' ) {\n\t\t\t\t\t\tcell_index = TimeSheetViewController_$( e.target ).index();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcell_index = TimeSheetViewController_$( e.target ).parents( 'td' ).index();\n\t\t\t\t\t}\n\n\t\t\t\t\tvar cell_val = TimeSheetViewController_$( e.target ).text();\n\n\t\t\t\t\t$this.onCellSelect( 'timesheet_grid', row_id, cell_index, cell_val, this, e );\n\t\t\t\t\t$this.onSelectRow( 'timesheet_grid', row_id, this );\n\n\t\t\t\t\treturn false;\n\t\t\t\t},\n\t\t\t\tmultiselectPosition: 'none',\n\t\t\t\twinMultiSelect: false,\n\t\t\t\tverticalResize: false\n\t\t\t};\n\n\t\t\tthis.timesheet_grid = this.grid_dic.timesheet_grid = this.grid = new TTGrid( grid_id, grid_setup_data, this.timesheet_columns );\n\t\t\tthis.grid_dic.timesheet_grid.grid.setGridWidth( this.getTimeSheetWidth() );\n\t\t}\n\n\t\tthis.grid_div.scroll( function( e ) {\n\t\t\t$this.scroll_position = $this.grid_div.scrollTop();\n\t\t} );\n\t}\n\n\tonGridDblClickRow( name ) {\n\t\tvar context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.determineContextMenuMountAttributes().id );\n\t\tvar len = context_menu_array.length;\n\t\tvar need_break = false;\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tif ( need_break ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlet id = context_menu_array[i].id;\n\t\t\tswitch ( id ) {\n\t\t\t\tcase 'edit':\n\t\t\t\t\tif ( !context_menu_array[i].disabled && context_menu_array[i].visible ) {\n\t\t\t\t\t\tProgressBar.showOverlay();\n\t\t\t\t\t\tthis.onEditClick();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tif ( need_break ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlet id = context_menu_array[i].id;\n\t\t\tswitch ( id ) {\n\t\t\t\tcase 'view':\n\t\t\t\t\tneed_break = true;\n\t\t\t\t\tif ( !context_menu_array[i].disabled && context_menu_array[i].visible ) {\n\t\t\t\t\t\tProgressBar.showOverlay();\n\t\t\t\t\t\tthis.onViewClick();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tlet id = context_menu_array[i].id;\n\t\t\tswitch ( id ) {\n\t\t\t\tcase 'add_absence':\n\t\t\t\tcase 'add':\n\t\t\t\tcase 'add_punch':\n\t\t\t\t\t// There are 2 add icons, one for punch and one for absence.\n\t\t\t\t\t// We must ensure to check the right one to provide permissions for the add click or absence will be allowed based on the punch permissions\n\t\t\t\t\tif ( name == 'absence' && id != 'add_absence' ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !context_menu_array[i].disabled && context_menu_array[i].visible ) {\n\t\t\t\t\t\tif ( this.isPunchCells() ) {\n\t\t\t\t\t\t\tProgressBar.showOverlay();\n\t\t\t\t\t\t\tthis.onAddClick();\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif ( !this.addPermissionValidate( 'punch' ) ) {\n\t\t\t//Regular employees open In/Out view when clicking a timesheet cell.\n\t\t\tMenuManager.openSelectView( 'InOut' );\n\t\t\treturn;\n\t\t}\n\t}\n\n\tisPunchCells() {\n\t\tvar result = false;\n\t\tvar cell = this.select_cells_Array && this.select_cells_Array.length > 0 && this.select_cells_Array[0];\n\t\tvar row = cell && this.timesheet_data_source[parseInt( cell.row_id ) - 1];\n\t\tif ( row && row.type === TimeSheetViewController.PUNCH_ROW ) {\n\t\t\tresult = true;\n\t\t} else if ( this.absence_select_cells_Array && this.absence_select_cells_Array.length > 0 ) {\n\t\t\tresult = true;\n\t\t}\n\t\treturn result;\n\t}\n\n\tbuildAccumulatedGrid() {\n\t\tvar $this = this;\n\n\t\tvar grid_id = 'accumulated_time_grid';\n\t\tvar title = TimeSheetViewController_$.i18n._( 'Accumulated Time' );\n\n\t\tif ( this[grid_id] ) {\n\t\t\t//Commenting out the next line replicates TypeError: Failed to execute 'replaceChild' on 'Node': parameter 2 is not of type 'Node'. when using Date left arrow on timesheet.\n\t\t\t// Also happens when clicking the top-right in-app refresh button too.\n\t\t\tthis[grid_id].unload();\n\t\t\tthis[grid_id] = null;\n\t\t\tthis.grid_dic[grid_id] = null;\n\t\t}\n\n\t\tthis[grid_id] = this.grid_dic[grid_id] = new TTGrid( 'accumulated_time_grid', {\n\t\t\tsortable: false,\n\t\t\thoverrows: false,\n\t\t\theight: 0, //Start the grid height at 0 instead of parent height to avoid transient scrollbars from causing the width to be inconsistent across tables.\n\t\t\tondblClickRow: function() {\n\t\t\t\t$this.onAccumulatedTimeClick();\n\t\t\t},\n\t\t\tonRightClickRow: function( row_id, iRow, cell_index, e ) {\n\t\t\t\tvar cell_val = TimeSheetViewController_$( e.target ).closest( 'td,th' ).html();\n\t\t\t\t$this.onCellSelect( 'accumulated_grid', row_id, cell_index, cell_val, this, e );\n\t\t\t\t$this.onSelectRow( 'accumulated_grid', row_id, this );\n\t\t\t},\n\t\t\tonCellSelect: function( row_id, cell_index, cell_val, e ) {\n\t\t\t\t$this.setDefaultMenu();\n\t\t\t},\n\t\t\tonResizeGrid: function() {\n\t\t\t\tif ( $this.grid_dic['accumulated_time_grid'] ) {\n\t\t\t\t\t$this.grid_dic['accumulated_time_grid'].grid.setGridWidth( $this.getTimeSheetWidth() );\n\t\t\t\t}\n\t\t\t},\n\t\t\tbeforeSelectRow: function( row_id, e ) {\n\t\t\t\te.preventDefault();\n\n\t\t\t\tvar cell_index = 0;\n\t\t\t\tif ( TimeSheetViewController_$( e.target ).attr( 'role' ) == 'gridcell' ) {\n\t\t\t\t\tcell_index = TimeSheetViewController_$( e.target ).index();\n\t\t\t\t} else {\n\t\t\t\t\tcell_index = TimeSheetViewController_$( e.target ).parents( 'td' ).index();\n\t\t\t\t}\n\n\t\t\t\tvar cell_val = TimeSheetViewController_$( e.target ).text();\n\n\t\t\t\t$this.onCellSelect( 'accumulated_grid', row_id, cell_index, cell_val, this, e );\n\t\t\t\t$this.onSelectRow( 'accumulated_grid', row_id, this );\n\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tmultiselectPosition: 'none',\n\t\t\twinMultiSelect: false,\n\t\t\tverticalResize: false\n\n\t\t}, this.timesheet_columns );\n\n\t\tthis.setGridHeaderBar( grid_id, title );\n\n\t\tif ( this.grid_dic[grid_id] && this.grid_dic[grid_id].grid ) {\n\t\t\tthis.grid_dic[grid_id].grid.setGridWidth( this.getTimeSheetWidth() );\n\t\t}\n\t}\n\n\tbuildSubGrid( grid_id, title ) {\n\t\tvar $this = this;\n\n\t\tvar html_grid_id = this.ui_id + '_' + grid_id;\n\t\tif ( !Global/* Global.isSet */.x.isSet( this[grid_id] ) ) {\n\t\t\tvar grid = TimeSheetViewController_$( this.el ).find( '#' + grid_id );\n\t\t\tgrid.attr( 'id', html_grid_id );\t//Grid's id is ScriptName + _grid\n\t\t}\n\n\t\tif ( this[grid_id] ) {\n\t\t\tthis[grid_id].unload();\n\t\t\tthis[grid_id] = null;\n\t\t\tthis.grid_dic[grid_id] = null;\n\t\t}\n\n\t\tif ( grid_id === 'premium_grid' ) {\n\t\t\tthis[grid_id] = this.grid_dic[grid_id] = new TTGrid( html_grid_id, {\n\t\t\t\thoverrows: false,\n\t\t\t\tmultiselectPosition: 'none',\n\t\t\t\twinMultiSelect: false,\n\t\t\t\theight: 0, //Start the grid height at 0 instead of parent height to avoid transient scrollbars from causing the width to be inconsistent across tables.\n\t\t\t\tonSelectRow: function( row_id, flag, e ) {\n\t\t\t\t\t$this.onSelectRow( 'premium_grid', row_id, this );\n\t\t\t\t},\n\t\t\t\tonRightClickRow: function( row_id, iRow, cell_index, e ) {\n\t\t\t\t\tvar cell_val = TimeSheetViewController_$( e.target ).closest( 'td,th' ).html();\n\t\t\t\t\t$this.onCellSelect( 'premium_grid', row_id, cell_index, cell_val, this, e );\n\t\t\t\t\t$this.onSelectRow( 'premium_grid', row_id, this );\n\t\t\t\t},\n\t\t\t\tonCellSelect: function( row_id, cell_index, cell_val, e ) {\n\t\t\t\t\t$this.unsetSelectedCells( 'timesheet_grid' );\n\t\t\t\t\t$this.unsetSelectedCells( 'absence_grid' );\n\t\t\t\t\t$this.onCellSelect( 'premium_grid', row_id, cell_index, cell_val, this, e );\n\t\t\t\t\t$this.select_punches_array = [];\n\t\t\t\t\t$this.setDefaultMenu();\n\t\t\t\t},\n\t\t\t\tondblClickRow: function() {\n\t\t\t\t\tif ( grid_id === 'premium_grid' ) {\n\t\t\t\t\t\t$this.onAccumulatedTimeClick();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonResizeGrid: function() {\n\t\t\t\t\tif ( $this.grid_dic[grid_id] ) {\n\t\t\t\t\t\t$this.grid_dic[grid_id].grid.setGridWidth( $this.getTimeSheetWidth() );\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tverticalResize: false\n\t\t\t}, this.timesheet_columns );\n\n\t\t\t//subgrids might not be rendered, so we need to check for them in the grid_dic first.\n\t\t\tif ( this[grid_id] && this[grid_id].grid ) {\n\t\t\t\tthis[grid_id].grid.addClass( 'premium-grid' );\n\t\t\t}\n\t\t} else {\n\t\t\tthis[grid_id] = this.grid_dic[grid_id] = new TTGrid( html_grid_id, {\n\t\t\t\thoverrows: false,\n\t\t\t\tmultiselectPosition: 'none',\n\t\t\t\twinMultiSelect: false,\n\t\t\t\theight: 0, //Start the grid height at 0 instead of parent height to avoid transient scrollbars from causing the width to be inconsistent across tables.\n\t\t\t\tonCellSelect: function( row_id, cell_index, cell_val, e ) {\n\t\t\t\t\t$this.unsetSelectedCells( 'timesheet_grid' );\n\t\t\t\t\t$this.unsetSelectedCells( 'absence_grid' );\n\n\t\t\t\t\t$this.onCellSelect( grid_id, row_id, cell_index, cell_val, this, e );\n\t\t\t\t\t$this.select_punches_array = [];\n\t\t\t\t\t$this.setDefaultMenu();\n\t\t\t\t},\n\t\t\t\tonResizeGrid: function() {\n\t\t\t\t\tif ( $this.grid_dic[grid_id] ) {\n\t\t\t\t\t\t$this.grid_dic[grid_id].grid.setGridWidth( $this.getTimeSheetWidth() );\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tverticalResize: false\n\t\t\t}, this.timesheet_columns );\n\t\t}\n\n\t\tthis.setGridHeaderBar( grid_id, title );\n\n\t\t//this loop hits all possible grids. subgrids might not be rendered, so we need to check for them in the grid_dic first.\n\t\tif ( this.grid_dic[grid_id] && this.grid_dic[grid_id].grid ) {\n\t\t\tthis.grid_dic[grid_id].grid.setGridWidth( this.getTimeSheetWidth() );\n\t\t}\n\t}\n\n\tsetGridSExpendOrCollapseStatus( grid_id, title ) {\n\t\tif ( this.grid_dic[grid_id] ) {\n\t\t\tvar grid = this.grid_dic[grid_id].grid;\n\t\t\tvar table = TimeSheetViewController_$( TimeSheetViewController_$( this.el ).find( 'table[aria-labelledby=gbox_' + this.ui_id + '_' + grid_id + ']' )[0] );\n\t\t\tvar title_bar = table.find( '.title-bar' );\n\t\t\tthis.setGridHeight( grid_id );\n\n\t\t\tif ( LocalCacheData.timesheet_sub_grid_expended_dic[grid_id] !== true ) {\n\t\t\t\tgrid.setGridHeight( 0 );\n\t\t\t}\n\n\t\t\tthis.updateGridHeaderBar( grid_id, title );\n\t\t}\n\t}\n\n\t//Show expend and collapse button in grid title bar\n\tsetGridExpendButton( grid_id, title ) {\n\t\tvar $this = this;\n\t\tvar table = TimeSheetViewController_$( TimeSheetViewController_$( this.el ).find( 'table[aria-labelledby=gbox_' + this.ui_id + '_' + grid_id + ']' )[0] );\n\t\tvar title_bar = table.find( '.title-bar' );\n\n\t\tif ( title_bar.find( '.grid-expend-btn' ).length === 0 ) { //prevent doubling up of expand arrows.\n\t\t\tvar img = TimeSheetViewController_$( '<img>' );\n\t\t\timg.addClass( 'grid-expend-btn' );\n\n\t\t\tif ( !Global/* Global.isSet */.x.isSet( LocalCacheData.timesheet_sub_grid_expended_dic[grid_id] ) ||\n\t\t\t\tLocalCacheData.timesheet_sub_grid_expended_dic[grid_id] === true ) {\n\n\t\t\t\timg.attr( 'src', Global/* Global.getRealImagePath */.x.getRealImagePath( 'images/big_collapse.png' ) );\n\t\t\t\tLocalCacheData.timesheet_sub_grid_expended_dic[grid_id] = true;\n\n\t\t\t} else {\n\t\t\t\timg.attr( 'src', Global/* Global.getRealImagePath */.x.getRealImagePath( 'images/big_expand.png' ) );\n\t\t\t\tLocalCacheData.timesheet_sub_grid_expended_dic[grid_id] = false;\n\t\t\t}\n\n\t\t\ttitle_bar.append( img );\n\n\t\t\tthis.setGridSExpendOrCollapseStatus( grid_id, title );\n\n\t\t\timg.click( function( e ) {\n\n\t\t\t\tif ( LocalCacheData.timesheet_sub_grid_expended_dic[grid_id] === true ) {\n\t\t\t\t\tTimeSheetViewController_$( this ).attr( 'src', Global/* Global.getRealImagePath */.x.getRealImagePath( 'images/big_expand.png' ) );\n\t\t\t\t\tLocalCacheData.timesheet_sub_grid_expended_dic[grid_id] = false;\n\t\t\t\t\t$this.setGridSExpendOrCollapseStatus( grid_id, title );\n\t\t\t\t} else {\n\t\t\t\t\tTimeSheetViewController_$( this ).attr( 'src', Global/* Global.getRealImagePath */.x.getRealImagePath( 'images/big_collapse.png' ) );\n\t\t\t\t\tLocalCacheData.timesheet_sub_grid_expended_dic[grid_id] = true;\n\t\t\t\t\t$this.setGridSExpendOrCollapseStatus( grid_id, title );\n\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n\n\tupdateGridHeaderBar( grid_id, description ) {\n\t\tvar label = description;\n\t\tvar table = TimeSheetViewController_$( TimeSheetViewController_$( this.el ).find( 'table[aria-labelledby=gbox_' + this.ui_id + '_' + grid_id + ']' )[0] );\n\t\tvar title_span = table.find( '.title-span' );\n\t\tvar count = 0;\n\n\t\tif ( LocalCacheData.timesheet_sub_grid_expended_dic[grid_id] !== true ) {\n\t\t\tswitch ( grid_id ) {\n\t\t\t\tcase 'branch_grid':\n\t\t\t\t\tlabel = label + ' (' + ( this.branch_cell_count ) + ')';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'department_grid':\n\t\t\t\t\tlabel = label + ' (' + ( this.department_cell_count ) + ')';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'job_item_grid':\n\t\t\t\t\tlabel = label + ' (' + ( this.task_cell_count ) + ')';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'punch_tag_grid':\n\t\t\t\t\tlabel = label + ' (' + ( this.punch_tag_cell_count ) + ')';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'job_grid':\n\t\t\t\t\tlabel = label + ' (' + ( this.job_cell_count ) + ')';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'premium_grid':\n\t\t\t\t\tlabel = label + ' (' + ( this.premium_cell_count ) + ')';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'absence_grid':\n\t\t\t\t\tlabel = label + ' (' + ( this.absence_cell_count ) + ')';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'punch_note_grid':\n\t\t\t\t\tlabel = label + ' (' + ( this.punch_note_account ) + ')';\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\ttitle_span.text( label );\n\t}\n\n\tsetGridHeaderBar( grid_id, label ) {\n\t\tvar table = TimeSheetViewController_$( this.grid_dic[grid_id].grid ).parents( '.ui-jqgrid-view' ).find( '.ui-jqgrid-hbox table' ); //grab the hbox\n\t\t//table.empty();\n\t\ttable.css( 'width', '100vw' ); //set default width of timesheet tables to the width of the screen to set the header widths.\n\n\t\tvar label = TimeSheetViewController_$.i18n._( label );\n\n\t\ttable.find( 'tr:first' ).hide();\n\t\tvar title_bar = TimeSheetViewController_$( '<div class=\\'title-bar\\'><span class=\\'title-span\\'>' + label + '</span></div>' );\n\t\ttable.append( title_bar );\n\t}\n\n\tbuildManualTimeSheetsColumns() {\n\t\tthis.day_dic = {};\n\t\tfor ( var i = 0; i < 7; i++ ) {\n\t\t\tvar current_date = new Date( new Date( this.start_date.getTime() ).setDate( this.start_date.getDate() + i ) );\n\t\t\tvar day_text = current_date.format( this.day_format );\n\t\t\tvar date_text = current_date.format( this.date_format );\n\t\t\tthis.day_dic['day_' + i] = { value: day_text + '<br>' + date_text, field: current_date.format() };\n\t\t}\n\t}\n\n\tgetManualTimeSheetData( callBack ) {\n\t\tvar $this = this;\n\n\t\tvar user_id = this.getSelectEmployee();\n\t\tif ( user_id ) {\n\t\t\tvar args = {};\n\t\t\targs.filter_data = {\n\t\t\t\tuser_id: user_id,\n\t\t\t\tobject_type_id: 10,\n\t\t\t\tstart_date: this.start_date.format(),\n\t\t\t\tend_date: this.end_date.format()\n\t\t\t};\n\t\t\targs.filter_columns = {\n\t\t\t\t'id': true,\n\t\t\t\t'date_stamp': true,\n\t\t\t\t'total_time': true,\n\t\t\t\t'object_type': true,\n\t\t\t\t'name': true,\n\t\t\t\t'branch_id': true,\n\t\t\t\t'department_id': true,\n\t\t\t\t'branch': true,\n\t\t\t\t'department': true,\n\t\t\t\t'job': true,\n\t\t\t\t'job_item': true,\n\t\t\t\t'job_id': true,\n\t\t\t\t'job_item_id': true,\n\t\t\t\t'punch_tag': true,\n\t\t\t\t'punch_tag_id': true,\n\t\t\t\t'note': true,\n\t\t\t\t'override': true\n\t\t\t};\n\t\t\tthis.api_user_date_total.getUserDateTotal( args, true, {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t$this.manual_timesheet_data = result.getResult();\n\t\t\t\t\tcallBack();\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n\n\tbuildManualTimeSheetData() {\n\t\tthis.time_sheet_data_overrode_true_map = {};\n\t\tthis.time_sheet_data_overrode_false_map = {};\n\t\tvar sort_by_fields = ['branch_id', 'department_id', 'job_id', 'job_item_id', 'punch_tag_id'],\n\t\t\tmanual_timesheet_data_group_array = [],\n\t\t\toverride_true_array = [],\n\t\t\toverride_false_array = [];\n\t\tthis.manual_timesheet_data.sort( Global/* Global.m_sort_by */.x.m_sort_by( sort_by_fields ) );\n\t\tmanual_timesheet_data_group_array = _.groupBy( this.manual_timesheet_data, 'override' );\n\t\toverride_true_array = manual_timesheet_data_group_array[true];\n\t\toverride_false_array = manual_timesheet_data_group_array[false];\n\t\tdoNext( override_true_array, this.time_sheet_data_overrode_true_map );\n\t\tdoNext( override_false_array, this.time_sheet_data_overrode_false_map );\n\n\t\tfunction doNext( manual_timesheet_data, target_map ) {\n\t\t\t!manual_timesheet_data && ( manual_timesheet_data = [] );\n\t\t\tfor ( var i = 0, m = manual_timesheet_data.length; i < m; i++ ) {\n\t\t\t\tvar data = manual_timesheet_data[i];\n\n\t\t\t\tvar key = data.branch_id + '-' + data.department_id + '-' + data.job_id + '-' + data.job_item_id;\n\t\t\t\tif ( !target_map[key] ) {\n\t\t\t\t\ttarget_map[key] = {};\n\t\t\t\t\ttarget_map[key].branch_id = data.branch_id;\n\t\t\t\t\ttarget_map[key].department_id = data.department_id;\n\t\t\t\t\ttarget_map[key].job_id = data.job_id;\n\t\t\t\t\ttarget_map[key].job_item_id = data.job_item_id;\n\t\t\t\t\ttarget_map[key].punch_tag_id = data.punch_tag_id;\n\t\t\t\t\ttarget_map[key].branch = data.branch;\n\t\t\t\t\ttarget_map[key].department = data.department;\n\t\t\t\t\ttarget_map[key].job = data.job;\n\t\t\t\t\ttarget_map[key].job_item = data.job_item;\n\t\t\t\t\ttarget_map[key].punch_tag = data.punch_tag;\n\t\t\t\t\ttarget_map[key].override = data.override;\n\t\t\t\t\ttarget_map[key][data.date_stamp] = data;\n\t\t\t\t} else if ( target_map[key][data.date_stamp] ) {\n\t\t\t\t\t// If already has data in this day, create next row.\n\t\t\t\t\tvar j = 1;\n\t\t\t\t\twhile ( true ) {\n\t\t\t\t\t\tif ( !target_map[key + '-' + j] ) {\n\t\t\t\t\t\t\ttarget_map[key + '-' + j] = {};\n\t\t\t\t\t\t\ttarget_map[key + '-' + j].branch_id = data.branch_id;\n\t\t\t\t\t\t\ttarget_map[key + '-' + j].department_id = data.department_id;\n\t\t\t\t\t\t\ttarget_map[key + '-' + j].job_id = data.job_id;\n\t\t\t\t\t\t\ttarget_map[key + '-' + j].job_item_id = data.job_item_id;\n\t\t\t\t\t\t\ttarget_map[key + '-' + j].punch_tag_id = data.punch_tag_id;\n\t\t\t\t\t\t\ttarget_map[key + '-' + j].branch = data.branch;\n\t\t\t\t\t\t\ttarget_map[key + '-' + j].department = data.department;\n\t\t\t\t\t\t\ttarget_map[key + '-' + j].job = data.job;\n\t\t\t\t\t\t\ttarget_map[key + '-' + j].punch_tag = data.punch_tag;\n\t\t\t\t\t\t\ttarget_map[key + '-' + j].override = data.override;\n\t\t\t\t\t\t\ttarget_map[key + '-' + j][data.date_stamp] = data;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else if ( !target_map[key + '-' + j][data.date_stamp] ) {\n\t\t\t\t\t\t\ttarget_map[key + '-' + j][data.date_stamp] = data;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tj = j + 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttarget_map[key][data.date_stamp] = data;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t}\n\n\tinitInsideEditorData( updateExistedCell ) {\n\t\tvar $this = this;\n\t\tfor ( var key in this.day_dic ) {\n\t\t\tthis.$( '#' + key + '_date' ).html( this.day_dic[key].value );\n\t\t\tthis.$( '#' + key + '_date' ).addClass( 'manual_grid_day_' + Global/* Global.strToDate */.x.strToDate( this.day_dic[key].field ).format( this.full_format ) );\n\t\t\tthis.$( '#' + key + '_date' ).attr( 'current_date', 'manual_grid_day_' + Global/* Global.strToDate */.x.strToDate( this.day_dic[key].field ).format( this.full_format ) );\n\t\t\tthis.$( '#' + key + '_date' ).unbind( 'click' ).bind( 'click', function( e ) {\n\t\t\t\tvar target = e.currentTarget;\n\t\t\t\tvar field = TimeSheetViewController_$( target ).attr( 'current_date' );\n\t\t\t\tfield = field.substring( 16, field.length );\n\t\t\t\tvar date = Global/* Global.strToDate */.x.strToDate( field, $this.full_format );\n\t\t\t\tif ( date && date.getYear() > 0 ) {\n\t\t\t\t\t$this.setDatePickerValue( date.format( Global/* Global.getLoginUserDateFormat */.x.getLoginUserDateFormat() ) );\n\t\t\t\t\t$this.highLightSelectDay();\n\t\t\t\t\t$this.reLoadSubGridsSource();\n\t\t\t\t}\n\t\t\t} );\n\t\t\tthis.$( '.is-saving-manual-grid' ).removeClass( 'is-saving-manual-grid' );\n\t\t}\n\t\tif ( this.is_auto_switch ) {\n\t\t\tthis.is_auto_switch = false;\n\t\t\tdoNext();\n\t\t} else {\n\t\t\tthis.getManualTimeSheetData( function() {\n\t\t\t\tdoNext();\n\t\t\t} );\n\t\t}\n\n\t\tfunction doNext() {\n\t\t\t$this.is_saving_manual_grid = false;\n\t\t\t$this.setDefaultMenu();\n\t\t\tif ( !updateExistedCell ) {\n\t\t\t\t$this.editor.removeAllRows();\n\t\t\t\tif ( $this.manual_timesheet_data.length > 0 ) {\n\t\t\t\t\t$this.buildManualTimeSheetData();\n\t\t\t\t\t_.map( $this.time_sheet_data_overrode_false_map, function( data ) {\n\t\t\t\t\t\t$this.editor.addRow( data );\n\t\t\t\t\t} );\n\t\t\t\t\t_.map( $this.time_sheet_data_overrode_true_map, function( data ) {\n\t\t\t\t\t\t$this.editor.addRow( data );\n\t\t\t\t\t} );\n\t\t\t\t\tif ( _.isEmpty( $this.time_sheet_data_overrode_true_map ) ) {\n\t\t\t\t\t\t$this.editor.addRow();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t$this.editor.addRow();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ( $this.manual_timesheet_data.length > 0 ) {\n\t\t\t\t\t$this.buildManualTimeSheetData();\n\t\t\t\t\tfor ( var map_key in $this.time_sheet_data_overrode_true_map ) {\n\t\t\t\t\t\tvar data = $this.time_sheet_data_overrode_true_map[map_key];\n\t\t\t\t\t\tfor ( var map_key_2 in data ) {\n\t\t\t\t\t\t\tvar item = data[map_key_2];\n\t\t\t\t\t\t\tif ( Array.isArray( item ) || !_.isObject( item ) ) {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar key = $this.generateManualTimeSheetRecordKey( item );\n\t\t\t\t\t\t\tvar item_id_key = item.id + '-' + key;\n\n\t\t\t\t\t\t\t//Check to see if the record with no ID (pre-save) exists, and if so update it, or replace it with the saved record.\n\t\t\t\t\t\t\tif ( $this.manual_grid_records_map[item_id_key] ) {\n\t\t\t\t\t\t\t\t$this.manual_grid_records_map[item_id_key][item.date_stamp].setValue( item.total_time );\n\t\t\t\t\t\t\t} else if ( $this.manual_grid_records_map[key] ) {\n\t\t\t\t\t\t\t\t$this.manual_grid_records_map[key].current_edit_item[item.date_stamp] = item;\n\t\t\t\t\t\t\t\t$this.manual_grid_records_map[key][item.date_stamp].setValue( item.total_time );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( $this.save_manual_grid_after_save ) {\n\t\t\t\t$this.autoSaveManualPunch();\n\t\t\t\t$this.save_manual_grid_after_save = false;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tinsideEditorAddRow( data, index ) {\n\t\tvar $this = this;\n\t\tif ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) {\n\t\t\tvar job_item_api = TTAPI.APIJobItem;\n\t\t\tvar job_api = TTAPI.APIJob;\n\t\t\tvar punch_tag_api = TTAPI.APIPunchTag;\n\t\t\tvar department_api = TTAPI.APIDepartment;\n\t\t}\n\t\tvar args;\n\t\tif ( !data ) {\n\t\t\tdata = {};\n\t\t\tif ( index >= 0 ) {\n\t\t\t\tvar widget_row = this.rows_widgets_array[index - 3];\n\t\t\t\tif ( this.parent_controller.show_branch_ui ) {\n\t\t\t\t\tif ( widget_row.branch_id ) {\n\t\t\t\t\t\tdata.branch_id = widget_row.branch_id.getValue();\n\t\t\t\t\t} else if ( widget_row.current_edit_item && widget_row.current_edit_item.branch_id ) {\n\t\t\t\t\t\tdata.branch_id = widget_row.current_edit_item.branch_id;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdata.branch_id = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( this.parent_controller.show_department_ui ) {\n\t\t\t\t\tif ( widget_row.department_id ) {\n\t\t\t\t\t\tdata.department_id = widget_row.department_id.getValue();\n\t\t\t\t\t} else if ( widget_row.current_edit_item && widget_row.current_edit_item.department_id ) {\n\t\t\t\t\t\tdata.department_id = widget_row.current_edit_item.department_id;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdata.department_id = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( this.parent_controller.show_job_ui && Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) {\n\t\t\t\t\tif ( widget_row.job_id ) {\n\t\t\t\t\t\tdata.job_id = widget_row.job_id.getValue();\n\t\t\t\t\t} else if ( widget_row.current_edit_item && widget_row.current_edit_item.job_id ) {\n\t\t\t\t\t\tdata.job_id = widget_row.current_edit_item.job_id;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdata.job_id = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( this.parent_controller.show_job_item_ui && Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) {\n\t\t\t\t\tif ( widget_row.job_item_id ) {\n\t\t\t\t\t\tdata.job_item_id = widget_row.job_item_id.getValue();\n\t\t\t\t\t} else if ( widget_row.current_edit_item && widget_row.current_edit_item.job_item_id ) {\n\t\t\t\t\t\tdata.job_item_id = widget_row.current_edit_item.job_item_id;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdata.job_item_id = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( this.parent_controller.show_punch_tag_ui && Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) {\n\t\t\t\t\tif ( widget_row.punch_tag_id ) {\n\t\t\t\t\t\tdata.punch_tag_id = widget_row.punch_tag_id.getValue();\n\t\t\t\t\t} else if ( widget_row.current_edit_item && widget_row.current_edit_item.punch_tag_id ) {\n\t\t\t\t\t\tdata.punch_tag_id = widget_row.current_edit_item.punch_tag_id;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdata.punch_tag_id = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t\tvar row = this.getRowRender(); //Get Row render\n\t\tvar render = this.getRender(); //get render, should be a table\n\t\tvar widgets = {}; //Save each row's widgets\n\t\tvar form_item_input;\n\t\t//Build row widgets\n\t\t//Branch\n\t\tif ( this.parent_controller.show_branch_ui ) {\n\t\t\tif ( data.hasOwnProperty( 'override' ) && !data.override ) {\n\t\t\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT );\n\t\t\t\tform_item_input.TText( { field: 'branch' } );\n\t\t\t\tform_item_input.setValue( data.branch );\n\t\t\t\trow.children().eq( 2 ).append( form_item_input );\n\t\t\t} else {\n\t\t\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.AWESOME_BOX );\n\t\t\t\tform_item_input.AComboBox( {\n\t\t\t\t\tapi_class: TTAPI.APIBranch,\n\t\t\t\t\twidth: 90,\n\t\t\t\t\tlayout_name: 'global_branch',\n\t\t\t\t\tshow_search_inputs: true,\n\t\t\t\t\tset_empty: true,\n\t\t\t\t\tfield: 'branch_id',\n\t\t\t\t\tis_static_width: true\n\t\t\t\t} );\n\t\t\t\twidgets[form_item_input.getField()] = form_item_input;\n\t\t\t\targs = {};\n\t\t\t\targs.filter_data = { user_id: this.parent_controller.getSelectEmployee() };\n\t\t\t\tform_item_input.setDefaultArgs( args );\n\t\t\t\tvar branch_id = data.hasOwnProperty( 'branch_id' ) ? data.branch_id : this.parent_controller.getSelectEmployee( true ).default_branch_id;\n\t\t\t\tform_item_input.setValue( data.hasOwnProperty( 'branch_id' ) ? data.branch_id : this.parent_controller.getSelectEmployee( true ).default_branch_id );\n\t\t\t\trow.children().eq( 2 ).append( form_item_input );\n\t\t\t}\n\t\t} else {\n\t\t\trow.children().eq( 2 ).hide();\n\t\t}\n\t\t//Department\n\t\tif ( this.parent_controller.show_department_ui ) {\n\t\t\tif ( data.hasOwnProperty( 'override' ) && !data.override ) {\n\t\t\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT );\n\t\t\t\tform_item_input.TText( { field: 'department' } );\n\t\t\t\tform_item_input.setValue( data.department );\n\t\t\t\trow.children().eq( 3 ).append( form_item_input );\n\t\t\t} else {\n\t\t\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.AWESOME_BOX );\n\t\t\t\tform_item_input.AComboBox( {\n\t\t\t\t\tapi_class: TTAPI.APIDepartment,\n\t\t\t\t\twidth: 90,\n\t\t\t\t\tlayout_name: 'global_department',\n\t\t\t\t\tshow_search_inputs: true,\n\t\t\t\t\tset_empty: true,\n\t\t\t\t\tfield: 'department_id',\n\t\t\t\t\tis_static_width: true\n\t\t\t\t} );\n\t\t\t\twidgets[form_item_input.getField()] = form_item_input;\n\t\t\t\targs = {};\n\t\t\t\targs.filter_data = { user_id: this.parent_controller.getSelectEmployee(), branch_id: branch_id };\n\t\t\t\tform_item_input.setDefaultArgs( args );\n\t\t\t\tvar department_id = data.hasOwnProperty( 'department_id' ) ? data.department_id : this.parent_controller.getSelectEmployee( true ).default_department_id;\n\t\t\t\tform_item_input.setValue( data.hasOwnProperty( 'department_id' ) ? data.department_id : this.parent_controller.getSelectEmployee( true ).default_department_id );\n\t\t\t\trow.children().eq( 3 ).append( form_item_input );\n\t\t\t}\n\t\t} else {\n\t\t\trow.children().eq( 3 ).hide();\n\t\t}\n\t\t//Job\n\t\tif ( this.parent_controller.show_job_ui && Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) {\n\t\t\tif ( data.hasOwnProperty( 'override' ) && !data.override ) {\n\t\t\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT );\n\t\t\t\tform_item_input.TText( { field: 'job' } );\n\t\t\t\tform_item_input.setValue( data.job );\n\t\t\t\trow.children().eq( 4 ).append( form_item_input );\n\t\t\t} else {\n\t\t\t\tvar job_form_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.AWESOME_BOX );\n\t\t\t\tjob_form_item_input.AComboBox( {\n\t\t\t\t\tapi_class: TTAPI.APIJob,\n\t\t\t\t\twidth: 90,\n\t\t\t\t\tlayout_name: 'global_job',\n\t\t\t\t\tshow_search_inputs: true,\n\t\t\t\t\tset_empty: true,\n\t\t\t\t\talways_include_columns: ['group_id'],\n\t\t\t\t\tfield: 'job_id',\n\t\t\t\t\tis_static_width: true,\n\t\t\t\t\tsetRealValueCallBack: ( function( val ) {\n\t\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\t\tjob_coder.setValue( val.manual_id );\n\t\t\t\t\t\t}\n\t\t\t\t\t} )\n\t\t\t\t} );\n\t\t\t\twidgets[job_form_item_input.getField()] = job_form_item_input;\n\t\t\t\t// Set default args\n\t\t\t\targs = {};\n\t\t\t\targs.filter_data = { status_id: 10, user_id: this.parent_controller.getSelectEmployee() };\n\t\t\t\tjob_form_item_input.setDefaultArgs( args );\n\t\t\t\tvar job_id = data.hasOwnProperty( 'job_id' ) ? data.job_id : this.parent_controller.getSelectEmployee( true ).default_job_id;\n\t\t\t\tjob_form_item_input.setValue( job_id );\n\t\t\t\tvar job_coder = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT_INPUT );\n\t\t\t\tjob_coder.TTextInput( { field: 'job_quick_search', disable_keyup_event: true, width: 30 } );\n\t\t\t\tjob_coder.css( 'display', 'inline-block' );\n\t\t\t\tjob_form_item_input.css( 'display', 'inline-block' );\n\t\t\t\trow.children().eq( 4 ).append( job_coder );\n\t\t\t\trow.children().eq( 4 ).append( job_form_item_input );\n\t\t\t\tjob_coder.unbind( 'formItemChange' ).bind( 'formItemChange', function( e, target ) {\n\t\t\t\t\tonJobQuickSearch( target.getField(), target.getValue() );\n\t\t\t\t} );\n\t\t\t}\n\t\t} else {\n\t\t\trow.children().eq( 4 ).hide();\n\t\t}\n\n\t\t//Task\n\t\tif ( this.parent_controller.show_job_item_ui && Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) {\n\t\t\tif ( data.hasOwnProperty( 'override' ) && !data.override ) {\n\t\t\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT );\n\t\t\t\tform_item_input.TText( { field: 'job_item' } );\n\t\t\t\tform_item_input.setValue( data.job_item );\n\t\t\t\trow.children().eq( 5 ).append( form_item_input );\n\t\t\t} else {\n\t\t\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.AWESOME_BOX );\n\t\t\t\tform_item_input.AComboBox( {\n\t\t\t\t\tapi_class: TTAPI.APIJobItem,\n\t\t\t\t\twidth: 90,\n\t\t\t\t\tlayout_name: 'global_job_item',\n\t\t\t\t\tshow_search_inputs: true,\n\t\t\t\t\tset_empty: true,\n\t\t\t\t\talways_include_columns: ['group_id'],\n\t\t\t\t\tfield: 'job_item_id',\n\t\t\t\t\tis_static_width: true,\n\t\t\t\t\tsetRealValueCallBack: ( function( val ) {\n\t\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\t\tjob_item_coder.setValue( val.manual_id );\n\t\t\t\t\t\t}\n\t\t\t\t\t} )\n\t\t\t\t} );\n\t\t\t\targs = {};\n\t\t\t\targs.filter_data = { status_id: 10, job_id: job_id };\n\t\t\t\tform_item_input.setDefaultArgs( args );\n\t\t\t\tvar job_item_id = data.hasOwnProperty( 'job_item_id' ) ? data.job_item_id : this.parent_controller.getSelectEmployee( true ).default_job_item_id;\n\t\t\t\tform_item_input.setValue( data.hasOwnProperty( 'job_item_id' ) ? data.job_item_id : this.parent_controller.getSelectEmployee( true ).default_job_item_id );\n\t\t\t\tvar job_item_coder = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT_INPUT );\n\t\t\t\tjob_item_coder.TTextInput( { field: 'job_item_quick_search', disable_keyup_event: true, width: 30 } );\n\t\t\t\twidgets[form_item_input.getField()] = form_item_input;\n\t\t\t\tjob_item_coder.css( 'display', 'inline-block' );\n\t\t\t\tform_item_input.css( 'display', 'inline-block' );\n\t\t\t\trow.children().eq( 5 ).append( job_item_coder );\n\t\t\t\trow.children().eq( 5 ).append( form_item_input );\n\t\t\t\tjob_item_coder.unbind( 'formItemChange' ).bind( 'formItemChange', function( e, target ) {\n\t\t\t\t\tonJobQuickSearch( target.getField(), target.getValue() );\n\t\t\t\t} );\n\t\t\t}\n\t\t} else {\n\t\t\trow.children().eq( 5 ).hide();\n\t\t}\n\n\t\t//Punch Tag\n\t\tif ( this.parent_controller.show_punch_tag_ui && Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) {\n\t\t\tif ( data.hasOwnProperty( 'override' ) && !data.override ) {\n\t\t\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT );\n\t\t\t\tform_item_input.TText( { field: 'punch_tag' } );\n\t\t\t\tform_item_input.setValue( data.punch_tag );\n\t\t\t\trow.children().eq( 6 ).append( form_item_input );\n\t\t\t} else {\n\t\t\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.AWESOME_BOX );\n\t\t\t\tform_item_input.AComboBox( {\n\t\t\t\t\tapi_class: TTAPI.APIPunchTag,\n\t\t\t\t\tallow_multiple_selection: true,\n\t\t\t\t\twidth: 90,\n\t\t\t\t\tlayout_name: 'global_punch_tag',\n\t\t\t\t\tshow_search_inputs: true,\n\t\t\t\t\tset_empty: true,\n\t\t\t\t\talways_include_columns: ['group_id'],\n\t\t\t\t\tfield: 'punch_tag_id',\n\t\t\t\t\tis_static_width: true\n/*\t\t\t\t\tsetRealValueCallBack: ( function( val ) {\n\t\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\t\tpunch_tag_coder.setValue( val.manual_id );\n\t\t\t\t\t\t}\n\t\t\t\t\t} )*/\n\t\t\t\t} );\n\t\t\t\targs = {};\n\t\t\t\targs.filter_data = {\n\t\t\t\t\tstatus_id: 10,\n\t\t\t\t\tuser_id: this.parent_controller.getSelectEmployee( true ).id,\n\t\t\t\t\tbranch_id: branch_id,\n\t\t\t\t\tdepartment_id: department_id,\n\t\t\t\t\tjob_id: job_id,\n\t\t\t\t\tjob_item_id: job_item_id\n\t\t\t\t};\n\t\t\t\tform_item_input.setDefaultArgs( args );\n\t\t\t\tform_item_input.setValue( data.hasOwnProperty( 'punch_tag_id' ) ? data.punch_tag_id : this.parent_controller.getSelectEmployee( true ).default_punch_tag_id );\n\t\t\t\t//var punch_tag_coder = Global.loadWidgetByName( FormItemType.TEXT_INPUT );\n\t\t\t\t//punch_tag_coder.TTextInput( { field: 'punch_tag_quick_search', disable_keyup_event: true, width: 30 } );\n\t\t\t\twidgets[form_item_input.getField()] = form_item_input;\n\t\t\t\t//punch_tag_coder.css( 'display', 'inline-block' );\n\t\t\t\tform_item_input.css( 'display', 'inline-block' );\n\t\t\t\t//row.children().eq( 6 ).append( punch_tag_coder );\n\t\t\t\trow.children().eq( 6 ).append( form_item_input );\n/*\t\t\t\tpunch_tag_coder.unbind( 'formItemChange' ).bind( 'formItemChange', function( e, target ) {\n\t\t\t\t\tonPunchTagQuickSearch( target.getField(), target.getValue() );\n\t\t\t\t} );*/\n\t\t\t}\n\t\t} else {\n\t\t\trow.children().eq( 6 ).hide();\n\t\t}\n\n\t\t//day 0\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT_INPUT );\n\t\tform_item_input.TTextInput( {\n\t\t\tfield: this.parent_controller.day_dic['day_0'].field,\n\t\t\twidth: 55,\n\t\t\tmode: 'time_unit',\n\t\t\tdisplay_na: false,\n\t\t\tneed_parser_sec: true,\n\t\t\tdo_validate: false\n\t\t} );\n\t\tform_item_input.setValue( data[form_item_input.getField()] ? data[form_item_input.getField()].total_time : 0 );\n\t\twidgets[form_item_input.getField()] = form_item_input;\n\t\trow.children().eq( 7 ).append( form_item_input );\n\n\t\t//day 1\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT_INPUT );\n\t\tform_item_input.TTextInput( {\n\t\t\tfield: this.parent_controller.day_dic['day_1'].field,\n\t\t\twidth: 55,\n\t\t\tmode: 'time_unit',\n\t\t\tdisplay_na: false,\n\t\t\tneed_parser_sec: true,\n\t\t\tdo_validate: false\n\t\t} );\n\t\tform_item_input.setValue( data[form_item_input.getField()] ? data[form_item_input.getField()].total_time : 0 );\n\t\twidgets[form_item_input.getField()] = form_item_input;\n\t\trow.children().eq( 8 ).append( form_item_input );\n\n\t\t//day 2\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT_INPUT );\n\t\tform_item_input.TTextInput( {\n\t\t\tfield: this.parent_controller.day_dic['day_2'].field,\n\t\t\twidth: 55,\n\t\t\tmode: 'time_unit',\n\t\t\tdisplay_na: false,\n\t\t\tneed_parser_sec: true,\n\t\t\tdo_validate: false\n\t\t} );\n\t\tform_item_input.setValue( data[form_item_input.getField()] ? data[form_item_input.getField()].total_time : 0 );\n\t\twidgets[form_item_input.getField()] = form_item_input;\n\t\trow.children().eq( 9 ).append( form_item_input );\n\n\t\t//day 3\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT_INPUT );\n\t\tform_item_input.TTextInput( {\n\t\t\tfield: this.parent_controller.day_dic['day_3'].field,\n\t\t\twidth: 55,\n\t\t\tmode: 'time_unit',\n\t\t\tdisplay_na: false,\n\t\t\tneed_parser_sec: true,\n\t\t\tdo_validate: false\n\t\t} );\n\t\tform_item_input.setValue( data[form_item_input.getField()] ? data[form_item_input.getField()].total_time : 0 );\n\t\twidgets[form_item_input.getField()] = form_item_input;\n\t\trow.children().eq( 10 ).append( form_item_input );\n\n\t\t//day 4\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT_INPUT );\n\t\tform_item_input.TTextInput( {\n\t\t\tfield: this.parent_controller.day_dic['day_4'].field,\n\t\t\twidth: 55,\n\t\t\tmode: 'time_unit',\n\t\t\tdisplay_na: false,\n\t\t\tneed_parser_sec: true,\n\t\t\tdo_validate: false\n\t\t} );\n\t\tform_item_input.setValue( data[form_item_input.getField()] ? data[form_item_input.getField()].total_time : 0 );\n\t\twidgets[form_item_input.getField()] = form_item_input;\n\t\trow.children().eq( 11 ).append( form_item_input );\n\n\t\t//day 5\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT_INPUT );\n\t\tform_item_input.TTextInput( {\n\t\t\tfield: this.parent_controller.day_dic['day_5'].field,\n\t\t\twidth: 55,\n\t\t\tmode: 'time_unit',\n\t\t\tdisplay_na: false,\n\t\t\tneed_parser_sec: true,\n\t\t\tdo_validate: false\n\t\t} );\n\t\tform_item_input.setValue( data[form_item_input.getField()] ? data[form_item_input.getField()].total_time : 0 );\n\t\twidgets[form_item_input.getField()] = form_item_input;\n\t\trow.children().eq( 12 ).append( form_item_input );\n\n\t\t//day 6\n\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT_INPUT );\n\t\tform_item_input.TTextInput( {\n\t\t\tfield: this.parent_controller.day_dic['day_6'].field,\n\t\t\twidth: 55,\n\t\t\tmode: 'time_unit',\n\t\t\tdisplay_na: false,\n\t\t\tneed_parser_sec: true,\n\t\t\tdo_validate: false\n\t\t} );\n\t\tform_item_input.setValue( data[form_item_input.getField()] ? data[form_item_input.getField()].total_time : 0 );\n\t\twidgets[form_item_input.getField()] = form_item_input;\n\t\trow.children().eq( 13 ).append( form_item_input );\n\t\tif ( data.hasOwnProperty( 'override' ) && !data.override ) {\n\t\t\trow.children().eq( 1 ).children().hide();\n\t\t}\n\n\t\tvar disable_plus = false;\n\t\tvar disable_minus = false;\n\t\tvar disable_dropdowns = false;\n\n\t\tfor ( var key in widgets ) {\n\t\t\tvar item = widgets[key];\n\n\t\t\t//disable if all pay_periods visible are not open.\n\t\t\tvar invalid = 0;\n\n\t\t\tfor ( var n in this.parent_controller.full_timesheet_data.pay_period_data ) {\n\t\t\t\tif ( this.parent_controller.full_timesheet_data.pay_period_data[n].status_id != 10 && this.parent_controller.full_timesheet_data.pay_period_data[n].status_id != 30 ) {\n\t\t\t\t\tinvalid++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( invalid > 0 && invalid == Object.keys( this.parent_controller.full_timesheet_data.pay_period_data ).length ) {\n\t\t\t\tif ( this.parent_controller.full_timesheet_data.punch_data.length != 0 ) {\n\t\t\t\t\tdisable_plus = true;\n\t\t\t\t\tdisable_minus = true;\n\t\t\t\t\tif ( Object.keys( data ).length == 0 ) {\n\t\t\t\t\t\treturn; //don't show a blank row if all pay periods are closed\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//disable fields under closed pay periods\n\t\t\tif ( this.parent_controller.full_timesheet_data.pay_period_data[this.parent_controller.full_timesheet_data.timesheet_dates.pay_period_date_map[item.getField()]] ) {\n\t\t\t\tvar field_pay_period_status = parseInt( this.parent_controller.full_timesheet_data.pay_period_data[this.parent_controller.full_timesheet_data.timesheet_dates.pay_period_date_map[item.getField()]].status_id );\n\t\t\t\tif ( field_pay_period_status != 10 && field_pay_period_status != 30 ) {\n\t\t\t\t\titem.setEnabled && item.setEnabled( false );\n\t\t\t\t\tif ( item.getField() != 'branch_id' && item.getField() != 'department_id' && item.getField() != 'job_id' && item.getField() != 'job_item_id' && item.getField() != 'punch_tag_id' && typeof data[item.getField()] != 'undefined' ) {\n\t\t\t\t\t\t//only disable dropdowns if there is data in the disabled fields\n\t\t\t\t\t\tdisable_dropdowns = true;\n\t\t\t\t\t\tdisable_minus = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( data.hasOwnProperty( 'override' ) && !data.override ) {\n\t\t\t\titem.setEnabled && item.setEnabled( false );\n\t\t\t\titem.getValue() > 0 && item.hasClass( 't-text-input' ) >= 0 && item.css( 'color', 'red' );\n\t\t\t}\n\t\t\titem.unbind( 'formItemChange' ).bind( 'formItemChange', function( e, target ) {\n\t\t\t\ttarget.is_changed = true;\n\t\t\t\tif ( target.getField() === 'job_id' ) {\n\t\t\t\t\twidgets.is_changed = true;\n\t\t\t\t\tjob_coder.setValue( target.getValue( true ) ? ( target.getValue( true ).manual_id ? target.getValue( true ).manual_id : '' ) : '' );\n\t\t\t\t\tsetJobItemValueWhenJobChanged( target.getValue( true ) );\n\t\t\t\t\tsetPunchTagValuesWhenCriteriaChanged( data );\n\t\t\t\t} else if ( target.getField() === 'job_item_id' ) {\n\t\t\t\t\twidgets.is_changed = true;\n\t\t\t\t\tjob_item_coder.setValue( target.getValue( true ) ? ( target.getValue( true ).manual_id ? target.getValue( true ).manual_id : '' ) : '' );\n\t\t\t\t\tsetPunchTagValuesWhenCriteriaChanged( data );\n\t\t\t\t} else if ( target.getField() === 'branch_id' ) {\n\t\t\t\t\twidgets.is_changed = true;\n\t\t\t\t\tif ( ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ) {\n\t\t\t\t\t\tsetDepartmentValueWhenBranchChanged( data );\n\t\t\t\t\t}\n\t\t\t\t} else if ( target.getField() === 'department_id' ) {\n\t\t\t\t\twidgets.is_changed = true;\n\t\t\t\t} else if ( target.getField() === 'punch_tag_id' ) {\n\t\t\t\t\twidgets.is_changed = true;\n\t\t\t\t}\n\t\t\t\t$this.parent_controller.autoSaveManualPunch();\n\t\t\t} );\n\t\t}\n\n\t\tif ( disable_dropdowns ) {\n\t\t\tfor ( var key in widgets ) {\n\t\t\t\tvar item = widgets[key];\n\t\t\t\tif ( item.getField() == 'branch_id' || item.getField() == 'department_id' || item.getField() == 'job_id' || item.getField() == 'job_item_id' ) {\n\t\t\t\t\tif ( item.getField() == 'job_id' || item.getField() == 'job_item_id' || item.getField() == 'punch_tag_id' ) {\n\t\t\t\t\t\titem.parents( 'td' ).find( 'input[type=\"text\"]' ).hide(); //hide job and task lookup box\n\t\t\t\t\t}\n\t\t\t\t\titem.setEnabled && item.setEnabled( false );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( disable_plus == true ) {\n\t\t\trow.find( '.plus-icon' ).hide();\n\t\t}\n\n\t\tif ( disable_minus == true ) {\n\t\t\trow.find( '.minus-icon' ).hide();\n\t\t}\n\n\t\tif ( typeof index != 'undefined' ) {\n\t\t\trow.insertAfter( TimeSheetViewController_$( render ).find( 'tr' ).eq( index ) );\n\t\t\tthis.rows_widgets_array.splice( ( index ), 0, widgets );\n\n\t\t} else {\n\t\t\tTimeSheetViewController_$( render ).append( row );\n\t\t\tthis.rows_widgets_array.push( widgets );\n\t\t}\n\t\t//Save current set item\n\t\twidgets.current_edit_item = data;\n\t\tthis.addIconsEvent( row ); //Bind event to add and minus icon\n\n\t\tfunction onJobQuickSearch( key, value ) {\n\t\t\tvar args = {};\n\t\t\tif ( key === 'job_quick_search' ) {\n\t\t\t\targs.filter_data = {\n\t\t\t\t\tmanual_id: value,\n\t\t\t\t\tuser_id: $this.parent_controller.getSelectEmployee(),\n\t\t\t\t\tstatus_id: '10'\n\t\t\t\t};\n\t\t\t\tjob_api.getJob( args, {\n\t\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t\tvar result_data = result.getResult();\n\t\t\t\t\t\twidgets.is_changed = true;\n\t\t\t\t\t\t$this.parent_controller.autoSaveManualPunch();\n\t\t\t\t\t\tif ( result_data.length > 0 ) {\n\t\t\t\t\t\t\twidgets['job_id'].setValue( result_data[0].id );\n\t\t\t\t\t\t\tsetJobItemValueWhenJobChanged( result_data[0] );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\twidgets['job_id'].setValue( '' );\n\t\t\t\t\t\t\tsetJobItemValueWhenJobChanged( false );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t} else if ( key === 'job_item_quick_search' ) {\n\t\t\t\targs.filter_data = { manual_id: value, job_id: widgets['job_id'].getValue(), status_id: '10' };\n\t\t\t\tjob_item_api.getJobItem( args, {\n\t\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t\tvar result_data = result.getResult();\n\t\t\t\t\t\twidgets.is_changed = true;\n\t\t\t\t\t\t$this.parent_controller.autoSaveManualPunch();\n\t\t\t\t\t\tif ( result_data.length > 0 ) {\n\t\t\t\t\t\t\twidgets['job_item_id'].setValue( result_data[0].id );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\twidgets['job_item_id'].setValue( '' );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\n\t\tfunction setJobItemValueWhenJobChanged( job ) {\n\t\t\tvar job_item_widget = widgets['job_item_id'];\n\t\t\tif ( !job_item_widget ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar current_job_item_id = job_item_widget.getValue();\n\t\t\tjob_item_widget.setSourceData( null );\n\t\t\tvar args = {};\n\t\t\targs.filter_data = { status_id: 10, job_id: widgets['job_id'].getValue() };\n\t\t\tjob_item_widget.setDefaultArgs( args );\n\t\t\tif ( current_job_item_id ) {\n\t\t\t\tvar new_arg = Global/* Global.clone */.x.clone( args );\n\t\t\t\tnew_arg.filter_data.id = current_job_item_id;\n\t\t\t\tnew_arg.filter_columns = job_item_widget.getColumnFilter();\n\t\t\t\tjob_item_api.getJobItem( new_arg, {\n\t\t\t\t\tonResult: function( task_result ) {\n\t\t\t\t\t\tvar data = task_result.getResult();\n\t\t\t\t\t\tif ( data.length > 0 ) {\n\t\t\t\t\t\t\tjob_item_widget.setValue( current_job_item_id );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsetDefaultData();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t} else {\n\t\t\t\tsetDefaultData();\n\t\t\t}\n\n\t\t\tfunction setDefaultData() {\n\t\t\t\tif ( widgets['job_id'].getValue() ) {\n\t\t\t\t\tjob_item_widget.setValue( job.default_item_id );\n\t\t\t\t\tif ( job.default_item_id === false || job.default_item_id === 0 ) {\n\t\t\t\t\t\tjob_item_coder.setValue( '' );\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tjob_item_widget.setValue( '' );\n\t\t\t\t\tjob_item_coder.setValue( '' );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfunction setDepartmentValueWhenBranchChanged() {\n\t\t\tvar department_widget = widgets['department_id'];\n\t\t\tif ( !department_widget ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdepartment_widget.setSourceData( null );\n\t\t\tvar args = {};\n\t\t\targs.filter_data = {\n\t\t\t\tuser_id: $this.parent_controller.getSelectEmployee( true ).id,\n\t\t\t\tbranch_id: widgets['branch_id'].getValue()\n\t\t\t};\n\t\t\tvar current_department_id = department_widget.getValue();\n\t\t\tdepartment_widget.setDefaultArgs( args );\n\n\t\t\tif ( current_department_id ) {\n\t\t\t\tvar new_arg = Global/* Global.clone */.x.clone( args );\n\n\t\t\t\tnew_arg.filter_columns = department_widget.getColumnFilter();\n\t\t\t\tdepartment_api.getDepartment( new_arg, {\n\t\t\t\t\tonResult: function( department_result ) {\n\n\t\t\t\t\t\tvar data = department_result.getResult();\n\n\t\t\t\t\t\tif ( data.length > 0 && data.some( department => department.id === current_department_id ) ) {\n\t\t\t\t\t\t\tdepartment_widget.setValue( current_department_id );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsetDefaultData();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t} else {\n\t\t\t\tsetDefaultData();\n\t\t\t}\n\n\t\t\tfunction setDefaultData() {\n\t\t\t\tdepartment_widget.setValue( '' );\n\t\t\t}\n\t\t}\n\n\t\tfunction setPunchTagValuesWhenCriteriaChanged() {\n\t\t\tif ( ( Global/* Global.getProductEdition */.x.getProductEdition() <= 15 ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar punch_tag_widget = widgets['punch_tag_id'];\n\t\t\tif ( !punch_tag_widget ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar current_punch_tag_ids = punch_tag_widget.getValue();\n\t\t\tpunch_tag_widget.setSourceData( null );\n\t\t\tvar args = {};\n\t\t\targs.filter_data = {\n\t\t\t\tstatus_id: 10,\n\t\t\t\tuser_id: $this.parent_controller.getSelectEmployee( true ).id,\n\t\t\t\tbranch_id: widgets['branch_id'] ? widgets['branch_id'].getValue() : TTUUID/* TTUUID.zero_id */.d.zero_id,\n\t\t\t\tdepartment_id: widgets['department_id'] ? widgets['department_id'].getValue() : TTUUID/* TTUUID.zero_id */.d.zero_id,\n\t\t\t\tjob_id: widgets['job_id'] ? widgets['job_id'].getValue() : TTUUID/* TTUUID.zero_id */.d.zero_id,\n\t\t\t\tjob_item_id: widgets['job_item_id'] ? widgets['job_item_id'].getValue() : TTUUID/* TTUUID.zero_id */.d.zero_id\n\t\t\t};\n\t\t\tpunch_tag_widget.setDefaultArgs( args );\n\n\t\t\tif ( current_punch_tag_ids && current_punch_tag_ids.length > 0 ) {\n\t\t\t\tvar new_arg = Global/* Global.clone */.x.clone( args );\n\n\t\t\t\tnew_arg.manual_id = current_punch_tag_ids;\n\t\t\t\tpunch_tag_api.getPunchTag( new_arg, {\n\t\t\t\t\tonResult: function( punch_tag_result ) {\n\t\t\t\t\t\tvar data = punch_tag_result.getResult();\n\n\t\t\t\t\t\tif ( data.length > 0 ) {\n\t\t\t\t\t\t\tif ( current_punch_tag_ids !== TTUUID/* TTUUID.zero_id */.d.zero_id && current_punch_tag_ids.length > 0 && shouldUpdatePunchTags( current_punch_tag_ids, data ) ) {\n\t\t\t\t\t\t\t\t//Compare current selected punch tags and the list of punch tags from the API and remove invalid punch tags.\n\t\t\t\t\t\t\t\tvar intersected_values = current_punch_tag_ids.filter( punch_tag_id => data.some( punch_tag => punch_tag_id === punch_tag.id ) );\n\t\t\t\t\t\t\t\tpunch_tag_widget.setValue( intersected_values );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsetDefaultData();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t} else {\n\t\t\t\tsetDefaultData();\n\t\t\t}\n\n\t\t\tfunction setDefaultData() {\n\t\t\t\tpunch_tag_widget.setValue( '' );\n\t\t\t}\n\t\t}\n\n\t\tfunction shouldUpdatePunchTags( current_punch_tag_ids, data ) {\n\t\t\t//If the data returned from the API does not contain every currently selected punch tag then we need to remove invalid tags.\n\t\t\tif ( current_punch_tag_ids.every( punch_tag_id => data.some( punch_tag => punch_tag.id === punch_tag_id ) ) === false ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\t//In the scenario where the user does not have permission to edit punch branch, department, job, job item and punch tag. (All of them)\n\t\t//Then the minus icon should not be centered as the <td> is too large and it looks out of place.\n\t\tif ( this.parent_controller.getPunchMode() === 'manual' ) {\n\t\t\tif ( this.parent_controller.timesheet_columns.length === 9 ) { // Plus and Minus icon + 7 days of the week.\n\t\t\t\tvar control_icons = document.querySelectorAll( '.control-icon' );\n\n\t\t\t\tfor ( var control_icon of control_icons ) {\n\t\t\t\t\tcontrol_icon.style.textAlign = 'left';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tautoSaveManualPunch() {\n\t\tvar $this = this;\n\t\tif ( this.is_saving_manual_grid ) {\n\t\t\tthis.save_manual_grid_after_save = true;\n\t\t\treturn;\n\t\t}\n\t\tthis.wait_auto_save && clearTimeout( this.wait_auto_save );\n\t\tthis.wait_auto_save = setTimeout( function() {\n\t\t\tif ( $this.getPunchMode() === 'manual' ) {\n\t\t\t\tProgressBar.showOverlay();\n\t\t\t\t$this.onSaveClick();\n\t\t\t}\n\t\t}, 2000 );\n\t}\n\n\tinsideEditorGetValue( isSave ) {\n\t\tvar len = this.rows_widgets_array.length;\n\t\tvar result = [];\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar row = this.rows_widgets_array[i];\n\t\t\tfor ( var j = 0; j < 7; j++ ) {\n\t\t\t\tvar current_date = new Date( new Date( this.parent_controller.start_date.getTime() ).setDate( this.parent_controller.start_date.getDate() + j ) );\n\t\t\t\tvar field = current_date.format();\n\t\t\t\tvar common_record = {};\n\t\t\t\tif ( !row[field] ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tcommon_record.total_time = row[field].getValue();\n\t\t\t\tif ( row[field].is_changed || ( row.is_changed && row.current_edit_item[field] ) ) {\n\t\t\t\t\trow.branch_id && ( common_record.branch_id = row.branch_id.getValue() );\n\t\t\t\t\trow.department_id && ( common_record.department_id = row.department_id.getValue() );\n\t\t\t\t\trow.job_id && ( common_record.job_id = row.job_id.getValue() );\n\t\t\t\t\trow.job_item_id && ( common_record.job_item_id = row.job_item_id.getValue() );\n\t\t\t\t\trow.punch_tag_id && ( common_record.punch_tag_id = row.punch_tag_id.getValue() );\n\t\t\t\t\tcommon_record.date_stamp = field;\n\t\t\t\t\tcommon_record.user_id = this.parent_controller.getSelectEmployee();\n\t\t\t\t\tcommon_record.object_type_id = 10;\n\t\t\t\t\tcommon_record.override = true;\n\t\t\t\t\tcommon_record.row = row;\n\t\t\t\t\trow.current_edit_item[field] && ( common_record.id = row.current_edit_item[field].id );\n\t\t\t\t\tresult.push( common_record );\n\t\t\t\t\tif ( isSave ) {\n\t\t\t\t\t\trow[field].is_changed = false;\n\t\t\t\t\t\trow[field].addClass( 'is-saving-manual-grid' );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( isSave ) {\n\t\t\t\trow.is_changed = false;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tinsideEditorRemoveRow( row ) {\n\t\tvar $this = this;\n\t\tvar index = row[0].rowIndex - 3;\n\t\tvar widget_row = this.rows_widgets_array[index];\n\t\tvar has_value = false;\n\t\tfor ( var j = 0; j < 7; j++ ) {\n\t\t\tvar current_date = new Date( new Date( this.parent_controller.start_date.getTime() ).setDate( this.parent_controller.start_date.getDate() + j ) );\n\t\t\tvar field = current_date.format();\n\t\t\tif ( widget_row[field].getValue() > 0 || widget_row.current_edit_item[field] ) {\n\t\t\t\thas_value = true;\n\t\t\t\tTAlertManager.showConfirmAlert( TimeSheetViewController_$.i18n._( 'You are about to delete the entire week worth of time for this row. Are you sure you wish to continue?' ), '', doNext );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t!has_value && doNext( true );\n\n\t\tfunction doNext( flag ) {\n\t\t\tif ( flag ) {\n\t\t\t\tvar remove_ids = [];\n\t\t\t\tfor ( var j = 0; j < 7; j++ ) {\n\t\t\t\t\tvar current_date = new Date( new Date( $this.parent_controller.start_date.getTime() ).setDate( $this.parent_controller.start_date.getDate() + j ) );\n\t\t\t\t\tvar field = current_date.format();\n\t\t\t\t\twidget_row.current_edit_item[field] && ( remove_ids.push( widget_row.current_edit_item[field].id ) );\n\t\t\t\t}\n\t\t\t\tif ( remove_ids.length > 0 ) {\n\t\t\t\t\tProgressBar.noProgressForNextCall();\n\t\t\t\t\tProgressBar.showNanobar();\n\t\t\t\t\t$this.is_saving_manual_grid = true;\n\t\t\t\t\t$this.parent_controller.setDefaultMenu();\n\t\t\t\t\t$this.api.deleteUserDateTotal( remove_ids, {\n\t\t\t\t\t\tonResult: function() {\n\t\t\t\t\t\t\t$this.parent_controller.reLoadSubGridsSource( true );\n\t\t\t\t\t\t\tProgressBar.removeNanobar();\n\t\t\t\t\t\t\t$this.parent_controller.setDefaultMenu();\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t\trow.remove();\n\t\t\t\t$this.rows_widgets_array.splice( index, 1 );\n\t\t\t\tif ( $this.rows_widgets_array.length === 0 ) {\n\t\t\t\t\t$this.addRow();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tbuildManualTimeSheetGrid() {\n\t\tvar args = {\n\t\t\tbranch: TimeSheetViewController_$.i18n._( 'Branch' ),\n\t\t\tdepartment: TimeSheetViewController_$.i18n._( 'Department' ),\n\t\t\tjob: TimeSheetViewController_$.i18n._( 'Job' ),\n\t\t\ttask: TimeSheetViewController_$.i18n._( 'Task' ),\n\t\t\tpunch_tag: TimeSheetViewController_$.i18n._( 'Tags' )\n\t\t};\n\n\t\tthis.editor = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.INSIDE_EDITOR );\n\t\tthis.editor.InsideEditor( {\n\t\t\ttitle: '',\n\t\t\taddRow: this.insideEditorAddRow,\n\t\t\tgetValue: this.insideEditorGetValue,\n\t\t\tsetValue: this.insideEditorSetValue,\n\t\t\tremoveRow: this.insideEditorRemoveRow,\n\t\t\tparent_controller: this,\n\t\t\trender: getRender(),\n\t\t\trender_args: args,\n\t\t\tapi: this.api_user_date_total,\n\t\t\trender_inline_html: true,\n\t\t\trow_render: getRowRender()\n\t\t} );\n\n\t\tfunction getRender() {\n\t\t\treturn `<table class=\"inside-editor-render grid-inside-editor-render\">\n\t\t\t\t\t\t<tr class=\"manual-timesheet-size-tr\">\n\t\t\t\t\t\t\t<td style=\"width: 25px\"></td>\n\t\t\t\t\t\t\t<td style=\"width: 25px\"></td>\n\t\t\t\t\t\t\t<td class=\"branch-header\" style=\"width: 120px\"></td>\n\t\t\t\t\t\t\t<td class=\"department-header\" style=\"width: 120px\"></td>\n\t\t\t\t\t\t\t<td class=\"job-header\" style=\"width: 120px\"></td>\n\t\t\t\t\t\t\t<td class=\"job-item-header\" style=\"width: 120px\"></td>\n\t\t\t\t\t\t\t<td class=\"punch-tag-header\" style=\"width: 120px\"></td>\n\t\t\t\t\t\t\t<td style=\"width: 50px\"></td>\n\t\t\t\t\t\t\t<td style=\"width: 50px\"></td>\n\t\t\t\t\t\t\t<td style=\"width: 50px\"></td>\n\t\t\t\t\t\t\t<td style=\"width: 50px\"></td>\n\t\t\t\t\t\t\t<td style=\"width: 50px\"></td>\n\t\t\t\t\t\t\t<td style=\"width: 50px\"></td>\n\t\t\t\t\t\t\t<td style=\"width: 50px\"></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"title\">\n\t\t\t\t\t\t\t<td></td>\n\t\t\t\t\t\t\t<td></td>\n\t\t\t\t\t\t\t<td class=\"branch-header\"><%= branch %></td>\n\t\t\t\t\t\t\t<td class=\"department-header\"><%= department %></td>\n\t\t\t\t\t\t\t<td class=\"job-header\"><%= job %></td>\n\t\t\t\t\t\t\t<td class=\"job-item-header\"><%= task %></td>\n\t\t\t\t\t\t\t<td class=\"punch-tag-header\"><%= punch_tag %></td>\n\t\t\t\t\t\t\t<td id=\"day_0_date\"></td>\n\t\t\t\t\t\t\t<td id=\"day_1_date\"></td>\n\t\t\t\t\t\t\t<td id=\"day_2_date\"></td>\n\t\t\t\t\t\t\t<td id=\"day_3_date\"></td>\n\t\t\t\t\t\t\t<td id=\"day_4_date\"></td>\n\t\t\t\t\t\t\t<td id=\"day_5_date\"></td>\n\t\t\t\t\t\t\t<td id=\"day_6_date\"></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</table>`;\n\t\t}\n\n\t\tfunction getRowRender() {\n\t\t\treturn `<tr class=\"inside-editor-row data-row\">\n\t\t\t\t\t\t<td class=\"cell control-icon\">\n\t\t\t\t\t\t\t<button class=\"plus-icon\" onclick=\"\"></button>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td class=\"cell control-icon\">\n\t\t\t\t\t\t\t<button class=\"minus-icon \" onclick=\"\"></button>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td class=\"branch \"></td>\n\t\t\t\t\t\t<td class=\"department \"></td>\n\t\t\t\t\t\t<td class=\"job \"></td>\n\t\t\t\t\t\t<td class=\"task \"></td>\n\t\t\t\t\t\t<td class=\"punch_tag \"></td>\n\t\t\t\t\t\t<td class=\"day-0 \"></td>\n\t\t\t\t\t\t<td class=\"day-1 \"></td>\n\t\t\t\t\t\t<td class=\"day-2 \"></td>\n\t\t\t\t\t\t<td class=\"day-3 \"></td>\n\t\t\t\t\t\t<td class=\"day-4 \"></td>\n\t\t\t\t\t\t<td class=\"day-5 \"></td>\n\t\t\t\t\t\t<td class=\"day-6 \"></td>\n\t\t\t\t\t</tr>`;\n\t\t}\n\n\t\tvar inside_editor_div = this.$( '.manual-timesheet-inside-editor-div' );\n\t\tinside_editor_div.append( this.editor );\n\t}\n\n\tbuildCalendars() {\n\t\tvar $this = this;\n\t\tif ( this.is_auto_switch ) {\n\t\t\tthis.getManualTimeSheetData( function() {\n\t\t\t\tif ( $this.manual_timesheet_data.length > 0 ) {\n\t\t\t\t\t$this.buildManualTimeSheetData();\n\t\t\t\t\tvar is_no_manual = _.isEmpty( $this.time_sheet_data_overrode_true_map );\n\t\t\t\t\tvar is_no_punch = _.isEmpty( $this.time_sheet_data_overrode_false_map );\n\t\t\t\t\tif ( is_no_manual && !is_no_punch && $this.toggle_button.getValue() !== 'manual' ) {\n\t\t\t\t\t\t$this.toggle_button.setValue( 'punch' );\n\t\t\t\t\t\t$this.is_auto_switch = false;\n\t\t\t\t\t} else if ( !is_no_manual && is_no_punch ) {\n\t\t\t\t\t\t$this.toggle_button.setValue( 'manual' );\n\t\t\t\t\t}\n\t\t\t\t\t$this.reSetURL();\n\t\t\t\t\tdoNext();\n\t\t\t\t} else {\n\t\t\t\t\t$this.getPunchMode() === 'punch' && ( $this.is_auto_switch = false );\n\t\t\t\t\tdoNext();\n\t\t\t\t}\n\t\t\t} );\n\t\t} else {\n\t\t\tdoNext();\n\t\t}\n\n\t\tfunction doNext() {\n\t\t\t$this.pay_period_data = $this.full_timesheet_data.pay_period_data;\n\t\t\t$this.pay_period_map = $this.full_timesheet_data.timesheet_dates.pay_period_date_map;\n\t\t\t$this.timesheet_verify_data = $this.full_timesheet_data.timesheet_verify_data;\n\t\t\t$this.grid_div = TimeSheetViewController_$( $this.el ).find( '.timesheet-grid-div' );\n\t\t\t// Punch grid\n\t\t\t$this.buildTimeSheetsColumns();\n\t\t\t$this.buildTimeSheetGrid();\n\t\t\tif ( $this.getPunchMode() === 'manual' ) {\n\t\t\t\t$this.$( '.timesheet-punch-grid-wrapper' ).hide();\n\t\t\t\t$this.$( '.manual-timesheet-inside-editor-div' ).show();\n\t\t\t\tif ( !$this.editor ) {\n\t\t\t\t\t$this.buildManualTimeSheetsColumns();\n\t\t\t\t\t$this.buildManualTimeSheetGrid();\n\t\t\t\t\t$this.initInsideEditorData();\n\t\t\t\t} else {\n\t\t\t\t\t$this.buildManualTimeSheetsColumns();\n\t\t\t\t\t$this.initInsideEditorData();\n\t\t\t\t}\n\t\t\t\tif ( !$this.show_job_ui || Global/* Global.getProductEdition */.x.getProductEdition() < 20 ) {\n\t\t\t\t\t$this.$( '.job-header' ).hide();\n\t\t\t\t}\n\t\t\t\tif ( !$this.show_job_item_ui || Global/* Global.getProductEdition */.x.getProductEdition() < 20 ) {\n\t\t\t\t\t$this.$( '.job-item-header' ).hide();\n\t\t\t\t}\n\t\t\t\tif ( !$this.show_punch_tag_ui || Global/* Global.getProductEdition */.x.getProductEdition() < 20 ) {\n\t\t\t\t\t$this.$( '.punch-tag-header' ).hide();\n\t\t\t\t}\n\t\t\t\tif ( !$this.show_branch_ui ) {\n\t\t\t\t\t$this.$( '.branch-header' ).hide();\n\t\t\t\t}\n\t\t\t\tif ( !$this.show_department_ui ) {\n\t\t\t\t\t$this.$( '.department-header' ).hide();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t$this.$( '.timesheet-punch-grid-wrapper' ).show();\n\t\t\t\t$this.$( '.manual-timesheet-inside-editor-div' ).hide();\n\t\t\t}\n\n\t\t\t$this.buildAccumulatedGrid();\n\n\t\t\t$this.buildSubGrid( 'branch_grid', 'Branch' );\n\t\t\t$this.buildSubGrid( 'department_grid', 'Department' );\n\t\t\t$this.buildSubGrid( 'job_grid', 'Job' );\n\t\t\t$this.buildSubGrid( 'job_item_grid', 'Task' );\n\t\t\t$this.buildSubGrid( 'punch_tag_grid', 'Tags' );\n\t\t\t$this.buildSubGrid( 'premium_grid', 'Premium' );\n\t\t\t$this.buildAbsenceGrid();\n\t\t\t$this.showGridBorders();\n\t\t\t$this.buildAccumulatedTotalGrid();\n\t\t\t$this.buildPunchNoteGrid();\n\t\t\t$this.buildVerificationGrid();\n\t\t\t//TimeSheet grid\n\t\t\t$this.buildTimeSheetSource(); //Create punch data\n\t\t\t$this.buildTimeSheetRequests();\n\t\t\t//Accumulated Time, Branch, Department, Job, Task, Pre\n\t\t\t$this.buildSubGridsSource();\n\t\t\t//Make sure exception rows goes after Lanuch and break create from buildSubGridsSource\n\t\t\t$this.buildTimeSheetExceptions();\n\t\t\t//Absence Grid source\n\t\t\t$this.buildAbsenceSource(); //Create punch data\n\t\t\t//Show punch notes in a grid\n\t\t\t$this.buildPunchNoteGridSource();\n\t\t\t//buildVerificationGridSource\n\t\t\t$this.buildVerificationGridSource();\n\t\t\t$this.setGridExpendButton( 'accumulated_time_grid', TimeSheetViewController_$.i18n._( 'Accumulated Time' ) );\n\t\t\t$this.setGridExpendButton( 'branch_grid', TimeSheetViewController_$.i18n._( 'Branch' ) );\n\t\t\t$this.setGridExpendButton( 'department_grid', TimeSheetViewController_$.i18n._( 'Department' ) );\n\t\t\t$this.setGridExpendButton( 'job_grid', TimeSheetViewController_$.i18n._( 'Job' ) );\n\t\t\t$this.setGridExpendButton( 'job_item_grid', TimeSheetViewController_$.i18n._( 'Task' ) );\n\t\t\t$this.setGridExpendButton( 'punch_tag_grid', TimeSheetViewController_$.i18n._( 'Tags' ) );\n\t\t\t$this.setGridExpendButton( 'premium_grid', TimeSheetViewController_$.i18n._( 'Premium' ) );\n\t\t\t$this.setGridExpendButton( 'absence_grid', TimeSheetViewController_$.i18n._( 'Absence' ) );\n\t\t\t$this.setGridExpendButton( 'punch_note_grid', TimeSheetViewController_$.i18n._( 'Punch Notes' ) );\n\n\t\t\tif ( $this.getPunchMode() === 'punch' ) {\n\t\t\t\t//var selection = $this.grid.getSelection(); //provides memory of selected cells\n\t\t\t\t$this.grid.setData( $this.timesheet_data_source, true );\n\t\t\t\t//$this.grid.setTimesheetSelection( selection ); //resets selection after refreshing grid data -- currently broken, see setTimesheetSelection() for details.\n\t\t\t}\n\n\t\t\tif ( typeof $this.accumulated_time_grid.setData == 'function' ) {\n\t\t\t\t$this.accumulated_time_grid.setData( $this.accumulated_time_source, false );\n\t\t\t}\n\n\t\t\tif ( typeof $this.branch_grid.setData == 'function' ) {\n\t\t\t\t$this.branch_grid.setData( $this.branch_source, false );\n\t\t\t}\n\n\t\t\tif ( typeof $this.department_grid.setData == 'function' ) {\n\t\t\t\t$this.department_grid.setData( $this.department_source, false );\n\t\t\t}\n\n\t\t\tif ( typeof $this.job_grid.setData == 'function' ) {\n\t\t\t\t$this.job_grid.setData( $this.job_source, false );\n\t\t\t}\n\n\t\t\tif ( typeof $this.job_item_grid.setData == 'function' ) {\n\t\t\t\t$this.job_item_grid.setData( $this.job_item_source, false );\n\t\t\t}\n\n\t\t\tif ( typeof $this.punch_tag_grid.setData == 'function' ) {\n\t\t\t\t$this.punch_tag_grid.setData( $this.punch_tag_source, false );\n\t\t\t}\n\n\t\t\tif ( typeof $this.premium_grid.setData == 'function' ) {\n\t\t\t\t$this.premium_grid.setData( $this.premium_source, false );\n\t\t\t}\n\n\t\t\tif ( $this.absence_grid ) {\n\t\t\t\t$this.absence_grid.setData( $this.absence_source, false );\n\t\t\t}\n\n\t\t\tif ( $this.accumulated_total_grid_source.length === 0 ) {\n\t\t\t\t$this.accumulated_total_grid_source.push();\n\t\t\t}\n\n\t\t\t$this.accumulated_total_grid.setData( $this.accumulated_total_grid_source, false );\n\t\t\t$this.punch_note_grid.setData( $this.punch_note_grid_source, false );\n\t\t\t$this.verification_grid.setData( $this.verification_grid_source, false );\n\n\t\t\t$this.setGridSize();\n\n\t\t\t$this.setTimeSheetGridPayPeriodHeaders();\n\t\t\t$this.setTimeSheetGridHolidayHeaders();\n\t\t\t$this.highLightSelectDay();\n\t\t\t$this.autoOpenEditViewIfNecessary();\n\t\t\t$this.setScrollPosition();\n\t\t\t$this.initRightClickMenu();\n\t\t\t$this.initRightClickMenu( RightClickMenuType.ABSENCE_GRID );\n\t\t\t$this.showWarningMessageIfAny();\n\t\t\t$this.setPunchModeClass();\n\n\t\t\tif ( $this.getPunchMode() != 'punch' ) {\n\t\t\t\tvar cols = $this.getManualPayPeriodDefaultTrColspan();\n\t\t\t\tfor ( var i = 0; i < cols; i++ ) {\n\t\t\t\t\tTimeSheetViewController_$( '.sub-grid td:nth-child(' + i + ')' ).css( 'border-right', 'none' );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tsearchDone() {\n\t\tTimeSheetViewController_$( '.button-rotate' ).removeClass( 'button-rotate' ); //the rotate icon from search panel\n\n\t\tTTPromise.resolve( 'init', 'init' );\n\t\tTTPromise.wait();\n\n\t\t//Check this.setGridSize() where we resize the grids if a scrollbar is detected to ensure all grids remain the same width after each one is built.\n\t\t// TTPromise.wait( null, null, function () {\n\t\t// //This was triggering JS exception: Permission denied to access property \"apply\" -- Seems like its no longer needed either.\n\t\t// \t$( window ).trigger( 'resize' );\n\t\t// } );\n\t}\n\n\tshowWarningMessageIfAny() {\n\t\tvar $this = this;\n\t\tvar timesheet_grid_div;\n\t\tvar warning_bar = TimeSheetViewController_$( this.el ).find( '.timesheet-warning-title-bar' );\n\t\twarning_bar.length > 0 && warning_bar.remove() && ( warning_bar = TimeSheetViewController_$( this.el ).find( '.timesheet-warning-title-bar' ) );\n\t\tif ( this.getPunchMode() === 'punch' ) {\n\t\t\ttimesheet_grid_div = TimeSheetViewController_$( this.el ).find( '#gbox_' + this.ui_id + '_grid' );\n\t\t} else {\n\t\t\ttimesheet_grid_div = TimeSheetViewController_$( this.el ).find( '.manual-timesheet-inside-editor-div' );\n\t\t}\n\n\t\tvar user = this.getSelectEmployee( true );\n\t\tvar user_pay_period_check = payPeriodCheck( user );\n\n\t\t//There seems to be a race condition here where if the server hasn't returned all the user data for the dropdown box (due to being slow/including many columns), \"user.id\" will exist, but no other object properties will.\n\t\t// This could trigger the below error message(s) to show when they shouldn't. So now we check to make sure there is at least more than 1 object property, and we check that the object properties actually exist and are actually blank, as compared to just checking that they don't exist previously.\n\t\tif ( Global/* Global.isObject */.x.isObject( user ) && Object.keys( user ).length > 1 && ( ( user.hasOwnProperty( 'pay_period_schedule_id' ) && user.pay_period_schedule_id == '' ) || ( user.hasOwnProperty( 'policy_group_id' ) && user.policy_group_id == '' ) || user_pay_period_check == false ) ) {\n\t\t\twarning_bar = TimeSheetViewController_$( '<div class=\\'timesheet-warning-title-bar\\'><span class=\\'p-message\\'></span><span class=\\'g-message\\'></span><span class=\\'pp-message\\'></span></div>' );\n\t\t\twarning_bar.insertBefore( timesheet_grid_div );\n\n\t\t\tif ( user.hasOwnProperty( 'pay_period_schedule_id' ) && user.pay_period_schedule_id == '' ) { //!user.pay_period_schedule_id\n\t\t\t\twarning_bar.children().eq( 0 ).html( TimeSheetViewController_$.i18n._( 'WARNING: Employee is not assigned to a pay period schedule.' ) );\n\t\t\t} else {\n\t\t\t\twarning_bar.children().eq( 0 ).html( '' );\n\t\t\t}\n\t\t\tif ( user.hasOwnProperty( 'policy_group_id' ) && user.policy_group_id == '' ) { //!user.policy_group_id\n\t\t\t\twarning_bar.children().eq( 1 ).html( TimeSheetViewController_$.i18n._( 'WARNING: Employee is not assigned to a policy group.' ) );\n\t\t\t} else {\n\t\t\t\twarning_bar.children().eq( 1 ).html( '' );\n\t\t\t}\n\n\t\t\tif ( user_pay_period_check == false ) {\n\t\t\t\twarning_bar.children().eq( 2 ).html( TimeSheetViewController_$.i18n._( 'WARNING: Employee has day(s) not assigned to a pay period. Please perform a pay period import to correct.' ) );\n\t\t\t} else {\n\t\t\t\twarning_bar.children().eq( 2 ).html( '' );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( warning_bar.length > 0 ) {\n\t\t\t\twarning_bar.remove();\n\t\t\t}\n\t\t}\n\n\t\tfunction payPeriodCheck( user ) {\n\t\t\tif ( $this.start_date ) {\n\t\t\t\tvar hire_date = user.hire_date;\n\t\t\t\tvar termination_date = user.termination_date;\n\n\t\t\t\tfor ( var i = 0; i < 7; i++ ) {\n\t\t\t\t\tvar select_date = new Date( new Date( $this.start_date.getTime() ).setDate( $this.start_date.getDate() + i ) );\n\t\t\t\t\tvar select_date_str = select_date.format();\n\n\t\t\t\t\t//Error: Uncaught TypeError: Cannot read property 'getTime' of null in interface/html5/index.php?user_name=dustin#!m=TimeSheet&date=20151214&user_id=38599&show_wage=0 line 2947\n\t\t\t\t\tif ( !select_date ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( select_date.getTime() < new Date().getTime() && !$this.getPayPeriod( select_date_str ) &&\n\t\t\t\t\t\t( !hire_date || select_date.getTime() >= Global/* Global.strToDate */.x.strToDate( hire_date ).getTime() ) &&\n\t\t\t\t\t\t( !termination_date || select_date.getTime() <= Global/* Global.strToDate */.x.strToDate( termination_date ).getTime() ) ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tautoOpenEditViewIfNecessary() {\n\t\t//Auto open edit view. Should set in IndexController\n\n\t\tswitch ( LocalCacheData.current_doing_context_action ) {\n\t\t\tcase 'edit':\n\t\t\t\tif ( LocalCacheData.edit_id_for_next_open_view ) {\n\t\t\t\t\tthis.onEditClick( LocalCacheData.edit_id_for_next_open_view, LocalCacheData.getAllURLArgs().t );\n\t\t\t\t\tLocalCacheData.edit_id_for_next_open_view = null;\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\tcase 'view':\n\t\t\t\tif ( LocalCacheData.edit_id_for_next_open_view ) {\n\t\t\t\t\tthis.onViewClick( LocalCacheData.edit_id_for_next_open_view, LocalCacheData.getAllURLArgs().t );\n\t\t\t\t\tLocalCacheData.edit_id_for_next_open_view = null;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'new':\n\t\t\t\tif ( !this.edit_view ) {\n\t\t\t\t\tif ( LocalCacheData.getAllURLArgs().t === 'absence' ) {\n\t\t\t\t\t\tthis.absence_model = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.absence_model = false;\n\t\t\t\t\t}\n\t\t\t\t\tthis.onAddClick();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\tthis.autoOpenEditOnlyViewIfNecessary();\n\t}\n\n\tgetWeekDayIndexFromADate( date_string ) {\n\n\t\tvar len = this.timesheet_columns.length;\n\n\t\tfor ( var i = 1; i < len; i++ ) {\n\t\t\tvar column = this.timesheet_columns[i];\n\t\t\tvar column_date_string = Global/* Global.strToDate */.x.strToDate( column.index, this.full_format ).format();\n\t\t\tif ( date_string === column_date_string ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\n\t\treturn 7;\n\t}\n\n\tsetAccumulatedTotalGridPayPeriodHeaders( width ) {\n\t\tvar table = TimeSheetViewController_$( TimeSheetViewController_$( this.el ).find( 'table[aria-labelledby=gbox_' + this.ui_id + '_accumulated_total_grid]' )[0] );\n\t\ttable.width( width );\n\n\t\tvar new_tr = TimeSheetViewController_$( '<tr class=\"group-column-tr\" role=\"rowheader\" >' +\n\t\t\t'</tr>' );\n\n\t\tvar new_th = TimeSheetViewController_$( '<th class=\"group-column-th\" >' +\n\t\t\t'<span class=\"group-column-label\"></span>' +\n\t\t\t'</th>' );\n\n\t\tvar default_th = new_th.clone();\n\n\t\tvar week_th = new_th.clone();\n\n\t\tvar pay_period_th = new_th.clone();\n\n\t\tweek_th.children( 0 ).text( TimeSheetViewController_$.i18n._( 'Week' ) );\n\t\tpay_period_th.children( 0 ).text( TimeSheetViewController_$.i18n._( 'Pay Period' ) );\n\n\t\tnew_tr.append( default_th );\n\t\tnew_tr.append( week_th );\n\t\tnew_tr.append( pay_period_th );\n\n\t\ttable.find( '.rowheader' ).remove();\n\t\ttable.find( 'thead' ).prepend( new_tr );\n\t}\n\n\tsetTimeSheetGridHolidayHeaders() {\n\t\tvar holiday_name_map = {};\n\t\tif ( this.full_timesheet_data && this.full_timesheet_data.holiday_data ) {\n\t\t\tfor ( var i = 0; i < this.full_timesheet_data.holiday_data.length; i++ ) {\n\t\t\t\tvar item = this.full_timesheet_data.holiday_data[i];\n\t\t\t\tvar standard_date = Global/* Global.strToDate */.x.strToDate( item.date_stamp ).format( this.full_format );\n\n\t\t\t\tvar cell = TimeSheetViewController_$( '<div></div>' );\n\t\t\t\tif ( this.getPunchMode() === 'manual' ) {\n\t\t\t\t\tcell = TimeSheetViewController_$( '.manual_grid_day_' + standard_date );\n\t\t\t\t} else {\n\t\t\t\t\tcell = TimeSheetViewController_$( 'div[id=\"jqgh_' + this.ui_id + '_grid_' + standard_date + '\"]' );\n\t\t\t\t}\n\n\t\t\t\tif ( cell && cell.text().indexOf( item.name ) == -1 && !holiday_name_map[item.name] ) {\n\t\t\t\t\tcell.html( cell.html() + '<br>' + Global/* Global.htmlEncode */.x.htmlEncode( item.name ) );\n\t\t\t\t\tholiday_name_map[item.name] = true;\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\t}\n\n\tgetManualPayPeriodDefaultTrColspan() {\n\t\tvar colspan = 2;\n\t\tif ( this.show_branch_ui ) {\n\t\t\tcolspan++;\n\t\t}\n\n\t\tif ( this.show_department_ui ) {\n\t\t\tcolspan++;\n\t\t}\n\n\t\tif ( this.show_job_ui ) {\n\t\t\tcolspan++;\n\t\t}\n\n\t\tif ( this.show_job_item_ui ) {\n\t\t\tcolspan++;\n\t\t}\n\n\t\tif ( this.show_punch_tag_ui ) {\n\t\t\tcolspan++;\n\t\t}\n\n\t\treturn colspan;\n\t}\n\n\tsetTimeSheetGridPayPeriodHeaders() {\n\t\tvar $this = this;\n\t\tvar table,\n\t\t\tsize_tr;\n\t\tif ( this.getPunchMode() === 'punch' ) {\n\t\t\ttable = TimeSheetViewController_$( TimeSheetViewController_$( this.el ).find( 'table[aria-labelledby=gbox_' + this.ui_id + '_grid]' )[0] );\n\t\t\tsize_tr = TimeSheetViewController_$( '<tr class=\"size-tr\" role=\"row\" style=\"height: 0;\" >' + '</tr>' );\n\t\t} else {\n\t\t\ttable = this.$( '.grid-inside-editor-render' );\n\t\t\ttable.find( '.group-column-tr' ).remove();\n\t\t\tsize_tr = TimeSheetViewController_$( this.$( '.grid-inside-editor-render' ).find( 'tr' )[0] );\n\t\t}\n\n\t\ttable.find( '.group-column-tr' ).remove();\n\n\t\tvar new_tr = TimeSheetViewController_$( '<tr class=\"group-column-tr pay_period_header_row\"></tr>' );\n\t\tvar new_th = TimeSheetViewController_$( '<th class=\"group-column-th\"><span class=\"group-column-label\"></span></th>' );\n\t\tvar current_trs = table.find( '.ui-jqgrid-labels' );\n\n\t\t// createSizeColumns was added in 2014. When manual timesheet mode was added in 2016, things were refactored and this should have been pulled out.\n\t\t// Leaving it in causes header row solumns to be out of alignment with the timesheet punch grid by a few pixels.\n\t\tif ( this.getPunchMode() === 'punch' ) {\n\t\t\tcreateSizeColumns();\n\t\t\tsize_tr.insertBefore( table.find( 'thead .ui-jqgrid-labels' ) );\n\t\t}\n\n\t\tvar default_th;\n\t\tif ( Object.keys( this.pay_period_data ).length === 0 ) {\n\t\t\tdefault_th = new_th.clone();\n\t\t\tnew_tr.append( default_th );\n\t\t\tif ( this.getPunchMode() === 'manual' ) {\n\t\t\t\tdefault_th.attr( 'colspan', this.getManualPayPeriodDefaultTrColspan() );\n\t\t\t}\n\t\t\tcreateNoPayPeriodColumns( 7 );\n\t\t\tnew_tr.insertAfter( size_tr );\n\t\t\treturn;\n\t\t}\n\t\tvar current_end_index = 0;\n\t\tvar last_pay_period_id;\n\t\tvar column_number = 0;\n\t\tvar pay_period;\n\t\tvar map_array = [];\n\t\tfor ( var y = 0; y < this.column_maps.length; y++ ) {\n\t\t\tvar p_key = this.column_maps[y];\n\t\t\tvar pay_period_id = this.pay_period_map[p_key];\n\t\t\tif ( !pay_period_id ) {\n\t\t\t\tpay_period_id = -1;\n\t\t\t}\n\t\t\tmap_array.push( { date: p_key, time_stamp: Global/* Global.strToDate */.x.strToDate( p_key ).getTime(), id: pay_period_id } );\n\t\t}\n\n\t\tdefault_th = new_th.clone();\n\t\tnew_tr.append( default_th );\n\t\tif ( this.getPunchMode() === 'manual' ) {\n\t\t\tdefault_th.attr( 'colspan', this.getManualPayPeriodDefaultTrColspan() );\n\t\t}\n\t\tfor ( var j = 0; j < map_array.length; j++ ) {\n\t\t\tif ( !last_pay_period_id ) {\n\t\t\t\tlast_pay_period_id = map_array[j].id;\n\t\t\t\tpay_period = getPayPeriod( map_array[j].id );\n\t\t\t\tcolumn_number = column_number + 1;\n\t\t\t} else if ( last_pay_period_id !== map_array[j].id ) {\n\t\t\t\tif ( pay_period ) {\n\t\t\t\t\tcreateTh();\n\t\t\t\t} else {\n\t\t\t\t\tcreateNoPayPeriodColumns( column_number );\n\t\t\t\t}\n\t\t\t\tlast_pay_period_id = map_array[j].id;\n\t\t\t\tpay_period = getPayPeriod( map_array[j].id );\n\t\t\t\tcolumn_number = 1;\n\n\t\t\t} else {\n\t\t\t\tcolumn_number = column_number + 1;\n\t\t\t}\n\t\t\tif ( j === map_array.length - 1 && column_number > 0 ) {\n\t\t\t\tif ( pay_period ) {\n\t\t\t\t\tcreateTh();\n\t\t\t\t} else {\n\t\t\t\t\tcreateNoPayPeriodColumns( column_number );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tTimeSheetViewController_$( '.pay_period_header_row' ).remove();\n\t\tnew_tr.insertAfter( size_tr );\n\n\t\tfunction createTh() {\n\t\t\tvar start_date = Global/* Global.strToDate */.x.strToDate( pay_period.start_date ).format();\n\t\t\tvar end_date = Global/* Global.strToDate */.x.strToDate( pay_period.end_date ).format();\n\t\t\tvar colspan = column_number;\n\t\t\tvar pay_period_th = new_th.clone();\n\t\t\tpay_period_th.children( 0 ).text( start_date + ' ' + TimeSheetViewController_$.i18n._( 'to' ) + ' ' + end_date );\n\t\t\tpay_period_th.attr( 'colspan', colspan );\n\t\t\t/* jshint ignore:start */\n\t\t\tif ( pay_period.status_id == 12 || pay_period.status_id == 20 ) {\n\t\t\t\tpay_period_th.css( 'background', '#EC0000' );\n\t\t\t} else if ( pay_period.status_id == 30 ) {\n\t\t\t\tpay_period_th.css( 'background', '#EED614' );\n\t\t\t}\n\t\t\t/* jshint ignore:end */\n\t\t\tnew_tr.append( pay_period_th );\n\t\t}\n\n\t\tfunction getPayPeriod( id ) {\n\t\t\tfor ( var key in $this.pay_period_data ) {\n\t\t\t\tvar pay_period = $this.pay_period_data[key];\n\t\t\t\tif ( pay_period.id === id ) {\n\t\t\t\t\treturn pay_period;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfunction createNoPayPeriodColumns( end_index ) {\n\t\t\tvar pay_period_th = new_th.clone();\n\t\t\tpay_period_th.addClass( 'no_pay_period_header' );\n\t\t\tpay_period_th.children( 0 ).text( TimeSheetViewController_$.i18n._( 'No Pay Period' ) );\n\t\t\tpay_period_th.attr( 'colspan', end_index );\n\t\t\tnew_tr.append( pay_period_th );\n\t\t}\n\n\t\tfunction createSizeColumns() {\n\t\t\tvar len = current_trs.children().length;\n\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\tvar th = TimeSheetViewController_$( '<td class=\"\" role=\"gridcell\">' + '</td>' );\n\t\t\t\tvar item = current_trs.children().eq( i );\n\t\t\t\t//th.width( item.width() );\n\t\t\t\tth.height( 0 );\n\t\t\t\tth.css( 'width', item.css( 'width' ) );\n\t\t\t\tsize_tr.append( th );\n\t\t\t}\n\n\t\t}\n\t}\n\n\tsetPayPeriodHeaderSize() {\n\n\t\tvar table = TimeSheetViewController_$( TimeSheetViewController_$( this.el ).find( 'table[aria-labelledby=gbox_' + this.ui_id + '_grid]' ) );\n\t\tvar size_tr = table.find( '.size-tr' );\n\n\t\tif ( size_tr.length === 0 ) {\n\t\t\treturn;\n\t\t}\n\t\t/**\n\t\t * #2353 - tiemsheet sizing fix\n\t\t *\n\t\t * Due to firefox reporting th widths incorrectly via the $.width() function, the sizes must come from the (tr.jqgfirstrow) of the data table\n\t\t * firefox also refuses to set the width of the first row of th's via the $.width() function, so we ned to ship the css values directly into the inline css using the css function\n\t\t */\n\t\tvar current_trs = table.find( '.jqgfirstrow' );\n\t\tvar len = current_trs.children().length;\n\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar item = current_trs.children().eq( i );\n\t\t\tsize_tr.children().eq( i ).css( 'width', item.css( 'width' ) );\n\t\t}\n\t}\n\n\thighLightSelectDay( e ) {\n\n\t\tif ( this.highlight_header ) {\n\t\t\tthis.highlight_header.removeClass( 'highlight-header' );\n\t\t}\n\n\t\t//Error: TypeError: select_date is null in interface/html5/framework/jquery.min.js?v=9.0.1-20151022-081724 line 2 > eval line 3214\n\t\tvar select_date = Global/* Global.strToDate */.x.strToDate( this.start_date_picker.getValue() );\n\t\t!select_date && ( select_date = new Date() );\n\n\t\tif ( this.getPunchMode() === 'punch' ) {\n\t\t\tselect_date = select_date.format( this.full_format );\n\t\t\tthis.highlight_header = TimeSheetViewController_$( '#' + this.ui_id + '_grid_' + select_date );\n\t\t} else {\n\t\t\tselect_date = select_date.format( this.full_format );\n\t\t\tthis.highlight_header = TimeSheetViewController_$( '.manual_grid_day_' + select_date );\n\t\t}\n\n\t\tthis.highlight_header.addClass( 'highlight-header' );\n\n\t\tif ( TimeSheetViewController_$( '.timesheet-grid tr td.ui-state-highlight' ).length == 0 && !e ) {\n\t\t\tTimeSheetViewController_$( TimeSheetViewController_$( '.timesheet-grid tr#1 td' )[this.highlight_header.index()] ).addClass( 'ui-state-highlight' );\n\t\t\tTimeSheetViewController_$( TimeSheetViewController_$( '.timesheet-grid tr#1 td' )[this.highlight_header.index()] ).click(); //trigger grid selection events\n\t\t}\n\t}\n\n\t/* jshint ignore:start */\n\tsetGridHeight( grid_id ) {\n\t\tvar grid = this.grid_dic[grid_id];\n\t\tif ( grid.grid ) {\n\t\t\tgrid = grid.grid;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t\tvar len = 0;\n\n\t\tswitch ( grid_id ) {\n\t\t\tcase 'timesheet_grid':\n\t\t\t\tlen = this.timesheet_data_source.length;\n\t\t\t\tbreak;\n\t\t\tcase 'accumulated_time_grid':\n\t\t\t\tlen = this.accumulated_time_source.length;\n\t\t\t\tbreak;\n\t\t\tcase 'branch_grid':\n\t\t\t\tlen = this.branch_source.length;\n\t\t\t\tbreak;\n\t\t\tcase 'department_grid':\n\t\t\t\tlen = this.department_source.length;\n\t\t\t\tbreak;\n\t\t\tcase 'job_grid':\n\t\t\t\tlen = this.job_source.length;\n\t\t\t\tbreak;\n\t\t\tcase 'job_item_grid':\n\t\t\t\tlen = this.job_item_source.length;\n\t\t\t\tbreak;\n\t\t\tcase 'punch_tag_grid':\n\t\t\t\tlen = this.punch_tag_source.length;\n\t\t\t\tbreak;\n\t\t\tcase 'premium_grid':\n\t\t\t\tlen = this.premium_source.length;\n\t\t\t\tbreak;\n\t\t\tcase 'absence_grid':\n\t\t\t\tlen = this.absence_source.length;\n\t\t\t\tbreak;\n\t\t\tcase 'accumulated_total_grid':\n\t\t\t\tlen = this.accumulated_total_grid_source.length;\n\t\t\t\tbreak;\n\t\t\tcase 'punch_note_grid':\n\t\t\t\tlen = this.punch_note_grid_source.length;\n\t\t\t\tbreak;\n\t\t\tcase 'verification_grid':\n\t\t\t\tlen = this.verification_grid_source.length;\n\t\t}\n\n\t\tif ( LocalCacheData.timesheet_sub_grid_expended_dic[grid_id] === true ||\n\t\t\tgrid_id === 'timesheet_grid' ||\n\t\t\tgrid_id === 'accumulated_total_grid' ||\n\t\t\tgrid_id === 'punch_note_grid' ||\n\t\t\tgrid_id === 'verification_grid' ) {\n\t\t\tgrid.setGridHeight( len * 22 );\n\t\t} else {\n\t\t\tgrid.setGridHeight( 0 );\n\n\t\t}\n\n\t\t//dont't show scroll bar of grid\n\t\tgrid.parent().parent().css( 'overflow', 'hidden' );\n\n\t\t//Do not show grid if no data in it\n\t\tif ( len === 0 && grid_id !== 'accumulated_time_grid' && grid_id !== 'verification_grid' ) {\n\t\t\tgrid.parent().parent().parent().parent().hide();\n\t\t} else {\n\t\t\tgrid.parent().parent().parent().parent().show();\n\t\t}\n\t}\n\n\t/* jshint ignore:end */\n\n\tsetGridColumnsWidth() {\n\t\t//BaseViewController definition of this function resizes the main grid of a view, but we want to resize all grids in this view.\n\t\t//The BaseViewController version would be called when expanding/collapsing the search panel causing only the main grid to be resized and be misaligned with the others.\n\t\tthis.setGridSize();\n\t}\n\n\tsetGridSize() {\n\t\tvar $this = this;\n\n\t\t//TTGrid backwards compatible.\n\t\tvar $grid = this.grid;\n\t\tif ( $grid.grid ) {\n\t\t\t$grid = $grid.grid;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t\tif ( ( !$grid || !TimeSheetViewController_$( $grid ).is( ':visible' ) ) && ( !this.editor || !this.editor.is( ':visible' ) ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( var key in this.grid_dic ) {\n\t\t\tif ( key != 'punch_note_grid' && key != 'accumulated_total_grid' && key != 'verification_grid' ) {\n\t\t\t\tif ( !this.grid_dic[key].grid ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tvar grid = this.grid_dic[key].grid;\n\t\t\t\tgrid.setGridWidth( this.getTimeSheetWidth() );\n\t\t\t\tthis.setGridHeight( key );\n\t\t\t}\n\t\t}\n\n\t\tthis.setGridHeight( 'accumulated_total_grid' ); //can't set height on this grid. until we fix what's wrong with it.\n\n\t\tthis.grid_dic['verification_grid'].grid.setGridWidth( 400 );\n\t\tthis.setGridHeight( 'verification_grid' );\n\n\t\tthis.setPunchNoteGridWidth( this.grid_dic['punch_note_grid'].grid );\n\t\tthis.setGridHeight( 'punch_note_grid' ); //can't set height on this grid. until we fix what's wrong with it.\n\n\t\tlet scroll_height = document.body.scrollHeight;\n\n\t\tlet height = scroll_height;\n\n\t\tlet timesheet_grid = document.querySelector( 'div.timesheet-grid-div' );\n\t\tif ( timesheet_grid ) { //Issue #3060 - JavaScript exceptions of trying to read getBoundingClientRect of null elements.\n\t\t\theight -= timesheet_grid.getBoundingClientRect().top;\n\t\t}\n\t\tlet context_border = document.querySelector( 'div.context-border' );\n\t\tif ( context_border ) { //Issue #3060 - JavaScript exceptions of trying to read getBoundingClientRect of null elements.\n\t\t\theight -= ( scroll_height - document.querySelector( 'div.context-border' ).getBoundingClientRect().bottom );\n\t\t}\n\t\theight -= 10; //Manual fine tuning to fit better.\n\n\t\tthis.grid_div.height( height );\n\t\tthis.grid.setGridWidth( this.getTimeSheetWidth() );\n\n\t\tthis.setPayPeriodHeaderSize();\n\n\t\tif ( this.getPunchMode() === 'manual' ) {\n\t\t\t$this.setManualTimeSheetGridSize();\n\t\t}\n\n\t\t//Because a scrollbar has appeared in the middle of resizing the top grids compared to the bottom grid, the page may have expanded to show the scrollbar and we may need to resize the grids (width) again to take into account.\n\t\t//This is manifested itself in misaligned columns between the two grids.\n\t\tif ( Global/* Global.isVerticalScrollBarRequired */.x.isVerticalScrollBarRequired( TimeSheetViewController_$('.timesheet-grid-div')[0] ) ) {\n\t\t\tfor ( var key in this.grid_dic ) {\n\t\t\t\tif ( key != 'punch_note_grid' && key != 'accumulated_total_grid' && key != 'verification_grid' ) {\n\t\t\t\t\tif ( !this.grid_dic[key].grid ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tvar grid = this.grid_dic[key].grid;\n\t\t\t\t\tgrid.setGridWidth( this.getTimeSheetWidth() );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tsetPunchNoteGridWidth( grid ) {\n\t\tif ( !grid ) {\n\t\t\tif ( !this.punch_note_grid || !this.punch_note_grid.grid ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tgrid = this.punch_note_grid.grid;\n\t\t}\n\n\t\tvar grid_width = grid.width();\n\n\t\tvar accumulated_grid_width = ( this.accumulated_total_grid && this.accumulated_total_grid.grid ) ? this.accumulated_total_grid.getWidth() : 0;\n\t\tvar verification_grid_width = ( this.verification_grid && this.verification_grid.grid ) ? this.verification_grid.getWidth() : 0;\n\n\t\tif ( this.verification_grid_source.length !== 0 ) {\n\t\t\tgrid_width = Math.floor( this.getTimeSheetWidth() - ( accumulated_grid_width + verification_grid_width + 7 ) );\n\t\t} else {\n\t\t\tgrid_width = Math.floor( this.getTimeSheetWidth() - ( 7 + accumulated_grid_width ) );\n\t\t}\n\t\tgrid_width = Math.abs( grid_width );\n\n\t\tif ( grid_width != grid.width() ) {\n\t\t\t//Debug.Text(\"Setting punch note grid width to \" + grid_width, 'TimesheetViewConroller.js', 'TimesheetViewConroller', 'setGridHeight', 10);\n\t\t\tgrid.setGridWidth( grid_width );\n\t\t\tTimeSheetViewController_$( 'td.notes_grid_td_container' ).css( 'width', '100%' );\n\t\t}\n\t}\n\n\tsetManualTimeSheetGridSize() {\n\t\tvar tr = TimeSheetViewController_$( this.accumulated_time_grid.grid.find( 'tr:first-child' )[0] );\n\t\tvar manual_grid_tr = TimeSheetViewController_$( this.editor.find( 'table' ).find( 'tr:first-child' )[0] );\n\t\tvar index = 0;\n\t\tfor ( var i = 0, m = manual_grid_tr.children().length; i < m; i++ ) {\n\t\t\tvar td = TimeSheetViewController_$( manual_grid_tr.children()[i] );\n\t\t\tif ( !td.is( ':visible' ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tTimeSheetViewController_$( td ).css( 'width', TimeSheetViewController_$( tr.children()[index] ).css( 'width' ) );\n\t\t\tindex++;\n\t\t}\n\n\t\tthis.editor.width( this.accumulated_time_grid.getGridWidth() );\n\t}\n\n\tonCellFormat( cell_value, related_data, row ) {\n\t\tvar col_model = related_data.colModel;\n\t\tvar row_id = related_data.rowid;\n\t\tvar content_div = TimeSheetViewController_$( '<div class=\\'punch-content-div\\'></div>' );\n\t\tvar punch_info;\n\t\tvar ex_span;\n\t\tvar i;\n\t\tvar time_span_prefix;\n\t\tvar time_span;\n\t\tvar time_span_suffix;\n\t\tvar punch;\n\t\tvar break_span;\n\t\tvar related_punch;\n\t\tvar exception;\n\t\tvar len;\n\t\tvar text;\n\t\tvar ex;\n\t\tvar data;\n\t\tvar currency = LocalCacheData.getCurrentCurrencySymbol();\n\n\t\tcell_value = Global/* Global.decodeCellValue */.x.decodeCellValue( cell_value );\n\t\tif ( related_data.pos === 0 ) {\n\t\t\tif ( row.type === TimeSheetViewController.TOTAL_ROW ) {\n\t\t\t\tpunch_info = TimeSheetViewController_$( '<span class=\\'total\\' style=\\'font-size: 11px\\'></span>' );\n\t\t\t\tif ( Global/* Global.isSet */.x.isSet( cell_value ) ) {\n\t\t\t\t\tpunch_info.text( cell_value );\n\t\t\t\t} else {\n\t\t\t\t\tpunch_info.text( '' );\n\t\t\t\t}\n\n\t\t\t\treturn punch_info.get( 0 ).outerHTML;\n\t\t\t} else if ( row.type === TimeSheetViewController.REGULAR_ROW ) {\n\t\t\t\tpunch_info = TimeSheetViewController_$( '<span class=\\'top-line-span\\' style=\\'font-size: 11px\\'></span>' );\n\t\t\t\tif ( Global/* Global.isSet */.x.isSet( cell_value ) ) {\n\t\t\t\t\tpunch_info.text( cell_value );\n\t\t\t\t} else {\n\t\t\t\t\tpunch_info.text( '' );\n\t\t\t\t}\n\t\t\t\treturn punch_info.get( 0 ).outerHTML;\n\t\t\t}\n\n\t\t\treturn cell_value;\n\t\t}\n\n\t\tif ( row.type === TimeSheetViewController.PUNCH_ROW ) {\n\t\t\tpunch = row[col_model.name + '_data'];\n\t\t\trelated_punch = row[col_model.name + '_related_data'];\n\t\t\ttime_span_prefix = TimeSheetViewController_$( '<span class=\\'punch-prefix\\'></span>' );\n\t\t\ttime_span = TimeSheetViewController_$( '<span class=\\'punch-time\\'></span>' );\n\t\t\ttime_span_suffix = TimeSheetViewController_$( '<span class=\\'punch-suffix\\'></span>' );\n\t\t\tbreak_span = TimeSheetViewController_$( '<span class=\\'punch-break\\'></span>' );\n\n\t\t\tif ( punch ) {\n\t\t\t\texception = punch.exception;\n\n\t\t\t\tvar break_label = '';\n\t\t\t\tvar break_label_title = '';\n\t\t\t\tif ( punch.type_id == 20 ) {\n\t\t\t\t\tbreak_label = 'L';\n\t\t\t\t\tbreak_label_title = TimeSheetViewController_$.i18n._('Lunch');\n\t\t\t\t} else if ( punch.type_id == 30 ) {\n\t\t\t\t\tbreak_label = 'B';\n\t\t\t\t\tbreak_label_title = TimeSheetViewController_$.i18n._('Break');\n\t\t\t\t}\n\n\t\t\t\tvar label_prefix = '';\n\t\t\t\tvar label_prefix_title = '';\n\t\t\t\tif ( punch.note != '' ) {\n\t\t\t\t\tlabel_prefix = '*';\n\t\t\t\t\tlabel_prefix_title = TimeSheetViewController_$.i18n._('Note') +': '+ punch.note;\n\t\t\t\t}\n\n\t\t\t\tvar label_suffix = '';\n\t\t\t\tvar label_suffix_title = '';\n\t\t\t\tif ( punch.id == TTUUID/* TTUUID.not_exist_id */.d.not_exist_id ) {\n\t\t\t\t\tlabel_suffix = 'P';\n\t\t\t\t\tlabel_suffix_title = 'P='+ TimeSheetViewController_$.i18n._('Processing');\n\t\t\t\t}\n\t\t\t\tif ( punch.latitude && punch.latitude != 0 && punch.longitude && punch.longitude != 0 ) {\n\t\t\t\t\tlabel_suffix = 'G';\n\t\t\t\t\tlabel_suffix_title = 'G='+ TimeSheetViewController_$.i18n._('GPS Location');\n\t\t\t\t}\n\n\t\t\t\tif ( punch.has_image ) {\n\t\t\t\t\tlabel_suffix = label_suffix + 'F';\n\t\t\t\t\tlabel_suffix_title = label_suffix_title + ' F='+ TimeSheetViewController_$.i18n._('Punch Image');\n\t\t\t\t}\n\n\t\t\t\tif ( punch.tainted ) {\n\t\t\t\t\ttime_span.css( 'color', '#ff0000' );\n\t\t\t\t}\n\t\t\t} else if ( related_punch ) {\n\t\t\t\texception = related_punch.exception;\n\t\t\t}\n\n\t\t\tif ( Global/* Global.isSet */.x.isSet( label_prefix ) && label_prefix != '' ) {\n\t\t\t\ttime_span_prefix.text( label_prefix );\n\t\t\t\ttime_span_prefix.attr( 'title', label_prefix_title );\n\t\t\t\tcontent_div.append( time_span_prefix );\n\t\t\t}\n\n\t\t\tif ( Global/* Global.isSet */.x.isSet( cell_value ) ) {\n\t\t\t\ttime_span.text( cell_value );\n\t\t\t} else {\n\t\t\t\ttime_span.text( '' );\n\t\t\t}\n\t\t\tcontent_div.append( time_span );\n\n\t\t\tif ( Global/* Global.isSet */.x.isSet( label_suffix ) && label_suffix != '' ) {\n\t\t\t\ttime_span_suffix.text( label_suffix );\n\t\t\t\ttime_span_suffix.attr( 'title', label_suffix_title );\n\t\t\t\tcontent_div.append( time_span_suffix );\n\t\t\t}\n\n\t\t\tif ( Global/* Global.isSet */.x.isSet( break_label ) && break_label != '' ) {\n\t\t\t\tbreak_span.text( break_label );\n\t\t\t\tbreak_span.attr( 'title', break_label_title );\n\t\t\t\tcontent_div.append( break_span );\n\t\t\t}\n\n\t\t\tif ( exception ) {\n\t\t\t\tlen = exception.length;\n\t\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\t\tex = exception[i];\n\t\t\t\t\tex_span = TimeSheetViewController_$( '<span class=\\'punch-exceptions\\'></span>' );\n\t\t\t\t\tex_span.css( 'color', ex.exception_color );\n\t\t\t\t\tex_span.text( ex.exception_policy_type_id );\n\t\t\t\t\tex_span.attr( 'title', ex.exception_policy_type_id + ': ' + ex.exception_policy_type );\n\t\t\t\t\tcontent_div.prepend( ex_span );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// ex_span = $( '<span class=\\'punch-exceptions\\'></span>' );\n\t\t\t\t// ex_span.text( ' ' );\n\t\t\t\t// content_div.prepend( ex_span );\n\t\t\t}\n\n\t\t} else if ( row.type === TimeSheetViewController.EXCEPTION_ROW ) {\n\t\t\texception = row[col_model.name + '_exceptions'];\n\n\t\t\tif ( Global/* Global.isSet */.x.isSet( exception ) ) {\n\t\t\t\tlen = exception.length;\n\t\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\t\tex = exception[i];\n\t\t\t\t\tex_span = TimeSheetViewController_$( '<span class=\\'punch-exceptions-center\\'></span>' );\n\t\t\t\t\tex_span.css( 'color', ex.exception_color );\n\t\t\t\t\tex_span.text( ex.exception_policy_type_id );\n\t\t\t\t\tex_span.attr( 'title', ex.exception_policy_type_id + ': ' + ex.exception_policy_type );\n\n\t\t\t\t\tcontent_div.append( ex_span );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else if ( row.type === TimeSheetViewController.REQUEST_ROW ) {\n\t\t\ttime_span = TimeSheetViewController_$( '<span class=\\'request\\'></span>' );\n\t\t\tif ( Global/* Global.isSet */.x.isSet( cell_value ) ) {\n\t\t\t\ttime_span.text( cell_value );\n\t\t\t\ttime_span.attr( 'title', createRequestToolTip( row[col_model.name + '_request'] ) );\n\t\t\t} else {\n\t\t\t\ttime_span.text( '' );\n\t\t\t}\n\t\t\tcontent_div.prepend( time_span );\n\n\t\t} else if ( row.type === TimeSheetViewController.TOTAL_ROW ) {\n\n\t\t\tdata = row[col_model.name + '_data'];\n\t\t\ttime_span = TimeSheetViewController_$( '<span class=\\'total\\'></span>' );\n\n\t\t\tif ( Global/* Global.isSet */.x.isSet( cell_value ) ) {\n\n\t\t\t\tif ( data ) {\n\n\t\t\t\t\tif ( data.hasOwnProperty( 'note' ) && data.note ) {\n\t\t\t\t\t\tcell_value = '*' + cell_value;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( time_sheet_view_controller.wage_btn && time_sheet_view_controller.wage_btn.getValue( true ) && data.hasOwnProperty( 'total_time_amount' ) && data.total_time_amount && data.hasOwnProperty( 'hourly_rate' ) && data.hourly_rate ) {\n\t\t\t\t\t\ttime_span = TimeSheetViewController_$( '<div class=\\'total--bold time-sheet-view-wage-container\\'></div>' );\n\t\t\t\t\t\tcell_value = '<span class=\"time-sheet-view-wage-hour-rate\">' + currency + Global/* Global.MoneyRound */.x.MoneyRound( data.hourly_rate ) + '/hr @</span>' +\n\t\t\t\t\t\t\t'<span class=\"time-sheet-view-wage-value\">' + cell_value +\n\t\t\t\t\t\t\t'</span ><span class=\"time-sheet-view-wage-amount\" >= ' + currency + Global/* Global.MoneyRound */.x.MoneyRound( data.total_time_amount ) +\n\t\t\t\t\t\t\t'</span>';\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( time_sheet_view_controller.getPunchMode() === 'punch' ) {\n\t\t\t\t\t\tif ( data.hasOwnProperty( 'override' ) && data.override === true ) {\n\t\t\t\t\t\t\ttime_span.addClass( 'absence-override' );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( !data.override && row.key === 'worked_time' ) {\n\t\t\t\t\t\t\ttime_span.addClass( 'absence-override' );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\ttime_span.html( cell_value );\n\n\t\t\t} else {\n\t\t\t\ttime_span.text( '' );\n\t\t\t}\n\t\t\tcontent_div.prepend( time_span );\n\n\t\t} else if ( row.type === TimeSheetViewController.REGULAR_ROW ) {\n\n\t\t\tcontent_div.addClass( 'top-line' );\n\n\t\t\tdata = row[col_model.name + '_data'];\n\n\t\t\ttime_span = TimeSheetViewController_$( '<span></span>' );\n\t\t\tif ( Global/* Global.isSet */.x.isSet( cell_value ) ) {\n\n\t\t\t\tif ( data ) {\n\n\t\t\t\t\tif ( data.hasOwnProperty( 'note' ) && data.note ) {\n\t\t\t\t\t\tcell_value = '*' + cell_value;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( time_sheet_view_controller.wage_btn && time_sheet_view_controller.wage_btn.getValue( true ) && data.hasOwnProperty( 'total_time_amount' ) && data.total_time_amount && data.hasOwnProperty( 'hourly_rate' ) && data.hourly_rate ) {\n\t\t\t\t\t\ttime_span = TimeSheetViewController_$( '<div class=\\'time-sheet-view-wage-container\\'></div>' );\n\t\t\t\t\t\tcell_value = '<span class=\"time-sheet-view-wage-hour-rate\">' + currency + Global/* Global.MoneyRound */.x.MoneyRound( data.hourly_rate ) + '/hr @</span>' +\n\t\t\t\t\t\t\t'<span class=\"time-sheet-view-wage-value\">' + cell_value +\n\t\t\t\t\t\t\t'</span ><span class=\"time-sheet-view-wage-amount\" >= ' + currency + Global/* Global.MoneyRound */.x.MoneyRound( data.total_time_amount ) +\n\t\t\t\t\t\t\t'</span>';\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( data.hasOwnProperty( 'override' ) && data.override === true ) {\n\t\t\t\t\t\ttime_span.addClass( 'absence-override' );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\ttime_span.html( cell_value );\n\t\t\t} else {\n\t\t\t\ttime_span.text( '' );\n\t\t\t}\n\t\t\tcontent_div.prepend( time_span );\n\n\t\t} else if ( row.type === TimeSheetViewController.ABSENCE_ROW ) {\n\n\t\t\tvar absence = row[col_model.name + '_data'];\n\t\t\ttime_span = TimeSheetViewController_$( '<span></span>' );\n\n\t\t\tif ( Global/* Global.isSet */.x.isSet( cell_value ) ) {\n\n\t\t\t\tif ( absence ) {\n\n\t\t\t\t\tif ( absence.override === true ) {\n\t\t\t\t\t\ttime_span.addClass( 'absence-override' );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( absence.note ) {\n\t\t\t\t\t\tcell_value = '*' + cell_value;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\ttime_span.text( cell_value );\n\n\t\t\t} else {\n\t\t\t\ttime_span.text( '' );\n\t\t\t}\n\t\t\tcontent_div.prepend( time_span );\n\n\t\t} else if ( row.type === TimeSheetViewController.ACCUMULATED_TIME_ROW ||\n\t\t\trow.type === TimeSheetViewController.PREMIUM_ROW ) {\n\t\t\tdata = row[col_model.name + '_data'];\n\t\t\ttime_span = TimeSheetViewController_$( '<span style=\\'width: 100%\\'></span>' );\n\n\t\t\tif ( Global/* Global.isSet */.x.isSet( cell_value ) ) {\n\n\t\t\t\tif ( data ) {\n\n\t\t\t\t\tif ( data.hasOwnProperty( 'note' ) && data.note ) {\n\t\t\t\t\t\tcell_value = '*' + cell_value;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( time_sheet_view_controller.wage_btn && time_sheet_view_controller.wage_btn.getValue( true ) && data.hasOwnProperty( 'total_time_amount' ) && data.total_time_amount && data.hasOwnProperty( 'hourly_rate' ) && data.hourly_rate ) {\n\t\t\t\t\t\ttime_span = TimeSheetViewController_$( '<div class=\\'time-sheet-view-wage-container\\'></div>' );\n\t\t\t\t\t\tcell_value = '<span class=\"time-sheet-view-wage-hour-rate\">' + currency + Global/* Global.MoneyRound */.x.MoneyRound( data.hourly_rate ) + '/hr @</span>' +\n\t\t\t\t\t\t\t'<span class=\"time-sheet-view-wage-value\">' + cell_value +\n\t\t\t\t\t\t\t'</span ><span class=\"time-sheet-view-wage-amount\" >= ' + currency + Global/* Global.MoneyRound */.x.MoneyRound( data.total_time_amount ) +\n\t\t\t\t\t\t\t'</span>';\n\t\t\t\t\t}\n\t\t\t\t\tif ( data.hasOwnProperty( 'override' ) && data.override === true ) {\n\t\t\t\t\t\ttime_span.addClass( 'absence-override' );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\ttime_span.html( cell_value );\n\n\t\t\t} else {\n\t\t\t\ttime_span.text( '' );\n\t\t\t}\n\t\t\tcontent_div.prepend( time_span );\n\n\t\t} else {\n\t\t\ttime_span = TimeSheetViewController_$( '<span class=\\'punch-time\\'></span>' );\n\t\t\tif ( Global/* Global.isSet */.x.isSet( cell_value ) ) {\n\t\t\t\ttime_span.text( cell_value );\n\t\t\t} else {\n\t\t\t\ttime_span.text( '' );\n\t\t\t}\n\t\t\tcontent_div.prepend( time_span );\n\t\t}\n\n\t\tfunction createRequestToolTip( value ) {\n\t\t\tvar label;\n\t\t\tif ( Global/* Global.isArray */.x.isArray( value ) ) {\n\t\t\t\tlabel = calDAndA( value );\n\t\t\t} else if ( Global/* Global.isObject */.x.isObject( value ) && value.status ) {\n\t\t\t\tlabel = value.status; //Use the label directly from the API.\n\t\t\t}\n\n\t\t\tfunction calDAndA( array ) {\n\t\t\t\tvar len = array.length;\n\t\t\t\tvar a = 0;\n\t\t\t\tvar d = 0;\n\t\t\t\tvar p = 0;\n\t\t\t\tvar label = '';\n\t\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\t\tvar item = array[i];\n\t\t\t\t\tif ( item.status_id == 50 ) {\n\t\t\t\t\t\ta = a + 1;\n\t\t\t\t\t} else if ( item.status_id == 55 ) {\n\t\t\t\t\t\td = d + 1;\n\t\t\t\t\t} else if ( item.status_id == 30 ) {\n\t\t\t\t\t\tp = p + 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( a > 0 ) {\n\t\t\t\t\tlabel += ' ' + TimeSheetViewController_$.i18n._( 'Authorized' ) + ': ' + a;\n\t\t\t\t}\n\t\t\t\tif ( p > 0 ) {\n\t\t\t\t\tlabel += ' ' + TimeSheetViewController_$.i18n._( 'Pending' ) + ': ' + p;\n\t\t\t\t}\n\t\t\t\tif ( d > 0 ) {\n\t\t\t\t\tlabel += ' ' + TimeSheetViewController_$.i18n._( 'Declined' ) + ': ' + d;\n\t\t\t\t}\n\t\t\t\treturn label;\n\t\t\t}\n\n\t\t\treturn label;\n\t\t}\n\n\t\tcontent_div.addClass( 'date-column' );\n\n\t\treturn content_div.get( 0 ).outerHTML;\n\t}\n\n\tonSelectRow( grid_id, row_id, target ) {\n\t\tvar $this = this;\n\t\tvar row_tr = TimeSheetViewController_$( target ).find( 'tr#' + row_id );\n\t\t$this.timesheet_grid.grid.find( 'td.ui-state-highlight' ).removeClass( 'ui-state-highlight' );\n\t\tvar cells_array = [];\n\t\tvar len = 0;\n\t\tif ( grid_id === 'timesheet_grid' ) {\n\t\t\tcells_array = $this.select_cells_Array;\n\t\t\tlen = $this.select_cells_Array.length;\n\t\t\t$this.absence_select_cells_Array = [];\n\t\t} else if ( grid_id === 'absence_grid' ) {\n\t\t\tcells_array = $this.absence_select_cells_Array;\n\t\t\tlen = $this.absence_select_cells_Array.length;\n\t\t\t$this.select_cells_Array = [];\n\t\t} else if ( grid_id === 'accumulated_grid' ) {\n\t\t\tcells_array = $this.accumulated_time_cells_array;\n\t\t\tlen = $this.accumulated_time_cells_array.length;\n\t\t} else if ( grid_id === 'premium_grid' ) {\n\t\t\tcells_array = $this.premium_cells_array;\n\t\t\tlen = $this.premium_cells_array.length;\n\t\t}\n\t\tthis.select_punches_array = [];\n\t\t/* jshint ignore:start */\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar info = cells_array[i];\n\t\t\trow_tr = TimeSheetViewController_$( target ).find( '#' + info.row_id );\n\t\t\tvar cell_td = TimeSheetViewController_$( row_tr.find( 'td' )[info.cell_index] );\n\t\t\tcell_td.addClass( 'ui-state-highlight' ).attr( 'aria-selected', true );\n\n\t\t\tif ( info.punch && info.punch.id ) {\n\n\t\t\t\tif ( Global/* Global.isSet */.x.isSet( info.punch.time_stamp ) ) { //date + time number\n\t\t\t\t\tvar date = Global/* Global.strToDate */.x.strToDate( info.punch.punch_date ).format( 'MM-DD-YYYY' );\n\t\t\t\t\tvar date_time = date + ' ' + info.punch.punch_time;\n\t\t\t\t\tinfo.punch.time_stamp_num = Global/* Global.strToDateTime */.x.strToDateTime( date_time ).getTime();\n\t\t\t\t} else {\n\t\t\t\t\tinfo.punch.time_stamp_num = info.time_stamp_num; //Uer time_stamp_num from cell select setting, a date number\n\t\t\t\t}\n\t\t\t\tthis.select_punches_array.push( info.punch );\n\t\t\t\tthis.select_punches_array.sort( function( a, b ) {\n\t\t\t\t\treturn Global/* Global.compare */.x.compare( a, b, 'time_stamp_num' );\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t\t/* jshint ignore:end */\n\t}\n\n\tunsetSelectedCells( grid_id ) {\n\t\tif ( grid_id == 'accumulated_grid' ) {\n\t\t\tgrid_id = 'accumulated_time_grid';\n\t\t}\n\n\t\tif ( this.last_clicked_grid_id && grid_id != this.last_clicked_grid_id ) {\n\t\t\t//Use window setTimeout to make this code asyncchronous for speed, it's the fastest way.\n\t\t\t//web worker : 850ms\n\t\t\t//inline code : 700ms\n\t\t\t//setTimeout: 400ms\n\t\t\twindow.setTimeout( function( t, n ) {\n\t\t\t\tt.grid_dic[n].grid.trigger( 'reloadGrid' );\n\t\t\t}, 0, this, this.last_clicked_grid_id );\n\t\t}\n\n\t\t//this.setDefaultMenu();\n\t\tthis.last_clicked_grid_id = grid_id;\n\t}\n\n\tgetRowData( grid_id, row_id ) {\n\t\tvar $this = this;\n\n\t\tvar row_data = null;\n\n\t\tif ( grid_id === 'absence_grid' ) {\n\t\t\trow_data = $this.absence_grid.getGridParam( 'data' );\n\t\t} else if ( grid_id === 'accumulated_grid' ) {\n\t\t\trow_data = $this.accumulated_time_grid.getGridParam( 'data' );\n\t\t} else if ( grid_id === 'premium_grid' ) {\n\t\t\trow_data = $this.premium_grid.getGridParam( 'data' );\n\t\t} else { //Should be: timesheet_grid\n\t\t\trow_data = $this.grid.getGridParam( 'data' );\n\t\t}\n\n\t\tvar row = false;\n\n\t\tfor ( var i in row_data ) {\n\t\t\tif ( row_data[i].id == row_id ) {\n\t\t\t\trow = row_data[i];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn row;\n\t}\n\n\tonCellSelect( grid_id, row_id, cell_index, cell_val, target, e ) {\n\t\tTimeSheetViewController_$( '#ribbon_view_container .context-menu:visible a' ).click();\n\n\t\tif ( cell_index < 0 ) {\n\t\t\tthis.unsetSelectedCells( grid_id );\n\t\t\tthis.setDefaultMenu();\n\t\t\treturn true; //continue default processing.\n\t\t}\n\n\t\tcell_index = parseInt( cell_index );\n\n\t\tvar $this = this;\n\t\tvar row;\n\t\tvar colModel;\n\t\tvar data_field;\n\t\tvar punch;\n\t\tvar related_punch;\n\t\tvar cells_array = [];\n\t\tvar date;\n\n\t\tif ( !this.is_edit && !this.is_add ) {\n\t\t\t$this.absence_model = false;\n\t\t}\n\n\t\trow = $this.getRowData( grid_id, row_id );\n\n\t\tif ( grid_id === 'timesheet_grid' ) {\n\t\t\tcells_array = $this.select_cells_Array;\n\n\t\t\tcolModel = $this.grid.getGridParam( 'colModel' );\n\t\t\tdata_field = colModel[cell_index].name;\n\n\t\t\tif ( row.type === TimeSheetViewController.REQUEST_ROW ) {\n\t\t\t\tvar filter = { filter_data: {} };\n\t\t\t\tfilter.filter_data.user_id = this.getSelectEmployee();\n\t\t\t\tfilter.filter_data.start_date = $this.full_timesheet_data.timesheet_dates.start_display_date;\n\t\t\t\tfilter.filter_data.end_date = $this.full_timesheet_data.timesheet_dates.end_display_date;\n\t\t\t\tfilter.filter_data.id = [];\n\n\t\t\t\t$this.unsetSelectedCells( grid_id );\n\t\t\t\tvar pending_requests = 0;\n\t\t\t\tvar total_requests = 0;\n\t\t\t\tif ( Global/* Global.isArray */.x.isArray( row[data_field + '_request'] ) ) {\n\t\t\t\t\tfor ( var n in row[data_field + '_request'] ) {\n\t\t\t\t\t\tvar obj = row[data_field + '_request'][n];\n\t\t\t\t\t\tfilter.filter_data.id.push( obj.id );\n\t\t\t\t\t\tif ( obj.status == TimeSheetViewController_$.i18n._( 'PENDING' ) ) {\n\t\t\t\t\t\t\tpending_requests += 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttotal_requests += 1;\n\t\t\t\t\t}\n\t\t\t\t} else if ( row[data_field + '_request'] ) {\n\t\t\t\t\t//is object;\n\t\t\t\t\tfilter.filter_data.id.push( row[data_field + '_request'].id );\n\t\t\t\t\tif ( row[data_field + '_request'].status == TimeSheetViewController_$.i18n._( 'PENDING' ) ) {\n\t\t\t\t\t\tpending_requests = 1;\n\t\t\t\t\t}\n\t\t\t\t\ttotal_requests = 1;\n\t\t\t\t} else {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tGlobal/* Global.addViewTab */.x.addViewTab( this.viewId, TimeSheetViewController_$.i18n._( 'TimeSheet' ), window.location.href );\n\n\t\t\t\tif ( total_requests > 0 ) {\n\t\t\t\t\tif ( this.getSelectEmployee() != LocalCacheData.getLoginUser().id && pending_requests > 0 ) {\n\t\t\t\t\t\t//Handle cases where an administrator who can see all requests might click on a pending request cell and want to be taken to MyAccount -> Requests\n\t\t\t\t\t\t//rather than MyAccount -> Request Authorization, which wouldn't show anything.\n\t\t\t\t\t\tif ( this.ownerOrChildPermissionValidate( 'request', 'view_child', filter.filter_data.id ) ) {\n\t\t\t\t\t\t\tIndexViewController.goToView( 'RequestAuthorization', filter );\n\t\t\t\t\t\t} else if ( this.viewPermissionValidate( 'request', filter.filter_data.id ) ) {\n\t\t\t\t\t\t\tIndexViewController.goToView( 'Request', filter );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t//If the request isn't pending, then go to MyAccount -> Requests, and MyAccount -> Request Authorization wouldn't show anything.\n\t\t\t\t\t\tif ( this.viewPermissionValidate( 'request', filter.filter_data.id ) ) {\n\t\t\t\t\t\t\tIndexViewController.goToView( 'Request', filter );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( row && row[data_field + '_data'] ) {\n\t\t\t\tpunch = row[data_field + '_data'];\n\t\t\t} else {\n\t\t\t\tpunch = null;\n\t\t\t}\n\n\t\t\trelated_punch = row[data_field + '_related_data'];\n\n\t\t\tdate = Global/* Global.strToDate */.x.strToDate( data_field, this.full_format );\n\t\t} else if ( grid_id === 'absence_grid' ) {\n\t\t\tcells_array = $this.absence_select_cells_Array;\n\n\t\t\tcolModel = $this.absence_grid.getGridParam( 'colModel' );\n\n\t\t\tdata_field = colModel[cell_index].name;\n\n\t\t\t// Error: Uncaught TypeError: Cannot read property 'punch_info_data' of undefined in interface/html5/#!m=TimeSheet&date=20151220&user_id=null&show_wage=0 line 3761\n\t\t\tif ( row ) {\n\t\t\t\tpunch = row[data_field + '_data'];\n\t\t\t} else {\n\t\t\t\tpunch = null;\n\t\t\t}\n\n\t\t\tdate = Global/* Global.strToDate */.x.strToDate( data_field, this.full_format );\n\n\t\t\t$this.absence_model = true;\n\t\t} else if ( grid_id === 'accumulated_grid' ) {\n\n\t\t\tcells_array = $this.accumulated_time_cells_array;\n\n\t\t\tcolModel = $this.accumulated_time_grid.getGridParam( 'colModel' );\n\n\t\t\tdata_field = colModel[cell_index].name;\n\n\t\t\tif ( row ) {\n\t\t\t\tpunch = row[data_field + '_data'];\n\t\t\t} else {\n\t\t\t\tpunch = null;\n\t\t\t}\n\n\t\t\tdate = Global/* Global.strToDate */.x.strToDate( data_field, this.full_format );\n\t\t} else if ( grid_id === 'premium_grid' ) {\n\n\t\t\tcells_array = $this.premium_cells_array;\n\n\t\t\tcolModel = $this.premium_grid.getGridParam( 'colModel' );\n\n\t\t\tdata_field = colModel[cell_index].name;\n\n\t\t\tif ( row ) {\n\t\t\t\tpunch = row[data_field + '_data'];\n\t\t\t} else {\n\t\t\t\tpunch = null;\n\t\t\t}\n\n\t\t\tdate = Global/* Global.strToDate */.x.strToDate( data_field, this.full_format );\n\n\t\t}\n\n\t\tif ( Global/* Global.isValidDate */.x.isValidDate( date ) == false ) {\n\t\t\t$this.unsetSelectedCells( grid_id );\n\t\t\treturn false;\n\t\t}\n\n\t\tvar info;\n\t\tvar row_tr;\n\t\tvar cell_td;\n\t\t//Clean all select cells first\n\t\tfor ( var i = 0; i < cells_array.length; i++ ) {\n\t\t\tinfo = cells_array[i];\n\t\t\trow_tr = TimeSheetViewController_$( target ).find( '#' + info.row_id );\n\t\t\tTimeSheetViewController_$( target ).find( 'tr' ).removeClass( 'ui-state-highlight' );\n\t\t\tcell_td = TimeSheetViewController_$( row_tr.find( 'td' )[info.cell_index] );\n\t\t\tcell_td.removeClass( 'ui-state-highlight' ).attr( 'aria-selected', false );\n\t\t}\n\n\t\tvar date_str;\n\t\tvar time_stamp_num;\n\n\t\t// Add multiple selectiend_display_date if click cell and hold ctrl or command\n\t\tif ( e.ctrlKey || e.metaKey ) {\n\t\t\tvar found = false;\n\t\t\tfor ( var i = 0; i < cells_array.length; i++ ) {\n\t\t\t\tinfo = cells_array[i];\n\t\t\t\tif ( row_id == info.row_id && cell_index == info.cell_index ) {\n\t\t\t\t\tcells_array.splice( i, 1 );\n\t\t\t\t\tfound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdate_str = date.format();\n\t\t\ttime_stamp_num = date.getTime();\n\n\t\t\tif ( !found ) {\n\t\t\t\tif ( grid_id === 'timesheet_grid' ) {\n\t\t\t\t\tpunch = getCellPunch( row_id, cell_index );\n\t\t\t\t\trelated_punch = getRelatedPunch( row_id, cell_index );\n\t\t\t\t\tcells_array.push( {\n\t\t\t\t\t\trow_id: row_id,\n\t\t\t\t\t\tcell_index: cell_index,\n\t\t\t\t\t\tcell_val: cell_val,\n\t\t\t\t\t\tpunch: punch,\n\t\t\t\t\t\trelated_punch: related_punch,\n\t\t\t\t\t\tdate: date_str,\n\t\t\t\t\t\ttime_stamp_num: time_stamp_num\n\t\t\t\t\t} );\n\n\t\t\t\t\t$this.select_cells_Array = cells_array;\n\t\t\t\t\t$this.select_cells_Array.sort( Global/* Global.m_sort_by */.x.m_sort_by( ['time_stamp_num', 'row_id'] ) );\n\t\t\t\t} else if ( grid_id === 'absence_grid' ) {\n\t\t\t\t\tcells_array.push( {\n\t\t\t\t\t\trow_id: row_id,\n\t\t\t\t\t\tcell_index: cell_index,\n\t\t\t\t\t\tcell_val: cell_val,\n\t\t\t\t\t\tpunch: punch,\n\t\t\t\t\t\tdate: date_str,\n\t\t\t\t\t\ttime_stamp_num: time_stamp_num,\n\t\t\t\t\t\tsrc_object_id: ( row.punch_info_id ) ? row.punch_info_id : null,\n\t\t\t\t\t} );\n\n\t\t\t\t\t$this.absence_select_cells_Array = cells_array;\n\t\t\t\t\t$this.absence_select_cells_Array.sort( Global/* Global.m_sort_by */.x.m_sort_by( ['time_stamp_num', 'row_id'] ) );\n\t\t\t\t} else if ( grid_id === 'premium_grid' ) {\n\t\t\t\t\tcells_array = [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trow_id: row_id,\n\t\t\t\t\t\t\tcell_index: cell_index,\n\t\t\t\t\t\t\tcell_val: cell_val,\n\t\t\t\t\t\t\tdate: date_str,\n\t\t\t\t\t\t\ttime_stamp_num: time_stamp_num\n\t\t\t\t\t\t}\n\t\t\t\t\t];\n\n\t\t\t\t\t$this.premium_cells_array = cells_array;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( e.shiftKey && cells_array.length > 0 ) {\n\t\t\tvar status_id = cells_array[0].status_id; //Get status_id of first punch so we can defaults to that on new.\n\n\t\t\t//cell.row_id is numeric here.\n\t\t\tvar start_row_index = parseInt( cells_array[0].row_id );\n\t\t\tvar start_cell_index = parseInt( cells_array[0].cell_index );\n\n\t\t\tvar end_row_index = row_id;\n\t\t\tvar end_cell_index = cell_index;\n\n\t\t\tif ( start_row_index > end_row_index ) {\n\t\t\t\tvar tmp_row_index = start_row_index;\n\t\t\t\tstart_row_index = end_row_index;\n\t\t\t\tend_row_index = tmp_row_index;\n\t\t\t}\n\n\t\t\tif ( start_cell_index > end_cell_index ) {\n\t\t\t\tvar tmp_cell_index = start_cell_index;\n\t\t\t\tstart_cell_index = end_cell_index;\n\t\t\t\tend_cell_index = tmp_cell_index;\n\t\t\t}\n\n\t\t\tfor ( var i = 0; i < cells_array.length; i++ ) {\n\t\t\t\tinfo = cells_array[i];\n\n\t\t\t\tvar tmp_row_id = parseInt( info.row_id );\n\n\t\t\t\tif ( tmp_row_id < start_row_index ) {\n\t\t\t\t\tstart_row_index = tmp_row_id;\n\t\t\t\t}\n\t\t\t\tif ( tmp_row_id > end_row_index ) {\n\t\t\t\t\tend_row_index = tmp_row_id;\n\t\t\t\t}\n\n\t\t\t\tif ( info.cell_index < start_cell_index ) {\n\t\t\t\t\tstart_cell_index = info.cell_index;\n\t\t\t\t}\n\t\t\t\tif ( info.cell_index > end_cell_index ) {\n\t\t\t\t\tend_cell_index = info.cell_index;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//If the click is inside the existing selection, truncate the existing selection to the click.\n\t\t\t//Check in ScheduleViewController.js for related change\n\t\t\t//Make sure to check for cells_array and cells_array.length before the other checks or when the user clicks into another grid while holding shift, it throws the following error:\n\t\t\t//Cannot read property 'cell_index' of undefined\n\n\t\t\tvar uppermost_row_index = parseInt( cells_array[0].row_id );\n\t\t\tvar lowermost_row_index = parseInt( cells_array[cells_array.length - 1].row_id );\n\t\t\tvar leftmost_cell_index = parseInt( cells_array[0].cell_index );\n\t\t\tvar rightmost_cell_index = parseInt( cells_array[cells_array.length - 1].cell_index );\n\n\t\t\tif ( cells_array && cells_array.length > 0 && cells_array[cells_array.length - 1].cell_index && cells_array[0].cell_index\n\t\t\t\t&& rightmost_cell_index >= cell_index\n\t\t\t\t&& leftmost_cell_index <= cell_index\n\t\t\t\t&& lowermost_row_index >= row_id\n\t\t\t\t&& uppermost_row_index <= row_id ) {\n\t\t\t\tend_row_index = row_id;\n\t\t\t\tend_cell_index = cell_index;\n\t\t\t}\n\n\t\t\t//build cells_array\n\t\t\tcells_array = [];\n\n\t\t\tfor ( var i = start_row_index; i <= end_row_index; i++ ) {\n\t\t\t\tvar r_index = i;\n\t\t\t\tfor ( var j = start_cell_index; j <= end_cell_index; j++ ) {\n\t\t\t\t\tvar c_index = j;\n\n\t\t\t\t\trow_tr = TimeSheetViewController_$( target ).find( 'tr#' + r_index );\n\n\t\t\t\t\tcell_td = TimeSheetViewController_$( row_tr.find( 'td' )[c_index] );\n\n\t\t\t\t\tcell_val = cell_td[0].outerHTML;\n\n\t\t\t\t\tif ( grid_id === 'timesheet_grid' ) {\n\t\t\t\t\t\tpunch = getCellPunch( i, j );\n\t\t\t\t\t\trelated_punch = getRelatedPunch( i, j );\n\n\t\t\t\t\t\tdate = Global/* Global.strToDate */.x.strToDate( data_field, this.full_format );\n\n\t\t\t\t\t\tdate_str = date.format();\n\t\t\t\t\t\ttime_stamp_num = date.getTime();\n\n\t\t\t\t\t\tcells_array.push( {\n\t\t\t\t\t\t\trow_id: r_index,\n\t\t\t\t\t\t\tcell_index: c_index,\n\t\t\t\t\t\t\tcell_val: cell_val,\n\t\t\t\t\t\t\tpunch: punch,\n\t\t\t\t\t\t\tstatus_id: status_id,\n\t\t\t\t\t\t\trelated_punch: related_punch,\n\t\t\t\t\t\t\tdate: date_str,\n\t\t\t\t\t\t\ttime_stamp_num: time_stamp_num\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t} else if ( grid_id === 'absence_grid' ) {\n\t\t\t\t\t\tcolModel = $this.absence_grid.getGridParam( 'colModel' );\n\n\t\t\t\t\t\tdata_field = colModel[c_index].name;\n\n\t\t\t\t\t\tpunch = row[data_field + '_data'];\n\n\t\t\t\t\t\tdate = Global/* Global.strToDate */.x.strToDate( data_field, this.full_format );\n\n\t\t\t\t\t\tdate_str = date.format();\n\t\t\t\t\t\ttime_stamp_num = date.getTime();\n\n\t\t\t\t\t\tcells_array.push( {\n\t\t\t\t\t\t\trow_id: r_index, //see bug #2149\n\t\t\t\t\t\t\t//row_id: r_index.toString(),\n\t\t\t\t\t\t\tcell_index: c_index,\n\t\t\t\t\t\t\tcell_val: cell_val,\n\t\t\t\t\t\t\tpunch: punch,\n\t\t\t\t\t\t\tdate: date_str,\n\t\t\t\t\t\t\ttime_stamp_num: time_stamp_num,\n\t\t\t\t\t\t\tsrc_object_id: ( row.punch_info_id ) ? row.punch_info_id : null,\n\t\t\t\t\t\t} );\n\t\t\t\t\t} else if ( grid_id === 'accumulated_grid' ) {\n\t\t\t\t\t\tcells_array = [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\trow_id: row_id,\n\t\t\t\t\t\t\t\tcell_index: cell_index,\n\t\t\t\t\t\t\t\tcell_val: cell_val,\n\t\t\t\t\t\t\t\tdate: date_str,\n\t\t\t\t\t\t\t\ttime_stamp_num: time_stamp_num\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t];\n\t\t\t\t\t\t$this.accumulated_time_cells_array = cells_array;\n\t\t\t\t\t} else if ( grid_id === 'premium_grid' ) {\n\t\t\t\t\t\tcells_array = [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\trow_id: row_id,\n\t\t\t\t\t\t\t\tcell_index: cell_index,\n\t\t\t\t\t\t\t\tcell_val: cell_val,\n\t\t\t\t\t\t\t\tdate: date_str,\n\t\t\t\t\t\t\t\ttime_stamp_num: time_stamp_num\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t];\n\t\t\t\t\t\t$this.premium_cells_array = cells_array;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( grid_id === 'timesheet_grid' ) {\n\t\t\t\t$this.select_cells_Array = cells_array;\n\t\t\t\t$this.select_cells_Array.sort( Global/* Global.m_sort_by */.x.m_sort_by( ['time_stamp_num', 'row_id'] ) );\n\t\t\t} else if ( grid_id === 'absence_grid' ) {\n\t\t\t\t$this.absence_select_cells_Array = cells_array;\n\t\t\t\t$this.absence_select_cells_Array.sort( Global/* Global.m_sort_by */.x.m_sort_by( ['time_stamp_num', 'row_id'] ) );\n\t\t\t} else if ( grid_id === 'accumulated_grid' ) {\n\t\t\t\t$this.accumulated_time_cells_array = cells_array;\n\t\t\t\t$this.accumulated_time_cells_array.sort( Global/* Global.m_sort_by */.x.m_sort_by( ['time_stamp_num', 'row_id'] ) );\n\t\t\t} else if ( grid_id === 'premium_grid' ) {\n\t\t\t\t$this.premium_cells_array = cells_array;\n\t\t\t\t$this.premium_cells_array.sort( Global/* Global.m_sort_by */.x.m_sort_by( ['time_stamp_num', 'row_id'] ) );\n\t\t\t}\n\n\t\t} else {\n\t\t\tdate_str = date ? date.format() : '';\n\t\t\ttime_stamp_num = date ? date.getTime() : 0;\n\t\t\tif ( grid_id === 'timesheet_grid' ) {\n\t\t\t\t//get the punch data.\n\t\t\t\tpunch = getCellPunch( row_id, cell_index );\n\n\t\t\t\trelated_punch = getRelatedPunch( row_id, cell_index );\n\n\t\t\t\tcells_array = [\n\t\t\t\t\t{\n\t\t\t\t\t\trow_id: row_id,\n\t\t\t\t\t\tcell_index: cell_index,\n\t\t\t\t\t\tcell_val: cell_val,\n\t\t\t\t\t\tpunch: punch,\n\t\t\t\t\t\tstatus_id: ( row && row.status_id ) ? row.status_id : null,\n\t\t\t\t\t\trelated_punch: related_punch,\n\t\t\t\t\t\tdate: date_str,\n\t\t\t\t\t\ttime_stamp_num: time_stamp_num\n\t\t\t\t\t}\n\t\t\t\t];\n\n\t\t\t\t$this.select_cells_Array = cells_array;\n\t\t\t} else if ( grid_id === 'absence_grid' ) {\n\t\t\t\tcells_array = [\n\t\t\t\t\t{\n\t\t\t\t\t\trow_id: row_id,\n\t\t\t\t\t\tcell_index: cell_index,\n\t\t\t\t\t\tcell_val: cell_val,\n\t\t\t\t\t\tpunch: punch,\n\t\t\t\t\t\tdate: date_str,\n\t\t\t\t\t\ttime_stamp_num: time_stamp_num,\n\t\t\t\t\t\tsrc_object_id: ( row.punch_info_id ) ? row.punch_info_id : null,\n\t\t\t\t\t}\n\t\t\t\t];\n\n\t\t\t\t$this.absence_select_cells_Array = cells_array;\n\t\t\t} else if ( grid_id === 'accumulated_grid' ) {\n\t\t\t\tcells_array = [\n\t\t\t\t\t{\n\t\t\t\t\t\trow_id: row_id,\n\t\t\t\t\t\tcell_index: cell_index,\n\t\t\t\t\t\tcell_val: cell_val,\n\t\t\t\t\t\tdate: date_str,\n\t\t\t\t\t\ttime_stamp_num: time_stamp_num\n\t\t\t\t\t}\n\t\t\t\t];\n\n\t\t\t\t$this.accumulated_time_cells_array = cells_array;\n\t\t\t} else if ( grid_id === 'premium_grid' ) {\n\t\t\t\tcells_array = [\n\t\t\t\t\t{\n\t\t\t\t\t\trow_id: row_id,\n\t\t\t\t\t\tcell_index: cell_index,\n\t\t\t\t\t\tcell_val: cell_val,\n\t\t\t\t\t\tdate: date_str,\n\t\t\t\t\t\ttime_stamp_num: time_stamp_num\n\t\t\t\t\t}\n\t\t\t\t];\n\n\t\t\t\t$this.premium_cells_array = cells_array;\n\t\t\t}\n\n\t\t\tif ( date && date.getYear() > 0 ) {\n\t\t\t\tthis.setDatePickerValue( date.format( Global/* Global.getLoginUserDateFormat */.x.getLoginUserDateFormat() ) );\n\t\t\t\tthis.highLightSelectDay( e );\n\t\t\t\tthis.reLoadSubGridsSource();\n\t\t\t}\n\n\t\t\tthis.unsetSelectedCells( grid_id );\n\t\t}\n\n\t\t//now set the selected punches array\n\t\tthis.select_punches_array = [];\n\t\tfor ( var n in cells_array ) {\n\t\t\tif ( cells_array[n].punch ) {\n\t\t\t\tthis.select_punches_array.push( cells_array[n].punch );\n\t\t\t}\n\t\t}\n\t\tthis.setTimesheetGridDragAble();\n\n\t\tfunction getCellPunch( row_id, cell_index ) {\n\t\t\tvar punch = null;\n\t\t\trow = null;\n\t\t\tfor ( var i in $this.timesheet_data_source ) {\n\t\t\t\tif ( $this.timesheet_data_source[i].id == row_id ) {\n\t\t\t\t\trow = $this.timesheet_data_source[i];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( row ) {\n\t\t\t\tcolModel = $this.grid.getGridParam( 'colModel' );\n\t\t\t\tdata_field = colModel[cell_index].name;\n\t\t\t\tpunch = row[data_field + '_data'] ? row[data_field + '_data'] : null;\n\t\t\t}\n\t\t\treturn punch;\n\t\t}\n\n\t\tfunction getRelatedPunch( row_id, cell_index ) {\n\t\t\tvar related_punch = null;\n\t\t\trow = null;\n\t\t\tfor ( var i in $this.timesheet_data_source ) {\n\t\t\t\tif ( $this.timesheet_data_source[i].id == row_id ) {\n\t\t\t\t\trow = $this.timesheet_data_source[i];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t//row = $this.timesheet_data_source[row_id -1 ];\n\t\t\tif ( row ) {\n\t\t\t\tcolModel = $this.grid.getGridParam( 'colModel' );\n\t\t\t\tdata_field = colModel[cell_index].name;\n\t\t\t\trelated_punch = row[data_field + '_related_data'] ? row[data_field + '_related_data'] : null;\n\t\t\t}\n\t\t\treturn related_punch;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tget_selected_punch_array() {\n\t}\n\n\tbuildTimeSheetRequests() {\n\t\tvar request_array = this.full_timesheet_data.request_data;\n\t\tvar len = request_array.length;\n\t\tvar request_row_index = null;\n\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar request = request_array[i];\n\n\t\t\tvar date_string = Global/* Global.strToDate */.x.strToDate( request.date_stamp ).format( this.full_format );\n\n\t\t\tvar row;\n\t\t\t//Build Exception row at bottom\n\t\t\tif ( !request_row_index ) {\n\t\t\t\trow = {};\n\t\t\t\trow.punch_info = TimeSheetViewController_$.i18n._( 'Requests' );\n\t\t\t\trow.user_id = request.user_id;\n\t\t\t\trow[date_string] = request.status;\n\t\t\t\trow[date_string + '_request'] = request;\n\n\t\t\t\trow.type = TimeSheetViewController.REQUEST_ROW;\n\t\t\t\tthis.timesheet_data_source.push( row );\n\t\t\t\trequest_row_index = this.timesheet_data_source.length - 1;\n\t\t\t} else {\n\t\t\t\trow = this.timesheet_data_source[request_row_index];\n\t\t\t\tif ( !Global/* Global.isSet */.x.isSet( row[date_string + '_request'] ) ) {\n\t\t\t\t\trow[date_string] = request.status;\n\t\t\t\t\trow[date_string + '_request'] = request;\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( TimeSheetViewController_$.type( row[date_string + '_request'] ) === 'array' ) {\n\t\t\t\t\t\trow[date_string + '_request'].push( request );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\trow[date_string + '_request'] = [row[date_string + '_request']];\n\t\t\t\t\t\trow[date_string + '_request'].push( request );\n\t\t\t\t\t}\n\n\t\t\t\t\trow[date_string] = calDAndA( row[date_string + '_request'] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\tfunction calDAndA( array ) {\n\t\t\tvar len = array.length;\n\t\t\tvar a = 0;\n\t\t\tvar d = 0;\n\t\t\tvar p = 0;\n\t\t\tvar label = '';\n\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\tvar item = array[i];\n\t\t\t\tif ( item.status_id == 50 ) {\n\t\t\t\t\ta = a + 1;\n\t\t\t\t} else if ( item.status_id == 55 ) {\n\t\t\t\t\td = d + 1;\n\t\t\t\t} else if ( item.status_id == 30 ) {\n\t\t\t\t\tp = p + 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( a > 0 ) {\n\t\t\t\tlabel += ' A: ' + a;\n\t\t\t}\n\t\t\tif ( p > 0 ) {\n\t\t\t\tlabel += ' P: ' + p;\n\t\t\t}\n\t\t\tif ( d > 0 ) {\n\t\t\t\tlabel += ' D: ' + d;\n\t\t\t}\n\t\t\treturn label;\n\t\t}\n\t}\n\n\tbuildTimeSheetExceptions() {\n\t\tvar exception_array = this.full_timesheet_data.exception_data;\n\n\t\tvar len = exception_array.length;\n\t\tvar timesheet_data_source_len = this.timesheet_data_source.length;\n\t\tvar exception_row_index = null;\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar ex = exception_array[i];\n\t\t\tvar date_string = Global/* Global.strToDate */.x.strToDate( ex.date_stamp ).format( this.full_format );\n\t\t\tvar row;\n\t\t\t//Build Exception row at bottom\n\t\t\tif ( !exception_row_index ) {\n\t\t\t\trow = {};\n\t\t\t\trow.punch_info = TimeSheetViewController_$.i18n._( 'Exceptions' );\n\t\t\t\trow.user_id = ex.user_id;\n\t\t\t\trow[date_string] = '';\n\t\t\t\trow[date_string + '_exceptions'] = [ex];\n\n\t\t\t\trow.type = TimeSheetViewController.EXCEPTION_ROW;\n\t\t\t\tthis.timesheet_data_source.push( row );\n\t\t\t\texception_row_index = this.timesheet_data_source.length - 1;\n\t\t\t} else {\n\t\t\t\trow = this.timesheet_data_source[exception_row_index];\n\t\t\t\tif ( !Global/* Global.isSet */.x.isSet( row[date_string + '_exceptions'] ) ) {\n\t\t\t\t\trow[date_string + '_exceptions'] = [ex];\n\t\t\t\t} else {\n\t\t\t\t\trow[date_string + '_exceptions'].push( ex );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar punch;\n\t\t\tvar j;\n\t\t\tif ( !Global/* Global.isFalseOrNull */.x.isFalseOrNull( ex.punch_id ) ) {\n\n\t\t\t\tfor ( var j = 0; j < timesheet_data_source_len; j++ ) {\n\t\t\t\t\trow = this.timesheet_data_source[j];\n\n\t\t\t\t\tif ( !row[date_string] ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( row[date_string + '_data'] ) {\n\t\t\t\t\t\tpunch = row[date_string + '_data'];\n\t\t\t\t\t} else if ( row[date_string + '_related__data'] ) {\n\t\t\t\t\t\tpunch = row[date_string + '_related_data'];\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( punch && punch.id === ex.punch_id && !punch.exception ) {\n\t\t\t\t\t\tpunch.exception = [ex];\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} else if ( !Global/* Global.isFalseOrNull */.x.isFalseOrNull( ex.punch_control_id ) ) {\n\t\t\t\tfor ( var j = 0; j < timesheet_data_source_len; j++ ) {\n\t\t\t\t\trow = this.timesheet_data_source[j];\n\n\t\t\t\t\tif ( !row[date_string] ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( row[date_string + '_data'] ) {\n\t\t\t\t\t\tpunch = row[date_string + '_data'];\n\t\t\t\t\t} else if ( row[date_string + '_related__data'] ) {\n\t\t\t\t\t\tpunch = row[date_string + '_related_data'];\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( punch && punch.punch_control_id === ex.punch_control_id && !punch.exception ) {\n\t\t\t\t\t\tpunch.exception = [ex];\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Make sure Totle_time go to last item\n\tsortAccumulatedTotalData() {\n\n\t\tvar sort_fields = ['order', 'punch_info'];\n\t\tthis.accumulated_total_grid_source.sort( Global/* Global.m_sort_by */.x.m_sort_by( sort_fields ) );\n\t}\n\n\t// Make sure total time go to last item\n\tsortAccumulatedTimeData() {\n\n\t\tvar sort_fields = ['order', 'punch_info'];\n\t\tthis.accumulated_time_source.sort( Global/* Global.m_sort_by */.x.m_sort_by( sort_fields ) );\n\t}\n\n\treLoadSubGridsSource( force ) {\n\t\t// Error: Uncaught TypeError: Cannot read property 'pay_period_id' of undefined in interface/html5/#!m=TimeSheet&date=20151214&user_id=null&show_wage=0 line 4290\n\t\tif ( !this.full_timesheet_data || !this.full_timesheet_data.timesheet_verify_data ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !force ) {\n\t\t\tif ( this.full_timesheet_data.timesheet_verify_data.pay_period_id === this.pay_period_map[this.getSelectDate()] ||\n\t\t\t\t( !Global/* Global.isSet */.x.isSet( this.full_timesheet_data.timesheet_verify_data.pay_period_id ) && !this.pay_period_map[this.getSelectDate()] )\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.accumulated_time_source_map = {};\n\t\tthis.branch_source_map = {};\n\t\tthis.department_source_map = {};\n\t\tthis.job_source_map = {};\n\t\tthis.job_item_source_map = {};\n\t\tthis.punch_tag_source_map = {};\n\t\tthis.premium_source_map = {};\n\t\tthis.accumulated_total_grid_source_map = {};\n\t\tthis.accumulated_time_source = [];\n\t\tthis.branch_source = [];\n\t\tthis.department_source = [];\n\t\tthis.job_source = [];\n\t\tthis.job_item_source = [];\n\t\tthis.punch_tag_source = [];\n\t\tthis.premium_source = [];\n\t\tthis.accumulated_total_grid_source = [];\n\t\tthis.verification_grid_source = [];\n\t\tvar $this = this;\n\t\tvar start_date_string = this.start_date_picker.getValue();\n\t\tvar user_id = this.getSelectEmployee();\n\t\tthis.api_timesheet.getTimeSheetTotalData( user_id, start_date_string, {\n\t\t\tonResult: function( result ) {\n\t\t\t\t$this.onReloadSubGridResult( result );\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tonReloadSubGridResult( result ) {\n\t\tvar $this = this;\n\t\tresult = result.getResult();\n\t\t$this.full_timesheet_data.accumulated_user_date_total_data = result.accumulated_user_date_total_data;\n\t\t$this.full_timesheet_data.meal_and_break_total_data = result.meal_and_break_total_data;\n\t\t$this.full_timesheet_data.pay_period_accumulated_user_date_total_data = result.pay_period_accumulated_user_date_total_data;\n\t\t$this.full_timesheet_data.timesheet_verify_data = result.timesheet_verify_data;\n\t\t$this.full_timesheet_data.pay_period_data = result.pay_period_data;\n\t\t$this.timesheet_verify_data = $this.full_timesheet_data.timesheet_verify_data;\n\n\t\t$this.buildSubGridsSource();\n\n\t\t$this.buildAccumulatedTotalGrid();\n\t\t$this.buildVerificationGridSource();\n\n\t\t$this.accumulated_time_grid.setData( $this.accumulated_time_source, false );\n\t\t$this.branch_grid.setData( $this.branch_source, false );\n\t\t$this.department_grid.setData( $this.department_source, false );\n\t\t$this.job_grid.setData( $this.job_source, false );\n\t\t$this.job_item_grid.setData( $this.job_item_source, false );\n\t\t$this.punch_tag_grid.setData( $this.punch_tag_source, false );\n\t\t$this.premium_grid.setData( $this.premium_source, false );\n\n\t\tif ( $this.accumulated_total_grid_source.length === 0 ) {\n\t\t\t$this.accumulated_total_grid_source.push();\n\t\t}\n\t\t$this.accumulated_total_grid.setData( $this.accumulated_total_grid_source, false );\n\n\t\t$this.punch_note_grid.setData( $this.punch_note_grid_source, false );\n\t\t$this.verification_grid.setData( $this.verification_grid_source, false );\n\n\t\t$this.setGridSize();\n\t}\n\n\tsetDefaultMenuEditIcon( context_btn, grid_selected_length ) {\n\t\tlet p_id = this.getPunchPermissionType();\n\n\t\tif ( !this.editPermissionValidate( p_id ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( grid_selected_length === 1 && this.editOwnerOrChildPermissionValidate( p_id ) && ( this.getPunchMode() === 'punch' || p_id === 'absence' ) ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\tif( grid_selected_length !== 0 ) {\n\t\t\t\t// This ensures the edit icon is still visible when nothing is selected, but should still be disabled. (to keep consistency with old design)\n\t\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t\t}\n\t\t}\n\t}\n\n\tsetEditMenuAddIcon( context_btn ) {\n\t\tlet p_id = this.getPunchPermissionType();\n\n\t\tif ( !this.addPermissionValidate( p_id ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( this.is_add == true ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuDeleteIcon( context_btn ) {\n\t\tlet p_id = this.getPunchPermissionType();\n\n\t\tif ( !this.deletePermissionValidate( p_id ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( ( !this.current_edit_record || !this.current_edit_record.id ) || !this.deleteOwnerOrChildPermissionValidate( p_id ) ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuDeleteAndNextIcon( context_btn ) {\n\t\tlet p_id = this.getPunchPermissionType();\n\n\t\tif ( !this.deletePermissionValidate( p_id ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( ( !this.current_edit_record || !this.current_edit_record.id ) || !this.deleteOwnerOrChildPermissionValidate( p_id ) ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuEditIcon( context_btn, pId ) {\n\t\tlet p_id = this.getPunchPermissionType();\n\n\t\tif ( !this.editPermissionValidate( p_id ) || this.edit_only_mode || this.is_mass_editing ) {\n\t\t\t//Not shown in edit only mode or mass edit. Mass edit should only show mass edit (need to set that part in mass edit icon).\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\n\t\tif ( !this.is_viewing || !this.editOwnerOrChildPermissionValidate( p_id ) ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuDeleteIcon( context_btn, grid_selected_length ) {\n\t\tlet p_id = this.getPunchPermissionType();\n\n\t\tif ( !this.deletePermissionValidate( p_id ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( grid_selected_length >= 1 && this.deleteOwnerOrChildPermissionValidate( p_id ) && ( this.getPunchMode() === 'punch' || p_id === 'absence' ) ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuDeleteAndNextIcon( context_btn, grid_selected_length ) {\n\t\tlet p_id = this.getPunchPermissionType();\n\n\t\tif ( !this.deletePermissionValidate( p_id ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetDefaultMenuViewIcon( context_btn, grid_selected_length ) {\n\t\tlet p_id = this.getPunchPermissionType();\n\n\t\tif ( !this.viewPermissionValidate( p_id ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( grid_selected_length === 1 && this.viewOwnerOrChildPermissionValidate() && ( this.getPunchMode() === 'punch' || p_id === 'absence' ) ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuAddPunchIcon( context_btn, grid_selected_length ) {\n\t\tlet p_id = 'punch';\n\n\t\tif ( !this.addPermissionValidate( p_id ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\n\t\tif ( this.getPunchMode() === 'manual' && p_id !== 'absence' ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuAddAbsenceIcon( context_btn, grid_selected_length ) {\n\t\tlet p_id = 'absence';\n\n\t\tif ( !this.addPermissionValidate( p_id ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\n\t\tif ( this.getPunchMode() === 'manual' && p_id !== 'absence' ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuSaveIcon( context_btn, grid_selected_length ) {\n\t\tlet p_id = this.getPunchPermissionType();\n\n\t\tif ( ( !this.addPermissionValidate( p_id ) && !this.editPermissionValidate( p_id ) ) ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\t\tif ( this.getPunchMode() === 'manual' ) {\n\t\t\tif ( ( !this.addPermissionValidate( p_id ) && !this.editPermissionValidate( p_id ) ) ) {\n\t\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t\t}\n\t\t\tif ( this.is_saving_manual_grid ) {\n\t\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\t}\n\t\t} else {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tbuildAccmulatedOrderMap( total ) {\n\n\t\tif ( !total ) {\n\t\t\treturn;\n\t\t}\n\t\tfor ( var key in total ) {\n\n\t\t\tfor ( var key1 in total[key] ) {\n\t\t\t\tthis.accmulated_order_map[key1] = total[key][key1].order;\n\t\t\t}\n\n\t\t}\n\t}\n\n\tbuildSubGridsSource() {\n\n\t\tvar accumulated_user_date_total_data = this.full_timesheet_data.accumulated_user_date_total_data;\n\t\tvar meal_and_break_total_data = this.full_timesheet_data.meal_and_break_total_data;\n\t\tvar pay_period_accumulated_user_date_total_data = this.full_timesheet_data.pay_period_accumulated_user_date_total_data;\n\n\t\tthis.accmulated_order_map = {};\n\n\t\t// Save the order, will do sort after all data prepared.\n\t\tif ( accumulated_user_date_total_data.total ) {\n\t\t\tthis.buildAccmulatedOrderMap( accumulated_user_date_total_data.total );\n\t\t}\n\n\t\tif ( pay_period_accumulated_user_date_total_data ) {\n\t\t\tthis.buildAccmulatedOrderMap( pay_period_accumulated_user_date_total_data );\n\t\t}\n\n\t\t//Build Accumulated Total Grid Pay_period column data\n\t\tvar accumulated_time = pay_period_accumulated_user_date_total_data.accumulated_time;\n\t\tvar premium_time = pay_period_accumulated_user_date_total_data.premium_time;\n\t\tvar absence_time = pay_period_accumulated_user_date_total_data.absence_time_taken;\n\n\t\tif ( Global/* Global.isSet */.x.isSet( accumulated_time ) ) {\n\t\t\tthis.buildSubGridsData( accumulated_time, 'pay_period', this.accumulated_total_grid_source_map, this.accumulated_total_grid_source, 'accumulated_time' );\n\t\t} else {\n\t\t\taccumulated_time = { total: { label: TimeSheetViewController_$.i18n._( 'Total Time' ), total_time: '0' } };\n\t\t\tthis.buildSubGridsData( accumulated_time, 'pay_period', this.accumulated_total_grid_source_map, this.accumulated_total_grid_source, 'accumulated_time' );\n\t\t}\n\n\t\tif ( Global/* Global.isSet */.x.isSet( premium_time ) ) {\n\t\t\tthis.buildSubGridsData( premium_time, 'pay_period', this.accumulated_total_grid_source_map, this.accumulated_total_grid_source, 'premium_time' );\n\t\t}\n\n\t\tif ( Global/* Global.isSet */.x.isSet( absence_time ) ) {\n\t\t\tthis.buildSubGridsData( absence_time, 'pay_period', this.accumulated_total_grid_source_map, this.accumulated_total_grid_source, 'absence_time' );\n\t\t}\n\n\t\t//Build Accumulated Total Grid Pay_period column data end\n\n\t\tvar column_len = this.timesheet_columns.length;\n\t\taccumulated_time = { total: { label: TimeSheetViewController_$.i18n._( 'Total Time' ), total_time: '0' } };\n\t\tvar date_string;\n\t\tvar date;\n\n\t\t//Start on column that is right before the 7 days of the week.\n\t\tvar start = ( column_len - 7 - 1 );\n\t\tfor ( var i = start; i < column_len; i++ ) {\n\t\t\tthis.buildSubGridsData( accumulated_time, date_string, this.accumulated_time_source_map, this.accumulated_time_source, 'accumulated_time' );\n\t\t}\n\t\tthis.buildSubGridsData( accumulated_time, 'week', this.accumulated_total_grid_source_map, this.accumulated_total_grid_source, 'accumulated_time' );\n\n\t\tfor ( var key in accumulated_user_date_total_data ) {\n\n\t\t\t//Build Accumulated Total Grid week column data\n\t\t\tif ( key === 'total' ) {\n\t\t\t\tvar total_result = accumulated_user_date_total_data.total;\n\t\t\t\taccumulated_time = total_result.accumulated_time;\n\t\t\t\tpremium_time = total_result.premium_time;\n\t\t\t\tabsence_time = total_result.absence_time_taken;\n\n\t\t\t\tif ( Global/* Global.isSet */.x.isSet( accumulated_time ) ) {\n\n\t\t\t\t\tthis.buildSubGridsData( accumulated_time, 'week', this.accumulated_total_grid_source_map, this.accumulated_total_grid_source, 'accumulated_time' );\n\t\t\t\t}\n\n\t\t\t\tif ( Global/* Global.isSet */.x.isSet( premium_time ) ) {\n\t\t\t\t\tthis.buildSubGridsData( premium_time, 'week', this.accumulated_total_grid_source_map, this.accumulated_total_grid_source, 'premium_time' );\n\t\t\t\t}\n\n\t\t\t\tif ( Global/* Global.isSet */.x.isSet( absence_time ) ) {\n\t\t\t\t\tthis.buildSubGridsData( absence_time, 'week', this.accumulated_total_grid_source_map, this.accumulated_total_grid_source, 'absence_time' );\n\t\t\t\t}\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t//Build Accumulated Total Grid week column data end\n\t\t\t//Build all sub grids data\n\t\t\t//Error: Uncaught TypeError: Cannot read property 'format' of null in interface/html5/#!m=TimeSheet&date=20151117&user_id=35367&show_wage=0 line 4478\n\t\t\tdate = Global/* Global.strToDate */.x.strToDate( key );\n\t\t\tif ( !date ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tdate_string = date.format( this.full_format );\n\n\t\t\t//Error: Uncaught TypeError: Cannot read property 'accumulated_time' of undefined\n\t\t\tif ( typeof accumulated_user_date_total_data[key] != 'undefined' ) {\n\t\t\t\taccumulated_time = accumulated_user_date_total_data[key].accumulated_time;\n\t\t\t\tvar branch_time = accumulated_user_date_total_data[key].branch_time;\n\t\t\t\tvar department_time = accumulated_user_date_total_data[key].department_time;\n\t\t\t\tvar job_time = accumulated_user_date_total_data[key].job_time;\n\t\t\t\tvar job_item_time = accumulated_user_date_total_data[key].job_item_time;\n\t\t\t\tvar punch_tag_time = accumulated_user_date_total_data[key].punch_tag_time;\n\t\t\t\tpremium_time = accumulated_user_date_total_data[key].premium_time;\n\t\t\t} else {\n\t\t\t\tDebug.Text( 'ERROR: accumulated_user_date_total_data[key] is null or undefined!', 'TimesheetViewController.js', 'TimesheetViewController', 'buildSubGridsSource', 1 );\n\t\t\t}\n\n\t\t\tif ( Global/* Global.isSet */.x.isSet( accumulated_time ) ) {\n\t\t\t\tthis.buildSubGridsData( accumulated_time, date_string, this.accumulated_time_source_map, this.accumulated_time_source, 'accumulated_time' );\n\t\t\t}\n\n\t\t\tif ( Global/* Global.isSet */.x.isSet( branch_time ) ) {\n\n\t\t\t\tthis.buildSubGridsData( branch_time, date_string, this.branch_source_map, this.branch_source, 'branch_time' );\n\t\t\t}\n\n\t\t\tif ( Global/* Global.isSet */.x.isSet( department_time ) ) {\n\n\t\t\t\tthis.buildSubGridsData( department_time, date_string, this.department_source_map, this.department_source, 'department_time' );\n\t\t\t}\n\n\t\t\tif ( Global/* Global.isSet */.x.isSet( job_time ) ) {\n\n\t\t\t\tthis.buildSubGridsData( job_time, date_string, this.job_source_map, this.job_source, 'job_time' );\n\t\t\t}\n\n\t\t\tif ( Global/* Global.isSet */.x.isSet( job_item_time ) ) {\n\n\t\t\t\tthis.buildSubGridsData( job_item_time, date_string, this.job_item_source_map, this.job_item_source, 'job_item_time' );\n\t\t\t}\n\n\t\t\tif ( Global/* Global.isSet */.x.isSet( punch_tag_time ) ) {\n\n\t\t\t\tthis.buildSubGridsData( punch_tag_time, date_string, this.punch_tag_source_map, this.punch_tag_source, 'punch_tag_time' );\n\t\t\t}\n\n\t\t\tif ( Global/* Global.isSet */.x.isSet( premium_time ) ) {\n\n\t\t\t\tthis.buildSubGridsData( premium_time, date_string, this.premium_source_map, this.premium_source, 'premium_time' );\n\t\t\t}\n\n\t\t}\n\n\t\tthis.sortAccumulatedTotalData();\n\t\tthis.sortAccumulatedTimeData();\n\n\t\tif ( Global/* Global.isSet */.x.isSet( meal_and_break_total_data ) ) {\n\n\t\t\tfor ( var key in meal_and_break_total_data ) {\n\t\t\t\t// Error: Uncaught TypeError: Cannot read property 'format' of null in interface/html5/#!m=TimeSheet&date=20151119&user_id=55338&show_wage=0 line 4527\n\t\t\t\tdate = Global/* Global.strToDate */.x.strToDate( key );\n\t\t\t\tif ( !date ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tdate_string = date.format( this.full_format );\n\n\t\t\t\tthis.buildBreakAndLunchData( meal_and_break_total_data[key], date_string );\n\n\t\t\t}\n\n\t\t}\n\t}\n\n\tbuildBreakAndLunchData( array, date_string ) {\n\t\tvar row;\n\t\tfor ( var key in array ) {\n\t\t\tif ( !this.accumulated_time_source_map[key] ) {\n\t\t\t\trow = {};\n\t\t\t\trow.punch_info = array[key].break_name;\n\t\t\t\tarray[key].key = key;\n\t\t\t\trow[date_string] = Global/* Global.getTimeUnit */.x.getTimeUnit( array[key].total_time ) + ' (' + array[key].total_breaks + ')';\n\t\t\t\trow[date_string + '_data'] = array[key];\n\t\t\t\tthis.timesheet_data_source.push( row );\n\t\t\t\tthis.accumulated_time_source_map[key] = row;\n\t\t\t} else {\n\t\t\t\trow = this.accumulated_time_source_map[key];\n\t\t\t\tif ( !row[date_string] ) {\n\t\t\t\t\tarray[key].key = key;\n\t\t\t\t\trow[date_string] = Global/* Global.getTimeUnit */.x.getTimeUnit( array[key].total_time ) + ' (' + array[key].total_breaks + ')';\n\n\t\t\t\t\trow[date_string + '_data'] = array[key];\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\t}\n\n\taddCellCount( key ) {\n\t\tswitch ( key ) {\n\t\t\tcase 'branch_time':\n\t\t\t\tthis.branch_cell_count = this.branch_cell_count + 1;\n\t\t\t\tbreak;\n\t\t\tcase 'department_time':\n\t\t\t\tthis.department_cell_count = this.department_cell_count + 1;\n\t\t\t\tbreak;\n\n\t\t\tcase 'premium_time':\n\t\t\t\tthis.premium_cell_count = this.premium_cell_count + 1;\n\t\t\t\tbreak;\n\t\t\tcase 'job_time':\n\t\t\t\tthis.job_cell_count = this.job_cell_count + 1;\n\t\t\t\tbreak;\n\t\t\tcase 'job_item_time':\n\t\t\t\tthis.task_cell_count = this.task_cell_count + 1;\n\t\t\t\tbreak;\n\t\t\tcase 'punch_tag_time':\n\t\t\t\tthis.punch_tag_cell_count = this.punch_tag_cell_count + 1;\n\t\t\t\tbreak;\n\n\t\t}\n\t}\n\n\tbuildSubGridsData( array, date_string, map, result_array, parent_key ) {\n\t\tvar row;\n\t\tvar marked_regular_row = false; //Only mark the first regular time row, as thats where the bold top-line is going to go.\n\t\tfor ( var key in array ) {\n\t\t\tif ( !map[key] ) {\n\t\t\t\trow = {};\n\t\t\t\trow.parent_key = parent_key;\n\t\t\t\trow.key = key;\n\n\t\t\t\tif ( parent_key === 'accumulated_time' ) {\n\n\t\t\t\t\tif ( key === 'total' || key === 'worked_time' ) {\n\t\t\t\t\t\trow.type = TimeSheetViewController.TOTAL_ROW;\n\t\t\t\t\t} else if ( marked_regular_row == false && key.indexOf( 'regular_time' ) === 0 ) {\n\t\t\t\t\t\trow.type = TimeSheetViewController.REGULAR_ROW;\n\t\t\t\t\t\tmarked_regular_row = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\trow.type = TimeSheetViewController.ACCUMULATED_TIME_ROW;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( array[key].override ) {\n\t\t\t\t\t\trow.is_override_row = true;\n\t\t\t\t\t}\n\n\t\t\t\t} else if ( parent_key === 'premium_time' ) {\n\t\t\t\t\trow.type = TimeSheetViewController.PREMIUM_ROW;\n\t\t\t\t}\n\n\t\t\t\tif ( this.accmulated_order_map[key] ) {\n\t\t\t\t\trow.order = this.accmulated_order_map[key];\n\t\t\t\t}\n\n\t\t\t\trow.punch_info = array[key].label;\n\n\t\t\t\tvar key_array = key.split( '_' );\n\t\t\t\tvar no_id = false;\n\t\t\t\tif ( key_array.length > 1 && key_array[1] == '0' ) {\n\t\t\t\t\tno_id = true;\n\t\t\t\t}\n\n\t\t\t\tarray[key].key = key;\n\t\t\t\trow[date_string] = Global/* Global.getTimeUnit */.x.getTimeUnit( array[key].total_time );\n\t\t\t\trow[date_string + '_data'] = array[key];\n\n\t\t\t\t//if id == 0, put the row as first row.\n\t\t\t\tif ( no_id ) {\n\t\t\t\t\tresult_array.unshift( row );\n\t\t\t\t} else {\n\t\t\t\t\tresult_array.push( row );\n\t\t\t\t}\n\n\t\t\t\tmap[key] = row;\n\t\t\t} else {\n\t\t\t\trow = map[key];\n\t\t\t\tif ( row[date_string] && key === 'total' ) { //Override total cell data since we set all to 00:00 at beginning\n\t\t\t\t\tarray[key].key = key;\n\t\t\t\t\trow[date_string] = Global/* Global.getTimeUnit */.x.getTimeUnit( array[key].total_time );\n\t\t\t\t\trow[date_string + '_data'] = array[key];\n\n\t\t\t\t\tif ( row.parent_key === 'accumulated_time' ) {\n\t\t\t\t\t\tif ( array[key].override ) {\n\t\t\t\t\t\t\trow.is_override_row = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tarray[key].key = key;\n\t\t\t\t\trow[date_string] = Global/* Global.getTimeUnit */.x.getTimeUnit( array[key].total_time );\n\t\t\t\t\trow[date_string + '_data'] = array[key];\n\n\t\t\t\t\tif ( row.parent_key === 'accumulated_time' ) {\n\t\t\t\t\t\tif ( array[key].override ) {\n\t\t\t\t\t\t\trow.is_override_row = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tthis.addCellCount( parent_key );\n\t\t}\n\t}\n\n\ttimeSheetVerifyPermissionValidate() {\n\t\tif ( PermissionManager.validate( 'punch', 'verify_time_sheet' ) &&\n\t\t\tthis.timesheet_verify_data.hasOwnProperty( 'pay_period_verify_type_id' ) &&\n\t\t\tthis.timesheet_verify_data.pay_period_verify_type_id != 10 ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tbuildVerificationGridSource() {\n\t\tthis.verification_grid_source = [];\n\t\tvar $this = this;\n\t\tvar verify_action_bar = TimeSheetViewController_$( this.el ).find( '.verification-action-bar' );\n\t\tvar verify_grid_div = TimeSheetViewController_$( this.el ).find( '.verification-grid-div' );\n\t\tvar verify_btn = TimeSheetViewController_$( this.el ).find( '.verify-button' );\n\t\tvar verify_title = TimeSheetViewController_$( this.el ).find( '.verification-grid-title' );\n\t\tvar verify_des = TimeSheetViewController_$( this.el ).find( '.verify-description' );\n\n\t\tif ( this.timeSheetVerifyPermissionValidate() &&\n\t\t\tGlobal/* Global.isSet */.x.isSet( this.timesheet_verify_data.pay_period_id ) &&\n\t\t\tGlobal/* Global.isSet */.x.isSet( this.timesheet_verify_data.pay_period_verify_type_id ) &&\n\t\t\tthis.timesheet_verify_data.pay_period_verify_type_id !== '10' ) {\n\n\t\t\tif ( !this.timesheet_verify_data.display_verify_button ) {\n\t\t\t\tverify_btn.css( 'display', 'none' );\n\t\t\t\tverify_title.css( 'display', 'none' );\n\t\t\t} else {\n\t\t\t\tverify_btn.css( 'display', 'inline-block' );\n\t\t\t\tverify_title.css( 'display', 'block' );\n\t\t\t}\n\n\t\t\tverify_grid_div.css( 'display', 'block' );\n\t\t\tverify_des.text( this.timesheet_verify_data.verification_status_display );\n\n\t\t\tif ( this.timesheet_verify_data.verification_box_color ) {\n\t\t\t\tverify_action_bar.css( 'background', this.timesheet_verify_data.verification_box_color );\n\t\t\t} else {\n\t\t\t\tverify_action_bar.css( 'background', '#ffffff' );\n\t\t\t}\n\n\t\t\tverify_btn.unbind( 'click' ).bind( 'click', function() {\n\t\t\t\tTAlertManager.showConfirmAlert( $this.timesheet_verify_data.verification_confirmation_message, '', function( flag ) {\n\n\t\t\t\t\tif ( flag ) {\n\t\t\t\t\t\t$this.api_timesheet.verifyTimeSheet( $this.getSelectEmployee(), $this.timesheet_verify_data.pay_period_id,\n\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tonResult: function( result ) {\n\n\t\t\t\t\t\t\t\t\tif ( result.isValid() ) {\n\t\t\t\t\t\t\t\t\t\t$this.search();\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tTAlertManager.showErrorAlert( result );\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\t\t\t} );\n\n\t\t} else {\n\n\t\t\tverify_btn.css( 'display', 'none' );\n\t\t\tverify_grid_div.css( 'display', 'none' );\n\t\t\treturn;\n\n\t\t}\n\n\t\tvar verification_data = this.timesheet_verify_data.verification_window_dates.start + ' ' + TimeSheetViewController_$.i18n._( 'to' ) + ' ' + this.timesheet_verify_data.verification_window_dates.end;\n\n\t\tvar pay_period_data = this.pay_period_header;\n\n\t\tthis.verification_grid_source.push( { pay_period: pay_period_data, verification: verification_data } );\n\n\t\t//This can be called by clicking on a different date column header, or using the top right refresh icon, so not all grids are resized at that time necessarily.\n\t\t$this.setGridHeight( 'verification_grid' );\n\t}\n\n\tbuildPunchNoteGridSource() {\n\t\tthis.punch_note_grid_source = [];\n\t\tvar punch_array = this.full_timesheet_data.punch_data;\n\t\tvar absence_array = this.full_timesheet_data.user_date_total_data;\n\t\tvar len = punch_array.length;\n\t\tvar len1 = absence_array.length;\n\t\tvar last_control_id = '';\n\t\tvar date;\n\t\tvar date_string;\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar punch = punch_array[i];\n\t\t\tdate = Global/* Global.strToDate */.x.strToDate( punch.date_stamp );\n\t\t\tdate_string = date.format();\n\t\t\tif ( punch.note && punch.punch_control_id !== last_control_id ) {\n\t\t\t\tthis.punch_note_account = this.punch_note_account + 1;\n\t\t\t\tthis.punch_note_grid_source.push( { note: date_string + ' @ ' + punch.punch_time + ': ' + punch.note.replace( /\\n/g, ' ' ) } );\n\t\t\t\tlast_control_id = punch.punch_control_id;\n\t\t\t}\n\t\t}\n\t\tfor ( var x = 0; x < len1; x++ ) {\n\t\t\tvar absence = absence_array[x];\n\t\t\tdate = Global/* Global.strToDate */.x.strToDate( absence.date_stamp );\n\t\t\tdate_string = date.format();\n\t\t\tif ( absence.note ) {\n\t\t\t\tthis.punch_note_account = this.punch_note_account + 1;\n\t\t\t\tthis.punch_note_grid_source.push( { note: date_string + ' @ ' + Global/* Global.getTimeUnit */.x.getTimeUnit( absence.total_time ) + ': ' + absence.note.replace( /\\n/g, ' ' ) } );\n\t\t\t}\n\t\t}\n\t}\n\n\tbuildAbsenceSource() {\n\n\t\tvar map = {};\n\t\tthis.absence_source = [];\n\t\tthis.absence_original_source = [];\n\t\tvar absence_array = this.full_timesheet_data.user_date_total_data;\n\t\tvar len = absence_array.length;\n\t\tvar row;\n\t\tvar row_id_counter = 1;\n\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar absence = absence_array[i];\n\n\t\t\tif ( absence.object_type_id != 50 ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tthis.absence_original_source.push( absence );\n\t\t\tvar date = Global/* Global.strToDate */.x.strToDate( absence.date_stamp );\n\t\t\tvar date_string = date.format( this.full_format );\n\t\t\tvar key = absence.src_object_id + '-' + absence.pay_code_id;\n\n\t\t\tif ( !map[key] ) {\n\t\t\t\trow = {};\n\t\t\t\trow.id = row_id_counter;\n\t\t\t\trow.type = TimeSheetViewController.ABSENCE_ROW;\n\t\t\t\trow.punch_info = absence.name; //Was: absence.absence_policy\n\t\t\t\trow.punch_info_id = absence.src_object_id;\n\t\t\t\trow.user_id = absence.user_id;\n\t\t\t\trow[date_string] = Global/* Global.getTimeUnit */.x.getTimeUnit( absence.total_time );\n\t\t\t\trow[date_string + '_data'] = absence;\n\t\t\t\tthis.absence_source.push( row );\n\t\t\t\tmap[key] = row;\n\t\t\t} else {\n\t\t\t\trow = map[key];\n\t\t\t\tif ( row[date_string] ) {\n\t\t\t\t\trow = {};\n\t\t\t\t\trow.id = row_id_counter;\n\t\t\t\t\trow.type = TimeSheetViewController.ABSENCE_ROW;\n\t\t\t\t\trow.punch_info = absence.name; //Was: absence.absence_policy\n\t\t\t\t\trow.punch_info_id = absence.src_object_id;\n\t\t\t\t\trow.user_id = absence.user_id;\n\t\t\t\t\trow[date_string] = Global/* Global.getTimeUnit */.x.getTimeUnit( absence.total_time );\n\n\t\t\t\t\trow[date_string + '_data'] = absence;\n\t\t\t\t\tthis.absence_source.push( row );\n\t\t\t\t\tmap[key] = row;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis.lastDayIsOverride( date, row, absence );\n\t\t\t\t\trow[date_string] = Global/* Global.getTimeUnit */.x.getTimeUnit( absence.total_time );\n\t\t\t\t\trow[date_string + '_data'] = absence;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trow_id_counter++;\n\n\t\t\tthis.absence_cell_count = this.absence_cell_count + 1;\n\n\t\t}\n\n\t\tif ( this.absence_source.length === 0 ) {\n\t\t\trow = {};\n\t\t\trow.id = 1;\n\t\t\trow.punch_info = '';\n\t\t\trow.user_id = this.getSelectEmployee();\n\t\t\tthis.absence_source.push( row );\n\t\t}\n\t}\n\n\tlastDayIsOverride( current_date, row, current_data ) {\n\n\t\tvar last_date = new Date( new Date( current_date.getTime() ).setDate( current_date.getDate() - 1 ) );\n\n\t\tvar date_str = last_date.format( this.full_format );\n\n\t\tvar data = row[date_str + '_data'];\n\n\t\tif ( data && data.override && current_data.src_object_id === data.src_object_id ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tbuildTimeSheetSource() {\n\t\tthis.select_punches_array = [];\n\t\tthis.timesheet_data_source = [];\n\n\t\tvar punch_array = this.full_timesheet_data.punch_data;\n\t\tvar len = punch_array.length;\n\t\tvar row;\n\t\tvar new_row;\n\t\tvar row_id_counter = 1;\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar punch = punch_array[i];\n\t\t\t// Error: TypeError: Global.strToDate(...) is null in interface/html5/framework/jquery.min.js?v=9.0.1-20151022-081724 line 2 > eval line 4869\n\t\t\t// Punch must have a date\n\t\t\tif ( !punch.date_stamp ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvar date = Global/* Global.strToDate */.x.strToDate( punch.date_stamp );\n\t\t\tvar date_string = date.format( this.full_format );\n\n\t\t\tvar punch_status_id = punch.status_id;\n\n\t\t\t//row 1.\n\t\t\tif ( i === 0 ) {\n\t\t\t\trow = {};\n\t\t\t\trow.id = row_id_counter;\n\t\t\t\trow_id_counter++;\n\t\t\t\trow.punch_info = punch.status;\n\t\t\t\trow.status_id = punch_status_id;\n\t\t\t\trow.user_id = punch.user_id;\n\t\t\t\trow[date_string] = punch.punch_time;\n\t\t\t\trow[date_string + '_data'] = punch;\n\t\t\t\trow[date_string + '_related_data'] = null;\n\t\t\t\trow.status_id = punch_status_id;\n\t\t\t\trow.type = TimeSheetViewController.PUNCH_ROW;\n\t\t\t\tthis.timesheet_data_source.push( row );\n\n\t\t\t\tif ( punch_status_id == 10 ) {\n\n\t\t\t\t\tvar our_row = {};\n\t\t\t\t\tour_row.punch_info = TimeSheetViewController_$.i18n._( 'Out' );\n\t\t\t\t\tour_row.user_id = punch.user_id;\n\t\t\t\t\tour_row[date_string] = '';\n\t\t\t\t\tour_row[date_string + '_data'] = null;\n\t\t\t\t\tour_row[date_string + '_related_data'] = punch;\n\t\t\t\t\tour_row.status_id = 20;\n\t\t\t\t\tour_row.type = TimeSheetViewController.PUNCH_ROW;\n\t\t\t\t\tour_row.id = row_id_counter;\n\t\t\t\t\trow_id_counter++;\n\t\t\t\t\tthis.timesheet_data_source.push( our_row );\n\n\t\t\t\t} else {\n\t\t\t\t\tnew_row = {};\n\t\t\t\t\tnew_row.punch_info = TimeSheetViewController_$.i18n._( 'In' );\n\t\t\t\t\tnew_row.user_id = punch.user_id;\n\t\t\t\t\tnew_row[date_string] = '';\n\t\t\t\t\tnew_row[date_string + '_data'] = null;\n\t\t\t\t\tnew_row[date_string + '_related_data'] = punch;\n\t\t\t\t\tnew_row.status_id = 10;\n\t\t\t\t\tnew_row.type = TimeSheetViewController.PUNCH_ROW;\n\t\t\t\t\tnew_row.id = row_id_counter;\n\t\t\t\t\trow_id_counter++;\n\t\t\t\t\tthis.timesheet_data_source.splice( this.timesheet_data_source.length - 1, 0, new_row );\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tvar find_position = false;\n\t\t\t\tvar timesheet_data_source_len = this.timesheet_data_source.length;\n\t\t\t\tfor ( var j = 0; j < timesheet_data_source_len; j++ ) {\n\t\t\t\t\trow = this.timesheet_data_source[j];\n\t\t\t\t\tif ( row[date_string] ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t} else if ( !row[date_string] && row[date_string + '_related_data'] ) {\n\t\t\t\t\t\tvar related_punch = row[date_string + '_related_data'];\n\n\t\t\t\t\t\tif ( related_punch.punch_control_id === punch.punch_control_id ) {\n\t\t\t\t\t\t\trow[date_string] = punch.punch_time;\n\t\t\t\t\t\t\trow[date_string + '_data'] = punch;\n\t\t\t\t\t\t\tfind_position = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( !row[date_string] && !row[date_string + '_related_data'] && punch.status_id == row.status_id ) {\n\t\t\t\t\t\trow[date_string] = punch.punch_time;\n\t\t\t\t\t\trow[date_string + '_data'] = punch;\n\t\t\t\t\t\trow[date_string + '_related_data'] = null;\n\t\t\t\t\t\tfind_position = true;\n\n\t\t\t\t\t\tif ( punch.status_id == 10 ) {\n\t\t\t\t\t\t\tnew_row = this.timesheet_data_source[j + 1];\n\t\t\t\t\t\t\tnew_row[date_string] = '';\n\t\t\t\t\t\t\tnew_row[date_string + '_data'] = null;\n\t\t\t\t\t\t\tnew_row[date_string + '_related_data'] = punch;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnew_row = this.timesheet_data_source[j - 1];\n\t\t\t\t\t\t\tnew_row[date_string] = '';\n\t\t\t\t\t\t\tnew_row[date_string + '_data'] = null;\n\t\t\t\t\t\t\tnew_row[date_string + '_related_data'] = punch;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t//Need add a new row\n\t\t\t\tif ( !find_position ) {\n\t\t\t\t\trow = {};\n\t\t\t\t\trow.punch_info = punch.status;\n\t\t\t\t\trow.user_id = punch.user_id;\n\t\t\t\t\trow[date_string] = punch.punch_time;\n\t\t\t\t\trow[date_string + '_data'] = punch;\n\t\t\t\t\trow[date_string + '_related_data'] = null;\n\t\t\t\t\trow.status_id = punch_status_id;\n\t\t\t\t\trow.type = TimeSheetViewController.PUNCH_ROW;\n\t\t\t\t\trow.id = row_id_counter;\n\t\t\t\t\trow_id_counter++;\n\t\t\t\t\tthis.timesheet_data_source.push( row );\n\n\t\t\t\t\tif ( punch_status_id == 10 ) {\n\n\t\t\t\t\t\tnew_row = {};\n\t\t\t\t\t\tnew_row.punch_info = TimeSheetViewController_$.i18n._( 'Out' );\n\t\t\t\t\t\tnew_row.user_id = punch.user_id;\n\t\t\t\t\t\tnew_row[date_string] = '';\n\t\t\t\t\t\tnew_row[date_string + '_data'] = null;\n\t\t\t\t\t\tnew_row[date_string + '_related_data'] = punch;\n\t\t\t\t\t\tnew_row.status_id = 20;\n\t\t\t\t\t\tnew_row.type = TimeSheetViewController.PUNCH_ROW;\n\t\t\t\t\t\tnew_row.id = row_id_counter;\n\t\t\t\t\t\trow_id_counter++;\n\t\t\t\t\t\tthis.timesheet_data_source.push( new_row );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnew_row = {};\n\t\t\t\t\t\tnew_row.punch_info = TimeSheetViewController_$.i18n._( 'In' );\n\t\t\t\t\t\tnew_row.user_id = punch.user_id;\n\t\t\t\t\t\tnew_row[date_string] = '';\n\t\t\t\t\t\tnew_row[date_string + '_data'] = null;\n\t\t\t\t\t\tnew_row[date_string + '_related_data'] = punch;\n\t\t\t\t\t\tnew_row.status_id = 10;\n\t\t\t\t\t\tnew_row.type = TimeSheetViewController.PUNCH_ROW;\n\t\t\t\t\t\tnew_row.id = row_id_counter;\n\t\t\t\t\t\trow_id_counter++;\n\t\t\t\t\t\tthis.timesheet_data_source.splice( this.timesheet_data_source.length - 1, 0, new_row );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\trow = {};\n\t\trow.punch_info = TimeSheetViewController_$.i18n._( 'In' );\n\t\trow.user_id = this.getSelectEmployee();\n\t\trow.status_id = 10;\n\t\trow.type = TimeSheetViewController.PUNCH_ROW;\n\t\trow.id = row_id_counter;\n\t\trow_id_counter++;\n\t\tthis.timesheet_data_source.push( row );\n\n\t\trow = {};\n\t\trow.punch_info = TimeSheetViewController_$.i18n._( 'Out' );\n\t\trow.user_id = this.getSelectEmployee();\n\t\trow.status_id = 20;\n\t\trow.type = TimeSheetViewController.PUNCH_ROW;\n\t\trow.id = row_id_counter;\n\t\trow_id_counter++;\n\t\tthis.timesheet_data_source.push( row );\n\t}\n\n\tbuildTimeSheetsColumns() {\n\t\tthis.timesheet_columns = [];\n\t\tif ( this.getPunchMode() === 'manual' ) {\n\t\t\tvar cost_center_cols = [\n\t\t\t\t{ 'name': 'plus_sign', 'width': 25 },\n\t\t\t\t{ 'name': 'minus_sign', 'width': 25 }\n\t\t\t];\n\n\t\t\tif ( this.show_branch_ui ) {\n\t\t\t\tcost_center_cols.push( { 'name': 'branch', 'width': 125 } );\n\t\t\t}\n\n\t\t\tif ( this.show_department_ui ) {\n\t\t\t\tcost_center_cols.push( { 'name': 'department', 'width': 125 } );\n\t\t\t}\n\n\t\t\tif ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) {\n\t\t\t\tif ( this.show_job_ui ) {\n\t\t\t\t\tcost_center_cols.push( { 'name': 'job', 'width': 170 } );\n\t\t\t\t}\n\n\t\t\t\tif ( this.show_job_item_ui ) {\n\t\t\t\t\tcost_center_cols.push( { 'name': 'job_item', 'width': 170 } );\n\t\t\t\t}\n\n\t\t\t\tif ( this.show_punch_tag_ui ) {\n\t\t\t\t\tcost_center_cols.push( { 'name': 'punch_tag', 'width': 170 } );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar last_col_index = cost_center_cols.length - 1;\n\t\t\tfor ( var i = 0; i < cost_center_cols.length; i++ ) {\n\t\t\t\tif ( i == last_col_index ) {\n\t\t\t\t\tvar column = {\n\t\t\t\t\t\tname: 'punch_info',\n\t\t\t\t\t\tindex: 'punch_info',\n\t\t\t\t\t\tlabel: ' ',\n\t\t\t\t\t\twidth: 170,\n\t\t\t\t\t\tsortable: false,\n\t\t\t\t\t\ttitle: false,\n\t\t\t\t\t\tformatter: this.onCellFormat,\n\t\t\t\t\t\tfixed: true\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tvar column = {\n\t\t\t\t\t\tname: 'empty_cell_' + i,\n\t\t\t\t\t\tindex: 'empty_cell_' + i,\n\t\t\t\t\t\tlabel: ' ',\n\t\t\t\t\t\twidth: cost_center_cols[i].width,\n\t\t\t\t\t\tsortable: false,\n\t\t\t\t\t\ttitle: false,\n\t\t\t\t\t\tfixed: true\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tthis.timesheet_columns.push( column );\n\t\t\t}\n\t\t} else {\n\t\t\tvar punch_in_out_column = {\n\t\t\t\tname: 'punch_info',\n\t\t\t\tindex: 'punch_info',\n\t\t\t\tlabel: ' ',\n\t\t\t\t//if not set to 0 in punch timesheet mode, the date column headers are a few px out of alignment and look bad.\n\t\t\t\t//see #2091 notes for link to the percent-based js fiddle\n\t\t\t\twidth: 100,\n\t\t\t\tsortable: false,\n\t\t\t\ttitle: false,\n\t\t\t\tformatter: this.onCellFormat,\n\t\t\t\tfixed: false\n\t\t\t};\n\t\t\tthis.timesheet_columns.push( punch_in_out_column );\n\t\t}\n\n\t\t//save full week columns map use to build no pey period column\n\t\tthis.column_maps = [];\n\t\tfor ( var i = 0; i < 7; i++ ) {\n\t\t\tvar current_date = new Date( new Date( this.start_date.getTime() ).setDate( this.start_date.getDate() + i ) );\n\t\t\tvar header_text = current_date.format( this.weekly_format );\n\n\t\t\t//Localize the day of week and month text.\n\t\t\tif ( LocalCacheData.getLoginData().language != 'en' && Global/* Global.isString */.x.isString( header_text ) ) {\n\t\t\t\tvar split_header_text_array = header_text.split( ',' );\n\t\t\t\tvar split_header_text_month = split_header_text_array[1].split( ' ' );\n\t\t\t\theader_text = TimeSheetViewController_$.i18n._( split_header_text_array[0] ) + ', ' + TimeSheetViewController_$.i18n._( split_header_text_month[1] ) + ' ' + split_header_text_month[2];\n\t\t\t}\n\n\t\t\tvar data_field = current_date.format( this.full_format );\n\n\t\t\tthis.column_maps.push( current_date.format() );\n\n\t\t\tvar column_info = {\n\t\t\t\tresizable: false,\n\t\t\t\tname: data_field,\n\t\t\t\tindex: data_field,\n\t\t\t\tlabel: header_text,\n\t\t\t\twidth: 100,\n\t\t\t\tsortable: false,\n\t\t\t\ttitle: false,\n\t\t\t\tformatter: this.onCellFormat\n\t\t\t};\n\t\t\tthis.timesheet_columns.push( column_info );\n\t\t}\n\n\t\treturn this.timesheet_columns;\n\t}\n\n\tgetDefaultDisplayColumns( callback ) {\n\t\t// Overriden to allow use of initLayout in BaseViewController, but no default display columns in this view, hence this function is 'disabled'\n\t\tcallback();\n\t}\n\n\tsetSelectLayout() {\n\t\tvar $this = this;\n\n\t\tif ( !Global/* Global.isSet */.x.isSet( this.grid ) ) {\n\t\t\tvar grid = TimeSheetViewController_$( this.el ).find( '#grid' );\n\n\t\t\tgrid.attr( 'id', this.ui_id + '_grid' ); //Grid's id is ScriptName + _grid\n\n\t\t\tgrid = TimeSheetViewController_$( this.el ).find( '#' + this.ui_id + '_grid' );\n\t\t}\n\n\t\tif ( !this.select_layout ) { //Set to defalt layout if no layout at all\n\t\t\tthis.select_layout = { id: '' };\n\t\t\tthis.select_layout.data = { filter_data: {}, filter_sort: {} };\n\t\t}\n\n\t\tif ( this.select_layout.data.mode ) {\n\t\t\tthis.toggle_button.setValue( this.select_layout.data.mode );\n\t\t}\n\n\t\tthis.wage_btn.setValue( this.select_layout.data.show_wage ? true : false );\n\n\t\tthis.timezone_btn.setValue( this.select_layout.data.use_employee_timezone ? true : false );\n\n\t\t//search panel doesn't always exist.\n\t\tif ( this.search_panel ) {\n\t\t\t//Set Previous Saved layout combobox in layout panel\n\t\t\tvar layouts_array = this.search_panel.getLayoutsArray();\n\t\t\tif ( this.previous_saved_layout_selector ) {\n\t\t\t\tthis.previous_saved_layout_selector.empty();\n\t\t\t}\n\n\t\t\tif ( layouts_array && layouts_array.length > 0 ) {\n\t\t\t\tthis.previous_saved_layout_div.css( 'display', 'inline' );\n\n\t\t\t\tvar len = layouts_array.length;\n\t\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\t\tvar item = layouts_array[i];\n\t\t\t\t\tthis.previous_saved_layout_selector.append( TimeSheetViewController_$( '<option value=\"' + item.id + '\"></option>' ).text( item.name ) );\n\t\t\t\t}\n\n\t\t\t\tTimeSheetViewController_$( this.previous_saved_layout_selector.find( 'option' ) ).filter( function() {\n\t\t\t\t\treturn TimeSheetViewController_$( this ).attr( 'value' ) === $this.select_layout.id;\n\t\t\t\t} ).prop( 'selected', true ).attr( 'selected', true );\n\n\t\t\t} else {\n\t\t\t\tif ( this.previous_saved_layout_div ) {\n\t\t\t\t\tthis.previous_saved_layout_div.css( 'display', 'none' );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//replace select layout filter_data to filter set in onNavigation function when goto view from navigation context group\n\t\t\tif ( LocalCacheData.default_filter_for_next_open_view ) {\n\t\t\t\tthis.select_layout.data.filter_data = LocalCacheData.default_filter_for_next_open_view.filter_data;\n\t\t\t\tLocalCacheData.default_filter_for_next_open_view = null;\n\t\t\t}\n\n\t\t\tthis.filter_data = this.select_layout.data.filter_data;\n\n\t\t\tthis.setSearchPanelFilter( true ); //Auto change to property tab when set value to search fields.\n\t\t}\n\n\t\t// this.search( true ); // get punches base on userid, data and filter - commented out as this is already called in BaseViewController.initLayout()\n\t}\n\n\t//Start Drag\n\tsetTimesheetGridDragAble() {\n\t\tvar $this = this;\n\n\t\tvar position = 0;\n\t\tvar cells = this.grid.grid.find( '.date-column' ).parents( 'td' );\n\t\tcells.attr( 'draggable', true );\n\n\t\tcells.off( 'dragstart' ).on( 'dragstart', function( event ) {\n\n\t\t\tvar td = event.target;\n\t\t\tif ( $this.select_punches_array.length < 1 || !TimeSheetViewController_$( td ).hasClass( 'ui-state-highlight' ) || !$this.select_drag_menu_id ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tvar container = TimeSheetViewController_$( '<div class=\\'drag-holder-div\\'></div>' );\n\n\t\t\tvar len = $this.select_punches_array.length;\n\n\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\tvar punch = $this.select_punches_array[i];\n\n\t\t\t\tvar span = TimeSheetViewController_$( '<span class=\\'drag-span\\'></span>' );\n\t\t\t\tspan.text( punch.status + ': ' + punch.time_stamp );\n\t\t\t\tcontainer.append( span );\n\t\t\t}\n\n\t\t\tTimeSheetViewController_$( 'body' ).find( '.drag-holder-div' ).remove();\n\n\t\t\tTimeSheetViewController_$( 'body' ).append( container );\n\n\t\t\tevent.originalEvent.dataTransfer.setData( 'Text', 'timesheet' );//JUST ELEMENT references is ok here NO ID\n\n\t\t\tif ( event.originalEvent.dataTransfer.setDragImage ) {\n\t\t\t\tevent.originalEvent.dataTransfer.setDragImage( container[0], 0, 0 );\n\t\t\t}\n\n\t\t\treturn true;\n\n\t\t} );\n\n\t\tcells.off( 'dragover' ).on( 'dragover', function( e ) {\n\n\t\t\tvar event = e.originalEvent;\n\n\t\t\tevent.preventDefault();\n\t\t\tvar $this = this;\n\t\t\tvar target = TimeSheetViewController_$( this );\n\n\t\t\tTimeSheetViewController_$( '.timesheet-drag-over' ).removeClass( 'timesheet-drag-over' );\n\t\t\tTimeSheetViewController_$( '.drag-over-top' ).removeClass( 'drag-over-top' );\n\t\t\tTimeSheetViewController_$( '.drag-over-center' ).removeClass( 'drag-over-center' );\n\t\t\tTimeSheetViewController_$( '.drag-over-bottom' ).removeClass( ' drag-over-bottom' );\n\n\t\t\tTimeSheetViewController_$( $this ).addClass( 'timesheet-drag-over' );\n\n\t\t\t//judge which area mouse on in the target cell and set proper style, Keep checking this in drag event.\n\t\t\tif ( event.pageY - target.offset().top <= 8 ) {\n\t\t\t\tposition = -1;\n\t\t\t\ttarget.removeClass( 'drag-over-top drag-over-center drag-over-bottom' ).addClass( 'drag-over-top' );\n\t\t\t} else if ( event.pageY - target.offset().top >= target.height() - 5 ) {\n\t\t\t\tposition = 1;\n\t\t\t\ttarget.removeClass( 'drag-over-top drag-over-center drag-over-bottom' ).addClass( 'drag-over-bottom' );\n\t\t\t} else {\n\t\t\t\tposition = 0;\n\t\t\t\ttarget.removeClass( 'drag-over-top drag-over-center drag-over-bottom' ).addClass( 'drag-over-center' );\n\t\t\t}\n\n\t\t} );\n\n\t\tcells.off( 'dragend' ).on( 'dragend', function( event ) {\n\n\t\t\tTimeSheetViewController_$( '.timesheet-drag-over' ).removeClass( 'timesheet-drag-over' );\n\t\t\tTimeSheetViewController_$( '.drag-over-top' ).removeClass( 'drag-over-top' );\n\t\t\tTimeSheetViewController_$( '.drag-over-center' ).removeClass( 'drag-over-center' );\n\t\t\tTimeSheetViewController_$( '.drag-over-bottom' ).removeClass( ' drag-over-bottom' );\n\t\t\tTimeSheetViewController_$( 'body' ).find( '.drag-holder-div' ).remove();\n\n\t\t} );\n\n\t\tcells.off( 'drop' ).on( 'drop', function( event ) {\n\n\t\t\tevent.preventDefault();\n\t\t\tif ( event.stopPropagation ) {\n\t\t\t\tevent.stopPropagation(); // stops the browser from redirecting.\n\t\t\t}\n\n\t\t\tTimeSheetViewController_$( this ).removeClass( 'drag-over-top drag-over-center drag-over-bottom timesheet-drag-over' );\n\t\t\tvar target_cell = event.currentTarget;\n\t\t\tvar i = 0; //start index;\n\n\t\t\tif ( TimeSheetViewController_$( target_cell ).index() === 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t//Error: Uncaught TypeError: Cannot read property 'punch_date' of undefined in /interface/html5/#!m=TimeSheet&date=20141118&user_id=32916 line 4563\n\t\t\tif ( !$this.select_punches_array || !$this.select_punches_array[i] ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar punch = $this.select_punches_array[i];\n\n\t\t\tvar punch_date = Global/* Global.strToDate */.x.strToDate( punch.punch_date );\n\n\t\t\tvar row = $this.timesheet_data_source[target_cell.parentNode.rowIndex - 1];\n\n\t\t\t//Error: Uncaught TypeError: Cannot read property 'status_id' of undefined in /interface/html5/#!m=TimeSheet&date=20150108&user_id=1068 line 5174\n\t\t\tif ( !row ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar colModel = $this.grid.getGridParam( 'colModel' );\n\n\t\t\tvar data_field = colModel[target_cell.cellIndex].name;\n\n\t\t\tvar target_punch = row[data_field + '_data'];\n\n\t\t\tvar target_related_punch = row[data_field + '_related_data'];\n\n\t\t\tvar target_column_date = Global/* Global.strToDate */.x.strToDate( data_field, $this.full_format );\n\n\t\t\tvar first_select_date = punch_date;\n\n\t\t\tvar time_offset = target_column_date.getTime() - punch_date.getTime();\n\n\t\t\tvar target_column_date_str = target_column_date.format();\n\n\t\t\tsavePunch();\n\n\t\t\tfunction savePunch() {\n\t\t\t\t//Error: Uncaught TypeError: Cannot read property 'date_stamp' of undefined in /interface/html5/#!m=TimeSheet&date=20141229&user_id=39555 line 5207\n\t\t\t\tif ( !$this.select_punches_array ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tvar new_punch_id = punch.id;\n\t\t\t\tvar target_id = false;\n\t\t\t\tvar target_status_id = row.status_id;\n\t\t\t\tvar action_type = $this.select_drag_menu_id === 'move' ? 1 : 0;\n\n\t\t\t\t//Issue #2008 - All in-punches need target_id to be false to ensure that each pair retains its punch_control settings.\n\t\t\t\t//Most out-punches need their target id to be the related in-punch.\n\t\t\t\t//If these conditions are not met, copying groups of punches with different punch_control data will result in all copied punches having the same punch_control data as the first punch pair.\n\t\t\t\tif ( target_punch && punch.status_id == 20 ) {\n\t\t\t\t\ttarget_id = target_punch.id;\n\t\t\t\t\ttarget_status_id = false;\n\t\t\t\t} else if ( target_related_punch ) {\n\t\t\t\t\ttarget_id = target_related_punch.id;\n\t\t\t\t\tif ( target_related_punch.status_id == 10 ) {\n\t\t\t\t\t\tposition = 1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tposition = -1;\n\t\t\t\t\t}\n\t\t\t\t\ttarget_status_id = false;\n\t\t\t\t}\n\n\t\t\t\tvar api_punch_control = TTAPI.APIPunchControl;\n\n\t\t\t\tapi_punch_control.dragNdropPunch( new_punch_id, target_id, target_status_id, position, action_type, target_column_date_str, {\n\t\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t\tvar result_data = result.getResult();\n\t\t\t\t\t\t//Error: Uncaught TypeError: Cannot read property 'date_stamp' of undefined in interface/html5/#!m=TimeSheet&date=20150831&user_id=129895&show_wage=0 line 5286\n\t\t\t\t\t\tif ( result.isValid() && $this.select_punches_array && $this.select_punches_array.length > 0 ) {\n\t\t\t\t\t\t\ti = i + 1;\n\t\t\t\t\t\t\tif ( i > $this.select_cells_Array.length - 1 ) {\n\t\t\t\t\t\t\t\t$this.search( true );\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t//Error: Uncaught TypeError: Cannot read property 'date_stamp' of undefined in interface/html5/#!m=TimeSheet&date=20150831&user_id=129895&show_wage=0 line 5286\n\t\t\t\t\t\t\tif ( !$this.select_punches_array[i] ) {\n\t\t\t\t\t\t\t\t$this.search( true );\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\twhile ( !$this.select_punches_array[i].date_stamp ) {\n\t\t\t\t\t\t\t\ti = i + 1;\n\t\t\t\t\t\t\t\tif ( i > $this.select_cells_Array.length - 1 ) {\n\t\t\t\t\t\t\t\t\t$this.search( true );\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tposition = 1; //put next punch below last one\n\t\t\t\t\t\t\tvar last_date_string = target_column_date_str;\n\t\t\t\t\t\t\tpunch = $this.select_punches_array[i];\n\t\t\t\t\t\t\tpunch_date = Global/* Global.strToDate */.x.strToDate( punch.punch_date );\n\t\t\t\t\t\t\trow = $this.timesheet_data_source[target_cell.parentNode.rowIndex - 1];\n\t\t\t\t\t\t\tcolModel = $this.grid.getGridParam( 'colModel' );\n\t\t\t\t\t\t\tdata_field = colModel[target_cell.cellIndex].name;\n\t\t\t\t\t\t\ttime_offset = punch_date.getTime() - first_select_date.getTime();\n\t\t\t\t\t\t\t//drop column date\n\t\t\t\t\t\t\ttarget_column_date = Global/* Global.strToDate */.x.strToDate( data_field, $this.full_format );\n\t\t\t\t\t\t\t//Real target column date str\n\t\t\t\t\t\t\ttarget_column_date_str = new Date( target_column_date.getTime() + time_offset ).format();\n\t\t\t\t\t\t\ttarget_punch = { id: result_data };\n\t\t\t\t\t\t\ttarget_related_punch = null;\n\t\t\t\t\t\t\tif ( target_column_date_str !== last_date_string ) {\n\t\t\t\t\t\t\t\tposition = 0;\n\t\t\t\t\t\t\t\ttarget_punch = null;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tsavePunch();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tTAlertManager.showAlert( TimeSheetViewController_$.i18n._( 'Unable to drag and drop punch to the specified location' ) );\n\t\t\t\t\t\t\tif ( i > 0 ) {\n\t\t\t\t\t\t\t\t$this.search( true );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\t}\n\n\tsetPunchModeClass() {\n\t\tthis.$el.removeClass( 'timesheet-punch-mode' );\n\t\tthis.$el.removeClass( 'timesheet-manual-mode' );\n\t\tthis.getPunchMode() === 'punch' ? this.$el.addClass( 'timesheet-punch-mode' ) : this.$el.addClass( 'timesheet-manual-mode' );\n\t}\n\n\tinitData() {\n\t\tvar $this = this;\n\t\tGlobal/* Global.removeViewTab */.x.removeViewTab( this.viewId );\n\t\tvar loginUser = LocalCacheData.getLoginUser();\n\t\tthis.initOptions();\n\t\tProgressBar.showOverlay();\n\t\t// Set Wage\n\t\tif ( !LocalCacheData.last_timesheet_selected_show_wage ) {\n\t\t\tthis.wage_btn.setValue( false );\n\t\t} else {\n\t\t\tthis.wage_btn.setValue( LocalCacheData.last_timesheet_selected_show_wage );\n\t\t}\n\n\t\t//Error: TypeError: Cannot read property 'show_wage' of null\n\t\t//just need to check that the variable exists before checking properties for the case of the LocalCacheData being empty\n\t\tif ( Global/* Global.isSet */.x.isSet( LocalCacheData.getAllURLArgs() ) && LocalCacheData.getAllURLArgs().show_wage ) {\n\t\t\tthis.wage_btn.setValue( LocalCacheData.getAllURLArgs().show_wage === '1' ? true : false );\n\t\t}\n\n\t\t// Set Use Employee TimeSheet\n\t\tif ( !LocalCacheData.last_timesheet_selected_timezone ) {\n\t\t\tthis.timezone_btn.setValue( false );\n\t\t} else {\n\t\t\tthis.timezone_btn.setValue( LocalCacheData.last_timesheet_selected_timezone );\n\t\t}\n\n\t\t//Error: TypeError: Cannot read property 'show_wage' of null\n\t\t//just need to check that the variable exists before checking properties for the case of the LocalCacheData being empty\n\t\tif ( Global/* Global.isSet */.x.isSet( LocalCacheData.getAllURLArgs() ) && LocalCacheData.getAllURLArgs().timezone ) {\n\t\t\tthis.timezone_btn.setValue( LocalCacheData.getAllURLArgs().timezone === '1' ? true : false );\n\t\t}\n\n\t\t// Set punch mode\n\t\tif ( !this.show_punch_mode_ui ) {\n\t\t\tif ( !PermissionManager.validate( this.permission_id, 'punch_timesheet' ) && !PermissionManager.validate( this.permission_id, 'manual_timesheet' ) ) {\n\t\t\t\tthis.toggle_button.setValue( 'punch' );\n\t\t\t} else {\n\t\t\t\tif ( PermissionManager.validate( this.permission_id, 'punch_timesheet' ) ) {\n\t\t\t\t\tthis.toggle_button.setValue( 'punch' );\n\t\t\t\t}\n\t\t\t\tif ( Global/* Global.getProductEdition */.x.getProductEdition() >= 15 && PermissionManager.validate( this.permission_id, 'manual_timesheet' ) ) {\n\t\t\t\t\tthis.toggle_button.setValue( 'manual' );\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif ( !LocalCacheData.last_timesheet_selected_punch_mode ) {\n\t\t\t\tthis.toggle_button.setValue( 'punch' );\n\n\t\t\t} else {\n\t\t\t\tthis.toggle_button.setValue( LocalCacheData.last_timesheet_selected_punch_mode );\n\t\t\t}\n\t\t\tif ( LocalCacheData.getAllURLArgs().mode ) {\n\t\t\t\t// Fix wrong value from url\n\t\t\t\tthis.toggle_button.setValue( LocalCacheData.getAllURLArgs().mode === 'manual' ? 'manual' : 'punch' );\n\t\t\t}\n\t\t}\n\n\t\tif ( Global/* Global.UNIT_TEST_MODE */.x.UNIT_TEST_MODE == true ) {\n\t\t\tLocalCacheData.last_timesheet_selected_date = '15-Feb-18';\n\t\t}\n\t\t//replace select layout filter_data to filter set in onNavigation function when goto view from navigation context group\n\t\tif ( LocalCacheData.default_filter_for_next_open_view ) {\n\t\t\tthis.employee_nav.setValue( LocalCacheData.default_filter_for_next_open_view.user_id );\n\t\t\tthis.setDatePickerValue( LocalCacheData.default_filter_for_next_open_view.base_date );\n\t\t} else {\n\t\t\tif ( LocalCacheData.getAllURLArgs().user_id ) {\n\t\t\t\tthis.employee_nav.setValue( LocalCacheData.getAllURLArgs().user_id );\n\t\t\t} else if ( LocalCacheData.last_timesheet_selected_user ) {\n\t\t\t\tthis.employee_nav.setValue( LocalCacheData.last_timesheet_selected_user );\n\t\t\t} else {\n\t\t\t\t//Default set current login user as select Employee\n\t\t\t\tthis.employee_nav.setValue( loginUser );\n\t\t\t}\n\n\t\t\tif ( !LocalCacheData.last_timesheet_selected_date ) { //Saved current select date in cache. so still select last select date when go to other view and back\n\t\t\t\tif ( LocalCacheData.current_select_date && Global/* Global.strToDate */.x.strToDate( LocalCacheData.current_select_date, 'YYYY-MM-DD' ) ) { //Select date get from URL.\n\t\t\t\t\tthis.setDatePickerValue( Global/* Global.strToDate */.x.strToDate( LocalCacheData.current_select_date, 'YYYY-MM-DD' ).format() );\n\t\t\t\t\tLocalCacheData.current_select_date = '';\n\t\t\t\t} else {\n\t\t\t\t\tvar date = new Date();\n\t\t\t\t\tvar format = Global/* Global.getLoginUserDateFormat */.x.getLoginUserDateFormat();\n\t\t\t\t\tvar dateStr = date.format( format );\n\t\t\t\t\tthis.setDatePickerValue( dateStr );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tthis.setDatePickerValue( LocalCacheData.last_timesheet_selected_date );\n\t\t\t}\n\t\t}\n\n\t\t//Issue #3268 - Race condition where previous search layout will not exist in UI when expected as API for custom field data has not returned yet.\n\t\t//Timesheet overrides initData() from BaseViewController that waits on the custom field promise to resolve before continuing.\n\t\tTTPromise.wait( 'BaseViewController', 'getCustomFields', function() {\n\t\t\t$this.initLayout();\n\t\t} );\n\n\t\tthis.setMoveOrDropMode( this.select_drag_menu_id ? this.select_drag_menu_id : 'move' );\n\t}\n\n\tsetDatePickerValue( val ) {\n\t\tthis.start_date_picker.setValue( val );\n\n\t\tvar default_date = this.start_date_picker.getDefaultFormatValue();\n\n\t\tvar user_id = this.getSelectEmployee();\n\n\t\tif ( user_id &&\n\t\t\t!this.edit_view &&\n\t\t\t//Removing date from the generated URLs to avoid bookmarking to stale dates by users.\n\t\t\t//(window.location.href.indexOf( 'date=' + default_date ) === -1 || window.location.href.indexOf( 'user_id=' + this.getSelectEmployee() === -1 )) ) {\n\t\t\t( window.location.href.indexOf( 'user_id=' + user_id ) === -1 ) ) {\n\n\t\t\t//var location = Global.getBaseURL() + '#!m=' + this.viewId + '&date=' + default_date + '&user_id=' + this.getSelectEmployee() + '&show_wage=' + this.wage_btn.getValue( true ) + '&mode=' + this.toggle_button.getValue();\n\t\t\tvar location = Global/* Global.getBaseURL */.x.getBaseURL() + '#!m=' + this.viewId + '&user_id=' + user_id + '&show_wage=' + this.wage_btn.getValue( true ) + '&mode=' + this.toggle_button.getValue();\n\n\t\t\tif ( LocalCacheData.getAllURLArgs() ) {\n\t\t\t\tfor ( var key in LocalCacheData.getAllURLArgs() ) {\n\t\t\t\t\t//if ( key === 'm' || key === 'date' || key === 'user_id' || key === 'show_wage' || key === 'mode' ) {\n\t\t\t\t\tif ( key === 'm' || key === 'user_id' || key === 'show_wage' || key === 'timezone' || key === 'mode' ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tlocation = location + '&' + key + '=' + LocalCacheData.getAllURLArgs()[key];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tGlobal/* Global.setURLToBrowser */.x.setURLToBrowser( location );\n\n\t\t}\n\n\t\tLocalCacheData.last_timesheet_selected_date = val;\n\t}\n\n\tbuildSearchFields() {\n\n\t\tsuper.buildSearchFields();\n\t\tthis.search_fields = [\n\n\t\t\tnew SearchField( {\n\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Punch Branch' ),\n\t\t\t\tin_column: 1,\n\t\t\t\tfield: 'branch_id',\n\t\t\t\tlayout_name: 'global_branch',\n\t\t\t\tapi_class: TTAPI.APIBranch,\n\t\t\t\tmultiple: true,\n\t\t\t\tbasic_search: true,\n\t\t\t\tadv_search: false,\n\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t} ),\n\t\t\tnew SearchField( {\n\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Punch Department' ),\n\t\t\t\tfield: 'department_id',\n\t\t\t\tin_column: 1,\n\t\t\t\tlayout_name: 'global_department',\n\t\t\t\tapi_class: TTAPI.APIDepartment,\n\t\t\t\tmultiple: true,\n\t\t\t\tbasic_search: true,\n\t\t\t\tadv_search: false,\n\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t} ),\n\t\t\tnew SearchField( {\n\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Job' ),\n\t\t\t\tin_column: 2,\n\t\t\t\tfield: 'job_id',\n\t\t\t\tlayout_name: 'global_job',\n\t\t\t\tapi_class: ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ? TTAPI.APIJob : null,\n\t\t\t\tmultiple: true,\n\t\t\t\tbasic_search: ( this.show_job_item_ui && ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ),\n\t\t\t\tadv_search: false,\n\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t} ),\n\n\t\t\tnew SearchField( {\n\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Task' ),\n\t\t\t\tin_column: 2,\n\t\t\t\tfield: 'job_item_id',\n\t\t\t\tlayout_name: 'global_job_item',\n\t\t\t\tapi_class: ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ? TTAPI.APIJobItem : null,\n\t\t\t\tmultiple: true,\n\t\t\t\tbasic_search: ( this.show_job_item_ui && ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ),\n\t\t\t\tadv_search: false,\n\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t} ),\n\n\t\t\tnew SearchField( {\n\t\t\t\tlabel: TimeSheetViewController_$.i18n._( 'Tags' ),\n\t\t\t\tin_column: 2,\n\t\t\t\tfield: 'punch_tag_id',\n\t\t\t\tlayout_name: 'global_punch_tag',\n\t\t\t\tapi_class: ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ? TTAPI.APIPunchTag : null,\n\t\t\t\tmultiple: true,\n\t\t\t\tbasic_search: ( this.show_punch_tag_ui && ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ),\n\t\t\t\tadv_search: false,\n\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t} )\n\t\t];\n\t}\n\n\tgetSelectEmployee( full_item ) {\n\t\tvar user = false;\n\t\tif ( this.show_navigation_box && this.employee_nav && typeof this.employee_nav.getValue == 'function' ) {\n\t\t\tuser = this.employee_nav.getValue( true ); //Always try to get the object (not the id), however in some cases like recalculating timesheets it still seems to return the ID instead of the object.\n\t\t}\n\n\t\t//Convert object if it isn't already, to make logic lower down easier.\n\t\tif ( Global/* Global.isObject */.x.isObject( user ) == false ) {\n\t\t\tuser = { id: user };\n\t\t}\n\n\t\tif ( Global/* Global.isObject */.x.isObject( user ) == false || ( Global/* Global.isObject */.x.isObject( user ) == true && ( user.hasOwnProperty( 'id' ) == false || TTUUID/* TTUUID.isUUID */.d.isUUID( user.id ) == false ) ) ) {\n\t\t\tuser = LocalCacheData.getLoginUser();\n\n\t\t\tif ( Global/* Global.isObject */.x.isObject( user ) == false || ( Global/* Global.isObject */.x.isObject( user ) == true && ( user.hasOwnProperty( 'id' ) == false || TTUUID/* TTUUID.isUUID */.d.isUUID( user.id ) == false ) ) ) {\n\t\t\t\t//currently logged in user object is corrupt.\n\t\t\t\tMenuManager.doLogout();\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tif ( full_item != true && ( Global/* Global.isObject */.x.isObject( user ) == true && user.hasOwnProperty( 'id' ) == true && TTUUID/* TTUUID.isUUID */.d.isUUID( user.id ) == true ) ) {\n\t\t\tuser = user.id;\n\t\t}\n\n\t\treturn user;\n\t}\n\n\tgetSelectDate() {\n\t\tif ( this.start_date_picker ) {\n\t\t\tvar retval = this.start_date_picker.getValue();\n\n\t\t\tif ( retval == 'Invalid date' ) {\n\t\t\t\tretval = new Date();\n\t\t\t}\n\n\t\t\treturn retval;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tonDeleteResult( result ) {\n\t\tvar $this = this;\n\t\t$this.timesheet_grid.grid.find( 'td.ui-state-highlight' ).removeClass( 'ui-state-highlight' );\n\t\tProgressBar.closeOverlay();\n\t\tif ( result.isValid() ) {\n\t\t\tif ( $this.edit_view ) {\n\t\t\t\tif ( LocalCacheData.current_doing_context_action === 'delete' ) {\n\t\t\t\t\t$this.removeEditView();\n\t\t\t\t} else if ( $this.edit_view && LocalCacheData.current_doing_context_action === 'delete_and_next' ) {\n\t\t\t\t\t$this.onRightArrowClick();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.setCurrentEditViewState( '' );\n\t\t\t}\n\t\t} else {\n\t\t\t$this.revertEditViewState();\n\t\t\tTAlertManager.showErrorAlert( result );\n\t\t}\n\n\t\t// refresh and rebuild search grid, as well as default menu\n\t\t$this.first_build = true;\n\t\t$this.search();\n\t\t$this.setDefaultMenu(); //Default menu needs to be set as we need to deactivate icons that are valid for the predeletion selection\n\t}\n\n\tgetDeleteSelectedRecordId() {\n\t\tvar retval = [];\n\t\tif ( this.edit_view ) {\n\t\t\tretval.push( this.current_edit_record.id );\n\t\t} else {\n\t\t\tfor ( var i in this.select_punches_array ) {\n\t\t\t\tvar item = this.select_punches_array[i];\n\t\t\t\tretval.push( item.id );\n\t\t\t}\n\t\t}\n\t\treturn retval;\n\t}\n\n\treSetURL() {\n\t\t//var args = '#!m=' + this.viewId + '&date=' + this.start_date_picker.getDefaultFormatValue() + '&user_id=' + this.getSelectEmployee() + '&show_wage=' + this.wage_btn.getValue( true ) + '&mode=' + this.toggle_button.getValue();\n\t\tvar args = '#!m=' + this.viewId + '&user_id=' + this.getSelectEmployee() + '&show_wage=' + this.wage_btn.getValue( true ) + '&timezone=' + this.timezone_btn.getValue( true ) + '&mode=' + this.toggle_button.getValue();\n\t\tGlobal/* Global.setURLToBrowser */.x.setURLToBrowser( Global/* Global.getBaseURL */.x.getBaseURL() + args );\n\t\tLocalCacheData.setAllURLArgs( Global/* Global.buildArgDic */.x.buildArgDic( args.split( '&' ) ) );\n\t}\n\n\tonSaveAndContinue( ignoreWarning ) {\n\t\tvar $this = this;\n\t\tif ( !Global/* Global.isSet */.x.isSet( ignoreWarning ) ) {\n\t\t\tignoreWarning = false;\n\t\t}\n\t\tthis.is_changed = false;\n\t\tLocalCacheData.current_doing_context_action = 'save_and_continue';\n\t\tvar current_api = this.getCurrentAPI();\n\n\t\tif ( this.is_mass_adding && this.current_edit_record.punch_dates && this.current_edit_record.punch_dates.length === 1 ) {\n\t\t\tthis.current_edit_record.punch_date = this.current_edit_record.punch_dates[0];\n\t\t}\n\n\t\tcurrent_api.setIsIdempotent( true ); //Force to idempotent API call to avoid duplicate network requests from causing errors displayed to the user.\n\t\tcurrent_api['set' + current_api.key_name]( this.current_edit_record, false, ignoreWarning, {\n\t\t\tonResult: function( result ) {\n\t\t\t\tif ( result.isValid() ) {\n\t\t\t\t\tvar result_data = result.getResult();\n\t\t\t\t\tvar refresh_id;\n\t\t\t\t\tif ( result_data === true ) {\n\t\t\t\t\t\trefresh_id = $this.current_edit_record.id;\n\n\t\t\t\t\t} else if ( TTUUID/* TTUUID.isUUID */.d.isUUID( result_data ) && result_data != TTUUID/* TTUUID.zero_id */.d.zero_id && result_data != TTUUID/* TTUUID.not_exist_id */.d.not_exist_id ) {\n\t\t\t\t\t\trefresh_id = result_data;\n\t\t\t\t\t}\n\t\t\t\t\t$this.search();\n\t\t\t\t\t$this.onEditClick( refresh_id, $this.getPunchPermissionType() );\n\n\t\t\t\t\t//#2295 - Re-initialize previous_absence_policy_id to ensure that previously saved values are passed correctly into the estimation of projected available balance.\n\t\t\t\t\t$this.previous_absence_policy_id = false;\n\n\t\t\t\t\t$this.onSaveAndContinueDone( result );\n\t\t\t\t} else {\n\t\t\t\t\t$this.setErrorMenu();\n\t\t\t\t\t$this.setErrorTips( result );\n\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tgetSelectedRecordId( record ) {\n\t\tvar retval = false;\n\n\t\tif ( Global/* Global.isSet */.x.isSet( record ) ) {\n\t\t\tif ( Global/* Global.isObject */.x.isObject( record ) && record.id ) {\n\t\t\t\tretval = record.id;\n\t\t\t} else if ( Global/* Global.isString */.x.isString( record ) && TTUUID/* TTUUID.isUUID */.d.isUUID( record ) ) {\n\t\t\t\tretval = record;\n\t\t\t}\n\t\t} else {\n\t\t\tif ( this.select_punches_array.length > 0 ) {\n\t\t\t\tretval = this.select_punches_array[0].id;\n\t\t\t} else {\n\t\t\t\tretval = null;\n\t\t\t}\n\t\t}\n\n\t\treturn retval;\n\t}\n\n\tgetViewSelectedRecordId( record ) {\n\t\treturn this.getSelectedRecordId( record );\n\t}\n\n\tdoViewAPICall( filter, api_args ) {\n\t\tvar current_api = this.getCurrentAPI();\n\t\tvar callback = { onResult: this.handleViewAPICallbackResult.bind( this ) };\n\t\tif ( api_args ) {\n\t\t\t// If api_args specified, use api_args.filter, and ignore function filter parameter.\n\t\t\tapi_args.push( callback );\n\t\t\treturn current_api['get' + current_api.key_name].apply( current_api, api_args );\n\t\t} else {\n\t\t\treturn current_api['get' + current_api.key_name]( filter, callback );\n\t\t}\n\t}\n\n\tonViewClick( record, type ) {\n\t\tvar tmp_record_id = this.getViewSelectedRecordId( record );\n\t\tif ( Global/* Global.isFalseOrNull */.x.isFalseOrNull( tmp_record_id ) || tmp_record_id == TTUUID/* TTUUID.not_exist_id */.d.not_exist_id ) {\n\t\t\tTAlertManager.showAlert( TimeSheetViewController_$.i18n._( 'This punch is still being processed, please try again later.' ) );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type ) {\n\t\t\tif ( type === 'absence' ) {\n\t\t\t\tthis.absence_model = true;\n\t\t\t} else {\n\t\t\t\tthis.absence_model = false;\n\t\t\t}\n\t\t}\n\t\tsuper.onViewClick( record );\n\t}\n\n\tbuildOtherFieldUI( field, label ) {\n\n\t\tif ( !this.edit_view_tab ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar form_item_input;\n\t\tvar $this = this;\n\t\tvar tab_punch = this.edit_view_tab.find( '#tab_punch' );\n\t\tvar tab_punch_column1 = tab_punch.find( '.first-column' );\n\n\t\tif ( $this.edit_view_ui_dic[field] ) {\n\t\t\tform_item_input = $this.edit_view_ui_dic[field];\n\t\t\tform_item_input.setValue( $this.current_edit_record[field] );\n\t\t} else {\n\t\t\tform_item_input = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.TEXT_INPUT );\n\t\t\tform_item_input.TTextInput( { field: field } );\n\t\t\tvar input_div = $this.addEditFieldToColumn( label, form_item_input, tab_punch_column1 );\n\n\t\t\tinput_div.insertBefore( this.edit_view_form_item_dic['note'] );\n\n\t\t\tform_item_input.setValue( $this.current_edit_record[field] );\n\t\t}\n\t\tform_item_input.css( 'opacity', 1 );\n\t\tform_item_input.css( 'minWidth', 300 );\n\n\t\tif ( $this.is_viewing ) {\n\t\t\tform_item_input.setEnabled( false );\n\t\t} else {\n\t\t\tform_item_input.setEnabled( true );\n\t\t}\n\t}\n\n\tonMassEditClick() {\n\t\tvar $this = this;\n\t\tLocalCacheData.current_doing_context_action = 'mass_edit';\n\t\t$this.openEditView();\n\t\tthis.is_mass_adding = false;\n\t\tthis.is_viewing = false;\n\n\t\tvar current_api = this.getCurrentAPI();\n\n\t\tvar filter = {};\n\t\tthis.mass_edit_record_ids = [];\n\n\t\tTimeSheetViewController_$.each( this.select_punches_array, function( index, value ) {\n\t\t\t$this.mass_edit_record_ids.push( value.id );\n\t\t} );\n\n\t\tfilter.filter_data = {};\n\t\tfilter.filter_data.id = this.mass_edit_record_ids;\n\n\t\tcurrent_api['getCommon' + current_api.key_name + 'Data']( filter, {\n\t\t\tonResult: function( result ) {\n\t\t\t\tvar result_data = result.getResult();\n\t\t\t\tcurrent_api['getOptions']( 'unique_columns', {\n\t\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t\t$this.unique_columns = result.getResult();\n\t\t\t\t\t\tcurrent_api['getOptions']( 'linked_columns', {\n\t\t\t\t\t\t\tonResult: function( result1 ) {\n\n\t\t\t\t\t\t\t\t$this.linked_columns = result1.getResult();\n\n\t\t\t\t\t\t\t\tif ( $this.sub_view_mode && $this.parent_key ) {\n\t\t\t\t\t\t\t\t\tresult_data[$this.parent_key] = $this.parent_value;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif ( !Global/* Global.isSet */.x.isSet( result_data.time_stamp ) ) {\n\t\t\t\t\t\t\t\t\tresult_data.time_stamp = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t$this.current_edit_record = result_data;\n\t\t\t\t\t\t\t\t$this.is_mass_editing = true;\n\t\t\t\t\t\t\t\t$this.initEditView();\n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tsetSubLogViewFilter() {\n\t\tif ( !this.sub_log_view_controller ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.sub_log_view_controller.getSubViewFilter = function( filter ) {\n\n\t\t\tif ( !this.parent_view_controller.absence_model ) {\n\t\t\t\tfilter['table_name_object_id'] = {\n\t\t\t\t\t'punch': [this.parent_edit_record.id],\n\t\t\t\t\t'punch_control': [this.parent_edit_record.punch_control_id]\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tfilter['table_name'] = 'user_date_total';\n\t\t\t\tfilter['object_id'] = this.parent_edit_record.id;\n\n\t\t\t}\n\n\t\t\treturn filter;\n\t\t};\n\n\t\treturn true;\n\t}\n\n\tgetEditSelectedRecordId( record_id ) {\n\t\treturn this.getSelectedRecordId( record_id );\n\t}\n\n\tdoEditAPICall( filter, api_args ) {\n\t\tvar current_api = this.getCurrentAPI();\n\t\tvar callback = { onResult: this.handleEditAPICallbackResult.bind( this ) };\n\t\tif ( api_args ) {\n\t\t\t// If api_args specified, use api_args.filter, and ignore function filter parameter.\n\t\t\tapi_args.push( callback );\n\t\t\treturn current_api['get' + current_api.key_name].apply( current_api, api_args );\n\t\t} else {\n\t\t\treturn current_api['get' + current_api.key_name]( filter, callback );\n\t\t}\n\t}\n\n\tonEditClick( record_id, type ) {\n\t\tvar tmp_record_id = this.getViewSelectedRecordId( record_id );\n\t\tif ( Global/* Global.isFalseOrNull */.x.isFalseOrNull( tmp_record_id ) || tmp_record_id == TTUUID/* TTUUID.not_exist_id */.d.not_exist_id ) {\n\t\t\tTAlertManager.showAlert( TimeSheetViewController_$.i18n._( 'This punch is still being processed, please try again later.' ) );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type ) {\n\t\t\tif ( type === 'absence' ) {\n\t\t\t\tthis.absence_model = true;\n\t\t\t} else {\n\t\t\t\tthis.absence_model = false;\n\t\t\t}\n\t\t}\n\t\tsuper.onEditClick( record_id );\n\t}\n\n\tsetURL() {\n\t\tvar t = this.getPunchPermissionType();\n\t\tvar a = '';\n\t\tswitch ( LocalCacheData.current_doing_context_action ) {\n\t\t\tcase 'new':\n\t\t\tcase 'edit':\n\t\t\tcase 'view':\n\t\t\t\ta = LocalCacheData.current_doing_context_action;\n\t\t\t\tbreak;\n\t\t\tcase 'copy_as_new':\n\t\t\t\ta = 'new';\n\t\t\t\tbreak;\n\t\t}\n\n\t\tvar tab_name = this.edit_view_tab ? this.edit_view_tab.find( '.edit-view-tab-bar-label' ).children().eq( this.getEditViewTabIndex() ).text() : '';\n\t\ttab_name = tab_name.replace( /\\/|\\s+/g, '' );\n\n\t\t//Error: Unable to get property 'id' of undefined or null reference in /interface/html5/views/BaseViewController.js?v=8.0.0-20141117-132941 line 2234\n\t\tif ( this.current_edit_record && this.current_edit_record.id ) {\n\n\t\t\tif ( a ) {\n\t\t\t\t//Global.setURLToBrowser( Global.getBaseURL() + '#!m=' + this.viewId + '&date=' + this.start_date_picker.getDefaultFormatValue() + '&user_id=' + this.getSelectEmployee() + '&show_wage=' + this.wage_btn.getValue( true ) + '&mode=' + this.toggle_button.getValue() + '&a=' + a + '&id=' + this.current_edit_record.id + '&t=' + t +\n\t\t\t\tGlobal/* Global.setURLToBrowser */.x.setURLToBrowser( Global/* Global.getBaseURL */.x.getBaseURL() + '#!m=' + this.viewId + '&user_id=' + this.getSelectEmployee() + '&show_wage=' + this.wage_btn.getValue( true ) + '&mode=' + this.toggle_button.getValue() + '&a=' + a + '&id=' + this.current_edit_record.id + '&t=' + t + '&tab=' + tab_name );\n\t\t\t} else {\n\t\t\t\t//Global.setURLToBrowser( Global.getBaseURL() + '#!m=' + this.viewId + '&date=' + this.start_date_picker.getDefaultFormatValue() + '&user_id=' + this.getSelectEmployee() + '&show_wage=' + this.wage_btn.getValue( true ) + '&mode=' + this.toggle_button.getValue() + '&id=' + this.current_edit_record.id + '&t=' + t );\n\t\t\t\tGlobal/* Global.setURLToBrowser */.x.setURLToBrowser( Global/* Global.getBaseURL */.x.getBaseURL() + '#!m=' + this.viewId + '&user_id=' + this.getSelectEmployee() + '&show_wage=' + this.wage_btn.getValue( true ) + '&mode=' + this.toggle_button.getValue() + '&id=' + this.current_edit_record.id + '&t=' + t );\n\t\t\t}\n\n\t\t\tGlobal/* Global.trackView */.x.trackView();\n\n\t\t} else {\n\n\t\t\tif ( a ) {\n\t\t\t\t//Global.setURLToBrowser( Global.getBaseURL() + '#!m=' + this.viewId + '&date=' + this.start_date_picker.getDefaultFormatValue() + '&user_id=' + this.getSelectEmployee() + '&show_wage=' + this.wage_btn.getValue( true ) + '&mode=' + this.toggle_button.getValue() + '&a=' + a + '&t=' + t +\n\t\t\t\tGlobal/* Global.setURLToBrowser */.x.setURLToBrowser( Global/* Global.getBaseURL */.x.getBaseURL() + '#!m=' + this.viewId + '&user_id=' + this.getSelectEmployee() + '&show_wage=' + this.wage_btn.getValue( true ) + '&mode=' + this.toggle_button.getValue() + '&a=' + a + '&t=' + t + '&tab=' + tab_name );\n\t\t\t} else {\n\t\t\t\t//Global.setURLToBrowser( Global.getBaseURL() + '#!m=' + this.viewId + '&date=' + this.start_date_picker.getDefaultFormatValue() + '&user_id=' + this.getSelectEmployee() + '&show_wage=' + this.wage_btn.getValue( true ) + '&mode=' + this.toggle_button.getValue() + '&t=' + t );\n\t\t\t\tGlobal/* Global.setURLToBrowser */.x.setURLToBrowser( Global/* Global.getBaseURL */.x.getBaseURL() + '#!m=' + this.viewId + '&user_id=' + this.getSelectEmployee() + '&show_wage=' + this.wage_btn.getValue( true ) + '&mode=' + this.toggle_button.getValue() + '&t=' + t );\n\t\t\t}\n\n\t\t}\n\t}\n\n\tonCustomContextClick( id ) {\n\t\tswitch ( id ) {\n\t\t\tcase 'add': //This is caught by onContextMenuClick(), so we have to use a different id: add_punch instead.\n\t\t\tcase 'add_punch':\n\t\t\t\tthis.absence_model = false;\n\t\t\t\tthis.onAddClick();\n\t\t\t\tbreak;\n\t\t\tcase 'add_absence':\n\t\t\t\tthis.absence_model = true;\n\t\t\t\tthis.onAddClick();\n\t\t\t\tbreak;\n\t\t\tcase 'move':\n\t\t\tcase 'drag_copy':\n\t\t\t\tthis.setMoveOrDropMode( id );\n\t\t\t\tbreak;\n\t\t\tcase 'in_out':\n\t\t\t\tMenuManager.openSelectView( 'InOut' );\n\t\t\t\tbreak;\n\t\t\tcase 'schedule':\n\t\t\tcase 'pay_stub':\n\t\t\tcase 'edit_employee':\n\t\t\tcase 'edit_pay_period':\n\t\t\t\tthis.onNavigationClick( id );\n\t\t\t\tbreak;\n\t\t\tcase 're_calculate_timesheet':\n\t\t\tcase 'generate_pay_stub':\n\t\t\t\tthis.onWizardClick( id );\n\t\t\t\tbreak;\n\t\t\tcase 'map':\n\t\t\t\tthis.onMapClick( id );\n\t\t\t\tbreak;\n\t\t\tcase 'accumulated_time':\n\t\t\t\tthis.onAccumulatedTimeClick( id );\n\t\t\t\tbreak;\n\t\t\tcase 'AddRequest':\n\t\t\t\t// Preventing TypeError: Cannot read property 'date' of undefined\n\t\t\t\tif ( this.select_cells_Array.length > 0 ) {\n\t\t\t\t\tthis.addRequestFromTimesheetCell( id );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'print_summary':\n\t\t\tcase 'print_detailed':\n\t\t\t\tthis.onReportMenuClick( id );\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\taddRequestFromTimesheetCell( id ) {\n\t\tif ( Global/* Global.getProductEdition */.x.getProductEdition() <= 10 ) {\n\t\t\tTAlertManager.showAlert( Global/* Global.getUpgradeMessage */.x.getUpgradeMessage() );\n\t\t\treturn false;\n\t\t}\n\n\t\tvar current_column_field = Global/* Global.strToDate */.x.strToDate( this.select_cells_Array[0].date ? this.select_cells_Array[0].date : this.start_date_picker.getValue() ).format( this.full_format );\n\n\t\tif ( this.select_cells_Array[0].punch ) {\n\t\t\tvar punch_control_id = this.select_cells_Array[0].punch.punch_control_id;\n\t\t\tvar current_punch_id = this.select_cells_Array[0].punch.id;\n\t\t\tvar current_punch_status_id = this.select_cells_Array[0].punch.status_id;\n\t\t\tvar type_id = this.select_cells_Array[0].punch.type_id;\n\t\t\tvar user_id = this.select_cells_Array[0].punch.user_id;\n\t\t} else {\n\t\t\tvar user_id = this.getSelectEmployee();\n\t\t\tvar punch_control_id = null;\n\t\t\tvar current_punch_id = null;\n\t\t\tvar current_punch_status_id = 10;\n\t\t\tvar type_id = 10;\n\t\t}\n\n\t\tvar previous_punch_id = null;\n\t\tif ( !current_punch_id ) {\n\t\t\t//row_id is numeric here.\n\t\t\tif ( this.select_cells_Array[0].row_id > 1 && this.timesheet_data_source[this.select_cells_Array[0].row_id - 2] && this.timesheet_data_source[this.select_cells_Array[0].row_id - 2][current_column_field + '_data'] ) {\n\t\t\t\tprevious_punch_id = this.timesheet_data_source[this.select_cells_Array[0].row_id - 2][current_column_field + '_data'].id;\n\t\t\t\ttype_id = this.timesheet_data_source[this.select_cells_Array[0].row_id - 2][current_column_field + '_data'].type_id;\n\t\t\t\tvar tmp_status_id = this.timesheet_data_source[this.select_cells_Array[0].row_id - 2][current_column_field + '_data'].status_id;\n\n\t\t\t\t// Issue #2895 - Request text would show a break / lunch out even though the last punch was an in.\n\t\t\t\tif ( current_punch_status_id == 10 && tmp_status_id == 10 && type_id != 10 ) { //Status 10=In,20=Out -- Type: 10=Normal, 20=Lunch, 30=Break\n\t\t\t\t\t// This has to be a normal out punch as the last punch was an in.\n\t\t\t\t\ttype_id = 10;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//blank and has no previous punch so we need to infer status_id from the selected row's status\n\t\t\tif ( this.timesheet_data_source[this.select_cells_Array[0].row_id - 1] ) {\n\t\t\t\tcurrent_punch_status_id = this.timesheet_data_source[this.select_cells_Array[0].row_id - 1].status_id;\n\t\t\t}\n\t\t}\n\n\t\tvar date = this.select_cells_Array[0].time_stamp_num / 1000;\n\t\tvar $this = this;\n\t\tthis.api_punch.getRequestDefaultData(\n\t\t\tuser_id,\n\t\t\tdate,\n\t\t\tpunch_control_id,\n\t\t\tprevious_punch_id,\n\t\t\tcurrent_punch_status_id,\n\t\t\ttype_id,\n\t\t\tcurrent_punch_id, {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\tvar request = result.getResult();\n\t\t\t\t\tIndexViewController.openEditView( $this, 'Request', request, null, 'openAddView' );\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n\tgetPayPeriod( date ) {\n\t\tvar current_date = this.getSelectDate();\n\n\t\t//if pass a date in, use the date\n\t\tif ( date ) {\n\t\t\tcurrent_date = date;\n\t\t}\n\n\t\tif ( this.pay_period_map && this.pay_period_map[current_date] && this.pay_period_map[current_date] != TTUUID/* TTUUID.zero_id */.d.zero_id && TTUUID/* TTUUID.isUUID */.d.isUUID( this.pay_period_map[current_date] ) == true ) {\n\t\t\treturn this.pay_period_map[current_date];\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tonNavigationClick( iconName ) {\n\n\t\tif ( !this.checkTimesheetData() ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar post_data;\n\n\t\tswitch ( iconName ) {\n\t\t\tcase 'in_out':\n\t\t\t\tIndexViewController.openEditView( LocalCacheData.current_open_primary_controller, 'InOut' );\n\t\t\t\tbreak;\n\t\t\tcase 'edit_employee':\n\t\t\t\tIndexViewController.openEditView( this, 'Employee', this.getSelectEmployee() );\n\t\t\t\tbreak;\n\t\t\tcase 'edit_pay_period':\n\t\t\t\tvar pay_period_id = this.getPayPeriod();\n\t\t\t\tif ( pay_period_id ) {\n\t\t\t\t\tIndexViewController.openEditView( this, 'PayPeriods', pay_period_id );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'schedule':\n\t\t\t\tvar filter = { filter_data: {} };\n\t\t\t\tvar include_users = { value: [this.getSelectEmployee()] };\n\t\t\t\tfilter.filter_data.include_user_ids = include_users;\n\t\t\t\tfilter.select_date = this.getSelectDate();\n\n\t\t\t\tGlobal/* Global.addViewTab */.x.addViewTab( this.viewId, TimeSheetViewController_$.i18n._( 'TimeSheet' ), window.location.href );\n\t\t\t\tIndexViewController.goToView( 'Schedule', filter );\n\n\t\t\t\tbreak;\n\t\t\tcase 'pay_stub':\n\t\t\t\tfilter = { filter_data: {} };\n\t\t\t\tvar users = { value: [this.getSelectEmployee()] };\n\t\t\t\tfilter.filter_data.user_id = users;\n\n\t\t\t\tGlobal/* Global.addViewTab */.x.addViewTab( this.viewId, TimeSheetViewController_$.i18n._( 'TimeSheet' ), window.location.href );\n\t\t\t\tIndexViewController.goToView( 'PayStub', filter );\n\n\t\t\t\tbreak;\n\t\t\tcase 'print_summary':\n\n\t\t\t\tfilter = { time_period: {} };\n\t\t\t\tfilter.time_period.time_period = 'custom_pay_period';\n\t\t\t\tfilter.time_period.pay_period_id = this.timesheet_verify_data.pay_period_id;\n\t\t\t\tfilter.include_user_id = [this.getSelectEmployee()];\n\t\t\t\tpost_data = { 0: filter, 1: 'pdf_timesheet' };\n\t\t\t\tthis.doFormIFrameCall( post_data );\n\t\t\t\tbreak;\n\t\t\tcase 'print_detailed':\n\t\t\t\tfilter = { time_period: {} };\n\t\t\t\tfilter.time_period.time_period = 'custom_pay_period';\n\t\t\t\tfilter.time_period.pay_period_id = this.timesheet_verify_data.pay_period_id;\n\t\t\t\tfilter.include_user_id = [this.getSelectEmployee()];\n\t\t\t\tpost_data = { 0: filter, 1: 'pdf_timesheet_detail' };\n\t\t\t\tthis.doFormIFrameCall( post_data );\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tdoFormIFrameCall( postData ) {\n\t\tGlobal/* Global.APIFileDownload */.x.APIFileDownload( 'APITimesheetDetailReport', 'getTimesheetDetailReport', postData );\n\t}\n\n\tonAccumulatedTimeClick() {\n\t\tif ( PermissionManager.checkTopLevelPermission( 'AccumulatedTime' ) ) {\n\t\t\tvar select_date = Global/* Global.strToDate */.x.strToDate( this.getSelectDate() ).format( 'YYYY-MM-DD' );\n\t\t\tIndexViewController.openEditView( this, 'UserDateTotalParent', select_date );\n\t\t}\n\t}\n\n\tonMapClick() {\n\t\t// only trigger map load in specific product editions.\n\t\tif ( ( Global/* Global.getProductEdition */.x.getProductEdition() >= 15 ) ) {\n\n\t\t\t// TODO: this is repeated below, perhaps in future now that getFilterColumnsFromDisplayColumns() is commented out, this can be consolidated?\n\t\t\tvar data = {\n\t\t\t\tfilter_columns: {\n\t\t\t\t\tid: true,\n\t\t\t\t\tlatitude: true,\n\t\t\t\t\tlongitude: true,\n\t\t\t\t\tpunch_date: true,\n\t\t\t\t\tpunch_time: true,\n\t\t\t\t\tposition_accuracy: true,\n\t\t\t\t\tuser_id: true\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tvar punches = [];\n\t\t\tvar map_options = {};\n\n\t\t\tif ( this.edit_view ) {\n\t\t\t\tpunches.push( this.current_edit_record );\n\t\t\t\tif ( !this.is_viewing ) {\n\t\t\t\t\t// make sure that when view only (so no save) marker is not draggable, and thus no new marker can be added either.\n\t\t\t\t\tmap_options.single_marker_draggable = true;\n\t\t\t\t}\n\t\t\t} else if ( this.select_punches_array && this.select_punches_array.length > 0 ) {\n\t\t\t\tvar ids = [];\n\t\t\t\tthis.select_punches_array.map( function( punch ) {\n\t\t\t\t\tif ( punch.id ) {\n\t\t\t\t\t\tids.push( punch.id );\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t\tdata.filter_data = Global/* Global.convertLayoutFilterToAPIFilter */.x.convertLayoutFilterToAPIFilter( this.select_layout );\n\t\t\t\tif ( data.filter_data && ids.length > 0 ) {\n\t\t\t\t\tdata.filter_data.id = ids;\n\t\t\t\t}\n\t\t\t\t// data.filter_columns = this.getFilterColumnsFromDisplayColumns()\n\t\t\t\tdata.filter_columns.first_name = true;\n\t\t\t\tdata.filter_columns.last_name = true;\n\t\t\t\tdata.filter_columns.user_id = true;\n\t\t\t\tdata.filter_columns.date_stamp = true; // #2735 - grouping punches by date_stamp instead of punch_date, to allow cross date punch controls to plot distances.\n\t\t\t\tdata.filter_columns.punch_date = true;\n\t\t\t\tdata.filter_columns.punch_time = true;\n\t\t\t\tdata.filter_columns.time_stamp = true;\n\t\t\t\tdata.filter_columns.status = true;\n\t\t\t\tdata.filter_columns.punch_control_id = true;\n\t\t\t\tdata.filter_columns.branch = true;\n\t\t\t\tdata.filter_columns.branch_id = true;\n\t\t\t\tdata.filter_columns.department = true;\n\t\t\t\tdata.filter_columns.department_id = true;\n\t\t\t\tdata.filter_columns.job_manual_id = true;\n\t\t\t\tdata.filter_columns.job = true;\n\t\t\t\tdata.filter_columns.job_id = true;\n\t\t\t\tdata.filter_columns.job_item_manual_id = true;\n\t\t\t\tdata.filter_columns.job_item = true; // also known as Task\n\t\t\t\tdata.filter_columns.job_item_id = true;\n\t\t\t\tdata.filter_columns.punch_tag = true;\n\t\t\t\tdata.filter_columns.punch_tag_id = true;\n\t\t\t\tdata.filter_columns.total_time = true;\n\t\t\t\tdata.filter_columns.latitude = true;\n\t\t\t\tdata.filter_columns.longitude = true;\n\t\t\t\tdata.filter_columns.position_accuracy = true;\n\n\t\t\t\tpunches = this.api.getPunch( data, { async: false } ).getResult();\n\t\t\t}\n\n\t\t\tif ( !this.is_mass_editing ) {\n\t\t\t\t// There is not enough detail in the 'punches' data pulled from the grid, get the full data from api, like PunchesViewController\n\t\t\t\t// Note there seems to be a multple ways to get the data e.g. select_punches_array,\n\t\t\t\t// but other view controllers use .getGridSelectIdArray() and theres also select_cells_Array.\n\t\t\t\t// TODO-future: Perhaps look at a future refactor/consolidation of all these?\n\n\t\t\t\tif ( Global/* Global.isArray */.x.isArray( punches ) ) {\n\t\t\t\t\tPromise.all(/* import() | leaflet-timetrex */[__webpack_require__.e(\"vendors-node_modules_leaflet_dist_images_marker-icon-2x_png-node_modules_leaflet_dist_images_-78d511\"), __webpack_require__.e(\"interface_html5_framework_leaflet_leaflet-timetrex_js\"), __webpack_require__.e(\"leaflet-timetrex\")]).then(__webpack_require__.bind(__webpack_require__, 6889)).then(( module )=>{\n\t\t\t\t\t\tvar processed_punches_for_map = module.TTConvertMapData.processPunchesFromViewController( punches, map_options );\n\t\t\t\t\t\tIndexViewController.openEditView( this, 'Map', processed_punches_for_map );\n\t\t\t\t\t}).catch( Global/* Global.importErrorHandler */.x.importErrorHandler );\n\t\t\t\t} else {\n\t\t\t\t\tDebug.Text( 'ERROR: Either punches is not an array, or data is empty', 'TimeSheetViewController.js', 'TimeSheetViewController', 'onMapClick', 1 );\n\t\t\t\t\tTAlertManager.showAlert( TimeSheetViewController_$.i18n._( 'Selected punches no longer exist, unable to map.' ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tonWizardClick( iconName ) {\n\n\t\tvar $this = this;\n\t\tswitch ( iconName ) {\n\t\t\tcase 're_calculate_timesheet':\n\t\t\t\tvar default_data = {};\n\t\t\t\tdefault_data.user_id = this.getSelectEmployee();\n\n\t\t\t\tvar pay_period_id = this.getPayPeriod();\n\t\t\t\tif ( pay_period_id ) {\n\t\t\t\t\tdefault_data.pay_period_id = pay_period_id;\n\t\t\t\t}\n\t\t\t\tIndexViewController.openWizard( 'ReCalculateTimeSheetWizard', default_data, function() {\n\n\t\t\t\t\t$this.onReCalTimeSheetDone();\n\t\t\t\t} );\n\t\t\t\tbreak;\n\t\t\tcase 'generate_pay_stub':\n\n\t\t\t\tdefault_data = {};\n\t\t\t\tdefault_data.user_id = this.getSelectEmployee();\n\n\t\t\t\tpay_period_id = this.getPayPeriod();\n\t\t\t\tif ( pay_period_id ) {\n\t\t\t\t\tdefault_data.pay_period_id = [pay_period_id];\n\t\t\t\t} else {\n\t\t\t\t\tdefault_data.pay_period_id = [];\n\t\t\t\t}\n\t\t\t\tIndexViewController.openWizard( 'GeneratePayStubWizard', default_data, function() {\n\t\t\t\t\t$this.search();\n\t\t\t\t} );\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tonReCalTimeSheetDone() {\n\t\t//Its possible the user has navigated away from the timesheet while a recalculation is in progress, if so, don't try to refresh the timesheet.\n\t\t//Also fixes: Uncaught TypeError: Failed to execute 'replaceChild' on 'Node': parameter 2 is not of type 'Node'.\n\n\t\tif ( MenuManager.isCurrentView( 'TimeSheet' ) ) {\n\t\t\tMenuManager.goToView( 'TimeSheet', true );\n\t\t\t//this.initData(); //Do a generic view refresh rather than just initData() as its less likely to cause problems.\n\t\t}\n\t}\n\n\tsetMoveOrDropMode( id ) {\n\t\tvar context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.determineContextMenuMountAttributes().id );\n\t\tvar drag_copy_icon = context_menu_array.find( icon => icon.id === 'drag_copy' );\n\t\tvar move_icon = context_menu_array.find( icon => icon.id === 'move' );\n\n\t\tif ( drag_copy_icon === undefined || move_icon === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tContextMenuManager.activateMenuItem( this.determineContextMenuMountAttributes().id, drag_copy_icon.id, true );\n\t\tContextMenuManager.activateMenuItem( this.determineContextMenuMountAttributes().id, move_icon.id, true );\n\t\tvar drag_invisible = false;\n\t\tvar move_invisible = false;\n\n\t\tif ( !this.copyPermissionValidate() ) {\n\t\t\tdrag_invisible = true;\n\t\t}\n\n\t\tif ( !this.movePermissionValidate() ) {\n\t\t\tmove_invisible = true;\n\t\t}\n\n\t\tif ( move_invisible && id === 'move' ) {\n\t\t\tContextMenuManager.activateMenuItem( this.determineContextMenuMountAttributes().id, drag_copy_icon.id, false );\n\t\t} else {\n\t\t\tvar icon = context_menu_array.find( icon => icon.id === id );\n\t\t\tContextMenuManager.activateMenuItem( this.determineContextMenuMountAttributes().id, icon.id, false );\n\t\t}\n\n\t\tif ( drag_invisible && move_invisible ) {\n\t\t\tthis.select_drag_menu_id = null;\n\t\t} else {\n\t\t\tthis.select_drag_menu_id = id;\n\t\t}\n\t}\n\n\tgetSelectDateArray() {\n\n\t\tvar result = [];\n\n\t\tvar cells_array = this.absence_model ? this.absence_select_cells_Array : this.select_cells_Array;\n\n\t\tvar len = cells_array.length;\n\n\t\tvar date_dic = {};\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar item = cells_array[i];\n\t\t\tdate_dic[item.date] = true;\n\t\t}\n\n\t\tfor ( var key in date_dic ) {\n\t\t\tresult.push( key );\n\t\t}\n\n\t\tif ( result.length === 0 ) {\n\t\t\tresult = [this.getSelectDate()];\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tonAddClick( doing_save_and_new ) {\n\t\tTTPromise.add( 'TimeSheetViewController', 'addclick' );\n\t\tTTPromise.wait();\n\t\tvar $this = this;\n\t\tthis.setCurrentEditViewState( 'new' );\n\t\tthis.is_mass_adding = true; //Is always true because we always want the user to be able to select multiple dates.\n\t\tvar punch_control_id = null;\n\t\tvar prev_punch_id = null;\n\t\tvar related_punch = null;\n\t\tvar date = this.getSelectDate();\n\t\tvar status_id = 10, type_id = 10, select_cell;\n\n\t\tif ( !this.absence_model ) {\n\t\t\tif ( this.select_cells_Array.length === 1 ) {\n\t\t\t\tvar select_item = this.select_cells_Array[0];\n\t\t\t\tif ( select_item.related_punch ) {\n\t\t\t\t\trelated_punch = select_item.related_punch;\n\t\t\t\t\tpunch_control_id = select_item.related_punch.punch_control_id;\n\t\t\t\t\tprev_punch_id = select_item.related_punch.id;\n\t\t\t\t} else {\n\t\t\t\t\t//Error: Uncaught TypeError: Cannot read property 'format' of null in interface/html5/#!m=TimeSheet&date=20151006&user_id=51085&show_wage=0 line 6292\n\t\t\t\t\tvar current_column_field = Global/* Global.strToDate */.x.strToDate( select_item.date ? select_item.date : this.start_date_picker.getValue() ).format( this.full_format );\n\n\t\t\t\t\t//row_id is nbumeric here\n\t\t\t\t\tif ( this.timesheet_data_source && this.timesheet_data_source[select_item.row_id - 2] ) {\n\t\t\t\t\t\tvar pre_punch = this.timesheet_data_source[select_item.row_id - 2][current_column_field + '_data'];\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( pre_punch ) {\n\t\t\t\t\t\tprev_punch_id = pre_punch.id;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\t\t\t// To use proper context menu for each punch or abseonce mode.\n\t\t\tthis.setDefaultMenu();\n\t\t\t$this.openEditView();\n\n\t\t\tif ( doing_save_and_new ) {\n\t\t\t\tdate = this.current_edit_record.punch_date;\n\t\t\t\trelated_punch = null;\n\t\t\t\tif ( this.current_edit_record.status_id == 10 ) {\n\t\t\t\t\tpunch_control_id = this.current_edit_record.punch_control_id;\n\t\t\t\t} else {\n\t\t\t\t\tpunch_control_id = null;\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( this.select_cells_Array.length === 1 ) {\n\t\t\t\tselect_cell = this.select_cells_Array[0];\n\t\t\t\tstatus_id = select_cell.status_id;\n\n\t\t\t\tvar select_date = Global/* Global.strToDate */.x.strToDate( this.start_date_picker.getValue() );\n\t\t\t\tvar new_date = new Date( new Date( select_date.getTime() ).setDate( select_date.getDate() - 1 ) );\n\t\t\t\tif ( new_date.getTime() < this.start_date.getTime() ) {\n\t\t\t\t\ttype_id = 10;\n\t\t\t\t} else {\n\t\t\t\t\tvar row_data = this.timesheet_data_source[select_cell.row_id - 1];\n\t\t\t\t\t//Error: Unable to get property 'Sun-Dec-13-2015_data' of undefined or null reference in interface/html5/ line 6362\n\t\t\t\t\tvar left_side_punch = row_data && row_data[new_date.format( this.full_format ) + '_data'];\n\t\t\t\t\tif ( left_side_punch ) {\n\t\t\t\t\t\ttype_id = left_side_punch.type_id;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttype_id = 10;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tselect_cell = this.select_cells_Array[0];\n\t\t\t\tif ( select_cell && select_cell.status_id ) {\n\t\t\t\t\tstatus_id = select_cell.status_id;\n\t\t\t\t} else {\n\t\t\t\t\tstatus_id = 10; //In\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.api['get' + this.api.key_name + 'DefaultData']( this.getSelectEmployee(),\n\t\t\t\tdate,\n\t\t\t\tpunch_control_id,\n\t\t\t\tprev_punch_id,\n\t\t\t\tstatus_id,\n\t\t\t\ttype_id,\n\t\t\t\t{\n\t\t\t\t\tonResult: function( result ) {\n\n\t\t\t\t\t\tvar result_data = result.getResult();\n\n\t\t\t\t\t\tif ( !Global/* Global.isSet */.x.isSet( result_data.time_stamp ) ) {\n\t\t\t\t\t\t\tresult_data.time_stamp = false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tresult_data.punch_date = $this.getSelectDate();\n\n\t\t\t\t\t\tif ( doing_save_and_new ) {\n\t\t\t\t\t\t\tresult_data.punch_date = $this.current_edit_record.punch_date;\n\n\t\t\t\t\t\t\tif ( $this.current_edit_record.status_id == 10 ) {\n\t\t\t\t\t\t\t\tresult_data.status_id = 20;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tresult_data.status_id = 10;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$this.current_edit_record = result_data;\n\t\t\t\t\t\t$this.initEditView();\n\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t} else { //Absence model branch\n\n\t\t\tif ( doing_save_and_new ) {\n\t\t\t\tdate = this.current_edit_record.date_stamp;\n\t\t\t}\n\t\t\t// To use proper context menu for each punch or abseonce mode.\n\t\t\t$this.setDefaultMenu();\n\t\t\t$this.openEditView();\n\t\t\tthis.api_user_date_total['get' + this.api_user_date_total.key_name + 'DefaultData']( this.getSelectEmployee(),\n\t\t\t\tdate,\n\t\t\t\t{\n\t\t\t\t\tonResult: function( result ) {\n\n\t\t\t\t\t\tvar result_data = result.getResult();\n\n\t\t\t\t\t\tif ( !Global/* Global.isSet */.x.isSet( result_data.time_stamp ) ) {\n\t\t\t\t\t\t\tresult_data.time_stamp = false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( Global/* Global.isSet */.x.isSet( $this.absence_select_cells_Array[0] ) ) {\n\t\t\t\t\t\t\tresult_data.src_object_id = $this.absence_select_cells_Array[0].src_object_id;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tresult_data.object_type_id = 50;\n\n\t\t\t\t\t\tresult_data.date_stamp = $this.getSelectDate();\n\t\t\t\t\t\t$this.current_edit_record = result_data;\n\t\t\t\t\t\t$this.initEditView();\n\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t}\n\t}\n\n\tremoveEditView() {\n\t\tsuper.removeEditView();\n\t\tif ( this.absence_select_cells_Array.length > 0 ) {\n\t\t\tthis.absence_model = true;\n\t\t} else {\n\t\t\tthis.absence_model = false;\n\t\t}\n\t\tthis.setDefaultMenu();\n\t}\n\n\tisMassDate() {\n\t\t//Error: Unable to get property 'punch_dates' of undefined or null reference in /interface/html5/ line 6300\n\t\tif ( this.is_mass_adding && this.current_edit_record && this.current_edit_record.punch_dates && this.current_edit_record.punch_dates.length > 1 ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tsetEditMenuSaveAndContinueIcon( context_btn ) {\n\t\tthis.saveAndContinueValidate( context_btn, this.getPunchPermissionType() );\n\n\t\tif ( this.is_mass_editing || this.is_viewing || this.isMassDate() ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tonSaveAndNewClick( ignoreWarning ) {\n\t\tvar $this = this;\n\t\tif ( !Global/* Global.isSet */.x.isSet( ignoreWarning ) ) {\n\t\t\tignoreWarning = false;\n\t\t}\n\t\tvar current_api = this.getCurrentAPI();\n\t\tLocalCacheData.current_doing_context_action = 'new';\n\n\t\tvar record = this.current_edit_record;\n\n\t\tif ( this.is_mass_adding ) {\n\n\t\t\trecord = [];\n\t\t\tvar dates_array = this.current_edit_record.punch_dates;\n\n\t\t\tif ( dates_array && dates_array.indexOf( ' - ' ) > 0 ) {\n\t\t\t\tdates_array = this.parserDatesRange( dates_array );\n\t\t\t}\n\n\t\t\tfor ( var i = 0; i < dates_array.length; i++ ) {\n\t\t\t\tvar common_record = Global/* Global.clone */.x.clone( this.current_edit_record );\n\t\t\t\tdelete common_record.punch_dates;\n\t\t\t\tif ( this.absence_model ) {\n\t\t\t\t\tcommon_record.date_stamp = dates_array[i];\n\t\t\t\t} else {\n\t\t\t\t\tcommon_record.punch_date = dates_array[i];\n\t\t\t\t}\n\n\t\t\t\trecord.push( common_record );\n\t\t\t}\n\t\t}\n\n\t\tcurrent_api.setIsIdempotent( true ); //Force to idempotent API call to avoid duplicate network requests from causing errors displayed to the user.\n\t\tcurrent_api['set' + current_api.key_name]( record, false, ignoreWarning, {\n\t\t\tonResult: function( result ) {\n\t\t\t\tif ( result.isValid() ) {\n\t\t\t\t\t$this.search( false );\n\t\t\t\t\t$this.onAddClick( true );\n\t\t\t\t} else {\n\t\t\t\t\t$this.setErrorMenu();\n\t\t\t\t\t$this.setErrorTips( result );\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\t_continueDoCopyAsNew() {\n\t\tvar $this = this;\n\t\tLocalCacheData.current_doing_context_action = 'copy_as_new';\n\t\tthis.is_mass_adding = true;\n\n\t\tif ( Global/* Global.isSet */.x.isSet( this.edit_view ) ) {\n\t\t\tthis.current_edit_record.id = '';\n\n\t\t\tif ( !this.absence_model ) {\n\n\t\t\t\tthis.current_edit_record.punch_control_id = '';\n\n\t\t\t\tif ( this.current_edit_record.status_id == 10 ) {\n\t\t\t\t\tthis.current_edit_record.status_id = 20;\n\n\t\t\t\t} else {\n\t\t\t\t\tthis.current_edit_record.status_id = 10;\n\t\t\t\t}\n\n\t\t\t\tthis.edit_view_ui_dic['status_id'].setValue( this.current_edit_record.status_id );\n\t\t\t}\n\n\t\t\tvar navigation_div = this.edit_view.find( '.navigation-div' );\n\t\t\tnavigation_div.css( 'display', 'none' );\n\t\t\tthis.openEditView();\n\t\t\tthis.initEditView();\n\t\t\tthis.setEditMenu();\n\t\t\tthis.setTabStatus();\n\t\t\tthis.is_changed = false;\n\t\t\tProgressBar.closeOverlay();\n\t\t}\n\t}\n\n\tonSaveAndCopy( ignoreWarning ) {\n\t\tvar $this = this;\n\t\tif ( !Global/* Global.isSet */.x.isSet( ignoreWarning ) ) {\n\t\t\tignoreWarning = false;\n\t\t}\n\t\tvar current_api = this.getCurrentAPI();\n\t\tthis.is_changed = false;\n\t\tLocalCacheData.current_doing_context_action = 'save_and_copy';\n\t\tvar record = this.current_edit_record;\n\t\tif ( this.is_mass_adding ) {\n\n\t\t\trecord = [];\n\t\t\tvar dates_array = this.current_edit_record.punch_dates;\n\n\t\t\tif ( dates_array && dates_array.indexOf( ' - ' ) > 0 ) {\n\t\t\t\tdates_array = this.parserDatesRange( dates_array );\n\t\t\t}\n\n\t\t\tfor ( var i = 0; i < dates_array.length; i++ ) {\n\t\t\t\tvar common_record = Global/* Global.clone */.x.clone( this.current_edit_record );\n\t\t\t\tdelete common_record.punch_dates;\n\t\t\t\tif ( this.absence_model ) {\n\t\t\t\t\tcommon_record.date_stamp = dates_array[i];\n\t\t\t\t} else {\n\t\t\t\t\tcommon_record.punch_date = dates_array[i];\n\t\t\t\t}\n\n\t\t\t\trecord.push( common_record );\n\t\t\t}\n\t\t}\n\n\t\tthis.clearNavigationData();\n\n\t\tcurrent_api.setIsIdempotent( true ); //Force to idempotent API call to avoid duplicate network requests from causing errors displayed to the user.\n\t\tcurrent_api['set' + current_api.key_name]( record, false, ignoreWarning, {\n\t\t\tonResult: function( result ) {\n\t\t\t\tif ( result.isValid() ) {\n\t\t\t\t\tvar result_data = result.getResult();\n\t\t\t\t\t$this.search( false );\n\t\t\t\t\t$this.onCopyAsNewClick();\n\t\t\t\t} else {\n\t\t\t\t\t$this.setErrorMenu();\n\t\t\t\t\t$this.setErrorTips( result );\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tgetCurrentAPI() {\n\t\tvar current_api = this.api;\n\n\t\tif ( this.absence_model ) {\n\t\t\tcurrent_api = this.api_user_date_total;\n\t\t}\n\n\t\treturn current_api;\n\t}\n\n\tgenerateManualTimeSheetRecordKey( item ) {\n\t\tvar key = item.date_stamp + '-' + ( ( this.show_branch_ui && item.branch_id ) ? item.branch_id : TTUUID/* TTUUID.zero_id */.d.zero_id ) +\n\t\t\t'-' + ( ( this.show_department_ui && item.department_id ) ? item.department_id : TTUUID/* TTUUID.zero_id */.d.zero_id )\n\t\t\t+ '-' + ( ( this.show_job_ui && item.job_id && Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ? item.job_id : TTUUID/* TTUUID.zero_id */.d.zero_id ) +\n\t\t\t'-' + ( ( this.show_job_item_ui && item.job_item_id && Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ? item.job_item_id : TTUUID/* TTUUID.zero_id */.d.zero_id ) +\n\t\t\t'-' + ( ( this.show_punch_tag_ui && item.punch_tag_id && item.punch_tag_id.length > 0 && Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ? item.punch_tag_id : TTUUID/* TTUUID.zero_id */.d.zero_id ) +\n\t\t\t'-' + item.total_time;\n\n\t\treturn key;\n\t}\n\n\tcreateCurrentManualGridRecordsMap( records ) {\n\t\tthis.manual_grid_records_map = {};\n\n\t\tfor ( var i = 0, m = records.length; i < m; i++ ) {\n\t\t\tvar item = records[i];\n\n\t\t\tvar key = this.generateManualTimeSheetRecordKey( item );\n\t\t\tif ( item.id ) {\n\t\t\t\tkey = item.id + '-' + key;\n\t\t\t}\n\n\t\t\tthis.manual_grid_records_map[key] = item.row;\n\t\t\tdelete item.row;\n\t\t}\n\t}\n\n\t//Don't send records with blank total_time to the API, to better handle cases where the employees hire date is in the middle of the week and they accidently enter time on the Monday, which cause a popup validation error.\n\t//This allows them to get out of the scenario by simply clearing out the field or setting it back to 0.\n\tfilterManualGridRecords( records ) {\n\t\tvar retarr = Array();\n\n\t\tfor ( var i = 0; i < records.length; i++ ) {\n\t\t\tvar item = records[i];\n\n\t\t\tif ( item.id || ( !item.id && item.total_time && item.total_time != 0 ) ) {\n\t\t\t\tretarr.push( item );\n\t\t\t}\n\t\t}\n\n\t\treturn retarr;\n\t}\n\n\tonSaveClick( ignoreWarning ) {\n\t\tvar $this = this;\n\t\tvar record;\n\t\t// Save manual punch\n\t\tif ( this.getPunchMode() === 'manual' && !this.edit_view ) {\n\t\t\tvar records = this.editor.getValue( true ); // reset is_changed\n\t\t\tif ( records.length > 0 ) {\n\t\t\t\tthis.wait_auto_save && clearTimeout( this.wait_auto_save );\n\t\t\t\tthis.createCurrentManualGridRecordsMap( records );\n\t\t\t\tProgressBar.noProgressForNextCall();\n\t\t\t\tthis.is_saving_manual_grid = true;\n\t\t\t\tthis.setDefaultMenu();\n\n\t\t\t\trecords = this.filterManualGridRecords( records );\n\t\t\t\tif ( records.length > 0 ) {\n\t\t\t\t\tthis.api_user_date_total['set' + this.api_user_date_total.key_name]( records, {\n\t\t\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t\t\tif ( !result.isValid() ) {\n\t\t\t\t\t\t\t\tTAlertManager.showErrorAlert( result );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t$this.updateManualGrid();\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t} else {\n\t\t\t\t\t$this.updateManualGrid();\n\t\t\t\t}\n\n\t\t\t\tProgressBar.showNanobar();\n\t\t\t\tProgressBar.closeOverlay();\n\t\t\t} else {\n\t\t\t\tProgressBar.closeOverlay();\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t//Save normal punch\n\t\tif ( !Global/* Global.isSet */.x.isSet( ignoreWarning ) ) {\n\t\t\tignoreWarning = false;\n\t\t}\n\t\tLocalCacheData.current_doing_context_action = 'save';\n\t\tvar current_api = this.getCurrentAPI();\n\n\t\tif ( this.is_mass_editing ) {\n\n\t\t\tvar check_fields = {};\n\t\t\tfor ( var key in this.edit_view_ui_dic ) {\n\t\t\t\tvar widget = this.edit_view_ui_dic[key];\n\n\t\t\t\tif ( Global/* Global.isSet */.x.isSet( widget.isChecked ) ) {\n\t\t\t\t\tif ( widget.isChecked() ) {\n\t\t\t\t\t\tcheck_fields[key] = this.current_edit_record[key];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trecord = [];\n\t\t\tTimeSheetViewController_$.each( this.mass_edit_record_ids, function( index, value ) {\n\t\t\t\tvar common_record = Global/* Global.clone */.x.clone( check_fields );\n\t\t\t\tcommon_record.id = value;\n\t\t\t\trecord.push( common_record );\n\n\t\t\t} );\n\t\t} else {\n\t\t\trecord = this.current_edit_record;\n\t\t}\n\n\t\t// Error: Uncaught TypeError: Cannot read property 'punch_dates' of null in /interface/html5/#!m=TimeSheet&date=20150323&user_id=69543 line 6448\n\t\tif ( this.is_mass_adding && this.current_edit_record ) {\n\n\t\t\trecord = [];\n\t\t\tvar dates_array = this.current_edit_record.punch_dates;\n\n\t\t\tif ( dates_array && dates_array.indexOf( ' - ' ) > 0 ) {\n\t\t\t\tdates_array = this.parserDatesRange( dates_array );\n\t\t\t}\n\n\t\t\tfor ( var i = 0; i < dates_array.length; i++ ) {\n\t\t\t\tvar common_record = Global/* Global.clone */.x.clone( this.current_edit_record );\n\t\t\t\tdelete common_record.punch_dates;\n\t\t\t\tif ( this.absence_model ) {\n\t\t\t\t\tcommon_record.date_stamp = dates_array[i];\n\t\t\t\t} else {\n\t\t\t\t\tcommon_record.punch_date = dates_array[i];\n\t\t\t\t}\n\n\t\t\t\trecord.push( common_record );\n\t\t\t}\n\t\t}\n\n\t\tcurrent_api.setIsIdempotent( true ); //Force to idempotent API call to avoid duplicate network requests from causing errors displayed to the user.\n\t\tcurrent_api['set' + current_api.key_name]( record, false, ignoreWarning, {\n\t\t\tonResult: function( result ) {\n\n\t\t\t\tif ( result.isValid() ) {\n\t\t\t\t\t$this.first_build = true;\n\t\t\t\t\t$this.search();\n\n\t\t\t\t\t$this.removeEditView();\n\n\t\t\t\t\t//#2295 - Re-initialize previous_absence_policy_id to ensure that previously saved values are passed correctly into the estimation of projected available balance.\n\t\t\t\t\t$this.previous_absence_policy_id = false;\n\t\t\t\t} else {\n\t\t\t\t\t$this.setErrorMenu();\n\t\t\t\t\t$this.setErrorTips( result );\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tonMapSaveClick( dataset, successCallback ) {\n\t\tthis.savePunchPosition( dataset, successCallback );\n\t}\n\n\tsavePunchPosition( moved_unsaved_markers, successCallback ) {\n\t\tif ( !moved_unsaved_markers || moved_unsaved_markers.length !== 1 ) {\n\t\t\tDebug.Text( 'ERROR: Invalid params/data passed to function.', 'TimesheetViewConroller.js', 'TimesheetViewConroller', 'savePunchPosition', 1 );\n\t\t\treturn false;\n\t\t}\n\t\tthis.setLocationValue( moved_unsaved_markers[0] );\n\t\tsuccessCallback();\n\t\tthis.is_changed = true;\n\t\treturn true;\n\t}\n\n\tgetOtherFieldTypeId() {\n\t\tvar res = 15;\n\n\t\tif ( this.absence_model ) {\n\t\t\tres = 0;\n\t\t}\n\n\t\treturn res;\n\t}\n\n\t/**\n\t * This function is special as it handles an edit view that deals with both absences and punches.\n\t * This is the only place where 2 different data layouts need to be handled by the same navigation without a change of view.\n\t */\n\tsetEditViewData() {\n\t\tvar $this = this;\n\t\tvar navigation_div = this.edit_view.find( '.navigation-div' );\n\t\tvar navigation_widget_div = navigation_div.find( '.navigation-widget-div' );\n\n\t\tthis.is_changed = false;\n\n\t\tif ( Global/* Global.isSet */.x.isSet( this.current_edit_record.id ) && this.current_edit_record.id ) {\n\t\t\t//fixing both #2171 and #2227\n\t\t\t//preventing unclickable navigation and \"cannot find property or function has of undefined.\"\n\t\t\tnavigation_div.css( 'display', 'block' );\n\t\t\tthis.navigation = Global/* Global.loadWidgetByName */.x.loadWidgetByName( FormItemType.AWESOME_BOX );\n\n\t\t\t//Set Navigation Awesomebox\n\t\t\tif ( this.absence_model ) {\n\t\t\t\tthis.navigation.AComboBox( {\n\t\t\t\t\tid: this.script_name + '_navigation',\n\t\t\t\t\tlayout_name: 'global_absence'\n\t\t\t\t} );\n\n\t\t\t\tif ( this.absence_original_source ) {\n\t\t\t\t\tthis.navigation.setSourceData( this.absence_original_source );\n\t\t\t\t\tthis.navigation.is_punch_nav = false;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.navigation.AComboBox( {\n\t\t\t\t\tid: this.script_name + '_navigation',\n\t\t\t\t\tlayout_name: 'global_timesheet'\n\t\t\t\t} );\n\n\t\t\t\tif ( this.full_timesheet_data ) {\n\t\t\t\t\tthis.navigation.setSourceData( this.full_timesheet_data.punch_data );\n\t\t\t\t\tthis.navigation.is_punch_nav = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.navigation.setValue( this.current_edit_record );\n\n\t\t\tnavigation_widget_div.html( this.navigation );\n\t\t\t// #2122 - Fixes navigation errors including: \"Cannot read property 'current_page' of null\" & \"Cannot read property 'has' of null\"\n\t\t\t// Prevents user clicking on drop-down to navigate to the first record then immediately clicking the left arrow which triggers the errors.\n\t\t\tthis.setNavigation();\n\n\t\t} else {\n\t\t\tnavigation_div.css( 'display', 'none' );\n\t\t}\n\n\t\tfor ( var key in this.edit_view_ui_dic ) {\n\n\t\t\t//Set all UI field to current edit record, we need validate all UI fielld when save and validate\n\t\t\tif ( !Global/* Global.isSet */.x.isSet( $this.current_edit_record[key] ) && !this.is_mass_editing ) {\n\t\t\t\t$this.current_edit_record[key] = false;\n\t\t\t}\n\t\t}\n\n\t\tif ( this.is_mass_editing ) {\n\t\t\tfor ( var key in this.edit_view_ui_dic ) {\n\t\t\t\tvar widget = this.edit_view_ui_dic[key];\n\t\t\t\tif ( Global/* Global.isSet */.x.isSet( widget.setMassEditMode ) ) {\n\t\t\t\t\twidget.setMassEditMode( true );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tTimeSheetViewController_$.each( this.unique_columns, function( index, value ) {\n\n\t\t\t\tif ( Global/* Global.isSet */.x.isSet( $this.edit_view_ui_dic[value] ) && Global/* Global.isSet */.x.isSet( $this.edit_view_ui_dic[value].setEnabled ) ) {\n\t\t\t\t\t$this.edit_view_ui_dic[value].setEnabled( false );\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t}\n\n\t\tthis.setNavigationArrowsEnabled();\n\n\t\t// Create this function alone because of the column value of view is different from each other, some columns need to be handle specially. and easily to rewrite this function in sub-class.\n\t\tthis.setCurrentEditRecordData();\n\n\t\t//Init *Please save this record before modifying any related data* box\n\t\tthis.edit_view.find( '.save-and-continue-div' ).SaveAndContinueBox( { related_view_controller: this } );\n\t\tthis.edit_view.find( '.save-and-continue-div' ).css( 'display', 'none' );\n\n\t\tthis.initTabData();\n\t\tthis.switchToProperTab();\n\t}\n\n\tsetCurrentEditRecordData() {\n\t\t//Set current edit record data to all widgets\n\t\tvar $this = this;\n\n\t\tvar tab_0_label = this.edit_view.find( 'a[ref=tab_punch]' );\n\t\tif ( tab_0_label ) {\n\t\t\tif ( this.absence_model ) {\n\t\t\t\ttab_0_label.text( TimeSheetViewController_$.i18n._( 'Absence' ) );\n\t\t\t} else {\n\t\t\t\ttab_0_label.text( TimeSheetViewController_$.i18n._( 'Punch' ) );\n\t\t\t}\n\t\t}\n\n\t\t//This needs to be done here or the user id gets stuck and subsequent punches for subordinates go to the admin's timesheet.\n\t\tthis.current_edit_record.user_id = this.getSelectEmployee();\n\n\t\tfor ( var key in this.current_edit_record ) {\n\n\t\t\tif ( !this.current_edit_record.hasOwnProperty( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvar widget = this.edit_view_ui_dic[key];\n\t\t\tvar args;\n\t\t\tif ( Global/* Global.isSet */.x.isSet( widget ) ) {\n\t\t\t\tswitch ( key ) {\n\t\t\t\t\tcase 'punch_dates':\n\t\t\t\t\t\tvar date_array;\n\t\t\t\t\t\tif ( !this.current_edit_record.punch_dates ) {\n\t\t\t\t\t\t\tdate_array = this.getSelectDateArray();\n\t\t\t\t\t\t\tthis.current_edit_record.punch_dates = date_array;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdate_array = this.current_edit_record.punch_dates;\n\t\t\t\t\t\t}\n\t\t\t\t\t\twidget.setValue( date_array );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'first_last_name':\n\t\t\t\t\t\tvar select_employee = this.getSelectEmployee( true ); //Get full item\n\t\t\t\t\t\t//Error: Uncaught TypeError: Cannot read property 'first_name' of null in interface/html5/#!m=TimeSheet&date=null&user_id=null&show_wage=0&a=new&t=punch&tab=Punch line 6810\n\t\t\t\t\t\tif ( select_employee ) {\n\t\t\t\t\t\t\twidget.setValue( select_employee['first_name'] + ' ' + select_employee['last_name'] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'total_time':\n\t\t\t\t\t\tif ( this.absence_model ) {\n\t\t\t\t\t\t\tvar result = Global/* Global.getTimeUnit */.x.getTimeUnit( this.current_edit_record[key] );\n\t\t\t\t\t\t\twidget.setValue( result );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'station_id':\n\t\t\t\t\t\tif ( this.current_edit_record[key] ) {\n\t\t\t\t\t\t\tthis.setStation();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\twidget.setValue( 'N/A' );\n\t\t\t\t\t\t\twidget.css( 'cursor', 'default' );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'punch_image':\n\t\t\t\t\t\tvar station_form_item = this.edit_view_form_item_dic['station_id'];\n\t\t\t\t\t\tif ( this.current_edit_record['has_image'] ) {\n\t\t\t\t\t\t\tthis.attachElement( 'punch_image' );\n\t\t\t\t\t\t\twidget.setValue( ServiceCaller.getURLByObjectType( 'file_download' ) + '&object_type=punch_image&parent_id=' + this.current_edit_record.user_id + '&object_id=' + this.current_edit_record.id );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.detachElement( 'punch_image' );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'job_id':\n\t\t\t\t\t\tif ( ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ) {\n\t\t\t\t\t\t\targs = {};\n\t\t\t\t\t\t\targs.filter_data = {\n\t\t\t\t\t\t\t\tstatus_id: 10,\n\t\t\t\t\t\t\t\tuser_id: this.current_edit_record.user_id,\n\t\t\t\t\t\t\t\tpunch_branch_id: this.current_edit_record.branch_id,\n\t\t\t\t\t\t\t\tpunch_department_id: this.current_edit_record.department_id\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\twidget.setDefaultArgs( args );\n\t\t\t\t\t\t\twidget.setValue( this.current_edit_record[key] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'job_item_id':\n\t\t\t\t\t\tif ( ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ) {\n\t\t\t\t\t\t\targs = {};\n\t\t\t\t\t\t\targs.filter_data = { status_id: 10, job_id: this.current_edit_record.job_id };\n\t\t\t\t\t\t\twidget.setDefaultArgs( args );\n\t\t\t\t\t\t\twidget.setValue( this.current_edit_record[key] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'punch_tag_id':\n\t\t\t\t\t\tif ( ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ) {\n\t\t\t\t\t\t\twidget.setValue( this.current_edit_record[key] );\n\t\t\t\t\t\t\tthis.previous_punch_tag_selection = this.current_edit_record[key];\n\n\t\t\t\t\t\t\tvar punch_tag_widget = widget;\n\t\t\t\t\t\t\tTTPromise.wait( null, null, function() {\n\t\t\t\t\t\t\t\t//Update default args for punch tags AComboBox last as they rely on data from job, job item and related fields.\n\t\t\t\t\t\t\t\tvar args = {};\n\t\t\t\t\t\t\t\targs.filter_data = $this.getPunchTagFilterData();\n\t\t\t\t\t\t\t\tpunch_tag_widget.setDefaultArgs( args );\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'branch_id':\n\t\t\t\t\t\tif ( ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ) {\n\t\t\t\t\t\t\tvar args = {};\n\t\t\t\t\t\t\targs.filter_data = { user_id: this.current_edit_record.user_id };\n\t\t\t\t\t\t\twidget.setDefaultArgs( args );\n\t\t\t\t\t\t}\n\t\t\t\t\t\twidget.setValue( this.current_edit_record[key] );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'department_id':\n\t\t\t\t\t\tif ( ( Global/* Global.getProductEdition */.x.getProductEdition() >= 20 ) ) {\n\t\t\t\t\t\t\tvar args = {};\n\t\t\t\t\t\t\targs.filter_data = { user_id: this.current_edit_record.user_id, branch_id: this.current_edit_record.branch_id };\n\t\t\t\t\t\t\twidget.setDefaultArgs( args );\n\t\t\t\t\t\t}\n\t\t\t\t\t\twidget.setValue( this.current_edit_record[key] );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'job_quick_search':\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'job_item_quick_search':\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'punch_tag_quick_search':\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'latitude':\n\t\t\t\t\tcase 'longitude':\n\t\t\t\t\tcase 'position_accuracy':\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\twidget.setValue( this.current_edit_record[key] );\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\n\t\tif ( this.absence_model ) {\n\n\t\t\tif ( this.current_edit_record.id ) {\n\t\t\t\tthis.pre_total_time = this.current_edit_record.total_time;\n\t\t\t} else {\n\t\t\t\tthis.pre_total_time = 0;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.pre_total_time = 0;\n\t\t}\n\n\t\tvar actual_time_value;\n\t\tif ( this.current_edit_record.id ) {\n\n\t\t\tif ( this.current_edit_record.actual_time_stamp ) {\n\t\t\t\tactual_time_value = TimeSheetViewController_$.i18n._( 'Actual Time' ) + ': ' + this.current_edit_record.actual_time_stamp;\n\t\t\t} else {\n\t\t\t\tactual_time_value = 'N/A';\n\t\t\t}\n\n\t\t}\n\n\t\tthis.setLocationValue( this.current_edit_record );\n\n\t\tthis.actual_time_label.text( actual_time_value );\n\n\t\tthis.onAvailableBalanceChange();\n\n\t\tthis.setEditMenu(); //To make sure save & continue icon disabled correct when multi dates\n\n\t\tthis.setEditViewDataDone();\n\t}\n\n\tsetEditViewDataDone() {\n\t\tsuper.setEditViewDataDone();\n\t\t//can't check is_edit here because in timesheet it can be both.\n\t\tif ( this.is_viewing == true && ( this.current_edit_record.latitude == 0 || this.current_edit_record.longitude == 0 ) ) {\n\t\t\tTimeSheetViewController_$( '.widget-h-box-mapLocationWrapper' ).parents( '.edit-view-form-item-div' ).hide();\n\t\t} else {\n\t\t\tif ( this.show_location_ui ) {\n\t\t\t\tTimeSheetViewController_$( '.widget-h-box-mapLocationWrapper' ).parents( '.edit-view-form-item-div' ).show();\n\t\t\t}\n\t\t}\n\t}\n\n\tsetLocationValue( location_data ) {\n\t\tif ( Global/* Global.getProductEdition */.x.getProductEdition() >= 15\n\t\t\t&& this.edit_view_ui_dic['latitude']\n\t\t\t&& this.edit_view_ui_dic['longitude']\n\t\t\t&& this.edit_view_ui_dic['position_accuracy']\n\t\t) {\n\t\t\tif ( location_data ) {\n\t\t\t\tthis.current_edit_record.latitude = location_data.latitude;\n\t\t\t\tthis.current_edit_record.longitude = location_data.longitude;\n\t\t\t\tthis.current_edit_record.position_accuracy = location_data.position_accuracy;\n\t\t\t}\n\t\t\tthis.edit_view_ui_dic['latitude'].setValue( this.current_edit_record.latitude );\n\t\t\tthis.edit_view_ui_dic['longitude'].setValue( this.current_edit_record.longitude );\n\t\t\tthis.edit_view_ui_dic['position_accuracy'].setValue( this.current_edit_record.position_accuracy ? this.current_edit_record.position_accuracy : 0 );\n\n\t\t\tif ( !this.current_edit_record.latitude && !this.is_mass_editing ) {\n\t\t\t\tthis.location_wrapper.hide();\n\t\t\t} else {\n\t\t\t\tif ( this.show_location_ui ) {\n\t\t\t\t\tthis.location_wrapper.show();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tonAvailableBalanceChange() {\n\t\tif ( this.current_edit_record.hasOwnProperty( 'src_object_id' ) &&\n\t\t\tthis.current_edit_record.src_object_id && !this.is_mass_editing ) {\n\t\t\tthis.getAvailableBalance( false );\n\t\t} else {\n\t\t\tthis.detachElement( 'available_balance' );\n\t\t}\n\t\tthis.editFieldResize();\n\t}\n\n\tgetAvailableBalance( release_balance ) {\n\n\t\tvar $this = this;\n\t\tvar result_data;\n\n\t\t//On first run, set previous_absence_policy_id.\n\t\tif ( this.previous_absence_policy_id == false ) {\n\t\t\tthis.previous_absence_policy_id = this.current_edit_record.src_object_id;\n\t\t}\n\n\t\tif ( this.absence_model ) {\n\n\t\t\tvar last_date_stamp = this.current_edit_record.date_stamp;\n\t\t\tvar total_time = this.current_edit_record.total_time;\n\n\t\t\tif ( this.is_mass_adding ) {\n\n\t\t\t\tlast_date_stamp = this.current_edit_record.punch_dates;\n\t\t\t\t//get dates from date ranger\n\t\t\t\tif ( last_date_stamp && last_date_stamp.indexOf( ' - ' ) > 0 ||\n\t\t\t\t\tTimeSheetViewController_$.type( last_date_stamp ) === 'array' ) {\n\n\t\t\t\t\tif ( last_date_stamp.indexOf( ' - ' ) > 0 ) {\n\t\t\t\t\t\tlast_date_stamp = this.parserDatesRange( last_date_stamp );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( last_date_stamp.length > 0 ) {\n\t\t\t\t\t\ttotal_time = total_time * last_date_stamp.length;\n\t\t\t\t\t\tlast_date_stamp = last_date_stamp[last_date_stamp.length - 1];\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.api_absence_policy.getProjectedAbsencePolicyBalance(\n\t\t\t\tthis.current_edit_record.src_object_id,\n\t\t\t\tthis.getSelectEmployee(),\n\t\t\t\tlast_date_stamp,\n\t\t\t\ttotal_time,\n\t\t\t\tthis.pre_total_time,\n\t\t\t\tthis.previous_absence_policy_id,\n\t\t\t\t{\n\t\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t\tif ( release_balance ) {\n\t\t\t\t\t\t\t$this.releaseBalance( result.getResult().available_balance );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$this.getBalanceHandler( result, last_date_stamp );\n\n\t\t\t\t\t\t\t// If the selected Absence Policy is not linked to any accrual.\n\t\t\t\t\t\t\t// The \"Remaining Balance\" button should not appear as there is no balance.\n\t\t\t\t\t\t\tif ( $this.is_viewing == true ) {\n\t\t\t\t\t\t\t\tTimeSheetViewController_$( '#release-balance-button' ).css( 'display', 'none' );\n\t\t\t\t\t\t\t} else if ( Global/* Global.isObject */.x.isObject( result ) ) {\n\t\t\t\t\t\t\t\tvar result_data = result.getResult();\n\t\t\t\t\t\t\t\tif ( !result_data ) {\n\t\t\t\t\t\t\t\t\tTimeSheetViewController_$( '#release-balance-button' ).css( 'display', 'none' );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tTimeSheetViewController_$( '#release-balance-button' ).css( 'display', '' );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tTimeSheetViewController_$( '#release-balance-button' ).css( 'display', 'none' );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\n\t\t}\n\t}\n\n\tsetStation() {\n\n\t\tvar $this = this;\n\t\tvar arg = { filter_data: { id: this.current_edit_record.station_id } };\n\n\t\tthis.api_station.getStation( arg, {\n\t\t\tonResult: function( result ) {\n\n\t\t\t\t$this.station = result.getResult()[0];\n\n\t\t\t\tvar widget = $this.edit_view_ui_dic['station_id'];\n\t\t\t\tif ( $this.station ) {\n\t\t\t\t\t//Error: Uncaught TypeError: Cannot read property 'setValue' of undefined in /interface/html5/#!m=TimeSheet&date=20140925 line 6017\n\t\t\t\t\tif ( widget ) {\n\t\t\t\t\t\twidget.setValue( $this.station.type + '-' + $this.station.description );\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( widget ) {\n\t\t\t\t\t\twidget.setValue( 'N/A' );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( PermissionManager.validate( 'station', 'view' ) ||\n\t\t\t\t\t( PermissionManager.validate( 'station', 'view_child' ) && $this.station.is_child ) ||\n\t\t\t\t\t( PermissionManager.validate( 'station', 'view_own' ) && $this.station.is_owner ) ) {\n\t\t\t\t\t$this.show_station_ui = true;\n\t\t\t\t} else {\n\t\t\t\t\t$this.show_station_ui = false;\n\t\t\t\t}\n\n\t\t\t\t// Error: TypeError: form_item_input is undefined in interface/html5/framework/jquery.min.js?v=9.0.1-20151022-091549 line 2 > eval line 7119\n\t\t\t\tif ( $this.show_station_ui && widget ) {\n\t\t\t\t\twidget.css( 'cursor', 'pointer' );\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tgetSelectedItems() {\n\t\tvar selected_item = null;\n\t\tif ( this.edit_view ) {\n\t\t\treturn [this.current_edit_record];\n\t\t} else {\n\n\t\t\tif ( this.select_punches_array.length > 0 ) {\n\t\t\t\treturn this.select_punches_array;\n\t\t\t}\n\t\t}\n\n\t\treturn [];\n\t}\n\n\tgetSelectedItem() {\n\n\t\tvar selected_item = null;\n\t\tif ( this.edit_view ) {\n\t\t\tselected_item = this.current_edit_record;\n\t\t} else {\n\n\t\t\tif ( this.select_punches_array.length > 0 ) {\n\t\t\t\tselected_item = this.select_punches_array[0];\n\t\t\t} else {\n\t\t\t\tselected_item = null;\n\t\t\t}\n\t\t}\n\n\t\treturn Global/* Global.clone */.x.clone( selected_item );\n\t}\n\n\taddPermissionValidate( p_id ) {\n\t\tif ( !Global/* Global.isSet */.x.isSet( p_id ) ) {\n\t\t\tp_id = this.permission_id;\n\t\t}\n\n\t\tif ( p_id === 'report' ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( PermissionManager.validate( p_id, 'add' ) && this.editPermissionValidate( p_id ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tsetDefaultMenu( doNotSetFocus ) {\n\t\t//TimeSheet uses a different grid than other views and needs \"select_punches_array\" instead of \"this.getGridSelectIdArray()\" for grid_selected_length\n\t\tsuper.setDefaultMenu( doNotSetFocus, this.select_punches_array.length );\n\t\t//Set move or drop mode after rest of menu.\n\t\tthis.setMoveOrDropMode( this.select_drag_menu_id ? this.select_drag_menu_id : 'move' ); // Ensure Move/Copy selections are set when closing pop-up windows from Jump-To menu, like Add Request.\n\t}\n\n\tsetCustomDefaultMenuIcon( id, context_btn, grid_selected_length ) {\n\t\tswitch ( id ) {\n\t\t\tcase 'add_punch':\n\t\t\t\tthis.setDefaultMenuAddPunchIcon( context_btn, grid_selected_length );\n\t\t\t\tif ( this.getPunchPermissionType() === 'punch' ) {\n\t\t\t\t\tContextMenuManager.activateSplitButtonItem( this.determineContextMenuMountAttributes().id, context_btn.id );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'add_absence':\n\t\t\t\tthis.setDefaultMenuAddAbsenceIcon( context_btn, grid_selected_length );\n\t\t\t\tif ( this.getPunchPermissionType() === 'absence' ) {\n\t\t\t\t\tContextMenuManager.activateSplitButtonItem( this.determineContextMenuMountAttributes().id, context_btn.id );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'in_out':\n\t\t\t\tthis.setDefaultMenuInOutIcon( context_btn, grid_selected_length );\n\t\t\t\tbreak;\n\t\t\tcase 'move':\n\t\t\t\tif ( !this.movePermissionValidate( this.getPunchPermissionType() ) ) {\n\t\t\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t\t\t}\n\t\t\t\tif ( this.getPunchMode() == 'manual' ) {\n\t\t\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\t\t} else {\n\t\t\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'edit_pay_period':\n\t\t\t\tthis.setDefaultMenuEditPayPeriodIcon( context_btn, grid_selected_length );\n\t\t\t\tbreak;\n\t\t\tcase 'print':\n\t\t\t\tthis.setDefaultMenuPrintIcon( context_btn, grid_selected_length );\n\t\t\t\tbreak;\n\t\t\tcase 'edit_employee':\n\t\t\t\tthis.setDefaultMenuEditEmployeeIcon( context_btn, grid_selected_length );\n\t\t\t\tbreak;\n\t\t\tcase 'pay_stub':\n\t\t\t\tthis.setDefaultMenuPayStubIcon( context_btn, grid_selected_length );\n\t\t\t\tbreak;\n\t\t\tcase 're_calculate_timesheet':\n\t\t\t\tthis.setDefaultMenuReCalculateTimesheet( context_btn, grid_selected_length );\n\t\t\t\tbreak;\n\t\t\tcase 'generate_pay_stub':\n\t\t\t\tthis.setDefaultMenuGeneratePayStubIcon( context_btn, grid_selected_length );\n\t\t\t\tbreak;\n\t\t\tcase 'schedule':\n\t\t\t\tthis.setDefaultMenuScheduleIcon( context_btn, grid_selected_length );\n\t\t\t\tbreak;\n\t\t\tcase 'accumulated_time':\n\t\t\t\tthis.setDefaultMenuAccumulatedTimeIcon( context_btn );\n\t\t\t\tbreak;\n\t\t\tcase 'AddRequest':\n\t\t\t\tthis.setAddRequestIcon( context_btn );\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tsetEditMenuDragCopyIcon( context_btn, grid_selected_length ) {\n\t\tif ( !this.copyPermissionValidate( this.getPunchPermissionType() ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( this.getPunchMode() == 'manual' ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t}\n\t}\n\n\tsetDefaultMenuDragCopyIcon( context_btn, grid_selected_length ) {\n\t\tif ( !this.copyPermissionValidate( this.getPunchPermissionType() ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( this.getPunchMode() == 'manual' ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t}\n\t}\n\n\tsetDefaultMenuScheduleIcon( context_btn, grid_selected_length ) {\n\t\tif ( !PermissionManager.checkTopLevelPermission( 'Schedule' ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\t}\n\n\treCalculateEditPermissionValidate() {\n\n\t\tvar p_id = this.permission_id;\n\n\t\tif ( PermissionManager.validate( p_id, 'edit' ) || this.ownerOrChildPermissionValidate( p_id, 'edit_child' ) ) {\n\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tsetDefaultMenuReCalculateTimesheet( context_btn, grid_selected_length ) {\n\n\t\tif ( !this.reCalculateEditPermissionValidate() ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\t}\n\n\tsetDefaultMenuGeneratePayStubIcon( context_btn, grid_selected_length ) {\n\n\t\tif ( !PermissionManager.checkTopLevelPermission( 'GeneratePayStubs' ) ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\t}\n\n\tsetDefaultMenuPayStubIcon( context_btn, grid_selected_length ) {\n\n\t\tif ( !PermissionManager.checkTopLevelPermission( 'PayStub' ) ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\t}\n\n\tsetDefaultMenuEditPayPeriodIcon( context_btn, grid_selected_length ) {\n\n\t\tif ( !this.editPermissionValidate( 'pay_period_schedule' ) ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tvar $this = this;\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\tif ( $this.getPayPeriod() ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t}\n\t}\n\n\tsetDefaultMenuAccumulatedTimeIcon( context_btn ) {\n\n\t\tif ( !PermissionManager.checkTopLevelPermission( 'AccumulatedTime' ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\t}\n\n\tsetDefaultMenuEditEmployeeIcon( context_btn, grid_selected_length ) {\n\n\t\tif ( !this.editChildPermissionValidate( 'user' ) ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\t}\n\n\tsetDefaultMenuInOutIcon( context_btn ) {\n\t\tif ( this.addPermissionValidate( 'punch' ) ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t} else {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n ContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t}\n\t}\n\n\tsetEditMenuInOutIcon( context_btn ) {\n\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\teditOwnerOrChildPermissionValidate( p_id, selected_item ) {\n\n\t\tif ( !p_id ) {\n\t\t\tp_id = this.permission_id;\n\t\t}\n\n\t\tif ( !selected_item ) {\n\t\t\tselected_item = this.getSelectEmployee( true );\n\t\t}\n\n\t\tif ( p_id === 'report' ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (\n\t\t\tPermissionManager.validate( p_id, 'edit' ) ||\n\t\t\t( selected_item && selected_item.is_owner && PermissionManager.validate( p_id, 'edit_own' ) ) ||\n\t\t\t( selected_item && selected_item.is_child && PermissionManager.validate( p_id, 'edit_child' ) ) ) {\n\n\t\t\treturn true;\n\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tviewOwnerOrChildPermissionValidate( p_id, selected_item ) {\n\n\t\tif ( !p_id ) {\n\t\t\tp_id = this.permission_id;\n\t\t}\n\n\t\tif ( p_id === 'report' ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( !selected_item ) {\n\t\t\tselected_item = this.getSelectEmployee( true );\n\t\t}\n\n\t\tif (\n\t\t\tPermissionManager.validate( p_id, 'view' ) ||\n\t\t\t( selected_item && selected_item.is_owner && PermissionManager.validate( p_id, 'view_own' ) ) ||\n\t\t\t( selected_item && selected_item.is_child && PermissionManager.validate( p_id, 'view_child' ) ) ) {\n\n\t\t\treturn true;\n\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tdeleteOwnerOrChildPermissionValidate( p_id, selected_item ) {\n\n\t\tif ( !p_id ) {\n\t\t\tp_id = this.permission_id;\n\t\t}\n\n\t\tif ( !selected_item ) {\n\t\t\tselected_item = this.getSelectEmployee( true );\n\t\t}\n\n\t\tif ( p_id === 'report' ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (\n\t\t\tPermissionManager.validate( p_id, 'delete' ) ||\n\t\t\t( selected_item && selected_item.is_owner && PermissionManager.validate( p_id, 'delete_own' ) ) ||\n\t\t\t( selected_item && selected_item.is_child && PermissionManager.validate( p_id, 'delete_child' ) ) ) {\n\n\t\t\treturn true;\n\n\t\t}\n\n\t\treturn false;\n\t}\n\n\teditChildPermissionValidate( p_id, selected_item ) {\n\t\tif ( !Global/* Global.isSet */.x.isSet( p_id ) ) {\n\t\t\tp_id = this.permission_id;\n\t\t}\n\n\t\tif ( !Global/* Global.isSet */.x.isSet( selected_item ) ) {\n\t\t\tselected_item = this.getSelectEmployee( true );\n\t\t}\n\n\t\tif ( p_id === 'report' ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( !PermissionManager.validate( p_id, 'enabled' ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( PermissionManager.validate( p_id, 'edit' ) ||\n\t\t\tthis.ownerOrChildPermissionValidate( p_id, 'edit_child', selected_item ) ) {\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tonReportMenuClick( id ) {\n\t\tthis.onNavigationClick( id );\n\t}\n\n\tsetDefaultMenuPrintIcon( context_btn, grid_selected_length ) {\n\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t}\n\n\tsetEditMenuMapIcon( context_btn ) {\n\t\tsuper.setDefaultMenuMapIcon( context_btn );\n\n\t\tif ( context_btn.disabled == true ) {\n\t\t\tif ( this.absence_model || this.getPunchMode() == 'manual' ) {\n\t\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\t}\n\t\t}\n\t}\n\n\tsetEditMenuSaveAndAddIcon( context_btn ) {\n\t\tthis.saveAndNewValidate( context_btn, this.getPunchPermissionType() );\n\n\t\tif ( this.is_viewing || this.is_mass_editing ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuMapIcon( context_btn, grid_selected_length ) {\n\t\tsuper.setDefaultMenuMapIcon( context_btn );\n\n\t\tif ( context_btn.disabled == true ) {\n\t\t\tif ( this.absence_model || this.getPunchMode() == 'manual' ) {\n\t\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\t}\n\t\t}\n\t}\n\n\tsetEditMenuSaveAndNextIcon( context_btn ) {\n\t\tif ( !this.editPermissionValidate( this.getPunchPermissionType() ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( ( !this.current_edit_record || !this.current_edit_record.id ) || this.is_viewing || this.is_mass_adding ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuSaveAndCopyIcon( context_btn ) {\n\t\tthis.saveAndNewValidate( context_btn, this.getPunchPermissionType() );\n\n\t\tif ( this.is_viewing || this.is_mass_editing ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuCopyAndAddIcon( context_btn ) {\n\t\tif ( !this.addPermissionValidate( this.getPunchPermissionType() ) ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( ( !this.current_edit_record || !this.current_edit_record.id ) || this.is_viewing || this.is_mass_adding ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\n\tsetCustomEditMenuIcon( id, context_btn ) {\n\t\tswitch ( id ) {\n\t\t\tcase 'add':\n\t\t\tcase 'add_punch':\n\t\t\t\tthis.setEditMenuAddIcon( context_btn );\n\t\t\t\tif ( this.getPunchPermissionType() === 'punch' ) {\n\t\t\t\t\tContextMenuManager.activateSplitButtonItem( this.determineContextMenuMountAttributes().id, context_btn.id );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'add_absence':\n\t\t\t\tthis.setEditMenuAddIcon( context_btn );\n\t\t\t\tif ( this.getPunchPermissionType() === 'absence' ) {\n\t\t\t\t\tContextMenuManager.activateSplitButtonItem( this.determineContextMenuMountAttributes().id, context_btn.id );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'view':\n\t\t\t\tthis.setEditMenuViewIcon( context_btn );\n\t\t\t\tbreak;\n\t\t\tcase 'in_out':\n\t\t\t\tthis.setEditMenuInOutIcon( context_btn );\n\t\t\t\tbreak;\n\t\t\tcase 'drag_copy':\n\t\t\t\tthis.setEditMenuDragCopyIcon( context_btn );\n\t\t\t\tbreak;\n\t\t\tcase 'move':\n\t\t\t\tif ( !this.movePermissionValidate( this.getPunchPermissionType() ) ) {\n\t\t\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'accumulated_time':\n\t\t\t\tthis.setDefaultMenuAccumulatedTimeIcon( context_btn );\n\t\t\t\tbreak;\n\t\t\tcase 'export_excel':\n\t\t\t\tthis.setDefaultMenuExportIcon( context_btn );\n\t\t\t\tbreak;\n\t\t\tcase 'edit_employee':\n\t\t\t\tthis.setDefaultMenuEditEmployeeIcon( context_btn );\n\t\t\t\tbreak;\n\t\t\tcase 'edit_pay_period':\n\t\t\t\tthis.setDefaultMenuEditPayPeriodIcon( context_btn );\n\t\t\t\tbreak;\n\t\t\tcase 're_calculate_timesheet':\n\t\t\t\tthis.setDefaultMenuReCalculateTimesheet( context_btn );\n\t\t\t\tbreak;\n\t\t\tcase 'generate_pay_stub':\n\t\t\t\tthis.setDefaultMenuGeneratePayStubIcon( context_btn );\n\t\t\t\tbreak;\n\t\t\tcase 'AddRequest':\n\t\t\t\tthis.setAddRequestIcon( context_btn );\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tenableAddRequestButton() {\n\t\tvar grid_selected_id_array = this.select_cells_Array;\n\t\tvar grid_selected_length = grid_selected_id_array.length;\n\n\t\tif ( grid_selected_length == 1 ) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tcleanWhenUnloadView( callBack ) {\n\t\tTTVueUtils/* default.unmountComponent */.Z.unmountComponent( this.vue_control_bar_id );\n\t\tTimeSheetViewController_$( '#timesheet_view_container' ).remove();\n\t\tsuper.cleanWhenUnloadView( callBack );\n\t}\n\n\tsetAddRequestIcon( context_btn, grid_selected_length ) {\n\t\tif ( Global/* Global.getProductEdition */.x.getProductEdition() <= 10 || !this.addPermissionValidate( 'request' ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( this.enableAddRequestButton() === true ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tuserValueSet( val ) {\n\t\t//If the value here is null, the timesheet data will be missing therefore we want to force the value to the currently logged in user.\n\t\t//Mostly caused when developers switch instances or databases during testing.\n\t\tif ( typeof val == 'undefined' ) {\n\t\t\tthis.employee_nav.setValue( LocalCacheData.getLoginUser() );\n\t\t\tDebug.Text( 'ERROR: Invalid User ID in URL. Switching to current User ID.', 'TimesheetViewConroller.js', 'TimesheetViewConroller', 'userValueSet', 10 );\n\t\t}\n\t}\n\n\t// Get available accrual balance for currently selected absence policy type and insert into the time field.\n\treleaseBalance( balance ) {\n\n\t\t//Balance could be positive or negative.\n\t\t//If the balance can be fully displayed in the preferred time unit, is that format.\n\t\t//Otherwise we need to release fractions of a minute, so force through \"HH:MM:SS\" and wrap it in quotes so it doesn't get rounded.\n\t\tif ( Global/* Global.parseTimeUnit */.x.parseTimeUnit( Global/* Global.getTimeUnit */.x.getTimeUnit( balance ) ) == balance ) {\n\t\t\tthis.edit_view_ui_dic['total_time'].setValue( Global/* Global.getTimeUnit */.x.getTimeUnit( balance ) );\n\t\t} else {\n\t\t\tthis.edit_view_ui_dic['total_time'].setValue( '\"' + Global/* Global.getTimeUnit */.x.getTimeUnit( balance, 12 ) + '\"' ); //12=\"HH:MM:SS\"\n\t\t}\n\n\t\t// Trigger field onFormChange to update available balance field and other data.\n\t\tthis.edit_view_ui_dic['total_time'].trigger( 'change' );\n\t}\n\n\tmergeJobQueueIntoTimeSheetData( timesheet_data ) {\n\t\t//Check locally if there is a queued job queue punch within the last 15 minutes (900 seconds).\n\t\tif ( LocalCacheData.getJobQueuePunchData() && LocalCacheData.getJobQueuePunchData().user_id === this.getSelectEmployee() && ( ( new Date().getTime() / 1000 ) - LocalCacheData.getJobQueuePunchData().epoch ) < ( 60 * 15 ) ) {\n\t\t\t//Check if punch is duplicate and alreaxy exists.\n\t\t\tlet is_punch_exist = false;\n\t\t\tfor( let i = 0; i < timesheet_data.punch_data.length; i++ ) {\n\t\t\t\tif( timesheet_data.punch_data[i].actual_time_stamp == LocalCacheData.getJobQueuePunchData().actual_time_stamp\n\t\t\t\t\t&& timesheet_data.punch_data[i].status_id == LocalCacheData.getJobQueuePunchData().status_id\n\t\t\t\t\t&& timesheet_data.punch_data[i].type_id == LocalCacheData.getJobQueuePunchData().type_id\n\t\t\t\t) {\n\t\t\t\t\tis_punch_exist = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( is_punch_exist === true ) {\n\t\t\t\t//Punch already exists, remove duplicate.\n\t\t\t\tLocalCacheData.setJobQueuePunchData( null );\n\t\t\t} else {\n\t\t\t\ttimesheet_data.punch_data.push( LocalCacheData.getJobQueuePunchData() );\n\t\t\t}\n\t\t}\n\n\t\treturn timesheet_data;\n\t}\n\n\tgetTimeSheetWidth() {\n\t\tlet scroll_adjustment = Global/* Global.isVerticalScrollBarRequired */.x.isVerticalScrollBarRequired( TimeSheetViewController_$('.timesheet-grid-div')[0] ) ? Global/* Global.getScrollbarWidth */.x.getScrollbarWidth() : 0;\n\t\treturn ( TimeSheetViewController_$( '.context-border' ).width() - scroll_adjustment );\n\t}\n}\n\nTimeSheetViewController.PUNCH_ROW = 1;\nTimeSheetViewController.EXCEPTION_ROW = 2;\nTimeSheetViewController.REQUEST_ROW = 3;\nTimeSheetViewController.TOTAL_ROW = 4;\nTimeSheetViewController.REGULAR_ROW = 5;\nTimeSheetViewController.ABSENCE_ROW = 6;\nTimeSheetViewController.ACCUMULATED_TIME_ROW = 7;\nTimeSheetViewController.PREMIUM_ROW = 8;\n\nTimeSheetViewController.html_template = `\n\t<div class=\"view time-sheet-view\" id=\"timesheet_view_container\">\n\t\t<div class=\"clear-both-div\"></div>\n\t\t<div class=\"control-bar\">\n\t\t\t<div id=\"vue-timesheet-control-bar\"></div>\n\t\t</div>\n\t\t<div class=\"clear-both-div\"></div>\n\t\t<div class=\"grid-top-border\"></div>\n\t\t<div class=\"timesheet-grid-div\">\n\t\t\t<div class=\"timesheet-punch-grid-wrapper\">\n\t\t\t\t<table id=\"grid\" class=\"timesheet-grid\"></table>\n\t\t\t</div>\n\t\t\t<div class=\"inside-editor-div manual-timesheet-inside-editor-div\"></div>\n\t\t\t<table class=\"accumulated-time-grid sub-grid\" id=\"accumulated_time_grid\"></table>\n\t\t\t<table class=\" sub-grid\" id=\"branch_grid\"></table>\n\t\t\t<table class=\" sub-grid\" id=\"department_grid\"></table>\n\t\t\t<table class=\" sub-grid\" id=\"job_grid\"></table>\n\t\t\t<table class=\" sub-grid\" id=\"job_item_grid\"></table>\n\t\t\t<table class=\" sub-grid\" id=\"premium_grid\"></table>\n\t\t\t<table class=\" sub-grid\" id=\"absence_grid\"></table>\n\t\t\t<table class=\"total_grids_div\" id=\"total_grids_table\">\n\t\t\t\t<tr style=\"vertical-align:top;\">\n\t\t\t\t\t<td>\n\t\t\t\t\t\t<div class=\"accumulated-total-grid-title\" style=\"display: none\"><%=accumulated_time%></div>\n\t\t\t\t\t\t<table id=\"accumulated_total_grid\"></table>\n\t\t\t\t\t</td>\n\t\t\t\t\t<td class=\"notes_grid_td_container\">\n\t\t\t\t\t\t<table id=\"punch_note_grid\" class=\"float-right\"></table>\n\t\t\t\t\t</td>\n\t\t\t\t\t<td>\n\t\t\t\t\t\t<div class=\"verification-grid-div\">\n\t\t\t\t\t\t\t<div class=\"verification-grid-title\" style=\"display: none\"><%=timesheet_verification%></div>\n\t\t\t\t\t\t\t<table id=\"verification_grid\" class=\"float-right\"></table>\n\t\t\t\t\t\t\t<div class=\"verification-action-bar\">\n\t\t\t\t\t\t\t\t<span class=\"verify-description\"></span>\n\t\t\t\t\t\t\t\t<button class=\"verify-button t-button\" style=\"display: none\"><%=verify%></button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t</table>\n\t\t</div>\n\t\t<div class=\"bottom-div\">\n\t\t\t<div class=\"grid-bottom-border\"></div>\n\t\t</div>\n\t</div>\n`;//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMjY5My5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7cUJBQ1MsS0FBSyxFQUFDLHVCQUF1Qjs7cUJBV3pCLEtBQUssRUFBQyxrQkFBa0I7cUJBQ3BCLEtBQUssRUFBQyx5QkFBeUI7cUJBRy9CLEtBQUssRUFBQyxzQkFBc0I7Ozs7OzttREFmekMsK0NBbUJNLE9BbkJOLFVBbUJNO0lBbEJGLFVBQW1DO0lBVW5DLDhDQU9NLE9BUE4sVUFPTTtNQU5GLDhDQUVNLE9BRk4sVUFFTTtRQURGLHdDQUErSTtzQkFBeEgseUJBQW1CO3VFQUFuQix5QkFBbUI7VUFBRyxPQUFPLEVBQUUsaUJBQVc7VUFBRSxXQUFXLEVBQUMsT0FBTztVQUFDLFdBQVcsRUFBQyxPQUFPO1VBQUUsT0FBSyw0Q0FBTyxpQkFBaUI7OztNQUU3SSw4Q0FFTSxPQUZOLFVBRU07UUFERix3Q0FBNEU7VUFBMUQsS0FBSyw2Q0FBRSxXQUFXO1VBQUcsS0FBSyxFQUFFLGdDQUEwQjs7Ozs7Ozs7Ozs7Ozs7O0FBT3ZDO0FBQ3VCOztBQUV4RSxpRkFBZTtJQUNYLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtRQUNILENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNuRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDWixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDaEIsQ0FBQztRQUNELENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDeEUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNkLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNoQixDQUFDO1FBQ0QsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3RFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDZCxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDaEIsQ0FBQztRQUNELENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN0RSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2QsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ2hCO0lBQ0osQ0FBQztJQUNELENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO1FBQ0gsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7WUFDSCxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM1QixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtnQkFDVCxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDOUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3BELENBQUM7WUFDRCxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtnQkFDeEI7b0JBQ0ksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7b0JBQy9CLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUNoQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUNwQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUM3QyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDbEMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO29CQUNyQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztvQkFDNUQsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUU7d0JBQ1gsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFOzRCQUNyRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQzt3QkFDckU7b0JBQ0o7Z0JBQ0osQ0FBQztnQkFDRDtvQkFDSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO29CQUMxQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7b0JBQzNCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7b0JBQ3BCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7b0JBQzdDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUNsQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7b0JBQ3JCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDO29CQUNqSCxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRTt3QkFDWCxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7NEJBQ3JFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO3dCQUNyRTtvQkFDSjtnQkFDSixDQUFDO1lBQ0w7UUFDSjtJQUNKLENBQUM7SUFDRCxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7SUFDVixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUU7SUFDN0MsQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO0lBQ3hGLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNuRCxDQUFDLFVBQVU7SUFDWCxDQUFDLE1BQU0sQ0FBQztJQUNSLENBQUMsRUFBRSxDQUFDO0lBQ0osQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7UUFDTixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDaEUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkM7SUFDSixDQUFDO0lBQ0QsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO1FBQ0wsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO1lBQ3RCLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDOUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDcEMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNmLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRTtnQkFDSCxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQztnQkFDN0gsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2hCO1FBQ0osQ0FBQztRQUNELENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7WUFDakMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDcEYsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO2dCQUNQLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN0QixFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUU7Z0JBQ0gsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUM7Z0JBQ3JKLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3BCO1FBQ0osQ0FBQztRQUNELENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7WUFDeEMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDcEYsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO2dCQUNQLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN2QixFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUU7Z0JBQ0gsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDeko7UUFDSjtJQUNKLENBQUM7SUFDRCxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7UUFDUixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLCtCQUFZO1FBQzFCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsOEJBQWU7SUFDcEM7QUFDSixDQUFDLEVBQUM7OztBRWxJMEosQzs7OztBQ0FoRTtBQUN0QjtBQUNMOztBQUVqRSxDQUEwRjs7QUFFVztBQUNyRyxpQ0FBaUMsK0JBQWUsQ0FBQywwQ0FBTSxhQUFhLE1BQU07O0FBRTFFLDBEQUFlOzs7Ozs7OztBQ1Q4QjtBQUNFO0FBQzhCO0FBQ3BDO0FBQ0E7O0FBRWxDO0FBQ1AsMkJBQTJCO0FBQzNCLEVBQUUsQ0FBQztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5Q0FBeUM7QUFDekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQjtBQUMzQixtQ0FBbUM7QUFDbkM7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLHlCQUFDO0FBQzVCLDBCQUEwQix5QkFBQztBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTLHdEQUF3QjtBQUNqQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUNBQXVDLHNCQUFzQixHQUFHOztBQUVoRTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsTUFBTSx3REFBd0I7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsTUFBTSx3REFBd0I7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBLE1BQU0sd0RBQXdCO0FBQzlCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNB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QUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUEsU0FBUyxnQ0FBWTtBQUNyQjs7QUFFQTtBQUNBLFFBQVEsZ0NBQVk7QUFDcEI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwRkFBMEY7QUFDMUY7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxRQUFRLGdDQUFZO0FBQ3BCO0FBQ0E7O0FBRUEsUUFBUSxnQ0FBWTtBQUNwQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUUsMkRBQTJCO0FBQzdCLEVBQUUseUJBQUM7QUFDSDtBQUNBOztBQUVBO0FBQ0EsT0FBTyx3REFBd0I7QUFDL0I7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTyxnREFBb0IsRUFBRSw0Q0FBa0I7QUFDL0MsaURBQWlELDRDQUFrQjtBQUNuRSxJQUFJO0FBQ0osdURBQXVELDRDQUFrQix5QkFBeUI7QUFDbEc7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIsc0NBQXNDO0FBQ3pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLDBCQUEwQiw0RUFBa0MsRUFBRSx5QkFBQywrQkFBK0Isd0RBQXdCO0FBQ3RILFdBQVcseUJBQUM7QUFDWjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0NBQWtDO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vaW50ZXJmYWNlL2h0bWw1L2NvbXBvbmVudHMvdGltZXNoZWV0L1RpbWVTaGVldENvbnRyb2xCYXIudnVlP2IwMGQiLCJ3ZWJwYWNrOi8vLy4vaW50ZXJmYWNlL2h0bWw1L2NvbXBvbmVudHMvdGltZXNoZWV0L1RpbWVTaGVldENvbnRyb2xCYXIudnVlPzAwZWEiLCJ3ZWJwYWNrOi8vLy4vaW50ZXJmYWNlL2h0bWw1L2NvbXBvbmVudHMvdGltZXNoZWV0L1RpbWVTaGVldENvbnRyb2xCYXIudnVlP2E3NzAiLCJ3ZWJwYWNrOi8vLy4vaW50ZXJmYWNlL2h0bWw1L2NvbXBvbmVudHMvdGltZXNoZWV0L1RpbWVTaGVldENvbnRyb2xCYXIudnVlPzNkMjMiLCJ3ZWJwYWNrOi8vLy4vaW50ZXJmYWNlL2h0bWw1L3ZpZXdzL2F0dGVuZGFuY2UvdGltZXNoZWV0L1RpbWVTaGVldFZpZXdDb250cm9sbGVyLmpzPzZjMDgiXSwic291cmNlc0NvbnRlbnQiOlsiPHRlbXBsYXRlPlxuICAgIDxkaXYgY2xhc3M9XCJ0dC1ob3Jpem9udGFsLXZ1ZS1iYXJcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImJhci1jb2x1bW4gbGVmdFwiPjwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiYmFyLWNvbHVtbiBjZW50ZXJcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJiYXItY29sdW1uIGRhdGUtY2hvb3Nlci1kaXZcIj48L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJiYXItY29sdW1uIGVtcGxveWVlLW5hdi1kaXZcIj5cbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm5hdmlnYXRpb24tbGFiZWxcIj48L3NwYW4+XG4gICAgICAgICAgICAgICAgPGltZyBjbGFzcz1cImxlZnQtY2xpY2tcIi8+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm5hdmlnYXRpb24td2lkZ2V0LWRpdlwiPjwvZGl2PlxuICAgICAgICAgICAgICAgIDxpbWcgY2xhc3M9XCJyaWdodC1jbGlja1wiLz5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImJhci1jb2x1bW4gcmlnaHRcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJiYXItY29sdW1uIHB1bmNoLW1hbnVhbFwiPlxuICAgICAgICAgICAgICAgIDxTZWxlY3RCdXR0b24gdi1tb2RlbD1cInB1bmNoX21vZGVfc2VsZWN0ZWRcIiA6b3B0aW9ucz1cInB1bmNoX21vZGVzXCIgb3B0aW9uTGFiZWw9XCJsYWJlbFwiIG9wdGlvblZhbHVlPVwidmFsdWVcIiBAY2xpY2s9XCJ0aGlzLm9uUHVuY2hNb2RlQ2hhbmdlKCk7XCIvPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYmFyLWNvbHVtbiBtZW51LWl0ZW1cIj5cbiAgICAgICAgICAgICAgICA8VFRDb250ZXh0QnV0dG9uIDpjbGFzcz1cIlsnbm8td3JhcCddXCIgOml0ZW1zPVwidGltZXNoZWV0X3NldHRpbmdzX29wdGlvbnNcIiAvPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuPC90ZW1wbGF0ZT5cblxuPHNjcmlwdD5cbmltcG9ydCBTZWxlY3RCdXR0b24gZnJvbSAncHJpbWV2dWUvc2VsZWN0YnV0dG9uJztcbmltcG9ydCBUVENvbnRleHRCdXR0b24gZnJvbSAnQC9jb21wb25lbnRzL2NvbnRleHRfbWVudS9UVENvbnRleHRCdXR0b24nO1xuXG5leHBvcnQgZGVmYXVsdCB7XG4gICAgbmFtZTogXCJUaW1lU2hlZXRDb250cm9sQmFyXCIsXG4gICAgcHJvcHM6IHtcbiAgICAgICAgY29tcG9uZW50X2lkOiB7IC8vIHBhc3NlZCBpbiB2aWEgcm9vdCBwcm9wcyBmcm9tIFRpbWVTaGVldFZpZXdDb250cm9sbGVyXG4gICAgICAgICAgICB0eXBlOiBTdHJpbmcsXG4gICAgICAgICAgICBkZWZhdWx0OiBudWxsXG4gICAgICAgIH0sXG4gICAgICAgIG9uUHVuY2hNb2RlQ2hhbmdlOiB7IC8vIHBhc3NlZCBpbiB2aWEgcm9vdCBwcm9wcyBmcm9tIFRpbWVTaGVldFZpZXdDb250cm9sbGVyXG4gICAgICAgICAgICB0eXBlOiBGdW5jdGlvbixcbiAgICAgICAgICAgIGRlZmF1bHQ6IG51bGxcbiAgICAgICAgfSxcbiAgICAgICAgb25TaG93V2FnZUNsaWNrOiB7IC8vIHBhc3NlZCBpbiB2aWEgcm9vdCBwcm9wcyBmcm9tIFRpbWVTaGVldFZpZXdDb250cm9sbGVyXG4gICAgICAgICAgICB0eXBlOiBGdW5jdGlvbixcbiAgICAgICAgICAgIGRlZmF1bHQ6IG51bGxcbiAgICAgICAgfSxcbiAgICAgICAgb25UaW1lem9uZUNsaWNrOiB7IC8vIHBhc3NlZCBpbiB2aWEgcm9vdCBwcm9wcyBmcm9tIFRpbWVTaGVldFZpZXdDb250cm9sbGVyXG4gICAgICAgICAgICB0eXBlOiBGdW5jdGlvbixcbiAgICAgICAgICAgIGRlZmF1bHQ6IG51bGxcbiAgICAgICAgfVxuICAgIH0sXG4gICAgZGF0YSgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHB1bmNoX21vZGVfc2VsZWN0ZWQ6ICdwdW5jaCcsXG4gICAgICAgICAgICBwdW5jaF9tb2RlczogW1xuICAgICAgICAgICAgICAgIHsgbGFiZWw6ICQuaTE4bi5fKCAnUHVuY2gnICksIHZhbHVlOiAncHVuY2gnIH0sXG4gICAgICAgICAgICAgICAgeyBsYWJlbDogJC5pMThuLl8oICdNYW51YWwnICksIHZhbHVlOiAnbWFudWFsJyB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIHRpbWVzaGVldF9zZXR0aW5nc19vcHRpb25zOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBsYWJlbDogJC5pMThuLl8oICdTaG93IFdhZ2VzJyApLFxuICAgICAgICAgICAgICAgICAgICBpZDogJ3Nob3dfd2FnZXMnLFxuICAgICAgICAgICAgICAgICAgICBub19ncm91cF9sYWJlbDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgdnVlX2ljb246ICd0dGljb24gdHRpY29uLXNldHRpbmdzX2JsYWNrXzI0ZHAnLFxuICAgICAgICAgICAgICAgICAgICBhY3Rpb25fZ3JvdXA6ICd0aW1lc2hlZXRfc2V0dGluZ3MnLFxuICAgICAgICAgICAgICAgICAgICBtdWx0aV9zZWxlY3RfZ3JvdXA6IDEsXG4gICAgICAgICAgICAgICAgICAgIHZpc2libGU6IFBlcm1pc3Npb25NYW5hZ2VyLmNoZWNrVG9wTGV2ZWxQZXJtaXNzaW9uKCAnV2FnZScgKSxcbiAgICAgICAgICAgICAgICAgICAgY29tbWFuZDogKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoIHRoaXMub25TaG93V2FnZUNsaWNrICYmIHR5cGVvZiB0aGlzLm9uU2hvd1dhZ2VDbGljayA9PT0gJ2Z1bmN0aW9uJyApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9uU2hvd1dhZ2VDbGljayggdGhpcy50aW1lc2hlZXRfc2V0dGluZ3Nfb3B0aW9uc1swXS5hY3RpdmUgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBsYWJlbDogJC5pMThuLl8oICdVc2UgRW1wbG95ZWUgVGltZXpvbmUnICksXG4gICAgICAgICAgICAgICAgICAgIGlkOiAndXNlX2VtcGxveWVlX3RpbWV6b25lJyxcbiAgICAgICAgICAgICAgICAgICAgbm9fZ3JvdXBfbGFiZWw6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIHZ1ZV9pY29uOiAndHRpY29uIHR0aWNvbi1zZXR0aW5nc19ibGFja18yNGRwJyxcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uX2dyb3VwOiAndGltZXNoZWV0X3NldHRpbmdzJyxcbiAgICAgICAgICAgICAgICAgICAgbXVsdGlfc2VsZWN0X2dyb3VwOiAyLFxuICAgICAgICAgICAgICAgICAgICB2aXNpYmxlOiAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCAncHVuY2gnLCAndmlldycgKSB8fCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggJ3B1bmNoJywgJ3ZpZXdfY2hpbGQnICkgKSxcbiAgICAgICAgICAgICAgICAgICAgY29tbWFuZDogKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoIHRoaXMub25UaW1lem9uZUNsaWNrICYmIHR5cGVvZiB0aGlzLm9uVGltZXpvbmVDbGljayA9PT0gJ2Z1bmN0aW9uJyApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9uVGltZXpvbmVDbGljayggdGhpcy50aW1lc2hlZXRfc2V0dGluZ3Nfb3B0aW9uc1sxXS5hY3RpdmUgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdXG4gICAgICAgIH1cbiAgICB9LFxuICAgIC8vIHdhdGNoOiB7XG4gICAgLy8gICAgIHB1bmNoX21vZGVfc2VsZWN0ZWQ6IGZ1bmN0aW9uICggdmFsICkge1xuICAgIC8vICAgICAgICAgaWYoIHRoaXMub25QdW5jaE1vZGVDaGFuZ2UgJiYgdHlwZW9mIHRoaXMub25QdW5jaE1vZGVDaGFuZ2UgPT09ICdmdW5jdGlvbicgKSB7XG4gICAgLy8gICAgICAgICAgICAgdGhpcy5vblB1bmNoTW9kZUNoYW5nZSggdmFsLCBmYWxzZSApO1xuICAgIC8vICAgICAgICAgfVxuICAgIC8vICAgICB9LFxuICAgIC8vIH0sXG4gICAgY29tcHV0ZWQ6IHtcbiAgICAgICAgZ2V0UHVuY2hNb2RlKCkgeyAvLyBUaGlzIHdheSB0aGUgdmFsdWUgaXMgY2FjaGVkIGlmIGl0IGRvZXNudCBjaGFuZ2UuXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wdW5jaF9tb2RlX3NlbGVjdGVkO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBtZXRob2RzOiB7XG4gICAgICAgIHNldFB1bmNoTW9kZSggbmV3X3ZhbHVlICkge1xuICAgICAgICAgICAgaWYgKCBuZXdfdmFsdWUgPT09ICdwdW5jaCcgfHwgbmV3X3ZhbHVlID09PSAnbWFudWFsJyApIHsgLy8gdmFsaWRhdGUgdGhlIGlucHV0IHBvdGVudGlhbGx5IGNvbWluZyBmcm9tIG91dHNpZGUgVnVlLlxuICAgICAgICAgICAgICAgIHRoaXMucHVuY2hfbW9kZV9zZWxlY3RlZCA9IG5ld192YWx1ZTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgRGVidWcuRXJyb3IoICdJbnZhbGlkIHBhcmFtZXRlcnMgcGFzc2VkIHRvIGZ1bmN0aW9uOiAnLCAnVGltZVNoZWV0Q29udHJvbEJhci52dWUnLCAnVGltZVNoZWV0Q29udHJvbEJhcicsICdzZXRQdW5jaE1vZGUnLCAxICk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBnZXRUaW1lc2hlZXRTZXR0aW5nc1N0YXRlKCBpdGVtX2lkICkge1xuICAgICAgICAgICAgdmFyIGl0ZW0gPSB0aGlzLnRpbWVzaGVldF9zZXR0aW5nc19vcHRpb25zLmZpbmQoIGVsZW1lbnQgPT4gZWxlbWVudC5pZCA9PT0gaXRlbV9pZCApO1xuICAgICAgICAgICAgaWYoIGl0ZW0gKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGl0ZW0uYWN0aXZlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBEZWJ1Zy5FcnJvciggJ0l0ZW0gbm90IGZvdW5kICgnKyBpdGVtX2lkICsnKS4gQ2hlY2sgc3VwcGxpZWQgaWQuJywgJ1RpbWVTaGVldENvbnRyb2xCYXIudnVlJywgJ1RpbWVTaGVldENvbnRyb2xCYXInLCAnZ2V0VGltZXNoZWV0U2V0dGluZ3NTdGF0ZScsIDEgKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBzZXRUaW1lc2hlZXRTZXR0aW5nc1N0YXRlKCBpdGVtX2lkLCB2YWx1ZSApIHtcbiAgICAgICAgICAgIHZhciBpdGVtID0gdGhpcy50aW1lc2hlZXRfc2V0dGluZ3Nfb3B0aW9ucy5maW5kKCBlbGVtZW50ID0+IGVsZW1lbnQuaWQgPT09IGl0ZW1faWQgKTtcbiAgICAgICAgICAgIGlmKCBpdGVtICkge1xuICAgICAgICAgICAgICAgIGl0ZW0uYWN0aXZlID0gdmFsdWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIERlYnVnLkVycm9yKCAnSXRlbSBub3QgZm91bmQgKCcrIGl0ZW1faWQgKycpLiBDaGVjayBzdXBwbGllZCBpZC4nLCAnVGltZVNoZWV0Q29udHJvbEJhci52dWUnLCAnVGltZVNoZWV0Q29udHJvbEJhcicsICdzZXRUaW1lc2hlZXRTZXR0aW5nc1N0YXRlJywgMSApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSxcbiAgICBjb21wb25lbnRzOiB7XG4gICAgICAgIFNlbGVjdEJ1dHRvbjogU2VsZWN0QnV0dG9uLFxuICAgICAgICBUVENvbnRleHRCdXR0b246IFRUQ29udGV4dEJ1dHRvblxuICAgIH1cbn07XG48L3NjcmlwdD5cblxuPHN0eWxlIHNjb3BlZD5cbiAgICAudHQtaG9yaXpvbnRhbC12dWUtYmFyIHtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgZmxleC1kaXJlY3Rpb246IHJvdztcbiAgICAgICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAgICBtYXJnaW4tdG9wOiAzcHg7XG4gICAgfVxuICAgIC5iYXItY29sdW1uIHtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgZmxleC1kaXJlY3Rpb246IHJvdztcbiAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICAgICAgcGFkZGluZzogMCA1cHg7XG4gICAgfVxuICAgIC5iYXItY29sdW1uLmxlZnQsXG4gICAgLmJhci1jb2x1bW4ucmlnaHQge1xuICAgICAgICB3aWR0aDogMjUlO1xuICAgIH1cbiAgICAuYmFyLWNvbHVtbi5yaWdodCB7XG4gICAgICAgIGp1c3RpZnktY29udGVudDogZmxleC1lbmQ7XG4gICAgfVxuICAgIDo6di1kZWVwKC5wdW5jaC1tYW51YWwgLnAtYnV0dG9uKSB7XG4gICAgICAgIHBhZGRpbmc6IC41NXJlbSAuNnJlbTtcbiAgICB9XG4gICAgOjp2LWRlZXAoLnAtYnV0dG9uLWxhYmVsKSB7XG4gICAgICAgIGZvbnQtc2l6ZTogMTRweDtcbiAgICB9XG48L3N0eWxlPiIsImV4cG9ydCAqIGZyb20gXCItIS4uLy4uLy4uLy4uL25vZGVfbW9kdWxlcy92dWUtbG9hZGVyL2Rpc3QvdGVtcGxhdGVMb2FkZXIuanM/P3J1bGVTZXRbMV0ucnVsZXNbMV0hLi4vLi4vLi4vLi4vbm9kZV9tb2R1bGVzL3Z1ZS1sb2FkZXIvZGlzdC9pbmRleC5qcz8/cnVsZVNldFsxXS5ydWxlc1s2XS51c2VbMF0hLi9UaW1lU2hlZXRDb250cm9sQmFyLnZ1ZT92dWUmdHlwZT10ZW1wbGF0ZSZpZD03MWZhMGI1MyZzY29wZWQ9dHJ1ZVwiIiwiZXhwb3J0IHsgZGVmYXVsdCB9IGZyb20gXCItIS4uLy4uLy4uLy4uL25vZGVfbW9kdWxlcy92dWUtbG9hZGVyL2Rpc3QvaW5kZXguanM/P3J1bGVTZXRbMV0ucnVsZXNbNl0udXNlWzBdIS4vVGltZVNoZWV0Q29udHJvbEJhci52dWU/dnVlJnR5cGU9c2NyaXB0Jmxhbmc9anNcIjsgZXhwb3J0ICogZnJvbSBcIi0hLi4vLi4vLi4vLi4vbm9kZV9tb2R1bGVzL3Z1ZS1sb2FkZXIvZGlzdC9pbmRleC5qcz8/cnVsZVNldFsxXS5ydWxlc1s2XS51c2VbMF0hLi9UaW1lU2hlZXRDb250cm9sQmFyLnZ1ZT92dWUmdHlwZT1zY3JpcHQmbGFuZz1qc1wiIiwiaW1wb3J0IHsgcmVuZGVyIH0gZnJvbSBcIi4vVGltZVNoZWV0Q29udHJvbEJhci52dWU/dnVlJnR5cGU9dGVtcGxhdGUmaWQ9NzFmYTBiNTMmc2NvcGVkPXRydWVcIlxuaW1wb3J0IHNjcmlwdCBmcm9tIFwiLi9UaW1lU2hlZXRDb250cm9sQmFyLnZ1ZT92dWUmdHlwZT1zY3JpcHQmbGFuZz1qc1wiXG5leHBvcnQgKiBmcm9tIFwiLi9UaW1lU2hlZXRDb250cm9sQmFyLnZ1ZT92dWUmdHlwZT1zY3JpcHQmbGFuZz1qc1wiXG5cbmltcG9ydCBcIi4vVGltZVNoZWV0Q29udHJvbEJhci52dWU/dnVlJnR5cGU9c3R5bGUmaW5kZXg9MCZpZD03MWZhMGI1MyZzY29wZWQ9dHJ1ZSZsYW5nPWNzc1wiXG5cbmltcG9ydCBleHBvcnRDb21wb25lbnQgZnJvbSBcIi9ob21lL21pa2ViL3RpbWV0cmV4L3RydW5rL25vZGVfbW9kdWxlcy92dWUtbG9hZGVyL2Rpc3QvZXhwb3J0SGVscGVyLmpzXCJcbmNvbnN0IF9fZXhwb3J0c19fID0gLyojX19QVVJFX18qL2V4cG9ydENvbXBvbmVudChzY3JpcHQsIFtbJ3JlbmRlcicscmVuZGVyXSxbJ19fc2NvcGVJZCcsXCJkYXRhLXYtNzFmYTBiNTNcIl1dKVxuXG5leHBvcnQgZGVmYXVsdCBfX2V4cG9ydHNfXyIsImltcG9ydCAnQC9nbG9iYWwvd2lkZ2V0cy9maWxlYnJvd3Nlci9USW1hZ2UnO1xuaW1wb3J0IFRUVnVlVXRpbHMgZnJvbSAnQC9zZXJ2aWNlcy9UVFZ1ZVV0aWxzJztcbmltcG9ydCBUaW1lU2hlZXRDb250cm9sQmFyIGZyb20gJ0AvY29tcG9uZW50cy90aW1lc2hlZXQvVGltZVNoZWV0Q29udHJvbEJhcic7XG5pbXBvcnQgeyBUVFVVSUQgfSBmcm9tICdAL2dsb2JhbC9UVFVVSUQnO1xuaW1wb3J0IHsgR2xvYmFsIH0gZnJvbSAnQC9nbG9iYWwvR2xvYmFsJztcblxuZXhwb3J0IGNsYXNzIFRpbWVTaGVldFZpZXdDb250cm9sbGVyIGV4dGVuZHMgQmFzZVZpZXdDb250cm9sbGVyIHtcblx0Y29uc3RydWN0b3IoIG9wdGlvbnMgPSB7fSApIHtcblx0XHRfLmRlZmF1bHRzKCBvcHRpb25zLCB7XG5cdFx0XHRlbDogJyN0aW1lc2hlZXRfdmlld19jb250YWluZXInLCAvL011c3Qgc2V0IGVsIGhlcmUgYW5kIGNhbiBvbmx5IHNldCBzdHJpbmcsIHNvIGV2ZW50cyBjYW4gd29ya1xuXHRcdFx0Ly8gX3JlcXVpcmVkX2ZpbGVzOiB7XG5cdFx0XHQvLyBcdDEwOiBbJ1RJbWFnZSddLFxuXHRcdFx0Ly8gXHQxNTogWydsZWFmbGV0LXRpbWV0cmV4J11cblx0XHRcdC8vIH0sXG5cdFx0XHRzdGF0dXNfYXJyYXk6IG51bGwsXG5cdFx0XHR0eXBlX2FycmF5OiBudWxsLFxuXHRcdFx0ZW1wbG95ZWVfbmF2OiBudWxsLFxuXHRcdFx0c3RhcnRfZGF0ZV9waWNrZXI6IG51bGwsXG5cdFx0XHRmdWxsX3RpbWVzaGVldF9kYXRhOiBudWxsLCAvL2Z1bGwgdGltZXNoZWV0IGRhdGFcblx0XHRcdGZ1bGxfZm9ybWF0OiAnZGRkLU1NTS1ERC1ZWVlZJyxcblx0XHRcdHdlZWtseV9mb3JtYXQ6ICdkZGQsIE1NTSBERCcsXG5cdFx0XHRkYXlfZm9ybWF0OiAnZGRkJyxcblx0XHRcdGRhdGVfZm9ybWF0OiAnTU1NIEREJyxcblx0XHRcdHN0YXJ0X2RhdGU6IG51bGwsXG5cdFx0XHRlbmRfZGF0ZTogbnVsbCxcblx0XHRcdHNlbGVjdF9jZWxsc19BcnJheTogW10sIC8vVGltZXNoZWV0IGdyaWRcblx0XHRcdHNlbGVjdF9wdW5jaGVzX2FycmF5OiBbXSwgLy9UaW1lc2hlZXQgZ3JpZC5cblx0XHRcdGFic2VuY2Vfc2VsZWN0X2NlbGxzX0FycmF5OiBbXSwgLy9BYnNlbmNlIGdyaWRcblx0XHRcdGFjY3VtdWxhdGVkX3RpbWVfY2VsbHNfYXJyYXk6IFtdLFxuXHRcdFx0cHJlbWl1bV9jZWxsc19hcnJheTogW10sXG5cdFx0XHR0aW1lc2hlZXRfZGF0YV9zb3VyY2U6IG51bGwsXG5cdFx0XHRhY2N1bXVsYXRlZF90aW1lX3NvdXJjZTogbnVsbCxcblx0XHRcdGFjY3VtdWxhdGVkX3RpbWVfZ3JpZDogbnVsbCxcblx0XHRcdGFjY3VtdWxhdGVkX3RpbWVfc291cmNlX21hcDogbnVsbCxcblx0XHRcdGJyYW5jaF9ncmlkOiBudWxsLFxuXHRcdFx0YnJhbmNoX3NvdXJjZV9tYXA6IG51bGwsXG5cdFx0XHRicmFuY2hfc291cmNlOiBudWxsLFxuXHRcdFx0ZGVwYXJ0bWVudF9ncmlkOiBudWxsLFxuXHRcdFx0ZGVwYXJ0bWVudF9zb3VyY2VfbWFwOiBudWxsLFxuXHRcdFx0ZGVwYXJ0bWVudF9zb3VyY2U6IG51bGwsXG5cdFx0XHRqb2JfZ3JpZDogbnVsbCxcblx0XHRcdGpvYl9zb3VyY2VfbWFwOiBudWxsLFxuXHRcdFx0am9iX3NvdXJjZTogbnVsbCxcblx0XHRcdGpvYl9pdGVtX2dyaWQ6IG51bGwsXG5cdFx0XHRqb2JfaXRlbV9zb3VyY2VfbWFwOiBudWxsLFxuXHRcdFx0am9iX2l0ZW1fc291cmNlOiBudWxsLFxuXHRcdFx0cHVuY2hfdGFnX3NvdXJjZV9tYXA6IG51bGwsXG5cdFx0XHRwdW5jaF90YWdfc291cmNlOiBudWxsLFxuXHRcdFx0cHJlbWl1bV9ncmlkOiBudWxsLFxuXHRcdFx0cHJlbWl1bV9zb3VyY2VfbWFwOiBudWxsLFxuXHRcdFx0cHJlbWl1bV9zb3VyY2U6IG51bGwsXG5cdFx0XHRhYnNlbmNlX2dyaWQ6IG51bGwsXG5cdFx0XHRhYnNlbmNlX3NvdXJjZTogbnVsbCxcblx0XHRcdGFic2VuY2Vfb3JpZ2luYWxfc291cmNlOiBudWxsLFxuXHRcdFx0YWNjdW11bGF0ZWRfdG90YWxfZ3JpZDogbnVsbCxcblx0XHRcdGFjY3VtdWxhdGVkX3RvdGFsX2dyaWRfc291cmNlX21hcDogbnVsbCxcblx0XHRcdGFjY3VtdWxhdGVkX3RvdGFsX2dyaWRfc291cmNlOiBudWxsLFxuXHRcdFx0cHVuY2hfbm90ZV9ncmlkOiBudWxsLFxuXHRcdFx0cHVuY2hfbm90ZV9ncmlkX3NvdXJjZTogbnVsbCxcblx0XHRcdHZlcmlmaWNhdGlvbl9ncmlkOiBudWxsLFxuXHRcdFx0dmVyaWZpY2F0aW9uX2dyaWRfc291cmNlOiBudWxsLFxuXHRcdFx0Z3JpZF9kaWM6IG51bGwsXG5cdFx0XHRwYXlfcGVyaW9kX21hcDogbnVsbCxcblx0XHRcdHBheV9wZXJpb2RfZGF0YTogbnVsbCxcblx0XHRcdHRpbWVzaGVldF92ZXJpZnlfZGF0YTogbnVsbCxcblx0XHRcdGFwaV90aW1lc2hlZXQ6IG51bGwsXG5cdFx0XHRhcGlfdXNlcl9kYXRlX3RvdGFsOiBudWxsLFxuXHRcdFx0YXBpX2RhdGU6IG51bGwsXG5cdFx0XHRhcGlfc3RhdGlvbjogbnVsbCxcblx0XHRcdGFwaV9wdW5jaDogbnVsbCxcblx0XHRcdGFic2VuY2VfbW9kZWw6IGZhbHNlLFxuXHRcdFx0c2VsZWN0X2RyYWdfbWVudV9pZDogJycsIC8vRG8gZHJhZyBtb3ZlIG9yIGNvcHlcblx0XHRcdGlzX21hc3NfYWRkaW5nOiBmYWxzZSxcblx0XHRcdGRlcGFydG1lbnRfY2VsbF9jb3VudDogMCxcblx0XHRcdGJyYW5jaF9jZWxsX2NvdW50OiAwLFxuXHRcdFx0cHJlbWl1bV9jZWxsX2NvdW50OiAwLFxuXHRcdFx0am9iX2NlbGxfY291bnQ6IDAsXG5cdFx0XHR0YXNrX2NlbGxfY291bnQ6IDAsXG5cdFx0XHRwdW5jaF90YWdfY2VsbF9jb3VudDogMCxcblx0XHRcdGFic2VuY2VfY2VsbF9jb3VudDogMCxcblx0XHRcdHB1bmNoX25vdGVfYWNjb3VudDogMCxcblx0XHRcdHNob3dfbmF2aWdhdGlvbl9ib3g6IHRydWUsXG5cdFx0XHRzdGF0aW9uOiBudWxsLFxuXHRcdFx0c2Nyb2xsX3Bvc2l0aW9uOiAwLFxuXHRcdFx0am9iX2FwaTogbnVsbCxcblx0XHRcdGpvYl9pdGVtX2FwaTogbnVsbCxcblx0XHRcdHVzZXJfZ3JvdXBfaWQ6IG51bGwsXG5cdFx0XHRwdW5jaF90YWdfYXBpOiBudWxsLFxuXHRcdFx0dXNlcl9hcGk6IG51bGwsXG5cdFx0XHRkZXBhcnRtZW50X2FwaTogbnVsbCxcblx0XHRcdGRlZmF1bHRfcHVuY2hfdGFnOiBbXSxcblx0XHRcdHByZXZpb3VzX3B1bmNoX3RhZ19zZWxlY3Rpb246IFtdLFxuXHRcdFx0YXBpX2Fic2VuY2VfcG9saWN5OiBudWxsLFxuXHRcdFx0cHJlX3RvdGFsX3RpbWU6IG51bGwsXG5cdFx0XHRhYnNlbmNlX2F2YWlsYWJsZV9iYWxhbmNlX2RhdGFMaXN0OiB7fSxcblx0XHRcdGF2YWlsYWJsZV9iYWxhbmNlX2luZm86IG51bGwsXG5cdFx0XHRzaG93X2pvYl91aTogZmFsc2UsXG5cdFx0XHRzaG93X2pvYl9pdGVtX3VpOiBmYWxzZSxcblx0XHRcdHNob3dfcHVuY2hfdGFnX3VpOiBmYWxzZSxcblx0XHRcdHNob3dfYnJhbmNoX3VpOiBmYWxzZSxcblx0XHRcdHNob3dfZGVwYXJ0bWVudF91aTogZmFsc2UsXG5cdFx0XHRzaG93X2dvb2RfcXVhbnRpdHlfdWk6IGZhbHNlLFxuXHRcdFx0c2hvd19iYWRfcXVhbnRpdHlfdWk6IGZhbHNlLFxuXHRcdFx0c2hvd19ub3RlX3VpOiBmYWxzZSxcblx0XHRcdHNob3dfc3RhdGlvbl91aTogZmFsc2UsXG5cdFx0XHRzaG93X2Fic2VuY2Vfam9iX3VpOiBmYWxzZSxcblx0XHRcdHNob3dfYWJzZW5jZV9qb2JfaXRlbV91aTogZmFsc2UsXG5cdFx0XHRzaG93X2Fic2VuY2VfcHVuY2hfdGFnX3VpOiBmYWxzZSxcblx0XHRcdHNob3dfYWJzZW5jZV9icmFuY2hfdWk6IGZhbHNlLFxuXHRcdFx0c2hvd19hYnNlbmNlX2RlcGFydG1lbnRfdWk6IGZhbHNlLFxuXHRcdFx0aG9saWRheV9kYXRhX2RpYzoge30sXG5cdFx0XHRncmlkX2RpdjogbnVsbCxcblx0XHRcdGFjdHVhbF90aW1lX2xhYmVsOiBudWxsLFxuXHRcdFx0Y29sdW1uX21hcHM6IG51bGwsXG5cdFx0XHRhY2NtdWxhdGVkX29yZGVyX21hcDoge30sXG5cdFx0XHR1cmxfYXJnc19iZWZvcmVfc2V0X2RhdGVfdXJsOiB7fSxcblx0XHRcdGFsbG93X2F1dG9fc3dpdGNoOiB0cnVlLFxuXHRcdFx0dnVlX2NvbnRyb2xfYmFyX2lkOiAnJyxcblx0XHRcdHByZXZpb3VzX2Fic2VuY2VfcG9saWN5X2lkOiBmYWxzZSxcblx0XHRcdGV2ZW50czoge30sXG5cdFx0XHQvL0lzc3VlICMzMjg2IC0gVXNlcnMgd2l0aG91dCBwZXJtaXNzaW9uIHRvIGRpc3BsYXkgXCJDdXJyZW50IFZpZXdcIiBkcm9wZG93biBzdGlsbCBuZWVkIHRvIGxvYWQgc2VsZWN0IGxheW91dCBmcm9tIHVzZXIgZ2VuZXJpYyBkYXRhXG5cdFx0XHQvL1RoaXMgaXMgdG8gZW5zdXJlIHRoZSBBUEkgYXR0ZW1wdHMgdG8gdXBkYXRlIHRoZSBjdXJyZW50IGxheW91dCBhbmQgbm90IGNyZWF0ZSBhIG5ldyBvbmUgY2F1c2luZyBhIHZhbGlkYXRpb24gZXJyb3IuXG5cdFx0XHRmb3JjZV9nZXRfc2VsZWN0X2xheW91dDogdHJ1ZVxuXHRcdH0gKTtcblxuXHRcdHN1cGVyKCBvcHRpb25zICk7XG5cdH1cblxuXHRpbml0KCBvcHRpb25zICkge1xuXHRcdC8vLy90aGlzLl9zdXBlcignaW5pdGlhbGl6ZScsIG9wdGlvbnMgKTtcblx0XHR0aGlzLnBlcm1pc3Npb25faWQgPSAncHVuY2gnO1xuXHRcdHRoaXMudmlld0lkID0gJ1RpbWVTaGVldCc7XG5cdFx0dGhpcy5zY3JpcHRfbmFtZSA9ICdUaW1lU2hlZXRWaWV3Jztcblx0XHR0aGlzLmNvbnRleHRfbWVudV9uYW1lID0gJC5pMThuLl8oICdUaW1lU2hlZXQnICk7XG5cdFx0dGhpcy5uYXZpZ2F0aW9uX2xhYmVsID0gJC5pMThuLl8oICdUaW1lU2hlZXQnICk7XG5cdFx0dGhpcy5hcGkgPSBUVEFQSS5BUElQdW5jaDtcblx0XHR0aGlzLmFwaV90aW1lc2hlZXQgPSBUVEFQSS5BUElUaW1lU2hlZXQ7XG5cdFx0dGhpcy5hcGlfdXNlcl9kYXRlX3RvdGFsID0gVFRBUEkuQVBJVXNlckRhdGVUb3RhbDtcblx0XHR0aGlzLmFwaV9kYXRlID0gVFRBUEkuQVBJVFREYXRlO1xuXHRcdHRoaXMuYXBpX3N0YXRpb24gPSBUVEFQSS5BUElTdGF0aW9uO1xuXHRcdHRoaXMuYXBpX3B1bmNoID0gVFRBUEkuQVBJUHVuY2g7XG5cdFx0aWYgKCAoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpID49IDIwICkgKSB7XG5cdFx0XHR0aGlzLmpvYl9hcGkgPSBUVEFQSS5BUElKb2I7XG5cdFx0XHR0aGlzLmpvYl9pdGVtX2FwaSA9IFRUQVBJLkFQSUpvYkl0ZW07XG5cdFx0XHR0aGlzLnB1bmNoX3RhZ19hcGkgPSBUVEFQSS5BUElQdW5jaFRhZztcblx0XHRcdHRoaXMuZGVwYXJ0bWVudF9hcGkgPSBUVEFQSS5BUElEZXBhcnRtZW50O1xuXHRcdH1cblx0XHR0aGlzLmFwaV9hYnNlbmNlX3BvbGljeSA9IFRUQVBJLkFQSUFic2VuY2VQb2xpY3k7XG5cdFx0dGhpcy5zY3JvbGxfcG9zaXRpb24gPSAwO1xuXHRcdHRoaXMuZ3JpZF9kaWMgPSB7fTtcblx0XHQvLyB0aGlzLmV2ZW50X2J1cyA9IG5ldyBUVEV2ZW50QnVzKHsgdmlld19pZDogdGhpcy52aWV3SWQgfSk7IC8vIFRpbWVTaGVldCBkb2VzIG5vdCB1c2UgVFRFdmVudEJ1cyB5ZXQsIGl0cyBjdXJyZW50bHkgdXNpbmcgZGlyZWN0IGFjY2VzcyB0byB0aGUgVnVlIGNvbXBvbmVudCBieSByZWZlcmVuY2UsIGFzIGEgcHJvb2Ygb2YgY29uY2VwdC4gQmVzdCB0byB1c2UgVFRFdmVudEJ1cyBmb3IgZnV0dXJlIHdvcmsgdGhvdWdoLlxuXG5cdFx0dGhpcy5pbml0UGVybWlzc2lvbigpO1xuXHRcdHRoaXMucmVuZGVyKCk7XG5cdFx0dGhpcy5idWlsZENvbnRleHRNZW51KCk7XG5cdFx0dGhpcy5pbml0RGF0YSgpO1xuXHR9XG5cblx0aW5pdEVkaXRWaWV3KCkge1xuXHRcdFRUUHJvbWlzZS5yZXNvbHZlKCAnVGltZVNoZWV0Vmlld0NvbnRyb2xsZXInLCAnYWRkY2xpY2snICk7XG5cdFx0c3VwZXIuaW5pdEVkaXRWaWV3KCk7XG5cdH1cblxuXHRvblN1YlZpZXdSZW1vdmVkKCBpc19jYW5jZWwgKSB7XG5cdFx0aWYgKCAhaXNfY2FuY2VsICkge1xuXHRcdFx0dGhpcy5zZWFyY2goKTtcblx0XHR9XG5cblx0XHRpZiAoICF0aGlzLmVkaXRfdmlldyApIHtcblx0XHRcdHRoaXMuc2V0RGVmYXVsdE1lbnUoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5zZXRFZGl0TWVudSgpO1xuXHRcdH1cblx0fVxuXG5cdHNldFNjcm9sbFBvc2l0aW9uKCkge1xuXHRcdGlmICggdGhpcy5zY3JvbGxfcG9zaXRpb24gPiAwICkge1xuXHRcdFx0dGhpcy5ncmlkX2Rpdi5zY3JvbGxUb3AoIHRoaXMuc2Nyb2xsX3Bvc2l0aW9uICk7XG5cdFx0fVxuXHR9XG5cblx0cHVuY2hNb2RlVmFsaWRhdGUoIHBfaWQgKSB7XG5cdFx0aWYgKCAhcF9pZCApIHtcblx0XHRcdHBfaWQgPSAncHVuY2gnO1xuXHRcdH1cblxuXHRcdGlmICggUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHBfaWQsICdwdW5jaF90aW1lc2hlZXQnICkgJiZcblx0XHRcdFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCBwX2lkLCAnbWFudWFsX3RpbWVzaGVldCcgKSApIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRnZXRQdW5jaFBlcm1pc3Npb25UeXBlKCkge1xuXHRcdHJldHVybiB0aGlzLmFic2VuY2VfbW9kZWwgPyAnYWJzZW5jZScgOiAncHVuY2gnO1xuXHR9XG5cblx0am9iVUlWYWxpZGF0ZSggcF9pZCApIHtcblxuXHRcdGlmICggIXBfaWQgKSB7XG5cdFx0XHRwX2lkID0gJ3B1bmNoJztcblx0XHR9XG5cblx0XHRpZiAoR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgJiYgUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoICdqb2InLCAnZW5hYmxlZCcgKSAmJlxuXHRcdFx0UGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHBfaWQsICdlZGl0X2pvYicgKSApIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRqb2JJdGVtVUlWYWxpZGF0ZSggcF9pZCApIHtcblxuXHRcdGlmICggIXBfaWQgKSB7XG5cdFx0XHRwX2lkID0gJ3B1bmNoJztcblx0XHR9XG5cblx0XHRpZiAoR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgJiYgUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHBfaWQsICdlZGl0X2pvYl9pdGVtJyApICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdHB1bmNoVGFnVUlWYWxpZGF0ZSggcF9pZCApIHtcblxuXHRcdGlmICggIXBfaWQgKSB7XG5cdFx0XHRwX2lkID0gJ3B1bmNoJztcblx0XHR9XG5cblx0XHRpZiAoR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgJiYgUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHBfaWQsICdlZGl0X3B1bmNoX3RhZycgKSApIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHQvL1JlZnJlc2ggdG8gY2xlYXIgd2Fybm5pbmcgbWVzc2FnZXMgYWZ0ZXIgc2F2aW5nIGZyb20gZW1wbG95ZWUgZWRpdCB2aWV3XG5cdHVwZGF0ZVNlbGVjdFVzZXJBbmRSZWZyZXNoKCBuZXdfaXRlbSApIHtcblxuXHRcdHRoaXMuZW1wbG95ZWVfbmF2LnVwZGF0ZVNlbGVjdEl0ZW0oIG5ld19pdGVtICk7XG5cblx0XHR0aGlzLnNlYXJjaCgpO1xuXHR9XG5cblx0YnJhbmNoVUlWYWxpZGF0ZSggcF9pZCApIHtcblxuXHRcdGlmICggIXBfaWQgKSB7XG5cdFx0XHRwX2lkID0gJ3B1bmNoJztcblx0XHR9XG5cblx0XHRpZiAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCBwX2lkLCAnZWRpdF9icmFuY2gnICkgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0ZGVwYXJ0bWVudFVJVmFsaWRhdGUoIHBfaWQgKSB7XG5cblx0XHRpZiAoICFwX2lkICkge1xuXHRcdFx0cF9pZCA9ICdwdW5jaCc7XG5cdFx0fVxuXG5cdFx0aWYgKCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggcF9pZCwgJ2VkaXRfZGVwYXJ0bWVudCcgKSApIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRnb29kUXVhbnRpdHlVSVZhbGlkYXRlKCBwX2lkICkge1xuXG5cdFx0aWYgKCAhcF9pZCApIHtcblx0XHRcdHBfaWQgPSAncHVuY2gnO1xuXHRcdH1cblxuXHRcdGlmICggUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHBfaWQsICdlZGl0X3F1YW50aXR5JyApICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdGJhZFF1YW50aXR5VUlWYWxpZGF0ZSggcF9pZCApIHtcblxuXHRcdGlmICggIXBfaWQgKSB7XG5cdFx0XHRwX2lkID0gJ3B1bmNoJztcblx0XHR9XG5cblx0XHRpZiAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCBwX2lkLCAnZWRpdF9xdWFudGl0eScgKSAmJlxuXHRcdFx0UGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHBfaWQsICdlZGl0X2JhZF9xdWFudGl0eScgKSApIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRsb2NhdGlvblVJVmFsaWRhdGUoIHBfaWQgKSB7XG5cblx0XHRpZiAoICFwX2lkICkge1xuXHRcdFx0cF9pZCA9ICdwdW5jaCc7XG5cdFx0fVxuXG5cdFx0aWYgKCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggcF9pZCwgJ2VkaXRfbG9jYXRpb24nICkgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0bm90ZVVJVmFsaWRhdGUoIHBfaWQgKSB7XG5cblx0XHRpZiAoICFwX2lkICkge1xuXHRcdFx0cF9pZCA9ICdwdW5jaCc7XG5cdFx0fVxuXG5cdFx0aWYgKCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggcF9pZCwgJ2VkaXRfbm90ZScgKSApIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRzdGF0aW9uVmFsaWRhdGUoKSB7XG5cdFx0aWYgKCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggJ3N0YXRpb24nLCAnZW5hYmxlZCcgKSApIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHQvKiBqc2hpbnQgaWdub3JlOnN0YXJ0ICovXG5cblx0Ly9TcGVjaWFsIHBlcm1pc3Npb24gY2hlY2sgZm9yIHZpZXdzLCBuZWVkIG92ZXJyaWRlXG5cdGluaXRQZXJtaXNzaW9uKCkge1xuXHRcdHN1cGVyLmluaXRQZXJtaXNzaW9uKCk7XG5cblx0XHRpZiAoICFQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggJ3B1bmNoJywgJ3ZpZXcnICkgJiYgIVBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCAncHVuY2gnLCAndmlld19jaGlsZCcgKSApIHtcblx0XHRcdHRoaXMuc2hvd19uYXZpZ2F0aW9uX2JveCA9IGZhbHNlO1xuXHRcdFx0dGhpcy5zaG93X3NlYXJjaF90YWIgPSBmYWxzZTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5zaG93X25hdmlnYXRpb25fYm94ID0gdHJ1ZTtcblx0XHRcdHRoaXMuc2hvd19zZWFyY2hfdGFiID0gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoIHRoaXMucHVuY2hNb2RlVmFsaWRhdGUoKSApIHtcblx0XHRcdHRoaXMuc2hvd19wdW5jaF9tb2RlX3VpID0gdHJ1ZTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5zaG93X3B1bmNoX21vZGVfdWkgPSBmYWxzZTtcblx0XHR9XG5cblx0XHR0aGlzLmFsbG93X2F1dG9fc3dpdGNoICYmIHRoaXMuc2hvd19wdW5jaF9tb2RlX3VpICYmICggdGhpcy5pc19hdXRvX3N3aXRjaCA9IHRydWUgKTtcblxuXHRcdGlmICggdGhpcy5qb2JVSVZhbGlkYXRlKCkgKSB7XG5cdFx0XHR0aGlzLnNob3dfam9iX3VpID0gdHJ1ZTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5zaG93X2pvYl91aSA9IGZhbHNlO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5qb2JJdGVtVUlWYWxpZGF0ZSgpICkge1xuXHRcdFx0dGhpcy5zaG93X2pvYl9pdGVtX3VpID0gdHJ1ZTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5zaG93X2pvYl9pdGVtX3VpID0gZmFsc2U7XG5cdFx0fVxuXG5cblx0XHRpZiAoIHRoaXMucHVuY2hUYWdVSVZhbGlkYXRlKCkgKSB7XG5cdFx0XHR0aGlzLnNob3dfcHVuY2hfdGFnX3VpID0gdHJ1ZTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5zaG93X3B1bmNoX3RhZ191aSA9IGZhbHNlO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5icmFuY2hVSVZhbGlkYXRlKCkgKSB7XG5cdFx0XHR0aGlzLnNob3dfYnJhbmNoX3VpID0gdHJ1ZTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5zaG93X2JyYW5jaF91aSA9IGZhbHNlO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5kZXBhcnRtZW50VUlWYWxpZGF0ZSgpICkge1xuXHRcdFx0dGhpcy5zaG93X2RlcGFydG1lbnRfdWkgPSB0cnVlO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnNob3dfZGVwYXJ0bWVudF91aSA9IGZhbHNlO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5nb29kUXVhbnRpdHlVSVZhbGlkYXRlKCkgKSB7XG5cdFx0XHR0aGlzLnNob3dfZ29vZF9xdWFudGl0eV91aSA9IHRydWU7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuc2hvd19nb29kX3F1YW50aXR5X3VpID0gZmFsc2U7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLmJhZFF1YW50aXR5VUlWYWxpZGF0ZSgpICkge1xuXHRcdFx0dGhpcy5zaG93X2JhZF9xdWFudGl0eV91aSA9IHRydWU7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuc2hvd19iYWRfcXVhbnRpdHlfdWkgPSBmYWxzZTtcblx0XHR9XG5cblx0XHRpZiAoIHRoaXMubm90ZVVJVmFsaWRhdGUoKSApIHtcblx0XHRcdHRoaXMuc2hvd19ub3RlX3VpID0gdHJ1ZTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5zaG93X25vdGVfdWkgPSBmYWxzZTtcblx0XHR9XG5cblx0XHRpZiAoIHRoaXMubG9jYXRpb25VSVZhbGlkYXRlKCkgKSB7XG5cdFx0XHR0aGlzLnNob3dfbG9jYXRpb25fdWkgPSB0cnVlO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnNob3dfbG9jYXRpb25fdWkgPSBmYWxzZTtcblx0XHR9XG5cblx0XHRpZiAoIHRoaXMuc3RhdGlvblZhbGlkYXRlKCkgKSB7XG5cdFx0XHR0aGlzLnNob3dfc3RhdGlvbl91aSA9IHRydWU7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuc2hvd19zdGF0aW9uX3VpID0gZmFsc2U7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLmpvYlVJVmFsaWRhdGUoICdhYnNlbmNlJyApICkge1xuXHRcdFx0dGhpcy5zaG93X2Fic2VuY2Vfam9iX3VpID0gdHJ1ZTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5zaG93X2Fic2VuY2Vfam9iX3VpID0gZmFsc2U7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLmpvYkl0ZW1VSVZhbGlkYXRlKCAnYWJzZW5jZScgKSApIHtcblx0XHRcdHRoaXMuc2hvd19hYnNlbmNlX2pvYl9pdGVtX3VpID0gdHJ1ZTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5zaG93X2Fic2VuY2Vfam9iX2l0ZW1fdWkgPSBmYWxzZTtcblx0XHR9XG5cblx0XHRpZiAoIHRoaXMucHVuY2hUYWdVSVZhbGlkYXRlKCAnYWJzZW5jZScgKSApIHtcblx0XHRcdHRoaXMuc2hvd19hYnNlbmNlX3B1bmNoX3RhZ191aSA9IHRydWU7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuc2hvd19hYnNlbmNlX3B1bmNoX3RhZ191aSA9IGZhbHNlO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5icmFuY2hVSVZhbGlkYXRlKCAnYWJzZW5jZScgKSApIHtcblx0XHRcdHRoaXMuc2hvd19hYnNlbmNlX2JyYW5jaF91aSA9IHRydWU7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuc2hvd19hYnNlbmNlX2JyYW5jaF91aSA9IGZhbHNlO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5kZXBhcnRtZW50VUlWYWxpZGF0ZSggJ2Fic2VuY2UnICkgKSB7XG5cdFx0XHR0aGlzLnNob3dfYWJzZW5jZV9kZXBhcnRtZW50X3VpID0gdHJ1ZTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5zaG93X2Fic2VuY2VfZGVwYXJ0bWVudF91aSA9IGZhbHNlO1xuXHRcdH1cblx0fVxuXG5cdC8qIGpzaGludCBpZ25vcmU6ZW5kICovXG5cblx0b3duZXJPckNoaWxkUGVybWlzc2lvblZhbGlkYXRlKCBwX2lkLCBwZXJtaXNzaW9uX25hbWUsIHNlbGVjdGVkX2l0ZW0gKSB7XG5cdFx0dmFyIGZpZWxkO1xuXHRcdGlmICggcGVybWlzc2lvbl9uYW1lICYmIHBlcm1pc3Npb25fbmFtZS5pbmRleE9mKCAnY2hpbGQnICkgPiAtMSApIHtcblx0XHRcdGZpZWxkID0gJ2lzX2NoaWxkJztcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZmllbGQgPSAnaXNfb3duZXInO1xuXHRcdH1cblxuXHRcdHZhciB1c2VyID0gdGhpcy5nZXRTZWxlY3RFbXBsb3llZSggdHJ1ZSApO1xuXG5cdFx0aWYgKCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggcF9pZCwgcGVybWlzc2lvbl9uYW1lICkgJiYgKCAhdXNlciB8fCAhR2xvYmFsLmlzU2V0KCB1c2VyW2ZpZWxkXSApIHx8ICggdXNlciAmJiB1c2VyW2ZpZWxkXSApICkgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRpbml0T3B0aW9ucygpIHtcblx0XHR2YXIgb3B0aW9ucyA9IFtcblx0XHRcdHsgb3B0aW9uX25hbWU6ICd0eXBlJywgYXBpOiB0aGlzLmFwaSB9LFxuXHRcdFx0eyBvcHRpb25fbmFtZTogJ3N0YXR1cycsIGFwaTogdGhpcy5hcGkgfSxcblx0XHRdO1xuXG5cdFx0dGhpcy5pbml0RHJvcERvd25PcHRpb25zKCBvcHRpb25zKTtcblx0fVxuXHRnZXRDdXN0b21Db250ZXh0TWVudU1vZGVsKCkge1xuXHRcdHZhciBjb250ZXh0X21lbnVfbW9kZWwgPSB7XG5cdFx0XHRncm91cHM6IHtcblx0XHRcdFx0ZHJhZ19hbmRfZHJvcDoge1xuXHRcdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ0RyYWcgJiBEcm9wJyApLFxuXHRcdFx0XHRcdGlkOiB0aGlzLnZpZXdJZCArICdkcmFnX2FuZF9kcm9wJ1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0ZXhjbHVkZTogW1xuXHRcdFx0XHQnZXhwb3J0X2V4Y2VsJyxcblx0XHRcdFx0J2FkZCcsXG5cdFx0XHRcdCdjb3B5Jyxcblx0XHRcdFx0J2NvcHlfYXNfbmV3J1xuXHRcdFx0XSxcblx0XHRcdGluY2x1ZGU6IFtcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ05ldyBQdW5jaCcgKSxcblx0XHRcdFx0XHRpZDogJ2FkZF9wdW5jaCcsXG5cdFx0XHRcdFx0YWN0aW9uX2dyb3VwOiAnbmV3Jyxcblx0XHRcdFx0XHRncm91cDogJ2VkaXRvcicsXG5cdFx0XHRcdFx0dnVlX2ljb246ICd0dGljb24gdHRpY29uLWFkZF9ibGFja18yNGRwJyxcblx0XHRcdFx0XHRzaG93X29uX3JpZ2h0X2NsaWNrOiB0cnVlLFxuXHRcdFx0XHRcdHNvcnRfb3JkZXI6IDkxMFxuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnTmV3IEFic2VuY2UnICksXG5cdFx0XHRcdFx0aWQ6ICdhZGRfYWJzZW5jZScsXG5cdFx0XHRcdFx0YWN0aW9uX2dyb3VwOiAnbmV3Jyxcblx0XHRcdFx0XHRncm91cDogJ2VkaXRvcicsXG5cdFx0XHRcdFx0dnVlX2ljb246ICd0dGljb24gdHRpY29uLWFkZF9ibGFja18yNGRwJyxcblx0XHRcdFx0XHRzaG93X29uX3JpZ2h0X2NsaWNrOiB0cnVlLFxuXHRcdFx0XHRcdHNvcnRfb3JkZXI6IDkyMFxuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnSW4vT3V0JyApLFxuXHRcdFx0XHRcdGlkOiAnaW5fb3V0Jyxcblx0XHRcdFx0XHRhY3Rpb25fZ3JvdXA6ICdpbl9vdXQnLFxuXHRcdFx0XHRcdGdyb3VwOiAnZWRpdG9yJyxcblx0XHRcdFx0XHR2dWVfaWNvbjogJ3R0aWNvbiB0dGljb24tdGltZXJfYmxhY2tfMjRkcCcsXG5cdFx0XHRcdFx0c2hvd19vbl9yaWdodF9jbGljazogdHJ1ZSxcblx0XHRcdFx0XHRzb3J0X29yZGVyOiAxMDUwXG5cdFx0XHRcdH0sXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRsYWJlbDogJC5pMThuLl8oICdEcmFnICYgRHJvcDogTW92ZScgKSxcblx0XHRcdFx0XHRpZDogJ21vdmUnLFxuXHRcdFx0XHRcdG1lbnVfYWxpZ246ICdyaWdodCcsXG5cdFx0XHRcdFx0YWN0aW9uX2dyb3VwOiAnbW92ZV9jb3B5Jyxcblx0XHRcdFx0XHRtdWx0aV9zZWxlY3RfZ3JvdXA6IDFcblx0XHRcdFx0fSxcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ0RyYWcgJiBEcm9wOiBDb3B5JyApLFxuXHRcdFx0XHRcdGlkOiAnZHJhZ19jb3B5Jyxcblx0XHRcdFx0XHRtZW51X2FsaWduOiAncmlnaHQnLFxuXHRcdFx0XHRcdGFjdGlvbl9ncm91cDogJ21vdmVfY29weScsXG5cdFx0XHRcdFx0bXVsdGlfc2VsZWN0X2dyb3VwOiAxXG5cdFx0XHRcdH0sXG5cdFx0XHRdXG5cdFx0fTtcblxuXHRcdGlmICggUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoICdyZXF1ZXN0JywgJ2FkZCcgKSApIHtcblx0XHRcdGNvbnRleHRfbWVudV9tb2RlbC5pbmNsdWRlLnB1c2goIHtcblx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnQWRkIFJlcXVlc3QnICksXG5cdFx0XHRcdGlkOiAnQWRkUmVxdWVzdCcsXG5cdFx0XHRcdHZ1ZV9pY29uOiAndHRpY29uIHR0aWNvbi1wb3N0X2FkZF9ibGFja18yNGRwJyxcblx0XHRcdFx0bWVudV9hbGlnbjogJ3JpZ2h0Jyxcblx0XHRcdFx0cGVybWlzc2lvbl9yZXN1bHQ6IHRydWUsXG5cdFx0XHRcdHBlcm1pc3Npb246IHRydWUsXG5cdFx0XHRcdHNob3dfb25fcmlnaHRfY2xpY2s6IHRydWUsXG5cdFx0XHRcdHNvcnRfb3JkZXI6IDEwMDBcblx0XHRcdH0gKTtcblx0XHR9XG5cblx0XHRpZiAoICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMTUgKSApIHtcblx0XHRcdGNvbnRleHRfbWVudV9tb2RlbC5pbmNsdWRlLnB1c2goXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRsYWJlbDogJC5pMThuLl8oICdNYXAnICksXG5cdFx0XHRcdFx0aWQ6ICdtYXAnLFxuXHRcdFx0XHRcdG1lbnVfYWxpZ246ICdyaWdodCcsXG5cdFx0XHRcdFx0dnVlX2ljb246ICd0dGljb24gdHRpY29uLW1hcF9ibGFja18yNGRwJyxcblx0XHRcdFx0XHRzaG93X29uX3JpZ2h0X2NsaWNrOiB0cnVlLFxuXHRcdFx0XHRcdHNvcnRfb3JkZXI6IDIwMDAsXG5cdFx0XHRcdH1cblx0XHRcdCk7XG5cdFx0fVxuXG5cdFx0Y29udGV4dF9tZW51X21vZGVsLmluY2x1ZGUucHVzaChcblx0XHRcdHtcblx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnUHJpbnQnICksXG5cdFx0XHRcdGlkOiAncHJpbnQnLFxuXHRcdFx0XHRhY3Rpb25fZ3JvdXBfaGVhZGVyOiB0cnVlLFxuXHRcdFx0XHRhY3Rpb25fZ3JvdXA6ICdwcmludF9tZW51Jyxcblx0XHRcdFx0c29ydF9vcmRlcjogNzAwMCxcblx0XHRcdFx0bWVudV9hbGlnbjogJ3JpZ2h0Jyxcblx0XHRcdFx0dHlwZTogMixcblx0XHRcdFx0cGVybWlzc2lvbl9yZXN1bHQ6IHRydWUsXG5cdFx0XHRcdHBlcm1pc3Npb246IHRydWVcblx0XHRcdH0sXG5cdFx0XHR7XG5cdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ1N1bW1hcnknICksXG5cdFx0XHRcdGlkOiAncHJpbnRfc3VtbWFyeScsXG5cdFx0XHRcdGFjdGlvbl9ncm91cDogJ3ByaW50X21lbnUnLFxuXHRcdFx0XHRzb3J0X29yZGVyOiA3MDAwLFxuXHRcdFx0XHRtZW51X2FsaWduOiAncmlnaHQnXG5cdFx0XHR9LFxuXHRcdFx0e1xuXHRcdFx0XHRsYWJlbDogJC5pMThuLl8oICdEZXRhaWxlZCcgKSxcblx0XHRcdFx0aWQ6ICdwcmludF9kZXRhaWxlZCcsXG5cdFx0XHRcdGFjdGlvbl9ncm91cDogJ3ByaW50X21lbnUnLFxuXHRcdFx0XHRzb3J0X29yZGVyOiA3MDAwLFxuXHRcdFx0XHRtZW51X2FsaWduOiAncmlnaHQnXG5cdFx0XHR9LFxuXHRcdFx0e1xuXHRcdFx0XHRsYWJlbDogJC5pMThuLl8oICdKdW1wIFRvJyApLFxuXHRcdFx0XHRpZDogJ2p1bXBfdG9faGVhZGVyJyxcblx0XHRcdFx0bWVudV9hbGlnbjogJ3JpZ2h0Jyxcblx0XHRcdFx0YWN0aW9uX2dyb3VwOiAnanVtcF90bycsXG5cdFx0XHRcdHNvcnRfb3JkZXI6IDgwMDAsXG5cdFx0XHRcdGFjdGlvbl9ncm91cF9oZWFkZXI6IHRydWUsXG5cdFx0XHRcdHBlcm1pc3Npb25fcmVzdWx0OiBmYWxzZSAvLyB0byBoaWRlIGl0IGluIGxlZ2FjeSBjb250ZXh0IG1lbnUgYW5kIGF2b2lkIGVycm9ycyBpbiBsZWdhY3kgcGFyc2Vycy5cblx0XHRcdH0sXG5cdFx0XHR7XG5cdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ1NjaGVkdWxlcycgKSxcblx0XHRcdFx0aWQ6ICdzY2hlZHVsZScsXG5cdFx0XHRcdG1lbnVfYWxpZ246ICdyaWdodCcsXG5cdFx0XHRcdGFjdGlvbl9ncm91cDogJ2p1bXBfdG8nLFxuXHRcdFx0XHRzb3J0X29yZGVyOiA4MDAwXG5cdFx0XHRcdH0sXG5cdFx0XHR7XG5cdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ1BheSBTdHVicycgKSxcblx0XHRcdFx0aWQ6ICdwYXlfc3R1YicsXG5cdFx0XHRcdG1lbnVfYWxpZ246ICdyaWdodCcsXG5cdFx0XHRcdGFjdGlvbl9ncm91cDogJ2p1bXBfdG8nLFxuXHRcdFx0XHRzb3J0X29yZGVyOiA4MDAwXG5cdFx0XHRcdH0sXG5cdFx0XHR7XG5cdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ0VkaXQgRW1wbG95ZWUnICksXG5cdFx0XHRcdGlkOiAnZWRpdF9lbXBsb3llZScsXG5cdFx0XHRcdG1lbnVfYWxpZ246ICdyaWdodCcsXG5cdFx0XHRcdGFjdGlvbl9ncm91cDogJ2p1bXBfdG8nLFxuXHRcdFx0XHRzb3J0X29yZGVyOiA4MDAwXG5cdFx0XHRcdH0sXG5cdFx0XHR7XG5cdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ0VkaXQgUGF5IFBlcmlvZCcgKSxcblx0XHRcdFx0aWQ6ICdlZGl0X3BheV9wZXJpb2QnLFxuXHRcdFx0XHRtZW51X2FsaWduOiAncmlnaHQnLFxuXHRcdFx0XHRhY3Rpb25fZ3JvdXA6ICdqdW1wX3RvJyxcblx0XHRcdFx0c29ydF9vcmRlcjogODAwMFxuXHRcdFx0XHR9LFxuXHRcdFx0e1xuXHRcdFx0XHRsYWJlbDogJC5pMThuLl8oICdBY2N1bXVsYXRlZCBUaW1lJyApLFxuXHRcdFx0XHRpZDogJ2FjY3VtdWxhdGVkX3RpbWUnLFxuXHRcdFx0XHRtZW51X2FsaWduOiAncmlnaHQnLFxuXHRcdFx0XHRhY3Rpb25fZ3JvdXA6ICdqdW1wX3RvJyxcblx0XHRcdFx0c29ydF9vcmRlcjogODAwMFxuXHRcdFx0XHR9LFxuXHRcdFx0e1xuXHRcdFx0XHRsYWJlbDogJycsIC8vRW1wdHkgbGFiZWwuIHZ1ZV9pY29uIGlzIGRpc3BsYXllZCBpbnN0ZWFkIG9mIHRleHQuXG5cdFx0XHRcdGlkOiAnb3RoZXJfaGVhZGVyJyxcblx0XHRcdFx0bWVudV9hbGlnbjogJ3JpZ2h0Jyxcblx0XHRcdFx0YWN0aW9uX2dyb3VwOiAnb3RoZXInLFxuXHRcdFx0XHRhY3Rpb25fZ3JvdXBfaGVhZGVyOiB0cnVlLFxuXHRcdFx0XHR2dWVfaWNvbjogJ3R0aWNvbiB0dGljb24tbW9yZV92ZXJ0X2JsYWNrXzI0ZHAnLFxuXHRcdFx0fSxcblx0XHRcdHtcblx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnUmVDYWxjdWxhdGUgVGltZVNoZWV0JyApLFxuXHRcdFx0XHRpZDogJ3JlX2NhbGN1bGF0ZV90aW1lc2hlZXQnLFxuXHRcdFx0XHRtZW51X2FsaWduOiAncmlnaHQnLFxuXHRcdFx0XHRhY3Rpb25fZ3JvdXA6ICdvdGhlcicsXG5cdFx0XHRcdH0sXG5cdFx0XHR7XG5cdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ0dlbmVyYXRlIFBheSBTdHViJyApLFxuXHRcdFx0XHRpZDogJ2dlbmVyYXRlX3BheV9zdHViJyxcblx0XHRcdFx0bWVudV9hbGlnbjogJ3JpZ2h0Jyxcblx0XHRcdFx0YWN0aW9uX2dyb3VwOiAnb3RoZXInLFxuXHRcdFx0XHR9LFxuXHRcdCk7XG5cblx0XHRyZXR1cm4gY29udGV4dF9tZW51X21vZGVsO1xuXHR9XG5cblx0cGFyc2VDdXN0b21Db250ZXh0TW9kZWxGb3JFZGl0Vmlld3MoIGNvbnRleHRfbWVudV9tb2RlbCApIHtcblxuXHRcdGNvbnRleHRfbWVudV9tb2RlbCA9IHN1cGVyLnBhcnNlQ3VzdG9tQ29udGV4dE1vZGVsRm9yRWRpdFZpZXdzKCBjb250ZXh0X21lbnVfbW9kZWwgKTtcblxuXHRcdGlmKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkubWVudV90eXBlID09PSAnZWRpdHZpZXdfY29udGV4dG1lbnUnICkge1xuXHRcdFx0Y29udGV4dF9tZW51X21vZGVsLmV4Y2x1ZGUucHVzaChcblx0XHRcdFx0J21vdmUnLFxuXHRcdFx0XHQnZHJhZ19jb3B5Jyxcblx0XHRcdFx0J3JlX2NhbGN1bGF0ZV90aW1lc2hlZXQnLFxuXHRcdFx0XHQnZ2VuZXJhdGVfcGF5X3N0dWInLFxuXHRcdFx0XHQncHJpbnQnLFxuXHRcdFx0XHQncHJpbnRfZGV0YWlsZWQnLFxuXHRcdFx0XHQncHJpbnRfc3VtbWFyeScsXG5cdFx0XHQpXG5cdFx0fVxuXG5cdFx0cmV0dXJuIGNvbnRleHRfbWVudV9tb2RlbDtcblx0fVxuXG5cdG9wZW5FZGl0VmlldygpIHtcblx0XHQvLyMyMjk1IC0gUmUtaW5pdGlhbGl6ZSBwcmV2aW91c19hYnNlbmNlX3BvbGljeV9pZCB0byBlbnN1cmUgdGhhdCBwcmV2aW91c2x5IHNhdmVkIHZhbHVlcyBhcmUgcGFzc2VkIGNvcnJlY3RseSBpbnRvIHRoZSBlc3RpbWF0aW9uIG9mIHByb2plY3RlZCBhdmFpbGFibGUgYmFsYW5jZS5cblx0XHR0aGlzLnByZXZpb3VzX2Fic2VuY2VfcG9saWN5X2lkID0gZmFsc2U7XG5cblx0XHRHbG9iYWwuc2V0VUlOb3RyZWFkeSgpO1xuXHRcdFRUUHJvbWlzZS5hZGQoICdpbml0JywgJ2luaXQnICk7XG5cdFx0VFRQcm9taXNlLndhaXQoKTtcblx0XHRpZiAoICF0aGlzLmVkaXRfdmlldyApIHtcblx0XHRcdHRoaXMuaXNfZWRpdCA9IHRydWU7XG5cdFx0XHR0aGlzLmluaXRFZGl0Vmlld1VJKCAnVGltZVNoZWV0JywgJ1RpbWVTaGVldEVkaXRWaWV3Lmh0bWwnICk7XG5cdFx0fVxuXHR9XG5cblx0LyoganNoaW50IGlnbm9yZTpzdGFydCAqL1xuXG5cdC8vc2V0IHdpZGdldCBkaXNhYmxlYmlsaXR5IGlmIHZpZXcgbW9kZSBvciBlZGl0IG1vZGVcblx0c2V0RWRpdFZpZXdXaWRnZXRzTW9kZSgpIHtcblx0XHR2YXIgZGlkX2NsZWFuID0gZmFsc2U7XG5cdFx0Zm9yICggdmFyIGtleSBpbiB0aGlzLmVkaXRfdmlld191aV9kaWMgKSB7XG5cdFx0XHRpZiAoICF0aGlzLmVkaXRfdmlld191aV9kaWMuaGFzT3duUHJvcGVydHkoIGtleSApICkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblx0XHRcdHZhciB3aWRnZXQgPSB0aGlzLmVkaXRfdmlld191aV9kaWNba2V5XTtcblx0XHRcdHZhciB3aWRnZXRDb250YWluZXIgPSB0aGlzLmVkaXRfdmlld19mb3JtX2l0ZW1fZGljW2tleV07XG5cdFx0XHR2YXIgY29sdW1uID0gd2lkZ2V0LnBhcmVudCgpLnBhcmVudCgpLnBhcmVudCgpO1xuXHRcdFx0aWYgKCAhY29sdW1uLmhhc0NsYXNzKCAndi1ib3gnICkgKSB7XG5cdFx0XHRcdGlmICggIWRpZF9jbGVhbiApIHtcblx0XHRcdFx0XHRkaWRfY2xlYW4gPSB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRpZiAoIHRoaXMuYWJzZW5jZV9tb2RlbCApIHtcblx0XHRcdFx0c3dpdGNoICgga2V5ICkge1xuXHRcdFx0XHRcdGNhc2UgJ3B1bmNoX2RhdGUnOlxuXHRcdFx0XHRcdGNhc2UgJ3B1bmNoX3RpbWUnOlxuXHRcdFx0XHRcdGNhc2UgJ3N0YXR1c19pZCc6XG5cdFx0XHRcdFx0Y2FzZSAndHlwZV9pZCc6XG5cdFx0XHRcdFx0Y2FzZSAncXVhbnRpdHknOlxuXHRcdFx0XHRcdGNhc2UgJ3N0YXRpb25faWQnOlxuXHRcdFx0XHRcdGNhc2UgJ2hhc19pbWFnZSc6XG5cdFx0XHRcdFx0Y2FzZSAnbGF0aXR1ZGUnOlxuXHRcdFx0XHRcdGNhc2UgJ3NwbGl0X3B1bmNoX2NvbnRyb2wnOlxuXHRcdFx0XHRcdFx0dGhpcy5kZXRhY2hFbGVtZW50KCBrZXkgKTtcblx0XHRcdFx0XHRcdHdpZGdldC5jc3MoICdvcGFjaXR5JywgMCApO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSAncHVuY2hfZGF0ZXMnOlxuXHRcdFx0XHRcdFx0aWYgKCB0aGlzLmlzX21hc3NfYWRkaW5nICkge1xuXHRcdFx0XHRcdFx0XHR0aGlzLmF0dGFjaEVsZW1lbnQoIGtleSApO1xuXHRcdFx0XHRcdFx0XHR3aWRnZXQuY3NzKCAnb3BhY2l0eScsIDEgKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHRoaXMuZGV0YWNoRWxlbWVudCgga2V5ICk7XG5cdFx0XHRcdFx0XHRcdHdpZGdldC5jc3MoICdvcGFjaXR5JywgMCApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSAnZGF0ZV9zdGFtcCc6XG5cdFx0XHRcdFx0XHRpZiAoIHRoaXMuaXNfbWFzc19hZGRpbmcgKSB7XG5cdFx0XHRcdFx0XHRcdHRoaXMuZGV0YWNoRWxlbWVudCgga2V5ICk7XG5cdFx0XHRcdFx0XHRcdHdpZGdldC5jc3MoICdvcGFjaXR5JywgMCApO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0dGhpcy5hdHRhY2hFbGVtZW50KCBrZXkgKTtcblx0XHRcdFx0XHRcdFx0d2lkZ2V0LmNzcyggJ29wYWNpdHknLCAxICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlICd0b3RhbF90aW1lJzpcblx0XHRcdFx0XHRjYXNlICdzcmNfb2JqZWN0X2lkJzpcblx0XHRcdFx0XHRjYXNlICdvdmVycmlkZSc6XG5cdFx0XHRcdFx0XHR0aGlzLmF0dGFjaEVsZW1lbnQoIGtleSApO1xuXHRcdFx0XHRcdFx0d2lkZ2V0LmNzcyggJ29wYWNpdHknLCAxICk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlICdhdmFpbGFibGVfYmFsYW5jZSc6XG5cdFx0XHRcdFx0XHR0aGlzLmRldGFjaEVsZW1lbnQoIGtleSApO1xuXHRcdFx0XHRcdFx0d2lkZ2V0LmNzcyggJ29wYWNpdHknLCAxICk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdFx0d2lkZ2V0LmNzcyggJ29wYWNpdHknLCAxICk7XG5cdFx0XHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHR9XG5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHN3aXRjaCAoIGtleSApIHtcblx0XHRcdFx0XHRjYXNlICdwdW5jaF9kYXRlcyc6XG5cdFx0XHRcdFx0XHRpZiAoIHRoaXMuaXNfbWFzc19hZGRpbmcgKSB7XG5cdFx0XHRcdFx0XHRcdHRoaXMuYXR0YWNoRWxlbWVudCgga2V5ICk7XG5cdFx0XHRcdFx0XHRcdHdpZGdldC5jc3MoICdvcGFjaXR5JywgMSApO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0dGhpcy5kZXRhY2hFbGVtZW50KCBrZXkgKTtcblx0XHRcdFx0XHRcdFx0d2lkZ2V0LmNzcyggJ29wYWNpdHknLCAwICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlICdwdW5jaF9kYXRlJzpcblx0XHRcdFx0XHRcdGlmICggdGhpcy5pc19tYXNzX2FkZGluZyApIHtcblx0XHRcdFx0XHRcdFx0dGhpcy5kZXRhY2hFbGVtZW50KCBrZXkgKTtcblx0XHRcdFx0XHRcdFx0d2lkZ2V0LmNzcyggJ29wYWNpdHknLCAwICk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHR0aGlzLmF0dGFjaEVsZW1lbnQoIGtleSApO1xuXHRcdFx0XHRcdFx0XHR3aWRnZXQuY3NzKCAnb3BhY2l0eScsIDEgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ3F1YW50aXR5Jzpcblx0XHRcdFx0XHRcdGlmICggdGhpcy5zaG93X2dvb2RfcXVhbnRpdHlfdWkgJiYgdGhpcy5zaG93X2JhZF9xdWFudGl0eV91aSApIHtcblx0XHRcdFx0XHRcdFx0dGhpcy5hdHRhY2hFbGVtZW50KCBrZXkgKTtcblx0XHRcdFx0XHRcdFx0d2lkZ2V0LmNzcyggJ29wYWNpdHknLCAxICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlICdzdGF0aW9uJzpcblx0XHRcdFx0XHRcdHRoaXMuYXR0YWNoRWxlbWVudCgga2V5ICk7XG5cdFx0XHRcdFx0XHR3aWRnZXQuY3NzKCAnb3BhY2l0eScsIDEgKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ3B1bmNoX3RpbWUnOlxuXHRcdFx0XHRcdGNhc2UgJ3N0YXR1c19pZCc6XG5cdFx0XHRcdFx0Y2FzZSAndHlwZV9pZCc6XG5cdFx0XHRcdFx0Y2FzZSAnaGFzX2ltYWdlJzpcblx0XHRcdFx0XHRjYXNlICdsYXRpdHVkZSc6XG5cdFx0XHRcdFx0XHR0aGlzLmF0dGFjaEVsZW1lbnQoIGtleSApO1xuXHRcdFx0XHRcdFx0d2lkZ2V0LmNzcyggJ29wYWNpdHknLCAxICk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlICdkYXRlX3N0YW1wJzpcblx0XHRcdFx0XHRjYXNlICd0b3RhbF90aW1lJzpcblx0XHRcdFx0XHRjYXNlICdzcmNfb2JqZWN0X2lkJzpcblx0XHRcdFx0XHRjYXNlICdvdmVycmlkZSc6XG5cdFx0XHRcdFx0XHR0aGlzLmRldGFjaEVsZW1lbnQoIGtleSApO1xuXHRcdFx0XHRcdFx0d2lkZ2V0LmNzcyggJ29wYWNpdHknLCAwICk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdFx0d2lkZ2V0LmNzcyggJ29wYWNpdHknLCAxICk7XG5cdFx0XHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRpZiAoIHRoaXMuaXNfdmlld2luZyApIHtcblx0XHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoIHdpZGdldC5zZXRFbmFibGVkICkgKSB7XG5cdFx0XHRcdFx0d2lkZ2V0LnNldEVuYWJsZWQoIGZhbHNlICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCB3aWRnZXQuc2V0RW5hYmxlZCApICkge1xuXHRcdFx0XHRcdHdpZGdldC5zZXRFbmFibGVkKCB0cnVlICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRnZXRDdXN0b21GaWVsZFJlZmVyZW5jZUZpZWxkKCkge1xuXHRcdHJldHVybiAnbm90ZSc7XG5cdH1cblxuXHRzZXRDdXN0b21GaWVsZHMoKSB7XG5cdFx0Ly9DdXN0b20gZmllbGRzIGFyZSBvbmx5IHNob3duIG9uIHB1bmNoIHR5cGVzIGFuZCBub3Qgb24gYWJzZW5jZSB0eXBlcy5cblx0XHRpZiAoIHRoaXMuZ2V0UHVuY2hQZXJtaXNzaW9uVHlwZSgpID09PSAncHVuY2gnICkge1xuXHRcdFx0c3VwZXIuc2V0Q3VzdG9tRmllbGRzKCk7XG5cdFx0fVxuXHR9XG5cblx0YnVpbGRFZGl0Vmlld1VJKCkge1xuXHRcdHN1cGVyLmJ1aWxkRWRpdFZpZXdVSSgpO1xuXG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdHZhciB0YWJfbW9kZWwgPSB7XG5cdFx0XHQndGFiX3B1bmNoJzoge1xuXHRcdFx0XHQnbGFiZWwnOiB0aGlzLmFic2VuY2VfbW9kZWwgPyAkLmkxOG4uXyggJ0Fic2VuY2UnICkgOiAkLmkxOG4uXyggJ1B1bmNoJyApXG5cdFx0XHR9LFxuXHRcdFx0J3RhYl9hdWRpdCc6IHRydWUsXG5cdFx0fTtcblx0XHR0aGlzLnNldFRhYk1vZGVsKCB0YWJfbW9kZWwgKTtcblxuXHRcdHZhciBmb3JtX2l0ZW1faW5wdXQ7XG5cdFx0dmFyIHdpZGdldENvbnRhaW5lcjtcblxuXHRcdC8vVGFiIDAgc3RhcnRcblxuXHRcdHZhciB0YWJfcHVuY2ggPSB0aGlzLmVkaXRfdmlld190YWIuZmluZCggJyN0YWJfcHVuY2gnICk7XG5cblx0XHR2YXIgdGFiX3B1bmNoX2NvbHVtbjEgPSB0YWJfcHVuY2guZmluZCggJy5maXJzdC1jb2x1bW4nICk7XG5cblx0XHQvL0VtcGxveWVlXG5cblx0XHRmb3JtX2l0ZW1faW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLlRFWFQgKTtcblx0XHRmb3JtX2l0ZW1faW5wdXQuVFRleHQoIHsgZmllbGQ6ICdmaXJzdF9sYXN0X25hbWUnIH0gKTtcblx0XHR0aGlzLmFkZEVkaXRGaWVsZFRvQ29sdW1uKCAkLmkxOG4uXyggJ0VtcGxveWVlJyApLCBmb3JtX2l0ZW1faW5wdXQsIHRhYl9wdW5jaF9jb2x1bW4xLCAnJyApO1xuXG5cdFx0Ly9UaW1lXG5cdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5USU1FX1BJQ0tFUiApO1xuXHRcdGZvcm1faXRlbV9pbnB1dC5UVGltZVBpY2tlciggeyBmaWVsZDogJ3B1bmNoX3RpbWUnLCB2YWxpZGF0aW9uX2ZpZWxkOiAndGltZV9zdGFtcCcgfSApO1xuXHRcdHdpZGdldENvbnRhaW5lciA9ICQoICc8ZGl2IGNsYXNzPVxcJ3dpZGdldC1oLWJveFxcJz48L2Rpdj4nICk7XG5cdFx0dGhpcy5hY3R1YWxfdGltZV9sYWJlbCA9ICQoICc8c3BhbiBjbGFzcz1cXCd3aWRnZXQtcmlnaHQtbGFiZWxcXCc+PC9zcGFuPicgKTtcblx0XHR3aWRnZXRDb250YWluZXIuYXBwZW5kKCBmb3JtX2l0ZW1faW5wdXQgKTtcblx0XHR3aWRnZXRDb250YWluZXIuYXBwZW5kKCB0aGlzLmFjdHVhbF90aW1lX2xhYmVsICk7XG5cdFx0dGhpcy5hZGRFZGl0RmllbGRUb0NvbHVtbiggJC5pMThuLl8oICdUaW1lJyApLCBmb3JtX2l0ZW1faW5wdXQsIHRhYl9wdW5jaF9jb2x1bW4xLCAnJywgd2lkZ2V0Q29udGFpbmVyLCB0cnVlICk7XG5cblx0XHQvL0Fic2VuY2UgTW9kZWxcblx0XHQvL0Fic2VuY2UgUG9saWN5IFR5cGVcblx0XHRmb3JtX2l0ZW1faW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLkFXRVNPTUVfQk9YICk7XG5cblx0XHRmb3JtX2l0ZW1faW5wdXQuQUNvbWJvQm94KCB7XG5cdFx0XHRhcGlfY2xhc3M6IFRUQVBJLkFQSUFic2VuY2VQb2xpY3ksXG5cdFx0XHRhbGxvd19tdWx0aXBsZV9zZWxlY3Rpb246IGZhbHNlLFxuXHRcdFx0bGF5b3V0X25hbWU6ICdnbG9iYWxfYWJzZW5jZXMnLFxuXHRcdFx0c2hvd19zZWFyY2hfaW5wdXRzOiB0cnVlLFxuXHRcdFx0c2V0X2VtcHR5OiB0cnVlLFxuXHRcdFx0ZmllbGQ6ICdzcmNfb2JqZWN0X2lkJyxcblx0XHRcdHZhbGlkYXRpb25fZmllbGQ6ICdhYnNlbmNlX3BvbGljeV9pZCdcblx0XHR9ICk7XG5cblx0XHRmb3JtX2l0ZW1faW5wdXQuY3VzdG9tU2VhcmNoRmlsdGVyID0gZnVuY3Rpb24oIGZpbHRlciApIHtcblx0XHRcdHJldHVybiAkdGhpcy5zZXRBYnNlbmNlUG9saWN5RmlsdGVyKCBmaWx0ZXIgKTtcblx0XHR9O1xuXG5cdFx0dGhpcy5hZGRFZGl0RmllbGRUb0NvbHVtbiggJC5pMThuLl8oICdBYnNlbmNlIFBvbGljeScgKSwgZm9ybV9pdGVtX2lucHV0LCB0YWJfcHVuY2hfY29sdW1uMSwgJycsIG51bGwsIHRydWUgKTtcblxuXHRcdC8vQXZhaWxhYmxlIEJhbGFuY2Vcblx0XHRmb3JtX2l0ZW1faW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLlRFWFQgKTtcblx0XHRmb3JtX2l0ZW1faW5wdXQuVFRleHQoIHsgZmllbGQ6ICdhdmFpbGFibGVfYmFsYW5jZScgfSApO1xuXG5cdFx0d2lkZ2V0Q29udGFpbmVyID0gJCggJzxkaXYgY2xhc3M9XFwnd2lkZ2V0LWgtYm94IGF2YWlsYWJsZS1iYWxhbmNlLWgtYm94XFwnPjwvZGl2PicgKTtcblx0XHR0aGlzLmF2YWlsYWJsZV9iYWxhbmNlX2luZm8gPSAkKCAnPHNwYW4gY2xhc3M9XCJhdmFpbGFibGUtYmFsYW5jZS1pbmZvIHR0aWNvbiB0dGljb24taW5mb19ibGFja18yNGRwXCI+PC9zcGFuPicgKTtcblxuXHRcdHdpZGdldENvbnRhaW5lci5hcHBlbmQoIGZvcm1faXRlbV9pbnB1dCApO1xuXHRcdHdpZGdldENvbnRhaW5lci5hcHBlbmQoIHRoaXMuYXZhaWxhYmxlX2JhbGFuY2VfaW5mbyApO1xuXG5cdFx0dGhpcy5hZGRFZGl0RmllbGRUb0NvbHVtbiggJC5pMThuLl8oICdBdmFpbGFibGUgQmFsYW5jZScgKSwgW2Zvcm1faXRlbV9pbnB1dF0sIHRhYl9wdW5jaF9jb2x1bW4xLCAnJywgd2lkZ2V0Q29udGFpbmVyLCB0cnVlICk7XG5cblx0XHQvL0RhdGVcblx0XHRmb3JtX2l0ZW1faW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLkRBVEVfUElDS0VSICk7XG5cdFx0Zm9ybV9pdGVtX2lucHV0LlREYXRlUGlja2VyKCB7IGZpZWxkOiAncHVuY2hfZGF0ZScsIHZhbGlkYXRpb25fZmllbGQ6ICdkYXRlX3N0YW1wJyB9ICk7XG5cblx0XHR0aGlzLmFkZEVkaXRGaWVsZFRvQ29sdW1uKCAkLmkxOG4uXyggJ0RhdGUnICksIGZvcm1faXRlbV9pbnB1dCwgdGFiX3B1bmNoX2NvbHVtbjEsICcnLCBudWxsLCB0cnVlICk7XG5cblx0XHQvL01hc3MgQWRkIERhdGVcblx0XHRmb3JtX2l0ZW1faW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLkRBVEVfUElDS0VSICk7XG5cblx0XHRmb3JtX2l0ZW1faW5wdXQuVFJhbmdlUGlja2VyKCB7IGZpZWxkOiAncHVuY2hfZGF0ZXMnLCB2YWxpZGF0aW9uX2ZpZWxkOiAnZGF0ZV9zdGFtcCcgfSApO1xuXG5cdFx0dGhpcy5hZGRFZGl0RmllbGRUb0NvbHVtbiggJC5pMThuLl8oICdEYXRlJyApLCBmb3JtX2l0ZW1faW5wdXQsIHRhYl9wdW5jaF9jb2x1bW4xLCAnJywgbnVsbCwgdHJ1ZSApO1xuXG5cdFx0Ly9BYnNlbmNlIE1vZGVsXG5cdFx0Ly9EYXRlXG5cdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5EQVRFX1BJQ0tFUiApO1xuXHRcdGZvcm1faXRlbV9pbnB1dC5URGF0ZVBpY2tlciggeyBmaWVsZDogJ2RhdGVfc3RhbXAnIH0gKTtcblxuXHRcdHRoaXMuYWRkRWRpdEZpZWxkVG9Db2x1bW4oICQuaTE4bi5fKCAnRGF0ZScgKSwgZm9ybV9pdGVtX2lucHV0LCB0YWJfcHVuY2hfY29sdW1uMSwgJycsIG51bGwsIHRydWUgKTtcblxuXHRcdC8vQWJzZW5jZSBNb2RlbFxuXHRcdC8vVGltZVxuXHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuVEVYVF9JTlBVVCApO1xuXHRcdGZvcm1faXRlbV9pbnB1dC5UVGV4dElucHV0KCB7IGZpZWxkOiAndG90YWxfdGltZScsIG1vZGU6ICd0aW1lX3VuaXQnIH0gKTtcblxuXHRcdHZhciB3aWRnZXRDb250YWluZXIgPSAkKCAnPGRpdiBjbGFzcz1cXCd3aWRnZXQtaC1ib3hcXCc+PC9kaXY+JyApO1xuXHRcdHZhciByZWxlYXNlX2JhbGFuY2VfYnV0dG9uID0gJCggJzxpbnB1dCBpZD1cXCdyZWxlYXNlLWJhbGFuY2UtYnV0dG9uXFwnIGNsYXNzPVxcJ3QtYnV0dG9uXFwnIHN0eWxlPVxcJ21hcmdpbi1sZWZ0OiA1cHhcXCcgdHlwZT1cXCdidXR0b25cXCcgdmFsdWU9XFwnJyArICQuaTE4bi5fKCAnQXZhaWxhYmxlIEJhbGFuY2UnICkgKyAnXFwnPicgKTtcblx0XHRyZWxlYXNlX2JhbGFuY2VfYnV0dG9uLmNzcyggJ2Rpc3BsYXknLCAnbm9uZScgKTtcblxuXHRcdHJlbGVhc2VfYmFsYW5jZV9idXR0b24uY2xpY2soIGZ1bmN0aW9uKCkge1xuXHRcdFx0JHRoaXMuZ2V0QXZhaWxhYmxlQmFsYW5jZSggdHJ1ZSApO1xuXHRcdH0gKTtcblxuXHRcdHdpZGdldENvbnRhaW5lci5hcHBlbmQoIGZvcm1faXRlbV9pbnB1dCApO1xuXHRcdHdpZGdldENvbnRhaW5lci5hcHBlbmQoIHJlbGVhc2VfYmFsYW5jZV9idXR0b24gKTtcblx0XHR0aGlzLmFkZEVkaXRGaWVsZFRvQ29sdW1uKCAkLmkxOG4uXyggJ1RpbWUnICksIGZvcm1faXRlbV9pbnB1dCwgdGFiX3B1bmNoX2NvbHVtbjEsICcnLCB3aWRnZXRDb250YWluZXIsIHRydWUgKTtcblxuXHRcdC8vUHVuY2ggVHlwZVxuXG5cdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5DT01CT19CT1ggKTtcblx0XHRmb3JtX2l0ZW1faW5wdXQuVENvbWJvQm94KCB7IGZpZWxkOiAndHlwZV9pZCcgfSApO1xuXHRcdGZvcm1faXRlbV9pbnB1dC5zZXRTb3VyY2VEYXRhKCAkdGhpcy50eXBlX2FycmF5ICk7XG5cblx0XHR3aWRnZXRDb250YWluZXIgPSAkKCAnPGRpdiBjbGFzcz1cXCd3aWRnZXQtaC1ib3hcXCc+PC9kaXY+JyApO1xuXG5cdFx0dmFyIGNoZWNrX2JveCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuQ0hFQ0tCT1ggKTtcblx0XHRjaGVja19ib3guVENoZWNrYm94KCB7IGZpZWxkOiAnZGlzYWJsZV9yb3VuZGluZycgfSApO1xuXG5cdFx0dmFyIGxhYmVsID0gJCggJzxzcGFuIGNsYXNzPVxcJ3dpZGdldC1yaWdodC1sYWJlbFxcJz4nICsgJC5pMThuLl8oICdEaXNhYmxlIFJvdW5kaW5nJyApICsgJzwvc3Bhbj4nICk7XG5cblx0XHR3aWRnZXRDb250YWluZXIuYXBwZW5kKCBmb3JtX2l0ZW1faW5wdXQgKTtcblxuXHRcdC8vIENoZWNrIGlmIHZpZXcgb25seSBtb2RlLiBUbyBwcmV2ZW50IG9wdGlvbiBhcHBlYXJpbmcgYnV0IGRpc2FibGVkLCBhcyBkaXNhYmxlZCBjaGVja2JveGVzIGFyZSBub3QgdmVyeSBjbGVhciAtIHNhbWUgaW4gUHVuY2hWaWV3Q29udHJvbGxlclxuXHRcdGlmICggdGhpcy5pc192aWV3aW5nICkge1xuXHRcdFx0Ly8gZGV2LW5vdGU6IG5vdCBzdXJlIGlmIHdlIG5lZWQgdG8gcGFzcyB3aWRnZXRDb250YWluZXIgaGVyZSwgb3IgaWYgd2UgY2FuIG9taXQgaWYgaXRzIG9ubHkgb25lIGVsZW1lbnQgbm93IChkdWUgdG8gdGhlIGlmIGlzX3ZpZXdpbmcpLlxuXHRcdFx0Ly8gdG8gYmUgc2FmZSwgd2lsbCBjb250aW51ZSB0byB1c2Ugd2lkZ2V0Q29udGFpbmVyIGZvciB0aGlzIGNhc2UuIFdlIG9ubHkgd2FudCB0byBhZmZlY3Qgdmlld2luZyBtb2RlIChoaWRlIHJvdW5kaW5nIGNoZWNrYm94KSwgbGVzcyByaXNrIG9mIHJlZ3Jlc3Npb24gdG8ga2VlcCB3aWRnZXQgY29udGFpbmVyIGluLlxuXHRcdFx0dGhpcy5hZGRFZGl0RmllbGRUb0NvbHVtbiggJC5pMThuLl8oICdQdW5jaCBUeXBlJyApLCBmb3JtX2l0ZW1faW5wdXQsIHRhYl9wdW5jaF9jb2x1bW4xLCAnJywgd2lkZ2V0Q29udGFpbmVyLCB0cnVlICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHdpZGdldENvbnRhaW5lci5hcHBlbmQoIGxhYmVsICk7XG5cdFx0XHR3aWRnZXRDb250YWluZXIuYXBwZW5kKCBjaGVja19ib3ggKTtcblx0XHRcdHRoaXMuYWRkRWRpdEZpZWxkVG9Db2x1bW4oICQuaTE4bi5fKCAnUHVuY2ggVHlwZScgKSwgW2Zvcm1faXRlbV9pbnB1dCwgY2hlY2tfYm94XSwgdGFiX3B1bmNoX2NvbHVtbjEsICcnLCB3aWRnZXRDb250YWluZXIsIHRydWUgKTtcblx0XHR9XG5cblx0XHQvL0luIE91dCAoU3RhdHVzKVxuXHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuQ09NQk9fQk9YICk7XG5cblx0XHRmb3JtX2l0ZW1faW5wdXQuVENvbWJvQm94KCB7IGZpZWxkOiAnc3RhdHVzX2lkJyB9ICk7XG5cdFx0Zm9ybV9pdGVtX2lucHV0LnNldFNvdXJjZURhdGEoICR0aGlzLnN0YXR1c19hcnJheSApO1xuXHRcdHRoaXMuYWRkRWRpdEZpZWxkVG9Db2x1bW4oICQuaTE4bi5fKCAnSW4vT3V0JyApLCBmb3JtX2l0ZW1faW5wdXQsIHRhYl9wdW5jaF9jb2x1bW4xLCAnJywgbnVsbCwgdHJ1ZSApO1xuXG5cdFx0Ly9EZWZhdWx0IEJyYW5jaFxuXHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1ggKTtcblxuXHRcdGZvcm1faXRlbV9pbnB1dC5BQ29tYm9Cb3goIHtcblx0XHRcdGFwaV9jbGFzczogVFRBUEkuQVBJQnJhbmNoLFxuXHRcdFx0YWxsb3dfbXVsdGlwbGVfc2VsZWN0aW9uOiBmYWxzZSxcblx0XHRcdGxheW91dF9uYW1lOiAnZ2xvYmFsX2JyYW5jaCcsXG5cdFx0XHRzaG93X3NlYXJjaF9pbnB1dHM6IHRydWUsXG5cdFx0XHRzZXRfZW1wdHk6IHRydWUsXG5cdFx0XHRmaWVsZDogJ2JyYW5jaF9pZCdcblx0XHR9ICk7XG5cdFx0dGhpcy5hZGRFZGl0RmllbGRUb0NvbHVtbiggJC5pMThuLl8oICdCcmFuY2gnICksIGZvcm1faXRlbV9pbnB1dCwgdGFiX3B1bmNoX2NvbHVtbjEsICcnLCBudWxsLCB0cnVlICk7XG5cblx0XHRpZiAoICF0aGlzLmFic2VuY2VfbW9kZWwgKSB7XG5cdFx0XHRpZiAoICF0aGlzLnNob3dfYnJhbmNoX3VpICkge1xuXHRcdFx0XHR0aGlzLmRldGFjaEVsZW1lbnQoICdicmFuY2hfaWQnICk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdGlmICggIXRoaXMuc2hvd19hYnNlbmNlX2JyYW5jaF91aSApIHtcblx0XHRcdFx0dGhpcy5kZXRhY2hFbGVtZW50KCAnYnJhbmNoX2lkJyApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vRGVwYXJ0bWVudFxuXHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1ggKTtcblxuXHRcdGZvcm1faXRlbV9pbnB1dC5BQ29tYm9Cb3goIHtcblx0XHRcdGFwaV9jbGFzczogVFRBUEkuQVBJRGVwYXJ0bWVudCxcblx0XHRcdGFsbG93X211bHRpcGxlX3NlbGVjdGlvbjogZmFsc2UsXG5cdFx0XHRsYXlvdXRfbmFtZTogJ2dsb2JhbF9kZXBhcnRtZW50Jyxcblx0XHRcdHNob3dfc2VhcmNoX2lucHV0czogdHJ1ZSxcblx0XHRcdHNldF9lbXB0eTogdHJ1ZSxcblx0XHRcdGZpZWxkOiAnZGVwYXJ0bWVudF9pZCdcblx0XHR9ICk7XG5cdFx0dGhpcy5hZGRFZGl0RmllbGRUb0NvbHVtbiggJC5pMThuLl8oICdEZXBhcnRtZW50JyApLCBmb3JtX2l0ZW1faW5wdXQsIHRhYl9wdW5jaF9jb2x1bW4xLCAnJywgbnVsbCwgdHJ1ZSApO1xuXG5cdFx0aWYgKCAhdGhpcy5hYnNlbmNlX21vZGVsICkge1xuXHRcdFx0aWYgKCAhdGhpcy5zaG93X2RlcGFydG1lbnRfdWkgKSB7XG5cdFx0XHRcdHRoaXMuZGV0YWNoRWxlbWVudCggJ2RlcGFydG1lbnRfaWQnICk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdGlmICggIXRoaXMuc2hvd19hYnNlbmNlX2RlcGFydG1lbnRfdWkgKSB7XG5cdFx0XHRcdHRoaXMuZGV0YWNoRWxlbWVudCggJ2RlcGFydG1lbnRfaWQnICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKCAoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpID49IDIwICkgKSB7XG5cblx0XHRcdC8vSm9iXG5cdFx0XHRmb3JtX2l0ZW1faW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLkFXRVNPTUVfQk9YICk7XG5cblx0XHRcdGZvcm1faXRlbV9pbnB1dC5BQ29tYm9Cb3goIHtcblx0XHRcdFx0YXBpX2NsYXNzOiBUVEFQSS5BUElKb2IsXG5cdFx0XHRcdGFsbG93X211bHRpcGxlX3NlbGVjdGlvbjogZmFsc2UsXG5cdFx0XHRcdGxheW91dF9uYW1lOiAnZ2xvYmFsX2pvYicsXG5cdFx0XHRcdHNob3dfc2VhcmNoX2lucHV0czogdHJ1ZSxcblx0XHRcdFx0c2V0X2VtcHR5OiB0cnVlLFxuXHRcdFx0XHRzZXRSZWFsVmFsdWVDYWxsQmFjazogKCBmdW5jdGlvbiggdmFsICkge1xuXG5cdFx0XHRcdFx0aWYgKCB2YWwgKSB7XG5cdFx0XHRcdFx0XHRqb2JfY29kZXIuc2V0VmFsdWUoIHZhbC5tYW51YWxfaWQgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKSxcblx0XHRcdFx0ZmllbGQ6ICdqb2JfaWQnXG5cdFx0XHR9ICk7XG5cblx0XHRcdHdpZGdldENvbnRhaW5lciA9ICQoICc8ZGl2IGNsYXNzPVxcJ3dpZGdldC1oLWJveFxcJz48L2Rpdj4nICk7XG5cblx0XHRcdHZhciBqb2JfY29kZXIgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLlRFWFRfSU5QVVQgKTtcblx0XHRcdGpvYl9jb2Rlci5UVGV4dElucHV0KCB7IGZpZWxkOiAnam9iX3F1aWNrX3NlYXJjaCcsIGRpc2FibGVfa2V5dXBfZXZlbnQ6IHRydWUgfSApO1xuXHRcdFx0am9iX2NvZGVyLmFkZENsYXNzKCAnam9iLWNvZGVyJyApO1xuXG5cdFx0XHR3aWRnZXRDb250YWluZXIuYXBwZW5kKCBqb2JfY29kZXIgKTtcblx0XHRcdHdpZGdldENvbnRhaW5lci5hcHBlbmQoIGZvcm1faXRlbV9pbnB1dCApO1xuXHRcdFx0dGhpcy5hZGRFZGl0RmllbGRUb0NvbHVtbiggJC5pMThuLl8oICdKb2InICksIFtmb3JtX2l0ZW1faW5wdXQsIGpvYl9jb2Rlcl0sIHRhYl9wdW5jaF9jb2x1bW4xLCAnJywgd2lkZ2V0Q29udGFpbmVyLCB0cnVlICk7XG5cblx0XHRcdGlmICggIXRoaXMuYWJzZW5jZV9tb2RlbCApIHtcblx0XHRcdFx0aWYgKCAhdGhpcy5zaG93X2pvYl91aSApIHtcblx0XHRcdFx0XHR0aGlzLmRldGFjaEVsZW1lbnQoICdqb2JfaWQnICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGlmICggIXRoaXMuc2hvd19hYnNlbmNlX2pvYl91aSApIHtcblx0XHRcdFx0XHR0aGlzLmRldGFjaEVsZW1lbnQoICdqb2JfaWQnICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly9Kb2IgSXRlbVxuXHRcdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWCApO1xuXG5cdFx0XHRmb3JtX2l0ZW1faW5wdXQuQUNvbWJvQm94KCB7XG5cdFx0XHRcdGFwaV9jbGFzczogVFRBUEkuQVBJSm9iSXRlbSxcblx0XHRcdFx0YWxsb3dfbXVsdGlwbGVfc2VsZWN0aW9uOiBmYWxzZSxcblx0XHRcdFx0bGF5b3V0X25hbWU6ICdnbG9iYWxfam9iX2l0ZW0nLFxuXHRcdFx0XHRzaG93X3NlYXJjaF9pbnB1dHM6IHRydWUsXG5cdFx0XHRcdHNldF9lbXB0eTogdHJ1ZSxcblx0XHRcdFx0c2V0UmVhbFZhbHVlQ2FsbEJhY2s6ICggZnVuY3Rpb24oIHZhbCApIHtcblxuXHRcdFx0XHRcdGlmICggdmFsICkge1xuXHRcdFx0XHRcdFx0am9iX2l0ZW1fY29kZXIuc2V0VmFsdWUoIHZhbC5tYW51YWxfaWQgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKSxcblx0XHRcdFx0ZmllbGQ6ICdqb2JfaXRlbV9pZCdcblx0XHRcdH0gKTtcblxuXHRcdFx0d2lkZ2V0Q29udGFpbmVyID0gJCggJzxkaXYgY2xhc3M9XFwnd2lkZ2V0LWgtYm94XFwnPjwvZGl2PicgKTtcblxuXHRcdFx0dmFyIGpvYl9pdGVtX2NvZGVyID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5URVhUX0lOUFVUICk7XG5cdFx0XHRqb2JfaXRlbV9jb2Rlci5UVGV4dElucHV0KCB7IGZpZWxkOiAnam9iX2l0ZW1fcXVpY2tfc2VhcmNoJywgZGlzYWJsZV9rZXl1cF9ldmVudDogdHJ1ZSB9ICk7XG5cdFx0XHRqb2JfaXRlbV9jb2Rlci5hZGRDbGFzcyggJ2pvYi1jb2RlcicgKTtcblxuXHRcdFx0d2lkZ2V0Q29udGFpbmVyLmFwcGVuZCggam9iX2l0ZW1fY29kZXIgKTtcblx0XHRcdHdpZGdldENvbnRhaW5lci5hcHBlbmQoIGZvcm1faXRlbV9pbnB1dCApO1xuXHRcdFx0dGhpcy5hZGRFZGl0RmllbGRUb0NvbHVtbiggJC5pMThuLl8oICdUYXNrJyApLCBbZm9ybV9pdGVtX2lucHV0LCBqb2JfaXRlbV9jb2Rlcl0sIHRhYl9wdW5jaF9jb2x1bW4xLCAnJywgd2lkZ2V0Q29udGFpbmVyLCB0cnVlICk7XG5cblx0XHRcdGlmICggIXRoaXMuYWJzZW5jZV9tb2RlbCApIHtcblx0XHRcdFx0aWYgKCAhdGhpcy5zaG93X2pvYl9pdGVtX3VpICkge1xuXHRcdFx0XHRcdHRoaXMuZGV0YWNoRWxlbWVudCggJ2pvYl9pdGVtX2lkJyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZiAoICF0aGlzLnNob3dfYWJzZW5jZV9qb2JfaXRlbV91aSApIHtcblx0XHRcdFx0XHR0aGlzLmRldGFjaEVsZW1lbnQoICdqb2JfaXRlbV9pZCcgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvL1B1bmNoIFRhZ1xuXG5cdFx0XHRmb3JtX2l0ZW1faW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLkFXRVNPTUVfQk9YICk7XG5cblx0XHRcdGZvcm1faXRlbV9pbnB1dC5BQ29tYm9Cb3goIHtcblx0XHRcdFx0YXBpX2NsYXNzOiBUVEFQSS5BUElQdW5jaFRhZyxcblx0XHRcdFx0YWxsb3dfbXVsdGlwbGVfc2VsZWN0aW9uOiB0cnVlLFxuXHRcdFx0XHRsYXlvdXRfbmFtZTogJ2dsb2JhbF9wdW5jaF90YWcnLFxuXHRcdFx0XHRzaG93X3NlYXJjaF9pbnB1dHM6IHRydWUsXG5cdFx0XHRcdHNldF9lbXB0eTogdHJ1ZSxcblx0XHRcdFx0Z2V0X3JlYWxfZGF0YV9vbl9tdWx0aTogdHJ1ZSxcblx0XHRcdFx0c2V0UmVhbFZhbHVlQ2FsbEJhY2s6ICggKCBwdW5jaF90YWdzLCBnZXRfcmVhbF9kYXRhICkgPT4ge1xuXHRcdFx0XHRcdGlmICggcHVuY2hfdGFncyApIHtcblx0XHRcdFx0XHRcdHRoaXMuc2V0UHVuY2hUYWdRdWlja1NlYXJjaE1hbnVhbElkcyggcHVuY2hfdGFncywgZ2V0X3JlYWxfZGF0YSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApLFxuXHRcdFx0XHRmaWVsZDogJ3B1bmNoX3RhZ19pZCdcblx0XHRcdH0gKTtcblxuXHRcdFx0d2lkZ2V0Q29udGFpbmVyID0gJCggJzxkaXYgY2xhc3M9XFwnd2lkZ2V0LWgtYm94XFwnPjwvZGl2PicgKTtcblxuXHRcdFx0dmFyIHB1bmNoX3RhZ19jb2RlciA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuVEVYVF9JTlBVVCApO1xuXHRcdFx0cHVuY2hfdGFnX2NvZGVyLlRUZXh0SW5wdXQoIHsgZmllbGQ6ICdwdW5jaF90YWdfcXVpY2tfc2VhcmNoJywgZGlzYWJsZV9rZXl1cF9ldmVudDogdHJ1ZSB9ICk7XG5cdFx0XHRwdW5jaF90YWdfY29kZXIuYWRkQ2xhc3MoICdqb2ItY29kZXInICk7XG5cblx0XHRcdHdpZGdldENvbnRhaW5lci5hcHBlbmQoIHB1bmNoX3RhZ19jb2RlciApO1xuXHRcdFx0d2lkZ2V0Q29udGFpbmVyLmFwcGVuZCggZm9ybV9pdGVtX2lucHV0ICk7XG5cdFx0XHR0aGlzLmFkZEVkaXRGaWVsZFRvQ29sdW1uKCAkLmkxOG4uXyggJ1RhZ3MnICksIFtmb3JtX2l0ZW1faW5wdXQsIHB1bmNoX3RhZ19jb2Rlcl0sIHRhYl9wdW5jaF9jb2x1bW4xLCAnJywgd2lkZ2V0Q29udGFpbmVyLCB0cnVlICk7XG5cblx0XHRcdGlmICggIXRoaXMuYWJzZW5jZV9tb2RlbCApIHtcblx0XHRcdFx0aWYgKCAhdGhpcy5zaG93X3B1bmNoX3RhZ191aSApIHtcblx0XHRcdFx0XHR0aGlzLmRldGFjaEVsZW1lbnQoICdwdW5jaF90YWdfaWQnICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGlmICggIXRoaXMuc2hvd19hYnNlbmNlX3B1bmNoX3RhZ191aSApIHtcblx0XHRcdFx0XHR0aGlzLmRldGFjaEVsZW1lbnQoICdwdW5jaF90YWdfaWQnICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSApIHtcblxuXHRcdFx0Ly9RdWFuaXRpdHlcblxuXHRcdFx0dmFyIGdvb2QgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLlRFWFRfSU5QVVQgKTtcblx0XHRcdGdvb2QuVFRleHRJbnB1dCggeyBmaWVsZDogJ3F1YW50aXR5JyB9ICk7XG5cdFx0XHRnb29kLmFkZENsYXNzKCAncXVhbnRpdHktaW5wdXQnICk7XG5cblx0XHRcdHZhciBnb29kX2xhYmVsID0gJCggJzxzcGFuIGNsYXNzPVxcJ3dpZGdldC1yaWdodC1sYWJlbFxcJz4nICsgJC5pMThuLl8oICdHb29kJyApICsgJzogPC9zcGFuPicgKTtcblxuXHRcdFx0dmFyIGJhZCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuVEVYVF9JTlBVVCApO1xuXHRcdFx0YmFkLlRUZXh0SW5wdXQoIHsgZmllbGQ6ICdiYWRfcXVhbnRpdHknIH0gKTtcblx0XHRcdGJhZC5hZGRDbGFzcyggJ3F1YW50aXR5LWlucHV0JyApO1xuXG5cdFx0XHR2YXIgYmFkX2xhYmVsID0gJCggJzxzcGFuIGNsYXNzPVxcJ3dpZGdldC1yaWdodC1sYWJlbFxcJz4vICcgKyAkLmkxOG4uXyggJ0JhZCcgKSArICc6IDwvc3Bhbj4nICk7XG5cblx0XHRcdHdpZGdldENvbnRhaW5lciA9ICQoICc8ZGl2IGNsYXNzPVxcJ3dpZGdldC1oLWJveFxcJz48L2Rpdj4nICk7XG5cblx0XHRcdHdpZGdldENvbnRhaW5lci5hcHBlbmQoIGdvb2RfbGFiZWwgKTtcblx0XHRcdHdpZGdldENvbnRhaW5lci5hcHBlbmQoIGdvb2QgKTtcblx0XHRcdHdpZGdldENvbnRhaW5lci5hcHBlbmQoIGJhZF9sYWJlbCApO1xuXHRcdFx0d2lkZ2V0Q29udGFpbmVyLmFwcGVuZCggYmFkICk7XG5cblx0XHRcdHRoaXMuYWRkRWRpdEZpZWxkVG9Db2x1bW4oICQuaTE4bi5fKCAnUXVhbnRpdHknICksIFtnb29kLCBiYWRdLCB0YWJfcHVuY2hfY29sdW1uMSwgJycsIHdpZGdldENvbnRhaW5lciwgdHJ1ZSApO1xuXG5cdFx0XHRpZiAoICF0aGlzLnNob3dfYmFkX3F1YW50aXR5X3VpICYmICF0aGlzLnNob3dfZ29vZF9xdWFudGl0eV91aSApIHtcblx0XHRcdFx0dGhpcy5kZXRhY2hFbGVtZW50KCAncXVhbnRpdHknICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZiAoICF0aGlzLnNob3dfYmFkX3F1YW50aXR5X3VpICkge1xuXHRcdFx0XHRcdGJhZF9sYWJlbC5oaWRlKCk7XG5cdFx0XHRcdFx0YmFkLmhpZGUoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggIXRoaXMuc2hvd19nb29kX3F1YW50aXR5X3VpICkge1xuXHRcdFx0XHRcdGdvb2RfbGFiZWwuaGlkZSgpO1xuXHRcdFx0XHRcdGdvb2QuaGlkZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly9Ob3RlXG5cdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5URVhUX0FSRUEgKTtcblx0XHRmb3JtX2l0ZW1faW5wdXQuVFRleHRBcmVhKCB7IGZpZWxkOiAnbm90ZScsIHdpZHRoOiAnMTAwJScgfSApO1xuXHRcdHRoaXMuYWRkRWRpdEZpZWxkVG9Db2x1bW4oICQuaTE4bi5fKCAnTm90ZScgKSwgZm9ybV9pdGVtX2lucHV0LCB0YWJfcHVuY2hfY29sdW1uMSwgJycsIG51bGwsIHRydWUsIHRydWUgKTtcblx0XHRmb3JtX2l0ZW1faW5wdXQucGFyZW50KCkud2lkdGgoICc0NSUnICk7XG5cblx0XHRpZiAoICF0aGlzLnNob3dfbm90ZV91aSApIHtcblx0XHRcdHRoaXMuZGV0YWNoRWxlbWVudCggJ25vdGUnICk7XG5cdFx0fVxuXG5cdFx0Ly9BYnNlbmNlIE1vZGVcblx0XHQvL092ZXJyaWRlXG5cdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5DSEVDS0JPWCApO1xuXHRcdGZvcm1faXRlbV9pbnB1dC5UQ2hlY2tib3goIHsgZmllbGQ6ICdvdmVycmlkZScgfSApO1xuXHRcdHRoaXMuYWRkRWRpdEZpZWxkVG9Db2x1bW4oICQuaTE4bi5fKCAnT3ZlcnJpZGUnICksIGZvcm1faXRlbV9pbnB1dCwgdGFiX3B1bmNoX2NvbHVtbjEsICcnLCBudWxsLCB0cnVlLCB0cnVlICk7XG5cblx0XHQvL0xvY2F0aW9uXG5cdFx0aWYgKCBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAxNSApIHtcblxuXHRcdFx0dmFyIGxhdGl0dWRlID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5URVhUICk7XG5cdFx0XHRsYXRpdHVkZS5UVGV4dCggeyBmaWVsZDogJ2xhdGl0dWRlJyB9ICk7XG5cdFx0XHR2YXIgbG9uZ2l0dWRlID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5URVhUICk7XG5cdFx0XHRsb25naXR1ZGUuVFRleHQoIHsgZmllbGQ6ICdsb25naXR1ZGUnIH0gKTtcblx0XHRcdHdpZGdldENvbnRhaW5lciA9ICQoICc8ZGl2IGNsYXNzPVxcJ3dpZGdldC1oLWJveCBsaW5rLXdpZGdldC1ib3hcXCc+PC9kaXY+JyApO1xuXHRcdFx0dmFyIGFjY3VyYWN5ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5URVhUICk7XG5cdFx0XHRhY2N1cmFjeS5UVGV4dCggeyBmaWVsZDogJ3Bvc2l0aW9uX2FjY3VyYWN5JyB9ICk7XG5cdFx0XHRsYWJlbCA9ICQoICc8c3BhbiBjbGFzcz1cXCd3aWRnZXQtcmlnaHQtbGFiZWxcXCc+JyArICQuaTE4bi5fKCAnQWNjdXJhY3knICkgKyAnOjwvc3Bhbj4nICk7XG5cblx0XHRcdHZhciBtYXBfaWNvbiA9ICQoICc8aW1nIGNsYXNzPVwid2lkZ2V0LWgtYm94LW1hcEljb25cIiBzcmM9XCJmcmFtZXdvcmsvbGVhZmxldC9pbWFnZXMvbWFya2VyLWljb24tcmVkLnBuZ1wiID4nICk7XG5cblx0XHRcdHRoaXMubG9jYXRpb25fd3JhcHBlciA9ICQoICc8ZGl2IGNsYXNzPVwid2lkZ2V0LWgtYm94LW1hcExvY2F0aW9uV3JhcHBlclwiPjwvZGl2PicgKTtcblx0XHRcdHdpZGdldENvbnRhaW5lci5hcHBlbmQoIG1hcF9pY29uICk7XG5cdFx0XHR3aWRnZXRDb250YWluZXIuYXBwZW5kKCB0aGlzLmxvY2F0aW9uX3dyYXBwZXIgKTtcblx0XHRcdHRoaXMubG9jYXRpb25fd3JhcHBlci5hcHBlbmQoIGxhdGl0dWRlICk7XG5cdFx0XHR0aGlzLmxvY2F0aW9uX3dyYXBwZXIuYXBwZW5kKCAkKCAnPHNwYW4+LCA8L3NwYW4+JyApICk7XG5cdFx0XHR0aGlzLmxvY2F0aW9uX3dyYXBwZXIuYXBwZW5kKCBsb25naXR1ZGUgKTtcblx0XHRcdHRoaXMubG9jYXRpb25fd3JhcHBlci5hcHBlbmQoIGxhYmVsICk7XG5cdFx0XHR0aGlzLmxvY2F0aW9uX3dyYXBwZXIuYXBwZW5kKCBhY2N1cmFjeSApO1xuXHRcdFx0dGhpcy5sb2NhdGlvbl93cmFwcGVyLmFwcGVuZCggJCggJzxzcGFuPm08L3NwYW4+JyApICk7XG5cdFx0XHR0aGlzLmFkZEVkaXRGaWVsZFRvQ29sdW1uKCAkLmkxOG4uXyggJ0xvY2F0aW9uJyApLCBbbGF0aXR1ZGUsIGxvbmdpdHVkZSwgYWNjdXJhY3ldLCB0YWJfcHVuY2hfY29sdW1uMSwgJycsIHdpZGdldENvbnRhaW5lciwgdHJ1ZSApO1xuXHRcdFx0d2lkZ2V0Q29udGFpbmVyLmNsaWNrKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0JHRoaXMub25NYXBDbGljaygpO1xuXHRcdFx0fSApO1xuXG5cdFx0XHQvLyAjMjExNyAtIE1hbnVhbCBsb2NhdGlvbiBvbmx5IHN1cHBvcnRlZCBpbiBlZGl0IGJlY2F1c2Ugd2UgbmVlZCBhIHB1bmNoIHJlY29yZCB0byBhcHBlbmQgdGhlIGRhdGEgdG8uXG5cdFx0XHRpZiAoICggIXRoaXMuaXNfZWRpdCAmJiAhdGhpcy5pc192aWV3aW5nICkgfHwgIXRoaXMuc2hvd19sb2NhdGlvbl91aSApIHtcblx0XHRcdFx0d2lkZ2V0Q29udGFpbmVyLnBhcmVudHMoICcuZWRpdC12aWV3LWZvcm0taXRlbS1kaXYnICkuaGlkZSgpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vU3RhdGlvblxuXHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuVEVYVCApO1xuXHRcdGZvcm1faXRlbV9pbnB1dC5UVGV4dCggeyBmaWVsZDogJ3N0YXRpb25faWQnIH0gKTtcblxuXHRcdHRoaXMuYWRkRWRpdEZpZWxkVG9Db2x1bW4oICQuaTE4bi5fKCAnU3RhdGlvbicgKSwgZm9ybV9pdGVtX2lucHV0LCB0YWJfcHVuY2hfY29sdW1uMSwgJycsIG51bGwsIHRydWUsIHRydWUgKTtcblxuXHRcdGZvcm1faXRlbV9pbnB1dC5jbGljayggZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3RhdGlvbl9pZCAmJiAkdGhpcy5zaG93X3N0YXRpb25fdWkgKSB7XG5cdFx0XHRcdEluZGV4Vmlld0NvbnRyb2xsZXIub3BlbkVkaXRWaWV3KCAkdGhpcywgJ1N0YXRpb24nLCAkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXRpb25faWQgKTtcblx0XHRcdH1cblxuXHRcdH0gKTtcblxuXHRcdC8vU3BsaXQgUHVuY2ggQ29udHJvbFxuXHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuQ0hFQ0tCT1ggKTtcblx0XHRmb3JtX2l0ZW1faW5wdXQuVENoZWNrYm94KCB7IGZpZWxkOiAnc3BsaXRfcHVuY2hfY29udHJvbCcgfSApO1xuXHRcdHRoaXMuYWRkRWRpdEZpZWxkVG9Db2x1bW4oICQuaTE4bi5fKCAnU3BsaXQgRXhpc3RpbmcgUHVuY2hlcycgKSwgZm9ybV9pdGVtX2lucHV0LCB0YWJfcHVuY2hfY29sdW1uMSwgJycsIG51bGwsIHRydWUsIHRydWUgKTtcblx0XHRpZiAoIHRoaXMuaXNfbWFzc19hZGRpbmcgPT0gZmFsc2UgKSB7XG5cdFx0XHR0aGlzLmRldGFjaEVsZW1lbnQoICdzcGxpdF9wdW5jaF9jb250cm9sJyApO1xuXHRcdH1cblxuXHRcdC8vUHVuY2ggSW1hZ2Vcblx0XHRmb3JtX2l0ZW1faW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLklNQUdFICk7XG5cdFx0Zm9ybV9pdGVtX2lucHV0LlRJbWFnZSggeyBmaWVsZDogJ3B1bmNoX2ltYWdlJyB9ICk7XG5cdFx0dGhpcy5hZGRFZGl0RmllbGRUb0NvbHVtbiggJC5pMThuLl8oICdJbWFnZScgKSwgZm9ybV9pdGVtX2lucHV0LCB0YWJfcHVuY2hfY29sdW1uMSwgJycsIG51bGwsIHRydWUsIHRydWUgKTtcblx0fVxuXG5cdC8qIGpzaGludCBpZ25vcmU6ZW5kICovXG5cblx0b25FZGl0U3RhdGlvbkRvbmUoKSB7XG5cdFx0dGhpcy5zZXRTdGF0aW9uKCk7XG5cdH1cblxuXHRzZXRBYnNlbmNlUG9saWN5RmlsdGVyKCBmaWx0ZXIgKSB7XG5cdFx0aWYgKCAhZmlsdGVyLmZpbHRlcl9kYXRhICkge1xuXHRcdFx0ZmlsdGVyLmZpbHRlcl9kYXRhID0ge307XG5cdFx0fVxuXG5cdFx0ZmlsdGVyLmZpbHRlcl9kYXRhLnVzZXJfaWQgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudXNlcl9pZDtcblxuXHRcdGlmICggZmlsdGVyLmZpbHRlcl9jb2x1bW5zICkge1xuXHRcdFx0ZmlsdGVyLmZpbHRlcl9jb2x1bW5zLmFic2VuY2VfcG9saWN5ID0gdHJ1ZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmlsdGVyO1xuXHR9XG5cblx0b25TZXRTZWFyY2hGaWx0ZXJGaW5pc2hlZCgpIHtcblx0fVxuXG5cdG9uQnVpbGRCYXNpY1VJRmluaXNoZWQoKSB7XG5cdH1cblxuXHRvbkJ1aWxkQWR2VUlGaW5pc2hlZCgpIHtcblx0fVxuXG5cdHBhcnNlckRhdGVzUmFuZ2UoIGRhdGUgKSB7XG5cdFx0dmFyIGRhdGVzID0gZGF0ZS5zcGxpdCggJyAtICcgKTtcblx0XHR2YXIgcmVzdWx0QXJyYXkgPSBbXTtcblx0XHR2YXIgYmVnaW5EYXRlID0gR2xvYmFsLnN0clRvRGF0ZSggZGF0ZXNbMF0gKTtcblx0XHR2YXIgZW5kRGF0ZSA9IEdsb2JhbC5zdHJUb0RhdGUoIGRhdGVzWzFdICk7XG5cblx0XHR2YXIgbmV4dERhdGUgPSBiZWdpbkRhdGU7XG5cblx0XHR3aGlsZSAoIG5leHREYXRlLmdldFRpbWUoKSA8IGVuZERhdGUuZ2V0VGltZSgpICkge1xuXHRcdFx0cmVzdWx0QXJyYXkucHVzaCggbmV4dERhdGUuZm9ybWF0KCkgKTtcblx0XHRcdG5leHREYXRlID0gbmV3IERhdGUoIG5ldyBEYXRlKCBuZXh0RGF0ZS5nZXRUaW1lKCkgKS5zZXREYXRlKCBuZXh0RGF0ZS5nZXREYXRlKCkgKyAxICkgKTtcblx0XHR9XG5cblx0XHRyZXN1bHRBcnJheS5wdXNoKCBkYXRlc1sxXSApO1xuXG5cdFx0cmV0dXJuIHJlc3VsdEFycmF5O1xuXHR9XG5cblx0dmFsaWRhdGUoKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgcmVjb3JkID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkO1xuXHRcdHZhciBpO1xuXHRcdGlmICggdGhpcy5pc19tYXNzX2VkaXRpbmcgKSB7XG5cdFx0XHRyZWNvcmQgPSBbXTtcblx0XHRcdHZhciBsZW4gPSB0aGlzLm1hc3NfZWRpdF9yZWNvcmRfaWRzLmxlbmd0aDtcblx0XHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0XHR2YXIgdGVtcF9pdGVtID0gR2xvYmFsLmNsb25lKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgKTtcblx0XHRcdFx0dGVtcF9pdGVtLmlkID0gdGhpcy5tYXNzX2VkaXRfcmVjb3JkX2lkc1tpXTtcblx0XHRcdFx0cmVjb3JkLnB1c2goIHRlbXBfaXRlbSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggdGhpcy5pc19tYXNzX2FkZGluZyApIHtcblxuXHRcdFx0cmVjb3JkID0gW107XG5cdFx0XHR2YXIgZGF0ZXNfYXJyYXkgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQucHVuY2hfZGF0ZXM7XG5cblx0XHRcdGlmICggZGF0ZXNfYXJyYXkgJiYgZGF0ZXNfYXJyYXkuaW5kZXhPZiggJyAtICcgKSA+IDAgKSB7XG5cdFx0XHRcdGRhdGVzX2FycmF5ID0gdGhpcy5wYXJzZXJEYXRlc1JhbmdlKCBkYXRlc19hcnJheSApO1xuXHRcdFx0fVxuXG5cdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBkYXRlc19hcnJheS5sZW5ndGg7IGkrKyApIHtcblx0XHRcdFx0dmFyIGNvbW1vbl9yZWNvcmQgPSBHbG9iYWwuY2xvbmUoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCApO1xuXHRcdFx0XHRkZWxldGUgY29tbW9uX3JlY29yZC5wdW5jaF9kYXRlcztcblx0XHRcdFx0aWYgKCB0aGlzLmFic2VuY2VfbW9kZWwgKSB7XG5cdFx0XHRcdFx0Y29tbW9uX3JlY29yZC5kYXRlX3N0YW1wID0gZGF0ZXNfYXJyYXlbaV07XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Y29tbW9uX3JlY29yZC5wdW5jaF9kYXRlID0gZGF0ZXNfYXJyYXlbaV07XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZWNvcmQucHVzaCggY29tbW9uX3JlY29yZCApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggIXRoaXMuYWJzZW5jZV9tb2RlbCApIHtcblxuXHRcdFx0dGhpcy5hcGlbJ3ZhbGlkYXRlJyArIHRoaXMuYXBpLmtleV9uYW1lXSggcmVjb3JkLCB7XG5cdFx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHRcdCR0aGlzLnZhbGlkYXRlUmVzdWx0KCByZXN1bHQgKTtcblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0dGhpcy5hcGlfdXNlcl9kYXRlX3RvdGFsWyd2YWxpZGF0ZScgKyB0aGlzLmFwaV91c2VyX2RhdGVfdG90YWwua2V5X25hbWVdKCByZWNvcmQsIHtcblx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cdFx0XHRcdFx0JHRoaXMuY2xlYXJFcnJvclRpcHMoKTsgLy9BbHdheXMgY2xlYXIgZXJyb3JcblxuXHRcdFx0XHRcdGlmICggcmVzdWx0LmlzVmFsaWQoKSApIHtcblx0XHRcdFx0XHRcdCR0aGlzLnNldEVkaXRNZW51KCk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdCR0aGlzLnNldEVycm9yTWVudSgpO1xuXHRcdFx0XHRcdFx0JHRoaXMuc2V0RXJyb3JUaXBzKCByZXN1bHQgKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXG5cdFx0fVxuXHR9XG5cblx0LyoganNoaW50IGlnbm9yZTpzdGFydCAqL1xuXHRvbkZvcm1JdGVtQ2hhbmdlKCB0YXJnZXQsIGRvTm90VmFsaWRhdGUgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR0aGlzLnNldElzQ2hhbmdlZCggdGFyZ2V0ICk7XG5cdFx0dGhpcy5zZXRNYXNzRWRpdGluZ0ZpZWxkc1doZW5Gb3JtQ2hhbmdlKCB0YXJnZXQgKTtcblx0XHR2YXIga2V5ID0gdGFyZ2V0LmdldEZpZWxkKCk7XG5cdFx0dmFyIGNfdmFsdWUgPSB0YXJnZXQuZ2V0VmFsdWUoKTtcblx0XHQvLyBFcnJvcjogVHlwZUVycm9yOiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgaXMgbnVsbCBpbiBpbnRlcmZhY2UvaHRtbDUvZnJhbWV3b3JrL2pxdWVyeS5taW4uanM/dj05LjAuNS0yMDE1MTIyMi0wOTQ5MzggbGluZSAyID4gZXZhbCBsaW5lIDE0MDlcblx0XHRpZiAoICF0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFtrZXldID0gY192YWx1ZTtcblx0XHRzd2l0Y2ggKCBrZXkgKSB7XG5cdFx0XHRjYXNlICdqb2JfaWQnOlxuXHRcdFx0XHRpZiAoICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSApIHtcblx0XHRcdFx0XHR0aGlzLmVkaXRfdmlld191aV9kaWNbJ2pvYl9xdWlja19zZWFyY2gnXS5zZXRWYWx1ZSggdGFyZ2V0LmdldFZhbHVlKCB0cnVlICkgPyAoIHRhcmdldC5nZXRWYWx1ZSggdHJ1ZSApLm1hbnVhbF9pZCA/IHRhcmdldC5nZXRWYWx1ZSggdHJ1ZSApLm1hbnVhbF9pZCA6ICcnICkgOiAnJyApO1xuXHRcdFx0XHRcdHRoaXMuc2V0Sm9iSXRlbVZhbHVlV2hlbkpvYkNoYW5nZWQoIHRhcmdldC5nZXRWYWx1ZSggdHJ1ZSApLCAnam9iX2l0ZW1faWQnLCB7XG5cdFx0XHRcdFx0XHRzdGF0dXNfaWQ6IDEwLFxuXHRcdFx0XHRcdFx0am9iX2lkOiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuam9iX2lkXG5cdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdHRoaXMuZWRpdF92aWV3X3VpX2RpY1snam9iX3F1aWNrX3NlYXJjaCddLnNldENoZWNrQm94KCB0cnVlICk7XG5cdFx0XHRcdFx0dGhpcy5zZXRQdW5jaFRhZ1ZhbHVlc1doZW5Dcml0ZXJpYUNoYW5nZWQoIHRoaXMuZ2V0UHVuY2hUYWdGaWx0ZXJEYXRhKCksICdwdW5jaF90YWdfaWQnICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ2pvYl9pdGVtX2lkJzpcblx0XHRcdFx0aWYgKCAoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpID49IDIwICkgKSB7XG5cdFx0XHRcdFx0dGhpcy5lZGl0X3ZpZXdfdWlfZGljWydqb2JfaXRlbV9xdWlja19zZWFyY2gnXS5zZXRWYWx1ZSggdGFyZ2V0LmdldFZhbHVlKCB0cnVlICkgPyAoIHRhcmdldC5nZXRWYWx1ZSggdHJ1ZSApLm1hbnVhbF9pZCA/IHRhcmdldC5nZXRWYWx1ZSggdHJ1ZSApLm1hbnVhbF9pZCA6ICcnICkgOiAnJyApO1xuXHRcdFx0XHRcdHRoaXMuZWRpdF92aWV3X3VpX2RpY1snam9iX2l0ZW1fcXVpY2tfc2VhcmNoJ10uc2V0Q2hlY2tCb3goIHRydWUgKTtcblx0XHRcdFx0XHR0aGlzLnNldFB1bmNoVGFnVmFsdWVzV2hlbkNyaXRlcmlhQ2hhbmdlZCggdGhpcy5nZXRQdW5jaFRhZ0ZpbHRlckRhdGEoKSwgJ3B1bmNoX3RhZ19pZCcgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3B1bmNoX3RhZ19pZCc6XG5cdFx0XHRcdGlmICggKCBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAyMCApICkge1xuXHRcdFx0XHRcdGlmICggY192YWx1ZSAhPT0gVFRVVUlELnplcm9faWQgJiYgY192YWx1ZSAhPT0gZmFsc2UgJiYgY192YWx1ZS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHRcdFx0dGhpcy5zZXRQdW5jaFRhZ1F1aWNrU2VhcmNoTWFudWFsSWRzKCB0YXJnZXQuZ2V0U2VsZWN0SXRlbXMoKSApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHR0aGlzLmVkaXRfdmlld191aV9kaWNbJ3B1bmNoX3RhZ19xdWlja19zZWFyY2gnXS5zZXRWYWx1ZSggJycgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0JHRoaXMucHJldmlvdXNfcHVuY2hfdGFnX3NlbGVjdGlvbiA9IGNfdmFsdWU7XG5cdFx0XHRcdFx0Ly9SZXNldCBzb3VyY2UgZGF0YSB0byBtYWtlIHN1cmUgY29ycmVjdCBwdW5jaCB0YWdzIGFyZSBhbHdheXMgc2hvd24uXG5cdFx0XHRcdFx0dGhpcy5lZGl0X3ZpZXdfdWlfZGljWydwdW5jaF90YWdfaWQnXS5zZXRTb3VyY2VEYXRhKCBudWxsICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdicmFuY2hfaWQnOlxuXHRcdFx0XHRpZiAoICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSApIHtcblx0XHRcdFx0XHR0aGlzLnNldFB1bmNoVGFnVmFsdWVzV2hlbkNyaXRlcmlhQ2hhbmdlZCggdGhpcy5nZXRQdW5jaFRhZ0ZpbHRlckRhdGEoKSwgJ3B1bmNoX3RhZ19pZCcgKTtcblx0XHRcdFx0XHR0aGlzLnNldEpvYlZhbHVlV2hlbkNyaXRlcmlhQ2hhbmdlZCggJ2pvYl9pZCcsIHtcblx0XHRcdFx0XHRcdHN0YXR1c19pZDogMTAsXG5cdFx0XHRcdFx0XHR1c2VyX2lkOiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudXNlcl9pZCxcblx0XHRcdFx0XHRcdHB1bmNoX2JyYW5jaF9pZDogdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmJyYW5jaF9pZCxcblx0XHRcdFx0XHRcdHB1bmNoX2RlcGFydG1lbnRfaWQ6IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5kZXBhcnRtZW50X2lkXG5cdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdHRoaXMuc2V0RGVwYXJ0bWVudFZhbHVlV2hlbkJyYW5jaENoYW5nZWQoIHRhcmdldC5nZXRWYWx1ZSggdHJ1ZSApLCAnZGVwYXJ0bWVudF9pZCcsIHtcblx0XHRcdFx0XHRcdGJyYW5jaF9pZDogdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmJyYW5jaF9pZCxcblx0XHRcdFx0XHRcdHVzZXJfaWQ6ICAgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnVzZXJfaWRcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICd1c2VyX2lkJzpcblx0XHRcdGNhc2UgJ2RlcGFydG1lbnRfaWQnOlxuXHRcdFx0XHRpZiAoICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSApIHtcblx0XHRcdFx0XHR0aGlzLnNldFB1bmNoVGFnVmFsdWVzV2hlbkNyaXRlcmlhQ2hhbmdlZCggdGhpcy5nZXRQdW5jaFRhZ0ZpbHRlckRhdGEoKSwgJ3B1bmNoX3RhZ19pZCcgKTtcblx0XHRcdFx0XHR0aGlzLnNldEpvYlZhbHVlV2hlbkNyaXRlcmlhQ2hhbmdlZCggJ2pvYl9pZCcsIHtcblx0XHRcdFx0XHRcdHN0YXR1c19pZDogMTAsXG5cdFx0XHRcdFx0XHR1c2VyX2lkOiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudXNlcl9pZCxcblx0XHRcdFx0XHRcdHB1bmNoX2JyYW5jaF9pZDogdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmJyYW5jaF9pZCxcblx0XHRcdFx0XHRcdHB1bmNoX2RlcGFydG1lbnRfaWQ6IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5kZXBhcnRtZW50X2lkXG5cdFx0XHRcdFx0fSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnam9iX3F1aWNrX3NlYXJjaCc6XG5cdFx0XHRjYXNlICdqb2JfaXRlbV9xdWlja19zZWFyY2gnOlxuXHRcdFx0XHRpZiAoICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSApIHtcblx0XHRcdFx0XHR0aGlzLm9uSm9iUXVpY2tTZWFyY2goIGtleSwgY192YWx1ZSApO1xuXHRcdFx0XHRcdFRUUHJvbWlzZS53YWl0KCAnQmFzZVZpZXdDb250cm9sbGVyJywgJ29uSm9iUXVpY2tTZWFyY2gnLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdCR0aGlzLnNldFB1bmNoVGFnVmFsdWVzV2hlbkNyaXRlcmlhQ2hhbmdlZCggJHRoaXMuZ2V0UHVuY2hUYWdGaWx0ZXJEYXRhKCksICdwdW5jaF90YWdfaWQnICk7XG5cdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdC8vRG9uJ3QgdmFsaWRhdGUgaW1tZWRpYXRlbHkgYXMgb25Kb2JRdWlja1NlYXJjaCBpcyBkb2luZyBhc3luYyBBUEkgY2FsbHMsIGFuZCBpdCB3b3VsZCBjYXVzZSBhIGd1YXJhbnRlZWQgdmFsaWRhdGlvbiBmYWlsdXJlLlxuXHRcdFx0XHRcdGRvTm90VmFsaWRhdGUgPSB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAncHVuY2hfdGFnX3F1aWNrX3NlYXJjaCc6XG5cdFx0XHRcdGlmICggKCBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAyMCApICkge1xuXHRcdFx0XHRcdHRoaXMub25QdW5jaFRhZ1F1aWNrU2VhcmNoKCBjX3ZhbHVlLCB0aGlzLmdldFB1bmNoVGFnRmlsdGVyRGF0YSgpLCAncHVuY2hfdGFnX2lkJyApO1xuXG5cdFx0XHRcdFx0Ly9Eb24ndCB2YWxpZGF0ZSBpbW1lZGlhdGVseSBhcyBvbkpvYlF1aWNrU2VhcmNoIGlzIGRvaW5nIGFzeW5jIEFQSSBjYWxscywgYW5kIGl0IHdvdWxkIGNhdXNlIGEgZ3VhcmFudGVlZCB2YWxpZGF0aW9uIGZhaWx1cmUuXG5cdFx0XHRcdFx0ZG9Ob3RWYWxpZGF0ZSA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdwdW5jaF9kYXRlcyc6XG5cdFx0XHRcdHRoaXMuc2V0RWRpdE1lbnUoKTtcblx0XHRcdFx0YnJlYWs7XG5cblx0XHR9XG5cblx0XHRpZiAoIHRoaXMuYWJzZW5jZV9tb2RlbCApIHtcblx0XHRcdGlmICgga2V5ID09PSAndG90YWxfdGltZScgKSB7XG5cblx0XHRcdFx0aWYgKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgKSB7XG5cdFx0XHRcdFx0dGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2tleV0gPSBHbG9iYWwucGFyc2VUaW1lVW5pdCggY192YWx1ZSApO1xuXHRcdFx0XHRcdC8vIHBhcnNlZF90b3RhbF90aW1lX29iaiA9IHRoaXMuYXBpX2RhdGUucGFyc2VUaW1lVW5pdCggY192YWx1ZSwgeyBhc3luYzogZmFsc2UgfSApO1xuXHRcdFx0XHRcdC8vIGlmICggcGFyc2VkX3RvdGFsX3RpbWVfb2JqICkge1xuXHRcdFx0XHRcdC8vIFx0dGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2tleV0gPSBwYXJzZWRfdG90YWxfdGltZV9vYmouZ2V0UmVzdWx0KCk7XG5cdFx0XHRcdFx0Ly8gfVxuXG5cdFx0XHRcdFx0Ly9XaGVuIGhhbmRsaW5nIGFic2VuY2VzLCBhbHdheXMgcmVtb3ZlIHRoZSBzdGFydC9lbmQgdGltZSBzdGFtcHMgb3RoZXJ3aXNlIHRoZXkgbWF5IGJlIGluY29ycmVjdCBhbmQgdHJpZ2dlciBhIHZhbGlkYXRpb24gZXJyb3IsIGFzIHRoZSB1c2VyIGRvZXNuJ3Qgc2VlIHRoZW0gYW55d2F5cy5cblx0XHRcdFx0XHQvLyBUaGUgQVBJIHdpbGwgYXV0b21hdGljYWxseSBjYWxjdWxhdGVkIHRoZXNlIG9uIHNhdmUgYW55d2F5cy5cblx0XHRcdFx0XHR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRbJ3N0YXJ0X3RpbWVfc3RhbXAnXSA9IGZhbHNlO1xuXHRcdFx0XHRcdHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFsnZW5kX3RpbWVfc3RhbXAnXSA9IGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmICgga2V5ICE9PSAnb3ZlcnJpZGUnICYmIHRoaXMuZWRpdF92aWV3X3VpX2RpY1snb3ZlcnJpZGUnXSApIHtcblx0XHRcdFx0dGhpcy5lZGl0X3ZpZXdfdWlfZGljWydvdmVycmlkZSddLnNldFZhbHVlKCB0cnVlICk7XG5cdFx0XHRcdHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFsnb3ZlcnJpZGUnXSA9IHRydWU7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFtrZXldID0gY192YWx1ZTtcblx0XHR9XG5cblx0XHRpZiAoICFkb05vdFZhbGlkYXRlICkge1xuXHRcdFx0aWYgKCB0aGlzLmFic2VuY2VfbW9kZWwgKSB7XG5cdFx0XHRcdGlmICgga2V5ID09PSAndG90YWxfdGltZScgfHxcblx0XHRcdFx0XHRrZXkgPT09ICdkYXRlX3N0YW1wJyB8fFxuXHRcdFx0XHRcdGtleSA9PT0gJ3B1bmNoX2RhdGVzJyB8fFxuXHRcdFx0XHRcdGtleSA9PT0gJ3NyY19vYmplY3RfaWQnICkge1xuXHRcdFx0XHRcdHRoaXMub25BdmFpbGFibGVCYWxhbmNlQ2hhbmdlKCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHRoaXMudmFsaWRhdGUoKTtcblx0XHR9XG5cdH1cblxuXHQvKiBqc2hpbnQgaWdub3JlOmVuZCAqL1xuXG5cdGJ1aWxkU2VhcmNoQW5kTGF5b3V0VUkoKSB7XG5cdFx0dmFyIGxheW91dF9kaXYgPSB0aGlzLnNlYXJjaF9wYW5lbC5maW5kKCAnZGl2ICNzYXZlZF9sYXlvdXRfY29udGVudF9kaXYnICk7XG5cblx0XHR2YXIgZm9ybV9pdGVtID0gJCggJC5mbi5TZWFyY2hQYW5lbC5odG1sLmZvcm1faXRlbSApO1xuXHRcdHZhciBmb3JtX2l0ZW1fbGFiZWwgPSBmb3JtX2l0ZW0uZmluZCggJy5mb3JtLWl0ZW0tbGFiZWwnICk7XG5cdFx0dmFyIGZvcm1faXRlbV9pbnB1dF9kaXYgPSBmb3JtX2l0ZW0uZmluZCggJy5mb3JtLWl0ZW0taW5wdXQtZGl2JyApO1xuXG5cdFx0Zm9ybV9pdGVtX2xhYmVsLnRleHQoICQuaTE4bi5fKCAnU2F2ZSBTZWFyY2ggQXMnICkgKTtcblxuXHRcdHRoaXMuc2F2ZV9zZWFyY2hfYXNfaW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLlRFWFRfSU5QVVQgKTtcblx0XHR0aGlzLnNhdmVfc2VhcmNoX2FzX2lucHV0LlRUZXh0SW5wdXQoKTtcblxuXHRcdHZhciBzYXZlX2J0biA9ICQoICc8YnV0dG9uIGNsYXNzPVwidHQtYnV0dG9uIHAtYnV0dG9uIHAtY29tcG9uZW50IHNtYWxsLXNlYXJjaC1wYW5lbC1idXR0b25cIiB0eXBlPVwiYnV0dG9uXCI+XFxuJyArXG5cdFx0XHQnPHNwYW4gY2xhc3M9XCJ0dGljb24gdHRpY29uLXNhdmVfYmxhY2tfMjRkcFwiPjwvc3Bhbj5cXG4nICtcblx0XHRcdCc8c3BhbiBjbGFzcz1cInAtYnV0dG9uLWxhYmVsXCI+JyArICQuaTE4bi5fKCAnU2F2ZScgKSArICc8L3NwYW4+XFxuJyArXG5cdFx0XHQnPC9idXR0b24+JyApO1xuXG5cdFx0Zm9ybV9pdGVtX2lucHV0X2Rpdi5hcHBlbmQoIHRoaXMuc2F2ZV9zZWFyY2hfYXNfaW5wdXQgKTtcblx0XHRmb3JtX2l0ZW1faW5wdXRfZGl2LmFwcGVuZCggc2F2ZV9idG4gKTtcblxuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0c2F2ZV9idG4uY2xpY2soIGZ1bmN0aW9uKCkge1xuXHRcdFx0JHRoaXMub25TYXZlTmV3TGF5b3V0KCk7XG5cdFx0fSApO1xuXG5cdFx0Ly9QcmV2aW91cyBTYXZlZCBMYXlvdXRcblxuXHRcdHRoaXMucHJldmlvdXNfc2F2ZWRfbGF5b3V0X2RpdiA9ICQoICc8ZGl2IGNsYXNzPVxcJ3ByZXZpb3VzLXNhdmVkLWxheW91dC1kaXZcXCc+PC9kaXY+JyApO1xuXG5cdFx0Zm9ybV9pdGVtX2lucHV0X2Rpdi5hcHBlbmQoIHRoaXMucHJldmlvdXNfc2F2ZWRfbGF5b3V0X2RpdiApO1xuXG5cdFx0Zm9ybV9pdGVtX2xhYmVsID0gJCggJzxzcGFuIHN0eWxlPVxcJ21hcmdpbi1sZWZ0OiA1cHhcXCcgPicgKyAkLmkxOG4uXyggJ1ByZXZpb3VzIFNhdmVkIFNlYXJjaGVzJyApICsgJzo8L3NwYW4+JyApO1xuXHRcdHRoaXMucHJldmlvdXNfc2F2ZWRfbGF5b3V0X2Rpdi5hcHBlbmQoIGZvcm1faXRlbV9sYWJlbCApO1xuXG5cdFx0dGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfc2VsZWN0b3IgPSAkKCAnPHNlbGVjdCBzdHlsZT1cXCdtYXJnaW4tbGVmdDogNXB4XFwnIGNsYXNzPVxcJ3Qtc2VsZWN0XFwnPicgKTtcblx0XHR2YXIgdXBkYXRlX2J0biA9ICQoICc8YnV0dG9uIGNsYXNzPVwidHQtYnV0dG9uIHAtYnV0dG9uIHAtY29tcG9uZW50IHNtYWxsLXNlYXJjaC1wYW5lbC1idXR0b25cIiB0eXBlPVwiYnV0dG9uXCI+XFxuJyArXG5cdFx0XHQnPHNwYW4gY2xhc3M9XCJ0dGljb24gdHRpY29uLXNhdmVfYmxhY2tfMjRkcFwiPjwvc3Bhbj5cXG4nICtcblx0XHRcdCc8c3BhbiBjbGFzcz1cInAtYnV0dG9uLWxhYmVsXCI+JyArICQuaTE4bi5fKCAnVXBkYXRlJyApICsgJzwvc3Bhbj5cXG4nICtcblx0XHRcdCc8L2J1dHRvbj4nICk7XG5cblx0XHR2YXIgZGVsX2J0biA9ICQoICc8YnV0dG9uIGNsYXNzPVwidHQtYnV0dG9uIHAtYnV0dG9uIHAtY29tcG9uZW50IHNtYWxsLXNlYXJjaC1wYW5lbC1idXR0b25cIiB0eXBlPVwiYnV0dG9uXCI+XFxuJyArXG5cdFx0XHQnPHNwYW4gY2xhc3M9XCJ0dGljb24gdHRpY29uLWRlbGV0ZV9ibGFja18yNGRwXCI+PC9zcGFuPlxcbicgK1xuXHRcdFx0JzxzcGFuIGNsYXNzPVwicC1idXR0b24tbGFiZWxcIj4nICsgJC5pMThuLl8oICdEZWxldGUnICkgKyAnPC9zcGFuPlxcbicgK1xuXHRcdFx0JzwvYnV0dG9uPicgKTtcblxuXHRcdHVwZGF0ZV9idG4uY2xpY2soIGZ1bmN0aW9uKCkge1xuXHRcdFx0JHRoaXMub25VcGRhdGVMYXlvdXQoKTtcblx0XHR9ICk7XG5cblx0XHRkZWxfYnRuLmNsaWNrKCBmdW5jdGlvbigpIHtcblx0XHRcdCR0aGlzLm9uRGVsZXRlTGF5b3V0KCk7XG5cdFx0fSApO1xuXG5cdFx0dGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfZGl2LmFwcGVuZCggdGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfc2VsZWN0b3IgKTtcblx0XHR0aGlzLnByZXZpb3VzX3NhdmVkX2xheW91dF9kaXYuYXBwZW5kKCB1cGRhdGVfYnRuICk7XG5cdFx0dGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfZGl2LmFwcGVuZCggZGVsX2J0biApO1xuXG5cdFx0bGF5b3V0X2Rpdi5hcHBlbmQoIGZvcm1faXRlbSApO1xuXG5cdFx0dGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfZGl2LmNzcyggJ2Rpc3BsYXknLCAnbm9uZScgKTtcblx0fVxuXG5cdGNoZWNrVGltZXNoZWV0RGF0YSgpIHtcblx0XHRpZiAoIHRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YSA9PT0gdHJ1ZSApIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdHJlbmRlcigpIHtcblxuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0c3VwZXIucmVuZGVyKCk7XG5cblx0XHQvLyBJbml0IFZ1ZSBjb250cm9sIGJhclxuXHRcdHRoaXMudnVlX2NvbnRyb2xfYmFyX2lkID0gJ3Z1ZS10aW1lc2hlZXQtY29udHJvbC1iYXInO1xuXG5cdFx0Ly8gQWRkIGNhbGxiYWNrcyBoZXJlIHRvIGluamVjdCBpbnRvIFZ1ZSwgZm9yIGJ1dHRvbi9tZW51IGludGVyYWN0aW9ucyBmcm9tIFZ1ZSBiYWNrIHRvIFRULlxuXHRcdHZhciByb290X3Byb3BzID0ge1xuXHRcdFx0b25QdW5jaE1vZGVDaGFuZ2U6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQkdGhpcy5vbldhZ2VPck1vZGVDaGFuZ2UoICdtYW51YWwnICk7XG5cdFx0XHRcdCR0aGlzLm9uU2VhcmNoKCB0cnVlICk7XG5cdFx0XHR9LFxuXHRcdFx0b25TaG93V2FnZUNsaWNrOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0JHRoaXMub25XYWdlT3JNb2RlQ2hhbmdlKCAnd2FnZScgKTtcblx0XHRcdFx0JHRoaXMub25TZWFyY2goIHRydWUgKTtcblx0XHRcdH0sXG5cdFx0XHRvblRpbWV6b25lQ2xpY2s6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQkdGhpcy5vbldhZ2VPck1vZGVDaGFuZ2UoICd0aW1lem9uZScgKTtcblx0XHRcdFx0JHRoaXMub25TZWFyY2goIHRydWUgKTtcblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0Ly8gUHJvb2Ygb2YgY29uY2VwdC4gRnV0dXJlIHdvcmsgc2hvdWxkIHVzZSBUVEV2ZW50QnVzIGluc3RlYWQgb2YgdnVlX3JldHVybiwgYXMgcGFzc2luZyBieSByZWZlcmVuY2UgYW5kIGRpcmVjdCBhY2Nlc3MgbGlrZSB0aGlzIGlzIGEgVnVlIGFudGktcGF0dGVybi5cblx0XHQvLyBDYXJlZnVsbHkgdXNlIHRoZSByZXR1cm4gb2JqZWN0cyBpbiB2dWVfcmV0dXJuLCBhcyBpbnRlcmFjdGlvbnMgYmV0d2VlbiBWdWUgYW5kIGxlZ2FjeSBzaG91bGQgYmUgY2FyZWZ1bGx5IGNvbnRyb2xsZWQgdG8gYXZvaWQgc3BhZ2V0dGkgY29kZSAvIHZ1ZSBhbnRpIHBhdHRlcm5zLlxuXHRcdHZhciB2dWVfcmV0dXJuID0gVFRWdWVVdGlscy5tb3VudENvbXBvbmVudCggdGhpcy52dWVfY29udHJvbF9iYXJfaWQsIFRpbWVTaGVldENvbnRyb2xCYXIsIHJvb3RfcHJvcHMgKTtcblxuXHRcdHZhciBkYXRlX2Nob29zZXJfZGl2ID0gJCggJy50aW1lLXNoZWV0LXZpZXcgLmRhdGUtY2hvb3Nlci1kaXYnICk7XG5cdFx0dmFyIGVtcGxveWVlX25hdl9kaXYgPSAkKCAnLnRpbWUtc2hlZXQtdmlldyAuZW1wbG95ZWUtbmF2LWRpdicgKTtcblxuXHRcdC8vSXNzdWUgIzMwOTcgLSBUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnRpZXMgb2YgdW5kZWZpbmVkIChyZWFkaW5nICdnZXRQdW5jaE1vZGUnKVxuXHRcdC8vVGhlIFZ1ZSBUaW1lU2hlZXRDb250cm9sQmFyIG1heSBhbHJlYWR5IGNvbnRhaW4gZG9tIGVsZW1lbnRzIGZyb20gcHJldmlvdXMgcmVuZGVycyAoY2FjaGVkPykgYW5kIG5lZWRzIHRvIGJlIHJlbW92ZWQuXG5cdFx0Ly9UaGUgcGFyZW50IGRpdiBuZWVkcyBhbGwgY2hpbGRyZW4gcmVtb3ZlZCB0byBwcmV2ZW50IG11bHRpcGxlIGRhdGUgcGlja2VycyBmcm9tIGJlaW5nIGFkZGVkLlxuXHRcdGRhdGVfY2hvb3Nlcl9kaXYuZW1wdHkoKTtcblxuXHRcdGlmICggIXRoaXMuc2hvd19uYXZpZ2F0aW9uX2JveCApIHtcblx0XHRcdGVtcGxveWVlX25hdl9kaXYuY3NzKCAnZGlzcGxheScsICdub25lJyApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRlbXBsb3llZV9uYXZfZGl2LmNzcyggJ2Rpc3BsYXknLCAnJyApO1xuXHRcdH1cblxuXHRcdHRoaXMud2FnZV9idG4gPSB7XG5cdFx0XHRpZDogdGhpcy52dWVfY29udHJvbF9iYXJfaWQsIC8vIFRPRE86IERvIHdlIG5lZWQgdGhpcyBzdGlsbD9cblx0XHRcdHNob3c6IGZ1bmN0aW9uKCkge30sXG5cdFx0XHRoaWRlOiBmdW5jdGlvbigpIHt9LFxuXHRcdFx0Z2V0VmFsdWU6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoIHZ1ZV9yZXR1cm4gJiYgdnVlX3JldHVybi5fdnVlX2NvbXBvbmVudF9pbnN0YW5jZSApIHtcblx0XHRcdFx0XHRyZXR1cm4gdnVlX3JldHVybi5fdnVlX2NvbXBvbmVudF9pbnN0YW5jZS5nZXRUaW1lc2hlZXRTZXR0aW5nc1N0YXRlKCAnc2hvd193YWdlcycgKTtcblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdHNldFZhbHVlOiBmdW5jdGlvbiggbmV3X3ZhbHVlICkge1xuXHRcdFx0XHRpZiAoIHZ1ZV9yZXR1cm4gJiYgdnVlX3JldHVybi5fdnVlX2NvbXBvbmVudF9pbnN0YW5jZSApIHtcblx0XHRcdFx0XHR2dWVfcmV0dXJuLl92dWVfY29tcG9uZW50X2luc3RhbmNlLnNldFRpbWVzaGVldFNldHRpbmdzU3RhdGUoICdzaG93X3dhZ2VzJywgbmV3X3ZhbHVlICk7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHQvLyBUT0RPIENhbnQgdXNlIHRoaXMgYXMgYSByZW1vdmUsIGFzIGl0IHdvdWxkIHJlbW92ZSB0aGUgd2hvbGUgY29udHJvbCBiYXIuIFdlIG9ubHkgd2FudCB0byBoaWRlL3JlbW92ZSB0aGUgdG9nZ2xlIGJ1dHRvbnMgZm9yIG1vZGUuXG5cdFx0XHRyZW1vdmU6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQvLyByZXR1cm4gVFRWdWVVdGlscy51bm1vdW50Q29tcG9uZW50KCB0aGlzLnZ1ZV9jb250cm9sX2Jhcl9pZCApXG5cdFx0XHR9XG5cdFx0fTtcblxuXHRcdHRoaXMudGltZXpvbmVfYnRuID0ge1xuXHRcdFx0aWQ6IHRoaXMudnVlX2NvbnRyb2xfYmFyX2lkLFxuXHRcdFx0c2hvdzogZnVuY3Rpb24oKSB7fSxcblx0XHRcdGhpZGU6IGZ1bmN0aW9uKCkge30sXG5cdFx0XHRnZXRWYWx1ZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggdnVlX3JldHVybiAmJiB2dWVfcmV0dXJuLl92dWVfY29tcG9uZW50X2luc3RhbmNlICkge1xuXHRcdFx0XHRcdHJldHVybiB2dWVfcmV0dXJuLl92dWVfY29tcG9uZW50X2luc3RhbmNlLmdldFRpbWVzaGVldFNldHRpbmdzU3RhdGUoICd1c2VfZW1wbG95ZWVfdGltZXpvbmUnICk7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRzZXRWYWx1ZTogZnVuY3Rpb24oIG5ld192YWx1ZSApIHtcblx0XHRcdFx0aWYgKCB2dWVfcmV0dXJuICYmIHZ1ZV9yZXR1cm4uX3Z1ZV9jb21wb25lbnRfaW5zdGFuY2UgKSB7XG5cdFx0XHRcdFx0dnVlX3JldHVybi5fdnVlX2NvbXBvbmVudF9pbnN0YW5jZS5zZXRUaW1lc2hlZXRTZXR0aW5nc1N0YXRlKCAndXNlX2VtcGxveWVlX3RpbWV6b25lJywgbmV3X3ZhbHVlICk7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHQvLyBUT0RPIENhbnQgdXNlIHRoaXMgYXMgYSByZW1vdmUsIGFzIGl0IHdvdWxkIHJlbW92ZSB0aGUgd2hvbGUgY29udHJvbCBiYXIuIFdlIG9ubHkgd2FudCB0byBoaWRlL3JlbW92ZSB0aGUgdG9nZ2xlIGJ1dHRvbnMgZm9yIG1vZGUuXG5cdFx0XHRyZW1vdmU6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQvLyByZXR1cm4gVFRWdWVVdGlscy51bm1vdW50Q29tcG9uZW50KCB0aGlzLnZ1ZV9jb250cm9sX2Jhcl9pZCApXG5cdFx0XHR9XG5cdFx0fTtcblxuXHRcdC8vQ3JlYXRlIFN0YXJ0IERhdGUgUGlja2VyXG5cdFx0dGhpcy5zdGFydF9kYXRlX3BpY2tlciA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuREFURV9QSUNLRVIgKTtcblx0XHR0aGlzLnN0YXJ0X2RhdGVfcGlja2VyLlREYXRlUGlja2VyKCB7IGZpZWxkOiAnc3RhcnRfZGF0ZScgfSApO1xuXHRcdHZhciBkYXRlX2Nob29zZXIgPSAkKCAnPHNwYW4gY2xhc3M9XFwnbGFiZWxcXCc+JyArICQuaTE4bi5fKCAnRGF0ZScgKSArICc6PC9zcGFuPicgK1xuXHRcdFx0JzxpbWcgY2xhc3M9XFwnbGVmdC1hcnJvdyBhcnJvd1xcJyBzcmM9JyArIEdsb2JhbC5nZXRSZWFsSW1hZ2VQYXRoKCAnaW1hZ2VzL2xlZnRfYXJyb3cuc3ZnJyApICsgJz4nICtcblx0XHRcdCc8ZGl2IGNsYXNzPVxcJ2RhdGUtcGlja2VyLWRpdlxcJz48L2Rpdj4nICtcblx0XHRcdCc8aW1nIGNsYXNzPVxcJ3JpZ2h0LWFycm93IGFycm93XFwnIHNyYz0nICsgR2xvYmFsLmdldFJlYWxJbWFnZVBhdGgoICdpbWFnZXMvcmlnaHRfYXJyb3cuc3ZnJyApICsgJz4nICk7XG5cblx0XHRkYXRlX2Nob29zZXJfZGl2LmFwcGVuZCggZGF0ZV9jaG9vc2VyICk7XG5cdFx0ZGF0ZV9jaG9vc2VyX2Rpdi5maW5kKCAnLmRhdGUtcGlja2VyLWRpdicgKS5hcHBlbmQoIHRoaXMuc3RhcnRfZGF0ZV9waWNrZXIgKTtcblxuXHRcdHZhciBkYXRlX2xlZnRfYXJyb3cgPSBkYXRlX2Nob29zZXJfZGl2LmZpbmQoICcubGVmdC1hcnJvdycgKTtcblx0XHR2YXIgZGF0ZV9yaWdodF9hcnJvdyA9IGRhdGVfY2hvb3Nlcl9kaXYuZmluZCggJy5yaWdodC1hcnJvdycgKTtcblxuXHRcdGRhdGVfbGVmdF9hcnJvdy5iaW5kKCAnY2xpY2snLCBmdW5jdGlvbigpIHtcblx0XHRcdC8vRXJyb3I6IFR5cGVFcnJvcjogJHRoaXMudGltZXNoZWV0X2NvbHVtbnMgaXMgdW5kZWZpbmVkIGluIC9pbnRlcmZhY2UvaHRtbDUvZnJhbWV3b3JrL2pxdWVyeS5taW4uanM/dj04LjAuMC0yMDE0MTIzMC0xMjU5MTkgbGluZSAyID4gZXZhbCBsaW5lIDE1Njlcblx0XHRcdGlmICggISR0aGlzLmNoZWNrVGltZXNoZWV0RGF0YSgpIHx8ICEkdGhpcy50aW1lc2hlZXRfY29sdW1ucyApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgc2VsZWN0X2RhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCAoICggJHRoaXMuZ2V0U2VsZWN0RGF0ZSgpICkgPyAkdGhpcy5nZXRTZWxlY3REYXRlKCkgOiBuZXcgRGF0ZSgpLmZvcm1hdCgpICkgKTtcblx0XHRcdHZhciBuZXdfZGF0ZSA9IG5ldyBEYXRlKCBuZXcgRGF0ZSggc2VsZWN0X2RhdGUuZ2V0VGltZSgpICkuc2V0RGF0ZSggc2VsZWN0X2RhdGUuZ2V0RGF0ZSgpIC0gNyApICkuZm9ybWF0KCk7XG5cdFx0XHQkdGhpcy5maXJzdF9idWlsZCA9IHRydWU7XG5cdFx0XHRjb250aW51ZUNoYW5nZURhdGUoIG5ld19kYXRlICk7XG5cblx0XHRcdC8vc2VlICMyMjI0IENhbm5vdCByZWFkIHByb3BlcnR5ICdkYXRlJyBvZiB1bmRlZmluZWRcblx0XHRcdCR0aGlzLnNldERlZmF1bHRNZW51KCk7XG5cdFx0fSApO1xuXG5cdFx0ZGF0ZV9yaWdodF9hcnJvdy5iaW5kKCAnY2xpY2snLCBmdW5jdGlvbigpIHtcblx0XHRcdC8vRXJyb3I6IFR5cGVFcnJvcjogJHRoaXMudGltZXNoZWV0X2NvbHVtbnMgaXMgdW5kZWZpbmVkIGluIC9pbnRlcmZhY2UvaHRtbDUvZnJhbWV3b3JrL2pxdWVyeS5taW4uanM/dj04LjAuMC0yMDE0MTIzMC0xMjU5MTkgbGluZSAyID4gZXZhbCBsaW5lIDE1Njlcblx0XHRcdGlmICggISR0aGlzLmNoZWNrVGltZXNoZWV0RGF0YSgpIHx8ICEkdGhpcy50aW1lc2hlZXRfY29sdW1ucyApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgc2VsZWN0X2RhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCAoICggJHRoaXMuZ2V0U2VsZWN0RGF0ZSgpICkgPyAkdGhpcy5nZXRTZWxlY3REYXRlKCkgOiBuZXcgRGF0ZSgpLmZvcm1hdCgpICkgKTtcblx0XHRcdHZhciBuZXdfZGF0ZSA9IG5ldyBEYXRlKCBuZXcgRGF0ZSggc2VsZWN0X2RhdGUuZ2V0VGltZSgpICkuc2V0RGF0ZSggc2VsZWN0X2RhdGUuZ2V0RGF0ZSgpICsgNyApICkuZm9ybWF0KCk7XG5cdFx0XHQkdGhpcy5maXJzdF9idWlsZCA9IHRydWU7XG5cdFx0XHRjb250aW51ZUNoYW5nZURhdGUoIG5ld19kYXRlICk7XG5cblx0XHRcdC8vc2VlICMyMjI0IENhbm5vdCByZWFkIHByb3BlcnR5ICdkYXRlJyBvZiB1bmRlZmluZWRcblx0XHRcdCR0aGlzLnNldERlZmF1bHRNZW51KCk7XG5cdFx0fSApO1xuXG5cdFx0dGhpcy5zdGFydF9kYXRlX3BpY2tlci5iaW5kKCAnZm9ybUl0ZW1DaGFuZ2UnLCBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBzZWxlY3RfZGF0ZSA9ICR0aGlzLmdldFNlbGVjdERhdGUoKSA/ICR0aGlzLmdldFNlbGVjdERhdGUoKSA6IG5ldyBEYXRlKCkuZm9ybWF0KCk7XG5cdFx0XHQkdGhpcy5maXJzdF9idWlsZCA9IHRydWU7XG5cdFx0XHRjb250aW51ZUNoYW5nZURhdGUoIHNlbGVjdF9kYXRlICk7XG5cdFx0fSApO1xuXG5cdFx0ZnVuY3Rpb24gY29udGludWVDaGFuZ2VEYXRlKCBuZXdfZGF0ZSApIHtcblx0XHRcdCR0aGlzLmRvTmV4dElmTm9WYWx1ZUNoYW5nZUluTWFudWFsR3JpZCggZG9OZXh0LCByZXNldCApO1xuXG5cdFx0XHRmdW5jdGlvbiByZXNldCgpIHtcblx0XHRcdFx0JHRoaXMuc2V0RGF0ZVBpY2tlclZhbHVlKCBMb2NhbENhY2hlRGF0YS5sYXN0X3RpbWVzaGVldF9zZWxlY3RlZF9kYXRlICk7XG5cdFx0XHR9XG5cblx0XHRcdGZ1bmN0aW9uIGRvTmV4dCgpIHtcblx0XHRcdFx0JHRoaXMuc2V0RGF0ZVBpY2tlclZhbHVlKCBuZXdfZGF0ZSApO1xuXHRcdFx0XHQkdGhpcy5zZWFyY2goKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvL0NyZWF0ZSBFbXBsb3llZSBOYXZpZ2F0aW9uXG5cblx0XHR2YXIgbGFiZWwgPSBlbXBsb3llZV9uYXZfZGl2LmZpbmQoICcubmF2aWdhdGlvbi1sYWJlbCcgKTtcblx0XHR2YXIgbGVmdF9jbGljayA9IGVtcGxveWVlX25hdl9kaXYuZmluZCggJy5sZWZ0LWNsaWNrJyApO1xuXHRcdHZhciByaWdodF9jbGljayA9IGVtcGxveWVlX25hdl9kaXYuZmluZCggJy5yaWdodC1jbGljaycgKTtcblx0XHR2YXIgbmF2aWdhdGlvbl93aWRnZXRfZGl2ID0gZW1wbG95ZWVfbmF2X2Rpdi5maW5kKCAnLm5hdmlnYXRpb24td2lkZ2V0LWRpdicgKTtcblxuXHRcdC8vSXNzdWUgIzMwOTcgLSBUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnRpZXMgb2YgdW5kZWZpbmVkIChyZWFkaW5nICdnZXRQdW5jaE1vZGUnKVxuXHRcdC8vVGhlIFZ1ZSBUaW1lU2hlZXRDb250cm9sQmFyIG1heSBhbHJlYWR5IGNvbnRhaW4gZG9tIGVsZW1lbnRzIGZyb20gcHJldmlvdXMgcmVuZGVycyAoY2FjaGVkPykgYW5kIG5lZWRzIHRvIGJlIHJlbW92ZWQuXG5cdFx0Ly9UaGUgcGFyZW50IGRpdiBuZWVkcyBhbGwgY2hpbGRyZW4gcmVtb3ZlZCB0byBwcmV2ZW50IG11bHRpcGxlIGVtcGxveWVlIHNlbGVjdG9ycyBmcm9tIGJlaW5nIGFkZGVkIHRvIHRoZSBkb20uXG5cdFx0bmF2aWdhdGlvbl93aWRnZXRfZGl2LmVtcHR5KCk7XG5cblx0XHR0aGlzLmVtcGxveWVlX25hdiA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1ggKTtcblx0XHR2YXIgZGVmYXVsdF9hcmdzID0geyBwZXJtaXNzaW9uX3NlY3Rpb246ICdwdW5jaCcgfTtcblx0XHR0aGlzLmVtcGxveWVlX25hdiA9IHRoaXMuZW1wbG95ZWVfbmF2LkFDb21ib0JveCgge1xuXHRcdFx0aWQ6ICdlbXBsb3llZV9uYXZpZ2F0aW9uJyxcblx0XHRcdGFwaV9jbGFzczogVFRBUEkuQVBJVXNlcixcblx0XHRcdGFsbG93X211bHRpcGxlX3NlbGVjdGlvbjogZmFsc2UsXG5cdFx0XHRsYXlvdXRfbmFtZTogJ2dsb2JhbF91c2VyJyxcblx0XHRcdGluaXRfZGF0YV9pbW1lZGlhdGVseTogdHJ1ZSxcblx0XHRcdGRlZmF1bHRfYXJnczogZGVmYXVsdF9hcmdzLFxuXHRcdFx0c2hvd19zZWFyY2hfaW5wdXRzOiB0cnVlLFxuXHRcdFx0YWx3YXlzX2luY2x1ZGVfY29sdW1uczogWydkZWZhdWx0X2JyYW5jaF9pZCcsICdkZWZhdWx0X2RlcGFydG1lbnRfaWQnLCAnZGVmYXVsdF9qb2JfaWQnLCAnZGVmYXVsdF9qb2JfaXRlbV9pZCcsICdkZWZhdWx0X3B1bmNoX3RhZ19pZCddLFxuXHRcdFx0d2lkdGg6IDIwMCxcblx0XHRcdGlzX3N0YXRpY193aWR0aDogdHJ1ZSwgLy9Vc2Ugc3RhdGljIHdpZHRoIHNvIHRoZSBsZWZ0L3JpZ2h0IG5hdmlnYXRpb24gYXJyb3dzIGRvbid0IG1vdmUgYXJvdW5kIGJhc2VkIG9uIHRoZSBsZW5ndGggb2YgdGhlIGVtcGxveWVlcyBuYW1lLlxuXHRcdFx0c2V0UmVhbFZhbHVlQ2FsbEJhY2s6ICggZnVuY3Rpb24oIHZhbCApIHtcblx0XHRcdFx0JHRoaXMudXNlclZhbHVlU2V0KCB2YWwgKTtcblx0XHRcdH0gKVxuXHRcdH0gKTtcblxuXHRcdG5hdmlnYXRpb25fd2lkZ2V0X2Rpdi5hcHBlbmQoIHRoaXMuZW1wbG95ZWVfbmF2ICk7XG5cdFx0bmF2aWdhdGlvbl93aWRnZXRfZGl2LmJpbmQoICdvbkNsb3NlJywgKCkgPT4ge1xuXHRcdFx0dGhpcy5zZXRFbXBsb3llZU5hdkFycm93c1N0YXR1cygpO1xuXHRcdH0gKTtcblx0XHR0aGlzLmVtcGxveWVlX25hdi5iaW5kKCAnZm9ybUl0ZW1DaGFuZ2UnLCBmdW5jdGlvbigpIHtcblx0XHRcdCR0aGlzLmRvTmV4dElmTm9WYWx1ZUNoYW5nZUluTWFudWFsR3JpZCggZG9OZXh0LCByZXNldCApO1xuXHRcdFx0R2xvYmFsLnRyaWdnZXJBbmFseXRpY3NFZGl0Vmlld05hdmlnYXRpb24oICduYXZpZ2F0aW9uJywgJHRoaXMudmlld0lkICk7XG5cblx0XHRcdGZ1bmN0aW9uIGRvTmV4dCgpIHtcblx0XHRcdFx0dmFyIHNlbGVjdGVkX3VzZXJfaWQgPSAkdGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpO1xuXHRcdFx0XHRpZiAoICEkdGhpcy5lZGl0X3ZpZXcgKSB7XG5cdFx0XHRcdFx0JHRoaXMucmVTZXRVUkwoKTtcblx0XHRcdFx0fVxuXHRcdFx0XHQkdGhpcy5hbGxvd19hdXRvX3N3aXRjaCAmJiAoICR0aGlzLmlzX2F1dG9fc3dpdGNoID0gdHJ1ZSApO1xuXHRcdFx0XHQkdGhpcy5maXJzdF9idWlsZCA9IHRydWU7XG5cdFx0XHRcdC8qIGpzaGludCBpZ25vcmU6c3RhcnQgKi9cblx0XHRcdFx0aWYgKCBMb2NhbENhY2hlRGF0YS5sYXN0X3RpbWVzaGVldF9zZWxlY3RlZF91c2VyICE9IHNlbGVjdGVkX3VzZXJfaWQgKSB7XG5cdFx0XHRcdFx0JHRoaXMuc2VhcmNoKCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0LyoganNoaW50IGlnbm9yZTplbmQgKi9cblx0XHRcdFx0JHRoaXMuYWJzZW5jZV9tb2RlbCA9IGZhbHNlO1xuXHRcdFx0XHQkdGhpcy5zZXREZWZhdWx0TWVudSgpO1xuXHRcdFx0fVxuXG5cdFx0XHRmdW5jdGlvbiByZXNldCgpIHtcblx0XHRcdFx0JHRoaXMuZW1wbG95ZWVfbmF2LnNldFZhbHVlKCBMb2NhbENhY2hlRGF0YS5sYXN0X3RpbWVzaGVldF9zZWxlY3RlZF91c2VyICk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXG5cdFx0dGhpcy5lbXBsb3llZV9uYXYuYmluZCggJ2luaXRTb3VyY2VDb21wbGV0ZScsIGZ1bmN0aW9uKCkge1xuXHRcdFx0JHRoaXMuc2V0RW1wbG95ZWVOYXZBcnJvd3NTdGF0dXMoKTtcblx0XHR9ICk7XG5cblx0XHRsZWZ0X2NsaWNrLmF0dHIoICdzcmMnLCBHbG9iYWwuZ2V0UmVhbEltYWdlUGF0aCggJ2ltYWdlcy9sZWZ0X2Fycm93LnN2ZycgKSApO1xuXHRcdHJpZ2h0X2NsaWNrLmF0dHIoICdzcmMnLCBHbG9iYWwuZ2V0UmVhbEltYWdlUGF0aCggJ2ltYWdlcy9yaWdodF9hcnJvdy5zdmcnICkgKTtcblx0XHRyaWdodF9jbGljay5jbGljayggZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoIHJpZ2h0X2NsaWNrLmhhc0NsYXNzKCAnZGlzYWJsZWQnICkgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHRcdCR0aGlzLmRvTmV4dElmTm9WYWx1ZUNoYW5nZUluTWFudWFsR3JpZCggZG9OZXh0ICk7XG5cdFx0XHRHbG9iYWwudHJpZ2dlckFuYWx5dGljc0VkaXRWaWV3TmF2aWdhdGlvbiggJ3JpZ2h0LWFycm93JywgJHRoaXMudmlld0lkICk7XG5cblx0XHRcdGZ1bmN0aW9uIGRvTmV4dCgpIHtcblx0XHRcdFx0dmFyIHNlbGVjdGVkX2luZGV4ID0gJHRoaXMuZW1wbG95ZWVfbmF2LmdldFNlbGVjdEluZGV4KCk7XG5cdFx0XHRcdHZhciBzb3VyY2VfZGF0YSA9ICR0aGlzLmVtcGxveWVlX25hdi5nZXRTb3VyY2VEYXRhKCk7XG5cdFx0XHRcdHZhciBjdXJyZW50X29wZW5fcGFnZSA9ICR0aGlzLmVtcGxveWVlX25hdi5nZXRDdXJyZW50T3BlblBhZ2UoKTtcblx0XHRcdFx0dmFyIG5leHRfc2VsZWN0X2l0ZW07XG5cdFx0XHRcdGlmICggc291cmNlX2RhdGEgJiYgc2VsZWN0ZWRfaW5kZXggPCAoIHNvdXJjZV9kYXRhLmxlbmd0aCAtIDEgKSApIHtcblx0XHRcdFx0XHRuZXh0X3NlbGVjdF9pdGVtID0gJHRoaXMuZW1wbG95ZWVfbmF2LmdldEl0ZW1CeUluZGV4KCAoIHNlbGVjdGVkX2luZGV4ICsgMSApICk7XG5cdFx0XHRcdFx0JHRoaXMuZW1wbG95ZWVfbmF2LnNldFZhbHVlKCBuZXh0X3NlbGVjdF9pdGVtICk7XG5cdFx0XHRcdFx0ZG9OZXh0RG9uZSgpO1xuXHRcdFx0XHR9IGVsc2UgaWYgKCBzb3VyY2VfZGF0YSAmJiBzZWxlY3RlZF9pbmRleCA9PT0gc291cmNlX2RhdGEubGVuZ3RoIC0gMSApIHtcblx0XHRcdFx0XHQvL29uQURyb3BEb3duU2VhcmNoKCkgbWFrZXMgYXN5bmMgY2FsbHMsIHNvIHdlIG5lZWQgdG8gaGF2ZSBhIGRvTmV4dERvbmUoKSBjYWxsYmFjayB0byB0cmlnZ2VyIHRvIGF2b2lkIHJhY2UgY29uZGl0aW9ucy5cblx0XHRcdFx0XHQkdGhpcy5lbXBsb3llZV9uYXYub25BRHJvcERvd25TZWFyY2goICd1bnNlbGVjdF9ncmlkJywgKCBjdXJyZW50X29wZW5fcGFnZSArIDEgKSwgJ2ZpcnN0JywgZG9OZXh0RG9uZSwgZmFsc2UgKTsgLy9Ta2lwIHRyaWdnZXJpbmcgRm9ybUl0ZW1DaGFuZ2UgYXMgd2UgY2FsbCBzZWFyY2goKSBvdXJzZWxmIGJlbG93IGFueXdheXMsIGFuZCBkb2luZyBib3RoIGNhbiBjYXVzZSByYWNlIGNvbmRpdGlvbnMgYW5kIGluY29ycmVjdCBkYXRhIHRvIGJlIGRpc3BsYXllZC5cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRuZXh0X3NlbGVjdF9pdGVtID0gJHRoaXMuZW1wbG95ZWVfbmF2LmdldEl0ZW1CeUluZGV4KCAwICk7XG5cdFx0XHRcdFx0JHRoaXMuZW1wbG95ZWVfbmF2LnNldFZhbHVlKCBuZXh0X3NlbGVjdF9pdGVtICk7XG5cdFx0XHRcdFx0ZG9OZXh0RG9uZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGZ1bmN0aW9uIGRvTmV4dERvbmUoKSB7XG5cdFx0XHRcdGlmICggISR0aGlzLmVkaXRfdmlldyApIHtcblx0XHRcdFx0XHQkdGhpcy5yZVNldFVSTCgpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdCR0aGlzLmFsbG93X2F1dG9fc3dpdGNoICYmICggJHRoaXMuaXNfYXV0b19zd2l0Y2ggPSB0cnVlICk7XG5cdFx0XHRcdCR0aGlzLmZpcnN0X2J1aWxkID0gdHJ1ZTtcblx0XHRcdFx0JHRoaXMuc2VhcmNoKCk7XG5cdFx0XHRcdCR0aGlzLnNldEVtcGxveWVlTmF2QXJyb3dzU3RhdHVzKCk7XG5cdFx0XHR9XG5cblx0XHR9ICk7XG5cblx0XHRsZWZ0X2NsaWNrLmNsaWNrKCBmdW5jdGlvbigpIHtcblx0XHRcdGlmICggbGVmdF9jbGljay5oYXNDbGFzcyggJ2Rpc2FibGVkJyApICkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0XHQkdGhpcy5kb05leHRJZk5vVmFsdWVDaGFuZ2VJbk1hbnVhbEdyaWQoIGRvTmV4dCApO1xuXHRcdFx0R2xvYmFsLnRyaWdnZXJBbmFseXRpY3NFZGl0Vmlld05hdmlnYXRpb24oICdsZWZ0LWFycm93JywgJHRoaXMudmlld0lkICk7XG5cblx0XHRcdGZ1bmN0aW9uIGRvTmV4dCgpIHtcblx0XHRcdFx0dmFyIHNlbGVjdGVkX2luZGV4ID0gJHRoaXMuZW1wbG95ZWVfbmF2LmdldFNlbGVjdEluZGV4KCk7XG5cdFx0XHRcdC8vdmFyIHNvdXJjZV9kYXRhID0gJHRoaXMuZW1wbG95ZWVfbmF2LmdldFNvdXJjZURhdGEoKTtcblx0XHRcdFx0dmFyIGN1cnJlbnRfb3Blbl9wYWdlID0gJHRoaXMuZW1wbG95ZWVfbmF2LmdldEN1cnJlbnRPcGVuUGFnZSgpO1xuXHRcdFx0XHR2YXIgbmV4dF9zZWxlY3RfaXRlbTtcblx0XHRcdFx0aWYgKCBzZWxlY3RlZF9pbmRleCA+IDAgKSB7XG5cdFx0XHRcdFx0bmV4dF9zZWxlY3RfaXRlbSA9ICR0aGlzLmVtcGxveWVlX25hdi5nZXRJdGVtQnlJbmRleCggKCBzZWxlY3RlZF9pbmRleCAtIDEgKSApO1xuXHRcdFx0XHRcdCR0aGlzLmVtcGxveWVlX25hdi5zZXRWYWx1ZSggbmV4dF9zZWxlY3RfaXRlbSApO1xuXHRcdFx0XHRcdGRvTmV4dERvbmUoKTtcblx0XHRcdFx0fSBlbHNlIGlmICggY3VycmVudF9vcGVuX3BhZ2UgPiAxICkge1xuXHRcdFx0XHRcdC8vb25BRHJvcERvd25TZWFyY2goKSBtYWtlcyBhc3luYyBjYWxscywgc28gd2UgbmVlZCB0byBoYXZlIGEgZG9OZXh0RG9uZSgpIGNhbGxiYWNrIHRvIHRyaWdnZXIgdG8gYXZvaWQgcmFjZSBjb25kaXRpb25zLlxuXHRcdFx0XHRcdCR0aGlzLmVtcGxveWVlX25hdi5vbkFEcm9wRG93blNlYXJjaCggJ3Vuc2VsZWN0X2dyaWQnLCAoIGN1cnJlbnRfb3Blbl9wYWdlIC0gMSApLCAnbGFzdCcsIGRvTmV4dERvbmUsIGZhbHNlICk7IC8vU2tpcCB0cmlnZ2VyaW5nIEZvcm1JdGVtQ2hhbmdlIGFzIHdlIGNhbGwgc2VhcmNoKCkgb3Vyc2VsZiBiZWxvdyBhbnl3YXlzLCBhbmQgZG9pbmcgYm90aCBjYW4gY2F1c2UgcmFjZSBjb25kaXRpb25zIGFuZCBpbmNvcnJlY3QgZGF0YSB0byBiZSBkaXNwbGF5ZWQuXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Ly8gRXJyb3I6IFR5cGVFcnJvcjogc291cmNlX2RhdGEgaXMgbnVsbCBpbiAvaW50ZXJmYWNlL2h0bWw1L2ZyYW1ld29yay9qcXVlcnkubWluLmpzP3Y9OC4wLjYtMjAxNTA0MTctMDg0MDAwIGxpbmUgMiA+IGV2YWwgbGluZSAxNjkxXG5cdFx0XHRcdFx0bmV4dF9zZWxlY3RfaXRlbSA9ICR0aGlzLmVtcGxveWVlX25hdi5nZXRJdGVtQnlJbmRleCggMCApO1xuXHRcdFx0XHRcdCR0aGlzLmVtcGxveWVlX25hdi5zZXRWYWx1ZSggbmV4dF9zZWxlY3RfaXRlbSApO1xuXHRcdFx0XHRcdGRvTmV4dERvbmUoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGZ1bmN0aW9uIGRvTmV4dERvbmUoKSB7XG5cdFx0XHRcdFx0aWYgKCAhJHRoaXMuZWRpdF92aWV3ICkge1xuXHRcdFx0XHRcdFx0JHRoaXMucmVTZXRVUkwoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0JHRoaXMuYWxsb3dfYXV0b19zd2l0Y2ggJiYgKCAkdGhpcy5pc19hdXRvX3N3aXRjaCA9IHRydWUgKTtcblx0XHRcdFx0XHQkdGhpcy5maXJzdF9idWlsZCA9IHRydWU7XG5cdFx0XHRcdFx0JHRoaXMuc2VhcmNoKCk7XG5cdFx0XHRcdFx0JHRoaXMuc2V0RW1wbG95ZWVOYXZBcnJvd3NTdGF0dXMoKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0fSApO1xuXG5cdFx0bGFiZWwudGV4dCggJC5pMThuLl8oICdFbXBsb3llZScgKSApO1xuXG5cdFx0Ly8gQ3JlYXRlIFZ1ZSB0aW1lc2hlZXQgbW9kZSB0b2dnbGUgYnV0dG9uc1xuXG5cdFx0aWYoIHRoaXMuc2hvd19wdW5jaF9tb2RlX3VpICkge1xuXHRcdFx0Ly8gQ3JlYXRlIHBzZXVkbyBlbGVtZW50IHRvIHBvc2UgYXMgalF1ZXJ5IG9iamVjdCBidXQgaXMgYWN0dWFsbHkganVzdCBhbiBpbnRlcmZhY2UgZm9yIHRoZSBWdWUgY29tcG9uZW50LlxuXHRcdFx0Ly8gVE9ETzogT25jZSBtb3JlL3ZpZXcgY29tcG9uZW50IGhhcyBiZWVuIGNvbnZlcnRlZCB0byBWdWUsIHdlIHdhbnQgdG8gcmVmYWN0b3IgdGhpcyB0b2dnbGUgYnV0dG9uIGxvZ2ljIHRvIG1ha2UgdXNlIG9mIG1vcmUgc3RyZWFtbGluZWQgVnVlIGRhdGEgZmVhdHVyZXMgbGlrZSB0d28gd2F5IGJpbmRpbmcuXG5cblx0XHRcdHRoaXMudG9nZ2xlX2J1dHRvbiA9IHtcblx0XHRcdFx0aWQ6IHRoaXMudnVlX2NvbnRyb2xfYmFyX2lkLFxuXHRcdFx0XHRnZXRWYWx1ZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0aWYgKCB2dWVfcmV0dXJuICYmIHZ1ZV9yZXR1cm4uX3Z1ZV9jb21wb25lbnRfaW5zdGFuY2UgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gdnVlX3JldHVybi5fdnVlX2NvbXBvbmVudF9pbnN0YW5jZS5nZXRQdW5jaE1vZGU7IC8vIGl0cyBkb25lIGFzIGEgZ2V0dGVyIGZ1bmN0aW9uIG9uIHRoZSBWdWUgc2lkZSwgc28gbm8gbmVlZCBmb3IgYnJhY2tldHMuXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRzZXRWYWx1ZTogZnVuY3Rpb24oIG5ld192YWx1ZSApIHtcblx0XHRcdFx0XHRpZiAoIHZ1ZV9yZXR1cm4gJiYgdnVlX3JldHVybi5fdnVlX2NvbXBvbmVudF9pbnN0YW5jZSApIHtcblx0XHRcdFx0XHRcdHZ1ZV9yZXR1cm4uX3Z1ZV9jb21wb25lbnRfaW5zdGFuY2Uuc2V0UHVuY2hNb2RlKCBuZXdfdmFsdWUgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdC8vIFRPRE8gQ2FudCB1c2UgdGhpcyBhcyBhIHJlbW92ZSwgYXMgaXQgd291bGQgcmVtb3ZlIHRoZSB3aG9sZSBjb250cm9sIGJhci4gV2Ugb25seSB3YW50IHRvIGhpZGUvcmVtb3ZlIHRoZSB0b2dnbGUgYnV0dG9ucyBmb3IgbW9kZS5cblx0XHRcdFx0cmVtb3ZlOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRyZXR1cm4gVFRWdWVVdGlscy51bm1vdW50Q29tcG9uZW50KCB0aGlzLnZ1ZV9jb250cm9sX2Jhcl9pZCApXG5cdFx0XHRcdH1cblx0XHRcdH07XG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0bGV0IG1vZGUgPSAncHVuY2gnO1xuXG5cdFx0XHRjb25zdCB0b2dnbGVfZGl2ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvciggJy5wdW5jaC1tYW51YWwnICk7XG5cblx0XHRcdGlmICggdG9nZ2xlX2RpdiApIHtcblx0XHRcdFx0dG9nZ2xlX2Rpdi5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnOyAvL0hpZGUgdG9nZ2xlIG1vZGUgYnV0dG9uXG5cdFx0XHR9XG5cblx0XHRcdC8vSWYgdGhleSBoYXZlIG1hbnVhbCBwZXJtaXNzaW9uLCBzaG93IG1hbnVhbCBtb2RlIG90aGVyd2lzZSBwdW5jaFxuXHRcdFx0aWYgKCBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAxNSAmJiBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggdGhpcy5wZXJtaXNzaW9uX2lkLCAnbWFudWFsX3RpbWVzaGVldCcgKSApIHtcblx0XHRcdFx0bW9kZSA9ICdtYW51YWwnO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLnRvZ2dsZV9idXR0b24gPSB7XG5cdFx0XHRcdGdldFZhbHVlOiAoKSA9PiBtb2RlLCAvL0Fsd2F5cyByZXR1cm4gdGhlIG1vZGUgdGhlIHVzZXIgaGFzIHBlcm1pc3Npb24gdG8gdmlldy5cblx0XHRcdFx0c2V0VmFsdWU6IGZ1bmN0aW9uKCBuZXdfdmFsdWUgKSB7XG5cdFx0XHRcdFx0Ly9Vc2VyIHdpdGhvdXQgcGVybWlzc2lvbnMgY2Fubm90IGNoYW5nZSBwdW5jaCBtb2RlLlxuXHRcdFx0XHR9LFxuXHRcdFx0fTtcblx0XHR9XG5cdH1cblxuXHRkb05leHRJZk5vVmFsdWVDaGFuZ2VJbk1hbnVhbEdyaWQoIGRvTmV4dCwgcmVzZXQsIG1vZGUgKSB7XG5cdFx0IW1vZGUgJiYgKCBtb2RlID0gJ21hbnVhbCcgKTtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdGlmICggdGhpcy5nZXRQdW5jaE1vZGUoKSA9PT0gbW9kZSAmJiB0aGlzLmVkaXRvciApIHtcblx0XHRcdHZhciByZWNvcmRzID0gdGhpcy5lZGl0b3IuZ2V0VmFsdWUoKTtcblx0XHRcdGlmICggcmVjb3Jkcy5sZW5ndGggPiAwICkge1xuXHRcdFx0XHRUQWxlcnRNYW5hZ2VyLnNob3dDb25maXJtQWxlcnQoIEdsb2JhbC5tb2RpZnlfYWxlcnRfbWVzc2FnZSwgJycsIGZ1bmN0aW9uKCBmbGFnICkge1xuXHRcdFx0XHRcdGlmICggZmxhZyApIHtcblx0XHRcdFx0XHRcdCR0aGlzLndhaXRfYXV0b19zYXZlICYmIGNsZWFyVGltZW91dCggJHRoaXMud2FpdF9hdXRvX3NhdmUgKTtcblx0XHRcdFx0XHRcdGRvTmV4dCgpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRyZXNldCAmJiByZXNldCgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZG9OZXh0KCk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdGRvTmV4dCgpO1xuXHRcdH1cblx0fVxuXG5cdGdldFB1bmNoTW9kZSgpIHtcblx0XHQvL01vZGUgdG9nZ2xlIGRvZXMgbm90IGV4aXN0IGlmIHRoZSB1c2VyIGRvZXNuJ3QgaGF2ZSBhY2Nlc3MgdG8gaXQuXG5cdFx0aWYgKCB0aGlzLnRvZ2dsZV9idXR0b24gKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy50b2dnbGVfYnV0dG9uLmdldFZhbHVlKCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiAncHVuY2gnO1xuXHRcdH1cblx0fVxuXG5cdGhhbmRsZU92ZXJyaWRlVXNlclByZWZlcmVuY2VDb29raWUoIHVzZXJfaWQgKSB7XG5cdFx0aWYgKCB0aGlzLnRpbWV6b25lX2J0bi5nZXRWYWx1ZSgpID09IHRydWUgKSB7XG5cdFx0XHRzZXRDb29raWUoICdPdmVycmlkZVVzZXJQcmVmZXJlbmNlJywgd2luZG93LmJ0b2EoICd7IFwidXNlcl9pZFwiOiBcIicgKyB1c2VyX2lkICsgJ1wifScgKSApOyAvL0Jhc2U2NCBlbmNvZGUuXG5cdFx0fSBlbHNlIHtcblx0XHRcdGRlbGV0ZUNvb2tpZSggJ092ZXJyaWRlVXNlclByZWZlcmVuY2UnICk7XG5cdFx0fVxuXHR9XG5cblx0b25XYWdlT3JNb2RlQ2hhbmdlKCBpZCApIHtcblx0XHR0aGlzLmZpcnN0X2J1aWxkID0gdHJ1ZTtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdGlmICggaWQgPT09ICd3YWdlJyApIHtcblx0XHRcdHRoaXMuZG9OZXh0SWZOb1ZhbHVlQ2hhbmdlSW5NYW51YWxHcmlkKCBkb05leHQsIHJlc2V0V2FnZSApO1xuXHRcdH0gZWxzZSBpZiAoIGlkID09PSAndGltZXpvbmUnICkge1xuXHRcdFx0dGhpcy5oYW5kbGVPdmVycmlkZVVzZXJQcmVmZXJlbmNlQ29va2llKCB0aGlzLmdldFNlbGVjdEVtcGxveWVlKCkgKTtcblx0XHRcdHRoaXMuZG9OZXh0SWZOb1ZhbHVlQ2hhbmdlSW5NYW51YWxHcmlkKCBkb05leHQsIHJlc2V0VGltZVpvbmUgKTtcblx0XHR9IGVsc2UgaWYgKCBpZCA9PT0gJ21hbnVhbCcgKSB7XG5cdFx0XHR0aGlzLmRvTmV4dElmTm9WYWx1ZUNoYW5nZUluTWFudWFsR3JpZCggZG9OZXh0LCByZXNldE1hbnVhbCwgJ3B1bmNoJyApO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIHJlc2V0V2FnZSgpIHtcblx0XHRcdCR0aGlzLndhZ2VfYnRuLnNldFZhbHVlKCAhJHRoaXMud2FnZV9idG4uZ2V0VmFsdWUoIHRydWUgKSApO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIHJlc2V0VGltZVpvbmUoKSB7XG5cdFx0XHQkdGhpcy50aW1lem9uZV9idG4uc2V0VmFsdWUoICEkdGhpcy50aW1lem9uZV9idG4uZ2V0VmFsdWUoIHRydWUgKSApO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIHJlc2V0TWFudWFsKCkge1xuXHRcdFx0JHRoaXMudG9nZ2xlX2J1dHRvbi5zZXRWYWx1ZSggJ21hbnVhbCcgKTtcblx0XHR9XG5cblx0XHRmdW5jdGlvbiBkb05leHQoKSB7XG5cdFx0XHRpZiAoICEkdGhpcy5lZGl0X3ZpZXcgKSB7XG5cdFx0XHRcdCR0aGlzLnJlU2V0VVJMKCk7XG5cdFx0XHR9XG5cdFx0XHQkdGhpcy5zZWFyY2goKTtcblx0XHRcdCR0aGlzLnNldERlZmF1bHRNZW51KCk7XG5cdFx0fVxuXHR9XG5cblx0c2V0RW1wbG95ZWVOYXZBcnJvd3NTdGF0dXMoKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgZW1wbG95ZWVfbmF2X2RpdiA9ICQoIHRoaXMuZWwgKS5maW5kKCAnLmVtcGxveWVlLW5hdi1kaXYnICk7XG5cdFx0dmFyIGxlZnRfY2xpY2sgPSBlbXBsb3llZV9uYXZfZGl2LmZpbmQoICcubGVmdC1jbGljaycgKTtcblx0XHR2YXIgcmlnaHRfY2xpY2sgPSBlbXBsb3llZV9uYXZfZGl2LmZpbmQoICcucmlnaHQtY2xpY2snICk7XG5cdFx0dmFyIHNlbGVjdGVkX2luZGV4ID0gJHRoaXMuZW1wbG95ZWVfbmF2LmdldFNlbGVjdEluZGV4KCk7XG5cdFx0dmFyIHNvdXJjZV9kYXRhID0gJHRoaXMuZW1wbG95ZWVfbmF2LmdldFNvdXJjZURhdGEoKTtcblxuXHRcdHJpZ2h0X2NsaWNrLnJlbW92ZUNsYXNzKCAnZGlzYWJsZWQnICk7XG5cdFx0bGVmdF9jbGljay5yZW1vdmVDbGFzcyggJ2Rpc2FibGVkJyApO1xuXG5cdFx0dmFyIHBhZ2VyX2RhdGEgPSAkdGhpcy5lbXBsb3llZV9uYXYuZ2V0UGFnZXJEYXRhKCk7XG5cdFx0dmFyIGN1cnJlbnRfb3Blbl9wYWdlID0gJHRoaXMuZW1wbG95ZWVfbmF2LmdldEN1cnJlbnRPcGVuUGFnZSgpO1xuXG5cdFx0Ly9FcnJvcjogVW5jYXVnaHQgVHlwZUVycm9yOiBDYW5ub3QgcmVhZCBwcm9wZXJ0eSAnbGVuZ3RoJyBvZiBudWxsIGluIC9pbnRlcmZhY2UvaHRtbDUvIyFtPVRpbWVTaGVldCZkYXRlPTIwMTUwMTAyJnVzZXJfaWQ9bnVsbCBsaW5lIDE2OThcblx0XHRpZiAoICFzb3VyY2VfZGF0YSB8fCAoIHNlbGVjdGVkX2luZGV4ID09PSBzb3VyY2VfZGF0YS5sZW5ndGggLSAxICYmIGN1cnJlbnRfb3Blbl9wYWdlID09PSBwYWdlcl9kYXRhLmxhc3RfcGFnZV9udW1iZXIgKSApIHtcblx0XHRcdHJpZ2h0X2NsaWNrLmFkZENsYXNzKCAnZGlzYWJsZWQnICk7XG5cdFx0fVxuXG5cdFx0aWYgKCAhc291cmNlX2RhdGEgfHwgKCBzZWxlY3RlZF9pbmRleCA9PT0gMCAmJiBjdXJyZW50X29wZW5fcGFnZSA9PT0gMSApICkge1xuXHRcdFx0bGVmdF9jbGljay5hZGRDbGFzcyggJ2Rpc2FibGVkJyApO1xuXHRcdH1cblx0fVxuXG5cdG9uQ2xlYXJTZWFyY2goKSB7XG5cdFx0dmFyIGRvX3VwZGF0ZSA9IGZhbHNlO1xuXHRcdHZhciBkZWZhdWx0X2xheW91dF9pZDtcblx0XHRpZiAoIHRoaXMuc2VhcmNoX3BhbmVsLmdldExheW91dHNBcnJheSgpICYmIHRoaXMuc2VhcmNoX3BhbmVsLmdldExheW91dHNBcnJheSgpLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRkZWZhdWx0X2xheW91dF9pZCA9ICQoIHRoaXMucHJldmlvdXNfc2F2ZWRfbGF5b3V0X3NlbGVjdG9yICkuY2hpbGRyZW4oICdvcHRpb246Y29udGFpbnMoXFwnJyArIEJhc2VWaWV3Q29udHJvbGxlci5kZWZhdWx0X2xheW91dF9uYW1lICsgJ1xcJyknICkuYXR0ciggJ3ZhbHVlJyApO1xuXHRcdFx0dmFyIGxheW91dF9uYW1lID0gQmFzZVZpZXdDb250cm9sbGVyLmRlZmF1bHRfbGF5b3V0X25hbWU7XG5cdFx0XHR0aGlzLmNsZWFyU2VhcmNoUGFuZWwoKTtcblx0XHRcdHRoaXMuZmlsdGVyX2RhdGEgPSBudWxsO1xuXHRcdFx0dGhpcy50ZW1wX2Fkdl9maWx0ZXJfZGF0YSA9IG51bGw7XG5cdFx0XHR0aGlzLnRlbXBfYmFzaWNfZmlsdGVyX2RhdGEgPSBudWxsO1xuXHRcdFx0ZG9fdXBkYXRlID0gdHJ1ZTtcblxuXHRcdH0gZWxzZSB7XG5cblx0XHRcdHRoaXMuY2xlYXJTZWFyY2hQYW5lbCgpO1xuXHRcdFx0dGhpcy5maWx0ZXJfZGF0YSA9IG51bGw7XG5cdFx0XHR0aGlzLnRlbXBfYWR2X2ZpbHRlcl9kYXRhID0gbnVsbDtcblx0XHRcdHRoaXMudGVtcF9iYXNpY19maWx0ZXJfZGF0YSA9IG51bGw7XG5cblx0XHRcdC8vRXJyb3I6IFVuY2F1Z2h0IFR5cGVFcnJvcjogQ2Fubm90IHJlYWQgcHJvcGVydHkgJ3NldFNlbGVjdEdyaWREYXRhJyBvZiBudWxsIGluIC9pbnRlcmZhY2UvaHRtbDUvIyFtPVRpbWVTaGVldCZkYXRlPTIwMTQxMjEzJnVzZXJfaWQ9Mjk3MTUgbGluZSAxNzM4XG5cdFx0XHRpZiAoIHRoaXMuY29sdW1uX3NlbGVjdG9yICkge1xuXHRcdFx0XHR0aGlzLmNvbHVtbl9zZWxlY3Rvci5zZXRTZWxlY3RHcmlkRGF0YSggdGhpcy5kZWZhdWx0X2Rpc3BsYXlfY29sdW1ucyApO1xuXHRcdFx0fVxuXG5cdFx0XHQvL0Vycm9yOiBVbmNhdWdodCBUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnR5ICdzZXRWYWx1ZScgb2YgbnVsbCBpbiAvaW50ZXJmYWNlL2h0bWw1LyMhbT1UaW1lU2hlZXQmZGF0ZT0yMDE1MDEyNSZ1c2VyX2lkPTUzMjg4IGxpbmUgMTc0MlxuXHRcdFx0aWYgKCB0aGlzLnNvcnRfYnlfc2VsZWN0b3IgKSB7XG5cdFx0XHRcdHRoaXMuc29ydF9ieV9zZWxlY3Rvci5zZXRWYWx1ZSggbnVsbCApO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLm9uU2F2ZU5ld0xheW91dCggQmFzZVZpZXdDb250cm9sbGVyLmRlZmF1bHRfbGF5b3V0X25hbWUgKTtcblx0XHRcdHJldHVybjtcblxuXHRcdH1cblxuXHRcdHZhciBmaWx0ZXJfZGF0YSA9IHRoaXMuZ2V0VmFsaWRTZWFyY2hGaWx0ZXIoKTtcblxuXHRcdHZhciBhcmdzO1xuXHRcdGlmICggZG9fdXBkYXRlICkge1xuXHRcdFx0YXJncyA9IHt9O1xuXHRcdFx0YXJncy5pZCA9IGRlZmF1bHRfbGF5b3V0X2lkO1xuXHRcdFx0YXJncy5kYXRhID0ge307XG5cdFx0XHRhcmdzLmRhdGEuZmlsdGVyX2RhdGEgPSBmaWx0ZXJfZGF0YTtcblxuXHRcdH1cblxuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dGhpcy51c2VyX2dlbmVyaWNfZGF0YV9hcGkuc2V0VXNlckdlbmVyaWNEYXRhKCBhcmdzLCB7XG5cdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlcyApIHtcblxuXHRcdFx0XHRpZiAoIHJlcy5pc1ZhbGlkKCkgKSB7XG5cdFx0XHRcdFx0JHRoaXMuY2xlYXJWaWV3TGF5b3V0Q2FjaGUoKTtcblx0XHRcdFx0XHQkdGhpcy5uZWVkX3NlbGVjdF9sYXlvdXRfbmFtZSA9IGxheW91dF9uYW1lO1xuXHRcdFx0XHRcdCR0aGlzLmluaXRMYXlvdXQoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cblx0b25VcGRhdGVMYXlvdXQoKSB7XG5cblx0XHR2YXIgc2VsZWN0SWQgPSAkKCB0aGlzLnByZXZpb3VzX3NhdmVkX2xheW91dF9zZWxlY3RvciApLmNoaWxkcmVuKCAnb3B0aW9uOnNlbGVjdGVkJyApLmF0dHIoICd2YWx1ZScgKTtcblx0XHR2YXIgbGF5b3V0X25hbWUgPSAkKCB0aGlzLnByZXZpb3VzX3NhdmVkX2xheW91dF9zZWxlY3RvciApLmNoaWxkcmVuKCAnb3B0aW9uOnNlbGVjdGVkJyApLnRleHQoKTtcblxuXHRcdHZhciBmaWx0ZXJfZGF0YSA9IHRoaXMuZ2V0VmFsaWRTZWFyY2hGaWx0ZXIoKTtcblxuXHRcdHZhciBhcmdzID0ge307XG5cdFx0YXJncy5pZCA9IHNlbGVjdElkO1xuXHRcdGFyZ3MuZGF0YSA9IHt9O1xuXHRcdGFyZ3MuZGF0YS5maWx0ZXJfZGF0YSA9IGZpbHRlcl9kYXRhO1xuXHRcdGFyZ3MuZGF0YS5tb2RlID0gdGhpcy50b2dnbGVfYnV0dG9uLmdldFZhbHVlKCk7XG5cdFx0YXJncy5kYXRhLnNob3dfd2FnZSA9ICB0aGlzLndhZ2VfYnRuLmdldFZhbHVlKCk7XG5cdFx0YXJncy5kYXRhLnVzZV9lbXBsb3llZV90aW1lem9uZSA9IHRoaXMudGltZXpvbmVfYnRuLmdldFZhbHVlKCk7XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHRoaXMudXNlcl9nZW5lcmljX2RhdGFfYXBpLnNldFVzZXJHZW5lcmljRGF0YSggYXJncywge1xuXHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXMgKSB7XG5cdFx0XHRcdGlmICggcmVzLmlzVmFsaWQoKSApIHtcblx0XHRcdFx0XHQkdGhpcy5jbGVhclZpZXdMYXlvdXRDYWNoZSgpO1xuXHRcdFx0XHRcdCR0aGlzLm5lZWRfc2VsZWN0X2xheW91dF9uYW1lID0gbGF5b3V0X25hbWU7XG5cdFx0XHRcdFx0JHRoaXMuaW5pdExheW91dCgpO1xuXHRcdFx0XHR9XG5cblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cblxuXHRvblNhdmVOZXdMYXlvdXQoIGRlZmF1bHRfbGF5b3V0X25hbWUgKSB7XG5cdFx0dmFyIGxheW91dF9uYW1lO1xuXHRcdGlmICggR2xvYmFsLmlzU2V0KCBkZWZhdWx0X2xheW91dF9uYW1lICkgKSB7XG5cdFx0XHRsYXlvdXRfbmFtZSA9IGRlZmF1bHRfbGF5b3V0X25hbWU7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGxheW91dF9uYW1lID0gdGhpcy5zYXZlX3NlYXJjaF9hc19pbnB1dC5nZXRWYWx1ZSgpO1xuXHRcdH1cblxuXHRcdGlmICggIWxheW91dF9uYW1lIHx8IGxheW91dF9uYW1lLmxlbmd0aCA8IDEgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIGZpbHRlcl9kYXRhID0gdGhpcy5nZXRWYWxpZFNlYXJjaEZpbHRlcigpO1xuXG5cdFx0dmFyIGFyZ3MgPSB7fTtcblx0XHRhcmdzLnNjcmlwdCA9IHRoaXMuc2NyaXB0X25hbWU7XG5cdFx0YXJncy5uYW1lID0gbGF5b3V0X25hbWU7XG5cdFx0YXJncy5pc19kZWZhdWx0ID0gZmFsc2U7XG5cdFx0YXJncy5kYXRhID0ge307XG5cdFx0YXJncy5kYXRhLmZpbHRlcl9kYXRhID0gZmlsdGVyX2RhdGE7XG5cdFx0YXJncy5kYXRhLm1vZGUgPSB0aGlzLnRvZ2dsZV9idXR0b24uZ2V0VmFsdWUoKTtcblx0XHRhcmdzLmRhdGEuc2hvd193YWdlID0gIHRoaXMud2FnZV9idG4uZ2V0VmFsdWUoKTtcblx0XHRhcmdzLmRhdGEudXNlX2VtcGxveWVlX3RpbWV6b25lID0gdGhpcy50aW1lem9uZV9idG4uZ2V0VmFsdWUoKTtcblxuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dGhpcy51c2VyX2dlbmVyaWNfZGF0YV9hcGkuc2V0VXNlckdlbmVyaWNEYXRhKCBhcmdzLCB7XG5cdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlcyApIHtcblxuXHRcdFx0XHRpZiAoIHJlcy5pc1ZhbGlkKCkgKSB7XG5cdFx0XHRcdFx0JHRoaXMuY2xlYXJWaWV3TGF5b3V0Q2FjaGUoKTtcblx0XHRcdFx0XHQkdGhpcy5uZWVkX3NlbGVjdF9sYXlvdXRfbmFtZSA9IGxheW91dF9uYW1lO1xuXHRcdFx0XHRcdCR0aGlzLmluaXRMYXlvdXQoKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRUQWxlcnRNYW5hZ2VyLnNob3dFcnJvckFsZXJ0KCByZXMgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cblx0b25TZWFyY2goIHNhdmVfb25seSApIHtcblx0XHRHbG9iYWwuc2V0VUlOb3RyZWFkeSgpO1xuXHRcdFRUUHJvbWlzZS5hZGQoICdpbml0JywgJ2luaXQnICk7XG5cdFx0VFRQcm9taXNlLndhaXQoKTtcblxuXHRcdHRoaXMudGVtcF9hZHZfZmlsdGVyX2RhdGEgPSBudWxsO1xuXHRcdHRoaXMudGVtcF9iYXNpY19maWx0ZXJfZGF0YSA9IG51bGw7XG5cblx0XHR0aGlzLmdldFNlYXJjaFBhbmVsRmlsdGVyKCk7XG5cdFx0dmFyIGRlZmF1bHRfbGF5b3V0X2lkO1xuXHRcdHZhciBsYXlvdXRfbmFtZTtcblx0XHRpZiAoIHRoaXMuc2VhcmNoX3BhbmVsLmdldExheW91dHNBcnJheSgpICYmIHRoaXMuc2VhcmNoX3BhbmVsLmdldExheW91dHNBcnJheSgpLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRkZWZhdWx0X2xheW91dF9pZCA9ICQoIHRoaXMucHJldmlvdXNfc2F2ZWRfbGF5b3V0X3NlbGVjdG9yICkuY2hpbGRyZW4oICdvcHRpb246Y29udGFpbnMoXFwnJyArIEJhc2VWaWV3Q29udHJvbGxlci5kZWZhdWx0X2xheW91dF9uYW1lICsgJ1xcJyknICkuYXR0ciggJ3ZhbHVlJyApO1xuXHRcdFx0bGF5b3V0X25hbWUgPSBCYXNlVmlld0NvbnRyb2xsZXIuZGVmYXVsdF9sYXlvdXRfbmFtZTtcblxuXHRcdFx0aWYgKCAhZGVmYXVsdF9sYXlvdXRfaWQgKSB7XG5cdFx0XHRcdHRoaXMub25TYXZlTmV3TGF5b3V0KCBCYXNlVmlld0NvbnRyb2xsZXIuZGVmYXVsdF9sYXlvdXRfbmFtZSApO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMub25TYXZlTmV3TGF5b3V0KCBCYXNlVmlld0NvbnRyb2xsZXIuZGVmYXVsdF9sYXlvdXRfbmFtZSApO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBmaWx0ZXJfZGF0YSA9IHRoaXMuZ2V0VmFsaWRTZWFyY2hGaWx0ZXIoKTtcblxuXHRcdHZhciBhcmdzID0ge307XG5cdFx0YXJncy5pZCA9IGRlZmF1bHRfbGF5b3V0X2lkO1xuXHRcdGFyZ3MuZGF0YSA9IHt9O1xuXHRcdGFyZ3MuZGF0YS5maWx0ZXJfZGF0YSA9IGZpbHRlcl9kYXRhO1xuXHRcdGFyZ3MuZGF0YS5tb2RlID0gdGhpcy50b2dnbGVfYnV0dG9uLmdldFZhbHVlKCk7XG5cdFx0YXJncy5kYXRhLnNob3dfd2FnZSA9ICB0aGlzLndhZ2VfYnRuLmdldFZhbHVlKCk7XG5cdFx0YXJncy5kYXRhLnVzZV9lbXBsb3llZV90aW1lem9uZSA9IHRoaXMudGltZXpvbmVfYnRuLmdldFZhbHVlKCk7XG5cblx0XHRQcm9ncmVzc0Jhci5zaG93T3ZlcmxheSgpO1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dGhpcy51c2VyX2dlbmVyaWNfZGF0YV9hcGkuc2V0VXNlckdlbmVyaWNEYXRhKCBhcmdzLCB7XG5cdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlcyApIHtcblxuXHRcdFx0XHRpZiAoIHJlcy5pc1ZhbGlkKCkgKSB7XG5cdFx0XHRcdFx0JHRoaXMuY2xlYXJWaWV3TGF5b3V0Q2FjaGUoKTtcblx0XHRcdFx0XHQkdGhpcy5uZWVkX3NlbGVjdF9sYXlvdXRfbmFtZSA9IGxheW91dF9uYW1lO1xuXHRcdFx0XHRcdGlmICggIXNhdmVfb25seSApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICR0aGlzLmluaXRMYXlvdXQoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXHRcdFx0XHR9XG5cblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cblxuXHR1cGRhdGVNYW51YWxHcmlkKCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dmFyIHN0YXJ0X2RhdGVfc3RyaW5nID0gdGhpcy5zdGFydF9kYXRlX3BpY2tlci5nZXRWYWx1ZSgpO1xuXHRcdHZhciB1c2VyX2lkID0gdGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpO1xuXHRcdFByb2dyZXNzQmFyLm5vUHJvZ3Jlc3NGb3JOZXh0Q2FsbCgpO1xuXG5cdFx0JHRoaXMuaGFuZGxlT3ZlcnJpZGVVc2VyUHJlZmVyZW5jZUNvb2tpZSggdXNlcl9pZCApO1xuXHRcdCR0aGlzLmFwaV90aW1lc2hlZXQuZ2V0VGltZVNoZWV0RGF0YSggdXNlcl9pZCwgc3RhcnRfZGF0ZV9zdHJpbmcsIHtcblx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHRQcm9ncmVzc0Jhci5yZW1vdmVOYW5vYmFyKCk7XG5cdFx0XHRcdCR0aGlzLmZ1bGxfdGltZXNoZWV0X2RhdGEgPSByZXN1bHQuZ2V0UmVzdWx0KCk7XG5cdFx0XHRcdGlmICggJHRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YSA9PT0gdHJ1ZSB8fCAhJHRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YS5oYXNPd25Qcm9wZXJ0eSggJ3RpbWVzaGVldF9kYXRlcycgKSApIHtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblx0XHRcdFx0JHRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YSA9ICR0aGlzLm1lcmdlSm9iUXVldWVJbnRvVGltZVNoZWV0RGF0YSggJHRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YSApO1xuXHRcdFx0XHQkdGhpcy5zdGFydF9kYXRlID0gR2xvYmFsLnN0clRvRGF0ZSggJHRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YS50aW1lc2hlZXRfZGF0ZXMuc3RhcnRfZGlzcGxheV9kYXRlICk7XG5cdFx0XHRcdCR0aGlzLmVuZF9kYXRlID0gR2xvYmFsLnN0clRvRGF0ZSggJHRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YS50aW1lc2hlZXRfZGF0ZXMuZW5kX2Rpc3BsYXlfZGF0ZSApO1xuXHRcdFx0XHQkdGhpcy5zZXREZWZhdWx0TWVudSgpO1xuXHRcdFx0XHQkdGhpcy5pbml0SW5zaWRlRWRpdG9yRGF0YSggdHJ1ZSApO1xuXHRcdFx0XHQkdGhpcy5hY2N1bXVsYXRlZF90aW1lX3NvdXJjZV9tYXAgPSB7fTtcblx0XHRcdFx0JHRoaXMuYnJhbmNoX3NvdXJjZV9tYXAgPSB7fTtcblx0XHRcdFx0JHRoaXMuZGVwYXJ0bWVudF9zb3VyY2VfbWFwID0ge307XG5cdFx0XHRcdCR0aGlzLmpvYl9zb3VyY2VfbWFwID0ge307XG5cdFx0XHRcdCR0aGlzLmpvYl9pdGVtX3NvdXJjZV9tYXAgPSB7fTtcblx0XHRcdFx0JHRoaXMucHVuY2hfdGFnX3NvdXJjZV9tYXAgPSB7fTtcblx0XHRcdFx0JHRoaXMucHJlbWl1bV9zb3VyY2VfbWFwID0ge307XG5cdFx0XHRcdCR0aGlzLmFjY3VtdWxhdGVkX3RvdGFsX2dyaWRfc291cmNlX21hcCA9IHt9O1xuXHRcdFx0XHQkdGhpcy5hY2N1bXVsYXRlZF90aW1lX3NvdXJjZSA9IFtdO1xuXHRcdFx0XHQkdGhpcy5icmFuY2hfc291cmNlID0gW107XG5cdFx0XHRcdCR0aGlzLmRlcGFydG1lbnRfc291cmNlID0gW107XG5cdFx0XHRcdCR0aGlzLmpvYl9zb3VyY2UgPSBbXTtcblx0XHRcdFx0JHRoaXMuam9iX2l0ZW1fc291cmNlID0gW107XG5cdFx0XHRcdCR0aGlzLnB1bmNoX3RhZ19zb3VyY2UgPSBbXTtcblx0XHRcdFx0JHRoaXMucHJlbWl1bV9zb3VyY2UgPSBbXTtcblx0XHRcdFx0JHRoaXMuYWNjdW11bGF0ZWRfdG90YWxfZ3JpZF9zb3VyY2UgPSBbXTtcblx0XHRcdFx0JHRoaXMudmVyaWZpY2F0aW9uX2dyaWRfc291cmNlID0gW107XG5cdFx0XHRcdCR0aGlzLm9uUmVsb2FkU3ViR3JpZFJlc3VsdCggcmVzdWx0ICk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cblx0Ly8gRGV2IE5vdGU6IFRPRE8vUkVGQUNUT1I6IHNlYXJjaCgpIHBhcmFtcyBoZXJlIGRpZmZlciBmcm9tIEJhc2VWaWV3Q29udHJvbGxlci5zZWFyY2goKSB0aGlzIGNvdWxkIGNhdXNlIGNvbmZ1c2lvbiBvciBpc3N1ZXMsXG5cdC8vIEN1cnJlbnRseSBtZWFucyBhbnkgc2VhcmNoKCkgY2FsbHMgaW4gYmFzZXZpZXcgdXNpbmcgdGhlIGNhbGxiYWNrIHBhcmFtIHdpbGwgbm90IHdvcmsgaGVyZSBpbiBUaW1lU2hlZXQuXG5cdHNlYXJjaCggc2V0RGVmYXVsdE1lbnUsIGZvcmNlICkge1xuXG5cdFx0dGhpcy5hY2N1bXVsYXRlZF90aW1lX2NlbGxzX2FycmF5ID0gW107IC8vcmVzZXQgYXJyYXkgc2luY2UgdGhlIHNlbGVjdCBjZWxsIGlzIGNsZWFuXG5cdFx0dGhpcy5wcmVtaXVtX2NlbGxzX2FycmF5ID0gW107IC8vcmVzZXQgYXJyYXkgc2luY2UgdGhlIHNlbGVjdCBjZWxsIGlzIGNsZWFuXG5cdFx0dGhpcy5hY2N1bXVsYXRlZF90aW1lX3NvdXJjZV9tYXAgPSB7fTtcblx0XHR0aGlzLmJyYW5jaF9zb3VyY2VfbWFwID0ge307XG5cdFx0dGhpcy5kZXBhcnRtZW50X3NvdXJjZV9tYXAgPSB7fTtcblx0XHR0aGlzLmpvYl9zb3VyY2VfbWFwID0ge307XG5cdFx0dGhpcy5qb2JfaXRlbV9zb3VyY2VfbWFwID0ge307XG5cdFx0dGhpcy5wdW5jaF90YWdfc291cmNlX21hcCA9IHt9O1xuXHRcdHRoaXMucHJlbWl1bV9zb3VyY2VfbWFwID0ge307XG5cdFx0dGhpcy5hY2N1bXVsYXRlZF90b3RhbF9ncmlkX3NvdXJjZV9tYXAgPSB7fTtcblx0XHR0aGlzLmFjY3VtdWxhdGVkX3RpbWVfc291cmNlID0gW107XG5cdFx0dGhpcy5icmFuY2hfc291cmNlID0gW107XG5cdFx0dGhpcy5kZXBhcnRtZW50X3NvdXJjZSA9IFtdO1xuXHRcdHRoaXMuam9iX3NvdXJjZSA9IFtdO1xuXHRcdHRoaXMuam9iX2l0ZW1fc291cmNlID0gW107XG5cdFx0dGhpcy5wdW5jaF90YWdfc291cmNlID0gW107XG5cdFx0dGhpcy5wcmVtaXVtX3NvdXJjZSA9IFtdO1xuXHRcdHRoaXMuYWJzZW5jZV9zb3VyY2UgPSBbXTtcblx0XHR0aGlzLmFjY3VtdWxhdGVkX3RvdGFsX2dyaWRfc291cmNlID0gW107XG5cdFx0dGhpcy5wdW5jaF9ub3RlX2dyaWRfc291cmNlID0gW107XG5cdFx0dGhpcy52ZXJpZmljYXRpb25fZ3JpZF9zb3VyY2UgPSBbXTtcblx0XHR0aGlzLnNlbGVjdF9jZWxsc19BcnJheSA9IFtdO1xuXHRcdHRoaXMuc2VsZWN0X3B1bmNoZXNfYXJyYXkgPSBbXTtcblx0XHR0aGlzLmJyYW5jaF9jZWxsX2NvdW50ID0gMDtcblx0XHR0aGlzLmRlcGFydG1lbnRfY2VsbF9jb3VudCA9IDA7XG5cdFx0dGhpcy5wcmVtaXVtX2NlbGxfY291bnQgPSAwO1xuXHRcdHRoaXMuam9iX2NlbGxfY291bnQgPSAwO1xuXHRcdHRoaXMudGFza19jZWxsX2NvdW50ID0gMDtcblx0XHR0aGlzLnB1bmNoX3RhZ19jZWxsX2NvdW50ID0gMDtcblx0XHR0aGlzLmFic2VuY2VfY2VsbF9jb3VudCA9IDA7XG5cdFx0dGhpcy5wdW5jaF9ub3RlX2FjY291bnQgPSAwO1xuXHRcdHRoaXMuc2VsZWN0X3B1bmNoZXNfYXJyYXkgPSBbXTtcblxuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dmFyIGZpbHRlcl9kYXRhID0gR2xvYmFsLmNvbnZlcnRMYXlvdXRGaWx0ZXJUb0FQSUZpbHRlciggdGhpcy5zZWxlY3RfbGF5b3V0ICk7XG5cdFx0dmFyIHN0YXJ0X2RhdGVfc3RyaW5nID0gKCB0aGlzLnN0YXJ0X2RhdGVfcGlja2VyICkgPyB0aGlzLnN0YXJ0X2RhdGVfcGlja2VyLmdldFZhbHVlKCkgOiAnJztcblx0XHR2YXIgdXNlcl9pZCA9IHRoaXMuZ2V0U2VsZWN0RW1wbG95ZWUoKTtcblx0XHRpZiAoICFmb3JjZSApIHtcblx0XHRcdHRoaXMuZG9OZXh0SWZOb1ZhbHVlQ2hhbmdlSW5NYW51YWxHcmlkKCBkb05leHQsIHJlc2V0ICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGRvTmV4dCgpO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIHJlc2V0KCkge1xuXHRcdFx0JCggJy5idXR0b24tcm90YXRlJyApLnJlbW92ZUNsYXNzKCAnYnV0dG9uLXJvdGF0ZScgKTtcblx0XHR9XG5cblx0XHRmdW5jdGlvbiBkb05leHQoKSB7XG5cdFx0XHRMb2NhbENhY2hlRGF0YS5sYXN0X3RpbWVzaGVldF9zZWxlY3RlZF9kYXRlID0gc3RhcnRfZGF0ZV9zdHJpbmc7XG5cdFx0XHRMb2NhbENhY2hlRGF0YS5sYXN0X3RpbWVzaGVldF9zZWxlY3RlZF91c2VyID0gJHRoaXMuZ2V0U2VsZWN0RW1wbG95ZWUoKTtcblxuXHRcdFx0aWYgKCBMb2NhbENhY2hlRGF0YS5sYXN0X3RpbWVzaGVldF9zZWxlY3RlZF91c2VyICkge1xuXHRcdFx0XHRMb2NhbENhY2hlRGF0YS5sYXN0X3RpbWVzaGVldF9zZWxlY3RlZF9zaG93X3dhZ2UgPSAoICR0aGlzLndhZ2VfYnRuICkgPyAkdGhpcy53YWdlX2J0bi5nZXRWYWx1ZSggdHJ1ZSApIDogZmFsc2U7XG5cdFx0XHRcdExvY2FsQ2FjaGVEYXRhLmxhc3RfdGltZXNoZWV0X3NlbGVjdGVkX3RpbWV6b25lID0gKCAkdGhpcy50aW1lem9uZV9idG4gKSA/ICR0aGlzLnRpbWV6b25lX2J0bi5nZXRWYWx1ZSggdHJ1ZSApIDogZmFsc2U7XG5cdFx0XHRcdGlmICggJHRoaXMudG9nZ2xlX2J1dHRvbiApIHtcblx0XHRcdFx0XHRMb2NhbENhY2hlRGF0YS5sYXN0X3RpbWVzaGVldF9zZWxlY3RlZF9wdW5jaF9tb2RlID0gJHRoaXMudG9nZ2xlX2J1dHRvbi5nZXRWYWx1ZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHZhciBhcmdzID0geyBmaWx0ZXJfZGF0YTogZmlsdGVyX2RhdGEgfTtcblx0XHRcdFx0UHJvZ3Jlc3NCYXIuc2hvd092ZXJsYXkoKTtcblx0XHRcdFx0Ly9FcnJvcjogVHlwZUVycm9yOiB0aGlzLmFwaV90aW1lc2hlZXQuZ2V0VGltZVNoZWV0RGF0YSBpcyBub3QgYSBmdW5jdGlvbiBpbiAvaW50ZXJmYWNlL2h0bWw1L2ZyYW1ld29yay9qcXVlcnkubWluLmpzP3Y9OC4wLjAtMjAxNDExMTctMTU1MTUzIGxpbmUgMiA+IGV2YWwgbGluZSAxODg1XG5cdFx0XHRcdGlmICggISR0aGlzLmFwaV90aW1lc2hlZXQgfHwgISR0aGlzLmFwaV90aW1lc2hlZXQgfHwgdHlwZW9mICggJHRoaXMuYXBpX3RpbWVzaGVldC5nZXRUaW1lU2hlZXREYXRhICkgIT09ICdmdW5jdGlvbicgKSB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCB1c2VyX2lkICkge1xuXHRcdFx0XHRcdCR0aGlzLmhhbmRsZU92ZXJyaWRlVXNlclByZWZlcmVuY2VDb29raWUoIHVzZXJfaWQgKTtcblx0XHRcdFx0XHQkdGhpcy5hcGlfdGltZXNoZWV0LmdldFRpbWVTaGVldERhdGEoIHVzZXJfaWQsIHN0YXJ0X2RhdGVfc3RyaW5nLCBhcmdzLCB7XG5cdFx0XHRcdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlc3VsdCApIHtcblx0XHRcdFx0XHRcdFx0JHRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YSA9IHJlc3VsdC5nZXRSZXN1bHQoKTtcblx0XHRcdFx0XHRcdFx0aWYgKCAkdGhpcy5mdWxsX3RpbWVzaGVldF9kYXRhID09PSB0cnVlIHx8ICEkdGhpcy5mdWxsX3RpbWVzaGVldF9kYXRhLmhhc093blByb3BlcnR5KCAndGltZXNoZWV0X2RhdGVzJyApICkge1xuXHRcdFx0XHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHQkdGhpcy5mdWxsX3RpbWVzaGVldF9kYXRhID0gJHRoaXMubWVyZ2VKb2JRdWV1ZUludG9UaW1lU2hlZXREYXRhKCAkdGhpcy5mdWxsX3RpbWVzaGVldF9kYXRhICk7XG5cdFx0XHRcdFx0XHRcdCR0aGlzLnN0YXJ0X2RhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCAkdGhpcy5mdWxsX3RpbWVzaGVldF9kYXRhLnRpbWVzaGVldF9kYXRlcy5zdGFydF9kaXNwbGF5X2RhdGUgKTtcblx0XHRcdFx0XHRcdFx0JHRoaXMuZW5kX2RhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCAkdGhpcy5mdWxsX3RpbWVzaGVldF9kYXRhLnRpbWVzaGVldF9kYXRlcy5lbmRfZGlzcGxheV9kYXRlICk7XG5cblx0XHRcdFx0XHRcdFx0JHRoaXMuYnVpbGRDYWxlbmRhcnMoKTtcblxuXHRcdFx0XHRcdFx0XHRpZiAoIHNldERlZmF1bHRNZW51ICkge1xuXHRcdFx0XHRcdFx0XHRcdCR0aGlzLnNldERlZmF1bHRNZW51KCB0cnVlICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0JHRoaXMuc2VhcmNoRG9uZSgpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGJ1aWxkVmVyaWZpY2F0aW9uR3JpZCgpIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXG5cdFx0dmFyIGNvbHVtbnMgPSBbXTtcblx0XHRpZiAoICFHbG9iYWwuaXNTZXQoIHRoaXMudmVyaWZpY2F0aW9uX2dyaWQgKSApIHtcblx0XHRcdHZhciBncmlkID0gJCggdGhpcy5lbCApLmZpbmQoICcjdmVyaWZpY2F0aW9uX2dyaWQnICk7XG5cdFx0XHRncmlkLmF0dHIoICdpZCcsIHRoaXMudWlfaWQgKyAnX3ZlcmlmaWNhdGlvbl9ncmlkJyApOyAgLy9HcmlkJ3MgaWQgaXMgU2NyaXB0TmFtZSArIF9ncmlkXG5cdFx0fVxuXHRcdHZhciBncmlkX2lkID0gdGhpcy51aV9pZCArICdfdmVyaWZpY2F0aW9uX2dyaWQnO1xuXG5cdFx0dmFyIGNvbHVtbiA9IHtcblx0XHRcdG5hbWU6ICdwYXlfcGVyaW9kJyxcblx0XHRcdGluZGV4OiAncGF5X3BlcmlvZCcsXG5cdFx0XHRsYWJlbDogJC5pMThuLl8oICdQYXkgUGVyaW9kJyApLFxuXHRcdFx0d2lkdGg6IDEwMCxcblx0XHRcdHNvcnRhYmxlOiBmYWxzZSxcblx0XHRcdHRpdGxlOiBmYWxzZVxuXHRcdH07XG5cdFx0Y29sdW1ucy5wdXNoKCBjb2x1bW4gKTtcblxuXHRcdGNvbHVtbiA9IHtcblx0XHRcdG5hbWU6ICd2ZXJpZmljYXRpb24nLFxuXHRcdFx0aW5kZXg6ICd2ZXJpZmljYXRpb24nLFxuXHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnV2luZG93JyApLFxuXHRcdFx0d2lkdGg6IDEwMCxcblx0XHRcdHNvcnRhYmxlOiBmYWxzZSxcblx0XHRcdHRpdGxlOiBmYWxzZVxuXHRcdH07XG5cdFx0Y29sdW1ucy5wdXNoKCBjb2x1bW4gKTtcblxuXHRcdGlmICggdGhpcy52ZXJpZmljYXRpb25fZ3JpZCApIHtcblx0XHRcdHRoaXMudmVyaWZpY2F0aW9uX2dyaWQudW5sb2FkKCk7XG5cdFx0XHR0aGlzLnZlcmlmaWNhdGlvbl9ncmlkID0gbnVsbDtcblx0XHRcdHRoaXMuZ3JpZF9kaWMudmVyaWZpY2F0aW9uX2dyaWQgPSBudWxsO1xuXHRcdH1cblxuXHRcdHRoaXMudmVyaWZpY2F0aW9uX2dyaWQgPSB0aGlzLmdyaWRfZGljLnZlcmlmaWNhdGlvbl9ncmlkID0gbmV3IFRUR3JpZCggZ3JpZF9pZCwge1xuXHRcdFx0aG92ZXJyb3dzOiBmYWxzZSxcblx0XHRcdG11bHRpc2VsZWN0UG9zaXRpb246ICdub25lJyxcblx0XHRcdHZlcnRpY2FsUmVzaXplOiBmYWxzZSxcblx0XHRcdG9uUmVzaXplR3JpZDogZmFsc2UsXG5cdFx0XHRoZWlnaHQ6IDAsXG5cdFx0fSwgY29sdW1ucyApO1xuXHR9XG5cblx0YnVpbGRQdW5jaE5vdGVHcmlkKCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cblx0XHR2YXIgY29sdW1ucyA9IFtdO1xuXHRcdGlmICggIUdsb2JhbC5pc1NldCggdGhpcy5wdW5jaF9ub3RlX2dyaWQgKSApIHtcblx0XHRcdHZhciBncmlkID0gJCggdGhpcy5lbCApLmZpbmQoICcjcHVuY2hfbm90ZV9ncmlkJyApO1xuXG5cdFx0XHQvL0dyaWQncyBpZCBpcyBTY3JpcHROYW1lICsgX2dyaWRcblx0XHRcdGdyaWQuYXR0ciggJ2lkJywgdGhpcy51aV9pZCArICdfcHVuY2hfbm90ZV9ncmlkJyApO1xuXHRcdH1cblxuXHRcdC8vaWYgb25seSBwdXQgb25lIGNvbHVtbiBpbiBncmlkLiBUaGVyZSBpcyBhIFVJIGJ1Z1xuXHRcdHZhciBmaXJzdF9jb2x1bW4gPSB7XG5cdFx0XHRuYW1lOiAnaW52aXNpYmxlX2NvbHVtbicsXG5cdFx0XHRpbmRleDogJ2ludmlzaWJsZV9jb2x1bW4nLFxuXHRcdFx0bGFiZWw6ICcgJyxcblx0XHRcdHdpZHRoOiAxLFxuXHRcdFx0c29ydGFibGU6IGZhbHNlLFxuXHRcdFx0dGl0bGU6IGZhbHNlLFxuXHRcdFx0aGlkZGVuOiB0cnVlXG5cdFx0fTtcblx0XHRjb2x1bW5zLnB1c2goIGZpcnN0X2NvbHVtbiApO1xuXG5cdFx0dmFyIHNlY29uZF9jb2x1bW4gPSB7XG5cdFx0XHRuYW1lOiAnbm90ZScsXG5cdFx0XHRpbmRleDogJ25vdGUnLFxuXHRcdFx0bGFiZWw6ICcgJyxcblx0XHRcdHdpZHRoOiAxMDAsXG5cdFx0XHRzb3J0YWJsZTogZmFsc2UsXG5cdFx0XHR0aXRsZTogZmFsc2UsXG5cdFx0XHRjZWxsYXR0cjogZnVuY3Rpb24oIGluZGV4LCB2YWx1ZSApIHtcblx0XHRcdFx0cmV0dXJuICd0aXRsZT1cIicgKyB2YWx1ZSArICdcIic7XG5cdFx0XHR9XG5cdFx0fTtcblx0XHRjb2x1bW5zLnB1c2goIHNlY29uZF9jb2x1bW4gKTtcblx0XHR2YXIgZ3JpZF9pZCA9IHRoaXMudWlfaWQgKyAnX3B1bmNoX25vdGVfZ3JpZCc7XG5cdFx0aWYgKCB0aGlzLnB1bmNoX25vdGVfZ3JpZCApIHtcblx0XHRcdHRoaXMucHVuY2hfbm90ZV9ncmlkLnVubG9hZCgpO1xuXHRcdFx0dGhpcy5wdW5jaF9ub3RlX2dyaWQgPSBudWxsO1xuXHRcdFx0dGhpcy5ncmlkX2RpYy5wdW5jaF9ub3RlX2dyaWQgPSBudWxsO1xuXHRcdH1cblxuXHRcdHRoaXMucHVuY2hfbm90ZV9ncmlkID0gdGhpcy5ncmlkX2RpYy5wdW5jaF9ub3RlX2dyaWQgPSBuZXcgVFRHcmlkKCBncmlkX2lkLCB7XG5cdFx0XHRob3ZlcnJvd3M6IGZhbHNlLFxuXHRcdFx0bXVsdGlzZWxlY3RQb3NpdGlvbjogJ25vbmUnLFxuXHRcdFx0dmVydGljYWxSZXNpemU6IGZhbHNlLFxuXHRcdFx0aGVpZ2h0OiAwLFxuXHRcdFx0b25SZXNpemVHcmlkOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0JHRoaXMuc2V0UHVuY2hOb3RlR3JpZFdpZHRoKCk7XG5cdFx0XHR9XG5cdFx0fSwgY29sdW1ucyApO1xuXG5cdFx0dGhpcy5zZXRHcmlkSGVhZGVyQmFyKCAncHVuY2hfbm90ZV9ncmlkJywgJ1B1bmNoIE5vdGVzJyApO1xuXG5cdFx0Ly8gc2V0R3JpZEhlYWRlckJhcigpIHNldHMgdGhlIHdpZHRoIHRvIDEwMHZ3IChhbmQgc2V0cyBncmlkIHRpdGxlKSwgYnV0IHRoaXMgY2F1c2VzIGlzc3VlIGFzIHRoZSBncmlkIGlzIG5vdCBmdWxsIHdpZHRoIG9mIHRoZSBzY3JlZW4gdW5saWtlIHRoZSBvdGhlcnMuIFRoZXJlZm9yZSwgb3ZlcmlkZSB0aGUgZGVmYXVsdCB3aWR0aCBvZiAxMDB2dyB3aXRoIDEwMCUuXG5cdFx0Ly8gUmVsYXRlZCB0byBpc3N1ZSAjMjcxMiwgYW5kICh2aWEgYmlzZWN0KSBhcHBlYXJzIHRvIGJlIGNhdXNlZCBieSA0ZTkyYzdhYjQ2M2Q5YjM0MTg3MzVjMGRiMzAyYTUwZWZjNDNlOGJmIHdoZW4ganF1ZXJ5LmpxZ3JpZC5leHRlbmQuanMgd2FzIHJlbW92ZWQgaW4gYSBKUyB1cGdyYWRlIGZpeC5cblx0XHR2YXIgdGFibGUgPSAkKCB0aGlzLmdyaWRfZGljLnB1bmNoX25vdGVfZ3JpZC5ncmlkICkucGFyZW50cyggJy51aS1qcWdyaWQtdmlldycgKS5maW5kKCAnLnVpLWpxZ3JpZC1oYm94IHRhYmxlJyApOyAvL2dyYWIgdGhlIGhib3hcblx0XHR0YWJsZS5jc3MoICd3aWR0aCcsICcxMDAlJyApO1xuXHR9XG5cblx0Z2V0QWNjdW11bGF0ZWRUb3RhbEdyaWRQYXlwZXJpb2RIZWFkZXIoKSB7XG5cdFx0dGhpcy5wYXlfcGVyaW9kX2hlYWRlciA9ICQuaTE4bi5fKCAnTm8gUGF5IFBlcmlvZCcgKTtcblxuXHRcdHZhciBwYXlfcGVyaW9kX2lkID0gdGhpcy50aW1lc2hlZXRfdmVyaWZ5X2RhdGEucGF5X3BlcmlvZF9pZDtcblxuXHRcdGlmICggcGF5X3BlcmlvZF9pZCAmJiB0aGlzLnBheV9wZXJpb2RfZGF0YSApIHtcblxuXHRcdFx0Zm9yICggdmFyIGtleSBpbiB0aGlzLnBheV9wZXJpb2RfZGF0YSApIHtcblx0XHRcdFx0dmFyIHBheV9wZXJpb2QgPSB0aGlzLnBheV9wZXJpb2RfZGF0YVtrZXldO1xuXHRcdFx0XHRpZiAoIHBheV9wZXJpb2QuaWQgPT09IHBheV9wZXJpb2RfaWQgKSB7XG5cdFx0XHRcdFx0dmFyIHN0YXJ0X2RhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCBwYXlfcGVyaW9kLnN0YXJ0X2RhdGUgKS5mb3JtYXQoKTtcblx0XHRcdFx0XHR2YXIgZW5kX2RhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCBwYXlfcGVyaW9kLmVuZF9kYXRlICkuZm9ybWF0KCk7XG5cdFx0XHRcdFx0dGhpcy5wYXlfcGVyaW9kX2hlYWRlciA9IHN0YXJ0X2RhdGUgKyAnICcgKyAkLmkxOG4uXyggJ3RvJyApICsgJyAnICsgZW5kX2RhdGU7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRidWlsZEFjY3VtdWxhdGVkVG90YWxHcmlkKCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cblx0XHR2YXIgY29sdW1ucyA9IFtdO1xuXG5cdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCB0aGlzLmFjY3VtdWxhdGVkX3RvdGFsX2dyaWQgKSApIHtcblx0XHRcdHZhciBncmlkID0gJCggdGhpcy5lbCApLmZpbmQoICcjYWNjdW11bGF0ZWRfdG90YWxfZ3JpZCcgKTtcblxuXHRcdFx0Z3JpZC5hdHRyKCAnaWQnLCB0aGlzLnVpX2lkICsgJ19hY2N1bXVsYXRlZF90b3RhbF9ncmlkJyApO1x0Ly9HcmlkJ3MgaWQgaXMgU2NyaXB0TmFtZSArIF9ncmlkXG5cblx0XHRcdGdyaWQgPSAkKCB0aGlzLmVsICkuZmluZCggJyMnICsgdGhpcy51aV9pZCArICdfYWNjdW11bGF0ZWRfdG90YWxfZ3JpZCcgKTtcblx0XHR9XG5cblx0XHR2YXIgd2lkdGggPSA1MDA7XG5cdFx0aWYgKCB0aGlzLndhZ2VfYnRuLmdldFZhbHVlKCB0cnVlICkgKSB7XG5cdFx0XHR3aWR0aCA9IDYwMDtcblx0XHR9XG5cblx0XHR2YXIgcHVuY2hfY29sdW1uX3dpZHRoID0gMTAwO1xuXHRcdGlmICggdGhpcy53YWdlX2J0bi5nZXRWYWx1ZSggdHJ1ZSApICkge1xuXHRcdFx0cHVuY2hfY29sdW1uX3dpZHRoID0gbnVsbDtcblx0XHR9XG5cblx0XHR2YXIgcHVuY2hfaW5fb3V0X2NvbHVtbiA9IHtcblx0XHRcdG5hbWU6ICdwdW5jaF9pbmZvJyxcblx0XHRcdGluZGV4OiAncHVuY2hfaW5mbycsXG5cdFx0XHRsYWJlbDogJyAnLFxuXHRcdFx0d2lkdGg6IHB1bmNoX2NvbHVtbl93aWR0aCxcblx0XHRcdHNvcnRhYmxlOiBmYWxzZSxcblx0XHRcdHRpdGxlOiBmYWxzZSxcblx0XHRcdGZvcm1hdHRlcjogdGhpcy5vbkNlbGxGb3JtYXRcblx0XHR9O1xuXHRcdGNvbHVtbnMucHVzaCggcHVuY2hfaW5fb3V0X2NvbHVtbiApO1xuXG5cdFx0dmFyIHN0YXJ0X2RhdGVfc3RyID0gdGhpcy5zdGFydF9kYXRlLmZvcm1hdCggR2xvYmFsLmdldExvZ2luVXNlckRhdGVGb3JtYXQoKSApO1xuXHRcdHZhciBlbmRfZGF0ZV9zdHIgPSB0aGlzLmVuZF9kYXRlLmZvcm1hdCggR2xvYmFsLmdldExvZ2luVXNlckRhdGVGb3JtYXQoKSApO1xuXG5cdFx0dGhpcy5nZXRBY2N1bXVsYXRlZFRvdGFsR3JpZFBheXBlcmlvZEhlYWRlcigpO1xuXG5cdFx0dmFyIGNvbHVtbl93aWR0aCA9IDEwMDtcblx0XHRpZiAoIHRoaXMud2FnZV9idG4uZ2V0VmFsdWUoIHRydWUgKSApIHtcblx0XHRcdGNvbHVtbl93aWR0aCA9IDE1MDtcblx0XHR9XG5cdFx0dmFyIGNvbHVtbl8xID0ge1xuXHRcdFx0bmFtZTogJ3dlZWsnLFxuXHRcdFx0aW5kZXg6ICd3ZWVrJyxcblx0XHRcdGxhYmVsOiBzdGFydF9kYXRlX3N0ciArICcgJyArICQuaTE4bi5fKCAndG8nICkgKyAnICcgKyBlbmRfZGF0ZV9zdHIsXG5cdFx0XHR3aWR0aDogY29sdW1uX3dpZHRoLFxuXHRcdFx0c29ydGFibGU6IGZhbHNlLFxuXHRcdFx0dGl0bGU6IGZhbHNlLFxuXHRcdFx0Zm9ybWF0dGVyOiB0aGlzLm9uQ2VsbEZvcm1hdFxuXHRcdH07XG5cdFx0dmFyIGNvbHVtbl8yID0ge1xuXHRcdFx0bmFtZTogJ3BheV9wZXJpb2QnLFxuXHRcdFx0aW5kZXg6ICdwYXlfcGVyaW9kJyxcblx0XHRcdGxhYmVsOiB0aGlzLnBheV9wZXJpb2RfaGVhZGVyLFxuXHRcdFx0d2lkdGg6IGNvbHVtbl93aWR0aCxcblx0XHRcdHNvcnRhYmxlOiBmYWxzZSxcblx0XHRcdHRpdGxlOiBmYWxzZSxcblx0XHRcdGZvcm1hdHRlcjogdGhpcy5vbkNlbGxGb3JtYXRcblx0XHR9O1xuXG5cdFx0Y29sdW1ucy5wdXNoKCBjb2x1bW5fMSApO1xuXHRcdGNvbHVtbnMucHVzaCggY29sdW1uXzIgKTtcblxuXHRcdHZhciBncmlkX2lkID0gdGhpcy51aV9pZCArICdfYWNjdW11bGF0ZWRfdG90YWxfZ3JpZCc7XG5cdFx0aWYgKCBHbG9iYWwuaXNTZXQoIHRoaXMuYWNjdW11bGF0ZWRfdG90YWxfZ3JpZCApID09IHRydWUgKSB7XG5cdFx0XHR0aGlzLmFjY3VtdWxhdGVkX3RvdGFsX2dyaWQudW5sb2FkKCk7XG5cdFx0XHR0aGlzLmFjY3VtdWxhdGVkX3RvdGFsX2dyaWQgPSBudWxsO1xuXHRcdFx0dGhpcy5ncmlkX2RpYy5hY2N1bXVsYXRlZF90b3RhbF9ncmlkID0gbnVsbDtcblx0XHR9XG5cblx0XHR0aGlzLmFjY3VtdWxhdGVkX3RvdGFsX2dyaWQgPSB0aGlzLmdyaWRfZGljLmFjY3VtdWxhdGVkX3RvdGFsX2dyaWQgPSBuZXcgVFRHcmlkKCBncmlkX2lkLCB7XG5cdFx0XHRob3ZlcnJvd3M6IGZhbHNlLFxuXHRcdFx0bXVsdGlzZWxlY3RQb3NpdGlvbjogJ25vbmUnLFxuXHRcdFx0dmVydGljYWxSZXNpemU6IGZhbHNlLFxuXHRcdFx0b25SZXNpemVHcmlkOiBmYWxzZSxcblx0XHRcdHdpZHRoOiB3aWR0aCxcblx0XHRcdGhlaWdodDogMCxcblx0XHR9LCBjb2x1bW5zICk7XG5cblx0XHR2YXIgYWNjdW11bGF0ZWRfdG90YWxfZ3JpZF90aXRsZSA9ICQoIHRoaXMuZWwgKS5maW5kKCAnLmFjY3VtdWxhdGVkLXRvdGFsLWdyaWQtdGl0bGUnICk7XG5cdFx0YWNjdW11bGF0ZWRfdG90YWxfZ3JpZF90aXRsZS5jc3MoICdkaXNwbGF5JywgJ2Jsb2NrJyApO1xuXHRcdHRoaXMuc2V0QWNjdW11bGF0ZWRUb3RhbEdyaWRQYXlQZXJpb2RIZWFkZXJzKCB3aWR0aCApO1xuXHR9XG5cblx0Ly9PdmVycmlkZSBhbmQgZGlzYWJsZSBhcyBiaW5kVGltZVNoZWV0R3JpZENvbHVtbkV2ZW50cygpIGlzIHVzZWQgYXQgYSBkaWZmZXJlbnQgcG9pbnQgaW5zdGVhZC5cblx0YmluZEdyaWRDb2x1bW5FdmVudHMoKSB7XG5cdH1cblxuXHQvL0JpbmQgY29sdW1uIGNsaWNrIGV2ZW50IHRvIGNoYW5nZSBzb3J0IHR5cGUgYW5kIHNhdmUgY29sdW1ucyB0byB0X2dyaWRfaGVhZGVyX2FycmF5IHRvIHVzZSB0byBzZXQgY29sdW1uIHN0eWxlIChhc2Mgb3IgZGVzYylcblx0YmluZFRpbWVTaGVldEdyaWRDb2x1bW5FdmVudHMoKSB7XG5cdFx0dmFyIGRpc3BsYXlfY29sdW1ucyA9IHRoaXMuZ3JpZC5nZXRHcmlkUGFyYW0oICdjb2xNb2RlbCcgKTtcblxuXHRcdC8vRXhjZXB0aW9uIHRhaHQgZGlzcGxheSBjb2x1bW4gbm90IGV4aXN0ZWQsIG5vdCBzdXJlIHdoZW4gdGhpcyB3aWxsIGhhcHBlbiwgYnV0IG1heSB0aGVyZSB3aWxsIGJlIGEgc2Vjb25kIHRpbWUgbG9hZCBpZiB0aGlzIGhhcHBlblxuXHRcdGlmICggIWRpc3BsYXlfY29sdW1ucyApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgbGVuID0gZGlzcGxheV9jb2x1bW5zLmxlbmd0aDtcblxuXHRcdHRoaXMudF9ncmlkX2hlYWRlcl9hcnJheSA9IFtdO1xuXG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHR2YXIgY29sdW1uX2luZm8gPSBkaXNwbGF5X2NvbHVtbnNbaV07XG5cdFx0XHR2YXIgY29sdW1uX2hlYWRlciA9ICQoICQoIHRoaXMuZWwgKS5maW5kKCAnI2dib3hfJyArIHRoaXMudWlfaWQgKyAnX2dyaWQnICkuZmluZCggJ2RpdiAjanFnaF8nICsgdGhpcy51aV9pZCArICdfZ3JpZF8nICsgY29sdW1uX2luZm8ubmFtZSApICk7XG5cblx0XHRcdHRoaXMudF9ncmlkX2hlYWRlcl9hcnJheS5wdXNoKCBjb2x1bW5faGVhZGVyLlRHcmlkSGVhZGVyKCkgKTtcblx0XHRcdGNvbHVtbl9oZWFkZXIuYmluZCggJ2NsaWNrJywgb25Db2x1bW5IZWFkZXJDbGljayApO1xuXHRcdH1cblxuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cblx0XHRmdW5jdGlvbiBvbkNvbHVtbkhlYWRlckNsaWNrKCBlICkge1xuXHRcdFx0dmFyIGZpZWxkID0gJCggdGhpcyApLmF0dHIoICdpZCcgKTtcblx0XHRcdGZpZWxkID0gZmllbGQuc3Vic3RyaW5nKCAxMCArICR0aGlzLnVpX2lkLmxlbmd0aCArIDEsIGZpZWxkLmxlbmd0aCApO1xuXG5cdFx0XHRpZiAoIGZpZWxkID09PSAnY2InIHx8IGZpZWxkID09PSAncHVuY2hfaW5mbycgKSB7IC8vZmlyc3QgY29sdW1uLCBjaGVjayBib3ggY29sdW1uLlxuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdHZhciBkYXRlID0gR2xvYmFsLnN0clRvRGF0ZSggZmllbGQsICR0aGlzLmZ1bGxfZm9ybWF0ICk7XG5cblx0XHRcdGlmICggZGF0ZSAmJiBkYXRlLmdldFllYXIoKSA+IDAgKSB7XG5cdFx0XHRcdCR0aGlzLnNldERhdGVQaWNrZXJWYWx1ZSggZGF0ZS5mb3JtYXQoIEdsb2JhbC5nZXRMb2dpblVzZXJEYXRlRm9ybWF0KCkgKSApO1xuXHRcdFx0XHQkdGhpcy5oaWdoTGlnaHRTZWxlY3REYXkoKTtcblx0XHRcdFx0Ly9yZUxvYWRTdWJHcmlkc1NvdXJjZSgpIGNhbGxzIGdldFRpbWVTaGVldFRvdGFsRGF0YSBhbmQgd291bGQgY2F1c2UgZHVwbGljYXRlIEFQSSByZXF1ZXN0cy5cblx0XHRcdFx0Ly9UaGUgcmVMb2FkU3ViR3JpZHNTb3VyY2UgY2FsbCBpcyBub3QgbmVlZGVkIHJlcXVpcmVkIGhlcmUsIGJlY2F1c2UgaXQgd2lsbCBiZSBjYWxsZWQgaW4gb25DZWxsU2VsZWN0KCkgd2hpY2ggaXMgdHJpZ2dlcmVkIGZyb20gdGhlIGNsaWNrIGV2ZW50IGJlbG93LlxuXHRcdFx0XHQvLyAkdGhpcy5yZUxvYWRTdWJHcmlkc1NvdXJjZSgpO1xuXHRcdFx0XHQvL3NlbGVjdCBmaXJzdCBwdW5jaCBjZWxsIHdoZW4gY2xpY2tpbmcgdGhlIGhlYWRlciByb3dcblx0XHRcdFx0JCggJCggJy50aW1lc2hlZXQtZ3JpZCB0ciMxIHRkJyApWyQoICd0aC5oaWdobGlnaHQtaGVhZGVyJyApLmluZGV4KCldICkuY2xpY2soKTtcblx0XHRcdH1cblxuXHRcdH1cblx0fVxuXG5cdGNoZWNrSXNTZWxlY3RlZEFic2VuY2VDZWxsKCByb3dfaWQsIGNlbGxfaW5kZXggKSB7XG5cdFx0Zm9yICggdmFyIGkgPSAwLCBtID0gdGhpcy5hYnNlbmNlX3NlbGVjdF9jZWxsc19BcnJheS5sZW5ndGg7IGkgPCBtOyBpKysgKSB7XG5cdFx0XHR2YXIgY2VsbCA9IHRoaXMuYWJzZW5jZV9zZWxlY3RfY2VsbHNfQXJyYXlbaV07XG5cdFx0XHRpZiAoIGNlbGwucm93X2lkID09IHJvd19pZCAmJiBjZWxsLmNlbGxfaW5kZXggPT09IGNlbGxfaW5kZXggKSB7XG5cdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdGJ1aWxkQWJzZW5jZUdyaWQoKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdHZhciBncmlkX2lkID0gJ2Fic2VuY2VfZ3JpZCc7XG5cdFx0dmFyIHRpdGxlID0gJC5pMThuLl8oICdBYnNlbmNlJyApO1xuXG5cdFx0aWYgKCB0aGlzW2dyaWRfaWRdICkge1xuXHRcdFx0dGhpc1tncmlkX2lkXS51bmxvYWQoKTtcblx0XHRcdHRoaXNbZ3JpZF9pZF0gPSBudWxsO1xuXHRcdFx0dGhpcy5ncmlkX2RpY1tncmlkX2lkXSA9IG51bGw7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHZhciBncmlkID0gJCggdGhpcy5lbCApLmZpbmQoICcjYWJzZW5jZV9ncmlkJyApO1xuXG5cdFx0XHRncmlkLmF0dHIoICdpZCcsIHRoaXMudWlfaWQgKyAnX2Fic2VuY2VfZ3JpZCcgKTsgIC8vR3JpZCdzIGlkIGlzIFNjcmlwdE5hbWUgKyBfZ3JpZFxuXG5cdFx0XHRncmlkID0gJCggdGhpcy5lbCApLmZpbmQoICcjJyArIHRoaXMudWlfaWQgKyAnX2Fic2VuY2VfZ3JpZCcgKTtcblx0XHR9XG5cblx0XHR0aGlzW2dyaWRfaWRdID0gdGhpcy5ncmlkX2RpY1tncmlkX2lkXSA9IG5ldyBUVEdyaWQoIHRoaXMudWlfaWQgKyAnX2Fic2VuY2VfZ3JpZCcsIHtcblx0XHRcdHNvcnRhYmxlOiBmYWxzZSxcblx0XHRcdGhvdmVycm93czogZmFsc2UsXG5cdFx0XHRoZWlnaHQ6IDAsIC8vU3RhcnQgdGhlIGdyaWQgaGVpZ2h0IGF0IDAgaW5zdGVhZCBvZiBwYXJlbnQgaGVpZ2h0IHRvIGF2b2lkIHRyYW5zaWVudCBzY3JvbGxiYXJzIGZyb20gY2F1c2luZyB0aGUgd2lkdGggdG8gYmUgaW5jb25zaXN0ZW50IGFjcm9zcyB0YWJsZXMuXG5cdFx0XHRvbmRibENsaWNrUm93OiBmdW5jdGlvbigpIHtcblx0XHRcdFx0JHRoaXMub25HcmlkRGJsQ2xpY2tSb3coICdhYnNlbmNlJyApO1xuXHRcdFx0fSxcblx0XHRcdG9uUmlnaHRDbGlja1JvdzogZnVuY3Rpb24oIHJvd19pZCwgaVJvdywgY2VsbF9pbmRleCwgZSApIHtcblx0XHRcdFx0aWYgKCAhJHRoaXMuY2hlY2tJc1NlbGVjdGVkQWJzZW5jZUNlbGwoIHJvd19pZCwgY2VsbF9pbmRleCApICkge1xuXHRcdFx0XHRcdHZhciBjZWxsX3ZhbCA9ICQoIGUudGFyZ2V0ICkuY2xvc2VzdCggJ3RkLHRoJyApLmh0bWwoKTtcblx0XHRcdFx0XHQkdGhpcy5vbkNlbGxTZWxlY3QoICdhYnNlbmNlX2dyaWQnLCByb3dfaWQsIGNlbGxfaW5kZXgsIGNlbGxfdmFsLCB0aGlzLCBlICk7XG5cdFx0XHRcdFx0JHRoaXMub25TZWxlY3RSb3coICdhYnNlbmNlX2dyaWQnLCByb3dfaWQsIHRoaXMgKTtcblxuXHRcdFx0XHRcdGlmICggJCggJy5lZGl0LXZpZXc6dmlzaWJsZScgKS5sZW5ndGggPT0gMCApIHtcblx0XHRcdFx0XHRcdCR0aGlzLnNldERlZmF1bHRNZW51KCk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdCR0aGlzLnNldEVkaXRNZW51KCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0b25DZWxsU2VsZWN0OiBmdW5jdGlvbiggcm93X2lkLCBjZWxsX2luZGV4LCBjZWxsX3ZhbCwgZSApIHtcblx0XHRcdFx0aWYgKCAkKCAnLmVkaXQtdmlldzp2aXNpYmxlJyApLmxlbmd0aCA9PSAwICkge1xuXHRcdFx0XHRcdCR0aGlzLnNldERlZmF1bHRNZW51KCk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JHRoaXMuc2V0RWRpdE1lbnUoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdG9uUmVzaXplR3JpZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggJHRoaXMuYWJzZW5jZV9ncmlkICYmICR0aGlzLmFic2VuY2VfZ3JpZC5nZXRHcmlkV2lkdGgoKSAhPSAkdGhpcy5nZXRUaW1lU2hlZXRXaWR0aCgpICkge1xuXHRcdFx0XHRcdCR0aGlzLmFic2VuY2VfZ3JpZC5zZXRHcmlkV2lkdGgoICR0aGlzLmdldFRpbWVTaGVldFdpZHRoKCkgKTtcblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdGJlZm9yZVNlbGVjdFJvdzogZnVuY3Rpb24oIHJvd19pZCwgZSApIHtcblx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHRcdHZhciBjZWxsX2luZGV4ID0gMDtcblx0XHRcdFx0aWYgKCAkKCBlLnRhcmdldCApLmF0dHIoICdyb2xlJyApID09ICdncmlkY2VsbCcgKSB7XG5cdFx0XHRcdFx0Y2VsbF9pbmRleCA9ICQoIGUudGFyZ2V0ICkuaW5kZXgoKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRjZWxsX2luZGV4ID0gJCggZS50YXJnZXQgKS5wYXJlbnRzKCAndGQnICkuaW5kZXgoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHZhciBjZWxsX3ZhbCA9ICQoIGUudGFyZ2V0ICkudGV4dCgpO1xuXG5cdFx0XHRcdCR0aGlzLm9uQ2VsbFNlbGVjdCggJ2Fic2VuY2VfZ3JpZCcsIHJvd19pZCwgY2VsbF9pbmRleCwgY2VsbF92YWwsIHRoaXMsIGUgKTtcblx0XHRcdFx0JHRoaXMub25TZWxlY3RSb3coICdhYnNlbmNlX2dyaWQnLCByb3dfaWQsIHRoaXMgKTtcblxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9LFxuXHRcdFx0bXVsdGlzZWxlY3RQb3NpdGlvbjogJ25vbmUnLFxuXHRcdFx0d2luTXVsdGlTZWxlY3Q6IGZhbHNlLFxuXHRcdFx0dmVydGljYWxSZXNpemU6IGZhbHNlXG5cblx0XHR9LCB0aGlzLnRpbWVzaGVldF9jb2x1bW5zLCAkLmkxOG4uXyggJ0Fic2VuY2UnICkgKTtcblxuXHRcdHRoaXMuYmluZFRpbWVTaGVldEdyaWRDb2x1bW5FdmVudHMoKTtcblx0XHR0aGlzLnNldEdyaWRIZWFkZXJCYXIoIGdyaWRfaWQsIHRpdGxlICk7XG5cblx0XHRpZiAoIHRoaXMuZ3JpZF9kaWNbZ3JpZF9pZF0gJiYgdGhpcy5ncmlkX2RpY1tncmlkX2lkXS5ncmlkICkge1xuXHRcdFx0dGhpcy5ncmlkX2RpYy5hYnNlbmNlX2dyaWQuZ3JpZC5zZXRHcmlkV2lkdGgoIHRoaXMuZ2V0VGltZVNoZWV0V2lkdGgoKSApO1xuXHRcdH1cblx0fVxuXG5cdGNoZWNrSXNTZWxlY3RlZFB1bmNoQ2VsbCggcm93X2lkLCBjZWxsX2luZGV4ICkge1xuXHRcdGZvciAoIHZhciBpID0gMCwgbSA9IHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5Lmxlbmd0aDsgaSA8IG07IGkrKyApIHtcblx0XHRcdHZhciBjZWxsID0gdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXlbaV07XG5cdFx0XHRpZiAoIGNlbGwucm93X2lkID09IHJvd19pZCAmJiBjZWxsLmNlbGxfaW5kZXggPT0gY2VsbF9pbmRleCApIHtcblx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0LyoqXG5cdCAqIFBhaXJlZCBzZWNvbmRhcnkgcm93IGNvbG9yaW5nIGZvciB0aW1lc2hlZXRcblx0ICovXG5cdGNvbG9yVGltZVNoZWV0Um93cygpIHtcblx0XHR2YXIgJHRycyA9ICQoICcudGltZXNoZWV0LWdyaWQtZGl2IC50aW1lc2hlZXQtZ3JpZCB0cicgKTtcblx0XHR2YXIgc2tpcHMgPSAwO1xuXHRcdHZhciBjb2xvcmVkID0gMDtcblx0XHRmb3IgKCB2YXIgaSA9IDE7IGkgPCAkdHJzLmxlbmd0aCAtIDE7IGkrKyApIHtcblx0XHRcdGlmICggc2tpcHMgPT0gMiAmJiBjb2xvcmVkIDwgMiApIHtcblx0XHRcdFx0JCggJHRyc1tpXSApLmFkZENsYXNzKCAndWktcHJpb3JpdHktc2Vjb25kYXJ5JyApO1xuXHRcdFx0XHRjb2xvcmVkKys7XG5cdFx0XHR9IGVsc2UgaWYgKCBjb2xvcmVkID09IDIgKSB7XG5cdFx0XHRcdHNraXBzID0gMTsgLy9SZXNldHMgdG8gMSBiZWNhdXNlIHdlJ3JlIHNraXBwaW5nIHRoaXMgaXRlcmF0aW9uLlxuXHRcdFx0XHRjb2xvcmVkID0gMDtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHNraXBzKys7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0YnVpbGRUaW1lU2hlZXRHcmlkKCkge1xuXHRcdHZhciBncmlkX2lkID0gdGhpcy51aV9pZCArICdfZ3JpZCc7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdGlmICggdGhpcy50aW1lc2hlZXRfZ3JpZCAmJiAhdGhpcy5maXJzdF9idWlsZCApIHtcblx0XHRcdCQuamdyaWQuZ3VpZCA9IDE7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGlmICggdGhpcy50aW1lc2hlZXRfZ3JpZCApIHtcblx0XHRcdFx0dGhpcy50aW1lc2hlZXRfZ3JpZC51bmxvYWQoKTtcblx0XHRcdFx0dGhpcy50aW1lc2hlZXRfZ3JpZCA9IG51bGw7XG5cdFx0XHRcdCQuamdyaWQuZ3VpZCA9IDE7XG5cdFx0XHR9XG5cdFx0XHR2YXIgZ3JpZCA9ICQoIHRoaXMuZWwgKS5maW5kKCAnI3RpbWVzaGVldF9ncmlkJyApO1xuXHRcdFx0Z3JpZC5hdHRyKCAnaWQnLCBncmlkX2lkICk7XHQvL0dyaWQncyBpZCBpcyBTY3JpcHROYW1lICsgX2dyaWRcblxuXHRcdFx0dmFyIGdyaWRfc2V0dXBfZGF0YSA9IHtcblx0XHRcdFx0Y29udGFpbmVyX3NlbGVjdG9yOiAnLmNvbnRleHQtYm9yZGVyJyxcblx0XHRcdFx0YWx0Um93czogZmFsc2UsXG5cdFx0XHRcdHNvcnRhYmxlOiBmYWxzZSxcblx0XHRcdFx0aG92ZXJyb3dzOiBmYWxzZSxcblx0XHRcdFx0aGVpZ2h0OiAwLCAvL1N0YXJ0IHRoZSBncmlkIGhlaWdodCBhdCAwIGluc3RlYWQgb2YgcGFyZW50IGhlaWdodCB0byBhdm9pZCB0cmFuc2llbnQgc2Nyb2xsYmFycyBmcm9tIGNhdXNpbmcgdGhlIHdpZHRoIHRvIGJlIGluY29uc2lzdGVudCBhY3Jvc3MgdGFibGVzLlxuXHRcdFx0XHRvbmRibENsaWNrUm93OiBmdW5jdGlvbiggcm93X2lkLCByb3dfaW5kZXgsIGNlbGxfaW5kZXgsIGUgKSB7XG5cdFx0XHRcdFx0dmFyIHJvdyA9ICR0aGlzLmdldFJvd0RhdGEoICd0aW1lc2hlZXRfZ3JpZCcsIHJvd19pZCApO1xuXG5cdFx0XHRcdFx0Ly9NYWtlIHN1cmUgZG91YmxlIGNsaWNrIGV2ZW50IGRvZXNuJ3QgZ2V0IHRyaWdnZXJlZCBvbiBhIHJlcXVlc3Qgcm93IChhdXRob3JpemVkL3BlbmRpbmcvZGVjbGluZWQpXG5cdFx0XHRcdFx0Ly8gYXMgd2UgYXJlIGFscmVhZHkgaW4gdGhlIHByb2Nlc3Mgb2YgbmF2aWdhdGluZyB0byB0aGF0IHZpZXcsIHNvIGl0IGNhdXNlcyBlZGl0IHZpZXcgYW5kIG5hdmlnYXRpb24gb3BlcmF0aW9ucyB0byBvY2N1ciBhdCB0aGUgc2FtZSB0aW1lLlxuXHRcdFx0XHRcdGlmICggcm93LnR5cGUgIT09IFRpbWVTaGVldFZpZXdDb250cm9sbGVyLlJFUVVFU1RfUk9XICkge1xuXHRcdFx0XHRcdFx0JHRoaXMub25HcmlkRGJsQ2xpY2tSb3coKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdG9uUmlnaHRDbGlja1JvdzogZnVuY3Rpb24oIHJvd19pZCwgaVJvdywgY2VsbF9pbmRleCwgZSApIHtcblx0XHRcdFx0XHRpZiAoICEkdGhpcy5jaGVja0lzU2VsZWN0ZWRQdW5jaENlbGwoIHJvd19pZCwgY2VsbF9pbmRleCApICkge1xuXHRcdFx0XHRcdFx0dmFyIGNlbGxfdmFsID0gJCggZS50YXJnZXQgKS5jbG9zZXN0KCAndGQsdGgnICkuaHRtbCgpO1xuXHRcdFx0XHRcdFx0JHRoaXMub25DZWxsU2VsZWN0KCAndGltZXNoZWV0X2dyaWQnLCByb3dfaWQsIGNlbGxfaW5kZXgsIGNlbGxfdmFsLCB0aGlzLCBlICk7XG5cdFx0XHRcdFx0XHQkdGhpcy5vblNlbGVjdFJvdyggJ3RpbWVzaGVldF9ncmlkJywgcm93X2lkLCB0aGlzICk7XG5cblx0XHRcdFx0XHRcdGlmICggJCggJy5lZGl0LXZpZXc6dmlzaWJsZScgKS5sZW5ndGggPT0gMCApIHtcblx0XHRcdFx0XHRcdFx0JHRoaXMuc2V0RGVmYXVsdE1lbnUoKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdCR0aGlzLnNldEVkaXRNZW51KCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRvbkNlbGxTZWxlY3Q6IGZ1bmN0aW9uKCByb3dfaWQsIGNlbGxfaW5kZXgsIGNlbGxfdmFsLCBlICkge1xuXHRcdFx0XHRcdGlmICggJCggJy5lZGl0LXZpZXc6dmlzaWJsZScgKS5sZW5ndGggPT0gMCApIHtcblx0XHRcdFx0XHRcdCR0aGlzLnNldERlZmF1bHRNZW51KCk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdCR0aGlzLnNldEVkaXRNZW51KCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRvblJlc2l6ZUdyaWQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGlmICggJHRoaXMuZ2V0UHVuY2hNb2RlKCkgPT09ICdtYW51YWwnICkge1xuXHRcdFx0XHRcdFx0aWYgKCAkdGhpcy5lZGl0b3IgKSB7XG5cdFx0XHRcdFx0XHRcdCR0aGlzLnNldE1hbnVhbFRpbWVTaGVldEdyaWRTaXplKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0JHRoaXMuc2V0R3JpZFNpemUoKTtcblx0XHRcdFx0XHQkdGhpcy5zZXRUaW1lU2hlZXRHcmlkUGF5UGVyaW9kSGVhZGVycygpO1xuXHRcdFx0XHRcdCR0aGlzLnNldFRpbWVTaGVldEdyaWRIb2xpZGF5SGVhZGVycygpO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRncmlkQ29tcGxldGU6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdCR0aGlzLmNvbG9yVGltZVNoZWV0Um93cygpO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRiZWZvcmVTZWxlY3RSb3c6IGZ1bmN0aW9uKCByb3dfaWQsIGUgKSB7XG5cdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHRcdFx0dmFyIGNlbGxfaW5kZXggPSAwO1xuXHRcdFx0XHRcdGlmICggJCggZS50YXJnZXQgKS5hdHRyKCAncm9sZScgKSA9PSAnZ3JpZGNlbGwnICkge1xuXHRcdFx0XHRcdFx0Y2VsbF9pbmRleCA9ICQoIGUudGFyZ2V0ICkuaW5kZXgoKTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0Y2VsbF9pbmRleCA9ICQoIGUudGFyZ2V0ICkucGFyZW50cyggJ3RkJyApLmluZGV4KCk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0dmFyIGNlbGxfdmFsID0gJCggZS50YXJnZXQgKS50ZXh0KCk7XG5cblx0XHRcdFx0XHQkdGhpcy5vbkNlbGxTZWxlY3QoICd0aW1lc2hlZXRfZ3JpZCcsIHJvd19pZCwgY2VsbF9pbmRleCwgY2VsbF92YWwsIHRoaXMsIGUgKTtcblx0XHRcdFx0XHQkdGhpcy5vblNlbGVjdFJvdyggJ3RpbWVzaGVldF9ncmlkJywgcm93X2lkLCB0aGlzICk7XG5cblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdG11bHRpc2VsZWN0UG9zaXRpb246ICdub25lJyxcblx0XHRcdFx0d2luTXVsdGlTZWxlY3Q6IGZhbHNlLFxuXHRcdFx0XHR2ZXJ0aWNhbFJlc2l6ZTogZmFsc2Vcblx0XHRcdH07XG5cblx0XHRcdHRoaXMudGltZXNoZWV0X2dyaWQgPSB0aGlzLmdyaWRfZGljLnRpbWVzaGVldF9ncmlkID0gdGhpcy5ncmlkID0gbmV3IFRUR3JpZCggZ3JpZF9pZCwgZ3JpZF9zZXR1cF9kYXRhLCB0aGlzLnRpbWVzaGVldF9jb2x1bW5zICk7XG5cdFx0XHR0aGlzLmdyaWRfZGljLnRpbWVzaGVldF9ncmlkLmdyaWQuc2V0R3JpZFdpZHRoKCB0aGlzLmdldFRpbWVTaGVldFdpZHRoKCkgKTtcblx0XHR9XG5cblx0XHR0aGlzLmdyaWRfZGl2LnNjcm9sbCggZnVuY3Rpb24oIGUgKSB7XG5cdFx0XHQkdGhpcy5zY3JvbGxfcG9zaXRpb24gPSAkdGhpcy5ncmlkX2Rpdi5zY3JvbGxUb3AoKTtcblx0XHR9ICk7XG5cdH1cblxuXHRvbkdyaWREYmxDbGlja1JvdyggbmFtZSApIHtcblx0XHR2YXIgY29udGV4dF9tZW51X2FycmF5ID0gQ29udGV4dE1lbnVNYW5hZ2VyLmdldE1lbnVNb2RlbEJ5TWVudUlkKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQgKTtcblx0XHR2YXIgbGVuID0gY29udGV4dF9tZW51X2FycmF5Lmxlbmd0aDtcblx0XHR2YXIgbmVlZF9icmVhayA9IGZhbHNlO1xuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0aWYgKCBuZWVkX2JyZWFrICkge1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHRcdGxldCBpZCA9IGNvbnRleHRfbWVudV9hcnJheVtpXS5pZDtcblx0XHRcdHN3aXRjaCAoIGlkICkge1xuXHRcdFx0XHRjYXNlICdlZGl0Jzpcblx0XHRcdFx0XHRpZiAoICFjb250ZXh0X21lbnVfYXJyYXlbaV0uZGlzYWJsZWQgJiYgY29udGV4dF9tZW51X2FycmF5W2ldLnZpc2libGUgKSB7XG5cdFx0XHRcdFx0XHRQcm9ncmVzc0Jhci5zaG93T3ZlcmxheSgpO1xuXHRcdFx0XHRcdFx0dGhpcy5vbkVkaXRDbGljaygpO1xuXHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHR9XG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRpZiAoIG5lZWRfYnJlYWsgKSB7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdFx0bGV0IGlkID0gY29udGV4dF9tZW51X2FycmF5W2ldLmlkO1xuXHRcdFx0c3dpdGNoICggaWQgKSB7XG5cdFx0XHRcdGNhc2UgJ3ZpZXcnOlxuXHRcdFx0XHRcdG5lZWRfYnJlYWsgPSB0cnVlO1xuXHRcdFx0XHRcdGlmICggIWNvbnRleHRfbWVudV9hcnJheVtpXS5kaXNhYmxlZCAmJiBjb250ZXh0X21lbnVfYXJyYXlbaV0udmlzaWJsZSApIHtcblx0XHRcdFx0XHRcdFByb2dyZXNzQmFyLnNob3dPdmVybGF5KCk7XG5cdFx0XHRcdFx0XHR0aGlzLm9uVmlld0NsaWNrKCk7XG5cdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdGxldCBpZCA9IGNvbnRleHRfbWVudV9hcnJheVtpXS5pZDtcblx0XHRcdHN3aXRjaCAoIGlkICkge1xuXHRcdFx0XHRjYXNlICdhZGRfYWJzZW5jZSc6XG5cdFx0XHRcdGNhc2UgJ2FkZCc6XG5cdFx0XHRcdGNhc2UgJ2FkZF9wdW5jaCc6XG5cdFx0XHRcdFx0Ly8gVGhlcmUgYXJlIDIgYWRkIGljb25zLCBvbmUgZm9yIHB1bmNoIGFuZCBvbmUgZm9yIGFic2VuY2UuXG5cdFx0XHRcdFx0Ly8gV2UgbXVzdCBlbnN1cmUgdG8gY2hlY2sgdGhlIHJpZ2h0IG9uZSB0byBwcm92aWRlIHBlcm1pc3Npb25zIGZvciB0aGUgYWRkIGNsaWNrIG9yIGFic2VuY2Ugd2lsbCBiZSBhbGxvd2VkIGJhc2VkIG9uIHRoZSBwdW5jaCBwZXJtaXNzaW9uc1xuXHRcdFx0XHRcdGlmICggbmFtZSA9PSAnYWJzZW5jZScgJiYgaWQgIT0gJ2FkZF9hYnNlbmNlJyApIHtcblx0XHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICggIWNvbnRleHRfbWVudV9hcnJheVtpXS5kaXNhYmxlZCAmJiBjb250ZXh0X21lbnVfYXJyYXlbaV0udmlzaWJsZSApIHtcblx0XHRcdFx0XHRcdGlmICggdGhpcy5pc1B1bmNoQ2VsbHMoKSApIHtcblx0XHRcdFx0XHRcdFx0UHJvZ3Jlc3NCYXIuc2hvd092ZXJsYXkoKTtcblx0XHRcdFx0XHRcdFx0dGhpcy5vbkFkZENsaWNrKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRpZiAoICF0aGlzLmFkZFBlcm1pc3Npb25WYWxpZGF0ZSggJ3B1bmNoJyApICkge1xuXHRcdFx0Ly9SZWd1bGFyIGVtcGxveWVlcyBvcGVuIEluL091dCB2aWV3IHdoZW4gY2xpY2tpbmcgYSB0aW1lc2hlZXQgY2VsbC5cblx0XHRcdE1lbnVNYW5hZ2VyLm9wZW5TZWxlY3RWaWV3KCAnSW5PdXQnICk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHR9XG5cblx0aXNQdW5jaENlbGxzKCkge1xuXHRcdHZhciByZXN1bHQgPSBmYWxzZTtcblx0XHR2YXIgY2VsbCA9IHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5ICYmIHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5Lmxlbmd0aCA+IDAgJiYgdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXlbMF07XG5cdFx0dmFyIHJvdyA9IGNlbGwgJiYgdGhpcy50aW1lc2hlZXRfZGF0YV9zb3VyY2VbcGFyc2VJbnQoIGNlbGwucm93X2lkICkgLSAxXTtcblx0XHRpZiAoIHJvdyAmJiByb3cudHlwZSA9PT0gVGltZVNoZWV0Vmlld0NvbnRyb2xsZXIuUFVOQ0hfUk9XICkge1xuXHRcdFx0cmVzdWx0ID0gdHJ1ZTtcblx0XHR9IGVsc2UgaWYgKCB0aGlzLmFic2VuY2Vfc2VsZWN0X2NlbGxzX0FycmF5ICYmIHRoaXMuYWJzZW5jZV9zZWxlY3RfY2VsbHNfQXJyYXkubGVuZ3RoID4gMCApIHtcblx0XHRcdHJlc3VsdCA9IHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cblxuXHRidWlsZEFjY3VtdWxhdGVkR3JpZCgpIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXG5cdFx0dmFyIGdyaWRfaWQgPSAnYWNjdW11bGF0ZWRfdGltZV9ncmlkJztcblx0XHR2YXIgdGl0bGUgPSAkLmkxOG4uXyggJ0FjY3VtdWxhdGVkIFRpbWUnICk7XG5cblx0XHRpZiAoIHRoaXNbZ3JpZF9pZF0gKSB7XG5cdFx0XHQvL0NvbW1lbnRpbmcgb3V0IHRoZSBuZXh0IGxpbmUgcmVwbGljYXRlcyBUeXBlRXJyb3I6IEZhaWxlZCB0byBleGVjdXRlICdyZXBsYWNlQ2hpbGQnIG9uICdOb2RlJzogcGFyYW1ldGVyIDIgaXMgbm90IG9mIHR5cGUgJ05vZGUnLiB3aGVuIHVzaW5nIERhdGUgbGVmdCBhcnJvdyBvbiB0aW1lc2hlZXQuXG5cdFx0XHQvLyAgQWxzbyBoYXBwZW5zIHdoZW4gY2xpY2tpbmcgdGhlIHRvcC1yaWdodCBpbi1hcHAgcmVmcmVzaCBidXR0b24gdG9vLlxuXHRcdFx0dGhpc1tncmlkX2lkXS51bmxvYWQoKTtcblx0XHRcdHRoaXNbZ3JpZF9pZF0gPSBudWxsO1xuXHRcdFx0dGhpcy5ncmlkX2RpY1tncmlkX2lkXSA9IG51bGw7XG5cdFx0fVxuXG5cdFx0dGhpc1tncmlkX2lkXSA9IHRoaXMuZ3JpZF9kaWNbZ3JpZF9pZF0gPSBuZXcgVFRHcmlkKCAnYWNjdW11bGF0ZWRfdGltZV9ncmlkJywge1xuXHRcdFx0c29ydGFibGU6IGZhbHNlLFxuXHRcdFx0aG92ZXJyb3dzOiBmYWxzZSxcblx0XHRcdGhlaWdodDogMCwgLy9TdGFydCB0aGUgZ3JpZCBoZWlnaHQgYXQgMCBpbnN0ZWFkIG9mIHBhcmVudCBoZWlnaHQgdG8gYXZvaWQgdHJhbnNpZW50IHNjcm9sbGJhcnMgZnJvbSBjYXVzaW5nIHRoZSB3aWR0aCB0byBiZSBpbmNvbnNpc3RlbnQgYWNyb3NzIHRhYmxlcy5cblx0XHRcdG9uZGJsQ2xpY2tSb3c6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQkdGhpcy5vbkFjY3VtdWxhdGVkVGltZUNsaWNrKCk7XG5cdFx0XHR9LFxuXHRcdFx0b25SaWdodENsaWNrUm93OiBmdW5jdGlvbiggcm93X2lkLCBpUm93LCBjZWxsX2luZGV4LCBlICkge1xuXHRcdFx0XHR2YXIgY2VsbF92YWwgPSAkKCBlLnRhcmdldCApLmNsb3Nlc3QoICd0ZCx0aCcgKS5odG1sKCk7XG5cdFx0XHRcdCR0aGlzLm9uQ2VsbFNlbGVjdCggJ2FjY3VtdWxhdGVkX2dyaWQnLCByb3dfaWQsIGNlbGxfaW5kZXgsIGNlbGxfdmFsLCB0aGlzLCBlICk7XG5cdFx0XHRcdCR0aGlzLm9uU2VsZWN0Um93KCAnYWNjdW11bGF0ZWRfZ3JpZCcsIHJvd19pZCwgdGhpcyApO1xuXHRcdFx0fSxcblx0XHRcdG9uQ2VsbFNlbGVjdDogZnVuY3Rpb24oIHJvd19pZCwgY2VsbF9pbmRleCwgY2VsbF92YWwsIGUgKSB7XG5cdFx0XHRcdCR0aGlzLnNldERlZmF1bHRNZW51KCk7XG5cdFx0XHR9LFxuXHRcdFx0b25SZXNpemVHcmlkOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCAkdGhpcy5ncmlkX2RpY1snYWNjdW11bGF0ZWRfdGltZV9ncmlkJ10gKSB7XG5cdFx0XHRcdFx0JHRoaXMuZ3JpZF9kaWNbJ2FjY3VtdWxhdGVkX3RpbWVfZ3JpZCddLmdyaWQuc2V0R3JpZFdpZHRoKCAkdGhpcy5nZXRUaW1lU2hlZXRXaWR0aCgpICk7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRiZWZvcmVTZWxlY3RSb3c6IGZ1bmN0aW9uKCByb3dfaWQsIGUgKSB7XG5cdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblxuXHRcdFx0XHR2YXIgY2VsbF9pbmRleCA9IDA7XG5cdFx0XHRcdGlmICggJCggZS50YXJnZXQgKS5hdHRyKCAncm9sZScgKSA9PSAnZ3JpZGNlbGwnICkge1xuXHRcdFx0XHRcdGNlbGxfaW5kZXggPSAkKCBlLnRhcmdldCApLmluZGV4KCk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Y2VsbF9pbmRleCA9ICQoIGUudGFyZ2V0ICkucGFyZW50cyggJ3RkJyApLmluZGV4KCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR2YXIgY2VsbF92YWwgPSAkKCBlLnRhcmdldCApLnRleHQoKTtcblxuXHRcdFx0XHQkdGhpcy5vbkNlbGxTZWxlY3QoICdhY2N1bXVsYXRlZF9ncmlkJywgcm93X2lkLCBjZWxsX2luZGV4LCBjZWxsX3ZhbCwgdGhpcywgZSApO1xuXHRcdFx0XHQkdGhpcy5vblNlbGVjdFJvdyggJ2FjY3VtdWxhdGVkX2dyaWQnLCByb3dfaWQsIHRoaXMgKTtcblxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9LFxuXHRcdFx0bXVsdGlzZWxlY3RQb3NpdGlvbjogJ25vbmUnLFxuXHRcdFx0d2luTXVsdGlTZWxlY3Q6IGZhbHNlLFxuXHRcdFx0dmVydGljYWxSZXNpemU6IGZhbHNlXG5cblx0XHR9LCB0aGlzLnRpbWVzaGVldF9jb2x1bW5zICk7XG5cblx0XHR0aGlzLnNldEdyaWRIZWFkZXJCYXIoIGdyaWRfaWQsIHRpdGxlICk7XG5cblx0XHRpZiAoIHRoaXMuZ3JpZF9kaWNbZ3JpZF9pZF0gJiYgdGhpcy5ncmlkX2RpY1tncmlkX2lkXS5ncmlkICkge1xuXHRcdFx0dGhpcy5ncmlkX2RpY1tncmlkX2lkXS5ncmlkLnNldEdyaWRXaWR0aCggdGhpcy5nZXRUaW1lU2hlZXRXaWR0aCgpICk7XG5cdFx0fVxuXHR9XG5cblx0YnVpbGRTdWJHcmlkKCBncmlkX2lkLCB0aXRsZSApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXG5cdFx0dmFyIGh0bWxfZ3JpZF9pZCA9IHRoaXMudWlfaWQgKyAnXycgKyBncmlkX2lkO1xuXHRcdGlmICggIUdsb2JhbC5pc1NldCggdGhpc1tncmlkX2lkXSApICkge1xuXHRcdFx0dmFyIGdyaWQgPSAkKCB0aGlzLmVsICkuZmluZCggJyMnICsgZ3JpZF9pZCApO1xuXHRcdFx0Z3JpZC5hdHRyKCAnaWQnLCBodG1sX2dyaWRfaWQgKTtcdC8vR3JpZCdzIGlkIGlzIFNjcmlwdE5hbWUgKyBfZ3JpZFxuXHRcdH1cblxuXHRcdGlmICggdGhpc1tncmlkX2lkXSApIHtcblx0XHRcdHRoaXNbZ3JpZF9pZF0udW5sb2FkKCk7XG5cdFx0XHR0aGlzW2dyaWRfaWRdID0gbnVsbDtcblx0XHRcdHRoaXMuZ3JpZF9kaWNbZ3JpZF9pZF0gPSBudWxsO1xuXHRcdH1cblxuXHRcdGlmICggZ3JpZF9pZCA9PT0gJ3ByZW1pdW1fZ3JpZCcgKSB7XG5cdFx0XHR0aGlzW2dyaWRfaWRdID0gdGhpcy5ncmlkX2RpY1tncmlkX2lkXSA9IG5ldyBUVEdyaWQoIGh0bWxfZ3JpZF9pZCwge1xuXHRcdFx0XHRob3ZlcnJvd3M6IGZhbHNlLFxuXHRcdFx0XHRtdWx0aXNlbGVjdFBvc2l0aW9uOiAnbm9uZScsXG5cdFx0XHRcdHdpbk11bHRpU2VsZWN0OiBmYWxzZSxcblx0XHRcdFx0aGVpZ2h0OiAwLCAvL1N0YXJ0IHRoZSBncmlkIGhlaWdodCBhdCAwIGluc3RlYWQgb2YgcGFyZW50IGhlaWdodCB0byBhdm9pZCB0cmFuc2llbnQgc2Nyb2xsYmFycyBmcm9tIGNhdXNpbmcgdGhlIHdpZHRoIHRvIGJlIGluY29uc2lzdGVudCBhY3Jvc3MgdGFibGVzLlxuXHRcdFx0XHRvblNlbGVjdFJvdzogZnVuY3Rpb24oIHJvd19pZCwgZmxhZywgZSApIHtcblx0XHRcdFx0XHQkdGhpcy5vblNlbGVjdFJvdyggJ3ByZW1pdW1fZ3JpZCcsIHJvd19pZCwgdGhpcyApO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRvblJpZ2h0Q2xpY2tSb3c6IGZ1bmN0aW9uKCByb3dfaWQsIGlSb3csIGNlbGxfaW5kZXgsIGUgKSB7XG5cdFx0XHRcdFx0dmFyIGNlbGxfdmFsID0gJCggZS50YXJnZXQgKS5jbG9zZXN0KCAndGQsdGgnICkuaHRtbCgpO1xuXHRcdFx0XHRcdCR0aGlzLm9uQ2VsbFNlbGVjdCggJ3ByZW1pdW1fZ3JpZCcsIHJvd19pZCwgY2VsbF9pbmRleCwgY2VsbF92YWwsIHRoaXMsIGUgKTtcblx0XHRcdFx0XHQkdGhpcy5vblNlbGVjdFJvdyggJ3ByZW1pdW1fZ3JpZCcsIHJvd19pZCwgdGhpcyApO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRvbkNlbGxTZWxlY3Q6IGZ1bmN0aW9uKCByb3dfaWQsIGNlbGxfaW5kZXgsIGNlbGxfdmFsLCBlICkge1xuXHRcdFx0XHRcdCR0aGlzLnVuc2V0U2VsZWN0ZWRDZWxscyggJ3RpbWVzaGVldF9ncmlkJyApO1xuXHRcdFx0XHRcdCR0aGlzLnVuc2V0U2VsZWN0ZWRDZWxscyggJ2Fic2VuY2VfZ3JpZCcgKTtcblx0XHRcdFx0XHQkdGhpcy5vbkNlbGxTZWxlY3QoICdwcmVtaXVtX2dyaWQnLCByb3dfaWQsIGNlbGxfaW5kZXgsIGNlbGxfdmFsLCB0aGlzLCBlICk7XG5cdFx0XHRcdFx0JHRoaXMuc2VsZWN0X3B1bmNoZXNfYXJyYXkgPSBbXTtcblx0XHRcdFx0XHQkdGhpcy5zZXREZWZhdWx0TWVudSgpO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRvbmRibENsaWNrUm93OiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRpZiAoIGdyaWRfaWQgPT09ICdwcmVtaXVtX2dyaWQnICkge1xuXHRcdFx0XHRcdFx0JHRoaXMub25BY2N1bXVsYXRlZFRpbWVDbGljaygpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcblx0XHRcdFx0b25SZXNpemVHcmlkOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRpZiAoICR0aGlzLmdyaWRfZGljW2dyaWRfaWRdICkge1xuXHRcdFx0XHRcdFx0JHRoaXMuZ3JpZF9kaWNbZ3JpZF9pZF0uZ3JpZC5zZXRHcmlkV2lkdGgoICR0aGlzLmdldFRpbWVTaGVldFdpZHRoKCkgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdHZlcnRpY2FsUmVzaXplOiBmYWxzZVxuXHRcdFx0fSwgdGhpcy50aW1lc2hlZXRfY29sdW1ucyApO1xuXG5cdFx0XHQvL3N1YmdyaWRzIG1pZ2h0IG5vdCBiZSByZW5kZXJlZCwgc28gd2UgbmVlZCB0byBjaGVjayBmb3IgdGhlbSBpbiB0aGUgZ3JpZF9kaWMgZmlyc3QuXG5cdFx0XHRpZiAoIHRoaXNbZ3JpZF9pZF0gJiYgdGhpc1tncmlkX2lkXS5ncmlkICkge1xuXHRcdFx0XHR0aGlzW2dyaWRfaWRdLmdyaWQuYWRkQ2xhc3MoICdwcmVtaXVtLWdyaWQnICk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXNbZ3JpZF9pZF0gPSB0aGlzLmdyaWRfZGljW2dyaWRfaWRdID0gbmV3IFRUR3JpZCggaHRtbF9ncmlkX2lkLCB7XG5cdFx0XHRcdGhvdmVycm93czogZmFsc2UsXG5cdFx0XHRcdG11bHRpc2VsZWN0UG9zaXRpb246ICdub25lJyxcblx0XHRcdFx0d2luTXVsdGlTZWxlY3Q6IGZhbHNlLFxuXHRcdFx0XHRoZWlnaHQ6IDAsIC8vU3RhcnQgdGhlIGdyaWQgaGVpZ2h0IGF0IDAgaW5zdGVhZCBvZiBwYXJlbnQgaGVpZ2h0IHRvIGF2b2lkIHRyYW5zaWVudCBzY3JvbGxiYXJzIGZyb20gY2F1c2luZyB0aGUgd2lkdGggdG8gYmUgaW5jb25zaXN0ZW50IGFjcm9zcyB0YWJsZXMuXG5cdFx0XHRcdG9uQ2VsbFNlbGVjdDogZnVuY3Rpb24oIHJvd19pZCwgY2VsbF9pbmRleCwgY2VsbF92YWwsIGUgKSB7XG5cdFx0XHRcdFx0JHRoaXMudW5zZXRTZWxlY3RlZENlbGxzKCAndGltZXNoZWV0X2dyaWQnICk7XG5cdFx0XHRcdFx0JHRoaXMudW5zZXRTZWxlY3RlZENlbGxzKCAnYWJzZW5jZV9ncmlkJyApO1xuXG5cdFx0XHRcdFx0JHRoaXMub25DZWxsU2VsZWN0KCBncmlkX2lkLCByb3dfaWQsIGNlbGxfaW5kZXgsIGNlbGxfdmFsLCB0aGlzLCBlICk7XG5cdFx0XHRcdFx0JHRoaXMuc2VsZWN0X3B1bmNoZXNfYXJyYXkgPSBbXTtcblx0XHRcdFx0XHQkdGhpcy5zZXREZWZhdWx0TWVudSgpO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRvblJlc2l6ZUdyaWQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGlmICggJHRoaXMuZ3JpZF9kaWNbZ3JpZF9pZF0gKSB7XG5cdFx0XHRcdFx0XHQkdGhpcy5ncmlkX2RpY1tncmlkX2lkXS5ncmlkLnNldEdyaWRXaWR0aCggJHRoaXMuZ2V0VGltZVNoZWV0V2lkdGgoKSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcblx0XHRcdFx0dmVydGljYWxSZXNpemU6IGZhbHNlXG5cdFx0XHR9LCB0aGlzLnRpbWVzaGVldF9jb2x1bW5zICk7XG5cdFx0fVxuXG5cdFx0dGhpcy5zZXRHcmlkSGVhZGVyQmFyKCBncmlkX2lkLCB0aXRsZSApO1xuXG5cdFx0Ly90aGlzIGxvb3AgaGl0cyBhbGwgcG9zc2libGUgZ3JpZHMuIHN1YmdyaWRzIG1pZ2h0IG5vdCBiZSByZW5kZXJlZCwgc28gd2UgbmVlZCB0byBjaGVjayBmb3IgdGhlbSBpbiB0aGUgZ3JpZF9kaWMgZmlyc3QuXG5cdFx0aWYgKCB0aGlzLmdyaWRfZGljW2dyaWRfaWRdICYmIHRoaXMuZ3JpZF9kaWNbZ3JpZF9pZF0uZ3JpZCApIHtcblx0XHRcdHRoaXMuZ3JpZF9kaWNbZ3JpZF9pZF0uZ3JpZC5zZXRHcmlkV2lkdGgoIHRoaXMuZ2V0VGltZVNoZWV0V2lkdGgoKSApO1xuXHRcdH1cblx0fVxuXG5cdHNldEdyaWRTRXhwZW5kT3JDb2xsYXBzZVN0YXR1cyggZ3JpZF9pZCwgdGl0bGUgKSB7XG5cdFx0aWYgKCB0aGlzLmdyaWRfZGljW2dyaWRfaWRdICkge1xuXHRcdFx0dmFyIGdyaWQgPSB0aGlzLmdyaWRfZGljW2dyaWRfaWRdLmdyaWQ7XG5cdFx0XHR2YXIgdGFibGUgPSAkKCAkKCB0aGlzLmVsICkuZmluZCggJ3RhYmxlW2FyaWEtbGFiZWxsZWRieT1nYm94XycgKyB0aGlzLnVpX2lkICsgJ18nICsgZ3JpZF9pZCArICddJyApWzBdICk7XG5cdFx0XHR2YXIgdGl0bGVfYmFyID0gdGFibGUuZmluZCggJy50aXRsZS1iYXInICk7XG5cdFx0XHR0aGlzLnNldEdyaWRIZWlnaHQoIGdyaWRfaWQgKTtcblxuXHRcdFx0aWYgKCBMb2NhbENhY2hlRGF0YS50aW1lc2hlZXRfc3ViX2dyaWRfZXhwZW5kZWRfZGljW2dyaWRfaWRdICE9PSB0cnVlICkge1xuXHRcdFx0XHRncmlkLnNldEdyaWRIZWlnaHQoIDAgKTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy51cGRhdGVHcmlkSGVhZGVyQmFyKCBncmlkX2lkLCB0aXRsZSApO1xuXHRcdH1cblx0fVxuXG5cdC8vU2hvdyBleHBlbmQgYW5kIGNvbGxhcHNlIGJ1dHRvbiBpbiBncmlkIHRpdGxlIGJhclxuXHRzZXRHcmlkRXhwZW5kQnV0dG9uKCBncmlkX2lkLCB0aXRsZSApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciB0YWJsZSA9ICQoICQoIHRoaXMuZWwgKS5maW5kKCAndGFibGVbYXJpYS1sYWJlbGxlZGJ5PWdib3hfJyArIHRoaXMudWlfaWQgKyAnXycgKyBncmlkX2lkICsgJ10nIClbMF0gKTtcblx0XHR2YXIgdGl0bGVfYmFyID0gdGFibGUuZmluZCggJy50aXRsZS1iYXInICk7XG5cblx0XHRpZiAoIHRpdGxlX2Jhci5maW5kKCAnLmdyaWQtZXhwZW5kLWJ0bicgKS5sZW5ndGggPT09IDAgKSB7IC8vcHJldmVudCBkb3VibGluZyB1cCBvZiBleHBhbmQgYXJyb3dzLlxuXHRcdFx0dmFyIGltZyA9ICQoICc8aW1nPicgKTtcblx0XHRcdGltZy5hZGRDbGFzcyggJ2dyaWQtZXhwZW5kLWJ0bicgKTtcblxuXHRcdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCBMb2NhbENhY2hlRGF0YS50aW1lc2hlZXRfc3ViX2dyaWRfZXhwZW5kZWRfZGljW2dyaWRfaWRdICkgfHxcblx0XHRcdFx0TG9jYWxDYWNoZURhdGEudGltZXNoZWV0X3N1Yl9ncmlkX2V4cGVuZGVkX2RpY1tncmlkX2lkXSA9PT0gdHJ1ZSApIHtcblxuXHRcdFx0XHRpbWcuYXR0ciggJ3NyYycsIEdsb2JhbC5nZXRSZWFsSW1hZ2VQYXRoKCAnaW1hZ2VzL2JpZ19jb2xsYXBzZS5wbmcnICkgKTtcblx0XHRcdFx0TG9jYWxDYWNoZURhdGEudGltZXNoZWV0X3N1Yl9ncmlkX2V4cGVuZGVkX2RpY1tncmlkX2lkXSA9IHRydWU7XG5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGltZy5hdHRyKCAnc3JjJywgR2xvYmFsLmdldFJlYWxJbWFnZVBhdGgoICdpbWFnZXMvYmlnX2V4cGFuZC5wbmcnICkgKTtcblx0XHRcdFx0TG9jYWxDYWNoZURhdGEudGltZXNoZWV0X3N1Yl9ncmlkX2V4cGVuZGVkX2RpY1tncmlkX2lkXSA9IGZhbHNlO1xuXHRcdFx0fVxuXG5cdFx0XHR0aXRsZV9iYXIuYXBwZW5kKCBpbWcgKTtcblxuXHRcdFx0dGhpcy5zZXRHcmlkU0V4cGVuZE9yQ29sbGFwc2VTdGF0dXMoIGdyaWRfaWQsIHRpdGxlICk7XG5cblx0XHRcdGltZy5jbGljayggZnVuY3Rpb24oIGUgKSB7XG5cblx0XHRcdFx0aWYgKCBMb2NhbENhY2hlRGF0YS50aW1lc2hlZXRfc3ViX2dyaWRfZXhwZW5kZWRfZGljW2dyaWRfaWRdID09PSB0cnVlICkge1xuXHRcdFx0XHRcdCQoIHRoaXMgKS5hdHRyKCAnc3JjJywgR2xvYmFsLmdldFJlYWxJbWFnZVBhdGgoICdpbWFnZXMvYmlnX2V4cGFuZC5wbmcnICkgKTtcblx0XHRcdFx0XHRMb2NhbENhY2hlRGF0YS50aW1lc2hlZXRfc3ViX2dyaWRfZXhwZW5kZWRfZGljW2dyaWRfaWRdID0gZmFsc2U7XG5cdFx0XHRcdFx0JHRoaXMuc2V0R3JpZFNFeHBlbmRPckNvbGxhcHNlU3RhdHVzKCBncmlkX2lkLCB0aXRsZSApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdCQoIHRoaXMgKS5hdHRyKCAnc3JjJywgR2xvYmFsLmdldFJlYWxJbWFnZVBhdGgoICdpbWFnZXMvYmlnX2NvbGxhcHNlLnBuZycgKSApO1xuXHRcdFx0XHRcdExvY2FsQ2FjaGVEYXRhLnRpbWVzaGVldF9zdWJfZ3JpZF9leHBlbmRlZF9kaWNbZ3JpZF9pZF0gPSB0cnVlO1xuXHRcdFx0XHRcdCR0aGlzLnNldEdyaWRTRXhwZW5kT3JDb2xsYXBzZVN0YXR1cyggZ3JpZF9pZCwgdGl0bGUgKTtcblxuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cdFx0fVxuXHR9XG5cblx0dXBkYXRlR3JpZEhlYWRlckJhciggZ3JpZF9pZCwgZGVzY3JpcHRpb24gKSB7XG5cdFx0dmFyIGxhYmVsID0gZGVzY3JpcHRpb247XG5cdFx0dmFyIHRhYmxlID0gJCggJCggdGhpcy5lbCApLmZpbmQoICd0YWJsZVthcmlhLWxhYmVsbGVkYnk9Z2JveF8nICsgdGhpcy51aV9pZCArICdfJyArIGdyaWRfaWQgKyAnXScgKVswXSApO1xuXHRcdHZhciB0aXRsZV9zcGFuID0gdGFibGUuZmluZCggJy50aXRsZS1zcGFuJyApO1xuXHRcdHZhciBjb3VudCA9IDA7XG5cblx0XHRpZiAoIExvY2FsQ2FjaGVEYXRhLnRpbWVzaGVldF9zdWJfZ3JpZF9leHBlbmRlZF9kaWNbZ3JpZF9pZF0gIT09IHRydWUgKSB7XG5cdFx0XHRzd2l0Y2ggKCBncmlkX2lkICkge1xuXHRcdFx0XHRjYXNlICdicmFuY2hfZ3JpZCc6XG5cdFx0XHRcdFx0bGFiZWwgPSBsYWJlbCArICcgKCcgKyAoIHRoaXMuYnJhbmNoX2NlbGxfY291bnQgKSArICcpJztcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAnZGVwYXJ0bWVudF9ncmlkJzpcblx0XHRcdFx0XHRsYWJlbCA9IGxhYmVsICsgJyAoJyArICggdGhpcy5kZXBhcnRtZW50X2NlbGxfY291bnQgKSArICcpJztcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAnam9iX2l0ZW1fZ3JpZCc6XG5cdFx0XHRcdFx0bGFiZWwgPSBsYWJlbCArICcgKCcgKyAoIHRoaXMudGFza19jZWxsX2NvdW50ICkgKyAnKSc7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ3B1bmNoX3RhZ19ncmlkJzpcblx0XHRcdFx0XHRsYWJlbCA9IGxhYmVsICsgJyAoJyArICggdGhpcy5wdW5jaF90YWdfY2VsbF9jb3VudCApICsgJyknO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdqb2JfZ3JpZCc6XG5cdFx0XHRcdFx0bGFiZWwgPSBsYWJlbCArICcgKCcgKyAoIHRoaXMuam9iX2NlbGxfY291bnQgKSArICcpJztcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAncHJlbWl1bV9ncmlkJzpcblx0XHRcdFx0XHRsYWJlbCA9IGxhYmVsICsgJyAoJyArICggdGhpcy5wcmVtaXVtX2NlbGxfY291bnQgKSArICcpJztcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAnYWJzZW5jZV9ncmlkJzpcblx0XHRcdFx0XHRsYWJlbCA9IGxhYmVsICsgJyAoJyArICggdGhpcy5hYnNlbmNlX2NlbGxfY291bnQgKSArICcpJztcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAncHVuY2hfbm90ZV9ncmlkJzpcblx0XHRcdFx0XHRsYWJlbCA9IGxhYmVsICsgJyAoJyArICggdGhpcy5wdW5jaF9ub3RlX2FjY291bnQgKSArICcpJztcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHR9XG5cblx0XHR0aXRsZV9zcGFuLnRleHQoIGxhYmVsICk7XG5cdH1cblxuXHRzZXRHcmlkSGVhZGVyQmFyKCBncmlkX2lkLCBsYWJlbCApIHtcblx0XHR2YXIgdGFibGUgPSAkKCB0aGlzLmdyaWRfZGljW2dyaWRfaWRdLmdyaWQgKS5wYXJlbnRzKCAnLnVpLWpxZ3JpZC12aWV3JyApLmZpbmQoICcudWktanFncmlkLWhib3ggdGFibGUnICk7IC8vZ3JhYiB0aGUgaGJveFxuXHRcdC8vdGFibGUuZW1wdHkoKTtcblx0XHR0YWJsZS5jc3MoICd3aWR0aCcsICcxMDB2dycgKTsgLy9zZXQgZGVmYXVsdCB3aWR0aCBvZiB0aW1lc2hlZXQgdGFibGVzIHRvIHRoZSB3aWR0aCBvZiB0aGUgc2NyZWVuIHRvIHNldCB0aGUgaGVhZGVyIHdpZHRocy5cblxuXHRcdHZhciBsYWJlbCA9ICQuaTE4bi5fKCBsYWJlbCApO1xuXG5cdFx0dGFibGUuZmluZCggJ3RyOmZpcnN0JyApLmhpZGUoKTtcblx0XHR2YXIgdGl0bGVfYmFyID0gJCggJzxkaXYgY2xhc3M9XFwndGl0bGUtYmFyXFwnPjxzcGFuIGNsYXNzPVxcJ3RpdGxlLXNwYW5cXCc+JyArIGxhYmVsICsgJzwvc3Bhbj48L2Rpdj4nICk7XG5cdFx0dGFibGUuYXBwZW5kKCB0aXRsZV9iYXIgKTtcblx0fVxuXG5cdGJ1aWxkTWFudWFsVGltZVNoZWV0c0NvbHVtbnMoKSB7XG5cdFx0dGhpcy5kYXlfZGljID0ge307XG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgNzsgaSsrICkge1xuXHRcdFx0dmFyIGN1cnJlbnRfZGF0ZSA9IG5ldyBEYXRlKCBuZXcgRGF0ZSggdGhpcy5zdGFydF9kYXRlLmdldFRpbWUoKSApLnNldERhdGUoIHRoaXMuc3RhcnRfZGF0ZS5nZXREYXRlKCkgKyBpICkgKTtcblx0XHRcdHZhciBkYXlfdGV4dCA9IGN1cnJlbnRfZGF0ZS5mb3JtYXQoIHRoaXMuZGF5X2Zvcm1hdCApO1xuXHRcdFx0dmFyIGRhdGVfdGV4dCA9IGN1cnJlbnRfZGF0ZS5mb3JtYXQoIHRoaXMuZGF0ZV9mb3JtYXQgKTtcblx0XHRcdHRoaXMuZGF5X2RpY1snZGF5XycgKyBpXSA9IHsgdmFsdWU6IGRheV90ZXh0ICsgJzxicj4nICsgZGF0ZV90ZXh0LCBmaWVsZDogY3VycmVudF9kYXRlLmZvcm1hdCgpIH07XG5cdFx0fVxuXHR9XG5cblx0Z2V0TWFudWFsVGltZVNoZWV0RGF0YSggY2FsbEJhY2sgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdHZhciB1c2VyX2lkID0gdGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpO1xuXHRcdGlmICggdXNlcl9pZCApIHtcblx0XHRcdHZhciBhcmdzID0ge307XG5cdFx0XHRhcmdzLmZpbHRlcl9kYXRhID0ge1xuXHRcdFx0XHR1c2VyX2lkOiB1c2VyX2lkLFxuXHRcdFx0XHRvYmplY3RfdHlwZV9pZDogMTAsXG5cdFx0XHRcdHN0YXJ0X2RhdGU6IHRoaXMuc3RhcnRfZGF0ZS5mb3JtYXQoKSxcblx0XHRcdFx0ZW5kX2RhdGU6IHRoaXMuZW5kX2RhdGUuZm9ybWF0KClcblx0XHRcdH07XG5cdFx0XHRhcmdzLmZpbHRlcl9jb2x1bW5zID0ge1xuXHRcdFx0XHQnaWQnOiB0cnVlLFxuXHRcdFx0XHQnZGF0ZV9zdGFtcCc6IHRydWUsXG5cdFx0XHRcdCd0b3RhbF90aW1lJzogdHJ1ZSxcblx0XHRcdFx0J29iamVjdF90eXBlJzogdHJ1ZSxcblx0XHRcdFx0J25hbWUnOiB0cnVlLFxuXHRcdFx0XHQnYnJhbmNoX2lkJzogdHJ1ZSxcblx0XHRcdFx0J2RlcGFydG1lbnRfaWQnOiB0cnVlLFxuXHRcdFx0XHQnYnJhbmNoJzogdHJ1ZSxcblx0XHRcdFx0J2RlcGFydG1lbnQnOiB0cnVlLFxuXHRcdFx0XHQnam9iJzogdHJ1ZSxcblx0XHRcdFx0J2pvYl9pdGVtJzogdHJ1ZSxcblx0XHRcdFx0J2pvYl9pZCc6IHRydWUsXG5cdFx0XHRcdCdqb2JfaXRlbV9pZCc6IHRydWUsXG5cdFx0XHRcdCdwdW5jaF90YWcnOiB0cnVlLFxuXHRcdFx0XHQncHVuY2hfdGFnX2lkJzogdHJ1ZSxcblx0XHRcdFx0J25vdGUnOiB0cnVlLFxuXHRcdFx0XHQnb3ZlcnJpZGUnOiB0cnVlXG5cdFx0XHR9O1xuXHRcdFx0dGhpcy5hcGlfdXNlcl9kYXRlX3RvdGFsLmdldFVzZXJEYXRlVG90YWwoIGFyZ3MsIHRydWUsIHtcblx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cdFx0XHRcdFx0JHRoaXMubWFudWFsX3RpbWVzaGVldF9kYXRhID0gcmVzdWx0LmdldFJlc3VsdCgpO1xuXHRcdFx0XHRcdGNhbGxCYWNrKCk7XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblx0XHR9XG5cdH1cblxuXHRidWlsZE1hbnVhbFRpbWVTaGVldERhdGEoKSB7XG5cdFx0dGhpcy50aW1lX3NoZWV0X2RhdGFfb3ZlcnJvZGVfdHJ1ZV9tYXAgPSB7fTtcblx0XHR0aGlzLnRpbWVfc2hlZXRfZGF0YV9vdmVycm9kZV9mYWxzZV9tYXAgPSB7fTtcblx0XHR2YXIgc29ydF9ieV9maWVsZHMgPSBbJ2JyYW5jaF9pZCcsICdkZXBhcnRtZW50X2lkJywgJ2pvYl9pZCcsICdqb2JfaXRlbV9pZCcsICdwdW5jaF90YWdfaWQnXSxcblx0XHRcdG1hbnVhbF90aW1lc2hlZXRfZGF0YV9ncm91cF9hcnJheSA9IFtdLFxuXHRcdFx0b3ZlcnJpZGVfdHJ1ZV9hcnJheSA9IFtdLFxuXHRcdFx0b3ZlcnJpZGVfZmFsc2VfYXJyYXkgPSBbXTtcblx0XHR0aGlzLm1hbnVhbF90aW1lc2hlZXRfZGF0YS5zb3J0KCBHbG9iYWwubV9zb3J0X2J5KCBzb3J0X2J5X2ZpZWxkcyApICk7XG5cdFx0bWFudWFsX3RpbWVzaGVldF9kYXRhX2dyb3VwX2FycmF5ID0gXy5ncm91cEJ5KCB0aGlzLm1hbnVhbF90aW1lc2hlZXRfZGF0YSwgJ292ZXJyaWRlJyApO1xuXHRcdG92ZXJyaWRlX3RydWVfYXJyYXkgPSBtYW51YWxfdGltZXNoZWV0X2RhdGFfZ3JvdXBfYXJyYXlbdHJ1ZV07XG5cdFx0b3ZlcnJpZGVfZmFsc2VfYXJyYXkgPSBtYW51YWxfdGltZXNoZWV0X2RhdGFfZ3JvdXBfYXJyYXlbZmFsc2VdO1xuXHRcdGRvTmV4dCggb3ZlcnJpZGVfdHJ1ZV9hcnJheSwgdGhpcy50aW1lX3NoZWV0X2RhdGFfb3ZlcnJvZGVfdHJ1ZV9tYXAgKTtcblx0XHRkb05leHQoIG92ZXJyaWRlX2ZhbHNlX2FycmF5LCB0aGlzLnRpbWVfc2hlZXRfZGF0YV9vdmVycm9kZV9mYWxzZV9tYXAgKTtcblxuXHRcdGZ1bmN0aW9uIGRvTmV4dCggbWFudWFsX3RpbWVzaGVldF9kYXRhLCB0YXJnZXRfbWFwICkge1xuXHRcdFx0IW1hbnVhbF90aW1lc2hlZXRfZGF0YSAmJiAoIG1hbnVhbF90aW1lc2hlZXRfZGF0YSA9IFtdICk7XG5cdFx0XHRmb3IgKCB2YXIgaSA9IDAsIG0gPSBtYW51YWxfdGltZXNoZWV0X2RhdGEubGVuZ3RoOyBpIDwgbTsgaSsrICkge1xuXHRcdFx0XHR2YXIgZGF0YSA9IG1hbnVhbF90aW1lc2hlZXRfZGF0YVtpXTtcblxuXHRcdFx0XHR2YXIga2V5ID0gZGF0YS5icmFuY2hfaWQgKyAnLScgKyBkYXRhLmRlcGFydG1lbnRfaWQgKyAnLScgKyBkYXRhLmpvYl9pZCArICctJyArIGRhdGEuam9iX2l0ZW1faWQ7XG5cdFx0XHRcdGlmICggIXRhcmdldF9tYXBba2V5XSApIHtcblx0XHRcdFx0XHR0YXJnZXRfbWFwW2tleV0gPSB7fTtcblx0XHRcdFx0XHR0YXJnZXRfbWFwW2tleV0uYnJhbmNoX2lkID0gZGF0YS5icmFuY2hfaWQ7XG5cdFx0XHRcdFx0dGFyZ2V0X21hcFtrZXldLmRlcGFydG1lbnRfaWQgPSBkYXRhLmRlcGFydG1lbnRfaWQ7XG5cdFx0XHRcdFx0dGFyZ2V0X21hcFtrZXldLmpvYl9pZCA9IGRhdGEuam9iX2lkO1xuXHRcdFx0XHRcdHRhcmdldF9tYXBba2V5XS5qb2JfaXRlbV9pZCA9IGRhdGEuam9iX2l0ZW1faWQ7XG5cdFx0XHRcdFx0dGFyZ2V0X21hcFtrZXldLnB1bmNoX3RhZ19pZCA9IGRhdGEucHVuY2hfdGFnX2lkO1xuXHRcdFx0XHRcdHRhcmdldF9tYXBba2V5XS5icmFuY2ggPSBkYXRhLmJyYW5jaDtcblx0XHRcdFx0XHR0YXJnZXRfbWFwW2tleV0uZGVwYXJ0bWVudCA9IGRhdGEuZGVwYXJ0bWVudDtcblx0XHRcdFx0XHR0YXJnZXRfbWFwW2tleV0uam9iID0gZGF0YS5qb2I7XG5cdFx0XHRcdFx0dGFyZ2V0X21hcFtrZXldLmpvYl9pdGVtID0gZGF0YS5qb2JfaXRlbTtcblx0XHRcdFx0XHR0YXJnZXRfbWFwW2tleV0ucHVuY2hfdGFnID0gZGF0YS5wdW5jaF90YWc7XG5cdFx0XHRcdFx0dGFyZ2V0X21hcFtrZXldLm92ZXJyaWRlID0gZGF0YS5vdmVycmlkZTtcblx0XHRcdFx0XHR0YXJnZXRfbWFwW2tleV1bZGF0YS5kYXRlX3N0YW1wXSA9IGRhdGE7XG5cdFx0XHRcdH0gZWxzZSBpZiAoIHRhcmdldF9tYXBba2V5XVtkYXRhLmRhdGVfc3RhbXBdICkge1xuXHRcdFx0XHRcdC8vIElmIGFscmVhZHkgaGFzIGRhdGEgaW4gdGhpcyBkYXksIGNyZWF0ZSBuZXh0IHJvdy5cblx0XHRcdFx0XHR2YXIgaiA9IDE7XG5cdFx0XHRcdFx0d2hpbGUgKCB0cnVlICkge1xuXHRcdFx0XHRcdFx0aWYgKCAhdGFyZ2V0X21hcFtrZXkgKyAnLScgKyBqXSApIHtcblx0XHRcdFx0XHRcdFx0dGFyZ2V0X21hcFtrZXkgKyAnLScgKyBqXSA9IHt9O1xuXHRcdFx0XHRcdFx0XHR0YXJnZXRfbWFwW2tleSArICctJyArIGpdLmJyYW5jaF9pZCA9IGRhdGEuYnJhbmNoX2lkO1xuXHRcdFx0XHRcdFx0XHR0YXJnZXRfbWFwW2tleSArICctJyArIGpdLmRlcGFydG1lbnRfaWQgPSBkYXRhLmRlcGFydG1lbnRfaWQ7XG5cdFx0XHRcdFx0XHRcdHRhcmdldF9tYXBba2V5ICsgJy0nICsgal0uam9iX2lkID0gZGF0YS5qb2JfaWQ7XG5cdFx0XHRcdFx0XHRcdHRhcmdldF9tYXBba2V5ICsgJy0nICsgal0uam9iX2l0ZW1faWQgPSBkYXRhLmpvYl9pdGVtX2lkO1xuXHRcdFx0XHRcdFx0XHR0YXJnZXRfbWFwW2tleSArICctJyArIGpdLnB1bmNoX3RhZ19pZCA9IGRhdGEucHVuY2hfdGFnX2lkO1xuXHRcdFx0XHRcdFx0XHR0YXJnZXRfbWFwW2tleSArICctJyArIGpdLmJyYW5jaCA9IGRhdGEuYnJhbmNoO1xuXHRcdFx0XHRcdFx0XHR0YXJnZXRfbWFwW2tleSArICctJyArIGpdLmRlcGFydG1lbnQgPSBkYXRhLmRlcGFydG1lbnQ7XG5cdFx0XHRcdFx0XHRcdHRhcmdldF9tYXBba2V5ICsgJy0nICsgal0uam9iID0gZGF0YS5qb2I7XG5cdFx0XHRcdFx0XHRcdHRhcmdldF9tYXBba2V5ICsgJy0nICsgal0ucHVuY2hfdGFnID0gZGF0YS5wdW5jaF90YWc7XG5cdFx0XHRcdFx0XHRcdHRhcmdldF9tYXBba2V5ICsgJy0nICsgal0ub3ZlcnJpZGUgPSBkYXRhLm92ZXJyaWRlO1xuXHRcdFx0XHRcdFx0XHR0YXJnZXRfbWFwW2tleSArICctJyArIGpdW2RhdGEuZGF0ZV9zdGFtcF0gPSBkYXRhO1xuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoICF0YXJnZXRfbWFwW2tleSArICctJyArIGpdW2RhdGEuZGF0ZV9zdGFtcF0gKSB7XG5cdFx0XHRcdFx0XHRcdHRhcmdldF9tYXBba2V5ICsgJy0nICsgal1bZGF0YS5kYXRlX3N0YW1wXSA9IGRhdGE7XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0aiA9IGogKyAxO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0YXJnZXRfbWFwW2tleV1bZGF0YS5kYXRlX3N0YW1wXSA9IGRhdGE7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdH1cblx0fVxuXG5cdGluaXRJbnNpZGVFZGl0b3JEYXRhKCB1cGRhdGVFeGlzdGVkQ2VsbCApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdGZvciAoIHZhciBrZXkgaW4gdGhpcy5kYXlfZGljICkge1xuXHRcdFx0dGhpcy4kKCAnIycgKyBrZXkgKyAnX2RhdGUnICkuaHRtbCggdGhpcy5kYXlfZGljW2tleV0udmFsdWUgKTtcblx0XHRcdHRoaXMuJCggJyMnICsga2V5ICsgJ19kYXRlJyApLmFkZENsYXNzKCAnbWFudWFsX2dyaWRfZGF5XycgKyBHbG9iYWwuc3RyVG9EYXRlKCB0aGlzLmRheV9kaWNba2V5XS5maWVsZCApLmZvcm1hdCggdGhpcy5mdWxsX2Zvcm1hdCApICk7XG5cdFx0XHR0aGlzLiQoICcjJyArIGtleSArICdfZGF0ZScgKS5hdHRyKCAnY3VycmVudF9kYXRlJywgJ21hbnVhbF9ncmlkX2RheV8nICsgR2xvYmFsLnN0clRvRGF0ZSggdGhpcy5kYXlfZGljW2tleV0uZmllbGQgKS5mb3JtYXQoIHRoaXMuZnVsbF9mb3JtYXQgKSApO1xuXHRcdFx0dGhpcy4kKCAnIycgKyBrZXkgKyAnX2RhdGUnICkudW5iaW5kKCAnY2xpY2snICkuYmluZCggJ2NsaWNrJywgZnVuY3Rpb24oIGUgKSB7XG5cdFx0XHRcdHZhciB0YXJnZXQgPSBlLmN1cnJlbnRUYXJnZXQ7XG5cdFx0XHRcdHZhciBmaWVsZCA9ICQoIHRhcmdldCApLmF0dHIoICdjdXJyZW50X2RhdGUnICk7XG5cdFx0XHRcdGZpZWxkID0gZmllbGQuc3Vic3RyaW5nKCAxNiwgZmllbGQubGVuZ3RoICk7XG5cdFx0XHRcdHZhciBkYXRlID0gR2xvYmFsLnN0clRvRGF0ZSggZmllbGQsICR0aGlzLmZ1bGxfZm9ybWF0ICk7XG5cdFx0XHRcdGlmICggZGF0ZSAmJiBkYXRlLmdldFllYXIoKSA+IDAgKSB7XG5cdFx0XHRcdFx0JHRoaXMuc2V0RGF0ZVBpY2tlclZhbHVlKCBkYXRlLmZvcm1hdCggR2xvYmFsLmdldExvZ2luVXNlckRhdGVGb3JtYXQoKSApICk7XG5cdFx0XHRcdFx0JHRoaXMuaGlnaExpZ2h0U2VsZWN0RGF5KCk7XG5cdFx0XHRcdFx0JHRoaXMucmVMb2FkU3ViR3JpZHNTb3VyY2UoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXHRcdFx0dGhpcy4kKCAnLmlzLXNhdmluZy1tYW51YWwtZ3JpZCcgKS5yZW1vdmVDbGFzcyggJ2lzLXNhdmluZy1tYW51YWwtZ3JpZCcgKTtcblx0XHR9XG5cdFx0aWYgKCB0aGlzLmlzX2F1dG9fc3dpdGNoICkge1xuXHRcdFx0dGhpcy5pc19hdXRvX3N3aXRjaCA9IGZhbHNlO1xuXHRcdFx0ZG9OZXh0KCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuZ2V0TWFudWFsVGltZVNoZWV0RGF0YSggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGRvTmV4dCgpO1xuXHRcdFx0fSApO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGRvTmV4dCgpIHtcblx0XHRcdCR0aGlzLmlzX3NhdmluZ19tYW51YWxfZ3JpZCA9IGZhbHNlO1xuXHRcdFx0JHRoaXMuc2V0RGVmYXVsdE1lbnUoKTtcblx0XHRcdGlmICggIXVwZGF0ZUV4aXN0ZWRDZWxsICkge1xuXHRcdFx0XHQkdGhpcy5lZGl0b3IucmVtb3ZlQWxsUm93cygpO1xuXHRcdFx0XHRpZiAoICR0aGlzLm1hbnVhbF90aW1lc2hlZXRfZGF0YS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHRcdCR0aGlzLmJ1aWxkTWFudWFsVGltZVNoZWV0RGF0YSgpO1xuXHRcdFx0XHRcdF8ubWFwKCAkdGhpcy50aW1lX3NoZWV0X2RhdGFfb3ZlcnJvZGVfZmFsc2VfbWFwLCBmdW5jdGlvbiggZGF0YSApIHtcblx0XHRcdFx0XHRcdCR0aGlzLmVkaXRvci5hZGRSb3coIGRhdGEgKTtcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0Xy5tYXAoICR0aGlzLnRpbWVfc2hlZXRfZGF0YV9vdmVycm9kZV90cnVlX21hcCwgZnVuY3Rpb24oIGRhdGEgKSB7XG5cdFx0XHRcdFx0XHQkdGhpcy5lZGl0b3IuYWRkUm93KCBkYXRhICk7XG5cdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdGlmICggXy5pc0VtcHR5KCAkdGhpcy50aW1lX3NoZWV0X2RhdGFfb3ZlcnJvZGVfdHJ1ZV9tYXAgKSApIHtcblx0XHRcdFx0XHRcdCR0aGlzLmVkaXRvci5hZGRSb3coKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JHRoaXMuZWRpdG9yLmFkZFJvdygpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZiAoICR0aGlzLm1hbnVhbF90aW1lc2hlZXRfZGF0YS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHRcdCR0aGlzLmJ1aWxkTWFudWFsVGltZVNoZWV0RGF0YSgpO1xuXHRcdFx0XHRcdGZvciAoIHZhciBtYXBfa2V5IGluICR0aGlzLnRpbWVfc2hlZXRfZGF0YV9vdmVycm9kZV90cnVlX21hcCApIHtcblx0XHRcdFx0XHRcdHZhciBkYXRhID0gJHRoaXMudGltZV9zaGVldF9kYXRhX292ZXJyb2RlX3RydWVfbWFwW21hcF9rZXldO1xuXHRcdFx0XHRcdFx0Zm9yICggdmFyIG1hcF9rZXlfMiBpbiBkYXRhICkge1xuXHRcdFx0XHRcdFx0XHR2YXIgaXRlbSA9IGRhdGFbbWFwX2tleV8yXTtcblx0XHRcdFx0XHRcdFx0aWYgKCBBcnJheS5pc0FycmF5KCBpdGVtICkgfHwgIV8uaXNPYmplY3QoIGl0ZW0gKSApIHtcblx0XHRcdFx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdHZhciBrZXkgPSAkdGhpcy5nZW5lcmF0ZU1hbnVhbFRpbWVTaGVldFJlY29yZEtleSggaXRlbSApO1xuXHRcdFx0XHRcdFx0XHR2YXIgaXRlbV9pZF9rZXkgPSBpdGVtLmlkICsgJy0nICsga2V5O1xuXG5cdFx0XHRcdFx0XHRcdC8vQ2hlY2sgdG8gc2VlIGlmIHRoZSByZWNvcmQgd2l0aCBubyBJRCAocHJlLXNhdmUpIGV4aXN0cywgYW5kIGlmIHNvIHVwZGF0ZSBpdCwgb3IgcmVwbGFjZSBpdCB3aXRoIHRoZSBzYXZlZCByZWNvcmQuXG5cdFx0XHRcdFx0XHRcdGlmICggJHRoaXMubWFudWFsX2dyaWRfcmVjb3Jkc19tYXBbaXRlbV9pZF9rZXldICkge1xuXHRcdFx0XHRcdFx0XHRcdCR0aGlzLm1hbnVhbF9ncmlkX3JlY29yZHNfbWFwW2l0ZW1faWRfa2V5XVtpdGVtLmRhdGVfc3RhbXBdLnNldFZhbHVlKCBpdGVtLnRvdGFsX3RpbWUgKTtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIGlmICggJHRoaXMubWFudWFsX2dyaWRfcmVjb3Jkc19tYXBba2V5XSApIHtcblx0XHRcdFx0XHRcdFx0XHQkdGhpcy5tYW51YWxfZ3JpZF9yZWNvcmRzX21hcFtrZXldLmN1cnJlbnRfZWRpdF9pdGVtW2l0ZW0uZGF0ZV9zdGFtcF0gPSBpdGVtO1xuXHRcdFx0XHRcdFx0XHRcdCR0aGlzLm1hbnVhbF9ncmlkX3JlY29yZHNfbWFwW2tleV1baXRlbS5kYXRlX3N0YW1wXS5zZXRWYWx1ZSggaXRlbS50b3RhbF90aW1lICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdGlmICggJHRoaXMuc2F2ZV9tYW51YWxfZ3JpZF9hZnRlcl9zYXZlICkge1xuXHRcdFx0XHQkdGhpcy5hdXRvU2F2ZU1hbnVhbFB1bmNoKCk7XG5cdFx0XHRcdCR0aGlzLnNhdmVfbWFudWFsX2dyaWRfYWZ0ZXJfc2F2ZSA9IGZhbHNlO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0aW5zaWRlRWRpdG9yQWRkUm93KCBkYXRhLCBpbmRleCApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdGlmICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSB7XG5cdFx0XHR2YXIgam9iX2l0ZW1fYXBpID0gVFRBUEkuQVBJSm9iSXRlbTtcblx0XHRcdHZhciBqb2JfYXBpID0gVFRBUEkuQVBJSm9iO1xuXHRcdFx0dmFyIHB1bmNoX3RhZ19hcGkgPSBUVEFQSS5BUElQdW5jaFRhZztcblx0XHRcdHZhciBkZXBhcnRtZW50X2FwaSA9IFRUQVBJLkFQSURlcGFydG1lbnQ7XG5cdFx0fVxuXHRcdHZhciBhcmdzO1xuXHRcdGlmICggIWRhdGEgKSB7XG5cdFx0XHRkYXRhID0ge307XG5cdFx0XHRpZiAoIGluZGV4ID49IDAgKSB7XG5cdFx0XHRcdHZhciB3aWRnZXRfcm93ID0gdGhpcy5yb3dzX3dpZGdldHNfYXJyYXlbaW5kZXggLSAzXTtcblx0XHRcdFx0aWYgKCB0aGlzLnBhcmVudF9jb250cm9sbGVyLnNob3dfYnJhbmNoX3VpICkge1xuXHRcdFx0XHRcdGlmICggd2lkZ2V0X3Jvdy5icmFuY2hfaWQgKSB7XG5cdFx0XHRcdFx0XHRkYXRhLmJyYW5jaF9pZCA9IHdpZGdldF9yb3cuYnJhbmNoX2lkLmdldFZhbHVlKCk7XG5cdFx0XHRcdFx0fSBlbHNlIGlmICggd2lkZ2V0X3Jvdy5jdXJyZW50X2VkaXRfaXRlbSAmJiB3aWRnZXRfcm93LmN1cnJlbnRfZWRpdF9pdGVtLmJyYW5jaF9pZCApIHtcblx0XHRcdFx0XHRcdGRhdGEuYnJhbmNoX2lkID0gd2lkZ2V0X3Jvdy5jdXJyZW50X2VkaXRfaXRlbS5icmFuY2hfaWQ7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGRhdGEuYnJhbmNoX2lkID0gZmFsc2U7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICggdGhpcy5wYXJlbnRfY29udHJvbGxlci5zaG93X2RlcGFydG1lbnRfdWkgKSB7XG5cdFx0XHRcdFx0aWYgKCB3aWRnZXRfcm93LmRlcGFydG1lbnRfaWQgKSB7XG5cdFx0XHRcdFx0XHRkYXRhLmRlcGFydG1lbnRfaWQgPSB3aWRnZXRfcm93LmRlcGFydG1lbnRfaWQuZ2V0VmFsdWUoKTtcblx0XHRcdFx0XHR9IGVsc2UgaWYgKCB3aWRnZXRfcm93LmN1cnJlbnRfZWRpdF9pdGVtICYmIHdpZGdldF9yb3cuY3VycmVudF9lZGl0X2l0ZW0uZGVwYXJ0bWVudF9pZCApIHtcblx0XHRcdFx0XHRcdGRhdGEuZGVwYXJ0bWVudF9pZCA9IHdpZGdldF9yb3cuY3VycmVudF9lZGl0X2l0ZW0uZGVwYXJ0bWVudF9pZDtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0ZGF0YS5kZXBhcnRtZW50X2lkID0gZmFsc2U7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICggdGhpcy5wYXJlbnRfY29udHJvbGxlci5zaG93X2pvYl91aSAmJiBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAyMCApIHtcblx0XHRcdFx0XHRpZiAoIHdpZGdldF9yb3cuam9iX2lkICkge1xuXHRcdFx0XHRcdFx0ZGF0YS5qb2JfaWQgPSB3aWRnZXRfcm93LmpvYl9pZC5nZXRWYWx1ZSgpO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoIHdpZGdldF9yb3cuY3VycmVudF9lZGl0X2l0ZW0gJiYgd2lkZ2V0X3Jvdy5jdXJyZW50X2VkaXRfaXRlbS5qb2JfaWQgKSB7XG5cdFx0XHRcdFx0XHRkYXRhLmpvYl9pZCA9IHdpZGdldF9yb3cuY3VycmVudF9lZGl0X2l0ZW0uam9iX2lkO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRkYXRhLmpvYl9pZCA9IGZhbHNlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoIHRoaXMucGFyZW50X2NvbnRyb2xsZXIuc2hvd19qb2JfaXRlbV91aSAmJiBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAyMCApIHtcblx0XHRcdFx0XHRpZiAoIHdpZGdldF9yb3cuam9iX2l0ZW1faWQgKSB7XG5cdFx0XHRcdFx0XHRkYXRhLmpvYl9pdGVtX2lkID0gd2lkZ2V0X3Jvdy5qb2JfaXRlbV9pZC5nZXRWYWx1ZSgpO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoIHdpZGdldF9yb3cuY3VycmVudF9lZGl0X2l0ZW0gJiYgd2lkZ2V0X3Jvdy5jdXJyZW50X2VkaXRfaXRlbS5qb2JfaXRlbV9pZCApIHtcblx0XHRcdFx0XHRcdGRhdGEuam9iX2l0ZW1faWQgPSB3aWRnZXRfcm93LmN1cnJlbnRfZWRpdF9pdGVtLmpvYl9pdGVtX2lkO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRkYXRhLmpvYl9pdGVtX2lkID0gZmFsc2U7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICggdGhpcy5wYXJlbnRfY29udHJvbGxlci5zaG93X3B1bmNoX3RhZ191aSAmJiBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAyMCApIHtcblx0XHRcdFx0XHRpZiAoIHdpZGdldF9yb3cucHVuY2hfdGFnX2lkICkge1xuXHRcdFx0XHRcdFx0ZGF0YS5wdW5jaF90YWdfaWQgPSB3aWRnZXRfcm93LnB1bmNoX3RhZ19pZC5nZXRWYWx1ZSgpO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoIHdpZGdldF9yb3cuY3VycmVudF9lZGl0X2l0ZW0gJiYgd2lkZ2V0X3Jvdy5jdXJyZW50X2VkaXRfaXRlbS5wdW5jaF90YWdfaWQgKSB7XG5cdFx0XHRcdFx0XHRkYXRhLnB1bmNoX3RhZ19pZCA9IHdpZGdldF9yb3cuY3VycmVudF9lZGl0X2l0ZW0ucHVuY2hfdGFnX2lkO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRkYXRhLnB1bmNoX3RhZ19pZCA9IGZhbHNlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0fVxuXHRcdHZhciByb3cgPSB0aGlzLmdldFJvd1JlbmRlcigpOyAvL0dldCBSb3cgcmVuZGVyXG5cdFx0dmFyIHJlbmRlciA9IHRoaXMuZ2V0UmVuZGVyKCk7IC8vZ2V0IHJlbmRlciwgc2hvdWxkIGJlIGEgdGFibGVcblx0XHR2YXIgd2lkZ2V0cyA9IHt9OyAvL1NhdmUgZWFjaCByb3cncyB3aWRnZXRzXG5cdFx0dmFyIGZvcm1faXRlbV9pbnB1dDtcblx0XHQvL0J1aWxkIHJvdyB3aWRnZXRzXG5cdFx0Ly9CcmFuY2hcblx0XHRpZiAoIHRoaXMucGFyZW50X2NvbnRyb2xsZXIuc2hvd19icmFuY2hfdWkgKSB7XG5cdFx0XHRpZiAoIGRhdGEuaGFzT3duUHJvcGVydHkoICdvdmVycmlkZScgKSAmJiAhZGF0YS5vdmVycmlkZSApIHtcblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5URVhUICk7XG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dC5UVGV4dCggeyBmaWVsZDogJ2JyYW5jaCcgfSApO1xuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQuc2V0VmFsdWUoIGRhdGEuYnJhbmNoICk7XG5cdFx0XHRcdHJvdy5jaGlsZHJlbigpLmVxKCAyICkuYXBwZW5kKCBmb3JtX2l0ZW1faW5wdXQgKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1ggKTtcblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0LkFDb21ib0JveCgge1xuXHRcdFx0XHRcdGFwaV9jbGFzczogVFRBUEkuQVBJQnJhbmNoLFxuXHRcdFx0XHRcdHdpZHRoOiA5MCxcblx0XHRcdFx0XHRsYXlvdXRfbmFtZTogJ2dsb2JhbF9icmFuY2gnLFxuXHRcdFx0XHRcdHNob3dfc2VhcmNoX2lucHV0czogdHJ1ZSxcblx0XHRcdFx0XHRzZXRfZW1wdHk6IHRydWUsXG5cdFx0XHRcdFx0ZmllbGQ6ICdicmFuY2hfaWQnLFxuXHRcdFx0XHRcdGlzX3N0YXRpY193aWR0aDogdHJ1ZVxuXHRcdFx0XHR9ICk7XG5cdFx0XHRcdHdpZGdldHNbZm9ybV9pdGVtX2lucHV0LmdldEZpZWxkKCldID0gZm9ybV9pdGVtX2lucHV0O1xuXHRcdFx0XHRhcmdzID0ge307XG5cdFx0XHRcdGFyZ3MuZmlsdGVyX2RhdGEgPSB7IHVzZXJfaWQ6IHRoaXMucGFyZW50X2NvbnRyb2xsZXIuZ2V0U2VsZWN0RW1wbG95ZWUoKSB9O1xuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQuc2V0RGVmYXVsdEFyZ3MoIGFyZ3MgKTtcblx0XHRcdFx0dmFyIGJyYW5jaF9pZCA9IGRhdGEuaGFzT3duUHJvcGVydHkoICdicmFuY2hfaWQnICkgPyBkYXRhLmJyYW5jaF9pZCA6IHRoaXMucGFyZW50X2NvbnRyb2xsZXIuZ2V0U2VsZWN0RW1wbG95ZWUoIHRydWUgKS5kZWZhdWx0X2JyYW5jaF9pZDtcblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0LnNldFZhbHVlKCBkYXRhLmhhc093blByb3BlcnR5KCAnYnJhbmNoX2lkJyApID8gZGF0YS5icmFuY2hfaWQgOiB0aGlzLnBhcmVudF9jb250cm9sbGVyLmdldFNlbGVjdEVtcGxveWVlKCB0cnVlICkuZGVmYXVsdF9icmFuY2hfaWQgKTtcblx0XHRcdFx0cm93LmNoaWxkcmVuKCkuZXEoIDIgKS5hcHBlbmQoIGZvcm1faXRlbV9pbnB1dCApO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRyb3cuY2hpbGRyZW4oKS5lcSggMiApLmhpZGUoKTtcblx0XHR9XG5cdFx0Ly9EZXBhcnRtZW50XG5cdFx0aWYgKCB0aGlzLnBhcmVudF9jb250cm9sbGVyLnNob3dfZGVwYXJ0bWVudF91aSApIHtcblx0XHRcdGlmICggZGF0YS5oYXNPd25Qcm9wZXJ0eSggJ292ZXJyaWRlJyApICYmICFkYXRhLm92ZXJyaWRlICkge1xuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLlRFWFQgKTtcblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0LlRUZXh0KCB7IGZpZWxkOiAnZGVwYXJ0bWVudCcgfSApO1xuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQuc2V0VmFsdWUoIGRhdGEuZGVwYXJ0bWVudCApO1xuXHRcdFx0XHRyb3cuY2hpbGRyZW4oKS5lcSggMyApLmFwcGVuZCggZm9ybV9pdGVtX2lucHV0ICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLkFXRVNPTUVfQk9YICk7XG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dC5BQ29tYm9Cb3goIHtcblx0XHRcdFx0XHRhcGlfY2xhc3M6IFRUQVBJLkFQSURlcGFydG1lbnQsXG5cdFx0XHRcdFx0d2lkdGg6IDkwLFxuXHRcdFx0XHRcdGxheW91dF9uYW1lOiAnZ2xvYmFsX2RlcGFydG1lbnQnLFxuXHRcdFx0XHRcdHNob3dfc2VhcmNoX2lucHV0czogdHJ1ZSxcblx0XHRcdFx0XHRzZXRfZW1wdHk6IHRydWUsXG5cdFx0XHRcdFx0ZmllbGQ6ICdkZXBhcnRtZW50X2lkJyxcblx0XHRcdFx0XHRpc19zdGF0aWNfd2lkdGg6IHRydWVcblx0XHRcdFx0fSApO1xuXHRcdFx0XHR3aWRnZXRzW2Zvcm1faXRlbV9pbnB1dC5nZXRGaWVsZCgpXSA9IGZvcm1faXRlbV9pbnB1dDtcblx0XHRcdFx0YXJncyA9IHt9O1xuXHRcdFx0XHRhcmdzLmZpbHRlcl9kYXRhID0geyB1c2VyX2lkOiB0aGlzLnBhcmVudF9jb250cm9sbGVyLmdldFNlbGVjdEVtcGxveWVlKCksIGJyYW5jaF9pZDogYnJhbmNoX2lkIH07XG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dC5zZXREZWZhdWx0QXJncyggYXJncyApO1xuXHRcdFx0XHR2YXIgZGVwYXJ0bWVudF9pZCA9IGRhdGEuaGFzT3duUHJvcGVydHkoICdkZXBhcnRtZW50X2lkJyApID8gZGF0YS5kZXBhcnRtZW50X2lkIDogdGhpcy5wYXJlbnRfY29udHJvbGxlci5nZXRTZWxlY3RFbXBsb3llZSggdHJ1ZSApLmRlZmF1bHRfZGVwYXJ0bWVudF9pZDtcblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0LnNldFZhbHVlKCBkYXRhLmhhc093blByb3BlcnR5KCAnZGVwYXJ0bWVudF9pZCcgKSA/IGRhdGEuZGVwYXJ0bWVudF9pZCA6IHRoaXMucGFyZW50X2NvbnRyb2xsZXIuZ2V0U2VsZWN0RW1wbG95ZWUoIHRydWUgKS5kZWZhdWx0X2RlcGFydG1lbnRfaWQgKTtcblx0XHRcdFx0cm93LmNoaWxkcmVuKCkuZXEoIDMgKS5hcHBlbmQoIGZvcm1faXRlbV9pbnB1dCApO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRyb3cuY2hpbGRyZW4oKS5lcSggMyApLmhpZGUoKTtcblx0XHR9XG5cdFx0Ly9Kb2Jcblx0XHRpZiAoIHRoaXMucGFyZW50X2NvbnRyb2xsZXIuc2hvd19qb2JfdWkgJiYgR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSB7XG5cdFx0XHRpZiAoIGRhdGEuaGFzT3duUHJvcGVydHkoICdvdmVycmlkZScgKSAmJiAhZGF0YS5vdmVycmlkZSApIHtcblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5URVhUICk7XG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dC5UVGV4dCggeyBmaWVsZDogJ2pvYicgfSApO1xuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQuc2V0VmFsdWUoIGRhdGEuam9iICk7XG5cdFx0XHRcdHJvdy5jaGlsZHJlbigpLmVxKCA0ICkuYXBwZW5kKCBmb3JtX2l0ZW1faW5wdXQgKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHZhciBqb2JfZm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWCApO1xuXHRcdFx0XHRqb2JfZm9ybV9pdGVtX2lucHV0LkFDb21ib0JveCgge1xuXHRcdFx0XHRcdGFwaV9jbGFzczogVFRBUEkuQVBJSm9iLFxuXHRcdFx0XHRcdHdpZHRoOiA5MCxcblx0XHRcdFx0XHRsYXlvdXRfbmFtZTogJ2dsb2JhbF9qb2InLFxuXHRcdFx0XHRcdHNob3dfc2VhcmNoX2lucHV0czogdHJ1ZSxcblx0XHRcdFx0XHRzZXRfZW1wdHk6IHRydWUsXG5cdFx0XHRcdFx0YWx3YXlzX2luY2x1ZGVfY29sdW1uczogWydncm91cF9pZCddLFxuXHRcdFx0XHRcdGZpZWxkOiAnam9iX2lkJyxcblx0XHRcdFx0XHRpc19zdGF0aWNfd2lkdGg6IHRydWUsXG5cdFx0XHRcdFx0c2V0UmVhbFZhbHVlQ2FsbEJhY2s6ICggZnVuY3Rpb24oIHZhbCApIHtcblx0XHRcdFx0XHRcdGlmICggdmFsICkge1xuXHRcdFx0XHRcdFx0XHRqb2JfY29kZXIuc2V0VmFsdWUoIHZhbC5tYW51YWxfaWQgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IClcblx0XHRcdFx0fSApO1xuXHRcdFx0XHR3aWRnZXRzW2pvYl9mb3JtX2l0ZW1faW5wdXQuZ2V0RmllbGQoKV0gPSBqb2JfZm9ybV9pdGVtX2lucHV0O1xuXHRcdFx0XHQvLyBTZXQgZGVmYXVsdCBhcmdzXG5cdFx0XHRcdGFyZ3MgPSB7fTtcblx0XHRcdFx0YXJncy5maWx0ZXJfZGF0YSA9IHsgc3RhdHVzX2lkOiAxMCwgdXNlcl9pZDogdGhpcy5wYXJlbnRfY29udHJvbGxlci5nZXRTZWxlY3RFbXBsb3llZSgpIH07XG5cdFx0XHRcdGpvYl9mb3JtX2l0ZW1faW5wdXQuc2V0RGVmYXVsdEFyZ3MoIGFyZ3MgKTtcblx0XHRcdFx0dmFyIGpvYl9pZCA9IGRhdGEuaGFzT3duUHJvcGVydHkoICdqb2JfaWQnICkgPyBkYXRhLmpvYl9pZCA6IHRoaXMucGFyZW50X2NvbnRyb2xsZXIuZ2V0U2VsZWN0RW1wbG95ZWUoIHRydWUgKS5kZWZhdWx0X2pvYl9pZDtcblx0XHRcdFx0am9iX2Zvcm1faXRlbV9pbnB1dC5zZXRWYWx1ZSggam9iX2lkICk7XG5cdFx0XHRcdHZhciBqb2JfY29kZXIgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLlRFWFRfSU5QVVQgKTtcblx0XHRcdFx0am9iX2NvZGVyLlRUZXh0SW5wdXQoIHsgZmllbGQ6ICdqb2JfcXVpY2tfc2VhcmNoJywgZGlzYWJsZV9rZXl1cF9ldmVudDogdHJ1ZSwgd2lkdGg6IDMwIH0gKTtcblx0XHRcdFx0am9iX2NvZGVyLmNzcyggJ2Rpc3BsYXknLCAnaW5saW5lLWJsb2NrJyApO1xuXHRcdFx0XHRqb2JfZm9ybV9pdGVtX2lucHV0LmNzcyggJ2Rpc3BsYXknLCAnaW5saW5lLWJsb2NrJyApO1xuXHRcdFx0XHRyb3cuY2hpbGRyZW4oKS5lcSggNCApLmFwcGVuZCggam9iX2NvZGVyICk7XG5cdFx0XHRcdHJvdy5jaGlsZHJlbigpLmVxKCA0ICkuYXBwZW5kKCBqb2JfZm9ybV9pdGVtX2lucHV0ICk7XG5cdFx0XHRcdGpvYl9jb2Rlci51bmJpbmQoICdmb3JtSXRlbUNoYW5nZScgKS5iaW5kKCAnZm9ybUl0ZW1DaGFuZ2UnLCBmdW5jdGlvbiggZSwgdGFyZ2V0ICkge1xuXHRcdFx0XHRcdG9uSm9iUXVpY2tTZWFyY2goIHRhcmdldC5nZXRGaWVsZCgpLCB0YXJnZXQuZ2V0VmFsdWUoKSApO1xuXHRcdFx0XHR9ICk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJvdy5jaGlsZHJlbigpLmVxKCA0ICkuaGlkZSgpO1xuXHRcdH1cblxuXHRcdC8vVGFza1xuXHRcdGlmICggdGhpcy5wYXJlbnRfY29udHJvbGxlci5zaG93X2pvYl9pdGVtX3VpICYmIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpID49IDIwICkge1xuXHRcdFx0aWYgKCBkYXRhLmhhc093blByb3BlcnR5KCAnb3ZlcnJpZGUnICkgJiYgIWRhdGEub3ZlcnJpZGUgKSB7XG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuVEVYVCApO1xuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQuVFRleHQoIHsgZmllbGQ6ICdqb2JfaXRlbScgfSApO1xuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQuc2V0VmFsdWUoIGRhdGEuam9iX2l0ZW0gKTtcblx0XHRcdFx0cm93LmNoaWxkcmVuKCkuZXEoIDUgKS5hcHBlbmQoIGZvcm1faXRlbV9pbnB1dCApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWCApO1xuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQuQUNvbWJvQm94KCB7XG5cdFx0XHRcdFx0YXBpX2NsYXNzOiBUVEFQSS5BUElKb2JJdGVtLFxuXHRcdFx0XHRcdHdpZHRoOiA5MCxcblx0XHRcdFx0XHRsYXlvdXRfbmFtZTogJ2dsb2JhbF9qb2JfaXRlbScsXG5cdFx0XHRcdFx0c2hvd19zZWFyY2hfaW5wdXRzOiB0cnVlLFxuXHRcdFx0XHRcdHNldF9lbXB0eTogdHJ1ZSxcblx0XHRcdFx0XHRhbHdheXNfaW5jbHVkZV9jb2x1bW5zOiBbJ2dyb3VwX2lkJ10sXG5cdFx0XHRcdFx0ZmllbGQ6ICdqb2JfaXRlbV9pZCcsXG5cdFx0XHRcdFx0aXNfc3RhdGljX3dpZHRoOiB0cnVlLFxuXHRcdFx0XHRcdHNldFJlYWxWYWx1ZUNhbGxCYWNrOiAoIGZ1bmN0aW9uKCB2YWwgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIHZhbCApIHtcblx0XHRcdFx0XHRcdFx0am9iX2l0ZW1fY29kZXIuc2V0VmFsdWUoIHZhbC5tYW51YWxfaWQgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IClcblx0XHRcdFx0fSApO1xuXHRcdFx0XHRhcmdzID0ge307XG5cdFx0XHRcdGFyZ3MuZmlsdGVyX2RhdGEgPSB7IHN0YXR1c19pZDogMTAsIGpvYl9pZDogam9iX2lkIH07XG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dC5zZXREZWZhdWx0QXJncyggYXJncyApO1xuXHRcdFx0XHR2YXIgam9iX2l0ZW1faWQgPSBkYXRhLmhhc093blByb3BlcnR5KCAnam9iX2l0ZW1faWQnICkgPyBkYXRhLmpvYl9pdGVtX2lkIDogdGhpcy5wYXJlbnRfY29udHJvbGxlci5nZXRTZWxlY3RFbXBsb3llZSggdHJ1ZSApLmRlZmF1bHRfam9iX2l0ZW1faWQ7XG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dC5zZXRWYWx1ZSggZGF0YS5oYXNPd25Qcm9wZXJ0eSggJ2pvYl9pdGVtX2lkJyApID8gZGF0YS5qb2JfaXRlbV9pZCA6IHRoaXMucGFyZW50X2NvbnRyb2xsZXIuZ2V0U2VsZWN0RW1wbG95ZWUoIHRydWUgKS5kZWZhdWx0X2pvYl9pdGVtX2lkICk7XG5cdFx0XHRcdHZhciBqb2JfaXRlbV9jb2RlciA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuVEVYVF9JTlBVVCApO1xuXHRcdFx0XHRqb2JfaXRlbV9jb2Rlci5UVGV4dElucHV0KCB7IGZpZWxkOiAnam9iX2l0ZW1fcXVpY2tfc2VhcmNoJywgZGlzYWJsZV9rZXl1cF9ldmVudDogdHJ1ZSwgd2lkdGg6IDMwIH0gKTtcblx0XHRcdFx0d2lkZ2V0c1tmb3JtX2l0ZW1faW5wdXQuZ2V0RmllbGQoKV0gPSBmb3JtX2l0ZW1faW5wdXQ7XG5cdFx0XHRcdGpvYl9pdGVtX2NvZGVyLmNzcyggJ2Rpc3BsYXknLCAnaW5saW5lLWJsb2NrJyApO1xuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQuY3NzKCAnZGlzcGxheScsICdpbmxpbmUtYmxvY2snICk7XG5cdFx0XHRcdHJvdy5jaGlsZHJlbigpLmVxKCA1ICkuYXBwZW5kKCBqb2JfaXRlbV9jb2RlciApO1xuXHRcdFx0XHRyb3cuY2hpbGRyZW4oKS5lcSggNSApLmFwcGVuZCggZm9ybV9pdGVtX2lucHV0ICk7XG5cdFx0XHRcdGpvYl9pdGVtX2NvZGVyLnVuYmluZCggJ2Zvcm1JdGVtQ2hhbmdlJyApLmJpbmQoICdmb3JtSXRlbUNoYW5nZScsIGZ1bmN0aW9uKCBlLCB0YXJnZXQgKSB7XG5cdFx0XHRcdFx0b25Kb2JRdWlja1NlYXJjaCggdGFyZ2V0LmdldEZpZWxkKCksIHRhcmdldC5nZXRWYWx1ZSgpICk7XG5cdFx0XHRcdH0gKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0cm93LmNoaWxkcmVuKCkuZXEoIDUgKS5oaWRlKCk7XG5cdFx0fVxuXG5cdFx0Ly9QdW5jaCBUYWdcblx0XHRpZiAoIHRoaXMucGFyZW50X2NvbnRyb2xsZXIuc2hvd19wdW5jaF90YWdfdWkgJiYgR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSB7XG5cdFx0XHRpZiAoIGRhdGEuaGFzT3duUHJvcGVydHkoICdvdmVycmlkZScgKSAmJiAhZGF0YS5vdmVycmlkZSApIHtcblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5URVhUICk7XG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dC5UVGV4dCggeyBmaWVsZDogJ3B1bmNoX3RhZycgfSApO1xuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQuc2V0VmFsdWUoIGRhdGEucHVuY2hfdGFnICk7XG5cdFx0XHRcdHJvdy5jaGlsZHJlbigpLmVxKCA2ICkuYXBwZW5kKCBmb3JtX2l0ZW1faW5wdXQgKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1ggKTtcblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0LkFDb21ib0JveCgge1xuXHRcdFx0XHRcdGFwaV9jbGFzczogVFRBUEkuQVBJUHVuY2hUYWcsXG5cdFx0XHRcdFx0YWxsb3dfbXVsdGlwbGVfc2VsZWN0aW9uOiB0cnVlLFxuXHRcdFx0XHRcdHdpZHRoOiA5MCxcblx0XHRcdFx0XHRsYXlvdXRfbmFtZTogJ2dsb2JhbF9wdW5jaF90YWcnLFxuXHRcdFx0XHRcdHNob3dfc2VhcmNoX2lucHV0czogdHJ1ZSxcblx0XHRcdFx0XHRzZXRfZW1wdHk6IHRydWUsXG5cdFx0XHRcdFx0YWx3YXlzX2luY2x1ZGVfY29sdW1uczogWydncm91cF9pZCddLFxuXHRcdFx0XHRcdGZpZWxkOiAncHVuY2hfdGFnX2lkJyxcblx0XHRcdFx0XHRpc19zdGF0aWNfd2lkdGg6IHRydWVcbi8qXHRcdFx0XHRcdHNldFJlYWxWYWx1ZUNhbGxCYWNrOiAoIGZ1bmN0aW9uKCB2YWwgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIHZhbCApIHtcblx0XHRcdFx0XHRcdFx0cHVuY2hfdGFnX2NvZGVyLnNldFZhbHVlKCB2YWwubWFudWFsX2lkICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSApKi9cblx0XHRcdFx0fSApO1xuXHRcdFx0XHRhcmdzID0ge307XG5cdFx0XHRcdGFyZ3MuZmlsdGVyX2RhdGEgPSB7XG5cdFx0XHRcdFx0c3RhdHVzX2lkOiAxMCxcblx0XHRcdFx0XHR1c2VyX2lkOiB0aGlzLnBhcmVudF9jb250cm9sbGVyLmdldFNlbGVjdEVtcGxveWVlKCB0cnVlICkuaWQsXG5cdFx0XHRcdFx0YnJhbmNoX2lkOiBicmFuY2hfaWQsXG5cdFx0XHRcdFx0ZGVwYXJ0bWVudF9pZDogZGVwYXJ0bWVudF9pZCxcblx0XHRcdFx0XHRqb2JfaWQ6IGpvYl9pZCxcblx0XHRcdFx0XHRqb2JfaXRlbV9pZDogam9iX2l0ZW1faWRcblx0XHRcdFx0fTtcblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0LnNldERlZmF1bHRBcmdzKCBhcmdzICk7XG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dC5zZXRWYWx1ZSggZGF0YS5oYXNPd25Qcm9wZXJ0eSggJ3B1bmNoX3RhZ19pZCcgKSA/IGRhdGEucHVuY2hfdGFnX2lkIDogdGhpcy5wYXJlbnRfY29udHJvbGxlci5nZXRTZWxlY3RFbXBsb3llZSggdHJ1ZSApLmRlZmF1bHRfcHVuY2hfdGFnX2lkICk7XG5cdFx0XHRcdC8vdmFyIHB1bmNoX3RhZ19jb2RlciA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuVEVYVF9JTlBVVCApO1xuXHRcdFx0XHQvL3B1bmNoX3RhZ19jb2Rlci5UVGV4dElucHV0KCB7IGZpZWxkOiAncHVuY2hfdGFnX3F1aWNrX3NlYXJjaCcsIGRpc2FibGVfa2V5dXBfZXZlbnQ6IHRydWUsIHdpZHRoOiAzMCB9ICk7XG5cdFx0XHRcdHdpZGdldHNbZm9ybV9pdGVtX2lucHV0LmdldEZpZWxkKCldID0gZm9ybV9pdGVtX2lucHV0O1xuXHRcdFx0XHQvL3B1bmNoX3RhZ19jb2Rlci5jc3MoICdkaXNwbGF5JywgJ2lubGluZS1ibG9jaycgKTtcblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0LmNzcyggJ2Rpc3BsYXknLCAnaW5saW5lLWJsb2NrJyApO1xuXHRcdFx0XHQvL3Jvdy5jaGlsZHJlbigpLmVxKCA2ICkuYXBwZW5kKCBwdW5jaF90YWdfY29kZXIgKTtcblx0XHRcdFx0cm93LmNoaWxkcmVuKCkuZXEoIDYgKS5hcHBlbmQoIGZvcm1faXRlbV9pbnB1dCApO1xuLypcdFx0XHRcdHB1bmNoX3RhZ19jb2Rlci51bmJpbmQoICdmb3JtSXRlbUNoYW5nZScgKS5iaW5kKCAnZm9ybUl0ZW1DaGFuZ2UnLCBmdW5jdGlvbiggZSwgdGFyZ2V0ICkge1xuXHRcdFx0XHRcdG9uUHVuY2hUYWdRdWlja1NlYXJjaCggdGFyZ2V0LmdldEZpZWxkKCksIHRhcmdldC5nZXRWYWx1ZSgpICk7XG5cdFx0XHRcdH0gKTsqL1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRyb3cuY2hpbGRyZW4oKS5lcSggNiApLmhpZGUoKTtcblx0XHR9XG5cblx0XHQvL2RheSAwXG5cdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5URVhUX0lOUFVUICk7XG5cdFx0Zm9ybV9pdGVtX2lucHV0LlRUZXh0SW5wdXQoIHtcblx0XHRcdGZpZWxkOiB0aGlzLnBhcmVudF9jb250cm9sbGVyLmRheV9kaWNbJ2RheV8wJ10uZmllbGQsXG5cdFx0XHR3aWR0aDogNTUsXG5cdFx0XHRtb2RlOiAndGltZV91bml0Jyxcblx0XHRcdGRpc3BsYXlfbmE6IGZhbHNlLFxuXHRcdFx0bmVlZF9wYXJzZXJfc2VjOiB0cnVlLFxuXHRcdFx0ZG9fdmFsaWRhdGU6IGZhbHNlXG5cdFx0fSApO1xuXHRcdGZvcm1faXRlbV9pbnB1dC5zZXRWYWx1ZSggZGF0YVtmb3JtX2l0ZW1faW5wdXQuZ2V0RmllbGQoKV0gPyBkYXRhW2Zvcm1faXRlbV9pbnB1dC5nZXRGaWVsZCgpXS50b3RhbF90aW1lIDogMCApO1xuXHRcdHdpZGdldHNbZm9ybV9pdGVtX2lucHV0LmdldEZpZWxkKCldID0gZm9ybV9pdGVtX2lucHV0O1xuXHRcdHJvdy5jaGlsZHJlbigpLmVxKCA3ICkuYXBwZW5kKCBmb3JtX2l0ZW1faW5wdXQgKTtcblxuXHRcdC8vZGF5IDFcblx0XHRmb3JtX2l0ZW1faW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLlRFWFRfSU5QVVQgKTtcblx0XHRmb3JtX2l0ZW1faW5wdXQuVFRleHRJbnB1dCgge1xuXHRcdFx0ZmllbGQ6IHRoaXMucGFyZW50X2NvbnRyb2xsZXIuZGF5X2RpY1snZGF5XzEnXS5maWVsZCxcblx0XHRcdHdpZHRoOiA1NSxcblx0XHRcdG1vZGU6ICd0aW1lX3VuaXQnLFxuXHRcdFx0ZGlzcGxheV9uYTogZmFsc2UsXG5cdFx0XHRuZWVkX3BhcnNlcl9zZWM6IHRydWUsXG5cdFx0XHRkb192YWxpZGF0ZTogZmFsc2Vcblx0XHR9ICk7XG5cdFx0Zm9ybV9pdGVtX2lucHV0LnNldFZhbHVlKCBkYXRhW2Zvcm1faXRlbV9pbnB1dC5nZXRGaWVsZCgpXSA/IGRhdGFbZm9ybV9pdGVtX2lucHV0LmdldEZpZWxkKCldLnRvdGFsX3RpbWUgOiAwICk7XG5cdFx0d2lkZ2V0c1tmb3JtX2l0ZW1faW5wdXQuZ2V0RmllbGQoKV0gPSBmb3JtX2l0ZW1faW5wdXQ7XG5cdFx0cm93LmNoaWxkcmVuKCkuZXEoIDggKS5hcHBlbmQoIGZvcm1faXRlbV9pbnB1dCApO1xuXG5cdFx0Ly9kYXkgMlxuXHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuVEVYVF9JTlBVVCApO1xuXHRcdGZvcm1faXRlbV9pbnB1dC5UVGV4dElucHV0KCB7XG5cdFx0XHRmaWVsZDogdGhpcy5wYXJlbnRfY29udHJvbGxlci5kYXlfZGljWydkYXlfMiddLmZpZWxkLFxuXHRcdFx0d2lkdGg6IDU1LFxuXHRcdFx0bW9kZTogJ3RpbWVfdW5pdCcsXG5cdFx0XHRkaXNwbGF5X25hOiBmYWxzZSxcblx0XHRcdG5lZWRfcGFyc2VyX3NlYzogdHJ1ZSxcblx0XHRcdGRvX3ZhbGlkYXRlOiBmYWxzZVxuXHRcdH0gKTtcblx0XHRmb3JtX2l0ZW1faW5wdXQuc2V0VmFsdWUoIGRhdGFbZm9ybV9pdGVtX2lucHV0LmdldEZpZWxkKCldID8gZGF0YVtmb3JtX2l0ZW1faW5wdXQuZ2V0RmllbGQoKV0udG90YWxfdGltZSA6IDAgKTtcblx0XHR3aWRnZXRzW2Zvcm1faXRlbV9pbnB1dC5nZXRGaWVsZCgpXSA9IGZvcm1faXRlbV9pbnB1dDtcblx0XHRyb3cuY2hpbGRyZW4oKS5lcSggOSApLmFwcGVuZCggZm9ybV9pdGVtX2lucHV0ICk7XG5cblx0XHQvL2RheSAzXG5cdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5URVhUX0lOUFVUICk7XG5cdFx0Zm9ybV9pdGVtX2lucHV0LlRUZXh0SW5wdXQoIHtcblx0XHRcdGZpZWxkOiB0aGlzLnBhcmVudF9jb250cm9sbGVyLmRheV9kaWNbJ2RheV8zJ10uZmllbGQsXG5cdFx0XHR3aWR0aDogNTUsXG5cdFx0XHRtb2RlOiAndGltZV91bml0Jyxcblx0XHRcdGRpc3BsYXlfbmE6IGZhbHNlLFxuXHRcdFx0bmVlZF9wYXJzZXJfc2VjOiB0cnVlLFxuXHRcdFx0ZG9fdmFsaWRhdGU6IGZhbHNlXG5cdFx0fSApO1xuXHRcdGZvcm1faXRlbV9pbnB1dC5zZXRWYWx1ZSggZGF0YVtmb3JtX2l0ZW1faW5wdXQuZ2V0RmllbGQoKV0gPyBkYXRhW2Zvcm1faXRlbV9pbnB1dC5nZXRGaWVsZCgpXS50b3RhbF90aW1lIDogMCApO1xuXHRcdHdpZGdldHNbZm9ybV9pdGVtX2lucHV0LmdldEZpZWxkKCldID0gZm9ybV9pdGVtX2lucHV0O1xuXHRcdHJvdy5jaGlsZHJlbigpLmVxKCAxMCApLmFwcGVuZCggZm9ybV9pdGVtX2lucHV0ICk7XG5cblx0XHQvL2RheSA0XG5cdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5URVhUX0lOUFVUICk7XG5cdFx0Zm9ybV9pdGVtX2lucHV0LlRUZXh0SW5wdXQoIHtcblx0XHRcdGZpZWxkOiB0aGlzLnBhcmVudF9jb250cm9sbGVyLmRheV9kaWNbJ2RheV80J10uZmllbGQsXG5cdFx0XHR3aWR0aDogNTUsXG5cdFx0XHRtb2RlOiAndGltZV91bml0Jyxcblx0XHRcdGRpc3BsYXlfbmE6IGZhbHNlLFxuXHRcdFx0bmVlZF9wYXJzZXJfc2VjOiB0cnVlLFxuXHRcdFx0ZG9fdmFsaWRhdGU6IGZhbHNlXG5cdFx0fSApO1xuXHRcdGZvcm1faXRlbV9pbnB1dC5zZXRWYWx1ZSggZGF0YVtmb3JtX2l0ZW1faW5wdXQuZ2V0RmllbGQoKV0gPyBkYXRhW2Zvcm1faXRlbV9pbnB1dC5nZXRGaWVsZCgpXS50b3RhbF90aW1lIDogMCApO1xuXHRcdHdpZGdldHNbZm9ybV9pdGVtX2lucHV0LmdldEZpZWxkKCldID0gZm9ybV9pdGVtX2lucHV0O1xuXHRcdHJvdy5jaGlsZHJlbigpLmVxKCAxMSApLmFwcGVuZCggZm9ybV9pdGVtX2lucHV0ICk7XG5cblx0XHQvL2RheSA1XG5cdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5URVhUX0lOUFVUICk7XG5cdFx0Zm9ybV9pdGVtX2lucHV0LlRUZXh0SW5wdXQoIHtcblx0XHRcdGZpZWxkOiB0aGlzLnBhcmVudF9jb250cm9sbGVyLmRheV9kaWNbJ2RheV81J10uZmllbGQsXG5cdFx0XHR3aWR0aDogNTUsXG5cdFx0XHRtb2RlOiAndGltZV91bml0Jyxcblx0XHRcdGRpc3BsYXlfbmE6IGZhbHNlLFxuXHRcdFx0bmVlZF9wYXJzZXJfc2VjOiB0cnVlLFxuXHRcdFx0ZG9fdmFsaWRhdGU6IGZhbHNlXG5cdFx0fSApO1xuXHRcdGZvcm1faXRlbV9pbnB1dC5zZXRWYWx1ZSggZGF0YVtmb3JtX2l0ZW1faW5wdXQuZ2V0RmllbGQoKV0gPyBkYXRhW2Zvcm1faXRlbV9pbnB1dC5nZXRGaWVsZCgpXS50b3RhbF90aW1lIDogMCApO1xuXHRcdHdpZGdldHNbZm9ybV9pdGVtX2lucHV0LmdldEZpZWxkKCldID0gZm9ybV9pdGVtX2lucHV0O1xuXHRcdHJvdy5jaGlsZHJlbigpLmVxKCAxMiApLmFwcGVuZCggZm9ybV9pdGVtX2lucHV0ICk7XG5cblx0XHQvL2RheSA2XG5cdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5URVhUX0lOUFVUICk7XG5cdFx0Zm9ybV9pdGVtX2lucHV0LlRUZXh0SW5wdXQoIHtcblx0XHRcdGZpZWxkOiB0aGlzLnBhcmVudF9jb250cm9sbGVyLmRheV9kaWNbJ2RheV82J10uZmllbGQsXG5cdFx0XHR3aWR0aDogNTUsXG5cdFx0XHRtb2RlOiAndGltZV91bml0Jyxcblx0XHRcdGRpc3BsYXlfbmE6IGZhbHNlLFxuXHRcdFx0bmVlZF9wYXJzZXJfc2VjOiB0cnVlLFxuXHRcdFx0ZG9fdmFsaWRhdGU6IGZhbHNlXG5cdFx0fSApO1xuXHRcdGZvcm1faXRlbV9pbnB1dC5zZXRWYWx1ZSggZGF0YVtmb3JtX2l0ZW1faW5wdXQuZ2V0RmllbGQoKV0gPyBkYXRhW2Zvcm1faXRlbV9pbnB1dC5nZXRGaWVsZCgpXS50b3RhbF90aW1lIDogMCApO1xuXHRcdHdpZGdldHNbZm9ybV9pdGVtX2lucHV0LmdldEZpZWxkKCldID0gZm9ybV9pdGVtX2lucHV0O1xuXHRcdHJvdy5jaGlsZHJlbigpLmVxKCAxMyApLmFwcGVuZCggZm9ybV9pdGVtX2lucHV0ICk7XG5cdFx0aWYgKCBkYXRhLmhhc093blByb3BlcnR5KCAnb3ZlcnJpZGUnICkgJiYgIWRhdGEub3ZlcnJpZGUgKSB7XG5cdFx0XHRyb3cuY2hpbGRyZW4oKS5lcSggMSApLmNoaWxkcmVuKCkuaGlkZSgpO1xuXHRcdH1cblxuXHRcdHZhciBkaXNhYmxlX3BsdXMgPSBmYWxzZTtcblx0XHR2YXIgZGlzYWJsZV9taW51cyA9IGZhbHNlO1xuXHRcdHZhciBkaXNhYmxlX2Ryb3Bkb3ducyA9IGZhbHNlO1xuXG5cdFx0Zm9yICggdmFyIGtleSBpbiB3aWRnZXRzICkge1xuXHRcdFx0dmFyIGl0ZW0gPSB3aWRnZXRzW2tleV07XG5cblx0XHRcdC8vZGlzYWJsZSBpZiBhbGwgcGF5X3BlcmlvZHMgdmlzaWJsZSBhcmUgbm90IG9wZW4uXG5cdFx0XHR2YXIgaW52YWxpZCA9IDA7XG5cblx0XHRcdGZvciAoIHZhciBuIGluIHRoaXMucGFyZW50X2NvbnRyb2xsZXIuZnVsbF90aW1lc2hlZXRfZGF0YS5wYXlfcGVyaW9kX2RhdGEgKSB7XG5cdFx0XHRcdGlmICggdGhpcy5wYXJlbnRfY29udHJvbGxlci5mdWxsX3RpbWVzaGVldF9kYXRhLnBheV9wZXJpb2RfZGF0YVtuXS5zdGF0dXNfaWQgIT0gMTAgJiYgdGhpcy5wYXJlbnRfY29udHJvbGxlci5mdWxsX3RpbWVzaGVldF9kYXRhLnBheV9wZXJpb2RfZGF0YVtuXS5zdGF0dXNfaWQgIT0gMzAgKSB7XG5cdFx0XHRcdFx0aW52YWxpZCsrO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmICggaW52YWxpZCA+IDAgJiYgaW52YWxpZCA9PSBPYmplY3Qua2V5cyggdGhpcy5wYXJlbnRfY29udHJvbGxlci5mdWxsX3RpbWVzaGVldF9kYXRhLnBheV9wZXJpb2RfZGF0YSApLmxlbmd0aCApIHtcblx0XHRcdFx0aWYgKCB0aGlzLnBhcmVudF9jb250cm9sbGVyLmZ1bGxfdGltZXNoZWV0X2RhdGEucHVuY2hfZGF0YS5sZW5ndGggIT0gMCApIHtcblx0XHRcdFx0XHRkaXNhYmxlX3BsdXMgPSB0cnVlO1xuXHRcdFx0XHRcdGRpc2FibGVfbWludXMgPSB0cnVlO1xuXHRcdFx0XHRcdGlmICggT2JqZWN0LmtleXMoIGRhdGEgKS5sZW5ndGggPT0gMCApIHtcblx0XHRcdFx0XHRcdHJldHVybjsgLy9kb24ndCBzaG93IGEgYmxhbmsgcm93IGlmIGFsbCBwYXkgcGVyaW9kcyBhcmUgY2xvc2VkXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vZGlzYWJsZSBmaWVsZHMgdW5kZXIgY2xvc2VkIHBheSBwZXJpb2RzXG5cdFx0XHRpZiAoIHRoaXMucGFyZW50X2NvbnRyb2xsZXIuZnVsbF90aW1lc2hlZXRfZGF0YS5wYXlfcGVyaW9kX2RhdGFbdGhpcy5wYXJlbnRfY29udHJvbGxlci5mdWxsX3RpbWVzaGVldF9kYXRhLnRpbWVzaGVldF9kYXRlcy5wYXlfcGVyaW9kX2RhdGVfbWFwW2l0ZW0uZ2V0RmllbGQoKV1dICkge1xuXHRcdFx0XHR2YXIgZmllbGRfcGF5X3BlcmlvZF9zdGF0dXMgPSBwYXJzZUludCggdGhpcy5wYXJlbnRfY29udHJvbGxlci5mdWxsX3RpbWVzaGVldF9kYXRhLnBheV9wZXJpb2RfZGF0YVt0aGlzLnBhcmVudF9jb250cm9sbGVyLmZ1bGxfdGltZXNoZWV0X2RhdGEudGltZXNoZWV0X2RhdGVzLnBheV9wZXJpb2RfZGF0ZV9tYXBbaXRlbS5nZXRGaWVsZCgpXV0uc3RhdHVzX2lkICk7XG5cdFx0XHRcdGlmICggZmllbGRfcGF5X3BlcmlvZF9zdGF0dXMgIT0gMTAgJiYgZmllbGRfcGF5X3BlcmlvZF9zdGF0dXMgIT0gMzAgKSB7XG5cdFx0XHRcdFx0aXRlbS5zZXRFbmFibGVkICYmIGl0ZW0uc2V0RW5hYmxlZCggZmFsc2UgKTtcblx0XHRcdFx0XHRpZiAoIGl0ZW0uZ2V0RmllbGQoKSAhPSAnYnJhbmNoX2lkJyAmJiBpdGVtLmdldEZpZWxkKCkgIT0gJ2RlcGFydG1lbnRfaWQnICYmIGl0ZW0uZ2V0RmllbGQoKSAhPSAnam9iX2lkJyAmJiBpdGVtLmdldEZpZWxkKCkgIT0gJ2pvYl9pdGVtX2lkJyAmJiBpdGVtLmdldEZpZWxkKCkgIT0gJ3B1bmNoX3RhZ19pZCcgJiYgdHlwZW9mIGRhdGFbaXRlbS5nZXRGaWVsZCgpXSAhPSAndW5kZWZpbmVkJyApIHtcblx0XHRcdFx0XHRcdC8vb25seSBkaXNhYmxlIGRyb3Bkb3ducyBpZiB0aGVyZSBpcyBkYXRhIGluIHRoZSBkaXNhYmxlZCBmaWVsZHNcblx0XHRcdFx0XHRcdGRpc2FibGVfZHJvcGRvd25zID0gdHJ1ZTtcblx0XHRcdFx0XHRcdGRpc2FibGVfbWludXMgPSB0cnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGRhdGEuaGFzT3duUHJvcGVydHkoICdvdmVycmlkZScgKSAmJiAhZGF0YS5vdmVycmlkZSApIHtcblx0XHRcdFx0aXRlbS5zZXRFbmFibGVkICYmIGl0ZW0uc2V0RW5hYmxlZCggZmFsc2UgKTtcblx0XHRcdFx0aXRlbS5nZXRWYWx1ZSgpID4gMCAmJiBpdGVtLmhhc0NsYXNzKCAndC10ZXh0LWlucHV0JyApID49IDAgJiYgaXRlbS5jc3MoICdjb2xvcicsICdyZWQnICk7XG5cdFx0XHR9XG5cdFx0XHRpdGVtLnVuYmluZCggJ2Zvcm1JdGVtQ2hhbmdlJyApLmJpbmQoICdmb3JtSXRlbUNoYW5nZScsIGZ1bmN0aW9uKCBlLCB0YXJnZXQgKSB7XG5cdFx0XHRcdHRhcmdldC5pc19jaGFuZ2VkID0gdHJ1ZTtcblx0XHRcdFx0aWYgKCB0YXJnZXQuZ2V0RmllbGQoKSA9PT0gJ2pvYl9pZCcgKSB7XG5cdFx0XHRcdFx0d2lkZ2V0cy5pc19jaGFuZ2VkID0gdHJ1ZTtcblx0XHRcdFx0XHRqb2JfY29kZXIuc2V0VmFsdWUoIHRhcmdldC5nZXRWYWx1ZSggdHJ1ZSApID8gKCB0YXJnZXQuZ2V0VmFsdWUoIHRydWUgKS5tYW51YWxfaWQgPyB0YXJnZXQuZ2V0VmFsdWUoIHRydWUgKS5tYW51YWxfaWQgOiAnJyApIDogJycgKTtcblx0XHRcdFx0XHRzZXRKb2JJdGVtVmFsdWVXaGVuSm9iQ2hhbmdlZCggdGFyZ2V0LmdldFZhbHVlKCB0cnVlICkgKTtcblx0XHRcdFx0XHRzZXRQdW5jaFRhZ1ZhbHVlc1doZW5Dcml0ZXJpYUNoYW5nZWQoIGRhdGEgKTtcblx0XHRcdFx0fSBlbHNlIGlmICggdGFyZ2V0LmdldEZpZWxkKCkgPT09ICdqb2JfaXRlbV9pZCcgKSB7XG5cdFx0XHRcdFx0d2lkZ2V0cy5pc19jaGFuZ2VkID0gdHJ1ZTtcblx0XHRcdFx0XHRqb2JfaXRlbV9jb2Rlci5zZXRWYWx1ZSggdGFyZ2V0LmdldFZhbHVlKCB0cnVlICkgPyAoIHRhcmdldC5nZXRWYWx1ZSggdHJ1ZSApLm1hbnVhbF9pZCA/IHRhcmdldC5nZXRWYWx1ZSggdHJ1ZSApLm1hbnVhbF9pZCA6ICcnICkgOiAnJyApO1xuXHRcdFx0XHRcdHNldFB1bmNoVGFnVmFsdWVzV2hlbkNyaXRlcmlhQ2hhbmdlZCggZGF0YSApO1xuXHRcdFx0XHR9IGVsc2UgaWYgKCB0YXJnZXQuZ2V0RmllbGQoKSA9PT0gJ2JyYW5jaF9pZCcgKSB7XG5cdFx0XHRcdFx0d2lkZ2V0cy5pc19jaGFuZ2VkID0gdHJ1ZTtcblx0XHRcdFx0XHRpZiAoICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSApIHtcblx0XHRcdFx0XHRcdHNldERlcGFydG1lbnRWYWx1ZVdoZW5CcmFuY2hDaGFuZ2VkKCBkYXRhICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IGVsc2UgaWYgKCB0YXJnZXQuZ2V0RmllbGQoKSA9PT0gJ2RlcGFydG1lbnRfaWQnICkge1xuXHRcdFx0XHRcdHdpZGdldHMuaXNfY2hhbmdlZCA9IHRydWU7XG5cdFx0XHRcdH0gZWxzZSBpZiAoIHRhcmdldC5nZXRGaWVsZCgpID09PSAncHVuY2hfdGFnX2lkJyApIHtcblx0XHRcdFx0XHR3aWRnZXRzLmlzX2NoYW5nZWQgPSB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdCR0aGlzLnBhcmVudF9jb250cm9sbGVyLmF1dG9TYXZlTWFudWFsUHVuY2goKTtcblx0XHRcdH0gKTtcblx0XHR9XG5cblx0XHRpZiAoIGRpc2FibGVfZHJvcGRvd25zICkge1xuXHRcdFx0Zm9yICggdmFyIGtleSBpbiB3aWRnZXRzICkge1xuXHRcdFx0XHR2YXIgaXRlbSA9IHdpZGdldHNba2V5XTtcblx0XHRcdFx0aWYgKCBpdGVtLmdldEZpZWxkKCkgPT0gJ2JyYW5jaF9pZCcgfHwgaXRlbS5nZXRGaWVsZCgpID09ICdkZXBhcnRtZW50X2lkJyB8fCBpdGVtLmdldEZpZWxkKCkgPT0gJ2pvYl9pZCcgfHwgaXRlbS5nZXRGaWVsZCgpID09ICdqb2JfaXRlbV9pZCcgKSB7XG5cdFx0XHRcdFx0aWYgKCBpdGVtLmdldEZpZWxkKCkgPT0gJ2pvYl9pZCcgfHwgaXRlbS5nZXRGaWVsZCgpID09ICdqb2JfaXRlbV9pZCcgfHwgaXRlbS5nZXRGaWVsZCgpID09ICdwdW5jaF90YWdfaWQnICkge1xuXHRcdFx0XHRcdFx0aXRlbS5wYXJlbnRzKCAndGQnICkuZmluZCggJ2lucHV0W3R5cGU9XCJ0ZXh0XCJdJyApLmhpZGUoKTsgLy9oaWRlIGpvYiBhbmQgdGFzayBsb29rdXAgYm94XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGl0ZW0uc2V0RW5hYmxlZCAmJiBpdGVtLnNldEVuYWJsZWQoIGZhbHNlICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoIGRpc2FibGVfcGx1cyA9PSB0cnVlICkge1xuXHRcdFx0cm93LmZpbmQoICcucGx1cy1pY29uJyApLmhpZGUoKTtcblx0XHR9XG5cblx0XHRpZiAoIGRpc2FibGVfbWludXMgPT0gdHJ1ZSApIHtcblx0XHRcdHJvdy5maW5kKCAnLm1pbnVzLWljb24nICkuaGlkZSgpO1xuXHRcdH1cblxuXHRcdGlmICggdHlwZW9mIGluZGV4ICE9ICd1bmRlZmluZWQnICkge1xuXHRcdFx0cm93Lmluc2VydEFmdGVyKCAkKCByZW5kZXIgKS5maW5kKCAndHInICkuZXEoIGluZGV4ICkgKTtcblx0XHRcdHRoaXMucm93c193aWRnZXRzX2FycmF5LnNwbGljZSggKCBpbmRleCApLCAwLCB3aWRnZXRzICk7XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0JCggcmVuZGVyICkuYXBwZW5kKCByb3cgKTtcblx0XHRcdHRoaXMucm93c193aWRnZXRzX2FycmF5LnB1c2goIHdpZGdldHMgKTtcblx0XHR9XG5cdFx0Ly9TYXZlIGN1cnJlbnQgc2V0IGl0ZW1cblx0XHR3aWRnZXRzLmN1cnJlbnRfZWRpdF9pdGVtID0gZGF0YTtcblx0XHR0aGlzLmFkZEljb25zRXZlbnQoIHJvdyApOyAvL0JpbmQgZXZlbnQgdG8gYWRkIGFuZCBtaW51cyBpY29uXG5cblx0XHRmdW5jdGlvbiBvbkpvYlF1aWNrU2VhcmNoKCBrZXksIHZhbHVlICkge1xuXHRcdFx0dmFyIGFyZ3MgPSB7fTtcblx0XHRcdGlmICgga2V5ID09PSAnam9iX3F1aWNrX3NlYXJjaCcgKSB7XG5cdFx0XHRcdGFyZ3MuZmlsdGVyX2RhdGEgPSB7XG5cdFx0XHRcdFx0bWFudWFsX2lkOiB2YWx1ZSxcblx0XHRcdFx0XHR1c2VyX2lkOiAkdGhpcy5wYXJlbnRfY29udHJvbGxlci5nZXRTZWxlY3RFbXBsb3llZSgpLFxuXHRcdFx0XHRcdHN0YXR1c19pZDogJzEwJ1xuXHRcdFx0XHR9O1xuXHRcdFx0XHRqb2JfYXBpLmdldEpvYiggYXJncywge1xuXHRcdFx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHRcdFx0dmFyIHJlc3VsdF9kYXRhID0gcmVzdWx0LmdldFJlc3VsdCgpO1xuXHRcdFx0XHRcdFx0d2lkZ2V0cy5pc19jaGFuZ2VkID0gdHJ1ZTtcblx0XHRcdFx0XHRcdCR0aGlzLnBhcmVudF9jb250cm9sbGVyLmF1dG9TYXZlTWFudWFsUHVuY2goKTtcblx0XHRcdFx0XHRcdGlmICggcmVzdWx0X2RhdGEubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0XHRcdFx0d2lkZ2V0c1snam9iX2lkJ10uc2V0VmFsdWUoIHJlc3VsdF9kYXRhWzBdLmlkICk7XG5cdFx0XHRcdFx0XHRcdHNldEpvYkl0ZW1WYWx1ZVdoZW5Kb2JDaGFuZ2VkKCByZXN1bHRfZGF0YVswXSApO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0d2lkZ2V0c1snam9iX2lkJ10uc2V0VmFsdWUoICcnICk7XG5cdFx0XHRcdFx0XHRcdHNldEpvYkl0ZW1WYWx1ZVdoZW5Kb2JDaGFuZ2VkKCBmYWxzZSApO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9ICk7XG5cdFx0XHR9IGVsc2UgaWYgKCBrZXkgPT09ICdqb2JfaXRlbV9xdWlja19zZWFyY2gnICkge1xuXHRcdFx0XHRhcmdzLmZpbHRlcl9kYXRhID0geyBtYW51YWxfaWQ6IHZhbHVlLCBqb2JfaWQ6IHdpZGdldHNbJ2pvYl9pZCddLmdldFZhbHVlKCksIHN0YXR1c19pZDogJzEwJyB9O1xuXHRcdFx0XHRqb2JfaXRlbV9hcGkuZ2V0Sm9iSXRlbSggYXJncywge1xuXHRcdFx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHRcdFx0dmFyIHJlc3VsdF9kYXRhID0gcmVzdWx0LmdldFJlc3VsdCgpO1xuXHRcdFx0XHRcdFx0d2lkZ2V0cy5pc19jaGFuZ2VkID0gdHJ1ZTtcblx0XHRcdFx0XHRcdCR0aGlzLnBhcmVudF9jb250cm9sbGVyLmF1dG9TYXZlTWFudWFsUHVuY2goKTtcblx0XHRcdFx0XHRcdGlmICggcmVzdWx0X2RhdGEubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0XHRcdFx0d2lkZ2V0c1snam9iX2l0ZW1faWQnXS5zZXRWYWx1ZSggcmVzdWx0X2RhdGFbMF0uaWQgKTtcblxuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0d2lkZ2V0c1snam9iX2l0ZW1faWQnXS5zZXRWYWx1ZSggJycgKTtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIHNldEpvYkl0ZW1WYWx1ZVdoZW5Kb2JDaGFuZ2VkKCBqb2IgKSB7XG5cdFx0XHR2YXIgam9iX2l0ZW1fd2lkZ2V0ID0gd2lkZ2V0c1snam9iX2l0ZW1faWQnXTtcblx0XHRcdGlmICggIWpvYl9pdGVtX3dpZGdldCApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0dmFyIGN1cnJlbnRfam9iX2l0ZW1faWQgPSBqb2JfaXRlbV93aWRnZXQuZ2V0VmFsdWUoKTtcblx0XHRcdGpvYl9pdGVtX3dpZGdldC5zZXRTb3VyY2VEYXRhKCBudWxsICk7XG5cdFx0XHR2YXIgYXJncyA9IHt9O1xuXHRcdFx0YXJncy5maWx0ZXJfZGF0YSA9IHsgc3RhdHVzX2lkOiAxMCwgam9iX2lkOiB3aWRnZXRzWydqb2JfaWQnXS5nZXRWYWx1ZSgpIH07XG5cdFx0XHRqb2JfaXRlbV93aWRnZXQuc2V0RGVmYXVsdEFyZ3MoIGFyZ3MgKTtcblx0XHRcdGlmICggY3VycmVudF9qb2JfaXRlbV9pZCApIHtcblx0XHRcdFx0dmFyIG5ld19hcmcgPSBHbG9iYWwuY2xvbmUoIGFyZ3MgKTtcblx0XHRcdFx0bmV3X2FyZy5maWx0ZXJfZGF0YS5pZCA9IGN1cnJlbnRfam9iX2l0ZW1faWQ7XG5cdFx0XHRcdG5ld19hcmcuZmlsdGVyX2NvbHVtbnMgPSBqb2JfaXRlbV93aWRnZXQuZ2V0Q29sdW1uRmlsdGVyKCk7XG5cdFx0XHRcdGpvYl9pdGVtX2FwaS5nZXRKb2JJdGVtKCBuZXdfYXJnLCB7XG5cdFx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCB0YXNrX3Jlc3VsdCApIHtcblx0XHRcdFx0XHRcdHZhciBkYXRhID0gdGFza19yZXN1bHQuZ2V0UmVzdWx0KCk7XG5cdFx0XHRcdFx0XHRpZiAoIGRhdGEubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0XHRcdFx0am9iX2l0ZW1fd2lkZ2V0LnNldFZhbHVlKCBjdXJyZW50X2pvYl9pdGVtX2lkICk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRzZXREZWZhdWx0RGF0YSgpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRzZXREZWZhdWx0RGF0YSgpO1xuXHRcdFx0fVxuXG5cdFx0XHRmdW5jdGlvbiBzZXREZWZhdWx0RGF0YSgpIHtcblx0XHRcdFx0aWYgKCB3aWRnZXRzWydqb2JfaWQnXS5nZXRWYWx1ZSgpICkge1xuXHRcdFx0XHRcdGpvYl9pdGVtX3dpZGdldC5zZXRWYWx1ZSggam9iLmRlZmF1bHRfaXRlbV9pZCApO1xuXHRcdFx0XHRcdGlmICggam9iLmRlZmF1bHRfaXRlbV9pZCA9PT0gZmFsc2UgfHwgam9iLmRlZmF1bHRfaXRlbV9pZCA9PT0gMCApIHtcblx0XHRcdFx0XHRcdGpvYl9pdGVtX2NvZGVyLnNldFZhbHVlKCAnJyApO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGpvYl9pdGVtX3dpZGdldC5zZXRWYWx1ZSggJycgKTtcblx0XHRcdFx0XHRqb2JfaXRlbV9jb2Rlci5zZXRWYWx1ZSggJycgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIHNldERlcGFydG1lbnRWYWx1ZVdoZW5CcmFuY2hDaGFuZ2VkKCkge1xuXHRcdFx0dmFyIGRlcGFydG1lbnRfd2lkZ2V0ID0gd2lkZ2V0c1snZGVwYXJ0bWVudF9pZCddO1xuXHRcdFx0aWYgKCAhZGVwYXJ0bWVudF93aWRnZXQgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0ZGVwYXJ0bWVudF93aWRnZXQuc2V0U291cmNlRGF0YSggbnVsbCApO1xuXHRcdFx0dmFyIGFyZ3MgPSB7fTtcblx0XHRcdGFyZ3MuZmlsdGVyX2RhdGEgPSB7XG5cdFx0XHRcdHVzZXJfaWQ6ICR0aGlzLnBhcmVudF9jb250cm9sbGVyLmdldFNlbGVjdEVtcGxveWVlKCB0cnVlICkuaWQsXG5cdFx0XHRcdGJyYW5jaF9pZDogd2lkZ2V0c1snYnJhbmNoX2lkJ10uZ2V0VmFsdWUoKVxuXHRcdFx0fTtcblx0XHRcdHZhciBjdXJyZW50X2RlcGFydG1lbnRfaWQgPSBkZXBhcnRtZW50X3dpZGdldC5nZXRWYWx1ZSgpO1xuXHRcdFx0ZGVwYXJ0bWVudF93aWRnZXQuc2V0RGVmYXVsdEFyZ3MoIGFyZ3MgKTtcblxuXHRcdFx0aWYgKCBjdXJyZW50X2RlcGFydG1lbnRfaWQgKSB7XG5cdFx0XHRcdHZhciBuZXdfYXJnID0gR2xvYmFsLmNsb25lKCBhcmdzICk7XG5cblx0XHRcdFx0bmV3X2FyZy5maWx0ZXJfY29sdW1ucyA9IGRlcGFydG1lbnRfd2lkZ2V0LmdldENvbHVtbkZpbHRlcigpO1xuXHRcdFx0XHRkZXBhcnRtZW50X2FwaS5nZXREZXBhcnRtZW50KCBuZXdfYXJnLCB7XG5cdFx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCBkZXBhcnRtZW50X3Jlc3VsdCApIHtcblxuXHRcdFx0XHRcdFx0dmFyIGRhdGEgPSBkZXBhcnRtZW50X3Jlc3VsdC5nZXRSZXN1bHQoKTtcblxuXHRcdFx0XHRcdFx0aWYgKCBkYXRhLmxlbmd0aCA+IDAgJiYgZGF0YS5zb21lKCBkZXBhcnRtZW50ID0+IGRlcGFydG1lbnQuaWQgPT09IGN1cnJlbnRfZGVwYXJ0bWVudF9pZCApICkge1xuXHRcdFx0XHRcdFx0XHRkZXBhcnRtZW50X3dpZGdldC5zZXRWYWx1ZSggY3VycmVudF9kZXBhcnRtZW50X2lkICk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRzZXREZWZhdWx0RGF0YSgpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRzZXREZWZhdWx0RGF0YSgpO1xuXHRcdFx0fVxuXG5cdFx0XHRmdW5jdGlvbiBzZXREZWZhdWx0RGF0YSgpIHtcblx0XHRcdFx0ZGVwYXJ0bWVudF93aWRnZXQuc2V0VmFsdWUoICcnICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gc2V0UHVuY2hUYWdWYWx1ZXNXaGVuQ3JpdGVyaWFDaGFuZ2VkKCkge1xuXHRcdFx0aWYgKCAoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpIDw9IDE1ICkgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0dmFyIHB1bmNoX3RhZ193aWRnZXQgPSB3aWRnZXRzWydwdW5jaF90YWdfaWQnXTtcblx0XHRcdGlmICggIXB1bmNoX3RhZ193aWRnZXQgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHRcdHZhciBjdXJyZW50X3B1bmNoX3RhZ19pZHMgPSBwdW5jaF90YWdfd2lkZ2V0LmdldFZhbHVlKCk7XG5cdFx0XHRwdW5jaF90YWdfd2lkZ2V0LnNldFNvdXJjZURhdGEoIG51bGwgKTtcblx0XHRcdHZhciBhcmdzID0ge307XG5cdFx0XHRhcmdzLmZpbHRlcl9kYXRhID0ge1xuXHRcdFx0XHRzdGF0dXNfaWQ6IDEwLFxuXHRcdFx0XHR1c2VyX2lkOiAkdGhpcy5wYXJlbnRfY29udHJvbGxlci5nZXRTZWxlY3RFbXBsb3llZSggdHJ1ZSApLmlkLFxuXHRcdFx0XHRicmFuY2hfaWQ6IHdpZGdldHNbJ2JyYW5jaF9pZCddID8gd2lkZ2V0c1snYnJhbmNoX2lkJ10uZ2V0VmFsdWUoKSA6IFRUVVVJRC56ZXJvX2lkLFxuXHRcdFx0XHRkZXBhcnRtZW50X2lkOiB3aWRnZXRzWydkZXBhcnRtZW50X2lkJ10gPyB3aWRnZXRzWydkZXBhcnRtZW50X2lkJ10uZ2V0VmFsdWUoKSA6IFRUVVVJRC56ZXJvX2lkLFxuXHRcdFx0XHRqb2JfaWQ6IHdpZGdldHNbJ2pvYl9pZCddID8gd2lkZ2V0c1snam9iX2lkJ10uZ2V0VmFsdWUoKSA6IFRUVVVJRC56ZXJvX2lkLFxuXHRcdFx0XHRqb2JfaXRlbV9pZDogd2lkZ2V0c1snam9iX2l0ZW1faWQnXSA/IHdpZGdldHNbJ2pvYl9pdGVtX2lkJ10uZ2V0VmFsdWUoKSA6IFRUVVVJRC56ZXJvX2lkXG5cdFx0XHR9O1xuXHRcdFx0cHVuY2hfdGFnX3dpZGdldC5zZXREZWZhdWx0QXJncyggYXJncyApO1xuXG5cdFx0XHRpZiAoIGN1cnJlbnRfcHVuY2hfdGFnX2lkcyAmJiBjdXJyZW50X3B1bmNoX3RhZ19pZHMubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0dmFyIG5ld19hcmcgPSBHbG9iYWwuY2xvbmUoIGFyZ3MgKTtcblxuXHRcdFx0XHRuZXdfYXJnLm1hbnVhbF9pZCA9IGN1cnJlbnRfcHVuY2hfdGFnX2lkcztcblx0XHRcdFx0cHVuY2hfdGFnX2FwaS5nZXRQdW5jaFRhZyggbmV3X2FyZywge1xuXHRcdFx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcHVuY2hfdGFnX3Jlc3VsdCApIHtcblx0XHRcdFx0XHRcdHZhciBkYXRhID0gcHVuY2hfdGFnX3Jlc3VsdC5nZXRSZXN1bHQoKTtcblxuXHRcdFx0XHRcdFx0aWYgKCBkYXRhLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdFx0XHRcdGlmICggY3VycmVudF9wdW5jaF90YWdfaWRzICE9PSBUVFVVSUQuemVyb19pZCAmJiBjdXJyZW50X3B1bmNoX3RhZ19pZHMubGVuZ3RoID4gMCAmJiBzaG91bGRVcGRhdGVQdW5jaFRhZ3MoIGN1cnJlbnRfcHVuY2hfdGFnX2lkcywgZGF0YSApICkge1xuXHRcdFx0XHRcdFx0XHRcdC8vQ29tcGFyZSBjdXJyZW50IHNlbGVjdGVkIHB1bmNoIHRhZ3MgYW5kIHRoZSBsaXN0IG9mIHB1bmNoIHRhZ3MgZnJvbSB0aGUgQVBJIGFuZCByZW1vdmUgaW52YWxpZCBwdW5jaCB0YWdzLlxuXHRcdFx0XHRcdFx0XHRcdHZhciBpbnRlcnNlY3RlZF92YWx1ZXMgPSBjdXJyZW50X3B1bmNoX3RhZ19pZHMuZmlsdGVyKCBwdW5jaF90YWdfaWQgPT4gZGF0YS5zb21lKCBwdW5jaF90YWcgPT4gcHVuY2hfdGFnX2lkID09PSBwdW5jaF90YWcuaWQgKSApO1xuXHRcdFx0XHRcdFx0XHRcdHB1bmNoX3RhZ193aWRnZXQuc2V0VmFsdWUoIGludGVyc2VjdGVkX3ZhbHVlcyApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRzZXREZWZhdWx0RGF0YSgpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRzZXREZWZhdWx0RGF0YSgpO1xuXHRcdFx0fVxuXG5cdFx0XHRmdW5jdGlvbiBzZXREZWZhdWx0RGF0YSgpIHtcblx0XHRcdFx0cHVuY2hfdGFnX3dpZGdldC5zZXRWYWx1ZSggJycgKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRmdW5jdGlvbiBzaG91bGRVcGRhdGVQdW5jaFRhZ3MoIGN1cnJlbnRfcHVuY2hfdGFnX2lkcywgZGF0YSApIHtcblx0XHRcdC8vSWYgdGhlIGRhdGEgcmV0dXJuZWQgZnJvbSB0aGUgQVBJIGRvZXMgbm90IGNvbnRhaW4gZXZlcnkgY3VycmVudGx5IHNlbGVjdGVkIHB1bmNoIHRhZyB0aGVuIHdlIG5lZWQgdG8gcmVtb3ZlIGludmFsaWQgdGFncy5cblx0XHRcdGlmICggY3VycmVudF9wdW5jaF90YWdfaWRzLmV2ZXJ5KCBwdW5jaF90YWdfaWQgPT4gZGF0YS5zb21lKCBwdW5jaF90YWcgPT4gcHVuY2hfdGFnLmlkID09PSBwdW5jaF90YWdfaWQgKSApID09PSBmYWxzZSApIHtcblx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly9JbiB0aGUgc2NlbmFyaW8gd2hlcmUgdGhlIHVzZXIgZG9lcyBub3QgaGF2ZSBwZXJtaXNzaW9uIHRvIGVkaXQgcHVuY2ggYnJhbmNoLCBkZXBhcnRtZW50LCBqb2IsIGpvYiBpdGVtIGFuZCBwdW5jaCB0YWcuIChBbGwgb2YgdGhlbSlcblx0XHQvL1RoZW4gdGhlIG1pbnVzIGljb24gc2hvdWxkIG5vdCBiZSBjZW50ZXJlZCBhcyB0aGUgPHRkPiBpcyB0b28gbGFyZ2UgYW5kIGl0IGxvb2tzIG91dCBvZiBwbGFjZS5cblx0XHRpZiAoIHRoaXMucGFyZW50X2NvbnRyb2xsZXIuZ2V0UHVuY2hNb2RlKCkgPT09ICdtYW51YWwnICkge1xuXHRcdFx0aWYgKCB0aGlzLnBhcmVudF9jb250cm9sbGVyLnRpbWVzaGVldF9jb2x1bW5zLmxlbmd0aCA9PT0gOSApIHsgLy8gUGx1cyBhbmQgTWludXMgaWNvbiArIDcgZGF5cyBvZiB0aGUgd2Vlay5cblx0XHRcdFx0dmFyIGNvbnRyb2xfaWNvbnMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCAnLmNvbnRyb2wtaWNvbicgKTtcblxuXHRcdFx0XHRmb3IgKCB2YXIgY29udHJvbF9pY29uIG9mIGNvbnRyb2xfaWNvbnMgKSB7XG5cdFx0XHRcdFx0Y29udHJvbF9pY29uLnN0eWxlLnRleHRBbGlnbiA9ICdsZWZ0Jztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGF1dG9TYXZlTWFudWFsUHVuY2goKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHRpZiAoIHRoaXMuaXNfc2F2aW5nX21hbnVhbF9ncmlkICkge1xuXHRcdFx0dGhpcy5zYXZlX21hbnVhbF9ncmlkX2FmdGVyX3NhdmUgPSB0cnVlO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLndhaXRfYXV0b19zYXZlICYmIGNsZWFyVGltZW91dCggdGhpcy53YWl0X2F1dG9fc2F2ZSApO1xuXHRcdHRoaXMud2FpdF9hdXRvX3NhdmUgPSBzZXRUaW1lb3V0KCBmdW5jdGlvbigpIHtcblx0XHRcdGlmICggJHRoaXMuZ2V0UHVuY2hNb2RlKCkgPT09ICdtYW51YWwnICkge1xuXHRcdFx0XHRQcm9ncmVzc0Jhci5zaG93T3ZlcmxheSgpO1xuXHRcdFx0XHQkdGhpcy5vblNhdmVDbGljaygpO1xuXHRcdFx0fVxuXHRcdH0sIDIwMDAgKTtcblx0fVxuXG5cdGluc2lkZUVkaXRvckdldFZhbHVlKCBpc1NhdmUgKSB7XG5cdFx0dmFyIGxlbiA9IHRoaXMucm93c193aWRnZXRzX2FycmF5Lmxlbmd0aDtcblx0XHR2YXIgcmVzdWx0ID0gW107XG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHR2YXIgcm93ID0gdGhpcy5yb3dzX3dpZGdldHNfYXJyYXlbaV07XG5cdFx0XHRmb3IgKCB2YXIgaiA9IDA7IGogPCA3OyBqKysgKSB7XG5cdFx0XHRcdHZhciBjdXJyZW50X2RhdGUgPSBuZXcgRGF0ZSggbmV3IERhdGUoIHRoaXMucGFyZW50X2NvbnRyb2xsZXIuc3RhcnRfZGF0ZS5nZXRUaW1lKCkgKS5zZXREYXRlKCB0aGlzLnBhcmVudF9jb250cm9sbGVyLnN0YXJ0X2RhdGUuZ2V0RGF0ZSgpICsgaiApICk7XG5cdFx0XHRcdHZhciBmaWVsZCA9IGN1cnJlbnRfZGF0ZS5mb3JtYXQoKTtcblx0XHRcdFx0dmFyIGNvbW1vbl9yZWNvcmQgPSB7fTtcblx0XHRcdFx0aWYgKCAhcm93W2ZpZWxkXSApIHtcblx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRjb21tb25fcmVjb3JkLnRvdGFsX3RpbWUgPSByb3dbZmllbGRdLmdldFZhbHVlKCk7XG5cdFx0XHRcdGlmICggcm93W2ZpZWxkXS5pc19jaGFuZ2VkIHx8ICggcm93LmlzX2NoYW5nZWQgJiYgcm93LmN1cnJlbnRfZWRpdF9pdGVtW2ZpZWxkXSApICkge1xuXHRcdFx0XHRcdHJvdy5icmFuY2hfaWQgJiYgKCBjb21tb25fcmVjb3JkLmJyYW5jaF9pZCA9IHJvdy5icmFuY2hfaWQuZ2V0VmFsdWUoKSApO1xuXHRcdFx0XHRcdHJvdy5kZXBhcnRtZW50X2lkICYmICggY29tbW9uX3JlY29yZC5kZXBhcnRtZW50X2lkID0gcm93LmRlcGFydG1lbnRfaWQuZ2V0VmFsdWUoKSApO1xuXHRcdFx0XHRcdHJvdy5qb2JfaWQgJiYgKCBjb21tb25fcmVjb3JkLmpvYl9pZCA9IHJvdy5qb2JfaWQuZ2V0VmFsdWUoKSApO1xuXHRcdFx0XHRcdHJvdy5qb2JfaXRlbV9pZCAmJiAoIGNvbW1vbl9yZWNvcmQuam9iX2l0ZW1faWQgPSByb3cuam9iX2l0ZW1faWQuZ2V0VmFsdWUoKSApO1xuXHRcdFx0XHRcdHJvdy5wdW5jaF90YWdfaWQgJiYgKCBjb21tb25fcmVjb3JkLnB1bmNoX3RhZ19pZCA9IHJvdy5wdW5jaF90YWdfaWQuZ2V0VmFsdWUoKSApO1xuXHRcdFx0XHRcdGNvbW1vbl9yZWNvcmQuZGF0ZV9zdGFtcCA9IGZpZWxkO1xuXHRcdFx0XHRcdGNvbW1vbl9yZWNvcmQudXNlcl9pZCA9IHRoaXMucGFyZW50X2NvbnRyb2xsZXIuZ2V0U2VsZWN0RW1wbG95ZWUoKTtcblx0XHRcdFx0XHRjb21tb25fcmVjb3JkLm9iamVjdF90eXBlX2lkID0gMTA7XG5cdFx0XHRcdFx0Y29tbW9uX3JlY29yZC5vdmVycmlkZSA9IHRydWU7XG5cdFx0XHRcdFx0Y29tbW9uX3JlY29yZC5yb3cgPSByb3c7XG5cdFx0XHRcdFx0cm93LmN1cnJlbnRfZWRpdF9pdGVtW2ZpZWxkXSAmJiAoIGNvbW1vbl9yZWNvcmQuaWQgPSByb3cuY3VycmVudF9lZGl0X2l0ZW1bZmllbGRdLmlkICk7XG5cdFx0XHRcdFx0cmVzdWx0LnB1c2goIGNvbW1vbl9yZWNvcmQgKTtcblx0XHRcdFx0XHRpZiAoIGlzU2F2ZSApIHtcblx0XHRcdFx0XHRcdHJvd1tmaWVsZF0uaXNfY2hhbmdlZCA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0cm93W2ZpZWxkXS5hZGRDbGFzcyggJ2lzLXNhdmluZy1tYW51YWwtZ3JpZCcgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdGlmICggaXNTYXZlICkge1xuXHRcdFx0XHRyb3cuaXNfY2hhbmdlZCA9IGZhbHNlO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cblxuXHRpbnNpZGVFZGl0b3JSZW1vdmVSb3coIHJvdyApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciBpbmRleCA9IHJvd1swXS5yb3dJbmRleCAtIDM7XG5cdFx0dmFyIHdpZGdldF9yb3cgPSB0aGlzLnJvd3Nfd2lkZ2V0c19hcnJheVtpbmRleF07XG5cdFx0dmFyIGhhc192YWx1ZSA9IGZhbHNlO1xuXHRcdGZvciAoIHZhciBqID0gMDsgaiA8IDc7IGorKyApIHtcblx0XHRcdHZhciBjdXJyZW50X2RhdGUgPSBuZXcgRGF0ZSggbmV3IERhdGUoIHRoaXMucGFyZW50X2NvbnRyb2xsZXIuc3RhcnRfZGF0ZS5nZXRUaW1lKCkgKS5zZXREYXRlKCB0aGlzLnBhcmVudF9jb250cm9sbGVyLnN0YXJ0X2RhdGUuZ2V0RGF0ZSgpICsgaiApICk7XG5cdFx0XHR2YXIgZmllbGQgPSBjdXJyZW50X2RhdGUuZm9ybWF0KCk7XG5cdFx0XHRpZiAoIHdpZGdldF9yb3dbZmllbGRdLmdldFZhbHVlKCkgPiAwIHx8IHdpZGdldF9yb3cuY3VycmVudF9lZGl0X2l0ZW1bZmllbGRdICkge1xuXHRcdFx0XHRoYXNfdmFsdWUgPSB0cnVlO1xuXHRcdFx0XHRUQWxlcnRNYW5hZ2VyLnNob3dDb25maXJtQWxlcnQoICQuaTE4bi5fKCAnWW91IGFyZSBhYm91dCB0byBkZWxldGUgdGhlIGVudGlyZSB3ZWVrIHdvcnRoIG9mIHRpbWUgZm9yIHRoaXMgcm93LiBBcmUgeW91IHN1cmUgeW91IHdpc2ggdG8gY29udGludWU/JyApLCAnJywgZG9OZXh0ICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdH1cblx0XHQhaGFzX3ZhbHVlICYmIGRvTmV4dCggdHJ1ZSApO1xuXG5cdFx0ZnVuY3Rpb24gZG9OZXh0KCBmbGFnICkge1xuXHRcdFx0aWYgKCBmbGFnICkge1xuXHRcdFx0XHR2YXIgcmVtb3ZlX2lkcyA9IFtdO1xuXHRcdFx0XHRmb3IgKCB2YXIgaiA9IDA7IGogPCA3OyBqKysgKSB7XG5cdFx0XHRcdFx0dmFyIGN1cnJlbnRfZGF0ZSA9IG5ldyBEYXRlKCBuZXcgRGF0ZSggJHRoaXMucGFyZW50X2NvbnRyb2xsZXIuc3RhcnRfZGF0ZS5nZXRUaW1lKCkgKS5zZXREYXRlKCAkdGhpcy5wYXJlbnRfY29udHJvbGxlci5zdGFydF9kYXRlLmdldERhdGUoKSArIGogKSApO1xuXHRcdFx0XHRcdHZhciBmaWVsZCA9IGN1cnJlbnRfZGF0ZS5mb3JtYXQoKTtcblx0XHRcdFx0XHR3aWRnZXRfcm93LmN1cnJlbnRfZWRpdF9pdGVtW2ZpZWxkXSAmJiAoIHJlbW92ZV9pZHMucHVzaCggd2lkZ2V0X3Jvdy5jdXJyZW50X2VkaXRfaXRlbVtmaWVsZF0uaWQgKSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICggcmVtb3ZlX2lkcy5sZW5ndGggPiAwICkge1xuXHRcdFx0XHRcdFByb2dyZXNzQmFyLm5vUHJvZ3Jlc3NGb3JOZXh0Q2FsbCgpO1xuXHRcdFx0XHRcdFByb2dyZXNzQmFyLnNob3dOYW5vYmFyKCk7XG5cdFx0XHRcdFx0JHRoaXMuaXNfc2F2aW5nX21hbnVhbF9ncmlkID0gdHJ1ZTtcblx0XHRcdFx0XHQkdGhpcy5wYXJlbnRfY29udHJvbGxlci5zZXREZWZhdWx0TWVudSgpO1xuXHRcdFx0XHRcdCR0aGlzLmFwaS5kZWxldGVVc2VyRGF0ZVRvdGFsKCByZW1vdmVfaWRzLCB7XG5cdFx0XHRcdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdCR0aGlzLnBhcmVudF9jb250cm9sbGVyLnJlTG9hZFN1YkdyaWRzU291cmNlKCB0cnVlICk7XG5cdFx0XHRcdFx0XHRcdFByb2dyZXNzQmFyLnJlbW92ZU5hbm9iYXIoKTtcblx0XHRcdFx0XHRcdFx0JHRoaXMucGFyZW50X2NvbnRyb2xsZXIuc2V0RGVmYXVsdE1lbnUoKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0cm93LnJlbW92ZSgpO1xuXHRcdFx0XHQkdGhpcy5yb3dzX3dpZGdldHNfYXJyYXkuc3BsaWNlKCBpbmRleCwgMSApO1xuXHRcdFx0XHRpZiAoICR0aGlzLnJvd3Nfd2lkZ2V0c19hcnJheS5sZW5ndGggPT09IDAgKSB7XG5cdFx0XHRcdFx0JHRoaXMuYWRkUm93KCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRidWlsZE1hbnVhbFRpbWVTaGVldEdyaWQoKSB7XG5cdFx0dmFyIGFyZ3MgPSB7XG5cdFx0XHRicmFuY2g6ICQuaTE4bi5fKCAnQnJhbmNoJyApLFxuXHRcdFx0ZGVwYXJ0bWVudDogJC5pMThuLl8oICdEZXBhcnRtZW50JyApLFxuXHRcdFx0am9iOiAkLmkxOG4uXyggJ0pvYicgKSxcblx0XHRcdHRhc2s6ICQuaTE4bi5fKCAnVGFzaycgKSxcblx0XHRcdHB1bmNoX3RhZzogJC5pMThuLl8oICdUYWdzJyApXG5cdFx0fTtcblxuXHRcdHRoaXMuZWRpdG9yID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5JTlNJREVfRURJVE9SICk7XG5cdFx0dGhpcy5lZGl0b3IuSW5zaWRlRWRpdG9yKCB7XG5cdFx0XHR0aXRsZTogJycsXG5cdFx0XHRhZGRSb3c6IHRoaXMuaW5zaWRlRWRpdG9yQWRkUm93LFxuXHRcdFx0Z2V0VmFsdWU6IHRoaXMuaW5zaWRlRWRpdG9yR2V0VmFsdWUsXG5cdFx0XHRzZXRWYWx1ZTogdGhpcy5pbnNpZGVFZGl0b3JTZXRWYWx1ZSxcblx0XHRcdHJlbW92ZVJvdzogdGhpcy5pbnNpZGVFZGl0b3JSZW1vdmVSb3csXG5cdFx0XHRwYXJlbnRfY29udHJvbGxlcjogdGhpcyxcblx0XHRcdHJlbmRlcjogZ2V0UmVuZGVyKCksXG5cdFx0XHRyZW5kZXJfYXJnczogYXJncyxcblx0XHRcdGFwaTogdGhpcy5hcGlfdXNlcl9kYXRlX3RvdGFsLFxuXHRcdFx0cmVuZGVyX2lubGluZV9odG1sOiB0cnVlLFxuXHRcdFx0cm93X3JlbmRlcjogZ2V0Um93UmVuZGVyKClcblx0XHR9ICk7XG5cblx0XHRmdW5jdGlvbiBnZXRSZW5kZXIoKSB7XG5cdFx0XHRyZXR1cm4gYDx0YWJsZSBjbGFzcz1cImluc2lkZS1lZGl0b3ItcmVuZGVyIGdyaWQtaW5zaWRlLWVkaXRvci1yZW5kZXJcIj5cblx0XHRcdFx0XHRcdDx0ciBjbGFzcz1cIm1hbnVhbC10aW1lc2hlZXQtc2l6ZS10clwiPlxuXHRcdFx0XHRcdFx0XHQ8dGQgc3R5bGU9XCJ3aWR0aDogMjVweFwiPjwvdGQ+XG5cdFx0XHRcdFx0XHRcdDx0ZCBzdHlsZT1cIndpZHRoOiAyNXB4XCI+PC90ZD5cblx0XHRcdFx0XHRcdFx0PHRkIGNsYXNzPVwiYnJhbmNoLWhlYWRlclwiIHN0eWxlPVwid2lkdGg6IDEyMHB4XCI+PC90ZD5cblx0XHRcdFx0XHRcdFx0PHRkIGNsYXNzPVwiZGVwYXJ0bWVudC1oZWFkZXJcIiBzdHlsZT1cIndpZHRoOiAxMjBweFwiPjwvdGQ+XG5cdFx0XHRcdFx0XHRcdDx0ZCBjbGFzcz1cImpvYi1oZWFkZXJcIiBzdHlsZT1cIndpZHRoOiAxMjBweFwiPjwvdGQ+XG5cdFx0XHRcdFx0XHRcdDx0ZCBjbGFzcz1cImpvYi1pdGVtLWhlYWRlclwiIHN0eWxlPVwid2lkdGg6IDEyMHB4XCI+PC90ZD5cblx0XHRcdFx0XHRcdFx0PHRkIGNsYXNzPVwicHVuY2gtdGFnLWhlYWRlclwiIHN0eWxlPVwid2lkdGg6IDEyMHB4XCI+PC90ZD5cblx0XHRcdFx0XHRcdFx0PHRkIHN0eWxlPVwid2lkdGg6IDUwcHhcIj48L3RkPlxuXHRcdFx0XHRcdFx0XHQ8dGQgc3R5bGU9XCJ3aWR0aDogNTBweFwiPjwvdGQ+XG5cdFx0XHRcdFx0XHRcdDx0ZCBzdHlsZT1cIndpZHRoOiA1MHB4XCI+PC90ZD5cblx0XHRcdFx0XHRcdFx0PHRkIHN0eWxlPVwid2lkdGg6IDUwcHhcIj48L3RkPlxuXHRcdFx0XHRcdFx0XHQ8dGQgc3R5bGU9XCJ3aWR0aDogNTBweFwiPjwvdGQ+XG5cdFx0XHRcdFx0XHRcdDx0ZCBzdHlsZT1cIndpZHRoOiA1MHB4XCI+PC90ZD5cblx0XHRcdFx0XHRcdFx0PHRkIHN0eWxlPVwid2lkdGg6IDUwcHhcIj48L3RkPlxuXHRcdFx0XHRcdFx0PC90cj5cblx0XHRcdFx0XHRcdDx0ciBjbGFzcz1cInRpdGxlXCI+XG5cdFx0XHRcdFx0XHRcdDx0ZD48L3RkPlxuXHRcdFx0XHRcdFx0XHQ8dGQ+PC90ZD5cblx0XHRcdFx0XHRcdFx0PHRkIGNsYXNzPVwiYnJhbmNoLWhlYWRlclwiPjwlPSBicmFuY2ggJT48L3RkPlxuXHRcdFx0XHRcdFx0XHQ8dGQgY2xhc3M9XCJkZXBhcnRtZW50LWhlYWRlclwiPjwlPSBkZXBhcnRtZW50ICU+PC90ZD5cblx0XHRcdFx0XHRcdFx0PHRkIGNsYXNzPVwiam9iLWhlYWRlclwiPjwlPSBqb2IgJT48L3RkPlxuXHRcdFx0XHRcdFx0XHQ8dGQgY2xhc3M9XCJqb2ItaXRlbS1oZWFkZXJcIj48JT0gdGFzayAlPjwvdGQ+XG5cdFx0XHRcdFx0XHRcdDx0ZCBjbGFzcz1cInB1bmNoLXRhZy1oZWFkZXJcIj48JT0gcHVuY2hfdGFnICU+PC90ZD5cblx0XHRcdFx0XHRcdFx0PHRkIGlkPVwiZGF5XzBfZGF0ZVwiPjwvdGQ+XG5cdFx0XHRcdFx0XHRcdDx0ZCBpZD1cImRheV8xX2RhdGVcIj48L3RkPlxuXHRcdFx0XHRcdFx0XHQ8dGQgaWQ9XCJkYXlfMl9kYXRlXCI+PC90ZD5cblx0XHRcdFx0XHRcdFx0PHRkIGlkPVwiZGF5XzNfZGF0ZVwiPjwvdGQ+XG5cdFx0XHRcdFx0XHRcdDx0ZCBpZD1cImRheV80X2RhdGVcIj48L3RkPlxuXHRcdFx0XHRcdFx0XHQ8dGQgaWQ9XCJkYXlfNV9kYXRlXCI+PC90ZD5cblx0XHRcdFx0XHRcdFx0PHRkIGlkPVwiZGF5XzZfZGF0ZVwiPjwvdGQ+XG5cdFx0XHRcdFx0XHQ8L3RyPlxuXHRcdFx0XHRcdDwvdGFibGU+YDtcblx0XHR9XG5cblx0XHRmdW5jdGlvbiBnZXRSb3dSZW5kZXIoKSB7XG5cdFx0XHRyZXR1cm4gYDx0ciBjbGFzcz1cImluc2lkZS1lZGl0b3Itcm93IGRhdGEtcm93XCI+XG5cdFx0XHRcdFx0XHQ8dGQgY2xhc3M9XCJjZWxsIGNvbnRyb2wtaWNvblwiPlxuXHRcdFx0XHRcdFx0XHQ8YnV0dG9uIGNsYXNzPVwicGx1cy1pY29uXCIgb25jbGljaz1cIlwiPjwvYnV0dG9uPlxuXHRcdFx0XHRcdFx0PC90ZD5cblx0XHRcdFx0XHRcdDx0ZCBjbGFzcz1cImNlbGwgY29udHJvbC1pY29uXCI+XG5cdFx0XHRcdFx0XHRcdDxidXR0b24gY2xhc3M9XCJtaW51cy1pY29uIFwiIG9uY2xpY2s9XCJcIj48L2J1dHRvbj5cblx0XHRcdFx0XHRcdDwvdGQ+XG5cdFx0XHRcdFx0XHQ8dGQgY2xhc3M9XCJicmFuY2ggXCI+PC90ZD5cblx0XHRcdFx0XHRcdDx0ZCBjbGFzcz1cImRlcGFydG1lbnQgXCI+PC90ZD5cblx0XHRcdFx0XHRcdDx0ZCBjbGFzcz1cImpvYiBcIj48L3RkPlxuXHRcdFx0XHRcdFx0PHRkIGNsYXNzPVwidGFzayBcIj48L3RkPlxuXHRcdFx0XHRcdFx0PHRkIGNsYXNzPVwicHVuY2hfdGFnIFwiPjwvdGQ+XG5cdFx0XHRcdFx0XHQ8dGQgY2xhc3M9XCJkYXktMCBcIj48L3RkPlxuXHRcdFx0XHRcdFx0PHRkIGNsYXNzPVwiZGF5LTEgXCI+PC90ZD5cblx0XHRcdFx0XHRcdDx0ZCBjbGFzcz1cImRheS0yIFwiPjwvdGQ+XG5cdFx0XHRcdFx0XHQ8dGQgY2xhc3M9XCJkYXktMyBcIj48L3RkPlxuXHRcdFx0XHRcdFx0PHRkIGNsYXNzPVwiZGF5LTQgXCI+PC90ZD5cblx0XHRcdFx0XHRcdDx0ZCBjbGFzcz1cImRheS01IFwiPjwvdGQ+XG5cdFx0XHRcdFx0XHQ8dGQgY2xhc3M9XCJkYXktNiBcIj48L3RkPlxuXHRcdFx0XHRcdDwvdHI+YDtcblx0XHR9XG5cblx0XHR2YXIgaW5zaWRlX2VkaXRvcl9kaXYgPSB0aGlzLiQoICcubWFudWFsLXRpbWVzaGVldC1pbnNpZGUtZWRpdG9yLWRpdicgKTtcblx0XHRpbnNpZGVfZWRpdG9yX2Rpdi5hcHBlbmQoIHRoaXMuZWRpdG9yICk7XG5cdH1cblxuXHRidWlsZENhbGVuZGFycygpIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdGlmICggdGhpcy5pc19hdXRvX3N3aXRjaCApIHtcblx0XHRcdHRoaXMuZ2V0TWFudWFsVGltZVNoZWV0RGF0YSggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggJHRoaXMubWFudWFsX3RpbWVzaGVldF9kYXRhLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdFx0JHRoaXMuYnVpbGRNYW51YWxUaW1lU2hlZXREYXRhKCk7XG5cdFx0XHRcdFx0dmFyIGlzX25vX21hbnVhbCA9IF8uaXNFbXB0eSggJHRoaXMudGltZV9zaGVldF9kYXRhX292ZXJyb2RlX3RydWVfbWFwICk7XG5cdFx0XHRcdFx0dmFyIGlzX25vX3B1bmNoID0gXy5pc0VtcHR5KCAkdGhpcy50aW1lX3NoZWV0X2RhdGFfb3ZlcnJvZGVfZmFsc2VfbWFwICk7XG5cdFx0XHRcdFx0aWYgKCBpc19ub19tYW51YWwgJiYgIWlzX25vX3B1bmNoICYmICR0aGlzLnRvZ2dsZV9idXR0b24uZ2V0VmFsdWUoKSAhPT0gJ21hbnVhbCcgKSB7XG5cdFx0XHRcdFx0XHQkdGhpcy50b2dnbGVfYnV0dG9uLnNldFZhbHVlKCAncHVuY2gnICk7XG5cdFx0XHRcdFx0XHQkdGhpcy5pc19hdXRvX3N3aXRjaCA9IGZhbHNlO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoICFpc19ub19tYW51YWwgJiYgaXNfbm9fcHVuY2ggKSB7XG5cdFx0XHRcdFx0XHQkdGhpcy50b2dnbGVfYnV0dG9uLnNldFZhbHVlKCAnbWFudWFsJyApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHQkdGhpcy5yZVNldFVSTCgpO1xuXHRcdFx0XHRcdGRvTmV4dCgpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdCR0aGlzLmdldFB1bmNoTW9kZSgpID09PSAncHVuY2gnICYmICggJHRoaXMuaXNfYXV0b19zd2l0Y2ggPSBmYWxzZSApO1xuXHRcdFx0XHRcdGRvTmV4dCgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGRvTmV4dCgpO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGRvTmV4dCgpIHtcblx0XHRcdCR0aGlzLnBheV9wZXJpb2RfZGF0YSA9ICR0aGlzLmZ1bGxfdGltZXNoZWV0X2RhdGEucGF5X3BlcmlvZF9kYXRhO1xuXHRcdFx0JHRoaXMucGF5X3BlcmlvZF9tYXAgPSAkdGhpcy5mdWxsX3RpbWVzaGVldF9kYXRhLnRpbWVzaGVldF9kYXRlcy5wYXlfcGVyaW9kX2RhdGVfbWFwO1xuXHRcdFx0JHRoaXMudGltZXNoZWV0X3ZlcmlmeV9kYXRhID0gJHRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YS50aW1lc2hlZXRfdmVyaWZ5X2RhdGE7XG5cdFx0XHQkdGhpcy5ncmlkX2RpdiA9ICQoICR0aGlzLmVsICkuZmluZCggJy50aW1lc2hlZXQtZ3JpZC1kaXYnICk7XG5cdFx0XHQvLyBQdW5jaCBncmlkXG5cdFx0XHQkdGhpcy5idWlsZFRpbWVTaGVldHNDb2x1bW5zKCk7XG5cdFx0XHQkdGhpcy5idWlsZFRpbWVTaGVldEdyaWQoKTtcblx0XHRcdGlmICggJHRoaXMuZ2V0UHVuY2hNb2RlKCkgPT09ICdtYW51YWwnICkge1xuXHRcdFx0XHQkdGhpcy4kKCAnLnRpbWVzaGVldC1wdW5jaC1ncmlkLXdyYXBwZXInICkuaGlkZSgpO1xuXHRcdFx0XHQkdGhpcy4kKCAnLm1hbnVhbC10aW1lc2hlZXQtaW5zaWRlLWVkaXRvci1kaXYnICkuc2hvdygpO1xuXHRcdFx0XHRpZiAoICEkdGhpcy5lZGl0b3IgKSB7XG5cdFx0XHRcdFx0JHRoaXMuYnVpbGRNYW51YWxUaW1lU2hlZXRzQ29sdW1ucygpO1xuXHRcdFx0XHRcdCR0aGlzLmJ1aWxkTWFudWFsVGltZVNoZWV0R3JpZCgpO1xuXHRcdFx0XHRcdCR0aGlzLmluaXRJbnNpZGVFZGl0b3JEYXRhKCk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JHRoaXMuYnVpbGRNYW51YWxUaW1lU2hlZXRzQ29sdW1ucygpO1xuXHRcdFx0XHRcdCR0aGlzLmluaXRJbnNpZGVFZGl0b3JEYXRhKCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCAhJHRoaXMuc2hvd19qb2JfdWkgfHwgR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPCAyMCApIHtcblx0XHRcdFx0XHQkdGhpcy4kKCAnLmpvYi1oZWFkZXInICkuaGlkZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICggISR0aGlzLnNob3dfam9iX2l0ZW1fdWkgfHwgR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPCAyMCApIHtcblx0XHRcdFx0XHQkdGhpcy4kKCAnLmpvYi1pdGVtLWhlYWRlcicgKS5oaWRlKCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCAhJHRoaXMuc2hvd19wdW5jaF90YWdfdWkgfHwgR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPCAyMCApIHtcblx0XHRcdFx0XHQkdGhpcy4kKCAnLnB1bmNoLXRhZy1oZWFkZXInICkuaGlkZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICggISR0aGlzLnNob3dfYnJhbmNoX3VpICkge1xuXHRcdFx0XHRcdCR0aGlzLiQoICcuYnJhbmNoLWhlYWRlcicgKS5oaWRlKCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCAhJHRoaXMuc2hvd19kZXBhcnRtZW50X3VpICkge1xuXHRcdFx0XHRcdCR0aGlzLiQoICcuZGVwYXJ0bWVudC1oZWFkZXInICkuaGlkZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkdGhpcy4kKCAnLnRpbWVzaGVldC1wdW5jaC1ncmlkLXdyYXBwZXInICkuc2hvdygpO1xuXHRcdFx0XHQkdGhpcy4kKCAnLm1hbnVhbC10aW1lc2hlZXQtaW5zaWRlLWVkaXRvci1kaXYnICkuaGlkZSgpO1xuXHRcdFx0fVxuXG5cdFx0XHQkdGhpcy5idWlsZEFjY3VtdWxhdGVkR3JpZCgpO1xuXG5cdFx0XHQkdGhpcy5idWlsZFN1YkdyaWQoICdicmFuY2hfZ3JpZCcsICdCcmFuY2gnICk7XG5cdFx0XHQkdGhpcy5idWlsZFN1YkdyaWQoICdkZXBhcnRtZW50X2dyaWQnLCAnRGVwYXJ0bWVudCcgKTtcblx0XHRcdCR0aGlzLmJ1aWxkU3ViR3JpZCggJ2pvYl9ncmlkJywgJ0pvYicgKTtcblx0XHRcdCR0aGlzLmJ1aWxkU3ViR3JpZCggJ2pvYl9pdGVtX2dyaWQnLCAnVGFzaycgKTtcblx0XHRcdCR0aGlzLmJ1aWxkU3ViR3JpZCggJ3B1bmNoX3RhZ19ncmlkJywgJ1RhZ3MnICk7XG5cdFx0XHQkdGhpcy5idWlsZFN1YkdyaWQoICdwcmVtaXVtX2dyaWQnLCAnUHJlbWl1bScgKTtcblx0XHRcdCR0aGlzLmJ1aWxkQWJzZW5jZUdyaWQoKTtcblx0XHRcdCR0aGlzLnNob3dHcmlkQm9yZGVycygpO1xuXHRcdFx0JHRoaXMuYnVpbGRBY2N1bXVsYXRlZFRvdGFsR3JpZCgpO1xuXHRcdFx0JHRoaXMuYnVpbGRQdW5jaE5vdGVHcmlkKCk7XG5cdFx0XHQkdGhpcy5idWlsZFZlcmlmaWNhdGlvbkdyaWQoKTtcblx0XHRcdC8vVGltZVNoZWV0IGdyaWRcblx0XHRcdCR0aGlzLmJ1aWxkVGltZVNoZWV0U291cmNlKCk7IC8vQ3JlYXRlIHB1bmNoIGRhdGFcblx0XHRcdCR0aGlzLmJ1aWxkVGltZVNoZWV0UmVxdWVzdHMoKTtcblx0XHRcdC8vQWNjdW11bGF0ZWQgVGltZSwgQnJhbmNoLCBEZXBhcnRtZW50LCBKb2IsIFRhc2ssIFByZVxuXHRcdFx0JHRoaXMuYnVpbGRTdWJHcmlkc1NvdXJjZSgpO1xuXHRcdFx0Ly9NYWtlIHN1cmUgZXhjZXB0aW9uIHJvd3MgZ29lcyBhZnRlciBMYW51Y2ggYW5kIGJyZWFrIGNyZWF0ZSBmcm9tIGJ1aWxkU3ViR3JpZHNTb3VyY2Vcblx0XHRcdCR0aGlzLmJ1aWxkVGltZVNoZWV0RXhjZXB0aW9ucygpO1xuXHRcdFx0Ly9BYnNlbmNlIEdyaWQgc291cmNlXG5cdFx0XHQkdGhpcy5idWlsZEFic2VuY2VTb3VyY2UoKTsgLy9DcmVhdGUgcHVuY2ggZGF0YVxuXHRcdFx0Ly9TaG93IHB1bmNoIG5vdGVzIGluIGEgZ3JpZFxuXHRcdFx0JHRoaXMuYnVpbGRQdW5jaE5vdGVHcmlkU291cmNlKCk7XG5cdFx0XHQvL2J1aWxkVmVyaWZpY2F0aW9uR3JpZFNvdXJjZVxuXHRcdFx0JHRoaXMuYnVpbGRWZXJpZmljYXRpb25HcmlkU291cmNlKCk7XG5cdFx0XHQkdGhpcy5zZXRHcmlkRXhwZW5kQnV0dG9uKCAnYWNjdW11bGF0ZWRfdGltZV9ncmlkJywgJC5pMThuLl8oICdBY2N1bXVsYXRlZCBUaW1lJyApICk7XG5cdFx0XHQkdGhpcy5zZXRHcmlkRXhwZW5kQnV0dG9uKCAnYnJhbmNoX2dyaWQnLCAkLmkxOG4uXyggJ0JyYW5jaCcgKSApO1xuXHRcdFx0JHRoaXMuc2V0R3JpZEV4cGVuZEJ1dHRvbiggJ2RlcGFydG1lbnRfZ3JpZCcsICQuaTE4bi5fKCAnRGVwYXJ0bWVudCcgKSApO1xuXHRcdFx0JHRoaXMuc2V0R3JpZEV4cGVuZEJ1dHRvbiggJ2pvYl9ncmlkJywgJC5pMThuLl8oICdKb2InICkgKTtcblx0XHRcdCR0aGlzLnNldEdyaWRFeHBlbmRCdXR0b24oICdqb2JfaXRlbV9ncmlkJywgJC5pMThuLl8oICdUYXNrJyApICk7XG5cdFx0XHQkdGhpcy5zZXRHcmlkRXhwZW5kQnV0dG9uKCAncHVuY2hfdGFnX2dyaWQnLCAkLmkxOG4uXyggJ1RhZ3MnICkgKTtcblx0XHRcdCR0aGlzLnNldEdyaWRFeHBlbmRCdXR0b24oICdwcmVtaXVtX2dyaWQnLCAkLmkxOG4uXyggJ1ByZW1pdW0nICkgKTtcblx0XHRcdCR0aGlzLnNldEdyaWRFeHBlbmRCdXR0b24oICdhYnNlbmNlX2dyaWQnLCAkLmkxOG4uXyggJ0Fic2VuY2UnICkgKTtcblx0XHRcdCR0aGlzLnNldEdyaWRFeHBlbmRCdXR0b24oICdwdW5jaF9ub3RlX2dyaWQnLCAkLmkxOG4uXyggJ1B1bmNoIE5vdGVzJyApICk7XG5cblx0XHRcdGlmICggJHRoaXMuZ2V0UHVuY2hNb2RlKCkgPT09ICdwdW5jaCcgKSB7XG5cdFx0XHRcdC8vdmFyIHNlbGVjdGlvbiA9ICR0aGlzLmdyaWQuZ2V0U2VsZWN0aW9uKCk7IC8vcHJvdmlkZXMgbWVtb3J5IG9mIHNlbGVjdGVkIGNlbGxzXG5cdFx0XHRcdCR0aGlzLmdyaWQuc2V0RGF0YSggJHRoaXMudGltZXNoZWV0X2RhdGFfc291cmNlLCB0cnVlICk7XG5cdFx0XHRcdC8vJHRoaXMuZ3JpZC5zZXRUaW1lc2hlZXRTZWxlY3Rpb24oIHNlbGVjdGlvbiApOyAvL3Jlc2V0cyBzZWxlY3Rpb24gYWZ0ZXIgcmVmcmVzaGluZyBncmlkIGRhdGEgLS0gY3VycmVudGx5IGJyb2tlbiwgc2VlIHNldFRpbWVzaGVldFNlbGVjdGlvbigpIGZvciBkZXRhaWxzLlxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHR5cGVvZiAkdGhpcy5hY2N1bXVsYXRlZF90aW1lX2dyaWQuc2V0RGF0YSA9PSAnZnVuY3Rpb24nICkge1xuXHRcdFx0XHQkdGhpcy5hY2N1bXVsYXRlZF90aW1lX2dyaWQuc2V0RGF0YSggJHRoaXMuYWNjdW11bGF0ZWRfdGltZV9zb3VyY2UsIGZhbHNlICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggdHlwZW9mICR0aGlzLmJyYW5jaF9ncmlkLnNldERhdGEgPT0gJ2Z1bmN0aW9uJyApIHtcblx0XHRcdFx0JHRoaXMuYnJhbmNoX2dyaWQuc2V0RGF0YSggJHRoaXMuYnJhbmNoX3NvdXJjZSwgZmFsc2UgKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCB0eXBlb2YgJHRoaXMuZGVwYXJ0bWVudF9ncmlkLnNldERhdGEgPT0gJ2Z1bmN0aW9uJyApIHtcblx0XHRcdFx0JHRoaXMuZGVwYXJ0bWVudF9ncmlkLnNldERhdGEoICR0aGlzLmRlcGFydG1lbnRfc291cmNlLCBmYWxzZSApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHR5cGVvZiAkdGhpcy5qb2JfZ3JpZC5zZXREYXRhID09ICdmdW5jdGlvbicgKSB7XG5cdFx0XHRcdCR0aGlzLmpvYl9ncmlkLnNldERhdGEoICR0aGlzLmpvYl9zb3VyY2UsIGZhbHNlICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggdHlwZW9mICR0aGlzLmpvYl9pdGVtX2dyaWQuc2V0RGF0YSA9PSAnZnVuY3Rpb24nICkge1xuXHRcdFx0XHQkdGhpcy5qb2JfaXRlbV9ncmlkLnNldERhdGEoICR0aGlzLmpvYl9pdGVtX3NvdXJjZSwgZmFsc2UgKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCB0eXBlb2YgJHRoaXMucHVuY2hfdGFnX2dyaWQuc2V0RGF0YSA9PSAnZnVuY3Rpb24nICkge1xuXHRcdFx0XHQkdGhpcy5wdW5jaF90YWdfZ3JpZC5zZXREYXRhKCAkdGhpcy5wdW5jaF90YWdfc291cmNlLCBmYWxzZSApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHR5cGVvZiAkdGhpcy5wcmVtaXVtX2dyaWQuc2V0RGF0YSA9PSAnZnVuY3Rpb24nICkge1xuXHRcdFx0XHQkdGhpcy5wcmVtaXVtX2dyaWQuc2V0RGF0YSggJHRoaXMucHJlbWl1bV9zb3VyY2UsIGZhbHNlICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggJHRoaXMuYWJzZW5jZV9ncmlkICkge1xuXHRcdFx0XHQkdGhpcy5hYnNlbmNlX2dyaWQuc2V0RGF0YSggJHRoaXMuYWJzZW5jZV9zb3VyY2UsIGZhbHNlICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggJHRoaXMuYWNjdW11bGF0ZWRfdG90YWxfZ3JpZF9zb3VyY2UubGVuZ3RoID09PSAwICkge1xuXHRcdFx0XHQkdGhpcy5hY2N1bXVsYXRlZF90b3RhbF9ncmlkX3NvdXJjZS5wdXNoKCk7XG5cdFx0XHR9XG5cblx0XHRcdCR0aGlzLmFjY3VtdWxhdGVkX3RvdGFsX2dyaWQuc2V0RGF0YSggJHRoaXMuYWNjdW11bGF0ZWRfdG90YWxfZ3JpZF9zb3VyY2UsIGZhbHNlICk7XG5cdFx0XHQkdGhpcy5wdW5jaF9ub3RlX2dyaWQuc2V0RGF0YSggJHRoaXMucHVuY2hfbm90ZV9ncmlkX3NvdXJjZSwgZmFsc2UgKTtcblx0XHRcdCR0aGlzLnZlcmlmaWNhdGlvbl9ncmlkLnNldERhdGEoICR0aGlzLnZlcmlmaWNhdGlvbl9ncmlkX3NvdXJjZSwgZmFsc2UgKTtcblxuXHRcdFx0JHRoaXMuc2V0R3JpZFNpemUoKTtcblxuXHRcdFx0JHRoaXMuc2V0VGltZVNoZWV0R3JpZFBheVBlcmlvZEhlYWRlcnMoKTtcblx0XHRcdCR0aGlzLnNldFRpbWVTaGVldEdyaWRIb2xpZGF5SGVhZGVycygpO1xuXHRcdFx0JHRoaXMuaGlnaExpZ2h0U2VsZWN0RGF5KCk7XG5cdFx0XHQkdGhpcy5hdXRvT3BlbkVkaXRWaWV3SWZOZWNlc3NhcnkoKTtcblx0XHRcdCR0aGlzLnNldFNjcm9sbFBvc2l0aW9uKCk7XG5cdFx0XHQkdGhpcy5pbml0UmlnaHRDbGlja01lbnUoKTtcblx0XHRcdCR0aGlzLmluaXRSaWdodENsaWNrTWVudSggUmlnaHRDbGlja01lbnVUeXBlLkFCU0VOQ0VfR1JJRCApO1xuXHRcdFx0JHRoaXMuc2hvd1dhcm5pbmdNZXNzYWdlSWZBbnkoKTtcblx0XHRcdCR0aGlzLnNldFB1bmNoTW9kZUNsYXNzKCk7XG5cblx0XHRcdGlmICggJHRoaXMuZ2V0UHVuY2hNb2RlKCkgIT0gJ3B1bmNoJyApIHtcblx0XHRcdFx0dmFyIGNvbHMgPSAkdGhpcy5nZXRNYW51YWxQYXlQZXJpb2REZWZhdWx0VHJDb2xzcGFuKCk7XG5cdFx0XHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGNvbHM7IGkrKyApIHtcblx0XHRcdFx0XHQkKCAnLnN1Yi1ncmlkIHRkOm50aC1jaGlsZCgnICsgaSArICcpJyApLmNzcyggJ2JvcmRlci1yaWdodCcsICdub25lJyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0c2VhcmNoRG9uZSgpIHtcblx0XHQkKCAnLmJ1dHRvbi1yb3RhdGUnICkucmVtb3ZlQ2xhc3MoICdidXR0b24tcm90YXRlJyApOyAvL3RoZSByb3RhdGUgaWNvbiBmcm9tIHNlYXJjaCBwYW5lbFxuXG5cdFx0VFRQcm9taXNlLnJlc29sdmUoICdpbml0JywgJ2luaXQnICk7XG5cdFx0VFRQcm9taXNlLndhaXQoKTtcblxuXHRcdC8vQ2hlY2sgdGhpcy5zZXRHcmlkU2l6ZSgpIHdoZXJlIHdlIHJlc2l6ZSB0aGUgZ3JpZHMgaWYgYSBzY3JvbGxiYXIgaXMgZGV0ZWN0ZWQgdG8gZW5zdXJlIGFsbCBncmlkcyByZW1haW4gdGhlIHNhbWUgd2lkdGggYWZ0ZXIgZWFjaCBvbmUgaXMgYnVpbHQuXG5cdFx0Ly8gVFRQcm9taXNlLndhaXQoIG51bGwsIG51bGwsIGZ1bmN0aW9uICgpIHtcblx0XHQvLyAgLy9UaGlzIHdhcyB0cmlnZ2VyaW5nIEpTIGV4Y2VwdGlvbjogUGVybWlzc2lvbiBkZW5pZWQgdG8gYWNjZXNzIHByb3BlcnR5IFwiYXBwbHlcIiAtLSBTZWVtcyBsaWtlIGl0cyBubyBsb25nZXIgbmVlZGVkIGVpdGhlci5cblx0XHQvLyBcdCQoIHdpbmRvdyApLnRyaWdnZXIoICdyZXNpemUnICk7XG5cdFx0Ly8gfSApO1xuXHR9XG5cblx0c2hvd1dhcm5pbmdNZXNzYWdlSWZBbnkoKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgdGltZXNoZWV0X2dyaWRfZGl2O1xuXHRcdHZhciB3YXJuaW5nX2JhciA9ICQoIHRoaXMuZWwgKS5maW5kKCAnLnRpbWVzaGVldC13YXJuaW5nLXRpdGxlLWJhcicgKTtcblx0XHR3YXJuaW5nX2Jhci5sZW5ndGggPiAwICYmIHdhcm5pbmdfYmFyLnJlbW92ZSgpICYmICggd2FybmluZ19iYXIgPSAkKCB0aGlzLmVsICkuZmluZCggJy50aW1lc2hlZXQtd2FybmluZy10aXRsZS1iYXInICkgKTtcblx0XHRpZiAoIHRoaXMuZ2V0UHVuY2hNb2RlKCkgPT09ICdwdW5jaCcgKSB7XG5cdFx0XHR0aW1lc2hlZXRfZ3JpZF9kaXYgPSAkKCB0aGlzLmVsICkuZmluZCggJyNnYm94XycgKyB0aGlzLnVpX2lkICsgJ19ncmlkJyApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aW1lc2hlZXRfZ3JpZF9kaXYgPSAkKCB0aGlzLmVsICkuZmluZCggJy5tYW51YWwtdGltZXNoZWV0LWluc2lkZS1lZGl0b3ItZGl2JyApO1xuXHRcdH1cblxuXHRcdHZhciB1c2VyID0gdGhpcy5nZXRTZWxlY3RFbXBsb3llZSggdHJ1ZSApO1xuXHRcdHZhciB1c2VyX3BheV9wZXJpb2RfY2hlY2sgPSBwYXlQZXJpb2RDaGVjayggdXNlciApO1xuXG5cdFx0Ly9UaGVyZSBzZWVtcyB0byBiZSBhIHJhY2UgY29uZGl0aW9uIGhlcmUgd2hlcmUgaWYgdGhlIHNlcnZlciBoYXNuJ3QgcmV0dXJuZWQgYWxsIHRoZSB1c2VyIGRhdGEgZm9yIHRoZSBkcm9wZG93biBib3ggKGR1ZSB0byBiZWluZyBzbG93L2luY2x1ZGluZyBtYW55IGNvbHVtbnMpLCBcInVzZXIuaWRcIiB3aWxsIGV4aXN0LCBidXQgbm8gb3RoZXIgb2JqZWN0IHByb3BlcnRpZXMgd2lsbC5cblx0XHQvLyAgVGhpcyBjb3VsZCB0cmlnZ2VyIHRoZSBiZWxvdyBlcnJvciBtZXNzYWdlKHMpIHRvIHNob3cgd2hlbiB0aGV5IHNob3VsZG4ndC4gU28gbm93IHdlIGNoZWNrIHRvIG1ha2Ugc3VyZSB0aGVyZSBpcyBhdCBsZWFzdCBtb3JlIHRoYW4gMSBvYmplY3QgcHJvcGVydHksIGFuZCB3ZSBjaGVjayB0aGF0IHRoZSBvYmplY3QgcHJvcGVydGllcyBhY3R1YWxseSBleGlzdCBhbmQgYXJlIGFjdHVhbGx5IGJsYW5rLCBhcyBjb21wYXJlZCB0byBqdXN0IGNoZWNraW5nIHRoYXQgdGhleSBkb24ndCBleGlzdCBwcmV2aW91c2x5LlxuXHRcdGlmICggR2xvYmFsLmlzT2JqZWN0KCB1c2VyICkgJiYgT2JqZWN0LmtleXMoIHVzZXIgKS5sZW5ndGggPiAxICYmICggKCB1c2VyLmhhc093blByb3BlcnR5KCAncGF5X3BlcmlvZF9zY2hlZHVsZV9pZCcgKSAmJiB1c2VyLnBheV9wZXJpb2Rfc2NoZWR1bGVfaWQgPT0gJycgKSB8fCAoIHVzZXIuaGFzT3duUHJvcGVydHkoICdwb2xpY3lfZ3JvdXBfaWQnICkgJiYgdXNlci5wb2xpY3lfZ3JvdXBfaWQgPT0gJycgKSB8fCB1c2VyX3BheV9wZXJpb2RfY2hlY2sgPT0gZmFsc2UgKSApIHtcblx0XHRcdHdhcm5pbmdfYmFyID0gJCggJzxkaXYgY2xhc3M9XFwndGltZXNoZWV0LXdhcm5pbmctdGl0bGUtYmFyXFwnPjxzcGFuIGNsYXNzPVxcJ3AtbWVzc2FnZVxcJz48L3NwYW4+PHNwYW4gY2xhc3M9XFwnZy1tZXNzYWdlXFwnPjwvc3Bhbj48c3BhbiBjbGFzcz1cXCdwcC1tZXNzYWdlXFwnPjwvc3Bhbj48L2Rpdj4nICk7XG5cdFx0XHR3YXJuaW5nX2Jhci5pbnNlcnRCZWZvcmUoIHRpbWVzaGVldF9ncmlkX2RpdiApO1xuXG5cdFx0XHRpZiAoIHVzZXIuaGFzT3duUHJvcGVydHkoICdwYXlfcGVyaW9kX3NjaGVkdWxlX2lkJyApICYmIHVzZXIucGF5X3BlcmlvZF9zY2hlZHVsZV9pZCA9PSAnJyApIHsgLy8hdXNlci5wYXlfcGVyaW9kX3NjaGVkdWxlX2lkXG5cdFx0XHRcdHdhcm5pbmdfYmFyLmNoaWxkcmVuKCkuZXEoIDAgKS5odG1sKCAkLmkxOG4uXyggJ1dBUk5JTkc6IEVtcGxveWVlIGlzIG5vdCBhc3NpZ25lZCB0byBhIHBheSBwZXJpb2Qgc2NoZWR1bGUuJyApICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR3YXJuaW5nX2Jhci5jaGlsZHJlbigpLmVxKCAwICkuaHRtbCggJycgKTtcblx0XHRcdH1cblx0XHRcdGlmICggdXNlci5oYXNPd25Qcm9wZXJ0eSggJ3BvbGljeV9ncm91cF9pZCcgKSAmJiB1c2VyLnBvbGljeV9ncm91cF9pZCA9PSAnJyApIHsgLy8hdXNlci5wb2xpY3lfZ3JvdXBfaWRcblx0XHRcdFx0d2FybmluZ19iYXIuY2hpbGRyZW4oKS5lcSggMSApLmh0bWwoICQuaTE4bi5fKCAnV0FSTklORzogRW1wbG95ZWUgaXMgbm90IGFzc2lnbmVkIHRvIGEgcG9saWN5IGdyb3VwLicgKSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0d2FybmluZ19iYXIuY2hpbGRyZW4oKS5lcSggMSApLmh0bWwoICcnICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggdXNlcl9wYXlfcGVyaW9kX2NoZWNrID09IGZhbHNlICkge1xuXHRcdFx0XHR3YXJuaW5nX2Jhci5jaGlsZHJlbigpLmVxKCAyICkuaHRtbCggJC5pMThuLl8oICdXQVJOSU5HOiBFbXBsb3llZSBoYXMgZGF5KHMpIG5vdCBhc3NpZ25lZCB0byBhIHBheSBwZXJpb2QuIFBsZWFzZSBwZXJmb3JtIGEgcGF5IHBlcmlvZCBpbXBvcnQgdG8gY29ycmVjdC4nICkgKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHdhcm5pbmdfYmFyLmNoaWxkcmVuKCkuZXEoIDIgKS5odG1sKCAnJyApO1xuXHRcdFx0fVxuXG5cdFx0fSBlbHNlIHtcblx0XHRcdGlmICggd2FybmluZ19iYXIubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0d2FybmluZ19iYXIucmVtb3ZlKCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gcGF5UGVyaW9kQ2hlY2soIHVzZXIgKSB7XG5cdFx0XHRpZiAoICR0aGlzLnN0YXJ0X2RhdGUgKSB7XG5cdFx0XHRcdHZhciBoaXJlX2RhdGUgPSB1c2VyLmhpcmVfZGF0ZTtcblx0XHRcdFx0dmFyIHRlcm1pbmF0aW9uX2RhdGUgPSB1c2VyLnRlcm1pbmF0aW9uX2RhdGU7XG5cblx0XHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgNzsgaSsrICkge1xuXHRcdFx0XHRcdHZhciBzZWxlY3RfZGF0ZSA9IG5ldyBEYXRlKCBuZXcgRGF0ZSggJHRoaXMuc3RhcnRfZGF0ZS5nZXRUaW1lKCkgKS5zZXREYXRlKCAkdGhpcy5zdGFydF9kYXRlLmdldERhdGUoKSArIGkgKSApO1xuXHRcdFx0XHRcdHZhciBzZWxlY3RfZGF0ZV9zdHIgPSBzZWxlY3RfZGF0ZS5mb3JtYXQoKTtcblxuXHRcdFx0XHRcdC8vRXJyb3I6IFVuY2F1Z2h0IFR5cGVFcnJvcjogQ2Fubm90IHJlYWQgcHJvcGVydHkgJ2dldFRpbWUnIG9mIG51bGwgaW4gaW50ZXJmYWNlL2h0bWw1L2luZGV4LnBocD91c2VyX25hbWU9ZHVzdGluIyFtPVRpbWVTaGVldCZkYXRlPTIwMTUxMjE0JnVzZXJfaWQ9Mzg1OTkmc2hvd193YWdlPTAgbGluZSAyOTQ3XG5cdFx0XHRcdFx0aWYgKCAhc2VsZWN0X2RhdGUgKSB7XG5cdFx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoIHNlbGVjdF9kYXRlLmdldFRpbWUoKSA8IG5ldyBEYXRlKCkuZ2V0VGltZSgpICYmICEkdGhpcy5nZXRQYXlQZXJpb2QoIHNlbGVjdF9kYXRlX3N0ciApICYmXG5cdFx0XHRcdFx0XHQoICFoaXJlX2RhdGUgfHwgc2VsZWN0X2RhdGUuZ2V0VGltZSgpID49IEdsb2JhbC5zdHJUb0RhdGUoIGhpcmVfZGF0ZSApLmdldFRpbWUoKSApICYmXG5cdFx0XHRcdFx0XHQoICF0ZXJtaW5hdGlvbl9kYXRlIHx8IHNlbGVjdF9kYXRlLmdldFRpbWUoKSA8PSBHbG9iYWwuc3RyVG9EYXRlKCB0ZXJtaW5hdGlvbl9kYXRlICkuZ2V0VGltZSgpICkgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHR9XG5cblx0YXV0b09wZW5FZGl0Vmlld0lmTmVjZXNzYXJ5KCkge1xuXHRcdC8vQXV0byBvcGVuIGVkaXQgdmlldy4gU2hvdWxkIHNldCBpbiBJbmRleENvbnRyb2xsZXJcblxuXHRcdHN3aXRjaCAoIExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfZG9pbmdfY29udGV4dF9hY3Rpb24gKSB7XG5cdFx0XHRjYXNlICdlZGl0Jzpcblx0XHRcdFx0aWYgKCBMb2NhbENhY2hlRGF0YS5lZGl0X2lkX2Zvcl9uZXh0X29wZW5fdmlldyApIHtcblx0XHRcdFx0XHR0aGlzLm9uRWRpdENsaWNrKCBMb2NhbENhY2hlRGF0YS5lZGl0X2lkX2Zvcl9uZXh0X29wZW5fdmlldywgTG9jYWxDYWNoZURhdGEuZ2V0QWxsVVJMQXJncygpLnQgKTtcblx0XHRcdFx0XHRMb2NhbENhY2hlRGF0YS5lZGl0X2lkX2Zvcl9uZXh0X29wZW5fdmlldyA9IG51bGw7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3ZpZXcnOlxuXHRcdFx0XHRpZiAoIExvY2FsQ2FjaGVEYXRhLmVkaXRfaWRfZm9yX25leHRfb3Blbl92aWV3ICkge1xuXHRcdFx0XHRcdHRoaXMub25WaWV3Q2xpY2soIExvY2FsQ2FjaGVEYXRhLmVkaXRfaWRfZm9yX25leHRfb3Blbl92aWV3LCBMb2NhbENhY2hlRGF0YS5nZXRBbGxVUkxBcmdzKCkudCApO1xuXHRcdFx0XHRcdExvY2FsQ2FjaGVEYXRhLmVkaXRfaWRfZm9yX25leHRfb3Blbl92aWV3ID0gbnVsbDtcblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ25ldyc6XG5cdFx0XHRcdGlmICggIXRoaXMuZWRpdF92aWV3ICkge1xuXHRcdFx0XHRcdGlmICggTG9jYWxDYWNoZURhdGEuZ2V0QWxsVVJMQXJncygpLnQgPT09ICdhYnNlbmNlJyApIHtcblx0XHRcdFx0XHRcdHRoaXMuYWJzZW5jZV9tb2RlbCA9IHRydWU7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHRoaXMuYWJzZW5jZV9tb2RlbCA9IGZhbHNlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHR0aGlzLm9uQWRkQ2xpY2soKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHR9XG5cblx0XHR0aGlzLmF1dG9PcGVuRWRpdE9ubHlWaWV3SWZOZWNlc3NhcnkoKTtcblx0fVxuXG5cdGdldFdlZWtEYXlJbmRleEZyb21BRGF0ZSggZGF0ZV9zdHJpbmcgKSB7XG5cblx0XHR2YXIgbGVuID0gdGhpcy50aW1lc2hlZXRfY29sdW1ucy5sZW5ndGg7XG5cblx0XHRmb3IgKCB2YXIgaSA9IDE7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdHZhciBjb2x1bW4gPSB0aGlzLnRpbWVzaGVldF9jb2x1bW5zW2ldO1xuXHRcdFx0dmFyIGNvbHVtbl9kYXRlX3N0cmluZyA9IEdsb2JhbC5zdHJUb0RhdGUoIGNvbHVtbi5pbmRleCwgdGhpcy5mdWxsX2Zvcm1hdCApLmZvcm1hdCgpO1xuXHRcdFx0aWYgKCBkYXRlX3N0cmluZyA9PT0gY29sdW1uX2RhdGVfc3RyaW5nICkge1xuXHRcdFx0XHRyZXR1cm4gaTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gNztcblx0fVxuXG5cdHNldEFjY3VtdWxhdGVkVG90YWxHcmlkUGF5UGVyaW9kSGVhZGVycyggd2lkdGggKSB7XG5cdFx0dmFyIHRhYmxlID0gJCggJCggdGhpcy5lbCApLmZpbmQoICd0YWJsZVthcmlhLWxhYmVsbGVkYnk9Z2JveF8nICsgdGhpcy51aV9pZCArICdfYWNjdW11bGF0ZWRfdG90YWxfZ3JpZF0nIClbMF0gKTtcblx0XHR0YWJsZS53aWR0aCggd2lkdGggKTtcblxuXHRcdHZhciBuZXdfdHIgPSAkKCAnPHRyIGNsYXNzPVwiZ3JvdXAtY29sdW1uLXRyXCIgIHJvbGU9XCJyb3doZWFkZXJcIiAgPicgK1xuXHRcdFx0JzwvdHI+JyApO1xuXG5cdFx0dmFyIG5ld190aCA9ICQoICc8dGggY2xhc3M9XCJncm91cC1jb2x1bW4tdGhcIiA+JyArXG5cdFx0XHQnPHNwYW4gY2xhc3M9XCJncm91cC1jb2x1bW4tbGFiZWxcIj48L3NwYW4+JyArXG5cdFx0XHQnPC90aD4nICk7XG5cblx0XHR2YXIgZGVmYXVsdF90aCA9IG5ld190aC5jbG9uZSgpO1xuXG5cdFx0dmFyIHdlZWtfdGggPSBuZXdfdGguY2xvbmUoKTtcblxuXHRcdHZhciBwYXlfcGVyaW9kX3RoID0gbmV3X3RoLmNsb25lKCk7XG5cblx0XHR3ZWVrX3RoLmNoaWxkcmVuKCAwICkudGV4dCggJC5pMThuLl8oICdXZWVrJyApICk7XG5cdFx0cGF5X3BlcmlvZF90aC5jaGlsZHJlbiggMCApLnRleHQoICQuaTE4bi5fKCAnUGF5IFBlcmlvZCcgKSApO1xuXG5cdFx0bmV3X3RyLmFwcGVuZCggZGVmYXVsdF90aCApO1xuXHRcdG5ld190ci5hcHBlbmQoIHdlZWtfdGggKTtcblx0XHRuZXdfdHIuYXBwZW5kKCBwYXlfcGVyaW9kX3RoICk7XG5cblx0XHR0YWJsZS5maW5kKCAnLnJvd2hlYWRlcicgKS5yZW1vdmUoKTtcblx0XHR0YWJsZS5maW5kKCAndGhlYWQnICkucHJlcGVuZCggbmV3X3RyICk7XG5cdH1cblxuXHRzZXRUaW1lU2hlZXRHcmlkSG9saWRheUhlYWRlcnMoKSB7XG5cdFx0dmFyIGhvbGlkYXlfbmFtZV9tYXAgPSB7fTtcblx0XHRpZiAoIHRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YSAmJiB0aGlzLmZ1bGxfdGltZXNoZWV0X2RhdGEuaG9saWRheV9kYXRhICkge1xuXHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgdGhpcy5mdWxsX3RpbWVzaGVldF9kYXRhLmhvbGlkYXlfZGF0YS5sZW5ndGg7IGkrKyApIHtcblx0XHRcdFx0dmFyIGl0ZW0gPSB0aGlzLmZ1bGxfdGltZXNoZWV0X2RhdGEuaG9saWRheV9kYXRhW2ldO1xuXHRcdFx0XHR2YXIgc3RhbmRhcmRfZGF0ZSA9IEdsb2JhbC5zdHJUb0RhdGUoIGl0ZW0uZGF0ZV9zdGFtcCApLmZvcm1hdCggdGhpcy5mdWxsX2Zvcm1hdCApO1xuXG5cdFx0XHRcdHZhciBjZWxsID0gJCggJzxkaXY+PC9kaXY+JyApO1xuXHRcdFx0XHRpZiAoIHRoaXMuZ2V0UHVuY2hNb2RlKCkgPT09ICdtYW51YWwnICkge1xuXHRcdFx0XHRcdGNlbGwgPSAkKCAnLm1hbnVhbF9ncmlkX2RheV8nICsgc3RhbmRhcmRfZGF0ZSApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGNlbGwgPSAkKCAnZGl2W2lkPVwianFnaF8nICsgdGhpcy51aV9pZCArICdfZ3JpZF8nICsgc3RhbmRhcmRfZGF0ZSArICdcIl0nICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIGNlbGwgJiYgY2VsbC50ZXh0KCkuaW5kZXhPZiggaXRlbS5uYW1lICkgPT0gLTEgJiYgIWhvbGlkYXlfbmFtZV9tYXBbaXRlbS5uYW1lXSApIHtcblx0XHRcdFx0XHRjZWxsLmh0bWwoIGNlbGwuaHRtbCgpICsgJzxicj4nICsgR2xvYmFsLmh0bWxFbmNvZGUoIGl0ZW0ubmFtZSApICk7XG5cdFx0XHRcdFx0aG9saWRheV9uYW1lX21hcFtpdGVtLm5hbWVdID0gdHJ1ZTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Z2V0TWFudWFsUGF5UGVyaW9kRGVmYXVsdFRyQ29sc3BhbigpIHtcblx0XHR2YXIgY29sc3BhbiA9IDI7XG5cdFx0aWYgKCB0aGlzLnNob3dfYnJhbmNoX3VpICkge1xuXHRcdFx0Y29sc3BhbisrO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5zaG93X2RlcGFydG1lbnRfdWkgKSB7XG5cdFx0XHRjb2xzcGFuKys7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLnNob3dfam9iX3VpICkge1xuXHRcdFx0Y29sc3BhbisrO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5zaG93X2pvYl9pdGVtX3VpICkge1xuXHRcdFx0Y29sc3BhbisrO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5zaG93X3B1bmNoX3RhZ191aSApIHtcblx0XHRcdGNvbHNwYW4rKztcblx0XHR9XG5cblx0XHRyZXR1cm4gY29sc3Bhbjtcblx0fVxuXG5cdHNldFRpbWVTaGVldEdyaWRQYXlQZXJpb2RIZWFkZXJzKCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dmFyIHRhYmxlLFxuXHRcdFx0c2l6ZV90cjtcblx0XHRpZiAoIHRoaXMuZ2V0UHVuY2hNb2RlKCkgPT09ICdwdW5jaCcgKSB7XG5cdFx0XHR0YWJsZSA9ICQoICQoIHRoaXMuZWwgKS5maW5kKCAndGFibGVbYXJpYS1sYWJlbGxlZGJ5PWdib3hfJyArIHRoaXMudWlfaWQgKyAnX2dyaWRdJyApWzBdICk7XG5cdFx0XHRzaXplX3RyID0gJCggJzx0ciBjbGFzcz1cInNpemUtdHJcIiByb2xlPVwicm93XCIgc3R5bGU9XCJoZWlnaHQ6IDA7XCIgPicgKyAnPC90cj4nICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRhYmxlID0gdGhpcy4kKCAnLmdyaWQtaW5zaWRlLWVkaXRvci1yZW5kZXInICk7XG5cdFx0XHR0YWJsZS5maW5kKCAnLmdyb3VwLWNvbHVtbi10cicgKS5yZW1vdmUoKTtcblx0XHRcdHNpemVfdHIgPSAkKCB0aGlzLiQoICcuZ3JpZC1pbnNpZGUtZWRpdG9yLXJlbmRlcicgKS5maW5kKCAndHInIClbMF0gKTtcblx0XHR9XG5cblx0XHR0YWJsZS5maW5kKCAnLmdyb3VwLWNvbHVtbi10cicgKS5yZW1vdmUoKTtcblxuXHRcdHZhciBuZXdfdHIgPSAkKCAnPHRyIGNsYXNzPVwiZ3JvdXAtY29sdW1uLXRyIHBheV9wZXJpb2RfaGVhZGVyX3Jvd1wiPjwvdHI+JyApO1xuXHRcdHZhciBuZXdfdGggPSAkKCAnPHRoIGNsYXNzPVwiZ3JvdXAtY29sdW1uLXRoXCI+PHNwYW4gY2xhc3M9XCJncm91cC1jb2x1bW4tbGFiZWxcIj48L3NwYW4+PC90aD4nICk7XG5cdFx0dmFyIGN1cnJlbnRfdHJzID0gdGFibGUuZmluZCggJy51aS1qcWdyaWQtbGFiZWxzJyApO1xuXG5cdFx0Ly8gY3JlYXRlU2l6ZUNvbHVtbnMgd2FzIGFkZGVkIGluIDIwMTQuIFdoZW4gbWFudWFsIHRpbWVzaGVldCBtb2RlIHdhcyBhZGRlZCBpbiAyMDE2LCB0aGluZ3Mgd2VyZSByZWZhY3RvcmVkIGFuZCB0aGlzIHNob3VsZCBoYXZlIGJlZW4gcHVsbGVkIG91dC5cblx0XHQvLyBMZWF2aW5nIGl0IGluIGNhdXNlcyAgaGVhZGVyIHJvdyBzb2x1bW5zIHRvIGJlIG91dCBvZiBhbGlnbm1lbnQgd2l0aCB0aGUgdGltZXNoZWV0IHB1bmNoIGdyaWQgYnkgYSBmZXcgcGl4ZWxzLlxuXHRcdGlmICggdGhpcy5nZXRQdW5jaE1vZGUoKSA9PT0gJ3B1bmNoJyApIHtcblx0XHRcdGNyZWF0ZVNpemVDb2x1bW5zKCk7XG5cdFx0XHRzaXplX3RyLmluc2VydEJlZm9yZSggdGFibGUuZmluZCggJ3RoZWFkIC51aS1qcWdyaWQtbGFiZWxzJyApICk7XG5cdFx0fVxuXG5cdFx0dmFyIGRlZmF1bHRfdGg7XG5cdFx0aWYgKCBPYmplY3Qua2V5cyggdGhpcy5wYXlfcGVyaW9kX2RhdGEgKS5sZW5ndGggPT09IDAgKSB7XG5cdFx0XHRkZWZhdWx0X3RoID0gbmV3X3RoLmNsb25lKCk7XG5cdFx0XHRuZXdfdHIuYXBwZW5kKCBkZWZhdWx0X3RoICk7XG5cdFx0XHRpZiAoIHRoaXMuZ2V0UHVuY2hNb2RlKCkgPT09ICdtYW51YWwnICkge1xuXHRcdFx0XHRkZWZhdWx0X3RoLmF0dHIoICdjb2xzcGFuJywgdGhpcy5nZXRNYW51YWxQYXlQZXJpb2REZWZhdWx0VHJDb2xzcGFuKCkgKTtcblx0XHRcdH1cblx0XHRcdGNyZWF0ZU5vUGF5UGVyaW9kQ29sdW1ucyggNyApO1xuXHRcdFx0bmV3X3RyLmluc2VydEFmdGVyKCBzaXplX3RyICk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHZhciBjdXJyZW50X2VuZF9pbmRleCA9IDA7XG5cdFx0dmFyIGxhc3RfcGF5X3BlcmlvZF9pZDtcblx0XHR2YXIgY29sdW1uX251bWJlciA9IDA7XG5cdFx0dmFyIHBheV9wZXJpb2Q7XG5cdFx0dmFyIG1hcF9hcnJheSA9IFtdO1xuXHRcdGZvciAoIHZhciB5ID0gMDsgeSA8IHRoaXMuY29sdW1uX21hcHMubGVuZ3RoOyB5KysgKSB7XG5cdFx0XHR2YXIgcF9rZXkgPSB0aGlzLmNvbHVtbl9tYXBzW3ldO1xuXHRcdFx0dmFyIHBheV9wZXJpb2RfaWQgPSB0aGlzLnBheV9wZXJpb2RfbWFwW3Bfa2V5XTtcblx0XHRcdGlmICggIXBheV9wZXJpb2RfaWQgKSB7XG5cdFx0XHRcdHBheV9wZXJpb2RfaWQgPSAtMTtcblx0XHRcdH1cblx0XHRcdG1hcF9hcnJheS5wdXNoKCB7IGRhdGU6IHBfa2V5LCB0aW1lX3N0YW1wOiBHbG9iYWwuc3RyVG9EYXRlKCBwX2tleSApLmdldFRpbWUoKSwgaWQ6IHBheV9wZXJpb2RfaWQgfSApO1xuXHRcdH1cblxuXHRcdGRlZmF1bHRfdGggPSBuZXdfdGguY2xvbmUoKTtcblx0XHRuZXdfdHIuYXBwZW5kKCBkZWZhdWx0X3RoICk7XG5cdFx0aWYgKCB0aGlzLmdldFB1bmNoTW9kZSgpID09PSAnbWFudWFsJyApIHtcblx0XHRcdGRlZmF1bHRfdGguYXR0ciggJ2NvbHNwYW4nLCB0aGlzLmdldE1hbnVhbFBheVBlcmlvZERlZmF1bHRUckNvbHNwYW4oKSApO1xuXHRcdH1cblx0XHRmb3IgKCB2YXIgaiA9IDA7IGogPCBtYXBfYXJyYXkubGVuZ3RoOyBqKysgKSB7XG5cdFx0XHRpZiAoICFsYXN0X3BheV9wZXJpb2RfaWQgKSB7XG5cdFx0XHRcdGxhc3RfcGF5X3BlcmlvZF9pZCA9IG1hcF9hcnJheVtqXS5pZDtcblx0XHRcdFx0cGF5X3BlcmlvZCA9IGdldFBheVBlcmlvZCggbWFwX2FycmF5W2pdLmlkICk7XG5cdFx0XHRcdGNvbHVtbl9udW1iZXIgPSBjb2x1bW5fbnVtYmVyICsgMTtcblx0XHRcdH0gZWxzZSBpZiAoIGxhc3RfcGF5X3BlcmlvZF9pZCAhPT0gbWFwX2FycmF5W2pdLmlkICkge1xuXHRcdFx0XHRpZiAoIHBheV9wZXJpb2QgKSB7XG5cdFx0XHRcdFx0Y3JlYXRlVGgoKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRjcmVhdGVOb1BheVBlcmlvZENvbHVtbnMoIGNvbHVtbl9udW1iZXIgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRsYXN0X3BheV9wZXJpb2RfaWQgPSBtYXBfYXJyYXlbal0uaWQ7XG5cdFx0XHRcdHBheV9wZXJpb2QgPSBnZXRQYXlQZXJpb2QoIG1hcF9hcnJheVtqXS5pZCApO1xuXHRcdFx0XHRjb2x1bW5fbnVtYmVyID0gMTtcblxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Y29sdW1uX251bWJlciA9IGNvbHVtbl9udW1iZXIgKyAxO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCBqID09PSBtYXBfYXJyYXkubGVuZ3RoIC0gMSAmJiBjb2x1bW5fbnVtYmVyID4gMCApIHtcblx0XHRcdFx0aWYgKCBwYXlfcGVyaW9kICkge1xuXHRcdFx0XHRcdGNyZWF0ZVRoKCk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Y3JlYXRlTm9QYXlQZXJpb2RDb2x1bW5zKCBjb2x1bW5fbnVtYmVyICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdFx0JCggJy5wYXlfcGVyaW9kX2hlYWRlcl9yb3cnICkucmVtb3ZlKCk7XG5cdFx0bmV3X3RyLmluc2VydEFmdGVyKCBzaXplX3RyICk7XG5cblx0XHRmdW5jdGlvbiBjcmVhdGVUaCgpIHtcblx0XHRcdHZhciBzdGFydF9kYXRlID0gR2xvYmFsLnN0clRvRGF0ZSggcGF5X3BlcmlvZC5zdGFydF9kYXRlICkuZm9ybWF0KCk7XG5cdFx0XHR2YXIgZW5kX2RhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCBwYXlfcGVyaW9kLmVuZF9kYXRlICkuZm9ybWF0KCk7XG5cdFx0XHR2YXIgY29sc3BhbiA9IGNvbHVtbl9udW1iZXI7XG5cdFx0XHR2YXIgcGF5X3BlcmlvZF90aCA9IG5ld190aC5jbG9uZSgpO1xuXHRcdFx0cGF5X3BlcmlvZF90aC5jaGlsZHJlbiggMCApLnRleHQoIHN0YXJ0X2RhdGUgKyAnICcgKyAkLmkxOG4uXyggJ3RvJyApICsgJyAnICsgZW5kX2RhdGUgKTtcblx0XHRcdHBheV9wZXJpb2RfdGguYXR0ciggJ2NvbHNwYW4nLCBjb2xzcGFuICk7XG5cdFx0XHQvKiBqc2hpbnQgaWdub3JlOnN0YXJ0ICovXG5cdFx0XHRpZiAoIHBheV9wZXJpb2Quc3RhdHVzX2lkID09IDEyIHx8IHBheV9wZXJpb2Quc3RhdHVzX2lkID09IDIwICkge1xuXHRcdFx0XHRwYXlfcGVyaW9kX3RoLmNzcyggJ2JhY2tncm91bmQnLCAnI0VDMDAwMCcgKTtcblx0XHRcdH0gZWxzZSBpZiAoIHBheV9wZXJpb2Quc3RhdHVzX2lkID09IDMwICkge1xuXHRcdFx0XHRwYXlfcGVyaW9kX3RoLmNzcyggJ2JhY2tncm91bmQnLCAnI0VFRDYxNCcgKTtcblx0XHRcdH1cblx0XHRcdC8qIGpzaGludCBpZ25vcmU6ZW5kICovXG5cdFx0XHRuZXdfdHIuYXBwZW5kKCBwYXlfcGVyaW9kX3RoICk7XG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gZ2V0UGF5UGVyaW9kKCBpZCApIHtcblx0XHRcdGZvciAoIHZhciBrZXkgaW4gJHRoaXMucGF5X3BlcmlvZF9kYXRhICkge1xuXHRcdFx0XHR2YXIgcGF5X3BlcmlvZCA9ICR0aGlzLnBheV9wZXJpb2RfZGF0YVtrZXldO1xuXHRcdFx0XHRpZiAoIHBheV9wZXJpb2QuaWQgPT09IGlkICkge1xuXHRcdFx0XHRcdHJldHVybiBwYXlfcGVyaW9kO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gY3JlYXRlTm9QYXlQZXJpb2RDb2x1bW5zKCBlbmRfaW5kZXggKSB7XG5cdFx0XHR2YXIgcGF5X3BlcmlvZF90aCA9IG5ld190aC5jbG9uZSgpO1xuXHRcdFx0cGF5X3BlcmlvZF90aC5hZGRDbGFzcyggJ25vX3BheV9wZXJpb2RfaGVhZGVyJyApO1xuXHRcdFx0cGF5X3BlcmlvZF90aC5jaGlsZHJlbiggMCApLnRleHQoICQuaTE4bi5fKCAnTm8gUGF5IFBlcmlvZCcgKSApO1xuXHRcdFx0cGF5X3BlcmlvZF90aC5hdHRyKCAnY29sc3BhbicsIGVuZF9pbmRleCApO1xuXHRcdFx0bmV3X3RyLmFwcGVuZCggcGF5X3BlcmlvZF90aCApO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGNyZWF0ZVNpemVDb2x1bW5zKCkge1xuXHRcdFx0dmFyIGxlbiA9IGN1cnJlbnRfdHJzLmNoaWxkcmVuKCkubGVuZ3RoO1xuXHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRcdHZhciB0aCA9ICQoICc8dGQgY2xhc3M9XCJcIiAgcm9sZT1cImdyaWRjZWxsXCI+JyArICc8L3RkPicgKTtcblx0XHRcdFx0dmFyIGl0ZW0gPSBjdXJyZW50X3Rycy5jaGlsZHJlbigpLmVxKCBpICk7XG5cdFx0XHRcdC8vdGgud2lkdGgoIGl0ZW0ud2lkdGgoKSApO1xuXHRcdFx0XHR0aC5oZWlnaHQoIDAgKTtcblx0XHRcdFx0dGguY3NzKCAnd2lkdGgnLCBpdGVtLmNzcyggJ3dpZHRoJyApICk7XG5cdFx0XHRcdHNpemVfdHIuYXBwZW5kKCB0aCApO1xuXHRcdFx0fVxuXG5cdFx0fVxuXHR9XG5cblx0c2V0UGF5UGVyaW9kSGVhZGVyU2l6ZSgpIHtcblxuXHRcdHZhciB0YWJsZSA9ICQoICQoIHRoaXMuZWwgKS5maW5kKCAndGFibGVbYXJpYS1sYWJlbGxlZGJ5PWdib3hfJyArIHRoaXMudWlfaWQgKyAnX2dyaWRdJyApICk7XG5cdFx0dmFyIHNpemVfdHIgPSB0YWJsZS5maW5kKCAnLnNpemUtdHInICk7XG5cblx0XHRpZiAoIHNpemVfdHIubGVuZ3RoID09PSAwICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHQvKipcblx0XHQgKiAjMjM1MyAtIHRpZW1zaGVldCBzaXppbmcgZml4XG5cdFx0ICpcblx0XHQgKiBEdWUgdG8gZmlyZWZveCByZXBvcnRpbmcgdGggd2lkdGhzIGluY29ycmVjdGx5IHZpYSB0aGUgJC53aWR0aCgpIGZ1bmN0aW9uLCB0aGUgc2l6ZXMgbXVzdCBjb21lIGZyb20gdGhlICh0ci5qcWdmaXJzdHJvdykgb2YgdGhlIGRhdGEgdGFibGVcblx0XHQgKiBmaXJlZm94IGFsc28gcmVmdXNlcyB0byBzZXQgdGhlIHdpZHRoIG9mIHRoZSBmaXJzdCByb3cgb2YgdGgncyB2aWEgdGhlICQud2lkdGgoKSBmdW5jdGlvbiwgc28gd2UgbmVkIHRvIHNoaXAgdGhlIGNzcyB2YWx1ZXMgZGlyZWN0bHkgaW50byB0aGUgaW5saW5lIGNzcyB1c2luZyB0aGUgY3NzIGZ1bmN0aW9uXG5cdFx0ICovXG5cdFx0dmFyIGN1cnJlbnRfdHJzID0gdGFibGUuZmluZCggJy5qcWdmaXJzdHJvdycgKTtcblx0XHR2YXIgbGVuID0gY3VycmVudF90cnMuY2hpbGRyZW4oKS5sZW5ndGg7XG5cblx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdHZhciBpdGVtID0gY3VycmVudF90cnMuY2hpbGRyZW4oKS5lcSggaSApO1xuXHRcdFx0c2l6ZV90ci5jaGlsZHJlbigpLmVxKCBpICkuY3NzKCAnd2lkdGgnLCBpdGVtLmNzcyggJ3dpZHRoJyApICk7XG5cdFx0fVxuXHR9XG5cblx0aGlnaExpZ2h0U2VsZWN0RGF5KCBlICkge1xuXG5cdFx0aWYgKCB0aGlzLmhpZ2hsaWdodF9oZWFkZXIgKSB7XG5cdFx0XHR0aGlzLmhpZ2hsaWdodF9oZWFkZXIucmVtb3ZlQ2xhc3MoICdoaWdobGlnaHQtaGVhZGVyJyApO1xuXHRcdH1cblxuXHRcdC8vRXJyb3I6IFR5cGVFcnJvcjogc2VsZWN0X2RhdGUgaXMgbnVsbCBpbiBpbnRlcmZhY2UvaHRtbDUvZnJhbWV3b3JrL2pxdWVyeS5taW4uanM/dj05LjAuMS0yMDE1MTAyMi0wODE3MjQgbGluZSAyID4gZXZhbCBsaW5lIDMyMTRcblx0XHR2YXIgc2VsZWN0X2RhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCB0aGlzLnN0YXJ0X2RhdGVfcGlja2VyLmdldFZhbHVlKCkgKTtcblx0XHQhc2VsZWN0X2RhdGUgJiYgKCBzZWxlY3RfZGF0ZSA9IG5ldyBEYXRlKCkgKTtcblxuXHRcdGlmICggdGhpcy5nZXRQdW5jaE1vZGUoKSA9PT0gJ3B1bmNoJyApIHtcblx0XHRcdHNlbGVjdF9kYXRlID0gc2VsZWN0X2RhdGUuZm9ybWF0KCB0aGlzLmZ1bGxfZm9ybWF0ICk7XG5cdFx0XHR0aGlzLmhpZ2hsaWdodF9oZWFkZXIgPSAkKCAnIycgKyB0aGlzLnVpX2lkICsgJ19ncmlkXycgKyBzZWxlY3RfZGF0ZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRzZWxlY3RfZGF0ZSA9IHNlbGVjdF9kYXRlLmZvcm1hdCggdGhpcy5mdWxsX2Zvcm1hdCApO1xuXHRcdFx0dGhpcy5oaWdobGlnaHRfaGVhZGVyID0gJCggJy5tYW51YWxfZ3JpZF9kYXlfJyArIHNlbGVjdF9kYXRlICk7XG5cdFx0fVxuXG5cdFx0dGhpcy5oaWdobGlnaHRfaGVhZGVyLmFkZENsYXNzKCAnaGlnaGxpZ2h0LWhlYWRlcicgKTtcblxuXHRcdGlmICggJCggJy50aW1lc2hlZXQtZ3JpZCB0ciB0ZC51aS1zdGF0ZS1oaWdobGlnaHQnICkubGVuZ3RoID09IDAgJiYgIWUgKSB7XG5cdFx0XHQkKCAkKCAnLnRpbWVzaGVldC1ncmlkIHRyIzEgdGQnIClbdGhpcy5oaWdobGlnaHRfaGVhZGVyLmluZGV4KCldICkuYWRkQ2xhc3MoICd1aS1zdGF0ZS1oaWdobGlnaHQnICk7XG5cdFx0XHQkKCAkKCAnLnRpbWVzaGVldC1ncmlkIHRyIzEgdGQnIClbdGhpcy5oaWdobGlnaHRfaGVhZGVyLmluZGV4KCldICkuY2xpY2soKTsgLy90cmlnZ2VyIGdyaWQgc2VsZWN0aW9uIGV2ZW50c1xuXHRcdH1cblx0fVxuXG5cdC8qIGpzaGludCBpZ25vcmU6c3RhcnQgKi9cblx0c2V0R3JpZEhlaWdodCggZ3JpZF9pZCApIHtcblx0XHR2YXIgZ3JpZCA9IHRoaXMuZ3JpZF9kaWNbZ3JpZF9pZF07XG5cdFx0aWYgKCBncmlkLmdyaWQgKSB7XG5cdFx0XHRncmlkID0gZ3JpZC5ncmlkO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdHZhciBsZW4gPSAwO1xuXG5cdFx0c3dpdGNoICggZ3JpZF9pZCApIHtcblx0XHRcdGNhc2UgJ3RpbWVzaGVldF9ncmlkJzpcblx0XHRcdFx0bGVuID0gdGhpcy50aW1lc2hlZXRfZGF0YV9zb3VyY2UubGVuZ3RoO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ2FjY3VtdWxhdGVkX3RpbWVfZ3JpZCc6XG5cdFx0XHRcdGxlbiA9IHRoaXMuYWNjdW11bGF0ZWRfdGltZV9zb3VyY2UubGVuZ3RoO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ2JyYW5jaF9ncmlkJzpcblx0XHRcdFx0bGVuID0gdGhpcy5icmFuY2hfc291cmNlLmxlbmd0aDtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdkZXBhcnRtZW50X2dyaWQnOlxuXHRcdFx0XHRsZW4gPSB0aGlzLmRlcGFydG1lbnRfc291cmNlLmxlbmd0aDtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdqb2JfZ3JpZCc6XG5cdFx0XHRcdGxlbiA9IHRoaXMuam9iX3NvdXJjZS5sZW5ndGg7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnam9iX2l0ZW1fZ3JpZCc6XG5cdFx0XHRcdGxlbiA9IHRoaXMuam9iX2l0ZW1fc291cmNlLmxlbmd0aDtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdwdW5jaF90YWdfZ3JpZCc6XG5cdFx0XHRcdGxlbiA9IHRoaXMucHVuY2hfdGFnX3NvdXJjZS5sZW5ndGg7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAncHJlbWl1bV9ncmlkJzpcblx0XHRcdFx0bGVuID0gdGhpcy5wcmVtaXVtX3NvdXJjZS5sZW5ndGg7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnYWJzZW5jZV9ncmlkJzpcblx0XHRcdFx0bGVuID0gdGhpcy5hYnNlbmNlX3NvdXJjZS5sZW5ndGg7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnYWNjdW11bGF0ZWRfdG90YWxfZ3JpZCc6XG5cdFx0XHRcdGxlbiA9IHRoaXMuYWNjdW11bGF0ZWRfdG90YWxfZ3JpZF9zb3VyY2UubGVuZ3RoO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3B1bmNoX25vdGVfZ3JpZCc6XG5cdFx0XHRcdGxlbiA9IHRoaXMucHVuY2hfbm90ZV9ncmlkX3NvdXJjZS5sZW5ndGg7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAndmVyaWZpY2F0aW9uX2dyaWQnOlxuXHRcdFx0XHRsZW4gPSB0aGlzLnZlcmlmaWNhdGlvbl9ncmlkX3NvdXJjZS5sZW5ndGg7XG5cdFx0fVxuXG5cdFx0aWYgKCBMb2NhbENhY2hlRGF0YS50aW1lc2hlZXRfc3ViX2dyaWRfZXhwZW5kZWRfZGljW2dyaWRfaWRdID09PSB0cnVlIHx8XG5cdFx0XHRncmlkX2lkID09PSAndGltZXNoZWV0X2dyaWQnIHx8XG5cdFx0XHRncmlkX2lkID09PSAnYWNjdW11bGF0ZWRfdG90YWxfZ3JpZCcgfHxcblx0XHRcdGdyaWRfaWQgPT09ICdwdW5jaF9ub3RlX2dyaWQnIHx8XG5cdFx0XHRncmlkX2lkID09PSAndmVyaWZpY2F0aW9uX2dyaWQnICkge1xuXHRcdFx0Z3JpZC5zZXRHcmlkSGVpZ2h0KCBsZW4gKiAyMiApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRncmlkLnNldEdyaWRIZWlnaHQoIDAgKTtcblxuXHRcdH1cblxuXHRcdC8vZG9udCd0IHNob3cgc2Nyb2xsIGJhciBvZiBncmlkXG5cdFx0Z3JpZC5wYXJlbnQoKS5wYXJlbnQoKS5jc3MoICdvdmVyZmxvdycsICdoaWRkZW4nICk7XG5cblx0XHQvL0RvIG5vdCBzaG93IGdyaWQgaWYgbm8gZGF0YSBpbiBpdFxuXHRcdGlmICggbGVuID09PSAwICYmIGdyaWRfaWQgIT09ICdhY2N1bXVsYXRlZF90aW1lX2dyaWQnICYmIGdyaWRfaWQgIT09ICd2ZXJpZmljYXRpb25fZ3JpZCcgKSB7XG5cdFx0XHRncmlkLnBhcmVudCgpLnBhcmVudCgpLnBhcmVudCgpLnBhcmVudCgpLmhpZGUoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Z3JpZC5wYXJlbnQoKS5wYXJlbnQoKS5wYXJlbnQoKS5wYXJlbnQoKS5zaG93KCk7XG5cdFx0fVxuXHR9XG5cblx0LyoganNoaW50IGlnbm9yZTplbmQgKi9cblxuXHRzZXRHcmlkQ29sdW1uc1dpZHRoKCkge1xuXHRcdC8vQmFzZVZpZXdDb250cm9sbGVyIGRlZmluaXRpb24gb2YgdGhpcyBmdW5jdGlvbiByZXNpemVzIHRoZSBtYWluIGdyaWQgb2YgYSB2aWV3LCBidXQgd2Ugd2FudCB0byByZXNpemUgYWxsIGdyaWRzIGluIHRoaXMgdmlldy5cblx0XHQvL1RoZSBCYXNlVmlld0NvbnRyb2xsZXIgdmVyc2lvbiB3b3VsZCBiZSBjYWxsZWQgd2hlbiBleHBhbmRpbmcvY29sbGFwc2luZyB0aGUgc2VhcmNoIHBhbmVsIGNhdXNpbmcgb25seSB0aGUgbWFpbiBncmlkIHRvIGJlIHJlc2l6ZWQgYW5kIGJlIG1pc2FsaWduZWQgd2l0aCB0aGUgb3RoZXJzLlxuXHRcdHRoaXMuc2V0R3JpZFNpemUoKTtcblx0fVxuXG5cdHNldEdyaWRTaXplKCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cblx0XHQvL1RUR3JpZCBiYWNrd2FyZHMgY29tcGF0aWJsZS5cblx0XHR2YXIgJGdyaWQgPSB0aGlzLmdyaWQ7XG5cdFx0aWYgKCAkZ3JpZC5ncmlkICkge1xuXHRcdFx0JGdyaWQgPSAkZ3JpZC5ncmlkO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdGlmICggKCAhJGdyaWQgfHwgISQoICRncmlkICkuaXMoICc6dmlzaWJsZScgKSApICYmICggIXRoaXMuZWRpdG9yIHx8ICF0aGlzLmVkaXRvci5pcyggJzp2aXNpYmxlJyApICkgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Zm9yICggdmFyIGtleSBpbiB0aGlzLmdyaWRfZGljICkge1xuXHRcdFx0aWYgKCBrZXkgIT0gJ3B1bmNoX25vdGVfZ3JpZCcgJiYga2V5ICE9ICdhY2N1bXVsYXRlZF90b3RhbF9ncmlkJyAmJiBrZXkgIT0gJ3ZlcmlmaWNhdGlvbl9ncmlkJyApIHtcblx0XHRcdFx0aWYgKCAhdGhpcy5ncmlkX2RpY1trZXldLmdyaWQgKSB7XG5cdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0dmFyIGdyaWQgPSB0aGlzLmdyaWRfZGljW2tleV0uZ3JpZDtcblx0XHRcdFx0Z3JpZC5zZXRHcmlkV2lkdGgoIHRoaXMuZ2V0VGltZVNoZWV0V2lkdGgoKSApO1xuXHRcdFx0XHR0aGlzLnNldEdyaWRIZWlnaHQoIGtleSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHRoaXMuc2V0R3JpZEhlaWdodCggJ2FjY3VtdWxhdGVkX3RvdGFsX2dyaWQnICk7IC8vY2FuJ3Qgc2V0IGhlaWdodCBvbiB0aGlzIGdyaWQuIHVudGlsIHdlIGZpeCB3aGF0J3Mgd3Jvbmcgd2l0aCBpdC5cblxuXHRcdHRoaXMuZ3JpZF9kaWNbJ3ZlcmlmaWNhdGlvbl9ncmlkJ10uZ3JpZC5zZXRHcmlkV2lkdGgoIDQwMCApO1xuXHRcdHRoaXMuc2V0R3JpZEhlaWdodCggJ3ZlcmlmaWNhdGlvbl9ncmlkJyApO1xuXG5cdFx0dGhpcy5zZXRQdW5jaE5vdGVHcmlkV2lkdGgoIHRoaXMuZ3JpZF9kaWNbJ3B1bmNoX25vdGVfZ3JpZCddLmdyaWQgKTtcblx0XHR0aGlzLnNldEdyaWRIZWlnaHQoICdwdW5jaF9ub3RlX2dyaWQnICk7IC8vY2FuJ3Qgc2V0IGhlaWdodCBvbiB0aGlzIGdyaWQuIHVudGlsIHdlIGZpeCB3aGF0J3Mgd3Jvbmcgd2l0aCBpdC5cblxuXHRcdGxldCBzY3JvbGxfaGVpZ2h0ID0gZG9jdW1lbnQuYm9keS5zY3JvbGxIZWlnaHQ7XG5cblx0XHRsZXQgaGVpZ2h0ID0gc2Nyb2xsX2hlaWdodDtcblxuXHRcdGxldCB0aW1lc2hlZXRfZ3JpZCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoICdkaXYudGltZXNoZWV0LWdyaWQtZGl2JyApO1xuXHRcdGlmICggdGltZXNoZWV0X2dyaWQgKSB7IC8vSXNzdWUgIzMwNjAgLSBKYXZhU2NyaXB0IGV4Y2VwdGlvbnMgb2YgdHJ5aW5nIHRvIHJlYWQgZ2V0Qm91bmRpbmdDbGllbnRSZWN0IG9mIG51bGwgZWxlbWVudHMuXG5cdFx0XHRoZWlnaHQgLT0gdGltZXNoZWV0X2dyaWQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wO1xuXHRcdH1cblx0XHRsZXQgY29udGV4dF9ib3JkZXIgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCAnZGl2LmNvbnRleHQtYm9yZGVyJyApO1xuXHRcdGlmICggY29udGV4dF9ib3JkZXIgKSB7IC8vSXNzdWUgIzMwNjAgLSBKYXZhU2NyaXB0IGV4Y2VwdGlvbnMgb2YgdHJ5aW5nIHRvIHJlYWQgZ2V0Qm91bmRpbmdDbGllbnRSZWN0IG9mIG51bGwgZWxlbWVudHMuXG5cdFx0XHRoZWlnaHQgLT0gKCBzY3JvbGxfaGVpZ2h0IC0gZG9jdW1lbnQucXVlcnlTZWxlY3RvciggJ2Rpdi5jb250ZXh0LWJvcmRlcicgKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5ib3R0b20gKTtcblx0XHR9XG5cdFx0aGVpZ2h0IC09IDEwOyAvL01hbnVhbCBmaW5lIHR1bmluZyB0byBmaXQgYmV0dGVyLlxuXG5cdFx0dGhpcy5ncmlkX2Rpdi5oZWlnaHQoIGhlaWdodCApO1xuXHRcdHRoaXMuZ3JpZC5zZXRHcmlkV2lkdGgoIHRoaXMuZ2V0VGltZVNoZWV0V2lkdGgoKSApO1xuXG5cdFx0dGhpcy5zZXRQYXlQZXJpb2RIZWFkZXJTaXplKCk7XG5cblx0XHRpZiAoIHRoaXMuZ2V0UHVuY2hNb2RlKCkgPT09ICdtYW51YWwnICkge1xuXHRcdFx0JHRoaXMuc2V0TWFudWFsVGltZVNoZWV0R3JpZFNpemUoKTtcblx0XHR9XG5cblx0XHQvL0JlY2F1c2UgYSBzY3JvbGxiYXIgaGFzIGFwcGVhcmVkIGluIHRoZSBtaWRkbGUgb2YgcmVzaXppbmcgdGhlIHRvcCBncmlkcyBjb21wYXJlZCB0byB0aGUgYm90dG9tIGdyaWQsIHRoZSBwYWdlIG1heSBoYXZlIGV4cGFuZGVkIHRvIHNob3cgdGhlIHNjcm9sbGJhciBhbmQgd2UgbWF5IG5lZWQgdG8gcmVzaXplIHRoZSBncmlkcyAod2lkdGgpIGFnYWluIHRvIHRha2UgaW50byBhY2NvdW50LlxuXHRcdC8vVGhpcyBpcyBtYW5pZmVzdGVkIGl0c2VsZiBpbiBtaXNhbGlnbmVkIGNvbHVtbnMgYmV0d2VlbiB0aGUgdHdvIGdyaWRzLlxuXHRcdGlmICggR2xvYmFsLmlzVmVydGljYWxTY3JvbGxCYXJSZXF1aXJlZCggJCgnLnRpbWVzaGVldC1ncmlkLWRpdicpWzBdICkgKSB7XG5cdFx0XHRmb3IgKCB2YXIga2V5IGluIHRoaXMuZ3JpZF9kaWMgKSB7XG5cdFx0XHRcdGlmICgga2V5ICE9ICdwdW5jaF9ub3RlX2dyaWQnICYmIGtleSAhPSAnYWNjdW11bGF0ZWRfdG90YWxfZ3JpZCcgJiYga2V5ICE9ICd2ZXJpZmljYXRpb25fZ3JpZCcgKSB7XG5cdFx0XHRcdFx0aWYgKCAhdGhpcy5ncmlkX2RpY1trZXldLmdyaWQgKSB7XG5cdFx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0dmFyIGdyaWQgPSB0aGlzLmdyaWRfZGljW2tleV0uZ3JpZDtcblx0XHRcdFx0XHRncmlkLnNldEdyaWRXaWR0aCggdGhpcy5nZXRUaW1lU2hlZXRXaWR0aCgpICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRzZXRQdW5jaE5vdGVHcmlkV2lkdGgoIGdyaWQgKSB7XG5cdFx0aWYgKCAhZ3JpZCApIHtcblx0XHRcdGlmICggIXRoaXMucHVuY2hfbm90ZV9ncmlkIHx8ICF0aGlzLnB1bmNoX25vdGVfZ3JpZC5ncmlkICkge1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cdFx0XHRncmlkID0gdGhpcy5wdW5jaF9ub3RlX2dyaWQuZ3JpZDtcblx0XHR9XG5cblx0XHR2YXIgZ3JpZF93aWR0aCA9IGdyaWQud2lkdGgoKTtcblxuXHRcdHZhciBhY2N1bXVsYXRlZF9ncmlkX3dpZHRoID0gKCB0aGlzLmFjY3VtdWxhdGVkX3RvdGFsX2dyaWQgJiYgdGhpcy5hY2N1bXVsYXRlZF90b3RhbF9ncmlkLmdyaWQgKSA/IHRoaXMuYWNjdW11bGF0ZWRfdG90YWxfZ3JpZC5nZXRXaWR0aCgpIDogMDtcblx0XHR2YXIgdmVyaWZpY2F0aW9uX2dyaWRfd2lkdGggPSAoIHRoaXMudmVyaWZpY2F0aW9uX2dyaWQgJiYgdGhpcy52ZXJpZmljYXRpb25fZ3JpZC5ncmlkICkgPyB0aGlzLnZlcmlmaWNhdGlvbl9ncmlkLmdldFdpZHRoKCkgOiAwO1xuXG5cdFx0aWYgKCB0aGlzLnZlcmlmaWNhdGlvbl9ncmlkX3NvdXJjZS5sZW5ndGggIT09IDAgKSB7XG5cdFx0XHRncmlkX3dpZHRoID0gTWF0aC5mbG9vciggdGhpcy5nZXRUaW1lU2hlZXRXaWR0aCgpIC0gKCBhY2N1bXVsYXRlZF9ncmlkX3dpZHRoICsgdmVyaWZpY2F0aW9uX2dyaWRfd2lkdGggKyA3ICkgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Z3JpZF93aWR0aCA9IE1hdGguZmxvb3IoIHRoaXMuZ2V0VGltZVNoZWV0V2lkdGgoKSAtICggNyArIGFjY3VtdWxhdGVkX2dyaWRfd2lkdGggKSApO1xuXHRcdH1cblx0XHRncmlkX3dpZHRoID0gTWF0aC5hYnMoIGdyaWRfd2lkdGggKTtcblxuXHRcdGlmICggZ3JpZF93aWR0aCAhPSBncmlkLndpZHRoKCkgKSB7XG5cdFx0XHQvL0RlYnVnLlRleHQoXCJTZXR0aW5nIHB1bmNoIG5vdGUgZ3JpZCB3aWR0aCB0byBcIiArIGdyaWRfd2lkdGgsICdUaW1lc2hlZXRWaWV3Q29ucm9sbGVyLmpzJywgJ1RpbWVzaGVldFZpZXdDb25yb2xsZXInLCAnc2V0R3JpZEhlaWdodCcsIDEwKTtcblx0XHRcdGdyaWQuc2V0R3JpZFdpZHRoKCBncmlkX3dpZHRoICk7XG5cdFx0XHQkKCAndGQubm90ZXNfZ3JpZF90ZF9jb250YWluZXInICkuY3NzKCAnd2lkdGgnLCAnMTAwJScgKTtcblx0XHR9XG5cdH1cblxuXHRzZXRNYW51YWxUaW1lU2hlZXRHcmlkU2l6ZSgpIHtcblx0XHR2YXIgdHIgPSAkKCB0aGlzLmFjY3VtdWxhdGVkX3RpbWVfZ3JpZC5ncmlkLmZpbmQoICd0cjpmaXJzdC1jaGlsZCcgKVswXSApO1xuXHRcdHZhciBtYW51YWxfZ3JpZF90ciA9ICQoIHRoaXMuZWRpdG9yLmZpbmQoICd0YWJsZScgKS5maW5kKCAndHI6Zmlyc3QtY2hpbGQnIClbMF0gKTtcblx0XHR2YXIgaW5kZXggPSAwO1xuXHRcdGZvciAoIHZhciBpID0gMCwgbSA9IG1hbnVhbF9ncmlkX3RyLmNoaWxkcmVuKCkubGVuZ3RoOyBpIDwgbTsgaSsrICkge1xuXHRcdFx0dmFyIHRkID0gJCggbWFudWFsX2dyaWRfdHIuY2hpbGRyZW4oKVtpXSApO1xuXHRcdFx0aWYgKCAhdGQuaXMoICc6dmlzaWJsZScgKSApIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cdFx0XHQkKCB0ZCApLmNzcyggJ3dpZHRoJywgJCggdHIuY2hpbGRyZW4oKVtpbmRleF0gKS5jc3MoICd3aWR0aCcgKSApO1xuXHRcdFx0aW5kZXgrKztcblx0XHR9XG5cblx0XHR0aGlzLmVkaXRvci53aWR0aCggdGhpcy5hY2N1bXVsYXRlZF90aW1lX2dyaWQuZ2V0R3JpZFdpZHRoKCkgKTtcblx0fVxuXG5cdG9uQ2VsbEZvcm1hdCggY2VsbF92YWx1ZSwgcmVsYXRlZF9kYXRhLCByb3cgKSB7XG5cdFx0dmFyIGNvbF9tb2RlbCA9IHJlbGF0ZWRfZGF0YS5jb2xNb2RlbDtcblx0XHR2YXIgcm93X2lkID0gcmVsYXRlZF9kYXRhLnJvd2lkO1xuXHRcdHZhciBjb250ZW50X2RpdiA9ICQoICc8ZGl2IGNsYXNzPVxcJ3B1bmNoLWNvbnRlbnQtZGl2XFwnPjwvZGl2PicgKTtcblx0XHR2YXIgcHVuY2hfaW5mbztcblx0XHR2YXIgZXhfc3Bhbjtcblx0XHR2YXIgaTtcblx0XHR2YXIgdGltZV9zcGFuX3ByZWZpeDtcblx0XHR2YXIgdGltZV9zcGFuO1xuXHRcdHZhciB0aW1lX3NwYW5fc3VmZml4O1xuXHRcdHZhciBwdW5jaDtcblx0XHR2YXIgYnJlYWtfc3Bhbjtcblx0XHR2YXIgcmVsYXRlZF9wdW5jaDtcblx0XHR2YXIgZXhjZXB0aW9uO1xuXHRcdHZhciBsZW47XG5cdFx0dmFyIHRleHQ7XG5cdFx0dmFyIGV4O1xuXHRcdHZhciBkYXRhO1xuXHRcdHZhciBjdXJyZW5jeSA9IExvY2FsQ2FjaGVEYXRhLmdldEN1cnJlbnRDdXJyZW5jeVN5bWJvbCgpO1xuXG5cdFx0Y2VsbF92YWx1ZSA9IEdsb2JhbC5kZWNvZGVDZWxsVmFsdWUoIGNlbGxfdmFsdWUgKTtcblx0XHRpZiAoIHJlbGF0ZWRfZGF0YS5wb3MgPT09IDAgKSB7XG5cdFx0XHRpZiAoIHJvdy50eXBlID09PSBUaW1lU2hlZXRWaWV3Q29udHJvbGxlci5UT1RBTF9ST1cgKSB7XG5cdFx0XHRcdHB1bmNoX2luZm8gPSAkKCAnPHNwYW4gY2xhc3M9XFwndG90YWxcXCcgc3R5bGU9XFwnZm9udC1zaXplOiAxMXB4XFwnPjwvc3Bhbj4nICk7XG5cdFx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCBjZWxsX3ZhbHVlICkgKSB7XG5cdFx0XHRcdFx0cHVuY2hfaW5mby50ZXh0KCBjZWxsX3ZhbHVlICk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0cHVuY2hfaW5mby50ZXh0KCAnJyApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmV0dXJuIHB1bmNoX2luZm8uZ2V0KCAwICkub3V0ZXJIVE1MO1xuXHRcdFx0fSBlbHNlIGlmICggcm93LnR5cGUgPT09IFRpbWVTaGVldFZpZXdDb250cm9sbGVyLlJFR1VMQVJfUk9XICkge1xuXHRcdFx0XHRwdW5jaF9pbmZvID0gJCggJzxzcGFuIGNsYXNzPVxcJ3RvcC1saW5lLXNwYW5cXCcgc3R5bGU9XFwnZm9udC1zaXplOiAxMXB4XFwnPjwvc3Bhbj4nICk7XG5cdFx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCBjZWxsX3ZhbHVlICkgKSB7XG5cdFx0XHRcdFx0cHVuY2hfaW5mby50ZXh0KCBjZWxsX3ZhbHVlICk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0cHVuY2hfaW5mby50ZXh0KCAnJyApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBwdW5jaF9pbmZvLmdldCggMCApLm91dGVySFRNTDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGNlbGxfdmFsdWU7XG5cdFx0fVxuXG5cdFx0aWYgKCByb3cudHlwZSA9PT0gVGltZVNoZWV0Vmlld0NvbnRyb2xsZXIuUFVOQ0hfUk9XICkge1xuXHRcdFx0cHVuY2ggPSByb3dbY29sX21vZGVsLm5hbWUgKyAnX2RhdGEnXTtcblx0XHRcdHJlbGF0ZWRfcHVuY2ggPSByb3dbY29sX21vZGVsLm5hbWUgKyAnX3JlbGF0ZWRfZGF0YSddO1xuXHRcdFx0dGltZV9zcGFuX3ByZWZpeCA9ICQoICc8c3BhbiBjbGFzcz1cXCdwdW5jaC1wcmVmaXhcXCc+PC9zcGFuPicgKTtcblx0XHRcdHRpbWVfc3BhbiA9ICQoICc8c3BhbiBjbGFzcz1cXCdwdW5jaC10aW1lXFwnPjwvc3Bhbj4nICk7XG5cdFx0XHR0aW1lX3NwYW5fc3VmZml4ID0gJCggJzxzcGFuIGNsYXNzPVxcJ3B1bmNoLXN1ZmZpeFxcJz48L3NwYW4+JyApO1xuXHRcdFx0YnJlYWtfc3BhbiA9ICQoICc8c3BhbiBjbGFzcz1cXCdwdW5jaC1icmVha1xcJz48L3NwYW4+JyApO1xuXG5cdFx0XHRpZiAoIHB1bmNoICkge1xuXHRcdFx0XHRleGNlcHRpb24gPSBwdW5jaC5leGNlcHRpb247XG5cblx0XHRcdFx0dmFyIGJyZWFrX2xhYmVsID0gJyc7XG5cdFx0XHRcdHZhciBicmVha19sYWJlbF90aXRsZSA9ICcnO1xuXHRcdFx0XHRpZiAoIHB1bmNoLnR5cGVfaWQgPT0gMjAgKSB7XG5cdFx0XHRcdFx0YnJlYWtfbGFiZWwgPSAnTCc7XG5cdFx0XHRcdFx0YnJlYWtfbGFiZWxfdGl0bGUgPSAkLmkxOG4uXygnTHVuY2gnKTtcblx0XHRcdFx0fSBlbHNlIGlmICggcHVuY2gudHlwZV9pZCA9PSAzMCApIHtcblx0XHRcdFx0XHRicmVha19sYWJlbCA9ICdCJztcblx0XHRcdFx0XHRicmVha19sYWJlbF90aXRsZSA9ICQuaTE4bi5fKCdCcmVhaycpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dmFyIGxhYmVsX3ByZWZpeCA9ICcnO1xuXHRcdFx0XHR2YXIgbGFiZWxfcHJlZml4X3RpdGxlID0gJyc7XG5cdFx0XHRcdGlmICggcHVuY2gubm90ZSAhPSAnJyApIHtcblx0XHRcdFx0XHRsYWJlbF9wcmVmaXggPSAnKic7XG5cdFx0XHRcdFx0bGFiZWxfcHJlZml4X3RpdGxlID0gJC5pMThuLl8oJ05vdGUnKSArJzogJysgcHVuY2gubm90ZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHZhciBsYWJlbF9zdWZmaXggPSAnJztcblx0XHRcdFx0dmFyIGxhYmVsX3N1ZmZpeF90aXRsZSA9ICcnO1xuXHRcdFx0XHRpZiAoIHB1bmNoLmlkID09IFRUVVVJRC5ub3RfZXhpc3RfaWQgKSB7XG5cdFx0XHRcdFx0bGFiZWxfc3VmZml4ID0gJ1AnO1xuXHRcdFx0XHRcdGxhYmVsX3N1ZmZpeF90aXRsZSA9ICdQPScrICQuaTE4bi5fKCdQcm9jZXNzaW5nJyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCBwdW5jaC5sYXRpdHVkZSAmJiBwdW5jaC5sYXRpdHVkZSAhPSAwICYmIHB1bmNoLmxvbmdpdHVkZSAmJiBwdW5jaC5sb25naXR1ZGUgIT0gMCApIHtcblx0XHRcdFx0XHRsYWJlbF9zdWZmaXggPSAnRyc7XG5cdFx0XHRcdFx0bGFiZWxfc3VmZml4X3RpdGxlID0gJ0c9JysgJC5pMThuLl8oJ0dQUyBMb2NhdGlvbicpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCBwdW5jaC5oYXNfaW1hZ2UgKSB7XG5cdFx0XHRcdFx0bGFiZWxfc3VmZml4ID0gbGFiZWxfc3VmZml4ICsgJ0YnO1xuXHRcdFx0XHRcdGxhYmVsX3N1ZmZpeF90aXRsZSA9IGxhYmVsX3N1ZmZpeF90aXRsZSArICcgRj0nKyAkLmkxOG4uXygnUHVuY2ggSW1hZ2UnKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggcHVuY2gudGFpbnRlZCApIHtcblx0XHRcdFx0XHR0aW1lX3NwYW4uY3NzKCAnY29sb3InLCAnI2ZmMDAwMCcgKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmICggcmVsYXRlZF9wdW5jaCApIHtcblx0XHRcdFx0ZXhjZXB0aW9uID0gcmVsYXRlZF9wdW5jaC5leGNlcHRpb247XG5cdFx0XHR9XG5cblx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCBsYWJlbF9wcmVmaXggKSAmJiBsYWJlbF9wcmVmaXggIT0gJycgKSB7XG5cdFx0XHRcdHRpbWVfc3Bhbl9wcmVmaXgudGV4dCggbGFiZWxfcHJlZml4ICk7XG5cdFx0XHRcdHRpbWVfc3Bhbl9wcmVmaXguYXR0ciggJ3RpdGxlJywgbGFiZWxfcHJlZml4X3RpdGxlICk7XG5cdFx0XHRcdGNvbnRlbnRfZGl2LmFwcGVuZCggdGltZV9zcGFuX3ByZWZpeCApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggY2VsbF92YWx1ZSApICkge1xuXHRcdFx0XHR0aW1lX3NwYW4udGV4dCggY2VsbF92YWx1ZSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGltZV9zcGFuLnRleHQoICcnICk7XG5cdFx0XHR9XG5cdFx0XHRjb250ZW50X2Rpdi5hcHBlbmQoIHRpbWVfc3BhbiApO1xuXG5cdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggbGFiZWxfc3VmZml4ICkgJiYgbGFiZWxfc3VmZml4ICE9ICcnICApIHtcblx0XHRcdFx0dGltZV9zcGFuX3N1ZmZpeC50ZXh0KCBsYWJlbF9zdWZmaXggKTtcblx0XHRcdFx0dGltZV9zcGFuX3N1ZmZpeC5hdHRyKCAndGl0bGUnLCBsYWJlbF9zdWZmaXhfdGl0bGUgKTtcblx0XHRcdFx0Y29udGVudF9kaXYuYXBwZW5kKCB0aW1lX3NwYW5fc3VmZml4ICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCBicmVha19sYWJlbCApICYmIGJyZWFrX2xhYmVsICE9ICcnICkge1xuXHRcdFx0XHRicmVha19zcGFuLnRleHQoIGJyZWFrX2xhYmVsICk7XG5cdFx0XHRcdGJyZWFrX3NwYW4uYXR0ciggJ3RpdGxlJywgYnJlYWtfbGFiZWxfdGl0bGUgKTtcblx0XHRcdFx0Y29udGVudF9kaXYuYXBwZW5kKCBicmVha19zcGFuICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggZXhjZXB0aW9uICkge1xuXHRcdFx0XHRsZW4gPSBleGNlcHRpb24ubGVuZ3RoO1xuXHRcdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdFx0XHRleCA9IGV4Y2VwdGlvbltpXTtcblx0XHRcdFx0XHRleF9zcGFuID0gJCggJzxzcGFuIGNsYXNzPVxcJ3B1bmNoLWV4Y2VwdGlvbnNcXCc+PC9zcGFuPicgKTtcblx0XHRcdFx0XHRleF9zcGFuLmNzcyggJ2NvbG9yJywgZXguZXhjZXB0aW9uX2NvbG9yICk7XG5cdFx0XHRcdFx0ZXhfc3Bhbi50ZXh0KCBleC5leGNlcHRpb25fcG9saWN5X3R5cGVfaWQgKTtcblx0XHRcdFx0XHRleF9zcGFuLmF0dHIoICd0aXRsZScsIGV4LmV4Y2VwdGlvbl9wb2xpY3lfdHlwZV9pZCArICc6ICcgKyBleC5leGNlcHRpb25fcG9saWN5X3R5cGUgKTtcblx0XHRcdFx0XHRjb250ZW50X2Rpdi5wcmVwZW5kKCBleF9zcGFuICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8vIGV4X3NwYW4gPSAkKCAnPHNwYW4gY2xhc3M9XFwncHVuY2gtZXhjZXB0aW9uc1xcJz48L3NwYW4+JyApO1xuXHRcdFx0XHQvLyBleF9zcGFuLnRleHQoICcgJyApO1xuXHRcdFx0XHQvLyBjb250ZW50X2Rpdi5wcmVwZW5kKCBleF9zcGFuICk7XG5cdFx0XHR9XG5cblx0XHR9IGVsc2UgaWYgKCByb3cudHlwZSA9PT0gVGltZVNoZWV0Vmlld0NvbnRyb2xsZXIuRVhDRVBUSU9OX1JPVyApIHtcblx0XHRcdGV4Y2VwdGlvbiA9IHJvd1tjb2xfbW9kZWwubmFtZSArICdfZXhjZXB0aW9ucyddO1xuXG5cdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggZXhjZXB0aW9uICkgKSB7XG5cdFx0XHRcdGxlbiA9IGV4Y2VwdGlvbi5sZW5ndGg7XG5cdFx0XHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0XHRcdGV4ID0gZXhjZXB0aW9uW2ldO1xuXHRcdFx0XHRcdGV4X3NwYW4gPSAkKCAnPHNwYW4gY2xhc3M9XFwncHVuY2gtZXhjZXB0aW9ucy1jZW50ZXJcXCc+PC9zcGFuPicgKTtcblx0XHRcdFx0XHRleF9zcGFuLmNzcyggJ2NvbG9yJywgZXguZXhjZXB0aW9uX2NvbG9yICk7XG5cdFx0XHRcdFx0ZXhfc3Bhbi50ZXh0KCBleC5leGNlcHRpb25fcG9saWN5X3R5cGVfaWQgKTtcblx0XHRcdFx0XHRleF9zcGFuLmF0dHIoICd0aXRsZScsIGV4LmV4Y2VwdGlvbl9wb2xpY3lfdHlwZV9pZCArICc6ICcgKyBleC5leGNlcHRpb25fcG9saWN5X3R5cGUgKTtcblxuXHRcdFx0XHRcdGNvbnRlbnRfZGl2LmFwcGVuZCggZXhfc3BhbiApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHR9IGVsc2UgaWYgKCByb3cudHlwZSA9PT0gVGltZVNoZWV0Vmlld0NvbnRyb2xsZXIuUkVRVUVTVF9ST1cgKSB7XG5cdFx0XHR0aW1lX3NwYW4gPSAkKCAnPHNwYW4gY2xhc3M9XFwncmVxdWVzdFxcJz48L3NwYW4+JyApO1xuXHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoIGNlbGxfdmFsdWUgKSApIHtcblx0XHRcdFx0dGltZV9zcGFuLnRleHQoIGNlbGxfdmFsdWUgKTtcblx0XHRcdFx0dGltZV9zcGFuLmF0dHIoICd0aXRsZScsIGNyZWF0ZVJlcXVlc3RUb29sVGlwKCByb3dbY29sX21vZGVsLm5hbWUgKyAnX3JlcXVlc3QnXSApICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aW1lX3NwYW4udGV4dCggJycgKTtcblx0XHRcdH1cblx0XHRcdGNvbnRlbnRfZGl2LnByZXBlbmQoIHRpbWVfc3BhbiApO1xuXG5cdFx0fSBlbHNlIGlmICggcm93LnR5cGUgPT09IFRpbWVTaGVldFZpZXdDb250cm9sbGVyLlRPVEFMX1JPVyApIHtcblxuXHRcdFx0ZGF0YSA9IHJvd1tjb2xfbW9kZWwubmFtZSArICdfZGF0YSddO1xuXHRcdFx0dGltZV9zcGFuID0gJCggJzxzcGFuIGNsYXNzPVxcJ3RvdGFsXFwnPjwvc3Bhbj4nICk7XG5cblx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCBjZWxsX3ZhbHVlICkgKSB7XG5cblx0XHRcdFx0aWYgKCBkYXRhICkge1xuXG5cdFx0XHRcdFx0aWYgKCBkYXRhLmhhc093blByb3BlcnR5KCAnbm90ZScgKSAmJiBkYXRhLm5vdGUgKSB7XG5cdFx0XHRcdFx0XHRjZWxsX3ZhbHVlID0gJyonICsgY2VsbF92YWx1ZTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoIHRpbWVfc2hlZXRfdmlld19jb250cm9sbGVyLndhZ2VfYnRuICYmIHRpbWVfc2hlZXRfdmlld19jb250cm9sbGVyLndhZ2VfYnRuLmdldFZhbHVlKCB0cnVlICkgJiYgZGF0YS5oYXNPd25Qcm9wZXJ0eSggJ3RvdGFsX3RpbWVfYW1vdW50JyApICYmIGRhdGEudG90YWxfdGltZV9hbW91bnQgJiYgZGF0YS5oYXNPd25Qcm9wZXJ0eSggJ2hvdXJseV9yYXRlJyApICYmIGRhdGEuaG91cmx5X3JhdGUgKSB7XG5cdFx0XHRcdFx0XHR0aW1lX3NwYW4gPSAkKCAnPGRpdiBjbGFzcz1cXCd0b3RhbC0tYm9sZCB0aW1lLXNoZWV0LXZpZXctd2FnZS1jb250YWluZXJcXCc+PC9kaXY+JyApO1xuXHRcdFx0XHRcdFx0Y2VsbF92YWx1ZSA9ICc8c3BhbiBjbGFzcz1cInRpbWUtc2hlZXQtdmlldy13YWdlLWhvdXItcmF0ZVwiPicgKyBjdXJyZW5jeSArIEdsb2JhbC5Nb25leVJvdW5kKCBkYXRhLmhvdXJseV9yYXRlICkgKyAnL2hyIEA8L3NwYW4+JyArXG5cdFx0XHRcdFx0XHRcdCc8c3BhbiBjbGFzcz1cInRpbWUtc2hlZXQtdmlldy13YWdlLXZhbHVlXCI+JyArIGNlbGxfdmFsdWUgK1xuXHRcdFx0XHRcdFx0XHQnPC9zcGFuID48c3BhbiBjbGFzcz1cInRpbWUtc2hlZXQtdmlldy13YWdlLWFtb3VudFwiID49ICcgKyBjdXJyZW5jeSArIEdsb2JhbC5Nb25leVJvdW5kKCBkYXRhLnRvdGFsX3RpbWVfYW1vdW50ICkgK1xuXHRcdFx0XHRcdFx0XHQnPC9zcGFuPic7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKCB0aW1lX3NoZWV0X3ZpZXdfY29udHJvbGxlci5nZXRQdW5jaE1vZGUoKSA9PT0gJ3B1bmNoJyApIHtcblx0XHRcdFx0XHRcdGlmICggZGF0YS5oYXNPd25Qcm9wZXJ0eSggJ292ZXJyaWRlJyApICYmIGRhdGEub3ZlcnJpZGUgPT09IHRydWUgKSB7XG5cdFx0XHRcdFx0XHRcdHRpbWVfc3Bhbi5hZGRDbGFzcyggJ2Fic2VuY2Utb3ZlcnJpZGUnICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGlmICggIWRhdGEub3ZlcnJpZGUgJiYgcm93LmtleSA9PT0gJ3dvcmtlZF90aW1lJyApIHtcblx0XHRcdFx0XHRcdFx0dGltZV9zcGFuLmFkZENsYXNzKCAnYWJzZW5jZS1vdmVycmlkZScgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR0aW1lX3NwYW4uaHRtbCggY2VsbF92YWx1ZSApO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aW1lX3NwYW4udGV4dCggJycgKTtcblx0XHRcdH1cblx0XHRcdGNvbnRlbnRfZGl2LnByZXBlbmQoIHRpbWVfc3BhbiApO1xuXG5cdFx0fSBlbHNlIGlmICggcm93LnR5cGUgPT09IFRpbWVTaGVldFZpZXdDb250cm9sbGVyLlJFR1VMQVJfUk9XICkge1xuXG5cdFx0XHRjb250ZW50X2Rpdi5hZGRDbGFzcyggJ3RvcC1saW5lJyApO1xuXG5cdFx0XHRkYXRhID0gcm93W2NvbF9tb2RlbC5uYW1lICsgJ19kYXRhJ107XG5cblx0XHRcdHRpbWVfc3BhbiA9ICQoICc8c3Bhbj48L3NwYW4+JyApO1xuXHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoIGNlbGxfdmFsdWUgKSApIHtcblxuXHRcdFx0XHRpZiAoIGRhdGEgKSB7XG5cblx0XHRcdFx0XHRpZiAoIGRhdGEuaGFzT3duUHJvcGVydHkoICdub3RlJyApICYmIGRhdGEubm90ZSApIHtcblx0XHRcdFx0XHRcdGNlbGxfdmFsdWUgPSAnKicgKyBjZWxsX3ZhbHVlO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICggdGltZV9zaGVldF92aWV3X2NvbnRyb2xsZXIud2FnZV9idG4gJiYgdGltZV9zaGVldF92aWV3X2NvbnRyb2xsZXIud2FnZV9idG4uZ2V0VmFsdWUoIHRydWUgKSAmJiBkYXRhLmhhc093blByb3BlcnR5KCAndG90YWxfdGltZV9hbW91bnQnICkgJiYgZGF0YS50b3RhbF90aW1lX2Ftb3VudCAmJiBkYXRhLmhhc093blByb3BlcnR5KCAnaG91cmx5X3JhdGUnICkgJiYgZGF0YS5ob3VybHlfcmF0ZSApIHtcblx0XHRcdFx0XHRcdHRpbWVfc3BhbiA9ICQoICc8ZGl2IGNsYXNzPVxcJ3RpbWUtc2hlZXQtdmlldy13YWdlLWNvbnRhaW5lclxcJz48L2Rpdj4nICk7XG5cdFx0XHRcdFx0XHRjZWxsX3ZhbHVlID0gJzxzcGFuIGNsYXNzPVwidGltZS1zaGVldC12aWV3LXdhZ2UtaG91ci1yYXRlXCI+JyArIGN1cnJlbmN5ICsgR2xvYmFsLk1vbmV5Um91bmQoIGRhdGEuaG91cmx5X3JhdGUgKSArICcvaHIgQDwvc3Bhbj4nICtcblx0XHRcdFx0XHRcdFx0JzxzcGFuIGNsYXNzPVwidGltZS1zaGVldC12aWV3LXdhZ2UtdmFsdWVcIj4nICsgY2VsbF92YWx1ZSArXG5cdFx0XHRcdFx0XHRcdCc8L3NwYW4gPjxzcGFuIGNsYXNzPVwidGltZS1zaGVldC12aWV3LXdhZ2UtYW1vdW50XCIgPj0gJyArIGN1cnJlbmN5ICsgR2xvYmFsLk1vbmV5Um91bmQoIGRhdGEudG90YWxfdGltZV9hbW91bnQgKSArXG5cdFx0XHRcdFx0XHRcdCc8L3NwYW4+Jztcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoIGRhdGEuaGFzT3duUHJvcGVydHkoICdvdmVycmlkZScgKSAmJiBkYXRhLm92ZXJyaWRlID09PSB0cnVlICkge1xuXHRcdFx0XHRcdFx0dGltZV9zcGFuLmFkZENsYXNzKCAnYWJzZW5jZS1vdmVycmlkZScgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR0aW1lX3NwYW4uaHRtbCggY2VsbF92YWx1ZSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGltZV9zcGFuLnRleHQoICcnICk7XG5cdFx0XHR9XG5cdFx0XHRjb250ZW50X2Rpdi5wcmVwZW5kKCB0aW1lX3NwYW4gKTtcblxuXHRcdH0gZWxzZSBpZiAoIHJvdy50eXBlID09PSBUaW1lU2hlZXRWaWV3Q29udHJvbGxlci5BQlNFTkNFX1JPVyApIHtcblxuXHRcdFx0dmFyIGFic2VuY2UgPSByb3dbY29sX21vZGVsLm5hbWUgKyAnX2RhdGEnXTtcblx0XHRcdHRpbWVfc3BhbiA9ICQoICc8c3Bhbj48L3NwYW4+JyApO1xuXG5cdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggY2VsbF92YWx1ZSApICkge1xuXG5cdFx0XHRcdGlmICggYWJzZW5jZSApIHtcblxuXHRcdFx0XHRcdGlmICggYWJzZW5jZS5vdmVycmlkZSA9PT0gdHJ1ZSApIHtcblx0XHRcdFx0XHRcdHRpbWVfc3Bhbi5hZGRDbGFzcyggJ2Fic2VuY2Utb3ZlcnJpZGUnICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKCBhYnNlbmNlLm5vdGUgKSB7XG5cdFx0XHRcdFx0XHRjZWxsX3ZhbHVlID0gJyonICsgY2VsbF92YWx1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR0aW1lX3NwYW4udGV4dCggY2VsbF92YWx1ZSApO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aW1lX3NwYW4udGV4dCggJycgKTtcblx0XHRcdH1cblx0XHRcdGNvbnRlbnRfZGl2LnByZXBlbmQoIHRpbWVfc3BhbiApO1xuXG5cdFx0fSBlbHNlIGlmICggcm93LnR5cGUgPT09IFRpbWVTaGVldFZpZXdDb250cm9sbGVyLkFDQ1VNVUxBVEVEX1RJTUVfUk9XIHx8XG5cdFx0XHRyb3cudHlwZSA9PT0gVGltZVNoZWV0Vmlld0NvbnRyb2xsZXIuUFJFTUlVTV9ST1cgKSB7XG5cdFx0XHRkYXRhID0gcm93W2NvbF9tb2RlbC5uYW1lICsgJ19kYXRhJ107XG5cdFx0XHR0aW1lX3NwYW4gPSAkKCAnPHNwYW4gIHN0eWxlPVxcJ3dpZHRoOiAxMDAlXFwnPjwvc3Bhbj4nICk7XG5cblx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCBjZWxsX3ZhbHVlICkgKSB7XG5cblx0XHRcdFx0aWYgKCBkYXRhICkge1xuXG5cdFx0XHRcdFx0aWYgKCBkYXRhLmhhc093blByb3BlcnR5KCAnbm90ZScgKSAmJiBkYXRhLm5vdGUgKSB7XG5cdFx0XHRcdFx0XHRjZWxsX3ZhbHVlID0gJyonICsgY2VsbF92YWx1ZTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoIHRpbWVfc2hlZXRfdmlld19jb250cm9sbGVyLndhZ2VfYnRuICYmIHRpbWVfc2hlZXRfdmlld19jb250cm9sbGVyLndhZ2VfYnRuLmdldFZhbHVlKCB0cnVlICkgJiYgZGF0YS5oYXNPd25Qcm9wZXJ0eSggJ3RvdGFsX3RpbWVfYW1vdW50JyApICYmIGRhdGEudG90YWxfdGltZV9hbW91bnQgJiYgZGF0YS5oYXNPd25Qcm9wZXJ0eSggJ2hvdXJseV9yYXRlJyApICYmIGRhdGEuaG91cmx5X3JhdGUgKSB7XG5cdFx0XHRcdFx0XHR0aW1lX3NwYW4gPSAkKCAnPGRpdiBjbGFzcz1cXCd0aW1lLXNoZWV0LXZpZXctd2FnZS1jb250YWluZXJcXCc+PC9kaXY+JyApO1xuXHRcdFx0XHRcdFx0Y2VsbF92YWx1ZSA9ICc8c3BhbiBjbGFzcz1cInRpbWUtc2hlZXQtdmlldy13YWdlLWhvdXItcmF0ZVwiPicgKyBjdXJyZW5jeSArIEdsb2JhbC5Nb25leVJvdW5kKCBkYXRhLmhvdXJseV9yYXRlICkgKyAnL2hyIEA8L3NwYW4+JyArXG5cdFx0XHRcdFx0XHRcdCc8c3BhbiBjbGFzcz1cInRpbWUtc2hlZXQtdmlldy13YWdlLXZhbHVlXCI+JyArIGNlbGxfdmFsdWUgK1xuXHRcdFx0XHRcdFx0XHQnPC9zcGFuID48c3BhbiBjbGFzcz1cInRpbWUtc2hlZXQtdmlldy13YWdlLWFtb3VudFwiID49ICcgKyBjdXJyZW5jeSArIEdsb2JhbC5Nb25leVJvdW5kKCBkYXRhLnRvdGFsX3RpbWVfYW1vdW50ICkgK1xuXHRcdFx0XHRcdFx0XHQnPC9zcGFuPic7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmICggZGF0YS5oYXNPd25Qcm9wZXJ0eSggJ292ZXJyaWRlJyApICYmIGRhdGEub3ZlcnJpZGUgPT09IHRydWUgKSB7XG5cdFx0XHRcdFx0XHR0aW1lX3NwYW4uYWRkQ2xhc3MoICdhYnNlbmNlLW92ZXJyaWRlJyApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRpbWVfc3Bhbi5odG1sKCBjZWxsX3ZhbHVlICk7XG5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRpbWVfc3Bhbi50ZXh0KCAnJyApO1xuXHRcdFx0fVxuXHRcdFx0Y29udGVudF9kaXYucHJlcGVuZCggdGltZV9zcGFuICk7XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0dGltZV9zcGFuID0gJCggJzxzcGFuIGNsYXNzPVxcJ3B1bmNoLXRpbWVcXCc+PC9zcGFuPicgKTtcblx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCBjZWxsX3ZhbHVlICkgKSB7XG5cdFx0XHRcdHRpbWVfc3Bhbi50ZXh0KCBjZWxsX3ZhbHVlICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aW1lX3NwYW4udGV4dCggJycgKTtcblx0XHRcdH1cblx0XHRcdGNvbnRlbnRfZGl2LnByZXBlbmQoIHRpbWVfc3BhbiApO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGNyZWF0ZVJlcXVlc3RUb29sVGlwKCB2YWx1ZSApIHtcblx0XHRcdHZhciBsYWJlbDtcblx0XHRcdGlmICggR2xvYmFsLmlzQXJyYXkoIHZhbHVlICkgKSB7XG5cdFx0XHRcdGxhYmVsID0gY2FsREFuZEEoIHZhbHVlICk7XG5cdFx0XHR9IGVsc2UgaWYgKCBHbG9iYWwuaXNPYmplY3QoIHZhbHVlICkgJiYgdmFsdWUuc3RhdHVzICkge1xuXHRcdFx0XHRsYWJlbCA9IHZhbHVlLnN0YXR1czsgLy9Vc2UgdGhlIGxhYmVsIGRpcmVjdGx5IGZyb20gdGhlIEFQSS5cblx0XHRcdH1cblxuXHRcdFx0ZnVuY3Rpb24gY2FsREFuZEEoIGFycmF5ICkge1xuXHRcdFx0XHR2YXIgbGVuID0gYXJyYXkubGVuZ3RoO1xuXHRcdFx0XHR2YXIgYSA9IDA7XG5cdFx0XHRcdHZhciBkID0gMDtcblx0XHRcdFx0dmFyIHAgPSAwO1xuXHRcdFx0XHR2YXIgbGFiZWwgPSAnJztcblx0XHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRcdFx0dmFyIGl0ZW0gPSBhcnJheVtpXTtcblx0XHRcdFx0XHRpZiAoIGl0ZW0uc3RhdHVzX2lkID09IDUwICkge1xuXHRcdFx0XHRcdFx0YSA9IGEgKyAxO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoIGl0ZW0uc3RhdHVzX2lkID09IDU1ICkge1xuXHRcdFx0XHRcdFx0ZCA9IGQgKyAxO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoIGl0ZW0uc3RhdHVzX2lkID09IDMwICkge1xuXHRcdFx0XHRcdFx0cCA9IHAgKyAxO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoIGEgPiAwICkge1xuXHRcdFx0XHRcdGxhYmVsICs9ICcgJyArICQuaTE4bi5fKCAnQXV0aG9yaXplZCcgKSArICc6ICcgKyBhO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICggcCA+IDAgKSB7XG5cdFx0XHRcdFx0bGFiZWwgKz0gJyAnICsgJC5pMThuLl8oICdQZW5kaW5nJyApICsgJzogJyArIHA7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCBkID4gMCApIHtcblx0XHRcdFx0XHRsYWJlbCArPSAnICcgKyAkLmkxOG4uXyggJ0RlY2xpbmVkJyApICsgJzogJyArIGQ7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIGxhYmVsO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gbGFiZWw7XG5cdFx0fVxuXG5cdFx0Y29udGVudF9kaXYuYWRkQ2xhc3MoICdkYXRlLWNvbHVtbicgKTtcblxuXHRcdHJldHVybiBjb250ZW50X2Rpdi5nZXQoIDAgKS5vdXRlckhUTUw7XG5cdH1cblxuXHRvblNlbGVjdFJvdyggZ3JpZF9pZCwgcm93X2lkLCB0YXJnZXQgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgcm93X3RyID0gJCggdGFyZ2V0ICkuZmluZCggJ3RyIycgKyByb3dfaWQgKTtcblx0XHQkdGhpcy50aW1lc2hlZXRfZ3JpZC5ncmlkLmZpbmQoICd0ZC51aS1zdGF0ZS1oaWdobGlnaHQnICkucmVtb3ZlQ2xhc3MoICd1aS1zdGF0ZS1oaWdobGlnaHQnICk7XG5cdFx0dmFyIGNlbGxzX2FycmF5ID0gW107XG5cdFx0dmFyIGxlbiA9IDA7XG5cdFx0aWYgKCBncmlkX2lkID09PSAndGltZXNoZWV0X2dyaWQnICkge1xuXHRcdFx0Y2VsbHNfYXJyYXkgPSAkdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXk7XG5cdFx0XHRsZW4gPSAkdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXkubGVuZ3RoO1xuXHRcdFx0JHRoaXMuYWJzZW5jZV9zZWxlY3RfY2VsbHNfQXJyYXkgPSBbXTtcblx0XHR9IGVsc2UgaWYgKCBncmlkX2lkID09PSAnYWJzZW5jZV9ncmlkJyApIHtcblx0XHRcdGNlbGxzX2FycmF5ID0gJHRoaXMuYWJzZW5jZV9zZWxlY3RfY2VsbHNfQXJyYXk7XG5cdFx0XHRsZW4gPSAkdGhpcy5hYnNlbmNlX3NlbGVjdF9jZWxsc19BcnJheS5sZW5ndGg7XG5cdFx0XHQkdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXkgPSBbXTtcblx0XHR9IGVsc2UgaWYgKCBncmlkX2lkID09PSAnYWNjdW11bGF0ZWRfZ3JpZCcgKSB7XG5cdFx0XHRjZWxsc19hcnJheSA9ICR0aGlzLmFjY3VtdWxhdGVkX3RpbWVfY2VsbHNfYXJyYXk7XG5cdFx0XHRsZW4gPSAkdGhpcy5hY2N1bXVsYXRlZF90aW1lX2NlbGxzX2FycmF5Lmxlbmd0aDtcblx0XHR9IGVsc2UgaWYgKCBncmlkX2lkID09PSAncHJlbWl1bV9ncmlkJyApIHtcblx0XHRcdGNlbGxzX2FycmF5ID0gJHRoaXMucHJlbWl1bV9jZWxsc19hcnJheTtcblx0XHRcdGxlbiA9ICR0aGlzLnByZW1pdW1fY2VsbHNfYXJyYXkubGVuZ3RoO1xuXHRcdH1cblx0XHR0aGlzLnNlbGVjdF9wdW5jaGVzX2FycmF5ID0gW107XG5cdFx0LyoganNoaW50IGlnbm9yZTpzdGFydCAqL1xuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0dmFyIGluZm8gPSBjZWxsc19hcnJheVtpXTtcblx0XHRcdHJvd190ciA9ICQoIHRhcmdldCApLmZpbmQoICcjJyArIGluZm8ucm93X2lkICk7XG5cdFx0XHR2YXIgY2VsbF90ZCA9ICQoIHJvd190ci5maW5kKCAndGQnIClbaW5mby5jZWxsX2luZGV4XSApO1xuXHRcdFx0Y2VsbF90ZC5hZGRDbGFzcyggJ3VpLXN0YXRlLWhpZ2hsaWdodCcgKS5hdHRyKCAnYXJpYS1zZWxlY3RlZCcsIHRydWUgKTtcblxuXHRcdFx0aWYgKCBpbmZvLnB1bmNoICYmIGluZm8ucHVuY2guaWQgKSB7XG5cblx0XHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoIGluZm8ucHVuY2gudGltZV9zdGFtcCApICkgeyAvL2RhdGUgKyB0aW1lIG51bWJlclxuXHRcdFx0XHRcdHZhciBkYXRlID0gR2xvYmFsLnN0clRvRGF0ZSggaW5mby5wdW5jaC5wdW5jaF9kYXRlICkuZm9ybWF0KCAnTU0tREQtWVlZWScgKTtcblx0XHRcdFx0XHR2YXIgZGF0ZV90aW1lID0gZGF0ZSArICcgJyArIGluZm8ucHVuY2gucHVuY2hfdGltZTtcblx0XHRcdFx0XHRpbmZvLnB1bmNoLnRpbWVfc3RhbXBfbnVtID0gR2xvYmFsLnN0clRvRGF0ZVRpbWUoIGRhdGVfdGltZSApLmdldFRpbWUoKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRpbmZvLnB1bmNoLnRpbWVfc3RhbXBfbnVtID0gaW5mby50aW1lX3N0YW1wX251bTsgLy9VZXIgdGltZV9zdGFtcF9udW0gZnJvbSBjZWxsIHNlbGVjdCBzZXR0aW5nLCBhIGRhdGUgbnVtYmVyXG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5zZWxlY3RfcHVuY2hlc19hcnJheS5wdXNoKCBpbmZvLnB1bmNoICk7XG5cdFx0XHRcdHRoaXMuc2VsZWN0X3B1bmNoZXNfYXJyYXkuc29ydCggZnVuY3Rpb24oIGEsIGIgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIEdsb2JhbC5jb21wYXJlKCBhLCBiLCAndGltZV9zdGFtcF9udW0nICk7XG5cdFx0XHRcdH0gKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0LyoganNoaW50IGlnbm9yZTplbmQgKi9cblx0fVxuXG5cdHVuc2V0U2VsZWN0ZWRDZWxscyggZ3JpZF9pZCApIHtcblx0XHRpZiAoIGdyaWRfaWQgPT0gJ2FjY3VtdWxhdGVkX2dyaWQnICkge1xuXHRcdFx0Z3JpZF9pZCA9ICdhY2N1bXVsYXRlZF90aW1lX2dyaWQnO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5sYXN0X2NsaWNrZWRfZ3JpZF9pZCAmJiBncmlkX2lkICE9IHRoaXMubGFzdF9jbGlja2VkX2dyaWRfaWQgKSB7XG5cdFx0XHQvL1VzZSB3aW5kb3cgc2V0VGltZW91dCB0byBtYWtlIHRoaXMgY29kZSBhc3luY2Nocm9ub3VzIGZvciBzcGVlZCwgaXQncyB0aGUgZmFzdGVzdCB3YXkuXG5cdFx0XHQvL3dlYiB3b3JrZXIgOiA4NTBtc1xuXHRcdFx0Ly9pbmxpbmUgY29kZSA6IDcwMG1zXG5cdFx0XHQvL3NldFRpbWVvdXQ6IDQwMG1zXG5cdFx0XHR3aW5kb3cuc2V0VGltZW91dCggZnVuY3Rpb24oIHQsIG4gKSB7XG5cdFx0XHRcdHQuZ3JpZF9kaWNbbl0uZ3JpZC50cmlnZ2VyKCAncmVsb2FkR3JpZCcgKTtcblx0XHRcdH0sIDAsIHRoaXMsIHRoaXMubGFzdF9jbGlja2VkX2dyaWRfaWQgKTtcblx0XHR9XG5cblx0XHQvL3RoaXMuc2V0RGVmYXVsdE1lbnUoKTtcblx0XHR0aGlzLmxhc3RfY2xpY2tlZF9ncmlkX2lkID0gZ3JpZF9pZDtcblx0fVxuXG5cdGdldFJvd0RhdGEoIGdyaWRfaWQsIHJvd19pZCApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXG5cdFx0dmFyIHJvd19kYXRhID0gbnVsbDtcblxuXHRcdGlmICggZ3JpZF9pZCA9PT0gJ2Fic2VuY2VfZ3JpZCcgKSB7XG5cdFx0XHRyb3dfZGF0YSA9ICR0aGlzLmFic2VuY2VfZ3JpZC5nZXRHcmlkUGFyYW0oICdkYXRhJyApO1xuXHRcdH0gZWxzZSBpZiAoIGdyaWRfaWQgPT09ICdhY2N1bXVsYXRlZF9ncmlkJyApIHtcblx0XHRcdHJvd19kYXRhID0gJHRoaXMuYWNjdW11bGF0ZWRfdGltZV9ncmlkLmdldEdyaWRQYXJhbSggJ2RhdGEnICk7XG5cdFx0fSBlbHNlIGlmICggZ3JpZF9pZCA9PT0gJ3ByZW1pdW1fZ3JpZCcgKSB7XG5cdFx0XHRyb3dfZGF0YSA9ICR0aGlzLnByZW1pdW1fZ3JpZC5nZXRHcmlkUGFyYW0oICdkYXRhJyApO1xuXHRcdH0gZWxzZSB7IC8vU2hvdWxkIGJlOiB0aW1lc2hlZXRfZ3JpZFxuXHRcdFx0cm93X2RhdGEgPSAkdGhpcy5ncmlkLmdldEdyaWRQYXJhbSggJ2RhdGEnICk7XG5cdFx0fVxuXG5cdFx0dmFyIHJvdyA9IGZhbHNlO1xuXG5cdFx0Zm9yICggdmFyIGkgaW4gcm93X2RhdGEgKSB7XG5cdFx0XHRpZiAoIHJvd19kYXRhW2ldLmlkID09IHJvd19pZCApIHtcblx0XHRcdFx0cm93ID0gcm93X2RhdGFbaV07XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiByb3c7XG5cdH1cblxuXHRvbkNlbGxTZWxlY3QoIGdyaWRfaWQsIHJvd19pZCwgY2VsbF9pbmRleCwgY2VsbF92YWwsIHRhcmdldCwgZSApIHtcblx0XHQkKCAnI3JpYmJvbl92aWV3X2NvbnRhaW5lciAuY29udGV4dC1tZW51OnZpc2libGUgYScgKS5jbGljaygpO1xuXG5cdFx0aWYgKCBjZWxsX2luZGV4IDwgMCApIHtcblx0XHRcdHRoaXMudW5zZXRTZWxlY3RlZENlbGxzKCBncmlkX2lkICk7XG5cdFx0XHR0aGlzLnNldERlZmF1bHRNZW51KCk7XG5cdFx0XHRyZXR1cm4gdHJ1ZTsgLy9jb250aW51ZSBkZWZhdWx0IHByb2Nlc3NpbmcuXG5cdFx0fVxuXG5cdFx0Y2VsbF9pbmRleCA9IHBhcnNlSW50KCBjZWxsX2luZGV4ICk7XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciByb3c7XG5cdFx0dmFyIGNvbE1vZGVsO1xuXHRcdHZhciBkYXRhX2ZpZWxkO1xuXHRcdHZhciBwdW5jaDtcblx0XHR2YXIgcmVsYXRlZF9wdW5jaDtcblx0XHR2YXIgY2VsbHNfYXJyYXkgPSBbXTtcblx0XHR2YXIgZGF0ZTtcblxuXHRcdGlmICggIXRoaXMuaXNfZWRpdCAmJiAhdGhpcy5pc19hZGQgKSB7XG5cdFx0XHQkdGhpcy5hYnNlbmNlX21vZGVsID0gZmFsc2U7XG5cdFx0fVxuXG5cdFx0cm93ID0gJHRoaXMuZ2V0Um93RGF0YSggZ3JpZF9pZCwgcm93X2lkICk7XG5cblx0XHRpZiAoIGdyaWRfaWQgPT09ICd0aW1lc2hlZXRfZ3JpZCcgKSB7XG5cdFx0XHRjZWxsc19hcnJheSA9ICR0aGlzLnNlbGVjdF9jZWxsc19BcnJheTtcblxuXHRcdFx0Y29sTW9kZWwgPSAkdGhpcy5ncmlkLmdldEdyaWRQYXJhbSggJ2NvbE1vZGVsJyApO1xuXHRcdFx0ZGF0YV9maWVsZCA9IGNvbE1vZGVsW2NlbGxfaW5kZXhdLm5hbWU7XG5cblx0XHRcdGlmICggcm93LnR5cGUgPT09IFRpbWVTaGVldFZpZXdDb250cm9sbGVyLlJFUVVFU1RfUk9XICkge1xuXHRcdFx0XHR2YXIgZmlsdGVyID0geyBmaWx0ZXJfZGF0YToge30gfTtcblx0XHRcdFx0ZmlsdGVyLmZpbHRlcl9kYXRhLnVzZXJfaWQgPSB0aGlzLmdldFNlbGVjdEVtcGxveWVlKCk7XG5cdFx0XHRcdGZpbHRlci5maWx0ZXJfZGF0YS5zdGFydF9kYXRlID0gJHRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YS50aW1lc2hlZXRfZGF0ZXMuc3RhcnRfZGlzcGxheV9kYXRlO1xuXHRcdFx0XHRmaWx0ZXIuZmlsdGVyX2RhdGEuZW5kX2RhdGUgPSAkdGhpcy5mdWxsX3RpbWVzaGVldF9kYXRhLnRpbWVzaGVldF9kYXRlcy5lbmRfZGlzcGxheV9kYXRlO1xuXHRcdFx0XHRmaWx0ZXIuZmlsdGVyX2RhdGEuaWQgPSBbXTtcblxuXHRcdFx0XHQkdGhpcy51bnNldFNlbGVjdGVkQ2VsbHMoIGdyaWRfaWQgKTtcblx0XHRcdFx0dmFyIHBlbmRpbmdfcmVxdWVzdHMgPSAwO1xuXHRcdFx0XHR2YXIgdG90YWxfcmVxdWVzdHMgPSAwO1xuXHRcdFx0XHRpZiAoIEdsb2JhbC5pc0FycmF5KCByb3dbZGF0YV9maWVsZCArICdfcmVxdWVzdCddICkgKSB7XG5cdFx0XHRcdFx0Zm9yICggdmFyIG4gaW4gcm93W2RhdGFfZmllbGQgKyAnX3JlcXVlc3QnXSApIHtcblx0XHRcdFx0XHRcdHZhciBvYmogPSByb3dbZGF0YV9maWVsZCArICdfcmVxdWVzdCddW25dO1xuXHRcdFx0XHRcdFx0ZmlsdGVyLmZpbHRlcl9kYXRhLmlkLnB1c2goIG9iai5pZCApO1xuXHRcdFx0XHRcdFx0aWYgKCBvYmouc3RhdHVzID09ICQuaTE4bi5fKCAnUEVORElORycgKSApIHtcblx0XHRcdFx0XHRcdFx0cGVuZGluZ19yZXF1ZXN0cyArPSAxO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0dG90YWxfcmVxdWVzdHMgKz0gMTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gZWxzZSBpZiAoIHJvd1tkYXRhX2ZpZWxkICsgJ19yZXF1ZXN0J10gKSB7XG5cdFx0XHRcdFx0Ly9pcyBvYmplY3Q7XG5cdFx0XHRcdFx0ZmlsdGVyLmZpbHRlcl9kYXRhLmlkLnB1c2goIHJvd1tkYXRhX2ZpZWxkICsgJ19yZXF1ZXN0J10uaWQgKTtcblx0XHRcdFx0XHRpZiAoIHJvd1tkYXRhX2ZpZWxkICsgJ19yZXF1ZXN0J10uc3RhdHVzID09ICQuaTE4bi5fKCAnUEVORElORycgKSApIHtcblx0XHRcdFx0XHRcdHBlbmRpbmdfcmVxdWVzdHMgPSAxO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHR0b3RhbF9yZXF1ZXN0cyA9IDE7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0R2xvYmFsLmFkZFZpZXdUYWIoIHRoaXMudmlld0lkLCAkLmkxOG4uXyggJ1RpbWVTaGVldCcgKSwgd2luZG93LmxvY2F0aW9uLmhyZWYgKTtcblxuXHRcdFx0XHRpZiAoIHRvdGFsX3JlcXVlc3RzID4gMCApIHtcblx0XHRcdFx0XHRpZiAoIHRoaXMuZ2V0U2VsZWN0RW1wbG95ZWUoKSAhPSBMb2NhbENhY2hlRGF0YS5nZXRMb2dpblVzZXIoKS5pZCAmJiBwZW5kaW5nX3JlcXVlc3RzID4gMCApIHtcblx0XHRcdFx0XHRcdC8vSGFuZGxlIGNhc2VzIHdoZXJlIGFuIGFkbWluaXN0cmF0b3Igd2hvIGNhbiBzZWUgYWxsIHJlcXVlc3RzIG1pZ2h0IGNsaWNrIG9uIGEgcGVuZGluZyByZXF1ZXN0IGNlbGwgYW5kIHdhbnQgdG8gYmUgdGFrZW4gdG8gTXlBY2NvdW50IC0+IFJlcXVlc3RzXG5cdFx0XHRcdFx0XHQvL3JhdGhlciB0aGFuIE15QWNjb3VudCAtPiBSZXF1ZXN0IEF1dGhvcml6YXRpb24sIHdoaWNoIHdvdWxkbid0IHNob3cgYW55dGhpbmcuXG5cdFx0XHRcdFx0XHRpZiAoIHRoaXMub3duZXJPckNoaWxkUGVybWlzc2lvblZhbGlkYXRlKCAncmVxdWVzdCcsICd2aWV3X2NoaWxkJywgZmlsdGVyLmZpbHRlcl9kYXRhLmlkICkgKSB7XG5cdFx0XHRcdFx0XHRcdEluZGV4Vmlld0NvbnRyb2xsZXIuZ29Ub1ZpZXcoICdSZXF1ZXN0QXV0aG9yaXphdGlvbicsIGZpbHRlciApO1xuXHRcdFx0XHRcdFx0fSBlbHNlIGlmICggdGhpcy52aWV3UGVybWlzc2lvblZhbGlkYXRlKCAncmVxdWVzdCcsIGZpbHRlci5maWx0ZXJfZGF0YS5pZCApICkge1xuXHRcdFx0XHRcdFx0XHRJbmRleFZpZXdDb250cm9sbGVyLmdvVG9WaWV3KCAnUmVxdWVzdCcsIGZpbHRlciApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHQvL0lmIHRoZSByZXF1ZXN0IGlzbid0IHBlbmRpbmcsIHRoZW4gZ28gdG8gTXlBY2NvdW50IC0+IFJlcXVlc3RzLCBhbmQgTXlBY2NvdW50IC0+IFJlcXVlc3QgQXV0aG9yaXphdGlvbiB3b3VsZG4ndCBzaG93IGFueXRoaW5nLlxuXHRcdFx0XHRcdFx0aWYgKCB0aGlzLnZpZXdQZXJtaXNzaW9uVmFsaWRhdGUoICdyZXF1ZXN0JywgZmlsdGVyLmZpbHRlcl9kYXRhLmlkICkgKSB7XG5cdFx0XHRcdFx0XHRcdEluZGV4Vmlld0NvbnRyb2xsZXIuZ29Ub1ZpZXcoICdSZXF1ZXN0JywgZmlsdGVyICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCByb3cgJiYgcm93W2RhdGFfZmllbGQgKyAnX2RhdGEnXSApIHtcblx0XHRcdFx0cHVuY2ggPSByb3dbZGF0YV9maWVsZCArICdfZGF0YSddO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cHVuY2ggPSBudWxsO1xuXHRcdFx0fVxuXG5cdFx0XHRyZWxhdGVkX3B1bmNoID0gcm93W2RhdGFfZmllbGQgKyAnX3JlbGF0ZWRfZGF0YSddO1xuXG5cdFx0XHRkYXRlID0gR2xvYmFsLnN0clRvRGF0ZSggZGF0YV9maWVsZCwgdGhpcy5mdWxsX2Zvcm1hdCApO1xuXHRcdH0gZWxzZSBpZiAoIGdyaWRfaWQgPT09ICdhYnNlbmNlX2dyaWQnICkge1xuXHRcdFx0Y2VsbHNfYXJyYXkgPSAkdGhpcy5hYnNlbmNlX3NlbGVjdF9jZWxsc19BcnJheTtcblxuXHRcdFx0Y29sTW9kZWwgPSAkdGhpcy5hYnNlbmNlX2dyaWQuZ2V0R3JpZFBhcmFtKCAnY29sTW9kZWwnICk7XG5cblx0XHRcdGRhdGFfZmllbGQgPSBjb2xNb2RlbFtjZWxsX2luZGV4XS5uYW1lO1xuXG5cdFx0XHQvLyBFcnJvcjogVW5jYXVnaHQgVHlwZUVycm9yOiBDYW5ub3QgcmVhZCBwcm9wZXJ0eSAncHVuY2hfaW5mb19kYXRhJyBvZiB1bmRlZmluZWQgaW4gaW50ZXJmYWNlL2h0bWw1LyMhbT1UaW1lU2hlZXQmZGF0ZT0yMDE1MTIyMCZ1c2VyX2lkPW51bGwmc2hvd193YWdlPTAgbGluZSAzNzYxXG5cdFx0XHRpZiAoIHJvdyApIHtcblx0XHRcdFx0cHVuY2ggPSByb3dbZGF0YV9maWVsZCArICdfZGF0YSddO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cHVuY2ggPSBudWxsO1xuXHRcdFx0fVxuXG5cdFx0XHRkYXRlID0gR2xvYmFsLnN0clRvRGF0ZSggZGF0YV9maWVsZCwgdGhpcy5mdWxsX2Zvcm1hdCApO1xuXG5cdFx0XHQkdGhpcy5hYnNlbmNlX21vZGVsID0gdHJ1ZTtcblx0XHR9IGVsc2UgaWYgKCBncmlkX2lkID09PSAnYWNjdW11bGF0ZWRfZ3JpZCcgKSB7XG5cblx0XHRcdGNlbGxzX2FycmF5ID0gJHRoaXMuYWNjdW11bGF0ZWRfdGltZV9jZWxsc19hcnJheTtcblxuXHRcdFx0Y29sTW9kZWwgPSAkdGhpcy5hY2N1bXVsYXRlZF90aW1lX2dyaWQuZ2V0R3JpZFBhcmFtKCAnY29sTW9kZWwnICk7XG5cblx0XHRcdGRhdGFfZmllbGQgPSBjb2xNb2RlbFtjZWxsX2luZGV4XS5uYW1lO1xuXG5cdFx0XHRpZiAoIHJvdyApIHtcblx0XHRcdFx0cHVuY2ggPSByb3dbZGF0YV9maWVsZCArICdfZGF0YSddO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cHVuY2ggPSBudWxsO1xuXHRcdFx0fVxuXG5cdFx0XHRkYXRlID0gR2xvYmFsLnN0clRvRGF0ZSggZGF0YV9maWVsZCwgdGhpcy5mdWxsX2Zvcm1hdCApO1xuXHRcdH0gZWxzZSBpZiAoIGdyaWRfaWQgPT09ICdwcmVtaXVtX2dyaWQnICkge1xuXG5cdFx0XHRjZWxsc19hcnJheSA9ICR0aGlzLnByZW1pdW1fY2VsbHNfYXJyYXk7XG5cblx0XHRcdGNvbE1vZGVsID0gJHRoaXMucHJlbWl1bV9ncmlkLmdldEdyaWRQYXJhbSggJ2NvbE1vZGVsJyApO1xuXG5cdFx0XHRkYXRhX2ZpZWxkID0gY29sTW9kZWxbY2VsbF9pbmRleF0ubmFtZTtcblxuXHRcdFx0aWYgKCByb3cgKSB7XG5cdFx0XHRcdHB1bmNoID0gcm93W2RhdGFfZmllbGQgKyAnX2RhdGEnXTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHB1bmNoID0gbnVsbDtcblx0XHRcdH1cblxuXHRcdFx0ZGF0ZSA9IEdsb2JhbC5zdHJUb0RhdGUoIGRhdGFfZmllbGQsIHRoaXMuZnVsbF9mb3JtYXQgKTtcblxuXHRcdH1cblxuXHRcdGlmICggR2xvYmFsLmlzVmFsaWREYXRlKCBkYXRlICkgPT0gZmFsc2UgKSB7XG5cdFx0XHQkdGhpcy51bnNldFNlbGVjdGVkQ2VsbHMoIGdyaWRfaWQgKTtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHR2YXIgaW5mbztcblx0XHR2YXIgcm93X3RyO1xuXHRcdHZhciBjZWxsX3RkO1xuXHRcdC8vQ2xlYW4gYWxsIHNlbGVjdCBjZWxscyBmaXJzdFxuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGNlbGxzX2FycmF5Lmxlbmd0aDsgaSsrICkge1xuXHRcdFx0aW5mbyA9IGNlbGxzX2FycmF5W2ldO1xuXHRcdFx0cm93X3RyID0gJCggdGFyZ2V0ICkuZmluZCggJyMnICsgaW5mby5yb3dfaWQgKTtcblx0XHRcdCQoIHRhcmdldCApLmZpbmQoICd0cicgKS5yZW1vdmVDbGFzcyggJ3VpLXN0YXRlLWhpZ2hsaWdodCcgKTtcblx0XHRcdGNlbGxfdGQgPSAkKCByb3dfdHIuZmluZCggJ3RkJyApW2luZm8uY2VsbF9pbmRleF0gKTtcblx0XHRcdGNlbGxfdGQucmVtb3ZlQ2xhc3MoICd1aS1zdGF0ZS1oaWdobGlnaHQnICkuYXR0ciggJ2FyaWEtc2VsZWN0ZWQnLCBmYWxzZSApO1xuXHRcdH1cblxuXHRcdHZhciBkYXRlX3N0cjtcblx0XHR2YXIgdGltZV9zdGFtcF9udW07XG5cblx0XHQvLyBBZGQgbXVsdGlwbGUgc2VsZWN0aWVuZF9kaXNwbGF5X2RhdGUgaWYgY2xpY2sgY2VsbCBhbmQgaG9sZCBjdHJsIG9yIGNvbW1hbmRcblx0XHRpZiAoIGUuY3RybEtleSB8fCBlLm1ldGFLZXkgKSB7XG5cdFx0XHR2YXIgZm91bmQgPSBmYWxzZTtcblx0XHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGNlbGxzX2FycmF5Lmxlbmd0aDsgaSsrICkge1xuXHRcdFx0XHRpbmZvID0gY2VsbHNfYXJyYXlbaV07XG5cdFx0XHRcdGlmICggcm93X2lkID09IGluZm8ucm93X2lkICYmIGNlbGxfaW5kZXggPT0gaW5mby5jZWxsX2luZGV4ICkge1xuXHRcdFx0XHRcdGNlbGxzX2FycmF5LnNwbGljZSggaSwgMSApO1xuXHRcdFx0XHRcdGZvdW5kID0gdHJ1ZTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRkYXRlX3N0ciA9IGRhdGUuZm9ybWF0KCk7XG5cdFx0XHR0aW1lX3N0YW1wX251bSA9IGRhdGUuZ2V0VGltZSgpO1xuXG5cdFx0XHRpZiAoICFmb3VuZCApIHtcblx0XHRcdFx0aWYgKCBncmlkX2lkID09PSAndGltZXNoZWV0X2dyaWQnICkge1xuXHRcdFx0XHRcdHB1bmNoID0gZ2V0Q2VsbFB1bmNoKCByb3dfaWQsIGNlbGxfaW5kZXggKTtcblx0XHRcdFx0XHRyZWxhdGVkX3B1bmNoID0gZ2V0UmVsYXRlZFB1bmNoKCByb3dfaWQsIGNlbGxfaW5kZXggKTtcblx0XHRcdFx0XHRjZWxsc19hcnJheS5wdXNoKCB7XG5cdFx0XHRcdFx0XHRyb3dfaWQ6IHJvd19pZCxcblx0XHRcdFx0XHRcdGNlbGxfaW5kZXg6IGNlbGxfaW5kZXgsXG5cdFx0XHRcdFx0XHRjZWxsX3ZhbDogY2VsbF92YWwsXG5cdFx0XHRcdFx0XHRwdW5jaDogcHVuY2gsXG5cdFx0XHRcdFx0XHRyZWxhdGVkX3B1bmNoOiByZWxhdGVkX3B1bmNoLFxuXHRcdFx0XHRcdFx0ZGF0ZTogZGF0ZV9zdHIsXG5cdFx0XHRcdFx0XHR0aW1lX3N0YW1wX251bTogdGltZV9zdGFtcF9udW1cblx0XHRcdFx0XHR9ICk7XG5cblx0XHRcdFx0XHQkdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXkgPSBjZWxsc19hcnJheTtcblx0XHRcdFx0XHQkdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXkuc29ydCggR2xvYmFsLm1fc29ydF9ieSggWyd0aW1lX3N0YW1wX251bScsICdyb3dfaWQnXSApICk7XG5cdFx0XHRcdH0gZWxzZSBpZiAoIGdyaWRfaWQgPT09ICdhYnNlbmNlX2dyaWQnICkge1xuXHRcdFx0XHRcdGNlbGxzX2FycmF5LnB1c2goIHtcblx0XHRcdFx0XHRcdHJvd19pZDogcm93X2lkLFxuXHRcdFx0XHRcdFx0Y2VsbF9pbmRleDogY2VsbF9pbmRleCxcblx0XHRcdFx0XHRcdGNlbGxfdmFsOiBjZWxsX3ZhbCxcblx0XHRcdFx0XHRcdHB1bmNoOiBwdW5jaCxcblx0XHRcdFx0XHRcdGRhdGU6IGRhdGVfc3RyLFxuXHRcdFx0XHRcdFx0dGltZV9zdGFtcF9udW06IHRpbWVfc3RhbXBfbnVtLFxuXHRcdFx0XHRcdFx0c3JjX29iamVjdF9pZDogKCByb3cucHVuY2hfaW5mb19pZCApID8gcm93LnB1bmNoX2luZm9faWQgOiBudWxsLFxuXHRcdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRcdCR0aGlzLmFic2VuY2Vfc2VsZWN0X2NlbGxzX0FycmF5ID0gY2VsbHNfYXJyYXk7XG5cdFx0XHRcdFx0JHRoaXMuYWJzZW5jZV9zZWxlY3RfY2VsbHNfQXJyYXkuc29ydCggR2xvYmFsLm1fc29ydF9ieSggWyd0aW1lX3N0YW1wX251bScsICdyb3dfaWQnXSApICk7XG5cdFx0XHRcdH0gZWxzZSBpZiAoIGdyaWRfaWQgPT09ICdwcmVtaXVtX2dyaWQnICkge1xuXHRcdFx0XHRcdGNlbGxzX2FycmF5ID0gW1xuXHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRyb3dfaWQ6IHJvd19pZCxcblx0XHRcdFx0XHRcdFx0Y2VsbF9pbmRleDogY2VsbF9pbmRleCxcblx0XHRcdFx0XHRcdFx0Y2VsbF92YWw6IGNlbGxfdmFsLFxuXHRcdFx0XHRcdFx0XHRkYXRlOiBkYXRlX3N0cixcblx0XHRcdFx0XHRcdFx0dGltZV9zdGFtcF9udW06IHRpbWVfc3RhbXBfbnVtXG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XTtcblxuXHRcdFx0XHRcdCR0aGlzLnByZW1pdW1fY2VsbHNfYXJyYXkgPSBjZWxsc19hcnJheTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0gZWxzZSBpZiAoIGUuc2hpZnRLZXkgJiYgY2VsbHNfYXJyYXkubGVuZ3RoID4gMCApIHtcblx0XHRcdHZhciBzdGF0dXNfaWQgPSBjZWxsc19hcnJheVswXS5zdGF0dXNfaWQ7IC8vR2V0IHN0YXR1c19pZCBvZiBmaXJzdCBwdW5jaCBzbyB3ZSBjYW4gZGVmYXVsdHMgdG8gdGhhdCBvbiBuZXcuXG5cblx0XHRcdC8vY2VsbC5yb3dfaWQgaXMgbnVtZXJpYyBoZXJlLlxuXHRcdFx0dmFyIHN0YXJ0X3Jvd19pbmRleCA9IHBhcnNlSW50KCBjZWxsc19hcnJheVswXS5yb3dfaWQgKTtcblx0XHRcdHZhciBzdGFydF9jZWxsX2luZGV4ID0gcGFyc2VJbnQoIGNlbGxzX2FycmF5WzBdLmNlbGxfaW5kZXggKTtcblxuXHRcdFx0dmFyIGVuZF9yb3dfaW5kZXggPSByb3dfaWQ7XG5cdFx0XHR2YXIgZW5kX2NlbGxfaW5kZXggPSBjZWxsX2luZGV4O1xuXG5cdFx0XHRpZiAoIHN0YXJ0X3Jvd19pbmRleCA+IGVuZF9yb3dfaW5kZXggKSB7XG5cdFx0XHRcdHZhciB0bXBfcm93X2luZGV4ID0gc3RhcnRfcm93X2luZGV4O1xuXHRcdFx0XHRzdGFydF9yb3dfaW5kZXggPSBlbmRfcm93X2luZGV4O1xuXHRcdFx0XHRlbmRfcm93X2luZGV4ID0gdG1wX3Jvd19pbmRleDtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBzdGFydF9jZWxsX2luZGV4ID4gZW5kX2NlbGxfaW5kZXggKSB7XG5cdFx0XHRcdHZhciB0bXBfY2VsbF9pbmRleCA9IHN0YXJ0X2NlbGxfaW5kZXg7XG5cdFx0XHRcdHN0YXJ0X2NlbGxfaW5kZXggPSBlbmRfY2VsbF9pbmRleDtcblx0XHRcdFx0ZW5kX2NlbGxfaW5kZXggPSB0bXBfY2VsbF9pbmRleDtcblx0XHRcdH1cblxuXHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgY2VsbHNfYXJyYXkubGVuZ3RoOyBpKysgKSB7XG5cdFx0XHRcdGluZm8gPSBjZWxsc19hcnJheVtpXTtcblxuXHRcdFx0XHR2YXIgdG1wX3Jvd19pZCA9IHBhcnNlSW50KCBpbmZvLnJvd19pZCApO1xuXG5cdFx0XHRcdGlmICggdG1wX3Jvd19pZCA8IHN0YXJ0X3Jvd19pbmRleCApIHtcblx0XHRcdFx0XHRzdGFydF9yb3dfaW5kZXggPSB0bXBfcm93X2lkO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICggdG1wX3Jvd19pZCA+IGVuZF9yb3dfaW5kZXggKSB7XG5cdFx0XHRcdFx0ZW5kX3Jvd19pbmRleCA9IHRtcF9yb3dfaWQ7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIGluZm8uY2VsbF9pbmRleCA8IHN0YXJ0X2NlbGxfaW5kZXggKSB7XG5cdFx0XHRcdFx0c3RhcnRfY2VsbF9pbmRleCA9IGluZm8uY2VsbF9pbmRleDtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoIGluZm8uY2VsbF9pbmRleCA+IGVuZF9jZWxsX2luZGV4ICkge1xuXHRcdFx0XHRcdGVuZF9jZWxsX2luZGV4ID0gaW5mby5jZWxsX2luZGV4O1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vSWYgdGhlIGNsaWNrIGlzIGluc2lkZSB0aGUgZXhpc3Rpbmcgc2VsZWN0aW9uLCB0cnVuY2F0ZSB0aGUgZXhpc3Rpbmcgc2VsZWN0aW9uIHRvIHRoZSBjbGljay5cblx0XHRcdC8vQ2hlY2sgaW4gU2NoZWR1bGVWaWV3Q29udHJvbGxlci5qcyBmb3IgcmVsYXRlZCBjaGFuZ2Vcblx0XHRcdC8vTWFrZSBzdXJlIHRvIGNoZWNrIGZvciBjZWxsc19hcnJheSBhbmQgY2VsbHNfYXJyYXkubGVuZ3RoIGJlZm9yZSB0aGUgb3RoZXIgY2hlY2tzIG9yIHdoZW4gdGhlIHVzZXIgY2xpY2tzIGludG8gYW5vdGhlciBncmlkIHdoaWxlIGhvbGRpbmcgc2hpZnQsIGl0IHRocm93cyB0aGUgZm9sbG93aW5nIGVycm9yOlxuXHRcdFx0Ly9DYW5ub3QgcmVhZCBwcm9wZXJ0eSAnY2VsbF9pbmRleCcgb2YgdW5kZWZpbmVkXG5cblx0XHRcdHZhciB1cHBlcm1vc3Rfcm93X2luZGV4ID0gcGFyc2VJbnQoIGNlbGxzX2FycmF5WzBdLnJvd19pZCApO1xuXHRcdFx0dmFyIGxvd2VybW9zdF9yb3dfaW5kZXggPSBwYXJzZUludCggY2VsbHNfYXJyYXlbY2VsbHNfYXJyYXkubGVuZ3RoIC0gMV0ucm93X2lkICk7XG5cdFx0XHR2YXIgbGVmdG1vc3RfY2VsbF9pbmRleCA9IHBhcnNlSW50KCBjZWxsc19hcnJheVswXS5jZWxsX2luZGV4ICk7XG5cdFx0XHR2YXIgcmlnaHRtb3N0X2NlbGxfaW5kZXggPSBwYXJzZUludCggY2VsbHNfYXJyYXlbY2VsbHNfYXJyYXkubGVuZ3RoIC0gMV0uY2VsbF9pbmRleCApO1xuXG5cdFx0XHRpZiAoIGNlbGxzX2FycmF5ICYmIGNlbGxzX2FycmF5Lmxlbmd0aCA+IDAgJiYgY2VsbHNfYXJyYXlbY2VsbHNfYXJyYXkubGVuZ3RoIC0gMV0uY2VsbF9pbmRleCAmJiBjZWxsc19hcnJheVswXS5jZWxsX2luZGV4XG5cdFx0XHRcdCYmIHJpZ2h0bW9zdF9jZWxsX2luZGV4ID49IGNlbGxfaW5kZXhcblx0XHRcdFx0JiYgbGVmdG1vc3RfY2VsbF9pbmRleCA8PSBjZWxsX2luZGV4XG5cdFx0XHRcdCYmIGxvd2VybW9zdF9yb3dfaW5kZXggPj0gcm93X2lkXG5cdFx0XHRcdCYmIHVwcGVybW9zdF9yb3dfaW5kZXggPD0gcm93X2lkICkge1xuXHRcdFx0XHRlbmRfcm93X2luZGV4ID0gcm93X2lkO1xuXHRcdFx0XHRlbmRfY2VsbF9pbmRleCA9IGNlbGxfaW5kZXg7XG5cdFx0XHR9XG5cblx0XHRcdC8vYnVpbGQgY2VsbHNfYXJyYXlcblx0XHRcdGNlbGxzX2FycmF5ID0gW107XG5cblx0XHRcdGZvciAoIHZhciBpID0gc3RhcnRfcm93X2luZGV4OyBpIDw9IGVuZF9yb3dfaW5kZXg7IGkrKyApIHtcblx0XHRcdFx0dmFyIHJfaW5kZXggPSBpO1xuXHRcdFx0XHRmb3IgKCB2YXIgaiA9IHN0YXJ0X2NlbGxfaW5kZXg7IGogPD0gZW5kX2NlbGxfaW5kZXg7IGorKyApIHtcblx0XHRcdFx0XHR2YXIgY19pbmRleCA9IGo7XG5cblx0XHRcdFx0XHRyb3dfdHIgPSAkKCB0YXJnZXQgKS5maW5kKCAndHIjJyArIHJfaW5kZXggKTtcblxuXHRcdFx0XHRcdGNlbGxfdGQgPSAkKCByb3dfdHIuZmluZCggJ3RkJyApW2NfaW5kZXhdICk7XG5cblx0XHRcdFx0XHRjZWxsX3ZhbCA9IGNlbGxfdGRbMF0ub3V0ZXJIVE1MO1xuXG5cdFx0XHRcdFx0aWYgKCBncmlkX2lkID09PSAndGltZXNoZWV0X2dyaWQnICkge1xuXHRcdFx0XHRcdFx0cHVuY2ggPSBnZXRDZWxsUHVuY2goIGksIGogKTtcblx0XHRcdFx0XHRcdHJlbGF0ZWRfcHVuY2ggPSBnZXRSZWxhdGVkUHVuY2goIGksIGogKTtcblxuXHRcdFx0XHRcdFx0ZGF0ZSA9IEdsb2JhbC5zdHJUb0RhdGUoIGRhdGFfZmllbGQsIHRoaXMuZnVsbF9mb3JtYXQgKTtcblxuXHRcdFx0XHRcdFx0ZGF0ZV9zdHIgPSBkYXRlLmZvcm1hdCgpO1xuXHRcdFx0XHRcdFx0dGltZV9zdGFtcF9udW0gPSBkYXRlLmdldFRpbWUoKTtcblxuXHRcdFx0XHRcdFx0Y2VsbHNfYXJyYXkucHVzaCgge1xuXHRcdFx0XHRcdFx0XHRyb3dfaWQ6IHJfaW5kZXgsXG5cdFx0XHRcdFx0XHRcdGNlbGxfaW5kZXg6IGNfaW5kZXgsXG5cdFx0XHRcdFx0XHRcdGNlbGxfdmFsOiBjZWxsX3ZhbCxcblx0XHRcdFx0XHRcdFx0cHVuY2g6IHB1bmNoLFxuXHRcdFx0XHRcdFx0XHRzdGF0dXNfaWQ6IHN0YXR1c19pZCxcblx0XHRcdFx0XHRcdFx0cmVsYXRlZF9wdW5jaDogcmVsYXRlZF9wdW5jaCxcblx0XHRcdFx0XHRcdFx0ZGF0ZTogZGF0ZV9zdHIsXG5cdFx0XHRcdFx0XHRcdHRpbWVfc3RhbXBfbnVtOiB0aW1lX3N0YW1wX251bVxuXHRcdFx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdFx0fSBlbHNlIGlmICggZ3JpZF9pZCA9PT0gJ2Fic2VuY2VfZ3JpZCcgKSB7XG5cdFx0XHRcdFx0XHRjb2xNb2RlbCA9ICR0aGlzLmFic2VuY2VfZ3JpZC5nZXRHcmlkUGFyYW0oICdjb2xNb2RlbCcgKTtcblxuXHRcdFx0XHRcdFx0ZGF0YV9maWVsZCA9IGNvbE1vZGVsW2NfaW5kZXhdLm5hbWU7XG5cblx0XHRcdFx0XHRcdHB1bmNoID0gcm93W2RhdGFfZmllbGQgKyAnX2RhdGEnXTtcblxuXHRcdFx0XHRcdFx0ZGF0ZSA9IEdsb2JhbC5zdHJUb0RhdGUoIGRhdGFfZmllbGQsIHRoaXMuZnVsbF9mb3JtYXQgKTtcblxuXHRcdFx0XHRcdFx0ZGF0ZV9zdHIgPSBkYXRlLmZvcm1hdCgpO1xuXHRcdFx0XHRcdFx0dGltZV9zdGFtcF9udW0gPSBkYXRlLmdldFRpbWUoKTtcblxuXHRcdFx0XHRcdFx0Y2VsbHNfYXJyYXkucHVzaCgge1xuXHRcdFx0XHRcdFx0XHRyb3dfaWQ6IHJfaW5kZXgsIC8vc2VlIGJ1ZyAjMjE0OVxuXHRcdFx0XHRcdFx0XHQvL3Jvd19pZDogcl9pbmRleC50b1N0cmluZygpLFxuXHRcdFx0XHRcdFx0XHRjZWxsX2luZGV4OiBjX2luZGV4LFxuXHRcdFx0XHRcdFx0XHRjZWxsX3ZhbDogY2VsbF92YWwsXG5cdFx0XHRcdFx0XHRcdHB1bmNoOiBwdW5jaCxcblx0XHRcdFx0XHRcdFx0ZGF0ZTogZGF0ZV9zdHIsXG5cdFx0XHRcdFx0XHRcdHRpbWVfc3RhbXBfbnVtOiB0aW1lX3N0YW1wX251bSxcblx0XHRcdFx0XHRcdFx0c3JjX29iamVjdF9pZDogKCByb3cucHVuY2hfaW5mb19pZCApID8gcm93LnB1bmNoX2luZm9faWQgOiBudWxsLFxuXHRcdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoIGdyaWRfaWQgPT09ICdhY2N1bXVsYXRlZF9ncmlkJyApIHtcblx0XHRcdFx0XHRcdGNlbGxzX2FycmF5ID0gW1xuXHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0cm93X2lkOiByb3dfaWQsXG5cdFx0XHRcdFx0XHRcdFx0Y2VsbF9pbmRleDogY2VsbF9pbmRleCxcblx0XHRcdFx0XHRcdFx0XHRjZWxsX3ZhbDogY2VsbF92YWwsXG5cdFx0XHRcdFx0XHRcdFx0ZGF0ZTogZGF0ZV9zdHIsXG5cdFx0XHRcdFx0XHRcdFx0dGltZV9zdGFtcF9udW06IHRpbWVfc3RhbXBfbnVtXG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdF07XG5cdFx0XHRcdFx0XHQkdGhpcy5hY2N1bXVsYXRlZF90aW1lX2NlbGxzX2FycmF5ID0gY2VsbHNfYXJyYXk7XG5cdFx0XHRcdFx0fSBlbHNlIGlmICggZ3JpZF9pZCA9PT0gJ3ByZW1pdW1fZ3JpZCcgKSB7XG5cdFx0XHRcdFx0XHRjZWxsc19hcnJheSA9IFtcblx0XHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRcdHJvd19pZDogcm93X2lkLFxuXHRcdFx0XHRcdFx0XHRcdGNlbGxfaW5kZXg6IGNlbGxfaW5kZXgsXG5cdFx0XHRcdFx0XHRcdFx0Y2VsbF92YWw6IGNlbGxfdmFsLFxuXHRcdFx0XHRcdFx0XHRcdGRhdGU6IGRhdGVfc3RyLFxuXHRcdFx0XHRcdFx0XHRcdHRpbWVfc3RhbXBfbnVtOiB0aW1lX3N0YW1wX251bVxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRdO1xuXHRcdFx0XHRcdFx0JHRoaXMucHJlbWl1bV9jZWxsc19hcnJheSA9IGNlbGxzX2FycmF5O1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmICggZ3JpZF9pZCA9PT0gJ3RpbWVzaGVldF9ncmlkJyApIHtcblx0XHRcdFx0JHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5ID0gY2VsbHNfYXJyYXk7XG5cdFx0XHRcdCR0aGlzLnNlbGVjdF9jZWxsc19BcnJheS5zb3J0KCBHbG9iYWwubV9zb3J0X2J5KCBbJ3RpbWVfc3RhbXBfbnVtJywgJ3Jvd19pZCddICkgKTtcblx0XHRcdH0gZWxzZSBpZiAoIGdyaWRfaWQgPT09ICdhYnNlbmNlX2dyaWQnICkge1xuXHRcdFx0XHQkdGhpcy5hYnNlbmNlX3NlbGVjdF9jZWxsc19BcnJheSA9IGNlbGxzX2FycmF5O1xuXHRcdFx0XHQkdGhpcy5hYnNlbmNlX3NlbGVjdF9jZWxsc19BcnJheS5zb3J0KCBHbG9iYWwubV9zb3J0X2J5KCBbJ3RpbWVfc3RhbXBfbnVtJywgJ3Jvd19pZCddICkgKTtcblx0XHRcdH0gZWxzZSBpZiAoIGdyaWRfaWQgPT09ICdhY2N1bXVsYXRlZF9ncmlkJyApIHtcblx0XHRcdFx0JHRoaXMuYWNjdW11bGF0ZWRfdGltZV9jZWxsc19hcnJheSA9IGNlbGxzX2FycmF5O1xuXHRcdFx0XHQkdGhpcy5hY2N1bXVsYXRlZF90aW1lX2NlbGxzX2FycmF5LnNvcnQoIEdsb2JhbC5tX3NvcnRfYnkoIFsndGltZV9zdGFtcF9udW0nLCAncm93X2lkJ10gKSApO1xuXHRcdFx0fSBlbHNlIGlmICggZ3JpZF9pZCA9PT0gJ3ByZW1pdW1fZ3JpZCcgKSB7XG5cdFx0XHRcdCR0aGlzLnByZW1pdW1fY2VsbHNfYXJyYXkgPSBjZWxsc19hcnJheTtcblx0XHRcdFx0JHRoaXMucHJlbWl1bV9jZWxsc19hcnJheS5zb3J0KCBHbG9iYWwubV9zb3J0X2J5KCBbJ3RpbWVfc3RhbXBfbnVtJywgJ3Jvd19pZCddICkgKTtcblx0XHRcdH1cblxuXHRcdH0gZWxzZSB7XG5cdFx0XHRkYXRlX3N0ciA9IGRhdGUgPyBkYXRlLmZvcm1hdCgpIDogJyc7XG5cdFx0XHR0aW1lX3N0YW1wX251bSA9IGRhdGUgPyBkYXRlLmdldFRpbWUoKSA6IDA7XG5cdFx0XHRpZiAoIGdyaWRfaWQgPT09ICd0aW1lc2hlZXRfZ3JpZCcgKSB7XG5cdFx0XHRcdC8vZ2V0IHRoZSBwdW5jaCBkYXRhLlxuXHRcdFx0XHRwdW5jaCA9IGdldENlbGxQdW5jaCggcm93X2lkLCBjZWxsX2luZGV4ICk7XG5cblx0XHRcdFx0cmVsYXRlZF9wdW5jaCA9IGdldFJlbGF0ZWRQdW5jaCggcm93X2lkLCBjZWxsX2luZGV4ICk7XG5cblx0XHRcdFx0Y2VsbHNfYXJyYXkgPSBbXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0cm93X2lkOiByb3dfaWQsXG5cdFx0XHRcdFx0XHRjZWxsX2luZGV4OiBjZWxsX2luZGV4LFxuXHRcdFx0XHRcdFx0Y2VsbF92YWw6IGNlbGxfdmFsLFxuXHRcdFx0XHRcdFx0cHVuY2g6IHB1bmNoLFxuXHRcdFx0XHRcdFx0c3RhdHVzX2lkOiAoIHJvdyAmJiByb3cuc3RhdHVzX2lkICkgPyByb3cuc3RhdHVzX2lkIDogbnVsbCxcblx0XHRcdFx0XHRcdHJlbGF0ZWRfcHVuY2g6IHJlbGF0ZWRfcHVuY2gsXG5cdFx0XHRcdFx0XHRkYXRlOiBkYXRlX3N0cixcblx0XHRcdFx0XHRcdHRpbWVfc3RhbXBfbnVtOiB0aW1lX3N0YW1wX251bVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XTtcblxuXHRcdFx0XHQkdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXkgPSBjZWxsc19hcnJheTtcblx0XHRcdH0gZWxzZSBpZiAoIGdyaWRfaWQgPT09ICdhYnNlbmNlX2dyaWQnICkge1xuXHRcdFx0XHRjZWxsc19hcnJheSA9IFtcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRyb3dfaWQ6IHJvd19pZCxcblx0XHRcdFx0XHRcdGNlbGxfaW5kZXg6IGNlbGxfaW5kZXgsXG5cdFx0XHRcdFx0XHRjZWxsX3ZhbDogY2VsbF92YWwsXG5cdFx0XHRcdFx0XHRwdW5jaDogcHVuY2gsXG5cdFx0XHRcdFx0XHRkYXRlOiBkYXRlX3N0cixcblx0XHRcdFx0XHRcdHRpbWVfc3RhbXBfbnVtOiB0aW1lX3N0YW1wX251bSxcblx0XHRcdFx0XHRcdHNyY19vYmplY3RfaWQ6ICggcm93LnB1bmNoX2luZm9faWQgKSA/IHJvdy5wdW5jaF9pbmZvX2lkIDogbnVsbCxcblx0XHRcdFx0XHR9XG5cdFx0XHRcdF07XG5cblx0XHRcdFx0JHRoaXMuYWJzZW5jZV9zZWxlY3RfY2VsbHNfQXJyYXkgPSBjZWxsc19hcnJheTtcblx0XHRcdH0gZWxzZSBpZiAoIGdyaWRfaWQgPT09ICdhY2N1bXVsYXRlZF9ncmlkJyApIHtcblx0XHRcdFx0Y2VsbHNfYXJyYXkgPSBbXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0cm93X2lkOiByb3dfaWQsXG5cdFx0XHRcdFx0XHRjZWxsX2luZGV4OiBjZWxsX2luZGV4LFxuXHRcdFx0XHRcdFx0Y2VsbF92YWw6IGNlbGxfdmFsLFxuXHRcdFx0XHRcdFx0ZGF0ZTogZGF0ZV9zdHIsXG5cdFx0XHRcdFx0XHR0aW1lX3N0YW1wX251bTogdGltZV9zdGFtcF9udW1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdF07XG5cblx0XHRcdFx0JHRoaXMuYWNjdW11bGF0ZWRfdGltZV9jZWxsc19hcnJheSA9IGNlbGxzX2FycmF5O1xuXHRcdFx0fSBlbHNlIGlmICggZ3JpZF9pZCA9PT0gJ3ByZW1pdW1fZ3JpZCcgKSB7XG5cdFx0XHRcdGNlbGxzX2FycmF5ID0gW1xuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdHJvd19pZDogcm93X2lkLFxuXHRcdFx0XHRcdFx0Y2VsbF9pbmRleDogY2VsbF9pbmRleCxcblx0XHRcdFx0XHRcdGNlbGxfdmFsOiBjZWxsX3ZhbCxcblx0XHRcdFx0XHRcdGRhdGU6IGRhdGVfc3RyLFxuXHRcdFx0XHRcdFx0dGltZV9zdGFtcF9udW06IHRpbWVfc3RhbXBfbnVtXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRdO1xuXG5cdFx0XHRcdCR0aGlzLnByZW1pdW1fY2VsbHNfYXJyYXkgPSBjZWxsc19hcnJheTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBkYXRlICYmIGRhdGUuZ2V0WWVhcigpID4gMCApIHtcblx0XHRcdFx0dGhpcy5zZXREYXRlUGlja2VyVmFsdWUoIGRhdGUuZm9ybWF0KCBHbG9iYWwuZ2V0TG9naW5Vc2VyRGF0ZUZvcm1hdCgpICkgKTtcblx0XHRcdFx0dGhpcy5oaWdoTGlnaHRTZWxlY3REYXkoIGUgKTtcblx0XHRcdFx0dGhpcy5yZUxvYWRTdWJHcmlkc1NvdXJjZSgpO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLnVuc2V0U2VsZWN0ZWRDZWxscyggZ3JpZF9pZCApO1xuXHRcdH1cblxuXHRcdC8vbm93IHNldCB0aGUgc2VsZWN0ZWQgcHVuY2hlcyBhcnJheVxuXHRcdHRoaXMuc2VsZWN0X3B1bmNoZXNfYXJyYXkgPSBbXTtcblx0XHRmb3IgKCB2YXIgbiBpbiBjZWxsc19hcnJheSApIHtcblx0XHRcdGlmICggY2VsbHNfYXJyYXlbbl0ucHVuY2ggKSB7XG5cdFx0XHRcdHRoaXMuc2VsZWN0X3B1bmNoZXNfYXJyYXkucHVzaCggY2VsbHNfYXJyYXlbbl0ucHVuY2ggKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0dGhpcy5zZXRUaW1lc2hlZXRHcmlkRHJhZ0FibGUoKTtcblxuXHRcdGZ1bmN0aW9uIGdldENlbGxQdW5jaCggcm93X2lkLCBjZWxsX2luZGV4ICkge1xuXHRcdFx0dmFyIHB1bmNoID0gbnVsbDtcblx0XHRcdHJvdyA9IG51bGw7XG5cdFx0XHRmb3IgKCB2YXIgaSBpbiAkdGhpcy50aW1lc2hlZXRfZGF0YV9zb3VyY2UgKSB7XG5cdFx0XHRcdGlmICggJHRoaXMudGltZXNoZWV0X2RhdGFfc291cmNlW2ldLmlkID09IHJvd19pZCApIHtcblx0XHRcdFx0XHRyb3cgPSAkdGhpcy50aW1lc2hlZXRfZGF0YV9zb3VyY2VbaV07XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0aWYgKCByb3cgKSB7XG5cdFx0XHRcdGNvbE1vZGVsID0gJHRoaXMuZ3JpZC5nZXRHcmlkUGFyYW0oICdjb2xNb2RlbCcgKTtcblx0XHRcdFx0ZGF0YV9maWVsZCA9IGNvbE1vZGVsW2NlbGxfaW5kZXhdLm5hbWU7XG5cdFx0XHRcdHB1bmNoID0gcm93W2RhdGFfZmllbGQgKyAnX2RhdGEnXSA/IHJvd1tkYXRhX2ZpZWxkICsgJ19kYXRhJ10gOiBudWxsO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHB1bmNoO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGdldFJlbGF0ZWRQdW5jaCggcm93X2lkLCBjZWxsX2luZGV4ICkge1xuXHRcdFx0dmFyIHJlbGF0ZWRfcHVuY2ggPSBudWxsO1xuXHRcdFx0cm93ID0gbnVsbDtcblx0XHRcdGZvciAoIHZhciBpIGluICR0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZSApIHtcblx0XHRcdFx0aWYgKCAkdGhpcy50aW1lc2hlZXRfZGF0YV9zb3VyY2VbaV0uaWQgPT0gcm93X2lkICkge1xuXHRcdFx0XHRcdHJvdyA9ICR0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZVtpXTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0Ly9yb3cgPSAkdGhpcy50aW1lc2hlZXRfZGF0YV9zb3VyY2Vbcm93X2lkIC0xIF07XG5cdFx0XHRpZiAoIHJvdyApIHtcblx0XHRcdFx0Y29sTW9kZWwgPSAkdGhpcy5ncmlkLmdldEdyaWRQYXJhbSggJ2NvbE1vZGVsJyApO1xuXHRcdFx0XHRkYXRhX2ZpZWxkID0gY29sTW9kZWxbY2VsbF9pbmRleF0ubmFtZTtcblx0XHRcdFx0cmVsYXRlZF9wdW5jaCA9IHJvd1tkYXRhX2ZpZWxkICsgJ19yZWxhdGVkX2RhdGEnXSA/IHJvd1tkYXRhX2ZpZWxkICsgJ19yZWxhdGVkX2RhdGEnXSA6IG51bGw7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gcmVsYXRlZF9wdW5jaDtcblx0XHR9XG5cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdGdldF9zZWxlY3RlZF9wdW5jaF9hcnJheSgpIHtcblx0fVxuXG5cdGJ1aWxkVGltZVNoZWV0UmVxdWVzdHMoKSB7XG5cdFx0dmFyIHJlcXVlc3RfYXJyYXkgPSB0aGlzLmZ1bGxfdGltZXNoZWV0X2RhdGEucmVxdWVzdF9kYXRhO1xuXHRcdHZhciBsZW4gPSByZXF1ZXN0X2FycmF5Lmxlbmd0aDtcblx0XHR2YXIgcmVxdWVzdF9yb3dfaW5kZXggPSBudWxsO1xuXG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHR2YXIgcmVxdWVzdCA9IHJlcXVlc3RfYXJyYXlbaV07XG5cblx0XHRcdHZhciBkYXRlX3N0cmluZyA9IEdsb2JhbC5zdHJUb0RhdGUoIHJlcXVlc3QuZGF0ZV9zdGFtcCApLmZvcm1hdCggdGhpcy5mdWxsX2Zvcm1hdCApO1xuXG5cdFx0XHR2YXIgcm93O1xuXHRcdFx0Ly9CdWlsZCBFeGNlcHRpb24gcm93IGF0IGJvdHRvbVxuXHRcdFx0aWYgKCAhcmVxdWVzdF9yb3dfaW5kZXggKSB7XG5cdFx0XHRcdHJvdyA9IHt9O1xuXHRcdFx0XHRyb3cucHVuY2hfaW5mbyA9ICQuaTE4bi5fKCAnUmVxdWVzdHMnICk7XG5cdFx0XHRcdHJvdy51c2VyX2lkID0gcmVxdWVzdC51c2VyX2lkO1xuXHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmddID0gcmVxdWVzdC5zdGF0dXM7XG5cdFx0XHRcdHJvd1tkYXRlX3N0cmluZyArICdfcmVxdWVzdCddID0gcmVxdWVzdDtcblxuXHRcdFx0XHRyb3cudHlwZSA9IFRpbWVTaGVldFZpZXdDb250cm9sbGVyLlJFUVVFU1RfUk9XO1xuXHRcdFx0XHR0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZS5wdXNoKCByb3cgKTtcblx0XHRcdFx0cmVxdWVzdF9yb3dfaW5kZXggPSB0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZS5sZW5ndGggLSAxO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cm93ID0gdGhpcy50aW1lc2hlZXRfZGF0YV9zb3VyY2VbcmVxdWVzdF9yb3dfaW5kZXhdO1xuXHRcdFx0XHRpZiAoICFHbG9iYWwuaXNTZXQoIHJvd1tkYXRlX3N0cmluZyArICdfcmVxdWVzdCddICkgKSB7XG5cdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nXSA9IHJlcXVlc3Quc3RhdHVzO1xuXHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZyArICdfcmVxdWVzdCddID0gcmVxdWVzdDtcblx0XHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRcdGlmICggJC50eXBlKCByb3dbZGF0ZV9zdHJpbmcgKyAnX3JlcXVlc3QnXSApID09PSAnYXJyYXknICkge1xuXHRcdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nICsgJ19yZXF1ZXN0J10ucHVzaCggcmVxdWVzdCApO1xuXG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZyArICdfcmVxdWVzdCddID0gW3Jvd1tkYXRlX3N0cmluZyArICdfcmVxdWVzdCddXTtcblx0XHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZyArICdfcmVxdWVzdCddLnB1c2goIHJlcXVlc3QgKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmddID0gY2FsREFuZEEoIHJvd1tkYXRlX3N0cmluZyArICdfcmVxdWVzdCddICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGNhbERBbmRBKCBhcnJheSApIHtcblx0XHRcdHZhciBsZW4gPSBhcnJheS5sZW5ndGg7XG5cdFx0XHR2YXIgYSA9IDA7XG5cdFx0XHR2YXIgZCA9IDA7XG5cdFx0XHR2YXIgcCA9IDA7XG5cdFx0XHR2YXIgbGFiZWwgPSAnJztcblx0XHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0XHR2YXIgaXRlbSA9IGFycmF5W2ldO1xuXHRcdFx0XHRpZiAoIGl0ZW0uc3RhdHVzX2lkID09IDUwICkge1xuXHRcdFx0XHRcdGEgPSBhICsgMTtcblx0XHRcdFx0fSBlbHNlIGlmICggaXRlbS5zdGF0dXNfaWQgPT0gNTUgKSB7XG5cdFx0XHRcdFx0ZCA9IGQgKyAxO1xuXHRcdFx0XHR9IGVsc2UgaWYgKCBpdGVtLnN0YXR1c19pZCA9PSAzMCApIHtcblx0XHRcdFx0XHRwID0gcCArIDE7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdGlmICggYSA+IDAgKSB7XG5cdFx0XHRcdGxhYmVsICs9ICcgQTogJyArIGE7XG5cdFx0XHR9XG5cdFx0XHRpZiAoIHAgPiAwICkge1xuXHRcdFx0XHRsYWJlbCArPSAnIFA6ICcgKyBwO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCBkID4gMCApIHtcblx0XHRcdFx0bGFiZWwgKz0gJyBEOiAnICsgZDtcblx0XHRcdH1cblx0XHRcdHJldHVybiBsYWJlbDtcblx0XHR9XG5cdH1cblxuXHRidWlsZFRpbWVTaGVldEV4Y2VwdGlvbnMoKSB7XG5cdFx0dmFyIGV4Y2VwdGlvbl9hcnJheSA9IHRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YS5leGNlcHRpb25fZGF0YTtcblxuXHRcdHZhciBsZW4gPSBleGNlcHRpb25fYXJyYXkubGVuZ3RoO1xuXHRcdHZhciB0aW1lc2hlZXRfZGF0YV9zb3VyY2VfbGVuID0gdGhpcy50aW1lc2hlZXRfZGF0YV9zb3VyY2UubGVuZ3RoO1xuXHRcdHZhciBleGNlcHRpb25fcm93X2luZGV4ID0gbnVsbDtcblx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdHZhciBleCA9IGV4Y2VwdGlvbl9hcnJheVtpXTtcblx0XHRcdHZhciBkYXRlX3N0cmluZyA9IEdsb2JhbC5zdHJUb0RhdGUoIGV4LmRhdGVfc3RhbXAgKS5mb3JtYXQoIHRoaXMuZnVsbF9mb3JtYXQgKTtcblx0XHRcdHZhciByb3c7XG5cdFx0XHQvL0J1aWxkIEV4Y2VwdGlvbiByb3cgYXQgYm90dG9tXG5cdFx0XHRpZiAoICFleGNlcHRpb25fcm93X2luZGV4ICkge1xuXHRcdFx0XHRyb3cgPSB7fTtcblx0XHRcdFx0cm93LnB1bmNoX2luZm8gPSAkLmkxOG4uXyggJ0V4Y2VwdGlvbnMnICk7XG5cdFx0XHRcdHJvdy51c2VyX2lkID0gZXgudXNlcl9pZDtcblx0XHRcdFx0cm93W2RhdGVfc3RyaW5nXSA9ICcnO1xuXHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmcgKyAnX2V4Y2VwdGlvbnMnXSA9IFtleF07XG5cblx0XHRcdFx0cm93LnR5cGUgPSBUaW1lU2hlZXRWaWV3Q29udHJvbGxlci5FWENFUFRJT05fUk9XO1xuXHRcdFx0XHR0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZS5wdXNoKCByb3cgKTtcblx0XHRcdFx0ZXhjZXB0aW9uX3Jvd19pbmRleCA9IHRoaXMudGltZXNoZWV0X2RhdGFfc291cmNlLmxlbmd0aCAtIDE7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyb3cgPSB0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZVtleGNlcHRpb25fcm93X2luZGV4XTtcblx0XHRcdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCByb3dbZGF0ZV9zdHJpbmcgKyAnX2V4Y2VwdGlvbnMnXSApICkge1xuXHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZyArICdfZXhjZXB0aW9ucyddID0gW2V4XTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmcgKyAnX2V4Y2VwdGlvbnMnXS5wdXNoKCBleCApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHZhciBwdW5jaDtcblx0XHRcdHZhciBqO1xuXHRcdFx0aWYgKCAhR2xvYmFsLmlzRmFsc2VPck51bGwoIGV4LnB1bmNoX2lkICkgKSB7XG5cblx0XHRcdFx0Zm9yICggdmFyIGogPSAwOyBqIDwgdGltZXNoZWV0X2RhdGFfc291cmNlX2xlbjsgaisrICkge1xuXHRcdFx0XHRcdHJvdyA9IHRoaXMudGltZXNoZWV0X2RhdGFfc291cmNlW2pdO1xuXG5cdFx0XHRcdFx0aWYgKCAhcm93W2RhdGVfc3RyaW5nXSApIHtcblx0XHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICggcm93W2RhdGVfc3RyaW5nICsgJ19kYXRhJ10gKSB7XG5cdFx0XHRcdFx0XHRwdW5jaCA9IHJvd1tkYXRlX3N0cmluZyArICdfZGF0YSddO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoIHJvd1tkYXRlX3N0cmluZyArICdfcmVsYXRlZF9fZGF0YSddICkge1xuXHRcdFx0XHRcdFx0cHVuY2ggPSByb3dbZGF0ZV9zdHJpbmcgKyAnX3JlbGF0ZWRfZGF0YSddO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICggcHVuY2ggJiYgcHVuY2guaWQgPT09IGV4LnB1bmNoX2lkICYmICFwdW5jaC5leGNlcHRpb24gKSB7XG5cdFx0XHRcdFx0XHRwdW5jaC5leGNlcHRpb24gPSBbZXhdO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHR9XG5cblx0XHRcdH0gZWxzZSBpZiAoICFHbG9iYWwuaXNGYWxzZU9yTnVsbCggZXgucHVuY2hfY29udHJvbF9pZCApICkge1xuXHRcdFx0XHRmb3IgKCB2YXIgaiA9IDA7IGogPCB0aW1lc2hlZXRfZGF0YV9zb3VyY2VfbGVuOyBqKysgKSB7XG5cdFx0XHRcdFx0cm93ID0gdGhpcy50aW1lc2hlZXRfZGF0YV9zb3VyY2Vbal07XG5cblx0XHRcdFx0XHRpZiAoICFyb3dbZGF0ZV9zdHJpbmddICkge1xuXHRcdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKCByb3dbZGF0ZV9zdHJpbmcgKyAnX2RhdGEnXSApIHtcblx0XHRcdFx0XHRcdHB1bmNoID0gcm93W2RhdGVfc3RyaW5nICsgJ19kYXRhJ107XG5cdFx0XHRcdFx0fSBlbHNlIGlmICggcm93W2RhdGVfc3RyaW5nICsgJ19yZWxhdGVkX19kYXRhJ10gKSB7XG5cdFx0XHRcdFx0XHRwdW5jaCA9IHJvd1tkYXRlX3N0cmluZyArICdfcmVsYXRlZF9kYXRhJ107XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKCBwdW5jaCAmJiBwdW5jaC5wdW5jaF9jb250cm9sX2lkID09PSBleC5wdW5jaF9jb250cm9sX2lkICYmICFwdW5jaC5leGNlcHRpb24gKSB7XG5cdFx0XHRcdFx0XHRwdW5jaC5leGNlcHRpb24gPSBbZXhdO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gTWFrZSBzdXJlIFRvdGxlX3RpbWUgZ28gdG8gbGFzdCBpdGVtXG5cdHNvcnRBY2N1bXVsYXRlZFRvdGFsRGF0YSgpIHtcblxuXHRcdHZhciBzb3J0X2ZpZWxkcyA9IFsnb3JkZXInLCAncHVuY2hfaW5mbyddO1xuXHRcdHRoaXMuYWNjdW11bGF0ZWRfdG90YWxfZ3JpZF9zb3VyY2Uuc29ydCggR2xvYmFsLm1fc29ydF9ieSggc29ydF9maWVsZHMgKSApO1xuXHR9XG5cblx0Ly8gTWFrZSBzdXJlIHRvdGFsIHRpbWUgZ28gdG8gbGFzdCBpdGVtXG5cdHNvcnRBY2N1bXVsYXRlZFRpbWVEYXRhKCkge1xuXG5cdFx0dmFyIHNvcnRfZmllbGRzID0gWydvcmRlcicsICdwdW5jaF9pbmZvJ107XG5cdFx0dGhpcy5hY2N1bXVsYXRlZF90aW1lX3NvdXJjZS5zb3J0KCBHbG9iYWwubV9zb3J0X2J5KCBzb3J0X2ZpZWxkcyApICk7XG5cdH1cblxuXHRyZUxvYWRTdWJHcmlkc1NvdXJjZSggZm9yY2UgKSB7XG5cdFx0Ly8gRXJyb3I6IFVuY2F1Z2h0IFR5cGVFcnJvcjogQ2Fubm90IHJlYWQgcHJvcGVydHkgJ3BheV9wZXJpb2RfaWQnIG9mIHVuZGVmaW5lZCBpbiBpbnRlcmZhY2UvaHRtbDUvIyFtPVRpbWVTaGVldCZkYXRlPTIwMTUxMjE0JnVzZXJfaWQ9bnVsbCZzaG93X3dhZ2U9MCBsaW5lIDQyOTBcblx0XHRpZiAoICF0aGlzLmZ1bGxfdGltZXNoZWV0X2RhdGEgfHwgIXRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YS50aW1lc2hlZXRfdmVyaWZ5X2RhdGEgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKCAhZm9yY2UgKSB7XG5cdFx0XHRpZiAoIHRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YS50aW1lc2hlZXRfdmVyaWZ5X2RhdGEucGF5X3BlcmlvZF9pZCA9PT0gdGhpcy5wYXlfcGVyaW9kX21hcFt0aGlzLmdldFNlbGVjdERhdGUoKV0gfHxcblx0XHRcdFx0KCAhR2xvYmFsLmlzU2V0KCB0aGlzLmZ1bGxfdGltZXNoZWV0X2RhdGEudGltZXNoZWV0X3ZlcmlmeV9kYXRhLnBheV9wZXJpb2RfaWQgKSAmJiAhdGhpcy5wYXlfcGVyaW9kX21hcFt0aGlzLmdldFNlbGVjdERhdGUoKV0gKVxuXHRcdFx0KSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHR9XG5cblx0XHR0aGlzLmFjY3VtdWxhdGVkX3RpbWVfc291cmNlX21hcCA9IHt9O1xuXHRcdHRoaXMuYnJhbmNoX3NvdXJjZV9tYXAgPSB7fTtcblx0XHR0aGlzLmRlcGFydG1lbnRfc291cmNlX21hcCA9IHt9O1xuXHRcdHRoaXMuam9iX3NvdXJjZV9tYXAgPSB7fTtcblx0XHR0aGlzLmpvYl9pdGVtX3NvdXJjZV9tYXAgPSB7fTtcblx0XHR0aGlzLnB1bmNoX3RhZ19zb3VyY2VfbWFwID0ge307XG5cdFx0dGhpcy5wcmVtaXVtX3NvdXJjZV9tYXAgPSB7fTtcblx0XHR0aGlzLmFjY3VtdWxhdGVkX3RvdGFsX2dyaWRfc291cmNlX21hcCA9IHt9O1xuXHRcdHRoaXMuYWNjdW11bGF0ZWRfdGltZV9zb3VyY2UgPSBbXTtcblx0XHR0aGlzLmJyYW5jaF9zb3VyY2UgPSBbXTtcblx0XHR0aGlzLmRlcGFydG1lbnRfc291cmNlID0gW107XG5cdFx0dGhpcy5qb2Jfc291cmNlID0gW107XG5cdFx0dGhpcy5qb2JfaXRlbV9zb3VyY2UgPSBbXTtcblx0XHR0aGlzLnB1bmNoX3RhZ19zb3VyY2UgPSBbXTtcblx0XHR0aGlzLnByZW1pdW1fc291cmNlID0gW107XG5cdFx0dGhpcy5hY2N1bXVsYXRlZF90b3RhbF9ncmlkX3NvdXJjZSA9IFtdO1xuXHRcdHRoaXMudmVyaWZpY2F0aW9uX2dyaWRfc291cmNlID0gW107XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgc3RhcnRfZGF0ZV9zdHJpbmcgPSB0aGlzLnN0YXJ0X2RhdGVfcGlja2VyLmdldFZhbHVlKCk7XG5cdFx0dmFyIHVzZXJfaWQgPSB0aGlzLmdldFNlbGVjdEVtcGxveWVlKCk7XG5cdFx0dGhpcy5hcGlfdGltZXNoZWV0LmdldFRpbWVTaGVldFRvdGFsRGF0YSggdXNlcl9pZCwgc3RhcnRfZGF0ZV9zdHJpbmcsIHtcblx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHQkdGhpcy5vblJlbG9hZFN1YkdyaWRSZXN1bHQoIHJlc3VsdCApO1xuXG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cblx0b25SZWxvYWRTdWJHcmlkUmVzdWx0KCByZXN1bHQgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHRyZXN1bHQgPSByZXN1bHQuZ2V0UmVzdWx0KCk7XG5cdFx0JHRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YS5hY2N1bXVsYXRlZF91c2VyX2RhdGVfdG90YWxfZGF0YSA9IHJlc3VsdC5hY2N1bXVsYXRlZF91c2VyX2RhdGVfdG90YWxfZGF0YTtcblx0XHQkdGhpcy5mdWxsX3RpbWVzaGVldF9kYXRhLm1lYWxfYW5kX2JyZWFrX3RvdGFsX2RhdGEgPSByZXN1bHQubWVhbF9hbmRfYnJlYWtfdG90YWxfZGF0YTtcblx0XHQkdGhpcy5mdWxsX3RpbWVzaGVldF9kYXRhLnBheV9wZXJpb2RfYWNjdW11bGF0ZWRfdXNlcl9kYXRlX3RvdGFsX2RhdGEgPSByZXN1bHQucGF5X3BlcmlvZF9hY2N1bXVsYXRlZF91c2VyX2RhdGVfdG90YWxfZGF0YTtcblx0XHQkdGhpcy5mdWxsX3RpbWVzaGVldF9kYXRhLnRpbWVzaGVldF92ZXJpZnlfZGF0YSA9IHJlc3VsdC50aW1lc2hlZXRfdmVyaWZ5X2RhdGE7XG5cdFx0JHRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YS5wYXlfcGVyaW9kX2RhdGEgPSByZXN1bHQucGF5X3BlcmlvZF9kYXRhO1xuXHRcdCR0aGlzLnRpbWVzaGVldF92ZXJpZnlfZGF0YSA9ICR0aGlzLmZ1bGxfdGltZXNoZWV0X2RhdGEudGltZXNoZWV0X3ZlcmlmeV9kYXRhO1xuXG5cdFx0JHRoaXMuYnVpbGRTdWJHcmlkc1NvdXJjZSgpO1xuXG5cdFx0JHRoaXMuYnVpbGRBY2N1bXVsYXRlZFRvdGFsR3JpZCgpO1xuXHRcdCR0aGlzLmJ1aWxkVmVyaWZpY2F0aW9uR3JpZFNvdXJjZSgpO1xuXG5cdFx0JHRoaXMuYWNjdW11bGF0ZWRfdGltZV9ncmlkLnNldERhdGEoICR0aGlzLmFjY3VtdWxhdGVkX3RpbWVfc291cmNlLCBmYWxzZSApO1xuXHRcdCR0aGlzLmJyYW5jaF9ncmlkLnNldERhdGEoICR0aGlzLmJyYW5jaF9zb3VyY2UsIGZhbHNlICk7XG5cdFx0JHRoaXMuZGVwYXJ0bWVudF9ncmlkLnNldERhdGEoICR0aGlzLmRlcGFydG1lbnRfc291cmNlLCBmYWxzZSApO1xuXHRcdCR0aGlzLmpvYl9ncmlkLnNldERhdGEoICR0aGlzLmpvYl9zb3VyY2UsIGZhbHNlICk7XG5cdFx0JHRoaXMuam9iX2l0ZW1fZ3JpZC5zZXREYXRhKCAkdGhpcy5qb2JfaXRlbV9zb3VyY2UsIGZhbHNlICk7XG5cdFx0JHRoaXMucHVuY2hfdGFnX2dyaWQuc2V0RGF0YSggJHRoaXMucHVuY2hfdGFnX3NvdXJjZSwgZmFsc2UgKTtcblx0XHQkdGhpcy5wcmVtaXVtX2dyaWQuc2V0RGF0YSggJHRoaXMucHJlbWl1bV9zb3VyY2UsIGZhbHNlICk7XG5cblx0XHRpZiAoICR0aGlzLmFjY3VtdWxhdGVkX3RvdGFsX2dyaWRfc291cmNlLmxlbmd0aCA9PT0gMCApIHtcblx0XHRcdCR0aGlzLmFjY3VtdWxhdGVkX3RvdGFsX2dyaWRfc291cmNlLnB1c2goKTtcblx0XHR9XG5cdFx0JHRoaXMuYWNjdW11bGF0ZWRfdG90YWxfZ3JpZC5zZXREYXRhKCAkdGhpcy5hY2N1bXVsYXRlZF90b3RhbF9ncmlkX3NvdXJjZSwgZmFsc2UgKTtcblxuXHRcdCR0aGlzLnB1bmNoX25vdGVfZ3JpZC5zZXREYXRhKCAkdGhpcy5wdW5jaF9ub3RlX2dyaWRfc291cmNlLCBmYWxzZSApO1xuXHRcdCR0aGlzLnZlcmlmaWNhdGlvbl9ncmlkLnNldERhdGEoICR0aGlzLnZlcmlmaWNhdGlvbl9ncmlkX3NvdXJjZSwgZmFsc2UgKTtcblxuXHRcdCR0aGlzLnNldEdyaWRTaXplKCk7XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudUVkaXRJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKSB7XG5cdFx0bGV0IHBfaWQgPSB0aGlzLmdldFB1bmNoUGVybWlzc2lvblR5cGUoKTtcblxuXHRcdGlmICggIXRoaXMuZWRpdFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCApIHx8IHRoaXMuZWRpdF9vbmx5X21vZGUgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApXG5cdFx0fVxuXG5cdFx0aWYgKCBncmlkX3NlbGVjdGVkX2xlbmd0aCA9PT0gMSAmJiB0aGlzLmVkaXRPd25lck9yQ2hpbGRQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQgKSAmJiAoIHRoaXMuZ2V0UHVuY2hNb2RlKCkgPT09ICdwdW5jaCcgfHwgcF9pZCA9PT0gJ2Fic2VuY2UnICkgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCB0cnVlICk7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCB0cnVlICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0XHRpZiggZ3JpZF9zZWxlY3RlZF9sZW5ndGggIT09IDAgKSB7XG5cdFx0XHRcdC8vIFRoaXMgZW5zdXJlcyB0aGUgZWRpdCBpY29uIGlzIHN0aWxsIHZpc2libGUgd2hlbiBub3RoaW5nIGlzIHNlbGVjdGVkLCBidXQgc2hvdWxkIHN0aWxsIGJlIGRpc2FibGVkLiAodG8ga2VlcCBjb25zaXN0ZW5jeSB3aXRoIG9sZCBkZXNpZ24pXG5cdFx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRzZXRFZGl0TWVudUFkZEljb24oIGNvbnRleHRfYnRuICkge1xuXHRcdGxldCBwX2lkID0gdGhpcy5nZXRQdW5jaFBlcm1pc3Npb25UeXBlKCk7XG5cblx0XHRpZiAoICF0aGlzLmFkZFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCApIHx8IHRoaXMuZWRpdF9vbmx5X21vZGUgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApXG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLmlzX2FkZCA9PSB0cnVlICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRzZXRFZGl0TWVudURlbGV0ZUljb24oIGNvbnRleHRfYnRuICkge1xuXHRcdGxldCBwX2lkID0gdGhpcy5nZXRQdW5jaFBlcm1pc3Npb25UeXBlKCk7XG5cblx0XHRpZiAoICF0aGlzLmRlbGV0ZVBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCApIHx8IHRoaXMuZWRpdF9vbmx5X21vZGUgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApXG5cdFx0fVxuXG5cdFx0aWYgKCAoICF0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgfHwgIXRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCApIHx8ICF0aGlzLmRlbGV0ZU93bmVyT3JDaGlsZFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCApICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRzZXRFZGl0TWVudURlbGV0ZUFuZE5leHRJY29uKCBjb250ZXh0X2J0biApIHtcblx0XHRsZXQgcF9pZCA9IHRoaXMuZ2V0UHVuY2hQZXJtaXNzaW9uVHlwZSgpO1xuXG5cdFx0aWYgKCAhdGhpcy5kZWxldGVQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQgKSB8fCB0aGlzLmVkaXRfb25seV9tb2RlICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdH1cblxuXHRcdGlmICggKCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkIHx8ICF0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgKSB8fCAhdGhpcy5kZWxldGVPd25lck9yQ2hpbGRQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQgKSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fVxuXHR9XG5cblx0c2V0RWRpdE1lbnVFZGl0SWNvbiggY29udGV4dF9idG4sIHBJZCApIHtcblx0XHRsZXQgcF9pZCA9IHRoaXMuZ2V0UHVuY2hQZXJtaXNzaW9uVHlwZSgpO1xuXG5cdFx0aWYgKCAhdGhpcy5lZGl0UGVybWlzc2lvblZhbGlkYXRlKCBwX2lkICkgfHwgdGhpcy5lZGl0X29ubHlfbW9kZSB8fCB0aGlzLmlzX21hc3NfZWRpdGluZyApIHtcblx0XHRcdC8vTm90IHNob3duIGluIGVkaXQgb25seSBtb2RlIG9yIG1hc3MgZWRpdC4gTWFzcyBlZGl0IHNob3VsZCBvbmx5IHNob3cgbWFzcyBlZGl0IChuZWVkIHRvIHNldCB0aGF0IHBhcnQgaW4gbWFzcyBlZGl0IGljb24pLlxuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cblx0XHRpZiAoICF0aGlzLmlzX3ZpZXdpbmcgfHwgIXRoaXMuZWRpdE93bmVyT3JDaGlsZFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCApICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudURlbGV0ZUljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApIHtcblx0XHRsZXQgcF9pZCA9IHRoaXMuZ2V0UHVuY2hQZXJtaXNzaW9uVHlwZSgpO1xuXG5cdFx0aWYgKCAhdGhpcy5kZWxldGVQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQgKSB8fCB0aGlzLmVkaXRfb25seV9tb2RlICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdH1cblxuXHRcdGlmICggZ3JpZF9zZWxlY3RlZF9sZW5ndGggPj0gMSAmJiB0aGlzLmRlbGV0ZU93bmVyT3JDaGlsZFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCApICYmICggdGhpcy5nZXRQdW5jaE1vZGUoKSA9PT0gJ3B1bmNoJyB8fCBwX2lkID09PSAnYWJzZW5jZScgKSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIHRydWUgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudURlbGV0ZUFuZE5leHRJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKSB7XG5cdFx0bGV0IHBfaWQgPSB0aGlzLmdldFB1bmNoUGVybWlzc2lvblR5cGUoKTtcblxuXHRcdGlmICggIXRoaXMuZGVsZXRlUGVybWlzc2lvblZhbGlkYXRlKCBwX2lkICkgfHwgdGhpcy5lZGl0X29ubHlfbW9kZSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHR9XG5cblx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHR9XG5cblx0c2V0RGVmYXVsdE1lbnVWaWV3SWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICkge1xuXHRcdGxldCBwX2lkID0gdGhpcy5nZXRQdW5jaFBlcm1pc3Npb25UeXBlKCk7XG5cblx0XHRpZiAoICF0aGlzLnZpZXdQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQgKSB8fCB0aGlzLmVkaXRfb25seV9tb2RlICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdH1cblxuXHRcdGlmICggZ3JpZF9zZWxlY3RlZF9sZW5ndGggPT09IDEgJiYgdGhpcy52aWV3T3duZXJPckNoaWxkUGVybWlzc2lvblZhbGlkYXRlKCkgJiYgKCB0aGlzLmdldFB1bmNoTW9kZSgpID09PSAncHVuY2gnIHx8IHBfaWQgPT09ICdhYnNlbmNlJyApICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgdHJ1ZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHRcdH1cblx0fVxuXG5cdHNldERlZmF1bHRNZW51QWRkUHVuY2hJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKSB7XG5cdFx0bGV0IHBfaWQgPSAncHVuY2gnO1xuXG5cdFx0aWYgKCAhdGhpcy5hZGRQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQgKSB8fCB0aGlzLmVkaXRfb25seV9tb2RlICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLmdldFB1bmNoTW9kZSgpID09PSAnbWFudWFsJyAmJiBwX2lkICE9PSAnYWJzZW5jZScgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHRcdH1cblx0fVxuXG5cdHNldERlZmF1bHRNZW51QWRkQWJzZW5jZUljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApIHtcblx0XHRsZXQgcF9pZCA9ICdhYnNlbmNlJztcblxuXHRcdGlmICggIXRoaXMuYWRkUGVybWlzc2lvblZhbGlkYXRlKCBwX2lkICkgfHwgdGhpcy5lZGl0X29ubHlfbW9kZSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5nZXRQdW5jaE1vZGUoKSA9PT0gJ21hbnVhbCcgJiYgcF9pZCAhPT0gJ2Fic2VuY2UnICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudVNhdmVJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKSB7XG5cdFx0bGV0IHBfaWQgPSB0aGlzLmdldFB1bmNoUGVybWlzc2lvblR5cGUoKTtcblxuXHRcdGlmICggKCAhdGhpcy5hZGRQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQgKSAmJiAhdGhpcy5lZGl0UGVybWlzc2lvblZhbGlkYXRlKCBwX2lkICkgKSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHR9XG5cdFx0aWYgKCB0aGlzLmdldFB1bmNoTW9kZSgpID09PSAnbWFudWFsJyApIHtcblx0XHRcdGlmICggKCAhdGhpcy5hZGRQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQgKSAmJiAhdGhpcy5lZGl0UGVybWlzc2lvblZhbGlkYXRlKCBwX2lkICkgKSApIHtcblx0XHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdFx0fVxuXHRcdFx0aWYgKCB0aGlzLmlzX3NhdmluZ19tYW51YWxfZ3JpZCApIHtcblx0XHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRidWlsZEFjY211bGF0ZWRPcmRlck1hcCggdG90YWwgKSB7XG5cblx0XHRpZiAoICF0b3RhbCApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0Zm9yICggdmFyIGtleSBpbiB0b3RhbCApIHtcblxuXHRcdFx0Zm9yICggdmFyIGtleTEgaW4gdG90YWxba2V5XSApIHtcblx0XHRcdFx0dGhpcy5hY2NtdWxhdGVkX29yZGVyX21hcFtrZXkxXSA9IHRvdGFsW2tleV1ba2V5MV0ub3JkZXI7XG5cdFx0XHR9XG5cblx0XHR9XG5cdH1cblxuXHRidWlsZFN1YkdyaWRzU291cmNlKCkge1xuXG5cdFx0dmFyIGFjY3VtdWxhdGVkX3VzZXJfZGF0ZV90b3RhbF9kYXRhID0gdGhpcy5mdWxsX3RpbWVzaGVldF9kYXRhLmFjY3VtdWxhdGVkX3VzZXJfZGF0ZV90b3RhbF9kYXRhO1xuXHRcdHZhciBtZWFsX2FuZF9icmVha190b3RhbF9kYXRhID0gdGhpcy5mdWxsX3RpbWVzaGVldF9kYXRhLm1lYWxfYW5kX2JyZWFrX3RvdGFsX2RhdGE7XG5cdFx0dmFyIHBheV9wZXJpb2RfYWNjdW11bGF0ZWRfdXNlcl9kYXRlX3RvdGFsX2RhdGEgPSB0aGlzLmZ1bGxfdGltZXNoZWV0X2RhdGEucGF5X3BlcmlvZF9hY2N1bXVsYXRlZF91c2VyX2RhdGVfdG90YWxfZGF0YTtcblxuXHRcdHRoaXMuYWNjbXVsYXRlZF9vcmRlcl9tYXAgPSB7fTtcblxuXHRcdC8vIFNhdmUgdGhlIG9yZGVyLCB3aWxsIGRvIHNvcnQgYWZ0ZXIgYWxsIGRhdGEgcHJlcGFyZWQuXG5cdFx0aWYgKCBhY2N1bXVsYXRlZF91c2VyX2RhdGVfdG90YWxfZGF0YS50b3RhbCApIHtcblx0XHRcdHRoaXMuYnVpbGRBY2NtdWxhdGVkT3JkZXJNYXAoIGFjY3VtdWxhdGVkX3VzZXJfZGF0ZV90b3RhbF9kYXRhLnRvdGFsICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBwYXlfcGVyaW9kX2FjY3VtdWxhdGVkX3VzZXJfZGF0ZV90b3RhbF9kYXRhICkge1xuXHRcdFx0dGhpcy5idWlsZEFjY211bGF0ZWRPcmRlck1hcCggcGF5X3BlcmlvZF9hY2N1bXVsYXRlZF91c2VyX2RhdGVfdG90YWxfZGF0YSApO1xuXHRcdH1cblxuXHRcdC8vQnVpbGQgQWNjdW11bGF0ZWQgVG90YWwgR3JpZCBQYXlfcGVyaW9kIGNvbHVtbiBkYXRhXG5cdFx0dmFyIGFjY3VtdWxhdGVkX3RpbWUgPSBwYXlfcGVyaW9kX2FjY3VtdWxhdGVkX3VzZXJfZGF0ZV90b3RhbF9kYXRhLmFjY3VtdWxhdGVkX3RpbWU7XG5cdFx0dmFyIHByZW1pdW1fdGltZSA9IHBheV9wZXJpb2RfYWNjdW11bGF0ZWRfdXNlcl9kYXRlX3RvdGFsX2RhdGEucHJlbWl1bV90aW1lO1xuXHRcdHZhciBhYnNlbmNlX3RpbWUgPSBwYXlfcGVyaW9kX2FjY3VtdWxhdGVkX3VzZXJfZGF0ZV90b3RhbF9kYXRhLmFic2VuY2VfdGltZV90YWtlbjtcblxuXHRcdGlmICggR2xvYmFsLmlzU2V0KCBhY2N1bXVsYXRlZF90aW1lICkgKSB7XG5cdFx0XHR0aGlzLmJ1aWxkU3ViR3JpZHNEYXRhKCBhY2N1bXVsYXRlZF90aW1lLCAncGF5X3BlcmlvZCcsIHRoaXMuYWNjdW11bGF0ZWRfdG90YWxfZ3JpZF9zb3VyY2VfbWFwLCB0aGlzLmFjY3VtdWxhdGVkX3RvdGFsX2dyaWRfc291cmNlLCAnYWNjdW11bGF0ZWRfdGltZScgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0YWNjdW11bGF0ZWRfdGltZSA9IHsgdG90YWw6IHsgbGFiZWw6ICQuaTE4bi5fKCAnVG90YWwgVGltZScgKSwgdG90YWxfdGltZTogJzAnIH0gfTtcblx0XHRcdHRoaXMuYnVpbGRTdWJHcmlkc0RhdGEoIGFjY3VtdWxhdGVkX3RpbWUsICdwYXlfcGVyaW9kJywgdGhpcy5hY2N1bXVsYXRlZF90b3RhbF9ncmlkX3NvdXJjZV9tYXAsIHRoaXMuYWNjdW11bGF0ZWRfdG90YWxfZ3JpZF9zb3VyY2UsICdhY2N1bXVsYXRlZF90aW1lJyApO1xuXHRcdH1cblxuXHRcdGlmICggR2xvYmFsLmlzU2V0KCBwcmVtaXVtX3RpbWUgKSApIHtcblx0XHRcdHRoaXMuYnVpbGRTdWJHcmlkc0RhdGEoIHByZW1pdW1fdGltZSwgJ3BheV9wZXJpb2QnLCB0aGlzLmFjY3VtdWxhdGVkX3RvdGFsX2dyaWRfc291cmNlX21hcCwgdGhpcy5hY2N1bXVsYXRlZF90b3RhbF9ncmlkX3NvdXJjZSwgJ3ByZW1pdW1fdGltZScgKTtcblx0XHR9XG5cblx0XHRpZiAoIEdsb2JhbC5pc1NldCggYWJzZW5jZV90aW1lICkgKSB7XG5cdFx0XHR0aGlzLmJ1aWxkU3ViR3JpZHNEYXRhKCBhYnNlbmNlX3RpbWUsICdwYXlfcGVyaW9kJywgdGhpcy5hY2N1bXVsYXRlZF90b3RhbF9ncmlkX3NvdXJjZV9tYXAsIHRoaXMuYWNjdW11bGF0ZWRfdG90YWxfZ3JpZF9zb3VyY2UsICdhYnNlbmNlX3RpbWUnICk7XG5cdFx0fVxuXG5cdFx0Ly9CdWlsZCBBY2N1bXVsYXRlZCBUb3RhbCBHcmlkIFBheV9wZXJpb2QgY29sdW1uIGRhdGEgZW5kXG5cblx0XHR2YXIgY29sdW1uX2xlbiA9IHRoaXMudGltZXNoZWV0X2NvbHVtbnMubGVuZ3RoO1xuXHRcdGFjY3VtdWxhdGVkX3RpbWUgPSB7IHRvdGFsOiB7IGxhYmVsOiAkLmkxOG4uXyggJ1RvdGFsIFRpbWUnICksIHRvdGFsX3RpbWU6ICcwJyB9IH07XG5cdFx0dmFyIGRhdGVfc3RyaW5nO1xuXHRcdHZhciBkYXRlO1xuXG5cdFx0Ly9TdGFydCBvbiBjb2x1bW4gdGhhdCBpcyByaWdodCBiZWZvcmUgdGhlIDcgZGF5cyBvZiB0aGUgd2Vlay5cblx0XHR2YXIgc3RhcnQgPSAoIGNvbHVtbl9sZW4gLSA3IC0gMSApO1xuXHRcdGZvciAoIHZhciBpID0gc3RhcnQ7IGkgPCBjb2x1bW5fbGVuOyBpKysgKSB7XG5cdFx0XHR0aGlzLmJ1aWxkU3ViR3JpZHNEYXRhKCBhY2N1bXVsYXRlZF90aW1lLCBkYXRlX3N0cmluZywgdGhpcy5hY2N1bXVsYXRlZF90aW1lX3NvdXJjZV9tYXAsIHRoaXMuYWNjdW11bGF0ZWRfdGltZV9zb3VyY2UsICdhY2N1bXVsYXRlZF90aW1lJyApO1xuXHRcdH1cblx0XHR0aGlzLmJ1aWxkU3ViR3JpZHNEYXRhKCBhY2N1bXVsYXRlZF90aW1lLCAnd2VlaycsIHRoaXMuYWNjdW11bGF0ZWRfdG90YWxfZ3JpZF9zb3VyY2VfbWFwLCB0aGlzLmFjY3VtdWxhdGVkX3RvdGFsX2dyaWRfc291cmNlLCAnYWNjdW11bGF0ZWRfdGltZScgKTtcblxuXHRcdGZvciAoIHZhciBrZXkgaW4gYWNjdW11bGF0ZWRfdXNlcl9kYXRlX3RvdGFsX2RhdGEgKSB7XG5cblx0XHRcdC8vQnVpbGQgQWNjdW11bGF0ZWQgVG90YWwgR3JpZCB3ZWVrIGNvbHVtbiBkYXRhXG5cdFx0XHRpZiAoIGtleSA9PT0gJ3RvdGFsJyApIHtcblx0XHRcdFx0dmFyIHRvdGFsX3Jlc3VsdCA9IGFjY3VtdWxhdGVkX3VzZXJfZGF0ZV90b3RhbF9kYXRhLnRvdGFsO1xuXHRcdFx0XHRhY2N1bXVsYXRlZF90aW1lID0gdG90YWxfcmVzdWx0LmFjY3VtdWxhdGVkX3RpbWU7XG5cdFx0XHRcdHByZW1pdW1fdGltZSA9IHRvdGFsX3Jlc3VsdC5wcmVtaXVtX3RpbWU7XG5cdFx0XHRcdGFic2VuY2VfdGltZSA9IHRvdGFsX3Jlc3VsdC5hYnNlbmNlX3RpbWVfdGFrZW47XG5cblx0XHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoIGFjY3VtdWxhdGVkX3RpbWUgKSApIHtcblxuXHRcdFx0XHRcdHRoaXMuYnVpbGRTdWJHcmlkc0RhdGEoIGFjY3VtdWxhdGVkX3RpbWUsICd3ZWVrJywgdGhpcy5hY2N1bXVsYXRlZF90b3RhbF9ncmlkX3NvdXJjZV9tYXAsIHRoaXMuYWNjdW11bGF0ZWRfdG90YWxfZ3JpZF9zb3VyY2UsICdhY2N1bXVsYXRlZF90aW1lJyApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoIHByZW1pdW1fdGltZSApICkge1xuXHRcdFx0XHRcdHRoaXMuYnVpbGRTdWJHcmlkc0RhdGEoIHByZW1pdW1fdGltZSwgJ3dlZWsnLCB0aGlzLmFjY3VtdWxhdGVkX3RvdGFsX2dyaWRfc291cmNlX21hcCwgdGhpcy5hY2N1bXVsYXRlZF90b3RhbF9ncmlkX3NvdXJjZSwgJ3ByZW1pdW1fdGltZScgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCBhYnNlbmNlX3RpbWUgKSApIHtcblx0XHRcdFx0XHR0aGlzLmJ1aWxkU3ViR3JpZHNEYXRhKCBhYnNlbmNlX3RpbWUsICd3ZWVrJywgdGhpcy5hY2N1bXVsYXRlZF90b3RhbF9ncmlkX3NvdXJjZV9tYXAsIHRoaXMuYWNjdW11bGF0ZWRfdG90YWxfZ3JpZF9zb3VyY2UsICdhYnNlbmNlX3RpbWUnICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0Ly9CdWlsZCBBY2N1bXVsYXRlZCBUb3RhbCBHcmlkIHdlZWsgY29sdW1uIGRhdGEgZW5kXG5cdFx0XHQvL0J1aWxkIGFsbCBzdWIgZ3JpZHMgZGF0YVxuXHRcdFx0Ly9FcnJvcjogVW5jYXVnaHQgVHlwZUVycm9yOiBDYW5ub3QgcmVhZCBwcm9wZXJ0eSAnZm9ybWF0JyBvZiBudWxsIGluIGludGVyZmFjZS9odG1sNS8jIW09VGltZVNoZWV0JmRhdGU9MjAxNTExMTcmdXNlcl9pZD0zNTM2NyZzaG93X3dhZ2U9MCBsaW5lIDQ0Nzhcblx0XHRcdGRhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCBrZXkgKTtcblx0XHRcdGlmICggIWRhdGUgKSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXHRcdFx0ZGF0ZV9zdHJpbmcgPSBkYXRlLmZvcm1hdCggdGhpcy5mdWxsX2Zvcm1hdCApO1xuXG5cdFx0XHQvL0Vycm9yOiBVbmNhdWdodCBUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnR5ICdhY2N1bXVsYXRlZF90aW1lJyBvZiB1bmRlZmluZWRcblx0XHRcdGlmICggdHlwZW9mIGFjY3VtdWxhdGVkX3VzZXJfZGF0ZV90b3RhbF9kYXRhW2tleV0gIT0gJ3VuZGVmaW5lZCcgKSB7XG5cdFx0XHRcdGFjY3VtdWxhdGVkX3RpbWUgPSBhY2N1bXVsYXRlZF91c2VyX2RhdGVfdG90YWxfZGF0YVtrZXldLmFjY3VtdWxhdGVkX3RpbWU7XG5cdFx0XHRcdHZhciBicmFuY2hfdGltZSA9IGFjY3VtdWxhdGVkX3VzZXJfZGF0ZV90b3RhbF9kYXRhW2tleV0uYnJhbmNoX3RpbWU7XG5cdFx0XHRcdHZhciBkZXBhcnRtZW50X3RpbWUgPSBhY2N1bXVsYXRlZF91c2VyX2RhdGVfdG90YWxfZGF0YVtrZXldLmRlcGFydG1lbnRfdGltZTtcblx0XHRcdFx0dmFyIGpvYl90aW1lID0gYWNjdW11bGF0ZWRfdXNlcl9kYXRlX3RvdGFsX2RhdGFba2V5XS5qb2JfdGltZTtcblx0XHRcdFx0dmFyIGpvYl9pdGVtX3RpbWUgPSBhY2N1bXVsYXRlZF91c2VyX2RhdGVfdG90YWxfZGF0YVtrZXldLmpvYl9pdGVtX3RpbWU7XG5cdFx0XHRcdHZhciBwdW5jaF90YWdfdGltZSA9IGFjY3VtdWxhdGVkX3VzZXJfZGF0ZV90b3RhbF9kYXRhW2tleV0ucHVuY2hfdGFnX3RpbWU7XG5cdFx0XHRcdHByZW1pdW1fdGltZSA9IGFjY3VtdWxhdGVkX3VzZXJfZGF0ZV90b3RhbF9kYXRhW2tleV0ucHJlbWl1bV90aW1lO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0RGVidWcuVGV4dCggJ0VSUk9SOiBhY2N1bXVsYXRlZF91c2VyX2RhdGVfdG90YWxfZGF0YVtrZXldIGlzIG51bGwgb3IgdW5kZWZpbmVkIScsICdUaW1lc2hlZXRWaWV3Q29udHJvbGxlci5qcycsICdUaW1lc2hlZXRWaWV3Q29udHJvbGxlcicsICdidWlsZFN1YkdyaWRzU291cmNlJywgMSApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggYWNjdW11bGF0ZWRfdGltZSApICkge1xuXHRcdFx0XHR0aGlzLmJ1aWxkU3ViR3JpZHNEYXRhKCBhY2N1bXVsYXRlZF90aW1lLCBkYXRlX3N0cmluZywgdGhpcy5hY2N1bXVsYXRlZF90aW1lX3NvdXJjZV9tYXAsIHRoaXMuYWNjdW11bGF0ZWRfdGltZV9zb3VyY2UsICdhY2N1bXVsYXRlZF90aW1lJyApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggYnJhbmNoX3RpbWUgKSApIHtcblxuXHRcdFx0XHR0aGlzLmJ1aWxkU3ViR3JpZHNEYXRhKCBicmFuY2hfdGltZSwgZGF0ZV9zdHJpbmcsIHRoaXMuYnJhbmNoX3NvdXJjZV9tYXAsIHRoaXMuYnJhbmNoX3NvdXJjZSwgJ2JyYW5jaF90aW1lJyApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggZGVwYXJ0bWVudF90aW1lICkgKSB7XG5cblx0XHRcdFx0dGhpcy5idWlsZFN1YkdyaWRzRGF0YSggZGVwYXJ0bWVudF90aW1lLCBkYXRlX3N0cmluZywgdGhpcy5kZXBhcnRtZW50X3NvdXJjZV9tYXAsIHRoaXMuZGVwYXJ0bWVudF9zb3VyY2UsICdkZXBhcnRtZW50X3RpbWUnICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCBqb2JfdGltZSApICkge1xuXG5cdFx0XHRcdHRoaXMuYnVpbGRTdWJHcmlkc0RhdGEoIGpvYl90aW1lLCBkYXRlX3N0cmluZywgdGhpcy5qb2Jfc291cmNlX21hcCwgdGhpcy5qb2Jfc291cmNlLCAnam9iX3RpbWUnICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCBqb2JfaXRlbV90aW1lICkgKSB7XG5cblx0XHRcdFx0dGhpcy5idWlsZFN1YkdyaWRzRGF0YSggam9iX2l0ZW1fdGltZSwgZGF0ZV9zdHJpbmcsIHRoaXMuam9iX2l0ZW1fc291cmNlX21hcCwgdGhpcy5qb2JfaXRlbV9zb3VyY2UsICdqb2JfaXRlbV90aW1lJyApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggcHVuY2hfdGFnX3RpbWUgKSApIHtcblxuXHRcdFx0XHR0aGlzLmJ1aWxkU3ViR3JpZHNEYXRhKCBwdW5jaF90YWdfdGltZSwgZGF0ZV9zdHJpbmcsIHRoaXMucHVuY2hfdGFnX3NvdXJjZV9tYXAsIHRoaXMucHVuY2hfdGFnX3NvdXJjZSwgJ3B1bmNoX3RhZ190aW1lJyApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggcHJlbWl1bV90aW1lICkgKSB7XG5cblx0XHRcdFx0dGhpcy5idWlsZFN1YkdyaWRzRGF0YSggcHJlbWl1bV90aW1lLCBkYXRlX3N0cmluZywgdGhpcy5wcmVtaXVtX3NvdXJjZV9tYXAsIHRoaXMucHJlbWl1bV9zb3VyY2UsICdwcmVtaXVtX3RpbWUnICk7XG5cdFx0XHR9XG5cblx0XHR9XG5cblx0XHR0aGlzLnNvcnRBY2N1bXVsYXRlZFRvdGFsRGF0YSgpO1xuXHRcdHRoaXMuc29ydEFjY3VtdWxhdGVkVGltZURhdGEoKTtcblxuXHRcdGlmICggR2xvYmFsLmlzU2V0KCBtZWFsX2FuZF9icmVha190b3RhbF9kYXRhICkgKSB7XG5cblx0XHRcdGZvciAoIHZhciBrZXkgaW4gbWVhbF9hbmRfYnJlYWtfdG90YWxfZGF0YSApIHtcblx0XHRcdFx0Ly8gRXJyb3I6IFVuY2F1Z2h0IFR5cGVFcnJvcjogQ2Fubm90IHJlYWQgcHJvcGVydHkgJ2Zvcm1hdCcgb2YgbnVsbCBpbiBpbnRlcmZhY2UvaHRtbDUvIyFtPVRpbWVTaGVldCZkYXRlPTIwMTUxMTE5JnVzZXJfaWQ9NTUzMzgmc2hvd193YWdlPTAgbGluZSA0NTI3XG5cdFx0XHRcdGRhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCBrZXkgKTtcblx0XHRcdFx0aWYgKCAhZGF0ZSApIHtcblx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRkYXRlX3N0cmluZyA9IGRhdGUuZm9ybWF0KCB0aGlzLmZ1bGxfZm9ybWF0ICk7XG5cblx0XHRcdFx0dGhpcy5idWlsZEJyZWFrQW5kTHVuY2hEYXRhKCBtZWFsX2FuZF9icmVha190b3RhbF9kYXRhW2tleV0sIGRhdGVfc3RyaW5nICk7XG5cblx0XHRcdH1cblxuXHRcdH1cblx0fVxuXG5cdGJ1aWxkQnJlYWtBbmRMdW5jaERhdGEoIGFycmF5LCBkYXRlX3N0cmluZyApIHtcblx0XHR2YXIgcm93O1xuXHRcdGZvciAoIHZhciBrZXkgaW4gYXJyYXkgKSB7XG5cdFx0XHRpZiAoICF0aGlzLmFjY3VtdWxhdGVkX3RpbWVfc291cmNlX21hcFtrZXldICkge1xuXHRcdFx0XHRyb3cgPSB7fTtcblx0XHRcdFx0cm93LnB1bmNoX2luZm8gPSBhcnJheVtrZXldLmJyZWFrX25hbWU7XG5cdFx0XHRcdGFycmF5W2tleV0ua2V5ID0ga2V5O1xuXHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmddID0gR2xvYmFsLmdldFRpbWVVbml0KCBhcnJheVtrZXldLnRvdGFsX3RpbWUgKSArICcgKCcgKyBhcnJheVtrZXldLnRvdGFsX2JyZWFrcyArICcpJztcblx0XHRcdFx0cm93W2RhdGVfc3RyaW5nICsgJ19kYXRhJ10gPSBhcnJheVtrZXldO1xuXHRcdFx0XHR0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZS5wdXNoKCByb3cgKTtcblx0XHRcdFx0dGhpcy5hY2N1bXVsYXRlZF90aW1lX3NvdXJjZV9tYXBba2V5XSA9IHJvdztcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHJvdyA9IHRoaXMuYWNjdW11bGF0ZWRfdGltZV9zb3VyY2VfbWFwW2tleV07XG5cdFx0XHRcdGlmICggIXJvd1tkYXRlX3N0cmluZ10gKSB7XG5cdFx0XHRcdFx0YXJyYXlba2V5XS5rZXkgPSBrZXk7XG5cdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nXSA9IEdsb2JhbC5nZXRUaW1lVW5pdCggYXJyYXlba2V5XS50b3RhbF90aW1lICkgKyAnICgnICsgYXJyYXlba2V5XS50b3RhbF9icmVha3MgKyAnKSc7XG5cblx0XHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmcgKyAnX2RhdGEnXSA9IGFycmF5W2tleV07XG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGFkZENlbGxDb3VudCgga2V5ICkge1xuXHRcdHN3aXRjaCAoIGtleSApIHtcblx0XHRcdGNhc2UgJ2JyYW5jaF90aW1lJzpcblx0XHRcdFx0dGhpcy5icmFuY2hfY2VsbF9jb3VudCA9IHRoaXMuYnJhbmNoX2NlbGxfY291bnQgKyAxO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ2RlcGFydG1lbnRfdGltZSc6XG5cdFx0XHRcdHRoaXMuZGVwYXJ0bWVudF9jZWxsX2NvdW50ID0gdGhpcy5kZXBhcnRtZW50X2NlbGxfY291bnQgKyAxO1xuXHRcdFx0XHRicmVhaztcblxuXHRcdFx0Y2FzZSAncHJlbWl1bV90aW1lJzpcblx0XHRcdFx0dGhpcy5wcmVtaXVtX2NlbGxfY291bnQgPSB0aGlzLnByZW1pdW1fY2VsbF9jb3VudCArIDE7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnam9iX3RpbWUnOlxuXHRcdFx0XHR0aGlzLmpvYl9jZWxsX2NvdW50ID0gdGhpcy5qb2JfY2VsbF9jb3VudCArIDE7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnam9iX2l0ZW1fdGltZSc6XG5cdFx0XHRcdHRoaXMudGFza19jZWxsX2NvdW50ID0gdGhpcy50YXNrX2NlbGxfY291bnQgKyAxO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3B1bmNoX3RhZ190aW1lJzpcblx0XHRcdFx0dGhpcy5wdW5jaF90YWdfY2VsbF9jb3VudCA9IHRoaXMucHVuY2hfdGFnX2NlbGxfY291bnQgKyAxO1xuXHRcdFx0XHRicmVhaztcblxuXHRcdH1cblx0fVxuXG5cdGJ1aWxkU3ViR3JpZHNEYXRhKCBhcnJheSwgZGF0ZV9zdHJpbmcsIG1hcCwgcmVzdWx0X2FycmF5LCBwYXJlbnRfa2V5ICkge1xuXHRcdHZhciByb3c7XG5cdFx0dmFyIG1hcmtlZF9yZWd1bGFyX3JvdyA9IGZhbHNlOyAvL09ubHkgbWFyayB0aGUgZmlyc3QgcmVndWxhciB0aW1lIHJvdywgYXMgdGhhdHMgd2hlcmUgdGhlIGJvbGQgdG9wLWxpbmUgaXMgZ29pbmcgdG8gZ28uXG5cdFx0Zm9yICggdmFyIGtleSBpbiBhcnJheSApIHtcblx0XHRcdGlmICggIW1hcFtrZXldICkge1xuXHRcdFx0XHRyb3cgPSB7fTtcblx0XHRcdFx0cm93LnBhcmVudF9rZXkgPSBwYXJlbnRfa2V5O1xuXHRcdFx0XHRyb3cua2V5ID0ga2V5O1xuXG5cdFx0XHRcdGlmICggcGFyZW50X2tleSA9PT0gJ2FjY3VtdWxhdGVkX3RpbWUnICkge1xuXG5cdFx0XHRcdFx0aWYgKCBrZXkgPT09ICd0b3RhbCcgfHwga2V5ID09PSAnd29ya2VkX3RpbWUnICkge1xuXHRcdFx0XHRcdFx0cm93LnR5cGUgPSBUaW1lU2hlZXRWaWV3Q29udHJvbGxlci5UT1RBTF9ST1c7XG5cdFx0XHRcdFx0fSBlbHNlIGlmICggbWFya2VkX3JlZ3VsYXJfcm93ID09IGZhbHNlICYmIGtleS5pbmRleE9mKCAncmVndWxhcl90aW1lJyApID09PSAwICkge1xuXHRcdFx0XHRcdFx0cm93LnR5cGUgPSBUaW1lU2hlZXRWaWV3Q29udHJvbGxlci5SRUdVTEFSX1JPVztcblx0XHRcdFx0XHRcdG1hcmtlZF9yZWd1bGFyX3JvdyA9IHRydWU7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHJvdy50eXBlID0gVGltZVNoZWV0Vmlld0NvbnRyb2xsZXIuQUNDVU1VTEFURURfVElNRV9ST1c7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKCBhcnJheVtrZXldLm92ZXJyaWRlICkge1xuXHRcdFx0XHRcdFx0cm93LmlzX292ZXJyaWRlX3JvdyA9IHRydWU7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH0gZWxzZSBpZiAoIHBhcmVudF9rZXkgPT09ICdwcmVtaXVtX3RpbWUnICkge1xuXHRcdFx0XHRcdHJvdy50eXBlID0gVGltZVNoZWV0Vmlld0NvbnRyb2xsZXIuUFJFTUlVTV9ST1c7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIHRoaXMuYWNjbXVsYXRlZF9vcmRlcl9tYXBba2V5XSApIHtcblx0XHRcdFx0XHRyb3cub3JkZXIgPSB0aGlzLmFjY211bGF0ZWRfb3JkZXJfbWFwW2tleV07XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyb3cucHVuY2hfaW5mbyA9IGFycmF5W2tleV0ubGFiZWw7XG5cblx0XHRcdFx0dmFyIGtleV9hcnJheSA9IGtleS5zcGxpdCggJ18nICk7XG5cdFx0XHRcdHZhciBub19pZCA9IGZhbHNlO1xuXHRcdFx0XHRpZiAoIGtleV9hcnJheS5sZW5ndGggPiAxICYmIGtleV9hcnJheVsxXSA9PSAnMCcgKSB7XG5cdFx0XHRcdFx0bm9faWQgPSB0cnVlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0YXJyYXlba2V5XS5rZXkgPSBrZXk7XG5cdFx0XHRcdHJvd1tkYXRlX3N0cmluZ10gPSBHbG9iYWwuZ2V0VGltZVVuaXQoIGFycmF5W2tleV0udG90YWxfdGltZSApO1xuXHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmcgKyAnX2RhdGEnXSA9IGFycmF5W2tleV07XG5cblx0XHRcdFx0Ly9pZiBpZCA9PSAwLCBwdXQgdGhlIHJvdyBhcyBmaXJzdCByb3cuXG5cdFx0XHRcdGlmICggbm9faWQgKSB7XG5cdFx0XHRcdFx0cmVzdWx0X2FycmF5LnVuc2hpZnQoIHJvdyApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHJlc3VsdF9hcnJheS5wdXNoKCByb3cgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdG1hcFtrZXldID0gcm93O1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cm93ID0gbWFwW2tleV07XG5cdFx0XHRcdGlmICggcm93W2RhdGVfc3RyaW5nXSAmJiBrZXkgPT09ICd0b3RhbCcgKSB7IC8vT3ZlcnJpZGUgdG90YWwgY2VsbCBkYXRhIHNpbmNlIHdlIHNldCBhbGwgdG8gMDA6MDAgYXQgYmVnaW5uaW5nXG5cdFx0XHRcdFx0YXJyYXlba2V5XS5rZXkgPSBrZXk7XG5cdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nXSA9IEdsb2JhbC5nZXRUaW1lVW5pdCggYXJyYXlba2V5XS50b3RhbF90aW1lICk7XG5cdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nICsgJ19kYXRhJ10gPSBhcnJheVtrZXldO1xuXG5cdFx0XHRcdFx0aWYgKCByb3cucGFyZW50X2tleSA9PT0gJ2FjY3VtdWxhdGVkX3RpbWUnICkge1xuXHRcdFx0XHRcdFx0aWYgKCBhcnJheVtrZXldLm92ZXJyaWRlICkge1xuXHRcdFx0XHRcdFx0XHRyb3cuaXNfb3ZlcnJpZGVfcm93ID0gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRcdGFycmF5W2tleV0ua2V5ID0ga2V5O1xuXHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZ10gPSBHbG9iYWwuZ2V0VGltZVVuaXQoIGFycmF5W2tleV0udG90YWxfdGltZSApO1xuXHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZyArICdfZGF0YSddID0gYXJyYXlba2V5XTtcblxuXHRcdFx0XHRcdGlmICggcm93LnBhcmVudF9rZXkgPT09ICdhY2N1bXVsYXRlZF90aW1lJyApIHtcblx0XHRcdFx0XHRcdGlmICggYXJyYXlba2V5XS5vdmVycmlkZSApIHtcblx0XHRcdFx0XHRcdFx0cm93LmlzX292ZXJyaWRlX3JvdyA9IHRydWU7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdH1cblxuXHRcdFx0dGhpcy5hZGRDZWxsQ291bnQoIHBhcmVudF9rZXkgKTtcblx0XHR9XG5cdH1cblxuXHR0aW1lU2hlZXRWZXJpZnlQZXJtaXNzaW9uVmFsaWRhdGUoKSB7XG5cdFx0aWYgKCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggJ3B1bmNoJywgJ3ZlcmlmeV90aW1lX3NoZWV0JyApICYmXG5cdFx0XHR0aGlzLnRpbWVzaGVldF92ZXJpZnlfZGF0YS5oYXNPd25Qcm9wZXJ0eSggJ3BheV9wZXJpb2RfdmVyaWZ5X3R5cGVfaWQnICkgJiZcblx0XHRcdHRoaXMudGltZXNoZWV0X3ZlcmlmeV9kYXRhLnBheV9wZXJpb2RfdmVyaWZ5X3R5cGVfaWQgIT0gMTAgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRidWlsZFZlcmlmaWNhdGlvbkdyaWRTb3VyY2UoKSB7XG5cdFx0dGhpcy52ZXJpZmljYXRpb25fZ3JpZF9zb3VyY2UgPSBbXTtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciB2ZXJpZnlfYWN0aW9uX2JhciA9ICQoIHRoaXMuZWwgKS5maW5kKCAnLnZlcmlmaWNhdGlvbi1hY3Rpb24tYmFyJyApO1xuXHRcdHZhciB2ZXJpZnlfZ3JpZF9kaXYgPSAkKCB0aGlzLmVsICkuZmluZCggJy52ZXJpZmljYXRpb24tZ3JpZC1kaXYnICk7XG5cdFx0dmFyIHZlcmlmeV9idG4gPSAkKCB0aGlzLmVsICkuZmluZCggJy52ZXJpZnktYnV0dG9uJyApO1xuXHRcdHZhciB2ZXJpZnlfdGl0bGUgPSAkKCB0aGlzLmVsICkuZmluZCggJy52ZXJpZmljYXRpb24tZ3JpZC10aXRsZScgKTtcblx0XHR2YXIgdmVyaWZ5X2RlcyA9ICQoIHRoaXMuZWwgKS5maW5kKCAnLnZlcmlmeS1kZXNjcmlwdGlvbicgKTtcblxuXHRcdGlmICggdGhpcy50aW1lU2hlZXRWZXJpZnlQZXJtaXNzaW9uVmFsaWRhdGUoKSAmJlxuXHRcdFx0R2xvYmFsLmlzU2V0KCB0aGlzLnRpbWVzaGVldF92ZXJpZnlfZGF0YS5wYXlfcGVyaW9kX2lkICkgJiZcblx0XHRcdEdsb2JhbC5pc1NldCggdGhpcy50aW1lc2hlZXRfdmVyaWZ5X2RhdGEucGF5X3BlcmlvZF92ZXJpZnlfdHlwZV9pZCApICYmXG5cdFx0XHR0aGlzLnRpbWVzaGVldF92ZXJpZnlfZGF0YS5wYXlfcGVyaW9kX3ZlcmlmeV90eXBlX2lkICE9PSAnMTAnICkge1xuXG5cdFx0XHRpZiAoICF0aGlzLnRpbWVzaGVldF92ZXJpZnlfZGF0YS5kaXNwbGF5X3ZlcmlmeV9idXR0b24gKSB7XG5cdFx0XHRcdHZlcmlmeV9idG4uY3NzKCAnZGlzcGxheScsICdub25lJyApO1xuXHRcdFx0XHR2ZXJpZnlfdGl0bGUuY3NzKCAnZGlzcGxheScsICdub25lJyApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dmVyaWZ5X2J0bi5jc3MoICdkaXNwbGF5JywgJ2lubGluZS1ibG9jaycgKTtcblx0XHRcdFx0dmVyaWZ5X3RpdGxlLmNzcyggJ2Rpc3BsYXknLCAnYmxvY2snICk7XG5cdFx0XHR9XG5cblx0XHRcdHZlcmlmeV9ncmlkX2Rpdi5jc3MoICdkaXNwbGF5JywgJ2Jsb2NrJyApO1xuXHRcdFx0dmVyaWZ5X2Rlcy50ZXh0KCB0aGlzLnRpbWVzaGVldF92ZXJpZnlfZGF0YS52ZXJpZmljYXRpb25fc3RhdHVzX2Rpc3BsYXkgKTtcblxuXHRcdFx0aWYgKCB0aGlzLnRpbWVzaGVldF92ZXJpZnlfZGF0YS52ZXJpZmljYXRpb25fYm94X2NvbG9yICkge1xuXHRcdFx0XHR2ZXJpZnlfYWN0aW9uX2Jhci5jc3MoICdiYWNrZ3JvdW5kJywgdGhpcy50aW1lc2hlZXRfdmVyaWZ5X2RhdGEudmVyaWZpY2F0aW9uX2JveF9jb2xvciApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dmVyaWZ5X2FjdGlvbl9iYXIuY3NzKCAnYmFja2dyb3VuZCcsICcjZmZmZmZmJyApO1xuXHRcdFx0fVxuXG5cdFx0XHR2ZXJpZnlfYnRuLnVuYmluZCggJ2NsaWNrJyApLmJpbmQoICdjbGljaycsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRUQWxlcnRNYW5hZ2VyLnNob3dDb25maXJtQWxlcnQoICR0aGlzLnRpbWVzaGVldF92ZXJpZnlfZGF0YS52ZXJpZmljYXRpb25fY29uZmlybWF0aW9uX21lc3NhZ2UsICcnLCBmdW5jdGlvbiggZmxhZyApIHtcblxuXHRcdFx0XHRcdGlmICggZmxhZyApIHtcblx0XHRcdFx0XHRcdCR0aGlzLmFwaV90aW1lc2hlZXQudmVyaWZ5VGltZVNoZWV0KCAkdGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpLCAkdGhpcy50aW1lc2hlZXRfdmVyaWZ5X2RhdGEucGF5X3BlcmlvZF9pZCxcblxuXHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHRcdGlmICggcmVzdWx0LmlzVmFsaWQoKSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0JHRoaXMuc2VhcmNoKCk7XG5cdFx0XHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRUQWxlcnRNYW5hZ2VyLnNob3dFcnJvckFsZXJ0KCByZXN1bHQgKTtcblx0XHRcdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH0gKTtcblx0XHRcdH0gKTtcblxuXHRcdH0gZWxzZSB7XG5cblx0XHRcdHZlcmlmeV9idG4uY3NzKCAnZGlzcGxheScsICdub25lJyApO1xuXHRcdFx0dmVyaWZ5X2dyaWRfZGl2LmNzcyggJ2Rpc3BsYXknLCAnbm9uZScgKTtcblx0XHRcdHJldHVybjtcblxuXHRcdH1cblxuXHRcdHZhciB2ZXJpZmljYXRpb25fZGF0YSA9IHRoaXMudGltZXNoZWV0X3ZlcmlmeV9kYXRhLnZlcmlmaWNhdGlvbl93aW5kb3dfZGF0ZXMuc3RhcnQgKyAnICcgKyAkLmkxOG4uXyggJ3RvJyApICsgJyAnICsgdGhpcy50aW1lc2hlZXRfdmVyaWZ5X2RhdGEudmVyaWZpY2F0aW9uX3dpbmRvd19kYXRlcy5lbmQ7XG5cblx0XHR2YXIgcGF5X3BlcmlvZF9kYXRhID0gdGhpcy5wYXlfcGVyaW9kX2hlYWRlcjtcblxuXHRcdHRoaXMudmVyaWZpY2F0aW9uX2dyaWRfc291cmNlLnB1c2goIHsgcGF5X3BlcmlvZDogcGF5X3BlcmlvZF9kYXRhLCB2ZXJpZmljYXRpb246IHZlcmlmaWNhdGlvbl9kYXRhIH0gKTtcblxuXHRcdC8vVGhpcyBjYW4gYmUgY2FsbGVkIGJ5IGNsaWNraW5nIG9uIGEgZGlmZmVyZW50IGRhdGUgY29sdW1uIGhlYWRlciwgb3IgdXNpbmcgdGhlIHRvcCByaWdodCByZWZyZXNoIGljb24sIHNvIG5vdCBhbGwgZ3JpZHMgYXJlIHJlc2l6ZWQgYXQgdGhhdCB0aW1lIG5lY2Vzc2FyaWx5LlxuXHRcdCR0aGlzLnNldEdyaWRIZWlnaHQoICd2ZXJpZmljYXRpb25fZ3JpZCcgKTtcblx0fVxuXG5cdGJ1aWxkUHVuY2hOb3RlR3JpZFNvdXJjZSgpIHtcblx0XHR0aGlzLnB1bmNoX25vdGVfZ3JpZF9zb3VyY2UgPSBbXTtcblx0XHR2YXIgcHVuY2hfYXJyYXkgPSB0aGlzLmZ1bGxfdGltZXNoZWV0X2RhdGEucHVuY2hfZGF0YTtcblx0XHR2YXIgYWJzZW5jZV9hcnJheSA9IHRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YS51c2VyX2RhdGVfdG90YWxfZGF0YTtcblx0XHR2YXIgbGVuID0gcHVuY2hfYXJyYXkubGVuZ3RoO1xuXHRcdHZhciBsZW4xID0gYWJzZW5jZV9hcnJheS5sZW5ndGg7XG5cdFx0dmFyIGxhc3RfY29udHJvbF9pZCA9ICcnO1xuXHRcdHZhciBkYXRlO1xuXHRcdHZhciBkYXRlX3N0cmluZztcblx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdHZhciBwdW5jaCA9IHB1bmNoX2FycmF5W2ldO1xuXHRcdFx0ZGF0ZSA9IEdsb2JhbC5zdHJUb0RhdGUoIHB1bmNoLmRhdGVfc3RhbXAgKTtcblx0XHRcdGRhdGVfc3RyaW5nID0gZGF0ZS5mb3JtYXQoKTtcblx0XHRcdGlmICggcHVuY2gubm90ZSAmJiBwdW5jaC5wdW5jaF9jb250cm9sX2lkICE9PSBsYXN0X2NvbnRyb2xfaWQgKSB7XG5cdFx0XHRcdHRoaXMucHVuY2hfbm90ZV9hY2NvdW50ID0gdGhpcy5wdW5jaF9ub3RlX2FjY291bnQgKyAxO1xuXHRcdFx0XHR0aGlzLnB1bmNoX25vdGVfZ3JpZF9zb3VyY2UucHVzaCggeyBub3RlOiBkYXRlX3N0cmluZyArICcgQCAnICsgcHVuY2gucHVuY2hfdGltZSArICc6ICcgKyBwdW5jaC5ub3RlLnJlcGxhY2UoIC9cXG4vZywgJyAnICkgfSApO1xuXHRcdFx0XHRsYXN0X2NvbnRyb2xfaWQgPSBwdW5jaC5wdW5jaF9jb250cm9sX2lkO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRmb3IgKCB2YXIgeCA9IDA7IHggPCBsZW4xOyB4KysgKSB7XG5cdFx0XHR2YXIgYWJzZW5jZSA9IGFic2VuY2VfYXJyYXlbeF07XG5cdFx0XHRkYXRlID0gR2xvYmFsLnN0clRvRGF0ZSggYWJzZW5jZS5kYXRlX3N0YW1wICk7XG5cdFx0XHRkYXRlX3N0cmluZyA9IGRhdGUuZm9ybWF0KCk7XG5cdFx0XHRpZiAoIGFic2VuY2Uubm90ZSApIHtcblx0XHRcdFx0dGhpcy5wdW5jaF9ub3RlX2FjY291bnQgPSB0aGlzLnB1bmNoX25vdGVfYWNjb3VudCArIDE7XG5cdFx0XHRcdHRoaXMucHVuY2hfbm90ZV9ncmlkX3NvdXJjZS5wdXNoKCB7IG5vdGU6IGRhdGVfc3RyaW5nICsgJyBAICcgKyBHbG9iYWwuZ2V0VGltZVVuaXQoIGFic2VuY2UudG90YWxfdGltZSApICsgJzogJyArIGFic2VuY2Uubm90ZS5yZXBsYWNlKCAvXFxuL2csICcgJyApIH0gKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRidWlsZEFic2VuY2VTb3VyY2UoKSB7XG5cblx0XHR2YXIgbWFwID0ge307XG5cdFx0dGhpcy5hYnNlbmNlX3NvdXJjZSA9IFtdO1xuXHRcdHRoaXMuYWJzZW5jZV9vcmlnaW5hbF9zb3VyY2UgPSBbXTtcblx0XHR2YXIgYWJzZW5jZV9hcnJheSA9IHRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YS51c2VyX2RhdGVfdG90YWxfZGF0YTtcblx0XHR2YXIgbGVuID0gYWJzZW5jZV9hcnJheS5sZW5ndGg7XG5cdFx0dmFyIHJvdztcblx0XHR2YXIgcm93X2lkX2NvdW50ZXIgPSAxO1xuXG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHR2YXIgYWJzZW5jZSA9IGFic2VuY2VfYXJyYXlbaV07XG5cblx0XHRcdGlmICggYWJzZW5jZS5vYmplY3RfdHlwZV9pZCAhPSA1MCApIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuYWJzZW5jZV9vcmlnaW5hbF9zb3VyY2UucHVzaCggYWJzZW5jZSApO1xuXHRcdFx0dmFyIGRhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCBhYnNlbmNlLmRhdGVfc3RhbXAgKTtcblx0XHRcdHZhciBkYXRlX3N0cmluZyA9IGRhdGUuZm9ybWF0KCB0aGlzLmZ1bGxfZm9ybWF0ICk7XG5cdFx0XHR2YXIga2V5ID0gYWJzZW5jZS5zcmNfb2JqZWN0X2lkICsgJy0nICsgYWJzZW5jZS5wYXlfY29kZV9pZDtcblxuXHRcdFx0aWYgKCAhbWFwW2tleV0gKSB7XG5cdFx0XHRcdHJvdyA9IHt9O1xuXHRcdFx0XHRyb3cuaWQgPSByb3dfaWRfY291bnRlcjtcblx0XHRcdFx0cm93LnR5cGUgPSBUaW1lU2hlZXRWaWV3Q29udHJvbGxlci5BQlNFTkNFX1JPVztcblx0XHRcdFx0cm93LnB1bmNoX2luZm8gPSBhYnNlbmNlLm5hbWU7IC8vV2FzOiBhYnNlbmNlLmFic2VuY2VfcG9saWN5XG5cdFx0XHRcdHJvdy5wdW5jaF9pbmZvX2lkID0gYWJzZW5jZS5zcmNfb2JqZWN0X2lkO1xuXHRcdFx0XHRyb3cudXNlcl9pZCA9IGFic2VuY2UudXNlcl9pZDtcblx0XHRcdFx0cm93W2RhdGVfc3RyaW5nXSA9IEdsb2JhbC5nZXRUaW1lVW5pdCggYWJzZW5jZS50b3RhbF90aW1lICk7XG5cdFx0XHRcdHJvd1tkYXRlX3N0cmluZyArICdfZGF0YSddID0gYWJzZW5jZTtcblx0XHRcdFx0dGhpcy5hYnNlbmNlX3NvdXJjZS5wdXNoKCByb3cgKTtcblx0XHRcdFx0bWFwW2tleV0gPSByb3c7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyb3cgPSBtYXBba2V5XTtcblx0XHRcdFx0aWYgKCByb3dbZGF0ZV9zdHJpbmddICkge1xuXHRcdFx0XHRcdHJvdyA9IHt9O1xuXHRcdFx0XHRcdHJvdy5pZCA9IHJvd19pZF9jb3VudGVyO1xuXHRcdFx0XHRcdHJvdy50eXBlID0gVGltZVNoZWV0Vmlld0NvbnRyb2xsZXIuQUJTRU5DRV9ST1c7XG5cdFx0XHRcdFx0cm93LnB1bmNoX2luZm8gPSBhYnNlbmNlLm5hbWU7IC8vV2FzOiBhYnNlbmNlLmFic2VuY2VfcG9saWN5XG5cdFx0XHRcdFx0cm93LnB1bmNoX2luZm9faWQgPSBhYnNlbmNlLnNyY19vYmplY3RfaWQ7XG5cdFx0XHRcdFx0cm93LnVzZXJfaWQgPSBhYnNlbmNlLnVzZXJfaWQ7XG5cdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nXSA9IEdsb2JhbC5nZXRUaW1lVW5pdCggYWJzZW5jZS50b3RhbF90aW1lICk7XG5cblx0XHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmcgKyAnX2RhdGEnXSA9IGFic2VuY2U7XG5cdFx0XHRcdFx0dGhpcy5hYnNlbmNlX3NvdXJjZS5wdXNoKCByb3cgKTtcblx0XHRcdFx0XHRtYXBba2V5XSA9IHJvdztcblxuXHRcdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdFx0dGhpcy5sYXN0RGF5SXNPdmVycmlkZSggZGF0ZSwgcm93LCBhYnNlbmNlICk7XG5cdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nXSA9IEdsb2JhbC5nZXRUaW1lVW5pdCggYWJzZW5jZS50b3RhbF90aW1lICk7XG5cdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nICsgJ19kYXRhJ10gPSBhYnNlbmNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHJvd19pZF9jb3VudGVyKys7XG5cblx0XHRcdHRoaXMuYWJzZW5jZV9jZWxsX2NvdW50ID0gdGhpcy5hYnNlbmNlX2NlbGxfY291bnQgKyAxO1xuXG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLmFic2VuY2Vfc291cmNlLmxlbmd0aCA9PT0gMCApIHtcblx0XHRcdHJvdyA9IHt9O1xuXHRcdFx0cm93LmlkID0gMTtcblx0XHRcdHJvdy5wdW5jaF9pbmZvID0gJyc7XG5cdFx0XHRyb3cudXNlcl9pZCA9IHRoaXMuZ2V0U2VsZWN0RW1wbG95ZWUoKTtcblx0XHRcdHRoaXMuYWJzZW5jZV9zb3VyY2UucHVzaCggcm93ICk7XG5cdFx0fVxuXHR9XG5cblx0bGFzdERheUlzT3ZlcnJpZGUoIGN1cnJlbnRfZGF0ZSwgcm93LCBjdXJyZW50X2RhdGEgKSB7XG5cblx0XHR2YXIgbGFzdF9kYXRlID0gbmV3IERhdGUoIG5ldyBEYXRlKCBjdXJyZW50X2RhdGUuZ2V0VGltZSgpICkuc2V0RGF0ZSggY3VycmVudF9kYXRlLmdldERhdGUoKSAtIDEgKSApO1xuXG5cdFx0dmFyIGRhdGVfc3RyID0gbGFzdF9kYXRlLmZvcm1hdCggdGhpcy5mdWxsX2Zvcm1hdCApO1xuXG5cdFx0dmFyIGRhdGEgPSByb3dbZGF0ZV9zdHIgKyAnX2RhdGEnXTtcblxuXHRcdGlmICggZGF0YSAmJiBkYXRhLm92ZXJyaWRlICYmIGN1cnJlbnRfZGF0YS5zcmNfb2JqZWN0X2lkID09PSBkYXRhLnNyY19vYmplY3RfaWQgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRidWlsZFRpbWVTaGVldFNvdXJjZSgpIHtcblx0XHR0aGlzLnNlbGVjdF9wdW5jaGVzX2FycmF5ID0gW107XG5cdFx0dGhpcy50aW1lc2hlZXRfZGF0YV9zb3VyY2UgPSBbXTtcblxuXHRcdHZhciBwdW5jaF9hcnJheSA9IHRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YS5wdW5jaF9kYXRhO1xuXHRcdHZhciBsZW4gPSBwdW5jaF9hcnJheS5sZW5ndGg7XG5cdFx0dmFyIHJvdztcblx0XHR2YXIgbmV3X3Jvdztcblx0XHR2YXIgcm93X2lkX2NvdW50ZXIgPSAxO1xuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0dmFyIHB1bmNoID0gcHVuY2hfYXJyYXlbaV07XG5cdFx0XHQvLyBFcnJvcjogVHlwZUVycm9yOiBHbG9iYWwuc3RyVG9EYXRlKC4uLikgaXMgbnVsbCBpbiBpbnRlcmZhY2UvaHRtbDUvZnJhbWV3b3JrL2pxdWVyeS5taW4uanM/dj05LjAuMS0yMDE1MTAyMi0wODE3MjQgbGluZSAyID4gZXZhbCBsaW5lIDQ4Njlcblx0XHRcdC8vIFB1bmNoIG11c3QgaGF2ZSBhIGRhdGVcblx0XHRcdGlmICggIXB1bmNoLmRhdGVfc3RhbXAgKSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXHRcdFx0dmFyIGRhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCBwdW5jaC5kYXRlX3N0YW1wICk7XG5cdFx0XHR2YXIgZGF0ZV9zdHJpbmcgPSBkYXRlLmZvcm1hdCggdGhpcy5mdWxsX2Zvcm1hdCApO1xuXG5cdFx0XHR2YXIgcHVuY2hfc3RhdHVzX2lkID0gcHVuY2guc3RhdHVzX2lkO1xuXG5cdFx0XHQvL3JvdyAxLlxuXHRcdFx0aWYgKCBpID09PSAwICkge1xuXHRcdFx0XHRyb3cgPSB7fTtcblx0XHRcdFx0cm93LmlkID0gcm93X2lkX2NvdW50ZXI7XG5cdFx0XHRcdHJvd19pZF9jb3VudGVyKys7XG5cdFx0XHRcdHJvdy5wdW5jaF9pbmZvID0gcHVuY2guc3RhdHVzO1xuXHRcdFx0XHRyb3cuc3RhdHVzX2lkID0gcHVuY2hfc3RhdHVzX2lkO1xuXHRcdFx0XHRyb3cudXNlcl9pZCA9IHB1bmNoLnVzZXJfaWQ7XG5cdFx0XHRcdHJvd1tkYXRlX3N0cmluZ10gPSBwdW5jaC5wdW5jaF90aW1lO1xuXHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmcgKyAnX2RhdGEnXSA9IHB1bmNoO1xuXHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmcgKyAnX3JlbGF0ZWRfZGF0YSddID0gbnVsbDtcblx0XHRcdFx0cm93LnN0YXR1c19pZCA9IHB1bmNoX3N0YXR1c19pZDtcblx0XHRcdFx0cm93LnR5cGUgPSBUaW1lU2hlZXRWaWV3Q29udHJvbGxlci5QVU5DSF9ST1c7XG5cdFx0XHRcdHRoaXMudGltZXNoZWV0X2RhdGFfc291cmNlLnB1c2goIHJvdyApO1xuXG5cdFx0XHRcdGlmICggcHVuY2hfc3RhdHVzX2lkID09IDEwICkge1xuXG5cdFx0XHRcdFx0dmFyIG91cl9yb3cgPSB7fTtcblx0XHRcdFx0XHRvdXJfcm93LnB1bmNoX2luZm8gPSAkLmkxOG4uXyggJ091dCcgKTtcblx0XHRcdFx0XHRvdXJfcm93LnVzZXJfaWQgPSBwdW5jaC51c2VyX2lkO1xuXHRcdFx0XHRcdG91cl9yb3dbZGF0ZV9zdHJpbmddID0gJyc7XG5cdFx0XHRcdFx0b3VyX3Jvd1tkYXRlX3N0cmluZyArICdfZGF0YSddID0gbnVsbDtcblx0XHRcdFx0XHRvdXJfcm93W2RhdGVfc3RyaW5nICsgJ19yZWxhdGVkX2RhdGEnXSA9IHB1bmNoO1xuXHRcdFx0XHRcdG91cl9yb3cuc3RhdHVzX2lkID0gMjA7XG5cdFx0XHRcdFx0b3VyX3Jvdy50eXBlID0gVGltZVNoZWV0Vmlld0NvbnRyb2xsZXIuUFVOQ0hfUk9XO1xuXHRcdFx0XHRcdG91cl9yb3cuaWQgPSByb3dfaWRfY291bnRlcjtcblx0XHRcdFx0XHRyb3dfaWRfY291bnRlcisrO1xuXHRcdFx0XHRcdHRoaXMudGltZXNoZWV0X2RhdGFfc291cmNlLnB1c2goIG91cl9yb3cgKTtcblxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdG5ld19yb3cgPSB7fTtcblx0XHRcdFx0XHRuZXdfcm93LnB1bmNoX2luZm8gPSAkLmkxOG4uXyggJ0luJyApO1xuXHRcdFx0XHRcdG5ld19yb3cudXNlcl9pZCA9IHB1bmNoLnVzZXJfaWQ7XG5cdFx0XHRcdFx0bmV3X3Jvd1tkYXRlX3N0cmluZ10gPSAnJztcblx0XHRcdFx0XHRuZXdfcm93W2RhdGVfc3RyaW5nICsgJ19kYXRhJ10gPSBudWxsO1xuXHRcdFx0XHRcdG5ld19yb3dbZGF0ZV9zdHJpbmcgKyAnX3JlbGF0ZWRfZGF0YSddID0gcHVuY2g7XG5cdFx0XHRcdFx0bmV3X3Jvdy5zdGF0dXNfaWQgPSAxMDtcblx0XHRcdFx0XHRuZXdfcm93LnR5cGUgPSBUaW1lU2hlZXRWaWV3Q29udHJvbGxlci5QVU5DSF9ST1c7XG5cdFx0XHRcdFx0bmV3X3Jvdy5pZCA9IHJvd19pZF9jb3VudGVyO1xuXHRcdFx0XHRcdHJvd19pZF9jb3VudGVyKys7XG5cdFx0XHRcdFx0dGhpcy50aW1lc2hlZXRfZGF0YV9zb3VyY2Uuc3BsaWNlKCB0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZS5sZW5ndGggLSAxLCAwLCBuZXdfcm93ICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHR2YXIgZmluZF9wb3NpdGlvbiA9IGZhbHNlO1xuXHRcdFx0XHR2YXIgdGltZXNoZWV0X2RhdGFfc291cmNlX2xlbiA9IHRoaXMudGltZXNoZWV0X2RhdGFfc291cmNlLmxlbmd0aDtcblx0XHRcdFx0Zm9yICggdmFyIGogPSAwOyBqIDwgdGltZXNoZWV0X2RhdGFfc291cmNlX2xlbjsgaisrICkge1xuXHRcdFx0XHRcdHJvdyA9IHRoaXMudGltZXNoZWV0X2RhdGFfc291cmNlW2pdO1xuXHRcdFx0XHRcdGlmICggcm93W2RhdGVfc3RyaW5nXSApIHtcblx0XHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoICFyb3dbZGF0ZV9zdHJpbmddICYmIHJvd1tkYXRlX3N0cmluZyArICdfcmVsYXRlZF9kYXRhJ10gKSB7XG5cdFx0XHRcdFx0XHR2YXIgcmVsYXRlZF9wdW5jaCA9IHJvd1tkYXRlX3N0cmluZyArICdfcmVsYXRlZF9kYXRhJ107XG5cblx0XHRcdFx0XHRcdGlmICggcmVsYXRlZF9wdW5jaC5wdW5jaF9jb250cm9sX2lkID09PSBwdW5jaC5wdW5jaF9jb250cm9sX2lkICkge1xuXHRcdFx0XHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmddID0gcHVuY2gucHVuY2hfdGltZTtcblx0XHRcdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nICsgJ19kYXRhJ10gPSBwdW5jaDtcblx0XHRcdFx0XHRcdFx0ZmluZF9wb3NpdGlvbiA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gZWxzZSBpZiAoICFyb3dbZGF0ZV9zdHJpbmddICYmICFyb3dbZGF0ZV9zdHJpbmcgKyAnX3JlbGF0ZWRfZGF0YSddICYmIHB1bmNoLnN0YXR1c19pZCA9PSByb3cuc3RhdHVzX2lkICkge1xuXHRcdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nXSA9IHB1bmNoLnB1bmNoX3RpbWU7XG5cdFx0XHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmcgKyAnX2RhdGEnXSA9IHB1bmNoO1xuXHRcdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nICsgJ19yZWxhdGVkX2RhdGEnXSA9IG51bGw7XG5cdFx0XHRcdFx0XHRmaW5kX3Bvc2l0aW9uID0gdHJ1ZTtcblxuXHRcdFx0XHRcdFx0aWYgKCBwdW5jaC5zdGF0dXNfaWQgPT0gMTAgKSB7XG5cdFx0XHRcdFx0XHRcdG5ld19yb3cgPSB0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZVtqICsgMV07XG5cdFx0XHRcdFx0XHRcdG5ld19yb3dbZGF0ZV9zdHJpbmddID0gJyc7XG5cdFx0XHRcdFx0XHRcdG5ld19yb3dbZGF0ZV9zdHJpbmcgKyAnX2RhdGEnXSA9IG51bGw7XG5cdFx0XHRcdFx0XHRcdG5ld19yb3dbZGF0ZV9zdHJpbmcgKyAnX3JlbGF0ZWRfZGF0YSddID0gcHVuY2g7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRuZXdfcm93ID0gdGhpcy50aW1lc2hlZXRfZGF0YV9zb3VyY2VbaiAtIDFdO1xuXHRcdFx0XHRcdFx0XHRuZXdfcm93W2RhdGVfc3RyaW5nXSA9ICcnO1xuXHRcdFx0XHRcdFx0XHRuZXdfcm93W2RhdGVfc3RyaW5nICsgJ19kYXRhJ10gPSBudWxsO1xuXHRcdFx0XHRcdFx0XHRuZXdfcm93W2RhdGVfc3RyaW5nICsgJ19yZWxhdGVkX2RhdGEnXSA9IHB1bmNoO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvL05lZWQgYWRkIGEgbmV3IHJvd1xuXHRcdFx0XHRpZiAoICFmaW5kX3Bvc2l0aW9uICkge1xuXHRcdFx0XHRcdHJvdyA9IHt9O1xuXHRcdFx0XHRcdHJvdy5wdW5jaF9pbmZvID0gcHVuY2guc3RhdHVzO1xuXHRcdFx0XHRcdHJvdy51c2VyX2lkID0gcHVuY2gudXNlcl9pZDtcblx0XHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmddID0gcHVuY2gucHVuY2hfdGltZTtcblx0XHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmcgKyAnX2RhdGEnXSA9IHB1bmNoO1xuXHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZyArICdfcmVsYXRlZF9kYXRhJ10gPSBudWxsO1xuXHRcdFx0XHRcdHJvdy5zdGF0dXNfaWQgPSBwdW5jaF9zdGF0dXNfaWQ7XG5cdFx0XHRcdFx0cm93LnR5cGUgPSBUaW1lU2hlZXRWaWV3Q29udHJvbGxlci5QVU5DSF9ST1c7XG5cdFx0XHRcdFx0cm93LmlkID0gcm93X2lkX2NvdW50ZXI7XG5cdFx0XHRcdFx0cm93X2lkX2NvdW50ZXIrKztcblx0XHRcdFx0XHR0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZS5wdXNoKCByb3cgKTtcblxuXHRcdFx0XHRcdGlmICggcHVuY2hfc3RhdHVzX2lkID09IDEwICkge1xuXG5cdFx0XHRcdFx0XHRuZXdfcm93ID0ge307XG5cdFx0XHRcdFx0XHRuZXdfcm93LnB1bmNoX2luZm8gPSAkLmkxOG4uXyggJ091dCcgKTtcblx0XHRcdFx0XHRcdG5ld19yb3cudXNlcl9pZCA9IHB1bmNoLnVzZXJfaWQ7XG5cdFx0XHRcdFx0XHRuZXdfcm93W2RhdGVfc3RyaW5nXSA9ICcnO1xuXHRcdFx0XHRcdFx0bmV3X3Jvd1tkYXRlX3N0cmluZyArICdfZGF0YSddID0gbnVsbDtcblx0XHRcdFx0XHRcdG5ld19yb3dbZGF0ZV9zdHJpbmcgKyAnX3JlbGF0ZWRfZGF0YSddID0gcHVuY2g7XG5cdFx0XHRcdFx0XHRuZXdfcm93LnN0YXR1c19pZCA9IDIwO1xuXHRcdFx0XHRcdFx0bmV3X3Jvdy50eXBlID0gVGltZVNoZWV0Vmlld0NvbnRyb2xsZXIuUFVOQ0hfUk9XO1xuXHRcdFx0XHRcdFx0bmV3X3Jvdy5pZCA9IHJvd19pZF9jb3VudGVyO1xuXHRcdFx0XHRcdFx0cm93X2lkX2NvdW50ZXIrKztcblx0XHRcdFx0XHRcdHRoaXMudGltZXNoZWV0X2RhdGFfc291cmNlLnB1c2goIG5ld19yb3cgKTtcblxuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRuZXdfcm93ID0ge307XG5cdFx0XHRcdFx0XHRuZXdfcm93LnB1bmNoX2luZm8gPSAkLmkxOG4uXyggJ0luJyApO1xuXHRcdFx0XHRcdFx0bmV3X3Jvdy51c2VyX2lkID0gcHVuY2gudXNlcl9pZDtcblx0XHRcdFx0XHRcdG5ld19yb3dbZGF0ZV9zdHJpbmddID0gJyc7XG5cdFx0XHRcdFx0XHRuZXdfcm93W2RhdGVfc3RyaW5nICsgJ19kYXRhJ10gPSBudWxsO1xuXHRcdFx0XHRcdFx0bmV3X3Jvd1tkYXRlX3N0cmluZyArICdfcmVsYXRlZF9kYXRhJ10gPSBwdW5jaDtcblx0XHRcdFx0XHRcdG5ld19yb3cuc3RhdHVzX2lkID0gMTA7XG5cdFx0XHRcdFx0XHRuZXdfcm93LnR5cGUgPSBUaW1lU2hlZXRWaWV3Q29udHJvbGxlci5QVU5DSF9ST1c7XG5cdFx0XHRcdFx0XHRuZXdfcm93LmlkID0gcm93X2lkX2NvdW50ZXI7XG5cdFx0XHRcdFx0XHRyb3dfaWRfY291bnRlcisrO1xuXHRcdFx0XHRcdFx0dGhpcy50aW1lc2hlZXRfZGF0YV9zb3VyY2Uuc3BsaWNlKCB0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZS5sZW5ndGggLSAxLCAwLCBuZXdfcm93ICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cm93ID0ge307XG5cdFx0cm93LnB1bmNoX2luZm8gPSAkLmkxOG4uXyggJ0luJyApO1xuXHRcdHJvdy51c2VyX2lkID0gdGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpO1xuXHRcdHJvdy5zdGF0dXNfaWQgPSAxMDtcblx0XHRyb3cudHlwZSA9IFRpbWVTaGVldFZpZXdDb250cm9sbGVyLlBVTkNIX1JPVztcblx0XHRyb3cuaWQgPSByb3dfaWRfY291bnRlcjtcblx0XHRyb3dfaWRfY291bnRlcisrO1xuXHRcdHRoaXMudGltZXNoZWV0X2RhdGFfc291cmNlLnB1c2goIHJvdyApO1xuXG5cdFx0cm93ID0ge307XG5cdFx0cm93LnB1bmNoX2luZm8gPSAkLmkxOG4uXyggJ091dCcgKTtcblx0XHRyb3cudXNlcl9pZCA9IHRoaXMuZ2V0U2VsZWN0RW1wbG95ZWUoKTtcblx0XHRyb3cuc3RhdHVzX2lkID0gMjA7XG5cdFx0cm93LnR5cGUgPSBUaW1lU2hlZXRWaWV3Q29udHJvbGxlci5QVU5DSF9ST1c7XG5cdFx0cm93LmlkID0gcm93X2lkX2NvdW50ZXI7XG5cdFx0cm93X2lkX2NvdW50ZXIrKztcblx0XHR0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZS5wdXNoKCByb3cgKTtcblx0fVxuXG5cdGJ1aWxkVGltZVNoZWV0c0NvbHVtbnMoKSB7XG5cdFx0dGhpcy50aW1lc2hlZXRfY29sdW1ucyA9IFtdO1xuXHRcdGlmICggdGhpcy5nZXRQdW5jaE1vZGUoKSA9PT0gJ21hbnVhbCcgKSB7XG5cdFx0XHR2YXIgY29zdF9jZW50ZXJfY29scyA9IFtcblx0XHRcdFx0eyAnbmFtZSc6ICdwbHVzX3NpZ24nLCAnd2lkdGgnOiAyNSB9LFxuXHRcdFx0XHR7ICduYW1lJzogJ21pbnVzX3NpZ24nLCAnd2lkdGgnOiAyNSB9XG5cdFx0XHRdO1xuXG5cdFx0XHRpZiAoIHRoaXMuc2hvd19icmFuY2hfdWkgKSB7XG5cdFx0XHRcdGNvc3RfY2VudGVyX2NvbHMucHVzaCggeyAnbmFtZSc6ICdicmFuY2gnLCAnd2lkdGgnOiAxMjUgfSApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHRoaXMuc2hvd19kZXBhcnRtZW50X3VpICkge1xuXHRcdFx0XHRjb3N0X2NlbnRlcl9jb2xzLnB1c2goIHsgJ25hbWUnOiAnZGVwYXJ0bWVudCcsICd3aWR0aCc6IDEyNSB9ICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSB7XG5cdFx0XHRcdGlmICggdGhpcy5zaG93X2pvYl91aSApIHtcblx0XHRcdFx0XHRjb3N0X2NlbnRlcl9jb2xzLnB1c2goIHsgJ25hbWUnOiAnam9iJywgJ3dpZHRoJzogMTcwIH0gKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggdGhpcy5zaG93X2pvYl9pdGVtX3VpICkge1xuXHRcdFx0XHRcdGNvc3RfY2VudGVyX2NvbHMucHVzaCggeyAnbmFtZSc6ICdqb2JfaXRlbScsICd3aWR0aCc6IDE3MCB9ICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIHRoaXMuc2hvd19wdW5jaF90YWdfdWkgKSB7XG5cdFx0XHRcdFx0Y29zdF9jZW50ZXJfY29scy5wdXNoKCB7ICduYW1lJzogJ3B1bmNoX3RhZycsICd3aWR0aCc6IDE3MCB9ICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0dmFyIGxhc3RfY29sX2luZGV4ID0gY29zdF9jZW50ZXJfY29scy5sZW5ndGggLSAxO1xuXHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgY29zdF9jZW50ZXJfY29scy5sZW5ndGg7IGkrKyApIHtcblx0XHRcdFx0aWYgKCBpID09IGxhc3RfY29sX2luZGV4ICkge1xuXHRcdFx0XHRcdHZhciBjb2x1bW4gPSB7XG5cdFx0XHRcdFx0XHRuYW1lOiAncHVuY2hfaW5mbycsXG5cdFx0XHRcdFx0XHRpbmRleDogJ3B1bmNoX2luZm8nLFxuXHRcdFx0XHRcdFx0bGFiZWw6ICcgJyxcblx0XHRcdFx0XHRcdHdpZHRoOiAxNzAsXG5cdFx0XHRcdFx0XHRzb3J0YWJsZTogZmFsc2UsXG5cdFx0XHRcdFx0XHR0aXRsZTogZmFsc2UsXG5cdFx0XHRcdFx0XHRmb3JtYXR0ZXI6IHRoaXMub25DZWxsRm9ybWF0LFxuXHRcdFx0XHRcdFx0Zml4ZWQ6IHRydWVcblx0XHRcdFx0XHR9O1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHZhciBjb2x1bW4gPSB7XG5cdFx0XHRcdFx0XHRuYW1lOiAnZW1wdHlfY2VsbF8nICsgaSxcblx0XHRcdFx0XHRcdGluZGV4OiAnZW1wdHlfY2VsbF8nICsgaSxcblx0XHRcdFx0XHRcdGxhYmVsOiAnICcsXG5cdFx0XHRcdFx0XHR3aWR0aDogY29zdF9jZW50ZXJfY29sc1tpXS53aWR0aCxcblx0XHRcdFx0XHRcdHNvcnRhYmxlOiBmYWxzZSxcblx0XHRcdFx0XHRcdHRpdGxlOiBmYWxzZSxcblx0XHRcdFx0XHRcdGZpeGVkOiB0cnVlXG5cdFx0XHRcdFx0fTtcblx0XHRcdFx0fVxuXHRcdFx0XHR0aGlzLnRpbWVzaGVldF9jb2x1bW5zLnB1c2goIGNvbHVtbiApO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHR2YXIgcHVuY2hfaW5fb3V0X2NvbHVtbiA9IHtcblx0XHRcdFx0bmFtZTogJ3B1bmNoX2luZm8nLFxuXHRcdFx0XHRpbmRleDogJ3B1bmNoX2luZm8nLFxuXHRcdFx0XHRsYWJlbDogJyAnLFxuXHRcdFx0XHQvL2lmIG5vdCBzZXQgdG8gMCBpbiBwdW5jaCB0aW1lc2hlZXQgbW9kZSwgdGhlIGRhdGUgY29sdW1uIGhlYWRlcnMgYXJlIGEgZmV3IHB4IG91dCBvZiBhbGlnbm1lbnQgYW5kIGxvb2sgYmFkLlxuXHRcdFx0XHQvL3NlZSAjMjA5MSBub3RlcyBmb3IgbGluayB0byB0aGUgcGVyY2VudC1iYXNlZCBqcyBmaWRkbGVcblx0XHRcdFx0d2lkdGg6IDEwMCxcblx0XHRcdFx0c29ydGFibGU6IGZhbHNlLFxuXHRcdFx0XHR0aXRsZTogZmFsc2UsXG5cdFx0XHRcdGZvcm1hdHRlcjogdGhpcy5vbkNlbGxGb3JtYXQsXG5cdFx0XHRcdGZpeGVkOiBmYWxzZVxuXHRcdFx0fTtcblx0XHRcdHRoaXMudGltZXNoZWV0X2NvbHVtbnMucHVzaCggcHVuY2hfaW5fb3V0X2NvbHVtbiApO1xuXHRcdH1cblxuXHRcdC8vc2F2ZSBmdWxsIHdlZWsgY29sdW1ucyBtYXAgdXNlIHRvIGJ1aWxkIG5vIHBleSBwZXJpb2QgY29sdW1uXG5cdFx0dGhpcy5jb2x1bW5fbWFwcyA9IFtdO1xuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IDc7IGkrKyApIHtcblx0XHRcdHZhciBjdXJyZW50X2RhdGUgPSBuZXcgRGF0ZSggbmV3IERhdGUoIHRoaXMuc3RhcnRfZGF0ZS5nZXRUaW1lKCkgKS5zZXREYXRlKCB0aGlzLnN0YXJ0X2RhdGUuZ2V0RGF0ZSgpICsgaSApICk7XG5cdFx0XHR2YXIgaGVhZGVyX3RleHQgPSBjdXJyZW50X2RhdGUuZm9ybWF0KCB0aGlzLndlZWtseV9mb3JtYXQgKTtcblxuXHRcdFx0Ly9Mb2NhbGl6ZSB0aGUgZGF5IG9mIHdlZWsgYW5kIG1vbnRoIHRleHQuXG5cdFx0XHRpZiAoIExvY2FsQ2FjaGVEYXRhLmdldExvZ2luRGF0YSgpLmxhbmd1YWdlICE9ICdlbicgJiYgR2xvYmFsLmlzU3RyaW5nKCBoZWFkZXJfdGV4dCApICkge1xuXHRcdFx0XHR2YXIgc3BsaXRfaGVhZGVyX3RleHRfYXJyYXkgPSBoZWFkZXJfdGV4dC5zcGxpdCggJywnICk7XG5cdFx0XHRcdHZhciBzcGxpdF9oZWFkZXJfdGV4dF9tb250aCA9IHNwbGl0X2hlYWRlcl90ZXh0X2FycmF5WzFdLnNwbGl0KCAnICcgKTtcblx0XHRcdFx0aGVhZGVyX3RleHQgPSAkLmkxOG4uXyggc3BsaXRfaGVhZGVyX3RleHRfYXJyYXlbMF0gKSArICcsICcgKyAkLmkxOG4uXyggc3BsaXRfaGVhZGVyX3RleHRfbW9udGhbMV0gKSArICcgJyArIHNwbGl0X2hlYWRlcl90ZXh0X21vbnRoWzJdO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgZGF0YV9maWVsZCA9IGN1cnJlbnRfZGF0ZS5mb3JtYXQoIHRoaXMuZnVsbF9mb3JtYXQgKTtcblxuXHRcdFx0dGhpcy5jb2x1bW5fbWFwcy5wdXNoKCBjdXJyZW50X2RhdGUuZm9ybWF0KCkgKTtcblxuXHRcdFx0dmFyIGNvbHVtbl9pbmZvID0ge1xuXHRcdFx0XHRyZXNpemFibGU6IGZhbHNlLFxuXHRcdFx0XHRuYW1lOiBkYXRhX2ZpZWxkLFxuXHRcdFx0XHRpbmRleDogZGF0YV9maWVsZCxcblx0XHRcdFx0bGFiZWw6IGhlYWRlcl90ZXh0LFxuXHRcdFx0XHR3aWR0aDogMTAwLFxuXHRcdFx0XHRzb3J0YWJsZTogZmFsc2UsXG5cdFx0XHRcdHRpdGxlOiBmYWxzZSxcblx0XHRcdFx0Zm9ybWF0dGVyOiB0aGlzLm9uQ2VsbEZvcm1hdFxuXHRcdFx0fTtcblx0XHRcdHRoaXMudGltZXNoZWV0X2NvbHVtbnMucHVzaCggY29sdW1uX2luZm8gKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy50aW1lc2hlZXRfY29sdW1ucztcblx0fVxuXG5cdGdldERlZmF1bHREaXNwbGF5Q29sdW1ucyggY2FsbGJhY2sgKSB7XG5cdFx0Ly8gT3ZlcnJpZGVuIHRvIGFsbG93IHVzZSBvZiBpbml0TGF5b3V0IGluIEJhc2VWaWV3Q29udHJvbGxlciwgYnV0IG5vIGRlZmF1bHQgZGlzcGxheSBjb2x1bW5zIGluIHRoaXMgdmlldywgaGVuY2UgdGhpcyBmdW5jdGlvbiBpcyAnZGlzYWJsZWQnXG5cdFx0Y2FsbGJhY2soKTtcblx0fVxuXG5cdHNldFNlbGVjdExheW91dCgpIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXG5cdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCB0aGlzLmdyaWQgKSApIHtcblx0XHRcdHZhciBncmlkID0gJCggdGhpcy5lbCApLmZpbmQoICcjZ3JpZCcgKTtcblxuXHRcdFx0Z3JpZC5hdHRyKCAnaWQnLCB0aGlzLnVpX2lkICsgJ19ncmlkJyApOyAgLy9HcmlkJ3MgaWQgaXMgU2NyaXB0TmFtZSArIF9ncmlkXG5cblx0XHRcdGdyaWQgPSAkKCB0aGlzLmVsICkuZmluZCggJyMnICsgdGhpcy51aV9pZCArICdfZ3JpZCcgKTtcblx0XHR9XG5cblx0XHRpZiAoICF0aGlzLnNlbGVjdF9sYXlvdXQgKSB7IC8vU2V0IHRvIGRlZmFsdCBsYXlvdXQgaWYgbm8gbGF5b3V0IGF0IGFsbFxuXHRcdFx0dGhpcy5zZWxlY3RfbGF5b3V0ID0geyBpZDogJycgfTtcblx0XHRcdHRoaXMuc2VsZWN0X2xheW91dC5kYXRhID0geyBmaWx0ZXJfZGF0YToge30sIGZpbHRlcl9zb3J0OiB7fSB9O1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5zZWxlY3RfbGF5b3V0LmRhdGEubW9kZSApIHtcblx0XHRcdHRoaXMudG9nZ2xlX2J1dHRvbi5zZXRWYWx1ZSggdGhpcy5zZWxlY3RfbGF5b3V0LmRhdGEubW9kZSApO1xuXHRcdH1cblxuXHRcdHRoaXMud2FnZV9idG4uc2V0VmFsdWUoIHRoaXMuc2VsZWN0X2xheW91dC5kYXRhLnNob3dfd2FnZSA/IHRydWUgOiBmYWxzZSApO1xuXG5cdFx0dGhpcy50aW1lem9uZV9idG4uc2V0VmFsdWUoIHRoaXMuc2VsZWN0X2xheW91dC5kYXRhLnVzZV9lbXBsb3llZV90aW1lem9uZSA/IHRydWUgOiBmYWxzZSApO1xuXG5cdFx0Ly9zZWFyY2ggcGFuZWwgZG9lc24ndCBhbHdheXMgZXhpc3QuXG5cdFx0aWYgKCB0aGlzLnNlYXJjaF9wYW5lbCApIHtcblx0XHRcdC8vU2V0IFByZXZpb3VzIFNhdmVkIGxheW91dCBjb21ib2JveCBpbiBsYXlvdXQgcGFuZWxcblx0XHRcdHZhciBsYXlvdXRzX2FycmF5ID0gdGhpcy5zZWFyY2hfcGFuZWwuZ2V0TGF5b3V0c0FycmF5KCk7XG5cdFx0XHRpZiAoIHRoaXMucHJldmlvdXNfc2F2ZWRfbGF5b3V0X3NlbGVjdG9yICkge1xuXHRcdFx0XHR0aGlzLnByZXZpb3VzX3NhdmVkX2xheW91dF9zZWxlY3Rvci5lbXB0eSgpO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGxheW91dHNfYXJyYXkgJiYgbGF5b3V0c19hcnJheS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHR0aGlzLnByZXZpb3VzX3NhdmVkX2xheW91dF9kaXYuY3NzKCAnZGlzcGxheScsICdpbmxpbmUnICk7XG5cblx0XHRcdFx0dmFyIGxlbiA9IGxheW91dHNfYXJyYXkubGVuZ3RoO1xuXHRcdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdFx0XHR2YXIgaXRlbSA9IGxheW91dHNfYXJyYXlbaV07XG5cdFx0XHRcdFx0dGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfc2VsZWN0b3IuYXBwZW5kKCAkKCAnPG9wdGlvbiB2YWx1ZT1cIicgKyBpdGVtLmlkICsgJ1wiPjwvb3B0aW9uPicgKS50ZXh0KCBpdGVtLm5hbWUgKSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0JCggdGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfc2VsZWN0b3IuZmluZCggJ29wdGlvbicgKSApLmZpbHRlciggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0cmV0dXJuICQoIHRoaXMgKS5hdHRyKCAndmFsdWUnICkgPT09ICR0aGlzLnNlbGVjdF9sYXlvdXQuaWQ7XG5cdFx0XHRcdH0gKS5wcm9wKCAnc2VsZWN0ZWQnLCB0cnVlICkuYXR0ciggJ3NlbGVjdGVkJywgdHJ1ZSApO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZiAoIHRoaXMucHJldmlvdXNfc2F2ZWRfbGF5b3V0X2RpdiApIHtcblx0XHRcdFx0XHR0aGlzLnByZXZpb3VzX3NhdmVkX2xheW91dF9kaXYuY3NzKCAnZGlzcGxheScsICdub25lJyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vcmVwbGFjZSBzZWxlY3QgbGF5b3V0IGZpbHRlcl9kYXRhIHRvIGZpbHRlciBzZXQgaW4gb25OYXZpZ2F0aW9uIGZ1bmN0aW9uIHdoZW4gZ290byB2aWV3IGZyb20gbmF2aWdhdGlvbiBjb250ZXh0IGdyb3VwXG5cdFx0XHRpZiAoIExvY2FsQ2FjaGVEYXRhLmRlZmF1bHRfZmlsdGVyX2Zvcl9uZXh0X29wZW5fdmlldyApIHtcblx0XHRcdFx0dGhpcy5zZWxlY3RfbGF5b3V0LmRhdGEuZmlsdGVyX2RhdGEgPSBMb2NhbENhY2hlRGF0YS5kZWZhdWx0X2ZpbHRlcl9mb3JfbmV4dF9vcGVuX3ZpZXcuZmlsdGVyX2RhdGE7XG5cdFx0XHRcdExvY2FsQ2FjaGVEYXRhLmRlZmF1bHRfZmlsdGVyX2Zvcl9uZXh0X29wZW5fdmlldyA9IG51bGw7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuZmlsdGVyX2RhdGEgPSB0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5maWx0ZXJfZGF0YTtcblxuXHRcdFx0dGhpcy5zZXRTZWFyY2hQYW5lbEZpbHRlciggdHJ1ZSApOyAvL0F1dG8gY2hhbmdlIHRvIHByb3BlcnR5IHRhYiB3aGVuIHNldCB2YWx1ZSB0byBzZWFyY2ggZmllbGRzLlxuXHRcdH1cblxuXHRcdC8vIHRoaXMuc2VhcmNoKCB0cnVlICk7IC8vIGdldCBwdW5jaGVzIGJhc2Ugb24gdXNlcmlkLCBkYXRhIGFuZCBmaWx0ZXIgLSBjb21tZW50ZWQgb3V0IGFzIHRoaXMgaXMgYWxyZWFkeSBjYWxsZWQgaW4gQmFzZVZpZXdDb250cm9sbGVyLmluaXRMYXlvdXQoKVxuXHR9XG5cblx0Ly9TdGFydCBEcmFnXG5cdHNldFRpbWVzaGVldEdyaWREcmFnQWJsZSgpIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXG5cdFx0dmFyIHBvc2l0aW9uID0gMDtcblx0XHR2YXIgY2VsbHMgPSB0aGlzLmdyaWQuZ3JpZC5maW5kKCAnLmRhdGUtY29sdW1uJyApLnBhcmVudHMoICd0ZCcgKTtcblx0XHRjZWxscy5hdHRyKCAnZHJhZ2dhYmxlJywgdHJ1ZSApO1xuXG5cdFx0Y2VsbHMub2ZmKCAnZHJhZ3N0YXJ0JyApLm9uKCAnZHJhZ3N0YXJ0JywgZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHR2YXIgdGQgPSBldmVudC50YXJnZXQ7XG5cdFx0XHRpZiAoICR0aGlzLnNlbGVjdF9wdW5jaGVzX2FycmF5Lmxlbmd0aCA8IDEgfHwgISQoIHRkICkuaGFzQ2xhc3MoICd1aS1zdGF0ZS1oaWdobGlnaHQnICkgfHwgISR0aGlzLnNlbGVjdF9kcmFnX21lbnVfaWQgKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblxuXHRcdFx0dmFyIGNvbnRhaW5lciA9ICQoICc8ZGl2IGNsYXNzPVxcJ2RyYWctaG9sZGVyLWRpdlxcJz48L2Rpdj4nICk7XG5cblx0XHRcdHZhciBsZW4gPSAkdGhpcy5zZWxlY3RfcHVuY2hlc19hcnJheS5sZW5ndGg7XG5cblx0XHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0XHR2YXIgcHVuY2ggPSAkdGhpcy5zZWxlY3RfcHVuY2hlc19hcnJheVtpXTtcblxuXHRcdFx0XHR2YXIgc3BhbiA9ICQoICc8c3BhbiBjbGFzcz1cXCdkcmFnLXNwYW5cXCc+PC9zcGFuPicgKTtcblx0XHRcdFx0c3Bhbi50ZXh0KCBwdW5jaC5zdGF0dXMgKyAnOiAnICsgcHVuY2gudGltZV9zdGFtcCApO1xuXHRcdFx0XHRjb250YWluZXIuYXBwZW5kKCBzcGFuICk7XG5cdFx0XHR9XG5cblx0XHRcdCQoICdib2R5JyApLmZpbmQoICcuZHJhZy1ob2xkZXItZGl2JyApLnJlbW92ZSgpO1xuXG5cdFx0XHQkKCAnYm9keScgKS5hcHBlbmQoIGNvbnRhaW5lciApO1xuXG5cdFx0XHRldmVudC5vcmlnaW5hbEV2ZW50LmRhdGFUcmFuc2Zlci5zZXREYXRhKCAnVGV4dCcsICd0aW1lc2hlZXQnICk7Ly9KVVNUIEVMRU1FTlQgcmVmZXJlbmNlcyBpcyBvayBoZXJlIE5PIElEXG5cblx0XHRcdGlmICggZXZlbnQub3JpZ2luYWxFdmVudC5kYXRhVHJhbnNmZXIuc2V0RHJhZ0ltYWdlICkge1xuXHRcdFx0XHRldmVudC5vcmlnaW5hbEV2ZW50LmRhdGFUcmFuc2Zlci5zZXREcmFnSW1hZ2UoIGNvbnRhaW5lclswXSwgMCwgMCApO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblxuXHRcdH0gKTtcblxuXHRcdGNlbGxzLm9mZiggJ2RyYWdvdmVyJyApLm9uKCAnZHJhZ292ZXInLCBmdW5jdGlvbiggZSApIHtcblxuXHRcdFx0dmFyIGV2ZW50ID0gZS5vcmlnaW5hbEV2ZW50O1xuXG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHRcdHZhciB0YXJnZXQgPSAkKCB0aGlzICk7XG5cblx0XHRcdCQoICcudGltZXNoZWV0LWRyYWctb3ZlcicgKS5yZW1vdmVDbGFzcyggJ3RpbWVzaGVldC1kcmFnLW92ZXInICk7XG5cdFx0XHQkKCAnLmRyYWctb3Zlci10b3AnICkucmVtb3ZlQ2xhc3MoICdkcmFnLW92ZXItdG9wJyApO1xuXHRcdFx0JCggJy5kcmFnLW92ZXItY2VudGVyJyApLnJlbW92ZUNsYXNzKCAnZHJhZy1vdmVyLWNlbnRlcicgKTtcblx0XHRcdCQoICcuZHJhZy1vdmVyLWJvdHRvbScgKS5yZW1vdmVDbGFzcyggJyBkcmFnLW92ZXItYm90dG9tJyApO1xuXG5cdFx0XHQkKCAkdGhpcyApLmFkZENsYXNzKCAndGltZXNoZWV0LWRyYWctb3ZlcicgKTtcblxuXHRcdFx0Ly9qdWRnZSB3aGljaCBhcmVhIG1vdXNlIG9uIGluIHRoZSB0YXJnZXQgY2VsbCBhbmQgc2V0IHByb3BlciBzdHlsZSwgS2VlcCBjaGVja2luZyB0aGlzIGluIGRyYWcgZXZlbnQuXG5cdFx0XHRpZiAoIGV2ZW50LnBhZ2VZIC0gdGFyZ2V0Lm9mZnNldCgpLnRvcCA8PSA4ICkge1xuXHRcdFx0XHRwb3NpdGlvbiA9IC0xO1xuXHRcdFx0XHR0YXJnZXQucmVtb3ZlQ2xhc3MoICdkcmFnLW92ZXItdG9wIGRyYWctb3Zlci1jZW50ZXIgZHJhZy1vdmVyLWJvdHRvbScgKS5hZGRDbGFzcyggJ2RyYWctb3Zlci10b3AnICk7XG5cdFx0XHR9IGVsc2UgaWYgKCBldmVudC5wYWdlWSAtIHRhcmdldC5vZmZzZXQoKS50b3AgPj0gdGFyZ2V0LmhlaWdodCgpIC0gNSApIHtcblx0XHRcdFx0cG9zaXRpb24gPSAxO1xuXHRcdFx0XHR0YXJnZXQucmVtb3ZlQ2xhc3MoICdkcmFnLW92ZXItdG9wIGRyYWctb3Zlci1jZW50ZXIgZHJhZy1vdmVyLWJvdHRvbScgKS5hZGRDbGFzcyggJ2RyYWctb3Zlci1ib3R0b20nICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRwb3NpdGlvbiA9IDA7XG5cdFx0XHRcdHRhcmdldC5yZW1vdmVDbGFzcyggJ2RyYWctb3Zlci10b3AgZHJhZy1vdmVyLWNlbnRlciBkcmFnLW92ZXItYm90dG9tJyApLmFkZENsYXNzKCAnZHJhZy1vdmVyLWNlbnRlcicgKTtcblx0XHRcdH1cblxuXHRcdH0gKTtcblxuXHRcdGNlbGxzLm9mZiggJ2RyYWdlbmQnICkub24oICdkcmFnZW5kJywgZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHQkKCAnLnRpbWVzaGVldC1kcmFnLW92ZXInICkucmVtb3ZlQ2xhc3MoICd0aW1lc2hlZXQtZHJhZy1vdmVyJyApO1xuXHRcdFx0JCggJy5kcmFnLW92ZXItdG9wJyApLnJlbW92ZUNsYXNzKCAnZHJhZy1vdmVyLXRvcCcgKTtcblx0XHRcdCQoICcuZHJhZy1vdmVyLWNlbnRlcicgKS5yZW1vdmVDbGFzcyggJ2RyYWctb3Zlci1jZW50ZXInICk7XG5cdFx0XHQkKCAnLmRyYWctb3Zlci1ib3R0b20nICkucmVtb3ZlQ2xhc3MoICcgZHJhZy1vdmVyLWJvdHRvbScgKTtcblx0XHRcdCQoICdib2R5JyApLmZpbmQoICcuZHJhZy1ob2xkZXItZGl2JyApLnJlbW92ZSgpO1xuXG5cdFx0fSApO1xuXG5cdFx0Y2VsbHMub2ZmKCAnZHJvcCcgKS5vbiggJ2Ryb3AnLCBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRpZiAoIGV2ZW50LnN0b3BQcm9wYWdhdGlvbiApIHtcblx0XHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7IC8vIHN0b3BzIHRoZSBicm93c2VyIGZyb20gcmVkaXJlY3RpbmcuXG5cdFx0XHR9XG5cblx0XHRcdCQoIHRoaXMgKS5yZW1vdmVDbGFzcyggJ2RyYWctb3Zlci10b3AgZHJhZy1vdmVyLWNlbnRlciBkcmFnLW92ZXItYm90dG9tIHRpbWVzaGVldC1kcmFnLW92ZXInICk7XG5cdFx0XHR2YXIgdGFyZ2V0X2NlbGwgPSBldmVudC5jdXJyZW50VGFyZ2V0O1xuXHRcdFx0dmFyIGkgPSAwOyAvL3N0YXJ0IGluZGV4O1xuXG5cdFx0XHRpZiAoICQoIHRhcmdldF9jZWxsICkuaW5kZXgoKSA9PT0gMCApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHQvL0Vycm9yOiBVbmNhdWdodCBUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnR5ICdwdW5jaF9kYXRlJyBvZiB1bmRlZmluZWQgaW4gL2ludGVyZmFjZS9odG1sNS8jIW09VGltZVNoZWV0JmRhdGU9MjAxNDExMTgmdXNlcl9pZD0zMjkxNiBsaW5lIDQ1NjNcblx0XHRcdGlmICggISR0aGlzLnNlbGVjdF9wdW5jaGVzX2FycmF5IHx8ICEkdGhpcy5zZWxlY3RfcHVuY2hlc19hcnJheVtpXSApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgcHVuY2ggPSAkdGhpcy5zZWxlY3RfcHVuY2hlc19hcnJheVtpXTtcblxuXHRcdFx0dmFyIHB1bmNoX2RhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCBwdW5jaC5wdW5jaF9kYXRlICk7XG5cblx0XHRcdHZhciByb3cgPSAkdGhpcy50aW1lc2hlZXRfZGF0YV9zb3VyY2VbdGFyZ2V0X2NlbGwucGFyZW50Tm9kZS5yb3dJbmRleCAtIDFdO1xuXG5cdFx0XHQvL0Vycm9yOiBVbmNhdWdodCBUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnR5ICdzdGF0dXNfaWQnIG9mIHVuZGVmaW5lZCBpbiAvaW50ZXJmYWNlL2h0bWw1LyMhbT1UaW1lU2hlZXQmZGF0ZT0yMDE1MDEwOCZ1c2VyX2lkPTEwNjggbGluZSA1MTc0XG5cdFx0XHRpZiAoICFyb3cgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0dmFyIGNvbE1vZGVsID0gJHRoaXMuZ3JpZC5nZXRHcmlkUGFyYW0oICdjb2xNb2RlbCcgKTtcblxuXHRcdFx0dmFyIGRhdGFfZmllbGQgPSBjb2xNb2RlbFt0YXJnZXRfY2VsbC5jZWxsSW5kZXhdLm5hbWU7XG5cblx0XHRcdHZhciB0YXJnZXRfcHVuY2ggPSByb3dbZGF0YV9maWVsZCArICdfZGF0YSddO1xuXG5cdFx0XHR2YXIgdGFyZ2V0X3JlbGF0ZWRfcHVuY2ggPSByb3dbZGF0YV9maWVsZCArICdfcmVsYXRlZF9kYXRhJ107XG5cblx0XHRcdHZhciB0YXJnZXRfY29sdW1uX2RhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCBkYXRhX2ZpZWxkLCAkdGhpcy5mdWxsX2Zvcm1hdCApO1xuXG5cdFx0XHR2YXIgZmlyc3Rfc2VsZWN0X2RhdGUgPSBwdW5jaF9kYXRlO1xuXG5cdFx0XHR2YXIgdGltZV9vZmZzZXQgPSB0YXJnZXRfY29sdW1uX2RhdGUuZ2V0VGltZSgpIC0gcHVuY2hfZGF0ZS5nZXRUaW1lKCk7XG5cblx0XHRcdHZhciB0YXJnZXRfY29sdW1uX2RhdGVfc3RyID0gdGFyZ2V0X2NvbHVtbl9kYXRlLmZvcm1hdCgpO1xuXG5cdFx0XHRzYXZlUHVuY2goKTtcblxuXHRcdFx0ZnVuY3Rpb24gc2F2ZVB1bmNoKCkge1xuXHRcdFx0XHQvL0Vycm9yOiBVbmNhdWdodCBUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnR5ICdkYXRlX3N0YW1wJyBvZiB1bmRlZmluZWQgaW4gL2ludGVyZmFjZS9odG1sNS8jIW09VGltZVNoZWV0JmRhdGU9MjAxNDEyMjkmdXNlcl9pZD0zOTU1NSBsaW5lIDUyMDdcblx0XHRcdFx0aWYgKCAhJHRoaXMuc2VsZWN0X3B1bmNoZXNfYXJyYXkgKSB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dmFyIG5ld19wdW5jaF9pZCA9IHB1bmNoLmlkO1xuXHRcdFx0XHR2YXIgdGFyZ2V0X2lkID0gZmFsc2U7XG5cdFx0XHRcdHZhciB0YXJnZXRfc3RhdHVzX2lkID0gcm93LnN0YXR1c19pZDtcblx0XHRcdFx0dmFyIGFjdGlvbl90eXBlID0gJHRoaXMuc2VsZWN0X2RyYWdfbWVudV9pZCA9PT0gJ21vdmUnID8gMSA6IDA7XG5cblx0XHRcdFx0Ly9Jc3N1ZSAjMjAwOCAtIEFsbCBpbi1wdW5jaGVzIG5lZWQgdGFyZ2V0X2lkIHRvIGJlIGZhbHNlIHRvIGVuc3VyZSB0aGF0IGVhY2ggcGFpciByZXRhaW5zIGl0cyBwdW5jaF9jb250cm9sIHNldHRpbmdzLlxuXHRcdFx0XHQvL01vc3Qgb3V0LXB1bmNoZXMgbmVlZCB0aGVpciB0YXJnZXQgaWQgdG8gYmUgdGhlIHJlbGF0ZWQgaW4tcHVuY2guXG5cdFx0XHRcdC8vSWYgdGhlc2UgY29uZGl0aW9ucyBhcmUgbm90IG1ldCwgY29weWluZyBncm91cHMgb2YgcHVuY2hlcyB3aXRoIGRpZmZlcmVudCBwdW5jaF9jb250cm9sIGRhdGEgd2lsbCByZXN1bHQgaW4gYWxsIGNvcGllZCBwdW5jaGVzIGhhdmluZyB0aGUgc2FtZSBwdW5jaF9jb250cm9sIGRhdGEgYXMgdGhlIGZpcnN0IHB1bmNoIHBhaXIuXG5cdFx0XHRcdGlmICggdGFyZ2V0X3B1bmNoICYmIHB1bmNoLnN0YXR1c19pZCA9PSAyMCApIHtcblx0XHRcdFx0XHR0YXJnZXRfaWQgPSB0YXJnZXRfcHVuY2guaWQ7XG5cdFx0XHRcdFx0dGFyZ2V0X3N0YXR1c19pZCA9IGZhbHNlO1xuXHRcdFx0XHR9IGVsc2UgaWYgKCB0YXJnZXRfcmVsYXRlZF9wdW5jaCApIHtcblx0XHRcdFx0XHR0YXJnZXRfaWQgPSB0YXJnZXRfcmVsYXRlZF9wdW5jaC5pZDtcblx0XHRcdFx0XHRpZiAoIHRhcmdldF9yZWxhdGVkX3B1bmNoLnN0YXR1c19pZCA9PSAxMCApIHtcblx0XHRcdFx0XHRcdHBvc2l0aW9uID0gMTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0cG9zaXRpb24gPSAtMTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0dGFyZ2V0X3N0YXR1c19pZCA9IGZhbHNlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dmFyIGFwaV9wdW5jaF9jb250cm9sID0gVFRBUEkuQVBJUHVuY2hDb250cm9sO1xuXG5cdFx0XHRcdGFwaV9wdW5jaF9jb250cm9sLmRyYWdOZHJvcFB1bmNoKCBuZXdfcHVuY2hfaWQsIHRhcmdldF9pZCwgdGFyZ2V0X3N0YXR1c19pZCwgcG9zaXRpb24sIGFjdGlvbl90eXBlLCB0YXJnZXRfY29sdW1uX2RhdGVfc3RyLCB7XG5cdFx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cdFx0XHRcdFx0XHR2YXIgcmVzdWx0X2RhdGEgPSByZXN1bHQuZ2V0UmVzdWx0KCk7XG5cdFx0XHRcdFx0XHQvL0Vycm9yOiBVbmNhdWdodCBUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnR5ICdkYXRlX3N0YW1wJyBvZiB1bmRlZmluZWQgaW4gaW50ZXJmYWNlL2h0bWw1LyMhbT1UaW1lU2hlZXQmZGF0ZT0yMDE1MDgzMSZ1c2VyX2lkPTEyOTg5NSZzaG93X3dhZ2U9MCBsaW5lIDUyODZcblx0XHRcdFx0XHRcdGlmICggcmVzdWx0LmlzVmFsaWQoKSAmJiAkdGhpcy5zZWxlY3RfcHVuY2hlc19hcnJheSAmJiAkdGhpcy5zZWxlY3RfcHVuY2hlc19hcnJheS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHRcdFx0XHRpID0gaSArIDE7XG5cdFx0XHRcdFx0XHRcdGlmICggaSA+ICR0aGlzLnNlbGVjdF9jZWxsc19BcnJheS5sZW5ndGggLSAxICkge1xuXHRcdFx0XHRcdFx0XHRcdCR0aGlzLnNlYXJjaCggdHJ1ZSApO1xuXHRcdFx0XHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHQvL0Vycm9yOiBVbmNhdWdodCBUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnR5ICdkYXRlX3N0YW1wJyBvZiB1bmRlZmluZWQgaW4gaW50ZXJmYWNlL2h0bWw1LyMhbT1UaW1lU2hlZXQmZGF0ZT0yMDE1MDgzMSZ1c2VyX2lkPTEyOTg5NSZzaG93X3dhZ2U9MCBsaW5lIDUyODZcblx0XHRcdFx0XHRcdFx0aWYgKCAhJHRoaXMuc2VsZWN0X3B1bmNoZXNfYXJyYXlbaV0gKSB7XG5cdFx0XHRcdFx0XHRcdFx0JHRoaXMuc2VhcmNoKCB0cnVlICk7XG5cdFx0XHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdHdoaWxlICggISR0aGlzLnNlbGVjdF9wdW5jaGVzX2FycmF5W2ldLmRhdGVfc3RhbXAgKSB7XG5cdFx0XHRcdFx0XHRcdFx0aSA9IGkgKyAxO1xuXHRcdFx0XHRcdFx0XHRcdGlmICggaSA+ICR0aGlzLnNlbGVjdF9jZWxsc19BcnJheS5sZW5ndGggLSAxICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0JHRoaXMuc2VhcmNoKCB0cnVlICk7XG5cdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdHBvc2l0aW9uID0gMTsgLy9wdXQgbmV4dCBwdW5jaCBiZWxvdyBsYXN0IG9uZVxuXHRcdFx0XHRcdFx0XHR2YXIgbGFzdF9kYXRlX3N0cmluZyA9IHRhcmdldF9jb2x1bW5fZGF0ZV9zdHI7XG5cdFx0XHRcdFx0XHRcdHB1bmNoID0gJHRoaXMuc2VsZWN0X3B1bmNoZXNfYXJyYXlbaV07XG5cdFx0XHRcdFx0XHRcdHB1bmNoX2RhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCBwdW5jaC5wdW5jaF9kYXRlICk7XG5cdFx0XHRcdFx0XHRcdHJvdyA9ICR0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZVt0YXJnZXRfY2VsbC5wYXJlbnROb2RlLnJvd0luZGV4IC0gMV07XG5cdFx0XHRcdFx0XHRcdGNvbE1vZGVsID0gJHRoaXMuZ3JpZC5nZXRHcmlkUGFyYW0oICdjb2xNb2RlbCcgKTtcblx0XHRcdFx0XHRcdFx0ZGF0YV9maWVsZCA9IGNvbE1vZGVsW3RhcmdldF9jZWxsLmNlbGxJbmRleF0ubmFtZTtcblx0XHRcdFx0XHRcdFx0dGltZV9vZmZzZXQgPSBwdW5jaF9kYXRlLmdldFRpbWUoKSAtIGZpcnN0X3NlbGVjdF9kYXRlLmdldFRpbWUoKTtcblx0XHRcdFx0XHRcdFx0Ly9kcm9wIGNvbHVtbiBkYXRlXG5cdFx0XHRcdFx0XHRcdHRhcmdldF9jb2x1bW5fZGF0ZSA9IEdsb2JhbC5zdHJUb0RhdGUoIGRhdGFfZmllbGQsICR0aGlzLmZ1bGxfZm9ybWF0ICk7XG5cdFx0XHRcdFx0XHRcdC8vUmVhbCB0YXJnZXQgY29sdW1uIGRhdGUgc3RyXG5cdFx0XHRcdFx0XHRcdHRhcmdldF9jb2x1bW5fZGF0ZV9zdHIgPSBuZXcgRGF0ZSggdGFyZ2V0X2NvbHVtbl9kYXRlLmdldFRpbWUoKSArIHRpbWVfb2Zmc2V0ICkuZm9ybWF0KCk7XG5cdFx0XHRcdFx0XHRcdHRhcmdldF9wdW5jaCA9IHsgaWQ6IHJlc3VsdF9kYXRhIH07XG5cdFx0XHRcdFx0XHRcdHRhcmdldF9yZWxhdGVkX3B1bmNoID0gbnVsbDtcblx0XHRcdFx0XHRcdFx0aWYgKCB0YXJnZXRfY29sdW1uX2RhdGVfc3RyICE9PSBsYXN0X2RhdGVfc3RyaW5nICkge1xuXHRcdFx0XHRcdFx0XHRcdHBvc2l0aW9uID0gMDtcblx0XHRcdFx0XHRcdFx0XHR0YXJnZXRfcHVuY2ggPSBudWxsO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdHNhdmVQdW5jaCgpO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0VEFsZXJ0TWFuYWdlci5zaG93QWxlcnQoICQuaTE4bi5fKCAnVW5hYmxlIHRvIGRyYWcgYW5kIGRyb3AgcHVuY2ggdG8gdGhlIHNwZWNpZmllZCBsb2NhdGlvbicgKSApO1xuXHRcdFx0XHRcdFx0XHRpZiAoIGkgPiAwICkge1xuXHRcdFx0XHRcdFx0XHRcdCR0aGlzLnNlYXJjaCggdHJ1ZSApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9ICk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cblx0c2V0UHVuY2hNb2RlQ2xhc3MoKSB7XG5cdFx0dGhpcy4kZWwucmVtb3ZlQ2xhc3MoICd0aW1lc2hlZXQtcHVuY2gtbW9kZScgKTtcblx0XHR0aGlzLiRlbC5yZW1vdmVDbGFzcyggJ3RpbWVzaGVldC1tYW51YWwtbW9kZScgKTtcblx0XHR0aGlzLmdldFB1bmNoTW9kZSgpID09PSAncHVuY2gnID8gdGhpcy4kZWwuYWRkQ2xhc3MoICd0aW1lc2hlZXQtcHVuY2gtbW9kZScgKSA6IHRoaXMuJGVsLmFkZENsYXNzKCAndGltZXNoZWV0LW1hbnVhbC1tb2RlJyApO1xuXHR9XG5cblx0aW5pdERhdGEoKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHRHbG9iYWwucmVtb3ZlVmlld1RhYiggdGhpcy52aWV3SWQgKTtcblx0XHR2YXIgbG9naW5Vc2VyID0gTG9jYWxDYWNoZURhdGEuZ2V0TG9naW5Vc2VyKCk7XG5cdFx0dGhpcy5pbml0T3B0aW9ucygpO1xuXHRcdFByb2dyZXNzQmFyLnNob3dPdmVybGF5KCk7XG5cdFx0Ly8gU2V0IFdhZ2Vcblx0XHRpZiAoICFMb2NhbENhY2hlRGF0YS5sYXN0X3RpbWVzaGVldF9zZWxlY3RlZF9zaG93X3dhZ2UgKSB7XG5cdFx0XHR0aGlzLndhZ2VfYnRuLnNldFZhbHVlKCBmYWxzZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLndhZ2VfYnRuLnNldFZhbHVlKCBMb2NhbENhY2hlRGF0YS5sYXN0X3RpbWVzaGVldF9zZWxlY3RlZF9zaG93X3dhZ2UgKTtcblx0XHR9XG5cblx0XHQvL0Vycm9yOiBUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnR5ICdzaG93X3dhZ2UnIG9mIG51bGxcblx0XHQvL2p1c3QgbmVlZCB0byBjaGVjayB0aGF0IHRoZSB2YXJpYWJsZSBleGlzdHMgYmVmb3JlIGNoZWNraW5nIHByb3BlcnRpZXMgZm9yIHRoZSBjYXNlIG9mIHRoZSBMb2NhbENhY2hlRGF0YSBiZWluZyBlbXB0eVxuXHRcdGlmICggR2xvYmFsLmlzU2V0KCBMb2NhbENhY2hlRGF0YS5nZXRBbGxVUkxBcmdzKCkgKSAmJiBMb2NhbENhY2hlRGF0YS5nZXRBbGxVUkxBcmdzKCkuc2hvd193YWdlICkge1xuXHRcdFx0dGhpcy53YWdlX2J0bi5zZXRWYWx1ZSggTG9jYWxDYWNoZURhdGEuZ2V0QWxsVVJMQXJncygpLnNob3dfd2FnZSA9PT0gJzEnID8gdHJ1ZSA6IGZhbHNlICk7XG5cdFx0fVxuXG5cdFx0Ly8gU2V0IFVzZSBFbXBsb3llZSBUaW1lU2hlZXRcblx0XHRpZiAoICFMb2NhbENhY2hlRGF0YS5sYXN0X3RpbWVzaGVldF9zZWxlY3RlZF90aW1lem9uZSApIHtcblx0XHRcdHRoaXMudGltZXpvbmVfYnRuLnNldFZhbHVlKCBmYWxzZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnRpbWV6b25lX2J0bi5zZXRWYWx1ZSggTG9jYWxDYWNoZURhdGEubGFzdF90aW1lc2hlZXRfc2VsZWN0ZWRfdGltZXpvbmUgKTtcblx0XHR9XG5cblx0XHQvL0Vycm9yOiBUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnR5ICdzaG93X3dhZ2UnIG9mIG51bGxcblx0XHQvL2p1c3QgbmVlZCB0byBjaGVjayB0aGF0IHRoZSB2YXJpYWJsZSBleGlzdHMgYmVmb3JlIGNoZWNraW5nIHByb3BlcnRpZXMgZm9yIHRoZSBjYXNlIG9mIHRoZSBMb2NhbENhY2hlRGF0YSBiZWluZyBlbXB0eVxuXHRcdGlmICggR2xvYmFsLmlzU2V0KCBMb2NhbENhY2hlRGF0YS5nZXRBbGxVUkxBcmdzKCkgKSAmJiBMb2NhbENhY2hlRGF0YS5nZXRBbGxVUkxBcmdzKCkudGltZXpvbmUgKSB7XG5cdFx0XHR0aGlzLnRpbWV6b25lX2J0bi5zZXRWYWx1ZSggTG9jYWxDYWNoZURhdGEuZ2V0QWxsVVJMQXJncygpLnRpbWV6b25lID09PSAnMScgPyB0cnVlIDogZmFsc2UgKTtcblx0XHR9XG5cblx0XHQvLyBTZXQgcHVuY2ggbW9kZVxuXHRcdGlmICggIXRoaXMuc2hvd19wdW5jaF9tb2RlX3VpICkge1xuXHRcdFx0aWYgKCAhUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHRoaXMucGVybWlzc2lvbl9pZCwgJ3B1bmNoX3RpbWVzaGVldCcgKSAmJiAhUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHRoaXMucGVybWlzc2lvbl9pZCwgJ21hbnVhbF90aW1lc2hlZXQnICkgKSB7XG5cdFx0XHRcdHRoaXMudG9nZ2xlX2J1dHRvbi5zZXRWYWx1ZSggJ3B1bmNoJyApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0aWYgKCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggdGhpcy5wZXJtaXNzaW9uX2lkLCAncHVuY2hfdGltZXNoZWV0JyApICkge1xuXHRcdFx0XHRcdHRoaXMudG9nZ2xlX2J1dHRvbi5zZXRWYWx1ZSggJ3B1bmNoJyApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMTUgJiYgUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHRoaXMucGVybWlzc2lvbl9pZCwgJ21hbnVhbF90aW1lc2hlZXQnICkgKSB7XG5cdFx0XHRcdFx0dGhpcy50b2dnbGVfYnV0dG9uLnNldFZhbHVlKCAnbWFudWFsJyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdGlmICggIUxvY2FsQ2FjaGVEYXRhLmxhc3RfdGltZXNoZWV0X3NlbGVjdGVkX3B1bmNoX21vZGUgKSB7XG5cdFx0XHRcdHRoaXMudG9nZ2xlX2J1dHRvbi5zZXRWYWx1ZSggJ3B1bmNoJyApO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLnRvZ2dsZV9idXR0b24uc2V0VmFsdWUoIExvY2FsQ2FjaGVEYXRhLmxhc3RfdGltZXNoZWV0X3NlbGVjdGVkX3B1bmNoX21vZGUgKTtcblx0XHRcdH1cblx0XHRcdGlmICggTG9jYWxDYWNoZURhdGEuZ2V0QWxsVVJMQXJncygpLm1vZGUgKSB7XG5cdFx0XHRcdC8vIEZpeCB3cm9uZyB2YWx1ZSBmcm9tIHVybFxuXHRcdFx0XHR0aGlzLnRvZ2dsZV9idXR0b24uc2V0VmFsdWUoIExvY2FsQ2FjaGVEYXRhLmdldEFsbFVSTEFyZ3MoKS5tb2RlID09PSAnbWFudWFsJyA/ICdtYW51YWwnIDogJ3B1bmNoJyApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggR2xvYmFsLlVOSVRfVEVTVF9NT0RFID09IHRydWUgKSB7XG5cdFx0XHRMb2NhbENhY2hlRGF0YS5sYXN0X3RpbWVzaGVldF9zZWxlY3RlZF9kYXRlID0gJzE1LUZlYi0xOCc7XG5cdFx0fVxuXHRcdC8vcmVwbGFjZSBzZWxlY3QgbGF5b3V0IGZpbHRlcl9kYXRhIHRvIGZpbHRlciBzZXQgaW4gb25OYXZpZ2F0aW9uIGZ1bmN0aW9uIHdoZW4gZ290byB2aWV3IGZyb20gbmF2aWdhdGlvbiBjb250ZXh0IGdyb3VwXG5cdFx0aWYgKCBMb2NhbENhY2hlRGF0YS5kZWZhdWx0X2ZpbHRlcl9mb3JfbmV4dF9vcGVuX3ZpZXcgKSB7XG5cdFx0XHR0aGlzLmVtcGxveWVlX25hdi5zZXRWYWx1ZSggTG9jYWxDYWNoZURhdGEuZGVmYXVsdF9maWx0ZXJfZm9yX25leHRfb3Blbl92aWV3LnVzZXJfaWQgKTtcblx0XHRcdHRoaXMuc2V0RGF0ZVBpY2tlclZhbHVlKCBMb2NhbENhY2hlRGF0YS5kZWZhdWx0X2ZpbHRlcl9mb3JfbmV4dF9vcGVuX3ZpZXcuYmFzZV9kYXRlICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGlmICggTG9jYWxDYWNoZURhdGEuZ2V0QWxsVVJMQXJncygpLnVzZXJfaWQgKSB7XG5cdFx0XHRcdHRoaXMuZW1wbG95ZWVfbmF2LnNldFZhbHVlKCBMb2NhbENhY2hlRGF0YS5nZXRBbGxVUkxBcmdzKCkudXNlcl9pZCApO1xuXHRcdFx0fSBlbHNlIGlmICggTG9jYWxDYWNoZURhdGEubGFzdF90aW1lc2hlZXRfc2VsZWN0ZWRfdXNlciApIHtcblx0XHRcdFx0dGhpcy5lbXBsb3llZV9uYXYuc2V0VmFsdWUoIExvY2FsQ2FjaGVEYXRhLmxhc3RfdGltZXNoZWV0X3NlbGVjdGVkX3VzZXIgKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8vRGVmYXVsdCBzZXQgY3VycmVudCBsb2dpbiB1c2VyIGFzIHNlbGVjdCBFbXBsb3llZVxuXHRcdFx0XHR0aGlzLmVtcGxveWVlX25hdi5zZXRWYWx1ZSggbG9naW5Vc2VyICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggIUxvY2FsQ2FjaGVEYXRhLmxhc3RfdGltZXNoZWV0X3NlbGVjdGVkX2RhdGUgKSB7IC8vU2F2ZWQgY3VycmVudCBzZWxlY3QgZGF0ZSBpbiBjYWNoZS4gc28gc3RpbGwgc2VsZWN0IGxhc3Qgc2VsZWN0IGRhdGUgd2hlbiBnbyB0byBvdGhlciB2aWV3IGFuZCBiYWNrXG5cdFx0XHRcdGlmICggTG9jYWxDYWNoZURhdGEuY3VycmVudF9zZWxlY3RfZGF0ZSAmJiBHbG9iYWwuc3RyVG9EYXRlKCBMb2NhbENhY2hlRGF0YS5jdXJyZW50X3NlbGVjdF9kYXRlLCAnWVlZWS1NTS1ERCcgKSApIHsgLy9TZWxlY3QgZGF0ZSBnZXQgZnJvbSBVUkwuXG5cdFx0XHRcdFx0dGhpcy5zZXREYXRlUGlja2VyVmFsdWUoIEdsb2JhbC5zdHJUb0RhdGUoIExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfc2VsZWN0X2RhdGUsICdZWVlZLU1NLUREJyApLmZvcm1hdCgpICk7XG5cdFx0XHRcdFx0TG9jYWxDYWNoZURhdGEuY3VycmVudF9zZWxlY3RfZGF0ZSA9ICcnO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHZhciBkYXRlID0gbmV3IERhdGUoKTtcblx0XHRcdFx0XHR2YXIgZm9ybWF0ID0gR2xvYmFsLmdldExvZ2luVXNlckRhdGVGb3JtYXQoKTtcblx0XHRcdFx0XHR2YXIgZGF0ZVN0ciA9IGRhdGUuZm9ybWF0KCBmb3JtYXQgKTtcblx0XHRcdFx0XHR0aGlzLnNldERhdGVQaWNrZXJWYWx1ZSggZGF0ZVN0ciApO1xuXHRcdFx0XHR9XG5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMuc2V0RGF0ZVBpY2tlclZhbHVlKCBMb2NhbENhY2hlRGF0YS5sYXN0X3RpbWVzaGVldF9zZWxlY3RlZF9kYXRlICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly9Jc3N1ZSAjMzI2OCAtIFJhY2UgY29uZGl0aW9uIHdoZXJlIHByZXZpb3VzIHNlYXJjaCBsYXlvdXQgd2lsbCBub3QgZXhpc3QgaW4gVUkgd2hlbiBleHBlY3RlZCBhcyBBUEkgZm9yIGN1c3RvbSBmaWVsZCBkYXRhIGhhcyBub3QgcmV0dXJuZWQgeWV0LlxuXHRcdC8vVGltZXNoZWV0IG92ZXJyaWRlcyBpbml0RGF0YSgpIGZyb20gQmFzZVZpZXdDb250cm9sbGVyIHRoYXQgd2FpdHMgb24gdGhlIGN1c3RvbSBmaWVsZCBwcm9taXNlIHRvIHJlc29sdmUgYmVmb3JlIGNvbnRpbnVpbmcuXG5cdFx0VFRQcm9taXNlLndhaXQoICdCYXNlVmlld0NvbnRyb2xsZXInLCAnZ2V0Q3VzdG9tRmllbGRzJywgZnVuY3Rpb24oKSB7XG5cdFx0XHQkdGhpcy5pbml0TGF5b3V0KCk7XG5cdFx0fSApO1xuXG5cdFx0dGhpcy5zZXRNb3ZlT3JEcm9wTW9kZSggdGhpcy5zZWxlY3RfZHJhZ19tZW51X2lkID8gdGhpcy5zZWxlY3RfZHJhZ19tZW51X2lkIDogJ21vdmUnICk7XG5cdH1cblxuXHRzZXREYXRlUGlja2VyVmFsdWUoIHZhbCApIHtcblx0XHR0aGlzLnN0YXJ0X2RhdGVfcGlja2VyLnNldFZhbHVlKCB2YWwgKTtcblxuXHRcdHZhciBkZWZhdWx0X2RhdGUgPSB0aGlzLnN0YXJ0X2RhdGVfcGlja2VyLmdldERlZmF1bHRGb3JtYXRWYWx1ZSgpO1xuXG5cdFx0dmFyIHVzZXJfaWQgPSB0aGlzLmdldFNlbGVjdEVtcGxveWVlKCk7XG5cblx0XHRpZiAoIHVzZXJfaWQgJiZcblx0XHRcdCF0aGlzLmVkaXRfdmlldyAmJlxuXHRcdFx0Ly9SZW1vdmluZyBkYXRlIGZyb20gdGhlIGdlbmVyYXRlZCBVUkxzIHRvIGF2b2lkIGJvb2ttYXJraW5nIHRvIHN0YWxlIGRhdGVzIGJ5IHVzZXJzLlxuXHRcdFx0Ly8od2luZG93LmxvY2F0aW9uLmhyZWYuaW5kZXhPZiggJ2RhdGU9JyArIGRlZmF1bHRfZGF0ZSApID09PSAtMSB8fCB3aW5kb3cubG9jYXRpb24uaHJlZi5pbmRleE9mKCAndXNlcl9pZD0nICsgdGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpID09PSAtMSApKSApIHtcblx0XHRcdCggd2luZG93LmxvY2F0aW9uLmhyZWYuaW5kZXhPZiggJ3VzZXJfaWQ9JyArIHVzZXJfaWQgKSA9PT0gLTEgKSApIHtcblxuXHRcdFx0Ly92YXIgbG9jYXRpb24gPSBHbG9iYWwuZ2V0QmFzZVVSTCgpICsgJyMhbT0nICsgdGhpcy52aWV3SWQgKyAnJmRhdGU9JyArIGRlZmF1bHRfZGF0ZSArICcmdXNlcl9pZD0nICsgdGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpICsgJyZzaG93X3dhZ2U9JyArIHRoaXMud2FnZV9idG4uZ2V0VmFsdWUoIHRydWUgKSArICcmbW9kZT0nICsgdGhpcy50b2dnbGVfYnV0dG9uLmdldFZhbHVlKCk7XG5cdFx0XHR2YXIgbG9jYXRpb24gPSBHbG9iYWwuZ2V0QmFzZVVSTCgpICsgJyMhbT0nICsgdGhpcy52aWV3SWQgKyAnJnVzZXJfaWQ9JyArIHVzZXJfaWQgKyAnJnNob3dfd2FnZT0nICsgdGhpcy53YWdlX2J0bi5nZXRWYWx1ZSggdHJ1ZSApICsgJyZtb2RlPScgKyB0aGlzLnRvZ2dsZV9idXR0b24uZ2V0VmFsdWUoKTtcblxuXHRcdFx0aWYgKCBMb2NhbENhY2hlRGF0YS5nZXRBbGxVUkxBcmdzKCkgKSB7XG5cdFx0XHRcdGZvciAoIHZhciBrZXkgaW4gTG9jYWxDYWNoZURhdGEuZ2V0QWxsVVJMQXJncygpICkge1xuXHRcdFx0XHRcdC8vaWYgKCBrZXkgPT09ICdtJyB8fCBrZXkgPT09ICdkYXRlJyB8fCBrZXkgPT09ICd1c2VyX2lkJyB8fCBrZXkgPT09ICdzaG93X3dhZ2UnIHx8IGtleSA9PT0gJ21vZGUnICkge1xuXHRcdFx0XHRcdGlmICgga2V5ID09PSAnbScgfHwga2V5ID09PSAndXNlcl9pZCcgfHwga2V5ID09PSAnc2hvd193YWdlJyB8fCBrZXkgPT09ICd0aW1lem9uZScgfHwga2V5ID09PSAnbW9kZScgKSB7XG5cdFx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0bG9jYXRpb24gPSBsb2NhdGlvbiArICcmJyArIGtleSArICc9JyArIExvY2FsQ2FjaGVEYXRhLmdldEFsbFVSTEFyZ3MoKVtrZXldO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdEdsb2JhbC5zZXRVUkxUb0Jyb3dzZXIoIGxvY2F0aW9uICk7XG5cblx0XHR9XG5cblx0XHRMb2NhbENhY2hlRGF0YS5sYXN0X3RpbWVzaGVldF9zZWxlY3RlZF9kYXRlID0gdmFsO1xuXHR9XG5cblx0YnVpbGRTZWFyY2hGaWVsZHMoKSB7XG5cblx0XHRzdXBlci5idWlsZFNlYXJjaEZpZWxkcygpO1xuXHRcdHRoaXMuc2VhcmNoX2ZpZWxkcyA9IFtcblxuXHRcdFx0bmV3IFNlYXJjaEZpZWxkKCB7XG5cdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ1B1bmNoIEJyYW5jaCcgKSxcblx0XHRcdFx0aW5fY29sdW1uOiAxLFxuXHRcdFx0XHRmaWVsZDogJ2JyYW5jaF9pZCcsXG5cdFx0XHRcdGxheW91dF9uYW1lOiAnZ2xvYmFsX2JyYW5jaCcsXG5cdFx0XHRcdGFwaV9jbGFzczogVFRBUEkuQVBJQnJhbmNoLFxuXHRcdFx0XHRtdWx0aXBsZTogdHJ1ZSxcblx0XHRcdFx0YmFzaWNfc2VhcmNoOiB0cnVlLFxuXHRcdFx0XHRhZHZfc2VhcmNoOiBmYWxzZSxcblx0XHRcdFx0Zm9ybV9pdGVtX3R5cGU6IEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWFxuXHRcdFx0fSApLFxuXHRcdFx0bmV3IFNlYXJjaEZpZWxkKCB7XG5cdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ1B1bmNoIERlcGFydG1lbnQnICksXG5cdFx0XHRcdGZpZWxkOiAnZGVwYXJ0bWVudF9pZCcsXG5cdFx0XHRcdGluX2NvbHVtbjogMSxcblx0XHRcdFx0bGF5b3V0X25hbWU6ICdnbG9iYWxfZGVwYXJ0bWVudCcsXG5cdFx0XHRcdGFwaV9jbGFzczogVFRBUEkuQVBJRGVwYXJ0bWVudCxcblx0XHRcdFx0bXVsdGlwbGU6IHRydWUsXG5cdFx0XHRcdGJhc2ljX3NlYXJjaDogdHJ1ZSxcblx0XHRcdFx0YWR2X3NlYXJjaDogZmFsc2UsXG5cdFx0XHRcdGZvcm1faXRlbV90eXBlOiBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1hcblx0XHRcdH0gKSxcblx0XHRcdG5ldyBTZWFyY2hGaWVsZCgge1xuXHRcdFx0XHRsYWJlbDogJC5pMThuLl8oICdKb2InICksXG5cdFx0XHRcdGluX2NvbHVtbjogMixcblx0XHRcdFx0ZmllbGQ6ICdqb2JfaWQnLFxuXHRcdFx0XHRsYXlvdXRfbmFtZTogJ2dsb2JhbF9qb2InLFxuXHRcdFx0XHRhcGlfY2xhc3M6ICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSA/IFRUQVBJLkFQSUpvYiA6IG51bGwsXG5cdFx0XHRcdG11bHRpcGxlOiB0cnVlLFxuXHRcdFx0XHRiYXNpY19zZWFyY2g6ICggdGhpcy5zaG93X2pvYl9pdGVtX3VpICYmICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSApLFxuXHRcdFx0XHRhZHZfc2VhcmNoOiBmYWxzZSxcblx0XHRcdFx0Zm9ybV9pdGVtX3R5cGU6IEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWFxuXHRcdFx0fSApLFxuXG5cdFx0XHRuZXcgU2VhcmNoRmllbGQoIHtcblx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnVGFzaycgKSxcblx0XHRcdFx0aW5fY29sdW1uOiAyLFxuXHRcdFx0XHRmaWVsZDogJ2pvYl9pdGVtX2lkJyxcblx0XHRcdFx0bGF5b3V0X25hbWU6ICdnbG9iYWxfam9iX2l0ZW0nLFxuXHRcdFx0XHRhcGlfY2xhc3M6ICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSA/IFRUQVBJLkFQSUpvYkl0ZW0gOiBudWxsLFxuXHRcdFx0XHRtdWx0aXBsZTogdHJ1ZSxcblx0XHRcdFx0YmFzaWNfc2VhcmNoOiAoIHRoaXMuc2hvd19qb2JfaXRlbV91aSAmJiAoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpID49IDIwICkgKSxcblx0XHRcdFx0YWR2X3NlYXJjaDogZmFsc2UsXG5cdFx0XHRcdGZvcm1faXRlbV90eXBlOiBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1hcblx0XHRcdH0gKSxcblxuXHRcdFx0bmV3IFNlYXJjaEZpZWxkKCB7XG5cdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ1RhZ3MnICksXG5cdFx0XHRcdGluX2NvbHVtbjogMixcblx0XHRcdFx0ZmllbGQ6ICdwdW5jaF90YWdfaWQnLFxuXHRcdFx0XHRsYXlvdXRfbmFtZTogJ2dsb2JhbF9wdW5jaF90YWcnLFxuXHRcdFx0XHRhcGlfY2xhc3M6ICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSA/IFRUQVBJLkFQSVB1bmNoVGFnIDogbnVsbCxcblx0XHRcdFx0bXVsdGlwbGU6IHRydWUsXG5cdFx0XHRcdGJhc2ljX3NlYXJjaDogKCB0aGlzLnNob3dfcHVuY2hfdGFnX3VpICYmICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSApLFxuXHRcdFx0XHRhZHZfc2VhcmNoOiBmYWxzZSxcblx0XHRcdFx0Zm9ybV9pdGVtX3R5cGU6IEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWFxuXHRcdFx0fSApXG5cdFx0XTtcblx0fVxuXG5cdGdldFNlbGVjdEVtcGxveWVlKCBmdWxsX2l0ZW0gKSB7XG5cdFx0dmFyIHVzZXIgPSBmYWxzZTtcblx0XHRpZiAoIHRoaXMuc2hvd19uYXZpZ2F0aW9uX2JveCAmJiB0aGlzLmVtcGxveWVlX25hdiAmJiB0eXBlb2YgdGhpcy5lbXBsb3llZV9uYXYuZ2V0VmFsdWUgPT0gJ2Z1bmN0aW9uJyApIHtcblx0XHRcdHVzZXIgPSB0aGlzLmVtcGxveWVlX25hdi5nZXRWYWx1ZSggdHJ1ZSApOyAvL0Fsd2F5cyB0cnkgdG8gZ2V0IHRoZSBvYmplY3QgKG5vdCB0aGUgaWQpLCBob3dldmVyIGluIHNvbWUgY2FzZXMgbGlrZSByZWNhbGN1bGF0aW5nIHRpbWVzaGVldHMgaXQgc3RpbGwgc2VlbXMgdG8gcmV0dXJuIHRoZSBJRCBpbnN0ZWFkIG9mIHRoZSBvYmplY3QuXG5cdFx0fVxuXG5cdFx0Ly9Db252ZXJ0IG9iamVjdCBpZiBpdCBpc24ndCBhbHJlYWR5LCB0byBtYWtlIGxvZ2ljIGxvd2VyIGRvd24gZWFzaWVyLlxuXHRcdGlmICggR2xvYmFsLmlzT2JqZWN0KCB1c2VyICkgPT0gZmFsc2UgKSB7XG5cdFx0XHR1c2VyID0geyBpZDogdXNlciB9O1xuXHRcdH1cblxuXHRcdGlmICggR2xvYmFsLmlzT2JqZWN0KCB1c2VyICkgPT0gZmFsc2UgfHwgKCBHbG9iYWwuaXNPYmplY3QoIHVzZXIgKSA9PSB0cnVlICYmICggdXNlci5oYXNPd25Qcm9wZXJ0eSggJ2lkJyApID09IGZhbHNlIHx8IFRUVVVJRC5pc1VVSUQoIHVzZXIuaWQgKSA9PSBmYWxzZSApICkgKSB7XG5cdFx0XHR1c2VyID0gTG9jYWxDYWNoZURhdGEuZ2V0TG9naW5Vc2VyKCk7XG5cblx0XHRcdGlmICggR2xvYmFsLmlzT2JqZWN0KCB1c2VyICkgPT0gZmFsc2UgfHwgKCBHbG9iYWwuaXNPYmplY3QoIHVzZXIgKSA9PSB0cnVlICYmICggdXNlci5oYXNPd25Qcm9wZXJ0eSggJ2lkJyApID09IGZhbHNlIHx8IFRUVVVJRC5pc1VVSUQoIHVzZXIuaWQgKSA9PSBmYWxzZSApICkgKSB7XG5cdFx0XHRcdC8vY3VycmVudGx5IGxvZ2dlZCBpbiB1c2VyIG9iamVjdCBpcyBjb3JydXB0LlxuXHRcdFx0XHRNZW51TWFuYWdlci5kb0xvZ291dCgpO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKCBmdWxsX2l0ZW0gIT0gdHJ1ZSAmJiAoIEdsb2JhbC5pc09iamVjdCggdXNlciApID09IHRydWUgJiYgdXNlci5oYXNPd25Qcm9wZXJ0eSggJ2lkJyApID09IHRydWUgJiYgVFRVVUlELmlzVVVJRCggdXNlci5pZCApID09IHRydWUgKSApIHtcblx0XHRcdHVzZXIgPSB1c2VyLmlkO1xuXHRcdH1cblxuXHRcdHJldHVybiB1c2VyO1xuXHR9XG5cblx0Z2V0U2VsZWN0RGF0ZSgpIHtcblx0XHRpZiAoIHRoaXMuc3RhcnRfZGF0ZV9waWNrZXIgKSB7XG5cdFx0XHR2YXIgcmV0dmFsID0gdGhpcy5zdGFydF9kYXRlX3BpY2tlci5nZXRWYWx1ZSgpO1xuXG5cdFx0XHRpZiAoIHJldHZhbCA9PSAnSW52YWxpZCBkYXRlJyApIHtcblx0XHRcdFx0cmV0dmFsID0gbmV3IERhdGUoKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIHJldHZhbDtcblx0XHR9XG5cblx0XHRyZXR1cm4gbnVsbDtcblx0fVxuXG5cdG9uRGVsZXRlUmVzdWx0KCByZXN1bHQgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHQkdGhpcy50aW1lc2hlZXRfZ3JpZC5ncmlkLmZpbmQoICd0ZC51aS1zdGF0ZS1oaWdobGlnaHQnICkucmVtb3ZlQ2xhc3MoICd1aS1zdGF0ZS1oaWdobGlnaHQnICk7XG5cdFx0UHJvZ3Jlc3NCYXIuY2xvc2VPdmVybGF5KCk7XG5cdFx0aWYgKCByZXN1bHQuaXNWYWxpZCgpICkge1xuXHRcdFx0aWYgKCAkdGhpcy5lZGl0X3ZpZXcgKSB7XG5cdFx0XHRcdGlmICggTG9jYWxDYWNoZURhdGEuY3VycmVudF9kb2luZ19jb250ZXh0X2FjdGlvbiA9PT0gJ2RlbGV0ZScgKSB7XG5cdFx0XHRcdFx0JHRoaXMucmVtb3ZlRWRpdFZpZXcoKTtcblx0XHRcdFx0fSBlbHNlIGlmICggJHRoaXMuZWRpdF92aWV3ICYmIExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfZG9pbmdfY29udGV4dF9hY3Rpb24gPT09ICdkZWxldGVfYW5kX25leHQnICkge1xuXHRcdFx0XHRcdCR0aGlzLm9uUmlnaHRBcnJvd0NsaWNrKCk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMuc2V0Q3VycmVudEVkaXRWaWV3U3RhdGUoICcnICk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdCR0aGlzLnJldmVydEVkaXRWaWV3U3RhdGUoKTtcblx0XHRcdFRBbGVydE1hbmFnZXIuc2hvd0Vycm9yQWxlcnQoIHJlc3VsdCApO1xuXHRcdH1cblxuXHRcdC8vIHJlZnJlc2ggYW5kIHJlYnVpbGQgc2VhcmNoIGdyaWQsIGFzIHdlbGwgYXMgZGVmYXVsdCBtZW51XG5cdFx0JHRoaXMuZmlyc3RfYnVpbGQgPSB0cnVlO1xuXHRcdCR0aGlzLnNlYXJjaCgpO1xuXHRcdCR0aGlzLnNldERlZmF1bHRNZW51KCk7IC8vRGVmYXVsdCBtZW51IG5lZWRzIHRvIGJlIHNldCBhcyB3ZSBuZWVkIHRvIGRlYWN0aXZhdGUgaWNvbnMgdGhhdCBhcmUgdmFsaWQgZm9yIHRoZSBwcmVkZWxldGlvbiBzZWxlY3Rpb25cblx0fVxuXG5cdGdldERlbGV0ZVNlbGVjdGVkUmVjb3JkSWQoKSB7XG5cdFx0dmFyIHJldHZhbCA9IFtdO1xuXHRcdGlmICggdGhpcy5lZGl0X3ZpZXcgKSB7XG5cdFx0XHRyZXR2YWwucHVzaCggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGZvciAoIHZhciBpIGluIHRoaXMuc2VsZWN0X3B1bmNoZXNfYXJyYXkgKSB7XG5cdFx0XHRcdHZhciBpdGVtID0gdGhpcy5zZWxlY3RfcHVuY2hlc19hcnJheVtpXTtcblx0XHRcdFx0cmV0dmFsLnB1c2goIGl0ZW0uaWQgKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHJldHZhbDtcblx0fVxuXG5cdHJlU2V0VVJMKCkge1xuXHRcdC8vdmFyIGFyZ3MgPSAnIyFtPScgKyB0aGlzLnZpZXdJZCArICcmZGF0ZT0nICsgdGhpcy5zdGFydF9kYXRlX3BpY2tlci5nZXREZWZhdWx0Rm9ybWF0VmFsdWUoKSArICcmdXNlcl9pZD0nICsgdGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpICsgJyZzaG93X3dhZ2U9JyArIHRoaXMud2FnZV9idG4uZ2V0VmFsdWUoIHRydWUgKSArICcmbW9kZT0nICsgdGhpcy50b2dnbGVfYnV0dG9uLmdldFZhbHVlKCk7XG5cdFx0dmFyIGFyZ3MgPSAnIyFtPScgKyB0aGlzLnZpZXdJZCArICcmdXNlcl9pZD0nICsgdGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpICsgJyZzaG93X3dhZ2U9JyArIHRoaXMud2FnZV9idG4uZ2V0VmFsdWUoIHRydWUgKSArICcmdGltZXpvbmU9JyArIHRoaXMudGltZXpvbmVfYnRuLmdldFZhbHVlKCB0cnVlICkgKyAnJm1vZGU9JyArIHRoaXMudG9nZ2xlX2J1dHRvbi5nZXRWYWx1ZSgpO1xuXHRcdEdsb2JhbC5zZXRVUkxUb0Jyb3dzZXIoIEdsb2JhbC5nZXRCYXNlVVJMKCkgKyBhcmdzICk7XG5cdFx0TG9jYWxDYWNoZURhdGEuc2V0QWxsVVJMQXJncyggR2xvYmFsLmJ1aWxkQXJnRGljKCBhcmdzLnNwbGl0KCAnJicgKSApICk7XG5cdH1cblxuXHRvblNhdmVBbmRDb250aW51ZSggaWdub3JlV2FybmluZyApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdGlmICggIUdsb2JhbC5pc1NldCggaWdub3JlV2FybmluZyApICkge1xuXHRcdFx0aWdub3JlV2FybmluZyA9IGZhbHNlO1xuXHRcdH1cblx0XHR0aGlzLmlzX2NoYW5nZWQgPSBmYWxzZTtcblx0XHRMb2NhbENhY2hlRGF0YS5jdXJyZW50X2RvaW5nX2NvbnRleHRfYWN0aW9uID0gJ3NhdmVfYW5kX2NvbnRpbnVlJztcblx0XHR2YXIgY3VycmVudF9hcGkgPSB0aGlzLmdldEN1cnJlbnRBUEkoKTtcblxuXHRcdGlmICggdGhpcy5pc19tYXNzX2FkZGluZyAmJiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQucHVuY2hfZGF0ZXMgJiYgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnB1bmNoX2RhdGVzLmxlbmd0aCA9PT0gMSApIHtcblx0XHRcdHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5wdW5jaF9kYXRlID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnB1bmNoX2RhdGVzWzBdO1xuXHRcdH1cblxuXHRcdGN1cnJlbnRfYXBpLnNldElzSWRlbXBvdGVudCggdHJ1ZSApOyAvL0ZvcmNlIHRvIGlkZW1wb3RlbnQgQVBJIGNhbGwgdG8gYXZvaWQgZHVwbGljYXRlIG5ldHdvcmsgcmVxdWVzdHMgZnJvbSBjYXVzaW5nIGVycm9ycyBkaXNwbGF5ZWQgdG8gdGhlIHVzZXIuXG5cdFx0Y3VycmVudF9hcGlbJ3NldCcgKyBjdXJyZW50X2FwaS5rZXlfbmFtZV0oIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCwgZmFsc2UsIGlnbm9yZVdhcm5pbmcsIHtcblx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHRpZiAoIHJlc3VsdC5pc1ZhbGlkKCkgKSB7XG5cdFx0XHRcdFx0dmFyIHJlc3VsdF9kYXRhID0gcmVzdWx0LmdldFJlc3VsdCgpO1xuXHRcdFx0XHRcdHZhciByZWZyZXNoX2lkO1xuXHRcdFx0XHRcdGlmICggcmVzdWx0X2RhdGEgPT09IHRydWUgKSB7XG5cdFx0XHRcdFx0XHRyZWZyZXNoX2lkID0gJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZDtcblxuXHRcdFx0XHRcdH0gZWxzZSBpZiAoIFRUVVVJRC5pc1VVSUQoIHJlc3VsdF9kYXRhICkgJiYgcmVzdWx0X2RhdGEgIT0gVFRVVUlELnplcm9faWQgJiYgcmVzdWx0X2RhdGEgIT0gVFRVVUlELm5vdF9leGlzdF9pZCApIHtcblx0XHRcdFx0XHRcdHJlZnJlc2hfaWQgPSByZXN1bHRfZGF0YTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0JHRoaXMuc2VhcmNoKCk7XG5cdFx0XHRcdFx0JHRoaXMub25FZGl0Q2xpY2soIHJlZnJlc2hfaWQsICR0aGlzLmdldFB1bmNoUGVybWlzc2lvblR5cGUoKSApO1xuXG5cdFx0XHRcdFx0Ly8jMjI5NSAtIFJlLWluaXRpYWxpemUgcHJldmlvdXNfYWJzZW5jZV9wb2xpY3lfaWQgdG8gZW5zdXJlIHRoYXQgcHJldmlvdXNseSBzYXZlZCB2YWx1ZXMgYXJlIHBhc3NlZCBjb3JyZWN0bHkgaW50byB0aGUgZXN0aW1hdGlvbiBvZiBwcm9qZWN0ZWQgYXZhaWxhYmxlIGJhbGFuY2UuXG5cdFx0XHRcdFx0JHRoaXMucHJldmlvdXNfYWJzZW5jZV9wb2xpY3lfaWQgPSBmYWxzZTtcblxuXHRcdFx0XHRcdCR0aGlzLm9uU2F2ZUFuZENvbnRpbnVlRG9uZSggcmVzdWx0ICk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JHRoaXMuc2V0RXJyb3JNZW51KCk7XG5cdFx0XHRcdFx0JHRoaXMuc2V0RXJyb3JUaXBzKCByZXN1bHQgKTtcblxuXHRcdFx0XHR9XG5cblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cblxuXHRnZXRTZWxlY3RlZFJlY29yZElkKCByZWNvcmQgKSB7XG5cdFx0dmFyIHJldHZhbCA9IGZhbHNlO1xuXG5cdFx0aWYgKCBHbG9iYWwuaXNTZXQoIHJlY29yZCApICkge1xuXHRcdFx0aWYgKCBHbG9iYWwuaXNPYmplY3QoIHJlY29yZCApICYmIHJlY29yZC5pZCApIHtcblx0XHRcdFx0cmV0dmFsID0gcmVjb3JkLmlkO1xuXHRcdFx0fSBlbHNlIGlmICggR2xvYmFsLmlzU3RyaW5nKCByZWNvcmQgKSAmJiBUVFVVSUQuaXNVVUlEKCByZWNvcmQgKSApIHtcblx0XHRcdFx0cmV0dmFsID0gcmVjb3JkO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRpZiAoIHRoaXMuc2VsZWN0X3B1bmNoZXNfYXJyYXkubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0cmV0dmFsID0gdGhpcy5zZWxlY3RfcHVuY2hlc19hcnJheVswXS5pZDtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHJldHZhbCA9IG51bGw7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHJldHZhbDtcblx0fVxuXG5cdGdldFZpZXdTZWxlY3RlZFJlY29yZElkKCByZWNvcmQgKSB7XG5cdFx0cmV0dXJuIHRoaXMuZ2V0U2VsZWN0ZWRSZWNvcmRJZCggcmVjb3JkICk7XG5cdH1cblxuXHRkb1ZpZXdBUElDYWxsKCBmaWx0ZXIsIGFwaV9hcmdzICkge1xuXHRcdHZhciBjdXJyZW50X2FwaSA9IHRoaXMuZ2V0Q3VycmVudEFQSSgpO1xuXHRcdHZhciBjYWxsYmFjayA9IHsgb25SZXN1bHQ6IHRoaXMuaGFuZGxlVmlld0FQSUNhbGxiYWNrUmVzdWx0LmJpbmQoIHRoaXMgKSB9O1xuXHRcdGlmICggYXBpX2FyZ3MgKSB7XG5cdFx0XHQvLyBJZiBhcGlfYXJncyBzcGVjaWZpZWQsIHVzZSBhcGlfYXJncy5maWx0ZXIsIGFuZCBpZ25vcmUgZnVuY3Rpb24gZmlsdGVyIHBhcmFtZXRlci5cblx0XHRcdGFwaV9hcmdzLnB1c2goIGNhbGxiYWNrICk7XG5cdFx0XHRyZXR1cm4gY3VycmVudF9hcGlbJ2dldCcgKyBjdXJyZW50X2FwaS5rZXlfbmFtZV0uYXBwbHkoIGN1cnJlbnRfYXBpLCBhcGlfYXJncyApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gY3VycmVudF9hcGlbJ2dldCcgKyBjdXJyZW50X2FwaS5rZXlfbmFtZV0oIGZpbHRlciwgY2FsbGJhY2sgKTtcblx0XHR9XG5cdH1cblxuXHRvblZpZXdDbGljayggcmVjb3JkLCB0eXBlICkge1xuXHRcdHZhciB0bXBfcmVjb3JkX2lkID0gdGhpcy5nZXRWaWV3U2VsZWN0ZWRSZWNvcmRJZCggcmVjb3JkICk7XG5cdFx0aWYgKCBHbG9iYWwuaXNGYWxzZU9yTnVsbCggdG1wX3JlY29yZF9pZCApIHx8IHRtcF9yZWNvcmRfaWQgPT0gVFRVVUlELm5vdF9leGlzdF9pZCApIHtcblx0XHRcdFRBbGVydE1hbmFnZXIuc2hvd0FsZXJ0KCAkLmkxOG4uXyggJ1RoaXMgcHVuY2ggaXMgc3RpbGwgYmVpbmcgcHJvY2Vzc2VkLCBwbGVhc2UgdHJ5IGFnYWluIGxhdGVyLicgKSAgKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIHR5cGUgKSB7XG5cdFx0XHRpZiAoIHR5cGUgPT09ICdhYnNlbmNlJyApIHtcblx0XHRcdFx0dGhpcy5hYnNlbmNlX21vZGVsID0gdHJ1ZTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMuYWJzZW5jZV9tb2RlbCA9IGZhbHNlO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRzdXBlci5vblZpZXdDbGljayggcmVjb3JkICk7XG5cdH1cblxuXHRidWlsZE90aGVyRmllbGRVSSggZmllbGQsIGxhYmVsICkge1xuXG5cdFx0aWYgKCAhdGhpcy5lZGl0X3ZpZXdfdGFiICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBmb3JtX2l0ZW1faW5wdXQ7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgdGFiX3B1bmNoID0gdGhpcy5lZGl0X3ZpZXdfdGFiLmZpbmQoICcjdGFiX3B1bmNoJyApO1xuXHRcdHZhciB0YWJfcHVuY2hfY29sdW1uMSA9IHRhYl9wdW5jaC5maW5kKCAnLmZpcnN0LWNvbHVtbicgKTtcblxuXHRcdGlmICggJHRoaXMuZWRpdF92aWV3X3VpX2RpY1tmaWVsZF0gKSB7XG5cdFx0XHRmb3JtX2l0ZW1faW5wdXQgPSAkdGhpcy5lZGl0X3ZpZXdfdWlfZGljW2ZpZWxkXTtcblx0XHRcdGZvcm1faXRlbV9pbnB1dC5zZXRWYWx1ZSggJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFtmaWVsZF0gKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5URVhUX0lOUFVUICk7XG5cdFx0XHRmb3JtX2l0ZW1faW5wdXQuVFRleHRJbnB1dCggeyBmaWVsZDogZmllbGQgfSApO1xuXHRcdFx0dmFyIGlucHV0X2RpdiA9ICR0aGlzLmFkZEVkaXRGaWVsZFRvQ29sdW1uKCBsYWJlbCwgZm9ybV9pdGVtX2lucHV0LCB0YWJfcHVuY2hfY29sdW1uMSApO1xuXG5cdFx0XHRpbnB1dF9kaXYuaW5zZXJ0QmVmb3JlKCB0aGlzLmVkaXRfdmlld19mb3JtX2l0ZW1fZGljWydub3RlJ10gKTtcblxuXHRcdFx0Zm9ybV9pdGVtX2lucHV0LnNldFZhbHVlKCAkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2ZpZWxkXSApO1xuXHRcdH1cblx0XHRmb3JtX2l0ZW1faW5wdXQuY3NzKCAnb3BhY2l0eScsIDEgKTtcblx0XHRmb3JtX2l0ZW1faW5wdXQuY3NzKCAnbWluV2lkdGgnLCAzMDAgKTtcblxuXHRcdGlmICggJHRoaXMuaXNfdmlld2luZyApIHtcblx0XHRcdGZvcm1faXRlbV9pbnB1dC5zZXRFbmFibGVkKCBmYWxzZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRmb3JtX2l0ZW1faW5wdXQuc2V0RW5hYmxlZCggdHJ1ZSApO1xuXHRcdH1cblx0fVxuXG5cdG9uTWFzc0VkaXRDbGljaygpIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfZG9pbmdfY29udGV4dF9hY3Rpb24gPSAnbWFzc19lZGl0Jztcblx0XHQkdGhpcy5vcGVuRWRpdFZpZXcoKTtcblx0XHR0aGlzLmlzX21hc3NfYWRkaW5nID0gZmFsc2U7XG5cdFx0dGhpcy5pc192aWV3aW5nID0gZmFsc2U7XG5cblx0XHR2YXIgY3VycmVudF9hcGkgPSB0aGlzLmdldEN1cnJlbnRBUEkoKTtcblxuXHRcdHZhciBmaWx0ZXIgPSB7fTtcblx0XHR0aGlzLm1hc3NfZWRpdF9yZWNvcmRfaWRzID0gW107XG5cblx0XHQkLmVhY2goIHRoaXMuc2VsZWN0X3B1bmNoZXNfYXJyYXksIGZ1bmN0aW9uKCBpbmRleCwgdmFsdWUgKSB7XG5cdFx0XHQkdGhpcy5tYXNzX2VkaXRfcmVjb3JkX2lkcy5wdXNoKCB2YWx1ZS5pZCApO1xuXHRcdH0gKTtcblxuXHRcdGZpbHRlci5maWx0ZXJfZGF0YSA9IHt9O1xuXHRcdGZpbHRlci5maWx0ZXJfZGF0YS5pZCA9IHRoaXMubWFzc19lZGl0X3JlY29yZF9pZHM7XG5cblx0XHRjdXJyZW50X2FwaVsnZ2V0Q29tbW9uJyArIGN1cnJlbnRfYXBpLmtleV9uYW1lICsgJ0RhdGEnXSggZmlsdGVyLCB7XG5cdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlc3VsdCApIHtcblx0XHRcdFx0dmFyIHJlc3VsdF9kYXRhID0gcmVzdWx0LmdldFJlc3VsdCgpO1xuXHRcdFx0XHRjdXJyZW50X2FwaVsnZ2V0T3B0aW9ucyddKCAndW5pcXVlX2NvbHVtbnMnLCB7XG5cdFx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cdFx0XHRcdFx0XHQkdGhpcy51bmlxdWVfY29sdW1ucyA9IHJlc3VsdC5nZXRSZXN1bHQoKTtcblx0XHRcdFx0XHRcdGN1cnJlbnRfYXBpWydnZXRPcHRpb25zJ10oICdsaW5rZWRfY29sdW1ucycsIHtcblx0XHRcdFx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQxICkge1xuXG5cdFx0XHRcdFx0XHRcdFx0JHRoaXMubGlua2VkX2NvbHVtbnMgPSByZXN1bHQxLmdldFJlc3VsdCgpO1xuXG5cdFx0XHRcdFx0XHRcdFx0aWYgKCAkdGhpcy5zdWJfdmlld19tb2RlICYmICR0aGlzLnBhcmVudF9rZXkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRyZXN1bHRfZGF0YVskdGhpcy5wYXJlbnRfa2V5XSA9ICR0aGlzLnBhcmVudF92YWx1ZTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0XHRpZiAoICFHbG9iYWwuaXNTZXQoIHJlc3VsdF9kYXRhLnRpbWVfc3RhbXAgKSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdHJlc3VsdF9kYXRhLnRpbWVfc3RhbXAgPSBmYWxzZTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0XHQkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkID0gcmVzdWx0X2RhdGE7XG5cdFx0XHRcdFx0XHRcdFx0JHRoaXMuaXNfbWFzc19lZGl0aW5nID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0XHQkdGhpcy5pbml0RWRpdFZpZXcoKTtcblxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9ICk7XG5cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0fVxuXHRcdH0gKTtcblx0fVxuXG5cdHNldFN1YkxvZ1ZpZXdGaWx0ZXIoKSB7XG5cdFx0aWYgKCAhdGhpcy5zdWJfbG9nX3ZpZXdfY29udHJvbGxlciApIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHR0aGlzLnN1Yl9sb2dfdmlld19jb250cm9sbGVyLmdldFN1YlZpZXdGaWx0ZXIgPSBmdW5jdGlvbiggZmlsdGVyICkge1xuXG5cdFx0XHRpZiAoICF0aGlzLnBhcmVudF92aWV3X2NvbnRyb2xsZXIuYWJzZW5jZV9tb2RlbCApIHtcblx0XHRcdFx0ZmlsdGVyWyd0YWJsZV9uYW1lX29iamVjdF9pZCddID0ge1xuXHRcdFx0XHRcdCdwdW5jaCc6IFt0aGlzLnBhcmVudF9lZGl0X3JlY29yZC5pZF0sXG5cdFx0XHRcdFx0J3B1bmNoX2NvbnRyb2wnOiBbdGhpcy5wYXJlbnRfZWRpdF9yZWNvcmQucHVuY2hfY29udHJvbF9pZF1cblx0XHRcdFx0fTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGZpbHRlclsndGFibGVfbmFtZSddID0gJ3VzZXJfZGF0ZV90b3RhbCc7XG5cdFx0XHRcdGZpbHRlclsnb2JqZWN0X2lkJ10gPSB0aGlzLnBhcmVudF9lZGl0X3JlY29yZC5pZDtcblxuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gZmlsdGVyO1xuXHRcdH07XG5cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdGdldEVkaXRTZWxlY3RlZFJlY29yZElkKCByZWNvcmRfaWQgKSB7XG5cdFx0cmV0dXJuIHRoaXMuZ2V0U2VsZWN0ZWRSZWNvcmRJZCggcmVjb3JkX2lkICk7XG5cdH1cblxuXHRkb0VkaXRBUElDYWxsKCBmaWx0ZXIsIGFwaV9hcmdzICkge1xuXHRcdHZhciBjdXJyZW50X2FwaSA9IHRoaXMuZ2V0Q3VycmVudEFQSSgpO1xuXHRcdHZhciBjYWxsYmFjayA9IHsgb25SZXN1bHQ6IHRoaXMuaGFuZGxlRWRpdEFQSUNhbGxiYWNrUmVzdWx0LmJpbmQoIHRoaXMgKSB9O1xuXHRcdGlmICggYXBpX2FyZ3MgKSB7XG5cdFx0XHQvLyBJZiBhcGlfYXJncyBzcGVjaWZpZWQsIHVzZSBhcGlfYXJncy5maWx0ZXIsIGFuZCBpZ25vcmUgZnVuY3Rpb24gZmlsdGVyIHBhcmFtZXRlci5cblx0XHRcdGFwaV9hcmdzLnB1c2goIGNhbGxiYWNrICk7XG5cdFx0XHRyZXR1cm4gY3VycmVudF9hcGlbJ2dldCcgKyBjdXJyZW50X2FwaS5rZXlfbmFtZV0uYXBwbHkoIGN1cnJlbnRfYXBpLCBhcGlfYXJncyApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gY3VycmVudF9hcGlbJ2dldCcgKyBjdXJyZW50X2FwaS5rZXlfbmFtZV0oIGZpbHRlciwgY2FsbGJhY2sgKTtcblx0XHR9XG5cdH1cblxuXHRvbkVkaXRDbGljayggcmVjb3JkX2lkLCB0eXBlICkge1xuXHRcdHZhciB0bXBfcmVjb3JkX2lkID0gdGhpcy5nZXRWaWV3U2VsZWN0ZWRSZWNvcmRJZCggcmVjb3JkX2lkICk7XG5cdFx0aWYgKCBHbG9iYWwuaXNGYWxzZU9yTnVsbCggdG1wX3JlY29yZF9pZCApIHx8IHRtcF9yZWNvcmRfaWQgPT0gVFRVVUlELm5vdF9leGlzdF9pZCApIHtcblx0XHRcdFRBbGVydE1hbmFnZXIuc2hvd0FsZXJ0KCAkLmkxOG4uXyggJ1RoaXMgcHVuY2ggaXMgc3RpbGwgYmVpbmcgcHJvY2Vzc2VkLCBwbGVhc2UgdHJ5IGFnYWluIGxhdGVyLicgKSAgKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIHR5cGUgKSB7XG5cdFx0XHRpZiAoIHR5cGUgPT09ICdhYnNlbmNlJyApIHtcblx0XHRcdFx0dGhpcy5hYnNlbmNlX21vZGVsID0gdHJ1ZTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMuYWJzZW5jZV9tb2RlbCA9IGZhbHNlO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRzdXBlci5vbkVkaXRDbGljayggcmVjb3JkX2lkICk7XG5cdH1cblxuXHRzZXRVUkwoKSB7XG5cdFx0dmFyIHQgPSB0aGlzLmdldFB1bmNoUGVybWlzc2lvblR5cGUoKTtcblx0XHR2YXIgYSA9ICcnO1xuXHRcdHN3aXRjaCAoIExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfZG9pbmdfY29udGV4dF9hY3Rpb24gKSB7XG5cdFx0XHRjYXNlICduZXcnOlxuXHRcdFx0Y2FzZSAnZWRpdCc6XG5cdFx0XHRjYXNlICd2aWV3Jzpcblx0XHRcdFx0YSA9IExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfZG9pbmdfY29udGV4dF9hY3Rpb247XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnY29weV9hc19uZXcnOlxuXHRcdFx0XHRhID0gJ25ldyc7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdH1cblxuXHRcdHZhciB0YWJfbmFtZSA9IHRoaXMuZWRpdF92aWV3X3RhYiA/IHRoaXMuZWRpdF92aWV3X3RhYi5maW5kKCAnLmVkaXQtdmlldy10YWItYmFyLWxhYmVsJyApLmNoaWxkcmVuKCkuZXEoIHRoaXMuZ2V0RWRpdFZpZXdUYWJJbmRleCgpICkudGV4dCgpIDogJyc7XG5cdFx0dGFiX25hbWUgPSB0YWJfbmFtZS5yZXBsYWNlKCAvXFwvfFxccysvZywgJycgKTtcblxuXHRcdC8vRXJyb3I6IFVuYWJsZSB0byBnZXQgcHJvcGVydHkgJ2lkJyBvZiB1bmRlZmluZWQgb3IgbnVsbCByZWZlcmVuY2UgaW4gL2ludGVyZmFjZS9odG1sNS92aWV3cy9CYXNlVmlld0NvbnRyb2xsZXIuanM/dj04LjAuMC0yMDE0MTExNy0xMzI5NDEgbGluZSAyMjM0XG5cdFx0aWYgKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgJiYgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkICkge1xuXG5cdFx0XHRpZiAoIGEgKSB7XG5cdFx0XHRcdC8vR2xvYmFsLnNldFVSTFRvQnJvd3NlciggR2xvYmFsLmdldEJhc2VVUkwoKSArICcjIW09JyArIHRoaXMudmlld0lkICsgJyZkYXRlPScgKyB0aGlzLnN0YXJ0X2RhdGVfcGlja2VyLmdldERlZmF1bHRGb3JtYXRWYWx1ZSgpICsgJyZ1c2VyX2lkPScgKyB0aGlzLmdldFNlbGVjdEVtcGxveWVlKCkgKyAnJnNob3dfd2FnZT0nICsgdGhpcy53YWdlX2J0bi5nZXRWYWx1ZSggdHJ1ZSApICsgJyZtb2RlPScgKyB0aGlzLnRvZ2dsZV9idXR0b24uZ2V0VmFsdWUoKSArICcmYT0nICsgYSArICcmaWQ9JyArIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCArICcmdD0nICsgdCArXG5cdFx0XHRcdEdsb2JhbC5zZXRVUkxUb0Jyb3dzZXIoIEdsb2JhbC5nZXRCYXNlVVJMKCkgKyAnIyFtPScgKyB0aGlzLnZpZXdJZCArICcmdXNlcl9pZD0nICsgdGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpICsgJyZzaG93X3dhZ2U9JyArIHRoaXMud2FnZV9idG4uZ2V0VmFsdWUoIHRydWUgKSArICcmbW9kZT0nICsgdGhpcy50b2dnbGVfYnV0dG9uLmdldFZhbHVlKCkgKyAnJmE9JyArIGEgKyAnJmlkPScgKyB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgKyAnJnQ9JyArIHQgKyAnJnRhYj0nICsgdGFiX25hbWUgKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8vR2xvYmFsLnNldFVSTFRvQnJvd3NlciggR2xvYmFsLmdldEJhc2VVUkwoKSArICcjIW09JyArIHRoaXMudmlld0lkICsgJyZkYXRlPScgKyB0aGlzLnN0YXJ0X2RhdGVfcGlja2VyLmdldERlZmF1bHRGb3JtYXRWYWx1ZSgpICsgJyZ1c2VyX2lkPScgKyB0aGlzLmdldFNlbGVjdEVtcGxveWVlKCkgKyAnJnNob3dfd2FnZT0nICsgdGhpcy53YWdlX2J0bi5nZXRWYWx1ZSggdHJ1ZSApICsgJyZtb2RlPScgKyB0aGlzLnRvZ2dsZV9idXR0b24uZ2V0VmFsdWUoKSArICcmaWQ9JyArIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCArICcmdD0nICsgdCApO1xuXHRcdFx0XHRHbG9iYWwuc2V0VVJMVG9Ccm93c2VyKCBHbG9iYWwuZ2V0QmFzZVVSTCgpICsgJyMhbT0nICsgdGhpcy52aWV3SWQgKyAnJnVzZXJfaWQ9JyArIHRoaXMuZ2V0U2VsZWN0RW1wbG95ZWUoKSArICcmc2hvd193YWdlPScgKyB0aGlzLndhZ2VfYnRuLmdldFZhbHVlKCB0cnVlICkgKyAnJm1vZGU9JyArIHRoaXMudG9nZ2xlX2J1dHRvbi5nZXRWYWx1ZSgpICsgJyZpZD0nICsgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkICsgJyZ0PScgKyB0ICk7XG5cdFx0XHR9XG5cblx0XHRcdEdsb2JhbC50cmFja1ZpZXcoKTtcblxuXHRcdH0gZWxzZSB7XG5cblx0XHRcdGlmICggYSApIHtcblx0XHRcdFx0Ly9HbG9iYWwuc2V0VVJMVG9Ccm93c2VyKCBHbG9iYWwuZ2V0QmFzZVVSTCgpICsgJyMhbT0nICsgdGhpcy52aWV3SWQgKyAnJmRhdGU9JyArIHRoaXMuc3RhcnRfZGF0ZV9waWNrZXIuZ2V0RGVmYXVsdEZvcm1hdFZhbHVlKCkgKyAnJnVzZXJfaWQ9JyArIHRoaXMuZ2V0U2VsZWN0RW1wbG95ZWUoKSArICcmc2hvd193YWdlPScgKyB0aGlzLndhZ2VfYnRuLmdldFZhbHVlKCB0cnVlICkgKyAnJm1vZGU9JyArIHRoaXMudG9nZ2xlX2J1dHRvbi5nZXRWYWx1ZSgpICsgJyZhPScgKyBhICsgJyZ0PScgKyB0ICtcblx0XHRcdFx0R2xvYmFsLnNldFVSTFRvQnJvd3NlciggR2xvYmFsLmdldEJhc2VVUkwoKSArICcjIW09JyArIHRoaXMudmlld0lkICsgJyZ1c2VyX2lkPScgKyB0aGlzLmdldFNlbGVjdEVtcGxveWVlKCkgKyAnJnNob3dfd2FnZT0nICsgdGhpcy53YWdlX2J0bi5nZXRWYWx1ZSggdHJ1ZSApICsgJyZtb2RlPScgKyB0aGlzLnRvZ2dsZV9idXR0b24uZ2V0VmFsdWUoKSArICcmYT0nICsgYSArICcmdD0nICsgdCArICcmdGFiPScgKyB0YWJfbmFtZSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Ly9HbG9iYWwuc2V0VVJMVG9Ccm93c2VyKCBHbG9iYWwuZ2V0QmFzZVVSTCgpICsgJyMhbT0nICsgdGhpcy52aWV3SWQgKyAnJmRhdGU9JyArIHRoaXMuc3RhcnRfZGF0ZV9waWNrZXIuZ2V0RGVmYXVsdEZvcm1hdFZhbHVlKCkgKyAnJnVzZXJfaWQ9JyArIHRoaXMuZ2V0U2VsZWN0RW1wbG95ZWUoKSArICcmc2hvd193YWdlPScgKyB0aGlzLndhZ2VfYnRuLmdldFZhbHVlKCB0cnVlICkgKyAnJm1vZGU9JyArIHRoaXMudG9nZ2xlX2J1dHRvbi5nZXRWYWx1ZSgpICsgJyZ0PScgKyB0ICk7XG5cdFx0XHRcdEdsb2JhbC5zZXRVUkxUb0Jyb3dzZXIoIEdsb2JhbC5nZXRCYXNlVVJMKCkgKyAnIyFtPScgKyB0aGlzLnZpZXdJZCArICcmdXNlcl9pZD0nICsgdGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpICsgJyZzaG93X3dhZ2U9JyArIHRoaXMud2FnZV9idG4uZ2V0VmFsdWUoIHRydWUgKSArICcmbW9kZT0nICsgdGhpcy50b2dnbGVfYnV0dG9uLmdldFZhbHVlKCkgKyAnJnQ9JyArIHQgKTtcblx0XHRcdH1cblxuXHRcdH1cblx0fVxuXG5cdG9uQ3VzdG9tQ29udGV4dENsaWNrKCBpZCApIHtcblx0XHRzd2l0Y2ggKCBpZCApIHtcblx0XHRcdGNhc2UgJ2FkZCc6IC8vVGhpcyBpcyBjYXVnaHQgYnkgb25Db250ZXh0TWVudUNsaWNrKCksIHNvIHdlIGhhdmUgdG8gdXNlIGEgZGlmZmVyZW50IGlkOiBhZGRfcHVuY2ggaW5zdGVhZC5cblx0XHRcdGNhc2UgJ2FkZF9wdW5jaCc6XG5cdFx0XHRcdHRoaXMuYWJzZW5jZV9tb2RlbCA9IGZhbHNlO1xuXHRcdFx0XHR0aGlzLm9uQWRkQ2xpY2soKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdhZGRfYWJzZW5jZSc6XG5cdFx0XHRcdHRoaXMuYWJzZW5jZV9tb2RlbCA9IHRydWU7XG5cdFx0XHRcdHRoaXMub25BZGRDbGljaygpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ21vdmUnOlxuXHRcdFx0Y2FzZSAnZHJhZ19jb3B5Jzpcblx0XHRcdFx0dGhpcy5zZXRNb3ZlT3JEcm9wTW9kZSggaWQgKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdpbl9vdXQnOlxuXHRcdFx0XHRNZW51TWFuYWdlci5vcGVuU2VsZWN0VmlldyggJ0luT3V0JyApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3NjaGVkdWxlJzpcblx0XHRcdGNhc2UgJ3BheV9zdHViJzpcblx0XHRcdGNhc2UgJ2VkaXRfZW1wbG95ZWUnOlxuXHRcdFx0Y2FzZSAnZWRpdF9wYXlfcGVyaW9kJzpcblx0XHRcdFx0dGhpcy5vbk5hdmlnYXRpb25DbGljayggaWQgKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdyZV9jYWxjdWxhdGVfdGltZXNoZWV0Jzpcblx0XHRcdGNhc2UgJ2dlbmVyYXRlX3BheV9zdHViJzpcblx0XHRcdFx0dGhpcy5vbldpemFyZENsaWNrKCBpZCApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ21hcCc6XG5cdFx0XHRcdHRoaXMub25NYXBDbGljayggaWQgKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdhY2N1bXVsYXRlZF90aW1lJzpcblx0XHRcdFx0dGhpcy5vbkFjY3VtdWxhdGVkVGltZUNsaWNrKCBpZCApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ0FkZFJlcXVlc3QnOlxuXHRcdFx0XHQvLyBQcmV2ZW50aW5nIFR5cGVFcnJvcjogQ2Fubm90IHJlYWQgcHJvcGVydHkgJ2RhdGUnIG9mIHVuZGVmaW5lZFxuXHRcdFx0XHRpZiAoIHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5Lmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdFx0dGhpcy5hZGRSZXF1ZXN0RnJvbVRpbWVzaGVldENlbGwoIGlkICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdwcmludF9zdW1tYXJ5Jzpcblx0XHRcdGNhc2UgJ3ByaW50X2RldGFpbGVkJzpcblx0XHRcdFx0dGhpcy5vblJlcG9ydE1lbnVDbGljayggaWQgKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0fVxuXHR9XG5cblx0YWRkUmVxdWVzdEZyb21UaW1lc2hlZXRDZWxsKCBpZCApIHtcblx0XHRpZiAoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpIDw9IDEwICkge1xuXHRcdFx0VEFsZXJ0TWFuYWdlci5zaG93QWxlcnQoIEdsb2JhbC5nZXRVcGdyYWRlTWVzc2FnZSgpICk7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0dmFyIGN1cnJlbnRfY29sdW1uX2ZpZWxkID0gR2xvYmFsLnN0clRvRGF0ZSggdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXlbMF0uZGF0ZSA/IHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5WzBdLmRhdGUgOiB0aGlzLnN0YXJ0X2RhdGVfcGlja2VyLmdldFZhbHVlKCkgKS5mb3JtYXQoIHRoaXMuZnVsbF9mb3JtYXQgKTtcblxuXHRcdGlmICggdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXlbMF0ucHVuY2ggKSB7XG5cdFx0XHR2YXIgcHVuY2hfY29udHJvbF9pZCA9IHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5WzBdLnB1bmNoLnB1bmNoX2NvbnRyb2xfaWQ7XG5cdFx0XHR2YXIgY3VycmVudF9wdW5jaF9pZCA9IHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5WzBdLnB1bmNoLmlkO1xuXHRcdFx0dmFyIGN1cnJlbnRfcHVuY2hfc3RhdHVzX2lkID0gdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXlbMF0ucHVuY2guc3RhdHVzX2lkO1xuXHRcdFx0dmFyIHR5cGVfaWQgPSB0aGlzLnNlbGVjdF9jZWxsc19BcnJheVswXS5wdW5jaC50eXBlX2lkO1xuXHRcdFx0dmFyIHVzZXJfaWQgPSB0aGlzLnNlbGVjdF9jZWxsc19BcnJheVswXS5wdW5jaC51c2VyX2lkO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR2YXIgdXNlcl9pZCA9IHRoaXMuZ2V0U2VsZWN0RW1wbG95ZWUoKTtcblx0XHRcdHZhciBwdW5jaF9jb250cm9sX2lkID0gbnVsbDtcblx0XHRcdHZhciBjdXJyZW50X3B1bmNoX2lkID0gbnVsbDtcblx0XHRcdHZhciBjdXJyZW50X3B1bmNoX3N0YXR1c19pZCA9IDEwO1xuXHRcdFx0dmFyIHR5cGVfaWQgPSAxMDtcblx0XHR9XG5cblx0XHR2YXIgcHJldmlvdXNfcHVuY2hfaWQgPSBudWxsO1xuXHRcdGlmICggIWN1cnJlbnRfcHVuY2hfaWQgKSB7XG5cdFx0XHQvL3Jvd19pZCBpcyBudW1lcmljIGhlcmUuXG5cdFx0XHRpZiAoIHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5WzBdLnJvd19pZCA+IDEgJiYgdGhpcy50aW1lc2hlZXRfZGF0YV9zb3VyY2VbdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXlbMF0ucm93X2lkIC0gMl0gJiYgdGhpcy50aW1lc2hlZXRfZGF0YV9zb3VyY2VbdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXlbMF0ucm93X2lkIC0gMl1bY3VycmVudF9jb2x1bW5fZmllbGQgKyAnX2RhdGEnXSApIHtcblx0XHRcdFx0cHJldmlvdXNfcHVuY2hfaWQgPSB0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZVt0aGlzLnNlbGVjdF9jZWxsc19BcnJheVswXS5yb3dfaWQgLSAyXVtjdXJyZW50X2NvbHVtbl9maWVsZCArICdfZGF0YSddLmlkO1xuXHRcdFx0XHR0eXBlX2lkID0gdGhpcy50aW1lc2hlZXRfZGF0YV9zb3VyY2VbdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXlbMF0ucm93X2lkIC0gMl1bY3VycmVudF9jb2x1bW5fZmllbGQgKyAnX2RhdGEnXS50eXBlX2lkO1xuXHRcdFx0XHR2YXIgdG1wX3N0YXR1c19pZCA9IHRoaXMudGltZXNoZWV0X2RhdGFfc291cmNlW3RoaXMuc2VsZWN0X2NlbGxzX0FycmF5WzBdLnJvd19pZCAtIDJdW2N1cnJlbnRfY29sdW1uX2ZpZWxkICsgJ19kYXRhJ10uc3RhdHVzX2lkO1xuXG5cdFx0XHRcdC8vIElzc3VlICMyODk1IC0gUmVxdWVzdCB0ZXh0IHdvdWxkIHNob3cgYSBicmVhayAvIGx1bmNoIG91dCBldmVuIHRob3VnaCB0aGUgbGFzdCBwdW5jaCB3YXMgYW4gaW4uXG5cdFx0XHRcdGlmICggY3VycmVudF9wdW5jaF9zdGF0dXNfaWQgPT0gMTAgJiYgdG1wX3N0YXR1c19pZCA9PSAxMCAmJiB0eXBlX2lkICE9IDEwICkgeyAvL1N0YXR1cyAxMD1JbiwyMD1PdXQgIC0tIFR5cGU6IDEwPU5vcm1hbCwgMjA9THVuY2gsIDMwPUJyZWFrXG5cdFx0XHRcdFx0Ly8gVGhpcyBoYXMgdG8gYmUgYSBub3JtYWwgb3V0IHB1bmNoIGFzIHRoZSBsYXN0IHB1bmNoIHdhcyBhbiBpbi5cblx0XHRcdFx0XHR0eXBlX2lkID0gMTA7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly9ibGFuayBhbmQgaGFzIG5vIHByZXZpb3VzIHB1bmNoIHNvIHdlIG5lZWQgdG8gaW5mZXIgc3RhdHVzX2lkIGZyb20gdGhlIHNlbGVjdGVkIHJvdydzIHN0YXR1c1xuXHRcdFx0aWYgKCB0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZVt0aGlzLnNlbGVjdF9jZWxsc19BcnJheVswXS5yb3dfaWQgLSAxXSApIHtcblx0XHRcdFx0Y3VycmVudF9wdW5jaF9zdGF0dXNfaWQgPSB0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZVt0aGlzLnNlbGVjdF9jZWxsc19BcnJheVswXS5yb3dfaWQgLSAxXS5zdGF0dXNfaWQ7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dmFyIGRhdGUgPSB0aGlzLnNlbGVjdF9jZWxsc19BcnJheVswXS50aW1lX3N0YW1wX251bSAvIDEwMDA7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR0aGlzLmFwaV9wdW5jaC5nZXRSZXF1ZXN0RGVmYXVsdERhdGEoXG5cdFx0XHR1c2VyX2lkLFxuXHRcdFx0ZGF0ZSxcblx0XHRcdHB1bmNoX2NvbnRyb2xfaWQsXG5cdFx0XHRwcmV2aW91c19wdW5jaF9pZCxcblx0XHRcdGN1cnJlbnRfcHVuY2hfc3RhdHVzX2lkLFxuXHRcdFx0dHlwZV9pZCxcblx0XHRcdGN1cnJlbnRfcHVuY2hfaWQsIHtcblx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cdFx0XHRcdFx0dmFyIHJlcXVlc3QgPSByZXN1bHQuZ2V0UmVzdWx0KCk7XG5cdFx0XHRcdFx0SW5kZXhWaWV3Q29udHJvbGxlci5vcGVuRWRpdFZpZXcoICR0aGlzLCAnUmVxdWVzdCcsIHJlcXVlc3QsIG51bGwsICdvcGVuQWRkVmlldycgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdCk7XG5cdH1cblxuXHRnZXRQYXlQZXJpb2QoIGRhdGUgKSB7XG5cdFx0dmFyIGN1cnJlbnRfZGF0ZSA9IHRoaXMuZ2V0U2VsZWN0RGF0ZSgpO1xuXG5cdFx0Ly9pZiBwYXNzIGEgZGF0ZSBpbiwgdXNlIHRoZSBkYXRlXG5cdFx0aWYgKCBkYXRlICkge1xuXHRcdFx0Y3VycmVudF9kYXRlID0gZGF0ZTtcblx0XHR9XG5cblx0XHRpZiAoIHRoaXMucGF5X3BlcmlvZF9tYXAgJiYgdGhpcy5wYXlfcGVyaW9kX21hcFtjdXJyZW50X2RhdGVdICYmIHRoaXMucGF5X3BlcmlvZF9tYXBbY3VycmVudF9kYXRlXSAhPSBUVFVVSUQuemVyb19pZCAmJiBUVFVVSUQuaXNVVUlEKCB0aGlzLnBheV9wZXJpb2RfbWFwW2N1cnJlbnRfZGF0ZV0gKSA9PSB0cnVlICkge1xuXHRcdFx0cmV0dXJuIHRoaXMucGF5X3BlcmlvZF9tYXBbY3VycmVudF9kYXRlXTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0fVxuXHR9XG5cblx0b25OYXZpZ2F0aW9uQ2xpY2soIGljb25OYW1lICkge1xuXG5cdFx0aWYgKCAhdGhpcy5jaGVja1RpbWVzaGVldERhdGEoKSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgcG9zdF9kYXRhO1xuXG5cdFx0c3dpdGNoICggaWNvbk5hbWUgKSB7XG5cdFx0XHRjYXNlICdpbl9vdXQnOlxuXHRcdFx0XHRJbmRleFZpZXdDb250cm9sbGVyLm9wZW5FZGl0VmlldyggTG9jYWxDYWNoZURhdGEuY3VycmVudF9vcGVuX3ByaW1hcnlfY29udHJvbGxlciwgJ0luT3V0JyApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ2VkaXRfZW1wbG95ZWUnOlxuXHRcdFx0XHRJbmRleFZpZXdDb250cm9sbGVyLm9wZW5FZGl0VmlldyggdGhpcywgJ0VtcGxveWVlJywgdGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnZWRpdF9wYXlfcGVyaW9kJzpcblx0XHRcdFx0dmFyIHBheV9wZXJpb2RfaWQgPSB0aGlzLmdldFBheVBlcmlvZCgpO1xuXHRcdFx0XHRpZiAoIHBheV9wZXJpb2RfaWQgKSB7XG5cdFx0XHRcdFx0SW5kZXhWaWV3Q29udHJvbGxlci5vcGVuRWRpdFZpZXcoIHRoaXMsICdQYXlQZXJpb2RzJywgcGF5X3BlcmlvZF9pZCApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnc2NoZWR1bGUnOlxuXHRcdFx0XHR2YXIgZmlsdGVyID0geyBmaWx0ZXJfZGF0YToge30gfTtcblx0XHRcdFx0dmFyIGluY2x1ZGVfdXNlcnMgPSB7IHZhbHVlOiBbdGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpXSB9O1xuXHRcdFx0XHRmaWx0ZXIuZmlsdGVyX2RhdGEuaW5jbHVkZV91c2VyX2lkcyA9IGluY2x1ZGVfdXNlcnM7XG5cdFx0XHRcdGZpbHRlci5zZWxlY3RfZGF0ZSA9IHRoaXMuZ2V0U2VsZWN0RGF0ZSgpO1xuXG5cdFx0XHRcdEdsb2JhbC5hZGRWaWV3VGFiKCB0aGlzLnZpZXdJZCwgJC5pMThuLl8oICdUaW1lU2hlZXQnICksIHdpbmRvdy5sb2NhdGlvbi5ocmVmICk7XG5cdFx0XHRcdEluZGV4Vmlld0NvbnRyb2xsZXIuZ29Ub1ZpZXcoICdTY2hlZHVsZScsIGZpbHRlciApO1xuXG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAncGF5X3N0dWInOlxuXHRcdFx0XHRmaWx0ZXIgPSB7IGZpbHRlcl9kYXRhOiB7fSB9O1xuXHRcdFx0XHR2YXIgdXNlcnMgPSB7IHZhbHVlOiBbdGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpXSB9O1xuXHRcdFx0XHRmaWx0ZXIuZmlsdGVyX2RhdGEudXNlcl9pZCA9IHVzZXJzO1xuXG5cdFx0XHRcdEdsb2JhbC5hZGRWaWV3VGFiKCB0aGlzLnZpZXdJZCwgJC5pMThuLl8oICdUaW1lU2hlZXQnICksIHdpbmRvdy5sb2NhdGlvbi5ocmVmICk7XG5cdFx0XHRcdEluZGV4Vmlld0NvbnRyb2xsZXIuZ29Ub1ZpZXcoICdQYXlTdHViJywgZmlsdGVyICk7XG5cblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdwcmludF9zdW1tYXJ5JzpcblxuXHRcdFx0XHRmaWx0ZXIgPSB7IHRpbWVfcGVyaW9kOiB7fSB9O1xuXHRcdFx0XHRmaWx0ZXIudGltZV9wZXJpb2QudGltZV9wZXJpb2QgPSAnY3VzdG9tX3BheV9wZXJpb2QnO1xuXHRcdFx0XHRmaWx0ZXIudGltZV9wZXJpb2QucGF5X3BlcmlvZF9pZCA9IHRoaXMudGltZXNoZWV0X3ZlcmlmeV9kYXRhLnBheV9wZXJpb2RfaWQ7XG5cdFx0XHRcdGZpbHRlci5pbmNsdWRlX3VzZXJfaWQgPSBbdGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpXTtcblx0XHRcdFx0cG9zdF9kYXRhID0geyAwOiBmaWx0ZXIsIDE6ICdwZGZfdGltZXNoZWV0JyB9O1xuXHRcdFx0XHR0aGlzLmRvRm9ybUlGcmFtZUNhbGwoIHBvc3RfZGF0YSApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3ByaW50X2RldGFpbGVkJzpcblx0XHRcdFx0ZmlsdGVyID0geyB0aW1lX3BlcmlvZDoge30gfTtcblx0XHRcdFx0ZmlsdGVyLnRpbWVfcGVyaW9kLnRpbWVfcGVyaW9kID0gJ2N1c3RvbV9wYXlfcGVyaW9kJztcblx0XHRcdFx0ZmlsdGVyLnRpbWVfcGVyaW9kLnBheV9wZXJpb2RfaWQgPSB0aGlzLnRpbWVzaGVldF92ZXJpZnlfZGF0YS5wYXlfcGVyaW9kX2lkO1xuXHRcdFx0XHRmaWx0ZXIuaW5jbHVkZV91c2VyX2lkID0gW3RoaXMuZ2V0U2VsZWN0RW1wbG95ZWUoKV07XG5cdFx0XHRcdHBvc3RfZGF0YSA9IHsgMDogZmlsdGVyLCAxOiAncGRmX3RpbWVzaGVldF9kZXRhaWwnIH07XG5cdFx0XHRcdHRoaXMuZG9Gb3JtSUZyYW1lQ2FsbCggcG9zdF9kYXRhICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdH1cblx0fVxuXG5cdGRvRm9ybUlGcmFtZUNhbGwoIHBvc3REYXRhICkge1xuXHRcdEdsb2JhbC5BUElGaWxlRG93bmxvYWQoICdBUElUaW1lc2hlZXREZXRhaWxSZXBvcnQnLCAnZ2V0VGltZXNoZWV0RGV0YWlsUmVwb3J0JywgcG9zdERhdGEgKTtcblx0fVxuXG5cdG9uQWNjdW11bGF0ZWRUaW1lQ2xpY2soKSB7XG5cdFx0aWYgKCBQZXJtaXNzaW9uTWFuYWdlci5jaGVja1RvcExldmVsUGVybWlzc2lvbiggJ0FjY3VtdWxhdGVkVGltZScgKSApIHtcblx0XHRcdHZhciBzZWxlY3RfZGF0ZSA9IEdsb2JhbC5zdHJUb0RhdGUoIHRoaXMuZ2V0U2VsZWN0RGF0ZSgpICkuZm9ybWF0KCAnWVlZWS1NTS1ERCcgKTtcblx0XHRcdEluZGV4Vmlld0NvbnRyb2xsZXIub3BlbkVkaXRWaWV3KCB0aGlzLCAnVXNlckRhdGVUb3RhbFBhcmVudCcsIHNlbGVjdF9kYXRlICk7XG5cdFx0fVxuXHR9XG5cblx0b25NYXBDbGljaygpIHtcblx0XHQvLyBvbmx5IHRyaWdnZXIgbWFwIGxvYWQgaW4gc3BlY2lmaWMgcHJvZHVjdCBlZGl0aW9ucy5cblx0XHRpZiAoICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMTUgKSApIHtcblxuXHRcdFx0Ly8gVE9ETzogdGhpcyBpcyByZXBlYXRlZCBiZWxvdywgcGVyaGFwcyBpbiBmdXR1cmUgbm93IHRoYXQgZ2V0RmlsdGVyQ29sdW1uc0Zyb21EaXNwbGF5Q29sdW1ucygpIGlzIGNvbW1lbnRlZCBvdXQsIHRoaXMgY2FuIGJlIGNvbnNvbGlkYXRlZD9cblx0XHRcdHZhciBkYXRhID0ge1xuXHRcdFx0XHRmaWx0ZXJfY29sdW1uczoge1xuXHRcdFx0XHRcdGlkOiB0cnVlLFxuXHRcdFx0XHRcdGxhdGl0dWRlOiB0cnVlLFxuXHRcdFx0XHRcdGxvbmdpdHVkZTogdHJ1ZSxcblx0XHRcdFx0XHRwdW5jaF9kYXRlOiB0cnVlLFxuXHRcdFx0XHRcdHB1bmNoX3RpbWU6IHRydWUsXG5cdFx0XHRcdFx0cG9zaXRpb25fYWNjdXJhY3k6IHRydWUsXG5cdFx0XHRcdFx0dXNlcl9pZDogdHJ1ZVxuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXG5cdFx0XHR2YXIgcHVuY2hlcyA9IFtdO1xuXHRcdFx0dmFyIG1hcF9vcHRpb25zID0ge307XG5cblx0XHRcdGlmICggdGhpcy5lZGl0X3ZpZXcgKSB7XG5cdFx0XHRcdHB1bmNoZXMucHVzaCggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICk7XG5cdFx0XHRcdGlmICggIXRoaXMuaXNfdmlld2luZyApIHtcblx0XHRcdFx0XHQvLyBtYWtlIHN1cmUgdGhhdCB3aGVuIHZpZXcgb25seSAoc28gbm8gc2F2ZSkgbWFya2VyIGlzIG5vdCBkcmFnZ2FibGUsIGFuZCB0aHVzIG5vIG5ldyBtYXJrZXIgY2FuIGJlIGFkZGVkIGVpdGhlci5cblx0XHRcdFx0XHRtYXBfb3B0aW9ucy5zaW5nbGVfbWFya2VyX2RyYWdnYWJsZSA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZiAoIHRoaXMuc2VsZWN0X3B1bmNoZXNfYXJyYXkgJiYgdGhpcy5zZWxlY3RfcHVuY2hlc19hcnJheS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHR2YXIgaWRzID0gW107XG5cdFx0XHRcdHRoaXMuc2VsZWN0X3B1bmNoZXNfYXJyYXkubWFwKCBmdW5jdGlvbiggcHVuY2ggKSB7XG5cdFx0XHRcdFx0aWYgKCBwdW5jaC5pZCApIHtcblx0XHRcdFx0XHRcdGlkcy5wdXNoKCBwdW5jaC5pZCApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdGRhdGEuZmlsdGVyX2RhdGEgPSBHbG9iYWwuY29udmVydExheW91dEZpbHRlclRvQVBJRmlsdGVyKCB0aGlzLnNlbGVjdF9sYXlvdXQgKTtcblx0XHRcdFx0aWYgKCBkYXRhLmZpbHRlcl9kYXRhICYmIGlkcy5sZW5ndGggPiAwICkge1xuXHRcdFx0XHRcdGRhdGEuZmlsdGVyX2RhdGEuaWQgPSBpZHM7XG5cdFx0XHRcdH1cblx0XHRcdFx0Ly8gZGF0YS5maWx0ZXJfY29sdW1ucyA9IHRoaXMuZ2V0RmlsdGVyQ29sdW1uc0Zyb21EaXNwbGF5Q29sdW1ucygpXG5cdFx0XHRcdGRhdGEuZmlsdGVyX2NvbHVtbnMuZmlyc3RfbmFtZSA9IHRydWU7XG5cdFx0XHRcdGRhdGEuZmlsdGVyX2NvbHVtbnMubGFzdF9uYW1lID0gdHJ1ZTtcblx0XHRcdFx0ZGF0YS5maWx0ZXJfY29sdW1ucy51c2VyX2lkID0gdHJ1ZTtcblx0XHRcdFx0ZGF0YS5maWx0ZXJfY29sdW1ucy5kYXRlX3N0YW1wID0gdHJ1ZTsgLy8gIzI3MzUgLSBncm91cGluZyBwdW5jaGVzIGJ5IGRhdGVfc3RhbXAgaW5zdGVhZCBvZiBwdW5jaF9kYXRlLCB0byBhbGxvdyBjcm9zcyBkYXRlIHB1bmNoIGNvbnRyb2xzIHRvIHBsb3QgZGlzdGFuY2VzLlxuXHRcdFx0XHRkYXRhLmZpbHRlcl9jb2x1bW5zLnB1bmNoX2RhdGUgPSB0cnVlO1xuXHRcdFx0XHRkYXRhLmZpbHRlcl9jb2x1bW5zLnB1bmNoX3RpbWUgPSB0cnVlO1xuXHRcdFx0XHRkYXRhLmZpbHRlcl9jb2x1bW5zLnRpbWVfc3RhbXAgPSB0cnVlO1xuXHRcdFx0XHRkYXRhLmZpbHRlcl9jb2x1bW5zLnN0YXR1cyA9IHRydWU7XG5cdFx0XHRcdGRhdGEuZmlsdGVyX2NvbHVtbnMucHVuY2hfY29udHJvbF9pZCA9IHRydWU7XG5cdFx0XHRcdGRhdGEuZmlsdGVyX2NvbHVtbnMuYnJhbmNoID0gdHJ1ZTtcblx0XHRcdFx0ZGF0YS5maWx0ZXJfY29sdW1ucy5icmFuY2hfaWQgPSB0cnVlO1xuXHRcdFx0XHRkYXRhLmZpbHRlcl9jb2x1bW5zLmRlcGFydG1lbnQgPSB0cnVlO1xuXHRcdFx0XHRkYXRhLmZpbHRlcl9jb2x1bW5zLmRlcGFydG1lbnRfaWQgPSB0cnVlO1xuXHRcdFx0XHRkYXRhLmZpbHRlcl9jb2x1bW5zLmpvYl9tYW51YWxfaWQgPSB0cnVlO1xuXHRcdFx0XHRkYXRhLmZpbHRlcl9jb2x1bW5zLmpvYiA9IHRydWU7XG5cdFx0XHRcdGRhdGEuZmlsdGVyX2NvbHVtbnMuam9iX2lkID0gdHJ1ZTtcblx0XHRcdFx0ZGF0YS5maWx0ZXJfY29sdW1ucy5qb2JfaXRlbV9tYW51YWxfaWQgPSB0cnVlO1xuXHRcdFx0XHRkYXRhLmZpbHRlcl9jb2x1bW5zLmpvYl9pdGVtID0gdHJ1ZTsgLy8gYWxzbyBrbm93biBhcyBUYXNrXG5cdFx0XHRcdGRhdGEuZmlsdGVyX2NvbHVtbnMuam9iX2l0ZW1faWQgPSB0cnVlO1xuXHRcdFx0XHRkYXRhLmZpbHRlcl9jb2x1bW5zLnB1bmNoX3RhZyA9IHRydWU7XG5cdFx0XHRcdGRhdGEuZmlsdGVyX2NvbHVtbnMucHVuY2hfdGFnX2lkID0gdHJ1ZTtcblx0XHRcdFx0ZGF0YS5maWx0ZXJfY29sdW1ucy50b3RhbF90aW1lID0gdHJ1ZTtcblx0XHRcdFx0ZGF0YS5maWx0ZXJfY29sdW1ucy5sYXRpdHVkZSA9IHRydWU7XG5cdFx0XHRcdGRhdGEuZmlsdGVyX2NvbHVtbnMubG9uZ2l0dWRlID0gdHJ1ZTtcblx0XHRcdFx0ZGF0YS5maWx0ZXJfY29sdW1ucy5wb3NpdGlvbl9hY2N1cmFjeSA9IHRydWU7XG5cblx0XHRcdFx0cHVuY2hlcyA9IHRoaXMuYXBpLmdldFB1bmNoKCBkYXRhLCB7IGFzeW5jOiBmYWxzZSB9ICkuZ2V0UmVzdWx0KCk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggIXRoaXMuaXNfbWFzc19lZGl0aW5nICkge1xuXHRcdFx0XHQvLyBUaGVyZSBpcyBub3QgZW5vdWdoIGRldGFpbCBpbiB0aGUgJ3B1bmNoZXMnIGRhdGEgcHVsbGVkIGZyb20gdGhlIGdyaWQsIGdldCB0aGUgZnVsbCBkYXRhIGZyb20gYXBpLCBsaWtlIFB1bmNoZXNWaWV3Q29udHJvbGxlclxuXHRcdFx0XHQvLyBOb3RlIHRoZXJlIHNlZW1zIHRvIGJlIGEgbXVsdHBsZSB3YXlzIHRvIGdldCB0aGUgZGF0YSBlLmcuIHNlbGVjdF9wdW5jaGVzX2FycmF5LFxuXHRcdFx0XHQvLyBidXQgb3RoZXIgdmlldyBjb250cm9sbGVycyB1c2UgLmdldEdyaWRTZWxlY3RJZEFycmF5KCkgYW5kIHRoZXJlcyBhbHNvIHNlbGVjdF9jZWxsc19BcnJheS5cblx0XHRcdFx0Ly8gVE9ETy1mdXR1cmU6IFBlcmhhcHMgbG9vayBhdCBhIGZ1dHVyZSByZWZhY3Rvci9jb25zb2xpZGF0aW9uIG9mIGFsbCB0aGVzZT9cblxuXHRcdFx0XHRpZiAoIEdsb2JhbC5pc0FycmF5KCBwdW5jaGVzICkgKSB7XG5cdFx0XHRcdFx0aW1wb3J0KCAvKiB3ZWJwYWNrQ2h1bmtOYW1lOiBcImxlYWZsZXQtdGltZXRyZXhcIiAqLyAnQC9mcmFtZXdvcmsvbGVhZmxldC9sZWFmbGV0LXRpbWV0cmV4JyApLnRoZW4oKCBtb2R1bGUgKT0+e1xuXHRcdFx0XHRcdFx0dmFyIHByb2Nlc3NlZF9wdW5jaGVzX2Zvcl9tYXAgPSBtb2R1bGUuVFRDb252ZXJ0TWFwRGF0YS5wcm9jZXNzUHVuY2hlc0Zyb21WaWV3Q29udHJvbGxlciggcHVuY2hlcywgbWFwX29wdGlvbnMgKTtcblx0XHRcdFx0XHRcdEluZGV4Vmlld0NvbnRyb2xsZXIub3BlbkVkaXRWaWV3KCB0aGlzLCAnTWFwJywgcHJvY2Vzc2VkX3B1bmNoZXNfZm9yX21hcCApO1xuXHRcdFx0XHRcdH0pLmNhdGNoKCBHbG9iYWwuaW1wb3J0RXJyb3JIYW5kbGVyICk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0RGVidWcuVGV4dCggJ0VSUk9SOiBFaXRoZXIgcHVuY2hlcyBpcyBub3QgYW4gYXJyYXksIG9yIGRhdGEgaXMgZW1wdHknLCAnVGltZVNoZWV0Vmlld0NvbnRyb2xsZXIuanMnLCAnVGltZVNoZWV0Vmlld0NvbnRyb2xsZXInLCAnb25NYXBDbGljaycsIDEgKTtcblx0XHRcdFx0XHRUQWxlcnRNYW5hZ2VyLnNob3dBbGVydCggJC5pMThuLl8oICdTZWxlY3RlZCBwdW5jaGVzIG5vIGxvbmdlciBleGlzdCwgdW5hYmxlIHRvIG1hcC4nICkgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdG9uV2l6YXJkQ2xpY2soIGljb25OYW1lICkge1xuXG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHRzd2l0Y2ggKCBpY29uTmFtZSApIHtcblx0XHRcdGNhc2UgJ3JlX2NhbGN1bGF0ZV90aW1lc2hlZXQnOlxuXHRcdFx0XHR2YXIgZGVmYXVsdF9kYXRhID0ge307XG5cdFx0XHRcdGRlZmF1bHRfZGF0YS51c2VyX2lkID0gdGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpO1xuXG5cdFx0XHRcdHZhciBwYXlfcGVyaW9kX2lkID0gdGhpcy5nZXRQYXlQZXJpb2QoKTtcblx0XHRcdFx0aWYgKCBwYXlfcGVyaW9kX2lkICkge1xuXHRcdFx0XHRcdGRlZmF1bHRfZGF0YS5wYXlfcGVyaW9kX2lkID0gcGF5X3BlcmlvZF9pZDtcblx0XHRcdFx0fVxuXHRcdFx0XHRJbmRleFZpZXdDb250cm9sbGVyLm9wZW5XaXphcmQoICdSZUNhbGN1bGF0ZVRpbWVTaGVldFdpemFyZCcsIGRlZmF1bHRfZGF0YSwgZnVuY3Rpb24oKSB7XG5cblx0XHRcdFx0XHQkdGhpcy5vblJlQ2FsVGltZVNoZWV0RG9uZSgpO1xuXHRcdFx0XHR9ICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnZ2VuZXJhdGVfcGF5X3N0dWInOlxuXG5cdFx0XHRcdGRlZmF1bHRfZGF0YSA9IHt9O1xuXHRcdFx0XHRkZWZhdWx0X2RhdGEudXNlcl9pZCA9IHRoaXMuZ2V0U2VsZWN0RW1wbG95ZWUoKTtcblxuXHRcdFx0XHRwYXlfcGVyaW9kX2lkID0gdGhpcy5nZXRQYXlQZXJpb2QoKTtcblx0XHRcdFx0aWYgKCBwYXlfcGVyaW9kX2lkICkge1xuXHRcdFx0XHRcdGRlZmF1bHRfZGF0YS5wYXlfcGVyaW9kX2lkID0gW3BheV9wZXJpb2RfaWRdO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGRlZmF1bHRfZGF0YS5wYXlfcGVyaW9kX2lkID0gW107XG5cdFx0XHRcdH1cblx0XHRcdFx0SW5kZXhWaWV3Q29udHJvbGxlci5vcGVuV2l6YXJkKCAnR2VuZXJhdGVQYXlTdHViV2l6YXJkJywgZGVmYXVsdF9kYXRhLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHQkdGhpcy5zZWFyY2goKTtcblx0XHRcdFx0fSApO1xuXHRcdFx0XHRicmVhaztcblx0XHR9XG5cdH1cblxuXHRvblJlQ2FsVGltZVNoZWV0RG9uZSgpIHtcblx0XHQvL0l0cyBwb3NzaWJsZSB0aGUgdXNlciBoYXMgbmF2aWdhdGVkIGF3YXkgZnJvbSB0aGUgdGltZXNoZWV0IHdoaWxlIGEgcmVjYWxjdWxhdGlvbiBpcyBpbiBwcm9ncmVzcywgaWYgc28sIGRvbid0IHRyeSB0byByZWZyZXNoIHRoZSB0aW1lc2hlZXQuXG5cdFx0Ly9BbHNvIGZpeGVzOiBVbmNhdWdodCBUeXBlRXJyb3I6IEZhaWxlZCB0byBleGVjdXRlICdyZXBsYWNlQ2hpbGQnIG9uICdOb2RlJzogcGFyYW1ldGVyIDIgaXMgbm90IG9mIHR5cGUgJ05vZGUnLlxuXG5cdFx0aWYgKCBNZW51TWFuYWdlci5pc0N1cnJlbnRWaWV3KCAnVGltZVNoZWV0JyApICkge1xuXHRcdFx0TWVudU1hbmFnZXIuZ29Ub1ZpZXcoICdUaW1lU2hlZXQnLCB0cnVlICk7XG5cdFx0XHQvL3RoaXMuaW5pdERhdGEoKTsgLy9EbyBhIGdlbmVyaWMgdmlldyByZWZyZXNoIHJhdGhlciB0aGFuIGp1c3QgaW5pdERhdGEoKSBhcyBpdHMgbGVzcyBsaWtlbHkgdG8gY2F1c2UgcHJvYmxlbXMuXG5cdFx0fVxuXHR9XG5cblx0c2V0TW92ZU9yRHJvcE1vZGUoIGlkICkge1xuXHRcdHZhciBjb250ZXh0X21lbnVfYXJyYXkgPSBDb250ZXh0TWVudU1hbmFnZXIuZ2V0TWVudU1vZGVsQnlNZW51SWQoIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCApO1xuXHRcdHZhciBkcmFnX2NvcHlfaWNvbiA9IGNvbnRleHRfbWVudV9hcnJheS5maW5kKCBpY29uID0+IGljb24uaWQgPT09ICdkcmFnX2NvcHknICk7XG5cdFx0dmFyIG1vdmVfaWNvbiA9IGNvbnRleHRfbWVudV9hcnJheS5maW5kKCBpY29uID0+IGljb24uaWQgPT09ICdtb3ZlJyApO1xuXG5cdFx0aWYgKCBkcmFnX2NvcHlfaWNvbiA9PT0gdW5kZWZpbmVkIHx8IG1vdmVfaWNvbiA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdENvbnRleHRNZW51TWFuYWdlci5hY3RpdmF0ZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGRyYWdfY29weV9pY29uLmlkLCB0cnVlICk7XG5cdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmFjdGl2YXRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgbW92ZV9pY29uLmlkLCB0cnVlICk7XG5cdFx0dmFyIGRyYWdfaW52aXNpYmxlID0gZmFsc2U7XG5cdFx0dmFyIG1vdmVfaW52aXNpYmxlID0gZmFsc2U7XG5cblx0XHRpZiAoICF0aGlzLmNvcHlQZXJtaXNzaW9uVmFsaWRhdGUoKSApIHtcblx0XHRcdGRyYWdfaW52aXNpYmxlID0gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoICF0aGlzLm1vdmVQZXJtaXNzaW9uVmFsaWRhdGUoKSApIHtcblx0XHRcdG1vdmVfaW52aXNpYmxlID0gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoIG1vdmVfaW52aXNpYmxlICYmIGlkID09PSAnbW92ZScgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuYWN0aXZhdGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBkcmFnX2NvcHlfaWNvbi5pZCwgZmFsc2UgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dmFyIGljb24gPSBjb250ZXh0X21lbnVfYXJyYXkuZmluZCggaWNvbiA9PiBpY29uLmlkID09PSBpZCApO1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmFjdGl2YXRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgaWNvbi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cblx0XHRpZiAoIGRyYWdfaW52aXNpYmxlICYmIG1vdmVfaW52aXNpYmxlICkge1xuXHRcdFx0dGhpcy5zZWxlY3RfZHJhZ19tZW51X2lkID0gbnVsbDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5zZWxlY3RfZHJhZ19tZW51X2lkID0gaWQ7XG5cdFx0fVxuXHR9XG5cblx0Z2V0U2VsZWN0RGF0ZUFycmF5KCkge1xuXG5cdFx0dmFyIHJlc3VsdCA9IFtdO1xuXG5cdFx0dmFyIGNlbGxzX2FycmF5ID0gdGhpcy5hYnNlbmNlX21vZGVsID8gdGhpcy5hYnNlbmNlX3NlbGVjdF9jZWxsc19BcnJheSA6IHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5O1xuXG5cdFx0dmFyIGxlbiA9IGNlbGxzX2FycmF5Lmxlbmd0aDtcblxuXHRcdHZhciBkYXRlX2RpYyA9IHt9O1xuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0dmFyIGl0ZW0gPSBjZWxsc19hcnJheVtpXTtcblx0XHRcdGRhdGVfZGljW2l0ZW0uZGF0ZV0gPSB0cnVlO1xuXHRcdH1cblxuXHRcdGZvciAoIHZhciBrZXkgaW4gZGF0ZV9kaWMgKSB7XG5cdFx0XHRyZXN1bHQucHVzaCgga2V5ICk7XG5cdFx0fVxuXG5cdFx0aWYgKCByZXN1bHQubGVuZ3RoID09PSAwICkge1xuXHRcdFx0cmVzdWx0ID0gW3RoaXMuZ2V0U2VsZWN0RGF0ZSgpXTtcblx0XHR9XG5cblx0XHRyZXR1cm4gcmVzdWx0O1xuXHR9XG5cblx0b25BZGRDbGljayggZG9pbmdfc2F2ZV9hbmRfbmV3ICkge1xuXHRcdFRUUHJvbWlzZS5hZGQoICdUaW1lU2hlZXRWaWV3Q29udHJvbGxlcicsICdhZGRjbGljaycgKTtcblx0XHRUVFByb21pc2Uud2FpdCgpO1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dGhpcy5zZXRDdXJyZW50RWRpdFZpZXdTdGF0ZSggJ25ldycgKTtcblx0XHR0aGlzLmlzX21hc3NfYWRkaW5nID0gdHJ1ZTsgLy9JcyBhbHdheXMgdHJ1ZSBiZWNhdXNlIHdlIGFsd2F5cyB3YW50IHRoZSB1c2VyIHRvIGJlIGFibGUgdG8gc2VsZWN0IG11bHRpcGxlIGRhdGVzLlxuXHRcdHZhciBwdW5jaF9jb250cm9sX2lkID0gbnVsbDtcblx0XHR2YXIgcHJldl9wdW5jaF9pZCA9IG51bGw7XG5cdFx0dmFyIHJlbGF0ZWRfcHVuY2ggPSBudWxsO1xuXHRcdHZhciBkYXRlID0gdGhpcy5nZXRTZWxlY3REYXRlKCk7XG5cdFx0dmFyIHN0YXR1c19pZCA9IDEwLCB0eXBlX2lkID0gMTAsIHNlbGVjdF9jZWxsO1xuXG5cdFx0aWYgKCAhdGhpcy5hYnNlbmNlX21vZGVsICkge1xuXHRcdFx0aWYgKCB0aGlzLnNlbGVjdF9jZWxsc19BcnJheS5sZW5ndGggPT09IDEgKSB7XG5cdFx0XHRcdHZhciBzZWxlY3RfaXRlbSA9IHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5WzBdO1xuXHRcdFx0XHRpZiAoIHNlbGVjdF9pdGVtLnJlbGF0ZWRfcHVuY2ggKSB7XG5cdFx0XHRcdFx0cmVsYXRlZF9wdW5jaCA9IHNlbGVjdF9pdGVtLnJlbGF0ZWRfcHVuY2g7XG5cdFx0XHRcdFx0cHVuY2hfY29udHJvbF9pZCA9IHNlbGVjdF9pdGVtLnJlbGF0ZWRfcHVuY2gucHVuY2hfY29udHJvbF9pZDtcblx0XHRcdFx0XHRwcmV2X3B1bmNoX2lkID0gc2VsZWN0X2l0ZW0ucmVsYXRlZF9wdW5jaC5pZDtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQvL0Vycm9yOiBVbmNhdWdodCBUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnR5ICdmb3JtYXQnIG9mIG51bGwgaW4gaW50ZXJmYWNlL2h0bWw1LyMhbT1UaW1lU2hlZXQmZGF0ZT0yMDE1MTAwNiZ1c2VyX2lkPTUxMDg1JnNob3dfd2FnZT0wIGxpbmUgNjI5MlxuXHRcdFx0XHRcdHZhciBjdXJyZW50X2NvbHVtbl9maWVsZCA9IEdsb2JhbC5zdHJUb0RhdGUoIHNlbGVjdF9pdGVtLmRhdGUgPyBzZWxlY3RfaXRlbS5kYXRlIDogdGhpcy5zdGFydF9kYXRlX3BpY2tlci5nZXRWYWx1ZSgpICkuZm9ybWF0KCB0aGlzLmZ1bGxfZm9ybWF0ICk7XG5cblx0XHRcdFx0XHQvL3Jvd19pZCBpcyBuYnVtZXJpYyBoZXJlXG5cdFx0XHRcdFx0aWYgKCB0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZSAmJiB0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZVtzZWxlY3RfaXRlbS5yb3dfaWQgLSAyXSApIHtcblx0XHRcdFx0XHRcdHZhciBwcmVfcHVuY2ggPSB0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZVtzZWxlY3RfaXRlbS5yb3dfaWQgLSAyXVtjdXJyZW50X2NvbHVtbl9maWVsZCArICdfZGF0YSddO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICggcHJlX3B1bmNoICkge1xuXHRcdFx0XHRcdFx0cHJldl9wdW5jaF9pZCA9IHByZV9wdW5jaC5pZDtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cdFx0XHQvLyBUbyB1c2UgcHJvcGVyIGNvbnRleHQgbWVudSBmb3IgZWFjaCBwdW5jaCBvciBhYnNlb25jZSBtb2RlLlxuXHRcdFx0dGhpcy5zZXREZWZhdWx0TWVudSgpO1xuXHRcdFx0JHRoaXMub3BlbkVkaXRWaWV3KCk7XG5cblx0XHRcdGlmICggZG9pbmdfc2F2ZV9hbmRfbmV3ICkge1xuXHRcdFx0XHRkYXRlID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnB1bmNoX2RhdGU7XG5cdFx0XHRcdHJlbGF0ZWRfcHVuY2ggPSBudWxsO1xuXHRcdFx0XHRpZiAoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5zdGF0dXNfaWQgPT0gMTAgKSB7XG5cdFx0XHRcdFx0cHVuY2hfY29udHJvbF9pZCA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5wdW5jaF9jb250cm9sX2lkO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHB1bmNoX2NvbnRyb2xfaWQgPSBudWxsO1xuXHRcdFx0XHR9XG5cblx0XHRcdH1cblxuXHRcdFx0aWYgKCB0aGlzLnNlbGVjdF9jZWxsc19BcnJheS5sZW5ndGggPT09IDEgKSB7XG5cdFx0XHRcdHNlbGVjdF9jZWxsID0gdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXlbMF07XG5cdFx0XHRcdHN0YXR1c19pZCA9IHNlbGVjdF9jZWxsLnN0YXR1c19pZDtcblxuXHRcdFx0XHR2YXIgc2VsZWN0X2RhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCB0aGlzLnN0YXJ0X2RhdGVfcGlja2VyLmdldFZhbHVlKCkgKTtcblx0XHRcdFx0dmFyIG5ld19kYXRlID0gbmV3IERhdGUoIG5ldyBEYXRlKCBzZWxlY3RfZGF0ZS5nZXRUaW1lKCkgKS5zZXREYXRlKCBzZWxlY3RfZGF0ZS5nZXREYXRlKCkgLSAxICkgKTtcblx0XHRcdFx0aWYgKCBuZXdfZGF0ZS5nZXRUaW1lKCkgPCB0aGlzLnN0YXJ0X2RhdGUuZ2V0VGltZSgpICkge1xuXHRcdFx0XHRcdHR5cGVfaWQgPSAxMDtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR2YXIgcm93X2RhdGEgPSB0aGlzLnRpbWVzaGVldF9kYXRhX3NvdXJjZVtzZWxlY3RfY2VsbC5yb3dfaWQgLSAxXTtcblx0XHRcdFx0XHQvL0Vycm9yOiBVbmFibGUgdG8gZ2V0IHByb3BlcnR5ICdTdW4tRGVjLTEzLTIwMTVfZGF0YScgb2YgdW5kZWZpbmVkIG9yIG51bGwgcmVmZXJlbmNlIGluIGludGVyZmFjZS9odG1sNS8gbGluZSA2MzYyXG5cdFx0XHRcdFx0dmFyIGxlZnRfc2lkZV9wdW5jaCA9IHJvd19kYXRhICYmIHJvd19kYXRhW25ld19kYXRlLmZvcm1hdCggdGhpcy5mdWxsX2Zvcm1hdCApICsgJ19kYXRhJ107XG5cdFx0XHRcdFx0aWYgKCBsZWZ0X3NpZGVfcHVuY2ggKSB7XG5cdFx0XHRcdFx0XHR0eXBlX2lkID0gbGVmdF9zaWRlX3B1bmNoLnR5cGVfaWQ7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHR5cGVfaWQgPSAxMDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHNlbGVjdF9jZWxsID0gdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXlbMF07XG5cdFx0XHRcdGlmICggc2VsZWN0X2NlbGwgJiYgc2VsZWN0X2NlbGwuc3RhdHVzX2lkICkge1xuXHRcdFx0XHRcdHN0YXR1c19pZCA9IHNlbGVjdF9jZWxsLnN0YXR1c19pZDtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRzdGF0dXNfaWQgPSAxMDsgLy9JblxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuYXBpWydnZXQnICsgdGhpcy5hcGkua2V5X25hbWUgKyAnRGVmYXVsdERhdGEnXSggdGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpLFxuXHRcdFx0XHRkYXRlLFxuXHRcdFx0XHRwdW5jaF9jb250cm9sX2lkLFxuXHRcdFx0XHRwcmV2X3B1bmNoX2lkLFxuXHRcdFx0XHRzdGF0dXNfaWQsXG5cdFx0XHRcdHR5cGVfaWQsXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlc3VsdCApIHtcblxuXHRcdFx0XHRcdFx0dmFyIHJlc3VsdF9kYXRhID0gcmVzdWx0LmdldFJlc3VsdCgpO1xuXG5cdFx0XHRcdFx0XHRpZiAoICFHbG9iYWwuaXNTZXQoIHJlc3VsdF9kYXRhLnRpbWVfc3RhbXAgKSApIHtcblx0XHRcdFx0XHRcdFx0cmVzdWx0X2RhdGEudGltZV9zdGFtcCA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRyZXN1bHRfZGF0YS5wdW5jaF9kYXRlID0gJHRoaXMuZ2V0U2VsZWN0RGF0ZSgpO1xuXG5cdFx0XHRcdFx0XHRpZiAoIGRvaW5nX3NhdmVfYW5kX25ldyApIHtcblx0XHRcdFx0XHRcdFx0cmVzdWx0X2RhdGEucHVuY2hfZGF0ZSA9ICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQucHVuY2hfZGF0ZTtcblxuXHRcdFx0XHRcdFx0XHRpZiAoICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3RhdHVzX2lkID09IDEwICkge1xuXHRcdFx0XHRcdFx0XHRcdHJlc3VsdF9kYXRhLnN0YXR1c19pZCA9IDIwO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdHJlc3VsdF9kYXRhLnN0YXR1c19pZCA9IDEwO1xuXHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0JHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCA9IHJlc3VsdF9kYXRhO1xuXHRcdFx0XHRcdFx0JHRoaXMuaW5pdEVkaXRWaWV3KCk7XG5cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKTtcblxuXHRcdH0gZWxzZSB7IC8vQWJzZW5jZSBtb2RlbCBicmFuY2hcblxuXHRcdFx0aWYgKCBkb2luZ19zYXZlX2FuZF9uZXcgKSB7XG5cdFx0XHRcdGRhdGUgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuZGF0ZV9zdGFtcDtcblx0XHRcdH1cblx0XHRcdC8vIFRvIHVzZSBwcm9wZXIgY29udGV4dCBtZW51IGZvciBlYWNoIHB1bmNoIG9yIGFic2VvbmNlIG1vZGUuXG5cdFx0XHQkdGhpcy5zZXREZWZhdWx0TWVudSgpO1xuXHRcdFx0JHRoaXMub3BlbkVkaXRWaWV3KCk7XG5cdFx0XHR0aGlzLmFwaV91c2VyX2RhdGVfdG90YWxbJ2dldCcgKyB0aGlzLmFwaV91c2VyX2RhdGVfdG90YWwua2V5X25hbWUgKyAnRGVmYXVsdERhdGEnXSggdGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpLFxuXHRcdFx0XHRkYXRlLFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cblx0XHRcdFx0XHRcdHZhciByZXN1bHRfZGF0YSA9IHJlc3VsdC5nZXRSZXN1bHQoKTtcblxuXHRcdFx0XHRcdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCByZXN1bHRfZGF0YS50aW1lX3N0YW1wICkgKSB7XG5cdFx0XHRcdFx0XHRcdHJlc3VsdF9kYXRhLnRpbWVfc3RhbXAgPSBmYWxzZTtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoICR0aGlzLmFic2VuY2Vfc2VsZWN0X2NlbGxzX0FycmF5WzBdICkgKSB7XG5cdFx0XHRcdFx0XHRcdHJlc3VsdF9kYXRhLnNyY19vYmplY3RfaWQgPSAkdGhpcy5hYnNlbmNlX3NlbGVjdF9jZWxsc19BcnJheVswXS5zcmNfb2JqZWN0X2lkO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRyZXN1bHRfZGF0YS5vYmplY3RfdHlwZV9pZCA9IDUwO1xuXG5cdFx0XHRcdFx0XHRyZXN1bHRfZGF0YS5kYXRlX3N0YW1wID0gJHRoaXMuZ2V0U2VsZWN0RGF0ZSgpO1xuXHRcdFx0XHRcdFx0JHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCA9IHJlc3VsdF9kYXRhO1xuXHRcdFx0XHRcdFx0JHRoaXMuaW5pdEVkaXRWaWV3KCk7XG5cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKTtcblxuXHRcdH1cblx0fVxuXG5cdHJlbW92ZUVkaXRWaWV3KCkge1xuXHRcdHN1cGVyLnJlbW92ZUVkaXRWaWV3KCk7XG5cdFx0aWYgKCB0aGlzLmFic2VuY2Vfc2VsZWN0X2NlbGxzX0FycmF5Lmxlbmd0aCA+IDAgKSB7XG5cdFx0XHR0aGlzLmFic2VuY2VfbW9kZWwgPSB0cnVlO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLmFic2VuY2VfbW9kZWwgPSBmYWxzZTtcblx0XHR9XG5cdFx0dGhpcy5zZXREZWZhdWx0TWVudSgpO1xuXHR9XG5cblx0aXNNYXNzRGF0ZSgpIHtcblx0XHQvL0Vycm9yOiBVbmFibGUgdG8gZ2V0IHByb3BlcnR5ICdwdW5jaF9kYXRlcycgb2YgdW5kZWZpbmVkIG9yIG51bGwgcmVmZXJlbmNlIGluIC9pbnRlcmZhY2UvaHRtbDUvIGxpbmUgNjMwMFxuXHRcdGlmICggdGhpcy5pc19tYXNzX2FkZGluZyAmJiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgJiYgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnB1bmNoX2RhdGVzICYmIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5wdW5jaF9kYXRlcy5sZW5ndGggPiAxICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0c2V0RWRpdE1lbnVTYXZlQW5kQ29udGludWVJY29uKCBjb250ZXh0X2J0biApIHtcblx0XHR0aGlzLnNhdmVBbmRDb250aW51ZVZhbGlkYXRlKCBjb250ZXh0X2J0biwgdGhpcy5nZXRQdW5jaFBlcm1pc3Npb25UeXBlKCkgKTtcblxuXHRcdGlmICggdGhpcy5pc19tYXNzX2VkaXRpbmcgfHwgdGhpcy5pc192aWV3aW5nIHx8IHRoaXMuaXNNYXNzRGF0ZSgpICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRvblNhdmVBbmROZXdDbGljayggaWdub3JlV2FybmluZyApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdGlmICggIUdsb2JhbC5pc1NldCggaWdub3JlV2FybmluZyApICkge1xuXHRcdFx0aWdub3JlV2FybmluZyA9IGZhbHNlO1xuXHRcdH1cblx0XHR2YXIgY3VycmVudF9hcGkgPSB0aGlzLmdldEN1cnJlbnRBUEkoKTtcblx0XHRMb2NhbENhY2hlRGF0YS5jdXJyZW50X2RvaW5nX2NvbnRleHRfYWN0aW9uID0gJ25ldyc7XG5cblx0XHR2YXIgcmVjb3JkID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkO1xuXG5cdFx0aWYgKCB0aGlzLmlzX21hc3NfYWRkaW5nICkge1xuXG5cdFx0XHRyZWNvcmQgPSBbXTtcblx0XHRcdHZhciBkYXRlc19hcnJheSA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5wdW5jaF9kYXRlcztcblxuXHRcdFx0aWYgKCBkYXRlc19hcnJheSAmJiBkYXRlc19hcnJheS5pbmRleE9mKCAnIC0gJyApID4gMCApIHtcblx0XHRcdFx0ZGF0ZXNfYXJyYXkgPSB0aGlzLnBhcnNlckRhdGVzUmFuZ2UoIGRhdGVzX2FycmF5ICk7XG5cdFx0XHR9XG5cblx0XHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGRhdGVzX2FycmF5Lmxlbmd0aDsgaSsrICkge1xuXHRcdFx0XHR2YXIgY29tbW9uX3JlY29yZCA9IEdsb2JhbC5jbG9uZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICk7XG5cdFx0XHRcdGRlbGV0ZSBjb21tb25fcmVjb3JkLnB1bmNoX2RhdGVzO1xuXHRcdFx0XHRpZiAoIHRoaXMuYWJzZW5jZV9tb2RlbCApIHtcblx0XHRcdFx0XHRjb21tb25fcmVjb3JkLmRhdGVfc3RhbXAgPSBkYXRlc19hcnJheVtpXTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRjb21tb25fcmVjb3JkLnB1bmNoX2RhdGUgPSBkYXRlc19hcnJheVtpXTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJlY29yZC5wdXNoKCBjb21tb25fcmVjb3JkICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Y3VycmVudF9hcGkuc2V0SXNJZGVtcG90ZW50KCB0cnVlICk7IC8vRm9yY2UgdG8gaWRlbXBvdGVudCBBUEkgY2FsbCB0byBhdm9pZCBkdXBsaWNhdGUgbmV0d29yayByZXF1ZXN0cyBmcm9tIGNhdXNpbmcgZXJyb3JzIGRpc3BsYXllZCB0byB0aGUgdXNlci5cblx0XHRjdXJyZW50X2FwaVsnc2V0JyArIGN1cnJlbnRfYXBpLmtleV9uYW1lXSggcmVjb3JkLCBmYWxzZSwgaWdub3JlV2FybmluZywge1xuXHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cdFx0XHRcdGlmICggcmVzdWx0LmlzVmFsaWQoKSApIHtcblx0XHRcdFx0XHQkdGhpcy5zZWFyY2goIGZhbHNlICk7XG5cdFx0XHRcdFx0JHRoaXMub25BZGRDbGljayggdHJ1ZSApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdCR0aGlzLnNldEVycm9yTWVudSgpO1xuXHRcdFx0XHRcdCR0aGlzLnNldEVycm9yVGlwcyggcmVzdWx0ICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXHRcdH0gKTtcblx0fVxuXG5cdF9jb250aW51ZURvQ29weUFzTmV3KCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0TG9jYWxDYWNoZURhdGEuY3VycmVudF9kb2luZ19jb250ZXh0X2FjdGlvbiA9ICdjb3B5X2FzX25ldyc7XG5cdFx0dGhpcy5pc19tYXNzX2FkZGluZyA9IHRydWU7XG5cblx0XHRpZiAoIEdsb2JhbC5pc1NldCggdGhpcy5lZGl0X3ZpZXcgKSApIHtcblx0XHRcdHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCA9ICcnO1xuXG5cdFx0XHRpZiAoICF0aGlzLmFic2VuY2VfbW9kZWwgKSB7XG5cblx0XHRcdFx0dGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnB1bmNoX2NvbnRyb2xfaWQgPSAnJztcblxuXHRcdFx0XHRpZiAoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5zdGF0dXNfaWQgPT0gMTAgKSB7XG5cdFx0XHRcdFx0dGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXR1c19pZCA9IDIwO1xuXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0dGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXR1c19pZCA9IDEwO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dGhpcy5lZGl0X3ZpZXdfdWlfZGljWydzdGF0dXNfaWQnXS5zZXRWYWx1ZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXR1c19pZCApO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgbmF2aWdhdGlvbl9kaXYgPSB0aGlzLmVkaXRfdmlldy5maW5kKCAnLm5hdmlnYXRpb24tZGl2JyApO1xuXHRcdFx0bmF2aWdhdGlvbl9kaXYuY3NzKCAnZGlzcGxheScsICdub25lJyApO1xuXHRcdFx0dGhpcy5vcGVuRWRpdFZpZXcoKTtcblx0XHRcdHRoaXMuaW5pdEVkaXRWaWV3KCk7XG5cdFx0XHR0aGlzLnNldEVkaXRNZW51KCk7XG5cdFx0XHR0aGlzLnNldFRhYlN0YXR1cygpO1xuXHRcdFx0dGhpcy5pc19jaGFuZ2VkID0gZmFsc2U7XG5cdFx0XHRQcm9ncmVzc0Jhci5jbG9zZU92ZXJsYXkoKTtcblx0XHR9XG5cdH1cblxuXHRvblNhdmVBbmRDb3B5KCBpZ25vcmVXYXJuaW5nICkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCBpZ25vcmVXYXJuaW5nICkgKSB7XG5cdFx0XHRpZ25vcmVXYXJuaW5nID0gZmFsc2U7XG5cdFx0fVxuXHRcdHZhciBjdXJyZW50X2FwaSA9IHRoaXMuZ2V0Q3VycmVudEFQSSgpO1xuXHRcdHRoaXMuaXNfY2hhbmdlZCA9IGZhbHNlO1xuXHRcdExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfZG9pbmdfY29udGV4dF9hY3Rpb24gPSAnc2F2ZV9hbmRfY29weSc7XG5cdFx0dmFyIHJlY29yZCA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZDtcblx0XHRpZiAoIHRoaXMuaXNfbWFzc19hZGRpbmcgKSB7XG5cblx0XHRcdHJlY29yZCA9IFtdO1xuXHRcdFx0dmFyIGRhdGVzX2FycmF5ID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnB1bmNoX2RhdGVzO1xuXG5cdFx0XHRpZiAoIGRhdGVzX2FycmF5ICYmIGRhdGVzX2FycmF5LmluZGV4T2YoICcgLSAnICkgPiAwICkge1xuXHRcdFx0XHRkYXRlc19hcnJheSA9IHRoaXMucGFyc2VyRGF0ZXNSYW5nZSggZGF0ZXNfYXJyYXkgKTtcblx0XHRcdH1cblxuXHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgZGF0ZXNfYXJyYXkubGVuZ3RoOyBpKysgKSB7XG5cdFx0XHRcdHZhciBjb21tb25fcmVjb3JkID0gR2xvYmFsLmNsb25lKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgKTtcblx0XHRcdFx0ZGVsZXRlIGNvbW1vbl9yZWNvcmQucHVuY2hfZGF0ZXM7XG5cdFx0XHRcdGlmICggdGhpcy5hYnNlbmNlX21vZGVsICkge1xuXHRcdFx0XHRcdGNvbW1vbl9yZWNvcmQuZGF0ZV9zdGFtcCA9IGRhdGVzX2FycmF5W2ldO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGNvbW1vbl9yZWNvcmQucHVuY2hfZGF0ZSA9IGRhdGVzX2FycmF5W2ldO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmVjb3JkLnB1c2goIGNvbW1vbl9yZWNvcmQgKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHR0aGlzLmNsZWFyTmF2aWdhdGlvbkRhdGEoKTtcblxuXHRcdGN1cnJlbnRfYXBpLnNldElzSWRlbXBvdGVudCggdHJ1ZSApOyAvL0ZvcmNlIHRvIGlkZW1wb3RlbnQgQVBJIGNhbGwgdG8gYXZvaWQgZHVwbGljYXRlIG5ldHdvcmsgcmVxdWVzdHMgZnJvbSBjYXVzaW5nIGVycm9ycyBkaXNwbGF5ZWQgdG8gdGhlIHVzZXIuXG5cdFx0Y3VycmVudF9hcGlbJ3NldCcgKyBjdXJyZW50X2FwaS5rZXlfbmFtZV0oIHJlY29yZCwgZmFsc2UsIGlnbm9yZVdhcm5pbmcsIHtcblx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHRpZiAoIHJlc3VsdC5pc1ZhbGlkKCkgKSB7XG5cdFx0XHRcdFx0dmFyIHJlc3VsdF9kYXRhID0gcmVzdWx0LmdldFJlc3VsdCgpO1xuXHRcdFx0XHRcdCR0aGlzLnNlYXJjaCggZmFsc2UgKTtcblx0XHRcdFx0XHQkdGhpcy5vbkNvcHlBc05ld0NsaWNrKCk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JHRoaXMuc2V0RXJyb3JNZW51KCk7XG5cdFx0XHRcdFx0JHRoaXMuc2V0RXJyb3JUaXBzKCByZXN1bHQgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cblx0Z2V0Q3VycmVudEFQSSgpIHtcblx0XHR2YXIgY3VycmVudF9hcGkgPSB0aGlzLmFwaTtcblxuXHRcdGlmICggdGhpcy5hYnNlbmNlX21vZGVsICkge1xuXHRcdFx0Y3VycmVudF9hcGkgPSB0aGlzLmFwaV91c2VyX2RhdGVfdG90YWw7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGN1cnJlbnRfYXBpO1xuXHR9XG5cblx0Z2VuZXJhdGVNYW51YWxUaW1lU2hlZXRSZWNvcmRLZXkoIGl0ZW0gKSB7XG5cdFx0dmFyIGtleSA9IGl0ZW0uZGF0ZV9zdGFtcCArICctJyArICggKCB0aGlzLnNob3dfYnJhbmNoX3VpICYmIGl0ZW0uYnJhbmNoX2lkICkgPyBpdGVtLmJyYW5jaF9pZCA6IFRUVVVJRC56ZXJvX2lkICkgK1xuXHRcdFx0Jy0nICsgKCAoIHRoaXMuc2hvd19kZXBhcnRtZW50X3VpICYmIGl0ZW0uZGVwYXJ0bWVudF9pZCApID8gaXRlbS5kZXBhcnRtZW50X2lkIDogVFRVVUlELnplcm9faWQgKVxuXHRcdFx0KyAnLScgKyAoICggdGhpcy5zaG93X2pvYl91aSAmJiBpdGVtLmpvYl9pZCAmJiBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAyMCApID8gaXRlbS5qb2JfaWQgOiBUVFVVSUQuemVyb19pZCApICtcblx0XHRcdCctJyArICggKCB0aGlzLnNob3dfam9iX2l0ZW1fdWkgJiYgaXRlbS5qb2JfaXRlbV9pZCAmJiBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAyMCApID8gaXRlbS5qb2JfaXRlbV9pZCA6IFRUVVVJRC56ZXJvX2lkICkgK1xuXHRcdFx0Jy0nICsgKCAoIHRoaXMuc2hvd19wdW5jaF90YWdfdWkgJiYgaXRlbS5wdW5jaF90YWdfaWQgJiYgaXRlbS5wdW5jaF90YWdfaWQubGVuZ3RoID4gMCAmJiBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAyMCApID8gaXRlbS5wdW5jaF90YWdfaWQgOiBUVFVVSUQuemVyb19pZCApICtcblx0XHRcdCctJyArIGl0ZW0udG90YWxfdGltZTtcblxuXHRcdHJldHVybiBrZXk7XG5cdH1cblxuXHRjcmVhdGVDdXJyZW50TWFudWFsR3JpZFJlY29yZHNNYXAoIHJlY29yZHMgKSB7XG5cdFx0dGhpcy5tYW51YWxfZ3JpZF9yZWNvcmRzX21hcCA9IHt9O1xuXG5cdFx0Zm9yICggdmFyIGkgPSAwLCBtID0gcmVjb3Jkcy5sZW5ndGg7IGkgPCBtOyBpKysgKSB7XG5cdFx0XHR2YXIgaXRlbSA9IHJlY29yZHNbaV07XG5cblx0XHRcdHZhciBrZXkgPSB0aGlzLmdlbmVyYXRlTWFudWFsVGltZVNoZWV0UmVjb3JkS2V5KCBpdGVtICk7XG5cdFx0XHRpZiAoIGl0ZW0uaWQgKSB7XG5cdFx0XHRcdGtleSA9IGl0ZW0uaWQgKyAnLScgKyBrZXk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMubWFudWFsX2dyaWRfcmVjb3Jkc19tYXBba2V5XSA9IGl0ZW0ucm93O1xuXHRcdFx0ZGVsZXRlIGl0ZW0ucm93O1xuXHRcdH1cblx0fVxuXG5cdC8vRG9uJ3Qgc2VuZCByZWNvcmRzIHdpdGggYmxhbmsgdG90YWxfdGltZSB0byB0aGUgQVBJLCB0byBiZXR0ZXIgaGFuZGxlIGNhc2VzIHdoZXJlIHRoZSBlbXBsb3llZXMgaGlyZSBkYXRlIGlzIGluIHRoZSBtaWRkbGUgb2YgdGhlIHdlZWsgYW5kIHRoZXkgYWNjaWRlbnRseSBlbnRlciB0aW1lIG9uIHRoZSBNb25kYXksIHdoaWNoIGNhdXNlIGEgcG9wdXAgdmFsaWRhdGlvbiBlcnJvci5cblx0Ly9UaGlzIGFsbG93cyB0aGVtIHRvIGdldCBvdXQgb2YgdGhlIHNjZW5hcmlvIGJ5IHNpbXBseSBjbGVhcmluZyBvdXQgdGhlIGZpZWxkIG9yIHNldHRpbmcgaXQgYmFjayB0byAwLlxuXHRmaWx0ZXJNYW51YWxHcmlkUmVjb3JkcyggcmVjb3JkcyApIHtcblx0XHR2YXIgcmV0YXJyID0gQXJyYXkoKTtcblxuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IHJlY29yZHMubGVuZ3RoOyBpKysgKSB7XG5cdFx0XHR2YXIgaXRlbSA9IHJlY29yZHNbaV07XG5cblx0XHRcdGlmICggaXRlbS5pZCB8fCAoICFpdGVtLmlkICYmIGl0ZW0udG90YWxfdGltZSAmJiBpdGVtLnRvdGFsX3RpbWUgIT0gMCApICkge1xuXHRcdFx0XHRyZXRhcnIucHVzaCggaXRlbSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiByZXRhcnI7XG5cdH1cblxuXHRvblNhdmVDbGljayggaWdub3JlV2FybmluZyApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciByZWNvcmQ7XG5cdFx0Ly8gU2F2ZSBtYW51YWwgcHVuY2hcblx0XHRpZiAoIHRoaXMuZ2V0UHVuY2hNb2RlKCkgPT09ICdtYW51YWwnICYmICF0aGlzLmVkaXRfdmlldyApIHtcblx0XHRcdHZhciByZWNvcmRzID0gdGhpcy5lZGl0b3IuZ2V0VmFsdWUoIHRydWUgKTsgLy8gcmVzZXQgaXNfY2hhbmdlZFxuXHRcdFx0aWYgKCByZWNvcmRzLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdHRoaXMud2FpdF9hdXRvX3NhdmUgJiYgY2xlYXJUaW1lb3V0KCB0aGlzLndhaXRfYXV0b19zYXZlICk7XG5cdFx0XHRcdHRoaXMuY3JlYXRlQ3VycmVudE1hbnVhbEdyaWRSZWNvcmRzTWFwKCByZWNvcmRzICk7XG5cdFx0XHRcdFByb2dyZXNzQmFyLm5vUHJvZ3Jlc3NGb3JOZXh0Q2FsbCgpO1xuXHRcdFx0XHR0aGlzLmlzX3NhdmluZ19tYW51YWxfZ3JpZCA9IHRydWU7XG5cdFx0XHRcdHRoaXMuc2V0RGVmYXVsdE1lbnUoKTtcblxuXHRcdFx0XHRyZWNvcmRzID0gdGhpcy5maWx0ZXJNYW51YWxHcmlkUmVjb3JkcyggcmVjb3JkcyApO1xuXHRcdFx0XHRpZiAoIHJlY29yZHMubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0XHR0aGlzLmFwaV91c2VyX2RhdGVfdG90YWxbJ3NldCcgKyB0aGlzLmFwaV91c2VyX2RhdGVfdG90YWwua2V5X25hbWVdKCByZWNvcmRzLCB7XG5cdFx0XHRcdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlc3VsdCApIHtcblx0XHRcdFx0XHRcdFx0aWYgKCAhcmVzdWx0LmlzVmFsaWQoKSApIHtcblx0XHRcdFx0XHRcdFx0XHRUQWxlcnRNYW5hZ2VyLnNob3dFcnJvckFsZXJ0KCByZXN1bHQgKTtcblx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdCR0aGlzLnVwZGF0ZU1hbnVhbEdyaWQoKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9ICk7XG5cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkdGhpcy51cGRhdGVNYW51YWxHcmlkKCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRQcm9ncmVzc0Jhci5zaG93TmFub2JhcigpO1xuXHRcdFx0XHRQcm9ncmVzc0Jhci5jbG9zZU92ZXJsYXkoKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFByb2dyZXNzQmFyLmNsb3NlT3ZlcmxheSgpO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly9TYXZlIG5vcm1hbCBwdW5jaFxuXHRcdGlmICggIUdsb2JhbC5pc1NldCggaWdub3JlV2FybmluZyApICkge1xuXHRcdFx0aWdub3JlV2FybmluZyA9IGZhbHNlO1xuXHRcdH1cblx0XHRMb2NhbENhY2hlRGF0YS5jdXJyZW50X2RvaW5nX2NvbnRleHRfYWN0aW9uID0gJ3NhdmUnO1xuXHRcdHZhciBjdXJyZW50X2FwaSA9IHRoaXMuZ2V0Q3VycmVudEFQSSgpO1xuXG5cdFx0aWYgKCB0aGlzLmlzX21hc3NfZWRpdGluZyApIHtcblxuXHRcdFx0dmFyIGNoZWNrX2ZpZWxkcyA9IHt9O1xuXHRcdFx0Zm9yICggdmFyIGtleSBpbiB0aGlzLmVkaXRfdmlld191aV9kaWMgKSB7XG5cdFx0XHRcdHZhciB3aWRnZXQgPSB0aGlzLmVkaXRfdmlld191aV9kaWNba2V5XTtcblxuXHRcdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggd2lkZ2V0LmlzQ2hlY2tlZCApICkge1xuXHRcdFx0XHRcdGlmICggd2lkZ2V0LmlzQ2hlY2tlZCgpICkge1xuXHRcdFx0XHRcdFx0Y2hlY2tfZmllbGRzW2tleV0gPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRba2V5XTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0cmVjb3JkID0gW107XG5cdFx0XHQkLmVhY2goIHRoaXMubWFzc19lZGl0X3JlY29yZF9pZHMsIGZ1bmN0aW9uKCBpbmRleCwgdmFsdWUgKSB7XG5cdFx0XHRcdHZhciBjb21tb25fcmVjb3JkID0gR2xvYmFsLmNsb25lKCBjaGVja19maWVsZHMgKTtcblx0XHRcdFx0Y29tbW9uX3JlY29yZC5pZCA9IHZhbHVlO1xuXHRcdFx0XHRyZWNvcmQucHVzaCggY29tbW9uX3JlY29yZCApO1xuXG5cdFx0XHR9ICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJlY29yZCA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZDtcblx0XHR9XG5cblx0XHQvLyBFcnJvcjogVW5jYXVnaHQgVHlwZUVycm9yOiBDYW5ub3QgcmVhZCBwcm9wZXJ0eSAncHVuY2hfZGF0ZXMnIG9mIG51bGwgaW4gL2ludGVyZmFjZS9odG1sNS8jIW09VGltZVNoZWV0JmRhdGU9MjAxNTAzMjMmdXNlcl9pZD02OTU0MyBsaW5lIDY0NDhcblx0XHRpZiAoIHRoaXMuaXNfbWFzc19hZGRpbmcgJiYgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICkge1xuXG5cdFx0XHRyZWNvcmQgPSBbXTtcblx0XHRcdHZhciBkYXRlc19hcnJheSA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5wdW5jaF9kYXRlcztcblxuXHRcdFx0aWYgKCBkYXRlc19hcnJheSAmJiBkYXRlc19hcnJheS5pbmRleE9mKCAnIC0gJyApID4gMCApIHtcblx0XHRcdFx0ZGF0ZXNfYXJyYXkgPSB0aGlzLnBhcnNlckRhdGVzUmFuZ2UoIGRhdGVzX2FycmF5ICk7XG5cdFx0XHR9XG5cblx0XHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGRhdGVzX2FycmF5Lmxlbmd0aDsgaSsrICkge1xuXHRcdFx0XHR2YXIgY29tbW9uX3JlY29yZCA9IEdsb2JhbC5jbG9uZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICk7XG5cdFx0XHRcdGRlbGV0ZSBjb21tb25fcmVjb3JkLnB1bmNoX2RhdGVzO1xuXHRcdFx0XHRpZiAoIHRoaXMuYWJzZW5jZV9tb2RlbCApIHtcblx0XHRcdFx0XHRjb21tb25fcmVjb3JkLmRhdGVfc3RhbXAgPSBkYXRlc19hcnJheVtpXTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRjb21tb25fcmVjb3JkLnB1bmNoX2RhdGUgPSBkYXRlc19hcnJheVtpXTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJlY29yZC5wdXNoKCBjb21tb25fcmVjb3JkICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Y3VycmVudF9hcGkuc2V0SXNJZGVtcG90ZW50KCB0cnVlICk7IC8vRm9yY2UgdG8gaWRlbXBvdGVudCBBUEkgY2FsbCB0byBhdm9pZCBkdXBsaWNhdGUgbmV0d29yayByZXF1ZXN0cyBmcm9tIGNhdXNpbmcgZXJyb3JzIGRpc3BsYXllZCB0byB0aGUgdXNlci5cblx0XHRjdXJyZW50X2FwaVsnc2V0JyArIGN1cnJlbnRfYXBpLmtleV9uYW1lXSggcmVjb3JkLCBmYWxzZSwgaWdub3JlV2FybmluZywge1xuXHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cblx0XHRcdFx0aWYgKCByZXN1bHQuaXNWYWxpZCgpICkge1xuXHRcdFx0XHRcdCR0aGlzLmZpcnN0X2J1aWxkID0gdHJ1ZTtcblx0XHRcdFx0XHQkdGhpcy5zZWFyY2goKTtcblxuXHRcdFx0XHRcdCR0aGlzLnJlbW92ZUVkaXRWaWV3KCk7XG5cblx0XHRcdFx0XHQvLyMyMjk1IC0gUmUtaW5pdGlhbGl6ZSBwcmV2aW91c19hYnNlbmNlX3BvbGljeV9pZCB0byBlbnN1cmUgdGhhdCBwcmV2aW91c2x5IHNhdmVkIHZhbHVlcyBhcmUgcGFzc2VkIGNvcnJlY3RseSBpbnRvIHRoZSBlc3RpbWF0aW9uIG9mIHByb2plY3RlZCBhdmFpbGFibGUgYmFsYW5jZS5cblx0XHRcdFx0XHQkdGhpcy5wcmV2aW91c19hYnNlbmNlX3BvbGljeV9pZCA9IGZhbHNlO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdCR0aGlzLnNldEVycm9yTWVudSgpO1xuXHRcdFx0XHRcdCR0aGlzLnNldEVycm9yVGlwcyggcmVzdWx0ICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXHRcdH0gKTtcblx0fVxuXG5cdG9uTWFwU2F2ZUNsaWNrKCBkYXRhc2V0LCBzdWNjZXNzQ2FsbGJhY2sgKSB7XG5cdFx0dGhpcy5zYXZlUHVuY2hQb3NpdGlvbiggZGF0YXNldCwgc3VjY2Vzc0NhbGxiYWNrICk7XG5cdH1cblxuXHRzYXZlUHVuY2hQb3NpdGlvbiggbW92ZWRfdW5zYXZlZF9tYXJrZXJzLCBzdWNjZXNzQ2FsbGJhY2sgKSB7XG5cdFx0aWYgKCAhbW92ZWRfdW5zYXZlZF9tYXJrZXJzIHx8IG1vdmVkX3Vuc2F2ZWRfbWFya2Vycy5sZW5ndGggIT09IDEgKSB7XG5cdFx0XHREZWJ1Zy5UZXh0KCAnRVJST1I6IEludmFsaWQgcGFyYW1zL2RhdGEgcGFzc2VkIHRvIGZ1bmN0aW9uLicsICdUaW1lc2hlZXRWaWV3Q29ucm9sbGVyLmpzJywgJ1RpbWVzaGVldFZpZXdDb25yb2xsZXInLCAnc2F2ZVB1bmNoUG9zaXRpb24nLCAxICk7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdHRoaXMuc2V0TG9jYXRpb25WYWx1ZSggbW92ZWRfdW5zYXZlZF9tYXJrZXJzWzBdICk7XG5cdFx0c3VjY2Vzc0NhbGxiYWNrKCk7XG5cdFx0dGhpcy5pc19jaGFuZ2VkID0gdHJ1ZTtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdGdldE90aGVyRmllbGRUeXBlSWQoKSB7XG5cdFx0dmFyIHJlcyA9IDE1O1xuXG5cdFx0aWYgKCB0aGlzLmFic2VuY2VfbW9kZWwgKSB7XG5cdFx0XHRyZXMgPSAwO1xuXHRcdH1cblxuXHRcdHJldHVybiByZXM7XG5cdH1cblxuXHQvKipcblx0ICogVGhpcyBmdW5jdGlvbiBpcyBzcGVjaWFsIGFzIGl0IGhhbmRsZXMgYW4gZWRpdCB2aWV3IHRoYXQgZGVhbHMgd2l0aCBib3RoIGFic2VuY2VzIGFuZCBwdW5jaGVzLlxuXHQgKiBUaGlzIGlzIHRoZSBvbmx5IHBsYWNlIHdoZXJlIDIgZGlmZmVyZW50IGRhdGEgbGF5b3V0cyBuZWVkIHRvIGJlIGhhbmRsZWQgYnkgdGhlIHNhbWUgbmF2aWdhdGlvbiB3aXRob3V0IGEgY2hhbmdlIG9mIHZpZXcuXG5cdCAqL1xuXHRzZXRFZGl0Vmlld0RhdGEoKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgbmF2aWdhdGlvbl9kaXYgPSB0aGlzLmVkaXRfdmlldy5maW5kKCAnLm5hdmlnYXRpb24tZGl2JyApO1xuXHRcdHZhciBuYXZpZ2F0aW9uX3dpZGdldF9kaXYgPSBuYXZpZ2F0aW9uX2Rpdi5maW5kKCAnLm5hdmlnYXRpb24td2lkZ2V0LWRpdicgKTtcblxuXHRcdHRoaXMuaXNfY2hhbmdlZCA9IGZhbHNlO1xuXG5cdFx0aWYgKCBHbG9iYWwuaXNTZXQoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCApICYmIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCApIHtcblx0XHRcdC8vZml4aW5nIGJvdGggIzIxNzEgYW5kICMyMjI3XG5cdFx0XHQvL3ByZXZlbnRpbmcgdW5jbGlja2FibGUgbmF2aWdhdGlvbiBhbmQgXCJjYW5ub3QgZmluZCBwcm9wZXJ0eSBvciBmdW5jdGlvbiBoYXMgb2YgdW5kZWZpbmVkLlwiXG5cdFx0XHRuYXZpZ2F0aW9uX2Rpdi5jc3MoICdkaXNwbGF5JywgJ2Jsb2NrJyApO1xuXHRcdFx0dGhpcy5uYXZpZ2F0aW9uID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWCApO1xuXG5cdFx0XHQvL1NldCBOYXZpZ2F0aW9uIEF3ZXNvbWVib3hcblx0XHRcdGlmICggdGhpcy5hYnNlbmNlX21vZGVsICkge1xuXHRcdFx0XHR0aGlzLm5hdmlnYXRpb24uQUNvbWJvQm94KCB7XG5cdFx0XHRcdFx0aWQ6IHRoaXMuc2NyaXB0X25hbWUgKyAnX25hdmlnYXRpb24nLFxuXHRcdFx0XHRcdGxheW91dF9uYW1lOiAnZ2xvYmFsX2Fic2VuY2UnXG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRpZiAoIHRoaXMuYWJzZW5jZV9vcmlnaW5hbF9zb3VyY2UgKSB7XG5cdFx0XHRcdFx0dGhpcy5uYXZpZ2F0aW9uLnNldFNvdXJjZURhdGEoIHRoaXMuYWJzZW5jZV9vcmlnaW5hbF9zb3VyY2UgKTtcblx0XHRcdFx0XHR0aGlzLm5hdmlnYXRpb24uaXNfcHVuY2hfbmF2ID0gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMubmF2aWdhdGlvbi5BQ29tYm9Cb3goIHtcblx0XHRcdFx0XHRpZDogdGhpcy5zY3JpcHRfbmFtZSArICdfbmF2aWdhdGlvbicsXG5cdFx0XHRcdFx0bGF5b3V0X25hbWU6ICdnbG9iYWxfdGltZXNoZWV0J1xuXHRcdFx0XHR9ICk7XG5cblx0XHRcdFx0aWYgKCB0aGlzLmZ1bGxfdGltZXNoZWV0X2RhdGEgKSB7XG5cdFx0XHRcdFx0dGhpcy5uYXZpZ2F0aW9uLnNldFNvdXJjZURhdGEoIHRoaXMuZnVsbF90aW1lc2hlZXRfZGF0YS5wdW5jaF9kYXRhICk7XG5cdFx0XHRcdFx0dGhpcy5uYXZpZ2F0aW9uLmlzX3B1bmNoX25hdiA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0dGhpcy5uYXZpZ2F0aW9uLnNldFZhbHVlKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgKTtcblxuXHRcdFx0bmF2aWdhdGlvbl93aWRnZXRfZGl2Lmh0bWwoIHRoaXMubmF2aWdhdGlvbiApO1xuXHRcdFx0Ly8gIzIxMjIgLSBGaXhlcyBuYXZpZ2F0aW9uIGVycm9ycyBpbmNsdWRpbmc6IFwiQ2Fubm90IHJlYWQgcHJvcGVydHkgJ2N1cnJlbnRfcGFnZScgb2YgbnVsbFwiICYgXCJDYW5ub3QgcmVhZCBwcm9wZXJ0eSAnaGFzJyBvZiBudWxsXCJcblx0XHRcdC8vIFByZXZlbnRzIHVzZXIgY2xpY2tpbmcgb24gZHJvcC1kb3duIHRvIG5hdmlnYXRlIHRvIHRoZSBmaXJzdCByZWNvcmQgdGhlbiBpbW1lZGlhdGVseSBjbGlja2luZyB0aGUgbGVmdCBhcnJvdyB3aGljaCB0cmlnZ2VycyB0aGUgZXJyb3JzLlxuXHRcdFx0dGhpcy5zZXROYXZpZ2F0aW9uKCk7XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0bmF2aWdhdGlvbl9kaXYuY3NzKCAnZGlzcGxheScsICdub25lJyApO1xuXHRcdH1cblxuXHRcdGZvciAoIHZhciBrZXkgaW4gdGhpcy5lZGl0X3ZpZXdfdWlfZGljICkge1xuXG5cdFx0XHQvL1NldCBhbGwgVUkgZmllbGQgdG8gY3VycmVudCBlZGl0IHJlY29yZCwgd2UgbmVlZCB2YWxpZGF0ZSBhbGwgVUkgZmllbGxkIHdoZW4gc2F2ZSBhbmQgdmFsaWRhdGVcblx0XHRcdGlmICggIUdsb2JhbC5pc1NldCggJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFtrZXldICkgJiYgIXRoaXMuaXNfbWFzc19lZGl0aW5nICkge1xuXHRcdFx0XHQkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2tleV0gPSBmYWxzZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoIHRoaXMuaXNfbWFzc19lZGl0aW5nICkge1xuXHRcdFx0Zm9yICggdmFyIGtleSBpbiB0aGlzLmVkaXRfdmlld191aV9kaWMgKSB7XG5cdFx0XHRcdHZhciB3aWRnZXQgPSB0aGlzLmVkaXRfdmlld191aV9kaWNba2V5XTtcblx0XHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoIHdpZGdldC5zZXRNYXNzRWRpdE1vZGUgKSApIHtcblx0XHRcdFx0XHR3aWRnZXQuc2V0TWFzc0VkaXRNb2RlKCB0cnVlICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXG5cdFx0XHQkLmVhY2goIHRoaXMudW5pcXVlX2NvbHVtbnMsIGZ1bmN0aW9uKCBpbmRleCwgdmFsdWUgKSB7XG5cblx0XHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoICR0aGlzLmVkaXRfdmlld191aV9kaWNbdmFsdWVdICkgJiYgR2xvYmFsLmlzU2V0KCAkdGhpcy5lZGl0X3ZpZXdfdWlfZGljW3ZhbHVlXS5zZXRFbmFibGVkICkgKSB7XG5cdFx0XHRcdFx0JHRoaXMuZWRpdF92aWV3X3VpX2RpY1t2YWx1ZV0uc2V0RW5hYmxlZCggZmFsc2UgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9ICk7XG5cblx0XHR9XG5cblx0XHR0aGlzLnNldE5hdmlnYXRpb25BcnJvd3NFbmFibGVkKCk7XG5cblx0XHQvLyBDcmVhdGUgdGhpcyBmdW5jdGlvbiBhbG9uZSBiZWNhdXNlIG9mIHRoZSBjb2x1bW4gdmFsdWUgb2YgdmlldyBpcyBkaWZmZXJlbnQgZnJvbSBlYWNoIG90aGVyLCBzb21lIGNvbHVtbnMgbmVlZCB0byBiZSBoYW5kbGUgc3BlY2lhbGx5LiBhbmQgZWFzaWx5IHRvIHJld3JpdGUgdGhpcyBmdW5jdGlvbiBpbiBzdWItY2xhc3MuXG5cdFx0dGhpcy5zZXRDdXJyZW50RWRpdFJlY29yZERhdGEoKTtcblxuXHRcdC8vSW5pdCAqUGxlYXNlIHNhdmUgdGhpcyByZWNvcmQgYmVmb3JlIG1vZGlmeWluZyBhbnkgcmVsYXRlZCBkYXRhKiBib3hcblx0XHR0aGlzLmVkaXRfdmlldy5maW5kKCAnLnNhdmUtYW5kLWNvbnRpbnVlLWRpdicgKS5TYXZlQW5kQ29udGludWVCb3goIHsgcmVsYXRlZF92aWV3X2NvbnRyb2xsZXI6IHRoaXMgfSApO1xuXHRcdHRoaXMuZWRpdF92aWV3LmZpbmQoICcuc2F2ZS1hbmQtY29udGludWUtZGl2JyApLmNzcyggJ2Rpc3BsYXknLCAnbm9uZScgKTtcblxuXHRcdHRoaXMuaW5pdFRhYkRhdGEoKTtcblx0XHR0aGlzLnN3aXRjaFRvUHJvcGVyVGFiKCk7XG5cdH1cblxuXHRzZXRDdXJyZW50RWRpdFJlY29yZERhdGEoKSB7XG5cdFx0Ly9TZXQgY3VycmVudCBlZGl0IHJlY29yZCBkYXRhIHRvIGFsbCB3aWRnZXRzXG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdHZhciB0YWJfMF9sYWJlbCA9IHRoaXMuZWRpdF92aWV3LmZpbmQoICdhW3JlZj10YWJfcHVuY2hdJyApO1xuXHRcdGlmICggdGFiXzBfbGFiZWwgKSB7XG5cdFx0XHRpZiAoIHRoaXMuYWJzZW5jZV9tb2RlbCApIHtcblx0XHRcdFx0dGFiXzBfbGFiZWwudGV4dCggJC5pMThuLl8oICdBYnNlbmNlJyApICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0YWJfMF9sYWJlbC50ZXh0KCAkLmkxOG4uXyggJ1B1bmNoJyApICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly9UaGlzIG5lZWRzIHRvIGJlIGRvbmUgaGVyZSBvciB0aGUgdXNlciBpZCBnZXRzIHN0dWNrIGFuZCBzdWJzZXF1ZW50IHB1bmNoZXMgZm9yIHN1Ym9yZGluYXRlcyBnbyB0byB0aGUgYWRtaW4ncyB0aW1lc2hlZXQuXG5cdFx0dGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnVzZXJfaWQgPSB0aGlzLmdldFNlbGVjdEVtcGxveWVlKCk7XG5cblx0XHRmb3IgKCB2YXIga2V5IGluIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCApIHtcblxuXHRcdFx0aWYgKCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmhhc093blByb3BlcnR5KCBrZXkgKSApIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cdFx0XHR2YXIgd2lkZ2V0ID0gdGhpcy5lZGl0X3ZpZXdfdWlfZGljW2tleV07XG5cdFx0XHR2YXIgYXJncztcblx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCB3aWRnZXQgKSApIHtcblx0XHRcdFx0c3dpdGNoICgga2V5ICkge1xuXHRcdFx0XHRcdGNhc2UgJ3B1bmNoX2RhdGVzJzpcblx0XHRcdFx0XHRcdHZhciBkYXRlX2FycmF5O1xuXHRcdFx0XHRcdFx0aWYgKCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnB1bmNoX2RhdGVzICkge1xuXHRcdFx0XHRcdFx0XHRkYXRlX2FycmF5ID0gdGhpcy5nZXRTZWxlY3REYXRlQXJyYXkoKTtcblx0XHRcdFx0XHRcdFx0dGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnB1bmNoX2RhdGVzID0gZGF0ZV9hcnJheTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdGRhdGVfYXJyYXkgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQucHVuY2hfZGF0ZXM7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR3aWRnZXQuc2V0VmFsdWUoIGRhdGVfYXJyYXkgKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ2ZpcnN0X2xhc3RfbmFtZSc6XG5cdFx0XHRcdFx0XHR2YXIgc2VsZWN0X2VtcGxveWVlID0gdGhpcy5nZXRTZWxlY3RFbXBsb3llZSggdHJ1ZSApOyAvL0dldCBmdWxsIGl0ZW1cblx0XHRcdFx0XHRcdC8vRXJyb3I6IFVuY2F1Z2h0IFR5cGVFcnJvcjogQ2Fubm90IHJlYWQgcHJvcGVydHkgJ2ZpcnN0X25hbWUnIG9mIG51bGwgaW4gaW50ZXJmYWNlL2h0bWw1LyMhbT1UaW1lU2hlZXQmZGF0ZT1udWxsJnVzZXJfaWQ9bnVsbCZzaG93X3dhZ2U9MCZhPW5ldyZ0PXB1bmNoJnRhYj1QdW5jaCBsaW5lIDY4MTBcblx0XHRcdFx0XHRcdGlmICggc2VsZWN0X2VtcGxveWVlICkge1xuXHRcdFx0XHRcdFx0XHR3aWRnZXQuc2V0VmFsdWUoIHNlbGVjdF9lbXBsb3llZVsnZmlyc3RfbmFtZSddICsgJyAnICsgc2VsZWN0X2VtcGxveWVlWydsYXN0X25hbWUnXSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSAndG90YWxfdGltZSc6XG5cdFx0XHRcdFx0XHRpZiAoIHRoaXMuYWJzZW5jZV9tb2RlbCApIHtcblx0XHRcdFx0XHRcdFx0dmFyIHJlc3VsdCA9IEdsb2JhbC5nZXRUaW1lVW5pdCggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2tleV0gKTtcblx0XHRcdFx0XHRcdFx0d2lkZ2V0LnNldFZhbHVlKCByZXN1bHQgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ3N0YXRpb25faWQnOlxuXHRcdFx0XHRcdFx0aWYgKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRba2V5XSApIHtcblx0XHRcdFx0XHRcdFx0dGhpcy5zZXRTdGF0aW9uKCk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHR3aWRnZXQuc2V0VmFsdWUoICdOL0EnICk7XG5cdFx0XHRcdFx0XHRcdHdpZGdldC5jc3MoICdjdXJzb3InLCAnZGVmYXVsdCcgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ3B1bmNoX2ltYWdlJzpcblx0XHRcdFx0XHRcdHZhciBzdGF0aW9uX2Zvcm1faXRlbSA9IHRoaXMuZWRpdF92aWV3X2Zvcm1faXRlbV9kaWNbJ3N0YXRpb25faWQnXTtcblx0XHRcdFx0XHRcdGlmICggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkWydoYXNfaW1hZ2UnXSApIHtcblx0XHRcdFx0XHRcdFx0dGhpcy5hdHRhY2hFbGVtZW50KCAncHVuY2hfaW1hZ2UnICk7XG5cdFx0XHRcdFx0XHRcdHdpZGdldC5zZXRWYWx1ZSggU2VydmljZUNhbGxlci5nZXRVUkxCeU9iamVjdFR5cGUoICdmaWxlX2Rvd25sb2FkJyApICsgJyZvYmplY3RfdHlwZT1wdW5jaF9pbWFnZSZwYXJlbnRfaWQ9JyArIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC51c2VyX2lkICsgJyZvYmplY3RfaWQ9JyArIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCApO1xuXG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHR0aGlzLmRldGFjaEVsZW1lbnQoICdwdW5jaF9pbWFnZScgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ2pvYl9pZCc6XG5cdFx0XHRcdFx0XHRpZiAoICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSApIHtcblx0XHRcdFx0XHRcdFx0YXJncyA9IHt9O1xuXHRcdFx0XHRcdFx0XHRhcmdzLmZpbHRlcl9kYXRhID0ge1xuXHRcdFx0XHRcdFx0XHRcdHN0YXR1c19pZDogMTAsXG5cdFx0XHRcdFx0XHRcdFx0dXNlcl9pZDogdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnVzZXJfaWQsXG5cdFx0XHRcdFx0XHRcdFx0cHVuY2hfYnJhbmNoX2lkOiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuYnJhbmNoX2lkLFxuXHRcdFx0XHRcdFx0XHRcdHB1bmNoX2RlcGFydG1lbnRfaWQ6IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5kZXBhcnRtZW50X2lkXG5cdFx0XHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0XHRcdHdpZGdldC5zZXREZWZhdWx0QXJncyggYXJncyApO1xuXHRcdFx0XHRcdFx0XHR3aWRnZXQuc2V0VmFsdWUoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFtrZXldICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlICdqb2JfaXRlbV9pZCc6XG5cdFx0XHRcdFx0XHRpZiAoICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSApIHtcblx0XHRcdFx0XHRcdFx0YXJncyA9IHt9O1xuXHRcdFx0XHRcdFx0XHRhcmdzLmZpbHRlcl9kYXRhID0geyBzdGF0dXNfaWQ6IDEwLCBqb2JfaWQ6IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5qb2JfaWQgfTtcblx0XHRcdFx0XHRcdFx0d2lkZ2V0LnNldERlZmF1bHRBcmdzKCBhcmdzICk7XG5cdFx0XHRcdFx0XHRcdHdpZGdldC5zZXRWYWx1ZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2tleV0gKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ3B1bmNoX3RhZ19pZCc6XG5cdFx0XHRcdFx0XHRpZiAoICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSApIHtcblx0XHRcdFx0XHRcdFx0d2lkZ2V0LnNldFZhbHVlKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRba2V5XSApO1xuXHRcdFx0XHRcdFx0XHR0aGlzLnByZXZpb3VzX3B1bmNoX3RhZ19zZWxlY3Rpb24gPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRba2V5XTtcblxuXHRcdFx0XHRcdFx0XHR2YXIgcHVuY2hfdGFnX3dpZGdldCA9IHdpZGdldDtcblx0XHRcdFx0XHRcdFx0VFRQcm9taXNlLndhaXQoIG51bGwsIG51bGwsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHRcdC8vVXBkYXRlIGRlZmF1bHQgYXJncyBmb3IgcHVuY2ggdGFncyBBQ29tYm9Cb3ggbGFzdCBhcyB0aGV5IHJlbHkgb24gZGF0YSBmcm9tIGpvYiwgam9iIGl0ZW0gYW5kIHJlbGF0ZWQgZmllbGRzLlxuXHRcdFx0XHRcdFx0XHRcdHZhciBhcmdzID0ge307XG5cdFx0XHRcdFx0XHRcdFx0YXJncy5maWx0ZXJfZGF0YSA9ICR0aGlzLmdldFB1bmNoVGFnRmlsdGVyRGF0YSgpO1xuXHRcdFx0XHRcdFx0XHRcdHB1bmNoX3RhZ193aWRnZXQuc2V0RGVmYXVsdEFyZ3MoIGFyZ3MgKTtcblx0XHRcdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSAnYnJhbmNoX2lkJzpcblx0XHRcdFx0XHRcdGlmICggKCBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAyMCApICkge1xuXHRcdFx0XHRcdFx0XHR2YXIgYXJncyA9IHt9O1xuXHRcdFx0XHRcdFx0XHRhcmdzLmZpbHRlcl9kYXRhID0geyB1c2VyX2lkOiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudXNlcl9pZCB9O1xuXHRcdFx0XHRcdFx0XHR3aWRnZXQuc2V0RGVmYXVsdEFyZ3MoIGFyZ3MgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdHdpZGdldC5zZXRWYWx1ZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2tleV0gKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ2RlcGFydG1lbnRfaWQnOlxuXHRcdFx0XHRcdFx0aWYgKCAoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpID49IDIwICkgKSB7XG5cdFx0XHRcdFx0XHRcdHZhciBhcmdzID0ge307XG5cdFx0XHRcdFx0XHRcdGFyZ3MuZmlsdGVyX2RhdGEgPSB7IHVzZXJfaWQ6IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC51c2VyX2lkLCBicmFuY2hfaWQ6IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5icmFuY2hfaWQgfTtcblx0XHRcdFx0XHRcdFx0d2lkZ2V0LnNldERlZmF1bHRBcmdzKCBhcmdzICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR3aWRnZXQuc2V0VmFsdWUoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFtrZXldICk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlICdqb2JfcXVpY2tfc2VhcmNoJzpcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ2pvYl9pdGVtX3F1aWNrX3NlYXJjaCc6XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlICdwdW5jaF90YWdfcXVpY2tfc2VhcmNoJzpcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ2xhdGl0dWRlJzpcblx0XHRcdFx0XHRjYXNlICdsb25naXR1ZGUnOlxuXHRcdFx0XHRcdGNhc2UgJ3Bvc2l0aW9uX2FjY3VyYWN5Jzpcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0XHR3aWRnZXQuc2V0VmFsdWUoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFtrZXldICk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLmFic2VuY2VfbW9kZWwgKSB7XG5cblx0XHRcdGlmICggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkICkge1xuXHRcdFx0XHR0aGlzLnByZV90b3RhbF90aW1lID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnRvdGFsX3RpbWU7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLnByZV90b3RhbF90aW1lID0gMDtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5wcmVfdG90YWxfdGltZSA9IDA7XG5cdFx0fVxuXG5cdFx0dmFyIGFjdHVhbF90aW1lX3ZhbHVlO1xuXHRcdGlmICggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkICkge1xuXG5cdFx0XHRpZiAoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5hY3R1YWxfdGltZV9zdGFtcCApIHtcblx0XHRcdFx0YWN0dWFsX3RpbWVfdmFsdWUgPSAkLmkxOG4uXyggJ0FjdHVhbCBUaW1lJyApICsgJzogJyArIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5hY3R1YWxfdGltZV9zdGFtcDtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGFjdHVhbF90aW1lX3ZhbHVlID0gJ04vQSc7XG5cdFx0XHR9XG5cblx0XHR9XG5cblx0XHR0aGlzLnNldExvY2F0aW9uVmFsdWUoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCApO1xuXG5cdFx0dGhpcy5hY3R1YWxfdGltZV9sYWJlbC50ZXh0KCBhY3R1YWxfdGltZV92YWx1ZSApO1xuXG5cdFx0dGhpcy5vbkF2YWlsYWJsZUJhbGFuY2VDaGFuZ2UoKTtcblxuXHRcdHRoaXMuc2V0RWRpdE1lbnUoKTsgLy9UbyBtYWtlIHN1cmUgc2F2ZSAmIGNvbnRpbnVlIGljb24gZGlzYWJsZWQgY29ycmVjdCB3aGVuIG11bHRpIGRhdGVzXG5cblx0XHR0aGlzLnNldEVkaXRWaWV3RGF0YURvbmUoKTtcblx0fVxuXG5cdHNldEVkaXRWaWV3RGF0YURvbmUoKSB7XG5cdFx0c3VwZXIuc2V0RWRpdFZpZXdEYXRhRG9uZSgpO1xuXHRcdC8vY2FuJ3QgY2hlY2sgaXNfZWRpdCBoZXJlIGJlY2F1c2UgaW4gdGltZXNoZWV0IGl0IGNhbiBiZSBib3RoLlxuXHRcdGlmICggdGhpcy5pc192aWV3aW5nID09IHRydWUgJiYgKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQubGF0aXR1ZGUgPT0gMCB8fCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQubG9uZ2l0dWRlID09IDAgKSApIHtcblx0XHRcdCQoICcud2lkZ2V0LWgtYm94LW1hcExvY2F0aW9uV3JhcHBlcicgKS5wYXJlbnRzKCAnLmVkaXQtdmlldy1mb3JtLWl0ZW0tZGl2JyApLmhpZGUoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKCB0aGlzLnNob3dfbG9jYXRpb25fdWkgKSB7XG5cdFx0XHRcdCQoICcud2lkZ2V0LWgtYm94LW1hcExvY2F0aW9uV3JhcHBlcicgKS5wYXJlbnRzKCAnLmVkaXQtdmlldy1mb3JtLWl0ZW0tZGl2JyApLnNob3coKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRzZXRMb2NhdGlvblZhbHVlKCBsb2NhdGlvbl9kYXRhICkge1xuXHRcdGlmICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMTVcblx0XHRcdCYmIHRoaXMuZWRpdF92aWV3X3VpX2RpY1snbGF0aXR1ZGUnXVxuXHRcdFx0JiYgdGhpcy5lZGl0X3ZpZXdfdWlfZGljWydsb25naXR1ZGUnXVxuXHRcdFx0JiYgdGhpcy5lZGl0X3ZpZXdfdWlfZGljWydwb3NpdGlvbl9hY2N1cmFjeSddXG5cdFx0KSB7XG5cdFx0XHRpZiAoIGxvY2F0aW9uX2RhdGEgKSB7XG5cdFx0XHRcdHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5sYXRpdHVkZSA9IGxvY2F0aW9uX2RhdGEubGF0aXR1ZGU7XG5cdFx0XHRcdHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5sb25naXR1ZGUgPSBsb2NhdGlvbl9kYXRhLmxvbmdpdHVkZTtcblx0XHRcdFx0dGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnBvc2l0aW9uX2FjY3VyYWN5ID0gbG9jYXRpb25fZGF0YS5wb3NpdGlvbl9hY2N1cmFjeTtcblx0XHRcdH1cblx0XHRcdHRoaXMuZWRpdF92aWV3X3VpX2RpY1snbGF0aXR1ZGUnXS5zZXRWYWx1ZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmxhdGl0dWRlICk7XG5cdFx0XHR0aGlzLmVkaXRfdmlld191aV9kaWNbJ2xvbmdpdHVkZSddLnNldFZhbHVlKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQubG9uZ2l0dWRlICk7XG5cdFx0XHR0aGlzLmVkaXRfdmlld191aV9kaWNbJ3Bvc2l0aW9uX2FjY3VyYWN5J10uc2V0VmFsdWUoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5wb3NpdGlvbl9hY2N1cmFjeSA/IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5wb3NpdGlvbl9hY2N1cmFjeSA6IDAgKTtcblxuXHRcdFx0aWYgKCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmxhdGl0dWRlICYmICF0aGlzLmlzX21hc3NfZWRpdGluZyApIHtcblx0XHRcdFx0dGhpcy5sb2NhdGlvbl93cmFwcGVyLmhpZGUoKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGlmICggdGhpcy5zaG93X2xvY2F0aW9uX3VpICkge1xuXHRcdFx0XHRcdHRoaXMubG9jYXRpb25fd3JhcHBlci5zaG93KCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRvbkF2YWlsYWJsZUJhbGFuY2VDaGFuZ2UoKSB7XG5cdFx0aWYgKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaGFzT3duUHJvcGVydHkoICdzcmNfb2JqZWN0X2lkJyApICYmXG5cdFx0XHR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3JjX29iamVjdF9pZCAmJiAhdGhpcy5pc19tYXNzX2VkaXRpbmcgKSB7XG5cdFx0XHR0aGlzLmdldEF2YWlsYWJsZUJhbGFuY2UoIGZhbHNlICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuZGV0YWNoRWxlbWVudCggJ2F2YWlsYWJsZV9iYWxhbmNlJyApO1xuXHRcdH1cblx0XHR0aGlzLmVkaXRGaWVsZFJlc2l6ZSgpO1xuXHR9XG5cblx0Z2V0QXZhaWxhYmxlQmFsYW5jZSggcmVsZWFzZV9iYWxhbmNlICkge1xuXG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgcmVzdWx0X2RhdGE7XG5cblx0XHQvL09uIGZpcnN0IHJ1biwgc2V0IHByZXZpb3VzX2Fic2VuY2VfcG9saWN5X2lkLlxuXHRcdGlmICggdGhpcy5wcmV2aW91c19hYnNlbmNlX3BvbGljeV9pZCA9PSBmYWxzZSApIHtcblx0XHRcdHRoaXMucHJldmlvdXNfYWJzZW5jZV9wb2xpY3lfaWQgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3JjX29iamVjdF9pZDtcblx0XHR9XG5cblx0XHRpZiAoIHRoaXMuYWJzZW5jZV9tb2RlbCApIHtcblxuXHRcdFx0dmFyIGxhc3RfZGF0ZV9zdGFtcCA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5kYXRlX3N0YW1wO1xuXHRcdFx0dmFyIHRvdGFsX3RpbWUgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudG90YWxfdGltZTtcblxuXHRcdFx0aWYgKCB0aGlzLmlzX21hc3NfYWRkaW5nICkge1xuXG5cdFx0XHRcdGxhc3RfZGF0ZV9zdGFtcCA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5wdW5jaF9kYXRlcztcblx0XHRcdFx0Ly9nZXQgZGF0ZXMgZnJvbSBkYXRlIHJhbmdlclxuXHRcdFx0XHRpZiAoIGxhc3RfZGF0ZV9zdGFtcCAmJiBsYXN0X2RhdGVfc3RhbXAuaW5kZXhPZiggJyAtICcgKSA+IDAgfHxcblx0XHRcdFx0XHQkLnR5cGUoIGxhc3RfZGF0ZV9zdGFtcCApID09PSAnYXJyYXknICkge1xuXG5cdFx0XHRcdFx0aWYgKCBsYXN0X2RhdGVfc3RhbXAuaW5kZXhPZiggJyAtICcgKSA+IDAgKSB7XG5cdFx0XHRcdFx0XHRsYXN0X2RhdGVfc3RhbXAgPSB0aGlzLnBhcnNlckRhdGVzUmFuZ2UoIGxhc3RfZGF0ZV9zdGFtcCApO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICggbGFzdF9kYXRlX3N0YW1wLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdFx0XHR0b3RhbF90aW1lID0gdG90YWxfdGltZSAqIGxhc3RfZGF0ZV9zdGFtcC5sZW5ndGg7XG5cdFx0XHRcdFx0XHRsYXN0X2RhdGVfc3RhbXAgPSBsYXN0X2RhdGVfc3RhbXBbbGFzdF9kYXRlX3N0YW1wLmxlbmd0aCAtIDFdO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuYXBpX2Fic2VuY2VfcG9saWN5LmdldFByb2plY3RlZEFic2VuY2VQb2xpY3lCYWxhbmNlKFxuXHRcdFx0XHR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3JjX29iamVjdF9pZCxcblx0XHRcdFx0dGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpLFxuXHRcdFx0XHRsYXN0X2RhdGVfc3RhbXAsXG5cdFx0XHRcdHRvdGFsX3RpbWUsXG5cdFx0XHRcdHRoaXMucHJlX3RvdGFsX3RpbWUsXG5cdFx0XHRcdHRoaXMucHJldmlvdXNfYWJzZW5jZV9wb2xpY3lfaWQsXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlc3VsdCApIHtcblx0XHRcdFx0XHRcdGlmICggcmVsZWFzZV9iYWxhbmNlICkge1xuXHRcdFx0XHRcdFx0XHQkdGhpcy5yZWxlYXNlQmFsYW5jZSggcmVzdWx0LmdldFJlc3VsdCgpLmF2YWlsYWJsZV9iYWxhbmNlICk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHQkdGhpcy5nZXRCYWxhbmNlSGFuZGxlciggcmVzdWx0LCBsYXN0X2RhdGVfc3RhbXAgKTtcblxuXHRcdFx0XHRcdFx0XHQvLyBJZiB0aGUgc2VsZWN0ZWQgQWJzZW5jZSBQb2xpY3kgaXMgbm90IGxpbmtlZCB0byBhbnkgYWNjcnVhbC5cblx0XHRcdFx0XHRcdFx0Ly8gVGhlIFwiUmVtYWluaW5nIEJhbGFuY2VcIiBidXR0b24gc2hvdWxkIG5vdCBhcHBlYXIgYXMgdGhlcmUgaXMgbm8gYmFsYW5jZS5cblx0XHRcdFx0XHRcdFx0aWYgKCAkdGhpcy5pc192aWV3aW5nID09IHRydWUgKSB7XG5cdFx0XHRcdFx0XHRcdFx0JCggJyNyZWxlYXNlLWJhbGFuY2UtYnV0dG9uJyApLmNzcyggJ2Rpc3BsYXknLCAnbm9uZScgKTtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIGlmICggR2xvYmFsLmlzT2JqZWN0KCByZXN1bHQgKSApIHtcblx0XHRcdFx0XHRcdFx0XHR2YXIgcmVzdWx0X2RhdGEgPSByZXN1bHQuZ2V0UmVzdWx0KCk7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKCAhcmVzdWx0X2RhdGEgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHQkKCAnI3JlbGVhc2UtYmFsYW5jZS1idXR0b24nICkuY3NzKCAnZGlzcGxheScsICdub25lJyApO1xuXHRcdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0XHQkKCAnI3JlbGVhc2UtYmFsYW5jZS1idXR0b24nICkuY3NzKCAnZGlzcGxheScsICcnICk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdCQoICcjcmVsZWFzZS1iYWxhbmNlLWJ1dHRvbicgKS5jc3MoICdkaXNwbGF5JywgJ25vbmUnICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdCk7XG5cblx0XHR9XG5cdH1cblxuXHRzZXRTdGF0aW9uKCkge1xuXG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgYXJnID0geyBmaWx0ZXJfZGF0YTogeyBpZDogdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXRpb25faWQgfSB9O1xuXG5cdFx0dGhpcy5hcGlfc3RhdGlvbi5nZXRTdGF0aW9uKCBhcmcsIHtcblx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXG5cdFx0XHRcdCR0aGlzLnN0YXRpb24gPSByZXN1bHQuZ2V0UmVzdWx0KClbMF07XG5cblx0XHRcdFx0dmFyIHdpZGdldCA9ICR0aGlzLmVkaXRfdmlld191aV9kaWNbJ3N0YXRpb25faWQnXTtcblx0XHRcdFx0aWYgKCAkdGhpcy5zdGF0aW9uICkge1xuXHRcdFx0XHRcdC8vRXJyb3I6IFVuY2F1Z2h0IFR5cGVFcnJvcjogQ2Fubm90IHJlYWQgcHJvcGVydHkgJ3NldFZhbHVlJyBvZiB1bmRlZmluZWQgaW4gL2ludGVyZmFjZS9odG1sNS8jIW09VGltZVNoZWV0JmRhdGU9MjAxNDA5MjUgbGluZSA2MDE3XG5cdFx0XHRcdFx0aWYgKCB3aWRnZXQgKSB7XG5cdFx0XHRcdFx0XHR3aWRnZXQuc2V0VmFsdWUoICR0aGlzLnN0YXRpb24udHlwZSArICctJyArICR0aGlzLnN0YXRpb24uZGVzY3JpcHRpb24gKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRpZiAoIHdpZGdldCApIHtcblx0XHRcdFx0XHRcdHdpZGdldC5zZXRWYWx1ZSggJ04vQScgKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCAnc3RhdGlvbicsICd2aWV3JyApIHx8XG5cdFx0XHRcdFx0KCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggJ3N0YXRpb24nLCAndmlld19jaGlsZCcgKSAmJiAkdGhpcy5zdGF0aW9uLmlzX2NoaWxkICkgfHxcblx0XHRcdFx0XHQoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCAnc3RhdGlvbicsICd2aWV3X293bicgKSAmJiAkdGhpcy5zdGF0aW9uLmlzX293bmVyICkgKSB7XG5cdFx0XHRcdFx0JHRoaXMuc2hvd19zdGF0aW9uX3VpID0gdHJ1ZTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkdGhpcy5zaG93X3N0YXRpb25fdWkgPSBmYWxzZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEVycm9yOiBUeXBlRXJyb3I6IGZvcm1faXRlbV9pbnB1dCBpcyB1bmRlZmluZWQgaW4gaW50ZXJmYWNlL2h0bWw1L2ZyYW1ld29yay9qcXVlcnkubWluLmpzP3Y9OS4wLjEtMjAxNTEwMjItMDkxNTQ5IGxpbmUgMiA+IGV2YWwgbGluZSA3MTE5XG5cdFx0XHRcdGlmICggJHRoaXMuc2hvd19zdGF0aW9uX3VpICYmIHdpZGdldCApIHtcblx0XHRcdFx0XHR3aWRnZXQuY3NzKCAnY3Vyc29yJywgJ3BvaW50ZXInICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXHRcdH0gKTtcblx0fVxuXG5cdGdldFNlbGVjdGVkSXRlbXMoKSB7XG5cdFx0dmFyIHNlbGVjdGVkX2l0ZW0gPSBudWxsO1xuXHRcdGlmICggdGhpcy5lZGl0X3ZpZXcgKSB7XG5cdFx0XHRyZXR1cm4gW3RoaXMuY3VycmVudF9lZGl0X3JlY29yZF07XG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0aWYgKCB0aGlzLnNlbGVjdF9wdW5jaGVzX2FycmF5Lmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdHJldHVybiB0aGlzLnNlbGVjdF9wdW5jaGVzX2FycmF5O1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBbXTtcblx0fVxuXG5cdGdldFNlbGVjdGVkSXRlbSgpIHtcblxuXHRcdHZhciBzZWxlY3RlZF9pdGVtID0gbnVsbDtcblx0XHRpZiAoIHRoaXMuZWRpdF92aWV3ICkge1xuXHRcdFx0c2VsZWN0ZWRfaXRlbSA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZDtcblx0XHR9IGVsc2Uge1xuXG5cdFx0XHRpZiAoIHRoaXMuc2VsZWN0X3B1bmNoZXNfYXJyYXkubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0c2VsZWN0ZWRfaXRlbSA9IHRoaXMuc2VsZWN0X3B1bmNoZXNfYXJyYXlbMF07XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRzZWxlY3RlZF9pdGVtID0gbnVsbDtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gR2xvYmFsLmNsb25lKCBzZWxlY3RlZF9pdGVtICk7XG5cdH1cblxuXHRhZGRQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQgKSB7XG5cdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCBwX2lkICkgKSB7XG5cdFx0XHRwX2lkID0gdGhpcy5wZXJtaXNzaW9uX2lkO1xuXHRcdH1cblxuXHRcdGlmICggcF9pZCA9PT0gJ3JlcG9ydCcgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCBwX2lkLCAnYWRkJyApICYmIHRoaXMuZWRpdFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCApICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0c2V0RGVmYXVsdE1lbnUoIGRvTm90U2V0Rm9jdXMgKSB7XG5cdFx0Ly9UaW1lU2hlZXQgdXNlcyBhIGRpZmZlcmVudCBncmlkIHRoYW4gb3RoZXIgdmlld3MgYW5kIG5lZWRzIFwic2VsZWN0X3B1bmNoZXNfYXJyYXlcIiBpbnN0ZWFkIG9mIFwidGhpcy5nZXRHcmlkU2VsZWN0SWRBcnJheSgpXCIgZm9yIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoXG5cdFx0c3VwZXIuc2V0RGVmYXVsdE1lbnUoIGRvTm90U2V0Rm9jdXMsIHRoaXMuc2VsZWN0X3B1bmNoZXNfYXJyYXkubGVuZ3RoICk7XG5cdFx0Ly9TZXQgbW92ZSBvciBkcm9wIG1vZGUgYWZ0ZXIgcmVzdCBvZiBtZW51LlxuXHRcdHRoaXMuc2V0TW92ZU9yRHJvcE1vZGUoIHRoaXMuc2VsZWN0X2RyYWdfbWVudV9pZCA/IHRoaXMuc2VsZWN0X2RyYWdfbWVudV9pZCA6ICdtb3ZlJyApOyAvLyBFbnN1cmUgTW92ZS9Db3B5IHNlbGVjdGlvbnMgYXJlIHNldCB3aGVuIGNsb3NpbmcgcG9wLXVwIHdpbmRvd3MgZnJvbSBKdW1wLVRvIG1lbnUsIGxpa2UgQWRkIFJlcXVlc3QuXG5cdH1cblxuXHRzZXRDdXN0b21EZWZhdWx0TWVudUljb24oIGlkLCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKSB7XG5cdFx0c3dpdGNoICggaWQgKSB7XG5cdFx0XHRjYXNlICdhZGRfcHVuY2gnOlxuXHRcdFx0XHR0aGlzLnNldERlZmF1bHRNZW51QWRkUHVuY2hJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKTtcblx0XHRcdFx0aWYgKCB0aGlzLmdldFB1bmNoUGVybWlzc2lvblR5cGUoKSA9PT0gJ3B1bmNoJyApIHtcblx0XHRcdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuYWN0aXZhdGVTcGxpdEJ1dHRvbkl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ2FkZF9hYnNlbmNlJzpcblx0XHRcdFx0dGhpcy5zZXREZWZhdWx0TWVudUFkZEFic2VuY2VJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKTtcblx0XHRcdFx0aWYgKCB0aGlzLmdldFB1bmNoUGVybWlzc2lvblR5cGUoKSA9PT0gJ2Fic2VuY2UnICkge1xuXHRcdFx0XHRcdENvbnRleHRNZW51TWFuYWdlci5hY3RpdmF0ZVNwbGl0QnV0dG9uSXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnaW5fb3V0Jzpcblx0XHRcdFx0dGhpcy5zZXREZWZhdWx0TWVudUluT3V0SWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnbW92ZSc6XG5cdFx0XHRcdGlmICggIXRoaXMubW92ZVBlcm1pc3Npb25WYWxpZGF0ZSggdGhpcy5nZXRQdW5jaFBlcm1pc3Npb25UeXBlKCkgKSApIHtcblx0XHRcdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApXG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCB0aGlzLmdldFB1bmNoTW9kZSgpID09ICdtYW51YWwnICkge1xuXHRcdFx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgdHJ1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnZWRpdF9wYXlfcGVyaW9kJzpcblx0XHRcdFx0dGhpcy5zZXREZWZhdWx0TWVudUVkaXRQYXlQZXJpb2RJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdwcmludCc6XG5cdFx0XHRcdHRoaXMuc2V0RGVmYXVsdE1lbnVQcmludEljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ2VkaXRfZW1wbG95ZWUnOlxuXHRcdFx0XHR0aGlzLnNldERlZmF1bHRNZW51RWRpdEVtcGxveWVlSWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAncGF5X3N0dWInOlxuXHRcdFx0XHR0aGlzLnNldERlZmF1bHRNZW51UGF5U3R1Ykljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3JlX2NhbGN1bGF0ZV90aW1lc2hlZXQnOlxuXHRcdFx0XHR0aGlzLnNldERlZmF1bHRNZW51UmVDYWxjdWxhdGVUaW1lc2hlZXQoIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ2dlbmVyYXRlX3BheV9zdHViJzpcblx0XHRcdFx0dGhpcy5zZXREZWZhdWx0TWVudUdlbmVyYXRlUGF5U3R1Ykljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3NjaGVkdWxlJzpcblx0XHRcdFx0dGhpcy5zZXREZWZhdWx0TWVudVNjaGVkdWxlSWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnYWNjdW11bGF0ZWRfdGltZSc6XG5cdFx0XHRcdHRoaXMuc2V0RGVmYXVsdE1lbnVBY2N1bXVsYXRlZFRpbWVJY29uKCBjb250ZXh0X2J0biApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ0FkZFJlcXVlc3QnOlxuXHRcdFx0XHR0aGlzLnNldEFkZFJlcXVlc3RJY29uKCBjb250ZXh0X2J0biApO1xuXHRcdFx0XHRicmVhaztcblx0XHR9XG5cdH1cblxuXHRzZXRFZGl0TWVudURyYWdDb3B5SWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICkge1xuXHRcdGlmICggIXRoaXMuY29weVBlcm1pc3Npb25WYWxpZGF0ZSggdGhpcy5nZXRQdW5jaFBlcm1pc3Npb25UeXBlKCkgKSB8fCB0aGlzLmVkaXRfb25seV9tb2RlICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdH1cblxuXHRcdGlmICggdGhpcy5nZXRQdW5jaE1vZGUoKSA9PSAnbWFudWFsJyApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIHRydWUgKTtcblx0XHR9XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudURyYWdDb3B5SWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICkge1xuXHRcdGlmICggIXRoaXMuY29weVBlcm1pc3Npb25WYWxpZGF0ZSggdGhpcy5nZXRQdW5jaFBlcm1pc3Npb25UeXBlKCkgKSB8fCB0aGlzLmVkaXRfb25seV9tb2RlICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdH1cblxuXHRcdGlmICggdGhpcy5nZXRQdW5jaE1vZGUoKSA9PSAnbWFudWFsJyApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIHRydWUgKTtcblx0XHR9XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudVNjaGVkdWxlSWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICkge1xuXHRcdGlmICggIVBlcm1pc3Npb25NYW5hZ2VyLmNoZWNrVG9wTGV2ZWxQZXJtaXNzaW9uKCAnU2NoZWR1bGUnICkgfHwgdGhpcy5lZGl0X29ubHlfbW9kZSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHR9XG5cdH1cblxuXHRyZUNhbGN1bGF0ZUVkaXRQZXJtaXNzaW9uVmFsaWRhdGUoKSB7XG5cblx0XHR2YXIgcF9pZCA9IHRoaXMucGVybWlzc2lvbl9pZDtcblxuXHRcdGlmICggUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHBfaWQsICdlZGl0JyApIHx8IHRoaXMub3duZXJPckNoaWxkUGVybWlzc2lvblZhbGlkYXRlKCBwX2lkLCAnZWRpdF9jaGlsZCcgKSApIHtcblxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHR9XG5cblx0c2V0RGVmYXVsdE1lbnVSZUNhbGN1bGF0ZVRpbWVzaGVldCggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICkge1xuXG5cdFx0aWYgKCAhdGhpcy5yZUNhbGN1bGF0ZUVkaXRQZXJtaXNzaW9uVmFsaWRhdGUoKSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHR9XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudUdlbmVyYXRlUGF5U3R1Ykljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApIHtcblxuXHRcdGlmICggIVBlcm1pc3Npb25NYW5hZ2VyLmNoZWNrVG9wTGV2ZWxQZXJtaXNzaW9uKCAnR2VuZXJhdGVQYXlTdHVicycgKSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHR9XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudVBheVN0dWJJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKSB7XG5cblx0XHRpZiAoICFQZXJtaXNzaW9uTWFuYWdlci5jaGVja1RvcExldmVsUGVybWlzc2lvbiggJ1BheVN0dWInICkgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApXG5cdFx0fVxuXHR9XG5cblx0c2V0RGVmYXVsdE1lbnVFZGl0UGF5UGVyaW9kSWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICkge1xuXG5cdFx0aWYgKCAhdGhpcy5lZGl0UGVybWlzc2lvblZhbGlkYXRlKCAncGF5X3BlcmlvZF9zY2hlZHVsZScgKSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHR9XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0aWYgKCAkdGhpcy5nZXRQYXlQZXJpb2QoKSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIHRydWUgKTtcblx0XHR9XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudUFjY3VtdWxhdGVkVGltZUljb24oIGNvbnRleHRfYnRuICkge1xuXG5cdFx0aWYgKCAhUGVybWlzc2lvbk1hbmFnZXIuY2hlY2tUb3BMZXZlbFBlcm1pc3Npb24oICdBY2N1bXVsYXRlZFRpbWUnICkgfHwgdGhpcy5lZGl0X29ubHlfbW9kZSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHR9XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudUVkaXRFbXBsb3llZUljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApIHtcblxuXHRcdGlmICggIXRoaXMuZWRpdENoaWxkUGVybWlzc2lvblZhbGlkYXRlKCAndXNlcicgKSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHR9XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudUluT3V0SWNvbiggY29udGV4dF9idG4gKSB7XG5cdFx0aWYgKCB0aGlzLmFkZFBlcm1pc3Npb25WYWxpZGF0ZSggJ3B1bmNoJyApICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIHRydWUgKTtcbiAgICAgICAgICAgIENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIHRydWUgKTtcblx0XHR9XG5cdH1cblxuXHRzZXRFZGl0TWVudUluT3V0SWNvbiggY29udGV4dF9idG4gKSB7XG5cdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHR9XG5cblx0ZWRpdE93bmVyT3JDaGlsZFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCwgc2VsZWN0ZWRfaXRlbSApIHtcblxuXHRcdGlmICggIXBfaWQgKSB7XG5cdFx0XHRwX2lkID0gdGhpcy5wZXJtaXNzaW9uX2lkO1xuXHRcdH1cblxuXHRcdGlmICggIXNlbGVjdGVkX2l0ZW0gKSB7XG5cdFx0XHRzZWxlY3RlZF9pdGVtID0gdGhpcy5nZXRTZWxlY3RFbXBsb3llZSggdHJ1ZSApO1xuXHRcdH1cblxuXHRcdGlmICggcF9pZCA9PT0gJ3JlcG9ydCcgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoXG5cdFx0XHRQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggcF9pZCwgJ2VkaXQnICkgfHxcblx0XHRcdCggc2VsZWN0ZWRfaXRlbSAmJiBzZWxlY3RlZF9pdGVtLmlzX293bmVyICYmIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCBwX2lkLCAnZWRpdF9vd24nICkgKSB8fFxuXHRcdFx0KCBzZWxlY3RlZF9pdGVtICYmIHNlbGVjdGVkX2l0ZW0uaXNfY2hpbGQgJiYgUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHBfaWQsICdlZGl0X2NoaWxkJyApICkgKSB7XG5cblx0XHRcdHJldHVybiB0cnVlO1xuXG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0dmlld093bmVyT3JDaGlsZFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCwgc2VsZWN0ZWRfaXRlbSApIHtcblxuXHRcdGlmICggIXBfaWQgKSB7XG5cdFx0XHRwX2lkID0gdGhpcy5wZXJtaXNzaW9uX2lkO1xuXHRcdH1cblxuXHRcdGlmICggcF9pZCA9PT0gJ3JlcG9ydCcgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoICFzZWxlY3RlZF9pdGVtICkge1xuXHRcdFx0c2VsZWN0ZWRfaXRlbSA9IHRoaXMuZ2V0U2VsZWN0RW1wbG95ZWUoIHRydWUgKTtcblx0XHR9XG5cblx0XHRpZiAoXG5cdFx0XHRQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggcF9pZCwgJ3ZpZXcnICkgfHxcblx0XHRcdCggc2VsZWN0ZWRfaXRlbSAmJiBzZWxlY3RlZF9pdGVtLmlzX293bmVyICYmIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCBwX2lkLCAndmlld19vd24nICkgKSB8fFxuXHRcdFx0KCBzZWxlY3RlZF9pdGVtICYmIHNlbGVjdGVkX2l0ZW0uaXNfY2hpbGQgJiYgUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHBfaWQsICd2aWV3X2NoaWxkJyApICkgKSB7XG5cblx0XHRcdHJldHVybiB0cnVlO1xuXG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0ZGVsZXRlT3duZXJPckNoaWxkUGVybWlzc2lvblZhbGlkYXRlKCBwX2lkLCBzZWxlY3RlZF9pdGVtICkge1xuXG5cdFx0aWYgKCAhcF9pZCApIHtcblx0XHRcdHBfaWQgPSB0aGlzLnBlcm1pc3Npb25faWQ7XG5cdFx0fVxuXG5cdFx0aWYgKCAhc2VsZWN0ZWRfaXRlbSApIHtcblx0XHRcdHNlbGVjdGVkX2l0ZW0gPSB0aGlzLmdldFNlbGVjdEVtcGxveWVlKCB0cnVlICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBwX2lkID09PSAncmVwb3J0JyApIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdGlmIChcblx0XHRcdFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCBwX2lkLCAnZGVsZXRlJyApIHx8XG5cdFx0XHQoIHNlbGVjdGVkX2l0ZW0gJiYgc2VsZWN0ZWRfaXRlbS5pc19vd25lciAmJiBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggcF9pZCwgJ2RlbGV0ZV9vd24nICkgKSB8fFxuXHRcdFx0KCBzZWxlY3RlZF9pdGVtICYmIHNlbGVjdGVkX2l0ZW0uaXNfY2hpbGQgJiYgUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHBfaWQsICdkZWxldGVfY2hpbGQnICkgKSApIHtcblxuXHRcdFx0cmV0dXJuIHRydWU7XG5cblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRlZGl0Q2hpbGRQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQsIHNlbGVjdGVkX2l0ZW0gKSB7XG5cdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCBwX2lkICkgKSB7XG5cdFx0XHRwX2lkID0gdGhpcy5wZXJtaXNzaW9uX2lkO1xuXHRcdH1cblxuXHRcdGlmICggIUdsb2JhbC5pc1NldCggc2VsZWN0ZWRfaXRlbSApICkge1xuXHRcdFx0c2VsZWN0ZWRfaXRlbSA9IHRoaXMuZ2V0U2VsZWN0RW1wbG95ZWUoIHRydWUgKTtcblx0XHR9XG5cblx0XHRpZiAoIHBfaWQgPT09ICdyZXBvcnQnICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0aWYgKCAhUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHBfaWQsICdlbmFibGVkJyApICkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdGlmICggUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHBfaWQsICdlZGl0JyApIHx8XG5cdFx0XHR0aGlzLm93bmVyT3JDaGlsZFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCwgJ2VkaXRfY2hpbGQnLCBzZWxlY3RlZF9pdGVtICkgKSB7XG5cblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdG9uUmVwb3J0TWVudUNsaWNrKCBpZCApIHtcblx0XHR0aGlzLm9uTmF2aWdhdGlvbkNsaWNrKCBpZCApO1xuXHR9XG5cblx0c2V0RGVmYXVsdE1lbnVQcmludEljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApIHtcblxuXHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIHRydWUgKTtcblx0fVxuXG5cdHNldEVkaXRNZW51TWFwSWNvbiggY29udGV4dF9idG4gKSB7XG5cdFx0c3VwZXIuc2V0RGVmYXVsdE1lbnVNYXBJY29uKCBjb250ZXh0X2J0biApO1xuXG5cdFx0aWYgKCBjb250ZXh0X2J0bi5kaXNhYmxlZCA9PSB0cnVlICkge1xuXHRcdFx0aWYgKCB0aGlzLmFic2VuY2VfbW9kZWwgfHwgdGhpcy5nZXRQdW5jaE1vZGUoKSA9PSAnbWFudWFsJyApIHtcblx0XHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRzZXRFZGl0TWVudVNhdmVBbmRBZGRJY29uKCBjb250ZXh0X2J0biApIHtcblx0XHR0aGlzLnNhdmVBbmROZXdWYWxpZGF0ZSggY29udGV4dF9idG4sIHRoaXMuZ2V0UHVuY2hQZXJtaXNzaW9uVHlwZSgpICk7XG5cblx0XHRpZiAoIHRoaXMuaXNfdmlld2luZyB8fCB0aGlzLmlzX21hc3NfZWRpdGluZyApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fVxuXHR9XG5cblx0c2V0RGVmYXVsdE1lbnVNYXBJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKSB7XG5cdFx0c3VwZXIuc2V0RGVmYXVsdE1lbnVNYXBJY29uKCBjb250ZXh0X2J0biApO1xuXG5cdFx0aWYgKCBjb250ZXh0X2J0bi5kaXNhYmxlZCA9PSB0cnVlICkge1xuXHRcdFx0aWYgKCB0aGlzLmFic2VuY2VfbW9kZWwgfHwgdGhpcy5nZXRQdW5jaE1vZGUoKSA9PSAnbWFudWFsJyApIHtcblx0XHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRzZXRFZGl0TWVudVNhdmVBbmROZXh0SWNvbiggY29udGV4dF9idG4gKSB7XG5cdFx0aWYgKCAhdGhpcy5lZGl0UGVybWlzc2lvblZhbGlkYXRlKCB0aGlzLmdldFB1bmNoUGVybWlzc2lvblR5cGUoKSApIHx8IHRoaXMuZWRpdF9vbmx5X21vZGUgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApXG5cdFx0fVxuXG5cdFx0aWYgKCAoICF0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgfHwgIXRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCApIHx8IHRoaXMuaXNfdmlld2luZyB8fCB0aGlzLmlzX21hc3NfYWRkaW5nICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRzZXRFZGl0TWVudVNhdmVBbmRDb3B5SWNvbiggY29udGV4dF9idG4gKSB7XG5cdFx0dGhpcy5zYXZlQW5kTmV3VmFsaWRhdGUoIGNvbnRleHRfYnRuLCB0aGlzLmdldFB1bmNoUGVybWlzc2lvblR5cGUoKSApO1xuXG5cdFx0aWYgKCB0aGlzLmlzX3ZpZXdpbmcgfHwgdGhpcy5pc19tYXNzX2VkaXRpbmcgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHRcdH1cblx0fVxuXG5cdHNldEVkaXRNZW51Q29weUFuZEFkZEljb24oIGNvbnRleHRfYnRuICkge1xuXHRcdGlmICggIXRoaXMuYWRkUGVybWlzc2lvblZhbGlkYXRlKCB0aGlzLmdldFB1bmNoUGVybWlzc2lvblR5cGUoKSApICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdH1cblxuXHRcdGlmICggKCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkIHx8ICF0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgKSB8fCB0aGlzLmlzX3ZpZXdpbmcgfHwgdGhpcy5pc19tYXNzX2FkZGluZyApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fVxuXHR9XG5cblxuXHRzZXRDdXN0b21FZGl0TWVudUljb24oIGlkLCBjb250ZXh0X2J0biApIHtcblx0XHRzd2l0Y2ggKCBpZCApIHtcblx0XHRcdGNhc2UgJ2FkZCc6XG5cdFx0XHRjYXNlICdhZGRfcHVuY2gnOlxuXHRcdFx0XHR0aGlzLnNldEVkaXRNZW51QWRkSWNvbiggY29udGV4dF9idG4gKTtcblx0XHRcdFx0aWYgKCB0aGlzLmdldFB1bmNoUGVybWlzc2lvblR5cGUoKSA9PT0gJ3B1bmNoJyApIHtcblx0XHRcdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuYWN0aXZhdGVTcGxpdEJ1dHRvbkl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ2FkZF9hYnNlbmNlJzpcblx0XHRcdFx0dGhpcy5zZXRFZGl0TWVudUFkZEljb24oIGNvbnRleHRfYnRuICk7XG5cdFx0XHRcdGlmICggdGhpcy5nZXRQdW5jaFBlcm1pc3Npb25UeXBlKCkgPT09ICdhYnNlbmNlJyApIHtcblx0XHRcdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuYWN0aXZhdGVTcGxpdEJ1dHRvbkl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3ZpZXcnOlxuXHRcdFx0XHR0aGlzLnNldEVkaXRNZW51Vmlld0ljb24oIGNvbnRleHRfYnRuICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnaW5fb3V0Jzpcblx0XHRcdFx0dGhpcy5zZXRFZGl0TWVudUluT3V0SWNvbiggY29udGV4dF9idG4gKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdkcmFnX2NvcHknOlxuXHRcdFx0XHR0aGlzLnNldEVkaXRNZW51RHJhZ0NvcHlJY29uKCBjb250ZXh0X2J0biApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ21vdmUnOlxuXHRcdFx0XHRpZiAoICF0aGlzLm1vdmVQZXJtaXNzaW9uVmFsaWRhdGUoIHRoaXMuZ2V0UHVuY2hQZXJtaXNzaW9uVHlwZSgpICkgKSB7XG5cdFx0XHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdFx0XHR9XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnYWNjdW11bGF0ZWRfdGltZSc6XG5cdFx0XHRcdHRoaXMuc2V0RGVmYXVsdE1lbnVBY2N1bXVsYXRlZFRpbWVJY29uKCBjb250ZXh0X2J0biApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ2V4cG9ydF9leGNlbCc6XG5cdFx0XHRcdHRoaXMuc2V0RGVmYXVsdE1lbnVFeHBvcnRJY29uKCBjb250ZXh0X2J0biApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ2VkaXRfZW1wbG95ZWUnOlxuXHRcdFx0XHR0aGlzLnNldERlZmF1bHRNZW51RWRpdEVtcGxveWVlSWNvbiggY29udGV4dF9idG4gKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdlZGl0X3BheV9wZXJpb2QnOlxuXHRcdFx0XHR0aGlzLnNldERlZmF1bHRNZW51RWRpdFBheVBlcmlvZEljb24oIGNvbnRleHRfYnRuICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAncmVfY2FsY3VsYXRlX3RpbWVzaGVldCc6XG5cdFx0XHRcdHRoaXMuc2V0RGVmYXVsdE1lbnVSZUNhbGN1bGF0ZVRpbWVzaGVldCggY29udGV4dF9idG4gKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdnZW5lcmF0ZV9wYXlfc3R1Yic6XG5cdFx0XHRcdHRoaXMuc2V0RGVmYXVsdE1lbnVHZW5lcmF0ZVBheVN0dWJJY29uKCBjb250ZXh0X2J0biApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ0FkZFJlcXVlc3QnOlxuXHRcdFx0XHR0aGlzLnNldEFkZFJlcXVlc3RJY29uKCBjb250ZXh0X2J0biApO1xuXHRcdFx0XHRicmVhaztcblx0XHR9XG5cdH1cblxuXHRlbmFibGVBZGRSZXF1ZXN0QnV0dG9uKCkge1xuXHRcdHZhciBncmlkX3NlbGVjdGVkX2lkX2FycmF5ID0gdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXk7XG5cdFx0dmFyIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoID0gZ3JpZF9zZWxlY3RlZF9pZF9hcnJheS5sZW5ndGg7XG5cblx0XHRpZiAoIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoID09IDEgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0Y2xlYW5XaGVuVW5sb2FkVmlldyggY2FsbEJhY2sgKSB7XG5cdFx0VFRWdWVVdGlscy51bm1vdW50Q29tcG9uZW50KCB0aGlzLnZ1ZV9jb250cm9sX2Jhcl9pZCApO1xuXHRcdCQoICcjdGltZXNoZWV0X3ZpZXdfY29udGFpbmVyJyApLnJlbW92ZSgpO1xuXHRcdHN1cGVyLmNsZWFuV2hlblVubG9hZFZpZXcoIGNhbGxCYWNrICk7XG5cdH1cblxuXHRzZXRBZGRSZXF1ZXN0SWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICkge1xuXHRcdGlmICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPD0gMTAgfHwgIXRoaXMuYWRkUGVybWlzc2lvblZhbGlkYXRlKCAncmVxdWVzdCcgKSB8fCB0aGlzLmVkaXRfb25seV9tb2RlICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdH1cblxuXHRcdGlmICggdGhpcy5lbmFibGVBZGRSZXF1ZXN0QnV0dG9uKCkgPT09IHRydWUgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCB0cnVlICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fVxuXHR9XG5cblx0dXNlclZhbHVlU2V0KCB2YWwgKSB7XG5cdFx0Ly9JZiB0aGUgdmFsdWUgaGVyZSBpcyBudWxsLCB0aGUgdGltZXNoZWV0IGRhdGEgd2lsbCBiZSBtaXNzaW5nIHRoZXJlZm9yZSB3ZSB3YW50IHRvIGZvcmNlIHRoZSB2YWx1ZSB0byB0aGUgY3VycmVudGx5IGxvZ2dlZCBpbiB1c2VyLlxuXHRcdC8vTW9zdGx5IGNhdXNlZCB3aGVuIGRldmVsb3BlcnMgc3dpdGNoIGluc3RhbmNlcyBvciBkYXRhYmFzZXMgZHVyaW5nIHRlc3RpbmcuXG5cdFx0aWYgKCB0eXBlb2YgdmFsID09ICd1bmRlZmluZWQnICkge1xuXHRcdFx0dGhpcy5lbXBsb3llZV9uYXYuc2V0VmFsdWUoIExvY2FsQ2FjaGVEYXRhLmdldExvZ2luVXNlcigpICk7XG5cdFx0XHREZWJ1Zy5UZXh0KCAnRVJST1I6IEludmFsaWQgVXNlciBJRCBpbiBVUkwuIFN3aXRjaGluZyB0byBjdXJyZW50IFVzZXIgSUQuJywgJ1RpbWVzaGVldFZpZXdDb25yb2xsZXIuanMnLCAnVGltZXNoZWV0Vmlld0NvbnJvbGxlcicsICd1c2VyVmFsdWVTZXQnLCAxMCApO1xuXHRcdH1cblx0fVxuXG5cdC8vIEdldCBhdmFpbGFibGUgYWNjcnVhbCBiYWxhbmNlIGZvciBjdXJyZW50bHkgc2VsZWN0ZWQgYWJzZW5jZSBwb2xpY3kgdHlwZSBhbmQgaW5zZXJ0IGludG8gdGhlIHRpbWUgZmllbGQuXG5cdHJlbGVhc2VCYWxhbmNlKCBiYWxhbmNlICkge1xuXG5cdFx0Ly9CYWxhbmNlIGNvdWxkIGJlIHBvc2l0aXZlIG9yIG5lZ2F0aXZlLlxuXHRcdC8vSWYgdGhlIGJhbGFuY2UgY2FuIGJlIGZ1bGx5IGRpc3BsYXllZCBpbiB0aGUgcHJlZmVycmVkIHRpbWUgdW5pdCwgaXMgdGhhdCBmb3JtYXQuXG5cdFx0Ly9PdGhlcndpc2Ugd2UgbmVlZCB0byByZWxlYXNlIGZyYWN0aW9ucyBvZiBhIG1pbnV0ZSwgc28gZm9yY2UgdGhyb3VnaCBcIkhIOk1NOlNTXCIgYW5kIHdyYXAgaXQgaW4gcXVvdGVzIHNvIGl0IGRvZXNuJ3QgZ2V0IHJvdW5kZWQuXG5cdFx0aWYgKCBHbG9iYWwucGFyc2VUaW1lVW5pdCggR2xvYmFsLmdldFRpbWVVbml0KCBiYWxhbmNlICkgKSA9PSBiYWxhbmNlICkge1xuXHRcdFx0dGhpcy5lZGl0X3ZpZXdfdWlfZGljWyd0b3RhbF90aW1lJ10uc2V0VmFsdWUoIEdsb2JhbC5nZXRUaW1lVW5pdCggYmFsYW5jZSApICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuZWRpdF92aWV3X3VpX2RpY1sndG90YWxfdGltZSddLnNldFZhbHVlKCAnXCInICsgR2xvYmFsLmdldFRpbWVVbml0KCBiYWxhbmNlLCAxMiApICsgJ1wiJyApOyAvLzEyPVwiSEg6TU06U1NcIlxuXHRcdH1cblxuXHRcdC8vIFRyaWdnZXIgZmllbGQgb25Gb3JtQ2hhbmdlIHRvIHVwZGF0ZSBhdmFpbGFibGUgYmFsYW5jZSBmaWVsZCBhbmQgb3RoZXIgZGF0YS5cblx0XHR0aGlzLmVkaXRfdmlld191aV9kaWNbJ3RvdGFsX3RpbWUnXS50cmlnZ2VyKCAnY2hhbmdlJyApO1xuXHR9XG5cblx0bWVyZ2VKb2JRdWV1ZUludG9UaW1lU2hlZXREYXRhKCB0aW1lc2hlZXRfZGF0YSApIHtcblx0XHQvL0NoZWNrIGxvY2FsbHkgaWYgdGhlcmUgaXMgYSBxdWV1ZWQgam9iIHF1ZXVlIHB1bmNoIHdpdGhpbiB0aGUgbGFzdCAxNSBtaW51dGVzICg5MDAgc2Vjb25kcykuXG5cdFx0aWYgKCBMb2NhbENhY2hlRGF0YS5nZXRKb2JRdWV1ZVB1bmNoRGF0YSgpICYmIExvY2FsQ2FjaGVEYXRhLmdldEpvYlF1ZXVlUHVuY2hEYXRhKCkudXNlcl9pZCA9PT0gdGhpcy5nZXRTZWxlY3RFbXBsb3llZSgpICYmICggKCBuZXcgRGF0ZSgpLmdldFRpbWUoKSAvIDEwMDAgKSAtIExvY2FsQ2FjaGVEYXRhLmdldEpvYlF1ZXVlUHVuY2hEYXRhKCkuZXBvY2ggKSA8ICggNjAgKiAxNSApICkge1xuXHRcdFx0Ly9DaGVjayBpZiBwdW5jaCBpcyBkdXBsaWNhdGUgYW5kIGFscmVheHkgZXhpc3RzLlxuXHRcdFx0bGV0IGlzX3B1bmNoX2V4aXN0ID0gZmFsc2U7XG5cdFx0XHRmb3IoIGxldCBpID0gMDsgaSA8IHRpbWVzaGVldF9kYXRhLnB1bmNoX2RhdGEubGVuZ3RoOyBpKysgKSB7XG5cdFx0XHRcdGlmKCB0aW1lc2hlZXRfZGF0YS5wdW5jaF9kYXRhW2ldLmFjdHVhbF90aW1lX3N0YW1wID09IExvY2FsQ2FjaGVEYXRhLmdldEpvYlF1ZXVlUHVuY2hEYXRhKCkuYWN0dWFsX3RpbWVfc3RhbXBcblx0XHRcdFx0XHQmJiB0aW1lc2hlZXRfZGF0YS5wdW5jaF9kYXRhW2ldLnN0YXR1c19pZCA9PSBMb2NhbENhY2hlRGF0YS5nZXRKb2JRdWV1ZVB1bmNoRGF0YSgpLnN0YXR1c19pZFxuXHRcdFx0XHRcdCYmIHRpbWVzaGVldF9kYXRhLnB1bmNoX2RhdGFbaV0udHlwZV9pZCA9PSBMb2NhbENhY2hlRGF0YS5nZXRKb2JRdWV1ZVB1bmNoRGF0YSgpLnR5cGVfaWRcblx0XHRcdFx0KSB7XG5cdFx0XHRcdFx0aXNfcHVuY2hfZXhpc3QgPSB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmICggaXNfcHVuY2hfZXhpc3QgPT09IHRydWUgKSB7XG5cdFx0XHRcdC8vUHVuY2ggYWxyZWFkeSBleGlzdHMsIHJlbW92ZSBkdXBsaWNhdGUuXG5cdFx0XHRcdExvY2FsQ2FjaGVEYXRhLnNldEpvYlF1ZXVlUHVuY2hEYXRhKCBudWxsICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aW1lc2hlZXRfZGF0YS5wdW5jaF9kYXRhLnB1c2goIExvY2FsQ2FjaGVEYXRhLmdldEpvYlF1ZXVlUHVuY2hEYXRhKCkgKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGltZXNoZWV0X2RhdGE7XG5cdH1cblxuXHRnZXRUaW1lU2hlZXRXaWR0aCgpIHtcblx0XHRsZXQgc2Nyb2xsX2FkanVzdG1lbnQgPSBHbG9iYWwuaXNWZXJ0aWNhbFNjcm9sbEJhclJlcXVpcmVkKCAkKCcudGltZXNoZWV0LWdyaWQtZGl2JylbMF0gKSA/IEdsb2JhbC5nZXRTY3JvbGxiYXJXaWR0aCgpIDogMDtcblx0XHRyZXR1cm4gKCAkKCAnLmNvbnRleHQtYm9yZGVyJyApLndpZHRoKCkgLSBzY3JvbGxfYWRqdXN0bWVudCApO1xuXHR9XG59XG5cblRpbWVTaGVldFZpZXdDb250cm9sbGVyLlBVTkNIX1JPVyA9IDE7XG5UaW1lU2hlZXRWaWV3Q29udHJvbGxlci5FWENFUFRJT05fUk9XID0gMjtcblRpbWVTaGVldFZpZXdDb250cm9sbGVyLlJFUVVFU1RfUk9XID0gMztcblRpbWVTaGVldFZpZXdDb250cm9sbGVyLlRPVEFMX1JPVyA9IDQ7XG5UaW1lU2hlZXRWaWV3Q29udHJvbGxlci5SRUdVTEFSX1JPVyA9IDU7XG5UaW1lU2hlZXRWaWV3Q29udHJvbGxlci5BQlNFTkNFX1JPVyA9IDY7XG5UaW1lU2hlZXRWaWV3Q29udHJvbGxlci5BQ0NVTVVMQVRFRF9USU1FX1JPVyA9IDc7XG5UaW1lU2hlZXRWaWV3Q29udHJvbGxlci5QUkVNSVVNX1JPVyA9IDg7XG5cblRpbWVTaGVldFZpZXdDb250cm9sbGVyLmh0bWxfdGVtcGxhdGUgPSBgXG5cdDxkaXYgY2xhc3M9XCJ2aWV3IHRpbWUtc2hlZXQtdmlld1wiIGlkPVwidGltZXNoZWV0X3ZpZXdfY29udGFpbmVyXCI+XG5cdFx0PGRpdiBjbGFzcz1cImNsZWFyLWJvdGgtZGl2XCI+PC9kaXY+XG5cdFx0PGRpdiBjbGFzcz1cImNvbnRyb2wtYmFyXCI+XG5cdFx0XHQ8ZGl2IGlkPVwidnVlLXRpbWVzaGVldC1jb250cm9sLWJhclwiPjwvZGl2PlxuXHRcdDwvZGl2PlxuXHRcdDxkaXYgY2xhc3M9XCJjbGVhci1ib3RoLWRpdlwiPjwvZGl2PlxuXHRcdDxkaXYgY2xhc3M9XCJncmlkLXRvcC1ib3JkZXJcIj48L2Rpdj5cblx0XHQ8ZGl2IGNsYXNzPVwidGltZXNoZWV0LWdyaWQtZGl2XCI+XG5cdFx0XHQ8ZGl2IGNsYXNzPVwidGltZXNoZWV0LXB1bmNoLWdyaWQtd3JhcHBlclwiPlxuXHRcdFx0XHQ8dGFibGUgaWQ9XCJncmlkXCIgY2xhc3M9XCJ0aW1lc2hlZXQtZ3JpZFwiPjwvdGFibGU+XG5cdFx0XHQ8L2Rpdj5cblx0XHRcdDxkaXYgY2xhc3M9XCJpbnNpZGUtZWRpdG9yLWRpdiBtYW51YWwtdGltZXNoZWV0LWluc2lkZS1lZGl0b3ItZGl2XCI+PC9kaXY+XG5cdFx0XHQ8dGFibGUgY2xhc3M9XCJhY2N1bXVsYXRlZC10aW1lLWdyaWQgc3ViLWdyaWRcIiBpZD1cImFjY3VtdWxhdGVkX3RpbWVfZ3JpZFwiPjwvdGFibGU+XG5cdFx0XHQ8dGFibGUgY2xhc3M9XCIgc3ViLWdyaWRcIiBpZD1cImJyYW5jaF9ncmlkXCI+PC90YWJsZT5cblx0XHRcdDx0YWJsZSBjbGFzcz1cIiBzdWItZ3JpZFwiIGlkPVwiZGVwYXJ0bWVudF9ncmlkXCI+PC90YWJsZT5cblx0XHRcdDx0YWJsZSBjbGFzcz1cIiBzdWItZ3JpZFwiIGlkPVwiam9iX2dyaWRcIj48L3RhYmxlPlxuXHRcdFx0PHRhYmxlIGNsYXNzPVwiIHN1Yi1ncmlkXCIgaWQ9XCJqb2JfaXRlbV9ncmlkXCI+PC90YWJsZT5cblx0XHRcdDx0YWJsZSBjbGFzcz1cIiBzdWItZ3JpZFwiIGlkPVwicHJlbWl1bV9ncmlkXCI+PC90YWJsZT5cblx0XHRcdDx0YWJsZSBjbGFzcz1cIiBzdWItZ3JpZFwiIGlkPVwiYWJzZW5jZV9ncmlkXCI+PC90YWJsZT5cblx0XHRcdDx0YWJsZSBjbGFzcz1cInRvdGFsX2dyaWRzX2RpdlwiIGlkPVwidG90YWxfZ3JpZHNfdGFibGVcIj5cblx0XHRcdFx0PHRyIHN0eWxlPVwidmVydGljYWwtYWxpZ246dG9wO1wiPlxuXHRcdFx0XHRcdDx0ZD5cblx0XHRcdFx0XHRcdDxkaXYgY2xhc3M9XCJhY2N1bXVsYXRlZC10b3RhbC1ncmlkLXRpdGxlXCIgc3R5bGU9XCJkaXNwbGF5OiBub25lXCI+PCU9YWNjdW11bGF0ZWRfdGltZSU+PC9kaXY+XG5cdFx0XHRcdFx0XHQ8dGFibGUgaWQ9XCJhY2N1bXVsYXRlZF90b3RhbF9ncmlkXCI+PC90YWJsZT5cblx0XHRcdFx0XHQ8L3RkPlxuXHRcdFx0XHRcdDx0ZCBjbGFzcz1cIm5vdGVzX2dyaWRfdGRfY29udGFpbmVyXCI+XG5cdFx0XHRcdFx0XHQ8dGFibGUgaWQ9XCJwdW5jaF9ub3RlX2dyaWRcIiBjbGFzcz1cImZsb2F0LXJpZ2h0XCI+PC90YWJsZT5cblx0XHRcdFx0XHQ8L3RkPlxuXHRcdFx0XHRcdDx0ZD5cblx0XHRcdFx0XHRcdDxkaXYgY2xhc3M9XCJ2ZXJpZmljYXRpb24tZ3JpZC1kaXZcIj5cblx0XHRcdFx0XHRcdFx0PGRpdiBjbGFzcz1cInZlcmlmaWNhdGlvbi1ncmlkLXRpdGxlXCIgc3R5bGU9XCJkaXNwbGF5OiBub25lXCI+PCU9dGltZXNoZWV0X3ZlcmlmaWNhdGlvbiU+PC9kaXY+XG5cdFx0XHRcdFx0XHRcdDx0YWJsZSBpZD1cInZlcmlmaWNhdGlvbl9ncmlkXCIgY2xhc3M9XCJmbG9hdC1yaWdodFwiPjwvdGFibGU+XG5cdFx0XHRcdFx0XHRcdDxkaXYgY2xhc3M9XCJ2ZXJpZmljYXRpb24tYWN0aW9uLWJhclwiPlxuXHRcdFx0XHRcdFx0XHRcdDxzcGFuIGNsYXNzPVwidmVyaWZ5LWRlc2NyaXB0aW9uXCI+PC9zcGFuPlxuXHRcdFx0XHRcdFx0XHRcdDxidXR0b24gY2xhc3M9XCJ2ZXJpZnktYnV0dG9uIHQtYnV0dG9uXCIgc3R5bGU9XCJkaXNwbGF5OiBub25lXCI+PCU9dmVyaWZ5JT48L2J1dHRvbj5cblx0XHRcdFx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0XHQ8L3RkPlxuXHRcdFx0XHQ8L3RyPlxuXHRcdFx0PC90YWJsZT5cblx0XHQ8L2Rpdj5cblx0XHQ8ZGl2IGNsYXNzPVwiYm90dG9tLWRpdlwiPlxuXHRcdFx0PGRpdiBjbGFzcz1cImdyaWQtYm90dG9tLWJvcmRlclwiPjwvZGl2PlxuXHRcdDwvZGl2PlxuXHQ8L2Rpdj5cbmA7Il0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///2693\n")}}]);
|