ems-web-app-utils
Version:
Utility methods that are intended for use in Angular.io [web applications developed by Educational Media Solutions](https://github.com/spencech/ems-web-app-template)
281 lines • 37.1 kB
JavaScript
import { NgModule } from '@angular/core';
import * as _ from 'underscore';
import * as i0 from "@angular/core";
export function alphabetize(...parameters) {
if (typeof parameters[0] === 'string') {
// if this method is supplied as a callback to Array.sort
const a = parameters[0];
const b = parameters[1];
if (a > b)
return 1;
if (a < b)
return -1;
return 0;
}
else {
// if we're sorting a list with a supplied key to alphabetize
const list = parameters[0];
const property = parameters[1];
list.sort((a, b) => {
if (a[property] > b[property])
return 1;
if (a[property] < b[property])
return -1;
return 0;
});
return list;
}
}
export function clone(obj) {
if (obj === null || obj === undefined)
return obj;
return JSON.parse(JSON.stringify(obj));
}
export function convertToEST(date) {
const gmtDate = new Date(date + " GMT");
const options = {
timeZone: 'America/New_York',
year: "numeric",
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
hour12: true
};
const formatter = new Intl.DateTimeFormat('en-US', options);
return formatter.format(gmtDate);
}
export function dateStrings(date) {
date = date || new Date();
return {
year: date.getFullYear(),
month: (date.getMonth() + 1).toString().padStart(2, '0'),
date: date.getDate().toString().padStart(2, '0'),
time: `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`,
seconds: date.getSeconds().toString().padStart(2, '0'),
};
}
export function delay(method, ms = 0) {
return window.setTimeout(method, ms);
}
export function download(content, name, extension = 'csv') {
const blob = new Blob([content]);
name = kebab(name);
if (window.navigator.msSaveOrOpenBlob)
window.navigator.msSaveBlob(blob, `${name}.${extension}`);
else {
const a = window.document.createElement('a');
a.href = window.URL.createObjectURL(blob);
a.download = `${name}.${extension}`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
}
export function empty(e) {
return falsy(e);
}
export function enumKeys(obj) {
return Object.keys(obj).filter(k => Number.isNaN(+k));
}
export function enumValues(obj) {
const output = [];
for (const value of enumKeys(obj)) {
output.push(obj[value]);
}
return output;
}
export function falsy(e) {
if (typeof e === 'string' && trim(e).match(/^false$/i))
return true;
if (typeof e === 'string')
return _.isEmpty(e.replace(/\s+/gim, ''));
if (typeof e === 'boolean')
return e === false;
if (!isNaN(parseInt(e, 10)))
return e === 0;
return _.isEmpty(e);
}
export function focus(selector) {
const element = document.querySelector(selector);
if (!element || !element.focus)
return 0;
return delay(() => element.focus());
}
export function getLargestRemainder(values, desiredSum) {
let sum = 0;
let valueParts = values.map((value, index) => {
const integerValue = value || 0;
sum += integerValue;
return {
integer: integerValue,
decimal: value % 1,
originalIndex: index,
};
});
if (sum !== desiredSum && sum) {
valueParts = valueParts.sort((a, b) => b.decimal - a.decimal);
const diff = desiredSum - sum;
let i = 0;
while (i < diff) {
valueParts[i].integer++;
i++;
}
}
return valueParts.sort((a, b) => a.originalIndex - b.originalIndex).map((p) => p.integer);
}
export function getparams(requestedProperty) {
const vars = {};
const parts = window.location.href.replace(/[?&#]+([^=&]+)=([^&]*)/gi, ((m, key, value) => {
vars[key] = value;
}));
for (const prop in vars) {
if (vars[prop].toLowerCase() === 'true')
vars[prop] = true;
else if (vars[prop].toLowerCase() === 'false')
vars[prop] = false;
else if (!isNaN(parseFloat(vars[prop])) && !vars[prop].match(/[^0-9]+/gim))
vars[prop] = parseFloat(vars[prop]);
}
if (requestedProperty)
return vars[requestedProperty];
return vars;
}
export function isset(e) {
return truthy(e);
}
export function kebab(e) {
if (_.isEmpty(e))
return e;
return e.toLowerCase().replace(/\s+/gim, '-').replace(/_/g, '-').replace(/-+/g, '-');
}
export function paginate(method, offset, limit, key, output = [], callback, prevResolve) {
return new Promise(async (resolve, reject) => {
let response;
try {
response = await method(offset, limit);
}
catch (e) {
reject(e);
}
output = output.concat(response[key]);
if (callback)
callback(output, response[key]);
if (response.nextPage) {
await paginate(method, response.nextPage, limit, key, output, callback, prevResolve ?? resolve);
}
else {
(prevResolve ?? resolve)(output);
}
});
}
export function prepareSearchString(value) {
if (!value)
return "";
return value.toLowerCase().replace(/\s+/gim, "");
}
export function replaceItem(array, item, key = 'id', position = 'current') {
const lookup = {};
lookup[key] = item[key];
const oldItem = _.findWhere(array, lookup);
if (!oldItem) {
array.unshift(item);
return item;
}
const index = array.indexOf(oldItem);
if (position === 'first') {
array.splice(index, 1);
array.unshift(item);
}
else {
array.splice(index, 1, item);
}
return item;
}
export function sleep(duration = 0) {
return new Promise((resolve) => {
delay(() => resolve(duration), duration);
});
}
export function snakecase(e) {
if (_.isEmpty(e))
return e;
return e.toLowerCase().replace(/\s+/gim, '_').replace(/-/g, '_').replace(/_+/g, '_');
}
export function tick(returnValue) {
return new Promise((resolve, reject) => {
delay(() => resolve(returnValue));
});
}
export function timestamp(date, includeTime = true) {
const info = dateStrings(date);
const time = ` ${info.time}:${info.seconds}`;
return `${info.year}-${info.month}-${info.date}${includeTime ? time : ''}`;
}
export function trace(...parameters) {
if (!getparams().debug)
return;
for (let i = 0, count = parameters.length; i < count; i++) {
// tslint:disable-next-line
console.log(parameters[i]);
}
}
export function trim(e) {
if (_.isEmpty(e))
return e;
return e.replace(/^\s+/, '').replace(/\s+$/, '');
}
export function truthy(e) {
return !falsy(e);
}
export function validateEmail(email) {
if (!email)
return null;
return String(email)
.toLowerCase()
.match(/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/);
}
export function viewport(el, percentVisible = 100) {
const rect = el.getBoundingClientRect();
const windowHeight = window.innerHeight || document.documentElement.clientHeight;
return !(Math.floor(100 - ((rect.top >= 0 ? 0 : rect.top) / +-(rect.height / 1)) * 100) < percentVisible ||
Math.floor(100 - ((rect.bottom - windowHeight) / rect.height) * 100) < percentVisible);
}
export function password(length) {
const upperCaseChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const lowerCaseChars = 'abcdefghijklmnopqrstuvwxyz';
const numbers = '0123456789';
const specialChars = '!@#$%^&*()-_=+[]|;:,.?';
length = length ?? 8;
// Ensure each type of character appears at least once
const password = [
upperCaseChars[Math.floor(Math.random() * upperCaseChars.length)],
lowerCaseChars[Math.floor(Math.random() * lowerCaseChars.length)],
numbers[Math.floor(Math.random() * numbers.length)],
specialChars[Math.floor(Math.random() * specialChars.length)], // One special char
];
// Pool of all allowed characters for remaining password characters
const allChars = upperCaseChars + lowerCaseChars + numbers + specialChars;
// Fill the rest of the password length (64 characters) with random characters
for (let i = password.length; i < length; i++) {
password.push(allChars[Math.floor(Math.random() * allChars.length)]);
}
// Shuffle the password array to ensure randomness, then join it into a string
const randomPassword = password.sort(() => Math.random() - 0.5).join('');
return randomPassword;
}
export class UtilsModule {
}
UtilsModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: UtilsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
UtilsModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: UtilsModule });
UtilsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: UtilsModule, imports: [[]] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: UtilsModule, decorators: [{
type: NgModule,
args: [{
declarations: [],
imports: [],
exports: []
}]
}] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMubW9kdWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi91dGlscy5tb2R1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUV6QyxPQUFPLEtBQUssQ0FBQyxNQUFNLFlBQVksQ0FBQzs7QUFFaEMsTUFBTSxVQUFVLFdBQVcsQ0FBQyxHQUFHLFVBQWlCO0lBQzlDLElBQUksT0FBTyxVQUFVLENBQUMsQ0FBQyxDQUFDLEtBQUssUUFBUSxFQUFFO1FBQ3JDLHlEQUF5RDtRQUN6RCxNQUFNLENBQUMsR0FBRyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDeEIsTUFBTSxDQUFDLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3hCLElBQUksQ0FBQyxHQUFHLENBQUM7WUFBRSxPQUFPLENBQUMsQ0FBQztRQUNwQixJQUFJLENBQUMsR0FBRyxDQUFDO1lBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUNyQixPQUFPLENBQUMsQ0FBQztLQUNWO1NBQU07UUFDTCw2REFBNkQ7UUFDN0QsTUFBTSxJQUFJLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNCLE1BQU0sUUFBUSxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMvQixJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBTSxFQUFFLENBQU0sRUFBRSxFQUFFO1lBQzNCLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUM7Z0JBQUUsT0FBTyxDQUFDLENBQUM7WUFDeEMsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQztnQkFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQ3pDLE9BQU8sQ0FBQyxDQUFDO1FBQ1gsQ0FBQyxDQUFDLENBQUM7UUFDSCxPQUFPLElBQUksQ0FB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QyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDbkQsWUFBWSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLG1CQUFtQjtLQUNuRixDQUFDO0lBRUYsbUVBQW1FO0lBQ25FLE1BQU0sUUFBUSxHQUFHLGNBQWMsR0FBRyxjQUFjLEdBQUcsT0FBTyxHQUFHLFlBQVksQ0FBQztJQUUxRSw4RUFBOEU7SUFDOUUsS0FBSyxJQUFJLENBQUMsR0FBRyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDN0MsUUFBUSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUN0RTtJQUVELDhFQUE4RTtJQUM5RSxNQUFNLGNBQWMsR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDekUsT0FBTyxjQUFjLENBQUM7QUFDeEIsQ0FBQztBQVlELE1BQU0sT0FBTyxXQUFXOzt3R0FBWCxXQUFXO3lHQUFYLFdBQVc7eUdBQVgsV0FBVyxZQUxiLEVBQ1I7MkZBSVUsV0FBVztrQkFSdkIsUUFBUTttQkFBQztvQkFDUixZQUFZLEVBQUUsRUFDYjtvQkFDRCxPQUFPLEVBQUUsRUFDUjtvQkFDRCxPQUFPLEVBQUUsRUFDUjtpQkFDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE5nTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBVdGlsc0NvbXBvbmVudCB9IGZyb20gJy4vdXRpbHMuY29tcG9uZW50JztcbmltcG9ydCAqIGFzIF8gZnJvbSAndW5kZXJzY29yZSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBhbHBoYWJldGl6ZSguLi5wYXJhbWV0ZXJzOiBhbnlbXSk6IGFueSB7XG4gIGlmICh0eXBlb2YgcGFyYW1ldGVyc1swXSA9PT0gJ3N0cmluZycpIHtcbiAgICAvLyBpZiB0aGlzIG1ldGhvZCBpcyBzdXBwbGllZCBhcyBhIGNhbGxiYWNrIHRvIEFycmF5LnNvcnRcbiAgICBjb25zdCBhID0gcGFyYW1ldGVyc1swXTtcbiAgICBjb25zdCBiID0gcGFyYW1ldGVyc1sxXTtcbiAgICBpZiAoYSA+IGIpIHJldHVybiAxO1xuICAgIGlmIChhIDwgYikgcmV0dXJuIC0xO1xuICAgIHJldHVybiAwO1xuICB9IGVsc2Uge1xuICAgIC8vIGlmIHdlJ3JlIHNvcnRpbmcgYSBsaXN0IHdpdGggYSBzdXBwbGllZCBrZXkgdG8gYWxwaGFiZXRpemVcbiAgICBjb25zdCBsaXN0ID0gcGFyYW1ldGVyc1swXTtcbiAgICBjb25zdCBwcm9wZXJ0eSA9IHBhcmFtZXRlcnNbMV07XG4gICAgbGlzdC5zb3J0KChhOiBhbnksIGI6IGFueSkgPT4ge1xuICAgICAgaWYgKGFbcHJvcGVydHldID4gYltwcm9wZXJ0eV0pIHJldHVybiAxO1xuICAgICAgaWYgKGFbcHJvcGVydHldIDwgYltwcm9wZXJ0eV0pIHJldHVybiAtMTtcbiAgICAgIHJldHVybiAwO1xuICAgIH0pO1xuICAgIHJldHVybiBsaXN0O1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjbG9uZShvYmo6IGFueSk6IGFueSB7XG4gIGlmIChvYmogPT09IG51bGwgfHwgb2JqID09PSB1bmRlZmluZWQpIHJldHVybiBvYmo7XG4gIHJldHVybiBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KG9iaikpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY29udmVydFRvRVNUKGRhdGU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IGdtdERhdGUgPSBuZXcgRGF0ZShkYXRlICsgXCIgR01UXCIpO1xuICBjb25zdCBvcHRpb25zOiBJbnRsLkRhdGVUaW1lRm9ybWF0T3B0aW9ucyA9IHtcbiAgICB0aW1lWm9uZTogJ0FtZXJpY2EvTmV3X1lvcmsnLFxuICAgIHllYXI6IFwibnVtZXJpY1wiLFxuICAgIG1vbnRoOiAnbnVtZXJpYycsXG4gICAgZGF5OiAnbnVtZXJpYycsXG4gICAgaG91cjogJ251bWVyaWMnLFxuICAgIG1pbnV0ZTogJ251bWVyaWMnLFxuICAgIHNlY29uZDogJ251bWVyaWMnLFxuICAgIGhvdXIxMjogdHJ1ZVxuICB9O1xuICBcbiAgY29uc3QgZm9ybWF0dGVyID0gbmV3IEludGwuRGF0ZVRpbWVGb3JtYXQoJ2VuLVVTJywgb3B0aW9ucyk7XG4gIHJldHVybiBmb3JtYXR0ZXIuZm9ybWF0KGdtdERhdGUpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGF0ZVN0cmluZ3MoZGF0ZT86IERhdGUpIHtcbiAgZGF0ZSA9IGRhdGUgfHwgbmV3IERhdGUoKTtcbiAgcmV0dXJuIHtcbiAgICB5ZWFyOiBkYXRlLmdldEZ1bGxZZWFyKCksXG4gICAgbW9udGg6IChkYXRlLmdldE1vbnRoKCkgKyAxKS50b1N0cmluZygpLnBhZFN0YXJ0KDIsICcwJyksXG4gICAgZGF0ZTogZGF0ZS5nZXREYXRlKCkudG9TdHJpbmcoKS5wYWRTdGFydCgyLCAnMCcpLFxuICAgIHRpbWU6IGAke2RhdGUuZ2V0SG91cnMoKS50b1N0cmluZygpLnBhZFN0YXJ0KDIsICcwJyl9OiR7ZGF0ZS5nZXRNaW51dGVzKCkudG9TdHJpbmcoKS5wYWRTdGFydCgyLCAnMCcpfWAsXG4gICAgc2Vjb25kczogZGF0ZS5nZXRTZWNvbmRzKCkudG9TdHJpbmcoKS5wYWRTdGFydCgyLCAnMCcpLFxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVsYXkobWV0aG9kOiAoKSA9PiB2b2lkLCBtczogbnVtYmVyID0gMCk6IG51bWJlciB7XG4gIHJldHVybiB3aW5kb3cuc2V0VGltZW91dChtZXRob2QsIG1zKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRvd25sb2FkKGNvbnRlbnQ6IHN0cmluZywgbmFtZTogc3RyaW5nLCBleHRlbnNpb246IHN0cmluZyA9ICdjc3YnKSB7XG4gIGNvbnN0IGJsb2IgPSBuZXcgQmxvYihbY29udGVudF0pO1xuICBuYW1lID0ga2ViYWIobmFtZSk7XG5cbiAgaWYgKCh3aW5kb3cubmF2aWdhdG9yIGFzIGFueSkubXNTYXZlT3JPcGVuQmxvYikgKHdpbmRvdy5uYXZpZ2F0b3IgYXMgYW55KS5tc1NhdmVCbG9iKGJsb2IsIGAke25hbWV9LiR7ZXh0ZW5zaW9ufWApO1xuICBlbHNlIHtcbiAgICBjb25zdCBhID0gd2luZG93LmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcbiAgICBhLmhyZWYgPSB3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTChibG9iKTtcbiAgICBhLmRvd25sb2FkID0gYCR7bmFtZX0uJHtleHRlbnNpb259YDtcbiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGEpO1xuICAgIGEuY2xpY2soKTtcbiAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGEpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbXB0eShlOiBhbnkpOiBib29sZWFuIHtcbiAgcmV0dXJuIGZhbHN5KGUpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZW51bUtleXM8TyBleHRlbmRzIG9iamVjdCwgSyBleHRlbmRzIGtleW9mIE8gPSBrZXlvZiBPPihvYmo6IE8pOiBLW10ge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmZpbHRlcihrID0+IE51bWJlci5pc05hTigraykpIGFzIEtbXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVudW1WYWx1ZXM8TyBleHRlbmRzIG9iamVjdCwgSyBleHRlbmRzIGtleW9mIE8gPSBrZXlvZiBPPihvYmo6IE8pOiBhbnlbXSB7XG4gICAgY29uc3Qgb3V0cHV0ID0gW11cbiAgICBmb3IgKGNvbnN0IHZhbHVlIG9mIGVudW1LZXlzKG9iaikpIHtcbiAgICAgIG91dHB1dC5wdXNoKG9ialt2YWx1ZV0pOyAgICBcbiAgICB9XG4gICAgcmV0dXJuIG91dHB1dCBhcyBhbnlbXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZhbHN5KGU6IGFueSk6IGJvb2xlYW4ge1xuICBpZiAodHlwZW9mIGUgPT09ICdzdHJpbmcnICYmIHRyaW0oZSkubWF0Y2goL15mYWxzZSQvaSkpIHJldHVybiB0cnVlO1xuICBpZiAodHlwZW9mIGUgPT09ICdzdHJpbmcnKSByZXR1cm4gXy5pc0VtcHR5KGUucmVwbGFjZSgvXFxzKy9naW0sICcnKSk7XG4gIGlmICh0eXBlb2YgZSA9PT0gJ2Jvb2xlYW4nKSByZXR1cm4gZSA9PT0gZmFsc2U7XG4gIGlmICghaXNOYU4ocGFyc2VJbnQoZSwgMTApKSkgcmV0dXJuIGUgPT09IDA7XG4gIHJldHVybiBfLmlzRW1wdHkoZSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmb2N1cyhzZWxlY3Rvcjogc3RyaW5nKTogbnVtYmVyIHtcbiAgY29uc3QgZWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3Ioc2VsZWN0b3IpIGFzIEhUTUxFbGVtZW50O1xuICBpZighZWxlbWVudCB8fCAhZWxlbWVudC5mb2N1cykgcmV0dXJuIDA7XG4gIHJldHVybiBkZWxheSgoKSA9PiBlbGVtZW50LmZvY3VzKCkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TGFyZ2VzdFJlbWFpbmRlcih2YWx1ZXM6IG51bWJlcltdLCBkZXNpcmVkU3VtOiBudW1iZXIpIHtcbiAgbGV0IHN1bSA9IDA7XG4gIGxldCB2YWx1ZVBhcnRzID0gdmFsdWVzLm1hcCgodmFsdWU6IG51bWJlciwgaW5kZXg6IG51bWJlcikgPT4ge1xuICAgIGNvbnN0IGludGVnZXJWYWx1ZSA9IHZhbHVlIHx8IDA7XG4gICAgc3VtICs9IGludGVnZXJWYWx1ZTtcbiAgICByZXR1cm4ge1xuICAgICAgaW50ZWdlcjogaW50ZWdlclZhbHVlLFxuICAgICAgZGVjaW1hbDogdmFsdWUgJSAxLFxuICAgICAgb3JpZ2luYWxJbmRleDogaW5kZXgsXG4gICAgfTtcbiAgfSk7XG5cbiAgaWYgKHN1bSAhPT0gZGVzaXJlZFN1bSAmJiBzdW0pIHtcbiAgICB2YWx1ZVBhcnRzID0gdmFsdWVQYXJ0cy5zb3J0KChhLCBiKSA9PiBiLmRlY2ltYWwgLSBhLmRlY2ltYWwpO1xuXG4gICAgY29uc3QgZGlmZiA9IGRlc2lyZWRTdW0gLSBzdW07XG4gICAgbGV0IGkgPSAwO1xuXG4gICAgd2hpbGUgKGkgPCBkaWZmKSB7XG4gICAgICB2YWx1ZVBhcnRzW2ldLmludGVnZXIrKztcbiAgICAgIGkrKztcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdmFsdWVQYXJ0cy5zb3J0KChhLCBiKSA9PiBhLm9yaWdpbmFsSW5kZXggLSBiLm9yaWdpbmFsSW5kZXgpLm1hcCgocCkgPT4gcC5pbnRlZ2VyKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldHBhcmFtcyhyZXF1ZXN0ZWRQcm9wZXJ0eT86IHN0cmluZyk6IGFueSB7XG4gIGNvbnN0IHZhcnMgPSB7fSBhcyBhbnk7XG4gIGNvbnN0IHBhcnRzID0gd2luZG93LmxvY2F0aW9uLmhyZWYucmVwbGFjZSgvWz8mI10rKFtePSZdKyk9KFteJl0qKS9naSwgKChtOiBhbnksIGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSA9PiB7XG4gICAgdmFyc1trZXldID0gdmFsdWU7XG4gIH0pIGFzIGFueSk7XG5cbiAgZm9yIChjb25zdCBwcm9wIGluIHZhcnMpIHtcbiAgICBpZiAodmFyc1twcm9wXS50b0xvd2VyQ2FzZSgpID09PSAndHJ1ZScpIHZhcnNbcHJvcF0gPSB0cnVlO1xuICAgIGVsc2UgaWYgKHZhcnNbcHJvcF0udG9Mb3dlckNhc2UoKSA9PT0gJ2ZhbHNlJykgdmFyc1twcm9wXSA9IGZhbHNlO1xuICAgIGVsc2UgaWYgKCFpc05hTihwYXJzZUZsb2F0KHZhcnNbcHJvcF0pKSAmJiAhdmFyc1twcm9wXS5tYXRjaCgvW14wLTldKy9naW0pKSB2YXJzW3Byb3BdID0gcGFyc2VGbG9hdCh2YXJzW3Byb3BdKTtcbiAgfVxuXG4gIGlmIChyZXF1ZXN0ZWRQcm9wZXJ0eSkgcmV0dXJuIHZhcnNbcmVxdWVzdGVkUHJvcGVydHldO1xuICByZXR1cm4gdmFycztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzc2V0KGU6IGFueSk6IGJvb2xlYW4ge1xuICByZXR1cm4gdHJ1dGh5KGUpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24ga2ViYWIoZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKF8uaXNFbXB0eShlKSkgcmV0dXJuIGU7XG4gIHJldHVybiBlLnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvXFxzKy9naW0sICctJykucmVwbGFjZSgvXy9nLCAnLScpLnJlcGxhY2UoLy0rL2csICctJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYWdpbmF0ZShtZXRob2Q6IChvZmZzZXQ6IG51bWJlciwgbGltaXQ6IG51bWJlcikgPT4gYW55LCBvZmZzZXQ6IG51bWJlciwgbGltaXQ6IG51bWJlciwga2V5OiBzdHJpbmcsIG91dHB1dDogYW55W10gPSBbXSwgY2FsbGJhY2s/OiAoYWxsUm93czphbnlbXSwgbmV3Um93czogYW55W10pID0+IHZvaWQsIHByZXZSZXNvbHZlPzogKHJlc3VsdDogYW55KSA9PiB2b2lkKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGFzeW5jIChyZXNvbHZlOiAocmVzdWx0OiBhbnkpID0+IHZvaWQsIHJlamVjdDogKHJlc3VsdDogYW55KSA9PiB2b2lkKSA9PiB7XG4gICAgICBsZXQgcmVzcG9uc2U7XG4gICAgICB0cnkge1xuICAgICAgICByZXNwb25zZSA9IGF3YWl0IG1ldGhvZChvZmZzZXQsIGxpbWl0KTtcbiAgICAgIH0gY2F0Y2goZTogYW55KSB7XG4gICAgICAgIHJlamVjdChlKTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgb3V0cHV0ID0gb3V0cHV0LmNvbmNhdChyZXNwb25zZVtrZXldKTtcbiAgICAgIFxuICAgICAgaWYoY2FsbGJhY2spIGNhbGxiYWNrKG91dHB1dCwgcmVzcG9uc2Vba2V5XSk7XG4gICAgICBcbiAgICAgIGlmKHJlc3BvbnNlLm5leHRQYWdlKSB7XG4gICAgICAgIGF3YWl0IHBhZ2luYXRlKG1ldGhvZCwgcmVzcG9uc2UubmV4dFBhZ2UsIGxpbWl0LCBrZXksIG91dHB1dCwgY2FsbGJhY2ssIHByZXZSZXNvbHZlID8/IHJlc29sdmUpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICAocHJldlJlc29sdmUgPz8gcmVzb2x2ZSkob3V0cHV0KTtcbiAgICAgIH1cbiAgICAgIFxuICAgIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcHJlcGFyZVNlYXJjaFN0cmluZyh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBpZighdmFsdWUpIHJldHVybiBcIlwiO1xuICAgIHJldHVybiB2YWx1ZS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoL1xccysvZ2ltLFwiXCIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVwbGFjZUl0ZW0oYXJyYXk6IGFueVtdLCBpdGVtOiBhbnksIGtleTogc3RyaW5nID0gJ2lkJywgcG9zaXRpb246IHN0cmluZyA9ICdjdXJyZW50Jyk6IGFueSB7XG4gIGNvbnN0IGxvb2t1cCA9IHt9IGFzIGFueTtcbiAgbG9va3VwW2tleV0gPSBpdGVtW2tleV07XG5cbiAgY29uc3Qgb2xkSXRlbSA9IF8uZmluZFdoZXJlKGFycmF5LCBsb29rdXApO1xuXG4gIGlmICghb2xkSXRlbSkge1xuICAgIGFycmF5LnVuc2hpZnQoaXRlbSk7XG4gICAgcmV0dXJuIGl0ZW07XG4gIH1cblxuICBjb25zdCBpbmRleCA9IGFycmF5LmluZGV4T2Yob2xkSXRlbSk7XG5cbiAgaWYgKHBvc2l0aW9uID09PSAnZmlyc3QnKSB7XG4gICAgYXJyYXkuc3BsaWNlKGluZGV4LCAxKTtcbiAgICBhcnJheS51bnNoaWZ0KGl0ZW0pO1xuICB9IGVsc2Uge1xuICAgIGFycmF5LnNwbGljZShpbmRleCwgMSwgaXRlbSk7XG4gIH1cblxuICByZXR1cm4gaXRlbTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNsZWVwKGR1cmF0aW9uOiBudW1iZXIgPSAwKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZTogKHZhbHVlOiBhbnkpID0+IHZvaWQpID0+IHtcbiAgICBkZWxheSgoKSA9PiByZXNvbHZlKGR1cmF0aW9uKSwgZHVyYXRpb24pO1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNuYWtlY2FzZShlOiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAoXy5pc0VtcHR5KGUpKSByZXR1cm4gZTtcbiAgcmV0dXJuIGUudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9cXHMrL2dpbSwgJ18nKS5yZXBsYWNlKC8tL2csICdfJykucmVwbGFjZSgvXysvZywgJ18nKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRpY2socmV0dXJuVmFsdWU/OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmU6IChyZXNwb25zZTogYW55KSA9PiB2b2lkLCByZWplY3Q6IChyZXNwb25zZTogYW55KSA9PiB2b2lkKSA9PiB7XG4gICAgZGVsYXkoKCkgPT4gcmVzb2x2ZShyZXR1cm5WYWx1ZSkpO1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRpbWVzdGFtcChkYXRlPzogRGF0ZSwgaW5jbHVkZVRpbWU6IGJvb2xlYW4gPSB0cnVlKTogc3RyaW5nIHtcbiAgY29uc3QgaW5mbyA9IGRhdGVTdHJpbmdzKGRhdGUpO1xuICBjb25zdCB0aW1lID0gYCAke2luZm8udGltZX06JHtpbmZvLnNlY29uZHN9YDtcbiAgcmV0dXJuIGAke2luZm8ueWVhcn0tJHtpbmZvLm1vbnRofS0ke2luZm8uZGF0ZX0ke2luY2x1ZGVUaW1lID8gdGltZSA6ICcnfWA7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0cmFjZSguLi5wYXJhbWV0ZXJzOiBhbnlbXSkge1xuICBpZiAoIWdldHBhcmFtcygpLmRlYnVnKSByZXR1cm47XG5cbiAgZm9yIChsZXQgaSA9IDAsIGNvdW50ID0gcGFyYW1ldGVycy5sZW5ndGg7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lXG4gICAgY29uc29sZS5sb2cocGFyYW1ldGVyc1tpXSk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRyaW0oZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKF8uaXNFbXB0eShlKSkgcmV0dXJuIGU7XG4gIHJldHVybiBlLnJlcGxhY2UoL15cXHMrLywgJycpLnJlcGxhY2UoL1xccyskLywgJycpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHJ1dGh5KGU6IGFueSk6IGJvb2xlYW4ge1xuICByZXR1cm4gIWZhbHN5KGUpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVFbWFpbChlbWFpbDogc3RyaW5nIHwgbnVsbCk6IFJlZ0V4cE1hdGNoQXJyYXkgfCBudWxsIHtcbiAgaWYgKCFlbWFpbCkgcmV0dXJuIG51bGw7XG5cbiAgcmV0dXJuIFN0cmluZyhlbWFpbClcbiAgICAudG9Mb3dlckNhc2UoKVxuICAgIC5tYXRjaChcbiAgICAgIC9eKChbXjw+KClbXFxdXFxcXC4sOzpcXHNAXCJdKyhcXC5bXjw+KClbXFxdXFxcXC4sOzpcXHNAXCJdKykqKXwoXCIuK1wiKSlAKChcXFtbMC05XXsxLDN9XFwuWzAtOV17MSwzfVxcLlswLTldezEsM31cXC5bMC05XXsxLDN9XFxdKXwoKFthLXpBLVpcXC0wLTldK1xcLikrW2EtekEtWl17Mix9KSkkLyxcbiAgICApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdmlld3BvcnQoZWw6IEhUTUxFbGVtZW50LCBwZXJjZW50VmlzaWJsZTogbnVtYmVyID0gMTAwKTogYm9vbGVhbiB7XG4gIGNvbnN0IHJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgY29uc3Qgd2luZG93SGVpZ2h0ID0gd2luZG93LmlubmVySGVpZ2h0IHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQ7XG5cbiAgcmV0dXJuICEoXG4gICAgTWF0aC5mbG9vcigxMDAgLSAoKHJlY3QudG9wID49IDAgPyAwIDogcmVjdC50b3ApIC8gKy0ocmVjdC5oZWlnaHQgLyAxKSkgKiAxMDApIDwgcGVyY2VudFZpc2libGUgfHxcbiAgICBNYXRoLmZsb29yKDEwMCAtICgocmVjdC5ib3R0b20gLSB3aW5kb3dIZWlnaHQpIC8gcmVjdC5oZWlnaHQpICogMTAwKSA8IHBlcmNlbnRWaXNpYmxlXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXNzd29yZChsZW5ndGg6IG51bWJlcik6IHN0cmluZyB7XG4gIGNvbnN0IHVwcGVyQ2FzZUNoYXJzID0gJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaJztcbiAgY29uc3QgbG93ZXJDYXNlQ2hhcnMgPSAnYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXonO1xuICBjb25zdCBudW1iZXJzID0gJzAxMjM0NTY3ODknO1xuICBjb25zdCBzcGVjaWFsQ2hhcnMgPSAnIUAjJCVeJiooKS1fPStbXXw7OiwuPyc7XG4gIGxlbmd0aCA9IGxlbmd0aCA/PyA4O1xuXG4gIC8vIEVuc3VyZSBlYWNoIHR5cGUgb2YgY2hhcmFjdGVyIGFwcGVhcnMgYXQgbGVhc3Qgb25jZVxuICBjb25zdCBwYXNzd29yZCA9IFtcbiAgICB1cHBlckNhc2VDaGFyc1tNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiB1cHBlckNhc2VDaGFycy5sZW5ndGgpXSwgLy8gT25lIHVwcGVyY2FzZVxuICAgIGxvd2VyQ2FzZUNoYXJzW01hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIGxvd2VyQ2FzZUNoYXJzLmxlbmd0aCldLCAvLyBPbmUgbG93ZXJjYXNlXG4gICAgbnVtYmVyc1tNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBudW1iZXJzLmxlbmd0aCldLCAvLyBPbmUgbnVtYmVyXG4gICAgc3BlY2lhbENoYXJzW01hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIHNwZWNpYWxDaGFycy5sZW5ndGgpXSwgLy8gT25lIHNwZWNpYWwgY2hhclxuICBdO1xuXG4gIC8vIFBvb2wgb2YgYWxsIGFsbG93ZWQgY2hhcmFjdGVycyBmb3IgcmVtYWluaW5nIHBhc3N3b3JkIGNoYXJhY3RlcnNcbiAgY29uc3QgYWxsQ2hhcnMgPSB1cHBlckNhc2VDaGFycyArIGxvd2VyQ2FzZUNoYXJzICsgbnVtYmVycyArIHNwZWNpYWxDaGFycztcblxuICAvLyBGaWxsIHRoZSByZXN0IG9mIHRoZSBwYXNzd29yZCBsZW5ndGggKDY0IGNoYXJhY3RlcnMpIHdpdGggcmFuZG9tIGNoYXJhY3RlcnNcbiAgZm9yIChsZXQgaSA9IHBhc3N3b3JkLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgcGFzc3dvcmQucHVzaChhbGxDaGFyc1tNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBhbGxDaGFycy5sZW5ndGgpXSk7XG4gIH1cblxuICAvLyBTaHVmZmxlIHRoZSBwYXNzd29yZCBhcnJheSB0byBlbnN1cmUgcmFuZG9tbmVzcywgdGhlbiBqb2luIGl0IGludG8gYSBzdHJpbmdcbiAgY29uc3QgcmFuZG9tUGFzc3dvcmQgPSBwYXNzd29yZC5zb3J0KCgpID0+IE1hdGgucmFuZG9tKCkgLSAwLjUpLmpvaW4oJycpO1xuICByZXR1cm4gcmFuZG9tUGFzc3dvcmQ7XG59XG5cblxuXG5ATmdNb2R1bGUoe1xuICBkZWNsYXJhdGlvbnM6IFtcbiAgXSxcbiAgaW1wb3J0czogW1xuICBdLFxuICBleHBvcnRzOiBbXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgVXRpbHNNb2R1bGUgeyB9XG4iXX0=