@alauda-fe/common
Version:
Alauda frontend team common codes.
293 lines • 32.9 kB
JavaScript
/**
* @packageDocumentation
* @module translate
*/
import { ChangeDetectorRef, inject, Injectable, Pipe, } from '@angular/core';
import { Subject, takeUntil } from 'rxjs';
import { FIELD_NOT_AVAILABLE_PLACEHOLDER } from '../core/public-api';
import { RelativeTimeManagerService } from './relative-time-manager.service';
import { TranslateService } from './translate.service';
import * as i0 from "@angular/core";
/**
* 基础国际化格式化 Pipe 抽象类
* 提供响应式的 locale 变化监听功能
*/
class BaseIntlPipe {
constructor() {
this.destroy$$ = new Subject();
this.cdr = inject(ChangeDetectorRef);
this.translate = inject(TranslateService);
// 监听 locale 变化
this.translate.locale$.pipe(takeUntil(this.destroy$$)).subscribe(() => {
this.cdr.markForCheck();
});
}
ngOnDestroy() {
this.destroy$$.next();
this.destroy$$.complete();
}
static { this.ɵfac = function BaseIntlPipe_Factory(t) { return new (t || BaseIntlPipe)(); }; }
static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: BaseIntlPipe, factory: BaseIntlPipe.ɵfac }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(BaseIntlPipe, [{
type: Injectable
}], () => [], null); })();
/**
* 数字格式化 Pipe
* @example
* {{ 1234.56 | aclIntlNumber }} // "1,234.56"
* {{ 0.85 | aclIntlNumber:{ style: 'percent' } }} // "85%"
* {{ 1234.56 | aclIntlNumber:{ minimumFractionDigits: 2 } }} // "1,234.56"
*/
export class IntlNumberPipe extends BaseIntlPipe {
transform(value, options) {
if (value == null || isNaN(value)) {
return FIELD_NOT_AVAILABLE_PLACEHOLDER;
}
return this.translate.formatNumber(value, options || {});
}
static { this.ɵfac = /*@__PURE__*/ (() => { let ɵIntlNumberPipe_BaseFactory; return function IntlNumberPipe_Factory(t) { return (ɵIntlNumberPipe_BaseFactory || (ɵIntlNumberPipe_BaseFactory = i0.ɵɵgetInheritedFactory(IntlNumberPipe)))(t || IntlNumberPipe); }; })(); }
static { this.ɵpipe = /*@__PURE__*/ i0.ɵɵdefinePipe({ name: "aclIntlNumber", type: IntlNumberPipe, pure: false, standalone: true }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(IntlNumberPipe, [{
type: Pipe,
args: [{
name: 'aclIntlNumber',
pure: false,
standalone: true,
}]
}], null, null); })();
/**
* 货币格式化 Pipe
* @example
* {{ 1234.56 | aclIntlCurrency }} // "¥1,234.56"
* {{ 1234.56 | aclIntlCurrency:'USD' }} // "$1,234.56"
* {{ 1234.56 | aclIntlCurrency:'EUR':{ minimumFractionDigits: 2 } }} // "€1,234.56"
*/
export class IntlCurrencyPipe extends BaseIntlPipe {
transform(value, currency, options) {
if (value == null || isNaN(value)) {
return FIELD_NOT_AVAILABLE_PLACEHOLDER;
}
return this.translate.formatCurrency(value, currency, options);
}
static { this.ɵfac = /*@__PURE__*/ (() => { let ɵIntlCurrencyPipe_BaseFactory; return function IntlCurrencyPipe_Factory(t) { return (ɵIntlCurrencyPipe_BaseFactory || (ɵIntlCurrencyPipe_BaseFactory = i0.ɵɵgetInheritedFactory(IntlCurrencyPipe)))(t || IntlCurrencyPipe); }; })(); }
static { this.ɵpipe = /*@__PURE__*/ i0.ɵɵdefinePipe({ name: "aclIntlCurrency", type: IntlCurrencyPipe, pure: false, standalone: true }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(IntlCurrencyPipe, [{
type: Pipe,
args: [{
name: 'aclIntlCurrency',
pure: false,
standalone: true,
}]
}], null, null); })();
/**
* 百分比格式化 Pipe
* @example
* {{ 0.85 | aclIntlPercent }} // "85%"
* {{ 0.8567 | aclIntlPercent:{ minimumFractionDigits: 2 } }} // "85.67%"
*/
export class IntlPercentPipe extends BaseIntlPipe {
transform(value, options) {
if (value == null || isNaN(value)) {
return FIELD_NOT_AVAILABLE_PLACEHOLDER;
}
return this.translate.formatPercent(value, options || {});
}
static { this.ɵfac = /*@__PURE__*/ (() => { let ɵIntlPercentPipe_BaseFactory; return function IntlPercentPipe_Factory(t) { return (ɵIntlPercentPipe_BaseFactory || (ɵIntlPercentPipe_BaseFactory = i0.ɵɵgetInheritedFactory(IntlPercentPipe)))(t || IntlPercentPipe); }; })(); }
static { this.ɵpipe = /*@__PURE__*/ i0.ɵɵdefinePipe({ name: "aclIntlPercent", type: IntlPercentPipe, pure: false, standalone: true }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(IntlPercentPipe, [{
type: Pipe,
args: [{
name: 'aclIntlPercent',
pure: false,
standalone: true,
}]
}], null, null); })();
/**
* 日期格式化 Pipe
* @example
* {{ date | aclIntlDate }} // "2025/01/01"
* {{ date | aclIntlDate:{ dateStyle: 'long' } }} // "2025年1月1日"
* {{ date | aclIntlDate:{ year: 'numeric', month: 'long' } }} // "2025年1月"
*/
export class IntlDatePipe extends BaseIntlPipe {
transform(value, options) {
if (value == null) {
return FIELD_NOT_AVAILABLE_PLACEHOLDER;
}
// 检查日期是否有效
const date = value instanceof Date ? value : new Date(value);
if (isNaN(date.getTime())) {
return FIELD_NOT_AVAILABLE_PLACEHOLDER;
}
return this.translate.formatDate(value, options);
}
static { this.ɵfac = /*@__PURE__*/ (() => { let ɵIntlDatePipe_BaseFactory; return function IntlDatePipe_Factory(t) { return (ɵIntlDatePipe_BaseFactory || (ɵIntlDatePipe_BaseFactory = i0.ɵɵgetInheritedFactory(IntlDatePipe)))(t || IntlDatePipe); }; })(); }
static { this.ɵpipe = /*@__PURE__*/ i0.ɵɵdefinePipe({ name: "aclIntlDate", type: IntlDatePipe, pure: false, standalone: true }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(IntlDatePipe, [{
type: Pipe,
args: [{
name: 'aclIntlDate',
pure: false,
standalone: true,
}]
}], null, null); })();
/**
* 日期时间格式化 Pipe
* @example
* {{ date | aclIntlDateTime }} // "2025/01/01 14:30:00"
* {{ date | aclIntlDateTime:{ dateStyle: 'medium', timeStyle: 'short' } }} // "2025年1月1日 14:30"
*/
export class IntlDateTimePipe extends BaseIntlPipe {
transform(value, options) {
if (value == null) {
return FIELD_NOT_AVAILABLE_PLACEHOLDER;
}
// 检查日期是否有效
const date = value instanceof Date ? value : new Date(value);
if (isNaN(date.getTime())) {
return FIELD_NOT_AVAILABLE_PLACEHOLDER;
}
return this.translate.formatDateTime(value, options);
}
static { this.ɵfac = /*@__PURE__*/ (() => { let ɵIntlDateTimePipe_BaseFactory; return function IntlDateTimePipe_Factory(t) { return (ɵIntlDateTimePipe_BaseFactory || (ɵIntlDateTimePipe_BaseFactory = i0.ɵɵgetInheritedFactory(IntlDateTimePipe)))(t || IntlDateTimePipe); }; })(); }
static { this.ɵpipe = /*@__PURE__*/ i0.ɵɵdefinePipe({ name: "aclIntlDateTime", type: IntlDateTimePipe, pure: false, standalone: true }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(IntlDateTimePipe, [{
type: Pipe,
args: [{
name: 'aclIntlDateTime',
pure: false,
standalone: true,
}]
}], null, null); })();
// 时间间隔常量 (毫秒)
const MILLISECONDS_SECOND = 1000;
const MILLISECONDS_MINUTE = MILLISECONDS_SECOND * 60;
const MILLISECONDS_HOUR = MILLISECONDS_MINUTE * 60;
const MILLISECONDS_DAY = MILLISECONDS_HOUR * 24;
/**
* 相对时间格式化 Pipe
* 支持两种使用方式:
* 1. 传入 Date 对象,自动计算相对时间
* 2. 传入数值和单位,手动指定相对时间
*
* 特性:
* - 自动刷新UI:根据时间距离智能调整刷新频率
* - 性能优化:共享定时器,避免大量单独计时器
* - 响应式设计:监听语言变化自动更新
*
* @example
* // 自动计算
* {{ pastDate | aclIntlRelativeTime }} // "2 hours ago"
* {{ futureDate | aclIntlRelativeTime:{ numeric: 'always' } }} // "in 2 hours"
*
* // 手动指定
* {{ -1 | aclIntlRelativeTime:'day' }} // "yesterday"
* {{ 2 | aclIntlRelativeTime:'hour':{ numeric: 'always' } }} // "in 2 hours"
* {{ -30 | aclIntlRelativeTime:'minute':{ numeric: 'always' } }} // "30 minutes ago"
*/
export class IntlRelativeTimePipe extends BaseIntlPipe {
constructor() {
super(...arguments);
this.relativeTimeManager = inject(RelativeTimeManagerService);
}
ngOnDestroy() {
super.ngOnDestroy();
this.cleanupRefresh();
}
transform(value, unitOrOptions, options) {
if (value == null) {
return FIELD_NOT_AVAILABLE_PLACEHOLDER;
}
// 情况1: 传入 Date 对象,自动计算相对时间(支持自动刷新)
if (value instanceof Date) {
this.currentValue = value;
this.setupAutoRefresh(value);
const relativeOptions = unitOrOptions;
return this.translate.formatRelativeTime(value, relativeOptions);
}
// 情况2: 传入数字,需要手动指定单位(不需要自动刷新)
if (typeof value === 'number') {
this.cleanupRefresh(); // 清除可能存在的刷新订阅
if (isNaN(value)) {
return FIELD_NOT_AVAILABLE_PLACEHOLDER;
}
const unit = unitOrOptions;
if (!unit) {
return FIELD_NOT_AVAILABLE_PLACEHOLDER;
}
// 对于手动指定单位的情况,直接调用翻译服务
return this.translate.formatRelativeTime(value, unit, options);
}
return FIELD_NOT_AVAILABLE_PLACEHOLDER;
}
/**
* 设置自动刷新机制
* 使用共享的计时器管理器,提高多实例场景下的性能
* 时间间隔大于一天时不设置自动刷新
*/
setupAutoRefresh(date) {
const distance = Math.abs(Date.now() - date.getTime());
// 时间间隔大于一天时,不需要自动刷新
if (distance >= MILLISECONDS_DAY) {
this.cleanupRefresh();
return;
}
let interval;
if (distance < MILLISECONDS_MINUTE) {
interval = MILLISECONDS_SECOND;
}
else if (distance < MILLISECONDS_HOUR) {
interval = MILLISECONDS_MINUTE;
}
else {
interval = MILLISECONDS_HOUR;
}
// 如果刷新间隔没有变化,无需重新订阅
if (this.currentInterval === interval && this.refreshSubscription) {
return;
}
this.cleanupRefresh();
this.currentInterval = interval;
// 订阅共享的刷新事件
this.refreshSubscription = this.relativeTimeManager
.getRefreshSubject(interval)
.pipe(takeUntil(this.destroy$$))
.subscribe(() => {
this.cdr.markForCheck();
// 重新计算刷新间隔,适应时间变化
if (this.currentValue) {
this.setupAutoRefresh(this.currentValue);
}
});
}
/**
* 清理刷新相关资源
*/
cleanupRefresh() {
if (this.refreshSubscription) {
this.refreshSubscription.unsubscribe();
this.refreshSubscription = undefined;
}
if (this.currentInterval !== undefined) {
this.relativeTimeManager.releaseRefreshSubject(this.currentInterval);
this.currentInterval = undefined;
}
}
static { this.ɵfac = /*@__PURE__*/ (() => { let ɵIntlRelativeTimePipe_BaseFactory; return function IntlRelativeTimePipe_Factory(t) { return (ɵIntlRelativeTimePipe_BaseFactory || (ɵIntlRelativeTimePipe_BaseFactory = i0.ɵɵgetInheritedFactory(IntlRelativeTimePipe)))(t || IntlRelativeTimePipe); }; })(); }
static { this.ɵpipe = /*@__PURE__*/ i0.ɵɵdefinePipe({ name: "aclIntlRelativeTime", type: IntlRelativeTimePipe, pure: false, standalone: true }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(IntlRelativeTimePipe, [{
type: Pipe,
args: [{
name: 'aclIntlRelativeTime',
pure: false,
standalone: true,
}]
}], null, null); })();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50bC1mb3JtYXQucGlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWJzL2NvbW1vbi9zcmMvdHJhbnNsYXRlL2ludGwtZm9ybWF0LnBpcGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sRUFDTCxpQkFBaUIsRUFDakIsTUFBTSxFQUNOLFVBQVUsRUFFVixJQUFJLEdBRUwsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLE9BQU8sRUFBZ0IsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRXhELE9BQU8sRUFBRSwrQkFBK0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRXJFLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzdFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDOztBQUV2RDs7O0dBR0c7QUFDSCxNQUNlLFlBQVk7SUFPekI7UUFObUIsY0FBUyxHQUFHLElBQUksT0FBTyxFQUFRLENBQUM7UUFFaEMsUUFBRyxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBRWhDLGNBQVMsR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUd0RCxlQUFlO1FBQ2YsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFO1lBQ3BFLElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDMUIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDdEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUM1QixDQUFDOzZFQWpCWSxZQUFZO3VFQUFaLFlBQVksV0FBWixZQUFZOztpRkFBWixZQUFZO2NBRDFCLFVBQVU7O0FBdUJYOzs7Ozs7R0FNRztBQU1ILE1BQU0sT0FBTyxjQUFlLFNBQVEsWUFBWTtJQUM5QyxTQUFTLENBQUMsS0FBYSxFQUFFLE9BQWtDO1FBQ3pELElBQUksS0FBSyxJQUFJLElBQUksSUFBSSxLQUFLLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNsQyxPQUFPLCtCQUErQixDQUFDO1FBQ3pDLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxPQUFPLElBQUksRUFBRSxDQUFDLENBQUM7SUFDM0QsQ0FBQzs0TkFQVSxjQUFjLFNBQWQsY0FBYzt1RkFBZCxjQUFjOztpRkFBZCxjQUFjO2NBTDFCLElBQUk7ZUFBQztnQkFDSixJQUFJLEVBQUUsZUFBZTtnQkFDckIsSUFBSSxFQUFFLEtBQUs7Z0JBQ1gsVUFBVSxFQUFFLElBQUk7YUFDakI7O0FBV0Q7Ozs7OztHQU1HO0FBTUgsTUFBTSxPQUFPLGdCQUFpQixTQUFRLFlBQVk7SUFDaEQsU0FBUyxDQUNQLEtBQWEsRUFDYixRQUFpQixFQUNqQixPQUFrQztRQUVsQyxJQUFJLEtBQUssSUFBSSxJQUFJLElBQUksS0FBSyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDbEMsT0FBTywrQkFBK0IsQ0FBQztRQUN6QyxDQUFDO1FBRUQsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ2pFLENBQUM7b09BWFUsZ0JBQWdCLFNBQWhCLGdCQUFnQjt5RkFBaEIsZ0JBQWdCOztpRkFBaEIsZ0JBQWdCO2NBTDVCLElBQUk7ZUFBQztnQkFDSixJQUFJLEVBQUUsaUJBQWlCO2dCQUN2QixJQUFJLEVBQUUsS0FBSztnQkFDWCxVQUFVLEVBQUUsSUFBSTthQUNqQjs7QUFlRDs7Ozs7R0FLRztBQU1ILE1BQU0sT0FBTyxlQUFnQixTQUFRLFlBQVk7SUFDL0MsU0FBUyxDQUNQLEtBQWEsRUFDYixPQUFpRDtRQUVqRCxJQUFJLEtBQUssSUFBSSxJQUFJLElBQUksS0FBSyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDbEMsT0FBTywrQkFBK0IsQ0FBQztRQUN6QyxDQUFDO1FBRUQsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsT0FBTyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQzVELENBQUM7Z09BVlUsZUFBZSxTQUFmLGVBQWU7d0ZBQWYsZUFBZTs7aUZBQWYsZUFBZTtjQUwzQixJQUFJO2VBQUM7Z0JBQ0osSUFBSSxFQUFFLGdCQUFnQjtnQkFDdEIsSUFBSSxFQUFFLEtBQUs7Z0JBQ1gsVUFBVSxFQUFFLElBQUk7YUFDakI7O0FBY0Q7Ozs7OztHQU1HO0FBTUgsTUFBTSxPQUFPLFlBQWEsU0FBUSxZQUFZO0lBQzVDLFNBQVMsQ0FDUCxLQUE2QixFQUM3QixPQUFvQztRQUVwQyxJQUFJLEtBQUssSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUNsQixPQUFPLCtCQUErQixDQUFDO1FBQ3pDLENBQUM7UUFFRCxXQUFXO1FBQ1gsTUFBTSxJQUFJLEdBQUcsS0FBSyxZQUFZLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM3RCxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDO1lBQzFCLE9BQU8sK0JBQStCLENBQUM7UUFDekMsQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ25ELENBQUM7b05BaEJVLFlBQVksU0FBWixZQUFZO3FGQUFaLFlBQVk7O2lGQUFaLFlBQVk7Y0FMeEIsSUFBSTtlQUFDO2dCQUNKLElBQUksRUFBRSxhQUFhO2dCQUNuQixJQUFJLEVBQUUsS0FBSztnQkFDWCxVQUFVLEVBQUUsSUFBSTthQUNqQjs7QUFvQkQ7Ozs7O0dBS0c7QUFNSCxNQUFNLE9BQU8sZ0JBQWlCLFNBQVEsWUFBWTtJQUNoRCxTQUFTLENBQ1AsS0FBNkIsRUFDN0IsT0FBb0M7UUFFcEMsSUFBSSxLQUFLLElBQUksSUFBSSxFQUFFLENBQUM7WUFDbEIsT0FBTywrQkFBK0IsQ0FBQztRQUN6QyxDQUFDO1FBRUQsV0FBVztRQUNYLE1BQU0sSUFBSSxHQUFHLEtBQUssWUFBWSxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDN0QsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsQ0FBQztZQUMxQixPQUFPLCtCQUErQixDQUFDO1FBQ3pDLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQztJQUN2RCxDQUFDO29PQWhCVSxnQkFBZ0IsU0FBaEIsZ0JBQWdCO3lGQUFoQixnQkFBZ0I7O2lGQUFoQixnQkFBZ0I7Y0FMNUIsSUFBSTtlQUFDO2dCQUNKLElBQUksRUFBRSxpQkFBaUI7Z0JBQ3ZCLElBQUksRUFBRSxLQUFLO2dCQUNYLFVBQVUsRUFBRSxJQUFJO2FBQ2pCOztBQW9CRCxjQUFjO0FBQ2QsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLENBQUM7QUFDakMsTUFBTSxtQkFBbUIsR0FBRyxtQkFBbUIsR0FBRyxFQUFFLENBQUM7QUFDckQsTUFBTSxpQkFBaUIsR0FBRyxtQkFBbUIsR0FBRyxFQUFFLENBQUM7QUFDbkQsTUFBTSxnQkFBZ0IsR0FBRyxpQkFBaUIsR0FBRyxFQUFFLENBQUM7QUFFaEQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHO0FBTUgsTUFBTSxPQUFPLG9CQUNYLFNBQVEsWUFBWTtJQU50Qjs7UUFTbUIsd0JBQW1CLEdBQUcsTUFBTSxDQUFDLDBCQUEwQixDQUFDLENBQUM7S0FnSDNFO0lBMUdVLFdBQVc7UUFDbEIsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ3BCLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztJQUN4QixDQUFDO0lBRUQsU0FBUyxDQUNQLEtBQW9CLEVBQ3BCLGFBRWtDLEVBQ2xDLE9BQXdDO1FBRXhDLElBQUksS0FBSyxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ2xCLE9BQU8sK0JBQStCLENBQUM7UUFDekMsQ0FBQztRQUVELG1DQUFtQztRQUNuQyxJQUFJLEtBQUssWUFBWSxJQUFJLEVBQUUsQ0FBQztZQUMxQixJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQztZQUMxQixJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFN0IsTUFBTSxlQUFlLEdBQUcsYUFFWCxDQUFDO1lBRWQsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLGtCQUFrQixDQUFDLEtBQUssRUFBRSxlQUFlLENBQUMsQ0FBQztRQUNuRSxDQUFDO1FBRUQsOEJBQThCO1FBQzlCLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDOUIsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUMsY0FBYztZQUVyQyxJQUFJLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUNqQixPQUFPLCtCQUErQixDQUFDO1lBQ3pDLENBQUM7WUFFRCxNQUFNLElBQUksR0FBRyxhQUE0QyxDQUFDO1lBQzFELElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDVixPQUFPLCtCQUErQixDQUFDO1lBQ3pDLENBQUM7WUFFRCx1QkFBdUI7WUFDdkIsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLGtCQUFrQixDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDakUsQ0FBQztRQUVELE9BQU8sK0JBQStCLENBQUM7SUFDekMsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxnQkFBZ0IsQ0FBQyxJQUFVO1FBQ2pDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBRXZELG9CQUFvQjtRQUNwQixJQUFJLFFBQVEsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO1lBQ2pDLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUN0QixPQUFPO1FBQ1QsQ0FBQztRQUVELElBQUksUUFBZ0IsQ0FBQztRQUNyQixJQUFJLFFBQVEsR0FBRyxtQkFBbUIsRUFBRSxDQUFDO1lBQ25DLFFBQVEsR0FBRyxtQkFBbUIsQ0FBQztRQUNqQyxDQUFDO2FBQU0sSUFBSSxRQUFRLEdBQUcsaUJBQWlCLEVBQUUsQ0FBQztZQUN4QyxRQUFRLEdBQUcsbUJBQW1CLENBQUM7UUFDakMsQ0FBQzthQUFNLENBQUM7WUFDTixRQUFRLEdBQUcsaUJBQWlCLENBQUM7UUFDL0IsQ0FBQztRQUVELG9CQUFvQjtRQUNwQixJQUFJLElBQUksQ0FBQyxlQUFlLEtBQUssUUFBUSxJQUFJLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBQ2xFLE9BQU87UUFDVCxDQUFDO1FBRUQsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxlQUFlLEdBQUcsUUFBUSxDQUFDO1FBRWhDLFlBQVk7UUFDWixJQUFJLENBQUMsbUJBQW1CLEdBQUcsSUFBSSxDQUFDLG1CQUFtQjthQUNoRCxpQkFBaUIsQ0FBQyxRQUFRLENBQUM7YUFDM0IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7YUFDL0IsU0FBUyxDQUFDLEdBQUcsRUFBRTtZQUNkLElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDeEIsa0JBQWtCO1lBQ2xCLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUN0QixJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQzNDLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRDs7T0FFRztJQUNLLGNBQWM7UUFDcEIsSUFBSSxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztZQUM3QixJQUFJLENBQUMsbUJBQW1CLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDdkMsSUFBSSxDQUFDLG1CQUFtQixHQUFHLFNBQVMsQ0FBQztRQUN2QyxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsZUFBZSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3ZDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7WUFDckUsSUFBSSxDQUFDLGVBQWUsR0FBRyxTQUFTLENBQUM7UUFDbkMsQ0FBQztJQUNILENBQUM7b1BBbkhVLG9CQUFvQixTQUFwQixvQkFBb0I7NkZBQXBCLG9CQUFvQjs7aUZBQXBCLG9CQUFvQjtjQUxoQyxJQUFJO2VBQUM7Z0JBQ0osSUFBSSxFQUFFLHFCQUFxQjtnQkFDM0IsSUFBSSxFQUFFLEtBQUs7Z0JBQ1gsVUFBVSxFQUFFLElBQUk7YUFDakIiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICogQG1vZHVsZSB0cmFuc2xhdGVcbiAqL1xuXG5pbXBvcnQge1xuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgaW5qZWN0LFxuICBJbmplY3RhYmxlLFxuICBPbkRlc3Ryb3ksXG4gIFBpcGUsXG4gIFBpcGVUcmFuc2Zvcm0sXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgU3ViamVjdCwgU3Vic2NyaXB0aW9uLCB0YWtlVW50aWwgfSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHsgRklFTERfTk9UX0FWQUlMQUJMRV9QTEFDRUhPTERFUiB9IGZyb20gJy4uL2NvcmUvcHVibGljLWFwaSc7XG5cbmltcG9ydCB7IFJlbGF0aXZlVGltZU1hbmFnZXJTZXJ2aWNlIH0gZnJvbSAnLi9yZWxhdGl2ZS10aW1lLW1hbmFnZXIuc2VydmljZSc7XG5pbXBvcnQgeyBUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnLi90cmFuc2xhdGUuc2VydmljZSc7XG5cbi8qKlxuICog5Z+656GA5Zu96ZmF5YyW5qC85byP5YyWIFBpcGUg5oq96LGh57G7XG4gKiDmj5Dkvpvlk43lupTlvI/nmoQgbG9jYWxlIOWPmOWMluebkeWQrOWKn+iDvVxuICovXG5ASW5qZWN0YWJsZSgpXG5hYnN0cmFjdCBjbGFzcyBCYXNlSW50bFBpcGUgaW1wbGVtZW50cyBQaXBlVHJhbnNmb3JtLCBPbkRlc3Ryb3kge1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZGVzdHJveSQkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgY2RyID0gaW5qZWN0KENoYW5nZURldGVjdG9yUmVmKTtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgdHJhbnNsYXRlID0gaW5qZWN0KFRyYW5zbGF0ZVNlcnZpY2UpO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIC8vIOebkeWQrCBsb2NhbGUg5Y+Y5YyWXG4gICAgdGhpcy50cmFuc2xhdGUubG9jYWxlJC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkJCkpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgICB9KTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMuZGVzdHJveSQkLm5leHQoKTtcbiAgICB0aGlzLmRlc3Ryb3kkJC5jb21wbGV0ZSgpO1xuICB9XG5cbiAgYWJzdHJhY3QgdHJhbnNmb3JtKHZhbHVlOiBhbnksIC4uLmFyZ3M6IGFueVtdKTogc3RyaW5nO1xufVxuXG4vKipcbiAqIOaVsOWtl+agvOW8j+WMliBQaXBlXG4gKiBAZXhhbXBsZVxuICoge3sgMTIzNC41NiB8IGFjbEludGxOdW1iZXIgfX0gLy8gXCIxLDIzNC41NlwiXG4gKiB7eyAwLjg1IHwgYWNsSW50bE51bWJlcjp7IHN0eWxlOiAncGVyY2VudCcgfSB9fSAvLyBcIjg1JVwiXG4gKiB7eyAxMjM0LjU2IHwgYWNsSW50bE51bWJlcjp7IG1pbmltdW1GcmFjdGlvbkRpZ2l0czogMiB9IH19IC8vIFwiMSwyMzQuNTZcIlxuICovXG5AUGlwZSh7XG4gIG5hbWU6ICdhY2xJbnRsTnVtYmVyJyxcbiAgcHVyZTogZmFsc2UsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG59KVxuZXhwb3J0IGNsYXNzIEludGxOdW1iZXJQaXBlIGV4dGVuZHMgQmFzZUludGxQaXBlIGltcGxlbWVudHMgUGlwZVRyYW5zZm9ybSB7XG4gIHRyYW5zZm9ybSh2YWx1ZTogbnVtYmVyLCBvcHRpb25zPzogSW50bC5OdW1iZXJGb3JtYXRPcHRpb25zKTogc3RyaW5nIHtcbiAgICBpZiAodmFsdWUgPT0gbnVsbCB8fCBpc05hTih2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBGSUVMRF9OT1RfQVZBSUxBQkxFX1BMQUNFSE9MREVSO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnRyYW5zbGF0ZS5mb3JtYXROdW1iZXIodmFsdWUsIG9wdGlvbnMgfHwge30pO1xuICB9XG59XG5cbi8qKlxuICog6LSn5biB5qC85byP5YyWIFBpcGVcbiAqIEBleGFtcGxlXG4gKiB7eyAxMjM0LjU2IHwgYWNsSW50bEN1cnJlbmN5IH19IC8vIFwiwqUxLDIzNC41NlwiXG4gKiB7eyAxMjM0LjU2IHwgYWNsSW50bEN1cnJlbmN5OidVU0QnIH19IC8vIFwiJDEsMjM0LjU2XCJcbiAqIHt7IDEyMzQuNTYgfCBhY2xJbnRsQ3VycmVuY3k6J0VVUic6eyBtaW5pbXVtRnJhY3Rpb25EaWdpdHM6IDIgfSB9fSAvLyBcIuKCrDEsMjM0LjU2XCJcbiAqL1xuQFBpcGUoe1xuICBuYW1lOiAnYWNsSW50bEN1cnJlbmN5JyxcbiAgcHVyZTogZmFsc2UsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG59KVxuZXhwb3J0IGNsYXNzIEludGxDdXJyZW5jeVBpcGUgZXh0ZW5kcyBCYXNlSW50bFBpcGUgaW1wbGVtZW50cyBQaXBlVHJhbnNmb3JtIHtcbiAgdHJhbnNmb3JtKFxuICAgIHZhbHVlOiBudW1iZXIsXG4gICAgY3VycmVuY3k/OiBzdHJpbmcsXG4gICAgb3B0aW9ucz86IEludGwuTnVtYmVyRm9ybWF0T3B0aW9ucyxcbiAgKTogc3RyaW5nIHtcbiAgICBpZiAodmFsdWUgPT0gbnVsbCB8fCBpc05hTih2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBGSUVMRF9OT1RfQVZBSUxBQkxFX1BMQUNFSE9MREVSO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnRyYW5zbGF0ZS5mb3JtYXRDdXJyZW5jeSh2YWx1ZSwgY3VycmVuY3ksIG9wdGlvbnMpO1xuICB9XG59XG5cbi8qKlxuICog55m+5YiG5q+U5qC85byP5YyWIFBpcGVcbiAqIEBleGFtcGxlXG4gKiB7eyAwLjg1IHwgYWNsSW50bFBlcmNlbnQgfX0gLy8gXCI4NSVcIlxuICoge3sgMC44NTY3IHwgYWNsSW50bFBlcmNlbnQ6eyBtaW5pbXVtRnJhY3Rpb25EaWdpdHM6IDIgfSB9fSAvLyBcIjg1LjY3JVwiXG4gKi9cbkBQaXBlKHtcbiAgbmFtZTogJ2FjbEludGxQZXJjZW50JyxcbiAgcHVyZTogZmFsc2UsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG59KVxuZXhwb3J0IGNsYXNzIEludGxQZXJjZW50UGlwZSBleHRlbmRzIEJhc2VJbnRsUGlwZSBpbXBsZW1lbnRzIFBpcGVUcmFuc2Zvcm0ge1xuICB0cmFuc2Zvcm0oXG4gICAgdmFsdWU6IG51bWJlcixcbiAgICBvcHRpb25zPzogT21pdDxJbnRsLk51bWJlckZvcm1hdE9wdGlvbnMsICdzdHlsZSc+LFxuICApOiBzdHJpbmcge1xuICAgIGlmICh2YWx1ZSA9PSBudWxsIHx8IGlzTmFOKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIEZJRUxEX05PVF9BVkFJTEFCTEVfUExBQ0VIT0xERVI7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMudHJhbnNsYXRlLmZvcm1hdFBlcmNlbnQodmFsdWUsIG9wdGlvbnMgfHwge30pO1xuICB9XG59XG5cbi8qKlxuICog5pel5pyf5qC85byP5YyWIFBpcGVcbiAqIEBleGFtcGxlXG4gKiB7eyBkYXRlIHwgYWNsSW50bERhdGUgfX0gLy8gXCIyMDI1LzAxLzAxXCJcbiAqIHt7IGRhdGUgfCBhY2xJbnRsRGF0ZTp7IGRhdGVTdHlsZTogJ2xvbmcnIH0gfX0gLy8gXCIyMDI15bm0MeaciDHml6VcIlxuICoge3sgZGF0ZSB8IGFjbEludGxEYXRlOnsgeWVhcjogJ251bWVyaWMnLCBtb250aDogJ2xvbmcnIH0gfX0gLy8gXCIyMDI15bm0MeaciFwiXG4gKi9cbkBQaXBlKHtcbiAgbmFtZTogJ2FjbEludGxEYXRlJyxcbiAgcHVyZTogZmFsc2UsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG59KVxuZXhwb3J0IGNsYXNzIEludGxEYXRlUGlwZSBleHRlbmRzIEJhc2VJbnRsUGlwZSBpbXBsZW1lbnRzIFBpcGVUcmFuc2Zvcm0ge1xuICB0cmFuc2Zvcm0oXG4gICAgdmFsdWU6IERhdGUgfCBzdHJpbmcgfCBudW1iZXIsXG4gICAgb3B0aW9ucz86IEludGwuRGF0ZVRpbWVGb3JtYXRPcHRpb25zLFxuICApOiBzdHJpbmcge1xuICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gRklFTERfTk9UX0FWQUlMQUJMRV9QTEFDRUhPTERFUjtcbiAgICB9XG5cbiAgICAvLyDmo4Dmn6Xml6XmnJ/mmK/lkKbmnInmlYhcbiAgICBjb25zdCBkYXRlID0gdmFsdWUgaW5zdGFuY2VvZiBEYXRlID8gdmFsdWUgOiBuZXcgRGF0ZSh2YWx1ZSk7XG4gICAgaWYgKGlzTmFOKGRhdGUuZ2V0VGltZSgpKSkge1xuICAgICAgcmV0dXJuIEZJRUxEX05PVF9BVkFJTEFCTEVfUExBQ0VIT0xERVI7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMudHJhbnNsYXRlLmZvcm1hdERhdGUodmFsdWUsIG9wdGlvbnMpO1xuICB9XG59XG5cbi8qKlxuICog5pel5pyf5pe26Ze05qC85byP5YyWIFBpcGVcbiAqIEBleGFtcGxlXG4gKiB7eyBkYXRlIHwgYWNsSW50bERhdGVUaW1lIH19IC8vIFwiMjAyNS8wMS8wMSAxNDozMDowMFwiXG4gKiB7eyBkYXRlIHwgYWNsSW50bERhdGVUaW1lOnsgZGF0ZVN0eWxlOiAnbWVkaXVtJywgdGltZVN0eWxlOiAnc2hvcnQnIH0gfX0gLy8gXCIyMDI15bm0MeaciDHml6UgMTQ6MzBcIlxuICovXG5AUGlwZSh7XG4gIG5hbWU6ICdhY2xJbnRsRGF0ZVRpbWUnLFxuICBwdXJlOiBmYWxzZSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbn0pXG5leHBvcnQgY2xhc3MgSW50bERhdGVUaW1lUGlwZSBleHRlbmRzIEJhc2VJbnRsUGlwZSBpbXBsZW1lbnRzIFBpcGVUcmFuc2Zvcm0ge1xuICB0cmFuc2Zvcm0oXG4gICAgdmFsdWU6IERhdGUgfCBzdHJpbmcgfCBudW1iZXIsXG4gICAgb3B0aW9ucz86IEludGwuRGF0ZVRpbWVGb3JtYXRPcHRpb25zLFxuICApOiBzdHJpbmcge1xuICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gRklFTERfTk9UX0FWQUlMQUJMRV9QTEFDRUhPTERFUjtcbiAgICB9XG5cbiAgICAvLyDmo4Dmn6Xml6XmnJ/mmK/lkKbmnInmlYhcbiAgICBjb25zdCBkYXRlID0gdmFsdWUgaW5zdGFuY2VvZiBEYXRlID8gdmFsdWUgOiBuZXcgRGF0ZSh2YWx1ZSk7XG4gICAgaWYgKGlzTmFOKGRhdGUuZ2V0VGltZSgpKSkge1xuICAgICAgcmV0dXJuIEZJRUxEX05PVF9BVkFJTEFCTEVfUExBQ0VIT0xERVI7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMudHJhbnNsYXRlLmZvcm1hdERhdGVUaW1lKHZhbHVlLCBvcHRpb25zKTtcbiAgfVxufVxuXG4vLyDml7bpl7Tpl7TpmpTluLjph48gKOavq+enkilcbmNvbnN0IE1JTExJU0VDT05EU19TRUNPTkQgPSAxMDAwO1xuY29uc3QgTUlMTElTRUNPTkRTX01JTlVURSA9IE1JTExJU0VDT05EU19TRUNPTkQgKiA2MDtcbmNvbnN0IE1JTExJU0VDT05EU19IT1VSID0gTUlMTElTRUNPTkRTX01JTlVURSAqIDYwO1xuY29uc3QgTUlMTElTRUNPTkRTX0RBWSA9IE1JTExJU0VDT05EU19IT1VSICogMjQ7XG5cbi8qKlxuICog55u45a+55pe26Ze05qC85byP5YyWIFBpcGVcbiAqIOaUr+aMgeS4pOenjeS9v+eUqOaWueW8j++8mlxuICogMS4g5Lyg5YWlIERhdGUg5a+56LGh77yM6Ieq5Yqo6K6h566X55u45a+55pe26Ze0XG4gKiAyLiDkvKDlhaXmlbDlgLzlkozljZXkvY3vvIzmiYvliqjmjIflrprnm7jlr7nml7bpl7RcbiAqXG4gKiDnibnmgKfvvJpcbiAqIC0g6Ieq5Yqo5Yi35pawVUnvvJrmoLnmja7ml7bpl7Tot53nprvmmbrog73osIPmlbTliLfmlrDpopHnjodcbiAqIC0g5oCn6IO95LyY5YyW77ya5YWx5Lqr5a6a5pe25Zmo77yM6YG/5YWN5aSn6YeP5Y2V54us6K6h5pe25ZmoXG4gKiAtIOWTjeW6lOW8j+iuvuiuoe+8muebkeWQrOivreiogOWPmOWMluiHquWKqOabtOaWsFxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyDoh6rliqjorqHnrpdcbiAqIHt7IHBhc3REYXRlIHwgYWNsSW50bFJlbGF0aXZlVGltZSB9fSAvLyBcIjIgaG91cnMgYWdvXCJcbiAqIHt7IGZ1dHVyZURhdGUgfCBhY2xJbnRsUmVsYXRpdmVUaW1lOnsgbnVtZXJpYzogJ2Fsd2F5cycgfSB9fSAvLyBcImluIDIgaG91cnNcIlxuICpcbiAqIC8vIOaJi+WKqOaMh+WumlxuICoge3sgLTEgfCBhY2xJbnRsUmVsYXRpdmVUaW1lOidkYXknIH19IC8vIFwieWVzdGVyZGF5XCJcbiAqIHt7IDIgfCBhY2xJbnRsUmVsYXRpdmVUaW1lOidob3VyJzp7IG51bWVyaWM6ICdhbHdheXMnIH0gfX0gLy8gXCJpbiAyIGhvdXJzXCJcbiAqIHt7IC0zMCB8IGFjbEludGxSZWxhdGl2ZVRpbWU6J21pbnV0ZSc6eyBudW1lcmljOiAnYWx3YXlzJyB9IH19IC8vIFwiMzAgbWludXRlcyBhZ29cIlxuICovXG5AUGlwZSh7XG4gIG5hbWU6ICdhY2xJbnRsUmVsYXRpdmVUaW1lJyxcbiAgcHVyZTogZmFsc2UsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG59KVxuZXhwb3J0IGNsYXNzIEludGxSZWxhdGl2ZVRpbWVQaXBlXG4gIGV4dGVuZHMgQmFzZUludGxQaXBlXG4gIGltcGxlbWVudHMgUGlwZVRyYW5zZm9ybSwgT25EZXN0cm95XG57XG4gIHByaXZhdGUgcmVhZG9ubHkgcmVsYXRpdmVUaW1lTWFuYWdlciA9IGluamVjdChSZWxhdGl2ZVRpbWVNYW5hZ2VyU2VydmljZSk7XG5cbiAgcHJpdmF0ZSBjdXJyZW50SW50ZXJ2YWw/OiBudW1iZXI7XG4gIHByaXZhdGUgcmVmcmVzaFN1YnNjcmlwdGlvbj86IFN1YnNjcmlwdGlvbjtcbiAgcHJpdmF0ZSBjdXJyZW50VmFsdWU/OiBEYXRlO1xuXG4gIG92ZXJyaWRlIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHN1cGVyLm5nT25EZXN0cm95KCk7XG4gICAgdGhpcy5jbGVhbnVwUmVmcmVzaCgpO1xuICB9XG5cbiAgdHJhbnNmb3JtKFxuICAgIHZhbHVlOiBEYXRlIHwgbnVtYmVyLFxuICAgIHVuaXRPck9wdGlvbnM/OlxuICAgICAgfCBJbnRsLlJlbGF0aXZlVGltZUZvcm1hdFVuaXRcbiAgICAgIHwgSW50bC5SZWxhdGl2ZVRpbWVGb3JtYXRPcHRpb25zLFxuICAgIG9wdGlvbnM/OiBJbnRsLlJlbGF0aXZlVGltZUZvcm1hdE9wdGlvbnMsXG4gICk6IHN0cmluZyB7XG4gICAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICAgIHJldHVybiBGSUVMRF9OT1RfQVZBSUxBQkxFX1BMQUNFSE9MREVSO1xuICAgIH1cblxuICAgIC8vIOaDheWGtTE6IOS8oOWFpSBEYXRlIOWvueixoe+8jOiHquWKqOiuoeeul+ebuOWvueaXtumXtO+8iOaUr+aMgeiHquWKqOWIt+aWsO+8iVxuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgIHRoaXMuY3VycmVudFZhbHVlID0gdmFsdWU7XG4gICAgICB0aGlzLnNldHVwQXV0b1JlZnJlc2godmFsdWUpO1xuXG4gICAgICBjb25zdCByZWxhdGl2ZU9wdGlvbnMgPSB1bml0T3JPcHRpb25zIGFzXG4gICAgICAgIHwgSW50bC5SZWxhdGl2ZVRpbWVGb3JtYXRPcHRpb25zXG4gICAgICAgIHwgdW5kZWZpbmVkO1xuXG4gICAgICByZXR1cm4gdGhpcy50cmFuc2xhdGUuZm9ybWF0UmVsYXRpdmVUaW1lKHZhbHVlLCByZWxhdGl2ZU9wdGlvbnMpO1xuICAgIH1cblxuICAgIC8vIOaDheWGtTI6IOS8oOWFpeaVsOWtl++8jOmcgOimgeaJi+WKqOaMh+WumuWNleS9je+8iOS4jemcgOimgeiHquWKqOWIt+aWsO+8iVxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICB0aGlzLmNsZWFudXBSZWZyZXNoKCk7IC8vIOa4hemZpOWPr+iDveWtmOWcqOeahOWIt+aWsOiuoumYhVxuXG4gICAgICBpZiAoaXNOYU4odmFsdWUpKSB7XG4gICAgICAgIHJldHVybiBGSUVMRF9OT1RfQVZBSUxBQkxFX1BMQUNFSE9MREVSO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB1bml0ID0gdW5pdE9yT3B0aW9ucyBhcyBJbnRsLlJlbGF0aXZlVGltZUZvcm1hdFVuaXQ7XG4gICAgICBpZiAoIXVuaXQpIHtcbiAgICAgICAgcmV0dXJuIEZJRUxEX05PVF9BVkFJTEFCTEVfUExBQ0VIT0xERVI7XG4gICAgICB9XG5cbiAgICAgIC8vIOWvueS6juaJi+WKqOaMh+WumuWNleS9jeeahOaDheWGte+8jOebtOaOpeiwg+eUqOe/u+ivkeacjeWKoVxuICAgICAgcmV0dXJuIHRoaXMudHJhbnNsYXRlLmZvcm1hdFJlbGF0aXZlVGltZSh2YWx1ZSwgdW5pdCwgb3B0aW9ucyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEZJRUxEX05PVF9BVkFJTEFCTEVfUExBQ0VIT0xERVI7XG4gIH1cblxuICAvKipcbiAgICog6K6+572u6Ieq5Yqo5Yi35paw5py65Yi2XG4gICAqIOS9v+eUqOWFseS6q+eahOiuoeaXtuWZqOeuoeeQhuWZqO+8jOaPkOmrmOWkmuWunuS+i+WcuuaZr+S4i+eahOaAp+iDvVxuICAgKiDml7bpl7Tpl7TpmpTlpKfkuo7kuIDlpKnml7bkuI3orr7nva7oh6rliqjliLfmlrBcbiAgICovXG4gIHByaXZhdGUgc2V0dXBBdXRvUmVmcmVzaChkYXRlOiBEYXRlKTogdm9pZCB7XG4gICAgY29uc3QgZGlzdGFuY2UgPSBNYXRoLmFicyhEYXRlLm5vdygpIC0gZGF0ZS5nZXRUaW1lKCkpO1xuXG4gICAgLy8g5pe26Ze06Ze06ZqU5aSn5LqO5LiA5aSp5pe277yM5LiN6ZyA6KaB6Ieq5Yqo5Yi35pawXG4gICAgaWYgKGRpc3RhbmNlID49IE1JTExJU0VDT05EU19EQVkpIHtcbiAgICAgIHRoaXMuY2xlYW51cFJlZnJlc2goKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgaW50ZXJ2YWw6IG51bWJlcjtcbiAgICBpZiAoZGlzdGFuY2UgPCBNSUxMSVNFQ09ORFNfTUlOVVRFKSB7XG4gICAgICBpbnRlcnZhbCA9IE1JTExJU0VDT05EU19TRUNPTkQ7XG4gICAgfSBlbHNlIGlmIChkaXN0YW5jZSA8IE1JTExJU0VDT05EU19IT1VSKSB7XG4gICAgICBpbnRlcnZhbCA9IE1JTExJU0VDT05EU19NSU5VVEU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGludGVydmFsID0gTUlMTElTRUNPTkRTX0hPVVI7XG4gICAgfVxuXG4gICAgLy8g5aaC5p6c5Yi35paw6Ze06ZqU5rKh5pyJ5Y+Y5YyW77yM5peg6ZyA6YeN5paw6K6i6ZiFXG4gICAgaWYgKHRoaXMuY3VycmVudEludGVydmFsID09PSBpbnRlcnZhbCAmJiB0aGlzLnJlZnJlc2hTdWJzY3JpcHRpb24pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmNsZWFudXBSZWZyZXNoKCk7XG4gICAgdGhpcy5jdXJyZW50SW50ZXJ2YWwgPSBpbnRlcnZhbDtcblxuICAgIC8vIOiuoumYheWFseS6q+eahOWIt+aWsOS6i+S7tlxuICAgIHRoaXMucmVmcmVzaFN1YnNjcmlwdGlvbiA9IHRoaXMucmVsYXRpdmVUaW1lTWFuYWdlclxuICAgICAgLmdldFJlZnJlc2hTdWJqZWN0KGludGVydmFsKVxuICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQkKSlcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgICAgICAgLy8g6YeN5paw6K6h566X5Yi35paw6Ze06ZqU77yM6YCC5bqU5pe26Ze05Y+Y5YyWXG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRWYWx1ZSkge1xuICAgICAgICAgIHRoaXMuc2V0dXBBdXRvUmVmcmVzaCh0aGlzLmN1cnJlbnRWYWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIOa4heeQhuWIt+aWsOebuOWFs+i1hOa6kFxuICAgKi9cbiAgcHJpdmF0ZSBjbGVhbnVwUmVmcmVzaCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5yZWZyZXNoU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLnJlZnJlc2hTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgIHRoaXMucmVmcmVzaFN1YnNjcmlwdGlvbiA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5jdXJyZW50SW50ZXJ2YWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5yZWxhdGl2ZVRpbWVNYW5hZ2VyLnJlbGVhc2VSZWZyZXNoU3ViamVjdCh0aGlzLmN1cnJlbnRJbnRlcnZhbCk7XG4gICAgICB0aGlzLmN1cnJlbnRJbnRlcnZhbCA9IHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cbn1cbiJdfQ==