1 line
764 KiB
JavaScript
1 line
764 KiB
JavaScript
"use strict";(self.webpackChunktimetrex=self.webpackChunktimetrex||[]).push([["attendance-schedule-ScheduleViewController"],{6478:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{eval("// ESM COMPAT FLAG\n__webpack_require__.r(__webpack_exports__);\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n \"ScheduleViewController\": () => (/* binding */ ScheduleViewController)\n});\n\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/schedule/ScheduleControlBar.vue?vue&type=template&id=4f970b96&scoped=true\n\n\nconst _withScopeId = n => ((0,vue_esm_bundler/* pushScopeId */.dD)(\"data-v-4f970b96\"),n=n(),(0,vue_esm_bundler/* popScopeId */.Cn)(),n)\nconst _hoisted_1 = { class: \"tt-horizontal-vue-bar\" }\nconst _hoisted_2 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/(0,vue_esm_bundler/* createElementVNode */._)(\"div\", { class: \"bar-column left\" }, null, -1 /* HOISTED */))\nconst _hoisted_3 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/(0,vue_esm_bundler/* createElementVNode */._)(\"div\", { class: \"bar-column center\" }, [\n /*#__PURE__*/(0,vue_esm_bundler/* createElementVNode */._)(\"div\", { class: \"date-chooser-div\" })\n], -1 /* HOISTED */))\nconst _hoisted_4 = { class: \"bar-column right\" }\nconst _hoisted_5 = { class: \"bar-column schedule-mode\" }\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 _hoisted_3,\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.schedule_mode_options_selected,\n \"onUpdate:modelValue\": _cache[0] || (_cache[0] = $event => (($data.schedule_mode_options_selected) = $event)),\n options: $props.schedule_mode_options,\n optionLabel: \"label\",\n optionValue: \"value\",\n onClick: _cache[1] || (_cache[1] = $event => {this.onScheduleModeChange();})\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: $props.schedule_settings_options\n }, null, 8 /* PROPS */, [\"items\"])\n ])\n ])\n ]))\n}\n;// CONCATENATED MODULE: ./interface/html5/components/schedule/ScheduleControlBar.vue?vue&type=template&id=4f970b96&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/schedule/ScheduleControlBar.vue?vue&type=script&lang=js\n\n\n\n\n/* harmony default export */ const ScheduleControlBarvue_type_script_lang_js = ({\n name: \"ScheduleControlBar\",\n created() {\n this.event_bus = new TTEventBus( {\n component_id: this.component_id\n } );\n this.event_bus.on( this.component_id, 'getValue', this.getValue, TTEventBusStatics.AUTO_CLEAR_ON_EXIT );\n this.event_bus.on( this.component_id, 'setValue', this.setValue, TTEventBusStatics.AUTO_CLEAR_ON_EXIT );\n this.event_bus.on( this.component_id, 'setScheduleSettingsState', this.setScheduleSettingsState, TTEventBusStatics.AUTO_CLEAR_ON_EXIT );\n this.event_bus.on( this.component_id, 'setSettingActive', this.setSettingActive, TTEventBusStatics.AUTO_CLEAR_ON_EXIT );\n this.event_bus.on( this.component_id, 'setSettingDeactivated', this.setSettingDeactivated, TTEventBusStatics.AUTO_CLEAR_ON_EXIT );\n },\n unmounted() {\n Debug.Text( 'Vue control bar component unmounted ('+ this.component_id +').', 'ScheduleControlBar.vue', 'ScheduleControlBar', 'unmounted', 2 );\n this.event_bus.autoClear();\n },\n props: { // passed in via root props from TimeSheetViewController\n view_id: {\n type: String,\n default: null\n },\n component_id: { /* Note: This is passed in via TTVueUtils.mountComponent param, and auto added to root_props. */\n type: String,\n default: null\n },\n schedule_mode_options: {\n type: Array,\n default: []\n },\n schedule_settings_options: {\n type: Array,\n default: []\n },\n },\n data() {\n return {\n removeEventsOnUnmount: [],\n schedule_mode_options_selected: 'week',\n }\n },\n // watch: {\n // schedule_mode_options_selected: function ( val ) {\n // this.event_bus.emit( this.component_id, 'scheduleModeOnChange', {\n // key: 'schedule_mode_options_selected',\n // value: val\n // });\n // },\n // },\n computed: {\n },\n methods: {\n // getValue( event_data ) {\n // // Validate\n // if ( event_data.key && ['schedule_mode_options_selected'].includes( event_data.key) ) {\n // EventBus.emit( this.vue_control_bar_id +'.getValueReturn', {\n // key: event_data.key,\n // value: this[ event_data.key ]\n // });\n // return this[ event_data.key ];\n // } else if ( event_data.key && ['all_employee_btn', 'daily_totals_btn', 'weekly_totals_btn', 'strict_range_btn'].includes( event_data.key) ) {\n //\n // } else {\n // // invalid\n // }\n // },\n setValue( event_data ) {\n var valid_editable_fields = ['schedule_mode_options_selected'];\n // Validate\n if( event_data.key && event_data.key && valid_editable_fields.includes( event_data.key) ) {\n this[ event_data.key ] = event_data.value;\n } else {\n // invalid\n Debug.Error( 'Invalid parameters passed to function.', 'ScheduleControlBar.vue', 'ScheduleControlBar', 'setValue', 1 );\n\n }\n },\n getScheduleSettingsState( item_id ) {\n var item = this.schedule_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.', 'ScheduleControlBar.vue', 'ScheduleControlBar', 'getScheduleSettingsState', 1 );\n return undefined;\n }\n },\n setScheduleSettingsState( event_data ) {\n var item = this.schedule_settings_options.find( element => element.id === event_data.item_id );\n if( item ) {\n item[ event_data.item_field ] = event_data.item_value;\n } else {\n Debug.Error( 'Item not found ('+ event_data.item_id +'). Check supplied id.', 'ScheduleControlBar.vue', 'ScheduleControlBar', 'setScheduleSettingsState', 1 );\n }\n },\n setSettingActive( event_data ) {\n var item = this.schedule_settings_options.find( element => element.id === event_data.item_id );\n if( item ) {\n item.setOnlySelfActive();\n } else {\n Debug.Error( 'Item not found ('+ event_data.item_id +'). Check supplied id.', 'ScheduleControlBar.vue', 'ScheduleControlBar', 'setSettingActive', 1 );\n }\n },\n setSettingDeactivated( event_data ) {\n var item = this.schedule_settings_options.find( element => element.id === event_data.item_id );\n if( item ) {\n item.setOnlySelfDeactivated();\n } else {\n Debug.Error( 'Item not found ('+ event_data.item_id +'). Check supplied id.', 'ScheduleControlBar.vue', 'ScheduleControlBar', 'setOnlySelfDeactivated', 1 );\n }\n },\n onScheduleModeChange() {\n this.event_bus.emit( this.component_id, 'scheduleModeOnChange', {\n key: 'schedule_mode_options_selected',\n value: this.schedule_mode_options_selected\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/schedule/ScheduleControlBar.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/schedule/ScheduleControlBar.vue\n\n\n\n\n;\n\n\nconst __exports__ = /*#__PURE__*/(0,exportHelper/* default */.Z)(ScheduleControlBarvue_type_script_lang_js, [['render',render],['__scopeId',\"data-v-4f970b96\"]])\n\n/* harmony default export */ const ScheduleControlBar = (__exports__);\n;// CONCATENATED MODULE: ./interface/html5/views/attendance/schedule/ScheduleViewController.js\n/* provided dependency */ var _ = __webpack_require__(9050);\n/* provided dependency */ var $ = __webpack_require__(9755);\n\n\n\nclass ScheduleViewController extends BaseViewController {\n\tconstructor( options = {} ) {\n\t\t_.defaults( options, {\n\t\t\tel: '#schedule_view_container', //Must set el here and can only set string, so events can work\n\n\n\n\t\t\tuser_group_api: null,\n\n\t\t\tstatus_array: null,\n\n\t\t\tuser_group_array: null,\n\n\t\t\ttoggle_button: null,\n\n\t\t\tstart_date_picker: null,\n\n\t\t\tstart_date: null,\n\n\t\t\tend_date: null,\n\n\t\t\tfull_schedule_data: null,\n\n\t\t\tschedule_columns: null,\n\n\t\t\tfull_format: 'ddd-MMM-DD-YYYY',\n\n\t\t\tweekly_format: 'ddd, MMM DD',\n\n\t\t\tfinal_schedule_data_array: [],\n\n\t\t\thas_date_array: [],\n\n\t\t\tno_date_array: [],\n\n\t\t\tshift_key_name_array: [],\n\n\t\t\tselect_cells_Array: [], //Timesheet grid\n\n\t\t\tselect_all_shifts_array: [], //Timesheet grid.\n\n\t\t\tselect_shifts_array: [], //Timesheet grid.\n\n\t\t\tselect_recurring_shifts_array: [], //Timesheet grid.\n\n\t\t\tall_employee_btn: null,\n\n\t\t\tdaily_totals_btn: null,\n\n\t\t\tweekly_totals_btn: null,\n\n\t\t\tstrict_range_btn: null,\n\n\t\t\tmonth_date_row_array: null,\n\n\t\t\tmonth_date_row_tr_ids: null, // month date tr id in grid table\n\n\t\t\tmonth_date_row_position: null, //month date tr position in table\n\n\t\t\tmonth_current_header_number: 0, //0 is default column header\n\n\t\t\tday_header_width: 0,\n\n\t\t\tday_hour_width: 40,\n\n\t\t\tselect_drag_menu_id: '', //Do drag move or copy\n\n\t\t\tis_override: false,\n\n\t\t\tnotify_user_schedule_change: false,\n\n\t\t\tscroll_position: 0,\n\n\t\t\tselected_user_ids: [],\n\n\t\t\tprev_total_time: 0,\n\n\t\t\tprev_status_id: null,\n\n\t\t\tis_mass_adding: false,\n\n\t\t\tcalculate_cell_number: 0,\n\n\t\t\tscroll_interval: null,\n\n\t\t\tscroll_unit: 0,\n\n\t\t\tholiday_data_dic: {},\n\n\t\t\tabsence_policy_api: null,\n\n\t\t\tjob_api: null,\n\t\t\tjob_item_api: null,\n\t\t\tuser_api: null,\n\t\t\tdepartment_api: null,\n\t\t\tpunch_tag_api: null,\n\t\t\tdefault_punch_tag: [],\n\t\t\tprevious_punch_tag_selection: [],\n\n\t\t\tyear_mode_original_date: null, //set this when search for yer mode with use_date_picker true, so Keep select date in ritict mode\n\t\t\tevents: {},\n\t\t\tvue_control_bar_id: ''\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 = 'schedule';\n\t\tthis.script_name = 'ScheduleView';\n\t\tthis.viewId = 'Schedule';\n\t\tthis.table_name_key = 'schedule';\n\t\tthis.context_menu_name = $.i18n._( 'Schedules' );\n\t\tthis.navigation_label = $.i18n._( 'Schedule' );\n\t\tthis.api = TTAPI.APISchedule;\n\t\tthis.user_group_api = TTAPI.APIUserGroup;\n\t\tthis.absence_policy_api = TTAPI.APIAbsencePolicy;\n\t\tthis.company_api = TTAPI.APICompany;\n\t\tthis.user_api = TTAPI.APIUser;\n\t\tthis.currency_api = TTAPI.APICurrency;\n\t\tthis.event_bus = new TTEventBus({ view_id: this.viewId });\n\n\n\t\tif ( Global.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\n\t\tthis.api_absence_policy = TTAPI.APIAbsencePolicy;\n\n\t\tthis.scroll_position = 0;\n\n\t\tthis.initPermission();\n\t\tthis.render();\n\t\tthis.buildContextMenu();\n\n\t\tthis.initData();\n\t}\n\n\tjobUIValidate( p_id ) {\n\n\t\tif ( !p_id ) {\n\t\t\tp_id = this.permission_id;\n\t\t}\n\n\t\tif ( PermissionManager.validate( 'job', 'enabled' ) &&\n\t\t\tPermissionManager.validate( p_id, 'edit_job' ) &&\n\t\t\t( Global.getProductEdition() >= 20 ) ) {\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 = this.permission_id;\n\t\t}\n\n\t\tif ( PermissionManager.validate( 'job_item', 'enabled' ) &&\n\t\t\tPermissionManager.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 = this.permission_id;\n\t\t}\n\n\t\tif ( PermissionManager.validate( 'punch_tag', 'enabled' ) &&\n\t\t\tPermissionManager.validate( p_id, 'edit_job_item' ) ) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tbranchUIValidate( p_id ) {\n\n\t\tif ( !p_id ) {\n\t\t\tp_id = this.permission_id;\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 = this.permission_id;\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\tunscheduledEmployeeUIValidate() {\n\n\t\tif ( PermissionManager.validate( 'schedule', 'view' ) || PermissionManager.validate( 'schedule', 'view_child' ) ) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t//Speical permission check for views, need override\n\tinitPermission() {\n\t\tsuper.initPermission();\n\n\t\tthis.show_search_tab = true;\n\t\t//See buildSearchFields() for additional permission checks.\n\t\t// if ( PermissionManager.validate( this.permission_id, 'view' ) || PermissionManager.validate( this.permission_id, 'view_child' ) ) {\n\t\t// \tthis.show_search_tab = true;\n\t\t// } else {\n\t\t// \tthis.show_search_tab = false;\n\t\t// }\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\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\t}\n\n\t//only be call once when open this view\n\tinitData() {\n\t\tvar $this = this;\n\n\t\t//Remove tab if any\n\t\tGlobal.removeViewTab( this.viewId );\n\t\tProgressBar.showOverlay();\n\t\tthis.initOptions();\n\n\t\t//For regular employees who currently can't see the \"Saved Search and Layout\" tab, try to be smarter about what columns they do see by default.\n\t\tthis.default_display_columns = [];\n\t\tif ( PermissionManager.validate( this.permission_id, 'edit_branch' ) ) {\n\t\t\tthis.default_display_columns.push( 'branch' );\n\t\t}\n\t\tif ( PermissionManager.validate( this.permission_id, 'edit_department' ) ) {\n\t\t\tthis.default_display_columns.push( 'department' );\n\t\t}\n\t\tif ( Global.getProductEdition() >= 20 ) {\n\t\t\tif ( PermissionManager.validate( this.permission_id, 'edit_job' ) ) {\n\t\t\t\tthis.default_display_columns.push( 'job' );\n\t\t\t}\n\t\t\tif ( PermissionManager.validate( this.permission_id, 'edit_job_item' ) ) {\n\t\t\t\tthis.default_display_columns.push( 'job_item' );\n\t\t\t}\n\t\t}\n\n\t\tvar date = new Date();\n\n\t\tif ( Global.UNIT_TEST_MODE == true ) {\n\t\t\tLocalCacheData.last_schedule_selected_date = '15-Feb-18';\n\t\t}\n\n\t\tvar format = Global.getLoginUserDateFormat();\n\t\tvar dateStr = date.format( format );\n\n\t\tif ( !LocalCacheData.last_schedule_selected_date ) {\n\t\t\tif ( LocalCacheData.current_select_date && Global.strToDate( LocalCacheData.current_select_date, 'YYYY-MM-DD' ) ) { //Select date get from URL.\n\t\t\t\tthis.setDatePickerValue( Global.strToDate( LocalCacheData.current_select_date, 'YYYY-MM-DD' ).format() );\n\t\t\t\tLocalCacheData.current_select_date = '';\n\t\t\t} else {\n\t\t\t\tthis.setDatePickerValue( dateStr );\n\t\t\t}\n\t\t} else {\n\t\t\tthis.setDatePickerValue( LocalCacheData.last_schedule_selected_date );\n\t\t}\n\n\t\tthis.setMoveOrDropMode( this.select_drag_menu_id ? this.select_drag_menu_id : 'move' );\n\t\t//Issue #3280 - 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//ScheduleViewController 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.getAllColumns( function() {\n\t\t\t\t$this.initLayout();\n\t\t\t} );\n\t\t} );\n\t}\n\n\tsetToggleButtonValue( val ) {\n\n\t\tif ( this.toggle_button ) {\n\t\t\tthis.toggle_button.setValue( val );\n\n\t\t\tthis.setToggleButtonUrl();\n\t\t}\n\t}\n\n\tsetToggleButtonUrl() {\n\n\t\tvar mode = this.getMode();\n\t\tvar default_date = this.start_date_picker.getDefaultFormatValue();\n\t\tif ( !this.edit_view ) {\n\t\t\tGlobal.setURLToBrowser( Global.getBaseURL() + '#!m=' + this.viewId + '&mode=' + mode );\n\t\t}\n\t}\n\n\tsetDatePickerValue( val ) {\n\n\t\tthis.start_date_picker.setValue( val );\n\n\t\t//this.setDateUrl();\n\n\t\tLocalCacheData.last_schedule_selected_date = val;\n\t}\n\n\tgetAllColumns( callBack ) {\n\n\t\tvar $this = this;\n\t\tthis.api.getOptions( 'columns', {\n\t\t\tonResult: function( columns_result ) {\n\t\t\t\tvar columns_result_data = columns_result.getResult();\n\t\t\t\t$this.all_columns = Global.buildColumnArray( columns_result_data );\n\n\t\t\t\t$this.api.getOptions( 'group_columns', {\n\t\t\t\t\tonResult: function( group_columns_result ) {\n\n\t\t\t\t\t\tvar all_columns = Global.buildColumnArray( columns_result_data );\n\t\t\t\t\t\tvar group_columns_result_data = group_columns_result.getResult();\n\n\t\t\t\t\t\tvar final_all_columns = [];\n\n\t\t\t\t\t\tvar all_len = all_columns.length;\n\t\t\t\t\t\tvar group_len = group_columns_result_data.length;\n\n\t\t\t\t\t\tfor ( var i = 0; i < group_len; i++ ) {\n\t\t\t\t\t\t\tvar group_column_id = group_columns_result_data[i];\n\t\t\t\t\t\t\tfor ( var j = 0; j < all_len; j++ ) {\n\t\t\t\t\t\t\t\tvar column = all_columns[j];\n\t\t\t\t\t\t\t\tif ( column.value === group_column_id ) {\n\t\t\t\t\t\t\t\t\tfinal_all_columns.push( column );\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$this.all_columns = final_all_columns;\n\n\t\t\t\t\t\t$this.column_selector.setUnselectedGridData( $this.all_columns );\n\t\t\t\t\t\tif ( callBack ) {\n\t\t\t\t\t\t\tcallBack();\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\tinitLayout() {\n\t\tvar $this = this;\n\t\t$this.getAllLayouts( function() {\n\t\t\t$this.setSelectLayout();\n\t\t\t$this.search( true, false ); //Make sure we setDefaultMenu is TRUE so autoOpenEditViewIfNecessary() is called.\n\t\t} );\n\t}\n\n\tinitOptions() {\n\t\tvar $this = this;\n\n\t\tthis.initDropDownOption( 'status', '', this.api );\n\n\t\tthis.user_group_api.getUserGroup( '', false, false, {\n\t\t\tonResult: function( res ) {\n\t\t\t\tres = res.getResult();\n\n\t\t\t\tres = Global.buildTreeRecord( res );\n\t\t\t\t$this.user_group_array = res;\n\n\t\t\t\tif ( $this.basic_search_field_ui_dic['group_ids'] ) {\n\t\t\t\t\t$this.basic_search_field_ui_dic['group_ids'].setSourceData( res );\n\t\t\t\t}\n\t\t\t\tif ( $this.adv_search_field_ui_dic['group_ids'] ) {\n\t\t\t\t\t$this.adv_search_field_ui_dic['group_ids'].setSourceData( res );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\tgetSelectDate() {\n\t\tvar retval = this.start_date_picker.getValue();\n\n\t\tif ( retval == 'Invalid date' ) {\n\t\t\tretval = new Date();\n\t\t}\n\n\t\treturn retval;\n\t}\n\n\tgetGridSelectIdArray() {\n\n\t\tvar result = [];\n\t\tvar len = this.select_all_shifts_array.length;\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar item = this.select_all_shifts_array[i];\n\t\t\tif ( item.id && item.id != TTUUID.zero_id && item.id != TTUUID.not_exist_id ) {\n\t\t\t\tresult.push( item.id );\n\t\t\t}\n\n\t\t}\n\n\t\treturn result;\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_all_shifts_array.length > 0 ) {\n\t\t\t\tselected_item = this.select_all_shifts_array[0];\n\t\t\t}\n\n\t\t}\n\n\t\tif ( selected_item ) {\n\t\t\treturn Global.clone( selected_item );\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t_continueDoCopyAsNew() {\n\t\tvar $this = this;\n\t\tthis.setCurrentEditViewState( 'new' );\n\t\tLocalCacheData.current_doing_context_action = 'copy_as_new';\n\n\t\tif ( Global.isSet( this.edit_view ) ) {\n\n\t\t\tthis.current_edit_record.id = '';\n\t\t\tvar navigation_div = this.edit_view.find( '.navigation-div' );\n\t\t\tnavigation_div.css( 'display', 'none' );\n\t\t\tthis.setCurrentEditRecordData(); // Reset data to widgets to reset all widgets stat\n\t\t\tthis.setEditMenu();\n\t\t\tthis.setTabStatus();\n\t\t\tthis.is_changed = false;\n\t\t\tProgressBar.closeOverlay();\n\n\t\t} else {\n\n\t\t\tvar filter = {};\n\t\t\tvar grid_selected_id_array = this.getGridSelectIdArray();\n\t\t\tvar grid_selected_length = grid_selected_id_array.length;\n\n\t\t\tif ( grid_selected_length > 0 ) {\n\t\t\t\tvar selectedId = grid_selected_id_array[0];\n\t\t\t} else {\n\t\t\t\tvar select_shift = Global.clone( $this.select_all_shifts_array[0] );\n\t\t\t\tselect_shift = $this.resetSomeFields( select_shift );\n\t\t\t\t$this.current_edit_record = select_shift;\n\t\t\t\t$this.openEditView();\n\t\t\t\t$this.initEditView();\n\t\t\t\treturn;\n\n\t\t\t}\n\n\t\t\tfilter.filter_data = {};\n\t\t\tfilter.filter_data.id = [selectedId];\n\n\t\t\tthis.api['get' + this.api.key_name]( filter, {\n\t\t\t\tonResult: function( result ) {\n\n\t\t\t\t\tvar result_data = result.getResult();\n\n\t\t\t\t\t//#2571 - result_data is undefined (when result_data === true there is no result[0])\n\t\t\t\t\tif ( !result_data || result_data === true ) {\n\t\t\t\t\t\tTAlertManager.showAlert( $.i18n._( 'Record does not exist' ) );\n\t\t\t\t\t\t$this.onCancelClick();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t$this.openEditView(); // Put it here is to avoid if the selected one is not existed in data or have deleted by other pragram. in this case, the edit view should not be opend.\n\n\t\t\t\t\tresult_data = result_data[0];\n\n\t\t\t\t\tresult_data.id = '';\n\n\t\t\t\t\tif ( $this.sub_view_mode && $this.parent_key ) {\n\t\t\t\t\t\tresult_data[$this.parent_key] = $this.parent_value;\n\t\t\t\t\t}\n\n\t\t\t\t\t$this.current_edit_record = result_data;\n\t\t\t\t\t$this.initEditView();\n\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n\n\tonViewClick( record, noRefreshUI ) {\n\t\tthis.setCurrentEditViewState( 'view' );\n\n\t\tvar record_id = this.getViewSelectedRecordId( record );\n\t\tif ( Global.isFalseOrNull( record_id ) ) {\n\t\t\tTTPromise.add( 'Schedule', 'init' );\n\t\t\tthis.openEditView();\n\t\t\tvar select_shift = Global.clone( this.select_all_shifts_array[0] );\n\t\t\tselect_shift = this.resetSomeFields( select_shift );\n\t\t\tthis.current_edit_record = select_shift;\n\n\t\t\tvar $this = this;\n\t\t\tTTPromise.wait( 'Schedule', 'init', function() {\n\t\t\t\t$this.initEditView();\n\t\t\t} );\n\t\t\treturn;\n\t\t}\n\t\tthis.setCurrentSelectedRecord( record_id );\n\n\t\tthis.openEditView();\n\n\t\tvar filter = this.getAPIFilters();\n\n\t\treturn this.doViewAPICall( filter );\n\t}\n\n\tgetCommonFields() {\n\t\tvar baseRecord;\n\t\t$.each( this.select_all_shifts_array, function( index, value ) {\n\t\t\tif ( !baseRecord ) {\n\t\t\t\tbaseRecord = Global.clone( value );\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tfor ( var key in value ) {\n\t\t\t\tbaseRecord[key] !== value[key] && delete baseRecord[key];\n\t\t\t}\n\t\t} );\n\n\t\treturn baseRecord;\n\t}\n\n\tonMassEditClick() {\n\t\tvar $this = this;\n\t\tvar filter = {};\n\t\tvar grid_selected_id_array = [];\n\t\tthis.setCurrentEditViewState( 'mass_edit' );\n\t\tthis.mass_edit_record_ids = [];\n\n\t\tgrid_selected_id_array = this.getGridSelectIdArray();\n\t\t$this.openEditView();\n\n\t\t$.each( grid_selected_id_array, function( index, value ) {\n\t\t\t$this.mass_edit_record_ids.push( value );\n\t\t} );\n\n\t\t$this.selected_user_ids = [];\n\t\t$.each( this.select_all_shifts_array, function( index, value ) {\n\t\t\tvar shift = value;\n\t\t\tif ( shift.hasOwnProperty( 'user_id' ) ) {\n\t\t\t\t$this.selected_user_ids.push( shift.user_id );\n\t\t\t}\n\n\t\t} );\n\n\t\tfilter.filter_data = {};\n\t\tfilter.filter_data.id = this.mass_edit_record_ids;\n\n\t\tif ( this.mass_edit_record_ids.length !== this.select_all_shifts_array.length ) {\n\t\t\tonMassEditResult( this.getCommonFields() );\n\t\t\treturn;\n\t\t}\n\n\t\tthis.api['getCommon' + this.api.key_name + 'Data']( filter, {\n\t\t\tonResult: function( result ) {\n\n\t\t\t\tvar result_data = result.getResult();\n\n\t\t\t\tif ( !result_data ) {\n\t\t\t\t\tresult_data = [];\n\t\t\t\t}\n\t\t\t\tonMassEditResult( result_data );\n\n\t\t\t}\n\t\t} );\n\n\t\tfunction onMassEditResult( result_data ) {\n\t\t\t$this.api['getOptions']( 'unique_columns', {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t$this.unique_columns = result.getResult();\n\t\t\t\t\t$this.api['getOptions']( 'linked_columns', {\n\t\t\t\t\t\tonResult: function( result1 ) {\n\n\t\t\t\t\t\t\t$this.linked_columns = result1.getResult();\n\n\t\t\t\t\t\t\tif ( $this.sub_view_mode && $this.parent_key ) {\n\t\t\t\t\t\t\t\tresult_data[$this.parent_key] = $this.parent_value;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t$this.current_edit_record = result_data;\n\t\t\t\t\t\t\t$this.is_mass_editing = true;\n\t\t\t\t\t\t\t$this.initEditView();\n\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n\n\tonEditClick( record_id, noRefreshUI ) {\n\t\t// #2644: Note: This code fixes a bug where the edit screen is not opened on first try, but is on second. Likely due to the TTPromise and potential race conditions. See commit history for details.\n\t\tTTPromise.add( 'Schedule', 'init' );\n\t\tthis.setCurrentEditViewState( 'edit' );\n\t\tthis.openEditView();\n\n\t\trecord_id = this.getEditSelectedRecordId( record_id );\n\t\tif ( Global.isFalseOrNull( record_id ) ) {\n\t\t\tthis.openEditView();\n\t\t\tvar select_shift = Global.clone( this.select_all_shifts_array[0] );\n\t\t\tselect_shift = this.resetSomeFields( select_shift );\n\t\t\tthis.current_edit_record = select_shift;\n\t\t\tthis.current_edit_record.user_ids = [this.current_edit_record.user_id]; //#2610 - ensure that edit record is properly formed in respect to user_ids\n\t\t\tthis.is_viewing = false;\n\n\t\t\tvar $this = this;\n\t\t\tTTPromise.wait( 'Schedule', 'init', function() {\n\t\t\t\t$this.initEditView();\n\t\t\t} );\n\t\t\treturn;\n\t\t}\n\t\tthis.setCurrentSelectedRecord( record_id );\n\n\t\tvar filter = this.getAPIFilters();\n\n\t\treturn this.doEditAPICall( filter );\n\t}\n\n\tdoDeleteAPICall( remove_ids, callback ) {\n\t\tif ( !callback ) {\n\t\t\tcallback = {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\tProgressBar.closeOverlay();\n\t\t\t\t\tdoNext.call( this, result );\n\t\t\t\t\tif ( result.isValid() ) {\n\t\t\t\t\t\tthis.onDeleteDone( result );\n\t\t\t\t\t\tif ( this.edit_view ) {\n\t\t\t\t\t\t\tthis.removeEditView();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.setCurrentEditViewState( '' );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tTAlertManager.showErrorAlert( result );\n\t\t\t\t\t}\n\t\t\t\t}.bind( this )\n\t\t\t};\n\t\t}\n\t\tif ( remove_ids && remove_ids.length > 0 ) {\n\t\t\treturn this.api['delete' + this.api.key_name]( remove_ids, callback );\n\t\t} else {\n\t\t\tdoNext.call( this, {\n\t\t\t\tisValid: function() {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\tfunction doNext( result ) {\n\t\t\t//Issue #3034 - TypeError: Cannot read properties of undefined (reading 'id').\n\t\t\t//Because deleting recurring schedules does not go through the normal pathway, we need to reset state\n\t\t\t//so that Vue does not decide we on an edit view and retrieve the wrong context menu array.\n\t\t\t//Otherwise JavaScript exceptions may trigger when reading an empty context menu array during other actions.\n\t\t\tif ( this.edit_view ) {\n\t\t\t\tthis.removeEditView();\n\t\t\t} else {\n\t\t\t\tthis.setCurrentEditViewState( '' );\n\t\t\t}\n\n\t\t\t//Since we can't delete recurring schedules, we need to override them as absent without a absence policy instead.\n\t\t\tvar recurring_delete_shifts_array = [];\n\t\t\tfor ( var i = 0; i < this.select_cells_Array.length; i++ ) {\n\t\t\t\tif ( this.select_cells_Array[i].shift ) {\n\t\t\t\t\tthis.select_cells_Array[i].shift.status_id = '20'; //Set shift to absent.\n\t\t\t\t\trecurring_delete_shifts_array.push( this.select_cells_Array[i].shift );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( recurring_delete_shifts_array.length > 0 ) {\n\t\t\t\tthis.api.setSchedule( recurring_delete_shifts_array, {\n\t\t\t\t\tonResult: function() {\n\t\t\t\t\t\tthis.search();\n\t\t\t\t\t}.bind( this )\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\tif ( result.isValid() ) {\n\t\t\t\t\tthis.search();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\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: $.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'save_and_next',\n\t\t\t\t'delete_and_next',\n\t\t\t\t'copy'\n\t\t\t],\n\t\t\tinclude: [\n\t\t\t\t// Note Drag&Drop icons will be conditionally prepended here later in code for list view modes.\n\t\t\t\t{\n\t\t\t\t\tlabel: $.i18n._( 'Jump To' ),\n\t\t\t\t\tid: 'jump_to_header',\n\t\t\t\t\tmenu_align: 'right',\n\t\t\t\t\taction_group: 'jump_to',\n\t\t\t\t\taction_group_header: true,\n\t\t\t\t\tpermission_result: false, // to hide it in legacy context menu and avoid errors in legacy parsers.\n\t\t\t\t\tsort_order: 9030\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: $.i18n._( 'TimeSheet' ),\n\t\t\t\t\tid: 'timesheet',\n\t\t\t\t\tmenu_align: 'right',\n\t\t\t\t\taction_group: 'jump_to',\n\t\t\t\t\tgroup: 'navigation',\n\t\t\t\t\tpermission_result: true,\n\t\t\t\t\tsort_order: 9030\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: $.i18n._( 'Edit Employee' ),\n\t\t\t\t\tid: 'edit_employee',\n\t\t\t\t\tmenu_align: 'right',\n\t\t\t\t\taction_group: 'jump_to',\n\t\t\t\t\tgroup: 'navigation',\n\t\t\t\t\tpermission_result: true,\n\t\t\t\t\tsort_order: 9030\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: $.i18n._( 'Import' ),\n\t\t\t\t\tid: 'import_icon',\n\t\t\t\t\tmenu_align: 'right',\n\t\t\t\t\taction_group: 'import_export',\n\t\t\t\t\tgroup: 'other',\n\t\t\t\t\tvue_icon: 'tticon tticon-file_download_black_24dp',\n\t\t\t\t\tpermission_result: PermissionManager.checkTopLevelPermission( 'ImportCSVSchedule' ),\n\t\t\t\t\tsort_order: 9025\n\t\t\t\t}\n\t\t\t]\n\t\t};\n\n\t\t// Edit Views\n\n\t\tcontext_menu_model.include.push( {\n\t\t\tlabel: $.i18n._( 'Print' ),\n\t\t\tid: 'print',\n\t\t\taction_group_header: true,\n\t\t\taction_group: 'print',\n\t\t\tmenu_align: 'right',\n\t\t\tsort_order: 9020,\n\t\t\t} );\n\n\t\tcontext_menu_model.include.push( {\n\t\t\tlabel: $.i18n._( 'Individual Schedules' ),\n\t\t\tid: 'pdf_schedule',\n\t\t\taction_group: 'print',\n\t\t\tmenu_align: 'right',\n\t\t\tsort_order: 9020\n\t\t} );\n\n\t\tcontext_menu_model.include.push(\n\t\t\t{\n\t\t\t\tlabel: $.i18n._( 'Find Available' ),\n\t\t\t\tid: 'find_available',\n\t\t\t\tvue_icon: 'tticon tticon-search_black_24dp',\n\t\t\t\tmenu_align: 'right',\n\t\t\t\tpermission_result: true,\n\t\t\t\tshow_on_right_click: true,\n\t\t\t\tsort_order: 7000\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: $.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: 7010\n\t\t\t} );\n\t\t}\n\n\t\tif ( !this.is_edit && !this.is_mass_editing && !this.is_viewing ) {\n\t\t\tcontext_menu_model.include.unshift( // Add to begginning of array to preserve item order.\n\t\t\t\t{\n\t\t\t\t\tlabel: $.i18n._( 'Drag & Drop: Move' ),\n\t\t\t\t\tid: 'move',\n\t\t\t\t\taction_group: 'drag_and_drop',\n\t\t\t\t\tmulti_select_group: 1,\n\t\t\t\t\tmenu_align: 'right',\n\t\t\t\t\tgroup: 'drag_and_drop',\n\t\t\t\t\tpermission_result: true,\n\t\t\t\t\tsort_order: 8050\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: $.i18n._( 'Drag & Drop: Copy' ),\n\t\t\t\t\tid: 'drag_copy',\n\t\t\t\t\taction_group: 'drag_and_drop',\n\t\t\t\t\tmenu_align: 'right',\n\t\t\t\t\tmulti_select_group: 1,\n\t\t\t\t\tgroup: 'drag_and_drop',\n\t\t\t\t\tpermission_result: true,\n\t\t\t\t\tsort_order: 8060\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: $.i18n._( 'Drag & Drop: Swap' ),\n\t\t\t\t\tid: 'swap',\n\t\t\t\t\taction_group: 'drag_and_drop',\n\t\t\t\t\tmenu_align: 'right',\n\t\t\t\t\tmulti_select_group: 1,\n\t\t\t\t\tgroup: 'drag_and_drop',\n\t\t\t\t\tpermission_result: true,\n\t\t\t\t\tsort_order: 8070\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'separator_drag_and_drop_1',\n\t\t\t\t\taction_group: 'drag_and_drop',\n\t\t\t\t\tmenu_align: 'right',\n\t\t\t\t\tseparator: true,\n\t\t\t\t\tsort_order: 8080\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: $.i18n._( 'Drag & Drop: Overwrite' ),\n\t\t\t\t\tid: 'override',\n\t\t\t\t\taction_group: 'drag_and_drop',\n\t\t\t\t\tmulti_select_group: 2,\n\t\t\t\t\tmenu_align: 'right',\n\t\t\t\t\tgroup: 'drag_and_drop',\n\t\t\t\t\tpermission_result: true,\n\t\t\t\t\tsort_order: 8090\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif ( Global.getProductEdition() >= 15 ) {\n\t\t\t\tcontext_menu_model.include.unshift(\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: $.i18n._( 'Drag & Drop: Notify Employee' ),\n\t\t\t\t\t\tid: 'notify_user_schedule_change',\n\t\t\t\t\t\taction_group: 'drag_and_drop',\n\t\t\t\t\t\tmulti_select_group: 3,\n\t\t\t\t\t\tmenu_align: 'right',\n\t\t\t\t\t\tgroup: 'drag_and_drop',\n\t\t\t\t\t\tpermission_result: true,\n\t\t\t\t\t\tsort_order: 8100\n\t\t\t\t\t} );\n\t\t\t}\n\n\t\t}\n\n\t\tif ( PermissionManager.validate( 'schedule', 'view' ) || PermissionManager.validate( 'schedule', 'view_child' ) ) {\n\t\t\tcontext_menu_model.include.push(\n\t\t\t\t{\n\t\t\t\t\tlabel: $.i18n._( 'Group - Combined' ),\n\t\t\t\t\tid: 'pdf_schedule_group_combined',\n\t\t\t\t\taction_group: 'print',\n\t\t\t\t\tmenu_align: 'right',\n\t\t\t\t\tsort_order: 9020,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: $.i18n._( 'Group - Separated' ),\n\t\t\t\t\tid: 'pdf_schedule_group',\n\t\t\t\t\taction_group: 'print',\n\t\t\t\t\tmenu_align: 'right',\n\t\t\t\t\tsort_order: 9020,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: $.i18n._( 'Group - Separated (Page Breaks)' ),\n\t\t\t\t\tid: 'pdf_schedule_group_pagebreak',\n\t\t\t\t\taction_group: 'print',\n\t\t\t\t\tmenu_align: 'right',\n\t\t\t\t\tsort_order: 9020,\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\n\t\tcontext_menu_model.include.push(\n\t\t);\n\n\t\tif ( ( PermissionManager.validate( 'punch', 'add' ) && ( PermissionManager.validate( 'punch', 'edit' ) || PermissionManager.validate( 'punch', 'edit_child' ) ) ) ) {\n\t\t\tcontext_menu_model.include.push(\n\t\t\t\t{\n\t\t\t\t\tlabel: '', //Empty label. vue_icon is displayed instead of text.\n\t\t\t\t\tid: 'other_header',\n\t\t\t\t\taction_group: 'other',\n\t\t\t\t\tmenu_align: 'right',\n\t\t\t\t\taction_group_header: true,\n\t\t\t\t\tvue_icon: 'tticon tticon-more_vert_black_24dp',\n\t\t\t\t\tsort_order: 9050\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: $.i18n._( 'Auto Punch' ),\n\t\t\t\t\tid: 'AutoPunch',\n\t\t\t\t\taction_group: 'other',\n\t\t\t\t\tmenu_align: 'right',\n\t\t\t\t\tgroup: 'other',\n\t\t\t\t\tpermission_result: true,\n\t\t\t\t\tpermission: true,\n\t\t\t\t\tshow_on_right_click: true,\n\t\t\t\t\tsort_order: 9050\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'swap',\n\t\t\t\t'override',\n\t\t\t\t'notify_user_schedule_change',\n\t\t\t\t'print',\n\t\t\t\t'pdf_schedule',\n\t\t\t\t'pdf_schedule_group_combined',\n\t\t\t\t'pdf_schedule_group',\n\t\t\t\t'pdf_schedule_group_pagebreak'\n\t\t\t);\n\t\t}\n\n\t\treturn context_menu_model;\n\t}\n\n\tonReportMenuClick( id ) {\n\t\tthis.onNavigationClick( id );\n\t}\n\n\tonCustomContextClick( id ) {\n\t\tswitch ( id ) {\n\t\t\tcase 'move':\n\t\t\tcase 'drag_copy':\n\t\t\tcase 'swap':\n\t\t\t\tthis.setMoveOrDropMode( id );\n\t\t\t\tbreak;\n\t\t\tcase 'override':\n\t\t\t\tthis.onOverrideClick();\n\t\t\t\tbreak;\n\t\t\tcase 'notify_user_schedule_change':\n\t\t\t\tthis.onNotifyUserScheduleChangeClick();\n\t\t\t\tbreak;\n\t\t\tcase 'edit_employee':\n\t\t\tcase 'timesheet':\n\t\t\t\tthis.onNavigationClick( id );\n\t\t\t\tbreak;\n\t\t\tcase 'find_available':\n\t\t\t\tthis.onFindAvailableClick( id );\n\t\t\t\tbreak;\n\t\t\tcase 'AutoPunch':\n\t\t\t\tthis.addPunchesFromScheduledShifts( id );\n\t\t\t\tbreak;\n\t\t\tcase 'AddRequest':\n\t\t\t\tthis.addRequestFromScheduledShifts( id );\n\t\t\t\tbreak;\n\t\t\tcase 'import_icon':\n\t\t\t\tthis.onImportClick();\n\t\t\t\tbreak;\n\t\t\tcase 'pdf_schedule':\n\t\t\tcase 'pdf_schedule_group':\n\t\t\tcase 'pdf_schedule_group_combined':\n\t\t\tcase 'pdf_schedule_group_pagebreak':\n\t\t\t\tthis.onReportMenuClick( id );\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\taddRequestFromScheduledShifts( id ) {\n\t\tif ( Global.getProductEdition() <= 10 ) {\n\t\t\tTAlertManager.showAlert( Global.getUpgradeMessage() );\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( shift_array && shift_array.length <= 0 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar shift_array = this.select_cells_Array;\n\t\tvar first_shift = ( shift_array[0] ) ? shift_array[0] : null;\n\t\tvar last_shift = ( shift_array[shift_array.length - 1] ) ? shift_array[shift_array.length - 1] : null;\n\t\tif ( !first_shift || !last_shift ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar request = this.api.getScheduleDefaultData( this.select_cells_Array, { async: false } ).getResult();\n\t\tvar shift_status = 10;\n\t\tvar type_id = 40;\n\n\t\tvar mon = false, tue = false, wed = false, thu = false, fri = false, sat = false, sun = false;\n\n\t\tfor ( var w in shift_array ) {\n\t\t\tif ( first_shift.shift == undefined && shift_array[w].shift ) {\n\t\t\t\t//Set the archetype to the first day with a shift.\n\t\t\t\tfirst_shift = shift_array[w];\n\t\t\t}\n\n\t\t\t//Set selected days of the week.\n\t\t\tvar d = new Date( shift_array[w].time_stamp_num );\n\t\t\tswitch ( d.getDay() ) {\n\t\t\t\tcase 0:\n\t\t\t\t\tsun = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\t\tmon = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\ttue = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\twed = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 4:\n\t\t\t\t\tthu = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 5:\n\t\t\t\t\tfri = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 6:\n\t\t\t\t\tsat = true;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// delete ( d ); #2792 In the new ES6 conversion, delete is causing errors, but technically should never have worked anyway. Potentially never did anything. Could maybe delete. Try null first.\n\t\t\td = null;\n\t\t}\n\n\t\trequest.mon = mon;\n\t\trequest.tue = tue;\n\t\trequest.wed = wed;\n\t\trequest.thu = thu;\n\t\trequest.fri = fri;\n\t\trequest.sat = sat;\n\t\trequest.sun = sun;\n\n\t\tif ( first_shift && first_shift.date ) {\n\t\t\tvar start_date = first_shift.date;\n\t\t}\n\n\t\tif ( last_shift && last_shift.date ) {\n\t\t\tvar end_date = last_shift.date;\n\t\t}\n\n\t\tif ( first_shift ) {\n\t\t\tif ( first_shift.shift && first_shift.shift.status_id == 10 && first_shift.shift.user_id && first_shift.shift.user_id != TTUUID.zero_id ) {\n\t\t\t\tshift_status = 20;\n\t\t\t\ttype_id = 30;\n\t\t\t}\n\t\t}\n\n\t\trequest.status_id = shift_status;\n\t\trequest.type_id = type_id;\n\t\trequest.user_id = LocalCacheData.getLoginUser().id;\n\t\trequest.full_name = LocalCacheData.getLoginUser().full_name;\n\t\tif ( start_date ) {\n\t\t\trequest.date_stamp = start_date;\n\t\t\trequest.start_date = start_date;\n\t\t}\n\n\t\tif ( end_date ) {\n\t\t\trequest.end_date = end_date;\n\t\t}\n\n\t\tif ( first_shift.start_time ) {\n\t\t\trequest.start_time = first_shift.start_time;\n\t\t}\n\n\t\tif ( first_shift.end_time ) {\n\t\t\trequest.end_time = first_shift.end_time;\n\t\t}\n\n\t\tif ( first_shift.branch_id ) {\n\t\t\trequest.branch_id = first_shift.branch_id;\n\t\t}\n\n\t\tif ( first_shift.department_id ) {\n\t\t\trequest.department_id = first_shift.department_id;\n\t\t}\n\n\t\tif ( first_shift.job_id ) {\n\t\t\trequest.job_id = first_shift.job_id;\n\t\t}\n\n\t\tif ( first_shift.job_item_id ) {\n\t\t\trequest.job_item_id = first_shift.job_item_id;\n\t\t}\n\n\t\tif ( first_shift.punch_tag_id ) {\n\t\t\trequest.punch_tag_id = first_shift.punch_tag_id;\n\t\t}\n\n\t\tIndexViewController.openEditView( this, 'Request', request, 'openAddView' );\n\t}\n\n\taddPunchesFromScheduledShifts( id ) {\n\n\t\tif ( Global.getProductEdition() <= 10 ) {\n\t\t\tTAlertManager.showAlert( Global.getUpgradeMessage() );\n\t\t\treturn false;\n\t\t}\n\t\tif ( this.select_cells_Array == undefined || this.select_cells_Array.length < 1 ) {\n\t\t\tTAlertManager.showAlert( 'No schedules selected. You can\\'t autopunch no schedules.' );\n\t\t\treturn false;\n\t\t}\n\n\t\tvar shift_array = this.select_cells_Array;\n\t\tvar schedules = {};\n\t\tvar users = [];\n\t\tschedules.schedule = [];\n\t\tschedules.recurring = [];\n\n\t\tfor ( var i = 0; i < shift_array.length; i++ ) {\n\t\t\tif ( shift_array[i].shift != undefined ) { //avoid when no user scheduled.\n\t\t\t\tif ( shift_array[i].shift.id\n\t\t\t\t\t&& shift_array[i].shift.id != TTUUID.zero_id\n\t\t\t\t\t&& shift_array[i].shift.id != TTUUID.not_exist_id\n\t\t\t\t) {\n\t\t\t\t\tschedules.schedule.push( shift_array[i].shift.id );\n\t\t\t\t} else if ( shift_array[i].shift.recurring_schedule_id\n\t\t\t\t\t&& shift_array[i].shift.recurring_schedule_id != TTUUID.not_exist_id\n\t\t\t\t) {\n\t\t\t\t\tschedules.recurring.push( shift_array[i].shift.recurring_schedule_id );\n\t\t\t\t}\n\t\t\t\tusers.push( shift_array[i].shift.user_id );\n\t\t\t}\n\t\t}\n\n\t\tthis.api.addPunchesFromScheduledShifts( schedules, {\n\t\t\tonResult: function( result ) {\n\t\t\t\tif ( result.isValid() ) {\n\t\t\t\t\tUserGenericStatusWindowController.open( result.getAttributeInAPIDetails( 'user_generic_status_batch_id' ), [LocalCacheData.getLoginUser().id] );\n\t\t\t\t} else {\n\t\t\t\t\tTAlertManager.showErrorAlert( result );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\tgetSelectEmployee() {\n\t\tvar shift = this.select_cells_Array[0];\n\n\t\t//Error: Uncaught TypeError: Cannot read property 'user_id' of undefined in /interface/html5/#!m=Schedule&date=20141117&mode=week&a=new&tab=Schedule line 1116\n\t\tif ( !shift || shift.user_id == TTUUID.zero_id ) {\n\t\t\tshift = { user_id: LocalCacheData.getLoginUser().id };\n\t\t} else if ( shift.user_id && shift.user_id != TTUUID.zero_id ) {\n\t\t\tshift = { user_id: shift.user_id };\n\t\t}\n\n\t\tif ( this.edit_view && this.current_edit_record ) {\n\t\t\tshift.user_id = this.current_edit_record.user_id;\n\t\t}\n\n\t\treturn shift.user_id;\n\t}\n\n\tonFindAvailableClick() {\n\t\tif ( Global.getProductEdition() <= 10 ) {\n\t\t\tTAlertManager.showAlert( Global.getUpgradeMessage() );\n\t\t\treturn;\n\t\t}\n\n\t\tvar $this = this;\n\t\tvar args = {};\n\t\targs.selected = [];\n\t\tvar len = this.select_all_shifts_array.length;\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar item = this.select_all_shifts_array[i];\n\t\t\targs.selected.push( item );\n\t\t}\n\n\t\tLocalCacheData.extra_filter_for_next_open_view = {};\n\t\tLocalCacheData.extra_filter_for_next_open_view.filter_data = args;\n\n\t\tIndexViewController.openWizard( 'FindAvailableWizard', null, function( employee_id, notify_users ) {\n\t\t\t$this.onFindAvailableClose( employee_id, args.selected, notify_users );\n\t\t} );\n\t}\n\n\tonFindAvailableClose( employee_id, shift_array, notify_users ) {\n\t\tvar $this = this;\n\t\tvar len = shift_array.length;\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar item = shift_array[i];\n\t\t\titem.user_id = employee_id;\n\t\t\titem.replaced_id = item.id;\n\t\t\titem.notify_user_schedule_change = notify_users;\n\t\t\tdelete item.id;\n\t\t}\n\n\t\tthis.api.setSchedule( shift_array, {\n\t\t\tonResult: function( result ) {\n\t\t\t\tif ( !result.isValid() ) {\n\t\t\t\t\tTAlertManager.showErrorAlert( result );\n\t\t\t\t}\n\t\t\t\t$this.search();\n\t\t\t}\n\t\t} );\n\t}\n\n\tonImportClick() {\n\t\tvar $this = this;\n\t\tIndexViewController.openWizard( 'ImportCSVWizard', 'Schedule', function() {\n\t\t\t$this.search();\n\t\t} );\n\t}\n\n\tonNavigationClick( iconName ) {\n\n\t\tif ( !this.checkScheduleData() ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar post_data;\n\n\t\tswitch ( iconName ) {\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 'timesheet':\n\t\t\t\tvar filter = { filter_data: {} };\n\t\t\t\tfilter.user_id = this.getSelectEmployee();\n\n\t\t\t\tif ( this.edit_view ) {\n\t\t\t\t\tfilter.base_date = this.current_edit_record.date_stamp;\n\t\t\t\t} else {\n\t\t\t\t\tfilter.base_date = this.start_date_picker.getValue();\n\t\t\t\t}\n\t\t\t\tGlobal.addViewTab( this.viewId, $.i18n._( 'Schedules' ), window.location.href );\n\t\t\t\tIndexViewController.goToView( 'TimeSheet', filter );\n\n\t\t\t\tbreak;\n\t\t\tcase 'pdf_schedule':\n\t\t\tcase 'pdf_schedule_group_combined':\n\t\t\tcase 'pdf_schedule_group':\n\t\t\tcase 'pdf_schedule_group_pagebreak':\n\t\t\t\tfilter = Global.convertLayoutFilterToAPIFilter( this.select_layout );\n\n\t\t\t\tif ( !filter ) {\n\t\t\t\t\tfilter = {};\n\t\t\t\t}\n\t\t\t\tfilter.time_period = {};\n\t\t\t\tfilter.time_period.time_period = 'custom_date';\n\t\t\t\tfilter.time_period.start_date = this.full_schedule_data.schedule_dates.start_display_date;\n\t\t\t\tfilter.time_period.end_date = this.full_schedule_data.schedule_dates.end_display_date;\n\n\t\t\t\tif ( filter.time_period.start_date == filter.time_period.end_date ) {\n\t\t\t\t\tvar new_end_date = new Date( new Date( this.start_date.getTime() ).setDate( this.start_date.getDate() + 6 ) );\n\t\t\t\t\tfilter.time_period.end_date = new_end_date.format();\n\t\t\t\t}\n\n\t\t\t\tpost_data = { 0: filter, 1: iconName };\n\t\t\t\tthis.doFormIFrameCall( post_data );\n\t\t\t\tbreak;\n\n\t\t}\n\t}\n\n\tdoFormIFrameCall( postData ) {\n\t\tGlobal.APIFileDownload( 'APIScheduleSummaryReport', 'getScheduleSummaryReport', postData );\n\t}\n\n\tsetScheduleGridDragAble() {\n\t\tvar mode = this.getMode();\n\n\t\tswitch ( mode ) {\n\t\t\tcase ScheduleViewControllerMode.DAY:\n\t\t\t\tthis.setWeekModeDragAble();\n\t\t\t\tbreak;\n\t\t\tcase ScheduleViewControllerMode.WEEK:\n\t\t\t\tthis.setWeekModeDragAble();\n\t\t\t\tbreak;\n\t\t\tcase ScheduleViewControllerMode.MONTH:\n\t\t\t\tthis.setWeekModeDragAble();\n\t\t\t\tbreak;\n\t\t\tcase ScheduleViewControllerMode.YEAR:\n\t\t\t\tthis.setWeekModeDragAble();\n\t\t\t\tbreak;\n\t\t}\n\n\t\tvar $this = this;\n\t\t//set bottom drag to scroll area\n\t\t$( '.schedule-grid-div' ).off( 'dragover' ).on( 'dragover', function( e ) {\n\n\t\t\tvar grid_div = $( '.schedule-grid-div' );\n\t\t\tvar grid_pos = grid_div.offset().top;\n\n\t\t\tvar mouse_y = e.originalEvent.clientY;\n\t\t\tvar grid_height = grid_div.height();\n\n\t\t\tif ( mouse_y > ( grid_pos + grid_height ) ) {\n\t\t\t\t$this.scroll_unit = mouse_y - ( grid_pos + grid_height );\n\t\t\t\tif ( !$this.scroll_interval ) {\n\t\t\t\t\t$this.scroll_interval = setInterval( function() {\n\t\t\t\t\t\tvar div = $this.grid.grid.parent().parent();\n\t\t\t\t\t\tdiv.scrollTop( div.scrollTop() + $this.scroll_unit );\n\t\t\t\t\t}, 50 );\n\t\t\t\t}\n\t\t\t} else if ( mouse_y < ( grid_pos + 15 ) && mouse_y > ( grid_pos - 50 ) ) {\n\t\t\t\t$this.scroll_unit = ( grid_pos + 15 ) - mouse_y;\n\t\t\t\tif ( !$this.scroll_interval ) {\n\t\t\t\t\t$this.scroll_interval = setInterval( function() {\n\t\t\t\t\t\tvar div = $this.grid.grid.parent().parent();\n\t\t\t\t\t\tdiv.scrollTop( div.scrollTop() - $this.scroll_unit );\n\t\t\t\t\t}, 50 );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tclearInterval( $this.scroll_interval );\n\t\t\t\t$this.scroll_interval = null;\n\t\t\t}\n\n\t\t} );\n\n\t\t$( '.schedule-grid-div' ).off( 'dragend' ).on( 'dragend', function( e ) {\n\n\t\t\tif ( $this.scroll_interval ) {\n\t\t\t\tclearInterval( $this.scroll_interval );\n\t\t\t\t$this.scroll_interval = null;\n\t\t\t}\n\n\t\t} );\n\n\t\t$( '.schedule-grid-div td' ).unbind( 'dragenter' ).bind( 'dragenter', function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\t$( '.schedule-drag-over' ).removeClass( 'schedule-drag-over' );\n\n\t\t\tif ( $( this ).attr( 'draggable' ) || $( this ).parents( 'td' ).attr( 'draggable' ) ) {\n\t\t\t\t$( this ).addClass( 'schedule-drag-over' );\n\t\t\t}\n\t\t} );\n\t}\n\n\tsetWeekModeDragAble() {\n\t\tvar $this = this;\n\t\tvar position = 0;\n\n\t\tvar cells = this.grid.grid.find( '.date-column' ).parents( 'td' );\n\n\t\tcells.attr( 'draggable', true );\n\n\t\tcells.unbind( 'dragstart' ).bind( 'dragstart', function( event ) {\n\t\t\tvar td = event.target;\n\t\t\tif ( $this.select_all_shifts_array.length < 1 || !$( 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 = $( '<div class=\\'drag-holder-div\\'></div>' );\n\n\t\t\tvar len = $this.select_all_shifts_array.length;\n\n\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\tvar shift = $this.select_all_shifts_array[i];\n\t\t\t\tvar span = $( '<span class=\\'drag-span\\'></span>' );\n\n\t\t\t\tif ( shift.status_id == 20 ) {\n\t\t\t\t\tspan.text( $this.getAbsenceCellValue( shift ) );\n\t\t\t\t} else {\n\t\t\t\t\tspan.text( shift.start_time + ' - ' + shift.end_time );\n\t\t\t\t}\n\n\t\t\t\tcontainer.append( span );\n\t\t\t}\n\n\t\t\t$( 'body' ).find( '.drag-holder-div' ).remove();\n\n\t\t\t$( 'body' ).append( container );\n\n\t\t\tevent.originalEvent.dataTransfer.setData( 'Text', 'schedule' );//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\t\t} );\n\n\t\tcells.unbind( 'drop' ).bind( 'drop', function( event ) {\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\t$( '.drag-holder-div' ).remove();\n\n\t\t\tvar target_empty_row = false;\n\t\t\tvar delete_old_items = false;\n\n\t\t\tvar new_shifts_array = [];\n\t\t\tvar delete_shifts_array = [];\n\t\t\tvar recurring_delete_shifts_array = [];\n\n\t\t\tvar target_cell = event.currentTarget;\n\n\t\t\tvar selected_shifts = $this.select_cellls_and_shifts_array;\n\t\t\t//Error: Uncaught TypeError: Cannot read property 'length' of undefined in interface/html5/#!m=Schedule&date=20151213&mode=week line 1420\n\t\t\tif ( !selected_shifts ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar first_target_row_index;\n\t\t\tvar first_target_cell_index;\n\n\t\t\tfirst_target_row_index = target_cell.parentNode.rowIndex - 1;\n\t\t\tfirst_target_cell_index = target_cell.cellIndex;\n\n\t\t\tvar row_index_offset = 0;\n\t\t\tvar cell_index_offset = 0;\n\n\t\t\tvar first_selected_row_index;\n\t\t\tvar first_selected_cell_index;\n\n\t\t\tvar colModel = $this.grid.grid.getGridParam( 'colModel' );\n\n\t\t\tif ( $this.select_drag_menu_id === 'move' ) {\n\t\t\t\tdelete_old_items = true;\n\t\t\t} else {\n\t\t\t\tdelete_old_items = false;\n\t\t\t}\n\n\t\t\tvar len = selected_shifts.length;\n\n\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\tvar cell = selected_shifts[i];\n\t\t\t\tvar shift;\n\n\t\t\t\tif ( i === 0 ) {\n\t\t\t\t\tfirst_selected_row_index = cell.row_id;\n\t\t\t\t\tfirst_selected_cell_index = cell.cell_index;\n\t\t\t\t} else {\n\t\t\t\t\tif ( !target_empty_row ) {\n\t\t\t\t\t\trow_index_offset = cell.row_id - first_selected_row_index;\n\t\t\t\t\t}\n\t\t\t\t\tcell_index_offset = cell.cell_index - first_selected_cell_index;\n\t\t\t\t}\n\n\t\t\t\tif ( cell.shift ) {\n\t\t\t\t\tshift = cell.shift;\n\t\t\t\t} else {\n\t\t\t\t\tvar target_row_index = first_target_row_index + row_index_offset;\n\t\t\t\t\tvar target_cell_index = first_target_cell_index + cell_index_offset;\n\t\t\t\t\tif ( target_cell_index > colModel.length - 1 ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tvar target_data = $this.getDataByCellIndex( target_row_index, target_cell_index );\n\t\t\t\t\tvar target_row = $this.schedule_source[target_row_index];\n\n\t\t\t\t\tif ( !target_row || !target_row.user_id ) {\n\t\t\t\t\t\ttarget_empty_row = true;\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tshift.branch_id = shift.branch ? shift.branch_id : '';\n\t\t\t\tshift.department_id = shift.department ? shift.department_id : '';\n\t\t\t\tshift.job_id = shift.job_id ? shift.job_id : '';\n\t\t\t\tshift.job_item_id = shift.job_item_id ? shift.job_item_id : '';\n\t\t\t\tshift.punch_tag_id = shift.punch_tag_id ? shift.punch_tag_id : '';\n\n\t\t\t\ttarget_row_index = first_target_row_index + row_index_offset;\n\t\t\t\ttarget_cell_index = first_target_cell_index + cell_index_offset;\n\n\t\t\t\tif ( target_cell_index > colModel.length - 1 ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\ttarget_data = $this.getDataByCellIndex( target_row_index, target_cell_index );\n\t\t\t\ttarget_row = $this.schedule_source[target_row_index];\n\n\t\t\t\tif ( !target_row || !target_row.user_id ) {\n\t\t\t\t\ttarget_empty_row = true;\n\t\t\t\t}\n\n\t\t\t\tif ( target_row ) {\n\t\t\t\t\tif ( target_row.type === ScheduleViewControllerRowType.DATE ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !target_data || target_empty_row ) {\n\t\t\t\t\t\tvar date_stamp;\n\n\t\t\t\t\t\t//Error: TypeError: colModel[target_cell_index] is undefined in /interface/html5/framework/jquery.min.js?v=8.0.0-20141230-153210 line 2 > eval line 1443\n\t\t\t\t\t\tif ( colModel ) {\n\t\t\t\t\t\t\tif ( $this.getMode() === ScheduleViewControllerMode.MONTH ) {\n\t\t\t\t\t\t\t\t//Error: \"TypeError: Cannot read property 'format' of null\"\n\t\t\t\t\t\t\t\t// when user drags a scedule to a non-date grid element we need to quietly fail\n\t\t\t\t\t\t\t\tvar related_date = $this.getCellRelatedDate( target_row_index, colModel, target_cell_index, colModel[target_cell_index].name );\n\t\t\t\t\t\t\t\tif ( related_date ) {\n\t\t\t\t\t\t\t\t\tdate_stamp = related_date.format();\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\tdate_stamp = Global.strToDate( colModel[target_cell_index].name, $this.full_format ).format();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( !date_stamp || date_stamp == 'Invalid date' ) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttarget_data = {};\n\n\t\t\t\t\t\tif ( !target_row.user_id ) { //Only happens in month mode;\n\t\t\t\t\t\t\ttarget_data = shift;\n\t\t\t\t\t\t\ttarget_data.date_stamp = date_stamp;\n\t\t\t\t\t\t\ttarget_data.start_date_stamp = date_stamp;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttarget_data.user_id = target_row.user_id;\n\t\t\t\t\t\t\ttarget_data.branch = target_row.branch;\n\t\t\t\t\t\t\ttarget_data.branch_id = target_row.branch ? target_row.branch_id : '';\n\t\t\t\t\t\t\ttarget_data.schedule_policy_id = target_row.schedule_policy_id;\n\t\t\t\t\t\t\ttarget_data.department_id = target_row.department ? target_row.department_id : '';\n\t\t\t\t\t\t\ttarget_data.department = target_row.department;\n\t\t\t\t\t\t\ttarget_data.job_id = target_row.job_id ? target_row.job_id : '';\n\t\t\t\t\t\t\ttarget_data.job = target_row.job;\n\t\t\t\t\t\t\ttarget_data.job_item_id = target_row.job_item_id ? target_row.job_item_id : '';\n\t\t\t\t\t\t\ttarget_data.punch_tag_id = target_row.punch_tag_id ? target_row.punch_tag_id : '';\n\t\t\t\t\t\t\ttarget_data.job_item = target_row.job_item;\n\t\t\t\t\t\t\ttarget_data.date_stamp = date_stamp;\n\t\t\t\t\t\t\ttarget_data.start_date_stamp = date_stamp;\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\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tvar new_shift = Global.clone( shift );\n\n\t\t\t\tif ( $this.select_drag_menu_id !== 'swap' ) {\n\t\t\t\t\tnew_shift.id = '';\n\t\t\t\t\tnew_shift.date_stamp = target_data.date_stamp;\n\t\t\t\t\tnew_shift.start_date_stamp = target_data.start_date_stamp;\n\t\t\t\t\tnew_shift.user_id = target_data.user_id;\n\t\t\t\t\t// When dragging an open shift to an empty cell in a user row with no branch column visible, the branch id value now defaults to user default branch id\n\t\t\t\t\tnew_shift.branch_id = target_data.branch ? target_data.branch_id : TTUUID.not_exist_id;\n\t\t\t\t\tnew_shift.department_id = target_data.department ? target_data.department_id : TTUUID.not_exist_id;\n\t\t\t\t\tnew_shift.job_id = target_data.job_id ? target_data.job_id : TTUUID.not_exist_id;\n\t\t\t\t\tnew_shift.job_item_id = target_data.job_item_id ? target_data.job_item_id : TTUUID.not_exist_id;\n\t\t\t\t\tnew_shift.punch_tag_id = target_data.punch_tag_id ? target_data.punch_tag_id : TTUUID.not_exist_id;\n\n\t\t\t\t\tif ( $this.is_override ) {\n\t\t\t\t\t\tnew_shift.overwrite = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( $this.notify_user_schedule_change ) {\n\t\t\t\t\t\tnew_shift.notify_user_schedule_change = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tnew_shifts_array.push( new_shift );\n\t\t\t\t\tif ( shift.id && shift.id != TTUUID.zero_id ) {\n\t\t\t\t\t\tdelete_shifts_array.push( shift.id );\n\t\t\t\t\t} else if ( shift.user_id != TTUUID.zero_id && shift.user_id != TTUUID.not_exist_id ) {\n\t\t\t\t\t\t//If dragging (move) a recurring shift assigned to a user and dropping on another user, switch the source shift to Absent in the process, otherwise both shifts will exist as being worked.\n\t\t\t\t\t\t// However when dragging from a OPEN shift as the source, that isn't required, as the OPEN shift will automatically be filled.\n\t\t\t\t\t\tshift.status_id = '20';\n\t\t\t\t\t\trecurring_delete_shifts_array.push( shift );\n\t\t\t\t\t} else if ( shift.user_id == TTUUID.zero_id ) {\n\t\t\t\t\t\tdelete_old_items = false; //Never delete old items when the source is a OPEN shift.\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tvar temp_selected_data = Global.clone( new_shift );\n\t\t\t\t\tvar temp_target_data = Global.clone( target_data );\n\n\t\t\t\t\tif ( !temp_target_data.start_date ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tfor ( var key in target_data ) {\n\t\t\t\t\t\tif ( key !== 'id' &&\n\t\t\t\t\t\t\tkey !== 'user_id' &&\n\t\t\t\t\t\t\tkey !== 'date_stamp' &&\n\t\t\t\t\t\t\tkey !== 'start_date_stamp' &&\n\t\t\t\t\t\t\tkey !== 'branch_id' &&\n\t\t\t\t\t\t\tkey !== 'department_id' &&\n\t\t\t\t\t\t\tkey !== 'job_id' &&\n\t\t\t\t\t\t\tkey !== 'job_item_id' &&\n\t\t\t\t\t\t\tkey !== 'punch_tag_id' &&\n\t\t\t\t\t\t\tkey !== 'branch' &&\n\t\t\t\t\t\t\tkey !== 'department' &&\n\t\t\t\t\t\t\tkey !== 'job' &&\n\t\t\t\t\t\t\tkey !== 'job_item' &&\n\t\t\t\t\t\t\tkey !== 'schedule_policy_id' ) {\n\n\t\t\t\t\t\t\ttarget_data[key] = temp_selected_data[key];\n\t\t\t\t\t\t\tnew_shift[key] = temp_target_data[key];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// When dragging an open shift to an empty cell in a user row with no branch column visible, the branch id value now defaults to user default branch id\n\t\t\t\t\ttarget_data.branch_id = target_data.branch ? target_data.branch_id : TTUUID.not_exist_id;\n\t\t\t\t\ttarget_data.department_id = target_data.department ? target_data.department_id : TTUUID.not_exist_id;\n\t\t\t\t\ttarget_data.job_id = target_data.job_id ? target_data.job_id : TTUUID.not_exist_id;\n\t\t\t\t\ttarget_data.job_item_id = target_data.job_item_id ? target_data.job_item_id : TTUUID.not_exist_id;\n\t\t\t\t\ttarget_data.punch_tag_id = target_data.punch_tag_id ? target_data.punch_tag_id : TTUUID.not_exist_id;\n\n\t\t\t\t\tnew_shifts_array.push( target_data );\n\t\t\t\t\tnew_shifts_array.push( new_shift );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( new_shifts_array.length > 0 ) {\n\t\t\t\t$this.api.setSchedule( new_shifts_array, {\n\t\t\t\t\tonResult: function( res ) {\n\t\t\t\t\t\tif ( res.isValid() ) {\n\t\t\t\t\t\t\tif ( delete_old_items ) {\n\t\t\t\t\t\t\t\tif ( delete_shifts_array.length > 0 ) {\n\t\t\t\t\t\t\t\t\t$this.api.deleteSchedule( delete_shifts_array, {\n\t\t\t\t\t\t\t\t\t\tonResult: function() {\n\t\t\t\t\t\t\t\t\t\t\tif ( recurring_delete_shifts_array.length > 0 ) {\n\t\t\t\t\t\t\t\t\t\t\t\t$this.api.setSchedule( recurring_delete_shifts_array, {\n\t\t\t\t\t\t\t\t\t\t\t\t\tonResult: function() {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t$this.search();\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t$this.search();\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t} else if ( recurring_delete_shifts_array.length > 0 ) {\n\t\t\t\t\t\t\t\t\t$this.api.setSchedule( recurring_delete_shifts_array, {\n\t\t\t\t\t\t\t\t\t\tonResult: function() {\n\t\t\t\t\t\t\t\t\t\t\t$this.search();\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t$this.search();\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\t$this.search();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tTAlertManager.showErrorAlert( res );\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\n\t\tcells.unbind( 'dragenter' ).bind( 'dragenter', function( event ) {\n\t\t\tevent.preventDefault();\n\t\t} );\n\n\t\tcells.unbind( 'dragover' ).bind( 'dragover', function( event ) {\n\t\t\tevent.preventDefault(); //Must prevent tihs\n\n\t\t} );\n\t\tcells.unbind( 'dragend' ).bind( 'dragend', function( event ) {\n\n\t\t\t$( '.drag-holder-div' ).remove();\n\t\t\t$( '.schedule-drag-over' ).removeClass( 'schedule-drag-over' );\n\n\t\t} );\n\t}\n\n\tresetSomeFields( item ) {\n\t\titem.branch_id = item.branch ? item.branch_id : '';\n\t\titem.department_id = item.department ? item.department_id : '';\n\t\titem.job_id = item.job ? item.job_id : '';\n\t\titem.job_item_id = item.job_item ? item.job_item_id : '';\n\t\titem.punch_tag_id = item.punch_tag_id ? item.punch_tag_id : [];\n\n\t\treturn item;\n\t}\n\n\t_createParametersForAdd() {\n\t\tvar result = [], user;\n\t\tif ( this.select_cells_Array.length > 0 ) {\n\t\t\tfor ( var i = 0, n = this.select_cells_Array.length; i < n; i++ ) {\n\t\t\t\tvar item = this.select_cells_Array[i];\n\t\t\t\tuser = {};\n\t\t\t\tuser.user_id = item.user_id;\n\t\t\t\tuser.branch_id = item.branch_id;\n\t\t\t\tuser.department_id = item.department_id;\n\t\t\t\tuser.job_id = item.job_id;\n\t\t\t\tuser.job_item_id = item.job_item_id;\n\t\t\t\tuser.punch_tag_id = item.punch_tag_id;\n\t\t\t\tuser.date = item.date;\n\t\t\t\tresult.push( user );\n\t\t\t}\n\t\t}\n\n\t\tif ( result.length < 1 ) {\n\t\t\tvar login_user = LocalCacheData.getLoginUser();\n\t\t\tuser = {};\n\t\t\tuser.user_id = login_user.id;\n\t\t\tuser.branch_id = login_user.branch_id;\n\t\t\tuser.department_id = login_user.department_id;\n\t\t\tuser.job_id = login_user.job_id;\n\t\t\tuser.job_item_id = login_user.job_item_id;\n\t\t\tuser.punch_tag_id = login_user.punch_tag_id;\n\t\t\tuser.date = this.getSelectDate();\n\t\t\tresult.push( user );\n\t\t}\n\t\treturn result;\n\t}\n\n\tonAddClick( doing_save_and_new ) {\n\n\t\tvar $this = this;\n\t\tthis.setCurrentEditViewState( 'new' );\n\n\t\tif ( this.select_cells_Array.length > 1 ) {\n\t\t\tthis.is_mass_adding = true;\n\t\t}\n\n\t\t$this.openEditView();\n\n\t\tvar args;\n\t\tif ( !doing_save_and_new ) {\n\t\t\targs = this._createParametersForAdd();\n\t\t} else {\n\t\t\targs = [\n\t\t\t\t{\n\t\t\t\t\tuser_id: this.current_edit_record.user_id,\n\t\t\t\t\tbranch_id: this.current_edit_record.branch_id,\n\t\t\t\t\tdepartment_id: this.current_edit_record.department_id,\n\t\t\t\t\tjob_id: this.current_edit_record.job_id,\n\t\t\t\t\tjob_item_id: this.current_edit_record.job_item_id,\n\t\t\t\t\tpunch_tag_id: this.current_edit_record.punch_tag_id,\n\t\t\t\t\tdate: this.current_edit_record.date_stamp\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\n\t\tthis.api['get' + this.api.key_name + 'DefaultData']( args, {\n\t\t\tonResult: function( result ) {\n\t\t\t\tvar select_shift;\n\t\t\t\tvar result_data = result.getResult();\n\n\t\t\t\tselect_shift = result_data;\n\t\t\t\tif ( $this.select_cells_Array.length >= 1 ) {\n\t\t\t\t\tfor ( var i = 0, n = args.length; i < n; i++ ) {\n\t\t\t\t\t\tvar item = args[i];\n\t\t\t\t\t\tif ( i == 0 ) {\n\t\t\t\t\t\t\tselect_shift.branch_id = item.branch_id;\n\t\t\t\t\t\t\tselect_shift.department_id = item.department_id;\n\t\t\t\t\t\t\tselect_shift.job_id = item.job_id;\n\t\t\t\t\t\t\tselect_shift.job_item_id = item.job_item_id;\n\t\t\t\t\t\t\tselect_shift.punch_tag_id = item.punch_tag_id;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t( select_shift.branch_id !== item.branch_id && select_shift.branch_id !== '-2' ) ? select_shift.branch_id = '-2' : item.branch_id;\n\t\t\t\t\t\t\t( select_shift.department_id !== item.department_id && select_shift.department_id !== '-2' ) ? select_shift.department_id = '-2' : item.department_id;\n\t\t\t\t\t\t\t( select_shift.job_id !== item.job_id && select_shift.job_id !== '-2' ) ? select_shift.job_id = '-2' : item.job_id;\n\t\t\t\t\t\t\t( select_shift.job_item_id !== item.job_item_id && select_shift.job_item_id !== '-2' ) ? select_shift.job_item_id = '-2' : item.job_item_id;\n\t\t\t\t\t\t\t( select_shift.punch_tag_id !== item.punch_tag_id && select_shift.punch_tag_id !== '-2' ) ? select_shift.punch_tag_id = '-2' : item.punch_tag_id;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( !doing_save_and_new ) {\n\t\t\t\t\tselect_shift.date_stamp = $this.getSelectDate();\n\n\t\t\t\t} else {\n\t\t\t\t\tvar temp_date = Global.strToDate( $this.current_edit_record.date_stamp );\n\t\t\t\t\tselect_shift.date_stamp = new Date( new Date( temp_date.getTime() ).setDate( temp_date.getDate() + 1 ) ).format();\n\n\t\t\t\t}\n\n\t\t\t\tif ( !select_shift.start_date_stamp ) {\n\t\t\t\t\tselect_shift.start_date_stamp = select_shift.date_stamp;\n\t\t\t\t}\n\n\t\t\t\tselect_shift.id = '';\n\n\t\t\t\tif ( $this.sub_view_mode && $this.parent_key ) {\n\t\t\t\t\tresult_data[$this.parent_key] = $this.parent_value;\n\t\t\t\t}\n\n\t\t\t\t$this.current_edit_record = select_shift;\n\t\t\t\t$this.initEditView();\n\n\t\t\t}\n\t\t} );\n\t}\n\n\topenEditView() {\n\n\t\tif ( !this.edit_view ) {\n\t\t\tthis.initEditViewUI( 'Schedule', 'ScheduleEditView.html' );\n\t\t}\n\t\tthis.previous_absence_policy_id = false;\n\t}\n\n\t//set widget disablebility if view mode or edit mode\n\tsetEditViewWidgetsMode() {\n\t\tvar did_clean_dic = {};\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\twidget.css( 'opacity', 1 );\n\t\t\tvar column = widget.parent().parent().parent();\n\t\t\tvar tab_id = column.parent().attr( 'id' );\n\t\t\tif ( !column.hasClass( 'v-box' ) ) {\n\t\t\t\tif ( !did_clean_dic[tab_id] ) {\n\t\t\t\t\tdid_clean_dic[tab_id] = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( this.is_viewing ) {\n\t\t\t\tif ( Global.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.isSet( widget.setEnabled ) ) {\n\t\t\t\t\twidget.setEnabled( true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t}\n\n\tsetJobValueWhenUserChanged( job, job_id_col_name, filter_data ) {\n\t\tvar $this = this;\n\n\t\t//Error: Uncaught TypeError: Cannot set property 'job_item_id' of null in /interface/html5/#!m=TimeSheet&date=20150126&user_id=54286 line 6785\n\t\tif ( !$this.current_edit_record ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.edit_view_ui_dic['user_ids'] && this.edit_view_ui_dic['user_ids'].is( ':visible' ) ) {\n\t\t\tfilter_data['user_id'] = this.edit_view_ui_dic['user_ids'].getValue();\n\n\t\t\t//If more than one user is selected, don't filter by user_id at all, show all jobs and let the validation system handle it.\n\t\t\tif ( filter_data['user_id'].length == 1 ) {\n\t\t\t\tfilter_data['user_id'] = filter_data['user_id'][0];\n\t\t\t} else {\n\t\t\t\tfilter_data['user_id'] = false;\n\t\t\t}\n\t\t} else {\n\t\t\tfilter_data['user_id'] = this.current_edit_record['user_id'];\n\t\t}\n\n\t\tvar job_widget = $this.edit_view_ui_dic[job_id_col_name];\n\t\tvar current_job_id = job_widget.getValue();\n\t\tjob_widget.setSourceData( null ); //Clear out source data so its reloaded when the Job dropdown is expanded again.\n\t\tjob_widget.setCheckBox( true );\n\t\tthis.edit_view_ui_dic['job_item_quick_search'].setCheckBox( true );\n\n\t\tvar args = {};\n\t\targs.filter_data = filter_data;\n\t\t$this.edit_view_ui_dic[job_id_col_name].setDefaultArgs( args );\n\n\t\treturn;\n\t}\n\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\tthis.current_edit_record[key] = c_value;\n\n\t\tswitch ( key ) {\n\t\t\tcase 'job_id':\n\t\t\t\tif ( Global.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\t\t\t\tbreak;\n\t\t\tcase 'job_item_id':\n\t\t\t\tif ( Global.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.getProductEdition() >= 20 ) {\n\t\t\t\t\tif ( c_value !== TTUUID.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.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 'department_id':\n\t\t\t\tif ( Global.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.getProductEdition() >= 20 ) {\n\t\t\t\t\tthis.onJobQuickSearch( key, c_value );\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_quick_search':\n\t\t\t\tif ( Global.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 onPunchTagQuickSearch 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 'status_id':\n\t\t\t\tthis.onTypeChange( true );\n\t\t\t\tbreak;\n\t\t\tcase 'user_id':\n\t\t\tcase 'user_ids':\n\t\t\t\tthis.setEditMenu();\n\n\t\t\t\tthis.setAbsencePolicyWhenUserChanged();\n\n\t\t\t\tif ( Global.getProductEdition() >= 20 ) {\n\t\t\t\t\tif ( this.edit_view_ui_dic['job_id'] ) {\n\t\t\t\t\t\tthis.setJobValueWhenUserChanged( this.edit_view_ui_dic['job_id'].getValue( true ), 'job_id', {\n\t\t\t\t\t\t\tstatus_id: 10,\n\t\t\t\t\t\t\tuser_id: this.edit_view_ui_dic[key].getValue(),\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.setPunchTagValuesWhenCriteriaChanged( this.getPunchTagFilterData(), 'punch_tag_id' );\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\tcase 'start_date_stamps':\n\t\t\t\tthis.setEditMenu();\n\t\t\t\tthis.current_edit_record['start_date_stamp'] = c_value;\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\tif ( key == 'absence_policy_id' ) {\n\t\t\tthis.previous_absence_policy_id = this.current_edit_record.absence_policy_id;\n\t\t}\n\n\t\tif ( key === 'date_stamp' ||\n\t\t\tkey === 'start_date_stamps' ||\n\t\t\tkey === 'start_date_stamp' ||\n\t\t\tkey === 'start_time' ||\n\t\t\tkey === 'end_time' ||\n\t\t\tkey === 'schedule_policy_id' ||\n\t\t\tkey === 'absence_policy_id' ) {\n\n\t\t\tif ( this.current_edit_record['date_stamp'] !== '' &&\n\t\t\t\tthis.current_edit_record['start_time'] !== '' &&\n\t\t\t\tthis.current_edit_record['end_time'] !== '' ) {\n\n\t\t\t\tvar startTime = this.current_edit_record['date_stamp'] + ' ' + this.current_edit_record['start_time'];\n\t\t\t\tvar endTime = this.current_edit_record['date_stamp'] + ' ' + this.current_edit_record['end_time'];\n\t\t\t\tvar schedulePolicyId = this.current_edit_record['schedule_policy_id'];\n\t\t\t\tvar user_id = this.current_edit_record.user_id;\n\n\t\t\t\tthis.api.getScheduleTotalTime( startTime, endTime, schedulePolicyId, user_id, {\n\t\t\t\t\tonResult: function( total_time ) {\n\n\t\t\t\t\t\t//Uncaught TypeError: Cannot set property 'total_time' of null\n\t\t\t\t\t\t//Error: Uncaught TypeError: Cannot read property 'setValue' of undefined in interface/html5/#!m=Schedule&date=20160202&mode=week&a=new&tab=Schedule line 1799\n\t\t\t\t\t\tif ( !$this.edit_view || !$this.current_edit_record || !$this.edit_view_ui_dic['total_time'] ) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t//Fixed exception that total_time is null\n\t\t\t\t\t\tif ( total_time ) {\n\t\t\t\t\t\t\ttotal_time = total_time.getResult();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttotal_time = $this.current_edit_record.total_time ? $this.current_edit_record.total_time : 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$this.current_edit_record.total_time = total_time;\n\t\t\t\t\t\ttotal_time = Global.getTimeUnit( total_time );\n\t\t\t\t\t\t$this.edit_view_ui_dic['total_time'].setValue( total_time );\n\n\t\t\t\t\t\t$this.onAvailableBalanceChange();\n\n\t\t\t\t\t}\n\t\t\t\t} );\n//\n\n\t\t\t} else {\n\t\t\t\tthis.onAvailableBalanceChange();\n\t\t\t}\n\n\t\t}\n\n\t\tif ( !doNotValidate ) {\n\t\t\tthis.validate();\n\t\t}\n\t}\n\n\tsetAbsencePolicyWhenUserChanged() {\n\n\t\tvar $this = this;\n\t\tvar absence_widget = $this.edit_view_ui_dic['absence_policy_id'];\n\t\tabsence_widget.setSourceData( null );\n\t\tvar old_value = absence_widget.getValue();\n\n\t\tvar args = {};\n\t\targs.filter_data = { id: old_value };\n\n\t\targs = this.setAbsencePolicyFilter( args );\n\n\t\tif ( old_value ) {\n\n\t\t\t$this.absence_policy_api.getAbsencePolicy( args, {\n\t\t\t\tonResult: function( task_result ) {\n\n\t\t\t\t\t// Returning early to help mitigate #2889 - \"Error: Uncaught TypeError: Cannot set property 'absence_policy_id' of null\"\n\t\t\t\t\t// This can happen when the user saves or leaves the page before the API call is completed.\n\t\t\t\t\tif ( $this.current_edit_record === null || $this.current_edit_record === undefined ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar data = task_result.getResult();\n\n\t\t\t\t\tif ( data.length > 0 ) {\n\t\t\t\t\t\tabsence_widget.setValue( old_value );\n\t\t\t\t\t\t$this.current_edit_record.absence_policy_id = old_value;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tabsence_widget.setValue( false );\n\t\t\t\t\t\t$this.current_edit_record.absence_policy_id = false;\n\t\t\t\t\t}\n\t\t\t\t\t$this.onAvailableBalanceChange();\n\t\t\t\t\t$this.validate();\n\n\t\t\t\t}\n\t\t\t} );\n\t\t} else {\n\t\t\tthis.onAvailableBalanceChange();\n\t\t\tthis.validate();\n\t\t}\n\t}\n\n\t//Make sure this.current_edit_record is updated before validate\n\tvalidate() {\n\t\tvar $this = this;\n\t\tvar record = {};\n\t\tif ( this.is_mass_adding ) {\n\t\t\trecord = [];\n\t\t\t$.each( this.select_cells_Array, function( index, value ) {\n\t\t\t\tif ( value.hasOwnProperty( 'user_id' ) && value.hasOwnProperty( 'date' ) && value.date ) {\n\t\t\t\t\tvar commonRecord = Global.clone( $this.current_edit_record );\n\t\t\t\t\tdelete commonRecord.user_ids;\n\t\t\t\t\tdelete commonRecord.start_dates;\n\t\t\t\t\tcommonRecord.id = '';\n\t\t\t\t\tcommonRecord.user_id = value.user_id;\n\t\t\t\t\tcommonRecord.start_date_stamp = value.date;\n\t\t\t\t\tcommonRecord = $this.buildMassAddRecord( commonRecord );\n\t\t\t\t\trecord.push( commonRecord );\n\t\t\t\t}\n\t\t\t} );\n\t\t} else if ( this.is_mass_editing ) {\n\t\t\tfor ( var key in this.edit_view_ui_dic ) {\n\t\t\t\tif ( !this.edit_view_ui_dic.hasOwnProperty( key ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tvar widget = this.edit_view_ui_dic[key];\n\t\t\t\tif ( Global.isSet( widget.isChecked ) ) {\n\t\t\t\t\tif ( widget.isChecked() && widget.getEnabled() ) {\n\t\t\t\t\t\trecord[key] = widget.getValue();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( this.mass_edit_record_ids.length > 0 ) {\n\t\t\t\tvar checkFields = record;\n\t\t\t\trecord = [];\n\t\t\t\t$.each( this.mass_edit_record_ids, function( index, value ) {\n\t\t\t\t\tvar commonRecord = Global.clone( checkFields );\n\t\t\t\t\tcommonRecord.id = value;\n\t\t\t\t\tcommonRecord = $this.processAddRecord( commonRecord );\n\t\t\t\t\trecord.push( commonRecord );\n\t\t\t\t} );\n\t\t\t\t$.each( this.select_all_shifts_array, function( index, value ) {\n\t\t\t\t\tif ( !value.id || value.id == TTUUID.zero_id ) {\n\t\t\t\t\t\tvar commonRecord = Global.clone( value );\n\t\t\t\t\t\tfor ( var key in checkFields ) {\n\t\t\t\t\t\t\tcommonRecord[key] = checkFields[key];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcommonRecord = $this.processAddRecord( commonRecord );\n\t\t\t\t\t\trecord.push( commonRecord );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\trecord = this.getRecordsFromUserIDs( record );\n\t\t\t} else {\n\t\t\t\tvar record_array = [];\n\t\t\t\t$.each( this.select_all_shifts_array, function( index, value ) {\n\t\t\t\t\tif ( !value.id || value.id == TTUUID.zero_id ) {\n\t\t\t\t\t\tvar commonRecord = Global.clone( value );\n\t\t\t\t\t\tfor ( var key in record ) {\n\t\t\t\t\t\t\tcommonRecord[key] = record[key];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcommonRecord = $this.processAddRecord( commonRecord );\n\t\t\t\t\t\trecord_array.push( commonRecord );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\tif ( record_array.length < 1 ) {\n\t\t\t\t\tif ( this.select_cells_Array.length > 0 ) {\n\t\t\t\t\t\t$this.processAddRecord( record );\n\t\t\t\t\t\trecord = this.getRecordsFromUserIDs( [record] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\trecord = record_array;\n\t\t\t\t\trecord = this.getRecordsFromUserIDs( record );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\t//Error: Uncaught TypeError: Cannot read property 'indexOf' of undefined in interface/html5/#!m=Schedule&date=20151204&mode=day line 1954\n\t\t\tif ( this.current_edit_record && this.current_edit_record.start_date_stamp &&\n\t\t\t\t( this.current_edit_record.start_date_stamp.indexOf( ' - ' ) > 0 ||\n\t\t\t\t\t$.type( this.current_edit_record.start_date_stamp ) === 'array' ) ) {\n\t\t\t\tif ( this.current_edit_record.start_date_stamp.indexOf( ' - ' ) > 0 ) {\n\t\t\t\t\tthis.current_edit_record.start_date_stamp = this.parserDatesRange( this.current_edit_record.start_date_stamp );\n\t\t\t\t}\n\t\t\t\trecord = [];\n\t\t\t\tfor ( var i = 0; i < this.current_edit_record.start_date_stamp.length; i++ ) {\n\t\t\t\t\tvar commonRecord = Global.clone( $this.current_edit_record );\n\t\t\t\t\tcommonRecord.start_date_stamp = this.current_edit_record.start_date_stamp[i];\n\t\t\t\t\tif ( this.select_cells_Array.length > 0 ) {\n\t\t\t\t\t\t$this.processAddRecord( commonRecord );\n\t\t\t\t\t}\n\t\t\t\t\trecord.push( commonRecord );\n\t\t\t\t}\n\t\t\t\trecord = this.getRecordsFromUserIDs( record );\n\t\t\t} else {\n\t\t\t\trecord = Global.clone( this.current_edit_record );\n\t\t\t\tif ( this.select_cells_Array.length > 0 ) {\n\t\t\t\t\t$this.processAddRecord( record );\n\t\t\t\t}\n\t\t\t\trecord = this.getRecordsFromUserIDs( [record] );\n\t\t\t}\n\n\t\t}\n\t\tthis.api['validate' + this.api.key_name]( record, {\n\t\t\tonResult: function( result ) {\n\t\t\t\t$this.validateResult( result );\n\t\t\t}\n\t\t} );\n\t}\n\n\tgetRecordsFromUserIDs( record ) {\n\t\tvar result = [];\n\n\t\tfor ( var j = 0; j < record.length; j++ ) {\n\t\t\tvar common_record = record[j];\n\n\t\t\tif ( common_record.user_ids && common_record.user_ids.length > 0 ) {\n\t\t\t\tfor ( var y = 0; y < common_record.user_ids.length; y++ ) {\n\t\t\t\t\tvar user_id = common_record.user_ids[y];\n\t\t\t\t\tif ( Global.isObject( user_id ) && user_id.id ) {\n\t\t\t\t\t\tuser_id = user_id.id;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar new_common_record = Global.clone( common_record );\n\t\t\t\t\tnew_common_record.user_id = user_id;\n\t\t\t\t\tresult.push( new_common_record );\n\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\tif ( ( !this.current_edit_record || !this.current_edit_record.id || this.current_edit_record.id == TTUUID.zero_id ) && !this.is_mass_editing ) {\n\t\t\t\t\tcommon_record.user_id = TTUUID.zero_id;\n\t\t\t\t}\n\n\t\t\t\tresult.push( common_record );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tonSaveAndCopy( ignoreWarning ) {\n\t\tvar $this = this;\n\t\tif ( !Global.isSet( ignoreWarning ) ) {\n\t\t\tignoreWarning = false;\n\t\t}\n\t\tthis.is_add = true;\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\trecord = this.processAddRecord( record );\n\t\trecord = this.getRecordsFromUserIDs( [record] );\n\n\t\tif ( this.current_edit_record.start_date_stamp.indexOf( ' - ' ) > 0 ||\n\t\t\t$.type( this.current_edit_record.start_date_stamp ) === 'array' ) {\n\n\t\t\tif ( this.current_edit_record.start_date_stamp.indexOf( ' - ' ) > 0 ) {\n\t\t\t\tthis.current_edit_record.start_date_stamp = this.parserDatesRange( this.current_edit_record.start_date_stamp );\n\t\t\t}\n\n\t\t\trecord = [];\n\t\t\tfor ( var i = 0; i < this.current_edit_record.start_date_stamp.length; i++ ) {\n\t\t\t\tvar commonRecord = Global.clone( $this.current_edit_record );\n\t\t\t\tcommonRecord.start_date_stamp = this.current_edit_record.start_date_stamp[i];\n\t\t\t\tcommonRecord = this.processAddRecord( commonRecord );\n\t\t\t\trecord.push( commonRecord );\n\t\t\t}\n\t\t\trecord = this.getRecordsFromUserIDs( record );\n\t\t}\n\n\t\tthis.clearNavigationData();\n\t\tthis.api['set' + this.api.key_name]( record, false, false, ignoreWarning, {\n\t\t\tonResult: function( result ) {\n\t\t\t\tif ( $this.current_edit_record ) {\n\t\t\t\t\tvar current_date_str = $this.current_edit_record.start_date_stamp;\n\n\t\t\t\t\tif ( $.type( current_date_str ) === 'array' ) {\n\t\t\t\t\t\tcurrent_date_str = current_date_str[current_date_str.length - 1];\n\t\t\t\t\t}\n\n\t\t\t\t\tvar current_date = Global.strToDate( current_date_str );\n\t\t\t\t\tvar next_date = new Date( new Date( current_date.getTime() ).setDate( current_date.getDate() + 1 ) );\n\n\t\t\t\t\t$this.current_edit_record.start_date_stamp = next_date.format();\n\n\t\t\t\t\t$this.onSaveAndCopyResult( result );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\tonSaveAndNewClick( ignoreWarning ) {\n\t\tvar $this = this;\n\t\tif ( !Global.isSet( ignoreWarning ) ) {\n\t\t\tignoreWarning = false;\n\t\t}\n\t\tthis.setCurrentEditViewState( 'new' );\n\t\tvar record = this.current_edit_record;\n\t\trecord = this.processAddRecord( record );\n\t\trecord = this.getRecordsFromUserIDs( [record] );\n\n\t\tif ( this.current_edit_record.start_date_stamp.indexOf( ' - ' ) > 0 ||\n\t\t\t$.type( this.current_edit_record.start_date_stamp ) === 'array' ) {\n\n\t\t\tif ( this.current_edit_record.start_date_stamp.indexOf( ' - ' ) > 0 ) {\n\t\t\t\tthis.current_edit_record.start_date_stamp = this.parserDatesRange( this.current_edit_record.start_date_stamp );\n\t\t\t}\n\n\t\t\trecord = [];\n\t\t\tfor ( var i = 0; i < this.current_edit_record.start_date_stamp.length; i++ ) {\n\t\t\t\tvar commonRecord = Global.clone( $this.current_edit_record );\n\t\t\t\tcommonRecord.start_date_stamp = this.current_edit_record.start_date_stamp[i];\n\t\t\t\tcommonRecord = this.processAddRecord( commonRecord );\n\t\t\t\trecord.push( commonRecord );\n\t\t\t}\n\t\t\trecord = this.getRecordsFromUserIDs( record );\n\t\t}\n\n\t\tthis.api['set' + this.api.key_name]( record, false, ignoreWarning, {\n\t\t\tonResult: function( result ) {\n\t\t\t\t$this.onSaveAndNewResult( result );\n\t\t\t}\n\t\t} );\n\t}\n\n\tbuildSelectedCellsRecord() {\n\t\tvar $this = this;\n\t\tvar retval = [];\n\t\t$.each( this.select_cells_Array, function( index, value ) {\n\t\t\tif ( value.hasOwnProperty( 'user_id' ) && value.hasOwnProperty( 'date' ) && value.date ) {\n\t\t\t\tvar commonRecord = Global.clone( $this.current_edit_record );\n\t\t\t\tdelete commonRecord.user_ids;\n\t\t\t\tdelete commonRecord.start_dates;\n\t\t\t\tcommonRecord.id = '';\n\t\t\t\tcommonRecord.user_id = value.user_id;\n\t\t\t\tcommonRecord.start_date_stamp = value.date;\n\t\t\t\tcommonRecord = $this.buildMassAddRecord( commonRecord );\n\n\t\t\t\tretval.push( commonRecord );\n\t\t\t}\n\n\t\t} );\n\n\t\treturn retval;\n\t}\n\n\tbuildMassAddRecord( record ) {\n\t\tvar massAddArgs = this._createParametersForAdd();\n\t\tfor ( var i = 0, n = massAddArgs.length; i < n; i++ ) {\n\t\t\tvar item = massAddArgs[i];\n\t\t\tif ( record.user_id === item.user_id ) {\n\t\t\t\trecord.branch_id == '-2' ? ( record.branch_id = item.branch_id ) : record.branch_id;\n\t\t\t\trecord.department_id == '-2' ? ( record.department_id = item.department_id ) : record.department_id;\n\t\t\t\trecord.job_id == '-2' ? ( record.job_id = item.job_id ) : record.job_id;\n\t\t\t\trecord.job_item_id == '-2' ? ( record.job_item_id = item.job_item_id ) : record.job_item_id;\n\t\t\t\trecord.punch_tag_id == '-2' ? ( record.punch_tag_id = item.punch_tag_id ) : record.punch_tag_id;\n\t\t\t}\n\t\t}\n\t\treturn record;\n\t}\n\n\tprocessAddRecord( record ) {\n\t\tvar massAddArgs = this._createParametersForAdd();\n\t\tfor ( var i = 0, n = massAddArgs.length; i < n; i++ ) {\n\t\t\tvar item = massAddArgs[i];\n\t\t\trecord.branch_id == '-2' ? ( record.branch_id = item.branch_id ) : record.branch_id;\n\t\t\trecord.department_id == '-2' ? ( record.department_id = item.department_id ) : record.department_id;\n\t\t\trecord.job_id == '-2' ? ( record.job_id = item.job_id ) : record.job_id;\n\t\t\trecord.job_item_id == '-2' ? ( record.job_item_id = item.job_item_id ) : record.job_item_id;\n\t\t\trecord.punch_tag_id == '-2' ? ( record.punch_tag_id = item.punch_tag_id ) : record.punch_tag_id;\n\t\t\tbreak;\n\t\t}\n\t\treturn record;\n\t}\n\n\tgetSelectedId( record, field, massAddArgs ) {\n\t\tfor ( var i = 0, n = massAddArgs.length; i < n; i++ ) {\n\t\t\tvar item = massAddArgs[i];\n\t\t\tif ( record.user_id === item.user_id ) {\n\t\t\t\trecord[field] = item[field];\n\t\t\t}\n\t\t}\n\t}\n\n\tonSaveAndContinue( ignoreWarning ) {\n\t\tvar $this = this;\n\t\tif ( !Global.isSet( ignoreWarning ) ) {\n\t\t\tignoreWarning = false;\n\t\t}\n\t\tthis.is_changed = false;\n\t\tthis.is_add = false;\n\t\tLocalCacheData.current_doing_context_action = 'save_and_continue';\n\t\tvar record = this.current_edit_record;\n\t\trecord = this.processAddRecord( record );\n\t\trecord = this.uniformVariable( record );\n\n\t\tif ( this.current_edit_record.start_date_stamp && ( this.current_edit_record.start_date_stamp.indexOf( ' - ' ) > 0 || $.type( this.current_edit_record.start_date_stamp ) === 'array' ) ) {\n\t\t\tif ( this.current_edit_record.start_date_stamp.indexOf( ' - ' ) > 0 ) {\n\t\t\t\tthis.current_edit_record.start_date_stamp = this.parserDatesRange( this.current_edit_record.start_date_stamp );\n\t\t\t}\n\n\t\t\trecord = [];\n\t\t\tfor ( var i = 0; i < this.current_edit_record.start_date_stamp.length; i++ ) {\n\t\t\t\tvar commonRecord = Global.clone( $this.current_edit_record );\n\t\t\t\tcommonRecord.start_date_stamp = this.current_edit_record.start_date_stamp[i];\n\t\t\t\tcommonRecord = this.processAddRecord( commonRecord );\n\t\t\t\trecord.push( commonRecord );\n\t\t\t}\n\t\t\trecord = this.getRecordsFromUserIDs( record );\n\t\t} else {\n\t\t\trecord = this.getRecordsFromUserIDs( [record] );\n\t\t}\n\n\t\tthis.api['set' + this.api.key_name]( record, false, ignoreWarning, {\n\t\t\tonResult: function( result ) {\n\t\t\t\t$this.previous_absence_policy_id = false;\n\t\t\t\t$this.onSaveAndContinueResult( result );\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tonSaveClick( ignoreWarning ) {\n\t\tvar $this = this;\n\t\tvar record;\n\t\tif ( !Global.isSet( ignoreWarning ) ) {\n\t\t\tignoreWarning = false;\n\t\t}\n\t\tLocalCacheData.current_doing_context_action = 'save';\n\n\t\tif ( this.is_mass_adding ) {\n\t\t\trecord = this.buildSelectedCellsRecord();\n\t\t} else if ( this.is_mass_editing ) {\n\n\t\t\tvar checkFields = this.getChangedFields();\n\n\t\t\trecord = [];\n\n\t\t\t$.each( this.mass_edit_record_ids, function( index, value ) {\n\t\t\t\tvar commonRecord = Global.clone( checkFields );\n\t\t\t\tcommonRecord.id = value;\n\t\t\t\tcommonRecord = $this.processAddRecord( commonRecord );\n\t\t\t\trecord.push( commonRecord );\n\n\t\t\t} );\n\n\t\t\t$.each( this.select_all_shifts_array, function( index, value ) {\n\t\t\t\tif ( !value.id || value.id == TTUUID.zero_id ) {\n\t\t\t\t\tvar commonRecord = Global.clone( value );\n\t\t\t\t\tfor ( var key in checkFields ) {\n\t\t\t\t\t\tcommonRecord[key] = checkFields[key];\n\t\t\t\t\t}\n\t\t\t\t\tcommonRecord = $this.processAddRecord( commonRecord );\n\t\t\t\t\trecord.push( commonRecord );\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t} else if ( this.current_edit_record.start_date_stamp.indexOf( ' - ' ) > 0 ||\n\t\t\t$.type( this.current_edit_record.start_date_stamp ) === 'array' ) {\n\n\t\t\tif ( this.current_edit_record.start_date_stamp.indexOf( ' - ' ) > 0 ) {\n\t\t\t\tthis.current_edit_record.start_date_stamp = this.parserDatesRange( this.current_edit_record.start_date_stamp );\n\t\t\t}\n\n\t\t\trecord = [];\n\t\t\tfor ( var i = 0; i < this.current_edit_record.start_date_stamp.length; i++ ) {\n\t\t\t\tvar commonRecord = Global.clone( $this.current_edit_record );\n\t\t\t\tcommonRecord.start_date_stamp = this.current_edit_record.start_date_stamp[i];\n\t\t\t\tcommonRecord = $this.processAddRecord( commonRecord );\n\t\t\t\trecord.push( commonRecord );\n\t\t\t}\n\n\t\t\trecord = this.getRecordsFromUserIDs( record );\n\n\t\t} else {\n\n\t\t\trecord = this.current_edit_record;\n\t\t\trecord = $this.processAddRecord( record );\n\t\t\trecord = this.getRecordsFromUserIDs( [record] );\n\n\t\t}\n\n\t\tthis.api['set' + this.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//#2571 - Cannot read property 'id' of null\n\t\t\t\t\tif ( result_data === true && $this.current_edit_record ) {\n\t\t\t\t\t\t$this.refresh_id = $this.current_edit_record.id;\n\t\t\t\t\t} else if ( TTUUID.isUUID( result_data ) && result_data != TTUUID.zero_id && result_data != TTUUID.not_exist_id ) {\n\t\t\t\t\t\t$this.refresh_id = result_data;\n\t\t\t\t\t}\n\t\t\t\t\t$this.search( false, false );\n\t\t\t\t\t$this.previous_absence_policy_id = false;\n\n\t\t\t\t\t$this.removeEditView();\n\n\t\t\t\t} else {\n\t\t\t\t\t//BUG#2073 - Pulled out the error message box that was showing the result array as its \"toString\" representation. ([object][object]);\n\t\t\t\t\t$this.setErrorTips( result );\n\t\t\t\t\t$this.setErrorMenu();\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tremoveEditView() {\n\t\tsuper.removeEditView();\n\n\t\tthis.setMoveOrDropMode( this.select_drag_menu_id ? this.select_drag_menu_id : 'move' );\n\t\tthis.selected_user_ids = [];\n\t\tthis.is_mass_adding = false;\n\t}\n\n\tsetEditMenuSaveAndContinueIcon( context_btn ) {\n\t\tthis.saveAndContinueValidate( context_btn );\n\n\t\tif ( this.is_mass_editing || this.is_viewing || this.is_mass_adding || this.isMassEmployeeOrDate() ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tisMassEmployeeOrDate() {\n\n\t\tif ( this.current_edit_record && this.current_edit_record.start_date_stamps && ( this.current_edit_record.start_date_stamps.indexOf( ' - ' ) > 0 ||\n\t\t\t$.type( this.current_edit_record.start_date_stamps ) === 'array' && this.current_edit_record.start_date_stamps.length > 1\n\t\t) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( this.current_edit_record && this.current_edit_record.user_ids && this.current_edit_record.user_ids.length > 1 ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tsetEditMenuSaveAndAddIcon( context_btn ) {\n\t\tthis.saveAndNewValidate( context_btn );\n\n\t\tif ( this.is_viewing || this.is_mass_editing || 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.saveAndCopyValidate( context_btn );\n\n\t\tif ( this.is_viewing || this.is_mass_editing || this.is_mass_adding ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tonTypeChange( getRate ) {\n\t\tif ( this.current_edit_record.status_id == 20 ) {\n\t\t\tthis.attachElement( 'absence_policy_id' );\n\t\t} else {\n\t\t\tthis.detachElement( 'absence_policy_id' );\n\t\t}\n\t}\n\n\tsetEditViewData() {\n\n\t\tvar $this = this;\n\t\tsuper.setEditViewData(); //Set Navigation\n\t\t$this.onTypeChange( false );\n\t}\n\n\tcheckOpenPermission() {\n\t\tif ( Global.getProductEdition() >= 15 && PermissionManager.validate( 'schedule', 'view_open' ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tgetCustomFieldReferenceField() {\n\t\treturn 'note';\n\t}\n\n\tbuildEditViewUI() {\n\n\t\tvar $this = this;\n\n\t\tvar form_item_input;\n\t\tvar widgetContainer;\n\n\t\t// #VueContextMenu# After we add the edit_view to the page in initEditViewUI(), add the context menu (Vue needs a valid id in dom)\n\t\tif( ContextMenuManager.getMenu( this.determineContextMenuMountAttributes().id ) === undefined ) {\n\t\t\tthis.buildContextMenu();\n\t\t} else {\n\t\t\tDebug.Warn( 'Context Menu ('+ this.determineContextMenuMountAttributes().id +') already exists for: '+ this.viewId, 'ScheduleViewController.js', 'ScheduleViewController', 'buildEditViewUI', 10 );\n\t\t}\n\n\t\tthis.edit_view_close_icon = this.edit_view.find( '.close-icon' );\n\t\tthis.edit_view_close_icon.hide();\n\t\tthis.edit_view_close_icon.click( function() {\n\t\t\t$this.onCloseIconClick();\n\t\t} );\n\n\t\tvar tab_model = {\n\t\t\t'tab_schedule': { 'label': $.i18n._( 'Schedule' ) },\n\t\t\t'tab_audit': true,\n\t\t};\n\t\tthis.setTabModel( tab_model );\n\n\t\t//Tab 0 start\n\n\t\tvar tab_schedule = this.edit_view_tab.find( '#tab_schedule' );\n\n\t\tvar tab_schedule_column1 = tab_schedule.find( '.first-column' );\n\n\t\t//Employee\n\n\t\tvar production_edition_id = Global.getProductEdition();\n\t\tform_item_input = Global.loadWidgetByName( FormItemType.AWESOME_BOX );\n\t\tform_item_input.AComboBox( {\n\t\t\tapi_class: TTAPI.APIUser,\n\t\t\tallow_multiple_selection: false,\n\t\t\tlayout_name: 'global_user',\n\t\t\tshow_search_inputs: true,\n\t\t\tset_empty: !this.checkOpenPermission(),\n\t\t\tset_open: this.checkOpenPermission(),\n\t\t\tfield: 'user_id'\n\t\t} );\n\n\t\tvar default_args = {};\n\t\tdefault_args.permission_section = 'schedule';\n\t\tform_item_input.setDefaultArgs( default_args );\n\n\t\tthis.addEditFieldToColumn( $.i18n._( 'Employee' ), form_item_input, tab_schedule_column1, '', null, true );\n\n\t\t//Mass Add Employees\n\n\t\tform_item_input = Global.loadWidgetByName( FormItemType.AWESOME_BOX );\n\t\tform_item_input.AComboBox( {\n\t\t\tapi_class: TTAPI.APIUser,\n\t\t\tallow_multiple_selection: true,\n\t\t\tlayout_name: 'global_user',\n\t\t\tshow_search_inputs: true,\n\t\t\tset_empty: !this.checkOpenPermission(),\n\t\t\tset_open: this.checkOpenPermission(),\n\t\t\taddition_source_function: ( function( target, source_data ) {\n\t\t\t\treturn $this.onEmployeeSourceCreate( target, source_data );\n\t\t\t} ),\n\t\t\tfield: 'user_ids'\n\t\t} );\n\n\t\tdefault_args = {};\n\t\tdefault_args.permission_section = 'schedule';\n\t\tform_item_input.setDefaultArgs( default_args );\n\n\t\tthis.addEditFieldToColumn( $.i18n._( 'Employee' ), form_item_input, tab_schedule_column1, '', null, true );\n\n\t\t//Status\n\t\tform_item_input = Global.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( $.i18n._( 'Status' ), form_item_input, tab_schedule_column1 );\n\n\t\t//Absence Policy\n\t\tform_item_input = Global.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: '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( $.i18n._( 'Absence Policy' ), form_item_input, tab_schedule_column1, '', null, true );\n\n\t\t//Available Balance\n\t\tform_item_input = Global.loadWidgetByName( FormItemType.TEXT );\n\t\tform_item_input.TText( { field: 'available_balance' } );\n\n\t\twidgetContainer = $( '<div class=\\'widget-h-box available-balance-h-box\\'></div>' );\n\t\tthis.available_balance_info = $( '<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( $.i18n._( 'Available Balance' ), form_item_input, tab_schedule_column1, '', widgetContainer, true );\n\n\t\tif ( !this.current_edit_record || ( this.current_edit_record.user_ids && this.current_edit_record.user_ids.length > 1 ) ) {\n\t\t\tthis.detachElement( 'available_balance' );\n\t\t}\n\n\t\t//Date\n\t\tform_item_input = Global.loadWidgetByName( FormItemType.DATE_PICKER );\n\n\t\tform_item_input.TDatePicker( { field: 'start_date_stamp', validation_field: 'date_stamp' } );\n\n\t\tthis.addEditFieldToColumn( $.i18n._( 'Date' ), form_item_input, tab_schedule_column1, '', null, true );\n\n\t\t//Dates\n\t\tform_item_input = Global.loadWidgetByName( FormItemType.DATE_PICKER );\n\n\t\tform_item_input.TRangePicker( { field: 'start_date_stamps' } );\n\n\t\tthis.addEditFieldToColumn( $.i18n._( 'Date' ), form_item_input, tab_schedule_column1, '', null, true );\n\n\t\t//Mass Add Date\n\t\tform_item_input = Global.loadWidgetByName( FormItemType.AWESOME_BOX );\n\n\t\tform_item_input.AComboBox( {\n\t\t\tallow_multiple_selection: true,\n\t\t\tlayout_name: 'global_option_column',\n\t\t\tshow_search_inputs: false,\n\t\t\tset_empty: true,\n\t\t\tfield: 'start_dates'\n\t\t} );\n\n\t\tthis.addEditFieldToColumn( $.i18n._( 'Date' ), form_item_input, tab_schedule_column1, '', null, true );\n\n\t\t//Start Time\n\t\tform_item_input = Global.loadWidgetByName( FormItemType.TIME_PICKER );\n\t\tform_item_input.TTimePicker( { field: 'start_time' } );\n\n\t\tthis.addEditFieldToColumn( $.i18n._( 'In' ), form_item_input, tab_schedule_column1, '', null, true );\n\n\t\t//End Time\n\t\tform_item_input = Global.loadWidgetByName( FormItemType.TIME_PICKER );\n\t\tform_item_input.TTimePicker( { field: 'end_time' } );\n\n\t\tthis.addEditFieldToColumn( $.i18n._( 'Out' ), form_item_input, tab_schedule_column1, '', null, true );\n\n\t\t//Total\n\t\tform_item_input = Global.loadWidgetByName( FormItemType.TEXT );\n\t\tform_item_input.TText( { field: 'total_time' } );\n\t\tform_item_input.css( 'cursor', 'pointer' );\n\t\tthis.addEditFieldToColumn( $.i18n._( 'Total' ), form_item_input, tab_schedule_column1 );\n\n\t\t//Schedule Policy\n\t\tform_item_input = Global.loadWidgetByName( FormItemType.AWESOME_BOX );\n\n\t\tform_item_input.AComboBox( {\n\t\t\tapi_class: TTAPI.APISchedulePolicy,\n\t\t\tallow_multiple_selection: false,\n\t\t\tlayout_name: 'global_schedule',\n\t\t\tshow_search_inputs: true,\n\t\t\tset_empty: true,\n\t\t\tfield: 'schedule_policy_id'\n\t\t} );\n\t\tthis.addEditFieldToColumn( $.i18n._( 'Schedule Policy' ), form_item_input, tab_schedule_column1 );\n\n\t\t//Default Branch\n\t\tform_item_input = Global.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\taddition_source_function: ( function( target, source_data ) {\n\t\t\t\treturn $this.onSourceDataCreate( target, source_data );\n\t\t\t} ),\n\t\t\t//FIXME: Follow -2 to the API do not switch to UUID unless absolutely necessary?\n\t\t\tadded_items: [\n\t\t\t\t{ value: TTUUID.not_exist_id, label: Global.default_item },\n\t\t\t\t{ value: '-2', label: Global.selected_item }\n\t\t\t]\n\t\t} );\n\t\tthis.addEditFieldToColumn( $.i18n._( 'Branch' ), form_item_input, tab_schedule_column1, '', null, true );\n\n\t\tif ( !this.show_branch_ui ) {\n\t\t\tthis.detachElement( 'branch_id' );\n\n\t\t}\n\n\t\t//Department\n\t\tform_item_input = Global.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\taddition_source_function: ( function( target, source_data ) {\n\t\t\t\treturn $this.onSourceDataCreate( target, source_data );\n\t\t\t} ),\n\t\t\tadded_items: [\n\t\t\t\t{ value: TTUUID.not_exist_id, label: Global.default_item },\n\t\t\t\t{ value: '-2', label: Global.selected_item }\n\t\t\t]\n\t\t} );\n\t\tthis.addEditFieldToColumn( $.i18n._( 'Department' ), form_item_input, tab_schedule_column1, '', null, true );\n\n\t\tif ( !this.show_department_ui ) {\n\t\t\tthis.detachElement( 'department_id' );\n\n\t\t}\n\n\t\tif ( Global.getProductEdition() >= 20 ) {\n\t\t\t//Job\n\t\t\tform_item_input = Global.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\taddition_source_function: ( function( target, source_data ) {\n\t\t\t\t\treturn $this.onSourceDataCreate( target, source_data );\n\t\t\t\t} ),\n\t\t\t\tadded_items: [\n\t\t\t\t\t{ value: TTUUID.not_exist_id, label: Global.default_item },\n\t\t\t\t\t{ value: '-2', label: Global.selected_item }\n\t\t\t\t]\n\t\t\t} );\n\n\t\t\twidgetContainer = $( '<div class=\\'widget-h-box\\'></div>' );\n\n\t\t\tvar job_coder = Global.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( $.i18n._( 'Job' ), [form_item_input, job_coder], tab_schedule_column1, '', widgetContainer, true );\n\n\t\t\tif ( !this.show_job_ui ) {\n\t\t\t\tthis.detachElement( 'job_id' );\n\t\t\t}\n\n\t\t\t//Job Item\n\t\t\tform_item_input = Global.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\taddition_source_function: ( function( target, source_data ) {\n\t\t\t\t\treturn $this.onSourceDataCreate( target, source_data );\n\t\t\t\t} ),\n\t\t\t\tadded_items: [\n\t\t\t\t\t{ value: TTUUID.not_exist_id, label: Global.default_item },\n\t\t\t\t\t{ value: '-2', label: Global.selected_item }\n\t\t\t\t]\n\t\t\t} );\n\n\t\t\twidgetContainer = $( '<div class=\\'widget-h-box\\'></div>' );\n\n\t\t\tvar job_item_coder = Global.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( $.i18n._( 'Task' ), [form_item_input, job_item_coder], tab_schedule_column1, '', widgetContainer, true );\n\n\t\t\tif ( !this.show_job_item_ui ) {\n\t\t\t\tthis.detachElement( 'job_item_id' );\n\t\t\t}\n\n\t\t\t//Punch Tag\n\t\t\tform_item_input = Global.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\taddition_source_function: ( function( target, source_data ) {\n\t\t\t\t\treturn $this.onSourceDataCreatePunchTag( target, source_data );\n\t\t\t\t} ),\n\t\t\t\tadded_items: [\n\t\t\t\t\t{ value: TTUUID.not_exist_id, label: Global.default_item }\n\t\t\t\t]\n\t\t\t} );\n\n\t\t\twidgetContainer = $( '<div class=\\'widget-h-box\\'></div>' );\n\n\t\t\tvar punch_tag_coder = Global.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( $.i18n._( 'Tags' ), [form_item_input, punch_tag_coder], tab_schedule_column1, '', widgetContainer, true );\n\n\n\t\t\tif ( !this.show_punch_tag_ui ) {\n\t\t\t\tthis.detachElement( 'punch_tag_id' );\n\t\t\t}\n\t\t}\n\n\t\t//Note\n\t\tform_item_input = Global.loadWidgetByName( FormItemType.TEXT_AREA );\n\t\tform_item_input.TTextArea( { field: 'note', width: '100%' } );\n\t\tthis.addEditFieldToColumn( $.i18n._( 'Note' ), form_item_input, tab_schedule_column1, '', null, null, true );\n\t\tform_item_input.parent().width( '45%' );\n\n\t\tif ( Global.getProductEdition() >= 15 && this.is_viewing == false ) {\n\t\t\t//Notify Employee\n\t\t\tform_item_input = Global.loadWidgetByName( FormItemType.CHECKBOX );\n\t\t\tform_item_input.TCheckbox( { field: 'notify_user_schedule_change' } );\n\t\t\tthis.addEditFieldToColumn( $.i18n._( 'Notify Employee' ), form_item_input, tab_schedule_column1, '', null, true );\n\t\t}\n\n\t\tTTPromise.resolve( 'Schedule', 'init' );\n\t}\n\n\tsetDefaultMenuDeleteIcon( context_btn, grid_selected_length ) {\n\t\tif ( !this.deletePermissionValidate( 'schedule' ) || 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 > 0 && this.deleteOwnerOrChildPermissionValidate( 'schedule' ) ) {\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\tonAvailableBalanceChange() {\n\t\tif ( this.current_edit_record.status_id == 20\n\t\t\t&& this.current_edit_record.hasOwnProperty( 'absence_policy_id' )\n\t\t\t&& this.current_edit_record.absence_policy_id && !this.is_mass_editing ) {\n\t\t\tthis.getAvailableBalance();\n\t\t} else {\n\t\t\tthis.detachElement( 'available_balance' );\n\t\t}\n\t}\n\n\tparserDatesRange( date ) {\n\t\tvar dates = date.split( ' - ' );\n\t\tvar resultArray = [];\n\t\tvar beginDate = Global.strToDate( dates[0] );\n\t\tvar endDate = Global.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\tgetSelectUsersArray() {\n\t\tvar result = [];\n\t\tvar cells_array = this.select_cells_Array;\n\t\tvar len = cells_array.length;\n\t\tvar date_dic = {};\n\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar item = cells_array[i];\n\n\t\t\t// If select empty cell with no user inside, set user_id to 0 as OPEN\n\t\t\tif ( !item.user_id ) {\n\t\t\t\titem.user_id = TTUUID.zero_id;\n\t\t\t}\n\n\t\t\tdate_dic[item.user_id] = 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.push( this.getDefaultUser() );\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tgetSelectDateArray() {\n\t\tvar result = [];\n\n\t\tvar 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\n\t\t\tif ( item.date ) {\n\t\t\t\tdate_dic[item.date] = true;\n\t\t\t}\n\n\t\t}\n\n\t\tfor ( var key in date_dic ) {\n\t\t\tresult.push( key );\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tgetAvailableBalance() {\n\t\tvar $this = this;\n\t\tvar user_id = this.current_edit_record.user_id;\n\t\tvar total_time = this.current_edit_record.total_time;\n\t\tvar last_date_stamp = this.current_edit_record.start_date_stamp;\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.absence_policy_id;\n\t\t}\n\n\t\t//For mass adding case, select multiple cells and click new\n\t\tif ( this.is_mass_adding ) {\n\t\t\tif ( this.current_edit_record.user_ids.length > 1 ) {\n\t\t\t\tthis.detachElement( 'available_balance' );\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tuser_id = this.current_edit_record.user_ids[0];\n\t\t\t\tif ( !user_id ) {\n\t\t\t\t\tthis.detachElement( 'available_balance' );\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttotal_time = total_time * this.current_edit_record.start_dates.length;\n\t\t\tlast_date_stamp = this.current_edit_record.start_dates[this.current_edit_record.start_dates.length - 1];\n\t\t} else {\n\t\t\t//get dates from date ranger\n\t\t\tif ( last_date_stamp.indexOf( ' - ' ) > 0 || $.type( last_date_stamp ) === 'array' ) {\n\t\t\t\tif ( last_date_stamp.indexOf( ' - ' ) > 0 ) {\n\t\t\t\t\tlast_date_stamp = this.parserDatesRange( last_date_stamp );\n\t\t\t\t}\n\n\t\t\t\tif ( last_date_stamp.length > 0 ) {\n\t\t\t\t\ttotal_time = total_time * last_date_stamp.length;\n\t\t\t\t\tlast_date_stamp = last_date_stamp[last_date_stamp.length - 1];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( ( !this.current_edit_record || !this.current_edit_record.id || this.current_edit_record.id == TTUUID.zero_id ) && !this.is_mass_editing ) {\n\t\t\t\tif ( this.current_edit_record.user_ids.length < 1 || this.current_edit_record.user_ids.length > 1 ) {\n\t\t\t\t\tthis.detachElement( 'available_balance' );\n\t\t\t\t\treturn;\n\t\t\t\t} else {\n\t\t\t\t\tuser_id = this.current_edit_record.user_ids[0];\n\t\t\t\t\tif ( !user_id ) {\n\t\t\t\t\t\tthis.detachElement( 'available_balance' );\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//Check if the user is editing a existing record that was originally Status=Working, and changing it to Status=Absent, in that case we can't adjust for the existing total time and must clear it out.\n\t\tif ( this.current_edit_record && this.current_edit_record.id && this.prev_status_id == 10 && this.edit_view_ui_dic['status_id'].getValue() == 20 ) {\n\t\t\tthis.prev_total_time = 0;\n\t\t}\n\n\t\tif ( this.current_edit_record.absence_policy_id != TTUUID.zero_id ) {\n\t\t\tthis.api_absence_policy.getProjectedAbsencePolicyBalance(\n\t\t\t\tthis.current_edit_record.absence_policy_id,\n\t\t\t\tuser_id,\n\t\t\t\tlast_date_stamp,\n\t\t\t\ttotal_time,\n\t\t\t\tthis.prev_total_time,\n\t\t\t\tthis.previous_absence_policy_id, {\n\t\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t\t$this.getBalanceHandler( result, last_date_stamp );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t} else {\n\t\t\tthis.getBalanceHandler( false, last_date_stamp );\n\t\t}\n\t}\n\n\tbuildSearchAndLayoutUI() {\n\t\tvar layout_div = this.search_panel.find( 'div #saved_layout_content_div' );\n\n\t\t//Display Columns\n\n\t\tvar form_item = $( $.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\tthis.column_selector = Global.loadWidgetByName( FormItemType.AWESOME_DROPDOWN );\n\n\t\tthis.column_selector = this.column_selector.ADropDown( {\n\t\t\tdisplay_show_all: false,\n\t\t\tid: 'column_selector',\n\t\t\tkey: 'value',\n\t\t\tallow_drag_to_order: true,\n\t\t\tdisplay_close_btn: false,\n\t\t\tdisplay_column_settings: false,\n\t\t\tstatic_height: 150\n\t\t} );\n\n\t\tform_item_label.text( $.i18n._( 'Display Columns' ) );\n\t\tform_item_input_div.append( this.column_selector );\n\n\t\tlayout_div.append( form_item );\n\n\t\tlayout_div.append( '<div class=\\'clear-both-div\\'></div>' );\n\n\t\tthis.column_selector.setColumns( [\n\t\t\t{ name: 'label', index: 'label', label: $.i18n._( 'Column Name' ), width: 100, sortable: false }\n\t\t] );\n\n\t\t//Save and update layout\n\n\t\tform_item = $( $.fn.SearchPanel.html.form_item );\n\t\tform_item_label = form_item.find( '.form-item-label' );\n\t\tform_item_input_div = form_item.find( '.form-item-input-div' );\n\n\t\tform_item_label.text( $.i18n._( 'Save Search As' ) );\n\n\t\tthis.save_search_as_input = Global.loadWidgetByName( FormItemType.TEXT_INPUT );\n\t\tthis.save_search_as_input.TTextInput();\n\n\t\tvar save_btn = $( '<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\">' + $.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 = $( '<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 = $( '<span style=\\'margin-left: 5px\\' >' + $.i18n._( 'Previous Saved Searches' ) + ':</span>' );\n\t\tthis.previous_saved_layout_div.append( form_item_label );\n\n\t\tthis.previous_saved_layout_selector = $( '<select style=\\'margin-left: 5px\\' class=\\'t-select\\'>' );\n\t\tvar update_btn = $( '<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\">' + $.i18n._( 'Update' ) + '</span>\\n' +\n\t\t\t'</button>' );\n\n\t\tvar del_btn = $( '<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\">' + $.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\tsetCurrentEditRecordData() {\n\t\tvar $this = this;\n\t\tif ( this.is_mass_adding ) {\n\t\t\tthis.attachElement( 'start_dates' );\n\t\t\tthis.detachElement( 'start_date_stamp' );\n\t\t\tthis.detachElement( 'start_date_stamps' );\n\n\t\t\tthis.attachElement( 'user_ids' );\n\t\t\tthis.detachElement( 'user_id' );\n\n\t\t\tthis.edit_view_ui_dic.start_dates.setEnabled( false );\n\t\t\tthis.edit_view_ui_dic.user_ids.setEnabled( false );\n\n\t\t} else {\n\t\t\tthis.detachElement( 'start_dates' );\n\n\t\t\tif ( ( this.current_edit_record.id && this.current_edit_record.id != TTUUID.zero_id ) || this.is_mass_editing ) {\n\t\t\t\tthis.attachElement( 'start_date_stamp' );\n\t\t\t\tthis.detachElement( 'start_date_stamps' );\n\t\t\t\tthis.detachElement( 'user_ids' );\n\t\t\t\tthis.attachElement( 'user_id' );\n\n\t\t\t} else {\n\t\t\t\tthis.attachElement( 'start_date_stamps' );\n\t\t\t\tthis.detachElement( 'start_date_stamp' );\n\t\t\t\tthis.current_edit_record.start_date_stamps = this.current_edit_record.start_date_stamp;\n\n\t\t\t\tthis.attachElement( 'user_ids' );\n\t\t\t\tthis.detachElement( 'user_id' );\n\t\t\t}\n\n\t\t}\n\n\t\tthis.prev_total_time = 0;\n\n\t\t//When editing an existing record, store the original status_id so we can later use it when calculating available balance.\n\t\tif ( this.current_edit_record.id && this.current_edit_record.id != TTUUID.zero_id ) {\n\t\t\tthis.prev_status_id = this.current_edit_record['status_id'];\n\t\t}\n\n\t\t//Set current edit record data to all widgets\n\t\tfor ( var key in this.current_edit_record ) {\n\t\t\tvar widget = this.edit_view_ui_dic[key];\n\t\t\tif ( Global.isSet( widget ) ) {\n\t\t\t\tswitch ( key ) {\n\t\t\t\t\tcase 'user_ids':\n\t\t\t\t\t\tif ( widget.is( ':visible' ) ) {\n\t\t\t\t\t\t\tvar user_array = this.getSelectUsersArray();\n\t\t\t\t\t\t\tthis.current_edit_record[key] = user_array;\n\t\t\t\t\t\t\twidget.setValue( user_array );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'start_dates':\n\t\t\t\t\t\tvar date_array = this.getSelectDateArray();\n\t\t\t\t\t\tthis.current_edit_record[key] = date_array;\n\t\t\t\t\t\tdate_array = Global.buildRecordArray( date_array );\n\n\t\t\t\t\t\twidget.setSourceData( date_array );\n\t\t\t\t\t\twidget.setValue( date_array );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'total_time':\n\t\t\t\t\t\t//Don't set when copy as new\n\t\t\t\t\t\tif ( this.current_edit_record.id && this.current_edit_record.id != TTUUID.zero_id ) {\n\t\t\t\t\t\t\tthis.prev_total_time = this.current_edit_record[key];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar startTime = this.current_edit_record['date_stamp'] + ' ' + this.current_edit_record['start_time'];\n\t\t\t\t\t\tvar endTime = this.current_edit_record['date_stamp'] + ' ' + this.current_edit_record['end_time'];\n\t\t\t\t\t\tvar schedulePolicyId = this.current_edit_record['schedule_policy_id'];\n\t\t\t\t\t\tvar user_id = this.current_edit_record.user_id;\n\t\t\t\t\t\tvar total_time = this.api.getScheduleTotalTime( startTime, endTime, schedulePolicyId, user_id, { async: false } );\n\t\t\t\t\t\t// Error: Uncaught TypeError: Cannot read property 'getResult' of undefined in interface/html5/#!m=Schedule&date=20160201&mode=week&a=new&tab=Schedule\n\t\t\t\t\t\ttotal_time ? ( total_time = total_time.getResult() ) : total_time = false;\n\t\t\t\t\t\tthis.current_edit_record.total_time = total_time;\n\t\t\t\t\t\twidget.setValue( Global.getTimeUnit( total_time ) );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'job_id':\n\t\t\t\t\t\tif ( Global.getProductEdition() >= 20 ) {\n\t\t\t\t\t\t\tvar user_id = false;\n\t\t\t\t\t\t\tif ( this.edit_view_ui_dic['user_ids'] && this.edit_view_ui_dic['user_ids'].is( ':visible' ) ) {\n\t\t\t\t\t\t\t\tuser_id = this.getSelectUsersArray();\n\n\t\t\t\t\t\t\t\t//If more than one user is selected, don't filter by user_id at all, show all jobs and let the validation system handle it.\n\t\t\t\t\t\t\t\tif ( user_id.length == 1 ) {\n\t\t\t\t\t\t\t\t\tuser_id = user_id[0];\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tuser_id = false;\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\tuser_id = this.current_edit_record['user_id'];\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar args = {};\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: 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.getProductEdition() >= 20 ) {\n\t\t\t\t\t\t\tvar args = {};\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.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.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.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 'punch_tag_quick_search':\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'job_quick_search':\n//\t\t\t\t\t\twidget.setValue( this.current_edit_record['job_id'] ? this.current_edit_record['job_id'] : 0 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'job_item_quick_search':\n//\t\t\t\t\t\twidget.setValue( this.current_edit_record['job_item_id'] ? this.current_edit_record['job_item_id'] : 0 );\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\tthis.onAvailableBalanceChange();\n\t\tthis.setEditViewDataDone();\n\t}\n\n\tsetAbsencePolicyFilter( filter ) {\n\t\tif ( !filter.filter_data ) {\n\t\t\tfilter.filter_data = {};\n\t\t}\n\n\t\tif ( !this.is_mass_editing ) {\n\n\t\t\tif ( !this.current_edit_record || !this.current_edit_record.id || this.current_edit_record.id == TTUUID.zero_id ) {\n\t\t\t\tfilter.filter_data.user_id = this.current_edit_record.user_ids;\n\t\t\t} else {\n\t\t\t\tfilter.filter_data.user_id = this.current_edit_record.user_id;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tif ( this.edit_view_ui_dic.user_id.isChecked() ) {\n\t\t\t\tfilter.filter_data.user_id = this.current_edit_record.user_id;\n\t\t\t} else {\n\t\t\t\tfilter.filter_data.user_id = this.selected_user_ids;\n\t\t\t}\n\n\t\t}\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\tsetDefaultMenuCopyIcon( context_btn, grid_selected_length ) {\n\t\tif ( !this.copyPermissionValidate() ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( grid_selected_length >= 1 ) {\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\tsetDefaultMenuCopyAsNewIcon( context_btn, grid_selected_length ) {\n\t\tif ( ( !this.copyAsNewPermissionValidate() ) ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( grid_selected_length === 1 ) {\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\n\tsetCustomEditMenuIcon( id, context_btn ) {\n\t\tswitch ( id ) {\n\t\t\tcase 'import_icon':\n\t\t\t\tthis.setEditMenuImportIcon( context_btn );\n\t\t\t\tbreak;\n\t\t\tcase 'AutoPunch':\n\t\t\t\tthis.setEditMenuAutoPunchIcon( context_btn );\n\t\t\t\tbreak;\n\t\t\tcase 'AddRequest':\n\t\t\t\tthis.setEditMenuAddRequestIcon( context_btn );\n\t\t\t\tbreak;\n\t\t\tcase 'find_available':\n\t\t\t\tthis.setEditMenuFindAvailableIcon( context_btn );\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t_getGridSelectedLength() {\n\t\tvar result = 0;\n\t\tresult = this.select_all_shifts_array.length;\n\n\t\treturn result;\n\t}\n\n\tsetCustomDefaultMenuIcon( id, context_btn, grid_selected_length ) {\n\t\tswitch ( id ) {\n\t\t\tcase 'move':\n\t\t\t\tif ( !this.movePermissionValidate() ) {\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 'drag_copy':\n\t\t\t\tif ( !this.copyPermissionValidate() ) {\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 'swap':\n\t\t\t\tif ( !this.editPermissionValidate() ) {\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 'override':\n\t\t\t\tif ( ( !this.editPermissionValidate() && !this.movePermissionValidate() && !this.copyPermissionValidate() ) ) {\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 'edit_employee':\n\t\t\t\tthis.setDefaultMenuEditEmployeeIcon( context_btn, grid_selected_length );\n\t\t\t\tbreak;\n\t\t\tcase 'import_icon':\n\t\t\t\tthis.setDefaultMenuImportIcon( context_btn, grid_selected_length );\n\t\t\t\tbreak;\n\t\t\tcase 'timesheet':\n\t\t\t\tthis.setDefaultMenuEditTimesheetIcon( context_btn, grid_selected_length );\n\t\t\t\tbreak;\n\t\t\tcase 'find_available':\n\t\t\t\tthis.setDefaultMenuFindAvailabletIcon( context_btn, grid_selected_length );\n\t\t\t\tbreak;\n\t\t\tcase 'AutoPunch':\n\t\t\t\tthis.setAutoPunchIcon( context_btn, grid_selected_length );\n\t\t\t\tbreak;\n\t\t\tcase 'AddRequest':\n\t\t\t\tthis.setAddRequestIcon( context_btn, grid_selected_length );\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tsetDefaultMenu( doNotSetFocus ) {\n\t\t//Schedule uses a different grid than other views and needs \"select_all_shifts_array.length\" instesd of \"this.getGridSelectIdArray()\" for grid_selected_length\n\t\tsuper.setDefaultMenu( doNotSetFocus, this._getGridSelectedLength() );\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\tenableAddRequestButton() {\n\t\tvar schedules = [];\n\t\t//var grid_selected_id_array = this.getGridSelectIdArray();\n\t\tif ( !this.select_cellls_and_shifts_array ) {\n\t\t\treturn false;\n\t\t}\n\t\tvar grid_selected_id_array = this.select_cellls_and_shifts_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\tif ( grid_selected_length == 0 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar schedules = this.select_cells_Array;\n\t\tvar first = schedules[0];\n\n\t\tfor ( var n = 1; n < schedules.length; n++ ) {\n\t\t\tif ( schedules[n].user_id && first.user_id != schedules[n].user_id ) {\n\t\t\t\tDebug.Text( 'mismatch on user_id', 'ScheduleViewController.js', 'ScheduleViewController', 'enableAddRequestButton', 10 );\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t//do not test blank cells beyond user_id\n\t\t\tif ( schedules[n].shift == undefined ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( ( first.shift && schedules[n].shift ) ) {\n\t\t\t\tif ( first.shift.start_time != schedules[n].shift.start_time ) {\n\t\t\t\t\tDebug.Text( 'mismatch on start_time', 'ScheduleViewController.js', 'ScheduleViewController', 'enableAddRequestButton', 10 );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif ( first.shift.end_time != schedules[n].shift.end_time ) {\n\t\t\t\t\tDebug.Text( 'mismatch on end_time', 'ScheduleViewController.js', 'ScheduleViewController', 'enableAddRequestButton', 10 );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif ( first.shift.branch_id != schedules[n].shift.branch_id ) {\n\t\t\t\t\tDebug.Text( 'mismatch on branch_id', 'ScheduleViewController.js', 'ScheduleViewController', 'enableAddRequestButton', 10 );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif ( first.shift.department_id != schedules[n].shift.department_id ) {\n\t\t\t\t\tDebug.Text( 'mismatch on department_id', 'ScheduleViewController.js', 'ScheduleViewController', 'enableAddRequestButton', 10 );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif ( first.shift.job_id != schedules[n].shift.job_id ) {\n\t\t\t\t\tDebug.Text( 'mismatch on job_id', 'ScheduleViewController.js', 'ScheduleViewController', 'enableAddRequestButton', 10 );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif ( first.shift.job_item_id != schedules[n].shift.job_item_id ) {\n\t\t\t\t\tDebug.Text( 'mismatch on job_item_id', 'ScheduleViewController.js', 'ScheduleViewController', 'enableAddRequestButton', 10 );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif ( first.shift.punch_tag_id != schedules[n].shift.punch_tag_id ) {\n\t\t\t\t\tDebug.Text( 'mismatch on punch_tag_id', 'ScheduleViewController.js', 'ScheduleViewController', 'enableAddRequestButton', 10 );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tif ( first.shift.schedule_policy_id != schedules[n].shift.schedule_policy_id ) {\n\t\t\t\t\tDebug.Text( 'mismatch on schedule_policy_id', 'ScheduleViewController.js', 'ScheduleViewController', 'enableAddRequestButton', 10 );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tif ( first.shift.status_id != schedules[n].shift.status_id ) {\n\t\t\t\t\tDebug.Text( 'mismatch on status_id', 'ScheduleViewController.js', 'ScheduleViewController', 'enableAddRequestButton', 10 );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif ( first.shift.status_id == 20 && first.shift.absence_policy_id != schedules[n].shift.absence_policy_id ) {\n\t\t\t\t\tDebug.Text( 'mismatch on absence_policy_id', 'ScheduleViewController.js', 'ScheduleViewController', 'enableAddRequestButton', 10 );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t//if the first one is a blank in a selection that includes shifts, we need to update the compared record to one with a shift.\n\t\t\t} else if ( first.shift == undefined && schedules[n].shift ) {\n\t\t\t\tfirst = schedules[n];\n\t\t\t}\n\t\t}\n\n\t\tDebug.Text( 'All Selected Schedules Match', 'ScheduleViewController.js', 'ScheduleViewController', 'enableAddRequestButton', 10 );\n\t\treturn true;\n\t}\n\n\tsetAutoPunchIcon( context_btn, grid_selected_length ) {\n\t\tif ( grid_selected_length > 0 ) {\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\tsetEditMenuAutoPunchIcon( context_btn, grid_selected_length ) {\n\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t}\n\n\tsetEditMenuAddRequestIcon( context_btn, grid_selected_length ) {\n\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t}\n\n\tsetEditMenuFindAvailableIcon( context_btn, grid_selected_length ) {\n\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t}\n\n\tsetDefaultMenuFindAvailabletIcon( context_btn, grid_selected_length ) {\n\t\tif ( !this.editChildPermissionValidate() ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( grid_selected_length >= 1 ) {\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\tsetDefaultMenuEditTimesheetIcon( context_btn, grid_selected_length ) {\n\n\t\tif ( this.select_cells_Array.length === 1 && TTUUID.isUUID( this.select_cells_Array[0].user_id ) && this.select_cells_Array[0].user_id != TTUUID.zero_id ) {\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\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\n\t\tif ( this.select_cells_Array.length === 1 && TTUUID.isUUID( this.select_cells_Array[0].user_id ) && this.select_cells_Array[0].user_id != TTUUID.zero_id ) {\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\tonUpdateLayout() {\n\n\t\tvar selectId = $( this.previous_saved_layout_selector ).children( 'option:selected' ).attr( 'value' );\n\t\tvar layout_name = $( this.previous_saved_layout_selector ).children( 'option:selected' ).text();\n\n\t\tvar selected_display_columns = this.getSearchPanelDisplayColumns();\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.display_columns = selected_display_columns;\n\t\targs.data.filter_data = filter_data;\n\t\targs.data.mode = Global.upCaseFirstLetter( this.getMode() );\n\t\targs.data.strictRange = this.settings_menu.getButton( 'strict_range_btn' ).active;\n\t\targs.data.weeklyTotals = this.settings_menu.getButton( 'weekly_totals_btn' ).active;\n\t\targs.data.dailyTotals = this.settings_menu.getButton( 'daily_totals_btn' ).active;\n\t\targs.data.showAllEmp = this.settings_menu.getButton( 'all_employee_btn' ).active;\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\tonSaveNewLayout( default_layout_name ) {\n\n\t\tif ( Global.isSet( default_layout_name ) ) {\n\t\t\tvar layout_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 selected_display_columns = this.getSearchPanelDisplayColumns();\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.display_columns = selected_display_columns;\n\t\targs.data.filter_data = filter_data;\n\t\targs.data.mode = Global.upCaseFirstLetter( this.getMode() );\n\t\targs.data.strictRange = this.settings_menu.getButton( 'strict_range_btn' ).active;\n\t\targs.data.weeklyTotals = this.settings_menu.getButton( 'weekly_totals_btn' ).active;\n\t\targs.data.dailyTotals = this.settings_menu.getButton( 'daily_totals_btn' ).active;\n\t\targs.data.showAllEmp = this.settings_menu.getButton( 'all_employee_btn' ).active;\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\tonClearSearch() {\n\t\tvar do_update = false;\n\t\tif ( this.search_panel.getLayoutsArray() && this.search_panel.getLayoutsArray().length > 0 ) {\n\t\t\tvar default_layout_id = $( 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\tthis.column_selector.setSelectGridData( this.default_display_columns );\n\n\t\t\tthis.onSaveNewLayout( BaseViewController.default_layout_name );\n\t\t\treturn;\n\n\t\t}\n\n\t\tvar selected_display_columns = this.getSearchPanelDisplayColumns();\n\t\tvar filter_data = this.getValidSearchFilter();\n\n\t\tif ( do_update ) {\n\t\t\tvar args = {};\n\t\t\targs.id = default_layout_id;\n\t\t\targs.data = {};\n\t\t\targs.data.display_columns = selected_display_columns;\n\t\t\targs.data.filter_data = filter_data;\n\t\t}\n\n\t\targs.data.mode = this.getMode();\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\tgetSearchPanelDisplayColumns() {\n\t\tvar display_columns = [];\n\n\t\tvar select_items = this.column_selector.getSelectItems();\n\n\t\tif ( select_items && select_items.length > 0 ) {\n\t\t\t$.each( select_items, function( index, content ) {\n\t\t\t\tdisplay_columns.push( content.value );\n\t\t\t} );\n\t\t}\n\n\t\treturn display_columns;\n\t}\n\n\tonSearch( save_only ) {\n\t\tthis.temp_adv_filter_data = null;\n\t\tthis.temp_basic_filter_data = null;\n\n\t\tthis.getSearchPanelFilter();\n\n\t\tif ( this.search_panel.getLayoutsArray() && this.search_panel.getLayoutsArray().length > 0 ) {\n\t\t\tvar default_layout_id = $( this.previous_saved_layout_selector ).children( 'option:contains(\\'' + BaseViewController.default_layout_name + '\\')' ).attr( 'value' );\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\tvar layout_name = BaseViewController.default_layout_name;\n\n\t\t} else {\n\t\t\tthis.onSaveNewLayout( BaseViewController.default_layout_name );\n\t\t\treturn;\n\t\t}\n\n\t\tvar selected_display_columns = this.getSearchPanelDisplayColumns();\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.display_columns = selected_display_columns;\n\t\targs.data.filter_data = filter_data;\n\t\targs.data.mode = Global.upCaseFirstLetter( this.getMode() );\n\t\targs.data.strictRange = this.settings_menu.getButton( 'strict_range_btn' ).active;\n\t\targs.data.weeklyTotals = this.settings_menu.getButton( 'weekly_totals_btn' ).active;\n\t\targs.data.dailyTotals = this.settings_menu.getButton( 'daily_totals_btn' ).active;\n\t\targs.data.showAllEmp = this.settings_menu.getButton( 'all_employee_btn' ).active;\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\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\t\t\t\t\t\t$this.initLayout();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\tsetSelectLayout() {\n\n\t\tvar $this = this;\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\tthis.select_layout.data.display_columns = this.default_display_columns;\n\t\t}\n\n\t\tvar layout_data = this.select_layout.data;\n\n\t\tvar display_columns = this.buildDisplayColumns( layout_data.display_columns );\n\n\t\tif ( Global.isSet( layout_data.mode ) && layout_data.mode != '' ) {\n\t\t\t$this.setToggleButtonValue( layout_data.mode.toLowerCase() );\n\t\t} else if ( LocalCacheData.getAllURLArgs() && LocalCacheData.getAllURLArgs().mode ) {\n\t\t\t$this.setToggleButtonValue( LocalCacheData.getAllURLArgs().mode );\n\t\t} else {\n\t\t\t$this.setToggleButtonValue( ScheduleViewControllerMode.WEEK );\n\t\t}\n\n\t\tif ( layout_data.hasOwnProperty( 'strictRange' ) ) {\n\t\t\tif ( layout_data.strictRange ) {\n\t\t\t\tthis.settings_menu.activateButton( 'strict_range_btn' );\n\t\t\t} else {\n\t\t\t\tthis.settings_menu.deactivateButton( 'strict_range_btn' );\n\t\t\t}\n\t\t} else {\n\t\t\tthis.settings_menu.activateButton( 'strict_range_btn' );\n\t\t}\n\n\t\tif ( layout_data.weeklyTotals ) {\n\t\t\tthis.settings_menu.activateButton( 'weekly_totals_btn' );\n\t\t} else {\n\t\t\tthis.settings_menu.deactivateButton( 'weekly_totals_btn' );\n\t\t}\n\n\t\tif ( layout_data.dailyTotals ) {\n\t\t\tthis.settings_menu.activateButton( 'daily_totals_btn' );\n\t\t} else {\n this.settings_menu.deactivateButton( 'daily_totals_btn' );\n }\n\n\t\tif ( layout_data.showAllEmp ) {\n\t\t\tthis.settings_menu.activateButton( 'all_employee_btn' );\n\t\t} else {\n this.settings_menu.deactivateButton( 'all_employee_btn' );\n }\n\n\t\t//Set Display Column in layout panel\n\t\tthis.column_selector.setSelectGridData( display_columns );\n\n\t\t//Set Previoous Saved layout combobox in layout panel\n\t\tvar layouts_array = this.search_panel.getLayoutsArray();\n\n\t\tthis.previous_saved_layout_selector.empty();\n\t\tif ( layouts_array && layouts_array.length > 0 ) {\n\t\t\tthis.previous_saved_layout_div.css( 'display', 'inline' );\n\n\t\t\tvar len = layouts_array.length;\n\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\tvar item = layouts_array[i];\n\t\t\t\tthis.previous_saved_layout_selector.append( $( '<option value=\"' + item.id + '\"></option>' ).text( item.name ) );\n\t\t\t}\n\t\t\t$( this.previous_saved_layout_selector.find( 'option' ) ).filter( function() {\n\t\t\t\treturn $( this ).attr( 'value' ) === $this.select_layout.id;\n\t\t\t} ).prop( 'selected', true ).attr( 'selected', true );\n\n\t\t} else {\n\t\t\tthis.previous_saved_layout_div.css( 'display', 'none' );\n\t\t}\n\n\t\tif ( LocalCacheData.default_filter_for_next_open_view ) {\n\t\t\tthis.select_layout.data.filter_data = LocalCacheData.default_filter_for_next_open_view.filter_data;\n\n\t\t\tthis.setDatePickerValue( LocalCacheData.default_filter_for_next_open_view.select_date );\n\n\t\t\tthis.select_layout.data.mode = 'Week';\n\t\t\t$this.setToggleButtonValue( layout_data.mode.toLowerCase() );\n\n\t\t\tLocalCacheData.default_filter_for_next_open_view = null;\n\t\t}\n\n\t\tthis.filter_data = this.select_layout.data.filter_data;\n\n\t\tthis.setSearchPanelFilter( true );\n\t}\n\n\tgetMode() {\n\t\tif ( this.toggle_button ) {\n\t\t\treturn this.toggle_button.getValue();\n\t\t}\n\t}\n\n\tsearch( setDefaultMenu, use_date_picker_date ) {\n\t\t//Issue #3095 - Race condition where a user switches views while the schedule is still loading can cause an exception.\n\t\tif ( !( LocalCacheData.current_open_primary_controller.viewId === 'Schedule' || LocalCacheData.current_open_primary_controller.viewId === 'FindAvailable' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.clearSelection( setDefaultMenu ); //Clear selection on search, as we aren't re-populating it anyways, and causes a problem if you select 2 cells, click top-right refresh icon, then click New icon, it thinks the selection still exists.\n\t\tthis.setActionsButtonStatus();\n\t\tthis.final_schedule_data_array = [];\n\n\t\tvar $this = this;\n\t\tvar filter_data = Global.convertLayoutFilterToAPIFilter( this.select_layout );\n\t\tvar start_date_string;\n\n\t\tvar mode = this.getMode();\n\n\t\tif ( this.settings_menu.getButton( 'all_employee_btn' ).active ) {\n\t\t\tfilter_data.include_all_users = true;\n\t\t}\n\n\t\tvar strict = this.settings_menu.getButton( 'strict_range_btn' ).active;\n\n\t\tif ( use_date_picker_date || !this.end_date ) {\n\t\t\tif ( this.start_date === null || use_date_picker_date ) {\n\t\t\t\tstart_date_string = this.start_date_picker.getValue();\n\t\t\t} else {\n\t\t\t\tstart_date_string = $this.start_date.format();\n\t\t\t}\n\n\t\t\tif ( mode === ScheduleViewControllerMode.YEAR ) {\n\t\t\t\tthis.year_mode_original_date = start_date_string;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tif ( strict ) {\n\t\t\t\tif ( mode === ScheduleViewControllerMode.YEAR ) {\n\t\t\t\t\tstart_date_string = this.year_mode_original_date ? this.year_mode_original_date : this.start_date_picker.getValue();\n\t\t\t\t} else if ( mode === ScheduleViewControllerMode.MONTH ) {\n\t\t\t\t\tstart_date_string = new Date( new Date( $this.end_date.getTime() ).setDate( $this.end_date.getDate() - 15 ) ).format();\n\t\t\t\t} else {\n\t\t\t\t\tstart_date_string = $this.end_date.format();\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tstart_date_string = $this.start_date.format();\n\t\t\t}\n\n\t\t}\n\n\t\tProgressBar.showOverlay();\n\t\tLocalCacheData.last_schedule_selected_date = start_date_string;\n\t\tthis.api.getCombinedSchedule( { filter_data: filter_data }, start_date_string, mode, strict, {\n\t\t\tonResult: function( result ) {\n\t\t\t\t//Issue #3095 - Race condition where a user switches views while the schedule is still loading can cause an exception.\n\t\t\t\tif ( !( LocalCacheData.current_open_primary_controller.viewId === 'Schedule' || LocalCacheData.current_open_primary_controller.viewId === 'FindAvailable' ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t$this.full_schedule_data = result.getResult();\n\n\t\t\t\t//Error: Unable to get property 'start_display_date' of undefined or null reference in /interface/html5/ line 3805\n\t\t\t\tif ( $this.full_schedule_data === true || !$this.full_schedule_data || !$this.full_schedule_data.schedule_dates ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t$this.start_date = Global.strToDate( $this.full_schedule_data.schedule_dates.start_display_date );\n\t\t\t\t$this.end_date = Global.strToDate( $this.full_schedule_data.schedule_dates.end_display_date );\n\n\t\t\t\t$this.buildCalendars();\n\n\t\t\t\tif ( setDefaultMenu ) {\n\t\t\t\t\t$this.setDefaultMenu( true );\n\t\t\t\t\t$this.autoOpenEditViewIfNecessary();\n\t\t\t\t}\n\n\t\t\t\t$this.searchDone();\n\n\t\t\t\t$this.setWeekModeDragAble();\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tsearchDone() {\n\t\t// this.setGridColumnsWidth();\n\t\t// this.setGridSize();\n\t\t$( '.button-rotate' ).removeClass( 'button-rotate' );\n\t\tTTPromise.resolve( 'init', 'init' );\n\t}\n\n\tgetLastDateOfRow( row ) {\n\t\tvar start_day = LocalCacheData.getLoginUserPreference().start_week_day == 0 ? 7 : LocalCacheData.getLoginUserPreference().start_week_day;\n\t\treturn row[( start_day - 1 ) + '_time'];\n\t}\n\n\tsetActionsButtonStatus() {\n\t\tvar mode = this.getMode();\n\n\t\tthis.settings_menu.enableButton( 'weekly_totals_btn' );\n\t\tthis.settings_menu.enableButton( 'strict_range_btn' );\n\t\tthis.settings_menu.enableButton( 'daily_totals_btn' );\n\t\tthis.settings_menu.enableButton( 'all_employee_btn' );\n\n\t\tswitch ( mode ) {\n\t\t\tcase ScheduleViewControllerMode.DAY:\n\t\t\t\tthis.settings_menu.disableButton( 'weekly_totals_btn' );\n\t\t\t\tthis.settings_menu.disableButton( 'strict_range_btn' );\n\t\t\t\tbreak;\n\t\t\tcase ScheduleViewControllerMode.WEEK:\n\t\t\t\tbreak;\n\t\t\tcase ScheduleViewControllerMode.MONTH:\n\t\t\t\tbreak;\n\t\t\tcase ScheduleViewControllerMode.YEAR:\n\t\t\t\tthis.settings_menu.disableButton( 'weekly_totals_btn' );\n\t\t\t\tthis.settings_menu.disableButton( 'daily_totals_btn' );\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tonOverrideClick() {\n\t\tvar context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.determineContextMenuMountAttributes().id );\n\t\tvar override_icon = context_menu_array.find( icon => icon.id === 'override' );\n\n\t\tif ( override_icon.active ) {\n\t\t\tthis.is_override = true;\n\t\t} else {\n\t\t\tthis.is_override = false;\n\t\t}\n\t}\n\n\tonNotifyUserScheduleChangeClick() {\n\t\tvar context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.determineContextMenuMountAttributes().id );\n\t\tvar notify_user_schedule_change_icon = context_menu_array.find( icon => icon.id === 'notify_user_schedule_change' );\n\n\t\tif ( notify_user_schedule_change_icon.active ) {\n\t\t\tthis.notify_user_schedule_change = true;\n\t\t} else {\n\t\t\tthis.notify_user_schedule_change = false;\n\t\t}\n\t}\n\n\tsetMoveOrDropMode( id ) {\n\t\t//Drag and drop context menu does not exist on edit view and thus this code does not need to be ran. Otherwise would cause JavaScript exception.\n\t\tif ( this.is_edit || this.is_mass_editing || this.is_add ) {\n\t\t\treturn;\n\t\t}\n\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\t\tvar swap_icon = context_menu_array.find( icon => icon.id === 'swap' );\n\n\t\tif ( drag_copy_icon === undefined || move_icon === undefined || swap_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\tContextMenuManager.activateMenuItem( this.determineContextMenuMountAttributes().id, swap_icon.id, true );\n\n\t\tvar drag_invisible = false;\n\t\tvar move_invisible = false;\n\t\tvar swap_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 ( !this.editPermissionValidate() ) {\n\t\t\tswap_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\tsetHolidayDataDic() {\n\n\t\tif ( this.full_schedule_data.holiday_data ) {\n\t\t\tfor ( var i = 0; i < this.full_schedule_data.holiday_data.length; i++ ) {\n\t\t\t\tvar item = this.full_schedule_data.holiday_data[i];\n\t\t\t\tvar standard_date = Global.strToDate( item.date_stamp ).format( this.weekly_format );\n\t\t\t\tthis.holiday_data_dic[standard_date] = item;\n\t\t\t}\n\t\t}\n\t}\n\n\tbuildCalendars( do_not_hide ) {\n\t\tvar $this = this;\n\t\tthis.grid_div = $( this.el ).find( '.schedule-grid-div' );\n\t\tthis.setHolidayDataDic();\n\n\t\tthis.buildScheduleColumns();\n\t\tthis.buildScheduleSource();\n\t\tthis.buildScheduleGrid();\n\n\t\tthis.setGridColumnsWidth(); //There is no grid data populated when this runs, so it only sizes columns to the label length, not longest row data length.\n\t\tthis.setGridSize();\n\n\t\t//Only work when year mode\n\t\tthis.setYearGroupHeader();\n\t\tthis.showGridBorders();\n\n\t\tvar start = 0;\n\t\tvar page = 1;\n\t\tvar page_num = 10;\n\n\t\t//this.grid will be empty when first time int this function, so put this judge here instead at begin.\n\t\t//Error: Uncaught TypeError: Cannot call method 'clearGridData' of null in /interface/html5/index.php?desktop=1#!m=Schedule&date=20150118&mode=week line 6944\n\t\tif ( !this.grid ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.grid.clearGridData();\n\n\t\tvar j = 0;\n\n\t\tif ( !do_not_hide ) {\n\t\t\tthis.grid.grid.css( 'opacity', 0 );\n\t\t}\n\n\t\t//Error: TypeError: $this.schedule_source is undefined in interface/html5/framework/jquery.min.js?v=9.0.6-20151231-155042 line 2 > eval line 3904\n\t\tif ( !this.schedule_source ) {\n\t\t\treturn;\n\t\t}\n\t\tvar $this = this;\n\t\taddGridData();\n\n\t\t// Add 200 record a time so UI not block.\n\t\tvar interval = setInterval( function() {\n\t\t\tif ( j < $this.schedule_source.length ) {\n\t\t\t\taddGridData();\n\t\t\t} else {\n\t\t\t\tdoNext();\n\t\t\t}\n\t\t}, 10 );\n\n\t\tfunction addGridData() {\n\t\t\tfor ( var i = j; i < j + 200; i++ ) {\n\t\t\t\tif ( i < $this.schedule_source.length ) {\n\t\t\t\t\tvar item = $this.schedule_source[i];\n\t\t\t\t\t$this.grid.grid.addRowData( i + 1, item );\n\t\t\t\t} else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tj = i;\n\t\t}\n\n\t\tfunction doNext() {\n\t\t\tif ( !do_not_hide ) {\n\t\t\t\t$this.grid.grid.css( 'opacity', 1 );\n\t\t\t}\n\t\t\tclearInterval( interval );\n\n\t\t\tif ( $this.getMode !== ScheduleViewControllerMode.YEAR ) {\n\t\t\t\t$this.setScheduleGridRowSpan();\n\t\t\t}\n\n\t\t\t$this.highLightSelectDay();\n\n\t\t\t//Only work when month mode\n\t\t\t$this.setMonthDateRowPosition();\n\n\t\t\t$this.setScheduleGridDragAble();\n\n\t\t\t$this.setScrollPosition();\n\n\t\t\t//$this.autoOpenEditViewIfNecessary();\n\n\t\t\t$this.setMonthDateRowBackGround();\n\n\t\t\t$this.setWeeklyTotalHeader();\n\t\t}\n\t}\n\n\tgetDefaultUser() {\n\t\tvar default_user_id = false;\n\t\tif ( this.schedule_source && this.schedule_source.length === 1 && this.schedule_source[0].user_id != '' ) {\n\t\t\t//case where only one user has a schedule on the sheet\n\t\t\tdefault_user_id = this.schedule_source[0].user_id;\n\t\t} else if ( this.schedule_source\n\t\t\t&& this.schedule_source.length === 1\n\t\t\t&& typeof this.filter_data == 'object' // #2571 - Uncaught TypeError: This.filter_data.include_user_id is undefined\n\t\t\t&& typeof this.filter_data.include_user_ids == 'object' // #2571 - Uncaught TypeError: Cannot read property 'value' of undefined\n\t\t\t&& this.filter_data.include_user_ids.value\n\t\t\t&& this.filter_data.include_user_ids.value.length === 1 ) {\n\t\t\t//case where one user is selected in include_users but does not have a schedule attributed to them (new users for example)\n\t\t\tdefault_user_id = this.filter_data.include_user_ids.value[0];\n\t\t} else {\n\t\t\t// #2740 Before defaulting to logged in user, check to see if user_id is set on the current_edit_record, as Save&Copy clears grid selection, so we need to re-set it.\n\t\t\tif ( this.current_edit_record.user_id && this.current_edit_record.user_id != '' ) {\n\t\t\t\tdefault_user_id = this.current_edit_record.user_id;\n\t\t\t} else {\n\t\t\t\tdefault_user_id = LocalCacheData.getLoginUser().id;\n\t\t\t}\n\t\t}\n\n\t\treturn default_user_id;\n\t}\n\n\tsetWeeklyTotalHeader() {\n\t\tvar show_weekly_total = this.settings_menu.getButton( 'weekly_totals_btn' ).active;\n\t\t$( '.size-tr' ).remove();\n\t\t$( '.group-tr' ).remove();\n\t\tif ( !show_weekly_total || this.settings_menu.getButton( 'weekly_totals_btn' ).disabled === true ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar table = $( $( this.el ).find( 'table[aria-labelledby=gbox_' + this.ui_id + '_grid]' ) );\n\n\t\tvar size_tr = $( '<tr class=\"size-tr\" >' +\n\t\t\t'</tr>' );\n\n\t\tvar new_tr = $( '<tr class=\"group-column-tr group-tr\" >' +\n\t\t\t'</tr>' );\n\n\t\tvar new_th = $( '<th class=\"group-column-th\" >' +\n\t\t\t'<span class=\"group-column-label\"></span>' +\n\t\t\t'</th>' );\n\n\t\tvar current_trs = table.find( '.jqgfirstrow' );\n\t\tcreateSizeColumns();\n\n\t\tvar column_length = this.grid.grid.getGridParam( 'colModel' ).length;\n\t\tcreateColumn( column_length - 5, '' );\n\t\tcreateColumn( 5, $.i18n._( 'Total' ) );\n\n\t\tsize_tr.insertBefore( table.find( '.ui-jqgrid-labels' ) );\n\t\tnew_tr.insertBefore( table.find( '.ui-jqgrid-labels' ) );\n\n\t\tfunction createSizeColumns() {\n\t\t\tvar len = current_trs.children().length;\n\n\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\tvar td = $( '<th class=\"\" style=\"border-right: 1px solid #dddddd\" >' + '</th>' );\n\t\t\t\tvar item = current_trs.children().eq( i );\n\n\t\t\t\t/**\n\t\t\t\t * #2353 - schedule sizing fix\n\t\t\t\t *\n\t\t\t\t * Due to firefox reporting th incorrectly via the $.width() function, the sizes must come from the (tr.jqgfirstrow) of the data table\n\t\t\t\t * firefox also refuses to set the width of the first row of th's via the $.width() function, so we need to ship the css values directly into the inline css using the css function\n\t\t\t\t */\n\t\t\t\ttd.css( 'width', item.css( 'width' ) );\n\n\t\t\t\ttd.height( 0 );\n\t\t\t\tsize_tr.append( td );\n\t\t\t}\n\n\t\t}\n\n\t\tfunction createColumn( end_index, text ) {\n\t\t\tvar pay_period_th = new_th.clone();\n\n\t\t\tpay_period_th.children( 0 ).text( text );\n\t\t\tpay_period_th.attr( 'colspan', end_index );\n\n\t\t\tnew_tr.append( pay_period_th );\n\t\t}\n\n\t\tthis.setGridHeight(); //Since we are changing the header height, resize the grid to fit.\n\t}\n\n\tsetMonthDateRowBackGround() {\n\t\tif ( this.getMode() === ScheduleViewControllerMode.MONTH ) {\n\t\t\t$( this.el ).find( '.month-date-cell' ).parent().css( 'background-color', '#375979' );\n\t\t}\n\t}\n\n\tsetScrollPosition() {\n\t\tif ( this.scroll_position > 0 ) {\n\t\t\tthis.grid.grid.parent().parent().scrollTop( this.scroll_position );\n\t\t}\n\t}\n\n\tsetYearGroupHeader() {\n\n\t\tif ( this.getMode() !== ScheduleViewControllerMode.YEAR ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$( '.schedule-year-group-header' ).remove();\n\t\tvar table = $( $( this.el ).find( 'table[aria-labelledby=gbox_' + this.ui_id + '_grid]' )[0] );\n\t\tvar new_tr = $( '<tr class=\"group-column-tr schedule-year-group-header\" >' +\n\t\t\t'</tr>' );\n\n\t\tvar new_th = $( '<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_tr = new_tr.clone();\n\n\t\t$( table.children()[0] ).prepend( default_tr );\n\n\t\t//Build first row to correct width for span columns which in second row, table width decided by first row\n\t\tvar datesTHs = table.find( 'th' );\n\t\tvar len = datesTHs.length;\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar th = $( datesTHs[i] );\n\n\t\t\tvar default_th = th.clone();\n\t\t\tdefault_th.attr( 'id', '' );\n\t\t\tdefault_th.empty();\n\t\t\tdefault_th.attr( 'row', '' );\n\t\t\tdefault_th.height( 0 );\n\t\t\tdefault_tr.append( default_th );\n\n\t\t}\n\n\t\tvar first_tr = $( $( table.children()[0] ).children()[0] );\n\n\t\tvar start = this.select_layout.data.display_columns.length + 1;\n\t\t//Create group column header\n\t\tdefault_tr = new_tr.clone();\n\t\tdefault_th = new_th.clone();\n\t\tdefault_th.attr( 'colspan', start );\n\t\tdefault_tr.append( default_th );\n\t\tdefault_tr.insertAfter( first_tr );\n\n\t\tvar current_month = null;\n\t\tvar current_date = null;\n\t\tvar same_month_count = 0;\n\n\t\tfor ( var i = start; i < len; i++ ) {\n\t\t\tth = $( datesTHs[i] );\n\t\t\tvar id_split_array = th.attr( 'id' ).split( '_' );\n\t\t\tvar date_str = id_split_array[id_split_array.length - 1];\n\n\t\t\tif ( date_str === 'shifts' || date_str === 'absences' || date_str === 'total_time' || date_str === 'total_time_wage' ) {\n\t\t\t\tvar month = '-1';\n\t\t\t} else {\n\t\t\t\tmonth = Global.strToDate( date_str, this.full_format ).getMonth();\n\t\t\t}\n\n\t\t\tif ( !Global.isSet( current_month ) ) {\n\t\t\t\tcurrent_month = month;\n\t\t\t\tcurrent_date = date_str;\n\t\t\t\tsame_month_count = 1;\n\n\t\t\t} else {\n\t\t\t\tvar month_header_text = Global.strToDate( current_date, this.full_format ).format( 'MMM' );\n\t\t\t\tif ( month === current_month && i !== len - 1 ) {\n\t\t\t\t\tsame_month_count = same_month_count + 1;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( i === len - 1 ) {\n\t\t\t\t\t\tif ( month !== current_month && !isNaN( month ) ) {\n\t\t\t\t\t\t\tdefault_th.children( 0 ).text( month_header_text );\n\t\t\t\t\t\t\tdefault_th.attr( 'colspan', same_month_count );\n\t\t\t\t\t\t\tdefault_tr.append( default_th );\n\n\t\t\t\t\t\t\tcurrent_month = month;\n\t\t\t\t\t\t\tcurrent_date = date_str;\n\t\t\t\t\t\t\tsame_month_count = 1;\n\n\t\t\t\t\t\t\tdefault_th = new_th.clone();\n\t\t\t\t\t\t\tdefault_th.children( 0 ).text( month_header_text );\n\t\t\t\t\t\t\tdefault_th.attr( 'colspan', same_month_count );\n\t\t\t\t\t\t\tdefault_tr.append( default_th );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsame_month_count = same_month_count + 1;\n\n\t\t\t\t\t\t\tdefault_th = new_th.clone();\n\t\t\t\t\t\t\tdefault_th.children( 0 ).text( month_header_text );\n\t\t\t\t\t\t\tdefault_th.attr( 'colspan', same_month_count );\n\t\t\t\t\t\t\tdefault_tr.append( default_th );\n\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdefault_th = new_th.clone();\n\t\t\t\t\t\tdefault_th.children( 0 ).text( month_header_text );\n\t\t\t\t\t\tdefault_th.attr( 'colspan', same_month_count );\n\t\t\t\t\t\tdefault_tr.append( default_th );\n\n\t\t\t\t\t\tcurrent_month = month;\n\t\t\t\t\t\tcurrent_date = date_str;\n\t\t\t\t\t\tsame_month_count = 1;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( month === '-1' ) {\n\t\t\t\t\t\tdefault_th = new_th.clone();\n\t\t\t\t\t\tdefault_th.children( 0 ).text( '' );\n\t\t\t\t\t\tdefault_th.attr( 'colspan', len - i );\n\t\t\t\t\t\tdefault_tr.append( default_th );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t}\n\n\tsetMonthDateRowPosition() {\n\n\t\tif ( this.getMode() !== ScheduleViewControllerMode.MONTH ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar $this = this;\n\t\tthis.month_date_row_position = {};\n\t\tvar i = 0;\n\t\tfor ( var key in this.month_date_row_tr_ids ) {\n\t\t\tthis.month_date_row_position[i] = this.grid.grid.find( '#' + key ).position().top;\n\t\t\ti = i + 1;\n\t\t}\n\n\t\tthis.grid.grid.parent().parent().scroll( function() {\n\t\t\tvar top = $( this ).scrollTop();\n\n\t\t\tvar start_day = $this.start_date.getDay();\n\n\t\t\tif ( top < $this.month_date_row_position[0] && $this.month_current_header_number !== 0 ) {\n\n\t\t\t\t//Deal with header before first date row.\n\t\t\t\t$this.month_date_row_tr_ids = {};\n\t\t\t\t$this.month_current_header_number = 0;\n\t\t\t\tfor ( var i = 0; i < 7; i++ ) {\n\t\t\t\t\tvar current_date = new Date( new Date( $this.start_date.getTime() ).setDate( $this.start_date.getDate() + i ) );\n\t\t\t\t\tvar header_text = current_date.format( $this.weekly_format );\n\t\t\t\t\tvar header_container = $( $this.el ).find( '#' + $this.ui_id + '_grid_' + data_field );\n\t\t\t\t\tvar data_field = ( ( start_day + i ) % 7 );\n\t\t\t\t\tvar header = $( $this.el ).find( '#jqgh_' + $this.ui_id + '_grid_' + data_field );\n\t\t\t\t\theader.text( header_text );\n\t\t\t\t\theader_container.removeClass( 'highlight-header' );\n\n\t\t\t\t}\n\n\t\t\t\t$this.highLightSelectDay();\n\n\t\t\t} else if ( top > $this.month_date_row_position[0] && top < $this.month_date_row_position[1] && $this.month_current_header_number !== 1 ) {\n\t\t\t\tsetHeaderText( 0, 1 );\n\n\t\t\t} else if ( top > $this.month_date_row_position[1] && top < $this.month_date_row_position[2] && $this.month_current_header_number !== 2 ) {\n\t\t\t\tsetHeaderText( 1, 2 );\n\t\t\t} else if ( top > $this.month_date_row_position[2] && top < $this.month_date_row_position[3] && $this.month_current_header_number !== 3 ) {\n\t\t\t\tsetHeaderText( 2, 3 );\n\t\t\t} else if ( top > $this.month_date_row_position[3] && $this.month_current_header_number !== 4 ) {\n\t\t\t\tsetHeaderText( 3, 4 );\n\t\t\t}\n\n\t\t\tfunction setHeaderText( index, headerNumber ) {\n\t\t\t\t$this.month_date_row_tr_ids = {};\n\t\t\t\t$this.month_current_header_number = headerNumber;\n\t\t\t\tvar date_row = $this.month_date_row_array[index];\n\t\t\t\tfor ( var i = 0; i < 7; i++ ) {\n\t\t\t\t\tvar data_field = ( ( start_day + i ) % 7 );\n\t\t\t\t\tvar header = $( $this.el ).find( '#jqgh_' + $this.ui_id + '_grid_' + data_field );\n\t\t\t\t\tvar header_container = $( $this.el ).find( '#' + $this.ui_id + '_grid_' + data_field );\n\t\t\t\t\theader_container.removeClass( 'highlight-header' );\n\t\t\t\t\tvar full_date = date_row[data_field + '_full_date'];\n\t\t\t\t\tvar date_cell = $( $this.el ).find( '#' + $this.ui_id + '_grid_' + full_date );\n\n\t\t\t\t\tif ( date_cell.hasClass( 'highlight-header' ) ) {\n\t\t\t\t\t\theader_container.addClass( 'highlight-header' );\n\t\t\t\t\t}\n\t\t\t\t\theader.html( date_row[data_field] );\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t} );\n\t}\n\n\tsetGridHeight() {\n\t\tlet scroll_height = document.body.scrollHeight;\n\n\t\tlet height = scroll_height;\n\n\t\tlet table_body = document.querySelector( 'div.ui-jqgrid-bdiv.ui-corner-bottom' );\n\t\tlet context_border = document.querySelector( 'div.context-border' );\n\t\t//Issue #3060 - JavaScript exceptions of trying to read getBoundingClientRect of null elements.\n\t\tif ( !table_body || !context_border ) {\n\t\t\treturn scroll_height;\n\t\t}\n\n\t\theight -= table_body.getBoundingClientRect().top;\n\t\theight -= ( scroll_height - context_border.getBoundingClientRect().bottom );\n\t\theight -= 10; //Manual fine tuning to fit better.\n\n\t\tif ( this.getMode() != ScheduleViewControllerMode.DAY ) {\n\t\t\tvar grid_div = $( '.schedule-view .grid-div .ui-jqgrid-bdiv' );\n\t\t\tif ( grid_div && grid_div.length > 0 && grid_div[0].scrollWidth > ( $( '.context-border' ).width() + 2 ) ) { //this plus 2 is because sometimes the scroll width is larger than the view width with no scrollbar\n\t\t\t\theight -= Global.getScrollbarWidth(); //scrollbar compensation\n\t\t\t}\n\t\t}\n\n\t\tthis.grid.setGridHeight( height );\n\t\treturn height;\n\t}\n\n\tsetGridColumnsWidth() {\n\t\tvar $this = this;\n\t\tswitch ( this.getMode() ) {\n\t\t\tcase ScheduleViewControllerMode.DAY:\n\t\t\t\tvar day_column_index;\n\n\t\t\t\t//Calculate the exact width of each column that isn't where the shift times are displayed.\n\t\t\t\t//Then any remaining width can be allocated to the shift times column.\n\t\t\t\tvar column_padding = 10;\n\t\t\t\t//var grid_data = this.grid.getData();\n\t\t\t\tvar grid_data = $this.schedule_source; //Must use the original source data, as the this.grid.getData() is not populated yet.\n\t\t\t\tfor ( var i in this.schedule_columns ) {\n\t\t\t\t\tif ( this.schedule_columns[i].is_static_size == true || this.schedule_columns[i].name == 'scrollbar_spacer' ) {\n\t\t\t\t\t\tthis.schedule_columns[i].fixed = true;\n\t\t\t\t\t\tif ( this.schedule_columns[i].name != 'scrollbar_spacer' ) {\n\t\t\t\t\t\t\tday_column_index = i;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t//size column based on text.\n\t\t\t\t\t\tvar column_width = Global.calculateTextWidth( this.schedule_columns[i].label ) + column_padding;\n\n\t\t\t\t\t\tif ( grid_data && grid_data.length > 0 ) {\n\t\t\t\t\t\t\tfor ( var row in grid_data ) {\n\t\t\t\t\t\t\t\tvar new_col_width = Global.calculateTextWidth( grid_data[row][this.schedule_columns[i].name] );\n\t\t\t\t\t\t\t\tif ( new_col_width > column_width ) {\n\t\t\t\t\t\t\t\t\tcolumn_width = new_col_width;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthis.schedule_columns[i].width = column_width;\n\t\t\t\t\t\tthis.schedule_columns[i].fixed = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tthis.calculateScheduleWidth();\n\t\t\t\t$( '.day_hour_div .day_hour_span' ).width( this.day_hour_width );\n\t\t\t\tvar day_column_width = ( this.day_hour_width * $( '.day_hour_div .day_hour_span' ).length ); // 60 is desired width of each day span\n\n\t\t\t\tthis.schedule_columns[day_column_index].width = day_column_width;\n\n\t\t\t\tthis.grid.setGridColumnsWidth( this.schedule_columns );\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tvar column_padding = 10;\n\t\t\t\tvar columns_width = 0;\n\n\t\t\t\t//Day columns must always be the same width, only make the employee name and other static columns variable width.\n\t\t\t\tvar max_width = $( '.context-border' ).width();\n\n\t\t\t\tvar grid_data = $this.schedule_source; //Must use the original source data, as the this.grid.getData() is not populated yet.\n\t\t\t\tfor ( var i in this.schedule_columns ) {\n\t\t\t\t\tif ( !this.schedule_columns[i].is_static_size || this.schedule_columns[i].is_static_size == false ) {\n\t\t\t\t\t\t//size column based on text.\n\t\t\t\t\t\tvar column_width = Global.calculateTextWidth( this.schedule_columns[i].label, { padding: column_padding } );\n\n\t\t\t\t\t\tif ( grid_data && grid_data.length > 0 ) {\n\t\t\t\t\t\t\tvar label_cache = [];\n\n\t\t\t\t\t\t\tfor ( var row in grid_data ) {\n\t\t\t\t\t\t\t\tvar label = grid_data[row][this.schedule_columns[i].name];\n\t\t\t\t\t\t\t\tif ( !label_cache[label]) { //Cache labels we have already calculated the size on, so we don't do it over and over again.\n\t\t\t\t\t\t\t\t\tvar new_col_width = Global.calculateTextWidth( label, { padding: column_padding } );\n\t\t\t\t\t\t\t\t\tif ( new_col_width > column_width ) {\n\t\t\t\t\t\t\t\t\t\tcolumn_width = new_col_width;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tlabel_cache[label] = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tlabel_cache = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthis.schedule_columns[i].width = column_width;\n\t\t\t\t\t\tthis.schedule_columns[i].fixed = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tcolumns_width += this.schedule_columns[i].width;\n\t\t\t\t}\n\n\t\t\t\t//Resize first column to fill screen.\n\t\t\t\tif ( this.schedule_columns[0] && columns_width < max_width ) {\n\t\t\t\t\tthis.schedule_columns[0].width += ( max_width - columns_width );\n\t\t\t\t}\n\n\t\t\t\tthis.grid.setGridColumnsWidth( this.schedule_columns );\n\n\t\t\t\tif ( this.getMode() == ScheduleViewControllerMode.YEAR ) {\n\t\t\t\t\tthis.setYearGroupHeader(); //Must go after the column widths are changed.\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t}\n\n\t\tthis.setGridHeight();\n\t}\n\n\tbuildScheduleSource() {\n\t\tthis.no_date_array = [];\n\t\tthis.has_date_array = [];\n\t\tthis.final_schedule_data_array = [];\n\t\tvar mode = this.getMode();\n\n\t\tthis.no_date_array = this.buildNoDateArray();\n\t\tthis.has_date_array = this.buildHasDateArray();\n\t\tvar has_date_temp_array_length = this.has_date_array.length;\n\t\tvar sort_fields = this.buildSortFields();\n\t\tthis.has_date_array.sort( Global.m_sort_by( sort_fields ) );\n\t\tthis.no_date_array.sort( Global.m_sort_by( sort_fields ) );\n\n\t\tif ( mode !== ScheduleViewControllerMode.MONTH ) {\n\t\t\tthis.final_schedule_data_array = this.no_date_array.concat( this.has_date_array );\n\t\t}\n\n\t\tswitch ( this.getMode() ) {\n\t\t\tcase ScheduleViewControllerMode.WEEK:\n\t\t\t\tthis.buildWeeklySource();\n\t\t\t\tbreak;\n\t\t\tcase ScheduleViewControllerMode.MONTH:\n\t\t\t\tthis.buildMonthSource();\n\t\t\t\tbreak;\n\t\t\tcase ScheduleViewControllerMode.YEAR:\n\t\t\t\tthis.buildYearlySource();\n\t\t\t\tbreak;\n\t\t\tcase ScheduleViewControllerMode.DAY:\n\t\t\t\tthis.buildDailySource();\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tbuildShiftKey( shift ) {\n\n\t\tvar key = '';\n\t\tfor ( var i = 0; i < this.shift_key_name_array.length; i++ ) {\n\t\t\tvar field_name = this.shift_key_name_array[i];\n\t\t\tvar column_name = this.shift_key_name_array[i].replace( '_id', '' ); //judge if shit has correct field value\n\t\t\tif ( column_name !== 'user' ) {\n\t\t\t\tif ( shift[column_name] ) {\n\t\t\t\t\tkey = shift[field_name] + '-' + key;\n\t\t\t\t} else {\n\t\t\t\t\tkey = 0 + '-' + key;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tkey = shift[field_name] + '-' + key;\n\t\t\t}\n\t\t}\n\t\treturn key;\n\t}\n\n\tbuildMonthSource() {\n\t\tvar $this = this;\n\t\tvar date_row_index = 0;\n\t\tvar month_week_data_index = 0;\n\t\tvar date_row = this.month_date_row_array[date_row_index];\n\t\tvar start_day = this.start_date.getDay(); //start from first date row, not include column\n\t\tvar first_day_time = date_row[start_day + '_time'];\n\t\tvar month_week_data_array = [];\n\t\tvar has_date_array = this.has_date_array.slice();\n\t\tfor ( var j = 0; j < 5; j++ ) {\n\t\t\tvar current_week_array = [];\n\t\t\tvar len = has_date_array.length;\n\t\t\tvar is_last_row = false;\n\t\t\tfor ( var i = 0; i < len; i++ ) {\n\n\t\t\t\tvar shift = has_date_array[i];\n\t\t\t\tvar date = Global.strToDate( shift.date_stamp );\n\t\t\t\tvar time = date.getTime();\n\n\t\t\t\tif ( time < first_day_time ) {\n\n\t\t\t\t\thas_date_array.splice( i, 1 );\n\n\t\t\t\t\ti = i - 1;\n\t\t\t\t\tlen = len - 1;\n\n\t\t\t\t\tcurrent_week_array.push( shift );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( this.settings_menu.getButton( 'all_employee_btn' ).active ) {\n\t\t\t\tif ( j === 0 ) {\n\t\t\t\t\tcurrent_week_array = this.no_date_array.slice().concat( current_week_array );\n\t\t\t\t} else {\n\t\t\t\t\t// only first week empty users are comming from API, calculate all other weeks data\n\t\t\t\t\tvar no_date_array = this.buildMonthWeekNoDateArray( current_week_array );\n\t\t\t\t\tcurrent_week_array = no_date_array.slice().concat( current_week_array );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tmonth_week_data_array[month_week_data_index] = current_week_array;\n\t\t\tif ( date_row_index > 2 ) {\n\t\t\t\tis_last_row = true;\n\t\t\t} else if ( date_row_index === 2 && !this.month_date_row_array[3].hasOwnProperty( 0 ) ) {\n\t\t\t\tis_last_row = true;\n\t\t\t}\n\t\t\tif ( !is_last_row ) {\n\t\t\t\tdate_row_index = date_row_index + 1;\n\t\t\t\tmonth_week_data_index = month_week_data_index + 1;\n\t\t\t\tdate_row = this.month_date_row_array[date_row_index];\n\t\t\t\tfirst_day_time = date_row[start_day + '_time'];\n\t\t\t} else {\n\t\t\t\tmonth_week_data_index = month_week_data_index + 1;\n\n\t\t\t\t//Don't use this.end_date because the end date may larger than the last day of this month. Use the last date in date row\n\t\t\t\tvar end_date_time = this.getLastDateOfRow( this.month_date_row_array[date_row_index] );\n\t\t\t\tvar end_date = new Date( end_date_time );\n\t\t\t\tfirst_day_time = new Date( end_date.setDate( end_date.getDate() + 1 ) ).getTime();\n\t\t\t}\n\t\t}\n\n\t\tbuildMonthWeeklyData( -1, month_week_data_array[0] );\n\t\tbuildMonthWeeklyData( 0, month_week_data_array[1] );\n\t\tbuildMonthWeeklyData( 1, month_week_data_array[2] );\n\t\tbuildMonthWeeklyData( 2, month_week_data_array[3] );\n\t\tbuildMonthWeeklyData( 3, month_week_data_array[4] );\n\n\t\tfunction buildMonthWeeklyData( rowIndex, source_array ) {\n\t\t\tif ( source_array.length < 1 ) {\n\t\t\t\tbuildEmptyRow( rowIndex );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar map = {};\n\t\t\tvar len = source_array.length;\n\t\t\tvar push_to_last = false;\n\n\t\t\tif ( rowIndex === $this.month_date_row_array.length - 1 ) {\n\t\t\t\tpush_to_last = true;\n\t\t\t} else {\n\t\t\t\tvar date_row = $this.month_date_row_array[rowIndex + 1];\n\t\t\t\tvar index = 0;\n\t\t\t}\n\n\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\tvar shift = source_array[i];\n\t\t\t\tvar date_string;\n\t\t\t\tif ( shift.date_stamp ) {\n\t\t\t\t\tvar date = Global.strToDate( shift.date_stamp );\n\n\t\t\t\t\tdate_string = date.getDay();\n\t\t\t\t}\n\n\t\t\t\tvar key = $this.buildShiftKey( shift );\n\n\t\t\t\t// each row of schedule data, start from first row\n\t\t\t\tif ( !map[key] ) {\n\t\t\t\t\tvar row = {};\n\t\t\t\t\trow.user_full_name = shift.user_full_name;\n\t\t\t\t\trow.last_name = shift.last_name;\n\t\t\t\t\trow.user_id = shift.user_id;\n\t\t\t\t\trow.branch_id = shift.branch_id;\n\t\t\t\t\trow.department_id = shift.department_id;\n\t\t\t\t\trow.schedule_policy_id = shift.schedule_policy_id;\n\t\t\t\t\trow.job_id = shift.job_id;\n\t\t\t\t\trow.job_item_id = shift.job_item_id;\n\t\t\t\t\trow.punch_tag_id = shift.punch_tag_id;\n\n\t\t\t\t\tvar display_columns = $this.select_layout.data.display_columns;\n\t\t\t\t\tvar display_columns_len = display_columns.length;\n\n\t\t\t\t\tfor ( var j = 0; j < display_columns_len; j++ ) {\n\t\t\t\t\t\tvar field_name = display_columns[j];\n\t\t\t\t\t\trow[field_name] = shift[field_name] ? shift[field_name] : '';\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( date_string >= 0 ) {\n\t\t\t\t\t\tif ( shift.status_id == 20 ) {\n\n\t\t\t\t\t\t\trow[date_string] = $this.getAbsenceCellValue( shift );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\trow[date_string] = shift.start_time + ' - ' + shift.end_time;\n\t\t\t\t\t\t}\n\t\t\t\t\t\trow[date_string + '_data'] = shift;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !push_to_last ) {\n\t\t\t\t\t\tindex = $this.schedule_source.indexOf( date_row );\n\t\t\t\t\t\t$this.schedule_source.splice( index, 0, row );\n\t\t\t\t\t\tmap[key] = [index];\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$this.schedule_source.push( row );\n\t\t\t\t\t\tmap[key] = [$this.schedule_source.length - 1];\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\t// if one row already created, go to here to create cells in this row\n\n\t\t\t\t\tvar find_position = false;\n\t\t\t\t\tfor ( var x = 0; x < map[key].length; x++ ) {\n\t\t\t\t\t\tvar row_index = map[key][x];\n\t\t\t\t\t\trow = $this.schedule_source[row_index];\n\t\t\t\t\t\tif ( row[date_string] ) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tif ( date_string >= 0 ) {\n\t\t\t\t\t\t\t\tif ( shift.status_id == 20 ) {\n\n\t\t\t\t\t\t\t\t\trow[date_string] = $this.getAbsenceCellValue( shift );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\trow[date_string] = shift.start_time + ' - ' + shift.end_time;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\trow[date_string + '_data'] = shift;\n\t\t\t\t\t\t\t}\n\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}\n\n\t\t\t\t\tif ( !find_position ) {\n\t\t\t\t\t\trow = {};\n\t\t\t\t\t\trow.user_full_name = shift.user_full_name;\n\t\t\t\t\t\trow.last_name = shift.last_name;\n\t\t\t\t\t\trow.user_id = shift.user_id;\n\t\t\t\t\t\trow.branch_id = shift.branch_id;\n\t\t\t\t\t\trow.department_id = shift.department_id;\n\t\t\t\t\t\trow.schedule_policy_id = shift.schedule_policy_id;\n\t\t\t\t\t\trow.job_id = shift.job_id;\n\t\t\t\t\t\trow.job_item_id = shift.job_item_id;\n\t\t\t\t\t\trow.punch_tag_id = shift.punch_tag_id;\n\n\t\t\t\t\t\tdisplay_columns = $this.select_layout.data.display_columns;\n\t\t\t\t\t\tdisplay_columns_len = display_columns.length;\n\n\t\t\t\t\t\tfor ( var j = 0; j < display_columns_len; j++ ) {\n\t\t\t\t\t\t\tfield_name = display_columns[j];\n\t\t\t\t\t\t\trow[field_name] = shift[field_name] ? shift[field_name] : '';\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( date_string >= 0 ) {\n\t\t\t\t\t\t\tif ( shift.status_id == 20 ) {\n\n\t\t\t\t\t\t\t\trow[date_string] = $this.getAbsenceCellValue( shift );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\trow[date_string] = shift.start_time + ' - ' + shift.end_time;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\trow[date_string + '_data'] = shift;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( !push_to_last ) {\n\t\t\t\t\t\t\tindex = $this.schedule_source.indexOf( date_row );\n\t\t\t\t\t\t\t$this.schedule_source.splice( index, 0, row );\n\t\t\t\t\t\t\tmap[key].push( index );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$this.schedule_source.push( row );\n\t\t\t\t\t\t\tmap[key].push( $this.schedule_source.length - 1 );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\t\t\tif ( source_array.length > 0 ) {\n\t\t\t\tbuildEmptyRow( rowIndex, true );\n\t\t\t}\n\t\t}\n\n\t\tfunction buildEmptyRow( date_row_index, add_last ) {\n\t\t\tif ( add_last ) {\n\t\t\t\tdate_row_index = date_row_index + 1;\n\t\t\t}\n\t\t\tif ( date_row_index === -1 ) {\n\t\t\t\tvar index = 0;\n\t\t\t} else {\n\t\t\t\tvar date_row = $this.month_date_row_array[date_row_index];\n\t\t\t\tif ( add_last ) {\n\t\t\t\t\tif ( date_row ) {\n\t\t\t\t\t\tindex = $this.schedule_source.indexOf( date_row );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tindex = $this.schedule_source.length;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tindex = $this.schedule_source.indexOf( date_row ) + 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar row = $this.getEmptyWeeklyRow();\n\t\t\trow.type = ScheduleViewControllerRowType.EMPTY;\n\t\t\t$this.schedule_source.splice( index, 0, row );\n\t\t}\n\n\t\tthis.showDailyTotal();\n\t\tthis.showWeeklyTotal();\n\t}\n\n\tbuildYearlySource() {\n\t\tvar $this = this;\n\t\tvar map = {};\n\t\tthis.schedule_source = [];\n\n\t\tvar len = this.final_schedule_data_array.length;\n\n\t\tif ( len < 1 ) {\n\t\t\tbuildEmptyRow();\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar shift = this.final_schedule_data_array[i];\n\t\t\tvar date_string = '';\n\t\t\tif ( shift.date_stamp ) {\n\t\t\t\tvar date = Global.strToDate( shift.date_stamp );\n\t\t\t\tdate_string = date.format( this.full_format );\n\t\t\t}\n\n\t\t\tvar key = this.buildShiftKey( shift );\n\n\t\t\t// each row of schedule data, start from first row\n\t\t\tif ( !map[key] ) {\n\t\t\t\tvar row = {};\n\t\t\t\trow.user_full_name = shift.user_full_name;\n\t\t\t\trow.last_name = shift.last_name;\n\t\t\t\trow.user_id = shift.user_id;\n\t\t\t\trow.branch_id = shift.branch_id;\n\t\t\t\trow.department_id = shift.department_id;\n\t\t\t\trow.schedule_policy_id = shift.schedule_policy_id;\n\t\t\t\trow.job_id = shift.job_id;\n\t\t\t\trow.job_item_id = shift.job_item_id;\n\t\t\t\trow.punch_tag_id = shift.punch_tag_id;\n\n\t\t\t\tvar display_columns = this.select_layout.data.display_columns;\n\t\t\t\tvar display_columns_len = display_columns.length;\n\n\t\t\t\tfor ( var j = 0; j < display_columns_len; j++ ) {\n\t\t\t\t\tvar field_name = display_columns[j];\n\t\t\t\t\trow[field_name] = shift[field_name] ? shift[field_name] : '';\n\t\t\t\t}\n\n\t\t\t\tif ( date_string ) {\n\t\t\t\t\trow[date_string] = shift.status_id == 10 ? 'S' : 'A';\n\t\t\t\t\trow[date_string + '_data'] = shift;\n\t\t\t\t}\n\n\t\t\t\tthis.schedule_source.push( row );\n\t\t\t\tmap[key] = [this.schedule_source.length - 1];\n\t\t\t} else {\n\n\t\t\t\tvar find_position = false;\n\t\t\t\tfor ( var x = 0; x < map[key].length; x++ ) {\n\t\t\t\t\tvar row_index = map[key][x];\n\t\t\t\t\trow = this.schedule_source[row_index];\n\t\t\t\t\tif ( row[date_string] ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tif ( date_string ) {\n\t\t\t\t\t\t\trow[date_string] = shift.status_id == 10 ? 'S' : 'A';\n\t\t\t\t\t\t\trow[date_string + '_data'] = shift;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfind_position = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( !find_position ) {\n\t\t\t\t\trow = {};\n\t\t\t\t\trow.user_full_name = shift.user_full_name;\n\t\t\t\t\trow.last_name = shift.last_name;\n\t\t\t\t\trow.user_id = shift.user_id;\n\t\t\t\t\trow.branch_id = shift.branch_id;\n\t\t\t\t\trow.department_id = shift.department_id;\n\t\t\t\t\trow.schedule_policy_id = shift.schedule_policy_id;\n\t\t\t\t\trow.job_id = shift.job_id;\n\t\t\t\t\trow.job_item_id = shift.job_item_id;\n\t\t\t\t\trow.punch_tag_id = shift.punch_tag_id;\n\n\t\t\t\t\tdisplay_columns = this.select_layout.data.display_columns;\n\t\t\t\t\tdisplay_columns_len = display_columns.length;\n\n\t\t\t\t\tfor ( var j = 0; j < display_columns_len; j++ ) {\n\t\t\t\t\t\tfield_name = display_columns[j];\n\t\t\t\t\t\trow[field_name] = shift[field_name] ? shift[field_name] : '';\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( date_string ) {\n\t\t\t\t\t\trow[date_string] = shift.status_id == 10 ? 'S' : 'A';\n\t\t\t\t\t\trow[date_string + '_data'] = shift;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.schedule_source.push( row );\n\t\t\t\t\tmap[key].push( this.schedule_source.length - 1 );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction buildEmptyRow() {\n\n\t\t\tvar row = {};\n\t\t\trow.user_full_name = '';\n\t\t\trow.last_name = '';\n\t\t\trow.user_id = '';\n\t\t\trow.branch_id = '';\n\t\t\trow.type = ScheduleViewControllerRowType.EMPTY;\n\t\t\t$this.schedule_source.push( row );\n\t\t}\n\n\t\tthis.showWeeklyTotal();\n\t}\n\n\tbuildDailyHeaders() {\n\t\tvar $this = this;\n\t\tvar col_model = this.schedule_columns;\n\t\tvar label_column = col_model[this.select_layout.data.display_columns.length + 1];\n\t\tvar first_time = -1;\n\t\tvar last_time = -1;\n\t\tvar first_date_time = '';\n\t\tvar last_date_time = '';\n\t\tvar first_time_str = '';\n\t\tvar last_time_str = '';\n\t\tvar len = this.has_date_array.length;\n\t\tif ( len === 0 ) {\n\t\t\tvar res = this.api.getScheduleDefaultData( { async: false } );\n\t\t\tvar data = res.getResult();\n\t\t\tvar selected_date_str = $this.getSelectDate();\n\t\t\tfirst_date_time = selected_date_str + ' ' + data.start_time;\n\t\t\tlast_date_time = selected_date_str + ' ' + data.end_time;\n\t\t\tdoNext();\n\t\t\treturn;\n\t\t}\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar item = this.has_date_array[i];\n\n\t\t\tif ( first_time === -1 ) {\n\t\t\t\tfirst_time = item.start_time_stamp;\n\t\t\t\tfirst_date_time = item.start_date;\n\t\t\t\tfirst_time_str = item.start_time;\n\t\t\t} else if ( item.start_time_stamp < first_time ) {\n\t\t\t\tfirst_time = item.start_time_stamp;\n\t\t\t\tfirst_date_time = item.start_date;\n\t\t\t\tfirst_time_str = item.start_time;\n\t\t\t}\n\n\t\t\tif ( last_time === -1 ) {\n\t\t\t\tlast_time = item.end_time_stamp;\n\t\t\t\tlast_date_time = item.end_date;\n\t\t\t\tlast_time_str = item.end_time;\n\t\t\t} else if ( item.end_time_stamp > last_time ) {\n\t\t\t\tlast_time = item.end_time_stamp;\n\t\t\t\tlast_date_time = item.end_date;\n\t\t\t\tlast_time_str = item.end_time;\n\t\t\t}\n\t\t}\n\n\t\tfirst_date_time = Global.getStandardDateTimeStr( first_date_time, first_time_str );\n\t\tlast_date_time = Global.getStandardDateTimeStr( last_date_time, last_time_str );\n\n\t\tdoNext();\n\n\t\tfunction doNext() {\n\t\t\tvar current_date_time = new Date( Global.strToDateTime( first_date_time ).getTime() - 3600000 );\n\t\t\tlast_date_time = Global.strToDateTime( last_date_time );\n\t\t\tvar min = current_date_time.getMinutes() * 60000;\n\t\t\tvar time_span = $( '<div class=\\'day_hour_span\\'></div>' );\n\t\t\tif ( min > 0 ) {\n\t\t\t\tcurrent_date_time = new Date( current_date_time.getTime() - min );\n\t\t\t}\n\t\t\t$this.day_mode_start_date_time = current_date_time;\n\t\t\tvar time_offset = ( last_date_time.getTime() - current_date_time.getTime() ) / 3600000;\n\t\t\tvar header_container = $( '<div class=\\'day_hour_div\\'></div>' );\n\t\t\tvar day_column = $( '<div class=\\'day-column\\'></div>' );\n\t\t\tvar day = $this.start_date.format( $this.weekly_format );\n\t\t\tday = $this.setHolidayHeader( day, true );\n\t\t\tday_column.text( day );\n\t\t\tvar time_columns = $( '<div style=\"padding:0px !important\"></div>' );\n\t\t\tvar time_string = '';\n\n\t\t\t//var time_format_string = 'hh:mm A';\n\t\t\t// var time_format_string = 'h A';\n\t\t\tvar time_format_string = 'hA';\n\t\t\tfor ( var i = 0; i < time_offset; i++ ) {\n\t\t\t\tvar current_hour_text = time_span.clone();\n\t\t\t\tcurrent_hour_text = current_hour_text.text( current_date_time.format( time_format_string ) );\n\t\t\t\tif ( i < time_offset - 1 ) {\n\t\t\t\t\ttime_string = time_string + current_date_time.format( time_format_string ) + '|';\n\t\t\t\t} else {\n\t\t\t\t\ttime_string = time_string + current_date_time.format( time_format_string );\n\t\t\t\t}\n\t\t\t\ttime_columns.append( current_hour_text );\n\t\t\t\tcurrent_date_time = new Date( current_date_time.getTime() + 3600000 );\n\t\t\t}\n\t\t\theader_container.append( day_column );\n\t\t\theader_container.append( time_columns );\n\t\t\t$this.buildTotalShiftDic( time_string );\n\t\t\tlabel_column.label = header_container[0].outerHTML;\n\t\t\t// Include padding.\n\t\t\tlabel_column.width = $this.day_hour_width * time_offset + 40;\n\t\t\t$this.day_header_width = label_column.width;\n\n\t\t}\n\t}\n\n\t//Build dic that contains all daily hours\n\tbuildTotalShiftDic( timeHeader ) {\n\t\tvar label_array = timeHeader.split( '|' );\n\t\tthis.total_shifts_dic = {};\n\t\tfor ( var i = 0; i < label_array.length; i++ ) {\n\t\t\tvar shift_item = { sort_order: i, key: label_array[i], value: 0 };\n\t\t\tthis.total_shifts_dic[label_array[i]] = shift_item;\n\t\t}\n\t}\n\n\tbuildDailySource() {\n\n\t\tvar $this = this;\n\t\tthis.buildDailyHeaders();\n\n\t\tvar map = {};\n\t\tthis.schedule_source = [];\n\n\t\tvar len = this.final_schedule_data_array.length;\n\n\t\tif ( len < 1 ) {\n\t\t\tbuildEmptyRow();\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar shift = this.final_schedule_data_array[i];\n\t\t\tvar date_string = '';\n\t\t\tif ( shift.date_stamp ) {\n\t\t\t\tvar date = Global.strToDate( shift.date_stamp );\n\t\t\t\tdate_string = date.format( this.full_format );\n\t\t\t}\n\n\t\t\tvar key = this.buildShiftKey( shift );\n\n\t\t\t// each row of schedule data, start from first row\n\t\t\tif ( !map[key] ) {\n\t\t\t\tvar row = {};\n\t\t\t\trow.user_full_name = shift.user_full_name;\n\t\t\t\trow.last_name = shift.last_name;\n\t\t\t\trow.user_id = shift.user_id;\n\t\t\t\trow.branch_id = shift.branch_id;\n\t\t\t\trow.department_id = shift.department_id;\n\t\t\t\trow.schedule_policy_id = shift.schedule_policy_id;\n\t\t\t\trow.job_id = shift.job_id;\n\t\t\t\trow.job_item_id = shift.job_item_id;\n\t\t\t\trow.punch_tag_id = shift.punch_tag_id;\n\t\t\t\trow.total = Global.getTimeUnit( shift.total_time );\n\n\t\t\t\tvar display_columns = this.select_layout.data.display_columns;\n\t\t\t\tvar display_columns_len = display_columns.length;\n\n\t\t\t\tfor ( var j = 0; j < display_columns_len; j++ ) {\n\t\t\t\t\tvar field_name = display_columns[j];\n\t\t\t\t\trow[field_name] = shift[field_name] ? shift[field_name] : '';\n\t\t\t\t}\n\n\t\t\t\tif ( date_string ) {\n\t\t\t\t\tif ( shift.status_id == 20 ) {\n\n\t\t\t\t\t\trow[date_string] = $this.getAbsenceCellValue( shift );\n\t\t\t\t\t} else {\n\t\t\t\t\t\trow[date_string] = shift.start_time + ' - ' + shift.end_time;\n\t\t\t\t\t}\n\t\t\t\t\trow[date_string + '_data'] = shift;\n\t\t\t\t}\n\n\t\t\t\tthis.schedule_source.push( row );\n\t\t\t\tmap[key] = [this.schedule_source.length - 1];\n\t\t\t} else {\n\t\t\t\t// if one row already created, go to here to create cells in this row\n\n\t\t\t\tvar find_position = false;\n\t\t\t\tfor ( var x = 0; x < map[key].length; x++ ) {\n\t\t\t\t\tvar row_index = map[key][x];\n\t\t\t\t\trow = this.schedule_source[row_index];\n\t\t\t\t\tif ( row[date_string] ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tif ( date_string ) {\n\t\t\t\t\t\t\tif ( shift.status_id == 20 ) {\n\n\t\t\t\t\t\t\t\trow[date_string] = $this.getAbsenceCellValue( shift );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\trow[date_string] = shift.start_time + ' - ' + shift.end_time;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\trow[date_string + '_data'] = shift;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfind_position = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( !find_position ) {\n\t\t\t\t\trow = {};\n\t\t\t\t\trow.user_full_name = shift.user_full_name;\n\t\t\t\t\trow.last_name = shift.last_name;\n\t\t\t\t\trow.user_id = shift.user_id;\n\t\t\t\t\trow.branch_id = shift.branch_id;\n\t\t\t\t\trow.department_id = shift.department_id;\n\t\t\t\t\trow.schedule_policy_id = shift.schedule_policy_id;\n\t\t\t\t\trow.job_id = shift.job_id;\n\t\t\t\t\trow.job_item_id = shift.job_item_id;\n\t\t\t\t\trow.punch_tag_id = shift.punch_tag_id;\n\t\t\t\t\trow.total = Global.getTimeUnit( shift.total_time );\n\n\t\t\t\t\tdisplay_columns = this.select_layout.data.display_columns;\n\t\t\t\t\tdisplay_columns_len = display_columns.length;\n\n\t\t\t\t\tfor ( var j = 0; j < display_columns_len; j++ ) {\n\t\t\t\t\t\tvar field_name = display_columns[j];\n\t\t\t\t\t\trow[field_name] = shift[field_name] ? shift[field_name] : '';\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( date_string ) {\n\t\t\t\t\t\tif ( shift.status_id == 20 ) {\n\n\t\t\t\t\t\t\trow[date_string] = $this.getAbsenceCellValue( shift );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\trow[date_string] = shift.start_time + ' - ' + shift.end_time;\n\t\t\t\t\t\t}\n\t\t\t\t\t\trow[date_string + '_data'] = shift;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.schedule_source.push( row );\n\t\t\t\t\tmap[key].push( this.schedule_source.length - 1 );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction buildEmptyRow() {\n\n\t\t\tvar row = $this.getEmptyWeeklyRow();\n\t\t\trow.type = ScheduleViewControllerRowType.EMPTY;\n\t\t\t$this.schedule_source.push( row );\n\t\t}\n\n\t\tthis.showDailyTotal();\n\t}\n\n\tbuildWeeklySource() {\n\t\tvar $this = this;\n\t\tvar map = {};\n\t\tthis.schedule_source = [];\n\n\t\tvar len = this.final_schedule_data_array.length;\n\n\t\tif ( len < 1 ) {\n\t\t\tbuildEmptyRow();\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar shift = this.final_schedule_data_array[i];\n\t\t\tvar date_string = '';\n\t\t\tif ( shift.date_stamp ) {\n\t\t\t\tvar date = Global.strToDate( shift.date_stamp );\n\t\t\t\tdate_string = date ? date.format( this.full_format ) : null;\n\t\t\t}\n\n\t\t\tvar key = this.buildShiftKey( shift );\n\n\t\t\t// each row of schedule data, start from first row\n\t\t\tif ( !map[key] ) {\n\t\t\t\tvar row = {};\n\t\t\t\trow.user_full_name = shift.user_full_name;\n\t\t\t\trow.last_name = shift.last_name;\n\t\t\t\trow.user_id = shift.user_id;\n\t\t\t\trow.branch_id = shift.branch_id;\n\t\t\t\trow.department_id = shift.department_id;\n\t\t\t\trow.schedule_policy_id = shift.schedule_policy_id;\n\t\t\t\trow.job_id = shift.job_id;\n\t\t\t\trow.job_item_id = shift.job_item_id;\n\t\t\t\trow.punch_tag_id = shift.punch_tag_id;\n\n\t\t\t\tvar display_columns = this.select_layout.data.display_columns;\n\t\t\t\tvar display_columns_len = display_columns.length;\n\n\t\t\t\tfor ( var j = 0; j < display_columns_len; j++ ) {\n\t\t\t\t\tvar field_name = display_columns[j];\n\t\t\t\t\trow[field_name] = shift[field_name] ? shift[field_name] : '';\n\t\t\t\t}\n\n\t\t\t\tif ( date_string ) {\n\n\t\t\t\t\tif ( shift.status_id == 20 ) {\n\n\t\t\t\t\t\trow[date_string] = $this.getAbsenceCellValue( shift );\n\t\t\t\t\t} else {\n\t\t\t\t\t\trow[date_string] = shift.start_time + ' - ' + shift.end_time;\n\t\t\t\t\t}\n\n\t\t\t\t\trow[date_string + '_data'] = shift;\n\t\t\t\t}\n\n\t\t\t\tthis.schedule_source.push( row );\n\t\t\t\tmap[key] = [this.schedule_source.length - 1];\n\t\t\t} else {\n\t\t\t\t// if one row already created, go to here to create cells in this row\n\n\t\t\t\tvar find_position = false;\n\t\t\t\tfor ( var x = 0; x < map[key].length; x++ ) {\n\t\t\t\t\tvar row_index = map[key][x];\n\t\t\t\t\trow = this.schedule_source[row_index];\n\t\t\t\t\tif ( row[date_string] ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tif ( date_string ) {\n\t\t\t\t\t\t\tif ( shift.status_id == 20 ) {\n\n\t\t\t\t\t\t\t\trow[date_string] = $this.getAbsenceCellValue( shift );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\trow[date_string] = shift.start_time + ' - ' + shift.end_time;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\trow[date_string + '_data'] = shift;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfind_position = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( !find_position ) {\n\t\t\t\t\trow = {};\n\t\t\t\t\trow.user_full_name = shift.user_full_name;\n\t\t\t\t\trow.last_name = shift.last_name;\n\t\t\t\t\trow.user_id = shift.user_id;\n\t\t\t\t\trow.branch_id = shift.branch_id;\n\t\t\t\t\trow.department_id = shift.department_id;\n\t\t\t\t\trow.schedule_policy_id = shift.schedule_policy_id;\n\t\t\t\t\trow.job_id = shift.job_id;\n\t\t\t\t\trow.job_item_id = shift.job_item_id;\n\t\t\t\t\trow.punch_tag_id = shift.punch_tag_id;\n\n\t\t\t\t\tdisplay_columns = this.select_layout.data.display_columns;\n\t\t\t\t\tdisplay_columns_len = display_columns.length;\n\n\t\t\t\t\tfor ( var j = 0; j < display_columns_len; j++ ) {\n\t\t\t\t\t\tfield_name = display_columns[j];\n\t\t\t\t\t\trow[field_name] = shift[field_name] ? shift[field_name] : '';\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( date_string ) {\n\n\t\t\t\t\t\tif ( shift.status_id == 20 ) {\n\n\t\t\t\t\t\t\trow[date_string] = $this.getAbsenceCellValue( shift );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\trow[date_string] = shift.start_time + ' - ' + shift.end_time;\n\t\t\t\t\t\t}\n\t\t\t\t\t\trow[date_string + '_data'] = shift;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.schedule_source.push( row );\n\t\t\t\t\tmap[key].push( this.schedule_source.length - 1 );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction buildEmptyRow() {\n\n\t\t\tvar row = $this.getEmptyWeeklyRow();\n\t\t\trow.type = ScheduleViewControllerRowType.EMPTY;\n\t\t\t$this.schedule_source.push( row );\n\t\t}\n\n\t\tthis.showDailyTotal();\n\t\tthis.showWeeklyTotal();\n\t}\n\n\tgetAbsenceCellValue( shift ) {\n\n\t\tvar result;\n\t\tif ( shift.absence_policy ) {\n\t\t\tif ( shift.note ) {\n\t\t\t\tresult = '*' + shift.absence_policy;\n\t\t\t} else {\n\t\t\t\tresult = shift.absence_policy;\n\t\t\t}\n\t\t} else {\n\t\t\tif ( shift.note ) {\n\t\t\t\tresult = '*' + 'N/A';\n\t\t\t} else {\n\t\t\t\tresult = 'N/A';\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tbuildSortFields() {\n\t\tvar sort_by_fields = [];\n\n\t\t//Error: Uncaught TypeError: Cannot read property 'data' of null in /interface/html5/#!m=Schedule line 5169\n\t\tif ( this.select_layout && this.select_layout.data ) {\n\t\t\tvar display_columns = this.select_layout.data.display_columns;\n\t\t\tvar display_columns_len = display_columns.length;\n\t\t\tif ( display_columns_len > 0 ) {\n\t\t\t\tsort_by_fields = display_columns.slice();\n\t\t\t}\n\t\t}\n\n\t\tsort_by_fields.push( 'user_full_name' );\n\n\t\tsort_by_fields.push( { name: 'start_time_stamp', primer: parseFloat, reverse: false } );\n\n\t\treturn sort_by_fields;\n\t}\n\n\tbuildMonthWeekNoDateArray( current_week_array ) {\n\t\tvar has_date_user_map = {};\n\t\tvar result = [];\n\n\t\tfor ( var i = 0, ii = current_week_array.length; i < ii; i++ ) {\n\t\t\tvar item = Global.clone( current_week_array[i] );\n\t\t\thas_date_user_map[item.user_id] = true;\n\t\t}\n\n\t\tfor ( var key in this.all_user_map ) {\n\t\t\tif ( !has_date_user_map[key] ) {\n\t\t\t\tvar item = Global.clone( this.all_user_map[key] );\n\t\t\t\titem.date_stamp = false;\n\t\t\t\tresult.push( item );\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tbuildNoDateArray() {\n\t\tvar records = [];\n\t\tvar sort_array = [];\n\t\tvar sort_item;\n\t\tvar schedule_data = this.full_schedule_data.schedule_data;\n\t\tfor ( var date_key in schedule_data ) {\n\t\t\tsort_item = {};\n\t\t\tsort_item.value = schedule_data[date_key];\n\t\t\tsort_item.sort_key = date_key;\n\t\t\tsort_array.push( sort_item );\n\t\t}\n\n\t\tvar len = sort_array.length;\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar date_item = sort_array[i];\n\t\t\tfor ( var item_key in date_item.value ) {\n\t\t\t\tvar item = date_item.value[item_key];\n\t\t\t\titem = this.replaceFalseToEmptyStringForSortFields( item );\n\t\t\t\tif ( !item.date_stamp ) {\n\t\t\t\t\trecords.push( date_item.value[item_key] );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\t\treturn records;\n\t}\n\n\tbuildHasDateArray() {\n\t\tvar records = [];\n\t\tthis.all_user_map = {};\n\t\tvar sort_array = [];\n\t\tvar sort_item;\n\t\tvar schedule_data = this.full_schedule_data.schedule_data;\n\n\t\tfor ( var date_key in schedule_data ) {\n\t\t\tsort_item = {};\n\t\t\tsort_item.value = schedule_data[date_key];\n\t\t\tsort_item.sort_key = date_key;\n\t\t\tsort_array.push( sort_item );\n\t\t}\n\t\tvar len = sort_array.length;\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar date_item = sort_array[i];\n\t\t\tfor ( var item_key in date_item.value ) {\n\t\t\t\tvar item = date_item.value[item_key];\n\t\t\t\titem = this.replaceFalseToEmptyStringForSortFields( item );\n\t\t\t\tthis.all_user_map[item.user_id] = Global.clone( item );\n\t\t\t\tif ( item.date_stamp ) {\n\t\t\t\t\trecords.push( date_item.value[item_key] );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\t\treturn records;\n\t}\n\n\treplaceFalseToEmptyStringForSortFields( item ) {\n\t\tif ( !item.branch ) {\n\t\t\titem.branch = '';\n\t\t}\n\n\t\tif ( !item.department ) {\n\t\t\titem.department = '';\n\t\t}\n\n\t\tif ( !item.default_branch ) {\n\t\t\titem.default_branch = '';\n\t\t}\n\n\t\tif ( !item.default_department ) {\n\t\t\titem.default_department = '';\n\t\t}\n\n\t\tif ( !item.job ) {\n\t\t\titem.job = '';\n\t\t}\n\n\t\tif ( !item.job_item ) {\n\t\t\titem.job_item = '';\n\t\t}\n\n\t\tif ( !item.title ) {\n\t\t\titem.title = '';\n\t\t}\n\n\t\treturn item;\n\t}\n\n\tcheckIsSelectedCell( 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.toString() === row_id.toString() && cell.cell_index.toString() === cell_index.toString() ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tbuildScheduleGrid() {\n\t\tvar $this = this;\n\t\tvar grid;\n\t\tvar grid_id = 'grid';\n\n\t\tif ( !this.grid ) {\n\t\t\tgrid = $( 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_id = this.ui_id + '_grid';\n\t\t} else {\n\t\t\tthis.grid.grid.jqGrid( 'GridUnload', true );\n\t\t\tdelete this.grid;\n\t\t\tthis.grid = null;\n\t\t}\n\n\t\tgrid_id = this.ui_id + '_grid';\n\n\t\tif ( !this.schedule_columns || this.schedule_columns.length == 0 ) {\n\t\t\tthis.buildScheduleColumns();\n\t\t}\n\n\t\tthis.grid = new TTGrid( grid_id, {\n\t\t\tdraggble: true,\n\t\t\taltRows: true,\n\t\t\tdata: [],\n\t\t\tdatatype: 'local',\n\t\t\tsortable: false,\n\t\t\tscrollOffset: 0,\n\t\t\trowNum: 10000,\n\t\t\thoverrows: false,\n\t\t\tmultiselectPosition: 'none',\n\t\t\tondblClickRow: function() {\n\t\t\t\t$this.onGridDblClickRow();\n\t\t\t},\n\t\t\tonSelectRow: function( row_id, flag, e ) {\n\t\t\t\tvar row_tr = $( this ).find( '#' + row_id );\n\t\t\t\trow_tr.removeClass( 'ui-state-highlight' ).attr( 'aria-selected', true );\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tonRightClickRow: function( row_id, iRow, cell_index, e ) {\n\t\t\t\tif ( !$this.checkIsSelectedCell( row_id, cell_index ) ) {\n\t\t\t\t\tvar cell_val = $( e.target ).closest( 'td,th' ).html();\n\t\t\t\t\tvar row_tr = $( this ).find( '#' + row_id );\n\t\t\t\t\trow_tr.removeClass( 'ui-state-highlight' ).attr( 'aria-selected', true );\n\t\t\t\t\t$this.onCellSelect( 'timesheet_grid', row_id, cell_index, cell_val, this, e );\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\t$this.onCellSelect( 'timesheet_grid', row_id, cell_index, cell_val, this, e );\n\t\t\t},\n\t\t\tcolNames: [],\n\t\t\t//colModel: this.schedule_columns,\n\t\t\tviewrecords: true,\n\t\t\twinMultiSelect: false,\n\t\t\tsetGridSize: function() {\n\t\t\t\t$this.setGridHeight();\n\t\t\t},\n\t\t\tonResizeGrid: function() {\n\t\t\t\t$this.onResizeGrid(); //Because we have the daily/weekly totals and mode buttons, we need custom grid height logic.\n\t\t\t}\n\t\t}, this.schedule_columns );\n\n\t\tthis.grid.grid.parent().parent().scrollLeft( 1000 );\n\n\t\tthis.grid.grid.parent().parent().scroll( function( e ) {\n\t\t\t$this.scroll_position = $( e.target ).scrollTop();\n\t\t} );\n\n\t\tthis.bindGridColumnEvents();\n\t}\n\n\tonResizeGrid() {\n\t\tif ( this.getMode() == ScheduleViewControllerMode.DAY ) {\n\t\t\t//Rebuild the special shift sizes\n\t\t\tthis.buildCalendars();\n\t\t} else {\n\t\t\tthis.setGridColumnsWidth();\n\t\t}\n\n\t\tthis.setGridHeight();\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\tbindGridColumnEvents() {\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 = $( $( 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 = $( 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;\n\t\t\tvar mode = $this.getMode();\n\n\t\t\tif ( mode === ScheduleViewControllerMode.MONTH ) {\n\t\t\t\tvar colModel = $this.grid.getGridParam( 'colModel' );\n\t\t\t\tdate = $this.getCellRelatedDate( 1, colModel, $( this ).parent().index(), field );\n\t\t\t} else {\n\t\t\t\tdate = Global.strToDate( field, $this.full_format );\n\t\t\t}\n\n\t\t\tif ( date && date.getYear() > 0 ) {\n\t\t\t\t$this.setDatePickerValue( date.format( Global.getLoginUserDateFormat() ) );\n\t\t\t\t$this.highLightSelectDay();\n\t\t\t}\n\n\t\t}\n\t}\n\n\tbuildMonthCell( cell_value, related_data, row, is_day_column ) {\n\t\tvar col_models = this.grid.getGridParam( 'colModel' );\n\t\tvar col_model = related_data.colModel;\n\t\tvar content_div = $( '<div class=\\'schedule-content-div\\'></div>' );\n\t\tif ( is_day_column ) {\n\t\t\tcontent_div.addClass( 'date-column' );\n\t\t}\n\t\tvar time_span = $( '<span class=\\'schedule-time\\' ></span>' );\n\t\tvar item = row[col_model.name + '_data'];\n\t\tvar full_date_str = row[col_model.name + '_full_date'];\n\n\t\tswitch ( row.type ) {\n\t\t\tcase ScheduleViewControllerRowType.TOTAL:\n\t\t\t\ttime_span = $( '<span class=\\'schedule-time total\\'></span>' );\n\t\t\t\tif ( this.select_layout.data.display_columns.indexOf( col_model.index ) === -1 && ['user_full_name', 'shifts', 'absences', 'total_time', 'total_time_wage'].indexOf( col_model.index ) === -1 ) {\n\t\t\t\t\tif ( !cell_value ) {\n\t\t\t\t\t\tvar cell_value = { shifts: 0, absences: 0, total_time: 0, total_time_wage: 0 };\n\t\t\t\t\t}\n\n\t\t\t\t\tvar total_span = $( '<span class=\\'schedule-time total\\'></span>' );\n\t\t\t\t\tvar currency = LocalCacheData.getCurrentCurrencySymbol();\n\t\t\t\t\ttime_span.text( 'S: ' + cell_value.shifts + ' A: ' + cell_value.absences );\n\t\t\t\t\ttotal_span.text( Global.getTimeUnit( cell_value.total_time ) + ' = ' + currency + Global.MoneyRound( cell_value.total_time_wage ) );\n\n\t\t\t\t\tcontent_div.prepend( total_span );\n\t\t\t\t\tcontent_div.prepend( time_span );\n\t\t\t\t\tcontent_div.css( 'height', 'auto' );\n\t\t\t\t} else {\n\t\t\t\t\ttime_span.text( cell_value );\n\t\t\t\t\tcontent_div.prepend( time_span );\n\n\t\t\t\t\tif ( related_data.pos === col_models.length - 1 ) {\n\t\t\t\t\t\tcontent_div.css( 'padding-right', '15px' );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase ScheduleViewControllerRowType.DATE:\n\t\t\t\ttime_span.addClass( 'date' );\n\t\t\t\tcontent_div.addClass( 'month-date-cell' );\n\t\t\t\tif ( cell_value ) {\n\n\t\t\t\t\ttime_span.html( cell_value );\n\n\t\t\t\t\tcontent_div.attr( 'id', this.ui_id + '_grid_' + full_date_str );\n\n\t\t\t\t} else {\n\t\t\t\t\ttime_span.addClass( 'empty-date' );\n\t\t\t\t\ttime_span.text( '.' );\n\t\t\t\t}\n\n\t\t\t\tcontent_div.prepend( time_span );\n\n\t\t\t\tbreak;\n\t\t\tcase ScheduleViewControllerRowType.EMPTY:\n\n\t\t\t\tif ( !Global.isSet( cell_value ) ) {\n\t\t\t\t\ttime_span.text( '' );\n\t\t\t\t}\n\n\t\t\t\ttime_span.addClass( 'empty' );\n\n\t\t\t\tcontent_div.prepend( time_span );\n\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif ( Global.isSet( item ) ) {\n\n\t\t\t\t\tif ( !Global.isSet( item.id ) || !item.id || ( item.id && item.id == TTUUID.zero_id ) ) {\n\t\t\t\t\t\ttime_span.addClass( 'no-id' );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( item.status_id == 20 ) {\n\t\t\t\t\t\ttime_span.addClass( 'red' );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( item.user_id === TTUUID.zero_id ) {\n\t\t\t\t\t\tcontent_div.addClass( 'yellow-outline' );\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( Global.isSet( cell_value ) ) {\n\t\t\t\t\tif ( Global.isSet( item ) && item.note && cell_value.indexOf( '*' ) == -1 ) {\n\t\t\t\t\t\tcell_value = '*' + cell_value;\n\t\t\t\t\t}\n\t\t\t\t\ttime_span.text( cell_value );\n\n\t\t\t\t\tif ( related_data.pos === col_models.length - 1 ) {\n\t\t\t\t\t\tcontent_div.css( 'padding-right', '15px' );\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\ttime_span.text( '' );\n\t\t\t\t}\n\t\t\t\tcontent_div.prepend( time_span );\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn content_div.get( 0 ).outerHTML;\n\t}\n\n\tbuildYearCell( cell_value, related_data, row, is_day_column ) {\n\t\tvar col_models = this.grid.getGridParam( 'colModel' );\n\t\tvar col_model = related_data.colModel;\n\t\tvar content_div = $( '<div class=\\'schedule-content-div\\'></div>' );\n\n\t\tif ( cell_value && cell_value.length == 1 && row.user_full_name == $.i18n._( 'OPEN' ) ) { //#2353 - only way to match open shifts.\n\t\t\tcontent_div.addClass( 'yellow-outline' );\n\t\t}\n\n\t\tif ( is_day_column ) {\n\t\t\tcontent_div.addClass( 'date-column' );\n\t\t}\n\n\t\tif ( !cell_value ) {\n\t\t\t//performance hack to speed up dom and rendering of year mode sheet\n\t\t\treturn content_div.get( 0 ).outerHTML;\n\t\t}\n\t\tvar time_span = $( '<span class=\\'schedule-time\\'></span>' );\n\t\tvar item = row[col_model.name + '_data'];\n\n\t\tswitch ( row.type ) {\n\t\t\tcase ScheduleViewControllerRowType.EMPTY:\n\t\t\t\t// if ( !Global.isSet( cell_value ) ) {\n\t\t\t\t// \ttime_span.text( $.i18n._( 'ZE' ) );\n\t\t\t\t// }\n\n\t\t\t\ttime_span.addClass( 'empty' );\n\n\t\t\t\tcontent_div.prepend( time_span );\n\n\t\t\t\tbreak;\n\t\t\tdefault:\n\n\t\t\t\tif ( col_model.index >= 0 ) {\n\n\t\t\t\t\tif ( cell_value === 'A' ) {\n\t\t\t\t\t\ttime_span.addClass( 'absence-cell' );\n\t\t\t\t\t} else if ( item && ( !item.id || ( item.id && item.id == TTUUID.zero_id ) ) ) {\n\t\t\t\t\t\ttime_span.addClass( 'no-id' );\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( Global.isSet( cell_value ) ) {\n\t\t\t\t\ttime_span.text( cell_value );\n\t\t\t\t} else {\n\t\t\t\t\ttime_span.text( '' );\n\t\t\t\t}\n\n\t\t\t\t// if ( related_data.pos === col_models.length - 1 ) {\n\t\t\t\t// \tcontent_div.css( 'padding-right', '15px' );\n\t\t\t\t// }\n\n\t\t\t\t//\n\t\t\t\t// if ( item && row.full_user_name == $.i18n._('OPEN') ) {\n\t\t\t\t// \tcontent_div.removeClass('date-column')\n\t\t\t\t// \tcontent_div.addClass( 'yellow-outline' );\n\t\t\t\t// }\n\n\t\t\t\tcontent_div.prepend( time_span );\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\treturn content_div[0].outerHTML;\n\t}\n\n\tcalculateScheduleWidth() {\n\t\t//Calculate width of all static columns like employee name, departments, total, etc... So we know how much room is left for the hours.\n\t\tvar static_width = 0;\n\t\tfor ( var i in this.schedule_columns ) {\n\t\t\tif ( !this.schedule_columns[i].is_static_size || this.schedule_columns[i].name == 'total' || this.schedule_columns[i].name == 'scrollbar_spacer' ) {\n\t\t\t\tstatic_width += this.schedule_columns[i].width;\n\t\t\t}\n\t\t}\n\n\t\tif ( Global.isVerticalScrollBarRequired( this.grid_div[0] ) || this.grid.getGridParam().height < this.grid_div[0].offsetHeight ) {\n\t\t\t//This stops showing a redundant horizontal scrollbar that only exists to show the vertical scrollbar.\n\t\t\tstatic_width += Global.getScrollbarWidth();\n\t\t}\n\n\t\tthis.day_hour_width = Math.floor( ( $( '.context-border' ).innerWidth() - static_width ) / $( '.day_hour_div .day_hour_span' ).length );\n\t\tDebug.Text( 'Day Hour Width: ' + this.day_hour_width + ' Static Width: ' + static_width, 'ScheduleViewController.js', 'ScheduleViewController', 'calculateScheduleWidth', 10 );\n\n\t\tif ( this.day_hour_width < 40 ) {\n\t\t\tthis.day_hour_width = 40;\n\t\t}\n\t\treturn this.day_hour_width;\n\t}\n\n\tbuildDayCell( cell_value, related_data, row, is_day_column ) {\n\t\tvar $this = this;\n\t\tvar col_model = related_data.colModel;\n\t\tvar content_div = $( '<div class=\\'schedule-content-div\\'></div>' );\n\t\tif ( is_day_column ) {\n\t\t\tcontent_div.addClass( 'date-column' );\n\t\t}\n\t\tvar time_span = $( '<span class=\\'schedule-time\\'></span>' );\n\t\tvar item = row[col_model.index + '_data'];\n\n\t\tswitch ( row.type ) {\n\t\t\tcase ScheduleViewControllerRowType.TOTAL:\n\n\t\t\t\tif ( cell_value && Global.isSet( cell_value.total_time ) ) {\n\t\t\t\t\tvar total_div = $( '<div style=\\'text-align: left\\'></div>' );\n\t\t\t\t\tvar currency = LocalCacheData.getCurrentCurrencySymbol();\n\t\t\t\t\ttime_span = $( '<span class=\\'schedule-time total\\'></span>' );\n\t\t\t\t\ttime_span.text( 'S: ' + cell_value.shifts + ' A: ' + cell_value.absences + ' ' + Global.getTimeUnit( cell_value.total_time ) + ' = ' + currency + cell_value.total_time_wage );\n\t\t\t\t\tcontent_div.prepend( time_span );\n\n\t\t\t\t\tif ( cell_value.total_shifts_dic ) {\n\t\t\t\t\t\tvar shifts_array = [];\n\t\t\t\t\t\tfor ( var key in cell_value.total_shifts_dic ) {\n\t\t\t\t\t\t\tshifts_array.push( cell_value.total_shifts_dic[key] );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tshifts_array = shifts_array.sort( function( a, b ) {\n\n\t\t\t\t\t\t\treturn Global.compare( a, b, 'sort_order' );\n\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t\tfor ( var i = 0; i < shifts_array.length; i++ ) {\n\t\t\t\t\t\t\tvar item = shifts_array[i];\n\t\t\t\t\t\t\tvar span = $( '<span class=\"day_hour_span\"></span>' );\n\t\t\t\t\t\t\tspan.text( item.value );\n\t\t\t\t\t\t\tspan.width( this.day_hour_width );\n\t\t\t\t\t\t\ttotal_div.append( span );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontent_div.prepend( total_div );\n\t\t\t\t\t}\n\n\t\t\t\t\tcontent_div.css( 'height', 'auto' );\n\n\t\t\t\t} else if ( cell_value ) {\n\t\t\t\t\ttime_span = $( '<span class=\\'schedule-time total\\'></span>' );\n\t\t\t\t\ttime_span.text( cell_value );\n\t\t\t\t\tcontent_div.prepend( time_span );\n\t\t\t\t} else if ( col_model.display_total_column == true ) {\n\t\t\t\t\tcurrency = LocalCacheData.getCurrentCurrencySymbol();\n\t\t\t\t\ttime_span = $( '<span class=\\'schedule-time total\\'></span>' );\n\t\t\t\t\ttime_span.text( 'S: 0 A: 0 00:00 = ' + currency + '0.00' );\n\n\t\t\t\t\tcontent_div.prepend( time_span );\n\t\t\t\t\tcontent_div.css( 'height', 'auto' );\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\tcase ScheduleViewControllerRowType.EMPTY:\n\t\t\t\tif ( !Global.isSet( cell_value ) ) {\n\t\t\t\t\ttime_span.text( '' );\n\t\t\t\t}\n\n\t\t\t\ttime_span.addClass( 'empty' );\n\n\t\t\t\tcontent_div.prepend( time_span );\n\n\t\t\t\tbreak;\n\t\t\tdefault:\n\n\t\t\t\tif ( Global.isSet( item ) ) {\n\t\t\t\t\tcontent_div.removeClass( 'schedule-content-div' ).addClass( 'schedule-content-day-div' );\n\n\t\t\t\t\tif ( related_data.rowId % 2 === 0 ) {\n\t\t\t\t\t\ttime_span.removeClass( 'schedule-time' ).addClass( 'schedule-day-time even' );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttime_span.removeClass( 'schedule-time' ).addClass( 'schedule-day-time' );\n\t\t\t\t\t}\n\n\t\t\t\t\tvar width = $this.getDayShiftWidth( item );\n\t\t\t\t\ttime_span.width( width );\n\t\t\t\t\ttime_span.css( 'left', $this.getDayShiftOffset( item ) );\n\n\t\t\t\t\tif ( !Global.isSet( item.id ) || !item.id || item.id == TTUUID.zero_id ) {\n\t\t\t\t\t\ttime_span.addClass( 'no-day-id' );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( item.status_id == 20 ) {\n\t\t\t\t\t\ttime_span.removeClass( 'even' );\n\t\t\t\t\t\ttime_span.addClass( 'red-bg' );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( item.user_id === TTUUID.zero_id ) {\n\t\t\t\t\t\tcontent_div.addClass( 'yellow-outline' );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( Global.isSet( cell_value ) ) {\n\t\t\t\t\tif ( Global.isSet( item ) && item.note && cell_value.indexOf( '*' ) == -1 ) {\n\t\t\t\t\t\tcell_value = '*' + cell_value;\n\t\t\t\t\t}\n\t\t\t\t\ttime_span.text( cell_value );\n\t\t\t\t} else {\n\t\t\t\t\ttime_span.text( '' );\n\t\t\t\t}\n\t\t\t\tcontent_div.prepend( time_span );\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\treturn content_div.get( 0 ).outerHTML;\n\t}\n\n\tgetDayShiftOffset( shift ) {\n\n\t\tvar start_date_time = Global.strToDateTime( Global.getStandardDateTimeStr( shift.start_date, shift.start_time ) );\n\t\tvar offset = ( start_date_time.getTime() - this.day_mode_start_date_time.getTime() ) / 3600000;\n\n\t\treturn ( offset * this.day_hour_width );\n\t}\n\n\tgetDayShiftWidth( shift ) {\n\t\tvar start_date_time = Global.strToDateTime( Global.getStandardDateTimeStr( shift.start_date, shift.start_time ) );\n\t\tvar end_date_time = Global.strToDateTime( Global.getStandardDateTimeStr( shift.end_date, shift.end_time ) );\n\t\tvar offset = ( end_date_time.getTime() - start_date_time.getTime() ) / 3600000;\n\n\t\t//Debug.Text( 'Using Day Hour Width: '+ this.day_hour_width , 'ScheduleViewController.js', 'ScheduleViewController', 'getDayShiftWidth', 10 );\n\t\treturn ( offset * this.day_hour_width );\n\t}\n\n\tbuildWeekCell( cell_value, related_data, row, is_day_column ) {\n\t\tvar col_models = this.grid.getGridParam( 'colModel' );\n\n\t\tvar col_model = related_data.colModel;\n\t\tvar content_div = $( '<div class=\\'schedule-content-div\\'></div>' );\n\t\tif ( is_day_column ) {\n\t\t\tcontent_div.addClass( 'date-column' );\n\t\t}\n\t\tvar time_span = $( '<span class=\\'schedule-time\\'></span>' );\n\t\tvar item = row[col_model.index + '_data'];\n\n\t\tswitch ( row.type ) {\n\t\t\tcase ScheduleViewControllerRowType.TOTAL:\n\t\t\t\ttime_span = $( '<span class=\\'schedule-time total\\'></span>' );\n\t\t\t\tif ( this.select_layout.data.display_columns.indexOf( col_model.index ) === -1 && ['user_full_name', 'shifts', 'absences', 'total_time', 'total_time_wage'].indexOf( col_model.index ) === -1 ) {\n\t\t\t\t\tif ( !cell_value ) {\n\t\t\t\t\t\tvar cell_value = { shifts: 0, absences: 0, total_time: 0, total_time_wage: 0 };\n\t\t\t\t\t}\n\n\t\t\t\t\tvar total_span = $( '<span class=\\'schedule-time total\\'></span>' );\n\t\t\t\t\tvar currency = LocalCacheData.getCurrentCurrencySymbol();\n\t\t\t\t\ttime_span.text( 'S: ' + cell_value.shifts + ' A: ' + cell_value.absences );\n\t\t\t\t\ttotal_span.text( Global.getTimeUnit( cell_value.total_time ) + ' = ' + currency + Global.MoneyRound( cell_value.total_time_wage ) );\n\n\t\t\t\t\tcontent_div.prepend( total_span );\n\t\t\t\t\tcontent_div.prepend( time_span );\n\t\t\t\t\tcontent_div.css( 'height', 'auto' );\n\t\t\t\t} else {\n\t\t\t\t\ttime_span.text( cell_value );\n\t\t\t\t\tcontent_div.prepend( time_span );\n\n\t\t\t\t\tif ( related_data.pos === col_models.length - 1 ) {\n\t\t\t\t\t\tcontent_div.css( 'padding-right', '15px' );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase ScheduleViewControllerRowType.EMPTY:\n\t\t\t\tif ( !Global.isSet( cell_value ) ) {\n\t\t\t\t\ttime_span.text( '' );\n\t\t\t\t}\n\n\t\t\t\ttime_span.addClass( 'empty' );\n\n\t\t\t\tcontent_div.prepend( time_span );\n\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif ( Global.isSet( item ) ) {\n\t\t\t\t\tif ( !Global.isSet( item.id ) || !item.id || ( item.id && item.id == TTUUID.zero_id ) ) {\n\t\t\t\t\t\ttime_span.addClass( 'no-id' );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( item.status_id == 20 ) {\n\t\t\t\t\t\ttime_span.addClass( 'red' );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( item.user_id === TTUUID.zero_id ) {\n\t\t\t\t\t\tcontent_div.addClass( 'yellow-outline' );\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( Global.isSet( cell_value ) ) {\n\n\t\t\t\t\tif ( Global.isSet( item ) && item.note && cell_value.indexOf( '*' ) == -1 ) {\n\t\t\t\t\t\tcell_value = '*' + cell_value;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( related_data.pos === col_models.length - 1 ) {\n\t\t\t\t\t\tcontent_div.css( 'padding-right', '15px' );\n\t\t\t\t\t}\n\n\t\t\t\t\ttime_span.text( cell_value );\n\t\t\t\t} else {\n\t\t\t\t\ttime_span.text( '' );\n\t\t\t\t}\n\n\t\t\t\tcontent_div.prepend( time_span );\n\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\treturn content_div.get( 0 ).outerHTML;\n\t}\n\n\tonCellFormat( cell_value, related_data, row ) {\n\t\t//cell_value = Global.decodeCellValue( cell_value );\n\t\t/**\n\t\t * FIXES BUG #1999: removed because it was double-encoding values in an attempt to avoid xss attacks.\n\t\t * the following functions handle the needed encoding using a pseudo div element and .outerHTML()\n\t\t * with this function in place, html encoded values come through to jqgrid double-encoded in the schedule view.\n\t\t **/\n\n\t\tvar retval = '';\n\t\tvar $this = this;\n\t\tvar is_day_column = true;\n\n\t\tif ( related_data.colModel.index == 'user_full_name' ) { //always part of grid.\n\t\t\tis_day_column = false;\n\t\t} else {\n\t\t\tfor ( var n in this.all_columns ) {\n\t\t\t\tif ( related_data.colModel.label == this.all_columns[n].label ) {\n\t\t\t\t\tis_day_column = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tswitch ( this.getMode() ) {\n\t\t\tcase ScheduleViewControllerMode.WEEK:\n\t\t\t\treturn this.buildWeekCell( cell_value, related_data, row, is_day_column );\n\t\t\tcase ScheduleViewControllerMode.MONTH:\n\t\t\t\treturn this.buildMonthCell( cell_value, related_data, row, is_day_column );\n\t\t\tcase ScheduleViewControllerMode.YEAR:\n\t\t\t\treturn this.buildYearCell( cell_value, related_data, row, is_day_column );\n\t\t\tcase ScheduleViewControllerMode.DAY:\n\t\t\t\treturn this.buildDayCell( cell_value, related_data, row, is_day_column );\n\t\t}\n\n\t\treturn '';\n\t}\n\n\tonSelectRow( grid_id, row_id, target ) {\n\t\tvar $this = this;\n\t\tvar row_tr = $( target ).find( '#' + row_id );\n\t\trow_tr.removeClass( 'ui-state-highlight' ).attr( 'aria-selected', true );\n\n\t\tvar cells_array = $this.select_cells_Array;\n\t\tvar len = $this.select_cells_Array.length;\n\n\t\tthis.select_all_shifts_array = [];\n\t\tthis.select_shifts_array = [];\n\t\tthis.select_recurring_shifts_array = [];\n\t\tthis.select_cellls_and_shifts_array = [];\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar info = cells_array[i];\n\t\t\trow_tr = $( target ).find( '#' + info.row_id );\n\t\t\tvar cell_td = $( row_tr.find( 'td' )[info.cell_index] );\n\t\t\tcell_td.addClass( 'ui-state-highlight' ).attr( 'aria-selected', true );\n\t\t\tinfo.row_id = info.row_id - 0;\n\t\t\tif ( info.shift ) {\n\t\t\t\tif ( Global.isSet( info.shift.start_date ) ) { //date + time number\n\t\t\t\t\tinfo.shift.start_date_num = Global.strToDateTime( info.shift.start_date ).getTime();\n\n\t\t\t\t} else {\n\t\t\t\t\tinfo.shift.start_date_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\tinfo.shift.row_index = info.row_id - 1;\n\t\t\t\tinfo.shift.cell_index = info.cell_index - 1;\n\n\t\t\t\tinfo.shift.orginal_row_index = info.row_id;\n\t\t\t\tinfo.shift.orginal_cell_index = info.cell_index;\n\n\t\t\t\tthis.select_all_shifts_array.push( info.shift );\n\t\t\t\tthis.select_cellls_and_shifts_array.push( info );\n\n\t\t\t\tif ( info.shift.id && info.shift_id != TTUUID.zero_id ) {\n\t\t\t\t\tthis.select_shifts_array.push( info.shift );\n\t\t\t\t} else {\n\t\t\t\t\tthis.select_recurring_shifts_array.push( info.shift );\n\t\t\t\t}\n\n\t\t\t\tthis.select_all_shifts_array.sort( function( a, b ) {\n\t\t\t\t\tif ( a.cell_index < b.cell_index ) {\n\t\t\t\t\t\treturn -1;\n\t\t\t\t\t}\n\t\t\t\t\tif ( a.cell_index > b.cell_index ) {\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( a.cell_index === b.cell_index ) {\n\t\t\t\t\t\tif ( a.row_index < b.row_index ) {\n\t\t\t\t\t\t\treturn -1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( a.row_index > b.row_index ) {\n\t\t\t\t\t\t\treturn 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn 0;\n\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\tthis.select_cellls_and_shifts_array.push( info );\n\t\t\t}\n\n\t\t\tthis.select_cellls_and_shifts_array.sort( function( a, b ) {\n\t\t\t\tif ( a.cell_index < b.cell_index ) {\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t\tif ( a.cell_index > b.cell_index ) {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\n\t\t\t\tif ( a.cell_index === b.cell_index ) {\n\t\t\t\t\tif ( a.row_id < b.row_id ) {\n\t\t\t\t\t\treturn -1;\n\t\t\t\t\t}\n\t\t\t\t\tif ( a.row_id > b.row_id ) {\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn 0;\n\n\t\t\t} );\n\n\t\t}\n\n\t\tthis.setDefaultMenu();\n\t}\n\n\tgetCellRelatedDate( row_index, col_model, cell_index, data_field ) {\n\t\tvar date;\n\t\tvar date_row_1_index = this.schedule_source.indexOf( this.month_date_row_array[0] );\n\t\tvar date_row_2_index = this.schedule_source.indexOf( this.month_date_row_array[1] );\n\t\tvar date_row_3_index = this.schedule_source.indexOf( this.month_date_row_array[2] );\n\t\tvar date_row_4_index = this.schedule_source.indexOf( this.month_date_row_array[3] );\n\n\t\tif ( row_index < date_row_1_index ) {\n\t\t\tdate = Global.strToDate( col_model[cell_index].index, this.full_format );\n\t\t} else if ( row_index >= date_row_1_index && row_index < date_row_2_index ) {\n\t\t\tdate = Global.strToDate( this.month_date_row_array[0][data_field + '_full_date'], this.full_format );\n\t\t} else if ( row_index >= date_row_2_index && row_index < date_row_3_index ) {\n\t\t\tdate = Global.strToDate( this.month_date_row_array[1][data_field + '_full_date'], this.full_format );\n\t\t} else if ( row_index >= date_row_3_index && row_index < date_row_4_index ) {\n\t\t\tdate = Global.strToDate( this.month_date_row_array[2][data_field + '_full_date'], this.full_format );\n\t\t} else if ( row_index >= date_row_4_index ) {\n\t\t\tdate = Global.strToDate( this.month_date_row_array[3][data_field + '_full_date'], this.full_format );\n\t\t}\n\n\t\treturn date;\n\t}\n\n\tgetDataByCellIndex( row_index, cell_index ) {\n\t\tvar $this = this;\n\t\tvar row = $this.schedule_source[row_index];\n\t\tvar colModel = $this.grid.getGridParam( 'colModel' );\n\n\t\t//Error: TypeError: row is undefined in /interface/html5/framework/jquery.min.js?v=8.0.0-20141117-134330 line 2 > eval line 5952\n\t\t//Error: TypeError: colModel[cell_index] is undefined in /interface/html5/framework/jquery.min.js?v=8.0.0-20141117-134330 line 2 > eval line 5951\n\t\tif ( !colModel || !colModel[cell_index] || !row ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar data_field = colModel[cell_index].name;\n\t\tvar data = row[data_field + '_data'];\n\n\t\treturn data;\n\t}\n\n\tonCellSelect( grid_id, row_id, cell_index, cell_val, target, e ) {\n\t\t$( '#ribbon_view_container .context-menu:visible a' ).click();\n\n\t\tif ( cell_index < 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar $this = this;\n\t\tvar len = 0;\n\t\tvar row;\n\t\tvar colModel;\n\t\tvar data_field;\n\t\tvar shift;\n\t\tvar cells_array = [];\n\t\tvar date;\n\t\tvar mode = this.getMode();\n\n\t\tcells_array = $this.select_cells_Array;\n\n\t\tlen = $this.select_cells_Array.length;\n\n\t\trow = $this.schedule_source[row_id - 1];\n\n\t\tvar row_index = $this.schedule_source.indexOf( row );\n\n\t\tcolModel = $this.grid.getGridParam( 'colModel' );\n\n\t\tdata_field = colModel[cell_index].name;\n\n\t\tshift = row[data_field + '_data'];\n\n\t\tif ( mode === ScheduleViewControllerMode.MONTH ) {\n\t\t\tdate = $this.getCellRelatedDate( row_index, colModel, cell_index, data_field );\n\t\t} else {\n\t\t\tdate = Global.strToDate( data_field, this.full_format );\n\t\t}\n\n\t\tif ( !date || date.getTime() < -1 ) {\n\t\t\tdate = new Date();\n\t\t}\n\n\t\t//Clean all select cells first\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar info = cells_array[i];\n\t\t\tvar row_tr = $( target ).find( '#' + info.row_id );\n\t\t\tvar cell_td = $( 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\tif ( date ) {\n\t\t\tvar date_str = date.format();\n\t\t\tvar time_stamp_num = Global.strToDate( date_str ).getTime();\n\t\t} else {\n\t\t\tdate_str = '';\n\t\t\ttime_stamp_num = 0;\n\t\t}\n\t\t// Add multiple selection 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 < len; i++ ) {\n\t\t\t\tinfo = cells_array[i];\n\t\t\t\t// row id should be number\n\t\t\t\tif ( parseInt( 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\tif ( !found ) {\n\n\t\t\t\tcells_array.push( {\n\t\t\t\t\trow_id: row_id,\n\t\t\t\t\tcell_index: cell_index,\n\t\t\t\t\tcell_val: cell_val,\n\t\t\t\t\tshift: shift,\n\t\t\t\t\tdate: date_str,\n\t\t\t\t\ttime_stamp_num: time_stamp_num,\n\t\t\t\t\tuser_id: row.user_id,\n\t\t\t\t\tbranch_id: row.branch_id,\n\t\t\t\t\tdepartment_id: row.department_id,\n\t\t\t\t\tjob_id: row.job_id,\n\t\t\t\t\tjob_item_id: row.job_item_id,\n\t\t\t\t\tpunch_tag_id: row.punch_tag_id\n\t\t\t\t} );\n\n\t\t\t\t$this.select_cells_Array = cells_array;\n\n\t\t\t\tthis.select_cells_Array.sort( function( a, b ) {\n\n\t\t\t\t\treturn Global.compare( a, b, 'time_stamp_num' );\n\n\t\t\t\t} );\n\n\t\t\t}\n\t\t} else if ( e.shiftKey ) {\n\t\t\tvar start_row_index = row_id;\n\t\t\tvar start_cell_index = 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\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\tinfo = cells_array[i];\n\n\t\t\t\tif ( parseInt( info.row_id ) < parseInt( start_row_index ) ) {\n\t\t\t\t\tstart_row_index = info.row_id;\n\t\t\t\t} else if ( parseInt( info.row_id ) > parseInt( end_row_index ) ) {\n\t\t\t\t\tend_row_index = info.row_id;\n\t\t\t\t}\n\n\t\t\t\tif ( parseInt( info.cell_index ) < parseInt( start_cell_index ) ) {\n\t\t\t\t\tstart_cell_index = info.cell_index;\n\t\t\t\t} else if ( parseInt( info.cell_index ) > parseInt( 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 TimeSheetViewController.js for related change\n\t\t\tif ( cells_array[cells_array.length - 1] && cells_array[0] && cells_array[cells_array.length - 1].cell_index >= cell_index && cells_array[0].cell_index <= cell_index && cells_array[cells_array.length - 1].row_id >= row_id && cells_array[0].row_id <= 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\tstart_row_index = parseInt( start_row_index );\n\t\t\tend_row_index = parseInt( end_row_index );\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 = $( target ).find( '#' + r_index );\n\n\t\t\t\t\tcell_td = $( row_tr.find( 'td' )[c_index] );\n\n\t\t\t\t\tcell_val = cell_td[0].outerHTML;\n\n\t\t\t\t\trow = $this.schedule_source[r_index - 1];\n\n\t\t\t\t\trow_index = $this.schedule_source.indexOf( row );\n\n\t\t\t\t\tcolModel = $this.grid.getGridParam( 'colModel' );\n\n\t\t\t\t\tdata_field = colModel[c_index].name;\n\n\t\t\t\t\tshift = row[data_field + '_data'];\n\n\t\t\t\t\tif ( mode === ScheduleViewControllerMode.MONTH ) {\n\t\t\t\t\t\tdate = $this.getCellRelatedDate( row_index, colModel, c_index, data_field );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdate = Global.strToDate( data_field, this.full_format );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( date && date.getTime() > 0 ) {\n\t\t\t\t\t\tdate_str = date.format();\n\t\t\t\t\t\ttime_stamp_num = Global.strToDate( date_str ).getTime();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdate_str = '';\n\t\t\t\t\t\ttime_stamp_num = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tcells_array.push( {\n\t\t\t\t\t\trow_id: r_index.toString(),\n\t\t\t\t\t\tcell_index: c_index,\n\t\t\t\t\t\tcell_val: cell_val,\n\t\t\t\t\t\tshift: shift,\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\tuser_id: row.user_id,\n\t\t\t\t\t\tbranch_id: row.branch_id,\n\t\t\t\t\t\tdepartment_id: row.department_id,\n\t\t\t\t\t\tjob_id: row.job_id,\n\t\t\t\t\t\tjob_item_id: row.job_item_id,\n\t\t\t\t\t\tpunch_tag_id: row.punch_tag_id\n\t\t\t\t\t} );\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$this.select_cells_Array = cells_array;\n\n\t\t\tthis.select_cells_Array.sort( function( a, b ) {\n\n\t\t\t\treturn Global.compare( a, b, 'time_stamp_num' );\n\n\t\t\t} );\n\n\t\t} else {\n\n\t\t\tcells_array = [\n\t\t\t\t{\n\t\t\t\t\trow_id: row_id,\n\t\t\t\t\tcell_index: cell_index,\n\t\t\t\t\tcell_val: cell_val,\n\t\t\t\t\tshift: shift,\n\t\t\t\t\tdate: date_str,\n\t\t\t\t\ttime_stamp_num: time_stamp_num,\n\t\t\t\t\tuser_id: row.user_id,\n\t\t\t\t\tbranch_id: row.branch_id,\n\t\t\t\t\tdepartment_id: row.department_id,\n\t\t\t\t\tjob_id: row.job_id,\n\t\t\t\t\tjob_item_id: row.job_item_id,\n\t\t\t\t\tpunch_tag_id: row.punch_tag_id\n\t\t\t\t}\n\t\t\t];\n\n\t\t\t$this.select_cells_Array = cells_array;\n\n\t\t\tif ( date && date.getYear() > 0 ) {\n\t\t\t\tthis.setDatePickerValue( date.format( Global.getLoginUserDateFormat() ) );\n\t\t\t\tthis.highLightSelectDay();\n\t\t\t}\n\n\t\t}\n\n\t\t$this.onSelectRow( grid_id, row_id, target );\n\n\t\tvar target_row_tr = $( target ).find( '#' + row_id );\n\t\tvar target_row_td = $( target_row_tr.find( 'td' )[cell_index] );\n\n\t\tif ( target_row_td.attr( 'infor_column' ) ) {\n\t\t\tvar target_row_index = target_row_tr.index();\n\t\t\tvar rowspan = parseInt( target_row_td.attr( 'rowspan' ) );\n\n\t\t\tif ( isNaN( rowspan ) ) {\n\t\t\t\trowspan = 1;\n\t\t\t}\n\n\t\t\tvar last_row = target_row_tr.parent().children().eq( ( target_row_index + rowspan - 1 ) );\n\t\t\tvar last_td = last_row.children().eq( ( last_row.children().length - 1 ) );\n\n\t\t\tvar last_row_id = last_row.attr( 'id' );\n\t\t\tvar last_cell_id = ( last_row.children().length - 1 );\n\t\t\tvar last_cell_value = last_td.find( '.schedule-time' ).text();\n\n\t\t\t$this.onCellSelect( 'timesheet_grid', last_row_id,\n\t\t\t\tlast_cell_id,\n\t\t\t\tlast_cell_value,\n\t\t\t\tthis.grid.grid,\n\t\t\t\t{ shiftKey: true } );\n\n\t\t}\n\t}\n\n\thighLightSelectDay() {\n\n\t\tvar mode = this.getMode();\n\n\t\t$( '.highlight-header' ).removeClass( 'highlight-header' ); //Clean all hight light header or date row\n\n\t\tif ( mode === ScheduleViewControllerMode.MONTH ) {\n\t\t\tvar select_date = Global.strToDate( this.start_date_picker.getValue() );\n\t\t\tvar select_day = select_date.getDay(); // column index is day number for month mode\n\t\t\tselect_date = select_date.format( this.full_format );\n\n\t\t\tvar header = $( '#' + this.ui_id + '_grid_' + select_day );\n\t\t\tvar header_text = $( header.children()[1] ).text();\t //get current column header value\n\n\t\t\tthis.highlight_header = $( '#' + this.ui_id + '_grid_' + select_date ); //get date row\n\n\t\t\tif ( this.highlight_header.length !== 1 ) {\n\t\t\t\tthis.highlight_header = $( '#' + this.ui_id + '_grid_' + select_day ); //get header\n\t\t\t} else {\n\t\t\t\tif ( header_text === this.highlight_header.text() ) {\n\t\t\t\t\t$( '.highlight-header' ).removeClass( 'highlight-header' );\n\t\t\t\t\theader.addClass( 'highlight-header' );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tselect_date = Global.strToDate( this.start_date_picker.getValue() );\n\t\t\t//Error: Uncaught TypeError: Cannot read property 'format' of null in interface/html5/#!m=Schedule&date=null&mode=week line 6295\n\t\t\tif ( !select_date ) {\n\t\t\t\tselect_date = new Date();\n\t\t\t\tthis.setDatePickerValue( select_date.format() );\n\t\t\t}\n\t\t\tselect_date = select_date.format( this.full_format );\n\t\t\tthis.highlight_header = $( '#' + this.ui_id + '_grid_' + select_date );\n\t\t}\n\n\t\tif ( mode !== ScheduleViewControllerMode.DAY ) {\n\n\t\t\tif ( mode === ScheduleViewControllerMode.MONTH ) {\n\t\t\t\tthis.highlight_header.parent().addClass( 'highlight-header' );\n\t\t\t}\n\n\t\t\tthis.highlight_header.addClass( 'highlight-header' );\n\n\t\t}\n\t}\n\n\tbuildAllModeCommonColumns() {\n\t\tvar $this = this;\n\t\tthis.shift_key_name_array = ['user_id'];\n\t\tvar display_columns = this.buildDisplayColumns( this.select_layout.data.display_columns );\n\n\t\tvar len = display_columns.length;\n\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar column = display_columns[i];\n\t\t\tvar column_info = {\n\t\t\t\tname: column.value,\n\t\t\t\tindex: column.value,\n\t\t\t\tlabel: column.label,\n\t\t\t\twidth: 122,\n\t\t\t\tsortable: false,\n\t\t\t\ttitle: false,\n\t\t\t\tfixed: true,\n\t\t\t\tresizable: false,\n\t\t\t\tformatter: function() {\n\n\t\t\t\t\treturn $this.onCellFormat( arguments[0], arguments[1], arguments[2], arguments[3] );\n\t\t\t\t},\n\t\t\t\tcellattr: function( rowId, tv, rawObject, cm, rdata ) {\n\t\t\t\t\tvar field_name = cm.index;\n\t\t\t\t\treturn 'class=\"' + field_name + '_cell\" infor_column=\"true\"';\n\t\t\t\t}\n\t\t\t};\n\t\t\tthis.schedule_columns.push( column_info );\n\t\t\tthis.shift_key_name_array.push( column.value + '_id' );\n\t\t}\n\n\t\tvar employee_column = {\n\t\t\tname: 'user_full_name',\n\t\t\tindex: 'user_full_name',\n\t\t\tlabel: $.i18n._( 'Employee' ),\n\t\t\twidth: 122,\n\t\t\tsortable: false,\n\t\t\ttitle: false,\n\t\t\tfixed: true,\n\t\t\tresizable: false,\n\t\t\tformatter: function() {\n\n\t\t\t\treturn $this.onCellFormat( arguments[0], arguments[1], arguments[2], arguments[3] );\n\t\t\t},\n\t\t\tcellattr: function( rowId, tv, rawObject, cm, rdata ) {\n\t\t\t\tvar field_name = cm.index;\n\t\t\t\treturn 'class=\"' + field_name + '_cell\" infor_column=\"true\"';\n\t\t\t}\n\t\t};\n\n\t\tthis.schedule_columns.push( employee_column );\n\t}\n\n\tbuildMonthRows() {\n\n\t\tvar month_days = ( this.end_date.getTime() - this.start_date.getTime() ) / 86400000 + 1;\n\t\tvar start_day = new Date( this.start_date.getTime() ).getDay();\n\t\tthis.schedule_source = [];\n\t\tvar start_date = new Date( new Date( this.start_date.getTime() ).setDate( this.start_date.getDate() + 7 ) );\n\n\t\tthis.month_date_row_array = [];\n\n\t\tvar row_num = 1;\n\t\tvar z = 0; //day offset\n\n\t\twhile ( row_num < 5 ) {\n\t\t\tvar current_day = start_day;\n\t\t\tvar row = this.getEmptyWeeklyRow();\n\t\t\trow.type = ScheduleViewControllerRowType.DATE;\n\n\t\t\tfor ( var i = 0; i < 7; i++ ) {\n\t\t\t\tvar current_date = new Date( new Date( start_date.getTime() ).setDate( start_date.getDate() + z ) );\n\n\t\t\t\tif ( current_date.getTime() > this.end_date.getTime() ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\trow[current_day] = current_date.format( this.weekly_format );\n\n\t\t\t\trow[current_day] = this.setHolidayHeader( row[current_day] );\n\t\t\t\trow[current_day + '_full_date'] = current_date.format( this.full_format );\n\t\t\t\trow[current_day + '_time'] = current_date.getTime();\n\n\t\t\t\tcurrent_day = current_day + 1;\n\n\t\t\t\tif ( current_day === 7 ) {\n\t\t\t\t\tcurrent_day = 0;\n\t\t\t\t}\n\n\t\t\t\tz = z + 1;\n\t\t\t}\n\n\t\t\tthis.month_date_row_array.push( row );\n\t\t\trow_num = row_num + 1;\n\n\t\t\tthis.schedule_source.push( row );\n\n\t\t}\n\t}\n\n\tgetEmptyWeeklyRow() {\n\t\tvar row = {};\n\t\trow.user_full_name = '';\n\t\trow.last_name = '';\n\t\trow.user_id = '';\n\t\trow.branch_id = '';\n\t\trow.department_id = '';\n\t\trow.schedule_policy_id = '';\n\t\trow.job_id = '';\n\t\trow.job_item_id = '';\n\t\trow.punch_tag_id = [];\n\n\t\tvar display_columns = this.select_layout.data.display_columns;\n\t\tvar display_columns_len = display_columns.length;\n\n\t\tfor ( var j = 0; j < display_columns_len; j++ ) {\n\t\t\tvar field_name = display_columns[j];\n\t\t\trow[field_name] = '';\n\t\t}\n\n\t\treturn row;\n\t}\n\n\tbuildMonthColumns() {\n\t\tvar $this = this;\n\t\tthis.schedule_columns = [];\n\t\tthis.buildAllModeCommonColumns();\n\n//\t\tvar current_date = new Date( this.start_date.getTime() );\n\n\t\tthis.month_date_row_tr_ids = {};\n\t\tfor ( var i = 0; i < 7; i++ ) {\n\t\t\tvar temp_start_date = new Date( this.start_date.getTime() );\n\t\t\tvar current_date = new Date( temp_start_date.setDate( temp_start_date.getDate() + i ) );\n\t\t\tvar start_day = current_date.getDay();\n\t\t\tvar header_text = current_date.format( this.weekly_format );\n\t\t\tvar data_field = start_day;\n\t\t\tif ( data_field === 7 ) {\n\t\t\t\tdata_field = 0;\n\t\t\t}\n\n\t\t\theader_text = this.setHolidayHeader( header_text );\n\n\t\t\tvar full_data_field = current_date.format( this.full_format );\n\n\t\t\tvar column_info = {\n\t\t\t\tresizable: false,\n\t\t\t\tname: data_field.toString(), //Needed for jqgrid otherwise it thinks its an index lookup.\n\t\t\t\tindex: full_data_field,\n\t\t\t\tlabel: header_text,\n\t\t\t\twidth: 150,\n\t\t\t\tfixed: true,\n\t\t\t\tsortable: false,\n\t\t\t\ttitle: false,\n\t\t\t\tformatter: function() {\n\t\t\t\t\treturn $this.onCellFormat( arguments[0], arguments[1], arguments[2], arguments[3] );\n\t\t\t\t},\n\t\t\t\tcellattr: function( rowId, tv, rawObject, cm, rdata ) {\n\t\t\t\t\tif ( rawObject.type === ScheduleViewControllerRowType.DATE ) {\n\t\t\t\t\t\t$this.month_date_row_tr_ids[rowId] = true;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tis_static_size: true\n\t\t\t};\n\t\t\tthis.schedule_columns.push( column_info );\n\n\t\t}\n\n\t\tthis.buildWeeklyTotalColumns();\n\n\t\tthis.schedule_columns.push( {\n\t\t\tname: 'scrollbar_spacer',\n\t\t\tindex: 'scrollbar_spacer',\n\t\t\tlabel: '',\n\t\t\twidth: Global.getScrollbarWidth(),\n\t\t\tsortable: false,\n\t\t\ttitle: false,\n\t\t\tfixed: true,\n\t\t\tis_static_size: true, //Used to skip our own auto-sizing.\n\t\t} );\n\n\t\tthis.buildMonthRows();\n\t}\n\n\tgetDayByDayNum( day ) {\n\n\t\tvar day;\n\t\tswitch ( day ) {\n\t\t\tcase 0:\n\t\t\t\tday = $.i18n._( 'S' );\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tday = $.i18n._( 'M' );\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tday = $.i18n._( 'T' );\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tday = $.i18n._( 'W' );\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tday = $.i18n._( 'T' );\n\t\t\t\tbreak;\n\t\t\tcase 5:\n\t\t\t\tday = $.i18n._( 'F' );\n\t\t\t\tbreak;\n\t\t\tcase 6:\n\t\t\t\tday = $.i18n._( 'S' );\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn day;\n\t}\n\n\tbuildYearColumns() {\n\t\tvar $this = this;\n\t\tthis.schedule_columns = [];\n\n\t\tthis.buildAllModeCommonColumns();\n\n\t\tvar current_date = new Date( this.start_date.getTime() );\n\t\tvar end_date = new Date( this.end_date.getTime() );\n\n\t\tvar i = 0;\n\t\twhile ( current_date.format( this.full_format ) !== end_date.format( this.full_format ) ) {\n\n\t\t\tcurrent_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\t\t\tvar data_field = current_date.format( this.full_format );\n\n\t\t\tvar day = this.getDayByDayNum( current_date.getDay() );\n\n\t\t\tvar column_info = {\n\t\t\t\tname: data_field,\n\t\t\t\tindex: i,\n\t\t\t\tlabel: day + '<br>' + current_date.getDate(),\n\t\t\t\twidth: 22,\n\t\t\t\tsortable: false,\n\t\t\t\ttitle: false,\n\t\t\t\tfixed: true,\n\t\t\t\tis_static_size: true, //Used to skip our own auto-sizing.\n\n\t\t\t\tformatter: function() {\n\n\t\t\t\t\treturn $this.onCellFormat( arguments[0], arguments[1], arguments[2], arguments[3] );\n\t\t\t\t}\n\t\t\t};\n\t\t\tthis.schedule_columns.push( column_info );\n\n\t\t\ti = i + 1;\n\t\t}\n\n\t\tthis.schedule_columns.push( {\n\t\t\tname: 'scrollbar_spacer',\n\t\t\tindex: i,\n\t\t\tlabel: '',\n\t\t\twidth: Global.getScrollbarWidth(),\n\t\t\tsortable: false,\n\t\t\ttitle: false,\n\t\t\tfixed: true,\n\t\t\tis_static_size: true, //Used to skip our own auto-sizing.\n\t\t} );\n\n\t\t//this.buildWeeklyTotalColumns();\n\t}\n\n\tbuildDayColumns() {\n\t\tvar $this = this;\n\t\tthis.schedule_columns = [];\n\n\t\tthis.buildAllModeCommonColumns();\n\n\t\tvar current_date = new Date( this.start_date.getTime() );\n\t\tvar header_text = current_date.format( this.weekly_format );\n\t\tvar data_field = current_date.format( this.full_format );\n\n\t\tvar column_info = {\n\t\t\tfixed: true,\n\t\t\tresizable: false,\n\t\t\twidth: 500,\n\t\t\tname: data_field,\n\t\t\tindex: data_field,\n\t\t\tlabel: 'daily_header_replace',\n\t\t\tis_static_size: true,\n\t\t\tsortable: false,\n\t\t\ttitle: false,\n\t\t\tdisplay_total_column: true,\n\t\t\tformatter: function() {\n\n\t\t\t\treturn $this.onCellFormat( arguments[0], arguments[1], arguments[2], arguments[3] );\n\t\t\t}\n\t\t};\n\t\tthis.schedule_columns.push( column_info );\n\n\t\tcolumn_info = {\n\t\t\tfixed: true,\n\t\t\tresizable: false,\n\t\t\twidth: 122,\n\t\t\tname: 'total',\n\t\t\tindex: 'total',\n\t\t\tlabel: 'Total Time',\n\t\t\tsortable: false,\n\t\t\ttitle: false,\n\t\t\tformatter: function() {\n\n\t\t\t\treturn $this.onCellFormat( arguments[0], arguments[1], arguments[2], arguments[3] );\n\t\t\t}\n\t\t};\n\t\tthis.schedule_columns.push( column_info );\n\n\t\tthis.schedule_columns.push( {\n\t\t\tname: 'scrollbar_spacer',\n\t\t\tindex: 'scrollbar_spacer',\n\t\t\tlabel: '',\n\t\t\twidth: Global.getScrollbarWidth(),\n\t\t\tsortable: false,\n\t\t\ttitle: false,\n\t\t\tfixed: true,\n\t\t\t//is_static_size: false, //Used to skip our own auto-sizing.\n\t\t} );\n\t}\n\n\tbuildWeekColumns() {\n\n\t\tvar $this = this;\n\t\tthis.schedule_columns = [];\n\n\t\tthis.buildAllModeCommonColumns();\n\n\t\t//Error: Uncaught TypeError: Cannot read property 'getTime' of null in /interface/html5/#!m=Schedule&date=20141208&mode=week line 6580\n\t\tif ( !this.start_date ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar current_date = new Date( this.start_date.getTime() );\n\t\tvar end_date = new Date( this.end_date.getTime() );\n\n\t\tvar i = 0;\n\t\tvar set_fixed_width = false;\n//\t\tif ( this.schedule_columns.length === 1 ) {\n//\t\t\tset_fixed_width = false;\n//\t\t}\n\n\t\twhile ( current_date.format( this.full_format ) !== end_date.format( this.full_format ) ) {\n\n\t\t\tcurrent_date = new Date( new Date( this.start_date.getTime() ).setDate( this.start_date.getDate() + i ) );\n\n\t\t\tvar header_text = current_date.format( this.weekly_format );\n\t\t\tvar data_field = current_date.format( this.full_format );\n\n\t\t\theader_text = this.setHolidayHeader( header_text );\n\n\t\t\tvar column_info = {\n\t\t\t\tresizable: false,\n\t\t\t\tname: data_field.toString(), //Needed for jqgrid otherwise it thinks its an index lookup.\n\t\t\t\tindex: data_field,\n\t\t\t\tlabel: header_text,\n\t\t\t\twidth: 150,\n\t\t\t\tfixed: true,\n\t\t\t\tsortable: false,\n\t\t\t\ttitle: false,\n\t\t\t\tformatter: function() {\n\n\t\t\t\t\treturn $this.onCellFormat( arguments[0], arguments[1], arguments[2], arguments[3] );\n\t\t\t\t},\n\t\t\t\tis_static_size: true\n\t\t\t};\n\n\t\t\tthis.schedule_columns.push( column_info );\n\n\t\t\ti = i + 1;\n\n\t\t}\n\n\t\tthis.buildWeeklyTotalColumns();\n\n\t\tthis.schedule_columns.push( {\n\t\t\tname: 'scrollbar_spacer',\n\t\t\tindex: 'scrollbar_spacer',\n\t\t\tlabel: '',\n\t\t\twidth: Global.getScrollbarWidth(),\n\t\t\tsortable: false,\n\t\t\ttitle: false,\n\t\t\tfixed: true,\n\t\t\tis_static_size: true, //Used to skip our own auto-sizing.\n\t\t} );\n\n\t\treturn this.schedule_columns;\n\t}\n\n\tsetHolidayHeader( header_text, inLine ) {\n\n\t\tif ( this.holiday_data_dic ) {\n\t\t\tif ( this.holiday_data_dic[header_text] ) {\n\n\t\t\t\tif ( inLine ) {\n\t\t\t\t\theader_text = header_text + ' (' + Global.htmlEncode( this.holiday_data_dic[header_text].name ) + ')';\n\t\t\t\t} else {\n\t\t\t\t\theader_text = header_text + '<br>' + Global.htmlEncode( this.holiday_data_dic[header_text].name );\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\n\t\treturn header_text;\n\t}\n\n\tbuildWeeklyTotalColumns() {\n\t\tvar $this = this;\n\t\tvar show_weekly_total = this.settings_menu.getButton( 'weekly_totals_btn' ).active;\n\n\t\tvar is_fixed = false;\n\n\t\tif ( show_weekly_total ) {\n\t\t\tvar shifts_column = {\n\t\t\t\tname: 'shifts',\n\t\t\t\tindex: 'shifts',\n\t\t\t\tlabel: $.i18n._( 'Shifts' ),\n\t\t\t\twidth: 50,\n\t\t\t\tsortable: false,\n\t\t\t\ttitle: false,\n\t\t\t\tformatter: function() {\n\t\t\t\t\treturn $this.onCellFormat( arguments[0], arguments[1], arguments[2], arguments[3] );\n\t\t\t\t},\n\t\t\t\tfixed: true\n\t\t\t};\n\n\t\t\tvar absences_column = {\n\t\t\t\tname: 'absences',\n\t\t\t\tindex: 'absences',\n\t\t\t\tlabel: $.i18n._( 'Absences' ),\n\t\t\t\twidth: 70,\n\t\t\t\tsortable: false,\n\t\t\t\ttitle: false,\n\t\t\t\tformatter: function() {\n\t\t\t\t\treturn $this.onCellFormat( arguments[0], arguments[1], arguments[2], arguments[3] );\n\t\t\t\t},\n\t\t\t\tfixed: true\n\t\t\t};\n\n\t\t\tvar total_time = {\n\t\t\t\tname: 'total_time',\n\t\t\t\tindex: 'total_time',\n\t\t\t\tlabel: $.i18n._( 'Total Time' ),\n\t\t\t\twidth: 70,\n\t\t\t\tsortable: false,\n\t\t\t\ttitle: false,\n\t\t\t\tformatter: function() {\n\t\t\t\t\treturn $this.onCellFormat( arguments[0], arguments[1], arguments[2], arguments[3] );\n\t\t\t\t},\n\t\t\t\tfixed: true\n\t\t\t};\n\n\t\t\tvar total_time_wage = {\n\t\t\t\tname: 'total_time_wage',\n\t\t\t\tindex: 'total_time_wage',\n\t\t\t\tlabel: $.i18n._( 'Wages' ),\n\t\t\t\twidth: 90,\n\t\t\t\tsortable: false,\n\t\t\t\ttitle: false,\n\t\t\t\tformatter: function() {\n\t\t\t\t\treturn $this.onCellFormat( arguments[0], arguments[1], arguments[2], arguments[3] );\n\t\t\t\t},\n\t\t\t\tfixed: true\n\t\t\t};\n\n\t\t\tthis.schedule_columns.push( shifts_column );\n\t\t\tthis.schedule_columns.push( absences_column );\n\t\t\tthis.schedule_columns.push( total_time );\n\t\t\tthis.schedule_columns.push( total_time_wage );\n\t\t}\n\t}\n\n\tbuildScheduleColumns() {\n\t\tthis.shift_key_name_array = ['user_id'];\n\t\tthis.schedule_columns = [];\n\n\t\tvar mode = this.getMode();\n\n\t\tswitch ( mode ) {\n\t\t\tcase ScheduleViewControllerMode.WEEK:\n\t\t\t\tthis.buildWeekColumns();\n\t\t\t\tbreak;\n\t\t\tcase ScheduleViewControllerMode.MONTH:\n\t\t\t\tthis.buildMonthColumns();\n\t\t\t\tbreak;\n\t\t\tcase ScheduleViewControllerMode.YEAR:\n\t\t\t\tthis.buildYearColumns();\n\t\t\t\tbreak;\n\t\t\tcase ScheduleViewControllerMode.DAY:\n\t\t\t\tthis.buildDayColumns();\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tsetScheduleGridRowSpan() {\n\n\t\tvar $this = this;\n\n\t\tvar display_columns = this.select_layout.data.display_columns;\n\n\t\tvar display_columns_len = display_columns.length;\n\n\t\tfor ( var i = 0; i < display_columns_len; i++ ) {\n\t\t\tvar column_name = display_columns[i];\n\n\t\t\tstartSet( column_name );\n\t\t}\n\n\t\tstartSet( 'user_full_name' );\n\n\t\tfunction startSet( key ) {\n\t\t\tvar cells = $this.grid.grid.find( '[aria-describedby=' + $this.ui_id + '_grid_' + key + ']' );\n\n\t\t\tvar len = cells.length;\n\n\t\t\tvar count = 0;\n\n\t\t\tvar last_val = null;\n\n\t\t\tvar last_cell = null;\n\n\t\t\tvar need_remove_cells = [];\n\n\t\t\tvar start = len - 1;\n\n\t\t\tsetRows();\n\n\t\t\tfunction setRows() {\n\t\t\t\tfor ( var i = start; i >= 0; i-- ) {\n\t\t\t\t\tvar cell = $( cells[i] );\n\t\t\t\t\tvar cell_val = $( cells[i] ).children().eq( 0 ).children().eq( 0 ).text();\n\n\t\t\t\t\tif ( i === len - 1 ) {\n\t\t\t\t\t\tlast_val = cell_val;\n\t\t\t\t\t\tcount = count + 1;\n\t\t\t\t\t\tlast_cell = cell;\n\t\t\t\t\t} else if ( last_val !== cell_val ) {\n\t\t\t\t\t\tlast_val = cell_val;\n\t\t\t\t\t\tlast_cell.attr( 'rowspan', count );\n\n\t\t\t\t\t\tfor ( var j = 0; j < need_remove_cells.length; j++ ) {\n\t\t\t\t\t\t\tvar need_removed_cell = need_remove_cells[j];\n//\t\t\t\t\t\t\tneed_removed_cell.addClass( 'need-remove' );\n\t\t\t\t\t\t\tvar node = need_removed_cell[0];\n\t\t\t\t\t\t\tif ( node.parentNode ) {\n\t\t\t\t\t\t\t\tnode.style.display = 'none';\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tneed_removed_cell = [];\n\t\t\t\t\t\tcount = 1;\n\t\t\t\t\t\tlast_cell = cell;\n\n\t\t\t\t\t} else if ( i === 0 ) {\n\t\t\t\t\t\tcount = count + 1;\n\t\t\t\t\t\tneed_remove_cells.push( last_cell );\n\t\t\t\t\t\tif ( count > 1 ) {\n\t\t\t\t\t\t\tcell.attr( 'rowspan', count );\n\t\t\t\t\t\t\tfor ( var j = 0; j < need_remove_cells.length; j++ ) {\n\t\t\t\t\t\t\t\tneed_removed_cell = need_remove_cells[j];\n//\t\t\t\t\t\t\t\tneed_removed_cell.addClass( 'need-remove' );\n\t\t\t\t\t\t\t\tnode = need_removed_cell[0];\n\t\t\t\t\t\t\t\tif ( node.parentNode ) {\n\t\t\t\t\t\t\t\t\tnode.style.display = 'none';\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcount = count + 1;\n\t\t\t\t\t\tneed_remove_cells.push( last_cell );\n\t\t\t\t\t\tlast_cell = cell;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\t}\n\n\tonSetSearchFilterFinished() {\n\t}\n\n\tonBuildBasicUIFinished() {\n\t}\n\n\tonBuildAdvUIFinished() {\n\t}\n\n\t// setDateUrl() {\n\t// \tvar $this = this;\n\t// \tif ( !$this.edit_view ) {\n\t//\n\t// \t\tvar mode = this.getMode();\n\t// \t\tvar default_date = $this.start_date_picker.getDefaultFormatValue();\n\t//\n\t// \t\tif ( mode ) {\n\t// \t\t\twindow.location = Global.getBaseURL() + '#!m=' + $this.viewId + '&date=' + default_date + '&mode=' + mode;\n\t// \t\t} else {\n\t// \t\t\tif ( LocalCacheData.getAllURLArgs() && LocalCacheData.getAllURLArgs().mode ) {\n\t// \t\t\t\t$this.setToggleButtonValue( LocalCacheData.getAllURLArgs().mode );\n\t// \t\t\t\tmode = this.getMode();\n\t// \t\t\t\twindow.location = Global.getBaseURL() + '#!m=' + $this.viewId + '&date=' + default_date + '&mode=' + mode;\n\t// \t\t\t} else {\n\t// \t\t\t\twindow.location = Global.getBaseURL() + '#!m=' + $this.viewId + '&date=' + default_date;\n\t// \t\t\t}\n\t// \t\t}\n\t//\n\t// \t}\n\t// },\n\n\treSetURL() {\n\t\tvar mode = this.getMode();\n\t\tvar args;\n\t\tif ( mode ) {\n\t\t\t//args = '#!m=' + this.viewId + '&date=' + this.start_date_picker.getDefaultFormatValue() + '&mode=' + mode;\n\t\t\targs = '#!m=' + this.viewId + '&mode=' + mode;\n\t\t\tGlobal.setURLToBrowser( Global.getBaseURL() + args );\n\t\t} else {\n\t\t\t//args = '#!m=' + this.viewId + '&date=' + this.start_date_picker.getDefaultFormatValue();\n\t\t\targs = '#!m=' + this.viewId;\n\t\t\tGlobal.setURLToBrowser( Global.getBaseURL() + args );\n\t\t}\n\t\tLocalCacheData.setAllURLArgs( Global.buildArgDic( args.split( '&' ) ) );\n\t}\n\n\tsetURL() {\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\tif ( this.canSetURL() ) {\n\t\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\t\ttab_name = tab_name.replace( /\\/|\\s+/g, '' );\n\n\t\t\tvar mode = this.getMode();\n\n\t\t\tif ( this.current_edit_record && this.current_edit_record.id && this.current_edit_record.id != TTUUID.zero_id ) {\n\t\t\t\tif ( a ) {\n\n\t\t\t\t\t//Global.setURLToBrowser( Global.getBaseURL() + '#!m=' + this.viewId + '&date=' + this.start_date_picker.getDefaultFormatValue() + '&mode=' + mode + '&a=' + a + '&id=' + this.current_edit_record.id +\n\t\t\t\t\tGlobal.setURLToBrowser( Global.getBaseURL() + '#!m=' + this.viewId + '&mode=' + mode + '&a=' + a + '&id=' + this.current_edit_record.id +\n\t\t\t\t\t\t'&tab=' + tab_name );\n\n\t\t\t\t} else {\n\t\t\t\t\t//Global.setURLToBrowser( Global.getBaseURL() + '#!m=' + this.viewId + '&date=' + this.start_date_picker.getDefaultFormatValue() + '&mode=' + mode + '&id=' + this.current_edit_record.id );\n\t\t\t\t\tGlobal.setURLToBrowser( Global.getBaseURL() + '#!m=' + this.viewId + '&mode=' + mode + '&id=' + this.current_edit_record.id );\n\n\t\t\t\t}\n\n\t\t\t\tGlobal.trackView( this.viewId, LocalCacheData.current_doing_context_action );\n\n\t\t\t} else {\n\t\t\t\tif ( a ) {\n\n\t\t\t\t\t//Edit a record which don't have id, schedule view Recurring Scedule\n\t\t\t\t\tif ( a === 'edit' ) {\n\t\t\t\t\t\t//Global.setURLToBrowser( Global.getBaseURL() + '#!m=' + this.viewId + '&date=' + this.start_date_picker.getDefaultFormatValue() + '&mode=' + mode + '&a=' + 'new' +\n\t\t\t\t\t\tGlobal.setURLToBrowser( Global.getBaseURL() + '#!m=' + this.viewId + '&mode=' + mode + '&a=' + 'new' +\n\t\t\t\t\t\t\t'&tab=' + tab_name );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t//Global.setURLToBrowser( Global.getBaseURL() + '#!m=' + this.viewId + '&date=' + this.start_date_picker.getDefaultFormatValue() + '&mode=' + mode + '&a=' + a +\n\t\t\t\t\t\tGlobal.setURLToBrowser( Global.getBaseURL() + '#!m=' + this.viewId + '&mode=' + mode + '&a=' + a +\n\t\t\t\t\t\t\t'&tab=' + tab_name );\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\t//Global.setURLToBrowser( Global.getBaseURL() + '#!m=' + this.viewId + '&date=' + this.start_date_picker.getDefaultFormatValue() + '&mode=' + mode );\n\t\t\t\t\tGlobal.setURLToBrowser( Global.getBaseURL() + '#!m=' + this.viewId + '&mode=' + mode );\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t}\n\n\tclearSelection( set_default_menu ) {\n\t\tif ( this.grid && this.grid.grid ) {\n\t\t\tthis.grid.grid.jqGrid( 'resetSelection' );\n\t\t}\n\n\t\tthis.select_cells_Array = [];\n\t\tthis.select_cellls_and_shifts_array = [];\n\t\tthis.select_all_shifts_array = [];\n\n\t\t//Issue #3067 - Causes incorrect context menu to be set when saving a schedule which produces context menu flashing\n\t\t//and button state to change. However this call is required to properly reset mass edit and other context menu buttons.\n\t\tif ( set_default_menu || set_default_menu === undefined ) {\n\t\t\tthis.setDefaultMenu();\n\t\t}\n\t}\n\n\trender() {\n\t\tvar $this = this;\n\t\tsuper.render();\n\n\t\t// Vue Schedule Settings Initialization\n\n\t\tvar schedule_settings_options = [\n\t\t\t{\n\t\t\t\tlabel: $.i18n._( 'Daily Totals' ),\n\t\t\t\tid: 'daily_totals_btn',\n\t\t\t\tno_group_label: true,\n\t\t\t\tvue_icon: 'tticon tticon-settings_black_24dp',\n\t\t\t\taction_group: 'schedule_settings',\n\t\t\t\tmulti_select_group: 2,\n\t\t\t\tvisible: true,\n\t\t\t\tcommand: () => {\n\t\t\t\t\t//Error: Uncaught TypeError: Cannot call method 'clearGridData' of null in /interface/html5/index.php?desktop=1#!m=Schedule&date=20150118&mode=week line 6944\n\t\t\t\t\tif ( !this.checkScheduleData() || !this.grid || !this.grid.grid ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.buildCalendars( true );\n\t\t\t\t\tthis.onResizeGrid();\n\t\t\t\t\tthis.setScheduleGridRowSpan();\n\t\t\t\t\tthis.setMonthDateRowPosition();\n\t\t\t\t\tthis.setGridColumnsWidth();\n\t\t\t\t\tthis.onSearch( true ); //Trigger saving of saved search & layout.\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: $.i18n._( 'Weekly Totals' ),\n\t\t\t\tid: 'weekly_totals_btn',\n\t\t\t\tno_group_label: true,\n\t\t\t\tvue_icon: 'tticon tticon-settings_black_24dp',\n\t\t\t\taction_group: 'schedule_settings',\n\t\t\t\tmulti_select_group: 3,\n\t\t\t\tvisible: true,\n\t\t\t\tcommand: () => {\n\t\t\t\t\tif ( !this.checkScheduleData() ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.buildCalendars();\n\t\t\t\t\tthis.onResizeGrid();\n\t\t\t\t\tthis.onSearch( true ); //Trigger saving of saved search & layout.\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ //Moved to second last item in dropdown as errors were triggering on the VueJS side when visible was set to false, and it was first item in the dropdown.\n\t\t\t\tlabel: $.i18n._( 'Show Unscheduled Employees' ),\n\t\t\t\tid: 'all_employee_btn',\n\t\t\t\tno_group_label: true,\n\t\t\t\tvue_icon: 'tticon tticon-settings_black_24dp',\n\t\t\t\taction_group: 'schedule_settings',\n\t\t\t\tmulti_select_group: 1,\n\t\t\t\tvisible: this.unscheduledEmployeeUIValidate(),\n\t\t\t\t// visible: PermissionManager.checkTopLevelPermission( 'Wage' ),\n\t\t\t\tcommand: () => {\n\t\t\t\t\tthis.search();\n\t\t\t\t\tthis.onSearch( true ); //Trigger saving of saved search & layout.\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: $.i18n._( 'Strict Range' ),\n\t\t\t\tid: 'strict_range_btn',\n\t\t\t\tactive: true,\n\t\t\t\tno_group_label: true,\n\t\t\t\tvue_icon: 'tticon tticon-settings_black_24dp',\n\t\t\t\taction_group: 'schedule_settings',\n\t\t\t\tmulti_select_group: 4,\n\t\t\t\tvisible: true,\n\t\t\t\tcommand: () => {\n\t\t\t\t\t$this.search( false, true );\n\t\t\t\t\t$this.onSearch( true ); //Trigger saving of saved search & layout.\n\t\t\t\t}\n\t\t\t},\n\t\t];\n\n\t\tvar schedule_mode_options = [\n\t\t\t{ label: $.i18n._( 'Day' ), value: 'day' },\n\t\t\t{ label: $.i18n._( 'Week' ), value: 'week' },\n\t\t\t{ label: $.i18n._( 'Month' ), value: 'month' },\n\t\t\t{ label: $.i18n._( 'Year' ), value: 'year' }\n\t\t];\n\n\t\t// Init Vue control bar\n\n\t\tthis.vue_control_bar_mount_id = 'vue-schedule-control-bar';\n\t\tvar root_props = {\n\t\t\tview_id: this.viewId,\n\t\t\tschedule_settings_options: schedule_settings_options,\n\t\t\tschedule_mode_options: schedule_mode_options,\n\t\t}\n\n\t\tTTVueUtils/* default.mountComponent */.Z.mountComponent( this.vue_control_bar_mount_id, ScheduleControlBar, root_props );\n\n\t\tvar date_chooser_div = $( '.schedule-view .date-chooser-div' );\n\n\t\t//The Vue ScheduleControlBar may already contain a date picker from a previous page load.\n\t\t//The parent div needs all children removed to prevent multiple date pickers from being added.\n\t\tdate_chooser_div.empty(); //TODO: Temp hack until root cause is found. Seems to happen on webpack prod but not build:dev:watch.\n\n\t\t//Create Start Date Picker\n\t\tthis.start_date_picker = Global.loadWidgetByName( FormItemType.DATE_PICKER );\n\t\tthis.start_date_picker.TDatePicker( { field: 'start_date' } );\n\t\tvar date_chooser = $( '<span class=\\'label\\'>' + $.i18n._( 'Date' ) + ':</span>' +\n\t\t\t'<img class=\\'left-arrow arrow\\' src=' + Global.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.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\tvar mode = $this.getMode();\n\t\t\tvar new_date;\n\t\t\tvar select_date = $this.start_date;\n\n\t\t\t$this.clearSelection();\n\n\t\t\tif ( !select_date ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tswitch ( mode ) {\n\t\t\t\tcase ScheduleViewControllerMode.WEEK:\n\t\t\t\t\tvar select_date = Global.strToDate( ( ( $this.getSelectDate() ) ? $this.getSelectDate() : new Date().format() ) );\n\t\t\t\t\tnew_date = new Date( new Date( select_date.getTime() ).setDate( select_date.getDate() - 7 ) );\n\t\t\t\t\tbreak;\n\t\t\t\tcase ScheduleViewControllerMode.YEAR:\n\t\t\t\t\tnew_date = new Date( new Date( select_date.getTime() ).setDate( select_date.getDate() - 56 ) ); //8 weeks.\n\t\t\t\t\tbreak;\n\t\t\t\tcase ScheduleViewControllerMode.DAY:\n\t\t\t\t\tnew_date = new Date( new Date( select_date.getTime() ).setDate( select_date.getDate() - 1 ) );\n\t\t\t\t\tbreak\n\t\t\t\tcase ScheduleViewControllerMode.MONTH:\n\t\t\t\t\tif ( $this.settings_menu.getButton( 'strict_range_btn' ).active ) {\n\t\t\t\t\t\tnew_date = new Date( new Date( select_date.getTime() ).setDate( select_date.getDate() - 1 ) );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnew_date = new Date( new Date( select_date.getTime() ).setDate( select_date.getDate() - 36 ) ); //5 weeks + 1 day same as going forward\n }\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tnew_date = new Date( new Date( select_date.getTime() ).setDate( select_date.getDate() - 1 ) );\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\t$this.setDatePickerValue( new_date.format() );\n\t\t\t//$this.setDateUrl();\n\n\t\t\t//$this.buildCalendars();\n\t\t\t$this.search( false, true );\n\t\t} );\n\n\t\tdate_right_arrow.bind( 'click', function() {\n\t\t\tvar mode = $this.getMode();\n\t\t\tvar select_date = $this.end_date;\n\t\t\tvar new_date;\n\t\t\tif ( !select_date ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t$this.clearSelection();\n\n\t\t\tswitch ( mode ) {\n\t\t\t\tcase ScheduleViewControllerMode.WEEK:\n\t\t\t\t\tvar select_date = Global.strToDate( ( ( $this.getSelectDate() ) ? $this.getSelectDate() : new Date().format() ) );\n\t\t\t\t\tnew_date = new Date( new Date( select_date.getTime() ).setDate( select_date.getDate() + 7 ) );\n\t\t\t\t\tbreak;\n\t\t\t\tcase ScheduleViewControllerMode.YEAR:\n\t\t\t\t\tnew_date = new Date( new Date( select_date.getTime() ).setDate( select_date.getDate() + 56 ) ); //8 weeks\n\t\t\t\t\tbreak;\n\t\t\t\tcase ScheduleViewControllerMode.DAY:\n\t\t\t\t\tif ( $this.settings_menu.getButton( 'strict_range_btn' ).active ) {\n new_date = new Date( new Date( select_date.getTime() ).setDate( select_date.getDate() + 1 ) );\n } else {\n new_date = new Date( new Date( select_date.getTime() ).setDate( select_date.getDate() ) );\n }\n\t\t\t\t\tbreak;\n\t\t\t\tcase ScheduleViewControllerMode.MONTH:\n\t\t\t\tdefault:\n\t\t\t\t\tnew_date = new Date( new Date( select_date.getTime() ).setDate( select_date.getDate() + 1 ) );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t$this.setDatePickerValue( new_date.format() );\n\t\t\t//$this.setDateUrl();\n\n\t\t\t//$this.buildCalendars();\n\t\t\t$this.search( false, true );\n\t\t} );\n\n\t\tthis.start_date_picker.bind( 'formItemChange', function() {\n\t\t\t//$this.setDateUrl();\n\t\t\t$this.clearSelection();\n\t\t\t$this.search( false, true );\n\t\t} );\n\n\t\t//Overwrite event listener on layout selector to prevent wrong start date issues by passing true on user_date_picker_date in search().\n\t\t$( this.search_panel.find( '#layout_selector' ) ).off( 'change' ).on( 'change', function() {\n\t\t\t$this.layout_changed = true;\n\n\t\t\tvar selectId = $this.search_panel.find( '#layout_selector' ).find( 'option:selected' ).attr( 'value' );\n\t\t\tvar layouts_array = $this.search_panel.getLayoutsArray();\n\t\t\tvar len = layouts_array.length;\n\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\tvar item = layouts_array[i];\n\n\t\t\t\tif ( item.id == selectId ) {\n\t\t\t\t\t$this.select_layout = item;\n\t\t\t\t\t$this.setSelectLayout();\n\t\t\t\t\t$this.search( false, true );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t}\n\t\t\tGlobal.triggerAnalyticsNavigationOther( 'searchpanel:layout_change', 'click', $this.viewId );\n\t\t} );\n\n\t\t// Vue dummy interface objects for legacy<->new vue menus.\n\t\t// TODO: Improve this by replacing with ES6 classes, and have a parent class of jQueryDummy, with methods for get, set etc, but tie them in with the view id / option bar id, and button id.\n\n\t\tthis.toggle_button = (function( context ) {\n\t\t\tvar _value = 'week';\n\t\t\tcontext.event_bus.on( context.vue_control_bar_mount_id, 'scheduleModeOnChange', updateValueOnChange, TTEventBusStatics.AUTO_CLEAR_ON_EXIT );\n\n\n\t\t\tfunction updateValueOnChange( event_data ) {\n\t\t\t\tDebug.Text( 'Toggle button value update! Change event received. ('+ event_data +').', 'ScheduleViewController.js', 'ScheduleViewController', 'updateValueOnChange', 10 );\n\t\t\t\t_value = event_data.value;\n\t\t\t}\n\n\t\t\tfunction getValue() {\n\t\t\t\treturn _value;\n\t\t\t}\n\n\t\t\tfunction setValue( new_value ) {\n\t\t\t\t_value = new_value; // Set locally in the button immediately, because setToggleButtonValue triggers setToggleButtonUrl which gets the value before the original set command has a chance to send the update to vue and back again to the dummy interface.\n\n\t\t\t\tcontext.event_bus.emit( context.vue_control_bar_mount_id, 'setValue', {\n\t\t\t\t\tkey: 'schedule_mode_options_selected',\n\t\t\t\t\tvalue: new_value\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tgetValue: getValue,\n\t\t\t\tsetValue: setValue\n\t\t\t}\n\t\t})(this);\n\n\t\t// schedule_settings_options\n\n\t\tthis.settings_menu = {\n\t\t\t//If issues happen with race conditions and execution ordeer, you can locally set the array value to the same\n\t\t\t// as what you are about to set the Vue component to, but this might have unexpected effects on the Vue reactive data.\n\t\t\tgetButton( id ) {\n\t\t\t\treturn schedule_settings_options.find( element => element.id === id );\n\t\t\t},\n\t\t\tenableButton( id ) {\n\t\t\t\t// set disable to false\n\t\t\t\t$this.event_bus.emit( $this.vue_control_bar_mount_id, 'setScheduleSettingsState', {\n\t\t\t\t\titem_id: id,\n\t\t\t\t\titem_field: 'disabled',\n\t\t\t\t\titem_value: false\n\t\t\t\t});\n\t\t\t},\n\t\t\tdisableButton( id ) {\n\t\t\t\t// set disable to true\n\t\t\t\t$this.event_bus.emit( $this.vue_control_bar_mount_id, 'setScheduleSettingsState', {\n\t\t\t\t\titem_id: id,\n\t\t\t\t\titem_field: 'disabled',\n\t\t\t\t\titem_value: true\n\t\t\t\t});\n\t\t\t},\n\t\t\tactivateButton( id ) {\n\t\t\t\t// set active to true\n\t\t\t\t$this.event_bus.emit( $this.vue_control_bar_mount_id, 'setSettingActive', {\n\t\t\t\t\titem_id: id\n\t\t\t\t});\n\t\t\t},\n\t\t\tdeactivateButton( id ) {\n\t\t\t\t// set active to false\n\t\t\t\t$this.event_bus.emit( $this.vue_control_bar_mount_id, 'setSettingDeactivated', {\n\t\t\t\t\titem_id: id\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tfunction scheduleModeOnChangeHandler( event_data ) {\n\t\t\tDebug.Text( 'Schedule mode change event received. ('+ event_data +').', 'ScheduleViewController.js', 'ScheduleViewController', 'scheduleModeOnChangeHandler', 10 );\n\n\t\t\t$this.scroll_position = 0;\n\t\t\t$this.select_all_shifts_array = [];\n\t\t\t$this.select_shifts_array = [];\n\t\t\t$this.select_recurring_shifts_array = [];\n\n\t\t\t$this.setToggleButtonUrl();\n\t\t\t$this.search( true, true );\n\t\t\t$this.onSearch( true ); //Trigger saving of saved search & layout, but do not search to stop double search calls.\n\t\t}\n\n\t\tthis.event_bus.on( this.vue_control_bar_mount_id, 'scheduleModeOnChange', scheduleModeOnChangeHandler, TTEventBusStatics.AUTO_CLEAR_ON_EXIT );\n\n\t}\n\n\tcheckScheduleData() {\n\t\tif ( this.full_schedule_data === true ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tshowWeeklyTotal() {\n\t\tvar show_weekly_total = this.settings_menu.getButton( 'weekly_totals_btn' ).active && !this.settings_menu.getButton( 'weekly_totals_btn' ).disabled;\n\n\t\tif ( !show_weekly_total ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar shifts = 0;\n\t\tvar absences = 0;\n\t\tvar total_time = 0;\n\t\tvar total_wage = 0;\n//\t\t var is_date_row = false;\n//\t\t var current_key = [];\n\n\t\tvar mode = this.getMode();\n\n\t\tvar len = this.schedule_source.length;\n\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar row = this.schedule_source[i];\n\n\t\t\tif ( row.type === ScheduleViewControllerRowType.DATE ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfor ( var key in row ) {\n\n\t\t\t\t//As data comes from the grid, we can't be sure of the types of any data within it. (Same goes for item below)\n\t\t\t\tvar data = Global.isSet( row[key] ) ? row[key] : '';\n\n\t\t\t\tif ( Global.isSet( data.user_id ) || ( Global.isArray( data ) && mode === ScheduleViewControllerMode.YEAR && data.every( item => item.total_time_wage ) ) ) {\n\n\t\t\t\t\tif ( mode === ScheduleViewControllerMode.YEAR ) {\n\t\t\t\t\t\tvar data_len = data.length;\n\t\t\t\t\t\tfor ( var j = 0; j < data_len; j++ ) {\n\t\t\t\t\t\t\tvar item = data[j];\n\t\t\t\t\t\t\titem.total_time_wage = parseFloat( item.total_time_wage );\n\t\t\t\t\t\t\titem.total_time = parseFloat( item.total_time );\n\n\t\t\t\t\t\t\tif ( Global.isSet( item.user_id ) ) {\n\t\t\t\t\t\t\t\ttotal_wage = ( item.total_time_wage + total_wage );\n\t\t\t\t\t\t\t\tif ( item.status_id == 10 ) {\n\t\t\t\t\t\t\t\t\ttotal_time = ( item.total_time + total_time );\n\t\t\t\t\t\t\t\t\tshifts = shifts + 1;\n\t\t\t\t\t\t\t\t} else if ( data.status_id == 20 && data.absence_policy_id != TTUUID.zero_id && data.absence_policy_id != TTUUID.not_exist_id ) { //&& data.total_time_wage != 0\n\t\t\t\t\t\t\t\t\ttotal_time = ( item.total_time + total_time );\n\t\t\t\t\t\t\t\t\tabsences = absences + 1;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdata.total_time_wage = parseFloat( data.total_time_wage );\n\t\t\t\t\t\tdata.total_time = parseFloat( data.total_time );\n\t\t\t\t\t\ttotal_wage = ( data.total_time_wage + total_wage );\n\t\t\t\t\t\tif ( data.status_id == 10 ) {\n\t\t\t\t\t\t\ttotal_time = ( data.total_time + total_time );\n\t\t\t\t\t\t\tshifts = shifts + 1;\n\t\t\t\t\t\t} else if ( data.status_id == 20 && data.absence_policy_id != TTUUID.zero_id && data.absence_policy_id != TTUUID.not_exist_id ) { //&& data.total_time_wage != 0\n\t\t\t\t\t\t\ttotal_time = ( data.total_time + total_time );\n\t\t\t\t\t\t\tabsences = absences + 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} else if ( Global.isSet( data.shifts ) ) {\n\t\t\t\t\tdata.total_time_wage = parseFloat( data.total_time_wage );\n\t\t\t\t\tdata.total_time = parseFloat( data.total_time );\n\n\t\t\t\t\ttotal_time = ( data.total_time + total_time );\n\t\t\t\t\ttotal_wage = ( data.total_time_wage + total_wage );\n\n\t\t\t\t\tshifts = shifts + data.shifts;\n\t\t\t\t\tabsences = absences + data.absences;\n\t\t\t\t} else if ( row.type !== ScheduleViewControllerRowType.DATE ) {\n\n\t\t\t\t} else {\n//\t\t\t\t\t current_key[key] = row[key];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trow.total_time = Global.getTimeUnit( total_time );\n\t\t\trow.total_time_wage = LocalCacheData.getCurrentCurrencySymbol() + Global.MoneyRound( total_wage );\n\t\t\t//ViewManagerUtil.getTimeUnit(totalTime);\n\t\t\trow.shifts = shifts;\n\t\t\trow.absences = absences;\n\n\t\t\ttotal_time = 0;\n\t\t\ttotal_wage = 0;\n\t\t\tshifts = 0;\n\t\t\tabsences = 0;\n\t\t}\n\t}\n\n\tbuildTotalShiftsValues( total_shifts_dic, currentItem ) {\n\t\tvar start_date = Global.strToDateTime( currentItem.start_date );\n\t\tvar end_date = Global.strToDateTime( currentItem.end_date );\n\t\tvar start_time_min = start_date.getMinutes();\n\t\tvar end_time_min = end_date.getMinutes();\n\n\t\tstart_date.setMinutes( 0 );\n\t\tend_date.setMinutes( 0 );\n\n\t\tvar start_time = start_date.format( 'hA' );\n\t\tvar end_time = end_date.format( 'hA' );\n\n\t\tvar time_offset = Math.ceil( getTimeOffset( start_date, end_date ) / 60 / 60 );\n\n\t\tvar rest_time;\n\t\tif ( time_offset < 1 ) {\n\n\t\t\ttotal_shifts_dic[end_time].value = total_shifts_dic[end_time].value + Number( ( end_time_min / 60 ).toFixed( 0 ) );\n\t\t} else {\n\t\t\tif ( start_time_min == 0 ) {\n\n\t\t\t\ttotal_shifts_dic[start_time].value = total_shifts_dic[start_time].value + 1;\n\t\t\t} else {\n\t\t\t\ttotal_shifts_dic[start_time].value = total_shifts_dic[start_time].value + Number( ( ( 60 - start_time_min ) /\n\t\t\t\t\t60 ).toFixed( 2 ) );\n\t\t\t}\n\n\t\t\tfor ( var i = 1; i < time_offset; i++ ) {\n\t\t\t\tstart_date.setHours( start_date.getHours() + 1 );\n\t\t\t\t//start_time = start_date.format( 'hh:mm A' );\n\t\t\t\tstart_time = start_date.format( 'hA' );\n\n\t\t\t\tif ( !total_shifts_dic.hasOwnProperty( start_time ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( i == time_offset - 1 ) {\n\t\t\t\t\tif ( end_time_min > 0 ) {\n\t\t\t\t\t\ttotal_shifts_dic[start_time].value = total_shifts_dic[start_time].value + Number( ( end_time_min /\n\t\t\t\t\t\t\t60 ).toFixed( 2 ) );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttotal_shifts_dic[start_time].value = total_shifts_dic[start_time].value + 1;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttotal_shifts_dic[start_time].value = total_shifts_dic[start_time].value + 1;\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction getTimeOffset( startDate, endDate ) {\n\t\t\tif ( !startDate ) {\n\t\t\t\tstartDate = new Date();\n\t\t\t}\n\t\t\tvar sec = ( endDate.getTime() - startDate.getTime() ) / 1000;\n\t\t\treturn sec.toFixed( 0 );\n\t\t}\n\t}\n\n\tshowDailyTotal() {\n\t\tvar show_daily_total = this.settings_menu.getButton( 'daily_totals_btn' ).active && !this.settings_menu.getButton( 'daily_totals_btn' ).disabled;\n\n\t\tif ( !show_daily_total ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar start = true;\n\t\tvar total_row = null;\n\t\tvar column_keys = [];\n\t\tvar over_all_total_row = {};\n\n\t\tvar display_columns = this.select_layout.data.display_columns;\n\t\tvar display_columns_len = display_columns.length;\n\n\t\tfor ( var i = 0; i < display_columns_len; i++ ) {\n\t\t\tvar column_name = display_columns[i];\n\n\t\t\tcolumn_keys.push( { key: column_name, row: null, value: null } );\n\n\t\t}\n\n\t\tvar column_keys_len = column_keys.length;\n\n\t\tfor ( var i = 0; i < this.schedule_source.length; i++ ) {\n\t\t\tvar row = this.schedule_source[i];\n\t\t\tif ( start ) {\n\n\t\t\t\tfor ( var j = 0; j < column_keys_len; j++ ) {\n\t\t\t\t\tvar column_key = column_keys[j];\n\t\t\t\t\ttotal_row = { type: ScheduleViewControllerRowType.TOTAL };\n\t\t\t\t\ttotal_row[column_key.key] = $.i18n._( 'Totals' );\n\t\t\t\t\tcolumn_key.row = total_row;\n\t\t\t\t\tcolumn_key.value = row[column_key.key];\n\n\t\t\t\t}\n\n\t\t\t\tover_all_total_row = { type: ScheduleViewControllerRowType.TOTAL };\n\t\t\t\tover_all_total_row.user_full_name = $.i18n._( 'Overall Totals' );\n\t\t\t}\n\n\t\t\tfor ( var y = column_keys_len - 1; y >= 0; y-- ) {\n\n\t\t\t\tcolumn_key = column_keys[y];\n\n\t\t\t\tif ( ( row[column_key.key] !== column_key.value && i > 0 ) && !start && i !== 0 ) {\n\n\t\t\t\t\tthis.schedule_source.splice( i, 0, column_key.row );\n\t\t\t\t\ti = i + 1;\n\t\t\t\t\ttotal_row = { type: ScheduleViewControllerRowType.TOTAL };\n\t\t\t\t\ttotal_row[column_key.key] = $.i18n._( 'Totals' );\n\t\t\t\t\tcolumn_key.row = total_row;\n\t\t\t\t\tcolumn_key.value = row[column_key.key];\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( start ) {\n\t\t\t\tstart = false;\n\t\t\t}\n\t\t\tif ( row.type === ScheduleViewControllerRowType.DATE ) { //do not calculate date row\n\t\t\t\tthis.schedule_source.splice( i, 0, over_all_total_row );\n\t\t\t\tover_all_total_row = { type: ScheduleViewControllerRowType.TOTAL };\n\t\t\t\tover_all_total_row.user_full_name = $.i18n._( 'Overall Totals' );\n\t\t\t\ti = i + 1;\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfor ( var key in row ) {\n\n\t\t\t\tvar data = Global.isSet( row[key] ) ? row[key] : '';\n\t\t\t\tfor ( var x = 0; x < column_keys_len; x++ ) {\n\n\t\t\t\t\tcolumn_key = column_keys[x];\n\t\t\t\t\ttotal_row = column_key.row;\n\n\t\t\t\t\t//Total rows for each columns\n\t\t\t\t\tif ( data && Global.isSet( data.user_id ) ) {\n\n\t\t\t\t\t\tvar no_data_key = key.replace( '_data', '' );\n\n\t\t\t\t\t\tvar total_row_key_data = total_row[no_data_key];\n\n\t\t\t\t\t\tif ( !total_row_key_data || !Global.isSet( total_row_key_data.total_time ) ) {\n\t\t\t\t\t\t\ttotal_row[no_data_key] = {};\n\t\t\t\t\t\t\ttotal_row_key_data = total_row[no_data_key];\n\t\t\t\t\t\t\ttotal_row_key_data.total_time = 0;\n\t\t\t\t\t\t\ttotal_row_key_data.total_shifts_dic = Global.clone( this.total_shifts_dic );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t//#2381 - total_time can be a string from the API\n\t\t\t\t\t\t\ttotal_row_key_data.total_time = parseInt( total_row_key_data.total_time );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( !Global.isSet( total_row_key_data.shifts ) ) {\n\t\t\t\t\t\t\ttotal_row_key_data.shifts = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( !Global.isSet( total_row_key_data.absences ) ) {\n\t\t\t\t\t\t\ttotal_row_key_data.absences = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( !Global.isSet( total_row_key_data.total_time_wage ) ) {\n\t\t\t\t\t\t\ttotal_row_key_data.total_time_wage = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar row_data = row[no_data_key + '_data'];\n\t\t\t\t\t\t//#2381 - total_time can be a string from the API\n\t\t\t\t\t\trow_data.total_time = parseInt( row_data.total_time );\n\n\t\t\t\t\t\ttotal_row_key_data.total_time_wage = Global.MoneyRound( parseFloat( parseFloat( row_data.total_time_wage ) + parseFloat( total_row_key_data.total_time_wage ) ) );\n\t\t\t\t\t\tif ( row_data.status_id == 10 ) {\n\t\t\t\t\t\t\ttotal_row_key_data.total_time = parseFloat( row_data.total_time ) + parseFloat( total_row_key_data.total_time );\n\t\t\t\t\t\t\ttotal_row_key_data.shifts = total_row_key_data.shifts + 1;\n\t\t\t\t\t\t\tif ( this.getMode() === ScheduleViewControllerMode.DAY ) {\n\t\t\t\t\t\t\t\tthis.buildTotalShiftsValues( total_row_key_data.total_shifts_dic, row[key] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if ( row_data.status_id == 20 && row_data.absence_policy_id != TTUUID.zero_id && row_data.absence_policy_id != TTUUID.not_exist_id ) { //&& row_data.total_time_wage != 0\n\t\t\t\t\t\t\ttotal_row_key_data.total_time = parseFloat( row_data.total_time ) + parseFloat( total_row_key_data.total_time );\n\t\t\t\t\t\t\ttotal_row_key_data.absences = total_row_key_data.absences + 1;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\t//Total rows for all employees\n\n\t\t\t\tif ( data && Global.isSet( data.user_id ) ) {\n\n\t\t\t\t\tno_data_key = key.replace( '_data', '' );\n\n\t\t\t\t\ttotal_row_key_data = over_all_total_row[no_data_key];\n\n\t\t\t\t\tif ( !total_row_key_data || !Global.isSet( total_row_key_data.total_time ) ) {\n\t\t\t\t\t\tover_all_total_row[no_data_key] = {};\n\t\t\t\t\t\ttotal_row_key_data = over_all_total_row[no_data_key];\n\t\t\t\t\t\ttotal_row_key_data.total_time = 0;\n\t\t\t\t\t\ttotal_row_key_data['total_shifts_dic'] = Global.clone( this.total_shifts_dic );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !Global.isSet( total_row_key_data.shifts ) ) {\n\t\t\t\t\t\ttotal_row_key_data.shifts = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !Global.isSet( total_row_key_data.absences ) ) {\n\t\t\t\t\t\ttotal_row_key_data.absences = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !Global.isSet( total_row_key_data.total_time_wage ) ) {\n\t\t\t\t\t\ttotal_row_key_data.total_time_wage = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\trow_data = row[no_data_key + '_data'];\n\n\t\t\t\t\ttotal_row_key_data.total_time_wage = Global.MoneyRound( parseFloat( parseFloat( row_data.total_time_wage ) + parseFloat( total_row_key_data.total_time_wage ) ) );\n\t\t\t\t\tif ( row_data.status_id == 10 ) {\n\t\t\t\t\t\ttotal_row_key_data.total_time = parseFloat( row_data.total_time ) + parseFloat( total_row_key_data.total_time );\n\t\t\t\t\t\ttotal_row_key_data.shifts = total_row_key_data.shifts + 1;\n\t\t\t\t\t\tif ( this.getMode() === ScheduleViewControllerMode.DAY ) {\n\t\t\t\t\t\t\tthis.buildTotalShiftsValues( total_row_key_data.total_shifts_dic, row[key] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( row_data.status_id == 20 && row_data.absence_policy_id != TTUUID.zero_id && row_data.absence_policy_id != TTUUID.not_exist_id ) { //&& row_data.total_time_wage != 0\n\t\t\t\t\t\ttotal_row_key_data.total_time = parseFloat( row_data.total_time ) + parseFloat( total_row_key_data.total_time );\n\t\t\t\t\t\ttotal_row_key_data.absences = total_row_key_data.absences + 1;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( i === this.schedule_source.length - 1 ) {\n\t\t\t\tfor ( var j = column_keys.length - 1; j >= 0; j-- ) {\n\t\t\t\t\tthis.schedule_source.push( column_keys[j].row );\n\t\t\t\t}\n\t\t\t\tthis.schedule_source.push( over_all_total_row );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tbuildSearchFields() {\n\t\tsuper.buildSearchFields();\n\t\tvar $this = this;\n\n\t\tvar default_args = { permission_section: 'schedule' };\n\n\t\tif ( PermissionManager.validate( this.permission_id, 'view' ) || PermissionManager.validate( this.permission_id, 'view_child' ) ) {\n\t\t\tthis.search_fields = [\n\t\t\t\tnew SearchField( {\n\t\t\t\t\tlabel: $.i18n._( 'Status' ),\n\t\t\t\t\tin_column: 1,\n\t\t\t\t\tfield: 'status_id',\n\t\t\t\t\tmultiple: true,\n\t\t\t\t\tbasic_search: true,\n\t\t\t\t\tadv_search: true,\n\t\t\t\t\tlayout_name: 'global_option_column',\n\t\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t\t} ),\n\n\t\t\t\tnew SearchField( {\n\t\t\t\t\tlabel: $.i18n._( 'Schedule Branch' ),\n\t\t\t\t\tin_column: 1,\n\t\t\t\t\tfield: 'schedule_branch_ids',\n\t\t\t\t\tlayout_name: 'global_branch',\n\t\t\t\t\tapi_class: TTAPI.APIBranch,\n\t\t\t\t\tmultiple: true,\n\t\t\t\t\tbasic_search: true,\n\t\t\t\t\tadv_search: true,\n\t\t\t\t\tscript_name: 'BranchView',\n\t\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t\t} ),\n\n\t\t\t\tnew SearchField( {\n\t\t\t\t\tlabel: $.i18n._( 'Schedule Department' ),\n\t\t\t\t\tin_column: 1,\n\t\t\t\t\tfield: 'department_ids',\n\t\t\t\t\tlayout_name: 'global_department',\n\t\t\t\t\tapi_class: TTAPI.APIDepartment,\n\t\t\t\t\tmultiple: true,\n\t\t\t\t\tbasic_search: true,\n\t\t\t\t\tadv_search: true,\n\t\t\t\t\tscript_name: 'DepartmentView',\n\t\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t\t} ),\n\n\t\t\t\tnew SearchField( {\n\t\t\t\t\tlabel: $.i18n._( 'Default Branch' ),\n\t\t\t\t\tin_column: 1,\n\t\t\t\t\tfield: 'default_branch_ids',\n\t\t\t\t\tlayout_name: 'global_branch',\n\t\t\t\t\tapi_class: TTAPI.APIBranch,\n\t\t\t\t\tmultiple: true,\n\t\t\t\t\tbasic_search: false,\n\t\t\t\t\tadv_search: true,\n\t\t\t\t\tscript_name: 'BranchView',\n\t\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t\t} ),\n\n\t\t\t\tnew SearchField( {\n\t\t\t\t\tlabel: $.i18n._( 'Default Department' ),\n\t\t\t\t\tin_column: 1,\n\t\t\t\t\tfield: 'default_department_ids',\n\t\t\t\t\tlayout_name: 'global_department',\n\t\t\t\t\tapi_class: TTAPI.APIDepartment,\n\t\t\t\t\tmultiple: true,\n\t\t\t\t\tbasic_search: false,\n\t\t\t\t\tadv_search: true,\n\t\t\t\t\tscript_name: 'DepartmentView',\n\t\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t\t} ),\n\n\t\t\t\tnew SearchField( {\n\t\t\t\t\tlabel: $.i18n._( 'Group' ),\n\t\t\t\t\tin_column: 2,\n\t\t\t\t\tmultiple: true,\n\t\t\t\t\tfield: 'group_ids',\n\t\t\t\t\tlayout_name: 'global_tree_column',\n\t\t\t\t\ttree_mode: true,\n\t\t\t\t\tbasic_search: true,\n\t\t\t\t\tadv_search: true,\n\t\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t\t} ),\n\n\t\t\t\tnew SearchField( {\n\t\t\t\t\tlabel: $.i18n._( 'Title' ),\n\t\t\t\t\tfield: 'title_id',\n\t\t\t\t\tin_column: 2,\n\t\t\t\t\tlayout_name: 'global_job_title',\n\t\t\t\t\tapi_class: TTAPI.APIUserTitle,\n\t\t\t\t\tmultiple: true,\n\t\t\t\t\tbasic_search: true,\n\t\t\t\t\tadv_search: true,\n\t\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t\t} ),\n\n\t\t\t\tnew SearchField( {\n\t\t\t\t\tlabel: $.i18n._( 'Job' ),\n\t\t\t\t\tin_column: 2,\n\t\t\t\t\tfield: 'job_id',\n\t\t\t\t\tlayout_name: 'global_job',\n\t\t\t\t\tapi_class: ( Global.getProductEdition() >= 20 ) ? TTAPI.APIJob : null,\n\t\t\t\t\tmultiple: true,\n\t\t\t\t\tbasic_search: false,\n\t\t\t\t\tadv_search: ( this.show_job_ui && ( Global.getProductEdition() >= 20 ) ),\n\t\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t\t} ),\n\n\t\t\t\tnew SearchField( {\n\t\t\t\t\tlabel: $.i18n._( 'Task' ),\n\t\t\t\t\tin_column: 2,\n\t\t\t\t\tfield: 'job_item_id',\n\t\t\t\t\tlayout_name: 'global_job_item',\n\t\t\t\t\tapi_class: ( Global.getProductEdition() >= 20 ) ? TTAPI.APIJobItem : null,\n\t\t\t\t\tmultiple: true,\n\t\t\t\t\tbasic_search: false,\n\t\t\t\t\tadv_search: ( this.show_job_item_ui && ( Global.getProductEdition() >= 20 ) ),\n\t\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t\t} ),\n\n\t\t\t\tnew SearchField( {\n\t\t\t\t\tlabel: $.i18n._( 'Recurring Template' ),\n\t\t\t\t\tfield: 'recurring_schedule_template_control_id',\n\t\t\t\t\tin_column: 2,\n\t\t\t\t\tlayout_name: 'global_recurring_schedule_control',\n\t\t\t\t\tapi_class: TTAPI.APIRecurringScheduleTemplateControl,\n\t\t\t\t\tmultiple: true,\n\t\t\t\t\tbasic_search: false,\n\t\t\t\t\tadv_search: true,\n\t\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t\t} ),\n\n\t\t\t\tnew SearchField( {\n\t\t\t\t\tlabel: $.i18n._( 'Absence Policy' ),\n\t\t\t\t\tfield: 'absence_policy_id',\n\t\t\t\t\tin_column: 3,\n\t\t\t\t\tlayout_name: 'global_absences',\n\t\t\t\t\tapi_class: TTAPI.APIAbsencePolicy,\n\t\t\t\t\tmultiple: true,\n\t\t\t\t\tbasic_search: false,\n\t\t\t\t\tadv_search: true,\n\t\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t\t} ),\n\n\t\t\t\tnew SearchField( {\n\t\t\t\t\tlabel: $.i18n._( 'Include Employees' ),\n\t\t\t\t\tin_column: 3,\n\t\t\t\t\tfield: 'include_user_ids',\n\t\t\t\t\tlayout_name: 'global_user',\n\t\t\t\t\tapi_class: TTAPI.APIUser,\n\t\t\t\t\tmultiple: true,\n\t\t\t\t\tbasic_search: false,\n\t\t\t\t\tadv_search: true,\n\t\t\t\t\tdefault_args: default_args,\n\t\t\t\t\taddition_source_function: ( function( target, source_data ) {\n\t\t\t\t\t\treturn $this.onEmployeeSourceCreate( target, source_data );\n\t\t\t\t\t} ),\n\t\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t\t} ),\n\n\t\t\t\tnew SearchField( {\n\t\t\t\t\tlabel: $.i18n._( 'Exclude Employees' ),\n\t\t\t\t\tin_column: 3,\n\t\t\t\t\tfield: 'exclude_user_ids',\n\t\t\t\t\tlayout_name: 'global_user',\n\t\t\t\t\tapi_class: TTAPI.APIUser,\n\t\t\t\t\tmultiple: true,\n\t\t\t\t\tbasic_search: false,\n\t\t\t\t\tadv_search: true,\n\t\t\t\t\tdefault_args: default_args,\n\t\t\t\t\taddition_source_function: ( function( target, source_data ) {\n\t\t\t\t\t\treturn $this.onEmployeeSourceCreate( target, source_data );\n\t\t\t\t\t} ),\n\t\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t\t} )\n\t\t\t];\n\t\t} else {\n\t\t\t//Allow regular employees to add job/task columns if needed, and do some other basic searches.\n\t\t\tthis.search_fields = [];\n\n\t\t\tthis.search_fields.push(\n\t\t\t\tnew SearchField( {\n\t\t\t\t\tlabel: $.i18n._( 'Status' ),\n\t\t\t\t\tin_column: 1,\n\t\t\t\t\tfield: 'status_id',\n\t\t\t\t\tmultiple: true,\n\t\t\t\t\tbasic_search: true,\n\t\t\t\t\tadv_search: false,\n\t\t\t\t\tlayout_name: 'global_option_column',\n\t\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t\t} ) );\n\n\t\t\t//Check punch permissions rather than schedule, since this is a regular employee who likely wouldn't have\n\t\t\tif ( PermissionManager.validate( 'punch', 'edit_branch' ) || PermissionManager.validate( this.permission_id, 'edit_branch' ) ) {\n\t\t\t\tthis.search_fields.push(\n\t\t\t\t\tnew SearchField( {\n\t\t\t\t\t\tlabel: $.i18n._( 'Schedule Branch' ),\n\t\t\t\t\t\tin_column: 1,\n\t\t\t\t\t\tfield: 'schedule_branch_ids',\n\t\t\t\t\t\tlayout_name: 'global_branch',\n\t\t\t\t\t\tapi_class: TTAPI.APIBranch,\n\t\t\t\t\t\tmultiple: true,\n\t\t\t\t\t\tbasic_search: true,\n\t\t\t\t\t\tadv_search: false,\n\t\t\t\t\t\tscript_name: 'BranchView',\n\t\t\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t\t\t} ) );\n\t\t\t}\n\n\t\t\tif ( PermissionManager.validate( 'punch', 'edit_department' ) || PermissionManager.validate( this.permission_id, 'edit_department' ) ) {\n\t\t\t\tthis.search_fields.push(\n\t\t\t\t\tnew SearchField( {\n\t\t\t\t\t\tlabel: $.i18n._( 'Schedule Department' ),\n\t\t\t\t\t\tin_column: 1,\n\t\t\t\t\t\tfield: 'department_ids',\n\t\t\t\t\t\tlayout_name: 'global_department',\n\t\t\t\t\t\tapi_class: TTAPI.APIDepartment,\n\t\t\t\t\t\tmultiple: true,\n\t\t\t\t\t\tbasic_search: true,\n\t\t\t\t\t\tadv_search: false,\n\t\t\t\t\t\tscript_name: 'DepartmentView',\n\t\t\t\t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t\t\t} ) );\n\t\t\t}\n\n\t\t\t//Could be permission issues with this, so disable for now.\n\t\t\t// if ( Global.getProductEdition() >= 20 && ( PermissionManager.validate( 'punch', 'edit_job' ) || PermissionManager.validate( this.permission_id, 'edit_job' ) ) ) {\n\t\t\t// \tthis.search_fields.push(\n\t\t\t// \t\tnew SearchField( {\n\t\t\t// \t\t\tlabel: $.i18n._( 'Job' ),\n\t\t\t// \t\t\tin_column: 2,\n\t\t\t// \t\t\tfield: 'job_id',\n\t\t\t// \t\t\tlayout_name: 'global_job',\n\t\t\t// \t\t\tapi_class: ( Global.getProductEdition() >= 20 ) ? TTAPI.APIJob : null,\n\t\t\t// \t\t\tmultiple: true,\n\t\t\t// \t\t\tbasic_search: true,\n\t\t\t// \t\t\tadv_search: false,\n\t\t\t// \t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t// \t\t} ) );\n\t\t\t// }\n\t\t\t//\n\t\t\t// if ( Global.getProductEdition() >= 20 && ( PermissionManager.validate( 'punch', 'edit_job_item' ) || PermissionManager.validate( this.permission_id, 'edit_job_item' ) ) ) {\n\t\t\t// \tthis.search_fields.push(\n\t\t\t// \t\tnew SearchField( {\n\t\t\t// \t\t\tlabel: $.i18n._( 'Task' ),\n\t\t\t// \t\t\tin_column: 2,\n\t\t\t// \t\t\tfield: 'job_item_id',\n\t\t\t// \t\t\tlayout_name: 'global_job_item',\n\t\t\t// \t\t\tapi_class: ( Global.getProductEdition() >= 20 ) ? TTAPI.APIJobItem : null,\n\t\t\t// \t\t\tmultiple: true,\n\t\t\t// \t\t\tbasic_search: true,\n\t\t\t// \t\t\tadv_search: false,\n\t\t\t// \t\t\tform_item_type: FormItemType.AWESOME_BOX\n\t\t\t// \t\t} ) );\n\t\t\t// }\n\n\t\t}\n\t}\n\n\tonSourceDataCreate( target, source_data ) {\n\n\t\t//if ( !this.is_mass_adding ) {\n\t\t//\treturn source_data;\n\t\t//}\n\t\tvar $this = this;\n\t\tvar display_columns = target.getDisplayColumns();\n\t\tvar first_item = {};\n\t\tvar second_item = {};\n\n\t\t//FIXME: what should we do about -2?\n\n\t\t$.each( display_columns, function( index, content ) {\n\t\t\tfirst_item.id = TTUUID.not_exist_id;\n\t\t\tfirst_item[content.name] = Global.default_item;\n\t\t\tif ( $this.select_cells_Array.length > 0 && !$this.is_mass_editing ) {\n\t\t\t\tsecond_item.id = '-2';\n\t\t\t\tsecond_item[content.name] = Global.selected_item;\n\t\t\t}\n\t\t\treturn false;\n\t\t} );\n\n\t\t//Error: Object doesn't support property or method 'unshift' in /interface/html5/line 6953\n\t\tif ( !source_data || $.type( source_data ) !== 'array' ) {\n\t\t\tsource_data = [];\n\t\t}\n\t\tif ( this.select_cells_Array.length > 0 && !$this.is_mass_editing ) {\n\t\t\tsource_data.unshift( second_item );\n\t\t}\n\t\tsource_data.unshift( first_item );\n\n\t\treturn source_data;\n\t}\n\n\tonSourceDataCreatePunchTag( target, source_data ) {\n\n\t\t//if ( !this.is_mass_adding ) {\n\t\t//\treturn source_data;\n\t\t//}\n\t\tvar $this = this;\n\t\tvar display_columns = target.getDisplayColumns();\n\t\tvar first_item = {};\n\n\t\t$.each( display_columns, function( index, content ) {\n\t\t\tfirst_item.id = TTUUID.not_exist_id;\n\t\t\tfirst_item[content.name] = Global.default_item;\n\t\t\treturn false;\n\t\t} );\n\n\t\t//Error: Object doesn't support property or method 'unshift' in /interface/html5/line 6953\n\t\tif ( !source_data || $.type( source_data ) !== 'array' ) {\n\t\t\tsource_data = [];\n\t\t}\n\n\t\tsource_data.unshift( first_item );\n\n\t\treturn source_data;\n\t}\n\n\tonEmployeeSourceCreate( target, source_data ) {\n\n\t\tif ( !this.checkOpenPermission() ) {\n\t\t\treturn source_data;\n\t\t}\n\n\t\tvar display_columns = target.getDisplayColumns();\n\n\t\tvar first_item = {};\n\t\t$.each( display_columns, function( index, content ) {\n\n\t\t\tfirst_item.id = TTUUID.zero_id;\n\t\t\tfirst_item[content.name] = Global.open_item;\n\n\t\t\treturn false;\n\t\t} );\n\n\t\t//Error: Object doesn't support property or method 'unshift' in /interface/html5/line 6953\n\t\tif ( !source_data || $.type( source_data ) !== 'array' ) {\n\t\t\tsource_data = [];\n\t\t}\n\t\tsource_data.unshift( first_item );\n\n\t\treturn source_data;\n\t}\n\n\taddOPenField( target, source_data ) {\n\t\tvar open_field = {};\n\t}\n\n\tcleanWhenUnloadView( callBack ) {\n\t\tthis.event_bus.autoClear(); // TODO: Once Schedule proof of concept works, move this to the BaseView function to apply to all views.\n\t\tTTVueUtils/* default.unmountComponent */.Z.unmountComponent( this.vue_control_bar_mount_id );\n\t\t$( '#schedule_view_container' ).remove();\n\t\tsuper.cleanWhenUnloadView( callBack );\n\t}\n\n\tsetAddRequestIcon( context_btn, grid_selected_length ) {\n\t\tif ( Global.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\nScheduleViewController.html_template = `\n<div class=\"view schedule-view\" id=\"schedule_view_container\">\n\t<div class=\"clear-both-div\"></div>\n\t<div id=\"vue-schedule-control-bar\"></div>\n\t<div class=\"clear-both-div\"></div>\n\t<div class=\"grid-top-border schedule-top-border\"></div>\n\t<div class=\"grid-div schedule-grid-div\">\n\t\t<table id=\"grid\"></table>\n\t</div>\n\t<div class=\"grid-bottom-border\"></div>\n</div>`;\n\nvar ScheduleViewControllerRowType = function() {\n\n};\n\nScheduleViewControllerRowType.TOTAL = 1;\nScheduleViewControllerRowType.DATE = 2;\nScheduleViewControllerRowType.EMPTY = 3;\n\nvar ScheduleViewControllerMode = function() {\n\n};\n\nScheduleViewControllerMode.DAY = 'day';\nScheduleViewControllerMode.WEEK = 'week';\nScheduleViewControllerMode.MONTH = 'month';\nScheduleViewControllerMode.YEAR = 'year';\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNjQ3OC5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O3FCQUNTLEtBQUssRUFBQyx1QkFBdUI7aUVBQzlCLDhDQUFtQyxTQUE5QixLQUFLLEVBQUMsaUJBQWlCO2lFQUM1Qiw4Q0FHTSxTQUhELEtBQUssRUFBQyxtQkFBbUI7ZUFDMUIsOENBQ00sU0FERCxLQUFLLEVBQUMsa0JBQWtCOztxQkFHNUIsS0FBSyxFQUFDLGtCQUFrQjtxQkFDcEIsS0FBSyxFQUFDLDBCQUEwQjtxQkFHaEMsS0FBSyxFQUFDLHNCQUFzQjs7Ozs7O21EQVZ6QywrQ0FjTSxPQWROLFVBY007SUFiRixVQUFtQztJQUNuQyxVQUdNO0lBQ04sOENBT00sT0FQTixVQU9NO01BTkYsOENBRU0sT0FGTixVQUVNO1FBREYsd0NBQXVLO3NCQUFoSixvQ0FBOEI7dUVBQTlCLG9DQUE4QjtVQUFHLE9BQU8sRUFBRSw0QkFBcUI7VUFBRSxXQUFXLEVBQUMsT0FBTztVQUFDLFdBQVcsRUFBQyxPQUFPO1VBQUUsT0FBSyw0Q0FBTyxvQkFBb0I7OztNQUVySyw4Q0FFTSxPQUZOLFVBRU07UUFERix3Q0FBMkU7VUFBekQsS0FBSyw2Q0FBRSxXQUFXO1VBQUcsS0FBSyxFQUFFLGdDQUF5Qjs7Ozs7Ozs7Ozs7Ozs7QUFPdEM7QUFDdUI7O0FBRXhFLGdGQUFlO0lBQ1gsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMxQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtRQUNOLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUM3QixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbEMsRUFBRSxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3ZHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUN2RyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3ZJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3ZILENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDckksQ0FBQztJQUNELENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtRQUNSLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQzlJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM5QixDQUFDO0lBQ0QsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM1RCxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7WUFDTCxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDWixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDaEIsQ0FBQztRQUNELENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUMzRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDWixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDaEIsQ0FBQztRQUNELENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7WUFDbkIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNYLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ2QsQ0FBQztRQUNELENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUN2QixDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ1gsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDZCxDQUFDO0lBQ0wsQ0FBQztJQUNELENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO1FBQ0gsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7WUFDSCxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUN6QixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzFDO0lBQ0osQ0FBQztJQUNELENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtJQUNWLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUU7SUFDeEQsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7SUFDM0UsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDeEIsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNiLENBQUMsTUFBTSxDQUFDO0lBQ1IsQ0FBQyxFQUFFLENBQUM7SUFDSixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtJQUNWLENBQUM7SUFDRCxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7UUFDTCxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO1FBQzFCLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNqQixDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtRQUM3RixDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO1FBQ3RFLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNsQyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtRQUMzQyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2IsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUN4QyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO1FBQ25KLENBQUM7UUFDRCxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFO1FBQ2QsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwQixDQUFDLE1BQU07UUFDUCxDQUFDLEVBQUUsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUNuQixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDOUQsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDVixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO2dCQUN0RixDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzdDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRTtnQkFDSCxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ1QsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUM7O1lBRTFIO1FBQ0osQ0FBQztRQUNELENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO1lBQ2hDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNuRixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7Z0JBQ1AsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3RCLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRTtnQkFDSCxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQztnQkFDbEosQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDcEI7UUFDSixDQUFDO1FBQ0QsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7WUFDbkMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUM5RixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7Z0JBQ1AsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN6RCxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUU7Z0JBQ0gsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ2pLO1FBQ0osQ0FBQztRQUNELENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7WUFDM0IsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUM5RixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7Z0JBQ1AsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDNUIsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFO2dCQUNILENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ3pKO1FBQ0osQ0FBQztRQUNELENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO1lBQ2hDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDOUYsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO2dCQUNQLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNqQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUU7Z0JBQ0gsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDL0o7UUFDSixDQUFDO1FBQ0QsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUNuQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO2dCQUM1RCxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDckMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM3QyxDQUFDLENBQUM7UUFDTixDQUFDO0lBQ0wsQ0FBQztJQUNELENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtRQUNSLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsK0JBQVk7UUFDMUIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSw4QkFBZTtJQUNwQztBQUNKLENBQUMsRUFBQzs7O0FFOUl5SixDOzs7O0FDQWhFO0FBQ3RCO0FBQ0w7O0FBRWhFLENBQXlGOztBQUVZO0FBQ3JHLGlDQUFpQywrQkFBZSxDQUFDLHlDQUFNLGFBQWEsTUFBTTs7QUFFMUUseURBQWU7Ozs7QUNUZ0M7QUFDMkI7O0FBRW5FO0FBQ1AsMkJBQTJCO0FBQzNCLEVBQUUsQ0FBQztBQUNIOzs7O0FBSUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUEsdUJBQXVCOztBQUV2Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGFBQWE7QUFDYjtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkIsQ0FBQztBQUM1QiwwQkFBMEIsQ0FBQztBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0Msc0JBQXNCOzs7QUFHMUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsdUhBQXVIO0FBQ3ZIO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxJQUFJO0FBQ0o7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQSx1QkFBdUIsZUFBZTtBQUN0QztBQUNBLHdCQUF3QixhQUFhO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsTUFBTTs7QUFFTjtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtB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QUs7QUFDTDtBQUNBLFlBQVksQ0FBQztBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLFlBQVksQ0FBQztBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLFlBQVksQ0FBQztBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsVUFBVSxDQUFDO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQSxVQUFVLENBQUM7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLFdBQVcsQ0FBQztBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsQ0FBQztBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFlBQVksQ0FBQztBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsWUFBWSxDQUFDO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxZQUFZLENBQUM7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxZQUFZLENBQUM7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLENBQUM7QUFDZDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLENBQUM7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLFlBQVksQ0FBQztBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsWUFBWSxDQUFDO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLFlBQVksQ0FBQztBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw0RUFBNEUsZUFBZTtBQUMzRjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsb0JBQW9CO0FBQ3BCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG1CQUFtQix3QkFBd0I7QUFDM0MsOENBQThDO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWE7QUFDYixJQUFJO0FBQ0osYUFBYTtBQUNiOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIsU0FBUztBQUM1QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQixTQUFTO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQjtBQUNuQjs7QUFFQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSxvQ0FBb0MsQ0FBQztBQUNyQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCO0FBQ2xCO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFLENBQUM7O0FBRUgsa0JBQWtCLENBQUM7QUFDbkI7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUEsSUFBSTs7QUFFSixFQUFFLENBQUM7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsSUFBSTs7QUFFSixFQUFFLENBQUM7QUFDSDtBQUNBLEdBQUcsQ0FBQzs7QUFFSixRQUFRLENBQUMsZ0NBQWdDLENBQUM7QUFDMUMsSUFBSSxDQUFDO0FBQ0w7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxxREFBcUQsQ0FBQztBQUN0RDtBQUNBOztBQUVBLG1CQUFtQixDQUFDOztBQUVwQjs7QUFFQSxvQkFBb0IsU0FBUztBQUM3QjtBQUNBLGVBQWUsQ0FBQzs7QUFFaEI7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsR0FBRyxDQUFDOztBQUVKLEdBQUcsQ0FBQzs7QUFFSixrRUFBa0U7O0FBRWxFO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCO0FBQzdCOztBQUVBLEdBQUcsQ0FBQzs7QUFFSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsb0JBQW9CLFNBQVM7QUFDN0I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsbUNBQW1DO0FBQ25DO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCxnQ0FBZ0M7QUFDaEM7O0FBRUEsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFVBQVU7QUFDVjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOOztBQUVBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQSwyQkFBMkI7O0FBRTNCLElBQUk7QUFDSjs7QUFFQSxHQUFHLENBQUM7QUFDSixHQUFHLENBQUM7O0FBRUosSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHdEQUF3RCxPQUFPO0FBQy9EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHVDQUF1QyxPQUFPO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxNQUFNO0FBQ047QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLG9DQUFvQztBQUNwQztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLE1BQU07QUFDTjs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHVCQUF1Qjs7QUFFdkI7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHLENBQUM7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJLENBQUM7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTixJQUFJLENBQUM7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0EsS0FBSztBQUNMO0FBQ0EsSUFBSSxDQUFDO0FBQ0w7QUFDQTtB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O0FBRUE7O0FBRUEsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEdBQUcsQ0FBQztBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLDJCQUEyQjtBQUMzQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0EscUJBQXFCLFNBQVMsQ0FBQyx1QkFBdUI7QUFDdEQ7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUEsNkJBQTZCLENBQUM7O0FBRTlCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUEsNkJBQTZCLENBQUM7O0FBRTlCO0FBQ0E7O0FBRUEsK0JBQStCLHFCQUFxQjtBQUNwRDtBQUNBLDZCQUE2QixDQUFDOztBQUU5QjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUEsNkJBQTZCLENBQUM7O0FBRTlCO0FBQ0E7QUFDQSwyQkFBMkIsNkJBQTZCOztBQUV4RCxvQkFBb0IsQ0FBQztBQUNyQixnQ0FBZ0MsQ0FBQzs7QUFFakM7QUFDQTs7QUFFQSw2QkFBNkIsQ0FBQzs7QUFFOUI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsaUNBQWlDLDREQUE0RDs7QUFFN0YsNkJBQTZCLENBQUM7O0FBRTlCO0FBQ0E7O0FBRUEsa0NBQWtDLDZCQUE2Qjs7QUFFL0QsNkJBQTZCLENBQUM7O0FBRTlCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSiw2QkFBNkIsQ0FBQzs7QUFFOUI7QUFDQTtBQUNBLGlDQUFpQyxzQkFBc0I7O0FBRXZELDZCQUE2QixDQUFDOztBQUU5QjtBQUNBO0FBQ0EsaUNBQWlDLG9CQUFvQjs7QUFFckQsNkJBQTZCLENBQUM7O0FBRTlCO0FBQ0E7QUFDQSwyQkFBMkIsc0JBQXNCO0FBQ2pEO0FBQ0EsNkJBQTZCLENBQUM7O0FBRTlCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0osNkJBQTZCLENBQUM7O0FBRTlCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxNQUFNLHdEQUF3RDtBQUM5RCxNQUFNO0FBQ047QUFDQSxJQUFJO0FBQ0osNkJBQTZCLENBQUM7O0FBRTlCO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxNQUFNLHdEQUF3RDtBQUM5RCxNQUFNO0FBQ047QUFDQSxJQUFJO0FBQ0osNkJBQTZCLENBQUM7O0FBRTlCO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQSxPQUFPLHdEQUF3RDtBQUMvRCxPQUFPO0FBQ1A7QUFDQSxLQUFLOztBQUVMLHFCQUFxQixDQUFDOztBQUV0QjtBQUNBLDJCQUEyQix1REFBdUQ7QUFDbEY7O0FBRUE7QUFDQTtBQUNBLDhCQUE4QixDQUFDOztBQUUvQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0EsT0FBTyx3REFBd0Q7QUFDL0QsT0FBTztBQUNQO0FBQ0EsS0FBSzs7QUFFTCxxQkFBcUIsQ0FBQzs7QUFFdEI7QUFDQSxnQ0FBZ0MsNERBQTREO0FBQzVGOztBQUVBO0FBQ0E7QUFDQSw4QkFBOEIsQ0FBQzs7QUFFL0I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQSxPQUFPO0FBQ1A7QUFDQSxLQUFLOztBQUVMLHFCQUFxQixDQUFDOztBQUV0QjtBQUNBLGlDQUFpQyw2REFBNkQ7QUFDOUY7O0FBRUE7QUFDQTtBQUNBLDhCQUE4QixDQUFDOzs7QUFHL0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLCtCQUErQiwrQkFBK0I7QUFDOUQsNkJBQTZCLENBQUM7QUFDOUI7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDLHVDQUF1QztBQUN2RSw4QkFBOEIsQ0FBQztBQUMvQjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG1CQUFtQixTQUFTO0FBQzVCOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQSxtQkFBbUIsU0FBUztBQUM1Qjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsZ0RBQWdELENBQUM7QUFDakQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQSxrQkFBa0IsQ0FBQyxFQUFFLENBQUM7QUFDdEI7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSix3QkFBd0IsQ0FBQztBQUN6Qjs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBLEtBQUssc0NBQXNDLENBQUM7QUFDNUM7O0FBRUE7O0FBRUEsY0FBYyxDQUFDLEVBQUUsQ0FBQztBQUNsQjtBQUNBOztBQUVBLHdCQUF3QixDQUFDOztBQUV6QjtBQUNBOztBQUVBLGlCQUFpQixDQUFDO0FBQ2xCO0FBQ0EscUNBQXFDLENBQUM7QUFDdEM7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKOztBQUVBLG1DQUFtQyxDQUFDOztBQUVwQzs7QUFFQSxvQkFBb0IsQ0FBQyx5Q0FBeUMsQ0FBQztBQUMvRDs7QUFFQSx3Q0FBd0MsQ0FBQztBQUN6QyxtQkFBbUIsQ0FBQztBQUNwQjtBQUNBLHFDQUFxQyxDQUFDO0FBQ3RDOztBQUVBLGdCQUFnQixDQUFDO0FBQ2pCO0FBQ0EscUNBQXFDLENBQUM7QUFDdEM7O0FBRUE7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1R0FBdUcsZUFBZTtBQUN0SDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRCQUE0QjtBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRCQUE0QjtBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUEsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBGQUEwRjtBQUMxRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLG1CQUFtQixzQkFBc0I7QUFDekM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxpQkFBaUIsQ0FBQztBQUNsQixvQkFBb0IsQ0FBQzs7QUFFckI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7QUFDSjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBOztBQUVBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQixDQUFDO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsR0FBRyxDQUFDO0FBQ0o7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSwyQkFBMkIsQ0FBQzs7QUFFNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBOztBQUVBOztBQUVBLCtCQUErQjtBQUMvQiwwQkFBMEI7QUFDMUIsK0JBQStCLGVBQWU7QUFDOUM7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtB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QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBLG9CQUFvQixTQUFTO0FBQzdCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsc0JBQXNCLHlCQUF5QjtBQUMvQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7O0FBRUEsTUFBTTtBQUNOOztBQUVBO0FBQ0Esc0JBQXNCLHFCQUFxQjtBQUMzQztBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7O0FBRVI7QUFDQTs7QUFFQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsdUJBQXVCLHlCQUF5QjtBQUNoRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztB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QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsTUFBTTtBQUNOLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSzs7QUFFTDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUUsQ0FBQzs7QUFFSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxtQkFBbUIsU0FBUztBQUM1QjtBQUNBLGdCQUFnQixDQUFDO0FBQ2pCLGlCQUFpQixDQUFDO0FBQ2xCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixTQUFTO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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OztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsVUFBVSxDQUFDO0FBQ1g7QUFDQTtBQUNBLFVBQVUsQ0FBQztBQUNYO0FBQ0E7QUFDQSxVQUFVLENBQUM7QUFDWDtBQUNBO0FBQ0EsVUFBVSxDQUFDO0FBQ1g7QUFDQTtBQUNBLFVBQVUsQ0FBQztBQUNYO0FBQ0E7QUFDQSxVQUFVLENBQUM7QUFDWDtBQUNBO0FBQ0EsVUFBVSxDQUFDO0FBQ1g7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxDQUFDO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsQ0FBQztBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLENBQUM7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxDQUFDO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBLG1CQUFtQix5QkFBeUI7QUFDNUM7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztB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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07O0FBRU47QUFDQSxZQUFZLENBQUM7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNOztBQUVOO0FBQ0EsWUFBWSxDQUFDO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTs7QUFFTjtBQUNBLFlBQVksQ0FBQztBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07O0FBRU47QUFDQSxZQUFZLENBQUM7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTs7QUFFTjtBQUNBLFlBQVksQ0FBQztBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNOztBQUVOO0FBQ0EsWUFBWSxDQUFDO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07O0FBRU47QUFDQSxZQUFZLENBQUM7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTs7QUFFTjtBQUNBLFlBQVksQ0FBQztBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNOztBQUVOO0FBQ0EsWUFBWSxDQUFDO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07O0FBRU47QUFDQSxZQUFZLENBQUM7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLE1BQU07O0FBRU47QUFDQSxZQUFZLENBQUM7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLE1BQU07QUFDTjtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxZQUFZLENBQUM7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07O0FBRU47QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLENBQUM7QUFDZDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYSxDQUFDO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxFQUFFLENBQUM7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQSx1QkFBdUIsQ0FBQztBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsRUFBRSxDQUFDO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBLHVCQUF1QixDQUFDO0FBQ3hCO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxFQUFFLENBQUM7O0FBRUg7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQSx1QkFBdUIsQ0FBQztBQUN4QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw4QkFBOEI7QUFDOUIsRUFBRSwyREFBMkI7QUFDN0IsRUFBRSxDQUFDO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vaW50ZXJmYWNlL2h0bWw1L2NvbXBvbmVudHMvc2NoZWR1bGUvU2NoZWR1bGVDb250cm9sQmFyLnZ1ZT8zYzYyIiwid2VicGFjazovLy8uL2ludGVyZmFjZS9odG1sNS9jb21wb25lbnRzL3NjaGVkdWxlL1NjaGVkdWxlQ29udHJvbEJhci52dWU/ZDY0YiIsIndlYnBhY2s6Ly8vLi9pbnRlcmZhY2UvaHRtbDUvY29tcG9uZW50cy9zY2hlZHVsZS9TY2hlZHVsZUNvbnRyb2xCYXIudnVlP2Y1MjAiLCJ3ZWJwYWNrOi8vLy4vaW50ZXJmYWNlL2h0bWw1L2NvbXBvbmVudHMvc2NoZWR1bGUvU2NoZWR1bGVDb250cm9sQmFyLnZ1ZT8yMDZkIiwid2VicGFjazovLy8uL2ludGVyZmFjZS9odG1sNS92aWV3cy9hdHRlbmRhbmNlL3NjaGVkdWxlL1NjaGVkdWxlVmlld0NvbnRyb2xsZXIuanM/YmQ2YyJdLCJzb3VyY2VzQ29udGVudCI6WyI8dGVtcGxhdGU+XG4gICAgPGRpdiBjbGFzcz1cInR0LWhvcml6b250YWwtdnVlLWJhclwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiYmFyLWNvbHVtbiBsZWZ0XCI+PC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJiYXItY29sdW1uIGNlbnRlclwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRhdGUtY2hvb3Nlci1kaXZcIj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImJhci1jb2x1bW4gcmlnaHRcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJiYXItY29sdW1uIHNjaGVkdWxlLW1vZGVcIj5cbiAgICAgICAgICAgICAgICA8U2VsZWN0QnV0dG9uIHYtbW9kZWw9XCJzY2hlZHVsZV9tb2RlX29wdGlvbnNfc2VsZWN0ZWRcIiA6b3B0aW9ucz1cInNjaGVkdWxlX21vZGVfb3B0aW9uc1wiIG9wdGlvbkxhYmVsPVwibGFiZWxcIiBvcHRpb25WYWx1ZT1cInZhbHVlXCIgQGNsaWNrPVwidGhpcy5vblNjaGVkdWxlTW9kZUNoYW5nZSgpO1wiLz5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImJhci1jb2x1bW4gbWVudS1pdGVtXCI+XG4gICAgICAgICAgICAgICAgPFRUQ29udGV4dEJ1dHRvbiA6Y2xhc3M9XCJbJ25vLXdyYXAnXVwiIDppdGVtcz1cInNjaGVkdWxlX3NldHRpbmdzX29wdGlvbnNcIiAvPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuPC90ZW1wbGF0ZT5cblxuPHNjcmlwdD5cbmltcG9ydCBTZWxlY3RCdXR0b24gZnJvbSAncHJpbWV2dWUvc2VsZWN0YnV0dG9uJztcbmltcG9ydCBUVENvbnRleHRCdXR0b24gZnJvbSAnQC9jb21wb25lbnRzL2NvbnRleHRfbWVudS9UVENvbnRleHRCdXR0b24nO1xuXG5leHBvcnQgZGVmYXVsdCB7XG4gICAgbmFtZTogXCJTY2hlZHVsZUNvbnRyb2xCYXJcIixcbiAgICBjcmVhdGVkKCkge1xuICAgICAgICB0aGlzLmV2ZW50X2J1cyA9IG5ldyBUVEV2ZW50QnVzKCB7XG4gICAgICAgICAgICBjb21wb25lbnRfaWQ6IHRoaXMuY29tcG9uZW50X2lkXG4gICAgICAgIH0gKTtcbiAgICAgICAgdGhpcy5ldmVudF9idXMub24oIHRoaXMuY29tcG9uZW50X2lkLCAnZ2V0VmFsdWUnLCB0aGlzLmdldFZhbHVlLCBUVEV2ZW50QnVzU3RhdGljcy5BVVRPX0NMRUFSX09OX0VYSVQgKTtcbiAgICAgICAgdGhpcy5ldmVudF9idXMub24oIHRoaXMuY29tcG9uZW50X2lkLCAnc2V0VmFsdWUnLCB0aGlzLnNldFZhbHVlLCBUVEV2ZW50QnVzU3RhdGljcy5BVVRPX0NMRUFSX09OX0VYSVQgKTtcbiAgICAgICAgdGhpcy5ldmVudF9idXMub24oIHRoaXMuY29tcG9uZW50X2lkLCAnc2V0U2NoZWR1bGVTZXR0aW5nc1N0YXRlJywgdGhpcy5zZXRTY2hlZHVsZVNldHRpbmdzU3RhdGUsIFRURXZlbnRCdXNTdGF0aWNzLkFVVE9fQ0xFQVJfT05fRVhJVCApO1xuICAgICAgICB0aGlzLmV2ZW50X2J1cy5vbiggdGhpcy5jb21wb25lbnRfaWQsICdzZXRTZXR0aW5nQWN0aXZlJywgdGhpcy5zZXRTZXR0aW5nQWN0aXZlLCBUVEV2ZW50QnVzU3RhdGljcy5BVVRPX0NMRUFSX09OX0VYSVQgKTtcbiAgICAgICAgdGhpcy5ldmVudF9idXMub24oIHRoaXMuY29tcG9uZW50X2lkLCAnc2V0U2V0dGluZ0RlYWN0aXZhdGVkJywgdGhpcy5zZXRTZXR0aW5nRGVhY3RpdmF0ZWQsIFRURXZlbnRCdXNTdGF0aWNzLkFVVE9fQ0xFQVJfT05fRVhJVCApO1xuICAgIH0sXG4gICAgdW5tb3VudGVkKCkge1xuICAgICAgICBEZWJ1Zy5UZXh0KCAnVnVlIGNvbnRyb2wgYmFyIGNvbXBvbmVudCB1bm1vdW50ZWQgKCcrIHRoaXMuY29tcG9uZW50X2lkICsnKS4nLCAnU2NoZWR1bGVDb250cm9sQmFyLnZ1ZScsICdTY2hlZHVsZUNvbnRyb2xCYXInLCAndW5tb3VudGVkJywgMiApO1xuICAgICAgICB0aGlzLmV2ZW50X2J1cy5hdXRvQ2xlYXIoKTtcbiAgICB9LFxuICAgIHByb3BzOiB7IC8vIHBhc3NlZCBpbiB2aWEgcm9vdCBwcm9wcyBmcm9tIFRpbWVTaGVldFZpZXdDb250cm9sbGVyXG4gICAgICAgIHZpZXdfaWQ6IHtcbiAgICAgICAgICAgIHR5cGU6IFN0cmluZyxcbiAgICAgICAgICAgIGRlZmF1bHQ6IG51bGxcbiAgICAgICAgfSxcbiAgICAgICAgY29tcG9uZW50X2lkOiB7IC8qIE5vdGU6IFRoaXMgaXMgcGFzc2VkIGluIHZpYSBUVFZ1ZVV0aWxzLm1vdW50Q29tcG9uZW50IHBhcmFtLCBhbmQgYXV0byBhZGRlZCB0byByb290X3Byb3BzLiAqL1xuICAgICAgICAgICAgdHlwZTogU3RyaW5nLFxuICAgICAgICAgICAgZGVmYXVsdDogbnVsbFxuICAgICAgICB9LFxuICAgICAgICBzY2hlZHVsZV9tb2RlX29wdGlvbnM6IHtcbiAgICAgICAgICAgIHR5cGU6IEFycmF5LFxuICAgICAgICAgICAgZGVmYXVsdDogW11cbiAgICAgICAgfSxcbiAgICAgICAgc2NoZWR1bGVfc2V0dGluZ3Nfb3B0aW9uczoge1xuICAgICAgICAgICAgdHlwZTogQXJyYXksXG4gICAgICAgICAgICBkZWZhdWx0OiBbXVxuICAgICAgICB9LFxuICAgIH0sXG4gICAgZGF0YSgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHJlbW92ZUV2ZW50c09uVW5tb3VudDogW10sXG4gICAgICAgICAgICBzY2hlZHVsZV9tb2RlX29wdGlvbnNfc2VsZWN0ZWQ6ICd3ZWVrJyxcbiAgICAgICAgfVxuICAgIH0sXG4gICAgLy8gd2F0Y2g6IHtcbiAgICAvLyAgICAgc2NoZWR1bGVfbW9kZV9vcHRpb25zX3NlbGVjdGVkOiBmdW5jdGlvbiAoIHZhbCApIHtcbiAgICAvLyAgICAgICAgIHRoaXMuZXZlbnRfYnVzLmVtaXQoIHRoaXMuY29tcG9uZW50X2lkLCAnc2NoZWR1bGVNb2RlT25DaGFuZ2UnLCB7XG4gICAgLy8gICAgICAgICAgICAga2V5OiAnc2NoZWR1bGVfbW9kZV9vcHRpb25zX3NlbGVjdGVkJyxcbiAgICAvLyAgICAgICAgICAgICB2YWx1ZTogdmFsXG4gICAgLy8gICAgICAgICB9KTtcbiAgICAvLyAgICAgfSxcbiAgICAvLyB9LFxuICAgIGNvbXB1dGVkOiB7XG4gICAgfSxcbiAgICBtZXRob2RzOiB7XG4gICAgICAgIC8vIGdldFZhbHVlKCBldmVudF9kYXRhICkge1xuICAgICAgICAvLyAgICAgLy8gVmFsaWRhdGVcbiAgICAgICAgLy8gICAgIGlmICggZXZlbnRfZGF0YS5rZXkgJiYgWydzY2hlZHVsZV9tb2RlX29wdGlvbnNfc2VsZWN0ZWQnXS5pbmNsdWRlcyggZXZlbnRfZGF0YS5rZXkpICkge1xuICAgICAgICAvLyAgICAgICAgIEV2ZW50QnVzLmVtaXQoIHRoaXMudnVlX2NvbnRyb2xfYmFyX2lkICsnLmdldFZhbHVlUmV0dXJuJywge1xuICAgICAgICAvLyAgICAgICAgICAgICBrZXk6IGV2ZW50X2RhdGEua2V5LFxuICAgICAgICAvLyAgICAgICAgICAgICB2YWx1ZTogdGhpc1sgZXZlbnRfZGF0YS5rZXkgXVxuICAgICAgICAvLyAgICAgICAgIH0pO1xuICAgICAgICAvLyAgICAgICAgIHJldHVybiB0aGlzWyBldmVudF9kYXRhLmtleSBdO1xuICAgICAgICAvLyAgICAgfSBlbHNlIGlmICggZXZlbnRfZGF0YS5rZXkgJiYgWydhbGxfZW1wbG95ZWVfYnRuJywgJ2RhaWx5X3RvdGFsc19idG4nLCAnd2Vla2x5X3RvdGFsc19idG4nLCAnc3RyaWN0X3JhbmdlX2J0biddLmluY2x1ZGVzKCBldmVudF9kYXRhLmtleSkgKSB7XG4gICAgICAgIC8vXG4gICAgICAgIC8vICAgICB9IGVsc2Uge1xuICAgICAgICAvLyAgICAgICAgIC8vIGludmFsaWRcbiAgICAgICAgLy8gICAgIH1cbiAgICAgICAgLy8gfSxcbiAgICAgICAgc2V0VmFsdWUoIGV2ZW50X2RhdGEgKSB7XG4gICAgICAgICAgICB2YXIgdmFsaWRfZWRpdGFibGVfZmllbGRzID0gWydzY2hlZHVsZV9tb2RlX29wdGlvbnNfc2VsZWN0ZWQnXTtcbiAgICAgICAgICAgIC8vIFZhbGlkYXRlXG4gICAgICAgICAgICBpZiggZXZlbnRfZGF0YS5rZXkgJiYgZXZlbnRfZGF0YS5rZXkgJiYgdmFsaWRfZWRpdGFibGVfZmllbGRzLmluY2x1ZGVzKCBldmVudF9kYXRhLmtleSkgKSB7XG4gICAgICAgICAgICAgICAgdGhpc1sgZXZlbnRfZGF0YS5rZXkgXSA9IGV2ZW50X2RhdGEudmFsdWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIGludmFsaWRcbiAgICAgICAgICAgICAgICBEZWJ1Zy5FcnJvciggJ0ludmFsaWQgcGFyYW1ldGVycyBwYXNzZWQgdG8gZnVuY3Rpb24uJywgJ1NjaGVkdWxlQ29udHJvbEJhci52dWUnLCAnU2NoZWR1bGVDb250cm9sQmFyJywgJ3NldFZhbHVlJywgMSApO1xuXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGdldFNjaGVkdWxlU2V0dGluZ3NTdGF0ZSggaXRlbV9pZCApIHtcbiAgICAgICAgICAgIHZhciBpdGVtID0gdGhpcy5zY2hlZHVsZV9zZXR0aW5nc19vcHRpb25zLmZpbmQoIGVsZW1lbnQgPT4gZWxlbWVudC5pZCA9PT0gaXRlbV9pZCApO1xuICAgICAgICAgICAgaWYoIGl0ZW0gKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGl0ZW0uYWN0aXZlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBEZWJ1Zy5FcnJvciggJ0l0ZW0gbm90IGZvdW5kICgnKyBpdGVtX2lkICsnKS4gQ2hlY2sgc3VwcGxpZWQgaWQuJywgJ1NjaGVkdWxlQ29udHJvbEJhci52dWUnLCAnU2NoZWR1bGVDb250cm9sQmFyJywgJ2dldFNjaGVkdWxlU2V0dGluZ3NTdGF0ZScsIDEgKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBzZXRTY2hlZHVsZVNldHRpbmdzU3RhdGUoIGV2ZW50X2RhdGEgKSB7XG4gICAgICAgICAgICB2YXIgaXRlbSA9IHRoaXMuc2NoZWR1bGVfc2V0dGluZ3Nfb3B0aW9ucy5maW5kKCBlbGVtZW50ID0+IGVsZW1lbnQuaWQgPT09IGV2ZW50X2RhdGEuaXRlbV9pZCApO1xuICAgICAgICAgICAgaWYoIGl0ZW0gKSB7XG4gICAgICAgICAgICAgICAgaXRlbVsgZXZlbnRfZGF0YS5pdGVtX2ZpZWxkIF0gPSBldmVudF9kYXRhLml0ZW1fdmFsdWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIERlYnVnLkVycm9yKCAnSXRlbSBub3QgZm91bmQgKCcrIGV2ZW50X2RhdGEuaXRlbV9pZCArJykuIENoZWNrIHN1cHBsaWVkIGlkLicsICdTY2hlZHVsZUNvbnRyb2xCYXIudnVlJywgJ1NjaGVkdWxlQ29udHJvbEJhcicsICdzZXRTY2hlZHVsZVNldHRpbmdzU3RhdGUnLCAxICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHNldFNldHRpbmdBY3RpdmUoIGV2ZW50X2RhdGEgKSB7XG4gICAgICAgICAgICB2YXIgaXRlbSA9IHRoaXMuc2NoZWR1bGVfc2V0dGluZ3Nfb3B0aW9ucy5maW5kKCBlbGVtZW50ID0+IGVsZW1lbnQuaWQgPT09IGV2ZW50X2RhdGEuaXRlbV9pZCApO1xuICAgICAgICAgICAgaWYoIGl0ZW0gKSB7XG4gICAgICAgICAgICAgICAgaXRlbS5zZXRPbmx5U2VsZkFjdGl2ZSgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBEZWJ1Zy5FcnJvciggJ0l0ZW0gbm90IGZvdW5kICgnKyBldmVudF9kYXRhLml0ZW1faWQgKycpLiBDaGVjayBzdXBwbGllZCBpZC4nLCAnU2NoZWR1bGVDb250cm9sQmFyLnZ1ZScsICdTY2hlZHVsZUNvbnRyb2xCYXInLCAnc2V0U2V0dGluZ0FjdGl2ZScsIDEgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgc2V0U2V0dGluZ0RlYWN0aXZhdGVkKCBldmVudF9kYXRhICkge1xuICAgICAgICAgICAgdmFyIGl0ZW0gPSB0aGlzLnNjaGVkdWxlX3NldHRpbmdzX29wdGlvbnMuZmluZCggZWxlbWVudCA9PiBlbGVtZW50LmlkID09PSBldmVudF9kYXRhLml0ZW1faWQgKTtcbiAgICAgICAgICAgIGlmKCBpdGVtICkge1xuICAgICAgICAgICAgICAgIGl0ZW0uc2V0T25seVNlbGZEZWFjdGl2YXRlZCgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBEZWJ1Zy5FcnJvciggJ0l0ZW0gbm90IGZvdW5kICgnKyBldmVudF9kYXRhLml0ZW1faWQgKycpLiBDaGVjayBzdXBwbGllZCBpZC4nLCAnU2NoZWR1bGVDb250cm9sQmFyLnZ1ZScsICdTY2hlZHVsZUNvbnRyb2xCYXInLCAnc2V0T25seVNlbGZEZWFjdGl2YXRlZCcsIDEgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgb25TY2hlZHVsZU1vZGVDaGFuZ2UoKSB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50X2J1cy5lbWl0KCB0aGlzLmNvbXBvbmVudF9pZCwgJ3NjaGVkdWxlTW9kZU9uQ2hhbmdlJywge1xuICAgICAgICAgICAgICAgIGtleTogJ3NjaGVkdWxlX21vZGVfb3B0aW9uc19zZWxlY3RlZCcsXG4gICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMuc2NoZWR1bGVfbW9kZV9vcHRpb25zX3NlbGVjdGVkXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICB9LFxuICAgIGNvbXBvbmVudHM6IHtcbiAgICAgICAgU2VsZWN0QnV0dG9uOiBTZWxlY3RCdXR0b24sXG4gICAgICAgIFRUQ29udGV4dEJ1dHRvbjogVFRDb250ZXh0QnV0dG9uXG4gICAgfVxufTtcbjwvc2NyaXB0PlxuXG48c3R5bGUgc2NvcGVkPlxuICAgIC50dC1ob3Jpem9udGFsLXZ1ZS1iYXIge1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBmbGV4LWRpcmVjdGlvbjogcm93O1xuICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XG4gICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICAgIG1hcmdpbi10b3A6IDNweDtcbiAgICB9XG4gICAgLmJhci1jb2x1bW4ge1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBmbGV4LWRpcmVjdGlvbjogcm93O1xuICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAgICBwYWRkaW5nOiAwIDVweDtcbiAgICB9XG4gICAgLmJhci1jb2x1bW4ubGVmdCxcbiAgICAuYmFyLWNvbHVtbi5yaWdodCB7XG4gICAgICAgIHdpZHRoOiAyNSU7XG4gICAgfVxuICAgIC5iYXItY29sdW1uLnJpZ2h0IHtcbiAgICAgICAganVzdGlmeS1jb250ZW50OiBmbGV4LWVuZDtcbiAgICB9XG4gICAgOjp2LWRlZXAoLnNjaGVkdWxlLW1vZGUgLnAtYnV0dG9uKSB7XG4gICAgICAgIHBhZGRpbmc6IC41NXJlbSAuNnJlbTtcbiAgICB9XG4gICAgOjp2LWRlZXAoLnAtYnV0dG9uLWxhYmVsKSB7XG4gICAgICAgIGZvbnQtc2l6ZTogMTRweDtcbiAgICB9XG48L3N0eWxlPiIsImV4cG9ydCAqIGZyb20gXCItIS4uLy4uLy4uLy4uL25vZGVfbW9kdWxlcy92dWUtbG9hZGVyL2Rpc3QvdGVtcGxhdGVMb2FkZXIuanM/P3J1bGVTZXRbMV0ucnVsZXNbMV0hLi4vLi4vLi4vLi4vbm9kZV9tb2R1bGVzL3Z1ZS1sb2FkZXIvZGlzdC9pbmRleC5qcz8/cnVsZVNldFsxXS5ydWxlc1s2XS51c2VbMF0hLi9TY2hlZHVsZUNvbnRyb2xCYXIudnVlP3Z1ZSZ0eXBlPXRlbXBsYXRlJmlkPTRmOTcwYjk2JnNjb3BlZD10cnVlXCIiLCJleHBvcnQgeyBkZWZhdWx0IH0gZnJvbSBcIi0hLi4vLi4vLi4vLi4vbm9kZV9tb2R1bGVzL3Z1ZS1sb2FkZXIvZGlzdC9pbmRleC5qcz8/cnVsZVNldFsxXS5ydWxlc1s2XS51c2VbMF0hLi9TY2hlZHVsZUNvbnRyb2xCYXIudnVlP3Z1ZSZ0eXBlPXNjcmlwdCZsYW5nPWpzXCI7IGV4cG9ydCAqIGZyb20gXCItIS4uLy4uLy4uLy4uL25vZGVfbW9kdWxlcy92dWUtbG9hZGVyL2Rpc3QvaW5kZXguanM/P3J1bGVTZXRbMV0ucnVsZXNbNl0udXNlWzBdIS4vU2NoZWR1bGVDb250cm9sQmFyLnZ1ZT92dWUmdHlwZT1zY3JpcHQmbGFuZz1qc1wiIiwiaW1wb3J0IHsgcmVuZGVyIH0gZnJvbSBcIi4vU2NoZWR1bGVDb250cm9sQmFyLnZ1ZT92dWUmdHlwZT10ZW1wbGF0ZSZpZD00Zjk3MGI5NiZzY29wZWQ9dHJ1ZVwiXG5pbXBvcnQgc2NyaXB0IGZyb20gXCIuL1NjaGVkdWxlQ29udHJvbEJhci52dWU/dnVlJnR5cGU9c2NyaXB0Jmxhbmc9anNcIlxuZXhwb3J0ICogZnJvbSBcIi4vU2NoZWR1bGVDb250cm9sQmFyLnZ1ZT92dWUmdHlwZT1zY3JpcHQmbGFuZz1qc1wiXG5cbmltcG9ydCBcIi4vU2NoZWR1bGVDb250cm9sQmFyLnZ1ZT92dWUmdHlwZT1zdHlsZSZpbmRleD0wJmlkPTRmOTcwYjk2JnNjb3BlZD10cnVlJmxhbmc9Y3NzXCJcblxuaW1wb3J0IGV4cG9ydENvbXBvbmVudCBmcm9tIFwiL2hvbWUvbWlrZWIvdGltZXRyZXgvdHJ1bmsvbm9kZV9tb2R1bGVzL3Z1ZS1sb2FkZXIvZGlzdC9leHBvcnRIZWxwZXIuanNcIlxuY29uc3QgX19leHBvcnRzX18gPSAvKiNfX1BVUkVfXyovZXhwb3J0Q29tcG9uZW50KHNjcmlwdCwgW1sncmVuZGVyJyxyZW5kZXJdLFsnX19zY29wZUlkJyxcImRhdGEtdi00Zjk3MGI5NlwiXV0pXG5cbmV4cG9ydCBkZWZhdWx0IF9fZXhwb3J0c19fIiwiaW1wb3J0IFRUVnVlVXRpbHMgZnJvbSAnQC9zZXJ2aWNlcy9UVFZ1ZVV0aWxzJztcbmltcG9ydCBTY2hlZHVsZUNvbnRyb2xCYXIgZnJvbSAnQC9jb21wb25lbnRzL3NjaGVkdWxlL1NjaGVkdWxlQ29udHJvbEJhcic7XG5cbmV4cG9ydCBjbGFzcyBTY2hlZHVsZVZpZXdDb250cm9sbGVyIGV4dGVuZHMgQmFzZVZpZXdDb250cm9sbGVyIHtcblx0Y29uc3RydWN0b3IoIG9wdGlvbnMgPSB7fSApIHtcblx0XHRfLmRlZmF1bHRzKCBvcHRpb25zLCB7XG5cdFx0XHRlbDogJyNzY2hlZHVsZV92aWV3X2NvbnRhaW5lcicsIC8vTXVzdCBzZXQgZWwgaGVyZSBhbmQgY2FuIG9ubHkgc2V0IHN0cmluZywgc28gZXZlbnRzIGNhbiB3b3JrXG5cblxuXG5cdFx0XHR1c2VyX2dyb3VwX2FwaTogbnVsbCxcblxuXHRcdFx0c3RhdHVzX2FycmF5OiBudWxsLFxuXG5cdFx0XHR1c2VyX2dyb3VwX2FycmF5OiBudWxsLFxuXG5cdFx0XHR0b2dnbGVfYnV0dG9uOiBudWxsLFxuXG5cdFx0XHRzdGFydF9kYXRlX3BpY2tlcjogbnVsbCxcblxuXHRcdFx0c3RhcnRfZGF0ZTogbnVsbCxcblxuXHRcdFx0ZW5kX2RhdGU6IG51bGwsXG5cblx0XHRcdGZ1bGxfc2NoZWR1bGVfZGF0YTogbnVsbCxcblxuXHRcdFx0c2NoZWR1bGVfY29sdW1uczogbnVsbCxcblxuXHRcdFx0ZnVsbF9mb3JtYXQ6ICdkZGQtTU1NLURELVlZWVknLFxuXG5cdFx0XHR3ZWVrbHlfZm9ybWF0OiAnZGRkLCBNTU0gREQnLFxuXG5cdFx0XHRmaW5hbF9zY2hlZHVsZV9kYXRhX2FycmF5OiBbXSxcblxuXHRcdFx0aGFzX2RhdGVfYXJyYXk6IFtdLFxuXG5cdFx0XHRub19kYXRlX2FycmF5OiBbXSxcblxuXHRcdFx0c2hpZnRfa2V5X25hbWVfYXJyYXk6IFtdLFxuXG5cdFx0XHRzZWxlY3RfY2VsbHNfQXJyYXk6IFtdLCAvL1RpbWVzaGVldCBncmlkXG5cblx0XHRcdHNlbGVjdF9hbGxfc2hpZnRzX2FycmF5OiBbXSwgLy9UaW1lc2hlZXQgZ3JpZC5cblxuXHRcdFx0c2VsZWN0X3NoaWZ0c19hcnJheTogW10sIC8vVGltZXNoZWV0IGdyaWQuXG5cblx0XHRcdHNlbGVjdF9yZWN1cnJpbmdfc2hpZnRzX2FycmF5OiBbXSwgLy9UaW1lc2hlZXQgZ3JpZC5cblxuXHRcdFx0YWxsX2VtcGxveWVlX2J0bjogbnVsbCxcblxuXHRcdFx0ZGFpbHlfdG90YWxzX2J0bjogbnVsbCxcblxuXHRcdFx0d2Vla2x5X3RvdGFsc19idG46IG51bGwsXG5cblx0XHRcdHN0cmljdF9yYW5nZV9idG46IG51bGwsXG5cblx0XHRcdG1vbnRoX2RhdGVfcm93X2FycmF5OiBudWxsLFxuXG5cdFx0XHRtb250aF9kYXRlX3Jvd190cl9pZHM6IG51bGwsIC8vIG1vbnRoIGRhdGUgdHIgaWQgaW4gZ3JpZCB0YWJsZVxuXG5cdFx0XHRtb250aF9kYXRlX3Jvd19wb3NpdGlvbjogbnVsbCwgLy9tb250aCBkYXRlIHRyIHBvc2l0aW9uIGluIHRhYmxlXG5cblx0XHRcdG1vbnRoX2N1cnJlbnRfaGVhZGVyX251bWJlcjogMCwgLy8wIGlzIGRlZmF1bHQgY29sdW1uIGhlYWRlclxuXG5cdFx0XHRkYXlfaGVhZGVyX3dpZHRoOiAwLFxuXG5cdFx0XHRkYXlfaG91cl93aWR0aDogNDAsXG5cblx0XHRcdHNlbGVjdF9kcmFnX21lbnVfaWQ6ICcnLCAvL0RvIGRyYWcgbW92ZSBvciBjb3B5XG5cblx0XHRcdGlzX292ZXJyaWRlOiBmYWxzZSxcblxuXHRcdFx0bm90aWZ5X3VzZXJfc2NoZWR1bGVfY2hhbmdlOiBmYWxzZSxcblxuXHRcdFx0c2Nyb2xsX3Bvc2l0aW9uOiAwLFxuXG5cdFx0XHRzZWxlY3RlZF91c2VyX2lkczogW10sXG5cblx0XHRcdHByZXZfdG90YWxfdGltZTogMCxcblxuXHRcdFx0cHJldl9zdGF0dXNfaWQ6IG51bGwsXG5cblx0XHRcdGlzX21hc3NfYWRkaW5nOiBmYWxzZSxcblxuXHRcdFx0Y2FsY3VsYXRlX2NlbGxfbnVtYmVyOiAwLFxuXG5cdFx0XHRzY3JvbGxfaW50ZXJ2YWw6IG51bGwsXG5cblx0XHRcdHNjcm9sbF91bml0OiAwLFxuXG5cdFx0XHRob2xpZGF5X2RhdGFfZGljOiB7fSxcblxuXHRcdFx0YWJzZW5jZV9wb2xpY3lfYXBpOiBudWxsLFxuXG5cdFx0XHRqb2JfYXBpOiBudWxsLFxuXHRcdFx0am9iX2l0ZW1fYXBpOiBudWxsLFxuXHRcdFx0dXNlcl9hcGk6IG51bGwsXG5cdFx0XHRkZXBhcnRtZW50X2FwaTogbnVsbCxcblx0XHRcdHB1bmNoX3RhZ19hcGk6IG51bGwsXG5cdFx0XHRkZWZhdWx0X3B1bmNoX3RhZzogW10sXG5cdFx0XHRwcmV2aW91c19wdW5jaF90YWdfc2VsZWN0aW9uOiBbXSxcblxuXHRcdFx0eWVhcl9tb2RlX29yaWdpbmFsX2RhdGU6IG51bGwsIC8vc2V0IHRoaXMgd2hlbiBzZWFyY2ggZm9yIHllciBtb2RlIHdpdGggdXNlX2RhdGVfcGlja2VyIHRydWUsIHNvIEtlZXAgc2VsZWN0IGRhdGUgaW4gcml0aWN0IG1vZGVcblx0XHRcdGV2ZW50czoge30sXG5cdFx0XHR2dWVfY29udHJvbF9iYXJfaWQ6ICcnXG5cdFx0fSApO1xuXG5cdFx0c3VwZXIoIG9wdGlvbnMgKTtcblx0fVxuXG5cdGluaXQoIG9wdGlvbnMgKSB7XG5cdFx0Ly90aGlzLl9zdXBlcignaW5pdGlhbGl6ZScsIG9wdGlvbnMgKTtcblx0XHR0aGlzLnBlcm1pc3Npb25faWQgPSAnc2NoZWR1bGUnO1xuXHRcdHRoaXMuc2NyaXB0X25hbWUgPSAnU2NoZWR1bGVWaWV3Jztcblx0XHR0aGlzLnZpZXdJZCA9ICdTY2hlZHVsZSc7XG5cdFx0dGhpcy50YWJsZV9uYW1lX2tleSA9ICdzY2hlZHVsZSc7XG5cdFx0dGhpcy5jb250ZXh0X21lbnVfbmFtZSA9ICQuaTE4bi5fKCAnU2NoZWR1bGVzJyApO1xuXHRcdHRoaXMubmF2aWdhdGlvbl9sYWJlbCA9ICQuaTE4bi5fKCAnU2NoZWR1bGUnICk7XG5cdFx0dGhpcy5hcGkgPSBUVEFQSS5BUElTY2hlZHVsZTtcblx0XHR0aGlzLnVzZXJfZ3JvdXBfYXBpID0gVFRBUEkuQVBJVXNlckdyb3VwO1xuXHRcdHRoaXMuYWJzZW5jZV9wb2xpY3lfYXBpID0gVFRBUEkuQVBJQWJzZW5jZVBvbGljeTtcblx0XHR0aGlzLmNvbXBhbnlfYXBpID0gVFRBUEkuQVBJQ29tcGFueTtcblx0XHR0aGlzLnVzZXJfYXBpID0gVFRBUEkuQVBJVXNlcjtcblx0XHR0aGlzLmN1cnJlbmN5X2FwaSA9IFRUQVBJLkFQSUN1cnJlbmN5O1xuXHRcdHRoaXMuZXZlbnRfYnVzID0gbmV3IFRURXZlbnRCdXMoeyB2aWV3X2lkOiB0aGlzLnZpZXdJZCB9KTtcblxuXG5cdFx0aWYgKCBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAyMCApIHtcblx0XHRcdHRoaXMuam9iX2FwaSA9IFRUQVBJLkFQSUpvYjtcblx0XHRcdHRoaXMuam9iX2l0ZW1fYXBpID0gVFRBUEkuQVBJSm9iSXRlbTtcblx0XHRcdHRoaXMucHVuY2hfdGFnX2FwaSA9IFRUQVBJLkFQSVB1bmNoVGFnO1xuXHRcdFx0dGhpcy5kZXBhcnRtZW50X2FwaSA9IFRUQVBJLkFQSURlcGFydG1lbnQ7XG5cdFx0fVxuXG5cdFx0dGhpcy5hcGlfYWJzZW5jZV9wb2xpY3kgPSBUVEFQSS5BUElBYnNlbmNlUG9saWN5O1xuXG5cdFx0dGhpcy5zY3JvbGxfcG9zaXRpb24gPSAwO1xuXG5cdFx0dGhpcy5pbml0UGVybWlzc2lvbigpO1xuXHRcdHRoaXMucmVuZGVyKCk7XG5cdFx0dGhpcy5idWlsZENvbnRleHRNZW51KCk7XG5cblx0XHR0aGlzLmluaXREYXRhKCk7XG5cdH1cblxuXHRqb2JVSVZhbGlkYXRlKCBwX2lkICkge1xuXG5cdFx0aWYgKCAhcF9pZCApIHtcblx0XHRcdHBfaWQgPSB0aGlzLnBlcm1pc3Npb25faWQ7XG5cdFx0fVxuXG5cdFx0aWYgKCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggJ2pvYicsICdlbmFibGVkJyApICYmXG5cdFx0XHRQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggcF9pZCwgJ2VkaXRfam9iJyApICYmXG5cdFx0XHQoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpID49IDIwICkgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0am9iSXRlbVVJVmFsaWRhdGUoIHBfaWQgKSB7XG5cblx0XHRpZiAoICFwX2lkICkge1xuXHRcdFx0cF9pZCA9IHRoaXMucGVybWlzc2lvbl9pZDtcblx0XHR9XG5cblx0XHRpZiAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCAnam9iX2l0ZW0nLCAnZW5hYmxlZCcgKSAmJlxuXHRcdFx0UGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHBfaWQsICdlZGl0X2pvYl9pdGVtJyApICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdHB1bmNoVGFnVUlWYWxpZGF0ZSggcF9pZCApIHtcblxuXHRcdGlmICggIXBfaWQgKSB7XG5cdFx0XHRwX2lkID0gdGhpcy5wZXJtaXNzaW9uX2lkO1xuXHRcdH1cblxuXHRcdGlmICggUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoICdwdW5jaF90YWcnLCAnZW5hYmxlZCcgKSAmJlxuXHRcdFx0UGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHBfaWQsICdlZGl0X2pvYl9pdGVtJyApICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdGJyYW5jaFVJVmFsaWRhdGUoIHBfaWQgKSB7XG5cblx0XHRpZiAoICFwX2lkICkge1xuXHRcdFx0cF9pZCA9IHRoaXMucGVybWlzc2lvbl9pZDtcblx0XHR9XG5cblx0XHRpZiAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCBwX2lkLCAnZWRpdF9icmFuY2gnICkgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0ZGVwYXJ0bWVudFVJVmFsaWRhdGUoIHBfaWQgKSB7XG5cblx0XHRpZiAoICFwX2lkICkge1xuXHRcdFx0cF9pZCA9IHRoaXMucGVybWlzc2lvbl9pZDtcblx0XHR9XG5cblx0XHRpZiAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCBwX2lkLCAnZWRpdF9kZXBhcnRtZW50JyApICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdHVuc2NoZWR1bGVkRW1wbG95ZWVVSVZhbGlkYXRlKCkge1xuXG5cdFx0aWYgKCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggJ3NjaGVkdWxlJywgJ3ZpZXcnICkgfHwgUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoICdzY2hlZHVsZScsICd2aWV3X2NoaWxkJyApICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdC8vU3BlaWNhbCBwZXJtaXNzaW9uIGNoZWNrIGZvciB2aWV3cywgbmVlZCBvdmVycmlkZVxuXHRpbml0UGVybWlzc2lvbigpIHtcblx0XHRzdXBlci5pbml0UGVybWlzc2lvbigpO1xuXG5cdFx0dGhpcy5zaG93X3NlYXJjaF90YWIgPSB0cnVlO1xuXHRcdC8vU2VlIGJ1aWxkU2VhcmNoRmllbGRzKCkgZm9yIGFkZGl0aW9uYWwgcGVybWlzc2lvbiBjaGVja3MuXG5cdFx0Ly8gaWYgKCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggdGhpcy5wZXJtaXNzaW9uX2lkLCAndmlldycgKSB8fCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggdGhpcy5wZXJtaXNzaW9uX2lkLCAndmlld19jaGlsZCcgKSApIHtcblx0XHQvLyBcdHRoaXMuc2hvd19zZWFyY2hfdGFiID0gdHJ1ZTtcblx0XHQvLyB9IGVsc2Uge1xuXHRcdC8vIFx0dGhpcy5zaG93X3NlYXJjaF90YWIgPSBmYWxzZTtcblx0XHQvLyB9XG5cblx0XHRpZiAoIHRoaXMuam9iVUlWYWxpZGF0ZSgpICkge1xuXHRcdFx0dGhpcy5zaG93X2pvYl91aSA9IHRydWU7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuc2hvd19qb2JfdWkgPSBmYWxzZTtcblx0XHR9XG5cblx0XHRpZiAoIHRoaXMuam9iSXRlbVVJVmFsaWRhdGUoKSApIHtcblx0XHRcdHRoaXMuc2hvd19qb2JfaXRlbV91aSA9IHRydWU7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuc2hvd19qb2JfaXRlbV91aSA9IGZhbHNlO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5wdW5jaFRhZ1VJVmFsaWRhdGUoKSApIHtcblx0XHRcdHRoaXMuc2hvd19wdW5jaF90YWdfdWkgPSB0cnVlO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnNob3dfcHVuY2hfdGFnX3VpID0gZmFsc2U7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLmJyYW5jaFVJVmFsaWRhdGUoKSApIHtcblx0XHRcdHRoaXMuc2hvd19icmFuY2hfdWkgPSB0cnVlO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnNob3dfYnJhbmNoX3VpID0gZmFsc2U7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLmRlcGFydG1lbnRVSVZhbGlkYXRlKCkgKSB7XG5cdFx0XHR0aGlzLnNob3dfZGVwYXJ0bWVudF91aSA9IHRydWU7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuc2hvd19kZXBhcnRtZW50X3VpID0gZmFsc2U7XG5cdFx0fVxuXHR9XG5cblx0Ly9vbmx5IGJlIGNhbGwgb25jZSB3aGVuIG9wZW4gdGhpcyB2aWV3XG5cdGluaXREYXRhKCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cblx0XHQvL1JlbW92ZSB0YWIgaWYgYW55XG5cdFx0R2xvYmFsLnJlbW92ZVZpZXdUYWIoIHRoaXMudmlld0lkICk7XG5cdFx0UHJvZ3Jlc3NCYXIuc2hvd092ZXJsYXkoKTtcblx0XHR0aGlzLmluaXRPcHRpb25zKCk7XG5cblx0XHQvL0ZvciByZWd1bGFyIGVtcGxveWVlcyB3aG8gY3VycmVudGx5IGNhbid0IHNlZSB0aGUgXCJTYXZlZCBTZWFyY2ggYW5kIExheW91dFwiIHRhYiwgdHJ5IHRvIGJlIHNtYXJ0ZXIgYWJvdXQgd2hhdCBjb2x1bW5zIHRoZXkgZG8gc2VlIGJ5IGRlZmF1bHQuXG5cdFx0dGhpcy5kZWZhdWx0X2Rpc3BsYXlfY29sdW1ucyA9IFtdO1xuXHRcdGlmICggUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHRoaXMucGVybWlzc2lvbl9pZCwgJ2VkaXRfYnJhbmNoJyApICkge1xuXHRcdFx0dGhpcy5kZWZhdWx0X2Rpc3BsYXlfY29sdW1ucy5wdXNoKCAnYnJhbmNoJyApO1xuXHRcdH1cblx0XHRpZiAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCB0aGlzLnBlcm1pc3Npb25faWQsICdlZGl0X2RlcGFydG1lbnQnICkgKSB7XG5cdFx0XHR0aGlzLmRlZmF1bHRfZGlzcGxheV9jb2x1bW5zLnB1c2goICdkZXBhcnRtZW50JyApO1xuXHRcdH1cblx0XHRpZiAoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpID49IDIwICkge1xuXHRcdFx0aWYgKCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggdGhpcy5wZXJtaXNzaW9uX2lkLCAnZWRpdF9qb2InICkgKSB7XG5cdFx0XHRcdHRoaXMuZGVmYXVsdF9kaXNwbGF5X2NvbHVtbnMucHVzaCggJ2pvYicgKTtcblx0XHRcdH1cblx0XHRcdGlmICggUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHRoaXMucGVybWlzc2lvbl9pZCwgJ2VkaXRfam9iX2l0ZW0nICkgKSB7XG5cdFx0XHRcdHRoaXMuZGVmYXVsdF9kaXNwbGF5X2NvbHVtbnMucHVzaCggJ2pvYl9pdGVtJyApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHZhciBkYXRlID0gbmV3IERhdGUoKTtcblxuXHRcdGlmICggR2xvYmFsLlVOSVRfVEVTVF9NT0RFID09IHRydWUgKSB7XG5cdFx0XHRMb2NhbENhY2hlRGF0YS5sYXN0X3NjaGVkdWxlX3NlbGVjdGVkX2RhdGUgPSAnMTUtRmViLTE4Jztcblx0XHR9XG5cblx0XHR2YXIgZm9ybWF0ID0gR2xvYmFsLmdldExvZ2luVXNlckRhdGVGb3JtYXQoKTtcblx0XHR2YXIgZGF0ZVN0ciA9IGRhdGUuZm9ybWF0KCBmb3JtYXQgKTtcblxuXHRcdGlmICggIUxvY2FsQ2FjaGVEYXRhLmxhc3Rfc2NoZWR1bGVfc2VsZWN0ZWRfZGF0ZSApIHtcblx0XHRcdGlmICggTG9jYWxDYWNoZURhdGEuY3VycmVudF9zZWxlY3RfZGF0ZSAmJiBHbG9iYWwuc3RyVG9EYXRlKCBMb2NhbENhY2hlRGF0YS5jdXJyZW50X3NlbGVjdF9kYXRlLCAnWVlZWS1NTS1ERCcgKSApIHsgLy9TZWxlY3QgZGF0ZSBnZXQgZnJvbSBVUkwuXG5cdFx0XHRcdHRoaXMuc2V0RGF0ZVBpY2tlclZhbHVlKCBHbG9iYWwuc3RyVG9EYXRlKCBMb2NhbENhY2hlRGF0YS5jdXJyZW50X3NlbGVjdF9kYXRlLCAnWVlZWS1NTS1ERCcgKS5mb3JtYXQoKSApO1xuXHRcdFx0XHRMb2NhbENhY2hlRGF0YS5jdXJyZW50X3NlbGVjdF9kYXRlID0gJyc7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLnNldERhdGVQaWNrZXJWYWx1ZSggZGF0ZVN0ciApO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnNldERhdGVQaWNrZXJWYWx1ZSggTG9jYWxDYWNoZURhdGEubGFzdF9zY2hlZHVsZV9zZWxlY3RlZF9kYXRlICk7XG5cdFx0fVxuXG5cdFx0dGhpcy5zZXRNb3ZlT3JEcm9wTW9kZSggdGhpcy5zZWxlY3RfZHJhZ19tZW51X2lkID8gdGhpcy5zZWxlY3RfZHJhZ19tZW51X2lkIDogJ21vdmUnICk7XG5cdFx0Ly9Jc3N1ZSAjMzI4MCAtIFJhY2UgY29uZGl0aW9uIHdoZXJlIHByZXZpb3VzIHNlYXJjaCBsYXlvdXQgd2lsbCBub3QgZXhpc3QgaW4gVUkgd2hlbiBleHBlY3RlZCBhcyBBUEkgZm9yIGN1c3RvbSBmaWVsZCBkYXRhIGhhcyBub3QgcmV0dXJuZWQgeWV0LlxuXHRcdC8vU2NoZWR1bGVWaWV3Q29udHJvbGxlciBvdmVycmlkZXMgaW5pdERhdGEoKSBmcm9tIEJhc2VWaWV3Q29udHJvbGxlciB0aGF0IHdhaXRzIG9uIHRoZSBjdXN0b20gZmllbGQgcHJvbWlzZSB0byByZXNvbHZlIGJlZm9yZSBjb250aW51aW5nLlxuXHRcdFRUUHJvbWlzZS53YWl0KCAnQmFzZVZpZXdDb250cm9sbGVyJywgJ2dldEN1c3RvbUZpZWxkcycsIGZ1bmN0aW9uKCkge1xuXHRcdFx0JHRoaXMuZ2V0QWxsQ29sdW1ucyggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCR0aGlzLmluaXRMYXlvdXQoKTtcblx0XHRcdH0gKTtcblx0XHR9ICk7XG5cdH1cblxuXHRzZXRUb2dnbGVCdXR0b25WYWx1ZSggdmFsICkge1xuXG5cdFx0aWYgKCB0aGlzLnRvZ2dsZV9idXR0b24gKSB7XG5cdFx0XHR0aGlzLnRvZ2dsZV9idXR0b24uc2V0VmFsdWUoIHZhbCApO1xuXG5cdFx0XHR0aGlzLnNldFRvZ2dsZUJ1dHRvblVybCgpO1xuXHRcdH1cblx0fVxuXG5cdHNldFRvZ2dsZUJ1dHRvblVybCgpIHtcblxuXHRcdHZhciBtb2RlID0gdGhpcy5nZXRNb2RlKCk7XG5cdFx0dmFyIGRlZmF1bHRfZGF0ZSA9IHRoaXMuc3RhcnRfZGF0ZV9waWNrZXIuZ2V0RGVmYXVsdEZvcm1hdFZhbHVlKCk7XG5cdFx0aWYgKCAhdGhpcy5lZGl0X3ZpZXcgKSB7XG5cdFx0XHRHbG9iYWwuc2V0VVJMVG9Ccm93c2VyKCBHbG9iYWwuZ2V0QmFzZVVSTCgpICsgJyMhbT0nICsgdGhpcy52aWV3SWQgKyAnJm1vZGU9JyArIG1vZGUgKTtcblx0XHR9XG5cdH1cblxuXHRzZXREYXRlUGlja2VyVmFsdWUoIHZhbCApIHtcblxuXHRcdHRoaXMuc3RhcnRfZGF0ZV9waWNrZXIuc2V0VmFsdWUoIHZhbCApO1xuXG5cdFx0Ly90aGlzLnNldERhdGVVcmwoKTtcblxuXHRcdExvY2FsQ2FjaGVEYXRhLmxhc3Rfc2NoZWR1bGVfc2VsZWN0ZWRfZGF0ZSA9IHZhbDtcblx0fVxuXG5cdGdldEFsbENvbHVtbnMoIGNhbGxCYWNrICkge1xuXG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR0aGlzLmFwaS5nZXRPcHRpb25zKCAnY29sdW1ucycsIHtcblx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggY29sdW1uc19yZXN1bHQgKSB7XG5cdFx0XHRcdHZhciBjb2x1bW5zX3Jlc3VsdF9kYXRhID0gY29sdW1uc19yZXN1bHQuZ2V0UmVzdWx0KCk7XG5cdFx0XHRcdCR0aGlzLmFsbF9jb2x1bW5zID0gR2xvYmFsLmJ1aWxkQ29sdW1uQXJyYXkoIGNvbHVtbnNfcmVzdWx0X2RhdGEgKTtcblxuXHRcdFx0XHQkdGhpcy5hcGkuZ2V0T3B0aW9ucyggJ2dyb3VwX2NvbHVtbnMnLCB7XG5cdFx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCBncm91cF9jb2x1bW5zX3Jlc3VsdCApIHtcblxuXHRcdFx0XHRcdFx0dmFyIGFsbF9jb2x1bW5zID0gR2xvYmFsLmJ1aWxkQ29sdW1uQXJyYXkoIGNvbHVtbnNfcmVzdWx0X2RhdGEgKTtcblx0XHRcdFx0XHRcdHZhciBncm91cF9jb2x1bW5zX3Jlc3VsdF9kYXRhID0gZ3JvdXBfY29sdW1uc19yZXN1bHQuZ2V0UmVzdWx0KCk7XG5cblx0XHRcdFx0XHRcdHZhciBmaW5hbF9hbGxfY29sdW1ucyA9IFtdO1xuXG5cdFx0XHRcdFx0XHR2YXIgYWxsX2xlbiA9IGFsbF9jb2x1bW5zLmxlbmd0aDtcblx0XHRcdFx0XHRcdHZhciBncm91cF9sZW4gPSBncm91cF9jb2x1bW5zX3Jlc3VsdF9kYXRhLmxlbmd0aDtcblxuXHRcdFx0XHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgZ3JvdXBfbGVuOyBpKysgKSB7XG5cdFx0XHRcdFx0XHRcdHZhciBncm91cF9jb2x1bW5faWQgPSBncm91cF9jb2x1bW5zX3Jlc3VsdF9kYXRhW2ldO1xuXHRcdFx0XHRcdFx0XHRmb3IgKCB2YXIgaiA9IDA7IGogPCBhbGxfbGVuOyBqKysgKSB7XG5cdFx0XHRcdFx0XHRcdFx0dmFyIGNvbHVtbiA9IGFsbF9jb2x1bW5zW2pdO1xuXHRcdFx0XHRcdFx0XHRcdGlmICggY29sdW1uLnZhbHVlID09PSBncm91cF9jb2x1bW5faWQgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRmaW5hbF9hbGxfY29sdW1ucy5wdXNoKCBjb2x1bW4gKTtcblx0XHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHQkdGhpcy5hbGxfY29sdW1ucyA9IGZpbmFsX2FsbF9jb2x1bW5zO1xuXG5cdFx0XHRcdFx0XHQkdGhpcy5jb2x1bW5fc2VsZWN0b3Iuc2V0VW5zZWxlY3RlZEdyaWREYXRhKCAkdGhpcy5hbGxfY29sdW1ucyApO1xuXHRcdFx0XHRcdFx0aWYgKCBjYWxsQmFjayApIHtcblx0XHRcdFx0XHRcdFx0Y2FsbEJhY2soKTtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cblx0aW5pdExheW91dCgpIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdCR0aGlzLmdldEFsbExheW91dHMoIGZ1bmN0aW9uKCkge1xuXHRcdFx0JHRoaXMuc2V0U2VsZWN0TGF5b3V0KCk7XG5cdFx0XHQkdGhpcy5zZWFyY2goIHRydWUsIGZhbHNlICk7IC8vTWFrZSBzdXJlIHdlIHNldERlZmF1bHRNZW51IGlzIFRSVUUgc28gYXV0b09wZW5FZGl0Vmlld0lmTmVjZXNzYXJ5KCkgaXMgY2FsbGVkLlxuXHRcdH0gKTtcblx0fVxuXG5cdGluaXRPcHRpb25zKCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cblx0XHR0aGlzLmluaXREcm9wRG93bk9wdGlvbiggJ3N0YXR1cycsICcnLCB0aGlzLmFwaSApO1xuXG5cdFx0dGhpcy51c2VyX2dyb3VwX2FwaS5nZXRVc2VyR3JvdXAoICcnLCBmYWxzZSwgZmFsc2UsIHtcblx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzICkge1xuXHRcdFx0XHRyZXMgPSByZXMuZ2V0UmVzdWx0KCk7XG5cblx0XHRcdFx0cmVzID0gR2xvYmFsLmJ1aWxkVHJlZVJlY29yZCggcmVzICk7XG5cdFx0XHRcdCR0aGlzLnVzZXJfZ3JvdXBfYXJyYXkgPSByZXM7XG5cblx0XHRcdFx0aWYgKCAkdGhpcy5iYXNpY19zZWFyY2hfZmllbGRfdWlfZGljWydncm91cF9pZHMnXSApIHtcblx0XHRcdFx0XHQkdGhpcy5iYXNpY19zZWFyY2hfZmllbGRfdWlfZGljWydncm91cF9pZHMnXS5zZXRTb3VyY2VEYXRhKCByZXMgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoICR0aGlzLmFkdl9zZWFyY2hfZmllbGRfdWlfZGljWydncm91cF9pZHMnXSApIHtcblx0XHRcdFx0XHQkdGhpcy5hZHZfc2VhcmNoX2ZpZWxkX3VpX2RpY1snZ3JvdXBfaWRzJ10uc2V0U291cmNlRGF0YSggcmVzICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cblxuXHRnZXRTZWxlY3REYXRlKCkge1xuXHRcdHZhciByZXR2YWwgPSB0aGlzLnN0YXJ0X2RhdGVfcGlja2VyLmdldFZhbHVlKCk7XG5cblx0XHRpZiAoIHJldHZhbCA9PSAnSW52YWxpZCBkYXRlJyApIHtcblx0XHRcdHJldHZhbCA9IG5ldyBEYXRlKCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHJldHZhbDtcblx0fVxuXG5cdGdldEdyaWRTZWxlY3RJZEFycmF5KCkge1xuXG5cdFx0dmFyIHJlc3VsdCA9IFtdO1xuXHRcdHZhciBsZW4gPSB0aGlzLnNlbGVjdF9hbGxfc2hpZnRzX2FycmF5Lmxlbmd0aDtcblx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdHZhciBpdGVtID0gdGhpcy5zZWxlY3RfYWxsX3NoaWZ0c19hcnJheVtpXTtcblx0XHRcdGlmICggaXRlbS5pZCAmJiBpdGVtLmlkICE9IFRUVVVJRC56ZXJvX2lkICYmIGl0ZW0uaWQgIT0gVFRVVUlELm5vdF9leGlzdF9pZCApIHtcblx0XHRcdFx0cmVzdWx0LnB1c2goIGl0ZW0uaWQgKTtcblx0XHRcdH1cblxuXHRcdH1cblxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cblxuXHRnZXRTZWxlY3RlZEl0ZW0oKSB7XG5cblx0XHR2YXIgc2VsZWN0ZWRfaXRlbSA9IG51bGw7XG5cdFx0aWYgKCB0aGlzLmVkaXRfdmlldyApIHtcblx0XHRcdHNlbGVjdGVkX2l0ZW0gPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQ7XG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0aWYgKCB0aGlzLnNlbGVjdF9hbGxfc2hpZnRzX2FycmF5Lmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdHNlbGVjdGVkX2l0ZW0gPSB0aGlzLnNlbGVjdF9hbGxfc2hpZnRzX2FycmF5WzBdO1xuXHRcdFx0fVxuXG5cdFx0fVxuXG5cdFx0aWYgKCBzZWxlY3RlZF9pdGVtICkge1xuXHRcdFx0cmV0dXJuIEdsb2JhbC5jbG9uZSggc2VsZWN0ZWRfaXRlbSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gbnVsbDtcblx0XHR9XG5cdH1cblxuXHRfY29udGludWVEb0NvcHlBc05ldygpIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHRoaXMuc2V0Q3VycmVudEVkaXRWaWV3U3RhdGUoICduZXcnICk7XG5cdFx0TG9jYWxDYWNoZURhdGEuY3VycmVudF9kb2luZ19jb250ZXh0X2FjdGlvbiA9ICdjb3B5X2FzX25ldyc7XG5cblx0XHRpZiAoIEdsb2JhbC5pc1NldCggdGhpcy5lZGl0X3ZpZXcgKSApIHtcblxuXHRcdFx0dGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkID0gJyc7XG5cdFx0XHR2YXIgbmF2aWdhdGlvbl9kaXYgPSB0aGlzLmVkaXRfdmlldy5maW5kKCAnLm5hdmlnYXRpb24tZGl2JyApO1xuXHRcdFx0bmF2aWdhdGlvbl9kaXYuY3NzKCAnZGlzcGxheScsICdub25lJyApO1xuXHRcdFx0dGhpcy5zZXRDdXJyZW50RWRpdFJlY29yZERhdGEoKTsgLy8gUmVzZXQgZGF0YSB0byB3aWRnZXRzIHRvIHJlc2V0IGFsbCB3aWRnZXRzIHN0YXRcblx0XHRcdHRoaXMuc2V0RWRpdE1lbnUoKTtcblx0XHRcdHRoaXMuc2V0VGFiU3RhdHVzKCk7XG5cdFx0XHR0aGlzLmlzX2NoYW5nZWQgPSBmYWxzZTtcblx0XHRcdFByb2dyZXNzQmFyLmNsb3NlT3ZlcmxheSgpO1xuXG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0dmFyIGZpbHRlciA9IHt9O1xuXHRcdFx0dmFyIGdyaWRfc2VsZWN0ZWRfaWRfYXJyYXkgPSB0aGlzLmdldEdyaWRTZWxlY3RJZEFycmF5KCk7XG5cdFx0XHR2YXIgZ3JpZF9zZWxlY3RlZF9sZW5ndGggPSBncmlkX3NlbGVjdGVkX2lkX2FycmF5Lmxlbmd0aDtcblxuXHRcdFx0aWYgKCBncmlkX3NlbGVjdGVkX2xlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdHZhciBzZWxlY3RlZElkID0gZ3JpZF9zZWxlY3RlZF9pZF9hcnJheVswXTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHZhciBzZWxlY3Rfc2hpZnQgPSBHbG9iYWwuY2xvbmUoICR0aGlzLnNlbGVjdF9hbGxfc2hpZnRzX2FycmF5WzBdICk7XG5cdFx0XHRcdHNlbGVjdF9zaGlmdCA9ICR0aGlzLnJlc2V0U29tZUZpZWxkcyggc2VsZWN0X3NoaWZ0ICk7XG5cdFx0XHRcdCR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgPSBzZWxlY3Rfc2hpZnQ7XG5cdFx0XHRcdCR0aGlzLm9wZW5FZGl0VmlldygpO1xuXHRcdFx0XHQkdGhpcy5pbml0RWRpdFZpZXcoKTtcblx0XHRcdFx0cmV0dXJuO1xuXG5cdFx0XHR9XG5cblx0XHRcdGZpbHRlci5maWx0ZXJfZGF0YSA9IHt9O1xuXHRcdFx0ZmlsdGVyLmZpbHRlcl9kYXRhLmlkID0gW3NlbGVjdGVkSWRdO1xuXG5cdFx0XHR0aGlzLmFwaVsnZ2V0JyArIHRoaXMuYXBpLmtleV9uYW1lXSggZmlsdGVyLCB7XG5cdFx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXG5cdFx0XHRcdFx0dmFyIHJlc3VsdF9kYXRhID0gcmVzdWx0LmdldFJlc3VsdCgpO1xuXG5cdFx0XHRcdFx0Ly8jMjU3MSAtIHJlc3VsdF9kYXRhIGlzIHVuZGVmaW5lZCAod2hlbiByZXN1bHRfZGF0YSA9PT0gdHJ1ZSB0aGVyZSBpcyBubyByZXN1bHRbMF0pXG5cdFx0XHRcdFx0aWYgKCAhcmVzdWx0X2RhdGEgfHwgcmVzdWx0X2RhdGEgPT09IHRydWUgKSB7XG5cdFx0XHRcdFx0XHRUQWxlcnRNYW5hZ2VyLnNob3dBbGVydCggJC5pMThuLl8oICdSZWNvcmQgZG9lcyBub3QgZXhpc3QnICkgKTtcblx0XHRcdFx0XHRcdCR0aGlzLm9uQ2FuY2VsQ2xpY2soKTtcblx0XHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQkdGhpcy5vcGVuRWRpdFZpZXcoKTsgLy8gUHV0IGl0IGhlcmUgaXMgdG8gYXZvaWQgaWYgdGhlIHNlbGVjdGVkIG9uZSBpcyBub3QgZXhpc3RlZCBpbiBkYXRhIG9yIGhhdmUgZGVsZXRlZCBieSBvdGhlciBwcmFncmFtLiBpbiB0aGlzIGNhc2UsIHRoZSBlZGl0IHZpZXcgc2hvdWxkIG5vdCBiZSBvcGVuZC5cblxuXHRcdFx0XHRcdHJlc3VsdF9kYXRhID0gcmVzdWx0X2RhdGFbMF07XG5cblx0XHRcdFx0XHRyZXN1bHRfZGF0YS5pZCA9ICcnO1xuXG5cdFx0XHRcdFx0aWYgKCAkdGhpcy5zdWJfdmlld19tb2RlICYmICR0aGlzLnBhcmVudF9rZXkgKSB7XG5cdFx0XHRcdFx0XHRyZXN1bHRfZGF0YVskdGhpcy5wYXJlbnRfa2V5XSA9ICR0aGlzLnBhcmVudF92YWx1ZTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkID0gcmVzdWx0X2RhdGE7XG5cdFx0XHRcdFx0JHRoaXMuaW5pdEVkaXRWaWV3KCk7XG5cblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXHRcdH1cblx0fVxuXG5cdG9uVmlld0NsaWNrKCByZWNvcmQsIG5vUmVmcmVzaFVJICkge1xuXHRcdHRoaXMuc2V0Q3VycmVudEVkaXRWaWV3U3RhdGUoICd2aWV3JyApO1xuXG5cdFx0dmFyIHJlY29yZF9pZCA9IHRoaXMuZ2V0Vmlld1NlbGVjdGVkUmVjb3JkSWQoIHJlY29yZCApO1xuXHRcdGlmICggR2xvYmFsLmlzRmFsc2VPck51bGwoIHJlY29yZF9pZCApICkge1xuXHRcdFx0VFRQcm9taXNlLmFkZCggJ1NjaGVkdWxlJywgJ2luaXQnICk7XG5cdFx0XHR0aGlzLm9wZW5FZGl0VmlldygpO1xuXHRcdFx0dmFyIHNlbGVjdF9zaGlmdCA9IEdsb2JhbC5jbG9uZSggdGhpcy5zZWxlY3RfYWxsX3NoaWZ0c19hcnJheVswXSApO1xuXHRcdFx0c2VsZWN0X3NoaWZ0ID0gdGhpcy5yZXNldFNvbWVGaWVsZHMoIHNlbGVjdF9zaGlmdCApO1xuXHRcdFx0dGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkID0gc2VsZWN0X3NoaWZ0O1xuXG5cdFx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdFx0VFRQcm9taXNlLndhaXQoICdTY2hlZHVsZScsICdpbml0JywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCR0aGlzLmluaXRFZGl0VmlldygpO1xuXHRcdFx0fSApO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLnNldEN1cnJlbnRTZWxlY3RlZFJlY29yZCggcmVjb3JkX2lkICk7XG5cblx0XHR0aGlzLm9wZW5FZGl0VmlldygpO1xuXG5cdFx0dmFyIGZpbHRlciA9IHRoaXMuZ2V0QVBJRmlsdGVycygpO1xuXG5cdFx0cmV0dXJuIHRoaXMuZG9WaWV3QVBJQ2FsbCggZmlsdGVyICk7XG5cdH1cblxuXHRnZXRDb21tb25GaWVsZHMoKSB7XG5cdFx0dmFyIGJhc2VSZWNvcmQ7XG5cdFx0JC5lYWNoKCB0aGlzLnNlbGVjdF9hbGxfc2hpZnRzX2FycmF5LCBmdW5jdGlvbiggaW5kZXgsIHZhbHVlICkge1xuXHRcdFx0aWYgKCAhYmFzZVJlY29yZCApIHtcblx0XHRcdFx0YmFzZVJlY29yZCA9IEdsb2JhbC5jbG9uZSggdmFsdWUgKTtcblx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHR9XG5cdFx0XHRmb3IgKCB2YXIga2V5IGluIHZhbHVlICkge1xuXHRcdFx0XHRiYXNlUmVjb3JkW2tleV0gIT09IHZhbHVlW2tleV0gJiYgZGVsZXRlIGJhc2VSZWNvcmRba2V5XTtcblx0XHRcdH1cblx0XHR9ICk7XG5cblx0XHRyZXR1cm4gYmFzZVJlY29yZDtcblx0fVxuXG5cdG9uTWFzc0VkaXRDbGljaygpIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciBmaWx0ZXIgPSB7fTtcblx0XHR2YXIgZ3JpZF9zZWxlY3RlZF9pZF9hcnJheSA9IFtdO1xuXHRcdHRoaXMuc2V0Q3VycmVudEVkaXRWaWV3U3RhdGUoICdtYXNzX2VkaXQnICk7XG5cdFx0dGhpcy5tYXNzX2VkaXRfcmVjb3JkX2lkcyA9IFtdO1xuXG5cdFx0Z3JpZF9zZWxlY3RlZF9pZF9hcnJheSA9IHRoaXMuZ2V0R3JpZFNlbGVjdElkQXJyYXkoKTtcblx0XHQkdGhpcy5vcGVuRWRpdFZpZXcoKTtcblxuXHRcdCQuZWFjaCggZ3JpZF9zZWxlY3RlZF9pZF9hcnJheSwgZnVuY3Rpb24oIGluZGV4LCB2YWx1ZSApIHtcblx0XHRcdCR0aGlzLm1hc3NfZWRpdF9yZWNvcmRfaWRzLnB1c2goIHZhbHVlICk7XG5cdFx0fSApO1xuXG5cdFx0JHRoaXMuc2VsZWN0ZWRfdXNlcl9pZHMgPSBbXTtcblx0XHQkLmVhY2goIHRoaXMuc2VsZWN0X2FsbF9zaGlmdHNfYXJyYXksIGZ1bmN0aW9uKCBpbmRleCwgdmFsdWUgKSB7XG5cdFx0XHR2YXIgc2hpZnQgPSB2YWx1ZTtcblx0XHRcdGlmICggc2hpZnQuaGFzT3duUHJvcGVydHkoICd1c2VyX2lkJyApICkge1xuXHRcdFx0XHQkdGhpcy5zZWxlY3RlZF91c2VyX2lkcy5wdXNoKCBzaGlmdC51c2VyX2lkICk7XG5cdFx0XHR9XG5cblx0XHR9ICk7XG5cblx0XHRmaWx0ZXIuZmlsdGVyX2RhdGEgPSB7fTtcblx0XHRmaWx0ZXIuZmlsdGVyX2RhdGEuaWQgPSB0aGlzLm1hc3NfZWRpdF9yZWNvcmRfaWRzO1xuXG5cdFx0aWYgKCB0aGlzLm1hc3NfZWRpdF9yZWNvcmRfaWRzLmxlbmd0aCAhPT0gdGhpcy5zZWxlY3RfYWxsX3NoaWZ0c19hcnJheS5sZW5ndGggKSB7XG5cdFx0XHRvbk1hc3NFZGl0UmVzdWx0KCB0aGlzLmdldENvbW1vbkZpZWxkcygpICk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dGhpcy5hcGlbJ2dldENvbW1vbicgKyB0aGlzLmFwaS5rZXlfbmFtZSArICdEYXRhJ10oIGZpbHRlciwge1xuXHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cblx0XHRcdFx0dmFyIHJlc3VsdF9kYXRhID0gcmVzdWx0LmdldFJlc3VsdCgpO1xuXG5cdFx0XHRcdGlmICggIXJlc3VsdF9kYXRhICkge1xuXHRcdFx0XHRcdHJlc3VsdF9kYXRhID0gW107XG5cdFx0XHRcdH1cblx0XHRcdFx0b25NYXNzRWRpdFJlc3VsdCggcmVzdWx0X2RhdGEgKTtcblxuXHRcdFx0fVxuXHRcdH0gKTtcblxuXHRcdGZ1bmN0aW9uIG9uTWFzc0VkaXRSZXN1bHQoIHJlc3VsdF9kYXRhICkge1xuXHRcdFx0JHRoaXMuYXBpWydnZXRPcHRpb25zJ10oICd1bmlxdWVfY29sdW1ucycsIHtcblx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cdFx0XHRcdFx0JHRoaXMudW5pcXVlX2NvbHVtbnMgPSByZXN1bHQuZ2V0UmVzdWx0KCk7XG5cdFx0XHRcdFx0JHRoaXMuYXBpWydnZXRPcHRpb25zJ10oICdsaW5rZWRfY29sdW1ucycsIHtcblx0XHRcdFx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0MSApIHtcblxuXHRcdFx0XHRcdFx0XHQkdGhpcy5saW5rZWRfY29sdW1ucyA9IHJlc3VsdDEuZ2V0UmVzdWx0KCk7XG5cblx0XHRcdFx0XHRcdFx0aWYgKCAkdGhpcy5zdWJfdmlld19tb2RlICYmICR0aGlzLnBhcmVudF9rZXkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0cmVzdWx0X2RhdGFbJHRoaXMucGFyZW50X2tleV0gPSAkdGhpcy5wYXJlbnRfdmFsdWU7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0JHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCA9IHJlc3VsdF9kYXRhO1xuXHRcdFx0XHRcdFx0XHQkdGhpcy5pc19tYXNzX2VkaXRpbmcgPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHQkdGhpcy5pbml0RWRpdFZpZXcoKTtcblxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gKTtcblxuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cdFx0fVxuXHR9XG5cblx0b25FZGl0Q2xpY2soIHJlY29yZF9pZCwgbm9SZWZyZXNoVUkgKSB7XG5cdFx0Ly8gIzI2NDQ6IE5vdGU6IFRoaXMgY29kZSBmaXhlcyBhIGJ1ZyB3aGVyZSB0aGUgZWRpdCBzY3JlZW4gaXMgbm90IG9wZW5lZCBvbiBmaXJzdCB0cnksIGJ1dCBpcyBvbiBzZWNvbmQuIExpa2VseSBkdWUgdG8gdGhlIFRUUHJvbWlzZSBhbmQgcG90ZW50aWFsIHJhY2UgY29uZGl0aW9ucy4gU2VlIGNvbW1pdCBoaXN0b3J5IGZvciBkZXRhaWxzLlxuXHRcdFRUUHJvbWlzZS5hZGQoICdTY2hlZHVsZScsICdpbml0JyApO1xuXHRcdHRoaXMuc2V0Q3VycmVudEVkaXRWaWV3U3RhdGUoICdlZGl0JyApO1xuXHRcdHRoaXMub3BlbkVkaXRWaWV3KCk7XG5cblx0XHRyZWNvcmRfaWQgPSB0aGlzLmdldEVkaXRTZWxlY3RlZFJlY29yZElkKCByZWNvcmRfaWQgKTtcblx0XHRpZiAoIEdsb2JhbC5pc0ZhbHNlT3JOdWxsKCByZWNvcmRfaWQgKSApIHtcblx0XHRcdHRoaXMub3BlbkVkaXRWaWV3KCk7XG5cdFx0XHR2YXIgc2VsZWN0X3NoaWZ0ID0gR2xvYmFsLmNsb25lKCB0aGlzLnNlbGVjdF9hbGxfc2hpZnRzX2FycmF5WzBdICk7XG5cdFx0XHRzZWxlY3Rfc2hpZnQgPSB0aGlzLnJlc2V0U29tZUZpZWxkcyggc2VsZWN0X3NoaWZ0ICk7XG5cdFx0XHR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgPSBzZWxlY3Rfc2hpZnQ7XG5cdFx0XHR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudXNlcl9pZHMgPSBbdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnVzZXJfaWRdOyAvLyMyNjEwIC0gZW5zdXJlIHRoYXQgZWRpdCByZWNvcmQgaXMgcHJvcGVybHkgZm9ybWVkIGluIHJlc3BlY3QgdG8gdXNlcl9pZHNcblx0XHRcdHRoaXMuaXNfdmlld2luZyA9IGZhbHNlO1xuXG5cdFx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdFx0VFRQcm9taXNlLndhaXQoICdTY2hlZHVsZScsICdpbml0JywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCR0aGlzLmluaXRFZGl0VmlldygpO1xuXHRcdFx0fSApO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLnNldEN1cnJlbnRTZWxlY3RlZFJlY29yZCggcmVjb3JkX2lkICk7XG5cblx0XHR2YXIgZmlsdGVyID0gdGhpcy5nZXRBUElGaWx0ZXJzKCk7XG5cblx0XHRyZXR1cm4gdGhpcy5kb0VkaXRBUElDYWxsKCBmaWx0ZXIgKTtcblx0fVxuXG5cdGRvRGVsZXRlQVBJQ2FsbCggcmVtb3ZlX2lkcywgY2FsbGJhY2sgKSB7XG5cdFx0aWYgKCAhY2FsbGJhY2sgKSB7XG5cdFx0XHRjYWxsYmFjayA9IHtcblx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cdFx0XHRcdFx0UHJvZ3Jlc3NCYXIuY2xvc2VPdmVybGF5KCk7XG5cdFx0XHRcdFx0ZG9OZXh0LmNhbGwoIHRoaXMsIHJlc3VsdCApO1xuXHRcdFx0XHRcdGlmICggcmVzdWx0LmlzVmFsaWQoKSApIHtcblx0XHRcdFx0XHRcdHRoaXMub25EZWxldGVEb25lKCByZXN1bHQgKTtcblx0XHRcdFx0XHRcdGlmICggdGhpcy5lZGl0X3ZpZXcgKSB7XG5cdFx0XHRcdFx0XHRcdHRoaXMucmVtb3ZlRWRpdFZpZXcoKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHRoaXMuc2V0Q3VycmVudEVkaXRWaWV3U3RhdGUoICcnICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFRBbGVydE1hbmFnZXIuc2hvd0Vycm9yQWxlcnQoIHJlc3VsdCApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fS5iaW5kKCB0aGlzIClcblx0XHRcdH07XG5cdFx0fVxuXHRcdGlmICggcmVtb3ZlX2lkcyAmJiByZW1vdmVfaWRzLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5hcGlbJ2RlbGV0ZScgKyB0aGlzLmFwaS5rZXlfbmFtZV0oIHJlbW92ZV9pZHMsIGNhbGxiYWNrICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGRvTmV4dC5jYWxsKCB0aGlzLCB7XG5cdFx0XHRcdGlzVmFsaWQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGRvTmV4dCggcmVzdWx0ICkge1xuXHRcdFx0Ly9Jc3N1ZSAjMzAzNCAtIFR5cGVFcnJvcjogQ2Fubm90IHJlYWQgcHJvcGVydGllcyBvZiB1bmRlZmluZWQgKHJlYWRpbmcgJ2lkJykuXG5cdFx0XHQvL0JlY2F1c2UgZGVsZXRpbmcgcmVjdXJyaW5nIHNjaGVkdWxlcyBkb2VzIG5vdCBnbyB0aHJvdWdoIHRoZSBub3JtYWwgcGF0aHdheSwgd2UgbmVlZCB0byByZXNldCBzdGF0ZVxuXHRcdFx0Ly9zbyB0aGF0IFZ1ZSBkb2VzIG5vdCBkZWNpZGUgd2Ugb24gYW4gZWRpdCB2aWV3IGFuZCByZXRyaWV2ZSB0aGUgd3JvbmcgY29udGV4dCBtZW51IGFycmF5LlxuXHRcdFx0Ly9PdGhlcndpc2UgSmF2YVNjcmlwdCBleGNlcHRpb25zIG1heSB0cmlnZ2VyIHdoZW4gcmVhZGluZyBhbiBlbXB0eSBjb250ZXh0IG1lbnUgYXJyYXkgZHVyaW5nIG90aGVyIGFjdGlvbnMuXG5cdFx0XHRpZiAoIHRoaXMuZWRpdF92aWV3ICkge1xuXHRcdFx0XHR0aGlzLnJlbW92ZUVkaXRWaWV3KCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLnNldEN1cnJlbnRFZGl0Vmlld1N0YXRlKCAnJyApO1xuXHRcdFx0fVxuXG5cdFx0XHQvL1NpbmNlIHdlIGNhbid0IGRlbGV0ZSByZWN1cnJpbmcgc2NoZWR1bGVzLCB3ZSBuZWVkIHRvIG92ZXJyaWRlIHRoZW0gYXMgYWJzZW50IHdpdGhvdXQgYSBhYnNlbmNlIHBvbGljeSBpbnN0ZWFkLlxuXHRcdFx0dmFyIHJlY3VycmluZ19kZWxldGVfc2hpZnRzX2FycmF5ID0gW107XG5cdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCB0aGlzLnNlbGVjdF9jZWxsc19BcnJheS5sZW5ndGg7IGkrKyApIHtcblx0XHRcdFx0aWYgKCB0aGlzLnNlbGVjdF9jZWxsc19BcnJheVtpXS5zaGlmdCApIHtcblx0XHRcdFx0XHR0aGlzLnNlbGVjdF9jZWxsc19BcnJheVtpXS5zaGlmdC5zdGF0dXNfaWQgPSAnMjAnOyAvL1NldCBzaGlmdCB0byBhYnNlbnQuXG5cdFx0XHRcdFx0cmVjdXJyaW5nX2RlbGV0ZV9zaGlmdHNfYXJyYXkucHVzaCggdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXlbaV0uc2hpZnQgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHJlY3VycmluZ19kZWxldGVfc2hpZnRzX2FycmF5Lmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdHRoaXMuYXBpLnNldFNjaGVkdWxlKCByZWN1cnJpbmdfZGVsZXRlX3NoaWZ0c19hcnJheSwge1xuXHRcdFx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdHRoaXMuc2VhcmNoKCk7XG5cdFx0XHRcdFx0fS5iaW5kKCB0aGlzIClcblx0XHRcdFx0fSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0aWYgKCByZXN1bHQuaXNWYWxpZCgpICkge1xuXHRcdFx0XHRcdHRoaXMuc2VhcmNoKCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRnZXRDdXN0b21Db250ZXh0TWVudU1vZGVsKCkge1xuXHRcdHZhciBjb250ZXh0X21lbnVfbW9kZWwgPSB7XG5cdFx0XHRncm91cHM6IHtcblx0XHRcdFx0ZHJhZ19hbmRfZHJvcDoge1xuXHRcdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ0RyYWcgJiBEcm9wJyApLFxuXHRcdFx0XHRcdGlkOiB0aGlzLnZpZXdJZCArICdkcmFnX2FuZF9kcm9wJ1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0ZXhjbHVkZTogW1xuXHRcdFx0XHQnZXhwb3J0X2V4Y2VsJyxcblx0XHRcdFx0J3NhdmVfYW5kX25leHQnLFxuXHRcdFx0XHQnZGVsZXRlX2FuZF9uZXh0Jyxcblx0XHRcdFx0J2NvcHknXG5cdFx0XHRdLFxuXHRcdFx0aW5jbHVkZTogW1xuXHRcdFx0XHQvLyBOb3RlIERyYWcmRHJvcCBpY29ucyB3aWxsIGJlIGNvbmRpdGlvbmFsbHkgcHJlcGVuZGVkIGhlcmUgbGF0ZXIgaW4gY29kZSBmb3IgbGlzdCB2aWV3IG1vZGVzLlxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnSnVtcCBUbycgKSxcblx0XHRcdFx0XHRpZDogJ2p1bXBfdG9faGVhZGVyJyxcblx0XHRcdFx0XHRtZW51X2FsaWduOiAncmlnaHQnLFxuXHRcdFx0XHRcdGFjdGlvbl9ncm91cDogJ2p1bXBfdG8nLFxuXHRcdFx0XHRcdGFjdGlvbl9ncm91cF9oZWFkZXI6IHRydWUsXG5cdFx0XHRcdFx0cGVybWlzc2lvbl9yZXN1bHQ6IGZhbHNlLCAvLyB0byBoaWRlIGl0IGluIGxlZ2FjeSBjb250ZXh0IG1lbnUgYW5kIGF2b2lkIGVycm9ycyBpbiBsZWdhY3kgcGFyc2Vycy5cblx0XHRcdFx0XHRzb3J0X29yZGVyOiA5MDMwXG5cdFx0XHRcdH0sXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRsYWJlbDogJC5pMThuLl8oICdUaW1lU2hlZXQnICksXG5cdFx0XHRcdFx0aWQ6ICd0aW1lc2hlZXQnLFxuXHRcdFx0XHRcdG1lbnVfYWxpZ246ICdyaWdodCcsXG5cdFx0XHRcdFx0YWN0aW9uX2dyb3VwOiAnanVtcF90bycsXG5cdFx0XHRcdFx0Z3JvdXA6ICduYXZpZ2F0aW9uJyxcblx0XHRcdFx0XHRwZXJtaXNzaW9uX3Jlc3VsdDogdHJ1ZSxcblx0XHRcdFx0XHRzb3J0X29yZGVyOiA5MDMwXG5cdFx0XHRcdH0sXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRsYWJlbDogJC5pMThuLl8oICdFZGl0IEVtcGxveWVlJyApLFxuXHRcdFx0XHRcdGlkOiAnZWRpdF9lbXBsb3llZScsXG5cdFx0XHRcdFx0bWVudV9hbGlnbjogJ3JpZ2h0Jyxcblx0XHRcdFx0XHRhY3Rpb25fZ3JvdXA6ICdqdW1wX3RvJyxcblx0XHRcdFx0XHRncm91cDogJ25hdmlnYXRpb24nLFxuXHRcdFx0XHRcdHBlcm1pc3Npb25fcmVzdWx0OiB0cnVlLFxuXHRcdFx0XHRcdHNvcnRfb3JkZXI6IDkwMzBcblx0XHRcdFx0fSxcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ0ltcG9ydCcgKSxcblx0XHRcdFx0XHRpZDogJ2ltcG9ydF9pY29uJyxcblx0XHRcdFx0XHRtZW51X2FsaWduOiAncmlnaHQnLFxuXHRcdFx0XHRcdGFjdGlvbl9ncm91cDogJ2ltcG9ydF9leHBvcnQnLFxuXHRcdFx0XHRcdGdyb3VwOiAnb3RoZXInLFxuXHRcdFx0XHRcdHZ1ZV9pY29uOiAndHRpY29uIHR0aWNvbi1maWxlX2Rvd25sb2FkX2JsYWNrXzI0ZHAnLFxuXHRcdFx0XHRcdHBlcm1pc3Npb25fcmVzdWx0OiBQZXJtaXNzaW9uTWFuYWdlci5jaGVja1RvcExldmVsUGVybWlzc2lvbiggJ0ltcG9ydENTVlNjaGVkdWxlJyApLFxuXHRcdFx0XHRcdHNvcnRfb3JkZXI6IDkwMjVcblx0XHRcdFx0fVxuXHRcdFx0XVxuXHRcdH07XG5cblx0XHQvLyBFZGl0IFZpZXdzXG5cblx0XHRjb250ZXh0X21lbnVfbW9kZWwuaW5jbHVkZS5wdXNoKCB7XG5cdFx0XHRsYWJlbDogJC5pMThuLl8oICdQcmludCcgKSxcblx0XHRcdGlkOiAncHJpbnQnLFxuXHRcdFx0YWN0aW9uX2dyb3VwX2hlYWRlcjogdHJ1ZSxcblx0XHRcdGFjdGlvbl9ncm91cDogJ3ByaW50Jyxcblx0XHRcdG1lbnVfYWxpZ246ICdyaWdodCcsXG5cdFx0XHRzb3J0X29yZGVyOiA5MDIwLFxuXHRcdFx0fSApO1xuXG5cdFx0Y29udGV4dF9tZW51X21vZGVsLmluY2x1ZGUucHVzaCgge1xuXHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnSW5kaXZpZHVhbCBTY2hlZHVsZXMnICksXG5cdFx0XHRpZDogJ3BkZl9zY2hlZHVsZScsXG5cdFx0XHRhY3Rpb25fZ3JvdXA6ICdwcmludCcsXG5cdFx0XHRtZW51X2FsaWduOiAncmlnaHQnLFxuXHRcdFx0c29ydF9vcmRlcjogOTAyMFxuXHRcdH0gKTtcblxuXHRcdGNvbnRleHRfbWVudV9tb2RlbC5pbmNsdWRlLnB1c2goXG5cdFx0XHR7XG5cdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ0ZpbmQgQXZhaWxhYmxlJyApLFxuXHRcdFx0XHRpZDogJ2ZpbmRfYXZhaWxhYmxlJyxcblx0XHRcdFx0dnVlX2ljb246ICd0dGljb24gdHRpY29uLXNlYXJjaF9ibGFja18yNGRwJyxcblx0XHRcdFx0bWVudV9hbGlnbjogJ3JpZ2h0Jyxcblx0XHRcdFx0cGVybWlzc2lvbl9yZXN1bHQ6IHRydWUsXG5cdFx0XHRcdHNob3dfb25fcmlnaHRfY2xpY2s6IHRydWUsXG5cdFx0XHRcdHNvcnRfb3JkZXI6IDcwMDBcblx0XHRcdH1cblx0XHQpO1xuXG5cdFx0aWYgKCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggJ3JlcXVlc3QnLCAnYWRkJyApICkge1xuXHRcdFx0Y29udGV4dF9tZW51X21vZGVsLmluY2x1ZGUucHVzaCgge1xuXHRcdFx0XHRsYWJlbDogJC5pMThuLl8oICdBZGQgUmVxdWVzdCcgKSxcblx0XHRcdFx0aWQ6ICdBZGRSZXF1ZXN0Jyxcblx0XHRcdFx0dnVlX2ljb246ICd0dGljb24gdHRpY29uLXBvc3RfYWRkX2JsYWNrXzI0ZHAnLFxuXHRcdFx0XHRtZW51X2FsaWduOiAncmlnaHQnLFxuXHRcdFx0XHRwZXJtaXNzaW9uX3Jlc3VsdDogdHJ1ZSxcblx0XHRcdFx0cGVybWlzc2lvbjogdHJ1ZSxcblx0XHRcdFx0c2hvd19vbl9yaWdodF9jbGljazogdHJ1ZSxcblx0XHRcdFx0c29ydF9vcmRlcjogNzAxMFxuXHRcdFx0fSApO1xuXHRcdH1cblxuXHRcdGlmICggIXRoaXMuaXNfZWRpdCAmJiAhdGhpcy5pc19tYXNzX2VkaXRpbmcgJiYgIXRoaXMuaXNfdmlld2luZyApIHtcblx0XHRcdGNvbnRleHRfbWVudV9tb2RlbC5pbmNsdWRlLnVuc2hpZnQoIC8vIEFkZCB0byBiZWdnaW5uaW5nIG9mIGFycmF5IHRvIHByZXNlcnZlIGl0ZW0gb3JkZXIuXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRsYWJlbDogJC5pMThuLl8oICdEcmFnICYgRHJvcDogTW92ZScgKSxcblx0XHRcdFx0XHRpZDogJ21vdmUnLFxuXHRcdFx0XHRcdGFjdGlvbl9ncm91cDogJ2RyYWdfYW5kX2Ryb3AnLFxuXHRcdFx0XHRcdG11bHRpX3NlbGVjdF9ncm91cDogMSxcblx0XHRcdFx0XHRtZW51X2FsaWduOiAncmlnaHQnLFxuXHRcdFx0XHRcdGdyb3VwOiAnZHJhZ19hbmRfZHJvcCcsXG5cdFx0XHRcdFx0cGVybWlzc2lvbl9yZXN1bHQ6IHRydWUsXG5cdFx0XHRcdFx0c29ydF9vcmRlcjogODA1MFxuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnRHJhZyAmIERyb3A6IENvcHknICksXG5cdFx0XHRcdFx0aWQ6ICdkcmFnX2NvcHknLFxuXHRcdFx0XHRcdGFjdGlvbl9ncm91cDogJ2RyYWdfYW5kX2Ryb3AnLFxuXHRcdFx0XHRcdG1lbnVfYWxpZ246ICdyaWdodCcsXG5cdFx0XHRcdFx0bXVsdGlfc2VsZWN0X2dyb3VwOiAxLFxuXHRcdFx0XHRcdGdyb3VwOiAnZHJhZ19hbmRfZHJvcCcsXG5cdFx0XHRcdFx0cGVybWlzc2lvbl9yZXN1bHQ6IHRydWUsXG5cdFx0XHRcdFx0c29ydF9vcmRlcjogODA2MFxuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnRHJhZyAmIERyb3A6IFN3YXAnICksXG5cdFx0XHRcdFx0aWQ6ICdzd2FwJyxcblx0XHRcdFx0XHRhY3Rpb25fZ3JvdXA6ICdkcmFnX2FuZF9kcm9wJyxcblx0XHRcdFx0XHRtZW51X2FsaWduOiAncmlnaHQnLFxuXHRcdFx0XHRcdG11bHRpX3NlbGVjdF9ncm91cDogMSxcblx0XHRcdFx0XHRncm91cDogJ2RyYWdfYW5kX2Ryb3AnLFxuXHRcdFx0XHRcdHBlcm1pc3Npb25fcmVzdWx0OiB0cnVlLFxuXHRcdFx0XHRcdHNvcnRfb3JkZXI6IDgwNzBcblx0XHRcdFx0fSxcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGlkOiAnc2VwYXJhdG9yX2RyYWdfYW5kX2Ryb3BfMScsXG5cdFx0XHRcdFx0YWN0aW9uX2dyb3VwOiAnZHJhZ19hbmRfZHJvcCcsXG5cdFx0XHRcdFx0bWVudV9hbGlnbjogJ3JpZ2h0Jyxcblx0XHRcdFx0XHRzZXBhcmF0b3I6IHRydWUsXG5cdFx0XHRcdFx0c29ydF9vcmRlcjogODA4MFxuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnRHJhZyAmIERyb3A6IE92ZXJ3cml0ZScgKSxcblx0XHRcdFx0XHRpZDogJ292ZXJyaWRlJyxcblx0XHRcdFx0XHRhY3Rpb25fZ3JvdXA6ICdkcmFnX2FuZF9kcm9wJyxcblx0XHRcdFx0XHRtdWx0aV9zZWxlY3RfZ3JvdXA6IDIsXG5cdFx0XHRcdFx0bWVudV9hbGlnbjogJ3JpZ2h0Jyxcblx0XHRcdFx0XHRncm91cDogJ2RyYWdfYW5kX2Ryb3AnLFxuXHRcdFx0XHRcdHBlcm1pc3Npb25fcmVzdWx0OiB0cnVlLFxuXHRcdFx0XHRcdHNvcnRfb3JkZXI6IDgwOTBcblx0XHRcdFx0fSxcblx0XHRcdCk7XG5cblx0XHRcdGlmICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMTUgKSB7XG5cdFx0XHRcdGNvbnRleHRfbWVudV9tb2RlbC5pbmNsdWRlLnVuc2hpZnQoXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnRHJhZyAmIERyb3A6IE5vdGlmeSBFbXBsb3llZScgKSxcblx0XHRcdFx0XHRcdGlkOiAnbm90aWZ5X3VzZXJfc2NoZWR1bGVfY2hhbmdlJyxcblx0XHRcdFx0XHRcdGFjdGlvbl9ncm91cDogJ2RyYWdfYW5kX2Ryb3AnLFxuXHRcdFx0XHRcdFx0bXVsdGlfc2VsZWN0X2dyb3VwOiAzLFxuXHRcdFx0XHRcdFx0bWVudV9hbGlnbjogJ3JpZ2h0Jyxcblx0XHRcdFx0XHRcdGdyb3VwOiAnZHJhZ19hbmRfZHJvcCcsXG5cdFx0XHRcdFx0XHRwZXJtaXNzaW9uX3Jlc3VsdDogdHJ1ZSxcblx0XHRcdFx0XHRcdHNvcnRfb3JkZXI6IDgxMDBcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHR9XG5cblx0XHR9XG5cblx0XHRpZiAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCAnc2NoZWR1bGUnLCAndmlldycgKSB8fCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggJ3NjaGVkdWxlJywgJ3ZpZXdfY2hpbGQnICkgKSB7XG5cdFx0XHRjb250ZXh0X21lbnVfbW9kZWwuaW5jbHVkZS5wdXNoKFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnR3JvdXAgLSBDb21iaW5lZCcgKSxcblx0XHRcdFx0XHRpZDogJ3BkZl9zY2hlZHVsZV9ncm91cF9jb21iaW5lZCcsXG5cdFx0XHRcdFx0YWN0aW9uX2dyb3VwOiAncHJpbnQnLFxuXHRcdFx0XHRcdG1lbnVfYWxpZ246ICdyaWdodCcsXG5cdFx0XHRcdFx0c29ydF9vcmRlcjogOTAyMCxcblx0XHRcdFx0fSxcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ0dyb3VwIC0gU2VwYXJhdGVkJyApLFxuXHRcdFx0XHRcdGlkOiAncGRmX3NjaGVkdWxlX2dyb3VwJyxcblx0XHRcdFx0XHRhY3Rpb25fZ3JvdXA6ICdwcmludCcsXG5cdFx0XHRcdFx0bWVudV9hbGlnbjogJ3JpZ2h0Jyxcblx0XHRcdFx0XHRzb3J0X29yZGVyOiA5MDIwLFxuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnR3JvdXAgLSBTZXBhcmF0ZWQgKFBhZ2UgQnJlYWtzKScgKSxcblx0XHRcdFx0XHRpZDogJ3BkZl9zY2hlZHVsZV9ncm91cF9wYWdlYnJlYWsnLFxuXHRcdFx0XHRcdGFjdGlvbl9ncm91cDogJ3ByaW50Jyxcblx0XHRcdFx0XHRtZW51X2FsaWduOiAncmlnaHQnLFxuXHRcdFx0XHRcdHNvcnRfb3JkZXI6IDkwMjAsXG5cdFx0XHRcdH1cblx0XHRcdCk7XG5cdFx0fVxuXG5cdFx0Y29udGV4dF9tZW51X21vZGVsLmluY2x1ZGUucHVzaChcblx0XHQpO1xuXG5cdFx0aWYgKCAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCAncHVuY2gnLCAnYWRkJyApICYmICggUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoICdwdW5jaCcsICdlZGl0JyApIHx8IFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCAncHVuY2gnLCAnZWRpdF9jaGlsZCcgKSApICkgKSB7XG5cdFx0XHRjb250ZXh0X21lbnVfbW9kZWwuaW5jbHVkZS5wdXNoKFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGFiZWw6ICcnLCAvL0VtcHR5IGxhYmVsLiB2dWVfaWNvbiBpcyBkaXNwbGF5ZWQgaW5zdGVhZCBvZiB0ZXh0LlxuXHRcdFx0XHRcdGlkOiAnb3RoZXJfaGVhZGVyJyxcblx0XHRcdFx0XHRhY3Rpb25fZ3JvdXA6ICdvdGhlcicsXG5cdFx0XHRcdFx0bWVudV9hbGlnbjogJ3JpZ2h0Jyxcblx0XHRcdFx0XHRhY3Rpb25fZ3JvdXBfaGVhZGVyOiB0cnVlLFxuXHRcdFx0XHRcdHZ1ZV9pY29uOiAndHRpY29uIHR0aWNvbi1tb3JlX3ZlcnRfYmxhY2tfMjRkcCcsXG5cdFx0XHRcdFx0c29ydF9vcmRlcjogOTA1MFxuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnQXV0byBQdW5jaCcgKSxcblx0XHRcdFx0XHRpZDogJ0F1dG9QdW5jaCcsXG5cdFx0XHRcdFx0YWN0aW9uX2dyb3VwOiAnb3RoZXInLFxuXHRcdFx0XHRcdG1lbnVfYWxpZ246ICdyaWdodCcsXG5cdFx0XHRcdFx0Z3JvdXA6ICdvdGhlcicsXG5cdFx0XHRcdFx0cGVybWlzc2lvbl9yZXN1bHQ6IHRydWUsXG5cdFx0XHRcdFx0cGVybWlzc2lvbjogdHJ1ZSxcblx0XHRcdFx0XHRzaG93X29uX3JpZ2h0X2NsaWNrOiB0cnVlLFxuXHRcdFx0XHRcdHNvcnRfb3JkZXI6IDkwNTBcblx0XHRcdFx0fSApO1xuXHRcdH1cblxuXHRcdHJldHVybiBjb250ZXh0X21lbnVfbW9kZWw7XG5cdH1cblxuXHRwYXJzZUN1c3RvbUNvbnRleHRNb2RlbEZvckVkaXRWaWV3cyggY29udGV4dF9tZW51X21vZGVsICkge1xuXG5cdFx0Y29udGV4dF9tZW51X21vZGVsID0gc3VwZXIucGFyc2VDdXN0b21Db250ZXh0TW9kZWxGb3JFZGl0Vmlld3MoIGNvbnRleHRfbWVudV9tb2RlbCApO1xuXG5cdFx0aWYgKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkubWVudV90eXBlID09PSAnZWRpdHZpZXdfY29udGV4dG1lbnUnICkge1xuXHRcdFx0Y29udGV4dF9tZW51X21vZGVsLmV4Y2x1ZGUucHVzaChcblx0XHRcdFx0J21vdmUnLFxuXHRcdFx0XHQnZHJhZ19jb3B5Jyxcblx0XHRcdFx0J3N3YXAnLFxuXHRcdFx0XHQnb3ZlcnJpZGUnLFxuXHRcdFx0XHQnbm90aWZ5X3VzZXJfc2NoZWR1bGVfY2hhbmdlJyxcblx0XHRcdFx0J3ByaW50Jyxcblx0XHRcdFx0J3BkZl9zY2hlZHVsZScsXG5cdFx0XHRcdCdwZGZfc2NoZWR1bGVfZ3JvdXBfY29tYmluZWQnLFxuXHRcdFx0XHQncGRmX3NjaGVkdWxlX2dyb3VwJyxcblx0XHRcdFx0J3BkZl9zY2hlZHVsZV9ncm91cF9wYWdlYnJlYWsnXG5cdFx0XHQpO1xuXHRcdH1cblxuXHRcdHJldHVybiBjb250ZXh0X21lbnVfbW9kZWw7XG5cdH1cblxuXHRvblJlcG9ydE1lbnVDbGljayggaWQgKSB7XG5cdFx0dGhpcy5vbk5hdmlnYXRpb25DbGljayggaWQgKTtcblx0fVxuXG5cdG9uQ3VzdG9tQ29udGV4dENsaWNrKCBpZCApIHtcblx0XHRzd2l0Y2ggKCBpZCApIHtcblx0XHRcdGNhc2UgJ21vdmUnOlxuXHRcdFx0Y2FzZSAnZHJhZ19jb3B5Jzpcblx0XHRcdGNhc2UgJ3N3YXAnOlxuXHRcdFx0XHR0aGlzLnNldE1vdmVPckRyb3BNb2RlKCBpZCApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ292ZXJyaWRlJzpcblx0XHRcdFx0dGhpcy5vbk92ZXJyaWRlQ2xpY2soKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdub3RpZnlfdXNlcl9zY2hlZHVsZV9jaGFuZ2UnOlxuXHRcdFx0XHR0aGlzLm9uTm90aWZ5VXNlclNjaGVkdWxlQ2hhbmdlQ2xpY2soKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdlZGl0X2VtcGxveWVlJzpcblx0XHRcdGNhc2UgJ3RpbWVzaGVldCc6XG5cdFx0XHRcdHRoaXMub25OYXZpZ2F0aW9uQ2xpY2soIGlkICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnZmluZF9hdmFpbGFibGUnOlxuXHRcdFx0XHR0aGlzLm9uRmluZEF2YWlsYWJsZUNsaWNrKCBpZCApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ0F1dG9QdW5jaCc6XG5cdFx0XHRcdHRoaXMuYWRkUHVuY2hlc0Zyb21TY2hlZHVsZWRTaGlmdHMoIGlkICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnQWRkUmVxdWVzdCc6XG5cdFx0XHRcdHRoaXMuYWRkUmVxdWVzdEZyb21TY2hlZHVsZWRTaGlmdHMoIGlkICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnaW1wb3J0X2ljb24nOlxuXHRcdFx0XHR0aGlzLm9uSW1wb3J0Q2xpY2soKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdwZGZfc2NoZWR1bGUnOlxuXHRcdFx0Y2FzZSAncGRmX3NjaGVkdWxlX2dyb3VwJzpcblx0XHRcdGNhc2UgJ3BkZl9zY2hlZHVsZV9ncm91cF9jb21iaW5lZCc6XG5cdFx0XHRjYXNlICdwZGZfc2NoZWR1bGVfZ3JvdXBfcGFnZWJyZWFrJzpcblx0XHRcdFx0dGhpcy5vblJlcG9ydE1lbnVDbGljayggaWQgKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0fVxuXHR9XG5cblx0YWRkUmVxdWVzdEZyb21TY2hlZHVsZWRTaGlmdHMoIGlkICkge1xuXHRcdGlmICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPD0gMTAgKSB7XG5cdFx0XHRUQWxlcnRNYW5hZ2VyLnNob3dBbGVydCggR2xvYmFsLmdldFVwZ3JhZGVNZXNzYWdlKCkgKTtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHRpZiAoIHNoaWZ0X2FycmF5ICYmIHNoaWZ0X2FycmF5Lmxlbmd0aCA8PSAwICkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdHZhciBzaGlmdF9hcnJheSA9IHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5O1xuXHRcdHZhciBmaXJzdF9zaGlmdCA9ICggc2hpZnRfYXJyYXlbMF0gKSA/IHNoaWZ0X2FycmF5WzBdIDogbnVsbDtcblx0XHR2YXIgbGFzdF9zaGlmdCA9ICggc2hpZnRfYXJyYXlbc2hpZnRfYXJyYXkubGVuZ3RoIC0gMV0gKSA/IHNoaWZ0X2FycmF5W3NoaWZ0X2FycmF5Lmxlbmd0aCAtIDFdIDogbnVsbDtcblx0XHRpZiAoICFmaXJzdF9zaGlmdCB8fCAhbGFzdF9zaGlmdCApIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHR2YXIgcmVxdWVzdCA9IHRoaXMuYXBpLmdldFNjaGVkdWxlRGVmYXVsdERhdGEoIHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5LCB7IGFzeW5jOiBmYWxzZSB9ICkuZ2V0UmVzdWx0KCk7XG5cdFx0dmFyIHNoaWZ0X3N0YXR1cyA9IDEwO1xuXHRcdHZhciB0eXBlX2lkID0gNDA7XG5cblx0XHR2YXIgbW9uID0gZmFsc2UsIHR1ZSA9IGZhbHNlLCB3ZWQgPSBmYWxzZSwgdGh1ID0gZmFsc2UsIGZyaSA9IGZhbHNlLCBzYXQgPSBmYWxzZSwgc3VuID0gZmFsc2U7XG5cblx0XHRmb3IgKCB2YXIgdyBpbiBzaGlmdF9hcnJheSApIHtcblx0XHRcdGlmICggZmlyc3Rfc2hpZnQuc2hpZnQgPT0gdW5kZWZpbmVkICYmIHNoaWZ0X2FycmF5W3ddLnNoaWZ0ICkge1xuXHRcdFx0XHQvL1NldCB0aGUgYXJjaGV0eXBlIHRvIHRoZSBmaXJzdCBkYXkgd2l0aCBhIHNoaWZ0LlxuXHRcdFx0XHRmaXJzdF9zaGlmdCA9IHNoaWZ0X2FycmF5W3ddO1xuXHRcdFx0fVxuXG5cdFx0XHQvL1NldCBzZWxlY3RlZCBkYXlzIG9mIHRoZSB3ZWVrLlxuXHRcdFx0dmFyIGQgPSBuZXcgRGF0ZSggc2hpZnRfYXJyYXlbd10udGltZV9zdGFtcF9udW0gKTtcblx0XHRcdHN3aXRjaCAoIGQuZ2V0RGF5KCkgKSB7XG5cdFx0XHRcdGNhc2UgMDpcblx0XHRcdFx0XHRzdW4gPSB0cnVlO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDE6XG5cdFx0XHRcdFx0bW9uID0gdHJ1ZTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAyOlxuXHRcdFx0XHRcdHR1ZSA9IHRydWU7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgMzpcblx0XHRcdFx0XHR3ZWQgPSB0cnVlO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDQ6XG5cdFx0XHRcdFx0dGh1ID0gdHJ1ZTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSA1OlxuXHRcdFx0XHRcdGZyaSA9IHRydWU7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgNjpcblx0XHRcdFx0XHRzYXQgPSB0cnVlO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBkZWxldGUgKCBkICk7ICMyNzkyIEluIHRoZSBuZXcgRVM2IGNvbnZlcnNpb24sIGRlbGV0ZSBpcyBjYXVzaW5nIGVycm9ycywgYnV0IHRlY2huaWNhbGx5IHNob3VsZCBuZXZlciBoYXZlIHdvcmtlZCBhbnl3YXkuIFBvdGVudGlhbGx5IG5ldmVyIGRpZCBhbnl0aGluZy4gQ291bGQgbWF5YmUgZGVsZXRlLiBUcnkgbnVsbCBmaXJzdC5cblx0XHRcdGQgPSBudWxsO1xuXHRcdH1cblxuXHRcdHJlcXVlc3QubW9uID0gbW9uO1xuXHRcdHJlcXVlc3QudHVlID0gdHVlO1xuXHRcdHJlcXVlc3Qud2VkID0gd2VkO1xuXHRcdHJlcXVlc3QudGh1ID0gdGh1O1xuXHRcdHJlcXVlc3QuZnJpID0gZnJpO1xuXHRcdHJlcXVlc3Quc2F0ID0gc2F0O1xuXHRcdHJlcXVlc3Quc3VuID0gc3VuO1xuXG5cdFx0aWYgKCBmaXJzdF9zaGlmdCAmJiBmaXJzdF9zaGlmdC5kYXRlICkge1xuXHRcdFx0dmFyIHN0YXJ0X2RhdGUgPSBmaXJzdF9zaGlmdC5kYXRlO1xuXHRcdH1cblxuXHRcdGlmICggbGFzdF9zaGlmdCAmJiBsYXN0X3NoaWZ0LmRhdGUgKSB7XG5cdFx0XHR2YXIgZW5kX2RhdGUgPSBsYXN0X3NoaWZ0LmRhdGU7XG5cdFx0fVxuXG5cdFx0aWYgKCBmaXJzdF9zaGlmdCApIHtcblx0XHRcdGlmICggZmlyc3Rfc2hpZnQuc2hpZnQgJiYgZmlyc3Rfc2hpZnQuc2hpZnQuc3RhdHVzX2lkID09IDEwICYmIGZpcnN0X3NoaWZ0LnNoaWZ0LnVzZXJfaWQgJiYgZmlyc3Rfc2hpZnQuc2hpZnQudXNlcl9pZCAhPSBUVFVVSUQuemVyb19pZCApIHtcblx0XHRcdFx0c2hpZnRfc3RhdHVzID0gMjA7XG5cdFx0XHRcdHR5cGVfaWQgPSAzMDtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXF1ZXN0LnN0YXR1c19pZCA9IHNoaWZ0X3N0YXR1cztcblx0XHRyZXF1ZXN0LnR5cGVfaWQgPSB0eXBlX2lkO1xuXHRcdHJlcXVlc3QudXNlcl9pZCA9IExvY2FsQ2FjaGVEYXRhLmdldExvZ2luVXNlcigpLmlkO1xuXHRcdHJlcXVlc3QuZnVsbF9uYW1lID0gTG9jYWxDYWNoZURhdGEuZ2V0TG9naW5Vc2VyKCkuZnVsbF9uYW1lO1xuXHRcdGlmICggc3RhcnRfZGF0ZSApIHtcblx0XHRcdHJlcXVlc3QuZGF0ZV9zdGFtcCA9IHN0YXJ0X2RhdGU7XG5cdFx0XHRyZXF1ZXN0LnN0YXJ0X2RhdGUgPSBzdGFydF9kYXRlO1xuXHRcdH1cblxuXHRcdGlmICggZW5kX2RhdGUgKSB7XG5cdFx0XHRyZXF1ZXN0LmVuZF9kYXRlID0gZW5kX2RhdGU7XG5cdFx0fVxuXG5cdFx0aWYgKCBmaXJzdF9zaGlmdC5zdGFydF90aW1lICkge1xuXHRcdFx0cmVxdWVzdC5zdGFydF90aW1lID0gZmlyc3Rfc2hpZnQuc3RhcnRfdGltZTtcblx0XHR9XG5cblx0XHRpZiAoIGZpcnN0X3NoaWZ0LmVuZF90aW1lICkge1xuXHRcdFx0cmVxdWVzdC5lbmRfdGltZSA9IGZpcnN0X3NoaWZ0LmVuZF90aW1lO1xuXHRcdH1cblxuXHRcdGlmICggZmlyc3Rfc2hpZnQuYnJhbmNoX2lkICkge1xuXHRcdFx0cmVxdWVzdC5icmFuY2hfaWQgPSBmaXJzdF9zaGlmdC5icmFuY2hfaWQ7XG5cdFx0fVxuXG5cdFx0aWYgKCBmaXJzdF9zaGlmdC5kZXBhcnRtZW50X2lkICkge1xuXHRcdFx0cmVxdWVzdC5kZXBhcnRtZW50X2lkID0gZmlyc3Rfc2hpZnQuZGVwYXJ0bWVudF9pZDtcblx0XHR9XG5cblx0XHRpZiAoIGZpcnN0X3NoaWZ0LmpvYl9pZCApIHtcblx0XHRcdHJlcXVlc3Quam9iX2lkID0gZmlyc3Rfc2hpZnQuam9iX2lkO1xuXHRcdH1cblxuXHRcdGlmICggZmlyc3Rfc2hpZnQuam9iX2l0ZW1faWQgKSB7XG5cdFx0XHRyZXF1ZXN0LmpvYl9pdGVtX2lkID0gZmlyc3Rfc2hpZnQuam9iX2l0ZW1faWQ7XG5cdFx0fVxuXG5cdFx0aWYgKCBmaXJzdF9zaGlmdC5wdW5jaF90YWdfaWQgKSB7XG5cdFx0XHRyZXF1ZXN0LnB1bmNoX3RhZ19pZCA9IGZpcnN0X3NoaWZ0LnB1bmNoX3RhZ19pZDtcblx0XHR9XG5cblx0XHRJbmRleFZpZXdDb250cm9sbGVyLm9wZW5FZGl0VmlldyggdGhpcywgJ1JlcXVlc3QnLCByZXF1ZXN0LCAnb3BlbkFkZFZpZXcnICk7XG5cdH1cblxuXHRhZGRQdW5jaGVzRnJvbVNjaGVkdWxlZFNoaWZ0cyggaWQgKSB7XG5cblx0XHRpZiAoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpIDw9IDEwICkge1xuXHRcdFx0VEFsZXJ0TWFuYWdlci5zaG93QWxlcnQoIEdsb2JhbC5nZXRVcGdyYWRlTWVzc2FnZSgpICk7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdGlmICggdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXkgPT0gdW5kZWZpbmVkIHx8IHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5Lmxlbmd0aCA8IDEgKSB7XG5cdFx0XHRUQWxlcnRNYW5hZ2VyLnNob3dBbGVydCggJ05vIHNjaGVkdWxlcyBzZWxlY3RlZC4gWW91IGNhblxcJ3QgYXV0b3B1bmNoIG5vIHNjaGVkdWxlcy4nICk7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0dmFyIHNoaWZ0X2FycmF5ID0gdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXk7XG5cdFx0dmFyIHNjaGVkdWxlcyA9IHt9O1xuXHRcdHZhciB1c2VycyA9IFtdO1xuXHRcdHNjaGVkdWxlcy5zY2hlZHVsZSA9IFtdO1xuXHRcdHNjaGVkdWxlcy5yZWN1cnJpbmcgPSBbXTtcblxuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IHNoaWZ0X2FycmF5Lmxlbmd0aDsgaSsrICkge1xuXHRcdFx0aWYgKCBzaGlmdF9hcnJheVtpXS5zaGlmdCAhPSB1bmRlZmluZWQgKSB7IC8vYXZvaWQgd2hlbiBubyB1c2VyIHNjaGVkdWxlZC5cblx0XHRcdFx0aWYgKCBzaGlmdF9hcnJheVtpXS5zaGlmdC5pZFxuXHRcdFx0XHRcdCYmIHNoaWZ0X2FycmF5W2ldLnNoaWZ0LmlkICE9IFRUVVVJRC56ZXJvX2lkXG5cdFx0XHRcdFx0JiYgc2hpZnRfYXJyYXlbaV0uc2hpZnQuaWQgIT0gVFRVVUlELm5vdF9leGlzdF9pZFxuXHRcdFx0XHQpIHtcblx0XHRcdFx0XHRzY2hlZHVsZXMuc2NoZWR1bGUucHVzaCggc2hpZnRfYXJyYXlbaV0uc2hpZnQuaWQgKTtcblx0XHRcdFx0fSBlbHNlIGlmICggc2hpZnRfYXJyYXlbaV0uc2hpZnQucmVjdXJyaW5nX3NjaGVkdWxlX2lkXG5cdFx0XHRcdFx0JiYgc2hpZnRfYXJyYXlbaV0uc2hpZnQucmVjdXJyaW5nX3NjaGVkdWxlX2lkICE9IFRUVVVJRC5ub3RfZXhpc3RfaWRcblx0XHRcdFx0KSB7XG5cdFx0XHRcdFx0c2NoZWR1bGVzLnJlY3VycmluZy5wdXNoKCBzaGlmdF9hcnJheVtpXS5zaGlmdC5yZWN1cnJpbmdfc2NoZWR1bGVfaWQgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHR1c2Vycy5wdXNoKCBzaGlmdF9hcnJheVtpXS5zaGlmdC51c2VyX2lkICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5hcGkuYWRkUHVuY2hlc0Zyb21TY2hlZHVsZWRTaGlmdHMoIHNjaGVkdWxlcywge1xuXHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cdFx0XHRcdGlmICggcmVzdWx0LmlzVmFsaWQoKSApIHtcblx0XHRcdFx0XHRVc2VyR2VuZXJpY1N0YXR1c1dpbmRvd0NvbnRyb2xsZXIub3BlbiggcmVzdWx0LmdldEF0dHJpYnV0ZUluQVBJRGV0YWlscyggJ3VzZXJfZ2VuZXJpY19zdGF0dXNfYmF0Y2hfaWQnICksIFtMb2NhbENhY2hlRGF0YS5nZXRMb2dpblVzZXIoKS5pZF0gKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRUQWxlcnRNYW5hZ2VyLnNob3dFcnJvckFsZXJ0KCByZXN1bHQgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0gKTtcblx0fVxuXG5cdGdldFNlbGVjdEVtcGxveWVlKCkge1xuXHRcdHZhciBzaGlmdCA9IHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5WzBdO1xuXG5cdFx0Ly9FcnJvcjogVW5jYXVnaHQgVHlwZUVycm9yOiBDYW5ub3QgcmVhZCBwcm9wZXJ0eSAndXNlcl9pZCcgb2YgdW5kZWZpbmVkIGluIC9pbnRlcmZhY2UvaHRtbDUvIyFtPVNjaGVkdWxlJmRhdGU9MjAxNDExMTcmbW9kZT13ZWVrJmE9bmV3JnRhYj1TY2hlZHVsZSBsaW5lIDExMTZcblx0XHRpZiAoICFzaGlmdCB8fCBzaGlmdC51c2VyX2lkID09IFRUVVVJRC56ZXJvX2lkICkge1xuXHRcdFx0c2hpZnQgPSB7IHVzZXJfaWQ6IExvY2FsQ2FjaGVEYXRhLmdldExvZ2luVXNlcigpLmlkIH07XG5cdFx0fSBlbHNlIGlmICggc2hpZnQudXNlcl9pZCAmJiBzaGlmdC51c2VyX2lkICE9IFRUVVVJRC56ZXJvX2lkICkge1xuXHRcdFx0c2hpZnQgPSB7IHVzZXJfaWQ6IHNoaWZ0LnVzZXJfaWQgfTtcblx0XHR9XG5cblx0XHRpZiAoIHRoaXMuZWRpdF92aWV3ICYmIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCApIHtcblx0XHRcdHNoaWZ0LnVzZXJfaWQgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudXNlcl9pZDtcblx0XHR9XG5cblx0XHRyZXR1cm4gc2hpZnQudXNlcl9pZDtcblx0fVxuXG5cdG9uRmluZEF2YWlsYWJsZUNsaWNrKCkge1xuXHRcdGlmICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPD0gMTAgKSB7XG5cdFx0XHRUQWxlcnRNYW5hZ2VyLnNob3dBbGVydCggR2xvYmFsLmdldFVwZ3JhZGVNZXNzYWdlKCkgKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciBhcmdzID0ge307XG5cdFx0YXJncy5zZWxlY3RlZCA9IFtdO1xuXHRcdHZhciBsZW4gPSB0aGlzLnNlbGVjdF9hbGxfc2hpZnRzX2FycmF5Lmxlbmd0aDtcblx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdHZhciBpdGVtID0gdGhpcy5zZWxlY3RfYWxsX3NoaWZ0c19hcnJheVtpXTtcblx0XHRcdGFyZ3Muc2VsZWN0ZWQucHVzaCggaXRlbSApO1xuXHRcdH1cblxuXHRcdExvY2FsQ2FjaGVEYXRhLmV4dHJhX2ZpbHRlcl9mb3JfbmV4dF9vcGVuX3ZpZXcgPSB7fTtcblx0XHRMb2NhbENhY2hlRGF0YS5leHRyYV9maWx0ZXJfZm9yX25leHRfb3Blbl92aWV3LmZpbHRlcl9kYXRhID0gYXJncztcblxuXHRcdEluZGV4Vmlld0NvbnRyb2xsZXIub3BlbldpemFyZCggJ0ZpbmRBdmFpbGFibGVXaXphcmQnLCBudWxsLCBmdW5jdGlvbiggZW1wbG95ZWVfaWQsIG5vdGlmeV91c2VycyApIHtcblx0XHRcdCR0aGlzLm9uRmluZEF2YWlsYWJsZUNsb3NlKCBlbXBsb3llZV9pZCwgYXJncy5zZWxlY3RlZCwgbm90aWZ5X3VzZXJzICk7XG5cdFx0fSApO1xuXHR9XG5cblx0b25GaW5kQXZhaWxhYmxlQ2xvc2UoIGVtcGxveWVlX2lkLCBzaGlmdF9hcnJheSwgbm90aWZ5X3VzZXJzICkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dmFyIGxlbiA9IHNoaWZ0X2FycmF5Lmxlbmd0aDtcblx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdHZhciBpdGVtID0gc2hpZnRfYXJyYXlbaV07XG5cdFx0XHRpdGVtLnVzZXJfaWQgPSBlbXBsb3llZV9pZDtcblx0XHRcdGl0ZW0ucmVwbGFjZWRfaWQgPSBpdGVtLmlkO1xuXHRcdFx0aXRlbS5ub3RpZnlfdXNlcl9zY2hlZHVsZV9jaGFuZ2UgPSBub3RpZnlfdXNlcnM7XG5cdFx0XHRkZWxldGUgaXRlbS5pZDtcblx0XHR9XG5cblx0XHR0aGlzLmFwaS5zZXRTY2hlZHVsZSggc2hpZnRfYXJyYXksIHtcblx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHRpZiAoICFyZXN1bHQuaXNWYWxpZCgpICkge1xuXHRcdFx0XHRcdFRBbGVydE1hbmFnZXIuc2hvd0Vycm9yQWxlcnQoIHJlc3VsdCApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdCR0aGlzLnNlYXJjaCgpO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fVxuXG5cdG9uSW1wb3J0Q2xpY2soKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHRJbmRleFZpZXdDb250cm9sbGVyLm9wZW5XaXphcmQoICdJbXBvcnRDU1ZXaXphcmQnLCAnU2NoZWR1bGUnLCBmdW5jdGlvbigpIHtcblx0XHRcdCR0aGlzLnNlYXJjaCgpO1xuXHRcdH0gKTtcblx0fVxuXG5cdG9uTmF2aWdhdGlvbkNsaWNrKCBpY29uTmFtZSApIHtcblxuXHRcdGlmICggIXRoaXMuY2hlY2tTY2hlZHVsZURhdGEoKSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgcG9zdF9kYXRhO1xuXG5cdFx0c3dpdGNoICggaWNvbk5hbWUgKSB7XG5cdFx0XHRjYXNlICdlZGl0X2VtcGxveWVlJzpcblx0XHRcdFx0SW5kZXhWaWV3Q29udHJvbGxlci5vcGVuRWRpdFZpZXcoIHRoaXMsICdFbXBsb3llZScsIHRoaXMuZ2V0U2VsZWN0RW1wbG95ZWUoKSApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3RpbWVzaGVldCc6XG5cdFx0XHRcdHZhciBmaWx0ZXIgPSB7IGZpbHRlcl9kYXRhOiB7fSB9O1xuXHRcdFx0XHRmaWx0ZXIudXNlcl9pZCA9IHRoaXMuZ2V0U2VsZWN0RW1wbG95ZWUoKTtcblxuXHRcdFx0XHRpZiAoIHRoaXMuZWRpdF92aWV3ICkge1xuXHRcdFx0XHRcdGZpbHRlci5iYXNlX2RhdGUgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuZGF0ZV9zdGFtcDtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRmaWx0ZXIuYmFzZV9kYXRlID0gdGhpcy5zdGFydF9kYXRlX3BpY2tlci5nZXRWYWx1ZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdEdsb2JhbC5hZGRWaWV3VGFiKCB0aGlzLnZpZXdJZCwgJC5pMThuLl8oICdTY2hlZHVsZXMnICksIHdpbmRvdy5sb2NhdGlvbi5ocmVmICk7XG5cdFx0XHRcdEluZGV4Vmlld0NvbnRyb2xsZXIuZ29Ub1ZpZXcoICdUaW1lU2hlZXQnLCBmaWx0ZXIgKTtcblxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3BkZl9zY2hlZHVsZSc6XG5cdFx0XHRjYXNlICdwZGZfc2NoZWR1bGVfZ3JvdXBfY29tYmluZWQnOlxuXHRcdFx0Y2FzZSAncGRmX3NjaGVkdWxlX2dyb3VwJzpcblx0XHRcdGNhc2UgJ3BkZl9zY2hlZHVsZV9ncm91cF9wYWdlYnJlYWsnOlxuXHRcdFx0XHRmaWx0ZXIgPSBHbG9iYWwuY29udmVydExheW91dEZpbHRlclRvQVBJRmlsdGVyKCB0aGlzLnNlbGVjdF9sYXlvdXQgKTtcblxuXHRcdFx0XHRpZiAoICFmaWx0ZXIgKSB7XG5cdFx0XHRcdFx0ZmlsdGVyID0ge307XG5cdFx0XHRcdH1cblx0XHRcdFx0ZmlsdGVyLnRpbWVfcGVyaW9kID0ge307XG5cdFx0XHRcdGZpbHRlci50aW1lX3BlcmlvZC50aW1lX3BlcmlvZCA9ICdjdXN0b21fZGF0ZSc7XG5cdFx0XHRcdGZpbHRlci50aW1lX3BlcmlvZC5zdGFydF9kYXRlID0gdGhpcy5mdWxsX3NjaGVkdWxlX2RhdGEuc2NoZWR1bGVfZGF0ZXMuc3RhcnRfZGlzcGxheV9kYXRlO1xuXHRcdFx0XHRmaWx0ZXIudGltZV9wZXJpb2QuZW5kX2RhdGUgPSB0aGlzLmZ1bGxfc2NoZWR1bGVfZGF0YS5zY2hlZHVsZV9kYXRlcy5lbmRfZGlzcGxheV9kYXRlO1xuXG5cdFx0XHRcdGlmICggZmlsdGVyLnRpbWVfcGVyaW9kLnN0YXJ0X2RhdGUgPT0gZmlsdGVyLnRpbWVfcGVyaW9kLmVuZF9kYXRlICkge1xuXHRcdFx0XHRcdHZhciBuZXdfZW5kX2RhdGUgPSBuZXcgRGF0ZSggbmV3IERhdGUoIHRoaXMuc3RhcnRfZGF0ZS5nZXRUaW1lKCkgKS5zZXREYXRlKCB0aGlzLnN0YXJ0X2RhdGUuZ2V0RGF0ZSgpICsgNiApICk7XG5cdFx0XHRcdFx0ZmlsdGVyLnRpbWVfcGVyaW9kLmVuZF9kYXRlID0gbmV3X2VuZF9kYXRlLmZvcm1hdCgpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0cG9zdF9kYXRhID0geyAwOiBmaWx0ZXIsIDE6IGljb25OYW1lIH07XG5cdFx0XHRcdHRoaXMuZG9Gb3JtSUZyYW1lQ2FsbCggcG9zdF9kYXRhICk7XG5cdFx0XHRcdGJyZWFrO1xuXG5cdFx0fVxuXHR9XG5cblx0ZG9Gb3JtSUZyYW1lQ2FsbCggcG9zdERhdGEgKSB7XG5cdFx0R2xvYmFsLkFQSUZpbGVEb3dubG9hZCggJ0FQSVNjaGVkdWxlU3VtbWFyeVJlcG9ydCcsICdnZXRTY2hlZHVsZVN1bW1hcnlSZXBvcnQnLCBwb3N0RGF0YSApO1xuXHR9XG5cblx0c2V0U2NoZWR1bGVHcmlkRHJhZ0FibGUoKSB7XG5cdFx0dmFyIG1vZGUgPSB0aGlzLmdldE1vZGUoKTtcblxuXHRcdHN3aXRjaCAoIG1vZGUgKSB7XG5cdFx0XHRjYXNlIFNjaGVkdWxlVmlld0NvbnRyb2xsZXJNb2RlLkRBWTpcblx0XHRcdFx0dGhpcy5zZXRXZWVrTW9kZURyYWdBYmxlKCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5XRUVLOlxuXHRcdFx0XHR0aGlzLnNldFdlZWtNb2RlRHJhZ0FibGUoKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIFNjaGVkdWxlVmlld0NvbnRyb2xsZXJNb2RlLk1PTlRIOlxuXHRcdFx0XHR0aGlzLnNldFdlZWtNb2RlRHJhZ0FibGUoKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIFNjaGVkdWxlVmlld0NvbnRyb2xsZXJNb2RlLllFQVI6XG5cdFx0XHRcdHRoaXMuc2V0V2Vla01vZGVEcmFnQWJsZSgpO1xuXHRcdFx0XHRicmVhaztcblx0XHR9XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdC8vc2V0IGJvdHRvbSBkcmFnIHRvIHNjcm9sbCBhcmVhXG5cdFx0JCggJy5zY2hlZHVsZS1ncmlkLWRpdicgKS5vZmYoICdkcmFnb3ZlcicgKS5vbiggJ2RyYWdvdmVyJywgZnVuY3Rpb24oIGUgKSB7XG5cblx0XHRcdHZhciBncmlkX2RpdiA9ICQoICcuc2NoZWR1bGUtZ3JpZC1kaXYnICk7XG5cdFx0XHR2YXIgZ3JpZF9wb3MgPSBncmlkX2Rpdi5vZmZzZXQoKS50b3A7XG5cblx0XHRcdHZhciBtb3VzZV95ID0gZS5vcmlnaW5hbEV2ZW50LmNsaWVudFk7XG5cdFx0XHR2YXIgZ3JpZF9oZWlnaHQgPSBncmlkX2Rpdi5oZWlnaHQoKTtcblxuXHRcdFx0aWYgKCBtb3VzZV95ID4gKCBncmlkX3BvcyArIGdyaWRfaGVpZ2h0ICkgKSB7XG5cdFx0XHRcdCR0aGlzLnNjcm9sbF91bml0ID0gbW91c2VfeSAtICggZ3JpZF9wb3MgKyBncmlkX2hlaWdodCApO1xuXHRcdFx0XHRpZiAoICEkdGhpcy5zY3JvbGxfaW50ZXJ2YWwgKSB7XG5cdFx0XHRcdFx0JHRoaXMuc2Nyb2xsX2ludGVydmFsID0gc2V0SW50ZXJ2YWwoIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0dmFyIGRpdiA9ICR0aGlzLmdyaWQuZ3JpZC5wYXJlbnQoKS5wYXJlbnQoKTtcblx0XHRcdFx0XHRcdGRpdi5zY3JvbGxUb3AoIGRpdi5zY3JvbGxUb3AoKSArICR0aGlzLnNjcm9sbF91bml0ICk7XG5cdFx0XHRcdFx0fSwgNTAgKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmICggbW91c2VfeSA8ICggZ3JpZF9wb3MgKyAxNSApICYmIG1vdXNlX3kgPiAoIGdyaWRfcG9zIC0gNTAgKSApIHtcblx0XHRcdFx0JHRoaXMuc2Nyb2xsX3VuaXQgPSAoIGdyaWRfcG9zICsgMTUgKSAtIG1vdXNlX3k7XG5cdFx0XHRcdGlmICggISR0aGlzLnNjcm9sbF9pbnRlcnZhbCApIHtcblx0XHRcdFx0XHQkdGhpcy5zY3JvbGxfaW50ZXJ2YWwgPSBzZXRJbnRlcnZhbCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHR2YXIgZGl2ID0gJHRoaXMuZ3JpZC5ncmlkLnBhcmVudCgpLnBhcmVudCgpO1xuXHRcdFx0XHRcdFx0ZGl2LnNjcm9sbFRvcCggZGl2LnNjcm9sbFRvcCgpIC0gJHRoaXMuc2Nyb2xsX3VuaXQgKTtcblx0XHRcdFx0XHR9LCA1MCApO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRjbGVhckludGVydmFsKCAkdGhpcy5zY3JvbGxfaW50ZXJ2YWwgKTtcblx0XHRcdFx0JHRoaXMuc2Nyb2xsX2ludGVydmFsID0gbnVsbDtcblx0XHRcdH1cblxuXHRcdH0gKTtcblxuXHRcdCQoICcuc2NoZWR1bGUtZ3JpZC1kaXYnICkub2ZmKCAnZHJhZ2VuZCcgKS5vbiggJ2RyYWdlbmQnLCBmdW5jdGlvbiggZSApIHtcblxuXHRcdFx0aWYgKCAkdGhpcy5zY3JvbGxfaW50ZXJ2YWwgKSB7XG5cdFx0XHRcdGNsZWFySW50ZXJ2YWwoICR0aGlzLnNjcm9sbF9pbnRlcnZhbCApO1xuXHRcdFx0XHQkdGhpcy5zY3JvbGxfaW50ZXJ2YWwgPSBudWxsO1xuXHRcdFx0fVxuXG5cdFx0fSApO1xuXG5cdFx0JCggJy5zY2hlZHVsZS1ncmlkLWRpdiB0ZCcgKS51bmJpbmQoICdkcmFnZW50ZXInICkuYmluZCggJ2RyYWdlbnRlcicsIGZ1bmN0aW9uKCBldmVudCApIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHQkKCAnLnNjaGVkdWxlLWRyYWctb3ZlcicgKS5yZW1vdmVDbGFzcyggJ3NjaGVkdWxlLWRyYWctb3ZlcicgKTtcblxuXHRcdFx0aWYgKCAkKCB0aGlzICkuYXR0ciggJ2RyYWdnYWJsZScgKSB8fCAkKCB0aGlzICkucGFyZW50cyggJ3RkJyApLmF0dHIoICdkcmFnZ2FibGUnICkgKSB7XG5cdFx0XHRcdCQoIHRoaXMgKS5hZGRDbGFzcyggJ3NjaGVkdWxlLWRyYWctb3ZlcicgKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cblxuXHRzZXRXZWVrTW9kZURyYWdBYmxlKCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dmFyIHBvc2l0aW9uID0gMDtcblxuXHRcdHZhciBjZWxscyA9IHRoaXMuZ3JpZC5ncmlkLmZpbmQoICcuZGF0ZS1jb2x1bW4nICkucGFyZW50cyggJ3RkJyApO1xuXG5cdFx0Y2VsbHMuYXR0ciggJ2RyYWdnYWJsZScsIHRydWUgKTtcblxuXHRcdGNlbGxzLnVuYmluZCggJ2RyYWdzdGFydCcgKS5iaW5kKCAnZHJhZ3N0YXJ0JywgZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0dmFyIHRkID0gZXZlbnQudGFyZ2V0O1xuXHRcdFx0aWYgKCAkdGhpcy5zZWxlY3RfYWxsX3NoaWZ0c19hcnJheS5sZW5ndGggPCAxIHx8ICEkKCB0ZCApLmhhc0NsYXNzKCAndWktc3RhdGUtaGlnaGxpZ2h0JyApIHx8ICEkdGhpcy5zZWxlY3RfZHJhZ19tZW51X2lkICkge1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cblx0XHRcdHZhciBjb250YWluZXIgPSAkKCAnPGRpdiBjbGFzcz1cXCdkcmFnLWhvbGRlci1kaXZcXCc+PC9kaXY+JyApO1xuXG5cdFx0XHR2YXIgbGVuID0gJHRoaXMuc2VsZWN0X2FsbF9zaGlmdHNfYXJyYXkubGVuZ3RoO1xuXG5cdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdFx0dmFyIHNoaWZ0ID0gJHRoaXMuc2VsZWN0X2FsbF9zaGlmdHNfYXJyYXlbaV07XG5cdFx0XHRcdHZhciBzcGFuID0gJCggJzxzcGFuIGNsYXNzPVxcJ2RyYWctc3BhblxcJz48L3NwYW4+JyApO1xuXG5cdFx0XHRcdGlmICggc2hpZnQuc3RhdHVzX2lkID09IDIwICkge1xuXHRcdFx0XHRcdHNwYW4udGV4dCggJHRoaXMuZ2V0QWJzZW5jZUNlbGxWYWx1ZSggc2hpZnQgKSApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHNwYW4udGV4dCggc2hpZnQuc3RhcnRfdGltZSArICcgLSAnICsgc2hpZnQuZW5kX3RpbWUgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGNvbnRhaW5lci5hcHBlbmQoIHNwYW4gKTtcblx0XHRcdH1cblxuXHRcdFx0JCggJ2JvZHknICkuZmluZCggJy5kcmFnLWhvbGRlci1kaXYnICkucmVtb3ZlKCk7XG5cblx0XHRcdCQoICdib2R5JyApLmFwcGVuZCggY29udGFpbmVyICk7XG5cblx0XHRcdGV2ZW50Lm9yaWdpbmFsRXZlbnQuZGF0YVRyYW5zZmVyLnNldERhdGEoICdUZXh0JywgJ3NjaGVkdWxlJyApOy8vSlVTVCBFTEVNRU5UIHJlZmVyZW5jZXMgaXMgb2sgaGVyZSBOTyBJRFxuXG5cdFx0XHRpZiAoIGV2ZW50Lm9yaWdpbmFsRXZlbnQuZGF0YVRyYW5zZmVyLnNldERyYWdJbWFnZSApIHtcblx0XHRcdFx0ZXZlbnQub3JpZ2luYWxFdmVudC5kYXRhVHJhbnNmZXIuc2V0RHJhZ0ltYWdlKCBjb250YWluZXJbMF0sIDAsIDAgKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fSApO1xuXG5cdFx0Y2VsbHMudW5iaW5kKCAnZHJvcCcgKS5iaW5kKCAnZHJvcCcsIGZ1bmN0aW9uKCBldmVudCApIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRpZiAoIGV2ZW50LnN0b3BQcm9wYWdhdGlvbiApIHtcblx0XHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7IC8vIHN0b3BzIHRoZSBicm93c2VyIGZyb20gcmVkaXJlY3RpbmcuXG5cdFx0XHR9XG5cblx0XHRcdCQoICcuZHJhZy1ob2xkZXItZGl2JyApLnJlbW92ZSgpO1xuXG5cdFx0XHR2YXIgdGFyZ2V0X2VtcHR5X3JvdyA9IGZhbHNlO1xuXHRcdFx0dmFyIGRlbGV0ZV9vbGRfaXRlbXMgPSBmYWxzZTtcblxuXHRcdFx0dmFyIG5ld19zaGlmdHNfYXJyYXkgPSBbXTtcblx0XHRcdHZhciBkZWxldGVfc2hpZnRzX2FycmF5ID0gW107XG5cdFx0XHR2YXIgcmVjdXJyaW5nX2RlbGV0ZV9zaGlmdHNfYXJyYXkgPSBbXTtcblxuXHRcdFx0dmFyIHRhcmdldF9jZWxsID0gZXZlbnQuY3VycmVudFRhcmdldDtcblxuXHRcdFx0dmFyIHNlbGVjdGVkX3NoaWZ0cyA9ICR0aGlzLnNlbGVjdF9jZWxsbHNfYW5kX3NoaWZ0c19hcnJheTtcblx0XHRcdC8vRXJyb3I6IFVuY2F1Z2h0IFR5cGVFcnJvcjogQ2Fubm90IHJlYWQgcHJvcGVydHkgJ2xlbmd0aCcgb2YgdW5kZWZpbmVkIGluIGludGVyZmFjZS9odG1sNS8jIW09U2NoZWR1bGUmZGF0ZT0yMDE1MTIxMyZtb2RlPXdlZWsgbGluZSAxNDIwXG5cdFx0XHRpZiAoICFzZWxlY3RlZF9zaGlmdHMgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHRcdHZhciBmaXJzdF90YXJnZXRfcm93X2luZGV4O1xuXHRcdFx0dmFyIGZpcnN0X3RhcmdldF9jZWxsX2luZGV4O1xuXG5cdFx0XHRmaXJzdF90YXJnZXRfcm93X2luZGV4ID0gdGFyZ2V0X2NlbGwucGFyZW50Tm9kZS5yb3dJbmRleCAtIDE7XG5cdFx0XHRmaXJzdF90YXJnZXRfY2VsbF9pbmRleCA9IHRhcmdldF9jZWxsLmNlbGxJbmRleDtcblxuXHRcdFx0dmFyIHJvd19pbmRleF9vZmZzZXQgPSAwO1xuXHRcdFx0dmFyIGNlbGxfaW5kZXhfb2Zmc2V0ID0gMDtcblxuXHRcdFx0dmFyIGZpcnN0X3NlbGVjdGVkX3Jvd19pbmRleDtcblx0XHRcdHZhciBmaXJzdF9zZWxlY3RlZF9jZWxsX2luZGV4O1xuXG5cdFx0XHR2YXIgY29sTW9kZWwgPSAkdGhpcy5ncmlkLmdyaWQuZ2V0R3JpZFBhcmFtKCAnY29sTW9kZWwnICk7XG5cblx0XHRcdGlmICggJHRoaXMuc2VsZWN0X2RyYWdfbWVudV9pZCA9PT0gJ21vdmUnICkge1xuXHRcdFx0XHRkZWxldGVfb2xkX2l0ZW1zID0gdHJ1ZTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGRlbGV0ZV9vbGRfaXRlbXMgPSBmYWxzZTtcblx0XHRcdH1cblxuXHRcdFx0dmFyIGxlbiA9IHNlbGVjdGVkX3NoaWZ0cy5sZW5ndGg7XG5cblx0XHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0XHR2YXIgY2VsbCA9IHNlbGVjdGVkX3NoaWZ0c1tpXTtcblx0XHRcdFx0dmFyIHNoaWZ0O1xuXG5cdFx0XHRcdGlmICggaSA9PT0gMCApIHtcblx0XHRcdFx0XHRmaXJzdF9zZWxlY3RlZF9yb3dfaW5kZXggPSBjZWxsLnJvd19pZDtcblx0XHRcdFx0XHRmaXJzdF9zZWxlY3RlZF9jZWxsX2luZGV4ID0gY2VsbC5jZWxsX2luZGV4O1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGlmICggIXRhcmdldF9lbXB0eV9yb3cgKSB7XG5cdFx0XHRcdFx0XHRyb3dfaW5kZXhfb2Zmc2V0ID0gY2VsbC5yb3dfaWQgLSBmaXJzdF9zZWxlY3RlZF9yb3dfaW5kZXg7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGNlbGxfaW5kZXhfb2Zmc2V0ID0gY2VsbC5jZWxsX2luZGV4IC0gZmlyc3Rfc2VsZWN0ZWRfY2VsbF9pbmRleDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggY2VsbC5zaGlmdCApIHtcblx0XHRcdFx0XHRzaGlmdCA9IGNlbGwuc2hpZnQ7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0dmFyIHRhcmdldF9yb3dfaW5kZXggPSBmaXJzdF90YXJnZXRfcm93X2luZGV4ICsgcm93X2luZGV4X29mZnNldDtcblx0XHRcdFx0XHR2YXIgdGFyZ2V0X2NlbGxfaW5kZXggPSBmaXJzdF90YXJnZXRfY2VsbF9pbmRleCArIGNlbGxfaW5kZXhfb2Zmc2V0O1xuXHRcdFx0XHRcdGlmICggdGFyZ2V0X2NlbGxfaW5kZXggPiBjb2xNb2RlbC5sZW5ndGggLSAxICkge1xuXHRcdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHZhciB0YXJnZXRfZGF0YSA9ICR0aGlzLmdldERhdGFCeUNlbGxJbmRleCggdGFyZ2V0X3Jvd19pbmRleCwgdGFyZ2V0X2NlbGxfaW5kZXggKTtcblx0XHRcdFx0XHR2YXIgdGFyZ2V0X3JvdyA9ICR0aGlzLnNjaGVkdWxlX3NvdXJjZVt0YXJnZXRfcm93X2luZGV4XTtcblxuXHRcdFx0XHRcdGlmICggIXRhcmdldF9yb3cgfHwgIXRhcmdldF9yb3cudXNlcl9pZCApIHtcblx0XHRcdFx0XHRcdHRhcmdldF9lbXB0eV9yb3cgPSB0cnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHNoaWZ0LmJyYW5jaF9pZCA9IHNoaWZ0LmJyYW5jaCA/IHNoaWZ0LmJyYW5jaF9pZCA6ICcnO1xuXHRcdFx0XHRzaGlmdC5kZXBhcnRtZW50X2lkID0gc2hpZnQuZGVwYXJ0bWVudCA/IHNoaWZ0LmRlcGFydG1lbnRfaWQgOiAnJztcblx0XHRcdFx0c2hpZnQuam9iX2lkID0gc2hpZnQuam9iX2lkID8gc2hpZnQuam9iX2lkIDogJyc7XG5cdFx0XHRcdHNoaWZ0LmpvYl9pdGVtX2lkID0gc2hpZnQuam9iX2l0ZW1faWQgPyBzaGlmdC5qb2JfaXRlbV9pZCA6ICcnO1xuXHRcdFx0XHRzaGlmdC5wdW5jaF90YWdfaWQgPSBzaGlmdC5wdW5jaF90YWdfaWQgPyBzaGlmdC5wdW5jaF90YWdfaWQgOiAnJztcblxuXHRcdFx0XHR0YXJnZXRfcm93X2luZGV4ID0gZmlyc3RfdGFyZ2V0X3Jvd19pbmRleCArIHJvd19pbmRleF9vZmZzZXQ7XG5cdFx0XHRcdHRhcmdldF9jZWxsX2luZGV4ID0gZmlyc3RfdGFyZ2V0X2NlbGxfaW5kZXggKyBjZWxsX2luZGV4X29mZnNldDtcblxuXHRcdFx0XHRpZiAoIHRhcmdldF9jZWxsX2luZGV4ID4gY29sTW9kZWwubGVuZ3RoIC0gMSApIHtcblx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRhcmdldF9kYXRhID0gJHRoaXMuZ2V0RGF0YUJ5Q2VsbEluZGV4KCB0YXJnZXRfcm93X2luZGV4LCB0YXJnZXRfY2VsbF9pbmRleCApO1xuXHRcdFx0XHR0YXJnZXRfcm93ID0gJHRoaXMuc2NoZWR1bGVfc291cmNlW3RhcmdldF9yb3dfaW5kZXhdO1xuXG5cdFx0XHRcdGlmICggIXRhcmdldF9yb3cgfHwgIXRhcmdldF9yb3cudXNlcl9pZCApIHtcblx0XHRcdFx0XHR0YXJnZXRfZW1wdHlfcm93ID0gdHJ1ZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggdGFyZ2V0X3JvdyApIHtcblx0XHRcdFx0XHRpZiAoIHRhcmdldF9yb3cudHlwZSA9PT0gU2NoZWR1bGVWaWV3Q29udHJvbGxlclJvd1R5cGUuREFURSApIHtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICggIXRhcmdldF9kYXRhIHx8IHRhcmdldF9lbXB0eV9yb3cgKSB7XG5cdFx0XHRcdFx0XHR2YXIgZGF0ZV9zdGFtcDtcblxuXHRcdFx0XHRcdFx0Ly9FcnJvcjogVHlwZUVycm9yOiBjb2xNb2RlbFt0YXJnZXRfY2VsbF9pbmRleF0gaXMgdW5kZWZpbmVkIGluIC9pbnRlcmZhY2UvaHRtbDUvZnJhbWV3b3JrL2pxdWVyeS5taW4uanM/dj04LjAuMC0yMDE0MTIzMC0xNTMyMTAgbGluZSAyID4gZXZhbCBsaW5lIDE0NDNcblx0XHRcdFx0XHRcdGlmICggY29sTW9kZWwgKSB7XG5cdFx0XHRcdFx0XHRcdGlmICggJHRoaXMuZ2V0TW9kZSgpID09PSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5NT05USCApIHtcblx0XHRcdFx0XHRcdFx0XHQvL0Vycm9yOiBcIlR5cGVFcnJvcjogQ2Fubm90IHJlYWQgcHJvcGVydHkgJ2Zvcm1hdCcgb2YgbnVsbFwiXG5cdFx0XHRcdFx0XHRcdFx0Ly8gd2hlbiB1c2VyIGRyYWdzIGEgc2NlZHVsZSB0byBhIG5vbi1kYXRlIGdyaWQgZWxlbWVudCB3ZSBuZWVkIHRvIHF1aWV0bHkgZmFpbFxuXHRcdFx0XHRcdFx0XHRcdHZhciByZWxhdGVkX2RhdGUgPSAkdGhpcy5nZXRDZWxsUmVsYXRlZERhdGUoIHRhcmdldF9yb3dfaW5kZXgsIGNvbE1vZGVsLCB0YXJnZXRfY2VsbF9pbmRleCwgY29sTW9kZWxbdGFyZ2V0X2NlbGxfaW5kZXhdLm5hbWUgKTtcblx0XHRcdFx0XHRcdFx0XHRpZiAoIHJlbGF0ZWRfZGF0ZSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdGRhdGVfc3RhbXAgPSByZWxhdGVkX2RhdGUuZm9ybWF0KCk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdGRhdGVfc3RhbXAgPSBHbG9iYWwuc3RyVG9EYXRlKCBjb2xNb2RlbFt0YXJnZXRfY2VsbF9pbmRleF0ubmFtZSwgJHRoaXMuZnVsbF9mb3JtYXQgKS5mb3JtYXQoKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRpZiAoICFkYXRlX3N0YW1wIHx8IGRhdGVfc3RhbXAgPT0gJ0ludmFsaWQgZGF0ZScgKSB7XG5cdFx0XHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0dGFyZ2V0X2RhdGEgPSB7fTtcblxuXHRcdFx0XHRcdFx0aWYgKCAhdGFyZ2V0X3Jvdy51c2VyX2lkICkgeyAvL09ubHkgaGFwcGVucyBpbiBtb250aCBtb2RlO1xuXHRcdFx0XHRcdFx0XHR0YXJnZXRfZGF0YSA9IHNoaWZ0O1xuXHRcdFx0XHRcdFx0XHR0YXJnZXRfZGF0YS5kYXRlX3N0YW1wID0gZGF0ZV9zdGFtcDtcblx0XHRcdFx0XHRcdFx0dGFyZ2V0X2RhdGEuc3RhcnRfZGF0ZV9zdGFtcCA9IGRhdGVfc3RhbXA7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHR0YXJnZXRfZGF0YS51c2VyX2lkID0gdGFyZ2V0X3Jvdy51c2VyX2lkO1xuXHRcdFx0XHRcdFx0XHR0YXJnZXRfZGF0YS5icmFuY2ggPSB0YXJnZXRfcm93LmJyYW5jaDtcblx0XHRcdFx0XHRcdFx0dGFyZ2V0X2RhdGEuYnJhbmNoX2lkID0gdGFyZ2V0X3Jvdy5icmFuY2ggPyB0YXJnZXRfcm93LmJyYW5jaF9pZCA6ICcnO1xuXHRcdFx0XHRcdFx0XHR0YXJnZXRfZGF0YS5zY2hlZHVsZV9wb2xpY3lfaWQgPSB0YXJnZXRfcm93LnNjaGVkdWxlX3BvbGljeV9pZDtcblx0XHRcdFx0XHRcdFx0dGFyZ2V0X2RhdGEuZGVwYXJ0bWVudF9pZCA9IHRhcmdldF9yb3cuZGVwYXJ0bWVudCA/IHRhcmdldF9yb3cuZGVwYXJ0bWVudF9pZCA6ICcnO1xuXHRcdFx0XHRcdFx0XHR0YXJnZXRfZGF0YS5kZXBhcnRtZW50ID0gdGFyZ2V0X3Jvdy5kZXBhcnRtZW50O1xuXHRcdFx0XHRcdFx0XHR0YXJnZXRfZGF0YS5qb2JfaWQgPSB0YXJnZXRfcm93LmpvYl9pZCA/IHRhcmdldF9yb3cuam9iX2lkIDogJyc7XG5cdFx0XHRcdFx0XHRcdHRhcmdldF9kYXRhLmpvYiA9IHRhcmdldF9yb3cuam9iO1xuXHRcdFx0XHRcdFx0XHR0YXJnZXRfZGF0YS5qb2JfaXRlbV9pZCA9IHRhcmdldF9yb3cuam9iX2l0ZW1faWQgPyB0YXJnZXRfcm93LmpvYl9pdGVtX2lkIDogJyc7XG5cdFx0XHRcdFx0XHRcdHRhcmdldF9kYXRhLnB1bmNoX3RhZ19pZCA9IHRhcmdldF9yb3cucHVuY2hfdGFnX2lkID8gdGFyZ2V0X3Jvdy5wdW5jaF90YWdfaWQgOiAnJztcblx0XHRcdFx0XHRcdFx0dGFyZ2V0X2RhdGEuam9iX2l0ZW0gPSB0YXJnZXRfcm93LmpvYl9pdGVtO1xuXHRcdFx0XHRcdFx0XHR0YXJnZXRfZGF0YS5kYXRlX3N0YW1wID0gZGF0ZV9zdGFtcDtcblx0XHRcdFx0XHRcdFx0dGFyZ2V0X2RhdGEuc3RhcnRfZGF0ZV9zdGFtcCA9IGRhdGVfc3RhbXA7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR2YXIgbmV3X3NoaWZ0ID0gR2xvYmFsLmNsb25lKCBzaGlmdCApO1xuXG5cdFx0XHRcdGlmICggJHRoaXMuc2VsZWN0X2RyYWdfbWVudV9pZCAhPT0gJ3N3YXAnICkge1xuXHRcdFx0XHRcdG5ld19zaGlmdC5pZCA9ICcnO1xuXHRcdFx0XHRcdG5ld19zaGlmdC5kYXRlX3N0YW1wID0gdGFyZ2V0X2RhdGEuZGF0ZV9zdGFtcDtcblx0XHRcdFx0XHRuZXdfc2hpZnQuc3RhcnRfZGF0ZV9zdGFtcCA9IHRhcmdldF9kYXRhLnN0YXJ0X2RhdGVfc3RhbXA7XG5cdFx0XHRcdFx0bmV3X3NoaWZ0LnVzZXJfaWQgPSB0YXJnZXRfZGF0YS51c2VyX2lkO1xuXHRcdFx0XHRcdC8vIFdoZW4gZHJhZ2dpbmcgYW4gb3BlbiBzaGlmdCB0byBhbiBlbXB0eSBjZWxsIGluIGEgdXNlciByb3cgd2l0aCBubyBicmFuY2ggY29sdW1uIHZpc2libGUsIHRoZSBicmFuY2ggaWQgdmFsdWUgbm93IGRlZmF1bHRzIHRvIHVzZXIgZGVmYXVsdCBicmFuY2ggaWRcblx0XHRcdFx0XHRuZXdfc2hpZnQuYnJhbmNoX2lkID0gdGFyZ2V0X2RhdGEuYnJhbmNoID8gdGFyZ2V0X2RhdGEuYnJhbmNoX2lkIDogVFRVVUlELm5vdF9leGlzdF9pZDtcblx0XHRcdFx0XHRuZXdfc2hpZnQuZGVwYXJ0bWVudF9pZCA9IHRhcmdldF9kYXRhLmRlcGFydG1lbnQgPyB0YXJnZXRfZGF0YS5kZXBhcnRtZW50X2lkIDogVFRVVUlELm5vdF9leGlzdF9pZDtcblx0XHRcdFx0XHRuZXdfc2hpZnQuam9iX2lkID0gdGFyZ2V0X2RhdGEuam9iX2lkID8gdGFyZ2V0X2RhdGEuam9iX2lkIDogVFRVVUlELm5vdF9leGlzdF9pZDtcblx0XHRcdFx0XHRuZXdfc2hpZnQuam9iX2l0ZW1faWQgPSB0YXJnZXRfZGF0YS5qb2JfaXRlbV9pZCA/IHRhcmdldF9kYXRhLmpvYl9pdGVtX2lkIDogVFRVVUlELm5vdF9leGlzdF9pZDtcblx0XHRcdFx0XHRuZXdfc2hpZnQucHVuY2hfdGFnX2lkID0gdGFyZ2V0X2RhdGEucHVuY2hfdGFnX2lkID8gdGFyZ2V0X2RhdGEucHVuY2hfdGFnX2lkIDogVFRVVUlELm5vdF9leGlzdF9pZDtcblxuXHRcdFx0XHRcdGlmICggJHRoaXMuaXNfb3ZlcnJpZGUgKSB7XG5cdFx0XHRcdFx0XHRuZXdfc2hpZnQub3ZlcndyaXRlID0gdHJ1ZTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoICR0aGlzLm5vdGlmeV91c2VyX3NjaGVkdWxlX2NoYW5nZSApIHtcblx0XHRcdFx0XHRcdG5ld19zaGlmdC5ub3RpZnlfdXNlcl9zY2hlZHVsZV9jaGFuZ2UgPSB0cnVlO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdG5ld19zaGlmdHNfYXJyYXkucHVzaCggbmV3X3NoaWZ0ICk7XG5cdFx0XHRcdFx0aWYgKCBzaGlmdC5pZCAmJiBzaGlmdC5pZCAhPSBUVFVVSUQuemVyb19pZCApIHtcblx0XHRcdFx0XHRcdGRlbGV0ZV9zaGlmdHNfYXJyYXkucHVzaCggc2hpZnQuaWQgKTtcblx0XHRcdFx0XHR9IGVsc2UgaWYgKCBzaGlmdC51c2VyX2lkICE9IFRUVVVJRC56ZXJvX2lkICYmIHNoaWZ0LnVzZXJfaWQgIT0gVFRVVUlELm5vdF9leGlzdF9pZCApIHtcblx0XHRcdFx0XHRcdC8vSWYgZHJhZ2dpbmcgKG1vdmUpIGEgcmVjdXJyaW5nIHNoaWZ0IGFzc2lnbmVkIHRvIGEgdXNlciBhbmQgZHJvcHBpbmcgb24gYW5vdGhlciB1c2VyLCBzd2l0Y2ggdGhlIHNvdXJjZSBzaGlmdCB0byBBYnNlbnQgaW4gdGhlIHByb2Nlc3MsIG90aGVyd2lzZSBib3RoIHNoaWZ0cyB3aWxsIGV4aXN0IGFzIGJlaW5nIHdvcmtlZC5cblx0XHRcdFx0XHRcdC8vICBIb3dldmVyIHdoZW4gZHJhZ2dpbmcgZnJvbSBhIE9QRU4gc2hpZnQgYXMgdGhlIHNvdXJjZSwgdGhhdCBpc24ndCByZXF1aXJlZCwgYXMgdGhlIE9QRU4gc2hpZnQgd2lsbCBhdXRvbWF0aWNhbGx5IGJlIGZpbGxlZC5cblx0XHRcdFx0XHRcdHNoaWZ0LnN0YXR1c19pZCA9ICcyMCc7XG5cdFx0XHRcdFx0XHRyZWN1cnJpbmdfZGVsZXRlX3NoaWZ0c19hcnJheS5wdXNoKCBzaGlmdCApO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoIHNoaWZ0LnVzZXJfaWQgPT0gVFRVVUlELnplcm9faWQgKSB7XG5cdFx0XHRcdFx0XHRkZWxldGVfb2xkX2l0ZW1zID0gZmFsc2U7IC8vTmV2ZXIgZGVsZXRlIG9sZCBpdGVtcyB3aGVuIHRoZSBzb3VyY2UgaXMgYSBPUEVOIHNoaWZ0LlxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHZhciB0ZW1wX3NlbGVjdGVkX2RhdGEgPSBHbG9iYWwuY2xvbmUoIG5ld19zaGlmdCApO1xuXHRcdFx0XHRcdHZhciB0ZW1wX3RhcmdldF9kYXRhID0gR2xvYmFsLmNsb25lKCB0YXJnZXRfZGF0YSApO1xuXG5cdFx0XHRcdFx0aWYgKCAhdGVtcF90YXJnZXRfZGF0YS5zdGFydF9kYXRlICkge1xuXHRcdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Zm9yICggdmFyIGtleSBpbiB0YXJnZXRfZGF0YSApIHtcblx0XHRcdFx0XHRcdGlmICgga2V5ICE9PSAnaWQnICYmXG5cdFx0XHRcdFx0XHRcdGtleSAhPT0gJ3VzZXJfaWQnICYmXG5cdFx0XHRcdFx0XHRcdGtleSAhPT0gJ2RhdGVfc3RhbXAnICYmXG5cdFx0XHRcdFx0XHRcdGtleSAhPT0gJ3N0YXJ0X2RhdGVfc3RhbXAnICYmXG5cdFx0XHRcdFx0XHRcdGtleSAhPT0gJ2JyYW5jaF9pZCcgJiZcblx0XHRcdFx0XHRcdFx0a2V5ICE9PSAnZGVwYXJ0bWVudF9pZCcgJiZcblx0XHRcdFx0XHRcdFx0a2V5ICE9PSAnam9iX2lkJyAmJlxuXHRcdFx0XHRcdFx0XHRrZXkgIT09ICdqb2JfaXRlbV9pZCcgJiZcblx0XHRcdFx0XHRcdFx0a2V5ICE9PSAncHVuY2hfdGFnX2lkJyAmJlxuXHRcdFx0XHRcdFx0XHRrZXkgIT09ICdicmFuY2gnICYmXG5cdFx0XHRcdFx0XHRcdGtleSAhPT0gJ2RlcGFydG1lbnQnICYmXG5cdFx0XHRcdFx0XHRcdGtleSAhPT0gJ2pvYicgJiZcblx0XHRcdFx0XHRcdFx0a2V5ICE9PSAnam9iX2l0ZW0nICYmXG5cdFx0XHRcdFx0XHRcdGtleSAhPT0gJ3NjaGVkdWxlX3BvbGljeV9pZCcgKSB7XG5cblx0XHRcdFx0XHRcdFx0dGFyZ2V0X2RhdGFba2V5XSA9IHRlbXBfc2VsZWN0ZWRfZGF0YVtrZXldO1xuXHRcdFx0XHRcdFx0XHRuZXdfc2hpZnRba2V5XSA9IHRlbXBfdGFyZ2V0X2RhdGFba2V5XTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBXaGVuIGRyYWdnaW5nIGFuIG9wZW4gc2hpZnQgdG8gYW4gZW1wdHkgY2VsbCBpbiBhIHVzZXIgcm93IHdpdGggbm8gYnJhbmNoIGNvbHVtbiB2aXNpYmxlLCB0aGUgYnJhbmNoIGlkIHZhbHVlIG5vdyBkZWZhdWx0cyB0byB1c2VyIGRlZmF1bHQgYnJhbmNoIGlkXG5cdFx0XHRcdFx0dGFyZ2V0X2RhdGEuYnJhbmNoX2lkID0gdGFyZ2V0X2RhdGEuYnJhbmNoID8gdGFyZ2V0X2RhdGEuYnJhbmNoX2lkIDogVFRVVUlELm5vdF9leGlzdF9pZDtcblx0XHRcdFx0XHR0YXJnZXRfZGF0YS5kZXBhcnRtZW50X2lkID0gdGFyZ2V0X2RhdGEuZGVwYXJ0bWVudCA/IHRhcmdldF9kYXRhLmRlcGFydG1lbnRfaWQgOiBUVFVVSUQubm90X2V4aXN0X2lkO1xuXHRcdFx0XHRcdHRhcmdldF9kYXRhLmpvYl9pZCA9IHRhcmdldF9kYXRhLmpvYl9pZCA/IHRhcmdldF9kYXRhLmpvYl9pZCA6IFRUVVVJRC5ub3RfZXhpc3RfaWQ7XG5cdFx0XHRcdFx0dGFyZ2V0X2RhdGEuam9iX2l0ZW1faWQgPSB0YXJnZXRfZGF0YS5qb2JfaXRlbV9pZCA/IHRhcmdldF9kYXRhLmpvYl9pdGVtX2lkIDogVFRVVUlELm5vdF9leGlzdF9pZDtcblx0XHRcdFx0XHR0YXJnZXRfZGF0YS5wdW5jaF90YWdfaWQgPSB0YXJnZXRfZGF0YS5wdW5jaF90YWdfaWQgPyB0YXJnZXRfZGF0YS5wdW5jaF90YWdfaWQgOiBUVFVVSUQubm90X2V4aXN0X2lkO1xuXG5cdFx0XHRcdFx0bmV3X3NoaWZ0c19hcnJheS5wdXNoKCB0YXJnZXRfZGF0YSApO1xuXHRcdFx0XHRcdG5ld19zaGlmdHNfYXJyYXkucHVzaCggbmV3X3NoaWZ0ICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIG5ld19zaGlmdHNfYXJyYXkubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0JHRoaXMuYXBpLnNldFNjaGVkdWxlKCBuZXdfc2hpZnRzX2FycmF5LCB7XG5cdFx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXMgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIHJlcy5pc1ZhbGlkKCkgKSB7XG5cdFx0XHRcdFx0XHRcdGlmICggZGVsZXRlX29sZF9pdGVtcyApIHtcblx0XHRcdFx0XHRcdFx0XHRpZiAoIGRlbGV0ZV9zaGlmdHNfYXJyYXkubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0XHRcdFx0XHRcdCR0aGlzLmFwaS5kZWxldGVTY2hlZHVsZSggZGVsZXRlX3NoaWZ0c19hcnJheSwge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0aWYgKCByZWN1cnJpbmdfZGVsZXRlX3NoaWZ0c19hcnJheS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0JHRoaXMuYXBpLnNldFNjaGVkdWxlKCByZWN1cnJpbmdfZGVsZXRlX3NoaWZ0c19hcnJheSwge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0JHRoaXMuc2VhcmNoKCk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0JHRoaXMuc2VhcmNoKCk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIGlmICggcmVjdXJyaW5nX2RlbGV0ZV9zaGlmdHNfYXJyYXkubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0XHRcdFx0XHRcdCR0aGlzLmFwaS5zZXRTY2hlZHVsZSggcmVjdXJyaW5nX2RlbGV0ZV9zaGlmdHNfYXJyYXksIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCR0aGlzLnNlYXJjaCgpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRcdCR0aGlzLnNlYXJjaCgpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHQkdGhpcy5zZWFyY2goKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0VEFsZXJ0TWFuYWdlci5zaG93RXJyb3JBbGVydCggcmVzICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9ICk7XG5cdFx0XHR9XG5cblx0XHR9ICk7XG5cblx0XHRjZWxscy51bmJpbmQoICdkcmFnZW50ZXInICkuYmluZCggJ2RyYWdlbnRlcicsIGZ1bmN0aW9uKCBldmVudCApIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0fSApO1xuXG5cdFx0Y2VsbHMudW5iaW5kKCAnZHJhZ292ZXInICkuYmluZCggJ2RyYWdvdmVyJywgZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTsgLy9NdXN0IHByZXZlbnQgdGloc1xuXG5cdFx0fSApO1xuXHRcdGNlbGxzLnVuYmluZCggJ2RyYWdlbmQnICkuYmluZCggJ2RyYWdlbmQnLCBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdCQoICcuZHJhZy1ob2xkZXItZGl2JyApLnJlbW92ZSgpO1xuXHRcdFx0JCggJy5zY2hlZHVsZS1kcmFnLW92ZXInICkucmVtb3ZlQ2xhc3MoICdzY2hlZHVsZS1kcmFnLW92ZXInICk7XG5cblx0XHR9ICk7XG5cdH1cblxuXHRyZXNldFNvbWVGaWVsZHMoIGl0ZW0gKSB7XG5cdFx0aXRlbS5icmFuY2hfaWQgPSBpdGVtLmJyYW5jaCA/IGl0ZW0uYnJhbmNoX2lkIDogJyc7XG5cdFx0aXRlbS5kZXBhcnRtZW50X2lkID0gaXRlbS5kZXBhcnRtZW50ID8gaXRlbS5kZXBhcnRtZW50X2lkIDogJyc7XG5cdFx0aXRlbS5qb2JfaWQgPSBpdGVtLmpvYiA/IGl0ZW0uam9iX2lkIDogJyc7XG5cdFx0aXRlbS5qb2JfaXRlbV9pZCA9IGl0ZW0uam9iX2l0ZW0gPyBpdGVtLmpvYl9pdGVtX2lkIDogJyc7XG5cdFx0aXRlbS5wdW5jaF90YWdfaWQgPSBpdGVtLnB1bmNoX3RhZ19pZCA/IGl0ZW0ucHVuY2hfdGFnX2lkIDogW107XG5cblx0XHRyZXR1cm4gaXRlbTtcblx0fVxuXG5cdF9jcmVhdGVQYXJhbWV0ZXJzRm9yQWRkKCkge1xuXHRcdHZhciByZXN1bHQgPSBbXSwgdXNlcjtcblx0XHRpZiAoIHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5Lmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRmb3IgKCB2YXIgaSA9IDAsIG4gPSB0aGlzLnNlbGVjdF9jZWxsc19BcnJheS5sZW5ndGg7IGkgPCBuOyBpKysgKSB7XG5cdFx0XHRcdHZhciBpdGVtID0gdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXlbaV07XG5cdFx0XHRcdHVzZXIgPSB7fTtcblx0XHRcdFx0dXNlci51c2VyX2lkID0gaXRlbS51c2VyX2lkO1xuXHRcdFx0XHR1c2VyLmJyYW5jaF9pZCA9IGl0ZW0uYnJhbmNoX2lkO1xuXHRcdFx0XHR1c2VyLmRlcGFydG1lbnRfaWQgPSBpdGVtLmRlcGFydG1lbnRfaWQ7XG5cdFx0XHRcdHVzZXIuam9iX2lkID0gaXRlbS5qb2JfaWQ7XG5cdFx0XHRcdHVzZXIuam9iX2l0ZW1faWQgPSBpdGVtLmpvYl9pdGVtX2lkO1xuXHRcdFx0XHR1c2VyLnB1bmNoX3RhZ19pZCA9IGl0ZW0ucHVuY2hfdGFnX2lkO1xuXHRcdFx0XHR1c2VyLmRhdGUgPSBpdGVtLmRhdGU7XG5cdFx0XHRcdHJlc3VsdC5wdXNoKCB1c2VyICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKCByZXN1bHQubGVuZ3RoIDwgMSApIHtcblx0XHRcdHZhciBsb2dpbl91c2VyID0gTG9jYWxDYWNoZURhdGEuZ2V0TG9naW5Vc2VyKCk7XG5cdFx0XHR1c2VyID0ge307XG5cdFx0XHR1c2VyLnVzZXJfaWQgPSBsb2dpbl91c2VyLmlkO1xuXHRcdFx0dXNlci5icmFuY2hfaWQgPSBsb2dpbl91c2VyLmJyYW5jaF9pZDtcblx0XHRcdHVzZXIuZGVwYXJ0bWVudF9pZCA9IGxvZ2luX3VzZXIuZGVwYXJ0bWVudF9pZDtcblx0XHRcdHVzZXIuam9iX2lkID0gbG9naW5fdXNlci5qb2JfaWQ7XG5cdFx0XHR1c2VyLmpvYl9pdGVtX2lkID0gbG9naW5fdXNlci5qb2JfaXRlbV9pZDtcblx0XHRcdHVzZXIucHVuY2hfdGFnX2lkID0gbG9naW5fdXNlci5wdW5jaF90YWdfaWQ7XG5cdFx0XHR1c2VyLmRhdGUgPSB0aGlzLmdldFNlbGVjdERhdGUoKTtcblx0XHRcdHJlc3VsdC5wdXNoKCB1c2VyICk7XG5cdFx0fVxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cblxuXHRvbkFkZENsaWNrKCBkb2luZ19zYXZlX2FuZF9uZXcgKSB7XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHRoaXMuc2V0Q3VycmVudEVkaXRWaWV3U3RhdGUoICduZXcnICk7XG5cblx0XHRpZiAoIHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5Lmxlbmd0aCA+IDEgKSB7XG5cdFx0XHR0aGlzLmlzX21hc3NfYWRkaW5nID0gdHJ1ZTtcblx0XHR9XG5cblx0XHQkdGhpcy5vcGVuRWRpdFZpZXcoKTtcblxuXHRcdHZhciBhcmdzO1xuXHRcdGlmICggIWRvaW5nX3NhdmVfYW5kX25ldyApIHtcblx0XHRcdGFyZ3MgPSB0aGlzLl9jcmVhdGVQYXJhbWV0ZXJzRm9yQWRkKCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGFyZ3MgPSBbXG5cdFx0XHRcdHtcblx0XHRcdFx0XHR1c2VyX2lkOiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudXNlcl9pZCxcblx0XHRcdFx0XHRicmFuY2hfaWQ6IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5icmFuY2hfaWQsXG5cdFx0XHRcdFx0ZGVwYXJ0bWVudF9pZDogdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmRlcGFydG1lbnRfaWQsXG5cdFx0XHRcdFx0am9iX2lkOiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuam9iX2lkLFxuXHRcdFx0XHRcdGpvYl9pdGVtX2lkOiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuam9iX2l0ZW1faWQsXG5cdFx0XHRcdFx0cHVuY2hfdGFnX2lkOiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQucHVuY2hfdGFnX2lkLFxuXHRcdFx0XHRcdGRhdGU6IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5kYXRlX3N0YW1wXG5cdFx0XHRcdH1cblx0XHRcdF07XG5cdFx0fVxuXG5cdFx0dGhpcy5hcGlbJ2dldCcgKyB0aGlzLmFwaS5rZXlfbmFtZSArICdEZWZhdWx0RGF0YSddKCBhcmdzLCB7XG5cdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlc3VsdCApIHtcblx0XHRcdFx0dmFyIHNlbGVjdF9zaGlmdDtcblx0XHRcdFx0dmFyIHJlc3VsdF9kYXRhID0gcmVzdWx0LmdldFJlc3VsdCgpO1xuXG5cdFx0XHRcdHNlbGVjdF9zaGlmdCA9IHJlc3VsdF9kYXRhO1xuXHRcdFx0XHRpZiAoICR0aGlzLnNlbGVjdF9jZWxsc19BcnJheS5sZW5ndGggPj0gMSApIHtcblx0XHRcdFx0XHRmb3IgKCB2YXIgaSA9IDAsIG4gPSBhcmdzLmxlbmd0aDsgaSA8IG47IGkrKyApIHtcblx0XHRcdFx0XHRcdHZhciBpdGVtID0gYXJnc1tpXTtcblx0XHRcdFx0XHRcdGlmICggaSA9PSAwICkge1xuXHRcdFx0XHRcdFx0XHRzZWxlY3Rfc2hpZnQuYnJhbmNoX2lkID0gaXRlbS5icmFuY2hfaWQ7XG5cdFx0XHRcdFx0XHRcdHNlbGVjdF9zaGlmdC5kZXBhcnRtZW50X2lkID0gaXRlbS5kZXBhcnRtZW50X2lkO1xuXHRcdFx0XHRcdFx0XHRzZWxlY3Rfc2hpZnQuam9iX2lkID0gaXRlbS5qb2JfaWQ7XG5cdFx0XHRcdFx0XHRcdHNlbGVjdF9zaGlmdC5qb2JfaXRlbV9pZCA9IGl0ZW0uam9iX2l0ZW1faWQ7XG5cdFx0XHRcdFx0XHRcdHNlbGVjdF9zaGlmdC5wdW5jaF90YWdfaWQgPSBpdGVtLnB1bmNoX3RhZ19pZDtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdCggc2VsZWN0X3NoaWZ0LmJyYW5jaF9pZCAhPT0gaXRlbS5icmFuY2hfaWQgJiYgc2VsZWN0X3NoaWZ0LmJyYW5jaF9pZCAhPT0gJy0yJyApID8gc2VsZWN0X3NoaWZ0LmJyYW5jaF9pZCA9ICctMicgOiBpdGVtLmJyYW5jaF9pZDtcblx0XHRcdFx0XHRcdFx0KCBzZWxlY3Rfc2hpZnQuZGVwYXJ0bWVudF9pZCAhPT0gaXRlbS5kZXBhcnRtZW50X2lkICYmIHNlbGVjdF9zaGlmdC5kZXBhcnRtZW50X2lkICE9PSAnLTInICkgPyBzZWxlY3Rfc2hpZnQuZGVwYXJ0bWVudF9pZCA9ICctMicgOiBpdGVtLmRlcGFydG1lbnRfaWQ7XG5cdFx0XHRcdFx0XHRcdCggc2VsZWN0X3NoaWZ0LmpvYl9pZCAhPT0gaXRlbS5qb2JfaWQgJiYgc2VsZWN0X3NoaWZ0LmpvYl9pZCAhPT0gJy0yJyApID8gc2VsZWN0X3NoaWZ0LmpvYl9pZCA9ICctMicgOiBpdGVtLmpvYl9pZDtcblx0XHRcdFx0XHRcdFx0KCBzZWxlY3Rfc2hpZnQuam9iX2l0ZW1faWQgIT09IGl0ZW0uam9iX2l0ZW1faWQgJiYgc2VsZWN0X3NoaWZ0LmpvYl9pdGVtX2lkICE9PSAnLTInICkgPyBzZWxlY3Rfc2hpZnQuam9iX2l0ZW1faWQgPSAnLTInIDogaXRlbS5qb2JfaXRlbV9pZDtcblx0XHRcdFx0XHRcdFx0KCBzZWxlY3Rfc2hpZnQucHVuY2hfdGFnX2lkICE9PSBpdGVtLnB1bmNoX3RhZ19pZCAmJiBzZWxlY3Rfc2hpZnQucHVuY2hfdGFnX2lkICE9PSAnLTInICkgPyBzZWxlY3Rfc2hpZnQucHVuY2hfdGFnX2lkID0gJy0yJyA6IGl0ZW0ucHVuY2hfdGFnX2lkO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggIWRvaW5nX3NhdmVfYW5kX25ldyApIHtcblx0XHRcdFx0XHRzZWxlY3Rfc2hpZnQuZGF0ZV9zdGFtcCA9ICR0aGlzLmdldFNlbGVjdERhdGUoKTtcblxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHZhciB0ZW1wX2RhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCAkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmRhdGVfc3RhbXAgKTtcblx0XHRcdFx0XHRzZWxlY3Rfc2hpZnQuZGF0ZV9zdGFtcCA9IG5ldyBEYXRlKCBuZXcgRGF0ZSggdGVtcF9kYXRlLmdldFRpbWUoKSApLnNldERhdGUoIHRlbXBfZGF0ZS5nZXREYXRlKCkgKyAxICkgKS5mb3JtYXQoKTtcblxuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCAhc2VsZWN0X3NoaWZ0LnN0YXJ0X2RhdGVfc3RhbXAgKSB7XG5cdFx0XHRcdFx0c2VsZWN0X3NoaWZ0LnN0YXJ0X2RhdGVfc3RhbXAgPSBzZWxlY3Rfc2hpZnQuZGF0ZV9zdGFtcDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHNlbGVjdF9zaGlmdC5pZCA9ICcnO1xuXG5cdFx0XHRcdGlmICggJHRoaXMuc3ViX3ZpZXdfbW9kZSAmJiAkdGhpcy5wYXJlbnRfa2V5ICkge1xuXHRcdFx0XHRcdHJlc3VsdF9kYXRhWyR0aGlzLnBhcmVudF9rZXldID0gJHRoaXMucGFyZW50X3ZhbHVlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0JHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCA9IHNlbGVjdF9zaGlmdDtcblx0XHRcdFx0JHRoaXMuaW5pdEVkaXRWaWV3KCk7XG5cblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cblxuXHRvcGVuRWRpdFZpZXcoKSB7XG5cblx0XHRpZiAoICF0aGlzLmVkaXRfdmlldyApIHtcblx0XHRcdHRoaXMuaW5pdEVkaXRWaWV3VUkoICdTY2hlZHVsZScsICdTY2hlZHVsZUVkaXRWaWV3Lmh0bWwnICk7XG5cdFx0fVxuXHRcdHRoaXMucHJldmlvdXNfYWJzZW5jZV9wb2xpY3lfaWQgPSBmYWxzZTtcblx0fVxuXG5cdC8vc2V0IHdpZGdldCBkaXNhYmxlYmlsaXR5IGlmIHZpZXcgbW9kZSBvciBlZGl0IG1vZGVcblx0c2V0RWRpdFZpZXdXaWRnZXRzTW9kZSgpIHtcblx0XHR2YXIgZGlkX2NsZWFuX2RpYyA9IHt9O1xuXHRcdGZvciAoIHZhciBrZXkgaW4gdGhpcy5lZGl0X3ZpZXdfdWlfZGljICkge1xuXHRcdFx0aWYgKCAhdGhpcy5lZGl0X3ZpZXdfdWlfZGljLmhhc093blByb3BlcnR5KCBrZXkgKSApIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cdFx0XHR2YXIgd2lkZ2V0ID0gdGhpcy5lZGl0X3ZpZXdfdWlfZGljW2tleV07XG5cdFx0XHR3aWRnZXQuY3NzKCAnb3BhY2l0eScsIDEgKTtcblx0XHRcdHZhciBjb2x1bW4gPSB3aWRnZXQucGFyZW50KCkucGFyZW50KCkucGFyZW50KCk7XG5cdFx0XHR2YXIgdGFiX2lkID0gY29sdW1uLnBhcmVudCgpLmF0dHIoICdpZCcgKTtcblx0XHRcdGlmICggIWNvbHVtbi5oYXNDbGFzcyggJ3YtYm94JyApICkge1xuXHRcdFx0XHRpZiAoICFkaWRfY2xlYW5fZGljW3RhYl9pZF0gKSB7XG5cdFx0XHRcdFx0ZGlkX2NsZWFuX2RpY1t0YWJfaWRdID0gdHJ1ZTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0aWYgKCB0aGlzLmlzX3ZpZXdpbmcgKSB7XG5cdFx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCB3aWRnZXQuc2V0RW5hYmxlZCApICkge1xuXHRcdFx0XHRcdHdpZGdldC5zZXRFbmFibGVkKCBmYWxzZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggd2lkZ2V0LnNldEVuYWJsZWQgKSApIHtcblx0XHRcdFx0XHR3aWRnZXQuc2V0RW5hYmxlZCggdHJ1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHR9XG5cdH1cblxuXHRzZXRKb2JWYWx1ZVdoZW5Vc2VyQ2hhbmdlZCggam9iLCBqb2JfaWRfY29sX25hbWUsIGZpbHRlcl9kYXRhICkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cblx0XHQvL0Vycm9yOiBVbmNhdWdodCBUeXBlRXJyb3I6IENhbm5vdCBzZXQgcHJvcGVydHkgJ2pvYl9pdGVtX2lkJyBvZiBudWxsIGluIC9pbnRlcmZhY2UvaHRtbDUvIyFtPVRpbWVTaGVldCZkYXRlPTIwMTUwMTI2JnVzZXJfaWQ9NTQyODYgbGluZSA2Nzg1XG5cdFx0aWYgKCAhJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIHRoaXMuZWRpdF92aWV3X3VpX2RpY1sndXNlcl9pZHMnXSAmJiB0aGlzLmVkaXRfdmlld191aV9kaWNbJ3VzZXJfaWRzJ10uaXMoICc6dmlzaWJsZScgKSApIHtcblx0XHRcdGZpbHRlcl9kYXRhWyd1c2VyX2lkJ10gPSB0aGlzLmVkaXRfdmlld191aV9kaWNbJ3VzZXJfaWRzJ10uZ2V0VmFsdWUoKTtcblxuXHRcdFx0Ly9JZiBtb3JlIHRoYW4gb25lIHVzZXIgaXMgc2VsZWN0ZWQsIGRvbid0IGZpbHRlciBieSB1c2VyX2lkIGF0IGFsbCwgc2hvdyBhbGwgam9icyBhbmQgbGV0IHRoZSB2YWxpZGF0aW9uIHN5c3RlbSBoYW5kbGUgaXQuXG5cdFx0XHRpZiAoIGZpbHRlcl9kYXRhWyd1c2VyX2lkJ10ubGVuZ3RoID09IDEgKSB7XG5cdFx0XHRcdGZpbHRlcl9kYXRhWyd1c2VyX2lkJ10gPSBmaWx0ZXJfZGF0YVsndXNlcl9pZCddWzBdO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZmlsdGVyX2RhdGFbJ3VzZXJfaWQnXSA9IGZhbHNlO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRmaWx0ZXJfZGF0YVsndXNlcl9pZCddID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkWyd1c2VyX2lkJ107XG5cdFx0fVxuXG5cdFx0dmFyIGpvYl93aWRnZXQgPSAkdGhpcy5lZGl0X3ZpZXdfdWlfZGljW2pvYl9pZF9jb2xfbmFtZV07XG5cdFx0dmFyIGN1cnJlbnRfam9iX2lkID0gam9iX3dpZGdldC5nZXRWYWx1ZSgpO1xuXHRcdGpvYl93aWRnZXQuc2V0U291cmNlRGF0YSggbnVsbCApOyAvL0NsZWFyIG91dCBzb3VyY2UgZGF0YSBzbyBpdHMgcmVsb2FkZWQgd2hlbiB0aGUgSm9iIGRyb3Bkb3duIGlzIGV4cGFuZGVkIGFnYWluLlxuXHRcdGpvYl93aWRnZXQuc2V0Q2hlY2tCb3goIHRydWUgKTtcblx0XHR0aGlzLmVkaXRfdmlld191aV9kaWNbJ2pvYl9pdGVtX3F1aWNrX3NlYXJjaCddLnNldENoZWNrQm94KCB0cnVlICk7XG5cblx0XHR2YXIgYXJncyA9IHt9O1xuXHRcdGFyZ3MuZmlsdGVyX2RhdGEgPSBmaWx0ZXJfZGF0YTtcblx0XHQkdGhpcy5lZGl0X3ZpZXdfdWlfZGljW2pvYl9pZF9jb2xfbmFtZV0uc2V0RGVmYXVsdEFyZ3MoIGFyZ3MgKTtcblxuXHRcdHJldHVybjtcblx0fVxuXG5cdG9uRm9ybUl0ZW1DaGFuZ2UoIHRhcmdldCwgZG9Ob3RWYWxpZGF0ZSApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHRoaXMuc2V0SXNDaGFuZ2VkKCB0YXJnZXQgKTtcblx0XHR0aGlzLnNldE1hc3NFZGl0aW5nRmllbGRzV2hlbkZvcm1DaGFuZ2UoIHRhcmdldCApO1xuXHRcdHZhciBrZXkgPSB0YXJnZXQuZ2V0RmllbGQoKTtcblx0XHR2YXIgY192YWx1ZSA9IHRhcmdldC5nZXRWYWx1ZSgpO1xuXHRcdHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFtrZXldID0gY192YWx1ZTtcblxuXHRcdHN3aXRjaCAoIGtleSApIHtcblx0XHRcdGNhc2UgJ2pvYl9pZCc6XG5cdFx0XHRcdGlmICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSB7XG5cdFx0XHRcdFx0dGhpcy5lZGl0X3ZpZXdfdWlfZGljWydqb2JfcXVpY2tfc2VhcmNoJ10uc2V0VmFsdWUoIHRhcmdldC5nZXRWYWx1ZSggdHJ1ZSApID8gKCB0YXJnZXQuZ2V0VmFsdWUoIHRydWUgKS5tYW51YWxfaWQgPyB0YXJnZXQuZ2V0VmFsdWUoIHRydWUgKS5tYW51YWxfaWQgOiAnJyApIDogJycgKTtcblx0XHRcdFx0XHR0aGlzLnNldEpvYkl0ZW1WYWx1ZVdoZW5Kb2JDaGFuZ2VkKCB0YXJnZXQuZ2V0VmFsdWUoIHRydWUgKSwgJ2pvYl9pdGVtX2lkJywge1xuXHRcdFx0XHRcdFx0c3RhdHVzX2lkOiAxMCxcblx0XHRcdFx0XHRcdGpvYl9pZDogdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmpvYl9pZFxuXHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHR0aGlzLmVkaXRfdmlld191aV9kaWNbJ2pvYl9xdWlja19zZWFyY2gnXS5zZXRDaGVja0JveCggdHJ1ZSApO1xuXHRcdFx0XHRcdHRoaXMuc2V0UHVuY2hUYWdWYWx1ZXNXaGVuQ3JpdGVyaWFDaGFuZ2VkKCB0aGlzLmdldFB1bmNoVGFnRmlsdGVyRGF0YSgpLCAncHVuY2hfdGFnX2lkJyApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnam9iX2l0ZW1faWQnOlxuXHRcdFx0XHRpZiAoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpID49IDIwICkge1xuXHRcdFx0XHRcdHRoaXMuZWRpdF92aWV3X3VpX2RpY1snam9iX2l0ZW1fcXVpY2tfc2VhcmNoJ10uc2V0VmFsdWUoIHRhcmdldC5nZXRWYWx1ZSggdHJ1ZSApID8gKCB0YXJnZXQuZ2V0VmFsdWUoIHRydWUgKS5tYW51YWxfaWQgPyB0YXJnZXQuZ2V0VmFsdWUoIHRydWUgKS5tYW51YWxfaWQgOiAnJyApIDogJycgKTtcblx0XHRcdFx0XHR0aGlzLmVkaXRfdmlld191aV9kaWNbJ2pvYl9pdGVtX3F1aWNrX3NlYXJjaCddLnNldENoZWNrQm94KCB0cnVlICk7XG5cdFx0XHRcdFx0dGhpcy5zZXRQdW5jaFRhZ1ZhbHVlc1doZW5Dcml0ZXJpYUNoYW5nZWQoIHRoaXMuZ2V0UHVuY2hUYWdGaWx0ZXJEYXRhKCksICdwdW5jaF90YWdfaWQnICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdwdW5jaF90YWdfaWQnOlxuXHRcdFx0XHRpZiAoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpID49IDIwICkge1xuXHRcdFx0XHRcdGlmICggY192YWx1ZSAhPT0gVFRVVUlELnplcm9faWQgJiYgY192YWx1ZSAhPT0gZmFsc2UgJiYgY192YWx1ZS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHRcdFx0dGhpcy5zZXRQdW5jaFRhZ1F1aWNrU2VhcmNoTWFudWFsSWRzKCB0YXJnZXQuZ2V0U2VsZWN0SXRlbXMoKSApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHR0aGlzLmVkaXRfdmlld191aV9kaWNbJ3B1bmNoX3RhZ19xdWlja19zZWFyY2gnXS5zZXRWYWx1ZSggJycgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0JHRoaXMucHJldmlvdXNfcHVuY2hfdGFnX3NlbGVjdGlvbiA9IGNfdmFsdWU7XG5cdFx0XHRcdFx0Ly9SZXNldCBzb3VyY2UgZGF0YSB0byBtYWtlIHN1cmUgY29ycmVjdCBwdW5jaCB0YWdzIGFyZSBhbHdheXMgc2hvd24uXG5cdFx0XHRcdFx0dGhpcy5lZGl0X3ZpZXdfdWlfZGljWydwdW5jaF90YWdfaWQnXS5zZXRTb3VyY2VEYXRhKCBudWxsICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdicmFuY2hfaWQnOlxuXHRcdFx0XHRpZiAoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpID49IDIwICkge1xuXHRcdFx0XHRcdHRoaXMuc2V0UHVuY2hUYWdWYWx1ZXNXaGVuQ3JpdGVyaWFDaGFuZ2VkKCB0aGlzLmdldFB1bmNoVGFnRmlsdGVyRGF0YSgpLCAncHVuY2hfdGFnX2lkJyApO1xuXHRcdFx0XHRcdHRoaXMuc2V0Sm9iVmFsdWVXaGVuQ3JpdGVyaWFDaGFuZ2VkKCAnam9iX2lkJywge1xuXHRcdFx0XHRcdFx0c3RhdHVzX2lkOiAxMCxcblx0XHRcdFx0XHRcdHVzZXJfaWQ6IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC51c2VyX2lkLFxuXHRcdFx0XHRcdFx0cHVuY2hfYnJhbmNoX2lkOiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuYnJhbmNoX2lkLFxuXHRcdFx0XHRcdFx0cHVuY2hfZGVwYXJ0bWVudF9pZDogdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmRlcGFydG1lbnRfaWRcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0dGhpcy5zZXREZXBhcnRtZW50VmFsdWVXaGVuQnJhbmNoQ2hhbmdlZCggdGFyZ2V0LmdldFZhbHVlKCB0cnVlICksICdkZXBhcnRtZW50X2lkJywge1xuXHRcdFx0XHRcdFx0YnJhbmNoX2lkOiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuYnJhbmNoX2lkLFxuXHRcdFx0XHRcdFx0dXNlcl9pZDogICB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudXNlcl9pZFxuXHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ2RlcGFydG1lbnRfaWQnOlxuXHRcdFx0XHRpZiAoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpID49IDIwICkge1xuXHRcdFx0XHRcdHRoaXMuc2V0UHVuY2hUYWdWYWx1ZXNXaGVuQ3JpdGVyaWFDaGFuZ2VkKCB0aGlzLmdldFB1bmNoVGFnRmlsdGVyRGF0YSgpLCAncHVuY2hfdGFnX2lkJyApO1xuXHRcdFx0XHRcdHRoaXMuc2V0Sm9iVmFsdWVXaGVuQ3JpdGVyaWFDaGFuZ2VkKCAnam9iX2lkJywge1xuXHRcdFx0XHRcdFx0c3RhdHVzX2lkOiAxMCxcblx0XHRcdFx0XHRcdHVzZXJfaWQ6IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC51c2VyX2lkLFxuXHRcdFx0XHRcdFx0cHVuY2hfYnJhbmNoX2lkOiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuYnJhbmNoX2lkLFxuXHRcdFx0XHRcdFx0cHVuY2hfZGVwYXJ0bWVudF9pZDogdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmRlcGFydG1lbnRfaWRcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdqb2JfcXVpY2tfc2VhcmNoJzpcblx0XHRcdGNhc2UgJ2pvYl9pdGVtX3F1aWNrX3NlYXJjaCc6XG5cdFx0XHRcdGlmICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSB7XG5cdFx0XHRcdFx0dGhpcy5vbkpvYlF1aWNrU2VhcmNoKCBrZXksIGNfdmFsdWUgKTtcblx0XHRcdFx0XHR0aGlzLnNldFB1bmNoVGFnVmFsdWVzV2hlbkNyaXRlcmlhQ2hhbmdlZCggdGhpcy5nZXRQdW5jaFRhZ0ZpbHRlckRhdGEoKSwgJ3B1bmNoX3RhZ19pZCcgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3B1bmNoX3RhZ19xdWlja19zZWFyY2gnOlxuXHRcdFx0XHRpZiAoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpID49IDIwICkge1xuXHRcdFx0XHRcdHRoaXMub25QdW5jaFRhZ1F1aWNrU2VhcmNoKCBjX3ZhbHVlLCB0aGlzLmdldFB1bmNoVGFnRmlsdGVyRGF0YSgpLCAncHVuY2hfdGFnX2lkJyApO1xuXG5cdFx0XHRcdFx0Ly9Eb24ndCB2YWxpZGF0ZSBpbW1lZGlhdGVseSBhcyBvblB1bmNoVGFnUXVpY2tTZWFyY2ggaXMgZG9pbmcgYXN5bmMgQVBJIGNhbGxzLCBhbmQgaXQgd291bGQgY2F1c2UgYSBndWFyYW50ZWVkIHZhbGlkYXRpb24gZmFpbHVyZS5cblx0XHRcdFx0XHRkb05vdFZhbGlkYXRlID0gdHJ1ZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3N0YXR1c19pZCc6XG5cdFx0XHRcdHRoaXMub25UeXBlQ2hhbmdlKCB0cnVlICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAndXNlcl9pZCc6XG5cdFx0XHRjYXNlICd1c2VyX2lkcyc6XG5cdFx0XHRcdHRoaXMuc2V0RWRpdE1lbnUoKTtcblxuXHRcdFx0XHR0aGlzLnNldEFic2VuY2VQb2xpY3lXaGVuVXNlckNoYW5nZWQoKTtcblxuXHRcdFx0XHRpZiAoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpID49IDIwICkge1xuXHRcdFx0XHRcdGlmICggdGhpcy5lZGl0X3ZpZXdfdWlfZGljWydqb2JfaWQnXSApIHtcblx0XHRcdFx0XHRcdHRoaXMuc2V0Sm9iVmFsdWVXaGVuVXNlckNoYW5nZWQoIHRoaXMuZWRpdF92aWV3X3VpX2RpY1snam9iX2lkJ10uZ2V0VmFsdWUoIHRydWUgKSwgJ2pvYl9pZCcsIHtcblx0XHRcdFx0XHRcdFx0c3RhdHVzX2lkOiAxMCxcblx0XHRcdFx0XHRcdFx0dXNlcl9pZDogdGhpcy5lZGl0X3ZpZXdfdWlfZGljW2tleV0uZ2V0VmFsdWUoKSxcblx0XHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR0aGlzLnNldFB1bmNoVGFnVmFsdWVzV2hlbkNyaXRlcmlhQ2hhbmdlZCggdGhpcy5nZXRQdW5jaFRhZ0ZpbHRlckRhdGEoKSwgJ3B1bmNoX3RhZ19pZCcgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHRjYXNlICdzdGFydF9kYXRlX3N0YW1wcyc6XG5cdFx0XHRcdHRoaXMuc2V0RWRpdE1lbnUoKTtcblx0XHRcdFx0dGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkWydzdGFydF9kYXRlX3N0YW1wJ10gPSBjX3ZhbHVlO1xuXHRcdFx0XHRicmVhaztcblxuXHRcdH1cblxuXHRcdGlmICgga2V5ID09ICdhYnNlbmNlX3BvbGljeV9pZCcgKSB7XG5cdFx0XHR0aGlzLnByZXZpb3VzX2Fic2VuY2VfcG9saWN5X2lkID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmFic2VuY2VfcG9saWN5X2lkO1xuXHRcdH1cblxuXHRcdGlmICgga2V5ID09PSAnZGF0ZV9zdGFtcCcgfHxcblx0XHRcdGtleSA9PT0gJ3N0YXJ0X2RhdGVfc3RhbXBzJyB8fFxuXHRcdFx0a2V5ID09PSAnc3RhcnRfZGF0ZV9zdGFtcCcgfHxcblx0XHRcdGtleSA9PT0gJ3N0YXJ0X3RpbWUnIHx8XG5cdFx0XHRrZXkgPT09ICdlbmRfdGltZScgfHxcblx0XHRcdGtleSA9PT0gJ3NjaGVkdWxlX3BvbGljeV9pZCcgfHxcblx0XHRcdGtleSA9PT0gJ2Fic2VuY2VfcG9saWN5X2lkJyApIHtcblxuXHRcdFx0aWYgKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRbJ2RhdGVfc3RhbXAnXSAhPT0gJycgJiZcblx0XHRcdFx0dGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkWydzdGFydF90aW1lJ10gIT09ICcnICYmXG5cdFx0XHRcdHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFsnZW5kX3RpbWUnXSAhPT0gJycgKSB7XG5cblx0XHRcdFx0dmFyIHN0YXJ0VGltZSA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFsnZGF0ZV9zdGFtcCddICsgJyAnICsgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkWydzdGFydF90aW1lJ107XG5cdFx0XHRcdHZhciBlbmRUaW1lID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkWydkYXRlX3N0YW1wJ10gKyAnICcgKyB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRbJ2VuZF90aW1lJ107XG5cdFx0XHRcdHZhciBzY2hlZHVsZVBvbGljeUlkID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkWydzY2hlZHVsZV9wb2xpY3lfaWQnXTtcblx0XHRcdFx0dmFyIHVzZXJfaWQgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudXNlcl9pZDtcblxuXHRcdFx0XHR0aGlzLmFwaS5nZXRTY2hlZHVsZVRvdGFsVGltZSggc3RhcnRUaW1lLCBlbmRUaW1lLCBzY2hlZHVsZVBvbGljeUlkLCB1c2VyX2lkLCB7XG5cdFx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCB0b3RhbF90aW1lICkge1xuXG5cdFx0XHRcdFx0XHQvL1VuY2F1Z2h0IFR5cGVFcnJvcjogQ2Fubm90IHNldCBwcm9wZXJ0eSAndG90YWxfdGltZScgb2YgbnVsbFxuXHRcdFx0XHRcdFx0Ly9FcnJvcjogVW5jYXVnaHQgVHlwZUVycm9yOiBDYW5ub3QgcmVhZCBwcm9wZXJ0eSAnc2V0VmFsdWUnIG9mIHVuZGVmaW5lZCBpbiBpbnRlcmZhY2UvaHRtbDUvIyFtPVNjaGVkdWxlJmRhdGU9MjAxNjAyMDImbW9kZT13ZWVrJmE9bmV3JnRhYj1TY2hlZHVsZSBsaW5lIDE3OTlcblx0XHRcdFx0XHRcdGlmICggISR0aGlzLmVkaXRfdmlldyB8fCAhJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCB8fCAhJHRoaXMuZWRpdF92aWV3X3VpX2RpY1sndG90YWxfdGltZSddICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdC8vRml4ZWQgZXhjZXB0aW9uIHRoYXQgdG90YWxfdGltZSBpcyBudWxsXG5cdFx0XHRcdFx0XHRpZiAoIHRvdGFsX3RpbWUgKSB7XG5cdFx0XHRcdFx0XHRcdHRvdGFsX3RpbWUgPSB0b3RhbF90aW1lLmdldFJlc3VsdCgpO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0dG90YWxfdGltZSA9ICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudG90YWxfdGltZSA/ICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudG90YWxfdGltZSA6IDA7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdCR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudG90YWxfdGltZSA9IHRvdGFsX3RpbWU7XG5cdFx0XHRcdFx0XHR0b3RhbF90aW1lID0gR2xvYmFsLmdldFRpbWVVbml0KCB0b3RhbF90aW1lICk7XG5cdFx0XHRcdFx0XHQkdGhpcy5lZGl0X3ZpZXdfdWlfZGljWyd0b3RhbF90aW1lJ10uc2V0VmFsdWUoIHRvdGFsX3RpbWUgKTtcblxuXHRcdFx0XHRcdFx0JHRoaXMub25BdmFpbGFibGVCYWxhbmNlQ2hhbmdlKCk7XG5cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKTtcbi8vXG5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMub25BdmFpbGFibGVCYWxhbmNlQ2hhbmdlKCk7XG5cdFx0XHR9XG5cblx0XHR9XG5cblx0XHRpZiAoICFkb05vdFZhbGlkYXRlICkge1xuXHRcdFx0dGhpcy52YWxpZGF0ZSgpO1xuXHRcdH1cblx0fVxuXG5cdHNldEFic2VuY2VQb2xpY3lXaGVuVXNlckNoYW5nZWQoKSB7XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciBhYnNlbmNlX3dpZGdldCA9ICR0aGlzLmVkaXRfdmlld191aV9kaWNbJ2Fic2VuY2VfcG9saWN5X2lkJ107XG5cdFx0YWJzZW5jZV93aWRnZXQuc2V0U291cmNlRGF0YSggbnVsbCApO1xuXHRcdHZhciBvbGRfdmFsdWUgPSBhYnNlbmNlX3dpZGdldC5nZXRWYWx1ZSgpO1xuXG5cdFx0dmFyIGFyZ3MgPSB7fTtcblx0XHRhcmdzLmZpbHRlcl9kYXRhID0geyBpZDogb2xkX3ZhbHVlIH07XG5cblx0XHRhcmdzID0gdGhpcy5zZXRBYnNlbmNlUG9saWN5RmlsdGVyKCBhcmdzICk7XG5cblx0XHRpZiAoIG9sZF92YWx1ZSApIHtcblxuXHRcdFx0JHRoaXMuYWJzZW5jZV9wb2xpY3lfYXBpLmdldEFic2VuY2VQb2xpY3koIGFyZ3MsIHtcblx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCB0YXNrX3Jlc3VsdCApIHtcblxuXHRcdFx0XHRcdC8vIFJldHVybmluZyBlYXJseSB0byBoZWxwIG1pdGlnYXRlICMyODg5IC0gXCJFcnJvcjogVW5jYXVnaHQgVHlwZUVycm9yOiBDYW5ub3Qgc2V0IHByb3BlcnR5ICdhYnNlbmNlX3BvbGljeV9pZCcgb2YgbnVsbFwiXG5cdFx0XHRcdFx0Ly8gVGhpcyBjYW4gaGFwcGVuIHdoZW4gdGhlIHVzZXIgc2F2ZXMgb3IgbGVhdmVzIHRoZSBwYWdlIGJlZm9yZSB0aGUgQVBJIGNhbGwgaXMgY29tcGxldGVkLlxuXHRcdFx0XHRcdGlmICggJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCA9PT0gbnVsbCB8fCAkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0dmFyIGRhdGEgPSB0YXNrX3Jlc3VsdC5nZXRSZXN1bHQoKTtcblxuXHRcdFx0XHRcdGlmICggZGF0YS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHRcdFx0YWJzZW5jZV93aWRnZXQuc2V0VmFsdWUoIG9sZF92YWx1ZSApO1xuXHRcdFx0XHRcdFx0JHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5hYnNlbmNlX3BvbGljeV9pZCA9IG9sZF92YWx1ZTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0YWJzZW5jZV93aWRnZXQuc2V0VmFsdWUoIGZhbHNlICk7XG5cdFx0XHRcdFx0XHQkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmFic2VuY2VfcG9saWN5X2lkID0gZmFsc2U7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdCR0aGlzLm9uQXZhaWxhYmxlQmFsYW5jZUNoYW5nZSgpO1xuXHRcdFx0XHRcdCR0aGlzLnZhbGlkYXRlKCk7XG5cblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLm9uQXZhaWxhYmxlQmFsYW5jZUNoYW5nZSgpO1xuXHRcdFx0dGhpcy52YWxpZGF0ZSgpO1xuXHRcdH1cblx0fVxuXG5cdC8vTWFrZSBzdXJlIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCBpcyB1cGRhdGVkIGJlZm9yZSB2YWxpZGF0ZVxuXHR2YWxpZGF0ZSgpIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciByZWNvcmQgPSB7fTtcblx0XHRpZiAoIHRoaXMuaXNfbWFzc19hZGRpbmcgKSB7XG5cdFx0XHRyZWNvcmQgPSBbXTtcblx0XHRcdCQuZWFjaCggdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXksIGZ1bmN0aW9uKCBpbmRleCwgdmFsdWUgKSB7XG5cdFx0XHRcdGlmICggdmFsdWUuaGFzT3duUHJvcGVydHkoICd1c2VyX2lkJyApICYmIHZhbHVlLmhhc093blByb3BlcnR5KCAnZGF0ZScgKSAmJiB2YWx1ZS5kYXRlICkge1xuXHRcdFx0XHRcdHZhciBjb21tb25SZWNvcmQgPSBHbG9iYWwuY2xvbmUoICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgKTtcblx0XHRcdFx0XHRkZWxldGUgY29tbW9uUmVjb3JkLnVzZXJfaWRzO1xuXHRcdFx0XHRcdGRlbGV0ZSBjb21tb25SZWNvcmQuc3RhcnRfZGF0ZXM7XG5cdFx0XHRcdFx0Y29tbW9uUmVjb3JkLmlkID0gJyc7XG5cdFx0XHRcdFx0Y29tbW9uUmVjb3JkLnVzZXJfaWQgPSB2YWx1ZS51c2VyX2lkO1xuXHRcdFx0XHRcdGNvbW1vblJlY29yZC5zdGFydF9kYXRlX3N0YW1wID0gdmFsdWUuZGF0ZTtcblx0XHRcdFx0XHRjb21tb25SZWNvcmQgPSAkdGhpcy5idWlsZE1hc3NBZGRSZWNvcmQoIGNvbW1vblJlY29yZCApO1xuXHRcdFx0XHRcdHJlY29yZC5wdXNoKCBjb21tb25SZWNvcmQgKTtcblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXHRcdH0gZWxzZSBpZiAoIHRoaXMuaXNfbWFzc19lZGl0aW5nICkge1xuXHRcdFx0Zm9yICggdmFyIGtleSBpbiB0aGlzLmVkaXRfdmlld191aV9kaWMgKSB7XG5cdFx0XHRcdGlmICggIXRoaXMuZWRpdF92aWV3X3VpX2RpYy5oYXNPd25Qcm9wZXJ0eSgga2V5ICkgKSB7XG5cdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0dmFyIHdpZGdldCA9IHRoaXMuZWRpdF92aWV3X3VpX2RpY1trZXldO1xuXHRcdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggd2lkZ2V0LmlzQ2hlY2tlZCApICkge1xuXHRcdFx0XHRcdGlmICggd2lkZ2V0LmlzQ2hlY2tlZCgpICYmIHdpZGdldC5nZXRFbmFibGVkKCkgKSB7XG5cdFx0XHRcdFx0XHRyZWNvcmRba2V5XSA9IHdpZGdldC5nZXRWYWx1ZSgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHRoaXMubWFzc19lZGl0X3JlY29yZF9pZHMubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0dmFyIGNoZWNrRmllbGRzID0gcmVjb3JkO1xuXHRcdFx0XHRyZWNvcmQgPSBbXTtcblx0XHRcdFx0JC5lYWNoKCB0aGlzLm1hc3NfZWRpdF9yZWNvcmRfaWRzLCBmdW5jdGlvbiggaW5kZXgsIHZhbHVlICkge1xuXHRcdFx0XHRcdHZhciBjb21tb25SZWNvcmQgPSBHbG9iYWwuY2xvbmUoIGNoZWNrRmllbGRzICk7XG5cdFx0XHRcdFx0Y29tbW9uUmVjb3JkLmlkID0gdmFsdWU7XG5cdFx0XHRcdFx0Y29tbW9uUmVjb3JkID0gJHRoaXMucHJvY2Vzc0FkZFJlY29yZCggY29tbW9uUmVjb3JkICk7XG5cdFx0XHRcdFx0cmVjb3JkLnB1c2goIGNvbW1vblJlY29yZCApO1xuXHRcdFx0XHR9ICk7XG5cdFx0XHRcdCQuZWFjaCggdGhpcy5zZWxlY3RfYWxsX3NoaWZ0c19hcnJheSwgZnVuY3Rpb24oIGluZGV4LCB2YWx1ZSApIHtcblx0XHRcdFx0XHRpZiAoICF2YWx1ZS5pZCB8fCB2YWx1ZS5pZCA9PSBUVFVVSUQuemVyb19pZCApIHtcblx0XHRcdFx0XHRcdHZhciBjb21tb25SZWNvcmQgPSBHbG9iYWwuY2xvbmUoIHZhbHVlICk7XG5cdFx0XHRcdFx0XHRmb3IgKCB2YXIga2V5IGluIGNoZWNrRmllbGRzICkge1xuXHRcdFx0XHRcdFx0XHRjb21tb25SZWNvcmRba2V5XSA9IGNoZWNrRmllbGRzW2tleV07XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRjb21tb25SZWNvcmQgPSAkdGhpcy5wcm9jZXNzQWRkUmVjb3JkKCBjb21tb25SZWNvcmQgKTtcblx0XHRcdFx0XHRcdHJlY29yZC5wdXNoKCBjb21tb25SZWNvcmQgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKTtcblx0XHRcdFx0cmVjb3JkID0gdGhpcy5nZXRSZWNvcmRzRnJvbVVzZXJJRHMoIHJlY29yZCApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dmFyIHJlY29yZF9hcnJheSA9IFtdO1xuXHRcdFx0XHQkLmVhY2goIHRoaXMuc2VsZWN0X2FsbF9zaGlmdHNfYXJyYXksIGZ1bmN0aW9uKCBpbmRleCwgdmFsdWUgKSB7XG5cdFx0XHRcdFx0aWYgKCAhdmFsdWUuaWQgfHwgdmFsdWUuaWQgPT0gVFRVVUlELnplcm9faWQgKSB7XG5cdFx0XHRcdFx0XHR2YXIgY29tbW9uUmVjb3JkID0gR2xvYmFsLmNsb25lKCB2YWx1ZSApO1xuXHRcdFx0XHRcdFx0Zm9yICggdmFyIGtleSBpbiByZWNvcmQgKSB7XG5cdFx0XHRcdFx0XHRcdGNvbW1vblJlY29yZFtrZXldID0gcmVjb3JkW2tleV07XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRjb21tb25SZWNvcmQgPSAkdGhpcy5wcm9jZXNzQWRkUmVjb3JkKCBjb21tb25SZWNvcmQgKTtcblx0XHRcdFx0XHRcdHJlY29yZF9hcnJheS5wdXNoKCBjb21tb25SZWNvcmQgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKTtcblx0XHRcdFx0aWYgKCByZWNvcmRfYXJyYXkubGVuZ3RoIDwgMSApIHtcblx0XHRcdFx0XHRpZiAoIHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5Lmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdFx0XHQkdGhpcy5wcm9jZXNzQWRkUmVjb3JkKCByZWNvcmQgKTtcblx0XHRcdFx0XHRcdHJlY29yZCA9IHRoaXMuZ2V0UmVjb3Jkc0Zyb21Vc2VySURzKCBbcmVjb3JkXSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRyZWNvcmQgPSByZWNvcmRfYXJyYXk7XG5cdFx0XHRcdFx0cmVjb3JkID0gdGhpcy5nZXRSZWNvcmRzRnJvbVVzZXJJRHMoIHJlY29yZCApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly9FcnJvcjogVW5jYXVnaHQgVHlwZUVycm9yOiBDYW5ub3QgcmVhZCBwcm9wZXJ0eSAnaW5kZXhPZicgb2YgdW5kZWZpbmVkIGluIGludGVyZmFjZS9odG1sNS8jIW09U2NoZWR1bGUmZGF0ZT0yMDE1MTIwNCZtb2RlPWRheSBsaW5lIDE5NTRcblx0XHRcdGlmICggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICYmIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5zdGFydF9kYXRlX3N0YW1wICYmXG5cdFx0XHRcdCggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXAuaW5kZXhPZiggJyAtICcgKSA+IDAgfHxcblx0XHRcdFx0XHQkLnR5cGUoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5zdGFydF9kYXRlX3N0YW1wICkgPT09ICdhcnJheScgKSApIHtcblx0XHRcdFx0aWYgKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3RhcnRfZGF0ZV9zdGFtcC5pbmRleE9mKCAnIC0gJyApID4gMCApIHtcblx0XHRcdFx0XHR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3RhcnRfZGF0ZV9zdGFtcCA9IHRoaXMucGFyc2VyRGF0ZXNSYW5nZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXAgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZWNvcmQgPSBbXTtcblx0XHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXAubGVuZ3RoOyBpKysgKSB7XG5cdFx0XHRcdFx0dmFyIGNvbW1vblJlY29yZCA9IEdsb2JhbC5jbG9uZSggJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCApO1xuXHRcdFx0XHRcdGNvbW1vblJlY29yZC5zdGFydF9kYXRlX3N0YW1wID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXBbaV07XG5cdFx0XHRcdFx0aWYgKCB0aGlzLnNlbGVjdF9jZWxsc19BcnJheS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHRcdFx0JHRoaXMucHJvY2Vzc0FkZFJlY29yZCggY29tbW9uUmVjb3JkICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJlY29yZC5wdXNoKCBjb21tb25SZWNvcmQgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZWNvcmQgPSB0aGlzLmdldFJlY29yZHNGcm9tVXNlcklEcyggcmVjb3JkICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyZWNvcmQgPSBHbG9iYWwuY2xvbmUoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCApO1xuXHRcdFx0XHRpZiAoIHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5Lmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdFx0JHRoaXMucHJvY2Vzc0FkZFJlY29yZCggcmVjb3JkICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmVjb3JkID0gdGhpcy5nZXRSZWNvcmRzRnJvbVVzZXJJRHMoIFtyZWNvcmRdICk7XG5cdFx0XHR9XG5cblx0XHR9XG5cdFx0dGhpcy5hcGlbJ3ZhbGlkYXRlJyArIHRoaXMuYXBpLmtleV9uYW1lXSggcmVjb3JkLCB7XG5cdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlc3VsdCApIHtcblx0XHRcdFx0JHRoaXMudmFsaWRhdGVSZXN1bHQoIHJlc3VsdCApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fVxuXG5cdGdldFJlY29yZHNGcm9tVXNlcklEcyggcmVjb3JkICkge1xuXHRcdHZhciByZXN1bHQgPSBbXTtcblxuXHRcdGZvciAoIHZhciBqID0gMDsgaiA8IHJlY29yZC5sZW5ndGg7IGorKyApIHtcblx0XHRcdHZhciBjb21tb25fcmVjb3JkID0gcmVjb3JkW2pdO1xuXG5cdFx0XHRpZiAoIGNvbW1vbl9yZWNvcmQudXNlcl9pZHMgJiYgY29tbW9uX3JlY29yZC51c2VyX2lkcy5sZW5ndGggPiAwICkge1xuXHRcdFx0XHRmb3IgKCB2YXIgeSA9IDA7IHkgPCBjb21tb25fcmVjb3JkLnVzZXJfaWRzLmxlbmd0aDsgeSsrICkge1xuXHRcdFx0XHRcdHZhciB1c2VyX2lkID0gY29tbW9uX3JlY29yZC51c2VyX2lkc1t5XTtcblx0XHRcdFx0XHRpZiAoIEdsb2JhbC5pc09iamVjdCggdXNlcl9pZCApICYmIHVzZXJfaWQuaWQgKSB7XG5cdFx0XHRcdFx0XHR1c2VyX2lkID0gdXNlcl9pZC5pZDtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR2YXIgbmV3X2NvbW1vbl9yZWNvcmQgPSBHbG9iYWwuY2xvbmUoIGNvbW1vbl9yZWNvcmQgKTtcblx0XHRcdFx0XHRuZXdfY29tbW9uX3JlY29yZC51c2VyX2lkID0gdXNlcl9pZDtcblx0XHRcdFx0XHRyZXN1bHQucHVzaCggbmV3X2NvbW1vbl9yZWNvcmQgKTtcblxuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdGlmICggKCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkIHx8ICF0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgfHwgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkID09IFRUVVVJRC56ZXJvX2lkICkgJiYgIXRoaXMuaXNfbWFzc19lZGl0aW5nICkge1xuXHRcdFx0XHRcdGNvbW1vbl9yZWNvcmQudXNlcl9pZCA9IFRUVVVJRC56ZXJvX2lkO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmVzdWx0LnB1c2goIGNvbW1vbl9yZWNvcmQgKTtcblxuXHRcdFx0fVxuXG5cdFx0fVxuXG5cdFx0cmV0dXJuIHJlc3VsdDtcblx0fVxuXG5cdG9uU2F2ZUFuZENvcHkoIGlnbm9yZVdhcm5pbmcgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHRpZiAoICFHbG9iYWwuaXNTZXQoIGlnbm9yZVdhcm5pbmcgKSApIHtcblx0XHRcdGlnbm9yZVdhcm5pbmcgPSBmYWxzZTtcblx0XHR9XG5cdFx0dGhpcy5pc19hZGQgPSB0cnVlO1xuXHRcdHRoaXMuaXNfY2hhbmdlZCA9IGZhbHNlO1xuXHRcdExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfZG9pbmdfY29udGV4dF9hY3Rpb24gPSAnc2F2ZV9hbmRfY29weSc7XG5cdFx0dmFyIHJlY29yZCA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZDtcblx0XHRyZWNvcmQgPSB0aGlzLnByb2Nlc3NBZGRSZWNvcmQoIHJlY29yZCApO1xuXHRcdHJlY29yZCA9IHRoaXMuZ2V0UmVjb3Jkc0Zyb21Vc2VySURzKCBbcmVjb3JkXSApO1xuXG5cdFx0aWYgKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3RhcnRfZGF0ZV9zdGFtcC5pbmRleE9mKCAnIC0gJyApID4gMCB8fFxuXHRcdFx0JC50eXBlKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3RhcnRfZGF0ZV9zdGFtcCApID09PSAnYXJyYXknICkge1xuXG5cdFx0XHRpZiAoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5zdGFydF9kYXRlX3N0YW1wLmluZGV4T2YoICcgLSAnICkgPiAwICkge1xuXHRcdFx0XHR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3RhcnRfZGF0ZV9zdGFtcCA9IHRoaXMucGFyc2VyRGF0ZXNSYW5nZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXAgKTtcblx0XHRcdH1cblxuXHRcdFx0cmVjb3JkID0gW107XG5cdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3RhcnRfZGF0ZV9zdGFtcC5sZW5ndGg7IGkrKyApIHtcblx0XHRcdFx0dmFyIGNvbW1vblJlY29yZCA9IEdsb2JhbC5jbG9uZSggJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCApO1xuXHRcdFx0XHRjb21tb25SZWNvcmQuc3RhcnRfZGF0ZV9zdGFtcCA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5zdGFydF9kYXRlX3N0YW1wW2ldO1xuXHRcdFx0XHRjb21tb25SZWNvcmQgPSB0aGlzLnByb2Nlc3NBZGRSZWNvcmQoIGNvbW1vblJlY29yZCApO1xuXHRcdFx0XHRyZWNvcmQucHVzaCggY29tbW9uUmVjb3JkICk7XG5cdFx0XHR9XG5cdFx0XHRyZWNvcmQgPSB0aGlzLmdldFJlY29yZHNGcm9tVXNlcklEcyggcmVjb3JkICk7XG5cdFx0fVxuXG5cdFx0dGhpcy5jbGVhck5hdmlnYXRpb25EYXRhKCk7XG5cdFx0dGhpcy5hcGlbJ3NldCcgKyB0aGlzLmFwaS5rZXlfbmFtZV0oIHJlY29yZCwgZmFsc2UsIGZhbHNlLCBpZ25vcmVXYXJuaW5nLCB7XG5cdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlc3VsdCApIHtcblx0XHRcdFx0aWYgKCAkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICkge1xuXHRcdFx0XHRcdHZhciBjdXJyZW50X2RhdGVfc3RyID0gJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5zdGFydF9kYXRlX3N0YW1wO1xuXG5cdFx0XHRcdFx0aWYgKCAkLnR5cGUoIGN1cnJlbnRfZGF0ZV9zdHIgKSA9PT0gJ2FycmF5JyApIHtcblx0XHRcdFx0XHRcdGN1cnJlbnRfZGF0ZV9zdHIgPSBjdXJyZW50X2RhdGVfc3RyW2N1cnJlbnRfZGF0ZV9zdHIubGVuZ3RoIC0gMV07XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0dmFyIGN1cnJlbnRfZGF0ZSA9IEdsb2JhbC5zdHJUb0RhdGUoIGN1cnJlbnRfZGF0ZV9zdHIgKTtcblx0XHRcdFx0XHR2YXIgbmV4dF9kYXRlID0gbmV3IERhdGUoIG5ldyBEYXRlKCBjdXJyZW50X2RhdGUuZ2V0VGltZSgpICkuc2V0RGF0ZSggY3VycmVudF9kYXRlLmdldERhdGUoKSArIDEgKSApO1xuXG5cdFx0XHRcdFx0JHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5zdGFydF9kYXRlX3N0YW1wID0gbmV4dF9kYXRlLmZvcm1hdCgpO1xuXG5cdFx0XHRcdFx0JHRoaXMub25TYXZlQW5kQ29weVJlc3VsdCggcmVzdWx0ICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cblxuXHRvblNhdmVBbmROZXdDbGljayggaWdub3JlV2FybmluZyApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdGlmICggIUdsb2JhbC5pc1NldCggaWdub3JlV2FybmluZyApICkge1xuXHRcdFx0aWdub3JlV2FybmluZyA9IGZhbHNlO1xuXHRcdH1cblx0XHR0aGlzLnNldEN1cnJlbnRFZGl0Vmlld1N0YXRlKCAnbmV3JyApO1xuXHRcdHZhciByZWNvcmQgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQ7XG5cdFx0cmVjb3JkID0gdGhpcy5wcm9jZXNzQWRkUmVjb3JkKCByZWNvcmQgKTtcblx0XHRyZWNvcmQgPSB0aGlzLmdldFJlY29yZHNGcm9tVXNlcklEcyggW3JlY29yZF0gKTtcblxuXHRcdGlmICggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXAuaW5kZXhPZiggJyAtICcgKSA+IDAgfHxcblx0XHRcdCQudHlwZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXAgKSA9PT0gJ2FycmF5JyApIHtcblxuXHRcdFx0aWYgKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3RhcnRfZGF0ZV9zdGFtcC5pbmRleE9mKCAnIC0gJyApID4gMCApIHtcblx0XHRcdFx0dGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXAgPSB0aGlzLnBhcnNlckRhdGVzUmFuZ2UoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5zdGFydF9kYXRlX3N0YW1wICk7XG5cdFx0XHR9XG5cblx0XHRcdHJlY29yZCA9IFtdO1xuXHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXAubGVuZ3RoOyBpKysgKSB7XG5cdFx0XHRcdHZhciBjb21tb25SZWNvcmQgPSBHbG9iYWwuY2xvbmUoICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgKTtcblx0XHRcdFx0Y29tbW9uUmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXAgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3RhcnRfZGF0ZV9zdGFtcFtpXTtcblx0XHRcdFx0Y29tbW9uUmVjb3JkID0gdGhpcy5wcm9jZXNzQWRkUmVjb3JkKCBjb21tb25SZWNvcmQgKTtcblx0XHRcdFx0cmVjb3JkLnB1c2goIGNvbW1vblJlY29yZCApO1xuXHRcdFx0fVxuXHRcdFx0cmVjb3JkID0gdGhpcy5nZXRSZWNvcmRzRnJvbVVzZXJJRHMoIHJlY29yZCApO1xuXHRcdH1cblxuXHRcdHRoaXMuYXBpWydzZXQnICsgdGhpcy5hcGkua2V5X25hbWVdKCByZWNvcmQsIGZhbHNlLCBpZ25vcmVXYXJuaW5nLCB7XG5cdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlc3VsdCApIHtcblx0XHRcdFx0JHRoaXMub25TYXZlQW5kTmV3UmVzdWx0KCByZXN1bHQgKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cblxuXHRidWlsZFNlbGVjdGVkQ2VsbHNSZWNvcmQoKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgcmV0dmFsID0gW107XG5cdFx0JC5lYWNoKCB0aGlzLnNlbGVjdF9jZWxsc19BcnJheSwgZnVuY3Rpb24oIGluZGV4LCB2YWx1ZSApIHtcblx0XHRcdGlmICggdmFsdWUuaGFzT3duUHJvcGVydHkoICd1c2VyX2lkJyApICYmIHZhbHVlLmhhc093blByb3BlcnR5KCAnZGF0ZScgKSAmJiB2YWx1ZS5kYXRlICkge1xuXHRcdFx0XHR2YXIgY29tbW9uUmVjb3JkID0gR2xvYmFsLmNsb25lKCAkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICk7XG5cdFx0XHRcdGRlbGV0ZSBjb21tb25SZWNvcmQudXNlcl9pZHM7XG5cdFx0XHRcdGRlbGV0ZSBjb21tb25SZWNvcmQuc3RhcnRfZGF0ZXM7XG5cdFx0XHRcdGNvbW1vblJlY29yZC5pZCA9ICcnO1xuXHRcdFx0XHRjb21tb25SZWNvcmQudXNlcl9pZCA9IHZhbHVlLnVzZXJfaWQ7XG5cdFx0XHRcdGNvbW1vblJlY29yZC5zdGFydF9kYXRlX3N0YW1wID0gdmFsdWUuZGF0ZTtcblx0XHRcdFx0Y29tbW9uUmVjb3JkID0gJHRoaXMuYnVpbGRNYXNzQWRkUmVjb3JkKCBjb21tb25SZWNvcmQgKTtcblxuXHRcdFx0XHRyZXR2YWwucHVzaCggY29tbW9uUmVjb3JkICk7XG5cdFx0XHR9XG5cblx0XHR9ICk7XG5cblx0XHRyZXR1cm4gcmV0dmFsO1xuXHR9XG5cblx0YnVpbGRNYXNzQWRkUmVjb3JkKCByZWNvcmQgKSB7XG5cdFx0dmFyIG1hc3NBZGRBcmdzID0gdGhpcy5fY3JlYXRlUGFyYW1ldGVyc0ZvckFkZCgpO1xuXHRcdGZvciAoIHZhciBpID0gMCwgbiA9IG1hc3NBZGRBcmdzLmxlbmd0aDsgaSA8IG47IGkrKyApIHtcblx0XHRcdHZhciBpdGVtID0gbWFzc0FkZEFyZ3NbaV07XG5cdFx0XHRpZiAoIHJlY29yZC51c2VyX2lkID09PSBpdGVtLnVzZXJfaWQgKSB7XG5cdFx0XHRcdHJlY29yZC5icmFuY2hfaWQgPT0gJy0yJyA/ICggcmVjb3JkLmJyYW5jaF9pZCA9IGl0ZW0uYnJhbmNoX2lkICkgOiByZWNvcmQuYnJhbmNoX2lkO1xuXHRcdFx0XHRyZWNvcmQuZGVwYXJ0bWVudF9pZCA9PSAnLTInID8gKCByZWNvcmQuZGVwYXJ0bWVudF9pZCA9IGl0ZW0uZGVwYXJ0bWVudF9pZCApIDogcmVjb3JkLmRlcGFydG1lbnRfaWQ7XG5cdFx0XHRcdHJlY29yZC5qb2JfaWQgPT0gJy0yJyA/ICggcmVjb3JkLmpvYl9pZCA9IGl0ZW0uam9iX2lkICkgOiByZWNvcmQuam9iX2lkO1xuXHRcdFx0XHRyZWNvcmQuam9iX2l0ZW1faWQgPT0gJy0yJyA/ICggcmVjb3JkLmpvYl9pdGVtX2lkID0gaXRlbS5qb2JfaXRlbV9pZCApIDogcmVjb3JkLmpvYl9pdGVtX2lkO1xuXHRcdFx0XHRyZWNvcmQucHVuY2hfdGFnX2lkID09ICctMicgPyAoIHJlY29yZC5wdW5jaF90YWdfaWQgPSBpdGVtLnB1bmNoX3RhZ19pZCApIDogcmVjb3JkLnB1bmNoX3RhZ19pZDtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHJlY29yZDtcblx0fVxuXG5cdHByb2Nlc3NBZGRSZWNvcmQoIHJlY29yZCApIHtcblx0XHR2YXIgbWFzc0FkZEFyZ3MgPSB0aGlzLl9jcmVhdGVQYXJhbWV0ZXJzRm9yQWRkKCk7XG5cdFx0Zm9yICggdmFyIGkgPSAwLCBuID0gbWFzc0FkZEFyZ3MubGVuZ3RoOyBpIDwgbjsgaSsrICkge1xuXHRcdFx0dmFyIGl0ZW0gPSBtYXNzQWRkQXJnc1tpXTtcblx0XHRcdHJlY29yZC5icmFuY2hfaWQgPT0gJy0yJyA/ICggcmVjb3JkLmJyYW5jaF9pZCA9IGl0ZW0uYnJhbmNoX2lkICkgOiByZWNvcmQuYnJhbmNoX2lkO1xuXHRcdFx0cmVjb3JkLmRlcGFydG1lbnRfaWQgPT0gJy0yJyA/ICggcmVjb3JkLmRlcGFydG1lbnRfaWQgPSBpdGVtLmRlcGFydG1lbnRfaWQgKSA6IHJlY29yZC5kZXBhcnRtZW50X2lkO1xuXHRcdFx0cmVjb3JkLmpvYl9pZCA9PSAnLTInID8gKCByZWNvcmQuam9iX2lkID0gaXRlbS5qb2JfaWQgKSA6IHJlY29yZC5qb2JfaWQ7XG5cdFx0XHRyZWNvcmQuam9iX2l0ZW1faWQgPT0gJy0yJyA/ICggcmVjb3JkLmpvYl9pdGVtX2lkID0gaXRlbS5qb2JfaXRlbV9pZCApIDogcmVjb3JkLmpvYl9pdGVtX2lkO1xuXHRcdFx0cmVjb3JkLnB1bmNoX3RhZ19pZCA9PSAnLTInID8gKCByZWNvcmQucHVuY2hfdGFnX2lkID0gaXRlbS5wdW5jaF90YWdfaWQgKSA6IHJlY29yZC5wdW5jaF90YWdfaWQ7XG5cdFx0XHRicmVhaztcblx0XHR9XG5cdFx0cmV0dXJuIHJlY29yZDtcblx0fVxuXG5cdGdldFNlbGVjdGVkSWQoIHJlY29yZCwgZmllbGQsIG1hc3NBZGRBcmdzICkge1xuXHRcdGZvciAoIHZhciBpID0gMCwgbiA9IG1hc3NBZGRBcmdzLmxlbmd0aDsgaSA8IG47IGkrKyApIHtcblx0XHRcdHZhciBpdGVtID0gbWFzc0FkZEFyZ3NbaV07XG5cdFx0XHRpZiAoIHJlY29yZC51c2VyX2lkID09PSBpdGVtLnVzZXJfaWQgKSB7XG5cdFx0XHRcdHJlY29yZFtmaWVsZF0gPSBpdGVtW2ZpZWxkXTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRvblNhdmVBbmRDb250aW51ZSggaWdub3JlV2FybmluZyApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdGlmICggIUdsb2JhbC5pc1NldCggaWdub3JlV2FybmluZyApICkge1xuXHRcdFx0aWdub3JlV2FybmluZyA9IGZhbHNlO1xuXHRcdH1cblx0XHR0aGlzLmlzX2NoYW5nZWQgPSBmYWxzZTtcblx0XHR0aGlzLmlzX2FkZCA9IGZhbHNlO1xuXHRcdExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfZG9pbmdfY29udGV4dF9hY3Rpb24gPSAnc2F2ZV9hbmRfY29udGludWUnO1xuXHRcdHZhciByZWNvcmQgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQ7XG5cdFx0cmVjb3JkID0gdGhpcy5wcm9jZXNzQWRkUmVjb3JkKCByZWNvcmQgKTtcblx0XHRyZWNvcmQgPSB0aGlzLnVuaWZvcm1WYXJpYWJsZSggcmVjb3JkICk7XG5cblx0XHRpZiAoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5zdGFydF9kYXRlX3N0YW1wICYmICggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXAuaW5kZXhPZiggJyAtICcgKSA+IDAgfHwgJC50eXBlKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3RhcnRfZGF0ZV9zdGFtcCApID09PSAnYXJyYXknICkgKSB7XG5cdFx0XHRpZiAoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5zdGFydF9kYXRlX3N0YW1wLmluZGV4T2YoICcgLSAnICkgPiAwICkge1xuXHRcdFx0XHR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3RhcnRfZGF0ZV9zdGFtcCA9IHRoaXMucGFyc2VyRGF0ZXNSYW5nZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXAgKTtcblx0XHRcdH1cblxuXHRcdFx0cmVjb3JkID0gW107XG5cdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3RhcnRfZGF0ZV9zdGFtcC5sZW5ndGg7IGkrKyApIHtcblx0XHRcdFx0dmFyIGNvbW1vblJlY29yZCA9IEdsb2JhbC5jbG9uZSggJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCApO1xuXHRcdFx0XHRjb21tb25SZWNvcmQuc3RhcnRfZGF0ZV9zdGFtcCA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5zdGFydF9kYXRlX3N0YW1wW2ldO1xuXHRcdFx0XHRjb21tb25SZWNvcmQgPSB0aGlzLnByb2Nlc3NBZGRSZWNvcmQoIGNvbW1vblJlY29yZCApO1xuXHRcdFx0XHRyZWNvcmQucHVzaCggY29tbW9uUmVjb3JkICk7XG5cdFx0XHR9XG5cdFx0XHRyZWNvcmQgPSB0aGlzLmdldFJlY29yZHNGcm9tVXNlcklEcyggcmVjb3JkICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJlY29yZCA9IHRoaXMuZ2V0UmVjb3Jkc0Zyb21Vc2VySURzKCBbcmVjb3JkXSApO1xuXHRcdH1cblxuXHRcdHRoaXMuYXBpWydzZXQnICsgdGhpcy5hcGkua2V5X25hbWVdKCByZWNvcmQsIGZhbHNlLCBpZ25vcmVXYXJuaW5nLCB7XG5cdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlc3VsdCApIHtcblx0XHRcdFx0JHRoaXMucHJldmlvdXNfYWJzZW5jZV9wb2xpY3lfaWQgPSBmYWxzZTtcblx0XHRcdFx0JHRoaXMub25TYXZlQW5kQ29udGludWVSZXN1bHQoIHJlc3VsdCApO1xuXG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cblx0b25TYXZlQ2xpY2soIGlnbm9yZVdhcm5pbmcgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgcmVjb3JkO1xuXHRcdGlmICggIUdsb2JhbC5pc1NldCggaWdub3JlV2FybmluZyApICkge1xuXHRcdFx0aWdub3JlV2FybmluZyA9IGZhbHNlO1xuXHRcdH1cblx0XHRMb2NhbENhY2hlRGF0YS5jdXJyZW50X2RvaW5nX2NvbnRleHRfYWN0aW9uID0gJ3NhdmUnO1xuXG5cdFx0aWYgKCB0aGlzLmlzX21hc3NfYWRkaW5nICkge1xuXHRcdFx0cmVjb3JkID0gdGhpcy5idWlsZFNlbGVjdGVkQ2VsbHNSZWNvcmQoKTtcblx0XHR9IGVsc2UgaWYgKCB0aGlzLmlzX21hc3NfZWRpdGluZyApIHtcblxuXHRcdFx0dmFyIGNoZWNrRmllbGRzID0gdGhpcy5nZXRDaGFuZ2VkRmllbGRzKCk7XG5cblx0XHRcdHJlY29yZCA9IFtdO1xuXG5cdFx0XHQkLmVhY2goIHRoaXMubWFzc19lZGl0X3JlY29yZF9pZHMsIGZ1bmN0aW9uKCBpbmRleCwgdmFsdWUgKSB7XG5cdFx0XHRcdHZhciBjb21tb25SZWNvcmQgPSBHbG9iYWwuY2xvbmUoIGNoZWNrRmllbGRzICk7XG5cdFx0XHRcdGNvbW1vblJlY29yZC5pZCA9IHZhbHVlO1xuXHRcdFx0XHRjb21tb25SZWNvcmQgPSAkdGhpcy5wcm9jZXNzQWRkUmVjb3JkKCBjb21tb25SZWNvcmQgKTtcblx0XHRcdFx0cmVjb3JkLnB1c2goIGNvbW1vblJlY29yZCApO1xuXG5cdFx0XHR9ICk7XG5cblx0XHRcdCQuZWFjaCggdGhpcy5zZWxlY3RfYWxsX3NoaWZ0c19hcnJheSwgZnVuY3Rpb24oIGluZGV4LCB2YWx1ZSApIHtcblx0XHRcdFx0aWYgKCAhdmFsdWUuaWQgfHwgdmFsdWUuaWQgPT0gVFRVVUlELnplcm9faWQgKSB7XG5cdFx0XHRcdFx0dmFyIGNvbW1vblJlY29yZCA9IEdsb2JhbC5jbG9uZSggdmFsdWUgKTtcblx0XHRcdFx0XHRmb3IgKCB2YXIga2V5IGluIGNoZWNrRmllbGRzICkge1xuXHRcdFx0XHRcdFx0Y29tbW9uUmVjb3JkW2tleV0gPSBjaGVja0ZpZWxkc1trZXldO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRjb21tb25SZWNvcmQgPSAkdGhpcy5wcm9jZXNzQWRkUmVjb3JkKCBjb21tb25SZWNvcmQgKTtcblx0XHRcdFx0XHRyZWNvcmQucHVzaCggY29tbW9uUmVjb3JkICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fSApO1xuXG5cdFx0fSBlbHNlIGlmICggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXAuaW5kZXhPZiggJyAtICcgKSA+IDAgfHxcblx0XHRcdCQudHlwZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXAgKSA9PT0gJ2FycmF5JyApIHtcblxuXHRcdFx0aWYgKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3RhcnRfZGF0ZV9zdGFtcC5pbmRleE9mKCAnIC0gJyApID4gMCApIHtcblx0XHRcdFx0dGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXAgPSB0aGlzLnBhcnNlckRhdGVzUmFuZ2UoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5zdGFydF9kYXRlX3N0YW1wICk7XG5cdFx0XHR9XG5cblx0XHRcdHJlY29yZCA9IFtdO1xuXHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXAubGVuZ3RoOyBpKysgKSB7XG5cdFx0XHRcdHZhciBjb21tb25SZWNvcmQgPSBHbG9iYWwuY2xvbmUoICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgKTtcblx0XHRcdFx0Y29tbW9uUmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXAgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3RhcnRfZGF0ZV9zdGFtcFtpXTtcblx0XHRcdFx0Y29tbW9uUmVjb3JkID0gJHRoaXMucHJvY2Vzc0FkZFJlY29yZCggY29tbW9uUmVjb3JkICk7XG5cdFx0XHRcdHJlY29yZC5wdXNoKCBjb21tb25SZWNvcmQgKTtcblx0XHRcdH1cblxuXHRcdFx0cmVjb3JkID0gdGhpcy5nZXRSZWNvcmRzRnJvbVVzZXJJRHMoIHJlY29yZCApO1xuXG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0cmVjb3JkID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkO1xuXHRcdFx0cmVjb3JkID0gJHRoaXMucHJvY2Vzc0FkZFJlY29yZCggcmVjb3JkICk7XG5cdFx0XHRyZWNvcmQgPSB0aGlzLmdldFJlY29yZHNGcm9tVXNlcklEcyggW3JlY29yZF0gKTtcblxuXHRcdH1cblxuXHRcdHRoaXMuYXBpWydzZXQnICsgdGhpcy5hcGkua2V5X25hbWVdKCByZWNvcmQsIGZhbHNlLCBpZ25vcmVXYXJuaW5nLCB7XG5cdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlc3VsdCApIHtcblx0XHRcdFx0aWYgKCByZXN1bHQuaXNWYWxpZCgpICkge1xuXHRcdFx0XHRcdHZhciByZXN1bHRfZGF0YSA9IHJlc3VsdC5nZXRSZXN1bHQoKTtcblx0XHRcdFx0XHQvLyMyNTcxIC0gQ2Fubm90IHJlYWQgcHJvcGVydHkgJ2lkJyBvZiBudWxsXG5cdFx0XHRcdFx0aWYgKCByZXN1bHRfZGF0YSA9PT0gdHJ1ZSAmJiAkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICkge1xuXHRcdFx0XHRcdFx0JHRoaXMucmVmcmVzaF9pZCA9ICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQ7XG5cdFx0XHRcdFx0fSBlbHNlIGlmICggVFRVVUlELmlzVVVJRCggcmVzdWx0X2RhdGEgKSAmJiByZXN1bHRfZGF0YSAhPSBUVFVVSUQuemVyb19pZCAmJiByZXN1bHRfZGF0YSAhPSBUVFVVSUQubm90X2V4aXN0X2lkICkge1xuXHRcdFx0XHRcdFx0JHRoaXMucmVmcmVzaF9pZCA9IHJlc3VsdF9kYXRhO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHQkdGhpcy5zZWFyY2goIGZhbHNlLCBmYWxzZSApO1xuXHRcdFx0XHRcdCR0aGlzLnByZXZpb3VzX2Fic2VuY2VfcG9saWN5X2lkID0gZmFsc2U7XG5cblx0XHRcdFx0XHQkdGhpcy5yZW1vdmVFZGl0VmlldygpO1xuXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Ly9CVUcjMjA3MyAtIFB1bGxlZCBvdXQgdGhlIGVycm9yIG1lc3NhZ2UgYm94IHRoYXQgd2FzIHNob3dpbmcgdGhlIHJlc3VsdCBhcnJheSBhcyBpdHMgXCJ0b1N0cmluZ1wiIHJlcHJlc2VudGF0aW9uLiAoW29iamVjdF1bb2JqZWN0XSk7XG5cdFx0XHRcdFx0JHRoaXMuc2V0RXJyb3JUaXBzKCByZXN1bHQgKTtcblx0XHRcdFx0XHQkdGhpcy5zZXRFcnJvck1lbnUoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cblx0cmVtb3ZlRWRpdFZpZXcoKSB7XG5cdFx0c3VwZXIucmVtb3ZlRWRpdFZpZXcoKTtcblxuXHRcdHRoaXMuc2V0TW92ZU9yRHJvcE1vZGUoIHRoaXMuc2VsZWN0X2RyYWdfbWVudV9pZCA/IHRoaXMuc2VsZWN0X2RyYWdfbWVudV9pZCA6ICdtb3ZlJyApO1xuXHRcdHRoaXMuc2VsZWN0ZWRfdXNlcl9pZHMgPSBbXTtcblx0XHR0aGlzLmlzX21hc3NfYWRkaW5nID0gZmFsc2U7XG5cdH1cblxuXHRzZXRFZGl0TWVudVNhdmVBbmRDb250aW51ZUljb24oIGNvbnRleHRfYnRuICkge1xuXHRcdHRoaXMuc2F2ZUFuZENvbnRpbnVlVmFsaWRhdGUoIGNvbnRleHRfYnRuICk7XG5cblx0XHRpZiAoIHRoaXMuaXNfbWFzc19lZGl0aW5nIHx8IHRoaXMuaXNfdmlld2luZyB8fCB0aGlzLmlzX21hc3NfYWRkaW5nIHx8IHRoaXMuaXNNYXNzRW1wbG95ZWVPckRhdGUoKSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fVxuXHR9XG5cblx0aXNNYXNzRW1wbG95ZWVPckRhdGUoKSB7XG5cblx0XHRpZiAoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCAmJiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3RhcnRfZGF0ZV9zdGFtcHMgJiYgKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3RhcnRfZGF0ZV9zdGFtcHMuaW5kZXhPZiggJyAtICcgKSA+IDAgfHxcblx0XHRcdCQudHlwZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXBzICkgPT09ICdhcnJheScgJiYgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXBzLmxlbmd0aCA+IDFcblx0XHQpICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgJiYgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnVzZXJfaWRzICYmIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC51c2VyX2lkcy5sZW5ndGggPiAxICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0c2V0RWRpdE1lbnVTYXZlQW5kQWRkSWNvbiggY29udGV4dF9idG4gKSB7XG5cdFx0dGhpcy5zYXZlQW5kTmV3VmFsaWRhdGUoIGNvbnRleHRfYnRuICk7XG5cblx0XHRpZiAoIHRoaXMuaXNfdmlld2luZyB8fCB0aGlzLmlzX21hc3NfZWRpdGluZyB8fCB0aGlzLmlzX21hc3NfYWRkaW5nICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRzZXRFZGl0TWVudVNhdmVBbmRDb3B5SWNvbiggY29udGV4dF9idG4gKSB7XG5cdFx0dGhpcy5zYXZlQW5kQ29weVZhbGlkYXRlKCBjb250ZXh0X2J0biApO1xuXG5cdFx0aWYgKCB0aGlzLmlzX3ZpZXdpbmcgfHwgdGhpcy5pc19tYXNzX2VkaXRpbmcgfHwgdGhpcy5pc19tYXNzX2FkZGluZyApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fVxuXHR9XG5cblx0b25UeXBlQ2hhbmdlKCBnZXRSYXRlICkge1xuXHRcdGlmICggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXR1c19pZCA9PSAyMCApIHtcblx0XHRcdHRoaXMuYXR0YWNoRWxlbWVudCggJ2Fic2VuY2VfcG9saWN5X2lkJyApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLmRldGFjaEVsZW1lbnQoICdhYnNlbmNlX3BvbGljeV9pZCcgKTtcblx0XHR9XG5cdH1cblxuXHRzZXRFZGl0Vmlld0RhdGEoKSB7XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHN1cGVyLnNldEVkaXRWaWV3RGF0YSgpOyAvL1NldCBOYXZpZ2F0aW9uXG5cdFx0JHRoaXMub25UeXBlQ2hhbmdlKCBmYWxzZSApO1xuXHR9XG5cblx0Y2hlY2tPcGVuUGVybWlzc2lvbigpIHtcblx0XHRpZiAoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpID49IDE1ICYmIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCAnc2NoZWR1bGUnLCAndmlld19vcGVuJyApICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0Z2V0Q3VzdG9tRmllbGRSZWZlcmVuY2VGaWVsZCgpIHtcblx0XHRyZXR1cm4gJ25vdGUnO1xuXHR9XG5cblx0YnVpbGRFZGl0Vmlld1VJKCkge1xuXG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdHZhciBmb3JtX2l0ZW1faW5wdXQ7XG5cdFx0dmFyIHdpZGdldENvbnRhaW5lcjtcblxuXHRcdC8vICNWdWVDb250ZXh0TWVudSMgQWZ0ZXIgd2UgYWRkIHRoZSBlZGl0X3ZpZXcgdG8gdGhlIHBhZ2UgaW4gaW5pdEVkaXRWaWV3VUkoKSwgYWRkIHRoZSBjb250ZXh0IG1lbnUgKFZ1ZSBuZWVkcyBhIHZhbGlkIGlkIGluIGRvbSlcblx0XHRpZiggQ29udGV4dE1lbnVNYW5hZ2VyLmdldE1lbnUoIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCApID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHR0aGlzLmJ1aWxkQ29udGV4dE1lbnUoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0RGVidWcuV2FybiggJ0NvbnRleHQgTWVudSAoJysgdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkICsnKSBhbHJlYWR5IGV4aXN0cyBmb3I6ICcrIHRoaXMudmlld0lkLCAnU2NoZWR1bGVWaWV3Q29udHJvbGxlci5qcycsICdTY2hlZHVsZVZpZXdDb250cm9sbGVyJywgJ2J1aWxkRWRpdFZpZXdVSScsIDEwICk7XG5cdFx0fVxuXG5cdFx0dGhpcy5lZGl0X3ZpZXdfY2xvc2VfaWNvbiA9IHRoaXMuZWRpdF92aWV3LmZpbmQoICcuY2xvc2UtaWNvbicgKTtcblx0XHR0aGlzLmVkaXRfdmlld19jbG9zZV9pY29uLmhpZGUoKTtcblx0XHR0aGlzLmVkaXRfdmlld19jbG9zZV9pY29uLmNsaWNrKCBmdW5jdGlvbigpIHtcblx0XHRcdCR0aGlzLm9uQ2xvc2VJY29uQ2xpY2soKTtcblx0XHR9ICk7XG5cblx0XHR2YXIgdGFiX21vZGVsID0ge1xuXHRcdFx0J3RhYl9zY2hlZHVsZSc6IHsgJ2xhYmVsJzogJC5pMThuLl8oICdTY2hlZHVsZScgKSB9LFxuXHRcdFx0J3RhYl9hdWRpdCc6IHRydWUsXG5cdFx0fTtcblx0XHR0aGlzLnNldFRhYk1vZGVsKCB0YWJfbW9kZWwgKTtcblxuXHRcdC8vVGFiIDAgc3RhcnRcblxuXHRcdHZhciB0YWJfc2NoZWR1bGUgPSB0aGlzLmVkaXRfdmlld190YWIuZmluZCggJyN0YWJfc2NoZWR1bGUnICk7XG5cblx0XHR2YXIgdGFiX3NjaGVkdWxlX2NvbHVtbjEgPSB0YWJfc2NoZWR1bGUuZmluZCggJy5maXJzdC1jb2x1bW4nICk7XG5cblx0XHQvL0VtcGxveWVlXG5cblx0XHR2YXIgcHJvZHVjdGlvbl9lZGl0aW9uX2lkID0gR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCk7XG5cdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWCApO1xuXHRcdGZvcm1faXRlbV9pbnB1dC5BQ29tYm9Cb3goIHtcblx0XHRcdGFwaV9jbGFzczogVFRBUEkuQVBJVXNlcixcblx0XHRcdGFsbG93X211bHRpcGxlX3NlbGVjdGlvbjogZmFsc2UsXG5cdFx0XHRsYXlvdXRfbmFtZTogJ2dsb2JhbF91c2VyJyxcblx0XHRcdHNob3dfc2VhcmNoX2lucHV0czogdHJ1ZSxcblx0XHRcdHNldF9lbXB0eTogIXRoaXMuY2hlY2tPcGVuUGVybWlzc2lvbigpLFxuXHRcdFx0c2V0X29wZW46IHRoaXMuY2hlY2tPcGVuUGVybWlzc2lvbigpLFxuXHRcdFx0ZmllbGQ6ICd1c2VyX2lkJ1xuXHRcdH0gKTtcblxuXHRcdHZhciBkZWZhdWx0X2FyZ3MgPSB7fTtcblx0XHRkZWZhdWx0X2FyZ3MucGVybWlzc2lvbl9zZWN0aW9uID0gJ3NjaGVkdWxlJztcblx0XHRmb3JtX2l0ZW1faW5wdXQuc2V0RGVmYXVsdEFyZ3MoIGRlZmF1bHRfYXJncyApO1xuXG5cdFx0dGhpcy5hZGRFZGl0RmllbGRUb0NvbHVtbiggJC5pMThuLl8oICdFbXBsb3llZScgKSwgZm9ybV9pdGVtX2lucHV0LCB0YWJfc2NoZWR1bGVfY29sdW1uMSwgJycsIG51bGwsIHRydWUgKTtcblxuXHRcdC8vTWFzcyBBZGQgRW1wbG95ZWVzXG5cblx0XHRmb3JtX2l0ZW1faW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLkFXRVNPTUVfQk9YICk7XG5cdFx0Zm9ybV9pdGVtX2lucHV0LkFDb21ib0JveCgge1xuXHRcdFx0YXBpX2NsYXNzOiBUVEFQSS5BUElVc2VyLFxuXHRcdFx0YWxsb3dfbXVsdGlwbGVfc2VsZWN0aW9uOiB0cnVlLFxuXHRcdFx0bGF5b3V0X25hbWU6ICdnbG9iYWxfdXNlcicsXG5cdFx0XHRzaG93X3NlYXJjaF9pbnB1dHM6IHRydWUsXG5cdFx0XHRzZXRfZW1wdHk6ICF0aGlzLmNoZWNrT3BlblBlcm1pc3Npb24oKSxcblx0XHRcdHNldF9vcGVuOiB0aGlzLmNoZWNrT3BlblBlcm1pc3Npb24oKSxcblx0XHRcdGFkZGl0aW9uX3NvdXJjZV9mdW5jdGlvbjogKCBmdW5jdGlvbiggdGFyZ2V0LCBzb3VyY2VfZGF0YSApIHtcblx0XHRcdFx0cmV0dXJuICR0aGlzLm9uRW1wbG95ZWVTb3VyY2VDcmVhdGUoIHRhcmdldCwgc291cmNlX2RhdGEgKTtcblx0XHRcdH0gKSxcblx0XHRcdGZpZWxkOiAndXNlcl9pZHMnXG5cdFx0fSApO1xuXG5cdFx0ZGVmYXVsdF9hcmdzID0ge307XG5cdFx0ZGVmYXVsdF9hcmdzLnBlcm1pc3Npb25fc2VjdGlvbiA9ICdzY2hlZHVsZSc7XG5cdFx0Zm9ybV9pdGVtX2lucHV0LnNldERlZmF1bHRBcmdzKCBkZWZhdWx0X2FyZ3MgKTtcblxuXHRcdHRoaXMuYWRkRWRpdEZpZWxkVG9Db2x1bW4oICQuaTE4bi5fKCAnRW1wbG95ZWUnICksIGZvcm1faXRlbV9pbnB1dCwgdGFiX3NjaGVkdWxlX2NvbHVtbjEsICcnLCBudWxsLCB0cnVlICk7XG5cblx0XHQvL1N0YXR1c1xuXHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuQ09NQk9fQk9YICk7XG5cblx0XHRmb3JtX2l0ZW1faW5wdXQuVENvbWJvQm94KCB7IGZpZWxkOiAnc3RhdHVzX2lkJyB9ICk7XG5cdFx0Zm9ybV9pdGVtX2lucHV0LnNldFNvdXJjZURhdGEoICR0aGlzLnN0YXR1c19hcnJheSApO1xuXHRcdHRoaXMuYWRkRWRpdEZpZWxkVG9Db2x1bW4oICQuaTE4bi5fKCAnU3RhdHVzJyApLCBmb3JtX2l0ZW1faW5wdXQsIHRhYl9zY2hlZHVsZV9jb2x1bW4xICk7XG5cblx0XHQvL0Fic2VuY2UgUG9saWN5XG5cdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWCApO1xuXG5cdFx0Zm9ybV9pdGVtX2lucHV0LkFDb21ib0JveCgge1xuXHRcdFx0YXBpX2NsYXNzOiBUVEFQSS5BUElBYnNlbmNlUG9saWN5LFxuXHRcdFx0YWxsb3dfbXVsdGlwbGVfc2VsZWN0aW9uOiBmYWxzZSxcblx0XHRcdGxheW91dF9uYW1lOiAnZ2xvYmFsX2Fic2VuY2VzJyxcblx0XHRcdHNob3dfc2VhcmNoX2lucHV0czogdHJ1ZSxcblx0XHRcdHNldF9lbXB0eTogdHJ1ZSxcblx0XHRcdGZpZWxkOiAnYWJzZW5jZV9wb2xpY3lfaWQnXG5cdFx0fSApO1xuXG5cdFx0Zm9ybV9pdGVtX2lucHV0LmN1c3RvbVNlYXJjaEZpbHRlciA9IGZ1bmN0aW9uKCBmaWx0ZXIgKSB7XG5cdFx0XHRyZXR1cm4gJHRoaXMuc2V0QWJzZW5jZVBvbGljeUZpbHRlciggZmlsdGVyICk7XG5cdFx0fTtcblxuXHRcdHRoaXMuYWRkRWRpdEZpZWxkVG9Db2x1bW4oICQuaTE4bi5fKCAnQWJzZW5jZSBQb2xpY3knICksIGZvcm1faXRlbV9pbnB1dCwgdGFiX3NjaGVkdWxlX2NvbHVtbjEsICcnLCBudWxsLCB0cnVlICk7XG5cblx0XHQvL0F2YWlsYWJsZSBCYWxhbmNlXG5cdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5URVhUICk7XG5cdFx0Zm9ybV9pdGVtX2lucHV0LlRUZXh0KCB7IGZpZWxkOiAnYXZhaWxhYmxlX2JhbGFuY2UnIH0gKTtcblxuXHRcdHdpZGdldENvbnRhaW5lciA9ICQoICc8ZGl2IGNsYXNzPVxcJ3dpZGdldC1oLWJveCBhdmFpbGFibGUtYmFsYW5jZS1oLWJveFxcJz48L2Rpdj4nICk7XG5cdFx0dGhpcy5hdmFpbGFibGVfYmFsYW5jZV9pbmZvID0gJCggJzxzcGFuIGNsYXNzPVwiYXZhaWxhYmxlLWJhbGFuY2UtaW5mbyB0dGljb24gdHRpY29uLWluZm9fYmxhY2tfMjRkcFwiPjwvc3Bhbj4nICk7XG5cblx0XHR3aWRnZXRDb250YWluZXIuYXBwZW5kKCBmb3JtX2l0ZW1faW5wdXQgKTtcblx0XHR3aWRnZXRDb250YWluZXIuYXBwZW5kKCB0aGlzLmF2YWlsYWJsZV9iYWxhbmNlX2luZm8gKTtcblxuXHRcdHRoaXMuYWRkRWRpdEZpZWxkVG9Db2x1bW4oICQuaTE4bi5fKCAnQXZhaWxhYmxlIEJhbGFuY2UnICksIGZvcm1faXRlbV9pbnB1dCwgdGFiX3NjaGVkdWxlX2NvbHVtbjEsICcnLCB3aWRnZXRDb250YWluZXIsIHRydWUgKTtcblxuXHRcdGlmICggIXRoaXMuY3VycmVudF9lZGl0X3JlY29yZCB8fCAoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC51c2VyX2lkcyAmJiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudXNlcl9pZHMubGVuZ3RoID4gMSApICkge1xuXHRcdFx0dGhpcy5kZXRhY2hFbGVtZW50KCAnYXZhaWxhYmxlX2JhbGFuY2UnICk7XG5cdFx0fVxuXG5cdFx0Ly9EYXRlXG5cdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5EQVRFX1BJQ0tFUiApO1xuXG5cdFx0Zm9ybV9pdGVtX2lucHV0LlREYXRlUGlja2VyKCB7IGZpZWxkOiAnc3RhcnRfZGF0ZV9zdGFtcCcsIHZhbGlkYXRpb25fZmllbGQ6ICdkYXRlX3N0YW1wJyB9ICk7XG5cblx0XHR0aGlzLmFkZEVkaXRGaWVsZFRvQ29sdW1uKCAkLmkxOG4uXyggJ0RhdGUnICksIGZvcm1faXRlbV9pbnB1dCwgdGFiX3NjaGVkdWxlX2NvbHVtbjEsICcnLCBudWxsLCB0cnVlICk7XG5cblx0XHQvL0RhdGVzXG5cdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5EQVRFX1BJQ0tFUiApO1xuXG5cdFx0Zm9ybV9pdGVtX2lucHV0LlRSYW5nZVBpY2tlciggeyBmaWVsZDogJ3N0YXJ0X2RhdGVfc3RhbXBzJyB9ICk7XG5cblx0XHR0aGlzLmFkZEVkaXRGaWVsZFRvQ29sdW1uKCAkLmkxOG4uXyggJ0RhdGUnICksIGZvcm1faXRlbV9pbnB1dCwgdGFiX3NjaGVkdWxlX2NvbHVtbjEsICcnLCBudWxsLCB0cnVlICk7XG5cblx0XHQvL01hc3MgQWRkIERhdGVcblx0XHRmb3JtX2l0ZW1faW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLkFXRVNPTUVfQk9YICk7XG5cblx0XHRmb3JtX2l0ZW1faW5wdXQuQUNvbWJvQm94KCB7XG5cdFx0XHRhbGxvd19tdWx0aXBsZV9zZWxlY3Rpb246IHRydWUsXG5cdFx0XHRsYXlvdXRfbmFtZTogJ2dsb2JhbF9vcHRpb25fY29sdW1uJyxcblx0XHRcdHNob3dfc2VhcmNoX2lucHV0czogZmFsc2UsXG5cdFx0XHRzZXRfZW1wdHk6IHRydWUsXG5cdFx0XHRmaWVsZDogJ3N0YXJ0X2RhdGVzJ1xuXHRcdH0gKTtcblxuXHRcdHRoaXMuYWRkRWRpdEZpZWxkVG9Db2x1bW4oICQuaTE4bi5fKCAnRGF0ZScgKSwgZm9ybV9pdGVtX2lucHV0LCB0YWJfc2NoZWR1bGVfY29sdW1uMSwgJycsIG51bGwsIHRydWUgKTtcblxuXHRcdC8vU3RhcnQgVGltZVxuXHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuVElNRV9QSUNLRVIgKTtcblx0XHRmb3JtX2l0ZW1faW5wdXQuVFRpbWVQaWNrZXIoIHsgZmllbGQ6ICdzdGFydF90aW1lJyB9ICk7XG5cblx0XHR0aGlzLmFkZEVkaXRGaWVsZFRvQ29sdW1uKCAkLmkxOG4uXyggJ0luJyApLCBmb3JtX2l0ZW1faW5wdXQsIHRhYl9zY2hlZHVsZV9jb2x1bW4xLCAnJywgbnVsbCwgdHJ1ZSApO1xuXG5cdFx0Ly9FbmQgVGltZVxuXHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuVElNRV9QSUNLRVIgKTtcblx0XHRmb3JtX2l0ZW1faW5wdXQuVFRpbWVQaWNrZXIoIHsgZmllbGQ6ICdlbmRfdGltZScgfSApO1xuXG5cdFx0dGhpcy5hZGRFZGl0RmllbGRUb0NvbHVtbiggJC5pMThuLl8oICdPdXQnICksIGZvcm1faXRlbV9pbnB1dCwgdGFiX3NjaGVkdWxlX2NvbHVtbjEsICcnLCBudWxsLCB0cnVlICk7XG5cblx0XHQvL1RvdGFsXG5cdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5URVhUICk7XG5cdFx0Zm9ybV9pdGVtX2lucHV0LlRUZXh0KCB7IGZpZWxkOiAndG90YWxfdGltZScgfSApO1xuXHRcdGZvcm1faXRlbV9pbnB1dC5jc3MoICdjdXJzb3InLCAncG9pbnRlcicgKTtcblx0XHR0aGlzLmFkZEVkaXRGaWVsZFRvQ29sdW1uKCAkLmkxOG4uXyggJ1RvdGFsJyApLCBmb3JtX2l0ZW1faW5wdXQsIHRhYl9zY2hlZHVsZV9jb2x1bW4xICk7XG5cblx0XHQvL1NjaGVkdWxlIFBvbGljeVxuXHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1ggKTtcblxuXHRcdGZvcm1faXRlbV9pbnB1dC5BQ29tYm9Cb3goIHtcblx0XHRcdGFwaV9jbGFzczogVFRBUEkuQVBJU2NoZWR1bGVQb2xpY3ksXG5cdFx0XHRhbGxvd19tdWx0aXBsZV9zZWxlY3Rpb246IGZhbHNlLFxuXHRcdFx0bGF5b3V0X25hbWU6ICdnbG9iYWxfc2NoZWR1bGUnLFxuXHRcdFx0c2hvd19zZWFyY2hfaW5wdXRzOiB0cnVlLFxuXHRcdFx0c2V0X2VtcHR5OiB0cnVlLFxuXHRcdFx0ZmllbGQ6ICdzY2hlZHVsZV9wb2xpY3lfaWQnXG5cdFx0fSApO1xuXHRcdHRoaXMuYWRkRWRpdEZpZWxkVG9Db2x1bW4oICQuaTE4bi5fKCAnU2NoZWR1bGUgUG9saWN5JyApLCBmb3JtX2l0ZW1faW5wdXQsIHRhYl9zY2hlZHVsZV9jb2x1bW4xICk7XG5cblx0XHQvL0RlZmF1bHQgQnJhbmNoXG5cdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWCApO1xuXG5cdFx0Zm9ybV9pdGVtX2lucHV0LkFDb21ib0JveCgge1xuXHRcdFx0YXBpX2NsYXNzOiBUVEFQSS5BUElCcmFuY2gsXG5cdFx0XHRhbGxvd19tdWx0aXBsZV9zZWxlY3Rpb246IGZhbHNlLFxuXHRcdFx0bGF5b3V0X25hbWU6ICdnbG9iYWxfYnJhbmNoJyxcblx0XHRcdHNob3dfc2VhcmNoX2lucHV0czogdHJ1ZSxcblx0XHRcdHNldF9lbXB0eTogdHJ1ZSxcblx0XHRcdGZpZWxkOiAnYnJhbmNoX2lkJyxcblx0XHRcdGFkZGl0aW9uX3NvdXJjZV9mdW5jdGlvbjogKCBmdW5jdGlvbiggdGFyZ2V0LCBzb3VyY2VfZGF0YSApIHtcblx0XHRcdFx0cmV0dXJuICR0aGlzLm9uU291cmNlRGF0YUNyZWF0ZSggdGFyZ2V0LCBzb3VyY2VfZGF0YSApO1xuXHRcdFx0fSApLFxuXHRcdFx0Ly9GSVhNRTogRm9sbG93IC0yIHRvIHRoZSBBUEkgZG8gbm90IHN3aXRjaCB0byBVVUlEIHVubGVzcyBhYnNvbHV0ZWx5IG5lY2Vzc2FyeT9cblx0XHRcdGFkZGVkX2l0ZW1zOiBbXG5cdFx0XHRcdHsgdmFsdWU6IFRUVVVJRC5ub3RfZXhpc3RfaWQsIGxhYmVsOiBHbG9iYWwuZGVmYXVsdF9pdGVtIH0sXG5cdFx0XHRcdHsgdmFsdWU6ICctMicsIGxhYmVsOiBHbG9iYWwuc2VsZWN0ZWRfaXRlbSB9XG5cdFx0XHRdXG5cdFx0fSApO1xuXHRcdHRoaXMuYWRkRWRpdEZpZWxkVG9Db2x1bW4oICQuaTE4bi5fKCAnQnJhbmNoJyApLCBmb3JtX2l0ZW1faW5wdXQsIHRhYl9zY2hlZHVsZV9jb2x1bW4xLCAnJywgbnVsbCwgdHJ1ZSApO1xuXG5cdFx0aWYgKCAhdGhpcy5zaG93X2JyYW5jaF91aSApIHtcblx0XHRcdHRoaXMuZGV0YWNoRWxlbWVudCggJ2JyYW5jaF9pZCcgKTtcblxuXHRcdH1cblxuXHRcdC8vRGVwYXJ0bWVudFxuXHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1ggKTtcblxuXHRcdGZvcm1faXRlbV9pbnB1dC5BQ29tYm9Cb3goIHtcblx0XHRcdGFwaV9jbGFzczogVFRBUEkuQVBJRGVwYXJ0bWVudCxcblx0XHRcdGFsbG93X211bHRpcGxlX3NlbGVjdGlvbjogZmFsc2UsXG5cdFx0XHRsYXlvdXRfbmFtZTogJ2dsb2JhbF9kZXBhcnRtZW50Jyxcblx0XHRcdHNob3dfc2VhcmNoX2lucHV0czogdHJ1ZSxcblx0XHRcdHNldF9lbXB0eTogdHJ1ZSxcblx0XHRcdGZpZWxkOiAnZGVwYXJ0bWVudF9pZCcsXG5cdFx0XHRhZGRpdGlvbl9zb3VyY2VfZnVuY3Rpb246ICggZnVuY3Rpb24oIHRhcmdldCwgc291cmNlX2RhdGEgKSB7XG5cdFx0XHRcdHJldHVybiAkdGhpcy5vblNvdXJjZURhdGFDcmVhdGUoIHRhcmdldCwgc291cmNlX2RhdGEgKTtcblx0XHRcdH0gKSxcblx0XHRcdGFkZGVkX2l0ZW1zOiBbXG5cdFx0XHRcdHsgdmFsdWU6IFRUVVVJRC5ub3RfZXhpc3RfaWQsIGxhYmVsOiBHbG9iYWwuZGVmYXVsdF9pdGVtIH0sXG5cdFx0XHRcdHsgdmFsdWU6ICctMicsIGxhYmVsOiBHbG9iYWwuc2VsZWN0ZWRfaXRlbSB9XG5cdFx0XHRdXG5cdFx0fSApO1xuXHRcdHRoaXMuYWRkRWRpdEZpZWxkVG9Db2x1bW4oICQuaTE4bi5fKCAnRGVwYXJ0bWVudCcgKSwgZm9ybV9pdGVtX2lucHV0LCB0YWJfc2NoZWR1bGVfY29sdW1uMSwgJycsIG51bGwsIHRydWUgKTtcblxuXHRcdGlmICggIXRoaXMuc2hvd19kZXBhcnRtZW50X3VpICkge1xuXHRcdFx0dGhpcy5kZXRhY2hFbGVtZW50KCAnZGVwYXJ0bWVudF9pZCcgKTtcblxuXHRcdH1cblxuXHRcdGlmICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSB7XG5cdFx0XHQvL0pvYlxuXHRcdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWCApO1xuXG5cdFx0XHRmb3JtX2l0ZW1faW5wdXQuQUNvbWJvQm94KCB7XG5cdFx0XHRcdGFwaV9jbGFzczogVFRBUEkuQVBJSm9iLFxuXHRcdFx0XHRhbGxvd19tdWx0aXBsZV9zZWxlY3Rpb246IGZhbHNlLFxuXHRcdFx0XHRsYXlvdXRfbmFtZTogJ2dsb2JhbF9qb2InLFxuXHRcdFx0XHRzaG93X3NlYXJjaF9pbnB1dHM6IHRydWUsXG5cdFx0XHRcdHNldF9lbXB0eTogdHJ1ZSxcblx0XHRcdFx0c2V0UmVhbFZhbHVlQ2FsbEJhY2s6ICggZnVuY3Rpb24oIHZhbCApIHtcblxuXHRcdFx0XHRcdGlmICggdmFsICkge1xuXHRcdFx0XHRcdFx0am9iX2NvZGVyLnNldFZhbHVlKCB2YWwubWFudWFsX2lkICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9ICksXG5cdFx0XHRcdGZpZWxkOiAnam9iX2lkJyxcblx0XHRcdFx0YWRkaXRpb25fc291cmNlX2Z1bmN0aW9uOiAoIGZ1bmN0aW9uKCB0YXJnZXQsIHNvdXJjZV9kYXRhICkge1xuXHRcdFx0XHRcdHJldHVybiAkdGhpcy5vblNvdXJjZURhdGFDcmVhdGUoIHRhcmdldCwgc291cmNlX2RhdGEgKTtcblx0XHRcdFx0fSApLFxuXHRcdFx0XHRhZGRlZF9pdGVtczogW1xuXHRcdFx0XHRcdHsgdmFsdWU6IFRUVVVJRC5ub3RfZXhpc3RfaWQsIGxhYmVsOiBHbG9iYWwuZGVmYXVsdF9pdGVtIH0sXG5cdFx0XHRcdFx0eyB2YWx1ZTogJy0yJywgbGFiZWw6IEdsb2JhbC5zZWxlY3RlZF9pdGVtIH1cblx0XHRcdFx0XVxuXHRcdFx0fSApO1xuXG5cdFx0XHR3aWRnZXRDb250YWluZXIgPSAkKCAnPGRpdiBjbGFzcz1cXCd3aWRnZXQtaC1ib3hcXCc+PC9kaXY+JyApO1xuXG5cdFx0XHR2YXIgam9iX2NvZGVyID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5URVhUX0lOUFVUICk7XG5cdFx0XHRqb2JfY29kZXIuVFRleHRJbnB1dCggeyBmaWVsZDogJ2pvYl9xdWlja19zZWFyY2gnLCBkaXNhYmxlX2tleXVwX2V2ZW50OiB0cnVlIH0gKTtcblx0XHRcdGpvYl9jb2Rlci5hZGRDbGFzcyggJ2pvYi1jb2RlcicgKTtcblxuXHRcdFx0d2lkZ2V0Q29udGFpbmVyLmFwcGVuZCggam9iX2NvZGVyICk7XG5cdFx0XHR3aWRnZXRDb250YWluZXIuYXBwZW5kKCBmb3JtX2l0ZW1faW5wdXQgKTtcblx0XHRcdHRoaXMuYWRkRWRpdEZpZWxkVG9Db2x1bW4oICQuaTE4bi5fKCAnSm9iJyApLCBbZm9ybV9pdGVtX2lucHV0LCBqb2JfY29kZXJdLCB0YWJfc2NoZWR1bGVfY29sdW1uMSwgJycsIHdpZGdldENvbnRhaW5lciwgdHJ1ZSApO1xuXG5cdFx0XHRpZiAoICF0aGlzLnNob3dfam9iX3VpICkge1xuXHRcdFx0XHR0aGlzLmRldGFjaEVsZW1lbnQoICdqb2JfaWQnICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vSm9iIEl0ZW1cblx0XHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1ggKTtcblxuXHRcdFx0Zm9ybV9pdGVtX2lucHV0LkFDb21ib0JveCgge1xuXHRcdFx0XHRhcGlfY2xhc3M6IFRUQVBJLkFQSUpvYkl0ZW0sXG5cdFx0XHRcdGFsbG93X211bHRpcGxlX3NlbGVjdGlvbjogZmFsc2UsXG5cdFx0XHRcdGxheW91dF9uYW1lOiAnZ2xvYmFsX2pvYl9pdGVtJyxcblx0XHRcdFx0c2hvd19zZWFyY2hfaW5wdXRzOiB0cnVlLFxuXHRcdFx0XHRzZXRfZW1wdHk6IHRydWUsXG5cdFx0XHRcdHNldFJlYWxWYWx1ZUNhbGxCYWNrOiAoIGZ1bmN0aW9uKCB2YWwgKSB7XG5cblx0XHRcdFx0XHRpZiAoIHZhbCApIHtcblx0XHRcdFx0XHRcdGpvYl9pdGVtX2NvZGVyLnNldFZhbHVlKCB2YWwubWFudWFsX2lkICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9ICksXG5cdFx0XHRcdGZpZWxkOiAnam9iX2l0ZW1faWQnLFxuXHRcdFx0XHRhZGRpdGlvbl9zb3VyY2VfZnVuY3Rpb246ICggZnVuY3Rpb24oIHRhcmdldCwgc291cmNlX2RhdGEgKSB7XG5cdFx0XHRcdFx0cmV0dXJuICR0aGlzLm9uU291cmNlRGF0YUNyZWF0ZSggdGFyZ2V0LCBzb3VyY2VfZGF0YSApO1xuXHRcdFx0XHR9ICksXG5cdFx0XHRcdGFkZGVkX2l0ZW1zOiBbXG5cdFx0XHRcdFx0eyB2YWx1ZTogVFRVVUlELm5vdF9leGlzdF9pZCwgbGFiZWw6IEdsb2JhbC5kZWZhdWx0X2l0ZW0gfSxcblx0XHRcdFx0XHR7IHZhbHVlOiAnLTInLCBsYWJlbDogR2xvYmFsLnNlbGVjdGVkX2l0ZW0gfVxuXHRcdFx0XHRdXG5cdFx0XHR9ICk7XG5cblx0XHRcdHdpZGdldENvbnRhaW5lciA9ICQoICc8ZGl2IGNsYXNzPVxcJ3dpZGdldC1oLWJveFxcJz48L2Rpdj4nICk7XG5cblx0XHRcdHZhciBqb2JfaXRlbV9jb2RlciA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuVEVYVF9JTlBVVCApO1xuXHRcdFx0am9iX2l0ZW1fY29kZXIuVFRleHRJbnB1dCggeyBmaWVsZDogJ2pvYl9pdGVtX3F1aWNrX3NlYXJjaCcsIGRpc2FibGVfa2V5dXBfZXZlbnQ6IHRydWUgfSApO1xuXHRcdFx0am9iX2l0ZW1fY29kZXIuYWRkQ2xhc3MoICdqb2ItY29kZXInICk7XG5cblx0XHRcdHdpZGdldENvbnRhaW5lci5hcHBlbmQoIGpvYl9pdGVtX2NvZGVyICk7XG5cdFx0XHR3aWRnZXRDb250YWluZXIuYXBwZW5kKCBmb3JtX2l0ZW1faW5wdXQgKTtcblx0XHRcdHRoaXMuYWRkRWRpdEZpZWxkVG9Db2x1bW4oICQuaTE4bi5fKCAnVGFzaycgKSwgW2Zvcm1faXRlbV9pbnB1dCwgam9iX2l0ZW1fY29kZXJdLCB0YWJfc2NoZWR1bGVfY29sdW1uMSwgJycsIHdpZGdldENvbnRhaW5lciwgdHJ1ZSApO1xuXG5cdFx0XHRpZiAoICF0aGlzLnNob3dfam9iX2l0ZW1fdWkgKSB7XG5cdFx0XHRcdHRoaXMuZGV0YWNoRWxlbWVudCggJ2pvYl9pdGVtX2lkJyApO1xuXHRcdFx0fVxuXG5cdFx0XHQvL1B1bmNoIFRhZ1xuXHRcdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWCApO1xuXG5cdFx0XHRmb3JtX2l0ZW1faW5wdXQuQUNvbWJvQm94KCB7XG5cdFx0XHRcdGFwaV9jbGFzczogVFRBUEkuQVBJUHVuY2hUYWcsXG5cdFx0XHRcdGFsbG93X211bHRpcGxlX3NlbGVjdGlvbjogdHJ1ZSxcblx0XHRcdFx0bGF5b3V0X25hbWU6ICdnbG9iYWxfcHVuY2hfdGFnJyxcblx0XHRcdFx0c2hvd19zZWFyY2hfaW5wdXRzOiB0cnVlLFxuXHRcdFx0XHRzZXRfZW1wdHk6IHRydWUsXG5cdFx0XHRcdGdldF9yZWFsX2RhdGFfb25fbXVsdGk6IHRydWUsXG5cdFx0XHRcdHNldFJlYWxWYWx1ZUNhbGxCYWNrOiAoICggcHVuY2hfdGFncywgZ2V0X3JlYWxfZGF0YSApID0+IHtcblx0XHRcdFx0XHRpZiAoIHB1bmNoX3RhZ3MgKSB7XG5cdFx0XHRcdFx0XHR0aGlzLnNldFB1bmNoVGFnUXVpY2tTZWFyY2hNYW51YWxJZHMoIHB1bmNoX3RhZ3MsIGdldF9yZWFsX2RhdGEgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKSxcblx0XHRcdFx0ZmllbGQ6ICdwdW5jaF90YWdfaWQnLFxuXHRcdFx0XHRhZGRpdGlvbl9zb3VyY2VfZnVuY3Rpb246ICggZnVuY3Rpb24oIHRhcmdldCwgc291cmNlX2RhdGEgKSB7XG5cdFx0XHRcdFx0cmV0dXJuICR0aGlzLm9uU291cmNlRGF0YUNyZWF0ZVB1bmNoVGFnKCB0YXJnZXQsIHNvdXJjZV9kYXRhICk7XG5cdFx0XHRcdH0gKSxcblx0XHRcdFx0YWRkZWRfaXRlbXM6IFtcblx0XHRcdFx0XHR7IHZhbHVlOiBUVFVVSUQubm90X2V4aXN0X2lkLCBsYWJlbDogR2xvYmFsLmRlZmF1bHRfaXRlbSB9XG5cdFx0XHRcdF1cblx0XHRcdH0gKTtcblxuXHRcdFx0d2lkZ2V0Q29udGFpbmVyID0gJCggJzxkaXYgY2xhc3M9XFwnd2lkZ2V0LWgtYm94XFwnPjwvZGl2PicgKTtcblxuXHRcdFx0dmFyIHB1bmNoX3RhZ19jb2RlciA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuVEVYVF9JTlBVVCApO1xuXHRcdFx0cHVuY2hfdGFnX2NvZGVyLlRUZXh0SW5wdXQoIHsgZmllbGQ6ICdwdW5jaF90YWdfcXVpY2tfc2VhcmNoJywgZGlzYWJsZV9rZXl1cF9ldmVudDogdHJ1ZSB9ICk7XG5cdFx0XHRwdW5jaF90YWdfY29kZXIuYWRkQ2xhc3MoICdqb2ItY29kZXInICk7XG5cblx0XHRcdHdpZGdldENvbnRhaW5lci5hcHBlbmQoIHB1bmNoX3RhZ19jb2RlciApO1xuXHRcdFx0d2lkZ2V0Q29udGFpbmVyLmFwcGVuZCggZm9ybV9pdGVtX2lucHV0ICk7XG5cdFx0XHR0aGlzLmFkZEVkaXRGaWVsZFRvQ29sdW1uKCAkLmkxOG4uXyggJ1RhZ3MnICksIFtmb3JtX2l0ZW1faW5wdXQsIHB1bmNoX3RhZ19jb2Rlcl0sIHRhYl9zY2hlZHVsZV9jb2x1bW4xLCAnJywgd2lkZ2V0Q29udGFpbmVyLCB0cnVlICk7XG5cblxuXHRcdFx0aWYgKCAhdGhpcy5zaG93X3B1bmNoX3RhZ191aSApIHtcblx0XHRcdFx0dGhpcy5kZXRhY2hFbGVtZW50KCAncHVuY2hfdGFnX2lkJyApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vTm90ZVxuXHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuVEVYVF9BUkVBICk7XG5cdFx0Zm9ybV9pdGVtX2lucHV0LlRUZXh0QXJlYSggeyBmaWVsZDogJ25vdGUnLCB3aWR0aDogJzEwMCUnIH0gKTtcblx0XHR0aGlzLmFkZEVkaXRGaWVsZFRvQ29sdW1uKCAkLmkxOG4uXyggJ05vdGUnICksIGZvcm1faXRlbV9pbnB1dCwgdGFiX3NjaGVkdWxlX2NvbHVtbjEsICcnLCBudWxsLCBudWxsLCB0cnVlICk7XG5cdFx0Zm9ybV9pdGVtX2lucHV0LnBhcmVudCgpLndpZHRoKCAnNDUlJyApO1xuXG5cdFx0aWYgKCBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAxNSAmJiB0aGlzLmlzX3ZpZXdpbmcgPT0gZmFsc2UgKSB7XG5cdFx0XHQvL05vdGlmeSBFbXBsb3llZVxuXHRcdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5DSEVDS0JPWCApO1xuXHRcdFx0Zm9ybV9pdGVtX2lucHV0LlRDaGVja2JveCggeyBmaWVsZDogJ25vdGlmeV91c2VyX3NjaGVkdWxlX2NoYW5nZScgfSApO1xuXHRcdFx0dGhpcy5hZGRFZGl0RmllbGRUb0NvbHVtbiggJC5pMThuLl8oICdOb3RpZnkgRW1wbG95ZWUnICksIGZvcm1faXRlbV9pbnB1dCwgdGFiX3NjaGVkdWxlX2NvbHVtbjEsICcnLCBudWxsLCB0cnVlICk7XG5cdFx0fVxuXG5cdFx0VFRQcm9taXNlLnJlc29sdmUoICdTY2hlZHVsZScsICdpbml0JyApO1xuXHR9XG5cblx0c2V0RGVmYXVsdE1lbnVEZWxldGVJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKSB7XG5cdFx0aWYgKCAhdGhpcy5kZWxldGVQZXJtaXNzaW9uVmFsaWRhdGUoICdzY2hlZHVsZScgKSB8fCB0aGlzLmVkaXRfb25seV9tb2RlICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdH1cblxuXHRcdGlmICggZ3JpZF9zZWxlY3RlZF9sZW5ndGggPiAwICYmIHRoaXMuZGVsZXRlT3duZXJPckNoaWxkUGVybWlzc2lvblZhbGlkYXRlKCAnc2NoZWR1bGUnICkgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCB0cnVlICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fVxuXHR9XG5cblx0b25BdmFpbGFibGVCYWxhbmNlQ2hhbmdlKCkge1xuXHRcdGlmICggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXR1c19pZCA9PSAyMFxuXHRcdFx0JiYgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmhhc093blByb3BlcnR5KCAnYWJzZW5jZV9wb2xpY3lfaWQnIClcblx0XHRcdCYmIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5hYnNlbmNlX3BvbGljeV9pZCAmJiAhdGhpcy5pc19tYXNzX2VkaXRpbmcgKSB7XG5cdFx0XHR0aGlzLmdldEF2YWlsYWJsZUJhbGFuY2UoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5kZXRhY2hFbGVtZW50KCAnYXZhaWxhYmxlX2JhbGFuY2UnICk7XG5cdFx0fVxuXHR9XG5cblx0cGFyc2VyRGF0ZXNSYW5nZSggZGF0ZSApIHtcblx0XHR2YXIgZGF0ZXMgPSBkYXRlLnNwbGl0KCAnIC0gJyApO1xuXHRcdHZhciByZXN1bHRBcnJheSA9IFtdO1xuXHRcdHZhciBiZWdpbkRhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCBkYXRlc1swXSApO1xuXHRcdHZhciBlbmREYXRlID0gR2xvYmFsLnN0clRvRGF0ZSggZGF0ZXNbMV0gKTtcblxuXHRcdHZhciBuZXh0RGF0ZSA9IGJlZ2luRGF0ZTtcblxuXHRcdHdoaWxlICggbmV4dERhdGUuZ2V0VGltZSgpIDwgZW5kRGF0ZS5nZXRUaW1lKCkgKSB7XG5cdFx0XHRyZXN1bHRBcnJheS5wdXNoKCBuZXh0RGF0ZS5mb3JtYXQoKSApO1xuXHRcdFx0bmV4dERhdGUgPSBuZXcgRGF0ZSggbmV3IERhdGUoIG5leHREYXRlLmdldFRpbWUoKSApLnNldERhdGUoIG5leHREYXRlLmdldERhdGUoKSArIDEgKSApO1xuXHRcdH1cblxuXHRcdHJlc3VsdEFycmF5LnB1c2goIGRhdGVzWzFdICk7XG5cblx0XHRyZXR1cm4gcmVzdWx0QXJyYXk7XG5cdH1cblxuXHRnZXRTZWxlY3RVc2Vyc0FycmF5KCkge1xuXHRcdHZhciByZXN1bHQgPSBbXTtcblx0XHR2YXIgY2VsbHNfYXJyYXkgPSB0aGlzLnNlbGVjdF9jZWxsc19BcnJheTtcblx0XHR2YXIgbGVuID0gY2VsbHNfYXJyYXkubGVuZ3RoO1xuXHRcdHZhciBkYXRlX2RpYyA9IHt9O1xuXG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHR2YXIgaXRlbSA9IGNlbGxzX2FycmF5W2ldO1xuXG5cdFx0XHQvLyBJZiBzZWxlY3QgZW1wdHkgY2VsbCB3aXRoIG5vIHVzZXIgaW5zaWRlLCBzZXQgdXNlcl9pZCB0byAwIGFzIE9QRU5cblx0XHRcdGlmICggIWl0ZW0udXNlcl9pZCApIHtcblx0XHRcdFx0aXRlbS51c2VyX2lkID0gVFRVVUlELnplcm9faWQ7XG5cdFx0XHR9XG5cblx0XHRcdGRhdGVfZGljW2l0ZW0udXNlcl9pZF0gPSB0cnVlO1xuXHRcdH1cblxuXHRcdGZvciAoIHZhciBrZXkgaW4gZGF0ZV9kaWMgKSB7XG5cdFx0XHRyZXN1bHQucHVzaCgga2V5ICk7XG5cdFx0fVxuXG5cdFx0aWYgKCByZXN1bHQubGVuZ3RoID09PSAwICkge1xuXHRcdFx0cmVzdWx0LnB1c2goIHRoaXMuZ2V0RGVmYXVsdFVzZXIoKSApO1xuXHRcdH1cblxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cblxuXHRnZXRTZWxlY3REYXRlQXJyYXkoKSB7XG5cdFx0dmFyIHJlc3VsdCA9IFtdO1xuXG5cdFx0dmFyIGNlbGxzX2FycmF5ID0gdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXk7XG5cblx0XHR2YXIgbGVuID0gY2VsbHNfYXJyYXkubGVuZ3RoO1xuXG5cdFx0dmFyIGRhdGVfZGljID0ge307XG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHR2YXIgaXRlbSA9IGNlbGxzX2FycmF5W2ldO1xuXG5cdFx0XHRpZiAoIGl0ZW0uZGF0ZSApIHtcblx0XHRcdFx0ZGF0ZV9kaWNbaXRlbS5kYXRlXSA9IHRydWU7XG5cdFx0XHR9XG5cblx0XHR9XG5cblx0XHRmb3IgKCB2YXIga2V5IGluIGRhdGVfZGljICkge1xuXHRcdFx0cmVzdWx0LnB1c2goIGtleSApO1xuXHRcdH1cblxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cblxuXHRnZXRBdmFpbGFibGVCYWxhbmNlKCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dmFyIHVzZXJfaWQgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudXNlcl9pZDtcblx0XHR2YXIgdG90YWxfdGltZSA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC50b3RhbF90aW1lO1xuXHRcdHZhciBsYXN0X2RhdGVfc3RhbXAgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3RhcnRfZGF0ZV9zdGFtcDtcblxuXHRcdC8vT24gZmlyc3QgcnVuLCBzZXQgcHJldmlvdXNfYWJzZW5jZV9wb2xpY3lfaWQuXG5cdFx0aWYgKCB0aGlzLnByZXZpb3VzX2Fic2VuY2VfcG9saWN5X2lkID09IGZhbHNlICkge1xuXHRcdFx0dGhpcy5wcmV2aW91c19hYnNlbmNlX3BvbGljeV9pZCA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5hYnNlbmNlX3BvbGljeV9pZDtcblx0XHR9XG5cblx0XHQvL0ZvciBtYXNzIGFkZGluZyBjYXNlLCBzZWxlY3QgbXVsdGlwbGUgY2VsbHMgYW5kIGNsaWNrIG5ld1xuXHRcdGlmICggdGhpcy5pc19tYXNzX2FkZGluZyApIHtcblx0XHRcdGlmICggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnVzZXJfaWRzLmxlbmd0aCA+IDEgKSB7XG5cdFx0XHRcdHRoaXMuZGV0YWNoRWxlbWVudCggJ2F2YWlsYWJsZV9iYWxhbmNlJyApO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR1c2VyX2lkID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnVzZXJfaWRzWzBdO1xuXHRcdFx0XHRpZiAoICF1c2VyX2lkICkge1xuXHRcdFx0XHRcdHRoaXMuZGV0YWNoRWxlbWVudCggJ2F2YWlsYWJsZV9iYWxhbmNlJyApO1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHR0b3RhbF90aW1lID0gdG90YWxfdGltZSAqIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5zdGFydF9kYXRlcy5sZW5ndGg7XG5cdFx0XHRsYXN0X2RhdGVfc3RhbXAgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuc3RhcnRfZGF0ZXNbdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVzLmxlbmd0aCAtIDFdO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvL2dldCBkYXRlcyBmcm9tIGRhdGUgcmFuZ2VyXG5cdFx0XHRpZiAoIGxhc3RfZGF0ZV9zdGFtcC5pbmRleE9mKCAnIC0gJyApID4gMCB8fCAkLnR5cGUoIGxhc3RfZGF0ZV9zdGFtcCApID09PSAnYXJyYXknICkge1xuXHRcdFx0XHRpZiAoIGxhc3RfZGF0ZV9zdGFtcC5pbmRleE9mKCAnIC0gJyApID4gMCApIHtcblx0XHRcdFx0XHRsYXN0X2RhdGVfc3RhbXAgPSB0aGlzLnBhcnNlckRhdGVzUmFuZ2UoIGxhc3RfZGF0ZV9zdGFtcCApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCBsYXN0X2RhdGVfc3RhbXAubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0XHR0b3RhbF90aW1lID0gdG90YWxfdGltZSAqIGxhc3RfZGF0ZV9zdGFtcC5sZW5ndGg7XG5cdFx0XHRcdFx0bGFzdF9kYXRlX3N0YW1wID0gbGFzdF9kYXRlX3N0YW1wW2xhc3RfZGF0ZV9zdGFtcC5sZW5ndGggLSAxXTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoICggIXRoaXMuY3VycmVudF9lZGl0X3JlY29yZCB8fCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkIHx8IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCA9PSBUVFVVSUQuemVyb19pZCApICYmICF0aGlzLmlzX21hc3NfZWRpdGluZyApIHtcblx0XHRcdFx0aWYgKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudXNlcl9pZHMubGVuZ3RoIDwgMSB8fCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudXNlcl9pZHMubGVuZ3RoID4gMSApIHtcblx0XHRcdFx0XHR0aGlzLmRldGFjaEVsZW1lbnQoICdhdmFpbGFibGVfYmFsYW5jZScgKTtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0dXNlcl9pZCA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC51c2VyX2lkc1swXTtcblx0XHRcdFx0XHRpZiAoICF1c2VyX2lkICkge1xuXHRcdFx0XHRcdFx0dGhpcy5kZXRhY2hFbGVtZW50KCAnYXZhaWxhYmxlX2JhbGFuY2UnICk7XG5cdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly9DaGVjayBpZiB0aGUgdXNlciBpcyBlZGl0aW5nIGEgZXhpc3RpbmcgcmVjb3JkIHRoYXQgd2FzIG9yaWdpbmFsbHkgU3RhdHVzPVdvcmtpbmcsIGFuZCBjaGFuZ2luZyBpdCB0byBTdGF0dXM9QWJzZW50LCBpbiB0aGF0IGNhc2Ugd2UgY2FuJ3QgYWRqdXN0IGZvciB0aGUgZXhpc3RpbmcgdG90YWwgdGltZSBhbmQgbXVzdCBjbGVhciBpdCBvdXQuXG5cdFx0aWYgKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgJiYgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkICYmIHRoaXMucHJldl9zdGF0dXNfaWQgPT0gMTAgJiYgdGhpcy5lZGl0X3ZpZXdfdWlfZGljWydzdGF0dXNfaWQnXS5nZXRWYWx1ZSgpID09IDIwICkge1xuXHRcdFx0dGhpcy5wcmV2X3RvdGFsX3RpbWUgPSAwO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmFic2VuY2VfcG9saWN5X2lkICE9IFRUVVVJRC56ZXJvX2lkICkge1xuXHRcdFx0dGhpcy5hcGlfYWJzZW5jZV9wb2xpY3kuZ2V0UHJvamVjdGVkQWJzZW5jZVBvbGljeUJhbGFuY2UoXG5cdFx0XHRcdHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5hYnNlbmNlX3BvbGljeV9pZCxcblx0XHRcdFx0dXNlcl9pZCxcblx0XHRcdFx0bGFzdF9kYXRlX3N0YW1wLFxuXHRcdFx0XHR0b3RhbF90aW1lLFxuXHRcdFx0XHR0aGlzLnByZXZfdG90YWxfdGltZSxcblx0XHRcdFx0dGhpcy5wcmV2aW91c19hYnNlbmNlX3BvbGljeV9pZCwge1xuXHRcdFx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHRcdFx0JHRoaXMuZ2V0QmFsYW5jZUhhbmRsZXIoIHJlc3VsdCwgbGFzdF9kYXRlX3N0YW1wICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLmdldEJhbGFuY2VIYW5kbGVyKCBmYWxzZSwgbGFzdF9kYXRlX3N0YW1wICk7XG5cdFx0fVxuXHR9XG5cblx0YnVpbGRTZWFyY2hBbmRMYXlvdXRVSSgpIHtcblx0XHR2YXIgbGF5b3V0X2RpdiA9IHRoaXMuc2VhcmNoX3BhbmVsLmZpbmQoICdkaXYgI3NhdmVkX2xheW91dF9jb250ZW50X2RpdicgKTtcblxuXHRcdC8vRGlzcGxheSBDb2x1bW5zXG5cblx0XHR2YXIgZm9ybV9pdGVtID0gJCggJC5mbi5TZWFyY2hQYW5lbC5odG1sLmZvcm1faXRlbSApO1xuXHRcdHZhciBmb3JtX2l0ZW1fbGFiZWwgPSBmb3JtX2l0ZW0uZmluZCggJy5mb3JtLWl0ZW0tbGFiZWwnICk7XG5cdFx0dmFyIGZvcm1faXRlbV9pbnB1dF9kaXYgPSBmb3JtX2l0ZW0uZmluZCggJy5mb3JtLWl0ZW0taW5wdXQtZGl2JyApO1xuXG5cdFx0dGhpcy5jb2x1bW5fc2VsZWN0b3IgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLkFXRVNPTUVfRFJPUERPV04gKTtcblxuXHRcdHRoaXMuY29sdW1uX3NlbGVjdG9yID0gdGhpcy5jb2x1bW5fc2VsZWN0b3IuQURyb3BEb3duKCB7XG5cdFx0XHRkaXNwbGF5X3Nob3dfYWxsOiBmYWxzZSxcblx0XHRcdGlkOiAnY29sdW1uX3NlbGVjdG9yJyxcblx0XHRcdGtleTogJ3ZhbHVlJyxcblx0XHRcdGFsbG93X2RyYWdfdG9fb3JkZXI6IHRydWUsXG5cdFx0XHRkaXNwbGF5X2Nsb3NlX2J0bjogZmFsc2UsXG5cdFx0XHRkaXNwbGF5X2NvbHVtbl9zZXR0aW5nczogZmFsc2UsXG5cdFx0XHRzdGF0aWNfaGVpZ2h0OiAxNTBcblx0XHR9ICk7XG5cblx0XHRmb3JtX2l0ZW1fbGFiZWwudGV4dCggJC5pMThuLl8oICdEaXNwbGF5IENvbHVtbnMnICkgKTtcblx0XHRmb3JtX2l0ZW1faW5wdXRfZGl2LmFwcGVuZCggdGhpcy5jb2x1bW5fc2VsZWN0b3IgKTtcblxuXHRcdGxheW91dF9kaXYuYXBwZW5kKCBmb3JtX2l0ZW0gKTtcblxuXHRcdGxheW91dF9kaXYuYXBwZW5kKCAnPGRpdiBjbGFzcz1cXCdjbGVhci1ib3RoLWRpdlxcJz48L2Rpdj4nICk7XG5cblx0XHR0aGlzLmNvbHVtbl9zZWxlY3Rvci5zZXRDb2x1bW5zKCBbXG5cdFx0XHR7IG5hbWU6ICdsYWJlbCcsIGluZGV4OiAnbGFiZWwnLCBsYWJlbDogJC5pMThuLl8oICdDb2x1bW4gTmFtZScgKSwgd2lkdGg6IDEwMCwgc29ydGFibGU6IGZhbHNlIH1cblx0XHRdICk7XG5cblx0XHQvL1NhdmUgYW5kIHVwZGF0ZSBsYXlvdXRcblxuXHRcdGZvcm1faXRlbSA9ICQoICQuZm4uU2VhcmNoUGFuZWwuaHRtbC5mb3JtX2l0ZW0gKTtcblx0XHRmb3JtX2l0ZW1fbGFiZWwgPSBmb3JtX2l0ZW0uZmluZCggJy5mb3JtLWl0ZW0tbGFiZWwnICk7XG5cdFx0Zm9ybV9pdGVtX2lucHV0X2RpdiA9IGZvcm1faXRlbS5maW5kKCAnLmZvcm0taXRlbS1pbnB1dC1kaXYnICk7XG5cblx0XHRmb3JtX2l0ZW1fbGFiZWwudGV4dCggJC5pMThuLl8oICdTYXZlIFNlYXJjaCBBcycgKSApO1xuXG5cdFx0dGhpcy5zYXZlX3NlYXJjaF9hc19pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuVEVYVF9JTlBVVCApO1xuXHRcdHRoaXMuc2F2ZV9zZWFyY2hfYXNfaW5wdXQuVFRleHRJbnB1dCgpO1xuXG5cdFx0dmFyIHNhdmVfYnRuID0gJCggJzxidXR0b24gY2xhc3M9XCJ0dC1idXR0b24gcC1idXR0b24gcC1jb21wb25lbnQgc21hbGwtc2VhcmNoLXBhbmVsLWJ1dHRvblwiIHR5cGU9XCJidXR0b25cIj5cXG4nICtcblx0XHRcdCc8c3BhbiBjbGFzcz1cInR0aWNvbiB0dGljb24tc2F2ZV9ibGFja18yNGRwXCI+PC9zcGFuPlxcbicgK1xuXHRcdFx0JzxzcGFuIGNsYXNzPVwicC1idXR0b24tbGFiZWxcIj4nICsgJC5pMThuLl8oICdTYXZlJyApICsgJzwvc3Bhbj5cXG4nICtcblx0XHRcdCc8L2J1dHRvbj4nICk7XG5cblx0XHRmb3JtX2l0ZW1faW5wdXRfZGl2LmFwcGVuZCggdGhpcy5zYXZlX3NlYXJjaF9hc19pbnB1dCApO1xuXHRcdGZvcm1faXRlbV9pbnB1dF9kaXYuYXBwZW5kKCBzYXZlX2J0biApO1xuXG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHRzYXZlX2J0bi5jbGljayggZnVuY3Rpb24oKSB7XG5cdFx0XHQkdGhpcy5vblNhdmVOZXdMYXlvdXQoKTtcblx0XHR9ICk7XG5cblx0XHQvL1ByZXZpb3VzIFNhdmVkIExheW91dFxuXG5cdFx0dGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfZGl2ID0gJCggJzxkaXYgY2xhc3M9XFwncHJldmlvdXMtc2F2ZWQtbGF5b3V0LWRpdlxcJz48L2Rpdj4nICk7XG5cblx0XHRmb3JtX2l0ZW1faW5wdXRfZGl2LmFwcGVuZCggdGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfZGl2ICk7XG5cblx0XHRmb3JtX2l0ZW1fbGFiZWwgPSAkKCAnPHNwYW4gc3R5bGU9XFwnbWFyZ2luLWxlZnQ6IDVweFxcJyA+JyArICQuaTE4bi5fKCAnUHJldmlvdXMgU2F2ZWQgU2VhcmNoZXMnICkgKyAnOjwvc3Bhbj4nICk7XG5cdFx0dGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfZGl2LmFwcGVuZCggZm9ybV9pdGVtX2xhYmVsICk7XG5cblx0XHR0aGlzLnByZXZpb3VzX3NhdmVkX2xheW91dF9zZWxlY3RvciA9ICQoICc8c2VsZWN0IHN0eWxlPVxcJ21hcmdpbi1sZWZ0OiA1cHhcXCcgY2xhc3M9XFwndC1zZWxlY3RcXCc+JyApO1xuXHRcdHZhciB1cGRhdGVfYnRuID0gJCggJzxidXR0b24gY2xhc3M9XCJ0dC1idXR0b24gcC1idXR0b24gcC1jb21wb25lbnQgc21hbGwtc2VhcmNoLXBhbmVsLWJ1dHRvblwiIHR5cGU9XCJidXR0b25cIj5cXG4nICtcblx0XHRcdCc8c3BhbiBjbGFzcz1cInR0aWNvbiB0dGljb24tc2F2ZV9ibGFja18yNGRwXCI+PC9zcGFuPlxcbicgK1xuXHRcdFx0JzxzcGFuIGNsYXNzPVwicC1idXR0b24tbGFiZWxcIj4nICsgJC5pMThuLl8oICdVcGRhdGUnICkgKyAnPC9zcGFuPlxcbicgK1xuXHRcdFx0JzwvYnV0dG9uPicgKTtcblxuXHRcdHZhciBkZWxfYnRuID0gJCggJzxidXR0b24gY2xhc3M9XCJ0dC1idXR0b24gcC1idXR0b24gcC1jb21wb25lbnQgc21hbGwtc2VhcmNoLXBhbmVsLWJ1dHRvblwiIHR5cGU9XCJidXR0b25cIj5cXG4nICtcblx0XHRcdCc8c3BhbiBjbGFzcz1cInR0aWNvbiB0dGljb24tZGVsZXRlX2JsYWNrXzI0ZHBcIj48L3NwYW4+XFxuJyArXG5cdFx0XHQnPHNwYW4gY2xhc3M9XCJwLWJ1dHRvbi1sYWJlbFwiPicgKyAkLmkxOG4uXyggJ0RlbGV0ZScgKSArICc8L3NwYW4+XFxuJyArXG5cdFx0XHQnPC9idXR0b24+JyApO1xuXG5cdFx0dXBkYXRlX2J0bi5jbGljayggZnVuY3Rpb24oKSB7XG5cdFx0XHQkdGhpcy5vblVwZGF0ZUxheW91dCgpO1xuXHRcdH0gKTtcblxuXHRcdGRlbF9idG4uY2xpY2soIGZ1bmN0aW9uKCkge1xuXHRcdFx0JHRoaXMub25EZWxldGVMYXlvdXQoKTtcblx0XHR9ICk7XG5cblx0XHR0aGlzLnByZXZpb3VzX3NhdmVkX2xheW91dF9kaXYuYXBwZW5kKCB0aGlzLnByZXZpb3VzX3NhdmVkX2xheW91dF9zZWxlY3RvciApO1xuXHRcdHRoaXMucHJldmlvdXNfc2F2ZWRfbGF5b3V0X2Rpdi5hcHBlbmQoIHVwZGF0ZV9idG4gKTtcblx0XHR0aGlzLnByZXZpb3VzX3NhdmVkX2xheW91dF9kaXYuYXBwZW5kKCBkZWxfYnRuICk7XG5cblx0XHRsYXlvdXRfZGl2LmFwcGVuZCggZm9ybV9pdGVtICk7XG5cblx0XHR0aGlzLnByZXZpb3VzX3NhdmVkX2xheW91dF9kaXYuY3NzKCAnZGlzcGxheScsICdub25lJyApO1xuXHR9XG5cblx0c2V0Q3VycmVudEVkaXRSZWNvcmREYXRhKCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0aWYgKCB0aGlzLmlzX21hc3NfYWRkaW5nICkge1xuXHRcdFx0dGhpcy5hdHRhY2hFbGVtZW50KCAnc3RhcnRfZGF0ZXMnICk7XG5cdFx0XHR0aGlzLmRldGFjaEVsZW1lbnQoICdzdGFydF9kYXRlX3N0YW1wJyApO1xuXHRcdFx0dGhpcy5kZXRhY2hFbGVtZW50KCAnc3RhcnRfZGF0ZV9zdGFtcHMnICk7XG5cblx0XHRcdHRoaXMuYXR0YWNoRWxlbWVudCggJ3VzZXJfaWRzJyApO1xuXHRcdFx0dGhpcy5kZXRhY2hFbGVtZW50KCAndXNlcl9pZCcgKTtcblxuXHRcdFx0dGhpcy5lZGl0X3ZpZXdfdWlfZGljLnN0YXJ0X2RhdGVzLnNldEVuYWJsZWQoIGZhbHNlICk7XG5cdFx0XHR0aGlzLmVkaXRfdmlld191aV9kaWMudXNlcl9pZHMuc2V0RW5hYmxlZCggZmFsc2UgKTtcblxuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLmRldGFjaEVsZW1lbnQoICdzdGFydF9kYXRlcycgKTtcblxuXHRcdFx0aWYgKCAoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCAmJiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgIT0gVFRVVUlELnplcm9faWQgKSB8fCB0aGlzLmlzX21hc3NfZWRpdGluZyApIHtcblx0XHRcdFx0dGhpcy5hdHRhY2hFbGVtZW50KCAnc3RhcnRfZGF0ZV9zdGFtcCcgKTtcblx0XHRcdFx0dGhpcy5kZXRhY2hFbGVtZW50KCAnc3RhcnRfZGF0ZV9zdGFtcHMnICk7XG5cdFx0XHRcdHRoaXMuZGV0YWNoRWxlbWVudCggJ3VzZXJfaWRzJyApO1xuXHRcdFx0XHR0aGlzLmF0dGFjaEVsZW1lbnQoICd1c2VyX2lkJyApO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLmF0dGFjaEVsZW1lbnQoICdzdGFydF9kYXRlX3N0YW1wcycgKTtcblx0XHRcdFx0dGhpcy5kZXRhY2hFbGVtZW50KCAnc3RhcnRfZGF0ZV9zdGFtcCcgKTtcblx0XHRcdFx0dGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXBzID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnN0YXJ0X2RhdGVfc3RhbXA7XG5cblx0XHRcdFx0dGhpcy5hdHRhY2hFbGVtZW50KCAndXNlcl9pZHMnICk7XG5cdFx0XHRcdHRoaXMuZGV0YWNoRWxlbWVudCggJ3VzZXJfaWQnICk7XG5cdFx0XHR9XG5cblx0XHR9XG5cblx0XHR0aGlzLnByZXZfdG90YWxfdGltZSA9IDA7XG5cblx0XHQvL1doZW4gZWRpdGluZyBhbiBleGlzdGluZyByZWNvcmQsIHN0b3JlIHRoZSBvcmlnaW5hbCBzdGF0dXNfaWQgc28gd2UgY2FuIGxhdGVyIHVzZSBpdCB3aGVuIGNhbGN1bGF0aW5nIGF2YWlsYWJsZSBiYWxhbmNlLlxuXHRcdGlmICggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkICYmIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCAhPSBUVFVVSUQuemVyb19pZCApIHtcblx0XHRcdHRoaXMucHJldl9zdGF0dXNfaWQgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRbJ3N0YXR1c19pZCddO1xuXHRcdH1cblxuXHRcdC8vU2V0IGN1cnJlbnQgZWRpdCByZWNvcmQgZGF0YSB0byBhbGwgd2lkZ2V0c1xuXHRcdGZvciAoIHZhciBrZXkgaW4gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICkge1xuXHRcdFx0dmFyIHdpZGdldCA9IHRoaXMuZWRpdF92aWV3X3VpX2RpY1trZXldO1xuXHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoIHdpZGdldCApICkge1xuXHRcdFx0XHRzd2l0Y2ggKCBrZXkgKSB7XG5cdFx0XHRcdFx0Y2FzZSAndXNlcl9pZHMnOlxuXHRcdFx0XHRcdFx0aWYgKCB3aWRnZXQuaXMoICc6dmlzaWJsZScgKSApIHtcblx0XHRcdFx0XHRcdFx0dmFyIHVzZXJfYXJyYXkgPSB0aGlzLmdldFNlbGVjdFVzZXJzQXJyYXkoKTtcblx0XHRcdFx0XHRcdFx0dGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2tleV0gPSB1c2VyX2FycmF5O1xuXHRcdFx0XHRcdFx0XHR3aWRnZXQuc2V0VmFsdWUoIHVzZXJfYXJyYXkgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ3N0YXJ0X2RhdGVzJzpcblx0XHRcdFx0XHRcdHZhciBkYXRlX2FycmF5ID0gdGhpcy5nZXRTZWxlY3REYXRlQXJyYXkoKTtcblx0XHRcdFx0XHRcdHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFtrZXldID0gZGF0ZV9hcnJheTtcblx0XHRcdFx0XHRcdGRhdGVfYXJyYXkgPSBHbG9iYWwuYnVpbGRSZWNvcmRBcnJheSggZGF0ZV9hcnJheSApO1xuXG5cdFx0XHRcdFx0XHR3aWRnZXQuc2V0U291cmNlRGF0YSggZGF0ZV9hcnJheSApO1xuXHRcdFx0XHRcdFx0d2lkZ2V0LnNldFZhbHVlKCBkYXRlX2FycmF5ICk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlICd0b3RhbF90aW1lJzpcblx0XHRcdFx0XHRcdC8vRG9uJ3Qgc2V0IHdoZW4gY29weSBhcyBuZXdcblx0XHRcdFx0XHRcdGlmICggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkICYmIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCAhPSBUVFVVSUQuemVyb19pZCApIHtcblx0XHRcdFx0XHRcdFx0dGhpcy5wcmV2X3RvdGFsX3RpbWUgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRba2V5XTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdHZhciBzdGFydFRpbWUgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRbJ2RhdGVfc3RhbXAnXSArICcgJyArIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFsnc3RhcnRfdGltZSddO1xuXHRcdFx0XHRcdFx0dmFyIGVuZFRpbWUgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRbJ2RhdGVfc3RhbXAnXSArICcgJyArIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFsnZW5kX3RpbWUnXTtcblx0XHRcdFx0XHRcdHZhciBzY2hlZHVsZVBvbGljeUlkID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkWydzY2hlZHVsZV9wb2xpY3lfaWQnXTtcblx0XHRcdFx0XHRcdHZhciB1c2VyX2lkID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnVzZXJfaWQ7XG5cdFx0XHRcdFx0XHR2YXIgdG90YWxfdGltZSA9IHRoaXMuYXBpLmdldFNjaGVkdWxlVG90YWxUaW1lKCBzdGFydFRpbWUsIGVuZFRpbWUsIHNjaGVkdWxlUG9saWN5SWQsIHVzZXJfaWQsIHsgYXN5bmM6IGZhbHNlIH0gKTtcblx0XHRcdFx0XHRcdC8vIEVycm9yOiBVbmNhdWdodCBUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnR5ICdnZXRSZXN1bHQnIG9mIHVuZGVmaW5lZCBpbiBpbnRlcmZhY2UvaHRtbDUvIyFtPVNjaGVkdWxlJmRhdGU9MjAxNjAyMDEmbW9kZT13ZWVrJmE9bmV3JnRhYj1TY2hlZHVsZVxuXHRcdFx0XHRcdFx0dG90YWxfdGltZSA/ICggdG90YWxfdGltZSA9IHRvdGFsX3RpbWUuZ2V0UmVzdWx0KCkgKSA6IHRvdGFsX3RpbWUgPSBmYWxzZTtcblx0XHRcdFx0XHRcdHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC50b3RhbF90aW1lID0gdG90YWxfdGltZTtcblx0XHRcdFx0XHRcdHdpZGdldC5zZXRWYWx1ZSggR2xvYmFsLmdldFRpbWVVbml0KCB0b3RhbF90aW1lICkgKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ2pvYl9pZCc6XG5cdFx0XHRcdFx0XHRpZiAoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpID49IDIwICkge1xuXHRcdFx0XHRcdFx0XHR2YXIgdXNlcl9pZCA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0XHRpZiAoIHRoaXMuZWRpdF92aWV3X3VpX2RpY1sndXNlcl9pZHMnXSAmJiB0aGlzLmVkaXRfdmlld191aV9kaWNbJ3VzZXJfaWRzJ10uaXMoICc6dmlzaWJsZScgKSApIHtcblx0XHRcdFx0XHRcdFx0XHR1c2VyX2lkID0gdGhpcy5nZXRTZWxlY3RVc2Vyc0FycmF5KCk7XG5cblx0XHRcdFx0XHRcdFx0XHQvL0lmIG1vcmUgdGhhbiBvbmUgdXNlciBpcyBzZWxlY3RlZCwgZG9uJ3QgZmlsdGVyIGJ5IHVzZXJfaWQgYXQgYWxsLCBzaG93IGFsbCBqb2JzIGFuZCBsZXQgdGhlIHZhbGlkYXRpb24gc3lzdGVtIGhhbmRsZSBpdC5cblx0XHRcdFx0XHRcdFx0XHRpZiAoIHVzZXJfaWQubGVuZ3RoID09IDEgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHR1c2VyX2lkID0gdXNlcl9pZFswXTtcblx0XHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdFx0dXNlcl9pZCA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHR1c2VyX2lkID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkWyd1c2VyX2lkJ107XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHR2YXIgYXJncyA9IHt9O1xuXHRcdFx0XHRcdFx0XHRhcmdzLmZpbHRlcl9kYXRhID0ge1xuXHRcdFx0XHRcdFx0XHRcdHN0YXR1c19pZDogMTAsXG5cdFx0XHRcdFx0XHRcdFx0dXNlcl9pZDogdXNlcl9pZCxcblx0XHRcdFx0XHRcdFx0XHRwdW5jaF9icmFuY2hfaWQ6IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5icmFuY2hfaWQsXG5cdFx0XHRcdFx0XHRcdFx0cHVuY2hfZGVwYXJ0bWVudF9pZDogdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmRlcGFydG1lbnRfaWRcblx0XHRcdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRcdFx0d2lkZ2V0LnNldERlZmF1bHRBcmdzKCBhcmdzICk7XG5cdFx0XHRcdFx0XHRcdHdpZGdldC5zZXRWYWx1ZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2tleV0gKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ2pvYl9pdGVtX2lkJzpcblx0XHRcdFx0XHRcdGlmICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSB7XG5cdFx0XHRcdFx0XHRcdHZhciBhcmdzID0ge307XG5cdFx0XHRcdFx0XHRcdGFyZ3MuZmlsdGVyX2RhdGEgPSB7IHN0YXR1c19pZDogMTAsIGpvYl9pZDogdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmpvYl9pZCB9O1xuXHRcdFx0XHRcdFx0XHR3aWRnZXQuc2V0RGVmYXVsdEFyZ3MoIGFyZ3MgKTtcblx0XHRcdFx0XHRcdFx0d2lkZ2V0LnNldFZhbHVlKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRba2V5XSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSAncHVuY2hfdGFnX2lkJzpcblx0XHRcdFx0XHRcdGlmICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSB7XG5cdFx0XHRcdFx0XHRcdHdpZGdldC5zZXRWYWx1ZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2tleV0gKTtcblx0XHRcdFx0XHRcdFx0dGhpcy5wcmV2aW91c19wdW5jaF90YWdfc2VsZWN0aW9uID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2tleV07XG5cblx0XHRcdFx0XHRcdFx0dmFyIHB1bmNoX3RhZ193aWRnZXQgPSB3aWRnZXQ7XG5cdFx0XHRcdFx0XHRcdFRUUHJvbWlzZS53YWl0KCBudWxsLCBudWxsLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0XHQvL1VwZGF0ZSBkZWZhdWx0IGFyZ3MgZm9yIHB1bmNoIHRhZ3MgQUNvbWJvQm94IGxhc3QgYXMgdGhleSByZWx5IG9uIGRhdGEgZnJvbSBqb2IsIGpvYiBpdGVtIGFuZCByZWxhdGVkIGZpZWxkcy5cblx0XHRcdFx0XHRcdFx0XHR2YXIgYXJncyA9IHt9O1xuXHRcdFx0XHRcdFx0XHRcdGFyZ3MuZmlsdGVyX2RhdGEgPSAkdGhpcy5nZXRQdW5jaFRhZ0ZpbHRlckRhdGEoKTtcblx0XHRcdFx0XHRcdFx0XHRwdW5jaF90YWdfd2lkZ2V0LnNldERlZmF1bHRBcmdzKCBhcmdzICk7XG5cdFx0XHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ2JyYW5jaF9pZCc6XG5cdFx0XHRcdFx0XHRpZiAoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpID49IDIwICkge1xuXHRcdFx0XHRcdFx0XHR2YXIgYXJncyA9IHt9O1xuXHRcdFx0XHRcdFx0XHRhcmdzLmZpbHRlcl9kYXRhID0geyB1c2VyX2lkOiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudXNlcl9pZCB9O1xuXHRcdFx0XHRcdFx0XHR3aWRnZXQuc2V0RGVmYXVsdEFyZ3MoIGFyZ3MgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdHdpZGdldC5zZXRWYWx1ZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2tleV0gKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ2RlcGFydG1lbnRfaWQnOlxuXHRcdFx0XHRcdFx0aWYgKCBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAyMCApIHtcblx0XHRcdFx0XHRcdFx0dmFyIGFyZ3MgPSB7fTtcblx0XHRcdFx0XHRcdFx0YXJncy5maWx0ZXJfZGF0YSA9IHsgdXNlcl9pZDogdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnVzZXJfaWQsIGJyYW5jaF9pZDogdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmJyYW5jaF9pZCB9O1xuXHRcdFx0XHRcdFx0XHR3aWRnZXQuc2V0RGVmYXVsdEFyZ3MoIGFyZ3MgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdHdpZGdldC5zZXRWYWx1ZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2tleV0gKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ3B1bmNoX3RhZ19xdWlja19zZWFyY2gnOlxuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSAnam9iX3F1aWNrX3NlYXJjaCc6XG4vL1x0XHRcdFx0XHRcdHdpZGdldC5zZXRWYWx1ZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkWydqb2JfaWQnXSA/IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFsnam9iX2lkJ10gOiAwICk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlICdqb2JfaXRlbV9xdWlja19zZWFyY2gnOlxuLy9cdFx0XHRcdFx0XHR3aWRnZXQuc2V0VmFsdWUoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFsnam9iX2l0ZW1faWQnXSA/IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFsnam9iX2l0ZW1faWQnXSA6IDAgKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0XHR3aWRnZXQuc2V0VmFsdWUoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFtrZXldICk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5vbkF2YWlsYWJsZUJhbGFuY2VDaGFuZ2UoKTtcblx0XHR0aGlzLnNldEVkaXRWaWV3RGF0YURvbmUoKTtcblx0fVxuXG5cdHNldEFic2VuY2VQb2xpY3lGaWx0ZXIoIGZpbHRlciApIHtcblx0XHRpZiAoICFmaWx0ZXIuZmlsdGVyX2RhdGEgKSB7XG5cdFx0XHRmaWx0ZXIuZmlsdGVyX2RhdGEgPSB7fTtcblx0XHR9XG5cblx0XHRpZiAoICF0aGlzLmlzX21hc3NfZWRpdGluZyApIHtcblxuXHRcdFx0aWYgKCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkIHx8ICF0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgfHwgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkID09IFRUVVVJRC56ZXJvX2lkICkge1xuXHRcdFx0XHRmaWx0ZXIuZmlsdGVyX2RhdGEudXNlcl9pZCA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC51c2VyX2lkcztcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGZpbHRlci5maWx0ZXJfZGF0YS51c2VyX2lkID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnVzZXJfaWQ7XG5cdFx0XHR9XG5cblx0XHR9IGVsc2Uge1xuXG5cdFx0XHRpZiAoIHRoaXMuZWRpdF92aWV3X3VpX2RpYy51c2VyX2lkLmlzQ2hlY2tlZCgpICkge1xuXHRcdFx0XHRmaWx0ZXIuZmlsdGVyX2RhdGEudXNlcl9pZCA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC51c2VyX2lkO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZmlsdGVyLmZpbHRlcl9kYXRhLnVzZXJfaWQgPSB0aGlzLnNlbGVjdGVkX3VzZXJfaWRzO1xuXHRcdFx0fVxuXG5cdFx0fVxuXG5cdFx0aWYgKCBmaWx0ZXIuZmlsdGVyX2NvbHVtbnMgKSB7XG5cdFx0XHRmaWx0ZXIuZmlsdGVyX2NvbHVtbnMuYWJzZW5jZV9wb2xpY3kgPSB0cnVlO1xuXHRcdH1cblxuXHRcdHJldHVybiBmaWx0ZXI7XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudUNvcHlJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKSB7XG5cdFx0aWYgKCAhdGhpcy5jb3B5UGVybWlzc2lvblZhbGlkYXRlKCkgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApXG5cdFx0fVxuXG5cdFx0aWYgKCBncmlkX3NlbGVjdGVkX2xlbmd0aCA+PSAxICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgdHJ1ZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHRcdH1cblx0fVxuXG5cdHNldERlZmF1bHRNZW51Q29weUFzTmV3SWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICkge1xuXHRcdGlmICggKCAhdGhpcy5jb3B5QXNOZXdQZXJtaXNzaW9uVmFsaWRhdGUoKSApICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdH1cblxuXHRcdGlmICggZ3JpZF9zZWxlY3RlZF9sZW5ndGggPT09IDEgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCB0cnVlICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fVxuXHR9XG5cblxuXHRzZXRDdXN0b21FZGl0TWVudUljb24oIGlkLCBjb250ZXh0X2J0biApIHtcblx0XHRzd2l0Y2ggKCBpZCApIHtcblx0XHRcdGNhc2UgJ2ltcG9ydF9pY29uJzpcblx0XHRcdFx0dGhpcy5zZXRFZGl0TWVudUltcG9ydEljb24oIGNvbnRleHRfYnRuICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnQXV0b1B1bmNoJzpcblx0XHRcdFx0dGhpcy5zZXRFZGl0TWVudUF1dG9QdW5jaEljb24oIGNvbnRleHRfYnRuICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnQWRkUmVxdWVzdCc6XG5cdFx0XHRcdHRoaXMuc2V0RWRpdE1lbnVBZGRSZXF1ZXN0SWNvbiggY29udGV4dF9idG4gKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdmaW5kX2F2YWlsYWJsZSc6XG5cdFx0XHRcdHRoaXMuc2V0RWRpdE1lbnVGaW5kQXZhaWxhYmxlSWNvbiggY29udGV4dF9idG4gKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0fVxuXHR9XG5cblx0X2dldEdyaWRTZWxlY3RlZExlbmd0aCgpIHtcblx0XHR2YXIgcmVzdWx0ID0gMDtcblx0XHRyZXN1bHQgPSB0aGlzLnNlbGVjdF9hbGxfc2hpZnRzX2FycmF5Lmxlbmd0aDtcblxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cblxuXHRzZXRDdXN0b21EZWZhdWx0TWVudUljb24oIGlkLCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKSB7XG5cdFx0c3dpdGNoICggaWQgKSB7XG5cdFx0XHRjYXNlICdtb3ZlJzpcblx0XHRcdFx0aWYgKCAhdGhpcy5tb3ZlUGVybWlzc2lvblZhbGlkYXRlKCkgKSB7XG5cdFx0XHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdFx0XHR9XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnZHJhZ19jb3B5Jzpcblx0XHRcdFx0aWYgKCAhdGhpcy5jb3B5UGVybWlzc2lvblZhbGlkYXRlKCkgKSB7XG5cdFx0XHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdFx0XHR9XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnc3dhcCc6XG5cdFx0XHRcdGlmICggIXRoaXMuZWRpdFBlcm1pc3Npb25WYWxpZGF0ZSgpICkge1xuXHRcdFx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ292ZXJyaWRlJzpcblx0XHRcdFx0aWYgKCAoICF0aGlzLmVkaXRQZXJtaXNzaW9uVmFsaWRhdGUoKSAmJiAhdGhpcy5tb3ZlUGVybWlzc2lvblZhbGlkYXRlKCkgJiYgIXRoaXMuY29weVBlcm1pc3Npb25WYWxpZGF0ZSgpICkgKSB7XG5cdFx0XHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdFx0XHR9XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnZWRpdF9lbXBsb3llZSc6XG5cdFx0XHRcdHRoaXMuc2V0RGVmYXVsdE1lbnVFZGl0RW1wbG95ZWVJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdpbXBvcnRfaWNvbic6XG5cdFx0XHRcdHRoaXMuc2V0RGVmYXVsdE1lbnVJbXBvcnRJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICd0aW1lc2hlZXQnOlxuXHRcdFx0XHR0aGlzLnNldERlZmF1bHRNZW51RWRpdFRpbWVzaGVldEljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ2ZpbmRfYXZhaWxhYmxlJzpcblx0XHRcdFx0dGhpcy5zZXREZWZhdWx0TWVudUZpbmRBdmFpbGFibGV0SWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnQXV0b1B1bmNoJzpcblx0XHRcdFx0dGhpcy5zZXRBdXRvUHVuY2hJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdBZGRSZXF1ZXN0Jzpcblx0XHRcdFx0dGhpcy5zZXRBZGRSZXF1ZXN0SWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdH1cblx0fVxuXG5cdHNldERlZmF1bHRNZW51KCBkb05vdFNldEZvY3VzICkge1xuXHRcdC8vU2NoZWR1bGUgdXNlcyBhIGRpZmZlcmVudCBncmlkIHRoYW4gb3RoZXIgdmlld3MgYW5kIG5lZWRzIFwic2VsZWN0X2FsbF9zaGlmdHNfYXJyYXkubGVuZ3RoXCIgaW5zdGVzZCBvZiBcInRoaXMuZ2V0R3JpZFNlbGVjdElkQXJyYXkoKVwiIGZvciBncmlkX3NlbGVjdGVkX2xlbmd0aFxuXHRcdHN1cGVyLnNldERlZmF1bHRNZW51KCBkb05vdFNldEZvY3VzLCB0aGlzLl9nZXRHcmlkU2VsZWN0ZWRMZW5ndGgoKSApO1xuXHRcdC8vU2V0IG1vdmUgb3IgZHJvcCBtb2RlIGFmdGVyIHJlc3Qgb2YgbWVudS5cblx0XHR0aGlzLnNldE1vdmVPckRyb3BNb2RlKCB0aGlzLnNlbGVjdF9kcmFnX21lbnVfaWQgPyB0aGlzLnNlbGVjdF9kcmFnX21lbnVfaWQgOiAnbW92ZScgKTsgLy8gRW5zdXJlIE1vdmUvQ29weSBzZWxlY3Rpb25zIGFyZSBzZXQgd2hlbiBjbG9zaW5nIHBvcC11cCB3aW5kb3dzIGZyb20gSnVtcC1UbyBtZW51LCBsaWtlIEFkZCBSZXF1ZXN0LlxuXHR9XG5cblx0ZW5hYmxlQWRkUmVxdWVzdEJ1dHRvbigpIHtcblx0XHR2YXIgc2NoZWR1bGVzID0gW107XG5cdFx0Ly92YXIgZ3JpZF9zZWxlY3RlZF9pZF9hcnJheSA9IHRoaXMuZ2V0R3JpZFNlbGVjdElkQXJyYXkoKTtcblx0XHRpZiAoICF0aGlzLnNlbGVjdF9jZWxsbHNfYW5kX3NoaWZ0c19hcnJheSApIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0dmFyIGdyaWRfc2VsZWN0ZWRfaWRfYXJyYXkgPSB0aGlzLnNlbGVjdF9jZWxsbHNfYW5kX3NoaWZ0c19hcnJheTtcblx0XHR2YXIgZ3JpZF9zZWxlY3RlZF9sZW5ndGggPSBncmlkX3NlbGVjdGVkX2lkX2FycmF5Lmxlbmd0aDtcblxuXHRcdGlmICggZ3JpZF9zZWxlY3RlZF9sZW5ndGggPT0gMSApIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblx0XHRpZiAoIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoID09IDAgKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0dmFyIHNjaGVkdWxlcyA9IHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5O1xuXHRcdHZhciBmaXJzdCA9IHNjaGVkdWxlc1swXTtcblxuXHRcdGZvciAoIHZhciBuID0gMTsgbiA8IHNjaGVkdWxlcy5sZW5ndGg7IG4rKyApIHtcblx0XHRcdGlmICggc2NoZWR1bGVzW25dLnVzZXJfaWQgJiYgZmlyc3QudXNlcl9pZCAhPSBzY2hlZHVsZXNbbl0udXNlcl9pZCApIHtcblx0XHRcdFx0RGVidWcuVGV4dCggJ21pc21hdGNoIG9uIHVzZXJfaWQnLCAnU2NoZWR1bGVWaWV3Q29udHJvbGxlci5qcycsICdTY2hlZHVsZVZpZXdDb250cm9sbGVyJywgJ2VuYWJsZUFkZFJlcXVlc3RCdXR0b24nLCAxMCApO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cblx0XHRcdC8vZG8gbm90IHRlc3QgYmxhbmsgY2VsbHMgYmV5b25kIHVzZXJfaWRcblx0XHRcdGlmICggc2NoZWR1bGVzW25dLnNoaWZ0ID09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggKCBmaXJzdC5zaGlmdCAmJiBzY2hlZHVsZXNbbl0uc2hpZnQgKSApIHtcblx0XHRcdFx0aWYgKCBmaXJzdC5zaGlmdC5zdGFydF90aW1lICE9IHNjaGVkdWxlc1tuXS5zaGlmdC5zdGFydF90aW1lICkge1xuXHRcdFx0XHRcdERlYnVnLlRleHQoICdtaXNtYXRjaCBvbiBzdGFydF90aW1lJywgJ1NjaGVkdWxlVmlld0NvbnRyb2xsZXIuanMnLCAnU2NoZWR1bGVWaWV3Q29udHJvbGxlcicsICdlbmFibGVBZGRSZXF1ZXN0QnV0dG9uJywgMTAgKTtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCBmaXJzdC5zaGlmdC5lbmRfdGltZSAhPSBzY2hlZHVsZXNbbl0uc2hpZnQuZW5kX3RpbWUgKSB7XG5cdFx0XHRcdFx0RGVidWcuVGV4dCggJ21pc21hdGNoIG9uIGVuZF90aW1lJywgJ1NjaGVkdWxlVmlld0NvbnRyb2xsZXIuanMnLCAnU2NoZWR1bGVWaWV3Q29udHJvbGxlcicsICdlbmFibGVBZGRSZXF1ZXN0QnV0dG9uJywgMTAgKTtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCBmaXJzdC5zaGlmdC5icmFuY2hfaWQgIT0gc2NoZWR1bGVzW25dLnNoaWZ0LmJyYW5jaF9pZCApIHtcblx0XHRcdFx0XHREZWJ1Zy5UZXh0KCAnbWlzbWF0Y2ggb24gYnJhbmNoX2lkJywgJ1NjaGVkdWxlVmlld0NvbnRyb2xsZXIuanMnLCAnU2NoZWR1bGVWaWV3Q29udHJvbGxlcicsICdlbmFibGVBZGRSZXF1ZXN0QnV0dG9uJywgMTAgKTtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCBmaXJzdC5zaGlmdC5kZXBhcnRtZW50X2lkICE9IHNjaGVkdWxlc1tuXS5zaGlmdC5kZXBhcnRtZW50X2lkICkge1xuXHRcdFx0XHRcdERlYnVnLlRleHQoICdtaXNtYXRjaCBvbiBkZXBhcnRtZW50X2lkJywgJ1NjaGVkdWxlVmlld0NvbnRyb2xsZXIuanMnLCAnU2NoZWR1bGVWaWV3Q29udHJvbGxlcicsICdlbmFibGVBZGRSZXF1ZXN0QnV0dG9uJywgMTAgKTtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCBmaXJzdC5zaGlmdC5qb2JfaWQgIT0gc2NoZWR1bGVzW25dLnNoaWZ0LmpvYl9pZCApIHtcblx0XHRcdFx0XHREZWJ1Zy5UZXh0KCAnbWlzbWF0Y2ggb24gam9iX2lkJywgJ1NjaGVkdWxlVmlld0NvbnRyb2xsZXIuanMnLCAnU2NoZWR1bGVWaWV3Q29udHJvbGxlcicsICdlbmFibGVBZGRSZXF1ZXN0QnV0dG9uJywgMTAgKTtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCBmaXJzdC5zaGlmdC5qb2JfaXRlbV9pZCAhPSBzY2hlZHVsZXNbbl0uc2hpZnQuam9iX2l0ZW1faWQgKSB7XG5cdFx0XHRcdFx0RGVidWcuVGV4dCggJ21pc21hdGNoIG9uIGpvYl9pdGVtX2lkJywgJ1NjaGVkdWxlVmlld0NvbnRyb2xsZXIuanMnLCAnU2NoZWR1bGVWaWV3Q29udHJvbGxlcicsICdlbmFibGVBZGRSZXF1ZXN0QnV0dG9uJywgMTAgKTtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCBmaXJzdC5zaGlmdC5wdW5jaF90YWdfaWQgIT0gc2NoZWR1bGVzW25dLnNoaWZ0LnB1bmNoX3RhZ19pZCApIHtcblx0XHRcdFx0XHREZWJ1Zy5UZXh0KCAnbWlzbWF0Y2ggb24gcHVuY2hfdGFnX2lkJywgJ1NjaGVkdWxlVmlld0NvbnRyb2xsZXIuanMnLCAnU2NoZWR1bGVWaWV3Q29udHJvbGxlcicsICdlbmFibGVBZGRSZXF1ZXN0QnV0dG9uJywgMTAgKTtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIGZpcnN0LnNoaWZ0LnNjaGVkdWxlX3BvbGljeV9pZCAhPSBzY2hlZHVsZXNbbl0uc2hpZnQuc2NoZWR1bGVfcG9saWN5X2lkICkge1xuXHRcdFx0XHRcdERlYnVnLlRleHQoICdtaXNtYXRjaCBvbiBzY2hlZHVsZV9wb2xpY3lfaWQnLCAnU2NoZWR1bGVWaWV3Q29udHJvbGxlci5qcycsICdTY2hlZHVsZVZpZXdDb250cm9sbGVyJywgJ2VuYWJsZUFkZFJlcXVlc3RCdXR0b24nLCAxMCApO1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggZmlyc3Quc2hpZnQuc3RhdHVzX2lkICE9IHNjaGVkdWxlc1tuXS5zaGlmdC5zdGF0dXNfaWQgKSB7XG5cdFx0XHRcdFx0RGVidWcuVGV4dCggJ21pc21hdGNoIG9uIHN0YXR1c19pZCcsICdTY2hlZHVsZVZpZXdDb250cm9sbGVyLmpzJywgJ1NjaGVkdWxlVmlld0NvbnRyb2xsZXInLCAnZW5hYmxlQWRkUmVxdWVzdEJ1dHRvbicsIDEwICk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICggZmlyc3Quc2hpZnQuc3RhdHVzX2lkID09IDIwICYmIGZpcnN0LnNoaWZ0LmFic2VuY2VfcG9saWN5X2lkICE9IHNjaGVkdWxlc1tuXS5zaGlmdC5hYnNlbmNlX3BvbGljeV9pZCApIHtcblx0XHRcdFx0XHREZWJ1Zy5UZXh0KCAnbWlzbWF0Y2ggb24gYWJzZW5jZV9wb2xpY3lfaWQnLCAnU2NoZWR1bGVWaWV3Q29udHJvbGxlci5qcycsICdTY2hlZHVsZVZpZXdDb250cm9sbGVyJywgJ2VuYWJsZUFkZFJlcXVlc3RCdXR0b24nLCAxMCApO1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0XHQvL2lmIHRoZSBmaXJzdCBvbmUgaXMgYSBibGFuayBpbiBhIHNlbGVjdGlvbiB0aGF0IGluY2x1ZGVzIHNoaWZ0cywgd2UgbmVlZCB0byB1cGRhdGUgdGhlIGNvbXBhcmVkIHJlY29yZCB0byBvbmUgd2l0aCBhIHNoaWZ0LlxuXHRcdFx0fSBlbHNlIGlmICggZmlyc3Quc2hpZnQgPT0gdW5kZWZpbmVkICYmIHNjaGVkdWxlc1tuXS5zaGlmdCApIHtcblx0XHRcdFx0Zmlyc3QgPSBzY2hlZHVsZXNbbl07XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0RGVidWcuVGV4dCggJ0FsbCBTZWxlY3RlZCBTY2hlZHVsZXMgTWF0Y2gnLCAnU2NoZWR1bGVWaWV3Q29udHJvbGxlci5qcycsICdTY2hlZHVsZVZpZXdDb250cm9sbGVyJywgJ2VuYWJsZUFkZFJlcXVlc3RCdXR0b24nLCAxMCApO1xuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0c2V0QXV0b1B1bmNoSWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICkge1xuXHRcdGlmICggZ3JpZF9zZWxlY3RlZF9sZW5ndGggPiAwICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgdHJ1ZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHRcdH1cblx0fVxuXG5cdHNldEVkaXRNZW51QXV0b1B1bmNoSWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICkge1xuXHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCB0cnVlICk7XG5cdH1cblxuXHRzZXRFZGl0TWVudUFkZFJlcXVlc3RJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKSB7XG5cdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIHRydWUgKTtcblx0fVxuXG5cdHNldEVkaXRNZW51RmluZEF2YWlsYWJsZUljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApIHtcblx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApXG5cdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgdHJ1ZSApO1xuXHR9XG5cblx0c2V0RGVmYXVsdE1lbnVGaW5kQXZhaWxhYmxldEljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApIHtcblx0XHRpZiAoICF0aGlzLmVkaXRDaGlsZFBlcm1pc3Npb25WYWxpZGF0ZSgpICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdH1cblxuXHRcdGlmICggZ3JpZF9zZWxlY3RlZF9sZW5ndGggPj0gMSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIHRydWUgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudUVkaXRUaW1lc2hlZXRJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKSB7XG5cblx0XHRpZiAoIHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5Lmxlbmd0aCA9PT0gMSAmJiBUVFVVSUQuaXNVVUlEKCB0aGlzLnNlbGVjdF9jZWxsc19BcnJheVswXS51c2VyX2lkICkgJiYgdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXlbMF0udXNlcl9pZCAhPSBUVFVVSUQuemVyb19pZCApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIHRydWUgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudUVkaXRFbXBsb3llZUljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApIHtcblxuXHRcdGlmICggIXRoaXMuZWRpdENoaWxkUGVybWlzc2lvblZhbGlkYXRlKCAndXNlcicgKSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHR9XG5cblx0XHRpZiAoIHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5Lmxlbmd0aCA9PT0gMSAmJiBUVFVVSUQuaXNVVUlEKCB0aGlzLnNlbGVjdF9jZWxsc19BcnJheVswXS51c2VyX2lkICkgJiYgdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXlbMF0udXNlcl9pZCAhPSBUVFVVSUQuemVyb19pZCApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIHRydWUgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRvblVwZGF0ZUxheW91dCgpIHtcblxuXHRcdHZhciBzZWxlY3RJZCA9ICQoIHRoaXMucHJldmlvdXNfc2F2ZWRfbGF5b3V0X3NlbGVjdG9yICkuY2hpbGRyZW4oICdvcHRpb246c2VsZWN0ZWQnICkuYXR0ciggJ3ZhbHVlJyApO1xuXHRcdHZhciBsYXlvdXRfbmFtZSA9ICQoIHRoaXMucHJldmlvdXNfc2F2ZWRfbGF5b3V0X3NlbGVjdG9yICkuY2hpbGRyZW4oICdvcHRpb246c2VsZWN0ZWQnICkudGV4dCgpO1xuXG5cdFx0dmFyIHNlbGVjdGVkX2Rpc3BsYXlfY29sdW1ucyA9IHRoaXMuZ2V0U2VhcmNoUGFuZWxEaXNwbGF5Q29sdW1ucygpO1xuXHRcdHZhciBmaWx0ZXJfZGF0YSA9IHRoaXMuZ2V0VmFsaWRTZWFyY2hGaWx0ZXIoKTtcblxuXHRcdHZhciBhcmdzID0ge307XG5cdFx0YXJncy5pZCA9IHNlbGVjdElkO1xuXHRcdGFyZ3MuZGF0YSA9IHt9O1xuXHRcdGFyZ3MuZGF0YS5kaXNwbGF5X2NvbHVtbnMgPSBzZWxlY3RlZF9kaXNwbGF5X2NvbHVtbnM7XG5cdFx0YXJncy5kYXRhLmZpbHRlcl9kYXRhID0gZmlsdGVyX2RhdGE7XG5cdFx0YXJncy5kYXRhLm1vZGUgPSBHbG9iYWwudXBDYXNlRmlyc3RMZXR0ZXIoIHRoaXMuZ2V0TW9kZSgpICk7XG5cdFx0YXJncy5kYXRhLnN0cmljdFJhbmdlID0gdGhpcy5zZXR0aW5nc19tZW51LmdldEJ1dHRvbiggJ3N0cmljdF9yYW5nZV9idG4nICkuYWN0aXZlO1xuXHRcdGFyZ3MuZGF0YS53ZWVrbHlUb3RhbHMgPSB0aGlzLnNldHRpbmdzX21lbnUuZ2V0QnV0dG9uKCAnd2Vla2x5X3RvdGFsc19idG4nICkuYWN0aXZlO1xuXHRcdGFyZ3MuZGF0YS5kYWlseVRvdGFscyA9IHRoaXMuc2V0dGluZ3NfbWVudS5nZXRCdXR0b24oICdkYWlseV90b3RhbHNfYnRuJyApLmFjdGl2ZTtcblx0XHRhcmdzLmRhdGEuc2hvd0FsbEVtcCA9IHRoaXMuc2V0dGluZ3NfbWVudS5nZXRCdXR0b24oICdhbGxfZW1wbG95ZWVfYnRuJyApLmFjdGl2ZTtcblxuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dGhpcy51c2VyX2dlbmVyaWNfZGF0YV9hcGkuc2V0VXNlckdlbmVyaWNEYXRhKCBhcmdzLCB7XG5cdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlcyApIHtcblxuXHRcdFx0XHRpZiAoIHJlcy5pc1ZhbGlkKCkgKSB7XG5cdFx0XHRcdFx0JHRoaXMuY2xlYXJWaWV3TGF5b3V0Q2FjaGUoKTtcblx0XHRcdFx0XHQkdGhpcy5uZWVkX3NlbGVjdF9sYXlvdXRfbmFtZSA9IGxheW91dF9uYW1lO1xuXHRcdFx0XHRcdCR0aGlzLmluaXRMYXlvdXQoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cblx0b25TYXZlTmV3TGF5b3V0KCBkZWZhdWx0X2xheW91dF9uYW1lICkge1xuXG5cdFx0aWYgKCBHbG9iYWwuaXNTZXQoIGRlZmF1bHRfbGF5b3V0X25hbWUgKSApIHtcblx0XHRcdHZhciBsYXlvdXRfbmFtZSA9IGRlZmF1bHRfbGF5b3V0X25hbWU7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGxheW91dF9uYW1lID0gdGhpcy5zYXZlX3NlYXJjaF9hc19pbnB1dC5nZXRWYWx1ZSgpO1xuXHRcdH1cblxuXHRcdGlmICggIWxheW91dF9uYW1lIHx8IGxheW91dF9uYW1lLmxlbmd0aCA8IDEgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIHNlbGVjdGVkX2Rpc3BsYXlfY29sdW1ucyA9IHRoaXMuZ2V0U2VhcmNoUGFuZWxEaXNwbGF5Q29sdW1ucygpO1xuXHRcdHZhciBmaWx0ZXJfZGF0YSA9IHRoaXMuZ2V0VmFsaWRTZWFyY2hGaWx0ZXIoKTtcblxuXHRcdHZhciBhcmdzID0ge307XG5cdFx0YXJncy5zY3JpcHQgPSB0aGlzLnNjcmlwdF9uYW1lO1xuXHRcdGFyZ3MubmFtZSA9IGxheW91dF9uYW1lO1xuXHRcdGFyZ3MuaXNfZGVmYXVsdCA9IGZhbHNlO1xuXHRcdGFyZ3MuZGF0YSA9IHt9O1xuXHRcdGFyZ3MuZGF0YS5kaXNwbGF5X2NvbHVtbnMgPSBzZWxlY3RlZF9kaXNwbGF5X2NvbHVtbnM7XG5cdFx0YXJncy5kYXRhLmZpbHRlcl9kYXRhID0gZmlsdGVyX2RhdGE7XG5cdFx0YXJncy5kYXRhLm1vZGUgPSBHbG9iYWwudXBDYXNlRmlyc3RMZXR0ZXIoIHRoaXMuZ2V0TW9kZSgpICk7XG5cdFx0YXJncy5kYXRhLnN0cmljdFJhbmdlID0gdGhpcy5zZXR0aW5nc19tZW51LmdldEJ1dHRvbiggJ3N0cmljdF9yYW5nZV9idG4nICkuYWN0aXZlO1xuXHRcdGFyZ3MuZGF0YS53ZWVrbHlUb3RhbHMgPSB0aGlzLnNldHRpbmdzX21lbnUuZ2V0QnV0dG9uKCAnd2Vla2x5X3RvdGFsc19idG4nICkuYWN0aXZlO1xuXHRcdGFyZ3MuZGF0YS5kYWlseVRvdGFscyA9IHRoaXMuc2V0dGluZ3NfbWVudS5nZXRCdXR0b24oICdkYWlseV90b3RhbHNfYnRuJyApLmFjdGl2ZTtcblx0XHRhcmdzLmRhdGEuc2hvd0FsbEVtcCA9IHRoaXMuc2V0dGluZ3NfbWVudS5nZXRCdXR0b24oICdhbGxfZW1wbG95ZWVfYnRuJyApLmFjdGl2ZTtcblxuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dGhpcy51c2VyX2dlbmVyaWNfZGF0YV9hcGkuc2V0VXNlckdlbmVyaWNEYXRhKCBhcmdzLCB7XG5cdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlcyApIHtcblxuXHRcdFx0XHRpZiAoIHJlcy5pc1ZhbGlkKCkgKSB7XG5cdFx0XHRcdFx0JHRoaXMuY2xlYXJWaWV3TGF5b3V0Q2FjaGUoKTtcblx0XHRcdFx0XHQkdGhpcy5uZWVkX3NlbGVjdF9sYXlvdXRfbmFtZSA9IGxheW91dF9uYW1lO1xuXHRcdFx0XHRcdCR0aGlzLmluaXRMYXlvdXQoKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRUQWxlcnRNYW5hZ2VyLnNob3dFcnJvckFsZXJ0KCByZXMgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cblx0b25DbGVhclNlYXJjaCgpIHtcblx0XHR2YXIgZG9fdXBkYXRlID0gZmFsc2U7XG5cdFx0aWYgKCB0aGlzLnNlYXJjaF9wYW5lbC5nZXRMYXlvdXRzQXJyYXkoKSAmJiB0aGlzLnNlYXJjaF9wYW5lbC5nZXRMYXlvdXRzQXJyYXkoKS5sZW5ndGggPiAwICkge1xuXHRcdFx0dmFyIGRlZmF1bHRfbGF5b3V0X2lkID0gJCggdGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfc2VsZWN0b3IgKS5jaGlsZHJlbiggJ29wdGlvbjpjb250YWlucyhcXCcnICsgQmFzZVZpZXdDb250cm9sbGVyLmRlZmF1bHRfbGF5b3V0X25hbWUgKyAnXFwnKScgKS5hdHRyKCAndmFsdWUnICk7XG5cdFx0XHR2YXIgbGF5b3V0X25hbWUgPSBCYXNlVmlld0NvbnRyb2xsZXIuZGVmYXVsdF9sYXlvdXRfbmFtZTtcblx0XHRcdHRoaXMuY2xlYXJTZWFyY2hQYW5lbCgpO1xuXHRcdFx0dGhpcy5maWx0ZXJfZGF0YSA9IG51bGw7XG5cdFx0XHR0aGlzLnRlbXBfYWR2X2ZpbHRlcl9kYXRhID0gbnVsbDtcblx0XHRcdHRoaXMudGVtcF9iYXNpY19maWx0ZXJfZGF0YSA9IG51bGw7XG5cdFx0XHRkb191cGRhdGUgPSB0cnVlO1xuXG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0dGhpcy5jbGVhclNlYXJjaFBhbmVsKCk7XG5cdFx0XHR0aGlzLmZpbHRlcl9kYXRhID0gbnVsbDtcblx0XHRcdHRoaXMudGVtcF9hZHZfZmlsdGVyX2RhdGEgPSBudWxsO1xuXHRcdFx0dGhpcy50ZW1wX2Jhc2ljX2ZpbHRlcl9kYXRhID0gbnVsbDtcblxuXHRcdFx0dGhpcy5jb2x1bW5fc2VsZWN0b3Iuc2V0U2VsZWN0R3JpZERhdGEoIHRoaXMuZGVmYXVsdF9kaXNwbGF5X2NvbHVtbnMgKTtcblxuXHRcdFx0dGhpcy5vblNhdmVOZXdMYXlvdXQoIEJhc2VWaWV3Q29udHJvbGxlci5kZWZhdWx0X2xheW91dF9uYW1lICk7XG5cdFx0XHRyZXR1cm47XG5cblx0XHR9XG5cblx0XHR2YXIgc2VsZWN0ZWRfZGlzcGxheV9jb2x1bW5zID0gdGhpcy5nZXRTZWFyY2hQYW5lbERpc3BsYXlDb2x1bW5zKCk7XG5cdFx0dmFyIGZpbHRlcl9kYXRhID0gdGhpcy5nZXRWYWxpZFNlYXJjaEZpbHRlcigpO1xuXG5cdFx0aWYgKCBkb191cGRhdGUgKSB7XG5cdFx0XHR2YXIgYXJncyA9IHt9O1xuXHRcdFx0YXJncy5pZCA9IGRlZmF1bHRfbGF5b3V0X2lkO1xuXHRcdFx0YXJncy5kYXRhID0ge307XG5cdFx0XHRhcmdzLmRhdGEuZGlzcGxheV9jb2x1bW5zID0gc2VsZWN0ZWRfZGlzcGxheV9jb2x1bW5zO1xuXHRcdFx0YXJncy5kYXRhLmZpbHRlcl9kYXRhID0gZmlsdGVyX2RhdGE7XG5cdFx0fVxuXG5cdFx0YXJncy5kYXRhLm1vZGUgPSB0aGlzLmdldE1vZGUoKTtcblxuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dGhpcy51c2VyX2dlbmVyaWNfZGF0YV9hcGkuc2V0VXNlckdlbmVyaWNEYXRhKCBhcmdzLCB7XG5cdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlcyApIHtcblxuXHRcdFx0XHRpZiAoIHJlcy5pc1ZhbGlkKCkgKSB7XG5cdFx0XHRcdFx0JHRoaXMuY2xlYXJWaWV3TGF5b3V0Q2FjaGUoKTtcblx0XHRcdFx0XHQkdGhpcy5uZWVkX3NlbGVjdF9sYXlvdXRfbmFtZSA9IGxheW91dF9uYW1lO1xuXHRcdFx0XHRcdCR0aGlzLmluaXRMYXlvdXQoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cblx0Z2V0U2VhcmNoUGFuZWxEaXNwbGF5Q29sdW1ucygpIHtcblx0XHR2YXIgZGlzcGxheV9jb2x1bW5zID0gW107XG5cblx0XHR2YXIgc2VsZWN0X2l0ZW1zID0gdGhpcy5jb2x1bW5fc2VsZWN0b3IuZ2V0U2VsZWN0SXRlbXMoKTtcblxuXHRcdGlmICggc2VsZWN0X2l0ZW1zICYmIHNlbGVjdF9pdGVtcy5sZW5ndGggPiAwICkge1xuXHRcdFx0JC5lYWNoKCBzZWxlY3RfaXRlbXMsIGZ1bmN0aW9uKCBpbmRleCwgY29udGVudCApIHtcblx0XHRcdFx0ZGlzcGxheV9jb2x1bW5zLnB1c2goIGNvbnRlbnQudmFsdWUgKTtcblx0XHRcdH0gKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZGlzcGxheV9jb2x1bW5zO1xuXHR9XG5cblx0b25TZWFyY2goIHNhdmVfb25seSApIHtcblx0XHR0aGlzLnRlbXBfYWR2X2ZpbHRlcl9kYXRhID0gbnVsbDtcblx0XHR0aGlzLnRlbXBfYmFzaWNfZmlsdGVyX2RhdGEgPSBudWxsO1xuXG5cdFx0dGhpcy5nZXRTZWFyY2hQYW5lbEZpbHRlcigpO1xuXG5cdFx0aWYgKCB0aGlzLnNlYXJjaF9wYW5lbC5nZXRMYXlvdXRzQXJyYXkoKSAmJiB0aGlzLnNlYXJjaF9wYW5lbC5nZXRMYXlvdXRzQXJyYXkoKS5sZW5ndGggPiAwICkge1xuXHRcdFx0dmFyIGRlZmF1bHRfbGF5b3V0X2lkID0gJCggdGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfc2VsZWN0b3IgKS5jaGlsZHJlbiggJ29wdGlvbjpjb250YWlucyhcXCcnICsgQmFzZVZpZXdDb250cm9sbGVyLmRlZmF1bHRfbGF5b3V0X25hbWUgKyAnXFwnKScgKS5hdHRyKCAndmFsdWUnICk7XG5cblx0XHRcdGlmICggIWRlZmF1bHRfbGF5b3V0X2lkICkge1xuXHRcdFx0XHR0aGlzLm9uU2F2ZU5ld0xheW91dCggQmFzZVZpZXdDb250cm9sbGVyLmRlZmF1bHRfbGF5b3V0X25hbWUgKTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0dmFyIGxheW91dF9uYW1lID0gQmFzZVZpZXdDb250cm9sbGVyLmRlZmF1bHRfbGF5b3V0X25hbWU7XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5vblNhdmVOZXdMYXlvdXQoIEJhc2VWaWV3Q29udHJvbGxlci5kZWZhdWx0X2xheW91dF9uYW1lICk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIHNlbGVjdGVkX2Rpc3BsYXlfY29sdW1ucyA9IHRoaXMuZ2V0U2VhcmNoUGFuZWxEaXNwbGF5Q29sdW1ucygpO1xuXHRcdHZhciBmaWx0ZXJfZGF0YSA9IHRoaXMuZ2V0VmFsaWRTZWFyY2hGaWx0ZXIoKTtcblxuXHRcdHZhciBhcmdzID0ge307XG5cdFx0YXJncy5pZCA9IGRlZmF1bHRfbGF5b3V0X2lkO1xuXHRcdGFyZ3MuZGF0YSA9IHt9O1xuXHRcdGFyZ3MuZGF0YS5kaXNwbGF5X2NvbHVtbnMgPSBzZWxlY3RlZF9kaXNwbGF5X2NvbHVtbnM7XG5cdFx0YXJncy5kYXRhLmZpbHRlcl9kYXRhID0gZmlsdGVyX2RhdGE7XG5cdFx0YXJncy5kYXRhLm1vZGUgPSBHbG9iYWwudXBDYXNlRmlyc3RMZXR0ZXIoIHRoaXMuZ2V0TW9kZSgpICk7XG5cdFx0YXJncy5kYXRhLnN0cmljdFJhbmdlID0gdGhpcy5zZXR0aW5nc19tZW51LmdldEJ1dHRvbiggJ3N0cmljdF9yYW5nZV9idG4nICkuYWN0aXZlO1xuXHRcdGFyZ3MuZGF0YS53ZWVrbHlUb3RhbHMgPSB0aGlzLnNldHRpbmdzX21lbnUuZ2V0QnV0dG9uKCAnd2Vla2x5X3RvdGFsc19idG4nICkuYWN0aXZlO1xuXHRcdGFyZ3MuZGF0YS5kYWlseVRvdGFscyA9IHRoaXMuc2V0dGluZ3NfbWVudS5nZXRCdXR0b24oICdkYWlseV90b3RhbHNfYnRuJyApLmFjdGl2ZTtcblx0XHRhcmdzLmRhdGEuc2hvd0FsbEVtcCA9IHRoaXMuc2V0dGluZ3NfbWVudS5nZXRCdXR0b24oICdhbGxfZW1wbG95ZWVfYnRuJyApLmFjdGl2ZTtcblxuXHRcdFByb2dyZXNzQmFyLnNob3dPdmVybGF5KCk7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR0aGlzLnVzZXJfZ2VuZXJpY19kYXRhX2FwaS5zZXRVc2VyR2VuZXJpY0RhdGEoIGFyZ3MsIHtcblx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzICkge1xuXHRcdFx0XHRpZiAoIHJlcy5pc1ZhbGlkKCkgKSB7XG5cdFx0XHRcdFx0JHRoaXMuY2xlYXJWaWV3TGF5b3V0Q2FjaGUoKTtcblx0XHRcdFx0XHQkdGhpcy5uZWVkX3NlbGVjdF9sYXlvdXRfbmFtZSA9IGxheW91dF9uYW1lO1xuXHRcdFx0XHRcdGlmICggIXNhdmVfb25seSApIHtcblx0XHRcdFx0XHRcdCR0aGlzLmluaXRMYXlvdXQoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cblxuXHRzZXRTZWxlY3RMYXlvdXQoKSB7XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXG5cdFx0aWYgKCAhdGhpcy5zZWxlY3RfbGF5b3V0ICkgeyAvL1NldCB0byBkZWZhbHQgbGF5b3V0IGlmIG5vIGxheW91dCBhdCBhbGxcblx0XHRcdHRoaXMuc2VsZWN0X2xheW91dCA9IHsgaWQ6ICcnIH07XG5cdFx0XHR0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YSA9IHsgZmlsdGVyX2RhdGE6IHt9LCBmaWx0ZXJfc29ydDoge30gfTtcblx0XHRcdHRoaXMuc2VsZWN0X2xheW91dC5kYXRhLmRpc3BsYXlfY29sdW1ucyA9IHRoaXMuZGVmYXVsdF9kaXNwbGF5X2NvbHVtbnM7XG5cdFx0fVxuXG5cdFx0dmFyIGxheW91dF9kYXRhID0gdGhpcy5zZWxlY3RfbGF5b3V0LmRhdGE7XG5cblx0XHR2YXIgZGlzcGxheV9jb2x1bW5zID0gdGhpcy5idWlsZERpc3BsYXlDb2x1bW5zKCBsYXlvdXRfZGF0YS5kaXNwbGF5X2NvbHVtbnMgKTtcblxuXHRcdGlmICggR2xvYmFsLmlzU2V0KCBsYXlvdXRfZGF0YS5tb2RlICkgJiYgbGF5b3V0X2RhdGEubW9kZSAhPSAnJyApIHtcblx0XHRcdCR0aGlzLnNldFRvZ2dsZUJ1dHRvblZhbHVlKCBsYXlvdXRfZGF0YS5tb2RlLnRvTG93ZXJDYXNlKCkgKTtcblx0XHR9IGVsc2UgaWYgKCBMb2NhbENhY2hlRGF0YS5nZXRBbGxVUkxBcmdzKCkgJiYgTG9jYWxDYWNoZURhdGEuZ2V0QWxsVVJMQXJncygpLm1vZGUgKSB7XG5cdFx0XHQkdGhpcy5zZXRUb2dnbGVCdXR0b25WYWx1ZSggTG9jYWxDYWNoZURhdGEuZ2V0QWxsVVJMQXJncygpLm1vZGUgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JHRoaXMuc2V0VG9nZ2xlQnV0dG9uVmFsdWUoIFNjaGVkdWxlVmlld0NvbnRyb2xsZXJNb2RlLldFRUsgKTtcblx0XHR9XG5cblx0XHRpZiAoIGxheW91dF9kYXRhLmhhc093blByb3BlcnR5KCAnc3RyaWN0UmFuZ2UnICkgKSB7XG5cdFx0XHRpZiAoIGxheW91dF9kYXRhLnN0cmljdFJhbmdlICkge1xuXHRcdFx0XHR0aGlzLnNldHRpbmdzX21lbnUuYWN0aXZhdGVCdXR0b24oICdzdHJpY3RfcmFuZ2VfYnRuJyApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5zZXR0aW5nc19tZW51LmRlYWN0aXZhdGVCdXR0b24oICdzdHJpY3RfcmFuZ2VfYnRuJyApO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnNldHRpbmdzX21lbnUuYWN0aXZhdGVCdXR0b24oICdzdHJpY3RfcmFuZ2VfYnRuJyApO1xuXHRcdH1cblxuXHRcdGlmICggbGF5b3V0X2RhdGEud2Vla2x5VG90YWxzICkge1xuXHRcdFx0dGhpcy5zZXR0aW5nc19tZW51LmFjdGl2YXRlQnV0dG9uKCAnd2Vla2x5X3RvdGFsc19idG4nICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuc2V0dGluZ3NfbWVudS5kZWFjdGl2YXRlQnV0dG9uKCAnd2Vla2x5X3RvdGFsc19idG4nICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBsYXlvdXRfZGF0YS5kYWlseVRvdGFscyApIHtcblx0XHRcdHRoaXMuc2V0dGluZ3NfbWVudS5hY3RpdmF0ZUJ1dHRvbiggJ2RhaWx5X3RvdGFsc19idG4nICk7XG5cdFx0fSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuc2V0dGluZ3NfbWVudS5kZWFjdGl2YXRlQnV0dG9uKCAnZGFpbHlfdG90YWxzX2J0bicgKTtcbiAgICAgICAgfVxuXG5cdFx0aWYgKCBsYXlvdXRfZGF0YS5zaG93QWxsRW1wICkge1xuXHRcdFx0dGhpcy5zZXR0aW5nc19tZW51LmFjdGl2YXRlQnV0dG9uKCAnYWxsX2VtcGxveWVlX2J0bicgKTtcblx0XHR9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zZXR0aW5nc19tZW51LmRlYWN0aXZhdGVCdXR0b24oICdhbGxfZW1wbG95ZWVfYnRuJyApO1xuICAgICAgICB9XG5cblx0XHQvL1NldCBEaXNwbGF5IENvbHVtbiBpbiBsYXlvdXQgcGFuZWxcblx0XHR0aGlzLmNvbHVtbl9zZWxlY3Rvci5zZXRTZWxlY3RHcmlkRGF0YSggZGlzcGxheV9jb2x1bW5zICk7XG5cblx0XHQvL1NldCBQcmV2aW9vdXMgU2F2ZWQgbGF5b3V0IGNvbWJvYm94IGluIGxheW91dCBwYW5lbFxuXHRcdHZhciBsYXlvdXRzX2FycmF5ID0gdGhpcy5zZWFyY2hfcGFuZWwuZ2V0TGF5b3V0c0FycmF5KCk7XG5cblx0XHR0aGlzLnByZXZpb3VzX3NhdmVkX2xheW91dF9zZWxlY3Rvci5lbXB0eSgpO1xuXHRcdGlmICggbGF5b3V0c19hcnJheSAmJiBsYXlvdXRzX2FycmF5Lmxlbmd0aCA+IDAgKSB7XG5cdFx0XHR0aGlzLnByZXZpb3VzX3NhdmVkX2xheW91dF9kaXYuY3NzKCAnZGlzcGxheScsICdpbmxpbmUnICk7XG5cblx0XHRcdHZhciBsZW4gPSBsYXlvdXRzX2FycmF5Lmxlbmd0aDtcblx0XHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0XHR2YXIgaXRlbSA9IGxheW91dHNfYXJyYXlbaV07XG5cdFx0XHRcdHRoaXMucHJldmlvdXNfc2F2ZWRfbGF5b3V0X3NlbGVjdG9yLmFwcGVuZCggJCggJzxvcHRpb24gdmFsdWU9XCInICsgaXRlbS5pZCArICdcIj48L29wdGlvbj4nICkudGV4dCggaXRlbS5uYW1lICkgKTtcblx0XHRcdH1cblx0XHRcdCQoIHRoaXMucHJldmlvdXNfc2F2ZWRfbGF5b3V0X3NlbGVjdG9yLmZpbmQoICdvcHRpb24nICkgKS5maWx0ZXIoIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRyZXR1cm4gJCggdGhpcyApLmF0dHIoICd2YWx1ZScgKSA9PT0gJHRoaXMuc2VsZWN0X2xheW91dC5pZDtcblx0XHRcdH0gKS5wcm9wKCAnc2VsZWN0ZWQnLCB0cnVlICkuYXR0ciggJ3NlbGVjdGVkJywgdHJ1ZSApO1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMucHJldmlvdXNfc2F2ZWRfbGF5b3V0X2Rpdi5jc3MoICdkaXNwbGF5JywgJ25vbmUnICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBMb2NhbENhY2hlRGF0YS5kZWZhdWx0X2ZpbHRlcl9mb3JfbmV4dF9vcGVuX3ZpZXcgKSB7XG5cdFx0XHR0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5maWx0ZXJfZGF0YSA9IExvY2FsQ2FjaGVEYXRhLmRlZmF1bHRfZmlsdGVyX2Zvcl9uZXh0X29wZW5fdmlldy5maWx0ZXJfZGF0YTtcblxuXHRcdFx0dGhpcy5zZXREYXRlUGlja2VyVmFsdWUoIExvY2FsQ2FjaGVEYXRhLmRlZmF1bHRfZmlsdGVyX2Zvcl9uZXh0X29wZW5fdmlldy5zZWxlY3RfZGF0ZSApO1xuXG5cdFx0XHR0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5tb2RlID0gJ1dlZWsnO1xuXHRcdFx0JHRoaXMuc2V0VG9nZ2xlQnV0dG9uVmFsdWUoIGxheW91dF9kYXRhLm1vZGUudG9Mb3dlckNhc2UoKSApO1xuXG5cdFx0XHRMb2NhbENhY2hlRGF0YS5kZWZhdWx0X2ZpbHRlcl9mb3JfbmV4dF9vcGVuX3ZpZXcgPSBudWxsO1xuXHRcdH1cblxuXHRcdHRoaXMuZmlsdGVyX2RhdGEgPSB0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5maWx0ZXJfZGF0YTtcblxuXHRcdHRoaXMuc2V0U2VhcmNoUGFuZWxGaWx0ZXIoIHRydWUgKTtcblx0fVxuXG5cdGdldE1vZGUoKSB7XG5cdFx0aWYgKCB0aGlzLnRvZ2dsZV9idXR0b24gKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy50b2dnbGVfYnV0dG9uLmdldFZhbHVlKCk7XG5cdFx0fVxuXHR9XG5cblx0c2VhcmNoKCBzZXREZWZhdWx0TWVudSwgdXNlX2RhdGVfcGlja2VyX2RhdGUgKSB7XG5cdFx0Ly9Jc3N1ZSAjMzA5NSAtIFJhY2UgY29uZGl0aW9uIHdoZXJlIGEgdXNlciBzd2l0Y2hlcyB2aWV3cyB3aGlsZSB0aGUgc2NoZWR1bGUgaXMgc3RpbGwgbG9hZGluZyBjYW4gY2F1c2UgYW4gZXhjZXB0aW9uLlxuXHRcdGlmICggISggTG9jYWxDYWNoZURhdGEuY3VycmVudF9vcGVuX3ByaW1hcnlfY29udHJvbGxlci52aWV3SWQgPT09ICdTY2hlZHVsZScgfHwgTG9jYWxDYWNoZURhdGEuY3VycmVudF9vcGVuX3ByaW1hcnlfY29udHJvbGxlci52aWV3SWQgPT09ICdGaW5kQXZhaWxhYmxlJyApICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHRoaXMuY2xlYXJTZWxlY3Rpb24oIHNldERlZmF1bHRNZW51ICk7IC8vQ2xlYXIgc2VsZWN0aW9uIG9uIHNlYXJjaCwgYXMgd2UgYXJlbid0IHJlLXBvcHVsYXRpbmcgaXQgYW55d2F5cywgYW5kIGNhdXNlcyBhIHByb2JsZW0gaWYgeW91IHNlbGVjdCAyIGNlbGxzLCBjbGljayB0b3AtcmlnaHQgcmVmcmVzaCBpY29uLCB0aGVuIGNsaWNrIE5ldyBpY29uLCBpdCB0aGlua3MgdGhlIHNlbGVjdGlvbiBzdGlsbCBleGlzdHMuXG5cdFx0dGhpcy5zZXRBY3Rpb25zQnV0dG9uU3RhdHVzKCk7XG5cdFx0dGhpcy5maW5hbF9zY2hlZHVsZV9kYXRhX2FycmF5ID0gW107XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciBmaWx0ZXJfZGF0YSA9IEdsb2JhbC5jb252ZXJ0TGF5b3V0RmlsdGVyVG9BUElGaWx0ZXIoIHRoaXMuc2VsZWN0X2xheW91dCApO1xuXHRcdHZhciBzdGFydF9kYXRlX3N0cmluZztcblxuXHRcdHZhciBtb2RlID0gdGhpcy5nZXRNb2RlKCk7XG5cblx0XHRpZiAoIHRoaXMuc2V0dGluZ3NfbWVudS5nZXRCdXR0b24oICdhbGxfZW1wbG95ZWVfYnRuJyApLmFjdGl2ZSApIHtcblx0XHRcdGZpbHRlcl9kYXRhLmluY2x1ZGVfYWxsX3VzZXJzID0gdHJ1ZTtcblx0XHR9XG5cblx0XHR2YXIgc3RyaWN0ID0gdGhpcy5zZXR0aW5nc19tZW51LmdldEJ1dHRvbiggJ3N0cmljdF9yYW5nZV9idG4nICkuYWN0aXZlO1xuXG5cdFx0aWYgKCB1c2VfZGF0ZV9waWNrZXJfZGF0ZSB8fCAhdGhpcy5lbmRfZGF0ZSApIHtcblx0XHRcdGlmICggdGhpcy5zdGFydF9kYXRlID09PSBudWxsIHx8IHVzZV9kYXRlX3BpY2tlcl9kYXRlICkge1xuXHRcdFx0XHRzdGFydF9kYXRlX3N0cmluZyA9IHRoaXMuc3RhcnRfZGF0ZV9waWNrZXIuZ2V0VmFsdWUoKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHN0YXJ0X2RhdGVfc3RyaW5nID0gJHRoaXMuc3RhcnRfZGF0ZS5mb3JtYXQoKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBtb2RlID09PSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5ZRUFSICkge1xuXHRcdFx0XHR0aGlzLnllYXJfbW9kZV9vcmlnaW5hbF9kYXRlID0gc3RhcnRfZGF0ZV9zdHJpbmc7XG5cdFx0XHR9XG5cblx0XHR9IGVsc2Uge1xuXG5cdFx0XHRpZiAoIHN0cmljdCApIHtcblx0XHRcdFx0aWYgKCBtb2RlID09PSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5ZRUFSICkge1xuXHRcdFx0XHRcdHN0YXJ0X2RhdGVfc3RyaW5nID0gdGhpcy55ZWFyX21vZGVfb3JpZ2luYWxfZGF0ZSA/IHRoaXMueWVhcl9tb2RlX29yaWdpbmFsX2RhdGUgOiB0aGlzLnN0YXJ0X2RhdGVfcGlja2VyLmdldFZhbHVlKCk7XG5cdFx0XHRcdH0gZWxzZSBpZiAoIG1vZGUgPT09IFNjaGVkdWxlVmlld0NvbnRyb2xsZXJNb2RlLk1PTlRIICkge1xuXHRcdFx0XHRcdHN0YXJ0X2RhdGVfc3RyaW5nID0gbmV3IERhdGUoIG5ldyBEYXRlKCAkdGhpcy5lbmRfZGF0ZS5nZXRUaW1lKCkgKS5zZXREYXRlKCAkdGhpcy5lbmRfZGF0ZS5nZXREYXRlKCkgLSAxNSApICkuZm9ybWF0KCk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0c3RhcnRfZGF0ZV9zdHJpbmcgPSAkdGhpcy5lbmRfZGF0ZS5mb3JtYXQoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRzdGFydF9kYXRlX3N0cmluZyA9ICR0aGlzLnN0YXJ0X2RhdGUuZm9ybWF0KCk7XG5cdFx0XHR9XG5cblx0XHR9XG5cblx0XHRQcm9ncmVzc0Jhci5zaG93T3ZlcmxheSgpO1xuXHRcdExvY2FsQ2FjaGVEYXRhLmxhc3Rfc2NoZWR1bGVfc2VsZWN0ZWRfZGF0ZSA9IHN0YXJ0X2RhdGVfc3RyaW5nO1xuXHRcdHRoaXMuYXBpLmdldENvbWJpbmVkU2NoZWR1bGUoIHsgZmlsdGVyX2RhdGE6IGZpbHRlcl9kYXRhIH0sIHN0YXJ0X2RhdGVfc3RyaW5nLCBtb2RlLCBzdHJpY3QsIHtcblx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHQvL0lzc3VlICMzMDk1IC0gUmFjZSBjb25kaXRpb24gd2hlcmUgYSB1c2VyIHN3aXRjaGVzIHZpZXdzIHdoaWxlIHRoZSBzY2hlZHVsZSBpcyBzdGlsbCBsb2FkaW5nIGNhbiBjYXVzZSBhbiBleGNlcHRpb24uXG5cdFx0XHRcdGlmICggISggTG9jYWxDYWNoZURhdGEuY3VycmVudF9vcGVuX3ByaW1hcnlfY29udHJvbGxlci52aWV3SWQgPT09ICdTY2hlZHVsZScgfHwgTG9jYWxDYWNoZURhdGEuY3VycmVudF9vcGVuX3ByaW1hcnlfY29udHJvbGxlci52aWV3SWQgPT09ICdGaW5kQXZhaWxhYmxlJyApICkge1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXHRcdFx0XHQkdGhpcy5mdWxsX3NjaGVkdWxlX2RhdGEgPSByZXN1bHQuZ2V0UmVzdWx0KCk7XG5cblx0XHRcdFx0Ly9FcnJvcjogVW5hYmxlIHRvIGdldCBwcm9wZXJ0eSAnc3RhcnRfZGlzcGxheV9kYXRlJyBvZiB1bmRlZmluZWQgb3IgbnVsbCByZWZlcmVuY2UgaW4gL2ludGVyZmFjZS9odG1sNS8gbGluZSAzODA1XG5cdFx0XHRcdGlmICggJHRoaXMuZnVsbF9zY2hlZHVsZV9kYXRhID09PSB0cnVlIHx8ICEkdGhpcy5mdWxsX3NjaGVkdWxlX2RhdGEgfHwgISR0aGlzLmZ1bGxfc2NoZWR1bGVfZGF0YS5zY2hlZHVsZV9kYXRlcyApIHtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblx0XHRcdFx0JHRoaXMuc3RhcnRfZGF0ZSA9IEdsb2JhbC5zdHJUb0RhdGUoICR0aGlzLmZ1bGxfc2NoZWR1bGVfZGF0YS5zY2hlZHVsZV9kYXRlcy5zdGFydF9kaXNwbGF5X2RhdGUgKTtcblx0XHRcdFx0JHRoaXMuZW5kX2RhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCAkdGhpcy5mdWxsX3NjaGVkdWxlX2RhdGEuc2NoZWR1bGVfZGF0ZXMuZW5kX2Rpc3BsYXlfZGF0ZSApO1xuXG5cdFx0XHRcdCR0aGlzLmJ1aWxkQ2FsZW5kYXJzKCk7XG5cblx0XHRcdFx0aWYgKCBzZXREZWZhdWx0TWVudSApIHtcblx0XHRcdFx0XHQkdGhpcy5zZXREZWZhdWx0TWVudSggdHJ1ZSApO1xuXHRcdFx0XHRcdCR0aGlzLmF1dG9PcGVuRWRpdFZpZXdJZk5lY2Vzc2FyeSgpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0JHRoaXMuc2VhcmNoRG9uZSgpO1xuXG5cdFx0XHRcdCR0aGlzLnNldFdlZWtNb2RlRHJhZ0FibGUoKTtcblxuXHRcdFx0fVxuXHRcdH0gKTtcblx0fVxuXG5cdHNlYXJjaERvbmUoKSB7XG5cdFx0Ly8gdGhpcy5zZXRHcmlkQ29sdW1uc1dpZHRoKCk7XG5cdFx0Ly8gdGhpcy5zZXRHcmlkU2l6ZSgpO1xuXHRcdCQoICcuYnV0dG9uLXJvdGF0ZScgKS5yZW1vdmVDbGFzcyggJ2J1dHRvbi1yb3RhdGUnICk7XG5cdFx0VFRQcm9taXNlLnJlc29sdmUoICdpbml0JywgJ2luaXQnICk7XG5cdH1cblxuXHRnZXRMYXN0RGF0ZU9mUm93KCByb3cgKSB7XG5cdFx0dmFyIHN0YXJ0X2RheSA9IExvY2FsQ2FjaGVEYXRhLmdldExvZ2luVXNlclByZWZlcmVuY2UoKS5zdGFydF93ZWVrX2RheSA9PSAwID8gNyA6IExvY2FsQ2FjaGVEYXRhLmdldExvZ2luVXNlclByZWZlcmVuY2UoKS5zdGFydF93ZWVrX2RheTtcblx0XHRyZXR1cm4gcm93Wyggc3RhcnRfZGF5IC0gMSApICsgJ190aW1lJ107XG5cdH1cblxuXHRzZXRBY3Rpb25zQnV0dG9uU3RhdHVzKCkge1xuXHRcdHZhciBtb2RlID0gdGhpcy5nZXRNb2RlKCk7XG5cblx0XHR0aGlzLnNldHRpbmdzX21lbnUuZW5hYmxlQnV0dG9uKCAnd2Vla2x5X3RvdGFsc19idG4nICk7XG5cdFx0dGhpcy5zZXR0aW5nc19tZW51LmVuYWJsZUJ1dHRvbiggJ3N0cmljdF9yYW5nZV9idG4nICk7XG5cdFx0dGhpcy5zZXR0aW5nc19tZW51LmVuYWJsZUJ1dHRvbiggJ2RhaWx5X3RvdGFsc19idG4nICk7XG5cdFx0dGhpcy5zZXR0aW5nc19tZW51LmVuYWJsZUJ1dHRvbiggJ2FsbF9lbXBsb3llZV9idG4nICk7XG5cblx0XHRzd2l0Y2ggKCBtb2RlICkge1xuXHRcdFx0Y2FzZSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5EQVk6XG5cdFx0XHRcdHRoaXMuc2V0dGluZ3NfbWVudS5kaXNhYmxlQnV0dG9uKCAnd2Vla2x5X3RvdGFsc19idG4nICk7XG5cdFx0XHRcdHRoaXMuc2V0dGluZ3NfbWVudS5kaXNhYmxlQnV0dG9uKCAnc3RyaWN0X3JhbmdlX2J0bicgKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIFNjaGVkdWxlVmlld0NvbnRyb2xsZXJNb2RlLldFRUs6XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5NT05USDpcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIFNjaGVkdWxlVmlld0NvbnRyb2xsZXJNb2RlLllFQVI6XG5cdFx0XHRcdHRoaXMuc2V0dGluZ3NfbWVudS5kaXNhYmxlQnV0dG9uKCAnd2Vla2x5X3RvdGFsc19idG4nICk7XG5cdFx0XHRcdHRoaXMuc2V0dGluZ3NfbWVudS5kaXNhYmxlQnV0dG9uKCAnZGFpbHlfdG90YWxzX2J0bicgKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0fVxuXHR9XG5cblx0b25PdmVycmlkZUNsaWNrKCkge1xuXHRcdHZhciBjb250ZXh0X21lbnVfYXJyYXkgPSBDb250ZXh0TWVudU1hbmFnZXIuZ2V0TWVudU1vZGVsQnlNZW51SWQoIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCApO1xuXHRcdHZhciBvdmVycmlkZV9pY29uID0gY29udGV4dF9tZW51X2FycmF5LmZpbmQoIGljb24gPT4gaWNvbi5pZCA9PT0gJ292ZXJyaWRlJyApO1xuXG5cdFx0aWYgKCBvdmVycmlkZV9pY29uLmFjdGl2ZSApIHtcblx0XHRcdHRoaXMuaXNfb3ZlcnJpZGUgPSB0cnVlO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLmlzX292ZXJyaWRlID0gZmFsc2U7XG5cdFx0fVxuXHR9XG5cblx0b25Ob3RpZnlVc2VyU2NoZWR1bGVDaGFuZ2VDbGljaygpIHtcblx0XHR2YXIgY29udGV4dF9tZW51X2FycmF5ID0gQ29udGV4dE1lbnVNYW5hZ2VyLmdldE1lbnVNb2RlbEJ5TWVudUlkKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQgKTtcblx0XHR2YXIgbm90aWZ5X3VzZXJfc2NoZWR1bGVfY2hhbmdlX2ljb24gPSBjb250ZXh0X21lbnVfYXJyYXkuZmluZCggaWNvbiA9PiBpY29uLmlkID09PSAnbm90aWZ5X3VzZXJfc2NoZWR1bGVfY2hhbmdlJyApO1xuXG5cdFx0aWYgKCBub3RpZnlfdXNlcl9zY2hlZHVsZV9jaGFuZ2VfaWNvbi5hY3RpdmUgKSB7XG5cdFx0XHR0aGlzLm5vdGlmeV91c2VyX3NjaGVkdWxlX2NoYW5nZSA9IHRydWU7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMubm90aWZ5X3VzZXJfc2NoZWR1bGVfY2hhbmdlID0gZmFsc2U7XG5cdFx0fVxuXHR9XG5cblx0c2V0TW92ZU9yRHJvcE1vZGUoIGlkICkge1xuXHRcdC8vRHJhZyBhbmQgZHJvcCBjb250ZXh0IG1lbnUgZG9lcyBub3QgZXhpc3Qgb24gZWRpdCB2aWV3IGFuZCB0aHVzIHRoaXMgY29kZSBkb2VzIG5vdCBuZWVkIHRvIGJlIHJhbi4gT3RoZXJ3aXNlIHdvdWxkIGNhdXNlIEphdmFTY3JpcHQgZXhjZXB0aW9uLlxuXHRcdGlmICggdGhpcy5pc19lZGl0IHx8IHRoaXMuaXNfbWFzc19lZGl0aW5nIHx8IHRoaXMuaXNfYWRkICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBjb250ZXh0X21lbnVfYXJyYXkgPSBDb250ZXh0TWVudU1hbmFnZXIuZ2V0TWVudU1vZGVsQnlNZW51SWQoIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCApO1xuXHRcdHZhciBkcmFnX2NvcHlfaWNvbiA9IGNvbnRleHRfbWVudV9hcnJheS5maW5kKCBpY29uID0+IGljb24uaWQgPT09ICdkcmFnX2NvcHknICk7XG5cdFx0dmFyIG1vdmVfaWNvbiA9IGNvbnRleHRfbWVudV9hcnJheS5maW5kKCBpY29uID0+IGljb24uaWQgPT09ICdtb3ZlJyApO1xuXHRcdHZhciBzd2FwX2ljb24gPSBjb250ZXh0X21lbnVfYXJyYXkuZmluZCggaWNvbiA9PiBpY29uLmlkID09PSAnc3dhcCcgKTtcblxuXHRcdGlmICggZHJhZ19jb3B5X2ljb24gPT09IHVuZGVmaW5lZCB8fCBtb3ZlX2ljb24gPT09IHVuZGVmaW5lZCB8fCBzd2FwX2ljb24gPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRDb250ZXh0TWVudU1hbmFnZXIuYWN0aXZhdGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBkcmFnX2NvcHlfaWNvbi5pZCwgdHJ1ZSApO1xuXHRcdENvbnRleHRNZW51TWFuYWdlci5hY3RpdmF0ZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIG1vdmVfaWNvbi5pZCwgdHJ1ZSApO1xuXHRcdENvbnRleHRNZW51TWFuYWdlci5hY3RpdmF0ZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIHN3YXBfaWNvbi5pZCwgdHJ1ZSApO1xuXG5cdFx0dmFyIGRyYWdfaW52aXNpYmxlID0gZmFsc2U7XG5cdFx0dmFyIG1vdmVfaW52aXNpYmxlID0gZmFsc2U7XG5cdFx0dmFyIHN3YXBfaW52aXNpYmxlID0gZmFsc2U7XG5cblx0XHRpZiAoICF0aGlzLmNvcHlQZXJtaXNzaW9uVmFsaWRhdGUoKSApIHtcblx0XHRcdGRyYWdfaW52aXNpYmxlID0gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoICF0aGlzLm1vdmVQZXJtaXNzaW9uVmFsaWRhdGUoKSApIHtcblx0XHRcdG1vdmVfaW52aXNpYmxlID0gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoICF0aGlzLmVkaXRQZXJtaXNzaW9uVmFsaWRhdGUoKSApIHtcblx0XHRcdHN3YXBfaW52aXNpYmxlID0gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoIG1vdmVfaW52aXNpYmxlICYmIGlkID09PSAnbW92ZScgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuYWN0aXZhdGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBkcmFnX2NvcHlfaWNvbi5pZCwgZmFsc2UgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dmFyIGljb24gPSBjb250ZXh0X21lbnVfYXJyYXkuZmluZCggaWNvbiA9PiBpY29uLmlkID09PSBpZCApO1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmFjdGl2YXRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgaWNvbi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cblx0XHRpZiAoIGRyYWdfaW52aXNpYmxlICYmIG1vdmVfaW52aXNpYmxlICkge1xuXHRcdFx0dGhpcy5zZWxlY3RfZHJhZ19tZW51X2lkID0gbnVsbDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5zZWxlY3RfZHJhZ19tZW51X2lkID0gaWQ7XG5cdFx0fVxuXHR9XG5cblx0c2V0SG9saWRheURhdGFEaWMoKSB7XG5cblx0XHRpZiAoIHRoaXMuZnVsbF9zY2hlZHVsZV9kYXRhLmhvbGlkYXlfZGF0YSApIHtcblx0XHRcdGZvciAoIHZhciBpID0gMDsgaSA8IHRoaXMuZnVsbF9zY2hlZHVsZV9kYXRhLmhvbGlkYXlfZGF0YS5sZW5ndGg7IGkrKyApIHtcblx0XHRcdFx0dmFyIGl0ZW0gPSB0aGlzLmZ1bGxfc2NoZWR1bGVfZGF0YS5ob2xpZGF5X2RhdGFbaV07XG5cdFx0XHRcdHZhciBzdGFuZGFyZF9kYXRlID0gR2xvYmFsLnN0clRvRGF0ZSggaXRlbS5kYXRlX3N0YW1wICkuZm9ybWF0KCB0aGlzLndlZWtseV9mb3JtYXQgKTtcblx0XHRcdFx0dGhpcy5ob2xpZGF5X2RhdGFfZGljW3N0YW5kYXJkX2RhdGVdID0gaXRlbTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRidWlsZENhbGVuZGFycyggZG9fbm90X2hpZGUgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR0aGlzLmdyaWRfZGl2ID0gJCggdGhpcy5lbCApLmZpbmQoICcuc2NoZWR1bGUtZ3JpZC1kaXYnICk7XG5cdFx0dGhpcy5zZXRIb2xpZGF5RGF0YURpYygpO1xuXG5cdFx0dGhpcy5idWlsZFNjaGVkdWxlQ29sdW1ucygpO1xuXHRcdHRoaXMuYnVpbGRTY2hlZHVsZVNvdXJjZSgpO1xuXHRcdHRoaXMuYnVpbGRTY2hlZHVsZUdyaWQoKTtcblxuXHRcdHRoaXMuc2V0R3JpZENvbHVtbnNXaWR0aCgpOyAvL1RoZXJlIGlzIG5vIGdyaWQgZGF0YSBwb3B1bGF0ZWQgd2hlbiB0aGlzIHJ1bnMsIHNvIGl0IG9ubHkgc2l6ZXMgY29sdW1ucyB0byB0aGUgbGFiZWwgbGVuZ3RoLCBub3QgbG9uZ2VzdCByb3cgZGF0YSBsZW5ndGguXG5cdFx0dGhpcy5zZXRHcmlkU2l6ZSgpO1xuXG5cdFx0Ly9Pbmx5IHdvcmsgd2hlbiB5ZWFyIG1vZGVcblx0XHR0aGlzLnNldFllYXJHcm91cEhlYWRlcigpO1xuXHRcdHRoaXMuc2hvd0dyaWRCb3JkZXJzKCk7XG5cblx0XHR2YXIgc3RhcnQgPSAwO1xuXHRcdHZhciBwYWdlID0gMTtcblx0XHR2YXIgcGFnZV9udW0gPSAxMDtcblxuXHRcdC8vdGhpcy5ncmlkIHdpbGwgYmUgZW1wdHkgd2hlbiBmaXJzdCB0aW1lIGludCB0aGlzIGZ1bmN0aW9uLCBzbyBwdXQgdGhpcyBqdWRnZSBoZXJlIGluc3RlYWQgYXQgYmVnaW4uXG5cdFx0Ly9FcnJvcjogVW5jYXVnaHQgVHlwZUVycm9yOiBDYW5ub3QgY2FsbCBtZXRob2QgJ2NsZWFyR3JpZERhdGEnIG9mIG51bGwgaW4gL2ludGVyZmFjZS9odG1sNS9pbmRleC5waHA/ZGVza3RvcD0xIyFtPVNjaGVkdWxlJmRhdGU9MjAxNTAxMTgmbW9kZT13ZWVrIGxpbmUgNjk0NFxuXHRcdGlmICggIXRoaXMuZ3JpZCApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR0aGlzLmdyaWQuY2xlYXJHcmlkRGF0YSgpO1xuXG5cdFx0dmFyIGogPSAwO1xuXG5cdFx0aWYgKCAhZG9fbm90X2hpZGUgKSB7XG5cdFx0XHR0aGlzLmdyaWQuZ3JpZC5jc3MoICdvcGFjaXR5JywgMCApO1xuXHRcdH1cblxuXHRcdC8vRXJyb3I6IFR5cGVFcnJvcjogJHRoaXMuc2NoZWR1bGVfc291cmNlIGlzIHVuZGVmaW5lZCBpbiBpbnRlcmZhY2UvaHRtbDUvZnJhbWV3b3JrL2pxdWVyeS5taW4uanM/dj05LjAuNi0yMDE1MTIzMS0xNTUwNDIgbGluZSAyID4gZXZhbCBsaW5lIDM5MDRcblx0XHRpZiAoICF0aGlzLnNjaGVkdWxlX3NvdXJjZSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHRhZGRHcmlkRGF0YSgpO1xuXG5cdFx0Ly8gQWRkIDIwMCByZWNvcmQgYSB0aW1lIHNvIFVJIG5vdCBibG9jay5cblx0XHR2YXIgaW50ZXJ2YWwgPSBzZXRJbnRlcnZhbCggZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoIGogPCAkdGhpcy5zY2hlZHVsZV9zb3VyY2UubGVuZ3RoICkge1xuXHRcdFx0XHRhZGRHcmlkRGF0YSgpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZG9OZXh0KCk7XG5cdFx0XHR9XG5cdFx0fSwgMTAgKTtcblxuXHRcdGZ1bmN0aW9uIGFkZEdyaWREYXRhKCkge1xuXHRcdFx0Zm9yICggdmFyIGkgPSBqOyBpIDwgaiArIDIwMDsgaSsrICkge1xuXHRcdFx0XHRpZiAoIGkgPCAkdGhpcy5zY2hlZHVsZV9zb3VyY2UubGVuZ3RoICkge1xuXHRcdFx0XHRcdHZhciBpdGVtID0gJHRoaXMuc2NoZWR1bGVfc291cmNlW2ldO1xuXHRcdFx0XHRcdCR0aGlzLmdyaWQuZ3JpZC5hZGRSb3dEYXRhKCBpICsgMSwgaXRlbSApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGogPSBpO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGRvTmV4dCgpIHtcblx0XHRcdGlmICggIWRvX25vdF9oaWRlICkge1xuXHRcdFx0XHQkdGhpcy5ncmlkLmdyaWQuY3NzKCAnb3BhY2l0eScsIDEgKTtcblx0XHRcdH1cblx0XHRcdGNsZWFySW50ZXJ2YWwoIGludGVydmFsICk7XG5cblx0XHRcdGlmICggJHRoaXMuZ2V0TW9kZSAhPT0gU2NoZWR1bGVWaWV3Q29udHJvbGxlck1vZGUuWUVBUiApIHtcblx0XHRcdFx0JHRoaXMuc2V0U2NoZWR1bGVHcmlkUm93U3BhbigpO1xuXHRcdFx0fVxuXG5cdFx0XHQkdGhpcy5oaWdoTGlnaHRTZWxlY3REYXkoKTtcblxuXHRcdFx0Ly9Pbmx5IHdvcmsgd2hlbiBtb250aCBtb2RlXG5cdFx0XHQkdGhpcy5zZXRNb250aERhdGVSb3dQb3NpdGlvbigpO1xuXG5cdFx0XHQkdGhpcy5zZXRTY2hlZHVsZUdyaWREcmFnQWJsZSgpO1xuXG5cdFx0XHQkdGhpcy5zZXRTY3JvbGxQb3NpdGlvbigpO1xuXG5cdFx0XHQvLyR0aGlzLmF1dG9PcGVuRWRpdFZpZXdJZk5lY2Vzc2FyeSgpO1xuXG5cdFx0XHQkdGhpcy5zZXRNb250aERhdGVSb3dCYWNrR3JvdW5kKCk7XG5cblx0XHRcdCR0aGlzLnNldFdlZWtseVRvdGFsSGVhZGVyKCk7XG5cdFx0fVxuXHR9XG5cblx0Z2V0RGVmYXVsdFVzZXIoKSB7XG5cdFx0dmFyIGRlZmF1bHRfdXNlcl9pZCA9IGZhbHNlO1xuXHRcdGlmICggdGhpcy5zY2hlZHVsZV9zb3VyY2UgJiYgdGhpcy5zY2hlZHVsZV9zb3VyY2UubGVuZ3RoID09PSAxICYmIHRoaXMuc2NoZWR1bGVfc291cmNlWzBdLnVzZXJfaWQgIT0gJycgKSB7XG5cdFx0XHQvL2Nhc2Ugd2hlcmUgb25seSBvbmUgdXNlciBoYXMgYSBzY2hlZHVsZSBvbiB0aGUgc2hlZXRcblx0XHRcdGRlZmF1bHRfdXNlcl9pZCA9IHRoaXMuc2NoZWR1bGVfc291cmNlWzBdLnVzZXJfaWQ7XG5cdFx0fSBlbHNlIGlmICggdGhpcy5zY2hlZHVsZV9zb3VyY2Vcblx0XHRcdCYmIHRoaXMuc2NoZWR1bGVfc291cmNlLmxlbmd0aCA9PT0gMVxuXHRcdFx0JiYgdHlwZW9mIHRoaXMuZmlsdGVyX2RhdGEgPT0gJ29iamVjdCcgLy8gIzI1NzEgLSBVbmNhdWdodCBUeXBlRXJyb3I6IFRoaXMuZmlsdGVyX2RhdGEuaW5jbHVkZV91c2VyX2lkIGlzIHVuZGVmaW5lZFxuXHRcdFx0JiYgdHlwZW9mIHRoaXMuZmlsdGVyX2RhdGEuaW5jbHVkZV91c2VyX2lkcyA9PSAnb2JqZWN0JyAvLyAjMjU3MSAtIFVuY2F1Z2h0IFR5cGVFcnJvcjogQ2Fubm90IHJlYWQgcHJvcGVydHkgJ3ZhbHVlJyBvZiB1bmRlZmluZWRcblx0XHRcdCYmIHRoaXMuZmlsdGVyX2RhdGEuaW5jbHVkZV91c2VyX2lkcy52YWx1ZVxuXHRcdFx0JiYgdGhpcy5maWx0ZXJfZGF0YS5pbmNsdWRlX3VzZXJfaWRzLnZhbHVlLmxlbmd0aCA9PT0gMSApIHtcblx0XHRcdC8vY2FzZSB3aGVyZSBvbmUgdXNlciBpcyBzZWxlY3RlZCBpbiBpbmNsdWRlX3VzZXJzIGJ1dCBkb2VzIG5vdCBoYXZlIGEgc2NoZWR1bGUgYXR0cmlidXRlZCB0byB0aGVtIChuZXcgdXNlcnMgZm9yIGV4YW1wbGUpXG5cdFx0XHRkZWZhdWx0X3VzZXJfaWQgPSB0aGlzLmZpbHRlcl9kYXRhLmluY2x1ZGVfdXNlcl9pZHMudmFsdWVbMF07XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vICMyNzQwIEJlZm9yZSBkZWZhdWx0aW5nIHRvIGxvZ2dlZCBpbiB1c2VyLCBjaGVjayB0byBzZWUgaWYgdXNlcl9pZCBpcyBzZXQgb24gdGhlIGN1cnJlbnRfZWRpdF9yZWNvcmQsIGFzIFNhdmUmQ29weSBjbGVhcnMgZ3JpZCBzZWxlY3Rpb24sIHNvIHdlIG5lZWQgdG8gcmUtc2V0IGl0LlxuXHRcdFx0aWYgKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudXNlcl9pZCAmJiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudXNlcl9pZCAhPSAnJyApIHtcblx0XHRcdFx0ZGVmYXVsdF91c2VyX2lkID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnVzZXJfaWQ7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRkZWZhdWx0X3VzZXJfaWQgPSBMb2NhbENhY2hlRGF0YS5nZXRMb2dpblVzZXIoKS5pZDtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gZGVmYXVsdF91c2VyX2lkO1xuXHR9XG5cblx0c2V0V2Vla2x5VG90YWxIZWFkZXIoKSB7XG5cdFx0dmFyIHNob3dfd2Vla2x5X3RvdGFsID0gdGhpcy5zZXR0aW5nc19tZW51LmdldEJ1dHRvbiggJ3dlZWtseV90b3RhbHNfYnRuJyApLmFjdGl2ZTtcblx0XHQkKCAnLnNpemUtdHInICkucmVtb3ZlKCk7XG5cdFx0JCggJy5ncm91cC10cicgKS5yZW1vdmUoKTtcblx0XHRpZiAoICFzaG93X3dlZWtseV90b3RhbCB8fCB0aGlzLnNldHRpbmdzX21lbnUuZ2V0QnV0dG9uKCAnd2Vla2x5X3RvdGFsc19idG4nICkuZGlzYWJsZWQgPT09IHRydWUgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIHRhYmxlID0gJCggJCggdGhpcy5lbCApLmZpbmQoICd0YWJsZVthcmlhLWxhYmVsbGVkYnk9Z2JveF8nICsgdGhpcy51aV9pZCArICdfZ3JpZF0nICkgKTtcblxuXHRcdHZhciBzaXplX3RyID0gJCggJzx0ciBjbGFzcz1cInNpemUtdHJcIiA+JyArXG5cdFx0XHQnPC90cj4nICk7XG5cblx0XHR2YXIgbmV3X3RyID0gJCggJzx0ciBjbGFzcz1cImdyb3VwLWNvbHVtbi10ciBncm91cC10clwiID4nICtcblx0XHRcdCc8L3RyPicgKTtcblxuXHRcdHZhciBuZXdfdGggPSAkKCAnPHRoIGNsYXNzPVwiZ3JvdXAtY29sdW1uLXRoXCIgID4nICtcblx0XHRcdCc8c3BhbiBjbGFzcz1cImdyb3VwLWNvbHVtbi1sYWJlbFwiPjwvc3Bhbj4nICtcblx0XHRcdCc8L3RoPicgKTtcblxuXHRcdHZhciBjdXJyZW50X3RycyA9IHRhYmxlLmZpbmQoICcuanFnZmlyc3Ryb3cnICk7XG5cdFx0Y3JlYXRlU2l6ZUNvbHVtbnMoKTtcblxuXHRcdHZhciBjb2x1bW5fbGVuZ3RoID0gdGhpcy5ncmlkLmdyaWQuZ2V0R3JpZFBhcmFtKCAnY29sTW9kZWwnICkubGVuZ3RoO1xuXHRcdGNyZWF0ZUNvbHVtbiggY29sdW1uX2xlbmd0aCAtIDUsICcnICk7XG5cdFx0Y3JlYXRlQ29sdW1uKCA1LCAkLmkxOG4uXyggJ1RvdGFsJyApICk7XG5cblx0XHRzaXplX3RyLmluc2VydEJlZm9yZSggdGFibGUuZmluZCggJy51aS1qcWdyaWQtbGFiZWxzJyApICk7XG5cdFx0bmV3X3RyLmluc2VydEJlZm9yZSggdGFibGUuZmluZCggJy51aS1qcWdyaWQtbGFiZWxzJyApICk7XG5cblx0XHRmdW5jdGlvbiBjcmVhdGVTaXplQ29sdW1ucygpIHtcblx0XHRcdHZhciBsZW4gPSBjdXJyZW50X3Rycy5jaGlsZHJlbigpLmxlbmd0aDtcblxuXHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRcdHZhciB0ZCA9ICQoICc8dGggY2xhc3M9XCJcIiBzdHlsZT1cImJvcmRlci1yaWdodDogMXB4IHNvbGlkICNkZGRkZGRcIiA+JyArICc8L3RoPicgKTtcblx0XHRcdFx0dmFyIGl0ZW0gPSBjdXJyZW50X3Rycy5jaGlsZHJlbigpLmVxKCBpICk7XG5cblx0XHRcdFx0LyoqXG5cdFx0XHRcdCAqICMyMzUzIC0gc2NoZWR1bGUgc2l6aW5nIGZpeFxuXHRcdFx0XHQgKlxuXHRcdFx0XHQgKiBEdWUgdG8gZmlyZWZveCByZXBvcnRpbmcgdGggIGluY29ycmVjdGx5IHZpYSB0aGUgJC53aWR0aCgpIGZ1bmN0aW9uLCB0aGUgc2l6ZXMgbXVzdCBjb21lIGZyb20gdGhlICh0ci5qcWdmaXJzdHJvdykgb2YgdGhlIGRhdGEgdGFibGVcblx0XHRcdFx0ICogZmlyZWZveCBhbHNvIHJlZnVzZXMgdG8gc2V0IHRoZSB3aWR0aCBvZiB0aGUgZmlyc3Qgcm93IG9mIHRoJ3MgdmlhIHRoZSAkLndpZHRoKCkgZnVuY3Rpb24sIHNvIHdlIG5lZWQgdG8gc2hpcCB0aGUgY3NzIHZhbHVlcyBkaXJlY3RseSBpbnRvIHRoZSBpbmxpbmUgY3NzIHVzaW5nIHRoZSBjc3MgZnVuY3Rpb25cblx0XHRcdFx0ICovXG5cdFx0XHRcdHRkLmNzcyggJ3dpZHRoJywgaXRlbS5jc3MoICd3aWR0aCcgKSApO1xuXG5cdFx0XHRcdHRkLmhlaWdodCggMCApO1xuXHRcdFx0XHRzaXplX3RyLmFwcGVuZCggdGQgKTtcblx0XHRcdH1cblxuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGNyZWF0ZUNvbHVtbiggZW5kX2luZGV4LCB0ZXh0ICkge1xuXHRcdFx0dmFyIHBheV9wZXJpb2RfdGggPSBuZXdfdGguY2xvbmUoKTtcblxuXHRcdFx0cGF5X3BlcmlvZF90aC5jaGlsZHJlbiggMCApLnRleHQoIHRleHQgKTtcblx0XHRcdHBheV9wZXJpb2RfdGguYXR0ciggJ2NvbHNwYW4nLCBlbmRfaW5kZXggKTtcblxuXHRcdFx0bmV3X3RyLmFwcGVuZCggcGF5X3BlcmlvZF90aCApO1xuXHRcdH1cblxuXHRcdHRoaXMuc2V0R3JpZEhlaWdodCgpOyAvL1NpbmNlIHdlIGFyZSBjaGFuZ2luZyB0aGUgaGVhZGVyIGhlaWdodCwgcmVzaXplIHRoZSBncmlkIHRvIGZpdC5cblx0fVxuXG5cdHNldE1vbnRoRGF0ZVJvd0JhY2tHcm91bmQoKSB7XG5cdFx0aWYgKCB0aGlzLmdldE1vZGUoKSA9PT0gU2NoZWR1bGVWaWV3Q29udHJvbGxlck1vZGUuTU9OVEggKSB7XG5cdFx0XHQkKCB0aGlzLmVsICkuZmluZCggJy5tb250aC1kYXRlLWNlbGwnICkucGFyZW50KCkuY3NzKCAnYmFja2dyb3VuZC1jb2xvcicsICcjMzc1OTc5JyApO1xuXHRcdH1cblx0fVxuXG5cdHNldFNjcm9sbFBvc2l0aW9uKCkge1xuXHRcdGlmICggdGhpcy5zY3JvbGxfcG9zaXRpb24gPiAwICkge1xuXHRcdFx0dGhpcy5ncmlkLmdyaWQucGFyZW50KCkucGFyZW50KCkuc2Nyb2xsVG9wKCB0aGlzLnNjcm9sbF9wb3NpdGlvbiApO1xuXHRcdH1cblx0fVxuXG5cdHNldFllYXJHcm91cEhlYWRlcigpIHtcblxuXHRcdGlmICggdGhpcy5nZXRNb2RlKCkgIT09IFNjaGVkdWxlVmlld0NvbnRyb2xsZXJNb2RlLllFQVIgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0JCggJy5zY2hlZHVsZS15ZWFyLWdyb3VwLWhlYWRlcicgKS5yZW1vdmUoKTtcblx0XHR2YXIgdGFibGUgPSAkKCAkKCB0aGlzLmVsICkuZmluZCggJ3RhYmxlW2FyaWEtbGFiZWxsZWRieT1nYm94XycgKyB0aGlzLnVpX2lkICsgJ19ncmlkXScgKVswXSApO1xuXHRcdHZhciBuZXdfdHIgPSAkKCAnPHRyIGNsYXNzPVwiZ3JvdXAtY29sdW1uLXRyIHNjaGVkdWxlLXllYXItZ3JvdXAtaGVhZGVyXCIgPicgK1xuXHRcdFx0JzwvdHI+JyApO1xuXG5cdFx0dmFyIG5ld190aCA9ICQoICc8dGggY2xhc3M9XCJncm91cC1jb2x1bW4tdGhcIiAgPicgK1xuXHRcdFx0JzxzcGFuIGNsYXNzPVwiZ3JvdXAtY29sdW1uLWxhYmVsXCI+PC9zcGFuPicgK1xuXHRcdFx0JzwvdGg+JyApO1xuXG5cdFx0dmFyIGRlZmF1bHRfdHIgPSBuZXdfdHIuY2xvbmUoKTtcblxuXHRcdCQoIHRhYmxlLmNoaWxkcmVuKClbMF0gKS5wcmVwZW5kKCBkZWZhdWx0X3RyICk7XG5cblx0XHQvL0J1aWxkIGZpcnN0IHJvdyB0byBjb3JyZWN0IHdpZHRoIGZvciBzcGFuIGNvbHVtbnMgd2hpY2ggaW4gc2Vjb25kIHJvdywgdGFibGUgd2lkdGggZGVjaWRlZCBieSBmaXJzdCByb3dcblx0XHR2YXIgZGF0ZXNUSHMgPSB0YWJsZS5maW5kKCAndGgnICk7XG5cdFx0dmFyIGxlbiA9IGRhdGVzVEhzLmxlbmd0aDtcblx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdHZhciB0aCA9ICQoIGRhdGVzVEhzW2ldICk7XG5cblx0XHRcdHZhciBkZWZhdWx0X3RoID0gdGguY2xvbmUoKTtcblx0XHRcdGRlZmF1bHRfdGguYXR0ciggJ2lkJywgJycgKTtcblx0XHRcdGRlZmF1bHRfdGguZW1wdHkoKTtcblx0XHRcdGRlZmF1bHRfdGguYXR0ciggJ3JvdycsICcnICk7XG5cdFx0XHRkZWZhdWx0X3RoLmhlaWdodCggMCApO1xuXHRcdFx0ZGVmYXVsdF90ci5hcHBlbmQoIGRlZmF1bHRfdGggKTtcblxuXHRcdH1cblxuXHRcdHZhciBmaXJzdF90ciA9ICQoICQoIHRhYmxlLmNoaWxkcmVuKClbMF0gKS5jaGlsZHJlbigpWzBdICk7XG5cblx0XHR2YXIgc3RhcnQgPSB0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5kaXNwbGF5X2NvbHVtbnMubGVuZ3RoICsgMTtcblx0XHQvL0NyZWF0ZSBncm91cCBjb2x1bW4gaGVhZGVyXG5cdFx0ZGVmYXVsdF90ciA9IG5ld190ci5jbG9uZSgpO1xuXHRcdGRlZmF1bHRfdGggPSBuZXdfdGguY2xvbmUoKTtcblx0XHRkZWZhdWx0X3RoLmF0dHIoICdjb2xzcGFuJywgc3RhcnQgKTtcblx0XHRkZWZhdWx0X3RyLmFwcGVuZCggZGVmYXVsdF90aCApO1xuXHRcdGRlZmF1bHRfdHIuaW5zZXJ0QWZ0ZXIoIGZpcnN0X3RyICk7XG5cblx0XHR2YXIgY3VycmVudF9tb250aCA9IG51bGw7XG5cdFx0dmFyIGN1cnJlbnRfZGF0ZSA9IG51bGw7XG5cdFx0dmFyIHNhbWVfbW9udGhfY291bnQgPSAwO1xuXG5cdFx0Zm9yICggdmFyIGkgPSBzdGFydDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0dGggPSAkKCBkYXRlc1RIc1tpXSApO1xuXHRcdFx0dmFyIGlkX3NwbGl0X2FycmF5ID0gdGguYXR0ciggJ2lkJyApLnNwbGl0KCAnXycgKTtcblx0XHRcdHZhciBkYXRlX3N0ciA9IGlkX3NwbGl0X2FycmF5W2lkX3NwbGl0X2FycmF5Lmxlbmd0aCAtIDFdO1xuXG5cdFx0XHRpZiAoIGRhdGVfc3RyID09PSAnc2hpZnRzJyB8fCBkYXRlX3N0ciA9PT0gJ2Fic2VuY2VzJyB8fCBkYXRlX3N0ciA9PT0gJ3RvdGFsX3RpbWUnIHx8IGRhdGVfc3RyID09PSAndG90YWxfdGltZV93YWdlJyApIHtcblx0XHRcdFx0dmFyIG1vbnRoID0gJy0xJztcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdG1vbnRoID0gR2xvYmFsLnN0clRvRGF0ZSggZGF0ZV9zdHIsIHRoaXMuZnVsbF9mb3JtYXQgKS5nZXRNb250aCgpO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoICFHbG9iYWwuaXNTZXQoIGN1cnJlbnRfbW9udGggKSApIHtcblx0XHRcdFx0Y3VycmVudF9tb250aCA9IG1vbnRoO1xuXHRcdFx0XHRjdXJyZW50X2RhdGUgPSBkYXRlX3N0cjtcblx0XHRcdFx0c2FtZV9tb250aF9jb3VudCA9IDE7XG5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHZhciBtb250aF9oZWFkZXJfdGV4dCA9IEdsb2JhbC5zdHJUb0RhdGUoIGN1cnJlbnRfZGF0ZSwgdGhpcy5mdWxsX2Zvcm1hdCApLmZvcm1hdCggJ01NTScgKTtcblx0XHRcdFx0aWYgKCBtb250aCA9PT0gY3VycmVudF9tb250aCAmJiBpICE9PSBsZW4gLSAxICkge1xuXHRcdFx0XHRcdHNhbWVfbW9udGhfY291bnQgPSBzYW1lX21vbnRoX2NvdW50ICsgMTtcblxuXHRcdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdFx0aWYgKCBpID09PSBsZW4gLSAxICkge1xuXHRcdFx0XHRcdFx0aWYgKCBtb250aCAhPT0gY3VycmVudF9tb250aCAmJiAhaXNOYU4oIG1vbnRoICkgKSB7XG5cdFx0XHRcdFx0XHRcdGRlZmF1bHRfdGguY2hpbGRyZW4oIDAgKS50ZXh0KCBtb250aF9oZWFkZXJfdGV4dCApO1xuXHRcdFx0XHRcdFx0XHRkZWZhdWx0X3RoLmF0dHIoICdjb2xzcGFuJywgc2FtZV9tb250aF9jb3VudCApO1xuXHRcdFx0XHRcdFx0XHRkZWZhdWx0X3RyLmFwcGVuZCggZGVmYXVsdF90aCApO1xuXG5cdFx0XHRcdFx0XHRcdGN1cnJlbnRfbW9udGggPSBtb250aDtcblx0XHRcdFx0XHRcdFx0Y3VycmVudF9kYXRlID0gZGF0ZV9zdHI7XG5cdFx0XHRcdFx0XHRcdHNhbWVfbW9udGhfY291bnQgPSAxO1xuXG5cdFx0XHRcdFx0XHRcdGRlZmF1bHRfdGggPSBuZXdfdGguY2xvbmUoKTtcblx0XHRcdFx0XHRcdFx0ZGVmYXVsdF90aC5jaGlsZHJlbiggMCApLnRleHQoIG1vbnRoX2hlYWRlcl90ZXh0ICk7XG5cdFx0XHRcdFx0XHRcdGRlZmF1bHRfdGguYXR0ciggJ2NvbHNwYW4nLCBzYW1lX21vbnRoX2NvdW50ICk7XG5cdFx0XHRcdFx0XHRcdGRlZmF1bHRfdHIuYXBwZW5kKCBkZWZhdWx0X3RoICk7XG5cblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHNhbWVfbW9udGhfY291bnQgPSBzYW1lX21vbnRoX2NvdW50ICsgMTtcblxuXHRcdFx0XHRcdFx0XHRkZWZhdWx0X3RoID0gbmV3X3RoLmNsb25lKCk7XG5cdFx0XHRcdFx0XHRcdGRlZmF1bHRfdGguY2hpbGRyZW4oIDAgKS50ZXh0KCBtb250aF9oZWFkZXJfdGV4dCApO1xuXHRcdFx0XHRcdFx0XHRkZWZhdWx0X3RoLmF0dHIoICdjb2xzcGFuJywgc2FtZV9tb250aF9jb3VudCApO1xuXHRcdFx0XHRcdFx0XHRkZWZhdWx0X3RyLmFwcGVuZCggZGVmYXVsdF90aCApO1xuXG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGRlZmF1bHRfdGggPSBuZXdfdGguY2xvbmUoKTtcblx0XHRcdFx0XHRcdGRlZmF1bHRfdGguY2hpbGRyZW4oIDAgKS50ZXh0KCBtb250aF9oZWFkZXJfdGV4dCApO1xuXHRcdFx0XHRcdFx0ZGVmYXVsdF90aC5hdHRyKCAnY29sc3BhbicsIHNhbWVfbW9udGhfY291bnQgKTtcblx0XHRcdFx0XHRcdGRlZmF1bHRfdHIuYXBwZW5kKCBkZWZhdWx0X3RoICk7XG5cblx0XHRcdFx0XHRcdGN1cnJlbnRfbW9udGggPSBtb250aDtcblx0XHRcdFx0XHRcdGN1cnJlbnRfZGF0ZSA9IGRhdGVfc3RyO1xuXHRcdFx0XHRcdFx0c2FtZV9tb250aF9jb3VudCA9IDE7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKCBtb250aCA9PT0gJy0xJyApIHtcblx0XHRcdFx0XHRcdGRlZmF1bHRfdGggPSBuZXdfdGguY2xvbmUoKTtcblx0XHRcdFx0XHRcdGRlZmF1bHRfdGguY2hpbGRyZW4oIDAgKS50ZXh0KCAnJyApO1xuXHRcdFx0XHRcdFx0ZGVmYXVsdF90aC5hdHRyKCAnY29sc3BhbicsIGxlbiAtIGkgKTtcblx0XHRcdFx0XHRcdGRlZmF1bHRfdHIuYXBwZW5kKCBkZWZhdWx0X3RoICk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0fVxuXHR9XG5cblx0c2V0TW9udGhEYXRlUm93UG9zaXRpb24oKSB7XG5cblx0XHRpZiAoIHRoaXMuZ2V0TW9kZSgpICE9PSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5NT05USCApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHRoaXMubW9udGhfZGF0ZV9yb3dfcG9zaXRpb24gPSB7fTtcblx0XHR2YXIgaSA9IDA7XG5cdFx0Zm9yICggdmFyIGtleSBpbiB0aGlzLm1vbnRoX2RhdGVfcm93X3RyX2lkcyApIHtcblx0XHRcdHRoaXMubW9udGhfZGF0ZV9yb3dfcG9zaXRpb25baV0gPSB0aGlzLmdyaWQuZ3JpZC5maW5kKCAnIycgKyBrZXkgKS5wb3NpdGlvbigpLnRvcDtcblx0XHRcdGkgPSBpICsgMTtcblx0XHR9XG5cblx0XHR0aGlzLmdyaWQuZ3JpZC5wYXJlbnQoKS5wYXJlbnQoKS5zY3JvbGwoIGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIHRvcCA9ICQoIHRoaXMgKS5zY3JvbGxUb3AoKTtcblxuXHRcdFx0dmFyIHN0YXJ0X2RheSA9ICR0aGlzLnN0YXJ0X2RhdGUuZ2V0RGF5KCk7XG5cblx0XHRcdGlmICggdG9wIDwgJHRoaXMubW9udGhfZGF0ZV9yb3dfcG9zaXRpb25bMF0gJiYgJHRoaXMubW9udGhfY3VycmVudF9oZWFkZXJfbnVtYmVyICE9PSAwICkge1xuXG5cdFx0XHRcdC8vRGVhbCB3aXRoIGhlYWRlciBiZWZvcmUgZmlyc3QgZGF0ZSByb3cuXG5cdFx0XHRcdCR0aGlzLm1vbnRoX2RhdGVfcm93X3RyX2lkcyA9IHt9O1xuXHRcdFx0XHQkdGhpcy5tb250aF9jdXJyZW50X2hlYWRlcl9udW1iZXIgPSAwO1xuXHRcdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCA3OyBpKysgKSB7XG5cdFx0XHRcdFx0dmFyIGN1cnJlbnRfZGF0ZSA9IG5ldyBEYXRlKCBuZXcgRGF0ZSggJHRoaXMuc3RhcnRfZGF0ZS5nZXRUaW1lKCkgKS5zZXREYXRlKCAkdGhpcy5zdGFydF9kYXRlLmdldERhdGUoKSArIGkgKSApO1xuXHRcdFx0XHRcdHZhciBoZWFkZXJfdGV4dCA9IGN1cnJlbnRfZGF0ZS5mb3JtYXQoICR0aGlzLndlZWtseV9mb3JtYXQgKTtcblx0XHRcdFx0XHR2YXIgaGVhZGVyX2NvbnRhaW5lciA9ICQoICR0aGlzLmVsICkuZmluZCggJyMnICsgJHRoaXMudWlfaWQgKyAnX2dyaWRfJyArIGRhdGFfZmllbGQgKTtcblx0XHRcdFx0XHR2YXIgZGF0YV9maWVsZCA9ICggKCBzdGFydF9kYXkgKyBpICkgJSA3ICk7XG5cdFx0XHRcdFx0dmFyIGhlYWRlciA9ICQoICR0aGlzLmVsICkuZmluZCggJyNqcWdoXycgKyAkdGhpcy51aV9pZCArICdfZ3JpZF8nICsgZGF0YV9maWVsZCApO1xuXHRcdFx0XHRcdGhlYWRlci50ZXh0KCBoZWFkZXJfdGV4dCApO1xuXHRcdFx0XHRcdGhlYWRlcl9jb250YWluZXIucmVtb3ZlQ2xhc3MoICdoaWdobGlnaHQtaGVhZGVyJyApO1xuXG5cdFx0XHRcdH1cblxuXHRcdFx0XHQkdGhpcy5oaWdoTGlnaHRTZWxlY3REYXkoKTtcblxuXHRcdFx0fSBlbHNlIGlmICggdG9wID4gJHRoaXMubW9udGhfZGF0ZV9yb3dfcG9zaXRpb25bMF0gJiYgdG9wIDwgJHRoaXMubW9udGhfZGF0ZV9yb3dfcG9zaXRpb25bMV0gJiYgJHRoaXMubW9udGhfY3VycmVudF9oZWFkZXJfbnVtYmVyICE9PSAxICkge1xuXHRcdFx0XHRzZXRIZWFkZXJUZXh0KCAwLCAxICk7XG5cblx0XHRcdH0gZWxzZSBpZiAoIHRvcCA+ICR0aGlzLm1vbnRoX2RhdGVfcm93X3Bvc2l0aW9uWzFdICYmIHRvcCA8ICR0aGlzLm1vbnRoX2RhdGVfcm93X3Bvc2l0aW9uWzJdICYmICR0aGlzLm1vbnRoX2N1cnJlbnRfaGVhZGVyX251bWJlciAhPT0gMiApIHtcblx0XHRcdFx0c2V0SGVhZGVyVGV4dCggMSwgMiApO1xuXHRcdFx0fSBlbHNlIGlmICggdG9wID4gJHRoaXMubW9udGhfZGF0ZV9yb3dfcG9zaXRpb25bMl0gJiYgdG9wIDwgJHRoaXMubW9udGhfZGF0ZV9yb3dfcG9zaXRpb25bM10gJiYgJHRoaXMubW9udGhfY3VycmVudF9oZWFkZXJfbnVtYmVyICE9PSAzICkge1xuXHRcdFx0XHRzZXRIZWFkZXJUZXh0KCAyLCAzICk7XG5cdFx0XHR9IGVsc2UgaWYgKCB0b3AgPiAkdGhpcy5tb250aF9kYXRlX3Jvd19wb3NpdGlvblszXSAmJiAkdGhpcy5tb250aF9jdXJyZW50X2hlYWRlcl9udW1iZXIgIT09IDQgKSB7XG5cdFx0XHRcdHNldEhlYWRlclRleHQoIDMsIDQgKTtcblx0XHRcdH1cblxuXHRcdFx0ZnVuY3Rpb24gc2V0SGVhZGVyVGV4dCggaW5kZXgsIGhlYWRlck51bWJlciApIHtcblx0XHRcdFx0JHRoaXMubW9udGhfZGF0ZV9yb3dfdHJfaWRzID0ge307XG5cdFx0XHRcdCR0aGlzLm1vbnRoX2N1cnJlbnRfaGVhZGVyX251bWJlciA9IGhlYWRlck51bWJlcjtcblx0XHRcdFx0dmFyIGRhdGVfcm93ID0gJHRoaXMubW9udGhfZGF0ZV9yb3dfYXJyYXlbaW5kZXhdO1xuXHRcdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCA3OyBpKysgKSB7XG5cdFx0XHRcdFx0dmFyIGRhdGFfZmllbGQgPSAoICggc3RhcnRfZGF5ICsgaSApICUgNyApO1xuXHRcdFx0XHRcdHZhciBoZWFkZXIgPSAkKCAkdGhpcy5lbCApLmZpbmQoICcjanFnaF8nICsgJHRoaXMudWlfaWQgKyAnX2dyaWRfJyArIGRhdGFfZmllbGQgKTtcblx0XHRcdFx0XHR2YXIgaGVhZGVyX2NvbnRhaW5lciA9ICQoICR0aGlzLmVsICkuZmluZCggJyMnICsgJHRoaXMudWlfaWQgKyAnX2dyaWRfJyArIGRhdGFfZmllbGQgKTtcblx0XHRcdFx0XHRoZWFkZXJfY29udGFpbmVyLnJlbW92ZUNsYXNzKCAnaGlnaGxpZ2h0LWhlYWRlcicgKTtcblx0XHRcdFx0XHR2YXIgZnVsbF9kYXRlID0gZGF0ZV9yb3dbZGF0YV9maWVsZCArICdfZnVsbF9kYXRlJ107XG5cdFx0XHRcdFx0dmFyIGRhdGVfY2VsbCA9ICQoICR0aGlzLmVsICkuZmluZCggJyMnICsgJHRoaXMudWlfaWQgKyAnX2dyaWRfJyArIGZ1bGxfZGF0ZSApO1xuXG5cdFx0XHRcdFx0aWYgKCBkYXRlX2NlbGwuaGFzQ2xhc3MoICdoaWdobGlnaHQtaGVhZGVyJyApICkge1xuXHRcdFx0XHRcdFx0aGVhZGVyX2NvbnRhaW5lci5hZGRDbGFzcyggJ2hpZ2hsaWdodC1oZWFkZXInICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGhlYWRlci5odG1sKCBkYXRlX3Jvd1tkYXRhX2ZpZWxkXSApO1xuXG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdH0gKTtcblx0fVxuXG5cdHNldEdyaWRIZWlnaHQoKSB7XG5cdFx0bGV0IHNjcm9sbF9oZWlnaHQgPSBkb2N1bWVudC5ib2R5LnNjcm9sbEhlaWdodDtcblxuXHRcdGxldCBoZWlnaHQgPSBzY3JvbGxfaGVpZ2h0O1xuXG5cdFx0bGV0IHRhYmxlX2JvZHkgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCAnZGl2LnVpLWpxZ3JpZC1iZGl2LnVpLWNvcm5lci1ib3R0b20nICk7XG5cdFx0bGV0IGNvbnRleHRfYm9yZGVyID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvciggJ2Rpdi5jb250ZXh0LWJvcmRlcicgKTtcblx0XHQvL0lzc3VlICMzMDYwIC0gSmF2YVNjcmlwdCBleGNlcHRpb25zIG9mIHRyeWluZyB0byByZWFkIGdldEJvdW5kaW5nQ2xpZW50UmVjdCBvZiBudWxsIGVsZW1lbnRzLlxuXHRcdGlmICggIXRhYmxlX2JvZHkgfHwgIWNvbnRleHRfYm9yZGVyICkge1xuXHRcdFx0cmV0dXJuIHNjcm9sbF9oZWlnaHQ7XG5cdFx0fVxuXG5cdFx0aGVpZ2h0IC09IHRhYmxlX2JvZHkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wO1xuXHRcdGhlaWdodCAtPSAoIHNjcm9sbF9oZWlnaHQgLSBjb250ZXh0X2JvcmRlci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5ib3R0b20gKTtcblx0XHRoZWlnaHQgLT0gMTA7IC8vTWFudWFsIGZpbmUgdHVuaW5nIHRvIGZpdCBiZXR0ZXIuXG5cblx0XHRpZiAoIHRoaXMuZ2V0TW9kZSgpICE9IFNjaGVkdWxlVmlld0NvbnRyb2xsZXJNb2RlLkRBWSApIHtcblx0XHRcdHZhciBncmlkX2RpdiA9ICQoICcuc2NoZWR1bGUtdmlldyAuZ3JpZC1kaXYgLnVpLWpxZ3JpZC1iZGl2JyApO1xuXHRcdFx0aWYgKCBncmlkX2RpdiAmJiBncmlkX2Rpdi5sZW5ndGggPiAwICYmIGdyaWRfZGl2WzBdLnNjcm9sbFdpZHRoID4gKCAkKCAnLmNvbnRleHQtYm9yZGVyJyApLndpZHRoKCkgKyAyICkgKSB7IC8vdGhpcyBwbHVzIDIgaXMgYmVjYXVzZSBzb21ldGltZXMgdGhlIHNjcm9sbCB3aWR0aCBpcyBsYXJnZXIgdGhhbiB0aGUgdmlldyB3aWR0aCB3aXRoIG5vIHNjcm9sbGJhclxuXHRcdFx0XHRoZWlnaHQgLT0gR2xvYmFsLmdldFNjcm9sbGJhcldpZHRoKCk7IC8vc2Nyb2xsYmFyIGNvbXBlbnNhdGlvblxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHRoaXMuZ3JpZC5zZXRHcmlkSGVpZ2h0KCBoZWlnaHQgKTtcblx0XHRyZXR1cm4gaGVpZ2h0O1xuXHR9XG5cblx0c2V0R3JpZENvbHVtbnNXaWR0aCgpIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHN3aXRjaCAoIHRoaXMuZ2V0TW9kZSgpICkge1xuXHRcdFx0Y2FzZSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5EQVk6XG5cdFx0XHRcdHZhciBkYXlfY29sdW1uX2luZGV4O1xuXG5cdFx0XHRcdC8vQ2FsY3VsYXRlIHRoZSBleGFjdCB3aWR0aCBvZiBlYWNoIGNvbHVtbiB0aGF0IGlzbid0IHdoZXJlIHRoZSBzaGlmdCB0aW1lcyBhcmUgZGlzcGxheWVkLlxuXHRcdFx0XHQvL1RoZW4gYW55IHJlbWFpbmluZyB3aWR0aCBjYW4gYmUgYWxsb2NhdGVkIHRvIHRoZSBzaGlmdCB0aW1lcyBjb2x1bW4uXG5cdFx0XHRcdHZhciBjb2x1bW5fcGFkZGluZyA9IDEwO1xuXHRcdFx0XHQvL3ZhciBncmlkX2RhdGEgPSB0aGlzLmdyaWQuZ2V0RGF0YSgpO1xuXHRcdFx0XHR2YXIgZ3JpZF9kYXRhID0gJHRoaXMuc2NoZWR1bGVfc291cmNlOyAvL011c3QgdXNlIHRoZSBvcmlnaW5hbCBzb3VyY2UgZGF0YSwgYXMgdGhlIHRoaXMuZ3JpZC5nZXREYXRhKCkgaXMgbm90IHBvcHVsYXRlZCB5ZXQuXG5cdFx0XHRcdGZvciAoIHZhciBpIGluIHRoaXMuc2NoZWR1bGVfY29sdW1ucyApIHtcblx0XHRcdFx0XHRpZiAoIHRoaXMuc2NoZWR1bGVfY29sdW1uc1tpXS5pc19zdGF0aWNfc2l6ZSA9PSB0cnVlIHx8IHRoaXMuc2NoZWR1bGVfY29sdW1uc1tpXS5uYW1lID09ICdzY3JvbGxiYXJfc3BhY2VyJyApIHtcblx0XHRcdFx0XHRcdHRoaXMuc2NoZWR1bGVfY29sdW1uc1tpXS5maXhlZCA9IHRydWU7XG5cdFx0XHRcdFx0XHRpZiAoIHRoaXMuc2NoZWR1bGVfY29sdW1uc1tpXS5uYW1lICE9ICdzY3JvbGxiYXJfc3BhY2VyJyApIHtcblx0XHRcdFx0XHRcdFx0ZGF5X2NvbHVtbl9pbmRleCA9IGk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdC8vc2l6ZSBjb2x1bW4gYmFzZWQgb24gdGV4dC5cblx0XHRcdFx0XHRcdHZhciBjb2x1bW5fd2lkdGggPSBHbG9iYWwuY2FsY3VsYXRlVGV4dFdpZHRoKCB0aGlzLnNjaGVkdWxlX2NvbHVtbnNbaV0ubGFiZWwgKSArIGNvbHVtbl9wYWRkaW5nO1xuXG5cdFx0XHRcdFx0XHRpZiAoIGdyaWRfZGF0YSAmJiBncmlkX2RhdGEubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0XHRcdFx0Zm9yICggdmFyIHJvdyBpbiBncmlkX2RhdGEgKSB7XG5cdFx0XHRcdFx0XHRcdFx0dmFyIG5ld19jb2xfd2lkdGggPSBHbG9iYWwuY2FsY3VsYXRlVGV4dFdpZHRoKCBncmlkX2RhdGFbcm93XVt0aGlzLnNjaGVkdWxlX2NvbHVtbnNbaV0ubmFtZV0gKTtcblx0XHRcdFx0XHRcdFx0XHRpZiAoIG5ld19jb2xfd2lkdGggPiBjb2x1bW5fd2lkdGggKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRjb2x1bW5fd2lkdGggPSBuZXdfY29sX3dpZHRoO1xuXHRcdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdHRoaXMuc2NoZWR1bGVfY29sdW1uc1tpXS53aWR0aCA9IGNvbHVtbl93aWR0aDtcblx0XHRcdFx0XHRcdHRoaXMuc2NoZWR1bGVfY29sdW1uc1tpXS5maXhlZCA9IHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0dGhpcy5jYWxjdWxhdGVTY2hlZHVsZVdpZHRoKCk7XG5cdFx0XHRcdCQoICcuZGF5X2hvdXJfZGl2IC5kYXlfaG91cl9zcGFuJyApLndpZHRoKCB0aGlzLmRheV9ob3VyX3dpZHRoICk7XG5cdFx0XHRcdHZhciBkYXlfY29sdW1uX3dpZHRoID0gKCB0aGlzLmRheV9ob3VyX3dpZHRoICogJCggJy5kYXlfaG91cl9kaXYgLmRheV9ob3VyX3NwYW4nICkubGVuZ3RoICk7IC8vIDYwIGlzIGRlc2lyZWQgd2lkdGggb2YgZWFjaCBkYXkgc3BhblxuXG5cdFx0XHRcdHRoaXMuc2NoZWR1bGVfY29sdW1uc1tkYXlfY29sdW1uX2luZGV4XS53aWR0aCA9IGRheV9jb2x1bW5fd2lkdGg7XG5cblx0XHRcdFx0dGhpcy5ncmlkLnNldEdyaWRDb2x1bW5zV2lkdGgoIHRoaXMuc2NoZWR1bGVfY29sdW1ucyApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdHZhciBjb2x1bW5fcGFkZGluZyA9IDEwO1xuXHRcdFx0XHR2YXIgY29sdW1uc193aWR0aCA9IDA7XG5cblx0XHRcdFx0Ly9EYXkgY29sdW1ucyBtdXN0IGFsd2F5cyBiZSB0aGUgc2FtZSB3aWR0aCwgb25seSBtYWtlIHRoZSBlbXBsb3llZSBuYW1lIGFuZCBvdGhlciBzdGF0aWMgY29sdW1ucyB2YXJpYWJsZSB3aWR0aC5cblx0XHRcdFx0dmFyIG1heF93aWR0aCA9ICQoICcuY29udGV4dC1ib3JkZXInICkud2lkdGgoKTtcblxuXHRcdFx0XHR2YXIgZ3JpZF9kYXRhID0gJHRoaXMuc2NoZWR1bGVfc291cmNlOyAvL011c3QgdXNlIHRoZSBvcmlnaW5hbCBzb3VyY2UgZGF0YSwgYXMgdGhlIHRoaXMuZ3JpZC5nZXREYXRhKCkgaXMgbm90IHBvcHVsYXRlZCB5ZXQuXG5cdFx0XHRcdGZvciAoIHZhciBpIGluIHRoaXMuc2NoZWR1bGVfY29sdW1ucyApIHtcblx0XHRcdFx0XHRpZiAoICF0aGlzLnNjaGVkdWxlX2NvbHVtbnNbaV0uaXNfc3RhdGljX3NpemUgfHwgdGhpcy5zY2hlZHVsZV9jb2x1bW5zW2ldLmlzX3N0YXRpY19zaXplID09IGZhbHNlICkge1xuXHRcdFx0XHRcdFx0Ly9zaXplIGNvbHVtbiBiYXNlZCBvbiB0ZXh0LlxuXHRcdFx0XHRcdFx0dmFyIGNvbHVtbl93aWR0aCA9IEdsb2JhbC5jYWxjdWxhdGVUZXh0V2lkdGgoIHRoaXMuc2NoZWR1bGVfY29sdW1uc1tpXS5sYWJlbCwgeyBwYWRkaW5nOiBjb2x1bW5fcGFkZGluZyB9ICk7XG5cblx0XHRcdFx0XHRcdGlmICggZ3JpZF9kYXRhICYmIGdyaWRfZGF0YS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHRcdFx0XHR2YXIgbGFiZWxfY2FjaGUgPSBbXTtcblxuXHRcdFx0XHRcdFx0XHRmb3IgKCB2YXIgcm93IGluIGdyaWRfZGF0YSApIHtcblx0XHRcdFx0XHRcdFx0XHR2YXIgbGFiZWwgPSBncmlkX2RhdGFbcm93XVt0aGlzLnNjaGVkdWxlX2NvbHVtbnNbaV0ubmFtZV07XG5cdFx0XHRcdFx0XHRcdFx0aWYgKCAhbGFiZWxfY2FjaGVbbGFiZWxdKSB7IC8vQ2FjaGUgbGFiZWxzIHdlIGhhdmUgYWxyZWFkeSBjYWxjdWxhdGVkIHRoZSBzaXplIG9uLCBzbyB3ZSBkb24ndCBkbyBpdCBvdmVyIGFuZCBvdmVyIGFnYWluLlxuXHRcdFx0XHRcdFx0XHRcdFx0dmFyIG5ld19jb2xfd2lkdGggPSBHbG9iYWwuY2FsY3VsYXRlVGV4dFdpZHRoKCBsYWJlbCwgeyBwYWRkaW5nOiBjb2x1bW5fcGFkZGluZyB9ICk7XG5cdFx0XHRcdFx0XHRcdFx0XHRpZiAoIG5ld19jb2xfd2lkdGggPiBjb2x1bW5fd2lkdGggKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGNvbHVtbl93aWR0aCA9IG5ld19jb2xfd2lkdGg7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHRsYWJlbF9jYWNoZVtsYWJlbF0gPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdGxhYmVsX2NhY2hlID0gbnVsbDtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0dGhpcy5zY2hlZHVsZV9jb2x1bW5zW2ldLndpZHRoID0gY29sdW1uX3dpZHRoO1xuXHRcdFx0XHRcdFx0dGhpcy5zY2hlZHVsZV9jb2x1bW5zW2ldLmZpeGVkID0gdHJ1ZTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRjb2x1bW5zX3dpZHRoICs9IHRoaXMuc2NoZWR1bGVfY29sdW1uc1tpXS53aWR0aDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vUmVzaXplIGZpcnN0IGNvbHVtbiB0byBmaWxsIHNjcmVlbi5cblx0XHRcdFx0aWYgKCB0aGlzLnNjaGVkdWxlX2NvbHVtbnNbMF0gJiYgY29sdW1uc193aWR0aCA8IG1heF93aWR0aCApIHtcblx0XHRcdFx0XHR0aGlzLnNjaGVkdWxlX2NvbHVtbnNbMF0ud2lkdGggKz0gKCBtYXhfd2lkdGggLSBjb2x1bW5zX3dpZHRoICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR0aGlzLmdyaWQuc2V0R3JpZENvbHVtbnNXaWR0aCggdGhpcy5zY2hlZHVsZV9jb2x1bW5zICk7XG5cblx0XHRcdFx0aWYgKCB0aGlzLmdldE1vZGUoKSA9PSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5ZRUFSICkge1xuXHRcdFx0XHRcdHRoaXMuc2V0WWVhckdyb3VwSGVhZGVyKCk7IC8vTXVzdCBnbyBhZnRlciB0aGUgY29sdW1uIHdpZHRocyBhcmUgY2hhbmdlZC5cblx0XHRcdFx0fVxuXG5cdFx0XHRcdGJyZWFrO1xuXHRcdH1cblxuXHRcdHRoaXMuc2V0R3JpZEhlaWdodCgpO1xuXHR9XG5cblx0YnVpbGRTY2hlZHVsZVNvdXJjZSgpIHtcblx0XHR0aGlzLm5vX2RhdGVfYXJyYXkgPSBbXTtcblx0XHR0aGlzLmhhc19kYXRlX2FycmF5ID0gW107XG5cdFx0dGhpcy5maW5hbF9zY2hlZHVsZV9kYXRhX2FycmF5ID0gW107XG5cdFx0dmFyIG1vZGUgPSB0aGlzLmdldE1vZGUoKTtcblxuXHRcdHRoaXMubm9fZGF0ZV9hcnJheSA9IHRoaXMuYnVpbGROb0RhdGVBcnJheSgpO1xuXHRcdHRoaXMuaGFzX2RhdGVfYXJyYXkgPSB0aGlzLmJ1aWxkSGFzRGF0ZUFycmF5KCk7XG5cdFx0dmFyIGhhc19kYXRlX3RlbXBfYXJyYXlfbGVuZ3RoID0gdGhpcy5oYXNfZGF0ZV9hcnJheS5sZW5ndGg7XG5cdFx0dmFyIHNvcnRfZmllbGRzID0gdGhpcy5idWlsZFNvcnRGaWVsZHMoKTtcblx0XHR0aGlzLmhhc19kYXRlX2FycmF5LnNvcnQoIEdsb2JhbC5tX3NvcnRfYnkoIHNvcnRfZmllbGRzICkgKTtcblx0XHR0aGlzLm5vX2RhdGVfYXJyYXkuc29ydCggR2xvYmFsLm1fc29ydF9ieSggc29ydF9maWVsZHMgKSApO1xuXG5cdFx0aWYgKCBtb2RlICE9PSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5NT05USCApIHtcblx0XHRcdHRoaXMuZmluYWxfc2NoZWR1bGVfZGF0YV9hcnJheSA9IHRoaXMubm9fZGF0ZV9hcnJheS5jb25jYXQoIHRoaXMuaGFzX2RhdGVfYXJyYXkgKTtcblx0XHR9XG5cblx0XHRzd2l0Y2ggKCB0aGlzLmdldE1vZGUoKSApIHtcblx0XHRcdGNhc2UgU2NoZWR1bGVWaWV3Q29udHJvbGxlck1vZGUuV0VFSzpcblx0XHRcdFx0dGhpcy5idWlsZFdlZWtseVNvdXJjZSgpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgU2NoZWR1bGVWaWV3Q29udHJvbGxlck1vZGUuTU9OVEg6XG5cdFx0XHRcdHRoaXMuYnVpbGRNb250aFNvdXJjZSgpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgU2NoZWR1bGVWaWV3Q29udHJvbGxlck1vZGUuWUVBUjpcblx0XHRcdFx0dGhpcy5idWlsZFllYXJseVNvdXJjZSgpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgU2NoZWR1bGVWaWV3Q29udHJvbGxlck1vZGUuREFZOlxuXHRcdFx0XHR0aGlzLmJ1aWxkRGFpbHlTb3VyY2UoKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0fVxuXHR9XG5cblx0YnVpbGRTaGlmdEtleSggc2hpZnQgKSB7XG5cblx0XHR2YXIga2V5ID0gJyc7XG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgdGhpcy5zaGlmdF9rZXlfbmFtZV9hcnJheS5sZW5ndGg7IGkrKyApIHtcblx0XHRcdHZhciBmaWVsZF9uYW1lID0gdGhpcy5zaGlmdF9rZXlfbmFtZV9hcnJheVtpXTtcblx0XHRcdHZhciBjb2x1bW5fbmFtZSA9IHRoaXMuc2hpZnRfa2V5X25hbWVfYXJyYXlbaV0ucmVwbGFjZSggJ19pZCcsICcnICk7IC8vanVkZ2UgaWYgc2hpdCBoYXMgY29ycmVjdCBmaWVsZCB2YWx1ZVxuXHRcdFx0aWYgKCBjb2x1bW5fbmFtZSAhPT0gJ3VzZXInICkge1xuXHRcdFx0XHRpZiAoIHNoaWZ0W2NvbHVtbl9uYW1lXSApIHtcblx0XHRcdFx0XHRrZXkgPSBzaGlmdFtmaWVsZF9uYW1lXSArICctJyArIGtleTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRrZXkgPSAwICsgJy0nICsga2V5O1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRrZXkgPSBzaGlmdFtmaWVsZF9uYW1lXSArICctJyArIGtleTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIGtleTtcblx0fVxuXG5cdGJ1aWxkTW9udGhTb3VyY2UoKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgZGF0ZV9yb3dfaW5kZXggPSAwO1xuXHRcdHZhciBtb250aF93ZWVrX2RhdGFfaW5kZXggPSAwO1xuXHRcdHZhciBkYXRlX3JvdyA9IHRoaXMubW9udGhfZGF0ZV9yb3dfYXJyYXlbZGF0ZV9yb3dfaW5kZXhdO1xuXHRcdHZhciBzdGFydF9kYXkgPSB0aGlzLnN0YXJ0X2RhdGUuZ2V0RGF5KCk7IC8vc3RhcnQgZnJvbSBmaXJzdCBkYXRlIHJvdywgbm90IGluY2x1ZGUgY29sdW1uXG5cdFx0dmFyIGZpcnN0X2RheV90aW1lID0gZGF0ZV9yb3dbc3RhcnRfZGF5ICsgJ190aW1lJ107XG5cdFx0dmFyIG1vbnRoX3dlZWtfZGF0YV9hcnJheSA9IFtdO1xuXHRcdHZhciBoYXNfZGF0ZV9hcnJheSA9IHRoaXMuaGFzX2RhdGVfYXJyYXkuc2xpY2UoKTtcblx0XHRmb3IgKCB2YXIgaiA9IDA7IGogPCA1OyBqKysgKSB7XG5cdFx0XHR2YXIgY3VycmVudF93ZWVrX2FycmF5ID0gW107XG5cdFx0XHR2YXIgbGVuID0gaGFzX2RhdGVfYXJyYXkubGVuZ3RoO1xuXHRcdFx0dmFyIGlzX2xhc3Rfcm93ID0gZmFsc2U7XG5cdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblxuXHRcdFx0XHR2YXIgc2hpZnQgPSBoYXNfZGF0ZV9hcnJheVtpXTtcblx0XHRcdFx0dmFyIGRhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCBzaGlmdC5kYXRlX3N0YW1wICk7XG5cdFx0XHRcdHZhciB0aW1lID0gZGF0ZS5nZXRUaW1lKCk7XG5cblx0XHRcdFx0aWYgKCB0aW1lIDwgZmlyc3RfZGF5X3RpbWUgKSB7XG5cblx0XHRcdFx0XHRoYXNfZGF0ZV9hcnJheS5zcGxpY2UoIGksIDEgKTtcblxuXHRcdFx0XHRcdGkgPSBpIC0gMTtcblx0XHRcdFx0XHRsZW4gPSBsZW4gLSAxO1xuXG5cdFx0XHRcdFx0Y3VycmVudF93ZWVrX2FycmF5LnB1c2goIHNoaWZ0ICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0aWYgKCB0aGlzLnNldHRpbmdzX21lbnUuZ2V0QnV0dG9uKCAnYWxsX2VtcGxveWVlX2J0bicgKS5hY3RpdmUgKSB7XG5cdFx0XHRcdGlmICggaiA9PT0gMCApIHtcblx0XHRcdFx0XHRjdXJyZW50X3dlZWtfYXJyYXkgPSB0aGlzLm5vX2RhdGVfYXJyYXkuc2xpY2UoKS5jb25jYXQoIGN1cnJlbnRfd2Vla19hcnJheSApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdC8vIG9ubHkgZmlyc3Qgd2VlayBlbXB0eSB1c2VycyBhcmUgY29tbWluZyBmcm9tIEFQSSwgY2FsY3VsYXRlIGFsbCBvdGhlciB3ZWVrcyBkYXRhXG5cdFx0XHRcdFx0dmFyIG5vX2RhdGVfYXJyYXkgPSB0aGlzLmJ1aWxkTW9udGhXZWVrTm9EYXRlQXJyYXkoIGN1cnJlbnRfd2Vla19hcnJheSApO1xuXHRcdFx0XHRcdGN1cnJlbnRfd2Vla19hcnJheSA9IG5vX2RhdGVfYXJyYXkuc2xpY2UoKS5jb25jYXQoIGN1cnJlbnRfd2Vla19hcnJheSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdG1vbnRoX3dlZWtfZGF0YV9hcnJheVttb250aF93ZWVrX2RhdGFfaW5kZXhdID0gY3VycmVudF93ZWVrX2FycmF5O1xuXHRcdFx0aWYgKCBkYXRlX3Jvd19pbmRleCA+IDIgKSB7XG5cdFx0XHRcdGlzX2xhc3Rfcm93ID0gdHJ1ZTtcblx0XHRcdH0gZWxzZSBpZiAoIGRhdGVfcm93X2luZGV4ID09PSAyICYmICF0aGlzLm1vbnRoX2RhdGVfcm93X2FycmF5WzNdLmhhc093blByb3BlcnR5KCAwICkgKSB7XG5cdFx0XHRcdGlzX2xhc3Rfcm93ID0gdHJ1ZTtcblx0XHRcdH1cblx0XHRcdGlmICggIWlzX2xhc3Rfcm93ICkge1xuXHRcdFx0XHRkYXRlX3Jvd19pbmRleCA9IGRhdGVfcm93X2luZGV4ICsgMTtcblx0XHRcdFx0bW9udGhfd2Vla19kYXRhX2luZGV4ID0gbW9udGhfd2Vla19kYXRhX2luZGV4ICsgMTtcblx0XHRcdFx0ZGF0ZV9yb3cgPSB0aGlzLm1vbnRoX2RhdGVfcm93X2FycmF5W2RhdGVfcm93X2luZGV4XTtcblx0XHRcdFx0Zmlyc3RfZGF5X3RpbWUgPSBkYXRlX3Jvd1tzdGFydF9kYXkgKyAnX3RpbWUnXTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdG1vbnRoX3dlZWtfZGF0YV9pbmRleCA9IG1vbnRoX3dlZWtfZGF0YV9pbmRleCArIDE7XG5cblx0XHRcdFx0Ly9Eb24ndCB1c2UgdGhpcy5lbmRfZGF0ZSBiZWNhdXNlIHRoZSBlbmQgZGF0ZSBtYXkgbGFyZ2VyIHRoYW4gdGhlIGxhc3QgZGF5IG9mIHRoaXMgbW9udGguIFVzZSB0aGUgbGFzdCBkYXRlIGluIGRhdGUgcm93XG5cdFx0XHRcdHZhciBlbmRfZGF0ZV90aW1lID0gdGhpcy5nZXRMYXN0RGF0ZU9mUm93KCB0aGlzLm1vbnRoX2RhdGVfcm93X2FycmF5W2RhdGVfcm93X2luZGV4XSApO1xuXHRcdFx0XHR2YXIgZW5kX2RhdGUgPSBuZXcgRGF0ZSggZW5kX2RhdGVfdGltZSApO1xuXHRcdFx0XHRmaXJzdF9kYXlfdGltZSA9IG5ldyBEYXRlKCBlbmRfZGF0ZS5zZXREYXRlKCBlbmRfZGF0ZS5nZXREYXRlKCkgKyAxICkgKS5nZXRUaW1lKCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0YnVpbGRNb250aFdlZWtseURhdGEoIC0xLCBtb250aF93ZWVrX2RhdGFfYXJyYXlbMF0gKTtcblx0XHRidWlsZE1vbnRoV2Vla2x5RGF0YSggMCwgbW9udGhfd2Vla19kYXRhX2FycmF5WzFdICk7XG5cdFx0YnVpbGRNb250aFdlZWtseURhdGEoIDEsIG1vbnRoX3dlZWtfZGF0YV9hcnJheVsyXSApO1xuXHRcdGJ1aWxkTW9udGhXZWVrbHlEYXRhKCAyLCBtb250aF93ZWVrX2RhdGFfYXJyYXlbM10gKTtcblx0XHRidWlsZE1vbnRoV2Vla2x5RGF0YSggMywgbW9udGhfd2Vla19kYXRhX2FycmF5WzRdICk7XG5cblx0XHRmdW5jdGlvbiBidWlsZE1vbnRoV2Vla2x5RGF0YSggcm93SW5kZXgsIHNvdXJjZV9hcnJheSApIHtcblx0XHRcdGlmICggc291cmNlX2FycmF5Lmxlbmd0aCA8IDEgKSB7XG5cdFx0XHRcdGJ1aWxkRW1wdHlSb3coIHJvd0luZGV4ICk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHRcdHZhciBtYXAgPSB7fTtcblx0XHRcdHZhciBsZW4gPSBzb3VyY2VfYXJyYXkubGVuZ3RoO1xuXHRcdFx0dmFyIHB1c2hfdG9fbGFzdCA9IGZhbHNlO1xuXG5cdFx0XHRpZiAoIHJvd0luZGV4ID09PSAkdGhpcy5tb250aF9kYXRlX3Jvd19hcnJheS5sZW5ndGggLSAxICkge1xuXHRcdFx0XHRwdXNoX3RvX2xhc3QgPSB0cnVlO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dmFyIGRhdGVfcm93ID0gJHRoaXMubW9udGhfZGF0ZV9yb3dfYXJyYXlbcm93SW5kZXggKyAxXTtcblx0XHRcdFx0dmFyIGluZGV4ID0gMDtcblx0XHRcdH1cblxuXHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRcdHZhciBzaGlmdCA9IHNvdXJjZV9hcnJheVtpXTtcblx0XHRcdFx0dmFyIGRhdGVfc3RyaW5nO1xuXHRcdFx0XHRpZiAoIHNoaWZ0LmRhdGVfc3RhbXAgKSB7XG5cdFx0XHRcdFx0dmFyIGRhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCBzaGlmdC5kYXRlX3N0YW1wICk7XG5cblx0XHRcdFx0XHRkYXRlX3N0cmluZyA9IGRhdGUuZ2V0RGF5KCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR2YXIga2V5ID0gJHRoaXMuYnVpbGRTaGlmdEtleSggc2hpZnQgKTtcblxuXHRcdFx0XHQvLyBlYWNoIHJvdyBvZiBzY2hlZHVsZSBkYXRhLCBzdGFydCBmcm9tIGZpcnN0IHJvd1xuXHRcdFx0XHRpZiAoICFtYXBba2V5XSApIHtcblx0XHRcdFx0XHR2YXIgcm93ID0ge307XG5cdFx0XHRcdFx0cm93LnVzZXJfZnVsbF9uYW1lID0gc2hpZnQudXNlcl9mdWxsX25hbWU7XG5cdFx0XHRcdFx0cm93Lmxhc3RfbmFtZSA9IHNoaWZ0Lmxhc3RfbmFtZTtcblx0XHRcdFx0XHRyb3cudXNlcl9pZCA9IHNoaWZ0LnVzZXJfaWQ7XG5cdFx0XHRcdFx0cm93LmJyYW5jaF9pZCA9IHNoaWZ0LmJyYW5jaF9pZDtcblx0XHRcdFx0XHRyb3cuZGVwYXJ0bWVudF9pZCA9IHNoaWZ0LmRlcGFydG1lbnRfaWQ7XG5cdFx0XHRcdFx0cm93LnNjaGVkdWxlX3BvbGljeV9pZCA9IHNoaWZ0LnNjaGVkdWxlX3BvbGljeV9pZDtcblx0XHRcdFx0XHRyb3cuam9iX2lkID0gc2hpZnQuam9iX2lkO1xuXHRcdFx0XHRcdHJvdy5qb2JfaXRlbV9pZCA9IHNoaWZ0LmpvYl9pdGVtX2lkO1xuXHRcdFx0XHRcdHJvdy5wdW5jaF90YWdfaWQgPSBzaGlmdC5wdW5jaF90YWdfaWQ7XG5cblx0XHRcdFx0XHR2YXIgZGlzcGxheV9jb2x1bW5zID0gJHRoaXMuc2VsZWN0X2xheW91dC5kYXRhLmRpc3BsYXlfY29sdW1ucztcblx0XHRcdFx0XHR2YXIgZGlzcGxheV9jb2x1bW5zX2xlbiA9IGRpc3BsYXlfY29sdW1ucy5sZW5ndGg7XG5cblx0XHRcdFx0XHRmb3IgKCB2YXIgaiA9IDA7IGogPCBkaXNwbGF5X2NvbHVtbnNfbGVuOyBqKysgKSB7XG5cdFx0XHRcdFx0XHR2YXIgZmllbGRfbmFtZSA9IGRpc3BsYXlfY29sdW1uc1tqXTtcblx0XHRcdFx0XHRcdHJvd1tmaWVsZF9uYW1lXSA9IHNoaWZ0W2ZpZWxkX25hbWVdID8gc2hpZnRbZmllbGRfbmFtZV0gOiAnJztcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoIGRhdGVfc3RyaW5nID49IDAgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIHNoaWZ0LnN0YXR1c19pZCA9PSAyMCApIHtcblxuXHRcdFx0XHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmddID0gJHRoaXMuZ2V0QWJzZW5jZUNlbGxWYWx1ZSggc2hpZnQgKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZ10gPSBzaGlmdC5zdGFydF90aW1lICsgJyAtICcgKyBzaGlmdC5lbmRfdGltZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZyArICdfZGF0YSddID0gc2hpZnQ7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKCAhcHVzaF90b19sYXN0ICkge1xuXHRcdFx0XHRcdFx0aW5kZXggPSAkdGhpcy5zY2hlZHVsZV9zb3VyY2UuaW5kZXhPZiggZGF0ZV9yb3cgKTtcblx0XHRcdFx0XHRcdCR0aGlzLnNjaGVkdWxlX3NvdXJjZS5zcGxpY2UoIGluZGV4LCAwLCByb3cgKTtcblx0XHRcdFx0XHRcdG1hcFtrZXldID0gW2luZGV4XTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0JHRoaXMuc2NoZWR1bGVfc291cmNlLnB1c2goIHJvdyApO1xuXHRcdFx0XHRcdFx0bWFwW2tleV0gPSBbJHRoaXMuc2NoZWR1bGVfc291cmNlLmxlbmd0aCAtIDFdO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdC8vIGlmIG9uZSByb3cgYWxyZWFkeSBjcmVhdGVkLCBnbyB0byBoZXJlIHRvIGNyZWF0ZSBjZWxscyBpbiB0aGlzIHJvd1xuXG5cdFx0XHRcdFx0dmFyIGZpbmRfcG9zaXRpb24gPSBmYWxzZTtcblx0XHRcdFx0XHRmb3IgKCB2YXIgeCA9IDA7IHggPCBtYXBba2V5XS5sZW5ndGg7IHgrKyApIHtcblx0XHRcdFx0XHRcdHZhciByb3dfaW5kZXggPSBtYXBba2V5XVt4XTtcblx0XHRcdFx0XHRcdHJvdyA9ICR0aGlzLnNjaGVkdWxlX3NvdXJjZVtyb3dfaW5kZXhdO1xuXHRcdFx0XHRcdFx0aWYgKCByb3dbZGF0ZV9zdHJpbmddICkge1xuXHRcdFx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0XHRcdFx0aWYgKCBkYXRlX3N0cmluZyA+PSAwICkge1xuXHRcdFx0XHRcdFx0XHRcdGlmICggc2hpZnQuc3RhdHVzX2lkID09IDIwICkge1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmddID0gJHRoaXMuZ2V0QWJzZW5jZUNlbGxWYWx1ZSggc2hpZnQgKTtcblx0XHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nXSA9IHNoaWZ0LnN0YXJ0X3RpbWUgKyAnIC0gJyArIHNoaWZ0LmVuZF90aW1lO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmcgKyAnX2RhdGEnXSA9IHNoaWZ0O1xuXHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0ZmluZF9wb3NpdGlvbiA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICggIWZpbmRfcG9zaXRpb24gKSB7XG5cdFx0XHRcdFx0XHRyb3cgPSB7fTtcblx0XHRcdFx0XHRcdHJvdy51c2VyX2Z1bGxfbmFtZSA9IHNoaWZ0LnVzZXJfZnVsbF9uYW1lO1xuXHRcdFx0XHRcdFx0cm93Lmxhc3RfbmFtZSA9IHNoaWZ0Lmxhc3RfbmFtZTtcblx0XHRcdFx0XHRcdHJvdy51c2VyX2lkID0gc2hpZnQudXNlcl9pZDtcblx0XHRcdFx0XHRcdHJvdy5icmFuY2hfaWQgPSBzaGlmdC5icmFuY2hfaWQ7XG5cdFx0XHRcdFx0XHRyb3cuZGVwYXJ0bWVudF9pZCA9IHNoaWZ0LmRlcGFydG1lbnRfaWQ7XG5cdFx0XHRcdFx0XHRyb3cuc2NoZWR1bGVfcG9saWN5X2lkID0gc2hpZnQuc2NoZWR1bGVfcG9saWN5X2lkO1xuXHRcdFx0XHRcdFx0cm93LmpvYl9pZCA9IHNoaWZ0LmpvYl9pZDtcblx0XHRcdFx0XHRcdHJvdy5qb2JfaXRlbV9pZCA9IHNoaWZ0LmpvYl9pdGVtX2lkO1xuXHRcdFx0XHRcdFx0cm93LnB1bmNoX3RhZ19pZCA9IHNoaWZ0LnB1bmNoX3RhZ19pZDtcblxuXHRcdFx0XHRcdFx0ZGlzcGxheV9jb2x1bW5zID0gJHRoaXMuc2VsZWN0X2xheW91dC5kYXRhLmRpc3BsYXlfY29sdW1ucztcblx0XHRcdFx0XHRcdGRpc3BsYXlfY29sdW1uc19sZW4gPSBkaXNwbGF5X2NvbHVtbnMubGVuZ3RoO1xuXG5cdFx0XHRcdFx0XHRmb3IgKCB2YXIgaiA9IDA7IGogPCBkaXNwbGF5X2NvbHVtbnNfbGVuOyBqKysgKSB7XG5cdFx0XHRcdFx0XHRcdGZpZWxkX25hbWUgPSBkaXNwbGF5X2NvbHVtbnNbal07XG5cdFx0XHRcdFx0XHRcdHJvd1tmaWVsZF9uYW1lXSA9IHNoaWZ0W2ZpZWxkX25hbWVdID8gc2hpZnRbZmllbGRfbmFtZV0gOiAnJztcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0aWYgKCBkYXRlX3N0cmluZyA+PSAwICkge1xuXHRcdFx0XHRcdFx0XHRpZiAoIHNoaWZ0LnN0YXR1c19pZCA9PSAyMCApIHtcblxuXHRcdFx0XHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZ10gPSAkdGhpcy5nZXRBYnNlbmNlQ2VsbFZhbHVlKCBzaGlmdCApO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZ10gPSBzaGlmdC5zdGFydF90aW1lICsgJyAtICcgKyBzaGlmdC5lbmRfdGltZTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmcgKyAnX2RhdGEnXSA9IHNoaWZ0O1xuXG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdGlmICggIXB1c2hfdG9fbGFzdCApIHtcblx0XHRcdFx0XHRcdFx0aW5kZXggPSAkdGhpcy5zY2hlZHVsZV9zb3VyY2UuaW5kZXhPZiggZGF0ZV9yb3cgKTtcblx0XHRcdFx0XHRcdFx0JHRoaXMuc2NoZWR1bGVfc291cmNlLnNwbGljZSggaW5kZXgsIDAsIHJvdyApO1xuXHRcdFx0XHRcdFx0XHRtYXBba2V5XS5wdXNoKCBpbmRleCApO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0JHRoaXMuc2NoZWR1bGVfc291cmNlLnB1c2goIHJvdyApO1xuXHRcdFx0XHRcdFx0XHRtYXBba2V5XS5wdXNoKCAkdGhpcy5zY2hlZHVsZV9zb3VyY2UubGVuZ3RoIC0gMSApO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXHRcdFx0aWYgKCBzb3VyY2VfYXJyYXkubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0YnVpbGRFbXB0eVJvdyggcm93SW5kZXgsIHRydWUgKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRmdW5jdGlvbiBidWlsZEVtcHR5Um93KCBkYXRlX3Jvd19pbmRleCwgYWRkX2xhc3QgKSB7XG5cdFx0XHRpZiAoIGFkZF9sYXN0ICkge1xuXHRcdFx0XHRkYXRlX3Jvd19pbmRleCA9IGRhdGVfcm93X2luZGV4ICsgMTtcblx0XHRcdH1cblx0XHRcdGlmICggZGF0ZV9yb3dfaW5kZXggPT09IC0xICkge1xuXHRcdFx0XHR2YXIgaW5kZXggPSAwO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dmFyIGRhdGVfcm93ID0gJHRoaXMubW9udGhfZGF0ZV9yb3dfYXJyYXlbZGF0ZV9yb3dfaW5kZXhdO1xuXHRcdFx0XHRpZiAoIGFkZF9sYXN0ICkge1xuXHRcdFx0XHRcdGlmICggZGF0ZV9yb3cgKSB7XG5cdFx0XHRcdFx0XHRpbmRleCA9ICR0aGlzLnNjaGVkdWxlX3NvdXJjZS5pbmRleE9mKCBkYXRlX3JvdyApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRpbmRleCA9ICR0aGlzLnNjaGVkdWxlX3NvdXJjZS5sZW5ndGg7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGluZGV4ID0gJHRoaXMuc2NoZWR1bGVfc291cmNlLmluZGV4T2YoIGRhdGVfcm93ICkgKyAxO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHR2YXIgcm93ID0gJHRoaXMuZ2V0RW1wdHlXZWVrbHlSb3coKTtcblx0XHRcdHJvdy50eXBlID0gU2NoZWR1bGVWaWV3Q29udHJvbGxlclJvd1R5cGUuRU1QVFk7XG5cdFx0XHQkdGhpcy5zY2hlZHVsZV9zb3VyY2Uuc3BsaWNlKCBpbmRleCwgMCwgcm93ICk7XG5cdFx0fVxuXG5cdFx0dGhpcy5zaG93RGFpbHlUb3RhbCgpO1xuXHRcdHRoaXMuc2hvd1dlZWtseVRvdGFsKCk7XG5cdH1cblxuXHRidWlsZFllYXJseVNvdXJjZSgpIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciBtYXAgPSB7fTtcblx0XHR0aGlzLnNjaGVkdWxlX3NvdXJjZSA9IFtdO1xuXG5cdFx0dmFyIGxlbiA9IHRoaXMuZmluYWxfc2NoZWR1bGVfZGF0YV9hcnJheS5sZW5ndGg7XG5cblx0XHRpZiAoIGxlbiA8IDEgKSB7XG5cdFx0XHRidWlsZEVtcHR5Um93KCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHR2YXIgc2hpZnQgPSB0aGlzLmZpbmFsX3NjaGVkdWxlX2RhdGFfYXJyYXlbaV07XG5cdFx0XHR2YXIgZGF0ZV9zdHJpbmcgPSAnJztcblx0XHRcdGlmICggc2hpZnQuZGF0ZV9zdGFtcCApIHtcblx0XHRcdFx0dmFyIGRhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCBzaGlmdC5kYXRlX3N0YW1wICk7XG5cdFx0XHRcdGRhdGVfc3RyaW5nID0gZGF0ZS5mb3JtYXQoIHRoaXMuZnVsbF9mb3JtYXQgKTtcblx0XHRcdH1cblxuXHRcdFx0dmFyIGtleSA9IHRoaXMuYnVpbGRTaGlmdEtleSggc2hpZnQgKTtcblxuXHRcdFx0Ly8gZWFjaCByb3cgb2Ygc2NoZWR1bGUgZGF0YSwgc3RhcnQgZnJvbSBmaXJzdCByb3dcblx0XHRcdGlmICggIW1hcFtrZXldICkge1xuXHRcdFx0XHR2YXIgcm93ID0ge307XG5cdFx0XHRcdHJvdy51c2VyX2Z1bGxfbmFtZSA9IHNoaWZ0LnVzZXJfZnVsbF9uYW1lO1xuXHRcdFx0XHRyb3cubGFzdF9uYW1lID0gc2hpZnQubGFzdF9uYW1lO1xuXHRcdFx0XHRyb3cudXNlcl9pZCA9IHNoaWZ0LnVzZXJfaWQ7XG5cdFx0XHRcdHJvdy5icmFuY2hfaWQgPSBzaGlmdC5icmFuY2hfaWQ7XG5cdFx0XHRcdHJvdy5kZXBhcnRtZW50X2lkID0gc2hpZnQuZGVwYXJ0bWVudF9pZDtcblx0XHRcdFx0cm93LnNjaGVkdWxlX3BvbGljeV9pZCA9IHNoaWZ0LnNjaGVkdWxlX3BvbGljeV9pZDtcblx0XHRcdFx0cm93LmpvYl9pZCA9IHNoaWZ0LmpvYl9pZDtcblx0XHRcdFx0cm93LmpvYl9pdGVtX2lkID0gc2hpZnQuam9iX2l0ZW1faWQ7XG5cdFx0XHRcdHJvdy5wdW5jaF90YWdfaWQgPSBzaGlmdC5wdW5jaF90YWdfaWQ7XG5cblx0XHRcdFx0dmFyIGRpc3BsYXlfY29sdW1ucyA9IHRoaXMuc2VsZWN0X2xheW91dC5kYXRhLmRpc3BsYXlfY29sdW1ucztcblx0XHRcdFx0dmFyIGRpc3BsYXlfY29sdW1uc19sZW4gPSBkaXNwbGF5X2NvbHVtbnMubGVuZ3RoO1xuXG5cdFx0XHRcdGZvciAoIHZhciBqID0gMDsgaiA8IGRpc3BsYXlfY29sdW1uc19sZW47IGorKyApIHtcblx0XHRcdFx0XHR2YXIgZmllbGRfbmFtZSA9IGRpc3BsYXlfY29sdW1uc1tqXTtcblx0XHRcdFx0XHRyb3dbZmllbGRfbmFtZV0gPSBzaGlmdFtmaWVsZF9uYW1lXSA/IHNoaWZ0W2ZpZWxkX25hbWVdIDogJyc7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIGRhdGVfc3RyaW5nICkge1xuXHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZ10gPSBzaGlmdC5zdGF0dXNfaWQgPT0gMTAgPyAnUycgOiAnQSc7XG5cdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nICsgJ19kYXRhJ10gPSBzaGlmdDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRoaXMuc2NoZWR1bGVfc291cmNlLnB1c2goIHJvdyApO1xuXHRcdFx0XHRtYXBba2V5XSA9IFt0aGlzLnNjaGVkdWxlX3NvdXJjZS5sZW5ndGggLSAxXTtcblx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0dmFyIGZpbmRfcG9zaXRpb24gPSBmYWxzZTtcblx0XHRcdFx0Zm9yICggdmFyIHggPSAwOyB4IDwgbWFwW2tleV0ubGVuZ3RoOyB4KysgKSB7XG5cdFx0XHRcdFx0dmFyIHJvd19pbmRleCA9IG1hcFtrZXldW3hdO1xuXHRcdFx0XHRcdHJvdyA9IHRoaXMuc2NoZWR1bGVfc291cmNlW3Jvd19pbmRleF07XG5cdFx0XHRcdFx0aWYgKCByb3dbZGF0ZV9zdHJpbmddICkge1xuXHRcdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRcdFx0aWYgKCBkYXRlX3N0cmluZyApIHtcblx0XHRcdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nXSA9IHNoaWZ0LnN0YXR1c19pZCA9PSAxMCA/ICdTJyA6ICdBJztcblx0XHRcdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nICsgJ19kYXRhJ10gPSBzaGlmdDtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0ZmluZF9wb3NpdGlvbiA9IHRydWU7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoICFmaW5kX3Bvc2l0aW9uICkge1xuXHRcdFx0XHRcdHJvdyA9IHt9O1xuXHRcdFx0XHRcdHJvdy51c2VyX2Z1bGxfbmFtZSA9IHNoaWZ0LnVzZXJfZnVsbF9uYW1lO1xuXHRcdFx0XHRcdHJvdy5sYXN0X25hbWUgPSBzaGlmdC5sYXN0X25hbWU7XG5cdFx0XHRcdFx0cm93LnVzZXJfaWQgPSBzaGlmdC51c2VyX2lkO1xuXHRcdFx0XHRcdHJvdy5icmFuY2hfaWQgPSBzaGlmdC5icmFuY2hfaWQ7XG5cdFx0XHRcdFx0cm93LmRlcGFydG1lbnRfaWQgPSBzaGlmdC5kZXBhcnRtZW50X2lkO1xuXHRcdFx0XHRcdHJvdy5zY2hlZHVsZV9wb2xpY3lfaWQgPSBzaGlmdC5zY2hlZHVsZV9wb2xpY3lfaWQ7XG5cdFx0XHRcdFx0cm93LmpvYl9pZCA9IHNoaWZ0LmpvYl9pZDtcblx0XHRcdFx0XHRyb3cuam9iX2l0ZW1faWQgPSBzaGlmdC5qb2JfaXRlbV9pZDtcblx0XHRcdFx0XHRyb3cucHVuY2hfdGFnX2lkID0gc2hpZnQucHVuY2hfdGFnX2lkO1xuXG5cdFx0XHRcdFx0ZGlzcGxheV9jb2x1bW5zID0gdGhpcy5zZWxlY3RfbGF5b3V0LmRhdGEuZGlzcGxheV9jb2x1bW5zO1xuXHRcdFx0XHRcdGRpc3BsYXlfY29sdW1uc19sZW4gPSBkaXNwbGF5X2NvbHVtbnMubGVuZ3RoO1xuXG5cdFx0XHRcdFx0Zm9yICggdmFyIGogPSAwOyBqIDwgZGlzcGxheV9jb2x1bW5zX2xlbjsgaisrICkge1xuXHRcdFx0XHRcdFx0ZmllbGRfbmFtZSA9IGRpc3BsYXlfY29sdW1uc1tqXTtcblx0XHRcdFx0XHRcdHJvd1tmaWVsZF9uYW1lXSA9IHNoaWZ0W2ZpZWxkX25hbWVdID8gc2hpZnRbZmllbGRfbmFtZV0gOiAnJztcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoIGRhdGVfc3RyaW5nICkge1xuXHRcdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nXSA9IHNoaWZ0LnN0YXR1c19pZCA9PSAxMCA/ICdTJyA6ICdBJztcblx0XHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZyArICdfZGF0YSddID0gc2hpZnQ7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0dGhpcy5zY2hlZHVsZV9zb3VyY2UucHVzaCggcm93ICk7XG5cdFx0XHRcdFx0bWFwW2tleV0ucHVzaCggdGhpcy5zY2hlZHVsZV9zb3VyY2UubGVuZ3RoIC0gMSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdH1cblxuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGJ1aWxkRW1wdHlSb3coKSB7XG5cblx0XHRcdHZhciByb3cgPSB7fTtcblx0XHRcdHJvdy51c2VyX2Z1bGxfbmFtZSA9ICcnO1xuXHRcdFx0cm93Lmxhc3RfbmFtZSA9ICcnO1xuXHRcdFx0cm93LnVzZXJfaWQgPSAnJztcblx0XHRcdHJvdy5icmFuY2hfaWQgPSAnJztcblx0XHRcdHJvdy50eXBlID0gU2NoZWR1bGVWaWV3Q29udHJvbGxlclJvd1R5cGUuRU1QVFk7XG5cdFx0XHQkdGhpcy5zY2hlZHVsZV9zb3VyY2UucHVzaCggcm93ICk7XG5cdFx0fVxuXG5cdFx0dGhpcy5zaG93V2Vla2x5VG90YWwoKTtcblx0fVxuXG5cdGJ1aWxkRGFpbHlIZWFkZXJzKCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dmFyIGNvbF9tb2RlbCA9IHRoaXMuc2NoZWR1bGVfY29sdW1ucztcblx0XHR2YXIgbGFiZWxfY29sdW1uID0gY29sX21vZGVsW3RoaXMuc2VsZWN0X2xheW91dC5kYXRhLmRpc3BsYXlfY29sdW1ucy5sZW5ndGggKyAxXTtcblx0XHR2YXIgZmlyc3RfdGltZSA9IC0xO1xuXHRcdHZhciBsYXN0X3RpbWUgPSAtMTtcblx0XHR2YXIgZmlyc3RfZGF0ZV90aW1lID0gJyc7XG5cdFx0dmFyIGxhc3RfZGF0ZV90aW1lID0gJyc7XG5cdFx0dmFyIGZpcnN0X3RpbWVfc3RyID0gJyc7XG5cdFx0dmFyIGxhc3RfdGltZV9zdHIgPSAnJztcblx0XHR2YXIgbGVuID0gdGhpcy5oYXNfZGF0ZV9hcnJheS5sZW5ndGg7XG5cdFx0aWYgKCBsZW4gPT09IDAgKSB7XG5cdFx0XHR2YXIgcmVzID0gdGhpcy5hcGkuZ2V0U2NoZWR1bGVEZWZhdWx0RGF0YSggeyBhc3luYzogZmFsc2UgfSApO1xuXHRcdFx0dmFyIGRhdGEgPSByZXMuZ2V0UmVzdWx0KCk7XG5cdFx0XHR2YXIgc2VsZWN0ZWRfZGF0ZV9zdHIgPSAkdGhpcy5nZXRTZWxlY3REYXRlKCk7XG5cdFx0XHRmaXJzdF9kYXRlX3RpbWUgPSBzZWxlY3RlZF9kYXRlX3N0ciArICcgJyArIGRhdGEuc3RhcnRfdGltZTtcblx0XHRcdGxhc3RfZGF0ZV90aW1lID0gc2VsZWN0ZWRfZGF0ZV9zdHIgKyAnICcgKyBkYXRhLmVuZF90aW1lO1xuXHRcdFx0ZG9OZXh0KCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0dmFyIGl0ZW0gPSB0aGlzLmhhc19kYXRlX2FycmF5W2ldO1xuXG5cdFx0XHRpZiAoIGZpcnN0X3RpbWUgPT09IC0xICkge1xuXHRcdFx0XHRmaXJzdF90aW1lID0gaXRlbS5zdGFydF90aW1lX3N0YW1wO1xuXHRcdFx0XHRmaXJzdF9kYXRlX3RpbWUgPSBpdGVtLnN0YXJ0X2RhdGU7XG5cdFx0XHRcdGZpcnN0X3RpbWVfc3RyID0gaXRlbS5zdGFydF90aW1lO1xuXHRcdFx0fSBlbHNlIGlmICggaXRlbS5zdGFydF90aW1lX3N0YW1wIDwgZmlyc3RfdGltZSApIHtcblx0XHRcdFx0Zmlyc3RfdGltZSA9IGl0ZW0uc3RhcnRfdGltZV9zdGFtcDtcblx0XHRcdFx0Zmlyc3RfZGF0ZV90aW1lID0gaXRlbS5zdGFydF9kYXRlO1xuXHRcdFx0XHRmaXJzdF90aW1lX3N0ciA9IGl0ZW0uc3RhcnRfdGltZTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBsYXN0X3RpbWUgPT09IC0xICkge1xuXHRcdFx0XHRsYXN0X3RpbWUgPSBpdGVtLmVuZF90aW1lX3N0YW1wO1xuXHRcdFx0XHRsYXN0X2RhdGVfdGltZSA9IGl0ZW0uZW5kX2RhdGU7XG5cdFx0XHRcdGxhc3RfdGltZV9zdHIgPSBpdGVtLmVuZF90aW1lO1xuXHRcdFx0fSBlbHNlIGlmICggaXRlbS5lbmRfdGltZV9zdGFtcCA+IGxhc3RfdGltZSApIHtcblx0XHRcdFx0bGFzdF90aW1lID0gaXRlbS5lbmRfdGltZV9zdGFtcDtcblx0XHRcdFx0bGFzdF9kYXRlX3RpbWUgPSBpdGVtLmVuZF9kYXRlO1xuXHRcdFx0XHRsYXN0X3RpbWVfc3RyID0gaXRlbS5lbmRfdGltZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRmaXJzdF9kYXRlX3RpbWUgPSBHbG9iYWwuZ2V0U3RhbmRhcmREYXRlVGltZVN0ciggZmlyc3RfZGF0ZV90aW1lLCBmaXJzdF90aW1lX3N0ciApO1xuXHRcdGxhc3RfZGF0ZV90aW1lID0gR2xvYmFsLmdldFN0YW5kYXJkRGF0ZVRpbWVTdHIoIGxhc3RfZGF0ZV90aW1lLCBsYXN0X3RpbWVfc3RyICk7XG5cblx0XHRkb05leHQoKTtcblxuXHRcdGZ1bmN0aW9uIGRvTmV4dCgpIHtcblx0XHRcdHZhciBjdXJyZW50X2RhdGVfdGltZSA9IG5ldyBEYXRlKCBHbG9iYWwuc3RyVG9EYXRlVGltZSggZmlyc3RfZGF0ZV90aW1lICkuZ2V0VGltZSgpIC0gMzYwMDAwMCApO1xuXHRcdFx0bGFzdF9kYXRlX3RpbWUgPSBHbG9iYWwuc3RyVG9EYXRlVGltZSggbGFzdF9kYXRlX3RpbWUgKTtcblx0XHRcdHZhciBtaW4gPSBjdXJyZW50X2RhdGVfdGltZS5nZXRNaW51dGVzKCkgKiA2MDAwMDtcblx0XHRcdHZhciB0aW1lX3NwYW4gPSAkKCAnPGRpdiBjbGFzcz1cXCdkYXlfaG91cl9zcGFuXFwnPjwvZGl2PicgKTtcblx0XHRcdGlmICggbWluID4gMCApIHtcblx0XHRcdFx0Y3VycmVudF9kYXRlX3RpbWUgPSBuZXcgRGF0ZSggY3VycmVudF9kYXRlX3RpbWUuZ2V0VGltZSgpIC0gbWluICk7XG5cdFx0XHR9XG5cdFx0XHQkdGhpcy5kYXlfbW9kZV9zdGFydF9kYXRlX3RpbWUgPSBjdXJyZW50X2RhdGVfdGltZTtcblx0XHRcdHZhciB0aW1lX29mZnNldCA9ICggbGFzdF9kYXRlX3RpbWUuZ2V0VGltZSgpIC0gY3VycmVudF9kYXRlX3RpbWUuZ2V0VGltZSgpICkgLyAzNjAwMDAwO1xuXHRcdFx0dmFyIGhlYWRlcl9jb250YWluZXIgPSAkKCAnPGRpdiBjbGFzcz1cXCdkYXlfaG91cl9kaXZcXCc+PC9kaXY+JyApO1xuXHRcdFx0dmFyIGRheV9jb2x1bW4gPSAkKCAnPGRpdiBjbGFzcz1cXCdkYXktY29sdW1uXFwnPjwvZGl2PicgKTtcblx0XHRcdHZhciBkYXkgPSAkdGhpcy5zdGFydF9kYXRlLmZvcm1hdCggJHRoaXMud2Vla2x5X2Zvcm1hdCApO1xuXHRcdFx0ZGF5ID0gJHRoaXMuc2V0SG9saWRheUhlYWRlciggZGF5LCB0cnVlICk7XG5cdFx0XHRkYXlfY29sdW1uLnRleHQoIGRheSApO1xuXHRcdFx0dmFyIHRpbWVfY29sdW1ucyA9ICQoICc8ZGl2IHN0eWxlPVwicGFkZGluZzowcHggIWltcG9ydGFudFwiPjwvZGl2PicgKTtcblx0XHRcdHZhciB0aW1lX3N0cmluZyA9ICcnO1xuXG5cdFx0XHQvL3ZhciB0aW1lX2Zvcm1hdF9zdHJpbmcgPSAnaGg6bW0gQSc7XG5cdFx0XHQvLyB2YXIgdGltZV9mb3JtYXRfc3RyaW5nID0gJ2ggQSc7XG5cdFx0XHR2YXIgdGltZV9mb3JtYXRfc3RyaW5nID0gJ2hBJztcblx0XHRcdGZvciAoIHZhciBpID0gMDsgaSA8IHRpbWVfb2Zmc2V0OyBpKysgKSB7XG5cdFx0XHRcdHZhciBjdXJyZW50X2hvdXJfdGV4dCA9IHRpbWVfc3Bhbi5jbG9uZSgpO1xuXHRcdFx0XHRjdXJyZW50X2hvdXJfdGV4dCA9IGN1cnJlbnRfaG91cl90ZXh0LnRleHQoIGN1cnJlbnRfZGF0ZV90aW1lLmZvcm1hdCggdGltZV9mb3JtYXRfc3RyaW5nICkgKTtcblx0XHRcdFx0aWYgKCBpIDwgdGltZV9vZmZzZXQgLSAxICkge1xuXHRcdFx0XHRcdHRpbWVfc3RyaW5nID0gdGltZV9zdHJpbmcgKyBjdXJyZW50X2RhdGVfdGltZS5mb3JtYXQoIHRpbWVfZm9ybWF0X3N0cmluZyApICsgJ3wnO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHRpbWVfc3RyaW5nID0gdGltZV9zdHJpbmcgKyBjdXJyZW50X2RhdGVfdGltZS5mb3JtYXQoIHRpbWVfZm9ybWF0X3N0cmluZyApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRpbWVfY29sdW1ucy5hcHBlbmQoIGN1cnJlbnRfaG91cl90ZXh0ICk7XG5cdFx0XHRcdGN1cnJlbnRfZGF0ZV90aW1lID0gbmV3IERhdGUoIGN1cnJlbnRfZGF0ZV90aW1lLmdldFRpbWUoKSArIDM2MDAwMDAgKTtcblx0XHRcdH1cblx0XHRcdGhlYWRlcl9jb250YWluZXIuYXBwZW5kKCBkYXlfY29sdW1uICk7XG5cdFx0XHRoZWFkZXJfY29udGFpbmVyLmFwcGVuZCggdGltZV9jb2x1bW5zICk7XG5cdFx0XHQkdGhpcy5idWlsZFRvdGFsU2hpZnREaWMoIHRpbWVfc3RyaW5nICk7XG5cdFx0XHRsYWJlbF9jb2x1bW4ubGFiZWwgPSBoZWFkZXJfY29udGFpbmVyWzBdLm91dGVySFRNTDtcblx0XHRcdC8vIEluY2x1ZGUgcGFkZGluZy5cblx0XHRcdGxhYmVsX2NvbHVtbi53aWR0aCA9ICR0aGlzLmRheV9ob3VyX3dpZHRoICogdGltZV9vZmZzZXQgKyA0MDtcblx0XHRcdCR0aGlzLmRheV9oZWFkZXJfd2lkdGggPSBsYWJlbF9jb2x1bW4ud2lkdGg7XG5cblx0XHR9XG5cdH1cblxuXHQvL0J1aWxkIGRpYyB0aGF0IGNvbnRhaW5zIGFsbCBkYWlseSBob3Vyc1xuXHRidWlsZFRvdGFsU2hpZnREaWMoIHRpbWVIZWFkZXIgKSB7XG5cdFx0dmFyIGxhYmVsX2FycmF5ID0gdGltZUhlYWRlci5zcGxpdCggJ3wnICk7XG5cdFx0dGhpcy50b3RhbF9zaGlmdHNfZGljID0ge307XG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGFiZWxfYXJyYXkubGVuZ3RoOyBpKysgKSB7XG5cdFx0XHR2YXIgc2hpZnRfaXRlbSA9IHsgc29ydF9vcmRlcjogaSwga2V5OiBsYWJlbF9hcnJheVtpXSwgdmFsdWU6IDAgfTtcblx0XHRcdHRoaXMudG90YWxfc2hpZnRzX2RpY1tsYWJlbF9hcnJheVtpXV0gPSBzaGlmdF9pdGVtO1xuXHRcdH1cblx0fVxuXG5cdGJ1aWxkRGFpbHlTb3VyY2UoKSB7XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHRoaXMuYnVpbGREYWlseUhlYWRlcnMoKTtcblxuXHRcdHZhciBtYXAgPSB7fTtcblx0XHR0aGlzLnNjaGVkdWxlX3NvdXJjZSA9IFtdO1xuXG5cdFx0dmFyIGxlbiA9IHRoaXMuZmluYWxfc2NoZWR1bGVfZGF0YV9hcnJheS5sZW5ndGg7XG5cblx0XHRpZiAoIGxlbiA8IDEgKSB7XG5cdFx0XHRidWlsZEVtcHR5Um93KCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHR2YXIgc2hpZnQgPSB0aGlzLmZpbmFsX3NjaGVkdWxlX2RhdGFfYXJyYXlbaV07XG5cdFx0XHR2YXIgZGF0ZV9zdHJpbmcgPSAnJztcblx0XHRcdGlmICggc2hpZnQuZGF0ZV9zdGFtcCApIHtcblx0XHRcdFx0dmFyIGRhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCBzaGlmdC5kYXRlX3N0YW1wICk7XG5cdFx0XHRcdGRhdGVfc3RyaW5nID0gZGF0ZS5mb3JtYXQoIHRoaXMuZnVsbF9mb3JtYXQgKTtcblx0XHRcdH1cblxuXHRcdFx0dmFyIGtleSA9IHRoaXMuYnVpbGRTaGlmdEtleSggc2hpZnQgKTtcblxuXHRcdFx0Ly8gZWFjaCByb3cgb2Ygc2NoZWR1bGUgZGF0YSwgc3RhcnQgZnJvbSBmaXJzdCByb3dcblx0XHRcdGlmICggIW1hcFtrZXldICkge1xuXHRcdFx0XHR2YXIgcm93ID0ge307XG5cdFx0XHRcdHJvdy51c2VyX2Z1bGxfbmFtZSA9IHNoaWZ0LnVzZXJfZnVsbF9uYW1lO1xuXHRcdFx0XHRyb3cubGFzdF9uYW1lID0gc2hpZnQubGFzdF9uYW1lO1xuXHRcdFx0XHRyb3cudXNlcl9pZCA9IHNoaWZ0LnVzZXJfaWQ7XG5cdFx0XHRcdHJvdy5icmFuY2hfaWQgPSBzaGlmdC5icmFuY2hfaWQ7XG5cdFx0XHRcdHJvdy5kZXBhcnRtZW50X2lkID0gc2hpZnQuZGVwYXJ0bWVudF9pZDtcblx0XHRcdFx0cm93LnNjaGVkdWxlX3BvbGljeV9pZCA9IHNoaWZ0LnNjaGVkdWxlX3BvbGljeV9pZDtcblx0XHRcdFx0cm93LmpvYl9pZCA9IHNoaWZ0LmpvYl9pZDtcblx0XHRcdFx0cm93LmpvYl9pdGVtX2lkID0gc2hpZnQuam9iX2l0ZW1faWQ7XG5cdFx0XHRcdHJvdy5wdW5jaF90YWdfaWQgPSBzaGlmdC5wdW5jaF90YWdfaWQ7XG5cdFx0XHRcdHJvdy50b3RhbCA9IEdsb2JhbC5nZXRUaW1lVW5pdCggc2hpZnQudG90YWxfdGltZSApO1xuXG5cdFx0XHRcdHZhciBkaXNwbGF5X2NvbHVtbnMgPSB0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5kaXNwbGF5X2NvbHVtbnM7XG5cdFx0XHRcdHZhciBkaXNwbGF5X2NvbHVtbnNfbGVuID0gZGlzcGxheV9jb2x1bW5zLmxlbmd0aDtcblxuXHRcdFx0XHRmb3IgKCB2YXIgaiA9IDA7IGogPCBkaXNwbGF5X2NvbHVtbnNfbGVuOyBqKysgKSB7XG5cdFx0XHRcdFx0dmFyIGZpZWxkX25hbWUgPSBkaXNwbGF5X2NvbHVtbnNbal07XG5cdFx0XHRcdFx0cm93W2ZpZWxkX25hbWVdID0gc2hpZnRbZmllbGRfbmFtZV0gPyBzaGlmdFtmaWVsZF9uYW1lXSA6ICcnO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCBkYXRlX3N0cmluZyApIHtcblx0XHRcdFx0XHRpZiAoIHNoaWZ0LnN0YXR1c19pZCA9PSAyMCApIHtcblxuXHRcdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nXSA9ICR0aGlzLmdldEFic2VuY2VDZWxsVmFsdWUoIHNoaWZ0ICk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZ10gPSBzaGlmdC5zdGFydF90aW1lICsgJyAtICcgKyBzaGlmdC5lbmRfdGltZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nICsgJ19kYXRhJ10gPSBzaGlmdDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRoaXMuc2NoZWR1bGVfc291cmNlLnB1c2goIHJvdyApO1xuXHRcdFx0XHRtYXBba2V5XSA9IFt0aGlzLnNjaGVkdWxlX3NvdXJjZS5sZW5ndGggLSAxXTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8vIGlmIG9uZSByb3cgYWxyZWFkeSBjcmVhdGVkLCBnbyB0byBoZXJlIHRvIGNyZWF0ZSBjZWxscyBpbiB0aGlzIHJvd1xuXG5cdFx0XHRcdHZhciBmaW5kX3Bvc2l0aW9uID0gZmFsc2U7XG5cdFx0XHRcdGZvciAoIHZhciB4ID0gMDsgeCA8IG1hcFtrZXldLmxlbmd0aDsgeCsrICkge1xuXHRcdFx0XHRcdHZhciByb3dfaW5kZXggPSBtYXBba2V5XVt4XTtcblx0XHRcdFx0XHRyb3cgPSB0aGlzLnNjaGVkdWxlX3NvdXJjZVtyb3dfaW5kZXhdO1xuXHRcdFx0XHRcdGlmICggcm93W2RhdGVfc3RyaW5nXSApIHtcblx0XHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0XHRcdGlmICggZGF0ZV9zdHJpbmcgKSB7XG5cdFx0XHRcdFx0XHRcdGlmICggc2hpZnQuc3RhdHVzX2lkID09IDIwICkge1xuXG5cdFx0XHRcdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nXSA9ICR0aGlzLmdldEFic2VuY2VDZWxsVmFsdWUoIHNoaWZ0ICk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nXSA9IHNoaWZ0LnN0YXJ0X3RpbWUgKyAnIC0gJyArIHNoaWZ0LmVuZF90aW1lO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZyArICdfZGF0YSddID0gc2hpZnQ7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdGZpbmRfcG9zaXRpb24gPSB0cnVlO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCAhZmluZF9wb3NpdGlvbiApIHtcblx0XHRcdFx0XHRyb3cgPSB7fTtcblx0XHRcdFx0XHRyb3cudXNlcl9mdWxsX25hbWUgPSBzaGlmdC51c2VyX2Z1bGxfbmFtZTtcblx0XHRcdFx0XHRyb3cubGFzdF9uYW1lID0gc2hpZnQubGFzdF9uYW1lO1xuXHRcdFx0XHRcdHJvdy51c2VyX2lkID0gc2hpZnQudXNlcl9pZDtcblx0XHRcdFx0XHRyb3cuYnJhbmNoX2lkID0gc2hpZnQuYnJhbmNoX2lkO1xuXHRcdFx0XHRcdHJvdy5kZXBhcnRtZW50X2lkID0gc2hpZnQuZGVwYXJ0bWVudF9pZDtcblx0XHRcdFx0XHRyb3cuc2NoZWR1bGVfcG9saWN5X2lkID0gc2hpZnQuc2NoZWR1bGVfcG9saWN5X2lkO1xuXHRcdFx0XHRcdHJvdy5qb2JfaWQgPSBzaGlmdC5qb2JfaWQ7XG5cdFx0XHRcdFx0cm93LmpvYl9pdGVtX2lkID0gc2hpZnQuam9iX2l0ZW1faWQ7XG5cdFx0XHRcdFx0cm93LnB1bmNoX3RhZ19pZCA9IHNoaWZ0LnB1bmNoX3RhZ19pZDtcblx0XHRcdFx0XHRyb3cudG90YWwgPSBHbG9iYWwuZ2V0VGltZVVuaXQoIHNoaWZ0LnRvdGFsX3RpbWUgKTtcblxuXHRcdFx0XHRcdGRpc3BsYXlfY29sdW1ucyA9IHRoaXMuc2VsZWN0X2xheW91dC5kYXRhLmRpc3BsYXlfY29sdW1ucztcblx0XHRcdFx0XHRkaXNwbGF5X2NvbHVtbnNfbGVuID0gZGlzcGxheV9jb2x1bW5zLmxlbmd0aDtcblxuXHRcdFx0XHRcdGZvciAoIHZhciBqID0gMDsgaiA8IGRpc3BsYXlfY29sdW1uc19sZW47IGorKyApIHtcblx0XHRcdFx0XHRcdHZhciBmaWVsZF9uYW1lID0gZGlzcGxheV9jb2x1bW5zW2pdO1xuXHRcdFx0XHRcdFx0cm93W2ZpZWxkX25hbWVdID0gc2hpZnRbZmllbGRfbmFtZV0gPyBzaGlmdFtmaWVsZF9uYW1lXSA6ICcnO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICggZGF0ZV9zdHJpbmcgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIHNoaWZ0LnN0YXR1c19pZCA9PSAyMCApIHtcblxuXHRcdFx0XHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmddID0gJHRoaXMuZ2V0QWJzZW5jZUNlbGxWYWx1ZSggc2hpZnQgKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZ10gPSBzaGlmdC5zdGFydF90aW1lICsgJyAtICcgKyBzaGlmdC5lbmRfdGltZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZyArICdfZGF0YSddID0gc2hpZnQ7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0dGhpcy5zY2hlZHVsZV9zb3VyY2UucHVzaCggcm93ICk7XG5cdFx0XHRcdFx0bWFwW2tleV0ucHVzaCggdGhpcy5zY2hlZHVsZV9zb3VyY2UubGVuZ3RoIC0gMSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdH1cblxuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGJ1aWxkRW1wdHlSb3coKSB7XG5cblx0XHRcdHZhciByb3cgPSAkdGhpcy5nZXRFbXB0eVdlZWtseVJvdygpO1xuXHRcdFx0cm93LnR5cGUgPSBTY2hlZHVsZVZpZXdDb250cm9sbGVyUm93VHlwZS5FTVBUWTtcblx0XHRcdCR0aGlzLnNjaGVkdWxlX3NvdXJjZS5wdXNoKCByb3cgKTtcblx0XHR9XG5cblx0XHR0aGlzLnNob3dEYWlseVRvdGFsKCk7XG5cdH1cblxuXHRidWlsZFdlZWtseVNvdXJjZSgpIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciBtYXAgPSB7fTtcblx0XHR0aGlzLnNjaGVkdWxlX3NvdXJjZSA9IFtdO1xuXG5cdFx0dmFyIGxlbiA9IHRoaXMuZmluYWxfc2NoZWR1bGVfZGF0YV9hcnJheS5sZW5ndGg7XG5cblx0XHRpZiAoIGxlbiA8IDEgKSB7XG5cdFx0XHRidWlsZEVtcHR5Um93KCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHR2YXIgc2hpZnQgPSB0aGlzLmZpbmFsX3NjaGVkdWxlX2RhdGFfYXJyYXlbaV07XG5cdFx0XHR2YXIgZGF0ZV9zdHJpbmcgPSAnJztcblx0XHRcdGlmICggc2hpZnQuZGF0ZV9zdGFtcCApIHtcblx0XHRcdFx0dmFyIGRhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCBzaGlmdC5kYXRlX3N0YW1wICk7XG5cdFx0XHRcdGRhdGVfc3RyaW5nID0gZGF0ZSA/IGRhdGUuZm9ybWF0KCB0aGlzLmZ1bGxfZm9ybWF0ICkgOiBudWxsO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIga2V5ID0gdGhpcy5idWlsZFNoaWZ0S2V5KCBzaGlmdCApO1xuXG5cdFx0XHQvLyBlYWNoIHJvdyBvZiBzY2hlZHVsZSBkYXRhLCBzdGFydCBmcm9tIGZpcnN0IHJvd1xuXHRcdFx0aWYgKCAhbWFwW2tleV0gKSB7XG5cdFx0XHRcdHZhciByb3cgPSB7fTtcblx0XHRcdFx0cm93LnVzZXJfZnVsbF9uYW1lID0gc2hpZnQudXNlcl9mdWxsX25hbWU7XG5cdFx0XHRcdHJvdy5sYXN0X25hbWUgPSBzaGlmdC5sYXN0X25hbWU7XG5cdFx0XHRcdHJvdy51c2VyX2lkID0gc2hpZnQudXNlcl9pZDtcblx0XHRcdFx0cm93LmJyYW5jaF9pZCA9IHNoaWZ0LmJyYW5jaF9pZDtcblx0XHRcdFx0cm93LmRlcGFydG1lbnRfaWQgPSBzaGlmdC5kZXBhcnRtZW50X2lkO1xuXHRcdFx0XHRyb3cuc2NoZWR1bGVfcG9saWN5X2lkID0gc2hpZnQuc2NoZWR1bGVfcG9saWN5X2lkO1xuXHRcdFx0XHRyb3cuam9iX2lkID0gc2hpZnQuam9iX2lkO1xuXHRcdFx0XHRyb3cuam9iX2l0ZW1faWQgPSBzaGlmdC5qb2JfaXRlbV9pZDtcblx0XHRcdFx0cm93LnB1bmNoX3RhZ19pZCA9IHNoaWZ0LnB1bmNoX3RhZ19pZDtcblxuXHRcdFx0XHR2YXIgZGlzcGxheV9jb2x1bW5zID0gdGhpcy5zZWxlY3RfbGF5b3V0LmRhdGEuZGlzcGxheV9jb2x1bW5zO1xuXHRcdFx0XHR2YXIgZGlzcGxheV9jb2x1bW5zX2xlbiA9IGRpc3BsYXlfY29sdW1ucy5sZW5ndGg7XG5cblx0XHRcdFx0Zm9yICggdmFyIGogPSAwOyBqIDwgZGlzcGxheV9jb2x1bW5zX2xlbjsgaisrICkge1xuXHRcdFx0XHRcdHZhciBmaWVsZF9uYW1lID0gZGlzcGxheV9jb2x1bW5zW2pdO1xuXHRcdFx0XHRcdHJvd1tmaWVsZF9uYW1lXSA9IHNoaWZ0W2ZpZWxkX25hbWVdID8gc2hpZnRbZmllbGRfbmFtZV0gOiAnJztcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggZGF0ZV9zdHJpbmcgKSB7XG5cblx0XHRcdFx0XHRpZiAoIHNoaWZ0LnN0YXR1c19pZCA9PSAyMCApIHtcblxuXHRcdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nXSA9ICR0aGlzLmdldEFic2VuY2VDZWxsVmFsdWUoIHNoaWZ0ICk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZ10gPSBzaGlmdC5zdGFydF90aW1lICsgJyAtICcgKyBzaGlmdC5lbmRfdGltZTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmcgKyAnX2RhdGEnXSA9IHNoaWZ0O1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dGhpcy5zY2hlZHVsZV9zb3VyY2UucHVzaCggcm93ICk7XG5cdFx0XHRcdG1hcFtrZXldID0gW3RoaXMuc2NoZWR1bGVfc291cmNlLmxlbmd0aCAtIDFdO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Ly8gaWYgb25lIHJvdyBhbHJlYWR5IGNyZWF0ZWQsIGdvIHRvIGhlcmUgdG8gY3JlYXRlIGNlbGxzIGluIHRoaXMgcm93XG5cblx0XHRcdFx0dmFyIGZpbmRfcG9zaXRpb24gPSBmYWxzZTtcblx0XHRcdFx0Zm9yICggdmFyIHggPSAwOyB4IDwgbWFwW2tleV0ubGVuZ3RoOyB4KysgKSB7XG5cdFx0XHRcdFx0dmFyIHJvd19pbmRleCA9IG1hcFtrZXldW3hdO1xuXHRcdFx0XHRcdHJvdyA9IHRoaXMuc2NoZWR1bGVfc291cmNlW3Jvd19pbmRleF07XG5cdFx0XHRcdFx0aWYgKCByb3dbZGF0ZV9zdHJpbmddICkge1xuXHRcdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRcdFx0aWYgKCBkYXRlX3N0cmluZyApIHtcblx0XHRcdFx0XHRcdFx0aWYgKCBzaGlmdC5zdGF0dXNfaWQgPT0gMjAgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmddID0gJHRoaXMuZ2V0QWJzZW5jZUNlbGxWYWx1ZSggc2hpZnQgKTtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmddID0gc2hpZnQuc3RhcnRfdGltZSArICcgLSAnICsgc2hpZnQuZW5kX3RpbWU7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0cm93W2RhdGVfc3RyaW5nICsgJ19kYXRhJ10gPSBzaGlmdDtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0ZmluZF9wb3NpdGlvbiA9IHRydWU7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoICFmaW5kX3Bvc2l0aW9uICkge1xuXHRcdFx0XHRcdHJvdyA9IHt9O1xuXHRcdFx0XHRcdHJvdy51c2VyX2Z1bGxfbmFtZSA9IHNoaWZ0LnVzZXJfZnVsbF9uYW1lO1xuXHRcdFx0XHRcdHJvdy5sYXN0X25hbWUgPSBzaGlmdC5sYXN0X25hbWU7XG5cdFx0XHRcdFx0cm93LnVzZXJfaWQgPSBzaGlmdC51c2VyX2lkO1xuXHRcdFx0XHRcdHJvdy5icmFuY2hfaWQgPSBzaGlmdC5icmFuY2hfaWQ7XG5cdFx0XHRcdFx0cm93LmRlcGFydG1lbnRfaWQgPSBzaGlmdC5kZXBhcnRtZW50X2lkO1xuXHRcdFx0XHRcdHJvdy5zY2hlZHVsZV9wb2xpY3lfaWQgPSBzaGlmdC5zY2hlZHVsZV9wb2xpY3lfaWQ7XG5cdFx0XHRcdFx0cm93LmpvYl9pZCA9IHNoaWZ0LmpvYl9pZDtcblx0XHRcdFx0XHRyb3cuam9iX2l0ZW1faWQgPSBzaGlmdC5qb2JfaXRlbV9pZDtcblx0XHRcdFx0XHRyb3cucHVuY2hfdGFnX2lkID0gc2hpZnQucHVuY2hfdGFnX2lkO1xuXG5cdFx0XHRcdFx0ZGlzcGxheV9jb2x1bW5zID0gdGhpcy5zZWxlY3RfbGF5b3V0LmRhdGEuZGlzcGxheV9jb2x1bW5zO1xuXHRcdFx0XHRcdGRpc3BsYXlfY29sdW1uc19sZW4gPSBkaXNwbGF5X2NvbHVtbnMubGVuZ3RoO1xuXG5cdFx0XHRcdFx0Zm9yICggdmFyIGogPSAwOyBqIDwgZGlzcGxheV9jb2x1bW5zX2xlbjsgaisrICkge1xuXHRcdFx0XHRcdFx0ZmllbGRfbmFtZSA9IGRpc3BsYXlfY29sdW1uc1tqXTtcblx0XHRcdFx0XHRcdHJvd1tmaWVsZF9uYW1lXSA9IHNoaWZ0W2ZpZWxkX25hbWVdID8gc2hpZnRbZmllbGRfbmFtZV0gOiAnJztcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoIGRhdGVfc3RyaW5nICkge1xuXG5cdFx0XHRcdFx0XHRpZiAoIHNoaWZ0LnN0YXR1c19pZCA9PSAyMCApIHtcblxuXHRcdFx0XHRcdFx0XHRyb3dbZGF0ZV9zdHJpbmddID0gJHRoaXMuZ2V0QWJzZW5jZUNlbGxWYWx1ZSggc2hpZnQgKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZ10gPSBzaGlmdC5zdGFydF90aW1lICsgJyAtICcgKyBzaGlmdC5lbmRfdGltZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdHJvd1tkYXRlX3N0cmluZyArICdfZGF0YSddID0gc2hpZnQ7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0dGhpcy5zY2hlZHVsZV9zb3VyY2UucHVzaCggcm93ICk7XG5cdFx0XHRcdFx0bWFwW2tleV0ucHVzaCggdGhpcy5zY2hlZHVsZV9zb3VyY2UubGVuZ3RoIC0gMSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdH1cblxuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGJ1aWxkRW1wdHlSb3coKSB7XG5cblx0XHRcdHZhciByb3cgPSAkdGhpcy5nZXRFbXB0eVdlZWtseVJvdygpO1xuXHRcdFx0cm93LnR5cGUgPSBTY2hlZHVsZVZpZXdDb250cm9sbGVyUm93VHlwZS5FTVBUWTtcblx0XHRcdCR0aGlzLnNjaGVkdWxlX3NvdXJjZS5wdXNoKCByb3cgKTtcblx0XHR9XG5cblx0XHR0aGlzLnNob3dEYWlseVRvdGFsKCk7XG5cdFx0dGhpcy5zaG93V2Vla2x5VG90YWwoKTtcblx0fVxuXG5cdGdldEFic2VuY2VDZWxsVmFsdWUoIHNoaWZ0ICkge1xuXG5cdFx0dmFyIHJlc3VsdDtcblx0XHRpZiAoIHNoaWZ0LmFic2VuY2VfcG9saWN5ICkge1xuXHRcdFx0aWYgKCBzaGlmdC5ub3RlICkge1xuXHRcdFx0XHRyZXN1bHQgPSAnKicgKyBzaGlmdC5hYnNlbmNlX3BvbGljeTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHJlc3VsdCA9IHNoaWZ0LmFic2VuY2VfcG9saWN5O1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRpZiAoIHNoaWZ0Lm5vdGUgKSB7XG5cdFx0XHRcdHJlc3VsdCA9ICcqJyArICdOL0EnO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmVzdWx0ID0gJ04vQSc7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHJlc3VsdDtcblx0fVxuXG5cdGJ1aWxkU29ydEZpZWxkcygpIHtcblx0XHR2YXIgc29ydF9ieV9maWVsZHMgPSBbXTtcblxuXHRcdC8vRXJyb3I6IFVuY2F1Z2h0IFR5cGVFcnJvcjogQ2Fubm90IHJlYWQgcHJvcGVydHkgJ2RhdGEnIG9mIG51bGwgaW4gL2ludGVyZmFjZS9odG1sNS8jIW09U2NoZWR1bGUgbGluZSA1MTY5XG5cdFx0aWYgKCB0aGlzLnNlbGVjdF9sYXlvdXQgJiYgdGhpcy5zZWxlY3RfbGF5b3V0LmRhdGEgKSB7XG5cdFx0XHR2YXIgZGlzcGxheV9jb2x1bW5zID0gdGhpcy5zZWxlY3RfbGF5b3V0LmRhdGEuZGlzcGxheV9jb2x1bW5zO1xuXHRcdFx0dmFyIGRpc3BsYXlfY29sdW1uc19sZW4gPSBkaXNwbGF5X2NvbHVtbnMubGVuZ3RoO1xuXHRcdFx0aWYgKCBkaXNwbGF5X2NvbHVtbnNfbGVuID4gMCApIHtcblx0XHRcdFx0c29ydF9ieV9maWVsZHMgPSBkaXNwbGF5X2NvbHVtbnMuc2xpY2UoKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRzb3J0X2J5X2ZpZWxkcy5wdXNoKCAndXNlcl9mdWxsX25hbWUnICk7XG5cblx0XHRzb3J0X2J5X2ZpZWxkcy5wdXNoKCB7IG5hbWU6ICdzdGFydF90aW1lX3N0YW1wJywgcHJpbWVyOiBwYXJzZUZsb2F0LCByZXZlcnNlOiBmYWxzZSB9ICk7XG5cblx0XHRyZXR1cm4gc29ydF9ieV9maWVsZHM7XG5cdH1cblxuXHRidWlsZE1vbnRoV2Vla05vRGF0ZUFycmF5KCBjdXJyZW50X3dlZWtfYXJyYXkgKSB7XG5cdFx0dmFyIGhhc19kYXRlX3VzZXJfbWFwID0ge307XG5cdFx0dmFyIHJlc3VsdCA9IFtdO1xuXG5cdFx0Zm9yICggdmFyIGkgPSAwLCBpaSA9IGN1cnJlbnRfd2Vla19hcnJheS5sZW5ndGg7IGkgPCBpaTsgaSsrICkge1xuXHRcdFx0dmFyIGl0ZW0gPSBHbG9iYWwuY2xvbmUoIGN1cnJlbnRfd2Vla19hcnJheVtpXSApO1xuXHRcdFx0aGFzX2RhdGVfdXNlcl9tYXBbaXRlbS51c2VyX2lkXSA9IHRydWU7XG5cdFx0fVxuXG5cdFx0Zm9yICggdmFyIGtleSBpbiB0aGlzLmFsbF91c2VyX21hcCApIHtcblx0XHRcdGlmICggIWhhc19kYXRlX3VzZXJfbWFwW2tleV0gKSB7XG5cdFx0XHRcdHZhciBpdGVtID0gR2xvYmFsLmNsb25lKCB0aGlzLmFsbF91c2VyX21hcFtrZXldICk7XG5cdFx0XHRcdGl0ZW0uZGF0ZV9zdGFtcCA9IGZhbHNlO1xuXHRcdFx0XHRyZXN1bHQucHVzaCggaXRlbSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cblxuXHRidWlsZE5vRGF0ZUFycmF5KCkge1xuXHRcdHZhciByZWNvcmRzID0gW107XG5cdFx0dmFyIHNvcnRfYXJyYXkgPSBbXTtcblx0XHR2YXIgc29ydF9pdGVtO1xuXHRcdHZhciBzY2hlZHVsZV9kYXRhID0gdGhpcy5mdWxsX3NjaGVkdWxlX2RhdGEuc2NoZWR1bGVfZGF0YTtcblx0XHRmb3IgKCB2YXIgZGF0ZV9rZXkgaW4gc2NoZWR1bGVfZGF0YSApIHtcblx0XHRcdHNvcnRfaXRlbSA9IHt9O1xuXHRcdFx0c29ydF9pdGVtLnZhbHVlID0gc2NoZWR1bGVfZGF0YVtkYXRlX2tleV07XG5cdFx0XHRzb3J0X2l0ZW0uc29ydF9rZXkgPSBkYXRlX2tleTtcblx0XHRcdHNvcnRfYXJyYXkucHVzaCggc29ydF9pdGVtICk7XG5cdFx0fVxuXG5cdFx0dmFyIGxlbiA9IHNvcnRfYXJyYXkubGVuZ3RoO1xuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0dmFyIGRhdGVfaXRlbSA9IHNvcnRfYXJyYXlbaV07XG5cdFx0XHRmb3IgKCB2YXIgaXRlbV9rZXkgaW4gZGF0ZV9pdGVtLnZhbHVlICkge1xuXHRcdFx0XHR2YXIgaXRlbSA9IGRhdGVfaXRlbS52YWx1ZVtpdGVtX2tleV07XG5cdFx0XHRcdGl0ZW0gPSB0aGlzLnJlcGxhY2VGYWxzZVRvRW1wdHlTdHJpbmdGb3JTb3J0RmllbGRzKCBpdGVtICk7XG5cdFx0XHRcdGlmICggIWl0ZW0uZGF0ZV9zdGFtcCApIHtcblx0XHRcdFx0XHRyZWNvcmRzLnB1c2goIGRhdGVfaXRlbS52YWx1ZVtpdGVtX2tleV0gKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cblx0XHR9XG5cdFx0cmV0dXJuIHJlY29yZHM7XG5cdH1cblxuXHRidWlsZEhhc0RhdGVBcnJheSgpIHtcblx0XHR2YXIgcmVjb3JkcyA9IFtdO1xuXHRcdHRoaXMuYWxsX3VzZXJfbWFwID0ge307XG5cdFx0dmFyIHNvcnRfYXJyYXkgPSBbXTtcblx0XHR2YXIgc29ydF9pdGVtO1xuXHRcdHZhciBzY2hlZHVsZV9kYXRhID0gdGhpcy5mdWxsX3NjaGVkdWxlX2RhdGEuc2NoZWR1bGVfZGF0YTtcblxuXHRcdGZvciAoIHZhciBkYXRlX2tleSBpbiBzY2hlZHVsZV9kYXRhICkge1xuXHRcdFx0c29ydF9pdGVtID0ge307XG5cdFx0XHRzb3J0X2l0ZW0udmFsdWUgPSBzY2hlZHVsZV9kYXRhW2RhdGVfa2V5XTtcblx0XHRcdHNvcnRfaXRlbS5zb3J0X2tleSA9IGRhdGVfa2V5O1xuXHRcdFx0c29ydF9hcnJheS5wdXNoKCBzb3J0X2l0ZW0gKTtcblx0XHR9XG5cdFx0dmFyIGxlbiA9IHNvcnRfYXJyYXkubGVuZ3RoO1xuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0dmFyIGRhdGVfaXRlbSA9IHNvcnRfYXJyYXlbaV07XG5cdFx0XHRmb3IgKCB2YXIgaXRlbV9rZXkgaW4gZGF0ZV9pdGVtLnZhbHVlICkge1xuXHRcdFx0XHR2YXIgaXRlbSA9IGRhdGVfaXRlbS52YWx1ZVtpdGVtX2tleV07XG5cdFx0XHRcdGl0ZW0gPSB0aGlzLnJlcGxhY2VGYWxzZVRvRW1wdHlTdHJpbmdGb3JTb3J0RmllbGRzKCBpdGVtICk7XG5cdFx0XHRcdHRoaXMuYWxsX3VzZXJfbWFwW2l0ZW0udXNlcl9pZF0gPSBHbG9iYWwuY2xvbmUoIGl0ZW0gKTtcblx0XHRcdFx0aWYgKCBpdGVtLmRhdGVfc3RhbXAgKSB7XG5cdFx0XHRcdFx0cmVjb3Jkcy5wdXNoKCBkYXRlX2l0ZW0udmFsdWVbaXRlbV9rZXldICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXG5cdFx0fVxuXHRcdHJldHVybiByZWNvcmRzO1xuXHR9XG5cblx0cmVwbGFjZUZhbHNlVG9FbXB0eVN0cmluZ0ZvclNvcnRGaWVsZHMoIGl0ZW0gKSB7XG5cdFx0aWYgKCAhaXRlbS5icmFuY2ggKSB7XG5cdFx0XHRpdGVtLmJyYW5jaCA9ICcnO1xuXHRcdH1cblxuXHRcdGlmICggIWl0ZW0uZGVwYXJ0bWVudCApIHtcblx0XHRcdGl0ZW0uZGVwYXJ0bWVudCA9ICcnO1xuXHRcdH1cblxuXHRcdGlmICggIWl0ZW0uZGVmYXVsdF9icmFuY2ggKSB7XG5cdFx0XHRpdGVtLmRlZmF1bHRfYnJhbmNoID0gJyc7XG5cdFx0fVxuXG5cdFx0aWYgKCAhaXRlbS5kZWZhdWx0X2RlcGFydG1lbnQgKSB7XG5cdFx0XHRpdGVtLmRlZmF1bHRfZGVwYXJ0bWVudCA9ICcnO1xuXHRcdH1cblxuXHRcdGlmICggIWl0ZW0uam9iICkge1xuXHRcdFx0aXRlbS5qb2IgPSAnJztcblx0XHR9XG5cblx0XHRpZiAoICFpdGVtLmpvYl9pdGVtICkge1xuXHRcdFx0aXRlbS5qb2JfaXRlbSA9ICcnO1xuXHRcdH1cblxuXHRcdGlmICggIWl0ZW0udGl0bGUgKSB7XG5cdFx0XHRpdGVtLnRpdGxlID0gJyc7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGl0ZW07XG5cdH1cblxuXHRjaGVja0lzU2VsZWN0ZWRDZWxsKCByb3dfaWQsIGNlbGxfaW5kZXggKSB7XG5cdFx0Zm9yICggdmFyIGkgPSAwLCBtID0gdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXkubGVuZ3RoOyBpIDwgbTsgaSsrICkge1xuXHRcdFx0dmFyIGNlbGwgPSB0aGlzLnNlbGVjdF9jZWxsc19BcnJheVtpXTtcblx0XHRcdGlmICggY2VsbC5yb3dfaWQudG9TdHJpbmcoKSA9PT0gcm93X2lkLnRvU3RyaW5nKCkgJiYgY2VsbC5jZWxsX2luZGV4LnRvU3RyaW5nKCkgPT09IGNlbGxfaW5kZXgudG9TdHJpbmcoKSApIHtcblx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0YnVpbGRTY2hlZHVsZUdyaWQoKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgZ3JpZDtcblx0XHR2YXIgZ3JpZF9pZCA9ICdncmlkJztcblxuXHRcdGlmICggIXRoaXMuZ3JpZCApIHtcblx0XHRcdGdyaWQgPSAkKCB0aGlzLmVsICkuZmluZCggJyNncmlkJyApO1xuXG5cdFx0XHRncmlkLmF0dHIoICdpZCcsIHRoaXMudWlfaWQgKyAnX2dyaWQnICk7ICAvL0dyaWQncyBpZCBpcyBTY3JpcHROYW1lICsgX2dyaWRcblxuXHRcdFx0Z3JpZF9pZCA9IHRoaXMudWlfaWQgKyAnX2dyaWQnO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLmdyaWQuZ3JpZC5qcUdyaWQoICdHcmlkVW5sb2FkJywgdHJ1ZSApO1xuXHRcdFx0ZGVsZXRlIHRoaXMuZ3JpZDtcblx0XHRcdHRoaXMuZ3JpZCA9IG51bGw7XG5cdFx0fVxuXG5cdFx0Z3JpZF9pZCA9IHRoaXMudWlfaWQgKyAnX2dyaWQnO1xuXG5cdFx0aWYgKCAhdGhpcy5zY2hlZHVsZV9jb2x1bW5zIHx8IHRoaXMuc2NoZWR1bGVfY29sdW1ucy5sZW5ndGggPT0gMCApIHtcblx0XHRcdHRoaXMuYnVpbGRTY2hlZHVsZUNvbHVtbnMoKTtcblx0XHR9XG5cblx0XHR0aGlzLmdyaWQgPSBuZXcgVFRHcmlkKCBncmlkX2lkLCB7XG5cdFx0XHRkcmFnZ2JsZTogdHJ1ZSxcblx0XHRcdGFsdFJvd3M6IHRydWUsXG5cdFx0XHRkYXRhOiBbXSxcblx0XHRcdGRhdGF0eXBlOiAnbG9jYWwnLFxuXHRcdFx0c29ydGFibGU6IGZhbHNlLFxuXHRcdFx0c2Nyb2xsT2Zmc2V0OiAwLFxuXHRcdFx0cm93TnVtOiAxMDAwMCxcblx0XHRcdGhvdmVycm93czogZmFsc2UsXG5cdFx0XHRtdWx0aXNlbGVjdFBvc2l0aW9uOiAnbm9uZScsXG5cdFx0XHRvbmRibENsaWNrUm93OiBmdW5jdGlvbigpIHtcblx0XHRcdFx0JHRoaXMub25HcmlkRGJsQ2xpY2tSb3coKTtcblx0XHRcdH0sXG5cdFx0XHRvblNlbGVjdFJvdzogZnVuY3Rpb24oIHJvd19pZCwgZmxhZywgZSApIHtcblx0XHRcdFx0dmFyIHJvd190ciA9ICQoIHRoaXMgKS5maW5kKCAnIycgKyByb3dfaWQgKTtcblx0XHRcdFx0cm93X3RyLnJlbW92ZUNsYXNzKCAndWktc3RhdGUtaGlnaGxpZ2h0JyApLmF0dHIoICdhcmlhLXNlbGVjdGVkJywgdHJ1ZSApO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9LFxuXHRcdFx0b25SaWdodENsaWNrUm93OiBmdW5jdGlvbiggcm93X2lkLCBpUm93LCBjZWxsX2luZGV4LCBlICkge1xuXHRcdFx0XHRpZiAoICEkdGhpcy5jaGVja0lzU2VsZWN0ZWRDZWxsKCByb3dfaWQsIGNlbGxfaW5kZXggKSApIHtcblx0XHRcdFx0XHR2YXIgY2VsbF92YWwgPSAkKCBlLnRhcmdldCApLmNsb3Nlc3QoICd0ZCx0aCcgKS5odG1sKCk7XG5cdFx0XHRcdFx0dmFyIHJvd190ciA9ICQoIHRoaXMgKS5maW5kKCAnIycgKyByb3dfaWQgKTtcblx0XHRcdFx0XHRyb3dfdHIucmVtb3ZlQ2xhc3MoICd1aS1zdGF0ZS1oaWdobGlnaHQnICkuYXR0ciggJ2FyaWEtc2VsZWN0ZWQnLCB0cnVlICk7XG5cdFx0XHRcdFx0JHRoaXMub25DZWxsU2VsZWN0KCAndGltZXNoZWV0X2dyaWQnLCByb3dfaWQsIGNlbGxfaW5kZXgsIGNlbGxfdmFsLCB0aGlzLCBlICk7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRvbkNlbGxTZWxlY3Q6IGZ1bmN0aW9uKCByb3dfaWQsIGNlbGxfaW5kZXgsIGNlbGxfdmFsLCBlICkge1xuXHRcdFx0XHQkdGhpcy5vbkNlbGxTZWxlY3QoICd0aW1lc2hlZXRfZ3JpZCcsIHJvd19pZCwgY2VsbF9pbmRleCwgY2VsbF92YWwsIHRoaXMsIGUgKTtcblx0XHRcdH0sXG5cdFx0XHRjb2xOYW1lczogW10sXG5cdFx0XHQvL2NvbE1vZGVsOiB0aGlzLnNjaGVkdWxlX2NvbHVtbnMsXG5cdFx0XHR2aWV3cmVjb3JkczogdHJ1ZSxcblx0XHRcdHdpbk11bHRpU2VsZWN0OiBmYWxzZSxcblx0XHRcdHNldEdyaWRTaXplOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0JHRoaXMuc2V0R3JpZEhlaWdodCgpO1xuXHRcdFx0fSxcblx0XHRcdG9uUmVzaXplR3JpZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCR0aGlzLm9uUmVzaXplR3JpZCgpOyAvL0JlY2F1c2Ugd2UgaGF2ZSB0aGUgZGFpbHkvd2Vla2x5IHRvdGFscyBhbmQgbW9kZSBidXR0b25zLCB3ZSBuZWVkIGN1c3RvbSBncmlkIGhlaWdodCBsb2dpYy5cblx0XHRcdH1cblx0XHR9LCB0aGlzLnNjaGVkdWxlX2NvbHVtbnMgKTtcblxuXHRcdHRoaXMuZ3JpZC5ncmlkLnBhcmVudCgpLnBhcmVudCgpLnNjcm9sbExlZnQoIDEwMDAgKTtcblxuXHRcdHRoaXMuZ3JpZC5ncmlkLnBhcmVudCgpLnBhcmVudCgpLnNjcm9sbCggZnVuY3Rpb24oIGUgKSB7XG5cdFx0XHQkdGhpcy5zY3JvbGxfcG9zaXRpb24gPSAkKCBlLnRhcmdldCApLnNjcm9sbFRvcCgpO1xuXHRcdH0gKTtcblxuXHRcdHRoaXMuYmluZEdyaWRDb2x1bW5FdmVudHMoKTtcblx0fVxuXG5cdG9uUmVzaXplR3JpZCgpIHtcblx0XHRpZiAoIHRoaXMuZ2V0TW9kZSgpID09IFNjaGVkdWxlVmlld0NvbnRyb2xsZXJNb2RlLkRBWSApIHtcblx0XHRcdC8vUmVidWlsZCB0aGUgc3BlY2lhbCBzaGlmdCBzaXplc1xuXHRcdFx0dGhpcy5idWlsZENhbGVuZGFycygpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnNldEdyaWRDb2x1bW5zV2lkdGgoKTtcblx0XHR9XG5cblx0XHR0aGlzLnNldEdyaWRIZWlnaHQoKTtcblx0fVxuXG5cdC8vQmluZCBjb2x1bW4gY2xpY2sgZXZlbnQgdG8gY2hhbmdlIHNvcnQgdHlwZSBhbmQgc2F2ZSBjb2x1bW5zIHRvIHRfZ3JpZF9oZWFkZXJfYXJyYXkgdG8gdXNlIHRvIHNldCBjb2x1bW4gc3R5bGUgKGFzYyBvciBkZXNjKVxuXHRiaW5kR3JpZENvbHVtbkV2ZW50cygpIHtcblx0XHR2YXIgZGlzcGxheV9jb2x1bW5zID0gdGhpcy5ncmlkLmdldEdyaWRQYXJhbSggJ2NvbE1vZGVsJyApO1xuXG5cdFx0Ly9FeGNlcHRpb24gdGFodCBkaXNwbGF5IGNvbHVtbiBub3QgZXhpc3RlZCwgbm90IHN1cmUgd2hlbiB0aGlzIHdpbGwgaGFwcGVuLCBidXQgbWF5IHRoZXJlIHdpbGwgYmUgYSBzZWNvbmQgdGltZSBsb2FkIGlmIHRoaXMgaGFwcGVuXG5cdFx0aWYgKCAhZGlzcGxheV9jb2x1bW5zICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBsZW4gPSBkaXNwbGF5X2NvbHVtbnMubGVuZ3RoO1xuXG5cdFx0dGhpcy50X2dyaWRfaGVhZGVyX2FycmF5ID0gW107XG5cblx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdHZhciBjb2x1bW5faW5mbyA9IGRpc3BsYXlfY29sdW1uc1tpXTtcblx0XHRcdHZhciBjb2x1bW5faGVhZGVyID0gJCggJCggdGhpcy5lbCApLmZpbmQoICcjZ2JveF8nICsgdGhpcy51aV9pZCArICdfZ3JpZCcgKS5maW5kKCAnZGl2ICNqcWdoXycgKyB0aGlzLnVpX2lkICsgJ19ncmlkXycgKyBjb2x1bW5faW5mby5uYW1lICkgKTtcblxuXHRcdFx0dGhpcy50X2dyaWRfaGVhZGVyX2FycmF5LnB1c2goIGNvbHVtbl9oZWFkZXIuVEdyaWRIZWFkZXIoKSApO1xuXHRcdFx0Y29sdW1uX2hlYWRlci5iaW5kKCAnY2xpY2snLCBvbkNvbHVtbkhlYWRlckNsaWNrICk7XG5cdFx0fVxuXG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdGZ1bmN0aW9uIG9uQ29sdW1uSGVhZGVyQ2xpY2soIGUgKSB7XG5cdFx0XHR2YXIgZmllbGQgPSAkKCB0aGlzICkuYXR0ciggJ2lkJyApO1xuXHRcdFx0ZmllbGQgPSBmaWVsZC5zdWJzdHJpbmcoIDEwICsgJHRoaXMudWlfaWQubGVuZ3RoICsgMSwgZmllbGQubGVuZ3RoICk7XG5cblx0XHRcdGlmICggZmllbGQgPT09ICdjYicgfHwgZmllbGQgPT09ICdwdW5jaF9pbmZvJyApIHsgLy9maXJzdCBjb2x1bW4sIGNoZWNrIGJveCBjb2x1bW4uXG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0dmFyIGRhdGU7XG5cdFx0XHR2YXIgbW9kZSA9ICR0aGlzLmdldE1vZGUoKTtcblxuXHRcdFx0aWYgKCBtb2RlID09PSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5NT05USCApIHtcblx0XHRcdFx0dmFyIGNvbE1vZGVsID0gJHRoaXMuZ3JpZC5nZXRHcmlkUGFyYW0oICdjb2xNb2RlbCcgKTtcblx0XHRcdFx0ZGF0ZSA9ICR0aGlzLmdldENlbGxSZWxhdGVkRGF0ZSggMSwgY29sTW9kZWwsICQoIHRoaXMgKS5wYXJlbnQoKS5pbmRleCgpLCBmaWVsZCApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZGF0ZSA9IEdsb2JhbC5zdHJUb0RhdGUoIGZpZWxkLCAkdGhpcy5mdWxsX2Zvcm1hdCApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGRhdGUgJiYgZGF0ZS5nZXRZZWFyKCkgPiAwICkge1xuXHRcdFx0XHQkdGhpcy5zZXREYXRlUGlja2VyVmFsdWUoIGRhdGUuZm9ybWF0KCBHbG9iYWwuZ2V0TG9naW5Vc2VyRGF0ZUZvcm1hdCgpICkgKTtcblx0XHRcdFx0JHRoaXMuaGlnaExpZ2h0U2VsZWN0RGF5KCk7XG5cdFx0XHR9XG5cblx0XHR9XG5cdH1cblxuXHRidWlsZE1vbnRoQ2VsbCggY2VsbF92YWx1ZSwgcmVsYXRlZF9kYXRhLCByb3csIGlzX2RheV9jb2x1bW4gKSB7XG5cdFx0dmFyIGNvbF9tb2RlbHMgPSB0aGlzLmdyaWQuZ2V0R3JpZFBhcmFtKCAnY29sTW9kZWwnICk7XG5cdFx0dmFyIGNvbF9tb2RlbCA9IHJlbGF0ZWRfZGF0YS5jb2xNb2RlbDtcblx0XHR2YXIgY29udGVudF9kaXYgPSAkKCAnPGRpdiBjbGFzcz1cXCdzY2hlZHVsZS1jb250ZW50LWRpdlxcJz48L2Rpdj4nICk7XG5cdFx0aWYgKCBpc19kYXlfY29sdW1uICkge1xuXHRcdFx0Y29udGVudF9kaXYuYWRkQ2xhc3MoICdkYXRlLWNvbHVtbicgKTtcblx0XHR9XG5cdFx0dmFyIHRpbWVfc3BhbiA9ICQoICc8c3BhbiBjbGFzcz1cXCdzY2hlZHVsZS10aW1lXFwnID48L3NwYW4+JyApO1xuXHRcdHZhciBpdGVtID0gcm93W2NvbF9tb2RlbC5uYW1lICsgJ19kYXRhJ107XG5cdFx0dmFyIGZ1bGxfZGF0ZV9zdHIgPSByb3dbY29sX21vZGVsLm5hbWUgKyAnX2Z1bGxfZGF0ZSddO1xuXG5cdFx0c3dpdGNoICggcm93LnR5cGUgKSB7XG5cdFx0XHRjYXNlIFNjaGVkdWxlVmlld0NvbnRyb2xsZXJSb3dUeXBlLlRPVEFMOlxuXHRcdFx0XHR0aW1lX3NwYW4gPSAkKCAnPHNwYW4gY2xhc3M9XFwnc2NoZWR1bGUtdGltZSB0b3RhbFxcJz48L3NwYW4+JyApO1xuXHRcdFx0XHRpZiAoIHRoaXMuc2VsZWN0X2xheW91dC5kYXRhLmRpc3BsYXlfY29sdW1ucy5pbmRleE9mKCBjb2xfbW9kZWwuaW5kZXggKSA9PT0gLTEgJiYgWyd1c2VyX2Z1bGxfbmFtZScsICdzaGlmdHMnLCAnYWJzZW5jZXMnLCAndG90YWxfdGltZScsICd0b3RhbF90aW1lX3dhZ2UnXS5pbmRleE9mKCBjb2xfbW9kZWwuaW5kZXggKSA9PT0gLTEgKSB7XG5cdFx0XHRcdFx0aWYgKCAhY2VsbF92YWx1ZSApIHtcblx0XHRcdFx0XHRcdHZhciBjZWxsX3ZhbHVlID0geyBzaGlmdHM6IDAsIGFic2VuY2VzOiAwLCB0b3RhbF90aW1lOiAwLCB0b3RhbF90aW1lX3dhZ2U6IDAgfTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR2YXIgdG90YWxfc3BhbiA9ICQoICc8c3BhbiBjbGFzcz1cXCdzY2hlZHVsZS10aW1lIHRvdGFsXFwnPjwvc3Bhbj4nICk7XG5cdFx0XHRcdFx0dmFyIGN1cnJlbmN5ID0gTG9jYWxDYWNoZURhdGEuZ2V0Q3VycmVudEN1cnJlbmN5U3ltYm9sKCk7XG5cdFx0XHRcdFx0dGltZV9zcGFuLnRleHQoICdTOiAnICsgY2VsbF92YWx1ZS5zaGlmdHMgKyAnIEE6ICcgKyBjZWxsX3ZhbHVlLmFic2VuY2VzICk7XG5cdFx0XHRcdFx0dG90YWxfc3Bhbi50ZXh0KCBHbG9iYWwuZ2V0VGltZVVuaXQoIGNlbGxfdmFsdWUudG90YWxfdGltZSApICsgJyA9ICcgKyBjdXJyZW5jeSArIEdsb2JhbC5Nb25leVJvdW5kKCBjZWxsX3ZhbHVlLnRvdGFsX3RpbWVfd2FnZSApICk7XG5cblx0XHRcdFx0XHRjb250ZW50X2Rpdi5wcmVwZW5kKCB0b3RhbF9zcGFuICk7XG5cdFx0XHRcdFx0Y29udGVudF9kaXYucHJlcGVuZCggdGltZV9zcGFuICk7XG5cdFx0XHRcdFx0Y29udGVudF9kaXYuY3NzKCAnaGVpZ2h0JywgJ2F1dG8nICk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0dGltZV9zcGFuLnRleHQoIGNlbGxfdmFsdWUgKTtcblx0XHRcdFx0XHRjb250ZW50X2Rpdi5wcmVwZW5kKCB0aW1lX3NwYW4gKTtcblxuXHRcdFx0XHRcdGlmICggcmVsYXRlZF9kYXRhLnBvcyA9PT0gY29sX21vZGVscy5sZW5ndGggLSAxICkge1xuXHRcdFx0XHRcdFx0Y29udGVudF9kaXYuY3NzKCAncGFkZGluZy1yaWdodCcsICcxNXB4JyApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgU2NoZWR1bGVWaWV3Q29udHJvbGxlclJvd1R5cGUuREFURTpcblx0XHRcdFx0dGltZV9zcGFuLmFkZENsYXNzKCAnZGF0ZScgKTtcblx0XHRcdFx0Y29udGVudF9kaXYuYWRkQ2xhc3MoICdtb250aC1kYXRlLWNlbGwnICk7XG5cdFx0XHRcdGlmICggY2VsbF92YWx1ZSApIHtcblxuXHRcdFx0XHRcdHRpbWVfc3Bhbi5odG1sKCBjZWxsX3ZhbHVlICk7XG5cblx0XHRcdFx0XHRjb250ZW50X2Rpdi5hdHRyKCAnaWQnLCB0aGlzLnVpX2lkICsgJ19ncmlkXycgKyBmdWxsX2RhdGVfc3RyICk7XG5cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0aW1lX3NwYW4uYWRkQ2xhc3MoICdlbXB0eS1kYXRlJyApO1xuXHRcdFx0XHRcdHRpbWVfc3Bhbi50ZXh0KCAnLicgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGNvbnRlbnRfZGl2LnByZXBlbmQoIHRpbWVfc3BhbiApO1xuXG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBTY2hlZHVsZVZpZXdDb250cm9sbGVyUm93VHlwZS5FTVBUWTpcblxuXHRcdFx0XHRpZiAoICFHbG9iYWwuaXNTZXQoIGNlbGxfdmFsdWUgKSApIHtcblx0XHRcdFx0XHR0aW1lX3NwYW4udGV4dCggJycgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRpbWVfc3Bhbi5hZGRDbGFzcyggJ2VtcHR5JyApO1xuXG5cdFx0XHRcdGNvbnRlbnRfZGl2LnByZXBlbmQoIHRpbWVfc3BhbiApO1xuXG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoIGl0ZW0gKSApIHtcblxuXHRcdFx0XHRcdGlmICggIUdsb2JhbC5pc1NldCggaXRlbS5pZCApIHx8ICFpdGVtLmlkIHx8ICggaXRlbS5pZCAmJiBpdGVtLmlkID09IFRUVVVJRC56ZXJvX2lkICkgKSB7XG5cdFx0XHRcdFx0XHR0aW1lX3NwYW4uYWRkQ2xhc3MoICduby1pZCcgKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoIGl0ZW0uc3RhdHVzX2lkID09IDIwICkge1xuXHRcdFx0XHRcdFx0dGltZV9zcGFuLmFkZENsYXNzKCAncmVkJyApO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICggaXRlbS51c2VyX2lkID09PSBUVFVVSUQuemVyb19pZCApIHtcblx0XHRcdFx0XHRcdGNvbnRlbnRfZGl2LmFkZENsYXNzKCAneWVsbG93LW91dGxpbmUnICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggY2VsbF92YWx1ZSApICkge1xuXHRcdFx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCBpdGVtICkgJiYgaXRlbS5ub3RlICYmIGNlbGxfdmFsdWUuaW5kZXhPZiggJyonICkgPT0gLTEgKSB7XG5cdFx0XHRcdFx0XHRjZWxsX3ZhbHVlID0gJyonICsgY2VsbF92YWx1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0dGltZV9zcGFuLnRleHQoIGNlbGxfdmFsdWUgKTtcblxuXHRcdFx0XHRcdGlmICggcmVsYXRlZF9kYXRhLnBvcyA9PT0gY29sX21vZGVscy5sZW5ndGggLSAxICkge1xuXHRcdFx0XHRcdFx0Y29udGVudF9kaXYuY3NzKCAncGFkZGluZy1yaWdodCcsICcxNXB4JyApO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHRpbWVfc3Bhbi50ZXh0KCAnJyApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGNvbnRlbnRfZGl2LnByZXBlbmQoIHRpbWVfc3BhbiApO1xuXHRcdFx0XHRicmVhaztcblx0XHR9XG5cblx0XHRyZXR1cm4gY29udGVudF9kaXYuZ2V0KCAwICkub3V0ZXJIVE1MO1xuXHR9XG5cblx0YnVpbGRZZWFyQ2VsbCggY2VsbF92YWx1ZSwgcmVsYXRlZF9kYXRhLCByb3csIGlzX2RheV9jb2x1bW4gKSB7XG5cdFx0dmFyIGNvbF9tb2RlbHMgPSB0aGlzLmdyaWQuZ2V0R3JpZFBhcmFtKCAnY29sTW9kZWwnICk7XG5cdFx0dmFyIGNvbF9tb2RlbCA9IHJlbGF0ZWRfZGF0YS5jb2xNb2RlbDtcblx0XHR2YXIgY29udGVudF9kaXYgPSAkKCAnPGRpdiBjbGFzcz1cXCdzY2hlZHVsZS1jb250ZW50LWRpdlxcJz48L2Rpdj4nICk7XG5cblx0XHRpZiAoIGNlbGxfdmFsdWUgJiYgY2VsbF92YWx1ZS5sZW5ndGggPT0gMSAmJiByb3cudXNlcl9mdWxsX25hbWUgPT0gJC5pMThuLl8oICdPUEVOJyApICkgeyAvLyMyMzUzIC0gb25seSB3YXkgdG8gbWF0Y2ggb3BlbiBzaGlmdHMuXG5cdFx0XHRjb250ZW50X2Rpdi5hZGRDbGFzcyggJ3llbGxvdy1vdXRsaW5lJyApO1xuXHRcdH1cblxuXHRcdGlmICggaXNfZGF5X2NvbHVtbiApIHtcblx0XHRcdGNvbnRlbnRfZGl2LmFkZENsYXNzKCAnZGF0ZS1jb2x1bW4nICk7XG5cdFx0fVxuXG5cdFx0aWYgKCAhY2VsbF92YWx1ZSApIHtcblx0XHRcdC8vcGVyZm9ybWFuY2UgaGFjayB0byBzcGVlZCB1cCBkb20gYW5kIHJlbmRlcmluZyBvZiB5ZWFyIG1vZGUgc2hlZXRcblx0XHRcdHJldHVybiBjb250ZW50X2Rpdi5nZXQoIDAgKS5vdXRlckhUTUw7XG5cdFx0fVxuXHRcdHZhciB0aW1lX3NwYW4gPSAkKCAnPHNwYW4gY2xhc3M9XFwnc2NoZWR1bGUtdGltZVxcJz48L3NwYW4+JyApO1xuXHRcdHZhciBpdGVtID0gcm93W2NvbF9tb2RlbC5uYW1lICsgJ19kYXRhJ107XG5cblx0XHRzd2l0Y2ggKCByb3cudHlwZSApIHtcblx0XHRcdGNhc2UgU2NoZWR1bGVWaWV3Q29udHJvbGxlclJvd1R5cGUuRU1QVFk6XG5cdFx0XHRcdC8vIGlmICggIUdsb2JhbC5pc1NldCggY2VsbF92YWx1ZSApICkge1xuXHRcdFx0XHQvLyBcdHRpbWVfc3Bhbi50ZXh0KCAkLmkxOG4uXyggJ1pFJyApICk7XG5cdFx0XHRcdC8vIH1cblxuXHRcdFx0XHR0aW1lX3NwYW4uYWRkQ2xhc3MoICdlbXB0eScgKTtcblxuXHRcdFx0XHRjb250ZW50X2Rpdi5wcmVwZW5kKCB0aW1lX3NwYW4gKTtcblxuXHRcdFx0XHRicmVhaztcblx0XHRcdGRlZmF1bHQ6XG5cblx0XHRcdFx0aWYgKCBjb2xfbW9kZWwuaW5kZXggPj0gMCApIHtcblxuXHRcdFx0XHRcdGlmICggY2VsbF92YWx1ZSA9PT0gJ0EnICkge1xuXHRcdFx0XHRcdFx0dGltZV9zcGFuLmFkZENsYXNzKCAnYWJzZW5jZS1jZWxsJyApO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoIGl0ZW0gJiYgKCAhaXRlbS5pZCB8fCAoIGl0ZW0uaWQgJiYgaXRlbS5pZCA9PSBUVFVVSUQuemVyb19pZCApICkgKSB7XG5cdFx0XHRcdFx0XHR0aW1lX3NwYW4uYWRkQ2xhc3MoICduby1pZCcgKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCBjZWxsX3ZhbHVlICkgKSB7XG5cdFx0XHRcdFx0dGltZV9zcGFuLnRleHQoIGNlbGxfdmFsdWUgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0aW1lX3NwYW4udGV4dCggJycgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIGlmICggcmVsYXRlZF9kYXRhLnBvcyA9PT0gY29sX21vZGVscy5sZW5ndGggLSAxICkge1xuXHRcdFx0XHQvLyBcdGNvbnRlbnRfZGl2LmNzcyggJ3BhZGRpbmctcmlnaHQnLCAnMTVweCcgKTtcblx0XHRcdFx0Ly8gfVxuXG5cdFx0XHRcdC8vXG5cdFx0XHRcdC8vIGlmICggaXRlbSAmJiByb3cuZnVsbF91c2VyX25hbWUgPT0gJC5pMThuLl8oJ09QRU4nKSApIHtcblx0XHRcdFx0Ly8gXHRjb250ZW50X2Rpdi5yZW1vdmVDbGFzcygnZGF0ZS1jb2x1bW4nKVxuXHRcdFx0XHQvLyBcdGNvbnRlbnRfZGl2LmFkZENsYXNzKCAneWVsbG93LW91dGxpbmUnICk7XG5cdFx0XHRcdC8vIH1cblxuXHRcdFx0XHRjb250ZW50X2Rpdi5wcmVwZW5kKCB0aW1lX3NwYW4gKTtcblx0XHRcdFx0YnJlYWs7XG5cblx0XHR9XG5cblx0XHRyZXR1cm4gY29udGVudF9kaXZbMF0ub3V0ZXJIVE1MO1xuXHR9XG5cblx0Y2FsY3VsYXRlU2NoZWR1bGVXaWR0aCgpIHtcblx0XHQvL0NhbGN1bGF0ZSB3aWR0aCBvZiBhbGwgc3RhdGljIGNvbHVtbnMgbGlrZSBlbXBsb3llZSBuYW1lLCBkZXBhcnRtZW50cywgdG90YWwsIGV0Yy4uLiBTbyB3ZSBrbm93IGhvdyBtdWNoIHJvb20gaXMgbGVmdCBmb3IgdGhlIGhvdXJzLlxuXHRcdHZhciBzdGF0aWNfd2lkdGggPSAwO1xuXHRcdGZvciAoIHZhciBpIGluIHRoaXMuc2NoZWR1bGVfY29sdW1ucyApIHtcblx0XHRcdGlmICggIXRoaXMuc2NoZWR1bGVfY29sdW1uc1tpXS5pc19zdGF0aWNfc2l6ZSB8fCB0aGlzLnNjaGVkdWxlX2NvbHVtbnNbaV0ubmFtZSA9PSAndG90YWwnIHx8IHRoaXMuc2NoZWR1bGVfY29sdW1uc1tpXS5uYW1lID09ICdzY3JvbGxiYXJfc3BhY2VyJyApIHtcblx0XHRcdFx0c3RhdGljX3dpZHRoICs9IHRoaXMuc2NoZWR1bGVfY29sdW1uc1tpXS53aWR0aDtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoIEdsb2JhbC5pc1ZlcnRpY2FsU2Nyb2xsQmFyUmVxdWlyZWQoIHRoaXMuZ3JpZF9kaXZbMF0gKSB8fCB0aGlzLmdyaWQuZ2V0R3JpZFBhcmFtKCkuaGVpZ2h0IDwgdGhpcy5ncmlkX2RpdlswXS5vZmZzZXRIZWlnaHQgKSB7XG5cdFx0XHQvL1RoaXMgc3RvcHMgc2hvd2luZyBhIHJlZHVuZGFudCBob3Jpem9udGFsIHNjcm9sbGJhciB0aGF0IG9ubHkgZXhpc3RzIHRvIHNob3cgdGhlIHZlcnRpY2FsIHNjcm9sbGJhci5cblx0XHRcdHN0YXRpY193aWR0aCArPSBHbG9iYWwuZ2V0U2Nyb2xsYmFyV2lkdGgoKTtcblx0XHR9XG5cblx0XHR0aGlzLmRheV9ob3VyX3dpZHRoID0gTWF0aC5mbG9vciggKCAkKCAnLmNvbnRleHQtYm9yZGVyJyApLmlubmVyV2lkdGgoKSAtIHN0YXRpY193aWR0aCApIC8gJCggJy5kYXlfaG91cl9kaXYgLmRheV9ob3VyX3NwYW4nICkubGVuZ3RoICk7XG5cdFx0RGVidWcuVGV4dCggJ0RheSBIb3VyIFdpZHRoOiAnICsgdGhpcy5kYXlfaG91cl93aWR0aCArICcgU3RhdGljIFdpZHRoOiAnICsgc3RhdGljX3dpZHRoLCAnU2NoZWR1bGVWaWV3Q29udHJvbGxlci5qcycsICdTY2hlZHVsZVZpZXdDb250cm9sbGVyJywgJ2NhbGN1bGF0ZVNjaGVkdWxlV2lkdGgnLCAxMCApO1xuXG5cdFx0aWYgKCB0aGlzLmRheV9ob3VyX3dpZHRoIDwgNDAgKSB7XG5cdFx0XHR0aGlzLmRheV9ob3VyX3dpZHRoID0gNDA7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzLmRheV9ob3VyX3dpZHRoO1xuXHR9XG5cblx0YnVpbGREYXlDZWxsKCBjZWxsX3ZhbHVlLCByZWxhdGVkX2RhdGEsIHJvdywgaXNfZGF5X2NvbHVtbiApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciBjb2xfbW9kZWwgPSByZWxhdGVkX2RhdGEuY29sTW9kZWw7XG5cdFx0dmFyIGNvbnRlbnRfZGl2ID0gJCggJzxkaXYgY2xhc3M9XFwnc2NoZWR1bGUtY29udGVudC1kaXZcXCc+PC9kaXY+JyApO1xuXHRcdGlmICggaXNfZGF5X2NvbHVtbiApIHtcblx0XHRcdGNvbnRlbnRfZGl2LmFkZENsYXNzKCAnZGF0ZS1jb2x1bW4nICk7XG5cdFx0fVxuXHRcdHZhciB0aW1lX3NwYW4gPSAkKCAnPHNwYW4gY2xhc3M9XFwnc2NoZWR1bGUtdGltZVxcJz48L3NwYW4+JyApO1xuXHRcdHZhciBpdGVtID0gcm93W2NvbF9tb2RlbC5pbmRleCArICdfZGF0YSddO1xuXG5cdFx0c3dpdGNoICggcm93LnR5cGUgKSB7XG5cdFx0XHRjYXNlIFNjaGVkdWxlVmlld0NvbnRyb2xsZXJSb3dUeXBlLlRPVEFMOlxuXG5cdFx0XHRcdGlmICggY2VsbF92YWx1ZSAmJiBHbG9iYWwuaXNTZXQoIGNlbGxfdmFsdWUudG90YWxfdGltZSApICkge1xuXHRcdFx0XHRcdHZhciB0b3RhbF9kaXYgPSAkKCAnPGRpdiAgc3R5bGU9XFwndGV4dC1hbGlnbjogbGVmdFxcJz48L2Rpdj4nICk7XG5cdFx0XHRcdFx0dmFyIGN1cnJlbmN5ID0gTG9jYWxDYWNoZURhdGEuZ2V0Q3VycmVudEN1cnJlbmN5U3ltYm9sKCk7XG5cdFx0XHRcdFx0dGltZV9zcGFuID0gJCggJzxzcGFuIGNsYXNzPVxcJ3NjaGVkdWxlLXRpbWUgdG90YWxcXCc+PC9zcGFuPicgKTtcblx0XHRcdFx0XHR0aW1lX3NwYW4udGV4dCggJ1M6ICcgKyBjZWxsX3ZhbHVlLnNoaWZ0cyArICcgQTogJyArIGNlbGxfdmFsdWUuYWJzZW5jZXMgKyAnICcgKyBHbG9iYWwuZ2V0VGltZVVuaXQoIGNlbGxfdmFsdWUudG90YWxfdGltZSApICsgJyA9ICcgKyBjdXJyZW5jeSArIGNlbGxfdmFsdWUudG90YWxfdGltZV93YWdlICk7XG5cdFx0XHRcdFx0Y29udGVudF9kaXYucHJlcGVuZCggdGltZV9zcGFuICk7XG5cblx0XHRcdFx0XHRpZiAoIGNlbGxfdmFsdWUudG90YWxfc2hpZnRzX2RpYyApIHtcblx0XHRcdFx0XHRcdHZhciBzaGlmdHNfYXJyYXkgPSBbXTtcblx0XHRcdFx0XHRcdGZvciAoIHZhciBrZXkgaW4gY2VsbF92YWx1ZS50b3RhbF9zaGlmdHNfZGljICkge1xuXHRcdFx0XHRcdFx0XHRzaGlmdHNfYXJyYXkucHVzaCggY2VsbF92YWx1ZS50b3RhbF9zaGlmdHNfZGljW2tleV0gKTtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0c2hpZnRzX2FycmF5ID0gc2hpZnRzX2FycmF5LnNvcnQoIGZ1bmN0aW9uKCBhLCBiICkge1xuXG5cdFx0XHRcdFx0XHRcdHJldHVybiBHbG9iYWwuY29tcGFyZSggYSwgYiwgJ3NvcnRfb3JkZXInICk7XG5cblx0XHRcdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgc2hpZnRzX2FycmF5Lmxlbmd0aDsgaSsrICkge1xuXHRcdFx0XHRcdFx0XHR2YXIgaXRlbSA9IHNoaWZ0c19hcnJheVtpXTtcblx0XHRcdFx0XHRcdFx0dmFyIHNwYW4gPSAkKCAnPHNwYW4gY2xhc3M9XCJkYXlfaG91cl9zcGFuXCI+PC9zcGFuPicgKTtcblx0XHRcdFx0XHRcdFx0c3Bhbi50ZXh0KCBpdGVtLnZhbHVlICk7XG5cdFx0XHRcdFx0XHRcdHNwYW4ud2lkdGgoIHRoaXMuZGF5X2hvdXJfd2lkdGggKTtcblx0XHRcdFx0XHRcdFx0dG90YWxfZGl2LmFwcGVuZCggc3BhbiApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0Y29udGVudF9kaXYucHJlcGVuZCggdG90YWxfZGl2ICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Y29udGVudF9kaXYuY3NzKCAnaGVpZ2h0JywgJ2F1dG8nICk7XG5cblx0XHRcdFx0fSBlbHNlIGlmICggY2VsbF92YWx1ZSApIHtcblx0XHRcdFx0XHR0aW1lX3NwYW4gPSAkKCAnPHNwYW4gY2xhc3M9XFwnc2NoZWR1bGUtdGltZSB0b3RhbFxcJz48L3NwYW4+JyApO1xuXHRcdFx0XHRcdHRpbWVfc3Bhbi50ZXh0KCBjZWxsX3ZhbHVlICk7XG5cdFx0XHRcdFx0Y29udGVudF9kaXYucHJlcGVuZCggdGltZV9zcGFuICk7XG5cdFx0XHRcdH0gZWxzZSBpZiAoIGNvbF9tb2RlbC5kaXNwbGF5X3RvdGFsX2NvbHVtbiA9PSB0cnVlICkge1xuXHRcdFx0XHRcdGN1cnJlbmN5ID0gTG9jYWxDYWNoZURhdGEuZ2V0Q3VycmVudEN1cnJlbmN5U3ltYm9sKCk7XG5cdFx0XHRcdFx0dGltZV9zcGFuID0gJCggJzxzcGFuIGNsYXNzPVxcJ3NjaGVkdWxlLXRpbWUgdG90YWxcXCc+PC9zcGFuPicgKTtcblx0XHRcdFx0XHR0aW1lX3NwYW4udGV4dCggJ1M6IDAgQTogMCAwMDowMCA9ICcgKyBjdXJyZW5jeSArICcwLjAwJyApO1xuXG5cdFx0XHRcdFx0Y29udGVudF9kaXYucHJlcGVuZCggdGltZV9zcGFuICk7XG5cdFx0XHRcdFx0Y29udGVudF9kaXYuY3NzKCAnaGVpZ2h0JywgJ2F1dG8nICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgU2NoZWR1bGVWaWV3Q29udHJvbGxlclJvd1R5cGUuRU1QVFk6XG5cdFx0XHRcdGlmICggIUdsb2JhbC5pc1NldCggY2VsbF92YWx1ZSApICkge1xuXHRcdFx0XHRcdHRpbWVfc3Bhbi50ZXh0KCAnJyApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dGltZV9zcGFuLmFkZENsYXNzKCAnZW1wdHknICk7XG5cblx0XHRcdFx0Y29udGVudF9kaXYucHJlcGVuZCggdGltZV9zcGFuICk7XG5cblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRkZWZhdWx0OlxuXG5cdFx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCBpdGVtICkgKSB7XG5cdFx0XHRcdFx0Y29udGVudF9kaXYucmVtb3ZlQ2xhc3MoICdzY2hlZHVsZS1jb250ZW50LWRpdicgKS5hZGRDbGFzcyggJ3NjaGVkdWxlLWNvbnRlbnQtZGF5LWRpdicgKTtcblxuXHRcdFx0XHRcdGlmICggcmVsYXRlZF9kYXRhLnJvd0lkICUgMiA9PT0gMCApIHtcblx0XHRcdFx0XHRcdHRpbWVfc3Bhbi5yZW1vdmVDbGFzcyggJ3NjaGVkdWxlLXRpbWUnICkuYWRkQ2xhc3MoICdzY2hlZHVsZS1kYXktdGltZSBldmVuJyApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHR0aW1lX3NwYW4ucmVtb3ZlQ2xhc3MoICdzY2hlZHVsZS10aW1lJyApLmFkZENsYXNzKCAnc2NoZWR1bGUtZGF5LXRpbWUnICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0dmFyIHdpZHRoID0gJHRoaXMuZ2V0RGF5U2hpZnRXaWR0aCggaXRlbSApO1xuXHRcdFx0XHRcdHRpbWVfc3Bhbi53aWR0aCggd2lkdGggKTtcblx0XHRcdFx0XHR0aW1lX3NwYW4uY3NzKCAnbGVmdCcsICR0aGlzLmdldERheVNoaWZ0T2Zmc2V0KCBpdGVtICkgKTtcblxuXHRcdFx0XHRcdGlmICggIUdsb2JhbC5pc1NldCggaXRlbS5pZCApIHx8ICFpdGVtLmlkIHx8IGl0ZW0uaWQgPT0gVFRVVUlELnplcm9faWQgKSB7XG5cdFx0XHRcdFx0XHR0aW1lX3NwYW4uYWRkQ2xhc3MoICduby1kYXktaWQnICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKCBpdGVtLnN0YXR1c19pZCA9PSAyMCApIHtcblx0XHRcdFx0XHRcdHRpbWVfc3Bhbi5yZW1vdmVDbGFzcyggJ2V2ZW4nICk7XG5cdFx0XHRcdFx0XHR0aW1lX3NwYW4uYWRkQ2xhc3MoICdyZWQtYmcnICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKCBpdGVtLnVzZXJfaWQgPT09IFRUVVVJRC56ZXJvX2lkICkge1xuXHRcdFx0XHRcdFx0Y29udGVudF9kaXYuYWRkQ2xhc3MoICd5ZWxsb3ctb3V0bGluZScgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggY2VsbF92YWx1ZSApICkge1xuXHRcdFx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCBpdGVtICkgJiYgaXRlbS5ub3RlICYmIGNlbGxfdmFsdWUuaW5kZXhPZiggJyonICkgPT0gLTEgKSB7XG5cdFx0XHRcdFx0XHRjZWxsX3ZhbHVlID0gJyonICsgY2VsbF92YWx1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0dGltZV9zcGFuLnRleHQoIGNlbGxfdmFsdWUgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0aW1lX3NwYW4udGV4dCggJycgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRjb250ZW50X2Rpdi5wcmVwZW5kKCB0aW1lX3NwYW4gKTtcblx0XHRcdFx0YnJlYWs7XG5cblx0XHR9XG5cblx0XHRyZXR1cm4gY29udGVudF9kaXYuZ2V0KCAwICkub3V0ZXJIVE1MO1xuXHR9XG5cblx0Z2V0RGF5U2hpZnRPZmZzZXQoIHNoaWZ0ICkge1xuXG5cdFx0dmFyIHN0YXJ0X2RhdGVfdGltZSA9IEdsb2JhbC5zdHJUb0RhdGVUaW1lKCBHbG9iYWwuZ2V0U3RhbmRhcmREYXRlVGltZVN0ciggc2hpZnQuc3RhcnRfZGF0ZSwgc2hpZnQuc3RhcnRfdGltZSApICk7XG5cdFx0dmFyIG9mZnNldCA9ICggc3RhcnRfZGF0ZV90aW1lLmdldFRpbWUoKSAtIHRoaXMuZGF5X21vZGVfc3RhcnRfZGF0ZV90aW1lLmdldFRpbWUoKSApIC8gMzYwMDAwMDtcblxuXHRcdHJldHVybiAoIG9mZnNldCAqIHRoaXMuZGF5X2hvdXJfd2lkdGggKTtcblx0fVxuXG5cdGdldERheVNoaWZ0V2lkdGgoIHNoaWZ0ICkge1xuXHRcdHZhciBzdGFydF9kYXRlX3RpbWUgPSBHbG9iYWwuc3RyVG9EYXRlVGltZSggR2xvYmFsLmdldFN0YW5kYXJkRGF0ZVRpbWVTdHIoIHNoaWZ0LnN0YXJ0X2RhdGUsIHNoaWZ0LnN0YXJ0X3RpbWUgKSApO1xuXHRcdHZhciBlbmRfZGF0ZV90aW1lID0gR2xvYmFsLnN0clRvRGF0ZVRpbWUoIEdsb2JhbC5nZXRTdGFuZGFyZERhdGVUaW1lU3RyKCBzaGlmdC5lbmRfZGF0ZSwgc2hpZnQuZW5kX3RpbWUgKSApO1xuXHRcdHZhciBvZmZzZXQgPSAoIGVuZF9kYXRlX3RpbWUuZ2V0VGltZSgpIC0gc3RhcnRfZGF0ZV90aW1lLmdldFRpbWUoKSApIC8gMzYwMDAwMDtcblxuXHRcdC8vRGVidWcuVGV4dCggJ1VzaW5nIERheSBIb3VyIFdpZHRoOiAnKyB0aGlzLmRheV9ob3VyX3dpZHRoICwgJ1NjaGVkdWxlVmlld0NvbnRyb2xsZXIuanMnLCAnU2NoZWR1bGVWaWV3Q29udHJvbGxlcicsICdnZXREYXlTaGlmdFdpZHRoJywgMTAgKTtcblx0XHRyZXR1cm4gKCBvZmZzZXQgKiB0aGlzLmRheV9ob3VyX3dpZHRoICk7XG5cdH1cblxuXHRidWlsZFdlZWtDZWxsKCBjZWxsX3ZhbHVlLCByZWxhdGVkX2RhdGEsIHJvdywgaXNfZGF5X2NvbHVtbiApIHtcblx0XHR2YXIgY29sX21vZGVscyA9IHRoaXMuZ3JpZC5nZXRHcmlkUGFyYW0oICdjb2xNb2RlbCcgKTtcblxuXHRcdHZhciBjb2xfbW9kZWwgPSByZWxhdGVkX2RhdGEuY29sTW9kZWw7XG5cdFx0dmFyIGNvbnRlbnRfZGl2ID0gJCggJzxkaXYgY2xhc3M9XFwnc2NoZWR1bGUtY29udGVudC1kaXZcXCc+PC9kaXY+JyApO1xuXHRcdGlmICggaXNfZGF5X2NvbHVtbiApIHtcblx0XHRcdGNvbnRlbnRfZGl2LmFkZENsYXNzKCAnZGF0ZS1jb2x1bW4nICk7XG5cdFx0fVxuXHRcdHZhciB0aW1lX3NwYW4gPSAkKCAnPHNwYW4gY2xhc3M9XFwnc2NoZWR1bGUtdGltZVxcJz48L3NwYW4+JyApO1xuXHRcdHZhciBpdGVtID0gcm93W2NvbF9tb2RlbC5pbmRleCArICdfZGF0YSddO1xuXG5cdFx0c3dpdGNoICggcm93LnR5cGUgKSB7XG5cdFx0XHRjYXNlIFNjaGVkdWxlVmlld0NvbnRyb2xsZXJSb3dUeXBlLlRPVEFMOlxuXHRcdFx0XHR0aW1lX3NwYW4gPSAkKCAnPHNwYW4gY2xhc3M9XFwnc2NoZWR1bGUtdGltZSB0b3RhbFxcJz48L3NwYW4+JyApO1xuXHRcdFx0XHRpZiAoIHRoaXMuc2VsZWN0X2xheW91dC5kYXRhLmRpc3BsYXlfY29sdW1ucy5pbmRleE9mKCBjb2xfbW9kZWwuaW5kZXggKSA9PT0gLTEgJiYgWyd1c2VyX2Z1bGxfbmFtZScsICdzaGlmdHMnLCAnYWJzZW5jZXMnLCAndG90YWxfdGltZScsICd0b3RhbF90aW1lX3dhZ2UnXS5pbmRleE9mKCBjb2xfbW9kZWwuaW5kZXggKSA9PT0gLTEgKSB7XG5cdFx0XHRcdFx0aWYgKCAhY2VsbF92YWx1ZSApIHtcblx0XHRcdFx0XHRcdHZhciBjZWxsX3ZhbHVlID0geyBzaGlmdHM6IDAsIGFic2VuY2VzOiAwLCB0b3RhbF90aW1lOiAwLCB0b3RhbF90aW1lX3dhZ2U6IDAgfTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR2YXIgdG90YWxfc3BhbiA9ICQoICc8c3BhbiBjbGFzcz1cXCdzY2hlZHVsZS10aW1lIHRvdGFsXFwnPjwvc3Bhbj4nICk7XG5cdFx0XHRcdFx0dmFyIGN1cnJlbmN5ID0gTG9jYWxDYWNoZURhdGEuZ2V0Q3VycmVudEN1cnJlbmN5U3ltYm9sKCk7XG5cdFx0XHRcdFx0dGltZV9zcGFuLnRleHQoICdTOiAnICsgY2VsbF92YWx1ZS5zaGlmdHMgKyAnIEE6ICcgKyBjZWxsX3ZhbHVlLmFic2VuY2VzICk7XG5cdFx0XHRcdFx0dG90YWxfc3Bhbi50ZXh0KCBHbG9iYWwuZ2V0VGltZVVuaXQoIGNlbGxfdmFsdWUudG90YWxfdGltZSApICsgJyA9ICcgKyBjdXJyZW5jeSArIEdsb2JhbC5Nb25leVJvdW5kKCBjZWxsX3ZhbHVlLnRvdGFsX3RpbWVfd2FnZSApICk7XG5cblx0XHRcdFx0XHRjb250ZW50X2Rpdi5wcmVwZW5kKCB0b3RhbF9zcGFuICk7XG5cdFx0XHRcdFx0Y29udGVudF9kaXYucHJlcGVuZCggdGltZV9zcGFuICk7XG5cdFx0XHRcdFx0Y29udGVudF9kaXYuY3NzKCAnaGVpZ2h0JywgJ2F1dG8nICk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0dGltZV9zcGFuLnRleHQoIGNlbGxfdmFsdWUgKTtcblx0XHRcdFx0XHRjb250ZW50X2Rpdi5wcmVwZW5kKCB0aW1lX3NwYW4gKTtcblxuXHRcdFx0XHRcdGlmICggcmVsYXRlZF9kYXRhLnBvcyA9PT0gY29sX21vZGVscy5sZW5ndGggLSAxICkge1xuXHRcdFx0XHRcdFx0Y29udGVudF9kaXYuY3NzKCAncGFkZGluZy1yaWdodCcsICcxNXB4JyApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgU2NoZWR1bGVWaWV3Q29udHJvbGxlclJvd1R5cGUuRU1QVFk6XG5cdFx0XHRcdGlmICggIUdsb2JhbC5pc1NldCggY2VsbF92YWx1ZSApICkge1xuXHRcdFx0XHRcdHRpbWVfc3Bhbi50ZXh0KCAnJyApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dGltZV9zcGFuLmFkZENsYXNzKCAnZW1wdHknICk7XG5cblx0XHRcdFx0Y29udGVudF9kaXYucHJlcGVuZCggdGltZV9zcGFuICk7XG5cblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggaXRlbSApICkge1xuXHRcdFx0XHRcdGlmICggIUdsb2JhbC5pc1NldCggaXRlbS5pZCApIHx8ICFpdGVtLmlkIHx8ICggaXRlbS5pZCAmJiBpdGVtLmlkID09IFRUVVVJRC56ZXJvX2lkICkgKSB7XG5cdFx0XHRcdFx0XHR0aW1lX3NwYW4uYWRkQ2xhc3MoICduby1pZCcgKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoIGl0ZW0uc3RhdHVzX2lkID09IDIwICkge1xuXHRcdFx0XHRcdFx0dGltZV9zcGFuLmFkZENsYXNzKCAncmVkJyApO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICggaXRlbS51c2VyX2lkID09PSBUVFVVSUQuemVyb19pZCApIHtcblx0XHRcdFx0XHRcdGNvbnRlbnRfZGl2LmFkZENsYXNzKCAneWVsbG93LW91dGxpbmUnICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggY2VsbF92YWx1ZSApICkge1xuXG5cdFx0XHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoIGl0ZW0gKSAmJiBpdGVtLm5vdGUgJiYgY2VsbF92YWx1ZS5pbmRleE9mKCAnKicgKSA9PSAtMSApIHtcblx0XHRcdFx0XHRcdGNlbGxfdmFsdWUgPSAnKicgKyBjZWxsX3ZhbHVlO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICggcmVsYXRlZF9kYXRhLnBvcyA9PT0gY29sX21vZGVscy5sZW5ndGggLSAxICkge1xuXHRcdFx0XHRcdFx0Y29udGVudF9kaXYuY3NzKCAncGFkZGluZy1yaWdodCcsICcxNXB4JyApO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHRpbWVfc3Bhbi50ZXh0KCBjZWxsX3ZhbHVlICk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0dGltZV9zcGFuLnRleHQoICcnICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRjb250ZW50X2Rpdi5wcmVwZW5kKCB0aW1lX3NwYW4gKTtcblxuXHRcdFx0XHRicmVhaztcblxuXHRcdH1cblxuXHRcdHJldHVybiBjb250ZW50X2Rpdi5nZXQoIDAgKS5vdXRlckhUTUw7XG5cdH1cblxuXHRvbkNlbGxGb3JtYXQoIGNlbGxfdmFsdWUsIHJlbGF0ZWRfZGF0YSwgcm93ICkge1xuXHRcdC8vY2VsbF92YWx1ZSA9IEdsb2JhbC5kZWNvZGVDZWxsVmFsdWUoIGNlbGxfdmFsdWUgKTtcblx0XHQvKipcblx0XHQgKiBGSVhFUyBCVUcgIzE5OTk6IHJlbW92ZWQgYmVjYXVzZSBpdCB3YXMgZG91YmxlLWVuY29kaW5nIHZhbHVlcyBpbiBhbiBhdHRlbXB0IHRvIGF2b2lkIHhzcyBhdHRhY2tzLlxuXHRcdCAqIHRoZSBmb2xsb3dpbmcgZnVuY3Rpb25zIGhhbmRsZSB0aGUgbmVlZGVkIGVuY29kaW5nIHVzaW5nIGEgcHNldWRvIGRpdiBlbGVtZW50IGFuZCAub3V0ZXJIVE1MKClcblx0XHQgKiB3aXRoIHRoaXMgZnVuY3Rpb24gaW4gcGxhY2UsIGh0bWwgZW5jb2RlZCB2YWx1ZXMgY29tZSB0aHJvdWdoIHRvIGpxZ3JpZCBkb3VibGUtZW5jb2RlZCBpbiB0aGUgc2NoZWR1bGUgdmlldy5cblx0XHQgKiovXG5cblx0XHR2YXIgcmV0dmFsID0gJyc7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgaXNfZGF5X2NvbHVtbiA9IHRydWU7XG5cblx0XHRpZiAoIHJlbGF0ZWRfZGF0YS5jb2xNb2RlbC5pbmRleCA9PSAndXNlcl9mdWxsX25hbWUnICkgeyAvL2Fsd2F5cyBwYXJ0IG9mIGdyaWQuXG5cdFx0XHRpc19kYXlfY29sdW1uID0gZmFsc2U7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGZvciAoIHZhciBuIGluIHRoaXMuYWxsX2NvbHVtbnMgKSB7XG5cdFx0XHRcdGlmICggcmVsYXRlZF9kYXRhLmNvbE1vZGVsLmxhYmVsID09IHRoaXMuYWxsX2NvbHVtbnNbbl0ubGFiZWwgKSB7XG5cdFx0XHRcdFx0aXNfZGF5X2NvbHVtbiA9IGZhbHNlO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHN3aXRjaCAoIHRoaXMuZ2V0TW9kZSgpICkge1xuXHRcdFx0Y2FzZSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5XRUVLOlxuXHRcdFx0XHRyZXR1cm4gdGhpcy5idWlsZFdlZWtDZWxsKCBjZWxsX3ZhbHVlLCByZWxhdGVkX2RhdGEsIHJvdywgaXNfZGF5X2NvbHVtbiApO1xuXHRcdFx0Y2FzZSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5NT05USDpcblx0XHRcdFx0cmV0dXJuIHRoaXMuYnVpbGRNb250aENlbGwoIGNlbGxfdmFsdWUsIHJlbGF0ZWRfZGF0YSwgcm93LCBpc19kYXlfY29sdW1uICk7XG5cdFx0XHRjYXNlIFNjaGVkdWxlVmlld0NvbnRyb2xsZXJNb2RlLllFQVI6XG5cdFx0XHRcdHJldHVybiB0aGlzLmJ1aWxkWWVhckNlbGwoIGNlbGxfdmFsdWUsIHJlbGF0ZWRfZGF0YSwgcm93LCBpc19kYXlfY29sdW1uICk7XG5cdFx0XHRjYXNlIFNjaGVkdWxlVmlld0NvbnRyb2xsZXJNb2RlLkRBWTpcblx0XHRcdFx0cmV0dXJuIHRoaXMuYnVpbGREYXlDZWxsKCBjZWxsX3ZhbHVlLCByZWxhdGVkX2RhdGEsIHJvdywgaXNfZGF5X2NvbHVtbiApO1xuXHRcdH1cblxuXHRcdHJldHVybiAnJztcblx0fVxuXG5cdG9uU2VsZWN0Um93KCBncmlkX2lkLCByb3dfaWQsIHRhcmdldCApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciByb3dfdHIgPSAkKCB0YXJnZXQgKS5maW5kKCAnIycgKyByb3dfaWQgKTtcblx0XHRyb3dfdHIucmVtb3ZlQ2xhc3MoICd1aS1zdGF0ZS1oaWdobGlnaHQnICkuYXR0ciggJ2FyaWEtc2VsZWN0ZWQnLCB0cnVlICk7XG5cblx0XHR2YXIgY2VsbHNfYXJyYXkgPSAkdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXk7XG5cdFx0dmFyIGxlbiA9ICR0aGlzLnNlbGVjdF9jZWxsc19BcnJheS5sZW5ndGg7XG5cblx0XHR0aGlzLnNlbGVjdF9hbGxfc2hpZnRzX2FycmF5ID0gW107XG5cdFx0dGhpcy5zZWxlY3Rfc2hpZnRzX2FycmF5ID0gW107XG5cdFx0dGhpcy5zZWxlY3RfcmVjdXJyaW5nX3NoaWZ0c19hcnJheSA9IFtdO1xuXHRcdHRoaXMuc2VsZWN0X2NlbGxsc19hbmRfc2hpZnRzX2FycmF5ID0gW107XG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHR2YXIgaW5mbyA9IGNlbGxzX2FycmF5W2ldO1xuXHRcdFx0cm93X3RyID0gJCggdGFyZ2V0ICkuZmluZCggJyMnICsgaW5mby5yb3dfaWQgKTtcblx0XHRcdHZhciBjZWxsX3RkID0gJCggcm93X3RyLmZpbmQoICd0ZCcgKVtpbmZvLmNlbGxfaW5kZXhdICk7XG5cdFx0XHRjZWxsX3RkLmFkZENsYXNzKCAndWktc3RhdGUtaGlnaGxpZ2h0JyApLmF0dHIoICdhcmlhLXNlbGVjdGVkJywgdHJ1ZSApO1xuXHRcdFx0aW5mby5yb3dfaWQgPSBpbmZvLnJvd19pZCAtIDA7XG5cdFx0XHRpZiAoIGluZm8uc2hpZnQgKSB7XG5cdFx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCBpbmZvLnNoaWZ0LnN0YXJ0X2RhdGUgKSApIHsgLy9kYXRlICsgdGltZSBudW1iZXJcblx0XHRcdFx0XHRpbmZvLnNoaWZ0LnN0YXJ0X2RhdGVfbnVtID0gR2xvYmFsLnN0clRvRGF0ZVRpbWUoIGluZm8uc2hpZnQuc3RhcnRfZGF0ZSApLmdldFRpbWUoKTtcblxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGluZm8uc2hpZnQuc3RhcnRfZGF0ZV9udW0gPSBpbmZvLnRpbWVfc3RhbXBfbnVtOyAvL1VlciB0aW1lX3N0YW1wX251bSBmcm9tIGNlbGwgc2VsZWN0IHNldHRpbmcsIGEgZGF0ZSBudW1iZXJcblx0XHRcdFx0fVxuXHRcdFx0XHRpbmZvLnNoaWZ0LnJvd19pbmRleCA9IGluZm8ucm93X2lkIC0gMTtcblx0XHRcdFx0aW5mby5zaGlmdC5jZWxsX2luZGV4ID0gaW5mby5jZWxsX2luZGV4IC0gMTtcblxuXHRcdFx0XHRpbmZvLnNoaWZ0Lm9yZ2luYWxfcm93X2luZGV4ID0gaW5mby5yb3dfaWQ7XG5cdFx0XHRcdGluZm8uc2hpZnQub3JnaW5hbF9jZWxsX2luZGV4ID0gaW5mby5jZWxsX2luZGV4O1xuXG5cdFx0XHRcdHRoaXMuc2VsZWN0X2FsbF9zaGlmdHNfYXJyYXkucHVzaCggaW5mby5zaGlmdCApO1xuXHRcdFx0XHR0aGlzLnNlbGVjdF9jZWxsbHNfYW5kX3NoaWZ0c19hcnJheS5wdXNoKCBpbmZvICk7XG5cblx0XHRcdFx0aWYgKCBpbmZvLnNoaWZ0LmlkICYmIGluZm8uc2hpZnRfaWQgIT0gVFRVVUlELnplcm9faWQgKSB7XG5cdFx0XHRcdFx0dGhpcy5zZWxlY3Rfc2hpZnRzX2FycmF5LnB1c2goIGluZm8uc2hpZnQgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0aGlzLnNlbGVjdF9yZWN1cnJpbmdfc2hpZnRzX2FycmF5LnB1c2goIGluZm8uc2hpZnQgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRoaXMuc2VsZWN0X2FsbF9zaGlmdHNfYXJyYXkuc29ydCggZnVuY3Rpb24oIGEsIGIgKSB7XG5cdFx0XHRcdFx0aWYgKCBhLmNlbGxfaW5kZXggPCBiLmNlbGxfaW5kZXggKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gLTE7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmICggYS5jZWxsX2luZGV4ID4gYi5jZWxsX2luZGV4ICkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIDE7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKCBhLmNlbGxfaW5kZXggPT09IGIuY2VsbF9pbmRleCApIHtcblx0XHRcdFx0XHRcdGlmICggYS5yb3dfaW5kZXggPCBiLnJvd19pbmRleCApIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIC0xO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0aWYgKCBhLnJvd19pbmRleCA+IGIucm93X2luZGV4ICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gMTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRyZXR1cm4gMDtcblxuXHRcdFx0XHR9ICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLnNlbGVjdF9jZWxsbHNfYW5kX3NoaWZ0c19hcnJheS5wdXNoKCBpbmZvICk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuc2VsZWN0X2NlbGxsc19hbmRfc2hpZnRzX2FycmF5LnNvcnQoIGZ1bmN0aW9uKCBhLCBiICkge1xuXHRcdFx0XHRpZiAoIGEuY2VsbF9pbmRleCA8IGIuY2VsbF9pbmRleCApIHtcblx0XHRcdFx0XHRyZXR1cm4gLTE7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCBhLmNlbGxfaW5kZXggPiBiLmNlbGxfaW5kZXggKSB7XG5cdFx0XHRcdFx0cmV0dXJuIDE7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIGEuY2VsbF9pbmRleCA9PT0gYi5jZWxsX2luZGV4ICkge1xuXHRcdFx0XHRcdGlmICggYS5yb3dfaWQgPCBiLnJvd19pZCApIHtcblx0XHRcdFx0XHRcdHJldHVybiAtMTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0aWYgKCBhLnJvd19pZCA+IGIucm93X2lkICkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIDE7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmV0dXJuIDA7XG5cblx0XHRcdH0gKTtcblxuXHRcdH1cblxuXHRcdHRoaXMuc2V0RGVmYXVsdE1lbnUoKTtcblx0fVxuXG5cdGdldENlbGxSZWxhdGVkRGF0ZSggcm93X2luZGV4LCBjb2xfbW9kZWwsIGNlbGxfaW5kZXgsIGRhdGFfZmllbGQgKSB7XG5cdFx0dmFyIGRhdGU7XG5cdFx0dmFyIGRhdGVfcm93XzFfaW5kZXggPSB0aGlzLnNjaGVkdWxlX3NvdXJjZS5pbmRleE9mKCB0aGlzLm1vbnRoX2RhdGVfcm93X2FycmF5WzBdICk7XG5cdFx0dmFyIGRhdGVfcm93XzJfaW5kZXggPSB0aGlzLnNjaGVkdWxlX3NvdXJjZS5pbmRleE9mKCB0aGlzLm1vbnRoX2RhdGVfcm93X2FycmF5WzFdICk7XG5cdFx0dmFyIGRhdGVfcm93XzNfaW5kZXggPSB0aGlzLnNjaGVkdWxlX3NvdXJjZS5pbmRleE9mKCB0aGlzLm1vbnRoX2RhdGVfcm93X2FycmF5WzJdICk7XG5cdFx0dmFyIGRhdGVfcm93XzRfaW5kZXggPSB0aGlzLnNjaGVkdWxlX3NvdXJjZS5pbmRleE9mKCB0aGlzLm1vbnRoX2RhdGVfcm93X2FycmF5WzNdICk7XG5cblx0XHRpZiAoIHJvd19pbmRleCA8IGRhdGVfcm93XzFfaW5kZXggKSB7XG5cdFx0XHRkYXRlID0gR2xvYmFsLnN0clRvRGF0ZSggY29sX21vZGVsW2NlbGxfaW5kZXhdLmluZGV4LCB0aGlzLmZ1bGxfZm9ybWF0ICk7XG5cdFx0fSBlbHNlIGlmICggcm93X2luZGV4ID49IGRhdGVfcm93XzFfaW5kZXggJiYgcm93X2luZGV4IDwgZGF0ZV9yb3dfMl9pbmRleCApIHtcblx0XHRcdGRhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCB0aGlzLm1vbnRoX2RhdGVfcm93X2FycmF5WzBdW2RhdGFfZmllbGQgKyAnX2Z1bGxfZGF0ZSddLCB0aGlzLmZ1bGxfZm9ybWF0ICk7XG5cdFx0fSBlbHNlIGlmICggcm93X2luZGV4ID49IGRhdGVfcm93XzJfaW5kZXggJiYgcm93X2luZGV4IDwgZGF0ZV9yb3dfM19pbmRleCApIHtcblx0XHRcdGRhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCB0aGlzLm1vbnRoX2RhdGVfcm93X2FycmF5WzFdW2RhdGFfZmllbGQgKyAnX2Z1bGxfZGF0ZSddLCB0aGlzLmZ1bGxfZm9ybWF0ICk7XG5cdFx0fSBlbHNlIGlmICggcm93X2luZGV4ID49IGRhdGVfcm93XzNfaW5kZXggJiYgcm93X2luZGV4IDwgZGF0ZV9yb3dfNF9pbmRleCApIHtcblx0XHRcdGRhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCB0aGlzLm1vbnRoX2RhdGVfcm93X2FycmF5WzJdW2RhdGFfZmllbGQgKyAnX2Z1bGxfZGF0ZSddLCB0aGlzLmZ1bGxfZm9ybWF0ICk7XG5cdFx0fSBlbHNlIGlmICggcm93X2luZGV4ID49IGRhdGVfcm93XzRfaW5kZXggKSB7XG5cdFx0XHRkYXRlID0gR2xvYmFsLnN0clRvRGF0ZSggdGhpcy5tb250aF9kYXRlX3Jvd19hcnJheVszXVtkYXRhX2ZpZWxkICsgJ19mdWxsX2RhdGUnXSwgdGhpcy5mdWxsX2Zvcm1hdCApO1xuXHRcdH1cblxuXHRcdHJldHVybiBkYXRlO1xuXHR9XG5cblx0Z2V0RGF0YUJ5Q2VsbEluZGV4KCByb3dfaW5kZXgsIGNlbGxfaW5kZXggKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgcm93ID0gJHRoaXMuc2NoZWR1bGVfc291cmNlW3Jvd19pbmRleF07XG5cdFx0dmFyIGNvbE1vZGVsID0gJHRoaXMuZ3JpZC5nZXRHcmlkUGFyYW0oICdjb2xNb2RlbCcgKTtcblxuXHRcdC8vRXJyb3I6IFR5cGVFcnJvcjogcm93IGlzIHVuZGVmaW5lZCBpbiAvaW50ZXJmYWNlL2h0bWw1L2ZyYW1ld29yay9qcXVlcnkubWluLmpzP3Y9OC4wLjAtMjAxNDExMTctMTM0MzMwIGxpbmUgMiA+IGV2YWwgbGluZSA1OTUyXG5cdFx0Ly9FcnJvcjogVHlwZUVycm9yOiBjb2xNb2RlbFtjZWxsX2luZGV4XSBpcyB1bmRlZmluZWQgaW4gL2ludGVyZmFjZS9odG1sNS9mcmFtZXdvcmsvanF1ZXJ5Lm1pbi5qcz92PTguMC4wLTIwMTQxMTE3LTEzNDMzMCBsaW5lIDIgPiBldmFsIGxpbmUgNTk1MVxuXHRcdGlmICggIWNvbE1vZGVsIHx8ICFjb2xNb2RlbFtjZWxsX2luZGV4XSB8fCAhcm93ICkge1xuXHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0fVxuXG5cdFx0dmFyIGRhdGFfZmllbGQgPSBjb2xNb2RlbFtjZWxsX2luZGV4XS5uYW1lO1xuXHRcdHZhciBkYXRhID0gcm93W2RhdGFfZmllbGQgKyAnX2RhdGEnXTtcblxuXHRcdHJldHVybiBkYXRhO1xuXHR9XG5cblx0b25DZWxsU2VsZWN0KCBncmlkX2lkLCByb3dfaWQsIGNlbGxfaW5kZXgsIGNlbGxfdmFsLCB0YXJnZXQsIGUgKSB7XG5cdFx0JCggJyNyaWJib25fdmlld19jb250YWluZXIgLmNvbnRleHQtbWVudTp2aXNpYmxlIGEnICkuY2xpY2soKTtcblxuXHRcdGlmICggY2VsbF9pbmRleCA8IDAgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgbGVuID0gMDtcblx0XHR2YXIgcm93O1xuXHRcdHZhciBjb2xNb2RlbDtcblx0XHR2YXIgZGF0YV9maWVsZDtcblx0XHR2YXIgc2hpZnQ7XG5cdFx0dmFyIGNlbGxzX2FycmF5ID0gW107XG5cdFx0dmFyIGRhdGU7XG5cdFx0dmFyIG1vZGUgPSB0aGlzLmdldE1vZGUoKTtcblxuXHRcdGNlbGxzX2FycmF5ID0gJHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5O1xuXG5cdFx0bGVuID0gJHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5Lmxlbmd0aDtcblxuXHRcdHJvdyA9ICR0aGlzLnNjaGVkdWxlX3NvdXJjZVtyb3dfaWQgLSAxXTtcblxuXHRcdHZhciByb3dfaW5kZXggPSAkdGhpcy5zY2hlZHVsZV9zb3VyY2UuaW5kZXhPZiggcm93ICk7XG5cblx0XHRjb2xNb2RlbCA9ICR0aGlzLmdyaWQuZ2V0R3JpZFBhcmFtKCAnY29sTW9kZWwnICk7XG5cblx0XHRkYXRhX2ZpZWxkID0gY29sTW9kZWxbY2VsbF9pbmRleF0ubmFtZTtcblxuXHRcdHNoaWZ0ID0gcm93W2RhdGFfZmllbGQgKyAnX2RhdGEnXTtcblxuXHRcdGlmICggbW9kZSA9PT0gU2NoZWR1bGVWaWV3Q29udHJvbGxlck1vZGUuTU9OVEggKSB7XG5cdFx0XHRkYXRlID0gJHRoaXMuZ2V0Q2VsbFJlbGF0ZWREYXRlKCByb3dfaW5kZXgsIGNvbE1vZGVsLCBjZWxsX2luZGV4LCBkYXRhX2ZpZWxkICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGRhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCBkYXRhX2ZpZWxkLCB0aGlzLmZ1bGxfZm9ybWF0ICk7XG5cdFx0fVxuXG5cdFx0aWYgKCAhZGF0ZSB8fCBkYXRlLmdldFRpbWUoKSA8IC0xICkge1xuXHRcdFx0ZGF0ZSA9IG5ldyBEYXRlKCk7XG5cdFx0fVxuXG5cdFx0Ly9DbGVhbiBhbGwgc2VsZWN0IGNlbGxzIGZpcnN0XG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHR2YXIgaW5mbyA9IGNlbGxzX2FycmF5W2ldO1xuXHRcdFx0dmFyIHJvd190ciA9ICQoIHRhcmdldCApLmZpbmQoICcjJyArIGluZm8ucm93X2lkICk7XG5cdFx0XHR2YXIgY2VsbF90ZCA9ICQoIHJvd190ci5maW5kKCAndGQnIClbaW5mby5jZWxsX2luZGV4XSApO1xuXHRcdFx0Y2VsbF90ZC5yZW1vdmVDbGFzcyggJ3VpLXN0YXRlLWhpZ2hsaWdodCcgKS5hdHRyKCAnYXJpYS1zZWxlY3RlZCcsIGZhbHNlICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBkYXRlICkge1xuXHRcdFx0dmFyIGRhdGVfc3RyID0gZGF0ZS5mb3JtYXQoKTtcblx0XHRcdHZhciB0aW1lX3N0YW1wX251bSA9IEdsb2JhbC5zdHJUb0RhdGUoIGRhdGVfc3RyICkuZ2V0VGltZSgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRkYXRlX3N0ciA9ICcnO1xuXHRcdFx0dGltZV9zdGFtcF9udW0gPSAwO1xuXHRcdH1cblx0XHQvLyBBZGQgbXVsdGlwbGUgc2VsZWN0aW9uIGlmIGNsaWNrIGNlbGwgYW5kIGhvbGQgY3RybCBvciBjb21tYW5kXG5cdFx0aWYgKCBlLmN0cmxLZXkgfHwgZS5tZXRhS2V5ICkge1xuXHRcdFx0dmFyIGZvdW5kID0gZmFsc2U7XG5cdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdFx0aW5mbyA9IGNlbGxzX2FycmF5W2ldO1xuXHRcdFx0XHQvLyByb3cgaWQgc2hvdWxkIGJlIG51bWJlclxuXHRcdFx0XHRpZiAoIHBhcnNlSW50KCByb3dfaWQgKSA9PT0gaW5mby5yb3dfaWQgJiYgY2VsbF9pbmRleCA9PT0gaW5mby5jZWxsX2luZGV4ICkge1xuXHRcdFx0XHRcdGNlbGxzX2FycmF5LnNwbGljZSggaSwgMSApO1xuXHRcdFx0XHRcdGZvdW5kID0gdHJ1ZTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoICFmb3VuZCApIHtcblxuXHRcdFx0XHRjZWxsc19hcnJheS5wdXNoKCB7XG5cdFx0XHRcdFx0cm93X2lkOiByb3dfaWQsXG5cdFx0XHRcdFx0Y2VsbF9pbmRleDogY2VsbF9pbmRleCxcblx0XHRcdFx0XHRjZWxsX3ZhbDogY2VsbF92YWwsXG5cdFx0XHRcdFx0c2hpZnQ6IHNoaWZ0LFxuXHRcdFx0XHRcdGRhdGU6IGRhdGVfc3RyLFxuXHRcdFx0XHRcdHRpbWVfc3RhbXBfbnVtOiB0aW1lX3N0YW1wX251bSxcblx0XHRcdFx0XHR1c2VyX2lkOiByb3cudXNlcl9pZCxcblx0XHRcdFx0XHRicmFuY2hfaWQ6IHJvdy5icmFuY2hfaWQsXG5cdFx0XHRcdFx0ZGVwYXJ0bWVudF9pZDogcm93LmRlcGFydG1lbnRfaWQsXG5cdFx0XHRcdFx0am9iX2lkOiByb3cuam9iX2lkLFxuXHRcdFx0XHRcdGpvYl9pdGVtX2lkOiByb3cuam9iX2l0ZW1faWQsXG5cdFx0XHRcdFx0cHVuY2hfdGFnX2lkOiByb3cucHVuY2hfdGFnX2lkXG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0XHQkdGhpcy5zZWxlY3RfY2VsbHNfQXJyYXkgPSBjZWxsc19hcnJheTtcblxuXHRcdFx0XHR0aGlzLnNlbGVjdF9jZWxsc19BcnJheS5zb3J0KCBmdW5jdGlvbiggYSwgYiApIHtcblxuXHRcdFx0XHRcdHJldHVybiBHbG9iYWwuY29tcGFyZSggYSwgYiwgJ3RpbWVfc3RhbXBfbnVtJyApO1xuXG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0fVxuXHRcdH0gZWxzZSBpZiAoIGUuc2hpZnRLZXkgKSB7XG5cdFx0XHR2YXIgc3RhcnRfcm93X2luZGV4ID0gcm93X2lkO1xuXHRcdFx0dmFyIHN0YXJ0X2NlbGxfaW5kZXggPSBjZWxsX2luZGV4O1xuXG5cdFx0XHR2YXIgZW5kX3Jvd19pbmRleCA9IHJvd19pZDtcblx0XHRcdHZhciBlbmRfY2VsbF9pbmRleCA9IGNlbGxfaW5kZXg7XG5cblx0XHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0XHRpbmZvID0gY2VsbHNfYXJyYXlbaV07XG5cblx0XHRcdFx0aWYgKCBwYXJzZUludCggaW5mby5yb3dfaWQgKSA8IHBhcnNlSW50KCBzdGFydF9yb3dfaW5kZXggKSApIHtcblx0XHRcdFx0XHRzdGFydF9yb3dfaW5kZXggPSBpbmZvLnJvd19pZDtcblx0XHRcdFx0fSBlbHNlIGlmICggcGFyc2VJbnQoIGluZm8ucm93X2lkICkgPiBwYXJzZUludCggZW5kX3Jvd19pbmRleCApICkge1xuXHRcdFx0XHRcdGVuZF9yb3dfaW5kZXggPSBpbmZvLnJvd19pZDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggcGFyc2VJbnQoIGluZm8uY2VsbF9pbmRleCApIDwgcGFyc2VJbnQoIHN0YXJ0X2NlbGxfaW5kZXggKSApIHtcblx0XHRcdFx0XHRzdGFydF9jZWxsX2luZGV4ID0gaW5mby5jZWxsX2luZGV4O1xuXHRcdFx0XHR9IGVsc2UgaWYgKCBwYXJzZUludCggaW5mby5jZWxsX2luZGV4ICkgPiBwYXJzZUludCggZW5kX2NlbGxfaW5kZXggKSApIHtcblx0XHRcdFx0XHRlbmRfY2VsbF9pbmRleCA9IGluZm8uY2VsbF9pbmRleDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvL0lmIHRoZSBjbGljayBpcyBpbnNpZGUgdGhlIGV4aXN0aW5nIHNlbGVjdGlvbiwgdHJ1bmNhdGUgdGhlIGV4aXN0aW5nIHNlbGVjdGlvbiB0byB0aGUgY2xpY2suXG5cdFx0XHQvL0NoZWNrIGluIFRpbWVTaGVldFZpZXdDb250cm9sbGVyLmpzIGZvciByZWxhdGVkIGNoYW5nZVxuXHRcdFx0aWYgKCBjZWxsc19hcnJheVtjZWxsc19hcnJheS5sZW5ndGggLSAxXSAmJiBjZWxsc19hcnJheVswXSAmJiBjZWxsc19hcnJheVtjZWxsc19hcnJheS5sZW5ndGggLSAxXS5jZWxsX2luZGV4ID49IGNlbGxfaW5kZXggJiYgY2VsbHNfYXJyYXlbMF0uY2VsbF9pbmRleCA8PSBjZWxsX2luZGV4ICYmIGNlbGxzX2FycmF5W2NlbGxzX2FycmF5Lmxlbmd0aCAtIDFdLnJvd19pZCA+PSByb3dfaWQgJiYgY2VsbHNfYXJyYXlbMF0ucm93X2lkIDw9IHJvd19pZCApIHtcblx0XHRcdFx0ZW5kX3Jvd19pbmRleCA9IHJvd19pZDtcblx0XHRcdFx0ZW5kX2NlbGxfaW5kZXggPSBjZWxsX2luZGV4O1xuXHRcdFx0fVxuXG5cdFx0XHRzdGFydF9yb3dfaW5kZXggPSBwYXJzZUludCggc3RhcnRfcm93X2luZGV4ICk7XG5cdFx0XHRlbmRfcm93X2luZGV4ID0gcGFyc2VJbnQoIGVuZF9yb3dfaW5kZXggKTtcblx0XHRcdGNlbGxzX2FycmF5ID0gW107XG5cblx0XHRcdGZvciAoIHZhciBpID0gc3RhcnRfcm93X2luZGV4OyBpIDw9IGVuZF9yb3dfaW5kZXg7IGkrKyApIHtcblx0XHRcdFx0dmFyIHJfaW5kZXggPSBpO1xuXHRcdFx0XHRmb3IgKCB2YXIgaiA9IHN0YXJ0X2NlbGxfaW5kZXg7IGogPD0gZW5kX2NlbGxfaW5kZXg7IGorKyApIHtcblx0XHRcdFx0XHR2YXIgY19pbmRleCA9IGo7XG5cblx0XHRcdFx0XHRyb3dfdHIgPSAkKCB0YXJnZXQgKS5maW5kKCAnIycgKyByX2luZGV4ICk7XG5cblx0XHRcdFx0XHRjZWxsX3RkID0gJCggcm93X3RyLmZpbmQoICd0ZCcgKVtjX2luZGV4XSApO1xuXG5cdFx0XHRcdFx0Y2VsbF92YWwgPSBjZWxsX3RkWzBdLm91dGVySFRNTDtcblxuXHRcdFx0XHRcdHJvdyA9ICR0aGlzLnNjaGVkdWxlX3NvdXJjZVtyX2luZGV4IC0gMV07XG5cblx0XHRcdFx0XHRyb3dfaW5kZXggPSAkdGhpcy5zY2hlZHVsZV9zb3VyY2UuaW5kZXhPZiggcm93ICk7XG5cblx0XHRcdFx0XHRjb2xNb2RlbCA9ICR0aGlzLmdyaWQuZ2V0R3JpZFBhcmFtKCAnY29sTW9kZWwnICk7XG5cblx0XHRcdFx0XHRkYXRhX2ZpZWxkID0gY29sTW9kZWxbY19pbmRleF0ubmFtZTtcblxuXHRcdFx0XHRcdHNoaWZ0ID0gcm93W2RhdGFfZmllbGQgKyAnX2RhdGEnXTtcblxuXHRcdFx0XHRcdGlmICggbW9kZSA9PT0gU2NoZWR1bGVWaWV3Q29udHJvbGxlck1vZGUuTU9OVEggKSB7XG5cdFx0XHRcdFx0XHRkYXRlID0gJHRoaXMuZ2V0Q2VsbFJlbGF0ZWREYXRlKCByb3dfaW5kZXgsIGNvbE1vZGVsLCBjX2luZGV4LCBkYXRhX2ZpZWxkICk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGRhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCBkYXRhX2ZpZWxkLCB0aGlzLmZ1bGxfZm9ybWF0ICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKCBkYXRlICYmIGRhdGUuZ2V0VGltZSgpID4gMCApIHtcblx0XHRcdFx0XHRcdGRhdGVfc3RyID0gZGF0ZS5mb3JtYXQoKTtcblx0XHRcdFx0XHRcdHRpbWVfc3RhbXBfbnVtID0gR2xvYmFsLnN0clRvRGF0ZSggZGF0ZV9zdHIgKS5nZXRUaW1lKCk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGRhdGVfc3RyID0gJyc7XG5cdFx0XHRcdFx0XHR0aW1lX3N0YW1wX251bSA9IDA7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Y2VsbHNfYXJyYXkucHVzaCgge1xuXHRcdFx0XHRcdFx0cm93X2lkOiByX2luZGV4LnRvU3RyaW5nKCksXG5cdFx0XHRcdFx0XHRjZWxsX2luZGV4OiBjX2luZGV4LFxuXHRcdFx0XHRcdFx0Y2VsbF92YWw6IGNlbGxfdmFsLFxuXHRcdFx0XHRcdFx0c2hpZnQ6IHNoaWZ0LFxuXHRcdFx0XHRcdFx0ZGF0ZTogZGF0ZV9zdHIsXG5cdFx0XHRcdFx0XHR0aW1lX3N0YW1wX251bTogdGltZV9zdGFtcF9udW0sXG5cdFx0XHRcdFx0XHR1c2VyX2lkOiByb3cudXNlcl9pZCxcblx0XHRcdFx0XHRcdGJyYW5jaF9pZDogcm93LmJyYW5jaF9pZCxcblx0XHRcdFx0XHRcdGRlcGFydG1lbnRfaWQ6IHJvdy5kZXBhcnRtZW50X2lkLFxuXHRcdFx0XHRcdFx0am9iX2lkOiByb3cuam9iX2lkLFxuXHRcdFx0XHRcdFx0am9iX2l0ZW1faWQ6IHJvdy5qb2JfaXRlbV9pZCxcblx0XHRcdFx0XHRcdHB1bmNoX3RhZ19pZDogcm93LnB1bmNoX3RhZ19pZFxuXHRcdFx0XHRcdH0gKTtcblxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdCR0aGlzLnNlbGVjdF9jZWxsc19BcnJheSA9IGNlbGxzX2FycmF5O1xuXG5cdFx0XHR0aGlzLnNlbGVjdF9jZWxsc19BcnJheS5zb3J0KCBmdW5jdGlvbiggYSwgYiApIHtcblxuXHRcdFx0XHRyZXR1cm4gR2xvYmFsLmNvbXBhcmUoIGEsIGIsICd0aW1lX3N0YW1wX251bScgKTtcblxuXHRcdFx0fSApO1xuXG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0Y2VsbHNfYXJyYXkgPSBbXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRyb3dfaWQ6IHJvd19pZCxcblx0XHRcdFx0XHRjZWxsX2luZGV4OiBjZWxsX2luZGV4LFxuXHRcdFx0XHRcdGNlbGxfdmFsOiBjZWxsX3ZhbCxcblx0XHRcdFx0XHRzaGlmdDogc2hpZnQsXG5cdFx0XHRcdFx0ZGF0ZTogZGF0ZV9zdHIsXG5cdFx0XHRcdFx0dGltZV9zdGFtcF9udW06IHRpbWVfc3RhbXBfbnVtLFxuXHRcdFx0XHRcdHVzZXJfaWQ6IHJvdy51c2VyX2lkLFxuXHRcdFx0XHRcdGJyYW5jaF9pZDogcm93LmJyYW5jaF9pZCxcblx0XHRcdFx0XHRkZXBhcnRtZW50X2lkOiByb3cuZGVwYXJ0bWVudF9pZCxcblx0XHRcdFx0XHRqb2JfaWQ6IHJvdy5qb2JfaWQsXG5cdFx0XHRcdFx0am9iX2l0ZW1faWQ6IHJvdy5qb2JfaXRlbV9pZCxcblx0XHRcdFx0XHRwdW5jaF90YWdfaWQ6IHJvdy5wdW5jaF90YWdfaWRcblx0XHRcdFx0fVxuXHRcdFx0XTtcblxuXHRcdFx0JHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5ID0gY2VsbHNfYXJyYXk7XG5cblx0XHRcdGlmICggZGF0ZSAmJiBkYXRlLmdldFllYXIoKSA+IDAgKSB7XG5cdFx0XHRcdHRoaXMuc2V0RGF0ZVBpY2tlclZhbHVlKCBkYXRlLmZvcm1hdCggR2xvYmFsLmdldExvZ2luVXNlckRhdGVGb3JtYXQoKSApICk7XG5cdFx0XHRcdHRoaXMuaGlnaExpZ2h0U2VsZWN0RGF5KCk7XG5cdFx0XHR9XG5cblx0XHR9XG5cblx0XHQkdGhpcy5vblNlbGVjdFJvdyggZ3JpZF9pZCwgcm93X2lkLCB0YXJnZXQgKTtcblxuXHRcdHZhciB0YXJnZXRfcm93X3RyID0gJCggdGFyZ2V0ICkuZmluZCggJyMnICsgcm93X2lkICk7XG5cdFx0dmFyIHRhcmdldF9yb3dfdGQgPSAkKCB0YXJnZXRfcm93X3RyLmZpbmQoICd0ZCcgKVtjZWxsX2luZGV4XSApO1xuXG5cdFx0aWYgKCB0YXJnZXRfcm93X3RkLmF0dHIoICdpbmZvcl9jb2x1bW4nICkgKSB7XG5cdFx0XHR2YXIgdGFyZ2V0X3Jvd19pbmRleCA9IHRhcmdldF9yb3dfdHIuaW5kZXgoKTtcblx0XHRcdHZhciByb3dzcGFuID0gcGFyc2VJbnQoIHRhcmdldF9yb3dfdGQuYXR0ciggJ3Jvd3NwYW4nICkgKTtcblxuXHRcdFx0aWYgKCBpc05hTiggcm93c3BhbiApICkge1xuXHRcdFx0XHRyb3dzcGFuID0gMTtcblx0XHRcdH1cblxuXHRcdFx0dmFyIGxhc3Rfcm93ID0gdGFyZ2V0X3Jvd190ci5wYXJlbnQoKS5jaGlsZHJlbigpLmVxKCAoIHRhcmdldF9yb3dfaW5kZXggKyByb3dzcGFuIC0gMSApICk7XG5cdFx0XHR2YXIgbGFzdF90ZCA9IGxhc3Rfcm93LmNoaWxkcmVuKCkuZXEoICggbGFzdF9yb3cuY2hpbGRyZW4oKS5sZW5ndGggLSAxICkgKTtcblxuXHRcdFx0dmFyIGxhc3Rfcm93X2lkID0gbGFzdF9yb3cuYXR0ciggJ2lkJyApO1xuXHRcdFx0dmFyIGxhc3RfY2VsbF9pZCA9ICggbGFzdF9yb3cuY2hpbGRyZW4oKS5sZW5ndGggLSAxICk7XG5cdFx0XHR2YXIgbGFzdF9jZWxsX3ZhbHVlID0gbGFzdF90ZC5maW5kKCAnLnNjaGVkdWxlLXRpbWUnICkudGV4dCgpO1xuXG5cdFx0XHQkdGhpcy5vbkNlbGxTZWxlY3QoICd0aW1lc2hlZXRfZ3JpZCcsIGxhc3Rfcm93X2lkLFxuXHRcdFx0XHRsYXN0X2NlbGxfaWQsXG5cdFx0XHRcdGxhc3RfY2VsbF92YWx1ZSxcblx0XHRcdFx0dGhpcy5ncmlkLmdyaWQsXG5cdFx0XHRcdHsgc2hpZnRLZXk6IHRydWUgfSApO1xuXG5cdFx0fVxuXHR9XG5cblx0aGlnaExpZ2h0U2VsZWN0RGF5KCkge1xuXG5cdFx0dmFyIG1vZGUgPSB0aGlzLmdldE1vZGUoKTtcblxuXHRcdCQoICcuaGlnaGxpZ2h0LWhlYWRlcicgKS5yZW1vdmVDbGFzcyggJ2hpZ2hsaWdodC1oZWFkZXInICk7IC8vQ2xlYW4gYWxsIGhpZ2h0IGxpZ2h0IGhlYWRlciBvciBkYXRlIHJvd1xuXG5cdFx0aWYgKCBtb2RlID09PSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5NT05USCApIHtcblx0XHRcdHZhciBzZWxlY3RfZGF0ZSA9IEdsb2JhbC5zdHJUb0RhdGUoIHRoaXMuc3RhcnRfZGF0ZV9waWNrZXIuZ2V0VmFsdWUoKSApO1xuXHRcdFx0dmFyIHNlbGVjdF9kYXkgPSBzZWxlY3RfZGF0ZS5nZXREYXkoKTsgLy8gY29sdW1uIGluZGV4IGlzIGRheSBudW1iZXIgZm9yIG1vbnRoIG1vZGVcblx0XHRcdHNlbGVjdF9kYXRlID0gc2VsZWN0X2RhdGUuZm9ybWF0KCB0aGlzLmZ1bGxfZm9ybWF0ICk7XG5cblx0XHRcdHZhciBoZWFkZXIgPSAkKCAnIycgKyB0aGlzLnVpX2lkICsgJ19ncmlkXycgKyBzZWxlY3RfZGF5ICk7XG5cdFx0XHR2YXIgaGVhZGVyX3RleHQgPSAkKCBoZWFkZXIuY2hpbGRyZW4oKVsxXSApLnRleHQoKTtcdCAvL2dldCBjdXJyZW50IGNvbHVtbiBoZWFkZXIgdmFsdWVcblxuXHRcdFx0dGhpcy5oaWdobGlnaHRfaGVhZGVyID0gJCggJyMnICsgdGhpcy51aV9pZCArICdfZ3JpZF8nICsgc2VsZWN0X2RhdGUgKTsgLy9nZXQgZGF0ZSByb3dcblxuXHRcdFx0aWYgKCB0aGlzLmhpZ2hsaWdodF9oZWFkZXIubGVuZ3RoICE9PSAxICkge1xuXHRcdFx0XHR0aGlzLmhpZ2hsaWdodF9oZWFkZXIgPSAkKCAnIycgKyB0aGlzLnVpX2lkICsgJ19ncmlkXycgKyBzZWxlY3RfZGF5ICk7IC8vZ2V0IGhlYWRlclxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0aWYgKCBoZWFkZXJfdGV4dCA9PT0gdGhpcy5oaWdobGlnaHRfaGVhZGVyLnRleHQoKSApIHtcblx0XHRcdFx0XHQkKCAnLmhpZ2hsaWdodC1oZWFkZXInICkucmVtb3ZlQ2xhc3MoICdoaWdobGlnaHQtaGVhZGVyJyApO1xuXHRcdFx0XHRcdGhlYWRlci5hZGRDbGFzcyggJ2hpZ2hsaWdodC1oZWFkZXInICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdH0gZWxzZSB7XG5cdFx0XHRzZWxlY3RfZGF0ZSA9IEdsb2JhbC5zdHJUb0RhdGUoIHRoaXMuc3RhcnRfZGF0ZV9waWNrZXIuZ2V0VmFsdWUoKSApO1xuXHRcdFx0Ly9FcnJvcjogVW5jYXVnaHQgVHlwZUVycm9yOiBDYW5ub3QgcmVhZCBwcm9wZXJ0eSAnZm9ybWF0JyBvZiBudWxsIGluIGludGVyZmFjZS9odG1sNS8jIW09U2NoZWR1bGUmZGF0ZT1udWxsJm1vZGU9d2VlayBsaW5lIDYyOTVcblx0XHRcdGlmICggIXNlbGVjdF9kYXRlICkge1xuXHRcdFx0XHRzZWxlY3RfZGF0ZSA9IG5ldyBEYXRlKCk7XG5cdFx0XHRcdHRoaXMuc2V0RGF0ZVBpY2tlclZhbHVlKCBzZWxlY3RfZGF0ZS5mb3JtYXQoKSApO1xuXHRcdFx0fVxuXHRcdFx0c2VsZWN0X2RhdGUgPSBzZWxlY3RfZGF0ZS5mb3JtYXQoIHRoaXMuZnVsbF9mb3JtYXQgKTtcblx0XHRcdHRoaXMuaGlnaGxpZ2h0X2hlYWRlciA9ICQoICcjJyArIHRoaXMudWlfaWQgKyAnX2dyaWRfJyArIHNlbGVjdF9kYXRlICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBtb2RlICE9PSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5EQVkgKSB7XG5cblx0XHRcdGlmICggbW9kZSA9PT0gU2NoZWR1bGVWaWV3Q29udHJvbGxlck1vZGUuTU9OVEggKSB7XG5cdFx0XHRcdHRoaXMuaGlnaGxpZ2h0X2hlYWRlci5wYXJlbnQoKS5hZGRDbGFzcyggJ2hpZ2hsaWdodC1oZWFkZXInICk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuaGlnaGxpZ2h0X2hlYWRlci5hZGRDbGFzcyggJ2hpZ2hsaWdodC1oZWFkZXInICk7XG5cblx0XHR9XG5cdH1cblxuXHRidWlsZEFsbE1vZGVDb21tb25Db2x1bW5zKCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dGhpcy5zaGlmdF9rZXlfbmFtZV9hcnJheSA9IFsndXNlcl9pZCddO1xuXHRcdHZhciBkaXNwbGF5X2NvbHVtbnMgPSB0aGlzLmJ1aWxkRGlzcGxheUNvbHVtbnMoIHRoaXMuc2VsZWN0X2xheW91dC5kYXRhLmRpc3BsYXlfY29sdW1ucyApO1xuXG5cdFx0dmFyIGxlbiA9IGRpc3BsYXlfY29sdW1ucy5sZW5ndGg7XG5cblx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdHZhciBjb2x1bW4gPSBkaXNwbGF5X2NvbHVtbnNbaV07XG5cdFx0XHR2YXIgY29sdW1uX2luZm8gPSB7XG5cdFx0XHRcdG5hbWU6IGNvbHVtbi52YWx1ZSxcblx0XHRcdFx0aW5kZXg6IGNvbHVtbi52YWx1ZSxcblx0XHRcdFx0bGFiZWw6IGNvbHVtbi5sYWJlbCxcblx0XHRcdFx0d2lkdGg6IDEyMixcblx0XHRcdFx0c29ydGFibGU6IGZhbHNlLFxuXHRcdFx0XHR0aXRsZTogZmFsc2UsXG5cdFx0XHRcdGZpeGVkOiB0cnVlLFxuXHRcdFx0XHRyZXNpemFibGU6IGZhbHNlLFxuXHRcdFx0XHRmb3JtYXR0ZXI6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRcdFx0cmV0dXJuICR0aGlzLm9uQ2VsbEZvcm1hdCggYXJndW1lbnRzWzBdLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdICk7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGNlbGxhdHRyOiBmdW5jdGlvbiggcm93SWQsIHR2LCByYXdPYmplY3QsIGNtLCByZGF0YSApIHtcblx0XHRcdFx0XHR2YXIgZmllbGRfbmFtZSA9IGNtLmluZGV4O1xuXHRcdFx0XHRcdHJldHVybiAnY2xhc3M9XCInICsgZmllbGRfbmFtZSArICdfY2VsbFwiIGluZm9yX2NvbHVtbj1cInRydWVcIic7XG5cdFx0XHRcdH1cblx0XHRcdH07XG5cdFx0XHR0aGlzLnNjaGVkdWxlX2NvbHVtbnMucHVzaCggY29sdW1uX2luZm8gKTtcblx0XHRcdHRoaXMuc2hpZnRfa2V5X25hbWVfYXJyYXkucHVzaCggY29sdW1uLnZhbHVlICsgJ19pZCcgKTtcblx0XHR9XG5cblx0XHR2YXIgZW1wbG95ZWVfY29sdW1uID0ge1xuXHRcdFx0bmFtZTogJ3VzZXJfZnVsbF9uYW1lJyxcblx0XHRcdGluZGV4OiAndXNlcl9mdWxsX25hbWUnLFxuXHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnRW1wbG95ZWUnICksXG5cdFx0XHR3aWR0aDogMTIyLFxuXHRcdFx0c29ydGFibGU6IGZhbHNlLFxuXHRcdFx0dGl0bGU6IGZhbHNlLFxuXHRcdFx0Zml4ZWQ6IHRydWUsXG5cdFx0XHRyZXNpemFibGU6IGZhbHNlLFxuXHRcdFx0Zm9ybWF0dGVyOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0XHRyZXR1cm4gJHRoaXMub25DZWxsRm9ybWF0KCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdLCBhcmd1bWVudHNbM10gKTtcblx0XHRcdH0sXG5cdFx0XHRjZWxsYXR0cjogZnVuY3Rpb24oIHJvd0lkLCB0diwgcmF3T2JqZWN0LCBjbSwgcmRhdGEgKSB7XG5cdFx0XHRcdHZhciBmaWVsZF9uYW1lID0gY20uaW5kZXg7XG5cdFx0XHRcdHJldHVybiAnY2xhc3M9XCInICsgZmllbGRfbmFtZSArICdfY2VsbFwiIGluZm9yX2NvbHVtbj1cInRydWVcIic7XG5cdFx0XHR9XG5cdFx0fTtcblxuXHRcdHRoaXMuc2NoZWR1bGVfY29sdW1ucy5wdXNoKCBlbXBsb3llZV9jb2x1bW4gKTtcblx0fVxuXG5cdGJ1aWxkTW9udGhSb3dzKCkge1xuXG5cdFx0dmFyIG1vbnRoX2RheXMgPSAoIHRoaXMuZW5kX2RhdGUuZ2V0VGltZSgpIC0gdGhpcy5zdGFydF9kYXRlLmdldFRpbWUoKSApIC8gODY0MDAwMDAgKyAxO1xuXHRcdHZhciBzdGFydF9kYXkgPSBuZXcgRGF0ZSggdGhpcy5zdGFydF9kYXRlLmdldFRpbWUoKSApLmdldERheSgpO1xuXHRcdHRoaXMuc2NoZWR1bGVfc291cmNlID0gW107XG5cdFx0dmFyIHN0YXJ0X2RhdGUgPSBuZXcgRGF0ZSggbmV3IERhdGUoIHRoaXMuc3RhcnRfZGF0ZS5nZXRUaW1lKCkgKS5zZXREYXRlKCB0aGlzLnN0YXJ0X2RhdGUuZ2V0RGF0ZSgpICsgNyApICk7XG5cblx0XHR0aGlzLm1vbnRoX2RhdGVfcm93X2FycmF5ID0gW107XG5cblx0XHR2YXIgcm93X251bSA9IDE7XG5cdFx0dmFyIHogPSAwOyAvL2RheSBvZmZzZXRcblxuXHRcdHdoaWxlICggcm93X251bSA8IDUgKSB7XG5cdFx0XHR2YXIgY3VycmVudF9kYXkgPSBzdGFydF9kYXk7XG5cdFx0XHR2YXIgcm93ID0gdGhpcy5nZXRFbXB0eVdlZWtseVJvdygpO1xuXHRcdFx0cm93LnR5cGUgPSBTY2hlZHVsZVZpZXdDb250cm9sbGVyUm93VHlwZS5EQVRFO1xuXG5cdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCA3OyBpKysgKSB7XG5cdFx0XHRcdHZhciBjdXJyZW50X2RhdGUgPSBuZXcgRGF0ZSggbmV3IERhdGUoIHN0YXJ0X2RhdGUuZ2V0VGltZSgpICkuc2V0RGF0ZSggc3RhcnRfZGF0ZS5nZXREYXRlKCkgKyB6ICkgKTtcblxuXHRcdFx0XHRpZiAoIGN1cnJlbnRfZGF0ZS5nZXRUaW1lKCkgPiB0aGlzLmVuZF9kYXRlLmdldFRpbWUoKSApIHtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJvd1tjdXJyZW50X2RheV0gPSBjdXJyZW50X2RhdGUuZm9ybWF0KCB0aGlzLndlZWtseV9mb3JtYXQgKTtcblxuXHRcdFx0XHRyb3dbY3VycmVudF9kYXldID0gdGhpcy5zZXRIb2xpZGF5SGVhZGVyKCByb3dbY3VycmVudF9kYXldICk7XG5cdFx0XHRcdHJvd1tjdXJyZW50X2RheSArICdfZnVsbF9kYXRlJ10gPSBjdXJyZW50X2RhdGUuZm9ybWF0KCB0aGlzLmZ1bGxfZm9ybWF0ICk7XG5cdFx0XHRcdHJvd1tjdXJyZW50X2RheSArICdfdGltZSddID0gY3VycmVudF9kYXRlLmdldFRpbWUoKTtcblxuXHRcdFx0XHRjdXJyZW50X2RheSA9IGN1cnJlbnRfZGF5ICsgMTtcblxuXHRcdFx0XHRpZiAoIGN1cnJlbnRfZGF5ID09PSA3ICkge1xuXHRcdFx0XHRcdGN1cnJlbnRfZGF5ID0gMDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHogPSB6ICsgMTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5tb250aF9kYXRlX3Jvd19hcnJheS5wdXNoKCByb3cgKTtcblx0XHRcdHJvd19udW0gPSByb3dfbnVtICsgMTtcblxuXHRcdFx0dGhpcy5zY2hlZHVsZV9zb3VyY2UucHVzaCggcm93ICk7XG5cblx0XHR9XG5cdH1cblxuXHRnZXRFbXB0eVdlZWtseVJvdygpIHtcblx0XHR2YXIgcm93ID0ge307XG5cdFx0cm93LnVzZXJfZnVsbF9uYW1lID0gJyc7XG5cdFx0cm93Lmxhc3RfbmFtZSA9ICcnO1xuXHRcdHJvdy51c2VyX2lkID0gJyc7XG5cdFx0cm93LmJyYW5jaF9pZCA9ICcnO1xuXHRcdHJvdy5kZXBhcnRtZW50X2lkID0gJyc7XG5cdFx0cm93LnNjaGVkdWxlX3BvbGljeV9pZCA9ICcnO1xuXHRcdHJvdy5qb2JfaWQgPSAnJztcblx0XHRyb3cuam9iX2l0ZW1faWQgPSAnJztcblx0XHRyb3cucHVuY2hfdGFnX2lkID0gW107XG5cblx0XHR2YXIgZGlzcGxheV9jb2x1bW5zID0gdGhpcy5zZWxlY3RfbGF5b3V0LmRhdGEuZGlzcGxheV9jb2x1bW5zO1xuXHRcdHZhciBkaXNwbGF5X2NvbHVtbnNfbGVuID0gZGlzcGxheV9jb2x1bW5zLmxlbmd0aDtcblxuXHRcdGZvciAoIHZhciBqID0gMDsgaiA8IGRpc3BsYXlfY29sdW1uc19sZW47IGorKyApIHtcblx0XHRcdHZhciBmaWVsZF9uYW1lID0gZGlzcGxheV9jb2x1bW5zW2pdO1xuXHRcdFx0cm93W2ZpZWxkX25hbWVdID0gJyc7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHJvdztcblx0fVxuXG5cdGJ1aWxkTW9udGhDb2x1bW5zKCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dGhpcy5zY2hlZHVsZV9jb2x1bW5zID0gW107XG5cdFx0dGhpcy5idWlsZEFsbE1vZGVDb21tb25Db2x1bW5zKCk7XG5cbi8vXHRcdHZhciBjdXJyZW50X2RhdGUgPSBuZXcgRGF0ZSggdGhpcy5zdGFydF9kYXRlLmdldFRpbWUoKSApO1xuXG5cdFx0dGhpcy5tb250aF9kYXRlX3Jvd190cl9pZHMgPSB7fTtcblx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCA3OyBpKysgKSB7XG5cdFx0XHR2YXIgdGVtcF9zdGFydF9kYXRlID0gbmV3IERhdGUoIHRoaXMuc3RhcnRfZGF0ZS5nZXRUaW1lKCkgKTtcblx0XHRcdHZhciBjdXJyZW50X2RhdGUgPSBuZXcgRGF0ZSggdGVtcF9zdGFydF9kYXRlLnNldERhdGUoIHRlbXBfc3RhcnRfZGF0ZS5nZXREYXRlKCkgKyBpICkgKTtcblx0XHRcdHZhciBzdGFydF9kYXkgPSBjdXJyZW50X2RhdGUuZ2V0RGF5KCk7XG5cdFx0XHR2YXIgaGVhZGVyX3RleHQgPSBjdXJyZW50X2RhdGUuZm9ybWF0KCB0aGlzLndlZWtseV9mb3JtYXQgKTtcblx0XHRcdHZhciBkYXRhX2ZpZWxkID0gc3RhcnRfZGF5O1xuXHRcdFx0aWYgKCBkYXRhX2ZpZWxkID09PSA3ICkge1xuXHRcdFx0XHRkYXRhX2ZpZWxkID0gMDtcblx0XHRcdH1cblxuXHRcdFx0aGVhZGVyX3RleHQgPSB0aGlzLnNldEhvbGlkYXlIZWFkZXIoIGhlYWRlcl90ZXh0ICk7XG5cblx0XHRcdHZhciBmdWxsX2RhdGFfZmllbGQgPSBjdXJyZW50X2RhdGUuZm9ybWF0KCB0aGlzLmZ1bGxfZm9ybWF0ICk7XG5cblx0XHRcdHZhciBjb2x1bW5faW5mbyA9IHtcblx0XHRcdFx0cmVzaXphYmxlOiBmYWxzZSxcblx0XHRcdFx0bmFtZTogZGF0YV9maWVsZC50b1N0cmluZygpLCAvL05lZWRlZCBmb3IganFncmlkIG90aGVyd2lzZSBpdCB0aGlua3MgaXRzIGFuIGluZGV4IGxvb2t1cC5cblx0XHRcdFx0aW5kZXg6IGZ1bGxfZGF0YV9maWVsZCxcblx0XHRcdFx0bGFiZWw6IGhlYWRlcl90ZXh0LFxuXHRcdFx0XHR3aWR0aDogMTUwLFxuXHRcdFx0XHRmaXhlZDogdHJ1ZSxcblx0XHRcdFx0c29ydGFibGU6IGZhbHNlLFxuXHRcdFx0XHR0aXRsZTogZmFsc2UsXG5cdFx0XHRcdGZvcm1hdHRlcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0cmV0dXJuICR0aGlzLm9uQ2VsbEZvcm1hdCggYXJndW1lbnRzWzBdLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdICk7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGNlbGxhdHRyOiBmdW5jdGlvbiggcm93SWQsIHR2LCByYXdPYmplY3QsIGNtLCByZGF0YSApIHtcblx0XHRcdFx0XHRpZiAoIHJhd09iamVjdC50eXBlID09PSBTY2hlZHVsZVZpZXdDb250cm9sbGVyUm93VHlwZS5EQVRFICkge1xuXHRcdFx0XHRcdFx0JHRoaXMubW9udGhfZGF0ZV9yb3dfdHJfaWRzW3Jvd0lkXSA9IHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXG5cdFx0XHRcdGlzX3N0YXRpY19zaXplOiB0cnVlXG5cdFx0XHR9O1xuXHRcdFx0dGhpcy5zY2hlZHVsZV9jb2x1bW5zLnB1c2goIGNvbHVtbl9pbmZvICk7XG5cblx0XHR9XG5cblx0XHR0aGlzLmJ1aWxkV2Vla2x5VG90YWxDb2x1bW5zKCk7XG5cblx0XHR0aGlzLnNjaGVkdWxlX2NvbHVtbnMucHVzaCgge1xuXHRcdFx0bmFtZTogJ3Njcm9sbGJhcl9zcGFjZXInLFxuXHRcdFx0aW5kZXg6ICdzY3JvbGxiYXJfc3BhY2VyJyxcblx0XHRcdGxhYmVsOiAnJyxcblx0XHRcdHdpZHRoOiBHbG9iYWwuZ2V0U2Nyb2xsYmFyV2lkdGgoKSxcblx0XHRcdHNvcnRhYmxlOiBmYWxzZSxcblx0XHRcdHRpdGxlOiBmYWxzZSxcblx0XHRcdGZpeGVkOiB0cnVlLFxuXHRcdFx0aXNfc3RhdGljX3NpemU6IHRydWUsIC8vVXNlZCB0byBza2lwIG91ciBvd24gYXV0by1zaXppbmcuXG5cdFx0fSApO1xuXG5cdFx0dGhpcy5idWlsZE1vbnRoUm93cygpO1xuXHR9XG5cblx0Z2V0RGF5QnlEYXlOdW0oIGRheSApIHtcblxuXHRcdHZhciBkYXk7XG5cdFx0c3dpdGNoICggZGF5ICkge1xuXHRcdFx0Y2FzZSAwOlxuXHRcdFx0XHRkYXkgPSAkLmkxOG4uXyggJ1MnICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAxOlxuXHRcdFx0XHRkYXkgPSAkLmkxOG4uXyggJ00nICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAyOlxuXHRcdFx0XHRkYXkgPSAkLmkxOG4uXyggJ1QnICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAzOlxuXHRcdFx0XHRkYXkgPSAkLmkxOG4uXyggJ1cnICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSA0OlxuXHRcdFx0XHRkYXkgPSAkLmkxOG4uXyggJ1QnICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSA1OlxuXHRcdFx0XHRkYXkgPSAkLmkxOG4uXyggJ0YnICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSA2OlxuXHRcdFx0XHRkYXkgPSAkLmkxOG4uXyggJ1MnICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdH1cblxuXHRcdHJldHVybiBkYXk7XG5cdH1cblxuXHRidWlsZFllYXJDb2x1bW5zKCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dGhpcy5zY2hlZHVsZV9jb2x1bW5zID0gW107XG5cblx0XHR0aGlzLmJ1aWxkQWxsTW9kZUNvbW1vbkNvbHVtbnMoKTtcblxuXHRcdHZhciBjdXJyZW50X2RhdGUgPSBuZXcgRGF0ZSggdGhpcy5zdGFydF9kYXRlLmdldFRpbWUoKSApO1xuXHRcdHZhciBlbmRfZGF0ZSA9IG5ldyBEYXRlKCB0aGlzLmVuZF9kYXRlLmdldFRpbWUoKSApO1xuXG5cdFx0dmFyIGkgPSAwO1xuXHRcdHdoaWxlICggY3VycmVudF9kYXRlLmZvcm1hdCggdGhpcy5mdWxsX2Zvcm1hdCApICE9PSBlbmRfZGF0ZS5mb3JtYXQoIHRoaXMuZnVsbF9mb3JtYXQgKSApIHtcblxuXHRcdFx0Y3VycmVudF9kYXRlID0gbmV3IERhdGUoIG5ldyBEYXRlKCB0aGlzLnN0YXJ0X2RhdGUuZ2V0VGltZSgpICkuc2V0RGF0ZSggdGhpcy5zdGFydF9kYXRlLmdldERhdGUoKSArIGkgKSApO1xuXHRcdFx0dmFyIGhlYWRlcl90ZXh0ID0gY3VycmVudF9kYXRlLmZvcm1hdCggdGhpcy53ZWVrbHlfZm9ybWF0ICk7XG5cdFx0XHR2YXIgZGF0YV9maWVsZCA9IGN1cnJlbnRfZGF0ZS5mb3JtYXQoIHRoaXMuZnVsbF9mb3JtYXQgKTtcblxuXHRcdFx0dmFyIGRheSA9IHRoaXMuZ2V0RGF5QnlEYXlOdW0oIGN1cnJlbnRfZGF0ZS5nZXREYXkoKSApO1xuXG5cdFx0XHR2YXIgY29sdW1uX2luZm8gPSB7XG5cdFx0XHRcdG5hbWU6IGRhdGFfZmllbGQsXG5cdFx0XHRcdGluZGV4OiBpLFxuXHRcdFx0XHRsYWJlbDogZGF5ICsgJzxicj4nICsgY3VycmVudF9kYXRlLmdldERhdGUoKSxcblx0XHRcdFx0d2lkdGg6IDIyLFxuXHRcdFx0XHRzb3J0YWJsZTogZmFsc2UsXG5cdFx0XHRcdHRpdGxlOiBmYWxzZSxcblx0XHRcdFx0Zml4ZWQ6IHRydWUsXG5cdFx0XHRcdGlzX3N0YXRpY19zaXplOiB0cnVlLCAvL1VzZWQgdG8gc2tpcCBvdXIgb3duIGF1dG8tc2l6aW5nLlxuXG5cdFx0XHRcdGZvcm1hdHRlcjogZnVuY3Rpb24oKSB7XG5cblx0XHRcdFx0XHRyZXR1cm4gJHRoaXMub25DZWxsRm9ybWF0KCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdLCBhcmd1bWVudHNbM10gKTtcblx0XHRcdFx0fVxuXHRcdFx0fTtcblx0XHRcdHRoaXMuc2NoZWR1bGVfY29sdW1ucy5wdXNoKCBjb2x1bW5faW5mbyApO1xuXG5cdFx0XHRpID0gaSArIDE7XG5cdFx0fVxuXG5cdFx0dGhpcy5zY2hlZHVsZV9jb2x1bW5zLnB1c2goIHtcblx0XHRcdG5hbWU6ICdzY3JvbGxiYXJfc3BhY2VyJyxcblx0XHRcdGluZGV4OiBpLFxuXHRcdFx0bGFiZWw6ICcnLFxuXHRcdFx0d2lkdGg6IEdsb2JhbC5nZXRTY3JvbGxiYXJXaWR0aCgpLFxuXHRcdFx0c29ydGFibGU6IGZhbHNlLFxuXHRcdFx0dGl0bGU6IGZhbHNlLFxuXHRcdFx0Zml4ZWQ6IHRydWUsXG5cdFx0XHRpc19zdGF0aWNfc2l6ZTogdHJ1ZSwgLy9Vc2VkIHRvIHNraXAgb3VyIG93biBhdXRvLXNpemluZy5cblx0XHR9ICk7XG5cblx0XHQvL3RoaXMuYnVpbGRXZWVrbHlUb3RhbENvbHVtbnMoKTtcblx0fVxuXG5cdGJ1aWxkRGF5Q29sdW1ucygpIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHRoaXMuc2NoZWR1bGVfY29sdW1ucyA9IFtdO1xuXG5cdFx0dGhpcy5idWlsZEFsbE1vZGVDb21tb25Db2x1bW5zKCk7XG5cblx0XHR2YXIgY3VycmVudF9kYXRlID0gbmV3IERhdGUoIHRoaXMuc3RhcnRfZGF0ZS5nZXRUaW1lKCkgKTtcblx0XHR2YXIgaGVhZGVyX3RleHQgPSBjdXJyZW50X2RhdGUuZm9ybWF0KCB0aGlzLndlZWtseV9mb3JtYXQgKTtcblx0XHR2YXIgZGF0YV9maWVsZCA9IGN1cnJlbnRfZGF0ZS5mb3JtYXQoIHRoaXMuZnVsbF9mb3JtYXQgKTtcblxuXHRcdHZhciBjb2x1bW5faW5mbyA9IHtcblx0XHRcdGZpeGVkOiB0cnVlLFxuXHRcdFx0cmVzaXphYmxlOiBmYWxzZSxcblx0XHRcdHdpZHRoOiA1MDAsXG5cdFx0XHRuYW1lOiBkYXRhX2ZpZWxkLFxuXHRcdFx0aW5kZXg6IGRhdGFfZmllbGQsXG5cdFx0XHRsYWJlbDogJ2RhaWx5X2hlYWRlcl9yZXBsYWNlJyxcblx0XHRcdGlzX3N0YXRpY19zaXplOiB0cnVlLFxuXHRcdFx0c29ydGFibGU6IGZhbHNlLFxuXHRcdFx0dGl0bGU6IGZhbHNlLFxuXHRcdFx0ZGlzcGxheV90b3RhbF9jb2x1bW46IHRydWUsXG5cdFx0XHRmb3JtYXR0ZXI6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRcdHJldHVybiAkdGhpcy5vbkNlbGxGb3JtYXQoIGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdLCBhcmd1bWVudHNbMl0sIGFyZ3VtZW50c1szXSApO1xuXHRcdFx0fVxuXHRcdH07XG5cdFx0dGhpcy5zY2hlZHVsZV9jb2x1bW5zLnB1c2goIGNvbHVtbl9pbmZvICk7XG5cblx0XHRjb2x1bW5faW5mbyA9IHtcblx0XHRcdGZpeGVkOiB0cnVlLFxuXHRcdFx0cmVzaXphYmxlOiBmYWxzZSxcblx0XHRcdHdpZHRoOiAxMjIsXG5cdFx0XHRuYW1lOiAndG90YWwnLFxuXHRcdFx0aW5kZXg6ICd0b3RhbCcsXG5cdFx0XHRsYWJlbDogJ1RvdGFsIFRpbWUnLFxuXHRcdFx0c29ydGFibGU6IGZhbHNlLFxuXHRcdFx0dGl0bGU6IGZhbHNlLFxuXHRcdFx0Zm9ybWF0dGVyOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0XHRyZXR1cm4gJHRoaXMub25DZWxsRm9ybWF0KCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdLCBhcmd1bWVudHNbM10gKTtcblx0XHRcdH1cblx0XHR9O1xuXHRcdHRoaXMuc2NoZWR1bGVfY29sdW1ucy5wdXNoKCBjb2x1bW5faW5mbyApO1xuXG5cdFx0dGhpcy5zY2hlZHVsZV9jb2x1bW5zLnB1c2goIHtcblx0XHRcdG5hbWU6ICdzY3JvbGxiYXJfc3BhY2VyJyxcblx0XHRcdGluZGV4OiAnc2Nyb2xsYmFyX3NwYWNlcicsXG5cdFx0XHRsYWJlbDogJycsXG5cdFx0XHR3aWR0aDogR2xvYmFsLmdldFNjcm9sbGJhcldpZHRoKCksXG5cdFx0XHRzb3J0YWJsZTogZmFsc2UsXG5cdFx0XHR0aXRsZTogZmFsc2UsXG5cdFx0XHRmaXhlZDogdHJ1ZSxcblx0XHRcdC8vaXNfc3RhdGljX3NpemU6IGZhbHNlLCAvL1VzZWQgdG8gc2tpcCBvdXIgb3duIGF1dG8tc2l6aW5nLlxuXHRcdH0gKTtcblx0fVxuXG5cdGJ1aWxkV2Vla0NvbHVtbnMoKSB7XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHRoaXMuc2NoZWR1bGVfY29sdW1ucyA9IFtdO1xuXG5cdFx0dGhpcy5idWlsZEFsbE1vZGVDb21tb25Db2x1bW5zKCk7XG5cblx0XHQvL0Vycm9yOiBVbmNhdWdodCBUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnR5ICdnZXRUaW1lJyBvZiBudWxsIGluIC9pbnRlcmZhY2UvaHRtbDUvIyFtPVNjaGVkdWxlJmRhdGU9MjAxNDEyMDgmbW9kZT13ZWVrIGxpbmUgNjU4MFxuXHRcdGlmICggIXRoaXMuc3RhcnRfZGF0ZSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgY3VycmVudF9kYXRlID0gbmV3IERhdGUoIHRoaXMuc3RhcnRfZGF0ZS5nZXRUaW1lKCkgKTtcblx0XHR2YXIgZW5kX2RhdGUgPSBuZXcgRGF0ZSggdGhpcy5lbmRfZGF0ZS5nZXRUaW1lKCkgKTtcblxuXHRcdHZhciBpID0gMDtcblx0XHR2YXIgc2V0X2ZpeGVkX3dpZHRoID0gZmFsc2U7XG4vL1x0XHRpZiAoIHRoaXMuc2NoZWR1bGVfY29sdW1ucy5sZW5ndGggPT09IDEgKSB7XG4vL1x0XHRcdHNldF9maXhlZF93aWR0aCA9IGZhbHNlO1xuLy9cdFx0fVxuXG5cdFx0d2hpbGUgKCBjdXJyZW50X2RhdGUuZm9ybWF0KCB0aGlzLmZ1bGxfZm9ybWF0ICkgIT09IGVuZF9kYXRlLmZvcm1hdCggdGhpcy5mdWxsX2Zvcm1hdCApICkge1xuXG5cdFx0XHRjdXJyZW50X2RhdGUgPSBuZXcgRGF0ZSggbmV3IERhdGUoIHRoaXMuc3RhcnRfZGF0ZS5nZXRUaW1lKCkgKS5zZXREYXRlKCB0aGlzLnN0YXJ0X2RhdGUuZ2V0RGF0ZSgpICsgaSApICk7XG5cblx0XHRcdHZhciBoZWFkZXJfdGV4dCA9IGN1cnJlbnRfZGF0ZS5mb3JtYXQoIHRoaXMud2Vla2x5X2Zvcm1hdCApO1xuXHRcdFx0dmFyIGRhdGFfZmllbGQgPSBjdXJyZW50X2RhdGUuZm9ybWF0KCB0aGlzLmZ1bGxfZm9ybWF0ICk7XG5cblx0XHRcdGhlYWRlcl90ZXh0ID0gdGhpcy5zZXRIb2xpZGF5SGVhZGVyKCBoZWFkZXJfdGV4dCApO1xuXG5cdFx0XHR2YXIgY29sdW1uX2luZm8gPSB7XG5cdFx0XHRcdHJlc2l6YWJsZTogZmFsc2UsXG5cdFx0XHRcdG5hbWU6IGRhdGFfZmllbGQudG9TdHJpbmcoKSwgLy9OZWVkZWQgZm9yIGpxZ3JpZCBvdGhlcndpc2UgaXQgdGhpbmtzIGl0cyBhbiBpbmRleCBsb29rdXAuXG5cdFx0XHRcdGluZGV4OiBkYXRhX2ZpZWxkLFxuXHRcdFx0XHRsYWJlbDogaGVhZGVyX3RleHQsXG5cdFx0XHRcdHdpZHRoOiAxNTAsXG5cdFx0XHRcdGZpeGVkOiB0cnVlLFxuXHRcdFx0XHRzb3J0YWJsZTogZmFsc2UsXG5cdFx0XHRcdHRpdGxlOiBmYWxzZSxcblx0XHRcdFx0Zm9ybWF0dGVyOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0XHRcdHJldHVybiAkdGhpcy5vbkNlbGxGb3JtYXQoIGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdLCBhcmd1bWVudHNbMl0sIGFyZ3VtZW50c1szXSApO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRpc19zdGF0aWNfc2l6ZTogdHJ1ZVxuXHRcdFx0fTtcblxuXHRcdFx0dGhpcy5zY2hlZHVsZV9jb2x1bW5zLnB1c2goIGNvbHVtbl9pbmZvICk7XG5cblx0XHRcdGkgPSBpICsgMTtcblxuXHRcdH1cblxuXHRcdHRoaXMuYnVpbGRXZWVrbHlUb3RhbENvbHVtbnMoKTtcblxuXHRcdHRoaXMuc2NoZWR1bGVfY29sdW1ucy5wdXNoKCB7XG5cdFx0XHRuYW1lOiAnc2Nyb2xsYmFyX3NwYWNlcicsXG5cdFx0XHRpbmRleDogJ3Njcm9sbGJhcl9zcGFjZXInLFxuXHRcdFx0bGFiZWw6ICcnLFxuXHRcdFx0d2lkdGg6IEdsb2JhbC5nZXRTY3JvbGxiYXJXaWR0aCgpLFxuXHRcdFx0c29ydGFibGU6IGZhbHNlLFxuXHRcdFx0dGl0bGU6IGZhbHNlLFxuXHRcdFx0Zml4ZWQ6IHRydWUsXG5cdFx0XHRpc19zdGF0aWNfc2l6ZTogdHJ1ZSwgLy9Vc2VkIHRvIHNraXAgb3VyIG93biBhdXRvLXNpemluZy5cblx0XHR9ICk7XG5cblx0XHRyZXR1cm4gdGhpcy5zY2hlZHVsZV9jb2x1bW5zO1xuXHR9XG5cblx0c2V0SG9saWRheUhlYWRlciggaGVhZGVyX3RleHQsIGluTGluZSApIHtcblxuXHRcdGlmICggdGhpcy5ob2xpZGF5X2RhdGFfZGljICkge1xuXHRcdFx0aWYgKCB0aGlzLmhvbGlkYXlfZGF0YV9kaWNbaGVhZGVyX3RleHRdICkge1xuXG5cdFx0XHRcdGlmICggaW5MaW5lICkge1xuXHRcdFx0XHRcdGhlYWRlcl90ZXh0ID0gaGVhZGVyX3RleHQgKyAnICgnICsgR2xvYmFsLmh0bWxFbmNvZGUoIHRoaXMuaG9saWRheV9kYXRhX2RpY1toZWFkZXJfdGV4dF0ubmFtZSApICsgJyknO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGhlYWRlcl90ZXh0ID0gaGVhZGVyX3RleHQgKyAnPGJyPicgKyBHbG9iYWwuaHRtbEVuY29kZSggdGhpcy5ob2xpZGF5X2RhdGFfZGljW2hlYWRlcl90ZXh0XS5uYW1lICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBoZWFkZXJfdGV4dDtcblx0fVxuXG5cdGJ1aWxkV2Vla2x5VG90YWxDb2x1bW5zKCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dmFyIHNob3dfd2Vla2x5X3RvdGFsID0gdGhpcy5zZXR0aW5nc19tZW51LmdldEJ1dHRvbiggJ3dlZWtseV90b3RhbHNfYnRuJyApLmFjdGl2ZTtcblxuXHRcdHZhciBpc19maXhlZCA9IGZhbHNlO1xuXG5cdFx0aWYgKCBzaG93X3dlZWtseV90b3RhbCApIHtcblx0XHRcdHZhciBzaGlmdHNfY29sdW1uID0ge1xuXHRcdFx0XHRuYW1lOiAnc2hpZnRzJyxcblx0XHRcdFx0aW5kZXg6ICdzaGlmdHMnLFxuXHRcdFx0XHRsYWJlbDogJC5pMThuLl8oICdTaGlmdHMnICksXG5cdFx0XHRcdHdpZHRoOiA1MCxcblx0XHRcdFx0c29ydGFibGU6IGZhbHNlLFxuXHRcdFx0XHR0aXRsZTogZmFsc2UsXG5cdFx0XHRcdGZvcm1hdHRlcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0cmV0dXJuICR0aGlzLm9uQ2VsbEZvcm1hdCggYXJndW1lbnRzWzBdLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdICk7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGZpeGVkOiB0cnVlXG5cdFx0XHR9O1xuXG5cdFx0XHR2YXIgYWJzZW5jZXNfY29sdW1uID0ge1xuXHRcdFx0XHRuYW1lOiAnYWJzZW5jZXMnLFxuXHRcdFx0XHRpbmRleDogJ2Fic2VuY2VzJyxcblx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnQWJzZW5jZXMnICksXG5cdFx0XHRcdHdpZHRoOiA3MCxcblx0XHRcdFx0c29ydGFibGU6IGZhbHNlLFxuXHRcdFx0XHR0aXRsZTogZmFsc2UsXG5cdFx0XHRcdGZvcm1hdHRlcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0cmV0dXJuICR0aGlzLm9uQ2VsbEZvcm1hdCggYXJndW1lbnRzWzBdLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdICk7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGZpeGVkOiB0cnVlXG5cdFx0XHR9O1xuXG5cdFx0XHR2YXIgdG90YWxfdGltZSA9IHtcblx0XHRcdFx0bmFtZTogJ3RvdGFsX3RpbWUnLFxuXHRcdFx0XHRpbmRleDogJ3RvdGFsX3RpbWUnLFxuXHRcdFx0XHRsYWJlbDogJC5pMThuLl8oICdUb3RhbCBUaW1lJyApLFxuXHRcdFx0XHR3aWR0aDogNzAsXG5cdFx0XHRcdHNvcnRhYmxlOiBmYWxzZSxcblx0XHRcdFx0dGl0bGU6IGZhbHNlLFxuXHRcdFx0XHRmb3JtYXR0ZXI6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHJldHVybiAkdGhpcy5vbkNlbGxGb3JtYXQoIGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdLCBhcmd1bWVudHNbMl0sIGFyZ3VtZW50c1szXSApO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRmaXhlZDogdHJ1ZVxuXHRcdFx0fTtcblxuXHRcdFx0dmFyIHRvdGFsX3RpbWVfd2FnZSA9IHtcblx0XHRcdFx0bmFtZTogJ3RvdGFsX3RpbWVfd2FnZScsXG5cdFx0XHRcdGluZGV4OiAndG90YWxfdGltZV93YWdlJyxcblx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnV2FnZXMnICksXG5cdFx0XHRcdHdpZHRoOiA5MCxcblx0XHRcdFx0c29ydGFibGU6IGZhbHNlLFxuXHRcdFx0XHR0aXRsZTogZmFsc2UsXG5cdFx0XHRcdGZvcm1hdHRlcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0cmV0dXJuICR0aGlzLm9uQ2VsbEZvcm1hdCggYXJndW1lbnRzWzBdLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdICk7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGZpeGVkOiB0cnVlXG5cdFx0XHR9O1xuXG5cdFx0XHR0aGlzLnNjaGVkdWxlX2NvbHVtbnMucHVzaCggc2hpZnRzX2NvbHVtbiApO1xuXHRcdFx0dGhpcy5zY2hlZHVsZV9jb2x1bW5zLnB1c2goIGFic2VuY2VzX2NvbHVtbiApO1xuXHRcdFx0dGhpcy5zY2hlZHVsZV9jb2x1bW5zLnB1c2goIHRvdGFsX3RpbWUgKTtcblx0XHRcdHRoaXMuc2NoZWR1bGVfY29sdW1ucy5wdXNoKCB0b3RhbF90aW1lX3dhZ2UgKTtcblx0XHR9XG5cdH1cblxuXHRidWlsZFNjaGVkdWxlQ29sdW1ucygpIHtcblx0XHR0aGlzLnNoaWZ0X2tleV9uYW1lX2FycmF5ID0gWyd1c2VyX2lkJ107XG5cdFx0dGhpcy5zY2hlZHVsZV9jb2x1bW5zID0gW107XG5cblx0XHR2YXIgbW9kZSA9IHRoaXMuZ2V0TW9kZSgpO1xuXG5cdFx0c3dpdGNoICggbW9kZSApIHtcblx0XHRcdGNhc2UgU2NoZWR1bGVWaWV3Q29udHJvbGxlck1vZGUuV0VFSzpcblx0XHRcdFx0dGhpcy5idWlsZFdlZWtDb2x1bW5zKCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5NT05USDpcblx0XHRcdFx0dGhpcy5idWlsZE1vbnRoQ29sdW1ucygpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgU2NoZWR1bGVWaWV3Q29udHJvbGxlck1vZGUuWUVBUjpcblx0XHRcdFx0dGhpcy5idWlsZFllYXJDb2x1bW5zKCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5EQVk6XG5cdFx0XHRcdHRoaXMuYnVpbGREYXlDb2x1bW5zKCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdH1cblx0fVxuXG5cdHNldFNjaGVkdWxlR3JpZFJvd1NwYW4oKSB7XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXG5cdFx0dmFyIGRpc3BsYXlfY29sdW1ucyA9IHRoaXMuc2VsZWN0X2xheW91dC5kYXRhLmRpc3BsYXlfY29sdW1ucztcblxuXHRcdHZhciBkaXNwbGF5X2NvbHVtbnNfbGVuID0gZGlzcGxheV9jb2x1bW5zLmxlbmd0aDtcblxuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGRpc3BsYXlfY29sdW1uc19sZW47IGkrKyApIHtcblx0XHRcdHZhciBjb2x1bW5fbmFtZSA9IGRpc3BsYXlfY29sdW1uc1tpXTtcblxuXHRcdFx0c3RhcnRTZXQoIGNvbHVtbl9uYW1lICk7XG5cdFx0fVxuXG5cdFx0c3RhcnRTZXQoICd1c2VyX2Z1bGxfbmFtZScgKTtcblxuXHRcdGZ1bmN0aW9uIHN0YXJ0U2V0KCBrZXkgKSB7XG5cdFx0XHR2YXIgY2VsbHMgPSAkdGhpcy5ncmlkLmdyaWQuZmluZCggJ1thcmlhLWRlc2NyaWJlZGJ5PScgKyAkdGhpcy51aV9pZCArICdfZ3JpZF8nICsga2V5ICsgJ10nICk7XG5cblx0XHRcdHZhciBsZW4gPSBjZWxscy5sZW5ndGg7XG5cblx0XHRcdHZhciBjb3VudCA9IDA7XG5cblx0XHRcdHZhciBsYXN0X3ZhbCA9IG51bGw7XG5cblx0XHRcdHZhciBsYXN0X2NlbGwgPSBudWxsO1xuXG5cdFx0XHR2YXIgbmVlZF9yZW1vdmVfY2VsbHMgPSBbXTtcblxuXHRcdFx0dmFyIHN0YXJ0ID0gbGVuIC0gMTtcblxuXHRcdFx0c2V0Um93cygpO1xuXG5cdFx0XHRmdW5jdGlvbiBzZXRSb3dzKCkge1xuXHRcdFx0XHRmb3IgKCB2YXIgaSA9IHN0YXJ0OyBpID49IDA7IGktLSApIHtcblx0XHRcdFx0XHR2YXIgY2VsbCA9ICQoIGNlbGxzW2ldICk7XG5cdFx0XHRcdFx0dmFyIGNlbGxfdmFsID0gJCggY2VsbHNbaV0gKS5jaGlsZHJlbigpLmVxKCAwICkuY2hpbGRyZW4oKS5lcSggMCApLnRleHQoKTtcblxuXHRcdFx0XHRcdGlmICggaSA9PT0gbGVuIC0gMSApIHtcblx0XHRcdFx0XHRcdGxhc3RfdmFsID0gY2VsbF92YWw7XG5cdFx0XHRcdFx0XHRjb3VudCA9IGNvdW50ICsgMTtcblx0XHRcdFx0XHRcdGxhc3RfY2VsbCA9IGNlbGw7XG5cdFx0XHRcdFx0fSBlbHNlIGlmICggbGFzdF92YWwgIT09IGNlbGxfdmFsICkge1xuXHRcdFx0XHRcdFx0bGFzdF92YWwgPSBjZWxsX3ZhbDtcblx0XHRcdFx0XHRcdGxhc3RfY2VsbC5hdHRyKCAncm93c3BhbicsIGNvdW50ICk7XG5cblx0XHRcdFx0XHRcdGZvciAoIHZhciBqID0gMDsgaiA8IG5lZWRfcmVtb3ZlX2NlbGxzLmxlbmd0aDsgaisrICkge1xuXHRcdFx0XHRcdFx0XHR2YXIgbmVlZF9yZW1vdmVkX2NlbGwgPSBuZWVkX3JlbW92ZV9jZWxsc1tqXTtcbi8vXHRcdFx0XHRcdFx0XHRuZWVkX3JlbW92ZWRfY2VsbC5hZGRDbGFzcyggJ25lZWQtcmVtb3ZlJyApO1xuXHRcdFx0XHRcdFx0XHR2YXIgbm9kZSA9IG5lZWRfcmVtb3ZlZF9jZWxsWzBdO1xuXHRcdFx0XHRcdFx0XHRpZiAoIG5vZGUucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0XHRcdFx0XHRub2RlLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRuZWVkX3JlbW92ZWRfY2VsbCA9IFtdO1xuXHRcdFx0XHRcdFx0Y291bnQgPSAxO1xuXHRcdFx0XHRcdFx0bGFzdF9jZWxsID0gY2VsbDtcblxuXHRcdFx0XHRcdH0gZWxzZSBpZiAoIGkgPT09IDAgKSB7XG5cdFx0XHRcdFx0XHRjb3VudCA9IGNvdW50ICsgMTtcblx0XHRcdFx0XHRcdG5lZWRfcmVtb3ZlX2NlbGxzLnB1c2goIGxhc3RfY2VsbCApO1xuXHRcdFx0XHRcdFx0aWYgKCBjb3VudCA+IDEgKSB7XG5cdFx0XHRcdFx0XHRcdGNlbGwuYXR0ciggJ3Jvd3NwYW4nLCBjb3VudCApO1xuXHRcdFx0XHRcdFx0XHRmb3IgKCB2YXIgaiA9IDA7IGogPCBuZWVkX3JlbW92ZV9jZWxscy5sZW5ndGg7IGorKyApIHtcblx0XHRcdFx0XHRcdFx0XHRuZWVkX3JlbW92ZWRfY2VsbCA9IG5lZWRfcmVtb3ZlX2NlbGxzW2pdO1xuLy9cdFx0XHRcdFx0XHRcdFx0bmVlZF9yZW1vdmVkX2NlbGwuYWRkQ2xhc3MoICduZWVkLXJlbW92ZScgKTtcblx0XHRcdFx0XHRcdFx0XHRub2RlID0gbmVlZF9yZW1vdmVkX2NlbGxbMF07XG5cdFx0XHRcdFx0XHRcdFx0aWYgKCBub2RlLnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRub2RlLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRjb3VudCA9IGNvdW50ICsgMTtcblx0XHRcdFx0XHRcdG5lZWRfcmVtb3ZlX2NlbGxzLnB1c2goIGxhc3RfY2VsbCApO1xuXHRcdFx0XHRcdFx0bGFzdF9jZWxsID0gY2VsbDtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cblx0XHR9XG5cdH1cblxuXHRvblNldFNlYXJjaEZpbHRlckZpbmlzaGVkKCkge1xuXHR9XG5cblx0b25CdWlsZEJhc2ljVUlGaW5pc2hlZCgpIHtcblx0fVxuXG5cdG9uQnVpbGRBZHZVSUZpbmlzaGVkKCkge1xuXHR9XG5cblx0Ly8gc2V0RGF0ZVVybCgpIHtcblx0Ly8gXHR2YXIgJHRoaXMgPSB0aGlzO1xuXHQvLyBcdGlmICggISR0aGlzLmVkaXRfdmlldyApIHtcblx0Ly9cblx0Ly8gXHRcdHZhciBtb2RlID0gdGhpcy5nZXRNb2RlKCk7XG5cdC8vIFx0XHR2YXIgZGVmYXVsdF9kYXRlID0gJHRoaXMuc3RhcnRfZGF0ZV9waWNrZXIuZ2V0RGVmYXVsdEZvcm1hdFZhbHVlKCk7XG5cdC8vXG5cdC8vIFx0XHRpZiAoIG1vZGUgKSB7XG5cdC8vIFx0XHRcdHdpbmRvdy5sb2NhdGlvbiA9IEdsb2JhbC5nZXRCYXNlVVJMKCkgKyAnIyFtPScgKyAkdGhpcy52aWV3SWQgKyAnJmRhdGU9JyArIGRlZmF1bHRfZGF0ZSArICcmbW9kZT0nICsgbW9kZTtcblx0Ly8gXHRcdH0gZWxzZSB7XG5cdC8vIFx0XHRcdGlmICggTG9jYWxDYWNoZURhdGEuZ2V0QWxsVVJMQXJncygpICYmIExvY2FsQ2FjaGVEYXRhLmdldEFsbFVSTEFyZ3MoKS5tb2RlICkge1xuXHQvLyBcdFx0XHRcdCR0aGlzLnNldFRvZ2dsZUJ1dHRvblZhbHVlKCBMb2NhbENhY2hlRGF0YS5nZXRBbGxVUkxBcmdzKCkubW9kZSApO1xuXHQvLyBcdFx0XHRcdG1vZGUgPSB0aGlzLmdldE1vZGUoKTtcblx0Ly8gXHRcdFx0XHR3aW5kb3cubG9jYXRpb24gPSBHbG9iYWwuZ2V0QmFzZVVSTCgpICsgJyMhbT0nICsgJHRoaXMudmlld0lkICsgJyZkYXRlPScgKyBkZWZhdWx0X2RhdGUgKyAnJm1vZGU9JyArIG1vZGU7XG5cdC8vIFx0XHRcdH0gZWxzZSB7XG5cdC8vIFx0XHRcdFx0d2luZG93LmxvY2F0aW9uID0gR2xvYmFsLmdldEJhc2VVUkwoKSArICcjIW09JyArICR0aGlzLnZpZXdJZCArICcmZGF0ZT0nICsgZGVmYXVsdF9kYXRlO1xuXHQvLyBcdFx0XHR9XG5cdC8vIFx0XHR9XG5cdC8vXG5cdC8vIFx0fVxuXHQvLyB9LFxuXG5cdHJlU2V0VVJMKCkge1xuXHRcdHZhciBtb2RlID0gdGhpcy5nZXRNb2RlKCk7XG5cdFx0dmFyIGFyZ3M7XG5cdFx0aWYgKCBtb2RlICkge1xuXHRcdFx0Ly9hcmdzID0gJyMhbT0nICsgdGhpcy52aWV3SWQgKyAnJmRhdGU9JyArIHRoaXMuc3RhcnRfZGF0ZV9waWNrZXIuZ2V0RGVmYXVsdEZvcm1hdFZhbHVlKCkgKyAnJm1vZGU9JyArIG1vZGU7XG5cdFx0XHRhcmdzID0gJyMhbT0nICsgdGhpcy52aWV3SWQgKyAnJm1vZGU9JyArIG1vZGU7XG5cdFx0XHRHbG9iYWwuc2V0VVJMVG9Ccm93c2VyKCBHbG9iYWwuZ2V0QmFzZVVSTCgpICsgYXJncyApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvL2FyZ3MgPSAnIyFtPScgKyB0aGlzLnZpZXdJZCArICcmZGF0ZT0nICsgdGhpcy5zdGFydF9kYXRlX3BpY2tlci5nZXREZWZhdWx0Rm9ybWF0VmFsdWUoKTtcblx0XHRcdGFyZ3MgPSAnIyFtPScgKyB0aGlzLnZpZXdJZDtcblx0XHRcdEdsb2JhbC5zZXRVUkxUb0Jyb3dzZXIoIEdsb2JhbC5nZXRCYXNlVVJMKCkgKyBhcmdzICk7XG5cdFx0fVxuXHRcdExvY2FsQ2FjaGVEYXRhLnNldEFsbFVSTEFyZ3MoIEdsb2JhbC5idWlsZEFyZ0RpYyggYXJncy5zcGxpdCggJyYnICkgKSApO1xuXHR9XG5cblx0c2V0VVJMKCkge1xuXHRcdHZhciBhID0gJyc7XG5cdFx0c3dpdGNoICggTG9jYWxDYWNoZURhdGEuY3VycmVudF9kb2luZ19jb250ZXh0X2FjdGlvbiApIHtcblx0XHRcdGNhc2UgJ25ldyc6XG5cdFx0XHRjYXNlICdlZGl0Jzpcblx0XHRcdGNhc2UgJ3ZpZXcnOlxuXHRcdFx0XHRhID0gTG9jYWxDYWNoZURhdGEuY3VycmVudF9kb2luZ19jb250ZXh0X2FjdGlvbjtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdjb3B5X2FzX25ldyc6XG5cdFx0XHRcdGEgPSAnbmV3Jztcblx0XHRcdFx0YnJlYWs7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLmNhblNldFVSTCgpICkge1xuXHRcdFx0dmFyIHRhYl9uYW1lID0gdGhpcy5lZGl0X3ZpZXdfdGFiID8gdGhpcy5lZGl0X3ZpZXdfdGFiLmZpbmQoICcuZWRpdC12aWV3LXRhYi1iYXItbGFiZWwnICkuY2hpbGRyZW4oKS5lcSggdGhpcy5nZXRFZGl0Vmlld1RhYkluZGV4KCkgKS50ZXh0KCkgOiAnJztcblx0XHRcdHRhYl9uYW1lID0gdGFiX25hbWUucmVwbGFjZSggL1xcL3xcXHMrL2csICcnICk7XG5cblx0XHRcdHZhciBtb2RlID0gdGhpcy5nZXRNb2RlKCk7XG5cblx0XHRcdGlmICggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICYmIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCAmJiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgIT0gVFRVVUlELnplcm9faWQgKSB7XG5cdFx0XHRcdGlmICggYSApIHtcblxuXHRcdFx0XHRcdC8vR2xvYmFsLnNldFVSTFRvQnJvd3NlciggR2xvYmFsLmdldEJhc2VVUkwoKSArICcjIW09JyArIHRoaXMudmlld0lkICsgJyZkYXRlPScgKyB0aGlzLnN0YXJ0X2RhdGVfcGlja2VyLmdldERlZmF1bHRGb3JtYXRWYWx1ZSgpICsgJyZtb2RlPScgKyBtb2RlICsgJyZhPScgKyBhICsgJyZpZD0nICsgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkICtcblx0XHRcdFx0XHRHbG9iYWwuc2V0VVJMVG9Ccm93c2VyKCBHbG9iYWwuZ2V0QmFzZVVSTCgpICsgJyMhbT0nICsgdGhpcy52aWV3SWQgKyAnJm1vZGU9JyArIG1vZGUgKyAnJmE9JyArIGEgKyAnJmlkPScgKyB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgK1xuXHRcdFx0XHRcdFx0JyZ0YWI9JyArIHRhYl9uYW1lICk7XG5cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQvL0dsb2JhbC5zZXRVUkxUb0Jyb3dzZXIoIEdsb2JhbC5nZXRCYXNlVVJMKCkgKyAnIyFtPScgKyB0aGlzLnZpZXdJZCArICcmZGF0ZT0nICsgdGhpcy5zdGFydF9kYXRlX3BpY2tlci5nZXREZWZhdWx0Rm9ybWF0VmFsdWUoKSArICcmbW9kZT0nICsgbW9kZSArICcmaWQ9JyArIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCApO1xuXHRcdFx0XHRcdEdsb2JhbC5zZXRVUkxUb0Jyb3dzZXIoIEdsb2JhbC5nZXRCYXNlVVJMKCkgKyAnIyFtPScgKyB0aGlzLnZpZXdJZCArICcmbW9kZT0nICsgbW9kZSArICcmaWQ9JyArIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCApO1xuXG5cdFx0XHRcdH1cblxuXHRcdFx0XHRHbG9iYWwudHJhY2tWaWV3KCB0aGlzLnZpZXdJZCwgTG9jYWxDYWNoZURhdGEuY3VycmVudF9kb2luZ19jb250ZXh0X2FjdGlvbiApO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZiAoIGEgKSB7XG5cblx0XHRcdFx0XHQvL0VkaXQgYSByZWNvcmQgd2hpY2ggZG9uJ3QgaGF2ZSBpZCwgc2NoZWR1bGUgdmlldyBSZWN1cnJpbmcgU2NlZHVsZVxuXHRcdFx0XHRcdGlmICggYSA9PT0gJ2VkaXQnICkge1xuXHRcdFx0XHRcdFx0Ly9HbG9iYWwuc2V0VVJMVG9Ccm93c2VyKCBHbG9iYWwuZ2V0QmFzZVVSTCgpICsgJyMhbT0nICsgdGhpcy52aWV3SWQgKyAnJmRhdGU9JyArIHRoaXMuc3RhcnRfZGF0ZV9waWNrZXIuZ2V0RGVmYXVsdEZvcm1hdFZhbHVlKCkgKyAnJm1vZGU9JyArIG1vZGUgKyAnJmE9JyArICduZXcnICtcblx0XHRcdFx0XHRcdEdsb2JhbC5zZXRVUkxUb0Jyb3dzZXIoIEdsb2JhbC5nZXRCYXNlVVJMKCkgKyAnIyFtPScgKyB0aGlzLnZpZXdJZCArICcmbW9kZT0nICsgbW9kZSArICcmYT0nICsgJ25ldycgK1xuXHRcdFx0XHRcdFx0XHQnJnRhYj0nICsgdGFiX25hbWUgKTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0Ly9HbG9iYWwuc2V0VVJMVG9Ccm93c2VyKCBHbG9iYWwuZ2V0QmFzZVVSTCgpICsgJyMhbT0nICsgdGhpcy52aWV3SWQgKyAnJmRhdGU9JyArIHRoaXMuc3RhcnRfZGF0ZV9waWNrZXIuZ2V0RGVmYXVsdEZvcm1hdFZhbHVlKCkgKyAnJm1vZGU9JyArIG1vZGUgKyAnJmE9JyArIGEgK1xuXHRcdFx0XHRcdFx0R2xvYmFsLnNldFVSTFRvQnJvd3NlciggR2xvYmFsLmdldEJhc2VVUkwoKSArICcjIW09JyArIHRoaXMudmlld0lkICsgJyZtb2RlPScgKyBtb2RlICsgJyZhPScgKyBhICtcblx0XHRcdFx0XHRcdFx0JyZ0YWI9JyArIHRhYl9uYW1lICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Ly9HbG9iYWwuc2V0VVJMVG9Ccm93c2VyKCBHbG9iYWwuZ2V0QmFzZVVSTCgpICsgJyMhbT0nICsgdGhpcy52aWV3SWQgKyAnJmRhdGU9JyArIHRoaXMuc3RhcnRfZGF0ZV9waWNrZXIuZ2V0RGVmYXVsdEZvcm1hdFZhbHVlKCkgKyAnJm1vZGU9JyArIG1vZGUgKTtcblx0XHRcdFx0XHRHbG9iYWwuc2V0VVJMVG9Ccm93c2VyKCBHbG9iYWwuZ2V0QmFzZVVSTCgpICsgJyMhbT0nICsgdGhpcy52aWV3SWQgKyAnJm1vZGU9JyArIG1vZGUgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0fVxuXHR9XG5cblx0Y2xlYXJTZWxlY3Rpb24oIHNldF9kZWZhdWx0X21lbnUgKSB7XG5cdFx0aWYgKCB0aGlzLmdyaWQgJiYgdGhpcy5ncmlkLmdyaWQgKSB7XG5cdFx0XHR0aGlzLmdyaWQuZ3JpZC5qcUdyaWQoICdyZXNldFNlbGVjdGlvbicgKTtcblx0XHR9XG5cblx0XHR0aGlzLnNlbGVjdF9jZWxsc19BcnJheSA9IFtdO1xuXHRcdHRoaXMuc2VsZWN0X2NlbGxsc19hbmRfc2hpZnRzX2FycmF5ID0gW107XG5cdFx0dGhpcy5zZWxlY3RfYWxsX3NoaWZ0c19hcnJheSA9IFtdO1xuXG5cdFx0Ly9Jc3N1ZSAjMzA2NyAtIENhdXNlcyBpbmNvcnJlY3QgY29udGV4dCBtZW51IHRvIGJlIHNldCB3aGVuIHNhdmluZyBhIHNjaGVkdWxlIHdoaWNoIHByb2R1Y2VzIGNvbnRleHQgbWVudSBmbGFzaGluZ1xuXHRcdC8vYW5kIGJ1dHRvbiBzdGF0ZSB0byBjaGFuZ2UuIEhvd2V2ZXIgdGhpcyBjYWxsIGlzIHJlcXVpcmVkIHRvIHByb3Blcmx5IHJlc2V0IG1hc3MgZWRpdCBhbmQgb3RoZXIgY29udGV4dCBtZW51IGJ1dHRvbnMuXG5cdFx0aWYgKCBzZXRfZGVmYXVsdF9tZW51IHx8IHNldF9kZWZhdWx0X21lbnUgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHRoaXMuc2V0RGVmYXVsdE1lbnUoKTtcblx0XHR9XG5cdH1cblxuXHRyZW5kZXIoKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHRzdXBlci5yZW5kZXIoKTtcblxuXHRcdC8vIFZ1ZSBTY2hlZHVsZSBTZXR0aW5ncyBJbml0aWFsaXphdGlvblxuXG5cdFx0dmFyIHNjaGVkdWxlX3NldHRpbmdzX29wdGlvbnMgPSBbXG5cdFx0XHR7XG5cdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ0RhaWx5IFRvdGFscycgKSxcblx0XHRcdFx0aWQ6ICdkYWlseV90b3RhbHNfYnRuJyxcblx0XHRcdFx0bm9fZ3JvdXBfbGFiZWw6IHRydWUsXG5cdFx0XHRcdHZ1ZV9pY29uOiAndHRpY29uIHR0aWNvbi1zZXR0aW5nc19ibGFja18yNGRwJyxcblx0XHRcdFx0YWN0aW9uX2dyb3VwOiAnc2NoZWR1bGVfc2V0dGluZ3MnLFxuXHRcdFx0XHRtdWx0aV9zZWxlY3RfZ3JvdXA6IDIsXG5cdFx0XHRcdHZpc2libGU6IHRydWUsXG5cdFx0XHRcdGNvbW1hbmQ6ICgpID0+IHtcblx0XHRcdFx0XHQvL0Vycm9yOiBVbmNhdWdodCBUeXBlRXJyb3I6IENhbm5vdCBjYWxsIG1ldGhvZCAnY2xlYXJHcmlkRGF0YScgb2YgbnVsbCBpbiAvaW50ZXJmYWNlL2h0bWw1L2luZGV4LnBocD9kZXNrdG9wPTEjIW09U2NoZWR1bGUmZGF0ZT0yMDE1MDExOCZtb2RlPXdlZWsgbGluZSA2OTQ0XG5cdFx0XHRcdFx0aWYgKCAhdGhpcy5jaGVja1NjaGVkdWxlRGF0YSgpIHx8ICF0aGlzLmdyaWQgfHwgIXRoaXMuZ3JpZC5ncmlkICkge1xuXHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHRoaXMuYnVpbGRDYWxlbmRhcnMoIHRydWUgKTtcblx0XHRcdFx0XHR0aGlzLm9uUmVzaXplR3JpZCgpO1xuXHRcdFx0XHRcdHRoaXMuc2V0U2NoZWR1bGVHcmlkUm93U3BhbigpO1xuXHRcdFx0XHRcdHRoaXMuc2V0TW9udGhEYXRlUm93UG9zaXRpb24oKTtcblx0XHRcdFx0XHR0aGlzLnNldEdyaWRDb2x1bW5zV2lkdGgoKTtcblx0XHRcdFx0XHR0aGlzLm9uU2VhcmNoKCB0cnVlICk7IC8vVHJpZ2dlciBzYXZpbmcgb2Ygc2F2ZWQgc2VhcmNoICYgbGF5b3V0LlxuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0e1xuXHRcdFx0XHRsYWJlbDogJC5pMThuLl8oICdXZWVrbHkgVG90YWxzJyApLFxuXHRcdFx0XHRpZDogJ3dlZWtseV90b3RhbHNfYnRuJyxcblx0XHRcdFx0bm9fZ3JvdXBfbGFiZWw6IHRydWUsXG5cdFx0XHRcdHZ1ZV9pY29uOiAndHRpY29uIHR0aWNvbi1zZXR0aW5nc19ibGFja18yNGRwJyxcblx0XHRcdFx0YWN0aW9uX2dyb3VwOiAnc2NoZWR1bGVfc2V0dGluZ3MnLFxuXHRcdFx0XHRtdWx0aV9zZWxlY3RfZ3JvdXA6IDMsXG5cdFx0XHRcdHZpc2libGU6IHRydWUsXG5cdFx0XHRcdGNvbW1hbmQ6ICgpID0+IHtcblx0XHRcdFx0XHRpZiAoICF0aGlzLmNoZWNrU2NoZWR1bGVEYXRhKCkgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0dGhpcy5idWlsZENhbGVuZGFycygpO1xuXHRcdFx0XHRcdHRoaXMub25SZXNpemVHcmlkKCk7XG5cdFx0XHRcdFx0dGhpcy5vblNlYXJjaCggdHJ1ZSApOyAvL1RyaWdnZXIgc2F2aW5nIG9mIHNhdmVkIHNlYXJjaCAmIGxheW91dC5cblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdHsgICAvL01vdmVkIHRvIHNlY29uZCBsYXN0IGl0ZW0gaW4gZHJvcGRvd24gYXMgZXJyb3JzIHdlcmUgdHJpZ2dlcmluZyBvbiB0aGUgVnVlSlMgc2lkZSB3aGVuIHZpc2libGUgd2FzIHNldCB0byBmYWxzZSwgYW5kIGl0IHdhcyBmaXJzdCBpdGVtIGluIHRoZSBkcm9wZG93bi5cblx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnU2hvdyBVbnNjaGVkdWxlZCBFbXBsb3llZXMnICksXG5cdFx0XHRcdGlkOiAnYWxsX2VtcGxveWVlX2J0bicsXG5cdFx0XHRcdG5vX2dyb3VwX2xhYmVsOiB0cnVlLFxuXHRcdFx0XHR2dWVfaWNvbjogJ3R0aWNvbiB0dGljb24tc2V0dGluZ3NfYmxhY2tfMjRkcCcsXG5cdFx0XHRcdGFjdGlvbl9ncm91cDogJ3NjaGVkdWxlX3NldHRpbmdzJyxcblx0XHRcdFx0bXVsdGlfc2VsZWN0X2dyb3VwOiAxLFxuXHRcdFx0XHR2aXNpYmxlOiB0aGlzLnVuc2NoZWR1bGVkRW1wbG95ZWVVSVZhbGlkYXRlKCksXG5cdFx0XHRcdC8vIHZpc2libGU6IFBlcm1pc3Npb25NYW5hZ2VyLmNoZWNrVG9wTGV2ZWxQZXJtaXNzaW9uKCAnV2FnZScgKSxcblx0XHRcdFx0Y29tbWFuZDogKCkgPT4ge1xuXHRcdFx0XHRcdHRoaXMuc2VhcmNoKCk7XG5cdFx0XHRcdFx0dGhpcy5vblNlYXJjaCggdHJ1ZSApOyAvL1RyaWdnZXIgc2F2aW5nIG9mIHNhdmVkIHNlYXJjaCAmIGxheW91dC5cblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdHtcblx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnU3RyaWN0IFJhbmdlJyApLFxuXHRcdFx0XHRpZDogJ3N0cmljdF9yYW5nZV9idG4nLFxuXHRcdFx0XHRhY3RpdmU6IHRydWUsXG5cdFx0XHRcdG5vX2dyb3VwX2xhYmVsOiB0cnVlLFxuXHRcdFx0XHR2dWVfaWNvbjogJ3R0aWNvbiB0dGljb24tc2V0dGluZ3NfYmxhY2tfMjRkcCcsXG5cdFx0XHRcdGFjdGlvbl9ncm91cDogJ3NjaGVkdWxlX3NldHRpbmdzJyxcblx0XHRcdFx0bXVsdGlfc2VsZWN0X2dyb3VwOiA0LFxuXHRcdFx0XHR2aXNpYmxlOiB0cnVlLFxuXHRcdFx0XHRjb21tYW5kOiAoKSA9PiB7XG5cdFx0XHRcdFx0JHRoaXMuc2VhcmNoKCBmYWxzZSwgdHJ1ZSApO1xuXHRcdFx0XHRcdCR0aGlzLm9uU2VhcmNoKCB0cnVlICk7IC8vVHJpZ2dlciBzYXZpbmcgb2Ygc2F2ZWQgc2VhcmNoICYgbGF5b3V0LlxuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdF07XG5cblx0XHR2YXIgc2NoZWR1bGVfbW9kZV9vcHRpb25zID0gW1xuXHRcdFx0eyBsYWJlbDogJC5pMThuLl8oICdEYXknICksIHZhbHVlOiAnZGF5JyB9LFxuXHRcdFx0eyBsYWJlbDogJC5pMThuLl8oICdXZWVrJyApLCB2YWx1ZTogJ3dlZWsnIH0sXG5cdFx0XHR7IGxhYmVsOiAkLmkxOG4uXyggJ01vbnRoJyApLCB2YWx1ZTogJ21vbnRoJyB9LFxuXHRcdFx0eyBsYWJlbDogJC5pMThuLl8oICdZZWFyJyApLCB2YWx1ZTogJ3llYXInIH1cblx0XHRdO1xuXG5cdFx0Ly8gSW5pdCBWdWUgY29udHJvbCBiYXJcblxuXHRcdHRoaXMudnVlX2NvbnRyb2xfYmFyX21vdW50X2lkID0gJ3Z1ZS1zY2hlZHVsZS1jb250cm9sLWJhcic7XG5cdFx0dmFyIHJvb3RfcHJvcHMgPSB7XG5cdFx0XHR2aWV3X2lkOiB0aGlzLnZpZXdJZCxcblx0XHRcdHNjaGVkdWxlX3NldHRpbmdzX29wdGlvbnM6IHNjaGVkdWxlX3NldHRpbmdzX29wdGlvbnMsXG5cdFx0XHRzY2hlZHVsZV9tb2RlX29wdGlvbnM6IHNjaGVkdWxlX21vZGVfb3B0aW9ucyxcblx0XHR9XG5cblx0XHRUVFZ1ZVV0aWxzLm1vdW50Q29tcG9uZW50KCB0aGlzLnZ1ZV9jb250cm9sX2Jhcl9tb3VudF9pZCwgU2NoZWR1bGVDb250cm9sQmFyLCByb290X3Byb3BzICk7XG5cblx0XHR2YXIgZGF0ZV9jaG9vc2VyX2RpdiA9ICQoICcuc2NoZWR1bGUtdmlldyAuZGF0ZS1jaG9vc2VyLWRpdicgKTtcblxuXHRcdC8vVGhlIFZ1ZSBTY2hlZHVsZUNvbnRyb2xCYXIgbWF5IGFscmVhZHkgY29udGFpbiBhIGRhdGUgcGlja2VyIGZyb20gYSBwcmV2aW91cyBwYWdlIGxvYWQuXG5cdFx0Ly9UaGUgcGFyZW50IGRpdiBuZWVkcyBhbGwgY2hpbGRyZW4gcmVtb3ZlZCB0byBwcmV2ZW50IG11bHRpcGxlIGRhdGUgcGlja2VycyBmcm9tIGJlaW5nIGFkZGVkLlxuXHRcdGRhdGVfY2hvb3Nlcl9kaXYuZW1wdHkoKTsgLy9UT0RPOiBUZW1wIGhhY2sgdW50aWwgcm9vdCBjYXVzZSBpcyBmb3VuZC4gU2VlbXMgdG8gaGFwcGVuIG9uIHdlYnBhY2sgcHJvZCBidXQgbm90IGJ1aWxkOmRldjp3YXRjaC5cblxuXHRcdC8vQ3JlYXRlIFN0YXJ0IERhdGUgUGlja2VyXG5cdFx0dGhpcy5zdGFydF9kYXRlX3BpY2tlciA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuREFURV9QSUNLRVIgKTtcblx0XHR0aGlzLnN0YXJ0X2RhdGVfcGlja2VyLlREYXRlUGlja2VyKCB7IGZpZWxkOiAnc3RhcnRfZGF0ZScgfSApO1xuXHRcdHZhciBkYXRlX2Nob29zZXIgPSAkKCAnPHNwYW4gY2xhc3M9XFwnbGFiZWxcXCc+JyArICQuaTE4bi5fKCAnRGF0ZScgKSArICc6PC9zcGFuPicgK1xuXHRcdFx0JzxpbWcgY2xhc3M9XFwnbGVmdC1hcnJvdyBhcnJvd1xcJyBzcmM9JyArIEdsb2JhbC5nZXRSZWFsSW1hZ2VQYXRoKCAnaW1hZ2VzL2xlZnRfYXJyb3cuc3ZnJyApICsgJz4nICtcblx0XHRcdCc8ZGl2IGNsYXNzPVxcJ2RhdGUtcGlja2VyLWRpdlxcJz48L2Rpdj4nICtcblx0XHRcdCc8aW1nIGNsYXNzPVxcJ3JpZ2h0LWFycm93IGFycm93XFwnIHNyYz0nICsgR2xvYmFsLmdldFJlYWxJbWFnZVBhdGgoICdpbWFnZXMvcmlnaHRfYXJyb3cuc3ZnJyApICsgJz4nICk7XG5cblx0XHRkYXRlX2Nob29zZXJfZGl2LmFwcGVuZCggZGF0ZV9jaG9vc2VyICk7XG5cdFx0ZGF0ZV9jaG9vc2VyX2Rpdi5maW5kKCAnLmRhdGUtcGlja2VyLWRpdicgKS5hcHBlbmQoIHRoaXMuc3RhcnRfZGF0ZV9waWNrZXIgKTtcblxuXHRcdHZhciBkYXRlX2xlZnRfYXJyb3cgPSBkYXRlX2Nob29zZXJfZGl2LmZpbmQoICcubGVmdC1hcnJvdycgKTtcblx0XHR2YXIgZGF0ZV9yaWdodF9hcnJvdyA9IGRhdGVfY2hvb3Nlcl9kaXYuZmluZCggJy5yaWdodC1hcnJvdycgKTtcblxuXHRcdGRhdGVfbGVmdF9hcnJvdy5iaW5kKCAnY2xpY2snLCBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBtb2RlID0gJHRoaXMuZ2V0TW9kZSgpO1xuXHRcdFx0dmFyIG5ld19kYXRlO1xuXHRcdFx0dmFyIHNlbGVjdF9kYXRlID0gJHRoaXMuc3RhcnRfZGF0ZTtcblxuXHRcdFx0JHRoaXMuY2xlYXJTZWxlY3Rpb24oKTtcblxuXHRcdFx0aWYgKCAhc2VsZWN0X2RhdGUgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0c3dpdGNoICggbW9kZSApIHtcblx0XHRcdFx0Y2FzZSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5XRUVLOlxuXHRcdFx0XHRcdHZhciBzZWxlY3RfZGF0ZSA9IEdsb2JhbC5zdHJUb0RhdGUoICggKCAkdGhpcy5nZXRTZWxlY3REYXRlKCkgKSA/ICR0aGlzLmdldFNlbGVjdERhdGUoKSA6IG5ldyBEYXRlKCkuZm9ybWF0KCkgKSApO1xuXHRcdFx0XHRcdG5ld19kYXRlID0gbmV3IERhdGUoIG5ldyBEYXRlKCBzZWxlY3RfZGF0ZS5nZXRUaW1lKCkgKS5zZXREYXRlKCBzZWxlY3RfZGF0ZS5nZXREYXRlKCkgLSA3ICkgKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5ZRUFSOlxuXHRcdFx0XHRcdG5ld19kYXRlID0gbmV3IERhdGUoIG5ldyBEYXRlKCBzZWxlY3RfZGF0ZS5nZXRUaW1lKCkgKS5zZXREYXRlKCBzZWxlY3RfZGF0ZS5nZXREYXRlKCkgLSA1NiApICk7IC8vOCB3ZWVrcy5cblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSBTY2hlZHVsZVZpZXdDb250cm9sbGVyTW9kZS5EQVk6XG5cdFx0XHRcdFx0bmV3X2RhdGUgPSBuZXcgRGF0ZSggbmV3IERhdGUoIHNlbGVjdF9kYXRlLmdldFRpbWUoKSApLnNldERhdGUoIHNlbGVjdF9kYXRlLmdldERhdGUoKSAtIDEgKSApO1xuXHRcdFx0XHRcdGJyZWFrXG5cdFx0XHRcdGNhc2UgU2NoZWR1bGVWaWV3Q29udHJvbGxlck1vZGUuTU9OVEg6XG5cdFx0XHRcdFx0aWYgKCAkdGhpcy5zZXR0aW5nc19tZW51LmdldEJ1dHRvbiggJ3N0cmljdF9yYW5nZV9idG4nICkuYWN0aXZlICkge1xuXHRcdFx0XHRcdFx0bmV3X2RhdGUgPSBuZXcgRGF0ZSggbmV3IERhdGUoIHNlbGVjdF9kYXRlLmdldFRpbWUoKSApLnNldERhdGUoIHNlbGVjdF9kYXRlLmdldERhdGUoKSAtIDEgKSApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRuZXdfZGF0ZSA9IG5ldyBEYXRlKCBuZXcgRGF0ZSggc2VsZWN0X2RhdGUuZ2V0VGltZSgpICkuc2V0RGF0ZSggc2VsZWN0X2RhdGUuZ2V0RGF0ZSgpIC0gMzYgKSApOyAvLzUgd2Vla3MgKyAxIGRheSBzYW1lIGFzIGdvaW5nIGZvcndhcmRcbiAgICAgICAgICAgICAgICAgICAgfVxuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdG5ld19kYXRlID0gbmV3IERhdGUoIG5ldyBEYXRlKCBzZWxlY3RfZGF0ZS5nZXRUaW1lKCkgKS5zZXREYXRlKCBzZWxlY3RfZGF0ZS5nZXREYXRlKCkgLSAxICkgKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHRcdCR0aGlzLnNldERhdGVQaWNrZXJWYWx1ZSggbmV3X2RhdGUuZm9ybWF0KCkgKTtcblx0XHRcdC8vJHRoaXMuc2V0RGF0ZVVybCgpO1xuXG5cdFx0XHQvLyR0aGlzLmJ1aWxkQ2FsZW5kYXJzKCk7XG5cdFx0XHQkdGhpcy5zZWFyY2goIGZhbHNlLCB0cnVlICk7XG5cdFx0fSApO1xuXG5cdFx0ZGF0ZV9yaWdodF9hcnJvdy5iaW5kKCAnY2xpY2snLCBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBtb2RlID0gJHRoaXMuZ2V0TW9kZSgpO1xuXHRcdFx0dmFyIHNlbGVjdF9kYXRlID0gJHRoaXMuZW5kX2RhdGU7XG5cdFx0XHR2YXIgbmV3X2RhdGU7XG5cdFx0XHRpZiAoICFzZWxlY3RfZGF0ZSApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHQkdGhpcy5jbGVhclNlbGVjdGlvbigpO1xuXG5cdFx0XHRzd2l0Y2ggKCBtb2RlICkge1xuXHRcdFx0XHRjYXNlIFNjaGVkdWxlVmlld0NvbnRyb2xsZXJNb2RlLldFRUs6XG5cdFx0XHRcdFx0dmFyIHNlbGVjdF9kYXRlID0gR2xvYmFsLnN0clRvRGF0ZSggKCAoICR0aGlzLmdldFNlbGVjdERhdGUoKSApID8gJHRoaXMuZ2V0U2VsZWN0RGF0ZSgpIDogbmV3IERhdGUoKS5mb3JtYXQoKSApICk7XG5cdFx0XHRcdFx0bmV3X2RhdGUgPSBuZXcgRGF0ZSggbmV3IERhdGUoIHNlbGVjdF9kYXRlLmdldFRpbWUoKSApLnNldERhdGUoIHNlbGVjdF9kYXRlLmdldERhdGUoKSArIDcgKSApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIFNjaGVkdWxlVmlld0NvbnRyb2xsZXJNb2RlLllFQVI6XG5cdFx0XHRcdFx0bmV3X2RhdGUgPSBuZXcgRGF0ZSggbmV3IERhdGUoIHNlbGVjdF9kYXRlLmdldFRpbWUoKSApLnNldERhdGUoIHNlbGVjdF9kYXRlLmdldERhdGUoKSArIDU2ICkgKTsgLy84IHdlZWtzXG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgU2NoZWR1bGVWaWV3Q29udHJvbGxlck1vZGUuREFZOlxuXHRcdFx0XHRcdGlmICggJHRoaXMuc2V0dGluZ3NfbWVudS5nZXRCdXR0b24oICdzdHJpY3RfcmFuZ2VfYnRuJyApLmFjdGl2ZSApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld19kYXRlID0gbmV3IERhdGUoIG5ldyBEYXRlKCBzZWxlY3RfZGF0ZS5nZXRUaW1lKCkgKS5zZXREYXRlKCBzZWxlY3RfZGF0ZS5nZXREYXRlKCkgKyAxICkgKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld19kYXRlID0gbmV3IERhdGUoIG5ldyBEYXRlKCBzZWxlY3RfZGF0ZS5nZXRUaW1lKCkgKS5zZXREYXRlKCBzZWxlY3RfZGF0ZS5nZXREYXRlKCkgKSApO1xuICAgICAgICAgICAgICAgICAgICB9XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgU2NoZWR1bGVWaWV3Q29udHJvbGxlck1vZGUuTU9OVEg6XG5cdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0bmV3X2RhdGUgPSBuZXcgRGF0ZSggbmV3IERhdGUoIHNlbGVjdF9kYXRlLmdldFRpbWUoKSApLnNldERhdGUoIHNlbGVjdF9kYXRlLmdldERhdGUoKSArIDEgKSApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXG5cdFx0XHQkdGhpcy5zZXREYXRlUGlja2VyVmFsdWUoIG5ld19kYXRlLmZvcm1hdCgpICk7XG5cdFx0XHQvLyR0aGlzLnNldERhdGVVcmwoKTtcblxuXHRcdFx0Ly8kdGhpcy5idWlsZENhbGVuZGFycygpO1xuXHRcdFx0JHRoaXMuc2VhcmNoKCBmYWxzZSwgdHJ1ZSApO1xuXHRcdH0gKTtcblxuXHRcdHRoaXMuc3RhcnRfZGF0ZV9waWNrZXIuYmluZCggJ2Zvcm1JdGVtQ2hhbmdlJywgZnVuY3Rpb24oKSB7XG5cdFx0XHQvLyR0aGlzLnNldERhdGVVcmwoKTtcblx0XHRcdCR0aGlzLmNsZWFyU2VsZWN0aW9uKCk7XG5cdFx0XHQkdGhpcy5zZWFyY2goIGZhbHNlLCB0cnVlICk7XG5cdFx0fSApO1xuXG5cdFx0Ly9PdmVyd3JpdGUgZXZlbnQgbGlzdGVuZXIgb24gbGF5b3V0IHNlbGVjdG9yIHRvIHByZXZlbnQgd3Jvbmcgc3RhcnQgZGF0ZSBpc3N1ZXMgYnkgcGFzc2luZyB0cnVlIG9uIHVzZXJfZGF0ZV9waWNrZXJfZGF0ZSBpbiBzZWFyY2goKS5cblx0XHQkKCB0aGlzLnNlYXJjaF9wYW5lbC5maW5kKCAnI2xheW91dF9zZWxlY3RvcicgKSApLm9mZiggJ2NoYW5nZScgKS5vbiggJ2NoYW5nZScsIGZ1bmN0aW9uKCkge1xuXHRcdFx0JHRoaXMubGF5b3V0X2NoYW5nZWQgPSB0cnVlO1xuXG5cdFx0XHR2YXIgc2VsZWN0SWQgPSAkdGhpcy5zZWFyY2hfcGFuZWwuZmluZCggJyNsYXlvdXRfc2VsZWN0b3InICkuZmluZCggJ29wdGlvbjpzZWxlY3RlZCcgKS5hdHRyKCAndmFsdWUnICk7XG5cdFx0XHR2YXIgbGF5b3V0c19hcnJheSA9ICR0aGlzLnNlYXJjaF9wYW5lbC5nZXRMYXlvdXRzQXJyYXkoKTtcblx0XHRcdHZhciBsZW4gPSBsYXlvdXRzX2FycmF5Lmxlbmd0aDtcblx0XHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0XHR2YXIgaXRlbSA9IGxheW91dHNfYXJyYXlbaV07XG5cblx0XHRcdFx0aWYgKCBpdGVtLmlkID09IHNlbGVjdElkICkge1xuXHRcdFx0XHRcdCR0aGlzLnNlbGVjdF9sYXlvdXQgPSBpdGVtO1xuXHRcdFx0XHRcdCR0aGlzLnNldFNlbGVjdExheW91dCgpO1xuXHRcdFx0XHRcdCR0aGlzLnNlYXJjaCggZmFsc2UsIHRydWUgKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cdFx0XHRHbG9iYWwudHJpZ2dlckFuYWx5dGljc05hdmlnYXRpb25PdGhlciggJ3NlYXJjaHBhbmVsOmxheW91dF9jaGFuZ2UnLCAnY2xpY2snLCAkdGhpcy52aWV3SWQgKTtcblx0XHR9ICk7XG5cblx0XHQvLyBWdWUgZHVtbXkgaW50ZXJmYWNlIG9iamVjdHMgZm9yIGxlZ2FjeTwtPm5ldyB2dWUgbWVudXMuXG5cdFx0Ly8gVE9ETzogSW1wcm92ZSB0aGlzIGJ5IHJlcGxhY2luZyB3aXRoIEVTNiBjbGFzc2VzLCBhbmQgaGF2ZSBhIHBhcmVudCBjbGFzcyBvZiBqUXVlcnlEdW1teSwgd2l0aCBtZXRob2RzIGZvciBnZXQsIHNldCBldGMsIGJ1dCB0aWUgdGhlbSBpbiB3aXRoIHRoZSB2aWV3IGlkIC8gb3B0aW9uIGJhciBpZCwgYW5kIGJ1dHRvbiBpZC5cblxuXHRcdHRoaXMudG9nZ2xlX2J1dHRvbiA9IChmdW5jdGlvbiggY29udGV4dCApIHtcblx0XHRcdHZhciBfdmFsdWUgPSAnd2Vlayc7XG5cdFx0XHRjb250ZXh0LmV2ZW50X2J1cy5vbiggY29udGV4dC52dWVfY29udHJvbF9iYXJfbW91bnRfaWQsICdzY2hlZHVsZU1vZGVPbkNoYW5nZScsIHVwZGF0ZVZhbHVlT25DaGFuZ2UsIFRURXZlbnRCdXNTdGF0aWNzLkFVVE9fQ0xFQVJfT05fRVhJVCApO1xuXG5cblx0XHRcdGZ1bmN0aW9uIHVwZGF0ZVZhbHVlT25DaGFuZ2UoIGV2ZW50X2RhdGEgKSB7XG5cdFx0XHRcdERlYnVnLlRleHQoICdUb2dnbGUgYnV0dG9uIHZhbHVlIHVwZGF0ZSEgQ2hhbmdlIGV2ZW50IHJlY2VpdmVkLiAoJysgZXZlbnRfZGF0YSArJykuJywgJ1NjaGVkdWxlVmlld0NvbnRyb2xsZXIuanMnLCAnU2NoZWR1bGVWaWV3Q29udHJvbGxlcicsICd1cGRhdGVWYWx1ZU9uQ2hhbmdlJywgMTAgKTtcblx0XHRcdFx0X3ZhbHVlID0gZXZlbnRfZGF0YS52YWx1ZTtcblx0XHRcdH1cblxuXHRcdFx0ZnVuY3Rpb24gZ2V0VmFsdWUoKSB7XG5cdFx0XHRcdHJldHVybiBfdmFsdWU7XG5cdFx0XHR9XG5cblx0XHRcdGZ1bmN0aW9uIHNldFZhbHVlKCBuZXdfdmFsdWUgKSB7XG5cdFx0XHRcdF92YWx1ZSA9IG5ld192YWx1ZTsgLy8gU2V0IGxvY2FsbHkgaW4gdGhlIGJ1dHRvbiBpbW1lZGlhdGVseSwgYmVjYXVzZSBzZXRUb2dnbGVCdXR0b25WYWx1ZSB0cmlnZ2VycyBzZXRUb2dnbGVCdXR0b25Vcmwgd2hpY2ggZ2V0cyB0aGUgdmFsdWUgYmVmb3JlIHRoZSBvcmlnaW5hbCBzZXQgY29tbWFuZCBoYXMgYSBjaGFuY2UgdG8gc2VuZCB0aGUgdXBkYXRlIHRvIHZ1ZSBhbmQgYmFjayBhZ2FpbiB0byB0aGUgZHVtbXkgaW50ZXJmYWNlLlxuXG5cdFx0XHRcdGNvbnRleHQuZXZlbnRfYnVzLmVtaXQoIGNvbnRleHQudnVlX2NvbnRyb2xfYmFyX21vdW50X2lkLCAnc2V0VmFsdWUnLCB7XG5cdFx0XHRcdFx0a2V5OiAnc2NoZWR1bGVfbW9kZV9vcHRpb25zX3NlbGVjdGVkJyxcblx0XHRcdFx0XHR2YWx1ZTogbmV3X3ZhbHVlXG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRnZXRWYWx1ZTogZ2V0VmFsdWUsXG5cdFx0XHRcdHNldFZhbHVlOiBzZXRWYWx1ZVxuXHRcdFx0fVxuXHRcdH0pKHRoaXMpO1xuXG5cdFx0Ly8gc2NoZWR1bGVfc2V0dGluZ3Nfb3B0aW9uc1xuXG5cdFx0dGhpcy5zZXR0aW5nc19tZW51ID0ge1xuXHRcdFx0Ly9JZiBpc3N1ZXMgaGFwcGVuIHdpdGggcmFjZSBjb25kaXRpb25zIGFuZCBleGVjdXRpb24gb3JkZWVyLCB5b3UgY2FuIGxvY2FsbHkgc2V0IHRoZSBhcnJheSB2YWx1ZSB0byB0aGUgc2FtZVxuXHRcdFx0Ly8gYXMgd2hhdCB5b3UgYXJlIGFib3V0IHRvIHNldCB0aGUgVnVlIGNvbXBvbmVudCB0bywgYnV0IHRoaXMgbWlnaHQgaGF2ZSB1bmV4cGVjdGVkIGVmZmVjdHMgb24gdGhlIFZ1ZSByZWFjdGl2ZSBkYXRhLlxuXHRcdFx0Z2V0QnV0dG9uKCBpZCApIHtcblx0XHRcdFx0cmV0dXJuIHNjaGVkdWxlX3NldHRpbmdzX29wdGlvbnMuZmluZCggZWxlbWVudCA9PiBlbGVtZW50LmlkID09PSBpZCApO1xuXHRcdFx0fSxcblx0XHRcdGVuYWJsZUJ1dHRvbiggaWQgKSB7XG5cdFx0XHRcdC8vIHNldCBkaXNhYmxlIHRvIGZhbHNlXG5cdFx0XHRcdCR0aGlzLmV2ZW50X2J1cy5lbWl0KCAkdGhpcy52dWVfY29udHJvbF9iYXJfbW91bnRfaWQsICdzZXRTY2hlZHVsZVNldHRpbmdzU3RhdGUnLCB7XG5cdFx0XHRcdFx0aXRlbV9pZDogaWQsXG5cdFx0XHRcdFx0aXRlbV9maWVsZDogJ2Rpc2FibGVkJyxcblx0XHRcdFx0XHRpdGVtX3ZhbHVlOiBmYWxzZVxuXHRcdFx0XHR9KTtcblx0XHRcdH0sXG5cdFx0XHRkaXNhYmxlQnV0dG9uKCBpZCApIHtcblx0XHRcdFx0Ly8gc2V0IGRpc2FibGUgdG8gdHJ1ZVxuXHRcdFx0XHQkdGhpcy5ldmVudF9idXMuZW1pdCggJHRoaXMudnVlX2NvbnRyb2xfYmFyX21vdW50X2lkLCAnc2V0U2NoZWR1bGVTZXR0aW5nc1N0YXRlJywge1xuXHRcdFx0XHRcdGl0ZW1faWQ6IGlkLFxuXHRcdFx0XHRcdGl0ZW1fZmllbGQ6ICdkaXNhYmxlZCcsXG5cdFx0XHRcdFx0aXRlbV92YWx1ZTogdHJ1ZVxuXHRcdFx0XHR9KTtcblx0XHRcdH0sXG5cdFx0XHRhY3RpdmF0ZUJ1dHRvbiggaWQgKSB7XG5cdFx0XHRcdC8vIHNldCBhY3RpdmUgdG8gdHJ1ZVxuXHRcdFx0XHQkdGhpcy5ldmVudF9idXMuZW1pdCggJHRoaXMudnVlX2NvbnRyb2xfYmFyX21vdW50X2lkLCAnc2V0U2V0dGluZ0FjdGl2ZScsIHtcblx0XHRcdFx0XHRpdGVtX2lkOiBpZFxuXHRcdFx0XHR9KTtcblx0XHRcdH0sXG5cdFx0XHRkZWFjdGl2YXRlQnV0dG9uKCBpZCApIHtcblx0XHRcdFx0Ly8gc2V0IGFjdGl2ZSB0byBmYWxzZVxuXHRcdFx0XHQkdGhpcy5ldmVudF9idXMuZW1pdCggJHRoaXMudnVlX2NvbnRyb2xfYmFyX21vdW50X2lkLCAnc2V0U2V0dGluZ0RlYWN0aXZhdGVkJywge1xuXHRcdFx0XHRcdGl0ZW1faWQ6IGlkXG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIHNjaGVkdWxlTW9kZU9uQ2hhbmdlSGFuZGxlciggZXZlbnRfZGF0YSApIHtcblx0XHRcdERlYnVnLlRleHQoICdTY2hlZHVsZSBtb2RlIGNoYW5nZSBldmVudCByZWNlaXZlZC4gKCcrIGV2ZW50X2RhdGEgKycpLicsICdTY2hlZHVsZVZpZXdDb250cm9sbGVyLmpzJywgJ1NjaGVkdWxlVmlld0NvbnRyb2xsZXInLCAnc2NoZWR1bGVNb2RlT25DaGFuZ2VIYW5kbGVyJywgMTAgKTtcblxuXHRcdFx0JHRoaXMuc2Nyb2xsX3Bvc2l0aW9uID0gMDtcblx0XHRcdCR0aGlzLnNlbGVjdF9hbGxfc2hpZnRzX2FycmF5ID0gW107XG5cdFx0XHQkdGhpcy5zZWxlY3Rfc2hpZnRzX2FycmF5ID0gW107XG5cdFx0XHQkdGhpcy5zZWxlY3RfcmVjdXJyaW5nX3NoaWZ0c19hcnJheSA9IFtdO1xuXG5cdFx0XHQkdGhpcy5zZXRUb2dnbGVCdXR0b25VcmwoKTtcblx0XHRcdCR0aGlzLnNlYXJjaCggdHJ1ZSwgdHJ1ZSApO1xuXHRcdFx0JHRoaXMub25TZWFyY2goIHRydWUgKTsgLy9UcmlnZ2VyIHNhdmluZyBvZiBzYXZlZCBzZWFyY2ggJiBsYXlvdXQsIGJ1dCBkbyBub3Qgc2VhcmNoIHRvIHN0b3AgZG91YmxlIHNlYXJjaCBjYWxscy5cblx0XHR9XG5cblx0XHR0aGlzLmV2ZW50X2J1cy5vbiggdGhpcy52dWVfY29udHJvbF9iYXJfbW91bnRfaWQsICdzY2hlZHVsZU1vZGVPbkNoYW5nZScsIHNjaGVkdWxlTW9kZU9uQ2hhbmdlSGFuZGxlciwgVFRFdmVudEJ1c1N0YXRpY3MuQVVUT19DTEVBUl9PTl9FWElUICk7XG5cblx0fVxuXG5cdGNoZWNrU2NoZWR1bGVEYXRhKCkge1xuXHRcdGlmICggdGhpcy5mdWxsX3NjaGVkdWxlX2RhdGEgPT09IHRydWUgKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHRzaG93V2Vla2x5VG90YWwoKSB7XG5cdFx0dmFyIHNob3dfd2Vla2x5X3RvdGFsID0gdGhpcy5zZXR0aW5nc19tZW51LmdldEJ1dHRvbiggJ3dlZWtseV90b3RhbHNfYnRuJyApLmFjdGl2ZSAmJiAhdGhpcy5zZXR0aW5nc19tZW51LmdldEJ1dHRvbiggJ3dlZWtseV90b3RhbHNfYnRuJyApLmRpc2FibGVkO1xuXG5cdFx0aWYgKCAhc2hvd193ZWVrbHlfdG90YWwgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIHNoaWZ0cyA9IDA7XG5cdFx0dmFyIGFic2VuY2VzID0gMDtcblx0XHR2YXIgdG90YWxfdGltZSA9IDA7XG5cdFx0dmFyIHRvdGFsX3dhZ2UgPSAwO1xuLy9cdFx0ICB2YXIgaXNfZGF0ZV9yb3cgPSBmYWxzZTtcbi8vXHRcdCAgdmFyIGN1cnJlbnRfa2V5ID0gW107XG5cblx0XHR2YXIgbW9kZSA9IHRoaXMuZ2V0TW9kZSgpO1xuXG5cdFx0dmFyIGxlbiA9IHRoaXMuc2NoZWR1bGVfc291cmNlLmxlbmd0aDtcblxuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0dmFyIHJvdyA9IHRoaXMuc2NoZWR1bGVfc291cmNlW2ldO1xuXG5cdFx0XHRpZiAoIHJvdy50eXBlID09PSBTY2hlZHVsZVZpZXdDb250cm9sbGVyUm93VHlwZS5EQVRFICkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0Zm9yICggdmFyIGtleSBpbiByb3cgKSB7XG5cblx0XHRcdFx0Ly9BcyBkYXRhIGNvbWVzIGZyb20gdGhlIGdyaWQsIHdlIGNhbid0IGJlIHN1cmUgb2YgdGhlIHR5cGVzIG9mIGFueSBkYXRhIHdpdGhpbiBpdC4gKFNhbWUgZ29lcyBmb3IgaXRlbSBiZWxvdylcblx0XHRcdFx0dmFyIGRhdGEgPSBHbG9iYWwuaXNTZXQoIHJvd1trZXldICkgPyByb3dba2V5XSA6ICcnO1xuXG5cdFx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCBkYXRhLnVzZXJfaWQgKSB8fCAoIEdsb2JhbC5pc0FycmF5KCBkYXRhICkgJiYgbW9kZSA9PT0gU2NoZWR1bGVWaWV3Q29udHJvbGxlck1vZGUuWUVBUiAmJiBkYXRhLmV2ZXJ5KCBpdGVtID0+IGl0ZW0udG90YWxfdGltZV93YWdlICkgKSApIHtcblxuXHRcdFx0XHRcdGlmICggbW9kZSA9PT0gU2NoZWR1bGVWaWV3Q29udHJvbGxlck1vZGUuWUVBUiApIHtcblx0XHRcdFx0XHRcdHZhciBkYXRhX2xlbiA9IGRhdGEubGVuZ3RoO1xuXHRcdFx0XHRcdFx0Zm9yICggdmFyIGogPSAwOyBqIDwgZGF0YV9sZW47IGorKyApIHtcblx0XHRcdFx0XHRcdFx0dmFyIGl0ZW0gPSBkYXRhW2pdO1xuXHRcdFx0XHRcdFx0XHRpdGVtLnRvdGFsX3RpbWVfd2FnZSA9IHBhcnNlRmxvYXQoIGl0ZW0udG90YWxfdGltZV93YWdlICk7XG5cdFx0XHRcdFx0XHRcdGl0ZW0udG90YWxfdGltZSA9IHBhcnNlRmxvYXQoIGl0ZW0udG90YWxfdGltZSApO1xuXG5cdFx0XHRcdFx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCBpdGVtLnVzZXJfaWQgKSApIHtcblx0XHRcdFx0XHRcdFx0XHR0b3RhbF93YWdlID0gKCBpdGVtLnRvdGFsX3RpbWVfd2FnZSArIHRvdGFsX3dhZ2UgKTtcblx0XHRcdFx0XHRcdFx0XHRpZiAoIGl0ZW0uc3RhdHVzX2lkID09IDEwICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0dG90YWxfdGltZSA9ICggaXRlbS50b3RhbF90aW1lICsgdG90YWxfdGltZSApO1xuXHRcdFx0XHRcdFx0XHRcdFx0c2hpZnRzID0gc2hpZnRzICsgMTtcblx0XHRcdFx0XHRcdFx0XHR9IGVsc2UgaWYgKCBkYXRhLnN0YXR1c19pZCA9PSAyMCAmJiBkYXRhLmFic2VuY2VfcG9saWN5X2lkICE9IFRUVVVJRC56ZXJvX2lkICYmIGRhdGEuYWJzZW5jZV9wb2xpY3lfaWQgIT0gVFRVVUlELm5vdF9leGlzdF9pZCApIHsgLy8mJiBkYXRhLnRvdGFsX3RpbWVfd2FnZSAhPSAwXG5cdFx0XHRcdFx0XHRcdFx0XHR0b3RhbF90aW1lID0gKCBpdGVtLnRvdGFsX3RpbWUgKyB0b3RhbF90aW1lICk7XG5cdFx0XHRcdFx0XHRcdFx0XHRhYnNlbmNlcyA9IGFic2VuY2VzICsgMTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0ZGF0YS50b3RhbF90aW1lX3dhZ2UgPSBwYXJzZUZsb2F0KCBkYXRhLnRvdGFsX3RpbWVfd2FnZSApO1xuXHRcdFx0XHRcdFx0ZGF0YS50b3RhbF90aW1lID0gcGFyc2VGbG9hdCggZGF0YS50b3RhbF90aW1lICk7XG5cdFx0XHRcdFx0XHR0b3RhbF93YWdlID0gKCBkYXRhLnRvdGFsX3RpbWVfd2FnZSArIHRvdGFsX3dhZ2UgKTtcblx0XHRcdFx0XHRcdGlmICggZGF0YS5zdGF0dXNfaWQgPT0gMTAgKSB7XG5cdFx0XHRcdFx0XHRcdHRvdGFsX3RpbWUgPSAoIGRhdGEudG90YWxfdGltZSArIHRvdGFsX3RpbWUgKTtcblx0XHRcdFx0XHRcdFx0c2hpZnRzID0gc2hpZnRzICsgMTtcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoIGRhdGEuc3RhdHVzX2lkID09IDIwICYmIGRhdGEuYWJzZW5jZV9wb2xpY3lfaWQgIT0gVFRVVUlELnplcm9faWQgJiYgZGF0YS5hYnNlbmNlX3BvbGljeV9pZCAhPSBUVFVVSUQubm90X2V4aXN0X2lkICkgeyAvLyYmIGRhdGEudG90YWxfdGltZV93YWdlICE9IDBcblx0XHRcdFx0XHRcdFx0dG90YWxfdGltZSA9ICggZGF0YS50b3RhbF90aW1lICsgdG90YWxfdGltZSApO1xuXHRcdFx0XHRcdFx0XHRhYnNlbmNlcyA9IGFic2VuY2VzICsgMTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0fSBlbHNlIGlmICggR2xvYmFsLmlzU2V0KCBkYXRhLnNoaWZ0cyApICkge1xuXHRcdFx0XHRcdGRhdGEudG90YWxfdGltZV93YWdlID0gcGFyc2VGbG9hdCggZGF0YS50b3RhbF90aW1lX3dhZ2UgKTtcblx0XHRcdFx0XHRkYXRhLnRvdGFsX3RpbWUgPSBwYXJzZUZsb2F0KCBkYXRhLnRvdGFsX3RpbWUgKTtcblxuXHRcdFx0XHRcdHRvdGFsX3RpbWUgPSAoIGRhdGEudG90YWxfdGltZSArIHRvdGFsX3RpbWUgKTtcblx0XHRcdFx0XHR0b3RhbF93YWdlID0gKCBkYXRhLnRvdGFsX3RpbWVfd2FnZSArIHRvdGFsX3dhZ2UgKTtcblxuXHRcdFx0XHRcdHNoaWZ0cyA9IHNoaWZ0cyArIGRhdGEuc2hpZnRzO1xuXHRcdFx0XHRcdGFic2VuY2VzID0gYWJzZW5jZXMgKyBkYXRhLmFic2VuY2VzO1xuXHRcdFx0XHR9IGVsc2UgaWYgKCByb3cudHlwZSAhPT0gU2NoZWR1bGVWaWV3Q29udHJvbGxlclJvd1R5cGUuREFURSApIHtcblxuXHRcdFx0XHR9IGVsc2Uge1xuLy9cdFx0XHRcdFx0ICBjdXJyZW50X2tleVtrZXldID0gcm93W2tleV07XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0cm93LnRvdGFsX3RpbWUgPSBHbG9iYWwuZ2V0VGltZVVuaXQoIHRvdGFsX3RpbWUgKTtcblx0XHRcdHJvdy50b3RhbF90aW1lX3dhZ2UgPSBMb2NhbENhY2hlRGF0YS5nZXRDdXJyZW50Q3VycmVuY3lTeW1ib2woKSArIEdsb2JhbC5Nb25leVJvdW5kKCB0b3RhbF93YWdlICk7XG5cdFx0XHQvL1ZpZXdNYW5hZ2VyVXRpbC5nZXRUaW1lVW5pdCh0b3RhbFRpbWUpO1xuXHRcdFx0cm93LnNoaWZ0cyA9IHNoaWZ0cztcblx0XHRcdHJvdy5hYnNlbmNlcyA9IGFic2VuY2VzO1xuXG5cdFx0XHR0b3RhbF90aW1lID0gMDtcblx0XHRcdHRvdGFsX3dhZ2UgPSAwO1xuXHRcdFx0c2hpZnRzID0gMDtcblx0XHRcdGFic2VuY2VzID0gMDtcblx0XHR9XG5cdH1cblxuXHRidWlsZFRvdGFsU2hpZnRzVmFsdWVzKCB0b3RhbF9zaGlmdHNfZGljLCBjdXJyZW50SXRlbSApIHtcblx0XHR2YXIgc3RhcnRfZGF0ZSA9IEdsb2JhbC5zdHJUb0RhdGVUaW1lKCBjdXJyZW50SXRlbS5zdGFydF9kYXRlICk7XG5cdFx0dmFyIGVuZF9kYXRlID0gR2xvYmFsLnN0clRvRGF0ZVRpbWUoIGN1cnJlbnRJdGVtLmVuZF9kYXRlICk7XG5cdFx0dmFyIHN0YXJ0X3RpbWVfbWluID0gc3RhcnRfZGF0ZS5nZXRNaW51dGVzKCk7XG5cdFx0dmFyIGVuZF90aW1lX21pbiA9IGVuZF9kYXRlLmdldE1pbnV0ZXMoKTtcblxuXHRcdHN0YXJ0X2RhdGUuc2V0TWludXRlcyggMCApO1xuXHRcdGVuZF9kYXRlLnNldE1pbnV0ZXMoIDAgKTtcblxuXHRcdHZhciBzdGFydF90aW1lID0gc3RhcnRfZGF0ZS5mb3JtYXQoICdoQScgKTtcblx0XHR2YXIgZW5kX3RpbWUgPSBlbmRfZGF0ZS5mb3JtYXQoICdoQScgKTtcblxuXHRcdHZhciB0aW1lX29mZnNldCA9IE1hdGguY2VpbCggZ2V0VGltZU9mZnNldCggc3RhcnRfZGF0ZSwgZW5kX2RhdGUgKSAvIDYwIC8gNjAgKTtcblxuXHRcdHZhciByZXN0X3RpbWU7XG5cdFx0aWYgKCB0aW1lX29mZnNldCA8IDEgKSB7XG5cblx0XHRcdHRvdGFsX3NoaWZ0c19kaWNbZW5kX3RpbWVdLnZhbHVlID0gdG90YWxfc2hpZnRzX2RpY1tlbmRfdGltZV0udmFsdWUgKyBOdW1iZXIoICggZW5kX3RpbWVfbWluIC8gNjAgKS50b0ZpeGVkKCAwICkgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKCBzdGFydF90aW1lX21pbiA9PSAwICkge1xuXG5cdFx0XHRcdHRvdGFsX3NoaWZ0c19kaWNbc3RhcnRfdGltZV0udmFsdWUgPSB0b3RhbF9zaGlmdHNfZGljW3N0YXJ0X3RpbWVdLnZhbHVlICsgMTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRvdGFsX3NoaWZ0c19kaWNbc3RhcnRfdGltZV0udmFsdWUgPSB0b3RhbF9zaGlmdHNfZGljW3N0YXJ0X3RpbWVdLnZhbHVlICsgTnVtYmVyKCAoICggNjAgLSBzdGFydF90aW1lX21pbiApIC9cblx0XHRcdFx0XHQ2MCApLnRvRml4ZWQoIDIgKSApO1xuXHRcdFx0fVxuXG5cdFx0XHRmb3IgKCB2YXIgaSA9IDE7IGkgPCB0aW1lX29mZnNldDsgaSsrICkge1xuXHRcdFx0XHRzdGFydF9kYXRlLnNldEhvdXJzKCBzdGFydF9kYXRlLmdldEhvdXJzKCkgKyAxICk7XG5cdFx0XHRcdC8vc3RhcnRfdGltZSA9IHN0YXJ0X2RhdGUuZm9ybWF0KCAnaGg6bW0gQScgKTtcblx0XHRcdFx0c3RhcnRfdGltZSA9IHN0YXJ0X2RhdGUuZm9ybWF0KCAnaEEnICk7XG5cblx0XHRcdFx0aWYgKCAhdG90YWxfc2hpZnRzX2RpYy5oYXNPd25Qcm9wZXJ0eSggc3RhcnRfdGltZSApICkge1xuXHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCBpID09IHRpbWVfb2Zmc2V0IC0gMSApIHtcblx0XHRcdFx0XHRpZiAoIGVuZF90aW1lX21pbiA+IDAgKSB7XG5cdFx0XHRcdFx0XHR0b3RhbF9zaGlmdHNfZGljW3N0YXJ0X3RpbWVdLnZhbHVlID0gdG90YWxfc2hpZnRzX2RpY1tzdGFydF90aW1lXS52YWx1ZSArIE51bWJlciggKCBlbmRfdGltZV9taW4gL1xuXHRcdFx0XHRcdFx0XHQ2MCApLnRvRml4ZWQoIDIgKSApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHR0b3RhbF9zaGlmdHNfZGljW3N0YXJ0X3RpbWVdLnZhbHVlID0gdG90YWxfc2hpZnRzX2RpY1tzdGFydF90aW1lXS52YWx1ZSArIDE7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHRvdGFsX3NoaWZ0c19kaWNbc3RhcnRfdGltZV0udmFsdWUgPSB0b3RhbF9zaGlmdHNfZGljW3N0YXJ0X3RpbWVdLnZhbHVlICsgMTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cblx0XHR9XG5cblx0XHRmdW5jdGlvbiBnZXRUaW1lT2Zmc2V0KCBzdGFydERhdGUsIGVuZERhdGUgKSB7XG5cdFx0XHRpZiAoICFzdGFydERhdGUgKSB7XG5cdFx0XHRcdHN0YXJ0RGF0ZSA9IG5ldyBEYXRlKCk7XG5cdFx0XHR9XG5cdFx0XHR2YXIgc2VjID0gKCBlbmREYXRlLmdldFRpbWUoKSAtIHN0YXJ0RGF0ZS5nZXRUaW1lKCkgKSAvIDEwMDA7XG5cdFx0XHRyZXR1cm4gc2VjLnRvRml4ZWQoIDAgKTtcblx0XHR9XG5cdH1cblxuXHRzaG93RGFpbHlUb3RhbCgpIHtcblx0XHR2YXIgc2hvd19kYWlseV90b3RhbCA9IHRoaXMuc2V0dGluZ3NfbWVudS5nZXRCdXR0b24oICdkYWlseV90b3RhbHNfYnRuJyApLmFjdGl2ZSAmJiAhdGhpcy5zZXR0aW5nc19tZW51LmdldEJ1dHRvbiggJ2RhaWx5X3RvdGFsc19idG4nICkuZGlzYWJsZWQ7XG5cblx0XHRpZiAoICFzaG93X2RhaWx5X3RvdGFsICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBzdGFydCA9IHRydWU7XG5cdFx0dmFyIHRvdGFsX3JvdyA9IG51bGw7XG5cdFx0dmFyIGNvbHVtbl9rZXlzID0gW107XG5cdFx0dmFyIG92ZXJfYWxsX3RvdGFsX3JvdyA9IHt9O1xuXG5cdFx0dmFyIGRpc3BsYXlfY29sdW1ucyA9IHRoaXMuc2VsZWN0X2xheW91dC5kYXRhLmRpc3BsYXlfY29sdW1ucztcblx0XHR2YXIgZGlzcGxheV9jb2x1bW5zX2xlbiA9IGRpc3BsYXlfY29sdW1ucy5sZW5ndGg7XG5cblx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBkaXNwbGF5X2NvbHVtbnNfbGVuOyBpKysgKSB7XG5cdFx0XHR2YXIgY29sdW1uX25hbWUgPSBkaXNwbGF5X2NvbHVtbnNbaV07XG5cblx0XHRcdGNvbHVtbl9rZXlzLnB1c2goIHsga2V5OiBjb2x1bW5fbmFtZSwgcm93OiBudWxsLCB2YWx1ZTogbnVsbCB9ICk7XG5cblx0XHR9XG5cblx0XHR2YXIgY29sdW1uX2tleXNfbGVuID0gY29sdW1uX2tleXMubGVuZ3RoO1xuXG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgdGhpcy5zY2hlZHVsZV9zb3VyY2UubGVuZ3RoOyBpKysgKSB7XG5cdFx0XHR2YXIgcm93ID0gdGhpcy5zY2hlZHVsZV9zb3VyY2VbaV07XG5cdFx0XHRpZiAoIHN0YXJ0ICkge1xuXG5cdFx0XHRcdGZvciAoIHZhciBqID0gMDsgaiA8IGNvbHVtbl9rZXlzX2xlbjsgaisrICkge1xuXHRcdFx0XHRcdHZhciBjb2x1bW5fa2V5ID0gY29sdW1uX2tleXNbal07XG5cdFx0XHRcdFx0dG90YWxfcm93ID0geyB0eXBlOiBTY2hlZHVsZVZpZXdDb250cm9sbGVyUm93VHlwZS5UT1RBTCB9O1xuXHRcdFx0XHRcdHRvdGFsX3Jvd1tjb2x1bW5fa2V5LmtleV0gPSAkLmkxOG4uXyggJ1RvdGFscycgKTtcblx0XHRcdFx0XHRjb2x1bW5fa2V5LnJvdyA9IHRvdGFsX3Jvdztcblx0XHRcdFx0XHRjb2x1bW5fa2V5LnZhbHVlID0gcm93W2NvbHVtbl9rZXkua2V5XTtcblxuXHRcdFx0XHR9XG5cblx0XHRcdFx0b3Zlcl9hbGxfdG90YWxfcm93ID0geyB0eXBlOiBTY2hlZHVsZVZpZXdDb250cm9sbGVyUm93VHlwZS5UT1RBTCB9O1xuXHRcdFx0XHRvdmVyX2FsbF90b3RhbF9yb3cudXNlcl9mdWxsX25hbWUgPSAkLmkxOG4uXyggJ092ZXJhbGwgVG90YWxzJyApO1xuXHRcdFx0fVxuXG5cdFx0XHRmb3IgKCB2YXIgeSA9IGNvbHVtbl9rZXlzX2xlbiAtIDE7IHkgPj0gMDsgeS0tICkge1xuXG5cdFx0XHRcdGNvbHVtbl9rZXkgPSBjb2x1bW5fa2V5c1t5XTtcblxuXHRcdFx0XHRpZiAoICggcm93W2NvbHVtbl9rZXkua2V5XSAhPT0gY29sdW1uX2tleS52YWx1ZSAmJiBpID4gMCApICYmICFzdGFydCAmJiBpICE9PSAwICkge1xuXG5cdFx0XHRcdFx0dGhpcy5zY2hlZHVsZV9zb3VyY2Uuc3BsaWNlKCBpLCAwLCBjb2x1bW5fa2V5LnJvdyApO1xuXHRcdFx0XHRcdGkgPSBpICsgMTtcblx0XHRcdFx0XHR0b3RhbF9yb3cgPSB7IHR5cGU6IFNjaGVkdWxlVmlld0NvbnRyb2xsZXJSb3dUeXBlLlRPVEFMIH07XG5cdFx0XHRcdFx0dG90YWxfcm93W2NvbHVtbl9rZXkua2V5XSA9ICQuaTE4bi5fKCAnVG90YWxzJyApO1xuXHRcdFx0XHRcdGNvbHVtbl9rZXkucm93ID0gdG90YWxfcm93O1xuXHRcdFx0XHRcdGNvbHVtbl9rZXkudmFsdWUgPSByb3dbY29sdW1uX2tleS5rZXldO1xuXHRcdFx0XHR9XG5cblx0XHRcdH1cblxuXHRcdFx0aWYgKCBzdGFydCApIHtcblx0XHRcdFx0c3RhcnQgPSBmYWxzZTtcblx0XHRcdH1cblx0XHRcdGlmICggcm93LnR5cGUgPT09IFNjaGVkdWxlVmlld0NvbnRyb2xsZXJSb3dUeXBlLkRBVEUgKSB7IC8vZG8gbm90IGNhbGN1bGF0ZSBkYXRlIHJvd1xuXHRcdFx0XHR0aGlzLnNjaGVkdWxlX3NvdXJjZS5zcGxpY2UoIGksIDAsIG92ZXJfYWxsX3RvdGFsX3JvdyApO1xuXHRcdFx0XHRvdmVyX2FsbF90b3RhbF9yb3cgPSB7IHR5cGU6IFNjaGVkdWxlVmlld0NvbnRyb2xsZXJSb3dUeXBlLlRPVEFMIH07XG5cdFx0XHRcdG92ZXJfYWxsX3RvdGFsX3Jvdy51c2VyX2Z1bGxfbmFtZSA9ICQuaTE4bi5fKCAnT3ZlcmFsbCBUb3RhbHMnICk7XG5cdFx0XHRcdGkgPSBpICsgMTtcblxuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0Zm9yICggdmFyIGtleSBpbiByb3cgKSB7XG5cblx0XHRcdFx0dmFyIGRhdGEgPSBHbG9iYWwuaXNTZXQoIHJvd1trZXldICkgPyByb3dba2V5XSA6ICcnO1xuXHRcdFx0XHRmb3IgKCB2YXIgeCA9IDA7IHggPCBjb2x1bW5fa2V5c19sZW47IHgrKyApIHtcblxuXHRcdFx0XHRcdGNvbHVtbl9rZXkgPSBjb2x1bW5fa2V5c1t4XTtcblx0XHRcdFx0XHR0b3RhbF9yb3cgPSBjb2x1bW5fa2V5LnJvdztcblxuXHRcdFx0XHRcdC8vVG90YWwgcm93cyBmb3IgZWFjaCBjb2x1bW5zXG5cdFx0XHRcdFx0aWYgKCBkYXRhICYmIEdsb2JhbC5pc1NldCggZGF0YS51c2VyX2lkICkgKSB7XG5cblx0XHRcdFx0XHRcdHZhciBub19kYXRhX2tleSA9IGtleS5yZXBsYWNlKCAnX2RhdGEnLCAnJyApO1xuXG5cdFx0XHRcdFx0XHR2YXIgdG90YWxfcm93X2tleV9kYXRhID0gdG90YWxfcm93W25vX2RhdGFfa2V5XTtcblxuXHRcdFx0XHRcdFx0aWYgKCAhdG90YWxfcm93X2tleV9kYXRhIHx8ICFHbG9iYWwuaXNTZXQoIHRvdGFsX3Jvd19rZXlfZGF0YS50b3RhbF90aW1lICkgKSB7XG5cdFx0XHRcdFx0XHRcdHRvdGFsX3Jvd1tub19kYXRhX2tleV0gPSB7fTtcblx0XHRcdFx0XHRcdFx0dG90YWxfcm93X2tleV9kYXRhID0gdG90YWxfcm93W25vX2RhdGFfa2V5XTtcblx0XHRcdFx0XHRcdFx0dG90YWxfcm93X2tleV9kYXRhLnRvdGFsX3RpbWUgPSAwO1xuXHRcdFx0XHRcdFx0XHR0b3RhbF9yb3dfa2V5X2RhdGEudG90YWxfc2hpZnRzX2RpYyA9IEdsb2JhbC5jbG9uZSggdGhpcy50b3RhbF9zaGlmdHNfZGljICk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHQvLyMyMzgxIC0gdG90YWxfdGltZSBjYW4gYmUgYSBzdHJpbmcgZnJvbSB0aGUgQVBJXG5cdFx0XHRcdFx0XHRcdHRvdGFsX3Jvd19rZXlfZGF0YS50b3RhbF90aW1lID0gcGFyc2VJbnQoIHRvdGFsX3Jvd19rZXlfZGF0YS50b3RhbF90aW1lICk7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdGlmICggIUdsb2JhbC5pc1NldCggdG90YWxfcm93X2tleV9kYXRhLnNoaWZ0cyApICkge1xuXHRcdFx0XHRcdFx0XHR0b3RhbF9yb3dfa2V5X2RhdGEuc2hpZnRzID0gMDtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCB0b3RhbF9yb3dfa2V5X2RhdGEuYWJzZW5jZXMgKSApIHtcblx0XHRcdFx0XHRcdFx0dG90YWxfcm93X2tleV9kYXRhLmFic2VuY2VzID0gMDtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCB0b3RhbF9yb3dfa2V5X2RhdGEudG90YWxfdGltZV93YWdlICkgKSB7XG5cdFx0XHRcdFx0XHRcdHRvdGFsX3Jvd19rZXlfZGF0YS50b3RhbF90aW1lX3dhZ2UgPSAwO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHR2YXIgcm93X2RhdGEgPSByb3dbbm9fZGF0YV9rZXkgKyAnX2RhdGEnXTtcblx0XHRcdFx0XHRcdC8vIzIzODEgLSB0b3RhbF90aW1lIGNhbiBiZSBhIHN0cmluZyBmcm9tIHRoZSBBUElcblx0XHRcdFx0XHRcdHJvd19kYXRhLnRvdGFsX3RpbWUgPSBwYXJzZUludCggcm93X2RhdGEudG90YWxfdGltZSApO1xuXG5cdFx0XHRcdFx0XHR0b3RhbF9yb3dfa2V5X2RhdGEudG90YWxfdGltZV93YWdlID0gR2xvYmFsLk1vbmV5Um91bmQoIHBhcnNlRmxvYXQoIHBhcnNlRmxvYXQoIHJvd19kYXRhLnRvdGFsX3RpbWVfd2FnZSApICsgcGFyc2VGbG9hdCggdG90YWxfcm93X2tleV9kYXRhLnRvdGFsX3RpbWVfd2FnZSApICkgKTtcblx0XHRcdFx0XHRcdGlmICggcm93X2RhdGEuc3RhdHVzX2lkID09IDEwICkge1xuXHRcdFx0XHRcdFx0XHR0b3RhbF9yb3dfa2V5X2RhdGEudG90YWxfdGltZSA9IHBhcnNlRmxvYXQoIHJvd19kYXRhLnRvdGFsX3RpbWUgKSArIHBhcnNlRmxvYXQoIHRvdGFsX3Jvd19rZXlfZGF0YS50b3RhbF90aW1lICk7XG5cdFx0XHRcdFx0XHRcdHRvdGFsX3Jvd19rZXlfZGF0YS5zaGlmdHMgPSB0b3RhbF9yb3dfa2V5X2RhdGEuc2hpZnRzICsgMTtcblx0XHRcdFx0XHRcdFx0aWYgKCB0aGlzLmdldE1vZGUoKSA9PT0gU2NoZWR1bGVWaWV3Q29udHJvbGxlck1vZGUuREFZICkge1xuXHRcdFx0XHRcdFx0XHRcdHRoaXMuYnVpbGRUb3RhbFNoaWZ0c1ZhbHVlcyggdG90YWxfcm93X2tleV9kYXRhLnRvdGFsX3NoaWZ0c19kaWMsIHJvd1trZXldICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoIHJvd19kYXRhLnN0YXR1c19pZCA9PSAyMCAmJiByb3dfZGF0YS5hYnNlbmNlX3BvbGljeV9pZCAhPSBUVFVVSUQuemVyb19pZCAmJiByb3dfZGF0YS5hYnNlbmNlX3BvbGljeV9pZCAhPSBUVFVVSUQubm90X2V4aXN0X2lkICkgeyAvLyYmIHJvd19kYXRhLnRvdGFsX3RpbWVfd2FnZSAhPSAwXG5cdFx0XHRcdFx0XHRcdHRvdGFsX3Jvd19rZXlfZGF0YS50b3RhbF90aW1lID0gcGFyc2VGbG9hdCggcm93X2RhdGEudG90YWxfdGltZSApICsgcGFyc2VGbG9hdCggdG90YWxfcm93X2tleV9kYXRhLnRvdGFsX3RpbWUgKTtcblx0XHRcdFx0XHRcdFx0dG90YWxfcm93X2tleV9kYXRhLmFic2VuY2VzID0gdG90YWxfcm93X2tleV9kYXRhLmFic2VuY2VzICsgMTtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly9Ub3RhbCByb3dzIGZvciBhbGwgZW1wbG95ZWVzXG5cblx0XHRcdFx0aWYgKCBkYXRhICYmIEdsb2JhbC5pc1NldCggZGF0YS51c2VyX2lkICkgKSB7XG5cblx0XHRcdFx0XHRub19kYXRhX2tleSA9IGtleS5yZXBsYWNlKCAnX2RhdGEnLCAnJyApO1xuXG5cdFx0XHRcdFx0dG90YWxfcm93X2tleV9kYXRhID0gb3Zlcl9hbGxfdG90YWxfcm93W25vX2RhdGFfa2V5XTtcblxuXHRcdFx0XHRcdGlmICggIXRvdGFsX3Jvd19rZXlfZGF0YSB8fCAhR2xvYmFsLmlzU2V0KCB0b3RhbF9yb3dfa2V5X2RhdGEudG90YWxfdGltZSApICkge1xuXHRcdFx0XHRcdFx0b3Zlcl9hbGxfdG90YWxfcm93W25vX2RhdGFfa2V5XSA9IHt9O1xuXHRcdFx0XHRcdFx0dG90YWxfcm93X2tleV9kYXRhID0gb3Zlcl9hbGxfdG90YWxfcm93W25vX2RhdGFfa2V5XTtcblx0XHRcdFx0XHRcdHRvdGFsX3Jvd19rZXlfZGF0YS50b3RhbF90aW1lID0gMDtcblx0XHRcdFx0XHRcdHRvdGFsX3Jvd19rZXlfZGF0YVsndG90YWxfc2hpZnRzX2RpYyddID0gR2xvYmFsLmNsb25lKCB0aGlzLnRvdGFsX3NoaWZ0c19kaWMgKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoICFHbG9iYWwuaXNTZXQoIHRvdGFsX3Jvd19rZXlfZGF0YS5zaGlmdHMgKSApIHtcblx0XHRcdFx0XHRcdHRvdGFsX3Jvd19rZXlfZGF0YS5zaGlmdHMgPSAwO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICggIUdsb2JhbC5pc1NldCggdG90YWxfcm93X2tleV9kYXRhLmFic2VuY2VzICkgKSB7XG5cdFx0XHRcdFx0XHR0b3RhbF9yb3dfa2V5X2RhdGEuYWJzZW5jZXMgPSAwO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICggIUdsb2JhbC5pc1NldCggdG90YWxfcm93X2tleV9kYXRhLnRvdGFsX3RpbWVfd2FnZSApICkge1xuXHRcdFx0XHRcdFx0dG90YWxfcm93X2tleV9kYXRhLnRvdGFsX3RpbWVfd2FnZSA9IDA7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0cm93X2RhdGEgPSByb3dbbm9fZGF0YV9rZXkgKyAnX2RhdGEnXTtcblxuXHRcdFx0XHRcdHRvdGFsX3Jvd19rZXlfZGF0YS50b3RhbF90aW1lX3dhZ2UgPSBHbG9iYWwuTW9uZXlSb3VuZCggcGFyc2VGbG9hdCggcGFyc2VGbG9hdCggcm93X2RhdGEudG90YWxfdGltZV93YWdlICkgKyBwYXJzZUZsb2F0KCB0b3RhbF9yb3dfa2V5X2RhdGEudG90YWxfdGltZV93YWdlICkgKSApO1xuXHRcdFx0XHRcdGlmICggcm93X2RhdGEuc3RhdHVzX2lkID09IDEwICkge1xuXHRcdFx0XHRcdFx0dG90YWxfcm93X2tleV9kYXRhLnRvdGFsX3RpbWUgPSBwYXJzZUZsb2F0KCByb3dfZGF0YS50b3RhbF90aW1lICkgKyBwYXJzZUZsb2F0KCB0b3RhbF9yb3dfa2V5X2RhdGEudG90YWxfdGltZSApO1xuXHRcdFx0XHRcdFx0dG90YWxfcm93X2tleV9kYXRhLnNoaWZ0cyA9IHRvdGFsX3Jvd19rZXlfZGF0YS5zaGlmdHMgKyAxO1xuXHRcdFx0XHRcdFx0aWYgKCB0aGlzLmdldE1vZGUoKSA9PT0gU2NoZWR1bGVWaWV3Q29udHJvbGxlck1vZGUuREFZICkge1xuXHRcdFx0XHRcdFx0XHR0aGlzLmJ1aWxkVG90YWxTaGlmdHNWYWx1ZXMoIHRvdGFsX3Jvd19rZXlfZGF0YS50b3RhbF9zaGlmdHNfZGljLCByb3dba2V5XSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gZWxzZSBpZiAoIHJvd19kYXRhLnN0YXR1c19pZCA9PSAyMCAmJiByb3dfZGF0YS5hYnNlbmNlX3BvbGljeV9pZCAhPSBUVFVVSUQuemVyb19pZCAmJiByb3dfZGF0YS5hYnNlbmNlX3BvbGljeV9pZCAhPSBUVFVVSUQubm90X2V4aXN0X2lkICkgeyAvLyYmIHJvd19kYXRhLnRvdGFsX3RpbWVfd2FnZSAhPSAwXG5cdFx0XHRcdFx0XHR0b3RhbF9yb3dfa2V5X2RhdGEudG90YWxfdGltZSA9IHBhcnNlRmxvYXQoIHJvd19kYXRhLnRvdGFsX3RpbWUgKSArIHBhcnNlRmxvYXQoIHRvdGFsX3Jvd19rZXlfZGF0YS50b3RhbF90aW1lICk7XG5cdFx0XHRcdFx0XHR0b3RhbF9yb3dfa2V5X2RhdGEuYWJzZW5jZXMgPSB0b3RhbF9yb3dfa2V5X2RhdGEuYWJzZW5jZXMgKyAxO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmICggaSA9PT0gdGhpcy5zY2hlZHVsZV9zb3VyY2UubGVuZ3RoIC0gMSApIHtcblx0XHRcdFx0Zm9yICggdmFyIGogPSBjb2x1bW5fa2V5cy5sZW5ndGggLSAxOyBqID49IDA7IGotLSApIHtcblx0XHRcdFx0XHR0aGlzLnNjaGVkdWxlX3NvdXJjZS5wdXNoKCBjb2x1bW5fa2V5c1tqXS5yb3cgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHR0aGlzLnNjaGVkdWxlX3NvdXJjZS5wdXNoKCBvdmVyX2FsbF90b3RhbF9yb3cgKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0YnVpbGRTZWFyY2hGaWVsZHMoKSB7XG5cdFx0c3VwZXIuYnVpbGRTZWFyY2hGaWVsZHMoKTtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXG5cdFx0dmFyIGRlZmF1bHRfYXJncyA9IHsgcGVybWlzc2lvbl9zZWN0aW9uOiAnc2NoZWR1bGUnIH07XG5cblx0XHRpZiAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCB0aGlzLnBlcm1pc3Npb25faWQsICd2aWV3JyApIHx8IFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCB0aGlzLnBlcm1pc3Npb25faWQsICd2aWV3X2NoaWxkJyApICkge1xuXHRcdFx0dGhpcy5zZWFyY2hfZmllbGRzID0gW1xuXHRcdFx0XHRuZXcgU2VhcmNoRmllbGQoIHtcblx0XHRcdFx0XHRsYWJlbDogJC5pMThuLl8oICdTdGF0dXMnICksXG5cdFx0XHRcdFx0aW5fY29sdW1uOiAxLFxuXHRcdFx0XHRcdGZpZWxkOiAnc3RhdHVzX2lkJyxcblx0XHRcdFx0XHRtdWx0aXBsZTogdHJ1ZSxcblx0XHRcdFx0XHRiYXNpY19zZWFyY2g6IHRydWUsXG5cdFx0XHRcdFx0YWR2X3NlYXJjaDogdHJ1ZSxcblx0XHRcdFx0XHRsYXlvdXRfbmFtZTogJ2dsb2JhbF9vcHRpb25fY29sdW1uJyxcblx0XHRcdFx0XHRmb3JtX2l0ZW1fdHlwZTogRm9ybUl0ZW1UeXBlLkFXRVNPTUVfQk9YXG5cdFx0XHRcdH0gKSxcblxuXHRcdFx0XHRuZXcgU2VhcmNoRmllbGQoIHtcblx0XHRcdFx0XHRsYWJlbDogJC5pMThuLl8oICdTY2hlZHVsZSBCcmFuY2gnICksXG5cdFx0XHRcdFx0aW5fY29sdW1uOiAxLFxuXHRcdFx0XHRcdGZpZWxkOiAnc2NoZWR1bGVfYnJhbmNoX2lkcycsXG5cdFx0XHRcdFx0bGF5b3V0X25hbWU6ICdnbG9iYWxfYnJhbmNoJyxcblx0XHRcdFx0XHRhcGlfY2xhc3M6IFRUQVBJLkFQSUJyYW5jaCxcblx0XHRcdFx0XHRtdWx0aXBsZTogdHJ1ZSxcblx0XHRcdFx0XHRiYXNpY19zZWFyY2g6IHRydWUsXG5cdFx0XHRcdFx0YWR2X3NlYXJjaDogdHJ1ZSxcblx0XHRcdFx0XHRzY3JpcHRfbmFtZTogJ0JyYW5jaFZpZXcnLFxuXHRcdFx0XHRcdGZvcm1faXRlbV90eXBlOiBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1hcblx0XHRcdFx0fSApLFxuXG5cdFx0XHRcdG5ldyBTZWFyY2hGaWVsZCgge1xuXHRcdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ1NjaGVkdWxlIERlcGFydG1lbnQnICksXG5cdFx0XHRcdFx0aW5fY29sdW1uOiAxLFxuXHRcdFx0XHRcdGZpZWxkOiAnZGVwYXJ0bWVudF9pZHMnLFxuXHRcdFx0XHRcdGxheW91dF9uYW1lOiAnZ2xvYmFsX2RlcGFydG1lbnQnLFxuXHRcdFx0XHRcdGFwaV9jbGFzczogVFRBUEkuQVBJRGVwYXJ0bWVudCxcblx0XHRcdFx0XHRtdWx0aXBsZTogdHJ1ZSxcblx0XHRcdFx0XHRiYXNpY19zZWFyY2g6IHRydWUsXG5cdFx0XHRcdFx0YWR2X3NlYXJjaDogdHJ1ZSxcblx0XHRcdFx0XHRzY3JpcHRfbmFtZTogJ0RlcGFydG1lbnRWaWV3Jyxcblx0XHRcdFx0XHRmb3JtX2l0ZW1fdHlwZTogRm9ybUl0ZW1UeXBlLkFXRVNPTUVfQk9YXG5cdFx0XHRcdH0gKSxcblxuXHRcdFx0XHRuZXcgU2VhcmNoRmllbGQoIHtcblx0XHRcdFx0XHRsYWJlbDogJC5pMThuLl8oICdEZWZhdWx0IEJyYW5jaCcgKSxcblx0XHRcdFx0XHRpbl9jb2x1bW46IDEsXG5cdFx0XHRcdFx0ZmllbGQ6ICdkZWZhdWx0X2JyYW5jaF9pZHMnLFxuXHRcdFx0XHRcdGxheW91dF9uYW1lOiAnZ2xvYmFsX2JyYW5jaCcsXG5cdFx0XHRcdFx0YXBpX2NsYXNzOiBUVEFQSS5BUElCcmFuY2gsXG5cdFx0XHRcdFx0bXVsdGlwbGU6IHRydWUsXG5cdFx0XHRcdFx0YmFzaWNfc2VhcmNoOiBmYWxzZSxcblx0XHRcdFx0XHRhZHZfc2VhcmNoOiB0cnVlLFxuXHRcdFx0XHRcdHNjcmlwdF9uYW1lOiAnQnJhbmNoVmlldycsXG5cdFx0XHRcdFx0Zm9ybV9pdGVtX3R5cGU6IEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWFxuXHRcdFx0XHR9ICksXG5cblx0XHRcdFx0bmV3IFNlYXJjaEZpZWxkKCB7XG5cdFx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnRGVmYXVsdCBEZXBhcnRtZW50JyApLFxuXHRcdFx0XHRcdGluX2NvbHVtbjogMSxcblx0XHRcdFx0XHRmaWVsZDogJ2RlZmF1bHRfZGVwYXJ0bWVudF9pZHMnLFxuXHRcdFx0XHRcdGxheW91dF9uYW1lOiAnZ2xvYmFsX2RlcGFydG1lbnQnLFxuXHRcdFx0XHRcdGFwaV9jbGFzczogVFRBUEkuQVBJRGVwYXJ0bWVudCxcblx0XHRcdFx0XHRtdWx0aXBsZTogdHJ1ZSxcblx0XHRcdFx0XHRiYXNpY19zZWFyY2g6IGZhbHNlLFxuXHRcdFx0XHRcdGFkdl9zZWFyY2g6IHRydWUsXG5cdFx0XHRcdFx0c2NyaXB0X25hbWU6ICdEZXBhcnRtZW50VmlldycsXG5cdFx0XHRcdFx0Zm9ybV9pdGVtX3R5cGU6IEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWFxuXHRcdFx0XHR9ICksXG5cblx0XHRcdFx0bmV3IFNlYXJjaEZpZWxkKCB7XG5cdFx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnR3JvdXAnICksXG5cdFx0XHRcdFx0aW5fY29sdW1uOiAyLFxuXHRcdFx0XHRcdG11bHRpcGxlOiB0cnVlLFxuXHRcdFx0XHRcdGZpZWxkOiAnZ3JvdXBfaWRzJyxcblx0XHRcdFx0XHRsYXlvdXRfbmFtZTogJ2dsb2JhbF90cmVlX2NvbHVtbicsXG5cdFx0XHRcdFx0dHJlZV9tb2RlOiB0cnVlLFxuXHRcdFx0XHRcdGJhc2ljX3NlYXJjaDogdHJ1ZSxcblx0XHRcdFx0XHRhZHZfc2VhcmNoOiB0cnVlLFxuXHRcdFx0XHRcdGZvcm1faXRlbV90eXBlOiBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1hcblx0XHRcdFx0fSApLFxuXG5cdFx0XHRcdG5ldyBTZWFyY2hGaWVsZCgge1xuXHRcdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ1RpdGxlJyApLFxuXHRcdFx0XHRcdGZpZWxkOiAndGl0bGVfaWQnLFxuXHRcdFx0XHRcdGluX2NvbHVtbjogMixcblx0XHRcdFx0XHRsYXlvdXRfbmFtZTogJ2dsb2JhbF9qb2JfdGl0bGUnLFxuXHRcdFx0XHRcdGFwaV9jbGFzczogVFRBUEkuQVBJVXNlclRpdGxlLFxuXHRcdFx0XHRcdG11bHRpcGxlOiB0cnVlLFxuXHRcdFx0XHRcdGJhc2ljX3NlYXJjaDogdHJ1ZSxcblx0XHRcdFx0XHRhZHZfc2VhcmNoOiB0cnVlLFxuXHRcdFx0XHRcdGZvcm1faXRlbV90eXBlOiBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1hcblx0XHRcdFx0fSApLFxuXG5cdFx0XHRcdG5ldyBTZWFyY2hGaWVsZCgge1xuXHRcdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ0pvYicgKSxcblx0XHRcdFx0XHRpbl9jb2x1bW46IDIsXG5cdFx0XHRcdFx0ZmllbGQ6ICdqb2JfaWQnLFxuXHRcdFx0XHRcdGxheW91dF9uYW1lOiAnZ2xvYmFsX2pvYicsXG5cdFx0XHRcdFx0YXBpX2NsYXNzOiAoIEdsb2JhbC5nZXRQcm9kdWN0RWRpdGlvbigpID49IDIwICkgPyBUVEFQSS5BUElKb2IgOiBudWxsLFxuXHRcdFx0XHRcdG11bHRpcGxlOiB0cnVlLFxuXHRcdFx0XHRcdGJhc2ljX3NlYXJjaDogZmFsc2UsXG5cdFx0XHRcdFx0YWR2X3NlYXJjaDogKCB0aGlzLnNob3dfam9iX3VpICYmICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSApLFxuXHRcdFx0XHRcdGZvcm1faXRlbV90eXBlOiBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1hcblx0XHRcdFx0fSApLFxuXG5cdFx0XHRcdG5ldyBTZWFyY2hGaWVsZCgge1xuXHRcdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ1Rhc2snICksXG5cdFx0XHRcdFx0aW5fY29sdW1uOiAyLFxuXHRcdFx0XHRcdGZpZWxkOiAnam9iX2l0ZW1faWQnLFxuXHRcdFx0XHRcdGxheW91dF9uYW1lOiAnZ2xvYmFsX2pvYl9pdGVtJyxcblx0XHRcdFx0XHRhcGlfY2xhc3M6ICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gMjAgKSA/IFRUQVBJLkFQSUpvYkl0ZW0gOiBudWxsLFxuXHRcdFx0XHRcdG11bHRpcGxlOiB0cnVlLFxuXHRcdFx0XHRcdGJhc2ljX3NlYXJjaDogZmFsc2UsXG5cdFx0XHRcdFx0YWR2X3NlYXJjaDogKCB0aGlzLnNob3dfam9iX2l0ZW1fdWkgJiYgKCBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAyMCApICksXG5cdFx0XHRcdFx0Zm9ybV9pdGVtX3R5cGU6IEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWFxuXHRcdFx0XHR9ICksXG5cblx0XHRcdFx0bmV3IFNlYXJjaEZpZWxkKCB7XG5cdFx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnUmVjdXJyaW5nIFRlbXBsYXRlJyApLFxuXHRcdFx0XHRcdGZpZWxkOiAncmVjdXJyaW5nX3NjaGVkdWxlX3RlbXBsYXRlX2NvbnRyb2xfaWQnLFxuXHRcdFx0XHRcdGluX2NvbHVtbjogMixcblx0XHRcdFx0XHRsYXlvdXRfbmFtZTogJ2dsb2JhbF9yZWN1cnJpbmdfc2NoZWR1bGVfY29udHJvbCcsXG5cdFx0XHRcdFx0YXBpX2NsYXNzOiBUVEFQSS5BUElSZWN1cnJpbmdTY2hlZHVsZVRlbXBsYXRlQ29udHJvbCxcblx0XHRcdFx0XHRtdWx0aXBsZTogdHJ1ZSxcblx0XHRcdFx0XHRiYXNpY19zZWFyY2g6IGZhbHNlLFxuXHRcdFx0XHRcdGFkdl9zZWFyY2g6IHRydWUsXG5cdFx0XHRcdFx0Zm9ybV9pdGVtX3R5cGU6IEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWFxuXHRcdFx0XHR9ICksXG5cblx0XHRcdFx0bmV3IFNlYXJjaEZpZWxkKCB7XG5cdFx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnQWJzZW5jZSBQb2xpY3knICksXG5cdFx0XHRcdFx0ZmllbGQ6ICdhYnNlbmNlX3BvbGljeV9pZCcsXG5cdFx0XHRcdFx0aW5fY29sdW1uOiAzLFxuXHRcdFx0XHRcdGxheW91dF9uYW1lOiAnZ2xvYmFsX2Fic2VuY2VzJyxcblx0XHRcdFx0XHRhcGlfY2xhc3M6IFRUQVBJLkFQSUFic2VuY2VQb2xpY3ksXG5cdFx0XHRcdFx0bXVsdGlwbGU6IHRydWUsXG5cdFx0XHRcdFx0YmFzaWNfc2VhcmNoOiBmYWxzZSxcblx0XHRcdFx0XHRhZHZfc2VhcmNoOiB0cnVlLFxuXHRcdFx0XHRcdGZvcm1faXRlbV90eXBlOiBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1hcblx0XHRcdFx0fSApLFxuXG5cdFx0XHRcdG5ldyBTZWFyY2hGaWVsZCgge1xuXHRcdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ0luY2x1ZGUgRW1wbG95ZWVzJyApLFxuXHRcdFx0XHRcdGluX2NvbHVtbjogMyxcblx0XHRcdFx0XHRmaWVsZDogJ2luY2x1ZGVfdXNlcl9pZHMnLFxuXHRcdFx0XHRcdGxheW91dF9uYW1lOiAnZ2xvYmFsX3VzZXInLFxuXHRcdFx0XHRcdGFwaV9jbGFzczogVFRBUEkuQVBJVXNlcixcblx0XHRcdFx0XHRtdWx0aXBsZTogdHJ1ZSxcblx0XHRcdFx0XHRiYXNpY19zZWFyY2g6IGZhbHNlLFxuXHRcdFx0XHRcdGFkdl9zZWFyY2g6IHRydWUsXG5cdFx0XHRcdFx0ZGVmYXVsdF9hcmdzOiBkZWZhdWx0X2FyZ3MsXG5cdFx0XHRcdFx0YWRkaXRpb25fc291cmNlX2Z1bmN0aW9uOiAoIGZ1bmN0aW9uKCB0YXJnZXQsIHNvdXJjZV9kYXRhICkge1xuXHRcdFx0XHRcdFx0cmV0dXJuICR0aGlzLm9uRW1wbG95ZWVTb3VyY2VDcmVhdGUoIHRhcmdldCwgc291cmNlX2RhdGEgKTtcblx0XHRcdFx0XHR9ICksXG5cdFx0XHRcdFx0Zm9ybV9pdGVtX3R5cGU6IEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWFxuXHRcdFx0XHR9ICksXG5cblx0XHRcdFx0bmV3IFNlYXJjaEZpZWxkKCB7XG5cdFx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnRXhjbHVkZSBFbXBsb3llZXMnICksXG5cdFx0XHRcdFx0aW5fY29sdW1uOiAzLFxuXHRcdFx0XHRcdGZpZWxkOiAnZXhjbHVkZV91c2VyX2lkcycsXG5cdFx0XHRcdFx0bGF5b3V0X25hbWU6ICdnbG9iYWxfdXNlcicsXG5cdFx0XHRcdFx0YXBpX2NsYXNzOiBUVEFQSS5BUElVc2VyLFxuXHRcdFx0XHRcdG11bHRpcGxlOiB0cnVlLFxuXHRcdFx0XHRcdGJhc2ljX3NlYXJjaDogZmFsc2UsXG5cdFx0XHRcdFx0YWR2X3NlYXJjaDogdHJ1ZSxcblx0XHRcdFx0XHRkZWZhdWx0X2FyZ3M6IGRlZmF1bHRfYXJncyxcblx0XHRcdFx0XHRhZGRpdGlvbl9zb3VyY2VfZnVuY3Rpb246ICggZnVuY3Rpb24oIHRhcmdldCwgc291cmNlX2RhdGEgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gJHRoaXMub25FbXBsb3llZVNvdXJjZUNyZWF0ZSggdGFyZ2V0LCBzb3VyY2VfZGF0YSApO1xuXHRcdFx0XHRcdH0gKSxcblx0XHRcdFx0XHRmb3JtX2l0ZW1fdHlwZTogRm9ybUl0ZW1UeXBlLkFXRVNPTUVfQk9YXG5cdFx0XHRcdH0gKVxuXHRcdFx0XTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly9BbGxvdyByZWd1bGFyIGVtcGxveWVlcyB0byBhZGQgam9iL3Rhc2sgY29sdW1ucyBpZiBuZWVkZWQsIGFuZCBkbyBzb21lIG90aGVyIGJhc2ljIHNlYXJjaGVzLlxuXHRcdFx0dGhpcy5zZWFyY2hfZmllbGRzID0gW107XG5cblx0XHRcdHRoaXMuc2VhcmNoX2ZpZWxkcy5wdXNoKFxuXHRcdFx0XHRuZXcgU2VhcmNoRmllbGQoIHtcblx0XHRcdFx0XHRsYWJlbDogJC5pMThuLl8oICdTdGF0dXMnICksXG5cdFx0XHRcdFx0aW5fY29sdW1uOiAxLFxuXHRcdFx0XHRcdGZpZWxkOiAnc3RhdHVzX2lkJyxcblx0XHRcdFx0XHRtdWx0aXBsZTogdHJ1ZSxcblx0XHRcdFx0XHRiYXNpY19zZWFyY2g6IHRydWUsXG5cdFx0XHRcdFx0YWR2X3NlYXJjaDogZmFsc2UsXG5cdFx0XHRcdFx0bGF5b3V0X25hbWU6ICdnbG9iYWxfb3B0aW9uX2NvbHVtbicsXG5cdFx0XHRcdFx0Zm9ybV9pdGVtX3R5cGU6IEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWFxuXHRcdFx0XHR9ICkgKTtcblxuXHRcdFx0Ly9DaGVjayBwdW5jaCBwZXJtaXNzaW9ucyByYXRoZXIgdGhhbiBzY2hlZHVsZSwgc2luY2UgdGhpcyBpcyBhIHJlZ3VsYXIgZW1wbG95ZWUgd2hvIGxpa2VseSB3b3VsZG4ndCBoYXZlXG5cdFx0XHRpZiAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCAncHVuY2gnLCAnZWRpdF9icmFuY2gnICkgfHwgUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHRoaXMucGVybWlzc2lvbl9pZCwgJ2VkaXRfYnJhbmNoJyApICkge1xuXHRcdFx0XHR0aGlzLnNlYXJjaF9maWVsZHMucHVzaChcblx0XHRcdFx0XHRuZXcgU2VhcmNoRmllbGQoIHtcblx0XHRcdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ1NjaGVkdWxlIEJyYW5jaCcgKSxcblx0XHRcdFx0XHRcdGluX2NvbHVtbjogMSxcblx0XHRcdFx0XHRcdGZpZWxkOiAnc2NoZWR1bGVfYnJhbmNoX2lkcycsXG5cdFx0XHRcdFx0XHRsYXlvdXRfbmFtZTogJ2dsb2JhbF9icmFuY2gnLFxuXHRcdFx0XHRcdFx0YXBpX2NsYXNzOiBUVEFQSS5BUElCcmFuY2gsXG5cdFx0XHRcdFx0XHRtdWx0aXBsZTogdHJ1ZSxcblx0XHRcdFx0XHRcdGJhc2ljX3NlYXJjaDogdHJ1ZSxcblx0XHRcdFx0XHRcdGFkdl9zZWFyY2g6IGZhbHNlLFxuXHRcdFx0XHRcdFx0c2NyaXB0X25hbWU6ICdCcmFuY2hWaWV3Jyxcblx0XHRcdFx0XHRcdGZvcm1faXRlbV90eXBlOiBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1hcblx0XHRcdFx0XHR9ICkgKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggJ3B1bmNoJywgJ2VkaXRfZGVwYXJ0bWVudCcgKSB8fCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggdGhpcy5wZXJtaXNzaW9uX2lkLCAnZWRpdF9kZXBhcnRtZW50JyApICkge1xuXHRcdFx0XHR0aGlzLnNlYXJjaF9maWVsZHMucHVzaChcblx0XHRcdFx0XHRuZXcgU2VhcmNoRmllbGQoIHtcblx0XHRcdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ1NjaGVkdWxlIERlcGFydG1lbnQnICksXG5cdFx0XHRcdFx0XHRpbl9jb2x1bW46IDEsXG5cdFx0XHRcdFx0XHRmaWVsZDogJ2RlcGFydG1lbnRfaWRzJyxcblx0XHRcdFx0XHRcdGxheW91dF9uYW1lOiAnZ2xvYmFsX2RlcGFydG1lbnQnLFxuXHRcdFx0XHRcdFx0YXBpX2NsYXNzOiBUVEFQSS5BUElEZXBhcnRtZW50LFxuXHRcdFx0XHRcdFx0bXVsdGlwbGU6IHRydWUsXG5cdFx0XHRcdFx0XHRiYXNpY19zZWFyY2g6IHRydWUsXG5cdFx0XHRcdFx0XHRhZHZfc2VhcmNoOiBmYWxzZSxcblx0XHRcdFx0XHRcdHNjcmlwdF9uYW1lOiAnRGVwYXJ0bWVudFZpZXcnLFxuXHRcdFx0XHRcdFx0Zm9ybV9pdGVtX3R5cGU6IEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWFxuXHRcdFx0XHRcdH0gKSApO1xuXHRcdFx0fVxuXG5cdFx0XHQvL0NvdWxkIGJlIHBlcm1pc3Npb24gaXNzdWVzIHdpdGggdGhpcywgc28gZGlzYWJsZSBmb3Igbm93LlxuXHRcdFx0Ly8gaWYgKCBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAyMCAmJiAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCAncHVuY2gnLCAnZWRpdF9qb2InICkgfHwgUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHRoaXMucGVybWlzc2lvbl9pZCwgJ2VkaXRfam9iJyApICkgKSB7XG5cdFx0XHQvLyBcdHRoaXMuc2VhcmNoX2ZpZWxkcy5wdXNoKFxuXHRcdFx0Ly8gXHRcdG5ldyBTZWFyY2hGaWVsZCgge1xuXHRcdFx0Ly8gXHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnSm9iJyApLFxuXHRcdFx0Ly8gXHRcdFx0aW5fY29sdW1uOiAyLFxuXHRcdFx0Ly8gXHRcdFx0ZmllbGQ6ICdqb2JfaWQnLFxuXHRcdFx0Ly8gXHRcdFx0bGF5b3V0X25hbWU6ICdnbG9iYWxfam9iJyxcblx0XHRcdC8vIFx0XHRcdGFwaV9jbGFzczogKCBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAyMCApID8gVFRBUEkuQVBJSm9iIDogbnVsbCxcblx0XHRcdC8vIFx0XHRcdG11bHRpcGxlOiB0cnVlLFxuXHRcdFx0Ly8gXHRcdFx0YmFzaWNfc2VhcmNoOiB0cnVlLFxuXHRcdFx0Ly8gXHRcdFx0YWR2X3NlYXJjaDogZmFsc2UsXG5cdFx0XHQvLyBcdFx0XHRmb3JtX2l0ZW1fdHlwZTogRm9ybUl0ZW1UeXBlLkFXRVNPTUVfQk9YXG5cdFx0XHQvLyBcdFx0fSApICk7XG5cdFx0XHQvLyB9XG5cdFx0XHQvL1xuXHRcdFx0Ly8gaWYgKCBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAyMCAmJiAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCAncHVuY2gnLCAnZWRpdF9qb2JfaXRlbScgKSB8fCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggdGhpcy5wZXJtaXNzaW9uX2lkLCAnZWRpdF9qb2JfaXRlbScgKSApICkge1xuXHRcdFx0Ly8gXHR0aGlzLnNlYXJjaF9maWVsZHMucHVzaChcblx0XHRcdC8vIFx0XHRuZXcgU2VhcmNoRmllbGQoIHtcblx0XHRcdC8vIFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ1Rhc2snICksXG5cdFx0XHQvLyBcdFx0XHRpbl9jb2x1bW46IDIsXG5cdFx0XHQvLyBcdFx0XHRmaWVsZDogJ2pvYl9pdGVtX2lkJyxcblx0XHRcdC8vIFx0XHRcdGxheW91dF9uYW1lOiAnZ2xvYmFsX2pvYl9pdGVtJyxcblx0XHRcdC8vIFx0XHRcdGFwaV9jbGFzczogKCBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAyMCApID8gVFRBUEkuQVBJSm9iSXRlbSA6IG51bGwsXG5cdFx0XHQvLyBcdFx0XHRtdWx0aXBsZTogdHJ1ZSxcblx0XHRcdC8vIFx0XHRcdGJhc2ljX3NlYXJjaDogdHJ1ZSxcblx0XHRcdC8vIFx0XHRcdGFkdl9zZWFyY2g6IGZhbHNlLFxuXHRcdFx0Ly8gXHRcdFx0Zm9ybV9pdGVtX3R5cGU6IEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWFxuXHRcdFx0Ly8gXHRcdH0gKSApO1xuXHRcdFx0Ly8gfVxuXG5cdFx0fVxuXHR9XG5cblx0b25Tb3VyY2VEYXRhQ3JlYXRlKCB0YXJnZXQsIHNvdXJjZV9kYXRhICkge1xuXG5cdFx0Ly9pZiAoICF0aGlzLmlzX21hc3NfYWRkaW5nICkge1xuXHRcdC8vXHRyZXR1cm4gc291cmNlX2RhdGE7XG5cdFx0Ly99XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgZGlzcGxheV9jb2x1bW5zID0gdGFyZ2V0LmdldERpc3BsYXlDb2x1bW5zKCk7XG5cdFx0dmFyIGZpcnN0X2l0ZW0gPSB7fTtcblx0XHR2YXIgc2Vjb25kX2l0ZW0gPSB7fTtcblxuXHRcdC8vRklYTUU6IHdoYXQgc2hvdWxkIHdlIGRvIGFib3V0IC0yP1xuXG5cdFx0JC5lYWNoKCBkaXNwbGF5X2NvbHVtbnMsIGZ1bmN0aW9uKCBpbmRleCwgY29udGVudCApIHtcblx0XHRcdGZpcnN0X2l0ZW0uaWQgPSBUVFVVSUQubm90X2V4aXN0X2lkO1xuXHRcdFx0Zmlyc3RfaXRlbVtjb250ZW50Lm5hbWVdID0gR2xvYmFsLmRlZmF1bHRfaXRlbTtcblx0XHRcdGlmICggJHRoaXMuc2VsZWN0X2NlbGxzX0FycmF5Lmxlbmd0aCA+IDAgJiYgISR0aGlzLmlzX21hc3NfZWRpdGluZyApIHtcblx0XHRcdFx0c2Vjb25kX2l0ZW0uaWQgPSAnLTInO1xuXHRcdFx0XHRzZWNvbmRfaXRlbVtjb250ZW50Lm5hbWVdID0gR2xvYmFsLnNlbGVjdGVkX2l0ZW07XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fSApO1xuXG5cdFx0Ly9FcnJvcjogT2JqZWN0IGRvZXNuJ3Qgc3VwcG9ydCBwcm9wZXJ0eSBvciBtZXRob2QgJ3Vuc2hpZnQnIGluIC9pbnRlcmZhY2UvaHRtbDUvbGluZSA2OTUzXG5cdFx0aWYgKCAhc291cmNlX2RhdGEgfHwgJC50eXBlKCBzb3VyY2VfZGF0YSApICE9PSAnYXJyYXknICkge1xuXHRcdFx0c291cmNlX2RhdGEgPSBbXTtcblx0XHR9XG5cdFx0aWYgKCB0aGlzLnNlbGVjdF9jZWxsc19BcnJheS5sZW5ndGggPiAwICYmICEkdGhpcy5pc19tYXNzX2VkaXRpbmcgKSB7XG5cdFx0XHRzb3VyY2VfZGF0YS51bnNoaWZ0KCBzZWNvbmRfaXRlbSApO1xuXHRcdH1cblx0XHRzb3VyY2VfZGF0YS51bnNoaWZ0KCBmaXJzdF9pdGVtICk7XG5cblx0XHRyZXR1cm4gc291cmNlX2RhdGE7XG5cdH1cblxuXHRvblNvdXJjZURhdGFDcmVhdGVQdW5jaFRhZyggdGFyZ2V0LCBzb3VyY2VfZGF0YSApIHtcblxuXHRcdC8vaWYgKCAhdGhpcy5pc19tYXNzX2FkZGluZyApIHtcblx0XHQvL1x0cmV0dXJuIHNvdXJjZV9kYXRhO1xuXHRcdC8vfVxuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dmFyIGRpc3BsYXlfY29sdW1ucyA9IHRhcmdldC5nZXREaXNwbGF5Q29sdW1ucygpO1xuXHRcdHZhciBmaXJzdF9pdGVtID0ge307XG5cblx0XHQkLmVhY2goIGRpc3BsYXlfY29sdW1ucywgZnVuY3Rpb24oIGluZGV4LCBjb250ZW50ICkge1xuXHRcdFx0Zmlyc3RfaXRlbS5pZCA9IFRUVVVJRC5ub3RfZXhpc3RfaWQ7XG5cdFx0XHRmaXJzdF9pdGVtW2NvbnRlbnQubmFtZV0gPSBHbG9iYWwuZGVmYXVsdF9pdGVtO1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH0gKTtcblxuXHRcdC8vRXJyb3I6IE9iamVjdCBkb2Vzbid0IHN1cHBvcnQgcHJvcGVydHkgb3IgbWV0aG9kICd1bnNoaWZ0JyBpbiAvaW50ZXJmYWNlL2h0bWw1L2xpbmUgNjk1M1xuXHRcdGlmICggIXNvdXJjZV9kYXRhIHx8ICQudHlwZSggc291cmNlX2RhdGEgKSAhPT0gJ2FycmF5JyApIHtcblx0XHRcdHNvdXJjZV9kYXRhID0gW107XG5cdFx0fVxuXG5cdFx0c291cmNlX2RhdGEudW5zaGlmdCggZmlyc3RfaXRlbSApO1xuXG5cdFx0cmV0dXJuIHNvdXJjZV9kYXRhO1xuXHR9XG5cblx0b25FbXBsb3llZVNvdXJjZUNyZWF0ZSggdGFyZ2V0LCBzb3VyY2VfZGF0YSApIHtcblxuXHRcdGlmICggIXRoaXMuY2hlY2tPcGVuUGVybWlzc2lvbigpICkge1xuXHRcdFx0cmV0dXJuIHNvdXJjZV9kYXRhO1xuXHRcdH1cblxuXHRcdHZhciBkaXNwbGF5X2NvbHVtbnMgPSB0YXJnZXQuZ2V0RGlzcGxheUNvbHVtbnMoKTtcblxuXHRcdHZhciBmaXJzdF9pdGVtID0ge307XG5cdFx0JC5lYWNoKCBkaXNwbGF5X2NvbHVtbnMsIGZ1bmN0aW9uKCBpbmRleCwgY29udGVudCApIHtcblxuXHRcdFx0Zmlyc3RfaXRlbS5pZCA9IFRUVVVJRC56ZXJvX2lkO1xuXHRcdFx0Zmlyc3RfaXRlbVtjb250ZW50Lm5hbWVdID0gR2xvYmFsLm9wZW5faXRlbTtcblxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH0gKTtcblxuXHRcdC8vRXJyb3I6IE9iamVjdCBkb2Vzbid0IHN1cHBvcnQgcHJvcGVydHkgb3IgbWV0aG9kICd1bnNoaWZ0JyBpbiAvaW50ZXJmYWNlL2h0bWw1L2xpbmUgNjk1M1xuXHRcdGlmICggIXNvdXJjZV9kYXRhIHx8ICQudHlwZSggc291cmNlX2RhdGEgKSAhPT0gJ2FycmF5JyApIHtcblx0XHRcdHNvdXJjZV9kYXRhID0gW107XG5cdFx0fVxuXHRcdHNvdXJjZV9kYXRhLnVuc2hpZnQoIGZpcnN0X2l0ZW0gKTtcblxuXHRcdHJldHVybiBzb3VyY2VfZGF0YTtcblx0fVxuXG5cdGFkZE9QZW5GaWVsZCggdGFyZ2V0LCBzb3VyY2VfZGF0YSApIHtcblx0XHR2YXIgb3Blbl9maWVsZCA9IHt9O1xuXHR9XG5cblx0Y2xlYW5XaGVuVW5sb2FkVmlldyggY2FsbEJhY2sgKSB7XG5cdFx0dGhpcy5ldmVudF9idXMuYXV0b0NsZWFyKCk7IC8vIFRPRE86IE9uY2UgU2NoZWR1bGUgcHJvb2Ygb2YgY29uY2VwdCB3b3JrcywgbW92ZSB0aGlzIHRvIHRoZSBCYXNlVmlldyBmdW5jdGlvbiB0byBhcHBseSB0byBhbGwgdmlld3MuXG5cdFx0VFRWdWVVdGlscy51bm1vdW50Q29tcG9uZW50KCB0aGlzLnZ1ZV9jb250cm9sX2Jhcl9tb3VudF9pZCApO1xuXHRcdCQoICcjc2NoZWR1bGVfdmlld19jb250YWluZXInICkucmVtb3ZlKCk7XG5cdFx0c3VwZXIuY2xlYW5XaGVuVW5sb2FkVmlldyggY2FsbEJhY2sgKTtcblx0fVxuXG5cdHNldEFkZFJlcXVlc3RJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKSB7XG5cdFx0aWYgKCBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA8PSAxMCB8fCAhdGhpcy5hZGRQZXJtaXNzaW9uVmFsaWRhdGUoICdyZXF1ZXN0JyApIHx8IHRoaXMuZWRpdF9vbmx5X21vZGUgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApXG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLmVuYWJsZUFkZFJlcXVlc3RCdXR0b24oKSA9PT0gdHJ1ZSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIHRydWUgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cbn1cblxuU2NoZWR1bGVWaWV3Q29udHJvbGxlci5odG1sX3RlbXBsYXRlID0gYFxuPGRpdiBjbGFzcz1cInZpZXcgc2NoZWR1bGUtdmlld1wiIGlkPVwic2NoZWR1bGVfdmlld19jb250YWluZXJcIj5cblx0PGRpdiBjbGFzcz1cImNsZWFyLWJvdGgtZGl2XCI+PC9kaXY+XG5cdDxkaXYgaWQ9XCJ2dWUtc2NoZWR1bGUtY29udHJvbC1iYXJcIj48L2Rpdj5cblx0PGRpdiBjbGFzcz1cImNsZWFyLWJvdGgtZGl2XCI+PC9kaXY+XG5cdDxkaXYgY2xhc3M9XCJncmlkLXRvcC1ib3JkZXIgc2NoZWR1bGUtdG9wLWJvcmRlclwiPjwvZGl2PlxuXHQ8ZGl2IGNsYXNzPVwiZ3JpZC1kaXYgc2NoZWR1bGUtZ3JpZC1kaXZcIj5cblx0XHQ8dGFibGUgaWQ9XCJncmlkXCI+PC90YWJsZT5cblx0PC9kaXY+XG5cdDxkaXYgY2xhc3M9XCJncmlkLWJvdHRvbS1ib3JkZXJcIj48L2Rpdj5cbjwvZGl2PmA7XG5cbnZhciBTY2hlZHVsZVZpZXdDb250cm9sbGVyUm93VHlwZSA9IGZ1bmN0aW9uKCkge1xuXG59O1xuXG5TY2hlZHVsZVZpZXdDb250cm9sbGVyUm93VHlwZS5UT1RBTCA9IDE7XG5TY2hlZHVsZVZpZXdDb250cm9sbGVyUm93VHlwZS5EQVRFID0gMjtcblNjaGVkdWxlVmlld0NvbnRyb2xsZXJSb3dUeXBlLkVNUFRZID0gMztcblxudmFyIFNjaGVkdWxlVmlld0NvbnRyb2xsZXJNb2RlID0gZnVuY3Rpb24oKSB7XG5cbn07XG5cblNjaGVkdWxlVmlld0NvbnRyb2xsZXJNb2RlLkRBWSA9ICdkYXknO1xuU2NoZWR1bGVWaWV3Q29udHJvbGxlck1vZGUuV0VFSyA9ICd3ZWVrJztcblNjaGVkdWxlVmlld0NvbnRyb2xsZXJNb2RlLk1PTlRIID0gJ21vbnRoJztcblNjaGVkdWxlVmlld0NvbnRyb2xsZXJNb2RlLllFQVIgPSAneWVhcic7XG5cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///6478\n")}}]);
|