tfjs-evolution 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,165 @@
1
+ import * as tf from '@tensorflow/tfjs';
2
+ export class Util {
3
+ /**
4
+ * Receives an image and normalizes it between -1 and 1.
5
+ * Returns a batched image (1 - element batch) of shape [1, w, h, c]
6
+ * @param rasterElement the element with pixels to convert to a Tensor
7
+ * @param grayscale optinal flag that changes the crop to [1, w, h, 1]
8
+ */
9
+ capture(rasterElement, grayscale) {
10
+ return tf.tidy(() => {
11
+ const pixels = tf.browser.fromPixels(rasterElement);
12
+ // // crop the image so we're using the center square
13
+ const cropped = this.cropTensor(pixels, grayscale);
14
+ // // Expand the outer most dimension so we have a batch size of 1
15
+ const batchedImage = cropped.expandDims(0);
16
+ // // Normalize the image between -1 and a1. The image comes in between 0-255
17
+ // // so we divide by 127 and subtract 1.
18
+ return batchedImage.toFloat().div(tf.scalar(127)).sub(tf.scalar(1));
19
+ });
20
+ }
21
+ cropTensor(img, grayscaleModel, grayscaleInput) {
22
+ const size = Math.min(img.shape[0], img.shape[1]);
23
+ const centerHeight = img.shape[0] / 2;
24
+ const beginHeight = centerHeight - (size / 2);
25
+ const centerWidth = img.shape[1] / 2;
26
+ const beginWidth = centerWidth - (size / 2);
27
+ if (grayscaleModel && !grayscaleInput) {
28
+ //cropped rgb data
29
+ let grayscale_cropped = img.slice([beginHeight, beginWidth, 0], [size, size, 3]);
30
+ grayscale_cropped = grayscale_cropped.reshape([size * size, 1, 3]);
31
+ const rgb_weights = [0.2989, 0.5870, 0.1140];
32
+ grayscale_cropped = tf.mul(grayscale_cropped, rgb_weights);
33
+ grayscale_cropped = grayscale_cropped.reshape([size, size, 3]);
34
+ grayscale_cropped = tf.sum(grayscale_cropped, -1);
35
+ grayscale_cropped = tf.expandDims(grayscale_cropped, -1);
36
+ return grayscale_cropped;
37
+ }
38
+ return img.slice([beginHeight, beginWidth, 0], [size, size, 3]);
39
+ }
40
+ /**
41
+ * This function will make a copy of a model on the weight level
42
+ * This is an attempt to avoid influencing the new mode when the old one
43
+ * is eliminated.
44
+ *
45
+ * @param originalModel - the model to be copied
46
+ * @param recipient - the new model
47
+ */
48
+ async copyModel_v3(originalModel, recipient) {
49
+ originalModel.layers.forEach((layer, index) => {
50
+ recipient.layers[index].setWeights(layer.getWeights());
51
+ });
52
+ // originalModel.dispose();
53
+ }
54
+ /**
55
+ * This function will make a copy of a TFJS model, as so it would be possible
56
+ * to erase the original.
57
+ * @param model - model to be copied
58
+ * @returns - copy of the model
59
+ */
60
+ async copyModel_v2(originalModel) {
61
+ // Serialize the original model
62
+ const modelTopology = originalModel.toJSON();
63
+ // Load the serialized model into a new model
64
+ const copiedModel = await tf.loadLayersModel(tf.io.fromMemory(modelTopology, undefined, undefined));
65
+ // Compile the copied model with the same settings as the original
66
+ copiedModel.compile({
67
+ loss: originalModel.loss,
68
+ optimizer: originalModel.optimizer
69
+ });
70
+ return copiedModel;
71
+ }
72
+ /**
73
+ * This function will make a copy of a TFJS model, as so it would be possible
74
+ * to erase the original.
75
+ * @param model - model to be copied
76
+ * @returns - copy of the model
77
+ */
78
+ copyModel(model) {
79
+ const copy = tf.sequential();
80
+ `
81
+ `;
82
+ model.layers.forEach(layer => {
83
+ const aux = layer;
84
+ // layer.dispose();
85
+ copy.add(aux);
86
+ });
87
+ copy.compile({
88
+ loss: model.loss,
89
+ optimizer: model.optimizer
90
+ });
91
+ return copy;
92
+ }
93
+ removeElementByIndex(arr, index) {
94
+ // Check if the index is within bounds
95
+ if (index >= 0 && index < arr.length) {
96
+ // Remove the element at the specified index
97
+ arr.splice(index, 1);
98
+ }
99
+ return arr;
100
+ }
101
+ removeElement(arr, element) {
102
+ // Remove all occurrences of the specified element from the array
103
+ return arr.filter((item) => item !== element);
104
+ }
105
+ clean_array_of_tensors(tensors) {
106
+ tensors.forEach((elem, index) => {
107
+ // if(!index_selection.includes(index))
108
+ elem.dispose();
109
+ });
110
+ }
111
+ getClassNameBySignature(classes, signature) {
112
+ const class_name = classes.find(p => {
113
+ let match = true;
114
+ p.signature?.forEach((elem, index) => {
115
+ if (elem !== signature[index])
116
+ match = false;
117
+ });
118
+ return match;
119
+ });
120
+ return class_name ? class_name.name : "not found";
121
+ }
122
+ identityMatrix(n) {
123
+ return Array.from({ length: n }, (_, i) => Array.from({ length: n }, (_, j) => (i === j ? 1 : 0)));
124
+ }
125
+ indexOfMax(arr) {
126
+ if (arr.length === 0) {
127
+ return -1; // Return -1 for an empty array
128
+ }
129
+ let max = arr[0];
130
+ let maxIndex = 0;
131
+ for (let i = 1; i < arr.length; i++) {
132
+ if (arr[i] > max) {
133
+ maxIndex = i;
134
+ max = arr[i];
135
+ }
136
+ }
137
+ return maxIndex;
138
+ }
139
+ suffle(array1, array2) {
140
+ // Shuffle the order of elements
141
+ for (let i = array1.length - 1; i > 0; i--) {
142
+ const j = Math.floor(Math.random() * (i + 1));
143
+ // Swap elements in both arrays
144
+ [array1[i], array1[j]] = [array1[j], array1[i]];
145
+ [array2[i], array2[j]] = [array2[j], array2[i]];
146
+ }
147
+ }
148
+ sortByValuePreservingIndex(arr1, arr2) {
149
+ // console.log("Vector for organizing: ", arr1)
150
+ // arr2[0].summary()
151
+ // Create an array of objects with value, index from arr1, and original index
152
+ const pairingArray = arr1.map((value, index) => ({
153
+ value,
154
+ index,
155
+ originalIndex: index,
156
+ elementFromArr2: arr2[index], // Preserve the corresponding element from arr2
157
+ }));
158
+ // Sort the pairing array by value (largest to smallest)
159
+ pairingArray.sort((a, b) => b.value - a.value);
160
+ // Extract the sorted elements from arr2 based on the original index
161
+ const sortedElementsFromArr2 = pairingArray.map(pair => pair.elementFromArr2);
162
+ return sortedElementsFromArr2;
163
+ }
164
+ }
165
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RmanMtZXZvbHV0aW9uL3NyYy9saWIvdXRpbHMvdXRpbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEtBQUssRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBR3ZDLE1BQU0sT0FBTyxJQUFJO0lBRWpCOzs7OztPQUtHO0lBQ0gsT0FBTyxDQUFDLGFBQXNFLEVBQUUsU0FBbUI7UUFDL0YsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUNoQixNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUVwRCxxREFBcUQ7WUFDckQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUM7WUFFbkQsa0VBQWtFO1lBQ2xFLE1BQU0sWUFBWSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFFM0MsNkVBQTZFO1lBQzdFLHlDQUF5QztZQUN6QyxPQUFPLFlBQVksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDeEUsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBR0QsVUFBVSxDQUFFLEdBQWdCLEVBQUUsY0FBd0IsRUFBRSxjQUF3QjtRQUM1RSxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xELE1BQU0sWUFBWSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FB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QUFDO1FBSS9DLG9FQUFvRTtRQUNwRSxNQUFNLHNCQUFzQixHQUFHLFlBQVksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7UUFFOUUsT0FBTyxzQkFBc0IsQ0FBQztJQUNsQyxDQUFDO0NBRUoiLCJzb3VyY2VzQ29udGVudCI6WyJcclxuaW1wb3J0IHtDbGFzc30gZnJvbSBcIi4vY2xhc3NcIlxyXG5pbXBvcnQgKiBhcyB0ZiBmcm9tICdAdGVuc29yZmxvdy90ZmpzJztcclxuXHJcblxyXG5leHBvcnQgY2xhc3MgVXRpbCB7XHJcblxyXG4vKipcclxuICogUmVjZWl2ZXMgYW4gaW1hZ2UgYW5kIG5vcm1hbGl6ZXMgaXQgYmV0d2VlbiAtMSBhbmQgMS5cclxuICogUmV0dXJucyBhIGJhdGNoZWQgaW1hZ2UgKDEgLSBlbGVtZW50IGJhdGNoKSBvZiBzaGFwZSBbMSwgdywgaCwgY11cclxuICogQHBhcmFtIHJhc3RlckVsZW1lbnQgdGhlIGVsZW1lbnQgd2l0aCBwaXhlbHMgdG8gY29udmVydCB0byBhIFRlbnNvclxyXG4gKiBAcGFyYW0gZ3JheXNjYWxlIG9wdGluYWwgZmxhZyB0aGF0IGNoYW5nZXMgdGhlIGNyb3AgdG8gWzEsIHcsIGgsIDFdXHJcbiAqL1xyXG5jYXB0dXJlKHJhc3RlckVsZW1lbnQ6IEhUTUxJbWFnZUVsZW1lbnQgfCBIVE1MVmlkZW9FbGVtZW50IHwgSFRNTENhbnZhc0VsZW1lbnQsIGdyYXlzY2FsZT86IGJvb2xlYW4pIHtcclxuICAgIHJldHVybiB0Zi50aWR5KCgpID0+IHtcclxuICAgICAgICBjb25zdCBwaXhlbHMgPSB0Zi5icm93c2VyLmZyb21QaXhlbHMocmFzdGVyRWxlbWVudCk7XHJcblxyXG4gICAgICAgIC8vIC8vIGNyb3AgdGhlIGltYWdlIHNvIHdlJ3JlIHVzaW5nIHRoZSBjZW50ZXIgc3F1YXJlXHJcbiAgICAgICAgY29uc3QgY3JvcHBlZCA9IHRoaXMuY3JvcFRlbnNvcihwaXhlbHMsIGdyYXlzY2FsZSk7XHJcblxyXG4gICAgICAgIC8vIC8vIEV4cGFuZCB0aGUgb3V0ZXIgbW9zdCBkaW1lbnNpb24gc28gd2UgaGF2ZSBhIGJhdGNoIHNpemUgb2YgMVxyXG4gICAgICAgIGNvbnN0IGJhdGNoZWRJbWFnZSA9IGNyb3BwZWQuZXhwYW5kRGltcygwKTtcclxuXHJcbiAgICAgICAgLy8gLy8gTm9ybWFsaXplIHRoZSBpbWFnZSBiZXR3ZWVuIC0xIGFuZCBhMS4gVGhlIGltYWdlIGNvbWVzIGluIGJldHdlZW4gMC0yNTVcclxuICAgICAgICAvLyAvLyBzbyB3ZSBkaXZpZGUgYnkgMTI3IGFuZCBzdWJ0cmFjdCAxLlxyXG4gICAgICAgIHJldHVybiBiYXRjaGVkSW1hZ2UudG9GbG9hdCgpLmRpdih0Zi5zY2FsYXIoMTI3KSkuc3ViKHRmLnNjYWxhcigxKSk7ICAgIFxyXG4gICAgfSk7XHJcbn0gICAgXHJcblxyXG5cclxuY3JvcFRlbnNvciggaW1nOiB0Zi5UZW5zb3IzRCwgZ3JheXNjYWxlTW9kZWw/OiBib29sZWFuLCBncmF5c2NhbGVJbnB1dD86IGJvb2xlYW4gKSA6IHRmLlRlbnNvcjNEIHtcclxuICAgIGNvbnN0IHNpemUgPSBNYXRoLm1pbihpbWcuc2hhcGVbMF0sIGltZy5zaGFwZVsxXSk7XHJcbiAgICBjb25zdCBjZW50ZXJIZWlnaHQgPSBpbWcuc2hhcGVbMF0gLyAyO1xyXG4gICAgY29uc3QgYmVnaW5IZWlnaHQgPSBjZW50ZXJIZWlnaHQgLSAoc2l6ZSAvIDIpO1xyXG4gICAgY29uc3QgY2VudGVyV2lkdGggPSBpbWcuc2hhcGVbMV0gLyAyO1xyXG4gICAgY29uc3QgYmVnaW5XaWR0aCA9IGNlbnRlcldpZHRoIC0gKHNpemUgLyAyKTtcclxuICAgIFxyXG4gICAgaWYgKGdyYXlzY2FsZU1vZGVsICYmICFncmF5c2NhbGVJbnB1dCkge1xyXG4gICAgICAgIC8vY3JvcHBlZCByZ2IgZGF0YVxyXG4gICAgICAgIGxldCBncmF5c2NhbGVfY3JvcHBlZCA9IGltZy5zbGljZShbYmVnaW5IZWlnaHQsIGJlZ2luV2lkdGgsIDBdLCBbc2l6ZSwgc2l6ZSwgM10pO1xyXG4gICAgICAgIFxyXG4gICAgICAgIGdyYXlzY2FsZV9jcm9wcGVkID0gZ3JheXNjYWxlX2Nyb3BwZWQucmVzaGFwZShbc2l6ZSAqIHNpemUsIDEsIDNdKVxyXG4gICAgICAgIGNvbnN0IHJnYl93ZWlnaHRzID0gWzAuMjk4OSwgMC41ODcwLCAwLjExNDBdXHJcbiAgICAgICAgZ3JheXNjYWxlX2Nyb3BwZWQgPSB0Zi5tdWwoZ3JheXNjYWxlX2Nyb3BwZWQsIHJnYl93ZWlnaHRzKVxyXG4gICAgICAgIGdyYXlzY2FsZV9jcm9wcGVkID0gZ3JheXNjYWxlX2Nyb3BwZWQucmVzaGFwZShbc2l6ZSwgc2l6ZSwgM10pO1xyXG4gICAgXHJcbiAgICAgICAgZ3JheXNjYWxlX2Nyb3BwZWQgPSB0Zi5zdW0oZ3JheXNjYWxlX2Nyb3BwZWQsIC0xKVxyXG4gICAgICAgIGdyYXlzY2FsZV9jcm9wcGVkID0gdGYuZXhwYW5kRGltcyhncmF5c2NhbGVfY3JvcHBlZCwgLTEpXHJcblxyXG4gICAgICAgIHJldHVybiBncmF5c2NhbGVfY3JvcHBlZDtcclxuICAgIH1cclxuICAgIHJldHVybiBpbWcuc2xpY2UoW2JlZ2luSGVpZ2h0LCBiZWdpbldpZHRoLCAwXSwgW3NpemUsIHNpemUsIDNdKTtcclxufVxyXG5cclxuXHJcblxyXG5cclxuLyoqXHJcbiAqIFRoaXMgZnVuY3Rpb24gd2lsbCBtYWtlIGEgY29weSBvZiBhIG1vZGVsIG9uIHRoZSB3ZWlnaHQgbGV2ZWxcclxuICogVGhpcyBpcyBhbiBhdHRlbXB0IHRvIGF2b2lkIGluZmx1ZW5jaW5nIHRoZSBuZXcgbW9kZSB3aGVuIHRoZSBvbGQgb25lXHJcbiAqIGlzIGVsaW1pbmF0ZWQuIFxyXG4gKiBcclxuICogQHBhcmFtIG9yaWdpbmFsTW9kZWwgLSB0aGUgbW9kZWwgdG8gYmUgY29waWVkIFxyXG4gKiBAcGFyYW0gcmVjaXBpZW50IC0gdGhlIG5ldyBtb2RlbFxyXG4gKi9cclxuYXN5bmMgY29weU1vZGVsX3YzIChvcmlnaW5hbE1vZGVsOiB0Zi5TZXF1ZW50aWFsLCByZWNpcGllbnQ6IHRmLlNlcXVlbnRpYWwpICB7XHJcblxyXG4gICAgICAgIG9yaWdpbmFsTW9kZWwubGF5ZXJzLmZvckVhY2goKGxheWVyLCBpbmRleCk9PntcclxuICAgICAgICAgICAgcmVjaXBpZW50LmxheWVyc1tpbmRleF0uc2V0V2VpZ2h0cyhsYXllci5nZXRXZWlnaHRzKCkpXHJcbiAgICAgICAgfSlcclxuXHJcbiAgICAvLyBvcmlnaW5hbE1vZGVsLmRpc3Bvc2UoKTtcclxufVxyXG4gICAgXHJcbi8qKlxyXG4gKiBUaGlzIGZ1bmN0aW9uIHdpbGwgbWFrZSBhIGNvcHkgb2YgYSBURkpTIG1vZGVsLCBhcyBzbyBpdCB3b3VsZCBiZSBwb3NzaWJsZSBcclxuICogdG8gZXJhc2UgdGhlIG9yaWdpbmFsLlxyXG4gKiBAcGFyYW0gbW9kZWwgLSBtb2RlbCB0byBiZSBjb3BpZWRcclxuICogQHJldHVybnMgLSBjb3B5IG9mIHRoZSBtb2RlbFxyXG4gKi8gIFxyXG5hc3luYyBjb3B5TW9kZWxfdjIgKG9yaWdpbmFsTW9kZWw6IHRmLlNlcXVlbnRpYWwpICB7XHJcbiAgICAgICAgLy8gU2VyaWFsaXplIHRoZSBvcmlnaW5hbCBtb2RlbFxyXG4gICAgICAgIGNvbnN0IG1vZGVsVG9wb2xvZ3kgPSBvcmlnaW5hbE1vZGVsLnRvSlNPTigpO1xyXG5cclxuICAgICAgICAvLyBMb2FkIHRoZSBzZXJpYWxpemVkIG1vZGVsIGludG8gYSBuZXcgbW9kZWxcclxuICAgICAgICBjb25zdCBjb3BpZWRNb2RlbCA9IGF3YWl0IHRmLmxvYWRMYXllcnNNb2RlbChcclxuICAgICAgICAgICAgdGYuaW8uZnJvbU1lbW9yeShtb2RlbFRvcG9sb2d5LCB1bmRlZmluZWQsIHVuZGVmaW5lZClcclxuICAgICAgICApO1xyXG4gICAgXHJcbiAgICAgICAgLy8gQ29tcGlsZSB0aGUgY29waWVkIG1vZGVsIHdpdGggdGhlIHNhbWUgc2V0dGluZ3MgYXMgdGhlIG9yaWdpbmFsXHJcbiAgICAgICAgY29waWVkTW9kZWwuY29tcGlsZSh7XHJcbiAgICAgICAgICAgIGxvc3M6IG9yaWdpbmFsTW9kZWwubG9zcyxcclxuICAgICAgICAgICAgb3B0aW1pemVyOiBvcmlnaW5hbE1vZGVsLm9wdGltaXplclxyXG4gICAgICAgIH0pO1xyXG4gICAgXHJcbiAgICAgICAgcmV0dXJuIGNvcGllZE1vZGVsO1xyXG59XHJcblxyXG4vKipcclxuICogVGhpcyBmdW5jdGlvbiB3aWxsIG1ha2UgYSBjb3B5IG9mIGEgVEZKUyBtb2RlbCwgYXMgc28gaXQgd291bGQgYmUgcG9zc2libGUgXHJcbiAqIHRvIGVyYXNlIHRoZSBvcmlnaW5hbC5cclxuICogQHBhcmFtIG1vZGVsIC0gbW9kZWwgdG8gYmUgY29waWVkXHJcbiAqIEByZXR1cm5zIC0gY29weSBvZiB0aGUgbW9kZWxcclxuICovICBcclxuY29weU1vZGVsIChtb2RlbDogdGYuU2VxdWVudGlhbCkgIHtcclxuICAgIFxyXG4gICAgICAgIGNvbnN0IGNvcHkgPSB0Zi5zZXF1ZW50aWFsKCk7YFxyXG4gICAgICAgIGBcclxuICAgICAgICBtb2RlbC5sYXllcnMuZm9yRWFjaChsYXllciA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IGF1eCA9bGF5ZXI7XHJcbiAgICAgICAgICAgIC8vIGxheWVyLmRpc3Bvc2UoKTtcclxuICAgICAgICAgICAgY29weS5hZGQoYXV4KTtcclxuICAgICAgICB9KTtcclxuICAgICAgICBjb3B5LmNvbXBpbGUoe1xyXG4gICAgICAgICAgICBsb3NzOiBtb2RlbC5sb3NzLFxyXG4gICAgICAgICAgICBvcHRpbWl6ZXI6IG1vZGVsLm9wdGltaXplclxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHJldHVybiBjb3B5O1xyXG4gICAgfVxyXG5cclxuXHJcbiAgICByZW1vdmVFbGVtZW50QnlJbmRleChhcnI6IGFueSwgaW5kZXg6IG51bWJlcik6IG51bWJlcltdIHtcclxuICAgICAgICAvLyBDaGVjayBpZiB0aGUgaW5kZXggaXMgd2l0aGluIGJvdW5kc1xyXG4gICAgICAgIGlmIChpbmRleCA+PSAwICYmIGluZGV4IDwgYXJyLmxlbmd0aCkge1xyXG4gICAgICAgICAgICAvLyBSZW1vdmUgdGhlIGVsZW1lbnQgYXQgdGhlIHNwZWNpZmllZCBpbmRleFxyXG4gICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTsgICAgICAgICAgICBcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGFycjtcclxuICAgIH1cclxuXHJcbiAgICByZW1vdmVFbGVtZW50KGFycjogYW55LCBlbGVtZW50OiBhbnkpOiBudW1iZXJbXSB7XHJcbiAgICAgICAgLy8gUmVtb3ZlIGFsbCBvY2N1cnJlbmNlcyBvZiB0aGUgc3BlY2lmaWVkIGVsZW1lbnQgZnJvbSB0aGUgYXJyYXlcclxuICAgICAgICByZXR1cm4gYXJyLmZpbHRlcigoaXRlbTogYW55KSA9PiBpdGVtICE9PSBlbGVtZW50KTtcclxuICAgIH1cclxuXHJcbmNsZWFuX2FycmF5X29mX3RlbnNvcnModGVuc29yczogdGYuU2VxdWVudGlhbFtdKSB7XHJcblxyXG4gICAgdGVuc29ycy5mb3JFYWNoKChlbGVtLCBpbmRleCk9PnsgXHJcbiAgICAgICAgLy8gaWYoIWluZGV4X3NlbGVjdGlvbi5pbmNsdWRlcyhpbmRleCkpICBcclxuICAgICAgICAgICAgZWxlbS5kaXNwb3NlKCkgXHJcbiAgICAgICAgfSk7XHJcblxyXG59XHJcblxyXG4gZ2V0Q2xhc3NOYW1lQnlTaWduYXR1cmUoY2xhc3NlczogQ2xhc3NbXSwgc2lnbmF0dXJlOiBudW1iZXJbXSkgeyAgICAgICAgICAgXHJcbiAgICBcclxuICAgICAgICBjb25zdCBjbGFzc19uYW1lID0gY2xhc3Nlcy5maW5kKHAgPT4ge1xyXG4gICAgICAgICAgICBsZXQgbWF0Y2ggPSB0cnVlO1xyXG4gICAgICAgICAgICBwLnNpZ25hdHVyZT8uZm9yRWFjaCAoKGVsZW0saW5kZXgpPT57IFxyXG4gICAgICAgICAgICAgICAgaWYoZWxlbSE9PXNpZ25hdHVyZVtpbmRleF0pXHJcbiAgICAgICAgICAgICAgICAgICAgbWF0Y2g9ZmFsc2U7ICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICB9KVxyXG5cclxuICAgICAgICAgICAgcmV0dXJuIG1hdGNoO1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICByZXR1cm4gY2xhc3NfbmFtZSA/IGNsYXNzX25hbWUubmFtZSA6IFwibm90IGZvdW5kXCI7XHJcbn1cclxuXHJcbmlkZW50aXR5TWF0cml4KG46IG51bWJlcik6IG51bWJlcltdW10ge1xyXG4gICAgICAgIHJldHVybiBBcnJheS5mcm9tKHsgbGVuZ3RoOiBuIH0sIChfLCBpKSA9PiBBcnJheS5mcm9tKHsgbGVuZ3RoOiBuIH0sIChfLCBqKSA9PiAoaSA9PT0gaiA/IDEgOiAwKSkpO1xyXG59ICBcclxuXHJcblxyXG5pbmRleE9mTWF4KGFycjogbnVtYmVyW10pOiBudW1iZXIge1xyXG4gICAgICAgIGlmIChhcnIubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAtMTsgLy8gUmV0dXJuIC0xIGZvciBhbiBlbXB0eSBhcnJheVxyXG4gICAgICAgIH1cclxuICAgIFxyXG4gICAgICAgIGxldCBtYXggPSBhcnJbMF07XHJcbiAgICAgICAgbGV0IG1heEluZGV4ID0gMDtcclxuICAgIFxyXG4gICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGlmIChhcnJbaV0gPiBtYXgpIHtcclxuICAgICAgICAgICAgICAgIG1heEluZGV4ID0gaTtcclxuICAgICAgICAgICAgICAgIG1heCA9IGFycltpXTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIFxyXG4gICAgICAgIHJldHVybiBtYXhJbmRleDtcclxuICAgIH1cclxuXHJcblxyXG5zdWZmbGUoYXJyYXkxOmFueSwgYXJyYXkyOiBhbnkpe1xyXG4gICAgICAgIC8vIFNodWZmbGUgdGhlIG9yZGVyIG9mIGVsZW1lbnRzXHJcbiAgICBmb3IgKGxldCBpID0gYXJyYXkxLmxlbmd0aCAtIDE7IGkgPiAwOyBpLS0pIHtcclxuICAgIGNvbnN0IGogPSBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAoaSArIDEpKTtcclxuXHJcbiAgICAvLyBTd2FwIGVsZW1lbnRzIGluIGJvdGggYXJyYXlzXHJcbiAgICBbYXJyYXkxW2ldLCBhcnJheTFbal1dID0gW2FycmF5MVtqXSwgYXJyYXkxW2ldXTtcclxuICAgIFthcnJheTJbaV0sIGFycmF5MltqXV0gPSBbYXJyYXkyW2pdLCBhcnJheTJbaV1dO1xyXG4gICAgICB9XHJcbiAgICBcclxuICAgIFxyXG4gICAgfVxyXG5cclxuICAgIHNvcnRCeVZhbHVlUHJlc2VydmluZ0luZGV4PFQ+KFxyXG4gICAgICAgIGFycjE6IG51bWJlcltdLFxyXG4gICAgICAgIGFycjI6IGFueVtdXHJcbiAgICApOiBUW10ge1xyXG5cclxuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlZlY3RvciBmb3Igb3JnYW5pemluZzogXCIsIGFycjEpXHJcbiAgICAgICAgLy8gYXJyMlswXS5zdW1tYXJ5KClcclxuXHJcbiAgICAgICAgLy8gQ3JlYXRlIGFuIGFycmF5IG9mIG9iamVjdHMgd2l0aCB2YWx1ZSwgaW5kZXggZnJvbSBhcnIxLCBhbmQgb3JpZ2luYWwgaW5kZXhcclxuICAgICAgICBjb25zdCBwYWlyaW5nQXJyYXkgPSBhcnIxLm1hcCgodmFsdWUsIGluZGV4KSA9PiAoe1xyXG4gICAgICAgICAgICB2YWx1ZSxcclxuICAgICAgICAgICAgaW5kZXgsXHJcbiAgICAgICAgICAgIG9yaWdpbmFsSW5kZXg6IGluZGV4LFxyXG4gICAgICAgICAgICBlbGVtZW50RnJvbUFycjI6IGFycjJbaW5kZXhdLCAvLyBQcmVzZXJ2ZSB0aGUgY29ycmVzcG9uZGluZyBlbGVtZW50IGZyb20gYXJyMlxyXG4gICAgICAgIH0pKTtcclxuICAgIFxyXG4gICAgICAgIC8vIFNvcnQgdGhlIHBhaXJpbmcgYXJyYXkgYnkgdmFsdWUgKGxhcmdlc3QgdG8gc21hbGxlc3QpXHJcbiAgICAgICAgcGFpcmluZ0FycmF5LnNvcnQoKGEsIGIpID0+IGIudmFsdWUgLSBhLnZhbHVlKTtcclxuXHJcbiAgICAgICAgXHJcbiAgICBcclxuICAgICAgICAvLyBFeHRyYWN0IHRoZSBzb3J0ZWQgZWxlbWVudHMgZnJvbSBhcnIyIGJhc2VkIG9uIHRoZSBvcmlnaW5hbCBpbmRleFxyXG4gICAgICAgIGNvbnN0IHNvcnRlZEVsZW1lbnRzRnJvbUFycjIgPSBwYWlyaW5nQXJyYXkubWFwKHBhaXIgPT4gcGFpci5lbGVtZW50RnJvbUFycjIpO1xyXG4gICAgXHJcbiAgICAgICAgcmV0dXJuIHNvcnRlZEVsZW1lbnRzRnJvbUFycjI7XHJcbiAgICB9ICAgIFxyXG4gICAgXHJcbn1cclxuXHJcbiJdfQ==