1 | /**
|
2 | * @license
|
3 | * Copyright 2018 Google LLC
|
4 | *
|
5 | * Use of this source code is governed by an MIT-style
|
6 | * license that can be found in the LICENSE file or at
|
7 | * https://opensource.org/licenses/MIT.
|
8 | * =============================================================================
|
9 | */
|
10 | /**
|
11 | * Padding Layers.
|
12 | */
|
13 | // Porting Note: In Python Keras, the padding layers are in convolutional.py,
|
14 | // but we decided to put them in a separate file (padding.ts) for clarity.
|
15 | import * as tfc from '@tensorflow/tfjs-core';
|
16 | import { serialization, tidy } from '@tensorflow/tfjs-core';
|
17 | import { imageDataFormat } from '../backend/common';
|
18 | import { InputSpec, Layer } from '../engine/topology';
|
19 | import { ValueError } from '../errors';
|
20 | import { getExactlyOneShape, getExactlyOneTensor } from '../utils/types_utils';
|
21 | /**
|
22 | * Pads the middle dimension of a 3D tensor.
|
23 | *
|
24 | * @param x Input `tf.Tensor` to be padded.
|
25 | * @param padding `Array` of 2 integers, how many zeros to add at the start and
|
26 | * end of the middle dimension (i.e., dimension 1).
|
27 | * @return A padded 3D `tf.Tensor`.
|
28 | */
|
29 | export function temporalPadding(x, padding) {
|
30 | return tidy(() => {
|
31 | if (x.rank !== 3) {
|
32 | throw new ValueError(`temporalPadding expects input tensor to be 3-D, but received a ` +
|
33 | `${x.rank}-D tensor.`);
|
34 | }
|
35 | if (padding == null) {
|
36 | padding = [1, 1];
|
37 | }
|
38 | if (padding.length !== 2) {
|
39 | throw new ValueError(`temporalPadding expects input padding pattern to be a length-2 ` +
|
40 | `array, but received a length-${padding.length} array.`);
|
41 | }
|
42 | const pattern = [[0, 0], padding, [0, 0]];
|
43 | return tfc.pad(x, pattern);
|
44 | });
|
45 | }
|
46 | /**
|
47 | * Pads the 2nd and 3rd dimensions of a 4D tensor.
|
48 | *
|
49 | * @param x Input `tf.Tensor` to be padded.
|
50 | * @param padding `Array` of two `Array`s, each of which is an `Array` of two
|
51 | * integers. The amount of padding at the beginning and end of the 2nd and 3rd
|
52 | * dimensions, respectively.
|
53 | * @param dataFormat 'channelsLast' (default) or 'channelsFirst'.
|
54 | * @return Padded 4D `tf.Tensor`.
|
55 | */
|
56 | export function spatial2dPadding(x, padding, dataFormat) {
|
57 | return tidy(() => {
|
58 | if (x.rank !== 4) {
|
59 | throw new ValueError(`temporalPadding expects input tensor to be 4-D, but received a ` +
|
60 | `${x.rank}-D tensor.`);
|
61 | }
|
62 | if (padding == null) {
|
63 | padding = [[1, 1], [1, 1]];
|
64 | }
|
65 | if (padding.length !== 2 || padding[0].length !== 2 ||
|
66 | padding[1].length !== 2) {
|
67 | throw new ValueError('spatial2dPadding expects `padding` to be an Array of two Arrays, ' +
|
68 | 'each of which is an Array of two integers.');
|
69 | }
|
70 | if (dataFormat == null) {
|
71 | dataFormat = imageDataFormat();
|
72 | }
|
73 | if (dataFormat !== 'channelsLast' && dataFormat !== 'channelsFirst') {
|
74 | throw new ValueError(`Unknown data format: ${dataFormat}. ` +
|
75 | `Supported data formats are 'channelsLast' and 'channelsFirst.`);
|
76 | }
|
77 | let pattern;
|
78 | if (dataFormat === 'channelsFirst') {
|
79 | pattern = [[0, 0], [0, 0], padding[0], padding[1]];
|
80 | }
|
81 | else {
|
82 | pattern = [[0, 0], padding[0], padding[1], [0, 0]];
|
83 | }
|
84 | return tfc.pad(x, pattern);
|
85 | });
|
86 | }
|
87 | export class ZeroPadding2D extends Layer {
|
88 | constructor(args) {
|
89 | if (args == null) {
|
90 | args = {};
|
91 | }
|
92 | super(args);
|
93 | this.dataFormat =
|
94 | args.dataFormat == null ? imageDataFormat() : args.dataFormat;
|
95 | // TODO(cais): Maybe refactor the following logic surrounding `padding`
|
96 | // into a helper method.
|
97 | if (args.padding == null) {
|
98 | this.padding = [[1, 1], [1, 1]];
|
99 | }
|
100 | else if (typeof args.padding === 'number') {
|
101 | this.padding =
|
102 | [[args.padding, args.padding], [args.padding, args.padding]];
|
103 | }
|
104 | else {
|
105 | args.padding = args.padding;
|
106 | if (args.padding.length !== 2) {
|
107 | throw new ValueError(`ZeroPadding2D expects padding to be a length-2 array, but ` +
|
108 | `received a length-${args.padding.length} array.`);
|
109 | }
|
110 | let heightPadding;
|
111 | let widthPadding;
|
112 | if (typeof args.padding[0] === 'number') {
|
113 | heightPadding = [args.padding[0], args.padding[0]];
|
114 | widthPadding = [args.padding[1], args.padding[1]];
|
115 | }
|
116 | else {
|
117 | args.padding = args.padding;
|
118 | if (args.padding[0].length !== 2) {
|
119 | throw new ValueError(`ZeroPadding2D expects height padding to be a length-2 array, ` +
|
120 | `but received a length-${args.padding[0].length} array.`);
|
121 | }
|
122 | heightPadding = args.padding[0];
|
123 | if (args.padding[1].length !== 2) {
|
124 | throw new ValueError(`ZeroPadding2D expects width padding to be a length-2 array, ` +
|
125 | `but received a length-${args.padding[1].length} array.`);
|
126 | }
|
127 | widthPadding = args.padding[1];
|
128 | }
|
129 | this.padding = [heightPadding, widthPadding];
|
130 | }
|
131 | this.inputSpec = [new InputSpec({ ndim: 4 })];
|
132 | }
|
133 | computeOutputShape(inputShape) {
|
134 | inputShape = getExactlyOneShape(inputShape);
|
135 | let rows;
|
136 | let cols;
|
137 | if (this.dataFormat === 'channelsFirst') {
|
138 | if (inputShape[2] != null && inputShape[2] >= 0) {
|
139 | rows = inputShape[2] + this.padding[0][0] + this.padding[0][1];
|
140 | }
|
141 | else {
|
142 | rows = null;
|
143 | }
|
144 | if (inputShape[3] != null && inputShape[3] >= 0) {
|
145 | cols = inputShape[3] + this.padding[1][0] + this.padding[1][1];
|
146 | }
|
147 | else {
|
148 | cols = null;
|
149 | }
|
150 | return [inputShape[0], inputShape[1], rows, cols];
|
151 | }
|
152 | else {
|
153 | if (inputShape[1] != null && inputShape[1] >= 0) {
|
154 | rows = inputShape[1] + this.padding[0][0] + this.padding[0][1];
|
155 | }
|
156 | else {
|
157 | rows = null;
|
158 | }
|
159 | if (inputShape[2] != null && inputShape[2] >= 0) {
|
160 | cols = inputShape[2] + this.padding[1][0] + this.padding[1][1];
|
161 | }
|
162 | else {
|
163 | cols = null;
|
164 | }
|
165 | return [inputShape[0], rows, cols, inputShape[3]];
|
166 | }
|
167 | }
|
168 | call(inputs, kwargs) {
|
169 | return tidy(() => spatial2dPadding(getExactlyOneTensor(inputs), this.padding, this.dataFormat));
|
170 | }
|
171 | getConfig() {
|
172 | const config = {
|
173 | padding: this.padding,
|
174 | dataFormat: this.dataFormat,
|
175 | };
|
176 | const baseConfig = super.getConfig();
|
177 | Object.assign(config, baseConfig);
|
178 | return config;
|
179 | }
|
180 | }
|
181 | /** @nocollapse */
|
182 | ZeroPadding2D.className = 'ZeroPadding2D';
|
183 | serialization.registerClass(ZeroPadding2D);
|
184 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFkZGluZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3RmanMtbGF5ZXJzL3NyYy9sYXllcnMvcGFkZGluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7R0FRRztBQUVIOztHQUVHO0FBRUgsNkVBQTZFO0FBQzdFLDRFQUE0RTtBQUU1RSxPQUFPLEtBQUssR0FBRyxNQUFNLHVCQUF1QixDQUFDO0FBQzdDLE9BQU8sRUFBQyxhQUFhLEVBQVUsSUFBSSxFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFFbEUsT0FBTyxFQUFDLGVBQWUsRUFBQyxNQUFNLG1CQUFtQixDQUFDO0FBQ2xELE9BQU8sRUFBQyxTQUFTLEVBQUUsS0FBSyxFQUFZLE1BQU0sb0JBQW9CLENBQUM7QUFDL0QsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLFdBQVcsQ0FBQztBQUdyQyxPQUFPLEVBQUMsa0JBQWtCLEVBQUUsbUJBQW1CLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQUU3RTs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxVQUFVLGVBQWUsQ0FBQyxDQUFTLEVBQUUsT0FBMEI7SUFDbkUsT0FBTyxJQUFJLENBQUMsR0FBRyxFQUFFO1FBQ2YsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLENBQUMsRUFBRTtZQUNoQixNQUFNLElBQUksVUFBVSxDQUNoQixpRUFBaUU7Z0JBQ2pFLEdBQUcsQ0FBQyxDQUFDLElBQUksWUFBWSxDQUFDLENBQUM7U0FDNUI7UUFFRCxJQUFJLE9BQU8sSUFBSSxJQUFJLEVBQUU7WUFDbkIsT0FBTyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1NBQ2xCO1FBQ0QsSUFBSSxPQUFPLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUN4QixNQUFNLElBQUksVUFBVSxDQUNoQixpRUFBaUU7Z0JBQ2pFLGdDQUFnQyxPQUFPLENBQUMsTUFBTSxTQUFTLENBQUMsQ0FBQztTQUM5RDtRQUVELE1B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LENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNuRDtJQUNILENBQUM7SUFFUSxJQUFJLENBQUMsTUFBdUIsRUFBRSxNQUFjO1FBQ25ELE9BQU8sSUFBSSxDQUNQLEdBQUcsRUFBRSxDQUFDLGdCQUFnQixDQUNsQixtQkFBbUIsQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQ3ZFLENBQUM7SUFFUSxTQUFTO1FBQ2hCLE1BQU0sTUFBTSxHQUE2QjtZQUN2QyxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87WUFDckIsVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVO1NBQzVCLENBQUM7UUFDRixNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDckMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDbEMsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQzs7QUFyR0Qsa0JBQWtCO0FBQ1gsdUJBQVMsR0FBRyxlQUFlLENBQUM7QUFzR3JDLGFBQWEsQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOCBHb29nbGUgTExDXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlXG4gKiBsaWNlbnNlIHRoYXQgY2FuIGJlIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgb3IgYXRcbiAqIGh0dHBzOi8vb3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvTUlULlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG4vKipcbiAqIFBhZGRpbmcgTGF5ZXJzLlxuICovXG5cbi8vIFBvcnRpbmcgTm90ZTogSW4gUHl0aG9uIEtlcmFzLCB0aGUgcGFkZGluZyBsYXllcnMgYXJlIGluIGNvbnZvbHV0aW9uYWwucHksXG4vLyAgIGJ1dCB3ZSBkZWNpZGVkIHRvIHB1dCB0aGVtIGluIGEgc2VwYXJhdGUgZmlsZSAocGFkZGluZy50cykgZm9yIGNsYXJpdHkuXG5cbmltcG9ydCAqIGFzIHRmYyBmcm9tICdAdGVuc29yZmxvdy90ZmpzLWNvcmUnO1xuaW1wb3J0IHtzZXJpYWxpemF0aW9uLCBUZW5zb3IsIHRpZHl9IGZyb20gJ0B0ZW5zb3JmbG93L3RmanMtY29yZSc7XG5cbmltcG9ydCB7aW1hZ2VEYXRhRm9ybWF0fSBmcm9tICcuLi9iYWNrZW5kL2NvbW1vbic7XG5pbXBvcnQge0lucHV0U3BlYywgTGF5ZXIsIExheWVyQXJnc30gZnJvbSAnLi4vZW5naW5lL3RvcG9sb2d5JztcbmltcG9ydCB7VmFsdWVFcnJvcn0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7RGF0YUZvcm1hdCwgU2hhcGV9IGZyb20gJy4uL2tlcmFzX2Zvcm1hdC9jb21tb24nO1xuaW1wb3J0IHtLd2FyZ3N9IGZyb20gJy4uL3R5cGVzJztcbmltcG9ydCB7Z2V0RXhhY3RseU9uZVNoYXBlLCBnZXRFeGFjdGx5T25lVGVuc29yfSBmcm9tICcuLi91dGlscy90eXBlc191dGlscyc7XG5cbi8qKlxuICogUGFkcyB0aGUgbWlkZGxlIGRpbWVuc2lvbiBvZiBhIDNEIHRlbnNvci5cbiAqXG4gKiBAcGFyYW0geCBJbnB1dCBgdGYuVGVuc29yYCB0byBiZSBwYWRkZWQuXG4gKiBAcGFyYW0gcGFkZGluZyBgQXJyYXlgIG9mIDIgaW50ZWdlcnMsIGhvdyBtYW55IHplcm9zIHRvIGFkZCBhdCB0aGUgc3RhcnQgYW5kXG4gKiAgIGVuZCBvZiB0aGUgbWlkZGxlIGRpbWVuc2lvbiAoaS5lLiwgZGltZW5zaW9uIDEpLlxuICogQHJldHVybiBBIHBhZGRlZCAzRCBgdGYuVGVuc29yYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRlbXBvcmFsUGFkZGluZyh4OiBUZW5zb3IsIHBhZGRpbmc/OiBbbnVtYmVyLCBudW1iZXJdKTogVGVuc29yIHtcbiAgcmV0dXJuIHRpZHkoKCkgPT4ge1xuICAgIGlmICh4LnJhbmsgIT09IDMpIHtcbiAgICAgIHRocm93IG5ldyBWYWx1ZUVycm9yKFxuICAgICAgICAgIGB0ZW1wb3JhbFBhZGRpbmcgZXhwZWN0cyBpbnB1dCB0ZW5zb3IgdG8gYmUgMy1ELCBidXQgcmVjZWl2ZWQgYSBgICtcbiAgICAgICAgICBgJHt4LnJhbmt9LUQgdGVuc29yLmApO1xuICAgIH1cblxuICAgIGlmIChwYWRkaW5nID09IG51bGwpIHtcbiAgICAgIHBhZGRpbmcgPSBbMSwgMV07XG4gICAgfVxuICAgIGlmIChwYWRkaW5nLmxlbmd0aCAhPT0gMikge1xuICAgICAgdGhyb3cgbmV3IFZhbHVlRXJyb3IoXG4gICAgICAgICAgYHRlbXBvcmFsUGFkZGluZyBleHBlY3RzIGlucHV0IHBhZGRpbmcgcGF0dGVybiB0byBiZSBhIGxlbmd0aC0yIGAgK1xuICAgICAgICAgIGBhcnJheSwgYnV0IHJlY2VpdmVkIGEgbGVuZ3RoLSR7cGFkZGluZy5sZW5ndGh9IGFycmF5LmApO1xuICAgIH1cblxuICAgIGNvbnN0IHBhdHRlcm46IEFycmF5PFtudW1iZXIsIG51bWJlcl0+ID0gW1swLCAwXSwgcGFkZGluZywgWzAsIDBdXTtcbiAgICByZXR1cm4gdGZjLnBhZCh4LCBwYXR0ZXJuKTtcbiAgfSk7XG59XG5cbi8qKlxuICogUGFkcyB0aGUgMm5kIGFuZCAzcmQgZGltZW5zaW9ucyBvZiBhIDREIHRlbnNvci5cbiAqXG4gKiBAcGFyYW0geCBJbnB1dCBgdGYuVGVuc29yYCB0byBiZSBwYWRkZWQuXG4gKiBAcGFyYW0gcGFkZGluZyBgQXJyYXlgIG9mIHR3byBgQXJyYXlgcywgZWFjaCBvZiB3aGljaCBpcyBhbiBgQXJyYXlgIG9mIHR3b1xuICogICBpbnRlZ2Vycy4gVGhlIGFtb3VudCBvZiBwYWRkaW5nIGF0IHRoZSBiZWdpbm5pbmcgYW5kIGVuZCBvZiB0aGUgMm5kIGFuZCAzcmRcbiAqICAgZGltZW5zaW9ucywgcmVzcGVjdGl2ZWx5LlxuICogQHBhcmFtIGRhdGFGb3JtYXQgJ2NoYW5uZWxzTGFzdCcgKGRlZmF1bHQpIG9yICdjaGFubmVsc0ZpcnN0Jy5cbiAqIEByZXR1cm4gUGFkZGVkIDREIGB0Zi5UZW5zb3JgLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc3BhdGlhbDJkUGFkZGluZyhcbiAgICB4OiBUZW5zb3IsIHBhZGRpbmc/OiBbW251bWJlciwgbnVtYmVyXSwgW251bWJlciwgbnVtYmVyXV0sXG4gICAgZGF0YUZvcm1hdD86IERhdGFGb3JtYXQpOiBUZW5zb3Ige1xuICByZXR1cm4gdGlkeSgoKSA9PiB7XG4gICAgaWYgKHgucmFuayAhPT0gNCkge1xuICAgICAgdGhyb3cgbmV3IFZhbHVlRXJyb3IoXG4gICAgICAgICAgYHRlbXBvcmFsUGFkZGluZyBleHBlY3RzIGlucHV0IHRlbnNvciB0byBiZSA0LUQsIGJ1dCByZWNlaXZlZCBhIGAgK1xuICAgICAgICAgIGAke3gucmFua30tRCB0ZW5zb3IuYCk7XG4gICAgfVxuXG4gICAgaWYgKHBhZGRpbmcgPT0gbnVsbCkge1xuICAgICAgcGFkZGluZyA9IFtbMSwgMV0sIFsxLCAxXV07XG4gICAgfVxuICAgIGlmIChwYWRkaW5nLmxlbmd0aCAhPT0gMiB8fCBwYWRkaW5nWzBdLmxlbmd0aCAhPT0gMiB8fFxuICAgICAgICBwYWRkaW5nWzFdLmxlbmd0aCAhPT0gMikge1xuICAgICAgdGhyb3cgbmV3IFZhbHVlRXJyb3IoXG4gICAgICAgICAgJ3NwYXRpYWwyZFBhZGRpbmcgZXhwZWN0cyBgcGFkZGluZ2AgdG8gYmUgYW4gQXJyYXkgb2YgdHdvIEFycmF5cywgJyArXG4gICAgICAgICAgJ2VhY2ggb2Ygd2hpY2ggaXMgYW4gQXJyYXkgb2YgdHdvIGludGVnZXJzLicpO1xuICAgIH1cblxuICAgIGlmIChkYXRhRm9ybWF0ID09IG51bGwpIHtcbiAgICAgIGRhdGFGb3JtYXQgPSBpbWFnZURhdGFGb3JtYXQoKTtcbiAgICB9XG4gICAgaWYgKGRhdGFGb3JtYXQgIT09ICdjaGFubmVsc0xhc3QnICYmIGRhdGFGb3JtYXQgIT09ICdjaGFubmVsc0ZpcnN0Jykge1xuICAgICAgdGhyb3cgbmV3IFZhbHVlRXJyb3IoXG4gICAgICAgICAgYFVua25vd24gZGF0YSBmb3JtYXQ6ICR7ZGF0YUZvcm1hdH0uIGAgK1xuICAgICAgICAgIGBTdXBwb3J0ZWQgZGF0YSBmb3JtYXRzIGFyZSAnY2hhbm5lbHNMYXN0JyBhbmQgJ2NoYW5uZWxzRmlyc3QuYCk7XG4gICAgfVxuXG4gICAgbGV0IHBhdHRlcm46IEFycmF5PFtudW1iZXIsIG51bWJlcl0+O1xuICAgIGlmIChkYXRhRm9ybWF0ID09PSAnY2hhbm5lbHNGaXJzdCcpIHtcbiAgICAgIHBhdHRlcm4gPSBbWzAsIDBdLCBbMCwgMF0sIHBhZGRpbmdbMF0sIHBhZGRpbmdbMV1dO1xuICAgIH0gZWxzZSB7XG4gICAgICBwYXR0ZXJuID0gW1swLCAwXSwgcGFkZGluZ1swXSwgcGFkZGluZ1sxXSwgWzAsIDBdXTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGZjLnBhZCh4LCBwYXR0ZXJuKTtcbiAgfSk7XG59XG5cbmV4cG9ydCBkZWNsYXJlIGludGVyZmFjZSBaZXJvUGFkZGluZzJETGF5ZXJBcmdzIGV4dGVuZHMgTGF5ZXJBcmdzIHtcbiAgLyoqXG4gICAqIEludGVnZXIsIG9yIGBBcnJheWAgb2YgMiBpbnRlZ2Vycywgb3IgYEFycmF5YCBvZiAyIGBBcnJheWBzLCBlYWNoIG9mXG4gICAqIHdoaWNoIGlzIGFuIGBBcnJheWAgb2YgMiBpbnRlZ2Vycy5cbiAgICogLSBJZiBpbnRlZ2VyLCB0aGUgc2FtZSBzeW1tZXRyaWMgcGFkZGluZyBpcyBhcHBsaWVkIHRvIHdpZHRoIGFuZCBoZWlnaHQuXG4gICAqIC0gSWYgYEFycmF5YCBvZiAyIGludGVnZXJzLCBpbnRlcnByZXRlZCBhcyB0d28gZGlmZmVyZW50IHN5bW1ldHJpYyB2YWx1ZXNcbiAgICogICBmb3IgaGVpZ2h0IGFuZCB3aWR0aDpcbiAgICogICBgW3N5bW1ldHJpY0hlaWdodFBhZCwgc3ltbWV0cmljV2lkdGhQYWRdYC5cbiAgICogLSBJZiBgQXJyYXlgIG9mIDIgYEFycmF5YHMsIGludGVycHJldGVkIGFzOlxuICAgKiAgIGBbW3RvcFBhZCwgYm90dG9tUGFkXSwgW2xlZnRQYWQsIHJpZ2h0UGFkXV1gLlxuICAgKi9cbiAgcGFkZGluZz86IG51bWJlcnxbbnVtYmVyLCBudW1iZXJdfFtbbnVtYmVyLCBudW1iZXJdLCBbbnVtYmVyLCBudW1iZXJdXTtcblxuICAvKipcbiAgICogT25lIG9mIGAnY2hhbm5lbHNMYXN0J2AgKGRlZmF1bHQpIGFuZCBgJ2NoYW5uZWxzRmlyc3QnYC5cbiAgICpcbiAgICogVGhlIG9yZGVyaW5nIG9mIHRoZSBkaW1lbnNpb25zIGluIHRoZSBpbnB1dHMuXG4gICAqIGBjaGFubmVsc0xhc3RgIGNvcnJlc3BvbmRzIHRvIGlucHV0cyB3aXRoIHNoYXBlXG4gICAqIGBbYmF0Y2gsIGhlaWdodCwgd2lkdGgsIGNoYW5uZWxzXWAgd2hpbGUgYGNoYW5uZWxzRmlyc3RgXG4gICAqIGNvcnJlc3BvbmRzIHRvIGlucHV0cyB3aXRoIHNoYXBlXG4gICAqIGBbYmF0Y2gsIGNoYW5uZWxzLCBoZWlnaHQsIHdpZHRoXWAuXG4gICAqL1xuICBkYXRhRm9ybWF0PzogRGF0YUZvcm1hdDtcbn1cblxuZXhwb3J0IGNsYXNzIFplcm9QYWRkaW5nMkQgZXh0ZW5kcyBMYXllciB7XG4gIC8qKiBAbm9jb2xsYXBzZSAqL1xuICBzdGF0aWMgY2xhc3NOYW1lID0gJ1plcm9QYWRkaW5nMkQnO1xuICByZWFkb25seSBkYXRhRm9ybWF0OiBEYXRhRm9ybWF0O1xuICByZWFkb25seSBwYWRkaW5nOiBbW251bWJlciwgbnVtYmVyXSwgW251bWJlciwgbnVtYmVyXV07XG5cbiAgY29uc3RydWN0b3IoYXJncz86IFplcm9QYWRkaW5nMkRMYXllckFyZ3MpIHtcbiAgICBpZiAoYXJncyA9PSBudWxsKSB7XG4gICAgICBhcmdzID0ge307XG4gICAgfVxuICAgIHN1cGVyKGFyZ3MpO1xuXG4gICAgdGhpcy5kYXRhRm9ybWF0ID1cbiAgICAgICAgYXJncy5kYXRhRm9ybWF0ID09IG51bGwgPyBpbWFnZURhdGFGb3JtYXQoKSA6IGFyZ3MuZGF0YUZvcm1hdDtcbiAgICAvLyBUT0RPKGNhaXMpOiBNYXliZSByZWZhY3RvciB0aGUgZm9sbG93aW5nIGxvZ2ljIHN1cnJvdW5kaW5nIGBwYWRkaW5nYFxuICAgIC8vICAgaW50byBhIGhlbHBlciBtZXRob2QuXG4gICAgaWYgKGFyZ3MucGFkZGluZyA9PSBudWxsKSB7XG4gICAgICB0aGlzLnBhZGRpbmcgPSBbWzEsIDFdLCBbMSwgMV1dO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGFyZ3MucGFkZGluZyA9PT0gJ251bWJlcicpIHtcbiAgICAgIHRoaXMucGFkZGluZyA9XG4gICAgICAgICAgW1thcmdzLnBhZGRpbmcsIGFyZ3MucGFkZGluZ10sIFthcmdzLnBhZGRpbmcsIGFyZ3MucGFkZGluZ11dO1xuICAgIH0gZWxzZSB7XG4gICAgICBhcmdzLnBhZGRpbmcgPSBhcmdzLnBhZGRpbmc7XG4gICAgICBpZiAoYXJncy5wYWRkaW5nLmxlbmd0aCAhPT0gMikge1xuICAgICAgICB0aHJvdyBuZXcgVmFsdWVFcnJvcihcbiAgICAgICAgICAgIGBaZXJvUGFkZGluZzJEIGV4cGVjdHMgcGFkZGluZyB0byBiZSBhIGxlbmd0aC0yIGFycmF5LCBidXQgYCArXG4gICAgICAgICAgICBgcmVjZWl2ZWQgYSBsZW5ndGgtJHthcmdzLnBhZGRpbmcubGVuZ3RofSBhcnJheS5gKTtcbiAgICAgIH1cblxuICAgICAgbGV0IGhlaWdodFBhZGRpbmc6IFtudW1iZXIsIG51bWJlcl07XG4gICAgICBsZXQgd2lkdGhQYWRkaW5nOiBbbnVtYmVyLCBudW1iZXJdO1xuICAgICAgaWYgKHR5cGVvZiBhcmdzLnBhZGRpbmdbMF0gPT09ICdudW1iZXInKSB7XG4gICAgICAgIGhlaWdodFBhZGRpbmcgPSBbYXJncy5wYWRkaW5nWzBdLCBhcmdzLnBhZGRpbmdbMF1dO1xuICAgICAgICB3aWR0aFBhZGRpbmcgPSBbYXJncy5wYWRkaW5nWzFdIGFzIG51bWJlciwgYXJncy5wYWRkaW5nWzFdIGFzIG51bWJlcl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhcmdzLnBhZGRpbmcgPSBhcmdzLnBhZGRpbmcgYXMgW1tudW1iZXIsIG51bWJlcl0sIFtudW1iZXIsIG51bWJlcl1dO1xuXG4gICAgICAgIGlmIChhcmdzLnBhZGRpbmdbMF0ubGVuZ3RoICE9PSAyKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFZhbHVlRXJyb3IoXG4gICAgICAgICAgICAgIGBaZXJvUGFkZGluZzJEIGV4cGVjdHMgaGVpZ2h0IHBhZGRpbmcgdG8gYmUgYSBsZW5ndGgtMiBhcnJheSwgYCArXG4gICAgICAgICAgICAgIGBidXQgcmVjZWl2ZWQgYSBsZW5ndGgtJHthcmdzLnBhZGRpbmdbMF0ubGVuZ3RofSBhcnJheS5gKTtcbiAgICAgICAgfVxuICAgICAgICBoZWlnaHRQYWRkaW5nID0gYXJncy5wYWRkaW5nWzBdIGFzIFtudW1iZXIsIG51bWJlcl07XG5cbiAgICAgICAgaWYgKGFyZ3MucGFkZGluZ1sxXS5sZW5ndGggIT09IDIpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVmFsdWVFcnJvcihcbiAgICAgICAgICAgICAgYFplcm9QYWRkaW5nMkQgZXhwZWN0cyB3aWR0aCBwYWRkaW5nIHRvIGJlIGEgbGVuZ3RoLTIgYXJyYXksIGAgK1xuICAgICAgICAgICAgICBgYnV0IHJlY2VpdmVkIGEgbGVuZ3RoLSR7YXJncy5wYWRkaW5nWzFdLmxlbmd0aH0gYXJyYXkuYCk7XG4gICAgICAgIH1cbiAgICAgICAgd2lkdGhQYWRkaW5nID0gYXJncy5wYWRkaW5nWzFdIGFzIFtudW1iZXIsIG51bWJlcl07XG4gICAgICB9XG4gICAgICB0aGlzLnBhZGRpbmcgPSBbaGVpZ2h0UGFkZGluZywgd2lkdGhQYWRkaW5nXTtcbiAgICB9XG4gICAgdGhpcy5pbnB1dFNwZWMgPSBbbmV3IElucHV0U3BlYyh7bmRpbTogNH0pXTtcbiAgfVxuXG4gIG92ZXJyaWRlIGNvbXB1dGVPdXRwdXRTaGFwZShpbnB1dFNoYXBlOiBTaGFwZXxTaGFwZVtdKTogU2hhcGV8U2hhcGVbXSB7XG4gICAgaW5wdXRTaGFwZSA9IGdldEV4YWN0bHlPbmVTaGFwZShpbnB1dFNoYXBlKTtcblxuICAgIGxldCByb3dzOiBudW1iZXI7XG4gICAgbGV0IGNvbHM6IG51bWJlcjtcbiAgICBpZiAodGhpcy5kYXRhRm9ybWF0ID09PSAnY2hhbm5lbHNGaXJzdCcpIHtcbiAgICAgIGlmIChpbnB1dFNoYXBlWzJdICE9IG51bGwgJiYgaW5wdXRTaGFwZVsyXSA+PSAwKSB7XG4gICAgICAgIHJvd3MgPSBpbnB1dFNoYXBlWzJdICsgdGhpcy5wYWRkaW5nWzBdWzBdICsgdGhpcy5wYWRkaW5nWzBdWzFdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcm93cyA9IG51bGw7XG4gICAgICB9XG4gICAgICBpZiAoaW5wdXRTaGFwZVszXSAhPSBudWxsICYmIGlucHV0U2hhcGVbM10gPj0gMCkge1xuICAgICAgICBjb2xzID0gaW5wdXRTaGFwZVszXSArIHRoaXMucGFkZGluZ1sxXVswXSArIHRoaXMucGFkZGluZ1sxXVsxXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbHMgPSBudWxsO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFtpbnB1dFNoYXBlWzBdLCBpbnB1dFNoYXBlWzFdLCByb3dzLCBjb2xzXTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGlucHV0U2hhcGVbMV0gIT0gbnVsbCAmJiBpbnB1dFNoYXBlWzFdID49IDApIHtcbiAgICAgICAgcm93cyA9IGlucHV0U2hhcGVbMV0gKyB0aGlzLnBhZGRpbmdbMF1bMF0gKyB0aGlzLnBhZGRpbmdbMF1bMV07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByb3dzID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIGlmIChpbnB1dFNoYXBlWzJdICE9IG51bGwgJiYgaW5wdXRTaGFwZVsyXSA+PSAwKSB7XG4gICAgICAgIGNvbHMgPSBpbnB1dFNoYXBlWzJdICsgdGhpcy5wYWRkaW5nWzFdWzBdICsgdGhpcy5wYWRkaW5nWzFdWzFdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29scyA9IG51bGw7XG4gICAgICB9XG4gICAgICByZXR1cm4gW2lucHV0U2hhcGVbMF0sIHJvd3MsIGNvbHMsIGlucHV0U2hhcGVbM11dO1xuICAgIH1cbiAgfVxuXG4gIG92ZXJyaWRlIGNhbGwoaW5wdXRzOiBUZW5zb3J8VGVuc29yW10sIGt3YXJnczogS3dhcmdzKTogVGVuc29yfFRlbnNvcltdIHtcbiAgICByZXR1cm4gdGlkeShcbiAgICAgICAgKCkgPT4gc3BhdGlhbDJkUGFkZGluZyhcbiAgICAgICAgICAgIGdldEV4YWN0bHlPbmVUZW5zb3IoaW5wdXRzKSwgdGhpcy5wYWRkaW5nLCB0aGlzLmRhdGFGb3JtYXQpKTtcbiAgfVxuXG4gIG92ZXJyaWRlIGdldENvbmZpZygpOiBzZXJpYWxpemF0aW9uLkNvbmZpZ0RpY3Qge1xuICAgIGNvbnN0IGNvbmZpZzogc2VyaWFsaXphdGlvbi5Db25maWdEaWN0ID0ge1xuICAgICAgcGFkZGluZzogdGhpcy5wYWRkaW5nLFxuICAgICAgZGF0YUZvcm1hdDogdGhpcy5kYXRhRm9ybWF0LFxuICAgIH07XG4gICAgY29uc3QgYmFzZUNvbmZpZyA9IHN1cGVyLmdldENvbmZpZygpO1xuICAgIE9iamVjdC5hc3NpZ24oY29uZmlnLCBiYXNlQ29uZmlnKTtcbiAgICByZXR1cm4gY29uZmlnO1xuICB9XG59XG5zZXJpYWxpemF0aW9uLnJlZ2lzdGVyQ2xhc3MoWmVyb1BhZGRpbmcyRCk7XG4iXX0= |
\ | No newline at end of file |