tfjs-evolution 0.0.9 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -77,9 +77,12 @@ You should see in our HTML file, in Angular, the images
77
77
 
78
78
  I have finished! Hope to publish a paper soon!
79
79
 
80
- <!-- ## Early results -->
81
80
 
82
- <!-- ![alt text](./images/confusion%20matrix.png) -->
81
+ # GitHub repo
82
+
83
+ You can find working examples on: https://github.com/JorgeGuerraPires/transfer-learning-by-evolutionary-computing/tree/master
84
+
85
+ Just clone the repository, NPM install and have fun!
83
86
 
84
87
  # Further help
85
88
 
@@ -32,8 +32,6 @@ export class NeuroEvolution {
32
32
  for (let i = 0; i < this.population_size; i++) {
33
33
  this.population.push({ individual: new TeachableMobileNet() });
34
34
  }
35
- // console.log("Population length: ", this.population.length);
36
- // console.log("Memory after population iniialization: ", tf.memory().numBytes);
37
35
  }
38
36
  async apply_evolution(iteration) {
39
37
  for (let i = 0; i < iteration; i++) {
@@ -196,4 +194,4 @@ export class NeuroEvolution {
196
194
  });
197
195
  }
198
196
  }
199
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV1cm8tZXZvbHV0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGZqcy1ldm9sdXRpb24vc3JjL2xpYi9DbGFzc2VzL25ldXJvLWV2b2x1dGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUMsa0JBQWtCLEVBQUMsTUFBTSwrQkFBK0IsQ0FBQTtBQUNoRSxPQUFPLEtBQUssRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBYXZDLE1BQU0sT0FBZ0IsY0FBYztJQUFwQztRQUVROzs7Ozs7O09BT0Q7UUFFSCxlQUFVLEdBQWUsRUFBRSxDQUFDO1FBQ3BCLHFCQUFnQixHQUFTLEVBQUUsQ0FBQztJQXdSeEMsQ0FBQztJQXRSRyx5QkFBeUI7SUFDekIsSUFBVyxlQUFlLENBQUMsZUFBdUI7UUFDOUMsSUFBSSxDQUFDLGdCQUFnQixHQUFDLGVBQWUsQ0FBQztJQUMxQyxDQUFDO0lBQ0QsSUFBVyxlQUFlO1FBQ3RCLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDO0lBQ2pDLENBQUM7SUFFSDs7T0FFRztJQUVGLEtBQUssQ0FBQyxRQUFRO1FBQ1osT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFDLEVBQUU7WUFDMUMsSUFBSSxDQUFDLFFBQVEsR0FBRSxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDcEQsQ0FBQyxDQUFDLENBQUE7SUFDSixDQUFDO0lBRUMsZ0JBQWdCO1FBRVosS0FBSSxJQUFJLENBQUMsR0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFDLElBQUksQ0FBQyxlQUFlLEVBQUMsQ0FBQyxFQUFFLEVBQUM7WUFDcEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBQyxVQUFVLEVBQUUsSUFBSSxrQkFBa0IsRUFBRSxFQUFDLENBQUMsQ0FBQTtTQUMvRDtRQUNELDhEQUE4RDtRQUM5RCxn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LENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQTtRQUMxRCxDQUFDLENBQUMsQ0FBQTtJQUNOLENBQUM7Q0FFQSIsInNvdXJjZXNDb250ZW50IjpbIlxyXG5pbXBvcnQge1RlYWNoYWJsZU1vYmlsZU5ldH0gZnJvbSBcIi4uL21vZGVscy90ZWFjaGFibGUtZXZvbHV0aW9uXCJcclxuaW1wb3J0ICogYXMgdGYgZnJvbSAnQHRlbnNvcmZsb3cvdGZqcyc7XHJcblxyXG4vKipcclxuICogRWFjaCBpbmRpdmlkdWFsIG9mIHRoZSBwb3B1bGF0aW9uIHdpbGwgYmUgbWFkZSBvZiBcclxuICogYW4gYXJyYXksIGNvcnJlc3BvZGVudCB0byB0aGUgbmV1cmFsIG5ldHdvcmsgd2VpZ2h0cyBhbmRcclxuICogYW4gZXZhbHVhdGlvbiwgaXRzIHJlc3BlY3RpdmUgYWNjdXJhY3kgb24gdGhlIGRhdGFzZXQgZ2l2ZW4uXHJcbiAqIFxyXG4gKi9cclxuaW50ZXJmYWNlIEluZGl2aWR1YWwge1xyXG4gICAgaW5kaXZpZHVhbDogVGVhY2hhYmxlTW9iaWxlTmV0LFxyXG4gICAgYWNjdXJhY3k/OiBudW1iZXJcclxufVxyXG5cclxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIE5ldXJvRXZvbHV0aW9uIHtcclxuXHJcbiAgICAgICAgLyoqICAgICBcclxuICAgIFRoaXMgaXMgdGhlIHBvcHVsYXRpb24uIEkgaGF2ZSBkZWNpZGVkIHRvIGNyZWF0ZSBhIHBvcHVsYXRpb24gb2YganVzdCB3ZWlnaHRzLlxyXG4gICAgSSBoYWQgdG8gY2hhbmdlIG15IG1pbmQuIFdvcmtpbmcgd2l0aCB3ZWlnaHRzIGlzIHRyaWNreS4gXHJcbiAgICBJIGhhdmUgZGVjaWRlZCB0byBzYWNyaWZpY2UgbWVtb3J5IHRvIG1ha2UgbXkgbGlmZSBlYXNpc2VyLlxyXG4gICAgVGVuc29ycyBoYXMgdGhlaXIgaW5uZXIgbWV0aG9kcywgaXQgaGVscHMgb24gdGhlIG9wZXJhdG9ycy5cclxuICAgIEkgaGF2ZSB0byBwYXkgYXR0ZW50aW9uIHRvIG1lbW9yeSBtYW5lZ2VtZW50LlxyXG4gICAgV29ya2luZyB3aXRoIG1lbW9yeSBpbiB0ZW5zb3JzIGlzIHRyaWNreS4gICAgIFxyXG4gICAgICovXHJcblxyXG4gICAgcG9wdWxhdGlvbjogSW5kaXZpZHVhbFtdPVtdO1xyXG4gICAgcHJpdmF0ZSBfcG9wdWxhdGlvbl9zaXplOiBudW1iZXI9MzA7XHJcbiAgICBcclxuICAgIC8qKlNldHRlcnMgYW5kIEdldHRlcnMgKi9cclxuICAgIHB1YmxpYyBzZXQgcG9wdWxhdGlvbl9zaXplKHBvcHVsYXRpb25fc2l6ZTogbnVtYmVyKXtcclxuICAgICAgICB0aGlzLl9wb3B1bGF0aW9uX3NpemU9cG9wdWxhdGlvbl9zaXplO1xyXG4gICAgfVxyXG4gICAgcHVibGljIGdldCBwb3B1bGF0aW9uX3NpemUoKXtcclxuICAgICAgICByZXR1cm4gdGhpcy5fcG9wdWxhdGlvbl9zaXplO1xyXG4gICAgfVxyXG5cclxuICAvKipcclxuICAgKiBNZXRob2RzIHdpdGggaW1wbGVtZW50YXRpb25cclxuICAgKi9cclxuXHJcbiAgIGFzeW5jIGV2YWx1YXRlKCl7XHJcbiAgICAgcmV0dXJuIHRoaXMucG9wdWxhdGlvbi5mb3JFYWNoKGFzeW5jIChlbGVtKT0+e1xyXG4gICAgICAgIGVsZW0uYWNjdXJhY3k9IGF3YWl0IGVsZW0uaW5kaXZpZHVhbC5ldmFsdWF0ZSgpOyAgICAgICAgXHJcbiAgICB9KVxyXG4gIH1cclxuXHJcbiAgICBzdGFydF9wb3B1bGF0aW9uKCl7XHJcblxyXG4gICAgICAgIGZvcihsZXQgaT0wOyBpPHRoaXMucG9wdWxhdGlvbl9zaXplO2krKyl7ICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIHRoaXMucG9wdWxhdGlvbi5wdXNoKHtpbmRpdmlkdWFsOiBuZXcgVGVhY2hhYmxlTW9iaWxlTmV0KCl9KVxyXG4gICAgICAgIH1cclxuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlBvcHVsYXRpb24gbGVuZ3RoOiBcIiwgdGhpcy5wb3B1bGF0aW9uLmxlbmd0aCk7XHJcbiAgICAgICAgLy8gY29uc29sZS5sb2coXCJNZW1vcnkgYWZ0ZXIgcG9wdWxhdGlvbiBpbmlpYWxpemF0aW9uOiBcIiwgdGYubWVtb3J5KCkubnVtQnl0ZXMpO1xyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIGFwcGx5X2V2b2x1dGlvbihpdGVyYXRpb246IG51bWJlcil7XHJcblxyXG4gICAgICAgIGZvcihsZXQgaT0wO2k8aXRlcmF0aW9uO2krKyl7XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIkludGVyYXRpb246IFwiLGkpXHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiTWVtb3J5OiBcIiwgdGYubWVtb3J5KCkubnVtQnl0ZXMpO1xyXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIlRlbnNvcnMgaW4gbWVtb3J5OiBcIiwgdGYubWVtb3J5KCkubnVtVGVuc29ycyk7XHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiUG9wdWxhdGlvbiBsZW5ndGg6IFwiLCB0aGlzLnBvcHVsYXRpb24ubGVuZ3RoKTtcclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5ldm9sdXRpb24oKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgfVxyXG4gXHJcbiAgICAvKipcclxuICAgICAqIFRoaXMgbWV0aG9kIHdpbGwgYXBwbHkgdGhlIGV2b2x1dGlvblxyXG4gICAgICovXHJcbiAgICBhc3luYyBldm9sdXRpb24oKXtcclxuXHJcbiAgICAgICAgXHJcbiAgICAgICAgXHJcbiAgICAgICAgLy9VcGRhdGUgdGhlIGFjY3VyYWN5XHJcbiAgICAgICAgYXdhaXQgdGhpcy5ldmFsdWF0ZSgpO1xyXG5cclxuICAgICAgICBjb25zdCBvZmZzcHJpbmc9W107XHJcblxyXG4gICAgICAgIC8qKkZpcnN0IHN0ZXAgaXMgY3Jvc3NvdmVyLCBmb3IgY3JlYXRpbmcgb2Zmc3ByaW5nICovXHJcbiAgICAgICAgZm9yKGxldCBpPTA7IGk8dGhpcy5wb3B1bGF0aW9uLmxlbmd0aDtpKyspXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIC8vVGhlIHBvcHVsYXRpb24gd2lsbCBkb3VibGUgaW4gc2l6ZVxyXG4gICAgICAgICAgICAgICAgb2Zmc3ByaW5nLnB1c2godGhpcy5jcm9zc292ZXIoKSk7IFxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgLy9NdXRhdGlvbiBvbiB0aGUgb2Zmc3ByaW5nXHJcbiAgICAvLyAgICBjb25zb2xlLmxvZyhcIldlaWdodCBiZWZvcmUgbXV0YXRpb246IFwiLCBvZmZzcHJpbmdbMF0uaW5kaXZpZHVhbC5nZXRIZWFkKCkubGF5ZXJzWzBdLmdldFdlaWdodHMoKVswXS5kYXRhU3luYygpKTtcclxuXHJcbiAgICAgICB0aGlzLm11dGF0aW9uKG9mZnNwcmluZykgICBcclxuXHJcbiAgICAgICAgLy9Kb2luaW5nIHBhcmVudHMgYW5kIG9mZnNwcmluZyBpbnRvIHRoZSBzYW1lIHBvb2wgZm9yIHNlbGVjdGlvblxyXG4gICAgICAgIHRoaXMucG9wdWxhdGlvbj1bLi4udGhpcy5wb3B1bGF0aW9uLCAuLi5vZmZzcHJpbmddO1xyXG5cclxuICAgICAgICAvL1VwZGF0ZSB0aGUgYWNjdXJhY3lcclxuICAgICAgICAgYXdhaXQgdGhpcy5ldmFsdWF0ZSgpO1xyXG5cclxuXHJcbiAgICAgICAgIC8vc2VsZWN0aW9uXHJcbiAgICAgICAgIHRoaXMuc2VsZWN0aW9uKCk7XHJcbiAgICAgICAgY29uc29sZS5sb2coXCJCZXN0IGFjY3VyYWN5OiBcIiwgdGhpcy5nZXRUaGVCZXN0KCkuYWNjdXJhY3kpXHJcbiAgICAgICAgY29uc29sZS5sb2coXCJXb3JzdCBhY2N1cmFjeTogXCIsIHRoaXMuZ2V0VGhlV29yc3QoKS5hY2N1cmFjeSkgICAgICAgIFxyXG5cclxuICAgIH1cclxuXHJcbiAgICAvKipBYnN0cmFjdCBtZXRob2RzLlxyXG4gICAgICogU2hvdWxkIGJlIGltcGxlbWVudGVkIGJ5IGVhY2ggdmFyaWF0aW9uIG9mIGV2b2x1dGlvbmFyeSBhbGdvcml0aG1zXHJcbiAgICAgKi9cclxuXHJcbiAgICBhYnN0cmFjdCBjcm9zc292ZXIoKTogSW5kaXZpZHVhbDtcclxuICAgIGFic3RyYWN0IG11dGF0aW9uKG9mZnNwcmluZzogSW5kaXZpZHVhbFtdKTogdm9pZDtcclxuICAgIGFic3RyYWN0IHNlbGVjdGlvbigpOiB2b2lkO1xyXG5cclxuXHJcbiAgICAvKipIZWxwZXJzICovXHJcblxyXG4gICAgZ2V0VGhlQmVzdCgpOiBJbmRpdmlkdWFse1xyXG4gICAgICAgIGxldCBpbmRleF9iZXN0OiBudW1iZXI9MDtcclxuICAgICAgICBsZXQgYmVzdD0wO1xyXG5cclxuICAgICAgICB0aGlzLnBvcHVsYXRpb24uZm9yRWFjaCgoZWxlbTogYW55LCBpbmRleDogbnVtYmVyKT0+e1xyXG5cclxuICAgICAgICAgICAgaWYoZWxlbS5hY2N1cmFjeT5iZXN0KXtcclxuICAgICAgICAgICAgICAgIGJlc3Q9ZWxlbS5hY2N1cmFjeTtcclxuICAgICAgICAgICAgICAgIGluZGV4X2Jlc3Q9aW5kZXhcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgfSlcclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXMucG9wdWxhdGlvbltpbmRleF9iZXN0XTtcclxuICAgIH1cclxuXHJcblxyXG4gICAgZ2V0VGhlV29yc3QoKTogSW5kaXZpZHVhbHtcclxuICAgICAgICBsZXQgaW5kZXhfd29yc3Q6IG51bWJlcj0wO1xyXG4gICAgICAgIGxldCB3b3JzdD0xO1xyXG5cclxuICAgICAgICB0aGlzLnBvcHVsYXRpb24uZm9yRWFjaCgoZWxlbTogYW55LCBpbmRleDogbnVtYmVyKT0+e1xyXG5cclxuICAgICAgICAgICAgaWYoZWxlbS5hY2N1cmFjeTx3b3JzdCl7XHJcbiAgICAgICAgICAgICAgICB3b3JzdD1lbGVtLmFjY3VyYWN5O1xyXG4gICAgICAgICAgICAgICAgaW5kZXhfd29yc3Q9aW5kZXhcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgfSlcclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXMucG9wdWxhdGlvbltpbmRleF93b3JzdF07XHJcbiAgICB9XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICogU2VsZWN0aW5nIGluZGl2aWR1YWxzIGJ5IGVsaXRpc21cclxuICAgICAqL1xyXG4gICAgc2VsZWN0X3BhcmVudHNfYnlfcm9sbGV0X3doZWVsc192MihzZWxlY3Rpb25fbnVtYmVyPTIpOiBJbmRpdmlkdWFsW117XHJcblxyXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlNlbGVjdGluZyBwYXJlbnRzIGJ5IHJvbGxldCB3aGVlbHMuLi5cIik7XHJcbiAgICBcclxuICAgICAgICAgICAgY29uc3Qgc2hhcmU6IGFueT1bXTtcclxuICAgIFxyXG4gICAgICAgICAgICBsZXQgdG90YWw6IGFueT0wO1xyXG4gICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlBvcHVsYXRpb24gbGVuZ3RoLi4uXCIsIHRoaXMucG9wdWxhdGlvbi5sZW5ndGgpO1xyXG4gICAgXHJcbiAgICAgICAgICAgIC8vVGhpcyB3aWxsIGNyZWF0ZSBhbiBvdmVyYWxsIGFjY3VyYWN5XHJcbiAgICAgICAgICAgIHRoaXMucG9wdWxhdGlvbi5mb3JFYWNoKChlbGVtKT0+dG90YWwrPWVsZW0uYWNjdXJhY3kpO1xyXG4gICAgXHJcbiAgICAgICAgICAgIGxldCBwb2ludGVyPTA7XHJcbiAgICBcclxuICAgICAgICAgICAgdGhpcy5wb3B1bGF0aW9uLmZvckVhY2goKGVsZW06YW55LCBpbmRleCk9PntcclxuICAgIFxyXG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJBY2N1cmFjeS4uLlwiLCBlbGVtLmFjY3VyYWN5KTtcclxuICAgIFxyXG4gICAgICAgICAgICAgICAgc2hhcmUucHVzaChcclxuICAgICAgICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICAgICAgICBpbmRleDogaW5kZXgsXHJcbiAgICAgICAgICAgICAgICAgICAgICBzaGFyZTogIGVsZW0uYWNjdXJhY3kvdG90YWwsXHJcbiAgICAgICAgICAgICAgICAgICAgICBtaW46IHBvaW50ZXIsXHJcbiAgICAgICAgICAgICAgICAgICAgICBtYXg6IHBvaW50ZXIgKyAoZWxlbS5hY2N1cmFjeS90b3RhbClcclxuICAgICAgICAgICAgICAgICAgfSlcclxuICAgIFxyXG4gICAgICAgICAgICAgICAgICBwb2ludGVyKz1lbGVtLmFjY3VyYWN5L3RvdGFsO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgIFxyXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlNoYXJlczogXCIsIHNoYXJlKTtcclxuICAgIFxyXG4gICAgICAgICAgICBjb25zdCBhdXhfc2VsZWN0aW9uOiBhbnkgPVtdO1xyXG4gICAgXHJcbiAgICAgICAgICAgICAgLy9TZWxlY3RpbmcgdHdvIGluZGl2aWR1YWxzIHVzaW5nIHJvdWxldHRlIHdoZWVsc1xyXG4gICAgICAgICAgICBsZXQgY291bnRlcj0wO1xyXG5cclxuICAgICAgICAgICAgY29uc3QgaW5kZXhlc19hdXg6IG51bWJlcltdPVtdO1xyXG5cclxuICAgICAgICAgICAgd2hpbGUoY291bnRlcjxzZWxlY3Rpb25fbnVtYmVyKXtcclxuICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgLy9SYW5kb20gcG9pbnRlciwgdXNlZCB0byByYW5kb21seSBzZWxlY3QgYW4gaW5kaXZpZHVhbFxyXG4gICAgICAgICAgICAgICAgY29uc3QgYXV4X2luZGV4PSBNYXRoLnJhbmRvbSgpO1xyXG4gICAgXHJcbiAgICAgICAgICAgICAgICBzaGFyZS5mb3JFYWNoKChlbGVtOiBhbnkpPT57XHJcbiAgICBcclxuICAgICAgICAgICAgICAgICAgICBpZigoZWxlbS5taW48YXV4X2luZGV4KSYmKGVsZW0ubWF4PmF1eF9pbmRleCkpe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYXV4OiBJbmRpdmlkdWFsID0ge2luZGl2aWR1YWw6IG5ldyBUZWFjaGFibGVNb2JpbGVOZXQoKSwgYWNjdXJhY3k6IHRoaXMucG9wdWxhdGlvbltlbGVtLmluZGV4XS5hY2N1cmFjeSB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkluZGl2aWR1YWwganVzdCBjcmVhdGVkICh3ZWlndGgpOiBcIiwgYXV4LmluZGl2aWR1YWwuZ2V0SGVhZCgpLmxheWVyc1swXS5nZXRXZWlnaHRzKClbMF0uZGF0YVN5bmMoKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkluZGl2aWR1YWwgb3JpZ2luYWw6IFwiLCB0aGlzLnBvcHVsYXRpb25bZWxlbS5pbmRleF0uaW5kaXZpZHVhbC5nZXRIZWFkKCkubGF5ZXJzWzBdLmdldFdlaWdodHMoKVswXS5kYXRhU3luYygpKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgICAgICAgICAgICAvLyBPcmlnaW5hbCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSZWNpcGllbnRcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhpcy5jb3B5TW9kZWwodGhpcy5wb3B1bGF0aW9uW2VsZW0uaW5kZXhdLmluZGl2aWR1YWwuZ2V0SGVhZCgpLGF1eC5pbmRpdmlkdWFsLmdldEhlYWQoKSlcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoaXMucG9wdWxhdGlvbltlbGVtLmluZGV4XS5pbmRpdmlkdWFsLmdldEhlYWQoKS5kaXNwb3NlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkluZGl2aWR1YWwganVzdCBjcmVhdGVkICh3ZWlndGh0LCBjb3BpZWQpOiBcIiwgYXV4LmluZGl2aWR1YWwuZ2V0SGVhZCgpLmxheWVyc1swXS5nZXRXZWlnaHRzKClbMF0uZGF0YVN5bmMoKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyKys7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGF1eF9zZWxlY3Rpb24ucHVzaCh0aGlzLnBvcHVsYXRpb25bZWxlbS5pbmRleF0pO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5kZXhlc19hdXgucHVzaChlbGVtLmluZGV4KVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIHRoaXMucG9wdWxhdGlvbi5mb3JFYWNoKChlbGVtLCBpbmRleCk9PntcclxuICAgICAgICAgICAgLy8gICAgIGlmKCFpbmRleGVzX2F1eC5pbmNsdWRlcyhpbmRleCkpe1xyXG4gICAgICAgICAgICAvLyAgICAgICAgIGNvbnNvbGUubG9nKFwiRGlzcG9zZWQuLi5cIilcclxuICAgICAgICAgICAgLy8gICAgICAgICBlbGVtLmluZGl2aWR1YWwuZ2V0SGVhZCgpLmRpc3Bvc2UoKTtcclxuICAgICAgICAgICAgLy8gICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgLy8gfSlcclxuXHJcbiAgICAgICAgICAgIC8vIHRoaXMucG9wdWxhdGlvbj1bXTtcclxuXHJcbiAgICAgICAgICAgIHJldHVybiBhdXhfc2VsZWN0aW9uO1xyXG4gICAgICAgIH1cclxuICAgIFxyXG4gICAgLyoqXHJcbiAgICAgKiBTZWxlY3RpbmcgaW5kaXZpZHVhbHMgYnkgZWxpdGlzbVxyXG4gICAgICovXHJcbiAgICBzZWxlY3RfcGFyZW50c19ieV9yb2xsZXRfd2hlZWxzKHNlbGVjdGlvbl9udW1iZXI9Mik6IEluZGl2aWR1YWxbXXtcclxuXHJcbiAgICAgICAgLy8gY29uc29sZS5sb2dcclxuICAgICAgICAvLyAoXCJTZWxlY3RpbmcgcGFyZW50cyBieSByb2xsZXQgd2hlZWxzLi4uXCIpO1xyXG5cclxuICAgICAgICBjb25zdCBzaGFyZTogYW55PVtdO1xyXG5cclxuICAgICAgICBsZXQgdG90YWw6IGFueT0wO1xyXG4gICAgICAgICAgXHJcbiAgICAgICAgLy8gY29uc29sZS5sb2coXCJQb3B1bGF0aW9uIGxlbmd0aC4uLlwiLCB0aGlzLnBvcHVsYXRpb24ubGVuZ3RoKTtcclxuXHJcbiAgICAgICAgLy9UaGlzIHdpbGwgY3JlYXRlIGFuIG92ZXJhbGwgYWNjdXJhY3lcclxuICAgICAgICB0aGlzLnBvcHVsYXRpb24uZm9yRWFjaCgoZWxlbSk9PnRvdGFsKz1lbGVtLmFjY3VyYWN5KTtcclxuXHJcbiAgICAgICAgbGV0IHBvaW50ZXI9MDtcclxuXHJcbiAgICAgICAgdGhpcy5wb3B1bGF0aW9uLmZvckVhY2goKGVsZW06YW55LCBpbmRleCk9PntcclxuXHJcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwiQWNjdXJhY3kuLi5cIiwgZWxlbS5hY2N1cmFjeSk7XHJcblxyXG4gICAgICAgICAgICBzaGFyZS5wdXNoKFxyXG4gICAgICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgICBpbmRleDogaW5kZXgsXHJcbiAgICAgICAgICAgICAgICAgIHNoYXJlOiAgZWxlbS5hY2N1cmFjeS90b3RhbCxcclxuICAgICAgICAgICAgICAgICAgbWluOiBwb2ludGVyLFxyXG4gICAgICAgICAgICAgICAgICBtYXg6IHBvaW50ZXIgKyAoZWxlbS5hY2N1cmFjeS90b3RhbClcclxuICAgICAgICAgICAgICB9KVxyXG5cclxuICAgICAgICAgICAgICBwb2ludGVyKz1lbGVtLmFjY3VyYWN5L3RvdGFsO1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlNoYXJlczogXCIsIHNoYXJlKTtcclxuXHJcbiAgICAgICAgY29uc3QgYXV4X3NlbGVjdGlvbjogYW55ID1bXTtcclxuXHJcbiAgICAgICAgICAvL1NlbGVjdGluZyB0d28gaW5kaXZpZHVhbHMgdXNpbmcgcm91bGV0dGUgd2hlZWxzXHJcbiAgICAgICAgbGV0IGNvdW50ZXI9MDtcclxuICAgICAgICB3aGlsZShjb3VudGVyPHNlbGVjdGlvbl9udW1iZXIpe1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgLy9SYW5kb20gcG9pbnRlciwgdXNlZCB0byByYW5kb21seSBzZWxlY3QgYW4gaW5kaXZpZHVhbFxyXG4gICAgICAgICAgICBjb25zdCBhdXhfaW5kZXg9IE1hdGgucmFuZG9tKCk7XHJcblxyXG4gICAgICAgICAgICBzaGFyZS5mb3JFYWNoKChlbGVtOiBhbnkpPT57XHJcblxyXG4gICAgICAgICAgICAgICAgaWYoKGVsZW0ubWluPGF1eF9pbmRleCkmJihlbGVtLm1heD5hdXhfaW5kZXgpKXtcclxuICAgICAgICAgICAgICAgICAgICBjb3VudGVyKys7XHJcbiAgICAgICAgICAgICAgICAgICAgYXV4X3NlbGVjdGlvbi5wdXNoKHRoaXMucG9wdWxhdGlvbltlbGVtLmluZGV4XSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBhdXhfc2VsZWN0aW9uO1xyXG4gICAgfVxyXG5cclxuLyoqXHJcbiAqIFRoaXMgZnVuY3Rpb24gd2lsbCBtYWtlIGEgY29weSBvZiBhIG1vZGVsIG9uIHRoZSB3ZWlnaHQgbGV2ZWxcclxuICogVGhpcyBpcyBhbiBhdHRlbXB0IHRvIGF2b2lkIGluZmx1ZW5jaW5nIHRoZSBuZXcgbW9kZWwgd2hlbiB0aGUgb2xkIG9uZVxyXG4gKiBpcyBlbGltaW5hdGVkLiBcclxuICogXHJcbiAqIEBwYXJhbSBvcmlnaW5hbE1vZGVsIC0gdGhlIG1vZGVsIHRvIGJlIGNvcGllZCBcclxuICogQHBhcmFtIHJlY2lwaWVudCAtIHRoZSBuZXcgbW9kZWxcclxuICovXHJcbmFzeW5jIGNvcHlNb2RlbCAob3JpZ2luYWxNb2RlbDogdGYuTGF5ZXJzTW9kZWwsIHJlY2lwaWVudDogdGYuTGF5ZXJzTW9kZWwpICB7XHJcblxyXG4gICAgb3JpZ2luYWxNb2RlbC5sYXllcnMuZm9yRWFjaCgobGF5ZXI6IGFueSwgaW5kZXg6IGFueSk9PntcclxuICAgICAgICByZWNpcGllbnQubGF5ZXJzW2luZGV4XS5zZXRXZWlnaHRzKGxheWVyLmdldFdlaWdodHMoKSlcclxuICAgIH0pXHJcbn0gICAgXHJcblxyXG59XHJcbiJdfQ==
197
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV1cm8tZXZvbHV0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGZqcy1ldm9sdXRpb24vc3JjL2xpYi9DbGFzc2VzL25ldXJvLWV2b2x1dGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUMsa0JBQWtCLEVBQUMsTUFBTSwrQkFBK0IsQ0FBQTtBQUNoRSxPQUFPLEtBQUssRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBYXZDLE1BQU0sT0FBZ0IsY0FBYztJQUFwQztRQUVROzs7Ozs7O09BT0Q7UUFFSCxlQUFVLEdBQWUsRUFBRSxDQUFDO1FBQ3BCLHFCQUFnQixHQUFTLEVBQUUsQ0FBQztJQXVSeEMsQ0FBQztJQXJSRyx5QkFBeUI7SUFDekIsSUFBVyxlQUFlLENBQUMsZUFBdUI7UUFDOUMsSUFBSSxDQUFDLGdCQUFnQixHQUFDLGVBQWUsQ0FBQztJQUMxQyxDQUFDO0lBQ0QsSUFBVyxlQUFlO1FBQ3RCLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDO0lBQ2pDLENBQUM7SUFFSDs7T0FFRztJQUVGLEtBQUssQ0FBQyxRQUFRO1FBQ1osT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFDLEVBQUU7WUFDMUMsSUFBSSxDQUFDLFFBQVEsR0FBRSxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDcEQsQ0FBQyxDQUFDLENBQUE7SUFDSixDQUFDO0lBRUMsZ0JBQWdCO1FBRVosS0FBSSxJQUFJLENBQUMsR0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFDLElBQUksQ0FBQyxlQUFlLEVBQUMsQ0FBQyxFQUFFLEVBQUM7WUFDcEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBQyxVQUFVLEVBQUUsSUFBSSxrQkFBa0IsRUFBRSxFQUFDLENBQUMsQ0FBQTtTQUMvRDtJQUVMLENBQUM7SUFFRCxLQUFL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UUFDMUQsQ0FBQyxDQUFDLENBQUE7SUFDTixDQUFDO0NBRUEiLCJzb3VyY2VzQ29udGVudCI6WyJcclxuaW1wb3J0IHtUZWFjaGFibGVNb2JpbGVOZXR9IGZyb20gXCIuLi9tb2RlbHMvdGVhY2hhYmxlLWV2b2x1dGlvblwiXHJcbmltcG9ydCAqIGFzIHRmIGZyb20gJ0B0ZW5zb3JmbG93L3RmanMnO1xyXG5cclxuLyoqXHJcbiAqIEVhY2ggaW5kaXZpZHVhbCBvZiB0aGUgcG9wdWxhdGlvbiB3aWxsIGJlIG1hZGUgb2YgXHJcbiAqIGFuIGFycmF5LCBjb3JyZXNwb2RlbnQgdG8gdGhlIG5ldXJhbCBuZXR3b3JrIHdlaWdodHMgYW5kXHJcbiAqIGFuIGV2YWx1YXRpb24sIGl0cyByZXNwZWN0aXZlIGFjY3VyYWN5IG9uIHRoZSBkYXRhc2V0IGdpdmVuLlxyXG4gKiBcclxuICovXHJcbmludGVyZmFjZSBJbmRpdmlkdWFsIHtcclxuICAgIGluZGl2aWR1YWw6IFRlYWNoYWJsZU1vYmlsZU5ldCxcclxuICAgIGFjY3VyYWN5PzogbnVtYmVyXHJcbn1cclxuXHJcbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBOZXVyb0V2b2x1dGlvbiB7XHJcblxyXG4gICAgICAgIC8qKiAgICAgXHJcbiAgICBUaGlzIGlzIHRoZSBwb3B1bGF0aW9uLiBJIGhhdmUgZGVjaWRlZCB0byBjcmVhdGUgYSBwb3B1bGF0aW9uIG9mIGp1c3Qgd2VpZ2h0cy5cclxuICAgIEkgaGFkIHRvIGNoYW5nZSBteSBtaW5kLiBXb3JraW5nIHdpdGggd2VpZ2h0cyBpcyB0cmlja3kuIFxyXG4gICAgSSBoYXZlIGRlY2lkZWQgdG8gc2FjcmlmaWNlIG1lbW9yeSB0byBtYWtlIG15IGxpZmUgZWFzaXNlci5cclxuICAgIFRlbnNvcnMgaGFzIHRoZWlyIGlubmVyIG1ldGhvZHMsIGl0IGhlbHBzIG9uIHRoZSBvcGVyYXRvcnMuXHJcbiAgICBJIGhhdmUgdG8gcGF5IGF0dGVudGlvbiB0byBtZW1vcnkgbWFuZWdlbWVudC5cclxuICAgIFdvcmtpbmcgd2l0aCBtZW1vcnkgaW4gdGVuc29ycyBpcyB0cmlja3kuICAgICBcclxuICAgICAqL1xyXG5cclxuICAgIHBvcHVsYXRpb246IEluZGl2aWR1YWxbXT1bXTtcclxuICAgIHByaXZhdGUgX3BvcHVsYXRpb25fc2l6ZTogbnVtYmVyPTMwO1xyXG4gICAgXHJcbiAgICAvKipTZXR0ZXJzIGFuZCBHZXR0ZXJzICovXHJcbiAgICBwdWJsaWMgc2V0IHBvcHVsYXRpb25fc2l6ZShwb3B1bGF0aW9uX3NpemU6IG51bWJlcil7XHJcbiAgICAgICAgdGhpcy5fcG9wdWxhdGlvbl9zaXplPXBvcHVsYXRpb25fc2l6ZTtcclxuICAgIH1cclxuICAgIHB1YmxpYyBnZXQgcG9wdWxhdGlvbl9zaXplKCl7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3BvcHVsYXRpb25fc2l6ZTtcclxuICAgIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTWV0aG9kcyB3aXRoIGltcGxlbWVudGF0aW9uXHJcbiAgICovXHJcblxyXG4gICBhc3luYyBldmFsdWF0ZSgpe1xyXG4gICAgIHJldHVybiB0aGlzLnBvcHVsYXRpb24uZm9yRWFjaChhc3luYyAoZWxlbSk9PntcclxuICAgICAgICBlbGVtLmFjY3VyYWN5PSBhd2FpdCBlbGVtLmluZGl2aWR1YWwuZXZhbHVhdGUoKTsgICAgICAgIFxyXG4gICAgfSlcclxuICB9XHJcblxyXG4gICAgc3RhcnRfcG9wdWxhdGlvbigpe1xyXG5cclxuICAgICAgICBmb3IobGV0IGk9MDsgaTx0aGlzLnBvcHVsYXRpb25fc2l6ZTtpKyspeyAgICAgICAgICAgIFxyXG4gICAgICAgICAgICB0aGlzLnBvcHVsYXRpb24ucHVzaCh7aW5kaXZpZHVhbDogbmV3IFRlYWNoYWJsZU1vYmlsZU5ldCgpfSlcclxuICAgICAgICB9XHJcblxyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIGFwcGx5X2V2b2x1dGlvbihpdGVyYXRpb246IG51bWJlcil7XHJcblxyXG4gICAgICAgIGZvcihsZXQgaT0wO2k8aXRlcmF0aW9uO2krKyl7XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIkludGVyYXRpb246IFwiLGkpXHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiTWVtb3J5OiBcIiwgdGYubWVtb3J5KCkubnVtQnl0ZXMpO1xyXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIlRlbnNvcnMgaW4gbWVtb3J5OiBcIiwgdGYubWVtb3J5KCkubnVtVGVuc29ycyk7XHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiUG9wdWxhdGlvbiBsZW5ndGg6IFwiLCB0aGlzLnBvcHVsYXRpb24ubGVuZ3RoKTtcclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5ldm9sdXRpb24oKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgfVxyXG4gXHJcbiAgICAvKipcclxuICAgICAqIFRoaXMgbWV0aG9kIHdpbGwgYXBwbHkgdGhlIGV2b2x1dGlvblxyXG4gICAgICovXHJcbiAgICBhc3luYyBldm9sdXRpb24oKXtcclxuXHJcbiAgICAgICAgXHJcbiAgICAgICAgXHJcbiAgICAgICAgLy9VcGRhdGUgdGhlIGFjY3VyYWN5XHJcbiAgICAgICAgYXdhaXQgdGhpcy5ldmFsdWF0ZSgpO1xyXG5cclxuICAgICAgICBjb25zdCBvZmZzcHJpbmc9W107XHJcblxyXG4gICAgICAgIC8qKkZpcnN0IHN0ZXAgaXMgY3Jvc3NvdmVyLCBmb3IgY3JlYXRpbmcgb2Zmc3ByaW5nICovXHJcbiAgICAgICAgZm9yKGxldCBpPTA7IGk8dGhpcy5wb3B1bGF0aW9uLmxlbmd0aDtpKyspXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIC8vVGhlIHBvcHVsYXRpb24gd2lsbCBkb3VibGUgaW4gc2l6ZVxyXG4gICAgICAgICAgICAgICAgb2Zmc3ByaW5nLnB1c2godGhpcy5jcm9zc292ZXIoKSk7IFxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgLy9NdXRhdGlvbiBvbiB0aGUgb2Zmc3ByaW5nXHJcbiAgICAvLyAgICBjb25zb2xlLmxvZyhcIldlaWdodCBiZWZvcmUgbXV0YXRpb246IFwiLCBvZmZzcHJpbmdbMF0uaW5kaXZpZHVhbC5nZXRIZWFkKCkubGF5ZXJzWzBdLmdldFdlaWdodHMoKVswXS5kYXRhU3luYygpKTtcclxuXHJcbiAgICAgICB0aGlzLm11dGF0aW9uKG9mZnNwcmluZykgICBcclxuXHJcbiAgICAgICAgLy9Kb2luaW5nIHBhcmVudHMgYW5kIG9mZnNwcmluZyBpbnRvIHRoZSBzYW1lIHBvb2wgZm9yIHNlbGVjdGlvblxyXG4gICAgICAgIHRoaXMucG9wdWxhdGlvbj1bLi4udGhpcy5wb3B1bGF0aW9uLCAuLi5vZmZzcHJpbmddO1xyXG5cclxuICAgICAgICAvL1VwZGF0ZSB0aGUgYWNjdXJhY3lcclxuICAgICAgICAgYXdhaXQgdGhpcy5ldmFsdWF0ZSgpO1xyXG5cclxuXHJcbiAgICAgICAgIC8vc2VsZWN0aW9uXHJcbiAgICAgICAgIHRoaXMuc2VsZWN0aW9uKCk7XHJcbiAgICAgICAgY29uc29sZS5sb2coXCJCZXN0IGFjY3VyYWN5OiBcIiwgdGhpcy5nZXRUaGVCZXN0KCkuYWNjdXJhY3kpXHJcbiAgICAgICAgY29uc29sZS5sb2coXCJXb3JzdCBhY2N1cmFjeTogXCIsIHRoaXMuZ2V0VGhlV29yc3QoKS5hY2N1cmFjeSkgICAgICAgIFxyXG5cclxuICAgIH1cclxuXHJcbiAgICAvKipBYnN0cmFjdCBtZXRob2RzLlxyXG4gICAgICogU2hvdWxkIGJlIGltcGxlbWVudGVkIGJ5IGVhY2ggdmFyaWF0aW9uIG9mIGV2b2x1dGlvbmFyeSBhbGdvcml0aG1zXHJcbiAgICAgKi9cclxuXHJcbiAgICBhYnN0cmFjdCBjcm9zc292ZXIoKTogSW5kaXZpZHVhbDtcclxuICAgIGFic3RyYWN0IG11dGF0aW9uKG9mZnNwcmluZzogSW5kaXZpZHVhbFtdKTogdm9pZDtcclxuICAgIGFic3RyYWN0IHNlbGVjdGlvbigpOiB2b2lkO1xyXG5cclxuXHJcbiAgICAvKipIZWxwZXJzICovXHJcblxyXG4gICAgZ2V0VGhlQmVzdCgpOiBJbmRpdmlkdWFse1xyXG4gICAgICAgIGxldCBpbmRleF9iZXN0OiBudW1iZXI9MDtcclxuICAgICAgICBsZXQgYmVzdD0wO1xyXG5cclxuICAgICAgICB0aGlzLnBvcHVsYXRpb24uZm9yRWFjaCgoZWxlbTogYW55LCBpbmRleDogbnVtYmVyKT0+e1xyXG5cclxuICAgICAgICAgICAgaWYoZWxlbS5hY2N1cmFjeT5iZXN0KXtcclxuICAgICAgICAgICAgICAgIGJlc3Q9ZWxlbS5hY2N1cmFjeTtcclxuICAgICAgICAgICAgICAgIGluZGV4X2Jlc3Q9aW5kZXhcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgfSlcclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXMucG9wdWxhdGlvbltpbmRleF9iZXN0XTtcclxuICAgIH1cclxuXHJcblxyXG4gICAgZ2V0VGhlV29yc3QoKTogSW5kaXZpZHVhbHtcclxuICAgICAgICBsZXQgaW5kZXhfd29yc3Q6IG51bWJlcj0wO1xyXG4gICAgICAgIGxldCB3b3JzdD0xO1xyXG5cclxuICAgICAgICB0aGlzLnBvcHVsYXRpb24uZm9yRWFjaCgoZWxlbTogYW55LCBpbmRleDogbnVtYmVyKT0+e1xyXG5cclxuICAgICAgICAgICAgaWYoZWxlbS5hY2N1cmFjeTx3b3JzdCl7XHJcbiAgICAgICAgICAgICAgICB3b3JzdD1lbGVtLmFjY3VyYWN5O1xyXG4gICAgICAgICAgICAgICAgaW5kZXhfd29yc3Q9aW5kZXhcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgfSlcclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXMucG9wdWxhdGlvbltpbmRleF93b3JzdF07XHJcbiAgICB9XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICogU2VsZWN0aW5nIGluZGl2aWR1YWxzIGJ5IGVsaXRpc21cclxuICAgICAqL1xyXG4gICAgc2VsZWN0X3BhcmVudHNfYnlfcm9sbGV0X3doZWVsc192MihzZWxlY3Rpb25fbnVtYmVyPTIpOiBJbmRpdmlkdWFsW117XHJcblxyXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlNlbGVjdGluZyBwYXJlbnRzIGJ5IHJvbGxldCB3aGVlbHMuLi5cIik7XHJcbiAgICBcclxuICAgICAgICAgICAgY29uc3Qgc2hhcmU6IGFueT1bXTtcclxuICAgIFxyXG4gICAgICAgICAgICBsZXQgdG90YWw6IGFueT0wO1xyXG4gICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlBvcHVsYXRpb24gbGVuZ3RoLi4uXCIsIHRoaXMucG9wdWxhdGlvbi5sZW5ndGgpO1xyXG4gICAgXHJcbiAgICAgICAgICAgIC8vVGhpcyB3aWxsIGNyZWF0ZSBhbiBvdmVyYWxsIGFjY3VyYWN5XHJcbiAgICAgICAgICAgIHRoaXMucG9wdWxhdGlvbi5mb3JFYWNoKChlbGVtKT0+dG90YWwrPWVsZW0uYWNjdXJhY3kpO1xyXG4gICAgXHJcbiAgICAgICAgICAgIGxldCBwb2ludGVyPTA7XHJcbiAgICBcclxuICAgICAgICAgICAgdGhpcy5wb3B1bGF0aW9uLmZvckVhY2goKGVsZW06YW55LCBpbmRleCk9PntcclxuICAgIFxyXG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJBY2N1cmFjeS4uLlwiLCBlbGVtLmFjY3VyYWN5KTtcclxuICAgIFxyXG4gICAgICAgICAgICAgICAgc2hhcmUucHVzaChcclxuICAgICAgICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICAgICAgICBpbmRleDogaW5kZXgsXHJcbiAgICAgICAgICAgICAgICAgICAgICBzaGFyZTogIGVsZW0uYWNjdXJhY3kvdG90YWwsXHJcbiAgICAgICAgICAgICAgICAgICAgICBtaW46IHBvaW50ZXIsXHJcbiAgICAgICAgICAgICAgICAgICAgICBtYXg6IHBvaW50ZXIgKyAoZWxlbS5hY2N1cmFjeS90b3RhbClcclxuICAgICAgICAgICAgICAgICAgfSlcclxuICAgIFxyXG4gICAgICAgICAgICAgICAgICBwb2ludGVyKz1lbGVtLmFjY3VyYWN5L3RvdGFsO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgIFxyXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlNoYXJlczogXCIsIHNoYXJlKTtcclxuICAgIFxyXG4gICAgICAgICAgICBjb25zdCBhdXhfc2VsZWN0aW9uOiBhbnkgPVtdO1xyXG4gICAgXHJcbiAgICAgICAgICAgICAgLy9TZWxlY3RpbmcgdHdvIGluZGl2aWR1YWxzIHVzaW5nIHJvdWxldHRlIHdoZWVsc1xyXG4gICAgICAgICAgICBsZXQgY291bnRlcj0wO1xyXG5cclxuICAgICAgICAgICAgY29uc3QgaW5kZXhlc19hdXg6IG51bWJlcltdPVtdO1xyXG5cclxuICAgICAgICAgICAgd2hpbGUoY291bnRlcjxzZWxlY3Rpb25fbnVtYmVyKXtcclxuICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgLy9SYW5kb20gcG9pbnRlciwgdXNlZCB0byByYW5kb21seSBzZWxlY3QgYW4gaW5kaXZpZHVhbFxyXG4gICAgICAgICAgICAgICAgY29uc3QgYXV4X2luZGV4PSBNYXRoLnJhbmRvbSgpO1xyXG4gICAgXHJcbiAgICAgICAgICAgICAgICBzaGFyZS5mb3JFYWNoKChlbGVtOiBhbnkpPT57XHJcbiAgICBcclxuICAgICAgICAgICAgICAgICAgICBpZigoZWxlbS5taW48YXV4X2luZGV4KSYmKGVsZW0ubWF4PmF1eF9pbmRleCkpe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYXV4OiBJbmRpdmlkdWFsID0ge2luZGl2aWR1YWw6IG5ldyBUZWFjaGFibGVNb2JpbGVOZXQoKSwgYWNjdXJhY3k6IHRoaXMucG9wdWxhdGlvbltlbGVtLmluZGV4XS5hY2N1cmFjeSB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkluZGl2aWR1YWwganVzdCBjcmVhdGVkICh3ZWlndGgpOiBcIiwgYXV4LmluZGl2aWR1YWwuZ2V0SGVhZCgpLmxheWVyc1swXS5nZXRXZWlnaHRzKClbMF0uZGF0YVN5bmMoKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkluZGl2aWR1YWwgb3JpZ2luYWw6IFwiLCB0aGlzLnBvcHVsYXRpb25bZWxlbS5pbmRleF0uaW5kaXZpZHVhbC5nZXRIZWFkKCkubGF5ZXJzWzBdLmdldFdlaWdodHMoKVswXS5kYXRhU3luYygpKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgICAgICAgICAgICAvLyBPcmlnaW5hbCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSZWNpcGllbnRcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhpcy5jb3B5TW9kZWwodGhpcy5wb3B1bGF0aW9uW2VsZW0uaW5kZXhdLmluZGl2aWR1YWwuZ2V0SGVhZCgpLGF1eC5pbmRpdmlkdWFsLmdldEhlYWQoKSlcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoaXMucG9wdWxhdGlvbltlbGVtLmluZGV4XS5pbmRpdmlkdWFsLmdldEhlYWQoKS5kaXNwb3NlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkluZGl2aWR1YWwganVzdCBjcmVhdGVkICh3ZWlndGh0LCBjb3BpZWQpOiBcIiwgYXV4LmluZGl2aWR1YWwuZ2V0SGVhZCgpLmxheWVyc1swXS5nZXRXZWlnaHRzKClbMF0uZGF0YVN5bmMoKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyKys7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGF1eF9zZWxlY3Rpb24ucHVzaCh0aGlzLnBvcHVsYXRpb25bZWxlbS5pbmRleF0pO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5kZXhlc19hdXgucHVzaChlbGVtLmluZGV4KVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIHRoaXMucG9wdWxhdGlvbi5mb3JFYWNoKChlbGVtLCBpbmRleCk9PntcclxuICAgICAgICAgICAgLy8gICAgIGlmKCFpbmRleGVzX2F1eC5pbmNsdWRlcyhpbmRleCkpe1xyXG4gICAgICAgICAgICAvLyAgICAgICAgIGNvbnNvbGUubG9nKFwiRGlzcG9zZWQuLi5cIilcclxuICAgICAgICAgICAgLy8gICAgICAgICBlbGVtLmluZGl2aWR1YWwuZ2V0SGVhZCgpLmRpc3Bvc2UoKTtcclxuICAgICAgICAgICAgLy8gICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgLy8gfSlcclxuXHJcbiAgICAgICAgICAgIC8vIHRoaXMucG9wdWxhdGlvbj1bXTtcclxuXHJcbiAgICAgICAgICAgIHJldHVybiBhdXhfc2VsZWN0aW9uO1xyXG4gICAgICAgIH1cclxuICAgIFxyXG4gICAgLyoqXHJcbiAgICAgKiBTZWxlY3RpbmcgaW5kaXZpZHVhbHMgYnkgZWxpdGlzbVxyXG4gICAgICovXHJcbiAgICBzZWxlY3RfcGFyZW50c19ieV9yb2xsZXRfd2hlZWxzKHNlbGVjdGlvbl9udW1iZXI9Mik6IEluZGl2aWR1YWxbXXtcclxuXHJcbiAgICAgICAgLy8gY29uc29sZS5sb2dcclxuICAgICAgICAvLyAoXCJTZWxlY3RpbmcgcGFyZW50cyBieSByb2xsZXQgd2hlZWxzLi4uXCIpO1xyXG5cclxuICAgICAgICBjb25zdCBzaGFyZTogYW55PVtdO1xyXG5cclxuICAgICAgICBsZXQgdG90YWw6IGFueT0wO1xyXG4gICAgICAgICAgXHJcbiAgICAgICAgLy8gY29uc29sZS5sb2coXCJQb3B1bGF0aW9uIGxlbmd0aC4uLlwiLCB0aGlzLnBvcHVsYXRpb24ubGVuZ3RoKTtcclxuXHJcbiAgICAgICAgLy9UaGlzIHdpbGwgY3JlYXRlIGFuIG92ZXJhbGwgYWNjdXJhY3lcclxuICAgICAgICB0aGlzLnBvcHVsYXRpb24uZm9yRWFjaCgoZWxlbSk9PnRvdGFsKz1lbGVtLmFjY3VyYWN5KTtcclxuXHJcbiAgICAgICAgbGV0IHBvaW50ZXI9MDtcclxuXHJcbiAgICAgICAgdGhpcy5wb3B1bGF0aW9uLmZvckVhY2goKGVsZW06YW55LCBpbmRleCk9PntcclxuXHJcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwiQWNjdXJhY3kuLi5cIiwgZWxlbS5hY2N1cmFjeSk7XHJcblxyXG4gICAgICAgICAgICBzaGFyZS5wdXNoKFxyXG4gICAgICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgICBpbmRleDogaW5kZXgsXHJcbiAgICAgICAgICAgICAgICAgIHNoYXJlOiAgZWxlbS5hY2N1cmFjeS90b3RhbCxcclxuICAgICAgICAgICAgICAgICAgbWluOiBwb2ludGVyLFxyXG4gICAgICAgICAgICAgICAgICBtYXg6IHBvaW50ZXIgKyAoZWxlbS5hY2N1cmFjeS90b3RhbClcclxuICAgICAgICAgICAgICB9KVxyXG5cclxuICAgICAgICAgICAgICBwb2ludGVyKz1lbGVtLmFjY3VyYWN5L3RvdGFsO1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlNoYXJlczogXCIsIHNoYXJlKTtcclxuXHJcbiAgICAgICAgY29uc3QgYXV4X3NlbGVjdGlvbjogYW55ID1bXTtcclxuXHJcbiAgICAgICAgICAvL1NlbGVjdGluZyB0d28gaW5kaXZpZHVhbHMgdXNpbmcgcm91bGV0dGUgd2hlZWxzXHJcbiAgICAgICAgbGV0IGNvdW50ZXI9MDtcclxuICAgICAgICB3aGlsZShjb3VudGVyPHNlbGVjdGlvbl9udW1iZXIpe1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgLy9SYW5kb20gcG9pbnRlciwgdXNlZCB0byByYW5kb21seSBzZWxlY3QgYW4gaW5kaXZpZHVhbFxyXG4gICAgICAgICAgICBjb25zdCBhdXhfaW5kZXg9IE1hdGgucmFuZG9tKCk7XHJcblxyXG4gICAgICAgICAgICBzaGFyZS5mb3JFYWNoKChlbGVtOiBhbnkpPT57XHJcblxyXG4gICAgICAgICAgICAgICAgaWYoKGVsZW0ubWluPGF1eF9pbmRleCkmJihlbGVtLm1heD5hdXhfaW5kZXgpKXtcclxuICAgICAgICAgICAgICAgICAgICBjb3VudGVyKys7XHJcbiAgICAgICAgICAgICAgICAgICAgYXV4X3NlbGVjdGlvbi5wdXNoKHRoaXMucG9wdWxhdGlvbltlbGVtLmluZGV4XSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBhdXhfc2VsZWN0aW9uO1xyXG4gICAgfVxyXG5cclxuLyoqXHJcbiAqIFRoaXMgZnVuY3Rpb24gd2lsbCBtYWtlIGEgY29weSBvZiBhIG1vZGVsIG9uIHRoZSB3ZWlnaHQgbGV2ZWxcclxuICogVGhpcyBpcyBhbiBhdHRlbXB0IHRvIGF2b2lkIGluZmx1ZW5jaW5nIHRoZSBuZXcgbW9kZWwgd2hlbiB0aGUgb2xkIG9uZVxyXG4gKiBpcyBlbGltaW5hdGVkLiBcclxuICogXHJcbiAqIEBwYXJhbSBvcmlnaW5hbE1vZGVsIC0gdGhlIG1vZGVsIHRvIGJlIGNvcGllZCBcclxuICogQHBhcmFtIHJlY2lwaWVudCAtIHRoZSBuZXcgbW9kZWxcclxuICovXHJcbmFzeW5jIGNvcHlNb2RlbCAob3JpZ2luYWxNb2RlbDogdGYuTGF5ZXJzTW9kZWwsIHJlY2lwaWVudDogdGYuTGF5ZXJzTW9kZWwpICB7XHJcblxyXG4gICAgb3JpZ2luYWxNb2RlbC5sYXllcnMuZm9yRWFjaCgobGF5ZXI6IGFueSwgaW5kZXg6IGFueSk9PntcclxuICAgICAgICByZWNpcGllbnQubGF5ZXJzW2luZGV4XS5zZXRXZWlnaHRzKGxheWVyLmdldFdlaWdodHMoKSlcclxuICAgIH0pXHJcbn0gICAgXHJcblxyXG59XHJcbiJdfQ==
@@ -23,6 +23,9 @@ export class DisplayPanelComponent {
23
23
  if (!options.file_name && (options.subfolder)) {
24
24
  class_add.push(`${options.base}/${name}/${options.subfolder}/${name} ${i + 1}.${options.file_extension}`);
25
25
  }
26
+ else if (options.numbered) {
27
+ class_add.push(`${options.base}/${name}/${i + 1}.${options.file_extension}`);
28
+ }
26
29
  else
27
30
  class_add.push(`${options.base}/${name}/${options.file_name} ${i + 1}.${options.file_extension}`);
28
31
  }
@@ -60,4 +63,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImpor
60
63
  type: Component,
61
64
  args: [{ selector: 'neuroevolution-display-panel', standalone: true, imports: [CommonModule], template: "<div *ngFor=\"let class of classes; index as i\">\r\n <h1>{{class.name}}</h1>\r\n <img *ngFor=\"let item of class.images; index as i\" [src]=\"item\" width=\"224\" height=\"224\" [id]=\"'class-' + class.name + '-' + i\" crossorigin=\"anonymous\" >\r\n</div>\r\n" }]
62
65
  }] });
63
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlzcGxheS1wYW5lbC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy90ZmpzLWV2b2x1dGlvbi9zcmMvbGliL2NvbXBvbmVudHMvZGlzcGxheS1wYW5lbC9kaXNwbGF5LXBhbmVsLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RmanMtZXZvbHV0aW9uL3NyYy9saWIvY29tcG9uZW50cy9kaXNwbGF5LXBhbmVsL2Rpc3BsYXktcGFuZWwuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUV6QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7OztBQVN0RSxNQUFNLE9BQU8scUJBQXFCO0lBUGxDO1FBU0UsWUFBTyxHQUFVLEVBQUUsQ0FBQztLQThFckI7SUF4RUQsVUFBVSxDQUFDLGlCQUF5QixFQUFFLGFBQXVCLEVBQUUsT0FBZTtRQUUxRSxJQUFJLENBQUMsYUFBYSxHQUFDLGFBQWEsQ0FBQztRQUNqQyxJQUFJLENBQUMsMkJBQTJCLEdBQUMsaUJBQWlCLENBQUM7UUFFbkQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUUvQyxDQUFDO0lBR0gsV0FBVyxDQUFDLGlCQUF5QixFQUFFLE9BQWU7UUFFbEQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ2xELElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsRUFBRSxpQkFBaUIsRUFBRSxPQUFPLENBQUMsQ0FBQztTQUVwRTtJQUVILENBQUM7SUFFRCxVQUFVLENBQUMsSUFBWSxFQUFFLGlCQUF5QixFQUFFLE9BQVk7UUFFOUQsTUFBTSxTQUFTLEdBQU8sRUFBRSxDQUFDO1FBRXpCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxpQkFBaUIsRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUMxQyxJQUFHLENBQUMsT0FBTyxDQUFDLFNBQVMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBQztnQkFDM0MsU0FBUyxDQUFDLElBQUksQ0FBQyxHQUFHLE9BQU8sQ0FBQyxJQUFJLElBQUksSUFBSSxJQUFJLE9BQU8sQ0FBQyxTQUFTLElBQUksSUFBSSxJQUFJLENBQUMsR0FBQyxDQUFDLElBQUksT0FBTyxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUM7YUFDekc7O2dCQUdDLFNBQVMsQ0FBQyxJQUFJLENBQUMsR0FBRyxPQUFPLENBQUMsSUFBSSxJQUFJLElBQUksSUFBSSxPQUFPLENBQUMsU0FBUyxJQUFJLENBQUMsR0FBQyxDQUFDLElBQUksT0FBTyxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUM7U0FDckc7UUFFRCxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBQyxDQUFDLENBQUE7SUFFbEQsQ0FBQztJQUVGLEtBQUssQ0FBQyxXQUFXO1FBRWhCLG9FQUFvRTtRQUNwRSwyRkFBMkY7UUFDM0YseUZBQXlGO1FBQ3pGLGlEQUFpRDtRQUNqRCxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFcEIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ2xELE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1NBQ2pGO0lBQ0QsQ0FBQztJQUVELEtBQUssQ0FBQyxXQUFXLENBQUMsSUFBWSxFQUFFLGlCQUF5QjtRQUV2RCxNQUFNLFNBQVMsR0FBTyxFQUFFLENBQUM7UUFDekIsb0JBQW9CO1FBQ3BCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxpQkFBaUIsRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUUxQyxpQ0FBaUM7WUFDakMsTUFBTSxHQUFHLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyxTQUFTLElBQUksSUFBSSxDQUFDLEVBQUUsQ0FBcUIsQ0FBQztZQUU5RSxvQkFBb0I7WUFDcEIsTUFBTSxLQUFLLEdBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxJQUFJLEVBQUMsRUFBRSxDQUFBLElBQUksS0FBRyxJQUFJLENBQUMsQ0FBQTtZQUU5RCxNQUFNLGtCQUFrQixDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1NBRXpEO1FBRUQsdURBQXVEO0lBRXZELENBQUM7SUFFRCxLQUFLLENBQUMsRUFBVTtRQUNkLE9BQU8sSUFBSSxPQUFPLENBQU8sQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNuRSxDQUFDOzhHQS9FWSxxQkFBcUI7a0dBQXJCLHFCQUFxQix3RkNabEMsMFFBSUEseURESVksWUFBWTs7MkZBSVgscUJBQXFCO2tCQVBqQyxTQUFTOytCQUNFLDhCQUE4QixjQUM1QixJQUFJLFdBQ1AsQ0FBQyxZQUFZLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnR9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBHcm91cCB9IGZyb20gJy4uLy4uL2ludGVyZmFjZXMvZ3JvdXAnO1xyXG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5pbXBvcnQgeyBUZWFjaGFibGVNb2JpbGVOZXQgfSBmcm9tICcuLi8uLi9tb2RlbHMvdGVhY2hhYmxlLWV2b2x1dGlvbic7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ25ldXJvZXZvbHV0aW9uLWRpc3BsYXktcGFuZWwnLFxyXG4gIHN0YW5kYWxvbmU6IHRydWUsXHJcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZV0sXHJcbiAgdGVtcGxhdGVVcmw6ICcuL2Rpc3BsYXktcGFuZWwuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsOiAnLi9kaXNwbGF5LXBhbmVsLmNvbXBvbmVudC5jc3MnXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBEaXNwbGF5UGFuZWxDb21wb25lbnQge1xyXG5cclxuICBjbGFzc2VzOiBHcm91cFtdPVtdO1xyXG5cclxuICBjbGFzc2VzX25hbWVzITogc3RyaW5nW107XHJcblxyXG4gIG51bWJlcl9vZl9zYW1wbGVzX3Blcl9jbGFzcyE6IG51bWJlcjtcclxuXHJcbmxvYWRJbWFnZXMobnVtYmVyX29mX3NwZWNpZXM6IG51bWJlciwgY2xhc3Nlc19uYW1lczogc3RyaW5nW10sIG9wdGlvbnM6IG9iamVjdCl7XHJcbiAgICBcclxuICAgIHRoaXMuY2xhc3Nlc19uYW1lcz1jbGFzc2VzX25hbWVzO1xyXG4gICAgdGhpcy5udW1iZXJfb2Zfc2FtcGxlc19wZXJfY2xhc3M9bnVtYmVyX29mX3NwZWNpZXM7XHJcblxyXG4gICAgdGhpcy5hZGRfc3BlY2llcyhudW1iZXJfb2Zfc3BlY2llcywgb3B0aW9ucyk7ICAgIFxyXG5cclxuICB9XHJcblxyXG5cclxuYWRkX3NwZWNpZXMobnVtYmVyX29mX3NwZWNpZXM6IG51bWJlciwgb3B0aW9uczogb2JqZWN0KXtcclxuXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuY2xhc3Nlc19uYW1lcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICB0aGlzLmFkZF9pbWFnZXModGhpcy5jbGFzc2VzX25hbWVzW2ldLCBudW1iZXJfb2Zfc3BlY2llcywgb3B0aW9ucyk7XHJcbiAgICAgIFxyXG4gICAgfVxyXG5cclxuICB9XHJcblxyXG4gIGFkZF9pbWFnZXMobmFtZTogc3RyaW5nLCBudW1iZXJfb2Zfc3BlY2llczogbnVtYmVyLCBvcHRpb25zOiBhbnkpeyAgIFxyXG5cclxuICAgIGNvbnN0IGNsYXNzX2FkZDogYW55PSBbXTtcclxuXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bWJlcl9vZl9zcGVjaWVzOyBpKyspIHtcclxuICAgICAgaWYoIW9wdGlvbnMuZmlsZV9uYW1lICYmIChvcHRpb25zLnN1YmZvbGRlcikpeyAgICAgICAgXHJcbiAgICAgICAgY2xhc3NfYWRkLnB1c2goYCR7b3B0aW9ucy5iYXNlfS8ke25hbWV9LyR7b3B0aW9ucy5zdWJmb2xkZXJ9LyR7bmFtZX0gJHtpKzF9LiR7b3B0aW9ucy5maWxlX2V4dGVuc2lvbn1gKTtcclxuICAgICAgfSBcclxuICAgICAgICAgXHJcbiAgICAgIGVsc2UgICAgICBcclxuICAgICAgICBjbGFzc19hZGQucHVzaChgJHtvcHRpb25zLmJhc2V9LyR7bmFtZX0vJHtvcHRpb25zLmZpbGVfbmFtZX0gJHtpKzF9LiR7b3B0aW9ucy5maWxlX2V4dGVuc2lvbn1gKTtcclxuICB9XHJcblxyXG4gIHRoaXMuY2xhc3Nlcy5wdXNoKHtuYW1lOiBuYW1lLCBpbWFnZXM6IGNsYXNzX2FkZH0pICBcclxuXHJcbiAgfVxyXG5cclxuIGFzeW5jIGFkZGV4YW1wbGVzKCl7XHJcblxyXG4gIC8vVGhpcyBpcyBuZWVkZWQgdG8gbWFrZSBzdXJlIGl0IGdpdmVzIHRpbWUgZm9yIHRoZSBpbWFnZXMgdG8gdXBsb2FkXHJcbiAgLy9UaGUgaW1hZ2VzIHVwbG9hZCB2ZXJ5IGZhc3QsIHdoYXQgbWFrZXMgdGhpcyBtZXRob2QgZXhlY3V0ZSBiZWZvcmUgdGhlIGltYWdlcyBhcmUgb24gSFRNTFxyXG4gIC8vSXQgY2FuIGJlIHJlbW92ZWQgaWYgc29tZWhvdyB0aGlzIG1ldGhvZCBpcyBqdXN0IGNhbGxlZCBhZnRlciB0aGUgaW1hZ2VzIGFyZSBhdmFpbGFibGUuXHJcbiAgLy8gY29uc29sZS5sb2coXCJMb2FkaW5nIGV4YW1wbGVzIGFzIHRlbnNvcnMuLi4uXCIpXHJcbiAgYXdhaXQgdGhpcy5kZWxheSgwKTtcclxuXHJcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmNsYXNzZXNfbmFtZXMubGVuZ3RoOyBpKyspIHtcclxuICAgIGF3YWl0IHRoaXMuYWRkX2V4YW1wbGUodGhpcy5jbGFzc2VzX25hbWVzW2ldLCB0aGlzLm51bWJlcl9vZl9zYW1wbGVzX3Blcl9jbGFzcyk7XHJcbiAgfVxyXG4gIH1cclxuXHJcbiAgYXN5bmMgYWRkX2V4YW1wbGUobmFtZTogc3RyaW5nLCBudW1iZXJfb2Zfc3BlY2llczogbnVtYmVyKXsgICBcclxuXHJcbiAgICBjb25zdCBjbGFzc19hZGQ6IGFueT0gW107XHJcbiAgICAvLyBjb25zb2xlLmxvZyhuYW1lKVxyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1iZXJfb2Zfc3BlY2llczsgaSsrKSB7IFxyXG4gICAgICBcclxuICAgICAgLy9Db2xsZWN0aW5nIHRoZSBpbWFnZXMgZnJvbSBIVE1MXHJcbiAgICAgIGNvbnN0IGF1eCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGBjbGFzcy0ke25hbWV9LSR7aX1gKSBhcyBIVE1MSW1hZ2VFbGVtZW50OyAgICAgIFxyXG5cclxuICAgICAgLy9BZGRpbmcgdGhlIGV4YW1wbGVcclxuICAgICAgY29uc3QgaW5kZXg9IHRoaXMuY2xhc3Nlc19uYW1lcy5maW5kSW5kZXgoKGVsZW0pPT5lbGVtPT09bmFtZSlcclxuXHJcbiAgICAgIGF3YWl0IFRlYWNoYWJsZU1vYmlsZU5ldC5hZGRFeGFtcGxlKGluZGV4LCBuYW1lLCBhdXgpOyAgICBcclxuICAgICAgXHJcbiAgfVxyXG5cclxuICAvLyB0aGlzLmNsYXNzZXMucHVzaCh7bmFtZTogbmFtZSwgaW1hZ2VzOiBjbGFzc19hZGR9KSAgXHJcblxyXG4gIH1cclxuXHJcbiAgZGVsYXkobXM6IG51bWJlcikge1xyXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSk7XHJcbn1cclxufVxyXG4iLCI8ZGl2ICpuZ0Zvcj1cImxldCBjbGFzcyBvZiBjbGFzc2VzOyBpbmRleCBhcyBpXCI+XHJcbiAgPGgxPnt7Y2xhc3MubmFtZX19PC9oMT5cclxuICA8aW1nICAqbmdGb3I9XCJsZXQgaXRlbSBvZiBjbGFzcy5pbWFnZXM7IGluZGV4IGFzIGlcIiBbc3JjXT1cIml0ZW1cIiB3aWR0aD1cIjIyNFwiIGhlaWdodD1cIjIyNFwiIFtpZF09XCInY2xhc3MtJyArIGNsYXNzLm5hbWUgKyAnLScgKyBpXCIgY3Jvc3NvcmlnaW49XCJhbm9ueW1vdXNcIiA+XHJcbjwvZGl2PlxyXG4iXX0=
66
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlzcGxheS1wYW5lbC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy90ZmpzLWV2b2x1dGlvbi9zcmMvbGliL2NvbXBvbmVudHMvZGlzcGxheS1wYW5lbC9kaXNwbGF5LXBhbmVsLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RmanMtZXZvbHV0aW9uL3NyYy9saWIvY29tcG9uZW50cy9kaXNwbGF5LXBhbmVsL2Rpc3BsYXktcGFuZWwuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUV6QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7OztBQVN0RSxNQUFNLE9BQU8scUJBQXFCO0lBUGxDO1FBU0UsWUFBTyxHQUFVLEVBQUUsQ0FBQztLQW9GckI7SUE5RUQsVUFBVSxDQUFDLGlCQUF5QixFQUFFLGFBQXVCLEVBQUUsT0FBZTtRQUUxRSxJQUFJLENBQUMsYUFBYSxHQUFDLGFBQWEsQ0FBQztRQUNqQyxJQUFJLENBQUMsMkJBQTJCLEdBQUMsaUJBQWlCLENBQUM7UUFFbkQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUUvQyxDQUFDO0lBR0gsV0FBVyxDQUFDLGlCQUF5QixFQUFFLE9BQWU7UUFFbEQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ2xELElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsRUFBRSxpQkFBaUIsRUFBRSxPQUFPLENBQUMsQ0FBQztTQUVwRTtJQUVILENBQUM7SUFFRCxVQUFVLENBQUMsSUFBWSxFQUFFLGlCQUF5QixFQUFFLE9BQVk7UUFFOUQsTUFBTSxTQUFTLEdBQU8sRUFBRSxDQUFDO1FBRXpCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxpQkFBaUIsRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUMxQyxJQUFHLENBQUMsT0FBTyxDQUFDLFNBQVMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBQztnQkFDM0MsU0FBUyxDQUFDLElBQUksQ0FBQyxHQUFHLE9BQU8sQ0FBQyxJQUFJLElBQUksSUFBSSxJQUFJLE9BQU8sQ0FBQyxTQUFTLElBQUksSUFBSSxJQUFJLENBQUMsR0FBQyxDQUFDLElBQUksT0FBTyxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUM7YUFDekc7aUJBQ0ksSUFBRyxPQUFPLENBQUMsUUFBUSxFQUFDO2dCQUV2QixTQUFTLENBQUMsSUFBSSxDQUFDLEdBQUcsT0FBTyxDQUFDLElBQUksSUFBSSxJQUFJLElBQUksQ0FBQyxHQUFDLENBQUMsSUFBSSxPQUFPLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQzthQUc1RTs7Z0JBR0MsU0FBUyxDQUFDLElBQUksQ0FBQyxHQUFHLE9BQU8sQ0FBQyxJQUFJLElBQUksSUFBSSxJQUFJLE9BQU8sQ0FBQyxTQUFTLElBQUksQ0FBQyxHQUFDLENBQUMsSUFBSSxPQUFPLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQztTQUNyRztRQUVELElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFDLENBQUMsQ0FBQTtJQUVsRCxDQUFDO0lBRUYsS0FBSyxDQUFDLFdBQVc7UUFFaEIsb0VBQW9FO1FBQ3BFLDJGQUEyRjtRQUMzRix5RkFBeUY7UUFDekYsaURBQWlEO1FBQ2pELE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUVwQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDbEQsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLDJCQUEyQixDQUFDLENBQUM7U0FDakY7SUFDRCxDQUFDO0lBRUQsS0FBSyxDQUFDLFdBQVcsQ0FBQyxJQUFZLEVBQUUsaUJBQXlCO1FBRXZELE1BQU0sU0FBUyxHQUFPLEVBQUUsQ0FBQztRQUN6QixvQkFBb0I7UUFDcEIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLGlCQUFpQixFQUFFLENBQUMsRUFBRSxFQUFFO1lBRTFDLGlDQUFpQztZQUNqQyxNQUFNLEdBQUcsR0FBRyxRQUFRLENBQUMsY0FBYyxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFxQixDQUFDO1lBRTlFLG9CQUFvQjtZQUNwQixNQUFNLEtBQUssR0FBRSxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxDQUFDLElBQUksRUFBQyxFQUFFLENBQUEsSUFBSSxLQUFHLElBQUksQ0FBQyxDQUFBO1lBRTlELE1BQU0sa0JBQWtCLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUM7U0FFekQ7UUFFRCx1REFBdUQ7SUFFdkQsQ0FBQztJQUVELEtBQUssQ0FBQyxFQUFVO1FBQ2QsT0FBTyxJQUFJLE9BQU8sQ0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25FLENBQUM7OEdBckZZLHFCQUFxQjtrR0FBckIscUJBQXFCLHdGQ1psQywwUUFJQSx5RERJWSxZQUFZOzsyRkFJWCxxQkFBcUI7a0JBUGpDLFNBQVM7K0JBQ0UsOEJBQThCLGNBQzVCLElBQUksV0FDUCxDQUFDLFlBQVksQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IEdyb3VwIH0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9ncm91cCc7XHJcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcbmltcG9ydCB7IFRlYWNoYWJsZU1vYmlsZU5ldCB9IGZyb20gJy4uLy4uL21vZGVscy90ZWFjaGFibGUtZXZvbHV0aW9uJztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnbmV1cm9ldm9sdXRpb24tZGlzcGxheS1wYW5lbCcsXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcclxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlXSxcclxuICB0ZW1wbGF0ZVVybDogJy4vZGlzcGxheS1wYW5lbC5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmw6ICcuL2Rpc3BsYXktcGFuZWwuY29tcG9uZW50LmNzcydcclxufSlcclxuZXhwb3J0IGNsYXNzIERpc3BsYXlQYW5lbENvbXBvbmVudCB7XHJcblxyXG4gIGNsYXNzZXM6IEdyb3VwW109W107XHJcblxyXG4gIGNsYXNzZXNfbmFtZXMhOiBzdHJpbmdbXTtcclxuXHJcbiAgbnVtYmVyX29mX3NhbXBsZXNfcGVyX2NsYXNzITogbnVtYmVyO1xyXG5cclxubG9hZEltYWdlcyhudW1iZXJfb2Zfc3BlY2llczogbnVtYmVyLCBjbGFzc2VzX25hbWVzOiBzdHJpbmdbXSwgb3B0aW9uczogb2JqZWN0KXtcclxuICAgIFxyXG4gICAgdGhpcy5jbGFzc2VzX25hbWVzPWNsYXNzZXNfbmFtZXM7XHJcbiAgICB0aGlzLm51bWJlcl9vZl9zYW1wbGVzX3Blcl9jbGFzcz1udW1iZXJfb2Zfc3BlY2llcztcclxuXHJcbiAgICB0aGlzLmFkZF9zcGVjaWVzKG51bWJlcl9vZl9zcGVjaWVzLCBvcHRpb25zKTsgICAgXHJcblxyXG4gIH1cclxuXHJcblxyXG5hZGRfc3BlY2llcyhudW1iZXJfb2Zfc3BlY2llczogbnVtYmVyLCBvcHRpb25zOiBvYmplY3Qpe1xyXG5cclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5jbGFzc2VzX25hbWVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIHRoaXMuYWRkX2ltYWdlcyh0aGlzLmNsYXNzZXNfbmFtZXNbaV0sIG51bWJlcl9vZl9zcGVjaWVzLCBvcHRpb25zKTtcclxuICAgICAgXHJcbiAgICB9XHJcblxyXG4gIH1cclxuXHJcbiAgYWRkX2ltYWdlcyhuYW1lOiBzdHJpbmcsIG51bWJlcl9vZl9zcGVjaWVzOiBudW1iZXIsIG9wdGlvbnM6IGFueSl7ICAgXHJcblxyXG4gICAgY29uc3QgY2xhc3NfYWRkOiBhbnk9IFtdO1xyXG5cclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyX29mX3NwZWNpZXM7IGkrKykge1xyXG4gICAgICBpZighb3B0aW9ucy5maWxlX25hbWUgJiYgKG9wdGlvbnMuc3ViZm9sZGVyKSl7ICAgICAgICBcclxuICAgICAgICBjbGFzc19hZGQucHVzaChgJHtvcHRpb25zLmJhc2V9LyR7bmFtZX0vJHtvcHRpb25zLnN1YmZvbGRlcn0vJHtuYW1lfSAke2krMX0uJHtvcHRpb25zLmZpbGVfZXh0ZW5zaW9ufWApO1xyXG4gICAgICB9IFxyXG4gICAgICBlbHNlIGlmKG9wdGlvbnMubnVtYmVyZWQpe1xyXG4gICAgICBcclxuICAgICAgICBjbGFzc19hZGQucHVzaChgJHtvcHRpb25zLmJhc2V9LyR7bmFtZX0vJHtpKzF9LiR7b3B0aW9ucy5maWxlX2V4dGVuc2lvbn1gKTtcclxuXHJcblxyXG4gICAgICB9IFxyXG4gICAgICAgICBcclxuICAgICAgZWxzZSAgICAgIFxyXG4gICAgICAgIGNsYXNzX2FkZC5wdXNoKGAke29wdGlvbnMuYmFzZX0vJHtuYW1lfS8ke29wdGlvbnMuZmlsZV9uYW1lfSAke2krMX0uJHtvcHRpb25zLmZpbGVfZXh0ZW5zaW9ufWApO1xyXG4gIH1cclxuXHJcbiAgdGhpcy5jbGFzc2VzLnB1c2goe25hbWU6IG5hbWUsIGltYWdlczogY2xhc3NfYWRkfSkgIFxyXG5cclxuICB9XHJcblxyXG4gYXN5bmMgYWRkZXhhbXBsZXMoKXtcclxuXHJcbiAgLy9UaGlzIGlzIG5lZWRlZCB0byBtYWtlIHN1cmUgaXQgZ2l2ZXMgdGltZSBmb3IgdGhlIGltYWdlcyB0byB1cGxvYWRcclxuICAvL1RoZSBpbWFnZXMgdXBsb2FkIHZlcnkgZmFzdCwgd2hhdCBtYWtlcyB0aGlzIG1ldGhvZCBleGVjdXRlIGJlZm9yZSB0aGUgaW1hZ2VzIGFyZSBvbiBIVE1MXHJcbiAgLy9JdCBjYW4gYmUgcmVtb3ZlZCBpZiBzb21laG93IHRoaXMgbWV0aG9kIGlzIGp1c3QgY2FsbGVkIGFmdGVyIHRoZSBpbWFnZXMgYXJlIGF2YWlsYWJsZS5cclxuICAvLyBjb25zb2xlLmxvZyhcIkxvYWRpbmcgZXhhbXBsZXMgYXMgdGVuc29ycy4uLi5cIilcclxuICBhd2FpdCB0aGlzLmRlbGF5KDApO1xyXG5cclxuICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuY2xhc3Nlc19uYW1lcy5sZW5ndGg7IGkrKykge1xyXG4gICAgYXdhaXQgdGhpcy5hZGRfZXhhbXBsZSh0aGlzLmNsYXNzZXNfbmFtZXNbaV0sIHRoaXMubnVtYmVyX29mX3NhbXBsZXNfcGVyX2NsYXNzKTtcclxuICB9XHJcbiAgfVxyXG5cclxuICBhc3luYyBhZGRfZXhhbXBsZShuYW1lOiBzdHJpbmcsIG51bWJlcl9vZl9zcGVjaWVzOiBudW1iZXIpeyAgIFxyXG5cclxuICAgIGNvbnN0IGNsYXNzX2FkZDogYW55PSBbXTtcclxuICAgIC8vIGNvbnNvbGUubG9nKG5hbWUpXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bWJlcl9vZl9zcGVjaWVzOyBpKyspIHsgXHJcbiAgICAgIFxyXG4gICAgICAvL0NvbGxlY3RpbmcgdGhlIGltYWdlcyBmcm9tIEhUTUxcclxuICAgICAgY29uc3QgYXV4ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoYGNsYXNzLSR7bmFtZX0tJHtpfWApIGFzIEhUTUxJbWFnZUVsZW1lbnQ7ICAgICAgXHJcblxyXG4gICAgICAvL0FkZGluZyB0aGUgZXhhbXBsZVxyXG4gICAgICBjb25zdCBpbmRleD0gdGhpcy5jbGFzc2VzX25hbWVzLmZpbmRJbmRleCgoZWxlbSk9PmVsZW09PT1uYW1lKVxyXG5cclxuICAgICAgYXdhaXQgVGVhY2hhYmxlTW9iaWxlTmV0LmFkZEV4YW1wbGUoaW5kZXgsIG5hbWUsIGF1eCk7ICAgIFxyXG4gICAgICBcclxuICB9XHJcblxyXG4gIC8vIHRoaXMuY2xhc3Nlcy5wdXNoKHtuYW1lOiBuYW1lLCBpbWFnZXM6IGNsYXNzX2FkZH0pICBcclxuXHJcbiAgfVxyXG5cclxuICBkZWxheShtczogbnVtYmVyKSB7XHJcbiAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpKTtcclxufVxyXG59XHJcbiIsIjxkaXYgKm5nRm9yPVwibGV0IGNsYXNzIG9mIGNsYXNzZXM7IGluZGV4IGFzIGlcIj5cclxuICA8aDE+e3tjbGFzcy5uYW1lfX08L2gxPlxyXG4gIDxpbWcgICpuZ0Zvcj1cImxldCBpdGVtIG9mIGNsYXNzLmltYWdlczsgaW5kZXggYXMgaVwiIFtzcmNdPVwiaXRlbVwiIHdpZHRoPVwiMjI0XCIgaGVpZ2h0PVwiMjI0XCIgW2lkXT1cIidjbGFzcy0nICsgY2xhc3MubmFtZSArICctJyArIGlcIiBjcm9zc29yaWdpbj1cImFub255bW91c1wiID5cclxuPC9kaXY+XHJcbiJdfQ==
@@ -0,0 +1,24 @@
1
+ import { Component, Input } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "@angular/common";
5
+ export class MetricsComponent {
6
+ constructor() {
7
+ this.accuracy_per_class = [];
8
+ this.classes_names = [];
9
+ this.confusion_matrix = [];
10
+ }
11
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: MetricsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
12
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: MetricsComponent, isStandalone: true, selector: "neuroevolution-metrics", inputs: { accuracy_per_class: "accuracy_per_class", classes_names: "classes_names", confusion_matrix: "confusion_matrix" }, ngImport: i0, template: "<h1>Accuracy per class</h1>\r\n<div *ngFor=\"let accuracy of accuracy_per_class; index as index\" > {{classes_names[index]}}: {{accuracy}}%</div>\r\n\r\n\r\n\r\n<h2>Confusion Matrix</h2>\r\n\r\n<table>\r\n <tr>\r\n <th *ngFor=\"let label of classes_names\">{{label}}</th>\r\n </tr>\r\n <tr *ngFor=\"let item of confusion_matrix ; index as i\">\r\n <td *ngFor=\"let value of item ; index as j\" > {{confusion_matrix[i][j]}}%</td> \r\n </tr>\r\n</table>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] }); }
13
+ }
14
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: MetricsComponent, decorators: [{
15
+ type: Component,
16
+ args: [{ selector: 'neuroevolution-metrics', standalone: true, imports: [CommonModule], template: "<h1>Accuracy per class</h1>\r\n<div *ngFor=\"let accuracy of accuracy_per_class; index as index\" > {{classes_names[index]}}: {{accuracy}}%</div>\r\n\r\n\r\n\r\n<h2>Confusion Matrix</h2>\r\n\r\n<table>\r\n <tr>\r\n <th *ngFor=\"let label of classes_names\">{{label}}</th>\r\n </tr>\r\n <tr *ngFor=\"let item of confusion_matrix ; index as i\">\r\n <td *ngFor=\"let value of item ; index as j\" > {{confusion_matrix[i][j]}}%</td> \r\n </tr>\r\n</table>\r\n" }]
17
+ }], propDecorators: { accuracy_per_class: [{
18
+ type: Input
19
+ }], classes_names: [{
20
+ type: Input
21
+ }], confusion_matrix: [{
22
+ type: Input
23
+ }] } });
24
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy90ZmpzLWV2b2x1dGlvbi9zcmMvbGliL2NvbXBvbmVudHMvbWV0cmljcy9tZXRyaWNzLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RmanMtZXZvbHV0aW9uL3NyYy9saWIvY29tcG9uZW50cy9tZXRyaWNzL21ldHJpY3MuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFakQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDOzs7QUFTL0MsTUFBTSxPQUFPLGdCQUFnQjtJQVA3QjtRQVNXLHVCQUFrQixHQUFXLEVBQUUsQ0FBQztRQUNoQyxrQkFBYSxHQUFXLEVBQUUsQ0FBQztRQUMzQixxQkFBZ0IsR0FBYSxFQUFFLENBQUM7S0FHMUM7OEdBUFksZ0JBQWdCO2tHQUFoQixnQkFBZ0IsOE1DWDdCLGtlQWVBLHlERFJZLFlBQVk7OzJGQUlYLGdCQUFnQjtrQkFQNUIsU0FBUzsrQkFDRSx3QkFBd0IsY0FDdEIsSUFBSSxXQUNQLENBQUMsWUFBWSxDQUFDOzhCQU1kLGtCQUFrQjtzQkFBMUIsS0FBSztnQkFDRyxhQUFhO3NCQUFyQixLQUFLO2dCQUNHLGdCQUFnQjtzQkFBeEIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuXHJcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ25ldXJvZXZvbHV0aW9uLW1ldHJpY3MnLFxyXG4gIHN0YW5kYWxvbmU6IHRydWUsXHJcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZV0sXHJcbiAgdGVtcGxhdGVVcmw6ICcuL21ldHJpY3MuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsOiAnLi9tZXRyaWNzLmNvbXBvbmVudC5jc3MnXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBNZXRyaWNzQ29tcG9uZW50IHtcclxuXHJcbiAgQElucHV0KCkgYWNjdXJhY3lfcGVyX2NsYXNzOiBudW1iZXJbXT1bXTtcclxuICBASW5wdXQoKSBjbGFzc2VzX25hbWVzOiBzdHJpbmdbXT1bXTtcclxuICBASW5wdXQoKSBjb25mdXNpb25fbWF0cml4OiBudW1iZXJbXVtdPVtdO1xyXG5cclxuXHJcbn1cclxuIiwiPGgxPkFjY3VyYWN5IHBlciBjbGFzczwvaDE+XHJcbjxkaXYgKm5nRm9yPVwibGV0IGFjY3VyYWN5IG9mIGFjY3VyYWN5X3Blcl9jbGFzczsgaW5kZXggYXMgaW5kZXhcIiA+IHt7Y2xhc3Nlc19uYW1lc1tpbmRleF19fToge3thY2N1cmFjeX19JTwvZGl2PlxyXG5cclxuXHJcblxyXG48aDI+Q29uZnVzaW9uIE1hdHJpeDwvaDI+XHJcblxyXG48dGFibGU+XHJcbiAgICA8dHI+XHJcbiAgICAgICAgPHRoICpuZ0Zvcj1cImxldCBsYWJlbCBvZiBjbGFzc2VzX25hbWVzXCI+e3tsYWJlbH19PC90aD5cclxuICAgIDwvdHI+XHJcbiAgICA8dHIgKm5nRm9yPVwibGV0IGl0ZW0gb2YgY29uZnVzaW9uX21hdHJpeCA7IGluZGV4IGFzIGlcIj5cclxuICAgICAgIDx0ZCAqbmdGb3I9XCJsZXQgdmFsdWUgb2YgaXRlbSA7IGluZGV4IGFzIGpcIiA+IHt7Y29uZnVzaW9uX21hdHJpeFtpXVtqXX19JTwvdGQ+IFxyXG4gICAgPC90cj5cclxuPC90YWJsZT5cclxuIl19
@@ -291,6 +291,8 @@ export class TeachableMobileNet extends CustomMobileNet {
291
291
  datasetForEvaluation() {
292
292
  }
293
293
  async evaluate() {
294
+ //Check of the features have already been calculated
295
+ /**For avoiding recalculating the features every generation */
294
296
  if (!TeachableMobileNet.feature_aux) {
295
297
  const features = [];
296
298
  const targets = [];
@@ -307,7 +309,9 @@ export class TeachableMobileNet extends CustomMobileNet {
307
309
  TeachableMobileNet.feature_aux = tf.tensor(features);
308
310
  TeachableMobileNet.target_aux = tf.tensor(targets);
309
311
  }
312
+ //Evaluating the model
310
313
  const aux = this.trainingModel.evaluate(TeachableMobileNet.feature_aux, TeachableMobileNet.target_aux);
314
+ //Return just the accuracy
311
315
  return aux[1].dataSync()[0];
312
316
  }
313
317
  // async evaluate(){
@@ -423,4 +427,4 @@ function fisherYates(array, seed) {
423
427
  }
424
428
  return shuffled;
425
429
  }
426
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVhY2hhYmxlLWV2b2x1dGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RmanMtZXZvbHV0aW9uL3NyYy9saWIvbW9kZWxzL3RlYWNoYWJsZS1ldm9sdXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGVBQWUsRUFBMEIsTUFBTSxvQkFBb0IsQ0FBQztBQUU3RSxPQUFPLEtBQUssRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRXZDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFdEMsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUlyQyxPQUFPLEtBQUssS0FBSyxNQUFNLHNCQUFzQixDQUFDO0FBSTlDLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxDQUFDO0FBc0JqQzs7O0dBR0c7QUFDSCxNQUFNLFlBQVksR0FBRyxDQUFDLElBQXVCLEVBQUUsRUFBRTtJQUMvQyw4RkFBOEY7SUFDOUYsd0RBQXdEO0lBQ3hELElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFdBQVcsSUFBSSx5QkFBeUIsQ0FBQztJQUNqRSxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLElBQUksSUFBSSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUM1RCxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxZQUFZLElBQUksRUFBRSxDQUFDO0lBQzVDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsSUFBSSxVQUFVLENBQUM7SUFDOUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQztJQUNoQyxpREFBaUQ7SUFDakQsT0FBTyxJQUFnQixDQUFDO0FBQzFCLENBQUMsQ0FBQztBQUVGLE1BQU0sT0FBTyxrQkFBbUIsU0FBUSxlQUFlO0lBRW5ELHVDQUF1QztJQUN2Qzs7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S0FDOUU7SUFFRCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ3VzdG9tTW9iaWxlTmV0LCBsb2FkVHJ1bmNhdGVkTW9iaWxlTmV0IH0gZnJvbSBcIi4vY3VzdG9tLW1vYmlsZW5ldFwiO1xyXG5cclxuaW1wb3J0ICogYXMgdGYgZnJvbSAnQHRlbnNvcmZsb3cvdGZqcyc7XHJcblxyXG5pbXBvcnQgeyBjYXB0dXJlIH0gZnJvbSAnLi4vdXRpbHMvdGYnO1xyXG5pbXBvcnQgeyBDbGFzcyB9IGZyb20gJy4uL3V0aWxzL2NsYXNzJztcclxuaW1wb3J0IHsgVXRpbCB9IGZyb20gXCIuLi91dGlscy91dGlsXCI7XHJcblxyXG5pbXBvcnQgKiBhcyBzZWVkcmFuZG9tIGZyb20gJ3NlZWRyYW5kb20nO1xyXG5cclxuaW1wb3J0ICogYXMgdGZ2aXMgZnJvbSAnQHRlbnNvcmZsb3cvdGZqcy12aXMnO1xyXG5cclxuaW1wb3J0IHsgVGVuc29yQ29udGFpbmVyIH0gZnJvbSAnQHRlbnNvcmZsb3cvdGZqcy1jb3JlL2Rpc3QvdGVuc29yX3R5cGVzJztcclxuXHJcbmNvbnN0IFZBTElEQVRJT05fRlJBQ1RJT04gPSAwLjE1O1xyXG5cclxuXHJcblxyXG4vKipcclxuICogdGhlIG1ldGFkYXRhIHRvIGRlc2NyaWJlIHRoZSBtb2RlbCdzIGNyZWF0aW9uLFxyXG4gKiBpbmNsdWRlcyB0aGUgbGFiZWxzIGFzc29jaWF0ZWQgd2l0aCB0aGUgY2xhc3Nlc1xyXG4gKiBhbmQgdmVyc2lvbmluZyBpbmZvcm1hdGlvbiBmcm9tIHRyYWluaW5nLlxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBNZXRhZGF0YSB7XHJcbiAgdGZqc1ZlcnNpb246IHN0cmluZztcclxuICB0bVZlcnNpb24/OiBzdHJpbmc7XHJcbiAgcGFja2FnZVZlcnNpb246IHN0cmluZztcclxuICBwYWNrYWdlTmFtZTogc3RyaW5nO1xyXG4gIG1vZGVsTmFtZT86IHN0cmluZztcclxuICB0aW1lU3RhbXA/OiBzdHJpbmc7XHJcbiAgbGFiZWxzOiBzdHJpbmdbXTtcclxuICB1c2VyTWV0YWRhdGE/OiB7fTtcclxuICBncmF5c2NhbGU/OiBib29sZWFuO1xyXG4gIGltYWdlU2l6ZT86IG51bWJlcjtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJlY2VpdmVzIGEgTWV0YWRhdGEgb2JqZWN0IGFuZCBmaWxscyBpbiB0aGUgb3B0aW9uYWwgZmllbGRzIHN1Y2ggYXMgdGltZVN0YW1wXHJcbiAqIEBwYXJhbSBkYXRhIGEgTWV0YWRhdGEgb2JqZWN0XHJcbiAqL1xyXG5jb25zdCBmaWxsTWV0YWRhdGEgPSAoZGF0YTogUGFydGlhbDxNZXRhZGF0YT4pID0+IHtcclxuICAvLyB1dGlsLmFzc2VydCh0eXBlb2YgZGF0YS50ZmpzVmVyc2lvbiA9PT0gJ3N0cmluZycsICgpID0+IGBtZXRhZGF0YS50ZmpzVmVyc2lvbiBpcyBpbnZhbGlkYCk7XHJcbiAgLy8gZGF0YS5wYWNrYWdlVmVyc2lvbiA9IGRhdGEucGFja2FnZVZlcnNpb24gfHwgdmVyc2lvbjtcclxuICBkYXRhLnBhY2thZ2VOYW1lID0gZGF0YS5wYWNrYWdlTmFtZSB8fCAnQHRlYWNoYWJsZW1hY2hpbmUvaW1hZ2UnO1xyXG4gIGRhdGEudGltZVN0YW1wID0gZGF0YS50aW1lU3RhbXAgfHwgbmV3IERhdGUoKS50b0lTT1N0cmluZygpO1xyXG4gIGRhdGEudXNlck1ldGFkYXRhID0gZGF0YS51c2VyTWV0YWRhdGEgfHwge307XHJcbiAgZGF0YS5tb2RlbE5hbWUgPSBkYXRhLm1vZGVsTmFtZSB8fCAndW50aXRsZWQnO1xyXG4gIGRhdGEubGFiZWxzID0gZGF0YS5sYWJlbHMgfHwgW107XHJcbiAgLy8gZGF0YS5pbWFnZVNpemUgPSBkYXRhLmltYWdlU2l6ZSB8fCBJTUFHRV9TSVpFO1xyXG4gIHJldHVybiBkYXRhIGFzIE1ldGFkYXRhO1xyXG59O1xyXG5cclxuZXhwb3J0IGNsYXNzIFRlYWNoYWJsZU1vYmlsZU5ldCBleHRlbmRzIEN1c3RvbU1vYmlsZU5ldCB7XHJcblxyXG4gICAgLy8gQXJyYXkgb2YgYWxsIHRoZSBleGFtcGxlcyBjb2xsZWN0ZWQuXHJcbiAgICAvKipcclxuICAgICAgSXQgaXMgc3RhdGljIHNpbmNlIGFsbCB0aGUgaW5zdGFuY2Ugd2lsbCBzaGFyZSB0aGUgc2FtZSBmZWF0dXJlcywgZm9yIHNhdmluZyBtZW1vcnkgYW5kIHRpbWUuXHJcbiAgICAgIFRoZSBpZGVhIGlzIGF2b2lkaW5nIHJlc3RvcmluZyB0aGUgZmVhdHVyZXMgaW5kaXZpZHVhbGx5IGFuZCBoYXZpbmcgdGhlIHJlY2FsY3VsYXRlIHRoZW0gZm9yIGV2ZXJ5IG5ld1xyXG4gICAgICBpbmRpdmlkdWFscy5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBleGFtcGxlczogRmxvYXQzMkFycmF5W11bXSA9IFtdO1xyXG5cclxuICAgIC8vIE51bWJlciBvZiB0b3RhbCBzYW1wbGVzXHJcbiAgICBwcml2YXRlIHN0YXRpYyB0b3RhbFNhbXBsZXMgPSAwO1xyXG5cclxuICAgIGNsYXNzZXM6IENsYXNzW109W107XHJcblxyXG4gICAgc3RhdGljIGNsYXNzZXNfbmFtZXM6IHN0cmluZ1tdPVtdO1xyXG5cclxuICAgIHN0YXRpYyBudW1DbGFzc2VzOiBudW1iZXI7XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICogdGhlIHRyYWluaW5nIG1vZGVsIGZvciB0cmFuc2ZlciBsZWFybmluZ1xyXG4gICAgICovXHJcbiAgICBwcm90ZWN0ZWQgdHJhaW5pbmdNb2RlbCE6IHRmLkxheWVyc01vZGVsO1xyXG4gIHRyYWluRGF0YXNldDogYW55O1xyXG4gIHZhbGlkYXRpb25EYXRhc2V0OiBhbnk7XHJcbiAgc3RhdGljIHRyYWluRGF0YXNldDogYW55O1xyXG4gIHN0YXRpYyB2YWxpZGF0aW9uRGF0YXNldDogYW55O1xyXG4gIHN0YXRpYyBudW1WYWxpZGF0aW9uOiBudW1iZXI7XHJcblxyXG4gIGNvbnN0cnVjdG9yKCl7XHJcbiAgICBzdXBlcigpO1xyXG4gICAgdGhpcy5jcmVhdGVIZWFkKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUaGlzIG1ldGhvZCB3aWxsIHJldHVybiB0aGUgaGVhZCwgdGhlIHRyYWluYWJsZSBwYXJ0LCB0aGUgcGFydCB1bmRlciBldm9sdXRpb24uXHJcbiAgICovXHJcbiAgZ2V0SGVhZCgpe1xyXG4gICAgcmV0dXJuIHRoaXMudHJhaW5pbmdNb2RlbDtcclxuICB9XHJcblxyXG4gLyoqXHJcbiAgKiBDcmVhdGUgdGhlIGhlYWQgZm9yIHRyYW5zZmVyIGxlYXJuaW5nLlxyXG4gICogVGhpcyBpcyB0aGUgdHJhaW5hYmxlIHNlY3Rpb24gb2YgdGhlIHRyYW5zZmVyIGxlYXJuaW5nLlxyXG4gICovXHJcbiBjcmVhdGVIZWFkKCl7XHJcblxyXG4gIGNvbnN0IGlucHV0U2l6ZT0gVGVhY2hhYmxlTW9iaWxlTmV0LmdldGlucHV0U2hhcGUoKTtcclxuXHJcbiAgdGhpcy50cmFpbmluZ01vZGVsID0gdGYuc2VxdWVudGlhbCh7XHJcbiAgICBsYXllcnM6IFtcclxuICAgICAgdGYubGF5ZXJzLmRlbnNlKHtcclxuICAgICAgICBpbnB1dFNoYXBlOiBbaW5wdXRTaXplXSxcclxuICAgICAgICB1bml0czoxMDAsXHJcbiAgICAgICAgYWN0aXZhdGlvbjogJ3JlbHUnLCAgXHJcbiAgICAgICAgdXNlQmlhczogdHJ1ZVxyXG4gICAgfSksXHJcbiAgICB0Zi5sYXllcnMuZGVuc2UoeyAgXHJcbiAgICAgIHVzZUJpYXM6IGZhbHNlLFxyXG4gICAgICBhY3RpdmF0aW9uOiAnc29mdG1heCcsXHJcbiAgICAgIHVuaXRzOiBUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lcy5sZW5ndGhcclxuICB9KVxyXG4gICAgXVxyXG4gIH0pO1xyXG5cclxuICBjb25zdCBvcHRpbWl6ZXIgPSB0Zi50cmFpbi5hZGFtKCk7XHJcbiAgLy8gY29uc3Qgb3B0aW1pemVyID0gdGYudHJhaW4ucm1zcHJvcChwYXJhbXMubGVhcm5pbmdSYXRlKTtcclxuXHJcbiAgdGhpcy50cmFpbmluZ01vZGVsLmNvbXBpbGUoe1xyXG4gICAgICBvcHRpbWl6ZXIsXHJcbiAgICAgIC8vIGxvc3M6ICdiaW5hcnlDcm9zc2VudHJvcHknLFxyXG4gICAgICBsb3NzOiAnY2F0ZWdvcmljYWxDcm9zc2VudHJvcHknLFxyXG4gICAgICBtZXRyaWNzOiBbJ2FjY3VyYWN5J11cclxuICB9KTtcclxuIH1cclxuIFxyXG4gYXN5bmMgIHRyYWluKCl7XHJcblxyXG4gIGNvbnN0IHRyYWluaW5nU3VyZmFjZSA9IHsgbmFtZTogJ0xvc3MgYW5kIE1TRScsIHRhYjogJ1RyYWluaW5nJyB9O1xyXG5cclxuICBjb25zdCBkYXRhc2V0PSBUZWFjaGFibGVNb2JpbGVOZXQuY29udmVydFRvVGZEYXRhc2V0KCk7XHJcblxyXG4gIC8vU2FsdmluZyBhIGNvcHkgb2YgdGhlIHZhbGlkYXRpb24gZGF0YXNldCwgZm9yIGxhdGVyXHJcbiAgVGVhY2hhYmxlTW9iaWxlTmV0LnZhbGlkYXRpb25EYXRhc2V0PSBkYXRhc2V0LnZhbGlkYXRpb25EYXRhc2V0O1xyXG5cclxuICAvLyBjb25zb2xlLmxvZyhcIkRhdGFzZXQgZm9yIHRyYWluaW5nOiBcIiwgZGF0YXNldC50cmFpbkRhdGFzZXQpO1xyXG5cclxuICBjb25zdCB0cmFpbkRhdGEgPSBkYXRhc2V0LnRyYWluRGF0YXNldC5iYXRjaCgzMCk7XHJcbiAgY29uc3QgdmFsaWRhdGlvbkRhdGEgPSBkYXRhc2V0LnZhbGlkYXRpb25EYXRhc2V0LmJhdGNoKDEwKTtcclxuXHJcbiAgLy8gdGhpcy5jcmVhdGVIZWFkKCk7XHJcblxyXG4gIGNvbnN0IGNhbGxiYWNrcz0gW1xyXG4gICAgLy8gU2hvdyBvbiBhIHRmanMtdmlzIHZpc29yIHRoZSBsb3NzIGFuZCBhY2N1cmFjeSB2YWx1ZXMgYXQgdGhlIGVuZCBvZiBlYWNoIGVwb2NoLlxyXG4gICAgdGZ2aXMuc2hvdy5maXRDYWxsYmFja3ModHJhaW5pbmdTdXJmYWNlLCBbJ2xvc3MnLCAnYWNjJywgXCJ2YWxfbG9zc1wiLCBcInZhbF9hY2NcIl0sXHJcbiAgICAgIHtcclxuICAgICAgICBjYWxsYmFja3M6IFsnb25FcG9jaEVuZCddLFxyXG4gICAgICB9XHJcbiAgICApLFxyXG4gICAge30sXVxyXG5cclxuICBjb25zdCBoaXN0b3J5OiBhbnkgPSBhd2FpdCB0aGlzLnRyYWluaW5nTW9kZWwuZml0RGF0YXNldCh0cmFpbkRhdGEsIHtcclxuICAgIGVwb2NoczogMTAwLFxyXG4gICAgdmFsaWRhdGlvbkRhdGEsXHJcbiAgICBjYWxsYmFja3NcclxufSkudGhlbigoaW5mbzphbnkpPT57XHJcbiAgIGNvbnNvbGUubG9nKCdQcmVjaXPDo28gZmluYWwnLCBpbmZvLmhpc3RvcnkudmFsX2FjY1tpbmZvLmhpc3RvcnkuYWNjLmxlbmd0aC0xXSk7XHJcbn0pO1xyXG5cclxuXHJcbi8vIGF3YWl0IHRoaXMuYWNjdXJhY3lfcGVyX2NsYXNzKCk7XHJcblxyXG5cclxuLy8gY29uc29sZS5sb2coXCJIaXN0b3J5OiBcIiwgaGlzdG9yeS5oaXN0b3J5LmFjYyk7XHJcbiAgLy8gYXdhaXQgdGhpcy50cmFpbmluZ01vZGVsLmZpdCh0aGlzLmZlYXR1cmVYLCB0aGlzLnRhcmdldCwge30pXHJcbiB9XHJcblxyXG5hc3luYyBhY2N1cmFjeV9wZXJfY2xhc3MoY29uZnVzaW9uX21hdHJpeF9yZWNpcGllbnQ6IGFueSl7XHJcbiAgLyoqQ2FsY3VsYXRpbmcgQWNjdXJhY3kgcGVyIGNsYXNzICovXHJcbmNvbnN0IGFjY3VyYWN5cGVyY2xhc3M6IGFueSA9ICBhd2FpdCB0aGlzLmNhbGN1bGF0ZUFjY3VyYWN5UGVyQ2xhc3MoVGVhY2hhYmxlTW9iaWxlTmV0LnZhbGlkYXRpb25EYXRhc2V0KTtcclxuLy8gY29uc29sZS5sb2coXCJBY2N1cmFjeSBwZXIgY2xhc3M6IFwiLCBhY2N1cmFjeXBlcmNsYXNzKTtcclxuXHJcbi8vQ29uZnVzaW9uIG1hdHJpeFxyXG4vLyBDYWxsaW5nIHRmLmNvbmZ1c2lvbk1hdHJpeCgpIG1ldGhvZCBcclxuY29uc3Qgb3V0cHV0ID0gdGYubWF0aC5jb25mdXNpb25NYXRyaXgoIGFjY3VyYWN5cGVyY2xhc3MucmVmZXJlbmNlLCBhY2N1cmFjeXBlcmNsYXNzLnByZWRpY3Rpb25zLCBUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lcy5sZW5ndGgpOyBcclxuICBcclxuLy8gUHJpbnRpbmcgb3V0cHV0IFxyXG5vdXRwdXQucHJpbnQoKVxyXG5jb25zdCBjb25mdXNpb25fbWF0cml4PSAgb3V0cHV0LmRhdGFTeW5jKCk7XHJcblxyXG4vLyBjb25zb2xlLmxvZyhjb25mdXNpb25fbWF0cml4KTtcclxuLy8gY29uc29sZS5sb2coY29uZnVzaW9uX21hdHJpeFtUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lcy5sZW5ndGggKyBUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lcy5sZW5ndGhdKTtcclxuXHJcbmNvbnN0IGFjY3VyYWN5ID0gW107XHJcblxyXG5mb3IobGV0IGk9MDsgaTxUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lcy5sZW5ndGg7aSsrKXtcclxuXHJcbiAgYWNjdXJhY3kucHVzaChjb25mdXNpb25fbWF0cml4W1RlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aCppKyBpXS9UZWFjaGFibGVNb2JpbGVOZXQubnVtVmFsaWRhdGlvbilcclxufVxyXG5cclxuY29uc29sZS5sb2coXCJBY2N1cmFjeSBwZXIgY2xhc3M6IFwiLCBhY2N1cmFjeSk7XHJcblxyXG5mb3IobGV0IGk9MDsgaTxUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lcy5sZW5ndGg7aSsrKXtcclxuXHJcbiAgY29uZnVzaW9uX21hdHJpeF9yZWNpcGllbnQucHVzaChbXSk7XHJcblxyXG4gIGZvcihsZXQgaj0wOyBqPFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aDtqKyspe1xyXG4gICAgY29uZnVzaW9uX21hdHJpeF9yZWNpcGllbnRbaV0ucHVzaChbXSk7XHJcblxyXG4gICAgY29uZnVzaW9uX21hdHJpeF9yZWNpcGllbnRbaV1bal09IGNvbmZ1c2lvbl9tYXRyaXhbVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoKmkrIGpdL1RlYWNoYWJsZU1vYmlsZU5ldC5udW1WYWxpZGF0aW9uXHJcbiAgICBjb25mdXNpb25fbWF0cml4X3JlY2lwaWVudFtpXVtqXT0oY29uZnVzaW9uX21hdHJpeF9yZWNpcGllbnRbaV1bal0udG9GaXhlZCgyKSkqMTAwO1xyXG4gIH1cclxuXHJcbiAgLy8gYWNjdXJhY3kucHVzaChjb25mdXNpb25fbWF0cml4W1RlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aCppKyBpXS9UZWFjaGFibGVNb2JpbGVOZXQubnVtVmFsaWRhdGlvbilcclxufVxyXG5cclxuY29uc29sZS5sb2coXCJDb25mdXNpb24gbWF0cml4IGFzIGEgbWF0cml4XCIpXHJcbmNvbnNvbGUubG9nKGNvbmZ1c2lvbl9tYXRyaXhfcmVjaXBpZW50KTtcclxuXHJcbnJldHVybiBhY2N1cmFjeS5tYXAoKGVsZW06IGFueSk9PmVsZW0udG9GaXhlZCgyKSoxMDApO1xyXG59XHJcblxyXG4gXHJcbiBhc3luYyBsb2FkSW1hZ2VzKG51bWJlcl9vZl9zcGVjaWVzOiBudW1iZXIsIGNsYXNzZXNfbmFtZXM6IHN0cmluZ1tdLCBvcHRpb25zOiBvYmplY3Qpe1xyXG4gICAgICAgIFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzPWNsYXNzZXNfbmFtZXM7XHJcbiAgICBcclxuICAgICAgICBhd2FpdCB0aGlzLmFkZF9zcGVjaWVzKG51bWJlcl9vZl9zcGVjaWVzLCBvcHRpb25zKTsgICAgICAgIFxyXG5cclxufVxyXG5cclxuYXN5bmMgYWRkX3NwZWNpZXMobnVtYmVyX29mX3NwZWNpZXM6IG51bWJlciwgb3B0aW9uczogb2JqZWN0KXtcclxuICBcclxuICAgIC8vTG9hZGluZyBmZWF0dXJlIG1vZGVsLCB1c2VkIHRvIGNyZWF0ZSBmZWF0dXJlcyBmcm9tIGltYWdlc1xyXG4gICAgLy8gIGF3YWl0IHRoaXMubG9hZEZlYXR1cmVNb2RlbCgpO1xyXG5cclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgLy8gdGhpcy5hZGRfaW1hZ2VzKHRoaXMuY2xhc3Nlc19uYW1lc1tpXSwgbnVtYmVyX29mX3NwZWNpZXMsIG9wdGlvbnMpO1xyXG4gICAgfVxyXG59XHJcblxyXG4vKipcclxuICogXHJcbiAqIEBwYXJhbSBuYW1lIC0gbmFtZSBvZiB0aGUgY2xhc3MgcmVjZWl2aW5nIGFuIGV4YW1wbGVcclxuICogQHBhcmFtIG51bWJlcl9vZl9zcGVjaWVzIC0gaG93IG1hbnkgaW1hZ2VzIHRvIGFkZFxyXG4gKiBAcGFyYW0gb3B0aW9ucyAtIGRldGFpbHMgb24gdGhlIGxvY2F0aW9uIG9mIHRoZSBpbWFnZXNcclxuICovXHJcbmFzeW5jIGFkZF9pbWFnZXMobmFtZTogc3RyaW5nLCBudW1iZXJfb2Zfc3BlY2llczogbnVtYmVyLCBvcHRpb25zOiBhbnkpeyAgIFxyXG5cclxuICAgIGNvbnN0IGNsYXNzX2FkZDogYW55PSBbXTtcclxuXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bWJlcl9vZl9zcGVjaWVzOyBpKyspIHsgICAgICBcclxuICAgIC8vICAgY2xhc3NfYWRkLnB1c2goYCR7b3B0aW9ucy5iYXNlfS8ke25hbWV9LyR7b3B0aW9ucy5maWxlX25hbWV9ICR7aX0uJHtvcHRpb25zLmZpbGVfZXh0ZW5zaW9ufWApO1xyXG4gICAgICAgIFxyXG4gICAgICAgIC8vVXBsb2FkaW5nIGltYWdlc1xyXG4gICAgICAgIGNvbnN0IGNha2UgPSBuZXcgSW1hZ2UoKTsgICAgICAgIFxyXG4gICAgICAgIC8vIGNha2Uuc3JjID0gYCR7b3B0aW9ucy5iYXNlfS8ke25hbWV9LyR7b3B0aW9ucy5maWxlX25hbWV9ICR7aX0uJHtvcHRpb25zLmZpbGVfZXh0ZW5zaW9ufWA7XHJcbiAgICAgICAgY2FrZS5oZWlnaHQ9MjI0O1xyXG4gICAgICAgIGNha2Uud2lkdGg9MjI0O1xyXG4gICAgICAgIGNha2Uuc3JjPVwiLi9hc3NldHMvZGF0YXNldC9DYW4lQzMlQTFyaW8tZGEtVGVycmEvaW1hZ2UlMjAwLmpwZWdcIlxyXG4gICAgICAgIC8vIGNvbnNvbGUubG9nKFwiSW1hZ2UgbG9jYXRpb246IFwiLCBjYWtlLnNyYyApXHJcblxyXG4gICAgICAgIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgICAgICAgICAgY2FrZS5vbmxvYWQgPSAoKSA9PiB7XHJcblxyXG4gICAgICAgICAgICAgICAgLy9GaW5kaW5nIHRoZSBjb3JyZXNwb25kZW50IGluZGV4IG9mIHRoZSBjbGFzcyB3aXRoIG5hbWUgZ2l2ZW5cclxuICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4PSBUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lcy5maW5kSW5kZXgoKGVsZW0pPT5lbGVtPT09bmFtZSlcclxuXHJcbiAgICAgICAgICAgICAgICAvLyB0aGlzLmFkZEV4YW1wbGUoaW5kZXgsIGNha2UpO1xyXG5cclxuICAgICAgICAgICAgICByZXNvbHZlKCk7XHJcbiAgICAgICAgICAgIH07XHJcbiAgXHJcbiAgICAgICAgICAgIGNha2Uub25lcnJvciA9IChlcnJvcikgPT4ge1xyXG4gICAgICAgICAgICAgIC8vIEhhbmRsZSBlcnJvciBpZiB0aGUgaW1hZ2UgZmFpbHMgdG8gbG9hZFxyXG4gICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICB9KTtcclxuICB9XHJcblxyXG4gIC8vIHRoaXMuY2xhc3Nlcy5wdXNoKHtuYW1lOiBuYW1lLCBpbWFnZXM6IGNsYXNzX2FkZH0pICBcclxuXHJcbiAgfVxyXG5cclxuXHJcblxyXG4gICAgICBcclxuLyoqXHJcbiAqIFRoaXMgbWV0aG9kIHdpbGwgdHJhbnNmb3JtIGltYWdlcyBpbnRvIHRlbnNvcnNcclxuICogQHBhcmFtIG51bWJlcl9vZl9jbGFzc2VzIC0gbnVtYmVyIG9mIGNsYXNzZXNcclxuICogQHBhcmFtIGNsYXNzZXNfbmFtZXMgLSBuYW1lIG9mIGVhY2ggY2xhc3NcclxuICovXHJcbmFzeW5jIGNyZWF0ZVRlbnNvcnMobnVtYmVyX29mX2NsYXNzZXM6IG51bWJlciwgY2xhc3Nlc19uYW1lczogc3RyaW5nW10pIHtcclxuXHJcbiAgICBsZXQgb3V0cHV0OiBhbnkgPSBbXTtcclxuXHJcbiAgICAvKiogVGhlcmUgaXMgYSBmdW5jdGlvbiBvbiBUZW5zb3JGbG93LmpzIHRoYXQgYWxzbyBkb2VzIHRoYXQgKi9cclxuICAgIGNvbnN0IHNpZ25hdHVyZXM9IG5ldyBVdGlsKCkuaWRlbnRpdHlNYXRyaXgobnVtYmVyX29mX2NsYXNzZXMpO1xyXG5cclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyX29mX2NsYXNzZXM7IGkrKykge1xyXG5cclxuICAgICAgICB0aGlzLmNsYXNzZXNbaV0uc2lnbmF0dXJlPXNpZ25hdHVyZXNbaV07XHJcbiAgICAgICAgdGhpcy5jbGFzc2VzW2ldLm5hbWU9Y2xhc3Nlc19uYW1lc1tpXTtcclxuXHJcbiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLmNsYXNzZXNbaV0uaW1hZ2VzLmxlbmd0aDsgaisrKSB7XHJcblxyXG5cclxuICAgICAgICB9XHJcblxyXG4gICAgfVxyXG59XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBBZGQgYSBzYW1wbGUgb2YgZGF0YSB1bmRlciB0aGUgcHJvdmlkZWQgY2xhc3NOYW1lXHJcbiAgICAgKiBAcGFyYW0gY2xhc3NOYW1lIHRoZSBjbGFzc2lmaWNhdGlvbiB0aGlzIGV4YW1wbGUgYmVsb25ncyB0b1xyXG4gICAgICogQHBhcmFtIHNhbXBsZSB0aGUgaW1hZ2UgLyB0ZW5zb3IgdGhhdCBiZWxvbmdzIGluIHRoaXMgY2xhc3NpZmljYXRpb25cclxuICAgICAqL1xyXG4gICAgLy8gcHVibGljIGFzeW5jIGFkZEV4YW1wbGUoY2xhc3NOYW1lOiBudW1iZXIsIHNhbXBsZTogSFRNTENhbnZhc0VsZW1lbnQgfCB0Zi5UZW5zb3IpIHtcclxucHVibGljIHN0YXRpYyBhc3luYyBhZGRFeGFtcGxlKGNsYXNzTmFtZTogbnVtYmVyLCBuYW1lOiBzdHJpbmcsIHNhbXBsZTogSFRNTEltYWdlRWxlbWVudCB8IEhUTUxDYW52YXNFbGVtZW50IHwgdGYuVGVuc29yKSB7XHJcblxyXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkFkZGluZyBhIG5ldyBleGFtcGxlLi4uXCIpIFxyXG4gICAgICAgICAgXHJcbiAgICAgICAgICAgIGNvbnN0IGNhcCA9IGlzVGVuc29yKHNhbXBsZSkgPyBzYW1wbGUgOiBjYXB0dXJlKHNhbXBsZSk7XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAvLyBpZighdGhpcy50cnVuY2F0ZWRNb2RlbClcclxuICAgICAgICAgICAgLy8gICBhd2FpdCB0aGlzLmxvYWRGZWF0dXJlTW9kZWwoKTtcclxuXHJcbiAgICAgICAgICAgIC8vR2V0dGluZyB0aGUgZmVhdHVyZXNcclxuICAgICAgICAgICAgY29uc3QgZXhhbXBsZSA9IHRoaXMudHJ1bmNhdGVkTW9kZWwucHJlZGljdChjYXApIGFzIHRmLlRlbnNvcjtcclxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJTaGFwZSBhZnRlciBmZWF0dXJlIGV4dHJhY3Rpb246IFwiLCBleGFtcGxlLnNoYXBlKSAgICAgICAgICBcclxuICAgICAgICAgICBcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGFjdGl2YXRpb24gPSBleGFtcGxlLmRhdGFTeW5jKCkgYXMgRmxvYXQzMkFycmF5O1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgLy9WZXJ5IGltcG9ydGFudCB0byBjbGVhbiB0aGUgbWVtb3J5IGFmdGVybWF0aCwgaXQgbWFrZXMgdGhlIGRpZmZlcmVuY2VcclxuICAgICAgICAgICAgY2FwLmRpc3Bvc2UoKTtcclxuICAgICAgICAgICAgZXhhbXBsZS5kaXNwb3NlKCk7XHJcbiAgICBcclxuICAgICAgICAgICAgLy8gLy9BY2Nlc3NpbmcgdGhlIGluc3RhbmNlIHZhcmlhYmxlLCBub3QgdGhlIGxvY2FsIG9uZXNcclxuICAgICAgICAgICAgLy8gLy8gc2F2ZSBzYW1wbGVzIG9mIGVhY2ggY2xhc3Mgc2VwYXJhdGVseSBcclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIGlmKCFUZWFjaGFibGVNb2JpbGVOZXQuZXhhbXBsZXNbY2xhc3NOYW1lXSlcclxuICAgICAgICAgICAgICAvL2FuZCBhbiBlbXB0eSBhcnJheSwgbWFrZSBzdXJlIHRoZXJlIGlzIG5vdCBlbXB0eSBlbGVtZW50cy4gXHJcbiAgICAgICAgICAgICAgLy9pdCB3aWxsIGNyZWF0ZSBpc3N1ZSB3aGVuIHRyYW5zZm9ybWluZyB0byB0ZW5zb3JzXHJcbiAgICAgICAgICAgICAgVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzW2NsYXNzTmFtZV09W11cclxuXHJcblxyXG4gICAgICAgICAgICAgIGlmKCFUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lc1tjbGFzc05hbWVdKVxyXG4gICAgICAgICAgICAgICAgLy9TYXZpbmcgdGhlIGxhYmxlIHdoZW4gaXQgZmlyc3QgYXBwZWFyc1xyXG4gICAgICAgICAgICAgICAgVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXNbY2xhc3NOYW1lXT1uYW1lO1xyXG5cclxuICAgICAgICAgICAgVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzW2NsYXNzTmFtZV0ucHVzaChhY3RpdmF0aW9uKTtcclxuICAgIFxyXG4gICAgICAgICAgICAvLyAvLyBpbmNyZWFzZSBvdXIgc2FtcGxlIGNvdW50ZXJcclxuICAgICAgICAgICAgVGVhY2hhYmxlTW9iaWxlTmV0LnRvdGFsU2FtcGxlcysrO1xyXG4gICAgICAgIH1cclxuXHJcblxyXG4gICAvKipcclxuICAgICAqIHByb2Nlc3MgdGhlIGN1cnJlbnQgZXhhbXBsZXMgcHJvdmlkZWQgdG8gY2FsY3VsYXRlIGxhYmVscyBhbmQgZm9ybWF0XHJcbiAgICAgKiBpbnRvIHByb3BlciB0Zi5kYXRhLkRhdGFzZXRcclxuICAgICAqL1xyXG4gICBzdGF0aWMgcHJlcGFyZSgpIHtcclxuICAgIGZvciAoY29uc3QgY2xhc3NlcyBpbiBUZWFjaGFibGVNb2JpbGVOZXQuZXhhbXBsZXMpe1xyXG4gICAgICAgIGlmIChjbGFzc2VzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FkZCBzb21lIGV4YW1wbGVzIGJlZm9yZSB0cmFpbmluZycpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBkYXRhc2V0czogYW55ID0gdGhpcy5jb252ZXJ0VG9UZkRhdGFzZXQoKTtcclxuXHJcbiAgICB0aGlzLnRyYWluRGF0YXNldCA9IGRhdGFzZXRzLnRyYWluRGF0YXNldDtcclxuICAgIHRoaXMudmFsaWRhdGlvbkRhdGFzZXQgPSBkYXRhc2V0cy52YWxpZGF0aW9uRGF0YXNldDtcclxufVxyXG5cclxucHVibGljIHByZXBhcmVEYXRhc2V0KCkge1xyXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgVGVhY2hhYmxlTW9iaWxlTmV0Lm51bUNsYXNzZXM7IGkrKykge1xyXG4gICAgLy9EaWZmZXJlbnQgZnJvbSB0aGUgb3JpZ2luYWwgaW1wbGVtZW50YXRpb24gb2YgVE0sIG1pbmUgaXMgdXNpbmcgZXhhbXBsZSBhcyBzdGF0aWMuXHJcbiAgICAvL1RoZSBnb2FsIGlzIHNhdmluZyBtZW1vcnkgYnkgdXNpbmcgYSBzaW5nbGUgaW5zdGFuY2Ugb2YgdGhlIHZhcmlhYmxlXHJcbiAgICBUZWFjaGFibGVNb2JpbGVOZXQuZXhhbXBsZXNbaV0gPSBbXTtcclxuICB9XHJcbn1cclxuXHJcbiBcclxuICAgIC8vIE9wdGlvbmFsIHNlZWQgdG8gbWFrZSBzaHVmZmxpbmcgb2YgZGF0YSBwcmVkaWN0YWJsZVxyXG4gICAgc3RhdGljIHNlZWQ6IHNlZWRyYW5kb20ucHJuZztcclxuXHJcblxyXG5cclxuICAgIFxyXG4vKipcclxuICAgICAqIFByb2Nlc3MgdGhlIGV4YW1wbGVzIGJ5IGZpcnN0IHNodWZmbGluZyByYW5kb21seSBwZXIgY2xhc3MsIHRoZW4gYWRkaW5nXHJcbiAgICAgKiBvbmUtaG90IGxhYmVscywgdGhlbiBzcGxpdHRpbmcgaW50byB0cmFpbmluZy92YWxpZGF0aW9uIGRhdHNldHMsIGFuZCBmaW5hbGx5XHJcbiAgICAgKiBzb3J0aW5nIG9uZSBsYXN0IHRpbWVcclxuICAgICAqL1xyXG4gXHJcbnN0YXRpYyBjb252ZXJ0VG9UZkRhdGFzZXQoKSB7XHJcblxyXG4gICAgICAgICAvLyBmaXJzdCBzaHVmZmxlIGVhY2ggY2xhc3MgaW5kaXZpZHVhbGx5XHJcbiAgICAgICAgLy8gVE9ETzogd2UgY291bGQgYmFzaWNhbGx5IHJlcGxpY2F0ZSB0aGlzIGJ5IGluc3RlcnRpbmcgcmFuZG9tbHlcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IFRlYWNoYWJsZU1vYmlsZU5ldC5leGFtcGxlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzW2ldID0gZmlzaGVyWWF0ZXMoVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzW2ldLCB0aGlzLnNlZWQpIGFzIEZsb2F0MzJBcnJheVtdO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyB0aGVuIGJyZWFrIGludG8gdmFsaWRhdGlvbiBhbmQgdGVzdCBkYXRhc2V0c1xyXG4gICAgICBsZXQgdHJhaW5EYXRhc2V0OiBTYW1wbGVbXSA9IFtdO1xyXG4gICAgICBsZXQgdmFsaWRhdGlvbkRhdGFzZXQ6IFNhbXBsZVtdID0gW107XHJcblxyXG4gICAgICAvLyBmb3IgZWFjaCBjbGFzcywgYWRkIHNhbXBsZXMgdG8gdHJhaW4gYW5kIHZhbGlkYXRpb24gZGF0YXNldFxyXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IFRlYWNoYWJsZU1vYmlsZU5ldC5leGFtcGxlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICBcclxuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIk51bWJlciBvZiBjbGFzc2VzOiBcIiwgVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoKTtcclxuXHJcbiAgICAgICAgY29uc3QgeSA9IGZsYXRPbmVIb3QoaSwgVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoKTtcclxuXHJcbiAgICAgICAgY29uc3QgY2xhc3NMZW5ndGggPSBUZWFjaGFibGVNb2JpbGVOZXQuZXhhbXBsZXNbaV0ubGVuZ3RoO1xyXG5cclxuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIk51bWJlciBvZiBlbGVtZW50cyBwZXIgY2xhc3M6IFwiLCBjbGFzc0xlbmd0aCk7XHJcblxyXG4gICAgICAgIGNvbnN0IG51bVZhbGlkYXRpb24gPSBNYXRoLmNlaWwoVkFMSURBVElPTl9GUkFDVElPTiAqIGNsYXNzTGVuZ3RoKTtcclxuICAgICAgICBjb25zdCBudW1UcmFpbiA9IGNsYXNzTGVuZ3RoIC0gbnVtVmFsaWRhdGlvbjtcclxuXHJcbiAgICAgICAgdGhpcy5udW1WYWxpZGF0aW9uPW51bVZhbGlkYXRpb247XHJcbiAgICAgICBcclxuICAgICAgICAvKipJdCBpcyB2aXNpdGluZyBwZXIgY2xhc3MsIHRodXMsIGl0IGlzIHBvc3NpYmxlIHRvIGZpeCB5LCB0aGUgdGFyZ2V0IGxhYmVsICovXHJcbiAgICAgXHJcbiAgICAgIGNvbnN0IGNsYXNzVHJhaW4gPSB0aGlzLmV4YW1wbGVzW2ldLnNsaWNlKDAsIG51bVRyYWluKS5tYXAoKGRhdGFBcnJheSkgPT4ge1xyXG4gICAgICAgICAgcmV0dXJuIHsgZGF0YTogZGF0YUFycmF5LCBsYWJlbDogeSB9O1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIGNvbnN0IGNsYXNzVmFsaWRhdGlvbiA9IHRoaXMuZXhhbXBsZXNbaV0uc2xpY2UobnVtVHJhaW4pLm1hcCgoZGF0YUFycmF5KSA9PiB7XHJcbiAgICAgICAgICByZXR1cm4geyBkYXRhOiBkYXRhQXJyYXksIGxhYmVsOiB5IH07XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdHJhaW5EYXRhc2V0ID0gdHJhaW5EYXRhc2V0LmNvbmNhdChjbGFzc1RyYWluKTtcclxuICAgICAgdmFsaWRhdGlvbkRhdGFzZXQgPSB2YWxpZGF0aW9uRGF0YXNldC5jb25jYXQoY2xhc3NWYWxpZGF0aW9uKTsgXHJcblxyXG5cclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gY29uc29sZS5sb2coXCJUcmFpbmluZyBlbGVtZW50OiBcIiwgdHJhaW5EYXRhc2V0W3RyYWluRGF0YXNldC5sZW5ndGgtMV0pICAgICAgXHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKFwiVHJhaW5pbmcgbGVuZ3RoOiBcIiwgdHJhaW5EYXRhc2V0Lmxlbmd0aClcclxuICAgICAgLy8gY29uc29sZS5sb2coXCJ2YWxpZGF0aW9uIGxlbmd0aDogXCIsIHZhbGlkYXRpb25EYXRhc2V0Lmxlbmd0aCk7XHJcblxyXG4gICAgICBcclxuICAgICAgICAvLyBmaW5hbGx5IHNodWZmbGUgYm90aCB0cmFpbiBhbmQgdmFsaWRhdGlvbiBkYXRhc2V0c1xyXG4gICAgICAgIHRyYWluRGF0YXNldCA9IGZpc2hlcllhdGVzKHRyYWluRGF0YXNldCwgdGhpcy5zZWVkKSBhcyBTYW1wbGVbXTtcclxuICAgICAgICB2YWxpZGF0aW9uRGF0YXNldCA9IGZpc2hlcllhdGVzKHZhbGlkYXRpb25EYXRhc2V0LCB0aGlzLnNlZWQpIGFzIFNhbXBsZVtdO1xyXG5cclxuICAgICAgICBjb25zdCB0cmFpblggPSB0Zi5kYXRhLmFycmF5KHRyYWluRGF0YXNldC5tYXAoc2FtcGxlID0+IHNhbXBsZS5kYXRhKSk7XHJcbiAgICAgICAgY29uc3QgdmFsaWRhdGlvblggPSB0Zi5kYXRhLmFycmF5KHZhbGlkYXRpb25EYXRhc2V0Lm1hcChzYW1wbGUgPT4gc2FtcGxlLmRhdGEpKTtcclxuICAgICAgICBjb25zdCB0cmFpblkgPSB0Zi5kYXRhLmFycmF5KHRyYWluRGF0YXNldC5tYXAoc2FtcGxlID0+IHNhbXBsZS5sYWJlbCkpO1xyXG4gICAgICAgIGNvbnN0IHZhbGlkYXRpb25ZID0gdGYuZGF0YS5hcnJheSh2YWxpZGF0aW9uRGF0YXNldC5tYXAoc2FtcGxlID0+IHNhbXBsZS5sYWJlbCkpO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIHJldHVybiB0Zi5kYXRhIGRhdGFzZXQgb2JqZWN0c1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgICAgdHJhaW5EYXRhc2V0OiB0Zi5kYXRhLnppcCh7IHhzOiB0cmFpblgsICB5czogdHJhaW5ZfSksXHJcbiAgICAgICAgICAgICAgICAgIHZhbGlkYXRpb25EYXRhc2V0OiB0Zi5kYXRhLnppcCh7IHhzOiB2YWxpZGF0aW9uWCwgIHlzOiB2YWxpZGF0aW9uWX0pXHJcbiAgICAgICAgICAgICAgfTtcclxuXHJcblxyXG59XHJcblxyXG5kYXRhc2V0Rm9yRXZhbHVhdGlvbigpe1xyXG5cclxufVxyXG5cclxuLyoqTWV0cmljcyAqL1xyXG5cclxuc3RhdGljIGZlYXR1cmVfYXV4OiBhbnk7XHJcbnN0YXRpYyB0YXJnZXRfYXV4OiBhbnk7XHJcblxyXG5hc3luYyBldmFsdWF0ZSgpe1xyXG4gICBcclxuICBpZighVGVhY2hhYmxlTW9iaWxlTmV0LmZlYXR1cmVfYXV4KXtcclxuICAgIGNvbnN0IGZlYXR1cmVzOiBhbnk9W107XHJcbiAgY29uc3QgdGFyZ2V0czogYW55PVtdO1xyXG5cclxuICBmb3IgKGxldCBpID0gMDsgaSA8IFRlYWNoYWJsZU1vYmlsZU5ldC5leGFtcGxlcy5sZW5ndGg7IGkrKykge1xyXG5cclxuICAgIGNvbnN0IHkgPSBmbGF0T25lSG90KGksIFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aCk7XHJcbiAgICBcclxuXHJcblxyXG4gICAgLy9Gb3IgY2xhc3MgaSwgcHVzaCBhbGwgdGhlIGV4YW1wbGVzLlxyXG4gICAgVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzW2ldLmZvckVhY2goKGVsZW1uKT0+e1xyXG5cclxuICAgICAgIC8vUHVzaGluZyB0aGUgdGFyZ2V0IHNpZ25hdHVyZVxyXG4gICAgICAgdGFyZ2V0cy5wdXNoKHkpO1xyXG4gICAgICAgXHJcbiAgICAgICAvL1B1c2hpbmcgZmVhdHVyZXNcclxuICAgICAgIGZlYXR1cmVzLnB1c2goZWxlbW4pXHJcbiAgICB9KVxyXG5cclxuICB9ICBcclxuXHJcbiAgVGVhY2hhYmxlTW9iaWxlTmV0LmZlYXR1cmVfYXV4PSB0Zi50ZW5zb3IoZmVhdHVyZXMpO1xyXG4gIFRlYWNoYWJsZU1vYmlsZU5ldC50YXJnZXRfYXV4PSB0Zi50ZW5zb3IodGFyZ2V0cyk7XHJcblxyXG4gIH0gXHJcblxyXG4gIGNvbnN0IGF1eDogYW55ID0gdGhpcy50cmFpbmluZ01vZGVsLmV2YWx1YXRlKFRlYWNoYWJsZU1vYmlsZU5ldC5mZWF0dXJlX2F1eCwgVGVhY2hhYmxlTW9iaWxlTmV0LnRhcmdldF9hdXgpO1xyXG4gIFxyXG4gIHJldHVybiBhdXhbMV0uZGF0YVN5bmMoKVswXTtcclxuXHJcblxyXG59XHJcblxyXG5cclxuLy8gYXN5bmMgZXZhbHVhdGUoKXtcclxuXHJcbi8vICAgY29uc3QgZmVhdHVyZXM6IGFueT1bXTtcclxuLy8gICBjb25zdCB0YXJnZXRzOiBhbnk9W107XHJcblxyXG4vLyAgIGZvciAobGV0IGkgPSAwOyBpIDwgVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzLmxlbmd0aDsgaSsrKSB7XHJcblxyXG4vLyAgICAgY29uc3QgeSA9IGZsYXRPbmVIb3QoaSwgVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoKTtcclxuICAgIFxyXG5cclxuXHJcbi8vICAgICAvL0ZvciBjbGFzcyBpLCBwdXNoIGFsbCB0aGUgZXhhbXBsZXMuXHJcbi8vICAgICBUZWFjaGFibGVNb2JpbGVOZXQuZXhhbXBsZXNbaV0uZm9yRWFjaCgoZWxlbW4pPT57XHJcblxyXG4vLyAgICAgICAgLy9QdXNoaW5nIHRoZSB0YXJnZXQgc2lnbmF0dXJlXHJcbi8vICAgICAgICB0YXJnZXRzLnB1c2goeSk7XHJcbiAgICAgICBcclxuLy8gICAgICAgIC8vUHVzaGluZyBmZWF0dXJlc1xyXG4vLyAgICAgICAgZmVhdHVyZXMucHVzaChlbGVtbilcclxuLy8gICAgIH0pXHJcblxyXG4vLyAgIH0gIFxyXG5cclxuLy8gICBjb25zdCBhdXhfZmVhdHVyZXM9IHRmLnRlbnNvcihmZWF0dXJlcyk7XHJcbi8vICAgY29uc3QgYXV4X3RhcmdldD0gdGYudGVuc29yKHRhcmdldHMpO1xyXG5cclxuICBcclxuLy8gICAvLyBjb25zb2xlLmxvZyhcIlRlbnNvciBzdGFjayBmb3IgZXZhbHVhdGlvbjogXCIsIGF1eF9mZWF0dXJlcy5zaGFwZSlcclxuXHJcbi8vICAgY29uc3QgYXV4OiBhbnkgPSB0aGlzLnRyYWluaW5nTW9kZWwuZXZhbHVhdGUoYXV4X2ZlYXR1cmVzLCBhdXhfdGFyZ2V0KTtcclxuXHJcblxyXG4vLyAgIHJldHVybiBhdXhbMV0uZGF0YVN5bmMoKVswXTtcclxuXHJcblxyXG4vLyB9XHJcblxyXG5cclxuLyoqKiBGaW5hbCBzdGF0aXN0aWNzICovXHJcbi8qIFxyXG4gICAgICogQ2FsY3VsYXRlIGVhY2ggY2xhc3MgYWNjdXJhY3kgdXNpbmcgdGhlIHZhbGlkYXRpb24gZGF0YXNldFxyXG4qL1xyXG5wdWJsaWMgYXN5bmMgY2FsY3VsYXRlQWNjdXJhY3lQZXJDbGFzcyh2YWxpZGF0aW9uRGF0YTogYW55KSB7XHJcblxyXG4gIGNvbnN0IHZhbGlkYXRpb25YcyA9IFRlYWNoYWJsZU1vYmlsZU5ldC52YWxpZGF0aW9uRGF0YXNldC5tYXBBc3luYyhhc3luYyAoZGF0YXNldDogVGVuc29yQ29udGFpbmVyKSA9PiB7XHJcbiAgICByZXR1cm4gKGRhdGFzZXQgYXMgeyB4czogVGVuc29yQ29udGFpbmVyLCB5czogVGVuc29yQ29udGFpbmVyfSkueHM7XHJcbn0pO1xyXG5cclxuY29uc3QgdmFsaWRhdGlvbllzID0gVGVhY2hhYmxlTW9iaWxlTmV0LnZhbGlkYXRpb25EYXRhc2V0Lm1hcEFzeW5jKGFzeW5jIChkYXRhc2V0OiBUZW5zb3JDb250YWluZXIpID0+IHtcclxuICAgIHJldHVybiAoZGF0YXNldCBhcyB7IHhzOiBUZW5zb3JDb250YWluZXIsIHlzOiBUZW5zb3JDb250YWluZXJ9KS55cztcclxufSk7XHJcblxyXG4vLyBjb25zb2xlLmxvZyhcInZhbGlkYXRpb24gZGF0YXNldDogXCIsIHZhbGlkYXRpb25Ycyk7XHJcbiBcclxuLy8gY29uc29sZS5sb2coXCJGb3IgY2FsY3VsYXRpbmcgYmF0Y2ggc2l6ZTogXCIsIHZhbGlkYXRpb25Zcyk7XHJcblxyXG4vLyB3ZSBuZWVkIHRvIHNwbGl0IG91ciB2YWxpZGF0aW9uIGRhdGEgaW50byBiYXRjaGVzIGluIGNhc2UgaXQgaXMgdG9vIGxhcmdlIHRvIGZpdCBpbiBtZW1vcnlcclxuY29uc3QgYmF0Y2hTaXplID0gTWF0aC5taW4odmFsaWRhdGlvbllzLnNpemUsIDMyKTtcclxuLy8gY29uc3QgYmF0Y2hTaXplID0xO1xyXG5cclxuY29uc3QgaXRlcmF0aW9ucyA9IE1hdGguY2VpbCh2YWxpZGF0aW9uWXMuc2l6ZSAvIGJhdGNoU2l6ZSk7XHJcblxyXG4vLyBjb25zb2xlLmxvZyhcIkJhdGNoIHNpemU6IFwiLCBiYXRjaFNpemUpO1xyXG5cclxuY29uc3QgYmF0Y2hlc1ggPSB2YWxpZGF0aW9uWHMuYmF0Y2goYmF0Y2hTaXplKTtcclxuXHJcbmNvbnN0IGJhdGNoZXNZID0gdmFsaWRhdGlvbllzLmJhdGNoKGJhdGNoU2l6ZSk7XHJcbmNvbnN0IGl0WCA9IGF3YWl0IGJhdGNoZXNYLml0ZXJhdG9yKCk7XHJcbmNvbnN0IGl0WSA9IGF3YWl0IGJhdGNoZXNZLml0ZXJhdG9yKCk7XHJcbmNvbnN0IGFsbFggPSBbXTtcclxuY29uc3QgYWxsWSA9IFtdO1xyXG5cclxuZm9yIChsZXQgaSA9IDA7IGkgPCBpdGVyYXRpb25zOyBpKyspIHtcclxuXHJcbiAgICAvLyAxLiBnZXQgdGhlIHByZWRpY3Rpb24gdmFsdWVzIGluIGJhdGNoZXNcclxuICAgICBjb25zdCBiYXRjaGVkWFRlbnNvciA9IGF3YWl0IGl0WC5uZXh0KCk7ICBcclxuXHJcbiAgICAvLyAgY29uc29sZS5sb2coXCJCYXRjaCBzaXplIG9uIGFjY3VyYWN5IHBlciBjbGFzczogXCIsIGJhdGNoZWRYVGVuc29yLnZhbHVlLnNoYXBlKTtcclxuXHJcbiAgICBjb25zdCBiYXRjaGVkWFByZWRpY3Rpb25UZW5zb3IgPSB0aGlzLnRyYWluaW5nTW9kZWwucHJlZGljdChiYXRjaGVkWFRlbnNvci52YWx1ZSkgYXMgdGYuVGVuc29yO1xyXG5cclxuICAgIGNvbnN0IGFyZ01heFggPSBiYXRjaGVkWFByZWRpY3Rpb25UZW5zb3IuYXJnTWF4KDEpOyAvLyBSZXR1cm5zIHRoZSBpbmRpY2VzIG9mIHRoZSBtYXggdmFsdWVzIGFsb25nIGFuIGF4aXNcclxuXHJcbiAgICBhbGxYLnB1c2goYXJnTWF4WCk7XHJcblxyXG4gICAgLy8gMi4gZ2V0IHRoZSBncm91bmQgdHJ1dGggbGFiZWwgdmFsdWVzIGluIGJhdGNoZXNcclxuICAgIGNvbnN0IGJhdGNoZWRZVGVuc29yID0gYXdhaXQgaXRZLm5leHQoKTtcclxuICAgIGNvbnN0IGFyZ01heFkgPSBiYXRjaGVkWVRlbnNvci52YWx1ZS5hcmdNYXgoMSk7IC8vIFJldHVybnMgdGhlIGluZGljZXMgb2YgdGhlIG1heCB2YWx1ZXMgYWxvbmcgYW4gYXhpc1xyXG5cclxuICAgIGFsbFkucHVzaChhcmdNYXhZKTtcclxuICAgIFxyXG4gICAgLy8gMy4gZGlzcG9zZSBvZiBhbGwgb3VyIHRlbnNvcnNcclxuICAgICBiYXRjaGVkWFRlbnNvci52YWx1ZS5kaXNwb3NlKCk7XHJcbiAgICAgYmF0Y2hlZFhQcmVkaWN0aW9uVGVuc29yLmRpc3Bvc2UoKTtcclxuICAgICBiYXRjaGVkWVRlbnNvci52YWx1ZS5kaXNwb3NlKCk7XHJcbn1cclxuXHJcbiAgICAgIC8vIGNvbmNhdGVuYXRlIGFsbCB0aGUgcmVzdWx0cyBvZiB0aGUgYmF0Y2hlc1xyXG4gICAgICBjb25zdCByZWZlcmVuY2UgPSB0Zi5jb25jYXQoYWxsWSk7IC8vIHRoaXMgaXMgdGhlIGdyb3VuZCB0cnV0aFxyXG4gICAgICBjb25zdCBwcmVkaWN0aW9ucyA9IHRmLmNvbmNhdChhbGxYKTsgLy8gdGhpcyBpcyB0aGUgcHJlZGljdGlvbiBvdXIgbW9kZWwgaXMgZ3Vlc3NpbmdcclxuICAgICAgXHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKFwidGhpcyBpcyB0aGUgZ3JvdW5kIHRydXRoOiBcIiwgIHJlZmVyZW5jZS5kYXRhU3luYygpKVxyXG4gICAgICAvLyBjb25zb2xlLmxvZyhcIlRoaXMgaXMgdGhlIHByZWRpY3Rpb24gb3VyIG1vZGVsIGlzIGd1ZXNzaW5nOiBcIiwgIHByZWRpY3Rpb25zLmRhdGFTeW5jKCkpXHJcblxyXG4gICAgICAgIC8vIG9ubHkgaWYgd2UgY29uY2F0ZW5hdGVkIG1vcmUgdGhhbiBvbmUgdGVuc29yIGZvciBwcmVmZXJlbmNlIGFuZCByZWZlcmVuY2VcclxuICAgICAgICBpZiAoaXRlcmF0aW9ucyAhPT0gMSkge1xyXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFsbFgubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIGFsbFhbaV0uZGlzcG9zZSgpO1xyXG4gICAgICAgICAgICAgICAgYWxsWVtpXS5kaXNwb3NlKCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgLy8gIGNvbnNvbGUubG9nKFwiTGVuZ3R0aDogXCIsIGF3YWl0IHJlZmVyZW5jZS5kYXRhU3luYygpLmxlbmd0aCkgIFxyXG4gICAgXHJcbiAgICAvLyBjb25zdCBhY2N1cmFjeXBlcmNsYXNzPVtdO1xyXG5cclxuICAgIC8vIGNvbnN0IHJlZmVyZW5jZV9hdXg9IGF3YWl0IHJlZmVyZW5jZS5kYXRhU3luYygpO1xyXG4gICAgLy8gY29uc3QgcHJlZGljdGlvbl9hdXg9IGF3YWl0IHByZWRpY3Rpb25zLmRhdGFTeW5jKCk7XHJcbiAgICAvLyBjb25zb2xlLmxvZyggcHJlZGljdGlvbnMuZGF0YVN5bmMoKSk7XHJcblxyXG4gICAgLy8gcmVmZXJlbmNlX2F1eC5mb3JFYWNoKChlbGVtZW50LCBpbmRleCkgPT4ge1xyXG4gICAgLy8gICBpZigpXHJcbiAgICAgIFxyXG4gICAgLy8gfSk7ICBcclxuXHJcblxyXG4gICAgICAgIHJldHVybiB7IHJlZmVyZW5jZSwgcHJlZGljdGlvbnMgfTsgIFxyXG5cclxufVxyXG5cclxufS8vZW5kIG9mIGNsYXNzXHJcblxyXG5cclxuXHJcblxyXG5cclxuLyoqKlN1cHBvcnQgbWV0aG9kcyAoaGVscGVycykgKi9cclxuXHJcbmNvbnN0IGlzVGVuc29yID0gKGM6IGFueSk6IGMgaXMgdGYuVGVuc29yID0+XHJcbiAgICB0eXBlb2YgYy5kYXRhSWQgPT09ICdvYmplY3QnICYmIHR5cGVvZiBjLnNoYXBlID09PSAnb2JqZWN0JztcclxuLyoqXHJcbiAqIENvbnZlcnRzIGFuIGludGVnZXIgaW50byBpdHMgb25lLWhvdCByZXByZXNlbnRhdGlvbiBhbmQgcmV0dXJuc1xyXG4gKiB0aGUgZGF0YSBhcyBhIEpTIEFycmF5LlxyXG4gKi9cclxuZnVuY3Rpb24gZmxhdE9uZUhvdChsYWJlbDogbnVtYmVyLCBudW1DbGFzc2VzOiBudW1iZXIpIHtcclxuXHJcbiAgY29uc3QgbGFiZWxPbmVIb3QgPSBuZXcgQXJyYXkobnVtQ2xhc3NlcykuZmlsbCgwKSBhcyBudW1iZXJbXTtcclxuICBsYWJlbE9uZUhvdFtsYWJlbF0gPSAxO1xyXG5cclxuICByZXR1cm4gbGFiZWxPbmVIb3Q7XHJcbn1cclxuXHJcbmludGVyZmFjZSBTYW1wbGUge1xyXG4gIGRhdGE6IEZsb2F0MzJBcnJheTtcclxuICBsYWJlbDogbnVtYmVyW107XHJcbn1cclxuXHJcblxyXG4vKipcclxuICogU2h1ZmZsZSBhbiBhcnJheSBvZiBGbG9hdDMyQXJyYXkgb3IgU2FtcGxlcyB1c2luZyBGaXNoZXItWWF0ZXMgYWxnb3JpdGhtXHJcbiAqIFRha2VzIGFuIG9wdGlvbmFsIHNlZWQgdmFsdWUgdG8gbWFrZSBzaHVmZmxpbmcgcHJlZGljdGFibGVcclxuICovXHJcbmZ1bmN0aW9uIGZpc2hlcllhdGVzKGFycmF5OiBGbG9hdDMyQXJyYXlbXSB8IFNhbXBsZVtdLCBzZWVkPzogc2VlZHJhbmRvbS5wcm5nKSB7XHJcbiAgY29uc3QgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xyXG5cclxuICAvLyBuZWVkIHRvIGNsb25lIGFycmF5IG9yIHdlJ2QgYmUgZWRpdGluZyBvcmlnaW5hbCBhcyB3ZSBnb29cclxuICBjb25zdCBzaHVmZmxlZCA9IGFycmF5LnNsaWNlKCk7XHJcblxyXG4gIGZvciAobGV0IGkgPSAobGVuZ3RoIC0gMSk7IGkgPiAwOyBpIC09IDEpIHtcclxuICAgICAgbGV0IHJhbmRvbUluZGV4IDtcclxuICAgICAgaWYgKHNlZWQpIHtcclxuICAgICAgICAgIHJhbmRvbUluZGV4ID0gTWF0aC5mbG9vcihzZWVkKCkgKiAoaSArIDEpKTtcclxuICAgICAgfVxyXG4gICAgICBlbHNlIHtcclxuICAgICAgICAgIHJhbmRvbUluZGV4ID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogKGkgKyAxKSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIFtzaHVmZmxlZFtpXSwgc2h1ZmZsZWRbcmFuZG9tSW5kZXhdXSA9IFtzaHVmZmxlZFtyYW5kb21JbmRleF0sc2h1ZmZsZWRbaV1dO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHNodWZmbGVkO1xyXG59XHJcbiJdfQ==
430
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVhY2hhYmxlLWV2b2x1dGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RmanMtZXZvbHV0aW9uL3NyYy9saWIvbW9kZWxzL3RlYWNoYWJsZS1ldm9sdXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGVBQWUsRUFBMEIsTUFBTSxvQkFBb0IsQ0FBQztBQUU3RSxPQUFPLEtBQUssRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRXZDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFdEMsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUlyQyxPQUFPLEtBQUssS0FBSyxNQUFNLHNCQUFzQixDQUFDO0FBSTlDLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxDQUFDO0FBc0JqQzs7O0dBR0c7QUFDSCxNQUFNLFlBQVksR0FBRyxDQUFDLElBQXVCLEVBQUUsRUFBRTtJQUMvQyw4RkFBOEY7SUFDOUYsd0RBQXdEO0lBQ3hELElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFdBQVcsSUFBSSx5QkFBeUIsQ0FBQztJQUNqRSxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLElBQUksSUFBSSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUM1RCxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxZQUFZLElBQUksRUFBRSxDQUFDO0lBQzVDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsSUFBSSxVQUFVLENBQUM7SUFDOUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQztJQUNoQyxpREFBaUQ7SUFDakQsT0FBTyxJQUFnQixDQUFDO0FBQzFCLENBQUMsQ0FBQztBQUVGLE1BQU0sT0FBTyxrQkFBbUIsU0FBUSxlQUFlO0lBRW5ELHVDQUF1QztJQUN2Qzs7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USxDQUFDLFdBQVcsQ0FBQyxFQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0tBQzlFO0lBRUQsT0FBTyxRQUFRLENBQUM7QUFDbEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEN1c3RvbU1vYmlsZU5ldCwgbG9hZFRydW5jYXRlZE1vYmlsZU5ldCB9IGZyb20gXCIuL2N1c3RvbS1tb2JpbGVuZXRcIjtcclxuXHJcbmltcG9ydCAqIGFzIHRmIGZyb20gJ0B0ZW5zb3JmbG93L3RmanMnO1xyXG5cclxuaW1wb3J0IHsgY2FwdHVyZSB9IGZyb20gJy4uL3V0aWxzL3RmJztcclxuaW1wb3J0IHsgQ2xhc3MgfSBmcm9tICcuLi91dGlscy9jbGFzcyc7XHJcbmltcG9ydCB7IFV0aWwgfSBmcm9tIFwiLi4vdXRpbHMvdXRpbFwiO1xyXG5cclxuaW1wb3J0ICogYXMgc2VlZHJhbmRvbSBmcm9tICdzZWVkcmFuZG9tJztcclxuXHJcbmltcG9ydCAqIGFzIHRmdmlzIGZyb20gJ0B0ZW5zb3JmbG93L3RmanMtdmlzJztcclxuXHJcbmltcG9ydCB7IFRlbnNvckNvbnRhaW5lciB9IGZyb20gJ0B0ZW5zb3JmbG93L3RmanMtY29yZS9kaXN0L3RlbnNvcl90eXBlcyc7XHJcblxyXG5jb25zdCBWQUxJREFUSU9OX0ZSQUNUSU9OID0gMC4xNTtcclxuXHJcblxyXG5cclxuLyoqXHJcbiAqIHRoZSBtZXRhZGF0YSB0byBkZXNjcmliZSB0aGUgbW9kZWwncyBjcmVhdGlvbixcclxuICogaW5jbHVkZXMgdGhlIGxhYmVscyBhc3NvY2lhdGVkIHdpdGggdGhlIGNsYXNzZXNcclxuICogYW5kIHZlcnNpb25pbmcgaW5mb3JtYXRpb24gZnJvbSB0cmFpbmluZy5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgTWV0YWRhdGEge1xyXG4gIHRmanNWZXJzaW9uOiBzdHJpbmc7XHJcbiAgdG1WZXJzaW9uPzogc3RyaW5nO1xyXG4gIHBhY2thZ2VWZXJzaW9uOiBzdHJpbmc7XHJcbiAgcGFja2FnZU5hbWU6IHN0cmluZztcclxuICBtb2RlbE5hbWU/OiBzdHJpbmc7XHJcbiAgdGltZVN0YW1wPzogc3RyaW5nO1xyXG4gIGxhYmVsczogc3RyaW5nW107XHJcbiAgdXNlck1ldGFkYXRhPzoge307XHJcbiAgZ3JheXNjYWxlPzogYm9vbGVhbjtcclxuICBpbWFnZVNpemU/OiBudW1iZXI7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZWNlaXZlcyBhIE1ldGFkYXRhIG9iamVjdCBhbmQgZmlsbHMgaW4gdGhlIG9wdGlvbmFsIGZpZWxkcyBzdWNoIGFzIHRpbWVTdGFtcFxyXG4gKiBAcGFyYW0gZGF0YSBhIE1ldGFkYXRhIG9iamVjdFxyXG4gKi9cclxuY29uc3QgZmlsbE1ldGFkYXRhID0gKGRhdGE6IFBhcnRpYWw8TWV0YWRhdGE+KSA9PiB7XHJcbiAgLy8gdXRpbC5hc3NlcnQodHlwZW9mIGRhdGEudGZqc1ZlcnNpb24gPT09ICdzdHJpbmcnLCAoKSA9PiBgbWV0YWRhdGEudGZqc1ZlcnNpb24gaXMgaW52YWxpZGApO1xyXG4gIC8vIGRhdGEucGFja2FnZVZlcnNpb24gPSBkYXRhLnBhY2thZ2VWZXJzaW9uIHx8IHZlcnNpb247XHJcbiAgZGF0YS5wYWNrYWdlTmFtZSA9IGRhdGEucGFja2FnZU5hbWUgfHwgJ0B0ZWFjaGFibGVtYWNoaW5lL2ltYWdlJztcclxuICBkYXRhLnRpbWVTdGFtcCA9IGRhdGEudGltZVN0YW1wIHx8IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKTtcclxuICBkYXRhLnVzZXJNZXRhZGF0YSA9IGRhdGEudXNlck1ldGFkYXRhIHx8IHt9O1xyXG4gIGRhdGEubW9kZWxOYW1lID0gZGF0YS5tb2RlbE5hbWUgfHwgJ3VudGl0bGVkJztcclxuICBkYXRhLmxhYmVscyA9IGRhdGEubGFiZWxzIHx8IFtdO1xyXG4gIC8vIGRhdGEuaW1hZ2VTaXplID0gZGF0YS5pbWFnZVNpemUgfHwgSU1BR0VfU0laRTtcclxuICByZXR1cm4gZGF0YSBhcyBNZXRhZGF0YTtcclxufTtcclxuXHJcbmV4cG9ydCBjbGFzcyBUZWFjaGFibGVNb2JpbGVOZXQgZXh0ZW5kcyBDdXN0b21Nb2JpbGVOZXQge1xyXG5cclxuICAgIC8vIEFycmF5IG9mIGFsbCB0aGUgZXhhbXBsZXMgY29sbGVjdGVkLlxyXG4gICAgLyoqXHJcbiAgICAgIEl0IGlzIHN0YXRpYyBzaW5jZSBhbGwgdGhlIGluc3RhbmNlIHdpbGwgc2hhcmUgdGhlIHNhbWUgZmVhdHVyZXMsIGZvciBzYXZpbmcgbWVtb3J5IGFuZCB0aW1lLlxyXG4gICAgICBUaGUgaWRlYSBpcyBhdm9pZGluZyByZXN0b3JpbmcgdGhlIGZlYXR1cmVzIGluZGl2aWR1YWxseSBhbmQgaGF2aW5nIHRoZSByZWNhbGN1bGF0ZSB0aGVtIGZvciBldmVyeSBuZXdcclxuICAgICAgaW5kaXZpZHVhbHMuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgZXhhbXBsZXM6IEZsb2F0MzJBcnJheVtdW10gPSBbXTtcclxuXHJcbiAgICAvLyBOdW1iZXIgb2YgdG90YWwgc2FtcGxlc1xyXG4gICAgcHJpdmF0ZSBzdGF0aWMgdG90YWxTYW1wbGVzID0gMDtcclxuXHJcbiAgICBjbGFzc2VzOiBDbGFzc1tdPVtdO1xyXG5cclxuICAgIHN0YXRpYyBjbGFzc2VzX25hbWVzOiBzdHJpbmdbXT1bXTtcclxuXHJcbiAgICBzdGF0aWMgbnVtQ2xhc3NlczogbnVtYmVyO1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAqIHRoZSB0cmFpbmluZyBtb2RlbCBmb3IgdHJhbnNmZXIgbGVhcm5pbmdcclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIHRyYWluaW5nTW9kZWwhOiB0Zi5MYXllcnNNb2RlbDtcclxuICB0cmFpbkRhdGFzZXQ6IGFueTtcclxuICB2YWxpZGF0aW9uRGF0YXNldDogYW55O1xyXG4gIHN0YXRpYyB0cmFpbkRhdGFzZXQ6IGFueTtcclxuICBzdGF0aWMgdmFsaWRhdGlvbkRhdGFzZXQ6IGFueTtcclxuICBzdGF0aWMgbnVtVmFsaWRhdGlvbjogbnVtYmVyO1xyXG5cclxuICBjb25zdHJ1Y3Rvcigpe1xyXG4gICAgc3VwZXIoKTtcclxuICAgIHRoaXMuY3JlYXRlSGVhZCgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVGhpcyBtZXRob2Qgd2lsbCByZXR1cm4gdGhlIGhlYWQsIHRoZSB0cmFpbmFibGUgcGFydCwgdGhlIHBhcnQgdW5kZXIgZXZvbHV0aW9uLlxyXG4gICAqL1xyXG4gIGdldEhlYWQoKXtcclxuICAgIHJldHVybiB0aGlzLnRyYWluaW5nTW9kZWw7XHJcbiAgfVxyXG5cclxuIC8qKlxyXG4gICogQ3JlYXRlIHRoZSBoZWFkIGZvciB0cmFuc2ZlciBsZWFybmluZy5cclxuICAqIFRoaXMgaXMgdGhlIHRyYWluYWJsZSBzZWN0aW9uIG9mIHRoZSB0cmFuc2ZlciBsZWFybmluZy5cclxuICAqL1xyXG4gY3JlYXRlSGVhZCgpe1xyXG5cclxuICBjb25zdCBpbnB1dFNpemU9IFRlYWNoYWJsZU1vYmlsZU5ldC5nZXRpbnB1dFNoYXBlKCk7XHJcblxyXG4gIHRoaXMudHJhaW5pbmdNb2RlbCA9IHRmLnNlcXVlbnRpYWwoe1xyXG4gICAgbGF5ZXJzOiBbXHJcbiAgICAgIHRmLmxheWVycy5kZW5zZSh7XHJcbiAgICAgICAgaW5wdXRTaGFwZTogW2lucHV0U2l6ZV0sXHJcbiAgICAgICAgdW5pdHM6MTAwLFxyXG4gICAgICAgIGFjdGl2YXRpb246ICdyZWx1JywgIFxyXG4gICAgICAgIHVzZUJpYXM6IHRydWVcclxuICAgIH0pLFxyXG4gICAgdGYubGF5ZXJzLmRlbnNlKHsgIFxyXG4gICAgICB1c2VCaWFzOiBmYWxzZSxcclxuICAgICAgYWN0aXZhdGlvbjogJ3NvZnRtYXgnLFxyXG4gICAgICB1bml0czogVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoXHJcbiAgfSlcclxuICAgIF1cclxuICB9KTtcclxuXHJcbiAgY29uc3Qgb3B0aW1pemVyID0gdGYudHJhaW4uYWRhbSgpO1xyXG4gIC8vIGNvbnN0IG9wdGltaXplciA9IHRmLnRyYWluLnJtc3Byb3AocGFyYW1zLmxlYXJuaW5nUmF0ZSk7XHJcblxyXG4gIHRoaXMudHJhaW5pbmdNb2RlbC5jb21waWxlKHtcclxuICAgICAgb3B0aW1pemVyLFxyXG4gICAgICAvLyBsb3NzOiAnYmluYXJ5Q3Jvc3NlbnRyb3B5JyxcclxuICAgICAgbG9zczogJ2NhdGVnb3JpY2FsQ3Jvc3NlbnRyb3B5JyxcclxuICAgICAgbWV0cmljczogWydhY2N1cmFjeSddXHJcbiAgfSk7XHJcbiB9XHJcbiBcclxuIGFzeW5jICB0cmFpbigpe1xyXG5cclxuICBjb25zdCB0cmFpbmluZ1N1cmZhY2UgPSB7IG5hbWU6ICdMb3NzIGFuZCBNU0UnLCB0YWI6ICdUcmFpbmluZycgfTtcclxuXHJcbiAgY29uc3QgZGF0YXNldD0gVGVhY2hhYmxlTW9iaWxlTmV0LmNvbnZlcnRUb1RmRGF0YXNldCgpO1xyXG5cclxuICAvL1NhbHZpbmcgYSBjb3B5IG9mIHRoZSB2YWxpZGF0aW9uIGRhdGFzZXQsIGZvciBsYXRlclxyXG4gIFRlYWNoYWJsZU1vYmlsZU5ldC52YWxpZGF0aW9uRGF0YXNldD0gZGF0YXNldC52YWxpZGF0aW9uRGF0YXNldDtcclxuXHJcbiAgLy8gY29uc29sZS5sb2coXCJEYXRhc2V0IGZvciB0cmFpbmluZzogXCIsIGRhdGFzZXQudHJhaW5EYXRhc2V0KTtcclxuXHJcbiAgY29uc3QgdHJhaW5EYXRhID0gZGF0YXNldC50cmFpbkRhdGFzZXQuYmF0Y2goMzApO1xyXG4gIGNvbnN0IHZhbGlkYXRpb25EYXRhID0gZGF0YXNldC52YWxpZGF0aW9uRGF0YXNldC5iYXRjaCgxMCk7XHJcblxyXG4gIC8vIHRoaXMuY3JlYXRlSGVhZCgpO1xyXG5cclxuICBjb25zdCBjYWxsYmFja3M9IFtcclxuICAgIC8vIFNob3cgb24gYSB0ZmpzLXZpcyB2aXNvciB0aGUgbG9zcyBhbmQgYWNjdXJhY3kgdmFsdWVzIGF0IHRoZSBlbmQgb2YgZWFjaCBlcG9jaC5cclxuICAgIHRmdmlzLnNob3cuZml0Q2FsbGJhY2tzKHRyYWluaW5nU3VyZmFjZSwgWydsb3NzJywgJ2FjYycsIFwidmFsX2xvc3NcIiwgXCJ2YWxfYWNjXCJdLFxyXG4gICAgICB7XHJcbiAgICAgICAgY2FsbGJhY2tzOiBbJ29uRXBvY2hFbmQnXSxcclxuICAgICAgfVxyXG4gICAgKSxcclxuICAgIHt9LF1cclxuXHJcbiAgY29uc3QgaGlzdG9yeTogYW55ID0gYXdhaXQgdGhpcy50cmFpbmluZ01vZGVsLmZpdERhdGFzZXQodHJhaW5EYXRhLCB7XHJcbiAgICBlcG9jaHM6IDEwMCxcclxuICAgIHZhbGlkYXRpb25EYXRhLFxyXG4gICAgY2FsbGJhY2tzXHJcbn0pLnRoZW4oKGluZm86YW55KT0+e1xyXG4gICBjb25zb2xlLmxvZygnUHJlY2lzw6NvIGZpbmFsJywgaW5mby5oaXN0b3J5LnZhbF9hY2NbaW5mby5oaXN0b3J5LmFjYy5sZW5ndGgtMV0pO1xyXG59KTtcclxuXHJcblxyXG4vLyBhd2FpdCB0aGlzLmFjY3VyYWN5X3Blcl9jbGFzcygpO1xyXG5cclxuXHJcbi8vIGNvbnNvbGUubG9nKFwiSGlzdG9yeTogXCIsIGhpc3RvcnkuaGlzdG9yeS5hY2MpO1xyXG4gIC8vIGF3YWl0IHRoaXMudHJhaW5pbmdNb2RlbC5maXQodGhpcy5mZWF0dXJlWCwgdGhpcy50YXJnZXQsIHt9KVxyXG4gfVxyXG5cclxuYXN5bmMgYWNjdXJhY3lfcGVyX2NsYXNzKGNvbmZ1c2lvbl9tYXRyaXhfcmVjaXBpZW50OiBhbnkpe1xyXG4gIFxyXG4gIC8qKkNhbGN1bGF0aW5nIEFjY3VyYWN5IHBlciBjbGFzcyAqL1xyXG5jb25zdCBhY2N1cmFjeXBlcmNsYXNzOiBhbnkgPSAgYXdhaXQgdGhpcy5jYWxjdWxhdGVBY2N1cmFjeVBlckNsYXNzKFRlYWNoYWJsZU1vYmlsZU5ldC52YWxpZGF0aW9uRGF0YXNldCk7XHJcbi8vIGNvbnNvbGUubG9nKFwiQWNjdXJhY3kgcGVyIGNsYXNzOiBcIiwgYWNjdXJhY3lwZXJjbGFzcyk7XHJcblxyXG4vL0NvbmZ1c2lvbiBtYXRyaXhcclxuLy8gQ2FsbGluZyB0Zi5jb25mdXNpb25NYXRyaXgoKSBtZXRob2QgXHJcbmNvbnN0IG91dHB1dCA9IHRmLm1hdGguY29uZnVzaW9uTWF0cml4KCBhY2N1cmFjeXBlcmNsYXNzLnJlZmVyZW5jZSwgYWNjdXJhY3lwZXJjbGFzcy5wcmVkaWN0aW9ucywgVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoKTsgXHJcbiAgXHJcbi8vIFByaW50aW5nIG91dHB1dCBcclxub3V0cHV0LnByaW50KClcclxuY29uc3QgY29uZnVzaW9uX21hdHJpeD0gIG91dHB1dC5kYXRhU3luYygpO1xyXG5cclxuLy8gY29uc29sZS5sb2coY29uZnVzaW9uX21hdHJpeCk7XHJcbi8vIGNvbnNvbGUubG9nKGNvbmZ1c2lvbl9tYXRyaXhbVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoICsgVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoXSk7XHJcblxyXG5jb25zdCBhY2N1cmFjeSA9IFtdO1xyXG5cclxuZm9yKGxldCBpPTA7IGk8VGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoO2krKyl7XHJcblxyXG4gIGFjY3VyYWN5LnB1c2goY29uZnVzaW9uX21hdHJpeFtUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lcy5sZW5ndGgqaSsgaV0vVGVhY2hhYmxlTW9iaWxlTmV0Lm51bVZhbGlkYXRpb24pXHJcbn1cclxuXHJcbmNvbnNvbGUubG9nKFwiQWNjdXJhY3kgcGVyIGNsYXNzOiBcIiwgYWNjdXJhY3kpO1xyXG5cclxuZm9yKGxldCBpPTA7IGk8VGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoO2krKyl7XHJcblxyXG4gIGNvbmZ1c2lvbl9tYXRyaXhfcmVjaXBpZW50LnB1c2goW10pO1xyXG5cclxuICBmb3IobGV0IGo9MDsgajxUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lcy5sZW5ndGg7aisrKXtcclxuICAgIGNvbmZ1c2lvbl9tYXRyaXhfcmVjaXBpZW50W2ldLnB1c2goW10pO1xyXG5cclxuICAgIGNvbmZ1c2lvbl9tYXRyaXhfcmVjaXBpZW50W2ldW2pdPSBjb25mdXNpb25fbWF0cml4W1RlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aCppKyBqXS9UZWFjaGFibGVNb2JpbGVOZXQubnVtVmFsaWRhdGlvblxyXG4gICAgY29uZnVzaW9uX21hdHJpeF9yZWNpcGllbnRbaV1bal09KGNvbmZ1c2lvbl9tYXRyaXhfcmVjaXBpZW50W2ldW2pdLnRvRml4ZWQoMikpKjEwMDtcclxuICB9XHJcblxyXG4gIC8vIGFjY3VyYWN5LnB1c2goY29uZnVzaW9uX21hdHJpeFtUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lcy5sZW5ndGgqaSsgaV0vVGVhY2hhYmxlTW9iaWxlTmV0Lm51bVZhbGlkYXRpb24pXHJcbn1cclxuXHJcbmNvbnNvbGUubG9nKFwiQ29uZnVzaW9uIG1hdHJpeCBhcyBhIG1hdHJpeFwiKVxyXG5jb25zb2xlLmxvZyhjb25mdXNpb25fbWF0cml4X3JlY2lwaWVudCk7XHJcblxyXG5yZXR1cm4gYWNjdXJhY3kubWFwKChlbGVtOiBhbnkpPT5lbGVtLnRvRml4ZWQoMikqMTAwKTtcclxufVxyXG5cclxuIFxyXG4gYXN5bmMgbG9hZEltYWdlcyhudW1iZXJfb2Zfc3BlY2llczogbnVtYmVyLCBjbGFzc2VzX25hbWVzOiBzdHJpbmdbXSwgb3B0aW9uczogb2JqZWN0KXtcclxuICAgICAgICBUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lcz1jbGFzc2VzX25hbWVzO1xyXG4gICAgXHJcbiAgICAgICAgYXdhaXQgdGhpcy5hZGRfc3BlY2llcyhudW1iZXJfb2Zfc3BlY2llcywgb3B0aW9ucyk7ICAgICAgICBcclxuXHJcbn1cclxuXHJcbmFzeW5jIGFkZF9zcGVjaWVzKG51bWJlcl9vZl9zcGVjaWVzOiBudW1iZXIsIG9wdGlvbnM6IG9iamVjdCl7XHJcbiAgXHJcbiAgICAvL0xvYWRpbmcgZmVhdHVyZSBtb2RlbCwgdXNlZCB0byBjcmVhdGUgZmVhdHVyZXMgZnJvbSBpbWFnZXNcclxuICAgIC8vICBhd2FpdCB0aGlzLmxvYWRGZWF0dXJlTW9kZWwoKTtcclxuXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIC8vIHRoaXMuYWRkX2ltYWdlcyh0aGlzLmNsYXNzZXNfbmFtZXNbaV0sIG51bWJlcl9vZl9zcGVjaWVzLCBvcHRpb25zKTtcclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIFxyXG4gKiBAcGFyYW0gbmFtZSAtIG5hbWUgb2YgdGhlIGNsYXNzIHJlY2VpdmluZyBhbiBleGFtcGxlXHJcbiAqIEBwYXJhbSBudW1iZXJfb2Zfc3BlY2llcyAtIGhvdyBtYW55IGltYWdlcyB0byBhZGRcclxuICogQHBhcmFtIG9wdGlvbnMgLSBkZXRhaWxzIG9uIHRoZSBsb2NhdGlvbiBvZiB0aGUgaW1hZ2VzXHJcbiAqL1xyXG5hc3luYyBhZGRfaW1hZ2VzKG5hbWU6IHN0cmluZywgbnVtYmVyX29mX3NwZWNpZXM6IG51bWJlciwgb3B0aW9uczogYW55KXsgICBcclxuXHJcbiAgICBjb25zdCBjbGFzc19hZGQ6IGFueT0gW107XHJcblxyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1iZXJfb2Zfc3BlY2llczsgaSsrKSB7ICAgICAgXHJcbiAgICAvLyAgIGNsYXNzX2FkZC5wdXNoKGAke29wdGlvbnMuYmFzZX0vJHtuYW1lfS8ke29wdGlvbnMuZmlsZV9uYW1lfSAke2l9LiR7b3B0aW9ucy5maWxlX2V4dGVuc2lvbn1gKTtcclxuICAgICAgICBcclxuICAgICAgICAvL1VwbG9hZGluZyBpbWFnZXNcclxuICAgICAgICBjb25zdCBjYWtlID0gbmV3IEltYWdlKCk7ICAgICAgICBcclxuICAgICAgICAvLyBjYWtlLnNyYyA9IGAke29wdGlvbnMuYmFzZX0vJHtuYW1lfS8ke29wdGlvbnMuZmlsZV9uYW1lfSAke2l9LiR7b3B0aW9ucy5maWxlX2V4dGVuc2lvbn1gO1xyXG4gICAgICAgIGNha2UuaGVpZ2h0PTIyNDtcclxuICAgICAgICBjYWtlLndpZHRoPTIyNDtcclxuICAgICAgICBjYWtlLnNyYz1cIi4vYXNzZXRzL2RhdGFzZXQvQ2FuJUMzJUExcmlvLWRhLVRlcnJhL2ltYWdlJTIwMC5qcGVnXCJcclxuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkltYWdlIGxvY2F0aW9uOiBcIiwgY2FrZS5zcmMgKVxyXG5cclxuICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XHJcbiAgICAgICAgICAgIGNha2Uub25sb2FkID0gKCkgPT4ge1xyXG5cclxuICAgICAgICAgICAgICAgIC8vRmluZGluZyB0aGUgY29ycmVzcG9uZGVudCBpbmRleCBvZiB0aGUgY2xhc3Mgd2l0aCBuYW1lIGdpdmVuXHJcbiAgICAgICAgICAgICAgICBjb25zdCBpbmRleD0gVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMuZmluZEluZGV4KChlbGVtKT0+ZWxlbT09PW5hbWUpXHJcblxyXG4gICAgICAgICAgICAgICAgLy8gdGhpcy5hZGRFeGFtcGxlKGluZGV4LCBjYWtlKTtcclxuXHJcbiAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xyXG4gICAgICAgICAgICB9O1xyXG4gIFxyXG4gICAgICAgICAgICBjYWtlLm9uZXJyb3IgPSAoZXJyb3IpID0+IHtcclxuICAgICAgICAgICAgICAvLyBIYW5kbGUgZXJyb3IgaWYgdGhlIGltYWdlIGZhaWxzIHRvIGxvYWRcclxuICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgICAgfSk7XHJcbiAgfVxyXG5cclxuICAvLyB0aGlzLmNsYXNzZXMucHVzaCh7bmFtZTogbmFtZSwgaW1hZ2VzOiBjbGFzc19hZGR9KSAgXHJcblxyXG4gIH1cclxuXHJcblxyXG5cclxuICAgICAgXHJcbi8qKlxyXG4gKiBUaGlzIG1ldGhvZCB3aWxsIHRyYW5zZm9ybSBpbWFnZXMgaW50byB0ZW5zb3JzXHJcbiAqIEBwYXJhbSBudW1iZXJfb2ZfY2xhc3NlcyAtIG51bWJlciBvZiBjbGFzc2VzXHJcbiAqIEBwYXJhbSBjbGFzc2VzX25hbWVzIC0gbmFtZSBvZiBlYWNoIGNsYXNzXHJcbiAqL1xyXG5hc3luYyBjcmVhdGVUZW5zb3JzKG51bWJlcl9vZl9jbGFzc2VzOiBudW1iZXIsIGNsYXNzZXNfbmFtZXM6IHN0cmluZ1tdKSB7XHJcblxyXG4gICAgbGV0IG91dHB1dDogYW55ID0gW107XHJcblxyXG4gICAgLyoqIFRoZXJlIGlzIGEgZnVuY3Rpb24gb24gVGVuc29yRmxvdy5qcyB0aGF0IGFsc28gZG9lcyB0aGF0ICovXHJcbiAgICBjb25zdCBzaWduYXR1cmVzPSBuZXcgVXRpbCgpLmlkZW50aXR5TWF0cml4KG51bWJlcl9vZl9jbGFzc2VzKTtcclxuXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bWJlcl9vZl9jbGFzc2VzOyBpKyspIHtcclxuXHJcbiAgICAgICAgdGhpcy5jbGFzc2VzW2ldLnNpZ25hdHVyZT1zaWduYXR1cmVzW2ldO1xyXG4gICAgICAgIHRoaXMuY2xhc3Nlc1tpXS5uYW1lPWNsYXNzZXNfbmFtZXNbaV07XHJcblxyXG4gICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5jbGFzc2VzW2ldLmltYWdlcy5sZW5ndGg7IGorKykge1xyXG5cclxuXHJcbiAgICAgICAgfVxyXG5cclxuICAgIH1cclxufVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQWRkIGEgc2FtcGxlIG9mIGRhdGEgdW5kZXIgdGhlIHByb3ZpZGVkIGNsYXNzTmFtZVxyXG4gICAgICogQHBhcmFtIGNsYXNzTmFtZSB0aGUgY2xhc3NpZmljYXRpb24gdGhpcyBleGFtcGxlIGJlbG9uZ3MgdG9cclxuICAgICAqIEBwYXJhbSBzYW1wbGUgdGhlIGltYWdlIC8gdGVuc29yIHRoYXQgYmVsb25ncyBpbiB0aGlzIGNsYXNzaWZpY2F0aW9uXHJcbiAgICAgKi9cclxuICAgIC8vIHB1YmxpYyBhc3luYyBhZGRFeGFtcGxlKGNsYXNzTmFtZTogbnVtYmVyLCBzYW1wbGU6IEhUTUxDYW52YXNFbGVtZW50IHwgdGYuVGVuc29yKSB7XHJcbnB1YmxpYyBzdGF0aWMgYXN5bmMgYWRkRXhhbXBsZShjbGFzc05hbWU6IG51bWJlciwgbmFtZTogc3RyaW5nLCBzYW1wbGU6IEhUTUxJbWFnZUVsZW1lbnQgfCBIVE1MQ2FudmFzRWxlbWVudCB8IHRmLlRlbnNvcikge1xyXG5cclxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJBZGRpbmcgYSBuZXcgZXhhbXBsZS4uLlwiKSBcclxuICAgICAgICAgIFxyXG4gICAgICAgICAgICBjb25zdCBjYXAgPSBpc1RlbnNvcihzYW1wbGUpID8gc2FtcGxlIDogY2FwdHVyZShzYW1wbGUpO1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgLy8gaWYoIXRoaXMudHJ1bmNhdGVkTW9kZWwpXHJcbiAgICAgICAgICAgIC8vICAgYXdhaXQgdGhpcy5sb2FkRmVhdHVyZU1vZGVsKCk7XHJcblxyXG4gICAgICAgICAgICAvL0dldHRpbmcgdGhlIGZlYXR1cmVzXHJcbiAgICAgICAgICAgIGNvbnN0IGV4YW1wbGUgPSB0aGlzLnRydW5jYXRlZE1vZGVsLnByZWRpY3QoY2FwKSBhcyB0Zi5UZW5zb3I7XHJcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwiU2hhcGUgYWZ0ZXIgZmVhdHVyZSBleHRyYWN0aW9uOiBcIiwgZXhhbXBsZS5zaGFwZSkgICAgICAgICAgXHJcbiAgICAgICAgICAgXHJcblxyXG4gICAgICAgICAgICBjb25zdCBhY3RpdmF0aW9uID0gZXhhbXBsZS5kYXRhU3luYygpIGFzIEZsb2F0MzJBcnJheTtcclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIC8vVmVyeSBpbXBvcnRhbnQgdG8gY2xlYW4gdGhlIG1lbW9yeSBhZnRlcm1hdGgsIGl0IG1ha2VzIHRoZSBkaWZmZXJlbmNlXHJcbiAgICAgICAgICAgIGNhcC5kaXNwb3NlKCk7XHJcbiAgICAgICAgICAgIGV4YW1wbGUuZGlzcG9zZSgpO1xyXG4gICAgXHJcbiAgICAgICAgICAgIC8vIC8vQWNjZXNzaW5nIHRoZSBpbnN0YW5jZSB2YXJpYWJsZSwgbm90IHRoZSBsb2NhbCBvbmVzXHJcbiAgICAgICAgICAgIC8vIC8vIHNhdmUgc2FtcGxlcyBvZiBlYWNoIGNsYXNzIHNlcGFyYXRlbHkgXHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICBpZighVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzW2NsYXNzTmFtZV0pXHJcbiAgICAgICAgICAgICAgLy9hbmQgYW4gZW1wdHkgYXJyYXksIG1ha2Ugc3VyZSB0aGVyZSBpcyBub3QgZW1wdHkgZWxlbWVudHMuIFxyXG4gICAgICAgICAgICAgIC8vaXQgd2lsbCBjcmVhdGUgaXNzdWUgd2hlbiB0cmFuc2Zvcm1pbmcgdG8gdGVuc29yc1xyXG4gICAgICAgICAgICAgIFRlYWNoYWJsZU1vYmlsZU5ldC5leGFtcGxlc1tjbGFzc05hbWVdPVtdXHJcblxyXG5cclxuICAgICAgICAgICAgICBpZighVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXNbY2xhc3NOYW1lXSlcclxuICAgICAgICAgICAgICAgIC8vU2F2aW5nIHRoZSBsYWJsZSB3aGVuIGl0IGZpcnN0IGFwcGVhcnNcclxuICAgICAgICAgICAgICAgIFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzW2NsYXNzTmFtZV09bmFtZTtcclxuXHJcbiAgICAgICAgICAgIFRlYWNoYWJsZU1vYmlsZU5ldC5leGFtcGxlc1tjbGFzc05hbWVdLnB1c2goYWN0aXZhdGlvbik7XHJcbiAgICBcclxuICAgICAgICAgICAgLy8gLy8gaW5jcmVhc2Ugb3VyIHNhbXBsZSBjb3VudGVyXHJcbiAgICAgICAgICAgIFRlYWNoYWJsZU1vYmlsZU5ldC50b3RhbFNhbXBsZXMrKztcclxuICAgICAgICB9XHJcblxyXG5cclxuICAgLyoqXHJcbiAgICAgKiBwcm9jZXNzIHRoZSBjdXJyZW50IGV4YW1wbGVzIHByb3ZpZGVkIHRvIGNhbGN1bGF0ZSBsYWJlbHMgYW5kIGZvcm1hdFxyXG4gICAgICogaW50byBwcm9wZXIgdGYuZGF0YS5EYXRhc2V0XHJcbiAgICAgKi9cclxuICAgc3RhdGljIHByZXBhcmUoKSB7XHJcbiAgICBmb3IgKGNvbnN0IGNsYXNzZXMgaW4gVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzKXtcclxuICAgICAgICBpZiAoY2xhc3Nlcy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdBZGQgc29tZSBleGFtcGxlcyBiZWZvcmUgdHJhaW5pbmcnKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgZGF0YXNldHM6IGFueSA9IHRoaXMuY29udmVydFRvVGZEYXRhc2V0KCk7XHJcblxyXG4gICAgdGhpcy50cmFpbkRhdGFzZXQgPSBkYXRhc2V0cy50cmFpbkRhdGFzZXQ7XHJcbiAgICB0aGlzLnZhbGlkYXRpb25EYXRhc2V0ID0gZGF0YXNldHMudmFsaWRhdGlvbkRhdGFzZXQ7XHJcbn1cclxuXHJcbnB1YmxpYyBwcmVwYXJlRGF0YXNldCgpIHtcclxuICBmb3IgKGxldCBpID0gMDsgaSA8IFRlYWNoYWJsZU1vYmlsZU5ldC5udW1DbGFzc2VzOyBpKyspIHtcclxuICAgIC8vRGlmZmVyZW50IGZyb20gdGhlIG9yaWdpbmFsIGltcGxlbWVudGF0aW9uIG9mIFRNLCBtaW5lIGlzIHVzaW5nIGV4YW1wbGUgYXMgc3RhdGljLlxyXG4gICAgLy9UaGUgZ29hbCBpcyBzYXZpbmcgbWVtb3J5IGJ5IHVzaW5nIGEgc2luZ2xlIGluc3RhbmNlIG9mIHRoZSB2YXJpYWJsZVxyXG4gICAgVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzW2ldID0gW107XHJcbiAgfVxyXG59XHJcblxyXG4gXHJcbiAgICAvLyBPcHRpb25hbCBzZWVkIHRvIG1ha2Ugc2h1ZmZsaW5nIG9mIGRhdGEgcHJlZGljdGFibGVcclxuICAgIHN0YXRpYyBzZWVkOiBzZWVkcmFuZG9tLnBybmc7XHJcblxyXG5cclxuXHJcbiAgICBcclxuLyoqXHJcbiAgICAgKiBQcm9jZXNzIHRoZSBleGFtcGxlcyBieSBmaXJzdCBzaHVmZmxpbmcgcmFuZG9tbHkgcGVyIGNsYXNzLCB0aGVuIGFkZGluZ1xyXG4gICAgICogb25lLWhvdCBsYWJlbHMsIHRoZW4gc3BsaXR0aW5nIGludG8gdHJhaW5pbmcvdmFsaWRhdGlvbiBkYXRzZXRzLCBhbmQgZmluYWxseVxyXG4gICAgICogc29ydGluZyBvbmUgbGFzdCB0aW1lXHJcbiAgICAgKi9cclxuIFxyXG5zdGF0aWMgY29udmVydFRvVGZEYXRhc2V0KCkge1xyXG5cclxuICAgICAgICAgLy8gZmlyc3Qgc2h1ZmZsZSBlYWNoIGNsYXNzIGluZGl2aWR1YWxseVxyXG4gICAgICAgIC8vIFRPRE86IHdlIGNvdWxkIGJhc2ljYWxseSByZXBsaWNhdGUgdGhpcyBieSBpbnN0ZXJ0aW5nIHJhbmRvbWx5XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBUZWFjaGFibGVNb2JpbGVOZXQuZXhhbXBsZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgIFRlYWNoYWJsZU1vYmlsZU5ldC5leGFtcGxlc1tpXSA9IGZpc2hlcllhdGVzKFRlYWNoYWJsZU1vYmlsZU5ldC5leGFtcGxlc1tpXSwgdGhpcy5zZWVkKSBhcyBGbG9hdDMyQXJyYXlbXTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gdGhlbiBicmVhayBpbnRvIHZhbGlkYXRpb24gYW5kIHRlc3QgZGF0YXNldHNcclxuICAgICAgbGV0IHRyYWluRGF0YXNldDogU2FtcGxlW10gPSBbXTtcclxuICAgICAgbGV0IHZhbGlkYXRpb25EYXRhc2V0OiBTYW1wbGVbXSA9IFtdO1xyXG5cclxuICAgICAgLy8gZm9yIGVhY2ggY2xhc3MsIGFkZCBzYW1wbGVzIHRvIHRyYWluIGFuZCB2YWxpZGF0aW9uIGRhdGFzZXRcclxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBUZWFjaGFibGVNb2JpbGVOZXQuZXhhbXBsZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgXHJcbiAgICAgICAgLy8gY29uc29sZS5sb2coXCJOdW1iZXIgb2YgY2xhc3NlczogXCIsIFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aCk7XHJcblxyXG4gICAgICAgIGNvbnN0IHkgPSBmbGF0T25lSG90KGksIFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aCk7XHJcblxyXG4gICAgICAgIGNvbnN0IGNsYXNzTGVuZ3RoID0gVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzW2ldLmxlbmd0aDtcclxuXHJcbiAgICAgICAgLy8gY29uc29sZS5sb2coXCJOdW1iZXIgb2YgZWxlbWVudHMgcGVyIGNsYXNzOiBcIiwgY2xhc3NMZW5ndGgpO1xyXG5cclxuICAgICAgICBjb25zdCBudW1WYWxpZGF0aW9uID0gTWF0aC5jZWlsKFZBTElEQVRJT05fRlJBQ1RJT04gKiBjbGFzc0xlbmd0aCk7XHJcbiAgICAgICAgY29uc3QgbnVtVHJhaW4gPSBjbGFzc0xlbmd0aCAtIG51bVZhbGlkYXRpb247XHJcblxyXG4gICAgICAgIHRoaXMubnVtVmFsaWRhdGlvbj1udW1WYWxpZGF0aW9uO1xyXG4gICAgICAgXHJcbiAgICAgICAgLyoqSXQgaXMgdmlzaXRpbmcgcGVyIGNsYXNzLCB0aHVzLCBpdCBpcyBwb3NzaWJsZSB0byBmaXggeSwgdGhlIHRhcmdldCBsYWJlbCAqL1xyXG4gICAgIFxyXG4gICAgICBjb25zdCBjbGFzc1RyYWluID0gdGhpcy5leGFtcGxlc1tpXS5zbGljZSgwLCBudW1UcmFpbikubWFwKChkYXRhQXJyYXkpID0+IHtcclxuICAgICAgICAgIHJldHVybiB7IGRhdGE6IGRhdGFBcnJheSwgbGFiZWw6IHkgfTtcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBjb25zdCBjbGFzc1ZhbGlkYXRpb24gPSB0aGlzLmV4YW1wbGVzW2ldLnNsaWNlKG51bVRyYWluKS5tYXAoKGRhdGFBcnJheSkgPT4ge1xyXG4gICAgICAgICAgcmV0dXJuIHsgZGF0YTogZGF0YUFycmF5LCBsYWJlbDogeSB9O1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHRyYWluRGF0YXNldCA9IHRyYWluRGF0YXNldC5jb25jYXQoY2xhc3NUcmFpbik7XHJcbiAgICAgIHZhbGlkYXRpb25EYXRhc2V0ID0gdmFsaWRhdGlvbkRhdGFzZXQuY29uY2F0KGNsYXNzVmFsaWRhdGlvbik7IFxyXG5cclxuXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKFwiVHJhaW5pbmcgZWxlbWVudDogXCIsIHRyYWluRGF0YXNldFt0cmFpbkRhdGFzZXQubGVuZ3RoLTFdKSAgICAgIFxyXG4gICAgICAvLyBjb25zb2xlLmxvZyhcIlRyYWluaW5nIGxlbmd0aDogXCIsIHRyYWluRGF0YXNldC5sZW5ndGgpXHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKFwidmFsaWRhdGlvbiBsZW5ndGg6IFwiLCB2YWxpZGF0aW9uRGF0YXNldC5sZW5ndGgpO1xyXG5cclxuICAgICAgXHJcbiAgICAgICAgLy8gZmluYWxseSBzaHVmZmxlIGJvdGggdHJhaW4gYW5kIHZhbGlkYXRpb24gZGF0YXNldHNcclxuICAgICAgICB0cmFpbkRhdGFzZXQgPSBmaXNoZXJZYXRlcyh0cmFpbkRhdGFzZXQsIHRoaXMuc2VlZCkgYXMgU2FtcGxlW107XHJcbiAgICAgICAgdmFsaWRhdGlvbkRhdGFzZXQgPSBmaXNoZXJZYXRlcyh2YWxpZGF0aW9uRGF0YXNldCwgdGhpcy5zZWVkKSBhcyBTYW1wbGVbXTtcclxuXHJcbiAgICAgICAgY29uc3QgdHJhaW5YID0gdGYuZGF0YS5hcnJheSh0cmFpbkRhdGFzZXQubWFwKHNhbXBsZSA9PiBzYW1wbGUuZGF0YSkpO1xyXG4gICAgICAgIGNvbnN0IHZhbGlkYXRpb25YID0gdGYuZGF0YS5hcnJheSh2YWxpZGF0aW9uRGF0YXNldC5tYXAoc2FtcGxlID0+IHNhbXBsZS5kYXRhKSk7XHJcbiAgICAgICAgY29uc3QgdHJhaW5ZID0gdGYuZGF0YS5hcnJheSh0cmFpbkRhdGFzZXQubWFwKHNhbXBsZSA9PiBzYW1wbGUubGFiZWwpKTtcclxuICAgICAgICBjb25zdCB2YWxpZGF0aW9uWSA9IHRmLmRhdGEuYXJyYXkodmFsaWRhdGlvbkRhdGFzZXQubWFwKHNhbXBsZSA9PiBzYW1wbGUubGFiZWwpKTtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyByZXR1cm4gdGYuZGF0YSBkYXRhc2V0IG9iamVjdHNcclxuICAgICAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICAgIHRyYWluRGF0YXNldDogdGYuZGF0YS56aXAoeyB4czogdHJhaW5YLCAgeXM6IHRyYWluWX0pLFxyXG4gICAgICAgICAgICAgICAgICB2YWxpZGF0aW9uRGF0YXNldDogdGYuZGF0YS56aXAoeyB4czogdmFsaWRhdGlvblgsICB5czogdmFsaWRhdGlvbll9KVxyXG4gICAgICAgICAgICAgIH07XHJcblxyXG5cclxufVxyXG5cclxuZGF0YXNldEZvckV2YWx1YXRpb24oKXtcclxuXHJcbn1cclxuXHJcbi8qKk1ldHJpY3MgKi9cclxuXHJcbnN0YXRpYyBmZWF0dXJlX2F1eDogYW55O1xyXG5zdGF0aWMgdGFyZ2V0X2F1eDogYW55O1xyXG5cclxuYXN5bmMgZXZhbHVhdGUoKXtcclxuICAgXHJcbiAgLy9DaGVjayBvZiB0aGUgZmVhdHVyZXMgaGF2ZSBhbHJlYWR5IGJlZW4gY2FsY3VsYXRlZFxyXG4gIC8qKkZvciBhdm9pZGluZyByZWNhbGN1bGF0aW5nIHRoZSBmZWF0dXJlcyBldmVyeSBnZW5lcmF0aW9uICovXHJcbiAgaWYoIVRlYWNoYWJsZU1vYmlsZU5ldC5mZWF0dXJlX2F1eCl7XHJcbiAgICBjb25zdCBmZWF0dXJlczogYW55PVtdO1xyXG4gICAgY29uc3QgdGFyZ2V0czogYW55PVtdO1xyXG5cclxuICBmb3IgKGxldCBpID0gMDsgaSA8IFRlYWNoYWJsZU1vYmlsZU5ldC5leGFtcGxlcy5sZW5ndGg7IGkrKykge1xyXG5cclxuICAgIGNvbnN0IHkgPSBmbGF0T25lSG90KGksIFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aCk7XHJcbiAgICAvL0ZvciBjbGFzcyBpLCBwdXNoIGFsbCB0aGUgZXhhbXBsZXMuXHJcbiAgICBUZWFjaGFibGVNb2JpbGVOZXQuZXhhbXBsZXNbaV0uZm9yRWFjaCgoZWxlbW4pPT57XHJcblxyXG4gICAgICAgLy9QdXNoaW5nIHRoZSB0YXJnZXQgc2lnbmF0dXJlXHJcbiAgICAgICB0YXJnZXRzLnB1c2goeSk7XHJcbiAgICAgICBcclxuICAgICAgIC8vUHVzaGluZyBmZWF0dXJlc1xyXG4gICAgICAgZmVhdHVyZXMucHVzaChlbGVtbilcclxuICAgIH0pXHJcblxyXG4gIH0gIFxyXG5cclxuICBUZWFjaGFibGVNb2JpbGVOZXQuZmVhdHVyZV9hdXg9IHRmLnRlbnNvcihmZWF0dXJlcyk7XHJcbiAgVGVhY2hhYmxlTW9iaWxlTmV0LnRhcmdldF9hdXg9IHRmLnRlbnNvcih0YXJnZXRzKTtcclxuXHJcbiAgfSBcclxuXHJcbiAgLy9FdmFsdWF0aW5nIHRoZSBtb2RlbFxyXG4gIGNvbnN0IGF1eDogYW55ID0gdGhpcy50cmFpbmluZ01vZGVsLmV2YWx1YXRlKFRlYWNoYWJsZU1vYmlsZU5ldC5mZWF0dXJlX2F1eCwgVGVhY2hhYmxlTW9iaWxlTmV0LnRhcmdldF9hdXgpO1xyXG4gIFxyXG4gIC8vUmV0dXJuIGp1c3QgdGhlIGFjY3VyYWN5XHJcbiAgcmV0dXJuIGF1eFsxXS5kYXRhU3luYygpWzBdO1xyXG5cclxuXHJcbn1cclxuXHJcblxyXG4vLyBhc3luYyBldmFsdWF0ZSgpe1xyXG5cclxuLy8gICBjb25zdCBmZWF0dXJlczogYW55PVtdO1xyXG4vLyAgIGNvbnN0IHRhcmdldHM6IGFueT1bXTtcclxuXHJcbi8vICAgZm9yIChsZXQgaSA9IDA7IGkgPCBUZWFjaGFibGVNb2JpbGVOZXQuZXhhbXBsZXMubGVuZ3RoOyBpKyspIHtcclxuXHJcbi8vICAgICBjb25zdCB5ID0gZmxhdE9uZUhvdChpLCBUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lcy5sZW5ndGgpO1xyXG4gICAgXHJcblxyXG5cclxuLy8gICAgIC8vRm9yIGNsYXNzIGksIHB1c2ggYWxsIHRoZSBleGFtcGxlcy5cclxuLy8gICAgIFRlYWNoYWJsZU1vYmlsZU5ldC5leGFtcGxlc1tpXS5mb3JFYWNoKChlbGVtbik9PntcclxuXHJcbi8vICAgICAgICAvL1B1c2hpbmcgdGhlIHRhcmdldCBzaWduYXR1cmVcclxuLy8gICAgICAgIHRhcmdldHMucHVzaCh5KTtcclxuICAgICAgIFxyXG4vLyAgICAgICAgLy9QdXNoaW5nIGZlYXR1cmVzXHJcbi8vICAgICAgICBmZWF0dXJlcy5wdXNoKGVsZW1uKVxyXG4vLyAgICAgfSlcclxuXHJcbi8vICAgfSAgXHJcblxyXG4vLyAgIGNvbnN0IGF1eF9mZWF0dXJlcz0gdGYudGVuc29yKGZlYXR1cmVzKTtcclxuLy8gICBjb25zdCBhdXhfdGFyZ2V0PSB0Zi50ZW5zb3IodGFyZ2V0cyk7XHJcblxyXG4gIFxyXG4vLyAgIC8vIGNvbnNvbGUubG9nKFwiVGVuc29yIHN0YWNrIGZvciBldmFsdWF0aW9uOiBcIiwgYXV4X2ZlYXR1cmVzLnNoYXBlKVxyXG5cclxuLy8gICBjb25zdCBhdXg6IGFueSA9IHRoaXMudHJhaW5pbmdNb2RlbC5ldmFsdWF0ZShhdXhfZmVhdHVyZXMsIGF1eF90YXJnZXQpO1xyXG5cclxuXHJcbi8vICAgcmV0dXJuIGF1eFsxXS5kYXRhU3luYygpWzBdO1xyXG5cclxuXHJcbi8vIH1cclxuXHJcblxyXG4vKioqIEZpbmFsIHN0YXRpc3RpY3MgKi9cclxuLyogXHJcbiAgICAgKiBDYWxjdWxhdGUgZWFjaCBjbGFzcyBhY2N1cmFjeSB1c2luZyB0aGUgdmFsaWRhdGlvbiBkYXRhc2V0XHJcbiovXHJcbnB1YmxpYyBhc3luYyBjYWxjdWxhdGVBY2N1cmFjeVBlckNsYXNzKHZhbGlkYXRpb25EYXRhOiBhbnkpIHtcclxuXHJcbiAgY29uc3QgdmFsaWRhdGlvblhzID0gVGVhY2hhYmxlTW9iaWxlTmV0LnZhbGlkYXRpb25EYXRhc2V0Lm1hcEFzeW5jKGFzeW5jIChkYXRhc2V0OiBUZW5zb3JDb250YWluZXIpID0+IHtcclxuICAgIHJldHVybiAoZGF0YXNldCBhcyB7IHhzOiBUZW5zb3JDb250YWluZXIsIHlzOiBUZW5zb3JDb250YWluZXJ9KS54cztcclxufSk7XHJcblxyXG5jb25zdCB2YWxpZGF0aW9uWXMgPSBUZWFjaGFibGVNb2JpbGVOZXQudmFsaWRhdGlvbkRhdGFzZXQubWFwQXN5bmMoYXN5bmMgKGRhdGFzZXQ6IFRlbnNvckNvbnRhaW5lcikgPT4ge1xyXG4gICAgcmV0dXJuIChkYXRhc2V0IGFzIHsgeHM6IFRlbnNvckNvbnRhaW5lciwgeXM6IFRlbnNvckNvbnRhaW5lcn0pLnlzO1xyXG59KTtcclxuXHJcbi8vIGNvbnNvbGUubG9nKFwidmFsaWRhdGlvbiBkYXRhc2V0OiBcIiwgdmFsaWRhdGlvblhzKTtcclxuIFxyXG4vLyBjb25zb2xlLmxvZyhcIkZvciBjYWxjdWxhdGluZyBiYXRjaCBzaXplOiBcIiwgdmFsaWRhdGlvbllzKTtcclxuXHJcbi8vIHdlIG5lZWQgdG8gc3BsaXQgb3VyIHZhbGlkYXRpb24gZGF0YSBpbnRvIGJhdGNoZXMgaW4gY2FzZSBpdCBpcyB0b28gbGFyZ2UgdG8gZml0IGluIG1lbW9yeVxyXG5jb25zdCBiYXRjaFNpemUgPSBNYXRoLm1pbih2YWxpZGF0aW9uWXMuc2l6ZSwgMzIpO1xyXG4vLyBjb25zdCBiYXRjaFNpemUgPTE7XHJcblxyXG5jb25zdCBpdGVyYXRpb25zID0gTWF0aC5jZWlsKHZhbGlkYXRpb25Zcy5zaXplIC8gYmF0Y2hTaXplKTtcclxuXHJcbi8vIGNvbnNvbGUubG9nKFwiQmF0Y2ggc2l6ZTogXCIsIGJhdGNoU2l6ZSk7XHJcblxyXG5jb25zdCBiYXRjaGVzWCA9IHZhbGlkYXRpb25Ycy5iYXRjaChiYXRjaFNpemUpO1xyXG5cclxuY29uc3QgYmF0Y2hlc1kgPSB2YWxpZGF0aW9uWXMuYmF0Y2goYmF0Y2hTaXplKTtcclxuY29uc3QgaXRYID0gYXdhaXQgYmF0Y2hlc1guaXRlcmF0b3IoKTtcclxuY29uc3QgaXRZID0gYXdhaXQgYmF0Y2hlc1kuaXRlcmF0b3IoKTtcclxuY29uc3QgYWxsWCA9IFtdO1xyXG5jb25zdCBhbGxZID0gW107XHJcblxyXG5mb3IgKGxldCBpID0gMDsgaSA8IGl0ZXJhdGlvbnM7IGkrKykge1xyXG5cclxuICAgIC8vIDEuIGdldCB0aGUgcHJlZGljdGlvbiB2YWx1ZXMgaW4gYmF0Y2hlc1xyXG4gICAgIGNvbnN0IGJhdGNoZWRYVGVuc29yID0gYXdhaXQgaXRYLm5leHQoKTsgIFxyXG5cclxuICAgIC8vICBjb25zb2xlLmxvZyhcIkJhdGNoIHNpemUgb24gYWNjdXJhY3kgcGVyIGNsYXNzOiBcIiwgYmF0Y2hlZFhUZW5zb3IudmFsdWUuc2hhcGUpO1xyXG5cclxuICAgIGNvbnN0IGJhdGNoZWRYUHJlZGljdGlvblRlbnNvciA9IHRoaXMudHJhaW5pbmdNb2RlbC5wcmVkaWN0KGJhdGNoZWRYVGVuc29yLnZhbHVlKSBhcyB0Zi5UZW5zb3I7XHJcblxyXG4gICAgY29uc3QgYXJnTWF4WCA9IGJhdGNoZWRYUHJlZGljdGlvblRlbnNvci5hcmdNYXgoMSk7IC8vIFJldHVybnMgdGhlIGluZGljZXMgb2YgdGhlIG1heCB2YWx1ZXMgYWxvbmcgYW4gYXhpc1xyXG5cclxuICAgIGFsbFgucHVzaChhcmdNYXhYKTtcclxuXHJcbiAgICAvLyAyLiBnZXQgdGhlIGdyb3VuZCB0cnV0aCBsYWJlbCB2YWx1ZXMgaW4gYmF0Y2hlc1xyXG4gICAgY29uc3QgYmF0Y2hlZFlUZW5zb3IgPSBhd2FpdCBpdFkubmV4dCgpO1xyXG4gICAgY29uc3QgYXJnTWF4WSA9IGJhdGNoZWRZVGVuc29yLnZhbHVlLmFyZ01heCgxKTsgLy8gUmV0dXJucyB0aGUgaW5kaWNlcyBvZiB0aGUgbWF4IHZhbHVlcyBhbG9uZyBhbiBheGlzXHJcblxyXG4gICAgYWxsWS5wdXNoKGFyZ01heFkpO1xyXG4gICAgXHJcbiAgICAvLyAzLiBkaXNwb3NlIG9mIGFsbCBvdXIgdGVuc29yc1xyXG4gICAgIGJhdGNoZWRYVGVuc29yLnZhbHVlLmRpc3Bvc2UoKTtcclxuICAgICBiYXRjaGVkWFByZWRpY3Rpb25UZW5zb3IuZGlzcG9zZSgpO1xyXG4gICAgIGJhdGNoZWRZVGVuc29yLnZhbHVlLmRpc3Bvc2UoKTtcclxufVxyXG5cclxuICAgICAgLy8gY29uY2F0ZW5hdGUgYWxsIHRoZSByZXN1bHRzIG9mIHRoZSBiYXRjaGVzXHJcbiAgICAgIGNvbnN0IHJlZmVyZW5jZSA9IHRmLmNvbmNhdChhbGxZKTsgLy8gdGhpcyBpcyB0aGUgZ3JvdW5kIHRydXRoXHJcbiAgICAgIGNvbnN0IHByZWRpY3Rpb25zID0gdGYuY29uY2F0KGFsbFgpOyAvLyB0aGlzIGlzIHRoZSBwcmVkaWN0aW9uIG91ciBtb2RlbCBpcyBndWVzc2luZ1xyXG4gICAgICBcclxuICAgICAgLy8gY29uc29sZS5sb2coXCJ0aGlzIGlzIHRoZSBncm91bmQgdHJ1dGg6IFwiLCAgcmVmZXJlbmNlLmRhdGFTeW5jKCkpXHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKFwiVGhpcyBpcyB0aGUgcHJlZGljdGlvbiBvdXIgbW9kZWwgaXMgZ3Vlc3Npbmc6IFwiLCAgcHJlZGljdGlvbnMuZGF0YVN5bmMoKSlcclxuXHJcbiAgICAgICAgLy8gb25seSBpZiB3ZSBjb25jYXRlbmF0ZWQgbW9yZSB0aGFuIG9uZSB0ZW5zb3IgZm9yIHByZWZlcmVuY2UgYW5kIHJlZmVyZW5jZVxyXG4gICAgICAgIGlmIChpdGVyYXRpb25zICE9PSAxKSB7XHJcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYWxsWC5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgYWxsWFtpXS5kaXNwb3NlKCk7XHJcbiAgICAgICAgICAgICAgICBhbGxZW2ldLmRpc3Bvc2UoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAvLyAgY29uc29sZS5sb2coXCJMZW5ndHRoOiBcIiwgYXdhaXQgcmVmZXJlbmNlLmRhdGFTeW5jKCkubGVuZ3RoKSAgXHJcbiAgICBcclxuICAgIC8vIGNvbnN0IGFjY3VyYWN5cGVyY2xhc3M9W107XHJcblxyXG4gICAgLy8gY29uc3QgcmVmZXJlbmNlX2F1eD0gYXdhaXQgcmVmZXJlbmNlLmRhdGFTeW5jKCk7XHJcbiAgICAvLyBjb25zdCBwcmVkaWN0aW9uX2F1eD0gYXdhaXQgcHJlZGljdGlvbnMuZGF0YVN5bmMoKTtcclxuICAgIC8vIGNvbnNvbGUubG9nKCBwcmVkaWN0aW9ucy5kYXRhU3luYygpKTtcclxuXHJcbiAgICAvLyByZWZlcmVuY2VfYXV4LmZvckVhY2goKGVsZW1lbnQsIGluZGV4KSA9PiB7XHJcbiAgICAvLyAgIGlmKClcclxuICAgICAgXHJcbiAgICAvLyB9KTsgIFxyXG5cclxuXHJcbiAgICAgICAgcmV0dXJuIHsgcmVmZXJlbmNlLCBwcmVkaWN0aW9ucyB9OyAgXHJcblxyXG59XHJcblxyXG59Ly9lbmQgb2YgY2xhc3NcclxuXHJcblxyXG5cclxuXHJcblxyXG4vKioqU3VwcG9ydCBtZXRob2RzIChoZWxwZXJzKSAqL1xyXG5cclxuY29uc3QgaXNUZW5zb3IgPSAoYzogYW55KTogYyBpcyB0Zi5UZW5zb3IgPT5cclxuICAgIHR5cGVvZiBjLmRhdGFJZCA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIGMuc2hhcGUgPT09ICdvYmplY3QnO1xyXG4vKipcclxuICogQ29udmVydHMgYW4gaW50ZWdlciBpbnRvIGl0cyBvbmUtaG90IHJlcHJlc2VudGF0aW9uIGFuZCByZXR1cm5zXHJcbiAqIHRoZSBkYXRhIGFzIGEgSlMgQXJyYXkuXHJcbiAqL1xyXG5mdW5jdGlvbiBmbGF0T25lSG90KGxhYmVsOiBudW1iZXIsIG51bUNsYXNzZXM6IG51bWJlcikge1xyXG5cclxuICBjb25zdCBsYWJlbE9uZUhvdCA9IG5ldyBBcnJheShudW1DbGFzc2VzKS5maWxsKDApIGFzIG51bWJlcltdO1xyXG4gIGxhYmVsT25lSG90W2xhYmVsXSA9IDE7XHJcblxyXG4gIHJldHVybiBsYWJlbE9uZUhvdDtcclxufVxyXG5cclxuaW50ZXJmYWNlIFNhbXBsZSB7XHJcbiAgZGF0YTogRmxvYXQzMkFycmF5O1xyXG4gIGxhYmVsOiBudW1iZXJbXTtcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiBTaHVmZmxlIGFuIGFycmF5IG9mIEZsb2F0MzJBcnJheSBvciBTYW1wbGVzIHVzaW5nIEZpc2hlci1ZYXRlcyBhbGdvcml0aG1cclxuICogVGFrZXMgYW4gb3B0aW9uYWwgc2VlZCB2YWx1ZSB0byBtYWtlIHNodWZmbGluZyBwcmVkaWN0YWJsZVxyXG4gKi9cclxuZnVuY3Rpb24gZmlzaGVyWWF0ZXMoYXJyYXk6IEZsb2F0MzJBcnJheVtdIHwgU2FtcGxlW10sIHNlZWQ/OiBzZWVkcmFuZG9tLnBybmcpIHtcclxuICBjb25zdCBsZW5ndGggPSBhcnJheS5sZW5ndGg7XHJcblxyXG4gIC8vIG5lZWQgdG8gY2xvbmUgYXJyYXkgb3Igd2UnZCBiZSBlZGl0aW5nIG9yaWdpbmFsIGFzIHdlIGdvb1xyXG4gIGNvbnN0IHNodWZmbGVkID0gYXJyYXkuc2xpY2UoKTtcclxuXHJcbiAgZm9yIChsZXQgaSA9IChsZW5ndGggLSAxKTsgaSA+IDA7IGkgLT0gMSkge1xyXG4gICAgICBsZXQgcmFuZG9tSW5kZXggO1xyXG4gICAgICBpZiAoc2VlZCkge1xyXG4gICAgICAgICAgcmFuZG9tSW5kZXggPSBNYXRoLmZsb29yKHNlZWQoKSAqIChpICsgMSkpO1xyXG4gICAgICB9XHJcbiAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgcmFuZG9tSW5kZXggPSBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAoaSArIDEpKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgW3NodWZmbGVkW2ldLCBzaHVmZmxlZFtyYW5kb21JbmRleF1dID0gW3NodWZmbGVkW3JhbmRvbUluZGV4XSxzaHVmZmxlZFtpXV07XHJcbiAgfVxyXG5cclxuICByZXR1cm4gc2h1ZmZsZWQ7XHJcbn1cclxuIl19
@@ -6,4 +6,5 @@ export * from './lib/tfjs-evolution.component';
6
6
  export * from './lib/components/display-panel/display-panel.component';
7
7
  export * from './lib/models/teachable-evolution';
8
8
  export * from './lib/Classes/genetic-algorithm';
9
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL3RmanMtZXZvbHV0aW9uL3NyYy9wdWJsaWMtYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsY0FBYyw4QkFBOEIsQ0FBQztBQUM3QyxjQUFjLGdDQUFnQyxDQUFDO0FBRS9DLGNBQWMsd0RBQXdELENBQUM7QUFFdkUsY0FBYyxrQ0FBa0MsQ0FBQztBQUVqRCxjQUFjLGlDQUFpQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcclxuICogUHVibGljIEFQSSBTdXJmYWNlIG9mIHRmanMtZXZvbHV0aW9uXHJcbiAqL1xyXG5cclxuZXhwb3J0ICogZnJvbSAnLi9saWIvdGZqcy1ldm9sdXRpb24uc2VydmljZSc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL3RmanMtZXZvbHV0aW9uLmNvbXBvbmVudCc7XHJcblxyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9jb21wb25lbnRzL2Rpc3BsYXktcGFuZWwvZGlzcGxheS1wYW5lbC5jb21wb25lbnQnO1xyXG5cclxuZXhwb3J0ICogZnJvbSAnLi9saWIvbW9kZWxzL3RlYWNoYWJsZS1ldm9sdXRpb24nO1xyXG5cclxuZXhwb3J0ICogZnJvbSAnLi9saWIvQ2xhc3Nlcy9nZW5ldGljLWFsZ29yaXRobSc7XHJcbiJdfQ==
9
+ export * from './lib/components/metrics/metrics.component';
10
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL3RmanMtZXZvbHV0aW9uL3NyYy9wdWJsaWMtYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsY0FBYyw4QkFBOEIsQ0FBQztBQUM3QyxjQUFjLGdDQUFnQyxDQUFDO0FBRS9DLGNBQWMsd0RBQXdELENBQUM7QUFFdkUsY0FBYyxrQ0FBa0MsQ0FBQztBQUVqRCxjQUFjLGlDQUFpQyxDQUFDO0FBRWhELGNBQWMsNENBQTRDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxyXG4gKiBQdWJsaWMgQVBJIFN1cmZhY2Ugb2YgdGZqcy1ldm9sdXRpb25cclxuICovXHJcblxyXG5leHBvcnQgKiBmcm9tICcuL2xpYi90ZmpzLWV2b2x1dGlvbi5zZXJ2aWNlJztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvdGZqcy1ldm9sdXRpb24uY29tcG9uZW50JztcclxuXHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL2NvbXBvbmVudHMvZGlzcGxheS1wYW5lbC9kaXNwbGF5LXBhbmVsLmNvbXBvbmVudCc7XHJcblxyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9tb2RlbHMvdGVhY2hhYmxlLWV2b2x1dGlvbic7XHJcblxyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9DbGFzc2VzL2dlbmV0aWMtYWxnb3JpdGhtJztcclxuXHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL2NvbXBvbmVudHMvbWV0cmljcy9tZXRyaWNzLmNvbXBvbmVudCc7XHJcbiJdfQ==
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, Component } from '@angular/core';
2
+ import { Injectable, Component, Input } from '@angular/core';
3
3
  import * as i1 from '@angular/common';
4
4
  import { CommonModule } from '@angular/common';
5
5
  import * as tf from '@tensorflow/tfjs';
@@ -695,6 +695,8 @@ class TeachableMobileNet extends CustomMobileNet {
695
695
  datasetForEvaluation() {
696
696
  }
697
697
  async evaluate() {
698
+ //Check of the features have already been calculated
699
+ /**For avoiding recalculating the features every generation */
698
700
  if (!TeachableMobileNet.feature_aux) {
699
701
  const features = [];
700
702
  const targets = [];
@@ -711,7 +713,9 @@ class TeachableMobileNet extends CustomMobileNet {
711
713
  TeachableMobileNet.feature_aux = tf.tensor(features);
712
714
  TeachableMobileNet.target_aux = tf.tensor(targets);
713
715
  }
716
+ //Evaluating the model
714
717
  const aux = this.trainingModel.evaluate(TeachableMobileNet.feature_aux, TeachableMobileNet.target_aux);
718
+ //Return just the accuracy
715
719
  return aux[1].dataSync()[0];
716
720
  }
717
721
  // async evaluate(){
@@ -848,6 +852,9 @@ class DisplayPanelComponent {
848
852
  if (!options.file_name && (options.subfolder)) {
849
853
  class_add.push(`${options.base}/${name}/${options.subfolder}/${name} ${i + 1}.${options.file_extension}`);
850
854
  }
855
+ else if (options.numbered) {
856
+ class_add.push(`${options.base}/${name}/${i + 1}.${options.file_extension}`);
857
+ }
851
858
  else
852
859
  class_add.push(`${options.base}/${name}/${options.file_name} ${i + 1}.${options.file_extension}`);
853
860
  }
@@ -918,8 +925,6 @@ class NeuroEvolution {
918
925
  for (let i = 0; i < this.population_size; i++) {
919
926
  this.population.push({ individual: new TeachableMobileNet() });
920
927
  }
921
- // console.log("Population length: ", this.population.length);
922
- // console.log("Memory after population iniialization: ", tf.memory().numBytes);
923
928
  }
924
929
  async apply_evolution(iteration) {
925
930
  for (let i = 0; i < iteration; i++) {
@@ -1125,6 +1130,26 @@ class GeneticAlgorithm extends NeuroEvolution {
1125
1130
  }
1126
1131
  }
1127
1132
 
1133
+ class MetricsComponent {
1134
+ constructor() {
1135
+ this.accuracy_per_class = [];
1136
+ this.classes_names = [];
1137
+ this.confusion_matrix = [];
1138
+ }
1139
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: MetricsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1140
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: MetricsComponent, isStandalone: true, selector: "neuroevolution-metrics", inputs: { accuracy_per_class: "accuracy_per_class", classes_names: "classes_names", confusion_matrix: "confusion_matrix" }, ngImport: i0, template: "<h1>Accuracy per class</h1>\r\n<div *ngFor=\"let accuracy of accuracy_per_class; index as index\" > {{classes_names[index]}}: {{accuracy}}%</div>\r\n\r\n\r\n\r\n<h2>Confusion Matrix</h2>\r\n\r\n<table>\r\n <tr>\r\n <th *ngFor=\"let label of classes_names\">{{label}}</th>\r\n </tr>\r\n <tr *ngFor=\"let item of confusion_matrix ; index as i\">\r\n <td *ngFor=\"let value of item ; index as j\" > {{confusion_matrix[i][j]}}%</td> \r\n </tr>\r\n</table>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] }); }
1141
+ }
1142
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: MetricsComponent, decorators: [{
1143
+ type: Component,
1144
+ args: [{ selector: 'neuroevolution-metrics', standalone: true, imports: [CommonModule], template: "<h1>Accuracy per class</h1>\r\n<div *ngFor=\"let accuracy of accuracy_per_class; index as index\" > {{classes_names[index]}}: {{accuracy}}%</div>\r\n\r\n\r\n\r\n<h2>Confusion Matrix</h2>\r\n\r\n<table>\r\n <tr>\r\n <th *ngFor=\"let label of classes_names\">{{label}}</th>\r\n </tr>\r\n <tr *ngFor=\"let item of confusion_matrix ; index as i\">\r\n <td *ngFor=\"let value of item ; index as j\" > {{confusion_matrix[i][j]}}%</td> \r\n </tr>\r\n</table>\r\n" }]
1145
+ }], propDecorators: { accuracy_per_class: [{
1146
+ type: Input
1147
+ }], classes_names: [{
1148
+ type: Input
1149
+ }], confusion_matrix: [{
1150
+ type: Input
1151
+ }] } });
1152
+
1128
1153
  /*
1129
1154
  * Public API Surface of tfjs-evolution
1130
1155
  */
@@ -1133,5 +1158,5 @@ class GeneticAlgorithm extends NeuroEvolution {
1133
1158
  * Generated bundle index. Do not edit.
1134
1159
  */
1135
1160
 
1136
- export { DisplayPanelComponent, GeneticAlgorithm, TeachableMobileNet, TfjsEvolutionComponent, TfjsEvolutionService };
1161
+ export { DisplayPanelComponent, GeneticAlgorithm, MetricsComponent, TeachableMobileNet, TfjsEvolutionComponent, TfjsEvolutionService };
1137
1162
  //# sourceMappingURL=tfjs-evolution.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"tfjs-evolution.mjs","sources":["../../../projects/tfjs-evolution/src/lib/tfjs-evolution.service.ts","../../../projects/tfjs-evolution/src/lib/tfjs-evolution.component.ts","../../../projects/tfjs-evolution/src/lib/models/custom-mobilenet.ts","../../../projects/tfjs-evolution/src/lib/utils/tf.ts","../../../projects/tfjs-evolution/src/lib/utils/util.ts","../../../projects/tfjs-evolution/src/lib/models/teachable-evolution.ts","../../../projects/tfjs-evolution/src/lib/components/display-panel/display-panel.component.ts","../../../projects/tfjs-evolution/src/lib/components/display-panel/display-panel.component.html","../../../projects/tfjs-evolution/src/lib/Classes/neuro-evolution.ts","../../../projects/tfjs-evolution/src/lib/Classes/genetic-algorithm.ts","../../../projects/tfjs-evolution/src/public-api.ts","../../../projects/tfjs-evolution/src/tfjs-evolution.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class TfjsEvolutionService {\r\n\r\n constructor() { }\r\n}\r\n","import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'neuroevolution-tfjs-evolution',\r\n standalone: true,\r\n imports: [],\r\n template: `\r\n <p>\r\n tfjs-evolution works!\r\n </p>\r\n `,\r\n styles: ``\r\n})\r\nexport class TfjsEvolutionComponent {\r\n\r\n}\r\n","\r\nimport * as tf from '@tensorflow/tfjs';\r\n\r\nimport { SymbolicTensor } from '@tensorflow/tfjs';\r\n\r\n\r\nexport const IMAGE_SIZE = 224;\r\n\r\n\r\n/**\r\n * the metadata to describe the model's creation,\r\n * includes the labels associated with the classes\r\n * and versioning information from training.\r\n */\r\nexport interface Metadata {\r\n tfjsVersion: string;\r\n tmVersion?: string;\r\n packageVersion: string;\r\n packageName: string;\r\n modelName?: string;\r\n timeStamp?: string;\r\n labels: string[];\r\n userMetadata?: {};\r\n grayscale?: boolean;\r\n imageSize?: number;\r\n}\r\n\r\nexport interface ModelOptions {\r\n version?: number;\r\n checkpointUrl?: string;\r\n alpha?: number;\r\n trainingLayer?: string;\r\n}\r\n\r\nconst DEFAULT_MOBILENET_VERSION = 2;\r\nconst DEFAULT_TRAINING_LAYER_V1 = 'conv_pw_13_relu';\r\nconst DEFAULT_TRAINING_LAYER_V2 = \"out_relu\"; \r\nconst DEFAULT_ALPHA_V1_v2 = 0.35;\r\nconst DEFAULT_ALPHA_V1 = 0.25;//256\r\nconst DEFAULT_ALPHA_V2 = 0.5; //512\r\nconst DEFAULT_ALPHA_V3 = 0.75;//768 features\r\nconst DEFAULT_ALPHA_V4 = 1;//1024 features\r\nconst DEFAULT_ALPHA = 1;//1024 features\r\n\r\n// v2: 0.35, 0.50, 0.75 or 1.00.\r\n\r\nconst isAlphaValid = (version: number, alpha: number) => {\r\n if (version === 1) {\r\n if (alpha !== 0.25 && alpha !== 0.5 && alpha !== 0.75 && alpha !== 1) {\r\n console.warn(\"Invalid alpha. Options are: 0.25, 0.50, 0.75 or 1.00.\");\r\n console.log(\"Loading model with alpha: \", DEFAULT_ALPHA_V1.toFixed(2)); \r\n return DEFAULT_ALPHA_V1;\r\n }\r\n }\r\n else {\r\n if (alpha !== 0.35 && alpha !== 0.5 && alpha !== 0.75 && alpha !== 1) {\r\n console.warn(\"Invalid alpha. Options are: 0.35, 0.50, 0.75 or 1.00.\");\r\n console.log(\"Loading model with alpha: \", DEFAULT_ALPHA_V2.toFixed(2)); \r\n return DEFAULT_ALPHA_V2;\r\n }\r\n }\r\n\r\n return alpha;\r\n};\r\n\r\n\r\nconst parseModelOptions = (options?: ModelOptions) => {\r\n options = options || {}\r\n\r\n if (options.checkpointUrl && options.trainingLayer) {\r\n if (options.alpha || options.version){\r\n console.warn(\"Checkpoint URL passed to modelOptions, alpha options are ignored\");\r\n } \r\n return [options.checkpointUrl, options.trainingLayer];\r\n } else {\r\n options.version = options.version || DEFAULT_MOBILENET_VERSION;\r\n \r\n if(options.version === 1){\r\n options.alpha = options.alpha || DEFAULT_ALPHA_V4; \r\n options.alpha = isAlphaValid(options.version, options.alpha);\r\n\r\n console.log(`Loading mobilenet ${options.version} and alpha ${options.alpha}`);\r\n // exception is alpha o f 1 can only be 1.0\r\n let alphaString = options.alpha.toFixed(2);\r\n if (alphaString === \"1.00\") { alphaString = \"1.0\"; }\r\n\r\n console.log(\"Using the model: \", )\r\n\r\n return [\r\n // tslint:disable-next-line:max-line-length\r\n //They are loading MobileNet_v1 \r\n `https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_${alphaString}_${IMAGE_SIZE}/model.json`,\r\n DEFAULT_TRAINING_LAYER_V1\r\n ];\r\n }\r\n else if (options.version === 2){\r\n options.alpha = options.alpha || DEFAULT_ALPHA_V4; \r\n options.alpha = isAlphaValid(options.version, options.alpha);\r\n\r\n console.log(`Loading mobilenet ${options.version} and alpha ${options.alpha}`);\r\n console.log(`Loading mobilenet ${options.version} and alpha ${options.alpha}`);\r\n\r\n return [\r\n // tslint:disable-next-line:max-line-length \r\n `https://storage.googleapis.com/teachable-machine-models/mobilenet_v2_weights_tf_dim_ordering_tf_kernels_${options.alpha.toFixed(2)}_${IMAGE_SIZE}_no_top/model.json`,\r\n DEFAULT_TRAINING_LAYER_V2\r\n ];\r\n } else {\r\n throw new Error(`MobileNet V${options.version} doesn't exist`);\r\n } \r\n }\r\n};\r\n\r\n\r\n/**\r\n * load the base mobilenet model\r\n * @param modelOptions options determining what model to load\r\n */\r\nexport async function loadTruncatedMobileNet(modelOptions?: ModelOptions) {\r\n const [checkpointUrl, trainingLayer] = parseModelOptions(modelOptions);\r\n \r\n \r\n const mobilenet = await tf.loadLayersModel(checkpointUrl);\r\n\r\n if (modelOptions && modelOptions.version === 1){\r\n const layer = mobilenet.getLayer(trainingLayer);\r\n \r\n const truncatedModel = tf.model({ inputs: mobilenet.inputs, outputs: layer.output });\r\n console.log(\"Feature model loaded, memory: \", tf.memory().numBytes);\r\n\r\n \r\n const model = tf.sequential();\r\n model.add(truncatedModel);\r\n model.add(tf.layers.flatten()); \r\n \r\n \r\n return model;\r\n }\r\n else {\r\n const layer = mobilenet.getLayer(trainingLayer);\r\n const truncatedModel = tf.model({ inputs: mobilenet.inputs, outputs: layer.output });\r\n console.log(\"Feature model loaded, memory: \", tf.memory().numBytes);\r\n const model = tf.sequential();\r\n model.add(truncatedModel);\r\n model.add(tf.layers.globalAveragePooling2d({})); // go from shape [7, 7, 1280] to [1280]\r\n return model;\r\n }\r\n}\r\n\r\n\r\nexport class CustomMobileNet {\r\n /**\r\n * the truncated mobilenet model we will train on top of\r\n */\r\n protected truncatedModel!: tf.LayersModel;\r\n static truncatedModel: tf.Sequential;\r\n\r\nstatic getinputShape(){\r\n /**truncatedModel is the base model, the model used to apply transfer learning */\r\n const inputShape: any = this.truncatedModel.outputs[0].shape.slice(1); // [ 7 x 7 x 1280] (not sure about those dimensions)\r\n// console.log(\"Input Shape(complete): \", this.truncatedModel.outputs[0].shape);\r\n// console.log(\"Input Shape: \", inputShape);\r\n\r\n const inputSize = tf.util.sizeFromShape(inputShape);\r\n\r\n// console.log(\"Input Size: \", inputSize);\r\n\r\n return inputSize;\r\n}\r\n\r\n static get EXPECTED_IMAGE_SIZE() {\r\n return IMAGE_SIZE;\r\n }\r\n\r\n protected _metadata!: Metadata;\r\n\r\n public getMetadata() {\r\n return this._metadata;\r\n }\r\n\r\n constructor() {\r\n // this._metadata = fillMetadata(metadata);\r\n //Loading the truncated model\r\n // loadTruncatedMobileNet();\r\n // this.loadFeatureModel();\r\n\r\n }\r\n\r\n static async loadFeatureModel(){\r\n\r\n this.truncatedModel = await loadTruncatedMobileNet();\r\n\r\n }\r\n\r\n /**\r\n * get the total number of classes existing within model\r\n */\r\n // getTotalClasses() {\r\n // const output = this.model.output as SymbolicTensor;\r\n // const totalClasses = output.shape[1];\r\n // return totalClasses;\r\n // }\r\n\r\n /**\r\n * get the model labels\r\n */\r\n getClassLabels() {\r\n return this._metadata.labels;\r\n }\r\n\r\n /**\r\n * Given an image element, makes a prediction through mobilenet returning the\r\n * probabilities of the top K classes.\r\n * @param image the image to classify\r\n * @param maxPredictions the maximum number of classification predictions\r\n */\r\n // async predictTopK(image: ClassifierInputSource, maxPredictions = 10, flipped = false) {\r\n // const croppedImage = cropTo(image, this._metadata.imageSize, flipped);\r\n\r\n // const logits = tf.tidy(() => {\r\n // const captured = capture(croppedImage, this._metadata.grayscale);\r\n // return this.model.predict(captured);\r\n // });\r\n\r\n // // Convert logits to probabilities and class names.\r\n // const classes = await getTopKClasses(this._metadata.labels, logits as tf.Tensor<tf.Rank>, maxPredictions);\r\n // dispose(logits);\r\n\r\n // return classes;\r\n // }\r\n\r\n /**\r\n * Given an image element, makes a prediction through mobilenet returning the\r\n * probabilities for ALL classes.\r\n * @param image the image to classify\r\n * @param flipped whether to flip the image on X\r\n */\r\n // async predict(image: ClassifierInputSource, flipped = false) {\r\n // const croppedImage = cropTo(image, this._metadata.imageSize, flipped);\r\n\r\n // const logits = tf.tidy(() => {\r\n // const captured = capture(croppedImage, this._metadata.grayscale);\r\n // return this.model.predict(captured);\r\n // });\r\n\r\n // const values = await (logits as tf.Tensor<tf.Rank>).data();\r\n\r\n // const classes = [];\r\n // for (let i = 0; i < values.length; i++) {\r\n // classes.push({\r\n // className: this._metadata.labels[i],\r\n // probability: values[i]\r\n // });\r\n // }\r\n\r\n // dispose(logits);\r\n\r\n // return classes;\r\n // }\r\n\r\n public dispose() {\r\n this.truncatedModel.dispose();\r\n }\r\n}// end of CustomMobileNet\r\n","import * as tf from '@tensorflow/tfjs';\r\n\r\n/**\r\n * Receives an image and normalizes it between -1 and 1.\r\n * Returns a batched image (1 - element batch) of shape [1, w, h, c]\r\n * @param rasterElement the element with pixels to convert to a Tensor\r\n * @param grayscale optinal flag that changes the crop to [1, w, h, 1]\r\n */\r\nexport function capture(rasterElement: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement, grayscale?: boolean) {\r\n return tf.tidy(() => {\r\n // console.log(\"Not a tensor....\")\r\n const pixels = tf.browser.fromPixels(rasterElement);\r\n\r\n // crop the image so we're using the center square\r\n const cropped = cropTensor(pixels);\r\n\r\n // Expand the outer most dimension so we have a batch size of 1\r\n const batchedImage = cropped.expandDims(0);\r\n\r\n // Normalize the image between -1 and a1. The image comes in between 0-255\r\n // so we divide by 127 and subtract 1.\r\n return batchedImage.toFloat().div(tf.scalar(127)).sub(tf.scalar(1));\r\n });\r\n}\r\n\r\n\r\n\r\nexport function cropTensor( img: tf.Tensor3D ) : tf.Tensor3D {\r\n \r\n const size = Math.min(img.shape[0], img.shape[1]);\r\n const centerHeight = img.shape[0] / 2;\r\n const beginHeight = centerHeight - (size / 2);\r\n const centerWidth = img.shape[1] / 2;\r\n const beginWidth = centerWidth - (size / 2);\r\n \r\n\r\n return img.slice([beginHeight, beginWidth, 0], [size, size, 3]);\r\n}","\r\nimport {Class} from \"./class\"\r\nimport * as tf from '@tensorflow/tfjs';\r\n\r\n\r\nexport class Util {\r\n\r\n/**\r\n * Receives an image and normalizes it between -1 and 1.\r\n * Returns a batched image (1 - element batch) of shape [1, w, h, c]\r\n * @param rasterElement the element with pixels to convert to a Tensor\r\n * @param grayscale optinal flag that changes the crop to [1, w, h, 1]\r\n */\r\ncapture(rasterElement: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement, grayscale?: boolean) {\r\n return tf.tidy(() => {\r\n const pixels = tf.browser.fromPixels(rasterElement);\r\n\r\n // // crop the image so we're using the center square\r\n const cropped = this.cropTensor(pixels, grayscale);\r\n\r\n // // Expand the outer most dimension so we have a batch size of 1\r\n const batchedImage = cropped.expandDims(0);\r\n\r\n // // Normalize the image between -1 and a1. The image comes in between 0-255\r\n // // so we divide by 127 and subtract 1.\r\n return batchedImage.toFloat().div(tf.scalar(127)).sub(tf.scalar(1)); \r\n });\r\n} \r\n\r\n\r\ncropTensor( img: tf.Tensor3D, grayscaleModel?: boolean, grayscaleInput?: boolean ) : tf.Tensor3D {\r\n const size = Math.min(img.shape[0], img.shape[1]);\r\n const centerHeight = img.shape[0] / 2;\r\n const beginHeight = centerHeight - (size / 2);\r\n const centerWidth = img.shape[1] / 2;\r\n const beginWidth = centerWidth - (size / 2);\r\n \r\n if (grayscaleModel && !grayscaleInput) {\r\n //cropped rgb data\r\n let grayscale_cropped = img.slice([beginHeight, beginWidth, 0], [size, size, 3]);\r\n \r\n grayscale_cropped = grayscale_cropped.reshape([size * size, 1, 3])\r\n const rgb_weights = [0.2989, 0.5870, 0.1140]\r\n grayscale_cropped = tf.mul(grayscale_cropped, rgb_weights)\r\n grayscale_cropped = grayscale_cropped.reshape([size, size, 3]);\r\n \r\n grayscale_cropped = tf.sum(grayscale_cropped, -1)\r\n grayscale_cropped = tf.expandDims(grayscale_cropped, -1)\r\n\r\n return grayscale_cropped;\r\n }\r\n return img.slice([beginHeight, beginWidth, 0], [size, size, 3]);\r\n}\r\n\r\n\r\n\r\n\r\n/**\r\n * This function will make a copy of a model on the weight level\r\n * This is an attempt to avoid influencing the new mode when the old one\r\n * is eliminated. \r\n * \r\n * @param originalModel - the model to be copied \r\n * @param recipient - the new model\r\n */\r\nasync copyModel_v3 (originalModel: tf.Sequential, recipient: tf.Sequential) {\r\n\r\n originalModel.layers.forEach((layer, index)=>{\r\n recipient.layers[index].setWeights(layer.getWeights())\r\n })\r\n\r\n // originalModel.dispose();\r\n}\r\n \r\n/**\r\n * This function will make a copy of a TFJS model, as so it would be possible \r\n * to erase the original.\r\n * @param model - model to be copied\r\n * @returns - copy of the model\r\n */ \r\nasync copyModel_v2 (originalModel: tf.Sequential) {\r\n // Serialize the original model\r\n const modelTopology = originalModel.toJSON();\r\n\r\n // Load the serialized model into a new model\r\n const copiedModel = await tf.loadLayersModel(\r\n tf.io.fromMemory(modelTopology, undefined, undefined)\r\n );\r\n \r\n // Compile the copied model with the same settings as the original\r\n copiedModel.compile({\r\n loss: originalModel.loss,\r\n optimizer: originalModel.optimizer\r\n });\r\n \r\n return copiedModel;\r\n}\r\n\r\n/**\r\n * This function will make a copy of a TFJS model, as so it would be possible \r\n * to erase the original.\r\n * @param model - model to be copied\r\n * @returns - copy of the model\r\n */ \r\ncopyModel (model: tf.Sequential) {\r\n \r\n const copy = tf.sequential();`\r\n `\r\n model.layers.forEach(layer => {\r\n const aux =layer;\r\n // layer.dispose();\r\n copy.add(aux);\r\n });\r\n copy.compile({\r\n loss: model.loss,\r\n optimizer: model.optimizer\r\n });\r\n return copy;\r\n }\r\n\r\n\r\n removeElementByIndex(arr: any, index: number): number[] {\r\n // Check if the index is within bounds\r\n if (index >= 0 && index < arr.length) {\r\n // Remove the element at the specified index\r\n arr.splice(index, 1); \r\n }\r\n return arr;\r\n }\r\n\r\n removeElement(arr: any, element: any): number[] {\r\n // Remove all occurrences of the specified element from the array\r\n return arr.filter((item: any) => item !== element);\r\n }\r\n\r\nclean_array_of_tensors(tensors: tf.Sequential[]) {\r\n\r\n tensors.forEach((elem, index)=>{ \r\n // if(!index_selection.includes(index)) \r\n elem.dispose() \r\n });\r\n\r\n}\r\n\r\n getClassNameBySignature(classes: Class[], signature: number[]) { \r\n \r\n const class_name = classes.find(p => {\r\n let match = true;\r\n p.signature?.forEach ((elem,index)=>{ \r\n if(elem!==signature[index])\r\n match=false; \r\n })\r\n\r\n return match;\r\n });\r\n\r\n return class_name ? class_name.name : \"not found\";\r\n}\r\n\r\nidentityMatrix(n: number): number[][] {\r\n return Array.from({ length: n }, (_, i) => Array.from({ length: n }, (_, j) => (i === j ? 1 : 0)));\r\n} \r\n\r\n\r\nindexOfMax(arr: number[]): number {\r\n if (arr.length === 0) {\r\n return -1; // Return -1 for an empty array\r\n }\r\n \r\n let max = arr[0];\r\n let maxIndex = 0;\r\n \r\n for (let i = 1; i < arr.length; i++) {\r\n if (arr[i] > max) {\r\n maxIndex = i;\r\n max = arr[i];\r\n }\r\n }\r\n \r\n return maxIndex;\r\n }\r\n\r\n\r\nsuffle(array1:any, array2: any){\r\n // Shuffle the order of elements\r\n for (let i = array1.length - 1; i > 0; i--) {\r\n const j = Math.floor(Math.random() * (i + 1));\r\n\r\n // Swap elements in both arrays\r\n [array1[i], array1[j]] = [array1[j], array1[i]];\r\n [array2[i], array2[j]] = [array2[j], array2[i]];\r\n }\r\n \r\n \r\n }\r\n\r\n sortByValuePreservingIndex<T>(\r\n arr1: number[],\r\n arr2: any[]\r\n ): T[] {\r\n\r\n // console.log(\"Vector for organizing: \", arr1)\r\n // arr2[0].summary()\r\n\r\n // Create an array of objects with value, index from arr1, and original index\r\n const pairingArray = arr1.map((value, index) => ({\r\n value,\r\n index,\r\n originalIndex: index,\r\n elementFromArr2: arr2[index], // Preserve the corresponding element from arr2\r\n }));\r\n \r\n // Sort the pairing array by value (largest to smallest)\r\n pairingArray.sort((a, b) => b.value - a.value);\r\n\r\n \r\n \r\n // Extract the sorted elements from arr2 based on the original index\r\n const sortedElementsFromArr2 = pairingArray.map(pair => pair.elementFromArr2);\r\n \r\n return sortedElementsFromArr2;\r\n } \r\n \r\n}\r\n\r\n","import { CustomMobileNet, loadTruncatedMobileNet } from \"./custom-mobilenet\";\r\n\r\nimport * as tf from '@tensorflow/tfjs';\r\n\r\nimport { capture } from '../utils/tf';\r\nimport { Class } from '../utils/class';\r\nimport { Util } from \"../utils/util\";\r\n\r\nimport * as seedrandom from 'seedrandom';\r\n\r\nimport * as tfvis from '@tensorflow/tfjs-vis';\r\n\r\nimport { TensorContainer } from '@tensorflow/tfjs-core/dist/tensor_types';\r\n\r\nconst VALIDATION_FRACTION = 0.15;\r\n\r\n\r\n\r\n/**\r\n * the metadata to describe the model's creation,\r\n * includes the labels associated with the classes\r\n * and versioning information from training.\r\n */\r\nexport interface Metadata {\r\n tfjsVersion: string;\r\n tmVersion?: string;\r\n packageVersion: string;\r\n packageName: string;\r\n modelName?: string;\r\n timeStamp?: string;\r\n labels: string[];\r\n userMetadata?: {};\r\n grayscale?: boolean;\r\n imageSize?: number;\r\n}\r\n\r\n/**\r\n * Receives a Metadata object and fills in the optional fields such as timeStamp\r\n * @param data a Metadata object\r\n */\r\nconst fillMetadata = (data: Partial<Metadata>) => {\r\n // util.assert(typeof data.tfjsVersion === 'string', () => `metadata.tfjsVersion is invalid`);\r\n // data.packageVersion = data.packageVersion || version;\r\n data.packageName = data.packageName || '@teachablemachine/image';\r\n data.timeStamp = data.timeStamp || new Date().toISOString();\r\n data.userMetadata = data.userMetadata || {};\r\n data.modelName = data.modelName || 'untitled';\r\n data.labels = data.labels || [];\r\n // data.imageSize = data.imageSize || IMAGE_SIZE;\r\n return data as Metadata;\r\n};\r\n\r\nexport class TeachableMobileNet extends CustomMobileNet {\r\n\r\n // Array of all the examples collected.\r\n /**\r\n It is static since all the instance will share the same features, for saving memory and time.\r\n The idea is avoiding restoring the features individually and having the recalculate them for every new\r\n individuals.\r\n */\r\n public static examples: Float32Array[][] = [];\r\n\r\n // Number of total samples\r\n private static totalSamples = 0;\r\n\r\n classes: Class[]=[];\r\n\r\n static classes_names: string[]=[];\r\n\r\n static numClasses: number;\r\n\r\n /**\r\n * the training model for transfer learning\r\n */\r\n protected trainingModel!: tf.LayersModel;\r\n trainDataset: any;\r\n validationDataset: any;\r\n static trainDataset: any;\r\n static validationDataset: any;\r\n static numValidation: number;\r\n\r\n constructor(){\r\n super();\r\n this.createHead();\r\n }\r\n\r\n /**\r\n * This method will return the head, the trainable part, the part under evolution.\r\n */\r\n getHead(){\r\n return this.trainingModel;\r\n }\r\n\r\n /**\r\n * Create the head for transfer learning.\r\n * This is the trainable section of the transfer learning.\r\n */\r\n createHead(){\r\n\r\n const inputSize= TeachableMobileNet.getinputShape();\r\n\r\n this.trainingModel = tf.sequential({\r\n layers: [\r\n tf.layers.dense({\r\n inputShape: [inputSize],\r\n units:100,\r\n activation: 'relu', \r\n useBias: true\r\n }),\r\n tf.layers.dense({ \r\n useBias: false,\r\n activation: 'softmax',\r\n units: TeachableMobileNet.classes_names.length\r\n })\r\n ]\r\n });\r\n\r\n const optimizer = tf.train.adam();\r\n // const optimizer = tf.train.rmsprop(params.learningRate);\r\n\r\n this.trainingModel.compile({\r\n optimizer,\r\n // loss: 'binaryCrossentropy',\r\n loss: 'categoricalCrossentropy',\r\n metrics: ['accuracy']\r\n });\r\n }\r\n \r\n async train(){\r\n\r\n const trainingSurface = { name: 'Loss and MSE', tab: 'Training' };\r\n\r\n const dataset= TeachableMobileNet.convertToTfDataset();\r\n\r\n //Salving a copy of the validation dataset, for later\r\n TeachableMobileNet.validationDataset= dataset.validationDataset;\r\n\r\n // console.log(\"Dataset for training: \", dataset.trainDataset);\r\n\r\n const trainData = dataset.trainDataset.batch(30);\r\n const validationData = dataset.validationDataset.batch(10);\r\n\r\n // this.createHead();\r\n\r\n const callbacks= [\r\n // Show on a tfjs-vis visor the loss and accuracy values at the end of each epoch.\r\n tfvis.show.fitCallbacks(trainingSurface, ['loss', 'acc', \"val_loss\", \"val_acc\"],\r\n {\r\n callbacks: ['onEpochEnd'],\r\n }\r\n ),\r\n {},]\r\n\r\n const history: any = await this.trainingModel.fitDataset(trainData, {\r\n epochs: 100,\r\n validationData,\r\n callbacks\r\n}).then((info:any)=>{\r\n console.log('Precisão final', info.history.val_acc[info.history.acc.length-1]);\r\n});\r\n\r\n\r\n// await this.accuracy_per_class();\r\n\r\n\r\n// console.log(\"History: \", history.history.acc);\r\n // await this.trainingModel.fit(this.featureX, this.target, {})\r\n }\r\n\r\nasync accuracy_per_class(confusion_matrix_recipient: any){\r\n /**Calculating Accuracy per class */\r\nconst accuracyperclass: any = await this.calculateAccuracyPerClass(TeachableMobileNet.validationDataset);\r\n// console.log(\"Accuracy per class: \", accuracyperclass);\r\n\r\n//Confusion matrix\r\n// Calling tf.confusionMatrix() method \r\nconst output = tf.math.confusionMatrix( accuracyperclass.reference, accuracyperclass.predictions, TeachableMobileNet.classes_names.length); \r\n \r\n// Printing output \r\noutput.print()\r\nconst confusion_matrix= output.dataSync();\r\n\r\n// console.log(confusion_matrix);\r\n// console.log(confusion_matrix[TeachableMobileNet.classes_names.length + TeachableMobileNet.classes_names.length]);\r\n\r\nconst accuracy = [];\r\n\r\nfor(let i=0; i<TeachableMobileNet.classes_names.length;i++){\r\n\r\n accuracy.push(confusion_matrix[TeachableMobileNet.classes_names.length*i+ i]/TeachableMobileNet.numValidation)\r\n}\r\n\r\nconsole.log(\"Accuracy per class: \", accuracy);\r\n\r\nfor(let i=0; i<TeachableMobileNet.classes_names.length;i++){\r\n\r\n confusion_matrix_recipient.push([]);\r\n\r\n for(let j=0; j<TeachableMobileNet.classes_names.length;j++){\r\n confusion_matrix_recipient[i].push([]);\r\n\r\n confusion_matrix_recipient[i][j]= confusion_matrix[TeachableMobileNet.classes_names.length*i+ j]/TeachableMobileNet.numValidation\r\n confusion_matrix_recipient[i][j]=(confusion_matrix_recipient[i][j].toFixed(2))*100;\r\n }\r\n\r\n // accuracy.push(confusion_matrix[TeachableMobileNet.classes_names.length*i+ i]/TeachableMobileNet.numValidation)\r\n}\r\n\r\nconsole.log(\"Confusion matrix as a matrix\")\r\nconsole.log(confusion_matrix_recipient);\r\n\r\nreturn accuracy.map((elem: any)=>elem.toFixed(2)*100);\r\n}\r\n\r\n \r\n async loadImages(number_of_species: number, classes_names: string[], options: object){\r\n TeachableMobileNet.classes_names=classes_names;\r\n \r\n await this.add_species(number_of_species, options); \r\n\r\n}\r\n\r\nasync add_species(number_of_species: number, options: object){\r\n \r\n //Loading feature model, used to create features from images\r\n // await this.loadFeatureModel();\r\n\r\n for (let i = 0; i < TeachableMobileNet.classes_names.length; i++) {\r\n // this.add_images(this.classes_names[i], number_of_species, options);\r\n }\r\n}\r\n\r\n/**\r\n * \r\n * @param name - name of the class receiving an example\r\n * @param number_of_species - how many images to add\r\n * @param options - details on the location of the images\r\n */\r\nasync add_images(name: string, number_of_species: number, options: any){ \r\n\r\n const class_add: any= [];\r\n\r\n for (let i = 0; i < number_of_species; i++) { \r\n // class_add.push(`${options.base}/${name}/${options.file_name} ${i}.${options.file_extension}`);\r\n \r\n //Uploading images\r\n const cake = new Image(); \r\n // cake.src = `${options.base}/${name}/${options.file_name} ${i}.${options.file_extension}`;\r\n cake.height=224;\r\n cake.width=224;\r\n cake.src=\"./assets/dataset/Can%C3%A1rio-da-Terra/image%200.jpeg\"\r\n // console.log(\"Image location: \", cake.src )\r\n\r\n await new Promise<void>((resolve, reject) => {\r\n cake.onload = () => {\r\n\r\n //Finding the correspondent index of the class with name given\r\n const index= TeachableMobileNet.classes_names.findIndex((elem)=>elem===name)\r\n\r\n // this.addExample(index, cake);\r\n\r\n resolve();\r\n };\r\n \r\n cake.onerror = (error) => {\r\n // Handle error if the image fails to load\r\n reject(error);\r\n };\r\n });\r\n }\r\n\r\n // this.classes.push({name: name, images: class_add}) \r\n\r\n }\r\n\r\n\r\n\r\n \r\n/**\r\n * This method will transform images into tensors\r\n * @param number_of_classes - number of classes\r\n * @param classes_names - name of each class\r\n */\r\nasync createTensors(number_of_classes: number, classes_names: string[]) {\r\n\r\n let output: any = [];\r\n\r\n /** There is a function on TensorFlow.js that also does that */\r\n const signatures= new Util().identityMatrix(number_of_classes);\r\n\r\n for (let i = 0; i < number_of_classes; i++) {\r\n\r\n this.classes[i].signature=signatures[i];\r\n this.classes[i].name=classes_names[i];\r\n\r\n for (let j = 0; j < this.classes[i].images.length; j++) {\r\n\r\n\r\n }\r\n\r\n }\r\n}\r\n\r\n /**\r\n * Add a sample of data under the provided className\r\n * @param className the classification this example belongs to\r\n * @param sample the image / tensor that belongs in this classification\r\n */\r\n // public async addExample(className: number, sample: HTMLCanvasElement | tf.Tensor) {\r\npublic static async addExample(className: number, name: string, sample: HTMLImageElement | HTMLCanvasElement | tf.Tensor) {\r\n\r\n // console.log(\"Adding a new example...\") \r\n \r\n const cap = isTensor(sample) ? sample : capture(sample);\r\n \r\n // if(!this.truncatedModel)\r\n // await this.loadFeatureModel();\r\n\r\n //Getting the features\r\n const example = this.truncatedModel.predict(cap) as tf.Tensor;\r\n // console.log(\"Shape after feature extraction: \", example.shape) \r\n \r\n\r\n const activation = example.dataSync() as Float32Array;\r\n \r\n //Very important to clean the memory aftermath, it makes the difference\r\n cap.dispose();\r\n example.dispose();\r\n \r\n // //Accessing the instance variable, not the local ones\r\n // // save samples of each class separately \r\n \r\n if(!TeachableMobileNet.examples[className])\r\n //and an empty array, make sure there is not empty elements. \r\n //it will create issue when transforming to tensors\r\n TeachableMobileNet.examples[className]=[]\r\n\r\n\r\n if(!TeachableMobileNet.classes_names[className])\r\n //Saving the lable when it first appears\r\n TeachableMobileNet.classes_names[className]=name;\r\n\r\n TeachableMobileNet.examples[className].push(activation);\r\n \r\n // // increase our sample counter\r\n TeachableMobileNet.totalSamples++;\r\n }\r\n\r\n\r\n /**\r\n * process the current examples provided to calculate labels and format\r\n * into proper tf.data.Dataset\r\n */\r\n static prepare() {\r\n for (const classes in TeachableMobileNet.examples){\r\n if (classes.length === 0) {\r\n throw new Error('Add some examples before training');\r\n }\r\n }\r\n\r\n const datasets: any = this.convertToTfDataset();\r\n\r\n this.trainDataset = datasets.trainDataset;\r\n this.validationDataset = datasets.validationDataset;\r\n}\r\n\r\npublic prepareDataset() {\r\n for (let i = 0; i < TeachableMobileNet.numClasses; i++) {\r\n //Different from the original implementation of TM, mine is using example as static.\r\n //The goal is saving memory by using a single instance of the variable\r\n TeachableMobileNet.examples[i] = [];\r\n }\r\n}\r\n\r\n \r\n // Optional seed to make shuffling of data predictable\r\n static seed: seedrandom.prng;\r\n\r\n\r\n\r\n \r\n/**\r\n * Process the examples by first shuffling randomly per class, then adding\r\n * one-hot labels, then splitting into training/validation datsets, and finally\r\n * sorting one last time\r\n */\r\n \r\nstatic convertToTfDataset() {\r\n\r\n // first shuffle each class individually\r\n // TODO: we could basically replicate this by insterting randomly\r\n for (let i = 0; i < TeachableMobileNet.examples.length; i++) {\r\n TeachableMobileNet.examples[i] = fisherYates(TeachableMobileNet.examples[i], this.seed) as Float32Array[];\r\n }\r\n\r\n // then break into validation and test datasets\r\n let trainDataset: Sample[] = [];\r\n let validationDataset: Sample[] = [];\r\n\r\n // for each class, add samples to train and validation dataset\r\n for (let i = 0; i < TeachableMobileNet.examples.length; i++) {\r\n \r\n // console.log(\"Number of classes: \", TeachableMobileNet.classes_names.length);\r\n\r\n const y = flatOneHot(i, TeachableMobileNet.classes_names.length);\r\n\r\n const classLength = TeachableMobileNet.examples[i].length;\r\n\r\n // console.log(\"Number of elements per class: \", classLength);\r\n\r\n const numValidation = Math.ceil(VALIDATION_FRACTION * classLength);\r\n const numTrain = classLength - numValidation;\r\n\r\n this.numValidation=numValidation;\r\n \r\n /**It is visiting per class, thus, it is possible to fix y, the target label */\r\n \r\n const classTrain = this.examples[i].slice(0, numTrain).map((dataArray) => {\r\n return { data: dataArray, label: y };\r\n });\r\n\r\n const classValidation = this.examples[i].slice(numTrain).map((dataArray) => {\r\n return { data: dataArray, label: y };\r\n });\r\n\r\n trainDataset = trainDataset.concat(classTrain);\r\n validationDataset = validationDataset.concat(classValidation); \r\n\r\n\r\n }\r\n\r\n // console.log(\"Training element: \", trainDataset[trainDataset.length-1]) \r\n // console.log(\"Training length: \", trainDataset.length)\r\n // console.log(\"validation length: \", validationDataset.length);\r\n\r\n \r\n // finally shuffle both train and validation datasets\r\n trainDataset = fisherYates(trainDataset, this.seed) as Sample[];\r\n validationDataset = fisherYates(validationDataset, this.seed) as Sample[];\r\n\r\n const trainX = tf.data.array(trainDataset.map(sample => sample.data));\r\n const validationX = tf.data.array(validationDataset.map(sample => sample.data));\r\n const trainY = tf.data.array(trainDataset.map(sample => sample.label));\r\n const validationY = tf.data.array(validationDataset.map(sample => sample.label));\r\n\r\n // return tf.data dataset objects\r\n return {\r\n trainDataset: tf.data.zip({ xs: trainX, ys: trainY}),\r\n validationDataset: tf.data.zip({ xs: validationX, ys: validationY})\r\n };\r\n\r\n\r\n}\r\n\r\ndatasetForEvaluation(){\r\n\r\n}\r\n\r\n/**Metrics */\r\n\r\nstatic feature_aux: any;\r\nstatic target_aux: any;\r\n\r\nasync evaluate(){\r\n \r\n if(!TeachableMobileNet.feature_aux){\r\n const features: any=[];\r\n const targets: any=[];\r\n\r\n for (let i = 0; i < TeachableMobileNet.examples.length; i++) {\r\n\r\n const y = flatOneHot(i, TeachableMobileNet.classes_names.length);\r\n \r\n\r\n\r\n //For class i, push all the examples.\r\n TeachableMobileNet.examples[i].forEach((elemn)=>{\r\n\r\n //Pushing the target signature\r\n targets.push(y);\r\n \r\n //Pushing features\r\n features.push(elemn)\r\n })\r\n\r\n } \r\n\r\n TeachableMobileNet.feature_aux= tf.tensor(features);\r\n TeachableMobileNet.target_aux= tf.tensor(targets);\r\n\r\n } \r\n\r\n const aux: any = this.trainingModel.evaluate(TeachableMobileNet.feature_aux, TeachableMobileNet.target_aux);\r\n \r\n return aux[1].dataSync()[0];\r\n\r\n\r\n}\r\n\r\n\r\n// async evaluate(){\r\n\r\n// const features: any=[];\r\n// const targets: any=[];\r\n\r\n// for (let i = 0; i < TeachableMobileNet.examples.length; i++) {\r\n\r\n// const y = flatOneHot(i, TeachableMobileNet.classes_names.length);\r\n \r\n\r\n\r\n// //For class i, push all the examples.\r\n// TeachableMobileNet.examples[i].forEach((elemn)=>{\r\n\r\n// //Pushing the target signature\r\n// targets.push(y);\r\n \r\n// //Pushing features\r\n// features.push(elemn)\r\n// })\r\n\r\n// } \r\n\r\n// const aux_features= tf.tensor(features);\r\n// const aux_target= tf.tensor(targets);\r\n\r\n \r\n// // console.log(\"Tensor stack for evaluation: \", aux_features.shape)\r\n\r\n// const aux: any = this.trainingModel.evaluate(aux_features, aux_target);\r\n\r\n\r\n// return aux[1].dataSync()[0];\r\n\r\n\r\n// }\r\n\r\n\r\n/*** Final statistics */\r\n/* \r\n * Calculate each class accuracy using the validation dataset\r\n*/\r\npublic async calculateAccuracyPerClass(validationData: any) {\r\n\r\n const validationXs = TeachableMobileNet.validationDataset.mapAsync(async (dataset: TensorContainer) => {\r\n return (dataset as { xs: TensorContainer, ys: TensorContainer}).xs;\r\n});\r\n\r\nconst validationYs = TeachableMobileNet.validationDataset.mapAsync(async (dataset: TensorContainer) => {\r\n return (dataset as { xs: TensorContainer, ys: TensorContainer}).ys;\r\n});\r\n\r\n// console.log(\"validation dataset: \", validationXs);\r\n \r\n// console.log(\"For calculating batch size: \", validationYs);\r\n\r\n// we need to split our validation data into batches in case it is too large to fit in memory\r\nconst batchSize = Math.min(validationYs.size, 32);\r\n// const batchSize =1;\r\n\r\nconst iterations = Math.ceil(validationYs.size / batchSize);\r\n\r\n// console.log(\"Batch size: \", batchSize);\r\n\r\nconst batchesX = validationXs.batch(batchSize);\r\n\r\nconst batchesY = validationYs.batch(batchSize);\r\nconst itX = await batchesX.iterator();\r\nconst itY = await batchesY.iterator();\r\nconst allX = [];\r\nconst allY = [];\r\n\r\nfor (let i = 0; i < iterations; i++) {\r\n\r\n // 1. get the prediction values in batches\r\n const batchedXTensor = await itX.next(); \r\n\r\n // console.log(\"Batch size on accuracy per class: \", batchedXTensor.value.shape);\r\n\r\n const batchedXPredictionTensor = this.trainingModel.predict(batchedXTensor.value) as tf.Tensor;\r\n\r\n const argMaxX = batchedXPredictionTensor.argMax(1); // Returns the indices of the max values along an axis\r\n\r\n allX.push(argMaxX);\r\n\r\n // 2. get the ground truth label values in batches\r\n const batchedYTensor = await itY.next();\r\n const argMaxY = batchedYTensor.value.argMax(1); // Returns the indices of the max values along an axis\r\n\r\n allY.push(argMaxY);\r\n \r\n // 3. dispose of all our tensors\r\n batchedXTensor.value.dispose();\r\n batchedXPredictionTensor.dispose();\r\n batchedYTensor.value.dispose();\r\n}\r\n\r\n // concatenate all the results of the batches\r\n const reference = tf.concat(allY); // this is the ground truth\r\n const predictions = tf.concat(allX); // this is the prediction our model is guessing\r\n \r\n // console.log(\"this is the ground truth: \", reference.dataSync())\r\n // console.log(\"This is the prediction our model is guessing: \", predictions.dataSync())\r\n\r\n // only if we concatenated more than one tensor for preference and reference\r\n if (iterations !== 1) {\r\n for (let i = 0; i < allX.length; i++) {\r\n allX[i].dispose();\r\n allY[i].dispose();\r\n }\r\n }\r\n\r\n // console.log(\"Lengtth: \", await reference.dataSync().length) \r\n \r\n // const accuracyperclass=[];\r\n\r\n // const reference_aux= await reference.dataSync();\r\n // const prediction_aux= await predictions.dataSync();\r\n // console.log( predictions.dataSync());\r\n\r\n // reference_aux.forEach((element, index) => {\r\n // if()\r\n \r\n // }); \r\n\r\n\r\n return { reference, predictions }; \r\n\r\n}\r\n\r\n}//end of class\r\n\r\n\r\n\r\n\r\n\r\n/***Support methods (helpers) */\r\n\r\nconst isTensor = (c: any): c is tf.Tensor =>\r\n typeof c.dataId === 'object' && typeof c.shape === 'object';\r\n/**\r\n * Converts an integer into its one-hot representation and returns\r\n * the data as a JS Array.\r\n */\r\nfunction flatOneHot(label: number, numClasses: number) {\r\n\r\n const labelOneHot = new Array(numClasses).fill(0) as number[];\r\n labelOneHot[label] = 1;\r\n\r\n return labelOneHot;\r\n}\r\n\r\ninterface Sample {\r\n data: Float32Array;\r\n label: number[];\r\n}\r\n\r\n\r\n/**\r\n * Shuffle an array of Float32Array or Samples using Fisher-Yates algorithm\r\n * Takes an optional seed value to make shuffling predictable\r\n */\r\nfunction fisherYates(array: Float32Array[] | Sample[], seed?: seedrandom.prng) {\r\n const length = array.length;\r\n\r\n // need to clone array or we'd be editing original as we goo\r\n const shuffled = array.slice();\r\n\r\n for (let i = (length - 1); i > 0; i -= 1) {\r\n let randomIndex ;\r\n if (seed) {\r\n randomIndex = Math.floor(seed() * (i + 1));\r\n }\r\n else {\r\n randomIndex = Math.floor(Math.random() * (i + 1));\r\n }\r\n\r\n [shuffled[i], shuffled[randomIndex]] = [shuffled[randomIndex],shuffled[i]];\r\n }\r\n\r\n return shuffled;\r\n}\r\n","import { Component} from '@angular/core';\r\nimport { Group } from '../../interfaces/group';\r\nimport { CommonModule } from '@angular/common';\r\nimport { TeachableMobileNet } from '../../models/teachable-evolution';\r\n\r\n@Component({\r\n selector: 'neuroevolution-display-panel',\r\n standalone: true,\r\n imports: [CommonModule],\r\n templateUrl: './display-panel.component.html',\r\n styleUrl: './display-panel.component.css'\r\n})\r\nexport class DisplayPanelComponent {\r\n\r\n classes: Group[]=[];\r\n\r\n classes_names!: string[];\r\n\r\n number_of_samples_per_class!: number;\r\n\r\nloadImages(number_of_species: number, classes_names: string[], options: object){\r\n \r\n this.classes_names=classes_names;\r\n this.number_of_samples_per_class=number_of_species;\r\n\r\n this.add_species(number_of_species, options); \r\n\r\n }\r\n\r\n\r\nadd_species(number_of_species: number, options: object){\r\n\r\n for (let i = 0; i < this.classes_names.length; i++) {\r\n this.add_images(this.classes_names[i], number_of_species, options);\r\n \r\n }\r\n\r\n }\r\n\r\n add_images(name: string, number_of_species: number, options: any){ \r\n\r\n const class_add: any= [];\r\n\r\n for (let i = 0; i < number_of_species; i++) {\r\n if(!options.file_name && (options.subfolder)){ \r\n class_add.push(`${options.base}/${name}/${options.subfolder}/${name} ${i+1}.${options.file_extension}`);\r\n } \r\n \r\n else \r\n class_add.push(`${options.base}/${name}/${options.file_name} ${i+1}.${options.file_extension}`);\r\n }\r\n\r\n this.classes.push({name: name, images: class_add}) \r\n\r\n }\r\n\r\n async addexamples(){\r\n\r\n //This is needed to make sure it gives time for the images to upload\r\n //The images upload very fast, what makes this method execute before the images are on HTML\r\n //It can be removed if somehow this method is just called after the images are available.\r\n // console.log(\"Loading examples as tensors....\")\r\n await this.delay(0);\r\n\r\n for (let i = 0; i < this.classes_names.length; i++) {\r\n await this.add_example(this.classes_names[i], this.number_of_samples_per_class);\r\n }\r\n }\r\n\r\n async add_example(name: string, number_of_species: number){ \r\n\r\n const class_add: any= [];\r\n // console.log(name)\r\n for (let i = 0; i < number_of_species; i++) { \r\n \r\n //Collecting the images from HTML\r\n const aux = document.getElementById(`class-${name}-${i}`) as HTMLImageElement; \r\n\r\n //Adding the example\r\n const index= this.classes_names.findIndex((elem)=>elem===name)\r\n\r\n await TeachableMobileNet.addExample(index, name, aux); \r\n \r\n }\r\n\r\n // this.classes.push({name: name, images: class_add}) \r\n\r\n }\r\n\r\n delay(ms: number) {\r\n return new Promise<void>((resolve) => setTimeout(resolve, ms));\r\n}\r\n}\r\n","<div *ngFor=\"let class of classes; index as i\">\r\n <h1>{{class.name}}</h1>\r\n <img *ngFor=\"let item of class.images; index as i\" [src]=\"item\" width=\"224\" height=\"224\" [id]=\"'class-' + class.name + '-' + i\" crossorigin=\"anonymous\" >\r\n</div>\r\n","\r\nimport {TeachableMobileNet} from \"../models/teachable-evolution\"\r\nimport * as tf from '@tensorflow/tfjs';\r\n\r\n/**\r\n * Each individual of the population will be made of \r\n * an array, correspodent to the neural network weights and\r\n * an evaluation, its respective accuracy on the dataset given.\r\n * \r\n */\r\ninterface Individual {\r\n individual: TeachableMobileNet,\r\n accuracy?: number\r\n}\r\n\r\nexport abstract class NeuroEvolution {\r\n\r\n /** \r\n This is the population. I have decided to create a population of just weights.\r\n I had to change my mind. Working with weights is tricky. \r\n I have decided to sacrifice memory to make my life easiser.\r\n Tensors has their inner methods, it helps on the operators.\r\n I have to pay attention to memory manegement.\r\n Working with memory in tensors is tricky. \r\n */\r\n\r\n population: Individual[]=[];\r\n private _population_size: number=30;\r\n \r\n /**Setters and Getters */\r\n public set population_size(population_size: number){\r\n this._population_size=population_size;\r\n }\r\n public get population_size(){\r\n return this._population_size;\r\n }\r\n\r\n /**\r\n * Methods with implementation\r\n */\r\n\r\n async evaluate(){\r\n return this.population.forEach(async (elem)=>{\r\n elem.accuracy= await elem.individual.evaluate(); \r\n })\r\n }\r\n\r\n start_population(){\r\n\r\n for(let i=0; i<this.population_size;i++){ \r\n this.population.push({individual: new TeachableMobileNet()})\r\n }\r\n // console.log(\"Population length: \", this.population.length);\r\n // console.log(\"Memory after population iniialization: \", tf.memory().numBytes);\r\n }\r\n\r\n async apply_evolution(iteration: number){\r\n\r\n for(let i=0;i<iteration;i++){\r\n \r\n console.log(\"Interation: \",i)\r\n console.log(\"Memory: \", tf.memory().numBytes);\r\n console.log(\"Tensors in memory: \", tf.memory().numTensors);\r\n console.log(\"Population length: \", this.population.length);\r\n await this.evolution();\r\n }\r\n\r\n }\r\n \r\n /**\r\n * This method will apply the evolution\r\n */\r\n async evolution(){\r\n\r\n \r\n \r\n //Update the accuracy\r\n await this.evaluate();\r\n\r\n const offspring=[];\r\n\r\n /**First step is crossover, for creating offspring */\r\n for(let i=0; i<this.population.length;i++)\r\n {\r\n //The population will double in size\r\n offspring.push(this.crossover()); \r\n }\r\n\r\n //Mutation on the offspring\r\n // console.log(\"Weight before mutation: \", offspring[0].individual.getHead().layers[0].getWeights()[0].dataSync());\r\n\r\n this.mutation(offspring) \r\n\r\n //Joining parents and offspring into the same pool for selection\r\n this.population=[...this.population, ...offspring];\r\n\r\n //Update the accuracy\r\n await this.evaluate();\r\n\r\n\r\n //selection\r\n this.selection();\r\n console.log(\"Best accuracy: \", this.getTheBest().accuracy)\r\n console.log(\"Worst accuracy: \", this.getTheWorst().accuracy) \r\n\r\n }\r\n\r\n /**Abstract methods.\r\n * Should be implemented by each variation of evolutionary algorithms\r\n */\r\n\r\n abstract crossover(): Individual;\r\n abstract mutation(offspring: Individual[]): void;\r\n abstract selection(): void;\r\n\r\n\r\n /**Helpers */\r\n\r\n getTheBest(): Individual{\r\n let index_best: number=0;\r\n let best=0;\r\n\r\n this.population.forEach((elem: any, index: number)=>{\r\n\r\n if(elem.accuracy>best){\r\n best=elem.accuracy;\r\n index_best=index\r\n }\r\n \r\n })\r\n\r\n return this.population[index_best];\r\n }\r\n\r\n\r\n getTheWorst(): Individual{\r\n let index_worst: number=0;\r\n let worst=1;\r\n\r\n this.population.forEach((elem: any, index: number)=>{\r\n\r\n if(elem.accuracy<worst){\r\n worst=elem.accuracy;\r\n index_worst=index\r\n }\r\n \r\n })\r\n\r\n return this.population[index_worst];\r\n }\r\n\r\n /**\r\n * Selecting individuals by elitism\r\n */\r\n select_parents_by_rollet_wheels_v2(selection_number=2): Individual[]{\r\n\r\n // console.log(\"Selecting parents by rollet wheels...\");\r\n \r\n const share: any=[];\r\n \r\n let total: any=0;\r\n \r\n // console.log(\"Population length...\", this.population.length);\r\n \r\n //This will create an overall accuracy\r\n this.population.forEach((elem)=>total+=elem.accuracy);\r\n \r\n let pointer=0;\r\n \r\n this.population.forEach((elem:any, index)=>{\r\n \r\n // console.log(\"Accuracy...\", elem.accuracy);\r\n \r\n share.push(\r\n {\r\n index: index,\r\n share: elem.accuracy/total,\r\n min: pointer,\r\n max: pointer + (elem.accuracy/total)\r\n })\r\n \r\n pointer+=elem.accuracy/total;\r\n });\r\n \r\n // console.log(\"Shares: \", share);\r\n \r\n const aux_selection: any =[];\r\n \r\n //Selecting two individuals using roulette wheels\r\n let counter=0;\r\n\r\n const indexes_aux: number[]=[];\r\n\r\n while(counter<selection_number){\r\n \r\n //Random pointer, used to randomly select an individual\r\n const aux_index= Math.random();\r\n \r\n share.forEach((elem: any)=>{\r\n \r\n if((elem.min<aux_index)&&(elem.max>aux_index)){\r\n \r\n const aux: Individual = {individual: new TeachableMobileNet(), accuracy: this.population[elem.index].accuracy }\r\n \r\n // console.log(\"Individual just created (weigth): \", aux.individual.getHead().layers[0].getWeights()[0].dataSync());\r\n \r\n // console.log(\"Individual original: \", this.population[elem.index].individual.getHead().layers[0].getWeights()[0].dataSync());\r\n // // Original Recipient\r\n // this.copyModel(this.population[elem.index].individual.getHead(),aux.individual.getHead())\r\n\r\n // this.population[elem.index].individual.getHead().dispose();\r\n \r\n // console.log(\"Individual just created (weigtht, copied): \", aux.individual.getHead().layers[0].getWeights()[0].dataSync());\r\n \r\n\r\n counter++;\r\n aux_selection.push(this.population[elem.index]);\r\n\r\n // indexes_aux.push(elem.index)\r\n }\r\n })\r\n }\r\n\r\n // this.population.forEach((elem, index)=>{\r\n // if(!indexes_aux.includes(index)){\r\n // console.log(\"Disposed...\")\r\n // elem.individual.getHead().dispose();\r\n // }\r\n \r\n // })\r\n\r\n // this.population=[];\r\n\r\n return aux_selection;\r\n }\r\n \r\n /**\r\n * Selecting individuals by elitism\r\n */\r\n select_parents_by_rollet_wheels(selection_number=2): Individual[]{\r\n\r\n // console.log\r\n // (\"Selecting parents by rollet wheels...\");\r\n\r\n const share: any=[];\r\n\r\n let total: any=0;\r\n \r\n // console.log(\"Population length...\", this.population.length);\r\n\r\n //This will create an overall accuracy\r\n this.population.forEach((elem)=>total+=elem.accuracy);\r\n\r\n let pointer=0;\r\n\r\n this.population.forEach((elem:any, index)=>{\r\n\r\n // console.log(\"Accuracy...\", elem.accuracy);\r\n\r\n share.push(\r\n {\r\n index: index,\r\n share: elem.accuracy/total,\r\n min: pointer,\r\n max: pointer + (elem.accuracy/total)\r\n })\r\n\r\n pointer+=elem.accuracy/total;\r\n });\r\n\r\n // console.log(\"Shares: \", share);\r\n\r\n const aux_selection: any =[];\r\n\r\n //Selecting two individuals using roulette wheels\r\n let counter=0;\r\n while(counter<selection_number){\r\n \r\n //Random pointer, used to randomly select an individual\r\n const aux_index= Math.random();\r\n\r\n share.forEach((elem: any)=>{\r\n\r\n if((elem.min<aux_index)&&(elem.max>aux_index)){\r\n counter++;\r\n aux_selection.push(this.population[elem.index]);\r\n }\r\n })\r\n }\r\n return aux_selection;\r\n }\r\n\r\n/**\r\n * This function will make a copy of a model on the weight level\r\n * This is an attempt to avoid influencing the new model when the old one\r\n * is eliminated. \r\n * \r\n * @param originalModel - the model to be copied \r\n * @param recipient - the new model\r\n */\r\nasync copyModel (originalModel: tf.LayersModel, recipient: tf.LayersModel) {\r\n\r\n originalModel.layers.forEach((layer: any, index: any)=>{\r\n recipient.layers[index].setWeights(layer.getWeights())\r\n })\r\n} \r\n\r\n}\r\n","import { NeuroEvolution } from \"./neuro-evolution\";\r\nimport {TeachableMobileNet} from \"../models/teachable-evolution\"\r\nimport * as tf from '@tensorflow/tfjs';\r\n\r\n/**\r\n * Each individual of the population will be made of \r\n * an array, correspodent to the neural network weights and\r\n * an evaluation, its respective accuracy on the dataset given.\r\n * \r\n */\r\ninterface Individual {\r\n individual: TeachableMobileNet,\r\n accuracy?: number\r\n}\r\n\r\n\r\nexport class GeneticAlgorithm extends NeuroEvolution { \r\n \r\n \r\n\r\n /**\r\n * Implementatin abstract methods\r\n */\r\n\r\n override crossover(): Individual {\r\n // console.log(\"Applying crossover on Genetic Algorithms...\")\r\n\r\n const selected = this.select_parents_by_rollet_wheels();\r\n\r\n const individual_1 = selected[0];\r\n const individual_2 = selected[1];\r\n\r\n // console.log(\"Individual 1: \")\r\n // individual_1.individual.getHead().summary();\r\n\r\n let individual_3: Individual= {individual: new TeachableMobileNet};\r\n\r\n const alfa = Math.random();\r\n\r\n individual_3.individual.getHead().layers.forEach((layer, index)=>{\r\n individual_3.individual.getHead().layers[index].setWeights(\r\n individual_1.individual.getHead().layers[index].getWeights()\r\n .map((elem: any, index_2: any)=> elem.mul(alfa)\r\n .add(individual_2.individual.getHead().layers[index]\r\n .getWeights()[index_2]\r\n .mul(1 - alfa)\r\n )))\r\n })\r\n\r\n // this.population.push(individual_3);\r\n // console.log(\"Population: \", this.population.length); \r\n \r\n return individual_3; \r\n \r\n }//end of crossover\r\n\r\n override mutation(offspring: Individual[]): void {\r\n\r\n const multation_rate=1;\r\n\r\n offspring.forEach((elem)=>{\r\n elem.individual.getHead().setWeights(\r\n elem.individual.getHead().getWeights().map((elem_2)=> { \r\n return elem_2.add(elem_2.mul(multation_rate*Math.random())) \r\n })\r\n );\r\n })\r\n }\r\n\r\n override selection(): void {\r\n\r\n const selected_individuals= this.select_parents_by_rollet_wheels(this.population_size);\r\n\r\n //The best will enter on the population by elitism\r\n const best= this.getTheBest();\r\n\r\n this.population=[];\r\n\r\n this.population=selected_individuals;\r\n\r\n console.log(\"Best accuracy (elitism): \", best.accuracy);\r\n \r\n\r\n }\r\n}\r\n","/*\r\n * Public API Surface of tfjs-evolution\r\n */\r\n\r\nexport * from './lib/tfjs-evolution.service';\r\nexport * from './lib/tfjs-evolution.component';\r\n\r\nexport * from './lib/components/display-panel/display-panel.component';\r\n\r\nexport * from './lib/models/teachable-evolution';\r\n\r\nexport * from './lib/Classes/genetic-algorithm';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tfjs-evolution.mjs","sources":["../../../projects/tfjs-evolution/src/lib/tfjs-evolution.service.ts","../../../projects/tfjs-evolution/src/lib/tfjs-evolution.component.ts","../../../projects/tfjs-evolution/src/lib/models/custom-mobilenet.ts","../../../projects/tfjs-evolution/src/lib/utils/tf.ts","../../../projects/tfjs-evolution/src/lib/utils/util.ts","../../../projects/tfjs-evolution/src/lib/models/teachable-evolution.ts","../../../projects/tfjs-evolution/src/lib/components/display-panel/display-panel.component.ts","../../../projects/tfjs-evolution/src/lib/components/display-panel/display-panel.component.html","../../../projects/tfjs-evolution/src/lib/Classes/neuro-evolution.ts","../../../projects/tfjs-evolution/src/lib/Classes/genetic-algorithm.ts","../../../projects/tfjs-evolution/src/lib/components/metrics/metrics.component.ts","../../../projects/tfjs-evolution/src/lib/components/metrics/metrics.component.html","../../../projects/tfjs-evolution/src/public-api.ts","../../../projects/tfjs-evolution/src/tfjs-evolution.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class TfjsEvolutionService {\r\n\r\n constructor() { }\r\n}\r\n","import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'neuroevolution-tfjs-evolution',\r\n standalone: true,\r\n imports: [],\r\n template: `\r\n <p>\r\n tfjs-evolution works!\r\n </p>\r\n `,\r\n styles: ``\r\n})\r\nexport class TfjsEvolutionComponent {\r\n\r\n}\r\n","\r\nimport * as tf from '@tensorflow/tfjs';\r\n\r\nimport { SymbolicTensor } from '@tensorflow/tfjs';\r\n\r\n\r\nexport const IMAGE_SIZE = 224;\r\n\r\n\r\n/**\r\n * the metadata to describe the model's creation,\r\n * includes the labels associated with the classes\r\n * and versioning information from training.\r\n */\r\nexport interface Metadata {\r\n tfjsVersion: string;\r\n tmVersion?: string;\r\n packageVersion: string;\r\n packageName: string;\r\n modelName?: string;\r\n timeStamp?: string;\r\n labels: string[];\r\n userMetadata?: {};\r\n grayscale?: boolean;\r\n imageSize?: number;\r\n}\r\n\r\nexport interface ModelOptions {\r\n version?: number;\r\n checkpointUrl?: string;\r\n alpha?: number;\r\n trainingLayer?: string;\r\n}\r\n\r\nconst DEFAULT_MOBILENET_VERSION = 2;\r\nconst DEFAULT_TRAINING_LAYER_V1 = 'conv_pw_13_relu';\r\nconst DEFAULT_TRAINING_LAYER_V2 = \"out_relu\"; \r\nconst DEFAULT_ALPHA_V1_v2 = 0.35;\r\nconst DEFAULT_ALPHA_V1 = 0.25;//256\r\nconst DEFAULT_ALPHA_V2 = 0.5; //512\r\nconst DEFAULT_ALPHA_V3 = 0.75;//768 features\r\nconst DEFAULT_ALPHA_V4 = 1;//1024 features\r\nconst DEFAULT_ALPHA = 1;//1024 features\r\n\r\n// v2: 0.35, 0.50, 0.75 or 1.00.\r\n\r\nconst isAlphaValid = (version: number, alpha: number) => {\r\n if (version === 1) {\r\n if (alpha !== 0.25 && alpha !== 0.5 && alpha !== 0.75 && alpha !== 1) {\r\n console.warn(\"Invalid alpha. Options are: 0.25, 0.50, 0.75 or 1.00.\");\r\n console.log(\"Loading model with alpha: \", DEFAULT_ALPHA_V1.toFixed(2)); \r\n return DEFAULT_ALPHA_V1;\r\n }\r\n }\r\n else {\r\n if (alpha !== 0.35 && alpha !== 0.5 && alpha !== 0.75 && alpha !== 1) {\r\n console.warn(\"Invalid alpha. Options are: 0.35, 0.50, 0.75 or 1.00.\");\r\n console.log(\"Loading model with alpha: \", DEFAULT_ALPHA_V2.toFixed(2)); \r\n return DEFAULT_ALPHA_V2;\r\n }\r\n }\r\n\r\n return alpha;\r\n};\r\n\r\n\r\nconst parseModelOptions = (options?: ModelOptions) => {\r\n options = options || {}\r\n\r\n if (options.checkpointUrl && options.trainingLayer) {\r\n if (options.alpha || options.version){\r\n console.warn(\"Checkpoint URL passed to modelOptions, alpha options are ignored\");\r\n } \r\n return [options.checkpointUrl, options.trainingLayer];\r\n } else {\r\n options.version = options.version || DEFAULT_MOBILENET_VERSION;\r\n \r\n if(options.version === 1){\r\n options.alpha = options.alpha || DEFAULT_ALPHA_V4; \r\n options.alpha = isAlphaValid(options.version, options.alpha);\r\n\r\n console.log(`Loading mobilenet ${options.version} and alpha ${options.alpha}`);\r\n // exception is alpha o f 1 can only be 1.0\r\n let alphaString = options.alpha.toFixed(2);\r\n if (alphaString === \"1.00\") { alphaString = \"1.0\"; }\r\n\r\n console.log(\"Using the model: \", )\r\n\r\n return [\r\n // tslint:disable-next-line:max-line-length\r\n //They are loading MobileNet_v1 \r\n `https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_${alphaString}_${IMAGE_SIZE}/model.json`,\r\n DEFAULT_TRAINING_LAYER_V1\r\n ];\r\n }\r\n else if (options.version === 2){\r\n options.alpha = options.alpha || DEFAULT_ALPHA_V4; \r\n options.alpha = isAlphaValid(options.version, options.alpha);\r\n\r\n console.log(`Loading mobilenet ${options.version} and alpha ${options.alpha}`);\r\n console.log(`Loading mobilenet ${options.version} and alpha ${options.alpha}`);\r\n\r\n return [\r\n // tslint:disable-next-line:max-line-length \r\n `https://storage.googleapis.com/teachable-machine-models/mobilenet_v2_weights_tf_dim_ordering_tf_kernels_${options.alpha.toFixed(2)}_${IMAGE_SIZE}_no_top/model.json`,\r\n DEFAULT_TRAINING_LAYER_V2\r\n ];\r\n } else {\r\n throw new Error(`MobileNet V${options.version} doesn't exist`);\r\n } \r\n }\r\n};\r\n\r\n\r\n/**\r\n * load the base mobilenet model\r\n * @param modelOptions options determining what model to load\r\n */\r\nexport async function loadTruncatedMobileNet(modelOptions?: ModelOptions) {\r\n const [checkpointUrl, trainingLayer] = parseModelOptions(modelOptions);\r\n \r\n \r\n const mobilenet = await tf.loadLayersModel(checkpointUrl);\r\n\r\n if (modelOptions && modelOptions.version === 1){\r\n const layer = mobilenet.getLayer(trainingLayer);\r\n \r\n const truncatedModel = tf.model({ inputs: mobilenet.inputs, outputs: layer.output });\r\n console.log(\"Feature model loaded, memory: \", tf.memory().numBytes);\r\n\r\n \r\n const model = tf.sequential();\r\n model.add(truncatedModel);\r\n model.add(tf.layers.flatten()); \r\n \r\n \r\n return model;\r\n }\r\n else {\r\n const layer = mobilenet.getLayer(trainingLayer);\r\n const truncatedModel = tf.model({ inputs: mobilenet.inputs, outputs: layer.output });\r\n console.log(\"Feature model loaded, memory: \", tf.memory().numBytes);\r\n const model = tf.sequential();\r\n model.add(truncatedModel);\r\n model.add(tf.layers.globalAveragePooling2d({})); // go from shape [7, 7, 1280] to [1280]\r\n return model;\r\n }\r\n}\r\n\r\n\r\nexport class CustomMobileNet {\r\n /**\r\n * the truncated mobilenet model we will train on top of\r\n */\r\n protected truncatedModel!: tf.LayersModel;\r\n static truncatedModel: tf.Sequential;\r\n\r\nstatic getinputShape(){\r\n /**truncatedModel is the base model, the model used to apply transfer learning */\r\n const inputShape: any = this.truncatedModel.outputs[0].shape.slice(1); // [ 7 x 7 x 1280] (not sure about those dimensions)\r\n// console.log(\"Input Shape(complete): \", this.truncatedModel.outputs[0].shape);\r\n// console.log(\"Input Shape: \", inputShape);\r\n\r\n const inputSize = tf.util.sizeFromShape(inputShape);\r\n\r\n// console.log(\"Input Size: \", inputSize);\r\n\r\n return inputSize;\r\n}\r\n\r\n static get EXPECTED_IMAGE_SIZE() {\r\n return IMAGE_SIZE;\r\n }\r\n\r\n protected _metadata!: Metadata;\r\n\r\n public getMetadata() {\r\n return this._metadata;\r\n }\r\n\r\n constructor() {\r\n // this._metadata = fillMetadata(metadata);\r\n //Loading the truncated model\r\n // loadTruncatedMobileNet();\r\n // this.loadFeatureModel();\r\n\r\n }\r\n\r\n static async loadFeatureModel(){\r\n\r\n this.truncatedModel = await loadTruncatedMobileNet();\r\n\r\n }\r\n\r\n /**\r\n * get the total number of classes existing within model\r\n */\r\n // getTotalClasses() {\r\n // const output = this.model.output as SymbolicTensor;\r\n // const totalClasses = output.shape[1];\r\n // return totalClasses;\r\n // }\r\n\r\n /**\r\n * get the model labels\r\n */\r\n getClassLabels() {\r\n return this._metadata.labels;\r\n }\r\n\r\n /**\r\n * Given an image element, makes a prediction through mobilenet returning the\r\n * probabilities of the top K classes.\r\n * @param image the image to classify\r\n * @param maxPredictions the maximum number of classification predictions\r\n */\r\n // async predictTopK(image: ClassifierInputSource, maxPredictions = 10, flipped = false) {\r\n // const croppedImage = cropTo(image, this._metadata.imageSize, flipped);\r\n\r\n // const logits = tf.tidy(() => {\r\n // const captured = capture(croppedImage, this._metadata.grayscale);\r\n // return this.model.predict(captured);\r\n // });\r\n\r\n // // Convert logits to probabilities and class names.\r\n // const classes = await getTopKClasses(this._metadata.labels, logits as tf.Tensor<tf.Rank>, maxPredictions);\r\n // dispose(logits);\r\n\r\n // return classes;\r\n // }\r\n\r\n /**\r\n * Given an image element, makes a prediction through mobilenet returning the\r\n * probabilities for ALL classes.\r\n * @param image the image to classify\r\n * @param flipped whether to flip the image on X\r\n */\r\n // async predict(image: ClassifierInputSource, flipped = false) {\r\n // const croppedImage = cropTo(image, this._metadata.imageSize, flipped);\r\n\r\n // const logits = tf.tidy(() => {\r\n // const captured = capture(croppedImage, this._metadata.grayscale);\r\n // return this.model.predict(captured);\r\n // });\r\n\r\n // const values = await (logits as tf.Tensor<tf.Rank>).data();\r\n\r\n // const classes = [];\r\n // for (let i = 0; i < values.length; i++) {\r\n // classes.push({\r\n // className: this._metadata.labels[i],\r\n // probability: values[i]\r\n // });\r\n // }\r\n\r\n // dispose(logits);\r\n\r\n // return classes;\r\n // }\r\n\r\n public dispose() {\r\n this.truncatedModel.dispose();\r\n }\r\n}// end of CustomMobileNet\r\n","import * as tf from '@tensorflow/tfjs';\r\n\r\n/**\r\n * Receives an image and normalizes it between -1 and 1.\r\n * Returns a batched image (1 - element batch) of shape [1, w, h, c]\r\n * @param rasterElement the element with pixels to convert to a Tensor\r\n * @param grayscale optinal flag that changes the crop to [1, w, h, 1]\r\n */\r\nexport function capture(rasterElement: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement, grayscale?: boolean) {\r\n return tf.tidy(() => {\r\n // console.log(\"Not a tensor....\")\r\n const pixels = tf.browser.fromPixels(rasterElement);\r\n\r\n // crop the image so we're using the center square\r\n const cropped = cropTensor(pixels);\r\n\r\n // Expand the outer most dimension so we have a batch size of 1\r\n const batchedImage = cropped.expandDims(0);\r\n\r\n // Normalize the image between -1 and a1. The image comes in between 0-255\r\n // so we divide by 127 and subtract 1.\r\n return batchedImage.toFloat().div(tf.scalar(127)).sub(tf.scalar(1));\r\n });\r\n}\r\n\r\n\r\n\r\nexport function cropTensor( img: tf.Tensor3D ) : tf.Tensor3D {\r\n \r\n const size = Math.min(img.shape[0], img.shape[1]);\r\n const centerHeight = img.shape[0] / 2;\r\n const beginHeight = centerHeight - (size / 2);\r\n const centerWidth = img.shape[1] / 2;\r\n const beginWidth = centerWidth - (size / 2);\r\n \r\n\r\n return img.slice([beginHeight, beginWidth, 0], [size, size, 3]);\r\n}","\r\nimport {Class} from \"./class\"\r\nimport * as tf from '@tensorflow/tfjs';\r\n\r\n\r\nexport class Util {\r\n\r\n/**\r\n * Receives an image and normalizes it between -1 and 1.\r\n * Returns a batched image (1 - element batch) of shape [1, w, h, c]\r\n * @param rasterElement the element with pixels to convert to a Tensor\r\n * @param grayscale optinal flag that changes the crop to [1, w, h, 1]\r\n */\r\ncapture(rasterElement: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement, grayscale?: boolean) {\r\n return tf.tidy(() => {\r\n const pixels = tf.browser.fromPixels(rasterElement);\r\n\r\n // // crop the image so we're using the center square\r\n const cropped = this.cropTensor(pixels, grayscale);\r\n\r\n // // Expand the outer most dimension so we have a batch size of 1\r\n const batchedImage = cropped.expandDims(0);\r\n\r\n // // Normalize the image between -1 and a1. The image comes in between 0-255\r\n // // so we divide by 127 and subtract 1.\r\n return batchedImage.toFloat().div(tf.scalar(127)).sub(tf.scalar(1)); \r\n });\r\n} \r\n\r\n\r\ncropTensor( img: tf.Tensor3D, grayscaleModel?: boolean, grayscaleInput?: boolean ) : tf.Tensor3D {\r\n const size = Math.min(img.shape[0], img.shape[1]);\r\n const centerHeight = img.shape[0] / 2;\r\n const beginHeight = centerHeight - (size / 2);\r\n const centerWidth = img.shape[1] / 2;\r\n const beginWidth = centerWidth - (size / 2);\r\n \r\n if (grayscaleModel && !grayscaleInput) {\r\n //cropped rgb data\r\n let grayscale_cropped = img.slice([beginHeight, beginWidth, 0], [size, size, 3]);\r\n \r\n grayscale_cropped = grayscale_cropped.reshape([size * size, 1, 3])\r\n const rgb_weights = [0.2989, 0.5870, 0.1140]\r\n grayscale_cropped = tf.mul(grayscale_cropped, rgb_weights)\r\n grayscale_cropped = grayscale_cropped.reshape([size, size, 3]);\r\n \r\n grayscale_cropped = tf.sum(grayscale_cropped, -1)\r\n grayscale_cropped = tf.expandDims(grayscale_cropped, -1)\r\n\r\n return grayscale_cropped;\r\n }\r\n return img.slice([beginHeight, beginWidth, 0], [size, size, 3]);\r\n}\r\n\r\n\r\n\r\n\r\n/**\r\n * This function will make a copy of a model on the weight level\r\n * This is an attempt to avoid influencing the new mode when the old one\r\n * is eliminated. \r\n * \r\n * @param originalModel - the model to be copied \r\n * @param recipient - the new model\r\n */\r\nasync copyModel_v3 (originalModel: tf.Sequential, recipient: tf.Sequential) {\r\n\r\n originalModel.layers.forEach((layer, index)=>{\r\n recipient.layers[index].setWeights(layer.getWeights())\r\n })\r\n\r\n // originalModel.dispose();\r\n}\r\n \r\n/**\r\n * This function will make a copy of a TFJS model, as so it would be possible \r\n * to erase the original.\r\n * @param model - model to be copied\r\n * @returns - copy of the model\r\n */ \r\nasync copyModel_v2 (originalModel: tf.Sequential) {\r\n // Serialize the original model\r\n const modelTopology = originalModel.toJSON();\r\n\r\n // Load the serialized model into a new model\r\n const copiedModel = await tf.loadLayersModel(\r\n tf.io.fromMemory(modelTopology, undefined, undefined)\r\n );\r\n \r\n // Compile the copied model with the same settings as the original\r\n copiedModel.compile({\r\n loss: originalModel.loss,\r\n optimizer: originalModel.optimizer\r\n });\r\n \r\n return copiedModel;\r\n}\r\n\r\n/**\r\n * This function will make a copy of a TFJS model, as so it would be possible \r\n * to erase the original.\r\n * @param model - model to be copied\r\n * @returns - copy of the model\r\n */ \r\ncopyModel (model: tf.Sequential) {\r\n \r\n const copy = tf.sequential();`\r\n `\r\n model.layers.forEach(layer => {\r\n const aux =layer;\r\n // layer.dispose();\r\n copy.add(aux);\r\n });\r\n copy.compile({\r\n loss: model.loss,\r\n optimizer: model.optimizer\r\n });\r\n return copy;\r\n }\r\n\r\n\r\n removeElementByIndex(arr: any, index: number): number[] {\r\n // Check if the index is within bounds\r\n if (index >= 0 && index < arr.length) {\r\n // Remove the element at the specified index\r\n arr.splice(index, 1); \r\n }\r\n return arr;\r\n }\r\n\r\n removeElement(arr: any, element: any): number[] {\r\n // Remove all occurrences of the specified element from the array\r\n return arr.filter((item: any) => item !== element);\r\n }\r\n\r\nclean_array_of_tensors(tensors: tf.Sequential[]) {\r\n\r\n tensors.forEach((elem, index)=>{ \r\n // if(!index_selection.includes(index)) \r\n elem.dispose() \r\n });\r\n\r\n}\r\n\r\n getClassNameBySignature(classes: Class[], signature: number[]) { \r\n \r\n const class_name = classes.find(p => {\r\n let match = true;\r\n p.signature?.forEach ((elem,index)=>{ \r\n if(elem!==signature[index])\r\n match=false; \r\n })\r\n\r\n return match;\r\n });\r\n\r\n return class_name ? class_name.name : \"not found\";\r\n}\r\n\r\nidentityMatrix(n: number): number[][] {\r\n return Array.from({ length: n }, (_, i) => Array.from({ length: n }, (_, j) => (i === j ? 1 : 0)));\r\n} \r\n\r\n\r\nindexOfMax(arr: number[]): number {\r\n if (arr.length === 0) {\r\n return -1; // Return -1 for an empty array\r\n }\r\n \r\n let max = arr[0];\r\n let maxIndex = 0;\r\n \r\n for (let i = 1; i < arr.length; i++) {\r\n if (arr[i] > max) {\r\n maxIndex = i;\r\n max = arr[i];\r\n }\r\n }\r\n \r\n return maxIndex;\r\n }\r\n\r\n\r\nsuffle(array1:any, array2: any){\r\n // Shuffle the order of elements\r\n for (let i = array1.length - 1; i > 0; i--) {\r\n const j = Math.floor(Math.random() * (i + 1));\r\n\r\n // Swap elements in both arrays\r\n [array1[i], array1[j]] = [array1[j], array1[i]];\r\n [array2[i], array2[j]] = [array2[j], array2[i]];\r\n }\r\n \r\n \r\n }\r\n\r\n sortByValuePreservingIndex<T>(\r\n arr1: number[],\r\n arr2: any[]\r\n ): T[] {\r\n\r\n // console.log(\"Vector for organizing: \", arr1)\r\n // arr2[0].summary()\r\n\r\n // Create an array of objects with value, index from arr1, and original index\r\n const pairingArray = arr1.map((value, index) => ({\r\n value,\r\n index,\r\n originalIndex: index,\r\n elementFromArr2: arr2[index], // Preserve the corresponding element from arr2\r\n }));\r\n \r\n // Sort the pairing array by value (largest to smallest)\r\n pairingArray.sort((a, b) => b.value - a.value);\r\n\r\n \r\n \r\n // Extract the sorted elements from arr2 based on the original index\r\n const sortedElementsFromArr2 = pairingArray.map(pair => pair.elementFromArr2);\r\n \r\n return sortedElementsFromArr2;\r\n } \r\n \r\n}\r\n\r\n","import { CustomMobileNet, loadTruncatedMobileNet } from \"./custom-mobilenet\";\r\n\r\nimport * as tf from '@tensorflow/tfjs';\r\n\r\nimport { capture } from '../utils/tf';\r\nimport { Class } from '../utils/class';\r\nimport { Util } from \"../utils/util\";\r\n\r\nimport * as seedrandom from 'seedrandom';\r\n\r\nimport * as tfvis from '@tensorflow/tfjs-vis';\r\n\r\nimport { TensorContainer } from '@tensorflow/tfjs-core/dist/tensor_types';\r\n\r\nconst VALIDATION_FRACTION = 0.15;\r\n\r\n\r\n\r\n/**\r\n * the metadata to describe the model's creation,\r\n * includes the labels associated with the classes\r\n * and versioning information from training.\r\n */\r\nexport interface Metadata {\r\n tfjsVersion: string;\r\n tmVersion?: string;\r\n packageVersion: string;\r\n packageName: string;\r\n modelName?: string;\r\n timeStamp?: string;\r\n labels: string[];\r\n userMetadata?: {};\r\n grayscale?: boolean;\r\n imageSize?: number;\r\n}\r\n\r\n/**\r\n * Receives a Metadata object and fills in the optional fields such as timeStamp\r\n * @param data a Metadata object\r\n */\r\nconst fillMetadata = (data: Partial<Metadata>) => {\r\n // util.assert(typeof data.tfjsVersion === 'string', () => `metadata.tfjsVersion is invalid`);\r\n // data.packageVersion = data.packageVersion || version;\r\n data.packageName = data.packageName || '@teachablemachine/image';\r\n data.timeStamp = data.timeStamp || new Date().toISOString();\r\n data.userMetadata = data.userMetadata || {};\r\n data.modelName = data.modelName || 'untitled';\r\n data.labels = data.labels || [];\r\n // data.imageSize = data.imageSize || IMAGE_SIZE;\r\n return data as Metadata;\r\n};\r\n\r\nexport class TeachableMobileNet extends CustomMobileNet {\r\n\r\n // Array of all the examples collected.\r\n /**\r\n It is static since all the instance will share the same features, for saving memory and time.\r\n The idea is avoiding restoring the features individually and having the recalculate them for every new\r\n individuals.\r\n */\r\n public static examples: Float32Array[][] = [];\r\n\r\n // Number of total samples\r\n private static totalSamples = 0;\r\n\r\n classes: Class[]=[];\r\n\r\n static classes_names: string[]=[];\r\n\r\n static numClasses: number;\r\n\r\n /**\r\n * the training model for transfer learning\r\n */\r\n protected trainingModel!: tf.LayersModel;\r\n trainDataset: any;\r\n validationDataset: any;\r\n static trainDataset: any;\r\n static validationDataset: any;\r\n static numValidation: number;\r\n\r\n constructor(){\r\n super();\r\n this.createHead();\r\n }\r\n\r\n /**\r\n * This method will return the head, the trainable part, the part under evolution.\r\n */\r\n getHead(){\r\n return this.trainingModel;\r\n }\r\n\r\n /**\r\n * Create the head for transfer learning.\r\n * This is the trainable section of the transfer learning.\r\n */\r\n createHead(){\r\n\r\n const inputSize= TeachableMobileNet.getinputShape();\r\n\r\n this.trainingModel = tf.sequential({\r\n layers: [\r\n tf.layers.dense({\r\n inputShape: [inputSize],\r\n units:100,\r\n activation: 'relu', \r\n useBias: true\r\n }),\r\n tf.layers.dense({ \r\n useBias: false,\r\n activation: 'softmax',\r\n units: TeachableMobileNet.classes_names.length\r\n })\r\n ]\r\n });\r\n\r\n const optimizer = tf.train.adam();\r\n // const optimizer = tf.train.rmsprop(params.learningRate);\r\n\r\n this.trainingModel.compile({\r\n optimizer,\r\n // loss: 'binaryCrossentropy',\r\n loss: 'categoricalCrossentropy',\r\n metrics: ['accuracy']\r\n });\r\n }\r\n \r\n async train(){\r\n\r\n const trainingSurface = { name: 'Loss and MSE', tab: 'Training' };\r\n\r\n const dataset= TeachableMobileNet.convertToTfDataset();\r\n\r\n //Salving a copy of the validation dataset, for later\r\n TeachableMobileNet.validationDataset= dataset.validationDataset;\r\n\r\n // console.log(\"Dataset for training: \", dataset.trainDataset);\r\n\r\n const trainData = dataset.trainDataset.batch(30);\r\n const validationData = dataset.validationDataset.batch(10);\r\n\r\n // this.createHead();\r\n\r\n const callbacks= [\r\n // Show on a tfjs-vis visor the loss and accuracy values at the end of each epoch.\r\n tfvis.show.fitCallbacks(trainingSurface, ['loss', 'acc', \"val_loss\", \"val_acc\"],\r\n {\r\n callbacks: ['onEpochEnd'],\r\n }\r\n ),\r\n {},]\r\n\r\n const history: any = await this.trainingModel.fitDataset(trainData, {\r\n epochs: 100,\r\n validationData,\r\n callbacks\r\n}).then((info:any)=>{\r\n console.log('Precisão final', info.history.val_acc[info.history.acc.length-1]);\r\n});\r\n\r\n\r\n// await this.accuracy_per_class();\r\n\r\n\r\n// console.log(\"History: \", history.history.acc);\r\n // await this.trainingModel.fit(this.featureX, this.target, {})\r\n }\r\n\r\nasync accuracy_per_class(confusion_matrix_recipient: any){\r\n \r\n /**Calculating Accuracy per class */\r\nconst accuracyperclass: any = await this.calculateAccuracyPerClass(TeachableMobileNet.validationDataset);\r\n// console.log(\"Accuracy per class: \", accuracyperclass);\r\n\r\n//Confusion matrix\r\n// Calling tf.confusionMatrix() method \r\nconst output = tf.math.confusionMatrix( accuracyperclass.reference, accuracyperclass.predictions, TeachableMobileNet.classes_names.length); \r\n \r\n// Printing output \r\noutput.print()\r\nconst confusion_matrix= output.dataSync();\r\n\r\n// console.log(confusion_matrix);\r\n// console.log(confusion_matrix[TeachableMobileNet.classes_names.length + TeachableMobileNet.classes_names.length]);\r\n\r\nconst accuracy = [];\r\n\r\nfor(let i=0; i<TeachableMobileNet.classes_names.length;i++){\r\n\r\n accuracy.push(confusion_matrix[TeachableMobileNet.classes_names.length*i+ i]/TeachableMobileNet.numValidation)\r\n}\r\n\r\nconsole.log(\"Accuracy per class: \", accuracy);\r\n\r\nfor(let i=0; i<TeachableMobileNet.classes_names.length;i++){\r\n\r\n confusion_matrix_recipient.push([]);\r\n\r\n for(let j=0; j<TeachableMobileNet.classes_names.length;j++){\r\n confusion_matrix_recipient[i].push([]);\r\n\r\n confusion_matrix_recipient[i][j]= confusion_matrix[TeachableMobileNet.classes_names.length*i+ j]/TeachableMobileNet.numValidation\r\n confusion_matrix_recipient[i][j]=(confusion_matrix_recipient[i][j].toFixed(2))*100;\r\n }\r\n\r\n // accuracy.push(confusion_matrix[TeachableMobileNet.classes_names.length*i+ i]/TeachableMobileNet.numValidation)\r\n}\r\n\r\nconsole.log(\"Confusion matrix as a matrix\")\r\nconsole.log(confusion_matrix_recipient);\r\n\r\nreturn accuracy.map((elem: any)=>elem.toFixed(2)*100);\r\n}\r\n\r\n \r\n async loadImages(number_of_species: number, classes_names: string[], options: object){\r\n TeachableMobileNet.classes_names=classes_names;\r\n \r\n await this.add_species(number_of_species, options); \r\n\r\n}\r\n\r\nasync add_species(number_of_species: number, options: object){\r\n \r\n //Loading feature model, used to create features from images\r\n // await this.loadFeatureModel();\r\n\r\n for (let i = 0; i < TeachableMobileNet.classes_names.length; i++) {\r\n // this.add_images(this.classes_names[i], number_of_species, options);\r\n }\r\n}\r\n\r\n/**\r\n * \r\n * @param name - name of the class receiving an example\r\n * @param number_of_species - how many images to add\r\n * @param options - details on the location of the images\r\n */\r\nasync add_images(name: string, number_of_species: number, options: any){ \r\n\r\n const class_add: any= [];\r\n\r\n for (let i = 0; i < number_of_species; i++) { \r\n // class_add.push(`${options.base}/${name}/${options.file_name} ${i}.${options.file_extension}`);\r\n \r\n //Uploading images\r\n const cake = new Image(); \r\n // cake.src = `${options.base}/${name}/${options.file_name} ${i}.${options.file_extension}`;\r\n cake.height=224;\r\n cake.width=224;\r\n cake.src=\"./assets/dataset/Can%C3%A1rio-da-Terra/image%200.jpeg\"\r\n // console.log(\"Image location: \", cake.src )\r\n\r\n await new Promise<void>((resolve, reject) => {\r\n cake.onload = () => {\r\n\r\n //Finding the correspondent index of the class with name given\r\n const index= TeachableMobileNet.classes_names.findIndex((elem)=>elem===name)\r\n\r\n // this.addExample(index, cake);\r\n\r\n resolve();\r\n };\r\n \r\n cake.onerror = (error) => {\r\n // Handle error if the image fails to load\r\n reject(error);\r\n };\r\n });\r\n }\r\n\r\n // this.classes.push({name: name, images: class_add}) \r\n\r\n }\r\n\r\n\r\n\r\n \r\n/**\r\n * This method will transform images into tensors\r\n * @param number_of_classes - number of classes\r\n * @param classes_names - name of each class\r\n */\r\nasync createTensors(number_of_classes: number, classes_names: string[]) {\r\n\r\n let output: any = [];\r\n\r\n /** There is a function on TensorFlow.js that also does that */\r\n const signatures= new Util().identityMatrix(number_of_classes);\r\n\r\n for (let i = 0; i < number_of_classes; i++) {\r\n\r\n this.classes[i].signature=signatures[i];\r\n this.classes[i].name=classes_names[i];\r\n\r\n for (let j = 0; j < this.classes[i].images.length; j++) {\r\n\r\n\r\n }\r\n\r\n }\r\n}\r\n\r\n /**\r\n * Add a sample of data under the provided className\r\n * @param className the classification this example belongs to\r\n * @param sample the image / tensor that belongs in this classification\r\n */\r\n // public async addExample(className: number, sample: HTMLCanvasElement | tf.Tensor) {\r\npublic static async addExample(className: number, name: string, sample: HTMLImageElement | HTMLCanvasElement | tf.Tensor) {\r\n\r\n // console.log(\"Adding a new example...\") \r\n \r\n const cap = isTensor(sample) ? sample : capture(sample);\r\n \r\n // if(!this.truncatedModel)\r\n // await this.loadFeatureModel();\r\n\r\n //Getting the features\r\n const example = this.truncatedModel.predict(cap) as tf.Tensor;\r\n // console.log(\"Shape after feature extraction: \", example.shape) \r\n \r\n\r\n const activation = example.dataSync() as Float32Array;\r\n \r\n //Very important to clean the memory aftermath, it makes the difference\r\n cap.dispose();\r\n example.dispose();\r\n \r\n // //Accessing the instance variable, not the local ones\r\n // // save samples of each class separately \r\n \r\n if(!TeachableMobileNet.examples[className])\r\n //and an empty array, make sure there is not empty elements. \r\n //it will create issue when transforming to tensors\r\n TeachableMobileNet.examples[className]=[]\r\n\r\n\r\n if(!TeachableMobileNet.classes_names[className])\r\n //Saving the lable when it first appears\r\n TeachableMobileNet.classes_names[className]=name;\r\n\r\n TeachableMobileNet.examples[className].push(activation);\r\n \r\n // // increase our sample counter\r\n TeachableMobileNet.totalSamples++;\r\n }\r\n\r\n\r\n /**\r\n * process the current examples provided to calculate labels and format\r\n * into proper tf.data.Dataset\r\n */\r\n static prepare() {\r\n for (const classes in TeachableMobileNet.examples){\r\n if (classes.length === 0) {\r\n throw new Error('Add some examples before training');\r\n }\r\n }\r\n\r\n const datasets: any = this.convertToTfDataset();\r\n\r\n this.trainDataset = datasets.trainDataset;\r\n this.validationDataset = datasets.validationDataset;\r\n}\r\n\r\npublic prepareDataset() {\r\n for (let i = 0; i < TeachableMobileNet.numClasses; i++) {\r\n //Different from the original implementation of TM, mine is using example as static.\r\n //The goal is saving memory by using a single instance of the variable\r\n TeachableMobileNet.examples[i] = [];\r\n }\r\n}\r\n\r\n \r\n // Optional seed to make shuffling of data predictable\r\n static seed: seedrandom.prng;\r\n\r\n\r\n\r\n \r\n/**\r\n * Process the examples by first shuffling randomly per class, then adding\r\n * one-hot labels, then splitting into training/validation datsets, and finally\r\n * sorting one last time\r\n */\r\n \r\nstatic convertToTfDataset() {\r\n\r\n // first shuffle each class individually\r\n // TODO: we could basically replicate this by insterting randomly\r\n for (let i = 0; i < TeachableMobileNet.examples.length; i++) {\r\n TeachableMobileNet.examples[i] = fisherYates(TeachableMobileNet.examples[i], this.seed) as Float32Array[];\r\n }\r\n\r\n // then break into validation and test datasets\r\n let trainDataset: Sample[] = [];\r\n let validationDataset: Sample[] = [];\r\n\r\n // for each class, add samples to train and validation dataset\r\n for (let i = 0; i < TeachableMobileNet.examples.length; i++) {\r\n \r\n // console.log(\"Number of classes: \", TeachableMobileNet.classes_names.length);\r\n\r\n const y = flatOneHot(i, TeachableMobileNet.classes_names.length);\r\n\r\n const classLength = TeachableMobileNet.examples[i].length;\r\n\r\n // console.log(\"Number of elements per class: \", classLength);\r\n\r\n const numValidation = Math.ceil(VALIDATION_FRACTION * classLength);\r\n const numTrain = classLength - numValidation;\r\n\r\n this.numValidation=numValidation;\r\n \r\n /**It is visiting per class, thus, it is possible to fix y, the target label */\r\n \r\n const classTrain = this.examples[i].slice(0, numTrain).map((dataArray) => {\r\n return { data: dataArray, label: y };\r\n });\r\n\r\n const classValidation = this.examples[i].slice(numTrain).map((dataArray) => {\r\n return { data: dataArray, label: y };\r\n });\r\n\r\n trainDataset = trainDataset.concat(classTrain);\r\n validationDataset = validationDataset.concat(classValidation); \r\n\r\n\r\n }\r\n\r\n // console.log(\"Training element: \", trainDataset[trainDataset.length-1]) \r\n // console.log(\"Training length: \", trainDataset.length)\r\n // console.log(\"validation length: \", validationDataset.length);\r\n\r\n \r\n // finally shuffle both train and validation datasets\r\n trainDataset = fisherYates(trainDataset, this.seed) as Sample[];\r\n validationDataset = fisherYates(validationDataset, this.seed) as Sample[];\r\n\r\n const trainX = tf.data.array(trainDataset.map(sample => sample.data));\r\n const validationX = tf.data.array(validationDataset.map(sample => sample.data));\r\n const trainY = tf.data.array(trainDataset.map(sample => sample.label));\r\n const validationY = tf.data.array(validationDataset.map(sample => sample.label));\r\n\r\n // return tf.data dataset objects\r\n return {\r\n trainDataset: tf.data.zip({ xs: trainX, ys: trainY}),\r\n validationDataset: tf.data.zip({ xs: validationX, ys: validationY})\r\n };\r\n\r\n\r\n}\r\n\r\ndatasetForEvaluation(){\r\n\r\n}\r\n\r\n/**Metrics */\r\n\r\nstatic feature_aux: any;\r\nstatic target_aux: any;\r\n\r\nasync evaluate(){\r\n \r\n //Check of the features have already been calculated\r\n /**For avoiding recalculating the features every generation */\r\n if(!TeachableMobileNet.feature_aux){\r\n const features: any=[];\r\n const targets: any=[];\r\n\r\n for (let i = 0; i < TeachableMobileNet.examples.length; i++) {\r\n\r\n const y = flatOneHot(i, TeachableMobileNet.classes_names.length);\r\n //For class i, push all the examples.\r\n TeachableMobileNet.examples[i].forEach((elemn)=>{\r\n\r\n //Pushing the target signature\r\n targets.push(y);\r\n \r\n //Pushing features\r\n features.push(elemn)\r\n })\r\n\r\n } \r\n\r\n TeachableMobileNet.feature_aux= tf.tensor(features);\r\n TeachableMobileNet.target_aux= tf.tensor(targets);\r\n\r\n } \r\n\r\n //Evaluating the model\r\n const aux: any = this.trainingModel.evaluate(TeachableMobileNet.feature_aux, TeachableMobileNet.target_aux);\r\n \r\n //Return just the accuracy\r\n return aux[1].dataSync()[0];\r\n\r\n\r\n}\r\n\r\n\r\n// async evaluate(){\r\n\r\n// const features: any=[];\r\n// const targets: any=[];\r\n\r\n// for (let i = 0; i < TeachableMobileNet.examples.length; i++) {\r\n\r\n// const y = flatOneHot(i, TeachableMobileNet.classes_names.length);\r\n \r\n\r\n\r\n// //For class i, push all the examples.\r\n// TeachableMobileNet.examples[i].forEach((elemn)=>{\r\n\r\n// //Pushing the target signature\r\n// targets.push(y);\r\n \r\n// //Pushing features\r\n// features.push(elemn)\r\n// })\r\n\r\n// } \r\n\r\n// const aux_features= tf.tensor(features);\r\n// const aux_target= tf.tensor(targets);\r\n\r\n \r\n// // console.log(\"Tensor stack for evaluation: \", aux_features.shape)\r\n\r\n// const aux: any = this.trainingModel.evaluate(aux_features, aux_target);\r\n\r\n\r\n// return aux[1].dataSync()[0];\r\n\r\n\r\n// }\r\n\r\n\r\n/*** Final statistics */\r\n/* \r\n * Calculate each class accuracy using the validation dataset\r\n*/\r\npublic async calculateAccuracyPerClass(validationData: any) {\r\n\r\n const validationXs = TeachableMobileNet.validationDataset.mapAsync(async (dataset: TensorContainer) => {\r\n return (dataset as { xs: TensorContainer, ys: TensorContainer}).xs;\r\n});\r\n\r\nconst validationYs = TeachableMobileNet.validationDataset.mapAsync(async (dataset: TensorContainer) => {\r\n return (dataset as { xs: TensorContainer, ys: TensorContainer}).ys;\r\n});\r\n\r\n// console.log(\"validation dataset: \", validationXs);\r\n \r\n// console.log(\"For calculating batch size: \", validationYs);\r\n\r\n// we need to split our validation data into batches in case it is too large to fit in memory\r\nconst batchSize = Math.min(validationYs.size, 32);\r\n// const batchSize =1;\r\n\r\nconst iterations = Math.ceil(validationYs.size / batchSize);\r\n\r\n// console.log(\"Batch size: \", batchSize);\r\n\r\nconst batchesX = validationXs.batch(batchSize);\r\n\r\nconst batchesY = validationYs.batch(batchSize);\r\nconst itX = await batchesX.iterator();\r\nconst itY = await batchesY.iterator();\r\nconst allX = [];\r\nconst allY = [];\r\n\r\nfor (let i = 0; i < iterations; i++) {\r\n\r\n // 1. get the prediction values in batches\r\n const batchedXTensor = await itX.next(); \r\n\r\n // console.log(\"Batch size on accuracy per class: \", batchedXTensor.value.shape);\r\n\r\n const batchedXPredictionTensor = this.trainingModel.predict(batchedXTensor.value) as tf.Tensor;\r\n\r\n const argMaxX = batchedXPredictionTensor.argMax(1); // Returns the indices of the max values along an axis\r\n\r\n allX.push(argMaxX);\r\n\r\n // 2. get the ground truth label values in batches\r\n const batchedYTensor = await itY.next();\r\n const argMaxY = batchedYTensor.value.argMax(1); // Returns the indices of the max values along an axis\r\n\r\n allY.push(argMaxY);\r\n \r\n // 3. dispose of all our tensors\r\n batchedXTensor.value.dispose();\r\n batchedXPredictionTensor.dispose();\r\n batchedYTensor.value.dispose();\r\n}\r\n\r\n // concatenate all the results of the batches\r\n const reference = tf.concat(allY); // this is the ground truth\r\n const predictions = tf.concat(allX); // this is the prediction our model is guessing\r\n \r\n // console.log(\"this is the ground truth: \", reference.dataSync())\r\n // console.log(\"This is the prediction our model is guessing: \", predictions.dataSync())\r\n\r\n // only if we concatenated more than one tensor for preference and reference\r\n if (iterations !== 1) {\r\n for (let i = 0; i < allX.length; i++) {\r\n allX[i].dispose();\r\n allY[i].dispose();\r\n }\r\n }\r\n\r\n // console.log(\"Lengtth: \", await reference.dataSync().length) \r\n \r\n // const accuracyperclass=[];\r\n\r\n // const reference_aux= await reference.dataSync();\r\n // const prediction_aux= await predictions.dataSync();\r\n // console.log( predictions.dataSync());\r\n\r\n // reference_aux.forEach((element, index) => {\r\n // if()\r\n \r\n // }); \r\n\r\n\r\n return { reference, predictions }; \r\n\r\n}\r\n\r\n}//end of class\r\n\r\n\r\n\r\n\r\n\r\n/***Support methods (helpers) */\r\n\r\nconst isTensor = (c: any): c is tf.Tensor =>\r\n typeof c.dataId === 'object' && typeof c.shape === 'object';\r\n/**\r\n * Converts an integer into its one-hot representation and returns\r\n * the data as a JS Array.\r\n */\r\nfunction flatOneHot(label: number, numClasses: number) {\r\n\r\n const labelOneHot = new Array(numClasses).fill(0) as number[];\r\n labelOneHot[label] = 1;\r\n\r\n return labelOneHot;\r\n}\r\n\r\ninterface Sample {\r\n data: Float32Array;\r\n label: number[];\r\n}\r\n\r\n\r\n/**\r\n * Shuffle an array of Float32Array or Samples using Fisher-Yates algorithm\r\n * Takes an optional seed value to make shuffling predictable\r\n */\r\nfunction fisherYates(array: Float32Array[] | Sample[], seed?: seedrandom.prng) {\r\n const length = array.length;\r\n\r\n // need to clone array or we'd be editing original as we goo\r\n const shuffled = array.slice();\r\n\r\n for (let i = (length - 1); i > 0; i -= 1) {\r\n let randomIndex ;\r\n if (seed) {\r\n randomIndex = Math.floor(seed() * (i + 1));\r\n }\r\n else {\r\n randomIndex = Math.floor(Math.random() * (i + 1));\r\n }\r\n\r\n [shuffled[i], shuffled[randomIndex]] = [shuffled[randomIndex],shuffled[i]];\r\n }\r\n\r\n return shuffled;\r\n}\r\n","import { Component} from '@angular/core';\r\nimport { Group } from '../../interfaces/group';\r\nimport { CommonModule } from '@angular/common';\r\nimport { TeachableMobileNet } from '../../models/teachable-evolution';\r\n\r\n@Component({\r\n selector: 'neuroevolution-display-panel',\r\n standalone: true,\r\n imports: [CommonModule],\r\n templateUrl: './display-panel.component.html',\r\n styleUrl: './display-panel.component.css'\r\n})\r\nexport class DisplayPanelComponent {\r\n\r\n classes: Group[]=[];\r\n\r\n classes_names!: string[];\r\n\r\n number_of_samples_per_class!: number;\r\n\r\nloadImages(number_of_species: number, classes_names: string[], options: object){\r\n \r\n this.classes_names=classes_names;\r\n this.number_of_samples_per_class=number_of_species;\r\n\r\n this.add_species(number_of_species, options); \r\n\r\n }\r\n\r\n\r\nadd_species(number_of_species: number, options: object){\r\n\r\n for (let i = 0; i < this.classes_names.length; i++) {\r\n this.add_images(this.classes_names[i], number_of_species, options);\r\n \r\n }\r\n\r\n }\r\n\r\n add_images(name: string, number_of_species: number, options: any){ \r\n\r\n const class_add: any= [];\r\n\r\n for (let i = 0; i < number_of_species; i++) {\r\n if(!options.file_name && (options.subfolder)){ \r\n class_add.push(`${options.base}/${name}/${options.subfolder}/${name} ${i+1}.${options.file_extension}`);\r\n } \r\n else if(options.numbered){\r\n \r\n class_add.push(`${options.base}/${name}/${i+1}.${options.file_extension}`);\r\n\r\n\r\n } \r\n \r\n else \r\n class_add.push(`${options.base}/${name}/${options.file_name} ${i+1}.${options.file_extension}`);\r\n }\r\n\r\n this.classes.push({name: name, images: class_add}) \r\n\r\n }\r\n\r\n async addexamples(){\r\n\r\n //This is needed to make sure it gives time for the images to upload\r\n //The images upload very fast, what makes this method execute before the images are on HTML\r\n //It can be removed if somehow this method is just called after the images are available.\r\n // console.log(\"Loading examples as tensors....\")\r\n await this.delay(0);\r\n\r\n for (let i = 0; i < this.classes_names.length; i++) {\r\n await this.add_example(this.classes_names[i], this.number_of_samples_per_class);\r\n }\r\n }\r\n\r\n async add_example(name: string, number_of_species: number){ \r\n\r\n const class_add: any= [];\r\n // console.log(name)\r\n for (let i = 0; i < number_of_species; i++) { \r\n \r\n //Collecting the images from HTML\r\n const aux = document.getElementById(`class-${name}-${i}`) as HTMLImageElement; \r\n\r\n //Adding the example\r\n const index= this.classes_names.findIndex((elem)=>elem===name)\r\n\r\n await TeachableMobileNet.addExample(index, name, aux); \r\n \r\n }\r\n\r\n // this.classes.push({name: name, images: class_add}) \r\n\r\n }\r\n\r\n delay(ms: number) {\r\n return new Promise<void>((resolve) => setTimeout(resolve, ms));\r\n}\r\n}\r\n","<div *ngFor=\"let class of classes; index as i\">\r\n <h1>{{class.name}}</h1>\r\n <img *ngFor=\"let item of class.images; index as i\" [src]=\"item\" width=\"224\" height=\"224\" [id]=\"'class-' + class.name + '-' + i\" crossorigin=\"anonymous\" >\r\n</div>\r\n","\r\nimport {TeachableMobileNet} from \"../models/teachable-evolution\"\r\nimport * as tf from '@tensorflow/tfjs';\r\n\r\n/**\r\n * Each individual of the population will be made of \r\n * an array, correspodent to the neural network weights and\r\n * an evaluation, its respective accuracy on the dataset given.\r\n * \r\n */\r\ninterface Individual {\r\n individual: TeachableMobileNet,\r\n accuracy?: number\r\n}\r\n\r\nexport abstract class NeuroEvolution {\r\n\r\n /** \r\n This is the population. I have decided to create a population of just weights.\r\n I had to change my mind. Working with weights is tricky. \r\n I have decided to sacrifice memory to make my life easiser.\r\n Tensors has their inner methods, it helps on the operators.\r\n I have to pay attention to memory manegement.\r\n Working with memory in tensors is tricky. \r\n */\r\n\r\n population: Individual[]=[];\r\n private _population_size: number=30;\r\n \r\n /**Setters and Getters */\r\n public set population_size(population_size: number){\r\n this._population_size=population_size;\r\n }\r\n public get population_size(){\r\n return this._population_size;\r\n }\r\n\r\n /**\r\n * Methods with implementation\r\n */\r\n\r\n async evaluate(){\r\n return this.population.forEach(async (elem)=>{\r\n elem.accuracy= await elem.individual.evaluate(); \r\n })\r\n }\r\n\r\n start_population(){\r\n\r\n for(let i=0; i<this.population_size;i++){ \r\n this.population.push({individual: new TeachableMobileNet()})\r\n }\r\n\r\n }\r\n\r\n async apply_evolution(iteration: number){\r\n\r\n for(let i=0;i<iteration;i++){\r\n \r\n console.log(\"Interation: \",i)\r\n console.log(\"Memory: \", tf.memory().numBytes);\r\n console.log(\"Tensors in memory: \", tf.memory().numTensors);\r\n console.log(\"Population length: \", this.population.length);\r\n await this.evolution();\r\n }\r\n\r\n }\r\n \r\n /**\r\n * This method will apply the evolution\r\n */\r\n async evolution(){\r\n\r\n \r\n \r\n //Update the accuracy\r\n await this.evaluate();\r\n\r\n const offspring=[];\r\n\r\n /**First step is crossover, for creating offspring */\r\n for(let i=0; i<this.population.length;i++)\r\n {\r\n //The population will double in size\r\n offspring.push(this.crossover()); \r\n }\r\n\r\n //Mutation on the offspring\r\n // console.log(\"Weight before mutation: \", offspring[0].individual.getHead().layers[0].getWeights()[0].dataSync());\r\n\r\n this.mutation(offspring) \r\n\r\n //Joining parents and offspring into the same pool for selection\r\n this.population=[...this.population, ...offspring];\r\n\r\n //Update the accuracy\r\n await this.evaluate();\r\n\r\n\r\n //selection\r\n this.selection();\r\n console.log(\"Best accuracy: \", this.getTheBest().accuracy)\r\n console.log(\"Worst accuracy: \", this.getTheWorst().accuracy) \r\n\r\n }\r\n\r\n /**Abstract methods.\r\n * Should be implemented by each variation of evolutionary algorithms\r\n */\r\n\r\n abstract crossover(): Individual;\r\n abstract mutation(offspring: Individual[]): void;\r\n abstract selection(): void;\r\n\r\n\r\n /**Helpers */\r\n\r\n getTheBest(): Individual{\r\n let index_best: number=0;\r\n let best=0;\r\n\r\n this.population.forEach((elem: any, index: number)=>{\r\n\r\n if(elem.accuracy>best){\r\n best=elem.accuracy;\r\n index_best=index\r\n }\r\n \r\n })\r\n\r\n return this.population[index_best];\r\n }\r\n\r\n\r\n getTheWorst(): Individual{\r\n let index_worst: number=0;\r\n let worst=1;\r\n\r\n this.population.forEach((elem: any, index: number)=>{\r\n\r\n if(elem.accuracy<worst){\r\n worst=elem.accuracy;\r\n index_worst=index\r\n }\r\n \r\n })\r\n\r\n return this.population[index_worst];\r\n }\r\n\r\n /**\r\n * Selecting individuals by elitism\r\n */\r\n select_parents_by_rollet_wheels_v2(selection_number=2): Individual[]{\r\n\r\n // console.log(\"Selecting parents by rollet wheels...\");\r\n \r\n const share: any=[];\r\n \r\n let total: any=0;\r\n \r\n // console.log(\"Population length...\", this.population.length);\r\n \r\n //This will create an overall accuracy\r\n this.population.forEach((elem)=>total+=elem.accuracy);\r\n \r\n let pointer=0;\r\n \r\n this.population.forEach((elem:any, index)=>{\r\n \r\n // console.log(\"Accuracy...\", elem.accuracy);\r\n \r\n share.push(\r\n {\r\n index: index,\r\n share: elem.accuracy/total,\r\n min: pointer,\r\n max: pointer + (elem.accuracy/total)\r\n })\r\n \r\n pointer+=elem.accuracy/total;\r\n });\r\n \r\n // console.log(\"Shares: \", share);\r\n \r\n const aux_selection: any =[];\r\n \r\n //Selecting two individuals using roulette wheels\r\n let counter=0;\r\n\r\n const indexes_aux: number[]=[];\r\n\r\n while(counter<selection_number){\r\n \r\n //Random pointer, used to randomly select an individual\r\n const aux_index= Math.random();\r\n \r\n share.forEach((elem: any)=>{\r\n \r\n if((elem.min<aux_index)&&(elem.max>aux_index)){\r\n \r\n const aux: Individual = {individual: new TeachableMobileNet(), accuracy: this.population[elem.index].accuracy }\r\n \r\n // console.log(\"Individual just created (weigth): \", aux.individual.getHead().layers[0].getWeights()[0].dataSync());\r\n \r\n // console.log(\"Individual original: \", this.population[elem.index].individual.getHead().layers[0].getWeights()[0].dataSync());\r\n // // Original Recipient\r\n // this.copyModel(this.population[elem.index].individual.getHead(),aux.individual.getHead())\r\n\r\n // this.population[elem.index].individual.getHead().dispose();\r\n \r\n // console.log(\"Individual just created (weigtht, copied): \", aux.individual.getHead().layers[0].getWeights()[0].dataSync());\r\n \r\n\r\n counter++;\r\n aux_selection.push(this.population[elem.index]);\r\n\r\n // indexes_aux.push(elem.index)\r\n }\r\n })\r\n }\r\n\r\n // this.population.forEach((elem, index)=>{\r\n // if(!indexes_aux.includes(index)){\r\n // console.log(\"Disposed...\")\r\n // elem.individual.getHead().dispose();\r\n // }\r\n \r\n // })\r\n\r\n // this.population=[];\r\n\r\n return aux_selection;\r\n }\r\n \r\n /**\r\n * Selecting individuals by elitism\r\n */\r\n select_parents_by_rollet_wheels(selection_number=2): Individual[]{\r\n\r\n // console.log\r\n // (\"Selecting parents by rollet wheels...\");\r\n\r\n const share: any=[];\r\n\r\n let total: any=0;\r\n \r\n // console.log(\"Population length...\", this.population.length);\r\n\r\n //This will create an overall accuracy\r\n this.population.forEach((elem)=>total+=elem.accuracy);\r\n\r\n let pointer=0;\r\n\r\n this.population.forEach((elem:any, index)=>{\r\n\r\n // console.log(\"Accuracy...\", elem.accuracy);\r\n\r\n share.push(\r\n {\r\n index: index,\r\n share: elem.accuracy/total,\r\n min: pointer,\r\n max: pointer + (elem.accuracy/total)\r\n })\r\n\r\n pointer+=elem.accuracy/total;\r\n });\r\n\r\n // console.log(\"Shares: \", share);\r\n\r\n const aux_selection: any =[];\r\n\r\n //Selecting two individuals using roulette wheels\r\n let counter=0;\r\n while(counter<selection_number){\r\n \r\n //Random pointer, used to randomly select an individual\r\n const aux_index= Math.random();\r\n\r\n share.forEach((elem: any)=>{\r\n\r\n if((elem.min<aux_index)&&(elem.max>aux_index)){\r\n counter++;\r\n aux_selection.push(this.population[elem.index]);\r\n }\r\n })\r\n }\r\n return aux_selection;\r\n }\r\n\r\n/**\r\n * This function will make a copy of a model on the weight level\r\n * This is an attempt to avoid influencing the new model when the old one\r\n * is eliminated. \r\n * \r\n * @param originalModel - the model to be copied \r\n * @param recipient - the new model\r\n */\r\nasync copyModel (originalModel: tf.LayersModel, recipient: tf.LayersModel) {\r\n\r\n originalModel.layers.forEach((layer: any, index: any)=>{\r\n recipient.layers[index].setWeights(layer.getWeights())\r\n })\r\n} \r\n\r\n}\r\n","import { NeuroEvolution } from \"./neuro-evolution\";\r\nimport {TeachableMobileNet} from \"../models/teachable-evolution\"\r\nimport * as tf from '@tensorflow/tfjs';\r\n\r\n/**\r\n * Each individual of the population will be made of \r\n * an array, correspodent to the neural network weights and\r\n * an evaluation, its respective accuracy on the dataset given.\r\n * \r\n */\r\ninterface Individual {\r\n individual: TeachableMobileNet,\r\n accuracy?: number\r\n}\r\n\r\n\r\nexport class GeneticAlgorithm extends NeuroEvolution { \r\n \r\n \r\n\r\n /**\r\n * Implementatin abstract methods\r\n */\r\n\r\n override crossover(): Individual {\r\n // console.log(\"Applying crossover on Genetic Algorithms...\")\r\n\r\n const selected = this.select_parents_by_rollet_wheels();\r\n\r\n const individual_1 = selected[0];\r\n const individual_2 = selected[1];\r\n\r\n // console.log(\"Individual 1: \")\r\n // individual_1.individual.getHead().summary();\r\n\r\n let individual_3: Individual= {individual: new TeachableMobileNet};\r\n\r\n const alfa = Math.random();\r\n\r\n individual_3.individual.getHead().layers.forEach((layer, index)=>{\r\n individual_3.individual.getHead().layers[index].setWeights(\r\n individual_1.individual.getHead().layers[index].getWeights()\r\n .map((elem: any, index_2: any)=> elem.mul(alfa)\r\n .add(individual_2.individual.getHead().layers[index]\r\n .getWeights()[index_2]\r\n .mul(1 - alfa)\r\n )))\r\n })\r\n\r\n // this.population.push(individual_3);\r\n // console.log(\"Population: \", this.population.length); \r\n \r\n return individual_3; \r\n \r\n }//end of crossover\r\n\r\n override mutation(offspring: Individual[]): void {\r\n\r\n const multation_rate=1;\r\n\r\n offspring.forEach((elem)=>{\r\n elem.individual.getHead().setWeights(\r\n elem.individual.getHead().getWeights().map((elem_2)=> { \r\n return elem_2.add(elem_2.mul(multation_rate*Math.random())) \r\n })\r\n );\r\n })\r\n }\r\n\r\n override selection(): void {\r\n\r\n const selected_individuals= this.select_parents_by_rollet_wheels(this.population_size);\r\n\r\n //The best will enter on the population by elitism\r\n const best= this.getTheBest();\r\n\r\n this.population=[];\r\n\r\n this.population=selected_individuals;\r\n\r\n console.log(\"Best accuracy (elitism): \", best.accuracy);\r\n \r\n\r\n }\r\n}\r\n","import { Component, Input } from '@angular/core';\r\n\r\nimport { CommonModule } from '@angular/common';\r\n\r\n@Component({\r\n selector: 'neuroevolution-metrics',\r\n standalone: true,\r\n imports: [CommonModule],\r\n templateUrl: './metrics.component.html',\r\n styleUrl: './metrics.component.css'\r\n})\r\nexport class MetricsComponent {\r\n\r\n @Input() accuracy_per_class: number[]=[];\r\n @Input() classes_names: string[]=[];\r\n @Input() confusion_matrix: number[][]=[];\r\n\r\n\r\n}\r\n","<h1>Accuracy per class</h1>\r\n<div *ngFor=\"let accuracy of accuracy_per_class; index as index\" > {{classes_names[index]}}: {{accuracy}}%</div>\r\n\r\n\r\n\r\n<h2>Confusion Matrix</h2>\r\n\r\n<table>\r\n <tr>\r\n <th *ngFor=\"let label of classes_names\">{{label}}</th>\r\n </tr>\r\n <tr *ngFor=\"let item of confusion_matrix ; index as i\">\r\n <td *ngFor=\"let value of item ; index as j\" > {{confusion_matrix[i][j]}}%</td> \r\n </tr>\r\n</table>\r\n","/*\r\n * Public API Surface of tfjs-evolution\r\n */\r\n\r\nexport * from './lib/tfjs-evolution.service';\r\nexport * from './lib/tfjs-evolution.component';\r\n\r\nexport * from './lib/components/display-panel/display-panel.component';\r\n\r\nexport * from './lib/models/teachable-evolution';\r\n\r\nexport * from './lib/Classes/genetic-algorithm';\r\n\r\nexport * from './lib/components/metrics/metrics.component';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import * as i0 from "@angular/core";
2
+ export declare class MetricsComponent {
3
+ accuracy_per_class: number[];
4
+ classes_names: string[];
5
+ confusion_matrix: number[][];
6
+ static ɵfac: i0.ɵɵFactoryDeclaration<MetricsComponent, never>;
7
+ static ɵcmp: i0.ɵɵComponentDeclaration<MetricsComponent, "neuroevolution-metrics", never, { "accuracy_per_class": { "alias": "accuracy_per_class"; "required": false; }; "classes_names": { "alias": "classes_names"; "required": false; }; "confusion_matrix": { "alias": "confusion_matrix"; "required": false; }; }, {}, never, never, true, never>;
8
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tfjs-evolution",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
4
  "description": "This is an experimentation with evolutionary computing applied to neural networks using TensorFlow.js",
5
5
  "author": "Jorge Guerra Pires",
6
6
  "license": "MIT",
package/public-api.d.ts CHANGED
@@ -3,3 +3,4 @@ export * from './lib/tfjs-evolution.component';
3
3
  export * from './lib/components/display-panel/display-panel.component';
4
4
  export * from './lib/models/teachable-evolution';
5
5
  export * from './lib/Classes/genetic-algorithm';
6
+ export * from './lib/components/metrics/metrics.component';