/** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * Copyright (C) 2018 Michael Czechowski * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as tslib_1 from "tslib"; import { Injectable } from '@angular/core'; import * as Random from 'd3-random'; var NlsMathService = /** @class */ (function () { function NlsMathService() { } /** * Calculate distance between to points with coordinates. * @param {?} a * @param {?} b * @return {?} */ NlsMathService.prototype.Δ = /** * Calculate distance between to points with coordinates. * @param {?} a * @param {?} b * @return {?} */ function (a, b) { return Math.pow(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2), 0.5); }; /** * @param {?} point * @param {?} matrix * @return {?} */ NlsMathService.prototype.getClosestCenter = /** * @param {?} point * @param {?} matrix * @return {?} */ function (point, matrix) { if (this.Δ(point, matrix.start) < this.Δ(point, matrix.end)) { return matrix.start; } else { return matrix.end; } }; /** * @param {?} point * @param {?} matrix * @return {?} */ NlsMathService.prototype.getFarestCenter = /** * @param {?} point * @param {?} matrix * @return {?} */ function (point, matrix) { if (this.Δ(point, matrix.start) > this.Δ(point, matrix.end)) { return matrix.start; } else { return matrix.end; } }; /** * @param {?} matrix * @param {?} overlap * @return {?} */ NlsMathService.prototype.randomPoint = /** * @param {?} matrix * @param {?} overlap * @return {?} */ function (matrix, overlap) { /** @type {?} */ var x = { min: matrix.center.x - matrix.width * overlap, max: matrix.center.x + matrix.width * overlap }; /** @type {?} */ var y = { min: matrix.center.y - matrix.height * overlap, max: matrix.center.y + matrix.height * overlap }; return { x: Random.randomUniform(x.min, x.max)(), y: Random.randomUniform(y.min, y.max)() }; }; /** * @param {?} width * @param {?} height * @return {?} */ NlsMathService.prototype.centerOfArea = /** * @param {?} width * @param {?} height * @return {?} */ function (width, height) { return { x: width * 0.5, y: height * 0.5 }; }; /** * @param {?} p1 * @param {?} p2 * @return {?} */ NlsMathService.prototype.centerOfPoints = /** * @param {?} p1 * @param {?} p2 * @return {?} */ function (p1, p2) { return { x: (p1.x + p2.x) * 0.5, y: (p1.y + p2.y) * 0.5 }; }; /** * @param {?} curve * @return {?} */ NlsMathService.prototype.centerOfCurve = /** * @param {?} curve * @return {?} */ function (curve) { /** @type {?} */ var genMedian = this.medianPoint(curve); /** @type {?} */ var p1 = genMedian.next().value; /** @type {?} */ var p2 = genMedian.next().value; /** @type {?} */ var radians = this.angleRadians(p1, p2); return Object.assign(this.centerOfPoints(p1, p2), { ascent: radians }); }; /** * @param {?} curve * @return {?} */ NlsMathService.prototype.medianOfCurve = /** * @param {?} curve * @return {?} */ function (curve) { /** @type {?} */ var genMedian = this.medianPoint(curve); /** @type {?} */ var p1 = genMedian.next().value; /** @type {?} */ var p2 = genMedian.next().value; /** @type {?} */ var p3 = genMedian.next().value; /** @type {?} */ var radians = this.angleRadians(p2, p3); // const radians = Math.round(Math.random() * 10000) / 1000; // @todo if nodes are less than 5 error occures return Object.assign(p1, { ascent: radians }); }; /** * @param {?} p1 * @param {?} p2 * @return {?} */ NlsMathService.prototype.angleRadians = /** * @param {?} p1 * @param {?} p2 * @return {?} */ function (p1, p2) { return Math.atan2(p2.y - p1.y, p2.x - p1.x); }; /** * @param {?} p1 * @param {?} p2 * @return {?} */ NlsMathService.prototype.angleDegree = /** * @param {?} p1 * @param {?} p2 * @return {?} */ function (p1, p2) { return this.angleRadians(p1, p2) * 180 / Math.PI; }; /** * @param {?} list * @return {?} */ NlsMathService.prototype.medianIndex = /** * @param {?} list * @return {?} */ function (list) { return Math.floor(list.length * 0.5); }; /** * @param {?} points * @return {?} */ NlsMathService.prototype.medianPoint = /** * @param {?} points * @return {?} */ function (points) { var index, list; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: list = points.slice(); _a.label = 1; case 1: if (!list) return [3 /*break*/, 3]; index = this.medianIndex(points); return [4 /*yield*/, list[index]]; case 2: _a.sent(); list.splice(index, 1); return [3 /*break*/, 1]; case 3: return [2 /*return*/]; } }); }; /** * Generator for sine bounce * * @param {?=} amplitude default to 1 indicates the amplitude in positive as well * in negative range * @param {?=} decimals amount of decimal places * @param {?=} start 0 indicates to initiate with positive numbers, 1 indicates to * start with negative numbers first * @return {?} */ NlsMathService.prototype.bounce = /** * Generator for sine bounce * * @param {?=} amplitude default to 1 indicates the amplitude in positive as well * in negative range * @param {?=} decimals amount of decimal places * @param {?=} start 0 indicates to initiate with positive numbers, 1 indicates to * start with negative numbers first * @return {?} */ function (amplitude, decimals, start) { if (amplitude === void 0) { amplitude = 1; } if (decimals === void 0) { decimals = 1; } if (start === void 0) { start = 0; } var power, step, index, radians; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: power = Math.pow(10, decimals); step = 2 / (power); index = 0; _a.label = 1; case 1: if (!true) return [3 /*break*/, 3]; radians = Math.PI * step * index + start; return [4 /*yield*/, Math.round((Math.sin(radians) * amplitude) * power) / power]; case 2: _a.sent(); index++; return [3 /*break*/, 1]; case 3: return [2 /*return*/]; } }); }; /** * @param {?=} startPositive * @return {?} */ NlsMathService.prototype.flipSign = /** * @param {?=} startPositive * @return {?} */ function (startPositive) { if (startPositive === void 0) { startPositive = true; } var sign; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: sign = startPositive ? 1 : -1; _a.label = 1; case 1: if (!true) return [3 /*break*/, 3]; return [4 /*yield*/, sign = sign * (-1)]; case 2: _a.sent(); return [3 /*break*/, 1]; case 3: return [2 /*return*/]; } }); }; NlsMathService.decorators = [ { type: Injectable }, ]; return NlsMathService; }()); export { NlsMathService }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0aC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vbmxzLWd1aWxsb2NoZS8iLCJzb3VyY2VzIjpbIm5scy9zZXJ2aWNlcy9tYXRoLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFnQkEsT0FBTyxFQUFVLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUVuRCxPQUFPLEtBQUssTUFBTSxNQUFNLFdBQVcsQ0FBQzs7Ozs7Ozs7OztJQWEzQiwwQkFBQzs7Ozs7O2NBQUMsQ0FBUSxFQUFFLENBQVE7UUFDekIsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7Ozs7Ozs7SUFHakUseUNBQWdCOzs7OztjQUFDLEtBQVksRUFBRSxNQUFXO1FBQy9DLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzVELE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDO1NBQ3JCO1FBQUMsSUFBSSxDQUFDLENBQUM7WUFDTixNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQztTQUNuQjs7Ozs7OztJQUdJLHdDQUFlOzs7OztjQUFDLEtBQVksRUFBRSxNQUFXO1FBQzlDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FB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Q0FBQyxDQUFDO29CQUMvQixJQUFJLEdBQUcsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBQ3JCLEtBQUssR0FBRyxDQUFDLENBQUM7Ozt5QkFFUCxJQUFJO29CQUNILE9BQU8sR0FBRyxJQUFJLENBQUMsRUFBRSxHQUFHLElBQUksR0FBRyxLQUFLLEdBQUcsS0FBSyxDQUFDO29CQUMvQyxxQkFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsR0FBRyxTQUFTLENBQUMsR0FBRyxLQUFLLENBQUMsR0FBRyxLQUFLLEVBQUE7O29CQUFqRSxTQUFpRSxDQUFDO29CQUVsRSxLQUFLLEVBQUUsQ0FBQzs7Ozs7Ozs7OztJQUlKLGlDQUFROzs7O2NBQUMsYUFBNkI7UUFBN0IsOEJBQUEsRUFBQSxvQkFBNkI7Ozs7O29CQUN4QyxJQUFJLEdBQUcsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDOzs7eUJBRTNCLElBQUk7b0JBQ1QscUJBQU0sSUFBSSxHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUE7O29CQUF4QixTQUF3QixDQUFDOzs7Ozs7O2dCQXJJOUIsVUFBVTs7eUJBdkJYOztTQXdCYSxjQUFjIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggTWljaGFlbCBDemVjaG93c2tpIDxtYWlsQGRhaWx5c2guaXQ+XG4gKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICogdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWVcbiAqIFNvZnR3YXJlIEZvdW5kYXRpb247IHZlcnNpb24gMi5cbiAqXG4gKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAqIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWSBvclxuICogRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yXG4gKiBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYWxvbmcgd2l0aFxuICogdGhpcyBwcm9ncmFtOyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIEluYy4sIDUxXG4gKiBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BIDAyMTEwLTEzMDEsIFVTQS5cbiAqL1xuXG5pbXBvcnQgeyBJbmplY3QsIEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCAqIGFzIFNlbGVjdGlvbiBmcm9tICdkMy1zZWxlY3Rpb24nO1xuaW1wb3J0ICogYXMgUmFuZG9tIGZyb20gJ2QzLXJhbmRvbSc7XG5cbmltcG9ydCB7IFBvaW50IH0gZnJvbSAnLi8uLi9tb2RlbHMvcG9pbnQubW9kZWwnO1xuaW1wb3J0IHsgR3JhcGggfSBmcm9tICcuLy4uL21vZGVscy9ncmFwaC5tb2RlbCc7XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBObHNNYXRoU2VydmljZSB7XG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZSBkaXN0YW5jZSBiZXR3ZWVuIHRvIHBvaW50cyB3aXRoIGNvb3JkaW5hdGVzLlxuICAgKiBAcGFyYW0gYVxuICAgKiBAcGFyYW0gYlxuICAgKi9cbiAgcHVibGljIM6UKGE6IFBvaW50LCBiOiBQb2ludCkge1xuICAgIHJldHVybiBNYXRoLnBvdyhNYXRoLnBvdyhhLnggLSBiLngsIDIpICsgTWF0aC5wb3coYS55IC0gYi55LCAyKSwgMC41KTtcbiAgfVxuXG4gIHB1YmxpYyBnZXRDbG9zZXN0Q2VudGVyKHBvaW50OiBQb2ludCwgbWF0cml4OiBhbnkpIHtcbiAgICBpZiAodGhpcy7OlChwb2ludCwgbWF0cml4LnN0YXJ0KSA8IHRoaXMuzpQocG9pbnQsIG1hdHJpeC5lbmQpKSB7XG4gICAgICByZXR1cm4gbWF0cml4LnN0YXJ0O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbWF0cml4LmVuZDtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZ2V0RmFyZXN0Q2VudGVyKHBvaW50OiBQb2ludCwgbWF0cml4OiBhbnkpIHtcbiAgICBpZiAodGhpcy7OlChwb2ludCwgbWF0cml4LnN0YXJ0KSA+IHRoaXMuzpQocG9pbnQsIG1hdHJpeC5lbmQpKSB7XG4gICAgICByZXR1cm4gbWF0cml4LnN0YXJ0O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbWF0cml4LmVuZDtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgcmFuZG9tUG9pbnQobWF0cml4OiBhbnksIG92ZXJsYXA6IG51bWJlcikge1xuICAgIGNvbnN0IHggPSB7XG4gICAgICBtaW46IG1hdHJpeC5jZW50ZXIueCAtIG1hdHJpeC53aWR0aCAqIG92ZXJsYXAsXG4gICAgICBtYXg6IG1hdHJpeC5jZW50ZXIueCArIG1hdHJpeC53aWR0aCAqIG92ZXJsYXBcbiAgICB9O1xuICAgIGNvbnN0IHkgPSB7XG4gICAgICBtaW46IG1hdHJpeC5jZW50ZXIueSAtIG1hdHJpeC5oZWlnaHQgKiBvdmVybGFwLFxuICAgICAgbWF4OiBtYXRyaXguY2VudGVyLnkgKyBtYXRyaXguaGVpZ2h0ICogb3ZlcmxhcFxuICAgIH07XG5cbiAgICByZXR1cm4ge1xuICAgICAgeDogUmFuZG9tLnJhbmRvbVVuaWZvcm0oeC5taW4sIHgubWF4KSgpLFxuICAgICAgeTogUmFuZG9tLnJhbmRvbVVuaWZvcm0oeS5taW4sIHkubWF4KSgpXG4gICAgfTtcbiAgfVxuXG4gIHB1YmxpYyBjZW50ZXJPZkFyZWEod2lkdGgsIGhlaWdodCk6IFBvaW50IHtcbiAgICByZXR1cm4ge1xuICAgICAgeDogd2lkdGggKiAwLjUsXG4gICAgICB5OiBoZWlnaHQgKiAwLjVcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIGNlbnRlck9mUG9pbnRzKHAxOiBQb2ludCwgcDI6IFBvaW50KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHg6IChwMS54ICsgcDIueCkgKiAwLjUsXG4gICAgICB5OiAocDEueSArIHAyLnkpICogMC41XG4gICAgfTtcbiAgfVxuXG4gIHB1YmxpYyBjZW50ZXJPZkN1cnZlKGN1cnZlOiBQb2ludFtdKSB7XG4gICAgY29uc3QgZ2VuTWVkaWFuID0gdGhpcy5tZWRpYW5Qb2ludChjdXJ2ZSk7XG4gICAgY29uc3QgcDEgPSBnZW5NZWRpYW4ubmV4dCgpLnZhbHVlO1xuICAgIGNvbnN0IHAyID0gZ2VuTWVkaWFuLm5leHQoKS52YWx1ZTtcbiAgICBjb25zdCByYWRpYW5zID0gdGhpcy5hbmdsZVJhZGlhbnMocDEsIHAyKTtcblxuICAgIHJldHVybiBPYmplY3QuYXNzaWduKHRoaXMuY2VudGVyT2ZQb2ludHMocDEsIHAyKSwgeyBhc2NlbnQ6IHJhZGlhbnMgfSk7XG4gIH1cblxuICBwdWJsaWMgbWVkaWFuT2ZDdXJ2ZShjdXJ2ZTogUG9pbnRbXSkge1xuICAgIGNvbnN0IGdlbk1lZGlhbiA9IHRoaXMubWVkaWFuUG9pbnQoY3VydmUpO1xuICAgIGNvbnN0IHAxID0gZ2VuTWVkaWFuLm5leHQoKS52YWx1ZTtcbiAgICBjb25zdCBwMiA9IGdlbk1lZGlhbi5uZXh0KCkudmFsdWU7XG4gICAgY29uc3QgcDMgPSBnZW5NZWRpYW4ubmV4dCgpLnZhbHVlO1xuICAgIGNvbnN0IHJhZGlhbnMgPSB0aGlzLmFuZ2xlUmFkaWFucyhwMiwgcDMpO1xuICAgIC8vIGNvbnN0IHJhZGlhbnMgPSBNYXRoLnJvdW5kKE1hdGgucmFuZG9tKCkgKiAxMDAwMCkgLyAxMDAwO1xuICAgIC8vIEB0b2RvIGlmIG5vZGVzIGFyZSBsZXNzIHRoYW4gNSBlcnJvciBvY2N1cmVzXG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24ocDEsIHsgYXNjZW50OiByYWRpYW5zIH0pO1xuICB9XG5cbiAgcHVibGljIGFuZ2xlUmFkaWFucyhwMTogUG9pbnQsIHAyOiBQb2ludCkge1xuICAgIHJldHVybiBNYXRoLmF0YW4yKHAyLnkgLSBwMS55LCBwMi54IC0gcDEueCk7XG4gIH1cblxuICBwdWJsaWMgYW5nbGVEZWdyZWUocDE6IFBvaW50LCBwMjogUG9pbnQpIHtcbiAgICByZXR1cm4gdGhpcy5hbmdsZVJhZGlhbnMocDEsIHAyKSAqIDE4MCAvIE1hdGguUEk7XG4gIH1cblxuICBwdWJsaWMgbWVkaWFuSW5kZXgobGlzdDogYW55KTogbnVtYmVyIHtcbiAgICByZXR1cm4gTWF0aC5mbG9vcihsaXN0Lmxlbmd0aCAqIDAuNSk7XG4gIH1cblxuICBwdWJsaWMgKm1lZGlhblBvaW50KHBvaW50czogUG9pbnRbXSkge1xuICAgIGxldCBpbmRleDogbnVtYmVyO1xuICAgIGNvbnN0IGxpc3Q6IFBvaW50W10gPSBwb2ludHMuc2xpY2UoKTtcblxuICAgIHdoaWxlIChsaXN0KSB7XG4gICAgICBpbmRleCA9IHRoaXMubWVkaWFuSW5kZXgocG9pbnRzKTtcbiAgICAgIHlpZWxkIGxpc3RbaW5kZXhdO1xuXG4gICAgICBsaXN0LnNwbGljZShpbmRleCwgMSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRvciBmb3Igc2luZSBib3VuY2VcbiAgICpcbiAgICogQHBhcmFtIHN0YXJ0IDAgaW5kaWNhdGVzIHRvIGluaXRpYXRlIHdpdGggcG9zaXRpdmUgbnVtYmVycywgMSBpbmRpY2F0ZXMgdG9cbiAgICogc3RhcnQgd2l0aCBuZWdhdGl2ZSBudW1iZXJzIGZpcnN0XG4gICAqIEBwYXJhbSBhbXBsaXR1ZGUgZGVmYXVsdCB0byAxIGluZGljYXRlcyB0aGUgYW1wbGl0dWRlIGluIHBvc2l0aXZlIGFzIHdlbGxcbiAgICogaW4gbmVnYXRpdmUgcmFuZ2VcbiAgICogQHBhcmFtIGRlY2ltYWxzIGFtb3VudCBvZiBkZWNpbWFsIHBsYWNlc1xuICAgKi9cblxuICBwdWJsaWMgKmJvdW5jZShcbiAgICBhbXBsaXR1ZGU6IG51bWJlciA9IDEsXG4gICAgZGVjaW1hbHM6IG51bWJlciA9IDEsXG4gICAgc3RhcnQ6IG51bWJlciA9IDBcbiAgKSB7XG4gICAgY29uc3QgcG93ZXIgPSBNYXRoLnBvdygxMCwgZGVjaW1hbHMpO1xuICAgIGNvbnN0IHN0ZXAgPSAyIC8gKHBvd2VyKTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGNvbnN0IHJhZGlhbnMgPSBNYXRoLlBJICogc3RlcCAqIGluZGV4ICsgc3RhcnQ7XG4gICAgICB5aWVsZCBNYXRoLnJvdW5kKChNYXRoLnNpbihyYWRpYW5zKSAqIGFtcGxpdHVkZSkgKiBwb3dlcikgLyBwb3dlcjtcblxuICAgICAgaW5kZXgrKztcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgKmZsaXBTaWduKHN0YXJ0UG9zaXRpdmU6IGJvb2xlYW4gPSB0cnVlKSB7XG4gICAgbGV0IHNpZ24gPSBzdGFydFBvc2l0aXZlID8gMSA6IC0xO1xuXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIHlpZWxkIHNpZ24gPSBzaWduICogKC0xKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==