tfjs-evolution 0.0.10 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -38,7 +38,8 @@ export class GeneticAlgorithm extends NeuroEvolution {
38
38
  const best = this.getTheBest();
39
39
  this.population = [];
40
40
  this.population = selected_individuals;
41
+ this.population.push(best);
41
42
  console.log("Best accuracy (elitism): ", best.accuracy);
42
43
  }
43
44
  }
44
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXRpYy1hbGdvcml0aG0uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy90ZmpzLWV2b2x1dGlvbi9zcmMvbGliL0NsYXNzZXMvZ2VuZXRpYy1hbGdvcml0aG0udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ25ELE9BQU8sRUFBQyxrQkFBa0IsRUFBQyxNQUFNLCtCQUErQixDQUFBO0FBZWhFLE1BQU0sT0FBTyxnQkFBaUIsU0FBUSxjQUFjO0lBSWhEOztPQUVHO0lBRU0sU0FBUztRQUNkLDZEQUE2RDtRQUU3RCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsK0JBQStCLEVBQUUsQ0FBQztRQUV4RCxNQUFNLFlBQVksR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDakMsTUFBTSxZQUFZLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRWpDLGdDQUFnQztRQUNoQywrQ0FBK0M7UUFFL0MsSUFBSSxZQUFZLEdBQWMsRUFBQyxVQUFVLEVBQUUsSUFBSSxrQkFBa0IsRUFBQyxDQUFDO1FBRW5FLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUUzQixZQUFZLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFDLEVBQUU7WUFDN0QsWUFBWSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsVUFBVSxDQUN0RCxZQUFZLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxVQUFVLEVBQUU7aUJBQzNELEdBQUcsQ0FBQyxDQUFDLElBQVMsRUFBRSxPQUFZLEVBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDO2lCQUM5QyxHQUFHLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDO2lCQUNuRCxVQUFVLEVBQUUsQ0FBQyxPQUFPLENBQUM7aUJBQ3JCLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQ2pCLENBQUMsQ0FBQyxDQUFBO1FBQ1AsQ0FBQyxDQUFDLENBQUE7UUFFRixzQ0FBc0M7UUFDdEMseURBQXlEO1FBRXpELE9BQU8sWUFBWSxDQUFDO0lBRXhCLENBQUMsQ0FBQSxrQkFBa0I7SUFFVixRQUFRLENBQUMsU0FBdUI7UUFFckMsTUFBTSxjQUFjLEdBQUMsQ0FBQyxDQUFDO1FBRXZCLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUMsRUFBRTtZQUN0QixJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFDLFVBQVUsQ0FDaEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUMsRUFBRTtnQkFDbkQsT0FBTyxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsY0FBYyxHQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUE7WUFDN0QsQ0FBQyxDQUFDLENBQ0gsQ0FBQztRQUNSLENBQUMsQ0FBQyxDQUFBO0lBQ04sQ0FBQztJQUVRLFNBQVM7UUFFZCxNQUFNLG9CQUFvQixHQUFFLElBQUksQ0FBQywrQkFBK0IsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7UUFFdkYsa0RBQWtEO1FBQ2xELE1BQU0sSUFBSSxHQUFFLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUU5QixJQUFJLENBQUMsVUFBVSxHQUFDLEVBQUUsQ0FBQztRQUVuQixJQUFJLENBQUMsVUFBVSxHQUFDLG9CQUFvQixDQUFDO1FBRXJDLE9BQU8sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBRzVELENBQUM7Q0FDSiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE5ldXJvRXZvbHV0aW9uIH0gZnJvbSBcIi4vbmV1cm8tZXZvbHV0aW9uXCI7XHJcbmltcG9ydCB7VGVhY2hhYmxlTW9iaWxlTmV0fSBmcm9tIFwiLi4vbW9kZWxzL3RlYWNoYWJsZS1ldm9sdXRpb25cIlxyXG5pbXBvcnQgKiBhcyB0ZiBmcm9tICdAdGVuc29yZmxvdy90ZmpzJztcclxuXHJcbi8qKlxyXG4gKiBFYWNoIGluZGl2aWR1YWwgb2YgdGhlIHBvcHVsYXRpb24gd2lsbCBiZSBtYWRlIG9mIFxyXG4gKiBhbiBhcnJheSwgY29ycmVzcG9kZW50IHRvIHRoZSBuZXVyYWwgbmV0d29yayB3ZWlnaHRzIGFuZFxyXG4gKiBhbiBldmFsdWF0aW9uLCBpdHMgcmVzcGVjdGl2ZSBhY2N1cmFjeSBvbiB0aGUgZGF0YXNldCBnaXZlbi5cclxuICogXHJcbiAqL1xyXG5pbnRlcmZhY2UgSW5kaXZpZHVhbCB7XHJcbiAgICBpbmRpdmlkdWFsOiBUZWFjaGFibGVNb2JpbGVOZXQsXHJcbiAgICBhY2N1cmFjeT86IG51bWJlclxyXG59XHJcblxyXG5cclxuZXhwb3J0IGNsYXNzIEdlbmV0aWNBbGdvcml0aG0gZXh0ZW5kcyBOZXVyb0V2b2x1dGlvbiB7IFxyXG4gICAgXHJcbiAgICBcclxuXHJcbiAgICAvKipcclxuICAgICAqIEltcGxlbWVudGF0aW4gYWJzdHJhY3QgbWV0aG9kc1xyXG4gICAgICovXHJcblxyXG4gICAgb3ZlcnJpZGUgY3Jvc3NvdmVyKCk6IEluZGl2aWR1YWwge1xyXG4gICAgICAgIC8vIGNvbnNvbGUubG9nKFwiQXBwbHlpbmcgY3Jvc3NvdmVyIG9uIEdlbmV0aWMgQWxnb3JpdGhtcy4uLlwiKVxyXG5cclxuICAgICAgICBjb25zdCBzZWxlY3RlZCA9IHRoaXMuc2VsZWN0X3BhcmVudHNfYnlfcm9sbGV0X3doZWVscygpO1xyXG5cclxuICAgICAgICBjb25zdCBpbmRpdmlkdWFsXzEgPSBzZWxlY3RlZFswXTtcclxuICAgICAgICBjb25zdCBpbmRpdmlkdWFsXzIgPSBzZWxlY3RlZFsxXTtcclxuXHJcbiAgICAgICAgLy8gY29uc29sZS5sb2coXCJJbmRpdmlkdWFsIDE6IFwiKVxyXG4gICAgICAgIC8vIGluZGl2aWR1YWxfMS5pbmRpdmlkdWFsLmdldEhlYWQoKS5zdW1tYXJ5KCk7XHJcblxyXG4gICAgICAgIGxldCBpbmRpdmlkdWFsXzM6IEluZGl2aWR1YWw9IHtpbmRpdmlkdWFsOiBuZXcgVGVhY2hhYmxlTW9iaWxlTmV0fTtcclxuXHJcbiAgICAgICAgY29uc3QgYWxmYSA9IE1hdGgucmFuZG9tKCk7XHJcblxyXG4gICAgICAgIGluZGl2aWR1YWxfMy5pbmRpdmlkdWFsLmdldEhlYWQoKS5sYXllcnMuZm9yRWFjaCgobGF5ZXIsIGluZGV4KT0+e1xyXG4gICAgICAgICAgICBpbmRpdmlkdWFsXzMuaW5kaXZpZHVhbC5nZXRIZWFkKCkubGF5ZXJzW2luZGV4XS5zZXRXZWlnaHRzKFxyXG4gICAgICAgICAgICAgICAgaW5kaXZpZHVhbF8xLmluZGl2aWR1YWwuZ2V0SGVhZCgpLmxheWVyc1tpbmRleF0uZ2V0V2VpZ2h0cygpXHJcbiAgICAgICAgICAgICAgICAubWFwKChlbGVtOiBhbnksIGluZGV4XzI6IGFueSk9PiBlbGVtLm11bChhbGZhKVxyXG4gICAgICAgICAgICAgICAgLmFkZChpbmRpdmlkdWFsXzIuaW5kaXZpZHVhbC5nZXRIZWFkKCkubGF5ZXJzW2luZGV4XVxyXG4gICAgICAgICAgICAgICAgLmdldFdlaWdodHMoKVtpbmRleF8yXVxyXG4gICAgICAgICAgICAgICAgLm11bCgxIC0gYWxmYSlcclxuICAgICAgICAgICAgKSkpXHJcbiAgICAgICAgfSlcclxuXHJcbiAgICAgICAgLy8gdGhpcy5wb3B1bGF0aW9uLnB1c2goaW5kaXZpZHVhbF8zKTtcclxuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlBvcHVsYXRpb246IFwiLCB0aGlzLnBvcHVsYXRpb24ubGVuZ3RoKTsgIFxyXG4gICAgICAgIFxyXG4gICAgICAgIHJldHVybiBpbmRpdmlkdWFsXzM7ICAgICAgICBcclxuICAgIFxyXG4gICAgfS8vZW5kIG9mIGNyb3Nzb3ZlclxyXG5cclxuICAgIG92ZXJyaWRlIG11dGF0aW9uKG9mZnNwcmluZzogSW5kaXZpZHVhbFtdKTogdm9pZCB7XHJcblxyXG4gICAgICAgIGNvbnN0IG11bHRhdGlvbl9yYXRlPTE7XHJcblxyXG4gICAgICAgIG9mZnNwcmluZy5mb3JFYWNoKChlbGVtKT0+e1xyXG4gICAgICAgICAgICBlbGVtLmluZGl2aWR1YWwuZ2V0SGVhZCgpLnNldFdlaWdodHMoXHJcbiAgICAgICAgICAgICAgICBlbGVtLmluZGl2aWR1YWwuZ2V0SGVhZCgpLmdldFdlaWdodHMoKS5tYXAoKGVsZW1fMik9PiB7ICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgIHJldHVybiBlbGVtXzIuYWRkKGVsZW1fMi5tdWwobXVsdGF0aW9uX3JhdGUqTWF0aC5yYW5kb20oKSkpICAgICBcclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICAgKTtcclxuICAgICAgICB9KVxyXG4gICAgfVxyXG5cclxuICAgIG92ZXJyaWRlIHNlbGVjdGlvbigpOiB2b2lkIHtcclxuXHJcbiAgICAgICAgY29uc3Qgc2VsZWN0ZWRfaW5kaXZpZHVhbHM9IHRoaXMuc2VsZWN0X3BhcmVudHNfYnlfcm9sbGV0X3doZWVscyh0aGlzLnBvcHVsYXRpb25fc2l6ZSk7XHJcblxyXG4gICAgICAgIC8vVGhlIGJlc3Qgd2lsbCBlbnRlciBvbiB0aGUgcG9wdWxhdGlvbiBieSBlbGl0aXNtXHJcbiAgICAgICAgY29uc3QgYmVzdD0gdGhpcy5nZXRUaGVCZXN0KCk7XHJcblxyXG4gICAgICAgIHRoaXMucG9wdWxhdGlvbj1bXTtcclxuXHJcbiAgICAgICAgdGhpcy5wb3B1bGF0aW9uPXNlbGVjdGVkX2luZGl2aWR1YWxzO1xyXG5cclxuICAgICAgICBjb25zb2xlLmxvZyhcIkJlc3QgYWNjdXJhY3kgKGVsaXRpc20pOiBcIiwgYmVzdC5hY2N1cmFjeSk7XHJcbiAgICAgICAgXHJcblxyXG4gICAgfVxyXG59XHJcbiJdfQ==
45
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXRpYy1hbGdvcml0aG0uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy90ZmpzLWV2b2x1dGlvbi9zcmMvbGliL0NsYXNzZXMvZ2VuZXRpYy1hbGdvcml0aG0udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ25ELE9BQU8sRUFBQyxrQkFBa0IsRUFBQyxNQUFNLCtCQUErQixDQUFBO0FBZWhFLE1BQU0sT0FBTyxnQkFBaUIsU0FBUSxjQUFjO0lBSWhEOztPQUVHO0lBRU0sU0FBUztRQUNkLDZEQUE2RDtRQUU3RCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsK0JBQStCLEVBQUUsQ0FBQztRQUV4RCxNQUFNLFlBQVksR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDakMsTUFBTSxZQUFZLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRWpDLGdDQUFnQztRQUNoQywrQ0FBK0M7UUFFL0MsSUFBSSxZQUFZLEdBQWMsRUFBQyxVQUFVLEVBQUUsSUFBSSxrQkFBa0IsRUFBQyxDQUFDO1FBRW5FLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUUzQixZQUFZLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFDLEVBQUU7WUFDN0QsWUFBWSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsVUFBVSxDQUN0RCxZQUFZLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxVQUFVLEVBQUU7aUJBQzNELEdBQUcsQ0FBQyxDQUFDLElBQVMsRUFBRSxPQUFZLEVBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDO2lCQUM5QyxHQUFHLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDO2lCQUNuRCxVQUFVLEVBQUUsQ0FBQyxPQUFPLENBQUM7aUJBQ3JCLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQ2pCLENBQUMsQ0FBQyxDQUFBO1FBQ1AsQ0FBQyxDQUFDLENBQUE7UUFFRixzQ0FBc0M7UUFDdEMseURBQXlEO1FBRXpELE9BQU8sWUFBWSxDQUFDO0lBRXhCLENBQUMsQ0FBQSxrQkFBa0I7SUFFVixRQUFRLENBQUMsU0FBdUI7UUFFckMsTUFBTSxjQUFjLEdBQUMsQ0FBQyxDQUFDO1FBRXZCLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUMsRUFBRTtZQUN0QixJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFDLFVBQVUsQ0FDaEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUMsRUFBRTtnQkFDbkQsT0FBTyxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsY0FBYyxHQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUE7WUFDN0QsQ0FBQyxDQUFDLENBQ0gsQ0FBQztRQUNSLENBQUMsQ0FBQyxDQUFBO0lBQ04sQ0FBQztJQUVRLFNBQVM7UUFFZCxNQUFNLG9CQUFvQixHQUFFLElBQUksQ0FBQywrQkFBK0IsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7UUFFdkYsa0RBQWtEO1FBQ2xELE1BQU0sSUFBSSxHQUFFLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUU5QixJQUFJLENBQUMsVUFBVSxHQUFDLEVBQUUsQ0FBQztRQUVuQixJQUFJLENBQUMsVUFBVSxHQUFDLG9CQUFvQixDQUFDO1FBRXJDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRTNCLE9BQU8sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBRzVELENBQUM7Q0FDSiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE5ldXJvRXZvbHV0aW9uIH0gZnJvbSBcIi4vbmV1cm8tZXZvbHV0aW9uXCI7XHJcbmltcG9ydCB7VGVhY2hhYmxlTW9iaWxlTmV0fSBmcm9tIFwiLi4vbW9kZWxzL3RlYWNoYWJsZS1ldm9sdXRpb25cIlxyXG5pbXBvcnQgKiBhcyB0ZiBmcm9tICdAdGVuc29yZmxvdy90ZmpzJztcclxuXHJcbi8qKlxyXG4gKiBFYWNoIGluZGl2aWR1YWwgb2YgdGhlIHBvcHVsYXRpb24gd2lsbCBiZSBtYWRlIG9mIFxyXG4gKiBhbiBhcnJheSwgY29ycmVzcG9kZW50IHRvIHRoZSBuZXVyYWwgbmV0d29yayB3ZWlnaHRzIGFuZFxyXG4gKiBhbiBldmFsdWF0aW9uLCBpdHMgcmVzcGVjdGl2ZSBhY2N1cmFjeSBvbiB0aGUgZGF0YXNldCBnaXZlbi5cclxuICogXHJcbiAqL1xyXG5pbnRlcmZhY2UgSW5kaXZpZHVhbCB7XHJcbiAgICBpbmRpdmlkdWFsOiBUZWFjaGFibGVNb2JpbGVOZXQsXHJcbiAgICBhY2N1cmFjeT86IG51bWJlclxyXG59XHJcblxyXG5cclxuZXhwb3J0IGNsYXNzIEdlbmV0aWNBbGdvcml0aG0gZXh0ZW5kcyBOZXVyb0V2b2x1dGlvbiB7IFxyXG4gICAgXHJcbiAgICBcclxuXHJcbiAgICAvKipcclxuICAgICAqIEltcGxlbWVudGF0aW4gYWJzdHJhY3QgbWV0aG9kc1xyXG4gICAgICovXHJcblxyXG4gICAgb3ZlcnJpZGUgY3Jvc3NvdmVyKCk6IEluZGl2aWR1YWwge1xyXG4gICAgICAgIC8vIGNvbnNvbGUubG9nKFwiQXBwbHlpbmcgY3Jvc3NvdmVyIG9uIEdlbmV0aWMgQWxnb3JpdGhtcy4uLlwiKVxyXG5cclxuICAgICAgICBjb25zdCBzZWxlY3RlZCA9IHRoaXMuc2VsZWN0X3BhcmVudHNfYnlfcm9sbGV0X3doZWVscygpO1xyXG5cclxuICAgICAgICBjb25zdCBpbmRpdmlkdWFsXzEgPSBzZWxlY3RlZFswXTtcclxuICAgICAgICBjb25zdCBpbmRpdmlkdWFsXzIgPSBzZWxlY3RlZFsxXTtcclxuXHJcbiAgICAgICAgLy8gY29uc29sZS5sb2coXCJJbmRpdmlkdWFsIDE6IFwiKVxyXG4gICAgICAgIC8vIGluZGl2aWR1YWxfMS5pbmRpdmlkdWFsLmdldEhlYWQoKS5zdW1tYXJ5KCk7XHJcblxyXG4gICAgICAgIGxldCBpbmRpdmlkdWFsXzM6IEluZGl2aWR1YWw9IHtpbmRpdmlkdWFsOiBuZXcgVGVhY2hhYmxlTW9iaWxlTmV0fTtcclxuXHJcbiAgICAgICAgY29uc3QgYWxmYSA9IE1hdGgucmFuZG9tKCk7XHJcblxyXG4gICAgICAgIGluZGl2aWR1YWxfMy5pbmRpdmlkdWFsLmdldEhlYWQoKS5sYXllcnMuZm9yRWFjaCgobGF5ZXIsIGluZGV4KT0+e1xyXG4gICAgICAgICAgICBpbmRpdmlkdWFsXzMuaW5kaXZpZHVhbC5nZXRIZWFkKCkubGF5ZXJzW2luZGV4XS5zZXRXZWlnaHRzKFxyXG4gICAgICAgICAgICAgICAgaW5kaXZpZHVhbF8xLmluZGl2aWR1YWwuZ2V0SGVhZCgpLmxheWVyc1tpbmRleF0uZ2V0V2VpZ2h0cygpXHJcbiAgICAgICAgICAgICAgICAubWFwKChlbGVtOiBhbnksIGluZGV4XzI6IGFueSk9PiBlbGVtLm11bChhbGZhKVxyXG4gICAgICAgICAgICAgICAgLmFkZChpbmRpdmlkdWFsXzIuaW5kaXZpZHVhbC5nZXRIZWFkKCkubGF5ZXJzW2luZGV4XVxyXG4gICAgICAgICAgICAgICAgLmdldFdlaWdodHMoKVtpbmRleF8yXVxyXG4gICAgICAgICAgICAgICAgLm11bCgxIC0gYWxmYSlcclxuICAgICAgICAgICAgKSkpXHJcbiAgICAgICAgfSlcclxuXHJcbiAgICAgICAgLy8gdGhpcy5wb3B1bGF0aW9uLnB1c2goaW5kaXZpZHVhbF8zKTtcclxuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlBvcHVsYXRpb246IFwiLCB0aGlzLnBvcHVsYXRpb24ubGVuZ3RoKTsgIFxyXG4gICAgICAgIFxyXG4gICAgICAgIHJldHVybiBpbmRpdmlkdWFsXzM7ICAgICAgICBcclxuICAgIFxyXG4gICAgfS8vZW5kIG9mIGNyb3Nzb3ZlclxyXG5cclxuICAgIG92ZXJyaWRlIG11dGF0aW9uKG9mZnNwcmluZzogSW5kaXZpZHVhbFtdKTogdm9pZCB7XHJcblxyXG4gICAgICAgIGNvbnN0IG11bHRhdGlvbl9yYXRlPTE7XHJcblxyXG4gICAgICAgIG9mZnNwcmluZy5mb3JFYWNoKChlbGVtKT0+e1xyXG4gICAgICAgICAgICBlbGVtLmluZGl2aWR1YWwuZ2V0SGVhZCgpLnNldFdlaWdodHMoXHJcbiAgICAgICAgICAgICAgICBlbGVtLmluZGl2aWR1YWwuZ2V0SGVhZCgpLmdldFdlaWdodHMoKS5tYXAoKGVsZW1fMik9PiB7ICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgIHJldHVybiBlbGVtXzIuYWRkKGVsZW1fMi5tdWwobXVsdGF0aW9uX3JhdGUqTWF0aC5yYW5kb20oKSkpICAgICBcclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICAgKTtcclxuICAgICAgICB9KVxyXG4gICAgfVxyXG5cclxuICAgIG92ZXJyaWRlIHNlbGVjdGlvbigpOiB2b2lkIHtcclxuXHJcbiAgICAgICAgY29uc3Qgc2VsZWN0ZWRfaW5kaXZpZHVhbHM9IHRoaXMuc2VsZWN0X3BhcmVudHNfYnlfcm9sbGV0X3doZWVscyh0aGlzLnBvcHVsYXRpb25fc2l6ZSk7XHJcblxyXG4gICAgICAgIC8vVGhlIGJlc3Qgd2lsbCBlbnRlciBvbiB0aGUgcG9wdWxhdGlvbiBieSBlbGl0aXNtXHJcbiAgICAgICAgY29uc3QgYmVzdD0gdGhpcy5nZXRUaGVCZXN0KCk7XHJcblxyXG4gICAgICAgIHRoaXMucG9wdWxhdGlvbj1bXTtcclxuXHJcbiAgICAgICAgdGhpcy5wb3B1bGF0aW9uPXNlbGVjdGVkX2luZGl2aWR1YWxzO1xyXG4gICAgICAgIFxyXG4gICAgICAgIHRoaXMucG9wdWxhdGlvbi5wdXNoKGJlc3QpO1xyXG5cclxuICAgICAgICBjb25zb2xlLmxvZyhcIkJlc3QgYWNjdXJhY3kgKGVsaXRpc20pOiBcIiwgYmVzdC5hY2N1cmFjeSk7XHJcbiAgICAgICAgXHJcblxyXG4gICAgfVxyXG59XHJcbiJdfQ==
@@ -63,8 +63,6 @@ export class NeuroEvolution {
63
63
  await this.evaluate();
64
64
  //selection
65
65
  this.selection();
66
- console.log("Best accuracy: ", this.getTheBest().accuracy);
67
- console.log("Worst accuracy: ", this.getTheWorst().accuracy);
68
66
  }
69
67
  /**Helpers */
70
68
  getTheBest() {
@@ -194,4 +192,4 @@ export class NeuroEvolution {
194
192
  });
195
193
  }
196
194
  }
197
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV1cm8tZXZvbHV0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGZqcy1ldm9sdXRpb24vc3JjL2xpYi9DbGFzc2VzL25ldXJvLWV2b2x1dGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUMsa0JBQWtCLEVBQUMsTUFBTSwrQkFBK0IsQ0FBQTtBQUNoRSxPQUFPLEtBQUssRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBYXZDLE1BQU0sT0FBZ0IsY0FBYztJQUFwQztRQUVROzs7Ozs7O09BT0Q7UUFFSCxlQUFVLEdBQWUsRUFBRSxDQUFDO1FBQ3BCLHFCQUFnQixHQUFTLEVBQUUsQ0FBQztJQXVSeEMsQ0FBQztJQXJSRyx5QkFBeUI7SUFDekIsSUFBVyxlQUFlLENBQUMsZUFBdUI7UUFDOUMsSUFBSSxDQUFDLGdCQUFnQixHQUFDLGVBQWUsQ0FBQztJQUMxQyxDQUFDO0lBQ0QsSUFBVyxlQUFlO1FBQ3RCLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDO0lBQ2pDLENBQUM7SUFFSDs7T0FFRztJQUVGLEtBQUssQ0FBQyxRQUFRO1FBQ1osT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFDLEVBQUU7WUFDMUMsSUFBSSxDQUFDLFFBQVEsR0FBRSxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDcEQsQ0FBQyxDQUFDLENBQUE7SUFDSixDQUFDO0lBRUMsZ0JBQWdCO1FBRVosS0FBSSxJQUFJLENBQUMsR0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFDLElBQUksQ0FBQyxlQUFlLEVBQUMsQ0FBQyxFQUFFLEVBQUM7WUFDcEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBQyxVQUFVLEVBQUUsSUFBSSxrQkFBa0IsRUFBRSxFQUFDLENBQUMsQ0FBQTtTQUMvRDtJQUVMLENBQUM7SUFFRCxLQUFLLENBQUMsZUFBZSxDQUFDLFNBQWlCO1FBRW5DLEtBQUksSUFBSSxDQUFDLEdBQUMsQ0FBQyxFQUFDLENBQUMsR0FBQyxTQUFTLEVBQUMsQ0FBQyxFQUFFLEVBQUM7WUFFeEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFjLEVBQUMsQ0FBQyxDQUFDLENBQUE7WUFDN0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQzlDLE9BQU8sQ0FBQyxHQUFHLENBQUMscUJBQXFCLEVBQUUsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQzNELE9BQU8sQ0FBQyxHQUFHLENBQUMscUJBQXFCLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUMzRCxNQUFNLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztTQUMxQjtJQUVMLENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxTQUFTO1FBSVgscUJBQXFCO1FBQ3JCLE1BQU0sSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBRXRCLE1BQU0sU0FBUyxHQUFDLEVBQUUsQ0FBQztRQUVuQixxREFBcUQ7UUFDckQsS0FBSSxJQUFJLENBQUMsR0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFDLENBQUMsRUFBRSxFQUNyQztZQUNJLG9DQUFvQztZQUNwQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDO1NBQ3BDO1FBRU4sMkJBQTJCO1FBQzlCLHNIQUFzSDtRQUVuSCxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFBO1FBRXZCLGdFQUFnRTtRQUNoRSxJQUFJLENBQUMsVUFBVSxHQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsVUFBVSxFQUFFLEdBQUcsU0FBUyxDQUFDLENBQUM7UUFFbkQscUJBQXFCO1FBQ3BCLE1BQU0sSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBR3RCLFdBQVc7UUFDWCxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDbEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDMUQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUE7SUFFaEUsQ0FBQztJQVdELGFBQWE7SUFFYixVQUFVO1FBQ04sSUFBSSxVQUFVLEdBQVMsQ0FBQyxDQUFDO1FBQ3pCLElBQUksSUFBSSxHQUFDLENBQUMsQ0FBQztRQUVYLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBUyxFQUFFLEtBQWEsRUFBQyxFQUFFO1lBRWhELElBQUcsSUFBSSxDQUFDLFFBQVEsR0FBQyxJQUFJLEVBQUM7Z0JBQ2xCLElBQUksR0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO2dCQUNuQixVQUFVLEdBQUMsS0FBSyxDQUFBO2FBQ25CO1FBRUwsQ0FBQyxDQUFDLENBQUE7UUFFRixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUdELFdBQVc7UUFDUCxJQUFJLFdBQVcsR0FBUyxDQUFDLENBQUM7UUFDMUIsSUFBSSxLQUFLLEdBQUMsQ0FBQyxDQUFDO1FBRVosSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFTLEVBQUUsS0FBYSxFQUFDLEVBQUU7WUFFaEQsSUFBRyxJQUFJLENBQUMsUUFBUSxHQUFDLEtBQUssRUFBQztnQkFDbkIsS0FBSyxHQUFDLElBQUksQ0FBQyxRQUFRLENBQUM7Z0JBQ3BCLFdBQVcsR0FBQyxLQUFLLENBQUE7YUFDcEI7UUFFTCxDQUFDLENBQUMsQ0FBQTtRQUVGLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUN4QyxDQUFDO0lBRUc7O0dBRUQ7SUFDSCxrQ0FBa0MsQ0FBQyxnQkFBZ0IsR0FBQyxDQUFDO1FBRTdDLHdEQUF3RDtRQUV4RCxNQUFNLEtBQUssR0FBTSxFQUFFLENBQUM7UUFFcEIsSUFBSSxLQUFLLEdBQU0sQ0FBQyxDQUFDO1FBRWpCLCtEQUErRDtRQUUvRCxzQ0FBc0M7UUFDdEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUMsRUFBRSxDQUFBLEtBQUssSUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFdEQsSUFBSSxPQUFPLEdBQUMsQ0FBQyxDQUFDO1FBRWQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFRLEVBQUUsS0FBSyxFQUFDLEVBQUU7WUFFdkMsNkNBQTZDO1lBRTdDLEtBQUssQ0FBQyxJQUFJLENBQ047Z0JBQ0UsS0FBSyxFQUFFLEtBQUs7Z0JBQ1osS0FBSyxFQUFHLElBQUksQ0FBQyxRQUFRLEdBQUMsS0FBSztnQkFDM0IsR0FBRyxFQUFFLE9BQU87Z0JBQ1osR0FBRyxFQUFFLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQyxRQUFRLEdBQUMsS0FBSyxDQUFDO2FBQ3ZDLENBQUMsQ0FBQTtZQUVGLE9BQU8sSUFBRSxJQUFJLENBQUMsUUFBUSxHQUFDLEtBQUssQ0FBQztRQUNuQyxDQUFDLENBQUMsQ0FBQztRQUVILGtDQUFrQztRQUVsQyxNQUFNLGFBQWEsR0FBTyxFQUFFLENBQUM7UUFFM0IsaURBQWlEO1FBQ25ELElBQUksT0FBTyxHQUFDLENBQUMsQ0FBQztRQUVkLE1BQU0sV0FBVyxHQUFXLEVBQUUsQ0FBQztRQUUvQixPQUFNLE9BQU8sR0FBQyxnQkFBZ0IsRUFBQztZQUUzQix1REFBdUQ7WUFDdkQsTUFBTSxTQUFTLEdBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBRS9CLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFTLEVBQUMsRUFBRTtnQkFFdkIsSUFBRyxDQUFDLElBQUksQ0FBQyxHQUFHLEdBQUMsU0FBUyxDQUFDLElBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFDLFNBQVMsQ0FBQyxFQUFDO29CQUUxQyxNQUFNLEdBQUcsR0FBZSxFQUFDLFVBQVUsRUFBRSxJQUFJLGtCQUFrQixFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFBO29CQUUvRyxvSEFBb0g7b0JBRXBILCtIQUErSDtvQkFDL0gsNkVBQTZFO29CQUM3RSw0RkFBNEY7b0JBRTVGLDhEQUE4RDtvQkFFOUQsNkhBQTZIO29CQUc3SCxPQUFPLEVBQUUsQ0FBQztvQkFDVixhQUFhLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7b0JBRWhELCtCQUErQjtpQkFDbEM7WUFDTCxDQUFDLENBQUMsQ0FBQTtTQUNMO1FBRUQsMkNBQTJDO1FBQzNDLHdDQUF3QztRQUN4QyxxQ0FBcUM7UUFDckMsK0NBQStDO1FBQy9DLFFBQVE7UUFFUixLQUFLO1FBRUwsc0JBQXNCO1FBRXRCLE9BQU8sYUFBYSxDQUFDO0lBQ3pCLENBQUM7SUFFTDs7T0FFRztJQUNILCtCQUErQixDQUFDLGdCQUFnQixHQUFDLENBQUM7UUFFOUMsY0FBYztRQUNkLDZDQUE2QztRQUU3QyxNQUFNLEtBQUssR0FBTSxFQUFFLENBQUM7UUFFcEIsSUFBSSxLQUFLLEdBQU0sQ0FBQyxDQUFDO1FBRWpCLCtEQUErRDtRQUUvRCxzQ0FBc0M7UUFDdEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUMsRUFBRSxDQUFBLEtBQUssSUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFdEQsSUFBSSxPQUFPLEdBQUMsQ0FBQyxDQUFDO1FBRWQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFRLEVBQUUsS0FBSyxFQUFDLEVBQUU7WUFFdkMsNkNBQTZDO1lBRTdDLEtBQUssQ0FBQyxJQUFJLENBQ047Z0JBQ0UsS0FBSyxFQUFFLEtBQUs7Z0JBQ1osS0FBSyxFQUFHLElBQUksQ0FBQyxRQUFRLEdBQUMsS0FBSztnQkFDM0IsR0FBRyxFQUFFLE9BQU87Z0JBQ1osR0FBRyxFQUFFLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQyxRQUFRLEdBQUMsS0FBSyxDQUFDO2FBQ3ZDLENBQUMsQ0FBQTtZQUVGLE9BQU8sSUFBRSxJQUFJLENBQUMsUUFBUSxHQUFDLEtBQUssQ0FBQztRQUNuQyxDQUFDLENBQUMsQ0FBQztRQUVILGtDQUFrQztRQUVsQyxNQUFNLGFBQWEsR0FBTyxFQUFFLENBQUM7UUFFM0IsaURBQWlEO1FBQ25ELElBQUksT0FBTyxHQUFDLENBQUMsQ0FBQztRQUNkLE9BQU0sT0FBTyxHQUFDLGdCQUFnQixFQUFDO1lBRTNCLHVEQUF1RDtZQUN2RCxNQUFNLFNBQVMsR0FBRSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFFL0IsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQVMsRUFBQyxFQUFFO2dCQUV2QixJQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsR0FBQyxTQUFTLENBQUMsSUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLEdBQUMsU0FBUyxDQUFDLEVBQUM7b0JBQzFDLE9BQU8sRUFBRSxDQUFDO29CQUNWLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztpQkFDbkQ7WUFDTCxDQUFDLENBQUMsQ0FBQTtTQUNMO1FBQ0QsT0FBTyxhQUFhLENBQUM7SUFDekIsQ0FBQztJQUVMOzs7Ozs7O09BT0c7SUFDSCxLQUFLLENBQUMsU0FBUyxDQUFFLGFBQTZCLEVBQUUsU0FBeUI7UUFFckUsYUFBYSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFVLEVBQUUsS0FBVSxFQUFDLEVBQUU7WUFDbkQsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUE7UUFDMUQsQ0FBQyxDQUFDLENBQUE7SUFDTixDQUFDO0NBRUEiLCJzb3VyY2VzQ29udGVudCI6WyJcclxuaW1wb3J0IHtUZWFjaGFibGVNb2JpbGVOZXR9IGZyb20gXCIuLi9tb2RlbHMvdGVhY2hhYmxlLWV2b2x1dGlvblwiXHJcbmltcG9ydCAqIGFzIHRmIGZyb20gJ0B0ZW5zb3JmbG93L3RmanMnO1xyXG5cclxuLyoqXHJcbiAqIEVhY2ggaW5kaXZpZHVhbCBvZiB0aGUgcG9wdWxhdGlvbiB3aWxsIGJlIG1hZGUgb2YgXHJcbiAqIGFuIGFycmF5LCBjb3JyZXNwb2RlbnQgdG8gdGhlIG5ldXJhbCBuZXR3b3JrIHdlaWdodHMgYW5kXHJcbiAqIGFuIGV2YWx1YXRpb24sIGl0cyByZXNwZWN0aXZlIGFjY3VyYWN5IG9uIHRoZSBkYXRhc2V0IGdpdmVuLlxyXG4gKiBcclxuICovXHJcbmludGVyZmFjZSBJbmRpdmlkdWFsIHtcclxuICAgIGluZGl2aWR1YWw6IFRlYWNoYWJsZU1vYmlsZU5ldCxcclxuICAgIGFjY3VyYWN5PzogbnVtYmVyXHJcbn1cclxuXHJcbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBOZXVyb0V2b2x1dGlvbiB7XHJcblxyXG4gICAgICAgIC8qKiAgICAgXHJcbiAgICBUaGlzIGlzIHRoZSBwb3B1bGF0aW9uLiBJIGhhdmUgZGVjaWRlZCB0byBjcmVhdGUgYSBwb3B1bGF0aW9uIG9mIGp1c3Qgd2VpZ2h0cy5cclxuICAgIEkgaGFkIHRvIGNoYW5nZSBteSBtaW5kLiBXb3JraW5nIHdpdGggd2VpZ2h0cyBpcyB0cmlja3kuIFxyXG4gICAgSSBoYXZlIGRlY2lkZWQgdG8gc2FjcmlmaWNlIG1lbW9yeSB0byBtYWtlIG15IGxpZmUgZWFzaXNlci5cclxuICAgIFRlbnNvcnMgaGFzIHRoZWlyIGlubmVyIG1ldGhvZHMsIGl0IGhlbHBzIG9uIHRoZSBvcGVyYXRvcnMuXHJcbiAgICBJIGhhdmUgdG8gcGF5IGF0dGVudGlvbiB0byBtZW1vcnkgbWFuZWdlbWVudC5cclxuICAgIFdvcmtpbmcgd2l0aCBtZW1vcnkgaW4gdGVuc29ycyBpcyB0cmlja3kuICAgICBcclxuICAgICAqL1xyXG5cclxuICAgIHBvcHVsYXRpb246IEluZGl2aWR1YWxbXT1bXTtcclxuICAgIHByaXZhdGUgX3BvcHVsYXRpb25fc2l6ZTogbnVtYmVyPTMwO1xyXG4gICAgXHJcbiAgICAvKipTZXR0ZXJzIGFuZCBHZXR0ZXJzICovXHJcbiAgICBwdWJsaWMgc2V0IHBvcHVsYXRpb25fc2l6ZShwb3B1bGF0aW9uX3NpemU6IG51bWJlcil7XHJcbiAgICAgICAgdGhpcy5fcG9wdWxhdGlvbl9zaXplPXBvcHVsYXRpb25fc2l6ZTtcclxuICAgIH1cclxuICAgIHB1YmxpYyBnZXQgcG9wdWxhdGlvbl9zaXplKCl7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3BvcHVsYXRpb25fc2l6ZTtcclxuICAgIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTWV0aG9kcyB3aXRoIGltcGxlbWVudGF0aW9uXHJcbiAgICovXHJcblxyXG4gICBhc3luYyBldmFsdWF0ZSgpe1xyXG4gICAgIHJldHVybiB0aGlzLnBvcHVsYXRpb24uZm9yRWFjaChhc3luYyAoZWxlbSk9PntcclxuICAgICAgICBlbGVtLmFjY3VyYWN5PSBhd2FpdCBlbGVtLmluZGl2aWR1YWwuZXZhbHVhdGUoKTsgICAgICAgIFxyXG4gICAgfSlcclxuICB9XHJcblxyXG4gICAgc3RhcnRfcG9wdWxhdGlvbigpe1xyXG5cclxuICAgICAgICBmb3IobGV0IGk9MDsgaTx0aGlzLnBvcHVsYXRpb25fc2l6ZTtpKyspeyAgICAgICAgICAgIFxyXG4gICAgICAgICAgICB0aGlzLnBvcHVsYXRpb24ucHVzaCh7aW5kaXZpZHVhbDogbmV3IFRlYWNoYWJsZU1vYmlsZU5ldCgpfSlcclxuICAgICAgICB9XHJcblxyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIGFwcGx5X2V2b2x1dGlvbihpdGVyYXRpb246IG51bWJlcil7XHJcblxyXG4gICAgICAgIGZvcihsZXQgaT0wO2k8aXRlcmF0aW9uO2krKyl7XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIkludGVyYXRpb246IFwiLGkpXHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiTWVtb3J5OiBcIiwgdGYubWVtb3J5KCkubnVtQnl0ZXMpO1xyXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIlRlbnNvcnMgaW4gbWVtb3J5OiBcIiwgdGYubWVtb3J5KCkubnVtVGVuc29ycyk7XHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiUG9wdWxhdGlvbiBsZW5ndGg6IFwiLCB0aGlzLnBvcHVsYXRpb24ubGVuZ3RoKTtcclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5ldm9sdXRpb24oKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgfVxyXG4gXHJcbiAgICAvKipcclxuICAgICAqIFRoaXMgbWV0aG9kIHdpbGwgYXBwbHkgdGhlIGV2b2x1dGlvblxyXG4gICAgICovXHJcbiAgICBhc3luYyBldm9sdXRpb24oKXtcclxuXHJcbiAgICAgICAgXHJcbiAgICAgICAgXHJcbiAgICAgICAgLy9VcGRhdGUgdGhlIGFjY3VyYWN5XHJcbiAgICAgICAgYXdhaXQgdGhpcy5ldmFsdWF0ZSgpO1xyXG5cclxuICAgICAgICBjb25zdCBvZmZzcHJpbmc9W107XHJcblxyXG4gICAgICAgIC8qKkZpcnN0IHN0ZXAgaXMgY3Jvc3NvdmVyLCBmb3IgY3JlYXRpbmcgb2Zmc3ByaW5nICovXHJcbiAgICAgICAgZm9yKGxldCBpPTA7IGk8dGhpcy5wb3B1bGF0aW9uLmxlbmd0aDtpKyspXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIC8vVGhlIHBvcHVsYXRpb24gd2lsbCBkb3VibGUgaW4gc2l6ZVxyXG4gICAgICAgICAgICAgICAgb2Zmc3ByaW5nLnB1c2godGhpcy5jcm9zc292ZXIoKSk7IFxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgLy9NdXRhdGlvbiBvbiB0aGUgb2Zmc3ByaW5nXHJcbiAgICAvLyAgICBjb25zb2xlLmxvZyhcIldlaWdodCBiZWZvcmUgbXV0YXRpb246IFwiLCBvZmZzcHJpbmdbMF0uaW5kaXZpZHVhbC5nZXRIZWFkKCkubGF5ZXJzWzBdLmdldFdlaWdodHMoKVswXS5kYXRhU3luYygpKTtcclxuXHJcbiAgICAgICB0aGlzLm11dGF0aW9uKG9mZnNwcmluZykgICBcclxuXHJcbiAgICAgICAgLy9Kb2luaW5nIHBhcmVudHMgYW5kIG9mZnNwcmluZyBpbnRvIHRoZSBzYW1lIHBvb2wgZm9yIHNlbGVjdGlvblxyXG4gICAgICAgIHRoaXMucG9wdWxhdGlvbj1bLi4udGhpcy5wb3B1bGF0aW9uLCAuLi5vZmZzcHJpbmddO1xyXG5cclxuICAgICAgICAvL1VwZGF0ZSB0aGUgYWNjdXJhY3lcclxuICAgICAgICAgYXdhaXQgdGhpcy5ldmFsdWF0ZSgpO1xyXG5cclxuXHJcbiAgICAgICAgIC8vc2VsZWN0aW9uXHJcbiAgICAgICAgIHRoaXMuc2VsZWN0aW9uKCk7XHJcbiAgICAgICAgY29uc29sZS5sb2coXCJCZXN0IGFjY3VyYWN5OiBcIiwgdGhpcy5nZXRUaGVCZXN0KCkuYWNjdXJhY3kpXHJcbiAgICAgICAgY29uc29sZS5sb2coXCJXb3JzdCBhY2N1cmFjeTogXCIsIHRoaXMuZ2V0VGhlV29yc3QoKS5hY2N1cmFjeSkgICAgICAgIFxyXG5cclxuICAgIH1cclxuXHJcbiAgICAvKipBYnN0cmFjdCBtZXRob2RzLlxyXG4gICAgICogU2hvdWxkIGJlIGltcGxlbWVudGVkIGJ5IGVhY2ggdmFyaWF0aW9uIG9mIGV2b2x1dGlvbmFyeSBhbGdvcml0aG1zXHJcbiAgICAgKi9cclxuXHJcbiAgICBhYnN0cmFjdCBjcm9zc292ZXIoKTogSW5kaXZpZHVhbDtcclxuICAgIGFic3RyYWN0IG11dGF0aW9uKG9mZnNwcmluZzogSW5kaXZpZHVhbFtdKTogdm9pZDtcclxuICAgIGFic3RyYWN0IHNlbGVjdGlvbigpOiB2b2lkO1xyXG5cclxuXHJcbiAgICAvKipIZWxwZXJzICovXHJcblxyXG4gICAgZ2V0VGhlQmVzdCgpOiBJbmRpdmlkdWFse1xyXG4gICAgICAgIGxldCBpbmRleF9iZXN0OiBudW1iZXI9MDtcclxuICAgICAgICBsZXQgYmVzdD0wO1xyXG5cclxuICAgICAgICB0aGlzLnBvcHVsYXRpb24uZm9yRWFjaCgoZWxlbTogYW55LCBpbmRleDogbnVtYmVyKT0+e1xyXG5cclxuICAgICAgICAgICAgaWYoZWxlbS5hY2N1cmFjeT5iZXN0KXtcclxuICAgICAgICAgICAgICAgIGJlc3Q9ZWxlbS5hY2N1cmFjeTtcclxuICAgICAgICAgICAgICAgIGluZGV4X2Jlc3Q9aW5kZXhcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgfSlcclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXMucG9wdWxhdGlvbltpbmRleF9iZXN0XTtcclxuICAgIH1cclxuXHJcblxyXG4gICAgZ2V0VGhlV29yc3QoKTogSW5kaXZpZHVhbHtcclxuICAgICAgICBsZXQgaW5kZXhfd29yc3Q6IG51bWJlcj0wO1xyXG4gICAgICAgIGxldCB3b3JzdD0xO1xyXG5cclxuICAgICAgICB0aGlzLnBvcHVsYXRpb24uZm9yRWFjaCgoZWxlbTogYW55LCBpbmRleDogbnVtYmVyKT0+e1xyXG5cclxuICAgICAgICAgICAgaWYoZWxlbS5hY2N1cmFjeTx3b3JzdCl7XHJcbiAgICAgICAgICAgICAgICB3b3JzdD1lbGVtLmFjY3VyYWN5O1xyXG4gICAgICAgICAgICAgICAgaW5kZXhfd29yc3Q9aW5kZXhcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgfSlcclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXMucG9wdWxhdGlvbltpbmRleF93b3JzdF07XHJcbiAgICB9XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICogU2VsZWN0aW5nIGluZGl2aWR1YWxzIGJ5IGVsaXRpc21cclxuICAgICAqL1xyXG4gICAgc2VsZWN0X3BhcmVudHNfYnlfcm9sbGV0X3doZWVsc192MihzZWxlY3Rpb25fbnVtYmVyPTIpOiBJbmRpdmlkdWFsW117XHJcblxyXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlNlbGVjdGluZyBwYXJlbnRzIGJ5IHJvbGxldCB3aGVlbHMuLi5cIik7XHJcbiAgICBcclxuICAgICAgICAgICAgY29uc3Qgc2hhcmU6IGFueT1bXTtcclxuICAgIFxyXG4gICAgICAgICAgICBsZXQgdG90YWw6IGFueT0wO1xyXG4gICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlBvcHVsYXRpb24gbGVuZ3RoLi4uXCIsIHRoaXMucG9wdWxhdGlvbi5sZW5ndGgpO1xyXG4gICAgXHJcbiAgICAgICAgICAgIC8vVGhpcyB3aWxsIGNyZWF0ZSBhbiBvdmVyYWxsIGFjY3VyYWN5XHJcbiAgICAgICAgICAgIHRoaXMucG9wdWxhdGlvbi5mb3JFYWNoKChlbGVtKT0+dG90YWwrPWVsZW0uYWNjdXJhY3kpO1xyXG4gICAgXHJcbiAgICAgICAgICAgIGxldCBwb2ludGVyPTA7XHJcbiAgICBcclxuICAgICAgICAgICAgdGhpcy5wb3B1bGF0aW9uLmZvckVhY2goKGVsZW06YW55LCBpbmRleCk9PntcclxuICAgIFxyXG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJBY2N1cmFjeS4uLlwiLCBlbGVtLmFjY3VyYWN5KTtcclxuICAgIFxyXG4gICAgICAgICAgICAgICAgc2hhcmUucHVzaChcclxuICAgICAgICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICAgICAgICBpbmRleDogaW5kZXgsXHJcbiAgICAgICAgICAgICAgICAgICAgICBzaGFyZTogIGVsZW0uYWNjdXJhY3kvdG90YWwsXHJcbiAgICAgICAgICAgICAgICAgICAgICBtaW46IHBvaW50ZXIsXHJcbiAgICAgICAgICAgICAgICAgICAgICBtYXg6IHBvaW50ZXIgKyAoZWxlbS5hY2N1cmFjeS90b3RhbClcclxuICAgICAgICAgICAgICAgICAgfSlcclxuICAgIFxyXG4gICAgICAgICAgICAgICAgICBwb2ludGVyKz1lbGVtLmFjY3VyYWN5L3RvdGFsO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgIFxyXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlNoYXJlczogXCIsIHNoYXJlKTtcclxuICAgIFxyXG4gICAgICAgICAgICBjb25zdCBhdXhfc2VsZWN0aW9uOiBhbnkgPVtdO1xyXG4gICAgXHJcbiAgICAgICAgICAgICAgLy9TZWxlY3RpbmcgdHdvIGluZGl2aWR1YWxzIHVzaW5nIHJvdWxldHRlIHdoZWVsc1xyXG4gICAgICAgICAgICBsZXQgY291bnRlcj0wO1xyXG5cclxuICAgICAgICAgICAgY29uc3QgaW5kZXhlc19hdXg6IG51bWJlcltdPVtdO1xyXG5cclxuICAgICAgICAgICAgd2hpbGUoY291bnRlcjxzZWxlY3Rpb25fbnVtYmVyKXtcclxuICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgLy9SYW5kb20gcG9pbnRlciwgdXNlZCB0byByYW5kb21seSBzZWxlY3QgYW4gaW5kaXZpZHVhbFxyXG4gICAgICAgICAgICAgICAgY29uc3QgYXV4X2luZGV4PSBNYXRoLnJhbmRvbSgpO1xyXG4gICAgXHJcbiAgICAgICAgICAgICAgICBzaGFyZS5mb3JFYWNoKChlbGVtOiBhbnkpPT57XHJcbiAgICBcclxuICAgICAgICAgICAgICAgICAgICBpZigoZWxlbS5taW48YXV4X2luZGV4KSYmKGVsZW0ubWF4PmF1eF9pbmRleCkpe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYXV4OiBJbmRpdmlkdWFsID0ge2luZGl2aWR1YWw6IG5ldyBUZWFjaGFibGVNb2JpbGVOZXQoKSwgYWNjdXJhY3k6IHRoaXMucG9wdWxhdGlvbltlbGVtLmluZGV4XS5hY2N1cmFjeSB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkluZGl2aWR1YWwganVzdCBjcmVhdGVkICh3ZWlndGgpOiBcIiwgYXV4LmluZGl2aWR1YWwuZ2V0SGVhZCgpLmxheWVyc1swXS5nZXRXZWlnaHRzKClbMF0uZGF0YVN5bmMoKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkluZGl2aWR1YWwgb3JpZ2luYWw6IFwiLCB0aGlzLnBvcHVsYXRpb25bZWxlbS5pbmRleF0uaW5kaXZpZHVhbC5nZXRIZWFkKCkubGF5ZXJzWzBdLmdldFdlaWdodHMoKVswXS5kYXRhU3luYygpKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgICAgICAgICAgICAvLyBPcmlnaW5hbCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSZWNpcGllbnRcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhpcy5jb3B5TW9kZWwodGhpcy5wb3B1bGF0aW9uW2VsZW0uaW5kZXhdLmluZGl2aWR1YWwuZ2V0SGVhZCgpLGF1eC5pbmRpdmlkdWFsLmdldEhlYWQoKSlcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoaXMucG9wdWxhdGlvbltlbGVtLmluZGV4XS5pbmRpdmlkdWFsLmdldEhlYWQoKS5kaXNwb3NlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkluZGl2aWR1YWwganVzdCBjcmVhdGVkICh3ZWlndGh0LCBjb3BpZWQpOiBcIiwgYXV4LmluZGl2aWR1YWwuZ2V0SGVhZCgpLmxheWVyc1swXS5nZXRXZWlnaHRzKClbMF0uZGF0YVN5bmMoKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyKys7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGF1eF9zZWxlY3Rpb24ucHVzaCh0aGlzLnBvcHVsYXRpb25bZWxlbS5pbmRleF0pO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5kZXhlc19hdXgucHVzaChlbGVtLmluZGV4KVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIHRoaXMucG9wdWxhdGlvbi5mb3JFYWNoKChlbGVtLCBpbmRleCk9PntcclxuICAgICAgICAgICAgLy8gICAgIGlmKCFpbmRleGVzX2F1eC5pbmNsdWRlcyhpbmRleCkpe1xyXG4gICAgICAgICAgICAvLyAgICAgICAgIGNvbnNvbGUubG9nKFwiRGlzcG9zZWQuLi5cIilcclxuICAgICAgICAgICAgLy8gICAgICAgICBlbGVtLmluZGl2aWR1YWwuZ2V0SGVhZCgpLmRpc3Bvc2UoKTtcclxuICAgICAgICAgICAgLy8gICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgLy8gfSlcclxuXHJcbiAgICAgICAgICAgIC8vIHRoaXMucG9wdWxhdGlvbj1bXTtcclxuXHJcbiAgICAgICAgICAgIHJldHVybiBhdXhfc2VsZWN0aW9uO1xyXG4gICAgICAgIH1cclxuICAgIFxyXG4gICAgLyoqXHJcbiAgICAgKiBTZWxlY3RpbmcgaW5kaXZpZHVhbHMgYnkgZWxpdGlzbVxyXG4gICAgICovXHJcbiAgICBzZWxlY3RfcGFyZW50c19ieV9yb2xsZXRfd2hlZWxzKHNlbGVjdGlvbl9udW1iZXI9Mik6IEluZGl2aWR1YWxbXXtcclxuXHJcbiAgICAgICAgLy8gY29uc29sZS5sb2dcclxuICAgICAgICAvLyAoXCJTZWxlY3RpbmcgcGFyZW50cyBieSByb2xsZXQgd2hlZWxzLi4uXCIpO1xyXG5cclxuICAgICAgICBjb25zdCBzaGFyZTogYW55PVtdO1xyXG5cclxuICAgICAgICBsZXQgdG90YWw6IGFueT0wO1xyXG4gICAgICAgICAgXHJcbiAgICAgICAgLy8gY29uc29sZS5sb2coXCJQb3B1bGF0aW9uIGxlbmd0aC4uLlwiLCB0aGlzLnBvcHVsYXRpb24ubGVuZ3RoKTtcclxuXHJcbiAgICAgICAgLy9UaGlzIHdpbGwgY3JlYXRlIGFuIG92ZXJhbGwgYWNjdXJhY3lcclxuICAgICAgICB0aGlzLnBvcHVsYXRpb24uZm9yRWFjaCgoZWxlbSk9PnRvdGFsKz1lbGVtLmFjY3VyYWN5KTtcclxuXHJcbiAgICAgICAgbGV0IHBvaW50ZXI9MDtcclxuXHJcbiAgICAgICAgdGhpcy5wb3B1bGF0aW9uLmZvckVhY2goKGVsZW06YW55LCBpbmRleCk9PntcclxuXHJcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwiQWNjdXJhY3kuLi5cIiwgZWxlbS5hY2N1cmFjeSk7XHJcblxyXG4gICAgICAgICAgICBzaGFyZS5wdXNoKFxyXG4gICAgICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgICBpbmRleDogaW5kZXgsXHJcbiAgICAgICAgICAgICAgICAgIHNoYXJlOiAgZWxlbS5hY2N1cmFjeS90b3RhbCxcclxuICAgICAgICAgICAgICAgICAgbWluOiBwb2ludGVyLFxyXG4gICAgICAgICAgICAgICAgICBtYXg6IHBvaW50ZXIgKyAoZWxlbS5hY2N1cmFjeS90b3RhbClcclxuICAgICAgICAgICAgICB9KVxyXG5cclxuICAgICAgICAgICAgICBwb2ludGVyKz1lbGVtLmFjY3VyYWN5L3RvdGFsO1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlNoYXJlczogXCIsIHNoYXJlKTtcclxuXHJcbiAgICAgICAgY29uc3QgYXV4X3NlbGVjdGlvbjogYW55ID1bXTtcclxuXHJcbiAgICAgICAgICAvL1NlbGVjdGluZyB0d28gaW5kaXZpZHVhbHMgdXNpbmcgcm91bGV0dGUgd2hlZWxzXHJcbiAgICAgICAgbGV0IGNvdW50ZXI9MDtcclxuICAgICAgICB3aGlsZShjb3VudGVyPHNlbGVjdGlvbl9udW1iZXIpe1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgLy9SYW5kb20gcG9pbnRlciwgdXNlZCB0byByYW5kb21seSBzZWxlY3QgYW4gaW5kaXZpZHVhbFxyXG4gICAgICAgICAgICBjb25zdCBhdXhfaW5kZXg9IE1hdGgucmFuZG9tKCk7XHJcblxyXG4gICAgICAgICAgICBzaGFyZS5mb3JFYWNoKChlbGVtOiBhbnkpPT57XHJcblxyXG4gICAgICAgICAgICAgICAgaWYoKGVsZW0ubWluPGF1eF9pbmRleCkmJihlbGVtLm1heD5hdXhfaW5kZXgpKXtcclxuICAgICAgICAgICAgICAgICAgICBjb3VudGVyKys7XHJcbiAgICAgICAgICAgICAgICAgICAgYXV4X3NlbGVjdGlvbi5wdXNoKHRoaXMucG9wdWxhdGlvbltlbGVtLmluZGV4XSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBhdXhfc2VsZWN0aW9uO1xyXG4gICAgfVxyXG5cclxuLyoqXHJcbiAqIFRoaXMgZnVuY3Rpb24gd2lsbCBtYWtlIGEgY29weSBvZiBhIG1vZGVsIG9uIHRoZSB3ZWlnaHQgbGV2ZWxcclxuICogVGhpcyBpcyBhbiBhdHRlbXB0IHRvIGF2b2lkIGluZmx1ZW5jaW5nIHRoZSBuZXcgbW9kZWwgd2hlbiB0aGUgb2xkIG9uZVxyXG4gKiBpcyBlbGltaW5hdGVkLiBcclxuICogXHJcbiAqIEBwYXJhbSBvcmlnaW5hbE1vZGVsIC0gdGhlIG1vZGVsIHRvIGJlIGNvcGllZCBcclxuICogQHBhcmFtIHJlY2lwaWVudCAtIHRoZSBuZXcgbW9kZWxcclxuICovXHJcbmFzeW5jIGNvcHlNb2RlbCAob3JpZ2luYWxNb2RlbDogdGYuTGF5ZXJzTW9kZWwsIHJlY2lwaWVudDogdGYuTGF5ZXJzTW9kZWwpICB7XHJcblxyXG4gICAgb3JpZ2luYWxNb2RlbC5sYXllcnMuZm9yRWFjaCgobGF5ZXI6IGFueSwgaW5kZXg6IGFueSk9PntcclxuICAgICAgICByZWNpcGllbnQubGF5ZXJzW2luZGV4XS5zZXRXZWlnaHRzKGxheWVyLmdldFdlaWdodHMoKSlcclxuICAgIH0pXHJcbn0gICAgXHJcblxyXG59XHJcbiJdfQ==
195
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV1cm8tZXZvbHV0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGZqcy1ldm9sdXRpb24vc3JjL2xpYi9DbGFzc2VzL25ldXJvLWV2b2x1dGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUMsa0JBQWtCLEVBQUMsTUFBTSwrQkFBK0IsQ0FBQTtBQUNoRSxPQUFPLEtBQUssRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBYXZDLE1BQU0sT0FBZ0IsY0FBYztJQUFwQztRQUVROzs7Ozs7O09BT0Q7UUFFSCxlQUFVLEdBQWUsRUFBRSxDQUFDO1FBQ3BCLHFCQUFnQixHQUFTLEVBQUUsQ0FBQztJQXNSeEMsQ0FBQztJQXBSRyx5QkFBeUI7SUFDekIsSUFBVyxlQUFlLENBQUMsZUFBdUI7UUFDOUMsSUFBSSxDQUFDLGdCQUFnQixHQUFDLGVBQWUsQ0FBQztJQUMxQyxDQUFDO0lBQ0QsSUFBVyxlQUFlO1FBQ3RCLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDO0lBQ2pDLENBQUM7SUFFSDs7T0FFRztJQUVGLEtBQUssQ0FBQyxRQUFRO1FBQ1osT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFDLEVBQUU7WUFDMUMsSUFBSSxDQUFDLFFBQVEsR0FBRSxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDcEQsQ0FBQyxDQUFDLENBQUE7SUFDSixDQUFDO0lBRUMsZ0JBQWdCO1FBRVosS0FBSSxJQUFJLENBQUMsR0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFDLElBQUksQ0FBQyxlQUFlLEVBQUMsQ0FBQyxFQUFFLEVBQUM7WUFDcEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBQyxVQUFVLEVBQUUsSUFBSSxrQkFBa0IsRUFBRSxFQUFDLENBQUMsQ0FBQTtTQUMvRDtJQUVMLENBQUM7SUFFRCxLQUFL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LE9BQU8sSUFBRSxJQUFJLENBQUMsUUFBUSxHQUFDLEtBQUssQ0FBQztRQUNuQyxDQUFDLENBQUMsQ0FBQztRQUVILGtDQUFrQztRQUVsQyxNQUFNLGFBQWEsR0FBTyxFQUFFLENBQUM7UUFFM0IsaURBQWlEO1FBQ25ELElBQUksT0FBTyxHQUFDLENBQUMsQ0FBQztRQUNkLE9BQU0sT0FBTyxHQUFDLGdCQUFnQixFQUFDO1lBRTNCLHVEQUF1RDtZQUN2RCxNQUFNLFNBQVMsR0FBRSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFFL0IsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQVMsRUFBQyxFQUFFO2dCQUV2QixJQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsR0FBQyxTQUFTLENBQUMsSUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLEdBQUMsU0FBUyxDQUFDLEVBQUM7b0JBQzFDLE9BQU8sRUFBRSxDQUFDO29CQUNWLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztpQkFDbkQ7WUFDTCxDQUFDLENBQUMsQ0FBQTtTQUNMO1FBQ0QsT0FBTyxhQUFhLENBQUM7SUFDekIsQ0FBQztJQUVMOzs7Ozs7O09BT0c7SUFDSCxLQUFLLENBQUMsU0FBUyxDQUFFLGFBQTZCLEVBQUUsU0FBeUI7UUFFckUsYUFBYSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFVLEVBQUUsS0FBVSxFQUFDLEVBQUU7WUFDbkQsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUE7UUFDMUQsQ0FBQyxDQUFDLENBQUE7SUFDTixDQUFDO0NBRUEiLCJzb3VyY2VzQ29udGVudCI6WyJcclxuaW1wb3J0IHtUZWFjaGFibGVNb2JpbGVOZXR9IGZyb20gXCIuLi9tb2RlbHMvdGVhY2hhYmxlLWV2b2x1dGlvblwiXHJcbmltcG9ydCAqIGFzIHRmIGZyb20gJ0B0ZW5zb3JmbG93L3RmanMnO1xyXG5cclxuLyoqXHJcbiAqIEVhY2ggaW5kaXZpZHVhbCBvZiB0aGUgcG9wdWxhdGlvbiB3aWxsIGJlIG1hZGUgb2YgXHJcbiAqIGFuIGFycmF5LCBjb3JyZXNwb2RlbnQgdG8gdGhlIG5ldXJhbCBuZXR3b3JrIHdlaWdodHMgYW5kXHJcbiAqIGFuIGV2YWx1YXRpb24sIGl0cyByZXNwZWN0aXZlIGFjY3VyYWN5IG9uIHRoZSBkYXRhc2V0IGdpdmVuLlxyXG4gKiBcclxuICovXHJcbmludGVyZmFjZSBJbmRpdmlkdWFsIHtcclxuICAgIGluZGl2aWR1YWw6IFRlYWNoYWJsZU1vYmlsZU5ldCxcclxuICAgIGFjY3VyYWN5PzogbnVtYmVyXHJcbn1cclxuXHJcbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBOZXVyb0V2b2x1dGlvbiB7XHJcblxyXG4gICAgICAgIC8qKiAgICAgXHJcbiAgICBUaGlzIGlzIHRoZSBwb3B1bGF0aW9uLiBJIGhhdmUgZGVjaWRlZCB0byBjcmVhdGUgYSBwb3B1bGF0aW9uIG9mIGp1c3Qgd2VpZ2h0cy5cclxuICAgIEkgaGFkIHRvIGNoYW5nZSBteSBtaW5kLiBXb3JraW5nIHdpdGggd2VpZ2h0cyBpcyB0cmlja3kuIFxyXG4gICAgSSBoYXZlIGRlY2lkZWQgdG8gc2FjcmlmaWNlIG1lbW9yeSB0byBtYWtlIG15IGxpZmUgZWFzaXNlci5cclxuICAgIFRlbnNvcnMgaGFzIHRoZWlyIGlubmVyIG1ldGhvZHMsIGl0IGhlbHBzIG9uIHRoZSBvcGVyYXRvcnMuXHJcbiAgICBJIGhhdmUgdG8gcGF5IGF0dGVudGlvbiB0byBtZW1vcnkgbWFuZWdlbWVudC5cclxuICAgIFdvcmtpbmcgd2l0aCBtZW1vcnkgaW4gdGVuc29ycyBpcyB0cmlja3kuICAgICBcclxuICAgICAqL1xyXG5cclxuICAgIHBvcHVsYXRpb246IEluZGl2aWR1YWxbXT1bXTtcclxuICAgIHByaXZhdGUgX3BvcHVsYXRpb25fc2l6ZTogbnVtYmVyPTMwO1xyXG4gICAgXHJcbiAgICAvKipTZXR0ZXJzIGFuZCBHZXR0ZXJzICovXHJcbiAgICBwdWJsaWMgc2V0IHBvcHVsYXRpb25fc2l6ZShwb3B1bGF0aW9uX3NpemU6IG51bWJlcil7XHJcbiAgICAgICAgdGhpcy5fcG9wdWxhdGlvbl9zaXplPXBvcHVsYXRpb25fc2l6ZTtcclxuICAgIH1cclxuICAgIHB1YmxpYyBnZXQgcG9wdWxhdGlvbl9zaXplKCl7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3BvcHVsYXRpb25fc2l6ZTtcclxuICAgIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTWV0aG9kcyB3aXRoIGltcGxlbWVudGF0aW9uXHJcbiAgICovXHJcblxyXG4gICBhc3luYyBldmFsdWF0ZSgpe1xyXG4gICAgIHJldHVybiB0aGlzLnBvcHVsYXRpb24uZm9yRWFjaChhc3luYyAoZWxlbSk9PntcclxuICAgICAgICBlbGVtLmFjY3VyYWN5PSBhd2FpdCBlbGVtLmluZGl2aWR1YWwuZXZhbHVhdGUoKTsgICAgICAgIFxyXG4gICAgfSlcclxuICB9XHJcblxyXG4gICAgc3RhcnRfcG9wdWxhdGlvbigpe1xyXG5cclxuICAgICAgICBmb3IobGV0IGk9MDsgaTx0aGlzLnBvcHVsYXRpb25fc2l6ZTtpKyspeyAgICAgICAgICAgIFxyXG4gICAgICAgICAgICB0aGlzLnBvcHVsYXRpb24ucHVzaCh7aW5kaXZpZHVhbDogbmV3IFRlYWNoYWJsZU1vYmlsZU5ldCgpfSlcclxuICAgICAgICB9XHJcblxyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIGFwcGx5X2V2b2x1dGlvbihpdGVyYXRpb246IG51bWJlcil7XHJcblxyXG4gICAgICAgIGZvcihsZXQgaT0wO2k8aXRlcmF0aW9uO2krKyl7XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIkludGVyYXRpb246IFwiLGkpXHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiTWVtb3J5OiBcIiwgdGYubWVtb3J5KCkubnVtQnl0ZXMpO1xyXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIlRlbnNvcnMgaW4gbWVtb3J5OiBcIiwgdGYubWVtb3J5KCkubnVtVGVuc29ycyk7XHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiUG9wdWxhdGlvbiBsZW5ndGg6IFwiLCB0aGlzLnBvcHVsYXRpb24ubGVuZ3RoKTtcclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5ldm9sdXRpb24oKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgfVxyXG4gXHJcbiAgICAvKipcclxuICAgICAqIFRoaXMgbWV0aG9kIHdpbGwgYXBwbHkgdGhlIGV2b2x1dGlvblxyXG4gICAgICovXHJcbiAgICBhc3luYyBldm9sdXRpb24oKXtcclxuXHJcbiAgICAgICAgXHJcbiAgICAgICAgXHJcbiAgICAgICAgLy9VcGRhdGUgdGhlIGFjY3VyYWN5XHJcbiAgICAgICAgYXdhaXQgdGhpcy5ldmFsdWF0ZSgpO1xyXG5cclxuICAgICAgICBjb25zdCBvZmZzcHJpbmc9W107XHJcblxyXG4gICAgICAgIC8qKkZpcnN0IHN0ZXAgaXMgY3Jvc3NvdmVyLCBmb3IgY3JlYXRpbmcgb2Zmc3ByaW5nICovXHJcbiAgICAgICAgZm9yKGxldCBpPTA7IGk8dGhpcy5wb3B1bGF0aW9uLmxlbmd0aDtpKyspXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIC8vVGhlIHBvcHVsYXRpb24gd2lsbCBkb3VibGUgaW4gc2l6ZVxyXG4gICAgICAgICAgICAgICAgb2Zmc3ByaW5nLnB1c2godGhpcy5jcm9zc292ZXIoKSk7IFxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgLy9NdXRhdGlvbiBvbiB0aGUgb2Zmc3ByaW5nXHJcbiAgICAvLyAgICBjb25zb2xlLmxvZyhcIldlaWdodCBiZWZvcmUgbXV0YXRpb246IFwiLCBvZmZzcHJpbmdbMF0uaW5kaXZpZHVhbC5nZXRIZWFkKCkubGF5ZXJzWzBdLmdldFdlaWdodHMoKVswXS5kYXRhU3luYygpKTtcclxuXHJcbiAgICAgICB0aGlzLm11dGF0aW9uKG9mZnNwcmluZykgICBcclxuXHJcbiAgICAgICAgLy9Kb2luaW5nIHBhcmVudHMgYW5kIG9mZnNwcmluZyBpbnRvIHRoZSBzYW1lIHBvb2wgZm9yIHNlbGVjdGlvblxyXG4gICAgICAgIHRoaXMucG9wdWxhdGlvbj1bLi4udGhpcy5wb3B1bGF0aW9uLCAuLi5vZmZzcHJpbmddO1xyXG5cclxuICAgICAgICAvL1VwZGF0ZSB0aGUgYWNjdXJhY3lcclxuICAgICAgICAgYXdhaXQgdGhpcy5ldmFsdWF0ZSgpO1xyXG5cclxuXHJcbiAgICAgICAgIC8vc2VsZWN0aW9uXHJcbiAgICAgICAgIHRoaXMuc2VsZWN0aW9uKCk7XHJcbiAgICAgICBcclxuXHJcbiAgICB9XHJcblxyXG4gICAgLyoqQWJzdHJhY3QgbWV0aG9kcy5cclxuICAgICAqIFNob3VsZCBiZSBpbXBsZW1lbnRlZCBieSBlYWNoIHZhcmlhdGlvbiBvZiBldm9sdXRpb25hcnkgYWxnb3JpdGhtc1xyXG4gICAgICovXHJcblxyXG4gICAgYWJzdHJhY3QgY3Jvc3NvdmVyKCk6IEluZGl2aWR1YWw7XHJcbiAgICBhYnN0cmFjdCBtdXRhdGlvbihvZmZzcHJpbmc6IEluZGl2aWR1YWxbXSk6IHZvaWQ7XHJcbiAgICBhYnN0cmFjdCBzZWxlY3Rpb24oKTogdm9pZDtcclxuXHJcblxyXG4gICAgLyoqSGVscGVycyAqL1xyXG5cclxuICAgIGdldFRoZUJlc3QoKTogSW5kaXZpZHVhbHtcclxuICAgICAgICBsZXQgaW5kZXhfYmVzdDogbnVtYmVyPTA7XHJcbiAgICAgICAgbGV0IGJlc3Q9MDtcclxuXHJcbiAgICAgICAgdGhpcy5wb3B1bGF0aW9uLmZvckVhY2goKGVsZW06IGFueSwgaW5kZXg6IG51bWJlcik9PntcclxuXHJcbiAgICAgICAgICAgIGlmKGVsZW0uYWNjdXJhY3k+YmVzdCl7XHJcbiAgICAgICAgICAgICAgICBiZXN0PWVsZW0uYWNjdXJhY3k7XHJcbiAgICAgICAgICAgICAgICBpbmRleF9iZXN0PWluZGV4XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIFxyXG4gICAgICAgIH0pXHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzLnBvcHVsYXRpb25baW5kZXhfYmVzdF07XHJcbiAgICB9XHJcblxyXG5cclxuICAgIGdldFRoZVdvcnN0KCk6IEluZGl2aWR1YWx7XHJcbiAgICAgICAgbGV0IGluZGV4X3dvcnN0OiBudW1iZXI9MDtcclxuICAgICAgICBsZXQgd29yc3Q9MTtcclxuXHJcbiAgICAgICAgdGhpcy5wb3B1bGF0aW9uLmZvckVhY2goKGVsZW06IGFueSwgaW5kZXg6IG51bWJlcik9PntcclxuXHJcbiAgICAgICAgICAgIGlmKGVsZW0uYWNjdXJhY3k8d29yc3Qpe1xyXG4gICAgICAgICAgICAgICAgd29yc3Q9ZWxlbS5hY2N1cmFjeTtcclxuICAgICAgICAgICAgICAgIGluZGV4X3dvcnN0PWluZGV4XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIFxyXG4gICAgICAgIH0pXHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzLnBvcHVsYXRpb25baW5kZXhfd29yc3RdO1xyXG4gICAgfVxyXG5cclxuICAgICAgICAvKipcclxuICAgICAqIFNlbGVjdGluZyBpbmRpdmlkdWFscyBieSBlbGl0aXNtXHJcbiAgICAgKi9cclxuICAgIHNlbGVjdF9wYXJlbnRzX2J5X3JvbGxldF93aGVlbHNfdjIoc2VsZWN0aW9uX251bWJlcj0yKTogSW5kaXZpZHVhbFtde1xyXG5cclxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJTZWxlY3RpbmcgcGFyZW50cyBieSByb2xsZXQgd2hlZWxzLi4uXCIpO1xyXG4gICAgXHJcbiAgICAgICAgICAgIGNvbnN0IHNoYXJlOiBhbnk9W107XHJcbiAgICBcclxuICAgICAgICAgICAgbGV0IHRvdGFsOiBhbnk9MDtcclxuICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJQb3B1bGF0aW9uIGxlbmd0aC4uLlwiLCB0aGlzLnBvcHVsYXRpb24ubGVuZ3RoKTtcclxuICAgIFxyXG4gICAgICAgICAgICAvL1RoaXMgd2lsbCBjcmVhdGUgYW4gb3ZlcmFsbCBhY2N1cmFjeVxyXG4gICAgICAgICAgICB0aGlzLnBvcHVsYXRpb24uZm9yRWFjaCgoZWxlbSk9PnRvdGFsKz1lbGVtLmFjY3VyYWN5KTtcclxuICAgIFxyXG4gICAgICAgICAgICBsZXQgcG9pbnRlcj0wO1xyXG4gICAgXHJcbiAgICAgICAgICAgIHRoaXMucG9wdWxhdGlvbi5mb3JFYWNoKChlbGVtOmFueSwgaW5kZXgpPT57XHJcbiAgICBcclxuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwiQWNjdXJhY3kuLi5cIiwgZWxlbS5hY2N1cmFjeSk7XHJcbiAgICBcclxuICAgICAgICAgICAgICAgIHNoYXJlLnB1c2goXHJcbiAgICAgICAgICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgICAgICAgaW5kZXg6IGluZGV4LFxyXG4gICAgICAgICAgICAgICAgICAgICAgc2hhcmU6ICBlbGVtLmFjY3VyYWN5L3RvdGFsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgbWluOiBwb2ludGVyLFxyXG4gICAgICAgICAgICAgICAgICAgICAgbWF4OiBwb2ludGVyICsgKGVsZW0uYWNjdXJhY3kvdG90YWwpXHJcbiAgICAgICAgICAgICAgICAgIH0pXHJcbiAgICBcclxuICAgICAgICAgICAgICAgICAgcG9pbnRlcis9ZWxlbS5hY2N1cmFjeS90b3RhbDtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICBcclxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJTaGFyZXM6IFwiLCBzaGFyZSk7XHJcbiAgICBcclxuICAgICAgICAgICAgY29uc3QgYXV4X3NlbGVjdGlvbjogYW55ID1bXTtcclxuICAgIFxyXG4gICAgICAgICAgICAgIC8vU2VsZWN0aW5nIHR3byBpbmRpdmlkdWFscyB1c2luZyByb3VsZXR0ZSB3aGVlbHNcclxuICAgICAgICAgICAgbGV0IGNvdW50ZXI9MDtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGluZGV4ZXNfYXV4OiBudW1iZXJbXT1bXTtcclxuXHJcbiAgICAgICAgICAgIHdoaWxlKGNvdW50ZXI8c2VsZWN0aW9uX251bWJlcil7XHJcbiAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgIC8vUmFuZG9tIHBvaW50ZXIsIHVzZWQgdG8gcmFuZG9tbHkgc2VsZWN0IGFuIGluZGl2aWR1YWxcclxuICAgICAgICAgICAgICAgIGNvbnN0IGF1eF9pbmRleD0gTWF0aC5yYW5kb20oKTtcclxuICAgIFxyXG4gICAgICAgICAgICAgICAgc2hhcmUuZm9yRWFjaCgoZWxlbTogYW55KT0+e1xyXG4gICAgXHJcbiAgICAgICAgICAgICAgICAgICAgaWYoKGVsZW0ubWluPGF1eF9pbmRleCkmJihlbGVtLm1heD5hdXhfaW5kZXgpKXtcclxuICAgICAgICAgICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGF1eDogSW5kaXZpZHVhbCA9IHtpbmRpdmlkdWFsOiBuZXcgVGVhY2hhYmxlTW9iaWxlTmV0KCksIGFjY3VyYWN5OiB0aGlzLnBvcHVsYXRpb25bZWxlbS5pbmRleF0uYWNjdXJhY3kgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJJbmRpdmlkdWFsIGp1c3QgY3JlYXRlZCAod2VpZ3RoKTogXCIsIGF1eC5pbmRpdmlkdWFsLmdldEhlYWQoKS5sYXllcnNbMF0uZ2V0V2VpZ2h0cygpWzBdLmRhdGFTeW5jKCkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJJbmRpdmlkdWFsIG9yaWdpbmFsOiBcIiwgdGhpcy5wb3B1bGF0aW9uW2VsZW0uaW5kZXhdLmluZGl2aWR1YWwuZ2V0SGVhZCgpLmxheWVyc1swXS5nZXRXZWlnaHRzKClbMF0uZGF0YVN5bmMoKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgICAgICAgICAgICAgLy8gT3JpZ2luYWwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUmVjaXBpZW50XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoaXMuY29weU1vZGVsKHRoaXMucG9wdWxhdGlvbltlbGVtLmluZGV4XS5pbmRpdmlkdWFsLmdldEhlYWQoKSxhdXguaW5kaXZpZHVhbC5nZXRIZWFkKCkpXHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGlzLnBvcHVsYXRpb25bZWxlbS5pbmRleF0uaW5kaXZpZHVhbC5nZXRIZWFkKCkuZGlzcG9zZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJJbmRpdmlkdWFsIGp1c3QgY3JlYXRlZCAod2VpZ3RodCwgY29waWVkKTogXCIsIGF1eC5pbmRpdmlkdWFsLmdldEhlYWQoKS5sYXllcnNbMF0uZ2V0V2VpZ2h0cygpWzBdLmRhdGFTeW5jKCkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlcisrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBhdXhfc2VsZWN0aW9uLnB1c2godGhpcy5wb3B1bGF0aW9uW2VsZW0uaW5kZXhdKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluZGV4ZXNfYXV4LnB1c2goZWxlbS5pbmRleClcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyB0aGlzLnBvcHVsYXRpb24uZm9yRWFjaCgoZWxlbSwgaW5kZXgpPT57XHJcbiAgICAgICAgICAgIC8vICAgICBpZighaW5kZXhlc19hdXguaW5jbHVkZXMoaW5kZXgpKXtcclxuICAgICAgICAgICAgLy8gICAgICAgICBjb25zb2xlLmxvZyhcIkRpc3Bvc2VkLi4uXCIpXHJcbiAgICAgICAgICAgIC8vICAgICAgICAgZWxlbS5pbmRpdmlkdWFsLmdldEhlYWQoKS5kaXNwb3NlKCk7XHJcbiAgICAgICAgICAgIC8vICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIC8vIH0pXHJcblxyXG4gICAgICAgICAgICAvLyB0aGlzLnBvcHVsYXRpb249W107XHJcblxyXG4gICAgICAgICAgICByZXR1cm4gYXV4X3NlbGVjdGlvbjtcclxuICAgICAgICB9XHJcbiAgICBcclxuICAgIC8qKlxyXG4gICAgICogU2VsZWN0aW5nIGluZGl2aWR1YWxzIGJ5IGVsaXRpc21cclxuICAgICAqL1xyXG4gICAgc2VsZWN0X3BhcmVudHNfYnlfcm9sbGV0X3doZWVscyhzZWxlY3Rpb25fbnVtYmVyPTIpOiBJbmRpdmlkdWFsW117XHJcblxyXG4gICAgICAgIC8vIGNvbnNvbGUubG9nXHJcbiAgICAgICAgLy8gKFwiU2VsZWN0aW5nIHBhcmVudHMgYnkgcm9sbGV0IHdoZWVscy4uLlwiKTtcclxuXHJcbiAgICAgICAgY29uc3Qgc2hhcmU6IGFueT1bXTtcclxuXHJcbiAgICAgICAgbGV0IHRvdGFsOiBhbnk9MDtcclxuICAgICAgICAgIFxyXG4gICAgICAgIC8vIGNvbnNvbGUubG9nKFwiUG9wdWxhdGlvbiBsZW5ndGguLi5cIiwgdGhpcy5wb3B1bGF0aW9uLmxlbmd0aCk7XHJcblxyXG4gICAgICAgIC8vVGhpcyB3aWxsIGNyZWF0ZSBhbiBvdmVyYWxsIGFjY3VyYWN5XHJcbiAgICAgICAgdGhpcy5wb3B1bGF0aW9uLmZvckVhY2goKGVsZW0pPT50b3RhbCs9ZWxlbS5hY2N1cmFjeSk7XHJcblxyXG4gICAgICAgIGxldCBwb2ludGVyPTA7XHJcblxyXG4gICAgICAgIHRoaXMucG9wdWxhdGlvbi5mb3JFYWNoKChlbGVtOmFueSwgaW5kZXgpPT57XHJcblxyXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkFjY3VyYWN5Li4uXCIsIGVsZW0uYWNjdXJhY3kpO1xyXG5cclxuICAgICAgICAgICAgc2hhcmUucHVzaChcclxuICAgICAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgICAgaW5kZXg6IGluZGV4LFxyXG4gICAgICAgICAgICAgICAgICBzaGFyZTogIGVsZW0uYWNjdXJhY3kvdG90YWwsXHJcbiAgICAgICAgICAgICAgICAgIG1pbjogcG9pbnRlcixcclxuICAgICAgICAgICAgICAgICAgbWF4OiBwb2ludGVyICsgKGVsZW0uYWNjdXJhY3kvdG90YWwpXHJcbiAgICAgICAgICAgICAgfSlcclxuXHJcbiAgICAgICAgICAgICAgcG9pbnRlcis9ZWxlbS5hY2N1cmFjeS90b3RhbDtcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgLy8gY29uc29sZS5sb2coXCJTaGFyZXM6IFwiLCBzaGFyZSk7XHJcblxyXG4gICAgICAgIGNvbnN0IGF1eF9zZWxlY3Rpb246IGFueSA9W107XHJcblxyXG4gICAgICAgICAgLy9TZWxlY3RpbmcgdHdvIGluZGl2aWR1YWxzIHVzaW5nIHJvdWxldHRlIHdoZWVsc1xyXG4gICAgICAgIGxldCBjb3VudGVyPTA7XHJcbiAgICAgICAgd2hpbGUoY291bnRlcjxzZWxlY3Rpb25fbnVtYmVyKXtcclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIC8vUmFuZG9tIHBvaW50ZXIsIHVzZWQgdG8gcmFuZG9tbHkgc2VsZWN0IGFuIGluZGl2aWR1YWxcclxuICAgICAgICAgICAgY29uc3QgYXV4X2luZGV4PSBNYXRoLnJhbmRvbSgpO1xyXG5cclxuICAgICAgICAgICAgc2hhcmUuZm9yRWFjaCgoZWxlbTogYW55KT0+e1xyXG5cclxuICAgICAgICAgICAgICAgIGlmKChlbGVtLm1pbjxhdXhfaW5kZXgpJiYoZWxlbS5tYXg+YXV4X2luZGV4KSl7XHJcbiAgICAgICAgICAgICAgICAgICAgY291bnRlcisrO1xyXG4gICAgICAgICAgICAgICAgICAgIGF1eF9zZWxlY3Rpb24ucHVzaCh0aGlzLnBvcHVsYXRpb25bZWxlbS5pbmRleF0pO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9KVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gYXV4X3NlbGVjdGlvbjtcclxuICAgIH1cclxuXHJcbi8qKlxyXG4gKiBUaGlzIGZ1bmN0aW9uIHdpbGwgbWFrZSBhIGNvcHkgb2YgYSBtb2RlbCBvbiB0aGUgd2VpZ2h0IGxldmVsXHJcbiAqIFRoaXMgaXMgYW4gYXR0ZW1wdCB0byBhdm9pZCBpbmZsdWVuY2luZyB0aGUgbmV3IG1vZGVsIHdoZW4gdGhlIG9sZCBvbmVcclxuICogaXMgZWxpbWluYXRlZC4gXHJcbiAqIFxyXG4gKiBAcGFyYW0gb3JpZ2luYWxNb2RlbCAtIHRoZSBtb2RlbCB0byBiZSBjb3BpZWQgXHJcbiAqIEBwYXJhbSByZWNpcGllbnQgLSB0aGUgbmV3IG1vZGVsXHJcbiAqL1xyXG5hc3luYyBjb3B5TW9kZWwgKG9yaWdpbmFsTW9kZWw6IHRmLkxheWVyc01vZGVsLCByZWNpcGllbnQ6IHRmLkxheWVyc01vZGVsKSAge1xyXG5cclxuICAgIG9yaWdpbmFsTW9kZWwubGF5ZXJzLmZvckVhY2goKGxheWVyOiBhbnksIGluZGV4OiBhbnkpPT57XHJcbiAgICAgICAgcmVjaXBpZW50LmxheWVyc1tpbmRleF0uc2V0V2VpZ2h0cyhsYXllci5nZXRXZWlnaHRzKCkpXHJcbiAgICB9KVxyXG59ICAgIFxyXG5cclxufVxyXG4iXX0=
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlzcGxheS1wYW5lbC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy90ZmpzLWV2b2x1dGlvbi9zcmMvbGliL2NvbXBvbmVudHMvZGlzcGxheS1wYW5lbC9kaXNwbGF5LXBhbmVsLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RmanMtZXZvbHV0aW9uL3NyYy9saWIvY29tcG9uZW50cy9kaXNwbGF5LXBhbmVsL2Rpc3BsYXktcGFuZWwuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUV6QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7OztBQVN0RSxNQUFNLE9BQU8scUJBQXFCO0lBUGxDO1FBU0UsWUFBTyxHQUFVLEVBQUUsQ0FBQztLQW9GckI7SUE5RUQsVUFBVSxDQUFDLGlCQUF5QixFQUFFLGFBQXVCLEVBQUUsT0FBZTtRQUUxRSxJQUFJLENBQUMsYUFBYSxHQUFDLGFBQWEsQ0FBQztRQUNqQyxJQUFJLENBQUMsMkJBQTJCLEdBQUMsaUJBQWlCLENBQUM7UUFFbkQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUUvQyxDQUFDO0lBR0gsV0FBVyxDQUFDLGlCQUF5QixFQUFFLE9BQWU7UUFFbEQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ2xELElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsRUFBRSxpQkFBaUIsRUFBRSxPQUFPLENBQUMsQ0FBQztTQUVw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ImltcG9ydCB7IENvbXBvbmVudH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IEdyb3VwIH0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9ncm91cCc7XHJcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcbmltcG9ydCB7IFRlYWNoYWJsZU1vYmlsZU5ldCB9IGZyb20gJy4uLy4uL21vZGVscy90ZWFjaGFibGUtZXZvbHV0aW9uJztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnbmV1cm9ldm9sdXRpb24tZGlzcGxheS1wYW5lbCcsXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcclxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlXSxcclxuICB0ZW1wbGF0ZVVybDogJy4vZGlzcGxheS1wYW5lbC5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmw6ICcuL2Rpc3BsYXktcGFuZWwuY29tcG9uZW50LmNzcydcclxufSlcclxuZXhwb3J0IGNsYXNzIERpc3BsYXlQYW5lbENvbXBvbmVudCB7XHJcblxyXG4gIGNsYXNzZXM6IEdyb3VwW109W107XHJcblxyXG4gIGNsYXNzZXNfbmFtZXMhOiBzdHJpbmdbXTtcclxuXHJcbiAgbnVtYmVyX29mX3NhbXBsZXNfcGVyX2NsYXNzITogbnVtYmVyO1xyXG5cclxubG9hZEltYWdlcyhudW1iZXJfb2Zfc3BlY2llczogbnVtYmVyLCBjbGFzc2VzX25hbWVzOiBzdHJpbmdbXSwgb3B0aW9uczogb2JqZWN0KXtcclxuICAgIFxyXG4gICAgdGhpcy5jbGFzc2VzX25hbWVzPWNsYXNzZXNfbmFtZXM7XHJcbiAgICB0aGlzLm51bWJlcl9vZl9zYW1wbGVzX3Blcl9jbGFzcz1udW1iZXJfb2Zfc3BlY2llcztcclxuXHJcbiAgICB0aGlzLmFkZF9zcGVjaWVzKG51bWJlcl9vZl9zcGVjaWVzLCBvcHRpb25zKTsgICAgXHJcblxyXG4gIH1cclxuXHJcblxyXG5hZGRfc3BlY2llcyhudW1iZXJfb2Zfc3BlY2llczogbnVtYmVyLCBvcHRpb25zOiBvYmplY3Qpe1xyXG5cclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5jbGFzc2VzX25hbWVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIHRoaXMuYWRkX2ltYWdlcyh0aGlzLmNsYXNzZXNfbmFtZXNbaV0sIG51bWJlcl9vZl9zcGVjaWVzLCBvcHRpb25zKTtcclxuICAgICAgXHJcbiAgICB9XHJcblxyXG4gIH1cclxuXHJcbiAgYWRkX2ltYWdlcyhuYW1lOiBzdHJpbmcsIG51bWJlcl9vZl9zcGVjaWVzOiBudW1iZXIsIG9wdGlvbnM6IGFueSl7ICAgXHJcblxyXG4gICAgY29uc3QgY2xhc3NfYWRkOiBhbnk9IFtdO1xyXG5cclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyX29mX3NwZWNpZXM7IGkrKykge1xyXG4gICAgICBpZighb3B0aW9ucy5maWxlX25hbWUgJiYgKG9wdGlvbnMuc3ViZm9sZGVyKSl7ICAgICAgICBcclxuICAgICAgICBjbGFzc19hZGQucHVzaChgJHtvcHRpb25zLmJhc2V9LyR7bmFtZX0vJHtvcHRpb25zLnN1YmZvbGRlcn0vJHtuYW1lfSAke2krMX0uJHtvcHRpb25zLmZpbGVfZXh0ZW5zaW9ufWApO1xyXG4gICAgICB9IFxyXG4gICAgICBlbHNlIGlmKG9wdGlvbnMubnVtYmVyZWQpe1xyXG4gICAgICBcclxuICAgICAgICBjbGFzc19hZGQucHVzaChgJHtvcHRpb25zLmJhc2V9LyR7bmFtZX0vJHtpKzF9LiR7b3B0aW9ucy5maWxlX2V4dGVuc2lvbn1gKTtcclxuXHJcblxyXG4gICAgICB9IFxyXG4gICAgICAgICBcclxuICAgICAgZWxzZSAgICAgIFxyXG4gICAgICAgIGNsYXNzX2FkZC5wdXNoKGAke29wdGlvbnMuYmFzZX0vJHtuYW1lfS8ke29wdGlvbnMuZmlsZV9uYW1lfSAke2krMX0uJHtvcHRpb25zLmZpbGVfZXh0ZW5zaW9ufWApO1xyXG4gIH1cclxuXHJcbiAgdGhpcy5jbGFzc2VzLnB1c2goe25hbWU6IG5hbWUsIGltYWdlczogY2xhc3NfYWRkfSkgIFxyXG5cclxuICB9XHJcblxyXG4gYXN5bmMgYWRkZXhhbXBsZXMoKXtcclxuXHJcbiAgLy9UaGlzIGlzIG5lZWRlZCB0byBtYWtlIHN1cmUgaXQgZ2l2ZXMgdGltZSBmb3IgdGhlIGltYWdlcyB0byB1cGxvYWRcclxuICAvL1RoZSBpbWFnZXMgdXBsb2FkIHZlcnkgZmFzdCwgd2hhdCBtYWtlcyB0aGlzIG1ldGhvZCBleGVjdXRlIGJlZm9yZSB0aGUgaW1hZ2VzIGFyZSBvbiBIVE1MXHJcbiAgLy9JdCBjYW4gYmUgcmVtb3ZlZCBpZiBzb21laG93IHRoaXMgbWV0aG9kIGlzIGp1c3QgY2FsbGVkIGFmdGVyIHRoZSBpbWFnZXMgYXJlIGF2YWlsYWJsZS5cclxuICAvLyBjb25zb2xlLmxvZyhcIkxvYWRpbmcgZXhhbXBsZXMgYXMgdGVuc29ycy4uLi5cIilcclxuICBhd2FpdCB0aGlzLmRlbGF5KDApO1xyXG5cclxuICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuY2xhc3Nlc19uYW1lcy5sZW5ndGg7IGkrKykge1xyXG4gICAgYXdhaXQgdGhpcy5hZGRfZXhhbXBsZSh0aGlzLmNsYXNzZXNfbmFtZXNbaV0sIHRoaXMubnVtYmVyX29mX3NhbXBsZXNfcGVyX2NsYXNzKTtcclxuICB9XHJcbiAgfVxyXG5cclxuICBhc3luYyBhZGRfZXhhbXBsZShuYW1lOiBzdHJpbmcsIG51bWJlcl9vZl9zcGVjaWVzOiBudW1iZXIpeyAgIFxyXG5cclxuICAgIGNvbnN0IGNsYXNzX2FkZDogYW55PSBbXTtcclxuICAgIC8vIGNvbnNvbGUubG9nKG5hbWUpXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bWJlcl9vZl9zcGVjaWVzOyBpKyspIHsgXHJcbiAgICAgIFxyXG4gICAgICAvL0NvbGxlY3RpbmcgdGhlIGltYWdlcyBmcm9tIEhUTUxcclxuICAgICAgY29uc3QgYXV4ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoYGNsYXNzLSR7bmFtZX0tJHtpfWApIGFzIEhUTUxJbWFnZUVsZW1lbnQ7ICAgICAgXHJcblxyXG4gICAgICAvL0FkZGluZyB0aGUgZXhhbXBsZVxyXG4gICAgICBjb25zdCBpbmRleD0gdGhpcy5jbGFzc2VzX25hbWVzLmZpbmRJbmRleCgoZWxlbSk9PmVsZW09PT1uYW1lKVxyXG5cclxuICAgICAgYXdhaXQgVGVhY2hhYmxlTW9iaWxlTmV0LmFkZEV4YW1wbGUoaW5kZXgsIG5hbWUsIGF1eCk7ICAgIFxyXG4gICAgICBcclxuICB9XHJcblxyXG4gIC8vIHRoaXMuY2xhc3Nlcy5wdXNoKHtuYW1lOiBuYW1lLCBpbWFnZXM6IGNsYXNzX2FkZH0pICBcclxuXHJcbiAgfVxyXG5cclxuICBkZWxheShtczogbnVtYmVyKSB7XHJcbiAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpKTtcclxufVxyXG59XHJcbiIsIjxkaXYgKm5nRm9yPVwibGV0IGNsYXNzIG9mIGNsYXNzZXM7IGluZGV4IGFzIGlcIj5cclxuICA8aDE+e3tjbGFzcy5uYW1lfX08L2gxPlxyXG4gIDxpbWcgICpuZ0Zvcj1cImxldCBpdGVtIG9mIGNsYXNzLmltYWdlczsgaW5kZXggYXMgaVwiIFtzcmNdPVwiaXRlbVwiIHdpZHRoPVwiMjI0XCIgaGVpZ2h0PVwiMjI0XCIgW2lkXT1cIidjbGFzcy0nICsgY2xhc3MubmFtZSArICctJyArIGlcIiBjcm9zc29yaWdpbj1cImFub255bW91c1wiID5cclxuPC9kaXY+XHJcbiJdfQ==
@@ -33,8 +33,15 @@ export class TeachableMobileNet extends CustomMobileNet {
33
33
  constructor() {
34
34
  super();
35
35
  this.classes = [];
36
+ //Parameters
37
+ this._epochs = 10;
36
38
  this.createHead();
37
39
  }
40
+ /*** */
41
+ set epochs(epochs) {
42
+ this._epochs = epochs;
43
+ }
44
+ /*** */
38
45
  /**
39
46
  * This method will return the head, the trainable part, the part under evolution.
40
47
  */
@@ -88,7 +95,7 @@ export class TeachableMobileNet extends CustomMobileNet {
88
95
  {},
89
96
  ];
90
97
  const history = await this.trainingModel.fitDataset(trainData, {
91
- epochs: 100,
98
+ epochs: this._epochs,
92
99
  validationData,
93
100
  callbacks
94
101
  }).then((info) => {
@@ -119,8 +126,8 @@ export class TeachableMobileNet extends CustomMobileNet {
119
126
  confusion_matrix_recipient.push([]);
120
127
  for (let j = 0; j < TeachableMobileNet.classes_names.length; j++) {
121
128
  confusion_matrix_recipient[i].push([]);
122
- confusion_matrix_recipient[i][j] = confusion_matrix[TeachableMobileNet.classes_names.length * i + j] / TeachableMobileNet.numValidation;
123
- confusion_matrix_recipient[i][j] = (confusion_matrix_recipient[i][j].toFixed(2)) * 100;
129
+ confusion_matrix_recipient[i][j] = (confusion_matrix[TeachableMobileNet.classes_names.length * i + j] / TeachableMobileNet.numValidation).toFixed(2);
130
+ confusion_matrix_recipient[i][j] = (confusion_matrix_recipient[i][j].toFixed(2) * 100);
124
131
  }
125
132
  // accuracy.push(confusion_matrix[TeachableMobileNet.classes_names.length*i+ i]/TeachableMobileNet.numValidation)
126
133
  }
@@ -427,4 +434,4 @@ function fisherYates(array, seed) {
427
434
  }
428
435
  return shuffled;
429
436
  }
430
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVhY2hhYmxlLWV2b2x1dGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RmanMtZXZvbHV0aW9uL3NyYy9saWIvbW9kZWxzL3RlYWNoYWJsZS1ldm9sdXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGVBQWUsRUFBMEIsTUFBTSxvQkFBb0IsQ0FBQztBQUU3RSxPQUFPLEtBQUssRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRXZDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFdEMsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUlyQyxPQUFPLEtBQUssS0FBSyxNQUFNLHNCQUFzQixDQUFDO0FBSTlDLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxDQUFDO0FBc0JqQzs7O0dBR0c7QUFDSCxNQUFNLFlBQVksR0FBRyxDQUFDLElBQXVCLEVBQUUsRUFBRTtJQUMvQyw4RkFBOEY7SUFDOUYsd0RBQXdEO0lBQ3hELElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFdBQVcsSUFBSSx5QkFBeUIsQ0FBQztJQUNqRSxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLElBQUksSUFBSSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUM1RCxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxZQUFZLElBQUksRUFBRSxDQUFDO0lBQzVDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsSUFBSSxVQUFVLENBQUM7SUFDOUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQztJQUNoQyxpREFBaUQ7SUFDakQsT0FBTyxJQUFnQixDQUFDO0FBQzFCLENBQUMsQ0FBQztBQUVGLE1BQU0sT0FBTyxrQkFBbUIsU0FBUSxlQUFlO0lBRW5ELHVDQUF1QztJQUN2Qzs7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USxDQUFDLFdBQVcsQ0FBQyxFQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0tBQzlFO0lBRUQsT0FBTyxRQUFRLENBQUM7QUFDbEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEN1c3RvbU1vYmlsZU5ldCwgbG9hZFRydW5jYXRlZE1vYmlsZU5ldCB9IGZyb20gXCIuL2N1c3RvbS1tb2JpbGVuZXRcIjtcclxuXHJcbmltcG9ydCAqIGFzIHRmIGZyb20gJ0B0ZW5zb3JmbG93L3RmanMnO1xyXG5cclxuaW1wb3J0IHsgY2FwdHVyZSB9IGZyb20gJy4uL3V0aWxzL3RmJztcclxuaW1wb3J0IHsgQ2xhc3MgfSBmcm9tICcuLi91dGlscy9jbGFzcyc7XHJcbmltcG9ydCB7IFV0aWwgfSBmcm9tIFwiLi4vdXRpbHMvdXRpbFwiO1xyXG5cclxuaW1wb3J0ICogYXMgc2VlZHJhbmRvbSBmcm9tICdzZWVkcmFuZG9tJztcclxuXHJcbmltcG9ydCAqIGFzIHRmdmlzIGZyb20gJ0B0ZW5zb3JmbG93L3RmanMtdmlzJztcclxuXHJcbmltcG9ydCB7IFRlbnNvckNvbnRhaW5lciB9IGZyb20gJ0B0ZW5zb3JmbG93L3RmanMtY29yZS9kaXN0L3RlbnNvcl90eXBlcyc7XHJcblxyXG5jb25zdCBWQUxJREFUSU9OX0ZSQUNUSU9OID0gMC4xNTtcclxuXHJcblxyXG5cclxuLyoqXHJcbiAqIHRoZSBtZXRhZGF0YSB0byBkZXNjcmliZSB0aGUgbW9kZWwncyBjcmVhdGlvbixcclxuICogaW5jbHVkZXMgdGhlIGxhYmVscyBhc3NvY2lhdGVkIHdpdGggdGhlIGNsYXNzZXNcclxuICogYW5kIHZlcnNpb25pbmcgaW5mb3JtYXRpb24gZnJvbSB0cmFpbmluZy5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgTWV0YWRhdGEge1xyXG4gIHRmanNWZXJzaW9uOiBzdHJpbmc7XHJcbiAgdG1WZXJzaW9uPzogc3RyaW5nO1xyXG4gIHBhY2thZ2VWZXJzaW9uOiBzdHJpbmc7XHJcbiAgcGFja2FnZU5hbWU6IHN0cmluZztcclxuICBtb2RlbE5hbWU/OiBzdHJpbmc7XHJcbiAgdGltZVN0YW1wPzogc3RyaW5nO1xyXG4gIGxhYmVsczogc3RyaW5nW107XHJcbiAgdXNlck1ldGFkYXRhPzoge307XHJcbiAgZ3JheXNjYWxlPzogYm9vbGVhbjtcclxuICBpbWFnZVNpemU/OiBudW1iZXI7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZWNlaXZlcyBhIE1ldGFkYXRhIG9iamVjdCBhbmQgZmlsbHMgaW4gdGhlIG9wdGlvbmFsIGZpZWxkcyBzdWNoIGFzIHRpbWVTdGFtcFxyXG4gKiBAcGFyYW0gZGF0YSBhIE1ldGFkYXRhIG9iamVjdFxyXG4gKi9cclxuY29uc3QgZmlsbE1ldGFkYXRhID0gKGRhdGE6IFBhcnRpYWw8TWV0YWRhdGE+KSA9PiB7XHJcbiAgLy8gdXRpbC5hc3NlcnQodHlwZW9mIGRhdGEudGZqc1ZlcnNpb24gPT09ICdzdHJpbmcnLCAoKSA9PiBgbWV0YWRhdGEudGZqc1ZlcnNpb24gaXMgaW52YWxpZGApO1xyXG4gIC8vIGRhdGEucGFja2FnZVZlcnNpb24gPSBkYXRhLnBhY2thZ2VWZXJzaW9uIHx8IHZlcnNpb247XHJcbiAgZGF0YS5wYWNrYWdlTmFtZSA9IGRhdGEucGFja2FnZU5hbWUgfHwgJ0B0ZWFjaGFibGVtYWNoaW5lL2ltYWdlJztcclxuICBkYXRhLnRpbWVTdGFtcCA9IGRhdGEudGltZVN0YW1wIHx8IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKTtcclxuICBkYXRhLnVzZXJNZXRhZGF0YSA9IGRhdGEudXNlck1ldGFkYXRhIHx8IHt9O1xyXG4gIGRhdGEubW9kZWxOYW1lID0gZGF0YS5tb2RlbE5hbWUgfHwgJ3VudGl0bGVkJztcclxuICBkYXRhLmxhYmVscyA9IGRhdGEubGFiZWxzIHx8IFtdO1xyXG4gIC8vIGRhdGEuaW1hZ2VTaXplID0gZGF0YS5pbWFnZVNpemUgfHwgSU1BR0VfU0laRTtcclxuICByZXR1cm4gZGF0YSBhcyBNZXRhZGF0YTtcclxufTtcclxuXHJcbmV4cG9ydCBjbGFzcyBUZWFjaGFibGVNb2JpbGVOZXQgZXh0ZW5kcyBDdXN0b21Nb2JpbGVOZXQge1xyXG5cclxuICAgIC8vIEFycmF5IG9mIGFsbCB0aGUgZXhhbXBsZXMgY29sbGVjdGVkLlxyXG4gICAgLyoqXHJcbiAgICAgIEl0IGlzIHN0YXRpYyBzaW5jZSBhbGwgdGhlIGluc3RhbmNlIHdpbGwgc2hhcmUgdGhlIHNhbWUgZmVhdHVyZXMsIGZvciBzYXZpbmcgbWVtb3J5IGFuZCB0aW1lLlxyXG4gICAgICBUaGUgaWRlYSBpcyBhdm9pZGluZyByZXN0b3JpbmcgdGhlIGZlYXR1cmVzIGluZGl2aWR1YWxseSBhbmQgaGF2aW5nIHRoZSByZWNhbGN1bGF0ZSB0aGVtIGZvciBldmVyeSBuZXdcclxuICAgICAgaW5kaXZpZHVhbHMuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgZXhhbXBsZXM6IEZsb2F0MzJBcnJheVtdW10gPSBbXTtcclxuXHJcbiAgICAvLyBOdW1iZXIgb2YgdG90YWwgc2FtcGxlc1xyXG4gICAgcHJpdmF0ZSBzdGF0aWMgdG90YWxTYW1wbGVzID0gMDtcclxuXHJcbiAgICBjbGFzc2VzOiBDbGFzc1tdPVtdO1xyXG5cclxuICAgIHN0YXRpYyBjbGFzc2VzX25hbWVzOiBzdHJpbmdbXT1bXTtcclxuXHJcbiAgICBzdGF0aWMgbnVtQ2xhc3NlczogbnVtYmVyO1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAqIHRoZSB0cmFpbmluZyBtb2RlbCBmb3IgdHJhbnNmZXIgbGVhcm5pbmdcclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIHRyYWluaW5nTW9kZWwhOiB0Zi5MYXllcnNNb2RlbDtcclxuICB0cmFpbkRhdGFzZXQ6IGFueTtcclxuICB2YWxpZGF0aW9uRGF0YXNldDogYW55O1xyXG4gIHN0YXRpYyB0cmFpbkRhdGFzZXQ6IGFueTtcclxuICBzdGF0aWMgdmFsaWRhdGlvbkRhdGFzZXQ6IGFueTtcclxuICBzdGF0aWMgbnVtVmFsaWRhdGlvbjogbnVtYmVyO1xyXG5cclxuICBjb25zdHJ1Y3Rvcigpe1xyXG4gICAgc3VwZXIoKTtcclxuICAgIHRoaXMuY3JlYXRlSGVhZCgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVGhpcyBtZXRob2Qgd2lsbCByZXR1cm4gdGhlIGhlYWQsIHRoZSB0cmFpbmFibGUgcGFydCwgdGhlIHBhcnQgdW5kZXIgZXZvbHV0aW9uLlxyXG4gICAqL1xyXG4gIGdldEhlYWQoKXtcclxuICAgIHJldHVybiB0aGlzLnRyYWluaW5nTW9kZWw7XHJcbiAgfVxyXG5cclxuIC8qKlxyXG4gICogQ3JlYXRlIHRoZSBoZWFkIGZvciB0cmFuc2ZlciBsZWFybmluZy5cclxuICAqIFRoaXMgaXMgdGhlIHRyYWluYWJsZSBzZWN0aW9uIG9mIHRoZSB0cmFuc2ZlciBsZWFybmluZy5cclxuICAqL1xyXG4gY3JlYXRlSGVhZCgpe1xyXG5cclxuICBjb25zdCBpbnB1dFNpemU9IFRlYWNoYWJsZU1vYmlsZU5ldC5nZXRpbnB1dFNoYXBlKCk7XHJcblxyXG4gIHRoaXMudHJhaW5pbmdNb2RlbCA9IHRmLnNlcXVlbnRpYWwoe1xyXG4gICAgbGF5ZXJzOiBbXHJcbiAgICAgIHRmLmxheWVycy5kZW5zZSh7XHJcbiAgICAgICAgaW5wdXRTaGFwZTogW2lucHV0U2l6ZV0sXHJcbiAgICAgICAgdW5pdHM6MTAwLFxyXG4gICAgICAgIGFjdGl2YXRpb246ICdyZWx1JywgIFxyXG4gICAgICAgIHVzZUJpYXM6IHRydWVcclxuICAgIH0pLFxyXG4gICAgdGYubGF5ZXJzLmRlbnNlKHsgIFxyXG4gICAgICB1c2VCaWFzOiBmYWxzZSxcclxuICAgICAgYWN0aXZhdGlvbjogJ3NvZnRtYXgnLFxyXG4gICAgICB1bml0czogVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoXHJcbiAgfSlcclxuICAgIF1cclxuICB9KTtcclxuXHJcbiAgY29uc3Qgb3B0aW1pemVyID0gdGYudHJhaW4uYWRhbSgpO1xyXG4gIC8vIGNvbnN0IG9wdGltaXplciA9IHRmLnRyYWluLnJtc3Byb3AocGFyYW1zLmxlYXJuaW5nUmF0ZSk7XHJcblxyXG4gIHRoaXMudHJhaW5pbmdNb2RlbC5jb21waWxlKHtcclxuICAgICAgb3B0aW1pemVyLFxyXG4gICAgICAvLyBsb3NzOiAnYmluYXJ5Q3Jvc3NlbnRyb3B5JyxcclxuICAgICAgbG9zczogJ2NhdGVnb3JpY2FsQ3Jvc3NlbnRyb3B5JyxcclxuICAgICAgbWV0cmljczogWydhY2N1cmFjeSddXHJcbiAgfSk7XHJcbiB9XHJcbiBcclxuIGFzeW5jICB0cmFpbigpe1xyXG5cclxuICBjb25zdCB0cmFpbmluZ1N1cmZhY2UgPSB7IG5hbWU6ICdMb3NzIGFuZCBNU0UnLCB0YWI6ICdUcmFpbmluZycgfTtcclxuXHJcbiAgY29uc3QgZGF0YXNldD0gVGVhY2hhYmxlTW9iaWxlTmV0LmNvbnZlcnRUb1RmRGF0YXNldCgpO1xyXG5cclxuICAvL1NhbHZpbmcgYSBjb3B5IG9mIHRoZSB2YWxpZGF0aW9uIGRhdGFzZXQsIGZvciBsYXRlclxyXG4gIFRlYWNoYWJsZU1vYmlsZU5ldC52YWxpZGF0aW9uRGF0YXNldD0gZGF0YXNldC52YWxpZGF0aW9uRGF0YXNldDtcclxuXHJcbiAgLy8gY29uc29sZS5sb2coXCJEYXRhc2V0IGZvciB0cmFpbmluZzogXCIsIGRhdGFzZXQudHJhaW5EYXRhc2V0KTtcclxuXHJcbiAgY29uc3QgdHJhaW5EYXRhID0gZGF0YXNldC50cmFpbkRhdGFzZXQuYmF0Y2goMzApO1xyXG4gIGNvbnN0IHZhbGlkYXRpb25EYXRhID0gZGF0YXNldC52YWxpZGF0aW9uRGF0YXNldC5iYXRjaCgxMCk7XHJcblxyXG4gIC8vIHRoaXMuY3JlYXRlSGVhZCgpO1xyXG5cclxuICBjb25zdCBjYWxsYmFja3M9IFtcclxuICAgIC8vIFNob3cgb24gYSB0ZmpzLXZpcyB2aXNvciB0aGUgbG9zcyBhbmQgYWNjdXJhY3kgdmFsdWVzIGF0IHRoZSBlbmQgb2YgZWFjaCBlcG9jaC5cclxuICAgIHRmdmlzLnNob3cuZml0Q2FsbGJhY2tzKHRyYWluaW5nU3VyZmFjZSwgWydsb3NzJywgJ2FjYycsIFwidmFsX2xvc3NcIiwgXCJ2YWxfYWNjXCJdLFxyXG4gICAgICB7XHJcbiAgICAgICAgY2FsbGJhY2tzOiBbJ29uRXBvY2hFbmQnXSxcclxuICAgICAgfVxyXG4gICAgKSxcclxuICAgIHt9LF1cclxuXHJcbiAgY29uc3QgaGlzdG9yeTogYW55ID0gYXdhaXQgdGhpcy50cmFpbmluZ01vZGVsLmZpdERhdGFzZXQodHJhaW5EYXRhLCB7XHJcbiAgICBlcG9jaHM6IDEwMCxcclxuICAgIHZhbGlkYXRpb25EYXRhLFxyXG4gICAgY2FsbGJhY2tzXHJcbn0pLnRoZW4oKGluZm86YW55KT0+e1xyXG4gICBjb25zb2xlLmxvZygnUHJlY2lzw6NvIGZpbmFsJywgaW5mby5oaXN0b3J5LnZhbF9hY2NbaW5mby5oaXN0b3J5LmFjYy5sZW5ndGgtMV0pO1xyXG59KTtcclxuXHJcblxyXG4vLyBhd2FpdCB0aGlzLmFjY3VyYWN5X3Blcl9jbGFzcygpO1xyXG5cclxuXHJcbi8vIGNvbnNvbGUubG9nKFwiSGlzdG9yeTogXCIsIGhpc3RvcnkuaGlzdG9yeS5hY2MpO1xyXG4gIC8vIGF3YWl0IHRoaXMudHJhaW5pbmdNb2RlbC5maXQodGhpcy5mZWF0dXJlWCwgdGhpcy50YXJnZXQsIHt9KVxyXG4gfVxyXG5cclxuYXN5bmMgYWNjdXJhY3lfcGVyX2NsYXNzKGNvbmZ1c2lvbl9tYXRyaXhfcmVjaXBpZW50OiBhbnkpe1xyXG4gIFxyXG4gIC8qKkNhbGN1bGF0aW5nIEFjY3VyYWN5IHBlciBjbGFzcyAqL1xyXG5jb25zdCBhY2N1cmFjeXBlcmNsYXNzOiBhbnkgPSAgYXdhaXQgdGhpcy5jYWxjdWxhdGVBY2N1cmFjeVBlckNsYXNzKFRlYWNoYWJsZU1vYmlsZU5ldC52YWxpZGF0aW9uRGF0YXNldCk7XHJcbi8vIGNvbnNvbGUubG9nKFwiQWNjdXJhY3kgcGVyIGNsYXNzOiBcIiwgYWNjdXJhY3lwZXJjbGFzcyk7XHJcblxyXG4vL0NvbmZ1c2lvbiBtYXRyaXhcclxuLy8gQ2FsbGluZyB0Zi5jb25mdXNpb25NYXRyaXgoKSBtZXRob2QgXHJcbmNvbnN0IG91dHB1dCA9IHRmLm1hdGguY29uZnVzaW9uTWF0cml4KCBhY2N1cmFjeXBlcmNsYXNzLnJlZmVyZW5jZSwgYWNjdXJhY3lwZXJjbGFzcy5wcmVkaWN0aW9ucywgVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoKTsgXHJcbiAgXHJcbi8vIFByaW50aW5nIG91dHB1dCBcclxub3V0cHV0LnByaW50KClcclxuY29uc3QgY29uZnVzaW9uX21hdHJpeD0gIG91dHB1dC5kYXRhU3luYygpO1xyXG5cclxuLy8gY29uc29sZS5sb2coY29uZnVzaW9uX21hdHJpeCk7XHJcbi8vIGNvbnNvbGUubG9nKGNvbmZ1c2lvbl9tYXRyaXhbVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoICsgVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoXSk7XHJcblxyXG5jb25zdCBhY2N1cmFjeSA9IFtdO1xyXG5cclxuZm9yKGxldCBpPTA7IGk8VGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoO2krKyl7XHJcblxyXG4gIGFjY3VyYWN5LnB1c2goY29uZnVzaW9uX21hdHJpeFtUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lcy5sZW5ndGgqaSsgaV0vVGVhY2hhYmxlTW9iaWxlTmV0Lm51bVZhbGlkYXRpb24pXHJcbn1cclxuXHJcbmNvbnNvbGUubG9nKFwiQWNjdXJhY3kgcGVyIGNsYXNzOiBcIiwgYWNjdXJhY3kpO1xyXG5cclxuZm9yKGxldCBpPTA7IGk8VGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoO2krKyl7XHJcblxyXG4gIGNvbmZ1c2lvbl9tYXRyaXhfcmVjaXBpZW50LnB1c2goW10pO1xyXG5cclxuICBmb3IobGV0IGo9MDsgajxUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lcy5sZW5ndGg7aisrKXtcclxuICAgIGNvbmZ1c2lvbl9tYXRyaXhfcmVjaXBpZW50W2ldLnB1c2goW10pO1xyXG5cclxuICAgIGNvbmZ1c2lvbl9tYXRyaXhfcmVjaXBpZW50W2ldW2pdPSBjb25mdXNpb25fbWF0cml4W1RlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aCppKyBqXS9UZWFjaGFibGVNb2JpbGVOZXQubnVtVmFsaWRhdGlvblxyXG4gICAgY29uZnVzaW9uX21hdHJpeF9yZWNpcGllbnRbaV1bal09KGNvbmZ1c2lvbl9tYXRyaXhfcmVjaXBpZW50W2ldW2pdLnRvRml4ZWQoMikpKjEwMDtcclxuICB9XHJcblxyXG4gIC8vIGFjY3VyYWN5LnB1c2goY29uZnVzaW9uX21hdHJpeFtUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lcy5sZW5ndGgqaSsgaV0vVGVhY2hhYmxlTW9iaWxlTmV0Lm51bVZhbGlkYXRpb24pXHJcbn1cclxuXHJcbmNvbnNvbGUubG9nKFwiQ29uZnVzaW9uIG1hdHJpeCBhcyBhIG1hdHJpeFwiKVxyXG5jb25zb2xlLmxvZyhjb25mdXNpb25fbWF0cml4X3JlY2lwaWVudCk7XHJcblxyXG5yZXR1cm4gYWNjdXJhY3kubWFwKChlbGVtOiBhbnkpPT5lbGVtLnRvRml4ZWQoMikqMTAwKTtcclxufVxyXG5cclxuIFxyXG4gYXN5bmMgbG9hZEltYWdlcyhudW1iZXJfb2Zfc3BlY2llczogbnVtYmVyLCBjbGFzc2VzX25hbWVzOiBzdHJpbmdbXSwgb3B0aW9uczogb2JqZWN0KXtcclxuICAgICAgICBUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lcz1jbGFzc2VzX25hbWVzO1xyXG4gICAgXHJcbiAgICAgICAgYXdhaXQgdGhpcy5hZGRfc3BlY2llcyhudW1iZXJfb2Zfc3BlY2llcywgb3B0aW9ucyk7ICAgICAgICBcclxuXHJcbn1cclxuXHJcbmFzeW5jIGFkZF9zcGVjaWVzKG51bWJlcl9vZl9zcGVjaWVzOiBudW1iZXIsIG9wdGlvbnM6IG9iamVjdCl7XHJcbiAgXHJcbiAgICAvL0xvYWRpbmcgZmVhdHVyZSBtb2RlbCwgdXNlZCB0byBjcmVhdGUgZmVhdHVyZXMgZnJvbSBpbWFnZXNcclxuICAgIC8vICBhd2FpdCB0aGlzLmxvYWRGZWF0dXJlTW9kZWwoKTtcclxuXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIC8vIHRoaXMuYWRkX2ltYWdlcyh0aGlzLmNsYXNzZXNfbmFtZXNbaV0sIG51bWJlcl9vZl9zcGVjaWVzLCBvcHRpb25zKTtcclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIFxyXG4gKiBAcGFyYW0gbmFtZSAtIG5hbWUgb2YgdGhlIGNsYXNzIHJlY2VpdmluZyBhbiBleGFtcGxlXHJcbiAqIEBwYXJhbSBudW1iZXJfb2Zfc3BlY2llcyAtIGhvdyBtYW55IGltYWdlcyB0byBhZGRcclxuICogQHBhcmFtIG9wdGlvbnMgLSBkZXRhaWxzIG9uIHRoZSBsb2NhdGlvbiBvZiB0aGUgaW1hZ2VzXHJcbiAqL1xyXG5hc3luYyBhZGRfaW1hZ2VzKG5hbWU6IHN0cmluZywgbnVtYmVyX29mX3NwZWNpZXM6IG51bWJlciwgb3B0aW9uczogYW55KXsgICBcclxuXHJcbiAgICBjb25zdCBjbGFzc19hZGQ6IGFueT0gW107XHJcblxyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1iZXJfb2Zfc3BlY2llczsgaSsrKSB7ICAgICAgXHJcbiAgICAvLyAgIGNsYXNzX2FkZC5wdXNoKGAke29wdGlvbnMuYmFzZX0vJHtuYW1lfS8ke29wdGlvbnMuZmlsZV9uYW1lfSAke2l9LiR7b3B0aW9ucy5maWxlX2V4dGVuc2lvbn1gKTtcclxuICAgICAgICBcclxuICAgICAgICAvL1VwbG9hZGluZyBpbWFnZXNcclxuICAgICAgICBjb25zdCBjYWtlID0gbmV3IEltYWdlKCk7ICAgICAgICBcclxuICAgICAgICAvLyBjYWtlLnNyYyA9IGAke29wdGlvbnMuYmFzZX0vJHtuYW1lfS8ke29wdGlvbnMuZmlsZV9uYW1lfSAke2l9LiR7b3B0aW9ucy5maWxlX2V4dGVuc2lvbn1gO1xyXG4gICAgICAgIGNha2UuaGVpZ2h0PTIyNDtcclxuICAgICAgICBjYWtlLndpZHRoPTIyNDtcclxuICAgICAgICBjYWtlLnNyYz1cIi4vYXNzZXRzL2RhdGFzZXQvQ2FuJUMzJUExcmlvLWRhLVRlcnJhL2ltYWdlJTIwMC5qcGVnXCJcclxuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkltYWdlIGxvY2F0aW9uOiBcIiwgY2FrZS5zcmMgKVxyXG5cclxuICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XHJcbiAgICAgICAgICAgIGNha2Uub25sb2FkID0gKCkgPT4ge1xyXG5cclxuICAgICAgICAgICAgICAgIC8vRmluZGluZyB0aGUgY29ycmVzcG9uZGVudCBpbmRleCBvZiB0aGUgY2xhc3Mgd2l0aCBuYW1lIGdpdmVuXHJcbiAgICAgICAgICAgICAgICBjb25zdCBpbmRleD0gVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMuZmluZEluZGV4KChlbGVtKT0+ZWxlbT09PW5hbWUpXHJcblxyXG4gICAgICAgICAgICAgICAgLy8gdGhpcy5hZGRFeGFtcGxlKGluZGV4LCBjYWtlKTtcclxuXHJcbiAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xyXG4gICAgICAgICAgICB9O1xyXG4gIFxyXG4gICAgICAgICAgICBjYWtlLm9uZXJyb3IgPSAoZXJyb3IpID0+IHtcclxuICAgICAgICAgICAgICAvLyBIYW5kbGUgZXJyb3IgaWYgdGhlIGltYWdlIGZhaWxzIHRvIGxvYWRcclxuICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgICAgfSk7XHJcbiAgfVxyXG5cclxuICAvLyB0aGlzLmNsYXNzZXMucHVzaCh7bmFtZTogbmFtZSwgaW1hZ2VzOiBjbGFzc19hZGR9KSAgXHJcblxyXG4gIH1cclxuXHJcblxyXG5cclxuICAgICAgXHJcbi8qKlxyXG4gKiBUaGlzIG1ldGhvZCB3aWxsIHRyYW5zZm9ybSBpbWFnZXMgaW50byB0ZW5zb3JzXHJcbiAqIEBwYXJhbSBudW1iZXJfb2ZfY2xhc3NlcyAtIG51bWJlciBvZiBjbGFzc2VzXHJcbiAqIEBwYXJhbSBjbGFzc2VzX25hbWVzIC0gbmFtZSBvZiBlYWNoIGNsYXNzXHJcbiAqL1xyXG5hc3luYyBjcmVhdGVUZW5zb3JzKG51bWJlcl9vZl9jbGFzc2VzOiBudW1iZXIsIGNsYXNzZXNfbmFtZXM6IHN0cmluZ1tdKSB7XHJcblxyXG4gICAgbGV0IG91dHB1dDogYW55ID0gW107XHJcblxyXG4gICAgLyoqIFRoZXJlIGlzIGEgZnVuY3Rpb24gb24gVGVuc29yRmxvdy5qcyB0aGF0IGFsc28gZG9lcyB0aGF0ICovXHJcbiAgICBjb25zdCBzaWduYXR1cmVzPSBuZXcgVXRpbCgpLmlkZW50aXR5TWF0cml4KG51bWJlcl9vZl9jbGFzc2VzKTtcclxuXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bWJlcl9vZl9jbGFzc2VzOyBpKyspIHtcclxuXHJcbiAgICAgICAgdGhpcy5jbGFzc2VzW2ldLnNpZ25hdHVyZT1zaWduYXR1cmVzW2ldO1xyXG4gICAgICAgIHRoaXMuY2xhc3Nlc1tpXS5uYW1lPWNsYXNzZXNfbmFtZXNbaV07XHJcblxyXG4gICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5jbGFzc2VzW2ldLmltYWdlcy5sZW5ndGg7IGorKykge1xyXG5cclxuXHJcbiAgICAgICAgfVxyXG5cclxuICAgIH1cclxufVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQWRkIGEgc2FtcGxlIG9mIGRhdGEgdW5kZXIgdGhlIHByb3ZpZGVkIGNsYXNzTmFtZVxyXG4gICAgICogQHBhcmFtIGNsYXNzTmFtZSB0aGUgY2xhc3NpZmljYXRpb24gdGhpcyBleGFtcGxlIGJlbG9uZ3MgdG9cclxuICAgICAqIEBwYXJhbSBzYW1wbGUgdGhlIGltYWdlIC8gdGVuc29yIHRoYXQgYmVsb25ncyBpbiB0aGlzIGNsYXNzaWZpY2F0aW9uXHJcbiAgICAgKi9cclxuICAgIC8vIHB1YmxpYyBhc3luYyBhZGRFeGFtcGxlKGNsYXNzTmFtZTogbnVtYmVyLCBzYW1wbGU6IEhUTUxDYW52YXNFbGVtZW50IHwgdGYuVGVuc29yKSB7XHJcbnB1YmxpYyBzdGF0aWMgYXN5bmMgYWRkRXhhbXBsZShjbGFzc05hbWU6IG51bWJlciwgbmFtZTogc3RyaW5nLCBzYW1wbGU6IEhUTUxJbWFnZUVsZW1lbnQgfCBIVE1MQ2FudmFzRWxlbWVudCB8IHRmLlRlbnNvcikge1xyXG5cclxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJBZGRpbmcgYSBuZXcgZXhhbXBsZS4uLlwiKSBcclxuICAgICAgICAgIFxyXG4gICAgICAgICAgICBjb25zdCBjYXAgPSBpc1RlbnNvcihzYW1wbGUpID8gc2FtcGxlIDogY2FwdHVyZShzYW1wbGUpO1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgLy8gaWYoIXRoaXMudHJ1bmNhdGVkTW9kZWwpXHJcbiAgICAgICAgICAgIC8vICAgYXdhaXQgdGhpcy5sb2FkRmVhdHVyZU1vZGVsKCk7XHJcblxyXG4gICAgICAgICAgICAvL0dldHRpbmcgdGhlIGZlYXR1cmVzXHJcbiAgICAgICAgICAgIGNvbnN0IGV4YW1wbGUgPSB0aGlzLnRydW5jYXRlZE1vZGVsLnByZWRpY3QoY2FwKSBhcyB0Zi5UZW5zb3I7XHJcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwiU2hhcGUgYWZ0ZXIgZmVhdHVyZSBleHRyYWN0aW9uOiBcIiwgZXhhbXBsZS5zaGFwZSkgICAgICAgICAgXHJcbiAgICAgICAgICAgXHJcblxyXG4gICAgICAgICAgICBjb25zdCBhY3RpdmF0aW9uID0gZXhhbXBsZS5kYXRhU3luYygpIGFzIEZsb2F0MzJBcnJheTtcclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIC8vVmVyeSBpbXBvcnRhbnQgdG8gY2xlYW4gdGhlIG1lbW9yeSBhZnRlcm1hdGgsIGl0IG1ha2VzIHRoZSBkaWZmZXJlbmNlXHJcbiAgICAgICAgICAgIGNhcC5kaXNwb3NlKCk7XHJcbiAgICAgICAgICAgIGV4YW1wbGUuZGlzcG9zZSgpO1xyXG4gICAgXHJcbiAgICAgICAgICAgIC8vIC8vQWNjZXNzaW5nIHRoZSBpbnN0YW5jZSB2YXJpYWJsZSwgbm90IHRoZSBsb2NhbCBvbmVzXHJcbiAgICAgICAgICAgIC8vIC8vIHNhdmUgc2FtcGxlcyBvZiBlYWNoIGNsYXNzIHNlcGFyYXRlbHkgXHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICBpZighVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzW2NsYXNzTmFtZV0pXHJcbiAgICAgICAgICAgICAgLy9hbmQgYW4gZW1wdHkgYXJyYXksIG1ha2Ugc3VyZSB0aGVyZSBpcyBub3QgZW1wdHkgZWxlbWVudHMuIFxyXG4gICAgICAgICAgICAgIC8vaXQgd2lsbCBjcmVhdGUgaXNzdWUgd2hlbiB0cmFuc2Zvcm1pbmcgdG8gdGVuc29yc1xyXG4gICAgICAgICAgICAgIFRlYWNoYWJsZU1vYmlsZU5ldC5leGFtcGxlc1tjbGFzc05hbWVdPVtdXHJcblxyXG5cclxuICAgICAgICAgICAgICBpZighVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXNbY2xhc3NOYW1lXSlcclxuICAgICAgICAgICAgICAgIC8vU2F2aW5nIHRoZSBsYWJsZSB3aGVuIGl0IGZpcnN0IGFwcGVhcnNcclxuICAgICAgICAgICAgICAgIFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzW2NsYXNzTmFtZV09bmFtZTtcclxuXHJcbiAgICAgICAgICAgIFRlYWNoYWJsZU1vYmlsZU5ldC5leGFtcGxlc1tjbGFzc05hbWVdLnB1c2goYWN0aXZhdGlvbik7XHJcbiAgICBcclxuICAgICAgICAgICAgLy8gLy8gaW5jcmVhc2Ugb3VyIHNhbXBsZSBjb3VudGVyXHJcbiAgICAgICAgICAgIFRlYWNoYWJsZU1vYmlsZU5ldC50b3RhbFNhbXBsZXMrKztcclxuICAgICAgICB9XHJcblxyXG5cclxuICAgLyoqXHJcbiAgICAgKiBwcm9jZXNzIHRoZSBjdXJyZW50IGV4YW1wbGVzIHByb3ZpZGVkIHRvIGNhbGN1bGF0ZSBsYWJlbHMgYW5kIGZvcm1hdFxyXG4gICAgICogaW50byBwcm9wZXIgdGYuZGF0YS5EYXRhc2V0XHJcbiAgICAgKi9cclxuICAgc3RhdGljIHByZXBhcmUoKSB7XHJcbiAgICBmb3IgKGNvbnN0IGNsYXNzZXMgaW4gVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzKXtcclxuICAgICAgICBpZiAoY2xhc3Nlcy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdBZGQgc29tZSBleGFtcGxlcyBiZWZvcmUgdHJhaW5pbmcnKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgZGF0YXNldHM6IGFueSA9IHRoaXMuY29udmVydFRvVGZEYXRhc2V0KCk7XHJcblxyXG4gICAgdGhpcy50cmFpbkRhdGFzZXQgPSBkYXRhc2V0cy50cmFpbkRhdGFzZXQ7XHJcbiAgICB0aGlzLnZhbGlkYXRpb25EYXRhc2V0ID0gZGF0YXNldHMudmFsaWRhdGlvbkRhdGFzZXQ7XHJcbn1cclxuXHJcbnB1YmxpYyBwcmVwYXJlRGF0YXNldCgpIHtcclxuICBmb3IgKGxldCBpID0gMDsgaSA8IFRlYWNoYWJsZU1vYmlsZU5ldC5udW1DbGFzc2VzOyBpKyspIHtcclxuICAgIC8vRGlmZmVyZW50IGZyb20gdGhlIG9yaWdpbmFsIGltcGxlbWVudGF0aW9uIG9mIFRNLCBtaW5lIGlzIHVzaW5nIGV4YW1wbGUgYXMgc3RhdGljLlxyXG4gICAgLy9UaGUgZ29hbCBpcyBzYXZpbmcgbWVtb3J5IGJ5IHVzaW5nIGEgc2luZ2xlIGluc3RhbmNlIG9mIHRoZSB2YXJpYWJsZVxyXG4gICAgVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzW2ldID0gW107XHJcbiAgfVxyXG59XHJcblxyXG4gXHJcbiAgICAvLyBPcHRpb25hbCBzZWVkIHRvIG1ha2Ugc2h1ZmZsaW5nIG9mIGRhdGEgcHJlZGljdGFibGVcclxuICAgIHN0YXRpYyBzZWVkOiBzZWVkcmFuZG9tLnBybmc7XHJcblxyXG5cclxuXHJcbiAgICBcclxuLyoqXHJcbiAgICAgKiBQcm9jZXNzIHRoZSBleGFtcGxlcyBieSBmaXJzdCBzaHVmZmxpbmcgcmFuZG9tbHkgcGVyIGNsYXNzLCB0aGVuIGFkZGluZ1xyXG4gICAgICogb25lLWhvdCBsYWJlbHMsIHRoZW4gc3BsaXR0aW5nIGludG8gdHJhaW5pbmcvdmFsaWRhdGlvbiBkYXRzZXRzLCBhbmQgZmluYWxseVxyXG4gICAgICogc29ydGluZyBvbmUgbGFzdCB0aW1lXHJcbiAgICAgKi9cclxuIFxyXG5zdGF0aWMgY29udmVydFRvVGZEYXRhc2V0KCkge1xyXG5cclxuICAgICAgICAgLy8gZmlyc3Qgc2h1ZmZsZSBlYWNoIGNsYXNzIGluZGl2aWR1YWxseVxyXG4gICAgICAgIC8vIFRPRE86IHdlIGNvdWxkIGJhc2ljYWxseSByZXBsaWNhdGUgdGhpcyBieSBpbnN0ZXJ0aW5nIHJhbmRvbWx5XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBUZWFjaGFibGVNb2JpbGVOZXQuZXhhbXBsZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgIFRlYWNoYWJsZU1vYmlsZU5ldC5leGFtcGxlc1tpXSA9IGZpc2hlcllhdGVzKFRlYWNoYWJsZU1vYmlsZU5ldC5leGFtcGxlc1tpXSwgdGhpcy5zZWVkKSBhcyBGbG9hdDMyQXJyYXlbXTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gdGhlbiBicmVhayBpbnRvIHZhbGlkYXRpb24gYW5kIHRlc3QgZGF0YXNldHNcclxuICAgICAgbGV0IHRyYWluRGF0YXNldDogU2FtcGxlW10gPSBbXTtcclxuICAgICAgbGV0IHZhbGlkYXRpb25EYXRhc2V0OiBTYW1wbGVbXSA9IFtdO1xyXG5cclxuICAgICAgLy8gZm9yIGVhY2ggY2xhc3MsIGFkZCBzYW1wbGVzIHRvIHRyYWluIGFuZCB2YWxpZGF0aW9uIGRhdGFzZXRcclxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBUZWFjaGFibGVNb2JpbGVOZXQuZXhhbXBsZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgXHJcbiAgICAgICAgLy8gY29uc29sZS5sb2coXCJOdW1iZXIgb2YgY2xhc3NlczogXCIsIFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aCk7XHJcblxyXG4gICAgICAgIGNvbnN0IHkgPSBmbGF0T25lSG90KGksIFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aCk7XHJcblxyXG4gICAgICAgIGNvbnN0IGNsYXNzTGVuZ3RoID0gVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzW2ldLmxlbmd0aDtcclxuXHJcbiAgICAgICAgLy8gY29uc29sZS5sb2coXCJOdW1iZXIgb2YgZWxlbWVudHMgcGVyIGNsYXNzOiBcIiwgY2xhc3NMZW5ndGgpO1xyXG5cclxuICAgICAgICBjb25zdCBudW1WYWxpZGF0aW9uID0gTWF0aC5jZWlsKFZBTElEQVRJT05fRlJBQ1RJT04gKiBjbGFzc0xlbmd0aCk7XHJcbiAgICAgICAgY29uc3QgbnVtVHJhaW4gPSBjbGFzc0xlbmd0aCAtIG51bVZhbGlkYXRpb247XHJcblxyXG4gICAgICAgIHRoaXMubnVtVmFsaWRhdGlvbj1udW1WYWxpZGF0aW9uO1xyXG4gICAgICAgXHJcbiAgICAgICAgLyoqSXQgaXMgdmlzaXRpbmcgcGVyIGNsYXNzLCB0aHVzLCBpdCBpcyBwb3NzaWJsZSB0byBmaXggeSwgdGhlIHRhcmdldCBsYWJlbCAqL1xyXG4gICAgIFxyXG4gICAgICBjb25zdCBjbGFzc1RyYWluID0gdGhpcy5leGFtcGxlc1tpXS5zbGljZSgwLCBudW1UcmFpbikubWFwKChkYXRhQXJyYXkpID0+IHtcclxuICAgICAgICAgIHJldHVybiB7IGRhdGE6IGRhdGFBcnJheSwgbGFiZWw6IHkgfTtcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBjb25zdCBjbGFzc1ZhbGlkYXRpb24gPSB0aGlzLmV4YW1wbGVzW2ldLnNsaWNlKG51bVRyYWluKS5tYXAoKGRhdGFBcnJheSkgPT4ge1xyXG4gICAgICAgICAgcmV0dXJuIHsgZGF0YTogZGF0YUFycmF5LCBsYWJlbDogeSB9O1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHRyYWluRGF0YXNldCA9IHRyYWluRGF0YXNldC5jb25jYXQoY2xhc3NUcmFpbik7XHJcbiAgICAgIHZhbGlkYXRpb25EYXRhc2V0ID0gdmFsaWRhdGlvbkRhdGFzZXQuY29uY2F0KGNsYXNzVmFsaWRhdGlvbik7IFxyXG5cclxuXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKFwiVHJhaW5pbmcgZWxlbWVudDogXCIsIHRyYWluRGF0YXNldFt0cmFpbkRhdGFzZXQubGVuZ3RoLTFdKSAgICAgIFxyXG4gICAgICAvLyBjb25zb2xlLmxvZyhcIlRyYWluaW5nIGxlbmd0aDogXCIsIHRyYWluRGF0YXNldC5sZW5ndGgpXHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKFwidmFsaWRhdGlvbiBsZW5ndGg6IFwiLCB2YWxpZGF0aW9uRGF0YXNldC5sZW5ndGgpO1xyXG5cclxuICAgICAgXHJcbiAgICAgICAgLy8gZmluYWxseSBzaHVmZmxlIGJvdGggdHJhaW4gYW5kIHZhbGlkYXRpb24gZGF0YXNldHNcclxuICAgICAgICB0cmFpbkRhdGFzZXQgPSBmaXNoZXJZYXRlcyh0cmFpbkRhdGFzZXQsIHRoaXMuc2VlZCkgYXMgU2FtcGxlW107XHJcbiAgICAgICAgdmFsaWRhdGlvbkRhdGFzZXQgPSBmaXNoZXJZYXRlcyh2YWxpZGF0aW9uRGF0YXNldCwgdGhpcy5zZWVkKSBhcyBTYW1wbGVbXTtcclxuXHJcbiAgICAgICAgY29uc3QgdHJhaW5YID0gdGYuZGF0YS5hcnJheSh0cmFpbkRhdGFzZXQubWFwKHNhbXBsZSA9PiBzYW1wbGUuZGF0YSkpO1xyXG4gICAgICAgIGNvbnN0IHZhbGlkYXRpb25YID0gdGYuZGF0YS5hcnJheSh2YWxpZGF0aW9uRGF0YXNldC5tYXAoc2FtcGxlID0+IHNhbXBsZS5kYXRhKSk7XHJcbiAgICAgICAgY29uc3QgdHJhaW5ZID0gdGYuZGF0YS5hcnJheSh0cmFpbkRhdGFzZXQubWFwKHNhbXBsZSA9PiBzYW1wbGUubGFiZWwpKTtcclxuICAgICAgICBjb25zdCB2YWxpZGF0aW9uWSA9IHRmLmRhdGEuYXJyYXkodmFsaWRhdGlvbkRhdGFzZXQubWFwKHNhbXBsZSA9PiBzYW1wbGUubGFiZWwpKTtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyByZXR1cm4gdGYuZGF0YSBkYXRhc2V0IG9iamVjdHNcclxuICAgICAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICAgIHRyYWluRGF0YXNldDogdGYuZGF0YS56aXAoeyB4czogdHJhaW5YLCAgeXM6IHRyYWluWX0pLFxyXG4gICAgICAgICAgICAgICAgICB2YWxpZGF0aW9uRGF0YXNldDogdGYuZGF0YS56aXAoeyB4czogdmFsaWRhdGlvblgsICB5czogdmFsaWRhdGlvbll9KVxyXG4gICAgICAgICAgICAgIH07XHJcblxyXG5cclxufVxyXG5cclxuZGF0YXNldEZvckV2YWx1YXRpb24oKXtcclxuXHJcbn1cclxuXHJcbi8qKk1ldHJpY3MgKi9cclxuXHJcbnN0YXRpYyBmZWF0dXJlX2F1eDogYW55O1xyXG5zdGF0aWMgdGFyZ2V0X2F1eDogYW55O1xyXG5cclxuYXN5bmMgZXZhbHVhdGUoKXtcclxuICAgXHJcbiAgLy9DaGVjayBvZiB0aGUgZmVhdHVyZXMgaGF2ZSBhbHJlYWR5IGJlZW4gY2FsY3VsYXRlZFxyXG4gIC8qKkZvciBhdm9pZGluZyByZWNhbGN1bGF0aW5nIHRoZSBmZWF0dXJlcyBldmVyeSBnZW5lcmF0aW9uICovXHJcbiAgaWYoIVRlYWNoYWJsZU1vYmlsZU5ldC5mZWF0dXJlX2F1eCl7XHJcbiAgICBjb25zdCBmZWF0dXJlczogYW55PVtdO1xyXG4gICAgY29uc3QgdGFyZ2V0czogYW55PVtdO1xyXG5cclxuICBmb3IgKGxldCBpID0gMDsgaSA8IFRlYWNoYWJsZU1vYmlsZU5ldC5leGFtcGxlcy5sZW5ndGg7IGkrKykge1xyXG5cclxuICAgIGNvbnN0IHkgPSBmbGF0T25lSG90KGksIFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aCk7XHJcbiAgICAvL0ZvciBjbGFzcyBpLCBwdXNoIGFsbCB0aGUgZXhhbXBsZXMuXHJcbiAgICBUZWFjaGFibGVNb2JpbGVOZXQuZXhhbXBsZXNbaV0uZm9yRWFjaCgoZWxlbW4pPT57XHJcblxyXG4gICAgICAgLy9QdXNoaW5nIHRoZSB0YXJnZXQgc2lnbmF0dXJlXHJcbiAgICAgICB0YXJnZXRzLnB1c2goeSk7XHJcbiAgICAgICBcclxuICAgICAgIC8vUHVzaGluZyBmZWF0dXJlc1xyXG4gICAgICAgZmVhdHVyZXMucHVzaChlbGVtbilcclxuICAgIH0pXHJcblxyXG4gIH0gIFxyXG5cclxuICBUZWFjaGFibGVNb2JpbGVOZXQuZmVhdHVyZV9hdXg9IHRmLnRlbnNvcihmZWF0dXJlcyk7XHJcbiAgVGVhY2hhYmxlTW9iaWxlTmV0LnRhcmdldF9hdXg9IHRmLnRlbnNvcih0YXJnZXRzKTtcclxuXHJcbiAgfSBcclxuXHJcbiAgLy9FdmFsdWF0aW5nIHRoZSBtb2RlbFxyXG4gIGNvbnN0IGF1eDogYW55ID0gdGhpcy50cmFpbmluZ01vZGVsLmV2YWx1YXRlKFRlYWNoYWJsZU1vYmlsZU5ldC5mZWF0dXJlX2F1eCwgVGVhY2hhYmxlTW9iaWxlTmV0LnRhcmdldF9hdXgpO1xyXG4gIFxyXG4gIC8vUmV0dXJuIGp1c3QgdGhlIGFjY3VyYWN5XHJcbiAgcmV0dXJuIGF1eFsxXS5kYXRhU3luYygpWzBdO1xyXG5cclxuXHJcbn1cclxuXHJcblxyXG4vLyBhc3luYyBldmFsdWF0ZSgpe1xyXG5cclxuLy8gICBjb25zdCBmZWF0dXJlczogYW55PVtdO1xyXG4vLyAgIGNvbnN0IHRhcmdldHM6IGFueT1bXTtcclxuXHJcbi8vICAgZm9yIChsZXQgaSA9IDA7IGkgPCBUZWFjaGFibGVNb2JpbGVOZXQuZXhhbXBsZXMubGVuZ3RoOyBpKyspIHtcclxuXHJcbi8vICAgICBjb25zdCB5ID0gZmxhdE9uZUhvdChpLCBUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lcy5sZW5ndGgpO1xyXG4gICAgXHJcblxyXG5cclxuLy8gICAgIC8vRm9yIGNsYXNzIGksIHB1c2ggYWxsIHRoZSBleGFtcGxlcy5cclxuLy8gICAgIFRlYWNoYWJsZU1vYmlsZU5ldC5leGFtcGxlc1tpXS5mb3JFYWNoKChlbGVtbik9PntcclxuXHJcbi8vICAgICAgICAvL1B1c2hpbmcgdGhlIHRhcmdldCBzaWduYXR1cmVcclxuLy8gICAgICAgIHRhcmdldHMucHVzaCh5KTtcclxuICAgICAgIFxyXG4vLyAgICAgICAgLy9QdXNoaW5nIGZlYXR1cmVzXHJcbi8vICAgICAgICBmZWF0dXJlcy5wdXNoKGVsZW1uKVxyXG4vLyAgICAgfSlcclxuXHJcbi8vICAgfSAgXHJcblxyXG4vLyAgIGNvbnN0IGF1eF9mZWF0dXJlcz0gdGYudGVuc29yKGZlYXR1cmVzKTtcclxuLy8gICBjb25zdCBhdXhfdGFyZ2V0PSB0Zi50ZW5zb3IodGFyZ2V0cyk7XHJcblxyXG4gIFxyXG4vLyAgIC8vIGNvbnNvbGUubG9nKFwiVGVuc29yIHN0YWNrIGZvciBldmFsdWF0aW9uOiBcIiwgYXV4X2ZlYXR1cmVzLnNoYXBlKVxyXG5cclxuLy8gICBjb25zdCBhdXg6IGFueSA9IHRoaXMudHJhaW5pbmdNb2RlbC5ldmFsdWF0ZShhdXhfZmVhdHVyZXMsIGF1eF90YXJnZXQpO1xyXG5cclxuXHJcbi8vICAgcmV0dXJuIGF1eFsxXS5kYXRhU3luYygpWzBdO1xyXG5cclxuXHJcbi8vIH1cclxuXHJcblxyXG4vKioqIEZpbmFsIHN0YXRpc3RpY3MgKi9cclxuLyogXHJcbiAgICAgKiBDYWxjdWxhdGUgZWFjaCBjbGFzcyBhY2N1cmFjeSB1c2luZyB0aGUgdmFsaWRhdGlvbiBkYXRhc2V0XHJcbiovXHJcbnB1YmxpYyBhc3luYyBjYWxjdWxhdGVBY2N1cmFjeVBlckNsYXNzKHZhbGlkYXRpb25EYXRhOiBhbnkpIHtcclxuXHJcbiAgY29uc3QgdmFsaWRhdGlvblhzID0gVGVhY2hhYmxlTW9iaWxlTmV0LnZhbGlkYXRpb25EYXRhc2V0Lm1hcEFzeW5jKGFzeW5jIChkYXRhc2V0OiBUZW5zb3JDb250YWluZXIpID0+IHtcclxuICAgIHJldHVybiAoZGF0YXNldCBhcyB7IHhzOiBUZW5zb3JDb250YWluZXIsIHlzOiBUZW5zb3JDb250YWluZXJ9KS54cztcclxufSk7XHJcblxyXG5jb25zdCB2YWxpZGF0aW9uWXMgPSBUZWFjaGFibGVNb2JpbGVOZXQudmFsaWRhdGlvbkRhdGFzZXQubWFwQXN5bmMoYXN5bmMgKGRhdGFzZXQ6IFRlbnNvckNvbnRhaW5lcikgPT4ge1xyXG4gICAgcmV0dXJuIChkYXRhc2V0IGFzIHsgeHM6IFRlbnNvckNvbnRhaW5lciwgeXM6IFRlbnNvckNvbnRhaW5lcn0pLnlzO1xyXG59KTtcclxuXHJcbi8vIGNvbnNvbGUubG9nKFwidmFsaWRhdGlvbiBkYXRhc2V0OiBcIiwgdmFsaWRhdGlvblhzKTtcclxuIFxyXG4vLyBjb25zb2xlLmxvZyhcIkZvciBjYWxjdWxhdGluZyBiYXRjaCBzaXplOiBcIiwgdmFsaWRhdGlvbllzKTtcclxuXHJcbi8vIHdlIG5lZWQgdG8gc3BsaXQgb3VyIHZhbGlkYXRpb24gZGF0YSBpbnRvIGJhdGNoZXMgaW4gY2FzZSBpdCBpcyB0b28gbGFyZ2UgdG8gZml0IGluIG1lbW9yeVxyXG5jb25zdCBiYXRjaFNpemUgPSBNYXRoLm1pbih2YWxpZGF0aW9uWXMuc2l6ZSwgMzIpO1xyXG4vLyBjb25zdCBiYXRjaFNpemUgPTE7XHJcblxyXG5jb25zdCBpdGVyYXRpb25zID0gTWF0aC5jZWlsKHZhbGlkYXRpb25Zcy5zaXplIC8gYmF0Y2hTaXplKTtcclxuXHJcbi8vIGNvbnNvbGUubG9nKFwiQmF0Y2ggc2l6ZTogXCIsIGJhdGNoU2l6ZSk7XHJcblxyXG5jb25zdCBiYXRjaGVzWCA9IHZhbGlkYXRpb25Ycy5iYXRjaChiYXRjaFNpemUpO1xyXG5cclxuY29uc3QgYmF0Y2hlc1kgPSB2YWxpZGF0aW9uWXMuYmF0Y2goYmF0Y2hTaXplKTtcclxuY29uc3QgaXRYID0gYXdhaXQgYmF0Y2hlc1guaXRlcmF0b3IoKTtcclxuY29uc3QgaXRZID0gYXdhaXQgYmF0Y2hlc1kuaXRlcmF0b3IoKTtcclxuY29uc3QgYWxsWCA9IFtdO1xyXG5jb25zdCBhbGxZID0gW107XHJcblxyXG5mb3IgKGxldCBpID0gMDsgaSA8IGl0ZXJhdGlvbnM7IGkrKykge1xyXG5cclxuICAgIC8vIDEuIGdldCB0aGUgcHJlZGljdGlvbiB2YWx1ZXMgaW4gYmF0Y2hlc1xyXG4gICAgIGNvbnN0IGJhdGNoZWRYVGVuc29yID0gYXdhaXQgaXRYLm5leHQoKTsgIFxyXG5cclxuICAgIC8vICBjb25zb2xlLmxvZyhcIkJhdGNoIHNpemUgb24gYWNjdXJhY3kgcGVyIGNsYXNzOiBcIiwgYmF0Y2hlZFhUZW5zb3IudmFsdWUuc2hhcGUpO1xyXG5cclxuICAgIGNvbnN0IGJhdGNoZWRYUHJlZGljdGlvblRlbnNvciA9IHRoaXMudHJhaW5pbmdNb2RlbC5wcmVkaWN0KGJhdGNoZWRYVGVuc29yLnZhbHVlKSBhcyB0Zi5UZW5zb3I7XHJcblxyXG4gICAgY29uc3QgYXJnTWF4WCA9IGJhdGNoZWRYUHJlZGljdGlvblRlbnNvci5hcmdNYXgoMSk7IC8vIFJldHVybnMgdGhlIGluZGljZXMgb2YgdGhlIG1heCB2YWx1ZXMgYWxvbmcgYW4gYXhpc1xyXG5cclxuICAgIGFsbFgucHVzaChhcmdNYXhYKTtcclxuXHJcbiAgICAvLyAyLiBnZXQgdGhlIGdyb3VuZCB0cnV0aCBsYWJlbCB2YWx1ZXMgaW4gYmF0Y2hlc1xyXG4gICAgY29uc3QgYmF0Y2hlZFlUZW5zb3IgPSBhd2FpdCBpdFkubmV4dCgpO1xyXG4gICAgY29uc3QgYXJnTWF4WSA9IGJhdGNoZWRZVGVuc29yLnZhbHVlLmFyZ01heCgxKTsgLy8gUmV0dXJucyB0aGUgaW5kaWNlcyBvZiB0aGUgbWF4IHZhbHVlcyBhbG9uZyBhbiBheGlzXHJcblxyXG4gICAgYWxsWS5wdXNoKGFyZ01heFkpO1xyXG4gICAgXHJcbiAgICAvLyAzLiBkaXNwb3NlIG9mIGFsbCBvdXIgdGVuc29yc1xyXG4gICAgIGJhdGNoZWRYVGVuc29yLnZhbHVlLmRpc3Bvc2UoKTtcclxuICAgICBiYXRjaGVkWFByZWRpY3Rpb25UZW5zb3IuZGlzcG9zZSgpO1xyXG4gICAgIGJhdGNoZWRZVGVuc29yLnZhbHVlLmRpc3Bvc2UoKTtcclxufVxyXG5cclxuICAgICAgLy8gY29uY2F0ZW5hdGUgYWxsIHRoZSByZXN1bHRzIG9mIHRoZSBiYXRjaGVzXHJcbiAgICAgIGNvbnN0IHJlZmVyZW5jZSA9IHRmLmNvbmNhdChhbGxZKTsgLy8gdGhpcyBpcyB0aGUgZ3JvdW5kIHRydXRoXHJcbiAgICAgIGNvbnN0IHByZWRpY3Rpb25zID0gdGYuY29uY2F0KGFsbFgpOyAvLyB0aGlzIGlzIHRoZSBwcmVkaWN0aW9uIG91ciBtb2RlbCBpcyBndWVzc2luZ1xyXG4gICAgICBcclxuICAgICAgLy8gY29uc29sZS5sb2coXCJ0aGlzIGlzIHRoZSBncm91bmQgdHJ1dGg6IFwiLCAgcmVmZXJlbmNlLmRhdGFTeW5jKCkpXHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKFwiVGhpcyBpcyB0aGUgcHJlZGljdGlvbiBvdXIgbW9kZWwgaXMgZ3Vlc3Npbmc6IFwiLCAgcHJlZGljdGlvbnMuZGF0YVN5bmMoKSlcclxuXHJcbiAgICAgICAgLy8gb25seSBpZiB3ZSBjb25jYXRlbmF0ZWQgbW9yZSB0aGFuIG9uZSB0ZW5zb3IgZm9yIHByZWZlcmVuY2UgYW5kIHJlZmVyZW5jZVxyXG4gICAgICAgIGlmIChpdGVyYXRpb25zICE9PSAxKSB7XHJcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYWxsWC5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgYWxsWFtpXS5kaXNwb3NlKCk7XHJcbiAgICAgICAgICAgICAgICBhbGxZW2ldLmRpc3Bvc2UoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAvLyAgY29uc29sZS5sb2coXCJMZW5ndHRoOiBcIiwgYXdhaXQgcmVmZXJlbmNlLmRhdGFTeW5jKCkubGVuZ3RoKSAgXHJcbiAgICBcclxuICAgIC8vIGNvbnN0IGFjY3VyYWN5cGVyY2xhc3M9W107XHJcblxyXG4gICAgLy8gY29uc3QgcmVmZXJlbmNlX2F1eD0gYXdhaXQgcmVmZXJlbmNlLmRhdGFTeW5jKCk7XHJcbiAgICAvLyBjb25zdCBwcmVkaWN0aW9uX2F1eD0gYXdhaXQgcHJlZGljdGlvbnMuZGF0YVN5bmMoKTtcclxuICAgIC8vIGNvbnNvbGUubG9nKCBwcmVkaWN0aW9ucy5kYXRhU3luYygpKTtcclxuXHJcbiAgICAvLyByZWZlcmVuY2VfYXV4LmZvckVhY2goKGVsZW1lbnQsIGluZGV4KSA9PiB7XHJcbiAgICAvLyAgIGlmKClcclxuICAgICAgXHJcbiAgICAvLyB9KTsgIFxyXG5cclxuXHJcbiAgICAgICAgcmV0dXJuIHsgcmVmZXJlbmNlLCBwcmVkaWN0aW9ucyB9OyAgXHJcblxyXG59XHJcblxyXG59Ly9lbmQgb2YgY2xhc3NcclxuXHJcblxyXG5cclxuXHJcblxyXG4vKioqU3VwcG9ydCBtZXRob2RzIChoZWxwZXJzKSAqL1xyXG5cclxuY29uc3QgaXNUZW5zb3IgPSAoYzogYW55KTogYyBpcyB0Zi5UZW5zb3IgPT5cclxuICAgIHR5cGVvZiBjLmRhdGFJZCA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIGMuc2hhcGUgPT09ICdvYmplY3QnO1xyXG4vKipcclxuICogQ29udmVydHMgYW4gaW50ZWdlciBpbnRvIGl0cyBvbmUtaG90IHJlcHJlc2VudGF0aW9uIGFuZCByZXR1cm5zXHJcbiAqIHRoZSBkYXRhIGFzIGEgSlMgQXJyYXkuXHJcbiAqL1xyXG5mdW5jdGlvbiBmbGF0T25lSG90KGxhYmVsOiBudW1iZXIsIG51bUNsYXNzZXM6IG51bWJlcikge1xyXG5cclxuICBjb25zdCBsYWJlbE9uZUhvdCA9IG5ldyBBcnJheShudW1DbGFzc2VzKS5maWxsKDApIGFzIG51bWJlcltdO1xyXG4gIGxhYmVsT25lSG90W2xhYmVsXSA9IDE7XHJcblxyXG4gIHJldHVybiBsYWJlbE9uZUhvdDtcclxufVxyXG5cclxuaW50ZXJmYWNlIFNhbXBsZSB7XHJcbiAgZGF0YTogRmxvYXQzMkFycmF5O1xyXG4gIGxhYmVsOiBudW1iZXJbXTtcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiBTaHVmZmxlIGFuIGFycmF5IG9mIEZsb2F0MzJBcnJheSBvciBTYW1wbGVzIHVzaW5nIEZpc2hlci1ZYXRlcyBhbGdvcml0aG1cclxuICogVGFrZXMgYW4gb3B0aW9uYWwgc2VlZCB2YWx1ZSB0byBtYWtlIHNodWZmbGluZyBwcmVkaWN0YWJsZVxyXG4gKi9cclxuZnVuY3Rpb24gZmlzaGVyWWF0ZXMoYXJyYXk6IEZsb2F0MzJBcnJheVtdIHwgU2FtcGxlW10sIHNlZWQ/OiBzZWVkcmFuZG9tLnBybmcpIHtcclxuICBjb25zdCBsZW5ndGggPSBhcnJheS5sZW5ndGg7XHJcblxyXG4gIC8vIG5lZWQgdG8gY2xvbmUgYXJyYXkgb3Igd2UnZCBiZSBlZGl0aW5nIG9yaWdpbmFsIGFzIHdlIGdvb1xyXG4gIGNvbnN0IHNodWZmbGVkID0gYXJyYXkuc2xpY2UoKTtcclxuXHJcbiAgZm9yIChsZXQgaSA9IChsZW5ndGggLSAxKTsgaSA+IDA7IGkgLT0gMSkge1xyXG4gICAgICBsZXQgcmFuZG9tSW5kZXggO1xyXG4gICAgICBpZiAoc2VlZCkge1xyXG4gICAgICAgICAgcmFuZG9tSW5kZXggPSBNYXRoLmZsb29yKHNlZWQoKSAqIChpICsgMSkpO1xyXG4gICAgICB9XHJcbiAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgcmFuZG9tSW5kZXggPSBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAoaSArIDEpKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgW3NodWZmbGVkW2ldLCBzaHVmZmxlZFtyYW5kb21JbmRleF1dID0gW3NodWZmbGVkW3JhbmRvbUluZGV4XSxzaHVmZmxlZFtpXV07XHJcbiAgfVxyXG5cclxuICByZXR1cm4gc2h1ZmZsZWQ7XHJcbn1cclxuIl19
437
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVhY2hhYmxlLWV2b2x1dGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RmanMtZXZvbHV0aW9uL3NyYy9saWIvbW9kZWxzL3RlYWNoYWJsZS1ldm9sdXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGVBQWUsRUFBMEIsTUFBTSxvQkFBb0IsQ0FBQztBQUU3RSxPQUFPLEtBQUssRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRXZDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFdEMsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUlyQyxPQUFPLEtBQUssS0FBSyxNQUFNLHNCQUFzQixDQUFDO0FBSTlDLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxDQUFDO0FBc0JqQzs7O0dBR0c7QUFDSCxNQUFNLFlBQVksR0FBRyxDQUFDLElBQXVCLEVBQUUsRUFBRTtJQUMvQyw4RkFBOEY7SUFDOUYsd0RBQXdEO0lBQ3hELElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFdBQVcsSUFBSSx5QkFBeUIsQ0FBQztJQUNqRSxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLElBQUksSUFBSSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUM1RCxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxZQUFZLElBQUksRUFBRSxDQUFDO0lBQzVDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsSUFBSSxVQUFVLENBQUM7SUFDOUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQztJQUNoQyxpREFBaUQ7SUFDakQsT0FBTyxJQUFnQixDQUFDO0FBQzFCLENBQUMsQ0FBQztBQUVGLE1BQU0sT0FBTyxrQkFBbUIsU0FBUSxlQUFlO0lBRW5ELHVDQUF1QztJQUN2Qzs7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O1lBQ0QsV0FBVyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDckQ7UUFFRCxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsRUFBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUM5RTtJQUVELE9BQU8sUUFBUSxDQUFDO0FBQ2xCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDdXN0b21Nb2JpbGVOZXQsIGxvYWRUcnVuY2F0ZWRNb2JpbGVOZXQgfSBmcm9tIFwiLi9jdXN0b20tbW9iaWxlbmV0XCI7XHJcblxyXG5pbXBvcnQgKiBhcyB0ZiBmcm9tICdAdGVuc29yZmxvdy90ZmpzJztcclxuXHJcbmltcG9ydCB7IGNhcHR1cmUgfSBmcm9tICcuLi91dGlscy90Zic7XHJcbmltcG9ydCB7IENsYXNzIH0gZnJvbSAnLi4vdXRpbHMvY2xhc3MnO1xyXG5pbXBvcnQgeyBVdGlsIH0gZnJvbSBcIi4uL3V0aWxzL3V0aWxcIjtcclxuXHJcbmltcG9ydCAqIGFzIHNlZWRyYW5kb20gZnJvbSAnc2VlZHJhbmRvbSc7XHJcblxyXG5pbXBvcnQgKiBhcyB0ZnZpcyBmcm9tICdAdGVuc29yZmxvdy90ZmpzLXZpcyc7XHJcblxyXG5pbXBvcnQgeyBUZW5zb3JDb250YWluZXIgfSBmcm9tICdAdGVuc29yZmxvdy90ZmpzLWNvcmUvZGlzdC90ZW5zb3JfdHlwZXMnO1xyXG5cclxuY29uc3QgVkFMSURBVElPTl9GUkFDVElPTiA9IDAuMTU7XHJcblxyXG5cclxuXHJcbi8qKlxyXG4gKiB0aGUgbWV0YWRhdGEgdG8gZGVzY3JpYmUgdGhlIG1vZGVsJ3MgY3JlYXRpb24sXHJcbiAqIGluY2x1ZGVzIHRoZSBsYWJlbHMgYXNzb2NpYXRlZCB3aXRoIHRoZSBjbGFzc2VzXHJcbiAqIGFuZCB2ZXJzaW9uaW5nIGluZm9ybWF0aW9uIGZyb20gdHJhaW5pbmcuXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIE1ldGFkYXRhIHtcclxuICB0ZmpzVmVyc2lvbjogc3RyaW5nO1xyXG4gIHRtVmVyc2lvbj86IHN0cmluZztcclxuICBwYWNrYWdlVmVyc2lvbjogc3RyaW5nO1xyXG4gIHBhY2thZ2VOYW1lOiBzdHJpbmc7XHJcbiAgbW9kZWxOYW1lPzogc3RyaW5nO1xyXG4gIHRpbWVTdGFtcD86IHN0cmluZztcclxuICBsYWJlbHM6IHN0cmluZ1tdO1xyXG4gIHVzZXJNZXRhZGF0YT86IHt9O1xyXG4gIGdyYXlzY2FsZT86IGJvb2xlYW47XHJcbiAgaW1hZ2VTaXplPzogbnVtYmVyO1xyXG59XHJcblxyXG4vKipcclxuICogUmVjZWl2ZXMgYSBNZXRhZGF0YSBvYmplY3QgYW5kIGZpbGxzIGluIHRoZSBvcHRpb25hbCBmaWVsZHMgc3VjaCBhcyB0aW1lU3RhbXBcclxuICogQHBhcmFtIGRhdGEgYSBNZXRhZGF0YSBvYmplY3RcclxuICovXHJcbmNvbnN0IGZpbGxNZXRhZGF0YSA9IChkYXRhOiBQYXJ0aWFsPE1ldGFkYXRhPikgPT4ge1xyXG4gIC8vIHV0aWwuYXNzZXJ0KHR5cGVvZiBkYXRhLnRmanNWZXJzaW9uID09PSAnc3RyaW5nJywgKCkgPT4gYG1ldGFkYXRhLnRmanNWZXJzaW9uIGlzIGludmFsaWRgKTtcclxuICAvLyBkYXRhLnBhY2thZ2VWZXJzaW9uID0gZGF0YS5wYWNrYWdlVmVyc2lvbiB8fCB2ZXJzaW9uO1xyXG4gIGRhdGEucGFja2FnZU5hbWUgPSBkYXRhLnBhY2thZ2VOYW1lIHx8ICdAdGVhY2hhYmxlbWFjaGluZS9pbWFnZSc7XHJcbiAgZGF0YS50aW1lU3RhbXAgPSBkYXRhLnRpbWVTdGFtcCB8fCBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCk7XHJcbiAgZGF0YS51c2VyTWV0YWRhdGEgPSBkYXRhLnVzZXJNZXRhZGF0YSB8fCB7fTtcclxuICBkYXRhLm1vZGVsTmFtZSA9IGRhdGEubW9kZWxOYW1lIHx8ICd1bnRpdGxlZCc7XHJcbiAgZGF0YS5sYWJlbHMgPSBkYXRhLmxhYmVscyB8fCBbXTtcclxuICAvLyBkYXRhLmltYWdlU2l6ZSA9IGRhdGEuaW1hZ2VTaXplIHx8IElNQUdFX1NJWkU7XHJcbiAgcmV0dXJuIGRhdGEgYXMgTWV0YWRhdGE7XHJcbn07XHJcblxyXG5leHBvcnQgY2xhc3MgVGVhY2hhYmxlTW9iaWxlTmV0IGV4dGVuZHMgQ3VzdG9tTW9iaWxlTmV0IHtcclxuXHJcbiAgICAvLyBBcnJheSBvZiBhbGwgdGhlIGV4YW1wbGVzIGNvbGxlY3RlZC5cclxuICAgIC8qKlxyXG4gICAgICBJdCBpcyBzdGF0aWMgc2luY2UgYWxsIHRoZSBpbnN0YW5jZSB3aWxsIHNoYXJlIHRoZSBzYW1lIGZlYXR1cmVzLCBmb3Igc2F2aW5nIG1lbW9yeSBhbmQgdGltZS5cclxuICAgICAgVGhlIGlkZWEgaXMgYXZvaWRpbmcgcmVzdG9yaW5nIHRoZSBmZWF0dXJlcyBpbmRpdmlkdWFsbHkgYW5kIGhhdmluZyB0aGUgcmVjYWxjdWxhdGUgdGhlbSBmb3IgZXZlcnkgbmV3XHJcbiAgICAgIGluZGl2aWR1YWxzLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIGV4YW1wbGVzOiBGbG9hdDMyQXJyYXlbXVtdID0gW107XHJcblxyXG4gICAgLy8gTnVtYmVyIG9mIHRvdGFsIHNhbXBsZXNcclxuICAgIHByaXZhdGUgc3RhdGljIHRvdGFsU2FtcGxlcyA9IDA7XHJcblxyXG4gICAgY2xhc3NlczogQ2xhc3NbXT1bXTtcclxuXHJcbiAgICBzdGF0aWMgY2xhc3Nlc19uYW1lczogc3RyaW5nW109W107XHJcblxyXG4gICAgc3RhdGljIG51bUNsYXNzZXM6IG51bWJlcjtcclxuXHJcbiAgICAgICAgLyoqXHJcbiAgICAgKiB0aGUgdHJhaW5pbmcgbW9kZWwgZm9yIHRyYW5zZmVyIGxlYXJuaW5nXHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCB0cmFpbmluZ01vZGVsITogdGYuTGF5ZXJzTW9kZWw7XHJcbiAgdHJhaW5EYXRhc2V0OiBhbnk7XHJcbiAgdmFsaWRhdGlvbkRhdGFzZXQ6IGFueTtcclxuICBzdGF0aWMgdHJhaW5EYXRhc2V0OiBhbnk7XHJcbiAgc3RhdGljIHZhbGlkYXRpb25EYXRhc2V0OiBhbnk7XHJcbiAgc3RhdGljIG51bVZhbGlkYXRpb246IG51bWJlcjtcclxuICBcclxuICAvL1BhcmFtZXRlcnNcclxuICBwcml2YXRlIF9lcG9jaHM6IG51bWJlcj0xMDtcclxuXHJcbiAgY29uc3RydWN0b3IoKXtcclxuICAgIHN1cGVyKCk7XHJcbiAgICB0aGlzLmNyZWF0ZUhlYWQoKTtcclxuICB9XHJcblxyXG4gIC8qKiogKi9cclxuICBzZXQgZXBvY2hzKGVwb2NoczogbnVtYmVyKXtcclxuICAgIHRoaXMuX2Vwb2Nocz1lcG9jaHM7XHJcbiAgfSBcclxuICAvKioqICovXHJcblxyXG4gIC8qKlxyXG4gICAqIFRoaXMgbWV0aG9kIHdpbGwgcmV0dXJuIHRoZSBoZWFkLCB0aGUgdHJhaW5hYmxlIHBhcnQsIHRoZSBwYXJ0IHVuZGVyIGV2b2x1dGlvbi5cclxuICAgKi9cclxuICBnZXRIZWFkKCl7XHJcbiAgICByZXR1cm4gdGhpcy50cmFpbmluZ01vZGVsO1xyXG4gIH1cclxuXHJcbiAvKipcclxuICAqIENyZWF0ZSB0aGUgaGVhZCBmb3IgdHJhbnNmZXIgbGVhcm5pbmcuXHJcbiAgKiBUaGlzIGlzIHRoZSB0cmFpbmFibGUgc2VjdGlvbiBvZiB0aGUgdHJhbnNmZXIgbGVhcm5pbmcuXHJcbiAgKi9cclxuIGNyZWF0ZUhlYWQoKXtcclxuXHJcbiAgY29uc3QgaW5wdXRTaXplPSBUZWFjaGFibGVNb2JpbGVOZXQuZ2V0aW5wdXRTaGFwZSgpO1xyXG5cclxuICB0aGlzLnRyYWluaW5nTW9kZWwgPSB0Zi5zZXF1ZW50aWFsKHtcclxuICAgIGxheWVyczogW1xyXG4gICAgICB0Zi5sYXllcnMuZGVuc2Uoe1xyXG4gICAgICAgIGlucHV0U2hhcGU6IFtpbnB1dFNpemVdLFxyXG4gICAgICAgIHVuaXRzOjEwMCxcclxuICAgICAgICBhY3RpdmF0aW9uOiAncmVsdScsICBcclxuICAgICAgICB1c2VCaWFzOiB0cnVlXHJcbiAgICB9KSxcclxuICAgIHRmLmxheWVycy5kZW5zZSh7ICBcclxuICAgICAgdXNlQmlhczogZmFsc2UsXHJcbiAgICAgIGFjdGl2YXRpb246ICdzb2Z0bWF4JyxcclxuICAgICAgdW5pdHM6IFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aFxyXG4gIH0pXHJcbiAgICBdXHJcbiAgfSk7XHJcblxyXG4gIGNvbnN0IG9wdGltaXplciA9IHRmLnRyYWluLmFkYW0oKTtcclxuICAvLyBjb25zdCBvcHRpbWl6ZXIgPSB0Zi50cmFpbi5ybXNwcm9wKHBhcmFtcy5sZWFybmluZ1JhdGUpO1xyXG5cclxuICB0aGlzLnRyYWluaW5nTW9kZWwuY29tcGlsZSh7XHJcbiAgICAgIG9wdGltaXplcixcclxuICAgICAgLy8gbG9zczogJ2JpbmFyeUNyb3NzZW50cm9weScsXHJcbiAgICAgIGxvc3M6ICdjYXRlZ29yaWNhbENyb3NzZW50cm9weScsXHJcbiAgICAgIG1ldHJpY3M6IFsnYWNjdXJhY3knXVxyXG4gIH0pO1xyXG4gfVxyXG4gXHJcbiBhc3luYyAgdHJhaW4oKXtcclxuXHJcbiAgY29uc3QgdHJhaW5pbmdTdXJmYWNlID0geyBuYW1lOiAnTG9zcyBhbmQgTVNFJywgdGFiOiAnVHJhaW5pbmcnIH07XHJcblxyXG4gIGNvbnN0IGRhdGFzZXQ9IFRlYWNoYWJsZU1vYmlsZU5ldC5jb252ZXJ0VG9UZkRhdGFzZXQoKTtcclxuXHJcbiAgLy9TYWx2aW5nIGEgY29weSBvZiB0aGUgdmFsaWRhdGlvbiBkYXRhc2V0LCBmb3IgbGF0ZXJcclxuICBUZWFjaGFibGVNb2JpbGVOZXQudmFsaWRhdGlvbkRhdGFzZXQ9IGRhdGFzZXQudmFsaWRhdGlvbkRhdGFzZXQ7XHJcblxyXG4gIC8vIGNvbnNvbGUubG9nKFwiRGF0YXNldCBmb3IgdHJhaW5pbmc6IFwiLCBkYXRhc2V0LnRyYWluRGF0YXNldCk7XHJcblxyXG4gIGNvbnN0IHRyYWluRGF0YSA9IGRhdGFzZXQudHJhaW5EYXRhc2V0LmJhdGNoKDMwKTtcclxuICBjb25zdCB2YWxpZGF0aW9uRGF0YSA9IGRhdGFzZXQudmFsaWRhdGlvbkRhdGFzZXQuYmF0Y2goMTApO1xyXG5cclxuICAvLyB0aGlzLmNyZWF0ZUhlYWQoKTtcclxuXHJcbiAgY29uc3QgY2FsbGJhY2tzPSBbXHJcbiAgICAvLyBTaG93IG9uIGEgdGZqcy12aXMgdmlzb3IgdGhlIGxvc3MgYW5kIGFjY3VyYWN5IHZhbHVlcyBhdCB0aGUgZW5kIG9mIGVhY2ggZXBvY2guXHJcbiAgICB0ZnZpcy5zaG93LmZpdENhbGxiYWNrcyh0cmFpbmluZ1N1cmZhY2UsIFsnbG9zcycsICdhY2MnLCBcInZhbF9sb3NzXCIsIFwidmFsX2FjY1wiXSxcclxuICAgICAge1xyXG4gICAgICAgIGNhbGxiYWNrczogWydvbkVwb2NoRW5kJ10sXHJcbiAgICAgIH1cclxuICAgICksXHJcbiAgICB7fSxdXHJcblxyXG4gIGNvbnN0IGhpc3Rvcnk6IGFueSA9IGF3YWl0IHRoaXMudHJhaW5pbmdNb2RlbC5maXREYXRhc2V0KHRyYWluRGF0YSwge1xyXG4gICAgZXBvY2hzOiB0aGlzLl9lcG9jaHMsXHJcbiAgICB2YWxpZGF0aW9uRGF0YSxcclxuICAgIGNhbGxiYWNrc1xyXG59KS50aGVuKChpbmZvOmFueSk9PntcclxuICAgY29uc29sZS5sb2coJ1ByZWNpc8OjbyBmaW5hbCcsIGluZm8uaGlzdG9yeS52YWxfYWNjW2luZm8uaGlzdG9yeS5hY2MubGVuZ3RoLTFdKTtcclxufSk7XHJcblxyXG5cclxuLy8gYXdhaXQgdGhpcy5hY2N1cmFjeV9wZXJfY2xhc3MoKTtcclxuXHJcblxyXG4vLyBjb25zb2xlLmxvZyhcIkhpc3Rvcnk6IFwiLCBoaXN0b3J5Lmhpc3RvcnkuYWNjKTtcclxuICAvLyBhd2FpdCB0aGlzLnRyYWluaW5nTW9kZWwuZml0KHRoaXMuZmVhdHVyZVgsIHRoaXMudGFyZ2V0LCB7fSlcclxuIH1cclxuXHJcbmFzeW5jIGFjY3VyYWN5X3Blcl9jbGFzcyhjb25mdXNpb25fbWF0cml4X3JlY2lwaWVudDogYW55KXtcclxuICBcclxuICAvKipDYWxjdWxhdGluZyBBY2N1cmFjeSBwZXIgY2xhc3MgKi9cclxuY29uc3QgYWNjdXJhY3lwZXJjbGFzczogYW55ID0gIGF3YWl0IHRoaXMuY2FsY3VsYXRlQWNjdXJhY3lQZXJDbGFzcyhUZWFjaGFibGVNb2JpbGVOZXQudmFsaWRhdGlvbkRhdGFzZXQpO1xyXG4vLyBjb25zb2xlLmxvZyhcIkFjY3VyYWN5IHBlciBjbGFzczogXCIsIGFjY3VyYWN5cGVyY2xhc3MpO1xyXG5cclxuLy9Db25mdXNpb24gbWF0cml4XHJcbi8vIENhbGxpbmcgdGYuY29uZnVzaW9uTWF0cml4KCkgbWV0aG9kIFxyXG5jb25zdCBvdXRwdXQgPSB0Zi5tYXRoLmNvbmZ1c2lvbk1hdHJpeCggYWNjdXJhY3lwZXJjbGFzcy5yZWZlcmVuY2UsIGFjY3VyYWN5cGVyY2xhc3MucHJlZGljdGlvbnMsIFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aCk7IFxyXG4gIFxyXG4vLyBQcmludGluZyBvdXRwdXQgXHJcbm91dHB1dC5wcmludCgpXHJcbmNvbnN0IGNvbmZ1c2lvbl9tYXRyaXg9ICBvdXRwdXQuZGF0YVN5bmMoKTtcclxuXHJcbi8vIGNvbnNvbGUubG9nKGNvbmZ1c2lvbl9tYXRyaXgpO1xyXG4vLyBjb25zb2xlLmxvZyhjb25mdXNpb25fbWF0cml4W1RlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aCArIFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aF0pO1xyXG5cclxuY29uc3QgYWNjdXJhY3kgPSBbXTtcclxuXHJcbmZvcihsZXQgaT0wOyBpPFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aDtpKyspe1xyXG5cclxuICBhY2N1cmFjeS5wdXNoKGNvbmZ1c2lvbl9tYXRyaXhbVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoKmkrIGldL1RlYWNoYWJsZU1vYmlsZU5ldC5udW1WYWxpZGF0aW9uKVxyXG59XHJcblxyXG5jb25zb2xlLmxvZyhcIkFjY3VyYWN5IHBlciBjbGFzczogXCIsIGFjY3VyYWN5KTtcclxuXHJcbmZvcihsZXQgaT0wOyBpPFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aDtpKyspe1xyXG5cclxuICBjb25mdXNpb25fbWF0cml4X3JlY2lwaWVudC5wdXNoKFtdKTtcclxuXHJcbiAgZm9yKGxldCBqPTA7IGo8VGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoO2orKyl7XHJcbiAgICBjb25mdXNpb25fbWF0cml4X3JlY2lwaWVudFtpXS5wdXNoKFtdKTtcclxuXHJcbiAgICBjb25mdXNpb25fbWF0cml4X3JlY2lwaWVudFtpXVtqXT0gKGNvbmZ1c2lvbl9tYXRyaXhbVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoKmkrIGpdL1RlYWNoYWJsZU1vYmlsZU5ldC5udW1WYWxpZGF0aW9uKS50b0ZpeGVkKDIpXHJcbiAgICBjb25mdXNpb25fbWF0cml4X3JlY2lwaWVudFtpXVtqXT0oY29uZnVzaW9uX21hdHJpeF9yZWNpcGllbnRbaV1bal0udG9GaXhlZCgyKSoxMDApO1xyXG4gIH1cclxuXHJcbiAgLy8gYWNjdXJhY3kucHVzaChjb25mdXNpb25fbWF0cml4W1RlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aCppKyBpXS9UZWFjaGFibGVNb2JpbGVOZXQubnVtVmFsaWRhdGlvbilcclxufVxyXG5cclxuY29uc29sZS5sb2coXCJDb25mdXNpb24gbWF0cml4IGFzIGEgbWF0cml4XCIpXHJcbmNvbnNvbGUubG9nKGNvbmZ1c2lvbl9tYXRyaXhfcmVjaXBpZW50KTtcclxuXHJcbnJldHVybiBhY2N1cmFjeS5tYXAoKGVsZW06IGFueSk9PmVsZW0udG9GaXhlZCgyKSoxMDApO1xyXG59XHJcblxyXG4gXHJcbiBhc3luYyBsb2FkSW1hZ2VzKG51bWJlcl9vZl9zcGVjaWVzOiBudW1iZXIsIGNsYXNzZXNfbmFtZXM6IHN0cmluZ1tdLCBvcHRpb25zOiBvYmplY3Qpe1xyXG4gICAgICAgIFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzPWNsYXNzZXNfbmFtZXM7XHJcbiAgICBcclxuICAgICAgICBhd2FpdCB0aGlzLmFkZF9zcGVjaWVzKG51bWJlcl9vZl9zcGVjaWVzLCBvcHRpb25zKTsgICAgICAgIFxyXG5cclxufVxyXG5cclxuYXN5bmMgYWRkX3NwZWNpZXMobnVtYmVyX29mX3NwZWNpZXM6IG51bWJlciwgb3B0aW9uczogb2JqZWN0KXtcclxuICBcclxuICAgIC8vTG9hZGluZyBmZWF0dXJlIG1vZGVsLCB1c2VkIHRvIGNyZWF0ZSBmZWF0dXJlcyBmcm9tIGltYWdlc1xyXG4gICAgLy8gIGF3YWl0IHRoaXMubG9hZEZlYXR1cmVNb2RlbCgpO1xyXG5cclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgLy8gdGhpcy5hZGRfaW1hZ2VzKHRoaXMuY2xhc3Nlc19uYW1lc1tpXSwgbnVtYmVyX29mX3NwZWNpZXMsIG9wdGlvbnMpO1xyXG4gICAgfVxyXG59XHJcblxyXG4vKipcclxuICogXHJcbiAqIEBwYXJhbSBuYW1lIC0gbmFtZSBvZiB0aGUgY2xhc3MgcmVjZWl2aW5nIGFuIGV4YW1wbGVcclxuICogQHBhcmFtIG51bWJlcl9vZl9zcGVjaWVzIC0gaG93IG1hbnkgaW1hZ2VzIHRvIGFkZFxyXG4gKiBAcGFyYW0gb3B0aW9ucyAtIGRldGFpbHMgb24gdGhlIGxvY2F0aW9uIG9mIHRoZSBpbWFnZXNcclxuICovXHJcbmFzeW5jIGFkZF9pbWFnZXMobmFtZTogc3RyaW5nLCBudW1iZXJfb2Zfc3BlY2llczogbnVtYmVyLCBvcHRpb25zOiBhbnkpeyAgIFxyXG5cclxuICAgIGNvbnN0IGNsYXNzX2FkZDogYW55PSBbXTtcclxuXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bWJlcl9vZl9zcGVjaWVzOyBpKyspIHsgICAgICBcclxuICAgIC8vICAgY2xhc3NfYWRkLnB1c2goYCR7b3B0aW9ucy5iYXNlfS8ke25hbWV9LyR7b3B0aW9ucy5maWxlX25hbWV9ICR7aX0uJHtvcHRpb25zLmZpbGVfZXh0ZW5zaW9ufWApO1xyXG4gICAgICAgIFxyXG4gICAgICAgIC8vVXBsb2FkaW5nIGltYWdlc1xyXG4gICAgICAgIGNvbnN0IGNha2UgPSBuZXcgSW1hZ2UoKTsgICAgICAgIFxyXG4gICAgICAgIC8vIGNha2Uuc3JjID0gYCR7b3B0aW9ucy5iYXNlfS8ke25hbWV9LyR7b3B0aW9ucy5maWxlX25hbWV9ICR7aX0uJHtvcHRpb25zLmZpbGVfZXh0ZW5zaW9ufWA7XHJcbiAgICAgICAgY2FrZS5oZWlnaHQ9MjI0O1xyXG4gICAgICAgIGNha2Uud2lkdGg9MjI0O1xyXG4gICAgICAgIGNha2Uuc3JjPVwiLi9hc3NldHMvZGF0YXNldC9DYW4lQzMlQTFyaW8tZGEtVGVycmEvaW1hZ2UlMjAwLmpwZWdcIlxyXG4gICAgICAgIC8vIGNvbnNvbGUubG9nKFwiSW1hZ2UgbG9jYXRpb246IFwiLCBjYWtlLnNyYyApXHJcblxyXG4gICAgICAgIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgICAgICAgICAgY2FrZS5vbmxvYWQgPSAoKSA9PiB7XHJcblxyXG4gICAgICAgICAgICAgICAgLy9GaW5kaW5nIHRoZSBjb3JyZXNwb25kZW50IGluZGV4IG9mIHRoZSBjbGFzcyB3aXRoIG5hbWUgZ2l2ZW5cclxuICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4PSBUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lcy5maW5kSW5kZXgoKGVsZW0pPT5lbGVtPT09bmFtZSlcclxuXHJcbiAgICAgICAgICAgICAgICAvLyB0aGlzLmFkZEV4YW1wbGUoaW5kZXgsIGNha2UpO1xyXG5cclxuICAgICAgICAgICAgICByZXNvbHZlKCk7XHJcbiAgICAgICAgICAgIH07XHJcbiAgXHJcbiAgICAgICAgICAgIGNha2Uub25lcnJvciA9IChlcnJvcikgPT4ge1xyXG4gICAgICAgICAgICAgIC8vIEhhbmRsZSBlcnJvciBpZiB0aGUgaW1hZ2UgZmFpbHMgdG8gbG9hZFxyXG4gICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICB9KTtcclxuICB9XHJcblxyXG4gIC8vIHRoaXMuY2xhc3Nlcy5wdXNoKHtuYW1lOiBuYW1lLCBpbWFnZXM6IGNsYXNzX2FkZH0pICBcclxuXHJcbiAgfVxyXG5cclxuXHJcblxyXG4gICAgICBcclxuLyoqXHJcbiAqIFRoaXMgbWV0aG9kIHdpbGwgdHJhbnNmb3JtIGltYWdlcyBpbnRvIHRlbnNvcnNcclxuICogQHBhcmFtIG51bWJlcl9vZl9jbGFzc2VzIC0gbnVtYmVyIG9mIGNsYXNzZXNcclxuICogQHBhcmFtIGNsYXNzZXNfbmFtZXMgLSBuYW1lIG9mIGVhY2ggY2xhc3NcclxuICovXHJcbmFzeW5jIGNyZWF0ZVRlbnNvcnMobnVtYmVyX29mX2NsYXNzZXM6IG51bWJlciwgY2xhc3Nlc19uYW1lczogc3RyaW5nW10pIHtcclxuXHJcbiAgICBsZXQgb3V0cHV0OiBhbnkgPSBbXTtcclxuXHJcbiAgICAvKiogVGhlcmUgaXMgYSBmdW5jdGlvbiBvbiBUZW5zb3JGbG93LmpzIHRoYXQgYWxzbyBkb2VzIHRoYXQgKi9cclxuICAgIGNvbnN0IHNpZ25hdHVyZXM9IG5ldyBVdGlsKCkuaWRlbnRpdHlNYXRyaXgobnVtYmVyX29mX2NsYXNzZXMpO1xyXG5cclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyX29mX2NsYXNzZXM7IGkrKykge1xyXG5cclxuICAgICAgICB0aGlzLmNsYXNzZXNbaV0uc2lnbmF0dXJlPXNpZ25hdHVyZXNbaV07XHJcbiAgICAgICAgdGhpcy5jbGFzc2VzW2ldLm5hbWU9Y2xhc3Nlc19uYW1lc1tpXTtcclxuXHJcbiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLmNsYXNzZXNbaV0uaW1hZ2VzLmxlbmd0aDsgaisrKSB7XHJcblxyXG5cclxuICAgICAgICB9XHJcblxyXG4gICAgfVxyXG59XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBBZGQgYSBzYW1wbGUgb2YgZGF0YSB1bmRlciB0aGUgcHJvdmlkZWQgY2xhc3NOYW1lXHJcbiAgICAgKiBAcGFyYW0gY2xhc3NOYW1lIHRoZSBjbGFzc2lmaWNhdGlvbiB0aGlzIGV4YW1wbGUgYmVsb25ncyB0b1xyXG4gICAgICogQHBhcmFtIHNhbXBsZSB0aGUgaW1hZ2UgLyB0ZW5zb3IgdGhhdCBiZWxvbmdzIGluIHRoaXMgY2xhc3NpZmljYXRpb25cclxuICAgICAqL1xyXG4gICAgLy8gcHVibGljIGFzeW5jIGFkZEV4YW1wbGUoY2xhc3NOYW1lOiBudW1iZXIsIHNhbXBsZTogSFRNTENhbnZhc0VsZW1lbnQgfCB0Zi5UZW5zb3IpIHtcclxucHVibGljIHN0YXRpYyBhc3luYyBhZGRFeGFtcGxlKGNsYXNzTmFtZTogbnVtYmVyLCBuYW1lOiBzdHJpbmcsIHNhbXBsZTogSFRNTEltYWdlRWxlbWVudCB8IEhUTUxDYW52YXNFbGVtZW50IHwgdGYuVGVuc29yKSB7XHJcblxyXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkFkZGluZyBhIG5ldyBleGFtcGxlLi4uXCIpIFxyXG4gICAgICAgICAgXHJcbiAgICAgICAgICAgIGNvbnN0IGNhcCA9IGlzVGVuc29yKHNhbXBsZSkgPyBzYW1wbGUgOiBjYXB0dXJlKHNhbXBsZSk7XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAvLyBpZighdGhpcy50cnVuY2F0ZWRNb2RlbClcclxuICAgICAgICAgICAgLy8gICBhd2FpdCB0aGlzLmxvYWRGZWF0dXJlTW9kZWwoKTtcclxuXHJcbiAgICAgICAgICAgIC8vR2V0dGluZyB0aGUgZmVhdHVyZXNcclxuICAgICAgICAgICAgY29uc3QgZXhhbXBsZSA9IHRoaXMudHJ1bmNhdGVkTW9kZWwucHJlZGljdChjYXApIGFzIHRmLlRlbnNvcjtcclxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJTaGFwZSBhZnRlciBmZWF0dXJlIGV4dHJhY3Rpb246IFwiLCBleGFtcGxlLnNoYXBlKSAgICAgICAgICBcclxuICAgICAgICAgICBcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGFjdGl2YXRpb24gPSBleGFtcGxlLmRhdGFTeW5jKCkgYXMgRmxvYXQzMkFycmF5O1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgLy9WZXJ5IGltcG9ydGFudCB0byBjbGVhbiB0aGUgbWVtb3J5IGFmdGVybWF0aCwgaXQgbWFrZXMgdGhlIGRpZmZlcmVuY2VcclxuICAgICAgICAgICAgY2FwLmRpc3Bvc2UoKTtcclxuICAgICAgICAgICAgZXhhbXBsZS5kaXNwb3NlKCk7XHJcbiAgICBcclxuICAgICAgICAgICAgLy8gLy9BY2Nlc3NpbmcgdGhlIGluc3RhbmNlIHZhcmlhYmxlLCBub3QgdGhlIGxvY2FsIG9uZXNcclxuICAgICAgICAgICAgLy8gLy8gc2F2ZSBzYW1wbGVzIG9mIGVhY2ggY2xhc3Mgc2VwYXJhdGVseSBcclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIGlmKCFUZWFjaGFibGVNb2JpbGVOZXQuZXhhbXBsZXNbY2xhc3NOYW1lXSlcclxuICAgICAgICAgICAgICAvL2FuZCBhbiBlbXB0eSBhcnJheSwgbWFrZSBzdXJlIHRoZXJlIGlzIG5vdCBlbXB0eSBlbGVtZW50cy4gXHJcbiAgICAgICAgICAgICAgLy9pdCB3aWxsIGNyZWF0ZSBpc3N1ZSB3aGVuIHRyYW5zZm9ybWluZyB0byB0ZW5zb3JzXHJcbiAgICAgICAgICAgICAgVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzW2NsYXNzTmFtZV09W11cclxuXHJcblxyXG4gICAgICAgICAgICAgIGlmKCFUZWFjaGFibGVNb2JpbGVOZXQuY2xhc3Nlc19uYW1lc1tjbGFzc05hbWVdKVxyXG4gICAgICAgICAgICAgICAgLy9TYXZpbmcgdGhlIGxhYmxlIHdoZW4gaXQgZmlyc3QgYXBwZWFyc1xyXG4gICAgICAgICAgICAgICAgVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXNbY2xhc3NOYW1lXT1uYW1lO1xyXG5cclxuICAgICAgICAgICAgVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzW2NsYXNzTmFtZV0ucHVzaChhY3RpdmF0aW9uKTtcclxuICAgIFxyXG4gICAgICAgICAgICAvLyAvLyBpbmNyZWFzZSBvdXIgc2FtcGxlIGNvdW50ZXJcclxuICAgICAgICAgICAgVGVhY2hhYmxlTW9iaWxlTmV0LnRvdGFsU2FtcGxlcysrO1xyXG4gICAgICAgIH1cclxuXHJcblxyXG4gICAvKipcclxuICAgICAqIHByb2Nlc3MgdGhlIGN1cnJlbnQgZXhhbXBsZXMgcHJvdmlkZWQgdG8gY2FsY3VsYXRlIGxhYmVscyBhbmQgZm9ybWF0XHJcbiAgICAgKiBpbnRvIHByb3BlciB0Zi5kYXRhLkRhdGFzZXRcclxuICAgICAqL1xyXG4gICBzdGF0aWMgcHJlcGFyZSgpIHtcclxuICAgIGZvciAoY29uc3QgY2xhc3NlcyBpbiBUZWFjaGFibGVNb2JpbGVOZXQuZXhhbXBsZXMpe1xyXG4gICAgICAgIGlmIChjbGFzc2VzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FkZCBzb21lIGV4YW1wbGVzIGJlZm9yZSB0cmFpbmluZycpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBkYXRhc2V0czogYW55ID0gdGhpcy5jb252ZXJ0VG9UZkRhdGFzZXQoKTtcclxuXHJcbiAgICB0aGlzLnRyYWluRGF0YXNldCA9IGRhdGFzZXRzLnRyYWluRGF0YXNldDtcclxuICAgIHRoaXMudmFsaWRhdGlvbkRhdGFzZXQgPSBkYXRhc2V0cy52YWxpZGF0aW9uRGF0YXNldDtcclxufVxyXG5cclxucHVibGljIHByZXBhcmVEYXRhc2V0KCkge1xyXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgVGVhY2hhYmxlTW9iaWxlTmV0Lm51bUNsYXNzZXM7IGkrKykge1xyXG4gICAgLy9EaWZmZXJlbnQgZnJvbSB0aGUgb3JpZ2luYWwgaW1wbGVtZW50YXRpb24gb2YgVE0sIG1pbmUgaXMgdXNpbmcgZXhhbXBsZSBhcyBzdGF0aWMuXHJcbiAgICAvL1RoZSBnb2FsIGlzIHNhdmluZyBtZW1vcnkgYnkgdXNpbmcgYSBzaW5nbGUgaW5zdGFuY2Ugb2YgdGhlIHZhcmlhYmxlXHJcbiAgICBUZWFjaGFibGVNb2JpbGVOZXQuZXhhbXBsZXNbaV0gPSBbXTtcclxuICB9XHJcbn1cclxuXHJcbiBcclxuICAgIC8vIE9wdGlvbmFsIHNlZWQgdG8gbWFrZSBzaHVmZmxpbmcgb2YgZGF0YSBwcmVkaWN0YWJsZVxyXG4gICAgc3RhdGljIHNlZWQ6IHNlZWRyYW5kb20ucHJuZztcclxuXHJcblxyXG5cclxuICAgIFxyXG4vKipcclxuICAgICAqIFByb2Nlc3MgdGhlIGV4YW1wbGVzIGJ5IGZpcnN0IHNodWZmbGluZyByYW5kb21seSBwZXIgY2xhc3MsIHRoZW4gYWRkaW5nXHJcbiAgICAgKiBvbmUtaG90IGxhYmVscywgdGhlbiBzcGxpdHRpbmcgaW50byB0cmFpbmluZy92YWxpZGF0aW9uIGRhdHNldHMsIGFuZCBmaW5hbGx5XHJcbiAgICAgKiBzb3J0aW5nIG9uZSBsYXN0IHRpbWVcclxuICAgICAqL1xyXG4gXHJcbnN0YXRpYyBjb252ZXJ0VG9UZkRhdGFzZXQoKSB7XHJcblxyXG4gICAgICAgICAvLyBmaXJzdCBzaHVmZmxlIGVhY2ggY2xhc3MgaW5kaXZpZHVhbGx5XHJcbiAgICAgICAgLy8gVE9ETzogd2UgY291bGQgYmFzaWNhbGx5IHJlcGxpY2F0ZSB0aGlzIGJ5IGluc3RlcnRpbmcgcmFuZG9tbHlcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IFRlYWNoYWJsZU1vYmlsZU5ldC5leGFtcGxlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzW2ldID0gZmlzaGVyWWF0ZXMoVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzW2ldLCB0aGlzLnNlZWQpIGFzIEZsb2F0MzJBcnJheVtdO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyB0aGVuIGJyZWFrIGludG8gdmFsaWRhdGlvbiBhbmQgdGVzdCBkYXRhc2V0c1xyXG4gICAgICBsZXQgdHJhaW5EYXRhc2V0OiBTYW1wbGVbXSA9IFtdO1xyXG4gICAgICBsZXQgdmFsaWRhdGlvbkRhdGFzZXQ6IFNhbXBsZVtdID0gW107XHJcblxyXG4gICAgICAvLyBmb3IgZWFjaCBjbGFzcywgYWRkIHNhbXBsZXMgdG8gdHJhaW4gYW5kIHZhbGlkYXRpb24gZGF0YXNldFxyXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IFRlYWNoYWJsZU1vYmlsZU5ldC5leGFtcGxlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICBcclxuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIk51bWJlciBvZiBjbGFzc2VzOiBcIiwgVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoKTtcclxuXHJcbiAgICAgICAgY29uc3QgeSA9IGZsYXRPbmVIb3QoaSwgVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoKTtcclxuXHJcbiAgICAgICAgY29uc3QgY2xhc3NMZW5ndGggPSBUZWFjaGFibGVNb2JpbGVOZXQuZXhhbXBsZXNbaV0ubGVuZ3RoO1xyXG5cclxuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIk51bWJlciBvZiBlbGVtZW50cyBwZXIgY2xhc3M6IFwiLCBjbGFzc0xlbmd0aCk7XHJcblxyXG4gICAgICAgIGNvbnN0IG51bVZhbGlkYXRpb24gPSBNYXRoLmNlaWwoVkFMSURBVElPTl9GUkFDVElPTiAqIGNsYXNzTGVuZ3RoKTtcclxuICAgICAgICBjb25zdCBudW1UcmFpbiA9IGNsYXNzTGVuZ3RoIC0gbnVtVmFsaWRhdGlvbjtcclxuXHJcbiAgICAgICAgdGhpcy5udW1WYWxpZGF0aW9uPW51bVZhbGlkYXRpb247XHJcbiAgICAgICBcclxuICAgICAgICAvKipJdCBpcyB2aXNpdGluZyBwZXIgY2xhc3MsIHRodXMsIGl0IGlzIHBvc3NpYmxlIHRvIGZpeCB5LCB0aGUgdGFyZ2V0IGxhYmVsICovXHJcbiAgICAgXHJcbiAgICAgIGNvbnN0IGNsYXNzVHJhaW4gPSB0aGlzLmV4YW1wbGVzW2ldLnNsaWNlKDAsIG51bVRyYWluKS5tYXAoKGRhdGFBcnJheSkgPT4ge1xyXG4gICAgICAgICAgcmV0dXJuIHsgZGF0YTogZGF0YUFycmF5LCBsYWJlbDogeSB9O1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIGNvbnN0IGNsYXNzVmFsaWRhdGlvbiA9IHRoaXMuZXhhbXBsZXNbaV0uc2xpY2UobnVtVHJhaW4pLm1hcCgoZGF0YUFycmF5KSA9PiB7XHJcbiAgICAgICAgICByZXR1cm4geyBkYXRhOiBkYXRhQXJyYXksIGxhYmVsOiB5IH07XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdHJhaW5EYXRhc2V0ID0gdHJhaW5EYXRhc2V0LmNvbmNhdChjbGFzc1RyYWluKTtcclxuICAgICAgdmFsaWRhdGlvbkRhdGFzZXQgPSB2YWxpZGF0aW9uRGF0YXNldC5jb25jYXQoY2xhc3NWYWxpZGF0aW9uKTsgXHJcblxyXG5cclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gY29uc29sZS5sb2coXCJUcmFpbmluZyBlbGVtZW50OiBcIiwgdHJhaW5EYXRhc2V0W3RyYWluRGF0YXNldC5sZW5ndGgtMV0pICAgICAgXHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKFwiVHJhaW5pbmcgbGVuZ3RoOiBcIiwgdHJhaW5EYXRhc2V0Lmxlbmd0aClcclxuICAgICAgLy8gY29uc29sZS5sb2coXCJ2YWxpZGF0aW9uIGxlbmd0aDogXCIsIHZhbGlkYXRpb25EYXRhc2V0Lmxlbmd0aCk7XHJcblxyXG4gICAgICBcclxuICAgICAgICAvLyBmaW5hbGx5IHNodWZmbGUgYm90aCB0cmFpbiBhbmQgdmFsaWRhdGlvbiBkYXRhc2V0c1xyXG4gICAgICAgIHRyYWluRGF0YXNldCA9IGZpc2hlcllhdGVzKHRyYWluRGF0YXNldCwgdGhpcy5zZWVkKSBhcyBTYW1wbGVbXTtcclxuICAgICAgICB2YWxpZGF0aW9uRGF0YXNldCA9IGZpc2hlcllhdGVzKHZhbGlkYXRpb25EYXRhc2V0LCB0aGlzLnNlZWQpIGFzIFNhbXBsZVtdO1xyXG5cclxuICAgICAgICBjb25zdCB0cmFpblggPSB0Zi5kYXRhLmFycmF5KHRyYWluRGF0YXNldC5tYXAoc2FtcGxlID0+IHNhbXBsZS5kYXRhKSk7XHJcbiAgICAgICAgY29uc3QgdmFsaWRhdGlvblggPSB0Zi5kYXRhLmFycmF5KHZhbGlkYXRpb25EYXRhc2V0Lm1hcChzYW1wbGUgPT4gc2FtcGxlLmRhdGEpKTtcclxuICAgICAgICBjb25zdCB0cmFpblkgPSB0Zi5kYXRhLmFycmF5KHRyYWluRGF0YXNldC5tYXAoc2FtcGxlID0+IHNhbXBsZS5sYWJlbCkpO1xyXG4gICAgICAgIGNvbnN0IHZhbGlkYXRpb25ZID0gdGYuZGF0YS5hcnJheSh2YWxpZGF0aW9uRGF0YXNldC5tYXAoc2FtcGxlID0+IHNhbXBsZS5sYWJlbCkpO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIHJldHVybiB0Zi5kYXRhIGRhdGFzZXQgb2JqZWN0c1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgICAgdHJhaW5EYXRhc2V0OiB0Zi5kYXRhLnppcCh7IHhzOiB0cmFpblgsICB5czogdHJhaW5ZfSksXHJcbiAgICAgICAgICAgICAgICAgIHZhbGlkYXRpb25EYXRhc2V0OiB0Zi5kYXRhLnppcCh7IHhzOiB2YWxpZGF0aW9uWCwgIHlzOiB2YWxpZGF0aW9uWX0pXHJcbiAgICAgICAgICAgICAgfTtcclxuXHJcblxyXG59XHJcblxyXG5kYXRhc2V0Rm9yRXZhbHVhdGlvbigpe1xyXG5cclxufVxyXG5cclxuLyoqTWV0cmljcyAqL1xyXG5cclxuc3RhdGljIGZlYXR1cmVfYXV4OiBhbnk7XHJcbnN0YXRpYyB0YXJnZXRfYXV4OiBhbnk7XHJcblxyXG5hc3luYyBldmFsdWF0ZSgpe1xyXG4gICBcclxuICAvL0NoZWNrIG9mIHRoZSBmZWF0dXJlcyBoYXZlIGFscmVhZHkgYmVlbiBjYWxjdWxhdGVkXHJcbiAgLyoqRm9yIGF2b2lkaW5nIHJlY2FsY3VsYXRpbmcgdGhlIGZlYXR1cmVzIGV2ZXJ5IGdlbmVyYXRpb24gKi9cclxuICBpZighVGVhY2hhYmxlTW9iaWxlTmV0LmZlYXR1cmVfYXV4KXtcclxuICAgIGNvbnN0IGZlYXR1cmVzOiBhbnk9W107XHJcbiAgICBjb25zdCB0YXJnZXRzOiBhbnk9W107XHJcblxyXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzLmxlbmd0aDsgaSsrKSB7XHJcblxyXG4gICAgY29uc3QgeSA9IGZsYXRPbmVIb3QoaSwgVGVhY2hhYmxlTW9iaWxlTmV0LmNsYXNzZXNfbmFtZXMubGVuZ3RoKTtcclxuICAgIC8vRm9yIGNsYXNzIGksIHB1c2ggYWxsIHRoZSBleGFtcGxlcy5cclxuICAgIFRlYWNoYWJsZU1vYmlsZU5ldC5leGFtcGxlc1tpXS5mb3JFYWNoKChlbGVtbik9PntcclxuXHJcbiAgICAgICAvL1B1c2hpbmcgdGhlIHRhcmdldCBzaWduYXR1cmVcclxuICAgICAgIHRhcmdldHMucHVzaCh5KTtcclxuICAgICAgIFxyXG4gICAgICAgLy9QdXNoaW5nIGZlYXR1cmVzXHJcbiAgICAgICBmZWF0dXJlcy5wdXNoKGVsZW1uKVxyXG4gICAgfSlcclxuXHJcbiAgfSAgXHJcblxyXG4gIFRlYWNoYWJsZU1vYmlsZU5ldC5mZWF0dXJlX2F1eD0gdGYudGVuc29yKGZlYXR1cmVzKTtcclxuICBUZWFjaGFibGVNb2JpbGVOZXQudGFyZ2V0X2F1eD0gdGYudGVuc29yKHRhcmdldHMpO1xyXG5cclxuICB9IFxyXG5cclxuICAvL0V2YWx1YXRpbmcgdGhlIG1vZGVsXHJcbiAgY29uc3QgYXV4OiBhbnkgPSB0aGlzLnRyYWluaW5nTW9kZWwuZXZhbHVhdGUoVGVhY2hhYmxlTW9iaWxlTmV0LmZlYXR1cmVfYXV4LCBUZWFjaGFibGVNb2JpbGVOZXQudGFyZ2V0X2F1eCk7XHJcbiAgXHJcbiAgLy9SZXR1cm4ganVzdCB0aGUgYWNjdXJhY3lcclxuICByZXR1cm4gYXV4WzFdLmRhdGFTeW5jKClbMF07XHJcblxyXG5cclxufVxyXG5cclxuXHJcbi8vIGFzeW5jIGV2YWx1YXRlKCl7XHJcblxyXG4vLyAgIGNvbnN0IGZlYXR1cmVzOiBhbnk9W107XHJcbi8vICAgY29uc3QgdGFyZ2V0czogYW55PVtdO1xyXG5cclxuLy8gICBmb3IgKGxldCBpID0gMDsgaSA8IFRlYWNoYWJsZU1vYmlsZU5ldC5leGFtcGxlcy5sZW5ndGg7IGkrKykge1xyXG5cclxuLy8gICAgIGNvbnN0IHkgPSBmbGF0T25lSG90KGksIFRlYWNoYWJsZU1vYmlsZU5ldC5jbGFzc2VzX25hbWVzLmxlbmd0aCk7XHJcbiAgICBcclxuXHJcblxyXG4vLyAgICAgLy9Gb3IgY2xhc3MgaSwgcHVzaCBhbGwgdGhlIGV4YW1wbGVzLlxyXG4vLyAgICAgVGVhY2hhYmxlTW9iaWxlTmV0LmV4YW1wbGVzW2ldLmZvckVhY2goKGVsZW1uKT0+e1xyXG5cclxuLy8gICAgICAgIC8vUHVzaGluZyB0aGUgdGFyZ2V0IHNpZ25hdHVyZVxyXG4vLyAgICAgICAgdGFyZ2V0cy5wdXNoKHkpO1xyXG4gICAgICAgXHJcbi8vICAgICAgICAvL1B1c2hpbmcgZmVhdHVyZXNcclxuLy8gICAgICAgIGZlYXR1cmVzLnB1c2goZWxlbW4pXHJcbi8vICAgICB9KVxyXG5cclxuLy8gICB9ICBcclxuXHJcbi8vICAgY29uc3QgYXV4X2ZlYXR1cmVzPSB0Zi50ZW5zb3IoZmVhdHVyZXMpO1xyXG4vLyAgIGNvbnN0IGF1eF90YXJnZXQ9IHRmLnRlbnNvcih0YXJnZXRzKTtcclxuXHJcbiAgXHJcbi8vICAgLy8gY29uc29sZS5sb2coXCJUZW5zb3Igc3RhY2sgZm9yIGV2YWx1YXRpb246IFwiLCBhdXhfZmVhdHVyZXMuc2hhcGUpXHJcblxyXG4vLyAgIGNvbnN0IGF1eDogYW55ID0gdGhpcy50cmFpbmluZ01vZGVsLmV2YWx1YXRlKGF1eF9mZWF0dXJlcywgYXV4X3RhcmdldCk7XHJcblxyXG5cclxuLy8gICByZXR1cm4gYXV4WzFdLmRhdGFTeW5jKClbMF07XHJcblxyXG5cclxuLy8gfVxyXG5cclxuXHJcbi8qKiogRmluYWwgc3RhdGlzdGljcyAqL1xyXG4vKiBcclxuICAgICAqIENhbGN1bGF0ZSBlYWNoIGNsYXNzIGFjY3VyYWN5IHVzaW5nIHRoZSB2YWxpZGF0aW9uIGRhdGFzZXRcclxuKi9cclxucHVibGljIGFzeW5jIGNhbGN1bGF0ZUFjY3VyYWN5UGVyQ2xhc3ModmFsaWRhdGlvbkRhdGE6IGFueSkge1xyXG5cclxuICBjb25zdCB2YWxpZGF0aW9uWHMgPSBUZWFjaGFibGVNb2JpbGVOZXQudmFsaWRhdGlvbkRhdGFzZXQubWFwQXN5bmMoYXN5bmMgKGRhdGFzZXQ6IFRlbnNvckNvbnRhaW5lcikgPT4ge1xyXG4gICAgcmV0dXJuIChkYXRhc2V0IGFzIHsgeHM6IFRlbnNvckNvbnRhaW5lciwgeXM6IFRlbnNvckNvbnRhaW5lcn0pLnhzO1xyXG59KTtcclxuXHJcbmNvbnN0IHZhbGlkYXRpb25ZcyA9IFRlYWNoYWJsZU1vYmlsZU5ldC52YWxpZGF0aW9uRGF0YXNldC5tYXBBc3luYyhhc3luYyAoZGF0YXNldDogVGVuc29yQ29udGFpbmVyKSA9PiB7XHJcbiAgICByZXR1cm4gKGRhdGFzZXQgYXMgeyB4czogVGVuc29yQ29udGFpbmVyLCB5czogVGVuc29yQ29udGFpbmVyfSkueXM7XHJcbn0pO1xyXG5cclxuLy8gY29uc29sZS5sb2coXCJ2YWxpZGF0aW9uIGRhdGFzZXQ6IFwiLCB2YWxpZGF0aW9uWHMpO1xyXG4gXHJcbi8vIGNvbnNvbGUubG9nKFwiRm9yIGNhbGN1bGF0aW5nIGJhdGNoIHNpemU6IFwiLCB2YWxpZGF0aW9uWXMpO1xyXG5cclxuLy8gd2UgbmVlZCB0byBzcGxpdCBvdXIgdmFsaWRhdGlvbiBkYXRhIGludG8gYmF0Y2hlcyBpbiBjYXNlIGl0IGlzIHRvbyBsYXJnZSB0byBmaXQgaW4gbWVtb3J5XHJcbmNvbnN0IGJhdGNoU2l6ZSA9IE1hdGgubWluKHZhbGlkYXRpb25Zcy5zaXplLCAzMik7XHJcbi8vIGNvbnN0IGJhdGNoU2l6ZSA9MTtcclxuXHJcbmNvbnN0IGl0ZXJhdGlvbnMgPSBNYXRoLmNlaWwodmFsaWRhdGlvbllzLnNpemUgLyBiYXRjaFNpemUpO1xyXG5cclxuLy8gY29uc29sZS5sb2coXCJCYXRjaCBzaXplOiBcIiwgYmF0Y2hTaXplKTtcclxuXHJcbmNvbnN0IGJhdGNoZXNYID0gdmFsaWRhdGlvblhzLmJhdGNoKGJhdGNoU2l6ZSk7XHJcblxyXG5jb25zdCBiYXRjaGVzWSA9IHZhbGlkYXRpb25Zcy5iYXRjaChiYXRjaFNpemUpO1xyXG5jb25zdCBpdFggPSBhd2FpdCBiYXRjaGVzWC5pdGVyYXRvcigpO1xyXG5jb25zdCBpdFkgPSBhd2FpdCBiYXRjaGVzWS5pdGVyYXRvcigpO1xyXG5jb25zdCBhbGxYID0gW107XHJcbmNvbnN0IGFsbFkgPSBbXTtcclxuXHJcbmZvciAobGV0IGkgPSAwOyBpIDwgaXRlcmF0aW9uczsgaSsrKSB7XHJcblxyXG4gICAgLy8gMS4gZ2V0IHRoZSBwcmVkaWN0aW9uIHZhbHVlcyBpbiBiYXRjaGVzXHJcbiAgICAgY29uc3QgYmF0Y2hlZFhUZW5zb3IgPSBhd2FpdCBpdFgubmV4dCgpOyAgXHJcblxyXG4gICAgLy8gIGNvbnNvbGUubG9nKFwiQmF0Y2ggc2l6ZSBvbiBhY2N1cmFjeSBwZXIgY2xhc3M6IFwiLCBiYXRjaGVkWFRlbnNvci52YWx1ZS5zaGFwZSk7XHJcblxyXG4gICAgY29uc3QgYmF0Y2hlZFhQcmVkaWN0aW9uVGVuc29yID0gdGhpcy50cmFpbmluZ01vZGVsLnByZWRpY3QoYmF0Y2hlZFhUZW5zb3IudmFsdWUpIGFzIHRmLlRlbnNvcjtcclxuXHJcbiAgICBjb25zdCBhcmdNYXhYID0gYmF0Y2hlZFhQcmVkaWN0aW9uVGVuc29yLmFyZ01heCgxKTsgLy8gUmV0dXJucyB0aGUgaW5kaWNlcyBvZiB0aGUgbWF4IHZhbHVlcyBhbG9uZyBhbiBheGlzXHJcblxyXG4gICAgYWxsWC5wdXNoKGFyZ01heFgpO1xyXG5cclxuICAgIC8vIDIuIGdldCB0aGUgZ3JvdW5kIHRydXRoIGxhYmVsIHZhbHVlcyBpbiBiYXRjaGVzXHJcbiAgICBjb25zdCBiYXRjaGVkWVRlbnNvciA9IGF3YWl0IGl0WS5uZXh0KCk7XHJcbiAgICBjb25zdCBhcmdNYXhZID0gYmF0Y2hlZFlUZW5zb3IudmFsdWUuYXJnTWF4KDEpOyAvLyBSZXR1cm5zIHRoZSBpbmRpY2VzIG9mIHRoZSBtYXggdmFsdWVzIGFsb25nIGFuIGF4aXNcclxuXHJcbiAgICBhbGxZLnB1c2goYXJnTWF4WSk7XHJcbiAgICBcclxuICAgIC8vIDMuIGRpc3Bvc2Ugb2YgYWxsIG91ciB0ZW5zb3JzXHJcbiAgICAgYmF0Y2hlZFhUZW5zb3IudmFsdWUuZGlzcG9zZSgpO1xyXG4gICAgIGJhdGNoZWRYUHJlZGljdGlvblRlbnNvci5kaXNwb3NlKCk7XHJcbiAgICAgYmF0Y2hlZFlUZW5zb3IudmFsdWUuZGlzcG9zZSgpO1xyXG59XHJcblxyXG4gICAgICAvLyBjb25jYXRlbmF0ZSBhbGwgdGhlIHJlc3VsdHMgb2YgdGhlIGJhdGNoZXNcclxuICAgICAgY29uc3QgcmVmZXJlbmNlID0gdGYuY29uY2F0KGFsbFkpOyAvLyB0aGlzIGlzIHRoZSBncm91bmQgdHJ1dGhcclxuICAgICAgY29uc3QgcHJlZGljdGlvbnMgPSB0Zi5jb25jYXQoYWxsWCk7IC8vIHRoaXMgaXMgdGhlIHByZWRpY3Rpb24gb3VyIG1vZGVsIGlzIGd1ZXNzaW5nXHJcbiAgICAgIFxyXG4gICAgICAvLyBjb25zb2xlLmxvZyhcInRoaXMgaXMgdGhlIGdyb3VuZCB0cnV0aDogXCIsICByZWZlcmVuY2UuZGF0YVN5bmMoKSlcclxuICAgICAgLy8gY29uc29sZS5sb2coXCJUaGlzIGlzIHRoZSBwcmVkaWN0aW9uIG91ciBtb2RlbCBpcyBndWVzc2luZzogXCIsICBwcmVkaWN0aW9ucy5kYXRhU3luYygpKVxyXG5cclxuICAgICAgICAvLyBvbmx5IGlmIHdlIGNvbmNhdGVuYXRlZCBtb3JlIHRoYW4gb25lIHRlbnNvciBmb3IgcHJlZmVyZW5jZSBhbmQgcmVmZXJlbmNlXHJcbiAgICAgICAgaWYgKGl0ZXJhdGlvbnMgIT09IDEpIHtcclxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhbGxYLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBhbGxYW2ldLmRpc3Bvc2UoKTtcclxuICAgICAgICAgICAgICAgIGFsbFlbaV0uZGlzcG9zZSgpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgIC8vICBjb25zb2xlLmxvZyhcIkxlbmd0dGg6IFwiLCBhd2FpdCByZWZlcmVuY2UuZGF0YVN5bmMoKS5sZW5ndGgpICBcclxuICAgIFxyXG4gICAgLy8gY29uc3QgYWNjdXJhY3lwZXJjbGFzcz1bXTtcclxuXHJcbiAgICAvLyBjb25zdCByZWZlcmVuY2VfYXV4PSBhd2FpdCByZWZlcmVuY2UuZGF0YVN5bmMoKTtcclxuICAgIC8vIGNvbnN0IHByZWRpY3Rpb25fYXV4PSBhd2FpdCBwcmVkaWN0aW9ucy5kYXRhU3luYygpO1xyXG4gICAgLy8gY29uc29sZS5sb2coIHByZWRpY3Rpb25zLmRhdGFTeW5jKCkpO1xyXG5cclxuICAgIC8vIHJlZmVyZW5jZV9hdXguZm9yRWFjaCgoZWxlbWVudCwgaW5kZXgpID0+IHtcclxuICAgIC8vICAgaWYoKVxyXG4gICAgICBcclxuICAgIC8vIH0pOyAgXHJcblxyXG5cclxuICAgICAgICByZXR1cm4geyByZWZlcmVuY2UsIHByZWRpY3Rpb25zIH07ICBcclxuXHJcbn1cclxuXHJcbn0vL2VuZCBvZiBjbGFzc1xyXG5cclxuXHJcblxyXG5cclxuXHJcbi8qKipTdXBwb3J0IG1ldGhvZHMgKGhlbHBlcnMpICovXHJcblxyXG5jb25zdCBpc1RlbnNvciA9IChjOiBhbnkpOiBjIGlzIHRmLlRlbnNvciA9PlxyXG4gICAgdHlwZW9mIGMuZGF0YUlkID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgYy5zaGFwZSA9PT0gJ29iamVjdCc7XHJcbi8qKlxyXG4gKiBDb252ZXJ0cyBhbiBpbnRlZ2VyIGludG8gaXRzIG9uZS1ob3QgcmVwcmVzZW50YXRpb24gYW5kIHJldHVybnNcclxuICogdGhlIGRhdGEgYXMgYSBKUyBBcnJheS5cclxuICovXHJcbmZ1bmN0aW9uIGZsYXRPbmVIb3QobGFiZWw6IG51bWJlciwgbnVtQ2xhc3NlczogbnVtYmVyKSB7XHJcblxyXG4gIGNvbnN0IGxhYmVsT25lSG90ID0gbmV3IEFycmF5KG51bUNsYXNzZXMpLmZpbGwoMCkgYXMgbnVtYmVyW107XHJcbiAgbGFiZWxPbmVIb3RbbGFiZWxdID0gMTtcclxuXHJcbiAgcmV0dXJuIGxhYmVsT25lSG90O1xyXG59XHJcblxyXG5pbnRlcmZhY2UgU2FtcGxlIHtcclxuICBkYXRhOiBGbG9hdDMyQXJyYXk7XHJcbiAgbGFiZWw6IG51bWJlcltdO1xyXG59XHJcblxyXG5cclxuLyoqXHJcbiAqIFNodWZmbGUgYW4gYXJyYXkgb2YgRmxvYXQzMkFycmF5IG9yIFNhbXBsZXMgdXNpbmcgRmlzaGVyLVlhdGVzIGFsZ29yaXRobVxyXG4gKiBUYWtlcyBhbiBvcHRpb25hbCBzZWVkIHZhbHVlIHRvIG1ha2Ugc2h1ZmZsaW5nIHByZWRpY3RhYmxlXHJcbiAqL1xyXG5mdW5jdGlvbiBmaXNoZXJZYXRlcyhhcnJheTogRmxvYXQzMkFycmF5W10gfCBTYW1wbGVbXSwgc2VlZD86IHNlZWRyYW5kb20ucHJuZykge1xyXG4gIGNvbnN0IGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcclxuXHJcbiAgLy8gbmVlZCB0byBjbG9uZSBhcnJheSBvciB3ZSdkIGJlIGVkaXRpbmcgb3JpZ2luYWwgYXMgd2UgZ29vXHJcbiAgY29uc3Qgc2h1ZmZsZWQgPSBhcnJheS5zbGljZSgpO1xyXG5cclxuICBmb3IgKGxldCBpID0gKGxlbmd0aCAtIDEpOyBpID4gMDsgaSAtPSAxKSB7XHJcbiAgICAgIGxldCByYW5kb21JbmRleCA7XHJcbiAgICAgIGlmIChzZWVkKSB7XHJcbiAgICAgICAgICByYW5kb21JbmRleCA9IE1hdGguZmxvb3Ioc2VlZCgpICogKGkgKyAxKSk7XHJcbiAgICAgIH1cclxuICAgICAgZWxzZSB7XHJcbiAgICAgICAgICByYW5kb21JbmRleCA9IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIChpICsgMSkpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBbc2h1ZmZsZWRbaV0sIHNodWZmbGVkW3JhbmRvbUluZGV4XV0gPSBbc2h1ZmZsZWRbcmFuZG9tSW5kZXhdLHNodWZmbGVkW2ldXTtcclxuICB9XHJcblxyXG4gIHJldHVybiBzaHVmZmxlZDtcclxufVxyXG4iXX0=
@@ -437,8 +437,15 @@ class TeachableMobileNet extends CustomMobileNet {
437
437
  constructor() {
438
438
  super();
439
439
  this.classes = [];
440
+ //Parameters
441
+ this._epochs = 10;
440
442
  this.createHead();
441
443
  }
444
+ /*** */
445
+ set epochs(epochs) {
446
+ this._epochs = epochs;
447
+ }
448
+ /*** */
442
449
  /**
443
450
  * This method will return the head, the trainable part, the part under evolution.
444
451
  */
@@ -492,7 +499,7 @@ class TeachableMobileNet extends CustomMobileNet {
492
499
  {},
493
500
  ];
494
501
  const history = await this.trainingModel.fitDataset(trainData, {
495
- epochs: 100,
502
+ epochs: this._epochs,
496
503
  validationData,
497
504
  callbacks
498
505
  }).then((info) => {
@@ -523,8 +530,8 @@ class TeachableMobileNet extends CustomMobileNet {
523
530
  confusion_matrix_recipient.push([]);
524
531
  for (let j = 0; j < TeachableMobileNet.classes_names.length; j++) {
525
532
  confusion_matrix_recipient[i].push([]);
526
- confusion_matrix_recipient[i][j] = confusion_matrix[TeachableMobileNet.classes_names.length * i + j] / TeachableMobileNet.numValidation;
527
- confusion_matrix_recipient[i][j] = (confusion_matrix_recipient[i][j].toFixed(2)) * 100;
533
+ confusion_matrix_recipient[i][j] = (confusion_matrix[TeachableMobileNet.classes_names.length * i + j] / TeachableMobileNet.numValidation).toFixed(2);
534
+ confusion_matrix_recipient[i][j] = (confusion_matrix_recipient[i][j].toFixed(2) * 100);
528
535
  }
529
536
  // accuracy.push(confusion_matrix[TeachableMobileNet.classes_names.length*i+ i]/TeachableMobileNet.numValidation)
530
537
  }
@@ -852,6 +859,9 @@ class DisplayPanelComponent {
852
859
  if (!options.file_name && (options.subfolder)) {
853
860
  class_add.push(`${options.base}/${name}/${options.subfolder}/${name} ${i + 1}.${options.file_extension}`);
854
861
  }
862
+ else if (options.numbered) {
863
+ class_add.push(`${options.base}/${name}/${i + 1}.${options.file_extension}`);
864
+ }
855
865
  else
856
866
  class_add.push(`${options.base}/${name}/${options.file_name} ${i + 1}.${options.file_extension}`);
857
867
  }
@@ -953,8 +963,6 @@ class NeuroEvolution {
953
963
  await this.evaluate();
954
964
  //selection
955
965
  this.selection();
956
- console.log("Best accuracy: ", this.getTheBest().accuracy);
957
- console.log("Worst accuracy: ", this.getTheWorst().accuracy);
958
966
  }
959
967
  /**Helpers */
960
968
  getTheBest() {
@@ -1123,6 +1131,7 @@ class GeneticAlgorithm extends NeuroEvolution {
1123
1131
  const best = this.getTheBest();
1124
1132
  this.population = [];
1125
1133
  this.population = selected_individuals;
1134
+ this.population.push(best);
1126
1135
  console.log("Best accuracy (elitism): ", best.accuracy);
1127
1136
  }
1128
1137
  }
@@ -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/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 \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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"}
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 //Parameters\r\n private _epochs: number=10;\r\n\r\n constructor(){\r\n super();\r\n this.createHead();\r\n }\r\n\r\n /*** */\r\n set epochs(epochs: number){\r\n this._epochs=epochs;\r\n } \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: this._epochs,\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).toFixed(2)\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 \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 this.population.push(best);\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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"}
@@ -39,7 +39,11 @@ export declare class TeachableMobileNet extends CustomMobileNet {
39
39
  static trainDataset: any;
40
40
  static validationDataset: any;
41
41
  static numValidation: number;
42
+ private _epochs;
42
43
  constructor();
44
+ /*** */
45
+ set epochs(epochs: number);
46
+ /*** */
43
47
  /**
44
48
  * This method will return the head, the trainable part, the part under evolution.
45
49
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tfjs-evolution",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
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",