timepicker.component.js 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. /**
  2. * @fileoverview added by tsickle
  3. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  4. */
  5. /* tslint:disable:no-forward-ref max-file-line-count */
  6. import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, forwardRef, Input, Output, ViewEncapsulation } from '@angular/core';
  7. import { NG_VALUE_ACCESSOR } from '@angular/forms';
  8. import { TimepickerActions } from './reducer/timepicker.actions';
  9. import { TimepickerStore } from './reducer/timepicker.store';
  10. import { getControlsValue } from './timepicker-controls.util';
  11. import { TimepickerConfig } from './timepicker.config';
  12. import { isValidDate, padNumber, parseTime, isInputValid, isHourInputValid, isMinuteInputValid, isSecondInputValid, isInputLimitValid } from './timepicker.utils';
  13. /** @type {?} */
  14. export const TIMEPICKER_CONTROL_VALUE_ACCESSOR = {
  15. provide: NG_VALUE_ACCESSOR,
  16. /* tslint:disable-next-line: no-use-before-declare */
  17. useExisting: forwardRef((/**
  18. * @return {?}
  19. */
  20. () => TimepickerComponent)),
  21. multi: true
  22. };
  23. export class TimepickerComponent {
  24. /**
  25. * @param {?} _config
  26. * @param {?} _cd
  27. * @param {?} _store
  28. * @param {?} _timepickerActions
  29. */
  30. constructor(_config, _cd, _store, _timepickerActions) {
  31. this._cd = _cd;
  32. this._store = _store;
  33. this._timepickerActions = _timepickerActions;
  34. /**
  35. * emits true if value is a valid date
  36. */
  37. this.isValid = new EventEmitter();
  38. // min\max validation for input fields
  39. this.invalidHours = false;
  40. this.invalidMinutes = false;
  41. this.invalidSeconds = false;
  42. // control value accessor methods
  43. // tslint:disable-next-line:no-any
  44. this.onChange = Function.prototype;
  45. // tslint:disable-next-line:no-any
  46. this.onTouched = Function.prototype;
  47. Object.assign(this, _config);
  48. this.timepickerSub = _store
  49. .select((/**
  50. * @param {?} state
  51. * @return {?}
  52. */
  53. state => state.value))
  54. .subscribe((/**
  55. * @param {?} value
  56. * @return {?}
  57. */
  58. (value) => {
  59. // update UI values if date changed
  60. this._renderTime(value);
  61. this.onChange(value);
  62. this._store.dispatch(this._timepickerActions.updateControls(getControlsValue(this)));
  63. }));
  64. _store
  65. .select((/**
  66. * @param {?} state
  67. * @return {?}
  68. */
  69. state => state.controls))
  70. .subscribe((/**
  71. * @param {?} controlsState
  72. * @return {?}
  73. */
  74. (controlsState) => {
  75. this.isValid.emit(isInputValid(this.hours, this.minutes, this.seconds, this.isPM()));
  76. Object.assign(this, controlsState);
  77. _cd.markForCheck();
  78. }));
  79. }
  80. /**
  81. * @deprecated - please use `isEditable` instead
  82. * @return {?}
  83. */
  84. get isSpinnersVisible() {
  85. return this.showSpinners && !this.readonlyInput;
  86. }
  87. /**
  88. * @return {?}
  89. */
  90. get isEditable() {
  91. return !(this.readonlyInput || this.disabled);
  92. }
  93. /**
  94. * @return {?}
  95. */
  96. resetValidation() {
  97. this.invalidHours = false;
  98. this.invalidMinutes = false;
  99. this.invalidSeconds = false;
  100. }
  101. /**
  102. * @return {?}
  103. */
  104. isPM() {
  105. return this.showMeridian && this.meridian === this.meridians[1];
  106. }
  107. /**
  108. * @param {?} $event
  109. * @return {?}
  110. */
  111. prevDef($event) {
  112. $event.preventDefault();
  113. }
  114. /**
  115. * @param {?} $event
  116. * @return {?}
  117. */
  118. wheelSign($event) {
  119. return Math.sign($event.deltaY) * -1;
  120. }
  121. /**
  122. * @param {?} changes
  123. * @return {?}
  124. */
  125. ngOnChanges(changes) {
  126. this._store.dispatch(this._timepickerActions.updateControls(getControlsValue(this)));
  127. }
  128. /**
  129. * @param {?} step
  130. * @param {?=} source
  131. * @return {?}
  132. */
  133. changeHours(step, source = '') {
  134. this.resetValidation();
  135. this._store.dispatch(this._timepickerActions.changeHours({ step, source }));
  136. }
  137. /**
  138. * @param {?} step
  139. * @param {?=} source
  140. * @return {?}
  141. */
  142. changeMinutes(step, source = '') {
  143. this.resetValidation();
  144. this._store.dispatch(this._timepickerActions.changeMinutes({ step, source }));
  145. }
  146. /**
  147. * @param {?} step
  148. * @param {?=} source
  149. * @return {?}
  150. */
  151. changeSeconds(step, source = '') {
  152. this.resetValidation();
  153. this._store.dispatch(this._timepickerActions.changeSeconds({ step, source }));
  154. }
  155. /**
  156. * @param {?} hours
  157. * @return {?}
  158. */
  159. updateHours(hours) {
  160. this.resetValidation();
  161. this.hours = hours;
  162. /** @type {?} */
  163. const isValid = isHourInputValid(this.hours, this.isPM()) && this.isValidLimit();
  164. if (!isValid) {
  165. this.invalidHours = true;
  166. this.isValid.emit(false);
  167. this.onChange(null);
  168. return;
  169. }
  170. this._updateTime();
  171. }
  172. /**
  173. * @param {?} minutes
  174. * @return {?}
  175. */
  176. updateMinutes(minutes) {
  177. this.resetValidation();
  178. this.minutes = minutes;
  179. /** @type {?} */
  180. const isValid = isMinuteInputValid(this.minutes) && this.isValidLimit();
  181. if (!isValid) {
  182. this.invalidMinutes = true;
  183. this.isValid.emit(false);
  184. this.onChange(null);
  185. return;
  186. }
  187. this._updateTime();
  188. }
  189. /**
  190. * @param {?} seconds
  191. * @return {?}
  192. */
  193. updateSeconds(seconds) {
  194. this.resetValidation();
  195. this.seconds = seconds;
  196. /** @type {?} */
  197. const isValid = isSecondInputValid(this.seconds) && this.isValidLimit();
  198. if (!isValid) {
  199. this.invalidSeconds = true;
  200. this.isValid.emit(false);
  201. this.onChange(null);
  202. return;
  203. }
  204. this._updateTime();
  205. }
  206. /**
  207. * @return {?}
  208. */
  209. isValidLimit() {
  210. return isInputLimitValid({
  211. hour: this.hours,
  212. minute: this.minutes,
  213. seconds: this.seconds,
  214. isPM: this.isPM()
  215. }, this.max, this.min);
  216. }
  217. /**
  218. * @return {?}
  219. */
  220. _updateTime() {
  221. /** @type {?} */
  222. const _seconds = this.showSeconds ? this.seconds : void 0;
  223. /** @type {?} */
  224. const _minutes = this.showMinutes ? this.minutes : void 0;
  225. if (!isInputValid(this.hours, _minutes, _seconds, this.isPM())) {
  226. this.isValid.emit(false);
  227. this.onChange(null);
  228. return;
  229. }
  230. this._store.dispatch(this._timepickerActions.setTime({
  231. hour: this.hours,
  232. minute: this.minutes,
  233. seconds: this.seconds,
  234. isPM: this.isPM()
  235. }));
  236. }
  237. /**
  238. * @return {?}
  239. */
  240. toggleMeridian() {
  241. if (!this.showMeridian || !this.isEditable) {
  242. return;
  243. }
  244. /** @type {?} */
  245. const _hoursPerDayHalf = 12;
  246. this._store.dispatch(this._timepickerActions.changeHours({
  247. step: _hoursPerDayHalf,
  248. source: ''
  249. }));
  250. }
  251. /**
  252. * Write a new value to the element.
  253. * @param {?} obj
  254. * @return {?}
  255. */
  256. writeValue(obj) {
  257. if (isValidDate(obj)) {
  258. this._store.dispatch(this._timepickerActions.writeValue(parseTime(obj)));
  259. }
  260. else if (obj == null) {
  261. this._store.dispatch(this._timepickerActions.writeValue(null));
  262. }
  263. }
  264. /**
  265. * Set the function to be called when the control receives a change event.
  266. * @param {?} fn
  267. * @return {?}
  268. */
  269. // tslint:disable-next-line:no-any
  270. registerOnChange(fn) {
  271. this.onChange = fn;
  272. }
  273. /**
  274. * Set the function to be called when the control receives a touch event.
  275. * @param {?} fn
  276. * @return {?}
  277. */
  278. registerOnTouched(fn) {
  279. this.onTouched = fn;
  280. }
  281. /**
  282. * This function is called when the control status changes to or from "disabled".
  283. * Depending on the value, it will enable or disable the appropriate DOM element.
  284. *
  285. * @param {?} isDisabled
  286. * @return {?}
  287. */
  288. setDisabledState(isDisabled) {
  289. this.disabled = isDisabled;
  290. this._cd.markForCheck();
  291. }
  292. /**
  293. * @return {?}
  294. */
  295. ngOnDestroy() {
  296. this.timepickerSub.unsubscribe();
  297. }
  298. /**
  299. * @private
  300. * @param {?} value
  301. * @return {?}
  302. */
  303. _renderTime(value) {
  304. if (!isValidDate(value)) {
  305. this.hours = '';
  306. this.minutes = '';
  307. this.seconds = '';
  308. this.meridian = this.meridians[0];
  309. return;
  310. }
  311. /** @type {?} */
  312. const _value = parseTime(value);
  313. /** @type {?} */
  314. const _hoursPerDayHalf = 12;
  315. /** @type {?} */
  316. let _hours = _value.getHours();
  317. if (this.showMeridian) {
  318. this.meridian = this.meridians[_hours >= _hoursPerDayHalf ? 1 : 0];
  319. _hours = _hours % _hoursPerDayHalf;
  320. // should be 12 PM, not 00 PM
  321. if (_hours === 0) {
  322. _hours = _hoursPerDayHalf;
  323. }
  324. }
  325. this.hours = padNumber(_hours);
  326. this.minutes = padNumber(_value.getMinutes());
  327. this.seconds = padNumber(_value.getUTCSeconds());
  328. }
  329. }
  330. TimepickerComponent.decorators = [
  331. { type: Component, args: [{
  332. selector: 'timepicker',
  333. changeDetection: ChangeDetectionStrategy.OnPush,
  334. providers: [TIMEPICKER_CONTROL_VALUE_ACCESSOR, TimepickerStore],
  335. template: "<table>\n <tbody>\n <tr class=\"text-center\" [hidden]=\"!showSpinners\">\n <!-- increment hours button-->\n <td>\n <a class=\"btn btn-link\" [class.disabled]=\"!canIncrementHours || !isEditable\"\n (click)=\"changeHours(hourStep)\"\n ><span class=\"bs-chevron bs-chevron-up\"></span></a>\n </td>\n <!-- divider -->\n <td *ngIf=\"showMinutes\">&nbsp;&nbsp;&nbsp;</td>\n <!-- increment minutes button -->\n <td *ngIf=\"showMinutes\">\n <a class=\"btn btn-link\" [class.disabled]=\"!canIncrementMinutes || !isEditable\"\n (click)=\"changeMinutes(minuteStep)\"\n ><span class=\"bs-chevron bs-chevron-up\"></span></a>\n </td>\n <!-- divider -->\n <td *ngIf=\"showSeconds\">&nbsp;</td>\n <!-- increment seconds button -->\n <td *ngIf=\"showSeconds\">\n <a class=\"btn btn-link\" [class.disabled]=\"!canIncrementSeconds || !isEditable\"\n (click)=\"changeSeconds(secondsStep)\">\n <span class=\"bs-chevron bs-chevron-up\"></span>\n </a>\n </td>\n <!-- space between -->\n <td *ngIf=\"showMeridian\">&nbsp;&nbsp;&nbsp;</td>\n <!-- meridian placeholder-->\n <td *ngIf=\"showMeridian\"></td>\n </tr>\n <tr>\n <!-- hours -->\n <td class=\"form-group\" [class.has-error]=\"invalidHours\">\n <input type=\"text\" [class.is-invalid]=\"invalidHours\"\n class=\"form-control text-center bs-timepicker-field\"\n [placeholder]=\"hoursPlaceholder\"\n maxlength=\"2\"\n [readonly]=\"readonlyInput\"\n [disabled]=\"disabled\"\n [value]=\"hours\"\n (wheel)=\"prevDef($event);changeHours(hourStep * wheelSign($event), 'wheel')\"\n (keydown.ArrowUp)=\"changeHours(hourStep, 'key')\"\n (keydown.ArrowDown)=\"changeHours(-hourStep, 'key')\"\n (change)=\"updateHours($event.target.value)\"></td>\n <!-- divider -->\n <td *ngIf=\"showMinutes\">&nbsp;:&nbsp;</td>\n <!-- minutes -->\n <td class=\"form-group\" *ngIf=\"showMinutes\" [class.has-error]=\"invalidMinutes\">\n <input type=\"text\" [class.is-invalid]=\"invalidMinutes\"\n class=\"form-control text-center bs-timepicker-field\"\n [placeholder]=\"minutesPlaceholder\"\n maxlength=\"2\"\n [readonly]=\"readonlyInput\"\n [disabled]=\"disabled\"\n [value]=\"minutes\"\n (wheel)=\"prevDef($event);changeMinutes(minuteStep * wheelSign($event), 'wheel')\"\n (keydown.ArrowUp)=\"changeMinutes(minuteStep, 'key')\"\n (keydown.ArrowDown)=\"changeMinutes(-minuteStep, 'key')\"\n (change)=\"updateMinutes($event.target.value)\">\n </td>\n <!-- divider -->\n <td *ngIf=\"showSeconds\">&nbsp;:&nbsp;</td>\n <!-- seconds -->\n <td class=\"form-group\" *ngIf=\"showSeconds\" [class.has-error]=\"invalidSeconds\">\n <input type=\"text\" [class.is-invalid]=\"invalidSeconds\"\n class=\"form-control text-center bs-timepicker-field\"\n [placeholder]=\"secondsPlaceholder\"\n maxlength=\"2\"\n [readonly]=\"readonlyInput\"\n [disabled]=\"disabled\"\n [value]=\"seconds\"\n (wheel)=\"prevDef($event);changeSeconds(secondsStep * wheelSign($event), 'wheel')\"\n (keydown.ArrowUp)=\"changeSeconds(secondsStep, 'key')\"\n (keydown.ArrowDown)=\"changeSeconds(-secondsStep, 'key')\"\n (change)=\"updateSeconds($event.target.value)\">\n </td>\n <!-- space between -->\n <td *ngIf=\"showMeridian\">&nbsp;&nbsp;&nbsp;</td>\n <!-- meridian -->\n <td *ngIf=\"showMeridian\">\n <button type=\"button\" class=\"btn btn-default text-center\"\n [disabled]=\"!isEditable || !canToggleMeridian\"\n [class.disabled]=\"!isEditable || !canToggleMeridian\"\n (click)=\"toggleMeridian()\"\n >{{ meridian }}\n </button>\n </td>\n </tr>\n <tr class=\"text-center\" [hidden]=\"!showSpinners\">\n <!-- decrement hours button-->\n <td>\n <a class=\"btn btn-link\" [class.disabled]=\"!canDecrementHours || !isEditable\"\n (click)=\"changeHours(-hourStep)\">\n <span class=\"bs-chevron bs-chevron-down\"></span>\n </a>\n </td>\n <!-- divider -->\n <td *ngIf=\"showMinutes\">&nbsp;&nbsp;&nbsp;</td>\n <!-- decrement minutes button-->\n <td *ngIf=\"showMinutes\">\n <a class=\"btn btn-link\" [class.disabled]=\"!canDecrementMinutes || !isEditable\"\n (click)=\"changeMinutes(-minuteStep)\">\n <span class=\"bs-chevron bs-chevron-down\"></span>\n </a>\n </td>\n <!-- divider -->\n <td *ngIf=\"showSeconds\">&nbsp;</td>\n <!-- decrement seconds button-->\n <td *ngIf=\"showSeconds\">\n <a class=\"btn btn-link\" [class.disabled]=\"!canDecrementSeconds || !isEditable\"\n (click)=\"changeSeconds(-secondsStep)\">\n <span class=\"bs-chevron bs-chevron-down\"></span>\n </a>\n </td>\n <!-- space between -->\n <td *ngIf=\"showMeridian\">&nbsp;&nbsp;&nbsp;</td>\n <!-- meridian placeholder-->\n <td *ngIf=\"showMeridian\"></td>\n </tr>\n </tbody>\n</table>\n",
  336. encapsulation: ViewEncapsulation.None,
  337. styles: [`
  338. .bs-chevron {
  339. border-style: solid;
  340. display: block;
  341. width: 9px;
  342. height: 9px;
  343. position: relative;
  344. border-width: 3px 0px 0 3px;
  345. }
  346. .bs-chevron-up {
  347. -webkit-transform: rotate(45deg);
  348. transform: rotate(45deg);
  349. top: 2px;
  350. }
  351. .bs-chevron-down {
  352. -webkit-transform: rotate(-135deg);
  353. transform: rotate(-135deg);
  354. top: -2px;
  355. }
  356. .bs-timepicker-field {
  357. width: 50px;
  358. padding: .375rem .55rem;
  359. }
  360. `]
  361. }] }
  362. ];
  363. /** @nocollapse */
  364. TimepickerComponent.ctorParameters = () => [
  365. { type: TimepickerConfig },
  366. { type: ChangeDetectorRef },
  367. { type: TimepickerStore },
  368. { type: TimepickerActions }
  369. ];
  370. TimepickerComponent.propDecorators = {
  371. hourStep: [{ type: Input }],
  372. minuteStep: [{ type: Input }],
  373. secondsStep: [{ type: Input }],
  374. readonlyInput: [{ type: Input }],
  375. disabled: [{ type: Input }],
  376. mousewheel: [{ type: Input }],
  377. arrowkeys: [{ type: Input }],
  378. showSpinners: [{ type: Input }],
  379. showMeridian: [{ type: Input }],
  380. showMinutes: [{ type: Input }],
  381. showSeconds: [{ type: Input }],
  382. meridians: [{ type: Input }],
  383. min: [{ type: Input }],
  384. max: [{ type: Input }],
  385. hoursPlaceholder: [{ type: Input }],
  386. minutesPlaceholder: [{ type: Input }],
  387. secondsPlaceholder: [{ type: Input }],
  388. isValid: [{ type: Output }]
  389. };
  390. if (false) {
  391. /**
  392. * hours change step
  393. * @type {?}
  394. */
  395. TimepickerComponent.prototype.hourStep;
  396. /**
  397. * hours change step
  398. * @type {?}
  399. */
  400. TimepickerComponent.prototype.minuteStep;
  401. /**
  402. * seconds change step
  403. * @type {?}
  404. */
  405. TimepickerComponent.prototype.secondsStep;
  406. /**
  407. * if true hours and minutes fields will be readonly
  408. * @type {?}
  409. */
  410. TimepickerComponent.prototype.readonlyInput;
  411. /**
  412. * if true hours and minutes fields will be disabled
  413. * @type {?}
  414. */
  415. TimepickerComponent.prototype.disabled;
  416. /**
  417. * if true scroll inside hours and minutes inputs will change time
  418. * @type {?}
  419. */
  420. TimepickerComponent.prototype.mousewheel;
  421. /**
  422. * if true the values of hours and minutes can be changed using the up/down arrow keys on the keyboard
  423. * @type {?}
  424. */
  425. TimepickerComponent.prototype.arrowkeys;
  426. /**
  427. * if true spinner arrows above and below the inputs will be shown
  428. * @type {?}
  429. */
  430. TimepickerComponent.prototype.showSpinners;
  431. /**
  432. * if true meridian button will be shown
  433. * @type {?}
  434. */
  435. TimepickerComponent.prototype.showMeridian;
  436. /**
  437. * show minutes in timepicker
  438. * @type {?}
  439. */
  440. TimepickerComponent.prototype.showMinutes;
  441. /**
  442. * show seconds in timepicker
  443. * @type {?}
  444. */
  445. TimepickerComponent.prototype.showSeconds;
  446. /**
  447. * meridian labels based on locale
  448. * @type {?}
  449. */
  450. TimepickerComponent.prototype.meridians;
  451. /**
  452. * minimum time user can select
  453. * @type {?}
  454. */
  455. TimepickerComponent.prototype.min;
  456. /**
  457. * maximum time user can select
  458. * @type {?}
  459. */
  460. TimepickerComponent.prototype.max;
  461. /**
  462. * placeholder for hours field in timepicker
  463. * @type {?}
  464. */
  465. TimepickerComponent.prototype.hoursPlaceholder;
  466. /**
  467. * placeholder for minutes field in timepicker
  468. * @type {?}
  469. */
  470. TimepickerComponent.prototype.minutesPlaceholder;
  471. /**
  472. * placeholder for seconds field in timepicker
  473. * @type {?}
  474. */
  475. TimepickerComponent.prototype.secondsPlaceholder;
  476. /**
  477. * emits true if value is a valid date
  478. * @type {?}
  479. */
  480. TimepickerComponent.prototype.isValid;
  481. /** @type {?} */
  482. TimepickerComponent.prototype.hours;
  483. /** @type {?} */
  484. TimepickerComponent.prototype.minutes;
  485. /** @type {?} */
  486. TimepickerComponent.prototype.seconds;
  487. /** @type {?} */
  488. TimepickerComponent.prototype.meridian;
  489. /** @type {?} */
  490. TimepickerComponent.prototype.invalidHours;
  491. /** @type {?} */
  492. TimepickerComponent.prototype.invalidMinutes;
  493. /** @type {?} */
  494. TimepickerComponent.prototype.invalidSeconds;
  495. /** @type {?} */
  496. TimepickerComponent.prototype.canIncrementHours;
  497. /** @type {?} */
  498. TimepickerComponent.prototype.canIncrementMinutes;
  499. /** @type {?} */
  500. TimepickerComponent.prototype.canIncrementSeconds;
  501. /** @type {?} */
  502. TimepickerComponent.prototype.canDecrementHours;
  503. /** @type {?} */
  504. TimepickerComponent.prototype.canDecrementMinutes;
  505. /** @type {?} */
  506. TimepickerComponent.prototype.canDecrementSeconds;
  507. /** @type {?} */
  508. TimepickerComponent.prototype.canToggleMeridian;
  509. /** @type {?} */
  510. TimepickerComponent.prototype.onChange;
  511. /** @type {?} */
  512. TimepickerComponent.prototype.onTouched;
  513. /** @type {?} */
  514. TimepickerComponent.prototype.timepickerSub;
  515. /**
  516. * @type {?}
  517. * @private
  518. */
  519. TimepickerComponent.prototype._cd;
  520. /**
  521. * @type {?}
  522. * @private
  523. */
  524. TimepickerComponent.prototype._store;
  525. /**
  526. * @type {?}
  527. * @private
  528. */
  529. TimepickerComponent.prototype._timepickerActions;
  530. }
  531. //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtYm9vdHN0cmFwL3RpbWVwaWNrZXIvIiwic291cmNlcyI6WyJ0aW1lcGlja2VyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUNBLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxZQUFZLEVBQ1osVUFBVSxFQUNWLEtBQUssRUFHTCxNQUFNLEVBQ1MsaUJBQWlCLEVBQ2pDLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV6RSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUNqRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDN0QsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDOUQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFRdkQsT0FBTyxFQUNMLFdBQVcsRUFDWCxTQUFTLEVBQ1QsU0FBUyxFQUNULFlBQVksRUFDWixnQkFBZ0IsRUFDaEIsa0JBQWtCLEVBQ2xCLGtCQUFrQixFQUNsQixpQkFBaUIsRUFDbEIsTUFBTSxvQkFBb0IsQ0FBQzs7QUFNNUIsTUFBTSxPQUFPLGlDQUFpQyxHQUE4QjtJQUMxRSxPQUFPLEVBQUUsaUJBQWlCOztJQUUxQixXQUFXLEVBQUUsVUFBVTs7O0lBQUMsR0FBRyxFQUFFLENBQUMsbUJBQW1CLEVBQUM7SUFDbEQsS0FBSyxFQUFFLElBQUk7Q0FDWjtBQW9DRCxNQUFNLE9BQU8sbUJBQW1COzs7Ozs7O0lBbUY5QixZQUNFLE9BQXlCLEVBQ2pCLEdBQXNCLEVBQ3RCLE1BQXVCLEVBQ3ZCLGtCQUFxQztRQUZyQyxRQUFHLEdBQUgsR0FBRyxDQUFtQjtRQUN0QixXQUFNLEdBQU4sTUFBTSxDQUFpQjtR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S0FBSzs0QkFFTCxLQUFLO3VCQUVMLEtBQUs7eUJBRUwsS0FBSzt3QkFFTCxLQUFLOzJCQUVMLEtBQUs7MkJBRUwsS0FBSzswQkFFTCxLQUFLOzBCQUVMLEtBQUs7d0JBRUwsS0FBSztrQkFFTCxLQUFLO2tCQUVMLEtBQUs7K0JBRUwsS0FBSztpQ0FFTCxLQUFLO2lDQUVMLEtBQUs7c0JBR0wsTUFBTTs7Ozs7OztJQW5DUCx1Q0FBMEI7Ozs7O0lBRTFCLHlDQUE0Qjs7Ozs7SUFFNUIsMENBQTZCOzs7OztJQUU3Qiw0Q0FBZ0M7Ozs7O0lBRWhDLHVDQUEyQjs7Ozs7SUFFM0IseUNBQTZCOzs7OztJQUU3Qix3Q0FBNEI7Ozs7O0lBRTVCLDJDQUErQjs7Ozs7SUFFL0IsMkNBQStCOzs7OztJQUUvQiwwQ0FBOEI7Ozs7O0lBRTlCLDBDQUE4Qjs7Ozs7SUFFOUIsd0NBQTZCOzs7OztJQUU3QixrQ0FBbUI7Ozs7O0lBRW5CLGtDQUFtQjs7Ozs7SUFFbkIsK0NBQWtDOzs7OztJQUVsQyxpREFBb0M7Ozs7O0lBRXBDLGlEQUFvQzs7Ozs7SUFHcEMsc0NBQWdEOztJQUdoRCxvQ0FBYzs7SUFDZCxzQ0FBZ0I7O0lBQ2hCLHNDQUFnQjs7SUFDaEIsdUNBQWlCOztJQVlqQiwyQ0FBcUI7O0lBQ3JCLDZDQUF1Qjs7SUFDdkIsNkNBQXVCOztJQUd2QixnREFBMkI7O0lBQzNCLGtEQUE2Qjs7SUFDN0Isa0RBQTZCOztJQUU3QixnREFBMkI7O0lBQzNCLGtEQUE2Qjs7SUFDN0Isa0RBQTZCOztJQUU3QixnREFBMkI7O0lBSTNCLHVDQUE4Qjs7SUFFOUIsd0NBQStCOztJQUUvQiw0Q0FBNEI7Ozs7O0lBSTFCLGtDQUE4Qjs7Ozs7SUFDOUIscUNBQStCOzs7OztJQUMvQixpREFBNkMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiB0c2xpbnQ6ZGlzYWJsZTpuby1mb3J3YXJkLXJlZiBtYXgtZmlsZS1saW5lLWNvdW50ICovXG5pbXBvcnQge1xuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBmb3J3YXJkUmVmLFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBPbkRlc3Ryb3ksXG4gIE91dHB1dCxcbiAgU2ltcGxlQ2hhbmdlcywgVmlld0VuY2Fwc3VsYXRpb25cbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7IENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBOR19WQUxVRV9BQ0NFU1NPUiB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcblxuaW1wb3J0IHsgVGltZXBpY2tlckFjdGlvbnMgfSBmcm9tICcuL3JlZHVjZXIvdGltZXBpY2tlci5hY3Rpb25zJztcbmltcG9ydCB7IFRpbWVwaWNrZXJTdG9yZSB9IGZyb20gJy4vcmVkdWNlci90aW1lcGlja2VyLnN0b3JlJztcbmltcG9ydCB7IGdldENvbnRyb2xzVmFsdWUgfSBmcm9tICcuL3RpbWVwaWNrZXItY29udHJvbHMudXRpbCc7XG5pbXBvcnQgeyBUaW1lcGlja2VyQ29uZmlnIH0gZnJvbSAnLi90aW1lcGlja2VyLmNvbmZpZyc7XG5cbmltcG9ydCB7XG4gIFRpbWVDaGFuZ2VTb3VyY2UsXG4gIFRpbWVwaWNrZXJDb21wb25lbnRTdGF0ZSxcbiAgVGltZXBpY2tlckNvbnRyb2xzXG59IGZyb20gJy4vdGltZXBpY2tlci5tb2RlbHMnO1xuXG5pbXBvcnQge1xuICBpc1ZhbGlkRGF0ZSxcbiAgcGFkTnVtYmVyLFxuICBwYXJzZVRpbWUsXG4gIGlzSW5wdXRWYWxpZCxcbiAgaXNIb3VySW5wdXRWYWxpZCxcbiAgaXNNaW51dGVJbnB1dFZhbGlkLFxuICBpc1NlY29uZElucHV0VmFsaWQsXG4gIGlzSW5wdXRMaW1pdFZhbGlkXG59IGZyb20gJy4vdGltZXBpY2tlci51dGlscyc7XG5cbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyBDb250cm9sVmFsdWVBY2Nlc3Nvck1vZGVsIH0gZnJvbSAnLi9tb2RlbHMnO1xuXG5leHBvcnQgY29uc3QgVElNRVBJQ0tFUl9DT05UUk9MX1ZBTFVFX0FDQ0VTU09SOiBDb250cm9sVmFsdWVBY2Nlc3Nvck1vZGVsID0ge1xuICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgLyogdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOiBuby11c2UtYmVmb3JlLWRlY2xhcmUgKi9cbiAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gVGltZXBpY2tlckNvbXBvbmVudCksXG4gIG11bHRpOiB0cnVlXG59O1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd0aW1lcGlja2VyJyxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHByb3ZpZGVyczogW1RJTUVQSUNLRVJfQ09OVFJPTF9WQUxVRV9BQ0NFU1NPUiwgVGltZXBpY2tlclN0b3JlXSxcbiAgdGVtcGxhdGVVcmw6ICcuL3RpbWVwaWNrZXIuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZXM6IFtgXG4gICAgLmJzLWNoZXZyb24ge1xuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDtcbiAgICAgIGRpc3BsYXk6IGJsb2NrO1xuICAgICAgd2lkdGg6IDlweDtcbiAgICAgIGhlaWdodDogOXB4O1xuICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICAgICAgYm9yZGVyLXdpZHRoOiAzcHggMHB4IDAgM3B4O1xuICAgIH1cblxuICAgIC5icy1jaGV2cm9uLXVwIHtcbiAgICAgIC13ZWJraXQtdHJhbnNmb3JtOiByb3RhdGUoNDVkZWcpO1xuICAgICAgdHJhbnNmb3JtOiByb3RhdGUoNDVkZWcpO1xuICAgICAgdG9wOiAycHg7XG4gICAgfVxuXG4gICAgLmJzLWNoZXZyb24tZG93biB7XG4gICAgICAtd2Via2l0LXRyYW5zZm9ybTogcm90YXRlKC0xMzVkZWcpO1xuICAgICAgdHJhbnNmb3JtOiByb3RhdGUoLTEzNWRlZyk7XG4gICAgICB0b3A6IC0ycHg7XG4gICAgfVxuXG4gICAgLmJzLXRpbWVwaWNrZXItZmllbGQge1xuICAgICAgd2lkdGg6IDUwcHg7XG4gICAgICBwYWRkaW5nOiAuMzc1cmVtIC41NXJlbTtcbiAgICB9XG4gIGBdLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lXG59KVxuZXhwb3J0IGNsYXNzIFRpbWVwaWNrZXJDb21wb25lbnRcbiAgaW1wbGVtZW50cyBDb250cm9sVmFsdWVBY2Nlc3NvcixcbiAgICBUaW1lcGlja2VyQ29tcG9uZW50U3RhdGUsXG4gICAgVGltZXBpY2tlckNvbnRyb2xzLFxuICAgIE9uQ2hhbmdlcyxcbiAgICBPbkRlc3Ryb3kge1xuICAvKiogaG91cnMgY2hhbmdlIHN0ZXAgKi9cbiAgQElucHV0KCkgaG91clN0ZXA6IG51bWJlcjtcbiAgLyoqIGhvdXJzIGNoYW5nZSBzdGVwICovXG4gIEBJbnB1dCgpIG1pbnV0ZVN0ZXA6IG51bWJlcjtcbiAgLyoqIHNlY29uZHMgY2hhbmdlIHN0ZXAgKi9cbiAgQElucHV0KCkgc2Vjb25kc1N0ZXA6IG51bWJlcjtcbiAgLyoqIGlmIHRydWUgaG91cnMgYW5kIG1pbnV0ZXMgZmllbGRzIHdpbGwgYmUgcmVhZG9ubHkgKi9cbiAgQElucHV0KCkgcmVhZG9ubHlJbnB1dDogYm9vbGVhbjtcbiAgLyoqIGlmIHRydWUgaG91cnMgYW5kIG1pbnV0ZXMgZmllbGRzIHdpbGwgYmUgZGlzYWJsZWQgKi9cbiAgQElucHV0KCkgZGlzYWJsZWQ6IGJvb2xlYW47XG4gIC8qKiBpZiB0cnVlIHNjcm9sbCBpbnNpZGUgaG91cnMgYW5kIG1pbnV0ZXMgaW5wdXRzIHdpbGwgY2hhbmdlIHRpbWUgKi9cbiAgQElucHV0KCkgbW91c2V3aGVlbDogYm9vbGVhbjtcbiAgLyoqIGlmIHRydWUgdGhlIHZhbHVlcyBvZiBob3VycyBhbmQgbWludXRlcyBjYW4gYmUgY2hhbmdlZCB1c2luZyB0aGUgdXAvZG93biBhcnJvdyBrZXlzIG9uIHRoZSBrZXlib2FyZCAqL1xuICBASW5wdXQoKSBhcnJvd2tleXM6IGJvb2xlYW47XG4gIC8qKiBpZiB0cnVlIHNwaW5uZXIgYXJyb3dzIGFib3ZlIGFuZCBiZWxvdyB0aGUgaW5wdXRzIHdpbGwgYmUgc2hvd24gKi9cbiAgQElucHV0KCkgc2hvd1NwaW5uZXJzOiBib29sZWFuO1xuICAvKiogaWYgdHJ1ZSBtZXJpZGlhbiBidXR0b24gd2lsbCBiZSBzaG93biAqL1xuICBASW5wdXQoKSBzaG93TWVyaWRpYW46IGJvb2xlYW47XG4gIC8qKiBzaG93IG1pbnV0ZXMgaW4gdGltZXBpY2tlciAqL1xuICBASW5wdXQoKSBzaG93TWludXRlczogYm9vbGVhbjtcbiAgLyoqIHNob3cgc2Vjb25kcyBpbiB0aW1lcGlja2VyICovXG4gIEBJbnB1dCgpIHNob3dTZWNvbmRzOiBib29sZWFuO1xuICAvKiogbWVyaWRpYW4gbGFiZWxzIGJhc2VkIG9uIGxvY2FsZSAqL1xuICBASW5wdXQoKSBtZXJpZGlhbnM6IHN0cmluZ1tdO1xuICAvKiogbWluaW11bSB0aW1lIHVzZXIgY2FuIHNlbGVjdCAqL1xuICBASW5wdXQoKSBtaW46IERhdGU7XG4gIC8qKiBtYXhpbXVtIHRpbWUgdXNlciBjYW4gc2VsZWN0ICovXG4gIEBJbnB1dCgpIG1heDogRGF0ZTtcbiAgLyoqIHBsYWNlaG9sZGVyIGZvciBob3VycyBmaWVsZCBpbiB0aW1lcGlja2VyICovXG4gIEBJbnB1dCgpIGhvdXJzUGxhY2Vob2xkZXI6IHN0cmluZztcbiAgLyoqIHBsYWNlaG9sZGVyIGZvciBtaW51dGVzIGZpZWxkIGluIHRpbWVwaWNrZXIgKi9cbiAgQElucHV0KCkgbWludXRlc1BsYWNlaG9sZGVyOiBzdHJpbmc7XG4gIC8qKiBwbGFjZWhvbGRlciBmb3Igc2Vjb25kcyBmaWVsZCBpbiB0aW1lcGlja2VyICovXG4gIEBJbnB1dCgpIHNlY29uZHNQbGFjZWhvbGRlcjogc3RyaW5nO1xuXG4gIC8qKiBlbWl0cyB0cnVlIGlmIHZhbHVlIGlzIGEgdmFsaWQgZGF0ZSAqL1xuICBAT3V0cHV0KCkgaXNWYWxpZCA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcblxuICAvLyB1aSB2YXJpYWJsZXNcbiAgaG91cnM6IHN0cmluZztcbiAgbWludXRlczogc3RyaW5nO1xuICBzZWNvbmRzOiBzdHJpbmc7XG4gIG1lcmlkaWFuOiBzdHJpbmc7XG5cbiAgLyoqIEBkZXByZWNhdGVkIC0gcGxlYXNlIHVzZSBgaXNFZGl0YWJsZWAgaW5zdGVhZCAqL1xuICBnZXQgaXNTcGlubmVyc1Zpc2libGUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuc2hvd1NwaW5uZXJzICYmICF0aGlzLnJlYWRvbmx5SW5wdXQ7XG4gIH1cblxuICBnZXQgaXNFZGl0YWJsZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISh0aGlzLnJlYWRvbmx5SW5wdXQgfHwgdGhpcy5kaXNhYmxlZCk7XG4gIH1cblxuICAvLyBtaW5cXG1heCB2YWxpZGF0aW9uIGZvciBpbnB1dCBmaWVsZHNcbiAgaW52YWxpZEhvdXJzID0gZmFsc2U7XG4gIGludmFsaWRNaW51dGVzID0gZmFsc2U7XG4gIGludmFsaWRTZWNvbmRzID0gZmFsc2U7XG5cbiAgLy8gdGltZSBwaWNrZXIgY29udHJvbHMgc3RhdGVcbiAgY2FuSW5jcmVtZW50SG91cnM6IGJvb2xlYW47XG4gIGNhbkluY3JlbWVudE1pbnV0ZXM6IGJvb2xlYW47XG4gIGNhbkluY3JlbWVudFNlY29uZHM6IGJvb2xlYW47XG5cbiAgY2FuRGVjcmVtZW50SG91cnM6IGJvb2xlYW47XG4gIGNhbkRlY3JlbWVudE1pbnV0ZXM6IGJvb2xlYW47XG4gIGNhbkRlY3JlbWVudFNlY29uZHM6IGJvb2xlYW47XG5cbiAgY2FuVG9nZ2xlTWVyaWRpYW46IGJvb2xlYW47XG5cbiAgLy8gY29udHJvbCB2YWx1ZSBhY2Nlc3NvciBtZXRob2RzXG4gIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1hbnlcbiAgb25DaGFuZ2UgPSBGdW5jdGlvbi5wcm90b3R5cGU7XG4gIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1hbnlcbiAgb25Ub3VjaGVkID0gRnVuY3Rpb24ucHJvdG90eXBlO1xuXG4gIHRpbWVwaWNrZXJTdWI6IFN1YnNjcmlwdGlvbjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBfY29uZmlnOiBUaW1lcGlja2VyQ29uZmlnLFxuICAgIHByaXZhdGUgX2NkOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBwcml2YXRlIF9zdG9yZTogVGltZXBpY2tlclN0b3JlLFxuICAgIHByaXZhdGUgX3RpbWVwaWNrZXJBY3Rpb25zOiBUaW1lcGlja2VyQWN0aW9uc1xuICApIHtcbiAgICBPYmplY3QuYXNzaWduKHRoaXMsIF9jb25maWcpO1xuXG4gICAgdGhpcy50aW1lcGlja2VyU3ViID0gX3N0b3JlXG4gICAgICAuc2VsZWN0KHN0YXRlID0+IHN0YXRlLnZhbHVlKVxuICAgICAgLnN1YnNjcmliZSgodmFsdWU6IERhdGUpID0+IHtcbiAgICAgICAgLy8gdXBkYXRlIFVJIHZhbHVlcyBpZiBkYXRlIGNoYW5nZWRcbiAgICAgICAgdGhpcy5fcmVuZGVyVGltZSh2YWx1ZSk7XG4gICAgICAgIHRoaXMub25DaGFuZ2UodmFsdWUpO1xuXG4gICAgICAgIHRoaXMuX3N0b3JlLmRpc3BhdGNoKFxuICAgICAgICAgIHRoaXMuX3RpbWVwaWNrZXJBY3Rpb25zLnVwZGF0ZUNvbnRyb2xzKGdldENvbnRyb2xzVmFsdWUodGhpcykpXG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgIF9zdG9yZVxuICAgICAgLnNlbGVjdChzdGF0ZSA9PiBzdGF0ZS5jb250cm9scylcbiAgICAgIC5zdWJzY3JpYmUoKGNvbnRyb2xzU3RhdGU6IFRpbWVwaWNrZXJDb250cm9scykgPT4ge1xuICAgICAgICB0aGlzLmlzVmFsaWQuZW1pdChpc0lucHV0VmFsaWQodGhpcy5ob3VycywgdGhpcy5taW51dGVzLCB0aGlzLnNlY29uZHMsIHRoaXMuaXNQTSgpKSk7XG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgY29udHJvbHNTdGF0ZSk7XG4gICAgICAgIF9jZC5tYXJrRm9yQ2hlY2soKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgcmVzZXRWYWxpZGF0aW9uKCk6IHZvaWQge1xuICAgIHRoaXMuaW52YWxpZEhvdXJzID0gZmFsc2U7XG4gICAgdGhpcy5pbnZhbGlkTWludXRlcyA9IGZhbHNlO1xuICAgIHRoaXMuaW52YWxpZFNlY29uZHMgPSBmYWxzZTtcbiAgfVxuXG4gIGlzUE0oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuc2hvd01lcmlkaWFuICYmIHRoaXMubWVyaWRpYW4gPT09IHRoaXMubWVyaWRpYW5zWzFdO1xuICB9XG5cbiAgcHJldkRlZigkZXZlbnQ6IEV2ZW50KSB7XG4gICAgJGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gIH1cblxuICB3aGVlbFNpZ24oJGV2ZW50OiBXaGVlbEV2ZW50SW5pdCk6IG51bWJlciB7XG4gICAgcmV0dXJuIE1hdGguc2lnbigkZXZlbnQuZGVsdGFZKSAqIC0xO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIHRoaXMuX3N0b3JlLmRpc3BhdGNoKFxuICAgICAgdGhpcy5fdGltZXBpY2tlckFjdGlvbnMudXBkYXRlQ29udHJvbHMoZ2V0Q29udHJvbHNWYWx1ZSh0aGlzKSlcbiAgICApO1xuICB9XG5cbiAgY2hhbmdlSG91cnMoc3RlcDogbnVtYmVyLCBzb3VyY2U6IFRpbWVDaGFuZ2VTb3VyY2UgPSAnJyk6IHZvaWQge1xuICAgIHRoaXMucmVzZXRWYWxpZGF0aW9uKCk7XG4gICAgdGhpcy5fc3RvcmUuZGlzcGF0Y2godGhpcy5fdGltZXBpY2tlckFjdGlvbnMuY2hhbmdlSG91cnMoeyBzdGVwLCBzb3VyY2UgfSkpO1xuICB9XG5cbiAgY2hhbmdlTWludXRlcyhzdGVwOiBudW1iZXIsIHNvdXJjZTogVGltZUNoYW5nZVNvdXJjZSA9ICcnKTogdm9pZCB7XG4gICAgdGhpcy5yZXNldFZhbGlkYXRpb24oKTtcbiAgICB0aGlzLl9zdG9yZS5kaXNwYXRjaChcbiAgICAgIHRoaXMuX3RpbWVwaWNrZXJBY3Rpb25zLmNoYW5nZU1pbnV0ZXMoeyBzdGVwLCBzb3VyY2UgfSlcbiAgICApO1xuICB9XG5cbiAgY2hhbmdlU2Vjb25kcyhzdGVwOiBudW1iZXIsIHNvdXJjZTogVGltZUNoYW5nZVNvdXJjZSA9ICcnKTogdm9pZCB7XG4gICAgdGhpcy5yZXNldFZhbGlkYXRpb24oKTtcbiAgICB0aGlzLl9zdG9yZS5kaXNwYXRjaChcbiAgICAgIHRoaXMuX3RpbWVwaWNrZXJBY3Rpb25zLmNoYW5nZVNlY29uZHMoeyBzdGVwLCBzb3VyY2UgfSlcbiAgICApO1xuICB9XG5cbiAgdXBkYXRlSG91cnMoaG91cnM6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMucmVzZXRWYWxpZGF0aW9uKCk7XG4gICAgdGhpcy5ob3VycyA9IGhvdXJzO1xuXG4gICAgY29uc3QgaXNWYWxpZCA9IGlzSG91cklucHV0VmFsaWQodGhpcy5ob3VycywgdGhpcy5pc1BNKCkpICYmIHRoaXMuaXNWYWxpZExpbWl0KCk7XG5cbiAgICBpZiAoIWlzVmFsaWQpIHtcbiAgICAgIHRoaXMuaW52YWxpZEhvdXJzID0gdHJ1ZTtcbiAgICAgIHRoaXMuaXNWYWxpZC5lbWl0KGZhbHNlKTtcbiAgICAgIHRoaXMub25DaGFuZ2UobnVsbCk7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl91cGRhdGVUaW1lKCk7XG4gIH1cblxuICB1cGRhdGVNaW51dGVzKG1pbnV0ZXM6IHN0cmluZykge1xuICAgIHRoaXMucmVzZXRWYWxpZGF0aW9uKCk7XG4gICAgdGhpcy5taW51dGVzID0gbWludXRlcztcblxuICAgIGNvbnN0IGlzVmFsaWQgPSBpc01pbnV0ZUlucHV0VmFsaWQodGhpcy5taW51dGVzKSAmJiB0aGlzLmlzVmFsaWRMaW1pdCgpO1xuXG4gICAgaWYgKCFpc1ZhbGlkKSB7XG4gICAgICB0aGlzLmludmFsaWRNaW51dGVzID0gdHJ1ZTtcbiAgICAgIHRoaXMuaXNWYWxpZC5lbWl0KGZhbHNlKTtcbiAgICAgIHRoaXMub25DaGFuZ2UobnVsbCk7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl91cGRhdGVUaW1lKCk7XG4gIH1cblxuICB1cGRhdGVTZWNvbmRzKHNlY29uZHM6IHN0cmluZykge1xuICAgIHRoaXMucmVzZXRWYWxpZGF0aW9uKCk7XG4gICAgdGhpcy5zZWNvbmRzID0gc2Vjb25kcztcblxuICAgIGNvbnN0IGlzVmFsaWQgPSBpc1NlY29uZElucHV0VmFsaWQodGhpcy5zZWNvbmRzKSAmJiB0aGlzLmlzVmFsaWRMaW1pdCgpO1xuXG4gICAgaWYgKCFpc1ZhbGlkKSB7XG4gICAgICB0aGlzLmludmFsaWRTZWNvbmRzID0gdHJ1ZTtcbiAgICAgIHRoaXMuaXNWYWxpZC5lbWl0KGZhbHNlKTtcbiAgICAgIHRoaXMub25DaGFuZ2UobnVsbCk7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl91cGRhdGVUaW1lKCk7XG4gIH1cblxuICBpc1ZhbGlkTGltaXQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGlzSW5wdXRMaW1pdFZhbGlkKHtcbiAgICAgIGhvdXI6IHRoaXMuaG91cnMsXG4gICAgICBtaW51dGU6IHRoaXMubWludXRlcyxcbiAgICAgIHNlY29uZHM6IHRoaXMuc2Vjb25kcyxcbiAgICAgIGlzUE06IHRoaXMuaXNQTSgpXG4gICAgfSwgdGhpcy5tYXgsIHRoaXMubWluKTtcbiAgfVxuXG4gIF91cGRhdGVUaW1lKCkge1xuICAgIGNvbnN0IF9zZWNvbmRzID0gdGhpcy5zaG93U2Vjb25kcyA/IHRoaXMuc2Vjb25kcyA6IHZvaWQgMDtcbiAgICBjb25zdCBfbWludXRlcyA9IHRoaXMuc2hvd01pbnV0ZXMgPyB0aGlzLm1pbnV0ZXMgOiB2b2lkIDA7XG4gICAgaWYgKCFpc0lucHV0VmFsaWQodGhpcy5ob3VycywgX21pbnV0ZXMsIF9zZWNvbmRzLCB0aGlzLmlzUE0oKSkpIHtcbiAgICAgIHRoaXMuaXNWYWxpZC5lbWl0KGZhbHNlKTtcbiAgICAgIHRoaXMub25DaGFuZ2UobnVsbCk7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9zdG9yZS5kaXNwYXRjaChcbiAgICAgIHRoaXMuX3RpbWVwaWNrZXJBY3Rpb25zLnNldFRpbWUoe1xuICAgICAgICBob3VyOiB0aGlzLmhvdXJzLFxuICAgICAgICBtaW51dGU6IHRoaXMubWludXRlcyxcbiAgICAgICAgc2Vjb25kczogdGhpcy5zZWNvbmRzLFxuICAgICAgICBpc1BNOiB0aGlzLmlzUE0oKVxuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgdG9nZ2xlTWVyaWRpYW4oKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnNob3dNZXJpZGlhbiB8fCAhdGhpcy5pc0VkaXRhYmxlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgX2hvdXJzUGVyRGF5SGFsZiA9IDEyO1xuICAgIHRoaXMuX3N0b3JlLmRpc3BhdGNoKFxuICAgICAgdGhpcy5fdGltZXBpY2tlckFjdGlvbnMuY2hhbmdlSG91cnMoe1xuICAgICAgICBzdGVwOiBfaG91cnNQZXJEYXlIYWxmLFxuICAgICAgICBzb3VyY2U6ICcnXG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogV3JpdGUgYSBuZXcgdmFsdWUgdG8gdGhlIGVsZW1lbnQuXG4gICAqL1xuICB3cml0ZVZhbHVlKG9iajogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCB8IERhdGUpOiB2b2lkIHtcbiAgICBpZiAoaXNWYWxpZERhdGUob2JqKSkge1xuICAgICAgdGhpcy5fc3RvcmUuZGlzcGF0Y2godGhpcy5fdGltZXBpY2tlckFjdGlvbnMud3JpdGVWYWx1ZShwYXJzZVRpbWUob2JqKSkpO1xuICAgIH0gZWxzZSBpZiAob2JqID09IG51bGwpIHtcbiAgICAgIHRoaXMuX3N0b3JlLmRpc3BhdGNoKHRoaXMuX3RpbWVwaWNrZXJBY3Rpb25zLndyaXRlVmFsdWUobnVsbCkpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgdGhlIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBjb250cm9sIHJlY2VpdmVzIGEgY2hhbmdlIGV2ZW50LlxuICAgKi9cbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWFueVxuICByZWdpc3Rlck9uQ2hhbmdlKGZuOiAoXzogYW55KSA9PiB7fSk6IHZvaWQge1xuICAgIHRoaXMub25DaGFuZ2UgPSBmbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgdGhlIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBjb250cm9sIHJlY2VpdmVzIGEgdG91Y2ggZXZlbnQuXG4gICAqL1xuICByZWdpc3Rlck9uVG91Y2hlZChmbjogKCkgPT4ge30pOiB2b2lkIHtcbiAgICB0aGlzLm9uVG91Y2hlZCA9IGZuO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIHdoZW4gdGhlIGNvbnRyb2wgc3RhdHVzIGNoYW5nZXMgdG8gb3IgZnJvbSBcImRpc2FibGVkXCIuXG4gICAqIERlcGVuZGluZyBvbiB0aGUgdmFsdWUsIGl0IHdpbGwgZW5hYmxlIG9yIGRpc2FibGUgdGhlIGFwcHJvcHJpYXRlIERPTSBlbGVtZW50LlxuICAgKlxuICAgKiBAcGFyYW0gaXNEaXNhYmxlZFxuICAgKi9cbiAgc2V0RGlzYWJsZWRTdGF0ZShpc0Rpc2FibGVkOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5kaXNhYmxlZCA9IGlzRGlzYWJsZWQ7XG4gICAgdGhpcy5fY2QubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnRpbWVwaWNrZXJTdWIudW5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIHByaXZhdGUgX3JlbmRlclRpbWUodmFsdWU6IHN0cmluZyB8IERhdGUpOiB2b2lkIHtcbiAgICBpZiAoIWlzVmFsaWREYXRlKHZhbHVlKSkge1xuICAgICAgdGhpcy5ob3VycyA9ICcnO1xuICAgICAgdGhpcy5taW51dGVzID0gJyc7XG4gICAgICB0aGlzLnNlY29uZHMgPSAnJztcbiAgICAgIHRoaXMubWVyaWRpYW4gPSB0aGlzLm1lcmlkaWFuc1swXTtcblxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IF92YWx1ZSA9IHBhcnNlVGltZSh2YWx1ZSk7XG4gICAgY29uc3QgX2hvdXJzUGVyRGF5SGFsZiA9IDEyO1xuICAgIGxldCBfaG91cnMgPSBfdmFsdWUuZ2V0SG91cnMoKTtcblxuICAgIGlmICh0aGlzLnNob3dNZXJpZGlhbikge1xuICAgICAgdGhpcy5tZXJpZGlhbiA9IHRoaXMubWVyaWRpYW5zW19ob3VycyA+PSBfaG91cnNQZXJEYXlIYWxmID8gMSA6IDBdO1xuICAgICAgX2hvdXJzID0gX2hvdXJzICUgX2hvdXJzUGVyRGF5SGFsZjtcbiAgICAgIC8vIHNob3VsZCBiZSAxMiBQTSwgbm90IDAwIFBNXG4gICAgICBpZiAoX2hvdXJzID09PSAwKSB7XG4gICAgICAgIF9ob3VycyA9IF9ob3Vyc1BlckRheUhhbGY7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5ob3VycyA9IHBhZE51bWJlcihfaG91cnMpO1xuICAgIHRoaXMubWludXRlcyA9IHBhZE51bWJlcihfdmFsdWUuZ2V0TWludXRlcygpKTtcbiAgICB0aGlzLnNlY29uZHMgPSBwYWROdW1iZXIoX3ZhbHVlLmdldFVUQ1NlY29uZHMoKSk7XG4gIH1cbn1cbiJdfQ==