ngx-network
Version:
get and tracking the network speed with simplest way ever
109 lines • 18.2 kB
JavaScript
import { HttpEventType, HttpRequest, } from '@angular/common/http';
import { Inject, Injectable } from '@angular/core';
import { BehaviorSubject, Observable, Subscription, } from 'rxjs';
import { concatMap, filter, finalize, map, takeLast, tap, throttleTime, } from 'rxjs/operators';
import { Units } from './api/units';
import { NGX_NETWORK_CONFIG } from './ngx-network.module';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common/http";
export class NgxNetworkService {
constructor(config, http) {
this.config = config;
this.http = http;
this.speedChanged$ = new BehaviorSubject({
speed: 0,
unit: config.speedUnit,
});
this.onSpeedChanged$ = this.speedChanged$.asObservable().pipe(throttleTime(this.config.delay), filter((payload) => payload.speed !== 0));
this.startSendingPayloadSubscription = new Subscription();
this.lastPayloadSize = 0;
this.lastTime = 0;
}
getSpeed() {
if (this.startSendingPayloadSubscription) {
this.startSendingPayloadSubscription.unsubscribe();
}
this.startSendingPayloadSubscription = this.startSendingPayload(this.config.url, false).subscribe();
return this.onSpeedChanged$;
}
onSpeedChanged() {
if (this.startSendingPayloadSubscription) {
this.startSendingPayloadSubscription.unsubscribe();
}
this.startSendingPayloadSubscription = this.startSendingPayload(this.config.url, true).subscribe();
return this.onSpeedChanged$;
}
startSendingPayload(url, repeatRequest) {
this.lastTime = 0;
this.lastPayloadSize = 0;
const randomQuery = `q=${Math.round(Math.random() * 99959).toString()}`;
if (!repeatRequest) {
return this.sendRequest(url, randomQuery).pipe(takeLast(1), tap((payload) => {
this.speedChanged$.next(payload);
}), map((e) => null));
}
return this.sendRequest(url, randomQuery).pipe(tap((payload) => {
this.speedChanged$.next(payload);
}), finalize(() => {
if (!repeatRequest)
return;
this.startSendingPayloadSubscription.unsubscribe();
this.startSendingPayloadSubscription = this.startSendingPayload(url, repeatRequest).subscribe();
}), map((e) => null));
}
sendRequest(url, params) {
const request = new HttpRequest('GET', url, {
params,
responseType: 'arraybuffer',
reportProgress: true,
});
return this.http
.request(request)
.pipe(concatMap((httpEvent) => this.handleHttpEvents(httpEvent)));
}
handleHttpEvents(e) {
return new Observable((subscriber) => {
if (e.type === HttpEventType.DownloadProgress) {
let currentTime = Date.now();
const elapseTimeForEveryPayload = currentTime - this.lastTime;
const elapseTimeSecs = elapseTimeForEveryPayload / 1000;
let speed = this.speedChanged$.getValue().speed.toString();
const currentPayloadSize = e.loaded;
const downloadPayloadSize = Math.abs(currentPayloadSize - this.lastPayloadSize);
switch (this.config.speedUnit) {
case Units['kb/s']:
speed = Number(downloadPayloadSize / 1024 / elapseTimeSecs).toFixed(3);
break;
case Units['mb/s']:
speed = Number(downloadPayloadSize / Math.pow(1024, 2) / elapseTimeSecs).toFixed(3);
break;
case Units['gb/s']:
speed = Number(downloadPayloadSize / Math.pow(1024, 3) / elapseTimeSecs).toFixed(3);
break;
case Units['tb/s']:
speed = Number(downloadPayloadSize / Math.pow(1024, 4) / elapseTimeSecs).toFixed(3);
break;
}
this.lastPayloadSize = e.loaded;
this.lastTime = Date.now();
subscriber.next({
speed: Number(Number(speed) === 0 ? this.speedChanged$.getValue().speed : speed),
unit: this.config.speedUnit,
});
}
subscriber.complete();
});
}
}
NgxNetworkService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NgxNetworkService, deps: [{ token: NGX_NETWORK_CONFIG }, { token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
NgxNetworkService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NgxNetworkService, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NgxNetworkService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Inject,
args: [NGX_NETWORK_CONFIG]
}] }, { type: i1.HttpClient }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LW5ldHdvcmsuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1uZXR3b3JrL3NyYy9saWIvbmd4LW5ldHdvcmsuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBR0wsYUFBYSxFQUNiLFdBQVcsR0FDWixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFDTCxlQUFlLEVBQ2YsVUFBVSxFQUVWLFlBQVksR0FDYixNQUFNLE1BQU0sQ0FBQztBQUNkLE9BQU8sRUFDTCxTQUFTLEVBQ1QsTUFBTSxFQUNOLFFBQVEsRUFDUixHQUFHLEVBRUgsUUFBUSxFQUNSLEdBQUcsRUFDSCxZQUFZLEdBQ2IsTUFBTSxnQkFBZ0IsQ0FBQztBQUd4QixPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDOzs7QUFJMUQsTUFBTSxPQUFPLGlCQUFpQjtJQU01QixZQUNzQyxNQUFjLEVBQzFDLElBQWdCO1FBRFksV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUMxQyxTQUFJLEdBQUosSUFBSSxDQUFZO1FBRXhCLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxlQUFlLENBQUM7WUFDdkMsS0FBSyxFQUFFLENBQUM7WUFDUixJQUFJLEVBQUUsTUFBTSxDQUFDLFNBQVM7U0FDdkIsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFlBQVksRUFBRSxDQUFDLElBQUksQ0FDM0QsWUFBWSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQy9CLE1BQU0sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssS0FBSyxDQUFDLENBQUMsQ0FDekMsQ0FBQztRQUNGLElBQUksQ0FBQywrQkFBK0IsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQzFELElBQUksQ0FBQyxlQUFlLEdBQUcsQ0FBQyxDQUFDO1FBQ3pCLElBQUksQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDO0lBQ3BCLENBQUM7SUFDRCxRQUFRO1FBQ04sSUFBSSxJQUFJLENBQUMsK0JBQStCLEVBQUU7WUFDeEMsSUFBSSxDQUFDLCtCQUErQixDQUFDLFdBQVcsRUFBRSxDQUFDO1NBQ3BEO1FBQ0QsSUFBSSxDQUFDLCtCQUErQixHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FDN0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQ2YsS0FBSyxDQUNOLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDZCxPQUFPLElBQUksQ0FBQyxlQUFlLENBQUM7SUFDOUIsQ0FBQztJQUNELGNBQWM7UUFDWixJQUFJLElBQUksQ0FBQywrQkFBK0IsRUFBRTtZQUN4QyxJQUFJLENBQUMsK0JBQStCLENBQUMsV0FBVyxFQUFFLENBQUM7U0FDcEQ7UUFDRCxJQUFJLENBQUMsK0JBQStCLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUM3RCxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFDZixJQUFJLENBQ0wsQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNkLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQztJQUM5QixDQUFDO0lBQ08sbUJBQW1CLENBQUMsR0FBVyxFQUFFLGFBQXNCO1FBQzdELElBQUksQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDO1FBQ2xCLElBQUksQ0FBQyxlQUFlLEdBQUcsQ0FBQyxDQUFDO1FBQ3pCLE1BQU0sV0FBVyxHQUFHLEtBQUssSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztRQUN4RSxJQUFHLENBQUMsYUFBYSxFQUFDO1lBQ2YsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsRUFBRSxXQUFXLENBQUMsQ0FBQyxJQUFJLENBQzdDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFDWCxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtnQkFDZCxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNuQyxDQUFDLENBQUMsRUFDRixHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUNqQixDQUFDO1NBQ0g7UUFDRCxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxFQUFFLFdBQVcsQ0FBQyxDQUFDLElBQUksQ0FDNUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUU7WUFDZCxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNuQyxDQUFDLENBQUMsRUFDRixRQUFRLENBQUMsR0FBRyxFQUFFO1lBQ1osSUFBSSxDQUFDLGFBQWE7Z0JBQUUsT0FBTztZQUMzQixJQUFJLENBQUMsK0JBQStCLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDbkQsSUFBSSxDQUFDLCtCQUErQixHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FDN0QsR0FBRyxFQUNILGFBQWEsQ0FDZCxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2hCLENBQUMsQ0FBQyxFQUNGLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLENBQ2pCLENBQUM7SUFDSixDQUFDO0lBRU8sV0FBVyxDQUFDLEdBQVcsRUFBRSxNQUFjO1FBQzdDLE1BQU0sT0FBTyxHQUFHLElBQUksV0FBVyxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUU7WUFDMUMsTUFBTTtZQUNOLFlBQVksRUFBRSxhQUFhO1lBQzNCLGNBQWMsRUFBRSxJQUFJO1NBQ3JCLENBQUMsQ0FBQztRQUVILE9BQU8sSUFBSSxDQUFDLElBQUk7YUFDYixPQUFPLENBQUMsT0FBTyxDQUFDO2FBQ2hCLElBQUksQ0FDSCxTQUFTLENBQUMsQ0FBQyxTQUF5QixFQUFFLEVBQUUsQ0FDdEMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxDQUNqQyxDQUNGLENBQUM7SUFDTixDQUFDO0lBQ08sZ0JBQWdCLENBQUMsQ0FBeUI7UUFDaEQsT0FBTyxJQUFJLFVBQVUsQ0FDbkIsQ0FBQyxVQUF3QyxFQUFFLEVBQUU7WUFDM0MsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLGFBQWEsQ0FBQyxnQkFBZ0IsRUFBRTtnQkFDN0MsSUFBSSxXQUFXLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO2dCQUM3QixNQUFNLHlCQUF5QixHQUFHLFdBQVcsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO2dCQUM5RCxNQUFNLGNBQWMsR0FBRyx5QkFBeUIsR0FBRyxJQUFJLENBQUM7Z0JBQ3hELElBQUksS0FBSyxHQUFXLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxFQUFFLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUNuRSxNQUFNLGtCQUFrQixHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUM7Z0JBQ3BDLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FDbEMsa0JBQWtCLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FDMUMsQ0FBQztnQkFDRixRQUFRLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFO29CQUM3QixLQUFLLEtBQUssQ0FBQyxNQUFNLENBQUM7d0JBQ2hCLEtBQUssR0FBRyxNQUFNLENBQ1osbUJBQW1CLEdBQUcsSUFBSSxHQUFHLGNBQWMsQ0FDNUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7d0JBQ2IsTUFBTTtvQkFDUixLQUFLLEtBQUssQ0FBQyxNQUFNLENBQUM7d0JBQ2hCLEtBQUssR0FBRyxNQUFNLENBQ1osbUJBQW1CLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLEdBQUcsY0FBYyxDQUN6RCxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQzt3QkFDYixNQUFNO29CQUNSLEtBQUssS0FBSyxDQUFDLE1BQU0sQ0FBQzt3QkFDaEIsS0FBSyxHQUFHLE1BQU0sQ0FDWixtQkFBbUIsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsR0FBRyxjQUFjLENBQ3pELENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO3dCQUNiLE1BQU07b0JBQ1IsS0FBSyxLQUFLLENBQUMsTUFBTSxDQUFDO3dCQUNoQixLQUFLLEdBQUcsTUFBTSxDQUNaLG1CQUFtQixHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxHQUFHLGNBQWMsQ0FDekQsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7d0JBQ2IsTUFBTTtpQkFDVDtnQkFDRCxJQUFJLENBQUMsZUFBZSxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUM7Z0JBQ2hDLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO2dCQUMzQixVQUFVLENBQUMsSUFBSSxDQUFDO29CQUNkLEtBQUssRUFBRSxNQUFNLENBQ1gsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FDbEU7b0JBQ0QsSUFBSSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUztpQkFDNUIsQ0FBQyxDQUFDO2FBQ0o7WUFDRCxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDeEIsQ0FBQyxDQUNGLENBQUM7SUFDSixDQUFDOzs4R0FwSVUsaUJBQWlCLGtCQU9sQixrQkFBa0I7a0hBUGpCLGlCQUFpQixjQUZqQixNQUFNOzJGQUVOLGlCQUFpQjtrQkFIN0IsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUMsTUFBTTtpQkFDbEI7OzBCQVFJLE1BQU07MkJBQUMsa0JBQWtCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgSHR0cENsaWVudCxcbiAgSHR0cEV2ZW50LFxuICBIdHRwRXZlbnRUeXBlLFxuICBIdHRwUmVxdWVzdCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBCZWhhdmlvclN1YmplY3QsXG4gIE9ic2VydmFibGUsXG4gIFN1YnNjcmliZXIsXG4gIFN1YnNjcmlwdGlvbixcbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQge1xuICBjb25jYXRNYXAsXG4gIGZpbHRlcixcbiAgZmluYWxpemUsXG4gIG1hcCxcbiAgcmVwZWF0LFxuICB0YWtlTGFzdCxcbiAgdGFwLFxuICB0aHJvdHRsZVRpbWUsXG59IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IENvbmZpZyB9IGZyb20gJy4vYXBpL2NvbmZpZyc7XG5pbXBvcnQgeyBOZXR3b3JrU3BlZWRJbmZvIH0gZnJvbSAnLi9hcGkvbmV0d29yay1zcGVlZC1pbmZvJztcbmltcG9ydCB7IFVuaXRzIH0gZnJvbSAnLi9hcGkvdW5pdHMnO1xuaW1wb3J0IHsgTkdYX05FVFdPUktfQ09ORklHIH0gZnJvbSAnLi9uZ3gtbmV0d29yay5tb2R1bGUnO1xuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOidyb290J1xufSlcbmV4cG9ydCBjbGFzcyBOZ3hOZXR3b3JrU2VydmljZSB7XG4gIHByaXZhdGUgc3BlZWRDaGFuZ2VkJDogQmVoYXZpb3JTdWJqZWN0PE5ldHdvcmtTcGVlZEluZm8+O1xuICBwcml2YXRlIG9uU3BlZWRDaGFuZ2VkJDogT2JzZXJ2YWJsZTxOZXR3b3JrU3BlZWRJbmZvPjtcbiAgcHJpdmF0ZSBzdGFydFNlbmRpbmdQYXlsb2FkU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG4gIHByaXZhdGUgbGFzdFRpbWU6IG51bWJlcjtcbiAgcHJpdmF0ZSBsYXN0UGF5bG9hZFNpemU6IG51bWJlcjtcbiAgY29uc3RydWN0b3IoXG4gICAgQEluamVjdChOR1hfTkVUV09SS19DT05GSUcpIHByaXZhdGUgY29uZmlnOiBDb25maWcsXG4gICAgcHJpdmF0ZSBodHRwOiBIdHRwQ2xpZW50XG4gICkge1xuICAgIHRoaXMuc3BlZWRDaGFuZ2VkJCA9IG5ldyBCZWhhdmlvclN1YmplY3Qoe1xuICAgICAgc3BlZWQ6IDAsXG4gICAgICB1bml0OiBjb25maWcuc3BlZWRVbml0LFxuICAgIH0pO1xuICAgIHRoaXMub25TcGVlZENoYW5nZWQkID0gdGhpcy5zcGVlZENoYW5nZWQkLmFzT2JzZXJ2YWJsZSgpLnBpcGUoXG4gICAgICB0aHJvdHRsZVRpbWUodGhpcy5jb25maWcuZGVsYXkpLFxuICAgICAgZmlsdGVyKChwYXlsb2FkKSA9PiBwYXlsb2FkLnNwZWVkICE9PSAwKVxuICAgICk7XG4gICAgdGhpcy5zdGFydFNlbmRpbmdQYXlsb2FkU3Vic2NyaXB0aW9uID0gbmV3IFN1YnNjcmlwdGlvbigpO1xuICAgIHRoaXMubGFzdFBheWxvYWRTaXplID0gMDtcbiAgICB0aGlzLmxhc3RUaW1lID0gMDtcbiAgfVxuICBnZXRTcGVlZCgpIHtcbiAgICBpZiAodGhpcy5zdGFydFNlbmRpbmdQYXlsb2FkU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLnN0YXJ0U2VuZGluZ1BheWxvYWRTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gICAgdGhpcy5zdGFydFNlbmRpbmdQYXlsb2FkU3Vic2NyaXB0aW9uID0gdGhpcy5zdGFydFNlbmRpbmdQYXlsb2FkKFxuICAgICAgdGhpcy5jb25maWcudXJsLFxuICAgICAgZmFsc2VcbiAgICApLnN1YnNjcmliZSgpO1xuICAgIHJldHVybiB0aGlzLm9uU3BlZWRDaGFuZ2VkJDtcbiAgfVxuICBvblNwZWVkQ2hhbmdlZCgpOiBPYnNlcnZhYmxlPE5ldHdvcmtTcGVlZEluZm8+IHtcbiAgICBpZiAodGhpcy5zdGFydFNlbmRpbmdQYXlsb2FkU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLnN0YXJ0U2VuZGluZ1BheWxvYWRTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gICAgdGhpcy5zdGFydFNlbmRpbmdQYXlsb2FkU3Vic2NyaXB0aW9uID0gdGhpcy5zdGFydFNlbmRpbmdQYXlsb2FkKFxuICAgICAgdGhpcy5jb25maWcudXJsLFxuICAgICAgdHJ1ZVxuICAgICkuc3Vic2NyaWJlKCk7XG4gICAgcmV0dXJuIHRoaXMub25TcGVlZENoYW5nZWQkO1xuICB9XG4gIHByaXZhdGUgc3RhcnRTZW5kaW5nUGF5bG9hZCh1cmw6IHN0cmluZywgcmVwZWF0UmVxdWVzdDogYm9vbGVhbik6IE9ic2VydmFibGU8bnVsbD4ge1xuICAgIHRoaXMubGFzdFRpbWUgPSAwO1xuICAgIHRoaXMubGFzdFBheWxvYWRTaXplID0gMDtcbiAgICBjb25zdCByYW5kb21RdWVyeSA9IGBxPSR7TWF0aC5yb3VuZChNYXRoLnJhbmRvbSgpICogOTk5NTkpLnRvU3RyaW5nKCl9YDtcbiAgICBpZighcmVwZWF0UmVxdWVzdCl7XG4gICAgICAgcmV0dXJuIHRoaXMuc2VuZFJlcXVlc3QodXJsLCByYW5kb21RdWVyeSkucGlwZShcbiAgICAgICAgdGFrZUxhc3QoMSksXG4gICAgICAgIHRhcCgocGF5bG9hZCkgPT4ge1xuICAgICAgICAgIHRoaXMuc3BlZWRDaGFuZ2VkJC5uZXh0KHBheWxvYWQpO1xuICAgICAgICB9KSxcbiAgICAgICAgbWFwKChlKSA9PiBudWxsKVxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2VuZFJlcXVlc3QodXJsLCByYW5kb21RdWVyeSkucGlwZShcbiAgICAgIHRhcCgocGF5bG9hZCkgPT4ge1xuICAgICAgICB0aGlzLnNwZWVkQ2hhbmdlZCQubmV4dChwYXlsb2FkKTtcbiAgICAgIH0pLFxuICAgICAgZmluYWxpemUoKCkgPT4ge1xuICAgICAgICBpZiAoIXJlcGVhdFJlcXVlc3QpIHJldHVybjtcbiAgICAgICAgdGhpcy5zdGFydFNlbmRpbmdQYXlsb2FkU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgIHRoaXMuc3RhcnRTZW5kaW5nUGF5bG9hZFN1YnNjcmlwdGlvbiA9IHRoaXMuc3RhcnRTZW5kaW5nUGF5bG9hZChcbiAgICAgICAgICB1cmwsXG4gICAgICAgICAgcmVwZWF0UmVxdWVzdFxuICAgICAgICApLnN1YnNjcmliZSgpO1xuICAgICAgfSksXG4gICAgICBtYXAoKGUpID0+IG51bGwpXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc2VuZFJlcXVlc3QodXJsOiBzdHJpbmcsIHBhcmFtczogc3RyaW5nKSB7XG4gICAgY29uc3QgcmVxdWVzdCA9IG5ldyBIdHRwUmVxdWVzdCgnR0VUJywgdXJsLCB7XG4gICAgICBwYXJhbXMsXG4gICAgICByZXNwb25zZVR5cGU6ICdhcnJheWJ1ZmZlcicsXG4gICAgICByZXBvcnRQcm9ncmVzczogdHJ1ZSxcbiAgICB9KTtcblxuICAgIHJldHVybiB0aGlzLmh0dHBcbiAgICAgIC5yZXF1ZXN0KHJlcXVlc3QpXG4gICAgICAucGlwZShcbiAgICAgICAgY29uY2F0TWFwKChodHRwRXZlbnQ6IEh0dHBFdmVudDxhbnk+KSA9PlxuICAgICAgICAgIHRoaXMuaGFuZGxlSHR0cEV2ZW50cyhodHRwRXZlbnQpXG4gICAgICAgIClcbiAgICAgICk7XG4gIH1cbiAgcHJpdmF0ZSBoYW5kbGVIdHRwRXZlbnRzKGU6IEh0dHBFdmVudDxBcnJheUJ1ZmZlcj4pIHtcbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGU8TmV0d29ya1NwZWVkSW5mbz4oXG4gICAgICAoc3Vic2NyaWJlcjogU3Vic2NyaWJlcjxOZXR3b3JrU3BlZWRJbmZvPikgPT4ge1xuICAgICAgICBpZiAoZS50eXBlID09PSBIdHRwRXZlbnRUeXBlLkRvd25sb2FkUHJvZ3Jlc3MpIHtcbiAgICAgICAgICBsZXQgY3VycmVudFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICAgIGNvbnN0IGVsYXBzZVRpbWVGb3JFdmVyeVBheWxvYWQgPSBjdXJyZW50VGltZSAtIHRoaXMubGFzdFRpbWU7XG4gICAgICAgICAgY29uc3QgZWxhcHNlVGltZVNlY3MgPSBlbGFwc2VUaW1lRm9yRXZlcnlQYXlsb2FkIC8gMTAwMDtcbiAgICAgICAgICBsZXQgc3BlZWQ6IHN0cmluZyA9IHRoaXMuc3BlZWRDaGFuZ2VkJC5nZXRWYWx1ZSgpLnNwZWVkLnRvU3RyaW5nKCk7XG4gICAgICAgICAgY29uc3QgY3VycmVudFBheWxvYWRTaXplID0gZS5sb2FkZWQ7XG4gICAgICAgICAgY29uc3QgZG93bmxvYWRQYXlsb2FkU2l6ZSA9IE1hdGguYWJzKFxuICAgICAgICAgICAgY3VycmVudFBheWxvYWRTaXplIC0gdGhpcy5sYXN0UGF5bG9hZFNpemVcbiAgICAgICAgICApO1xuICAgICAgICAgIHN3aXRjaCAodGhpcy5jb25maWcuc3BlZWRVbml0KSB7XG4gICAgICAgICAgICBjYXNlIFVuaXRzWydrYi9zJ106XG4gICAgICAgICAgICAgIHNwZWVkID0gTnVtYmVyKFxuICAgICAgICAgICAgICAgIGRvd25sb2FkUGF5bG9hZFNpemUgLyAxMDI0IC8gZWxhcHNlVGltZVNlY3NcbiAgICAgICAgICAgICAgKS50b0ZpeGVkKDMpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVW5pdHNbJ21iL3MnXTpcbiAgICAgICAgICAgICAgc3BlZWQgPSBOdW1iZXIoXG4gICAgICAgICAgICAgICAgZG93bmxvYWRQYXlsb2FkU2l6ZSAvIE1hdGgucG93KDEwMjQsIDIpIC8gZWxhcHNlVGltZVNlY3NcbiAgICAgICAgICAgICAgKS50b0ZpeGVkKDMpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVW5pdHNbJ2diL3MnXTpcbiAgICAgICAgICAgICAgc3BlZWQgPSBOdW1iZXIoXG4gICAgICAgICAgICAgICAgZG93bmxvYWRQYXlsb2FkU2l6ZSAvIE1hdGgucG93KDEwMjQsIDMpIC8gZWxhcHNlVGltZVNlY3NcbiAgICAgICAgICAgICAgKS50b0ZpeGVkKDMpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVW5pdHNbJ3RiL3MnXTpcbiAgICAgICAgICAgICAgc3BlZWQgPSBOdW1iZXIoXG4gICAgICAgICAgICAgICAgZG93bmxvYWRQYXlsb2FkU2l6ZSAvIE1hdGgucG93KDEwMjQsIDQpIC8gZWxhcHNlVGltZVNlY3NcbiAgICAgICAgICAgICAgKS50b0ZpeGVkKDMpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5sYXN0UGF5bG9hZFNpemUgPSBlLmxvYWRlZDtcbiAgICAgICAgICB0aGlzLmxhc3RUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICBzdWJzY3JpYmVyLm5leHQoe1xuICAgICAgICAgICAgc3BlZWQ6IE51bWJlcihcbiAgICAgICAgICAgICAgTnVtYmVyKHNwZWVkKSA9PT0gMCA/IHRoaXMuc3BlZWRDaGFuZ2VkJC5nZXRWYWx1ZSgpLnNwZWVkIDogc3BlZWRcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICB1bml0OiB0aGlzLmNvbmZpZy5zcGVlZFVuaXQsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgc3Vic2NyaWJlci5jb21wbGV0ZSgpO1xuICAgICAgfVxuICAgICk7XG4gIH1cbn1cbiJdfQ==