diff --git a/README.md b/README.md index 9a0ff7cb..80786ada 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,8 @@ ## REQUIREMENTS -* **Current SGNUIKit Version**: 1.1.5 + +**Current SGNUIKit Version**: 1.2.1 ### Core Requirements diff --git a/SECURITY.md b/SECURITY.md index a9db43ea..083540e5 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,9 +4,9 @@ | Version | Supported | |---------|--------------------| +| 1.2.1 | :white_check_mark: | | 1.1.5 | :white_check_mark: | -| 1.1.4 | :white_check_mark: | -| < 1.1.4 | :x: | +| < 1.1.5 | :x: | ## Reporting a Vulnerability diff --git a/build/config.js b/build/config.js index cc5eaab5..ae3b7d73 100644 --- a/build/config.js +++ b/build/config.js @@ -27,7 +27,7 @@ const version = { }; -const SGNUIKitLoader = "LyoNCiAqIENvcHlyaWdodCAoYykgMjAyMiBTR05ldHdvcmtzLiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KICoNCiAqIFRoZSBzb2Z0d2FyZSBpcyBhbiBleGNsdXNpdmUgY29weXJpZ2h0IG9mICJTR05ldHdvcmtzIiBhbmQgaXMgcHJvdmlkZWQgYXMgaXMgZXhjbHVzaXZlbHkgd2l0aCBvbmx5ICJVU0FHRSIgYWNjZXNzLiAiTW9kaWZpY2F0aW9uIiwgICJBbHRlcmF0aW9uIiwgIlJlLWRpc3RyaWJ1dGlvbiIgaXMgY29tcGxldGVseSBwcm9oaWJpdGVkLg0KICogVklPTEFUSU5HIFRIRSBBQk9WRSBURVJNUyBJUyBBIFBVTklTSEFCTEUgT0ZGRU5TRSBXSElDSCBNQVkgTEVBRCBUTyBMRUdBTCBDT05TRVFVRU5DRVMuDQogKi8NCg0KY29uc3QgU0dOVUlLaXQgPSB7DQoJaXNSZWFkeTogZmFsc2UsDQoJaXNQcmVsb2FkZXJIZWxkOiBmYWxzZSwNCgljb21wb25lbnRzOiB7fSwNCglvbkNoYW5nZUxpc3RlbmVyOiBbXSwNCglvblJlYWR5TGlzdGVuZXI6IFtdLA0KDQoJLyoqDQoJICogVGhpcyBjYWxsYmFjayBpcyBjYWxsZWQgd2hlbiBhIGNvbXBvbmVudCBpcyBsb2FkZWQvcmVtb3ZlZCBvciB0aGUgc3RhdHVzIG9mIHJlYWRpbmVzcyBpcyBjaGFuZ2VkLg0KCSAqDQoJICogQGNhbGxiYWNrIFNHTlVJS2l0Q2hhbmdlQ2FsbGJhY2sNCgkgKiBAcGFyYW0ge3N0cmluZ30gc3RhdGUgVGhlIG5hbWUgb2YgdGhlIHN0YXRlIHdoaWNoIGlzIGNoYW5nZWQuDQoJICogQHBhcmFtIHtib29sZWFufEpTT059IHZhbHVlIFRoZSB2YWx1ZSBvZiB0aGUgc3RhdGUgd2hpY2ggaXMgY2hhbmdlZC4NCgkgKiBAcGFyYW0ge0pTT059IGNvbXBvbmVudHMgVGhlIDxiPjxpPkpTT048L2k+PC9iPiBvYmplY3Qgb2YgbG9hZGVkIDxiPlNHTlVJS2l0PC9iPiBjb21wb25lbnRzLCBvciBhbiBlbXB0eSA8Yj48aT5KU09OPC9pPjwvYj4gb2JqZWN0IGlmIG5vIGNvbXBvbmVudHMgbG9hZGVkLg0KCSAqLw0KCS8qKg0KCSAqIFRoaXMgY2FsbGJhY2sgaXMgY2FsbGVkIHdoZW4gPGI+U0dOVUlLaXQ8L2I+IGlzIHJlYWR5Lg0KCSAqDQoJICogQGNhbGxiYWNrIFNHTlVJS2l0UmVhZHlDYWxsYmFjaw0KCSAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNSZWFkeSB0aGUgc3RhdHVzIG9mIHJlYWRpbmVzcyBvZiA8Yj5TR05VSUtpdDwvYj4uDQoJICovDQoNCgkvKioNCgkgKiBBZGQgYSBsb2FkZWQgPGI+U0dOVUlLaXQ8L2I+IGNvbXBvbmVudC4NCgkgKg0KCSAqIEBwYXJhbSB7SlNPTn0gdmFsdWUgVGhlIDxiPjxpPkpTT048L2k+PC9iPiBvYmplY3Qgb2YgdGhlIGxvYWRlZCA8Yj5TR05VSUtpdDwvYj4gY29tcG9uZW50Lg0KCSAqLw0KCXNldCBjb21wb25lbnQodmFsdWUpIHsNCgkJaWYodmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gIiIpDQoJCQl2YWx1ZSA9IHt9Ow0KCQlPYmplY3QuYXNzaWduKHRoaXMuY29tcG9uZW50cywgdmFsdWUpOw0KDQoJCXRoaXMub25DaGFuZ2VMaXN0ZW5lci5mb3JFYWNoKChsaXN0ZW5lcikgPT4gbGlzdGVuZXIoImNvbXBvbmVudHMiLCB2YWx1ZSwgdGhpcy5jb21wb25lbnRzKSk7DQoJfSwNCg0KCS8qKg0KCSAqIEdldCB0aGUgbGlzdCBvZiBsb2FkZWQgPGI+U0dOVUlLaXQ8L2I+IGNvbXBvbmVudHMuDQoJICoNCgkgKiBAcmV0dXJuIHtvYmplY3R9IFRoZSA8Yj48aT5KU09OPC9pPjwvYj4gb2JqZWN0IG9mIGxvYWRlZCA8Yj5TR05VSUtpdDwvYj4gY29tcG9uZW50cywgb3IgYW4gZW1wdHkgPGI+PGk+SlNPTjwvaT48L2I+IG9iamVjdCBpZiBubyBjb21wb25lbnRzIGxvYWRlZC4NCgkgKi8NCglnZXQgY29tcG9uZW50KCkgew0KCQlyZXR1cm4gdGhpcy5jb21wb25lbnRzOw0KCX0sDQoNCgkvKioNCgkgKiBTZXQgdGhlIHN0YXR1cyBvZiByZWFkaW5lc3Mgb2YgPGI+U0dOVUlLaXQ8L2I+Lg0KCSAqDQoJICogQHBhcmFtIHtib29sZWFufSBpc1JlYWR5IFRoZSB0aGUgc3RhdHVzIG9mIHJlYWRpbmVzcyBvZiA8Yj5TR05VSUtpdDwvYj4uDQoJICovDQoJc2V0IHJlYWR5KGlzUmVhZHkpIHsNCgkJdGhpcy5pc1JlYWR5ID0gaXNSZWFkeTsNCgkJdGhpcy5vbkNoYW5nZUxpc3RlbmVyLmZvckVhY2goKGxpc3RlbmVyKSA9PiBsaXN0ZW5lcigicmVhZHkiLCB0aGlzLmlzUmVhZHkpKTsNCg0KCQlpZihpc1JlYWR5KQ0KCQkJdGhpcy5vblJlYWR5TGlzdGVuZXIuZm9yRWFjaCgobGlzdGVuZXIpID0+IGxpc3RlbmVyKGlzUmVhZHkpKTsNCgl9LA0KDQoJLyoqDQoJICogR2V0IHRoZSBzdGF0dXMgb2YgcmVhZGluZXNzIG9mIDxiPlNHTlVJS2l0PC9iPi4NCgkgKg0KCSAqIEByZXR1cm4ge2Jvb2xlYW59IDxiPjxpPlRSVUU8L2k+PC9iPiBpZiA8Yj5TR05VSUtpdDwvYj4gaXMgcmVhZHksIDxiPjxpPkZBTFNFPC9pPjwvYj4gb3RoZXJ3aXNlLg0KCSAqLw0KCWdldCByZWFkeSgpIHsNCgkJcmV0dXJuIHRoaXMuaXNSZWFkeTsNCgl9LA0KDQoJLyoqDQoJICogSG9sZCB0aGUgPGI+U0dOVUlLaXQ8L2I+IHByZWxvYWRlciBldmVuIGFmdGVyICA8Yj5TR05VSUtpdDwvYj4gaGFzIGZpbmlzaGVkIGxvYWRpbmcgdGhlIGNvbXBvbmVudHMuDQoJICoNCgkgKiBAcGFyYW0ge2Jvb2xlYW59IGhvbGQgVGhlIHRoZSBzdGF0dXMgb2YgcmVhZGluZXNzIG9mIDxiPlNHTlVJS2l0PC9iPi4NCgkgKi8NCglzZXQgaG9sZFByZWxvYWRlcihob2xkKSB7DQoJCXRoaXMuaXNQcmVsb2FkZXJIZWxkID0gaG9sZDsNCgkJdGhpcy5vbkNoYW5nZUxpc3RlbmVyLmZvckVhY2goKGxpc3RlbmVyKSA9PiBsaXN0ZW5lcigiaG9sZFByZWxvYWRlciIsIHRoaXMuaXNQcmVsb2FkZXJIZWxkKSk7DQoJfSwNCg0KCS8qKg0KCSAqIEdldCB0aGUgc3RhdHVzIG9mIHJlYWRpbmVzcyBvZiA8Yj5TR05VSUtpdDwvYj4uDQoJICoNCgkgKiBAcmV0dXJuIHtib29sZWFufSA8Yj48aT5UUlVFPC9pPjwvYj4gaWYgPGI+U0dOVUlLaXQ8L2I+IGlzIHJlYWR5LCA8Yj48aT5GQUxTRTwvaT48L2I+IG90aGVyd2lzZS4NCgkgKi8NCglnZXQgaG9sZFByZWxvYWRlcigpIHsNCgkJcmV0dXJuIHRoaXMuaXNQcmVsb2FkZXJIZWxkOw0KCX0sDQoNCgkvKioNCgkgKiBTZXQgdGhlIGhhbmRsZXIgZm9yIDxiPlNHTlVJS2l0PC9iPiA8Yj48aT5PbkNoYW5nZTwvaT48L2I+IGV2ZW50LCB3aGljaCB3aWxsIGJlIHRyaWdnZXJlZCB3aGVuIGEgY29tcG9uZW50IGlzIGxvYWRlZC9yZW1vdmVkIG9yIHRoZSBzdGF0dXMgb2YgcmVhZGluZXNzIGlzIGNoYW5nZWQuDQoJICoNCgkgKiBAcGFyYW0ge1NHTlVJS2l0Q2hhbmdlQ2FsbGJhY2t9bGlzdGVuZXINCgkgKi8NCglzZXRPbkNoYW5nZUxpc3RlbmVyOiBmdW5jdGlvbihsaXN0ZW5lcikgew0KCQl0aGlzLm9uQ2hhbmdlTGlzdGVuZXIucHVzaChsaXN0ZW5lcik7DQoJfSwNCg0KCS8qKg0KCSAqIFNldCB0aGUgaGFuZGxlciBmb3IgPGI+U0dOVUlLaXQ8L2I+IDxiPjxpPk9uUmVhZHk8L2k+PC9iPiBldmVudCwgd2hpY2ggd2lsbCBiZSB0cmlnZ2VyZWQgd2hlbiB0aGUgPGI+U0dOVUlLaXQ8L2I+IGlzIHJlYWR5Lg0KCSAqDQoJICogQHBhcmFtIHtTR05VSUtpdFJlYWR5Q2FsbGJhY2t9bGlzdGVuZXINCgkgKi8NCglzZXRPblJlYWR5TGlzdGVuZXI6IGZ1bmN0aW9uKGxpc3RlbmVyKSB7DQoJCXRoaXMub25SZWFkeUxpc3RlbmVyLnB1c2gobGlzdGVuZXIpOw0KDQoJCWlmKHRoaXMucmVhZHkpDQoJCQl0aGlzLm9uUmVhZHlMaXN0ZW5lci5mb3JFYWNoKChsaXN0ZW5lcikgPT4gbGlzdGVuZXIodGhpcy5yZWFkeSkpOw0KCX0sDQp9Ow0Kd2luZG93LlNHTlVJS2l0ID0gU0dOVUlLaXQ7DQoNCmlmKHR5cGVvZiBqUXVlcnkgPT09ICd1bmRlZmluZWQnKSB7DQoJLyohIGpRdWVyeSB2My42LjMgfCAoYykgT3BlbkpTIEZvdW5kYXRpb24gYW5kIG90aGVyIGNvbnRyaWJ1dG9ycyB8IGpxdWVyeS5vcmcvbGljZW5zZSAqLw0KCSFmdW5jdGlvbihlLCB0KSB7DQoJCSJ1c2Ugc3RyaWN0IjsNCgkJIm9iamVjdCIgPT0gdHlwZW9mIG1vZHVsZSAmJiAib2JqZWN0IiA9PSB0eXBlb2YgbW9kdWxlLmV4cG9ydHMgPyBtb2R1bGUuZXhwb3J0cyA9IGUuZG9jdW1lbnQgPyB0KGUsICEwKSA6IGZ1bmN0aW9uKGUpIHsNCgkJCWlmKCFlLmRvY3VtZW50KSB0aHJvdyBuZXcgRXJyb3IoImpRdWVyeSByZXF1aXJlcyBhIHdpbmRvdyB3aXRoIGEgZG9jdW1lbnQiKTsNCgkJCXJldHVybiB0KGUpDQoJCX0gOiB0KGUpDQoJfSgidW5kZWZpbmVkIiAhPSB0eXBlb2Ygd2luZG93ID8gd2luZG93IDogdGhpcywgZnVuY3Rpb24oQywgZSkgew0KCQkidXNlIHN0cmljdCI7DQoJCXZhciB0ID0gW10sDQoJCSAgICByID0gT2JqZWN0LmdldFByb3RvdHlwZU9mLA0KCQkgICAgcyA9IHQuc2xpY2UsDQoJCSAgICBnID0gdC5mbGF0ID8gZnVuY3Rpb24oZSkge3JldHVybiB0LmZsYXQuY2FsbChlKX0gOiBmdW5jdGlvbihlKSB7cmV0dXJuIHQuY29uY2F0LmFwcGx5KFtdLCBlKX0sDQoJCSAgICB1ID0gdC5wdXNoLA0KCQkgICAgaSA9IHQuaW5kZXhPZiwNCgkJICAgIG4gPSB7fSwNCgkJICAgIG8gPSBuLnRvU3RyaW5nLA0KCQkgICAgeSA9IG4uaGFzT3duUHJvcGVydHksDQoJCSAgICBhID0geS50b1N0cmluZywNCgkJICAgIGwgPSBhLmNhbGwoT2JqZWN0KSwNCgkJICAgIHYgPSB7fSwNCgkJICAgIG0gPSBmdW5jdGlvbihlKSB7cmV0dXJuICJmdW5jdGlvbiIgPT0gdHlwZW9mIGUgJiYgIm51bWJlciIgIT0gdHlwZW9mIGUubm9kZVR5cGUgJiYgImZ1bmN0aW9uIiAhPSB0eXBlb2YgZS5pdGVtfSwNCgkJICAgIHggPSBmdW5jdGlvbihlKSB7cmV0dXJuIG51bGwgIT0gZSAmJiBlID09PSBlLndpbmRvd30sDQoJCSAgICBTID0gQy5kb2N1bWVudCwNCgkJICAgIGMgPSB7dHlwZTogITAsIHNyYzogITAsIG5vbmNlOiAhMCwgbm9Nb2R1bGU6ICEwfTsNCg0KCQlmdW5jdGlvbiBiKGUsIHQsIG4pIHsNCgkJCXZhciByLCBpLCBvID0gKG4gPSBuIHx8IFMpLmNyZWF0ZUVsZW1lbnQoInNjcmlwdCIpOw0KCQkJaWYoby50ZXh0ID0gZSwgdCkgZm9yKHIgaW4gYykgKGkgPSB0W3JdIHx8IHQuZ2V0QXR0cmlidXRlICYmIHQuZ2V0QXR0cmlidXRlKHIpKSAmJiBvLnNldEF0dHJpYnV0ZShyLCBpKTsNCgkJCW4uaGVhZC5hcHBlbmRDaGlsZChvKS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG8pDQoJCX0NCg0KCQlmdW5jdGlvbiB3KGUpIHtyZXR1cm4gbnVsbCA9PSBlID8gZSArICIiIDogIm9iamVjdCIgPT0gdHlwZW9mIGUgfHwgImZ1bmN0aW9uIiA9PSB0eXBlb2YgZSA/IG5bby5jYWxsKGUpXSB8fCAib2JqZWN0IiA6IHR5cGVvZiBlfQ0KDQoJCXZhciBmID0gIjMuNi4zIiwgRSA9IGZ1bmN0aW9uKGUsIHQpIHtyZXR1cm4gbmV3IEUuZm4uaW5pdChlLCB0KX07DQoNCgkJZnVuY3Rpb24gcChlKSB7DQoJCQl2YXIgdCA9ICEhZSAmJiAibGVuZ3RoIiBpbiBlICYmIGUubGVuZ3RoLCBuID0gdyhlKTsNCgkJCXJldHVybiAhbShlKSAmJiAheChlKSAmJiAoImFycmF5IiA9PT0gbiB8fCAwID09PSB0IHx8ICJudW1iZXIiID09IHR5cGVvZiB0ICYmIDAgPCB0ICYmIHQgLSAxIGluIGUpDQoJCX0NCg0KCQlFLmZuID0gRS5wcm90b3R5cGUgPSB7DQoJCQlqcXVlcnk6IGYsDQoJCQljb25zdHJ1Y3RvcjogRSwNCgkJCWxlbmd0aDogMCwNCgkJCXRvQXJyYXk6IGZ1bmN0aW9uKCkge3JldHVybiBzLmNhbGwodGhpcyl9LA0KCQkJZ2V0OiBmdW5jdGlvbihlKSB7cmV0dXJuIG51bGwgPT0gZSA/IHMuY2FsbCh0aGlzKSA6IGUgPCAwID8gdGhpc1tlICsgdGhpcy5sZW5ndGhdIDogdGhpc1tlXX0sDQoJCQlwdXNoU3RhY2s6IGZ1bmN0aW9uKGUpIHsNCgkJCQl2YXIgdCA9IEUubWVyZ2UodGhpcy5jb25zdHJ1Y3RvcigpLCBlKTsNCgkJCQlyZXR1cm4gdC5wcmV2T2JqZWN0ID0gdGhpcywgdA0KCQkJfSwNCgkJCWVhY2g6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gRS5lYWNoKHRoaXMsIGUpfSwNCgkJCW1hcDogZnVuY3Rpb24obikge3JldHVybiB0aGlzLnB1c2hTdGFjayhFLm1hcCh0aGlzLCBmdW5jdGlvbihlLCB0KSB7cmV0dXJuIG4uY2FsbChlLCB0LCBlKX0pKX0sDQoJCQlzbGljZTogZnVuY3Rpb24oKSB7cmV0dXJuIHRoaXMucHVzaFN0YWNrKHMuYXBwbHkodGhpcywgYXJndW1lbnRzKSl9LA0KCQkJZmlyc3Q6IGZ1bmN0aW9uKCkge3JldHVybiB0aGlzLmVxKDApfSwNCgkJCWxhc3Q6IGZ1bmN0aW9uKCkge3JldHVybiB0aGlzLmVxKC0xKX0sDQoJCQlldmVuOiBmdW5jdGlvbigpIHtyZXR1cm4gdGhpcy5wdXNoU3RhY2soRS5ncmVwKHRoaXMsIGZ1bmN0aW9uKGUsIHQpIHtyZXR1cm4gKHQgKyAxKSAlIDJ9KSl9LA0KCQkJb2RkOiBmdW5jdGlvbigpIHtyZXR1cm4gdGhpcy5wdXNoU3RhY2soRS5ncmVwKHRoaXMsIGZ1bmN0aW9uKGUsIHQpIHtyZXR1cm4gdCAlIDJ9KSl9LA0KCQkJZXE6IGZ1bmN0aW9uKGUpIHsNCgkJCQl2YXIgdCA9IHRoaXMubGVuZ3RoLCBuID0gK2UgKyAoZSA8IDAgPyB0IDogMCk7DQoJCQkJcmV0dXJuIHRoaXMucHVzaFN0YWNrKDAgPD0gbiAmJiBuIDwgdCA/IFt0aGlzW25dXSA6IFtdKQ0KCQkJfSwNCgkJCWVuZDogZnVuY3Rpb24oKSB7cmV0dXJuIHRoaXMucHJldk9iamVjdCB8fCB0aGlzLmNvbnN0cnVjdG9yKCl9LA0KCQkJcHVzaDogdSwNCgkJCXNvcnQ6IHQuc29ydCwNCgkJCXNwbGljZTogdC5zcGxpY2UNCgkJfSwgRS5leHRlbmQgPSBFLmZuLmV4dGVuZCA9IGZ1bmN0aW9uKCkgew0KCQkJdmFyIGUsIHQsIG4sIHIsIGksIG8sIGEgPSBhcmd1bWVudHNbMF0gfHwge30sIHMgPSAxLCB1ID0gYXJndW1lbnRzLmxlbmd0aCwgbCA9ICExOw0KCQkJZm9yKCJib29sZWFuIiA9PSB0eXBlb2YgYSAmJiAobCA9IGEsIGEgPSBhcmd1bWVudHNbc10gfHwge30sIHMrKyksICJvYmplY3QiID09IHR5cGVvZiBhIHx8IG0oYSkgfHwgKGEgPSB7fSksIHMgPT09IHUgJiYgKGEgPSB0aGlzLCBzLS0pOyBzIDwgdTsgcysrKSBpZihudWxsICE9IChlID0gYXJndW1lbnRzW3NdKSkgZm9yKHQgaW4gZSkgciA9IGVbdF0sICJfX3Byb3RvX18iICE9PSB0ICYmIGEgIT09IHIgJiYgKGwgJiYgciAmJiAoRS5pc1BsYWluT2JqZWN0KHIpIHx8IChpID0gQXJyYXkuaXNBcnJheShyKSkpID8gKG4gPSBhW3RdLCBvID0gaSAmJiAhQXJyYXkuaXNBcnJheShuKSA/IFtdIDogaSB8fCBFLmlzUGxhaW5PYmplY3QobikgPyBuIDoge30sIGkgPSAhMSwgYVt0XSA9IEUuZXh0ZW5kKGwsIG8sIHIpKSA6IHZvaWQgMCAhPT0gciAmJiAoYVt0XSA9IHIpKTsNCgkJCXJldHVybiBhDQoJCX0sIEUuZXh0ZW5kKHsNCgkJCWV4cGFuZG86ICJqUXVlcnkiICsgKGYgKyBNYXRoLnJhbmRvbSgpKS5yZXBsYWNlKC9cRC9nLCAiIiksIGlzUmVhZHk6ICEwLCBlcnJvcjogZnVuY3Rpb24oZSkge3Rocm93IG5ldyBFcnJvcihlKX0sIG5vb3A6IGZ1bmN0aW9uKCkge30sIGlzUGxhaW5PYmplY3Q6IGZ1bmN0aW9uKGUpIHsNCgkJCQl2YXIgdCwgbjsNCgkJCQlyZXR1cm4gISghZSB8fCAiW29iamVjdCBPYmplY3RdIiAhPT0gby5jYWxsKGUpKSAmJiAoISh0ID0gcihlKSkgfHwgImZ1bmN0aW9uIiA9PSB0eXBlb2YgKG4gPSB5LmNhbGwodCwgImNvbnN0cnVjdG9yIikgJiYgdC5jb25zdHJ1Y3RvcikgJiYgYS5jYWxsKG4pID09PSBsKQ0KCQkJfSwgaXNFbXB0eU9iamVjdDogZnVuY3Rpb24oZSkgew0KCQkJCXZhciB0Ow0KCQkJCWZvcih0IGluIGUpIHJldHVybiAhMTsNCgkJCQlyZXR1cm4gITANCgkJCX0sIGdsb2JhbEV2YWw6IGZ1bmN0aW9uKGUsIHQsIG4pIHtiKGUsIHtub25jZTogdCAmJiB0Lm5vbmNlfSwgbil9LCBlYWNoOiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJdmFyIG4sIHIgPSAwOw0KCQkJCWlmKHAoZSkpIHtmb3IobiA9IGUubGVuZ3RoOyByIDwgbjsgcisrKSBpZighMSA9PT0gdC5jYWxsKGVbcl0sIHIsIGVbcl0pKSBicmVha30gZWxzZSBmb3IociBpbiBlKSBpZighMSA9PT0gdC5jYWxsKGVbcl0sIHIsIGVbcl0pKSBicmVhazsNCgkJCQlyZXR1cm4gZQ0KCQkJfSwgbWFrZUFycmF5OiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJdmFyIG4gPSB0IHx8IFtdOw0KCQkJCXJldHVybiBudWxsICE9IGUgJiYgKHAoT2JqZWN0KGUpKSA/IEUubWVyZ2UobiwgInN0cmluZyIgPT0gdHlwZW9mIGUgPyBbZV0gOiBlKSA6IHUuY2FsbChuLCBlKSksIG4NCgkJCX0sIGluQXJyYXk6IGZ1bmN0aW9uKGUsIHQsIG4pIHtyZXR1cm4gbnVsbCA9PSB0ID8gLTEgOiBpLmNhbGwodCwgZSwgbil9LCBtZXJnZTogZnVuY3Rpb24oZSwgdCkgew0KCQkJCWZvcih2YXIgbiA9ICt0Lmxlbmd0aCwgciA9IDAsIGkgPSBlLmxlbmd0aDsgciA8IG47IHIrKykgZVtpKytdID0gdFtyXTsNCgkJCQlyZXR1cm4gZS5sZW5ndGggPSBpLCBlDQoJCQl9LCBncmVwOiBmdW5jdGlvbihlLCB0LCBuKSB7DQoJCQkJZm9yKHZhciByID0gW10sIGkgPSAwLCBvID0gZS5sZW5ndGgsIGEgPSAhbjsgaSA8IG87IGkrKykgIXQoZVtpXSwgaSkgIT09IGEgJiYgci5wdXNoKGVbaV0pOw0KCQkJCXJldHVybiByDQoJCQl9LCBtYXA6IGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQl2YXIgciwgaSwgbyA9IDAsIGEgPSBbXTsNCgkJCQlpZihwKGUpKSBmb3IociA9IGUubGVuZ3RoOyBvIDwgcjsgbysrKSBudWxsICE9IChpID0gdChlW29dLCBvLCBuKSkgJiYgYS5wdXNoKGkpOyBlbHNlIGZvcihvIGluIGUpIG51bGwgIT0gKGkgPSB0KGVbb10sIG8sIG4pKSAmJiBhLnB1c2goaSk7DQoJCQkJcmV0dXJuIGcoYSkNCgkJCX0sIGd1aWQ6IDEsIHN1cHBvcnQ6IHYNCgkJfSksICJmdW5jdGlvbiIgPT0gdHlwZW9mIFN5bWJvbCAmJiAoRS5mbltTeW1ib2wuaXRlcmF0b3JdID0gdFtTeW1ib2wuaXRlcmF0b3JdKSwgRS5lYWNoKCJCb29sZWFuIE51bWJlciBTdHJpbmcgRnVuY3Rpb24gQXJyYXkgRGF0ZSBSZWdFeHAgT2JqZWN0IEVycm9yIFN5bWJvbCIuc3BsaXQoIiAiKSwgZnVuY3Rpb24oZSwgdCkge25bIltvYmplY3QgIiArIHQgKyAiXSJdID0gdC50b0xvd2VyQ2FzZSgpfSk7DQoJCXZhciBkID0gZnVuY3Rpb24obikgew0KCQkJdmFyIGUsDQoJCQkgICAgZCwNCgkJCSAgICBiLA0KCQkJICAgIG8sDQoJCQkgICAgaSwNCgkJCSAgICBoLA0KCQkJICAgIGYsDQoJCQkgICAgZywNCgkJCSAgICB3LA0KCQkJICAgIHUsDQoJCQkgICAgbCwNCgkJCSAgICBULA0KCQkJICAgIEMsDQoJCQkgICAgYSwNCgkJCSAgICBTLA0KCQkJICAgIHksDQoJCQkgICAgcywNCgkJCSAgICBjLA0KCQkJICAgIHYsDQoJCQkgICAgRSA9ICJzaXp6bGUiICsgMSAqIG5ldyBEYXRlLA0KCQkJICAgIHAgPSBuLmRvY3VtZW50LA0KCQkJICAgIGsgPSAwLA0KCQkJICAgIHIgPSAwLA0KCQkJICAgIG0gPSB1ZSgpLA0KCQkJICAgIHggPSB1ZSgpLA0KCQkJICAgIEEgPSB1ZSgpLA0KCQkJICAgIE4gPSB1ZSgpLA0KCQkJICAgIGogPSBmdW5jdGlvbihlLCB0KSB7cmV0dXJuIGUgPT09IHQgJiYgKGwgPSAhMCksIDB9LA0KCQkJICAgIEQgPSB7fS5oYXNPd25Qcm9wZXJ0eSwNCgkJCSAgICB0ID0gW10sDQoJCQkgICAgcSA9IHQucG9wLA0KCQkJICAgIEwgPSB0LnB1c2gsDQoJCQkgICAgSCA9IHQucHVzaCwNCgkJCSAgICBPID0gdC5zbGljZSwNCgkJCSAgICBQID0gZnVuY3Rpb24oZSwgdCkgew0KCQkJCSAgICBmb3IodmFyIG4gPSAwLCByID0gZS5sZW5ndGg7IG4gPCByOyBuKyspIGlmKGVbbl0gPT09IHQpIHJldHVybiBuOw0KCQkJCSAgICByZXR1cm4gLTENCgkJCSAgICB9LA0KCQkJICAgIFIgPSAiY2hlY2tlZHxzZWxlY3RlZHxhc3luY3xhdXRvZm9jdXN8YXV0b3BsYXl8Y29udHJvbHN8ZGVmZXJ8ZGlzYWJsZWR8aGlkZGVufGlzbWFwfGxvb3B8bXVsdGlwbGV8b3BlbnxyZWFkb25seXxyZXF1aXJlZHxzY29wZWQiLA0KCQkJICAgIE0gPSAiW1xceDIwXFx0XFxyXFxuXFxmXSIsDQoJCQkgICAgSSA9ICIoPzpcXFxcW1xcZGEtZkEtRl17MSw2fSIgKyBNICsgIj98XFxcXFteXFxyXFxuXFxmXXxbXFx3LV18W15cMC1cXHg3Zl0pKyIsDQoJCQkgICAgVyA9ICJcXFsiICsgTSArICIqKCIgKyBJICsgIikoPzoiICsgTSArICIqKFsqXiR8IX5dPz0pIiArIE0gKyAiKig/OicoKD86XFxcXC58W15cXFxcJ10pKiknfFwiKCg/OlxcXFwufFteXFxcXFwiXSkqKVwifCgiICsgSSArICIpKXwpIiArIE0gKyAiKlxcXSIsDQoJCQkgICAgRiA9ICI6KCIgKyBJICsgIikoPzpcXCgoKCcoKD86XFxcXC58W15cXFxcJ10pKiknfFwiKCg/OlxcXFwufFteXFxcXFwiXSkqKVwiKXwoKD86XFxcXC58W15cXFxcKClbXFxdXXwiICsgVyArICIpKil8LiopXFwpfCkiLA0KCQkJICAgICQgPSBuZXcgUmVnRXhwKE0gKyAiKyIsICJnIiksDQoJCQkgICAgQiA9IG5ldyBSZWdFeHAoIl4iICsgTSArICIrfCgoPzpefFteXFxcXF0pKD86XFxcXC4pKikiICsgTSArICIrJCIsICJnIiksDQoJCQkgICAgXyA9IG5ldyBSZWdFeHAoIl4iICsgTSArICIqLCIgKyBNICsgIioiKSwNCgkJCSAgICB6ID0gbmV3IFJlZ0V4cCgiXiIgKyBNICsgIiooWz4rfl18IiArIE0gKyAiKSIgKyBNICsgIioiKSwNCgkJCSAgICBVID0gbmV3IFJlZ0V4cChNICsgInw+IiksDQoJCQkgICAgWCA9IG5ldyBSZWdFeHAoRiksDQoJCQkgICAgViA9IG5ldyBSZWdFeHAoIl4iICsgSSArICIkIiksDQoJCQkgICAgRyA9IHsNCgkJCQkgICAgSUQ6IG5ldyBSZWdFeHAoIl4jKCIgKyBJICsgIikiKSwNCgkJCQkgICAgQ0xBU1M6IG5ldyBSZWdFeHAoIl5cXC4oIiArIEkgKyAiKSIpLA0KCQkJCSAgICBUQUc6IG5ldyBSZWdFeHAoIl4oIiArIEkgKyAifFsqXSkiKSwNCgkJCQkgICAgQVRUUjogbmV3IFJlZ0V4cCgiXiIgKyBXKSwNCgkJCQkgICAgUFNFVURPOiBuZXcgUmVnRXhwKCJeIiArIEYpLA0KCQkJCSAgICBDSElMRDogbmV3IFJlZ0V4cCgiXjoob25seXxmaXJzdHxsYXN0fG50aHxudGgtbGFzdCktKGNoaWxkfG9mLXR5cGUpKD86XFwoIiArIE0gKyAiKihldmVufG9kZHwoKFsrLV18KShcXGQqKW58KSIgKyBNICsgIiooPzooWystXXwpIiArIE0gKyAiKihcXGQrKXwpKSIgKyBNICsgIipcXCl8KSIsICJpIiksDQoJCQkJICAgIGJvb2w6IG5ldyBSZWdFeHAoIl4oPzoiICsgUiArICIpJCIsICJpIiksDQoJCQkJICAgIG5lZWRzQ29udGV4dDogbmV3IFJlZ0V4cCgiXiIgKyBNICsgIipbPit+XXw6KGV2ZW58b2RkfGVxfGd0fGx0fG50aHxmaXJzdHxsYXN0KSg/OlxcKCIgKyBNICsgIiooKD86LVxcZCk/XFxkKikiICsgTSArICIqXFwpfCkoPz1bXi1dfCQpIiwgImkiKQ0KCQkJICAgIH0sDQoJCQkgICAgWSA9IC9IVE1MJC9pLA0KCQkJICAgIFEgPSAvXig/OmlucHV0fHNlbGVjdHx0ZXh0YXJlYXxidXR0b24pJC9pLA0KCQkJICAgIEogPSAvXmhcZCQvaSwNCgkJCSAgICBLID0gL15bXntdK1x7XHMqXFtuYXRpdmUgXHcvLA0KCQkJICAgIFogPSAvXig/OiMoW1x3LV0rKXwoXHcrKXxcLihbXHctXSspKSQvLA0KCQkJICAgIGVlID0gL1srfl0vLA0KCQkJICAgIHRlID0gbmV3IFJlZ0V4cCgiXFxcXFtcXGRhLWZBLUZdezEsNn0iICsgTSArICI/fFxcXFwoW15cXHJcXG5cXGZdKSIsICJnIiksDQoJCQkgICAgbmUgPSBmdW5jdGlvbihlLCB0KSB7DQoJCQkJICAgIHZhciBuID0gIjB4IiArIGUuc2xpY2UoMSkgLSA2NTUzNjsNCgkJCQkgICAgcmV0dXJuIHQgfHwgKG4gPCAwID8gU3RyaW5nLmZyb21DaGFyQ29kZShuICsgNjU1MzYpIDogU3RyaW5nLmZyb21DaGFyQ29kZShuID4+IDEwIHwgNTUyOTYsIDEwMjMgJiBuIHwgNTYzMjApKQ0KCQkJICAgIH0sDQoJCQkgICAgcmUgPSAvKFtcMC1ceDFmXHg3Zl18Xi0/XGQpfF4tJHxbXlwwLVx4MWZceDdmLVx1RkZGRlx3LV0vZywNCgkJCSAgICBpZSA9IGZ1bmN0aW9uKGUsIHQpIHtyZXR1cm4gdCA/ICJcMCIgPT09IGUgPyAiXHVmZmZkIiA6IGUuc2xpY2UoMCwgLTEpICsgIlxcIiArIGUuY2hhckNvZGVBdChlLmxlbmd0aCAtIDEpLnRvU3RyaW5nKDE2KSArICIgIiA6ICJcXCIgKyBlfSwNCgkJCSAgICBvZSA9IGZ1bmN0aW9uKCkge1QoKX0sDQoJCQkgICAgYWUgPSBiZShmdW5jdGlvbihlKSB7cmV0dXJuICEwID09PSBlLmRpc2FibGVkICYmICJmaWVsZHNldCIgPT09IGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKX0sIHtkaXI6ICJwYXJlbnROb2RlIiwgbmV4dDogImxlZ2VuZCJ9KTsNCgkJCXRyeSB7SC5hcHBseSh0ID0gTy5jYWxsKHAuY2hpbGROb2RlcyksIHAuY2hpbGROb2RlcyksIHRbcC5jaGlsZE5vZGVzLmxlbmd0aF0ubm9kZVR5cGV9IGNhdGNoKGUpIHsNCgkJCQlIID0gew0KCQkJCQlhcHBseTogdC5sZW5ndGggPyBmdW5jdGlvbihlLCB0KSB7TC5hcHBseShlLCBPLmNhbGwodCkpfSA6IGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQkJCXZhciBuID0gZS5sZW5ndGgsIHIgPSAwOw0KCQkJCQkJd2hpbGUoZVtuKytdID0gdFtyKytdKSA7DQoJCQkJCQllLmxlbmd0aCA9IG4gLSAxDQoJCQkJCX0NCgkJCQl9DQoJCQl9DQoNCgkJCWZ1bmN0aW9uIHNlKHQsIGUsIG4sIHIpIHsNCgkJCQl2YXIgaSwgbywgYSwgcywgdSwgbCwgYywgZiA9IGUgJiYgZS5vd25lckRvY3VtZW50LCBwID0gZSA/IGUubm9kZVR5cGUgOiA5Ow0KCQkJCWlmKG4gPSBuIHx8IFtdLCAic3RyaW5nIiAhPSB0eXBlb2YgdCB8fCAhdCB8fCAxICE9PSBwICYmIDkgIT09IHAgJiYgMTEgIT09IHApIHJldHVybiBuOw0KCQkJCWlmKCFyICYmIChUKGUpLCBlID0gZSB8fCBDLCBTKSkgew0KCQkJCQlpZigxMSAhPT0gcCAmJiAodSA9IFouZXhlYyh0KSkpIGlmKGkgPSB1WzFdKSB7DQoJCQkJCQlpZig5ID09PSBwKSB7DQoJCQkJCQkJaWYoIShhID0gZS5nZXRFbGVtZW50QnlJZChpKSkpIHJldHVybiBuOw0KCQkJCQkJCWlmKGEuaWQgPT09IGkpIHJldHVybiBuLnB1c2goYSksIG4NCgkJCQkJCX0gZWxzZSBpZihmICYmIChhID0gZi5nZXRFbGVtZW50QnlJZChpKSkgJiYgdihlLCBhKSAmJiBhLmlkID09PSBpKSByZXR1cm4gbi5wdXNoKGEpLCBuDQoJCQkJCX0gZWxzZSB7DQoJCQkJCQlpZih1WzJdKSByZXR1cm4gSC5hcHBseShuLCBlLmdldEVsZW1lbnRzQnlUYWdOYW1lKHQpKSwgbjsNCgkJCQkJCWlmKChpID0gdVszXSkgJiYgZC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lICYmIGUuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSkgcmV0dXJuIEguYXBwbHkobiwgZS5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKGkpKSwgbg0KCQkJCQl9DQoJCQkJCWlmKGQucXNhICYmICFOW3QgKyAiICJdICYmICgheSB8fCAheS50ZXN0KHQpKSAmJiAoMSAhPT0gcCB8fCAib2JqZWN0IiAhPT0gZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpKSkgew0KCQkJCQkJaWYoYyA9IHQsIGYgPSBlLCAxID09PSBwICYmIChVLnRlc3QodCkgfHwgei50ZXN0KHQpKSkgew0KCQkJCQkJCShmID0gZWUudGVzdCh0KSAmJiB2ZShlLnBhcmVudE5vZGUpIHx8IGUpID09PSBlICYmIGQuc2NvcGUgfHwgKChzID0gZS5nZXRBdHRyaWJ1dGUoImlkIikpID8gcyA9IHMucmVwbGFjZShyZSwgaWUpIDogZS5zZXRBdHRyaWJ1dGUoImlkIiwgcyA9IEUpKSwgbyA9IChsID0gaCh0KSkubGVuZ3RoOw0KCQkJCQkJCXdoaWxlKG8tLSkgbFtvXSA9IChzID8gIiMiICsgcyA6ICI6c2NvcGUiKSArICIgIiArIHhlKGxbb10pOw0KCQkJCQkJCWMgPSBsLmpvaW4oIiwiKQ0KCQkJCQkJfQ0KCQkJCQkJdHJ5IHsNCgkJCQkJCQlpZihkLmNzc1N1cHBvcnRzU2VsZWN0b3IgJiYgIUNTUy5zdXBwb3J0cygic2VsZWN0b3IoOmlzKCIgKyBjICsgIikpIikpIHRocm93IG5ldyBFcnJvcjsNCgkJCQkJCQlyZXR1cm4gSC5hcHBseShuLCBmLnF1ZXJ5U2VsZWN0b3JBbGwoYykpLCBuDQoJCQkJCQl9IGNhdGNoKGUpIHtOKHQsICEwKX0gZmluYWxseSB7cyA9PT0gRSAmJiBlLnJlbW92ZUF0dHJpYnV0ZSgiaWQiKX0NCgkJCQkJfQ0KCQkJCX0NCgkJCQlyZXR1cm4gZyh0LnJlcGxhY2UoQiwgIiQxIiksIGUsIG4sIHIpDQoJCQl9DQoNCgkJCWZ1bmN0aW9uIHVlKCkgew0KCQkJCXZhciByID0gW107DQoJCQkJcmV0dXJuIGZ1bmN0aW9uIGUodCwgbikge3JldHVybiByLnB1c2godCArICIgIikgPiBiLmNhY2hlTGVuZ3RoICYmIGRlbGV0ZSBlW3Iuc2hpZnQoKV0sIGVbdCArICIgIl0gPSBufQ0KCQkJfQ0KDQoJCQlmdW5jdGlvbiBsZShlKSB7cmV0dXJuIGVbRV0gPSAhMCwgZX0NCg0KCQkJZnVuY3Rpb24gY2UoZSkgew0KCQkJCXZhciB0ID0gQy5jcmVhdGVFbGVtZW50KCJmaWVsZHNldCIpOw0KCQkJCXRyeSB7cmV0dXJuICEhZSh0KX0gY2F0Y2goZSkge3JldHVybiAhMX0gZmluYWxseSB7dC5wYXJlbnROb2RlICYmIHQucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0KSwgdCA9IG51bGx9DQoJCQl9DQoNCgkJCWZ1bmN0aW9uIGZlKGUsIHQpIHsNCgkJCQl2YXIgbiA9IGUuc3BsaXQoInwiKSwgciA9IG4ubGVuZ3RoOw0KCQkJCXdoaWxlKHItLSkgYi5hdHRySGFuZGxlW25bcl1dID0gdA0KCQkJfQ0KDQoJCQlmdW5jdGlvbiBwZShlLCB0KSB7DQoJCQkJdmFyIG4gPSB0ICYmIGUsIHIgPSBuICYmIDEgPT09IGUubm9kZVR5cGUgJiYgMSA9PT0gdC5ub2RlVHlwZSAmJiBlLnNvdXJjZUluZGV4IC0gdC5zb3VyY2VJbmRleDsNCgkJCQlpZihyKSByZXR1cm4gcjsNCgkJCQlpZihuKSB3aGlsZShuID0gbi5uZXh0U2libGluZykgaWYobiA9PT0gdCkgcmV0dXJuIC0xOw0KCQkJCXJldHVybiBlID8gMSA6IC0xDQoJCQl9DQoNCgkJCWZ1bmN0aW9uIGRlKHQpIHtyZXR1cm4gZnVuY3Rpb24oZSkge3JldHVybiAiaW5wdXQiID09PSBlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgJiYgZS50eXBlID09PSB0fX0NCg0KCQkJZnVuY3Rpb24gaGUobikgew0KCQkJCXJldHVybiBmdW5jdGlvbihlKSB7DQoJCQkJCXZhciB0ID0gZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpOw0KCQkJCQlyZXR1cm4gKCJpbnB1dCIgPT09IHQgfHwgImJ1dHRvbiIgPT09IHQpICYmIGUudHlwZSA9PT0gbg0KCQkJCX0NCgkJCX0NCg0KCQkJZnVuY3Rpb24gZ2UodCkge3JldHVybiBmdW5jdGlvbihlKSB7cmV0dXJuICJmb3JtIiBpbiBlID8gZS5wYXJlbnROb2RlICYmICExID09PSBlLmRpc2FibGVkID8gImxhYmVsIiBpbiBlID8gImxhYmVsIiBpbiBlLnBhcmVudE5vZGUgPyBlLnBhcmVudE5vZGUuZGlzYWJsZWQgPT09IHQgOiBlLmRpc2FibGVkID09PSB0IDogZS5pc0Rpc2FibGVkID09PSB0IHx8IGUuaXNEaXNhYmxlZCAhPT0gIXQgJiYgYWUoZSkgPT09IHQgOiBlLmRpc2FibGVkID09PSB0IDogImxhYmVsIiBpbiBlICYmIGUuZGlzYWJsZWQgPT09IHR9fQ0KDQoJCQlmdW5jdGlvbiB5ZShhKSB7DQoJCQkJcmV0dXJuIGxlKGZ1bmN0aW9uKG8pIHsNCgkJCQkJcmV0dXJuIG8gPSArbywgbGUoZnVuY3Rpb24oZSwgdCkgew0KCQkJCQkJdmFyIG4sIHIgPSBhKFtdLCBlLmxlbmd0aCwgbyksIGkgPSByLmxlbmd0aDsNCgkJCQkJCXdoaWxlKGktLSkgZVtuID0gcltpXV0gJiYgKGVbbl0gPSAhKHRbbl0gPSBlW25dKSkNCgkJCQkJfSkNCgkJCQl9KQ0KCQkJfQ0KDQoJCQlmdW5jdGlvbiB2ZShlKSB7cmV0dXJuIGUgJiYgInVuZGVmaW5lZCIgIT0gdHlwZW9mIGUuZ2V0RWxlbWVudHNCeVRhZ05hbWUgJiYgZX0NCg0KCQkJZm9yKGUgaW4gZCA9IHNlLnN1cHBvcnQgPSB7fSwgaSA9IHNlLmlzWE1MID0gZnVuY3Rpb24oZSkgew0KCQkJCXZhciB0ID0gZSAmJiBlLm5hbWVzcGFjZVVSSSwgbiA9IGUgJiYgKGUub3duZXJEb2N1bWVudCB8fCBlKS5kb2N1bWVudEVsZW1lbnQ7DQoJCQkJcmV0dXJuICFZLnRlc3QodCB8fCBuICYmIG4ubm9kZU5hbWUgfHwgIkhUTUwiKQ0KCQkJfSwgVCA9IHNlLnNldERvY3VtZW50ID0gZnVuY3Rpb24oZSkgew0KCQkJCXZhciB0LCBuLCByID0gZSA/IGUub3duZXJEb2N1bWVudCB8fCBlIDogcDsNCgkJCQlyZXR1cm4gciAhPSBDICYmIDkgPT09IHIubm9kZVR5cGUgJiYgci5kb2N1bWVudEVsZW1lbnQgJiYgKGEgPSAoQyA9IHIpLmRvY3VtZW50RWxlbWVudCwgUyA9ICFpKEMpLCBwICE9IEMgJiYgKG4gPSBDLmRlZmF1bHRWaWV3KSAmJiBuLnRvcCAhPT0gbiAmJiAobi5hZGRFdmVudExpc3RlbmVyID8gbi5hZGRFdmVudExpc3RlbmVyKCJ1bmxvYWQiLCBvZSwgITEpIDogbi5hdHRhY2hFdmVudCAmJiBuLmF0dGFjaEV2ZW50KCJvbnVubG9hZCIsIG9lKSksIGQuc2NvcGUgPSBjZShmdW5jdGlvbihlKSB7cmV0dXJuIGEuYXBwZW5kQ2hpbGQoZSkuYXBwZW5kQ2hpbGQoQy5jcmVhdGVFbGVtZW50KCJkaXYiKSksICJ1bmRlZmluZWQiICE9IHR5cGVvZiBlLnF1ZXJ5U2VsZWN0b3JBbGwgJiYgIWUucXVlcnlTZWxlY3RvckFsbCgiOnNjb3BlIGZpZWxkc2V0IGRpdiIpLmxlbmd0aH0pLCBkLmNzc1N1cHBvcnRzU2VsZWN0b3IgPSBjZShmdW5jdGlvbigpIHtyZXR1cm4gQ1NTLnN1cHBvcnRzKCJzZWxlY3RvcigqKSIpICYmIEMucXVlcnlTZWxlY3RvckFsbCgiOmlzKDpqcWZha2UpIikgJiYgIUNTUy5zdXBwb3J0cygic2VsZWN0b3IoOmlzKCosOmpxZmFrZSkpIil9KSwgZC5hdHRyaWJ1dGVzID0gY2UoZnVuY3Rpb24oZSkge3JldHVybiBlLmNsYXNzTmFtZSA9ICJpIiwgIWUuZ2V0QXR0cmlidXRlKCJjbGFzc05hbWUiKX0pLCBkLmdldEVsZW1lbnRzQnlUYWdOYW1lID0gY2UoZnVuY3Rpb24oZSkge3JldHVybiBlLmFwcGVuZENoaWxkKEMuY3JlYXRlQ29tbWVudCgiIikpLCAhZS5nZXRFbGVtZW50c0J5VGFnTmFtZSgiKiIpLmxlbmd0aH0pLCBkLmdldEVsZW1lbnRzQnlDbGFzc05hbWUgPSBLLnRlc3QoQy5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKSwgZC5nZXRCeUlkID0gY2UoZnVuY3Rpb24oZSkge3JldHVybiBhLmFwcGVuZENoaWxkKGUpLmlkID0gRSwgIUMuZ2V0RWxlbWVudHNCeU5hbWUgfHwgIUMuZ2V0RWxlbWVudHNCeU5hbWUoRSkubGVuZ3RofSksIGQuZ2V0QnlJZCA/IChiLmZpbHRlci5JRCA9IGZ1bmN0aW9uKGUpIHsNCgkJCQkJdmFyIHQgPSBlLnJlcGxhY2UodGUsIG5lKTsNCgkJCQkJcmV0dXJuIGZ1bmN0aW9uKGUpIHtyZXR1cm4gZS5nZXRBdHRyaWJ1dGUoImlkIikgPT09IHR9DQoJCQkJfSwgYi5maW5kLklEID0gZnVuY3Rpb24oZSwgdCkgew0KCQkJCQlpZigidW5kZWZpbmVkIiAhPSB0eXBlb2YgdC5nZXRFbGVtZW50QnlJZCAmJiBTKSB7DQoJCQkJCQl2YXIgbiA9IHQuZ2V0RWxlbWVudEJ5SWQoZSk7DQoJCQkJCQlyZXR1cm4gbiA/IFtuXSA6IFtdDQoJCQkJCX0NCgkJCQl9KSA6IChiLmZpbHRlci5JRCA9IGZ1bmN0aW9uKGUpIHsNCgkJCQkJdmFyIG4gPSBlLnJlcGxhY2UodGUsIG5lKTsNCgkJCQkJcmV0dXJuIGZ1bmN0aW9uKGUpIHsNCgkJCQkJCXZhciB0ID0gInVuZGVmaW5lZCIgIT0gdHlwZW9mIGUuZ2V0QXR0cmlidXRlTm9kZSAmJiBlLmdldEF0dHJpYnV0ZU5vZGUoImlkIik7DQoJCQkJCQlyZXR1cm4gdCAmJiB0LnZhbHVlID09PSBuDQoJCQkJCX0NCgkJCQl9LCBiLmZpbmQuSUQgPSBmdW5jdGlvbihlLCB0KSB7DQoJCQkJCWlmKCJ1bmRlZmluZWQiICE9IHR5cGVvZiB0LmdldEVsZW1lbnRCeUlkICYmIFMpIHsNCgkJCQkJCXZhciBuLCByLCBpLCBvID0gdC5nZXRFbGVtZW50QnlJZChlKTsNCgkJCQkJCWlmKG8pIHsNCgkJCQkJCQlpZigobiA9IG8uZ2V0QXR0cmlidXRlTm9kZSgiaWQiKSkgJiYgbi52YWx1ZSA9PT0gZSkgcmV0dXJuIFtvXTsNCgkJCQkJCQlpID0gdC5nZXRFbGVtZW50c0J5TmFtZShlKSwgciA9IDA7DQoJCQkJCQkJd2hpbGUobyA9IGlbcisrXSkgaWYoKG4gPSBvLmdldEF0dHJpYnV0ZU5vZGUoImlkIikpICYmIG4udmFsdWUgPT09IGUpIHJldHVybiBbb10NCgkJCQkJCX0NCgkJCQkJCXJldHVybiBbXQ0KCQkJCQl9DQoJCQkJfSksIGIuZmluZC5UQUcgPSBkLmdldEVsZW1lbnRzQnlUYWdOYW1lID8gZnVuY3Rpb24oZSwgdCkge3JldHVybiAidW5kZWZpbmVkIiAhPSB0eXBlb2YgdC5nZXRFbGVtZW50c0J5VGFnTmFtZSA/IHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoZSkgOiBkLnFzYSA/IHQucXVlcnlTZWxlY3RvckFsbChlKSA6IHZvaWQgMH0gOiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJCXZhciBuLCByID0gW10sIGkgPSAwLCBvID0gdC5nZXRFbGVtZW50c0J5VGFnTmFtZShlKTsNCgkJCQkJaWYoIioiID09PSBlKSB7DQoJCQkJCQl3aGlsZShuID0gb1tpKytdKSAxID09PSBuLm5vZGVUeXBlICYmIHIucHVzaChuKTsNCgkJCQkJCXJldHVybiByDQoJCQkJCX0NCgkJCQkJcmV0dXJuIG8NCgkJCQl9LCBiLmZpbmQuQ0xBU1MgPSBkLmdldEVsZW1lbnRzQnlDbGFzc05hbWUgJiYgZnVuY3Rpb24oZSwgdCkge2lmKCJ1bmRlZmluZWQiICE9IHR5cGVvZiB0LmdldEVsZW1lbnRzQnlDbGFzc05hbWUgJiYgUykgcmV0dXJuIHQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShlKX0sIHMgPSBbXSwgeSA9IFtdLCAoZC5xc2EgPSBLLnRlc3QoQy5xdWVyeVNlbGVjdG9yQWxsKSkgJiYgKGNlKGZ1bmN0aW9uKGUpIHsNCgkJCQkJdmFyIHQ7DQoJCQkJCWEuYXBwZW5kQ2hpbGQoZSkuaW5uZXJIVE1MID0gIjxhIGlkPSciICsgRSArICInPjwvYT48c2VsZWN0IGlkPSciICsgRSArICItXHJcXCcgbXNhbGxvd2NhcHR1cmU9Jyc+PG9wdGlvbiBzZWxlY3RlZD0nJz48L29wdGlvbj48L3NlbGVjdD4iLCBlLnF1ZXJ5U2VsZWN0b3JBbGwoIlttc2FsbG93Y2FwdHVyZV49JyddIikubGVuZ3RoICYmIHkucHVzaCgiWypeJF09IiArIE0gKyAiKig/OicnfFwiXCIpIiksIGUucXVlcnlTZWxlY3RvckFsbCgiW3NlbGVjdGVkXSIpLmxlbmd0aCB8fCB5LnB1c2goIlxcWyIgKyBNICsgIiooPzp2YWx1ZXwiICsgUiArICIpIiksIGUucXVlcnlTZWxlY3RvckFsbCgiW2lkfj0iICsgRSArICItXSIpLmxlbmd0aCB8fCB5LnB1c2goIn49IiksICh0ID0gQy5jcmVhdGVFbGVtZW50KCJpbnB1dCIpKS5zZXRBdHRyaWJ1dGUoIm5hbWUiLCAiIiksIGUuYXBwZW5kQ2hpbGQodCksIGUucXVlcnlTZWxlY3RvckFsbCgiW25hbWU9JyddIikubGVuZ3RoIHx8IHkucHVzaCgiXFxbIiArIE0gKyAiKm5hbWUiICsgTSArICIqPSIgKyBNICsgIiooPzonJ3xcIlwiKSIpLCBlLnF1ZXJ5U2VsZWN0b3JBbGwoIjpjaGVja2VkIikubGVuZ3RoIHx8IHkucHVzaCgiOmNoZWNrZWQiKSwgZS5xdWVyeVNlbGVjdG9yQWxsKCJhIyIgKyBFICsgIisqIikubGVuZ3RoIHx8IHkucHVzaCgiLiMuK1srfl0iKSwgZS5xdWVyeVNlbGVjdG9yQWxsKCJcXFxmIiksIHkucHVzaCgiW1xcclxcblxcZl0iKQ0KCQkJCX0pLCBjZShmdW5jdGlvbihlKSB7DQoJCQkJCWUuaW5uZXJIVE1MID0gIjxhIGhyZWY9JycgZGlzYWJsZWQ9J2Rpc2FibGVkJz48L2E+PHNlbGVjdCBkaXNhYmxlZD0nZGlzYWJsZWQnPjxvcHRpb24vPjwvc2VsZWN0PiI7DQoJCQkJCXZhciB0ID0gQy5jcmVhdGVFbGVtZW50KCJpbnB1dCIpOw0KCQkJCQl0LnNldEF0dHJpYnV0ZSgidHlwZSIsICJoaWRkZW4iKSwgZS5hcHBlbmRDaGlsZCh0KS5zZXRBdHRyaWJ1dGUoIm5hbWUiLCAiRCIpLCBlLnF1ZXJ5U2VsZWN0b3JBbGwoIltuYW1lPWRdIikubGVuZ3RoICYmIHkucHVzaCgibmFtZSIgKyBNICsgIipbKl4kfCF+XT89IiksIDIgIT09IGUucXVlcnlTZWxlY3RvckFsbCgiOmVuYWJsZWQiKS5sZW5ndGggJiYgeS5wdXNoKCI6ZW5hYmxlZCIsICI6ZGlzYWJsZWQiKSwgYS5hcHBlbmRDaGlsZChlKS5kaXNhYmxlZCA9ICEwLCAyICE9PSBlLnF1ZXJ5U2VsZWN0b3JBbGwoIjpkaXNhYmxlZCIpLmxlbmd0aCAmJiB5LnB1c2goIjplbmFibGVkIiwgIjpkaXNhYmxlZCIpLCBlLnF1ZXJ5U2VsZWN0b3JBbGwoIiosOngiKSwgeS5wdXNoKCIsLio6IikNCgkJCQl9KSksIChkLm1hdGNoZXNTZWxlY3RvciA9IEsudGVzdChjID0gYS5tYXRjaGVzIHx8IGEud2Via2l0TWF0Y2hlc1NlbGVjdG9yIHx8IGEubW96TWF0Y2hlc1NlbGVjdG9yIHx8IGEub01hdGNoZXNTZWxlY3RvciB8fCBhLm1zTWF0Y2hlc1NlbGVjdG9yKSkgJiYgY2UoZnVuY3Rpb24oZSkge2QuZGlzY29ubmVjdGVkTWF0Y2ggPSBjLmNhbGwoZSwgIioiKSwgYy5jYWxsKGUsICJbcyE9JyddOngiKSwgcy5wdXNoKCIhPSIsIEYpfSksIGQuY3NzU3VwcG9ydHNTZWxlY3RvciB8fCB5LnB1c2goIjpoYXMiKSwgeSA9IHkubGVuZ3RoICYmIG5ldyBSZWdFeHAoeS5qb2luKCJ8IikpLCBzID0gcy5sZW5ndGggJiYgbmV3IFJlZ0V4cChzLmpvaW4oInwiKSksIHQgPSBLLnRlc3QoYS5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbiksIHYgPSB0IHx8IEsudGVzdChhLmNvbnRhaW5zKSA/IGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQkJdmFyIG4gPSA5ID09PSBlLm5vZGVUeXBlICYmIGUuZG9jdW1lbnRFbGVtZW50IHx8IGUsDQoJCQkJCSAgICByID0gdCAmJiB0LnBhcmVudE5vZGU7DQoJCQkJCXJldHVybiBlID09PSByIHx8ICEoIXIgfHwgMSAhPT0gci5ub2RlVHlwZSB8fCAhKG4uY29udGFpbnMgPyBuLmNvbnRhaW5zKHIpIDogZS5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbiAmJiAxNiAmIGUuY29tcGFyZURvY3VtZW50UG9zaXRpb24ocikpKQ0KCQkJCX0gOiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJCWlmKHQpIHdoaWxlKHQgPSB0LnBhcmVudE5vZGUpIGlmKHQgPT09IGUpIHJldHVybiAhMDsNCgkJCQkJcmV0dXJuICExDQoJCQkJfSwgaiA9IHQgPyBmdW5jdGlvbihlLCB0KSB7DQoJCQkJCWlmKGUgPT09IHQpIHJldHVybiBsID0gITAsIDA7DQoJCQkJCXZhciBuID0gIWUuY29tcGFyZURvY3VtZW50UG9zaXRpb24gLSAhdC5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbjsNCgkJCQkJcmV0dXJuIG4gfHwgKDEgJiAobiA9IChlLm93bmVyRG9jdW1lbnQgfHwgZSkgPT0gKHQub3duZXJEb2N1bWVudCB8fCB0KSA/IGUuY29tcGFyZURvY3VtZW50UG9zaXRpb24odCkgOiAxKSB8fCAhZC5zb3J0RGV0YWNoZWQgJiYgdC5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbihlKSA9PT0gbiA/IGUgPT0gQyB8fCBlLm93bmVyRG9jdW1lbnQgPT0gcCAmJiB2KHAsIGUpID8gLTEgOiB0ID09IEMgfHwgdC5vd25lckRvY3VtZW50ID09IHAgJiYgdihwLCB0KSA/IDEgOiB1ID8gUCh1LCBlKSAtIFAodSwgdCkgOiAwIDogNCAmIG4gPyAtMSA6IDEpDQoJCQkJfSA6IGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQkJaWYoZSA9PT0gdCkgcmV0dXJuIGwgPSAhMCwgMDsNCgkJCQkJdmFyIG4sIHIgPSAwLCBpID0gZS5wYXJlbnROb2RlLCBvID0gdC5wYXJlbnROb2RlLCBhID0gW2VdLCBzID0gW3RdOw0KCQkJCQlpZighaSB8fCAhbykgcmV0dXJuIGUgPT0gQyA/IC0xIDogdCA9PSBDID8gMSA6IGkgPyAtMSA6IG8gPyAxIDogdSA/IFAodSwgZSkgLSBQKHUsIHQpIDogMDsNCgkJCQkJaWYoaSA9PT0gbykgcmV0dXJuIHBlKGUsIHQpOw0KCQkJCQluID0gZTsNCgkJCQkJd2hpbGUobiA9IG4ucGFyZW50Tm9kZSkgYS51bnNoaWZ0KG4pOw0KCQkJCQluID0gdDsNCgkJCQkJd2hpbGUobiA9IG4ucGFyZW50Tm9kZSkgcy51bnNoaWZ0KG4pOw0KCQkJCQl3aGlsZShhW3JdID09PSBzW3JdKSByKys7DQoJCQkJCXJldHVybiByID8gcGUoYVtyXSwgc1tyXSkgOiBhW3JdID09IHAgPyAtMSA6IHNbcl0gPT0gcCA/IDEgOiAwDQoJCQkJfSksIEMNCgkJCX0sIHNlLm1hdGNoZXMgPSBmdW5jdGlvbihlLCB0KSB7cmV0dXJuIHNlKGUsIG51bGwsIG51bGwsIHQpfSwgc2UubWF0Y2hlc1NlbGVjdG9yID0gZnVuY3Rpb24oZSwgdCkgew0KCQkJCWlmKFQoZSksIGQubWF0Y2hlc1NlbGVjdG9yICYmIFMgJiYgIU5bdCArICIgIl0gJiYgKCFzIHx8ICFzLnRlc3QodCkpICYmICgheSB8fCAheS50ZXN0KHQpKSkgdHJ5IHsNCgkJCQkJdmFyIG4gPSBjLmNhbGwoZSwgdCk7DQoJCQkJCWlmKG4gfHwgZC5kaXNjb25uZWN0ZWRNYXRjaCB8fCBlLmRvY3VtZW50ICYmIDExICE9PSBlLmRvY3VtZW50Lm5vZGVUeXBlKSByZXR1cm4gbg0KCQkJCX0gY2F0Y2goZSkge04odCwgITApfQ0KCQkJCXJldHVybiAwIDwgc2UodCwgQywgbnVsbCwgW2VdKS5sZW5ndGgNCgkJCX0sIHNlLmNvbnRhaW5zID0gZnVuY3Rpb24oZSwgdCkge3JldHVybiAoZS5vd25lckRvY3VtZW50IHx8IGUpICE9IEMgJiYgVChlKSwgdihlLCB0KX0sIHNlLmF0dHIgPSBmdW5jdGlvbihlLCB0KSB7DQoJCQkJKGUub3duZXJEb2N1bWVudCB8fCBlKSAhPSBDICYmIFQoZSk7DQoJCQkJdmFyIG4gPSBiLmF0dHJIYW5kbGVbdC50b0xvd2VyQ2FzZSgpXSwgciA9IG4gJiYgRC5jYWxsKGIuYXR0ckhhbmRsZSwgdC50b0xvd2VyQ2FzZSgpKSA/IG4oZSwgdCwgIVMpIDogdm9pZCAwOw0KCQkJCXJldHVybiB2b2lkIDAgIT09IHIgPyByIDogZC5hdHRyaWJ1dGVzIHx8ICFTID8gZS5nZXRBdHRyaWJ1dGUodCkgOiAociA9IGUuZ2V0QXR0cmlidXRlTm9kZSh0KSkgJiYgci5zcGVjaWZpZWQgPyByLnZhbHVlIDogbnVsbA0KCQkJfSwgc2UuZXNjYXBlID0gZnVuY3Rpb24oZSkge3JldHVybiAoZSArICIiKS5yZXBsYWNlKHJlLCBpZSl9LCBzZS5lcnJvciA9IGZ1bmN0aW9uKGUpIHt0aHJvdyBuZXcgRXJyb3IoIlN5bnRheCBlcnJvciwgdW5yZWNvZ25pemVkIGV4cHJlc3Npb246ICIgKyBlKX0sIHNlLnVuaXF1ZVNvcnQgPSBmdW5jdGlvbihlKSB7DQoJCQkJdmFyIHQsIG4gPSBbXSwgciA9IDAsIGkgPSAwOw0KCQkJCWlmKGwgPSAhZC5kZXRlY3REdXBsaWNhdGVzLCB1ID0gIWQuc29ydFN0YWJsZSAmJiBlLnNsaWNlKDApLCBlLnNvcnQoaiksIGwpIHsNCgkJCQkJd2hpbGUodCA9IGVbaSsrXSkgdCA9PT0gZVtpXSAmJiAociA9IG4ucHVzaChpKSk7DQoJCQkJCXdoaWxlKHItLSkgZS5zcGxpY2UobltyXSwgMSkNCgkJCQl9DQoJCQkJcmV0dXJuIHUgPSBudWxsLCBlDQoJCQl9LCBvID0gc2UuZ2V0VGV4dCA9IGZ1bmN0aW9uKGUpIHsNCgkJCQl2YXIgdCwgbiA9ICIiLCByID0gMCwgaSA9IGUubm9kZVR5cGU7DQoJCQkJaWYoaSkgew0KCQkJCQlpZigxID09PSBpIHx8IDkgPT09IGkgfHwgMTEgPT09IGkpIHsNCgkJCQkJCWlmKCJzdHJpbmciID09IHR5cGVvZiBlLnRleHRDb250ZW50KSByZXR1cm4gZS50ZXh0Q29udGVudDsNCgkJCQkJCWZvcihlID0gZS5maXJzdENoaWxkOyBlOyBlID0gZS5uZXh0U2libGluZykgbiArPSBvKGUpDQoJCQkJCX0gZWxzZSBpZigzID09PSBpIHx8IDQgPT09IGkpIHJldHVybiBlLm5vZGVWYWx1ZQ0KCQkJCX0gZWxzZSB3aGlsZSh0ID0gZVtyKytdKSBuICs9IG8odCk7DQoJCQkJcmV0dXJuIG4NCgkJCX0sIChiID0gc2Uuc2VsZWN0b3JzID0gew0KCQkJCWNhY2hlTGVuZ3RoOiA1MCwNCgkJCQljcmVhdGVQc2V1ZG86IGxlLA0KCQkJCW1hdGNoOiBHLA0KCQkJCWF0dHJIYW5kbGU6IHt9LA0KCQkJCWZpbmQ6IHt9LA0KCQkJCXJlbGF0aXZlOiB7Ij4iOiB7ZGlyOiAicGFyZW50Tm9kZSIsIGZpcnN0OiAhMH0sICIgIjoge2RpcjogInBhcmVudE5vZGUifSwgIisiOiB7ZGlyOiAicHJldmlvdXNTaWJsaW5nIiwgZmlyc3Q6ICEwfSwgIn4iOiB7ZGlyOiAicHJldmlvdXNTaWJsaW5nIn19LA0KCQkJCXByZUZpbHRlcjogew0KCQkJCQlBVFRSOiBmdW5jdGlvbihlKSB7cmV0dXJuIGVbMV0gPSBlWzFdLnJlcGxhY2UodGUsIG5lKSwgZVszXSA9IChlWzNdIHx8IGVbNF0gfHwgZVs1XSB8fCAiIikucmVwbGFjZSh0ZSwgbmUpLCAifj0iID09PSBlWzJdICYmIChlWzNdID0gIiAiICsgZVszXSArICIgIiksIGUuc2xpY2UoMCwgNCl9LA0KCQkJCQlDSElMRDogZnVuY3Rpb24oZSkge3JldHVybiBlWzFdID0gZVsxXS50b0xvd2VyQ2FzZSgpLCAibnRoIiA9PT0gZVsxXS5zbGljZSgwLCAzKSA/IChlWzNdIHx8IHNlLmVycm9yKGVbMF0pLCBlWzRdID0gKyhlWzRdID8gZVs1XSArIChlWzZdIHx8IDEpIDogMiAqICgiZXZlbiIgPT09IGVbM10gfHwgIm9kZCIgPT09IGVbM10pKSwgZVs1XSA9ICsoZVs3XSArIGVbOF0gfHwgIm9kZCIgPT09IGVbM10pKSA6IGVbM10gJiYgc2UuZXJyb3IoZVswXSksIGV9LA0KCQkJCQlQU0VVRE86IGZ1bmN0aW9uKGUpIHsNCgkJCQkJCXZhciB0LCBuID0gIWVbNl0gJiYgZVsyXTsNCgkJCQkJCXJldHVybiBHLkNISUxELnRlc3QoZVswXSkgPyBudWxsIDogKGVbM10gPyBlWzJdID0gZVs0XSB8fCBlWzVdIHx8ICIiIDogbiAmJiBYLnRlc3QobikgJiYgKHQgPSBoKG4sICEwKSkgJiYgKHQgPSBuLmluZGV4T2YoIikiLCBuLmxlbmd0aCAtIHQpIC0gbi5sZW5ndGgpICYmIChlWzBdID0gZVswXS5zbGljZSgwLCB0KSwgZVsyXSA9IG4uc2xpY2UoMCwgdCkpLCBlLnNsaWNlKDAsIDMpKQ0KCQkJCQl9DQoJCQkJfSwNCgkJCQlmaWx0ZXI6IHsNCgkJCQkJVEFHOiBmdW5jdGlvbihlKSB7DQoJCQkJCQl2YXIgdCA9IGUucmVwbGFjZSh0ZSwgbmUpLnRvTG93ZXJDYXNlKCk7DQoJCQkJCQlyZXR1cm4gIioiID09PSBlID8gZnVuY3Rpb24oKSB7cmV0dXJuICEwfSA6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gZS5ub2RlTmFtZSAmJiBlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IHR9DQoJCQkJCX0sIENMQVNTOiBmdW5jdGlvbihlKSB7DQoJCQkJCQl2YXIgdCA9IG1bZSArICIgIl07DQoJCQkJCQlyZXR1cm4gdCB8fCAodCA9IG5ldyBSZWdFeHAoIihefCIgKyBNICsgIikiICsgZSArICIoIiArIE0gKyAifCQpIikpICYmIG0oZSwgZnVuY3Rpb24oZSkge3JldHVybiB0LnRlc3QoInN0cmluZyIgPT0gdHlwZW9mIGUuY2xhc3NOYW1lICYmIGUuY2xhc3NOYW1lIHx8ICJ1bmRlZmluZWQiICE9IHR5cGVvZiBlLmdldEF0dHJpYnV0ZSAmJiBlLmdldEF0dHJpYnV0ZSgiY2xhc3MiKSB8fCAiIil9KQ0KCQkJCQl9LCBBVFRSOiBmdW5jdGlvbihuLCByLCBpKSB7DQoJCQkJCQlyZXR1cm4gZnVuY3Rpb24oZSkgew0KCQkJCQkJCXZhciB0ID0gc2UuYXR0cihlLCBuKTsNCgkJCQkJCQlyZXR1cm4gbnVsbCA9PSB0ID8gIiE9IiA9PT0gciA6ICFyIHx8ICh0ICs9ICIiLCAiPSIgPT09IHIgPyB0ID09PSBpIDogIiE9IiA9PT0gciA/IHQgIT09IGkgOiAiXj0iID09PSByID8gaSAmJiAwID09PSB0LmluZGV4T2YoaSkgOiAiKj0iID09PSByID8gaSAmJiAtMSA8IHQuaW5kZXhPZihpKSA6ICIkPSIgPT09IHIgPyBpICYmIHQuc2xpY2UoLWkubGVuZ3RoKSA9PT0gaSA6ICJ+PSIgPT09IHIgPyAtMSA8ICgiICIgKyB0LnJlcGxhY2UoJCwgIiAiKSArICIgIikuaW5kZXhPZihpKSA6ICJ8PSIgPT09IHIgJiYgKHQgPT09IGkgfHwgdC5zbGljZSgwLCBpLmxlbmd0aCArIDEpID09PSBpICsgIi0iKSkNCgkJCQkJCX0NCgkJCQkJfSwgQ0hJTEQ6IGZ1bmN0aW9uKGgsIGUsIHQsIGcsIHkpIHsNCgkJCQkJCXZhciB2ID0gIm50aCIgIT09IGguc2xpY2UoMCwgMyksIG0gPSAibGFzdCIgIT09IGguc2xpY2UoLTQpLCB4ID0gIm9mLXR5cGUiID09PSBlOw0KCQkJCQkJcmV0dXJuIDEgPT09IGcgJiYgMCA9PT0geSA/IGZ1bmN0aW9uKGUpIHtyZXR1cm4gISFlLnBhcmVudE5vZGV9IDogZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJCQkJCXZhciByLCBpLCBvLCBhLCBzLCB1LCBsID0gdiAhPT0gbSA/ICJuZXh0U2libGluZyIgOiAicHJldmlvdXNTaWJsaW5nIiwgYyA9IGUucGFyZW50Tm9kZSwgZiA9IHggJiYgZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpLCBwID0gIW4gJiYgIXgsIGQgPSAhMTsNCgkJCQkJCQlpZihjKSB7DQoJCQkJCQkJCWlmKHYpIHsNCgkJCQkJCQkJCXdoaWxlKGwpIHsNCgkJCQkJCQkJCQlhID0gZTsNCgkJCQkJCQkJCQl3aGlsZShhID0gYVtsXSkgaWYoeCA/IGEubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gZiA6IDEgPT09IGEubm9kZVR5cGUpIHJldHVybiAhMTsNCgkJCQkJCQkJCQl1ID0gbCA9ICJvbmx5IiA9PT0gaCAmJiAhdSAmJiAibmV4dFNpYmxpbmciDQoJCQkJCQkJCQl9DQoJCQkJCQkJCQlyZXR1cm4gITANCgkJCQkJCQkJfQ0KCQkJCQkJCQlpZih1ID0gW20gPyBjLmZpcnN0Q2hpbGQgOiBjLmxhc3RDaGlsZF0sIG0gJiYgcCkgew0KCQkJCQkJCQkJZCA9IChzID0gKHIgPSAoaSA9IChvID0gKGEgPSBjKVtFXSB8fCAoYVtFXSA9IHt9KSlbYS51bmlxdWVJRF0gfHwgKG9bYS51bmlxdWVJRF0gPSB7fSkpW2hdIHx8IFtdKVswXSA9PT0gayAmJiByWzFdKSAmJiByWzJdLCBhID0gcyAmJiBjLmNoaWxkTm9kZXNbc107DQoJCQkJCQkJCQl3aGlsZShhID0gKytzICYmIGEgJiYgYVtsXSB8fCAoZCA9IHMgPSAwKSB8fCB1LnBvcCgpKSBpZigxID09PSBhLm5vZGVUeXBlICYmICsrZCAmJiBhID09PSBlKSB7DQoJCQkJCQkJCQkJaVtoXSA9IFtrLCBzLCBkXTsNCgkJCQkJCQkJCQlicmVhaw0KCQkJCQkJCQkJfQ0KCQkJCQkJCQl9IGVsc2UgaWYocCAmJiAoZCA9IHMgPSAociA9IChpID0gKG8gPSAoYSA9IGUpW0VdIHx8IChhW0VdID0ge30pKVthLnVuaXF1ZUlEXSB8fCAob1thLnVuaXF1ZUlEXSA9IHt9KSlbaF0gfHwgW10pWzBdID09PSBrICYmIHJbMV0pLCAhMSA9PT0gZCkgd2hpbGUoYSA9ICsrcyAmJiBhICYmIGFbbF0gfHwgKGQgPSBzID0gMCkgfHwgdS5wb3AoKSkgaWYoKHggPyBhLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IGYgOiAxID09PSBhLm5vZGVUeXBlKSAmJiArK2QgJiYgKHAgJiYgKChpID0gKG8gPSBhW0VdIHx8IChhW0VdID0ge30pKVthLnVuaXF1ZUlEXSB8fCAob1thLnVuaXF1ZUlEXSA9IHt9KSlbaF0gPSBbaywgZF0pLCBhID09PSBlKSkgYnJlYWs7DQoJCQkJCQkJCXJldHVybiAoZCAtPSB5KSA9PT0gZyB8fCBkICUgZyA9PSAwICYmIDAgPD0gZCAvIGcNCgkJCQkJCQl9DQoJCQkJCQl9DQoJCQkJCX0sIFBTRVVETzogZnVuY3Rpb24oZSwgbykgew0KCQkJCQkJdmFyIHQsIGEgPSBiLnBzZXVkb3NbZV0gfHwgYi5zZXRGaWx0ZXJzW2UudG9Mb3dlckNhc2UoKV0gfHwgc2UuZXJyb3IoInVuc3VwcG9ydGVkIHBzZXVkbzogIiArIGUpOw0KCQkJCQkJcmV0dXJuIGFbRV0gPyBhKG8pIDogMSA8IGEubGVuZ3RoID8gKHQgPSBbZSwgZSwgIiIsIG9dLCBiLnNldEZpbHRlcnMuaGFzT3duUHJvcGVydHkoZS50b0xvd2VyQ2FzZSgpKSA/IGxlKGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQkJCQl2YXIgbiwgciA9IGEoZSwgbyksIGkgPSByLmxlbmd0aDsNCgkJCQkJCQl3aGlsZShpLS0pIGVbbiA9IFAoZSwgcltpXSldID0gISh0W25dID0gcltpXSkNCgkJCQkJCX0pIDogZnVuY3Rpb24oZSkge3JldHVybiBhKGUsIDAsIHQpfSkgOiBhDQoJCQkJCX0NCgkJCQl9LA0KCQkJCXBzZXVkb3M6IHsNCgkJCQkJbm90OiBsZShmdW5jdGlvbihlKSB7DQoJCQkJCQl2YXIgciA9IFtdLCBpID0gW10sIHMgPSBmKGUucmVwbGFjZShCLCAiJDEiKSk7DQoJCQkJCQlyZXR1cm4gc1tFXSA/IGxlKGZ1bmN0aW9uKGUsIHQsIG4sIHIpIHsNCgkJCQkJCQl2YXIgaSwgbyA9IHMoZSwgbnVsbCwgciwgW10pLCBhID0gZS5sZW5ndGg7DQoJCQkJCQkJd2hpbGUoYS0tKSAoaSA9IG9bYV0pICYmIChlW2FdID0gISh0W2FdID0gaSkpDQoJCQkJCQl9KSA6IGZ1bmN0aW9uKGUsIHQsIG4pIHtyZXR1cm4gclswXSA9IGUsIHMociwgbnVsbCwgbiwgaSksIHJbMF0gPSBudWxsLCAhaS5wb3AoKX0NCgkJCQkJfSksDQoJCQkJCWhhczogbGUoZnVuY3Rpb24odCkge3JldHVybiBmdW5jdGlvbihlKSB7cmV0dXJuIDAgPCBzZSh0LCBlKS5sZW5ndGh9fSksDQoJCQkJCWNvbnRhaW5zOiBsZShmdW5jdGlvbih0KSB7cmV0dXJuIHQgPSB0LnJlcGxhY2UodGUsIG5lKSwgZnVuY3Rpb24oZSkge3JldHVybiAtMSA8IChlLnRleHRDb250ZW50IHx8IG8oZSkpLmluZGV4T2YodCl9fSksDQoJCQkJCWxhbmc6IGxlKGZ1bmN0aW9uKG4pIHsNCgkJCQkJCXJldHVybiBWLnRlc3QobiB8fCAiIikgfHwgc2UuZXJyb3IoInVuc3VwcG9ydGVkIGxhbmc6ICIgKyBuKSwgbiA9IG4ucmVwbGFjZSh0ZSwgbmUpLnRvTG93ZXJDYXNlKCksIGZ1bmN0aW9uKGUpIHsNCgkJCQkJCQl2YXIgdDsNCgkJCQkJCQlkbyB7aWYodCA9IFMgPyBlLmxhbmcgOiBlLmdldEF0dHJpYnV0ZSgieG1sOmxhbmciKSB8fCBlLmdldEF0dHJpYnV0ZSgibGFuZyIpKSByZXR1cm4gKHQgPSB0LnRvTG93ZXJDYXNlKCkpID09PSBuIHx8IDAgPT09IHQuaW5kZXhPZihuICsgIi0iKX0gd2hpbGUoKGUgPSBlLnBhcmVudE5vZGUpICYmIDEgPT09IGUubm9kZVR5cGUpOw0KCQkJCQkJCXJldHVybiAhMQ0KCQkJCQkJfQ0KCQkJCQl9KSwNCgkJCQkJdGFyZ2V0OiBmdW5jdGlvbihlKSB7DQoJCQkJCQl2YXIgdCA9IG4ubG9jYXRpb24gJiYgbi5sb2NhdGlvbi5oYXNoOw0KCQkJCQkJcmV0dXJuIHQgJiYgdC5zbGljZSgxKSA9PT0gZS5pZA0KCQkJCQl9LA0KCQkJCQlyb290OiBmdW5jdGlvbihlKSB7cmV0dXJuIGUgPT09IGF9LA0KCQkJCQlmb2N1czogZnVuY3Rpb24oZSkge3JldHVybiBlID09PSBDLmFjdGl2ZUVsZW1lbnQgJiYgKCFDLmhhc0ZvY3VzIHx8IEMuaGFzRm9jdXMoKSkgJiYgISEoZS50eXBlIHx8IGUuaHJlZiB8fCB+ZS50YWJJbmRleCl9LA0KCQkJCQllbmFibGVkOiBnZSghMSksDQoJCQkJCWRpc2FibGVkOiBnZSghMCksDQoJCQkJCWNoZWNrZWQ6IGZ1bmN0aW9uKGUpIHsNCgkJCQkJCXZhciB0ID0gZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpOw0KCQkJCQkJcmV0dXJuICJpbnB1dCIgPT09IHQgJiYgISFlLmNoZWNrZWQgfHwgIm9wdGlvbiIgPT09IHQgJiYgISFlLnNlbGVjdGVkDQoJCQkJCX0sDQoJCQkJCXNlbGVjdGVkOiBmdW5jdGlvbihlKSB7cmV0dXJuIGUucGFyZW50Tm9kZSAmJiBlLnBhcmVudE5vZGUuc2VsZWN0ZWRJbmRleCwgITAgPT09IGUuc2VsZWN0ZWR9LA0KCQkJCQllbXB0eTogZnVuY3Rpb24oZSkgew0KCQkJCQkJZm9yKGUgPSBlLmZpcnN0Q2hpbGQ7IGU7IGUgPSBlLm5leHRTaWJsaW5nKSBpZihlLm5vZGVUeXBlIDwgNikgcmV0dXJuICExOw0KCQkJCQkJcmV0dXJuICEwDQoJCQkJCX0sDQoJCQkJCXBhcmVudDogZnVuY3Rpb24oZSkge3JldHVybiAhYi5wc2V1ZG9zLmVtcHR5KGUpfSwNCgkJCQkJaGVhZGVyOiBmdW5jdGlvbihlKSB7cmV0dXJuIEoudGVzdChlLm5vZGVOYW1lKX0sDQoJCQkJCWlucHV0OiBmdW5jdGlvbihlKSB7cmV0dXJuIFEudGVzdChlLm5vZGVOYW1lKX0sDQoJCQkJCWJ1dHRvbjogZnVuY3Rpb24oZSkgew0KCQkJCQkJdmFyIHQgPSBlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7DQoJCQkJCQlyZXR1cm4gImlucHV0IiA9PT0gdCAmJiAiYnV0dG9uIiA9PT0gZS50eXBlIHx8ICJidXR0b24iID09PSB0DQoJCQkJCX0sDQoJCQkJCXRleHQ6IGZ1bmN0aW9uKGUpIHsNCgkJCQkJCXZhciB0Ow0KCQkJCQkJcmV0dXJuICJpbnB1dCIgPT09IGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKSAmJiAidGV4dCIgPT09IGUudHlwZSAmJiAobnVsbCA9PSAodCA9IGUuZ2V0QXR0cmlidXRlKCJ0eXBlIikpIHx8ICJ0ZXh0IiA9PT0gdC50b0xvd2VyQ2FzZSgpKQ0KCQkJCQl9LA0KCQkJCQlmaXJzdDogeWUoZnVuY3Rpb24oKSB7cmV0dXJuIFswXX0pLA0KCQkJCQlsYXN0OiB5ZShmdW5jdGlvbihlLCB0KSB7cmV0dXJuIFt0IC0gMV19KSwNCgkJCQkJZXE6IHllKGZ1bmN0aW9uKGUsIHQsIG4pIHtyZXR1cm4gW24gPCAwID8gbiArIHQgOiBuXX0pLA0KCQkJCQlldmVuOiB5ZShmdW5jdGlvbihlLCB0KSB7DQoJCQkJCQlmb3IodmFyIG4gPSAwOyBuIDwgdDsgbiArPSAyKSBlLnB1c2gobik7DQoJCQkJCQlyZXR1cm4gZQ0KCQkJCQl9KSwNCgkJCQkJb2RkOiB5ZShmdW5jdGlvbihlLCB0KSB7DQoJCQkJCQlmb3IodmFyIG4gPSAxOyBuIDwgdDsgbiArPSAyKSBlLnB1c2gobik7DQoJCQkJCQlyZXR1cm4gZQ0KCQkJCQl9KSwNCgkJCQkJbHQ6IHllKGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQkJCWZvcih2YXIgciA9IG4gPCAwID8gbiArIHQgOiB0IDwgbiA/IHQgOiBuOyAwIDw9IC0tcjspIGUucHVzaChyKTsNCgkJCQkJCXJldHVybiBlDQoJCQkJCX0pLA0KCQkJCQlndDogeWUoZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJCQkJZm9yKHZhciByID0gbiA8IDAgPyBuICsgdCA6IG47ICsrciA8IHQ7KSBlLnB1c2gocik7DQoJCQkJCQlyZXR1cm4gZQ0KCQkJCQl9KQ0KCQkJCX0NCgkJCX0pLnBzZXVkb3MubnRoID0gYi5wc2V1ZG9zLmVxLCB7cmFkaW86ICEwLCBjaGVja2JveDogITAsIGZpbGU6ICEwLCBwYXNzd29yZDogITAsIGltYWdlOiAhMH0pIGIucHNldWRvc1tlXSA9IGRlKGUpOw0KCQkJZm9yKGUgaW4ge3N1Ym1pdDogITAsIHJlc2V0OiAhMH0pIGIucHNldWRvc1tlXSA9IGhlKGUpOw0KDQoJCQlmdW5jdGlvbiBtZSgpIHt9DQoNCgkJCWZ1bmN0aW9uIHhlKGUpIHsNCgkJCQlmb3IodmFyIHQgPSAwLCBuID0gZS5sZW5ndGgsIHIgPSAiIjsgdCA8IG47IHQrKykgciArPSBlW3RdLnZhbHVlOw0KCQkJCXJldHVybiByDQoJCQl9DQoNCgkJCWZ1bmN0aW9uIGJlKHMsIGUsIHQpIHsNCgkJCQl2YXIgdSA9IGUuZGlyLCBsID0gZS5uZXh0LCBjID0gbCB8fCB1LCBmID0gdCAmJiAicGFyZW50Tm9kZSIgPT09IGMsIHAgPSByKys7DQoJCQkJcmV0dXJuIGUuZmlyc3QgPyBmdW5jdGlvbihlLCB0LCBuKSB7DQoJCQkJCXdoaWxlKGUgPSBlW3VdKSBpZigxID09PSBlLm5vZGVUeXBlIHx8IGYpIHJldHVybiBzKGUsIHQsIG4pOw0KCQkJCQlyZXR1cm4gITENCgkJCQl9IDogZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJCQl2YXIgciwgaSwgbywgYSA9IFtrLCBwXTsNCgkJCQkJaWYobikge3doaWxlKGUgPSBlW3VdKSBpZigoMSA9PT0gZS5ub2RlVHlwZSB8fCBmKSAmJiBzKGUsIHQsIG4pKSByZXR1cm4gITB9IGVsc2Ugd2hpbGUoZSA9IGVbdV0pIGlmKDEgPT09IGUubm9kZVR5cGUgfHwgZikgaWYoaSA9IChvID0gZVtFXSB8fCAoZVtFXSA9IHt9KSlbZS51bmlxdWVJRF0gfHwgKG9bZS51bmlxdWVJRF0gPSB7fSksIGwgJiYgbCA9PT0gZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpKSBlID0gZVt1XSB8fCBlOyBlbHNlIHsNCgkJCQkJCWlmKChyID0gaVtjXSkgJiYgclswXSA9PT0gayAmJiByWzFdID09PSBwKSByZXR1cm4gYVsyXSA9IHJbMl07DQoJCQkJCQlpZigoaVtjXSA9IGEpWzJdID0gcyhlLCB0LCBuKSkgcmV0dXJuICEwDQoJCQkJCX0NCgkJCQkJcmV0dXJuICExDQoJCQkJfQ0KCQkJfQ0KDQoJCQlmdW5jdGlvbiB3ZShpKSB7DQoJCQkJcmV0dXJuIDEgPCBpLmxlbmd0aCA/IGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQkJdmFyIHIgPSBpLmxlbmd0aDsNCgkJCQkJd2hpbGUoci0tKSBpZighaVtyXShlLCB0LCBuKSkgcmV0dXJuICExOw0KCQkJCQlyZXR1cm4gITANCgkJCQl9IDogaVswXQ0KCQkJfQ0KDQoJCQlmdW5jdGlvbiBUZShlLCB0LCBuLCByLCBpKSB7DQoJCQkJZm9yKHZhciBvLCBhID0gW10sIHMgPSAwLCB1ID0gZS5sZW5ndGgsIGwgPSBudWxsICE9IHQ7IHMgPCB1OyBzKyspIChvID0gZVtzXSkgJiYgKG4gJiYgIW4obywgciwgaSkgfHwgKGEucHVzaChvKSwgbCAmJiB0LnB1c2gocykpKTsNCgkJCQlyZXR1cm4gYQ0KCQkJfQ0KDQoJCQlmdW5jdGlvbiBDZShkLCBoLCBnLCB5LCB2LCBlKSB7DQoJCQkJcmV0dXJuIHkgJiYgIXlbRV0gJiYgKHkgPSBDZSh5KSksIHYgJiYgIXZbRV0gJiYgKHYgPSBDZSh2LCBlKSksIGxlKGZ1bmN0aW9uKGUsIHQsIG4sIHIpIHsNCgkJCQkJdmFyIGksIG8sIGEsIHMgICAgICAgICAgICAgICAgICAgICAgICAgICA9IFtdLCB1ID0gW10sIGwgPSB0Lmxlbmd0aCwgYyA9IGUgfHwgZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJCQkJZm9yKHZhciByID0gMCwgaSA9IHQubGVuZ3RoOyByIDwgaTsgcisrKSBzZShlLCB0W3JdLCBuKTsNCgkJCQkJCXJldHVybiBuDQoJCQkJCX0oaCB8fCAiKiIsIG4ubm9kZVR5cGUgPyBbbl0gOiBuLCBbXSksIGYgPSAhZCB8fCAhZSAmJiBoID8gYyA6IFRlKGMsIHMsIGQsIG4sIHIpLCBwID0gZyA/IHYgfHwgKGUgPyBkIDogbCB8fCB5KSA/IFtdIDogdCA6IGY7DQoJCQkJCWlmKGcgJiYgZyhmLCBwLCBuLCByKSwgeSkgew0KCQkJCQkJaSA9IFRlKHAsIHUpLCB5KGksIFtdLCBuLCByKSwgbyA9IGkubGVuZ3RoOw0KCQkJCQkJd2hpbGUoby0tKSAoYSA9IGlbb10pICYmIChwW3Vbb11dID0gIShmW3Vbb11dID0gYSkpDQoJCQkJCX0NCgkJCQkJaWYoZSkgew0KCQkJCQkJaWYodiB8fCBkKSB7DQoJCQkJCQkJaWYodikgew0KCQkJCQkJCQlpID0gW10sIG8gPSBwLmxlbmd0aDsNCgkJCQkJCQkJd2hpbGUoby0tKSAoYSA9IHBbb10pICYmIGkucHVzaChmW29dID0gYSk7DQoJCQkJCQkJCXYobnVsbCwgcCA9IFtdLCBpLCByKQ0KCQkJCQkJCX0NCgkJCQkJCQlvID0gcC5sZW5ndGg7DQoJCQkJCQkJd2hpbGUoby0tKSAoYSA9IHBbb10pICYmIC0xIDwgKGkgPSB2ID8gUChlLCBhKSA6IHNbb10pICYmIChlW2ldID0gISh0W2ldID0gYSkpDQoJCQkJCQl9DQoJCQkJCX0gZWxzZSBwID0gVGUocCA9PT0gdCA/IHAuc3BsaWNlKGwsIHAubGVuZ3RoKSA6IHApLCB2ID8gdihudWxsLCB0LCBwLCByKSA6IEguYXBwbHkodCwgcCkNCgkJCQl9KQ0KCQkJfQ0KDQoJCQlmdW5jdGlvbiBTZShlKSB7DQoJCQkJZm9yKHZhciBpLCB0LCBuLCByID0gZS5sZW5ndGgsIG8gPSBiLnJlbGF0aXZlW2VbMF0udHlwZV0sIGEgPSBvIHx8IGIucmVsYXRpdmVbIiAiXSwgcyA9IG8gPyAxIDogMCwgdSA9IGJlKGZ1bmN0aW9uKGUpIHtyZXR1cm4gZSA9PT0gaX0sIGEsICEwKSwgbCA9IGJlKGZ1bmN0aW9uKGUpIHtyZXR1cm4gLTEgPCBQKGksIGUpfSwgYSwgITApLCBjID0gW2Z1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQkJdmFyIHIgPSAhbyAmJiAobiB8fCB0ICE9PSB3KSB8fCAoKGkgPSB0KS5ub2RlVHlwZSA/IHUoZSwgdCwgbikgOiBsKGUsIHQsIG4pKTsNCgkJCQkJcmV0dXJuIGkgPSBudWxsLCByDQoJCQkJfV07IHMgPCByOyBzKyspIGlmKHQgPSBiLnJlbGF0aXZlW2Vbc10udHlwZV0pIGMgPSBbYmUod2UoYyksIHQpXTsgZWxzZSB7DQoJCQkJCWlmKCh0ID0gYi5maWx0ZXJbZVtzXS50eXBlXS5hcHBseShudWxsLCBlW3NdLm1hdGNoZXMpKVtFXSkgew0KCQkJCQkJZm9yKG4gPSArK3M7IG4gPCByOyBuKyspIGlmKGIucmVsYXRpdmVbZVtuXS50eXBlXSkgYnJlYWs7DQoJCQkJCQlyZXR1cm4gQ2UoMSA8IHMgJiYgd2UoYyksIDEgPCBzICYmIHhlKGUuc2xpY2UoMCwgcyAtIDEpLmNvbmNhdCh7dmFsdWU6ICIgIiA9PT0gZVtzIC0gMl0udHlwZSA/ICIqIiA6ICIifSkpLnJlcGxhY2UoQiwgIiQxIiksIHQsIHMgPCBuICYmIFNlKGUuc2xpY2UocywgbikpLCBuIDwgciAmJiBTZShlID0gZS5zbGljZShuKSksIG4gPCByICYmIHhlKGUpKQ0KCQkJCQl9DQoJCQkJCWMucHVzaCh0KQ0KCQkJCX0NCgkJCQlyZXR1cm4gd2UoYykNCgkJCX0NCg0KCQkJcmV0dXJuIG1lLnByb3RvdHlwZSA9IGIuZmlsdGVycyA9IGIucHNldWRvcywgYi5zZXRGaWx0ZXJzID0gbmV3IG1lLCBoID0gc2UudG9rZW5pemUgPSBmdW5jdGlvbihlLCB0KSB7DQoJCQkJdmFyIG4sIHIsIGksIG8sIGEsIHMsIHUsIGwgPSB4W2UgKyAiICJdOw0KCQkJCWlmKGwpIHJldHVybiB0ID8gMCA6IGwuc2xpY2UoMCk7DQoJCQkJYSA9IGUsIHMgPSBbXSwgdSA9IGIucHJlRmlsdGVyOw0KCQkJCXdoaWxlKGEpIHsNCgkJCQkJZm9yKG8gaW4gbiAmJiAhKHIgPSBfLmV4ZWMoYSkpIHx8IChyICYmIChhID0gYS5zbGljZShyWzBdLmxlbmd0aCkgfHwgYSksIHMucHVzaChpID0gW10pKSwgbiA9ICExLCAociA9IHouZXhlYyhhKSkgJiYgKG4gPSByLnNoaWZ0KCksIGkucHVzaCh7DQoJCQkJCQl2YWx1ZTogbiwNCgkJCQkJCXR5cGU6IHJbMF0ucmVwbGFjZShCLCAiICIpDQoJCQkJCX0pLCBhID0gYS5zbGljZShuLmxlbmd0aCkpLCBiLmZpbHRlcikgIShyID0gR1tvXS5leGVjKGEpKSB8fCB1W29dICYmICEociA9IHVbb10ocikpIHx8IChuID0gci5zaGlmdCgpLCBpLnB1c2goe3ZhbHVlOiBuLCB0eXBlOiBvLCBtYXRjaGVzOiByfSksIGEgPSBhLnNsaWNlKG4ubGVuZ3RoKSk7DQoJCQkJCWlmKCFuKSBicmVhaw0KCQkJCX0NCgkJCQlyZXR1cm4gdCA/IGEubGVuZ3RoIDogYSA/IHNlLmVycm9yKGUpIDogeChlLCBzKS5zbGljZSgwKQ0KCQkJfSwgZiA9IHNlLmNvbXBpbGUgPSBmdW5jdGlvbihlLCB0KSB7DQoJCQkJdmFyIG4sIHksIHYsIG0sIHgsIHIsIGkgPSBbXSwgbyA9IFtdLCBhID0gQVtlICsgIiAiXTsNCgkJCQlpZighYSkgew0KCQkJCQl0IHx8ICh0ID0gaChlKSksIG4gPSB0Lmxlbmd0aDsNCgkJCQkJd2hpbGUobi0tKSAoYSA9IFNlKHRbbl0pKVtFXSA/IGkucHVzaChhKSA6IG8ucHVzaChhKTsNCgkJCQkJKGEgPSBBKGUsICh5ID0gbywgbSA9IDAgPCAodiA9IGkpLmxlbmd0aCwgeCA9IDAgPCB5Lmxlbmd0aCwgciA9IGZ1bmN0aW9uKGUsIHQsIG4sIHIsIGkpIHsNCgkJCQkJCXZhciBvLCBhLCBzLCB1ID0gMCwgbCA9ICIwIiwgYyA9IGUgJiYgW10sIGYgPSBbXSwgcCA9IHcsIGQgPSBlIHx8IHggJiYgYi5maW5kLlRBRygiKiIsIGkpLCBoID0gayArPSBudWxsID09IHAgPyAxIDogTWF0aC5yYW5kb20oKSB8fCAuMSwgZyA9IGQubGVuZ3RoOw0KCQkJCQkJZm9yKGkgJiYgKHcgPSB0ID09IEMgfHwgdCB8fCBpKTsgbCAhPT0gZyAmJiBudWxsICE9IChvID0gZFtsXSk7IGwrKykgew0KCQkJCQkJCWlmKHggJiYgbykgew0KCQkJCQkJCQlhID0gMCwgdCB8fCBvLm93bmVyRG9jdW1lbnQgPT0gQyB8fCAoVChvKSwgbiA9ICFTKTsNCgkJCQkJCQkJd2hpbGUocyA9IHlbYSsrXSkgaWYocyhvLCB0IHx8IEMsIG4pKSB7DQoJCQkJCQkJCQlyLnB1c2gobyk7DQoJCQkJCQkJCQlicmVhaw0KCQkJCQkJCQl9DQoJCQkJCQkJCWkgJiYgKGsgPSBoKQ0KCQkJCQkJCX0NCgkJCQkJCQltICYmICgobyA9ICFzICYmIG8pICYmIHUtLSwgZSAmJiBjLnB1c2gobykpDQoJCQkJCQl9DQoJCQkJCQlpZih1ICs9IGwsIG0gJiYgbCAhPT0gdSkgew0KCQkJCQkJCWEgPSAwOw0KCQkJCQkJCXdoaWxlKHMgPSB2W2ErK10pIHMoYywgZiwgdCwgbik7DQoJCQkJCQkJaWYoZSkgew0KCQkJCQkJCQlpZigwIDwgdSkgd2hpbGUobC0tKSBjW2xdIHx8IGZbbF0gfHwgKGZbbF0gPSBxLmNhbGwocikpOw0KCQkJCQkJCQlmID0gVGUoZikNCgkJCQkJCQl9DQoJCQkJCQkJSC5hcHBseShyLCBmKSwgaSAmJiAhZSAmJiAwIDwgZi5sZW5ndGggJiYgMSA8IHUgKyB2Lmxlbmd0aCAmJiBzZS51bmlxdWVTb3J0KHIpDQoJCQkJCQl9DQoJCQkJCQlyZXR1cm4gaSAmJiAoayA9IGgsIHcgPSBwKSwgYw0KCQkJCQl9LCBtID8gbGUocikgOiByKSkpLnNlbGVjdG9yID0gZQ0KCQkJCX0NCgkJCQlyZXR1cm4gYQ0KCQkJfSwgZyA9IHNlLnNlbGVjdCA9IGZ1bmN0aW9uKGUsIHQsIG4sIHIpIHsNCgkJCQl2YXIgaSwgbywgYSwgcywgdSwgbCA9ICJmdW5jdGlvbiIgPT0gdHlwZW9mIGUgJiYgZSwgYyA9ICFyICYmIGgoZSA9IGwuc2VsZWN0b3IgfHwgZSk7DQoJCQkJaWYobiA9IG4gfHwgW10sIDEgPT09IGMubGVuZ3RoKSB7DQoJCQkJCWlmKDIgPCAobyA9IGNbMF0gPSBjWzBdLnNsaWNlKDApKS5sZW5ndGggJiYgIklEIiA9PT0gKGEgPSBvWzBdKS50eXBlICYmIDkgPT09IHQubm9kZVR5cGUgJiYgUyAmJiBiLnJlbGF0aXZlW29bMV0udHlwZV0pIHsNCgkJCQkJCWlmKCEodCA9IChiLmZpbmQuSUQoYS5tYXRjaGVzWzBdLnJlcGxhY2UodGUsIG5lKSwgdCkgfHwgW10pWzBdKSkgcmV0dXJuIG47DQoJCQkJCQlsICYmICh0ID0gdC5wYXJlbnROb2RlKSwgZSA9IGUuc2xpY2Uoby5zaGlmdCgpLnZhbHVlLmxlbmd0aCkNCgkJCQkJfQ0KCQkJCQlpID0gRy5uZWVkc0NvbnRleHQudGVzdChlKSA/IDAgOiBvLmxlbmd0aDsNCgkJCQkJd2hpbGUoaS0tKSB7DQoJCQkJCQlpZihhID0gb1tpXSwgYi5yZWxhdGl2ZVtzID0gYS50eXBlXSkgYnJlYWs7DQoJCQkJCQlpZigodSA9IGIuZmluZFtzXSkgJiYgKHIgPSB1KGEubWF0Y2hlc1swXS5yZXBsYWNlKHRlLCBuZSksIGVlLnRlc3Qob1swXS50eXBlKSAmJiB2ZSh0LnBhcmVudE5vZGUpIHx8IHQpKSkgew0KCQkJCQkJCWlmKG8uc3BsaWNlKGksIDEpLCAhKGUgPSByLmxlbmd0aCAmJiB4ZShvKSkpIHJldHVybiBILmFwcGx5KG4sIHIpLCBuOw0KCQkJCQkJCWJyZWFrDQoJCQkJCQl9DQoJCQkJCX0NCgkJCQl9DQoJCQkJcmV0dXJuIChsIHx8IGYoZSwgYykpKHIsIHQsICFTLCBuLCAhdCB8fCBlZS50ZXN0KGUpICYmIHZlKHQucGFyZW50Tm9kZSkgfHwgdCksIG4NCgkJCX0sIGQuc29ydFN0YWJsZSA9IEUuc3BsaXQoIiIpLnNvcnQoaikuam9pbigiIikgPT09IEUsIGQuZGV0ZWN0RHVwbGljYXRlcyA9ICEhbCwgVCgpLCBkLnNvcnREZXRhY2hlZCA9IGNlKGZ1bmN0aW9uKGUpIHtyZXR1cm4gMSAmIGUuY29tcGFyZURvY3VtZW50UG9zaXRpb24oQy5jcmVhdGVFbGVtZW50KCJmaWVsZHNldCIpKX0pLCBjZShmdW5jdGlvbihlKSB7cmV0dXJuIGUuaW5uZXJIVE1MID0gIjxhIGhyZWY9JyMnPjwvYT4iLCAiIyIgPT09IGUuZmlyc3RDaGlsZC5nZXRBdHRyaWJ1dGUoImhyZWYiKX0pIHx8IGZlKCJ0eXBlfGhyZWZ8aGVpZ2h0fHdpZHRoIiwgZnVuY3Rpb24oZSwgdCwgbikge2lmKCFuKSByZXR1cm4gZS5nZXRBdHRyaWJ1dGUodCwgInR5cGUiID09PSB0LnRvTG93ZXJDYXNlKCkgPyAxIDogMil9KSwgZC5hdHRyaWJ1dGVzICYmIGNlKGZ1bmN0aW9uKGUpIHtyZXR1cm4gZS5pbm5lckhUTUwgPSAiPGlucHV0Lz4iLCBlLmZpcnN0Q2hpbGQuc2V0QXR0cmlidXRlKCJ2YWx1ZSIsICIiKSwgIiIgPT09IGUuZmlyc3RDaGlsZC5nZXRBdHRyaWJ1dGUoInZhbHVlIil9KSB8fCBmZSgidmFsdWUiLCBmdW5jdGlvbihlLCB0LCBuKSB7aWYoIW4gJiYgImlucHV0IiA9PT0gZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpKSByZXR1cm4gZS5kZWZhdWx0VmFsdWV9KSwgY2UoZnVuY3Rpb24oZSkge3JldHVybiBudWxsID09IGUuZ2V0QXR0cmlidXRlKCJkaXNhYmxlZCIpfSkgfHwgZmUoUiwgZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJCXZhciByOw0KCQkJCWlmKCFuKSByZXR1cm4gITAgPT09IGVbdF0gPyB0LnRvTG93ZXJDYXNlKCkgOiAociA9IGUuZ2V0QXR0cmlidXRlTm9kZSh0KSkgJiYgci5zcGVjaWZpZWQgPyByLnZhbHVlIDogbnVsbA0KCQkJfSksIHNlDQoJCX0oQyk7DQoJCUUuZmluZCA9IGQsIEUuZXhwciA9IGQuc2VsZWN0b3JzLCBFLmV4cHJbIjoiXSA9IEUuZXhwci5wc2V1ZG9zLCBFLnVuaXF1ZVNvcnQgPSBFLnVuaXF1ZSA9IGQudW5pcXVlU29ydCwgRS50ZXh0ID0gZC5nZXRUZXh0LCBFLmlzWE1MRG9jID0gZC5pc1hNTCwgRS5jb250YWlucyA9IGQuY29udGFpbnMsIEUuZXNjYXBlU2VsZWN0b3IgPSBkLmVzY2FwZTsNCgkJdmFyIGggPSBmdW5jdGlvbihlLCB0LCBuKSB7DQoJCQl2YXIgciA9IFtdLCBpID0gdm9pZCAwICE9PSBuOw0KCQkJd2hpbGUoKGUgPSBlW3RdKSAmJiA5ICE9PSBlLm5vZGVUeXBlKSBpZigxID09PSBlLm5vZGVUeXBlKSB7DQoJCQkJaWYoaSAmJiBFKGUpLmlzKG4pKSBicmVhazsNCgkJCQlyLnB1c2goZSkNCgkJCX0NCgkJCXJldHVybiByDQoJCX0sIFQgID0gZnVuY3Rpb24oZSwgdCkgew0KCQkJZm9yKHZhciBuID0gW107IGU7IGUgPSBlLm5leHRTaWJsaW5nKSAxID09PSBlLm5vZGVUeXBlICYmIGUgIT09IHQgJiYgbi5wdXNoKGUpOw0KCQkJcmV0dXJuIG4NCgkJfSwgayAgPSBFLmV4cHIubWF0Y2gubmVlZHNDb250ZXh0Ow0KDQoJCWZ1bmN0aW9uIEEoZSwgdCkge3JldHVybiBlLm5vZGVOYW1lICYmIGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gdC50b0xvd2VyQ2FzZSgpfQ0KDQoJCXZhciBOID0gL148KFthLXpdW15cL1wwPjpceDIwXHRcclxuXGZdKilbXHgyMFx0XHJcblxmXSpcLz8+KD86PFwvXDE+fCkkL2k7DQoNCgkJZnVuY3Rpb24gaihlLCBuLCByKSB7cmV0dXJuIG0obikgPyBFLmdyZXAoZSwgZnVuY3Rpb24oZSwgdCkge3JldHVybiAhIW4uY2FsbChlLCB0LCBlKSAhPT0gcn0pIDogbi5ub2RlVHlwZSA/IEUuZ3JlcChlLCBmdW5jdGlvbihlKSB7cmV0dXJuIGUgPT09IG4gIT09IHJ9KSA6ICJzdHJpbmciICE9IHR5cGVvZiBuID8gRS5ncmVwKGUsIGZ1bmN0aW9uKGUpIHtyZXR1cm4gLTEgPCBpLmNhbGwobiwgZSkgIT09IHJ9KSA6IEUuZmlsdGVyKG4sIGUsIHIpfQ0KDQoJCUUuZmlsdGVyID0gZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJdmFyIHIgPSB0WzBdOw0KCQkJcmV0dXJuIG4gJiYgKGUgPSAiOm5vdCgiICsgZSArICIpIiksIDEgPT09IHQubGVuZ3RoICYmIDEgPT09IHIubm9kZVR5cGUgPyBFLmZpbmQubWF0Y2hlc1NlbGVjdG9yKHIsIGUpID8gW3JdIDogW10gOiBFLmZpbmQubWF0Y2hlcyhlLCBFLmdyZXAodCwgZnVuY3Rpb24oZSkge3JldHVybiAxID09PSBlLm5vZGVUeXBlfSkpDQoJCX0sIEUuZm4uZXh0ZW5kKHsNCgkJCWZpbmQ6IGZ1bmN0aW9uKGUpIHsNCgkJCQl2YXIgdCwgbiwgciA9IHRoaXMubGVuZ3RoLCBpID0gdGhpczsNCgkJCQlpZigic3RyaW5nIiAhPSB0eXBlb2YgZSkgcmV0dXJuIHRoaXMucHVzaFN0YWNrKEUoZSkuZmlsdGVyKGZ1bmN0aW9uKCkge2Zvcih0ID0gMDsgdCA8IHI7IHQrKykgaWYoRS5jb250YWlucyhpW3RdLCB0aGlzKSkgcmV0dXJuICEwfSkpOw0KCQkJCWZvcihuID0gdGhpcy5wdXNoU3RhY2soW10pLCB0ID0gMDsgdCA8IHI7IHQrKykgRS5maW5kKGUsIGlbdF0sIG4pOw0KCQkJCXJldHVybiAxIDwgciA/IEUudW5pcXVlU29ydChuKSA6IG4NCgkJCX0sIGZpbHRlcjogZnVuY3Rpb24oZSkge3JldHVybiB0aGlzLnB1c2hTdGFjayhqKHRoaXMsIGUgfHwgW10sICExKSl9LCBub3Q6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gdGhpcy5wdXNoU3RhY2soaih0aGlzLCBlIHx8IFtdLCAhMCkpfSwgaXM6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gISFqKHRoaXMsICJzdHJpbmciID09IHR5cGVvZiBlICYmIGsudGVzdChlKSA/IEUoZSkgOiBlIHx8IFtdLCAhMSkubGVuZ3RofQ0KCQl9KTsNCgkJdmFyIEQsIHEgPSAvXig/OlxzKig8W1x3XFddKz4pW14+XSp8IyhbXHctXSspKSQvOw0KCQkoRS5mbi5pbml0ID0gZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJdmFyIHIsIGk7DQoJCQlpZighZSkgcmV0dXJuIHRoaXM7DQoJCQlpZihuID0gbiB8fCBELCAic3RyaW5nIiA9PSB0eXBlb2YgZSkgew0KCQkJCWlmKCEociA9ICI8IiA9PT0gZVswXSAmJiAiPiIgPT09IGVbZS5sZW5ndGggLSAxXSAmJiAzIDw9IGUubGVuZ3RoID8gW251bGwsIGUsIG51bGxdIDogcS5leGVjKGUpKSB8fCAhclsxXSAmJiB0KSByZXR1cm4gIXQgfHwgdC5qcXVlcnkgPyAodCB8fCBuKS5maW5kKGUpIDogdGhpcy5jb25zdHJ1Y3Rvcih0KS5maW5kKGUpOw0KCQkJCWlmKHJbMV0pIHsNCgkJCQkJaWYodCA9IHQgaW5zdGFuY2VvZiBFID8gdFswXSA6IHQsIEUubWVyZ2UodGhpcywgRS5wYXJzZUhUTUwoclsxXSwgdCAmJiB0Lm5vZGVUeXBlID8gdC5vd25lckRvY3VtZW50IHx8IHQgOiBTLCAhMCkpLCBOLnRlc3QoclsxXSkgJiYgRS5pc1BsYWluT2JqZWN0KHQpKSBmb3IociBpbiB0KSBtKHRoaXNbcl0pID8gdGhpc1tyXSh0W3JdKSA6IHRoaXMuYXR0cihyLCB0W3JdKTsNCgkJCQkJcmV0dXJuIHRoaXMNCgkJCQl9DQoJCQkJcmV0dXJuIChpID0gUy5nZXRFbGVtZW50QnlJZChyWzJdKSkgJiYgKHRoaXNbMF0gPSBpLCB0aGlzLmxlbmd0aCA9IDEpLCB0aGlzDQoJCQl9DQoJCQlyZXR1cm4gZS5ub2RlVHlwZSA/ICh0aGlzWzBdID0gZSwgdGhpcy5sZW5ndGggPSAxLCB0aGlzKSA6IG0oZSkgPyB2b2lkIDAgIT09IG4ucmVhZHkgPyBuLnJlYWR5KGUpIDogZShFKSA6IEUubWFrZUFycmF5KGUsIHRoaXMpDQoJCX0pLnByb3RvdHlwZSA9IEUuZm4sIEQgPSBFKFMpOw0KCQl2YXIgTCA9IC9eKD86cGFyZW50c3xwcmV2KD86VW50aWx8QWxsKSkvLCBIID0ge2NoaWxkcmVuOiAhMCwgY29udGVudHM6ICEwLCBuZXh0OiAhMCwgcHJldjogITB9Ow0KDQoJCWZ1bmN0aW9uIE8oZSwgdCkgew0KCQkJd2hpbGUoKGUgPSBlW3RdKSAmJiAxICE9PSBlLm5vZGVUeXBlKSA7DQoJCQlyZXR1cm4gZQ0KCQl9DQoNCgkJRS5mbi5leHRlbmQoew0KCQkJaGFzOiBmdW5jdGlvbihlKSB7DQoJCQkJdmFyIHQgPSBFKGUsIHRoaXMpLCBuID0gdC5sZW5ndGg7DQoJCQkJcmV0dXJuIHRoaXMuZmlsdGVyKGZ1bmN0aW9uKCkge2Zvcih2YXIgZSA9IDA7IGUgPCBuOyBlKyspIGlmKEUuY29udGFpbnModGhpcywgdFtlXSkpIHJldHVybiAhMH0pDQoJCQl9LA0KCQkJY2xvc2VzdDogZnVuY3Rpb24oZSwgdCkgew0KCQkJCXZhciBuLCByID0gMCwgaSA9IHRoaXMubGVuZ3RoLCBvID0gW10sIGEgPSAic3RyaW5nIiAhPSB0eXBlb2YgZSAmJiBFKGUpOw0KCQkJCWlmKCFrLnRlc3QoZSkpIGZvcig7IHIgPCBpOyByKyspIGZvcihuID0gdGhpc1tyXTsgbiAmJiBuICE9PSB0OyBuID0gbi5wYXJlbnROb2RlKSBpZihuLm5vZGVUeXBlIDwgMTEgJiYgKGEgPyAtMSA8IGEuaW5kZXgobikgOiAxID09PSBuLm5vZGVUeXBlICYmIEUuZmluZC5tYXRjaGVzU2VsZWN0b3IobiwgZSkpKSB7DQoJCQkJCW8ucHVzaChuKTsNCgkJCQkJYnJlYWsNCgkJCQl9DQoJCQkJcmV0dXJuIHRoaXMucHVzaFN0YWNrKDEgPCBvLmxlbmd0aCA/IEUudW5pcXVlU29ydChvKSA6IG8pDQoJCQl9LA0KCQkJaW5kZXg6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gZSA/ICJzdHJpbmciID09IHR5cGVvZiBlID8gaS5jYWxsKEUoZSksIHRoaXNbMF0pIDogaS5jYWxsKHRoaXMsIGUuanF1ZXJ5ID8gZVswXSA6IGUpIDogdGhpc1swXSAmJiB0aGlzWzBdLnBhcmVudE5vZGUgPyB0aGlzLmZpcnN0KCkucHJldkFsbCgpLmxlbmd0aCA6IC0xfSwNCgkJCWFkZDogZnVuY3Rpb24oZSwgdCkge3JldHVybiB0aGlzLnB1c2hTdGFjayhFLnVuaXF1ZVNvcnQoRS5tZXJnZSh0aGlzLmdldCgpLCBFKGUsIHQpKSkpfSwNCgkJCWFkZEJhY2s6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gdGhpcy5hZGQobnVsbCA9PSBlID8gdGhpcy5wcmV2T2JqZWN0IDogdGhpcy5wcmV2T2JqZWN0LmZpbHRlcihlKSl9DQoJCX0pLCBFLmVhY2goew0KCQkJcGFyZW50OiBmdW5jdGlvbihlKSB7DQoJCQkJdmFyIHQgPSBlLnBhcmVudE5vZGU7DQoJCQkJcmV0dXJuIHQgJiYgMTEgIT09IHQubm9kZVR5cGUgPyB0IDogbnVsbA0KCQkJfSwNCgkJCXBhcmVudHM6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gaChlLCAicGFyZW50Tm9kZSIpfSwNCgkJCXBhcmVudHNVbnRpbDogZnVuY3Rpb24oZSwgdCwgbikge3JldHVybiBoKGUsICJwYXJlbnROb2RlIiwgbil9LA0KCQkJbmV4dDogZnVuY3Rpb24oZSkge3JldHVybiBPKGUsICJuZXh0U2libGluZyIpfSwNCgkJCXByZXY6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gTyhlLCAicHJldmlvdXNTaWJsaW5nIil9LA0KCQkJbmV4dEFsbDogZnVuY3Rpb24oZSkge3JldHVybiBoKGUsICJuZXh0U2libGluZyIpfSwNCgkJCXByZXZBbGw6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gaChlLCAicHJldmlvdXNTaWJsaW5nIil9LA0KCQkJbmV4dFVudGlsOiBmdW5jdGlvbihlLCB0LCBuKSB7cmV0dXJuIGgoZSwgIm5leHRTaWJsaW5nIiwgbil9LA0KCQkJcHJldlVudGlsOiBmdW5jdGlvbihlLCB0LCBuKSB7cmV0dXJuIGgoZSwgInByZXZpb3VzU2libGluZyIsIG4pfSwNCgkJCXNpYmxpbmdzOiBmdW5jdGlvbihlKSB7cmV0dXJuIFQoKGUucGFyZW50Tm9kZSB8fCB7fSkuZmlyc3RDaGlsZCwgZSl9LA0KCQkJY2hpbGRyZW46IGZ1bmN0aW9uKGUpIHtyZXR1cm4gVChlLmZpcnN0Q2hpbGQpfSwNCgkJCWNvbnRlbnRzOiBmdW5jdGlvbihlKSB7cmV0dXJuIG51bGwgIT0gZS5jb250ZW50RG9jdW1lbnQgJiYgcihlLmNvbnRlbnREb2N1bWVudCkgPyBlLmNvbnRlbnREb2N1bWVudCA6IChBKGUsICJ0ZW1wbGF0ZSIpICYmIChlID0gZS5jb250ZW50IHx8IGUpLCBFLm1lcmdlKFtdLCBlLmNoaWxkTm9kZXMpKX0NCgkJfSwgZnVuY3Rpb24ociwgaSkgew0KCQkJRS5mbltyXSA9IGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQl2YXIgbiA9IEUubWFwKHRoaXMsIGksIGUpOw0KCQkJCXJldHVybiAiVW50aWwiICE9PSByLnNsaWNlKC01KSAmJiAodCA9IGUpLCB0ICYmICJzdHJpbmciID09IHR5cGVvZiB0ICYmIChuID0gRS5maWx0ZXIodCwgbikpLCAxIDwgdGhpcy5sZW5ndGggJiYgKEhbcl0gfHwgRS51bmlxdWVTb3J0KG4pLCBMLnRlc3QocikgJiYgbi5yZXZlcnNlKCkpLCB0aGlzLnB1c2hTdGFjayhuKQ0KCQkJfQ0KCQl9KTsNCgkJdmFyIFAgPSAvW15ceDIwXHRcclxuXGZdKy9nOw0KDQoJCWZ1bmN0aW9uIFIoZSkge3JldHVybiBlfQ0KDQoJCWZ1bmN0aW9uIE0oZSkge3Rocm93IGV9DQoNCgkJZnVuY3Rpb24gSShlLCB0LCBuLCByKSB7DQoJCQl2YXIgaTsNCgkJCXRyeSB7ZSAmJiBtKGkgPSBlLnByb21pc2UpID8gaS5jYWxsKGUpLmRvbmUodCkuZmFpbChuKSA6IGUgJiYgbShpID0gZS50aGVuKSA/IGkuY2FsbChlLCB0LCBuKSA6IHQuYXBwbHkodm9pZCAwLCBbZV0uc2xpY2UocikpfSBjYXRjaChlKSB7bi5hcHBseSh2b2lkIDAsIFtlXSl9DQoJCX0NCg0KCQlFLkNhbGxiYWNrcyA9IGZ1bmN0aW9uKHIpIHsNCgkJCXZhciBlLCBuOw0KCQkJciA9ICJzdHJpbmciID09IHR5cGVvZiByID8gKGUgPSByLCBuID0ge30sIEUuZWFjaChlLm1hdGNoKFApIHx8IFtdLCBmdW5jdGlvbihlLCB0KSB7blt0XSA9ICEwfSksIG4pIDogRS5leHRlbmQoe30sIHIpOw0KCQkJdmFyIGksDQoJCQkgICAgdCwNCgkJCSAgICBvLA0KCQkJICAgIGEsDQoJCQkgICAgcyA9IFtdLA0KCQkJICAgIHUgPSBbXSwNCgkJCSAgICBsID0gLTEsDQoJCQkgICAgYyA9IGZ1bmN0aW9uKCkgew0KCQkJCSAgICBmb3IoYSA9IGEgfHwgci5vbmNlLCBvID0gaSA9ICEwOyB1Lmxlbmd0aDsgbCA9IC0xKSB7DQoJCQkJCSAgICB0ID0gdS5zaGlmdCgpOw0KCQkJCQkgICAgd2hpbGUoKytsIDwgcy5sZW5ndGgpICExID09PSBzW2xdLmFwcGx5KHRbMF0sIHRbMV0pICYmIHIuc3RvcE9uRmFsc2UgJiYgKGwgPSBzLmxlbmd0aCwgdCA9ICExKQ0KCQkJCSAgICB9DQoJCQkJICAgIHIubWVtb3J5IHx8ICh0ID0gITEpLCBpID0gITEsIGEgJiYgKHMgPSB0ID8gW10gOiAiIikNCgkJCSAgICB9LA0KCQkJICAgIGYgPSB7DQoJCQkJICAgIGFkZDogZnVuY3Rpb24oKSB7cmV0dXJuIHMgJiYgKHQgJiYgIWkgJiYgKGwgPSBzLmxlbmd0aCAtIDEsIHUucHVzaCh0KSksIGZ1bmN0aW9uIG4oZSkge0UuZWFjaChlLCBmdW5jdGlvbihlLCB0KSB7bSh0KSA/IHIudW5pcXVlICYmIGYuaGFzKHQpIHx8IHMucHVzaCh0KSA6IHQgJiYgdC5sZW5ndGggJiYgInN0cmluZyIgIT09IHcodCkgJiYgbih0KX0pfShhcmd1bWVudHMpLCB0ICYmICFpICYmIGMoKSksIHRoaXN9LA0KCQkJCSAgICByZW1vdmU6IGZ1bmN0aW9uKCkgew0KCQkJCQkgICAgcmV0dXJuIEUuZWFjaChhcmd1bWVudHMsIGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQkJCSAgICB2YXIgbjsNCgkJCQkJCSAgICB3aGlsZSgtMSA8IChuID0gRS5pbkFycmF5KHQsIHMsIG4pKSkgcy5zcGxpY2UobiwgMSksIG4gPD0gbCAmJiBsLS0NCgkJCQkJICAgIH0pLCB0aGlzDQoJCQkJICAgIH0sDQoJCQkJICAgIGhhczogZnVuY3Rpb24oZSkge3JldHVybiBlID8gLTEgPCBFLmluQXJyYXkoZSwgcykgOiAwIDwgcy5sZW5ndGh9LA0KCQkJCSAgICBlbXB0eTogZnVuY3Rpb24oKSB7cmV0dXJuIHMgJiYgKHMgPSBbXSksIHRoaXN9LA0KCQkJCSAgICBkaXNhYmxlOiBmdW5jdGlvbigpIHtyZXR1cm4gYSA9IHUgPSBbXSwgcyA9IHQgPSAiIiwgdGhpc30sDQoJCQkJICAgIGRpc2FibGVkOiBmdW5jdGlvbigpIHtyZXR1cm4gIXN9LA0KCQkJCSAgICBsb2NrOiBmdW5jdGlvbigpIHtyZXR1cm4gYSA9IHUgPSBbXSwgdCB8fCBpIHx8IChzID0gdCA9ICIiKSwgdGhpc30sDQoJCQkJICAgIGxvY2tlZDogZnVuY3Rpb24oKSB7cmV0dXJuICEhYX0sDQoJCQkJICAgIGZpcmVXaXRoOiBmdW5jdGlvbihlLCB0KSB7cmV0dXJuIGEgfHwgKHQgPSBbZSwgKHQgPSB0IHx8IFtdKS5zbGljZSA/IHQuc2xpY2UoKSA6IHRdLCB1LnB1c2godCksIGkgfHwgYygpKSwgdGhpc30sDQoJCQkJICAgIGZpcmU6IGZ1bmN0aW9uKCkge3JldHVybiBmLmZpcmVXaXRoKHRoaXMsIGFyZ3VtZW50cyksIHRoaXN9LA0KCQkJCSAgICBmaXJlZDogZnVuY3Rpb24oKSB7cmV0dXJuICEhb30NCgkJCSAgICB9Ow0KCQkJcmV0dXJuIGYNCgkJfSwgRS5leHRlbmQoew0KCQkJRGVmZXJyZWQ6IGZ1bmN0aW9uKGUpIHsNCgkJCQl2YXIgbyA9IFtbIm5vdGlmeSIsICJwcm9ncmVzcyIsIEUuQ2FsbGJhY2tzKCJtZW1vcnkiKSwgRS5DYWxsYmFja3MoIm1lbW9yeSIpLCAyXSwgWyJyZXNvbHZlIiwgImRvbmUiLCBFLkNhbGxiYWNrcygib25jZSBtZW1vcnkiKSwgRS5DYWxsYmFja3MoIm9uY2UgbWVtb3J5IiksIDAsICJyZXNvbHZlZCJdLCBbInJlamVjdCIsICJmYWlsIiwgRS5DYWxsYmFja3MoIm9uY2UgbWVtb3J5IiksIEUuQ2FsbGJhY2tzKCJvbmNlIG1lbW9yeSIpLCAxLCAicmVqZWN0ZWQiXV0sDQoJCQkJICAgIGkgPSAicGVuZGluZyIsDQoJCQkJICAgIGEgPSB7DQoJCQkJCSAgICBzdGF0ZTogZnVuY3Rpb24oKSB7cmV0dXJuIGl9LCBhbHdheXM6IGZ1bmN0aW9uKCkge3JldHVybiBzLmRvbmUoYXJndW1lbnRzKS5mYWlsKGFyZ3VtZW50cyksIHRoaXN9LCAiY2F0Y2giOiBmdW5jdGlvbihlKSB7cmV0dXJuIGEudGhlbihudWxsLCBlKX0sIHBpcGU6IGZ1bmN0aW9uKCkgew0KCQkJCQkJICAgIHZhciBpID0gYXJndW1lbnRzOw0KCQkJCQkJICAgIHJldHVybiBFLkRlZmVycmVkKGZ1bmN0aW9uKHIpIHsNCgkJCQkJCQkgICAgRS5lYWNoKG8sIGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQkJCQkJICAgIHZhciBuID0gbShpW3RbNF1dKSAmJiBpW3RbNF1dOw0KCQkJCQkJCQkgICAgc1t0WzFdXShmdW5jdGlvbigpIHsNCgkJCQkJCQkJCSAgICB2YXIgZSA9IG4gJiYgbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpOw0KCQkJCQkJCQkJICAgIGUgJiYgbShlLnByb21pc2UpID8gZS5wcm9taXNlKCkucHJvZ3Jlc3Moci5ub3RpZnkpLmRvbmUoci5yZXNvbHZlKS5mYWlsKHIucmVqZWN0KSA6IHJbdFswXSArICJXaXRoIl0odGhpcywgbiA/IFtlXSA6IGFyZ3VtZW50cykNCgkJCQkJCQkJICAgIH0pDQoJCQkJCQkJICAgIH0pLCBpID0gbnVsbA0KCQkJCQkJICAgIH0pLnByb21pc2UoKQ0KCQkJCQkgICAgfSwgdGhlbjogZnVuY3Rpb24odCwgbiwgcikgew0KCQkJCQkJICAgIHZhciB1ID0gMDsNCg0KCQkJCQkJICAgIGZ1bmN0aW9uIGwoaSwgbywgYSwgcykgew0KCQkJCQkJCSAgICByZXR1cm4gZnVuY3Rpb24oKSB7DQoJCQkJCQkJCSAgICB2YXIgbiA9IHRoaXMsIHIgPSBhcmd1bWVudHMsIGUgPSBmdW5jdGlvbigpIHsNCgkJCQkJCQkJCSAgICB2YXIgZSwgdDsNCgkJCQkJCQkJCSAgICBpZighKGkgPCB1KSkgew0KCQkJCQkJCQkJCSAgICBpZigoZSA9IGEuYXBwbHkobiwgcikpID09PSBvLnByb21pc2UoKSkgdGhyb3cgbmV3IFR5cGVFcnJvcigiVGhlbmFibGUgc2VsZi1yZXNvbHV0aW9uIik7DQoJCQkJCQkJCQkJICAgIHQgPSBlICYmICgib2JqZWN0IiA9PSB0eXBlb2YgZSB8fCAiZnVuY3Rpb24iID09IHR5cGVvZiBlKSAmJiBlLnRoZW4sIG0odCkgPyBzID8gdC5jYWxsKGUsIGwodSwgbywgUiwgcyksIGwodSwgbywgTSwgcykpIDogKHUrKywgdC5jYWxsKGUsIGwodSwgbywgUiwgcyksIGwodSwgbywgTSwgcyksIGwodSwgbywgUiwgby5ub3RpZnlXaXRoKSkpIDogKGEgIT09IFIgJiYgKG4gPSB2b2lkIDAsIHIgPSBbZV0pLCAocyB8fCBvLnJlc29sdmVXaXRoKShuLCByKSkNCgkJCQkJCQkJCSAgICB9DQoJCQkJCQkJCSAgICB9LCB0ID0gcyA/IGUgOiBmdW5jdGlvbigpIHt0cnkge2UoKX0gY2F0Y2goZSkge0UuRGVmZXJyZWQuZXhjZXB0aW9uSG9vayAmJiBFLkRlZmVycmVkLmV4Y2VwdGlvbkhvb2soZSwgdC5zdGFja1RyYWNlKSwgdSA8PSBpICsgMSAmJiAoYSAhPT0gTSAmJiAobiA9IHZvaWQgMCwgciA9IFtlXSksIG8ucmVqZWN0V2l0aChuLCByKSl9fTsNCgkJCQkJCQkJICAgIGkgPyB0KCkgOiAoRS5EZWZlcnJlZC5nZXRTdGFja0hvb2sgJiYgKHQuc3RhY2tUcmFjZSA9IEUuRGVmZXJyZWQuZ2V0U3RhY2tIb29rKCkpLCBDLnNldFRpbWVvdXQodCkpDQoJCQkJCQkJICAgIH0NCgkJCQkJCSAgICB9DQoNCgkJCQkJCSAgICByZXR1cm4gRS5EZWZlcnJlZChmdW5jdGlvbihlKSB7b1swXVszXS5hZGQobCgwLCBlLCBtKHIpID8gciA6IFIsIGUubm90aWZ5V2l0aCkpLCBvWzFdWzNdLmFkZChsKDAsIGUsIG0odCkgPyB0IDogUikpLCBvWzJdWzNdLmFkZChsKDAsIGUsIG0obikgPyBuIDogTSkpfSkucHJvbWlzZSgpDQoJCQkJCSAgICB9LCBwcm9taXNlOiBmdW5jdGlvbihlKSB7cmV0dXJuIG51bGwgIT0gZSA/IEUuZXh0ZW5kKGUsIGEpIDogYX0NCgkJCQkgICAgfSwNCgkJCQkgICAgcyA9IHt9Ow0KCQkJCXJldHVybiBFLmVhY2gobywgZnVuY3Rpb24oZSwgdCkgew0KCQkJCQl2YXIgbiA9IHRbMl0sIHIgPSB0WzVdOw0KCQkJCQlhW3RbMV1dID0gbi5hZGQsIHIgJiYgbi5hZGQoZnVuY3Rpb24oKSB7aSA9IHJ9LCBvWzMgLSBlXVsyXS5kaXNhYmxlLCBvWzMgLSBlXVszXS5kaXNhYmxlLCBvWzBdWzJdLmxvY2ssIG9bMF1bM10ubG9jayksIG4uYWRkKHRbM10uZmlyZSksIHNbdFswXV0gPSBmdW5jdGlvbigpIHtyZXR1cm4gc1t0WzBdICsgIldpdGgiXSh0aGlzID09PSBzID8gdm9pZCAwIDogdGhpcywgYXJndW1lbnRzKSwgdGhpc30sIHNbdFswXSArICJXaXRoIl0gPSBuLmZpcmVXaXRoDQoJCQkJfSksIGEucHJvbWlzZShzKSwgZSAmJiBlLmNhbGwocywgcyksIHMNCgkJCX0sIHdoZW46IGZ1bmN0aW9uKGUpIHsNCgkJCQl2YXIgbiA9IGFyZ3VtZW50cy5sZW5ndGgsIHQgPSBuLCByID0gQXJyYXkodCksIGkgPSBzLmNhbGwoYXJndW1lbnRzKSwgbyA9IEUuRGVmZXJyZWQoKSwgYSA9IGZ1bmN0aW9uKHQpIHtyZXR1cm4gZnVuY3Rpb24oZSkge3JbdF0gPSB0aGlzLCBpW3RdID0gMSA8IGFyZ3VtZW50cy5sZW5ndGggPyBzLmNhbGwoYXJndW1lbnRzKSA6IGUsIC0tbiB8fCBvLnJlc29sdmVXaXRoKHIsIGkpfX07DQoJCQkJaWYobiA8PSAxICYmIChJKGUsIG8uZG9uZShhKHQpKS5yZXNvbHZlLCBvLnJlamVjdCwgIW4pLCAicGVuZGluZyIgPT09IG8uc3RhdGUoKSB8fCBtKGlbdF0gJiYgaVt0XS50aGVuKSkpIHJldHVybiBvLnRoZW4oKTsNCgkJCQl3aGlsZSh0LS0pIEkoaVt0XSwgYSh0KSwgby5yZWplY3QpOw0KCQkJCXJldHVybiBvLnByb21pc2UoKQ0KCQkJfQ0KCQl9KTsNCgkJdmFyIFcgPSAvXihFdmFsfEludGVybmFsfFJhbmdlfFJlZmVyZW5jZXxTeW50YXh8VHlwZXxVUkkpRXJyb3IkLzsNCgkJRS5EZWZlcnJlZC5leGNlcHRpb25Ib29rID0gZnVuY3Rpb24oZSwgdCkge0MuY29uc29sZSAmJiBDLmNvbnNvbGUud2FybiAmJiBlICYmIFcudGVzdChlLm5hbWUpICYmIEMuY29uc29sZS53YXJuKCJqUXVlcnkuRGVmZXJyZWQgZXhjZXB0aW9uOiAiICsgZS5tZXNzYWdlLCBlLnN0YWNrLCB0KX0sIEUucmVhZHlFeGNlcHRpb24gPSBmdW5jdGlvbihlKSB7Qy5zZXRUaW1lb3V0KGZ1bmN0aW9uKCkge3Rocm93IGV9KX07DQoJCXZhciBGID0gRS5EZWZlcnJlZCgpOw0KDQoJCWZ1bmN0aW9uICQoKSB7Uy5yZW1vdmVFdmVudExpc3RlbmVyKCJET01Db250ZW50TG9hZGVkIiwgJCksIEMucmVtb3ZlRXZlbnRMaXN0ZW5lcigibG9hZCIsICQpLCBFLnJlYWR5KCl9DQoNCgkJRS5mbi5yZWFkeSA9IGZ1bmN0aW9uKGUpIHtyZXR1cm4gRi50aGVuKGUpWyJjYXRjaCJdKGZ1bmN0aW9uKGUpIHtFLnJlYWR5RXhjZXB0aW9uKGUpfSksIHRoaXN9LCBFLmV4dGVuZCh7DQoJCQlpc1JlYWR5OiAhMSwNCgkJCXJlYWR5V2FpdDogMSwNCgkJCXJlYWR5OiBmdW5jdGlvbihlKSB7KCEwID09PSBlID8gLS1FLnJlYWR5V2FpdCA6IEUuaXNSZWFkeSkgfHwgKEUuaXNSZWFkeSA9ICEwKSAhPT0gZSAmJiAwIDwgLS1FLnJlYWR5V2FpdCB8fCBGLnJlc29sdmVXaXRoKFMsIFtFXSl9DQoJCX0pLCBFLnJlYWR5LnRoZW4gPSBGLnRoZW4sICJjb21wbGV0ZSIgPT09IFMucmVhZHlTdGF0ZSB8fCAibG9hZGluZyIgIT09IFMucmVhZHlTdGF0ZSAmJiAhUy5kb2N1bWVudEVsZW1lbnQuZG9TY3JvbGwgPyBDLnNldFRpbWVvdXQoRS5yZWFkeSkgOiAoUy5hZGRFdmVudExpc3RlbmVyKCJET01Db250ZW50TG9hZGVkIiwgJCksIEMuYWRkRXZlbnRMaXN0ZW5lcigibG9hZCIsICQpKTsNCgkJdmFyIEIgPSBmdW5jdGlvbihlLCB0LCBuLCByLCBpLCBvLCBhKSB7DQoJCQl2YXIgcyA9IDAsIHUgPSBlLmxlbmd0aCwgbCA9IG51bGwgPT0gbjsNCgkJCWlmKCJvYmplY3QiID09PSB3KG4pKSBmb3IocyBpbiBpID0gITAsIG4pIEIoZSwgdCwgcywgbltzXSwgITAsIG8sIGEpOyBlbHNlIGlmKHZvaWQgMCAhPT0gciAmJiAoaSA9ICEwLCBtKHIpIHx8IChhID0gITApLCBsICYmIChhID8gKHQuY2FsbChlLCByKSwgdCA9IG51bGwpIDogKGwgPSB0LCB0ID0gZnVuY3Rpb24oZSwgdCwgbikge3JldHVybiBsLmNhbGwoRShlKSwgbil9KSksIHQpKSBmb3IoOyBzIDwgdTsgcysrKSB0KGVbc10sIG4sIGEgPyByIDogci5jYWxsKGVbc10sIHMsIHQoZVtzXSwgbikpKTsNCgkJCXJldHVybiBpID8gZSA6IGwgPyB0LmNhbGwoZSkgOiB1ID8gdChlWzBdLCBuKSA6IG8NCgkJfSwgXyAgPSAvXi1tcy0vLCB6ID0gLy0oW2Etel0pL2c7DQoNCgkJZnVuY3Rpb24gVShlLCB0KSB7cmV0dXJuIHQudG9VcHBlckNhc2UoKX0NCg0KCQlmdW5jdGlvbiBYKGUpIHtyZXR1cm4gZS5yZXBsYWNlKF8sICJtcy0iKS5yZXBsYWNlKHosIFUpfQ0KDQoJCXZhciBWID0gZnVuY3Rpb24oZSkge3JldHVybiAxID09PSBlLm5vZGVUeXBlIHx8IDkgPT09IGUubm9kZVR5cGUgfHwgIStlLm5vZGVUeXBlfTsNCg0KCQlmdW5jdGlvbiBHKCkge3RoaXMuZXhwYW5kbyA9IEUuZXhwYW5kbyArIEcudWlkKyt9DQoNCgkJRy51aWQgPSAxLCBHLnByb3RvdHlwZSA9IHsNCgkJCWNhY2hlOiBmdW5jdGlvbihlKSB7DQoJCQkJdmFyIHQgPSBlW3RoaXMuZXhwYW5kb107DQoJCQkJcmV0dXJuIHQgfHwgKHQgPSB7fSwgVihlKSAmJiAoZS5ub2RlVHlwZSA/IGVbdGhpcy5leHBhbmRvXSA9IHQgOiBPYmplY3QuZGVmaW5lUHJvcGVydHkoZSwgdGhpcy5leHBhbmRvLCB7dmFsdWU6IHQsIGNvbmZpZ3VyYWJsZTogITB9KSkpLCB0DQoJCQl9LA0KCQkJc2V0OiBmdW5jdGlvbihlLCB0LCBuKSB7DQoJCQkJdmFyIHIsIGkgPSB0aGlzLmNhY2hlKGUpOw0KCQkJCWlmKCJzdHJpbmciID09IHR5cGVvZiB0KSBpW1godCldID0gbjsgZWxzZSBmb3IociBpbiB0KSBpW1gocildID0gdFtyXTsNCgkJCQlyZXR1cm4gaQ0KCQkJfSwNCgkJCWdldDogZnVuY3Rpb24oZSwgdCkge3JldHVybiB2b2lkIDAgPT09IHQgPyB0aGlzLmNhY2hlKGUpIDogZVt0aGlzLmV4cGFuZG9dICYmIGVbdGhpcy5leHBhbmRvXVtYKHQpXX0sDQoJCQlhY2Nlc3M6IGZ1bmN0aW9uKGUsIHQsIG4pIHtyZXR1cm4gdm9pZCAwID09PSB0IHx8IHQgJiYgInN0cmluZyIgPT0gdHlwZW9mIHQgJiYgdm9pZCAwID09PSBuID8gdGhpcy5nZXQoZSwgdCkgOiAodGhpcy5zZXQoZSwgdCwgbiksIHZvaWQgMCAhPT0gbiA/IG4gOiB0KX0sDQoJCQlyZW1vdmU6IGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQl2YXIgbiwgciA9IGVbdGhpcy5leHBhbmRvXTsNCgkJCQlpZih2b2lkIDAgIT09IHIpIHsNCgkJCQkJaWYodm9pZCAwICE9PSB0KSB7DQoJCQkJCQluID0gKHQgPSBBcnJheS5pc0FycmF5KHQpID8gdC5tYXAoWCkgOiAodCA9IFgodCkpIGluIHIgPyBbdF0gOiB0Lm1hdGNoKFApIHx8IFtdKS5sZW5ndGg7DQoJCQkJCQl3aGlsZShuLS0pIGRlbGV0ZSByW3Rbbl1dDQoJCQkJCX0NCgkJCQkJKHZvaWQgMCA9PT0gdCB8fCBFLmlzRW1wdHlPYmplY3QocikpICYmIChlLm5vZGVUeXBlID8gZVt0aGlzLmV4cGFuZG9dID0gdm9pZCAwIDogZGVsZXRlIGVbdGhpcy5leHBhbmRvXSkNCgkJCQl9DQoJCQl9LA0KCQkJaGFzRGF0YTogZnVuY3Rpb24oZSkgew0KCQkJCXZhciB0ID0gZVt0aGlzLmV4cGFuZG9dOw0KCQkJCXJldHVybiB2b2lkIDAgIT09IHQgJiYgIUUuaXNFbXB0eU9iamVjdCh0KQ0KCQkJfQ0KCQl9Ow0KCQl2YXIgWSA9IG5ldyBHLCBRID0gbmV3IEcsIEogPSAvXig/Olx7W1x3XFddKlx9fFxbW1x3XFddKlxdKSQvLCBLID0gL1tBLVpdL2c7DQoNCgkJZnVuY3Rpb24gWihlLCB0LCBuKSB7DQoJCQl2YXIgciwgaTsNCgkJCWlmKHZvaWQgMCA9PT0gbiAmJiAxID09PSBlLm5vZGVUeXBlKSBpZihyID0gImRhdGEtIiArIHQucmVwbGFjZShLLCAiLSQmIikudG9Mb3dlckNhc2UoKSwgInN0cmluZyIgPT0gdHlwZW9mIChuID0gZS5nZXRBdHRyaWJ1dGUocikpKSB7DQoJCQkJdHJ5IHtuID0gInRydWUiID09PSAoaSA9IG4pIHx8ICJmYWxzZSIgIT09IGkgJiYgKCJudWxsIiA9PT0gaSA/IG51bGwgOiBpID09PSAraSArICIiID8gK2kgOiBKLnRlc3QoaSkgPyBKU09OLnBhcnNlKGkpIDogaSl9IGNhdGNoKGUpIHt9DQoJCQkJUS5zZXQoZSwgdCwgbikNCgkJCX0gZWxzZSBuID0gdm9pZCAwOw0KCQkJcmV0dXJuIG4NCgkJfQ0KDQoJCUUuZXh0ZW5kKHsNCgkJCWhhc0RhdGE6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gUS5oYXNEYXRhKGUpIHx8IFkuaGFzRGF0YShlKX0sDQoJCQlkYXRhOiBmdW5jdGlvbihlLCB0LCBuKSB7cmV0dXJuIFEuYWNjZXNzKGUsIHQsIG4pfSwNCgkJCXJlbW92ZURhdGE6IGZ1bmN0aW9uKGUsIHQpIHtRLnJlbW92ZShlLCB0KX0sDQoJCQlfZGF0YTogZnVuY3Rpb24oZSwgdCwgbikge3JldHVybiBZLmFjY2VzcyhlLCB0LCBuKX0sDQoJCQlfcmVtb3ZlRGF0YTogZnVuY3Rpb24oZSwgdCkge1kucmVtb3ZlKGUsIHQpfQ0KCQl9KSwgRS5mbi5leHRlbmQoew0KCQkJZGF0YTogZnVuY3Rpb24obiwgZSkgew0KCQkJCXZhciB0LCByLCBpLCBvID0gdGhpc1swXSwgYSA9IG8gJiYgby5hdHRyaWJ1dGVzOw0KCQkJCWlmKHZvaWQgMCA9PT0gbikgew0KCQkJCQlpZih0aGlzLmxlbmd0aCAmJiAoaSA9IFEuZ2V0KG8pLCAxID09PSBvLm5vZGVUeXBlICYmICFZLmdldChvLCAiaGFzRGF0YUF0dHJzIikpKSB7DQoJCQkJCQl0ID0gYS5sZW5ndGg7DQoJCQkJCQl3aGlsZSh0LS0pIGFbdF0gJiYgMCA9PT0gKHIgPSBhW3RdLm5hbWUpLmluZGV4T2YoImRhdGEtIikgJiYgKHIgPSBYKHIuc2xpY2UoNSkpLCBaKG8sIHIsIGlbcl0pKTsNCgkJCQkJCVkuc2V0KG8sICJoYXNEYXRhQXR0cnMiLCAhMCkNCgkJCQkJfQ0KCQkJCQlyZXR1cm4gaQ0KCQkJCX0NCgkJCQlyZXR1cm4gIm9iamVjdCIgPT0gdHlwZW9mIG4gPyB0aGlzLmVhY2goZnVuY3Rpb24oKSB7US5zZXQodGhpcywgbil9KSA6IEIodGhpcywgZnVuY3Rpb24oZSkgew0KCQkJCQl2YXIgdDsNCgkJCQkJaWYobyAmJiB2b2lkIDAgPT09IGUpIHJldHVybiB2b2lkIDAgIT09ICh0ID0gUS5nZXQobywgbikpID8gdCA6IHZvaWQgMCAhPT0gKHQgPSBaKG8sIG4pKSA/IHQgOiB2b2lkIDA7DQoJCQkJCXRoaXMuZWFjaChmdW5jdGlvbigpIHtRLnNldCh0aGlzLCBuLCBlKX0pDQoJCQkJfSwgbnVsbCwgZSwgMSA8IGFyZ3VtZW50cy5sZW5ndGgsIG51bGwsICEwKQ0KCQkJfSwgcmVtb3ZlRGF0YTogZnVuY3Rpb24oZSkge3JldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7US5yZW1vdmUodGhpcywgZSl9KX0NCgkJfSksIEUuZXh0ZW5kKHsNCgkJCXF1ZXVlOiBmdW5jdGlvbihlLCB0LCBuKSB7DQoJCQkJdmFyIHI7DQoJCQkJaWYoZSkgcmV0dXJuIHQgPSAodCB8fCAiZngiKSArICJxdWV1ZSIsIHIgPSBZLmdldChlLCB0KSwgbiAmJiAoIXIgfHwgQXJyYXkuaXNBcnJheShuKSA/IHIgPSBZLmFjY2VzcyhlLCB0LCBFLm1ha2VBcnJheShuKSkgOiByLnB1c2gobikpLCByIHx8IFtdDQoJCQl9LCBkZXF1ZXVlOiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJdCA9IHQgfHwgImZ4IjsNCgkJCQl2YXIgbiA9IEUucXVldWUoZSwgdCksIHIgPSBuLmxlbmd0aCwgaSA9IG4uc2hpZnQoKSwgbyA9IEUuX3F1ZXVlSG9va3MoZSwgdCk7DQoJCQkJImlucHJvZ3Jlc3MiID09PSBpICYmIChpID0gbi5zaGlmdCgpLCByLS0pLCBpICYmICgiZngiID09PSB0ICYmIG4udW5zaGlmdCgiaW5wcm9ncmVzcyIpLCBkZWxldGUgby5zdG9wLCBpLmNhbGwoZSwgZnVuY3Rpb24oKSB7RS5kZXF1ZXVlKGUsIHQpfSwgbykpLCAhciAmJiBvICYmIG8uZW1wdHkuZmlyZSgpDQoJCQl9LCBfcXVldWVIb29rczogZnVuY3Rpb24oZSwgdCkgew0KCQkJCXZhciBuID0gdCArICJxdWV1ZUhvb2tzIjsNCgkJCQlyZXR1cm4gWS5nZXQoZSwgbikgfHwgWS5hY2Nlc3MoZSwgbiwge2VtcHR5OiBFLkNhbGxiYWNrcygib25jZSBtZW1vcnkiKS5hZGQoZnVuY3Rpb24oKSB7WS5yZW1vdmUoZSwgW3QgKyAicXVldWUiLCBuXSl9KX0pDQoJCQl9DQoJCX0pLCBFLmZuLmV4dGVuZCh7DQoJCQlxdWV1ZTogZnVuY3Rpb24odCwgbikgew0KCQkJCXZhciBlID0gMjsNCgkJCQlyZXR1cm4gInN0cmluZyIgIT0gdHlwZW9mIHQgJiYgKG4gPSB0LCB0ID0gImZ4IiwgZS0tKSwgYXJndW1lbnRzLmxlbmd0aCA8IGUgPyBFLnF1ZXVlKHRoaXNbMF0sIHQpIDogdm9pZCAwID09PSBuID8gdGhpcyA6IHRoaXMuZWFjaChmdW5jdGlvbigpIHsNCgkJCQkJdmFyIGUgPSBFLnF1ZXVlKHRoaXMsIHQsIG4pOw0KCQkJCQlFLl9xdWV1ZUhvb2tzKHRoaXMsIHQpLCAiZngiID09PSB0ICYmICJpbnByb2dyZXNzIiAhPT0gZVswXSAmJiBFLmRlcXVldWUodGhpcywgdCkNCgkJCQl9KQ0KCQkJfSwgZGVxdWV1ZTogZnVuY3Rpb24oZSkge3JldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7RS5kZXF1ZXVlKHRoaXMsIGUpfSl9LCBjbGVhclF1ZXVlOiBmdW5jdGlvbihlKSB7cmV0dXJuIHRoaXMucXVldWUoZSB8fCAiZngiLCBbXSl9LCBwcm9taXNlOiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJdmFyIG4sIHIgPSAxLCBpID0gRS5EZWZlcnJlZCgpLCBvID0gdGhpcywgYSA9IHRoaXMubGVuZ3RoLCBzID0gZnVuY3Rpb24oKSB7LS1yIHx8IGkucmVzb2x2ZVdpdGgobywgW29dKX07DQoJCQkJInN0cmluZyIgIT0gdHlwZW9mIGUgJiYgKHQgPSBlLCBlID0gdm9pZCAwKSwgZSA9IGUgfHwgImZ4IjsNCgkJCQl3aGlsZShhLS0pIChuID0gWS5nZXQob1thXSwgZSArICJxdWV1ZUhvb2tzIikpICYmIG4uZW1wdHkgJiYgKHIrKywgbi5lbXB0eS5hZGQocykpOw0KCQkJCXJldHVybiBzKCksIGkucHJvbWlzZSh0KQ0KCQkJfQ0KCQl9KTsNCgkJdmFyIGVlID0gL1srLV0/KD86XGQqXC58KVxkKyg/OltlRV1bKy1dP1xkK3wpLy5zb3VyY2UsIHRlID0gbmV3IFJlZ0V4cCgiXig/OihbKy1dKT18KSgiICsgZWUgKyAiKShbYS16JV0qKSQiLCAiaSIpLCBuZSA9IFsiVG9wIiwgIlJpZ2h0IiwgIkJvdHRvbSIsICJMZWZ0Il0sIHJlID0gUy5kb2N1bWVudEVsZW1lbnQsIGllID0gZnVuY3Rpb24oZSkge3JldHVybiBFLmNvbnRhaW5zKGUub3duZXJEb2N1bWVudCwgZSl9LCBvZSA9IHtjb21wb3NlZDogITB9Ow0KCQlyZS5nZXRSb290Tm9kZSAmJiAoaWUgPSBmdW5jdGlvbihlKSB7cmV0dXJuIEUuY29udGFpbnMoZS5vd25lckRvY3VtZW50LCBlKSB8fCBlLmdldFJvb3ROb2RlKG9lKSA9PT0gZS5vd25lckRvY3VtZW50fSk7DQoJCXZhciBhZSA9IGZ1bmN0aW9uKGUsIHQpIHtyZXR1cm4gIm5vbmUiID09PSAoZSA9IHQgfHwgZSkuc3R5bGUuZGlzcGxheSB8fCAiIiA9PT0gZS5zdHlsZS5kaXNwbGF5ICYmIGllKGUpICYmICJub25lIiA9PT0gRS5jc3MoZSwgImRpc3BsYXkiKX07DQoNCgkJZnVuY3Rpb24gc2UoZSwgdCwgbiwgcikgew0KCQkJdmFyIGksIG8sIGEgPSAyMCwgcyA9IHIgPyBmdW5jdGlvbigpIHtyZXR1cm4gci5jdXIoKX0gOiBmdW5jdGlvbigpIHtyZXR1cm4gRS5jc3MoZSwgdCwgIiIpfSwgdSA9IHMoKSwgbCA9IG4gJiYgblszXSB8fCAoRS5jc3NOdW1iZXJbdF0gPyAiIiA6ICJweCIpLCBjID0gZS5ub2RlVHlwZSAmJiAoRS5jc3NOdW1iZXJbdF0gfHwgInB4IiAhPT0gbCAmJiArdSkgJiYgdGUuZXhlYyhFLmNzcyhlLCB0KSk7DQoJCQlpZihjICYmIGNbM10gIT09IGwpIHsNCgkJCQl1IC89IDIsIGwgPSBsIHx8IGNbM10sIGMgPSArdSB8fCAxOw0KCQkJCXdoaWxlKGEtLSkgRS5zdHlsZShlLCB0LCBjICsgbCksICgxIC0gbykgKiAoMSAtIChvID0gcygpIC8gdSB8fCAuNSkpIDw9IDAgJiYgKGEgPSAwKSwgYyAvPSBvOw0KCQkJCWMgKj0gMiwgRS5zdHlsZShlLCB0LCBjICsgbCksIG4gPSBuIHx8IFtdDQoJCQl9DQoJCQlyZXR1cm4gbiAmJiAoYyA9ICtjIHx8ICt1IHx8IDAsIGkgPSBuWzFdID8gYyArIChuWzFdICsgMSkgKiBuWzJdIDogK25bMl0sIHIgJiYgKHIudW5pdCA9IGwsIHIuc3RhcnQgPSBjLCByLmVuZCA9IGkpKSwgaQ0KCQl9DQoNCgkJdmFyIHVlID0ge307DQoNCgkJZnVuY3Rpb24gbGUoZSwgdCkgew0KCQkJZm9yKHZhciBuLCByLCBpLCBvLCBhLCBzLCB1LCBsID0gW10sIGMgPSAwLCBmID0gZS5sZW5ndGg7IGMgPCBmOyBjKyspIChyID0gZVtjXSkuc3R5bGUgJiYgKG4gPSByLnN0eWxlLmRpc3BsYXksIHQgPyAoIm5vbmUiID09PSBuICYmIChsW2NdID0gWS5nZXQociwgImRpc3BsYXkiKSB8fCBudWxsLCBsW2NdIHx8IChyLnN0eWxlLmRpc3BsYXkgPSAiIikpLCAiIiA9PT0gci5zdHlsZS5kaXNwbGF5ICYmIGFlKHIpICYmIChsW2NdID0gKHUgPSBhID0gbyA9IHZvaWQgMCwgYSA9IChpID0gcikub3duZXJEb2N1bWVudCwgcyA9IGkubm9kZU5hbWUsICh1ID0gdWVbc10pIHx8IChvID0gYS5ib2R5LmFwcGVuZENoaWxkKGEuY3JlYXRlRWxlbWVudChzKSksIHUgPSBFLmNzcyhvLCAiZGlzcGxheSIpLCBvLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQobyksICJub25lIiA9PT0gdSAmJiAodSA9ICJibG9jayIpLCB1ZVtzXSA9IHUpKSkpIDogIm5vbmUiICE9PSBuICYmIChsW2NdID0gIm5vbmUiLCBZLnNldChyLCAiZGlzcGxheSIsIG4pKSk7DQoJCQlmb3IoYyA9IDA7IGMgPCBmOyBjKyspIG51bGwgIT0gbFtjXSAmJiAoZVtjXS5zdHlsZS5kaXNwbGF5ID0gbFtjXSk7DQoJCQlyZXR1cm4gZQ0KCQl9DQoNCgkJRS5mbi5leHRlbmQoe3Nob3c6IGZ1bmN0aW9uKCkge3JldHVybiBsZSh0aGlzLCAhMCl9LCBoaWRlOiBmdW5jdGlvbigpIHtyZXR1cm4gbGUodGhpcyl9LCB0b2dnbGU6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gImJvb2xlYW4iID09IHR5cGVvZiBlID8gZSA/IHRoaXMuc2hvdygpIDogdGhpcy5oaWRlKCkgOiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7YWUodGhpcykgPyBFKHRoaXMpLnNob3coKSA6IEUodGhpcykuaGlkZSgpfSl9fSk7DQoJCXZhciBjZSwgZmUsIHBlID0gL14oPzpjaGVja2JveHxyYWRpbykkL2ksIGRlID0gLzwoW2Etel1bXlwvXDA+XHgyMFx0XHJcblxmXSopL2ksIGhlID0gL14kfF5tb2R1bGUkfFwvKD86amF2YXxlY21hKXNjcmlwdC9pOw0KCQljZSA9IFMuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpLmFwcGVuZENoaWxkKFMuY3JlYXRlRWxlbWVudCgiZGl2IikpLCAoZmUgPSBTLmNyZWF0ZUVsZW1lbnQoImlucHV0IikpLnNldEF0dHJpYnV0ZSgidHlwZSIsICJyYWRpbyIpLCBmZS5zZXRBdHRyaWJ1dGUoImNoZWNrZWQiLCAiY2hlY2tlZCIpLCBmZS5zZXRBdHRyaWJ1dGUoIm5hbWUiLCAidCIpLCBjZS5hcHBlbmRDaGlsZChmZSksIHYuY2hlY2tDbG9uZSA9IGNlLmNsb25lTm9kZSghMCkuY2xvbmVOb2RlKCEwKS5sYXN0Q2hpbGQuY2hlY2tlZCwgY2UuaW5uZXJIVE1MID0gIjx0ZXh0YXJlYT54PC90ZXh0YXJlYT4iLCB2Lm5vQ2xvbmVDaGVja2VkID0gISFjZS5jbG9uZU5vZGUoITApLmxhc3RDaGlsZC5kZWZhdWx0VmFsdWUsIGNlLmlubmVySFRNTCA9ICI8b3B0aW9uPjwvb3B0aW9uPiIsIHYub3B0aW9uID0gISFjZS5sYXN0Q2hpbGQ7DQoJCXZhciBnZSA9IHt0aGVhZDogWzEsICI8dGFibGU+IiwgIjwvdGFibGU+Il0sIGNvbDogWzIsICI8dGFibGU+PGNvbGdyb3VwPiIsICI8L2NvbGdyb3VwPjwvdGFibGU+Il0sIHRyOiBbMiwgIjx0YWJsZT48dGJvZHk+IiwgIjwvdGJvZHk+PC90YWJsZT4iXSwgdGQ6IFszLCAiPHRhYmxlPjx0Ym9keT48dHI+IiwgIjwvdHI+PC90Ym9keT48L3RhYmxlPiJdLCBfZGVmYXVsdDogWzAsICIiLCAiIl19Ow0KDQoJCWZ1bmN0aW9uIHllKGUsIHQpIHsNCgkJCXZhciBuOw0KCQkJcmV0dXJuIG4gPSAidW5kZWZpbmVkIiAhPSB0eXBlb2YgZS5nZXRFbGVtZW50c0J5VGFnTmFtZSA/IGUuZ2V0RWxlbWVudHNCeVRhZ05hbWUodCB8fCAiKiIpIDogInVuZGVmaW5lZCIgIT0gdHlwZW9mIGUucXVlcnlTZWxlY3RvckFsbCA/IGUucXVlcnlTZWxlY3RvckFsbCh0IHx8ICIqIikgOiBbXSwgdm9pZCAwID09PSB0IHx8IHQgJiYgQShlLCB0KSA/IEUubWVyZ2UoW2VdLCBuKSA6IG4NCgkJfQ0KDQoJCWZ1bmN0aW9uIHZlKGUsIHQpIHtmb3IodmFyIG4gPSAwLCByID0gZS5sZW5ndGg7IG4gPCByOyBuKyspIFkuc2V0KGVbbl0sICJnbG9iYWxFdmFsIiwgIXQgfHwgWS5nZXQodFtuXSwgImdsb2JhbEV2YWwiKSl9DQoNCgkJZ2UudGJvZHkgPSBnZS50Zm9vdCA9IGdlLmNvbGdyb3VwID0gZ2UuY2FwdGlvbiA9IGdlLnRoZWFkLCBnZS50aCA9IGdlLnRkLCB2Lm9wdGlvbiB8fCAoZ2Uub3B0Z3JvdXAgPSBnZS5vcHRpb24gPSBbMSwgIjxzZWxlY3QgbXVsdGlwbGU9J211bHRpcGxlJz4iLCAiPC9zZWxlY3Q+Il0pOw0KCQl2YXIgbWUgPSAvPHwmIz9cdys7LzsNCg0KCQlmdW5jdGlvbiB4ZShlLCB0LCBuLCByLCBpKSB7DQoJCQlmb3IodmFyIG8sIGEsIHMsIHUsIGwsIGMsIGYgPSB0LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKSwgcCA9IFtdLCBkID0gMCwgaCA9IGUubGVuZ3RoOyBkIDwgaDsgZCsrKSBpZigobyA9IGVbZF0pIHx8IDAgPT09IG8pIGlmKCJvYmplY3QiID09PSB3KG8pKSBFLm1lcmdlKHAsIG8ubm9kZVR5cGUgPyBbb10gOiBvKTsgZWxzZSBpZihtZS50ZXN0KG8pKSB7DQoJCQkJYSA9IGEgfHwgZi5hcHBlbmRDaGlsZCh0LmNyZWF0ZUVsZW1lbnQoImRpdiIpKSwgcyA9IChkZS5leGVjKG8pIHx8IFsiIiwgIiJdKVsxXS50b0xvd2VyQ2FzZSgpLCB1ID0gZ2Vbc10gfHwgZ2UuX2RlZmF1bHQsIGEuaW5uZXJIVE1MID0gdVsxXSArIEUuaHRtbFByZWZpbHRlcihvKSArIHVbMl0sIGMgPSB1WzBdOw0KCQkJCXdoaWxlKGMtLSkgYSA9IGEubGFzdENoaWxkOw0KCQkJCUUubWVyZ2UocCwgYS5jaGlsZE5vZGVzKSwgKGEgPSBmLmZpcnN0Q2hpbGQpLnRleHRDb250ZW50ID0gIiINCgkJCX0gZWxzZSBwLnB1c2godC5jcmVhdGVUZXh0Tm9kZShvKSk7DQoJCQlmLnRleHRDb250ZW50ID0gIiIsIGQgPSAwOw0KCQkJd2hpbGUobyA9IHBbZCsrXSkgaWYociAmJiAtMSA8IEUuaW5BcnJheShvLCByKSkgaSAmJiBpLnB1c2gobyk7IGVsc2UgaWYobCA9IGllKG8pLCBhID0geWUoZi5hcHBlbmRDaGlsZChvKSwgInNjcmlwdCIpLCBsICYmIHZlKGEpLCBuKSB7DQoJCQkJYyA9IDA7DQoJCQkJd2hpbGUobyA9IGFbYysrXSkgaGUudGVzdChvLnR5cGUgfHwgIiIpICYmIG4ucHVzaChvKQ0KCQkJfQ0KCQkJcmV0dXJuIGYNCgkJfQ0KDQoJCXZhciBiZSA9IC9eKFteLl0qKSg/OlwuKC4rKXwpLzsNCg0KCQlmdW5jdGlvbiB3ZSgpIHtyZXR1cm4gITB9DQoNCgkJZnVuY3Rpb24gVGUoKSB7cmV0dXJuICExfQ0KDQoJCWZ1bmN0aW9uIENlKGUsIHQpIHtyZXR1cm4gZSA9PT0gZnVuY3Rpb24oKSB7dHJ5IHtyZXR1cm4gUy5hY3RpdmVFbGVtZW50fSBjYXRjaChlKSB7fX0oKSA9PSAoImZvY3VzIiA9PT0gdCl9DQoNCgkJZnVuY3Rpb24gU2UoZSwgdCwgbiwgciwgaSwgbykgew0KCQkJdmFyIGEsIHM7DQoJCQlpZigib2JqZWN0IiA9PSB0eXBlb2YgdCkgew0KCQkJCWZvcihzIGluICJzdHJpbmciICE9IHR5cGVvZiBuICYmIChyID0gciB8fCBuLCBuID0gdm9pZCAwKSwgdCkgU2UoZSwgcywgbiwgciwgdFtzXSwgbyk7DQoJCQkJcmV0dXJuIGUNCgkJCX0NCgkJCWlmKG51bGwgPT0gciAmJiBudWxsID09IGkgPyAoaSA9IG4sIHIgPSBuID0gdm9pZCAwKSA6IG51bGwgPT0gaSAmJiAoInN0cmluZyIgPT0gdHlwZW9mIG4gPyAoaSA9IHIsIHIgPSB2b2lkIDApIDogKGkgPSByLCByID0gbiwgbiA9IHZvaWQgMCkpLCAhMSA9PT0gaSkgaSA9IFRlOyBlbHNlIGlmKCFpKSByZXR1cm4gZTsNCgkJCXJldHVybiAxID09PSBvICYmIChhID0gaSwgKGkgPSBmdW5jdGlvbihlKSB7cmV0dXJuIEUoKS5vZmYoZSksIGEuYXBwbHkodGhpcywgYXJndW1lbnRzKX0pLmd1aWQgPSBhLmd1aWQgfHwgKGEuZ3VpZCA9IEUuZ3VpZCsrKSksIGUuZWFjaChmdW5jdGlvbigpIHtFLmV2ZW50LmFkZCh0aGlzLCB0LCBpLCByLCBuKX0pDQoJCX0NCg0KCQlmdW5jdGlvbiBFZShlLCBpLCBvKSB7DQoJCQlvID8gKFkuc2V0KGUsIGksICExKSwgRS5ldmVudC5hZGQoZSwgaSwgew0KCQkJCW5hbWVzcGFjZTogITEsIGhhbmRsZXI6IGZ1bmN0aW9uKGUpIHsNCgkJCQkJdmFyIHQsIG4sIHIgPSBZLmdldCh0aGlzLCBpKTsNCgkJCQkJaWYoMSAmIGUuaXNUcmlnZ2VyICYmIHRoaXNbaV0pIHtpZihyLmxlbmd0aCkgKEUuZXZlbnQuc3BlY2lhbFtpXSB8fCB7fSkuZGVsZWdhdGVUeXBlICYmIGUuc3RvcFByb3BhZ2F0aW9uKCk7IGVsc2UgaWYociA9IHMuY2FsbChhcmd1bWVudHMpLCBZLnNldCh0aGlzLCBpLCByKSwgdCA9IG8odGhpcywgaSksIHRoaXNbaV0oKSwgciAhPT0gKG4gPSBZLmdldCh0aGlzLCBpKSkgfHwgdCA/IFkuc2V0KHRoaXMsIGksICExKSA6IG4gPSB7fSwgciAhPT0gbikgcmV0dXJuIGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCksIGUucHJldmVudERlZmF1bHQoKSwgbiAmJiBuLnZhbHVlfSBlbHNlIHIubGVuZ3RoICYmIChZLnNldCh0aGlzLCBpLCB7dmFsdWU6IEUuZXZlbnQudHJpZ2dlcihFLmV4dGVuZChyWzBdLCBFLkV2ZW50LnByb3RvdHlwZSksIHIuc2xpY2UoMSksIHRoaXMpfSksIGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCkpDQoJCQkJfQ0KCQkJfSkpIDogdm9pZCAwID09PSBZLmdldChlLCBpKSAmJiBFLmV2ZW50LmFkZChlLCBpLCB3ZSkNCgkJfQ0KDQoJCUUuZXZlbnQgPSB7DQoJCQlnbG9iYWw6IHt9LA0KCQkJYWRkOiBmdW5jdGlvbih0LCBlLCBuLCByLCBpKSB7DQoJCQkJdmFyIG8sIGEsIHMsIHUsIGwsIGMsIGYsIHAsIGQsIGgsIGcsIHkgPSBZLmdldCh0KTsNCgkJCQlpZihWKHQpKSB7DQoJCQkJCW4uaGFuZGxlciAmJiAobiA9IChvID0gbikuaGFuZGxlciwgaSA9IG8uc2VsZWN0b3IpLCBpICYmIEUuZmluZC5tYXRjaGVzU2VsZWN0b3IocmUsIGkpLCBuLmd1aWQgfHwgKG4uZ3VpZCA9IEUuZ3VpZCsrKSwgKHUgPSB5LmV2ZW50cykgfHwgKHUgPSB5LmV2ZW50cyA9IE9iamVjdC5jcmVhdGUobnVsbCkpLCAoYSA9IHkuaGFuZGxlKSB8fCAoYSA9IHkuaGFuZGxlID0gZnVuY3Rpb24oZSkge3JldHVybiAidW5kZWZpbmVkIiAhPSB0eXBlb2YgRSAmJiBFLmV2ZW50LnRyaWdnZXJlZCAhPT0gZS50eXBlID8gRS5ldmVudC5kaXNwYXRjaC5hcHBseSh0LCBhcmd1bWVudHMpIDogdm9pZCAwfSksIGwgPSAoZSA9IChlIHx8ICIiKS5tYXRjaChQKSB8fCBbIiJdKS5sZW5ndGg7DQoJCQkJCXdoaWxlKGwtLSkgZCA9IGcgPSAocyA9IGJlLmV4ZWMoZVtsXSkgfHwgW10pWzFdLCBoID0gKHNbMl0gfHwgIiIpLnNwbGl0KCIuIikuc29ydCgpLCBkICYmIChmID0gRS5ldmVudC5zcGVjaWFsW2RdIHx8IHt9LCBkID0gKGkgPyBmLmRlbGVnYXRlVHlwZSA6IGYuYmluZFR5cGUpIHx8IGQsIGYgPSBFLmV2ZW50LnNwZWNpYWxbZF0gfHwge30sIGMgPSBFLmV4dGVuZCh7DQoJCQkJCQl0eXBlOiBkLA0KCQkJCQkJb3JpZ1R5cGU6IGcsDQoJCQkJCQlkYXRhOiByLA0KCQkJCQkJaGFuZGxlcjogbiwNCgkJCQkJCWd1aWQ6IG4uZ3VpZCwNCgkJCQkJCXNlbGVjdG9yOiBpLA0KCQkJCQkJbmVlZHNDb250ZXh0OiBpICYmIEUuZXhwci5tYXRjaC5uZWVkc0NvbnRleHQudGVzdChpKSwNCgkJCQkJCW5hbWVzcGFjZTogaC5qb2luKCIuIikNCgkJCQkJfSwgbyksIChwID0gdVtkXSkgfHwgKChwID0gdVtkXSA9IFtdKS5kZWxlZ2F0ZUNvdW50ID0gMCwgZi5zZXR1cCAmJiAhMSAhPT0gZi5zZXR1cC5jYWxsKHQsIHIsIGgsIGEpIHx8IHQuYWRkRXZlbnRMaXN0ZW5lciAmJiB0LmFkZEV2ZW50TGlzdGVuZXIoZCwgYSkpLCBmLmFkZCAmJiAoZi5hZGQuY2FsbCh0LCBjKSwgYy5oYW5kbGVyLmd1aWQgfHwgKGMuaGFuZGxlci5ndWlkID0gbi5ndWlkKSksIGkgPyBwLnNwbGljZShwLmRlbGVnYXRlQ291bnQrKywgMCwgYykgOiBwLnB1c2goYyksIEUuZXZlbnQuZ2xvYmFsW2RdID0gITApDQoJCQkJfQ0KCQkJfSwNCgkJCXJlbW92ZTogZnVuY3Rpb24oZSwgdCwgbiwgciwgaSkgew0KCQkJCXZhciBvLCBhLCBzLCB1LCBsLCBjLCBmLCBwLCBkLCBoLCBnLCB5ID0gWS5oYXNEYXRhKGUpICYmIFkuZ2V0KGUpOw0KCQkJCWlmKHkgJiYgKHUgPSB5LmV2ZW50cykpIHsNCgkJCQkJbCA9ICh0ID0gKHQgfHwgIiIpLm1hdGNoKFApIHx8IFsiIl0pLmxlbmd0aDsNCgkJCQkJd2hpbGUobC0tKSBpZihkID0gZyA9IChzID0gYmUuZXhlYyh0W2xdKSB8fCBbXSlbMV0sIGggPSAoc1syXSB8fCAiIikuc3BsaXQoIi4iKS5zb3J0KCksIGQpIHsNCgkJCQkJCWYgPSBFLmV2ZW50LnNwZWNpYWxbZF0gfHwge30sIHAgPSB1W2QgPSAociA/IGYuZGVsZWdhdGVUeXBlIDogZi5iaW5kVHlwZSkgfHwgZF0gfHwgW10sIHMgPSBzWzJdICYmIG5ldyBSZWdFeHAoIihefFxcLikiICsgaC5qb2luKCJcXC4oPzouKlxcLnwpIikgKyAiKFxcLnwkKSIpLCBhID0gbyA9IHAubGVuZ3RoOw0KCQkJCQkJd2hpbGUoby0tKSBjID0gcFtvXSwgIWkgJiYgZyAhPT0gYy5vcmlnVHlwZSB8fCBuICYmIG4uZ3VpZCAhPT0gYy5ndWlkIHx8IHMgJiYgIXMudGVzdChjLm5hbWVzcGFjZSkgfHwgciAmJiByICE9PSBjLnNlbGVjdG9yICYmICgiKioiICE9PSByIHx8ICFjLnNlbGVjdG9yKSB8fCAocC5zcGxpY2UobywgMSksIGMuc2VsZWN0b3IgJiYgcC5kZWxlZ2F0ZUNvdW50LS0sIGYucmVtb3ZlICYmIGYucmVtb3ZlLmNhbGwoZSwgYykpOw0KCQkJCQkJYSAmJiAhcC5sZW5ndGggJiYgKGYudGVhcmRvd24gJiYgITEgIT09IGYudGVhcmRvd24uY2FsbChlLCBoLCB5LmhhbmRsZSkgfHwgRS5yZW1vdmVFdmVudChlLCBkLCB5LmhhbmRsZSksIGRlbGV0ZSB1W2RdKQ0KCQkJCQl9IGVsc2UgZm9yKGQgaW4gdSkgRS5ldmVudC5yZW1vdmUoZSwgZCArIHRbbF0sIG4sIHIsICEwKTsNCgkJCQkJRS5pc0VtcHR5T2JqZWN0KHUpICYmIFkucmVtb3ZlKGUsICJoYW5kbGUgZXZlbnRzIikNCgkJCQl9DQoJCQl9LA0KCQkJZGlzcGF0Y2g6IGZ1bmN0aW9uKGUpIHsNCgkJCQl2YXIgdCwgbiwgciwgaSwgbywgYSwgcyA9IG5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoKSwgdSA9IEUuZXZlbnQuZml4KGUpLCBsID0gKFkuZ2V0KHRoaXMsICJldmVudHMiKSB8fCBPYmplY3QuY3JlYXRlKG51bGwpKVt1LnR5cGVdIHx8IFtdLCBjID0gRS5ldmVudC5zcGVjaWFsW3UudHlwZV0gfHwge307DQoJCQkJZm9yKHNbMF0gPSB1LCB0ID0gMTsgdCA8IGFyZ3VtZW50cy5sZW5ndGg7IHQrKykgc1t0XSA9IGFyZ3VtZW50c1t0XTsNCgkJCQlpZih1LmRlbGVnYXRlVGFyZ2V0ID0gdGhpcywgIWMucHJlRGlzcGF0Y2ggfHwgITEgIT09IGMucHJlRGlzcGF0Y2guY2FsbCh0aGlzLCB1KSkgew0KCQkJCQlhID0gRS5ldmVudC5oYW5kbGVycy5jYWxsKHRoaXMsIHUsIGwpLCB0ID0gMDsNCgkJCQkJd2hpbGUoKGkgPSBhW3QrK10pICYmICF1LmlzUHJvcGFnYXRpb25TdG9wcGVkKCkpIHsNCgkJCQkJCXUuY3VycmVudFRhcmdldCA9IGkuZWxlbSwgbiA9IDA7DQoJCQkJCQl3aGlsZSgobyA9IGkuaGFuZGxlcnNbbisrXSkgJiYgIXUuaXNJbW1lZGlhdGVQcm9wYWdhdGlvblN0b3BwZWQoKSkgdS5ybmFtZXNwYWNlICYmICExICE9PSBvLm5hbWVzcGFjZSAmJiAhdS5ybmFtZXNwYWNlLnRlc3Qoby5uYW1lc3BhY2UpIHx8ICh1LmhhbmRsZU9iaiA9IG8sIHUuZGF0YSA9IG8uZGF0YSwgdm9pZCAwICE9PSAociA9ICgoRS5ldmVudC5zcGVjaWFsW28ub3JpZ1R5cGVdIHx8IHt9KS5oYW5kbGUgfHwgby5oYW5kbGVyKS5hcHBseShpLmVsZW0sIHMpKSAmJiAhMSA9PT0gKHUucmVzdWx0ID0gcikgJiYgKHUucHJldmVudERlZmF1bHQoKSwgdS5zdG9wUHJvcGFnYXRpb24oKSkpDQoJCQkJCX0NCgkJCQkJcmV0dXJuIGMucG9zdERpc3BhdGNoICYmIGMucG9zdERpc3BhdGNoLmNhbGwodGhpcywgdSksIHUucmVzdWx0DQoJCQkJfQ0KCQkJfSwNCgkJCWhhbmRsZXJzOiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJdmFyIG4sIHIsIGksIG8sIGEsIHMgPSBbXSwgdSA9IHQuZGVsZWdhdGVDb3VudCwgbCA9IGUudGFyZ2V0Ow0KCQkJCWlmKHUgJiYgbC5ub2RlVHlwZSAmJiAhKCJjbGljayIgPT09IGUudHlwZSAmJiAxIDw9IGUuYnV0dG9uKSkgZm9yKDsgbCAhPT0gdGhpczsgbCA9IGwucGFyZW50Tm9kZSB8fCB0aGlzKSBpZigxID09PSBsLm5vZGVUeXBlICYmICgiY2xpY2siICE9PSBlLnR5cGUgfHwgITAgIT09IGwuZGlzYWJsZWQpKSB7DQoJCQkJCWZvcihvID0gW10sIGEgPSB7fSwgbiA9IDA7IG4gPCB1OyBuKyspIHZvaWQgMCA9PT0gYVtpID0gKHIgPSB0W25dKS5zZWxlY3RvciArICIgIl0gJiYgKGFbaV0gPSByLm5lZWRzQ29udGV4dCA/IC0xIDwgRShpLCB0aGlzKS5pbmRleChsKSA6IEUuZmluZChpLCB0aGlzLCBudWxsLCBbbF0pLmxlbmd0aCksIGFbaV0gJiYgby5wdXNoKHIpOw0KCQkJCQlvLmxlbmd0aCAmJiBzLnB1c2goe2VsZW06IGwsIGhhbmRsZXJzOiBvfSkNCgkJCQl9DQoJCQkJcmV0dXJuIGwgPSB0aGlzLCB1IDwgdC5sZW5ndGggJiYgcy5wdXNoKHtlbGVtOiBsLCBoYW5kbGVyczogdC5zbGljZSh1KX0pLCBzDQoJCQl9LA0KCQkJYWRkUHJvcDogZnVuY3Rpb24odCwgZSkgew0KCQkJCU9iamVjdC5kZWZpbmVQcm9wZXJ0eShFLkV2ZW50LnByb3RvdHlwZSwgdCwgew0KCQkJCQllbnVtZXJhYmxlOiAhMCwNCgkJCQkJY29uZmlndXJhYmxlOiAhMCwNCgkJCQkJZ2V0OiBtKGUpID8gZnVuY3Rpb24oKSB7aWYodGhpcy5vcmlnaW5hbEV2ZW50KSByZXR1cm4gZSh0aGlzLm9yaWdpbmFsRXZlbnQpfSA6IGZ1bmN0aW9uKCkge2lmKHRoaXMub3JpZ2luYWxFdmVudCkgcmV0dXJuIHRoaXMub3JpZ2luYWxFdmVudFt0XX0sDQoJCQkJCXNldDogZnVuY3Rpb24oZSkge09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCB0LCB7ZW51bWVyYWJsZTogITAsIGNvbmZpZ3VyYWJsZTogITAsIHdyaXRhYmxlOiAhMCwgdmFsdWU6IGV9KX0NCgkJCQl9KQ0KCQkJfSwNCgkJCWZpeDogZnVuY3Rpb24oZSkge3JldHVybiBlW0UuZXhwYW5kb10gPyBlIDogbmV3IEUuRXZlbnQoZSl9LA0KCQkJc3BlY2lhbDogew0KCQkJCWxvYWQ6IHtub0J1YmJsZTogITB9LCBjbGljazogew0KCQkJCQlzZXR1cDogZnVuY3Rpb24oZSkgew0KCQkJCQkJdmFyIHQgPSB0aGlzIHx8IGU7DQoJCQkJCQlyZXR1cm4gcGUudGVzdCh0LnR5cGUpICYmIHQuY2xpY2sgJiYgQSh0LCAiaW5wdXQiKSAmJiBFZSh0LCAiY2xpY2siLCB3ZSksICExDQoJCQkJCX0sIHRyaWdnZXI6IGZ1bmN0aW9uKGUpIHsNCgkJCQkJCXZhciB0ID0gdGhpcyB8fCBlOw0KCQkJCQkJcmV0dXJuIHBlLnRlc3QodC50eXBlKSAmJiB0LmNsaWNrICYmIEEodCwgImlucHV0IikgJiYgRWUodCwgImNsaWNrIiksICEwDQoJCQkJCX0sIF9kZWZhdWx0OiBmdW5jdGlvbihlKSB7DQoJCQkJCQl2YXIgdCA9IGUudGFyZ2V0Ow0KCQkJCQkJcmV0dXJuIHBlLnRlc3QodC50eXBlKSAmJiB0LmNsaWNrICYmIEEodCwgImlucHV0IikgJiYgWS5nZXQodCwgImNsaWNrIikgfHwgQSh0LCAiYSIpDQoJCQkJCX0NCgkJCQl9LCBiZWZvcmV1bmxvYWQ6IHtwb3N0RGlzcGF0Y2g6IGZ1bmN0aW9uKGUpIHt2b2lkIDAgIT09IGUucmVzdWx0ICYmIGUub3JpZ2luYWxFdmVudCAmJiAoZS5vcmlnaW5hbEV2ZW50LnJldHVyblZhbHVlID0gZS5yZXN1bHQpfX0NCgkJCX0NCgkJfSwgRS5yZW1vdmVFdmVudCA9IGZ1bmN0aW9uKGUsIHQsIG4pIHtlLnJlbW92ZUV2ZW50TGlzdGVuZXIgJiYgZS5yZW1vdmVFdmVudExpc3RlbmVyKHQsIG4pfSwgRS5FdmVudCA9IGZ1bmN0aW9uKGUsIHQpIHsNCgkJCWlmKCEodGhpcyBpbnN0YW5jZW9mIEUuRXZlbnQpKSByZXR1cm4gbmV3IEUuRXZlbnQoZSwgdCk7DQoJCQllICYmIGUudHlwZSA/ICh0aGlzLm9yaWdpbmFsRXZlbnQgPSBlLCB0aGlzLnR5cGUgPSBlLnR5cGUsIHRoaXMuaXNEZWZhdWx0UHJldmVudGVkID0gZS5kZWZhdWx0UHJldmVudGVkIHx8IHZvaWQgMCA9PT0gZS5kZWZhdWx0UHJldmVudGVkICYmICExID09PSBlLnJldHVyblZhbHVlID8gd2UgOiBUZSwgdGhpcy50YXJnZXQgPSBlLnRhcmdldCAmJiAzID09PSBlLnRhcmdldC5ub2RlVHlwZSA/IGUudGFyZ2V0LnBhcmVudE5vZGUgOiBlLnRhcmdldCwgdGhpcy5jdXJyZW50VGFyZ2V0ID0gZS5jdXJyZW50VGFyZ2V0LCB0aGlzLnJlbGF0ZWRUYXJnZXQgPSBlLnJlbGF0ZWRUYXJnZXQpIDogdGhpcy50eXBlID0gZSwgdCAmJiBFLmV4dGVuZCh0aGlzLCB0KSwgdGhpcy50aW1lU3RhbXAgPSBlICYmIGUudGltZVN0YW1wIHx8IERhdGUubm93KCksIHRoaXNbRS5leHBhbmRvXSA9ICEwDQoJCX0sIEUuRXZlbnQucHJvdG90eXBlID0gew0KCQkJY29uc3RydWN0b3I6IEUuRXZlbnQsIGlzRGVmYXVsdFByZXZlbnRlZDogVGUsIGlzUHJvcGFnYXRpb25TdG9wcGVkOiBUZSwgaXNJbW1lZGlhdGVQcm9wYWdhdGlvblN0b3BwZWQ6IFRlLCBpc1NpbXVsYXRlZDogITEsIHByZXZlbnREZWZhdWx0OiBmdW5jdGlvbigpIHsNCgkJCQl2YXIgZSA9IHRoaXMub3JpZ2luYWxFdmVudDsNCgkJCQl0aGlzLmlzRGVmYXVsdFByZXZlbnRlZCA9IHdlLCBlICYmICF0aGlzLmlzU2ltdWxhdGVkICYmIGUucHJldmVudERlZmF1bHQoKQ0KCQkJfSwgc3RvcFByb3BhZ2F0aW9uOiBmdW5jdGlvbigpIHsNCgkJCQl2YXIgZSA9IHRoaXMub3JpZ2luYWxFdmVudDsNCgkJCQl0aGlzLmlzUHJvcGFnYXRpb25TdG9wcGVkID0gd2UsIGUgJiYgIXRoaXMuaXNTaW11bGF0ZWQgJiYgZS5zdG9wUHJvcGFnYXRpb24oKQ0KCQkJfSwgc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uOiBmdW5jdGlvbigpIHsNCgkJCQl2YXIgZSA9IHRoaXMub3JpZ2luYWxFdmVudDsNCgkJCQl0aGlzLmlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkID0gd2UsIGUgJiYgIXRoaXMuaXNTaW11bGF0ZWQgJiYgZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKSwgdGhpcy5zdG9wUHJvcGFnYXRpb24oKQ0KCQkJfQ0KCQl9LCBFLmVhY2goew0KCQkJYWx0S2V5OiAhMCwNCgkJCWJ1YmJsZXM6ICEwLA0KCQkJY2FuY2VsYWJsZTogITAsDQoJCQljaGFuZ2VkVG91Y2hlczogITAsDQoJCQljdHJsS2V5OiAhMCwNCgkJCWRldGFpbDogITAsDQoJCQlldmVudFBoYXNlOiAhMCwNCgkJCW1ldGFLZXk6ICEwLA0KCQkJcGFnZVg6ICEwLA0KCQkJcGFnZVk6ICEwLA0KCQkJc2hpZnRLZXk6ICEwLA0KCQkJdmlldzogITAsDQoJCQkiY2hhciI6ICEwLA0KCQkJY29kZTogITAsDQoJCQljaGFyQ29kZTogITAsDQoJCQlrZXk6ICEwLA0KCQkJa2V5Q29kZTogITAsDQoJCQlidXR0b246ICEwLA0KCQkJYnV0dG9uczogITAsDQoJCQljbGllbnRYOiAhMCwNCgkJCWNsaWVudFk6ICEwLA0KCQkJb2Zmc2V0WDogITAsDQoJCQlvZmZzZXRZOiAhMCwNCgkJCXBvaW50ZXJJZDogITAsDQoJCQlwb2ludGVyVHlwZTogITAsDQoJCQlzY3JlZW5YOiAhMCwNCgkJCXNjcmVlblk6ICEwLA0KCQkJdGFyZ2V0VG91Y2hlczogITAsDQoJCQl0b0VsZW1lbnQ6ICEwLA0KCQkJdG91Y2hlczogITAsDQoJCQl3aGljaDogITANCgkJfSwgRS5ldmVudC5hZGRQcm9wKSwgRS5lYWNoKHtmb2N1czogImZvY3VzaW4iLCBibHVyOiAiZm9jdXNvdXQifSwgZnVuY3Rpb24odCwgZSkgew0KCQkJRS5ldmVudC5zcGVjaWFsW3RdID0gew0KCQkJCXNldHVwOiBmdW5jdGlvbigpIHtyZXR1cm4gRWUodGhpcywgdCwgQ2UpLCAhMX0sDQoJCQkJdHJpZ2dlcjogZnVuY3Rpb24oKSB7cmV0dXJuIEVlKHRoaXMsIHQpLCAhMH0sDQoJCQkJX2RlZmF1bHQ6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gWS5nZXQoZS50YXJnZXQsIHQpfSwNCgkJCQlkZWxlZ2F0ZVR5cGU6IGUNCgkJCX0NCgkJfSksIEUuZWFjaCh7bW91c2VlbnRlcjogIm1vdXNlb3ZlciIsIG1vdXNlbGVhdmU6ICJtb3VzZW91dCIsIHBvaW50ZXJlbnRlcjogInBvaW50ZXJvdmVyIiwgcG9pbnRlcmxlYXZlOiAicG9pbnRlcm91dCJ9LCBmdW5jdGlvbihlLCBpKSB7DQoJCQlFLmV2ZW50LnNwZWNpYWxbZV0gPSB7DQoJCQkJZGVsZWdhdGVUeXBlOiBpLCBiaW5kVHlwZTogaSwgaGFuZGxlOiBmdW5jdGlvbihlKSB7DQoJCQkJCXZhciB0LCBuID0gZS5yZWxhdGVkVGFyZ2V0LCByID0gZS5oYW5kbGVPYmo7DQoJCQkJCXJldHVybiBuICYmIChuID09PSB0aGlzIHx8IEUuY29udGFpbnModGhpcywgbikpIHx8IChlLnR5cGUgPSByLm9yaWdUeXBlLCB0ID0gci5oYW5kbGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyksIGUudHlwZSA9IGkpLCB0DQoJCQkJfQ0KCQkJfQ0KCQl9KSwgRS5mbi5leHRlbmQoew0KCQkJb246IGZ1bmN0aW9uKGUsIHQsIG4sIHIpIHtyZXR1cm4gU2UodGhpcywgZSwgdCwgbiwgcil9LCBvbmU6IGZ1bmN0aW9uKGUsIHQsIG4sIHIpIHtyZXR1cm4gU2UodGhpcywgZSwgdCwgbiwgciwgMSl9LCBvZmY6IGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQl2YXIgciwgaTsNCgkJCQlpZihlICYmIGUucHJldmVudERlZmF1bHQgJiYgZS5oYW5kbGVPYmopIHJldHVybiByID0gZS5oYW5kbGVPYmosIEUoZS5kZWxlZ2F0ZVRhcmdldCkub2ZmKHIubmFtZXNwYWNlID8gci5vcmlnVHlwZSArICIuIiArIHIubmFtZXNwYWNlIDogci5vcmlnVHlwZSwgci5zZWxlY3Rvciwgci5oYW5kbGVyKSwgdGhpczsNCgkJCQlpZigib2JqZWN0IiA9PSB0eXBlb2YgZSkgew0KCQkJCQlmb3IoaSBpbiBlKSB0aGlzLm9mZihpLCB0LCBlW2ldKTsNCgkJCQkJcmV0dXJuIHRoaXMNCgkJCQl9DQoJCQkJcmV0dXJuICExICE9PSB0ICYmICJmdW5jdGlvbiIgIT0gdHlwZW9mIHQgfHwgKG4gPSB0LCB0ID0gdm9pZCAwKSwgITEgPT09IG4gJiYgKG4gPSBUZSksIHRoaXMuZWFjaChmdW5jdGlvbigpIHtFLmV2ZW50LnJlbW92ZSh0aGlzLCBlLCBuLCB0KX0pDQoJCQl9DQoJCX0pOw0KCQl2YXIga2UgPSAvPHNjcmlwdHw8c3R5bGV8PGxpbmsvaSwgQWUgPSAvY2hlY2tlZFxzKig/OltePV18PVxzKi5jaGVja2VkLikvaSwgTmUgPSAvXlxzKjwhXFtDREFUQVxbfFxdXF0+XHMqJC9nOw0KDQoJCWZ1bmN0aW9uIGplKGUsIHQpIHtyZXR1cm4gQShlLCAidGFibGUiKSAmJiBBKDExICE9PSB0Lm5vZGVUeXBlID8gdCA6IHQuZmlyc3RDaGlsZCwgInRyIikgJiYgRShlKS5jaGlsZHJlbigidGJvZHkiKVswXSB8fCBlfQ0KDQoJCWZ1bmN0aW9uIERlKGUpIHtyZXR1cm4gZS50eXBlID0gKG51bGwgIT09IGUuZ2V0QXR0cmlidXRlKCJ0eXBlIikpICsgIi8iICsgZS50eXBlLCBlfQ0KDQoJCWZ1bmN0aW9uIHFlKGUpIHtyZXR1cm4gInRydWUvIiA9PT0gKGUudHlwZSB8fCAiIikuc2xpY2UoMCwgNSkgPyBlLnR5cGUgPSBlLnR5cGUuc2xpY2UoNSkgOiBlLnJlbW92ZUF0dHJpYnV0ZSgidHlwZSIpLCBlfQ0KDQoJCWZ1bmN0aW9uIExlKGUsIHQpIHsNCgkJCXZhciBuLCByLCBpLCBvLCBhLCBzOw0KCQkJaWYoMSA9PT0gdC5ub2RlVHlwZSkgew0KCQkJCWlmKFkuaGFzRGF0YShlKSAmJiAocyA9IFkuZ2V0KGUpLmV2ZW50cykpIGZvcihpIGluIFkucmVtb3ZlKHQsICJoYW5kbGUgZXZlbnRzIiksIHMpIGZvcihuID0gMCwgciA9IHNbaV0ubGVuZ3RoOyBuIDwgcjsgbisrKSBFLmV2ZW50LmFkZCh0LCBpLCBzW2ldW25dKTsNCgkJCQlRLmhhc0RhdGEoZSkgJiYgKG8gPSBRLmFjY2VzcyhlKSwgYSA9IEUuZXh0ZW5kKHt9LCBvKSwgUS5zZXQodCwgYSkpDQoJCQl9DQoJCX0NCg0KCQlmdW5jdGlvbiBIZShuLCByLCBpLCBvKSB7DQoJCQlyID0gZyhyKTsNCgkJCXZhciBlLCB0LCBhLCBzLCB1LCBsLCBjID0gMCwgZiA9IG4ubGVuZ3RoLCBwID0gZiAtIDEsIGQgPSByWzBdLCBoID0gbShkKTsNCgkJCWlmKGggfHwgMSA8IGYgJiYgInN0cmluZyIgPT0gdHlwZW9mIGQgJiYgIXYuY2hlY2tDbG9uZSAmJiBBZS50ZXN0KGQpKSByZXR1cm4gbi5lYWNoKGZ1bmN0aW9uKGUpIHsNCgkJCQl2YXIgdCA9IG4uZXEoZSk7DQoJCQkJaCAmJiAoclswXSA9IGQuY2FsbCh0aGlzLCBlLCB0Lmh0bWwoKSkpLCBIZSh0LCByLCBpLCBvKQ0KCQkJfSk7DQoJCQlpZihmICYmICh0ID0gKGUgPSB4ZShyLCBuWzBdLm93bmVyRG9jdW1lbnQsICExLCBuLCBvKSkuZmlyc3RDaGlsZCwgMSA9PT0gZS5jaGlsZE5vZGVzLmxlbmd0aCAmJiAoZSA9IHQpLCB0IHx8IG8pKSB7DQoJCQkJZm9yKHMgPSAoYSA9IEUubWFwKHllKGUsICJzY3JpcHQiKSwgRGUpKS5sZW5ndGg7IGMgPCBmOyBjKyspIHUgPSBlLCBjICE9PSBwICYmICh1ID0gRS5jbG9uZSh1LCAhMCwgITApLCBzICYmIEUubWVyZ2UoYSwgeWUodSwgInNjcmlwdCIpKSksIGkuY2FsbChuW2NdLCB1LCBjKTsNCgkJCQlpZihzKSBmb3IobCA9IGFbYS5sZW5ndGggLSAxXS5vd25lckRvY3VtZW50LCBFLm1hcChhLCBxZSksIGMgPSAwOyBjIDwgczsgYysrKSB1ID0gYVtjXSwgaGUudGVzdCh1LnR5cGUgfHwgIiIpICYmICFZLmFjY2Vzcyh1LCAiZ2xvYmFsRXZhbCIpICYmIEUuY29udGFpbnMobCwgdSkgJiYgKHUuc3JjICYmICJtb2R1bGUiICE9PSAodS50eXBlIHx8ICIiKS50b0xvd2VyQ2FzZSgpID8gRS5fZXZhbFVybCAmJiAhdS5ub01vZHVsZSAmJiBFLl9ldmFsVXJsKHUuc3JjLCB7bm9uY2U6IHUubm9uY2UgfHwgdS5nZXRBdHRyaWJ1dGUoIm5vbmNlIil9LCBsKSA6IGIodS50ZXh0Q29udGVudC5yZXBsYWNlKE5lLCAiIiksIHUsIGwpKQ0KCQkJfQ0KCQkJcmV0dXJuIG4NCgkJfQ0KDQoJCWZ1bmN0aW9uIE9lKGUsIHQsIG4pIHsNCgkJCWZvcih2YXIgciwgaSA9IHQgPyBFLmZpbHRlcih0LCBlKSA6IGUsIG8gPSAwOyBudWxsICE9IChyID0gaVtvXSk7IG8rKykgbiB8fCAxICE9PSByLm5vZGVUeXBlIHx8IEUuY2xlYW5EYXRhKHllKHIpKSwgci5wYXJlbnROb2RlICYmIChuICYmIGllKHIpICYmIHZlKHllKHIsICJzY3JpcHQiKSksIHIucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChyKSk7DQoJCQlyZXR1cm4gZQ0KCQl9DQoNCgkJRS5leHRlbmQoew0KCQkJaHRtbFByZWZpbHRlcjogZnVuY3Rpb24oZSkge3JldHVybiBlfSwgY2xvbmU6IGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQl2YXIgciwgaSwgbywgYSwgcywgdSwgbCwgYyA9IGUuY2xvbmVOb2RlKCEwKSwgZiA9IGllKGUpOw0KCQkJCWlmKCEodi5ub0Nsb25lQ2hlY2tlZCB8fCAxICE9PSBlLm5vZGVUeXBlICYmIDExICE9PSBlLm5vZGVUeXBlIHx8IEUuaXNYTUxEb2MoZSkpKSBmb3IoYSA9IHllKGMpLCByID0gMCwgaSA9IChvID0geWUoZSkpLmxlbmd0aDsgciA8IGk7IHIrKykgcyA9IG9bcl0sIHUgPSBhW3JdLCB2b2lkIDAsICJpbnB1dCIgPT09IChsID0gdS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpKSAmJiBwZS50ZXN0KHMudHlwZSkgPyB1LmNoZWNrZWQgPSBzLmNoZWNrZWQgOiAiaW5wdXQiICE9PSBsICYmICJ0ZXh0YXJlYSIgIT09IGwgfHwgKHUuZGVmYXVsdFZhbHVlID0gcy5kZWZhdWx0VmFsdWUpOw0KCQkJCWlmKHQpIGlmKG4pIGZvcihvID0gbyB8fCB5ZShlKSwgYSA9IGEgfHwgeWUoYyksIHIgPSAwLCBpID0gby5sZW5ndGg7IHIgPCBpOyByKyspIExlKG9bcl0sIGFbcl0pOyBlbHNlIExlKGUsIGMpOw0KCQkJCXJldHVybiAwIDwgKGEgPSB5ZShjLCAic2NyaXB0IikpLmxlbmd0aCAmJiB2ZShhLCAhZiAmJiB5ZShlLCAic2NyaXB0IikpLCBjDQoJCQl9LCBjbGVhbkRhdGE6IGZ1bmN0aW9uKGUpIHsNCgkJCQlmb3IodmFyIHQsIG4sIHIsIGkgPSBFLmV2ZW50LnNwZWNpYWwsIG8gPSAwOyB2b2lkIDAgIT09IChuID0gZVtvXSk7IG8rKykgaWYoVihuKSkgew0KCQkJCQlpZih0ID0gbltZLmV4cGFuZG9dKSB7DQoJCQkJCQlpZih0LmV2ZW50cykgZm9yKHIgaW4gdC5ldmVudHMpIGlbcl0gPyBFLmV2ZW50LnJlbW92ZShuLCByKSA6IEUucmVtb3ZlRXZlbnQobiwgciwgdC5oYW5kbGUpOw0KCQkJCQkJbltZLmV4cGFuZG9dID0gdm9pZCAwDQoJCQkJCX0NCgkJCQkJbltRLmV4cGFuZG9dICYmIChuW1EuZXhwYW5kb10gPSB2b2lkIDApDQoJCQkJfQ0KCQkJfQ0KCQl9KSwgRS5mbi5leHRlbmQoew0KCQkJZGV0YWNoOiBmdW5jdGlvbihlKSB7cmV0dXJuIE9lKHRoaXMsIGUsICEwKX0sDQoJCQlyZW1vdmU6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gT2UodGhpcywgZSl9LA0KCQkJdGV4dDogZnVuY3Rpb24oZSkge3JldHVybiBCKHRoaXMsIGZ1bmN0aW9uKGUpIHtyZXR1cm4gdm9pZCAwID09PSBlID8gRS50ZXh0KHRoaXMpIDogdGhpcy5lbXB0eSgpLmVhY2goZnVuY3Rpb24oKSB7MSAhPT0gdGhpcy5ub2RlVHlwZSAmJiAxMSAhPT0gdGhpcy5ub2RlVHlwZSAmJiA5ICE9PSB0aGlzLm5vZGVUeXBlIHx8ICh0aGlzLnRleHRDb250ZW50ID0gZSl9KX0sIG51bGwsIGUsIGFyZ3VtZW50cy5sZW5ndGgpfSwNCgkJCWFwcGVuZDogZnVuY3Rpb24oKSB7cmV0dXJuIEhlKHRoaXMsIGFyZ3VtZW50cywgZnVuY3Rpb24oZSkgezEgIT09IHRoaXMubm9kZVR5cGUgJiYgMTEgIT09IHRoaXMubm9kZVR5cGUgJiYgOSAhPT0gdGhpcy5ub2RlVHlwZSB8fCBqZSh0aGlzLCBlKS5hcHBlbmRDaGlsZChlKX0pfSwNCgkJCXByZXBlbmQ6IGZ1bmN0aW9uKCkgew0KCQkJCXJldHVybiBIZSh0aGlzLCBhcmd1bWVudHMsIGZ1bmN0aW9uKGUpIHsNCgkJCQkJaWYoMSA9PT0gdGhpcy5ub2RlVHlwZSB8fCAxMSA9PT0gdGhpcy5ub2RlVHlwZSB8fCA5ID09PSB0aGlzLm5vZGVUeXBlKSB7DQoJCQkJCQl2YXIgdCA9IGplKHRoaXMsIGUpOw0KCQkJCQkJdC5pbnNlcnRCZWZvcmUoZSwgdC5maXJzdENoaWxkKQ0KCQkJCQl9DQoJCQkJfSkNCgkJCX0sDQoJCQliZWZvcmU6IGZ1bmN0aW9uKCkge3JldHVybiBIZSh0aGlzLCBhcmd1bWVudHMsIGZ1bmN0aW9uKGUpIHt0aGlzLnBhcmVudE5vZGUgJiYgdGhpcy5wYXJlbnROb2RlLmluc2VydEJlZm9yZShlLCB0aGlzKX0pfSwNCgkJCWFmdGVyOiBmdW5jdGlvbigpIHtyZXR1cm4gSGUodGhpcywgYXJndW1lbnRzLCBmdW5jdGlvbihlKSB7dGhpcy5wYXJlbnROb2RlICYmIHRoaXMucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoZSwgdGhpcy5uZXh0U2libGluZyl9KX0sDQoJCQllbXB0eTogZnVuY3Rpb24oKSB7DQoJCQkJZm9yKHZhciBlLCB0ID0gMDsgbnVsbCAhPSAoZSA9IHRoaXNbdF0pOyB0KyspIDEgPT09IGUubm9kZVR5cGUgJiYgKEUuY2xlYW5EYXRhKHllKGUsICExKSksIGUudGV4dENvbnRlbnQgPSAiIik7DQoJCQkJcmV0dXJuIHRoaXMNCgkJCX0sDQoJCQljbG9uZTogZnVuY3Rpb24oZSwgdCkge3JldHVybiBlID0gbnVsbCAhPSBlICYmIGUsIHQgPSBudWxsID09IHQgPyBlIDogdCwgdGhpcy5tYXAoZnVuY3Rpb24oKSB7cmV0dXJuIEUuY2xvbmUodGhpcywgZSwgdCl9KX0sDQoJCQlodG1sOiBmdW5jdGlvbihlKSB7DQoJCQkJcmV0dXJuIEIodGhpcywgZnVuY3Rpb24oZSkgew0KCQkJCQl2YXIgdCA9IHRoaXNbMF0gfHwge30sIG4gPSAwLCByID0gdGhpcy5sZW5ndGg7DQoJCQkJCWlmKHZvaWQgMCA9PT0gZSAmJiAxID09PSB0Lm5vZGVUeXBlKSByZXR1cm4gdC5pbm5lckhUTUw7DQoJCQkJCWlmKCJzdHJpbmciID09IHR5cGVvZiBlICYmICFrZS50ZXN0KGUpICYmICFnZVsoZGUuZXhlYyhlKSB8fCBbIiIsICIiXSlbMV0udG9Mb3dlckNhc2UoKV0pIHsNCgkJCQkJCWUgPSBFLmh0bWxQcmVmaWx0ZXIoZSk7DQoJCQkJCQl0cnkgew0KCQkJCQkJCWZvcig7IG4gPCByOyBuKyspIDEgPT09ICh0ID0gdGhpc1tuXSB8fCB7fSkubm9kZVR5cGUgJiYgKEUuY2xlYW5EYXRhKHllKHQsICExKSksIHQuaW5uZXJIVE1MID0gZSk7DQoJCQkJCQkJdCA9IDANCgkJCQkJCX0gY2F0Y2goZSkge30NCgkJCQkJfQ0KCQkJCQl0ICYmIHRoaXMuZW1wdHkoKS5hcHBlbmQoZSkNCgkJCQl9LCBudWxsLCBlLCBhcmd1bWVudHMubGVuZ3RoKQ0KCQkJfSwNCgkJCXJlcGxhY2VXaXRoOiBmdW5jdGlvbigpIHsNCgkJCQl2YXIgbiA9IFtdOw0KCQkJCXJldHVybiBIZSh0aGlzLCBhcmd1bWVudHMsIGZ1bmN0aW9uKGUpIHsNCgkJCQkJdmFyIHQgPSB0aGlzLnBhcmVudE5vZGU7DQoJCQkJCUUuaW5BcnJheSh0aGlzLCBuKSA8IDAgJiYgKEUuY2xlYW5EYXRhKHllKHRoaXMpKSwgdCAmJiB0LnJlcGxhY2VDaGlsZChlLCB0aGlzKSkNCgkJCQl9LCBuKQ0KCQkJfQ0KCQl9KSwgRS5lYWNoKHsNCgkJCWFwcGVuZFRvOiAiYXBwZW5kIiwNCgkJCXByZXBlbmRUbzogInByZXBlbmQiLA0KCQkJaW5zZXJ0QmVmb3JlOiAiYmVmb3JlIiwNCgkJCWluc2VydEFmdGVyOiAiYWZ0ZXIiLA0KCQkJcmVwbGFjZUFsbDogInJlcGxhY2VXaXRoIg0KCQl9LCBmdW5jdGlvbihlLCBhKSB7DQoJCQlFLmZuW2VdID0gZnVuY3Rpb24oZSkgew0KCQkJCWZvcih2YXIgdCwgbiA9IFtdLCByID0gRShlKSwgaSA9IHIubGVuZ3RoIC0gMSwgbyA9IDA7IG8gPD0gaTsgbysrKSB0ID0gbyA9PT0gaSA/IHRoaXMgOiB0aGlzLmNsb25lKCEwKSwgRShyW29dKVthXSh0KSwgdS5hcHBseShuLCB0LmdldCgpKTsNCgkJCQlyZXR1cm4gdGhpcy5wdXNoU3RhY2sobikNCgkJCX0NCgkJfSk7DQoJCXZhciBQZSA9IG5ldyBSZWdFeHAoIl4oIiArIGVlICsgIikoPyFweClbYS16JV0rJCIsICJpIiksIFJlID0gL14tLS8sIE1lID0gZnVuY3Rpb24oZSkgew0KCQkJdmFyIHQgPSBlLm93bmVyRG9jdW1lbnQuZGVmYXVsdFZpZXc7DQoJCQlyZXR1cm4gdCAmJiB0Lm9wZW5lciB8fCAodCA9IEMpLCB0LmdldENvbXB1dGVkU3R5bGUoZSkNCgkJfSwgSWUgID0gZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJdmFyIHIsIGksIG8gPSB7fTsNCgkJCWZvcihpIGluIHQpIG9baV0gPSBlLnN0eWxlW2ldLCBlLnN0eWxlW2ldID0gdFtpXTsNCgkJCWZvcihpIGluIHIgPSBuLmNhbGwoZSksIHQpIGUuc3R5bGVbaV0gPSBvW2ldOw0KCQkJcmV0dXJuIHINCgkJfSwgV2UgID0gbmV3IFJlZ0V4cChuZS5qb2luKCJ8IiksICJpIiksIEZlID0gIltcXHgyMFxcdFxcclxcblxcZl0iLCAkZSA9IG5ldyBSZWdFeHAoIl4iICsgRmUgKyAiK3woKD86XnxbXlxcXFxdKSg/OlxcXFwuKSopIiArIEZlICsgIiskIiwgImciKTsNCg0KCQlmdW5jdGlvbiBCZShlLCB0LCBuKSB7DQoJCQl2YXIgciwgaSwgbywgYSwgcyA9IFJlLnRlc3QodCksIHUgPSBlLnN0eWxlOw0KCQkJcmV0dXJuIChuID0gbiB8fCBNZShlKSkgJiYgKGEgPSBuLmdldFByb3BlcnR5VmFsdWUodCkgfHwgblt0XSwgcyAmJiBhICYmIChhID0gYS5yZXBsYWNlKCRlLCAiJDEiKSB8fCB2b2lkIDApLCAiIiAhPT0gYSB8fCBpZShlKSB8fCAoYSA9IEUuc3R5bGUoZSwgdCkpLCAhdi5waXhlbEJveFN0eWxlcygpICYmIFBlLnRlc3QoYSkgJiYgV2UudGVzdCh0KSAmJiAociA9IHUud2lkdGgsIGkgPSB1Lm1pbldpZHRoLCBvID0gdS5tYXhXaWR0aCwgdS5taW5XaWR0aCA9IHUubWF4V2lkdGggPSB1LndpZHRoID0gYSwgYSA9IG4ud2lkdGgsIHUud2lkdGggPSByLCB1Lm1pbldpZHRoID0gaSwgdS5tYXhXaWR0aCA9IG8pKSwgdm9pZCAwICE9PSBhID8gYSArICIiIDogYQ0KCQl9DQoNCgkJZnVuY3Rpb24gX2UoZSwgdCkgew0KCQkJcmV0dXJuIHsNCgkJCQlnZXQ6IGZ1bmN0aW9uKCkgew0KCQkJCQlpZighZSgpKSByZXR1cm4gKHRoaXMuZ2V0ID0gdCkuYXBwbHkodGhpcywgYXJndW1lbnRzKTsNCgkJCQkJZGVsZXRlIHRoaXMuZ2V0DQoJCQkJfQ0KCQkJfQ0KCQl9DQoNCgkJIWZ1bmN0aW9uKCkgew0KCQkJZnVuY3Rpb24gZSgpIHsNCgkJCQlpZihsKSB7DQoJCQkJCXUuc3R5bGUuY3NzVGV4dCA9ICJwb3NpdGlvbjphYnNvbHV0ZTtsZWZ0Oi0xMTExMXB4O3dpZHRoOjYwcHg7bWFyZ2luLXRvcDoxcHg7cGFkZGluZzowO2JvcmRlcjowIiwgbC5zdHlsZS5jc3NUZXh0ID0gInBvc2l0aW9uOnJlbGF0aXZlO2Rpc3BsYXk6YmxvY2s7Ym94LXNpemluZzpib3JkZXItYm94O292ZXJmbG93OnNjcm9sbDttYXJnaW46YXV0bztib3JkZXI6MXB4O3BhZGRpbmc6MXB4O3dpZHRoOjYwJTt0b3A6MSUiLCByZS5hcHBlbmRDaGlsZCh1KS5hcHBlbmRDaGlsZChsKTsNCgkJCQkJdmFyIGUgPSBDLmdldENvbXB1dGVkU3R5bGUobCk7DQoJCQkJCW4gPSAiMSUiICE9PSBlLnRvcCwgcyA9IDEyID09PSB0KGUubWFyZ2luTGVmdCksIGwuc3R5bGUucmlnaHQgPSAiNjAlIiwgbyA9IDM2ID09PSB0KGUucmlnaHQpLCByID0gMzYgPT09IHQoZS53aWR0aCksIGwuc3R5bGUucG9zaXRpb24gPSAiYWJzb2x1dGUiLCBpID0gMTIgPT09IHQobC5vZmZzZXRXaWR0aCAvIDMpLCByZS5yZW1vdmVDaGlsZCh1KSwgbCA9IG51bGwNCgkJCQl9DQoJCQl9DQoNCgkJCWZ1bmN0aW9uIHQoZSkge3JldHVybiBNYXRoLnJvdW5kKHBhcnNlRmxvYXQoZSkpfQ0KDQoJCQl2YXIgbiwgciwgaSwgbywgYSwgcywgdSA9IFMuY3JlYXRlRWxlbWVudCgiZGl2IiksIGwgPSBTLmNyZWF0ZUVsZW1lbnQoImRpdiIpOw0KCQkJbC5zdHlsZSAmJiAobC5zdHlsZS5iYWNrZ3JvdW5kQ2xpcCA9ICJjb250ZW50LWJveCIsIGwuY2xvbmVOb2RlKCEwKS5zdHlsZS5iYWNrZ3JvdW5kQ2xpcCA9ICIiLCB2LmNsZWFyQ2xvbmVTdHlsZSA9ICJjb250ZW50LWJveCIgPT09IGwuc3R5bGUuYmFja2dyb3VuZENsaXAsIEUuZXh0ZW5kKHYsIHsNCgkJCQlib3hTaXppbmdSZWxpYWJsZTogZnVuY3Rpb24oKSB7cmV0dXJuIGUoKSwgcn0sDQoJCQkJcGl4ZWxCb3hTdHlsZXM6IGZ1bmN0aW9uKCkge3JldHVybiBlKCksIG99LA0KCQkJCXBpeGVsUG9zaXRpb246IGZ1bmN0aW9uKCkge3JldHVybiBlKCksIG59LA0KCQkJCXJlbGlhYmxlTWFyZ2luTGVmdDogZnVuY3Rpb24oKSB7cmV0dXJuIGUoKSwgc30sDQoJCQkJc2Nyb2xsYm94U2l6ZTogZnVuY3Rpb24oKSB7cmV0dXJuIGUoKSwgaX0sDQoJCQkJcmVsaWFibGVUckRpbWVuc2lvbnM6IGZ1bmN0aW9uKCkgew0KCQkJCQl2YXIgZSwgdCwgbiwgcjsNCgkJCQkJcmV0dXJuIG51bGwgPT0gYSAmJiAoZSA9IFMuY3JlYXRlRWxlbWVudCgidGFibGUiKSwgdCA9IFMuY3JlYXRlRWxlbWVudCgidHIiKSwgbiA9IFMuY3JlYXRlRWxlbWVudCgiZGl2IiksIGUuc3R5bGUuY3NzVGV4dCA9ICJwb3NpdGlvbjphYnNvbHV0ZTtsZWZ0Oi0xMTExMXB4O2JvcmRlci1jb2xsYXBzZTpzZXBhcmF0ZSIsIHQuc3R5bGUuY3NzVGV4dCA9ICJib3JkZXI6MXB4IHNvbGlkIiwgdC5zdHlsZS5oZWlnaHQgPSAiMXB4Iiwgbi5zdHlsZS5oZWlnaHQgPSAiOXB4Iiwgbi5zdHlsZS5kaXNwbGF5ID0gImJsb2NrIiwgcmUuYXBwZW5kQ2hpbGQoZSkuYXBwZW5kQ2hpbGQodCkuYXBwZW5kQ2hpbGQobiksIHIgPSBDLmdldENvbXB1dGVkU3R5bGUodCksIGEgPSBwYXJzZUludChyLmhlaWdodCwgMTApICsgcGFyc2VJbnQoci5ib3JkZXJUb3BXaWR0aCwgMTApICsgcGFyc2VJbnQoci5ib3JkZXJCb3R0b21XaWR0aCwgMTApID09PSB0Lm9mZnNldEhlaWdodCwgcmUucmVtb3ZlQ2hpbGQoZSkpLCBhDQoJCQkJfQ0KCQkJfSkpDQoJCX0oKTsNCgkJdmFyIHplID0gWyJXZWJraXQiLCAiTW96IiwgIm1zIl0sIFVlID0gUy5jcmVhdGVFbGVtZW50KCJkaXYiKS5zdHlsZSwgWGUgPSB7fTsNCg0KCQlmdW5jdGlvbiBWZShlKSB7DQoJCQl2YXIgdCA9IEUuY3NzUHJvcHNbZV0gfHwgWGVbZV07DQoJCQlyZXR1cm4gdCB8fCAoZSBpbiBVZSA/IGUgOiBYZVtlXSA9IGZ1bmN0aW9uKGUpIHsNCgkJCQl2YXIgdCA9IGVbMF0udG9VcHBlckNhc2UoKSArIGUuc2xpY2UoMSksIG4gPSB6ZS5sZW5ndGg7DQoJCQkJd2hpbGUobi0tKSBpZigoZSA9IHplW25dICsgdCkgaW4gVWUpIHJldHVybiBlDQoJCQl9KGUpIHx8IGUpDQoJCX0NCg0KCQl2YXIgR2UgPSAvXihub25lfHRhYmxlKD8hLWNbZWFdKS4rKS8sIFllID0ge3Bvc2l0aW9uOiAiYWJzb2x1dGUiLCB2aXNpYmlsaXR5OiAiaGlkZGVuIiwgZGlzcGxheTogImJsb2NrIn0sIFFlID0ge2xldHRlclNwYWNpbmc6ICIwIiwgZm9udFdlaWdodDogIjQwMCJ9Ow0KDQoJCWZ1bmN0aW9uIEplKGUsIHQsIG4pIHsNCgkJCXZhciByID0gdGUuZXhlYyh0KTsNCgkJCXJldHVybiByID8gTWF0aC5tYXgoMCwgclsyXSAtIChuIHx8IDApKSArIChyWzNdIHx8ICJweCIpIDogdA0KCQl9DQoNCgkJZnVuY3Rpb24gS2UoZSwgdCwgbiwgciwgaSwgbykgew0KCQkJdmFyIGEgPSAid2lkdGgiID09PSB0ID8gMSA6IDAsIHMgPSAwLCB1ID0gMDsNCgkJCWlmKG4gPT09IChyID8gImJvcmRlciIgOiAiY29udGVudCIpKSByZXR1cm4gMDsNCgkJCWZvcig7IGEgPCA0OyBhICs9IDIpICJtYXJnaW4iID09PSBuICYmICh1ICs9IEUuY3NzKGUsIG4gKyBuZVthXSwgITAsIGkpKSwgciA/ICgiY29udGVudCIgPT09IG4gJiYgKHUgLT0gRS5jc3MoZSwgInBhZGRpbmciICsgbmVbYV0sICEwLCBpKSksICJtYXJnaW4iICE9PSBuICYmICh1IC09IEUuY3NzKGUsICJib3JkZXIiICsgbmVbYV0gKyAiV2lkdGgiLCAhMCwgaSkpKSA6ICh1ICs9IEUuY3NzKGUsICJwYWRkaW5nIiArIG5lW2FdLCAhMCwgaSksICJwYWRkaW5nIiAhPT0gbiA/IHUgKz0gRS5jc3MoZSwgImJvcmRlciIgKyBuZVthXSArICJXaWR0aCIsICEwLCBpKSA6IHMgKz0gRS5jc3MoZSwgImJvcmRlciIgKyBuZVthXSArICJXaWR0aCIsICEwLCBpKSk7DQoJCQlyZXR1cm4gIXIgJiYgMCA8PSBvICYmICh1ICs9IE1hdGgubWF4KDAsIE1hdGguY2VpbChlWyJvZmZzZXQiICsgdFswXS50b1VwcGVyQ2FzZSgpICsgdC5zbGljZSgxKV0gLSBvIC0gdSAtIHMgLSAuNSkpIHx8IDApLCB1DQoJCX0NCg0KCQlmdW5jdGlvbiBaZShlLCB0LCBuKSB7DQoJCQl2YXIgciA9IE1lKGUpLCBpID0gKCF2LmJveFNpemluZ1JlbGlhYmxlKCkgfHwgbikgJiYgImJvcmRlci1ib3giID09PSBFLmNzcyhlLCAiYm94U2l6aW5nIiwgITEsIHIpLCBvID0gaSwgYSA9IEJlKGUsIHQsIHIpLCBzID0gIm9mZnNldCIgKyB0WzBdLnRvVXBwZXJDYXNlKCkgKyB0LnNsaWNlKDEpOw0KCQkJaWYoUGUudGVzdChhKSkgew0KCQkJCWlmKCFuKSByZXR1cm4gYTsNCgkJCQlhID0gImF1dG8iDQoJCQl9DQoJCQlyZXR1cm4gKCF2LmJveFNpemluZ1JlbGlhYmxlKCkgJiYgaSB8fCAhdi5yZWxpYWJsZVRyRGltZW5zaW9ucygpICYmIEEoZSwgInRyIikgfHwgImF1dG8iID09PSBhIHx8ICFwYXJzZUZsb2F0KGEpICYmICJpbmxpbmUiID09PSBFLmNzcyhlLCAiZGlzcGxheSIsICExLCByKSkgJiYgZS5nZXRDbGllbnRSZWN0cygpLmxlbmd0aCAmJiAoaSA9ICJib3JkZXItYm94IiA9PT0gRS5jc3MoZSwgImJveFNpemluZyIsICExLCByKSwgKG8gPSBzIGluIGUpICYmIChhID0gZVtzXSkpLCAoYSA9IHBhcnNlRmxvYXQoYSkgfHwgMCkgKyBLZShlLCB0LCBuIHx8IChpID8gImJvcmRlciIgOiAiY29udGVudCIpLCBvLCByLCBhKSArICJweCINCgkJfQ0KDQoJCWZ1bmN0aW9uIGV0KGUsIHQsIG4sIHIsIGkpIHtyZXR1cm4gbmV3IGV0LnByb3RvdHlwZS5pbml0KGUsIHQsIG4sIHIsIGkpfQ0KDQoJCUUuZXh0ZW5kKHsNCgkJCWNzc0hvb2tzOiB7DQoJCQkJb3BhY2l0eTogew0KCQkJCQlnZXQ6IGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQkJCWlmKHQpIHsNCgkJCQkJCQl2YXIgbiA9IEJlKGUsICJvcGFjaXR5Iik7DQoJCQkJCQkJcmV0dXJuICIiID09PSBuID8gIjEiIDogbg0KCQkJCQkJfQ0KCQkJCQl9DQoJCQkJfQ0KCQkJfSwNCgkJCWNzc051bWJlcjogew0KCQkJCWFuaW1hdGlvbkl0ZXJhdGlvbkNvdW50OiAhMCwNCgkJCQljb2x1bW5Db3VudDogITAsDQoJCQkJZmlsbE9wYWNpdHk6ICEwLA0KCQkJCWZsZXhHcm93OiAhMCwNCgkJCQlmbGV4U2hyaW5rOiAhMCwNCgkJCQlmb250V2VpZ2h0OiAhMCwNCgkJCQlncmlkQXJlYTogITAsDQoJCQkJZ3JpZENvbHVtbjogITAsDQoJCQkJZ3JpZENvbHVtbkVuZDogITAsDQoJCQkJZ3JpZENvbHVtblN0YXJ0OiAhMCwNCgkJCQlncmlkUm93OiAhMCwNCgkJCQlncmlkUm93RW5kOiAhMCwNCgkJCQlncmlkUm93U3RhcnQ6ICEwLA0KCQkJCWxpbmVIZWlnaHQ6ICEwLA0KCQkJCW9wYWNpdHk6ICEwLA0KCQkJCW9yZGVyOiAhMCwNCgkJCQlvcnBoYW5zOiAhMCwNCgkJCQl3aWRvd3M6ICEwLA0KCQkJCXpJbmRleDogITAsDQoJCQkJem9vbTogITANCgkJCX0sDQoJCQljc3NQcm9wczoge30sDQoJCQlzdHlsZTogZnVuY3Rpb24oZSwgdCwgbiwgcikgew0KCQkJCWlmKGUgJiYgMyAhPT0gZS5ub2RlVHlwZSAmJiA4ICE9PSBlLm5vZGVUeXBlICYmIGUuc3R5bGUpIHsNCgkJCQkJdmFyIGksIG8sIGEsIHMgPSBYKHQpLCB1ID0gUmUudGVzdCh0KSwgbCA9IGUuc3R5bGU7DQoJCQkJCWlmKHUgfHwgKHQgPSBWZShzKSksIGEgPSBFLmNzc0hvb2tzW3RdIHx8IEUuY3NzSG9va3Nbc10sIHZvaWQgMCA9PT0gbikgcmV0dXJuIGEgJiYgImdldCIgaW4gYSAmJiB2b2lkIDAgIT09IChpID0gYS5nZXQoZSwgITEsIHIpKSA/IGkgOiBsW3RdOw0KCQkJCQkic3RyaW5nIiA9PT0gKG8gPSB0eXBlb2YgbikgJiYgKGkgPSB0ZS5leGVjKG4pKSAmJiBpWzFdICYmIChuID0gc2UoZSwgdCwgaSksIG8gPSAibnVtYmVyIiksIG51bGwgIT0gbiAmJiBuID09IG4gJiYgKCJudW1iZXIiICE9PSBvIHx8IHUgfHwgKG4gKz0gaSAmJiBpWzNdIHx8IChFLmNzc051bWJlcltzXSA/ICIiIDogInB4IikpLCB2LmNsZWFyQ2xvbmVTdHlsZSB8fCAiIiAhPT0gbiB8fCAwICE9PSB0LmluZGV4T2YoImJhY2tncm91bmQiKSB8fCAobFt0XSA9ICJpbmhlcml0IiksIGEgJiYgInNldCIgaW4gYSAmJiB2b2lkIDAgPT09IChuID0gYS5zZXQoZSwgbiwgcikpIHx8ICh1ID8gbC5zZXRQcm9wZXJ0eSh0LCBuKSA6IGxbdF0gPSBuKSkNCgkJCQl9DQoJCQl9LA0KCQkJY3NzOiBmdW5jdGlvbihlLCB0LCBuLCByKSB7DQoJCQkJdmFyIGksIG8sIGEsIHMgPSBYKHQpOw0KCQkJCXJldHVybiBSZS50ZXN0KHQpIHx8ICh0ID0gVmUocykpLCAoYSA9IEUuY3NzSG9va3NbdF0gfHwgRS5jc3NIb29rc1tzXSkgJiYgImdldCIgaW4gYSAmJiAoaSA9IGEuZ2V0KGUsICEwLCBuKSksIHZvaWQgMCA9PT0gaSAmJiAoaSA9IEJlKGUsIHQsIHIpKSwgIm5vcm1hbCIgPT09IGkgJiYgdCBpbiBRZSAmJiAoaSA9IFFlW3RdKSwgIiIgPT09IG4gfHwgbiA/IChvID0gcGFyc2VGbG9hdChpKSwgITAgPT09IG4gfHwgaXNGaW5pdGUobykgPyBvIHx8IDAgOiBpKSA6IGkNCgkJCX0NCgkJfSksIEUuZWFjaChbImhlaWdodCIsICJ3aWR0aCJdLCBmdW5jdGlvbihlLCB1KSB7DQoJCQlFLmNzc0hvb2tzW3VdID0gew0KCQkJCWdldDogZnVuY3Rpb24oZSwgdCwgbikge2lmKHQpIHJldHVybiAhR2UudGVzdChFLmNzcyhlLCAiZGlzcGxheSIpKSB8fCBlLmdldENsaWVudFJlY3RzKCkubGVuZ3RoICYmIGUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGggPyBaZShlLCB1LCBuKSA6IEllKGUsIFllLCBmdW5jdGlvbigpIHtyZXR1cm4gWmUoZSwgdSwgbil9KX0sDQoJCQkJc2V0OiBmdW5jdGlvbihlLCB0LCBuKSB7DQoJCQkJCXZhciByLCBpID0gTWUoZSksIG8gPSAhdi5zY3JvbGxib3hTaXplKCkgJiYgImFic29sdXRlIiA9PT0gaS5wb3NpdGlvbiwgYSA9IChvIHx8IG4pICYmICJib3JkZXItYm94IiA9PT0gRS5jc3MoZSwgImJveFNpemluZyIsICExLCBpKSwgcyA9IG4gPyBLZShlLCB1LCBuLCBhLCBpKSA6IDA7DQoJCQkJCXJldHVybiBhICYmIG8gJiYgKHMgLT0gTWF0aC5jZWlsKGVbIm9mZnNldCIgKyB1WzBdLnRvVXBwZXJDYXNlKCkgKyB1LnNsaWNlKDEpXSAtIHBhcnNlRmxvYXQoaVt1XSkgLSBLZShlLCB1LCAiYm9yZGVyIiwgITEsIGkpIC0gLjUpKSwgcyAmJiAociA9IHRlLmV4ZWModCkpICYmICJweCIgIT09IChyWzNdIHx8ICJweCIpICYmIChlLnN0eWxlW3VdID0gdCwgdCA9IEUuY3NzKGUsIHUpKSwgSmUoMCwgdCwgcykNCgkJCQl9DQoJCQl9DQoJCX0pLCBFLmNzc0hvb2tzLm1hcmdpbkxlZnQgPSBfZSh2LnJlbGlhYmxlTWFyZ2luTGVmdCwgZnVuY3Rpb24oZSwgdCkge2lmKHQpIHJldHVybiAocGFyc2VGbG9hdChCZShlLCAibWFyZ2luTGVmdCIpKSB8fCBlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmxlZnQgLSBJZShlLCB7bWFyZ2luTGVmdDogMH0sIGZ1bmN0aW9uKCkge3JldHVybiBlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmxlZnR9KSkgKyAicHgifSksIEUuZWFjaCh7DQoJCQltYXJnaW46ICIiLA0KCQkJcGFkZGluZzogIiIsDQoJCQlib3JkZXI6ICJXaWR0aCINCgkJfSwgZnVuY3Rpb24oaSwgbykgew0KCQkJRS5jc3NIb29rc1tpICsgb10gPSB7DQoJCQkJZXhwYW5kOiBmdW5jdGlvbihlKSB7DQoJCQkJCWZvcih2YXIgdCA9IDAsIG4gPSB7fSwgciA9ICJzdHJpbmciID09IHR5cGVvZiBlID8gZS5zcGxpdCgiICIpIDogW2VdOyB0IDwgNDsgdCsrKSBuW2kgKyBuZVt0XSArIG9dID0gclt0XSB8fCByW3QgLSAyXSB8fCByWzBdOw0KCQkJCQlyZXR1cm4gbg0KCQkJCX0NCgkJCX0sICJtYXJnaW4iICE9PSBpICYmIChFLmNzc0hvb2tzW2kgKyBvXS5zZXQgPSBKZSkNCgkJfSksIEUuZm4uZXh0ZW5kKHsNCgkJCWNzczogZnVuY3Rpb24oZSwgdCkgew0KCQkJCXJldHVybiBCKHRoaXMsIGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQkJdmFyIHIsIGksIG8gPSB7fSwgYSA9IDA7DQoJCQkJCWlmKEFycmF5LmlzQXJyYXkodCkpIHsNCgkJCQkJCWZvcihyID0gTWUoZSksIGkgPSB0Lmxlbmd0aDsgYSA8IGk7IGErKykgb1t0W2FdXSA9IEUuY3NzKGUsIHRbYV0sICExLCByKTsNCgkJCQkJCXJldHVybiBvDQoJCQkJCX0NCgkJCQkJcmV0dXJuIHZvaWQgMCAhPT0gbiA/IEUuc3R5bGUoZSwgdCwgbikgOiBFLmNzcyhlLCB0KQ0KCQkJCX0sIGUsIHQsIDEgPCBhcmd1bWVudHMubGVuZ3RoKQ0KCQkJfQ0KCQl9KSwgKChFLlR3ZWVuID0gZXQpLnByb3RvdHlwZSA9IHsNCgkJCWNvbnN0cnVjdG9yOiBldCwNCgkJCWluaXQ6IGZ1bmN0aW9uKGUsIHQsIG4sIHIsIGksIG8pIHt0aGlzLmVsZW0gPSBlLCB0aGlzLnByb3AgPSBuLCB0aGlzLmVhc2luZyA9IGkgfHwgRS5lYXNpbmcuX2RlZmF1bHQsIHRoaXMub3B0aW9ucyA9IHQsIHRoaXMuc3RhcnQgPSB0aGlzLm5vdyA9IHRoaXMuY3VyKCksIHRoaXMuZW5kID0gciwgdGhpcy51bml0ID0gbyB8fCAoRS5jc3NOdW1iZXJbbl0gPyAiIiA6ICJweCIpfSwNCgkJCWN1cjogZnVuY3Rpb24oKSB7DQoJCQkJdmFyIGUgPSBldC5wcm9wSG9va3NbdGhpcy5wcm9wXTsNCgkJCQlyZXR1cm4gZSAmJiBlLmdldCA/IGUuZ2V0KHRoaXMpIDogZXQucHJvcEhvb2tzLl9kZWZhdWx0LmdldCh0aGlzKQ0KCQkJfSwNCgkJCXJ1bjogZnVuY3Rpb24oZSkgew0KCQkJCXZhciB0LCBuID0gZXQucHJvcEhvb2tzW3RoaXMucHJvcF07DQoJCQkJcmV0dXJuIHRoaXMub3B0aW9ucy5kdXJhdGlvbiA/IHRoaXMucG9zID0gdCA9IEUuZWFzaW5nW3RoaXMuZWFzaW5nXShlLCB0aGlzLm9wdGlvbnMuZHVyYXRpb24gKiBlLCAwLCAxLCB0aGlzLm9wdGlvbnMuZHVyYXRpb24pIDogdGhpcy5wb3MgPSB0ID0gZSwgdGhpcy5ub3cgPSAodGhpcy5lbmQgLSB0aGlzLnN0YXJ0KSAqIHQgKyB0aGlzLnN0YXJ0LCB0aGlzLm9wdGlvbnMuc3RlcCAmJiB0aGlzLm9wdGlvbnMuc3RlcC5jYWxsKHRoaXMuZWxlbSwgdGhpcy5ub3csIHRoaXMpLCBuICYmIG4uc2V0ID8gbi5zZXQodGhpcykgOiBldC5wcm9wSG9va3MuX2RlZmF1bHQuc2V0KHRoaXMpLCB0aGlzDQoJCQl9DQoJCX0pLmluaXQucHJvdG90eXBlID0gZXQucHJvdG90eXBlLCAoZXQucHJvcEhvb2tzID0gew0KCQkJX2RlZmF1bHQ6IHsNCgkJCQlnZXQ6IGZ1bmN0aW9uKGUpIHsNCgkJCQkJdmFyIHQ7DQoJCQkJCXJldHVybiAxICE9PSBlLmVsZW0ubm9kZVR5cGUgfHwgbnVsbCAhPSBlLmVsZW1bZS5wcm9wXSAmJiBudWxsID09IGUuZWxlbS5zdHlsZVtlLnByb3BdID8gZS5lbGVtW2UucHJvcF0gOiAodCA9IEUuY3NzKGUuZWxlbSwgZS5wcm9wLCAiIikpICYmICJhdXRvIiAhPT0gdCA/IHQgOiAwDQoJCQkJfSwgc2V0OiBmdW5jdGlvbihlKSB7RS5meC5zdGVwW2UucHJvcF0gPyBFLmZ4LnN0ZXBbZS5wcm9wXShlKSA6IDEgIT09IGUuZWxlbS5ub2RlVHlwZSB8fCAhRS5jc3NIb29rc1tlLnByb3BdICYmIG51bGwgPT0gZS5lbGVtLnN0eWxlW1ZlKGUucHJvcCldID8gZS5lbGVtW2UucHJvcF0gPSBlLm5vdyA6IEUuc3R5bGUoZS5lbGVtLCBlLnByb3AsIGUubm93ICsgZS51bml0KX0NCgkJCX0NCgkJfSkuc2Nyb2xsVG9wID0gZXQucHJvcEhvb2tzLnNjcm9sbExlZnQgPSB7c2V0OiBmdW5jdGlvbihlKSB7ZS5lbGVtLm5vZGVUeXBlICYmIGUuZWxlbS5wYXJlbnROb2RlICYmIChlLmVsZW1bZS5wcm9wXSA9IGUubm93KX19LCBFLmVhc2luZyA9IHsNCgkJCWxpbmVhcjogZnVuY3Rpb24oZSkge3JldHVybiBlfSwNCgkJCXN3aW5nOiBmdW5jdGlvbihlKSB7cmV0dXJuIC41IC0gTWF0aC5jb3MoZSAqIE1hdGguUEkpIC8gMn0sDQoJCQlfZGVmYXVsdDogInN3aW5nIg0KCQl9LCBFLmZ4ID0gZXQucHJvdG90eXBlLmluaXQsIEUuZnguc3RlcCA9IHt9Ow0KCQl2YXIgdHQsIG50LCBydCwgaXQsIG90ID0gL14oPzp0b2dnbGV8c2hvd3xoaWRlKSQvLCBhdCA9IC9xdWV1ZUhvb2tzJC87DQoNCgkJZnVuY3Rpb24gc3QoKSB7bnQgJiYgKCExID09PSBTLmhpZGRlbiAmJiBDLnJlcXVlc3RBbmltYXRpb25GcmFtZSA/IEMucmVxdWVzdEFuaW1hdGlvbkZyYW1lKHN0KSA6IEMuc2V0VGltZW91dChzdCwgRS5meC5pbnRlcnZhbCksIEUuZngudGljaygpKX0NCg0KCQlmdW5jdGlvbiB1dCgpIHtyZXR1cm4gQy5zZXRUaW1lb3V0KGZ1bmN0aW9uKCkge3R0ID0gdm9pZCAwfSksIHR0ID0gRGF0ZS5ub3coKX0NCg0KCQlmdW5jdGlvbiBsdChlLCB0KSB7DQoJCQl2YXIgbiwgciA9IDAsIGkgPSB7aGVpZ2h0OiBlfTsNCgkJCWZvcih0ID0gdCA/IDEgOiAwOyByIDwgNDsgciArPSAyIC0gdCkgaVsibWFyZ2luIiArIChuID0gbmVbcl0pXSA9IGlbInBhZGRpbmciICsgbl0gPSBlOw0KCQkJcmV0dXJuIHQgJiYgKGkub3BhY2l0eSA9IGkud2lkdGggPSBlKSwgaQ0KCQl9DQoNCgkJZnVuY3Rpb24gY3QoZSwgdCwgbikge2Zvcih2YXIgciwgaSA9IChmdC50d2VlbmVyc1t0XSB8fCBbXSkuY29uY2F0KGZ0LnR3ZWVuZXJzWyIqIl0pLCBvID0gMCwgYSA9IGkubGVuZ3RoOyBvIDwgYTsgbysrKSBpZihyID0gaVtvXS5jYWxsKG4sIHQsIGUpKSByZXR1cm4gcn0NCg0KCQlmdW5jdGlvbiBmdChvLCBlLCB0KSB7DQoJCQl2YXIgbiwNCgkJCSAgICBhLA0KCQkJICAgIHIgPSAwLA0KCQkJICAgIGkgPSBmdC5wcmVmaWx0ZXJzLmxlbmd0aCwNCgkJCSAgICBzID0gRS5EZWZlcnJlZCgpLmFsd2F5cyhmdW5jdGlvbigpIHtkZWxldGUgdS5lbGVtfSksDQoJCQkgICAgdSA9IGZ1bmN0aW9uKCkgew0KCQkJCSAgICBpZihhKSByZXR1cm4gITE7DQoJCQkJICAgIGZvcih2YXIgZSA9IHR0IHx8IHV0KCksIHQgPSBNYXRoLm1heCgwLCBsLnN0YXJ0VGltZSArIGwuZHVyYXRpb24gLSBlKSwgbiA9IDEgLSAodCAvIGwuZHVyYXRpb24gfHwgMCksIHIgPSAwLCBpID0gbC50d2VlbnMubGVuZ3RoOyByIDwgaTsgcisrKSBsLnR3ZWVuc1tyXS5ydW4obik7DQoJCQkJICAgIHJldHVybiBzLm5vdGlmeVdpdGgobywgW2wsIG4sIHRdKSwgbiA8IDEgJiYgaSA/IHQgOiAoaSB8fCBzLm5vdGlmeVdpdGgobywgW2wsIDEsIDBdKSwgcy5yZXNvbHZlV2l0aChvLCBbbF0pLCAhMSkNCgkJCSAgICB9LA0KCQkJICAgIGwgPSBzLnByb21pc2Uoew0KCQkJCSAgICBlbGVtOiBvLA0KCQkJCSAgICBwcm9wczogRS5leHRlbmQoe30sIGUpLA0KCQkJCSAgICBvcHRzOiBFLmV4dGVuZCghMCwge3NwZWNpYWxFYXNpbmc6IHt9LCBlYXNpbmc6IEUuZWFzaW5nLl9kZWZhdWx0fSwgdCksDQoJCQkJICAgIG9yaWdpbmFsUHJvcGVydGllczogZSwNCgkJCQkgICAgb3JpZ2luYWxPcHRpb25zOiB0LA0KCQkJCSAgICBzdGFydFRpbWU6IHR0IHx8IHV0KCksDQoJCQkJICAgIGR1cmF0aW9uOiB0LmR1cmF0aW9uLA0KCQkJCSAgICB0d2VlbnM6IFtdLA0KCQkJCSAgICBjcmVhdGVUd2VlbjogZnVuY3Rpb24oZSwgdCkgew0KCQkJCQkgICAgdmFyIG4gPSBFLlR3ZWVuKG8sIGwub3B0cywgZSwgdCwgbC5vcHRzLnNwZWNpYWxFYXNpbmdbZV0gfHwgbC5vcHRzLmVhc2luZyk7DQoJCQkJCSAgICByZXR1cm4gbC50d2VlbnMucHVzaChuKSwgbg0KCQkJCSAgICB9LA0KCQkJCSAgICBzdG9wOiBmdW5jdGlvbihlKSB7DQoJCQkJCSAgICB2YXIgdCA9IDAsIG4gPSBlID8gbC50d2VlbnMubGVuZ3RoIDogMDsNCgkJCQkJICAgIGlmKGEpIHJldHVybiB0aGlzOw0KCQkJCQkgICAgZm9yKGEgPSAhMDsgdCA8IG47IHQrKykgbC50d2VlbnNbdF0ucnVuKDEpOw0KCQkJCQkgICAgcmV0dXJuIGUgPyAocy5ub3RpZnlXaXRoKG8sIFtsLCAxLCAwXSksIHMucmVzb2x2ZVdpdGgobywgW2wsIGVdKSkgOiBzLnJlamVjdFdpdGgobywgW2wsIGVdKSwgdGhpcw0KCQkJCSAgICB9DQoJCQkgICAgfSksDQoJCQkgICAgYyA9IGwucHJvcHM7DQoJCQlmb3IoIWZ1bmN0aW9uKGUsIHQpIHsNCgkJCQl2YXIgbiwgciwgaSwgbywgYTsNCgkJCQlmb3IobiBpbiBlKSBpZihpID0gdFtyID0gWChuKV0sIG8gPSBlW25dLCBBcnJheS5pc0FycmF5KG8pICYmIChpID0gb1sxXSwgbyA9IGVbbl0gPSBvWzBdKSwgbiAhPT0gciAmJiAoZVtyXSA9IG8sIGRlbGV0ZSBlW25dKSwgKGEgPSBFLmNzc0hvb2tzW3JdKSAmJiAiZXhwYW5kIiBpbiBhKSBmb3IobiBpbiBvID0gYS5leHBhbmQobyksIGRlbGV0ZSBlW3JdLCBvKSBuIGluIGUgfHwgKGVbbl0gPSBvW25dLCB0W25dID0gaSk7IGVsc2UgdFtyXSA9IGkNCgkJCX0oYywgbC5vcHRzLnNwZWNpYWxFYXNpbmcpOyByIDwgaTsgcisrKSBpZihuID0gZnQucHJlZmlsdGVyc1tyXS5jYWxsKGwsIG8sIGMsIGwub3B0cykpIHJldHVybiBtKG4uc3RvcCkgJiYgKEUuX3F1ZXVlSG9va3MobC5lbGVtLCBsLm9wdHMucXVldWUpLnN0b3AgPSBuLnN0b3AuYmluZChuKSksIG47DQoJCQlyZXR1cm4gRS5tYXAoYywgY3QsIGwpLCBtKGwub3B0cy5zdGFydCkgJiYgbC5vcHRzLnN0YXJ0LmNhbGwobywgbCksIGwucHJvZ3Jlc3MobC5vcHRzLnByb2dyZXNzKS5kb25lKGwub3B0cy5kb25lLCBsLm9wdHMuY29tcGxldGUpLmZhaWwobC5vcHRzLmZhaWwpLmFsd2F5cyhsLm9wdHMuYWx3YXlzKSwgRS5meC50aW1lcihFLmV4dGVuZCh1LCB7ZWxlbTogbywgYW5pbTogbCwgcXVldWU6IGwub3B0cy5xdWV1ZX0pKSwgbA0KCQl9DQoNCgkJRS5BbmltYXRpb24gPSBFLmV4dGVuZChmdCwgew0KCQkJdHdlZW5lcnM6IHsNCgkJCQkiKiI6IFtmdW5jdGlvbihlLCB0KSB7DQoJCQkJCXZhciBuID0gdGhpcy5jcmVhdGVUd2VlbihlLCB0KTsNCgkJCQkJcmV0dXJuIHNlKG4uZWxlbSwgZSwgdGUuZXhlYyh0KSwgbiksIG4NCgkJCQl9XQ0KCQkJfSwgdHdlZW5lcjogZnVuY3Rpb24oZSwgdCkgew0KCQkJCW0oZSkgPyAodCA9IGUsIGUgPSBbIioiXSkgOiBlID0gZS5tYXRjaChQKTsNCgkJCQlmb3IodmFyIG4sIHIgPSAwLCBpID0gZS5sZW5ndGg7IHIgPCBpOyByKyspIG4gPSBlW3JdLCBmdC50d2VlbmVyc1tuXSA9IGZ0LnR3ZWVuZXJzW25dIHx8IFtdLCBmdC50d2VlbmVyc1tuXS51bnNoaWZ0KHQpDQoJCQl9LCBwcmVmaWx0ZXJzOiBbZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJCXZhciByLCBpLCBvLCBhLCBzLCB1LCBsLCBjLCBmID0gIndpZHRoIiBpbiB0IHx8ICJoZWlnaHQiIGluIHQsIHAgPSB0aGlzLCBkID0ge30sIGggPSBlLnN0eWxlLCBnID0gZS5ub2RlVHlwZSAmJiBhZShlKSwgeSA9IFkuZ2V0KGUsICJmeHNob3ciKTsNCgkJCQlmb3IociBpbiBuLnF1ZXVlIHx8IChudWxsID09IChhID0gRS5fcXVldWVIb29rcyhlLCAiZngiKSkudW5xdWV1ZWQgJiYgKGEudW5xdWV1ZWQgPSAwLCBzID0gYS5lbXB0eS5maXJlLCBhLmVtcHR5LmZpcmUgPSBmdW5jdGlvbigpIHthLnVucXVldWVkIHx8IHMoKX0pLCBhLnVucXVldWVkKyssIHAuYWx3YXlzKGZ1bmN0aW9uKCkge3AuYWx3YXlzKGZ1bmN0aW9uKCkge2EudW5xdWV1ZWQtLSwgRS5xdWV1ZShlLCAiZngiKS5sZW5ndGggfHwgYS5lbXB0eS5maXJlKCl9KX0pKSwgdCkgaWYoaSA9IHRbcl0sIG90LnRlc3QoaSkpIHsNCgkJCQkJaWYoZGVsZXRlIHRbcl0sIG8gPSBvIHx8ICJ0b2dnbGUiID09PSBpLCBpID09PSAoZyA/ICJoaWRlIiA6ICJzaG93IikpIHsNCgkJCQkJCWlmKCJzaG93IiAhPT0gaSB8fCAheSB8fCB2b2lkIDAgPT09IHlbcl0pIGNvbnRpbnVlOw0KCQkJCQkJZyA9ICEwDQoJCQkJCX0NCgkJCQkJZFtyXSA9IHkgJiYgeVtyXSB8fCBFLnN0eWxlKGUsIHIpDQoJCQkJfQ0KCQkJCWlmKCh1ID0gIUUuaXNFbXB0eU9iamVjdCh0KSkgfHwgIUUuaXNFbXB0eU9iamVjdChkKSkgZm9yKHIgaW4gZiAmJiAxID09PSBlLm5vZGVUeXBlICYmIChuLm92ZXJmbG93ID0gW2gub3ZlcmZsb3csIGgub3ZlcmZsb3dYLCBoLm92ZXJmbG93WV0sIG51bGwgPT0gKGwgPSB5ICYmIHkuZGlzcGxheSkgJiYgKGwgPSBZLmdldChlLCAiZGlzcGxheSIpKSwgIm5vbmUiID09PSAoYyA9IEUuY3NzKGUsICJkaXNwbGF5IikpICYmIChsID8gYyA9IGwgOiAobGUoW2VdLCAhMCksIGwgPSBlLnN0eWxlLmRpc3BsYXkgfHwgbCwgYyA9IEUuY3NzKGUsICJkaXNwbGF5IiksIGxlKFtlXSkpKSwgKCJpbmxpbmUiID09PSBjIHx8ICJpbmxpbmUtYmxvY2siID09PSBjICYmIG51bGwgIT0gbCkgJiYgIm5vbmUiID09PSBFLmNzcyhlLCAiZmxvYXQiKSAmJiAodSB8fCAocC5kb25lKGZ1bmN0aW9uKCkge2guZGlzcGxheSA9IGx9KSwgbnVsbCA9PSBsICYmIChjID0gaC5kaXNwbGF5LCBsID0gIm5vbmUiID09PSBjID8gIiIgOiBjKSksIGguZGlzcGxheSA9ICJpbmxpbmUtYmxvY2siKSksIG4ub3ZlcmZsb3cgJiYgKGgub3ZlcmZsb3cgPSAiaGlkZGVuIiwgcC5hbHdheXMoZnVuY3Rpb24oKSB7aC5vdmVyZmxvdyA9IG4ub3ZlcmZsb3dbMF0sIGgub3ZlcmZsb3dYID0gbi5vdmVyZmxvd1sxXSwgaC5vdmVyZmxvd1kgPSBuLm92ZXJmbG93WzJdfSkpLCB1ID0gITEsIGQpIHUgfHwgKHkgPyAiaGlkZGVuIiBpbiB5ICYmIChnID0geS5oaWRkZW4pIDogeSA9IFkuYWNjZXNzKGUsICJmeHNob3ciLCB7ZGlzcGxheTogbH0pLCBvICYmICh5LmhpZGRlbiA9ICFnKSwgZyAmJiBsZShbZV0sICEwKSwgcC5kb25lKGZ1bmN0aW9uKCkge2ZvcihyIGluIGcgfHwgbGUoW2VdKSwgWS5yZW1vdmUoZSwgImZ4c2hvdyIpLCBkKSBFLnN0eWxlKGUsIHIsIGRbcl0pfSkpLCB1ID0gY3QoZyA/IHlbcl0gOiAwLCByLCBwKSwgciBpbiB5IHx8ICh5W3JdID0gdS5zdGFydCwgZyAmJiAodS5lbmQgPSB1LnN0YXJ0LCB1LnN0YXJ0ID0gMCkpDQoJCQl9XSwgcHJlZmlsdGVyOiBmdW5jdGlvbihlLCB0KSB7dCA/IGZ0LnByZWZpbHRlcnMudW5zaGlmdChlKSA6IGZ0LnByZWZpbHRlcnMucHVzaChlKX0NCgkJfSksIEUuc3BlZWQgPSBmdW5jdGlvbihlLCB0LCBuKSB7DQoJCQl2YXIgciA9IGUgJiYgIm9iamVjdCIgPT0gdHlwZW9mIGUgPyBFLmV4dGVuZCh7fSwgZSkgOiB7Y29tcGxldGU6IG4gfHwgIW4gJiYgdCB8fCBtKGUpICYmIGUsIGR1cmF0aW9uOiBlLCBlYXNpbmc6IG4gJiYgdCB8fCB0ICYmICFtKHQpICYmIHR9Ow0KCQkJcmV0dXJuIEUuZngub2ZmID8gci5kdXJhdGlvbiA9IDAgOiAibnVtYmVyIiAhPSB0eXBlb2Ygci5kdXJhdGlvbiAmJiAoci5kdXJhdGlvbiBpbiBFLmZ4LnNwZWVkcyA/IHIuZHVyYXRpb24gPSBFLmZ4LnNwZWVkc1tyLmR1cmF0aW9uXSA6IHIuZHVyYXRpb24gPSBFLmZ4LnNwZWVkcy5fZGVmYXVsdCksIG51bGwgIT0gci5xdWV1ZSAmJiAhMCAhPT0gci5xdWV1ZSB8fCAoci5xdWV1ZSA9ICJmeCIpLCByLm9sZCA9IHIuY29tcGxldGUsIHIuY29tcGxldGUgPSBmdW5jdGlvbigpIHttKHIub2xkKSAmJiByLm9sZC5jYWxsKHRoaXMpLCByLnF1ZXVlICYmIEUuZGVxdWV1ZSh0aGlzLCByLnF1ZXVlKX0sIHINCgkJfSwgRS5mbi5leHRlbmQoew0KCQkJZmFkZVRvOiBmdW5jdGlvbihlLCB0LCBuLCByKSB7cmV0dXJuIHRoaXMuZmlsdGVyKGFlKS5jc3MoIm9wYWNpdHkiLCAwKS5zaG93KCkuZW5kKCkuYW5pbWF0ZSh7b3BhY2l0eTogdH0sIGUsIG4sIHIpfSwgYW5pbWF0ZTogZnVuY3Rpb24odCwgZSwgbiwgcikgew0KCQkJCXZhciBpID0gRS5pc0VtcHR5T2JqZWN0KHQpLCBvID0gRS5zcGVlZChlLCBuLCByKSwgYSA9IGZ1bmN0aW9uKCkgew0KCQkJCQl2YXIgZSA9IGZ0KHRoaXMsIEUuZXh0ZW5kKHt9LCB0KSwgbyk7DQoJCQkJCShpIHx8IFkuZ2V0KHRoaXMsICJmaW5pc2giKSkgJiYgZS5zdG9wKCEwKQ0KCQkJCX07DQoJCQkJcmV0dXJuIGEuZmluaXNoID0gYSwgaSB8fCAhMSA9PT0gby5xdWV1ZSA/IHRoaXMuZWFjaChhKSA6IHRoaXMucXVldWUoby5xdWV1ZSwgYSkNCgkJCX0sIHN0b3A6IGZ1bmN0aW9uKGksIGUsIG8pIHsNCgkJCQl2YXIgYSA9IGZ1bmN0aW9uKGUpIHsNCgkJCQkJdmFyIHQgPSBlLnN0b3A7DQoJCQkJCWRlbGV0ZSBlLnN0b3AsIHQobykNCgkJCQl9Ow0KCQkJCXJldHVybiAic3RyaW5nIiAhPSB0eXBlb2YgaSAmJiAobyA9IGUsIGUgPSBpLCBpID0gdm9pZCAwKSwgZSAmJiB0aGlzLnF1ZXVlKGkgfHwgImZ4IiwgW10pLCB0aGlzLmVhY2goZnVuY3Rpb24oKSB7DQoJCQkJCXZhciBlID0gITAsIHQgPSBudWxsICE9IGkgJiYgaSArICJxdWV1ZUhvb2tzIiwgbiA9IEUudGltZXJzLCByID0gWS5nZXQodGhpcyk7DQoJCQkJCWlmKHQpIHJbdF0gJiYgclt0XS5zdG9wICYmIGEoclt0XSk7IGVsc2UgZm9yKHQgaW4gcikgclt0XSAmJiByW3RdLnN0b3AgJiYgYXQudGVzdCh0KSAmJiBhKHJbdF0pOw0KCQkJCQlmb3IodCA9IG4ubGVuZ3RoOyB0LS07KSBuW3RdLmVsZW0gIT09IHRoaXMgfHwgbnVsbCAhPSBpICYmIG5bdF0ucXVldWUgIT09IGkgfHwgKG5bdF0uYW5pbS5zdG9wKG8pLCBlID0gITEsIG4uc3BsaWNlKHQsIDEpKTsNCgkJCQkJIWUgJiYgbyB8fCBFLmRlcXVldWUodGhpcywgaSkNCgkJCQl9KQ0KCQkJfSwgZmluaXNoOiBmdW5jdGlvbihhKSB7DQoJCQkJcmV0dXJuICExICE9PSBhICYmIChhID0gYSB8fCAiZngiKSwgdGhpcy5lYWNoKGZ1bmN0aW9uKCkgew0KCQkJCQl2YXIgZSwgdCA9IFkuZ2V0KHRoaXMpLCBuID0gdFthICsgInF1ZXVlIl0sIHIgPSB0W2EgKyAicXVldWVIb29rcyJdLCBpID0gRS50aW1lcnMsIG8gPSBuID8gbi5sZW5ndGggOiAwOw0KCQkJCQlmb3IodC5maW5pc2ggPSAhMCwgRS5xdWV1ZSh0aGlzLCBhLCBbXSksIHIgJiYgci5zdG9wICYmIHIuc3RvcC5jYWxsKHRoaXMsICEwKSwgZSA9IGkubGVuZ3RoOyBlLS07KSBpW2VdLmVsZW0gPT09IHRoaXMgJiYgaVtlXS5xdWV1ZSA9PT0gYSAmJiAoaVtlXS5hbmltLnN0b3AoITApLCBpLnNwbGljZShlLCAxKSk7DQoJCQkJCWZvcihlID0gMDsgZSA8IG87IGUrKykgbltlXSAmJiBuW2VdLmZpbmlzaCAmJiBuW2VdLmZpbmlzaC5jYWxsKHRoaXMpOw0KCQkJCQlkZWxldGUgdC5maW5pc2gNCgkJCQl9KQ0KCQkJfQ0KCQl9KSwgRS5lYWNoKFsidG9nZ2xlIiwgInNob3ciLCAiaGlkZSJdLCBmdW5jdGlvbihlLCByKSB7DQoJCQl2YXIgaSA9IEUuZm5bcl07DQoJCQlFLmZuW3JdID0gZnVuY3Rpb24oZSwgdCwgbikge3JldHVybiBudWxsID09IGUgfHwgImJvb2xlYW4iID09IHR5cGVvZiBlID8gaS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIDogdGhpcy5hbmltYXRlKGx0KHIsICEwKSwgZSwgdCwgbil9DQoJCX0pLCBFLmVhY2goew0KCQkJc2xpZGVEb3duOiBsdCgic2hvdyIpLA0KCQkJc2xpZGVVcDogbHQoImhpZGUiKSwNCgkJCXNsaWRlVG9nZ2xlOiBsdCgidG9nZ2xlIiksDQoJCQlmYWRlSW46IHtvcGFjaXR5OiAic2hvdyJ9LA0KCQkJZmFkZU91dDoge29wYWNpdHk6ICJoaWRlIn0sDQoJCQlmYWRlVG9nZ2xlOiB7b3BhY2l0eTogInRvZ2dsZSJ9DQoJCX0sIGZ1bmN0aW9uKGUsIHIpIHtFLmZuW2VdID0gZnVuY3Rpb24oZSwgdCwgbikge3JldHVybiB0aGlzLmFuaW1hdGUociwgZSwgdCwgbil9fSksIEUudGltZXJzID0gW10sIEUuZngudGljayA9IGZ1bmN0aW9uKCkgew0KCQkJdmFyIGUsIHQgPSAwLCBuID0gRS50aW1lcnM7DQoJCQlmb3IodHQgPSBEYXRlLm5vdygpOyB0IDwgbi5sZW5ndGg7IHQrKykgKGUgPSBuW3RdKSgpIHx8IG5bdF0gIT09IGUgfHwgbi5zcGxpY2UodC0tLCAxKTsNCgkJCW4ubGVuZ3RoIHx8IEUuZnguc3RvcCgpLCB0dCA9IHZvaWQgMA0KCQl9LCBFLmZ4LnRpbWVyID0gZnVuY3Rpb24oZSkge0UudGltZXJzLnB1c2goZSksIEUuZnguc3RhcnQoKX0sIEUuZnguaW50ZXJ2YWwgPSAxMywgRS5meC5zdGFydCA9IGZ1bmN0aW9uKCkge250IHx8IChudCA9ICEwLCBzdCgpKX0sIEUuZnguc3RvcCA9IGZ1bmN0aW9uKCkge250ID0gbnVsbH0sIEUuZnguc3BlZWRzID0gew0KCQkJc2xvdzogNjAwLA0KCQkJZmFzdDogMjAwLA0KCQkJX2RlZmF1bHQ6IDQwMA0KCQl9LCBFLmZuLmRlbGF5ID0gZnVuY3Rpb24ociwgZSkgew0KCQkJcmV0dXJuIHIgPSBFLmZ4ICYmIEUuZnguc3BlZWRzW3JdIHx8IHIsIGUgPSBlIHx8ICJmeCIsIHRoaXMucXVldWUoZSwgZnVuY3Rpb24oZSwgdCkgew0KCQkJCXZhciBuID0gQy5zZXRUaW1lb3V0KGUsIHIpOw0KCQkJCXQuc3RvcCA9IGZ1bmN0aW9uKCkge0MuY2xlYXJUaW1lb3V0KG4pfQ0KCQkJfSkNCgkJfSwgcnQgPSBTLmNyZWF0ZUVsZW1lbnQoImlucHV0IiksIGl0ID0gUy5jcmVhdGVFbGVtZW50KCJzZWxlY3QiKS5hcHBlbmRDaGlsZChTLmNyZWF0ZUVsZW1lbnQoIm9wdGlvbiIpKSwgcnQudHlwZSA9ICJjaGVja2JveCIsIHYuY2hlY2tPbiA9ICIiICE9PSBydC52YWx1ZSwgdi5vcHRTZWxlY3RlZCA9IGl0LnNlbGVjdGVkLCAocnQgPSBTLmNyZWF0ZUVsZW1lbnQoImlucHV0IikpLnZhbHVlID0gInQiLCBydC50eXBlID0gInJhZGlvIiwgdi5yYWRpb1ZhbHVlID0gInQiID09PSBydC52YWx1ZTsNCgkJdmFyIHB0LCBkdCA9IEUuZXhwci5hdHRySGFuZGxlOw0KCQlFLmZuLmV4dGVuZCh7YXR0cjogZnVuY3Rpb24oZSwgdCkge3JldHVybiBCKHRoaXMsIEUuYXR0ciwgZSwgdCwgMSA8IGFyZ3VtZW50cy5sZW5ndGgpfSwgcmVtb3ZlQXR0cjogZnVuY3Rpb24oZSkge3JldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7RS5yZW1vdmVBdHRyKHRoaXMsIGUpfSl9fSksIEUuZXh0ZW5kKHsNCgkJCWF0dHI6IGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQl2YXIgciwgaSwgbyA9IGUubm9kZVR5cGU7DQoJCQkJaWYoMyAhPT0gbyAmJiA4ICE9PSBvICYmIDIgIT09IG8pIHJldHVybiAidW5kZWZpbmVkIiA9PSB0eXBlb2YgZS5nZXRBdHRyaWJ1dGUgPyBFLnByb3AoZSwgdCwgbikgOiAoMSA9PT0gbyAmJiBFLmlzWE1MRG9jKGUpIHx8IChpID0gRS5hdHRySG9va3NbdC50b0xvd2VyQ2FzZSgpXSB8fCAoRS5leHByLm1hdGNoLmJvb2wudGVzdCh0KSA/IHB0IDogdm9pZCAwKSksIHZvaWQgMCAhPT0gbiA/IG51bGwgPT09IG4gPyB2b2lkIEUucmVtb3ZlQXR0cihlLCB0KSA6IGkgJiYgInNldCIgaW4gaSAmJiB2b2lkIDAgIT09IChyID0gaS5zZXQoZSwgbiwgdCkpID8gciA6IChlLnNldEF0dHJpYnV0ZSh0LCBuICsgIiIpLCBuKSA6IGkgJiYgImdldCIgaW4gaSAmJiBudWxsICE9PSAociA9IGkuZ2V0KGUsIHQpKSA/IHIgOiBudWxsID09IChyID0gRS5maW5kLmF0dHIoZSwgdCkpID8gdm9pZCAwIDogcikNCgkJCX0sIGF0dHJIb29rczogew0KCQkJCXR5cGU6IHsNCgkJCQkJc2V0OiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJCQlpZighdi5yYWRpb1ZhbHVlICYmICJyYWRpbyIgPT09IHQgJiYgQShlLCAiaW5wdXQiKSkgew0KCQkJCQkJCXZhciBuID0gZS52YWx1ZTsNCgkJCQkJCQlyZXR1cm4gZS5zZXRBdHRyaWJ1dGUoInR5cGUiLCB0KSwgbiAmJiAoZS52YWx1ZSA9IG4pLCB0DQoJCQkJCQl9DQoJCQkJCX0NCgkJCQl9DQoJCQl9LCByZW1vdmVBdHRyOiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJdmFyIG4sIHIgPSAwLCBpID0gdCAmJiB0Lm1hdGNoKFApOw0KCQkJCWlmKGkgJiYgMSA9PT0gZS5ub2RlVHlwZSkgd2hpbGUobiA9IGlbcisrXSkgZS5yZW1vdmVBdHRyaWJ1dGUobikNCgkJCX0NCgkJfSksIHB0ID0ge3NldDogZnVuY3Rpb24oZSwgdCwgbikge3JldHVybiAhMSA9PT0gdCA/IEUucmVtb3ZlQXR0cihlLCBuKSA6IGUuc2V0QXR0cmlidXRlKG4sIG4pLCBufX0sIEUuZWFjaChFLmV4cHIubWF0Y2guYm9vbC5zb3VyY2UubWF0Y2goL1x3Ky9nKSwgZnVuY3Rpb24oZSwgdCkgew0KCQkJdmFyIGEgPSBkdFt0XSB8fCBFLmZpbmQuYXR0cjsNCgkJCWR0W3RdID0gZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJCXZhciByLCBpLCBvID0gdC50b0xvd2VyQ2FzZSgpOw0KCQkJCXJldHVybiBuIHx8IChpID0gZHRbb10sIGR0W29dID0gciwgciA9IG51bGwgIT0gYShlLCB0LCBuKSA/IG8gOiBudWxsLCBkdFtvXSA9IGkpLCByDQoJCQl9DQoJCX0pOw0KCQl2YXIgaHQgPSAvXig/OmlucHV0fHNlbGVjdHx0ZXh0YXJlYXxidXR0b24pJC9pLCBndCA9IC9eKD86YXxhcmVhKSQvaTsNCg0KCQlmdW5jdGlvbiB5dChlKSB7cmV0dXJuIChlLm1hdGNoKFApIHx8IFtdKS5qb2luKCIgIil9DQoNCgkJZnVuY3Rpb24gdnQoZSkge3JldHVybiBlLmdldEF0dHJpYnV0ZSAmJiBlLmdldEF0dHJpYnV0ZSgiY2xhc3MiKSB8fCAiIn0NCg0KCQlmdW5jdGlvbiBtdChlKSB7cmV0dXJuIEFycmF5LmlzQXJyYXkoZSkgPyBlIDogInN0cmluZyIgPT0gdHlwZW9mIGUgJiYgZS5tYXRjaChQKSB8fCBbXX0NCg0KCQlFLmZuLmV4dGVuZCh7cHJvcDogZnVuY3Rpb24oZSwgdCkge3JldHVybiBCKHRoaXMsIEUucHJvcCwgZSwgdCwgMSA8IGFyZ3VtZW50cy5sZW5ndGgpfSwgcmVtb3ZlUHJvcDogZnVuY3Rpb24oZSkge3JldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7ZGVsZXRlIHRoaXNbRS5wcm9wRml4W2VdIHx8IGVdfSl9fSksIEUuZXh0ZW5kKHsNCgkJCXByb3A6IGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQl2YXIgciwgaSwgbyA9IGUubm9kZVR5cGU7DQoJCQkJaWYoMyAhPT0gbyAmJiA4ICE9PSBvICYmIDIgIT09IG8pIHJldHVybiAxID09PSBvICYmIEUuaXNYTUxEb2MoZSkgfHwgKHQgPSBFLnByb3BGaXhbdF0gfHwgdCwgaSA9IEUucHJvcEhvb2tzW3RdKSwgdm9pZCAwICE9PSBuID8gaSAmJiAic2V0IiBpbiBpICYmIHZvaWQgMCAhPT0gKHIgPSBpLnNldChlLCBuLCB0KSkgPyByIDogZVt0XSA9IG4gOiBpICYmICJnZXQiIGluIGkgJiYgbnVsbCAhPT0gKHIgPSBpLmdldChlLCB0KSkgPyByIDogZVt0XQ0KCQkJfSwgcHJvcEhvb2tzOiB7DQoJCQkJdGFiSW5kZXg6IHsNCgkJCQkJZ2V0OiBmdW5jdGlvbihlKSB7DQoJCQkJCQl2YXIgdCA9IEUuZmluZC5hdHRyKGUsICJ0YWJpbmRleCIpOw0KCQkJCQkJcmV0dXJuIHQgPyBwYXJzZUludCh0LCAxMCkgOiBodC50ZXN0KGUubm9kZU5hbWUpIHx8IGd0LnRlc3QoZS5ub2RlTmFtZSkgJiYgZS5ocmVmID8gMCA6IC0xDQoJCQkJCX0NCgkJCQl9DQoJCQl9LCBwcm9wRml4OiB7ImZvciI6ICJodG1sRm9yIiwgImNsYXNzIjogImNsYXNzTmFtZSJ9DQoJCX0pLCB2Lm9wdFNlbGVjdGVkIHx8IChFLnByb3BIb29rcy5zZWxlY3RlZCA9IHsNCgkJCWdldDogZnVuY3Rpb24oZSkgew0KCQkJCXZhciB0ID0gZS5wYXJlbnROb2RlOw0KCQkJCXJldHVybiB0ICYmIHQucGFyZW50Tm9kZSAmJiB0LnBhcmVudE5vZGUuc2VsZWN0ZWRJbmRleCwgbnVsbA0KCQkJfSwgc2V0OiBmdW5jdGlvbihlKSB7DQoJCQkJdmFyIHQgPSBlLnBhcmVudE5vZGU7DQoJCQkJdCAmJiAodC5zZWxlY3RlZEluZGV4LCB0LnBhcmVudE5vZGUgJiYgdC5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXgpDQoJCQl9DQoJCX0pLCBFLmVhY2goWyJ0YWJJbmRleCIsICJyZWFkT25seSIsICJtYXhMZW5ndGgiLCAiY2VsbFNwYWNpbmciLCAiY2VsbFBhZGRpbmciLCAicm93U3BhbiIsICJjb2xTcGFuIiwgInVzZU1hcCIsICJmcmFtZUJvcmRlciIsICJjb250ZW50RWRpdGFibGUiXSwgZnVuY3Rpb24oKSB7RS5wcm9wRml4W3RoaXMudG9Mb3dlckNhc2UoKV0gPSB0aGlzfSksIEUuZm4uZXh0ZW5kKHsNCgkJCWFkZENsYXNzOiBmdW5jdGlvbih0KSB7DQoJCQkJdmFyIGUsIG4sIHIsIGksIG8sIGE7DQoJCQkJcmV0dXJuIG0odCkgPyB0aGlzLmVhY2goZnVuY3Rpb24oZSkge0UodGhpcykuYWRkQ2xhc3ModC5jYWxsKHRoaXMsIGUsIHZ0KHRoaXMpKSl9KSA6IChlID0gbXQodCkpLmxlbmd0aCA/IHRoaXMuZWFjaChmdW5jdGlvbigpIHsNCgkJCQkJaWYociA9IHZ0KHRoaXMpLCBuID0gMSA9PT0gdGhpcy5ub2RlVHlwZSAmJiAiICIgKyB5dChyKSArICIgIikgew0KCQkJCQkJZm9yKG8gPSAwOyBvIDwgZS5sZW5ndGg7IG8rKykgaSA9IGVbb10sIG4uaW5kZXhPZigiICIgKyBpICsgIiAiKSA8IDAgJiYgKG4gKz0gaSArICIgIik7DQoJCQkJCQlhID0geXQobiksIHIgIT09IGEgJiYgdGhpcy5zZXRBdHRyaWJ1dGUoImNsYXNzIiwgYSkNCgkJCQkJfQ0KCQkJCX0pIDogdGhpcw0KCQkJfSwgcmVtb3ZlQ2xhc3M6IGZ1bmN0aW9uKHQpIHsNCgkJCQl2YXIgZSwgbiwgciwgaSwgbywgYTsNCgkJCQlyZXR1cm4gbSh0KSA/IHRoaXMuZWFjaChmdW5jdGlvbihlKSB7RSh0aGlzKS5yZW1vdmVDbGFzcyh0LmNhbGwodGhpcywgZSwgdnQodGhpcykpKX0pIDogYXJndW1lbnRzLmxlbmd0aCA/IChlID0gbXQodCkpLmxlbmd0aCA/IHRoaXMuZWFjaChmdW5jdGlvbigpIHsNCgkJCQkJaWYociA9IHZ0KHRoaXMpLCBuID0gMSA9PT0gdGhpcy5ub2RlVHlwZSAmJiAiICIgKyB5dChyKSArICIgIikgew0KCQkJCQkJZm9yKG8gPSAwOyBvIDwgZS5sZW5ndGg7IG8rKykgew0KCQkJCQkJCWkgPSBlW29dOw0KCQkJCQkJCXdoaWxlKC0xIDwgbi5pbmRleE9mKCIgIiArIGkgKyAiICIpKSBuID0gbi5yZXBsYWNlKCIgIiArIGkgKyAiICIsICIgIikNCgkJCQkJCX0NCgkJCQkJCWEgPSB5dChuKSwgciAhPT0gYSAmJiB0aGlzLnNldEF0dHJpYnV0ZSgiY2xhc3MiLCBhKQ0KCQkJCQl9DQoJCQkJfSkgOiB0aGlzIDogdGhpcy5hdHRyKCJjbGFzcyIsICIiKQ0KCQkJfSwgdG9nZ2xlQ2xhc3M6IGZ1bmN0aW9uKHQsIG4pIHsNCgkJCQl2YXIgZSwgciwgaSwgbywgYSA9IHR5cGVvZiB0LCBzID0gInN0cmluZyIgPT09IGEgfHwgQXJyYXkuaXNBcnJheSh0KTsNCgkJCQlyZXR1cm4gbSh0KSA/IHRoaXMuZWFjaChmdW5jdGlvbihlKSB7RSh0aGlzKS50b2dnbGVDbGFzcyh0LmNhbGwodGhpcywgZSwgdnQodGhpcyksIG4pLCBuKX0pIDogImJvb2xlYW4iID09IHR5cGVvZiBuICYmIHMgPyBuID8gdGhpcy5hZGRDbGFzcyh0KSA6IHRoaXMucmVtb3ZlQ2xhc3ModCkgOiAoZSA9IG10KHQpLCB0aGlzLmVhY2goZnVuY3Rpb24oKSB7aWYocykgZm9yKG8gPSBFKHRoaXMpLCBpID0gMDsgaSA8IGUubGVuZ3RoOyBpKyspIHIgPSBlW2ldLCBvLmhhc0NsYXNzKHIpID8gby5yZW1vdmVDbGFzcyhyKSA6IG8uYWRkQ2xhc3Mocik7IGVsc2Ugdm9pZCAwICE9PSB0ICYmICJib29sZWFuIiAhPT0gYSB8fCAoKHIgPSB2dCh0aGlzKSkgJiYgWS5zZXQodGhpcywgIl9fY2xhc3NOYW1lX18iLCByKSwgdGhpcy5zZXRBdHRyaWJ1dGUgJiYgdGhpcy5zZXRBdHRyaWJ1dGUoImNsYXNzIiwgciB8fCAhMSA9PT0gdCA/ICIiIDogWS5nZXQodGhpcywgIl9fY2xhc3NOYW1lX18iKSB8fCAiIikpfSkpDQoJCQl9LCBoYXNDbGFzczogZnVuY3Rpb24oZSkgew0KCQkJCXZhciB0LCBuLCByID0gMDsNCgkJCQl0ID0gIiAiICsgZSArICIgIjsNCgkJCQl3aGlsZShuID0gdGhpc1tyKytdKSBpZigxID09PSBuLm5vZGVUeXBlICYmIC0xIDwgKCIgIiArIHl0KHZ0KG4pKSArICIgIikuaW5kZXhPZih0KSkgcmV0dXJuICEwOw0KCQkJCXJldHVybiAhMQ0KCQkJfQ0KCQl9KTsNCgkJdmFyIHh0ID0gL1xyL2c7DQoJCUUuZm4uZXh0ZW5kKHsNCgkJCXZhbDogZnVuY3Rpb24obikgew0KCQkJCXZhciByLCBlLCBpLCB0ID0gdGhpc1swXTsNCgkJCQlyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChpID0gbShuKSwgdGhpcy5lYWNoKGZ1bmN0aW9uKGUpIHsNCgkJCQkJdmFyIHQ7DQoJCQkJCTEgPT09IHRoaXMubm9kZVR5cGUgJiYgKG51bGwgPT0gKHQgPSBpID8gbi5jYWxsKHRoaXMsIGUsIEUodGhpcykudmFsKCkpIDogbikgPyB0ID0gIiIgOiAibnVtYmVyIiA9PSB0eXBlb2YgdCA/IHQgKz0gIiIgOiBBcnJheS5pc0FycmF5KHQpICYmICh0ID0gRS5tYXAodCwgZnVuY3Rpb24oZSkge3JldHVybiBudWxsID09IGUgPyAiIiA6IGUgKyAiIn0pKSwgKHIgPSBFLnZhbEhvb2tzW3RoaXMudHlwZV0gfHwgRS52YWxIb29rc1t0aGlzLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCldKSAmJiAic2V0IiBpbiByICYmIHZvaWQgMCAhPT0gci5zZXQodGhpcywgdCwgInZhbHVlIikgfHwgKHRoaXMudmFsdWUgPSB0KSkNCgkJCQl9KSkgOiB0ID8gKHIgPSBFLnZhbEhvb2tzW3QudHlwZV0gfHwgRS52YWxIb29rc1t0Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCldKSAmJiAiZ2V0IiBpbiByICYmIHZvaWQgMCAhPT0gKGUgPSByLmdldCh0LCAidmFsdWUiKSkgPyBlIDogInN0cmluZyIgPT0gdHlwZW9mIChlID0gdC52YWx1ZSkgPyBlLnJlcGxhY2UoeHQsICIiKSA6IG51bGwgPT0gZSA/ICIiIDogZSA6IHZvaWQgMA0KCQkJfQ0KCQl9KSwgRS5leHRlbmQoew0KCQkJdmFsSG9va3M6IHsNCgkJCQlvcHRpb246IHsNCgkJCQkJZ2V0OiBmdW5jdGlvbihlKSB7DQoJCQkJCQl2YXIgdCA9IEUuZmluZC5hdHRyKGUsICJ2YWx1ZSIpOw0KCQkJCQkJcmV0dXJuIG51bGwgIT0gdCA/IHQgOiB5dChFLnRleHQoZSkpDQoJCQkJCX0NCgkJCQl9LCBzZWxlY3Q6IHsNCgkJCQkJZ2V0OiBmdW5jdGlvbihlKSB7DQoJCQkJCQl2YXIgdCwgbiwgciwgaSA9IGUub3B0aW9ucywgbyA9IGUuc2VsZWN0ZWRJbmRleCwgYSA9ICJzZWxlY3Qtb25lIiA9PT0gZS50eXBlLCBzID0gYSA/IG51bGwgOiBbXSwgdSA9IGEgPyBvICsgMSA6IGkubGVuZ3RoOw0KCQkJCQkJZm9yKHIgPSBvIDwgMCA/IHUgOiBhID8gbyA6IDA7IHIgPCB1OyByKyspIGlmKCgobiA9IGlbcl0pLnNlbGVjdGVkIHx8IHIgPT09IG8pICYmICFuLmRpc2FibGVkICYmICghbi5wYXJlbnROb2RlLmRpc2FibGVkIHx8ICFBKG4ucGFyZW50Tm9kZSwgIm9wdGdyb3VwIikpKSB7DQoJCQkJCQkJaWYodCA9IEUobikudmFsKCksIGEpIHJldHVybiB0Ow0KCQkJCQkJCXMucHVzaCh0KQ0KCQkJCQkJfQ0KCQkJCQkJcmV0dXJuIHMNCgkJCQkJfSwgc2V0OiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJCQl2YXIgbiwgciwgaSA9IGUub3B0aW9ucywgbyA9IEUubWFrZUFycmF5KHQpLCBhID0gaS5sZW5ndGg7DQoJCQkJCQl3aGlsZShhLS0pICgociA9IGlbYV0pLnNlbGVjdGVkID0gLTEgPCBFLmluQXJyYXkoRS52YWxIb29rcy5vcHRpb24uZ2V0KHIpLCBvKSkgJiYgKG4gPSAhMCk7DQoJCQkJCQlyZXR1cm4gbiB8fCAoZS5zZWxlY3RlZEluZGV4ID0gLTEpLCBvDQoJCQkJCX0NCgkJCQl9DQoJCQl9DQoJCX0pLCBFLmVhY2goWyJyYWRpbyIsICJjaGVja2JveCJdLCBmdW5jdGlvbigpIHtFLnZhbEhvb2tzW3RoaXNdID0ge3NldDogZnVuY3Rpb24oZSwgdCkge2lmKEFycmF5LmlzQXJyYXkodCkpIHJldHVybiBlLmNoZWNrZWQgPSAtMSA8IEUuaW5BcnJheShFKGUpLnZhbCgpLCB0KX19LCB2LmNoZWNrT24gfHwgKEUudmFsSG9va3NbdGhpc10uZ2V0ID0gZnVuY3Rpb24oZSkge3JldHVybiBudWxsID09PSBlLmdldEF0dHJpYnV0ZSgidmFsdWUiKSA/ICJvbiIgOiBlLnZhbHVlfSl9KSwgdi5mb2N1c2luID0gIm9uZm9jdXNpbiIgaW4gQzsNCgkJdmFyIGJ0ID0gL14oPzpmb2N1c2luZm9jdXN8Zm9jdXNvdXRibHVyKSQvLCB3dCA9IGZ1bmN0aW9uKGUpIHtlLnN0b3BQcm9wYWdhdGlvbigpfTsNCgkJRS5leHRlbmQoRS5ldmVudCwgew0KCQkJdHJpZ2dlcjogZnVuY3Rpb24oZSwgdCwgbiwgcikgew0KCQkJCXZhciBpLCBvLCBhLCBzLCB1LCBsLCBjLCBmLCBwID0gW24gfHwgU10sIGQgPSB5LmNhbGwoZSwgInR5cGUiKSA/IGUudHlwZSA6IGUsIGggPSB5LmNhbGwoZSwgIm5hbWVzcGFjZSIpID8gZS5uYW1lc3BhY2Uuc3BsaXQoIi4iKSA6IFtdOw0KCQkJCWlmKG8gPSBmID0gYSA9IG4gPSBuIHx8IFMsIDMgIT09IG4ubm9kZVR5cGUgJiYgOCAhPT0gbi5ub2RlVHlwZSAmJiAhYnQudGVzdChkICsgRS5ldmVudC50cmlnZ2VyZWQpICYmICgtMSA8IGQuaW5kZXhPZigiLiIpICYmIChkID0gKGggPSBkLnNwbGl0KCIuIikpLnNoaWZ0KCksIGguc29ydCgpKSwgdSA9IGQuaW5kZXhPZigiOiIpIDwgMCAmJiAib24iICsgZCwgKGUgPSBlW0UuZXhwYW5kb10gPyBlIDogbmV3IEUuRXZlbnQoZCwgIm9iamVjdCIgPT0gdHlwZW9mIGUgJiYgZSkpLmlzVHJpZ2dlciA9IHIgPyAyIDogMywgZS5uYW1lc3BhY2UgPSBoLmpvaW4oIi4iKSwgZS5ybmFtZXNwYWNlID0gZS5uYW1lc3BhY2UgPyBuZXcgUmVnRXhwKCIoXnxcXC4pIiArIGguam9pbigiXFwuKD86LipcXC58KSIpICsgIihcXC58JCkiKSA6IG51bGwsIGUucmVzdWx0ID0gdm9pZCAwLCBlLnRhcmdldCB8fCAoZS50YXJnZXQgPSBuKSwgdCA9IG51bGwgPT0gdCA/IFtlXSA6IEUubWFrZUFycmF5KHQsIFtlXSksIGMgPSBFLmV2ZW50LnNwZWNpYWxbZF0gfHwge30sIHIgfHwgIWMudHJpZ2dlciB8fCAhMSAhPT0gYy50cmlnZ2VyLmFwcGx5KG4sIHQpKSkgew0KCQkJCQlpZighciAmJiAhYy5ub0J1YmJsZSAmJiAheChuKSkgew0KCQkJCQkJZm9yKHMgPSBjLmRlbGVnYXRlVHlwZSB8fCBkLCBidC50ZXN0KHMgKyBkKSB8fCAobyA9IG8ucGFyZW50Tm9kZSk7IG87IG8gPSBvLnBhcmVudE5vZGUpIHAucHVzaChvKSwgYSA9IG87DQoJCQkJCQlhID09PSAobi5vd25lckRvY3VtZW50IHx8IFMpICYmIHAucHVzaChhLmRlZmF1bHRWaWV3IHx8IGEucGFyZW50V2luZG93IHx8IEMpDQoJCQkJCX0NCgkJCQkJaSA9IDA7DQoJCQkJCXdoaWxlKChvID0gcFtpKytdKSAmJiAhZS5pc1Byb3BhZ2F0aW9uU3RvcHBlZCgpKSBmID0gbywgZS50eXBlID0gMSA8IGkgPyBzIDogYy5iaW5kVHlwZSB8fCBkLCAobCA9IChZLmdldChvLCAiZXZlbnRzIikgfHwgT2JqZWN0LmNyZWF0ZShudWxsKSlbZS50eXBlXSAmJiBZLmdldChvLCAiaGFuZGxlIikpICYmIGwuYXBwbHkobywgdCksIChsID0gdSAmJiBvW3VdKSAmJiBsLmFwcGx5ICYmIFYobykgJiYgKGUucmVzdWx0ID0gbC5hcHBseShvLCB0KSwgITEgPT09IGUucmVzdWx0ICYmIGUucHJldmVudERlZmF1bHQoKSk7DQoJCQkJCXJldHVybiBlLnR5cGUgPSBkLCByIHx8IGUuaXNEZWZhdWx0UHJldmVudGVkKCkgfHwgYy5fZGVmYXVsdCAmJiAhMSAhPT0gYy5fZGVmYXVsdC5hcHBseShwLnBvcCgpLCB0KSB8fCAhVihuKSB8fCB1ICYmIG0obltkXSkgJiYgIXgobikgJiYgKChhID0gblt1XSkgJiYgKG5bdV0gPSBudWxsKSwgRS5ldmVudC50cmlnZ2VyZWQgPSBkLCBlLmlzUHJvcGFnYXRpb25TdG9wcGVkKCkgJiYgZi5hZGRFdmVudExpc3RlbmVyKGQsIHd0KSwgbltkXSgpLCBlLmlzUHJvcGFnYXRpb25TdG9wcGVkKCkgJiYgZi5yZW1vdmVFdmVudExpc3RlbmVyKGQsIHd0KSwgRS5ldmVudC50cmlnZ2VyZWQgPSB2b2lkIDAsIGEgJiYgKG5bdV0gPSBhKSksIGUucmVzdWx0DQoJCQkJfQ0KCQkJfSwgc2ltdWxhdGU6IGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQl2YXIgciA9IEUuZXh0ZW5kKG5ldyBFLkV2ZW50LCBuLCB7dHlwZTogZSwgaXNTaW11bGF0ZWQ6ICEwfSk7DQoJCQkJRS5ldmVudC50cmlnZ2VyKHIsIG51bGwsIHQpDQoJCQl9DQoJCX0pLCBFLmZuLmV4dGVuZCh7DQoJCQl0cmlnZ2VyOiBmdW5jdGlvbihlLCB0KSB7cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpIHtFLmV2ZW50LnRyaWdnZXIoZSwgdCwgdGhpcyl9KX0sIHRyaWdnZXJIYW5kbGVyOiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJdmFyIG4gPSB0aGlzWzBdOw0KCQkJCWlmKG4pIHJldHVybiBFLmV2ZW50LnRyaWdnZXIoZSwgdCwgbiwgITApDQoJCQl9DQoJCX0pLCB2LmZvY3VzaW4gfHwgRS5lYWNoKHtmb2N1czogImZvY3VzaW4iLCBibHVyOiAiZm9jdXNvdXQifSwgZnVuY3Rpb24obiwgcikgew0KCQkJdmFyIGkgPSBmdW5jdGlvbihlKSB7RS5ldmVudC5zaW11bGF0ZShyLCBlLnRhcmdldCwgRS5ldmVudC5maXgoZSkpfTsNCgkJCUUuZXZlbnQuc3BlY2lhbFtyXSA9IHsNCgkJCQlzZXR1cDogZnVuY3Rpb24oKSB7DQoJCQkJCXZhciBlID0gdGhpcy5vd25lckRvY3VtZW50IHx8IHRoaXMuZG9jdW1lbnQgfHwgdGhpcywgdCA9IFkuYWNjZXNzKGUsIHIpOw0KCQkJCQl0IHx8IGUuYWRkRXZlbnRMaXN0ZW5lcihuLCBpLCAhMCksIFkuYWNjZXNzKGUsIHIsICh0IHx8IDApICsgMSkNCgkJCQl9LCB0ZWFyZG93bjogZnVuY3Rpb24oKSB7DQoJCQkJCXZhciBlID0gdGhpcy5vd25lckRvY3VtZW50IHx8IHRoaXMuZG9jdW1lbnQgfHwgdGhpcywgdCA9IFkuYWNjZXNzKGUsIHIpIC0gMTsNCgkJCQkJdCA/IFkuYWNjZXNzKGUsIHIsIHQpIDogKGUucmVtb3ZlRXZlbnRMaXN0ZW5lcihuLCBpLCAhMCksIFkucmVtb3ZlKGUsIHIpKQ0KCQkJCX0NCgkJCX0NCgkJfSk7DQoJCXZhciBUdCA9IEMubG9jYXRpb24sIEN0ID0ge2d1aWQ6IERhdGUubm93KCl9LCBTdCA9IC9cPy87DQoJCUUucGFyc2VYTUwgPSBmdW5jdGlvbihlKSB7DQoJCQl2YXIgdCwgbjsNCgkJCWlmKCFlIHx8ICJzdHJpbmciICE9IHR5cGVvZiBlKSByZXR1cm4gbnVsbDsNCgkJCXRyeSB7dCA9IChuZXcgQy5ET01QYXJzZXIpLnBhcnNlRnJvbVN0cmluZyhlLCAidGV4dC94bWwiKX0gY2F0Y2goZSkge30NCgkJCXJldHVybiBuID0gdCAmJiB0LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJwYXJzZXJlcnJvciIpWzBdLCB0ICYmICFuIHx8IEUuZXJyb3IoIkludmFsaWQgWE1MOiAiICsgKG4gPyBFLm1hcChuLmNoaWxkTm9kZXMsIGZ1bmN0aW9uKGUpIHtyZXR1cm4gZS50ZXh0Q29udGVudH0pLmpvaW4oIlxuIikgOiBlKSksIHQNCgkJfTsNCgkJdmFyIEV0ID0gL1xbXF0kLywga3QgPSAvXHI/XG4vZywgQXQgPSAvXig/OnN1Ym1pdHxidXR0b258aW1hZ2V8cmVzZXR8ZmlsZSkkL2ksIE50ID0gL14oPzppbnB1dHxzZWxlY3R8dGV4dGFyZWF8a2V5Z2VuKS9pOw0KDQoJCWZ1bmN0aW9uIGp0KG4sIGUsIHIsIGkpIHsNCgkJCXZhciB0Ow0KCQkJaWYoQXJyYXkuaXNBcnJheShlKSkgRS5lYWNoKGUsIGZ1bmN0aW9uKGUsIHQpIHtyIHx8IEV0LnRlc3QobikgPyBpKG4sIHQpIDoganQobiArICJbIiArICgib2JqZWN0IiA9PSB0eXBlb2YgdCAmJiBudWxsICE9IHQgPyBlIDogIiIpICsgIl0iLCB0LCByLCBpKX0pOyBlbHNlIGlmKHIgfHwgIm9iamVjdCIgIT09IHcoZSkpIGkobiwgZSk7IGVsc2UgZm9yKHQgaW4gZSkganQobiArICJbIiArIHQgKyAiXSIsIGVbdF0sIHIsIGkpDQoJCX0NCg0KCQlFLnBhcmFtID0gZnVuY3Rpb24oZSwgdCkgew0KCQkJdmFyIG4sIHIgPSBbXSwgaSA9IGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQl2YXIgbiA9IG0odCkgPyB0KCkgOiB0Ow0KCQkJCXJbci5sZW5ndGhdID0gZW5jb2RlVVJJQ29tcG9uZW50KGUpICsgIj0iICsgZW5jb2RlVVJJQ29tcG9uZW50KG51bGwgPT0gbiA/ICIiIDogbikNCgkJCX07DQoJCQlpZihudWxsID09IGUpIHJldHVybiAiIjsNCgkJCWlmKEFycmF5LmlzQXJyYXkoZSkgfHwgZS5qcXVlcnkgJiYgIUUuaXNQbGFpbk9iamVjdChlKSkgRS5lYWNoKGUsIGZ1bmN0aW9uKCkge2kodGhpcy5uYW1lLCB0aGlzLnZhbHVlKX0pOyBlbHNlIGZvcihuIGluIGUpIGp0KG4sIGVbbl0sIHQsIGkpOw0KCQkJcmV0dXJuIHIuam9pbigiJiIpDQoJCX0sIEUuZm4uZXh0ZW5kKHsNCgkJCXNlcmlhbGl6ZTogZnVuY3Rpb24oKSB7cmV0dXJuIEUucGFyYW0odGhpcy5zZXJpYWxpemVBcnJheSgpKX0sIHNlcmlhbGl6ZUFycmF5OiBmdW5jdGlvbigpIHsNCgkJCQlyZXR1cm4gdGhpcy5tYXAoZnVuY3Rpb24oKSB7DQoJCQkJCXZhciBlID0gRS5wcm9wKHRoaXMsICJlbGVtZW50cyIpOw0KCQkJCQlyZXR1cm4gZSA/IEUubWFrZUFycmF5KGUpIDogdGhpcw0KCQkJCX0pLmZpbHRlcihmdW5jdGlvbigpIHsNCgkJCQkJdmFyIGUgPSB0aGlzLnR5cGU7DQoJCQkJCXJldHVybiB0aGlzLm5hbWUgJiYgIUUodGhpcykuaXMoIjpkaXNhYmxlZCIpICYmIE50LnRlc3QodGhpcy5ub2RlTmFtZSkgJiYgIUF0LnRlc3QoZSkgJiYgKHRoaXMuY2hlY2tlZCB8fCAhcGUudGVzdChlKSkNCgkJCQl9KS5tYXAoZnVuY3Rpb24oZSwgdCkgew0KCQkJCQl2YXIgbiA9IEUodGhpcykudmFsKCk7DQoJCQkJCXJldHVybiBudWxsID09IG4gPyBudWxsIDogQXJyYXkuaXNBcnJheShuKSA/IEUubWFwKG4sIGZ1bmN0aW9uKGUpIHtyZXR1cm4ge25hbWU6IHQubmFtZSwgdmFsdWU6IGUucmVwbGFjZShrdCwgIlxyXG4iKX19KSA6IHtuYW1lOiB0Lm5hbWUsIHZhbHVlOiBuLnJlcGxhY2Uoa3QsICJcclxuIil9DQoJCQkJfSkuZ2V0KCkNCgkJCX0NCgkJfSk7DQoJCXZhciBEdCA9IC8lMjAvZywgcXQgPSAvIy4qJC8sIEx0ID0gLyhbPyZdKV89W14mXSovLCBIdCA9IC9eKC4qPyk6WyBcdF0qKFteXHJcbl0qKSQvZ20sIE90ID0gL14oPzpHRVR8SEVBRCkkLywgUHQgPSAvXlwvXC8vLCBSdCA9IHt9LCBNdCA9IHt9LCBJdCA9ICIqLyIuY29uY2F0KCIqIiksIFd0ID0gUy5jcmVhdGVFbGVtZW50KCJhIik7DQoNCgkJZnVuY3Rpb24gRnQobykgew0KCQkJcmV0dXJuIGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQkic3RyaW5nIiAhPSB0eXBlb2YgZSAmJiAodCA9IGUsIGUgPSAiKiIpOw0KCQkJCXZhciBuLCByID0gMCwgaSA9IGUudG9Mb3dlckNhc2UoKS5tYXRjaChQKSB8fCBbXTsNCgkJCQlpZihtKHQpKSB3aGlsZShuID0gaVtyKytdKSAiKyIgPT09IG5bMF0gPyAobiA9IG4uc2xpY2UoMSkgfHwgIioiLCAob1tuXSA9IG9bbl0gfHwgW10pLnVuc2hpZnQodCkpIDogKG9bbl0gPSBvW25dIHx8IFtdKS5wdXNoKHQpDQoJCQl9DQoJCX0NCg0KCQlmdW5jdGlvbiAkdCh0LCBpLCBvLCBhKSB7DQoJCQl2YXIgcyA9IHt9LCB1ID0gdCA9PT0gTXQ7DQoNCgkJCWZ1bmN0aW9uIGwoZSkgew0KCQkJCXZhciByOw0KCQkJCXJldHVybiBzW2VdID0gITAsIEUuZWFjaCh0W2VdIHx8IFtdLCBmdW5jdGlvbihlLCB0KSB7DQoJCQkJCXZhciBuID0gdChpLCBvLCBhKTsNCgkJCQkJcmV0dXJuICJzdHJpbmciICE9IHR5cGVvZiBuIHx8IHUgfHwgc1tuXSA/IHUgPyAhKHIgPSBuKSA6IHZvaWQgMCA6IChpLmRhdGFUeXBlcy51bnNoaWZ0KG4pLCBsKG4pLCAhMSkNCgkJCQl9KSwgcg0KCQkJfQ0KDQoJCQlyZXR1cm4gbChpLmRhdGFUeXBlc1swXSkgfHwgIXNbIioiXSAmJiBsKCIqIikNCgkJfQ0KDQoJCWZ1bmN0aW9uIEJ0KGUsIHQpIHsNCgkJCXZhciBuLCByLCBpID0gRS5hamF4U2V0dGluZ3MuZmxhdE9wdGlvbnMgfHwge307DQoJCQlmb3IobiBpbiB0KSB2b2lkIDAgIT09IHRbbl0gJiYgKChpW25dID8gZSA6IHIgfHwgKHIgPSB7fSkpW25dID0gdFtuXSk7DQoJCQlyZXR1cm4gciAmJiBFLmV4dGVuZCghMCwgZSwgciksIGUNCgkJfQ0KDQoJCVd0LmhyZWYgPSBUdC5ocmVmLCBFLmV4dGVuZCh7DQoJCQlhY3RpdmU6IDAsDQoJCQlsYXN0TW9kaWZpZWQ6IHt9LA0KCQkJZXRhZzoge30sDQoJCQlhamF4U2V0dGluZ3M6IHsNCgkJCQl1cmw6IFR0LmhyZWYsDQoJCQkJdHlwZTogIkdFVCIsDQoJCQkJaXNMb2NhbDogL14oPzphYm91dHxhcHB8YXBwLXN0b3JhZ2V8ListZXh0ZW5zaW9ufGZpbGV8cmVzfHdpZGdldCk6JC8udGVzdChUdC5wcm90b2NvbCksDQoJCQkJZ2xvYmFsOiAhMCwNCgkJCQlwcm9jZXNzRGF0YTogITAsDQoJCQkJYXN5bmM6ICEwLA0KCQkJCWNvbnRlbnRUeXBlOiAiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkOyBjaGFyc2V0PVVURi04IiwNCgkJCQlhY2NlcHRzOiB7IioiOiBJdCwgdGV4dDogInRleHQvcGxhaW4iLCBodG1sOiAidGV4dC9odG1sIiwgeG1sOiAiYXBwbGljYXRpb24veG1sLCB0ZXh0L3htbCIsIGpzb246ICJhcHBsaWNhdGlvbi9qc29uLCB0ZXh0L2phdmFzY3JpcHQifSwNCgkJCQljb250ZW50czoge3htbDogL1xieG1sXGIvLCBodG1sOiAvXGJodG1sLywganNvbjogL1xianNvblxiL30sDQoJCQkJcmVzcG9uc2VGaWVsZHM6IHt4bWw6ICJyZXNwb25zZVhNTCIsIHRleHQ6ICJyZXNwb25zZVRleHQiLCBqc29uOiAicmVzcG9uc2VKU09OIn0sDQoJCQkJY29udmVydGVyczogeyIqIHRleHQiOiBTdHJpbmcsICJ0ZXh0IGh0bWwiOiAhMCwgInRleHQganNvbiI6IEpTT04ucGFyc2UsICJ0ZXh0IHhtbCI6IEUucGFyc2VYTUx9LA0KCQkJCWZsYXRPcHRpb25zOiB7dXJsOiAhMCwgY29udGV4dDogITB9DQoJCQl9LA0KCQkJYWpheFNldHVwOiBmdW5jdGlvbihlLCB0KSB7cmV0dXJuIHQgPyBCdChCdChlLCBFLmFqYXhTZXR0aW5ncyksIHQpIDogQnQoRS5hamF4U2V0dGluZ3MsIGUpfSwNCgkJCWFqYXhQcmVmaWx0ZXI6IEZ0KFJ0KSwNCgkJCWFqYXhUcmFuc3BvcnQ6IEZ0KE10KSwNCgkJCWFqYXg6IGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQkib2JqZWN0IiA9PSB0eXBlb2YgZSAmJiAodCA9IGUsIGUgPSB2b2lkIDApLCB0ID0gdCB8fCB7fTsNCgkJCQl2YXIgYywNCgkJCQkgICAgZiwNCgkJCQkgICAgcCwNCgkJCQkgICAgbiwNCgkJCQkgICAgZCwNCgkJCQkgICAgciwNCgkJCQkgICAgaCwNCgkJCQkgICAgZywNCgkJCQkgICAgaSwNCgkJCQkgICAgbywNCgkJCQkgICAgeSA9IEUuYWpheFNldHVwKHt9LCB0KSwNCgkJCQkgICAgdiA9IHkuY29udGV4dCB8fCB5LA0KCQkJCSAgICBtID0geS5jb250ZXh0ICYmICh2Lm5vZGVUeXBlIHx8IHYuanF1ZXJ5KSA/IEUodikgOiBFLmV2ZW50LA0KCQkJCSAgICB4ID0gRS5EZWZlcnJlZCgpLA0KCQkJCSAgICBiID0gRS5DYWxsYmFja3MoIm9uY2UgbWVtb3J5IiksDQoJCQkJICAgIHcgPSB5LnN0YXR1c0NvZGUgfHwge30sDQoJCQkJICAgIGEgPSB7fSwNCgkJCQkgICAgcyA9IHt9LA0KCQkJCSAgICB1ID0gImNhbmNlbGVkIiwNCgkJCQkgICAgVCA9IHsNCgkJCQkJICAgIHJlYWR5U3RhdGU6IDAsDQoJCQkJCSAgICBnZXRSZXNwb25zZUhlYWRlcjogZnVuY3Rpb24oZSkgew0KCQkJCQkJICAgIHZhciB0Ow0KCQkJCQkJICAgIGlmKGgpIHsNCgkJCQkJCQkgICAgaWYoIW4pIHsNCgkJCQkJCQkJICAgIG4gPSB7fTsNCgkJCQkJCQkJICAgIHdoaWxlKHQgPSBIdC5leGVjKHApKSBuW3RbMV0udG9Mb3dlckNhc2UoKSArICIgIl0gPSAoblt0WzFdLnRvTG93ZXJDYXNlKCkgKyAiICJdIHx8IFtdKS5jb25jYXQodFsyXSkNCgkJCQkJCQkgICAgfQ0KCQkJCQkJCSAgICB0ID0gbltlLnRvTG93ZXJDYXNlKCkgKyAiICJdDQoJCQkJCQkgICAgfQ0KCQkJCQkJICAgIHJldHVybiBudWxsID09IHQgPyBudWxsIDogdC5qb2luKCIsICIpDQoJCQkJCSAgICB9LA0KCQkJCQkgICAgZ2V0QWxsUmVzcG9uc2VIZWFkZXJzOiBmdW5jdGlvbigpIHtyZXR1cm4gaCA/IHAgOiBudWxsfSwNCgkJCQkJICAgIHNldFJlcXVlc3RIZWFkZXI6IGZ1bmN0aW9uKGUsIHQpIHtyZXR1cm4gbnVsbCA9PSBoICYmIChlID0gc1tlLnRvTG93ZXJDYXNlKCldID0gc1tlLnRvTG93ZXJDYXNlKCldIHx8IGUsIGFbZV0gPSB0KSwgdGhpc30sDQoJCQkJCSAgICBvdmVycmlkZU1pbWVUeXBlOiBmdW5jdGlvbihlKSB7cmV0dXJuIG51bGwgPT0gaCAmJiAoeS5taW1lVHlwZSA9IGUpLCB0aGlzfSwNCgkJCQkJICAgIHN0YXR1c0NvZGU6IGZ1bmN0aW9uKGUpIHsNCgkJCQkJCSAgICB2YXIgdDsNCgkJCQkJCSAgICBpZihlKSBpZihoKSBULmFsd2F5cyhlW1Quc3RhdHVzXSk7IGVsc2UgZm9yKHQgaW4gZSkgd1t0XSA9IFt3W3RdLCBlW3RdXTsNCgkJCQkJCSAgICByZXR1cm4gdGhpcw0KCQkJCQkgICAgfSwNCgkJCQkJICAgIGFib3J0OiBmdW5jdGlvbihlKSB7DQoJCQkJCQkgICAgdmFyIHQgPSBlIHx8IHU7DQoJCQkJCQkgICAgcmV0dXJuIGMgJiYgYy5hYm9ydCh0KSwgbCgwLCB0KSwgdGhpcw0KCQkJCQkgICAgfQ0KCQkJCSAgICB9Ow0KCQkJCWlmKHgucHJvbWlzZShUKSwgeS51cmwgPSAoKGUgfHwgeS51cmwgfHwgVHQuaHJlZikgKyAiIikucmVwbGFjZShQdCwgVHQucHJvdG9jb2wgKyAiLy8iKSwgeS50eXBlID0gdC5tZXRob2QgfHwgdC50eXBlIHx8IHkubWV0aG9kIHx8IHkudHlwZSwgeS5kYXRhVHlwZXMgPSAoeS5kYXRhVHlwZSB8fCAiKiIpLnRvTG93ZXJDYXNlKCkubWF0Y2goUCkgfHwgWyIiXSwgbnVsbCA9PSB5LmNyb3NzRG9tYWluKSB7DQoJCQkJCXIgPSBTLmNyZWF0ZUVsZW1lbnQoImEiKTsNCgkJCQkJdHJ5IHtyLmhyZWYgPSB5LnVybCwgci5ocmVmID0gci5ocmVmLCB5LmNyb3NzRG9tYWluID0gV3QucHJvdG9jb2wgKyAiLy8iICsgV3QuaG9zdCAhPSByLnByb3RvY29sICsgIi8vIiArIHIuaG9zdH0gY2F0Y2goZSkge3kuY3Jvc3NEb21haW4gPSAhMH0NCgkJCQl9DQoJCQkJaWYoeS5kYXRhICYmIHkucHJvY2Vzc0RhdGEgJiYgInN0cmluZyIgIT0gdHlwZW9mIHkuZGF0YSAmJiAoeS5kYXRhID0gRS5wYXJhbSh5LmRhdGEsIHkudHJhZGl0aW9uYWwpKSwgJHQoUnQsIHksIHQsIFQpLCBoKSByZXR1cm4gVDsNCgkJCQlmb3IoaSBpbiAoZyA9IEUuZXZlbnQgJiYgeS5nbG9iYWwpICYmIDAgPT0gRS5hY3RpdmUrKyAmJiBFLmV2ZW50LnRyaWdnZXIoImFqYXhTdGFydCIpLCB5LnR5cGUgPSB5LnR5cGUudG9VcHBlckNhc2UoKSwgeS5oYXNDb250ZW50ID0gIU90LnRlc3QoeS50eXBlKSwgZiA9IHkudXJsLnJlcGxhY2UocXQsICIiKSwgeS5oYXNDb250ZW50ID8geS5kYXRhICYmIHkucHJvY2Vzc0RhdGEgJiYgMCA9PT0gKHkuY29udGVudFR5cGUgfHwgIiIpLmluZGV4T2YoImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCIpICYmICh5LmRhdGEgPSB5LmRhdGEucmVwbGFjZShEdCwgIisiKSkgOiAobyA9IHkudXJsLnNsaWNlKGYubGVuZ3RoKSwgeS5kYXRhICYmICh5LnByb2Nlc3NEYXRhIHx8ICJzdHJpbmciID09IHR5cGVvZiB5LmRhdGEpICYmIChmICs9IChTdC50ZXN0KGYpID8gIiYiIDogIj8iKSArIHkuZGF0YSwgZGVsZXRlIHkuZGF0YSksICExID09PSB5LmNhY2hlICYmIChmID0gZi5yZXBsYWNlKEx0LCAiJDEiKSwgbyA9IChTdC50ZXN0KGYpID8gIiYiIDogIj8iKSArICJfPSIgKyBDdC5ndWlkKysgKyBvKSwgeS51cmwgPSBmICsgbyksIHkuaWZNb2RpZmllZCAmJiAoRS5sYXN0TW9kaWZpZWRbZl0gJiYgVC5zZXRSZXF1ZXN0SGVhZGVyKCJJZi1Nb2RpZmllZC1TaW5jZSIsIEUubGFzdE1vZGlmaWVkW2ZdKSwgRS5ldGFnW2ZdICYmIFQuc2V0UmVxdWVzdEhlYWRlcigiSWYtTm9uZS1NYXRjaCIsIEUuZXRhZ1tmXSkpLCAoeS5kYXRhICYmIHkuaGFzQ29udGVudCAmJiAhMSAhPT0geS5jb250ZW50VHlwZSB8fCB0LmNvbnRlbnRUeXBlKSAmJiBULnNldFJlcXVlc3RIZWFkZXIoIkNvbnRlbnQtVHlwZSIsIHkuY29udGVudFR5cGUpLCBULnNldFJlcXVlc3RIZWFkZXIoIkFjY2VwdCIsIHkuZGF0YVR5cGVzWzBdICYmIHkuYWNjZXB0c1t5LmRhdGFUeXBlc1swXV0gPyB5LmFjY2VwdHNbeS5kYXRhVHlwZXNbMF1dICsgKCIqIiAhPT0geS5kYXRhVHlwZXNbMF0gPyAiLCAiICsgSXQgKyAiOyBxPTAuMDEiIDogIiIpIDogeS5hY2NlcHRzWyIqIl0pLCB5LmhlYWRlcnMpIFQuc2V0UmVxdWVzdEhlYWRlcihpLCB5LmhlYWRlcnNbaV0pOw0KCQkJCWlmKHkuYmVmb3JlU2VuZCAmJiAoITEgPT09IHkuYmVmb3JlU2VuZC5jYWxsKHYsIFQsIHkpIHx8IGgpKSByZXR1cm4gVC5hYm9ydCgpOw0KCQkJCWlmKHUgPSAiYWJvcnQiLCBiLmFkZCh5LmNvbXBsZXRlKSwgVC5kb25lKHkuc3VjY2VzcyksIFQuZmFpbCh5LmVycm9yKSwgYyA9ICR0KE10LCB5LCB0LCBUKSkgew0KCQkJCQlpZihULnJlYWR5U3RhdGUgPSAxLCBnICYmIG0udHJpZ2dlcigiYWpheFNlbmQiLCBbVCwgeV0pLCBoKSByZXR1cm4gVDsNCgkJCQkJeS5hc3luYyAmJiAwIDwgeS50aW1lb3V0ICYmIChkID0gQy5zZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1QuYWJvcnQoInRpbWVvdXQiKX0sIHkudGltZW91dCkpOw0KCQkJCQl0cnkge2ggPSAhMSwgYy5zZW5kKGEsIGwpfSBjYXRjaChlKSB7DQoJCQkJCQlpZihoKSB0aHJvdyBlOw0KCQkJCQkJbCgtMSwgZSkNCgkJCQkJfQ0KCQkJCX0gZWxzZSBsKC0xLCAiTm8gVHJhbnNwb3J0Iik7DQoNCgkJCQlmdW5jdGlvbiBsKGUsIHQsIG4sIHIpIHsNCgkJCQkJdmFyIGksIG8sIGEsIHMsIHUsIGwgPSB0Ow0KCQkJCQloIHx8IChoID0gITAsIGQgJiYgQy5jbGVhclRpbWVvdXQoZCksIGMgPSB2b2lkIDAsIHAgPSByIHx8ICIiLCBULnJlYWR5U3RhdGUgPSAwIDwgZSA/IDQgOiAwLCBpID0gMjAwIDw9IGUgJiYgZSA8IDMwMCB8fCAzMDQgPT09IGUsIG4gJiYgKHMgPSBmdW5jdGlvbihlLCB0LCBuKSB7DQoJCQkJCQl2YXIgciwgaSwgbywgYSwgcyA9IGUuY29udGVudHMsIHUgPSBlLmRhdGFUeXBlczsNCgkJCQkJCXdoaWxlKCIqIiA9PT0gdVswXSkgdS5zaGlmdCgpLCB2b2lkIDAgPT09IHIgJiYgKHIgPSBlLm1pbWVUeXBlIHx8IHQuZ2V0UmVzcG9uc2VIZWFkZXIoIkNvbnRlbnQtVHlwZSIpKTsNCgkJCQkJCWlmKHIpIGZvcihpIGluIHMpIGlmKHNbaV0gJiYgc1tpXS50ZXN0KHIpKSB7DQoJCQkJCQkJdS51bnNoaWZ0KGkpOw0KCQkJCQkJCWJyZWFrDQoJCQkJCQl9DQoJCQkJCQlpZih1WzBdIGluIG4pIG8gPSB1WzBdOyBlbHNlIHsNCgkJCQkJCQlmb3IoaSBpbiBuKSB7DQoJCQkJCQkJCWlmKCF1WzBdIHx8IGUuY29udmVydGVyc1tpICsgIiAiICsgdVswXV0pIHsNCgkJCQkJCQkJCW8gPSBpOw0KCQkJCQkJCQkJYnJlYWsNCgkJCQkJCQkJfQ0KCQkJCQkJCQlhIHx8IChhID0gaSkNCgkJCQkJCQl9DQoJCQkJCQkJbyA9IG8gfHwgYQ0KCQkJCQkJfQ0KCQkJCQkJaWYobykgcmV0dXJuIG8gIT09IHVbMF0gJiYgdS51bnNoaWZ0KG8pLCBuW29dDQoJCQkJCX0oeSwgVCwgbikpLCAhaSAmJiAtMSA8IEUuaW5BcnJheSgic2NyaXB0IiwgeS5kYXRhVHlwZXMpICYmIEUuaW5BcnJheSgianNvbiIsIHkuZGF0YVR5cGVzKSA8IDAgJiYgKHkuY29udmVydGVyc1sidGV4dCBzY3JpcHQiXSA9IGZ1bmN0aW9uKCkge30pLCBzID0gZnVuY3Rpb24oZSwgdCwgbiwgcikgew0KCQkJCQkJdmFyIGksIG8sIGEsIHMsIHUsIGwgPSB7fSwgYyA9IGUuZGF0YVR5cGVzLnNsaWNlKCk7DQoJCQkJCQlpZihjWzFdKSBmb3IoYSBpbiBlLmNvbnZlcnRlcnMpIGxbYS50b0xvd2VyQ2FzZSgpXSA9IGUuY29udmVydGVyc1thXTsNCgkJCQkJCW8gPSBjLnNoaWZ0KCk7DQoJCQkJCQl3aGlsZShvKSBpZihlLnJlc3BvbnNlRmllbGRzW29dICYmIChuW2UucmVzcG9uc2VGaWVsZHNbb11dID0gdCksICF1ICYmIHIgJiYgZS5kYXRhRmlsdGVyICYmICh0ID0gZS5kYXRhRmlsdGVyKHQsIGUuZGF0YVR5cGUpKSwgdSA9IG8sIG8gPSBjLnNoaWZ0KCkpIGlmKCIqIiA9PT0gbykgbyA9IHU7IGVsc2UgaWYoIioiICE9PSB1ICYmIHUgIT09IG8pIHsNCgkJCQkJCQlpZighKGEgPSBsW3UgKyAiICIgKyBvXSB8fCBsWyIqICIgKyBvXSkpIGZvcihpIGluIGwpIGlmKChzID0gaS5zcGxpdCgiICIpKVsxXSA9PT0gbyAmJiAoYSA9IGxbdSArICIgIiArIHNbMF1dIHx8IGxbIiogIiArIHNbMF1dKSkgew0KCQkJCQkJCQkhMCA9PT0gYSA/IGEgPSBsW2ldIDogITAgIT09IGxbaV0gJiYgKG8gPSBzWzBdLCBjLnVuc2hpZnQoc1sxXSkpOw0KCQkJCQkJCQlicmVhaw0KCQkJCQkJCX0NCgkJCQkJCQlpZighMCAhPT0gYSkgaWYoYSAmJiBlWyJ0aHJvd3MiXSkgdCA9IGEodCk7IGVsc2UgdHJ5IHt0ID0gYSh0KX0gY2F0Y2goZSkge3JldHVybiB7c3RhdGU6ICJwYXJzZXJlcnJvciIsIGVycm9yOiBhID8gZSA6ICJObyBjb252ZXJzaW9uIGZyb20gIiArIHUgKyAiIHRvICIgKyBvfX0NCgkJCQkJCX0NCgkJCQkJCXJldHVybiB7c3RhdGU6ICJzdWNjZXNzIiwgZGF0YTogdH0NCgkJCQkJfSh5LCBzLCBULCBpKSwgaSA/ICh5LmlmTW9kaWZpZWQgJiYgKCh1ID0gVC5nZXRSZXNwb25zZUhlYWRlcigiTGFzdC1Nb2RpZmllZCIpKSAmJiAoRS5sYXN0TW9kaWZpZWRbZl0gPSB1KSwgKHUgPSBULmdldFJlc3BvbnNlSGVhZGVyKCJldGFnIikpICYmIChFLmV0YWdbZl0gPSB1KSksIDIwNCA9PT0gZSB8fCAiSEVBRCIgPT09IHkudHlwZSA/IGwgPSAibm9jb250ZW50IiA6IDMwNCA9PT0gZSA/IGwgPSAibm90bW9kaWZpZWQiIDogKGwgPSBzLnN0YXRlLCBvID0gcy5kYXRhLCBpID0gIShhID0gcy5lcnJvcikpKSA6IChhID0gbCwgIWUgJiYgbCB8fCAobCA9ICJlcnJvciIsIGUgPCAwICYmIChlID0gMCkpKSwgVC5zdGF0dXMgPSBlLCBULnN0YXR1c1RleHQgPSAodCB8fCBsKSArICIiLCBpID8geC5yZXNvbHZlV2l0aCh2LCBbbywgbCwgVF0pIDogeC5yZWplY3RXaXRoKHYsIFtULCBsLCBhXSksIFQuc3RhdHVzQ29kZSh3KSwgdyA9IHZvaWQgMCwgZyAmJiBtLnRyaWdnZXIoaSA/ICJhamF4U3VjY2VzcyIgOiAiYWpheEVycm9yIiwgW1QsIHksIGkgPyBvIDogYV0pLCBiLmZpcmVXaXRoKHYsIFtULCBsXSksIGcgJiYgKG0udHJpZ2dlcigiYWpheENvbXBsZXRlIiwgW1QsIHldKSwgLS1FLmFjdGl2ZSB8fCBFLmV2ZW50LnRyaWdnZXIoImFqYXhTdG9wIikpKQ0KCQkJCX0NCg0KCQkJCXJldHVybiBUDQoJCQl9LA0KCQkJZ2V0SlNPTjogZnVuY3Rpb24oZSwgdCwgbikge3JldHVybiBFLmdldChlLCB0LCBuLCAianNvbiIpfSwNCgkJCWdldFNjcmlwdDogZnVuY3Rpb24oZSwgdCkge3JldHVybiBFLmdldChlLCB2b2lkIDAsIHQsICJzY3JpcHQiKX0NCgkJfSksIEUuZWFjaChbImdldCIsICJwb3N0Il0sIGZ1bmN0aW9uKGUsIGkpIHtFW2ldID0gZnVuY3Rpb24oZSwgdCwgbiwgcikge3JldHVybiBtKHQpICYmIChyID0gciB8fCBuLCBuID0gdCwgdCA9IHZvaWQgMCksIEUuYWpheChFLmV4dGVuZCh7dXJsOiBlLCB0eXBlOiBpLCBkYXRhVHlwZTogciwgZGF0YTogdCwgc3VjY2Vzczogbn0sIEUuaXNQbGFpbk9iamVjdChlKSAmJiBlKSl9fSksIEUuYWpheFByZWZpbHRlcihmdW5jdGlvbihlKSB7DQoJCQl2YXIgdDsNCgkJCWZvcih0IGluIGUuaGVhZGVycykgImNvbnRlbnQtdHlwZSIgPT09IHQudG9Mb3dlckNhc2UoKSAmJiAoZS5jb250ZW50VHlwZSA9IGUuaGVhZGVyc1t0XSB8fCAiIikNCgkJfSksIEUuX2V2YWxVcmwgPSBmdW5jdGlvbihlLCB0LCBuKSB7cmV0dXJuIEUuYWpheCh7dXJsOiBlLCB0eXBlOiAiR0VUIiwgZGF0YVR5cGU6ICJzY3JpcHQiLCBjYWNoZTogITAsIGFzeW5jOiAhMSwgZ2xvYmFsOiAhMSwgY29udmVydGVyczogeyJ0ZXh0IHNjcmlwdCI6IGZ1bmN0aW9uKCkge319LCBkYXRhRmlsdGVyOiBmdW5jdGlvbihlKSB7RS5nbG9iYWxFdmFsKGUsIHQsIG4pfX0pfSwgRS5mbi5leHRlbmQoew0KCQkJd3JhcEFsbDogZnVuY3Rpb24oZSkgew0KCQkJCXZhciB0Ow0KCQkJCXJldHVybiB0aGlzWzBdICYmIChtKGUpICYmIChlID0gZS5jYWxsKHRoaXNbMF0pKSwgdCA9IEUoZSwgdGhpc1swXS5vd25lckRvY3VtZW50KS5lcSgwKS5jbG9uZSghMCksIHRoaXNbMF0ucGFyZW50Tm9kZSAmJiB0Lmluc2VydEJlZm9yZSh0aGlzWzBdKSwgdC5tYXAoZnVuY3Rpb24oKSB7DQoJCQkJCXZhciBlID0gdGhpczsNCgkJCQkJd2hpbGUoZS5maXJzdEVsZW1lbnRDaGlsZCkgZSA9IGUuZmlyc3RFbGVtZW50Q2hpbGQ7DQoJCQkJCXJldHVybiBlDQoJCQkJfSkuYXBwZW5kKHRoaXMpKSwgdGhpcw0KCQkJfSwgd3JhcElubmVyOiBmdW5jdGlvbihuKSB7DQoJCQkJcmV0dXJuIG0obikgPyB0aGlzLmVhY2goZnVuY3Rpb24oZSkge0UodGhpcykud3JhcElubmVyKG4uY2FsbCh0aGlzLCBlKSl9KSA6IHRoaXMuZWFjaChmdW5jdGlvbigpIHsNCgkJCQkJdmFyIGUgPSBFKHRoaXMpLCB0ID0gZS5jb250ZW50cygpOw0KCQkJCQl0Lmxlbmd0aCA/IHQud3JhcEFsbChuKSA6IGUuYXBwZW5kKG4pDQoJCQkJfSkNCgkJCX0sIHdyYXA6IGZ1bmN0aW9uKHQpIHsNCgkJCQl2YXIgbiA9IG0odCk7DQoJCQkJcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbihlKSB7RSh0aGlzKS53cmFwQWxsKG4gPyB0LmNhbGwodGhpcywgZSkgOiB0KX0pDQoJCQl9LCB1bndyYXA6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gdGhpcy5wYXJlbnQoZSkubm90KCJib2R5IikuZWFjaChmdW5jdGlvbigpIHtFKHRoaXMpLnJlcGxhY2VXaXRoKHRoaXMuY2hpbGROb2Rlcyl9KSwgdGhpc30NCgkJfSksIEUuZXhwci5wc2V1ZG9zLmhpZGRlbiA9IGZ1bmN0aW9uKGUpIHtyZXR1cm4gIUUuZXhwci5wc2V1ZG9zLnZpc2libGUoZSl9LCBFLmV4cHIucHNldWRvcy52aXNpYmxlID0gZnVuY3Rpb24oZSkge3JldHVybiAhIShlLm9mZnNldFdpZHRoIHx8IGUub2Zmc2V0SGVpZ2h0IHx8IGUuZ2V0Q2xpZW50UmVjdHMoKS5sZW5ndGgpfSwgRS5hamF4U2V0dGluZ3MueGhyID0gZnVuY3Rpb24oKSB7dHJ5IHtyZXR1cm4gbmV3IEMuWE1MSHR0cFJlcXVlc3R9IGNhdGNoKGUpIHt9fTsNCgkJdmFyIF90ID0gezA6IDIwMCwgMTIyMzogMjA0fSwgenQgPSBFLmFqYXhTZXR0aW5ncy54aHIoKTsNCgkJdi5jb3JzID0gISF6dCAmJiAid2l0aENyZWRlbnRpYWxzIiBpbiB6dCwgdi5hamF4ID0genQgPSAhIXp0LCBFLmFqYXhUcmFuc3BvcnQoZnVuY3Rpb24oaSkgew0KCQkJdmFyIG8sIGE7DQoJCQlpZih2LmNvcnMgfHwgenQgJiYgIWkuY3Jvc3NEb21haW4pIHJldHVybiB7DQoJCQkJc2VuZDogZnVuY3Rpb24oZSwgdCkgew0KCQkJCQl2YXIgbiwgciA9IGkueGhyKCk7DQoJCQkJCWlmKHIub3BlbihpLnR5cGUsIGkudXJsLCBpLmFzeW5jLCBpLnVzZXJuYW1lLCBpLnBhc3N3b3JkKSwgaS54aHJGaWVsZHMpIGZvcihuIGluIGkueGhyRmllbGRzKSByW25dID0gaS54aHJGaWVsZHNbbl07DQoJCQkJCWZvcihuIGluIGkubWltZVR5cGUgJiYgci5vdmVycmlkZU1pbWVUeXBlICYmIHIub3ZlcnJpZGVNaW1lVHlwZShpLm1pbWVUeXBlKSwgaS5jcm9zc0RvbWFpbiB8fCBlWyJYLVJlcXVlc3RlZC1XaXRoIl0gfHwgKGVbIlgtUmVxdWVzdGVkLVdpdGgiXSA9ICJYTUxIdHRwUmVxdWVzdCIpLCBlKSByLnNldFJlcXVlc3RIZWFkZXIobiwgZVtuXSk7DQoJCQkJCW8gPSBmdW5jdGlvbihlKSB7cmV0dXJuIGZ1bmN0aW9uKCkge28gJiYgKG8gPSBhID0gci5vbmxvYWQgPSByLm9uZXJyb3IgPSByLm9uYWJvcnQgPSByLm9udGltZW91dCA9IHIub25yZWFkeXN0YXRlY2hhbmdlID0gbnVsbCwgImFib3J0IiA9PT0gZSA/IHIuYWJvcnQoKSA6ICJlcnJvciIgPT09IGUgPyAibnVtYmVyIiAhPSB0eXBlb2Ygci5zdGF0dXMgPyB0KDAsICJlcnJvciIpIDogdChyLnN0YXR1cywgci5zdGF0dXNUZXh0KSA6IHQoX3Rbci5zdGF0dXNdIHx8IHIuc3RhdHVzLCByLnN0YXR1c1RleHQsICJ0ZXh0IiAhPT0gKHIucmVzcG9uc2VUeXBlIHx8ICJ0ZXh0IikgfHwgInN0cmluZyIgIT0gdHlwZW9mIHIucmVzcG9uc2VUZXh0ID8ge2JpbmFyeTogci5yZXNwb25zZX0gOiB7dGV4dDogci5yZXNwb25zZVRleHR9LCByLmdldEFsbFJlc3BvbnNlSGVhZGVycygpKSl9fSwgci5vbmxvYWQgPSBvKCksIGEgPSByLm9uZXJyb3IgPSByLm9udGltZW91dCA9IG8oImVycm9yIiksIHZvaWQgMCAhPT0gci5vbmFib3J0ID8gci5vbmFib3J0ID0gYSA6IHIub25yZWFkeXN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7NCA9PT0gci5yZWFkeVN0YXRlICYmIEMuc2V0VGltZW91dChmdW5jdGlvbigpIHtvICYmIGEoKX0pfSwgbyA9IG8oImFib3J0Iik7DQoJCQkJCXRyeSB7ci5zZW5kKGkuaGFzQ29udGVudCAmJiBpLmRhdGEgfHwgbnVsbCl9IGNhdGNoKGUpIHtpZihvKSB0aHJvdyBlfQ0KCQkJCX0sIGFib3J0OiBmdW5jdGlvbigpIHtvICYmIG8oKX0NCgkJCX0NCgkJfSksIEUuYWpheFByZWZpbHRlcihmdW5jdGlvbihlKSB7ZS5jcm9zc0RvbWFpbiAmJiAoZS5jb250ZW50cy5zY3JpcHQgPSAhMSl9KSwgRS5hamF4U2V0dXAoew0KCQkJYWNjZXB0czoge3NjcmlwdDogInRleHQvamF2YXNjcmlwdCwgYXBwbGljYXRpb24vamF2YXNjcmlwdCwgYXBwbGljYXRpb24vZWNtYXNjcmlwdCwgYXBwbGljYXRpb24veC1lY21hc2NyaXB0In0sDQoJCQljb250ZW50czoge3NjcmlwdDogL1xiKD86amF2YXxlY21hKXNjcmlwdFxiL30sDQoJCQljb252ZXJ0ZXJzOiB7InRleHQgc2NyaXB0IjogZnVuY3Rpb24oZSkge3JldHVybiBFLmdsb2JhbEV2YWwoZSksIGV9fQ0KCQl9KSwgRS5hamF4UHJlZmlsdGVyKCJzY3JpcHQiLCBmdW5jdGlvbihlKSB7dm9pZCAwID09PSBlLmNhY2hlICYmIChlLmNhY2hlID0gITEpLCBlLmNyb3NzRG9tYWluICYmIChlLnR5cGUgPSAiR0VUIil9KSwgRS5hamF4VHJhbnNwb3J0KCJzY3JpcHQiLCBmdW5jdGlvbihuKSB7DQoJCQl2YXIgciwgaTsNCgkJCWlmKG4uY3Jvc3NEb21haW4gfHwgbi5zY3JpcHRBdHRycykgcmV0dXJuIHsNCgkJCQlzZW5kOiBmdW5jdGlvbihlLCB0KSB7ciA9IEUoIjxzY3JpcHQ+IikuYXR0cihuLnNjcmlwdEF0dHJzIHx8IHt9KS5wcm9wKHtjaGFyc2V0OiBuLnNjcmlwdENoYXJzZXQsIHNyYzogbi51cmx9KS5vbigibG9hZCBlcnJvciIsIGkgPSBmdW5jdGlvbihlKSB7ci5yZW1vdmUoKSwgaSA9IG51bGwsIGUgJiYgdCgiZXJyb3IiID09PSBlLnR5cGUgPyA0MDQgOiAyMDAsIGUudHlwZSl9KSwgUy5oZWFkLmFwcGVuZENoaWxkKHJbMF0pfSwNCgkJCQlhYm9ydDogZnVuY3Rpb24oKSB7aSAmJiBpKCl9DQoJCQl9DQoJCX0pOw0KCQl2YXIgVXQsIFh0ID0gW10sIFZ0ID0gLyg9KVw/KD89JnwkKXxcP1w/LzsNCgkJRS5hamF4U2V0dXAoew0KCQkJanNvbnA6ICJjYWxsYmFjayIsIGpzb25wQ2FsbGJhY2s6IGZ1bmN0aW9uKCkgew0KCQkJCXZhciBlID0gWHQucG9wKCkgfHwgRS5leHBhbmRvICsgIl8iICsgQ3QuZ3VpZCsrOw0KCQkJCXJldHVybiB0aGlzW2VdID0gITAsIGUNCgkJCX0NCgkJfSksIEUuYWpheFByZWZpbHRlcigianNvbiBqc29ucCIsIGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCXZhciByLCBpLCBvLCBhID0gITEgIT09IGUuanNvbnAgJiYgKFZ0LnRlc3QoZS51cmwpID8gInVybCIgOiAic3RyaW5nIiA9PSB0eXBlb2YgZS5kYXRhICYmIDAgPT09IChlLmNvbnRlbnRUeXBlIHx8ICIiKS5pbmRleE9mKCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQiKSAmJiBWdC50ZXN0KGUuZGF0YSkgJiYgImRhdGEiKTsNCgkJCWlmKGEgfHwgImpzb25wIiA9PT0gZS5kYXRhVHlwZXNbMF0pIHJldHVybiByID0gZS5qc29ucENhbGxiYWNrID0gbShlLmpzb25wQ2FsbGJhY2spID8gZS5qc29ucENhbGxiYWNrKCkgOiBlLmpzb25wQ2FsbGJhY2ssIGEgPyBlW2FdID0gZVthXS5yZXBsYWNlKFZ0LCAiJDEiICsgcikgOiAhMSAhPT0gZS5qc29ucCAmJiAoZS51cmwgKz0gKFN0LnRlc3QoZS51cmwpID8gIiYiIDogIj8iKSArIGUuanNvbnAgKyAiPSIgKyByKSwgZS5jb252ZXJ0ZXJzWyJzY3JpcHQganNvbiJdID0gZnVuY3Rpb24oKSB7cmV0dXJuIG8gfHwgRS5lcnJvcihyICsgIiB3YXMgbm90IGNhbGxlZCIpLCBvWzBdfSwgZS5kYXRhVHlwZXNbMF0gPSAianNvbiIsIGkgPSBDW3JdLCBDW3JdID0gZnVuY3Rpb24oKSB7byA9IGFyZ3VtZW50c30sIG4uYWx3YXlzKGZ1bmN0aW9uKCkge3ZvaWQgMCA9PT0gaSA/IEUoQykucmVtb3ZlUHJvcChyKSA6IENbcl0gPSBpLCBlW3JdICYmIChlLmpzb25wQ2FsbGJhY2sgPSB0Lmpzb25wQ2FsbGJhY2ssIFh0LnB1c2gocikpLCBvICYmIG0oaSkgJiYgaShvWzBdKSwgbyA9IGkgPSB2b2lkIDB9KSwgInNjcmlwdCINCgkJfSksIHYuY3JlYXRlSFRNTERvY3VtZW50ID0gKChVdCA9IFMuaW1wbGVtZW50YXRpb24uY3JlYXRlSFRNTERvY3VtZW50KCIiKS5ib2R5KS5pbm5lckhUTUwgPSAiPGZvcm0+PC9mb3JtPjxmb3JtPjwvZm9ybT4iLCAyID09PSBVdC5jaGlsZE5vZGVzLmxlbmd0aCksIEUucGFyc2VIVE1MID0gZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJcmV0dXJuICJzdHJpbmciICE9IHR5cGVvZiBlID8gW10gOiAoImJvb2xlYW4iID09IHR5cGVvZiB0ICYmIChuID0gdCwgdCA9ICExKSwgdCB8fCAodi5jcmVhdGVIVE1MRG9jdW1lbnQgPyAoKHIgPSAodCA9IFMuaW1wbGVtZW50YXRpb24uY3JlYXRlSFRNTERvY3VtZW50KCIiKSkuY3JlYXRlRWxlbWVudCgiYmFzZSIpKS5ocmVmID0gUy5sb2NhdGlvbi5ocmVmLCB0LmhlYWQuYXBwZW5kQ2hpbGQocikpIDogdCA9IFMpLCBvID0gIW4gJiYgW10sIChpID0gTi5leGVjKGUpKSA/IFt0LmNyZWF0ZUVsZW1lbnQoaVsxXSldIDogKGkgPSB4ZShbZV0sIHQsIG8pLCBvICYmIG8ubGVuZ3RoICYmIEUobykucmVtb3ZlKCksIEUubWVyZ2UoW10sIGkuY2hpbGROb2RlcykpKTsNCgkJCXZhciByLCBpLCBvDQoJCX0sIEUuZm4ubG9hZCA9IGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCXZhciByLCBpLCBvLCBhID0gdGhpcywgcyA9IGUuaW5kZXhPZigiICIpOw0KCQkJcmV0dXJuIC0xIDwgcyAmJiAociA9IHl0KGUuc2xpY2UocykpLCBlID0gZS5zbGljZSgwLCBzKSksIG0odCkgPyAobiA9IHQsIHQgPSB2b2lkIDApIDogdCAmJiAib2JqZWN0IiA9PSB0eXBlb2YgdCAmJiAoaSA9ICJQT1NUIiksIDAgPCBhLmxlbmd0aCAmJiBFLmFqYXgoew0KCQkJCXVybDogZSwNCgkJCQl0eXBlOiBpIHx8ICJHRVQiLA0KCQkJCWRhdGFUeXBlOiAiaHRtbCIsDQoJCQkJZGF0YTogdA0KCQkJfSkuZG9uZShmdW5jdGlvbihlKSB7byA9IGFyZ3VtZW50cywgYS5odG1sKHIgPyBFKCI8ZGl2PiIpLmFwcGVuZChFLnBhcnNlSFRNTChlKSkuZmluZChyKSA6IGUpfSkuYWx3YXlzKG4gJiYgZnVuY3Rpb24oZSwgdCkge2EuZWFjaChmdW5jdGlvbigpIHtuLmFwcGx5KHRoaXMsIG8gfHwgW2UucmVzcG9uc2VUZXh0LCB0LCBlXSl9KX0pLCB0aGlzDQoJCX0sIEUuZXhwci5wc2V1ZG9zLmFuaW1hdGVkID0gZnVuY3Rpb24odCkge3JldHVybiBFLmdyZXAoRS50aW1lcnMsIGZ1bmN0aW9uKGUpIHtyZXR1cm4gdCA9PT0gZS5lbGVtfSkubGVuZ3RofSwgRS5vZmZzZXQgPSB7DQoJCQlzZXRPZmZzZXQ6IGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQl2YXIgciwgaSwgbywgYSwgcywgdSwgbCA9IEUuY3NzKGUsICJwb3NpdGlvbiIpLCBjID0gRShlKSwgZiA9IHt9Ow0KCQkJCSJzdGF0aWMiID09PSBsICYmIChlLnN0eWxlLnBvc2l0aW9uID0gInJlbGF0aXZlIiksIHMgPSBjLm9mZnNldCgpLCBvID0gRS5jc3MoZSwgInRvcCIpLCB1ID0gRS5jc3MoZSwgImxlZnQiKSwgKCJhYnNvbHV0ZSIgPT09IGwgfHwgImZpeGVkIiA9PT0gbCkgJiYgLTEgPCAobyArIHUpLmluZGV4T2YoImF1dG8iKSA/IChhID0gKHIgPSBjLnBvc2l0aW9uKCkpLnRvcCwgaSA9IHIubGVmdCkgOiAoYSA9IHBhcnNlRmxvYXQobykgfHwgMCwgaSA9IHBhcnNlRmxvYXQodSkgfHwgMCksIG0odCkgJiYgKHQgPSB0LmNhbGwoZSwgbiwgRS5leHRlbmQoe30sIHMpKSksIG51bGwgIT0gdC50b3AgJiYgKGYudG9wID0gdC50b3AgLSBzLnRvcCArIGEpLCBudWxsICE9IHQubGVmdCAmJiAoZi5sZWZ0ID0gdC5sZWZ0IC0gcy5sZWZ0ICsgaSksICJ1c2luZyIgaW4gdCA/IHQudXNpbmcuY2FsbChlLCBmKSA6IGMuY3NzKGYpDQoJCQl9DQoJCX0sIEUuZm4uZXh0ZW5kKHsNCgkJCW9mZnNldDogZnVuY3Rpb24odCkgew0KCQkJCWlmKGFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB2b2lkIDAgPT09IHQgPyB0aGlzIDogdGhpcy5lYWNoKGZ1bmN0aW9uKGUpIHtFLm9mZnNldC5zZXRPZmZzZXQodGhpcywgdCwgZSl9KTsNCgkJCQl2YXIgZSwgbiwgciA9IHRoaXNbMF07DQoJCQkJcmV0dXJuIHIgPyByLmdldENsaWVudFJlY3RzKCkubGVuZ3RoID8gKGUgPSByLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLCBuID0gci5vd25lckRvY3VtZW50LmRlZmF1bHRWaWV3LCB7dG9wOiBlLnRvcCArIG4ucGFnZVlPZmZzZXQsIGxlZnQ6IGUubGVmdCArIG4ucGFnZVhPZmZzZXR9KSA6IHt0b3A6IDAsIGxlZnQ6IDB9IDogdm9pZCAwDQoJCQl9LCBwb3NpdGlvbjogZnVuY3Rpb24oKSB7DQoJCQkJaWYodGhpc1swXSkgew0KCQkJCQl2YXIgZSwgdCwgbiwgciA9IHRoaXNbMF0sIGkgPSB7dG9wOiAwLCBsZWZ0OiAwfTsNCgkJCQkJaWYoImZpeGVkIiA9PT0gRS5jc3MociwgInBvc2l0aW9uIikpIHQgPSByLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOyBlbHNlIHsNCgkJCQkJCXQgPSB0aGlzLm9mZnNldCgpLCBuID0gci5vd25lckRvY3VtZW50LCBlID0gci5vZmZzZXRQYXJlbnQgfHwgbi5kb2N1bWVudEVsZW1lbnQ7DQoJCQkJCQl3aGlsZShlICYmIChlID09PSBuLmJvZHkgfHwgZSA9PT0gbi5kb2N1bWVudEVsZW1lbnQpICYmICJzdGF0aWMiID09PSBFLmNzcyhlLCAicG9zaXRpb24iKSkgZSA9IGUucGFyZW50Tm9kZTsNCgkJCQkJCWUgJiYgZSAhPT0gciAmJiAxID09PSBlLm5vZGVUeXBlICYmICgoaSA9IEUoZSkub2Zmc2V0KCkpLnRvcCArPSBFLmNzcyhlLCAiYm9yZGVyVG9wV2lkdGgiLCAhMCksIGkubGVmdCArPSBFLmNzcyhlLCAiYm9yZGVyTGVmdFdpZHRoIiwgITApKQ0KCQkJCQl9DQoJCQkJCXJldHVybiB7dG9wOiB0LnRvcCAtIGkudG9wIC0gRS5jc3MociwgIm1hcmdpblRvcCIsICEwKSwgbGVmdDogdC5sZWZ0IC0gaS5sZWZ0IC0gRS5jc3MociwgIm1hcmdpbkxlZnQiLCAhMCl9DQoJCQkJfQ0KCQkJfSwgb2Zmc2V0UGFyZW50OiBmdW5jdGlvbigpIHsNCgkJCQlyZXR1cm4gdGhpcy5tYXAoZnVuY3Rpb24oKSB7DQoJCQkJCXZhciBlID0gdGhpcy5vZmZzZXRQYXJlbnQ7DQoJCQkJCXdoaWxlKGUgJiYgInN0YXRpYyIgPT09IEUuY3NzKGUsICJwb3NpdGlvbiIpKSBlID0gZS5vZmZzZXRQYXJlbnQ7DQoJCQkJCXJldHVybiBlIHx8IHJlDQoJCQkJfSkNCgkJCX0NCgkJfSksIEUuZWFjaCh7c2Nyb2xsTGVmdDogInBhZ2VYT2Zmc2V0Iiwgc2Nyb2xsVG9wOiAicGFnZVlPZmZzZXQifSwgZnVuY3Rpb24odCwgaSkgew0KCQkJdmFyIG8gPSAicGFnZVlPZmZzZXQiID09PSBpOw0KCQkJRS5mblt0XSA9IGZ1bmN0aW9uKGUpIHsNCgkJCQlyZXR1cm4gQih0aGlzLCBmdW5jdGlvbihlLCB0LCBuKSB7DQoJCQkJCXZhciByOw0KCQkJCQlpZih4KGUpID8gciA9IGUgOiA5ID09PSBlLm5vZGVUeXBlICYmIChyID0gZS5kZWZhdWx0VmlldyksIHZvaWQgMCA9PT0gbikgcmV0dXJuIHIgPyByW2ldIDogZVt0XTsNCgkJCQkJciA/IHIuc2Nyb2xsVG8obyA/IHIucGFnZVhPZmZzZXQgOiBuLCBvID8gbiA6IHIucGFnZVlPZmZzZXQpIDogZVt0XSA9IG4NCgkJCQl9LCB0LCBlLCBhcmd1bWVudHMubGVuZ3RoKQ0KCQkJfQ0KCQl9KSwgRS5lYWNoKFsidG9wIiwgImxlZnQiXSwgZnVuY3Rpb24oZSwgbikge0UuY3NzSG9va3Nbbl0gPSBfZSh2LnBpeGVsUG9zaXRpb24sIGZ1bmN0aW9uKGUsIHQpIHtpZih0KSByZXR1cm4gdCA9IEJlKGUsIG4pLCBQZS50ZXN0KHQpID8gRShlKS5wb3NpdGlvbigpW25dICsgInB4IiA6IHR9KX0pLCBFLmVhY2goe0hlaWdodDogImhlaWdodCIsIFdpZHRoOiAid2lkdGgifSwgZnVuY3Rpb24oYSwgcykgew0KCQkJRS5lYWNoKHsNCgkJCQlwYWRkaW5nOiAiaW5uZXIiICsgYSwNCgkJCQljb250ZW50OiBzLA0KCQkJCSIiOiAib3V0ZXIiICsgYQ0KCQkJfSwgZnVuY3Rpb24ociwgbykgew0KCQkJCUUuZm5bb10gPSBmdW5jdGlvbihlLCB0KSB7DQoJCQkJCXZhciBuID0gYXJndW1lbnRzLmxlbmd0aCAmJiAociB8fCAiYm9vbGVhbiIgIT0gdHlwZW9mIGUpLCBpID0gciB8fCAoITAgPT09IGUgfHwgITAgPT09IHQgPyAibWFyZ2luIiA6ICJib3JkZXIiKTsNCgkJCQkJcmV0dXJuIEIodGhpcywgZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJCQkJdmFyIHI7DQoJCQkJCQlyZXR1cm4geChlKSA/IDAgPT09IG8uaW5kZXhPZigib3V0ZXIiKSA/IGVbImlubmVyIiArIGFdIDogZS5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnRbImNsaWVudCIgKyBhXSA6IDkgPT09IGUubm9kZVR5cGUgPyAociA9IGUuZG9jdW1lbnRFbGVtZW50LCBNYXRoLm1heChlLmJvZHlbInNjcm9sbCIgKyBhXSwgclsic2Nyb2xsIiArIGFdLCBlLmJvZHlbIm9mZnNldCIgKyBhXSwgclsib2Zmc2V0IiArIGFdLCByWyJjbGllbnQiICsgYV0pKSA6IHZvaWQgMCA9PT0gbiA/IEUuY3NzKGUsIHQsIGkpIDogRS5zdHlsZShlLCB0LCBuLCBpKQ0KCQkJCQl9LCBzLCBuID8gZSA6IHZvaWQgMCwgbikNCgkJCQl9DQoJCQl9KQ0KCQl9KSwgRS5lYWNoKFsiYWpheFN0YXJ0IiwgImFqYXhTdG9wIiwgImFqYXhDb21wbGV0ZSIsICJhamF4RXJyb3IiLCAiYWpheFN1Y2Nlc3MiLCAiYWpheFNlbmQiXSwgZnVuY3Rpb24oZSwgdCkge0UuZm5bdF0gPSBmdW5jdGlvbihlKSB7cmV0dXJuIHRoaXMub24odCwgZSl9fSksIEUuZm4uZXh0ZW5kKHsNCgkJCWJpbmQ6IGZ1bmN0aW9uKGUsIHQsIG4pIHtyZXR1cm4gdGhpcy5vbihlLCBudWxsLCB0LCBuKX0sDQoJCQl1bmJpbmQ6IGZ1bmN0aW9uKGUsIHQpIHtyZXR1cm4gdGhpcy5vZmYoZSwgbnVsbCwgdCl9LA0KCQkJZGVsZWdhdGU6IGZ1bmN0aW9uKGUsIHQsIG4sIHIpIHtyZXR1cm4gdGhpcy5vbih0LCBlLCBuLCByKX0sDQoJCQl1bmRlbGVnYXRlOiBmdW5jdGlvbihlLCB0LCBuKSB7cmV0dXJuIDEgPT09IGFyZ3VtZW50cy5sZW5ndGggPyB0aGlzLm9mZihlLCAiKioiKSA6IHRoaXMub2ZmKHQsIGUgfHwgIioqIiwgbil9LA0KCQkJaG92ZXI6IGZ1bmN0aW9uKGUsIHQpIHtyZXR1cm4gdGhpcy5tb3VzZWVudGVyKGUpLm1vdXNlbGVhdmUodCB8fCBlKX0NCgkJfSksIEUuZWFjaCgiYmx1ciBmb2N1cyBmb2N1c2luIGZvY3Vzb3V0IHJlc2l6ZSBzY3JvbGwgY2xpY2sgZGJsY2xpY2sgbW91c2Vkb3duIG1vdXNldXAgbW91c2Vtb3ZlIG1vdXNlb3ZlciBtb3VzZW91dCBtb3VzZWVudGVyIG1vdXNlbGVhdmUgY2hhbmdlIHNlbGVjdCBzdWJtaXQga2V5ZG93biBrZXlwcmVzcyBrZXl1cCBjb250ZXh0bWVudSIuc3BsaXQoIiAiKSwgZnVuY3Rpb24oZSwgbikge0UuZm5bbl0gPSBmdW5jdGlvbihlLCB0KSB7cmV0dXJuIDAgPCBhcmd1bWVudHMubGVuZ3RoID8gdGhpcy5vbihuLCBudWxsLCBlLCB0KSA6IHRoaXMudHJpZ2dlcihuKX19KTsNCgkJdmFyIEd0ID0gL15bXHNcdUZFRkZceEEwXSt8KFteXHNcdUZFRkZceEEwXSlbXHNcdUZFRkZceEEwXSskL2c7DQoJCUUucHJveHkgPSBmdW5jdGlvbihlLCB0KSB7DQoJCQl2YXIgbiwgciwgaTsNCgkJCWlmKCJzdHJpbmciID09IHR5cGVvZiB0ICYmIChuID0gZVt0XSwgdCA9IGUsIGUgPSBuKSwgbShlKSkgcmV0dXJuIHIgPSBzLmNhbGwoYXJndW1lbnRzLCAyKSwgKGkgPSBmdW5jdGlvbigpIHtyZXR1cm4gZS5hcHBseSh0IHx8IHRoaXMsIHIuY29uY2F0KHMuY2FsbChhcmd1bWVudHMpKSl9KS5ndWlkID0gZS5ndWlkID0gZS5ndWlkIHx8IEUuZ3VpZCsrLCBpDQoJCX0sIEUuaG9sZFJlYWR5ID0gZnVuY3Rpb24oZSkge2UgPyBFLnJlYWR5V2FpdCsrIDogRS5yZWFkeSghMCl9LCBFLmlzQXJyYXkgPSBBcnJheS5pc0FycmF5LCBFLnBhcnNlSlNPTiA9IEpTT04ucGFyc2UsIEUubm9kZU5hbWUgPSBBLCBFLmlzRnVuY3Rpb24gPSBtLCBFLmlzV2luZG93ID0geCwgRS5jYW1lbENhc2UgPSBYLCBFLnR5cGUgPSB3LCBFLm5vdyA9IERhdGUubm93LCBFLmlzTnVtZXJpYyA9IGZ1bmN0aW9uKGUpIHsNCgkJCXZhciB0ID0gRS50eXBlKGUpOw0KCQkJcmV0dXJuICgibnVtYmVyIiA9PT0gdCB8fCAic3RyaW5nIiA9PT0gdCkgJiYgIWlzTmFOKGUgLSBwYXJzZUZsb2F0KGUpKQ0KCQl9LCBFLnRyaW0gPSBmdW5jdGlvbihlKSB7cmV0dXJuIG51bGwgPT0gZSA/ICIiIDogKGUgKyAiIikucmVwbGFjZShHdCwgIiQxIil9LCAiZnVuY3Rpb24iID09IHR5cGVvZiBkZWZpbmUgJiYgZGVmaW5lLmFtZCAmJiBkZWZpbmUoImpxdWVyeSIsIFtdLCBmdW5jdGlvbigpIHtyZXR1cm4gRX0pOw0KCQl2YXIgWXQgPSBDLmpRdWVyeSwgUXQgPSBDLiQ7DQoJCXJldHVybiBFLm5vQ29uZmxpY3QgPSBmdW5jdGlvbihlKSB7cmV0dXJuIEMuJCA9PT0gRSAmJiAoQy4kID0gUXQpLCBlICYmIEMualF1ZXJ5ID09PSBFICYmIChDLmpRdWVyeSA9IFl0KSwgRX0sICJ1bmRlZmluZWQiID09IHR5cGVvZiBlICYmIChDLmpRdWVyeSA9IEMuJCA9IEUpLCBFDQoJfSk7DQp9DQoNCmNvbnN0IHVudGlsID0gKHByZWRpY2F0ZUZuKSA9PiB7DQoJY29uc3QgcG9sbCA9IChkb25lKSA9PiAocHJlZGljYXRlRm4oKSA/IGRvbmUoKSA6IHNldFRpbWVvdXQoKCkgPT4gcG9sbChkb25lKSwgNTAwKSk7DQoJcmV0dXJuIG5ldyBQcm9taXNlKHBvbGwpOw0KfTsNCg0KYXN5bmMgZnVuY3Rpb24gcGF1c2Uodikgew0KCXdoaWxlKHYgPCAxMDApDQoJCWF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDAwKSk7DQp9DQoNCmZ1bmN0aW9uIGxvb3AobGlnaHRib3hJbWFnZXMsIGluZGV4KSB7DQoJaWYoaW5kZXggPT09IGxpZ2h0Ym94SW1hZ2VzLmxlbmd0aCkgcmV0dXJuOw0KDQoJbGlnaHRib3hJbWFnZXNbaW5kZXhdLm9ubG9hZCA9IGZ1bmN0aW9uKCkgew0KCQljb25zb2xlLmxvZygiaW1hZ2UgIiArIGluZGV4ICsgIiBsb2FkZWQuIik7DQoJCWxvb3AobGlnaHRib3hJbWFnZXMsICsraW5kZXgpOw0KCX07DQp9DQoNCjsoZnVuY3Rpb24oZmFjdG9yeSkgew0KCWZhY3RvcnkoJCk7DQp9KShmdW5jdGlvbihqUXVlcnkpIHsNCgkoYXN5bmMgZnVuY3Rpb24ocHJlY2FsbGJhY2spIHsNCgkJY29uc3QgdGl0bGUgPSBkb2N1bWVudC50aXRsZTsNCgkJaWYodGl0bGUgIT09IHVuZGVmaW5lZCkNCgkJCWRvY3VtZW50LnRpdGxlID0gIkxvYWRpbmcuLi4iOw0KDQoJCWlmKHdpbmRvdy5qUXVlcnkpDQoJCQkkLmhvbGRSZWFkeSh0cnVlKTsNCg0KCQkoKCkgPT4gew0KCQkJY29uc3QgY3NzID0gYC8qDQogKiBDb3B5cmlnaHQgKGMpIDIwMjIgU0dOZXR3b3Jrcy4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCiAqDQogKiBUaGUgc29mdHdhcmUgaXMgYW4gZXhjbHVzaXZlIGNvcHlyaWdodCBvZiAiU0dOZXR3b3JrcyIgYW5kIGlzIHByb3ZpZGVkIGFzIGlzIGV4Y2x1c2l2ZWx5IHdpdGggb25seSAiVVNBR0UiIGFjY2Vzcy4gIk1vZGlmaWNhdGlvbiIsICAiQWx0ZXJhdGlvbiIsICJSZS1kaXN0cmlidXRpb24iIGlzIGNvbXBsZXRlbHkgcHJvaGliaXRlZC4NCiAqIFZJT0xBVElORyBUSEUgQUJPVkUgVEVSTVMgSVMgQSBQVU5JU0hBQkxFIE9GRkVOU0UgV0hJQ0ggTUFZIExFQUQgVE8gTEVHQUwgQ09OU0VRVUVOQ0VTLg0KICovDQoNCi5oYXMtcHJlbG9hZGVyLA0KLmhhcy1wcmVsb2FkZXIgKiB7DQpcdC0tc2duLWJhY2tncm91bmQ6ICNmZmY7DQpcdC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoOiA2cHg7DQpcdC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoOiA0NHB4Ow0KXHQtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1oZWlnaHQ6IDIycHg7DQpcdC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbjogMXB4Ow0KXHQtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1yYWRpdXM6IDZweDsNCn0NCg0KQG1lZGlhIGFsbCBhbmQgKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKSB7DQpcdC5oYXMtcHJlbG9hZGVyLA0KXHQuaGFzLXByZWxvYWRlciAqIHsNClx0LS1zZ24tYmFja2dyb3VuZDogIzAwMDsNClx0fQ0KfQ0KDQpib2R5IHsNClx0bWFyZ2luOiAwOw0KfQ0KDQouc2duLXByZWxvYWRlciB7DQpcdHBhZGRpbmc6IDA7DQpcdHdpZHRoOiAxMDAlOw0KXHRoZWlnaHQ6IDEwMCU7DQpcdGJhY2tncm91bmQtY29sb3I6IHZhcigtLXNnbi1iYWNrZ3JvdW5kKTsNClx0ZGlzcGxheTogZmxleDsNClx0anVzdGlmeS1jb250ZW50OiBjZW50ZXI7DQpcdGFsaWduLWl0ZW1zOiBjZW50ZXI7DQpcdHBvc2l0aW9uOiBhYnNvbHV0ZTsNClx0ei1pbmRleDogOTk5OTk5Ow0KfQ0KDQoNCi5zZ24tcHJlbG9hZGVyID4gLnByZWxvYWRlciB7DQpcdHBvc2l0aW9uOiByZWxhdGl2ZTsNClx0ZGlzcGxheTogaW5saW5lLWZsZXg7DQpcdGp1c3RpZnktY29udGVudDogY2VudGVyOw0KXHRhbGlnbi1pdGVtczogY2VudGVyOw0KfQ0KDQouc2duLXByZWxvYWRlciA+IC5wcmVsb2FkZXIgPiAuc3Bpbm5lciB7DQpcdGFuaW1hdGlvbjogcm90YXRlIDEwcyBpbmZpbml0ZSBsaW5lYXI7DQpcdHBvc2l0aW9uOiByZWxhdGl2ZTsNClx0ZGlzcGxheTogaW5saW5lLWZsZXg7DQpcdGp1c3RpZnktY29udGVudDogY2VudGVyOw0KXHRhbGlnbi1pdGVtczogY2VudGVyOw0KXHR3aWR0aDogMTAwJTsNClx0aGVpZ2h0OiAxMDAlOw0KfQ0KDQoNCi5zZ24tcHJlbG9hZGVyID4gLnByZWxvYWRlciA+IGltZyB7DQpcdHdpZHRoOiAxMDAlOw0KXHRoZWlnaHQ6IDEwMCU7DQpcdG1hcmdpbjogdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbik7DQpcdGRpc3BsYXk6IGZsZXg7DQpcdGp1c3RpZnktY29udGVudDogY2VudGVyOw0KXHRhbGlnbi1pdGVtczogY2VudGVyOw0KXHRwb3NpdGlvbjogcmVsYXRpdmU7DQpcdHRvcDogNTAlOw0KXHRsZWZ0OiA1MCU7DQp9DQouc2duLXByZWxvYWRlciA+IC5wcmVsb2FkZXIgPiAuc3Bpbm5lciA+IGltZyB7DQpcdHdpZHRoOiBjYWxjKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy13aWR0aCkpOw0KXHRoZWlnaHQ6IGNhbGModmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoKSk7DQpcdG1hcmdpbjogdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbik7DQp9DQouc2duLXByZWxvYWRlciA+IC5wcmVsb2FkZXIgPiAuc3Bpbm5lciA+IGkgew0KXHRhbmltYXRpb246IHJvdGF0ZSAzcyBpbmZpbml0ZSBjdWJpYy1iZXppZXIoMC4wOSwgMC42LCAwLjgsIDAuMDMpOw0KXHR0cmFuc2Zvcm0tb3JpZ2luOiA1MCUgMTAwJSAwOw0KXHRwb3NpdGlvbjogYWJzb2x1dGU7DQpcdGRpc3BsYXk6IGlubGluZS1mbGV4Ow0KXHRqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsNClx0YWxpZ24taXRlbXM6IGNlbnRlcjsNClx0dG9wOiA1MCU7DQpcdGxlZnQ6IDUwJTsNClx0Ym9yZGVyOiBzb2xpZCB2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpIHRyYW5zcGFyZW50Ow0KXHRib3JkZXItYm90dG9tOiBub25lOw0KfQ0KLnNnbi1wcmVsb2FkZXIgPiAucHJlbG9hZGVyID4gLnNwaW5uZXIgPiBpOm50aC1jaGlsZCgxKSB7DQpcdC1tb3otYW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogY3ViaWMtYmV6aWVyKDAuMDksIDAuMywgMC4xMiwgMC4wMyk7DQpcdC13ZWJraXQtYW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogY3ViaWMtYmV6aWVyKDAuMDksIDAuMywgMC4xMiwgMC4wMyk7DQpcdGFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb246IGN1YmljLWJlemllcigwLjA5LCAwLjMsIDAuMTIsIDAuMDMpOw0KXHR3aWR0aDogdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoKTsNClx0aGVpZ2h0OiB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KTsNClx0bWFyZ2luLXRvcDogY2FsYygwcHggLSB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KSk7DQpcdG1hcmdpbi1sZWZ0OiBjYWxjKDBweCAtIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1oZWlnaHQpKTsNClx0Ym9yZGVyLWNvbG9yOiAjMjE3MmI4Ow0KXHRib3JkZXItdG9wLWxlZnQtcmFkaXVzOiBjYWxjKCh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtd2lkdGgpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikgKiAxKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1yYWRpdXMpKTsNClx0Ym9yZGVyLXRvcC1yaWdodC1yYWRpdXM6IGNhbGMoKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy13aWR0aCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiAyKSAqIDEpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXJhZGl1cykpOw0KfQ0KLnNnbi1wcmVsb2FkZXIgPiAucHJlbG9hZGVyID4gLnNwaW5uZXIgPiBpOm50aC1jaGlsZCgyKSB7DQpcdC1tb3otYW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogY3ViaWMtYmV6aWVyKDAuMDksIDAuNiwgMC4yNCwgMC4wMyk7DQpcdC13ZWJraXQtYW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogY3ViaWMtYmV6aWVyKDAuMDksIDAuNiwgMC4yNCwgMC4wMyk7DQpcdGFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb246IGN1YmljLWJlemllcigwLjA5LCAwLjYsIDAuMjQsIDAuMDMpOw0KXHR3aWR0aDogY2FsYyh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtd2lkdGgpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikpOw0KXHRoZWlnaHQ6IGNhbGModmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLWhlaWdodCkgKyAodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSk7DQpcdG1hcmdpbi10b3A6IGNhbGMoMHB4IC0gKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1oZWlnaHQpICsgKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkpKTsNClx0bWFyZ2luLWxlZnQ6IGNhbGMoMHB4IC0gKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1oZWlnaHQpICsgKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkpKTsNClx0Ym9yZGVyLWNvbG9yOiAjMThhMzliOw0KXHRib3JkZXItdG9wLWxlZnQtcmFkaXVzOiBjYWxjKCh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtd2lkdGgpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikgKiAyKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1yYWRpdXMpKTsNClx0Ym9yZGVyLXRvcC1yaWdodC1yYWRpdXM6IGNhbGMoKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy13aWR0aCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiAyKSAqIDIpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXJhZGl1cykpOw0KfQ0KLnNnbi1wcmVsb2FkZXIgPiAucHJlbG9hZGVyID4gLnNwaW5uZXIgPiBpOm50aC1jaGlsZCgzKSB7DQpcdC1tb3otYW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogY3ViaWMtYmV6aWVyKDAuMDksIDAuOSwgMC4zNiwgMC4wMyk7DQpcdC13ZWJraXQtYW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogY3ViaWMtYmV6aWVyKDAuMDksIDAuOSwgMC4zNiwgMC4wMyk7DQpcdGFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb246IGN1YmljLWJlemllcigwLjA5LCAwLjksIDAuMzYsIDAuMDMpOw0KXHR3aWR0aDogY2FsYyh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtd2lkdGgpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikgKiAyKTsNClx0aGVpZ2h0OiBjYWxjKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1oZWlnaHQpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikpOw0KXHRtYXJnaW4tdG9wOiBjYWxjKDBweCAtICh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpKSk7DQpcdG1hcmdpbi1sZWZ0OiBjYWxjKDBweCAtICh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpKSk7DQpcdGJvcmRlci1jb2xvcjogIzgyYzU0NTsNClx0Ym9yZGVyLXRvcC1sZWZ0LXJhZGl1czogY2FsYygodmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoKSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogMikgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtcmFkaXVzKSk7DQpcdGJvcmRlci10b3AtcmlnaHQtcmFkaXVzOiBjYWxjKCh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtd2lkdGgpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikgKiAyKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1yYWRpdXMpKTsNCn0NCi5zZ24tcHJlbG9hZGVyID4gLnByZWxvYWRlciA+IC5zcGlubmVyID4gaTpudGgtY2hpbGQoNCkgew0KXHQtbW96LWFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb246IGN1YmljLWJlemllcigwLjA5LCAxLjIsIDAuNDgsIDAuMDMpOw0KXHQtd2Via2l0LWFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb246IGN1YmljLWJlemllcigwLjA5LCAxLjIsIDAuNDgsIDAuMDMpOw0KXHRhbmltYXRpb24tdGltaW5nLWZ1bmN0aW9uOiBjdWJpYy1iZXppZXIoMC4wOSwgMS4yLCAwLjQ4LCAwLjAzKTsNClx0d2lkdGg6IGNhbGModmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoKSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogMyk7DQpcdGhlaWdodDogY2FsYyh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogMS41KTsNClx0bWFyZ2luLXRvcDogY2FsYygwcHggLSAodmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLWhlaWdodCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiAzKSkpOw0KXHRtYXJnaW4tbGVmdDogY2FsYygwcHggLSAodmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLWhlaWdodCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiAzKSkpOw0KXHRib3JkZXItY29sb3I6ICNmOGI3Mzk7DQpcdGJvcmRlci10b3AtbGVmdC1yYWRpdXM6IGNhbGMoKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy13aWR0aCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiAyKSAqIDMpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXJhZGl1cykpOw0KXHRib3JkZXItdG9wLXJpZ2h0LXJhZGl1czogY2FsYygodmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoKSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogMykgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtcmFkaXVzKSk7DQp9DQouc2duLXByZWxvYWRlciA+IC5wcmVsb2FkZXIgPiAuc3Bpbm5lciA+IGk6bnRoLWNoaWxkKDUpIHsNClx0LW1vei1hbmltYXRpb24tdGltaW5nLWZ1bmN0aW9uOiBjdWJpYy1iZXppZXIoMC4wOSwgMS41LCAwLjYsIDAuMDMpOw0KXHQtd2Via2l0LWFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb246IGN1YmljLWJlemllcigwLjA5LCAxLjUsIDAuNiwgMC4wMyk7DQpcdGFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb246IGN1YmljLWJlemllcigwLjA5LCAxLjUsIDAuNiwgMC4wMyk7DQpcdHdpZHRoOiBjYWxjKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy13aWR0aCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiAyKSAqIDQpOw0KXHRoZWlnaHQ6IGNhbGModmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLWhlaWdodCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiAyKSAqIDIpOw0KXHRtYXJnaW4tdG9wOiBjYWxjKDBweCAtICh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDQpKSk7DQpcdG1hcmdpbi1sZWZ0OiBjYWxjKDBweCAtICh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDQpKSk7DQpcdGJvcmRlci1jb2xvcjogI2YwNjA0NTsNClx0Ym9yZGVyLXRvcC1sZWZ0LXJhZGl1czogY2FsYygodmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoKSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogNCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtcmFkaXVzKSk7DQpcdGJvcmRlci10b3AtcmlnaHQtcmFkaXVzOiBjYWxjKCh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtd2lkdGgpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikgKiA0KSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1yYWRpdXMpKTsNCn0NCi5zZ24tcHJlbG9hZGVyID4gLnByZWxvYWRlciA+IC5zcGlubmVyID4gaTpudGgtY2hpbGQoNikgew0KXHQtbW96LWFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb246IGN1YmljLWJlemllcigwLjA5LCAxLjgsIDAuNzIsIDAuMDMpOw0KXHQtd2Via2l0LWFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb246IGN1YmljLWJlemllcigwLjA5LCAxLjgsIDAuNzIsIDAuMDMpOw0KXHRhbmltYXRpb24tdGltaW5nLWZ1bmN0aW9uOiBjdWJpYy1iZXppZXIoMC4wOSwgMS44LCAwLjcyLCAwLjAzKTsNClx0d2lkdGg6IGNhbGModmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoKSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogNSk7DQpcdGhlaWdodDogY2FsYyh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogMi41KTsNClx0bWFyZ2luLXRvcDogY2FsYygwcHggLSAodmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLWhlaWdodCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiA1KSkpOw0KXHRtYXJnaW4tbGVmdDogY2FsYygwcHggLSAodmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLWhlaWdodCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiA1KSkpOw0KXHRib3JkZXItY29sb3I6ICNlZDI4NjE7DQpcdGJvcmRlci10b3AtbGVmdC1yYWRpdXM6IGNhbGMoKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy13aWR0aCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiAyKSAqIDUpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXJhZGl1cykpOw0KXHRib3JkZXItdG9wLXJpZ2h0LXJhZGl1czogY2FsYygodmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoKSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogNSkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtcmFkaXVzKSk7DQp9DQouc2duLXByZWxvYWRlciA+IC5wcmVsb2FkZXIgPiAuc3Bpbm5lciA+IGk6bnRoLWNoaWxkKDcpIHsNClx0LW1vei1hbmltYXRpb24tdGltaW5nLWZ1bmN0aW9uOiBjdWJpYy1iZXppZXIoMC4wOSwgMi4xLCAwLjg0LCAwLjAzKTsNClx0LXdlYmtpdC1hbmltYXRpb24tdGltaW5nLWZ1bmN0aW9uOiBjdWJpYy1iZXppZXIoMC4wOSwgMi4xLCAwLjg0LCAwLjAzKTsNClx0YW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogY3ViaWMtYmV6aWVyKDAuMDksIDIuMSwgMC44NCwgMC4wMyk7DQpcdHdpZHRoOiBjYWxjKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy13aWR0aCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiAyKSAqIDYpOw0KXHRoZWlnaHQ6IGNhbGModmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLWhlaWdodCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiAyKSAqIDMpOw0KXHRtYXJnaW4tdG9wOiBjYWxjKDBweCAtICh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDYpKSk7DQpcdG1hcmdpbi1sZWZ0OiBjYWxjKDBweCAtICh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDYpKSk7DQpcdGJvcmRlci1jb2xvcjogI2MxMjY4MDsNClx0Ym9yZGVyLXRvcC1sZWZ0LXJhZGl1czogY2FsYygodmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoKSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogNikgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtcmFkaXVzKSk7DQpcdGJvcmRlci10b3AtcmlnaHQtcmFkaXVzOiBjYWxjKCh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtd2lkdGgpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikgKiA2KSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1yYWRpdXMpKTsNCn0NCi5zZ24tcHJlbG9hZGVyID4gLnByZWxvYWRlciA+IC5zcGlubmVyID4gaTpudGgtY2hpbGQoOCkgew0KXHQtbW96LWFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb246IGN1YmljLWJlemllcigwLjA5LCAyLjQsIDAuOTYsIDAuMDMpOw0KXHQtd2Via2l0LWFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb246IGN1YmljLWJlemllcigwLjA5LCAyLjQsIDAuOTYsIDAuMDMpOw0KXHRhbmltYXRpb24tdGltaW5nLWZ1bmN0aW9uOiBjdWJpYy1iZXppZXIoMC4wOSwgMi40LCAwLjk2LCAwLjAzKTsNClx0d2lkdGg6IGNhbGModmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoKSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogNyk7DQpcdGhlaWdodDogY2FsYyh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogMy41KTsNClx0bWFyZ2luLXRvcDogY2FsYygwcHggLSAodmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLWhlaWdodCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiA3KSkpOw0KXHRtYXJnaW4tbGVmdDogY2FsYygwcHggLSAodmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLWhlaWdodCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiA3KSkpOw0KXHRib3JkZXItY29sb3I6ICM1ZDMxOTE7DQpcdGJvcmRlci10b3AtbGVmdC1yYWRpdXM6IGNhbGMoKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy13aWR0aCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiAyKSAqIDcpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXJhZGl1cykpOw0KXHRib3JkZXItdG9wLXJpZ2h0LXJhZGl1czogY2FsYygodmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoKSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogNykgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtcmFkaXVzKSk7DQp9DQoNCkAtbW96LWtleWZyYW1lcyByb3RhdGUgew0KXHR0byB7DQpcdFx0dHJhbnNmb3JtOiByb3RhdGUoMzYwZGVnKTsNClx0fQ0KfQ0KQC13ZWJraXQta2V5ZnJhbWVzIHJvdGF0ZSB7DQpcdHRvIHsNClx0XHR0cmFuc2Zvcm06IHJvdGF0ZSgzNjBkZWcpOw0KXHR9DQp9DQpAa2V5ZnJhbWVzIHJvdGF0ZSB7DQpcdHRvIHsNClx0XHR0cmFuc2Zvcm06IHJvdGF0ZSgzNjBkZWcpOw0KXHR9DQp9DQoNCg0KYDsNCgkJCWNvbnN0IGhlYWQgID0gZG9jdW1lbnQuaGVhZCB8fCBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgiaGVhZCIpWzBdLA0KCQkJICAgICAgc3R5bGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJzdHlsZSIpOw0KDQoJCQloZWFkLmFwcGVuZENoaWxkKHN0eWxlKTsNCgkJCXN0eWxlLnR5cGUgPSAidGV4dC9jc3MiOw0KCQkJc3R5bGUuaWQgPSAic2duLXVpa2l0LXN0eWxlcyI7DQoJCQlpZihzdHlsZS5zdHlsZVNoZWV0KSB7DQoJCQkJLy8gVGhpcyBpcyByZXF1aXJlZCBmb3IgSUU4IGFuZCBiZWxvdy4NCgkJCQlzdHlsZS5zdHlsZVNoZWV0LmNzc1RleHQgPSBjc3M7DQoJCQl9IGVsc2Ugew0KCQkJCXN0eWxlLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKGNzcykpOw0KCQkJfQ0KCQl9KSgpOw0KCQkoZnVuY3Rpb24oKSB7DQoJCQlsZXQgcHJlbG9hZGVyRWxlbSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpOw0KCQkJcHJlbG9hZGVyRWxlbS5jbGFzc05hbWUgPSAic2duLXByZWxvYWRlciI7DQoJCQlsZXQgcHJlbG9hZGVyID0gYFx0XHRcdDxkaXYgY2xhc3M9InByZWxvYWRlciI+XG5gOw0KCQkJLy9wcmVsb2FkZXIgKz0gYFx0XHRcdFx0PGltZyBzcmM9Ijw/PSRwdWJsaWNfaW1nQXNzZXRzOz8+aWNvbnMveHNtYWxsLnBuZyI+XG5gOw0KCQkJcHJlbG9hZGVyICs9IGBcdFx0XHRcdDxkaXYgY2xhc3M9InNwaW5uZXIiPlxuYDsNCgkJCXByZWxvYWRlciArPSBgXHRcdFx0XHRcdDxpPjwvaT5cbmA7DQoJCQlwcmVsb2FkZXIgKz0gYFx0XHRcdFx0XHQ8aT48L2k+XG5gOw0KCQkJcHJlbG9hZGVyICs9IGBcdFx0XHRcdFx0PGk+PC9pPlxuYDsNCgkJCXByZWxvYWRlciArPSBgXHRcdFx0XHRcdDxpPjwvaT5cbmA7DQoJCQlwcmVsb2FkZXIgKz0gYFx0XHRcdFx0XHQ8aT48L2k+XG5gOw0KCQkJcHJlbG9hZGVyICs9IGBcdFx0XHRcdFx0PGk+PC9pPlxuYDsNCgkJCXByZWxvYWRlciArPSBgXHRcdFx0XHRcdDxpPjwvaT5cbmA7DQoJCQlwcmVsb2FkZXIgKz0gYFx0XHRcdFx0XHQ8aT48L2k+XG5gOw0KCQkJcHJlbG9hZGVyICs9IGBcdFx0XHRcdDwvZGl2PlxuYDsNCgkJCXByZWxvYWRlciArPSBgXHRcdFx0PC9kaXY+XG5gOw0KCQkJcHJlbG9hZGVyICs9IGBcdFx0PC9kaXY+XG5gOw0KDQoJCQlwcmVsb2FkZXJFbGVtLmlubmVySFRNTCA9IHByZWxvYWRlcjsNCg0KCQkJd2luZG93Lm9ubG9hZCA9IGZ1bmN0aW9uKCkgew0KCQkJCWRvY3VtZW50LmJvZHkuY2xhc3NOYW1lICs9ICIgaGFzLXByZWxvYWRlciI7DQoJCQkJZG9jdW1lbnQuYm9keS5pbnNlcnRCZWZvcmUocHJlbG9hZGVyRWxlbSwgZG9jdW1lbnQuYm9keS5maXJzdENoaWxkKTsNCgkJCX07DQoJCX0pKCk7DQoNCgkJY29uc3QgY3VycmVudFNjcmlwdCA9IGRvY3VtZW50LmN1cnJlbnRTY3JpcHQgfHwgZG9jdW1lbnQucXVlcnlTZWxlY3Rvcigic2NyaXB0W3NyYyo9XCJTR05VSUtpdC5sb2FkZXIuanNcIl0iKTsNCgkJY29uc3QgdXJsID0gY3VycmVudFNjcmlwdC5zcmMuc3BsaXQoIi8iKS5zbGljZSgwLCAtMikuam9pbigiLyIpICsgIi8iOw0KCQljb25zdCBwcmVsb2FkID0gWw0KCQkJLy8nanMvaTE4bi9TR05pMThuLmpzJw0KCQldOw0KDQoJCWxldCBmaWxlc2xvYWRlZCA9IDA7DQoJCWNvbnN0IGZpbGVzdG9sb2FkID0gcHJlbG9hZC5sZW5ndGg7DQoNCgkJaWYoZmlsZXN0b2xvYWQgPiAwKSB7DQoJCQlmb3IobGV0IGkgPSAwOyBpIDwgZmlsZXN0b2xvYWQ7IGkrKykgew0KCQkJCWNvbnN0IHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInNjcmlwdCIpOw0KCQkJCXNjcmlwdC5zcmMgPSB1cmwgKyBwcmVsb2FkW2ldOw0KCQkJCXNjcmlwdC5hc3luYyA9IGZhbHNlOw0KCQkJCXNjcmlwdC5kZWZlciA9IGZhbHNlOw0KCQkJCWN1cnJlbnRTY3JpcHQuYWZ0ZXIoc2NyaXB0KTsNCgkJCQlpZihpID09PSAwKQ0KCQkJCQlzY3JpcHQuaWQgPSAic2duLXByZWxvYWQtZW5kIjsNCgkJCQlzY3JpcHQub25sb2FkID0gZnVuY3Rpb24oKSB7DQoJCQkJCWZpbGVzbG9hZGVkKys7DQoJCQkJCXNjcmlwdC5vbmxvYWQgPSBudWxsOw0KCQkJCQlmaW5pc2hMb2FkKCk7DQoJCQkJfTsNCgkJCX0NCgkJfSBlbHNlDQoJCQlmaW5pc2hMb2FkKCk7DQoNCgkJYXN5bmMgZnVuY3Rpb24gZmluaXNoTG9hZCgpIHsNCgkJCWxldCBwcm9ncmVzcyA9IE1hdGgucm91bmQoKGZpbGVzbG9hZGVkICogMTAwKSAvIGZpbGVzdG9sb2FkKSB8fCAxMDA7DQoNCgkJCWF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gew0KCQkJCWlmKGZpbGVzbG9hZGVkID49IGZpbGVzdG9sb2FkKSB7DQoJCQkJCXJlc29sdmUoKTsNCgkJCQl9DQoJCQl9KS50aGVuKGZ1bmN0aW9uKCkgew0KCQkJCS8vaW1wb3J0KCcuL2hlbHBlcnMvaGVscGVycy5qcycpOw0KCQkJCSQoImhlYWQgPiB0aXRsZSIpLnRleHQodGl0bGUpOw0KCQkJCWlmKHR5cGVvZiBwcmVjYWxsYmFjayA9PT0gImZ1bmN0aW9uIiAmJiBwcm9ncmVzcyA9PT0gMTAwKQ0KCQkJCQlwcmVjYWxsYmFjaygpOw0KCQkJfSk7DQoJCX0NCgl9KShmdW5jdGlvbigpIHsNCgkJKGFzeW5jIGZ1bmN0aW9uKGNhbGxiYWNrKSB7DQoJCQljb25zdCBzZ251aWtpdFNjcmlwdCA9IGRvY3VtZW50LmN1cnJlbnRTY3JpcHQgfHwgZG9jdW1lbnQucXVlcnlTZWxlY3Rvcigic2NyaXB0W3NyYyo9XCJTR05VSUtpdC5sb2FkZXIuanNcIl0iKTsNCgkJCWNvbnN0IGN1cnJlbnRTY3JpcHQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgic2duLXByZWxvYWQtZW5kIikgfHwgc2dudWlraXRTY3JpcHQ7DQoNCgkJCWZ1bmN0aW9uIGdldFNjcmlwdFVSTCgpIHsNCgkJCQlyZXR1cm4gc2dudWlraXRTY3JpcHQuc3JjOw0KCQkJfQ0KDQoJCQljb25zdCB1cmwgPSBnZXRTY3JpcHRVUkwoKS5zcGxpdCgiLyIpLnNsaWNlKDAsIC0yKS5qb2luKCIvIikgKyAiLyI7DQoNCgkJCXNldFRpbWVvdXQoZnVuY3Rpb24oKSB7DQoJCQkJc3RhcnRMb2FkKCk7DQoJCQl9LCA1MDAwKTsNCg0KCQkJZnVuY3Rpb24gc3RhcnRMb2FkKCkgew0KCQkJCWNvbnN0IHNjcmlwdHMgPSBbDQoJCQkJCSJqcy9TR05VSUtpdC5idW5kbGUuanMiLA0KCQkJCV07DQoJCQkJY29uc3Qgc3R5bGVzID0gWw0KCQkJCQkiY3NzL1NHTlVJS2l0LmJ1bmRsZS5jc3MiLA0KCQkJCV07DQoJCQkJbGV0IGZpbGVzbG9hZGVkID0gMCwNCgkJCQkgICAgbGFzdFNjcmlwdCAgPSBjdXJyZW50U2NyaXB0Ow0KCQkJCWNvbnN0IGZpbGVzdG9sb2FkID0gc2NyaXB0cy5sZW5ndGggKyBzdHlsZXMubGVuZ3RoOw0KDQoJCQkJZnVuY3Rpb24gbG9hZFNjcmlwdChpKSB7DQoJCQkJCWlmKGkgPT09IHNjcmlwdHMubGVuZ3RoKSByZXR1cm47DQoNCgkJCQkJY29uc3Qgc2NyaXB0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0Iik7DQoJCQkJCXNjcmlwdC5zcmMgPSB1cmwgKyBzY3JpcHRzW2ldOw0KCQkJCQlzY3JpcHQub25sb2FkID0gZnVuY3Rpb24oKSB7DQoJCQkJCQlmaWxlc2xvYWRlZCsrOw0KCQkJCQkJU0dOVUlLaXQuY29tcG9uZW50ID0gew0KCQkJCQkJCWk6IHNjcmlwdHNbaV0sDQoJCQkJCQl9Ow0KCQkJCQkJc2NyaXB0Lm9ubG9hZCA9IG51bGw7DQoJCQkJCQkvL2NvbnNvbGUubG9nKGBMT0FERUQgU0NSSVBUOiAke3NjcmlwdC5zcmN9YCwgYCR7aX0vJHtmaWxlc3RvbG9hZH1gKTsNCgkJCQkJCWZpbmlzaExvYWQoKTsNCgkJCQkJCWxvYWRTY3JpcHQoKytpKTsNCgkJCQkJfTsNCgkJCQkJbGFzdFNjcmlwdC5hZnRlcihzY3JpcHQpOw0KCQkJCQlsYXN0U2NyaXB0ID0gbGFzdFNjcmlwdC5uZXh0RWxlbWVudFNpYmxpbmcgfHwgY3VycmVudFNjcmlwdDsNCgkJCQl9DQoNCgkJCQlmdW5jdGlvbiBsb2FkU3R5bGUoaSkgew0KCQkJCQlpZihpID09PSBzY3JpcHRzLmxlbmd0aCkgcmV0dXJuOw0KDQoJCQkJCWNvbnN0IHN0eWxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgibGluayIpOw0KCQkJCQlzdHlsZS5yZWwgPSAic3R5bGVzaGVldCI7DQoJCQkJCXN0eWxlLmhyZWYgPSB1cmwgKyBzdHlsZXNbaV07DQoJCQkJCXN0eWxlLm9ubG9hZCA9IGZ1bmN0aW9uKCkgew0KCQkJCQkJZmlsZXNsb2FkZWQrKzsNCgkJCQkJCXN0eWxlLm9ubG9hZCA9IG51bGw7DQoJCQkJCQlmaW5pc2hMb2FkKCk7DQoJCQkJCQlsb29wKCsraSk7DQoJCQkJCX07DQoJCQkJCWN1cnJlbnRTY3JpcHQuYWZ0ZXIoc3R5bGUpOw0KCQkJCX0NCg0KCQkJCWxvYWRTY3JpcHQoMCk7DQoJCQkJbG9hZFN0eWxlKDApOw0KDQoJCQkJYXN5bmMgZnVuY3Rpb24gZmluaXNoTG9hZCgpIHsNCgkJCQkJY29uc3QgcHJvZ3Jlc3MgPSBNYXRoLnJvdW5kKChmaWxlc2xvYWRlZCAqIDEwMCkgLyBmaWxlc3RvbG9hZCk7DQoNCgkJCQkJaWYodHlwZW9mIGNhbGxiYWNrID09PSAiZnVuY3Rpb24iKSB7DQoJCQkJCQljYWxsYmFjayhmaWxlc2xvYWRlZCwgZmlsZXN0b2xvYWQsIHByb2dyZXNzKTsNCgkJCQkJfQ0KCQkJCX0NCgkJCX0NCgkJfSkoYXN5bmMgZnVuY3Rpb24obG9hZGVkLCB0b3RhbCwgcHJvZ3Jlc3MpIHsNCgkJCWlmKHByb2dyZXNzID09PSAxMDApIHsNCgkJCQkvL2ltcG9ydCgnLi9pMThuL1NHTmkxOG4uanMnKTsNCgkJCQkvL2ltcG9ydCgnLi9jb21wb25lbnRzL2NvbXBvbmVudHMuanMnKTsNCgkJCQlTR05VSUtpdC5yZWFkeSA9IHRydWU7DQoJCQkJd2luZG93LlNHTlVJS2l0UmVhZHkgPSB0cnVlOw0KDQoJCQkJY29uc3QgbGVmdCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoInN0eWxlW2RhdGEtY2tlPVwidHJ1ZVwiXSIpOw0KCQkJCWlmKGxlZnQgIT09IG51bGwpDQoJCQkJCWxlZnQucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChsZWZ0KTsNCg0KCQkJCXNldFRpbWVvdXQoZnVuY3Rpb24oKSB7DQoJCQkJCSQuaG9sZFJlYWR5KGZhbHNlKTsNCgkJCQkJalF1ZXJ5LnJlYWR5KCk7DQoNCgkJCQkJU0dOVUlLaXQuc2V0T25DaGFuZ2VMaXN0ZW5lcigocHJvcCwgdmFsdWUpID0+IHsNCgkJCQkJCWlmKHByb3AgPT09ICdob2xkUHJlbG9hZGVyJyAmJiAhdmFsdWUpIHsNCgkJCQkJCQljb25zdCAkYm9keSA9ICQoImJvZHkiKTsNCg0KCQkJCQkJCSRib2R5LmNoaWxkcmVuKCIuc2duLXByZWxvYWRlciIpLmZhZGVPdXQoMjAwMCwgZnVuY3Rpb24oKSB7DQoJCQkJCQkJCSRib2R5LmNoaWxkcmVuKCIuc2duLXByZWxvYWRlciIpLnJlbW92ZSgpOw0KCQkJCQkJCQkkYm9keS5yZW1vdmVDbGFzcygiaGFzLXByZWxvYWRlciIpOw0KCQkJCQkJCX0pOw0KCQkJCQkJfQ0KCQkJCQl9KTsNCgkJCQl9LCA1MDAwKTsNCg0KCQkJfQ0KCQl9KTsNCgl9KTsNCn0pOw0KDQoNCmFzeW5jIGZ1bmN0aW9uIGdldFNHTkkxOG5JbnN0YW5jZShjYWxsYmFjaykgew0KCXJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7DQoJCWNvbnN0IHRpbWVvdXRIYW5kbGVyID0gc2V0VGltZW91dChmdW5jdGlvbigpIHsNCgkJCWlmKGNoZWNrSW50ZXJ2YWxIYW5kbGVyKQ0KCQkJCWNsZWFySW50ZXJ2YWwoY2hlY2tJbnRlcnZhbEhhbmRsZXIpOw0KCQl9LCAxMDAwMCk7DQoNCgkJY29uc3QgY2hlY2tJbnRlcnZhbEhhbmRsZXIgPSBzZXRJbnRlcnZhbChmdW5jdGlvbigpIHsNCgkJCWlmKHdpbmRvdy5TR05VSUtpdFJlYWR5KSB7DQoJCQkJaWYodGltZW91dEhhbmRsZXIpDQoJCQkJCWNsZWFyVGltZW91dCh0aW1lb3V0SGFuZGxlcik7DQoJCQkJY2xlYXJJbnRlcnZhbChjaGVja0ludGVydmFsSGFuZGxlcik7DQoJCQkJY29uc3QgYyA9IG5ldyBTR05pMThuKCk7DQoNCgkJCQlyZXNvbHZlKGMpOw0KCQkJfQ0KCQl9LCAxMDApOw0KCX0pOw0KfQ0KDQo="; +const SGNUIKitLoader = "LyoNCiAqIENvcHlyaWdodCAoYykgMjAyMi0yMDIzIFNHTmV0d29ya3MuIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQogKg0KICogVGhlIHNvZnR3YXJlIGlzIGFuIGV4Y2x1c2l2ZSBjb3B5cmlnaHQgb2YgIlNHTmV0d29ya3MiIGFuZCBpcyBwcm92aWRlZCBhcyBpcyBleGNsdXNpdmVseSB3aXRoIG9ubHkgIlVTQUdFIiBhY2Nlc3MuICJNb2RpZmljYXRpb24iLCAgIkFsdGVyYXRpb24iLCAiUmUtZGlzdHJpYnV0aW9uIiBpcyBjb21wbGV0ZWx5IHByb2hpYml0ZWQuDQogKiBWSU9MQVRJTkcgVEhFIEFCT1ZFIFRFUk1TIElTIEEgUFVOSVNIQUJMRSBPRkZFTlNFIFdISUNIIE1BWSBMRUFEIFRPIExFR0FMIENPTlNFUVVFTkNFUy4NCiAqLw0KDQovKioNCiAqIFBlcmZvcm1zIHRoZSBzcGVjaWZpZWQgYWN0aW9uIGZvciBlYWNoIGVsZW1lbnQgaW4gYW4gb2JqZWN0Lg0KICoNCiAqIEBwYXJhbSB7T2JqZWN0fSBvYmoNCiAqIEBwYXJhbSB7KHZhbHVlOmFueSwga2V5OnN0cmluZyk9PnZvaWR9IGNhbGxiYWNrIEEgZnVuY3Rpb24gdGhhdCBhY2NlcHRzIHVwIHRvIHRocmVlIGFyZ3VtZW50cy4gZm9yRWFjaCBjYWxscyB0aGUgPGI+PGk+Y2FsbGJhY2s8L2k+PC9iPiBmdW5jdGlvbiBvbmUgdGltZSBmb3IgZWFjaCBlbGVtZW50IGluIHRoZSBvYmplY3QuDQogKi8NCmNvbnN0IGZvckVhY2ggPSAob2JqLCBjYWxsYmFjaykgPT4gew0KCWxldCB2YWx1ZTsNCgkvL2NvbnRleHQgPSBjb250ZXh0IHx8IHRoaXM7ICAvL2FwcGx5IHRoZSBmdW5jdGlvbiB0byAndGhpcycgYnkgZGVmYXVsdA0KDQoJZm9yKGNvbnN0IGtleSBpbiBvYmopIHsNCgkJaWYoa2V5ICE9PSAnbGVuZ3RoJyAmJiBvYmouaGFzT3duUHJvcGVydHkoa2V5KSkgeyAgLy90byBydWxlIG91dCBpbmhlcml0ZWQgcHJvcGVydGllcw0KCQkJdmFsdWUgPSBvYmpba2V5XTsNCgkJCWlmKHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykNCgkJCQljYWxsYmFjayh2YWx1ZSwga2V5KTsNCgkJfQ0KCX0NCn0NCg0KLyoqDQogKiBBcHBlbmRzIG5ldyBlbGVtZW50cyB0byB0aGUgZW5kIG9mIGFuIG9iamVjdCwgYW5kIHJldHVybnMgdGhlIG5ldyBsZW5ndGggb2YgdGhlIG9iamVjdC4NCiAqIEBwYXJhbSB7T2JqZWN0fSBvYmoNCiAqIEBwYXJhbSB7Li4uYW55fSBpdGVtcyBOZXcgZWxlbWVudHMgdG8gYWRkIHRvIHRoZSBvYmplY3QuDQogKi8NCmNvbnN0IHB1c2ggPSAob2JqLCAuLi5pdGVtcykgPT4gew0KCWxldCBrID0gb2JqLmxlbmd0aCB8fCAwOw0KDQoJaXRlbXMuZm9yRWFjaCgodmFsdWUpID0+IHsNCgkJb2JqW2tdID0gdmFsdWU7DQoJCWsrKzsNCgkJb2JqLmxlbmd0aCA9IGs7DQoJfSk7DQp9DQoNCmNvbnN0IFNHTlVJS2l0ID0gew0KCWlzUmVhZHk6IGZhbHNlLA0KCWlzSW5pdDogZmFsc2UsDQoJaXNQcmVsb2FkZXJIZWxkOiBmYWxzZSwNCgljb25maWdzOiB7DQoJCSd1cmxzJzogew0KCQkJJ2FwaSc6IHsNCgkJCQknZ2VvbmFtZXMnOiAnaHR0cHM6Ly9zZWN1cmUuZ2VvbmFtZXMub3JnLycsDQoJCQkJJ29zbSc6ICdodHRwczovL25vbWluYXRpbS5vcGVuc3RyZWV0bWFwLm9yZy8nDQoJCQl9LA0KCQl9LA0KCQknYXBpJzogew0KCQkJJ2dlb25hbWVzJzogJycgLy91c2VybmFtZQ0KCQl9LA0KCQknZ2VvY29kaW5nJzogew0KCQkJJ2RlZmF1bHRBUEknOiAnb3NtJw0KCQl9DQoJfSwNCgljb21wb25lbnRzOiB7fSwNCglvbkNoYW5nZUxpc3RlbmVyOiB7fSwNCglvbkluaXRMaXN0ZW5lcjoge30sDQoJb25SZWFkeUxpc3RlbmVyOiB7fSwNCgljYWxsQ291bnRzOiB7DQoJCSdpbml0JzogMCwNCgkJJ3JlYWR5JzogMCwNCgkJJ2NvbmZpZyc6IDAsDQoJCSdjb21wb25lbnQnOiAwLA0KCQknaG9sZFByZWxvYWRlcic6IDAsDQoJfSwNCg0KCS8qKg0KCSAqIFRoaXMgY2FsbGJhY2sgaXMgY2FsbGVkIHdoZW4gYSBjb21wb25lbnQgaXMgbG9hZGVkL3JlbW92ZWQgb3IgdGhlIHN0YXR1cyBvZiByZWFkaW5lc3MgaXMgY2hhbmdlZC4NCgkgKg0KCSAqIEBjYWxsYmFjayBTR05VSUtpdENoYW5nZUNhbGxiYWNrDQoJICogQHBhcmFtIHtzdHJpbmd9IHN0YXRlIFRoZSBuYW1lIG9mIHRoZSBzdGF0ZSB3aGljaCBpcyBjaGFuZ2VkLg0KCSAqIEBwYXJhbSB7Ym9vbGVhbnxKU09OfSB2YWx1ZSBUaGUgdmFsdWUgb2YgdGhlIHN0YXRlIHdoaWNoIGlzIGNoYW5nZWQuDQoJICogQHBhcmFtIHtKU09OfSBjb21wb25lbnRzIFRoZSA8Yj48aT5KU09OPC9pPjwvYj4gb2JqZWN0IG9mIGxvYWRlZCA8Yj5TR05VSUtpdDwvYj4gY29tcG9uZW50cywgb3IgYW4gZW1wdHkgPGI+PGk+SlNPTjwvaT48L2I+IG9iamVjdCBpZiBubyBjb21wb25lbnRzIGxvYWRlZC4NCgkgKi8NCgkvKioNCgkgKiBUaGlzIGNhbGxiYWNrIGlzIGNhbGxlZCB3aGVuIDxiPlNHTlVJS2l0PC9iPiBpcyByZWFkeS4NCgkgKg0KCSAqIEBjYWxsYmFjayBTR05VSUtpdFJlYWR5Q2FsbGJhY2sNCgkgKiBAcGFyYW0ge2Jvb2xlYW59IGlzUmVhZHkgdGhlIHN0YXR1cyBvZiByZWFkaW5lc3Mgb2YgPGI+U0dOVUlLaXQ8L2I+Lg0KCSAqLw0KDQoJLyoqDQoJICogQWRkIGEgbG9hZGVkIDxiPlNHTlVJS2l0PC9iPiBjb21wb25lbnQuDQoJICoNCgkgKiBAcGFyYW0ge3t9fSBjb25maWcgVGhlIDxiPjxpPkpTT048L2k+PC9iPiBvYmplY3Qgb2YgdGhlIDxiPlNHTlVJS2l0PC9iPiBjb25maWd1cmF0aW9uIG9wdGlvbnMuDQoJICovDQoJc2V0IGNvbmZpZyhjb25maWcpIHsNCgkJaWYoY29uZmlnICE9PSB1bmRlZmluZWQgJiYgY29uZmlnICE9PSBudWxsICYmIGNvbmZpZyAhPT0gIiIpIHsNCgkJCXRoaXMuY29uZmlncyA9IG5ldyBTR05VS0NvbmZpZyhjb25maWcpOw0KCQkJdGhpcy5jYWxsQ291bnRzLmNvbmZpZysrOw0KDQoJCQlmb3JFYWNoKHRoaXMub25DaGFuZ2VMaXN0ZW5lciwgKGxpc3RlbmVyKSA9PiBsaXN0ZW5lcigiY29uZmlnIiwgY29uZmlnLCB0aGlzLmNvbmZpZ3MpKTsNCgkJfQ0KCX0sDQoNCgkvKioNCgkgKiBHZXQgdGhlIGxpc3Qgb2YgbG9hZGVkIDxiPlNHTlVJS2l0PC9iPiBjb21wb25lbnRzLg0KCSAqDQoJICogQHJldHVybiB7T2JqZWN0fSBUaGUgPGI+PGk+SlNPTjwvaT48L2I+IG9iamVjdCBvZiBsb2FkZWQgPGI+U0dOVUlLaXQ8L2I+IGNvbXBvbmVudHMsIG9yIGFuIGVtcHR5IDxiPjxpPkpTT048L2k+PC9iPiBvYmplY3QgaWYgbm8gY29tcG9uZW50cyBsb2FkZWQuDQoJICovDQoJZ2V0IGNvbmZpZygpIHsNCgkJcmV0dXJuIHRoaXMuY29uZmlnczsNCgl9LA0KDQoJLyoqDQoJICogQWRkIGEgbG9hZGVkIDxiPlNHTlVJS2l0PC9iPiBjb21wb25lbnQuDQoJICoNCgkgKiBAcGFyYW0ge3t9fSB2YWx1ZSBUaGUgPGI+PGk+SlNPTjwvaT48L2I+IG9iamVjdCBvZiB0aGUgbG9hZGVkIDxiPlNHTlVJS2l0PC9iPiBjb21wb25lbnQuDQoJICovDQoJc2V0IGNvbXBvbmVudCh2YWx1ZSkgew0KCQlpZih2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSBudWxsICYmIHZhbHVlICE9PSAiIikgew0KCQkJT2JqZWN0LmFzc2lnbih0aGlzLmNvbXBvbmVudHMsIHZhbHVlKTsNCgkJCXRoaXMuY2FsbENvdW50cy5jb21wb25lbnQrKzsNCg0KCQkJZm9yRWFjaCh0aGlzLm9uQ2hhbmdlTGlzdGVuZXIsIChsaXN0ZW5lcikgPT4gbGlzdGVuZXIoImNvbXBvbmVudHMiLCB2YWx1ZSwgdGhpcy5jb21wb25lbnRzKSk7DQoJCQkvL3RoaXMub25DaGFuZ2VMaXN0ZW5lci5mb3JFYWNoKChsaXN0ZW5lcikgPT4gbGlzdGVuZXIoImNvbXBvbmVudHMiLCB2YWx1ZSwgdGhpcy5jb21wb25lbnRzKSk7DQoJCX0NCgl9LA0KDQoJLyoqDQoJICogR2V0IHRoZSBsaXN0IG9mIGxvYWRlZCA8Yj5TR05VSUtpdDwvYj4gY29tcG9uZW50cy4NCgkgKg0KCSAqIEByZXR1cm4ge29iamVjdH0gVGhlIDxiPjxpPkpTT048L2k+PC9iPiBvYmplY3Qgb2YgbG9hZGVkIDxiPlNHTlVJS2l0PC9iPiBjb21wb25lbnRzLCBvciBhbiBlbXB0eSA8Yj48aT5KU09OPC9pPjwvYj4gb2JqZWN0IGlmIG5vIGNvbXBvbmVudHMgbG9hZGVkLg0KCSAqLw0KCWdldCBjb21wb25lbnQoKSB7DQoJCXJldHVybiB0aGlzLmNvbXBvbmVudHM7DQoJfSwNCg0KCS8qKg0KCSAqIENoZWNrIGlmIGEgPGI+U0dOVUlLaXQ8L2I+IGNvbXBvbmVudCBpcyBsb2FkZWQuDQoJICoNCgkgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIFRoZSA8aT5JRDwvaT4gb2YgdGhlIDxiPlNHTlVJS2l0PC9iPiBjb21wb25lbnQgdG8gY2hlY2suDQoJICovDQoJaXNDb21wb25lbnRMb2FkZWQ6IGZ1bmN0aW9uKGlkKSB7DQoJCXJldHVybiB0aGlzLmNvbXBvbmVudHMuaGFzT3duUHJvcGVydHkoaWQpOw0KCX0sDQoNCgkvKioNCgkgKiBTZXQgdGhlIHN0YXR1cyBvZiByZWFkaW5lc3Mgb2YgPGI+U0dOVUlLaXQ8L2I+Lg0KCSAqDQoJICogQHBhcmFtIHtib29sZWFufSBpc0luaXQgVGhlIHRoZSBzdGF0dXMgb2YgcmVhZGluZXNzIG9mIDxiPlNHTlVJS2l0PC9iPi4NCgkgKi8NCglzZXQgaW5pdChpc0luaXQpIHsNCgkJdGhpcy5pc0luaXQgPSBpc0luaXQ7DQoJCXRoaXMuY2FsbENvdW50cy5pbml0Kys7DQoJCWZvckVhY2godGhpcy5vbkNoYW5nZUxpc3RlbmVyLCAobGlzdGVuZXIpID0+IGxpc3RlbmVyKCJpbml0IiwgdGhpcy5pc0luaXQpKTsNCg0KCQlpZihpc0luaXQpDQoJCQlmb3JFYWNoKHRoaXMub25Jbml0TGlzdGVuZXIsIChsaXN0ZW5lcikgPT4gbGlzdGVuZXIoaXNJbml0KSk7DQoJfSwNCg0KCS8qKg0KCSAqIEdldCB0aGUgc3RhdHVzIG9mIHJlYWRpbmVzcyBvZiA8Yj5TR05VSUtpdDwvYj4uDQoJICoNCgkgKiBAcmV0dXJuIHtib29sZWFufSA8Yj48aT5UUlVFPC9pPjwvYj4gaWYgPGI+U0dOVUlLaXQ8L2I+IGlzIHJlYWR5LCA8Yj48aT5GQUxTRTwvaT48L2I+IG90aGVyd2lzZS4NCgkgKi8NCglnZXQgaW5pdCgpIHsNCgkJcmV0dXJuIHRoaXMuaXNJbml0Ow0KCX0sDQoNCgkvKioNCgkgKiBTZXQgdGhlIHN0YXR1cyBvZiByZWFkaW5lc3Mgb2YgPGI+U0dOVUlLaXQ8L2I+Lg0KCSAqDQoJICogQHBhcmFtIHtib29sZWFufSBpc1JlYWR5IFRoZSB0aGUgc3RhdHVzIG9mIHJlYWRpbmVzcyBvZiA8Yj5TR05VSUtpdDwvYj4uDQoJICovDQoJc2V0IHJlYWR5KGlzUmVhZHkpIHsNCgkJdGhpcy5pc1JlYWR5ID0gaXNSZWFkeTsNCgkJdGhpcy5jYWxsQ291bnRzLnJlYWR5Kys7DQoJCWZvckVhY2godGhpcy5vbkNoYW5nZUxpc3RlbmVyLCAobGlzdGVuZXIpID0+IGxpc3RlbmVyKCJyZWFkeSIsIHRoaXMuaXNSZWFkeSkpOw0KCQkvL3RoaXMub25DaGFuZ2VMaXN0ZW5lci5mb3JFYWNoKChsaXN0ZW5lcikgPT4gbGlzdGVuZXIoInJlYWR5IiwgdGhpcy5pc1JlYWR5KSk7DQoNCgkJaWYoaXNSZWFkeSkNCgkJCWZvckVhY2godGhpcy5vblJlYWR5TGlzdGVuZXIsIChsaXN0ZW5lcikgPT4gbGlzdGVuZXIoaXNSZWFkeSkpOw0KCQkvL3RoaXMub25SZWFkeUxpc3RlbmVyLmZvckVhY2goKGxpc3RlbmVyKSA9PiBsaXN0ZW5lcihpc1JlYWR5KSk7DQoJfSwNCg0KCS8qKg0KCSAqIEdldCB0aGUgc3RhdHVzIG9mIHJlYWRpbmVzcyBvZiA8Yj5TR05VSUtpdDwvYj4uDQoJICoNCgkgKiBAcmV0dXJuIHtib29sZWFufSA8Yj48aT5UUlVFPC9pPjwvYj4gaWYgPGI+U0dOVUlLaXQ8L2I+IGlzIHJlYWR5LCA8Yj48aT5GQUxTRTwvaT48L2I+IG90aGVyd2lzZS4NCgkgKi8NCglnZXQgcmVhZHkoKSB7DQoJCXJldHVybiB0aGlzLmlzUmVhZHk7DQoJfSwNCg0KCS8qKg0KCSAqIEhvbGQgdGhlIDxiPlNHTlVJS2l0PC9iPiBwcmVsb2FkZXIgZXZlbiBhZnRlciAgPGI+U0dOVUlLaXQ8L2I+IGhhcyBmaW5pc2hlZCBsb2FkaW5nIHRoZSBjb21wb25lbnRzLg0KCSAqDQoJICogQHBhcmFtIHtib29sZWFufSBob2xkIFRoZSB0aGUgc3RhdHVzIG9mIHJlYWRpbmVzcyBvZiA8Yj5TR05VSUtpdDwvYj4uDQoJICovDQoJc2V0IGhvbGRQcmVsb2FkZXIoaG9sZCkgew0KCQl0aGlzLmlzUHJlbG9hZGVySGVsZCA9IGhvbGQ7DQoJCXRoaXMuY2FsbENvdW50cy5ob2xkUHJlbG9hZGVyKys7DQoJCWZvckVhY2godGhpcy5vbkNoYW5nZUxpc3RlbmVyLCAobGlzdGVuZXIpID0+IGxpc3RlbmVyKCJob2xkUHJlbG9hZGVyIiwgdGhpcy5pc1ByZWxvYWRlckhlbGQpKTsNCgkJLy90aGlzLm9uQ2hhbmdlTGlzdGVuZXIuZm9yRWFjaCgobGlzdGVuZXIpID0+IGxpc3RlbmVyKCJob2xkUHJlbG9hZGVyIiwgdGhpcy5pc1ByZWxvYWRlckhlbGQpKTsNCgl9LA0KDQoJLyoqDQoJICogR2V0IHRoZSBzdGF0dXMgb2YgcmVhZGluZXNzIG9mIDxiPlNHTlVJS2l0PC9iPi4NCgkgKg0KCSAqIEByZXR1cm4ge2Jvb2xlYW59IDxiPjxpPlRSVUU8L2k+PC9iPiBpZiA8Yj5TR05VSUtpdDwvYj4gaXMgcmVhZHksIDxiPjxpPkZBTFNFPC9pPjwvYj4gb3RoZXJ3aXNlLg0KCSAqLw0KCWdldCBob2xkUHJlbG9hZGVyKCkgew0KCQlyZXR1cm4gdGhpcy5pc1ByZWxvYWRlckhlbGQ7DQoJfSwNCg0KCS8qKg0KCSAqIFNldCB0aGUgaGFuZGxlciBmb3IgPGI+U0dOVUlLaXQ8L2I+IDxiPjxpPk9uQ2hhbmdlPC9pPjwvYj4gZXZlbnQsIHdoaWNoIHdpbGwgYmUgdHJpZ2dlcmVkIHdoZW4gYSBjb21wb25lbnQgaXMgbG9hZGVkL3JlbW92ZWQgb3IgdGhlIHN0YXR1cyBvZiByZWFkaW5lc3MgaXMgY2hhbmdlZC4NCgkgKg0KCSAqIEBwYXJhbSB7U0dOVUlLaXRDaGFuZ2VDYWxsYmFja31saXN0ZW5lcg0KCSAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn1baWQ9dW5kZWZpbmVkXQ0KCSAqLw0KCXNldE9uQ2hhbmdlTGlzdGVuZXI6IGZ1bmN0aW9uKGxpc3RlbmVyLCBpZCkgew0KCQlpZih0eXBlb2YgaWQgIT09ICdzdHJpbmcnIHx8ICQuaXNOdW1lcmljKGlkKSkNCgkJCXRoaXMub25DaGFuZ2VMaXN0ZW5lcltpZF0gPSBsaXN0ZW5lcjsNCgkJZWxzZQ0KCQkJcHVzaCh0aGlzLm9uQ2hhbmdlTGlzdGVuZXIsIGxpc3RlbmVyKTsNCgl9LA0KDQoJLyoqDQoJICogU2V0IHRoZSBoYW5kbGVyIGZvciA8Yj5TR05VSUtpdDwvYj4gPGI+PGk+T25SZWFkeTwvaT48L2I+IGV2ZW50LCB3aGljaCB3aWxsIGJlIHRyaWdnZXJlZCB3aGVuIHRoZSA8Yj5TR05VSUtpdDwvYj4gaXMgcmVhZHkuDQoJICoNCgkgKiBAcGFyYW0ge1NHTlVJS2l0UmVhZHlDYWxsYmFja31saXN0ZW5lcg0KCSAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn1baWQ9dW5kZWZpbmVkXQ0KCSAqLw0KCXNldE9uSW5pdExpc3RlbmVyOiBmdW5jdGlvbihsaXN0ZW5lciwgaWQpIHsNCgkJaWYodHlwZW9mIGlkICE9PSAnc3RyaW5nJyB8fCAkLmlzTnVtZXJpYyhpZCkpDQoJCQl0aGlzLm9uSW5pdExpc3RlbmVyW2lkXSA9IGxpc3RlbmVyOw0KCQllbHNlDQoJCQlwdXNoKHRoaXMub25Jbml0TGlzdGVuZXIsIGxpc3RlbmVyKTsNCg0KCQlpZih0aGlzLmluaXQpDQoJCQlmb3JFYWNoKHRoaXMub25Jbml0TGlzdGVuZXIsIChsaXN0ZW5lcikgPT4gbGlzdGVuZXIodGhpcy5pc0luaXQpKTsNCgl9LA0KDQoJLyoqDQoJICogU2V0IHRoZSBoYW5kbGVyIGZvciA8Yj5TR05VSUtpdDwvYj4gPGI+PGk+T25SZWFkeTwvaT48L2I+IGV2ZW50LCB3aGljaCB3aWxsIGJlIHRyaWdnZXJlZCB3aGVuIHRoZSA8Yj5TR05VSUtpdDwvYj4gaXMgcmVhZHkuDQoJICoNCgkgKiBAcGFyYW0ge1NHTlVJS2l0UmVhZHlDYWxsYmFja31saXN0ZW5lcg0KCSAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn1baWQ9dW5kZWZpbmVkXQ0KCSAqLw0KCXNldE9uUmVhZHlMaXN0ZW5lcjogZnVuY3Rpb24obGlzdGVuZXIsIGlkKSB7DQoJCWlmKHR5cGVvZiBpZCAhPT0gJ3N0cmluZycgfHwgJC5pc051bWVyaWMoaWQpKQ0KCQkJdGhpcy5vblJlYWR5TGlzdGVuZXJbaWRdID0gbGlzdGVuZXI7DQoJCWVsc2UNCgkJCXB1c2godGhpcy5vblJlYWR5TGlzdGVuZXIsIGxpc3RlbmVyKTsNCg0KCQlpZih0aGlzLnJlYWR5KQ0KCQkJZm9yRWFjaCh0aGlzLm9uUmVhZHlMaXN0ZW5lciwgKGxpc3RlbmVyKSA9PiBsaXN0ZW5lcih0aGlzLmlzUmVhZHkpKTsNCgkJLy90aGlzLm9uUmVhZHlMaXN0ZW5lci5mb3JFYWNoKChsaXN0ZW5lcikgPT4gbGlzdGVuZXIodGhpcy5yZWFkeSkpOw0KCX0sDQp9Ow0Kd2luZG93LlNHTlVJS2l0ID0gU0dOVUlLaXQ7DQoNCmlmKHR5cGVvZiBqUXVlcnkgPT09ICd1bmRlZmluZWQnKSB7DQoJLyohIGpRdWVyeSB2My42LjAgfCAoYykgT3BlbkpTIEZvdW5kYXRpb24gYW5kIG90aGVyIGNvbnRyaWJ1dG9ycyB8IGpxdWVyeS5vcmcvbGljZW5zZSAqLw0KCSFmdW5jdGlvbihlLCB0KSB7DQoJCSJ1c2Ugc3RyaWN0IjsNCgkJIm9iamVjdCIgPT0gdHlwZW9mIG1vZHVsZSAmJiAib2JqZWN0IiA9PSB0eXBlb2YgbW9kdWxlLmV4cG9ydHMgPyBtb2R1bGUuZXhwb3J0cyA9IGUuZG9jdW1lbnQgPyB0KGUsICEwKSA6IGZ1bmN0aW9uKGUpIHsNCgkJCWlmKCFlLmRvY3VtZW50KSB0aHJvdyBuZXcgRXJyb3IoImpRdWVyeSByZXF1aXJlcyBhIHdpbmRvdyB3aXRoIGEgZG9jdW1lbnQiKTsNCgkJCXJldHVybiB0KGUpDQoJCX0gOiB0KGUpDQoJfSgidW5kZWZpbmVkIiAhPSB0eXBlb2Ygd2luZG93ID8gd2luZG93IDogdGhpcywgZnVuY3Rpb24oQywgZSkgew0KCQkidXNlIHN0cmljdCI7DQoJCXZhciB0ID0gW10sDQoJCSAgICByID0gT2JqZWN0LmdldFByb3RvdHlwZU9mLA0KCQkgICAgcyA9IHQuc2xpY2UsDQoJCSAgICBnID0gdC5mbGF0ID8gZnVuY3Rpb24oZSkge3JldHVybiB0LmZsYXQuY2FsbChlKX0gOiBmdW5jdGlvbihlKSB7cmV0dXJuIHQuY29uY2F0LmFwcGx5KFtdLCBlKX0sDQoJCSAgICB1ID0gdC5wdXNoLA0KCQkgICAgaSA9IHQuaW5kZXhPZiwNCgkJICAgIG4gPSB7fSwNCgkJICAgIG8gPSBuLnRvU3RyaW5nLA0KCQkgICAgdiA9IG4uaGFzT3duUHJvcGVydHksDQoJCSAgICBhID0gdi50b1N0cmluZywNCgkJICAgIGwgPSBhLmNhbGwoT2JqZWN0KSwNCgkJICAgIHkgPSB7fSwNCgkJICAgIG0gPSBmdW5jdGlvbihlKSB7cmV0dXJuICJmdW5jdGlvbiIgPT0gdHlwZW9mIGUgJiYgIm51bWJlciIgIT0gdHlwZW9mIGUubm9kZVR5cGUgJiYgImZ1bmN0aW9uIiAhPSB0eXBlb2YgZS5pdGVtfSwNCgkJICAgIHggPSBmdW5jdGlvbihlKSB7cmV0dXJuIG51bGwgIT0gZSAmJiBlID09PSBlLndpbmRvd30sDQoJCSAgICBFID0gQy5kb2N1bWVudCwNCgkJICAgIGMgPSB7dHlwZTogITAsIHNyYzogITAsIG5vbmNlOiAhMCwgbm9Nb2R1bGU6ICEwfTsNCg0KCQlmdW5jdGlvbiBiKGUsIHQsIG4pIHsNCgkJCXZhciByLCBpLCBvID0gKG4gPSBuIHx8IEUpLmNyZWF0ZUVsZW1lbnQoInNjcmlwdCIpOw0KCQkJaWYoby50ZXh0ID0gZSwgdCkgZm9yKHIgaW4gYykgKGkgPSB0W3JdIHx8IHQuZ2V0QXR0cmlidXRlICYmIHQuZ2V0QXR0cmlidXRlKHIpKSAmJiBvLnNldEF0dHJpYnV0ZShyLCBpKTsNCgkJCW4uaGVhZC5hcHBlbmRDaGlsZChvKS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG8pDQoJCX0NCg0KCQlmdW5jdGlvbiB3KGUpIHtyZXR1cm4gbnVsbCA9PSBlID8gZSArICIiIDogIm9iamVjdCIgPT0gdHlwZW9mIGUgfHwgImZ1bmN0aW9uIiA9PSB0eXBlb2YgZSA/IG5bby5jYWxsKGUpXSB8fCAib2JqZWN0IiA6IHR5cGVvZiBlfQ0KDQoJCXZhciBmID0gIjMuNi4wIiwgUyA9IGZ1bmN0aW9uKGUsIHQpIHtyZXR1cm4gbmV3IFMuZm4uaW5pdChlLCB0KX07DQoNCgkJZnVuY3Rpb24gcChlKSB7DQoJCQl2YXIgdCA9ICEhZSAmJiAibGVuZ3RoIiBpbiBlICYmIGUubGVuZ3RoLCBuID0gdyhlKTsNCgkJCXJldHVybiAhbShlKSAmJiAheChlKSAmJiAoImFycmF5IiA9PT0gbiB8fCAwID09PSB0IHx8ICJudW1iZXIiID09IHR5cGVvZiB0ICYmIDAgPCB0ICYmIHQgLSAxIGluIGUpDQoJCX0NCg0KCQlTLmZuID0gUy5wcm90b3R5cGUgPSB7DQoJCQlqcXVlcnk6IGYsDQoJCQljb25zdHJ1Y3RvcjogUywNCgkJCWxlbmd0aDogMCwNCgkJCXRvQXJyYXk6IGZ1bmN0aW9uKCkge3JldHVybiBzLmNhbGwodGhpcyl9LA0KCQkJZ2V0OiBmdW5jdGlvbihlKSB7cmV0dXJuIG51bGwgPT0gZSA/IHMuY2FsbCh0aGlzKSA6IGUgPCAwID8gdGhpc1tlICsgdGhpcy5sZW5ndGhdIDogdGhpc1tlXX0sDQoJCQlwdXNoU3RhY2s6IGZ1bmN0aW9uKGUpIHsNCgkJCQl2YXIgdCA9IFMubWVyZ2UodGhpcy5jb25zdHJ1Y3RvcigpLCBlKTsNCgkJCQlyZXR1cm4gdC5wcmV2T2JqZWN0ID0gdGhpcywgdA0KCQkJfSwNCgkJCWVhY2g6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gUy5lYWNoKHRoaXMsIGUpfSwNCgkJCW1hcDogZnVuY3Rpb24obikge3JldHVybiB0aGlzLnB1c2hTdGFjayhTLm1hcCh0aGlzLCBmdW5jdGlvbihlLCB0KSB7cmV0dXJuIG4uY2FsbChlLCB0LCBlKX0pKX0sDQoJCQlzbGljZTogZnVuY3Rpb24oKSB7cmV0dXJuIHRoaXMucHVzaFN0YWNrKHMuYXBwbHkodGhpcywgYXJndW1lbnRzKSl9LA0KCQkJZmlyc3Q6IGZ1bmN0aW9uKCkge3JldHVybiB0aGlzLmVxKDApfSwNCgkJCWxhc3Q6IGZ1bmN0aW9uKCkge3JldHVybiB0aGlzLmVxKC0xKX0sDQoJCQlldmVuOiBmdW5jdGlvbigpIHtyZXR1cm4gdGhpcy5wdXNoU3RhY2soUy5ncmVwKHRoaXMsIGZ1bmN0aW9uKGUsIHQpIHtyZXR1cm4gKHQgKyAxKSAlIDJ9KSl9LA0KCQkJb2RkOiBmdW5jdGlvbigpIHtyZXR1cm4gdGhpcy5wdXNoU3RhY2soUy5ncmVwKHRoaXMsIGZ1bmN0aW9uKGUsIHQpIHtyZXR1cm4gdCAlIDJ9KSl9LA0KCQkJZXE6IGZ1bmN0aW9uKGUpIHsNCgkJCQl2YXIgdCA9IHRoaXMubGVuZ3RoLCBuID0gK2UgKyAoZSA8IDAgPyB0IDogMCk7DQoJCQkJcmV0dXJuIHRoaXMucHVzaFN0YWNrKDAgPD0gbiAmJiBuIDwgdCA/IFt0aGlzW25dXSA6IFtdKQ0KCQkJfSwNCgkJCWVuZDogZnVuY3Rpb24oKSB7cmV0dXJuIHRoaXMucHJldk9iamVjdCB8fCB0aGlzLmNvbnN0cnVjdG9yKCl9LA0KCQkJcHVzaDogdSwNCgkJCXNvcnQ6IHQuc29ydCwNCgkJCXNwbGljZTogdC5zcGxpY2UNCgkJfSwgUy5leHRlbmQgPSBTLmZuLmV4dGVuZCA9IGZ1bmN0aW9uKCkgew0KCQkJdmFyIGUsIHQsIG4sIHIsIGksIG8sIGEgPSBhcmd1bWVudHNbMF0gfHwge30sIHMgPSAxLCB1ID0gYXJndW1lbnRzLmxlbmd0aCwgbCA9ICExOw0KCQkJZm9yKCJib29sZWFuIiA9PSB0eXBlb2YgYSAmJiAobCA9IGEsIGEgPSBhcmd1bWVudHNbc10gfHwge30sIHMrKyksICJvYmplY3QiID09IHR5cGVvZiBhIHx8IG0oYSkgfHwgKGEgPSB7fSksIHMgPT09IHUgJiYgKGEgPSB0aGlzLCBzLS0pOyBzIDwgdTsgcysrKSBpZihudWxsICE9IChlID0gYXJndW1lbnRzW3NdKSkgZm9yKHQgaW4gZSkgciA9IGVbdF0sICJfX3Byb3RvX18iICE9PSB0ICYmIGEgIT09IHIgJiYgKGwgJiYgciAmJiAoUy5pc1BsYWluT2JqZWN0KHIpIHx8IChpID0gQXJyYXkuaXNBcnJheShyKSkpID8gKG4gPSBhW3RdLCBvID0gaSAmJiAhQXJyYXkuaXNBcnJheShuKSA/IFtdIDogaSB8fCBTLmlzUGxhaW5PYmplY3QobikgPyBuIDoge30sIGkgPSAhMSwgYVt0XSA9IFMuZXh0ZW5kKGwsIG8sIHIpKSA6IHZvaWQgMCAhPT0gciAmJiAoYVt0XSA9IHIpKTsNCgkJCXJldHVybiBhDQoJCX0sIFMuZXh0ZW5kKHsNCgkJCWV4cGFuZG86ICJqUXVlcnkiICsgKGYgKyBNYXRoLnJhbmRvbSgpKS5yZXBsYWNlKC9cRC9nLCAiIiksIGlzUmVhZHk6ICEwLCBlcnJvcjogZnVuY3Rpb24oZSkge3Rocm93IG5ldyBFcnJvcihlKX0sIG5vb3A6IGZ1bmN0aW9uKCkge30sIGlzUGxhaW5PYmplY3Q6IGZ1bmN0aW9uKGUpIHsNCgkJCQl2YXIgdCwgbjsNCgkJCQlyZXR1cm4gISghZSB8fCAiW29iamVjdCBPYmplY3RdIiAhPT0gby5jYWxsKGUpKSAmJiAoISh0ID0gcihlKSkgfHwgImZ1bmN0aW9uIiA9PSB0eXBlb2YgKG4gPSB2LmNhbGwodCwgImNvbnN0cnVjdG9yIikgJiYgdC5jb25zdHJ1Y3RvcikgJiYgYS5jYWxsKG4pID09PSBsKQ0KCQkJfSwgaXNFbXB0eU9iamVjdDogZnVuY3Rpb24oZSkgew0KCQkJCXZhciB0Ow0KCQkJCWZvcih0IGluIGUpIHJldHVybiAhMTsNCgkJCQlyZXR1cm4gITANCgkJCX0sIGdsb2JhbEV2YWw6IGZ1bmN0aW9uKGUsIHQsIG4pIHtiKGUsIHtub25jZTogdCAmJiB0Lm5vbmNlfSwgbil9LCBlYWNoOiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJdmFyIG4sIHIgPSAwOw0KCQkJCWlmKHAoZSkpIHtmb3IobiA9IGUubGVuZ3RoOyByIDwgbjsgcisrKSBpZighMSA9PT0gdC5jYWxsKGVbcl0sIHIsIGVbcl0pKSBicmVha30gZWxzZSBmb3IociBpbiBlKSBpZighMSA9PT0gdC5jYWxsKGVbcl0sIHIsIGVbcl0pKSBicmVhazsNCgkJCQlyZXR1cm4gZQ0KCQkJfSwgbWFrZUFycmF5OiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJdmFyIG4gPSB0IHx8IFtdOw0KCQkJCXJldHVybiBudWxsICE9IGUgJiYgKHAoT2JqZWN0KGUpKSA/IFMubWVyZ2UobiwgInN0cmluZyIgPT0gdHlwZW9mIGUgPyBbZV0gOiBlKSA6IHUuY2FsbChuLCBlKSksIG4NCgkJCX0sIGluQXJyYXk6IGZ1bmN0aW9uKGUsIHQsIG4pIHtyZXR1cm4gbnVsbCA9PSB0ID8gLTEgOiBpLmNhbGwodCwgZSwgbil9LCBtZXJnZTogZnVuY3Rpb24oZSwgdCkgew0KCQkJCWZvcih2YXIgbiA9ICt0Lmxlbmd0aCwgciA9IDAsIGkgPSBlLmxlbmd0aDsgciA8IG47IHIrKykgZVtpKytdID0gdFtyXTsNCgkJCQlyZXR1cm4gZS5sZW5ndGggPSBpLCBlDQoJCQl9LCBncmVwOiBmdW5jdGlvbihlLCB0LCBuKSB7DQoJCQkJZm9yKHZhciByID0gW10sIGkgPSAwLCBvID0gZS5sZW5ndGgsIGEgPSAhbjsgaSA8IG87IGkrKykgIXQoZVtpXSwgaSkgIT09IGEgJiYgci5wdXNoKGVbaV0pOw0KCQkJCXJldHVybiByDQoJCQl9LCBtYXA6IGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQl2YXIgciwgaSwgbyA9IDAsIGEgPSBbXTsNCgkJCQlpZihwKGUpKSBmb3IociA9IGUubGVuZ3RoOyBvIDwgcjsgbysrKSBudWxsICE9IChpID0gdChlW29dLCBvLCBuKSkgJiYgYS5wdXNoKGkpOyBlbHNlIGZvcihvIGluIGUpIG51bGwgIT0gKGkgPSB0KGVbb10sIG8sIG4pKSAmJiBhLnB1c2goaSk7DQoJCQkJcmV0dXJuIGcoYSkNCgkJCX0sIGd1aWQ6IDEsIHN1cHBvcnQ6IHkNCgkJfSksICJmdW5jdGlvbiIgPT0gdHlwZW9mIFN5bWJvbCAmJiAoUy5mbltTeW1ib2wuaXRlcmF0b3JdID0gdFtTeW1ib2wuaXRlcmF0b3JdKSwgUy5lYWNoKCJCb29sZWFuIE51bWJlciBTdHJpbmcgRnVuY3Rpb24gQXJyYXkgRGF0ZSBSZWdFeHAgT2JqZWN0IEVycm9yIFN5bWJvbCIuc3BsaXQoIiAiKSwgZnVuY3Rpb24oZSwgdCkge25bIltvYmplY3QgIiArIHQgKyAiXSJdID0gdC50b0xvd2VyQ2FzZSgpfSk7DQoJCXZhciBkID0gZnVuY3Rpb24obikgew0KCQkJdmFyIGUsDQoJCQkgICAgZCwNCgkJCSAgICBiLA0KCQkJICAgIG8sDQoJCQkgICAgaSwNCgkJCSAgICBoLA0KCQkJICAgIGYsDQoJCQkgICAgZywNCgkJCSAgICB3LA0KCQkJICAgIHUsDQoJCQkgICAgbCwNCgkJCSAgICBULA0KCQkJICAgIEMsDQoJCQkgICAgYSwNCgkJCSAgICBFLA0KCQkJICAgIHYsDQoJCQkgICAgcywNCgkJCSAgICBjLA0KCQkJICAgIHksDQoJCQkgICAgUyAgPSAic2l6emxlIiArIDEgKiBuZXcgRGF0ZSwNCgkJCSAgICBwICA9IG4uZG9jdW1lbnQsDQoJCQkgICAgayAgPSAwLA0KCQkJICAgIHIgID0gMCwNCgkJCSAgICBtICA9IHVlKCksDQoJCQkgICAgeCAgPSB1ZSgpLA0KCQkJICAgIEEgID0gdWUoKSwNCgkJCSAgICBOICA9IHVlKCksDQoJCQkgICAgaiAgPSBmdW5jdGlvbihlLCB0KSB7cmV0dXJuIGUgPT09IHQgJiYgKGwgPSAhMCksIDB9LA0KCQkJICAgIEQgID0ge30uaGFzT3duUHJvcGVydHksDQoJCQkgICAgdCAgPSBbXSwNCgkJCSAgICBxICA9IHQucG9wLA0KCQkJICAgIEwgID0gdC5wdXNoLA0KCQkJICAgIEggID0gdC5wdXNoLA0KCQkJICAgIE8gID0gdC5zbGljZSwNCgkJCSAgICBQICA9IGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQkgICAgZm9yKHZhciBuID0gMCwgciA9IGUubGVuZ3RoOyBuIDwgcjsgbisrKSBpZihlW25dID09PSB0KSByZXR1cm4gbjsNCgkJCQkgICAgcmV0dXJuIC0xDQoJCQkgICAgfSwNCgkJCSAgICBSICA9ICJjaGVja2VkfHNlbGVjdGVkfGFzeW5jfGF1dG9mb2N1c3xhdXRvcGxheXxjb250cm9sc3xkZWZlcnxkaXNhYmxlZHxoaWRkZW58aXNtYXB8bG9vcHxtdWx0aXBsZXxvcGVufHJlYWRvbmx5fHJlcXVpcmVkfHNjb3BlZCIsDQoJCQkgICAgTSAgPSAiW1xceDIwXFx0XFxyXFxuXFxmXSIsDQoJCQkgICAgSSAgPSAiKD86XFxcXFtcXGRhLWZBLUZdezEsNn0iICsgTSArICI/fFxcXFxbXlxcclxcblxcZl18W1xcdy1dfFteXDAtXFx4N2ZdKSsiLA0KCQkJICAgIFcgID0gIlxcWyIgKyBNICsgIiooIiArIEkgKyAiKSg/OiIgKyBNICsgIiooWypeJHwhfl0/PSkiICsgTSArICIqKD86JygoPzpcXFxcLnxbXlxcXFwnXSkqKSd8XCIoKD86XFxcXC58W15cXFxcXCJdKSopXCJ8KCIgKyBJICsgIikpfCkiICsgTSArICIqXFxdIiwNCgkJCSAgICBGICA9ICI6KCIgKyBJICsgIikoPzpcXCgoKCcoKD86XFxcXC58W15cXFxcJ10pKiknfFwiKCg/OlxcXFwufFteXFxcXFwiXSkqKVwiKXwoKD86XFxcXC58W15cXFxcKClbXFxdXXwiICsgVyArICIpKil8LiopXFwpfCkiLA0KCQkJICAgIEIgID0gbmV3IFJlZ0V4cChNICsgIisiLCAiZyIpLA0KCQkJICAgICQgID0gbmV3IFJlZ0V4cCgiXiIgKyBNICsgIit8KCg/Ol58W15cXFxcXSkoPzpcXFxcLikqKSIgKyBNICsgIiskIiwgImciKSwNCgkJCSAgICBfICA9IG5ldyBSZWdFeHAoIl4iICsgTSArICIqLCIgKyBNICsgIioiKSwNCgkJCSAgICB6ICA9IG5ldyBSZWdFeHAoIl4iICsgTSArICIqKFs+K35dfCIgKyBNICsgIikiICsgTSArICIqIiksDQoJCQkgICAgVSAgPSBuZXcgUmVnRXhwKE0gKyAifD4iKSwNCgkJCSAgICBYICA9IG5ldyBSZWdFeHAoRiksDQoJCQkgICAgViAgPSBuZXcgUmVnRXhwKCJeIiArIEkgKyAiJCIpLA0KCQkJICAgIEcgID0gew0KCQkJCSAgICBJRDogbmV3IFJlZ0V4cCgiXiMoIiArIEkgKyAiKSIpLA0KCQkJCSAgICBDTEFTUzogbmV3IFJlZ0V4cCgiXlxcLigiICsgSSArICIpIiksDQoJCQkJICAgIFRBRzogbmV3IFJlZ0V4cCgiXigiICsgSSArICJ8WypdKSIpLA0KCQkJCSAgICBBVFRSOiBuZXcgUmVnRXhwKCJeIiArIFcpLA0KCQkJCSAgICBQU0VVRE86IG5ldyBSZWdFeHAoIl4iICsgRiksDQoJCQkJICAgIENISUxEOiBuZXcgUmVnRXhwKCJeOihvbmx5fGZpcnN0fGxhc3R8bnRofG50aC1sYXN0KS0oY2hpbGR8b2YtdHlwZSkoPzpcXCgiICsgTSArICIqKGV2ZW58b2RkfCgoWystXXwpKFxcZCopbnwpIiArIE0gKyAiKig/OihbKy1dfCkiICsgTSArICIqKFxcZCspfCkpIiArIE0gKyAiKlxcKXwpIiwgImkiKSwNCgkJCQkgICAgYm9vbDogbmV3IFJlZ0V4cCgiXig/OiIgKyBSICsgIikkIiwgImkiKSwNCgkJCQkgICAgbmVlZHNDb250ZXh0OiBuZXcgUmVnRXhwKCJeIiArIE0gKyAiKls+K35dfDooZXZlbnxvZGR8ZXF8Z3R8bHR8bnRofGZpcnN0fGxhc3QpKD86XFwoIiArIE0gKyAiKigoPzotXFxkKT9cXGQqKSIgKyBNICsgIipcXCl8KSg/PVteLV18JCkiLCAiaSIpDQoJCQkgICAgfSwNCgkJCSAgICBZICA9IC9IVE1MJC9pLA0KCQkJICAgIFEgID0gL14oPzppbnB1dHxzZWxlY3R8dGV4dGFyZWF8YnV0dG9uKSQvaSwNCgkJCSAgICBKICA9IC9eaFxkJC9pLA0KCQkJICAgIEsgID0gL15bXntdK1x7XHMqXFtuYXRpdmUgXHcvLA0KCQkJICAgIFogID0gL14oPzojKFtcdy1dKyl8KFx3Kyl8XC4oW1x3LV0rKSkkLywNCgkJCSAgICBlZSA9IC9bK35dLywNCgkJCSAgICB0ZSA9IG5ldyBSZWdFeHAoIlxcXFxbXFxkYS1mQS1GXXsxLDZ9IiArIE0gKyAiP3xcXFxcKFteXFxyXFxuXFxmXSkiLCAiZyIpLA0KCQkJICAgIG5lID0gZnVuY3Rpb24oZSwgdCkgew0KCQkJCSAgICB2YXIgbiA9ICIweCIgKyBlLnNsaWNlKDEpIC0gNjU1MzY7DQoJCQkJICAgIHJldHVybiB0IHx8IChuIDwgMCA/IFN0cmluZy5mcm9tQ2hhckNvZGUobiArIDY1NTM2KSA6IFN0cmluZy5mcm9tQ2hhckNvZGUobiA+PiAxMCB8IDU1Mjk2LCAxMDIzICYgbiB8IDU2MzIwKSkNCgkJCSAgICB9LA0KCQkJICAgIHJlID0gLyhbXDAtXHgxZlx4N2ZdfF4tP1xkKXxeLSR8W15cMC1ceDFmXHg3Zi1cdUZGRkZcdy1dL2csDQoJCQkgICAgaWUgPSBmdW5jdGlvbihlLCB0KSB7cmV0dXJuIHQgPyAiXDAiID09PSBlID8gIlx1ZmZmZCIgOiBlLnNsaWNlKDAsIC0xKSArICJcXCIgKyBlLmNoYXJDb2RlQXQoZS5sZW5ndGggLSAxKS50b1N0cmluZygxNikgKyAiICIgOiAiXFwiICsgZX0sDQoJCQkgICAgb2UgPSBmdW5jdGlvbigpIHtUKCl9LA0KCQkJICAgIGFlID0gYmUoZnVuY3Rpb24oZSkge3JldHVybiAhMCA9PT0gZS5kaXNhYmxlZCAmJiAiZmllbGRzZXQiID09PSBlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCl9LCB7ZGlyOiAicGFyZW50Tm9kZSIsIG5leHQ6ICJsZWdlbmQifSk7DQoJCQl0cnkge0guYXBwbHkodCA9IE8uY2FsbChwLmNoaWxkTm9kZXMpLCBwLmNoaWxkTm9kZXMpLCB0W3AuY2hpbGROb2Rlcy5sZW5ndGhdLm5vZGVUeXBlfSBjYXRjaChlKSB7DQoJCQkJSCA9IHsNCgkJCQkJYXBwbHk6IHQubGVuZ3RoID8gZnVuY3Rpb24oZSwgdCkge0wuYXBwbHkoZSwgTy5jYWxsKHQpKX0gOiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJCQl2YXIgbiA9IGUubGVuZ3RoLCByID0gMDsNCgkJCQkJCXdoaWxlKGVbbisrXSA9IHRbcisrXSkgOw0KCQkJCQkJZS5sZW5ndGggPSBuIC0gMQ0KCQkJCQl9DQoJCQkJfQ0KCQkJfQ0KDQoJCQlmdW5jdGlvbiBzZSh0LCBlLCBuLCByKSB7DQoJCQkJdmFyIGksIG8sIGEsIHMsIHUsIGwsIGMsIGYgPSBlICYmIGUub3duZXJEb2N1bWVudCwgcCA9IGUgPyBlLm5vZGVUeXBlIDogOTsNCgkJCQlpZihuID0gbiB8fCBbXSwgInN0cmluZyIgIT0gdHlwZW9mIHQgfHwgIXQgfHwgMSAhPT0gcCAmJiA5ICE9PSBwICYmIDExICE9PSBwKSByZXR1cm4gbjsNCgkJCQlpZighciAmJiAoVChlKSwgZSA9IGUgfHwgQywgRSkpIHsNCgkJCQkJaWYoMTEgIT09IHAgJiYgKHUgPSBaLmV4ZWModCkpKSBpZihpID0gdVsxXSkgew0KCQkJCQkJaWYoOSA9PT0gcCkgew0KCQkJCQkJCWlmKCEoYSA9IGUuZ2V0RWxlbWVudEJ5SWQoaSkpKSByZXR1cm4gbjsNCgkJCQkJCQlpZihhLmlkID09PSBpKSByZXR1cm4gbi5wdXNoKGEpLCBuDQoJCQkJCQl9IGVsc2UgaWYoZiAmJiAoYSA9IGYuZ2V0RWxlbWVudEJ5SWQoaSkpICYmIHkoZSwgYSkgJiYgYS5pZCA9PT0gaSkgcmV0dXJuIG4ucHVzaChhKSwgbg0KCQkJCQl9IGVsc2Ugew0KCQkJCQkJaWYodVsyXSkgcmV0dXJuIEguYXBwbHkobiwgZS5nZXRFbGVtZW50c0J5VGFnTmFtZSh0KSksIG47DQoJCQkJCQlpZigoaSA9IHVbM10pICYmIGQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSAmJiBlLmdldEVsZW1lbnRzQnlDbGFzc05hbWUpIHJldHVybiBILmFwcGx5KG4sIGUuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShpKSksIG4NCgkJCQkJfQ0KCQkJCQlpZihkLnFzYSAmJiAhTlt0ICsgIiAiXSAmJiAoIXYgfHwgIXYudGVzdCh0KSkgJiYgKDEgIT09IHAgfHwgIm9iamVjdCIgIT09IGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKSkpIHsNCgkJCQkJCWlmKGMgPSB0LCBmID0gZSwgMSA9PT0gcCAmJiAoVS50ZXN0KHQpIHx8IHoudGVzdCh0KSkpIHsNCgkJCQkJCQkoZiA9IGVlLnRlc3QodCkgJiYgeWUoZS5wYXJlbnROb2RlKSB8fCBlKSA9PT0gZSAmJiBkLnNjb3BlIHx8ICgocyA9IGUuZ2V0QXR0cmlidXRlKCJpZCIpKSA/IHMgPSBzLnJlcGxhY2UocmUsIGllKSA6IGUuc2V0QXR0cmlidXRlKCJpZCIsIHMgPSBTKSksIG8gPSAobCA9IGgodCkpLmxlbmd0aDsNCgkJCQkJCQl3aGlsZShvLS0pIGxbb10gPSAocyA/ICIjIiArIHMgOiAiOnNjb3BlIikgKyAiICIgKyB4ZShsW29dKTsNCgkJCQkJCQljID0gbC5qb2luKCIsIikNCgkJCQkJCX0NCgkJCQkJCXRyeSB7cmV0dXJuIEguYXBwbHkobiwgZi5xdWVyeVNlbGVjdG9yQWxsKGMpKSwgbn0gY2F0Y2goZSkge04odCwgITApfSBmaW5hbGx5IHtzID09PSBTICYmIGUucmVtb3ZlQXR0cmlidXRlKCJpZCIpfQ0KCQkJCQl9DQoJCQkJfQ0KCQkJCXJldHVybiBnKHQucmVwbGFjZSgkLCAiJDEiKSwgZSwgbiwgcikNCgkJCX0NCg0KCQkJZnVuY3Rpb24gdWUoKSB7DQoJCQkJdmFyIHIgPSBbXTsNCgkJCQlyZXR1cm4gZnVuY3Rpb24gZSh0LCBuKSB7cmV0dXJuIHIucHVzaCh0ICsgIiAiKSA+IGIuY2FjaGVMZW5ndGggJiYgZGVsZXRlIGVbci5zaGlmdCgpXSwgZVt0ICsgIiAiXSA9IG59DQoJCQl9DQoNCgkJCWZ1bmN0aW9uIGxlKGUpIHtyZXR1cm4gZVtTXSA9ICEwLCBlfQ0KDQoJCQlmdW5jdGlvbiBjZShlKSB7DQoJCQkJdmFyIHQgPSBDLmNyZWF0ZUVsZW1lbnQoImZpZWxkc2V0Iik7DQoJCQkJdHJ5IHtyZXR1cm4gISFlKHQpfSBjYXRjaChlKSB7cmV0dXJuICExfSBmaW5hbGx5IHt0LnBhcmVudE5vZGUgJiYgdC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHQpLCB0ID0gbnVsbH0NCgkJCX0NCg0KCQkJZnVuY3Rpb24gZmUoZSwgdCkgew0KCQkJCXZhciBuID0gZS5zcGxpdCgifCIpLCByID0gbi5sZW5ndGg7DQoJCQkJd2hpbGUoci0tKSBiLmF0dHJIYW5kbGVbbltyXV0gPSB0DQoJCQl9DQoNCgkJCWZ1bmN0aW9uIHBlKGUsIHQpIHsNCgkJCQl2YXIgbiA9IHQgJiYgZSwgciA9IG4gJiYgMSA9PT0gZS5ub2RlVHlwZSAmJiAxID09PSB0Lm5vZGVUeXBlICYmIGUuc291cmNlSW5kZXggLSB0LnNvdXJjZUluZGV4Ow0KCQkJCWlmKHIpIHJldHVybiByOw0KCQkJCWlmKG4pIHdoaWxlKG4gPSBuLm5leHRTaWJsaW5nKSBpZihuID09PSB0KSByZXR1cm4gLTE7DQoJCQkJcmV0dXJuIGUgPyAxIDogLTENCgkJCX0NCg0KCQkJZnVuY3Rpb24gZGUodCkge3JldHVybiBmdW5jdGlvbihlKSB7cmV0dXJuICJpbnB1dCIgPT09IGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKSAmJiBlLnR5cGUgPT09IHR9fQ0KDQoJCQlmdW5jdGlvbiBoZShuKSB7DQoJCQkJcmV0dXJuIGZ1bmN0aW9uKGUpIHsNCgkJCQkJdmFyIHQgPSBlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7DQoJCQkJCXJldHVybiAoImlucHV0IiA9PT0gdCB8fCAiYnV0dG9uIiA9PT0gdCkgJiYgZS50eXBlID09PSBuDQoJCQkJfQ0KCQkJfQ0KDQoJCQlmdW5jdGlvbiBnZSh0KSB7cmV0dXJuIGZ1bmN0aW9uKGUpIHtyZXR1cm4gImZvcm0iIGluIGUgPyBlLnBhcmVudE5vZGUgJiYgITEgPT09IGUuZGlzYWJsZWQgPyAibGFiZWwiIGluIGUgPyAibGFiZWwiIGluIGUucGFyZW50Tm9kZSA/IGUucGFyZW50Tm9kZS5kaXNhYmxlZCA9PT0gdCA6IGUuZGlzYWJsZWQgPT09IHQgOiBlLmlzRGlzYWJsZWQgPT09IHQgfHwgZS5pc0Rpc2FibGVkICE9PSAhdCAmJiBhZShlKSA9PT0gdCA6IGUuZGlzYWJsZWQgPT09IHQgOiAibGFiZWwiIGluIGUgJiYgZS5kaXNhYmxlZCA9PT0gdH19DQoNCgkJCWZ1bmN0aW9uIHZlKGEpIHsNCgkJCQlyZXR1cm4gbGUoZnVuY3Rpb24obykgew0KCQkJCQlyZXR1cm4gbyA9ICtvLCBsZShmdW5jdGlvbihlLCB0KSB7DQoJCQkJCQl2YXIgbiwgciA9IGEoW10sIGUubGVuZ3RoLCBvKSwgaSA9IHIubGVuZ3RoOw0KCQkJCQkJd2hpbGUoaS0tKSBlW24gPSByW2ldXSAmJiAoZVtuXSA9ICEodFtuXSA9IGVbbl0pKQ0KCQkJCQl9KQ0KCQkJCX0pDQoJCQl9DQoNCgkJCWZ1bmN0aW9uIHllKGUpIHtyZXR1cm4gZSAmJiAidW5kZWZpbmVkIiAhPSB0eXBlb2YgZS5nZXRFbGVtZW50c0J5VGFnTmFtZSAmJiBlfQ0KDQoJCQlmb3IoZSBpbiBkID0gc2Uuc3VwcG9ydCA9IHt9LCBpID0gc2UuaXNYTUwgPSBmdW5jdGlvbihlKSB7DQoJCQkJdmFyIHQgPSBlICYmIGUubmFtZXNwYWNlVVJJLCBuID0gZSAmJiAoZS5vd25lckRvY3VtZW50IHx8IGUpLmRvY3VtZW50RWxlbWVudDsNCgkJCQlyZXR1cm4gIVkudGVzdCh0IHx8IG4gJiYgbi5ub2RlTmFtZSB8fCAiSFRNTCIpDQoJCQl9LCBUID0gc2Uuc2V0RG9jdW1lbnQgPSBmdW5jdGlvbihlKSB7DQoJCQkJdmFyIHQsIG4sIHIgPSBlID8gZS5vd25lckRvY3VtZW50IHx8IGUgOiBwOw0KCQkJCXJldHVybiByICE9IEMgJiYgOSA9PT0gci5ub2RlVHlwZSAmJiByLmRvY3VtZW50RWxlbWVudCAmJiAoYSA9IChDID0gcikuZG9jdW1lbnRFbGVtZW50LCBFID0gIWkoQyksIHAgIT0gQyAmJiAobiA9IEMuZGVmYXVsdFZpZXcpICYmIG4udG9wICE9PSBuICYmIChuLmFkZEV2ZW50TGlzdGVuZXIgPyBuLmFkZEV2ZW50TGlzdGVuZXIoInVubG9hZCIsIG9lLCAhMSkgOiBuLmF0dGFjaEV2ZW50ICYmIG4uYXR0YWNoRXZlbnQoIm9udW5sb2FkIiwgb2UpKSwgZC5zY29wZSA9IGNlKGZ1bmN0aW9uKGUpIHtyZXR1cm4gYS5hcHBlbmRDaGlsZChlKS5hcHBlbmRDaGlsZChDLmNyZWF0ZUVsZW1lbnQoImRpdiIpKSwgInVuZGVmaW5lZCIgIT0gdHlwZW9mIGUucXVlcnlTZWxlY3RvckFsbCAmJiAhZS5xdWVyeVNlbGVjdG9yQWxsKCI6c2NvcGUgZmllbGRzZXQgZGl2IikubGVuZ3RofSksIGQuYXR0cmlidXRlcyA9IGNlKGZ1bmN0aW9uKGUpIHtyZXR1cm4gZS5jbGFzc05hbWUgPSAiaSIsICFlLmdldEF0dHJpYnV0ZSgiY2xhc3NOYW1lIil9KSwgZC5nZXRFbGVtZW50c0J5VGFnTmFtZSA9IGNlKGZ1bmN0aW9uKGUpIHtyZXR1cm4gZS5hcHBlbmRDaGlsZChDLmNyZWF0ZUNvbW1lbnQoIiIpKSwgIWUuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIioiKS5sZW5ndGh9KSwgZC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lID0gSy50ZXN0KEMuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSksIGQuZ2V0QnlJZCA9IGNlKGZ1bmN0aW9uKGUpIHtyZXR1cm4gYS5hcHBlbmRDaGlsZChlKS5pZCA9IFMsICFDLmdldEVsZW1lbnRzQnlOYW1lIHx8ICFDLmdldEVsZW1lbnRzQnlOYW1lKFMpLmxlbmd0aH0pLCBkLmdldEJ5SWQgPyAoYi5maWx0ZXIuSUQgPSBmdW5jdGlvbihlKSB7DQoJCQkJCXZhciB0ID0gZS5yZXBsYWNlKHRlLCBuZSk7DQoJCQkJCXJldHVybiBmdW5jdGlvbihlKSB7cmV0dXJuIGUuZ2V0QXR0cmlidXRlKCJpZCIpID09PSB0fQ0KCQkJCX0sIGIuZmluZC5JRCA9IGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQkJaWYoInVuZGVmaW5lZCIgIT0gdHlwZW9mIHQuZ2V0RWxlbWVudEJ5SWQgJiYgRSkgew0KCQkJCQkJdmFyIG4gPSB0LmdldEVsZW1lbnRCeUlkKGUpOw0KCQkJCQkJcmV0dXJuIG4gPyBbbl0gOiBbXQ0KCQkJCQl9DQoJCQkJfSkgOiAoYi5maWx0ZXIuSUQgPSBmdW5jdGlvbihlKSB7DQoJCQkJCXZhciBuID0gZS5yZXBsYWNlKHRlLCBuZSk7DQoJCQkJCXJldHVybiBmdW5jdGlvbihlKSB7DQoJCQkJCQl2YXIgdCA9ICJ1bmRlZmluZWQiICE9IHR5cGVvZiBlLmdldEF0dHJpYnV0ZU5vZGUgJiYgZS5nZXRBdHRyaWJ1dGVOb2RlKCJpZCIpOw0KCQkJCQkJcmV0dXJuIHQgJiYgdC52YWx1ZSA9PT0gbg0KCQkJCQl9DQoJCQkJfSwgYi5maW5kLklEID0gZnVuY3Rpb24oZSwgdCkgew0KCQkJCQlpZigidW5kZWZpbmVkIiAhPSB0eXBlb2YgdC5nZXRFbGVtZW50QnlJZCAmJiBFKSB7DQoJCQkJCQl2YXIgbiwgciwgaSwgbyA9IHQuZ2V0RWxlbWVudEJ5SWQoZSk7DQoJCQkJCQlpZihvKSB7DQoJCQkJCQkJaWYoKG4gPSBvLmdldEF0dHJpYnV0ZU5vZGUoImlkIikpICYmIG4udmFsdWUgPT09IGUpIHJldHVybiBbb107DQoJCQkJCQkJaSA9IHQuZ2V0RWxlbWVudHNCeU5hbWUoZSksIHIgPSAwOw0KCQkJCQkJCXdoaWxlKG8gPSBpW3IrK10pIGlmKChuID0gby5nZXRBdHRyaWJ1dGVOb2RlKCJpZCIpKSAmJiBuLnZhbHVlID09PSBlKSByZXR1cm4gW29dDQoJCQkJCQl9DQoJCQkJCQlyZXR1cm4gW10NCgkJCQkJfQ0KCQkJCX0pLCBiLmZpbmQuVEFHID0gZC5nZXRFbGVtZW50c0J5VGFnTmFtZSA/IGZ1bmN0aW9uKGUsIHQpIHtyZXR1cm4gInVuZGVmaW5lZCIgIT0gdHlwZW9mIHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUgPyB0LmdldEVsZW1lbnRzQnlUYWdOYW1lKGUpIDogZC5xc2EgPyB0LnF1ZXJ5U2VsZWN0b3JBbGwoZSkgOiB2b2lkIDB9IDogZnVuY3Rpb24oZSwgdCkgew0KCQkJCQl2YXIgbiwgciA9IFtdLCBpID0gMCwgbyA9IHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoZSk7DQoJCQkJCWlmKCIqIiA9PT0gZSkgew0KCQkJCQkJd2hpbGUobiA9IG9baSsrXSkgMSA9PT0gbi5ub2RlVHlwZSAmJiByLnB1c2gobik7DQoJCQkJCQlyZXR1cm4gcg0KCQkJCQl9DQoJCQkJCXJldHVybiBvDQoJCQkJfSwgYi5maW5kLkNMQVNTID0gZC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lICYmIGZ1bmN0aW9uKGUsIHQpIHtpZigidW5kZWZpbmVkIiAhPSB0eXBlb2YgdC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lICYmIEUpIHJldHVybiB0LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoZSl9LCBzID0gW10sIHYgPSBbXSwgKGQucXNhID0gSy50ZXN0KEMucXVlcnlTZWxlY3RvckFsbCkpICYmIChjZShmdW5jdGlvbihlKSB7DQoJCQkJCXZhciB0Ow0KCQkJCQlhLmFwcGVuZENoaWxkKGUpLmlubmVySFRNTCA9ICI8YSBpZD0nIiArIFMgKyAiJz48L2E+PHNlbGVjdCBpZD0nIiArIFMgKyAiLVxyXFwnIG1zYWxsb3djYXB0dXJlPScnPjxvcHRpb24gc2VsZWN0ZWQ9Jyc+PC9vcHRpb24+PC9zZWxlY3Q+IiwgZS5xdWVyeVNlbGVjdG9yQWxsKCJbbXNhbGxvd2NhcHR1cmVePScnXSIpLmxlbmd0aCAmJiB2LnB1c2goIlsqXiRdPSIgKyBNICsgIiooPzonJ3xcIlwiKSIpLCBlLnF1ZXJ5U2VsZWN0b3JBbGwoIltzZWxlY3RlZF0iKS5sZW5ndGggfHwgdi5wdXNoKCJcXFsiICsgTSArICIqKD86dmFsdWV8IiArIFIgKyAiKSIpLCBlLnF1ZXJ5U2VsZWN0b3JBbGwoIltpZH49IiArIFMgKyAiLV0iKS5sZW5ndGggfHwgdi5wdXNoKCJ+PSIpLCAodCA9IEMuY3JlYXRlRWxlbWVudCgiaW5wdXQiKSkuc2V0QXR0cmlidXRlKCJuYW1lIiwgIiIpLCBlLmFwcGVuZENoaWxkKHQpLCBlLnF1ZXJ5U2VsZWN0b3JBbGwoIltuYW1lPScnXSIpLmxlbmd0aCB8fCB2LnB1c2goIlxcWyIgKyBNICsgIipuYW1lIiArIE0gKyAiKj0iICsgTSArICIqKD86Jyd8XCJcIikiKSwgZS5xdWVyeVNlbGVjdG9yQWxsKCI6Y2hlY2tlZCIpLmxlbmd0aCB8fCB2LnB1c2goIjpjaGVja2VkIiksIGUucXVlcnlTZWxlY3RvckFsbCgiYSMiICsgUyArICIrKiIpLmxlbmd0aCB8fCB2LnB1c2goIi4jLitbK35dIiksIGUucXVlcnlTZWxlY3RvckFsbCgiXFxcZiIpLCB2LnB1c2goIltcXHJcXG5cXGZdIikNCgkJCQl9KSwgY2UoZnVuY3Rpb24oZSkgew0KCQkJCQllLmlubmVySFRNTCA9ICI8YSBocmVmPScnIGRpc2FibGVkPSdkaXNhYmxlZCc+PC9hPjxzZWxlY3QgZGlzYWJsZWQ9J2Rpc2FibGVkJz48b3B0aW9uLz48L3NlbGVjdD4iOw0KCQkJCQl2YXIgdCA9IEMuY3JlYXRlRWxlbWVudCgiaW5wdXQiKTsNCgkJCQkJdC5zZXRBdHRyaWJ1dGUoInR5cGUiLCAiaGlkZGVuIiksIGUuYXBwZW5kQ2hpbGQodCkuc2V0QXR0cmlidXRlKCJuYW1lIiwgIkQiKSwgZS5xdWVyeVNlbGVjdG9yQWxsKCJbbmFtZT1kXSIpLmxlbmd0aCAmJiB2LnB1c2goIm5hbWUiICsgTSArICIqWypeJHwhfl0/PSIpLCAyICE9PSBlLnF1ZXJ5U2VsZWN0b3JBbGwoIjplbmFibGVkIikubGVuZ3RoICYmIHYucHVzaCgiOmVuYWJsZWQiLCAiOmRpc2FibGVkIiksIGEuYXBwZW5kQ2hpbGQoZSkuZGlzYWJsZWQgPSAhMCwgMiAhPT0gZS5xdWVyeVNlbGVjdG9yQWxsKCI6ZGlzYWJsZWQiKS5sZW5ndGggJiYgdi5wdXNoKCI6ZW5hYmxlZCIsICI6ZGlzYWJsZWQiKSwgZS5xdWVyeVNlbGVjdG9yQWxsKCIqLDp4IiksIHYucHVzaCgiLC4qOiIpDQoJCQkJfSkpLCAoZC5tYXRjaGVzU2VsZWN0b3IgPSBLLnRlc3QoYyA9IGEubWF0Y2hlcyB8fCBhLndlYmtpdE1hdGNoZXNTZWxlY3RvciB8fCBhLm1vek1hdGNoZXNTZWxlY3RvciB8fCBhLm9NYXRjaGVzU2VsZWN0b3IgfHwgYS5tc01hdGNoZXNTZWxlY3RvcikpICYmIGNlKGZ1bmN0aW9uKGUpIHtkLmRpc2Nvbm5lY3RlZE1hdGNoID0gYy5jYWxsKGUsICIqIiksIGMuY2FsbChlLCAiW3MhPScnXTp4IiksIHMucHVzaCgiIT0iLCBGKX0pLCB2ID0gdi5sZW5ndGggJiYgbmV3IFJlZ0V4cCh2LmpvaW4oInwiKSksIHMgPSBzLmxlbmd0aCAmJiBuZXcgUmVnRXhwKHMuam9pbigifCIpKSwgdCA9IEsudGVzdChhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKSwgeSA9IHQgfHwgSy50ZXN0KGEuY29udGFpbnMpID8gZnVuY3Rpb24oZSwgdCkgew0KCQkJCQl2YXIgbiA9IDkgPT09IGUubm9kZVR5cGUgPyBlLmRvY3VtZW50RWxlbWVudCA6IGUsDQoJCQkJCSAgICByID0gdCAmJiB0LnBhcmVudE5vZGU7DQoJCQkJCXJldHVybiBlID09PSByIHx8ICEoIXIgfHwgMSAhPT0gci5ub2RlVHlwZSB8fCAhKG4uY29udGFpbnMgPyBuLmNvbnRhaW5zKHIpIDogZS5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbiAmJiAxNiAmIGUuY29tcGFyZURvY3VtZW50UG9zaXRpb24ocikpKQ0KCQkJCX0gOiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJCWlmKHQpIHdoaWxlKHQgPSB0LnBhcmVudE5vZGUpIGlmKHQgPT09IGUpIHJldHVybiAhMDsNCgkJCQkJcmV0dXJuICExDQoJCQkJfSwgaiA9IHQgPyBmdW5jdGlvbihlLCB0KSB7DQoJCQkJCWlmKGUgPT09IHQpIHJldHVybiBsID0gITAsIDA7DQoJCQkJCXZhciBuID0gIWUuY29tcGFyZURvY3VtZW50UG9zaXRpb24gLSAhdC5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbjsNCgkJCQkJcmV0dXJuIG4gfHwgKDEgJiAobiA9IChlLm93bmVyRG9jdW1lbnQgfHwgZSkgPT0gKHQub3duZXJEb2N1bWVudCB8fCB0KSA/IGUuY29tcGFyZURvY3VtZW50UG9zaXRpb24odCkgOiAxKSB8fCAhZC5zb3J0RGV0YWNoZWQgJiYgdC5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbihlKSA9PT0gbiA/IGUgPT0gQyB8fCBlLm93bmVyRG9jdW1lbnQgPT0gcCAmJiB5KHAsIGUpID8gLTEgOiB0ID09IEMgfHwgdC5vd25lckRvY3VtZW50ID09IHAgJiYgeShwLCB0KSA/IDEgOiB1ID8gUCh1LCBlKSAtIFAodSwgdCkgOiAwIDogNCAmIG4gPyAtMSA6IDEpDQoJCQkJfSA6IGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQkJaWYoZSA9PT0gdCkgcmV0dXJuIGwgPSAhMCwgMDsNCgkJCQkJdmFyIG4sIHIgPSAwLCBpID0gZS5wYXJlbnROb2RlLCBvID0gdC5wYXJlbnROb2RlLCBhID0gW2VdLCBzID0gW3RdOw0KCQkJCQlpZighaSB8fCAhbykgcmV0dXJuIGUgPT0gQyA/IC0xIDogdCA9PSBDID8gMSA6IGkgPyAtMSA6IG8gPyAxIDogdSA/IFAodSwgZSkgLSBQKHUsIHQpIDogMDsNCgkJCQkJaWYoaSA9PT0gbykgcmV0dXJuIHBlKGUsIHQpOw0KCQkJCQluID0gZTsNCgkJCQkJd2hpbGUobiA9IG4ucGFyZW50Tm9kZSkgYS51bnNoaWZ0KG4pOw0KCQkJCQluID0gdDsNCgkJCQkJd2hpbGUobiA9IG4ucGFyZW50Tm9kZSkgcy51bnNoaWZ0KG4pOw0KCQkJCQl3aGlsZShhW3JdID09PSBzW3JdKSByKys7DQoJCQkJCXJldHVybiByID8gcGUoYVtyXSwgc1tyXSkgOiBhW3JdID09IHAgPyAtMSA6IHNbcl0gPT0gcCA/IDEgOiAwDQoJCQkJfSksIEMNCgkJCX0sIHNlLm1hdGNoZXMgPSBmdW5jdGlvbihlLCB0KSB7cmV0dXJuIHNlKGUsIG51bGwsIG51bGwsIHQpfSwgc2UubWF0Y2hlc1NlbGVjdG9yID0gZnVuY3Rpb24oZSwgdCkgew0KCQkJCWlmKFQoZSksIGQubWF0Y2hlc1NlbGVjdG9yICYmIEUgJiYgIU5bdCArICIgIl0gJiYgKCFzIHx8ICFzLnRlc3QodCkpICYmICghdiB8fCAhdi50ZXN0KHQpKSkgdHJ5IHsNCgkJCQkJdmFyIG4gPSBjLmNhbGwoZSwgdCk7DQoJCQkJCWlmKG4gfHwgZC5kaXNjb25uZWN0ZWRNYXRjaCB8fCBlLmRvY3VtZW50ICYmIDExICE9PSBlLmRvY3VtZW50Lm5vZGVUeXBlKSByZXR1cm4gbg0KCQkJCX0gY2F0Y2goZSkge04odCwgITApfQ0KCQkJCXJldHVybiAwIDwgc2UodCwgQywgbnVsbCwgW2VdKS5sZW5ndGgNCgkJCX0sIHNlLmNvbnRhaW5zID0gZnVuY3Rpb24oZSwgdCkge3JldHVybiAoZS5vd25lckRvY3VtZW50IHx8IGUpICE9IEMgJiYgVChlKSwgeShlLCB0KX0sIHNlLmF0dHIgPSBmdW5jdGlvbihlLCB0KSB7DQoJCQkJKGUub3duZXJEb2N1bWVudCB8fCBlKSAhPSBDICYmIFQoZSk7DQoJCQkJdmFyIG4gPSBiLmF0dHJIYW5kbGVbdC50b0xvd2VyQ2FzZSgpXSwgciA9IG4gJiYgRC5jYWxsKGIuYXR0ckhhbmRsZSwgdC50b0xvd2VyQ2FzZSgpKSA/IG4oZSwgdCwgIUUpIDogdm9pZCAwOw0KCQkJCXJldHVybiB2b2lkIDAgIT09IHIgPyByIDogZC5hdHRyaWJ1dGVzIHx8ICFFID8gZS5nZXRBdHRyaWJ1dGUodCkgOiAociA9IGUuZ2V0QXR0cmlidXRlTm9kZSh0KSkgJiYgci5zcGVjaWZpZWQgPyByLnZhbHVlIDogbnVsbA0KCQkJfSwgc2UuZXNjYXBlID0gZnVuY3Rpb24oZSkge3JldHVybiAoZSArICIiKS5yZXBsYWNlKHJlLCBpZSl9LCBzZS5lcnJvciA9IGZ1bmN0aW9uKGUpIHt0aHJvdyBuZXcgRXJyb3IoIlN5bnRheCBlcnJvciwgdW5yZWNvZ25pemVkIGV4cHJlc3Npb246ICIgKyBlKX0sIHNlLnVuaXF1ZVNvcnQgPSBmdW5jdGlvbihlKSB7DQoJCQkJdmFyIHQsIG4gPSBbXSwgciA9IDAsIGkgPSAwOw0KCQkJCWlmKGwgPSAhZC5kZXRlY3REdXBsaWNhdGVzLCB1ID0gIWQuc29ydFN0YWJsZSAmJiBlLnNsaWNlKDApLCBlLnNvcnQoaiksIGwpIHsNCgkJCQkJd2hpbGUodCA9IGVbaSsrXSkgdCA9PT0gZVtpXSAmJiAociA9IG4ucHVzaChpKSk7DQoJCQkJCXdoaWxlKHItLSkgZS5zcGxpY2UobltyXSwgMSkNCgkJCQl9DQoJCQkJcmV0dXJuIHUgPSBudWxsLCBlDQoJCQl9LCBvID0gc2UuZ2V0VGV4dCA9IGZ1bmN0aW9uKGUpIHsNCgkJCQl2YXIgdCwgbiA9ICIiLCByID0gMCwgaSA9IGUubm9kZVR5cGU7DQoJCQkJaWYoaSkgew0KCQkJCQlpZigxID09PSBpIHx8IDkgPT09IGkgfHwgMTEgPT09IGkpIHsNCgkJCQkJCWlmKCJzdHJpbmciID09IHR5cGVvZiBlLnRleHRDb250ZW50KSByZXR1cm4gZS50ZXh0Q29udGVudDsNCgkJCQkJCWZvcihlID0gZS5maXJzdENoaWxkOyBlOyBlID0gZS5uZXh0U2libGluZykgbiArPSBvKGUpDQoJCQkJCX0gZWxzZSBpZigzID09PSBpIHx8IDQgPT09IGkpIHJldHVybiBlLm5vZGVWYWx1ZQ0KCQkJCX0gZWxzZSB3aGlsZSh0ID0gZVtyKytdKSBuICs9IG8odCk7DQoJCQkJcmV0dXJuIG4NCgkJCX0sIChiID0gc2Uuc2VsZWN0b3JzID0gew0KCQkJCWNhY2hlTGVuZ3RoOiA1MCwNCgkJCQljcmVhdGVQc2V1ZG86IGxlLA0KCQkJCW1hdGNoOiBHLA0KCQkJCWF0dHJIYW5kbGU6IHt9LA0KCQkJCWZpbmQ6IHt9LA0KCQkJCXJlbGF0aXZlOiB7Ij4iOiB7ZGlyOiAicGFyZW50Tm9kZSIsIGZpcnN0OiAhMH0sICIgIjoge2RpcjogInBhcmVudE5vZGUifSwgIisiOiB7ZGlyOiAicHJldmlvdXNTaWJsaW5nIiwgZmlyc3Q6ICEwfSwgIn4iOiB7ZGlyOiAicHJldmlvdXNTaWJsaW5nIn19LA0KCQkJCXByZUZpbHRlcjogew0KCQkJCQlBVFRSOiBmdW5jdGlvbihlKSB7cmV0dXJuIGVbMV0gPSBlWzFdLnJlcGxhY2UodGUsIG5lKSwgZVszXSA9IChlWzNdIHx8IGVbNF0gfHwgZVs1XSB8fCAiIikucmVwbGFjZSh0ZSwgbmUpLCAifj0iID09PSBlWzJdICYmIChlWzNdID0gIiAiICsgZVszXSArICIgIiksIGUuc2xpY2UoMCwgNCl9LA0KCQkJCQlDSElMRDogZnVuY3Rpb24oZSkge3JldHVybiBlWzFdID0gZVsxXS50b0xvd2VyQ2FzZSgpLCAibnRoIiA9PT0gZVsxXS5zbGljZSgwLCAzKSA/IChlWzNdIHx8IHNlLmVycm9yKGVbMF0pLCBlWzRdID0gKyhlWzRdID8gZVs1XSArIChlWzZdIHx8IDEpIDogMiAqICgiZXZlbiIgPT09IGVbM10gfHwgIm9kZCIgPT09IGVbM10pKSwgZVs1XSA9ICsoZVs3XSArIGVbOF0gfHwgIm9kZCIgPT09IGVbM10pKSA6IGVbM10gJiYgc2UuZXJyb3IoZVswXSksIGV9LA0KCQkJCQlQU0VVRE86IGZ1bmN0aW9uKGUpIHsNCgkJCQkJCXZhciB0LCBuID0gIWVbNl0gJiYgZVsyXTsNCgkJCQkJCXJldHVybiBHLkNISUxELnRlc3QoZVswXSkgPyBudWxsIDogKGVbM10gPyBlWzJdID0gZVs0XSB8fCBlWzVdIHx8ICIiIDogbiAmJiBYLnRlc3QobikgJiYgKHQgPSBoKG4sICEwKSkgJiYgKHQgPSBuLmluZGV4T2YoIikiLCBuLmxlbmd0aCAtIHQpIC0gbi5sZW5ndGgpICYmIChlWzBdID0gZVswXS5zbGljZSgwLCB0KSwgZVsyXSA9IG4uc2xpY2UoMCwgdCkpLCBlLnNsaWNlKDAsIDMpKQ0KCQkJCQl9DQoJCQkJfSwNCgkJCQlmaWx0ZXI6IHsNCgkJCQkJVEFHOiBmdW5jdGlvbihlKSB7DQoJCQkJCQl2YXIgdCA9IGUucmVwbGFjZSh0ZSwgbmUpLnRvTG93ZXJDYXNlKCk7DQoJCQkJCQlyZXR1cm4gIioiID09PSBlID8gZnVuY3Rpb24oKSB7cmV0dXJuICEwfSA6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gZS5ub2RlTmFtZSAmJiBlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IHR9DQoJCQkJCX0sIENMQVNTOiBmdW5jdGlvbihlKSB7DQoJCQkJCQl2YXIgdCA9IG1bZSArICIgIl07DQoJCQkJCQlyZXR1cm4gdCB8fCAodCA9IG5ldyBSZWdFeHAoIihefCIgKyBNICsgIikiICsgZSArICIoIiArIE0gKyAifCQpIikpICYmIG0oZSwgZnVuY3Rpb24oZSkge3JldHVybiB0LnRlc3QoInN0cmluZyIgPT0gdHlwZW9mIGUuY2xhc3NOYW1lICYmIGUuY2xhc3NOYW1lIHx8ICJ1bmRlZmluZWQiICE9IHR5cGVvZiBlLmdldEF0dHJpYnV0ZSAmJiBlLmdldEF0dHJpYnV0ZSgiY2xhc3MiKSB8fCAiIil9KQ0KCQkJCQl9LCBBVFRSOiBmdW5jdGlvbihuLCByLCBpKSB7DQoJCQkJCQlyZXR1cm4gZnVuY3Rpb24oZSkgew0KCQkJCQkJCXZhciB0ID0gc2UuYXR0cihlLCBuKTsNCgkJCQkJCQlyZXR1cm4gbnVsbCA9PSB0ID8gIiE9IiA9PT0gciA6ICFyIHx8ICh0ICs9ICIiLCAiPSIgPT09IHIgPyB0ID09PSBpIDogIiE9IiA9PT0gciA/IHQgIT09IGkgOiAiXj0iID09PSByID8gaSAmJiAwID09PSB0LmluZGV4T2YoaSkgOiAiKj0iID09PSByID8gaSAmJiAtMSA8IHQuaW5kZXhPZihpKSA6ICIkPSIgPT09IHIgPyBpICYmIHQuc2xpY2UoLWkubGVuZ3RoKSA9PT0gaSA6ICJ+PSIgPT09IHIgPyAtMSA8ICgiICIgKyB0LnJlcGxhY2UoQiwgIiAiKSArICIgIikuaW5kZXhPZihpKSA6ICJ8PSIgPT09IHIgJiYgKHQgPT09IGkgfHwgdC5zbGljZSgwLCBpLmxlbmd0aCArIDEpID09PSBpICsgIi0iKSkNCgkJCQkJCX0NCgkJCQkJfSwgQ0hJTEQ6IGZ1bmN0aW9uKGgsIGUsIHQsIGcsIHYpIHsNCgkJCQkJCXZhciB5ID0gIm50aCIgIT09IGguc2xpY2UoMCwgMyksIG0gPSAibGFzdCIgIT09IGguc2xpY2UoLTQpLCB4ID0gIm9mLXR5cGUiID09PSBlOw0KCQkJCQkJcmV0dXJuIDEgPT09IGcgJiYgMCA9PT0gdiA/IGZ1bmN0aW9uKGUpIHtyZXR1cm4gISFlLnBhcmVudE5vZGV9IDogZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJCQkJCXZhciByLCBpLCBvLCBhLCBzLCB1LCBsID0geSAhPT0gbSA/ICJuZXh0U2libGluZyIgOiAicHJldmlvdXNTaWJsaW5nIiwgYyA9IGUucGFyZW50Tm9kZSwgZiA9IHggJiYgZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpLCBwID0gIW4gJiYgIXgsIGQgPSAhMTsNCgkJCQkJCQlpZihjKSB7DQoJCQkJCQkJCWlmKHkpIHsNCgkJCQkJCQkJCXdoaWxlKGwpIHsNCgkJCQkJCQkJCQlhID0gZTsNCgkJCQkJCQkJCQl3aGlsZShhID0gYVtsXSkgaWYoeCA/IGEubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gZiA6IDEgPT09IGEubm9kZVR5cGUpIHJldHVybiAhMTsNCgkJCQkJCQkJCQl1ID0gbCA9ICJvbmx5IiA9PT0gaCAmJiAhdSAmJiAibmV4dFNpYmxpbmciDQoJCQkJCQkJCQl9DQoJCQkJCQkJCQlyZXR1cm4gITANCgkJCQkJCQkJfQ0KCQkJCQkJCQlpZih1ID0gW20gPyBjLmZpcnN0Q2hpbGQgOiBjLmxhc3RDaGlsZF0sIG0gJiYgcCkgew0KCQkJCQkJCQkJZCA9IChzID0gKHIgPSAoaSA9IChvID0gKGEgPSBjKVtTXSB8fCAoYVtTXSA9IHt9KSlbYS51bmlxdWVJRF0gfHwgKG9bYS51bmlxdWVJRF0gPSB7fSkpW2hdIHx8IFtdKVswXSA9PT0gayAmJiByWzFdKSAmJiByWzJdLCBhID0gcyAmJiBjLmNoaWxkTm9kZXNbc107DQoJCQkJCQkJCQl3aGlsZShhID0gKytzICYmIGEgJiYgYVtsXSB8fCAoZCA9IHMgPSAwKSB8fCB1LnBvcCgpKSBpZigxID09PSBhLm5vZGVUeXBlICYmICsrZCAmJiBhID09PSBlKSB7DQoJCQkJCQkJCQkJaVtoXSA9IFtrLCBzLCBkXTsNCgkJCQkJCQkJCQlicmVhaw0KCQkJCQkJCQkJfQ0KCQkJCQkJCQl9IGVsc2UgaWYocCAmJiAoZCA9IHMgPSAociA9IChpID0gKG8gPSAoYSA9IGUpW1NdIHx8IChhW1NdID0ge30pKVthLnVuaXF1ZUlEXSB8fCAob1thLnVuaXF1ZUlEXSA9IHt9KSlbaF0gfHwgW10pWzBdID09PSBrICYmIHJbMV0pLCAhMSA9PT0gZCkgd2hpbGUoYSA9ICsrcyAmJiBhICYmIGFbbF0gfHwgKGQgPSBzID0gMCkgfHwgdS5wb3AoKSkgaWYoKHggPyBhLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IGYgOiAxID09PSBhLm5vZGVUeXBlKSAmJiArK2QgJiYgKHAgJiYgKChpID0gKG8gPSBhW1NdIHx8IChhW1NdID0ge30pKVthLnVuaXF1ZUlEXSB8fCAob1thLnVuaXF1ZUlEXSA9IHt9KSlbaF0gPSBbaywgZF0pLCBhID09PSBlKSkgYnJlYWs7DQoJCQkJCQkJCXJldHVybiAoZCAtPSB2KSA9PT0gZyB8fCBkICUgZyA9PSAwICYmIDAgPD0gZCAvIGcNCgkJCQkJCQl9DQoJCQkJCQl9DQoJCQkJCX0sIFBTRVVETzogZnVuY3Rpb24oZSwgbykgew0KCQkJCQkJdmFyIHQsIGEgPSBiLnBzZXVkb3NbZV0gfHwgYi5zZXRGaWx0ZXJzW2UudG9Mb3dlckNhc2UoKV0gfHwgc2UuZXJyb3IoInVuc3VwcG9ydGVkIHBzZXVkbzogIiArIGUpOw0KCQkJCQkJcmV0dXJuIGFbU10gPyBhKG8pIDogMSA8IGEubGVuZ3RoID8gKHQgPSBbZSwgZSwgIiIsIG9dLCBiLnNldEZpbHRlcnMuaGFzT3duUHJvcGVydHkoZS50b0xvd2VyQ2FzZSgpKSA/IGxlKGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQkJCQl2YXIgbiwgciA9IGEoZSwgbyksIGkgPSByLmxlbmd0aDsNCgkJCQkJCQl3aGlsZShpLS0pIGVbbiA9IFAoZSwgcltpXSldID0gISh0W25dID0gcltpXSkNCgkJCQkJCX0pIDogZnVuY3Rpb24oZSkge3JldHVybiBhKGUsIDAsIHQpfSkgOiBhDQoJCQkJCX0NCgkJCQl9LA0KCQkJCXBzZXVkb3M6IHsNCgkJCQkJbm90OiBsZShmdW5jdGlvbihlKSB7DQoJCQkJCQl2YXIgciA9IFtdLCBpID0gW10sIHMgPSBmKGUucmVwbGFjZSgkLCAiJDEiKSk7DQoJCQkJCQlyZXR1cm4gc1tTXSA/IGxlKGZ1bmN0aW9uKGUsIHQsIG4sIHIpIHsNCgkJCQkJCQl2YXIgaSwgbyA9IHMoZSwgbnVsbCwgciwgW10pLCBhID0gZS5sZW5ndGg7DQoJCQkJCQkJd2hpbGUoYS0tKSAoaSA9IG9bYV0pICYmIChlW2FdID0gISh0W2FdID0gaSkpDQoJCQkJCQl9KSA6IGZ1bmN0aW9uKGUsIHQsIG4pIHtyZXR1cm4gclswXSA9IGUsIHMociwgbnVsbCwgbiwgaSksIHJbMF0gPSBudWxsLCAhaS5wb3AoKX0NCgkJCQkJfSksDQoJCQkJCWhhczogbGUoZnVuY3Rpb24odCkge3JldHVybiBmdW5jdGlvbihlKSB7cmV0dXJuIDAgPCBzZSh0LCBlKS5sZW5ndGh9fSksDQoJCQkJCWNvbnRhaW5zOiBsZShmdW5jdGlvbih0KSB7cmV0dXJuIHQgPSB0LnJlcGxhY2UodGUsIG5lKSwgZnVuY3Rpb24oZSkge3JldHVybiAtMSA8IChlLnRleHRDb250ZW50IHx8IG8oZSkpLmluZGV4T2YodCl9fSksDQoJCQkJCWxhbmc6IGxlKGZ1bmN0aW9uKG4pIHsNCgkJCQkJCXJldHVybiBWLnRlc3QobiB8fCAiIikgfHwgc2UuZXJyb3IoInVuc3VwcG9ydGVkIGxhbmc6ICIgKyBuKSwgbiA9IG4ucmVwbGFjZSh0ZSwgbmUpLnRvTG93ZXJDYXNlKCksIGZ1bmN0aW9uKGUpIHsNCgkJCQkJCQl2YXIgdDsNCgkJCQkJCQlkbyB7aWYodCA9IEUgPyBlLmxhbmcgOiBlLmdldEF0dHJpYnV0ZSgieG1sOmxhbmciKSB8fCBlLmdldEF0dHJpYnV0ZSgibGFuZyIpKSByZXR1cm4gKHQgPSB0LnRvTG93ZXJDYXNlKCkpID09PSBuIHx8IDAgPT09IHQuaW5kZXhPZihuICsgIi0iKX0gd2hpbGUoKGUgPSBlLnBhcmVudE5vZGUpICYmIDEgPT09IGUubm9kZVR5cGUpOw0KCQkJCQkJCXJldHVybiAhMQ0KCQkJCQkJfQ0KCQkJCQl9KSwNCgkJCQkJdGFyZ2V0OiBmdW5jdGlvbihlKSB7DQoJCQkJCQl2YXIgdCA9IG4ubG9jYXRpb24gJiYgbi5sb2NhdGlvbi5oYXNoOw0KCQkJCQkJcmV0dXJuIHQgJiYgdC5zbGljZSgxKSA9PT0gZS5pZA0KCQkJCQl9LA0KCQkJCQlyb290OiBmdW5jdGlvbihlKSB7cmV0dXJuIGUgPT09IGF9LA0KCQkJCQlmb2N1czogZnVuY3Rpb24oZSkge3JldHVybiBlID09PSBDLmFjdGl2ZUVsZW1lbnQgJiYgKCFDLmhhc0ZvY3VzIHx8IEMuaGFzRm9jdXMoKSkgJiYgISEoZS50eXBlIHx8IGUuaHJlZiB8fCB+ZS50YWJJbmRleCl9LA0KCQkJCQllbmFibGVkOiBnZSghMSksDQoJCQkJCWRpc2FibGVkOiBnZSghMCksDQoJCQkJCWNoZWNrZWQ6IGZ1bmN0aW9uKGUpIHsNCgkJCQkJCXZhciB0ID0gZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpOw0KCQkJCQkJcmV0dXJuICJpbnB1dCIgPT09IHQgJiYgISFlLmNoZWNrZWQgfHwgIm9wdGlvbiIgPT09IHQgJiYgISFlLnNlbGVjdGVkDQoJCQkJCX0sDQoJCQkJCXNlbGVjdGVkOiBmdW5jdGlvbihlKSB7cmV0dXJuIGUucGFyZW50Tm9kZSAmJiBlLnBhcmVudE5vZGUuc2VsZWN0ZWRJbmRleCwgITAgPT09IGUuc2VsZWN0ZWR9LA0KCQkJCQllbXB0eTogZnVuY3Rpb24oZSkgew0KCQkJCQkJZm9yKGUgPSBlLmZpcnN0Q2hpbGQ7IGU7IGUgPSBlLm5leHRTaWJsaW5nKSBpZihlLm5vZGVUeXBlIDwgNikgcmV0dXJuICExOw0KCQkJCQkJcmV0dXJuICEwDQoJCQkJCX0sDQoJCQkJCXBhcmVudDogZnVuY3Rpb24oZSkge3JldHVybiAhYi5wc2V1ZG9zLmVtcHR5KGUpfSwNCgkJCQkJaGVhZGVyOiBmdW5jdGlvbihlKSB7cmV0dXJuIEoudGVzdChlLm5vZGVOYW1lKX0sDQoJCQkJCWlucHV0OiBmdW5jdGlvbihlKSB7cmV0dXJuIFEudGVzdChlLm5vZGVOYW1lKX0sDQoJCQkJCWJ1dHRvbjogZnVuY3Rpb24oZSkgew0KCQkJCQkJdmFyIHQgPSBlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7DQoJCQkJCQlyZXR1cm4gImlucHV0IiA9PT0gdCAmJiAiYnV0dG9uIiA9PT0gZS50eXBlIHx8ICJidXR0b24iID09PSB0DQoJCQkJCX0sDQoJCQkJCXRleHQ6IGZ1bmN0aW9uKGUpIHsNCgkJCQkJCXZhciB0Ow0KCQkJCQkJcmV0dXJuICJpbnB1dCIgPT09IGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKSAmJiAidGV4dCIgPT09IGUudHlwZSAmJiAobnVsbCA9PSAodCA9IGUuZ2V0QXR0cmlidXRlKCJ0eXBlIikpIHx8ICJ0ZXh0IiA9PT0gdC50b0xvd2VyQ2FzZSgpKQ0KCQkJCQl9LA0KCQkJCQlmaXJzdDogdmUoZnVuY3Rpb24oKSB7cmV0dXJuIFswXX0pLA0KCQkJCQlsYXN0OiB2ZShmdW5jdGlvbihlLCB0KSB7cmV0dXJuIFt0IC0gMV19KSwNCgkJCQkJZXE6IHZlKGZ1bmN0aW9uKGUsIHQsIG4pIHtyZXR1cm4gW24gPCAwID8gbiArIHQgOiBuXX0pLA0KCQkJCQlldmVuOiB2ZShmdW5jdGlvbihlLCB0KSB7DQoJCQkJCQlmb3IodmFyIG4gPSAwOyBuIDwgdDsgbiArPSAyKSBlLnB1c2gobik7DQoJCQkJCQlyZXR1cm4gZQ0KCQkJCQl9KSwNCgkJCQkJb2RkOiB2ZShmdW5jdGlvbihlLCB0KSB7DQoJCQkJCQlmb3IodmFyIG4gPSAxOyBuIDwgdDsgbiArPSAyKSBlLnB1c2gobik7DQoJCQkJCQlyZXR1cm4gZQ0KCQkJCQl9KSwNCgkJCQkJbHQ6IHZlKGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQkJCWZvcih2YXIgciA9IG4gPCAwID8gbiArIHQgOiB0IDwgbiA/IHQgOiBuOyAwIDw9IC0tcjspIGUucHVzaChyKTsNCgkJCQkJCXJldHVybiBlDQoJCQkJCX0pLA0KCQkJCQlndDogdmUoZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJCQkJZm9yKHZhciByID0gbiA8IDAgPyBuICsgdCA6IG47ICsrciA8IHQ7KSBlLnB1c2gocik7DQoJCQkJCQlyZXR1cm4gZQ0KCQkJCQl9KQ0KCQkJCX0NCgkJCX0pLnBzZXVkb3MubnRoID0gYi5wc2V1ZG9zLmVxLCB7cmFkaW86ICEwLCBjaGVja2JveDogITAsIGZpbGU6ICEwLCBwYXNzd29yZDogITAsIGltYWdlOiAhMH0pIGIucHNldWRvc1tlXSA9IGRlKGUpOw0KCQkJZm9yKGUgaW4ge3N1Ym1pdDogITAsIHJlc2V0OiAhMH0pIGIucHNldWRvc1tlXSA9IGhlKGUpOw0KDQoJCQlmdW5jdGlvbiBtZSgpIHt9DQoNCgkJCWZ1bmN0aW9uIHhlKGUpIHsNCgkJCQlmb3IodmFyIHQgPSAwLCBuID0gZS5sZW5ndGgsIHIgPSAiIjsgdCA8IG47IHQrKykgciArPSBlW3RdLnZhbHVlOw0KCQkJCXJldHVybiByDQoJCQl9DQoNCgkJCWZ1bmN0aW9uIGJlKHMsIGUsIHQpIHsNCgkJCQl2YXIgdSA9IGUuZGlyLCBsID0gZS5uZXh0LCBjID0gbCB8fCB1LCBmID0gdCAmJiAicGFyZW50Tm9kZSIgPT09IGMsIHAgPSByKys7DQoJCQkJcmV0dXJuIGUuZmlyc3QgPyBmdW5jdGlvbihlLCB0LCBuKSB7DQoJCQkJCXdoaWxlKGUgPSBlW3VdKSBpZigxID09PSBlLm5vZGVUeXBlIHx8IGYpIHJldHVybiBzKGUsIHQsIG4pOw0KCQkJCQlyZXR1cm4gITENCgkJCQl9IDogZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJCQl2YXIgciwgaSwgbywgYSA9IFtrLCBwXTsNCgkJCQkJaWYobikge3doaWxlKGUgPSBlW3VdKSBpZigoMSA9PT0gZS5ub2RlVHlwZSB8fCBmKSAmJiBzKGUsIHQsIG4pKSByZXR1cm4gITB9IGVsc2Ugd2hpbGUoZSA9IGVbdV0pIGlmKDEgPT09IGUubm9kZVR5cGUgfHwgZikgaWYoaSA9IChvID0gZVtTXSB8fCAoZVtTXSA9IHt9KSlbZS51bmlxdWVJRF0gfHwgKG9bZS51bmlxdWVJRF0gPSB7fSksIGwgJiYgbCA9PT0gZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpKSBlID0gZVt1XSB8fCBlOyBlbHNlIHsNCgkJCQkJCWlmKChyID0gaVtjXSkgJiYgclswXSA9PT0gayAmJiByWzFdID09PSBwKSByZXR1cm4gYVsyXSA9IHJbMl07DQoJCQkJCQlpZigoaVtjXSA9IGEpWzJdID0gcyhlLCB0LCBuKSkgcmV0dXJuICEwDQoJCQkJCX0NCgkJCQkJcmV0dXJuICExDQoJCQkJfQ0KCQkJfQ0KDQoJCQlmdW5jdGlvbiB3ZShpKSB7DQoJCQkJcmV0dXJuIDEgPCBpLmxlbmd0aCA/IGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQkJdmFyIHIgPSBpLmxlbmd0aDsNCgkJCQkJd2hpbGUoci0tKSBpZighaVtyXShlLCB0LCBuKSkgcmV0dXJuICExOw0KCQkJCQlyZXR1cm4gITANCgkJCQl9IDogaVswXQ0KCQkJfQ0KDQoJCQlmdW5jdGlvbiBUZShlLCB0LCBuLCByLCBpKSB7DQoJCQkJZm9yKHZhciBvLCBhID0gW10sIHMgPSAwLCB1ID0gZS5sZW5ndGgsIGwgPSBudWxsICE9IHQ7IHMgPCB1OyBzKyspIChvID0gZVtzXSkgJiYgKG4gJiYgIW4obywgciwgaSkgfHwgKGEucHVzaChvKSwgbCAmJiB0LnB1c2gocykpKTsNCgkJCQlyZXR1cm4gYQ0KCQkJfQ0KDQoJCQlmdW5jdGlvbiBDZShkLCBoLCBnLCB2LCB5LCBlKSB7DQoJCQkJcmV0dXJuIHYgJiYgIXZbU10gJiYgKHYgPSBDZSh2KSksIHkgJiYgIXlbU10gJiYgKHkgPSBDZSh5LCBlKSksIGxlKGZ1bmN0aW9uKGUsIHQsIG4sIHIpIHsNCgkJCQkJdmFyIGksIG8sIGEsIHMgICAgICAgICAgICAgICAgICAgICAgICAgICA9IFtdLCB1ID0gW10sIGwgPSB0Lmxlbmd0aCwgYyA9IGUgfHwgZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJCQkJZm9yKHZhciByID0gMCwgaSA9IHQubGVuZ3RoOyByIDwgaTsgcisrKSBzZShlLCB0W3JdLCBuKTsNCgkJCQkJCXJldHVybiBuDQoJCQkJCX0oaCB8fCAiKiIsIG4ubm9kZVR5cGUgPyBbbl0gOiBuLCBbXSksIGYgPSAhZCB8fCAhZSAmJiBoID8gYyA6IFRlKGMsIHMsIGQsIG4sIHIpLCBwID0gZyA/IHkgfHwgKGUgPyBkIDogbCB8fCB2KSA/IFtdIDogdCA6IGY7DQoJCQkJCWlmKGcgJiYgZyhmLCBwLCBuLCByKSwgdikgew0KCQkJCQkJaSA9IFRlKHAsIHUpLCB2KGksIFtdLCBuLCByKSwgbyA9IGkubGVuZ3RoOw0KCQkJCQkJd2hpbGUoby0tKSAoYSA9IGlbb10pICYmIChwW3Vbb11dID0gIShmW3Vbb11dID0gYSkpDQoJCQkJCX0NCgkJCQkJaWYoZSkgew0KCQkJCQkJaWYoeSB8fCBkKSB7DQoJCQkJCQkJaWYoeSkgew0KCQkJCQkJCQlpID0gW10sIG8gPSBwLmxlbmd0aDsNCgkJCQkJCQkJd2hpbGUoby0tKSAoYSA9IHBbb10pICYmIGkucHVzaChmW29dID0gYSk7DQoJCQkJCQkJCXkobnVsbCwgcCA9IFtdLCBpLCByKQ0KCQkJCQkJCX0NCgkJCQkJCQlvID0gcC5sZW5ndGg7DQoJCQkJCQkJd2hpbGUoby0tKSAoYSA9IHBbb10pICYmIC0xIDwgKGkgPSB5ID8gUChlLCBhKSA6IHNbb10pICYmIChlW2ldID0gISh0W2ldID0gYSkpDQoJCQkJCQl9DQoJCQkJCX0gZWxzZSBwID0gVGUocCA9PT0gdCA/IHAuc3BsaWNlKGwsIHAubGVuZ3RoKSA6IHApLCB5ID8geShudWxsLCB0LCBwLCByKSA6IEguYXBwbHkodCwgcCkNCgkJCQl9KQ0KCQkJfQ0KDQoJCQlmdW5jdGlvbiBFZShlKSB7DQoJCQkJZm9yKHZhciBpLCB0LCBuLCByID0gZS5sZW5ndGgsIG8gPSBiLnJlbGF0aXZlW2VbMF0udHlwZV0sIGEgPSBvIHx8IGIucmVsYXRpdmVbIiAiXSwgcyA9IG8gPyAxIDogMCwgdSA9IGJlKGZ1bmN0aW9uKGUpIHtyZXR1cm4gZSA9PT0gaX0sIGEsICEwKSwgbCA9IGJlKGZ1bmN0aW9uKGUpIHtyZXR1cm4gLTEgPCBQKGksIGUpfSwgYSwgITApLCBjID0gW2Z1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQkJdmFyIHIgPSAhbyAmJiAobiB8fCB0ICE9PSB3KSB8fCAoKGkgPSB0KS5ub2RlVHlwZSA/IHUoZSwgdCwgbikgOiBsKGUsIHQsIG4pKTsNCgkJCQkJcmV0dXJuIGkgPSBudWxsLCByDQoJCQkJfV07IHMgPCByOyBzKyspIGlmKHQgPSBiLnJlbGF0aXZlW2Vbc10udHlwZV0pIGMgPSBbYmUod2UoYyksIHQpXTsgZWxzZSB7DQoJCQkJCWlmKCh0ID0gYi5maWx0ZXJbZVtzXS50eXBlXS5hcHBseShudWxsLCBlW3NdLm1hdGNoZXMpKVtTXSkgew0KCQkJCQkJZm9yKG4gPSArK3M7IG4gPCByOyBuKyspIGlmKGIucmVsYXRpdmVbZVtuXS50eXBlXSkgYnJlYWs7DQoJCQkJCQlyZXR1cm4gQ2UoMSA8IHMgJiYgd2UoYyksIDEgPCBzICYmIHhlKGUuc2xpY2UoMCwgcyAtIDEpLmNvbmNhdCh7dmFsdWU6ICIgIiA9PT0gZVtzIC0gMl0udHlwZSA/ICIqIiA6ICIifSkpLnJlcGxhY2UoJCwgIiQxIiksIHQsIHMgPCBuICYmIEVlKGUuc2xpY2UocywgbikpLCBuIDwgciAmJiBFZShlID0gZS5zbGljZShuKSksIG4gPCByICYmIHhlKGUpKQ0KCQkJCQl9DQoJCQkJCWMucHVzaCh0KQ0KCQkJCX0NCgkJCQlyZXR1cm4gd2UoYykNCgkJCX0NCg0KCQkJcmV0dXJuIG1lLnByb3RvdHlwZSA9IGIuZmlsdGVycyA9IGIucHNldWRvcywgYi5zZXRGaWx0ZXJzID0gbmV3IG1lLCBoID0gc2UudG9rZW5pemUgPSBmdW5jdGlvbihlLCB0KSB7DQoJCQkJdmFyIG4sIHIsIGksIG8sIGEsIHMsIHUsIGwgPSB4W2UgKyAiICJdOw0KCQkJCWlmKGwpIHJldHVybiB0ID8gMCA6IGwuc2xpY2UoMCk7DQoJCQkJYSA9IGUsIHMgPSBbXSwgdSA9IGIucHJlRmlsdGVyOw0KCQkJCXdoaWxlKGEpIHsNCgkJCQkJZm9yKG8gaW4gbiAmJiAhKHIgPSBfLmV4ZWMoYSkpIHx8IChyICYmIChhID0gYS5zbGljZShyWzBdLmxlbmd0aCkgfHwgYSksIHMucHVzaChpID0gW10pKSwgbiA9ICExLCAociA9IHouZXhlYyhhKSkgJiYgKG4gPSByLnNoaWZ0KCksIGkucHVzaCh7DQoJCQkJCQl2YWx1ZTogbiwNCgkJCQkJCXR5cGU6IHJbMF0ucmVwbGFjZSgkLCAiICIpDQoJCQkJCX0pLCBhID0gYS5zbGljZShuLmxlbmd0aCkpLCBiLmZpbHRlcikgIShyID0gR1tvXS5leGVjKGEpKSB8fCB1W29dICYmICEociA9IHVbb10ocikpIHx8IChuID0gci5zaGlmdCgpLCBpLnB1c2goe3ZhbHVlOiBuLCB0eXBlOiBvLCBtYXRjaGVzOiByfSksIGEgPSBhLnNsaWNlKG4ubGVuZ3RoKSk7DQoJCQkJCWlmKCFuKSBicmVhaw0KCQkJCX0NCgkJCQlyZXR1cm4gdCA/IGEubGVuZ3RoIDogYSA/IHNlLmVycm9yKGUpIDogeChlLCBzKS5zbGljZSgwKQ0KCQkJfSwgZiA9IHNlLmNvbXBpbGUgPSBmdW5jdGlvbihlLCB0KSB7DQoJCQkJdmFyIG4sIHYsIHksIG0sIHgsIHIsIGkgPSBbXSwgbyA9IFtdLCBhID0gQVtlICsgIiAiXTsNCgkJCQlpZighYSkgew0KCQkJCQl0IHx8ICh0ID0gaChlKSksIG4gPSB0Lmxlbmd0aDsNCgkJCQkJd2hpbGUobi0tKSAoYSA9IEVlKHRbbl0pKVtTXSA/IGkucHVzaChhKSA6IG8ucHVzaChhKTsNCgkJCQkJKGEgPSBBKGUsICh2ID0gbywgbSA9IDAgPCAoeSA9IGkpLmxlbmd0aCwgeCA9IDAgPCB2Lmxlbmd0aCwgciA9IGZ1bmN0aW9uKGUsIHQsIG4sIHIsIGkpIHsNCgkJCQkJCXZhciBvLCBhLCBzLCB1ID0gMCwgbCA9ICIwIiwgYyA9IGUgJiYgW10sIGYgPSBbXSwgcCA9IHcsIGQgPSBlIHx8IHggJiYgYi5maW5kLlRBRygiKiIsIGkpLCBoID0gayArPSBudWxsID09IHAgPyAxIDogTWF0aC5yYW5kb20oKSB8fCAuMSwgZyA9IGQubGVuZ3RoOw0KCQkJCQkJZm9yKGkgJiYgKHcgPSB0ID09IEMgfHwgdCB8fCBpKTsgbCAhPT0gZyAmJiBudWxsICE9IChvID0gZFtsXSk7IGwrKykgew0KCQkJCQkJCWlmKHggJiYgbykgew0KCQkJCQkJCQlhID0gMCwgdCB8fCBvLm93bmVyRG9jdW1lbnQgPT0gQyB8fCAoVChvKSwgbiA9ICFFKTsNCgkJCQkJCQkJd2hpbGUocyA9IHZbYSsrXSkgaWYocyhvLCB0IHx8IEMsIG4pKSB7DQoJCQkJCQkJCQlyLnB1c2gobyk7DQoJCQkJCQkJCQlicmVhaw0KCQkJCQkJCQl9DQoJCQkJCQkJCWkgJiYgKGsgPSBoKQ0KCQkJCQkJCX0NCgkJCQkJCQltICYmICgobyA9ICFzICYmIG8pICYmIHUtLSwgZSAmJiBjLnB1c2gobykpDQoJCQkJCQl9DQoJCQkJCQlpZih1ICs9IGwsIG0gJiYgbCAhPT0gdSkgew0KCQkJCQkJCWEgPSAwOw0KCQkJCQkJCXdoaWxlKHMgPSB5W2ErK10pIHMoYywgZiwgdCwgbik7DQoJCQkJCQkJaWYoZSkgew0KCQkJCQkJCQlpZigwIDwgdSkgd2hpbGUobC0tKSBjW2xdIHx8IGZbbF0gfHwgKGZbbF0gPSBxLmNhbGwocikpOw0KCQkJCQkJCQlmID0gVGUoZikNCgkJCQkJCQl9DQoJCQkJCQkJSC5hcHBseShyLCBmKSwgaSAmJiAhZSAmJiAwIDwgZi5sZW5ndGggJiYgMSA8IHUgKyB5Lmxlbmd0aCAmJiBzZS51bmlxdWVTb3J0KHIpDQoJCQkJCQl9DQoJCQkJCQlyZXR1cm4gaSAmJiAoayA9IGgsIHcgPSBwKSwgYw0KCQkJCQl9LCBtID8gbGUocikgOiByKSkpLnNlbGVjdG9yID0gZQ0KCQkJCX0NCgkJCQlyZXR1cm4gYQ0KCQkJfSwgZyA9IHNlLnNlbGVjdCA9IGZ1bmN0aW9uKGUsIHQsIG4sIHIpIHsNCgkJCQl2YXIgaSwgbywgYSwgcywgdSwgbCA9ICJmdW5jdGlvbiIgPT0gdHlwZW9mIGUgJiYgZSwgYyA9ICFyICYmIGgoZSA9IGwuc2VsZWN0b3IgfHwgZSk7DQoJCQkJaWYobiA9IG4gfHwgW10sIDEgPT09IGMubGVuZ3RoKSB7DQoJCQkJCWlmKDIgPCAobyA9IGNbMF0gPSBjWzBdLnNsaWNlKDApKS5sZW5ndGggJiYgIklEIiA9PT0gKGEgPSBvWzBdKS50eXBlICYmIDkgPT09IHQubm9kZVR5cGUgJiYgRSAmJiBiLnJlbGF0aXZlW29bMV0udHlwZV0pIHsNCgkJCQkJCWlmKCEodCA9IChiLmZpbmQuSUQoYS5tYXRjaGVzWzBdLnJlcGxhY2UodGUsIG5lKSwgdCkgfHwgW10pWzBdKSkgcmV0dXJuIG47DQoJCQkJCQlsICYmICh0ID0gdC5wYXJlbnROb2RlKSwgZSA9IGUuc2xpY2Uoby5zaGlmdCgpLnZhbHVlLmxlbmd0aCkNCgkJCQkJfQ0KCQkJCQlpID0gRy5uZWVkc0NvbnRleHQudGVzdChlKSA/IDAgOiBvLmxlbmd0aDsNCgkJCQkJd2hpbGUoaS0tKSB7DQoJCQkJCQlpZihhID0gb1tpXSwgYi5yZWxhdGl2ZVtzID0gYS50eXBlXSkgYnJlYWs7DQoJCQkJCQlpZigodSA9IGIuZmluZFtzXSkgJiYgKHIgPSB1KGEubWF0Y2hlc1swXS5yZXBsYWNlKHRlLCBuZSksIGVlLnRlc3Qob1swXS50eXBlKSAmJiB5ZSh0LnBhcmVudE5vZGUpIHx8IHQpKSkgew0KCQkJCQkJCWlmKG8uc3BsaWNlKGksIDEpLCAhKGUgPSByLmxlbmd0aCAmJiB4ZShvKSkpIHJldHVybiBILmFwcGx5KG4sIHIpLCBuOw0KCQkJCQkJCWJyZWFrDQoJCQkJCQl9DQoJCQkJCX0NCgkJCQl9DQoJCQkJcmV0dXJuIChsIHx8IGYoZSwgYykpKHIsIHQsICFFLCBuLCAhdCB8fCBlZS50ZXN0KGUpICYmIHllKHQucGFyZW50Tm9kZSkgfHwgdCksIG4NCgkJCX0sIGQuc29ydFN0YWJsZSA9IFMuc3BsaXQoIiIpLnNvcnQoaikuam9pbigiIikgPT09IFMsIGQuZGV0ZWN0RHVwbGljYXRlcyA9ICEhbCwgVCgpLCBkLnNvcnREZXRhY2hlZCA9IGNlKGZ1bmN0aW9uKGUpIHtyZXR1cm4gMSAmIGUuY29tcGFyZURvY3VtZW50UG9zaXRpb24oQy5jcmVhdGVFbGVtZW50KCJmaWVsZHNldCIpKX0pLCBjZShmdW5jdGlvbihlKSB7cmV0dXJuIGUuaW5uZXJIVE1MID0gIjxhIGhyZWY9JyMnPjwvYT4iLCAiIyIgPT09IGUuZmlyc3RDaGlsZC5nZXRBdHRyaWJ1dGUoImhyZWYiKX0pIHx8IGZlKCJ0eXBlfGhyZWZ8aGVpZ2h0fHdpZHRoIiwgZnVuY3Rpb24oZSwgdCwgbikge2lmKCFuKSByZXR1cm4gZS5nZXRBdHRyaWJ1dGUodCwgInR5cGUiID09PSB0LnRvTG93ZXJDYXNlKCkgPyAxIDogMil9KSwgZC5hdHRyaWJ1dGVzICYmIGNlKGZ1bmN0aW9uKGUpIHtyZXR1cm4gZS5pbm5lckhUTUwgPSAiPGlucHV0Lz4iLCBlLmZpcnN0Q2hpbGQuc2V0QXR0cmlidXRlKCJ2YWx1ZSIsICIiKSwgIiIgPT09IGUuZmlyc3RDaGlsZC5nZXRBdHRyaWJ1dGUoInZhbHVlIil9KSB8fCBmZSgidmFsdWUiLCBmdW5jdGlvbihlLCB0LCBuKSB7aWYoIW4gJiYgImlucHV0IiA9PT0gZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpKSByZXR1cm4gZS5kZWZhdWx0VmFsdWV9KSwgY2UoZnVuY3Rpb24oZSkge3JldHVybiBudWxsID09IGUuZ2V0QXR0cmlidXRlKCJkaXNhYmxlZCIpfSkgfHwgZmUoUiwgZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJCXZhciByOw0KCQkJCWlmKCFuKSByZXR1cm4gITAgPT09IGVbdF0gPyB0LnRvTG93ZXJDYXNlKCkgOiAociA9IGUuZ2V0QXR0cmlidXRlTm9kZSh0KSkgJiYgci5zcGVjaWZpZWQgPyByLnZhbHVlIDogbnVsbA0KCQkJfSksIHNlDQoJCX0oQyk7DQoJCVMuZmluZCA9IGQsIFMuZXhwciA9IGQuc2VsZWN0b3JzLCBTLmV4cHJbIjoiXSA9IFMuZXhwci5wc2V1ZG9zLCBTLnVuaXF1ZVNvcnQgPSBTLnVuaXF1ZSA9IGQudW5pcXVlU29ydCwgUy50ZXh0ID0gZC5nZXRUZXh0LCBTLmlzWE1MRG9jID0gZC5pc1hNTCwgUy5jb250YWlucyA9IGQuY29udGFpbnMsIFMuZXNjYXBlU2VsZWN0b3IgPSBkLmVzY2FwZTsNCgkJdmFyIGggPSBmdW5jdGlvbihlLCB0LCBuKSB7DQoJCQl2YXIgciA9IFtdLCBpID0gdm9pZCAwICE9PSBuOw0KCQkJd2hpbGUoKGUgPSBlW3RdKSAmJiA5ICE9PSBlLm5vZGVUeXBlKSBpZigxID09PSBlLm5vZGVUeXBlKSB7DQoJCQkJaWYoaSAmJiBTKGUpLmlzKG4pKSBicmVhazsNCgkJCQlyLnB1c2goZSkNCgkJCX0NCgkJCXJldHVybiByDQoJCX0sIFQgID0gZnVuY3Rpb24oZSwgdCkgew0KCQkJZm9yKHZhciBuID0gW107IGU7IGUgPSBlLm5leHRTaWJsaW5nKSAxID09PSBlLm5vZGVUeXBlICYmIGUgIT09IHQgJiYgbi5wdXNoKGUpOw0KCQkJcmV0dXJuIG4NCgkJfSwgayAgPSBTLmV4cHIubWF0Y2gubmVlZHNDb250ZXh0Ow0KDQoJCWZ1bmN0aW9uIEEoZSwgdCkge3JldHVybiBlLm5vZGVOYW1lICYmIGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gdC50b0xvd2VyQ2FzZSgpfQ0KDQoJCXZhciBOID0gL148KFthLXpdW15cL1wwPjpceDIwXHRcclxuXGZdKilbXHgyMFx0XHJcblxmXSpcLz8+KD86PFwvXDE+fCkkL2k7DQoNCgkJZnVuY3Rpb24gaihlLCBuLCByKSB7cmV0dXJuIG0obikgPyBTLmdyZXAoZSwgZnVuY3Rpb24oZSwgdCkge3JldHVybiAhIW4uY2FsbChlLCB0LCBlKSAhPT0gcn0pIDogbi5ub2RlVHlwZSA/IFMuZ3JlcChlLCBmdW5jdGlvbihlKSB7cmV0dXJuIGUgPT09IG4gIT09IHJ9KSA6ICJzdHJpbmciICE9IHR5cGVvZiBuID8gUy5ncmVwKGUsIGZ1bmN0aW9uKGUpIHtyZXR1cm4gLTEgPCBpLmNhbGwobiwgZSkgIT09IHJ9KSA6IFMuZmlsdGVyKG4sIGUsIHIpfQ0KDQoJCVMuZmlsdGVyID0gZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJdmFyIHIgPSB0WzBdOw0KCQkJcmV0dXJuIG4gJiYgKGUgPSAiOm5vdCgiICsgZSArICIpIiksIDEgPT09IHQubGVuZ3RoICYmIDEgPT09IHIubm9kZVR5cGUgPyBTLmZpbmQubWF0Y2hlc1NlbGVjdG9yKHIsIGUpID8gW3JdIDogW10gOiBTLmZpbmQubWF0Y2hlcyhlLCBTLmdyZXAodCwgZnVuY3Rpb24oZSkge3JldHVybiAxID09PSBlLm5vZGVUeXBlfSkpDQoJCX0sIFMuZm4uZXh0ZW5kKHsNCgkJCWZpbmQ6IGZ1bmN0aW9uKGUpIHsNCgkJCQl2YXIgdCwgbiwgciA9IHRoaXMubGVuZ3RoLCBpID0gdGhpczsNCgkJCQlpZigic3RyaW5nIiAhPSB0eXBlb2YgZSkgcmV0dXJuIHRoaXMucHVzaFN0YWNrKFMoZSkuZmlsdGVyKGZ1bmN0aW9uKCkge2Zvcih0ID0gMDsgdCA8IHI7IHQrKykgaWYoUy5jb250YWlucyhpW3RdLCB0aGlzKSkgcmV0dXJuICEwfSkpOw0KCQkJCWZvcihuID0gdGhpcy5wdXNoU3RhY2soW10pLCB0ID0gMDsgdCA8IHI7IHQrKykgUy5maW5kKGUsIGlbdF0sIG4pOw0KCQkJCXJldHVybiAxIDwgciA/IFMudW5pcXVlU29ydChuKSA6IG4NCgkJCX0sIGZpbHRlcjogZnVuY3Rpb24oZSkge3JldHVybiB0aGlzLnB1c2hTdGFjayhqKHRoaXMsIGUgfHwgW10sICExKSl9LCBub3Q6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gdGhpcy5wdXNoU3RhY2soaih0aGlzLCBlIHx8IFtdLCAhMCkpfSwgaXM6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gISFqKHRoaXMsICJzdHJpbmciID09IHR5cGVvZiBlICYmIGsudGVzdChlKSA/IFMoZSkgOiBlIHx8IFtdLCAhMSkubGVuZ3RofQ0KCQl9KTsNCgkJdmFyIEQsIHEgPSAvXig/OlxzKig8W1x3XFddKz4pW14+XSp8IyhbXHctXSspKSQvOw0KCQkoUy5mbi5pbml0ID0gZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJdmFyIHIsIGk7DQoJCQlpZighZSkgcmV0dXJuIHRoaXM7DQoJCQlpZihuID0gbiB8fCBELCAic3RyaW5nIiA9PSB0eXBlb2YgZSkgew0KCQkJCWlmKCEociA9ICI8IiA9PT0gZVswXSAmJiAiPiIgPT09IGVbZS5sZW5ndGggLSAxXSAmJiAzIDw9IGUubGVuZ3RoID8gW251bGwsIGUsIG51bGxdIDogcS5leGVjKGUpKSB8fCAhclsxXSAmJiB0KSByZXR1cm4gIXQgfHwgdC5qcXVlcnkgPyAodCB8fCBuKS5maW5kKGUpIDogdGhpcy5jb25zdHJ1Y3Rvcih0KS5maW5kKGUpOw0KCQkJCWlmKHJbMV0pIHsNCgkJCQkJaWYodCA9IHQgaW5zdGFuY2VvZiBTID8gdFswXSA6IHQsIFMubWVyZ2UodGhpcywgUy5wYXJzZUhUTUwoclsxXSwgdCAmJiB0Lm5vZGVUeXBlID8gdC5vd25lckRvY3VtZW50IHx8IHQgOiBFLCAhMCkpLCBOLnRlc3QoclsxXSkgJiYgUy5pc1BsYWluT2JqZWN0KHQpKSBmb3IociBpbiB0KSBtKHRoaXNbcl0pID8gdGhpc1tyXSh0W3JdKSA6IHRoaXMuYXR0cihyLCB0W3JdKTsNCgkJCQkJcmV0dXJuIHRoaXMNCgkJCQl9DQoJCQkJcmV0dXJuIChpID0gRS5nZXRFbGVtZW50QnlJZChyWzJdKSkgJiYgKHRoaXNbMF0gPSBpLCB0aGlzLmxlbmd0aCA9IDEpLCB0aGlzDQoJCQl9DQoJCQlyZXR1cm4gZS5ub2RlVHlwZSA/ICh0aGlzWzBdID0gZSwgdGhpcy5sZW5ndGggPSAxLCB0aGlzKSA6IG0oZSkgPyB2b2lkIDAgIT09IG4ucmVhZHkgPyBuLnJlYWR5KGUpIDogZShTKSA6IFMubWFrZUFycmF5KGUsIHRoaXMpDQoJCX0pLnByb3RvdHlwZSA9IFMuZm4sIEQgPSBTKEUpOw0KCQl2YXIgTCA9IC9eKD86cGFyZW50c3xwcmV2KD86VW50aWx8QWxsKSkvLCBIID0ge2NoaWxkcmVuOiAhMCwgY29udGVudHM6ICEwLCBuZXh0OiAhMCwgcHJldjogITB9Ow0KDQoJCWZ1bmN0aW9uIE8oZSwgdCkgew0KCQkJd2hpbGUoKGUgPSBlW3RdKSAmJiAxICE9PSBlLm5vZGVUeXBlKSA7DQoJCQlyZXR1cm4gZQ0KCQl9DQoNCgkJUy5mbi5leHRlbmQoew0KCQkJaGFzOiBmdW5jdGlvbihlKSB7DQoJCQkJdmFyIHQgPSBTKGUsIHRoaXMpLCBuID0gdC5sZW5ndGg7DQoJCQkJcmV0dXJuIHRoaXMuZmlsdGVyKGZ1bmN0aW9uKCkge2Zvcih2YXIgZSA9IDA7IGUgPCBuOyBlKyspIGlmKFMuY29udGFpbnModGhpcywgdFtlXSkpIHJldHVybiAhMH0pDQoJCQl9LA0KCQkJY2xvc2VzdDogZnVuY3Rpb24oZSwgdCkgew0KCQkJCXZhciBuLCByID0gMCwgaSA9IHRoaXMubGVuZ3RoLCBvID0gW10sIGEgPSAic3RyaW5nIiAhPSB0eXBlb2YgZSAmJiBTKGUpOw0KCQkJCWlmKCFrLnRlc3QoZSkpIGZvcig7IHIgPCBpOyByKyspIGZvcihuID0gdGhpc1tyXTsgbiAmJiBuICE9PSB0OyBuID0gbi5wYXJlbnROb2RlKSBpZihuLm5vZGVUeXBlIDwgMTEgJiYgKGEgPyAtMSA8IGEuaW5kZXgobikgOiAxID09PSBuLm5vZGVUeXBlICYmIFMuZmluZC5tYXRjaGVzU2VsZWN0b3IobiwgZSkpKSB7DQoJCQkJCW8ucHVzaChuKTsNCgkJCQkJYnJlYWsNCgkJCQl9DQoJCQkJcmV0dXJuIHRoaXMucHVzaFN0YWNrKDEgPCBvLmxlbmd0aCA/IFMudW5pcXVlU29ydChvKSA6IG8pDQoJCQl9LA0KCQkJaW5kZXg6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gZSA/ICJzdHJpbmciID09IHR5cGVvZiBlID8gaS5jYWxsKFMoZSksIHRoaXNbMF0pIDogaS5jYWxsKHRoaXMsIGUuanF1ZXJ5ID8gZVswXSA6IGUpIDogdGhpc1swXSAmJiB0aGlzWzBdLnBhcmVudE5vZGUgPyB0aGlzLmZpcnN0KCkucHJldkFsbCgpLmxlbmd0aCA6IC0xfSwNCgkJCWFkZDogZnVuY3Rpb24oZSwgdCkge3JldHVybiB0aGlzLnB1c2hTdGFjayhTLnVuaXF1ZVNvcnQoUy5tZXJnZSh0aGlzLmdldCgpLCBTKGUsIHQpKSkpfSwNCgkJCWFkZEJhY2s6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gdGhpcy5hZGQobnVsbCA9PSBlID8gdGhpcy5wcmV2T2JqZWN0IDogdGhpcy5wcmV2T2JqZWN0LmZpbHRlcihlKSl9DQoJCX0pLCBTLmVhY2goew0KCQkJcGFyZW50OiBmdW5jdGlvbihlKSB7DQoJCQkJdmFyIHQgPSBlLnBhcmVudE5vZGU7DQoJCQkJcmV0dXJuIHQgJiYgMTEgIT09IHQubm9kZVR5cGUgPyB0IDogbnVsbA0KCQkJfSwNCgkJCXBhcmVudHM6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gaChlLCAicGFyZW50Tm9kZSIpfSwNCgkJCXBhcmVudHNVbnRpbDogZnVuY3Rpb24oZSwgdCwgbikge3JldHVybiBoKGUsICJwYXJlbnROb2RlIiwgbil9LA0KCQkJbmV4dDogZnVuY3Rpb24oZSkge3JldHVybiBPKGUsICJuZXh0U2libGluZyIpfSwNCgkJCXByZXY6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gTyhlLCAicHJldmlvdXNTaWJsaW5nIil9LA0KCQkJbmV4dEFsbDogZnVuY3Rpb24oZSkge3JldHVybiBoKGUsICJuZXh0U2libGluZyIpfSwNCgkJCXByZXZBbGw6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gaChlLCAicHJldmlvdXNTaWJsaW5nIil9LA0KCQkJbmV4dFVudGlsOiBmdW5jdGlvbihlLCB0LCBuKSB7cmV0dXJuIGgoZSwgIm5leHRTaWJsaW5nIiwgbil9LA0KCQkJcHJldlVudGlsOiBmdW5jdGlvbihlLCB0LCBuKSB7cmV0dXJuIGgoZSwgInByZXZpb3VzU2libGluZyIsIG4pfSwNCgkJCXNpYmxpbmdzOiBmdW5jdGlvbihlKSB7cmV0dXJuIFQoKGUucGFyZW50Tm9kZSB8fCB7fSkuZmlyc3RDaGlsZCwgZSl9LA0KCQkJY2hpbGRyZW46IGZ1bmN0aW9uKGUpIHtyZXR1cm4gVChlLmZpcnN0Q2hpbGQpfSwNCgkJCWNvbnRlbnRzOiBmdW5jdGlvbihlKSB7cmV0dXJuIG51bGwgIT0gZS5jb250ZW50RG9jdW1lbnQgJiYgcihlLmNvbnRlbnREb2N1bWVudCkgPyBlLmNvbnRlbnREb2N1bWVudCA6IChBKGUsICJ0ZW1wbGF0ZSIpICYmIChlID0gZS5jb250ZW50IHx8IGUpLCBTLm1lcmdlKFtdLCBlLmNoaWxkTm9kZXMpKX0NCgkJfSwgZnVuY3Rpb24ociwgaSkgew0KCQkJUy5mbltyXSA9IGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQl2YXIgbiA9IFMubWFwKHRoaXMsIGksIGUpOw0KCQkJCXJldHVybiAiVW50aWwiICE9PSByLnNsaWNlKC01KSAmJiAodCA9IGUpLCB0ICYmICJzdHJpbmciID09IHR5cGVvZiB0ICYmIChuID0gUy5maWx0ZXIodCwgbikpLCAxIDwgdGhpcy5sZW5ndGggJiYgKEhbcl0gfHwgUy51bmlxdWVTb3J0KG4pLCBMLnRlc3QocikgJiYgbi5yZXZlcnNlKCkpLCB0aGlzLnB1c2hTdGFjayhuKQ0KCQkJfQ0KCQl9KTsNCgkJdmFyIFAgPSAvW15ceDIwXHRcclxuXGZdKy9nOw0KDQoJCWZ1bmN0aW9uIFIoZSkge3JldHVybiBlfQ0KDQoJCWZ1bmN0aW9uIE0oZSkge3Rocm93IGV9DQoNCgkJZnVuY3Rpb24gSShlLCB0LCBuLCByKSB7DQoJCQl2YXIgaTsNCgkJCXRyeSB7ZSAmJiBtKGkgPSBlLnByb21pc2UpID8gaS5jYWxsKGUpLmRvbmUodCkuZmFpbChuKSA6IGUgJiYgbShpID0gZS50aGVuKSA/IGkuY2FsbChlLCB0LCBuKSA6IHQuYXBwbHkodm9pZCAwLCBbZV0uc2xpY2UocikpfSBjYXRjaChlKSB7bi5hcHBseSh2b2lkIDAsIFtlXSl9DQoJCX0NCg0KCQlTLkNhbGxiYWNrcyA9IGZ1bmN0aW9uKHIpIHsNCgkJCXZhciBlLCBuOw0KCQkJciA9ICJzdHJpbmciID09IHR5cGVvZiByID8gKGUgPSByLCBuID0ge30sIFMuZWFjaChlLm1hdGNoKFApIHx8IFtdLCBmdW5jdGlvbihlLCB0KSB7blt0XSA9ICEwfSksIG4pIDogUy5leHRlbmQoe30sIHIpOw0KCQkJdmFyIGksDQoJCQkgICAgdCwNCgkJCSAgICBvLA0KCQkJICAgIGEsDQoJCQkgICAgcyA9IFtdLA0KCQkJICAgIHUgPSBbXSwNCgkJCSAgICBsID0gLTEsDQoJCQkgICAgYyA9IGZ1bmN0aW9uKCkgew0KCQkJCSAgICBmb3IoYSA9IGEgfHwgci5vbmNlLCBvID0gaSA9ICEwOyB1Lmxlbmd0aDsgbCA9IC0xKSB7DQoJCQkJCSAgICB0ID0gdS5zaGlmdCgpOw0KCQkJCQkgICAgd2hpbGUoKytsIDwgcy5sZW5ndGgpICExID09PSBzW2xdLmFwcGx5KHRbMF0sIHRbMV0pICYmIHIuc3RvcE9uRmFsc2UgJiYgKGwgPSBzLmxlbmd0aCwgdCA9ICExKQ0KCQkJCSAgICB9DQoJCQkJICAgIHIubWVtb3J5IHx8ICh0ID0gITEpLCBpID0gITEsIGEgJiYgKHMgPSB0ID8gW10gOiAiIikNCgkJCSAgICB9LA0KCQkJICAgIGYgPSB7DQoJCQkJICAgIGFkZDogZnVuY3Rpb24oKSB7cmV0dXJuIHMgJiYgKHQgJiYgIWkgJiYgKGwgPSBzLmxlbmd0aCAtIDEsIHUucHVzaCh0KSksIGZ1bmN0aW9uIG4oZSkge1MuZWFjaChlLCBmdW5jdGlvbihlLCB0KSB7bSh0KSA/IHIudW5pcXVlICYmIGYuaGFzKHQpIHx8IHMucHVzaCh0KSA6IHQgJiYgdC5sZW5ndGggJiYgInN0cmluZyIgIT09IHcodCkgJiYgbih0KX0pfShhcmd1bWVudHMpLCB0ICYmICFpICYmIGMoKSksIHRoaXN9LA0KCQkJCSAgICByZW1vdmU6IGZ1bmN0aW9uKCkgew0KCQkJCQkgICAgcmV0dXJuIFMuZWFjaChhcmd1bWVudHMsIGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQkJCSAgICB2YXIgbjsNCgkJCQkJCSAgICB3aGlsZSgtMSA8IChuID0gUy5pbkFycmF5KHQsIHMsIG4pKSkgcy5zcGxpY2UobiwgMSksIG4gPD0gbCAmJiBsLS0NCgkJCQkJICAgIH0pLCB0aGlzDQoJCQkJICAgIH0sDQoJCQkJICAgIGhhczogZnVuY3Rpb24oZSkge3JldHVybiBlID8gLTEgPCBTLmluQXJyYXkoZSwgcykgOiAwIDwgcy5sZW5ndGh9LA0KCQkJCSAgICBlbXB0eTogZnVuY3Rpb24oKSB7cmV0dXJuIHMgJiYgKHMgPSBbXSksIHRoaXN9LA0KCQkJCSAgICBkaXNhYmxlOiBmdW5jdGlvbigpIHtyZXR1cm4gYSA9IHUgPSBbXSwgcyA9IHQgPSAiIiwgdGhpc30sDQoJCQkJICAgIGRpc2FibGVkOiBmdW5jdGlvbigpIHtyZXR1cm4gIXN9LA0KCQkJCSAgICBsb2NrOiBmdW5jdGlvbigpIHtyZXR1cm4gYSA9IHUgPSBbXSwgdCB8fCBpIHx8IChzID0gdCA9ICIiKSwgdGhpc30sDQoJCQkJICAgIGxvY2tlZDogZnVuY3Rpb24oKSB7cmV0dXJuICEhYX0sDQoJCQkJICAgIGZpcmVXaXRoOiBmdW5jdGlvbihlLCB0KSB7cmV0dXJuIGEgfHwgKHQgPSBbZSwgKHQgPSB0IHx8IFtdKS5zbGljZSA/IHQuc2xpY2UoKSA6IHRdLCB1LnB1c2godCksIGkgfHwgYygpKSwgdGhpc30sDQoJCQkJICAgIGZpcmU6IGZ1bmN0aW9uKCkge3JldHVybiBmLmZpcmVXaXRoKHRoaXMsIGFyZ3VtZW50cyksIHRoaXN9LA0KCQkJCSAgICBmaXJlZDogZnVuY3Rpb24oKSB7cmV0dXJuICEhb30NCgkJCSAgICB9Ow0KCQkJcmV0dXJuIGYNCgkJfSwgUy5leHRlbmQoew0KCQkJRGVmZXJyZWQ6IGZ1bmN0aW9uKGUpIHsNCgkJCQl2YXIgbyA9IFtbIm5vdGlmeSIsICJwcm9ncmVzcyIsIFMuQ2FsbGJhY2tzKCJtZW1vcnkiKSwgUy5DYWxsYmFja3MoIm1lbW9yeSIpLCAyXSwgWyJyZXNvbHZlIiwgImRvbmUiLCBTLkNhbGxiYWNrcygib25jZSBtZW1vcnkiKSwgUy5DYWxsYmFja3MoIm9uY2UgbWVtb3J5IiksIDAsICJyZXNvbHZlZCJdLCBbInJlamVjdCIsICJmYWlsIiwgUy5DYWxsYmFja3MoIm9uY2UgbWVtb3J5IiksIFMuQ2FsbGJhY2tzKCJvbmNlIG1lbW9yeSIpLCAxLCAicmVqZWN0ZWQiXV0sDQoJCQkJICAgIGkgPSAicGVuZGluZyIsDQoJCQkJICAgIGEgPSB7DQoJCQkJCSAgICBzdGF0ZTogZnVuY3Rpb24oKSB7cmV0dXJuIGl9LCBhbHdheXM6IGZ1bmN0aW9uKCkge3JldHVybiBzLmRvbmUoYXJndW1lbnRzKS5mYWlsKGFyZ3VtZW50cyksIHRoaXN9LCAiY2F0Y2giOiBmdW5jdGlvbihlKSB7cmV0dXJuIGEudGhlbihudWxsLCBlKX0sIHBpcGU6IGZ1bmN0aW9uKCkgew0KCQkJCQkJICAgIHZhciBpID0gYXJndW1lbnRzOw0KCQkJCQkJICAgIHJldHVybiBTLkRlZmVycmVkKGZ1bmN0aW9uKHIpIHsNCgkJCQkJCQkgICAgUy5lYWNoKG8sIGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQkJCQkJICAgIHZhciBuID0gbShpW3RbNF1dKSAmJiBpW3RbNF1dOw0KCQkJCQkJCQkgICAgc1t0WzFdXShmdW5jdGlvbigpIHsNCgkJCQkJCQkJCSAgICB2YXIgZSA9IG4gJiYgbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpOw0KCQkJCQkJCQkJICAgIGUgJiYgbShlLnByb21pc2UpID8gZS5wcm9taXNlKCkucHJvZ3Jlc3Moci5ub3RpZnkpLmRvbmUoci5yZXNvbHZlKS5mYWlsKHIucmVqZWN0KSA6IHJbdFswXSArICJXaXRoIl0odGhpcywgbiA/IFtlXSA6IGFyZ3VtZW50cykNCgkJCQkJCQkJICAgIH0pDQoJCQkJCQkJICAgIH0pLCBpID0gbnVsbA0KCQkJCQkJICAgIH0pLnByb21pc2UoKQ0KCQkJCQkgICAgfSwgdGhlbjogZnVuY3Rpb24odCwgbiwgcikgew0KCQkJCQkJICAgIHZhciB1ID0gMDsNCg0KCQkJCQkJICAgIGZ1bmN0aW9uIGwoaSwgbywgYSwgcykgew0KCQkJCQkJCSAgICByZXR1cm4gZnVuY3Rpb24oKSB7DQoJCQkJCQkJCSAgICB2YXIgbiA9IHRoaXMsIHIgPSBhcmd1bWVudHMsIGUgPSBmdW5jdGlvbigpIHsNCgkJCQkJCQkJCSAgICB2YXIgZSwgdDsNCgkJCQkJCQkJCSAgICBpZighKGkgPCB1KSkgew0KCQkJCQkJCQkJCSAgICBpZigoZSA9IGEuYXBwbHkobiwgcikpID09PSBvLnByb21pc2UoKSkgdGhyb3cgbmV3IFR5cGVFcnJvcigiVGhlbmFibGUgc2VsZi1yZXNvbHV0aW9uIik7DQoJCQkJCQkJCQkJICAgIHQgPSBlICYmICgib2JqZWN0IiA9PSB0eXBlb2YgZSB8fCAiZnVuY3Rpb24iID09IHR5cGVvZiBlKSAmJiBlLnRoZW4sIG0odCkgPyBzID8gdC5jYWxsKGUsIGwodSwgbywgUiwgcyksIGwodSwgbywgTSwgcykpIDogKHUrKywgdC5jYWxsKGUsIGwodSwgbywgUiwgcyksIGwodSwgbywgTSwgcyksIGwodSwgbywgUiwgby5ub3RpZnlXaXRoKSkpIDogKGEgIT09IFIgJiYgKG4gPSB2b2lkIDAsIHIgPSBbZV0pLCAocyB8fCBvLnJlc29sdmVXaXRoKShuLCByKSkNCgkJCQkJCQkJCSAgICB9DQoJCQkJCQkJCSAgICB9LCB0ICAgICAgICAgICAgICAgICAgICAgICAgICAgPSBzID8gZSA6IGZ1bmN0aW9uKCkge3RyeSB7ZSgpfSBjYXRjaChlKSB7Uy5EZWZlcnJlZC5leGNlcHRpb25Ib29rICYmIFMuRGVmZXJyZWQuZXhjZXB0aW9uSG9vayhlLCB0LnN0YWNrVHJhY2UpLCB1IDw9IGkgKyAxICYmIChhICE9PSBNICYmIChuID0gdm9pZCAwLCByID0gW2VdKSwgby5yZWplY3RXaXRoKG4sIHIpKX19Ow0KCQkJCQkJCQkgICAgaSA/IHQoKSA6IChTLkRlZmVycmVkLmdldFN0YWNrSG9vayAmJiAodC5zdGFja1RyYWNlID0gUy5EZWZlcnJlZC5nZXRTdGFja0hvb2soKSksIEMuc2V0VGltZW91dCh0KSkNCgkJCQkJCQkgICAgfQ0KCQkJCQkJICAgIH0NCg0KCQkJCQkJICAgIHJldHVybiBTLkRlZmVycmVkKGZ1bmN0aW9uKGUpIHtvWzBdWzNdLmFkZChsKDAsIGUsIG0ocikgPyByIDogUiwgZS5ub3RpZnlXaXRoKSksIG9bMV1bM10uYWRkKGwoMCwgZSwgbSh0KSA/IHQgOiBSKSksIG9bMl1bM10uYWRkKGwoMCwgZSwgbShuKSA/IG4gOiBNKSl9KS5wcm9taXNlKCkNCgkJCQkJICAgIH0sIHByb21pc2U6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gbnVsbCAhPSBlID8gUy5leHRlbmQoZSwgYSkgOiBhfQ0KCQkJCSAgICB9LA0KCQkJCSAgICBzID0ge307DQoJCQkJcmV0dXJuIFMuZWFjaChvLCBmdW5jdGlvbihlLCB0KSB7DQoJCQkJCXZhciBuID0gdFsyXSwgciA9IHRbNV07DQoJCQkJCWFbdFsxXV0gPSBuLmFkZCwgciAmJiBuLmFkZChmdW5jdGlvbigpIHtpID0gcn0sIG9bMyAtIGVdWzJdLmRpc2FibGUsIG9bMyAtIGVdWzNdLmRpc2FibGUsIG9bMF1bMl0ubG9jaywgb1swXVszXS5sb2NrKSwgbi5hZGQodFszXS5maXJlKSwgc1t0WzBdXSA9IGZ1bmN0aW9uKCkge3JldHVybiBzW3RbMF0gKyAiV2l0aCJdKHRoaXMgPT09IHMgPyB2b2lkIDAgOiB0aGlzLCBhcmd1bWVudHMpLCB0aGlzfSwgc1t0WzBdICsgIldpdGgiXSA9IG4uZmlyZVdpdGgNCgkJCQl9KSwgYS5wcm9taXNlKHMpLCBlICYmIGUuY2FsbChzLCBzKSwgcw0KCQkJfSwgd2hlbjogZnVuY3Rpb24oZSkgew0KCQkJCXZhciBuID0gYXJndW1lbnRzLmxlbmd0aCwgdCA9IG4sIHIgPSBBcnJheSh0KSwgaSA9IHMuY2FsbChhcmd1bWVudHMpLCBvID0gUy5EZWZlcnJlZCgpLCBhID0gZnVuY3Rpb24odCkge3JldHVybiBmdW5jdGlvbihlKSB7clt0XSA9IHRoaXMsIGlbdF0gPSAxIDwgYXJndW1lbnRzLmxlbmd0aCA/IHMuY2FsbChhcmd1bWVudHMpIDogZSwgLS1uIHx8IG8ucmVzb2x2ZVdpdGgociwgaSl9fTsNCgkJCQlpZihuIDw9IDEgJiYgKEkoZSwgby5kb25lKGEodCkpLnJlc29sdmUsIG8ucmVqZWN0LCAhbiksICJwZW5kaW5nIiA9PT0gby5zdGF0ZSgpIHx8IG0oaVt0XSAmJiBpW3RdLnRoZW4pKSkgcmV0dXJuIG8udGhlbigpOw0KCQkJCXdoaWxlKHQtLSkgSShpW3RdLCBhKHQpLCBvLnJlamVjdCk7DQoJCQkJcmV0dXJuIG8ucHJvbWlzZSgpDQoJCQl9DQoJCX0pOw0KCQl2YXIgVyA9IC9eKEV2YWx8SW50ZXJuYWx8UmFuZ2V8UmVmZXJlbmNlfFN5bnRheHxUeXBlfFVSSSlFcnJvciQvOw0KCQlTLkRlZmVycmVkLmV4Y2VwdGlvbkhvb2sgPSBmdW5jdGlvbihlLCB0KSB7Qy5jb25zb2xlICYmIEMuY29uc29sZS53YXJuICYmIGUgJiYgVy50ZXN0KGUubmFtZSkgJiYgQy5jb25zb2xlLndhcm4oImpRdWVyeS5EZWZlcnJlZCBleGNlcHRpb246ICIgKyBlLm1lc3NhZ2UsIGUuc3RhY2ssIHQpfSwgUy5yZWFkeUV4Y2VwdGlvbiA9IGZ1bmN0aW9uKGUpIHtDLnNldFRpbWVvdXQoZnVuY3Rpb24oKSB7dGhyb3cgZX0pfTsNCgkJdmFyIEYgPSBTLkRlZmVycmVkKCk7DQoNCgkJZnVuY3Rpb24gQigpIHtFLnJlbW92ZUV2ZW50TGlzdGVuZXIoIkRPTUNvbnRlbnRMb2FkZWQiLCBCKSwgQy5yZW1vdmVFdmVudExpc3RlbmVyKCJsb2FkIiwgQiksIFMucmVhZHkoKX0NCg0KCQlTLmZuLnJlYWR5ID0gZnVuY3Rpb24oZSkge3JldHVybiBGLnRoZW4oZSlbImNhdGNoIl0oZnVuY3Rpb24oZSkge1MucmVhZHlFeGNlcHRpb24oZSl9KSwgdGhpc30sIFMuZXh0ZW5kKHsNCgkJCWlzUmVhZHk6ICExLA0KCQkJcmVhZHlXYWl0OiAxLA0KCQkJcmVhZHk6IGZ1bmN0aW9uKGUpIHsoITAgPT09IGUgPyAtLVMucmVhZHlXYWl0IDogUy5pc1JlYWR5KSB8fCAoUy5pc1JlYWR5ID0gITApICE9PSBlICYmIDAgPCAtLVMucmVhZHlXYWl0IHx8IEYucmVzb2x2ZVdpdGgoRSwgW1NdKX0NCgkJfSksIFMucmVhZHkudGhlbiA9IEYudGhlbiwgImNvbXBsZXRlIiA9PT0gRS5yZWFkeVN0YXRlIHx8ICJsb2FkaW5nIiAhPT0gRS5yZWFkeVN0YXRlICYmICFFLmRvY3VtZW50RWxlbWVudC5kb1Njcm9sbCA/IEMuc2V0VGltZW91dChTLnJlYWR5KSA6IChFLmFkZEV2ZW50TGlzdGVuZXIoIkRPTUNvbnRlbnRMb2FkZWQiLCBCKSwgQy5hZGRFdmVudExpc3RlbmVyKCJsb2FkIiwgQikpOw0KCQl2YXIgJCA9IGZ1bmN0aW9uKGUsIHQsIG4sIHIsIGksIG8sIGEpIHsNCgkJCXZhciBzID0gMCwgdSA9IGUubGVuZ3RoLCBsID0gbnVsbCA9PSBuOw0KCQkJaWYoIm9iamVjdCIgPT09IHcobikpIGZvcihzIGluIGkgPSAhMCwgbikgJChlLCB0LCBzLCBuW3NdLCAhMCwgbywgYSk7IGVsc2UgaWYodm9pZCAwICE9PSByICYmIChpID0gITAsIG0ocikgfHwgKGEgPSAhMCksIGwgJiYgKGEgPyAodC5jYWxsKGUsIHIpLCB0ID0gbnVsbCkgOiAobCA9IHQsIHQgPSBmdW5jdGlvbihlLCB0LCBuKSB7cmV0dXJuIGwuY2FsbChTKGUpLCBuKX0pKSwgdCkpIGZvcig7IHMgPCB1OyBzKyspIHQoZVtzXSwgbiwgYSA/IHIgOiByLmNhbGwoZVtzXSwgcywgdChlW3NdLCBuKSkpOw0KCQkJcmV0dXJuIGkgPyBlIDogbCA/IHQuY2FsbChlKSA6IHUgPyB0KGVbMF0sIG4pIDogbw0KCQl9LCBfICA9IC9eLW1zLS8sIHogPSAvLShbYS16XSkvZzsNCg0KCQlmdW5jdGlvbiBVKGUsIHQpIHtyZXR1cm4gdC50b1VwcGVyQ2FzZSgpfQ0KDQoJCWZ1bmN0aW9uIFgoZSkge3JldHVybiBlLnJlcGxhY2UoXywgIm1zLSIpLnJlcGxhY2UoeiwgVSl9DQoNCgkJdmFyIFYgPSBmdW5jdGlvbihlKSB7cmV0dXJuIDEgPT09IGUubm9kZVR5cGUgfHwgOSA9PT0gZS5ub2RlVHlwZSB8fCAhK2Uubm9kZVR5cGV9Ow0KDQoJCWZ1bmN0aW9uIEcoKSB7dGhpcy5leHBhbmRvID0gUy5leHBhbmRvICsgRy51aWQrK30NCg0KCQlHLnVpZCA9IDEsIEcucHJvdG90eXBlID0gew0KCQkJY2FjaGU6IGZ1bmN0aW9uKGUpIHsNCgkJCQl2YXIgdCA9IGVbdGhpcy5leHBhbmRvXTsNCgkJCQlyZXR1cm4gdCB8fCAodCA9IHt9LCBWKGUpICYmIChlLm5vZGVUeXBlID8gZVt0aGlzLmV4cGFuZG9dID0gdCA6IE9iamVjdC5kZWZpbmVQcm9wZXJ0eShlLCB0aGlzLmV4cGFuZG8sIHt2YWx1ZTogdCwgY29uZmlndXJhYmxlOiAhMH0pKSksIHQNCgkJCX0sDQoJCQlzZXQ6IGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQl2YXIgciwgaSA9IHRoaXMuY2FjaGUoZSk7DQoJCQkJaWYoInN0cmluZyIgPT0gdHlwZW9mIHQpIGlbWCh0KV0gPSBuOyBlbHNlIGZvcihyIGluIHQpIGlbWChyKV0gPSB0W3JdOw0KCQkJCXJldHVybiBpDQoJCQl9LA0KCQkJZ2V0OiBmdW5jdGlvbihlLCB0KSB7cmV0dXJuIHZvaWQgMCA9PT0gdCA/IHRoaXMuY2FjaGUoZSkgOiBlW3RoaXMuZXhwYW5kb10gJiYgZVt0aGlzLmV4cGFuZG9dW1godCldfSwNCgkJCWFjY2VzczogZnVuY3Rpb24oZSwgdCwgbikge3JldHVybiB2b2lkIDAgPT09IHQgfHwgdCAmJiAic3RyaW5nIiA9PSB0eXBlb2YgdCAmJiB2b2lkIDAgPT09IG4gPyB0aGlzLmdldChlLCB0KSA6ICh0aGlzLnNldChlLCB0LCBuKSwgdm9pZCAwICE9PSBuID8gbiA6IHQpfSwNCgkJCXJlbW92ZTogZnVuY3Rpb24oZSwgdCkgew0KCQkJCXZhciBuLCByID0gZVt0aGlzLmV4cGFuZG9dOw0KCQkJCWlmKHZvaWQgMCAhPT0gcikgew0KCQkJCQlpZih2b2lkIDAgIT09IHQpIHsNCgkJCQkJCW4gPSAodCA9IEFycmF5LmlzQXJyYXkodCkgPyB0Lm1hcChYKSA6ICh0ID0gWCh0KSkgaW4gciA/IFt0XSA6IHQubWF0Y2goUCkgfHwgW10pLmxlbmd0aDsNCgkJCQkJCXdoaWxlKG4tLSkgZGVsZXRlIHJbdFtuXV0NCgkJCQkJfQ0KCQkJCQkodm9pZCAwID09PSB0IHx8IFMuaXNFbXB0eU9iamVjdChyKSkgJiYgKGUubm9kZVR5cGUgPyBlW3RoaXMuZXhwYW5kb10gPSB2b2lkIDAgOiBkZWxldGUgZVt0aGlzLmV4cGFuZG9dKQ0KCQkJCX0NCgkJCX0sDQoJCQloYXNEYXRhOiBmdW5jdGlvbihlKSB7DQoJCQkJdmFyIHQgPSBlW3RoaXMuZXhwYW5kb107DQoJCQkJcmV0dXJuIHZvaWQgMCAhPT0gdCAmJiAhUy5pc0VtcHR5T2JqZWN0KHQpDQoJCQl9DQoJCX07DQoJCXZhciBZID0gbmV3IEcsIFEgPSBuZXcgRywgSiA9IC9eKD86XHtbXHdcV10qXH18XFtbXHdcV10qXF0pJC8sIEsgPSAvW0EtWl0vZzsNCg0KCQlmdW5jdGlvbiBaKGUsIHQsIG4pIHsNCgkJCXZhciByLCBpOw0KCQkJaWYodm9pZCAwID09PSBuICYmIDEgPT09IGUubm9kZVR5cGUpIGlmKHIgPSAiZGF0YS0iICsgdC5yZXBsYWNlKEssICItJCYiKS50b0xvd2VyQ2FzZSgpLCAic3RyaW5nIiA9PSB0eXBlb2YgKG4gPSBlLmdldEF0dHJpYnV0ZShyKSkpIHsNCgkJCQl0cnkge24gPSAidHJ1ZSIgPT09IChpID0gbikgfHwgImZhbHNlIiAhPT0gaSAmJiAoIm51bGwiID09PSBpID8gbnVsbCA6IGkgPT09ICtpICsgIiIgPyAraSA6IEoudGVzdChpKSA/IEpTT04ucGFyc2UoaSkgOiBpKX0gY2F0Y2goZSkge30NCgkJCQlRLnNldChlLCB0LCBuKQ0KCQkJfSBlbHNlIG4gPSB2b2lkIDA7DQoJCQlyZXR1cm4gbg0KCQl9DQoNCgkJUy5leHRlbmQoew0KCQkJaGFzRGF0YTogZnVuY3Rpb24oZSkge3JldHVybiBRLmhhc0RhdGEoZSkgfHwgWS5oYXNEYXRhKGUpfSwNCgkJCWRhdGE6IGZ1bmN0aW9uKGUsIHQsIG4pIHtyZXR1cm4gUS5hY2Nlc3MoZSwgdCwgbil9LA0KCQkJcmVtb3ZlRGF0YTogZnVuY3Rpb24oZSwgdCkge1EucmVtb3ZlKGUsIHQpfSwNCgkJCV9kYXRhOiBmdW5jdGlvbihlLCB0LCBuKSB7cmV0dXJuIFkuYWNjZXNzKGUsIHQsIG4pfSwNCgkJCV9yZW1vdmVEYXRhOiBmdW5jdGlvbihlLCB0KSB7WS5yZW1vdmUoZSwgdCl9DQoJCX0pLCBTLmZuLmV4dGVuZCh7DQoJCQlkYXRhOiBmdW5jdGlvbihuLCBlKSB7DQoJCQkJdmFyIHQsIHIsIGksIG8gPSB0aGlzWzBdLCBhID0gbyAmJiBvLmF0dHJpYnV0ZXM7DQoJCQkJaWYodm9pZCAwID09PSBuKSB7DQoJCQkJCWlmKHRoaXMubGVuZ3RoICYmIChpID0gUS5nZXQobyksIDEgPT09IG8ubm9kZVR5cGUgJiYgIVkuZ2V0KG8sICJoYXNEYXRhQXR0cnMiKSkpIHsNCgkJCQkJCXQgPSBhLmxlbmd0aDsNCgkJCQkJCXdoaWxlKHQtLSkgYVt0XSAmJiAwID09PSAociA9IGFbdF0ubmFtZSkuaW5kZXhPZigiZGF0YS0iKSAmJiAociA9IFgoci5zbGljZSg1KSksIFoobywgciwgaVtyXSkpOw0KCQkJCQkJWS5zZXQobywgImhhc0RhdGFBdHRycyIsICEwKQ0KCQkJCQl9DQoJCQkJCXJldHVybiBpDQoJCQkJfQ0KCQkJCXJldHVybiAib2JqZWN0IiA9PSB0eXBlb2YgbiA/IHRoaXMuZWFjaChmdW5jdGlvbigpIHtRLnNldCh0aGlzLCBuKX0pIDogJCh0aGlzLCBmdW5jdGlvbihlKSB7DQoJCQkJCXZhciB0Ow0KCQkJCQlpZihvICYmIHZvaWQgMCA9PT0gZSkgcmV0dXJuIHZvaWQgMCAhPT0gKHQgPSBRLmdldChvLCBuKSkgPyB0IDogdm9pZCAwICE9PSAodCA9IFoobywgbikpID8gdCA6IHZvaWQgMDsNCgkJCQkJdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1Euc2V0KHRoaXMsIG4sIGUpfSkNCgkJCQl9LCBudWxsLCBlLCAxIDwgYXJndW1lbnRzLmxlbmd0aCwgbnVsbCwgITApDQoJCQl9LCByZW1vdmVEYXRhOiBmdW5jdGlvbihlKSB7cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpIHtRLnJlbW92ZSh0aGlzLCBlKX0pfQ0KCQl9KSwgUy5leHRlbmQoew0KCQkJcXVldWU6IGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQl2YXIgcjsNCgkJCQlpZihlKSByZXR1cm4gdCA9ICh0IHx8ICJmeCIpICsgInF1ZXVlIiwgciA9IFkuZ2V0KGUsIHQpLCBuICYmICghciB8fCBBcnJheS5pc0FycmF5KG4pID8gciA9IFkuYWNjZXNzKGUsIHQsIFMubWFrZUFycmF5KG4pKSA6IHIucHVzaChuKSksIHIgfHwgW10NCgkJCX0sIGRlcXVldWU6IGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQl0ID0gdCB8fCAiZngiOw0KCQkJCXZhciBuID0gUy5xdWV1ZShlLCB0KSwgciA9IG4ubGVuZ3RoLCBpID0gbi5zaGlmdCgpLCBvID0gUy5fcXVldWVIb29rcyhlLCB0KTsNCgkJCQkiaW5wcm9ncmVzcyIgPT09IGkgJiYgKGkgPSBuLnNoaWZ0KCksIHItLSksIGkgJiYgKCJmeCIgPT09IHQgJiYgbi51bnNoaWZ0KCJpbnByb2dyZXNzIiksIGRlbGV0ZSBvLnN0b3AsIGkuY2FsbChlLCBmdW5jdGlvbigpIHtTLmRlcXVldWUoZSwgdCl9LCBvKSksICFyICYmIG8gJiYgby5lbXB0eS5maXJlKCkNCgkJCX0sIF9xdWV1ZUhvb2tzOiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJdmFyIG4gPSB0ICsgInF1ZXVlSG9va3MiOw0KCQkJCXJldHVybiBZLmdldChlLCBuKSB8fCBZLmFjY2VzcyhlLCBuLCB7ZW1wdHk6IFMuQ2FsbGJhY2tzKCJvbmNlIG1lbW9yeSIpLmFkZChmdW5jdGlvbigpIHtZLnJlbW92ZShlLCBbdCArICJxdWV1ZSIsIG5dKX0pfSkNCgkJCX0NCgkJfSksIFMuZm4uZXh0ZW5kKHsNCgkJCXF1ZXVlOiBmdW5jdGlvbih0LCBuKSB7DQoJCQkJdmFyIGUgPSAyOw0KCQkJCXJldHVybiAic3RyaW5nIiAhPSB0eXBlb2YgdCAmJiAobiA9IHQsIHQgPSAiZngiLCBlLS0pLCBhcmd1bWVudHMubGVuZ3RoIDwgZSA/IFMucXVldWUodGhpc1swXSwgdCkgOiB2b2lkIDAgPT09IG4gPyB0aGlzIDogdGhpcy5lYWNoKGZ1bmN0aW9uKCkgew0KCQkJCQl2YXIgZSA9IFMucXVldWUodGhpcywgdCwgbik7DQoJCQkJCVMuX3F1ZXVlSG9va3ModGhpcywgdCksICJmeCIgPT09IHQgJiYgImlucHJvZ3Jlc3MiICE9PSBlWzBdICYmIFMuZGVxdWV1ZSh0aGlzLCB0KQ0KCQkJCX0pDQoJCQl9LCBkZXF1ZXVlOiBmdW5jdGlvbihlKSB7cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpIHtTLmRlcXVldWUodGhpcywgZSl9KX0sIGNsZWFyUXVldWU6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gdGhpcy5xdWV1ZShlIHx8ICJmeCIsIFtdKX0sIHByb21pc2U6IGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQl2YXIgbiwgciA9IDEsIGkgPSBTLkRlZmVycmVkKCksIG8gPSB0aGlzLCBhID0gdGhpcy5sZW5ndGgsIHMgPSBmdW5jdGlvbigpIHstLXIgfHwgaS5yZXNvbHZlV2l0aChvLCBbb10pfTsNCgkJCQkic3RyaW5nIiAhPSB0eXBlb2YgZSAmJiAodCA9IGUsIGUgPSB2b2lkIDApLCBlID0gZSB8fCAiZngiOw0KCQkJCXdoaWxlKGEtLSkgKG4gPSBZLmdldChvW2FdLCBlICsgInF1ZXVlSG9va3MiKSkgJiYgbi5lbXB0eSAmJiAocisrLCBuLmVtcHR5LmFkZChzKSk7DQoJCQkJcmV0dXJuIHMoKSwgaS5wcm9taXNlKHQpDQoJCQl9DQoJCX0pOw0KCQl2YXIgZWUgPSAvWystXT8oPzpcZCpcLnwpXGQrKD86W2VFXVsrLV0/XGQrfCkvLnNvdXJjZSwgdGUgPSBuZXcgUmVnRXhwKCJeKD86KFsrLV0pPXwpKCIgKyBlZSArICIpKFthLXolXSopJCIsICJpIiksIG5lID0gWyJUb3AiLCAiUmlnaHQiLCAiQm90dG9tIiwgIkxlZnQiXSwgcmUgPSBFLmRvY3VtZW50RWxlbWVudCwgaWUgPSBmdW5jdGlvbihlKSB7cmV0dXJuIFMuY29udGFpbnMoZS5vd25lckRvY3VtZW50LCBlKX0sIG9lID0ge2NvbXBvc2VkOiAhMH07DQoJCXJlLmdldFJvb3ROb2RlICYmIChpZSA9IGZ1bmN0aW9uKGUpIHtyZXR1cm4gUy5jb250YWlucyhlLm93bmVyRG9jdW1lbnQsIGUpIHx8IGUuZ2V0Um9vdE5vZGUob2UpID09PSBlLm93bmVyRG9jdW1lbnR9KTsNCgkJdmFyIGFlID0gZnVuY3Rpb24oZSwgdCkge3JldHVybiAibm9uZSIgPT09IChlID0gdCB8fCBlKS5zdHlsZS5kaXNwbGF5IHx8ICIiID09PSBlLnN0eWxlLmRpc3BsYXkgJiYgaWUoZSkgJiYgIm5vbmUiID09PSBTLmNzcyhlLCAiZGlzcGxheSIpfTsNCg0KCQlmdW5jdGlvbiBzZShlLCB0LCBuLCByKSB7DQoJCQl2YXIgaSwgbywgYSA9IDIwLCBzID0gciA/IGZ1bmN0aW9uKCkge3JldHVybiByLmN1cigpfSA6IGZ1bmN0aW9uKCkge3JldHVybiBTLmNzcyhlLCB0LCAiIil9LCB1ID0gcygpLCBsID0gbiAmJiBuWzNdIHx8IChTLmNzc051bWJlclt0XSA/ICIiIDogInB4IiksIGMgPSBlLm5vZGVUeXBlICYmIChTLmNzc051bWJlclt0XSB8fCAicHgiICE9PSBsICYmICt1KSAmJiB0ZS5leGVjKFMuY3NzKGUsIHQpKTsNCgkJCWlmKGMgJiYgY1szXSAhPT0gbCkgew0KCQkJCXUgLz0gMiwgbCA9IGwgfHwgY1szXSwgYyA9ICt1IHx8IDE7DQoJCQkJd2hpbGUoYS0tKSBTLnN0eWxlKGUsIHQsIGMgKyBsKSwgKDEgLSBvKSAqICgxIC0gKG8gPSBzKCkgLyB1IHx8IC41KSkgPD0gMCAmJiAoYSA9IDApLCBjIC89IG87DQoJCQkJYyAqPSAyLCBTLnN0eWxlKGUsIHQsIGMgKyBsKSwgbiA9IG4gfHwgW10NCgkJCX0NCgkJCXJldHVybiBuICYmIChjID0gK2MgfHwgK3UgfHwgMCwgaSA9IG5bMV0gPyBjICsgKG5bMV0gKyAxKSAqIG5bMl0gOiArblsyXSwgciAmJiAoci51bml0ID0gbCwgci5zdGFydCA9IGMsIHIuZW5kID0gaSkpLCBpDQoJCX0NCg0KCQl2YXIgdWUgPSB7fTsNCg0KCQlmdW5jdGlvbiBsZShlLCB0KSB7DQoJCQlmb3IodmFyIG4sIHIsIGksIG8sIGEsIHMsIHUsIGwgPSBbXSwgYyA9IDAsIGYgPSBlLmxlbmd0aDsgYyA8IGY7IGMrKykgKHIgPSBlW2NdKS5zdHlsZSAmJiAobiA9IHIuc3R5bGUuZGlzcGxheSwgdCA/ICgibm9uZSIgPT09IG4gJiYgKGxbY10gPSBZLmdldChyLCAiZGlzcGxheSIpIHx8IG51bGwsIGxbY10gfHwgKHIuc3R5bGUuZGlzcGxheSA9ICIiKSksICIiID09PSByLnN0eWxlLmRpc3BsYXkgJiYgYWUocikgJiYgKGxbY10gPSAodSA9IGEgPSBvID0gdm9pZCAwLCBhID0gKGkgPSByKS5vd25lckRvY3VtZW50LCBzID0gaS5ub2RlTmFtZSwgKHUgPSB1ZVtzXSkgfHwgKG8gPSBhLmJvZHkuYXBwZW5kQ2hpbGQoYS5jcmVhdGVFbGVtZW50KHMpKSwgdSA9IFMuY3NzKG8sICJkaXNwbGF5IiksIG8ucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChvKSwgIm5vbmUiID09PSB1ICYmICh1ID0gImJsb2NrIiksIHVlW3NdID0gdSkpKSkgOiAibm9uZSIgIT09IG4gJiYgKGxbY10gPSAibm9uZSIsIFkuc2V0KHIsICJkaXNwbGF5IiwgbikpKTsNCgkJCWZvcihjID0gMDsgYyA8IGY7IGMrKykgbnVsbCAhPSBsW2NdICYmIChlW2NdLnN0eWxlLmRpc3BsYXkgPSBsW2NdKTsNCgkJCXJldHVybiBlDQoJCX0NCg0KCQlTLmZuLmV4dGVuZCh7c2hvdzogZnVuY3Rpb24oKSB7cmV0dXJuIGxlKHRoaXMsICEwKX0sIGhpZGU6IGZ1bmN0aW9uKCkge3JldHVybiBsZSh0aGlzKX0sIHRvZ2dsZTogZnVuY3Rpb24oZSkge3JldHVybiAiYm9vbGVhbiIgPT0gdHlwZW9mIGUgPyBlID8gdGhpcy5zaG93KCkgOiB0aGlzLmhpZGUoKSA6IHRoaXMuZWFjaChmdW5jdGlvbigpIHthZSh0aGlzKSA/IFModGhpcykuc2hvdygpIDogUyh0aGlzKS5oaWRlKCl9KX19KTsNCgkJdmFyIGNlLCBmZSwgcGUgPSAvXig/OmNoZWNrYm94fHJhZGlvKSQvaSwgZGUgPSAvPChbYS16XVteXC9cMD5ceDIwXHRcclxuXGZdKikvaSwgaGUgPSAvXiR8Xm1vZHVsZSR8XC8oPzpqYXZhfGVjbWEpc2NyaXB0L2k7DQoJCWNlID0gRS5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCkuYXBwZW5kQ2hpbGQoRS5jcmVhdGVFbGVtZW50KCJkaXYiKSksIChmZSA9IEUuY3JlYXRlRWxlbWVudCgiaW5wdXQiKSkuc2V0QXR0cmlidXRlKCJ0eXBlIiwgInJhZGlvIiksIGZlLnNldEF0dHJpYnV0ZSgiY2hlY2tlZCIsICJjaGVja2VkIiksIGZlLnNldEF0dHJpYnV0ZSgibmFtZSIsICJ0IiksIGNlLmFwcGVuZENoaWxkKGZlKSwgeS5jaGVja0Nsb25lID0gY2UuY2xvbmVOb2RlKCEwKS5jbG9uZU5vZGUoITApLmxhc3RDaGlsZC5jaGVja2VkLCBjZS5pbm5lckhUTUwgPSAiPHRleHRhcmVhPng8L3RleHRhcmVhPiIsIHkubm9DbG9uZUNoZWNrZWQgPSAhIWNlLmNsb25lTm9kZSghMCkubGFzdENoaWxkLmRlZmF1bHRWYWx1ZSwgY2UuaW5uZXJIVE1MID0gIjxvcHRpb24+PC9vcHRpb24+IiwgeS5vcHRpb24gPSAhIWNlLmxhc3RDaGlsZDsNCgkJdmFyIGdlID0ge3RoZWFkOiBbMSwgIjx0YWJsZT4iLCAiPC90YWJsZT4iXSwgY29sOiBbMiwgIjx0YWJsZT48Y29sZ3JvdXA+IiwgIjwvY29sZ3JvdXA+PC90YWJsZT4iXSwgdHI6IFsyLCAiPHRhYmxlPjx0Ym9keT4iLCAiPC90Ym9keT48L3RhYmxlPiJdLCB0ZDogWzMsICI8dGFibGU+PHRib2R5Pjx0cj4iLCAiPC90cj48L3Rib2R5PjwvdGFibGU+Il0sIF9kZWZhdWx0OiBbMCwgIiIsICIiXX07DQoNCgkJZnVuY3Rpb24gdmUoZSwgdCkgew0KCQkJdmFyIG47DQoJCQlyZXR1cm4gbiA9ICJ1bmRlZmluZWQiICE9IHR5cGVvZiBlLmdldEVsZW1lbnRzQnlUYWdOYW1lID8gZS5nZXRFbGVtZW50c0J5VGFnTmFtZSh0IHx8ICIqIikgOiAidW5kZWZpbmVkIiAhPSB0eXBlb2YgZS5xdWVyeVNlbGVjdG9yQWxsID8gZS5xdWVyeVNlbGVjdG9yQWxsKHQgfHwgIioiKSA6IFtdLCB2b2lkIDAgPT09IHQgfHwgdCAmJiBBKGUsIHQpID8gUy5tZXJnZShbZV0sIG4pIDogbg0KCQl9DQoNCgkJZnVuY3Rpb24geWUoZSwgdCkge2Zvcih2YXIgbiA9IDAsIHIgPSBlLmxlbmd0aDsgbiA8IHI7IG4rKykgWS5zZXQoZVtuXSwgImdsb2JhbEV2YWwiLCAhdCB8fCBZLmdldCh0W25dLCAiZ2xvYmFsRXZhbCIpKX0NCg0KCQlnZS50Ym9keSA9IGdlLnRmb290ID0gZ2UuY29sZ3JvdXAgPSBnZS5jYXB0aW9uID0gZ2UudGhlYWQsIGdlLnRoID0gZ2UudGQsIHkub3B0aW9uIHx8IChnZS5vcHRncm91cCA9IGdlLm9wdGlvbiA9IFsxLCAiPHNlbGVjdCBtdWx0aXBsZT0nbXVsdGlwbGUnPiIsICI8L3NlbGVjdD4iXSk7DQoJCXZhciBtZSA9IC88fCYjP1x3KzsvOw0KDQoJCWZ1bmN0aW9uIHhlKGUsIHQsIG4sIHIsIGkpIHsNCgkJCWZvcih2YXIgbywgYSwgcywgdSwgbCwgYywgZiA9IHQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpLCBwID0gW10sIGQgPSAwLCBoID0gZS5sZW5ndGg7IGQgPCBoOyBkKyspIGlmKChvID0gZVtkXSkgfHwgMCA9PT0gbykgaWYoIm9iamVjdCIgPT09IHcobykpIFMubWVyZ2UocCwgby5ub2RlVHlwZSA/IFtvXSA6IG8pOyBlbHNlIGlmKG1lLnRlc3QobykpIHsNCgkJCQlhID0gYSB8fCBmLmFwcGVuZENoaWxkKHQuY3JlYXRlRWxlbWVudCgiZGl2IikpLCBzID0gKGRlLmV4ZWMobykgfHwgWyIiLCAiIl0pWzFdLnRvTG93ZXJDYXNlKCksIHUgPSBnZVtzXSB8fCBnZS5fZGVmYXVsdCwgYS5pbm5lckhUTUwgPSB1WzFdICsgUy5odG1sUHJlZmlsdGVyKG8pICsgdVsyXSwgYyA9IHVbMF07DQoJCQkJd2hpbGUoYy0tKSBhID0gYS5sYXN0Q2hpbGQ7DQoJCQkJUy5tZXJnZShwLCBhLmNoaWxkTm9kZXMpLCAoYSA9IGYuZmlyc3RDaGlsZCkudGV4dENvbnRlbnQgPSAiIg0KCQkJfSBlbHNlIHAucHVzaCh0LmNyZWF0ZVRleHROb2RlKG8pKTsNCgkJCWYudGV4dENvbnRlbnQgPSAiIiwgZCA9IDA7DQoJCQl3aGlsZShvID0gcFtkKytdKSBpZihyICYmIC0xIDwgUy5pbkFycmF5KG8sIHIpKSBpICYmIGkucHVzaChvKTsgZWxzZSBpZihsID0gaWUobyksIGEgPSB2ZShmLmFwcGVuZENoaWxkKG8pLCAic2NyaXB0IiksIGwgJiYgeWUoYSksIG4pIHsNCgkJCQljID0gMDsNCgkJCQl3aGlsZShvID0gYVtjKytdKSBoZS50ZXN0KG8udHlwZSB8fCAiIikgJiYgbi5wdXNoKG8pDQoJCQl9DQoJCQlyZXR1cm4gZg0KCQl9DQoNCgkJdmFyIGJlID0gL14oW14uXSopKD86XC4oLispfCkvOw0KDQoJCWZ1bmN0aW9uIHdlKCkge3JldHVybiAhMH0NCg0KCQlmdW5jdGlvbiBUZSgpIHtyZXR1cm4gITF9DQoNCgkJZnVuY3Rpb24gQ2UoZSwgdCkge3JldHVybiBlID09PSBmdW5jdGlvbigpIHt0cnkge3JldHVybiBFLmFjdGl2ZUVsZW1lbnR9IGNhdGNoKGUpIHt9fSgpID09ICgiZm9jdXMiID09PSB0KX0NCg0KCQlmdW5jdGlvbiBFZShlLCB0LCBuLCByLCBpLCBvKSB7DQoJCQl2YXIgYSwgczsNCgkJCWlmKCJvYmplY3QiID09IHR5cGVvZiB0KSB7DQoJCQkJZm9yKHMgaW4gInN0cmluZyIgIT0gdHlwZW9mIG4gJiYgKHIgPSByIHx8IG4sIG4gPSB2b2lkIDApLCB0KSBFZShlLCBzLCBuLCByLCB0W3NdLCBvKTsNCgkJCQlyZXR1cm4gZQ0KCQkJfQ0KCQkJaWYobnVsbCA9PSByICYmIG51bGwgPT0gaSA/IChpID0gbiwgciA9IG4gPSB2b2lkIDApIDogbnVsbCA9PSBpICYmICgic3RyaW5nIiA9PSB0eXBlb2YgbiA/IChpID0gciwgciA9IHZvaWQgMCkgOiAoaSA9IHIsIHIgPSBuLCBuID0gdm9pZCAwKSksICExID09PSBpKSBpID0gVGU7IGVsc2UgaWYoIWkpIHJldHVybiBlOw0KCQkJcmV0dXJuIDEgPT09IG8gJiYgKGEgPSBpLCAoaSA9IGZ1bmN0aW9uKGUpIHtyZXR1cm4gUygpLm9mZihlKSwgYS5hcHBseSh0aGlzLCBhcmd1bWVudHMpfSkuZ3VpZCA9IGEuZ3VpZCB8fCAoYS5ndWlkID0gUy5ndWlkKyspKSwgZS5lYWNoKGZ1bmN0aW9uKCkge1MuZXZlbnQuYWRkKHRoaXMsIHQsIGksIHIsIG4pfSkNCgkJfQ0KDQoJCWZ1bmN0aW9uIFNlKGUsIGksIG8pIHsNCgkJCW8gPyAoWS5zZXQoZSwgaSwgITEpLCBTLmV2ZW50LmFkZChlLCBpLCB7DQoJCQkJbmFtZXNwYWNlOiAhMSwgaGFuZGxlcjogZnVuY3Rpb24oZSkgew0KCQkJCQl2YXIgdCwgbiwgciA9IFkuZ2V0KHRoaXMsIGkpOw0KCQkJCQlpZigxICYgZS5pc1RyaWdnZXIgJiYgdGhpc1tpXSkge2lmKHIubGVuZ3RoKSAoUy5ldmVudC5zcGVjaWFsW2ldIHx8IHt9KS5kZWxlZ2F0ZVR5cGUgJiYgZS5zdG9wUHJvcGFnYXRpb24oKTsgZWxzZSBpZihyID0gcy5jYWxsKGFyZ3VtZW50cyksIFkuc2V0KHRoaXMsIGksIHIpLCB0ID0gbyh0aGlzLCBpKSwgdGhpc1tpXSgpLCByICE9PSAobiA9IFkuZ2V0KHRoaXMsIGkpKSB8fCB0ID8gWS5zZXQodGhpcywgaSwgITEpIDogbiA9IHt9LCByICE9PSBuKSByZXR1cm4gZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKSwgZS5wcmV2ZW50RGVmYXVsdCgpLCBuICYmIG4udmFsdWV9IGVsc2Ugci5sZW5ndGggJiYgKFkuc2V0KHRoaXMsIGksIHt2YWx1ZTogUy5ldmVudC50cmlnZ2VyKFMuZXh0ZW5kKHJbMF0sIFMuRXZlbnQucHJvdG90eXBlKSwgci5zbGljZSgxKSwgdGhpcyl9KSwgZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKSkNCgkJCQl9DQoJCQl9KSkgOiB2b2lkIDAgPT09IFkuZ2V0KGUsIGkpICYmIFMuZXZlbnQuYWRkKGUsIGksIHdlKQ0KCQl9DQoNCgkJUy5ldmVudCA9IHsNCgkJCWdsb2JhbDoge30sDQoJCQlhZGQ6IGZ1bmN0aW9uKHQsIGUsIG4sIHIsIGkpIHsNCgkJCQl2YXIgbywgYSwgcywgdSwgbCwgYywgZiwgcCwgZCwgaCwgZywgdiA9IFkuZ2V0KHQpOw0KCQkJCWlmKFYodCkpIHsNCgkJCQkJbi5oYW5kbGVyICYmIChuID0gKG8gPSBuKS5oYW5kbGVyLCBpID0gby5zZWxlY3RvciksIGkgJiYgUy5maW5kLm1hdGNoZXNTZWxlY3RvcihyZSwgaSksIG4uZ3VpZCB8fCAobi5ndWlkID0gUy5ndWlkKyspLCAodSA9IHYuZXZlbnRzKSB8fCAodSA9IHYuZXZlbnRzID0gT2JqZWN0LmNyZWF0ZShudWxsKSksIChhID0gdi5oYW5kbGUpIHx8IChhID0gdi5oYW5kbGUgPSBmdW5jdGlvbihlKSB7cmV0dXJuICJ1bmRlZmluZWQiICE9IHR5cGVvZiBTICYmIFMuZXZlbnQudHJpZ2dlcmVkICE9PSBlLnR5cGUgPyBTLmV2ZW50LmRpc3BhdGNoLmFwcGx5KHQsIGFyZ3VtZW50cykgOiB2b2lkIDB9KSwgbCA9IChlID0gKGUgfHwgIiIpLm1hdGNoKFApIHx8IFsiIl0pLmxlbmd0aDsNCgkJCQkJd2hpbGUobC0tKSBkID0gZyA9IChzID0gYmUuZXhlYyhlW2xdKSB8fCBbXSlbMV0sIGggPSAoc1syXSB8fCAiIikuc3BsaXQoIi4iKS5zb3J0KCksIGQgJiYgKGYgPSBTLmV2ZW50LnNwZWNpYWxbZF0gfHwge30sIGQgPSAoaSA/IGYuZGVsZWdhdGVUeXBlIDogZi5iaW5kVHlwZSkgfHwgZCwgZiA9IFMuZXZlbnQuc3BlY2lhbFtkXSB8fCB7fSwgYyA9IFMuZXh0ZW5kKHsNCgkJCQkJCXR5cGU6IGQsDQoJCQkJCQlvcmlnVHlwZTogZywNCgkJCQkJCWRhdGE6IHIsDQoJCQkJCQloYW5kbGVyOiBuLA0KCQkJCQkJZ3VpZDogbi5ndWlkLA0KCQkJCQkJc2VsZWN0b3I6IGksDQoJCQkJCQluZWVkc0NvbnRleHQ6IGkgJiYgUy5leHByLm1hdGNoLm5lZWRzQ29udGV4dC50ZXN0KGkpLA0KCQkJCQkJbmFtZXNwYWNlOiBoLmpvaW4oIi4iKQ0KCQkJCQl9LCBvKSwgKHAgPSB1W2RdKSB8fCAoKHAgPSB1W2RdID0gW10pLmRlbGVnYXRlQ291bnQgPSAwLCBmLnNldHVwICYmICExICE9PSBmLnNldHVwLmNhbGwodCwgciwgaCwgYSkgfHwgdC5hZGRFdmVudExpc3RlbmVyICYmIHQuYWRkRXZlbnRMaXN0ZW5lcihkLCBhKSksIGYuYWRkICYmIChmLmFkZC5jYWxsKHQsIGMpLCBjLmhhbmRsZXIuZ3VpZCB8fCAoYy5oYW5kbGVyLmd1aWQgPSBuLmd1aWQpKSwgaSA/IHAuc3BsaWNlKHAuZGVsZWdhdGVDb3VudCsrLCAwLCBjKSA6IHAucHVzaChjKSwgUy5ldmVudC5nbG9iYWxbZF0gPSAhMCkNCgkJCQl9DQoJCQl9LA0KCQkJcmVtb3ZlOiBmdW5jdGlvbihlLCB0LCBuLCByLCBpKSB7DQoJCQkJdmFyIG8sIGEsIHMsIHUsIGwsIGMsIGYsIHAsIGQsIGgsIGcsIHYgPSBZLmhhc0RhdGEoZSkgJiYgWS5nZXQoZSk7DQoJCQkJaWYodiAmJiAodSA9IHYuZXZlbnRzKSkgew0KCQkJCQlsID0gKHQgPSAodCB8fCAiIikubWF0Y2goUCkgfHwgWyIiXSkubGVuZ3RoOw0KCQkJCQl3aGlsZShsLS0pIGlmKGQgPSBnID0gKHMgPSBiZS5leGVjKHRbbF0pIHx8IFtdKVsxXSwgaCA9IChzWzJdIHx8ICIiKS5zcGxpdCgiLiIpLnNvcnQoKSwgZCkgew0KCQkJCQkJZiA9IFMuZXZlbnQuc3BlY2lhbFtkXSB8fCB7fSwgcCA9IHVbZCA9IChyID8gZi5kZWxlZ2F0ZVR5cGUgOiBmLmJpbmRUeXBlKSB8fCBkXSB8fCBbXSwgcyA9IHNbMl0gJiYgbmV3IFJlZ0V4cCgiKF58XFwuKSIgKyBoLmpvaW4oIlxcLig/Oi4qXFwufCkiKSArICIoXFwufCQpIiksIGEgPSBvID0gcC5sZW5ndGg7DQoJCQkJCQl3aGlsZShvLS0pIGMgPSBwW29dLCAhaSAmJiBnICE9PSBjLm9yaWdUeXBlIHx8IG4gJiYgbi5ndWlkICE9PSBjLmd1aWQgfHwgcyAmJiAhcy50ZXN0KGMubmFtZXNwYWNlKSB8fCByICYmIHIgIT09IGMuc2VsZWN0b3IgJiYgKCIqKiIgIT09IHIgfHwgIWMuc2VsZWN0b3IpIHx8IChwLnNwbGljZShvLCAxKSwgYy5zZWxlY3RvciAmJiBwLmRlbGVnYXRlQ291bnQtLSwgZi5yZW1vdmUgJiYgZi5yZW1vdmUuY2FsbChlLCBjKSk7DQoJCQkJCQlhICYmICFwLmxlbmd0aCAmJiAoZi50ZWFyZG93biAmJiAhMSAhPT0gZi50ZWFyZG93bi5jYWxsKGUsIGgsIHYuaGFuZGxlKSB8fCBTLnJlbW92ZUV2ZW50KGUsIGQsIHYuaGFuZGxlKSwgZGVsZXRlIHVbZF0pDQoJCQkJCX0gZWxzZSBmb3IoZCBpbiB1KSBTLmV2ZW50LnJlbW92ZShlLCBkICsgdFtsXSwgbiwgciwgITApOw0KCQkJCQlTLmlzRW1wdHlPYmplY3QodSkgJiYgWS5yZW1vdmUoZSwgImhhbmRsZSBldmVudHMiKQ0KCQkJCX0NCgkJCX0sDQoJCQlkaXNwYXRjaDogZnVuY3Rpb24oZSkgew0KCQkJCXZhciB0LCBuLCByLCBpLCBvLCBhLCBzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpLCB1ID0gUy5ldmVudC5maXgoZSksIGwgPSAoWS5nZXQodGhpcywgImV2ZW50cyIpIHx8IE9iamVjdC5jcmVhdGUobnVsbCkpW3UudHlwZV0gfHwgW10sIGMgPSBTLmV2ZW50LnNwZWNpYWxbdS50eXBlXSB8fCB7fTsNCgkJCQlmb3Ioc1swXSA9IHUsIHQgPSAxOyB0IDwgYXJndW1lbnRzLmxlbmd0aDsgdCsrKSBzW3RdID0gYXJndW1lbnRzW3RdOw0KCQkJCWlmKHUuZGVsZWdhdGVUYXJnZXQgPSB0aGlzLCAhYy5wcmVEaXNwYXRjaCB8fCAhMSAhPT0gYy5wcmVEaXNwYXRjaC5jYWxsKHRoaXMsIHUpKSB7DQoJCQkJCWEgPSBTLmV2ZW50LmhhbmRsZXJzLmNhbGwodGhpcywgdSwgbCksIHQgPSAwOw0KCQkJCQl3aGlsZSgoaSA9IGFbdCsrXSkgJiYgIXUuaXNQcm9wYWdhdGlvblN0b3BwZWQoKSkgew0KCQkJCQkJdS5jdXJyZW50VGFyZ2V0ID0gaS5lbGVtLCBuID0gMDsNCgkJCQkJCXdoaWxlKChvID0gaS5oYW5kbGVyc1tuKytdKSAmJiAhdS5pc0ltbWVkaWF0ZVByb3BhZ2F0aW9uU3RvcHBlZCgpKSB1LnJuYW1lc3BhY2UgJiYgITEgIT09IG8ubmFtZXNwYWNlICYmICF1LnJuYW1lc3BhY2UudGVzdChvLm5hbWVzcGFjZSkgfHwgKHUuaGFuZGxlT2JqID0gbywgdS5kYXRhID0gby5kYXRhLCB2b2lkIDAgIT09IChyID0gKChTLmV2ZW50LnNwZWNpYWxbby5vcmlnVHlwZV0gfHwge30pLmhhbmRsZSB8fCBvLmhhbmRsZXIpLmFwcGx5KGkuZWxlbSwgcykpICYmICExID09PSAodS5yZXN1bHQgPSByKSAmJiAodS5wcmV2ZW50RGVmYXVsdCgpLCB1LnN0b3BQcm9wYWdhdGlvbigpKSkNCgkJCQkJfQ0KCQkJCQlyZXR1cm4gYy5wb3N0RGlzcGF0Y2ggJiYgYy5wb3N0RGlzcGF0Y2guY2FsbCh0aGlzLCB1KSwgdS5yZXN1bHQNCgkJCQl9DQoJCQl9LA0KCQkJaGFuZGxlcnM6IGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQl2YXIgbiwgciwgaSwgbywgYSwgcyA9IFtdLCB1ID0gdC5kZWxlZ2F0ZUNvdW50LCBsID0gZS50YXJnZXQ7DQoJCQkJaWYodSAmJiBsLm5vZGVUeXBlICYmICEoImNsaWNrIiA9PT0gZS50eXBlICYmIDEgPD0gZS5idXR0b24pKSBmb3IoOyBsICE9PSB0aGlzOyBsID0gbC5wYXJlbnROb2RlIHx8IHRoaXMpIGlmKDEgPT09IGwubm9kZVR5cGUgJiYgKCJjbGljayIgIT09IGUudHlwZSB8fCAhMCAhPT0gbC5kaXNhYmxlZCkpIHsNCgkJCQkJZm9yKG8gPSBbXSwgYSA9IHt9LCBuID0gMDsgbiA8IHU7IG4rKykgdm9pZCAwID09PSBhW2kgPSAociA9IHRbbl0pLnNlbGVjdG9yICsgIiAiXSAmJiAoYVtpXSA9IHIubmVlZHNDb250ZXh0ID8gLTEgPCBTKGksIHRoaXMpLmluZGV4KGwpIDogUy5maW5kKGksIHRoaXMsIG51bGwsIFtsXSkubGVuZ3RoKSwgYVtpXSAmJiBvLnB1c2gocik7DQoJCQkJCW8ubGVuZ3RoICYmIHMucHVzaCh7ZWxlbTogbCwgaGFuZGxlcnM6IG99KQ0KCQkJCX0NCgkJCQlyZXR1cm4gbCA9IHRoaXMsIHUgPCB0Lmxlbmd0aCAmJiBzLnB1c2goe2VsZW06IGwsIGhhbmRsZXJzOiB0LnNsaWNlKHUpfSksIHMNCgkJCX0sDQoJCQlhZGRQcm9wOiBmdW5jdGlvbih0LCBlKSB7DQoJCQkJT2JqZWN0LmRlZmluZVByb3BlcnR5KFMuRXZlbnQucHJvdG90eXBlLCB0LCB7DQoJCQkJCWVudW1lcmFibGU6ICEwLA0KCQkJCQljb25maWd1cmFibGU6ICEwLA0KCQkJCQlnZXQ6IG0oZSkgPyBmdW5jdGlvbigpIHtpZih0aGlzLm9yaWdpbmFsRXZlbnQpIHJldHVybiBlKHRoaXMub3JpZ2luYWxFdmVudCl9IDogZnVuY3Rpb24oKSB7aWYodGhpcy5vcmlnaW5hbEV2ZW50KSByZXR1cm4gdGhpcy5vcmlnaW5hbEV2ZW50W3RdfSwNCgkJCQkJc2V0OiBmdW5jdGlvbihlKSB7T2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIHQsIHtlbnVtZXJhYmxlOiAhMCwgY29uZmlndXJhYmxlOiAhMCwgd3JpdGFibGU6ICEwLCB2YWx1ZTogZX0pfQ0KCQkJCX0pDQoJCQl9LA0KCQkJZml4OiBmdW5jdGlvbihlKSB7cmV0dXJuIGVbUy5leHBhbmRvXSA/IGUgOiBuZXcgUy5FdmVudChlKX0sDQoJCQlzcGVjaWFsOiB7DQoJCQkJbG9hZDoge25vQnViYmxlOiAhMH0sIGNsaWNrOiB7DQoJCQkJCXNldHVwOiBmdW5jdGlvbihlKSB7DQoJCQkJCQl2YXIgdCA9IHRoaXMgfHwgZTsNCgkJCQkJCXJldHVybiBwZS50ZXN0KHQudHlwZSkgJiYgdC5jbGljayAmJiBBKHQsICJpbnB1dCIpICYmIFNlKHQsICJjbGljayIsIHdlKSwgITENCgkJCQkJfSwgdHJpZ2dlcjogZnVuY3Rpb24oZSkgew0KCQkJCQkJdmFyIHQgPSB0aGlzIHx8IGU7DQoJCQkJCQlyZXR1cm4gcGUudGVzdCh0LnR5cGUpICYmIHQuY2xpY2sgJiYgQSh0LCAiaW5wdXQiKSAmJiBTZSh0LCAiY2xpY2siKSwgITANCgkJCQkJfSwgX2RlZmF1bHQ6IGZ1bmN0aW9uKGUpIHsNCgkJCQkJCXZhciB0ID0gZS50YXJnZXQ7DQoJCQkJCQlyZXR1cm4gcGUudGVzdCh0LnR5cGUpICYmIHQuY2xpY2sgJiYgQSh0LCAiaW5wdXQiKSAmJiBZLmdldCh0LCAiY2xpY2siKSB8fCBBKHQsICJhIikNCgkJCQkJfQ0KCQkJCX0sIGJlZm9yZXVubG9hZDoge3Bvc3REaXNwYXRjaDogZnVuY3Rpb24oZSkge3ZvaWQgMCAhPT0gZS5yZXN1bHQgJiYgZS5vcmlnaW5hbEV2ZW50ICYmIChlLm9yaWdpbmFsRXZlbnQucmV0dXJuVmFsdWUgPSBlLnJlc3VsdCl9fQ0KCQkJfQ0KCQl9LCBTLnJlbW92ZUV2ZW50ID0gZnVuY3Rpb24oZSwgdCwgbikge2UucmVtb3ZlRXZlbnRMaXN0ZW5lciAmJiBlLnJlbW92ZUV2ZW50TGlzdGVuZXIodCwgbil9LCBTLkV2ZW50ID0gZnVuY3Rpb24oZSwgdCkgew0KCQkJaWYoISh0aGlzIGluc3RhbmNlb2YgUy5FdmVudCkpIHJldHVybiBuZXcgUy5FdmVudChlLCB0KTsNCgkJCWUgJiYgZS50eXBlID8gKHRoaXMub3JpZ2luYWxFdmVudCA9IGUsIHRoaXMudHlwZSA9IGUudHlwZSwgdGhpcy5pc0RlZmF1bHRQcmV2ZW50ZWQgPSBlLmRlZmF1bHRQcmV2ZW50ZWQgfHwgdm9pZCAwID09PSBlLmRlZmF1bHRQcmV2ZW50ZWQgJiYgITEgPT09IGUucmV0dXJuVmFsdWUgPyB3ZSA6IFRlLCB0aGlzLnRhcmdldCA9IGUudGFyZ2V0ICYmIDMgPT09IGUudGFyZ2V0Lm5vZGVUeXBlID8gZS50YXJnZXQucGFyZW50Tm9kZSA6IGUudGFyZ2V0LCB0aGlzLmN1cnJlbnRUYXJnZXQgPSBlLmN1cnJlbnRUYXJnZXQsIHRoaXMucmVsYXRlZFRhcmdldCA9IGUucmVsYXRlZFRhcmdldCkgOiB0aGlzLnR5cGUgPSBlLCB0ICYmIFMuZXh0ZW5kKHRoaXMsIHQpLCB0aGlzLnRpbWVTdGFtcCA9IGUgJiYgZS50aW1lU3RhbXAgfHwgRGF0ZS5ub3coKSwgdGhpc1tTLmV4cGFuZG9dID0gITANCgkJfSwgUy5FdmVudC5wcm90b3R5cGUgPSB7DQoJCQljb25zdHJ1Y3RvcjogUy5FdmVudCwgaXNEZWZhdWx0UHJldmVudGVkOiBUZSwgaXNQcm9wYWdhdGlvblN0b3BwZWQ6IFRlLCBpc0ltbWVkaWF0ZVByb3BhZ2F0aW9uU3RvcHBlZDogVGUsIGlzU2ltdWxhdGVkOiAhMSwgcHJldmVudERlZmF1bHQ6IGZ1bmN0aW9uKCkgew0KCQkJCXZhciBlID0gdGhpcy5vcmlnaW5hbEV2ZW50Ow0KCQkJCXRoaXMuaXNEZWZhdWx0UHJldmVudGVkID0gd2UsIGUgJiYgIXRoaXMuaXNTaW11bGF0ZWQgJiYgZS5wcmV2ZW50RGVmYXVsdCgpDQoJCQl9LCBzdG9wUHJvcGFnYXRpb246IGZ1bmN0aW9uKCkgew0KCQkJCXZhciBlID0gdGhpcy5vcmlnaW5hbEV2ZW50Ow0KCQkJCXRoaXMuaXNQcm9wYWdhdGlvblN0b3BwZWQgPSB3ZSwgZSAmJiAhdGhpcy5pc1NpbXVsYXRlZCAmJiBlLnN0b3BQcm9wYWdhdGlvbigpDQoJCQl9LCBzdG9wSW1tZWRpYXRlUHJvcGFnYXRpb246IGZ1bmN0aW9uKCkgew0KCQkJCXZhciBlID0gdGhpcy5vcmlnaW5hbEV2ZW50Ow0KCQkJCXRoaXMuaXNJbW1lZGlhdGVQcm9wYWdhdGlvblN0b3BwZWQgPSB3ZSwgZSAmJiAhdGhpcy5pc1NpbXVsYXRlZCAmJiBlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpLCB0aGlzLnN0b3BQcm9wYWdhdGlvbigpDQoJCQl9DQoJCX0sIFMuZWFjaCh7DQoJCQlhbHRLZXk6ICEwLA0KCQkJYnViYmxlczogITAsDQoJCQljYW5jZWxhYmxlOiAhMCwNCgkJCWNoYW5nZWRUb3VjaGVzOiAhMCwNCgkJCWN0cmxLZXk6ICEwLA0KCQkJZGV0YWlsOiAhMCwNCgkJCWV2ZW50UGhhc2U6ICEwLA0KCQkJbWV0YUtleTogITAsDQoJCQlwYWdlWDogITAsDQoJCQlwYWdlWTogITAsDQoJCQlzaGlmdEtleTogITAsDQoJCQl2aWV3OiAhMCwNCgkJCSJjaGFyIjogITAsDQoJCQljb2RlOiAhMCwNCgkJCWNoYXJDb2RlOiAhMCwNCgkJCWtleTogITAsDQoJCQlrZXlDb2RlOiAhMCwNCgkJCWJ1dHRvbjogITAsDQoJCQlidXR0b25zOiAhMCwNCgkJCWNsaWVudFg6ICEwLA0KCQkJY2xpZW50WTogITAsDQoJCQlvZmZzZXRYOiAhMCwNCgkJCW9mZnNldFk6ICEwLA0KCQkJcG9pbnRlcklkOiAhMCwNCgkJCXBvaW50ZXJUeXBlOiAhMCwNCgkJCXNjcmVlblg6ICEwLA0KCQkJc2NyZWVuWTogITAsDQoJCQl0YXJnZXRUb3VjaGVzOiAhMCwNCgkJCXRvRWxlbWVudDogITAsDQoJCQl0b3VjaGVzOiAhMCwNCgkJCXdoaWNoOiAhMA0KCQl9LCBTLmV2ZW50LmFkZFByb3ApLCBTLmVhY2goe2ZvY3VzOiAiZm9jdXNpbiIsIGJsdXI6ICJmb2N1c291dCJ9LCBmdW5jdGlvbihlLCB0KSB7Uy5ldmVudC5zcGVjaWFsW2VdID0ge3NldHVwOiBmdW5jdGlvbigpIHtyZXR1cm4gU2UodGhpcywgZSwgQ2UpLCAhMX0sIHRyaWdnZXI6IGZ1bmN0aW9uKCkge3JldHVybiBTZSh0aGlzLCBlKSwgITB9LCBfZGVmYXVsdDogZnVuY3Rpb24oKSB7cmV0dXJuICEwfSwgZGVsZWdhdGVUeXBlOiB0fX0pLCBTLmVhY2goew0KCQkJbW91c2VlbnRlcjogIm1vdXNlb3ZlciIsDQoJCQltb3VzZWxlYXZlOiAibW91c2VvdXQiLA0KCQkJcG9pbnRlcmVudGVyOiAicG9pbnRlcm92ZXIiLA0KCQkJcG9pbnRlcmxlYXZlOiAicG9pbnRlcm91dCINCgkJfSwgZnVuY3Rpb24oZSwgaSkgew0KCQkJUy5ldmVudC5zcGVjaWFsW2VdID0gew0KCQkJCWRlbGVnYXRlVHlwZTogaSwgYmluZFR5cGU6IGksIGhhbmRsZTogZnVuY3Rpb24oZSkgew0KCQkJCQl2YXIgdCwgbiA9IGUucmVsYXRlZFRhcmdldCwgciA9IGUuaGFuZGxlT2JqOw0KCQkJCQlyZXR1cm4gbiAmJiAobiA9PT0gdGhpcyB8fCBTLmNvbnRhaW5zKHRoaXMsIG4pKSB8fCAoZS50eXBlID0gci5vcmlnVHlwZSwgdCA9IHIuaGFuZGxlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpLCBlLnR5cGUgPSBpKSwgdA0KCQkJCX0NCgkJCX0NCgkJfSksIFMuZm4uZXh0ZW5kKHsNCgkJCW9uOiBmdW5jdGlvbihlLCB0LCBuLCByKSB7cmV0dXJuIEVlKHRoaXMsIGUsIHQsIG4sIHIpfSwgb25lOiBmdW5jdGlvbihlLCB0LCBuLCByKSB7cmV0dXJuIEVlKHRoaXMsIGUsIHQsIG4sIHIsIDEpfSwgb2ZmOiBmdW5jdGlvbihlLCB0LCBuKSB7DQoJCQkJdmFyIHIsIGk7DQoJCQkJaWYoZSAmJiBlLnByZXZlbnREZWZhdWx0ICYmIGUuaGFuZGxlT2JqKSByZXR1cm4gciA9IGUuaGFuZGxlT2JqLCBTKGUuZGVsZWdhdGVUYXJnZXQpLm9mZihyLm5hbWVzcGFjZSA/IHIub3JpZ1R5cGUgKyAiLiIgKyByLm5hbWVzcGFjZSA6IHIub3JpZ1R5cGUsIHIuc2VsZWN0b3IsIHIuaGFuZGxlciksIHRoaXM7DQoJCQkJaWYoIm9iamVjdCIgPT0gdHlwZW9mIGUpIHsNCgkJCQkJZm9yKGkgaW4gZSkgdGhpcy5vZmYoaSwgdCwgZVtpXSk7DQoJCQkJCXJldHVybiB0aGlzDQoJCQkJfQ0KCQkJCXJldHVybiAhMSAhPT0gdCAmJiAiZnVuY3Rpb24iICE9IHR5cGVvZiB0IHx8IChuID0gdCwgdCA9IHZvaWQgMCksICExID09PSBuICYmIChuID0gVGUpLCB0aGlzLmVhY2goZnVuY3Rpb24oKSB7Uy5ldmVudC5yZW1vdmUodGhpcywgZSwgbiwgdCl9KQ0KCQkJfQ0KCQl9KTsNCgkJdmFyIGtlID0gLzxzY3JpcHR8PHN0eWxlfDxsaW5rL2ksIEFlID0gL2NoZWNrZWRccyooPzpbXj1dfD1ccyouY2hlY2tlZC4pL2ksIE5lID0gL15ccyo8ISg/OlxbQ0RBVEFcW3wtLSl8KD86XF1cXXwtLSk+XHMqJC9nOw0KDQoJCWZ1bmN0aW9uIGplKGUsIHQpIHtyZXR1cm4gQShlLCAidGFibGUiKSAmJiBBKDExICE9PSB0Lm5vZGVUeXBlID8gdCA6IHQuZmlyc3RDaGlsZCwgInRyIikgJiYgUyhlKS5jaGlsZHJlbigidGJvZHkiKVswXSB8fCBlfQ0KDQoJCWZ1bmN0aW9uIERlKGUpIHtyZXR1cm4gZS50eXBlID0gKG51bGwgIT09IGUuZ2V0QXR0cmlidXRlKCJ0eXBlIikpICsgIi8iICsgZS50eXBlLCBlfQ0KDQoJCWZ1bmN0aW9uIHFlKGUpIHtyZXR1cm4gInRydWUvIiA9PT0gKGUudHlwZSB8fCAiIikuc2xpY2UoMCwgNSkgPyBlLnR5cGUgPSBlLnR5cGUuc2xpY2UoNSkgOiBlLnJlbW92ZUF0dHJpYnV0ZSgidHlwZSIpLCBlfQ0KDQoJCWZ1bmN0aW9uIExlKGUsIHQpIHsNCgkJCXZhciBuLCByLCBpLCBvLCBhLCBzOw0KCQkJaWYoMSA9PT0gdC5ub2RlVHlwZSkgew0KCQkJCWlmKFkuaGFzRGF0YShlKSAmJiAocyA9IFkuZ2V0KGUpLmV2ZW50cykpIGZvcihpIGluIFkucmVtb3ZlKHQsICJoYW5kbGUgZXZlbnRzIiksIHMpIGZvcihuID0gMCwgciA9IHNbaV0ubGVuZ3RoOyBuIDwgcjsgbisrKSBTLmV2ZW50LmFkZCh0LCBpLCBzW2ldW25dKTsNCgkJCQlRLmhhc0RhdGEoZSkgJiYgKG8gPSBRLmFjY2VzcyhlKSwgYSA9IFMuZXh0ZW5kKHt9LCBvKSwgUS5zZXQodCwgYSkpDQoJCQl9DQoJCX0NCg0KCQlmdW5jdGlvbiBIZShuLCByLCBpLCBvKSB7DQoJCQlyID0gZyhyKTsNCgkJCXZhciBlLCB0LCBhLCBzLCB1LCBsLCBjID0gMCwgZiA9IG4ubGVuZ3RoLCBwID0gZiAtIDEsIGQgPSByWzBdLCBoID0gbShkKTsNCgkJCWlmKGggfHwgMSA8IGYgJiYgInN0cmluZyIgPT0gdHlwZW9mIGQgJiYgIXkuY2hlY2tDbG9uZSAmJiBBZS50ZXN0KGQpKSByZXR1cm4gbi5lYWNoKGZ1bmN0aW9uKGUpIHsNCgkJCQl2YXIgdCA9IG4uZXEoZSk7DQoJCQkJaCAmJiAoclswXSA9IGQuY2FsbCh0aGlzLCBlLCB0Lmh0bWwoKSkpLCBIZSh0LCByLCBpLCBvKQ0KCQkJfSk7DQoJCQlpZihmICYmICh0ID0gKGUgPSB4ZShyLCBuWzBdLm93bmVyRG9jdW1lbnQsICExLCBuLCBvKSkuZmlyc3RDaGlsZCwgMSA9PT0gZS5jaGlsZE5vZGVzLmxlbmd0aCAmJiAoZSA9IHQpLCB0IHx8IG8pKSB7DQoJCQkJZm9yKHMgPSAoYSA9IFMubWFwKHZlKGUsICJzY3JpcHQiKSwgRGUpKS5sZW5ndGg7IGMgPCBmOyBjKyspIHUgPSBlLCBjICE9PSBwICYmICh1ID0gUy5jbG9uZSh1LCAhMCwgITApLCBzICYmIFMubWVyZ2UoYSwgdmUodSwgInNjcmlwdCIpKSksIGkuY2FsbChuW2NdLCB1LCBjKTsNCgkJCQlpZihzKSBmb3IobCA9IGFbYS5sZW5ndGggLSAxXS5vd25lckRvY3VtZW50LCBTLm1hcChhLCBxZSksIGMgPSAwOyBjIDwgczsgYysrKSB1ID0gYVtjXSwgaGUudGVzdCh1LnR5cGUgfHwgIiIpICYmICFZLmFjY2Vzcyh1LCAiZ2xvYmFsRXZhbCIpICYmIFMuY29udGFpbnMobCwgdSkgJiYgKHUuc3JjICYmICJtb2R1bGUiICE9PSAodS50eXBlIHx8ICIiKS50b0xvd2VyQ2FzZSgpID8gUy5fZXZhbFVybCAmJiAhdS5ub01vZHVsZSAmJiBTLl9ldmFsVXJsKHUuc3JjLCB7bm9uY2U6IHUubm9uY2UgfHwgdS5nZXRBdHRyaWJ1dGUoIm5vbmNlIil9LCBsKSA6IGIodS50ZXh0Q29udGVudC5yZXBsYWNlKE5lLCAiIiksIHUsIGwpKQ0KCQkJfQ0KCQkJcmV0dXJuIG4NCgkJfQ0KDQoJCWZ1bmN0aW9uIE9lKGUsIHQsIG4pIHsNCgkJCWZvcih2YXIgciwgaSA9IHQgPyBTLmZpbHRlcih0LCBlKSA6IGUsIG8gPSAwOyBudWxsICE9IChyID0gaVtvXSk7IG8rKykgbiB8fCAxICE9PSByLm5vZGVUeXBlIHx8IFMuY2xlYW5EYXRhKHZlKHIpKSwgci5wYXJlbnROb2RlICYmIChuICYmIGllKHIpICYmIHllKHZlKHIsICJzY3JpcHQiKSksIHIucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChyKSk7DQoJCQlyZXR1cm4gZQ0KCQl9DQoNCgkJUy5leHRlbmQoew0KCQkJaHRtbFByZWZpbHRlcjogZnVuY3Rpb24oZSkge3JldHVybiBlfSwgY2xvbmU6IGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQl2YXIgciwgaSwgbywgYSwgcywgdSwgbCwgYyA9IGUuY2xvbmVOb2RlKCEwKSwgZiA9IGllKGUpOw0KCQkJCWlmKCEoeS5ub0Nsb25lQ2hlY2tlZCB8fCAxICE9PSBlLm5vZGVUeXBlICYmIDExICE9PSBlLm5vZGVUeXBlIHx8IFMuaXNYTUxEb2MoZSkpKSBmb3IoYSA9IHZlKGMpLCByID0gMCwgaSA9IChvID0gdmUoZSkpLmxlbmd0aDsgciA8IGk7IHIrKykgcyA9IG9bcl0sIHUgPSBhW3JdLCB2b2lkIDAsICJpbnB1dCIgPT09IChsID0gdS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpKSAmJiBwZS50ZXN0KHMudHlwZSkgPyB1LmNoZWNrZWQgPSBzLmNoZWNrZWQgOiAiaW5wdXQiICE9PSBsICYmICJ0ZXh0YXJlYSIgIT09IGwgfHwgKHUuZGVmYXVsdFZhbHVlID0gcy5kZWZhdWx0VmFsdWUpOw0KCQkJCWlmKHQpIGlmKG4pIGZvcihvID0gbyB8fCB2ZShlKSwgYSA9IGEgfHwgdmUoYyksIHIgPSAwLCBpID0gby5sZW5ndGg7IHIgPCBpOyByKyspIExlKG9bcl0sIGFbcl0pOyBlbHNlIExlKGUsIGMpOw0KCQkJCXJldHVybiAwIDwgKGEgPSB2ZShjLCAic2NyaXB0IikpLmxlbmd0aCAmJiB5ZShhLCAhZiAmJiB2ZShlLCAic2NyaXB0IikpLCBjDQoJCQl9LCBjbGVhbkRhdGE6IGZ1bmN0aW9uKGUpIHsNCgkJCQlmb3IodmFyIHQsIG4sIHIsIGkgPSBTLmV2ZW50LnNwZWNpYWwsIG8gPSAwOyB2b2lkIDAgIT09IChuID0gZVtvXSk7IG8rKykgaWYoVihuKSkgew0KCQkJCQlpZih0ID0gbltZLmV4cGFuZG9dKSB7DQoJCQkJCQlpZih0LmV2ZW50cykgZm9yKHIgaW4gdC5ldmVudHMpIGlbcl0gPyBTLmV2ZW50LnJlbW92ZShuLCByKSA6IFMucmVtb3ZlRXZlbnQobiwgciwgdC5oYW5kbGUpOw0KCQkJCQkJbltZLmV4cGFuZG9dID0gdm9pZCAwDQoJCQkJCX0NCgkJCQkJbltRLmV4cGFuZG9dICYmIChuW1EuZXhwYW5kb10gPSB2b2lkIDApDQoJCQkJfQ0KCQkJfQ0KCQl9KSwgUy5mbi5leHRlbmQoew0KCQkJZGV0YWNoOiBmdW5jdGlvbihlKSB7cmV0dXJuIE9lKHRoaXMsIGUsICEwKX0sDQoJCQlyZW1vdmU6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gT2UodGhpcywgZSl9LA0KCQkJdGV4dDogZnVuY3Rpb24oZSkge3JldHVybiAkKHRoaXMsIGZ1bmN0aW9uKGUpIHtyZXR1cm4gdm9pZCAwID09PSBlID8gUy50ZXh0KHRoaXMpIDogdGhpcy5lbXB0eSgpLmVhY2goZnVuY3Rpb24oKSB7MSAhPT0gdGhpcy5ub2RlVHlwZSAmJiAxMSAhPT0gdGhpcy5ub2RlVHlwZSAmJiA5ICE9PSB0aGlzLm5vZGVUeXBlIHx8ICh0aGlzLnRleHRDb250ZW50ID0gZSl9KX0sIG51bGwsIGUsIGFyZ3VtZW50cy5sZW5ndGgpfSwNCgkJCWFwcGVuZDogZnVuY3Rpb24oKSB7cmV0dXJuIEhlKHRoaXMsIGFyZ3VtZW50cywgZnVuY3Rpb24oZSkgezEgIT09IHRoaXMubm9kZVR5cGUgJiYgMTEgIT09IHRoaXMubm9kZVR5cGUgJiYgOSAhPT0gdGhpcy5ub2RlVHlwZSB8fCBqZSh0aGlzLCBlKS5hcHBlbmRDaGlsZChlKX0pfSwNCgkJCXByZXBlbmQ6IGZ1bmN0aW9uKCkgew0KCQkJCXJldHVybiBIZSh0aGlzLCBhcmd1bWVudHMsIGZ1bmN0aW9uKGUpIHsNCgkJCQkJaWYoMSA9PT0gdGhpcy5ub2RlVHlwZSB8fCAxMSA9PT0gdGhpcy5ub2RlVHlwZSB8fCA5ID09PSB0aGlzLm5vZGVUeXBlKSB7DQoJCQkJCQl2YXIgdCA9IGplKHRoaXMsIGUpOw0KCQkJCQkJdC5pbnNlcnRCZWZvcmUoZSwgdC5maXJzdENoaWxkKQ0KCQkJCQl9DQoJCQkJfSkNCgkJCX0sDQoJCQliZWZvcmU6IGZ1bmN0aW9uKCkge3JldHVybiBIZSh0aGlzLCBhcmd1bWVudHMsIGZ1bmN0aW9uKGUpIHt0aGlzLnBhcmVudE5vZGUgJiYgdGhpcy5wYXJlbnROb2RlLmluc2VydEJlZm9yZShlLCB0aGlzKX0pfSwNCgkJCWFmdGVyOiBmdW5jdGlvbigpIHtyZXR1cm4gSGUodGhpcywgYXJndW1lbnRzLCBmdW5jdGlvbihlKSB7dGhpcy5wYXJlbnROb2RlICYmIHRoaXMucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoZSwgdGhpcy5uZXh0U2libGluZyl9KX0sDQoJCQllbXB0eTogZnVuY3Rpb24oKSB7DQoJCQkJZm9yKHZhciBlLCB0ID0gMDsgbnVsbCAhPSAoZSA9IHRoaXNbdF0pOyB0KyspIDEgPT09IGUubm9kZVR5cGUgJiYgKFMuY2xlYW5EYXRhKHZlKGUsICExKSksIGUudGV4dENvbnRlbnQgPSAiIik7DQoJCQkJcmV0dXJuIHRoaXMNCgkJCX0sDQoJCQljbG9uZTogZnVuY3Rpb24oZSwgdCkge3JldHVybiBlID0gbnVsbCAhPSBlICYmIGUsIHQgPSBudWxsID09IHQgPyBlIDogdCwgdGhpcy5tYXAoZnVuY3Rpb24oKSB7cmV0dXJuIFMuY2xvbmUodGhpcywgZSwgdCl9KX0sDQoJCQlodG1sOiBmdW5jdGlvbihlKSB7DQoJCQkJcmV0dXJuICQodGhpcywgZnVuY3Rpb24oZSkgew0KCQkJCQl2YXIgdCA9IHRoaXNbMF0gfHwge30sIG4gPSAwLCByID0gdGhpcy5sZW5ndGg7DQoJCQkJCWlmKHZvaWQgMCA9PT0gZSAmJiAxID09PSB0Lm5vZGVUeXBlKSByZXR1cm4gdC5pbm5lckhUTUw7DQoJCQkJCWlmKCJzdHJpbmciID09IHR5cGVvZiBlICYmICFrZS50ZXN0KGUpICYmICFnZVsoZGUuZXhlYyhlKSB8fCBbIiIsICIiXSlbMV0udG9Mb3dlckNhc2UoKV0pIHsNCgkJCQkJCWUgPSBTLmh0bWxQcmVmaWx0ZXIoZSk7DQoJCQkJCQl0cnkgew0KCQkJCQkJCWZvcig7IG4gPCByOyBuKyspIDEgPT09ICh0ID0gdGhpc1tuXSB8fCB7fSkubm9kZVR5cGUgJiYgKFMuY2xlYW5EYXRhKHZlKHQsICExKSksIHQuaW5uZXJIVE1MID0gZSk7DQoJCQkJCQkJdCA9IDANCgkJCQkJCX0gY2F0Y2goZSkge30NCgkJCQkJfQ0KCQkJCQl0ICYmIHRoaXMuZW1wdHkoKS5hcHBlbmQoZSkNCgkJCQl9LCBudWxsLCBlLCBhcmd1bWVudHMubGVuZ3RoKQ0KCQkJfSwNCgkJCXJlcGxhY2VXaXRoOiBmdW5jdGlvbigpIHsNCgkJCQl2YXIgbiA9IFtdOw0KCQkJCXJldHVybiBIZSh0aGlzLCBhcmd1bWVudHMsIGZ1bmN0aW9uKGUpIHsNCgkJCQkJdmFyIHQgPSB0aGlzLnBhcmVudE5vZGU7DQoJCQkJCVMuaW5BcnJheSh0aGlzLCBuKSA8IDAgJiYgKFMuY2xlYW5EYXRhKHZlKHRoaXMpKSwgdCAmJiB0LnJlcGxhY2VDaGlsZChlLCB0aGlzKSkNCgkJCQl9LCBuKQ0KCQkJfQ0KCQl9KSwgUy5lYWNoKHsNCgkJCWFwcGVuZFRvOiAiYXBwZW5kIiwNCgkJCXByZXBlbmRUbzogInByZXBlbmQiLA0KCQkJaW5zZXJ0QmVmb3JlOiAiYmVmb3JlIiwNCgkJCWluc2VydEFmdGVyOiAiYWZ0ZXIiLA0KCQkJcmVwbGFjZUFsbDogInJlcGxhY2VXaXRoIg0KCQl9LCBmdW5jdGlvbihlLCBhKSB7DQoJCQlTLmZuW2VdID0gZnVuY3Rpb24oZSkgew0KCQkJCWZvcih2YXIgdCwgbiA9IFtdLCByID0gUyhlKSwgaSA9IHIubGVuZ3RoIC0gMSwgbyA9IDA7IG8gPD0gaTsgbysrKSB0ID0gbyA9PT0gaSA/IHRoaXMgOiB0aGlzLmNsb25lKCEwKSwgUyhyW29dKVthXSh0KSwgdS5hcHBseShuLCB0LmdldCgpKTsNCgkJCQlyZXR1cm4gdGhpcy5wdXNoU3RhY2sobikNCgkJCX0NCgkJfSk7DQoJCXZhciBQZSA9IG5ldyBSZWdFeHAoIl4oIiArIGVlICsgIikoPyFweClbYS16JV0rJCIsICJpIiksIFJlID0gZnVuY3Rpb24oZSkgew0KCQkJdmFyIHQgPSBlLm93bmVyRG9jdW1lbnQuZGVmYXVsdFZpZXc7DQoJCQlyZXR1cm4gdCAmJiB0Lm9wZW5lciB8fCAodCA9IEMpLCB0LmdldENvbXB1dGVkU3R5bGUoZSkNCgkJfSwgTWUgID0gZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJdmFyIHIsIGksIG8gPSB7fTsNCgkJCWZvcihpIGluIHQpIG9baV0gPSBlLnN0eWxlW2ldLCBlLnN0eWxlW2ldID0gdFtpXTsNCgkJCWZvcihpIGluIHIgPSBuLmNhbGwoZSksIHQpIGUuc3R5bGVbaV0gPSBvW2ldOw0KCQkJcmV0dXJuIHINCgkJfSwgSWUgID0gbmV3IFJlZ0V4cChuZS5qb2luKCJ8IiksICJpIik7DQoNCgkJZnVuY3Rpb24gV2UoZSwgdCwgbikgew0KCQkJdmFyIHIsIGksIG8sIGEsIHMgPSBlLnN0eWxlOw0KCQkJcmV0dXJuIChuID0gbiB8fCBSZShlKSkgJiYgKCIiICE9PSAoYSA9IG4uZ2V0UHJvcGVydHlWYWx1ZSh0KSB8fCBuW3RdKSB8fCBpZShlKSB8fCAoYSA9IFMuc3R5bGUoZSwgdCkpLCAheS5waXhlbEJveFN0eWxlcygpICYmIFBlLnRlc3QoYSkgJiYgSWUudGVzdCh0KSAmJiAociA9IHMud2lkdGgsIGkgPSBzLm1pbldpZHRoLCBvID0gcy5tYXhXaWR0aCwgcy5taW5XaWR0aCA9IHMubWF4V2lkdGggPSBzLndpZHRoID0gYSwgYSA9IG4ud2lkdGgsIHMud2lkdGggPSByLCBzLm1pbldpZHRoID0gaSwgcy5tYXhXaWR0aCA9IG8pKSwgdm9pZCAwICE9PSBhID8gYSArICIiIDogYQ0KCQl9DQoNCgkJZnVuY3Rpb24gRmUoZSwgdCkgew0KCQkJcmV0dXJuIHsNCgkJCQlnZXQ6IGZ1bmN0aW9uKCkgew0KCQkJCQlpZighZSgpKSByZXR1cm4gKHRoaXMuZ2V0ID0gdCkuYXBwbHkodGhpcywgYXJndW1lbnRzKTsNCgkJCQkJZGVsZXRlIHRoaXMuZ2V0DQoJCQkJfQ0KCQkJfQ0KCQl9DQoNCgkJIWZ1bmN0aW9uKCkgew0KCQkJZnVuY3Rpb24gZSgpIHsNCgkJCQlpZihsKSB7DQoJCQkJCXUuc3R5bGUuY3NzVGV4dCA9ICJwb3NpdGlvbjphYnNvbHV0ZTtsZWZ0Oi0xMTExMXB4O3dpZHRoOjYwcHg7bWFyZ2luLXRvcDoxcHg7cGFkZGluZzowO2JvcmRlcjowIiwgbC5zdHlsZS5jc3NUZXh0ID0gInBvc2l0aW9uOnJlbGF0aXZlO2Rpc3BsYXk6YmxvY2s7Ym94LXNpemluZzpib3JkZXItYm94O292ZXJmbG93OnNjcm9sbDttYXJnaW46YXV0bztib3JkZXI6MXB4O3BhZGRpbmc6MXB4O3dpZHRoOjYwJTt0b3A6MSUiLCByZS5hcHBlbmRDaGlsZCh1KS5hcHBlbmRDaGlsZChsKTsNCgkJCQkJdmFyIGUgPSBDLmdldENvbXB1dGVkU3R5bGUobCk7DQoJCQkJCW4gPSAiMSUiICE9PSBlLnRvcCwgcyA9IDEyID09PSB0KGUubWFyZ2luTGVmdCksIGwuc3R5bGUucmlnaHQgPSAiNjAlIiwgbyA9IDM2ID09PSB0KGUucmlnaHQpLCByID0gMzYgPT09IHQoZS53aWR0aCksIGwuc3R5bGUucG9zaXRpb24gPSAiYWJzb2x1dGUiLCBpID0gMTIgPT09IHQobC5vZmZzZXRXaWR0aCAvIDMpLCByZS5yZW1vdmVDaGlsZCh1KSwgbCA9IG51bGwNCgkJCQl9DQoJCQl9DQoNCgkJCWZ1bmN0aW9uIHQoZSkge3JldHVybiBNYXRoLnJvdW5kKHBhcnNlRmxvYXQoZSkpfQ0KDQoJCQl2YXIgbiwgciwgaSwgbywgYSwgcywgdSA9IEUuY3JlYXRlRWxlbWVudCgiZGl2IiksIGwgPSBFLmNyZWF0ZUVsZW1lbnQoImRpdiIpOw0KCQkJbC5zdHlsZSAmJiAobC5zdHlsZS5iYWNrZ3JvdW5kQ2xpcCA9ICJjb250ZW50LWJveCIsIGwuY2xvbmVOb2RlKCEwKS5zdHlsZS5iYWNrZ3JvdW5kQ2xpcCA9ICIiLCB5LmNsZWFyQ2xvbmVTdHlsZSA9ICJjb250ZW50LWJveCIgPT09IGwuc3R5bGUuYmFja2dyb3VuZENsaXAsIFMuZXh0ZW5kKHksIHsNCgkJCQlib3hTaXppbmdSZWxpYWJsZTogZnVuY3Rpb24oKSB7cmV0dXJuIGUoKSwgcn0sDQoJCQkJcGl4ZWxCb3hTdHlsZXM6IGZ1bmN0aW9uKCkge3JldHVybiBlKCksIG99LA0KCQkJCXBpeGVsUG9zaXRpb246IGZ1bmN0aW9uKCkge3JldHVybiBlKCksIG59LA0KCQkJCXJlbGlhYmxlTWFyZ2luTGVmdDogZnVuY3Rpb24oKSB7cmV0dXJuIGUoKSwgc30sDQoJCQkJc2Nyb2xsYm94U2l6ZTogZnVuY3Rpb24oKSB7cmV0dXJuIGUoKSwgaX0sDQoJCQkJcmVsaWFibGVUckRpbWVuc2lvbnM6IGZ1bmN0aW9uKCkgew0KCQkJCQl2YXIgZSwgdCwgbiwgcjsNCgkJCQkJcmV0dXJuIG51bGwgPT0gYSAmJiAoZSA9IEUuY3JlYXRlRWxlbWVudCgidGFibGUiKSwgdCA9IEUuY3JlYXRlRWxlbWVudCgidHIiKSwgbiA9IEUuY3JlYXRlRWxlbWVudCgiZGl2IiksIGUuc3R5bGUuY3NzVGV4dCA9ICJwb3NpdGlvbjphYnNvbHV0ZTtsZWZ0Oi0xMTExMXB4O2JvcmRlci1jb2xsYXBzZTpzZXBhcmF0ZSIsIHQuc3R5bGUuY3NzVGV4dCA9ICJib3JkZXI6MXB4IHNvbGlkIiwgdC5zdHlsZS5oZWlnaHQgPSAiMXB4Iiwgbi5zdHlsZS5oZWlnaHQgPSAiOXB4Iiwgbi5zdHlsZS5kaXNwbGF5ID0gImJsb2NrIiwgcmUuYXBwZW5kQ2hpbGQoZSkuYXBwZW5kQ2hpbGQodCkuYXBwZW5kQ2hpbGQobiksIHIgPSBDLmdldENvbXB1dGVkU3R5bGUodCksIGEgPSBwYXJzZUludChyLmhlaWdodCwgMTApICsgcGFyc2VJbnQoci5ib3JkZXJUb3BXaWR0aCwgMTApICsgcGFyc2VJbnQoci5ib3JkZXJCb3R0b21XaWR0aCwgMTApID09PSB0Lm9mZnNldEhlaWdodCwgcmUucmVtb3ZlQ2hpbGQoZSkpLCBhDQoJCQkJfQ0KCQkJfSkpDQoJCX0oKTsNCgkJdmFyIEJlID0gWyJXZWJraXQiLCAiTW96IiwgIm1zIl0sICRlID0gRS5jcmVhdGVFbGVtZW50KCJkaXYiKS5zdHlsZSwgX2UgPSB7fTsNCg0KCQlmdW5jdGlvbiB6ZShlKSB7DQoJCQl2YXIgdCA9IFMuY3NzUHJvcHNbZV0gfHwgX2VbZV07DQoJCQlyZXR1cm4gdCB8fCAoZSBpbiAkZSA/IGUgOiBfZVtlXSA9IGZ1bmN0aW9uKGUpIHsNCgkJCQl2YXIgdCA9IGVbMF0udG9VcHBlckNhc2UoKSArIGUuc2xpY2UoMSksIG4gPSBCZS5sZW5ndGg7DQoJCQkJd2hpbGUobi0tKSBpZigoZSA9IEJlW25dICsgdCkgaW4gJGUpIHJldHVybiBlDQoJCQl9KGUpIHx8IGUpDQoJCX0NCg0KCQl2YXIgVWUgPSAvXihub25lfHRhYmxlKD8hLWNbZWFdKS4rKS8sIFhlID0gL14tLS8sIFZlID0ge3Bvc2l0aW9uOiAiYWJzb2x1dGUiLCB2aXNpYmlsaXR5OiAiaGlkZGVuIiwgZGlzcGxheTogImJsb2NrIn0sIEdlID0ge2xldHRlclNwYWNpbmc6ICIwIiwgZm9udFdlaWdodDogIjQwMCJ9Ow0KDQoJCWZ1bmN0aW9uIFllKGUsIHQsIG4pIHsNCgkJCXZhciByID0gdGUuZXhlYyh0KTsNCgkJCXJldHVybiByID8gTWF0aC5tYXgoMCwgclsyXSAtIChuIHx8IDApKSArIChyWzNdIHx8ICJweCIpIDogdA0KCQl9DQoNCgkJZnVuY3Rpb24gUWUoZSwgdCwgbiwgciwgaSwgbykgew0KCQkJdmFyIGEgPSAid2lkdGgiID09PSB0ID8gMSA6IDAsIHMgPSAwLCB1ID0gMDsNCgkJCWlmKG4gPT09IChyID8gImJvcmRlciIgOiAiY29udGVudCIpKSByZXR1cm4gMDsNCgkJCWZvcig7IGEgPCA0OyBhICs9IDIpICJtYXJnaW4iID09PSBuICYmICh1ICs9IFMuY3NzKGUsIG4gKyBuZVthXSwgITAsIGkpKSwgciA/ICgiY29udGVudCIgPT09IG4gJiYgKHUgLT0gUy5jc3MoZSwgInBhZGRpbmciICsgbmVbYV0sICEwLCBpKSksICJtYXJnaW4iICE9PSBuICYmICh1IC09IFMuY3NzKGUsICJib3JkZXIiICsgbmVbYV0gKyAiV2lkdGgiLCAhMCwgaSkpKSA6ICh1ICs9IFMuY3NzKGUsICJwYWRkaW5nIiArIG5lW2FdLCAhMCwgaSksICJwYWRkaW5nIiAhPT0gbiA/IHUgKz0gUy5jc3MoZSwgImJvcmRlciIgKyBuZVthXSArICJXaWR0aCIsICEwLCBpKSA6IHMgKz0gUy5jc3MoZSwgImJvcmRlciIgKyBuZVthXSArICJXaWR0aCIsICEwLCBpKSk7DQoJCQlyZXR1cm4gIXIgJiYgMCA8PSBvICYmICh1ICs9IE1hdGgubWF4KDAsIE1hdGguY2VpbChlWyJvZmZzZXQiICsgdFswXS50b1VwcGVyQ2FzZSgpICsgdC5zbGljZSgxKV0gLSBvIC0gdSAtIHMgLSAuNSkpIHx8IDApLCB1DQoJCX0NCg0KCQlmdW5jdGlvbiBKZShlLCB0LCBuKSB7DQoJCQl2YXIgciA9IFJlKGUpLCBpID0gKCF5LmJveFNpemluZ1JlbGlhYmxlKCkgfHwgbikgJiYgImJvcmRlci1ib3giID09PSBTLmNzcyhlLCAiYm94U2l6aW5nIiwgITEsIHIpLCBvID0gaSwgYSA9IFdlKGUsIHQsIHIpLCBzID0gIm9mZnNldCIgKyB0WzBdLnRvVXBwZXJDYXNlKCkgKyB0LnNsaWNlKDEpOw0KCQkJaWYoUGUudGVzdChhKSkgew0KCQkJCWlmKCFuKSByZXR1cm4gYTsNCgkJCQlhID0gImF1dG8iDQoJCQl9DQoJCQlyZXR1cm4gKCF5LmJveFNpemluZ1JlbGlhYmxlKCkgJiYgaSB8fCAheS5yZWxpYWJsZVRyRGltZW5zaW9ucygpICYmIEEoZSwgInRyIikgfHwgImF1dG8iID09PSBhIHx8ICFwYXJzZUZsb2F0KGEpICYmICJpbmxpbmUiID09PSBTLmNzcyhlLCAiZGlzcGxheSIsICExLCByKSkgJiYgZS5nZXRDbGllbnRSZWN0cygpLmxlbmd0aCAmJiAoaSA9ICJib3JkZXItYm94IiA9PT0gUy5jc3MoZSwgImJveFNpemluZyIsICExLCByKSwgKG8gPSBzIGluIGUpICYmIChhID0gZVtzXSkpLCAoYSA9IHBhcnNlRmxvYXQoYSkgfHwgMCkgKyBRZShlLCB0LCBuIHx8IChpID8gImJvcmRlciIgOiAiY29udGVudCIpLCBvLCByLCBhKSArICJweCINCgkJfQ0KDQoJCWZ1bmN0aW9uIEtlKGUsIHQsIG4sIHIsIGkpIHtyZXR1cm4gbmV3IEtlLnByb3RvdHlwZS5pbml0KGUsIHQsIG4sIHIsIGkpfQ0KDQoJCVMuZXh0ZW5kKHsNCgkJCWNzc0hvb2tzOiB7DQoJCQkJb3BhY2l0eTogew0KCQkJCQlnZXQ6IGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQkJCWlmKHQpIHsNCgkJCQkJCQl2YXIgbiA9IFdlKGUsICJvcGFjaXR5Iik7DQoJCQkJCQkJcmV0dXJuICIiID09PSBuID8gIjEiIDogbg0KCQkJCQkJfQ0KCQkJCQl9DQoJCQkJfQ0KCQkJfSwNCgkJCWNzc051bWJlcjogew0KCQkJCWFuaW1hdGlvbkl0ZXJhdGlvbkNvdW50OiAhMCwNCgkJCQljb2x1bW5Db3VudDogITAsDQoJCQkJZmlsbE9wYWNpdHk6ICEwLA0KCQkJCWZsZXhHcm93OiAhMCwNCgkJCQlmbGV4U2hyaW5rOiAhMCwNCgkJCQlmb250V2VpZ2h0OiAhMCwNCgkJCQlncmlkQXJlYTogITAsDQoJCQkJZ3JpZENvbHVtbjogITAsDQoJCQkJZ3JpZENvbHVtbkVuZDogITAsDQoJCQkJZ3JpZENvbHVtblN0YXJ0OiAhMCwNCgkJCQlncmlkUm93OiAhMCwNCgkJCQlncmlkUm93RW5kOiAhMCwNCgkJCQlncmlkUm93U3RhcnQ6ICEwLA0KCQkJCWxpbmVIZWlnaHQ6ICEwLA0KCQkJCW9wYWNpdHk6ICEwLA0KCQkJCW9yZGVyOiAhMCwNCgkJCQlvcnBoYW5zOiAhMCwNCgkJCQl3aWRvd3M6ICEwLA0KCQkJCXpJbmRleDogITAsDQoJCQkJem9vbTogITANCgkJCX0sDQoJCQljc3NQcm9wczoge30sDQoJCQlzdHlsZTogZnVuY3Rpb24oZSwgdCwgbiwgcikgew0KCQkJCWlmKGUgJiYgMyAhPT0gZS5ub2RlVHlwZSAmJiA4ICE9PSBlLm5vZGVUeXBlICYmIGUuc3R5bGUpIHsNCgkJCQkJdmFyIGksIG8sIGEsIHMgPSBYKHQpLCB1ID0gWGUudGVzdCh0KSwgbCA9IGUuc3R5bGU7DQoJCQkJCWlmKHUgfHwgKHQgPSB6ZShzKSksIGEgPSBTLmNzc0hvb2tzW3RdIHx8IFMuY3NzSG9va3Nbc10sIHZvaWQgMCA9PT0gbikgcmV0dXJuIGEgJiYgImdldCIgaW4gYSAmJiB2b2lkIDAgIT09IChpID0gYS5nZXQoZSwgITEsIHIpKSA/IGkgOiBsW3RdOw0KCQkJCQkic3RyaW5nIiA9PT0gKG8gPSB0eXBlb2YgbikgJiYgKGkgPSB0ZS5leGVjKG4pKSAmJiBpWzFdICYmIChuID0gc2UoZSwgdCwgaSksIG8gPSAibnVtYmVyIiksIG51bGwgIT0gbiAmJiBuID09IG4gJiYgKCJudW1iZXIiICE9PSBvIHx8IHUgfHwgKG4gKz0gaSAmJiBpWzNdIHx8IChTLmNzc051bWJlcltzXSA/ICIiIDogInB4IikpLCB5LmNsZWFyQ2xvbmVTdHlsZSB8fCAiIiAhPT0gbiB8fCAwICE9PSB0LmluZGV4T2YoImJhY2tncm91bmQiKSB8fCAobFt0XSA9ICJpbmhlcml0IiksIGEgJiYgInNldCIgaW4gYSAmJiB2b2lkIDAgPT09IChuID0gYS5zZXQoZSwgbiwgcikpIHx8ICh1ID8gbC5zZXRQcm9wZXJ0eSh0LCBuKSA6IGxbdF0gPSBuKSkNCgkJCQl9DQoJCQl9LA0KCQkJY3NzOiBmdW5jdGlvbihlLCB0LCBuLCByKSB7DQoJCQkJdmFyIGksIG8sIGEsIHMgPSBYKHQpOw0KCQkJCXJldHVybiBYZS50ZXN0KHQpIHx8ICh0ID0gemUocykpLCAoYSA9IFMuY3NzSG9va3NbdF0gfHwgUy5jc3NIb29rc1tzXSkgJiYgImdldCIgaW4gYSAmJiAoaSA9IGEuZ2V0KGUsICEwLCBuKSksIHZvaWQgMCA9PT0gaSAmJiAoaSA9IFdlKGUsIHQsIHIpKSwgIm5vcm1hbCIgPT09IGkgJiYgdCBpbiBHZSAmJiAoaSA9IEdlW3RdKSwgIiIgPT09IG4gfHwgbiA/IChvID0gcGFyc2VGbG9hdChpKSwgITAgPT09IG4gfHwgaXNGaW5pdGUobykgPyBvIHx8IDAgOiBpKSA6IGkNCgkJCX0NCgkJfSksIFMuZWFjaChbImhlaWdodCIsICJ3aWR0aCJdLCBmdW5jdGlvbihlLCB1KSB7DQoJCQlTLmNzc0hvb2tzW3VdID0gew0KCQkJCWdldDogZnVuY3Rpb24oZSwgdCwgbikge2lmKHQpIHJldHVybiAhVWUudGVzdChTLmNzcyhlLCAiZGlzcGxheSIpKSB8fCBlLmdldENsaWVudFJlY3RzKCkubGVuZ3RoICYmIGUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGggPyBKZShlLCB1LCBuKSA6IE1lKGUsIFZlLCBmdW5jdGlvbigpIHtyZXR1cm4gSmUoZSwgdSwgbil9KX0sDQoJCQkJc2V0OiBmdW5jdGlvbihlLCB0LCBuKSB7DQoJCQkJCXZhciByLCBpID0gUmUoZSksIG8gPSAheS5zY3JvbGxib3hTaXplKCkgJiYgImFic29sdXRlIiA9PT0gaS5wb3NpdGlvbiwgYSA9IChvIHx8IG4pICYmICJib3JkZXItYm94IiA9PT0gUy5jc3MoZSwgImJveFNpemluZyIsICExLCBpKSwgcyA9IG4gPyBRZShlLCB1LCBuLCBhLCBpKSA6IDA7DQoJCQkJCXJldHVybiBhICYmIG8gJiYgKHMgLT0gTWF0aC5jZWlsKGVbIm9mZnNldCIgKyB1WzBdLnRvVXBwZXJDYXNlKCkgKyB1LnNsaWNlKDEpXSAtIHBhcnNlRmxvYXQoaVt1XSkgLSBRZShlLCB1LCAiYm9yZGVyIiwgITEsIGkpIC0gLjUpKSwgcyAmJiAociA9IHRlLmV4ZWModCkpICYmICJweCIgIT09IChyWzNdIHx8ICJweCIpICYmIChlLnN0eWxlW3VdID0gdCwgdCA9IFMuY3NzKGUsIHUpKSwgWWUoMCwgdCwgcykNCgkJCQl9DQoJCQl9DQoJCX0pLCBTLmNzc0hvb2tzLm1hcmdpbkxlZnQgPSBGZSh5LnJlbGlhYmxlTWFyZ2luTGVmdCwgZnVuY3Rpb24oZSwgdCkge2lmKHQpIHJldHVybiAocGFyc2VGbG9hdChXZShlLCAibWFyZ2luTGVmdCIpKSB8fCBlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmxlZnQgLSBNZShlLCB7bWFyZ2luTGVmdDogMH0sIGZ1bmN0aW9uKCkge3JldHVybiBlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmxlZnR9KSkgKyAicHgifSksIFMuZWFjaCh7DQoJCQltYXJnaW46ICIiLA0KCQkJcGFkZGluZzogIiIsDQoJCQlib3JkZXI6ICJXaWR0aCINCgkJfSwgZnVuY3Rpb24oaSwgbykgew0KCQkJUy5jc3NIb29rc1tpICsgb10gPSB7DQoJCQkJZXhwYW5kOiBmdW5jdGlvbihlKSB7DQoJCQkJCWZvcih2YXIgdCA9IDAsIG4gPSB7fSwgciA9ICJzdHJpbmciID09IHR5cGVvZiBlID8gZS5zcGxpdCgiICIpIDogW2VdOyB0IDwgNDsgdCsrKSBuW2kgKyBuZVt0XSArIG9dID0gclt0XSB8fCByW3QgLSAyXSB8fCByWzBdOw0KCQkJCQlyZXR1cm4gbg0KCQkJCX0NCgkJCX0sICJtYXJnaW4iICE9PSBpICYmIChTLmNzc0hvb2tzW2kgKyBvXS5zZXQgPSBZZSkNCgkJfSksIFMuZm4uZXh0ZW5kKHsNCgkJCWNzczogZnVuY3Rpb24oZSwgdCkgew0KCQkJCXJldHVybiAkKHRoaXMsIGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQkJdmFyIHIsIGksIG8gPSB7fSwgYSA9IDA7DQoJCQkJCWlmKEFycmF5LmlzQXJyYXkodCkpIHsNCgkJCQkJCWZvcihyID0gUmUoZSksIGkgPSB0Lmxlbmd0aDsgYSA8IGk7IGErKykgb1t0W2FdXSA9IFMuY3NzKGUsIHRbYV0sICExLCByKTsNCgkJCQkJCXJldHVybiBvDQoJCQkJCX0NCgkJCQkJcmV0dXJuIHZvaWQgMCAhPT0gbiA/IFMuc3R5bGUoZSwgdCwgbikgOiBTLmNzcyhlLCB0KQ0KCQkJCX0sIGUsIHQsIDEgPCBhcmd1bWVudHMubGVuZ3RoKQ0KCQkJfQ0KCQl9KSwgKChTLlR3ZWVuID0gS2UpLnByb3RvdHlwZSA9IHsNCgkJCWNvbnN0cnVjdG9yOiBLZSwNCgkJCWluaXQ6IGZ1bmN0aW9uKGUsIHQsIG4sIHIsIGksIG8pIHt0aGlzLmVsZW0gPSBlLCB0aGlzLnByb3AgPSBuLCB0aGlzLmVhc2luZyA9IGkgfHwgUy5lYXNpbmcuX2RlZmF1bHQsIHRoaXMub3B0aW9ucyA9IHQsIHRoaXMuc3RhcnQgPSB0aGlzLm5vdyA9IHRoaXMuY3VyKCksIHRoaXMuZW5kID0gciwgdGhpcy51bml0ID0gbyB8fCAoUy5jc3NOdW1iZXJbbl0gPyAiIiA6ICJweCIpfSwNCgkJCWN1cjogZnVuY3Rpb24oKSB7DQoJCQkJdmFyIGUgPSBLZS5wcm9wSG9va3NbdGhpcy5wcm9wXTsNCgkJCQlyZXR1cm4gZSAmJiBlLmdldCA/IGUuZ2V0KHRoaXMpIDogS2UucHJvcEhvb2tzLl9kZWZhdWx0LmdldCh0aGlzKQ0KCQkJfSwNCgkJCXJ1bjogZnVuY3Rpb24oZSkgew0KCQkJCXZhciB0LCBuID0gS2UucHJvcEhvb2tzW3RoaXMucHJvcF07DQoJCQkJcmV0dXJuIHRoaXMub3B0aW9ucy5kdXJhdGlvbiA/IHRoaXMucG9zID0gdCA9IFMuZWFzaW5nW3RoaXMuZWFzaW5nXShlLCB0aGlzLm9wdGlvbnMuZHVyYXRpb24gKiBlLCAwLCAxLCB0aGlzLm9wdGlvbnMuZHVyYXRpb24pIDogdGhpcy5wb3MgPSB0ID0gZSwgdGhpcy5ub3cgPSAodGhpcy5lbmQgLSB0aGlzLnN0YXJ0KSAqIHQgKyB0aGlzLnN0YXJ0LCB0aGlzLm9wdGlvbnMuc3RlcCAmJiB0aGlzLm9wdGlvbnMuc3RlcC5jYWxsKHRoaXMuZWxlbSwgdGhpcy5ub3csIHRoaXMpLCBuICYmIG4uc2V0ID8gbi5zZXQodGhpcykgOiBLZS5wcm9wSG9va3MuX2RlZmF1bHQuc2V0KHRoaXMpLCB0aGlzDQoJCQl9DQoJCX0pLmluaXQucHJvdG90eXBlID0gS2UucHJvdG90eXBlLCAoS2UucHJvcEhvb2tzID0gew0KCQkJX2RlZmF1bHQ6IHsNCgkJCQlnZXQ6IGZ1bmN0aW9uKGUpIHsNCgkJCQkJdmFyIHQ7DQoJCQkJCXJldHVybiAxICE9PSBlLmVsZW0ubm9kZVR5cGUgfHwgbnVsbCAhPSBlLmVsZW1bZS5wcm9wXSAmJiBudWxsID09IGUuZWxlbS5zdHlsZVtlLnByb3BdID8gZS5lbGVtW2UucHJvcF0gOiAodCA9IFMuY3NzKGUuZWxlbSwgZS5wcm9wLCAiIikpICYmICJhdXRvIiAhPT0gdCA/IHQgOiAwDQoJCQkJfSwgc2V0OiBmdW5jdGlvbihlKSB7Uy5meC5zdGVwW2UucHJvcF0gPyBTLmZ4LnN0ZXBbZS5wcm9wXShlKSA6IDEgIT09IGUuZWxlbS5ub2RlVHlwZSB8fCAhUy5jc3NIb29rc1tlLnByb3BdICYmIG51bGwgPT0gZS5lbGVtLnN0eWxlW3plKGUucHJvcCldID8gZS5lbGVtW2UucHJvcF0gPSBlLm5vdyA6IFMuc3R5bGUoZS5lbGVtLCBlLnByb3AsIGUubm93ICsgZS51bml0KX0NCgkJCX0NCgkJfSkuc2Nyb2xsVG9wID0gS2UucHJvcEhvb2tzLnNjcm9sbExlZnQgPSB7c2V0OiBmdW5jdGlvbihlKSB7ZS5lbGVtLm5vZGVUeXBlICYmIGUuZWxlbS5wYXJlbnROb2RlICYmIChlLmVsZW1bZS5wcm9wXSA9IGUubm93KX19LCBTLmVhc2luZyA9IHsNCgkJCWxpbmVhcjogZnVuY3Rpb24oZSkge3JldHVybiBlfSwNCgkJCXN3aW5nOiBmdW5jdGlvbihlKSB7cmV0dXJuIC41IC0gTWF0aC5jb3MoZSAqIE1hdGguUEkpIC8gMn0sDQoJCQlfZGVmYXVsdDogInN3aW5nIg0KCQl9LCBTLmZ4ID0gS2UucHJvdG90eXBlLmluaXQsIFMuZnguc3RlcCA9IHt9Ow0KCQl2YXIgWmUsIGV0LCB0dCwgbnQsIHJ0ID0gL14oPzp0b2dnbGV8c2hvd3xoaWRlKSQvLCBpdCA9IC9xdWV1ZUhvb2tzJC87DQoNCgkJZnVuY3Rpb24gb3QoKSB7ZXQgJiYgKCExID09PSBFLmhpZGRlbiAmJiBDLnJlcXVlc3RBbmltYXRpb25GcmFtZSA/IEMucmVxdWVzdEFuaW1hdGlvbkZyYW1lKG90KSA6IEMuc2V0VGltZW91dChvdCwgUy5meC5pbnRlcnZhbCksIFMuZngudGljaygpKX0NCg0KCQlmdW5jdGlvbiBhdCgpIHtyZXR1cm4gQy5zZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1plID0gdm9pZCAwfSksIFplID0gRGF0ZS5ub3coKX0NCg0KCQlmdW5jdGlvbiBzdChlLCB0KSB7DQoJCQl2YXIgbiwgciA9IDAsIGkgPSB7aGVpZ2h0OiBlfTsNCgkJCWZvcih0ID0gdCA/IDEgOiAwOyByIDwgNDsgciArPSAyIC0gdCkgaVsibWFyZ2luIiArIChuID0gbmVbcl0pXSA9IGlbInBhZGRpbmciICsgbl0gPSBlOw0KCQkJcmV0dXJuIHQgJiYgKGkub3BhY2l0eSA9IGkud2lkdGggPSBlKSwgaQ0KCQl9DQoNCgkJZnVuY3Rpb24gdXQoZSwgdCwgbikge2Zvcih2YXIgciwgaSA9IChsdC50d2VlbmVyc1t0XSB8fCBbXSkuY29uY2F0KGx0LnR3ZWVuZXJzWyIqIl0pLCBvID0gMCwgYSA9IGkubGVuZ3RoOyBvIDwgYTsgbysrKSBpZihyID0gaVtvXS5jYWxsKG4sIHQsIGUpKSByZXR1cm4gcn0NCg0KCQlmdW5jdGlvbiBsdChvLCBlLCB0KSB7DQoJCQl2YXIgbiwNCgkJCSAgICBhLA0KCQkJICAgIHIgPSAwLA0KCQkJICAgIGkgPSBsdC5wcmVmaWx0ZXJzLmxlbmd0aCwNCgkJCSAgICBzID0gUy5EZWZlcnJlZCgpLmFsd2F5cyhmdW5jdGlvbigpIHtkZWxldGUgdS5lbGVtfSksDQoJCQkgICAgdSA9IGZ1bmN0aW9uKCkgew0KCQkJCSAgICBpZihhKSByZXR1cm4gITE7DQoJCQkJICAgIGZvcih2YXIgZSA9IFplIHx8IGF0KCksIHQgPSBNYXRoLm1heCgwLCBsLnN0YXJ0VGltZSArIGwuZHVyYXRpb24gLSBlKSwgbiA9IDEgLSAodCAvIGwuZHVyYXRpb24gfHwgMCksIHIgPSAwLCBpID0gbC50d2VlbnMubGVuZ3RoOyByIDwgaTsgcisrKSBsLnR3ZWVuc1tyXS5ydW4obik7DQoJCQkJICAgIHJldHVybiBzLm5vdGlmeVdpdGgobywgW2wsIG4sIHRdKSwgbiA8IDEgJiYgaSA/IHQgOiAoaSB8fCBzLm5vdGlmeVdpdGgobywgW2wsIDEsIDBdKSwgcy5yZXNvbHZlV2l0aChvLCBbbF0pLCAhMSkNCgkJCSAgICB9LA0KCQkJICAgIGwgPSBzLnByb21pc2Uoew0KCQkJCSAgICBlbGVtOiBvLA0KCQkJCSAgICBwcm9wczogUy5leHRlbmQoe30sIGUpLA0KCQkJCSAgICBvcHRzOiBTLmV4dGVuZCghMCwge3NwZWNpYWxFYXNpbmc6IHt9LCBlYXNpbmc6IFMuZWFzaW5nLl9kZWZhdWx0fSwgdCksDQoJCQkJICAgIG9yaWdpbmFsUHJvcGVydGllczogZSwNCgkJCQkgICAgb3JpZ2luYWxPcHRpb25zOiB0LA0KCQkJCSAgICBzdGFydFRpbWU6IFplIHx8IGF0KCksDQoJCQkJICAgIGR1cmF0aW9uOiB0LmR1cmF0aW9uLA0KCQkJCSAgICB0d2VlbnM6IFtdLA0KCQkJCSAgICBjcmVhdGVUd2VlbjogZnVuY3Rpb24oZSwgdCkgew0KCQkJCQkgICAgdmFyIG4gPSBTLlR3ZWVuKG8sIGwub3B0cywgZSwgdCwgbC5vcHRzLnNwZWNpYWxFYXNpbmdbZV0gfHwgbC5vcHRzLmVhc2luZyk7DQoJCQkJCSAgICByZXR1cm4gbC50d2VlbnMucHVzaChuKSwgbg0KCQkJCSAgICB9LA0KCQkJCSAgICBzdG9wOiBmdW5jdGlvbihlKSB7DQoJCQkJCSAgICB2YXIgdCA9IDAsIG4gPSBlID8gbC50d2VlbnMubGVuZ3RoIDogMDsNCgkJCQkJICAgIGlmKGEpIHJldHVybiB0aGlzOw0KCQkJCQkgICAgZm9yKGEgPSAhMDsgdCA8IG47IHQrKykgbC50d2VlbnNbdF0ucnVuKDEpOw0KCQkJCQkgICAgcmV0dXJuIGUgPyAocy5ub3RpZnlXaXRoKG8sIFtsLCAxLCAwXSksIHMucmVzb2x2ZVdpdGgobywgW2wsIGVdKSkgOiBzLnJlamVjdFdpdGgobywgW2wsIGVdKSwgdGhpcw0KCQkJCSAgICB9DQoJCQkgICAgfSksDQoJCQkgICAgYyA9IGwucHJvcHM7DQoJCQlmb3IoIWZ1bmN0aW9uKGUsIHQpIHsNCgkJCQl2YXIgbiwgciwgaSwgbywgYTsNCgkJCQlmb3IobiBpbiBlKSBpZihpID0gdFtyID0gWChuKV0sIG8gPSBlW25dLCBBcnJheS5pc0FycmF5KG8pICYmIChpID0gb1sxXSwgbyA9IGVbbl0gPSBvWzBdKSwgbiAhPT0gciAmJiAoZVtyXSA9IG8sIGRlbGV0ZSBlW25dKSwgKGEgPSBTLmNzc0hvb2tzW3JdKSAmJiAiZXhwYW5kIiBpbiBhKSBmb3IobiBpbiBvID0gYS5leHBhbmQobyksIGRlbGV0ZSBlW3JdLCBvKSBuIGluIGUgfHwgKGVbbl0gPSBvW25dLCB0W25dID0gaSk7IGVsc2UgdFtyXSA9IGkNCgkJCX0oYywgbC5vcHRzLnNwZWNpYWxFYXNpbmcpOyByIDwgaTsgcisrKSBpZihuID0gbHQucHJlZmlsdGVyc1tyXS5jYWxsKGwsIG8sIGMsIGwub3B0cykpIHJldHVybiBtKG4uc3RvcCkgJiYgKFMuX3F1ZXVlSG9va3MobC5lbGVtLCBsLm9wdHMucXVldWUpLnN0b3AgPSBuLnN0b3AuYmluZChuKSksIG47DQoJCQlyZXR1cm4gUy5tYXAoYywgdXQsIGwpLCBtKGwub3B0cy5zdGFydCkgJiYgbC5vcHRzLnN0YXJ0LmNhbGwobywgbCksIGwucHJvZ3Jlc3MobC5vcHRzLnByb2dyZXNzKS5kb25lKGwub3B0cy5kb25lLCBsLm9wdHMuY29tcGxldGUpLmZhaWwobC5vcHRzLmZhaWwpLmFsd2F5cyhsLm9wdHMuYWx3YXlzKSwgUy5meC50aW1lcihTLmV4dGVuZCh1LCB7ZWxlbTogbywgYW5pbTogbCwgcXVldWU6IGwub3B0cy5xdWV1ZX0pKSwgbA0KCQl9DQoNCgkJUy5BbmltYXRpb24gPSBTLmV4dGVuZChsdCwgew0KCQkJdHdlZW5lcnM6IHsNCgkJCQkiKiI6IFtmdW5jdGlvbihlLCB0KSB7DQoJCQkJCXZhciBuID0gdGhpcy5jcmVhdGVUd2VlbihlLCB0KTsNCgkJCQkJcmV0dXJuIHNlKG4uZWxlbSwgZSwgdGUuZXhlYyh0KSwgbiksIG4NCgkJCQl9XQ0KCQkJfSwgdHdlZW5lcjogZnVuY3Rpb24oZSwgdCkgew0KCQkJCW0oZSkgPyAodCA9IGUsIGUgPSBbIioiXSkgOiBlID0gZS5tYXRjaChQKTsNCgkJCQlmb3IodmFyIG4sIHIgPSAwLCBpID0gZS5sZW5ndGg7IHIgPCBpOyByKyspIG4gPSBlW3JdLCBsdC50d2VlbmVyc1tuXSA9IGx0LnR3ZWVuZXJzW25dIHx8IFtdLCBsdC50d2VlbmVyc1tuXS51bnNoaWZ0KHQpDQoJCQl9LCBwcmVmaWx0ZXJzOiBbZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJCXZhciByLCBpLCBvLCBhLCBzLCB1LCBsLCBjLCBmID0gIndpZHRoIiBpbiB0IHx8ICJoZWlnaHQiIGluIHQsIHAgPSB0aGlzLCBkID0ge30sIGggPSBlLnN0eWxlLCBnID0gZS5ub2RlVHlwZSAmJiBhZShlKSwgdiA9IFkuZ2V0KGUsICJmeHNob3ciKTsNCgkJCQlmb3IociBpbiBuLnF1ZXVlIHx8IChudWxsID09IChhID0gUy5fcXVldWVIb29rcyhlLCAiZngiKSkudW5xdWV1ZWQgJiYgKGEudW5xdWV1ZWQgPSAwLCBzID0gYS5lbXB0eS5maXJlLCBhLmVtcHR5LmZpcmUgPSBmdW5jdGlvbigpIHthLnVucXVldWVkIHx8IHMoKX0pLCBhLnVucXVldWVkKyssIHAuYWx3YXlzKGZ1bmN0aW9uKCkge3AuYWx3YXlzKGZ1bmN0aW9uKCkge2EudW5xdWV1ZWQtLSwgUy5xdWV1ZShlLCAiZngiKS5sZW5ndGggfHwgYS5lbXB0eS5maXJlKCl9KX0pKSwgdCkgaWYoaSA9IHRbcl0sIHJ0LnRlc3QoaSkpIHsNCgkJCQkJaWYoZGVsZXRlIHRbcl0sIG8gPSBvIHx8ICJ0b2dnbGUiID09PSBpLCBpID09PSAoZyA/ICJoaWRlIiA6ICJzaG93IikpIHsNCgkJCQkJCWlmKCJzaG93IiAhPT0gaSB8fCAhdiB8fCB2b2lkIDAgPT09IHZbcl0pIGNvbnRpbnVlOw0KCQkJCQkJZyA9ICEwDQoJCQkJCX0NCgkJCQkJZFtyXSA9IHYgJiYgdltyXSB8fCBTLnN0eWxlKGUsIHIpDQoJCQkJfQ0KCQkJCWlmKCh1ID0gIVMuaXNFbXB0eU9iamVjdCh0KSkgfHwgIVMuaXNFbXB0eU9iamVjdChkKSkgZm9yKHIgaW4gZiAmJiAxID09PSBlLm5vZGVUeXBlICYmIChuLm92ZXJmbG93ID0gW2gub3ZlcmZsb3csIGgub3ZlcmZsb3dYLCBoLm92ZXJmbG93WV0sIG51bGwgPT0gKGwgPSB2ICYmIHYuZGlzcGxheSkgJiYgKGwgPSBZLmdldChlLCAiZGlzcGxheSIpKSwgIm5vbmUiID09PSAoYyA9IFMuY3NzKGUsICJkaXNwbGF5IikpICYmIChsID8gYyA9IGwgOiAobGUoW2VdLCAhMCksIGwgPSBlLnN0eWxlLmRpc3BsYXkgfHwgbCwgYyA9IFMuY3NzKGUsICJkaXNwbGF5IiksIGxlKFtlXSkpKSwgKCJpbmxpbmUiID09PSBjIHx8ICJpbmxpbmUtYmxvY2siID09PSBjICYmIG51bGwgIT0gbCkgJiYgIm5vbmUiID09PSBTLmNzcyhlLCAiZmxvYXQiKSAmJiAodSB8fCAocC5kb25lKGZ1bmN0aW9uKCkge2guZGlzcGxheSA9IGx9KSwgbnVsbCA9PSBsICYmIChjID0gaC5kaXNwbGF5LCBsID0gIm5vbmUiID09PSBjID8gIiIgOiBjKSksIGguZGlzcGxheSA9ICJpbmxpbmUtYmxvY2siKSksIG4ub3ZlcmZsb3cgJiYgKGgub3ZlcmZsb3cgPSAiaGlkZGVuIiwgcC5hbHdheXMoZnVuY3Rpb24oKSB7aC5vdmVyZmxvdyA9IG4ub3ZlcmZsb3dbMF0sIGgub3ZlcmZsb3dYID0gbi5vdmVyZmxvd1sxXSwgaC5vdmVyZmxvd1kgPSBuLm92ZXJmbG93WzJdfSkpLCB1ID0gITEsIGQpIHUgfHwgKHYgPyAiaGlkZGVuIiBpbiB2ICYmIChnID0gdi5oaWRkZW4pIDogdiA9IFkuYWNjZXNzKGUsICJmeHNob3ciLCB7ZGlzcGxheTogbH0pLCBvICYmICh2LmhpZGRlbiA9ICFnKSwgZyAmJiBsZShbZV0sICEwKSwgcC5kb25lKGZ1bmN0aW9uKCkge2ZvcihyIGluIGcgfHwgbGUoW2VdKSwgWS5yZW1vdmUoZSwgImZ4c2hvdyIpLCBkKSBTLnN0eWxlKGUsIHIsIGRbcl0pfSkpLCB1ID0gdXQoZyA/IHZbcl0gOiAwLCByLCBwKSwgciBpbiB2IHx8ICh2W3JdID0gdS5zdGFydCwgZyAmJiAodS5lbmQgPSB1LnN0YXJ0LCB1LnN0YXJ0ID0gMCkpDQoJCQl9XSwgcHJlZmlsdGVyOiBmdW5jdGlvbihlLCB0KSB7dCA/IGx0LnByZWZpbHRlcnMudW5zaGlmdChlKSA6IGx0LnByZWZpbHRlcnMucHVzaChlKX0NCgkJfSksIFMuc3BlZWQgPSBmdW5jdGlvbihlLCB0LCBuKSB7DQoJCQl2YXIgciA9IGUgJiYgIm9iamVjdCIgPT0gdHlwZW9mIGUgPyBTLmV4dGVuZCh7fSwgZSkgOiB7Y29tcGxldGU6IG4gfHwgIW4gJiYgdCB8fCBtKGUpICYmIGUsIGR1cmF0aW9uOiBlLCBlYXNpbmc6IG4gJiYgdCB8fCB0ICYmICFtKHQpICYmIHR9Ow0KCQkJcmV0dXJuIFMuZngub2ZmID8gci5kdXJhdGlvbiA9IDAgOiAibnVtYmVyIiAhPSB0eXBlb2Ygci5kdXJhdGlvbiAmJiAoci5kdXJhdGlvbiBpbiBTLmZ4LnNwZWVkcyA/IHIuZHVyYXRpb24gPSBTLmZ4LnNwZWVkc1tyLmR1cmF0aW9uXSA6IHIuZHVyYXRpb24gPSBTLmZ4LnNwZWVkcy5fZGVmYXVsdCksIG51bGwgIT0gci5xdWV1ZSAmJiAhMCAhPT0gci5xdWV1ZSB8fCAoci5xdWV1ZSA9ICJmeCIpLCByLm9sZCA9IHIuY29tcGxldGUsIHIuY29tcGxldGUgPSBmdW5jdGlvbigpIHttKHIub2xkKSAmJiByLm9sZC5jYWxsKHRoaXMpLCByLnF1ZXVlICYmIFMuZGVxdWV1ZSh0aGlzLCByLnF1ZXVlKX0sIHINCgkJfSwgUy5mbi5leHRlbmQoew0KCQkJZmFkZVRvOiBmdW5jdGlvbihlLCB0LCBuLCByKSB7cmV0dXJuIHRoaXMuZmlsdGVyKGFlKS5jc3MoIm9wYWNpdHkiLCAwKS5zaG93KCkuZW5kKCkuYW5pbWF0ZSh7b3BhY2l0eTogdH0sIGUsIG4sIHIpfSwgYW5pbWF0ZTogZnVuY3Rpb24odCwgZSwgbiwgcikgew0KCQkJCXZhciBpID0gUy5pc0VtcHR5T2JqZWN0KHQpLCBvID0gUy5zcGVlZChlLCBuLCByKSwgYSA9IGZ1bmN0aW9uKCkgew0KCQkJCQl2YXIgZSA9IGx0KHRoaXMsIFMuZXh0ZW5kKHt9LCB0KSwgbyk7DQoJCQkJCShpIHx8IFkuZ2V0KHRoaXMsICJmaW5pc2giKSkgJiYgZS5zdG9wKCEwKQ0KCQkJCX07DQoJCQkJcmV0dXJuIGEuZmluaXNoID0gYSwgaSB8fCAhMSA9PT0gby5xdWV1ZSA/IHRoaXMuZWFjaChhKSA6IHRoaXMucXVldWUoby5xdWV1ZSwgYSkNCgkJCX0sIHN0b3A6IGZ1bmN0aW9uKGksIGUsIG8pIHsNCgkJCQl2YXIgYSA9IGZ1bmN0aW9uKGUpIHsNCgkJCQkJdmFyIHQgPSBlLnN0b3A7DQoJCQkJCWRlbGV0ZSBlLnN0b3AsIHQobykNCgkJCQl9Ow0KCQkJCXJldHVybiAic3RyaW5nIiAhPSB0eXBlb2YgaSAmJiAobyA9IGUsIGUgPSBpLCBpID0gdm9pZCAwKSwgZSAmJiB0aGlzLnF1ZXVlKGkgfHwgImZ4IiwgW10pLCB0aGlzLmVhY2goZnVuY3Rpb24oKSB7DQoJCQkJCXZhciBlID0gITAsIHQgPSBudWxsICE9IGkgJiYgaSArICJxdWV1ZUhvb2tzIiwgbiA9IFMudGltZXJzLCByID0gWS5nZXQodGhpcyk7DQoJCQkJCWlmKHQpIHJbdF0gJiYgclt0XS5zdG9wICYmIGEoclt0XSk7IGVsc2UgZm9yKHQgaW4gcikgclt0XSAmJiByW3RdLnN0b3AgJiYgaXQudGVzdCh0KSAmJiBhKHJbdF0pOw0KCQkJCQlmb3IodCA9IG4ubGVuZ3RoOyB0LS07KSBuW3RdLmVsZW0gIT09IHRoaXMgfHwgbnVsbCAhPSBpICYmIG5bdF0ucXVldWUgIT09IGkgfHwgKG5bdF0uYW5pbS5zdG9wKG8pLCBlID0gITEsIG4uc3BsaWNlKHQsIDEpKTsNCgkJCQkJIWUgJiYgbyB8fCBTLmRlcXVldWUodGhpcywgaSkNCgkJCQl9KQ0KCQkJfSwgZmluaXNoOiBmdW5jdGlvbihhKSB7DQoJCQkJcmV0dXJuICExICE9PSBhICYmIChhID0gYSB8fCAiZngiKSwgdGhpcy5lYWNoKGZ1bmN0aW9uKCkgew0KCQkJCQl2YXIgZSwgdCA9IFkuZ2V0KHRoaXMpLCBuID0gdFthICsgInF1ZXVlIl0sIHIgPSB0W2EgKyAicXVldWVIb29rcyJdLCBpID0gUy50aW1lcnMsIG8gPSBuID8gbi5sZW5ndGggOiAwOw0KCQkJCQlmb3IodC5maW5pc2ggPSAhMCwgUy5xdWV1ZSh0aGlzLCBhLCBbXSksIHIgJiYgci5zdG9wICYmIHIuc3RvcC5jYWxsKHRoaXMsICEwKSwgZSA9IGkubGVuZ3RoOyBlLS07KSBpW2VdLmVsZW0gPT09IHRoaXMgJiYgaVtlXS5xdWV1ZSA9PT0gYSAmJiAoaVtlXS5hbmltLnN0b3AoITApLCBpLnNwbGljZShlLCAxKSk7DQoJCQkJCWZvcihlID0gMDsgZSA8IG87IGUrKykgbltlXSAmJiBuW2VdLmZpbmlzaCAmJiBuW2VdLmZpbmlzaC5jYWxsKHRoaXMpOw0KCQkJCQlkZWxldGUgdC5maW5pc2gNCgkJCQl9KQ0KCQkJfQ0KCQl9KSwgUy5lYWNoKFsidG9nZ2xlIiwgInNob3ciLCAiaGlkZSJdLCBmdW5jdGlvbihlLCByKSB7DQoJCQl2YXIgaSA9IFMuZm5bcl07DQoJCQlTLmZuW3JdID0gZnVuY3Rpb24oZSwgdCwgbikge3JldHVybiBudWxsID09IGUgfHwgImJvb2xlYW4iID09IHR5cGVvZiBlID8gaS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIDogdGhpcy5hbmltYXRlKHN0KHIsICEwKSwgZSwgdCwgbil9DQoJCX0pLCBTLmVhY2goew0KCQkJc2xpZGVEb3duOiBzdCgic2hvdyIpLA0KCQkJc2xpZGVVcDogc3QoImhpZGUiKSwNCgkJCXNsaWRlVG9nZ2xlOiBzdCgidG9nZ2xlIiksDQoJCQlmYWRlSW46IHtvcGFjaXR5OiAic2hvdyJ9LA0KCQkJZmFkZU91dDoge29wYWNpdHk6ICJoaWRlIn0sDQoJCQlmYWRlVG9nZ2xlOiB7b3BhY2l0eTogInRvZ2dsZSJ9DQoJCX0sIGZ1bmN0aW9uKGUsIHIpIHtTLmZuW2VdID0gZnVuY3Rpb24oZSwgdCwgbikge3JldHVybiB0aGlzLmFuaW1hdGUociwgZSwgdCwgbil9fSksIFMudGltZXJzID0gW10sIFMuZngudGljayA9IGZ1bmN0aW9uKCkgew0KCQkJdmFyIGUsIHQgPSAwLCBuID0gUy50aW1lcnM7DQoJCQlmb3IoWmUgPSBEYXRlLm5vdygpOyB0IDwgbi5sZW5ndGg7IHQrKykgKGUgPSBuW3RdKSgpIHx8IG5bdF0gIT09IGUgfHwgbi5zcGxpY2UodC0tLCAxKTsNCgkJCW4ubGVuZ3RoIHx8IFMuZnguc3RvcCgpLCBaZSA9IHZvaWQgMA0KCQl9LCBTLmZ4LnRpbWVyID0gZnVuY3Rpb24oZSkge1MudGltZXJzLnB1c2goZSksIFMuZnguc3RhcnQoKX0sIFMuZnguaW50ZXJ2YWwgPSAxMywgUy5meC5zdGFydCA9IGZ1bmN0aW9uKCkge2V0IHx8IChldCA9ICEwLCBvdCgpKX0sIFMuZnguc3RvcCA9IGZ1bmN0aW9uKCkge2V0ID0gbnVsbH0sIFMuZnguc3BlZWRzID0gew0KCQkJc2xvdzogNjAwLA0KCQkJZmFzdDogMjAwLA0KCQkJX2RlZmF1bHQ6IDQwMA0KCQl9LCBTLmZuLmRlbGF5ID0gZnVuY3Rpb24ociwgZSkgew0KCQkJcmV0dXJuIHIgPSBTLmZ4ICYmIFMuZnguc3BlZWRzW3JdIHx8IHIsIGUgPSBlIHx8ICJmeCIsIHRoaXMucXVldWUoZSwgZnVuY3Rpb24oZSwgdCkgew0KCQkJCXZhciBuID0gQy5zZXRUaW1lb3V0KGUsIHIpOw0KCQkJCXQuc3RvcCA9IGZ1bmN0aW9uKCkge0MuY2xlYXJUaW1lb3V0KG4pfQ0KCQkJfSkNCgkJfSwgdHQgPSBFLmNyZWF0ZUVsZW1lbnQoImlucHV0IiksIG50ID0gRS5jcmVhdGVFbGVtZW50KCJzZWxlY3QiKS5hcHBlbmRDaGlsZChFLmNyZWF0ZUVsZW1lbnQoIm9wdGlvbiIpKSwgdHQudHlwZSA9ICJjaGVja2JveCIsIHkuY2hlY2tPbiA9ICIiICE9PSB0dC52YWx1ZSwgeS5vcHRTZWxlY3RlZCA9IG50LnNlbGVjdGVkLCAodHQgPSBFLmNyZWF0ZUVsZW1lbnQoImlucHV0IikpLnZhbHVlID0gInQiLCB0dC50eXBlID0gInJhZGlvIiwgeS5yYWRpb1ZhbHVlID0gInQiID09PSB0dC52YWx1ZTsNCgkJdmFyIGN0LCBmdCA9IFMuZXhwci5hdHRySGFuZGxlOw0KCQlTLmZuLmV4dGVuZCh7YXR0cjogZnVuY3Rpb24oZSwgdCkge3JldHVybiAkKHRoaXMsIFMuYXR0ciwgZSwgdCwgMSA8IGFyZ3VtZW50cy5sZW5ndGgpfSwgcmVtb3ZlQXR0cjogZnVuY3Rpb24oZSkge3JldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7Uy5yZW1vdmVBdHRyKHRoaXMsIGUpfSl9fSksIFMuZXh0ZW5kKHsNCgkJCWF0dHI6IGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQl2YXIgciwgaSwgbyA9IGUubm9kZVR5cGU7DQoJCQkJaWYoMyAhPT0gbyAmJiA4ICE9PSBvICYmIDIgIT09IG8pIHJldHVybiAidW5kZWZpbmVkIiA9PSB0eXBlb2YgZS5nZXRBdHRyaWJ1dGUgPyBTLnByb3AoZSwgdCwgbikgOiAoMSA9PT0gbyAmJiBTLmlzWE1MRG9jKGUpIHx8IChpID0gUy5hdHRySG9va3NbdC50b0xvd2VyQ2FzZSgpXSB8fCAoUy5leHByLm1hdGNoLmJvb2wudGVzdCh0KSA/IGN0IDogdm9pZCAwKSksIHZvaWQgMCAhPT0gbiA/IG51bGwgPT09IG4gPyB2b2lkIFMucmVtb3ZlQXR0cihlLCB0KSA6IGkgJiYgInNldCIgaW4gaSAmJiB2b2lkIDAgIT09IChyID0gaS5zZXQoZSwgbiwgdCkpID8gciA6IChlLnNldEF0dHJpYnV0ZSh0LCBuICsgIiIpLCBuKSA6IGkgJiYgImdldCIgaW4gaSAmJiBudWxsICE9PSAociA9IGkuZ2V0KGUsIHQpKSA/IHIgOiBudWxsID09IChyID0gUy5maW5kLmF0dHIoZSwgdCkpID8gdm9pZCAwIDogcikNCgkJCX0sIGF0dHJIb29rczogew0KCQkJCXR5cGU6IHsNCgkJCQkJc2V0OiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJCQlpZigheS5yYWRpb1ZhbHVlICYmICJyYWRpbyIgPT09IHQgJiYgQShlLCAiaW5wdXQiKSkgew0KCQkJCQkJCXZhciBuID0gZS52YWx1ZTsNCgkJCQkJCQlyZXR1cm4gZS5zZXRBdHRyaWJ1dGUoInR5cGUiLCB0KSwgbiAmJiAoZS52YWx1ZSA9IG4pLCB0DQoJCQkJCQl9DQoJCQkJCX0NCgkJCQl9DQoJCQl9LCByZW1vdmVBdHRyOiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJdmFyIG4sIHIgPSAwLCBpID0gdCAmJiB0Lm1hdGNoKFApOw0KCQkJCWlmKGkgJiYgMSA9PT0gZS5ub2RlVHlwZSkgd2hpbGUobiA9IGlbcisrXSkgZS5yZW1vdmVBdHRyaWJ1dGUobikNCgkJCX0NCgkJfSksIGN0ID0ge3NldDogZnVuY3Rpb24oZSwgdCwgbikge3JldHVybiAhMSA9PT0gdCA/IFMucmVtb3ZlQXR0cihlLCBuKSA6IGUuc2V0QXR0cmlidXRlKG4sIG4pLCBufX0sIFMuZWFjaChTLmV4cHIubWF0Y2guYm9vbC5zb3VyY2UubWF0Y2goL1x3Ky9nKSwgZnVuY3Rpb24oZSwgdCkgew0KCQkJdmFyIGEgPSBmdFt0XSB8fCBTLmZpbmQuYXR0cjsNCgkJCWZ0W3RdID0gZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJCXZhciByLCBpLCBvID0gdC50b0xvd2VyQ2FzZSgpOw0KCQkJCXJldHVybiBuIHx8IChpID0gZnRbb10sIGZ0W29dID0gciwgciA9IG51bGwgIT0gYShlLCB0LCBuKSA/IG8gOiBudWxsLCBmdFtvXSA9IGkpLCByDQoJCQl9DQoJCX0pOw0KCQl2YXIgcHQgPSAvXig/OmlucHV0fHNlbGVjdHx0ZXh0YXJlYXxidXR0b24pJC9pLCBkdCA9IC9eKD86YXxhcmVhKSQvaTsNCg0KCQlmdW5jdGlvbiBodChlKSB7cmV0dXJuIChlLm1hdGNoKFApIHx8IFtdKS5qb2luKCIgIil9DQoNCgkJZnVuY3Rpb24gZ3QoZSkge3JldHVybiBlLmdldEF0dHJpYnV0ZSAmJiBlLmdldEF0dHJpYnV0ZSgiY2xhc3MiKSB8fCAiIn0NCg0KCQlmdW5jdGlvbiB2dChlKSB7cmV0dXJuIEFycmF5LmlzQXJyYXkoZSkgPyBlIDogInN0cmluZyIgPT0gdHlwZW9mIGUgJiYgZS5tYXRjaChQKSB8fCBbXX0NCg0KCQlTLmZuLmV4dGVuZCh7cHJvcDogZnVuY3Rpb24oZSwgdCkge3JldHVybiAkKHRoaXMsIFMucHJvcCwgZSwgdCwgMSA8IGFyZ3VtZW50cy5sZW5ndGgpfSwgcmVtb3ZlUHJvcDogZnVuY3Rpb24oZSkge3JldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7ZGVsZXRlIHRoaXNbUy5wcm9wRml4W2VdIHx8IGVdfSl9fSksIFMuZXh0ZW5kKHsNCgkJCXByb3A6IGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQl2YXIgciwgaSwgbyA9IGUubm9kZVR5cGU7DQoJCQkJaWYoMyAhPT0gbyAmJiA4ICE9PSBvICYmIDIgIT09IG8pIHJldHVybiAxID09PSBvICYmIFMuaXNYTUxEb2MoZSkgfHwgKHQgPSBTLnByb3BGaXhbdF0gfHwgdCwgaSA9IFMucHJvcEhvb2tzW3RdKSwgdm9pZCAwICE9PSBuID8gaSAmJiAic2V0IiBpbiBpICYmIHZvaWQgMCAhPT0gKHIgPSBpLnNldChlLCBuLCB0KSkgPyByIDogZVt0XSA9IG4gOiBpICYmICJnZXQiIGluIGkgJiYgbnVsbCAhPT0gKHIgPSBpLmdldChlLCB0KSkgPyByIDogZVt0XQ0KCQkJfSwgcHJvcEhvb2tzOiB7DQoJCQkJdGFiSW5kZXg6IHsNCgkJCQkJZ2V0OiBmdW5jdGlvbihlKSB7DQoJCQkJCQl2YXIgdCA9IFMuZmluZC5hdHRyKGUsICJ0YWJpbmRleCIpOw0KCQkJCQkJcmV0dXJuIHQgPyBwYXJzZUludCh0LCAxMCkgOiBwdC50ZXN0KGUubm9kZU5hbWUpIHx8IGR0LnRlc3QoZS5ub2RlTmFtZSkgJiYgZS5ocmVmID8gMCA6IC0xDQoJCQkJCX0NCgkJCQl9DQoJCQl9LCBwcm9wRml4OiB7ImZvciI6ICJodG1sRm9yIiwgImNsYXNzIjogImNsYXNzTmFtZSJ9DQoJCX0pLCB5Lm9wdFNlbGVjdGVkIHx8IChTLnByb3BIb29rcy5zZWxlY3RlZCA9IHsNCgkJCWdldDogZnVuY3Rpb24oZSkgew0KCQkJCXZhciB0ID0gZS5wYXJlbnROb2RlOw0KCQkJCXJldHVybiB0ICYmIHQucGFyZW50Tm9kZSAmJiB0LnBhcmVudE5vZGUuc2VsZWN0ZWRJbmRleCwgbnVsbA0KCQkJfSwgc2V0OiBmdW5jdGlvbihlKSB7DQoJCQkJdmFyIHQgPSBlLnBhcmVudE5vZGU7DQoJCQkJdCAmJiAodC5zZWxlY3RlZEluZGV4LCB0LnBhcmVudE5vZGUgJiYgdC5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXgpDQoJCQl9DQoJCX0pLCBTLmVhY2goWyJ0YWJJbmRleCIsICJyZWFkT25seSIsICJtYXhMZW5ndGgiLCAiY2VsbFNwYWNpbmciLCAiY2VsbFBhZGRpbmciLCAicm93U3BhbiIsICJjb2xTcGFuIiwgInVzZU1hcCIsICJmcmFtZUJvcmRlciIsICJjb250ZW50RWRpdGFibGUiXSwgZnVuY3Rpb24oKSB7Uy5wcm9wRml4W3RoaXMudG9Mb3dlckNhc2UoKV0gPSB0aGlzfSksIFMuZm4uZXh0ZW5kKHsNCgkJCWFkZENsYXNzOiBmdW5jdGlvbih0KSB7DQoJCQkJdmFyIGUsIG4sIHIsIGksIG8sIGEsIHMsIHUgPSAwOw0KCQkJCWlmKG0odCkpIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oZSkge1ModGhpcykuYWRkQ2xhc3ModC5jYWxsKHRoaXMsIGUsIGd0KHRoaXMpKSl9KTsNCgkJCQlpZigoZSA9IHZ0KHQpKS5sZW5ndGgpIHdoaWxlKG4gPSB0aGlzW3UrK10pIGlmKGkgPSBndChuKSwgciA9IDEgPT09IG4ubm9kZVR5cGUgJiYgIiAiICsgaHQoaSkgKyAiICIpIHsNCgkJCQkJYSA9IDA7DQoJCQkJCXdoaWxlKG8gPSBlW2ErK10pIHIuaW5kZXhPZigiICIgKyBvICsgIiAiKSA8IDAgJiYgKHIgKz0gbyArICIgIik7DQoJCQkJCWkgIT09IChzID0gaHQocikpICYmIG4uc2V0QXR0cmlidXRlKCJjbGFzcyIsIHMpDQoJCQkJfQ0KCQkJCXJldHVybiB0aGlzDQoJCQl9LCByZW1vdmVDbGFzczogZnVuY3Rpb24odCkgew0KCQkJCXZhciBlLCBuLCByLCBpLCBvLCBhLCBzLCB1ID0gMDsNCgkJCQlpZihtKHQpKSByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKGUpIHtTKHRoaXMpLnJlbW92ZUNsYXNzKHQuY2FsbCh0aGlzLCBlLCBndCh0aGlzKSkpfSk7DQoJCQkJaWYoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB0aGlzLmF0dHIoImNsYXNzIiwgIiIpOw0KCQkJCWlmKChlID0gdnQodCkpLmxlbmd0aCkgd2hpbGUobiA9IHRoaXNbdSsrXSkgaWYoaSA9IGd0KG4pLCByID0gMSA9PT0gbi5ub2RlVHlwZSAmJiAiICIgKyBodChpKSArICIgIikgew0KCQkJCQlhID0gMDsNCgkJCQkJd2hpbGUobyA9IGVbYSsrXSkgd2hpbGUoLTEgPCByLmluZGV4T2YoIiAiICsgbyArICIgIikpIHIgPSByLnJlcGxhY2UoIiAiICsgbyArICIgIiwgIiAiKTsNCgkJCQkJaSAhPT0gKHMgPSBodChyKSkgJiYgbi5zZXRBdHRyaWJ1dGUoImNsYXNzIiwgcykNCgkJCQl9DQoJCQkJcmV0dXJuIHRoaXMNCgkJCX0sIHRvZ2dsZUNsYXNzOiBmdW5jdGlvbihpLCB0KSB7DQoJCQkJdmFyIG8gPSB0eXBlb2YgaSwgYSA9ICJzdHJpbmciID09PSBvIHx8IEFycmF5LmlzQXJyYXkoaSk7DQoJCQkJcmV0dXJuICJib29sZWFuIiA9PSB0eXBlb2YgdCAmJiBhID8gdCA/IHRoaXMuYWRkQ2xhc3MoaSkgOiB0aGlzLnJlbW92ZUNsYXNzKGkpIDogbShpKSA/IHRoaXMuZWFjaChmdW5jdGlvbihlKSB7Uyh0aGlzKS50b2dnbGVDbGFzcyhpLmNhbGwodGhpcywgZSwgZ3QodGhpcyksIHQpLCB0KX0pIDogdGhpcy5lYWNoKGZ1bmN0aW9uKCkgew0KCQkJCQl2YXIgZSwgdCwgbiwgcjsNCgkJCQkJaWYoYSkgew0KCQkJCQkJdCA9IDAsIG4gPSBTKHRoaXMpLCByID0gdnQoaSk7DQoJCQkJCQl3aGlsZShlID0gclt0KytdKSBuLmhhc0NsYXNzKGUpID8gbi5yZW1vdmVDbGFzcyhlKSA6IG4uYWRkQ2xhc3MoZSkNCgkJCQkJfSBlbHNlIHZvaWQgMCAhPT0gaSAmJiAiYm9vbGVhbiIgIT09IG8gfHwgKChlID0gZ3QodGhpcykpICYmIFkuc2V0KHRoaXMsICJfX2NsYXNzTmFtZV9fIiwgZSksIHRoaXMuc2V0QXR0cmlidXRlICYmIHRoaXMuc2V0QXR0cmlidXRlKCJjbGFzcyIsIGUgfHwgITEgPT09IGkgPyAiIiA6IFkuZ2V0KHRoaXMsICJfX2NsYXNzTmFtZV9fIikgfHwgIiIpKQ0KCQkJCX0pDQoJCQl9LCBoYXNDbGFzczogZnVuY3Rpb24oZSkgew0KCQkJCXZhciB0LCBuLCByID0gMDsNCgkJCQl0ID0gIiAiICsgZSArICIgIjsNCgkJCQl3aGlsZShuID0gdGhpc1tyKytdKSBpZigxID09PSBuLm5vZGVUeXBlICYmIC0xIDwgKCIgIiArIGh0KGd0KG4pKSArICIgIikuaW5kZXhPZih0KSkgcmV0dXJuICEwOw0KCQkJCXJldHVybiAhMQ0KCQkJfQ0KCQl9KTsNCgkJdmFyIHl0ID0gL1xyL2c7DQoJCVMuZm4uZXh0ZW5kKHsNCgkJCXZhbDogZnVuY3Rpb24obikgew0KCQkJCXZhciByLCBlLCBpLCB0ID0gdGhpc1swXTsNCgkJCQlyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChpID0gbShuKSwgdGhpcy5lYWNoKGZ1bmN0aW9uKGUpIHsNCgkJCQkJdmFyIHQ7DQoJCQkJCTEgPT09IHRoaXMubm9kZVR5cGUgJiYgKG51bGwgPT0gKHQgPSBpID8gbi5jYWxsKHRoaXMsIGUsIFModGhpcykudmFsKCkpIDogbikgPyB0ID0gIiIgOiAibnVtYmVyIiA9PSB0eXBlb2YgdCA/IHQgKz0gIiIgOiBBcnJheS5pc0FycmF5KHQpICYmICh0ID0gUy5tYXAodCwgZnVuY3Rpb24oZSkge3JldHVybiBudWxsID09IGUgPyAiIiA6IGUgKyAiIn0pKSwgKHIgPSBTLnZhbEhvb2tzW3RoaXMudHlwZV0gfHwgUy52YWxIb29rc1t0aGlzLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCldKSAmJiAic2V0IiBpbiByICYmIHZvaWQgMCAhPT0gci5zZXQodGhpcywgdCwgInZhbHVlIikgfHwgKHRoaXMudmFsdWUgPSB0KSkNCgkJCQl9KSkgOiB0ID8gKHIgPSBTLnZhbEhvb2tzW3QudHlwZV0gfHwgUy52YWxIb29rc1t0Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCldKSAmJiAiZ2V0IiBpbiByICYmIHZvaWQgMCAhPT0gKGUgPSByLmdldCh0LCAidmFsdWUiKSkgPyBlIDogInN0cmluZyIgPT0gdHlwZW9mIChlID0gdC52YWx1ZSkgPyBlLnJlcGxhY2UoeXQsICIiKSA6IG51bGwgPT0gZSA/ICIiIDogZSA6IHZvaWQgMA0KCQkJfQ0KCQl9KSwgUy5leHRlbmQoew0KCQkJdmFsSG9va3M6IHsNCgkJCQlvcHRpb246IHsNCgkJCQkJZ2V0OiBmdW5jdGlvbihlKSB7DQoJCQkJCQl2YXIgdCA9IFMuZmluZC5hdHRyKGUsICJ2YWx1ZSIpOw0KCQkJCQkJcmV0dXJuIG51bGwgIT0gdCA/IHQgOiBodChTLnRleHQoZSkpDQoJCQkJCX0NCgkJCQl9LCBzZWxlY3Q6IHsNCgkJCQkJZ2V0OiBmdW5jdGlvbihlKSB7DQoJCQkJCQl2YXIgdCwgbiwgciwgaSA9IGUub3B0aW9ucywgbyA9IGUuc2VsZWN0ZWRJbmRleCwgYSA9ICJzZWxlY3Qtb25lIiA9PT0gZS50eXBlLCBzID0gYSA/IG51bGwgOiBbXSwgdSA9IGEgPyBvICsgMSA6IGkubGVuZ3RoOw0KCQkJCQkJZm9yKHIgPSBvIDwgMCA/IHUgOiBhID8gbyA6IDA7IHIgPCB1OyByKyspIGlmKCgobiA9IGlbcl0pLnNlbGVjdGVkIHx8IHIgPT09IG8pICYmICFuLmRpc2FibGVkICYmICghbi5wYXJlbnROb2RlLmRpc2FibGVkIHx8ICFBKG4ucGFyZW50Tm9kZSwgIm9wdGdyb3VwIikpKSB7DQoJCQkJCQkJaWYodCA9IFMobikudmFsKCksIGEpIHJldHVybiB0Ow0KCQkJCQkJCXMucHVzaCh0KQ0KCQkJCQkJfQ0KCQkJCQkJcmV0dXJuIHMNCgkJCQkJfSwgc2V0OiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJCQl2YXIgbiwgciwgaSA9IGUub3B0aW9ucywgbyA9IFMubWFrZUFycmF5KHQpLCBhID0gaS5sZW5ndGg7DQoJCQkJCQl3aGlsZShhLS0pICgociA9IGlbYV0pLnNlbGVjdGVkID0gLTEgPCBTLmluQXJyYXkoUy52YWxIb29rcy5vcHRpb24uZ2V0KHIpLCBvKSkgJiYgKG4gPSAhMCk7DQoJCQkJCQlyZXR1cm4gbiB8fCAoZS5zZWxlY3RlZEluZGV4ID0gLTEpLCBvDQoJCQkJCX0NCgkJCQl9DQoJCQl9DQoJCX0pLCBTLmVhY2goWyJyYWRpbyIsICJjaGVja2JveCJdLCBmdW5jdGlvbigpIHtTLnZhbEhvb2tzW3RoaXNdID0ge3NldDogZnVuY3Rpb24oZSwgdCkge2lmKEFycmF5LmlzQXJyYXkodCkpIHJldHVybiBlLmNoZWNrZWQgPSAtMSA8IFMuaW5BcnJheShTKGUpLnZhbCgpLCB0KX19LCB5LmNoZWNrT24gfHwgKFMudmFsSG9va3NbdGhpc10uZ2V0ID0gZnVuY3Rpb24oZSkge3JldHVybiBudWxsID09PSBlLmdldEF0dHJpYnV0ZSgidmFsdWUiKSA/ICJvbiIgOiBlLnZhbHVlfSl9KSwgeS5mb2N1c2luID0gIm9uZm9jdXNpbiIgaW4gQzsNCgkJdmFyIG10ID0gL14oPzpmb2N1c2luZm9jdXN8Zm9jdXNvdXRibHVyKSQvLCB4dCA9IGZ1bmN0aW9uKGUpIHtlLnN0b3BQcm9wYWdhdGlvbigpfTsNCgkJUy5leHRlbmQoUy5ldmVudCwgew0KCQkJdHJpZ2dlcjogZnVuY3Rpb24oZSwgdCwgbiwgcikgew0KCQkJCXZhciBpLCBvLCBhLCBzLCB1LCBsLCBjLCBmLCBwID0gW24gfHwgRV0sIGQgPSB2LmNhbGwoZSwgInR5cGUiKSA/IGUudHlwZSA6IGUsIGggPSB2LmNhbGwoZSwgIm5hbWVzcGFjZSIpID8gZS5uYW1lc3BhY2Uuc3BsaXQoIi4iKSA6IFtdOw0KCQkJCWlmKG8gPSBmID0gYSA9IG4gPSBuIHx8IEUsIDMgIT09IG4ubm9kZVR5cGUgJiYgOCAhPT0gbi5ub2RlVHlwZSAmJiAhbXQudGVzdChkICsgUy5ldmVudC50cmlnZ2VyZWQpICYmICgtMSA8IGQuaW5kZXhPZigiLiIpICYmIChkID0gKGggPSBkLnNwbGl0KCIuIikpLnNoaWZ0KCksIGguc29ydCgpKSwgdSA9IGQuaW5kZXhPZigiOiIpIDwgMCAmJiAib24iICsgZCwgKGUgPSBlW1MuZXhwYW5kb10gPyBlIDogbmV3IFMuRXZlbnQoZCwgIm9iamVjdCIgPT0gdHlwZW9mIGUgJiYgZSkpLmlzVHJpZ2dlciA9IHIgPyAyIDogMywgZS5uYW1lc3BhY2UgPSBoLmpvaW4oIi4iKSwgZS5ybmFtZXNwYWNlID0gZS5uYW1lc3BhY2UgPyBuZXcgUmVnRXhwKCIoXnxcXC4pIiArIGguam9pbigiXFwuKD86LipcXC58KSIpICsgIihcXC58JCkiKSA6IG51bGwsIGUucmVzdWx0ID0gdm9pZCAwLCBlLnRhcmdldCB8fCAoZS50YXJnZXQgPSBuKSwgdCA9IG51bGwgPT0gdCA/IFtlXSA6IFMubWFrZUFycmF5KHQsIFtlXSksIGMgPSBTLmV2ZW50LnNwZWNpYWxbZF0gfHwge30sIHIgfHwgIWMudHJpZ2dlciB8fCAhMSAhPT0gYy50cmlnZ2VyLmFwcGx5KG4sIHQpKSkgew0KCQkJCQlpZighciAmJiAhYy5ub0J1YmJsZSAmJiAheChuKSkgew0KCQkJCQkJZm9yKHMgPSBjLmRlbGVnYXRlVHlwZSB8fCBkLCBtdC50ZXN0KHMgKyBkKSB8fCAobyA9IG8ucGFyZW50Tm9kZSk7IG87IG8gPSBvLnBhcmVudE5vZGUpIHAucHVzaChvKSwgYSA9IG87DQoJCQkJCQlhID09PSAobi5vd25lckRvY3VtZW50IHx8IEUpICYmIHAucHVzaChhLmRlZmF1bHRWaWV3IHx8IGEucGFyZW50V2luZG93IHx8IEMpDQoJCQkJCX0NCgkJCQkJaSA9IDA7DQoJCQkJCXdoaWxlKChvID0gcFtpKytdKSAmJiAhZS5pc1Byb3BhZ2F0aW9uU3RvcHBlZCgpKSBmID0gbywgZS50eXBlID0gMSA8IGkgPyBzIDogYy5iaW5kVHlwZSB8fCBkLCAobCA9IChZLmdldChvLCAiZXZlbnRzIikgfHwgT2JqZWN0LmNyZWF0ZShudWxsKSlbZS50eXBlXSAmJiBZLmdldChvLCAiaGFuZGxlIikpICYmIGwuYXBwbHkobywgdCksIChsID0gdSAmJiBvW3VdKSAmJiBsLmFwcGx5ICYmIFYobykgJiYgKGUucmVzdWx0ID0gbC5hcHBseShvLCB0KSwgITEgPT09IGUucmVzdWx0ICYmIGUucHJldmVudERlZmF1bHQoKSk7DQoJCQkJCXJldHVybiBlLnR5cGUgPSBkLCByIHx8IGUuaXNEZWZhdWx0UHJldmVudGVkKCkgfHwgYy5fZGVmYXVsdCAmJiAhMSAhPT0gYy5fZGVmYXVsdC5hcHBseShwLnBvcCgpLCB0KSB8fCAhVihuKSB8fCB1ICYmIG0obltkXSkgJiYgIXgobikgJiYgKChhID0gblt1XSkgJiYgKG5bdV0gPSBudWxsKSwgUy5ldmVudC50cmlnZ2VyZWQgPSBkLCBlLmlzUHJvcGFnYXRpb25TdG9wcGVkKCkgJiYgZi5hZGRFdmVudExpc3RlbmVyKGQsIHh0KSwgbltkXSgpLCBlLmlzUHJvcGFnYXRpb25TdG9wcGVkKCkgJiYgZi5yZW1vdmVFdmVudExpc3RlbmVyKGQsIHh0KSwgUy5ldmVudC50cmlnZ2VyZWQgPSB2b2lkIDAsIGEgJiYgKG5bdV0gPSBhKSksIGUucmVzdWx0DQoJCQkJfQ0KCQkJfSwgc2ltdWxhdGU6IGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQl2YXIgciA9IFMuZXh0ZW5kKG5ldyBTLkV2ZW50LCBuLCB7dHlwZTogZSwgaXNTaW11bGF0ZWQ6ICEwfSk7DQoJCQkJUy5ldmVudC50cmlnZ2VyKHIsIG51bGwsIHQpDQoJCQl9DQoJCX0pLCBTLmZuLmV4dGVuZCh7DQoJCQl0cmlnZ2VyOiBmdW5jdGlvbihlLCB0KSB7cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpIHtTLmV2ZW50LnRyaWdnZXIoZSwgdCwgdGhpcyl9KX0sIHRyaWdnZXJIYW5kbGVyOiBmdW5jdGlvbihlLCB0KSB7DQoJCQkJdmFyIG4gPSB0aGlzWzBdOw0KCQkJCWlmKG4pIHJldHVybiBTLmV2ZW50LnRyaWdnZXIoZSwgdCwgbiwgITApDQoJCQl9DQoJCX0pLCB5LmZvY3VzaW4gfHwgUy5lYWNoKHtmb2N1czogImZvY3VzaW4iLCBibHVyOiAiZm9jdXNvdXQifSwgZnVuY3Rpb24obiwgcikgew0KCQkJdmFyIGkgPSBmdW5jdGlvbihlKSB7Uy5ldmVudC5zaW11bGF0ZShyLCBlLnRhcmdldCwgUy5ldmVudC5maXgoZSkpfTsNCgkJCVMuZXZlbnQuc3BlY2lhbFtyXSA9IHsNCgkJCQlzZXR1cDogZnVuY3Rpb24oKSB7DQoJCQkJCXZhciBlID0gdGhpcy5vd25lckRvY3VtZW50IHx8IHRoaXMuZG9jdW1lbnQgfHwgdGhpcywgdCA9IFkuYWNjZXNzKGUsIHIpOw0KCQkJCQl0IHx8IGUuYWRkRXZlbnRMaXN0ZW5lcihuLCBpLCAhMCksIFkuYWNjZXNzKGUsIHIsICh0IHx8IDApICsgMSkNCgkJCQl9LCB0ZWFyZG93bjogZnVuY3Rpb24oKSB7DQoJCQkJCXZhciBlID0gdGhpcy5vd25lckRvY3VtZW50IHx8IHRoaXMuZG9jdW1lbnQgfHwgdGhpcywgdCA9IFkuYWNjZXNzKGUsIHIpIC0gMTsNCgkJCQkJdCA/IFkuYWNjZXNzKGUsIHIsIHQpIDogKGUucmVtb3ZlRXZlbnRMaXN0ZW5lcihuLCBpLCAhMCksIFkucmVtb3ZlKGUsIHIpKQ0KCQkJCX0NCgkJCX0NCgkJfSk7DQoJCXZhciBidCA9IEMubG9jYXRpb24sIHd0ID0ge2d1aWQ6IERhdGUubm93KCl9LCBUdCA9IC9cPy87DQoJCVMucGFyc2VYTUwgPSBmdW5jdGlvbihlKSB7DQoJCQl2YXIgdCwgbjsNCgkJCWlmKCFlIHx8ICJzdHJpbmciICE9IHR5cGVvZiBlKSByZXR1cm4gbnVsbDsNCgkJCXRyeSB7dCA9IChuZXcgQy5ET01QYXJzZXIpLnBhcnNlRnJvbVN0cmluZyhlLCAidGV4dC94bWwiKX0gY2F0Y2goZSkge30NCgkJCXJldHVybiBuID0gdCAmJiB0LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJwYXJzZXJlcnJvciIpWzBdLCB0ICYmICFuIHx8IFMuZXJyb3IoIkludmFsaWQgWE1MOiAiICsgKG4gPyBTLm1hcChuLmNoaWxkTm9kZXMsIGZ1bmN0aW9uKGUpIHtyZXR1cm4gZS50ZXh0Q29udGVudH0pLmpvaW4oIlxuIikgOiBlKSksIHQNCgkJfTsNCgkJdmFyIEN0ID0gL1xbXF0kLywgRXQgPSAvXHI/XG4vZywgU3QgPSAvXig/OnN1Ym1pdHxidXR0b258aW1hZ2V8cmVzZXR8ZmlsZSkkL2ksIGt0ID0gL14oPzppbnB1dHxzZWxlY3R8dGV4dGFyZWF8a2V5Z2VuKS9pOw0KDQoJCWZ1bmN0aW9uIEF0KG4sIGUsIHIsIGkpIHsNCgkJCXZhciB0Ow0KCQkJaWYoQXJyYXkuaXNBcnJheShlKSkgUy5lYWNoKGUsIGZ1bmN0aW9uKGUsIHQpIHtyIHx8IEN0LnRlc3QobikgPyBpKG4sIHQpIDogQXQobiArICJbIiArICgib2JqZWN0IiA9PSB0eXBlb2YgdCAmJiBudWxsICE9IHQgPyBlIDogIiIpICsgIl0iLCB0LCByLCBpKX0pOyBlbHNlIGlmKHIgfHwgIm9iamVjdCIgIT09IHcoZSkpIGkobiwgZSk7IGVsc2UgZm9yKHQgaW4gZSkgQXQobiArICJbIiArIHQgKyAiXSIsIGVbdF0sIHIsIGkpDQoJCX0NCg0KCQlTLnBhcmFtID0gZnVuY3Rpb24oZSwgdCkgew0KCQkJdmFyIG4sIHIgPSBbXSwgaSA9IGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQl2YXIgbiA9IG0odCkgPyB0KCkgOiB0Ow0KCQkJCXJbci5sZW5ndGhdID0gZW5jb2RlVVJJQ29tcG9uZW50KGUpICsgIj0iICsgZW5jb2RlVVJJQ29tcG9uZW50KG51bGwgPT0gbiA/ICIiIDogbikNCgkJCX07DQoJCQlpZihudWxsID09IGUpIHJldHVybiAiIjsNCgkJCWlmKEFycmF5LmlzQXJyYXkoZSkgfHwgZS5qcXVlcnkgJiYgIVMuaXNQbGFpbk9iamVjdChlKSkgUy5lYWNoKGUsIGZ1bmN0aW9uKCkge2kodGhpcy5uYW1lLCB0aGlzLnZhbHVlKX0pOyBlbHNlIGZvcihuIGluIGUpIEF0KG4sIGVbbl0sIHQsIGkpOw0KCQkJcmV0dXJuIHIuam9pbigiJiIpDQoJCX0sIFMuZm4uZXh0ZW5kKHsNCgkJCXNlcmlhbGl6ZTogZnVuY3Rpb24oKSB7cmV0dXJuIFMucGFyYW0odGhpcy5zZXJpYWxpemVBcnJheSgpKX0sIHNlcmlhbGl6ZUFycmF5OiBmdW5jdGlvbigpIHsNCgkJCQlyZXR1cm4gdGhpcy5tYXAoZnVuY3Rpb24oKSB7DQoJCQkJCXZhciBlID0gUy5wcm9wKHRoaXMsICJlbGVtZW50cyIpOw0KCQkJCQlyZXR1cm4gZSA/IFMubWFrZUFycmF5KGUpIDogdGhpcw0KCQkJCX0pLmZpbHRlcihmdW5jdGlvbigpIHsNCgkJCQkJdmFyIGUgPSB0aGlzLnR5cGU7DQoJCQkJCXJldHVybiB0aGlzLm5hbWUgJiYgIVModGhpcykuaXMoIjpkaXNhYmxlZCIpICYmIGt0LnRlc3QodGhpcy5ub2RlTmFtZSkgJiYgIVN0LnRlc3QoZSkgJiYgKHRoaXMuY2hlY2tlZCB8fCAhcGUudGVzdChlKSkNCgkJCQl9KS5tYXAoZnVuY3Rpb24oZSwgdCkgew0KCQkJCQl2YXIgbiA9IFModGhpcykudmFsKCk7DQoJCQkJCXJldHVybiBudWxsID09IG4gPyBudWxsIDogQXJyYXkuaXNBcnJheShuKSA/IFMubWFwKG4sIGZ1bmN0aW9uKGUpIHtyZXR1cm4ge25hbWU6IHQubmFtZSwgdmFsdWU6IGUucmVwbGFjZShFdCwgIlxyXG4iKX19KSA6IHtuYW1lOiB0Lm5hbWUsIHZhbHVlOiBuLnJlcGxhY2UoRXQsICJcclxuIil9DQoJCQkJfSkuZ2V0KCkNCgkJCX0NCgkJfSk7DQoJCXZhciBOdCA9IC8lMjAvZywganQgPSAvIy4qJC8sIER0ID0gLyhbPyZdKV89W14mXSovLCBxdCA9IC9eKC4qPyk6WyBcdF0qKFteXHJcbl0qKSQvZ20sIEx0ID0gL14oPzpHRVR8SEVBRCkkLywgSHQgPSAvXlwvXC8vLCBPdCA9IHt9LCBQdCA9IHt9LCBSdCA9ICIqLyIuY29uY2F0KCIqIiksIE10ID0gRS5jcmVhdGVFbGVtZW50KCJhIik7DQoNCgkJZnVuY3Rpb24gSXQobykgew0KCQkJcmV0dXJuIGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQkic3RyaW5nIiAhPSB0eXBlb2YgZSAmJiAodCA9IGUsIGUgPSAiKiIpOw0KCQkJCXZhciBuLCByID0gMCwgaSA9IGUudG9Mb3dlckNhc2UoKS5tYXRjaChQKSB8fCBbXTsNCgkJCQlpZihtKHQpKSB3aGlsZShuID0gaVtyKytdKSAiKyIgPT09IG5bMF0gPyAobiA9IG4uc2xpY2UoMSkgfHwgIioiLCAob1tuXSA9IG9bbl0gfHwgW10pLnVuc2hpZnQodCkpIDogKG9bbl0gPSBvW25dIHx8IFtdKS5wdXNoKHQpDQoJCQl9DQoJCX0NCg0KCQlmdW5jdGlvbiBXdCh0LCBpLCBvLCBhKSB7DQoJCQl2YXIgcyA9IHt9LCB1ID0gdCA9PT0gUHQ7DQoNCgkJCWZ1bmN0aW9uIGwoZSkgew0KCQkJCXZhciByOw0KCQkJCXJldHVybiBzW2VdID0gITAsIFMuZWFjaCh0W2VdIHx8IFtdLCBmdW5jdGlvbihlLCB0KSB7DQoJCQkJCXZhciBuID0gdChpLCBvLCBhKTsNCgkJCQkJcmV0dXJuICJzdHJpbmciICE9IHR5cGVvZiBuIHx8IHUgfHwgc1tuXSA/IHUgPyAhKHIgPSBuKSA6IHZvaWQgMCA6IChpLmRhdGFUeXBlcy51bnNoaWZ0KG4pLCBsKG4pLCAhMSkNCgkJCQl9KSwgcg0KCQkJfQ0KDQoJCQlyZXR1cm4gbChpLmRhdGFUeXBlc1swXSkgfHwgIXNbIioiXSAmJiBsKCIqIikNCgkJfQ0KDQoJCWZ1bmN0aW9uIEZ0KGUsIHQpIHsNCgkJCXZhciBuLCByLCBpID0gUy5hamF4U2V0dGluZ3MuZmxhdE9wdGlvbnMgfHwge307DQoJCQlmb3IobiBpbiB0KSB2b2lkIDAgIT09IHRbbl0gJiYgKChpW25dID8gZSA6IHIgfHwgKHIgPSB7fSkpW25dID0gdFtuXSk7DQoJCQlyZXR1cm4gciAmJiBTLmV4dGVuZCghMCwgZSwgciksIGUNCgkJfQ0KDQoJCU10LmhyZWYgPSBidC5ocmVmLCBTLmV4dGVuZCh7DQoJCQlhY3RpdmU6IDAsDQoJCQlsYXN0TW9kaWZpZWQ6IHt9LA0KCQkJZXRhZzoge30sDQoJCQlhamF4U2V0dGluZ3M6IHsNCgkJCQl1cmw6IGJ0LmhyZWYsDQoJCQkJdHlwZTogIkdFVCIsDQoJCQkJaXNMb2NhbDogL14oPzphYm91dHxhcHB8YXBwLXN0b3JhZ2V8ListZXh0ZW5zaW9ufGZpbGV8cmVzfHdpZGdldCk6JC8udGVzdChidC5wcm90b2NvbCksDQoJCQkJZ2xvYmFsOiAhMCwNCgkJCQlwcm9jZXNzRGF0YTogITAsDQoJCQkJYXN5bmM6ICEwLA0KCQkJCWNvbnRlbnRUeXBlOiAiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkOyBjaGFyc2V0PVVURi04IiwNCgkJCQlhY2NlcHRzOiB7IioiOiBSdCwgdGV4dDogInRleHQvcGxhaW4iLCBodG1sOiAidGV4dC9odG1sIiwgeG1sOiAiYXBwbGljYXRpb24veG1sLCB0ZXh0L3htbCIsIGpzb246ICJhcHBsaWNhdGlvbi9qc29uLCB0ZXh0L2phdmFzY3JpcHQifSwNCgkJCQljb250ZW50czoge3htbDogL1xieG1sXGIvLCBodG1sOiAvXGJodG1sLywganNvbjogL1xianNvblxiL30sDQoJCQkJcmVzcG9uc2VGaWVsZHM6IHt4bWw6ICJyZXNwb25zZVhNTCIsIHRleHQ6ICJyZXNwb25zZVRleHQiLCBqc29uOiAicmVzcG9uc2VKU09OIn0sDQoJCQkJY29udmVydGVyczogeyIqIHRleHQiOiBTdHJpbmcsICJ0ZXh0IGh0bWwiOiAhMCwgInRleHQganNvbiI6IEpTT04ucGFyc2UsICJ0ZXh0IHhtbCI6IFMucGFyc2VYTUx9LA0KCQkJCWZsYXRPcHRpb25zOiB7dXJsOiAhMCwgY29udGV4dDogITB9DQoJCQl9LA0KCQkJYWpheFNldHVwOiBmdW5jdGlvbihlLCB0KSB7cmV0dXJuIHQgPyBGdChGdChlLCBTLmFqYXhTZXR0aW5ncyksIHQpIDogRnQoUy5hamF4U2V0dGluZ3MsIGUpfSwNCgkJCWFqYXhQcmVmaWx0ZXI6IEl0KE90KSwNCgkJCWFqYXhUcmFuc3BvcnQ6IEl0KFB0KSwNCgkJCWFqYXg6IGZ1bmN0aW9uKGUsIHQpIHsNCgkJCQkib2JqZWN0IiA9PSB0eXBlb2YgZSAmJiAodCA9IGUsIGUgPSB2b2lkIDApLCB0ID0gdCB8fCB7fTsNCgkJCQl2YXIgYywNCgkJCQkgICAgZiwNCgkJCQkgICAgcCwNCgkJCQkgICAgbiwNCgkJCQkgICAgZCwNCgkJCQkgICAgciwNCgkJCQkgICAgaCwNCgkJCQkgICAgZywNCgkJCQkgICAgaSwNCgkJCQkgICAgbywNCgkJCQkgICAgdiA9IFMuYWpheFNldHVwKHt9LCB0KSwNCgkJCQkgICAgeSA9IHYuY29udGV4dCB8fCB2LA0KCQkJCSAgICBtID0gdi5jb250ZXh0ICYmICh5Lm5vZGVUeXBlIHx8IHkuanF1ZXJ5KSA/IFMoeSkgOiBTLmV2ZW50LA0KCQkJCSAgICB4ID0gUy5EZWZlcnJlZCgpLA0KCQkJCSAgICBiID0gUy5DYWxsYmFja3MoIm9uY2UgbWVtb3J5IiksDQoJCQkJICAgIHcgPSB2LnN0YXR1c0NvZGUgfHwge30sDQoJCQkJICAgIGEgPSB7fSwNCgkJCQkgICAgcyA9IHt9LA0KCQkJCSAgICB1ID0gImNhbmNlbGVkIiwNCgkJCQkgICAgVCA9IHsNCgkJCQkJICAgIHJlYWR5U3RhdGU6IDAsDQoJCQkJCSAgICBnZXRSZXNwb25zZUhlYWRlcjogZnVuY3Rpb24oZSkgew0KCQkJCQkJICAgIHZhciB0Ow0KCQkJCQkJICAgIGlmKGgpIHsNCgkJCQkJCQkgICAgaWYoIW4pIHsNCgkJCQkJCQkJICAgIG4gPSB7fTsNCgkJCQkJCQkJICAgIHdoaWxlKHQgPSBxdC5leGVjKHApKSBuW3RbMV0udG9Mb3dlckNhc2UoKSArICIgIl0gPSAoblt0WzFdLnRvTG93ZXJDYXNlKCkgKyAiICJdIHx8IFtdKS5jb25jYXQodFsyXSkNCgkJCQkJCQkgICAgfQ0KCQkJCQkJCSAgICB0ID0gbltlLnRvTG93ZXJDYXNlKCkgKyAiICJdDQoJCQkJCQkgICAgfQ0KCQkJCQkJICAgIHJldHVybiBudWxsID09IHQgPyBudWxsIDogdC5qb2luKCIsICIpDQoJCQkJCSAgICB9LA0KCQkJCQkgICAgZ2V0QWxsUmVzcG9uc2VIZWFkZXJzOiBmdW5jdGlvbigpIHtyZXR1cm4gaCA/IHAgOiBudWxsfSwNCgkJCQkJICAgIHNldFJlcXVlc3RIZWFkZXI6IGZ1bmN0aW9uKGUsIHQpIHtyZXR1cm4gbnVsbCA9PSBoICYmIChlID0gc1tlLnRvTG93ZXJDYXNlKCldID0gc1tlLnRvTG93ZXJDYXNlKCldIHx8IGUsIGFbZV0gPSB0KSwgdGhpc30sDQoJCQkJCSAgICBvdmVycmlkZU1pbWVUeXBlOiBmdW5jdGlvbihlKSB7cmV0dXJuIG51bGwgPT0gaCAmJiAodi5taW1lVHlwZSA9IGUpLCB0aGlzfSwNCgkJCQkJICAgIHN0YXR1c0NvZGU6IGZ1bmN0aW9uKGUpIHsNCgkJCQkJCSAgICB2YXIgdDsNCgkJCQkJCSAgICBpZihlKSBpZihoKSBULmFsd2F5cyhlW1Quc3RhdHVzXSk7IGVsc2UgZm9yKHQgaW4gZSkgd1t0XSA9IFt3W3RdLCBlW3RdXTsNCgkJCQkJCSAgICByZXR1cm4gdGhpcw0KCQkJCQkgICAgfSwNCgkJCQkJICAgIGFib3J0OiBmdW5jdGlvbihlKSB7DQoJCQkJCQkgICAgdmFyIHQgPSBlIHx8IHU7DQoJCQkJCQkgICAgcmV0dXJuIGMgJiYgYy5hYm9ydCh0KSwgbCgwLCB0KSwgdGhpcw0KCQkJCQkgICAgfQ0KCQkJCSAgICB9Ow0KCQkJCWlmKHgucHJvbWlzZShUKSwgdi51cmwgPSAoKGUgfHwgdi51cmwgfHwgYnQuaHJlZikgKyAiIikucmVwbGFjZShIdCwgYnQucHJvdG9jb2wgKyAiLy8iKSwgdi50eXBlID0gdC5tZXRob2QgfHwgdC50eXBlIHx8IHYubWV0aG9kIHx8IHYudHlwZSwgdi5kYXRhVHlwZXMgPSAodi5kYXRhVHlwZSB8fCAiKiIpLnRvTG93ZXJDYXNlKCkubWF0Y2goUCkgfHwgWyIiXSwgbnVsbCA9PSB2LmNyb3NzRG9tYWluKSB7DQoJCQkJCXIgPSBFLmNyZWF0ZUVsZW1lbnQoImEiKTsNCgkJCQkJdHJ5IHtyLmhyZWYgPSB2LnVybCwgci5ocmVmID0gci5ocmVmLCB2LmNyb3NzRG9tYWluID0gTXQucHJvdG9jb2wgKyAiLy8iICsgTXQuaG9zdCAhPSByLnByb3RvY29sICsgIi8vIiArIHIuaG9zdH0gY2F0Y2goZSkge3YuY3Jvc3NEb21haW4gPSAhMH0NCgkJCQl9DQoJCQkJaWYodi5kYXRhICYmIHYucHJvY2Vzc0RhdGEgJiYgInN0cmluZyIgIT0gdHlwZW9mIHYuZGF0YSAmJiAodi5kYXRhID0gUy5wYXJhbSh2LmRhdGEsIHYudHJhZGl0aW9uYWwpKSwgV3QoT3QsIHYsIHQsIFQpLCBoKSByZXR1cm4gVDsNCgkJCQlmb3IoaSBpbiAoZyA9IFMuZXZlbnQgJiYgdi5nbG9iYWwpICYmIDAgPT0gUy5hY3RpdmUrKyAmJiBTLmV2ZW50LnRyaWdnZXIoImFqYXhTdGFydCIpLCB2LnR5cGUgPSB2LnR5cGUudG9VcHBlckNhc2UoKSwgdi5oYXNDb250ZW50ID0gIUx0LnRlc3Qodi50eXBlKSwgZiA9IHYudXJsLnJlcGxhY2UoanQsICIiKSwgdi5oYXNDb250ZW50ID8gdi5kYXRhICYmIHYucHJvY2Vzc0RhdGEgJiYgMCA9PT0gKHYuY29udGVudFR5cGUgfHwgIiIpLmluZGV4T2YoImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCIpICYmICh2LmRhdGEgPSB2LmRhdGEucmVwbGFjZShOdCwgIisiKSkgOiAobyA9IHYudXJsLnNsaWNlKGYubGVuZ3RoKSwgdi5kYXRhICYmICh2LnByb2Nlc3NEYXRhIHx8ICJzdHJpbmciID09IHR5cGVvZiB2LmRhdGEpICYmIChmICs9IChUdC50ZXN0KGYpID8gIiYiIDogIj8iKSArIHYuZGF0YSwgZGVsZXRlIHYuZGF0YSksICExID09PSB2LmNhY2hlICYmIChmID0gZi5yZXBsYWNlKER0LCAiJDEiKSwgbyA9IChUdC50ZXN0KGYpID8gIiYiIDogIj8iKSArICJfPSIgKyB3dC5ndWlkKysgKyBvKSwgdi51cmwgPSBmICsgbyksIHYuaWZNb2RpZmllZCAmJiAoUy5sYXN0TW9kaWZpZWRbZl0gJiYgVC5zZXRSZXF1ZXN0SGVhZGVyKCJJZi1Nb2RpZmllZC1TaW5jZSIsIFMubGFzdE1vZGlmaWVkW2ZdKSwgUy5ldGFnW2ZdICYmIFQuc2V0UmVxdWVzdEhlYWRlcigiSWYtTm9uZS1NYXRjaCIsIFMuZXRhZ1tmXSkpLCAodi5kYXRhICYmIHYuaGFzQ29udGVudCAmJiAhMSAhPT0gdi5jb250ZW50VHlwZSB8fCB0LmNvbnRlbnRUeXBlKSAmJiBULnNldFJlcXVlc3RIZWFkZXIoIkNvbnRlbnQtVHlwZSIsIHYuY29udGVudFR5cGUpLCBULnNldFJlcXVlc3RIZWFkZXIoIkFjY2VwdCIsIHYuZGF0YVR5cGVzWzBdICYmIHYuYWNjZXB0c1t2LmRhdGFUeXBlc1swXV0gPyB2LmFjY2VwdHNbdi5kYXRhVHlwZXNbMF1dICsgKCIqIiAhPT0gdi5kYXRhVHlwZXNbMF0gPyAiLCAiICsgUnQgKyAiOyBxPTAuMDEiIDogIiIpIDogdi5hY2NlcHRzWyIqIl0pLCB2LmhlYWRlcnMpIFQuc2V0UmVxdWVzdEhlYWRlcihpLCB2LmhlYWRlcnNbaV0pOw0KCQkJCWlmKHYuYmVmb3JlU2VuZCAmJiAoITEgPT09IHYuYmVmb3JlU2VuZC5jYWxsKHksIFQsIHYpIHx8IGgpKSByZXR1cm4gVC5hYm9ydCgpOw0KCQkJCWlmKHUgPSAiYWJvcnQiLCBiLmFkZCh2LmNvbXBsZXRlKSwgVC5kb25lKHYuc3VjY2VzcyksIFQuZmFpbCh2LmVycm9yKSwgYyA9IFd0KFB0LCB2LCB0LCBUKSkgew0KCQkJCQlpZihULnJlYWR5U3RhdGUgPSAxLCBnICYmIG0udHJpZ2dlcigiYWpheFNlbmQiLCBbVCwgdl0pLCBoKSByZXR1cm4gVDsNCgkJCQkJdi5hc3luYyAmJiAwIDwgdi50aW1lb3V0ICYmIChkID0gQy5zZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1QuYWJvcnQoInRpbWVvdXQiKX0sIHYudGltZW91dCkpOw0KCQkJCQl0cnkge2ggPSAhMSwgYy5zZW5kKGEsIGwpfSBjYXRjaChlKSB7DQoJCQkJCQlpZihoKSB0aHJvdyBlOw0KCQkJCQkJbCgtMSwgZSkNCgkJCQkJfQ0KCQkJCX0gZWxzZSBsKC0xLCAiTm8gVHJhbnNwb3J0Iik7DQoNCgkJCQlmdW5jdGlvbiBsKGUsIHQsIG4sIHIpIHsNCgkJCQkJdmFyIGksIG8sIGEsIHMsIHUsIGwgPSB0Ow0KCQkJCQloIHx8IChoID0gITAsIGQgJiYgQy5jbGVhclRpbWVvdXQoZCksIGMgPSB2b2lkIDAsIHAgPSByIHx8ICIiLCBULnJlYWR5U3RhdGUgPSAwIDwgZSA/IDQgOiAwLCBpID0gMjAwIDw9IGUgJiYgZSA8IDMwMCB8fCAzMDQgPT09IGUsIG4gJiYgKHMgPSBmdW5jdGlvbihlLCB0LCBuKSB7DQoJCQkJCQl2YXIgciwgaSwgbywgYSwgcyA9IGUuY29udGVudHMsIHUgPSBlLmRhdGFUeXBlczsNCgkJCQkJCXdoaWxlKCIqIiA9PT0gdVswXSkgdS5zaGlmdCgpLCB2b2lkIDAgPT09IHIgJiYgKHIgPSBlLm1pbWVUeXBlIHx8IHQuZ2V0UmVzcG9uc2VIZWFkZXIoIkNvbnRlbnQtVHlwZSIpKTsNCgkJCQkJCWlmKHIpIGZvcihpIGluIHMpIGlmKHNbaV0gJiYgc1tpXS50ZXN0KHIpKSB7DQoJCQkJCQkJdS51bnNoaWZ0KGkpOw0KCQkJCQkJCWJyZWFrDQoJCQkJCQl9DQoJCQkJCQlpZih1WzBdIGluIG4pIG8gPSB1WzBdOyBlbHNlIHsNCgkJCQkJCQlmb3IoaSBpbiBuKSB7DQoJCQkJCQkJCWlmKCF1WzBdIHx8IGUuY29udmVydGVyc1tpICsgIiAiICsgdVswXV0pIHsNCgkJCQkJCQkJCW8gPSBpOw0KCQkJCQkJCQkJYnJlYWsNCgkJCQkJCQkJfQ0KCQkJCQkJCQlhIHx8IChhID0gaSkNCgkJCQkJCQl9DQoJCQkJCQkJbyA9IG8gfHwgYQ0KCQkJCQkJfQ0KCQkJCQkJaWYobykgcmV0dXJuIG8gIT09IHVbMF0gJiYgdS51bnNoaWZ0KG8pLCBuW29dDQoJCQkJCX0odiwgVCwgbikpLCAhaSAmJiAtMSA8IFMuaW5BcnJheSgic2NyaXB0Iiwgdi5kYXRhVHlwZXMpICYmIFMuaW5BcnJheSgianNvbiIsIHYuZGF0YVR5cGVzKSA8IDAgJiYgKHYuY29udmVydGVyc1sidGV4dCBzY3JpcHQiXSA9IGZ1bmN0aW9uKCkge30pLCBzID0gZnVuY3Rpb24oZSwgdCwgbiwgcikgew0KCQkJCQkJdmFyIGksIG8sIGEsIHMsIHUsIGwgPSB7fSwgYyA9IGUuZGF0YVR5cGVzLnNsaWNlKCk7DQoJCQkJCQlpZihjWzFdKSBmb3IoYSBpbiBlLmNvbnZlcnRlcnMpIGxbYS50b0xvd2VyQ2FzZSgpXSA9IGUuY29udmVydGVyc1thXTsNCgkJCQkJCW8gPSBjLnNoaWZ0KCk7DQoJCQkJCQl3aGlsZShvKSBpZihlLnJlc3BvbnNlRmllbGRzW29dICYmIChuW2UucmVzcG9uc2VGaWVsZHNbb11dID0gdCksICF1ICYmIHIgJiYgZS5kYXRhRmlsdGVyICYmICh0ID0gZS5kYXRhRmlsdGVyKHQsIGUuZGF0YVR5cGUpKSwgdSA9IG8sIG8gPSBjLnNoaWZ0KCkpIGlmKCIqIiA9PT0gbykgbyA9IHU7IGVsc2UgaWYoIioiICE9PSB1ICYmIHUgIT09IG8pIHsNCgkJCQkJCQlpZighKGEgPSBsW3UgKyAiICIgKyBvXSB8fCBsWyIqICIgKyBvXSkpIGZvcihpIGluIGwpIGlmKChzID0gaS5zcGxpdCgiICIpKVsxXSA9PT0gbyAmJiAoYSA9IGxbdSArICIgIiArIHNbMF1dIHx8IGxbIiogIiArIHNbMF1dKSkgew0KCQkJCQkJCQkhMCA9PT0gYSA/IGEgPSBsW2ldIDogITAgIT09IGxbaV0gJiYgKG8gPSBzWzBdLCBjLnVuc2hpZnQoc1sxXSkpOw0KCQkJCQkJCQlicmVhaw0KCQkJCQkJCX0NCgkJCQkJCQlpZighMCAhPT0gYSkgaWYoYSAmJiBlWyJ0aHJvd3MiXSkgdCA9IGEodCk7IGVsc2UgdHJ5IHt0ID0gYSh0KX0gY2F0Y2goZSkge3JldHVybiB7c3RhdGU6ICJwYXJzZXJlcnJvciIsIGVycm9yOiBhID8gZSA6ICJObyBjb252ZXJzaW9uIGZyb20gIiArIHUgKyAiIHRvICIgKyBvfX0NCgkJCQkJCX0NCgkJCQkJCXJldHVybiB7c3RhdGU6ICJzdWNjZXNzIiwgZGF0YTogdH0NCgkJCQkJfSh2LCBzLCBULCBpKSwgaSA/ICh2LmlmTW9kaWZpZWQgJiYgKCh1ID0gVC5nZXRSZXNwb25zZUhlYWRlcigiTGFzdC1Nb2RpZmllZCIpKSAmJiAoUy5sYXN0TW9kaWZpZWRbZl0gPSB1KSwgKHUgPSBULmdldFJlc3BvbnNlSGVhZGVyKCJldGFnIikpICYmIChTLmV0YWdbZl0gPSB1KSksIDIwNCA9PT0gZSB8fCAiSEVBRCIgPT09IHYudHlwZSA/IGwgPSAibm9jb250ZW50IiA6IDMwNCA9PT0gZSA/IGwgPSAibm90bW9kaWZpZWQiIDogKGwgPSBzLnN0YXRlLCBvID0gcy5kYXRhLCBpID0gIShhID0gcy5lcnJvcikpKSA6IChhID0gbCwgIWUgJiYgbCB8fCAobCA9ICJlcnJvciIsIGUgPCAwICYmIChlID0gMCkpKSwgVC5zdGF0dXMgPSBlLCBULnN0YXR1c1RleHQgPSAodCB8fCBsKSArICIiLCBpID8geC5yZXNvbHZlV2l0aCh5LCBbbywgbCwgVF0pIDogeC5yZWplY3RXaXRoKHksIFtULCBsLCBhXSksIFQuc3RhdHVzQ29kZSh3KSwgdyA9IHZvaWQgMCwgZyAmJiBtLnRyaWdnZXIoaSA/ICJhamF4U3VjY2VzcyIgOiAiYWpheEVycm9yIiwgW1QsIHYsIGkgPyBvIDogYV0pLCBiLmZpcmVXaXRoKHksIFtULCBsXSksIGcgJiYgKG0udHJpZ2dlcigiYWpheENvbXBsZXRlIiwgW1QsIHZdKSwgLS1TLmFjdGl2ZSB8fCBTLmV2ZW50LnRyaWdnZXIoImFqYXhTdG9wIikpKQ0KCQkJCX0NCg0KCQkJCXJldHVybiBUDQoJCQl9LA0KCQkJZ2V0SlNPTjogZnVuY3Rpb24oZSwgdCwgbikge3JldHVybiBTLmdldChlLCB0LCBuLCAianNvbiIpfSwNCgkJCWdldFNjcmlwdDogZnVuY3Rpb24oZSwgdCkge3JldHVybiBTLmdldChlLCB2b2lkIDAsIHQsICJzY3JpcHQiKX0NCgkJfSksIFMuZWFjaChbImdldCIsICJwb3N0Il0sIGZ1bmN0aW9uKGUsIGkpIHtTW2ldID0gZnVuY3Rpb24oZSwgdCwgbiwgcikge3JldHVybiBtKHQpICYmIChyID0gciB8fCBuLCBuID0gdCwgdCA9IHZvaWQgMCksIFMuYWpheChTLmV4dGVuZCh7dXJsOiBlLCB0eXBlOiBpLCBkYXRhVHlwZTogciwgZGF0YTogdCwgc3VjY2Vzczogbn0sIFMuaXNQbGFpbk9iamVjdChlKSAmJiBlKSl9fSksIFMuYWpheFByZWZpbHRlcihmdW5jdGlvbihlKSB7DQoJCQl2YXIgdDsNCgkJCWZvcih0IGluIGUuaGVhZGVycykgImNvbnRlbnQtdHlwZSIgPT09IHQudG9Mb3dlckNhc2UoKSAmJiAoZS5jb250ZW50VHlwZSA9IGUuaGVhZGVyc1t0XSB8fCAiIikNCgkJfSksIFMuX2V2YWxVcmwgPSBmdW5jdGlvbihlLCB0LCBuKSB7cmV0dXJuIFMuYWpheCh7dXJsOiBlLCB0eXBlOiAiR0VUIiwgZGF0YVR5cGU6ICJzY3JpcHQiLCBjYWNoZTogITAsIGFzeW5jOiAhMSwgZ2xvYmFsOiAhMSwgY29udmVydGVyczogeyJ0ZXh0IHNjcmlwdCI6IGZ1bmN0aW9uKCkge319LCBkYXRhRmlsdGVyOiBmdW5jdGlvbihlKSB7Uy5nbG9iYWxFdmFsKGUsIHQsIG4pfX0pfSwgUy5mbi5leHRlbmQoew0KCQkJd3JhcEFsbDogZnVuY3Rpb24oZSkgew0KCQkJCXZhciB0Ow0KCQkJCXJldHVybiB0aGlzWzBdICYmIChtKGUpICYmIChlID0gZS5jYWxsKHRoaXNbMF0pKSwgdCA9IFMoZSwgdGhpc1swXS5vd25lckRvY3VtZW50KS5lcSgwKS5jbG9uZSghMCksIHRoaXNbMF0ucGFyZW50Tm9kZSAmJiB0Lmluc2VydEJlZm9yZSh0aGlzWzBdKSwgdC5tYXAoZnVuY3Rpb24oKSB7DQoJCQkJCXZhciBlID0gdGhpczsNCgkJCQkJd2hpbGUoZS5maXJzdEVsZW1lbnRDaGlsZCkgZSA9IGUuZmlyc3RFbGVtZW50Q2hpbGQ7DQoJCQkJCXJldHVybiBlDQoJCQkJfSkuYXBwZW5kKHRoaXMpKSwgdGhpcw0KCQkJfSwgd3JhcElubmVyOiBmdW5jdGlvbihuKSB7DQoJCQkJcmV0dXJuIG0obikgPyB0aGlzLmVhY2goZnVuY3Rpb24oZSkge1ModGhpcykud3JhcElubmVyKG4uY2FsbCh0aGlzLCBlKSl9KSA6IHRoaXMuZWFjaChmdW5jdGlvbigpIHsNCgkJCQkJdmFyIGUgPSBTKHRoaXMpLCB0ID0gZS5jb250ZW50cygpOw0KCQkJCQl0Lmxlbmd0aCA/IHQud3JhcEFsbChuKSA6IGUuYXBwZW5kKG4pDQoJCQkJfSkNCgkJCX0sIHdyYXA6IGZ1bmN0aW9uKHQpIHsNCgkJCQl2YXIgbiA9IG0odCk7DQoJCQkJcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbihlKSB7Uyh0aGlzKS53cmFwQWxsKG4gPyB0LmNhbGwodGhpcywgZSkgOiB0KX0pDQoJCQl9LCB1bndyYXA6IGZ1bmN0aW9uKGUpIHtyZXR1cm4gdGhpcy5wYXJlbnQoZSkubm90KCJib2R5IikuZWFjaChmdW5jdGlvbigpIHtTKHRoaXMpLnJlcGxhY2VXaXRoKHRoaXMuY2hpbGROb2Rlcyl9KSwgdGhpc30NCgkJfSksIFMuZXhwci5wc2V1ZG9zLmhpZGRlbiA9IGZ1bmN0aW9uKGUpIHtyZXR1cm4gIVMuZXhwci5wc2V1ZG9zLnZpc2libGUoZSl9LCBTLmV4cHIucHNldWRvcy52aXNpYmxlID0gZnVuY3Rpb24oZSkge3JldHVybiAhIShlLm9mZnNldFdpZHRoIHx8IGUub2Zmc2V0SGVpZ2h0IHx8IGUuZ2V0Q2xpZW50UmVjdHMoKS5sZW5ndGgpfSwgUy5hamF4U2V0dGluZ3MueGhyID0gZnVuY3Rpb24oKSB7dHJ5IHtyZXR1cm4gbmV3IEMuWE1MSHR0cFJlcXVlc3R9IGNhdGNoKGUpIHt9fTsNCgkJdmFyIEJ0ID0gezA6IDIwMCwgMTIyMzogMjA0fSwgJHQgPSBTLmFqYXhTZXR0aW5ncy54aHIoKTsNCgkJeS5jb3JzID0gISEkdCAmJiAid2l0aENyZWRlbnRpYWxzIiBpbiAkdCwgeS5hamF4ID0gJHQgPSAhISR0LCBTLmFqYXhUcmFuc3BvcnQoZnVuY3Rpb24oaSkgew0KCQkJdmFyIG8sIGE7DQoJCQlpZih5LmNvcnMgfHwgJHQgJiYgIWkuY3Jvc3NEb21haW4pIHJldHVybiB7DQoJCQkJc2VuZDogZnVuY3Rpb24oZSwgdCkgew0KCQkJCQl2YXIgbiwgciA9IGkueGhyKCk7DQoJCQkJCWlmKHIub3BlbihpLnR5cGUsIGkudXJsLCBpLmFzeW5jLCBpLnVzZXJuYW1lLCBpLnBhc3N3b3JkKSwgaS54aHJGaWVsZHMpIGZvcihuIGluIGkueGhyRmllbGRzKSByW25dID0gaS54aHJGaWVsZHNbbl07DQoJCQkJCWZvcihuIGluIGkubWltZVR5cGUgJiYgci5vdmVycmlkZU1pbWVUeXBlICYmIHIub3ZlcnJpZGVNaW1lVHlwZShpLm1pbWVUeXBlKSwgaS5jcm9zc0RvbWFpbiB8fCBlWyJYLVJlcXVlc3RlZC1XaXRoIl0gfHwgKGVbIlgtUmVxdWVzdGVkLVdpdGgiXSA9ICJYTUxIdHRwUmVxdWVzdCIpLCBlKSByLnNldFJlcXVlc3RIZWFkZXIobiwgZVtuXSk7DQoJCQkJCW8gPSBmdW5jdGlvbihlKSB7cmV0dXJuIGZ1bmN0aW9uKCkge28gJiYgKG8gPSBhID0gci5vbmxvYWQgPSByLm9uZXJyb3IgPSByLm9uYWJvcnQgPSByLm9udGltZW91dCA9IHIub25yZWFkeXN0YXRlY2hhbmdlID0gbnVsbCwgImFib3J0IiA9PT0gZSA/IHIuYWJvcnQoKSA6ICJlcnJvciIgPT09IGUgPyAibnVtYmVyIiAhPSB0eXBlb2Ygci5zdGF0dXMgPyB0KDAsICJlcnJvciIpIDogdChyLnN0YXR1cywgci5zdGF0dXNUZXh0KSA6IHQoQnRbci5zdGF0dXNdIHx8IHIuc3RhdHVzLCByLnN0YXR1c1RleHQsICJ0ZXh0IiAhPT0gKHIucmVzcG9uc2VUeXBlIHx8ICJ0ZXh0IikgfHwgInN0cmluZyIgIT0gdHlwZW9mIHIucmVzcG9uc2VUZXh0ID8ge2JpbmFyeTogci5yZXNwb25zZX0gOiB7dGV4dDogci5yZXNwb25zZVRleHR9LCByLmdldEFsbFJlc3BvbnNlSGVhZGVycygpKSl9fSwgci5vbmxvYWQgPSBvKCksIGEgPSByLm9uZXJyb3IgPSByLm9udGltZW91dCA9IG8oImVycm9yIiksIHZvaWQgMCAhPT0gci5vbmFib3J0ID8gci5vbmFib3J0ID0gYSA6IHIub25yZWFkeXN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7NCA9PT0gci5yZWFkeVN0YXRlICYmIEMuc2V0VGltZW91dChmdW5jdGlvbigpIHtvICYmIGEoKX0pfSwgbyA9IG8oImFib3J0Iik7DQoJCQkJCXRyeSB7ci5zZW5kKGkuaGFzQ29udGVudCAmJiBpLmRhdGEgfHwgbnVsbCl9IGNhdGNoKGUpIHtpZihvKSB0aHJvdyBlfQ0KCQkJCX0sIGFib3J0OiBmdW5jdGlvbigpIHtvICYmIG8oKX0NCgkJCX0NCgkJfSksIFMuYWpheFByZWZpbHRlcihmdW5jdGlvbihlKSB7ZS5jcm9zc0RvbWFpbiAmJiAoZS5jb250ZW50cy5zY3JpcHQgPSAhMSl9KSwgUy5hamF4U2V0dXAoew0KCQkJYWNjZXB0czoge3NjcmlwdDogInRleHQvamF2YXNjcmlwdCwgYXBwbGljYXRpb24vamF2YXNjcmlwdCwgYXBwbGljYXRpb24vZWNtYXNjcmlwdCwgYXBwbGljYXRpb24veC1lY21hc2NyaXB0In0sDQoJCQljb250ZW50czoge3NjcmlwdDogL1xiKD86amF2YXxlY21hKXNjcmlwdFxiL30sDQoJCQljb252ZXJ0ZXJzOiB7InRleHQgc2NyaXB0IjogZnVuY3Rpb24oZSkge3JldHVybiBTLmdsb2JhbEV2YWwoZSksIGV9fQ0KCQl9KSwgUy5hamF4UHJlZmlsdGVyKCJzY3JpcHQiLCBmdW5jdGlvbihlKSB7dm9pZCAwID09PSBlLmNhY2hlICYmIChlLmNhY2hlID0gITEpLCBlLmNyb3NzRG9tYWluICYmIChlLnR5cGUgPSAiR0VUIil9KSwgUy5hamF4VHJhbnNwb3J0KCJzY3JpcHQiLCBmdW5jdGlvbihuKSB7DQoJCQl2YXIgciwgaTsNCgkJCWlmKG4uY3Jvc3NEb21haW4gfHwgbi5zY3JpcHRBdHRycykgcmV0dXJuIHsNCgkJCQlzZW5kOiBmdW5jdGlvbihlLCB0KSB7ciA9IFMoIjxzY3JpcHQ+IikuYXR0cihuLnNjcmlwdEF0dHJzIHx8IHt9KS5wcm9wKHtjaGFyc2V0OiBuLnNjcmlwdENoYXJzZXQsIHNyYzogbi51cmx9KS5vbigibG9hZCBlcnJvciIsIGkgPSBmdW5jdGlvbihlKSB7ci5yZW1vdmUoKSwgaSA9IG51bGwsIGUgJiYgdCgiZXJyb3IiID09PSBlLnR5cGUgPyA0MDQgOiAyMDAsIGUudHlwZSl9KSwgRS5oZWFkLmFwcGVuZENoaWxkKHJbMF0pfSwNCgkJCQlhYm9ydDogZnVuY3Rpb24oKSB7aSAmJiBpKCl9DQoJCQl9DQoJCX0pOw0KCQl2YXIgX3QsIHp0ID0gW10sIFV0ID0gLyg9KVw/KD89JnwkKXxcP1w/LzsNCgkJUy5hamF4U2V0dXAoew0KCQkJanNvbnA6ICJjYWxsYmFjayIsIGpzb25wQ2FsbGJhY2s6IGZ1bmN0aW9uKCkgew0KCQkJCXZhciBlID0genQucG9wKCkgfHwgUy5leHBhbmRvICsgIl8iICsgd3QuZ3VpZCsrOw0KCQkJCXJldHVybiB0aGlzW2VdID0gITAsIGUNCgkJCX0NCgkJfSksIFMuYWpheFByZWZpbHRlcigianNvbiBqc29ucCIsIGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCXZhciByLCBpLCBvLCBhID0gITEgIT09IGUuanNvbnAgJiYgKFV0LnRlc3QoZS51cmwpID8gInVybCIgOiAic3RyaW5nIiA9PSB0eXBlb2YgZS5kYXRhICYmIDAgPT09IChlLmNvbnRlbnRUeXBlIHx8ICIiKS5pbmRleE9mKCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQiKSAmJiBVdC50ZXN0KGUuZGF0YSkgJiYgImRhdGEiKTsNCgkJCWlmKGEgfHwgImpzb25wIiA9PT0gZS5kYXRhVHlwZXNbMF0pIHJldHVybiByID0gZS5qc29ucENhbGxiYWNrID0gbShlLmpzb25wQ2FsbGJhY2spID8gZS5qc29ucENhbGxiYWNrKCkgOiBlLmpzb25wQ2FsbGJhY2ssIGEgPyBlW2FdID0gZVthXS5yZXBsYWNlKFV0LCAiJDEiICsgcikgOiAhMSAhPT0gZS5qc29ucCAmJiAoZS51cmwgKz0gKFR0LnRlc3QoZS51cmwpID8gIiYiIDogIj8iKSArIGUuanNvbnAgKyAiPSIgKyByKSwgZS5jb252ZXJ0ZXJzWyJzY3JpcHQganNvbiJdID0gZnVuY3Rpb24oKSB7cmV0dXJuIG8gfHwgUy5lcnJvcihyICsgIiB3YXMgbm90IGNhbGxlZCIpLCBvWzBdfSwgZS5kYXRhVHlwZXNbMF0gPSAianNvbiIsIGkgPSBDW3JdLCBDW3JdID0gZnVuY3Rpb24oKSB7byA9IGFyZ3VtZW50c30sIG4uYWx3YXlzKGZ1bmN0aW9uKCkge3ZvaWQgMCA9PT0gaSA/IFMoQykucmVtb3ZlUHJvcChyKSA6IENbcl0gPSBpLCBlW3JdICYmIChlLmpzb25wQ2FsbGJhY2sgPSB0Lmpzb25wQ2FsbGJhY2ssIHp0LnB1c2gocikpLCBvICYmIG0oaSkgJiYgaShvWzBdKSwgbyA9IGkgPSB2b2lkIDB9KSwgInNjcmlwdCINCgkJfSksIHkuY3JlYXRlSFRNTERvY3VtZW50ID0gKChfdCA9IEUuaW1wbGVtZW50YXRpb24uY3JlYXRlSFRNTERvY3VtZW50KCIiKS5ib2R5KS5pbm5lckhUTUwgPSAiPGZvcm0+PC9mb3JtPjxmb3JtPjwvZm9ybT4iLCAyID09PSBfdC5jaGlsZE5vZGVzLmxlbmd0aCksIFMucGFyc2VIVE1MID0gZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJcmV0dXJuICJzdHJpbmciICE9IHR5cGVvZiBlID8gW10gOiAoImJvb2xlYW4iID09IHR5cGVvZiB0ICYmIChuID0gdCwgdCA9ICExKSwgdCB8fCAoeS5jcmVhdGVIVE1MRG9jdW1lbnQgPyAoKHIgPSAodCA9IEUuaW1wbGVtZW50YXRpb24uY3JlYXRlSFRNTERvY3VtZW50KCIiKSkuY3JlYXRlRWxlbWVudCgiYmFzZSIpKS5ocmVmID0gRS5sb2NhdGlvbi5ocmVmLCB0LmhlYWQuYXBwZW5kQ2hpbGQocikpIDogdCA9IEUpLCBvID0gIW4gJiYgW10sIChpID0gTi5leGVjKGUpKSA/IFt0LmNyZWF0ZUVsZW1lbnQoaVsxXSldIDogKGkgPSB4ZShbZV0sIHQsIG8pLCBvICYmIG8ubGVuZ3RoICYmIFMobykucmVtb3ZlKCksIFMubWVyZ2UoW10sIGkuY2hpbGROb2RlcykpKTsNCgkJCXZhciByLCBpLCBvDQoJCX0sIFMuZm4ubG9hZCA9IGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCXZhciByLCBpLCBvLCBhID0gdGhpcywgcyA9IGUuaW5kZXhPZigiICIpOw0KCQkJcmV0dXJuIC0xIDwgcyAmJiAociA9IGh0KGUuc2xpY2UocykpLCBlID0gZS5zbGljZSgwLCBzKSksIG0odCkgPyAobiA9IHQsIHQgPSB2b2lkIDApIDogdCAmJiAib2JqZWN0IiA9PSB0eXBlb2YgdCAmJiAoaSA9ICJQT1NUIiksIDAgPCBhLmxlbmd0aCAmJiBTLmFqYXgoew0KCQkJCXVybDogZSwNCgkJCQl0eXBlOiBpIHx8ICJHRVQiLA0KCQkJCWRhdGFUeXBlOiAiaHRtbCIsDQoJCQkJZGF0YTogdA0KCQkJfSkuZG9uZShmdW5jdGlvbihlKSB7byA9IGFyZ3VtZW50cywgYS5odG1sKHIgPyBTKCI8ZGl2PiIpLmFwcGVuZChTLnBhcnNlSFRNTChlKSkuZmluZChyKSA6IGUpfSkuYWx3YXlzKG4gJiYgZnVuY3Rpb24oZSwgdCkge2EuZWFjaChmdW5jdGlvbigpIHtuLmFwcGx5KHRoaXMsIG8gfHwgW2UucmVzcG9uc2VUZXh0LCB0LCBlXSl9KX0pLCB0aGlzDQoJCX0sIFMuZXhwci5wc2V1ZG9zLmFuaW1hdGVkID0gZnVuY3Rpb24odCkge3JldHVybiBTLmdyZXAoUy50aW1lcnMsIGZ1bmN0aW9uKGUpIHtyZXR1cm4gdCA9PT0gZS5lbGVtfSkubGVuZ3RofSwgUy5vZmZzZXQgPSB7DQoJCQlzZXRPZmZzZXQ6IGZ1bmN0aW9uKGUsIHQsIG4pIHsNCgkJCQl2YXIgciwgaSwgbywgYSwgcywgdSwgbCA9IFMuY3NzKGUsICJwb3NpdGlvbiIpLCBjID0gUyhlKSwgZiA9IHt9Ow0KCQkJCSJzdGF0aWMiID09PSBsICYmIChlLnN0eWxlLnBvc2l0aW9uID0gInJlbGF0aXZlIiksIHMgPSBjLm9mZnNldCgpLCBvID0gUy5jc3MoZSwgInRvcCIpLCB1ID0gUy5jc3MoZSwgImxlZnQiKSwgKCJhYnNvbHV0ZSIgPT09IGwgfHwgImZpeGVkIiA9PT0gbCkgJiYgLTEgPCAobyArIHUpLmluZGV4T2YoImF1dG8iKSA/IChhID0gKHIgPSBjLnBvc2l0aW9uKCkpLnRvcCwgaSA9IHIubGVmdCkgOiAoYSA9IHBhcnNlRmxvYXQobykgfHwgMCwgaSA9IHBhcnNlRmxvYXQodSkgfHwgMCksIG0odCkgJiYgKHQgPSB0LmNhbGwoZSwgbiwgUy5leHRlbmQoe30sIHMpKSksIG51bGwgIT0gdC50b3AgJiYgKGYudG9wID0gdC50b3AgLSBzLnRvcCArIGEpLCBudWxsICE9IHQubGVmdCAmJiAoZi5sZWZ0ID0gdC5sZWZ0IC0gcy5sZWZ0ICsgaSksICJ1c2luZyIgaW4gdCA/IHQudXNpbmcuY2FsbChlLCBmKSA6IGMuY3NzKGYpDQoJCQl9DQoJCX0sIFMuZm4uZXh0ZW5kKHsNCgkJCW9mZnNldDogZnVuY3Rpb24odCkgew0KCQkJCWlmKGFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB2b2lkIDAgPT09IHQgPyB0aGlzIDogdGhpcy5lYWNoKGZ1bmN0aW9uKGUpIHtTLm9mZnNldC5zZXRPZmZzZXQodGhpcywgdCwgZSl9KTsNCgkJCQl2YXIgZSwgbiwgciA9IHRoaXNbMF07DQoJCQkJcmV0dXJuIHIgPyByLmdldENsaWVudFJlY3RzKCkubGVuZ3RoID8gKGUgPSByLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLCBuID0gci5vd25lckRvY3VtZW50LmRlZmF1bHRWaWV3LCB7dG9wOiBlLnRvcCArIG4ucGFnZVlPZmZzZXQsIGxlZnQ6IGUubGVmdCArIG4ucGFnZVhPZmZzZXR9KSA6IHt0b3A6IDAsIGxlZnQ6IDB9IDogdm9pZCAwDQoJCQl9LCBwb3NpdGlvbjogZnVuY3Rpb24oKSB7DQoJCQkJaWYodGhpc1swXSkgew0KCQkJCQl2YXIgZSwgdCwgbiwgciA9IHRoaXNbMF0sIGkgPSB7dG9wOiAwLCBsZWZ0OiAwfTsNCgkJCQkJaWYoImZpeGVkIiA9PT0gUy5jc3MociwgInBvc2l0aW9uIikpIHQgPSByLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOyBlbHNlIHsNCgkJCQkJCXQgPSB0aGlzLm9mZnNldCgpLCBuID0gci5vd25lckRvY3VtZW50LCBlID0gci5vZmZzZXRQYXJlbnQgfHwgbi5kb2N1bWVudEVsZW1lbnQ7DQoJCQkJCQl3aGlsZShlICYmIChlID09PSBuLmJvZHkgfHwgZSA9PT0gbi5kb2N1bWVudEVsZW1lbnQpICYmICJzdGF0aWMiID09PSBTLmNzcyhlLCAicG9zaXRpb24iKSkgZSA9IGUucGFyZW50Tm9kZTsNCgkJCQkJCWUgJiYgZSAhPT0gciAmJiAxID09PSBlLm5vZGVUeXBlICYmICgoaSA9IFMoZSkub2Zmc2V0KCkpLnRvcCArPSBTLmNzcyhlLCAiYm9yZGVyVG9wV2lkdGgiLCAhMCksIGkubGVmdCArPSBTLmNzcyhlLCAiYm9yZGVyTGVmdFdpZHRoIiwgITApKQ0KCQkJCQl9DQoJCQkJCXJldHVybiB7dG9wOiB0LnRvcCAtIGkudG9wIC0gUy5jc3MociwgIm1hcmdpblRvcCIsICEwKSwgbGVmdDogdC5sZWZ0IC0gaS5sZWZ0IC0gUy5jc3MociwgIm1hcmdpbkxlZnQiLCAhMCl9DQoJCQkJfQ0KCQkJfSwgb2Zmc2V0UGFyZW50OiBmdW5jdGlvbigpIHsNCgkJCQlyZXR1cm4gdGhpcy5tYXAoZnVuY3Rpb24oKSB7DQoJCQkJCXZhciBlID0gdGhpcy5vZmZzZXRQYXJlbnQ7DQoJCQkJCXdoaWxlKGUgJiYgInN0YXRpYyIgPT09IFMuY3NzKGUsICJwb3NpdGlvbiIpKSBlID0gZS5vZmZzZXRQYXJlbnQ7DQoJCQkJCXJldHVybiBlIHx8IHJlDQoJCQkJfSkNCgkJCX0NCgkJfSksIFMuZWFjaCh7c2Nyb2xsTGVmdDogInBhZ2VYT2Zmc2V0Iiwgc2Nyb2xsVG9wOiAicGFnZVlPZmZzZXQifSwgZnVuY3Rpb24odCwgaSkgew0KCQkJdmFyIG8gPSAicGFnZVlPZmZzZXQiID09PSBpOw0KCQkJUy5mblt0XSA9IGZ1bmN0aW9uKGUpIHsNCgkJCQlyZXR1cm4gJCh0aGlzLCBmdW5jdGlvbihlLCB0LCBuKSB7DQoJCQkJCXZhciByOw0KCQkJCQlpZih4KGUpID8gciA9IGUgOiA5ID09PSBlLm5vZGVUeXBlICYmIChyID0gZS5kZWZhdWx0VmlldyksIHZvaWQgMCA9PT0gbikgcmV0dXJuIHIgPyByW2ldIDogZVt0XTsNCgkJCQkJciA/IHIuc2Nyb2xsVG8obyA/IHIucGFnZVhPZmZzZXQgOiBuLCBvID8gbiA6IHIucGFnZVlPZmZzZXQpIDogZVt0XSA9IG4NCgkJCQl9LCB0LCBlLCBhcmd1bWVudHMubGVuZ3RoKQ0KCQkJfQ0KCQl9KSwgUy5lYWNoKFsidG9wIiwgImxlZnQiXSwgZnVuY3Rpb24oZSwgbikge1MuY3NzSG9va3Nbbl0gPSBGZSh5LnBpeGVsUG9zaXRpb24sIGZ1bmN0aW9uKGUsIHQpIHtpZih0KSByZXR1cm4gdCA9IFdlKGUsIG4pLCBQZS50ZXN0KHQpID8gUyhlKS5wb3NpdGlvbigpW25dICsgInB4IiA6IHR9KX0pLCBTLmVhY2goe0hlaWdodDogImhlaWdodCIsIFdpZHRoOiAid2lkdGgifSwgZnVuY3Rpb24oYSwgcykgew0KCQkJUy5lYWNoKHsNCgkJCQlwYWRkaW5nOiAiaW5uZXIiICsgYSwNCgkJCQljb250ZW50OiBzLA0KCQkJCSIiOiAib3V0ZXIiICsgYQ0KCQkJfSwgZnVuY3Rpb24ociwgbykgew0KCQkJCVMuZm5bb10gPSBmdW5jdGlvbihlLCB0KSB7DQoJCQkJCXZhciBuID0gYXJndW1lbnRzLmxlbmd0aCAmJiAociB8fCAiYm9vbGVhbiIgIT0gdHlwZW9mIGUpLCBpID0gciB8fCAoITAgPT09IGUgfHwgITAgPT09IHQgPyAibWFyZ2luIiA6ICJib3JkZXIiKTsNCgkJCQkJcmV0dXJuICQodGhpcywgZnVuY3Rpb24oZSwgdCwgbikgew0KCQkJCQkJdmFyIHI7DQoJCQkJCQlyZXR1cm4geChlKSA/IDAgPT09IG8uaW5kZXhPZigib3V0ZXIiKSA/IGVbImlubmVyIiArIGFdIDogZS5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnRbImNsaWVudCIgKyBhXSA6IDkgPT09IGUubm9kZVR5cGUgPyAociA9IGUuZG9jdW1lbnRFbGVtZW50LCBNYXRoLm1heChlLmJvZHlbInNjcm9sbCIgKyBhXSwgclsic2Nyb2xsIiArIGFdLCBlLmJvZHlbIm9mZnNldCIgKyBhXSwgclsib2Zmc2V0IiArIGFdLCByWyJjbGllbnQiICsgYV0pKSA6IHZvaWQgMCA9PT0gbiA/IFMuY3NzKGUsIHQsIGkpIDogUy5zdHlsZShlLCB0LCBuLCBpKQ0KCQkJCQl9LCBzLCBuID8gZSA6IHZvaWQgMCwgbikNCgkJCQl9DQoJCQl9KQ0KCQl9KSwgUy5lYWNoKFsiYWpheFN0YXJ0IiwgImFqYXhTdG9wIiwgImFqYXhDb21wbGV0ZSIsICJhamF4RXJyb3IiLCAiYWpheFN1Y2Nlc3MiLCAiYWpheFNlbmQiXSwgZnVuY3Rpb24oZSwgdCkge1MuZm5bdF0gPSBmdW5jdGlvbihlKSB7cmV0dXJuIHRoaXMub24odCwgZSl9fSksIFMuZm4uZXh0ZW5kKHsNCgkJCWJpbmQ6IGZ1bmN0aW9uKGUsIHQsIG4pIHtyZXR1cm4gdGhpcy5vbihlLCBudWxsLCB0LCBuKX0sDQoJCQl1bmJpbmQ6IGZ1bmN0aW9uKGUsIHQpIHtyZXR1cm4gdGhpcy5vZmYoZSwgbnVsbCwgdCl9LA0KCQkJZGVsZWdhdGU6IGZ1bmN0aW9uKGUsIHQsIG4sIHIpIHtyZXR1cm4gdGhpcy5vbih0LCBlLCBuLCByKX0sDQoJCQl1bmRlbGVnYXRlOiBmdW5jdGlvbihlLCB0LCBuKSB7cmV0dXJuIDEgPT09IGFyZ3VtZW50cy5sZW5ndGggPyB0aGlzLm9mZihlLCAiKioiKSA6IHRoaXMub2ZmKHQsIGUgfHwgIioqIiwgbil9LA0KCQkJaG92ZXI6IGZ1bmN0aW9uKGUsIHQpIHtyZXR1cm4gdGhpcy5tb3VzZWVudGVyKGUpLm1vdXNlbGVhdmUodCB8fCBlKX0NCgkJfSksIFMuZWFjaCgiYmx1ciBmb2N1cyBmb2N1c2luIGZvY3Vzb3V0IHJlc2l6ZSBzY3JvbGwgY2xpY2sgZGJsY2xpY2sgbW91c2Vkb3duIG1vdXNldXAgbW91c2Vtb3ZlIG1vdXNlb3ZlciBtb3VzZW91dCBtb3VzZWVudGVyIG1vdXNlbGVhdmUgY2hhbmdlIHNlbGVjdCBzdWJtaXQga2V5ZG93biBrZXlwcmVzcyBrZXl1cCBjb250ZXh0bWVudSIuc3BsaXQoIiAiKSwgZnVuY3Rpb24oZSwgbikge1MuZm5bbl0gPSBmdW5jdGlvbihlLCB0KSB7cmV0dXJuIDAgPCBhcmd1bWVudHMubGVuZ3RoID8gdGhpcy5vbihuLCBudWxsLCBlLCB0KSA6IHRoaXMudHJpZ2dlcihuKX19KTsNCgkJdmFyIFh0ID0gL15bXHNcdUZFRkZceEEwXSt8W1xzXHVGRUZGXHhBMF0rJC9nOw0KCQlTLnByb3h5ID0gZnVuY3Rpb24oZSwgdCkgew0KCQkJdmFyIG4sIHIsIGk7DQoJCQlpZigic3RyaW5nIiA9PSB0eXBlb2YgdCAmJiAobiA9IGVbdF0sIHQgPSBlLCBlID0gbiksIG0oZSkpIHJldHVybiByID0gcy5jYWxsKGFyZ3VtZW50cywgMiksIChpID0gZnVuY3Rpb24oKSB7cmV0dXJuIGUuYXBwbHkodCB8fCB0aGlzLCByLmNvbmNhdChzLmNhbGwoYXJndW1lbnRzKSkpfSkuZ3VpZCA9IGUuZ3VpZCA9IGUuZ3VpZCB8fCBTLmd1aWQrKywgaQ0KCQl9LCBTLmhvbGRSZWFkeSA9IGZ1bmN0aW9uKGUpIHtlID8gUy5yZWFkeVdhaXQrKyA6IFMucmVhZHkoITApfSwgUy5pc0FycmF5ID0gQXJyYXkuaXNBcnJheSwgUy5wYXJzZUpTT04gPSBKU09OLnBhcnNlLCBTLm5vZGVOYW1lID0gQSwgUy5pc0Z1bmN0aW9uID0gbSwgUy5pc1dpbmRvdyA9IHgsIFMuY2FtZWxDYXNlID0gWCwgUy50eXBlID0gdywgUy5ub3cgPSBEYXRlLm5vdywgUy5pc051bWVyaWMgPSBmdW5jdGlvbihlKSB7DQoJCQl2YXIgdCA9IFMudHlwZShlKTsNCgkJCXJldHVybiAoIm51bWJlciIgPT09IHQgfHwgInN0cmluZyIgPT09IHQpICYmICFpc05hTihlIC0gcGFyc2VGbG9hdChlKSkNCgkJfSwgUy50cmltID0gZnVuY3Rpb24oZSkge3JldHVybiBudWxsID09IGUgPyAiIiA6IChlICsgIiIpLnJlcGxhY2UoWHQsICIiKX0sICJmdW5jdGlvbiIgPT0gdHlwZW9mIGRlZmluZSAmJiBkZWZpbmUuYW1kICYmIGRlZmluZSgianF1ZXJ5IiwgW10sIGZ1bmN0aW9uKCkge3JldHVybiBTfSk7DQoJCXZhciBWdCA9IEMualF1ZXJ5LCBHdCA9IEMuJDsNCgkJcmV0dXJuIFMubm9Db25mbGljdCA9IGZ1bmN0aW9uKGUpIHtyZXR1cm4gQy4kID09PSBTICYmIChDLiQgPSBHdCksIGUgJiYgQy5qUXVlcnkgPT09IFMgJiYgKEMualF1ZXJ5ID0gVnQpLCBTfSwgInVuZGVmaW5lZCIgPT0gdHlwZW9mIGUgJiYgKEMualF1ZXJ5ID0gQy4kID0gUyksIFMNCgl9KTsNCn0NCg0KY29uc3QgU1VLUkluc3RhbmNlcyA9IHsNCglpbnN0YW5jZXM6IHt9LA0KCW9uQ2hhbmdlTGlzdGVuZXI6IHt9LA0KCW9uQ3JlYXRlTGlzdGVuZXI6IHt9LA0KDQoJLyoqDQoJICogQWRkIGEgbG9hZGVkIDxiPlNHTlVJS2l0PC9iPiBjb21wb25lbnQuDQoJICoNCgkgKiBAcGFyYW0ge3t9fSB2YWx1ZSBUaGUgPGI+PGk+SlNPTjwvaT48L2I+IG9iamVjdCBvZiB0aGUgbG9hZGVkIDxiPlNHTlVJS2l0PC9iPiBjb21wb25lbnQuDQoJICovDQoJc2V0IGluc3RhbmNlKHZhbHVlKSB7DQoJCWlmKHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09ICIiKQ0KCQkJdmFsdWUgPSB7fTsNCgkJcHVzaCh0aGlzLmluc3RhbmNlcywgdmFsdWUpOw0KDQoJCS8vY29uc29sZS5sb2coU0dOVUlLaXQpOw0KDQoJCWZvckVhY2godGhpcy5vbkNoYW5nZUxpc3RlbmVyLCAobGlzdGVuZXIpID0+IGxpc3RlbmVyKHZhbHVlLCB0aGlzLmluc3RhbmNlcykpOw0KCQkvL1NHTlVJS2l0LnNldE9uUmVhZHlMaXN0ZW5lcigoKSA9PiBmb3JFYWNoKHRoaXMub25DcmVhdGVMaXN0ZW5lciwgKGxpc3RlbmVyKSA9PiBsaXN0ZW5lcih0aGlzLmluc3RhbmNlcykpLCAnc2duLXVrci1jcmVhdGUtbGlzdGVuZXInKTsNCgl9LA0KDQoJLyoqDQoJICogR2V0IHRoZSBsaXN0IG9mIGxvYWRlZCA8Yj5TR05VSUtpdDwvYj4gY29tcG9uZW50cy4NCgkgKg0KCSAqIEByZXR1cm4ge29iamVjdH0gVGhlIDxiPjxpPkpTT048L2k+PC9iPiBvYmplY3Qgb2YgbG9hZGVkIDxiPlNHTlVJS2l0PC9iPiBjb21wb25lbnRzLCBvciBhbiBlbXB0eSA8Yj48aT5KU09OPC9pPjwvYj4gb2JqZWN0IGlmIG5vIGNvbXBvbmVudHMgbG9hZGVkLg0KCSAqLw0KCWdldCBpbnN0YW5jZSgpIHsNCgkJcmV0dXJuIHRoaXMuaW5zdGFuY2VzOw0KCX0sDQoJLyoqDQoJICogU2V0IHRoZSBoYW5kbGVyIGZvciA8Yj5TR05VSUtpdDwvYj4gPGI+PGk+T25DaGFuZ2U8L2k+PC9iPiBldmVudCwgd2hpY2ggd2lsbCBiZSB0cmlnZ2VyZWQgd2hlbiBhIGNvbXBvbmVudCBpcyBsb2FkZWQvcmVtb3ZlZCBvciB0aGUgc3RhdHVzIG9mIHJlYWRpbmVzcyBpcyBjaGFuZ2VkLg0KCSAqDQoJICogQHBhcmFtIHsobmV3SW5zdGFuY2U6e30sIGluc3RhbmNlczp7fSk9PnZvaWR9bGlzdGVuZXINCgkgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9W2lkPXVuZGVmaW5lZF0NCgkgKi8NCglzZXRPbkNoYW5nZUxpc3RlbmVyOiBmdW5jdGlvbihsaXN0ZW5lciwgaWQpIHsNCgkJaWYodHlwZW9mIGlkICE9PSAnc3RyaW5nJyB8fCAkLmlzTnVtZXJpYyhpZCkpDQoJCQl0aGlzLm9uQ2hhbmdlTGlzdGVuZXJbaWRdID0gbGlzdGVuZXI7DQoJCWVsc2UNCgkJCXB1c2godGhpcy5vbkNoYW5nZUxpc3RlbmVyLCBsaXN0ZW5lcik7DQoNCgkJZm9yRWFjaCh0aGlzLm9uQ2hhbmdlTGlzdGVuZXIsIChsaXN0ZW5lcikgPT4gbGlzdGVuZXIoJycsIHRoaXMuaW5zdGFuY2VzKSk7DQoJfSwNCg0KCS8qKg0KCSAqIFNldCB0aGUgaGFuZGxlciBmb3IgPGI+U0dOVUlLaXQ8L2I+IDxiPjxpPk9uQ2hhbmdlPC9pPjwvYj4gZXZlbnQsIHdoaWNoIHdpbGwgYmUgdHJpZ2dlcmVkIHdoZW4gYSBjb21wb25lbnQgaXMgbG9hZGVkL3JlbW92ZWQgb3IgdGhlIHN0YXR1cyBvZiByZWFkaW5lc3MgaXMgY2hhbmdlZC4NCgkgKg0KCSAqIEBwYXJhbSB7KG5ld0luc3RhbmNlOnt9LCBpbnN0YW5jZXM6e30pPT52b2lkfWxpc3RlbmVyDQoJICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfVtpZD11bmRlZmluZWRdDQoJICovDQoJc2V0T25DcmVhdGVMaXN0ZW5lcjogZnVuY3Rpb24obGlzdGVuZXIsIGlkKSB7DQoJCWlmKHR5cGVvZiBpZCAhPT0gJ3N0cmluZycgfHwgJC5pc051bWVyaWMoaWQpKQ0KCQkJdGhpcy5vbkNyZWF0ZUxpc3RlbmVyW2lkXSA9IGxpc3RlbmVyOw0KCQllbHNlDQoJCQlwdXNoKHRoaXMub25DcmVhdGVMaXN0ZW5lciwgbGlzdGVuZXIpOw0KDQoJCVNHTlVJS2l0LnNldE9uUmVhZHlMaXN0ZW5lcigoKSA9PiBmb3JFYWNoKHRoaXMub25DcmVhdGVMaXN0ZW5lciwgKGxpc3RlbmVyKSA9PiBsaXN0ZW5lcih0aGlzLmluc3RhbmNlcykpLCAnc2duLXVrci1jcmVhdGUtbGlzdGVuZXInKTsNCgl9LA0KfTsNCg0KLyoqKg0KICogU1VLUiAoU0dOVUlLaXQgUmVhZHkpIGNhbGxiYWNrIGlzIHVzZWQgdG8gZGV0ZXJtaW5lIGlmIHRoZSBwYWdlIGlzIGxvYWRlZCBhbmQgcmVhZHkgdG8gdXNlLiBJdCBjb21iaW5lcyBpbnRlcm5hbCA8Yj5TR05VSUtpdDwvYj4gcmVhZHkgZXZlbnRzIGFzIHdlbGwgYXMgalF1ZXJ5IGAkKGZ1bmN0aW9uKCl7fSlgIGNhbGxiYWNrLg0KICogPGJyPg0KICogPGI+Tk9URTo8L2I+IElmIDxiPjxpPlNHTkF0b208L2I+PC9pPiBpcyB1c2VkIHRoZW4sIHRoZSA8Yj48aT5TVUtSPC9iPjwvaT4gY2FsbGJhY2sgd2lsbCBiZSBjYWxsZWQgYWZ0ZXIgdGhlIDxiPjxpPkRPTTwvYj48L2k+IGlzIHJlYWR5IGFuZCB0aGUgPGk+RGVmYXVsdCBQYWdlPC9pPiBpcyBsb2FkZWQgYnkgPGI+PGk+U0dOQXRvbTwvYj48L2k+Lg0KICoNCiAqIEBwYXJhbSB7KHZhbHVlOmJvb2xlYW4pPT52b2lkfSBjYWxsYmFjaw0KICovDQp3aW5kb3cuU1VLUiA9IChjYWxsYmFjaykgPT4gew0KCWNvbnN0IFNVS1Jpbml0ID0gZnVuY3Rpb24oKSB7DQoJCWNvbnN0IHBsdWdpbiA9IHRoaXM7DQoJCXBsdWdpbi5vblJlYWR5TGlzdGVuZXIgPSB7fTsNCg0KCQljb25zdCBjYWxsZXJTdGFjayA9IGdldFN0YWNrKClbMF0sDQoJCSAgICAgIGNhbGxlciAgICAgID0gYCR7Y2FsbGVyU3RhY2suZmlsZS5uYW1lfS4ke2NhbGxlclN0YWNrLnNpZ25hdHVyZX06JHtjYWxsZXJTdGFjay5saW5lfToke2NhbGxlclN0YWNrLmNvbHVtbn1gIHx8IG51bGw7DQoNCgkJaWYoY2FsbGVyKQ0KCQkJcGx1Z2luLm9uUmVhZHlMaXN0ZW5lcltjYWxsZXJdID0gY2FsbGJhY2s7DQoJCWVsc2UNCgkJCXB1c2gocGx1Z2luLm9uUmVhZHlMaXN0ZW5lciwgY2FsbGJhY2spOw0KDQoJCXBsdWdpbi50cmlnZ2VyID0gKCkgPT4gew0KCQkJZm9yRWFjaChwbHVnaW4ub25SZWFkeUxpc3RlbmVyLCAobGlzdGVuZXIpID0+IGxpc3RlbmVyKHRydWUpKTsNCgkJfQ0KCX0NCg0KCWNvbnN0IGdldFN0YWNrID0gKHNlYXJjaCA9IG51bGwpID0+IHsNCgkJY29uc3QgcmVnZXggPSAvXig8PyhcdyspKFwuKFx3KykpPz4/KT8gPyhbYS16QS1aMC05Ki88XSspPyA/QD8oaHR0cHM/OlwvXC9bYS16XGQtX10rXC4/W2EtelxkLV9dK1teXHM6Il0rKTooXGQrKTo/KFxkKyk/JC87DQoJCWNvbnN0IGVycm9ycyA9IFtdLA0KCQkgICAgICBzdGFjayAgPSAobmV3IEVycm9yKCkpLnN0YWNrOw0KDQoJCS8vY29uc29sZS5sb2coc3RhY2spOw0KDQoJCWZ1bmN0aW9uIGdldEZpbGVuYW1lQW5kRXh0ZW5zaW9uKHBhdGgpIHsNCgkJCWlmKHBhdGggIT09IHVuZGVmaW5lZCkgew0KCQkJCWNvbnN0IGZpbGVuYW1lZXh0ZW5zaW9uID0gcGF0aC5yZXBsYWNlKC9eLipbXFxcL10vLCAnJyksDQoJCQkJICAgICAgZmlsZW5hbWUgICAgICAgICAgPSBmaWxlbmFtZWV4dGVuc2lvbi5zdWJzdHJpbmcoMCwgZmlsZW5hbWVleHRlbnNpb24ubGFzdEluZGV4T2YoJy4nKSksDQoJCQkJICAgICAgZXh0ICAgICAgICAgICAgICAgPSBmaWxlbmFtZWV4dGVuc2lvbi5zcGxpdCgnLicpLnBvcCgpOw0KDQoJCQkJcmV0dXJuIHsNCgkJCQkJJ25hbWUnOiBmaWxlbmFtZSwNCgkJCQkJJ2V4dCc6IGV4dA0KCQkJCX07DQoJCQl9DQoJCQlyZXR1cm4gew0KCQkJCSduYW1lJzogJycsDQoJCQkJJ2V4dCc6ICcnDQoJCQl9Ow0KCQl9DQoNCgkJc3RhY2suc3BsaXQoIlxuIikuZm9yRWFjaCgodiwgaSkgPT4gew0KCQkJY29uc3QgbWF0Y2ggPSB2Lm1hdGNoKHJlZ2V4KTsNCgkJCWxldCB2YWw7DQoJCQlpZihtYXRjaCAhPT0gbnVsbCkgew0KCQkJCWlmKHYuc3RhcnRzV2l0aCgnQCcpKSB7DQoJCQkJCXZhbCA9IHsNCgkJCQkJCSJzaWduYXR1cmUiOiAiPGFub255bW91cz4iLA0KCQkJCQkJImNsYXNzIjogbWF0Y2hbMl0sDQoJCQkJCQkiZnVuY3Rpb24iOiAiPGFub255bW91cz4iLA0KCQkJCQkJInVybCI6IG1hdGNoWzZdLA0KCQkJCQkJImxpbmUiOiBtYXRjaFs3XSwNCgkJCQkJCSJjb2x1bW4iOiBtYXRjaFs4XSwNCgkJCQkJCSdzdHInOiB2LA0KCQkJCQkJJ2ZpbGUnOiBnZXRGaWxlbmFtZUFuZEV4dGVuc2lvbihtYXRjaFs2XSksDQoJCQkJCX07DQoJCQkJfSBlbHNlIHsNCgkJCQkJdmFsID0gew0KCQkJCQkJInNpZ25hdHVyZSI6IG1hdGNoWzFdLA0KCQkJCQkJImNsYXNzIjogbWF0Y2hbMl0sDQoJCQkJCQkiZnVuY3Rpb24iOiBtYXRjaFs0XSwNCgkJCQkJCSJ1cmwiOiBtYXRjaFs2XSwNCgkJCQkJCSJsaW5lIjogbWF0Y2hbN10sDQoJCQkJCQkiY29sdW1uIjogbWF0Y2hbOF0sDQoJCQkJCQknc3RyJzogdiwNCgkJCQkJCSdmaWxlJzogZ2V0RmlsZW5hbWVBbmRFeHRlbnNpb24obWF0Y2hbNl0pLA0KCQkJCQl9Ow0KCQkJCX0NCgkJCX0NCgkJCWlmKHNlYXJjaCAhPT0gdW5kZWZpbmVkICYmIHNlYXJjaCAhPT0gbnVsbCkgew0KCQkJCWlmKHYuaW5kZXhPZihzZWFyY2gpICE9PSAtMSkNCgkJCQkJZXJyb3JzLnB1c2godmFsKTsNCgkJCX0gZWxzZSB7DQoJCQkJaWYodmFsICE9PSB1bmRlZmluZWQgJiYgdmFsICE9PSAnJyAmJiB2YWwuc2lnbmF0dXJlICE9PSAnZ2V0U3RhY2snICYmIHZhbC5zaWduYXR1cmUgIT09ICdTVUtSaW5pdCcgJiYgdmFsLnNpZ25hdHVyZSAhPT0gJ1NVS1InICYmIHZhbC5zaWduYXR1cmUgIT09ICd3aW5kb3cuU1VLUicpDQoJCQkJCWVycm9ycy5wdXNoKHZhbCk7DQoJCQl9DQoJCX0pOw0KCQlpZihzZWFyY2ggIT09IHVuZGVmaW5lZCAmJiBzZWFyY2ggIT09IG51bGwpDQoJCQlyZXR1cm4gKGVycm9ycy5sZW5ndGggPiAwKSA/IGVycm9yc1swXSA6IG51bGw7DQoJCWVsc2UNCgkJCXJldHVybiBlcnJvcnM7DQoJfTsNCg0KCVNVS1JJbnN0YW5jZXMuaW5zdGFuY2UgPSBuZXcgU1VLUmluaXQoKTsNCn07DQoNCmNvbnN0IHVudGlsID0gKHByZWRpY2F0ZUZuKSA9PiB7DQoJY29uc3QgcG9sbCA9IChkb25lKSA9PiAocHJlZGljYXRlRm4oKSA/IGRvbmUoKSA6IHNldFRpbWVvdXQoKCkgPT4gcG9sbChkb25lKSwgNTAwKSk7DQoJcmV0dXJuIG5ldyBQcm9taXNlKHBvbGwpOw0KfTsNCg0KYXN5bmMgZnVuY3Rpb24gcGF1c2Uodikgew0KCXdoaWxlKHYgPCAxMDApDQoJCWF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDAwKSk7DQp9DQoNCg0KY29uc3QgbG9vcCA9IChhcnIsIGZuLCBidXN5LCBlcnIsIGkgPSAwKSA9PiB7DQoJY29uc3QgYm9keSA9IChvaywgZXIpID0+IHsNCgkJdHJ5IHsNCgkJCWNvbnN0IHIgPSBmbihhcnJbaV0sIGksIGFycik7DQoJCQlyICYmIHIudGhlbiA/IHIudGhlbihvaykuY2F0Y2goZXIpIDogb2socikNCgkJfSBjYXRjaChlKSB7ZXIoZSl9DQoJfQ0KCWNvbnN0IG5leHQgPSAob2ssIGVyKSA9PiAoKSA9PiBsb29wKGFyciwgZm4sIG9rLCBlciwgKytpKQ0KCWNvbnN0IHJ1biA9IChvaywgZXIpID0+IGkgPCBhcnIubGVuZ3RoID8gbmV3IFByb21pc2UoYm9keSkudGhlbihuZXh0KG9rLCBlcikpLmNhdGNoKGVyKSA6IG9rKCkNCglyZXR1cm4gYnVzeSA/IHJ1bihidXN5LCBlcnIpIDogbmV3IFByb21pc2UocnVuKQ0KfQ0KDQovKioqDQogKiBAcmV0dXJuIHtTR05VS0NvbmZpZ30NCiAqLw0KY29uc3QgU0dOVUtDb25maWcgPSBmdW5jdGlvbihjb25maWcpIHsNCgljb25zdCBwbHVnaW4gPSB0aGlzOw0KCWNvbnN0IF9kZWZhdWx0cyA9IHsNCgkJJ3VybHMnOiB7DQoJCQknYXBpJzogew0KCQkJCSdnZW9uYW1lcyc6ICdodHRwczovL3NlY3VyZS5nZW9uYW1lcy5vcmcvJywNCgkJCQknb3NtJzogJ2h0dHBzOi8vbm9taW5hdGltLm9wZW5zdHJlZXRtYXAub3JnLycNCgkJCX0sDQoJCX0NCgl9DQoJcGx1Z2luLmNvbmZpZyA9IHsNCgkJJ2FwaSc6IHsNCgkJCSdnZW9uYW1lcyc6IHVuZGVmaW5lZCAvL3VzZXJuYW1lDQoJCX0sDQoJCSdnZW9jb2RpbmcnOiB7DQoJCQknZGVmYXVsdEFQSSc6ICdvc20nDQoJCX0NCgl9DQoNCgljb25zdCBpbml0ID0gKCkgPT4gew0KCQlwbHVnaW4uY29uZmlnID0gT2JqZWN0LmFzc2lnbihwbHVnaW4uY29uZmlnLCBjb25maWcpOw0KCQlwbHVnaW4uY29uZmlnID0gT2JqZWN0LmFzc2lnbihwbHVnaW4uY29uZmlnLCBfZGVmYXVsdHMpOw0KCX0NCg0KCWluaXQoKTsNCg0KCXJldHVybiBwbHVnaW47DQp9Ow0KDQooKGNhbGxiYWNrKSA9PiB7DQoJY29uc3QgY3NzID0gYC8qDQogKiBDb3B5cmlnaHQgKGMpIDIwMjIgU0dOZXR3b3Jrcy4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCiAqDQogKiBUaGUgc29mdHdhcmUgaXMgYW4gZXhjbHVzaXZlIGNvcHlyaWdodCBvZiAiU0dOZXR3b3JrcyIgYW5kIGlzIHByb3ZpZGVkIGFzIGlzIGV4Y2x1c2l2ZWx5IHdpdGggb25seSAiVVNBR0UiIGFjY2Vzcy4gIk1vZGlmaWNhdGlvbiIsICAiQWx0ZXJhdGlvbiIsICJSZS1kaXN0cmlidXRpb24iIGlzIGNvbXBsZXRlbHkgcHJvaGliaXRlZC4NCiAqIFZJT0xBVElORyBUSEUgQUJPVkUgVEVSTVMgSVMgQSBQVU5JU0hBQkxFIE9GRkVOU0UgV0hJQ0ggTUFZIExFQUQgVE8gTEVHQUwgQ09OU0VRVUVOQ0VTLg0KICovDQoNCi5oYXMtcHJlbG9hZGVyLA0KLmhhcy1wcmVsb2FkZXIgKiB7DQpcdC0tc2duLWJhY2tncm91bmQ6ICNmZmY7DQpcdC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoOiA2cHg7DQpcdC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoOiA0NHB4Ow0KXHQtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1oZWlnaHQ6IDIycHg7DQpcdC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbjogMXB4Ow0KXHQtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1yYWRpdXM6IDZweDsNCn0NCg0KQG1lZGlhIGFsbCBhbmQgKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKSB7DQpcdC5oYXMtcHJlbG9hZGVyLA0KXHQuaGFzLXByZWxvYWRlciAqIHsNClx0LS1zZ24tYmFja2dyb3VuZDogIzAwMDsNClx0fQ0KfQ0KDQpib2R5IHsNClx0bWFyZ2luOiAwOw0KXHRkaXNwbGF5OiBub25lOw0KfQ0KDQouaGFzLXByZWxvYWRlciB7DQpcdG92ZXJmbG93OiBoaWRkZW4gIWltcG9ydGFudDsNClxkaXNwbGF5OiBibG9jazsNCn0NCg0KLnNnbi1wcmVsb2FkZXIgew0KXHRwYWRkaW5nOiAwOw0KXHR3aWR0aDogMTAwJTsNClx0aGVpZ2h0OiAxMDAlOw0KXHRiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1zZ24tYmFja2dyb3VuZCk7DQpcdGRpc3BsYXk6IGZsZXg7DQpcdGp1c3RpZnktY29udGVudDogY2VudGVyOw0KXHRhbGlnbi1pdGVtczogY2VudGVyOw0KXHRwb3NpdGlvbjogYWJzb2x1dGU7DQpcdHotaW5kZXg6IDk5OTk5OTsNCn0NCg0KDQouc2duLXByZWxvYWRlciA+IC5wcmVsb2FkZXIgew0KXHRwb3NpdGlvbjogcmVsYXRpdmU7DQpcdGRpc3BsYXk6IGlubGluZS1mbGV4Ow0KXHRqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsNClx0YWxpZ24taXRlbXM6IGNlbnRlcjsNCn0NCg0KLnNnbi1wcmVsb2FkZXIgPiAucHJlbG9hZGVyID4gLnNwaW5uZXIgew0KXHRhbmltYXRpb246IHJvdGF0ZSAxMHMgaW5maW5pdGUgbGluZWFyOw0KXHRwb3NpdGlvbjogcmVsYXRpdmU7DQpcdGRpc3BsYXk6IGlubGluZS1mbGV4Ow0KXHRqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsNClx0YWxpZ24taXRlbXM6IGNlbnRlcjsNClx0d2lkdGg6IDEwMCU7DQpcdGhlaWdodDogMTAwJTsNCn0NCg0KDQouc2duLXByZWxvYWRlciA+IC5wcmVsb2FkZXIgPiBpbWcgew0KXHR3aWR0aDogY2FsYyh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtd2lkdGgpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikpOw0KXHRoZWlnaHQ6IGNhbGModmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLWhlaWdodCkgKyAodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSk7DQpcdG1hcmdpbjogdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbik7DQpcdGRpc3BsYXk6IGZsZXg7DQpcdGp1c3RpZnktY29udGVudDogY2VudGVyOw0KXHRhbGlnbi1pdGVtczogY2VudGVyOw0KXHRwb3NpdGlvbjogcmVsYXRpdmU7DQpcdHRvcDogNTAlOw0KXHRsZWZ0OiA1MCU7DQpcdGFuaW1hdGlvbjogc3BpbiA0cyBlYXNlLWluLW91dCBmb3J3YXJkcyBpbmZpbml0ZTsNCn0NCi5zZ24tcHJlbG9hZGVyID4gLnByZWxvYWRlciA+IC5zcGlubmVyID4gaW1nIHsNClx0d2lkdGg6IGNhbGModmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoKSk7DQpcdGhlaWdodDogY2FsYyh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtd2lkdGgpKTsNClx0bWFyZ2luOiB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKTsNCn0NCi5zZ24tcHJlbG9hZGVyID4gLnByZWxvYWRlciA+IC5zcGlubmVyID4gaSB7DQpcdGFuaW1hdGlvbjogcm90YXRlIDNzIGluZmluaXRlIGN1YmljLWJlemllcigwLjA5LCAwLjYsIDAuOCwgMC4wMyk7DQpcdHRyYW5zZm9ybS1vcmlnaW46IDUwJSAxMDAlIDA7DQpcdHBvc2l0aW9uOiBhYnNvbHV0ZTsNClx0ZGlzcGxheTogaW5saW5lLWZsZXg7DQpcdGp1c3RpZnktY29udGVudDogY2VudGVyOw0KXHRhbGlnbi1pdGVtczogY2VudGVyOw0KXHR0b3A6IDUwJTsNClx0bGVmdDogNTAlOw0KXHRib3JkZXI6IHNvbGlkIHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgdHJhbnNwYXJlbnQ7DQpcdGJvcmRlci1ib3R0b206IG5vbmU7DQp9DQouc2duLXByZWxvYWRlciA+IC5wcmVsb2FkZXIgPiAuc3Bpbm5lciA+IGk6bnRoLWNoaWxkKDEpIHsNClx0LW1vei1hbmltYXRpb24tdGltaW5nLWZ1bmN0aW9uOiBjdWJpYy1iZXppZXIoMC4wOSwgMC4zLCAwLjEyLCAwLjAzKTsNClx0LXdlYmtpdC1hbmltYXRpb24tdGltaW5nLWZ1bmN0aW9uOiBjdWJpYy1iZXppZXIoMC4wOSwgMC4zLCAwLjEyLCAwLjAzKTsNClx0YW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogY3ViaWMtYmV6aWVyKDAuMDksIDAuMywgMC4xMiwgMC4wMyk7DQpcdHdpZHRoOiB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtd2lkdGgpOw0KXHRoZWlnaHQ6IHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1oZWlnaHQpOw0KXHRtYXJnaW4tdG9wOiBjYWxjKDBweCAtIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1oZWlnaHQpKTsNClx0bWFyZ2luLWxlZnQ6IGNhbGMoMHB4IC0gdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLWhlaWdodCkpOw0KXHRib3JkZXItY29sb3I6ICMyMTcyYjg7DQpcdGJvcmRlci10b3AtbGVmdC1yYWRpdXM6IGNhbGMoKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy13aWR0aCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiAyKSAqIDEpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXJhZGl1cykpOw0KXHRib3JkZXItdG9wLXJpZ2h0LXJhZGl1czogY2FsYygodmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoKSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogMSkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtcmFkaXVzKSk7DQp9DQouc2duLXByZWxvYWRlciA+IC5wcmVsb2FkZXIgPiAuc3Bpbm5lciA+IGk6bnRoLWNoaWxkKDIpIHsNClx0LW1vei1hbmltYXRpb24tdGltaW5nLWZ1bmN0aW9uOiBjdWJpYy1iZXppZXIoMC4wOSwgMC42LCAwLjI0LCAwLjAzKTsNClx0LXdlYmtpdC1hbmltYXRpb24tdGltaW5nLWZ1bmN0aW9uOiBjdWJpYy1iZXppZXIoMC4wOSwgMC42LCAwLjI0LCAwLjAzKTsNClx0YW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogY3ViaWMtYmV6aWVyKDAuMDksIDAuNiwgMC4yNCwgMC4wMyk7DQpcdHdpZHRoOiBjYWxjKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy13aWR0aCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiAyKSk7DQpcdGhlaWdodDogY2FsYyh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KSArICh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpKTsNClx0bWFyZ2luLXRvcDogY2FsYygwcHggLSAodmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLWhlaWdodCkgKyAodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSkpOw0KXHRtYXJnaW4tbGVmdDogY2FsYygwcHggLSAodmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLWhlaWdodCkgKyAodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSkpOw0KXHRib3JkZXItY29sb3I6ICMxOGEzOWI7DQpcdGJvcmRlci10b3AtbGVmdC1yYWRpdXM6IGNhbGMoKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy13aWR0aCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiAyKSAqIDIpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXJhZGl1cykpOw0KXHRib3JkZXItdG9wLXJpZ2h0LXJhZGl1czogY2FsYygodmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoKSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogMikgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtcmFkaXVzKSk7DQp9DQouc2duLXByZWxvYWRlciA+IC5wcmVsb2FkZXIgPiAuc3Bpbm5lciA+IGk6bnRoLWNoaWxkKDMpIHsNClx0LW1vei1hbmltYXRpb24tdGltaW5nLWZ1bmN0aW9uOiBjdWJpYy1iZXppZXIoMC4wOSwgMC45LCAwLjM2LCAwLjAzKTsNClx0LXdlYmtpdC1hbmltYXRpb24tdGltaW5nLWZ1bmN0aW9uOiBjdWJpYy1iZXppZXIoMC4wOSwgMC45LCAwLjM2LCAwLjAzKTsNClx0YW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogY3ViaWMtYmV6aWVyKDAuMDksIDAuOSwgMC4zNiwgMC4wMyk7DQpcdHdpZHRoOiBjYWxjKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy13aWR0aCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiAyKSAqIDIpOw0KXHRoZWlnaHQ6IGNhbGModmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLWhlaWdodCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiAyKSk7DQpcdG1hcmdpbi10b3A6IGNhbGMoMHB4IC0gKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1oZWlnaHQpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikpKTsNClx0bWFyZ2luLWxlZnQ6IGNhbGMoMHB4IC0gKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1oZWlnaHQpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikpKTsNClx0Ym9yZGVyLWNvbG9yOiAjODJjNTQ1Ow0KXHRib3JkZXItdG9wLWxlZnQtcmFkaXVzOiBjYWxjKCh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtd2lkdGgpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikgKiAyKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1yYWRpdXMpKTsNClx0Ym9yZGVyLXRvcC1yaWdodC1yYWRpdXM6IGNhbGMoKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy13aWR0aCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiAyKSAqIDIpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXJhZGl1cykpOw0KfQ0KLnNnbi1wcmVsb2FkZXIgPiAucHJlbG9hZGVyID4gLnNwaW5uZXIgPiBpOm50aC1jaGlsZCg0KSB7DQpcdC1tb3otYW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogY3ViaWMtYmV6aWVyKDAuMDksIDEuMiwgMC40OCwgMC4wMyk7DQpcdC13ZWJraXQtYW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogY3ViaWMtYmV6aWVyKDAuMDksIDEuMiwgMC40OCwgMC4wMyk7DQpcdGFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb246IGN1YmljLWJlemllcigwLjA5LCAxLjIsIDAuNDgsIDAuMDMpOw0KXHR3aWR0aDogY2FsYyh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtd2lkdGgpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikgKiAzKTsNClx0aGVpZ2h0OiBjYWxjKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1oZWlnaHQpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikgKiAxLjUpOw0KXHRtYXJnaW4tdG9wOiBjYWxjKDBweCAtICh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDMpKSk7DQpcdG1hcmdpbi1sZWZ0OiBjYWxjKDBweCAtICh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDMpKSk7DQpcdGJvcmRlci1jb2xvcjogI2Y4YjczOTsNClx0Ym9yZGVyLXRvcC1sZWZ0LXJhZGl1czogY2FsYygodmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoKSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogMykgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtcmFkaXVzKSk7DQpcdGJvcmRlci10b3AtcmlnaHQtcmFkaXVzOiBjYWxjKCh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtd2lkdGgpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikgKiAzKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1yYWRpdXMpKTsNCn0NCi5zZ24tcHJlbG9hZGVyID4gLnByZWxvYWRlciA+IC5zcGlubmVyID4gaTpudGgtY2hpbGQoNSkgew0KXHQtbW96LWFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb246IGN1YmljLWJlemllcigwLjA5LCAxLjUsIDAuNiwgMC4wMyk7DQpcdC13ZWJraXQtYW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogY3ViaWMtYmV6aWVyKDAuMDksIDEuNSwgMC42LCAwLjAzKTsNClx0YW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogY3ViaWMtYmV6aWVyKDAuMDksIDEuNSwgMC42LCAwLjAzKTsNClx0d2lkdGg6IGNhbGModmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoKSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogNCk7DQpcdGhlaWdodDogY2FsYyh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogMik7DQpcdG1hcmdpbi10b3A6IGNhbGMoMHB4IC0gKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1oZWlnaHQpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogNCkpKTsNClx0bWFyZ2luLWxlZnQ6IGNhbGMoMHB4IC0gKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1oZWlnaHQpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogNCkpKTsNClx0Ym9yZGVyLWNvbG9yOiAjZjA2MDQ1Ow0KXHRib3JkZXItdG9wLWxlZnQtcmFkaXVzOiBjYWxjKCh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtd2lkdGgpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikgKiA0KSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1yYWRpdXMpKTsNClx0Ym9yZGVyLXRvcC1yaWdodC1yYWRpdXM6IGNhbGMoKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy13aWR0aCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiAyKSAqIDQpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXJhZGl1cykpOw0KfQ0KLnNnbi1wcmVsb2FkZXIgPiAucHJlbG9hZGVyID4gLnNwaW5uZXIgPiBpOm50aC1jaGlsZCg2KSB7DQpcdC1tb3otYW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogY3ViaWMtYmV6aWVyKDAuMDksIDEuOCwgMC43MiwgMC4wMyk7DQpcdC13ZWJraXQtYW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogY3ViaWMtYmV6aWVyKDAuMDksIDEuOCwgMC43MiwgMC4wMyk7DQpcdGFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb246IGN1YmljLWJlemllcigwLjA5LCAxLjgsIDAuNzIsIDAuMDMpOw0KXHR3aWR0aDogY2FsYyh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtd2lkdGgpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikgKiA1KTsNClx0aGVpZ2h0OiBjYWxjKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1oZWlnaHQpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikgKiAyLjUpOw0KXHRtYXJnaW4tdG9wOiBjYWxjKDBweCAtICh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDUpKSk7DQpcdG1hcmdpbi1sZWZ0OiBjYWxjKDBweCAtICh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDUpKSk7DQpcdGJvcmRlci1jb2xvcjogI2VkMjg2MTsNClx0Ym9yZGVyLXRvcC1sZWZ0LXJhZGl1czogY2FsYygodmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoKSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogNSkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtcmFkaXVzKSk7DQpcdGJvcmRlci10b3AtcmlnaHQtcmFkaXVzOiBjYWxjKCh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtd2lkdGgpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikgKiA1KSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1yYWRpdXMpKTsNCn0NCi5zZ24tcHJlbG9hZGVyID4gLnByZWxvYWRlciA+IC5zcGlubmVyID4gaTpudGgtY2hpbGQoNykgew0KXHQtbW96LWFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb246IGN1YmljLWJlemllcigwLjA5LCAyLjEsIDAuODQsIDAuMDMpOw0KXHQtd2Via2l0LWFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb246IGN1YmljLWJlemllcigwLjA5LCAyLjEsIDAuODQsIDAuMDMpOw0KXHRhbmltYXRpb24tdGltaW5nLWZ1bmN0aW9uOiBjdWJpYy1iZXppZXIoMC4wOSwgMi4xLCAwLjg0LCAwLjAzKTsNClx0d2lkdGg6IGNhbGModmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoKSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogNik7DQpcdGhlaWdodDogY2FsYyh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogMyk7DQpcdG1hcmdpbi10b3A6IGNhbGMoMHB4IC0gKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1oZWlnaHQpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogNikpKTsNClx0bWFyZ2luLWxlZnQ6IGNhbGMoMHB4IC0gKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1oZWlnaHQpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogNikpKTsNClx0Ym9yZGVyLWNvbG9yOiAjYzEyNjgwOw0KXHRib3JkZXItdG9wLWxlZnQtcmFkaXVzOiBjYWxjKCh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtd2lkdGgpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikgKiA2KSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1yYWRpdXMpKTsNClx0Ym9yZGVyLXRvcC1yaWdodC1yYWRpdXM6IGNhbGMoKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy13aWR0aCkgKyAoKHZhcigtLXNnbi1wcmVsb2FkZXItc3RyaXBlcy13aWR0aCkgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtbWFyZ2luKSkgKiAyKSAqIDYpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXJhZGl1cykpOw0KfQ0KLnNnbi1wcmVsb2FkZXIgPiAucHJlbG9hZGVyID4gLnNwaW5uZXIgPiBpOm50aC1jaGlsZCg4KSB7DQpcdC1tb3otYW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogY3ViaWMtYmV6aWVyKDAuMDksIDIuNCwgMC45NiwgMC4wMyk7DQpcdC13ZWJraXQtYW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogY3ViaWMtYmV6aWVyKDAuMDksIDIuNCwgMC45NiwgMC4wMyk7DQpcdGFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb246IGN1YmljLWJlemllcigwLjA5LCAyLjQsIDAuOTYsIDAuMDMpOw0KXHR3aWR0aDogY2FsYyh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtd2lkdGgpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikgKiA3KTsNClx0aGVpZ2h0OiBjYWxjKHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1oZWlnaHQpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikgKiAzLjUpOw0KXHRtYXJnaW4tdG9wOiBjYWxjKDBweCAtICh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDcpKSk7DQpcdG1hcmdpbi1sZWZ0OiBjYWxjKDBweCAtICh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtaGVpZ2h0KSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDcpKSk7DQpcdGJvcmRlci1jb2xvcjogIzVkMzE5MTsNClx0Ym9yZGVyLXRvcC1sZWZ0LXJhZGl1czogY2FsYygodmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLXdpZHRoKSArICgodmFyKC0tc2duLXByZWxvYWRlci1zdHJpcGVzLXdpZHRoKSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1tYXJnaW4pKSAqIDIpICogNykgKyB2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtcmFkaXVzKSk7DQpcdGJvcmRlci10b3AtcmlnaHQtcmFkaXVzOiBjYWxjKCh2YXIoLS1zZ24tcHJlbG9hZGVyLWNpcmNsZXMtd2lkdGgpICsgKCh2YXIoLS1zZ24tcHJlbG9hZGVyLXN0cmlwZXMtd2lkdGgpICsgdmFyKC0tc2duLXByZWxvYWRlci1jaXJjbGVzLW1hcmdpbikpICogMikgKiA3KSArIHZhcigtLXNnbi1wcmVsb2FkZXItY2lyY2xlcy1yYWRpdXMpKTsNCn0NCg0KQC1tb3ota2V5ZnJhbWVzIHJvdGF0ZSB7DQpcdHRvIHsNClx0XHR0cmFuc2Zvcm06IHJvdGF0ZSgzNjBkZWcpOw0KXHR9DQp9DQpALXdlYmtpdC1rZXlmcmFtZXMgcm90YXRlIHsNClx0dG8gew0KXHRcdHRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7DQpcdH0NCn0NCkBrZXlmcmFtZXMgcm90YXRlIHsNClx0dG8gew0KXHRcdHRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7DQpcdH0NCn0NCg0KQGtleWZyYW1lcyBwdWxzZSB7DQpcdGZyb20gew0KXHRcdHRyYW5zZm9ybTogc2NhbGUoLjgpOw0KXHR9DQpcdHRvIHsNClx0XHR0cmFuc2Zvcm06IHNjYWxlKDEpOw0KXHR9DQp9DQoNCkBrZXlmcmFtZXMgc3BpbiB7DQpcdDAlIHsNClx0XHR0cmFuc2Zvcm06IHJvdGF0ZVkoMGRlZyk7DQpcdH0NClx0NTAlIHsNClx0XHR0cmFuc2Zvcm06IHJvdGF0ZVkoMTgwZGVnKTsNClx0fQ0KXHQxMDAlIHsNClx0XHR0cmFuc2Zvcm06IHJvdGF0ZVkoMzYwZGVnKTsNClx0fQ0KfQ0KDQpgOw0KCWNvbnN0IGhlYWQgID0gZG9jdW1lbnQuaGVhZCB8fCBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgiaGVhZCIpWzBdLA0KCSAgICAgIHN0eWxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic3R5bGUiKTsNCgljb25zdCBjdXJyZW50U2NyaXB0ID0gZG9jdW1lbnQuY3VycmVudFNjcmlwdCB8fCBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCJzY3JpcHRbc3JjKj1cIlNHTlVJS2l0LmxvYWRlci5qc1wiXSIpOw0KDQoJaGVhZC5hcHBlbmRDaGlsZChzdHlsZSk7DQoJc3R5bGUudHlwZSA9ICJ0ZXh0L2NzcyI7DQoJc3R5bGUuaWQgPSAic2duLXVpa2l0LXN0eWxlcyI7DQoJaWYoc3R5bGUuc3R5bGVTaGVldCkgew0KCQkvLyBUaGlzIGlzIHJlcXVpcmVkIGZvciBJRTggYW5kIGJlbG93Lg0KCQlzdHlsZS5zdHlsZVNoZWV0LmNzc1RleHQgPSBjc3M7DQoJfSBlbHNlIHsNCgkJc3R5bGUuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoY3NzKSk7DQoJfQ0KCWxldCBwcmVsb2FkZXJFbGVtID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiZGl2Iik7DQoJcHJlbG9hZGVyRWxlbS5jbGFzc05hbWUgPSAic2duLXByZWxvYWRlciI7DQoJbGV0IHByZWxvYWRlciA9IGBcdFx0XHQ8ZGl2IGNsYXNzPSJwcmVsb2FkZXIiPlxuYDsNCgljb25zdCBpY29uID0gY3VycmVudFNjcmlwdC5nZXRBdHRyaWJ1dGUoJ3Nnbi11aS1raXQtbG9hZGVyLWljb24nKTsNCglpZihpY29uICE9PSB1bmRlZmluZWQpDQoJCXByZWxvYWRlciArPSBgXHRcdFx0XHQ8aW1nIHNyYz0iJHtpY29ufSIgYWx0PSJJQ09OIj5cbmA7DQoJcHJlbG9hZGVyICs9IGBcdFx0XHRcdDxkaXYgY2xhc3M9InNwaW5uZXIiPlxuYDsNCglwcmVsb2FkZXIgKz0gYFx0XHRcdFx0XHQ8aT48L2k+XG5gOw0KCXByZWxvYWRlciArPSBgXHRcdFx0XHRcdDxpPjwvaT5cbmA7DQoJcHJlbG9hZGVyICs9IGBcdFx0XHRcdFx0PGk+PC9pPlxuYDsNCglwcmVsb2FkZXIgKz0gYFx0XHRcdFx0XHQ8aT48L2k+XG5gOw0KCXByZWxvYWRlciArPSBgXHRcdFx0XHRcdDxpPjwvaT5cbmA7DQoJcHJlbG9hZGVyICs9IGBcdFx0XHRcdFx0PGk+PC9pPlxuYDsNCglwcmVsb2FkZXIgKz0gYFx0XHRcdFx0XHQ8aT48L2k+XG5gOw0KCXByZWxvYWRlciArPSBgXHRcdFx0XHRcdDxpPjwvaT5cbmA7DQoJcHJlbG9hZGVyICs9IGBcdFx0XHRcdDwvZGl2PlxuYDsNCglwcmVsb2FkZXIgKz0gYFx0XHRcdDwvZGl2PlxuYDsNCglwcmVsb2FkZXIgKz0gYFx0XHQ8L2Rpdj5cbmA7DQoNCglwcmVsb2FkZXJFbGVtLmlubmVySFRNTCA9IHByZWxvYWRlcjsNCg0KCXdpbmRvdy5vbmxvYWQgPSBmdW5jdGlvbigpIHsNCgkJZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QuYWRkKCJoYXMtcHJlbG9hZGVyIik7DQoJCWRvY3VtZW50LmJvZHkuaW5zZXJ0QmVmb3JlKHByZWxvYWRlckVsZW0sIGRvY3VtZW50LmJvZHkuZmlyc3RDaGlsZCk7DQoNCgkJaWYodHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKQ0KCQkJY2FsbGJhY2soKTsNCgl9Ow0KfSkoKCkgPT4gew0KCWZ1bmN0aW9uIGdldEZpbGVuYW1lQW5kRXh0ZW5zaW9uKHBhdGgpIHsNCgkJaWYocGF0aCAhPT0gdW5kZWZpbmVkKSB7DQoJCQljb25zdCBmaWxlbmFtZWV4dGVuc2lvbiA9IHBhdGgucmVwbGFjZSgvXi4qW1xcXC9dLywgJycpLA0KCQkJICAgICAgZmlsZW5hbWUgICAgICAgICAgPSBmaWxlbmFtZWV4dGVuc2lvbi5zdWJzdHJpbmcoMCwgZmlsZW5hbWVleHRlbnNpb24ubGFzdEluZGV4T2YoJy4nKSksDQoJCQkgICAgICBleHQgICAgICAgICAgICAgICA9IGZpbGVuYW1lZXh0ZW5zaW9uLnNwbGl0KCcuJykucG9wKCk7DQoNCgkJCXJldHVybiB7DQoJCQkJJ25hbWUnOiBmaWxlbmFtZSwNCgkJCQknZXh0JzogZXh0DQoJCQl9Ow0KCQl9DQoJCXJldHVybiB7DQoJCQknbmFtZSc6ICcnLA0KCQkJJ2V4dCc6ICcnDQoJCX07DQoJfQ0KDQoJaWYodHlwZW9mIEhUTUxFbGVtZW50LnByb3RvdHlwZS5hdHRyICE9PSAiZnVuY3Rpb24iKSB7DQoJCUhUTUxFbGVtZW50LnByb3RvdHlwZS5hdHRyID0gZnVuY3Rpb24obmFtZSwgdmFsdWUpIHsNCgkJCWlmKHZhbHVlID09PSB1bmRlZmluZWQpIHsNCgkJCQlyZXR1cm4gdGhpcy5nZXRBdHRyaWJ1dGUobmFtZSk7DQoJCQl9IGVsc2UNCgkJCQl0aGlzLnNldEF0dHJpYnV0ZShuYW1lLCB2YWx1ZSk7DQoJCX07DQoJfQ0KDQoJaWYodHlwZW9mIEhUTUxFbGVtZW50LnByb3RvdHlwZS5mYWRlSW4gIT09ICJmdW5jdGlvbiIpIHsNCgkJSFRNTEVsZW1lbnQucHJvdG90eXBlLmZhZGVJbiA9IGZ1bmN0aW9uKHNwZWVkLCBjYWxsYmFjaykgew0KCQkJbGV0IF90aGlzID0gdGhpczsNCgkJCXNwZWVkID0gKHR5cGVvZiBzcGVlZCAhPT0gIm51bWJlciIpID8gMjAwMCA6IHNwZWVkOw0KDQoJCQlpZighX3RoaXMuc3R5bGUub3BhY2l0eSkgew0KCQkJCV90aGlzLnN0eWxlLm9wYWNpdHkgPSAoc3BlZWQgPiAwKSA/IDAgOiAxOw0KCQkJfQ0KDQoJCQlpZihzcGVlZCA+IDApIHsNCgkJCQljb25zdCBpbkludGVydmFsID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24oKSB7DQoJCQkJCV90aGlzLnN0eWxlLm9wYWNpdHkgPSBOdW1iZXIoX3RoaXMuc3R5bGUub3BhY2l0eSkgKyAwLjAyOw0KCQkJCQlpZihfdGhpcy5zdHlsZS5vcGFjaXR5ID49IDEpIHsNCgkJCQkJCWNsZWFySW50ZXJ2YWwoaW5JbnRlcnZhbCk7DQoNCgkJCQkJCWlmKHR5cGVvZiBjYWxsYmFjayA9PT0gImZ1bmN0aW9uIikNCgkJCQkJCQljYWxsYmFjayhfdGhpcyk7DQoJCQkJCX0NCgkJCQl9LCBzcGVlZCAvIDUwKTsNCgkJCX0gZWxzZSB7DQoJCQkJaWYodHlwZW9mIGNhbGxiYWNrID09PSAiZnVuY3Rpb24iKQ0KCQkJCQljYWxsYmFjayhfdGhpcyk7DQoJCQl9DQoJCX07DQoJfQ0KDQoJaWYodHlwZW9mIEhUTUxFbGVtZW50LnByb3RvdHlwZS5mYWRlT3V0ICE9PSAiZnVuY3Rpb24iKSB7DQoJCUhUTUxFbGVtZW50LnByb3RvdHlwZS5mYWRlT3V0ID0gZnVuY3Rpb24oc3BlZWQsIGNhbGxiYWNrKSB7DQoJCQlsZXQgX3RoaXMgPSB0aGlzOw0KCQkJc3BlZWQgPSAodHlwZW9mIHNwZWVkICE9PSAibnVtYmVyIikgPyAyMDAwIDogc3BlZWQ7DQoNCgkJCWlmKCFfdGhpcy5zdHlsZS5vcGFjaXR5KSB7DQoJCQkJX3RoaXMuc3R5bGUub3BhY2l0eSA9IChzcGVlZCA+IDApID8gMSA6IDA7DQoJCQl9DQoNCgkJCWlmKHNwZWVkID4gMCkgew0KCQkJCWNvbnN0IG91dEludGVydmFsID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24oKSB7DQoJCQkJCV90aGlzLnN0eWxlLm9wYWNpdHkgLT0gMC4wMjsNCgkJCQkJaWYoX3RoaXMuc3R5bGUub3BhY2l0eSA8PSAwKSB7DQoJCQkJCQljbGVhckludGVydmFsKG91dEludGVydmFsKTsNCg0KCQkJCQkJaWYodHlwZW9mIGNhbGxiYWNrID09PSAiZnVuY3Rpb24iKQ0KCQkJCQkJCWNhbGxiYWNrKF90aGlzKTsNCgkJCQkJfQ0KCQkJCX0sIHNwZWVkIC8gNTApOw0KCQkJfSBlbHNlIHsNCgkJCQlpZih0eXBlb2YgY2FsbGJhY2sgPT09ICJmdW5jdGlvbiIpDQoJCQkJCWNhbGxiYWNrKF90aGlzKTsNCgkJCX0NCgkJfTsNCgl9DQoNCgkoYXN5bmMgcHJlY2FsbGJhY2sgPT4gew0KCQljb25zdCB0aXRsZSA9IGRvY3VtZW50LnRpdGxlOw0KCQlpZih0aXRsZSAhPT0gdW5kZWZpbmVkKQ0KCQkJZG9jdW1lbnQudGl0bGUgPSAiTG9hZGluZy4uLiI7DQoNCgkJaWYod2luZG93LmpRdWVyeSkNCgkJCSQuaG9sZFJlYWR5KHRydWUpOw0KDQoJCWNvbnN0IGN1cnJlbnRTY3JpcHQgPSBkb2N1bWVudC5jdXJyZW50U2NyaXB0IHx8IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoInNjcmlwdFtzcmMqPVwiU0dOVUlLaXQubG9hZGVyLmpzXCJdIik7DQoJCWNvbnN0IHVybCA9IGN1cnJlbnRTY3JpcHQuc3JjLnNwbGl0KCIvIikuc2xpY2UoMCwgLTIpLmpvaW4oIi8iKSArICIvIjsNCgkJY29uc3QgcHJlbG9hZCA9IFsNCgkJCS8vImpzL2kxOG4vU0dOaTE4bi5qcyIsDQoJCV07DQoJCS8qaWYoIXdpbmRvdy5qUXVlcnkgfHwgalF1ZXJ5ID09PSB1bmRlZmluZWQpDQoJCSBwcmVsb2FkLnB1c2goJ2FkZG9ucy9qUXVlcnkvalF1ZXJ5Lm1pbi5qcycpOyovDQoNCgkJbGV0IGZpbGVzbG9hZGVkID0gMDsNCgkJY29uc3QgZmlsZXN0b2xvYWQgPSBwcmVsb2FkLmxlbmd0aDsNCg0KCQlmb3IobGV0IGkgPSAwOyBpIDwgZmlsZXN0b2xvYWQ7IGkrKykgew0KCQkJY29uc3QgY29tcG9uZW50ID0gcHJlbG9hZFtpXSwNCgkJCSAgICAgIHNyYyAgICAgICA9IHVybCArIGNvbXBvbmVudCwNCgkJCSAgICAgIG5hbWUgICAgICA9ICdqc18nICsgZ2V0RmlsZW5hbWVBbmRFeHRlbnNpb24oY29tcG9uZW50KS5uYW1lOw0KCQkJY29uc3Qgb2JqID0ge307DQoJCQlvYmpbbmFtZV0gPSBjb21wb25lbnQ7DQoNCgkJCWlmKCFTR05VSUtpdC5pc0NvbXBvbmVudExvYWRlZChuYW1lKSkgew0KCQkJCWNvbnN0IHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInNjcmlwdCIpOw0KCQkJCXNjcmlwdC5zcmMgPSBzcmM7DQoJCQkJc2NyaXB0LmFzeW5jID0gZmFsc2U7DQoJCQkJc2NyaXB0LmRlZmVyID0gZmFsc2U7DQoJCQkJY3VycmVudFNjcmlwdC5hZnRlcihzY3JpcHQpOw0KCQkJCWlmKGkgPT09IDApDQoJCQkJCXNjcmlwdC5pZCA9ICJzZ24tcHJlbG9hZC1lbmQiOw0KDQoJCQkJLyphd2FpdCBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHsNCgkJCQkgc2NyaXB0Lm9ubG9hZCA9IGZ1bmN0aW9uKCkgew0KCQkJCSBmaWxlc2xvYWRlZCsrOw0KCQkJCSBzY3JpcHQub25sb2FkID0gbnVsbDsNCgkJCQkgcmVzb2x2ZSgpOw0KCQkJCSB9Ow0KCQkJCSB9KS50aGVuKHIgPT4gZmluaXNoTG9hZCgpKTsqLw0KCQkJCXNjcmlwdC5vbmxvYWQgPSBmdW5jdGlvbigpIHsNCgkJCQkJZmlsZXNsb2FkZWQrKzsNCgkJCQkJU0dOVUlLaXQuY29tcG9uZW50ID0gb2JqOw0KCQkJCQlzY3JpcHQub25sb2FkID0gbnVsbDsNCgkJCQkJZmluaXNoTG9hZCgpOw0KCQkJCX07DQoJCQl9IGVsc2Ugew0KCQkJCWZpbGVzbG9hZGVkKys7DQoJCQkJYXdhaXQgZmluaXNoTG9hZCgpOw0KCQkJfQ0KCQl9DQoNCgkJbGV0IHByb2dyZXNzID0gMDsNCg0KCQlhc3luYyBmdW5jdGlvbiBmaW5pc2hMb2FkKCkgew0KCQkJcHJvZ3Jlc3MgPSBNYXRoLnJvdW5kKChmaWxlc2xvYWRlZCAqIDEwMCkgLyBmaWxlc3RvbG9hZCk7DQoNCgkJCWF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gew0KCQkJCWlmKGZpbGVzbG9hZGVkID49IGZpbGVzdG9sb2FkKSB7DQoJCQkJCXJlc29sdmUoKTsNCgkJCQl9DQoJCQl9KS50aGVuKGZ1bmN0aW9uKCkgew0KCQkJCWltcG9ydCgiLi9oZWxwZXJzL2hlbHBlcnMuanMiKTsNCgkJCQkkKCJoZWFkID4gdGl0bGUiKS50ZXh0KHRpdGxlKTsNCgkJCQlpZih0eXBlb2YgcHJlY2FsbGJhY2sgPT09ICJmdW5jdGlvbiIgJiYgcHJvZ3Jlc3MgPT09IDEwMCkNCgkJCQkJcHJlY2FsbGJhY2soKTsNCgkJCX0pOw0KCQl9DQoNCgkJd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ29mZmxpbmUnLCAoZSkgPT4gew0KCQkJY29uc3QgZ2V0STE4blN0cmluZyA9IChrLCBtKSA9PiBtOw0KCQkJLy9pZih0eXBlb2YgZ2V0STE4blN0cmluZyAhPT0gJ2Z1bmN0aW9uJykNCgkJCWNvbnN0ICRib2R5ID0gJCgnYm9keScpOw0KCQkJbGV0IG9mZmxpbmVFcnJvck1zZyA9IChTR05VSUtpdC5yZWFkeSkgPyBnZXRJMThuU3RyaW5nKCdzZ25fdWlraXRfZXJyb3JfdXNlcl9vZmZsaW5lX21zZycsIGBTb3JyeSEgWW91IGFyZSBjdXJyZW50bHkgb2ZmbGluZS4gWW91J2xsIGJlIGFibGUgdG8gYWNjZXNzIHRoZSBhcHBsaWNhdGlvbiBvbmNlIHlvdXIgaW50ZXJuZXQgY29ubmVjdGlvbiBpcyByZXN0b3JlZC5gKSA6IGdldEkxOG5TdHJpbmcoJ3Nnbl91aWtpdF91c2VyX29mZmxpbmVfbG9hZGluZ19pbnRlcnJ1cHRlZF9tc2cnLCBgU29ycnkhIEluaXRpYWwgbG9hZGluZyBpcyBpbnRlcnJ1cHRlZC4gVGhlIGFwcGxpY2F0aW9uIHdpbGwgY29udGludWUgdG8gbG9hZCBvbmNlIHlvdXIgaW50ZXJuZXQgY29ubmVjdGlvbiBpcyByZXN0b3JlZC5gKTsNCgkJCWlmKHByb2dyZXNzIDwgMTAwKQ0KCQkJCW9mZmxpbmVFcnJvck1zZyA9IGdldEkxOG5TdHJpbmcoJ3Nnbl91aWtpdF91c2VyX29mZmxpbmVfcHJlbG9hZF9mYWlsZWRfbXNnJywgYEhvb3JheSEgWW91ciBpbnRlcm5ldCBjb25uZWN0aW9uIGlzIHJlc3RvcmVkLCBidXQgaXQgaGFzIGJyb2tlbiB0aGUgYXBwbGljYXRpb24ncyBwcmVsb2FkIHByb2Nlc3MsIHBsZWFzZSByZWxvYWQgdGhlIHBhZ2UgdG8gZml4IGl0LmApOw0KCQkJY29uc3Qgb2ZmbGluZUVycm9ySGVhZGluZyA9IGdldEkxOG5TdHJpbmcoJ3R4dF9ub19pbnRlcm5ldCcsIGBObyBJbnRlcm5ldCFgKTsNCg0KCQkJbGV0IG92ZXJsYXlFbGVtID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiZGl2Iik7DQoJCQlvdmVybGF5RWxlbS5jbGFzc05hbWUgPSAib3ZlcmxheSBibGFja291dCI7DQoJCQlsZXQgcHJlbG9hZGVyID0gYFx0XHQ8ZGl2IGNsYXNzPSJvZmZsaW5lLW1zZyI+XG5gOw0KCQkJcHJlbG9hZGVyICs9IGBcdFx0XHQ8aDIgY2xhc3M9InRpdGxlIGVycm9yIj4ke29mZmxpbmVFcnJvckhlYWRpbmd9PC9oMj5cbmA7DQoJCQlwcmVsb2FkZXIgKz0gYFx0XHRcdDxkaXYgY2xhc3M9Im1zZyI+JHtvZmZsaW5lRXJyb3JNc2d9PC9kaXY+XG5gOw0KCQkJcHJlbG9hZGVyICs9IGBcdFx0PC9kaXY+XG5gOw0KDQoJCQlvdmVybGF5RWxlbS5pbm5lckhUTUwgPSBwcmVsb2FkZXI7DQoJCQkkKCcuc2duLXByZWxvYWRlcicpLmZhZGVPdXQoMTAwMCk7DQoJCQkkYm9keS5yZW1vdmVDbGFzcygnaGFzLXByZWxvYWRlcicpLmFkZENsYXNzKCd1c2VyLW9mZmxpbmUnKTsNCgkJCWRvY3VtZW50LmJvZHkuaW5zZXJ0QmVmb3JlKG92ZXJsYXlFbGVtLCBkb2N1bWVudC5ib2R5LmZpcnN0Q2hpbGQpOw0KDQoJCQkvL292ZXJsYXlFbGVtID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcigiLnNnbi1wcmVsb2FkZXIiKTsNCgkJCW92ZXJsYXlFbGVtID0gJCgiLnVzZXItb2ZmbGluZSA+IC5vdmVybGF5Iik7DQoNCgkJCWlmKG92ZXJsYXlFbGVtLmxlbmd0aCA+IDApIHsNCgkJCQlvdmVybGF5RWxlbS5mYWRlSW4oMTAwMCk7DQoJCQl9DQoJCX0pOw0KCQl3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignb25saW5lJywgKGUpID0+IHsNCgkJCWNvbnN0IGdldEkxOG5TdHJpbmcgPSAoaywgbSkgPT4gbTsNCgkJCS8vaWYodHlwZW9mIGdldEkxOG5TdHJpbmcgIT09ICdmdW5jdGlvbicpDQoJCQlsZXQgb25saW5lTXNnID0gKFNHTlVJS2l0LnJlYWR5KSA/IGdldEkxOG5TdHJpbmcoJ3Nnbl91aWtpdF91c2VyX29ubGluZV9tc2cnLCBgSG9vcmF5ISBZb3VyIGludGVybmV0IGNvbm5lY3Rpb24gaXMgcmVzdG9yZWQsIHlvdSdsbCBub3cgYmUgYWJsZSB0byBhY2Nlc3MgdGhlIGFwcGxpY2F0aW9uIHNob3J0bHkuYCkgOiBnZXRJMThuU3RyaW5nKCdzZ25fdWlraXRfdXNlcl9vbmxpbmVfbG9hZGluZ19pbnRlcnJ1cHRlZF9tc2cnLCBgSG9vcmF5ISBZb3VyIGludGVybmV0IGNvbm5lY3Rpb24gaXMgcmVzdG9yZWQsIHRoZSBhcHBsaWNhdGlvbiB3aWxsIHJlc3VtZSB0byBsb2FkIHNob3J0bHkuYCk7DQoJCQlpZihwcm9ncmVzcyA8IDEwMCkNCgkJCQlvbmxpbmVNc2cgPSBnZXRJMThuU3RyaW5nKCdzZ25fdWlraXRfdXNlcl9vbmxpbmVfcHJlbG9hZF9mYWlsZWRfbXNnJywgYEhvb3JheSEgWW91ciBpbnRlcm5ldCBjb25uZWN0aW9uIGlzIHJlc3RvcmVkLCBidXQgaXQgaGFzIGJyb2tlbiB0aGUgYXBwbGljYXRpb24ncyBwcmVsb2FkIHByb2Nlc3MsIHBsZWFzZSByZWxvYWQgdGhlIHBhZ2UgdG8gZml4IGl0LmApOw0KCQkJY29uc3Qgb25saW5lSGVhZGluZyA9IGdldEkxOG5TdHJpbmcoJ3R4dF9pbnRlcm5ldF9jb25uZWN0aW9uX3Jlc3RvcmVkJywgYEludGVybmV0IENvbm5lY3Rpb24gUmVzdG9yZWQhYCk7DQoNCgkJCS8vY29uc3Qgb3ZlcmxheUVsZW0gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIub3ZlcmxheSIpOw0KCQkJY29uc3QgJG92ZXJsYXlFbGVtID0gJCgiLnVzZXItb2ZmbGluZSA+IC5vdmVybGF5Iik7DQoJCQljb25zdCAkaGVhZGluZyA9ICRvdmVybGF5RWxlbS5maW5kKCcudGl0bGUnKSwNCgkJCSAgICAgICRtc2cgICAgID0gJG92ZXJsYXlFbGVtLmZpbmQoJy5tc2cnKTsNCgkJCWxldCBNU0dfVElNRU9VVCA9IDEwMDAwOw0KCQkJaWYodHlwZW9mICQuU0dOU25hY2tiYXIgPT09ICdmdW5jdGlvbicpIHsNCgkJCQlNU0dfVElNRU9VVCA9IDUwOw0KCQkJCSQuU0dOU25hY2tiYXIob25saW5lTXNnKS5zaG93KCk7DQoJCQl9IGVsc2Ugew0KCQkJCSRoZWFkaW5nLmh0bWwob25saW5lSGVhZGluZykucmVtb3ZlQ2xhc3MoJ2Vycm9yJykuYWRkQ2xhc3MoJ3N1Y2Nlc3MnKTsNCgkJCQkkbXNnLmh0bWwob25saW5lTXNnKTsNCgkJCX0NCg0KCQkJaWYoJG92ZXJsYXlFbGVtLmxlbmd0aCA+IDApIHsNCgkJCQlzZXRUaW1lb3V0KCgpID0+IHsNCgkJCQkJJCgnLnNnbi1wcmVsb2FkZXInKS5mYWRlSW4oMTAwMCk7DQoJCQkJCSRvdmVybGF5RWxlbS5mYWRlT3V0KDEwMDAsICgpID0+IHsNCgkJCQkJCSRvdmVybGF5RWxlbS5yZW1vdmUoKTsNCgkJCQkJCWRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LnJlbW92ZSgidXNlci1vZmZsaW5lIik7DQoJCQkJCQkkKCdib2R5JykuYWRkQ2xhc3MoJ2hhcy1wcmVsb2FkZXInKTsNCgkJCQkJfSk7DQoJCQkJfSwgTVNHX1RJTUVPVVQpOw0KCQkJfQ0KDQoJCQlpZih0eXBlb2YgcHJlY2FsbGJhY2sgPT09ICJmdW5jdGlvbiIgJiYgcHJvZ3Jlc3MgPT09IDEwMCkNCgkJCQlwcmVjYWxsYmFjaygpOw0KCQl9KTsNCgl9KShmdW5jdGlvbigpIHsNCgkJKGFzeW5jIGNhbGxiYWNrID0+IHsNCgkJCWNvbnN0IHNnbnVpa2l0U2NyaXB0ID0gZG9jdW1lbnQuY3VycmVudFNjcmlwdCB8fCBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCJzY3JpcHRbc3JjKj1cIlNHTlVJS2l0LmxvYWRlci5qc1wiXSIpOw0KCQkJY29uc3QgY3VycmVudFNjcmlwdCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJzZ24tcHJlbG9hZC1lbmQiKSB8fCBzZ251aWtpdFNjcmlwdDsNCg0KCQkJZnVuY3Rpb24gZ2V0U2NyaXB0VVJMKCkgew0KCQkJCXJldHVybiBzZ251aWtpdFNjcmlwdC5zcmM7DQoJCQl9DQoNCgkJCWNvbnN0IHVybCA9IGdldFNjcmlwdFVSTCgpLnNwbGl0KCIvIikuc2xpY2UoMCwgLTIpLmpvaW4oIi8iKSArICIvIjsNCg0KCQkJY29uc3Qgc2NyaXB0cyA9IFsNCgkJCQkianMvU0dOVUlLaXQuYnVuZGxlLmpzIiwNCgkJCV07DQoJCQljb25zdCBzdHlsZXMgPSBbDQoJCQkJImNzcy9TR05VSUtpdC5idW5kbGUuY3NzIiwNCgkJCV07DQoNCgkJCWxldCBzY3JpcHRzTG9hZGVkID0gMCwgc3R5bGVzTG9hZGVkID0gMCwgbG9hZGVkID0gMCwNCgkJCSAgICBsYXN0U2NyaXB0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID0gY3VycmVudFNjcmlwdDsNCgkJCWNvbnN0IHRvdGFsU2NyaXB0cyA9IHNjcmlwdHMubGVuZ3RoLCB0b3RhbFN0eWxlcyA9IHN0eWxlcy5sZW5ndGgsIHRvdGFsID0gdG90YWxTY3JpcHRzICsgdG90YWxTdHlsZXM7DQoNCgkJCWNvbnN0IGxvYWRTY3JpcHQgPSBpID0+IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHsNCgkJCQlpZihpID09PSBzY3JpcHRzLmxlbmd0aCkgcmV0dXJuOw0KDQoJCQkJY29uc3QgY29tcG9uZW50ID0gc2NyaXB0c1tpXSwNCgkJCQkgICAgICBzcmMgICAgICAgPSB1cmwgKyBjb21wb25lbnQsDQoJCQkJICAgICAgbmFtZSAgICAgID0gJ2pzXycgKyBnZXRGaWxlbmFtZUFuZEV4dGVuc2lvbihjb21wb25lbnQpLm5hbWU7DQoJCQkJY29uc3Qgb2JqID0ge307DQoJCQkJb2JqW25hbWVdID0gY29tcG9uZW50Ow0KDQoJCQkJaWYoIVNHTlVJS2l0LmlzQ29tcG9uZW50TG9hZGVkKG5hbWUpKSB7DQoJCQkJCWNvbnN0IHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInNjcmlwdCIpOw0KCQkJCQkvL3NjcmlwdC50eXBlID0gJ3RleHQvamF2YXNjcmlwdCc7DQoJCQkJCXNjcmlwdC5zcmMgPSBzcmM7DQoJCQkJCWxhc3RTY3JpcHQuYWZ0ZXIoc2NyaXB0KTsNCgkJCQkJbGFzdFNjcmlwdCA9IGxhc3RTY3JpcHQubmV4dEVsZW1lbnRTaWJsaW5nIHx8IGN1cnJlbnRTY3JpcHQ7DQoNCgkJCQkJc2NyaXB0Lm9ubG9hZCA9IGFzeW5jIGZ1bmN0aW9uKCkgew0KCQkJCQkJU0dOVUlLaXQuY29tcG9uZW50ID0gb2JqOw0KCQkJCQkJc2NyaXB0Lm9ubG9hZCA9IG51bGw7DQoJCQkJCQlzY3JpcHRzTG9hZGVkKys7DQoJCQkJCQlsb2FkZWQrKzsNCg0KCQkJCQkJaWYoc2NyaXB0c0xvYWRlZCA9PT0gdG90YWxTY3JpcHRzKQ0KCQkJCQkJCXJlc29sdmUoaSk7DQoJCQkJCQllbHNlDQoJCQkJCQkJcmVzb2x2ZShsb2FkU2NyaXB0KCsraSkpOw0KCQkJCQl9Ow0KCQkJCX0gZWxzZSB7DQoJCQkJCXNjcmlwdHNMb2FkZWQrKzsNCgkJCQkJbG9hZGVkKys7DQoNCgkJCQkJaWYoc2NyaXB0c0xvYWRlZCA9PT0gdG90YWxTY3JpcHRzKQ0KCQkJCQkJcmVzb2x2ZShpKTsNCgkJCQkJZWxzZQ0KCQkJCQkJcmVzb2x2ZShsb2FkU2NyaXB0KCsraSkpOw0KCQkJCX0NCgkJCX0pOw0KDQoJCQljb25zdCBsb2FkU3R5bGUgPSBpID0+IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHsNCgkJCQlpZihpID09PSBzdHlsZXMubGVuZ3RoKSByZXR1cm47DQoNCgkJCQljb25zdCBjb21wb25lbnQgPSBzdHlsZXNbaV0sDQoJCQkJICAgICAgc3JjICAgICAgID0gdXJsICsgY29tcG9uZW50LA0KCQkJCSAgICAgIG5hbWUgICAgICA9ICdjc3NfJyArIGdldEZpbGVuYW1lQW5kRXh0ZW5zaW9uKGNvbXBvbmVudCkubmFtZTsNCgkJCQljb25zdCBvYmogPSB7fTsNCgkJCQlvYmpbbmFtZV0gPSBjb21wb25lbnQ7DQoNCgkJCQlpZighU0dOVUlLaXQuaXNDb21wb25lbnRMb2FkZWQobmFtZSkpIHsNCgkJCQkJY29uc3Qgc3R5bGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJsaW5rIik7DQoJCQkJCXN0eWxlLnJlbCA9ICJzdHlsZXNoZWV0IjsNCgkJCQkJc3R5bGUuaHJlZiA9IHNyYzsNCgkJCQkJLy9zdHlsZS50eXBlID0gJ3RleHQvY3NzJzsNCgkJCQkJY3VycmVudFNjcmlwdC5hZnRlcihzdHlsZSk7DQoJCQkJCXN0eWxlLm9ubG9hZCA9IGFzeW5jIGZ1bmN0aW9uKCkgew0KCQkJCQkJU0dOVUlLaXQuY29tcG9uZW50ID0gb2JqOw0KCQkJCQkJc3R5bGUub25sb2FkID0gbnVsbDsNCgkJCQkJCXN0eWxlc0xvYWRlZCsrOw0KCQkJCQkJbG9hZGVkKys7DQoNCgkJCQkJCWlmKHN0eWxlc0xvYWRlZCA9PT0gdG90YWxTdHlsZXMpDQoJCQkJCQkJcmVzb2x2ZShpKTsNCgkJCQkJCWVsc2UNCgkJCQkJCQlyZXNvbHZlKGxvYWRTdHlsZSgrK2kpKTsNCgkJCQkJfTsNCgkJCQl9IGVsc2Ugew0KCQkJCQlzdHlsZXNMb2FkZWQrKzsNCgkJCQkJbG9hZGVkKys7DQoNCgkJCQkJaWYoc3R5bGVzTG9hZGVkID09PSB0b3RhbFN0eWxlcykNCgkJCQkJCXJlc29sdmUoaSk7DQoJCQkJCWVsc2UNCgkJCQkJCXJlc29sdmUobG9hZFN0eWxlKCsraSkpOw0KCQkJCX0NCgkJCX0pOw0KDQoJCQkoKCkgPT4gew0KCQkJCWNvbnN0IHN0YXJ0TG9hZCA9IG5ldyBQcm9taXNlKGFzeW5jIGZ1bmN0aW9uKHJlc29sdmUpIHsNCgkJCQkJYXdhaXQgbG9hZFN0eWxlKDApOw0KCQkJCQlhd2FpdCBsb2FkU2NyaXB0KDApOw0KCQkJCQlpZihsb2FkZWQgPT09IHRvdGFsKQ0KCQkJCQkJcmVzb2x2ZSgpOw0KCQkJCX0pOw0KDQoJCQkJc3RhcnRMb2FkLnRoZW4oKCkgPT4gew0KCQkJCQlmaW5pc2hMb2FkKCk7DQoJCQkJfSk7DQoJCQl9KSgpOw0KDQoJCQlhc3luYyBmdW5jdGlvbiBmaW5pc2hMb2FkKCkgew0KCQkJCWNvbnN0IHByb2dyZXNzID0gTWF0aC5yb3VuZCgobG9hZGVkICogMTAwKSAvIHRvdGFsKTsNCg0KCQkJCWF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gew0KCQkJCQlpZihsb2FkZWQgPT09IHRvdGFsKSB7DQoJCQkJCQlyZXNvbHZlKCk7DQoJCQkJCX0NCgkJCQl9KS50aGVuKGZ1bmN0aW9uKCkgew0KCQkJCQlpZih0eXBlb2YgY2FsbGJhY2sgPT09ICJmdW5jdGlvbiIpDQoJCQkJCQljYWxsYmFjayhsb2FkZWQsIHRvdGFsLCBwcm9ncmVzcyk7DQoJCQkJfSk7DQoJCQl9DQoJCX0pKChsb2FkZWQsIHRvdGFsLCBwcm9ncmVzcykgPT4gew0KCQkJaWYocHJvZ3Jlc3MgPT09IDEwMCkgew0KCQkJCVNHTlVJS2l0LmluaXQgPSB0cnVlOw0KDQoJCQkJY29uc3Qgc3R5bGVzID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcigic3R5bGUjc2duLXVpa2l0LXN0eWxlcyIpOw0KCQkJCWNvbnN0IGxlZnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCJzdHlsZVtkYXRhLWNrZT1cInRydWVcIl0iKTsNCgkJCQlpZihsZWZ0ICE9PSBudWxsKQ0KCQkJCQlsZWZ0LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQobGVmdCk7DQoJCQkJaWYoc3R5bGVzICE9PSBudWxsKQ0KCQkJCQlzdHlsZXMucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChzdHlsZXMpOw0KDQoJCQkJJC5ob2xkUmVhZHkoZmFsc2UpOw0KCQkJCWpRdWVyeS5yZWFkeSgpOw0KCQkJfQ0KCQl9KTsNCgl9KTsNCg0KCSgoKSA9PiB7DQoJCWNvbnN0IGZpbmFsaXplID0gKGhvbGRQcmVsb2FkZXIgPSBmYWxzZSkgPT4gew0KCQkJY29uc3QgJGJvZHkgPSAkKCJib2R5Iik7DQoNCgkJCS8qKioNCgkJCSAqDQoJCQkgKiBAdHlwZSB7T2JqZWN0PFNHTkF0b20+fQ0KCQkJICovDQoJCQljb25zdCBzZ25hdG9tcyA9IFNHTkF0b20uZ2V0SW5zdGFuY2UoKTsNCg0KCQkJc2duYXRvbXMuc2V0T25DcmVhdGVMaXN0ZW5lcigoc2duYXRvbXMpID0+IHsNCgkJCQlpZihzZ25hdG9tcy5sZW5ndGggPiAwKSB7DQoJCQkJCWZvcihjb25zdCBndWlkIGluIHNnbmF0b21zKSB7DQoJCQkJCQljb25zdCBzZ25hdG9tID0gc2duYXRvbXNbZ3VpZF07DQoNCgkJCQkJCWlmKHNnbmF0b20gaW5zdGFuY2VvZiBTR05BdG9tKSB7DQoJCQkJCQkJc2duYXRvbS5TR05BdG9tU3RhdGVzLnNldE9uUmVhZHlMaXN0ZW5lcigoaXNSZWFkeSkgPT4gew0KCQkJCQkJCQlpZihpc1JlYWR5KSB7DQoJCQkJCQkJCQljb25zdCBuYXZpZ2F0b3IgPSBzZ25hdG9tLmNvcmUubmF2aWdhdG9yOw0KCQkJCQkJCQkJbmF2aWdhdG9yLnNldE9uUGFnZUxvYWRMaXN0ZW5lcigodXJsLCBjb2RlKSA9PiB7DQoJCQkJCQkJCQkJaWYoY29kZSA9PT0gMjAwIHx8IGNvZGUgPT09IDIwMSB8fCBjb2RlID09PSAyMDIpIHsNCgkJCQkJCQkJCQkJU0dOVUlLaXQucmVhZHkgPSB0cnVlOw0KCQkJCQkJCQkJCQlTVUtSSW5zdGFuY2VzLnNldE9uQ3JlYXRlTGlzdGVuZXIoKGluc3RhbmNlcykgPT4gew0KCQkJCQkJCQkJCQkJZm9yRWFjaChpbnN0YW5jZXMsIGluc3QgPT4gaW5zdC50cmlnZ2VyKCkpOw0KCQkJCQkJCQkJCQl9KTsNCg0KCQkJCQkJCQkJCQlpZighaG9sZFByZWxvYWRlcikgew0KCQkJCQkJCQkJCQkJJGJvZHkuY2hpbGRyZW4oIi5zZ24tcHJlbG9hZGVyIikuZmFkZU91dCgyMDAwLCBmdW5jdGlvbigpIHsNCgkJCQkJCQkJCQkJCQkkYm9keS5jaGlsZHJlbigiLnNnbi1wcmVsb2FkZXIiKS5yZW1vdmUoKTsNCgkJCQkJCQkJCQkJCQkkYm9keS5yZW1vdmVDbGFzcygiaGFzLXByZWxvYWRlciIpOw0KCQkJCQkJCQkJCQkJfSk7DQoJCQkJCQkJCQkJCX0NCgkJCQkJCQkJCQl9DQoJCQkJCQkJCQl9KTsNCgkJCQkJCQkJfQ0KCQkJCQkJCX0pOw0KCQkJCQkJfQ0KCQkJCQl9DQoJCQkJfSBlbHNlIHsNCgkJCQkJU1VLUkluc3RhbmNlcy5zZXRPbkNoYW5nZUxpc3RlbmVyKChpbnN0YW5jZSwgaW5zdGFuY2VzKSA9PiB7DQoJCQkJCQkvL2NvbnNvbGUubG9nKGluc3RhbmNlcyk7DQoJCQkJCQlmb3JFYWNoKGluc3RhbmNlcywgaW5zdCA9PiB7DQoJCQkJCQkJaW5zdC50cmlnZ2VyKCk7DQoJCQkJCQl9KTsNCgkJCQkJfSk7DQoJCQkJCXdpbmRvdy5TR05VSUtpdFJlYWR5ID0gdHJ1ZTsNCgkJCQkJU0dOVUlLaXQucmVhZHkgPSB0cnVlOw0KCQkJCQlpZihTR05VSUtpdC5yZWFkeSkgew0KCQkJCQkJaWYoIWhvbGRQcmVsb2FkZXIpIHsNCgkJCQkJCQkkYm9keS5jaGlsZHJlbigiLnNnbi1wcmVsb2FkZXIiKS5mYWRlT3V0KDIwMDAsIGZ1bmN0aW9uKCkgew0KCQkJCQkJCQkkYm9keS5jaGlsZHJlbigiLnNnbi1wcmVsb2FkZXIiKS5yZW1vdmUoKTsNCgkJCQkJCQkJJGJvZHkucmVtb3ZlQ2xhc3MoImhhcy1wcmVsb2FkZXIiKTsNCgkJCQkJCQl9KTsNCgkJCQkJCX0NCgkJCQkJfQ0KCQkJCX0NCgkJCX0pOw0KCQl9DQoNCgkJU0dOVUlLaXQuc2V0T25DaGFuZ2VMaXN0ZW5lcigocHJvcCwgdmFsdWUpID0+IHsNCgkJCWlmKHByb3AgPT09ICdob2xkUHJlbG9hZGVyJykgew0KCQkJCWlmKFNHTlVJS2l0LmluaXQgJiYgIXZhbHVlKSB7DQoJCQkJCWZpbmFsaXplKHRydWUpOw0KCQkJCX0NCgkJCX0gZWxzZSB7DQoJCQkJaWYocHJvcCA9PT0gJ2luaXQnICYmIHZhbHVlKSB7DQoJCQkJCWZpbmFsaXplKGZhbHNlKTsNCgkJCQl9DQoJCQl9DQoJCX0sICdzZ24tdWstcHJvcC1jaGFuZ2UtbGlzdGVuZXInKTsNCgl9KSgpOw0KfSk7DQoNCg0KYXN5bmMgZnVuY3Rpb24gZ2V0U0dOSTE4bkluc3RhbmNlKGNhbGxiYWNrKSB7DQoJcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHsNCgkJY29uc3QgdGltZW91dEhhbmRsZXIgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgew0KCQkJaWYoY2hlY2tJbnRlcnZhbEhhbmRsZXIpDQoJCQkJY2xlYXJJbnRlcnZhbChjaGVja0ludGVydmFsSGFuZGxlcik7DQoJCX0sIDEwMDAwKTsNCg0KCQljb25zdCBjaGVja0ludGVydmFsSGFuZGxlciA9IHNldEludGVydmFsKGZ1bmN0aW9uKCkgew0KCQkJaWYod2luZG93LlNHTlVJS2l0UmVhZHkpIHsNCgkJCQlpZih0aW1lb3V0SGFuZGxlcikNCgkJCQkJY2xlYXJUaW1lb3V0KHRpbWVvdXRIYW5kbGVyKTsNCgkJCQljbGVhckludGVydmFsKGNoZWNrSW50ZXJ2YWxIYW5kbGVyKTsNCgkJCQljb25zdCBjID0gbmV3IFNHTmkxOG4oKTsNCg0KCQkJCS8qaWYodHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKQ0KCQkJCSBjYWxsYmFjayhjKTsqLw0KCQkJCXJlc29sdmUoYyk7DQoJCQl9DQoJCX0sIDEwMCk7DQoJfSk7DQp9DQoNCg=="; module.exports = { args, SGNUIKitLoader, version, cdn_dir, diff --git a/demos/grids.html b/demos/grids.html new file mode 100644 index 00000000..50120031 --- /dev/null +++ b/demos/grids.html @@ -0,0 +1,160 @@ + + + + + + + Grids - SGNUIKit Demo + + + + + +
+
+ + +
+
1/12
+
1/12
+
1/12
+
1/12
+
1/12
+
1/12
+
1/12
+
1/12
+
1/12
+
1/12
+
1/12
+
1/12
+
+ +
+
2/12
+
2/12
+
2/12
+
2/12
+
2/12
+
2/12
+
+ +
+
3/12
+
3/12
+
3/12
+
3/12
+
+ +
+
4/12
+
4/12
+
4/12
+
+ +
+
6/12
+
6/12
+
+ +
+
5/12
+
7/12
+
+ +
+
4/12
+
8/12
+
+ +
+
3/12
+
9/12
+
+ +
+
2/12
+
10/12
+
+ +
+
1/12
+
11/12
+
+ +
+
12/12
+
+
+
+ + diff --git a/demos/index.html b/demos/index.html index c20336b3..138dd9c4 100644 --- a/demos/index.html +++ b/demos/index.html @@ -40,6 +40,7 @@
Text Colours Gradients + Grids Shapes Shadows
@@ -48,7 +49,7 @@
Addons
SGNAtom - fullPage.js + SGNFullPage
diff --git a/package.json b/package.json index 17de0669..ba3f793e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sgnuikit", - "version": "1.1.5", + "version": "1.2.1", "description": "SGNUIKit is a very powerful UI kit designed to allow web developers use the power of the kit to build efficient and beautiful websites. SGNUIKit is currently being used in all the websites by SGNetworks.", "homepage": "https://sgnuikit.cdn.sgnetworks.eu.org", "author": { diff --git a/src/addons/Marquee/marquee.js b/src/addons/Marquee/marquee.js deleted file mode 100644 index a0693840..00000000 --- a/src/addons/Marquee/marquee.js +++ /dev/null @@ -1,505 +0,0 @@ -/* - * Copyright (c) 2022 SGNetworks. All rights reserved. - * - * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. - * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. - */ - -/** - * jQuery.marquee - scrolling text like old marquee element - * @author Aamir Afridi - aamirafridi(at)gmail(dot)com / http://aamirafridi.com/jquery/jquery-marquee-plugin - */ -;(function(factory) { - 'use strict'; - if(typeof define === 'function' && define.amd) { - define(['jquery'], factory); - } else if(typeof exports !== 'undefined') { - module.exports = factory(require('jquery')); - } else { - factory(jQuery); - } -})(function($) { - $.fn.marquee = function(options) { - return this.each(function() { - // Extend the options if any provided - var o = $.extend({}, $.fn.marquee.defaults, options), - $this = $(this), - $marqueeWrapper, containerWidth, animationCss, verticalDir, elWidth, - loopCount = 3, - playState = 'animation-play-state', - css3AnimationIsSupported = false, - - // Private methods - _prefixedEvent = function(element, type, callback) { - var pfx = ["webkit", "moz", "MS", "o", ""]; - for(var p = 0; p < pfx.length; p++) { - if(!pfx[p]) type = type.toLowerCase(); - element.addEventListener(pfx[p] + type, callback, false); - } - }, - - _objToString = function(obj) { - var tabjson = []; - for(var p in obj) { - if(obj.hasOwnProperty(p)) { - tabjson.push(p + ':' + obj[p]); - } - } - tabjson.push(); - return '{' + tabjson.join(',') + '}'; - }, - - _startAnimationWithDelay = function() { - $this.timer = setTimeout(animate, o.delayBeforeStart); - }, - - // Public methods - methods = { - pause: function() { - if(css3AnimationIsSupported && o.allowCss3Support) { - $marqueeWrapper.css(playState, 'paused'); - } else { - // pause using pause plugin - if($.fn.pause) { - $marqueeWrapper.pause(); - } - } - // save the status - $this.data('runningStatus', 'paused'); - // fire event - $this.trigger('paused'); - }, - - resume: function() { - // resume using css3 - if(css3AnimationIsSupported && o.allowCss3Support) { - $marqueeWrapper.css(playState, 'running'); - } else { - // resume using pause plugin - if($.fn.resume) { - $marqueeWrapper.resume(); - } - } - // save the status - $this.data('runningStatus', 'resumed'); - // fire event - $this.trigger('resumed'); - }, - - toggle: function() { - methods[$this.data('runningStatus') === 'resumed' ? 'pause' : 'resume'](); - }, - - destroy: function() { - // Clear timer - clearTimeout($this.timer); - // Unbind all events - $this.find("*").addBack().off(); - // Just unwrap the elements that has been added using this plugin - $this.html($this.find('.js-marquee:first').html()); - } - }; - - // Check for methods - if(typeof options === 'string') { - if($.isFunction(methods[options])) { - // Following two IF statements to support public methods - if(!$marqueeWrapper) { - $marqueeWrapper = $this.find('.js-marquee-wrapper'); - } - if($this.data('css3AnimationIsSupported') === true) { - css3AnimationIsSupported = true; - } - methods[options](); - } - return; - } - - /* Check if element has data attributes. They have top priority - For details https://twitter.com/aamirafridi/status/403848044069679104 - Can't find a better solution :/ - jQuery 1.3.2 doesn't support $.data().KEY hence writting the following */ - var dataAttributes = {}, - attr; - $.each(o, function(key) { - // Check if element has this data attribute - attr = $this.attr('data-' + key); - if(typeof attr !== 'undefined') { - // Now check if value is boolean or not - switch(attr) { - case 'true': - attr = true; - break; - case 'false': - attr = false; - break; - } - o[key] = attr; - } - }); - - // Reintroduce speed as an option. It calculates duration as a factor of the container width - // measured in pixels per second. - if(o.speed) { - o.duration = parseInt($this.width(), 10) / o.speed * 1000; - } - - // Shortcut to see if direction is upward or downward - verticalDir = o.direction === 'up' || o.direction === 'down'; - - // no gap if not duplicated - o.gap = o.duplicated ? parseInt(o.gap) : 0; - - // wrap inner content into a div - $this.wrapInner('
'); - - // Make copy of the element - var $el = $this.find('.js-marquee').css({ - 'margin-right': o.gap, - 'float': 'left' - }); - - if(o.duplicated) { - $el.clone(true).appendTo($this); - } - - // wrap both inner elements into one div - $this.wrapInner('
'); - - // Save the reference of the wrapper - $marqueeWrapper = $this.find('.js-marquee-wrapper'); - - // If direction is up or down, get the height of main element - if(verticalDir) { - var containerHeight = $this.height(); - $marqueeWrapper.removeAttr('style'); - $this.height(containerHeight); - - // Change the CSS for js-marquee element - $this.find('.js-marquee').css({ - 'float': 'none', - 'margin-bottom': o.gap, - 'margin-right': 0 - }); - - // Remove bottom margin from 2nd element if duplicated - if(o.duplicated) { - $this.find('.js-marquee:last').css({ - 'margin-bottom': 0 - }); - } - - var elHeight = $this.find('.js-marquee:first').height() + o.gap; - - // adjust the animation duration according to the text length - if(o.startVisible && !o.duplicated) { - // Compute the complete animation duration and save it for later reference - // formula is to: (Height of the text node + height of the main container / Height of the main container) * duration; - o._completeDuration = ((parseInt(elHeight, 10) + parseInt(containerHeight, 10)) / parseInt(containerHeight, 10)) * o.duration; - - // formula is to: (Height of the text node / height of the main container) * duration - o.duration = (parseInt(elHeight, 10) / parseInt(containerHeight, 10)) * o.duration; - } else { - // formula is to: (Height of the text node + height of the main container / Height of the main container) * duration; - o.duration = ((parseInt(elHeight, 10) + parseInt(containerHeight, 10)) / parseInt(containerHeight, 10)) * o.duration; - } - - } else { - // Save the width of the each element so we can use it in animation - elWidth = $this.find('.js-marquee:first').width() + o.gap; - - // container width - containerWidth = $this.width(); - - // adjust the animation duration according to the text length - if(o.startVisible && !o.duplicated) { - // Compute the complete animation duration and save it for later reference - // formula is to: (Width of the text node + width of the main container / Width of the main container) * duration; - o._completeDuration = ((parseInt(elWidth, 10) + parseInt(containerWidth, 10)) / parseInt(containerWidth, 10)) * o.duration; - - // (Width of the text node / width of the main container) * duration - o.duration = (parseInt(elWidth, 10) / parseInt(containerWidth, 10)) * o.duration; - } else { - // formula is to: (Width of the text node + width of the main container / Width of the main container) * duration; - o.duration = ((parseInt(elWidth, 10) + parseInt(containerWidth, 10)) / parseInt(containerWidth, 10)) * o.duration; - } - } - - // if duplicated then reduce the duration - if(o.duplicated) { - o.duration = o.duration / 2; - } - - if(o.allowCss3Support) { - var elm = document.body || document.createElement('div'), - animationName = 'marqueeAnimation-' + Math.floor(Math.random() * 10000000), - domPrefixes = 'Webkit Moz O ms Khtml'.split(' '), - animationString = 'animation', - animationCss3Str = '', - keyframeString = ''; - - // Check css3 support - if(elm.style.animation !== undefined) { - keyframeString = '@keyframes ' + animationName + ' '; - css3AnimationIsSupported = true; - } - - if(css3AnimationIsSupported === false) { - for(var i = 0; i < domPrefixes.length; i++) { - if(elm.style[domPrefixes[i] + 'AnimationName'] !== undefined) { - var prefix = '-' + domPrefixes[i].toLowerCase() + '-'; - animationString = prefix + animationString; - playState = prefix + playState; - keyframeString = '@' + prefix + 'keyframes ' + animationName + ' '; - css3AnimationIsSupported = true; - break; - } - } - } - - if(css3AnimationIsSupported) { - animationCss3Str = animationName + ' ' + o.duration / 1000 + 's ' + o.delayBeforeStart / 1000 + 's infinite ' + o.css3easing; - $this.data('css3AnimationIsSupported', true); - } - } - - var _rePositionVertically = function() { - $marqueeWrapper.css('transform', 'translateY(' + (o.direction === 'up' ? containerHeight + 'px' : '-' + elHeight + 'px') + ')'); - }, - _rePositionHorizontally = function() { - $marqueeWrapper.css('transform', 'translateX(' + (o.direction === 'left' ? containerWidth + 'px' : '-' + elWidth + 'px') + ')'); - }; - - // if duplicated option is set to true than position the wrapper - if(o.duplicated) { - if(verticalDir) { - if(o.startVisible) { - $marqueeWrapper.css('transform', 'translateY(0)'); - } else { - $marqueeWrapper.css('transform', 'translateY(' + (o.direction === 'up' ? containerHeight + 'px' : '-' + ((elHeight * 2) - o.gap) + 'px') + ')'); - } - } else { - if(o.startVisible) { - $marqueeWrapper.css('transform', 'translateX(0)'); - } else { - $marqueeWrapper.css('transform', 'translateX(' + (o.direction === 'left' ? containerWidth + 'px' : '-' + ((elWidth * 2) - o.gap) + 'px') + ')'); - } - } - - // If the text starts out visible we can skip the two initial loops - if(!o.startVisible) { - loopCount = 1; - } - } else if(o.startVisible) { - // We only have two different loops if marquee is duplicated and starts visible - loopCount = 2; - } else { - if(verticalDir) { - _rePositionVertically(); - } else { - _rePositionHorizontally(); - } - } - - // Animate recursive method - var animate = function() { - if(o.duplicated) { - // When duplicated, the first loop will be scroll longer so double the duration - if(loopCount === 1) { - o._originalDuration = o.duration; - if(verticalDir) { - o.duration = o.direction === 'up' ? o.duration + (containerHeight / ((elHeight) / o.duration)) : o.duration * 2; - } else { - o.duration = o.direction === 'left' ? o.duration + (containerWidth / ((elWidth) / o.duration)) : o.duration * 2; - } - // Adjust the css3 animation as well - if(animationCss3Str) { - animationCss3Str = animationName + ' ' + o.duration / 1000 + 's ' + o.delayBeforeStart / 1000 + 's ' + o.css3easing; - } - loopCount++; - } - // On 2nd loop things back to normal, normal duration for the rest of animations - else if(loopCount === 2) { - o.duration = o._originalDuration; - // Adjust the css3 animation as well - if(animationCss3Str) { - animationName = animationName + '0'; - keyframeString = $.trim(keyframeString) + '0 '; - animationCss3Str = animationName + ' ' + o.duration / 1000 + 's 0s infinite ' + o.css3easing; - } - loopCount++; - } - } - - if(verticalDir) { - if(o.duplicated) { - - // Adjust the starting point of animation only when first loops finishes - if(loopCount > 2) { - $marqueeWrapper.css('transform', 'translateY(' + (o.direction === 'up' ? 0 : '-' + elHeight + 'px') + ')'); - } - - animationCss = { - 'transform': 'translateY(' + (o.direction === 'up' ? '-' + elHeight + 'px' : 0) + ')' - }; - } else if(o.startVisible) { - // This loop moves the marquee out of the container - if(loopCount === 2) { - // Adjust the css3 animation as well - if(animationCss3Str) { - animationCss3Str = animationName + ' ' + o.duration / 1000 + 's ' + o.delayBeforeStart / 1000 + 's ' + o.css3easing; - } - animationCss = { - 'transform': 'translateY(' + (o.direction === 'up' ? '-' + elHeight + 'px' : containerHeight + 'px') + ')' - }; - loopCount++; - } else if(loopCount === 3) { - // Set the duration for the animation that will run forever - o.duration = o._completeDuration; - // Adjust the css3 animation as well - if(animationCss3Str) { - animationName = animationName + '0'; - keyframeString = $.trim(keyframeString) + '0 '; - animationCss3Str = animationName + ' ' + o.duration / 1000 + 's 0s infinite ' + o.css3easing; - } - _rePositionVertically(); - } - } else { - _rePositionVertically(); - animationCss = { - 'transform': 'translateY(' + (o.direction === 'up' ? '-' + ($marqueeWrapper.height()) + 'px' : containerHeight + 'px') + ')' - }; - } - } else { - if(o.duplicated) { - - // Adjust the starting point of animation only when first loops finishes - if(loopCount > 2) { - $marqueeWrapper.css('transform', 'translateX(' + (o.direction === 'left' ? 0 : '-' + elWidth + 'px') + ')'); - } - - animationCss = { - 'transform': 'translateX(' + (o.direction === 'left' ? '-' + elWidth + 'px' : 0) + ')' - }; - - } else if(o.startVisible) { - // This loop moves the marquee out of the container - if(loopCount === 2) { - // Adjust the css3 animation as well - if(animationCss3Str) { - animationCss3Str = animationName + ' ' + o.duration / 1000 + 's ' + o.delayBeforeStart / 1000 + 's ' + o.css3easing; - } - animationCss = { - 'transform': 'translateX(' + (o.direction === 'left' ? '-' + elWidth + 'px' : containerWidth + 'px') + ')' - }; - loopCount++; - } else if(loopCount === 3) { - // Set the duration for the animation that will run forever - o.duration = o._completeDuration; - // Adjust the css3 animation as well - if(animationCss3Str) { - animationName = animationName + '0'; - keyframeString = $.trim(keyframeString) + '0 '; - animationCss3Str = animationName + ' ' + o.duration / 1000 + 's 0s infinite ' + o.css3easing; - } - _rePositionHorizontally(); - } - } else { - _rePositionHorizontally(); - animationCss = { - 'transform': 'translateX(' + (o.direction === 'left' ? '-' + elWidth + 'px' : containerWidth + 'px') + ')' - }; - } - } - - // fire event - $this.trigger('beforeStarting'); - - // If css3 support is available than do it with css3, otherwise use jQuery as fallback - if(css3AnimationIsSupported) { - // Add css3 animation to the element - $marqueeWrapper.css(animationString, animationCss3Str); - var keyframeCss = keyframeString + ' { 100% ' + _objToString(animationCss) + '}', - $styles = $marqueeWrapper.find('style'); - - // Now add the keyframe animation to the marquee element - if($styles.length !== 0) { - // Bug fixed for jQuery 1.3.x - Instead of using .last(), use following - $styles.filter(":last").html(keyframeCss); - } else { - $('head').append(''); - } - - // Animation iteration event - _prefixedEvent($marqueeWrapper[0], "AnimationIteration", function() { - $this.trigger('finished'); - }); - // Animation stopped - _prefixedEvent($marqueeWrapper[0], "AnimationEnd", function() { - animate(); - $this.trigger('finished'); - }); - - } else { - // Start animating - $marqueeWrapper.animate(animationCss, o.duration, o.easing, function() { - // fire event - $this.trigger('finished'); - // animate again - if(o.pauseOnCycle) { - _startAnimationWithDelay(); - } else { - animate(); - } - }); - } - // save the status - $this.data('runningStatus', 'resumed'); - }; - - // bind pause and resume events - $this.on('pause', methods.pause); - $this.on('resume', methods.resume); - - if(o.pauseOnHover) { - $this.on('mouseenter', methods.pause); - $this.on('mouseleave', methods.resume); - } - - // If css3 animation is supported than call animate method at once - if(css3AnimationIsSupported && o.allowCss3Support) { - animate(); - } else { - // Starts the recursive method - _startAnimationWithDelay(); - } - - }); - }; // End of Plugin - // Public: plugin defaults options - $.fn.marquee.defaults = { - // If you wish to always animate using jQuery - allowCss3Support: true, - // works when allowCss3Support is set to true - for full list see http://www.w3.org/TR/2013/WD-css3-transitions-20131119/#transition-timing-function - css3easing: 'linear', - // requires jQuery easing plugin. Default is 'linear' - easing: 'linear', - // pause time before the next animation turn in milliseconds - delayBeforeStart: 1000, - // 'left', 'right', 'up' or 'down' - direction: 'left', - // true or false - should the marquee be duplicated to show an effect of continues flow - duplicated: false, - // duration in milliseconds of the marquee in milliseconds - duration: 5000, - // Speed allows you to set a relatively constant marquee speed regardless of the width of the containing element. Speed is measured in pixels per second. - speed: 0, - // gap in pixels between the tickers - gap: 20, - // on cycle pause the marquee - pauseOnCycle: false, - // on hover pause the marquee - using jQuery plugin https://github.com/tobia/Pause - pauseOnHover: false, - // the marquee is visible initially positioned next to the border towards it will be moving - startVisible: false - }; -}); \ No newline at end of file diff --git a/src/addons/SGNLoaders/SGNLoaders.css b/src/addons/SGNLoaders/SGNLoaders.css new file mode 100644 index 00000000..cfe979f7 --- /dev/null +++ b/src/addons/SGNLoaders/SGNLoaders.css @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +/************************************************************************************************************************************ +******************************************************SGNSPINNER v1.0.9************************************************************** +************************************************************************************************************************************* +* DATE: December 19, 2019 * +* AUTHOR: Sagnik Ganguly * +* E-MAIL: sagnikganguly2012@rediffmail.com * +* WEBSITE: https://plugins.sgnetworks.ga/jquery/sgnspinner * +* DOCUMENTATION: https://docs.plugins.sgnetworks.ga/jquery/sgnspinner * +************************************************************************************************************************************/ + +/********************SGN SPINNERS DEFAULTS********************/ +@import url("./components/spinners/spinners.css"); +@import url("./components/bars/bars.css"); +@import url("./components/aligners.css"); + +.sgn-loader { + padding: 5px; +} + +input.sgn-loader, +button.sgn-loader, +a.sgn-loader { + /* padding: 0px !important; */ + margin-top: 5px; +} + +.sgn-loader.sgn-loader-modal { + background-color: rgba(0, 0, 0, .9); + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1000; + display: block; +} diff --git a/src/addons/SGNLoaders/SGNLoaders.js b/src/addons/SGNLoaders/SGNLoaders.js new file mode 100644 index 00000000..7281da16 --- /dev/null +++ b/src/addons/SGNLoaders/SGNLoaders.js @@ -0,0 +1,613 @@ +/* + * Copyright (c) 2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +/************************************************************************************************************************************************************ + ******************************************************SGNLoader v1.0.9*************************************************************************************** + ************************************************************************************************************************************************************* + * DATE: December 19, 2019 * + * AUTHOR: Sagnik Ganguly * + * E-MAIL: sagnikganguly2012@rediffmail.com * + * WEBSITE: https://plugins.sgnetworks.ga/jquery/SGNLoader * + * DOCUMENTATION: https://docs.plugins.sgnetworks.ga/jquery/SGNLoader * + ************************************************************************************************************************************************************* + * DEPENDENCIES: * + * jQuery v3.2.1+ * + ************************************************************************************************************************************************************/ +/************************************************************************************************************************************************************ + * WHAT'S NEW: * + * Version: 1.0.9 * + * + Added Option 'addElementClass' * + * + Added Option 'addElementStyles' * + * + Added Option 'loaderType' * + * + Added Option 'type' * + * + Added Option 'dialogHeading' * + * + Added Option 'dialogHeadingImg' * + * + Added Option 'dialogHeadingText' * + * + Added Option 'dialogBody' * + * + Added Option 'dialogBodyImg' * + * + Added Option 'dialogBodyText' * + * + Added Option 'modalImg' * + * + Added Option 'modalText' * + * + Added Option 'modalFooterImg' * + * + Added Option 'modalFooterText' * + * + Added Option 'speedup' * + * + Added Option 'barStripesDirection' * + * + Added Callback Function 'onShow' * + * + Added Callback Function 'onHide' * + * + Added Callback Function 'onRemove' * + ************************************************************************************************************************************************************/ +/************************************************************************************************************************************************************ + * USAGE: * + ************************************************************************************************************************************************************* + * INITIALIZATION: * + * $(".myLoader").SGNLoader({ * + * //Options * + * }); * + * * + * * + * OPTIONS: * + * animation : 'default','linear','ease','easein','easeinout','easeout','steps','stepstart','stepend' * + * border : 'default','xxxs','xxs','xs','sm','md','lg','xl','xxl','xxxl' * + * size : 'default','xxs','xxs','xs','sm','md','lg','xl','xxl','xxl' * + * slowdown : 'default','1x','2x','3x','4x','5x' * + * speedup : 'default','1x','2x','3x','4x','5x','6x','7x','8x','9x','10x','11x','12x','13x','14x','15x','16x','17x','18x','19x','20x' * + * style : 'default','black','black-inverse','white','white-inverse','colour','neon','nimbus','trimmed' * + * barStripesDirection : 'left','right' * + * keepContents : true,false * + * showContents : true,false * + * keepSize : true,false * + * addElementClass : 'name of css class(es)' * + * addElementStyles : 'custom css3 rules for root element' * + * strictHide : true,false * + * halign : 'left','center','right' * + * valign : 'default','top','middle','bottom' * + * disable : true,false * + * loaderType : 'spinner','bar' * + * type : 'default','dialog','modal' * + * dialogHeading : '[HTML]' * + * dialogHeadingImg : '[IMAGE URL]' * + * dialogHeadingText : '[TEXT]' * + * dialogBody : '[HTML]' * + * dialogBodyImg : '[IMAGE URL]' * + * dialogBodyText : '[TEXT]' * + * modalImg : '[IMAGE URL]' * + * modalText : '[TEXT]' * + * modalFooterImg : '[IMAGE URL]' * + * modalFooterText : '[TEXT]' * + * * + * * + * EVENTS: * + * onCreate : Fired after the loader has been created * + * ARGUMENTS : function(callback) * + * SYNTAX : - At the time of initialization: * + * $(".myLoader").SGNLoader({ * + * onCreate: function(callback){ * + * //do something * + * } * + * -----------OR--------- * + * onCreate: myCallbackFunction(callback) * + * }); * + * - At the time of update (After initialization): * + * $(".myLoader").SGNLoader().update({ * + * onCreate: function(callback){ * + * //do something * + * } * + * -----------OR--------- * + * onCreate: myCallbackFunction(callback) * + * }); * + * onShow : Fired after the loader has been shown * + * ARGUMENTS : function(callback) * + * SYNTAX : - At the time of initialization: * + * $(".myLoader").SGNLoader({ * + * onShow: function(callback){ * + * //do something * + * } * + * -----------OR--------- * + * onShow: myCallbackFunction(callback) * + * }); * + * - At the time of update (After initialization): * + * $(".myLoader").SGNLoader().update({ * + * onShow: function(callback){ * + * //do something * + * } * + * -----------OR--------- * + * onShow: myCallbackFunction(callback) * + * }); * + * onHide : Fired after the loader has been shown * + * ARGUMENTS : function(callback) * + * SYNTAX : - At the time of initialization: * + * $(".myLoader").SGNLoader({ * + * onHide: function(callback){ * + * //do something * + * } * + * -----------OR--------- * + * onHide: myCallbackFunction(callback) * + * }); * + * - At the time of update (After initialization): * + * $(".myLoader").SGNLoader().update({ * + * onHide: function(callback){ * + * //do something * + * } * + * -----------OR--------- * + * onHide: myCallbackFunction(callback) * + * }); * + * onRemove : Fired after the loader has been shown * + * ARGUMENTS : function(callback) * + * SYNTAX : - At the time of initialization: * + * $(".myLoader").SGNLoader({ * + * onRemove: function(callback){ * + * //do something * + * } * + * -----------OR--------- * + * onRemove: myCallbackFunction(callback) * + * }); * + * - At the time of update (After initialization): * + * $(".myLoader").SGNLoader().update({ * + * onRemove: function(callback){ * + * //do something * + * } * + * -----------OR--------- * + * onRemove: myCallbackFunction(callback) * + * }); * + * * + * * + * METHODS: * + * show() : Show the currently initialized hidden loader * + * SYNTAX : $(".myLoader").SGNLoader().show(); * + * * + * hide([boolean strict=false]) : Show the currently initialized shown loader * + * ARGUMENTS : strict - false(default). If true, SGNLoader will remove the layout also * + * SYNTAX : $(".myLoader").SGNLoader().hide(); * + * * + * update(json options) : Update the currently initialized loader with new option(s) * + * ARGUMENTS : options - specify the option to be modified * + * SYNTAX : $(".myLoader").SGNLoader().update({ * + * style: "nimbus" * + * }); * + * * + * remove() : Remove the currently initialized loader * + * SYNTAX : $(".myLoader").SGNLoader().remove() * + ************************************************************************************************************************************/ + +(function($) { + $.fn.removeClassStartingWith = function(name) { + let classes = this.attr('class'); + if(classes) { + classes = classes.replace(new RegExp('\\b' + name + '\\S*\\s?', 'g'), '').trim(); + classes ? this.attr('class', classes) : this.removeAttr('class'); + } + return this; + }; + + var SGNLoader = function(element, options) { + var _pluginName = "SGNLoader", + _pluginVersion = "1.0.9"; + var _defaults = { + animation: 'linear', + border: 'sm', + size: 'xs', + slowdown: '2x', + speedup: '1x', + style: 'default', + barStripesDirection: 'left', + keepContents: true, + showContents: true, + keepSize: true, + addElementClass: '', + strictHide: false, + positionType: 'absolute', + halign: 'center', + valign: 'middle', + disable: true, + loaderType: 'spinner', + type: 'default', + dialogHeadingText: 'Loading', + dialogBodyText: 'Please wait...', + onCreate: function(el, spinner) {}, + onShow: function(el, spinner) {}, + onHide: function(el, spinner) {}, + onRemove: function(el, spinner) {} + } + var _options = { + animation: [ + 'default', 'linear', 'ease', 'easein', 'easeinout', 'easeout', 'steps', 'stepstart', 'stepend' + ], + border: [ + 'default', 'xxxs', 'xxs', 'xs', 'sm', 'md', 'lg', 'xl', 'xxl', 'xxxl' + ], + size: [ + 'default', 'xxxs', 'xxs', 'xs', 'sm', 'md', 'lg', 'xl', 'xxl', 'xxxl' + ], + slowdown: [ + 'default', '1x', '2x', '3x', '4x', '5x' + ], + speedup: [ + 'default', '1x', '2x', '3x', '4x', '5x', '6x', '7x', '8x', '9x', '10x', '11x', '12x', '13x', '14x', '15x', '16x', '17x', '18x', '19x', '20x' + ], + style: [ + 'default', 'black', 'black-inverse', 'white', 'white-inverse', 'colour', 'neon', 'nimbus', 'trimmed' + ], + barStripesDirection: [ + 'left', 'right' + ], + keepContents: [ + true, false + ], + showContents: [ + true, false + ], + keepSize: [ + true, false + ], + addElementClass: ':string', + addElementStyles: ':string', + strictHide: [ + true, false + ], + positionType: [ + 'absolute', 'flex', 'relative' + ], + halign: [ + 'default', 'left', 'center', 'right' + ], + valign: [ + 'default', 'top', 'middle', 'bottom' + ], + disable: [ + true, false + ], + loaderType: [ + 'spinner', 'bar' + ], + type: [ + 'default', 'dialog', 'modal' + ], + dialogHeading: ':string', + dialogHeadingImg: ':url', + dialogHeadingText: ':string', + dialogBody: ':string', + dialogBodyImg: ':url', + dialogBodyText: ':string', + modalImg: ':url', + modalText: ':string', + modalFooterImg: ':url', + modalFooterText: ':string', + onCreate: '', + onShow: '', + onHide: '', + onRemove: '' + }; + var plugin = this; + + plugin.settings = {} + + var $element = $(element), + element = element; + + plugin.init = function(args) { + if((options.loaderType == 'spinner' || options.loaderType == 'default')) { + _defaults.slowdown = '2x'; + } else if(options.loaderType == 'bar') { + _defaults.slowdown = '1x'; + } + plugin.settings = $.extend(_defaults, options); + $.each(plugin.settings, function(k, v) { + if(typeof v === 'function') { + if(_options.hasOwnProperty(k)) { + _checked = true; + } else { + _checked = false; + $.error('Invalid callback for: ' + k + ' in jQuery.' + _pluginName + ' v' + _pluginVersion); + } + } else if(typeof v === 'string') { + if($.inArray(v, _options[k]) !== -1 || _options[k] == ':string') { + _checked = true; + } else { + _checked = false; + $.error('Invalid value: ' + v + ' for option: ' + k + ' in jQuery.' + _pluginName + ' v' + _pluginVersion); + } + } + }); + if(_checked) { + $element.data('options', plugin.settings); + plugin.settings = $element.data('options'); + create(); + } + } + + //PUBLIC METHODS + plugin.showLoader = function() { + showLoader(); + } + plugin.hideLoader = function(strict) { + hideLoader(strict); + } + plugin.update = function(options) { + update(options); + } + plugin.removeLoader = function() { + removeLoader(); + } + + //PRIVATE METHODS + var getClasses = function() { + var rx = /(^|\s)sgn-loader-\S+/g; + var classes = $element.attr('class').split(' '); + var ret = ""; + $.each(classes, function(i, c) { + if(rx.test(c) || c == "sgn-loader" || c == "sgn-spinner" || c == "sgn-bar") + ret = c + " "; + }); + return ret.trim(); + } + var create = function() { + if(plugin.settings.type == 'modal' || plugin.settings.type == 'dialog') { + $element.addClass("sgn-loader-modal"); + } else { + $element.removeClass("sgn-loader-modal"); + } + if(plugin.settings.loaderType == 'spinner' || plugin.settings.loaderType == 'default') { + if(plugin.settings.animation) { + _anim = "sgn-spinner-animation-" + plugin.settings.animation; + } + if(plugin.settings.border) { + _border = "sgn-loader-border-" + plugin.settings.border; + } + if(plugin.settings.size) { + _size = "sgn-loader-" + plugin.settings.size; + } + if(plugin.settings.slowdown) { + _slowdown = "sgn-spinner-" + plugin.settings.slowdown; + } + if(plugin.settings.style) { + _style = "sgn-spinner-" + plugin.settings.style; + } + _classes = _style + " " + _slowdown + " " + _size + " " + _border + " " + _anim; + _classes = "sgn-spinner " + _classes.trim(); + } else if(plugin.settings.loaderType == 'bar') { + if(plugin.settings.animation) { + _anim = "sgn-bar-animation-" + plugin.settings.animation; + } + if(plugin.settings.size) { + _size = "sgn-loader-" + plugin.settings.size; + } + if(plugin.settings.slowdown) { + _slowdown = "sgn-bar-delay-" + plugin.settings.slowdown; + } + if(plugin.settings.barStripesDirection) { + _barStripesDirection = "sgn-bar-stripes-" + plugin.settings.barStripesDirection; + } + if(plugin.settings.speedup) { + _speedup = "sgn-bar-speed-" + plugin.settings.speedup; + } + if(plugin.settings.style) { + _style = "sgn-bar-" + plugin.settings.style; + } + _classes = _style + " " + _size + " " + _barStripesDirection + " " + _slowdown + " " + _speedup + " " + _anim; + _classes = "sgn-bar " + _classes.trim(); + } + if(plugin.settings.keepSize) { + _width = $element.width(); + _height = $element.height(); + $element.width(_width); + $element.height(_height); + } + if(plugin.settings.disable) { + $element.attr("disabled", true); + } + if(plugin.settings.addElementClass) { + $element.addClass(plugin.settings.addElementClass); + } + + var _content = ($element.html()) ? $element.html() : ""; + _showContent = (plugin.settings.showContents) ? '' : ' style="display:none;"'; + _content = '' + _content + ''; + _content = (plugin.settings.keepContents) ? _content : ""; + $element.removeClass("sgn-loader").addClass("sgn-loader"); + + if(plugin.settings.loaderType == 'spinner' || plugin.settings.loaderType == 'default') { + $element.html('' + _content); + } else if(plugin.settings.loaderType == 'bar') { + $element.html('' + _content); + } + + if((plugin.settings.halign != '' && plugin.settings.halign != null && plugin.settings.halign !== undefined && plugin.settings.halign != 'default') && (plugin.settings.valign != '' && plugin.settings.valign != null && plugin.settings.valign !== undefined && plugin.settings.valign != 'default')) { + if(plugin.settings.halign == 'default') + plugin.settings.halign = 'center'; + if(plugin.settings.valign == 'default') + plugin.settings.valign = 'middle'; + if(plugin.settings.valign != '' && plugin.settings.valign != null && plugin.settings.valign !== undefined) + _align = plugin.settings.valign; + if(plugin.settings.halign != '' && plugin.settings.halign != null && plugin.settings.halign !== undefined) + _align = _align + "_" + plugin.settings.halign; + + if(plugin.settings.positionType !== undefined) + positionType = plugin.settings.positionType; + + if(plugin.settings.loaderType == 'spinner' || plugin.settings.loaderType == 'default') + $element.children('.sgn-spinner').addClass('sgn-loader-aligner-type-' + positionType + ' sgn-loader-aligner-' + _align); + else if(plugin.settings.loaderType == 'bar') + $element.children('.sgn-bar').addClass('sgn-loader-aligner-type-' + positionType + ' sgn-loader-aligner-' + _align); + } + if(plugin.settings.loaderType == 'spinner' || plugin.settings.loaderType == 'default') { + plugin.settings.onCreate($element, $element.children('.sgn-spinner')); + plugin.settings.onShow($element, $element.children('.sgn-spinner')); + } else if(plugin.settings.loaderType == 'bar') { + plugin.settings.onCreate($element, $element.children('.sgn-bar')); + plugin.settings.onShow($element, $element.children('.sgn-bar')); + } + } + var update = function(options) { + _defaults = (!$element.data('options')) ? defaults : $element.data('options'); + plugin.settings = $.extend(_defaults, options); + $.each(plugin.settings, function(k, v) { + if(typeof v === 'function') { + if(_options.hasOwnProperty(k)) { + _checked = true; + } else { + _checked = false; + $.error('Invalid callback for ' + k + ' in jQuery.' + _pluginName + ' v' + _pluginVersion); + } + } else if(typeof v === 'object') { + if($.inArray(v, _options[k]) !== -1) { + _checked = true; + } else { + _checked = false; + $.error('Invalid Value for option ' + k + ' in jQuery.' + _pluginName + ' v' + _pluginVersion); + } + } + }); + if(_checked) { + if(plugin.settings.animation) { + _anim = "sgn-spinner-animation-" + plugin.settings.animation; + } + if(plugin.settings.border) { + _border = "sgn-loader-border-" + plugin.settings.border; + } + if(plugin.settings.size) { + _size = "sgn-loader-" + plugin.settings.size; + } + if(plugin.settings.slowdown) { + _slowdown = "sgn-spinner-" + plugin.settings.slowdown; + } + if(plugin.settings.style) { + _style = "sgn-spinner-" + plugin.settings.style; + } + _classes = _style + " " + _slowdown + " " + _size + " " + _border + " " + _anim; + _classes = "sgn-spinner " + _classes.trim(); + var _content = ($element.html()) ? $element.html() : ""; + _showContent = (plugin.settings.showContents) ? '' : ' style="display:none;"'; + _content = '' + _content + ''; + _content = (plugin.settings.keepContents) ? _content : ""; + if($element.hasClass("sgn-loader")) { + if($element.children(".sgn-spinner").length > 0) { + $element.children(".sgn-spinner").removeClass().addClass(_classes); + } else { + $element.html('' + _content); + } + } else { + if($element.children(".sgn-spinner").length > 0) { + $element.addClass("sgn-loader"); + $element.children(".sgn-spinner").removeClass().addClass(_classes); + } else { + $element.removeClass("sgn-loader").addClass("sgn-loader"); + $element.html('' + _content); + } + } + } + } + var showLoader = function(options) { + var settings = $element.data('options'); + if(!$element.hasClass("sgn-loader")) + $element.addClass("sgn-loader"); + if(settings.disable) + $element.attr("disabled", true); + if(plugin.settings.loaderType == 'spinner' || plugin.settings.loaderType == 'default') { + $element.children(".sgn-spinner").next(".sgn-spinner-contents").hide(); + $element.children(".sgn-spinner").show(); + settings.onShow($element, $element.children('.sgn-spinner')); + } else if(plugin.settings.loaderType == 'bar') { + $element.children(".sgn-bar").next(".sgn-spinner-contents").hide(); + $element.children(".sgn-bar").show(); + settings.onShow($element, $element.children('.sgn-bar')); + } + } + var hideLoader = function(options) { + var settings = $element.data('options'); + var strict = (typeof strict == 'undefined') ? $element.data('options').strictHide : strict; + if(plugin.settings.loaderType == 'spinner' || plugin.settings.loaderType == 'default') { + $element.children(".sgn-spinner").next(".sgn-spinner-contents").show(); + $element.children(".sgn-spinner").hide(); + } else if(plugin.settings.loaderType == 'bar') { + $element.children(".sgn-bar").next(".sgn-spinner-contents").show(); + $element.children(".sgn-bar").hide(); + } + if(settings.disable) + $element.removeAttr("disabled"); + if(strict) { + $element.removeClass(getClasses()); + $element.removeClass('sgn-loader'); + } + if(plugin.settings.loaderType == 'spinner' || plugin.settings.loaderType == 'default') + settings.onHide($element, $element.children('.sgn-spinner')); + else if(plugin.settings.loaderType == 'bar') + settings.onHide($element, $element.children('.sgn-bar')); + } + var removeLoader = function(options) { + var settings = $element.data('options'); + var _content; + if(settings.disable) + $element.removeAttr("disabled"); + if(plugin.settings.loaderType == 'spinner' || plugin.settings.loaderType == 'default') { + _content = $element.children(".sgn-spinner").next(".sgn-spinner-contents").html(); + $element.children(".sgn-spinner").remove(); + } else if(plugin.settings.loaderType == 'bar') { + _content = $element.children(".sgn-bar").next(".sgn-spinner-contents").html(); + $element.children(".sgn-bar").remove(); + } + $element.removeClass("sgn-loader"); + $element.css("width", ""); + $element.css("height", ""); + $element.html(_content); + if(plugin.settings.loaderType == 'spinner' || plugin.settings.loaderType == 'default') + settings.onRemove($element, $element.children('.sgn-spinner')); + else if(plugin.settings.loaderType == 'bar') + settings.onRemove($element, $element.children('.sgn-bar')); + } + } + + // add the plugin to the jQuery.fn object + $.fn.SGNLoader = function(options) { + var _this = this; + var _plugin = new SGNLoader(this, options); + this.initialize = function(options) { + _plugin.init(options); + return this; + } + this.show = function() { + _plugin.showLoader(); + } + this.hide = function(strict) { + _plugin.hideLoader(strict); + } + this.update = function(options) { + _plugin.update(options); + } + this.remove = function() { + _plugin.removeLoader(); + } + if(typeof options !== 'undefined') + return this.initialize(); + return this; + } + $.fn.SGNSpinner = function(options) { + var _this = this; + var _plugin = new SGNLoader(this, options); + this.initialize = function(options) { + _plugin.init(options); + return this; + } + this.show = function() { + _plugin.showLoader(); + } + this.hide = function(strict) { + _plugin.hideLoader(strict); + } + this.update = function(options) { + _plugin.update(options); + } + this.remove = function() { + _plugin.removeLoader(); + } + if(typeof options !== 'undefined') + return this.initialize(); + return this; + } + + return this; + +})(jQuery); diff --git a/src/addons/SGNLoaders/SGNLoaders.min.css b/src/addons/SGNLoaders/SGNLoaders.min.css new file mode 100644 index 00000000..918c52b7 --- /dev/null +++ b/src/addons/SGNLoaders/SGNLoaders.min.css @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +/************************************************************************************************************************************ +******************************************************SGNSPINNER v1.0.9************************************************************** +************************************************************************************************************************************* +* DATE: December 19, 2019 * +* AUTHOR: Sagnik Ganguly * +* E-MAIL: sagnikganguly2012@rediffmail.com * +* WEBSITE: https://plugins.sgnetworks.ga/jquery/sgnspinner * +* DOCUMENTATION: https://docs.plugins.sgnetworks.ga/jquery/sgnspinner * +************************************************************************************************************************************/ +.sgn-loader{padding:5px;}input.sgn-loader,button.sgn-loader,a.sgn-loader{margin-top: 5px;}.sgn-loader>.sgn-spinner:before{content:'';box-sizing:border-box;display:inline-block;animation-name:sgn-spinner;animation-duration:.6s;animation-timing-function:linear;animation-iteration-count:infinite;border-radius:50%;height:30px;width:30px;margin:0px;padding:0px;margin-top:.5em;}.sgn-loader>.sgn-spinner.sgn-spinner-1x:before{animation-duration:1s;}.sgn-loader>.sgn-spinner.sgn-spinner-2x:before{animation-duration:2s;}.sgn-loader>.sgn-spinner.sgn-spinner-3x:before{animation-duration:3s;}.sgn-loader>.sgn-spinner.sgn-spinner-4x:before{animation-duration:4s;}.sgn-loader>.sgn-spinner.sgn-spinner-5x:before{animation-duration:5s;}.sgn-loader>.sgn-spinner.sgn-spinner-animation-ease:before{animation-timing-function:ease;}.sgn-loader>.sgn-spinner.sgn-spinner-animation-easein:before{animation-timing-function:ease-in;}.sgn-loader>.sgn-spinner.sgn-spinner-animation-easeinout:before{animation-timing-function:ease-in-out;}.sgn-loader>.sgn-spinner.sgn-spinner-animation-easeout:before{animation-timing-function:ease-out;}.sgn-loader>.sgn-spinner.sgn-spinner-animation-steps:before{animation-timing-function:steps;}.sgn-loader>.sgn-spinner.sgn-spinner-animation-stepstart:before{animation-timing-function:step-start;}.sgn-loader>.sgn-spinner.sgn-spinner-animation-stepend:before{animation-timing-function:step-end;}.sgn-loader>.sgn-spinner.sgn-loader-xxxs:before{height:20px;width:20px;}.sgn-loader>.sgn-spinner.sgn-loader-xxs:before{height:30px;width:30px;}.sgn-loader>.sgn-spinner.sgn-loader-xs:before{height:40px;width:40px;}.sgn-loader>.sgn-spinner.sgn-loader-sm:before{height:60px;width:60px;}.sgn-loader>.sgn-spinner.sgn-loader-md:before{height:80px;width:80px;}.sgn-loader>.sgn-spinner.sgn-loader-lg:before{height:100px;width:100px;}.sgn-loader>.sgn-spinner.sgn-loader-xl:before{height:120px;width:120px;}.sgn-loader>.sgn-spinner.sgn-loader-xxl:before{height:130px;width:130px;}.sgn-loader>.sgn-spinner.sgn-loader-xxxl:before{height:140px;width:140px;}.sgn-loader>.sgn-spinner.sgn-loader-border-xxxs:before{border-width:1px!important;}.sgn-loader>.sgn-spinner.sgn-loader-border-xxs:before{border-width:2px!important;}.sgn-loader>.sgn-spinner.sgn-loader-border-xs:before{border-width:4px!important;}.sgn-loader>.sgn-spinner.sgn-loader-border-sm:before{border-width:6px!important;}.sgn-loader>.sgn-spinner.sgn-loader-border-md:before{border-width:8px!important;}.sgn-loader>.sgn-spinner.sgn-loader-border-lg:before{border-width:10px!important;}.sgn-loader>.sgn-spinner.sgn-loader-border-xl:before{border-width:12px!important;}.sgn-loader>.sgn-spinner.sgn-loader-border-xxl:before{border-width:14px!important;}.sgn-loader>.sgn-spinner.sgn-loader-border-xxxl:before{border-width:16px!important;}.sgn-loader-aligner{position:absolute;}.sgn-loader-align-left{left:0%;transform:translate3d(0,0%,0);}.sgn-loader-align-center{left:50%;transform:translate3d(-50%,0,0);}.sgn-loader-align-right{text-align:right;}.sgn-loader-align-top{top:0%;transform:translate3d(0,0%,0);}.sgn-loader-align-middle{top:50%;transform:translate3d(0,-50%,0);}.sgn-loader-align-bottom{top:100%;transform:translate3d(0,-100%,0);}.sgn-loader-aligner-top_left{position:absolute;top:0%;left:0%;transform:translate3d(-0%,-0%,0);}.sgn-loader-aligner-top_center{position:absolute;top:0%;left:50%;transform:translate3d(-50%,-0%,0);}.sgn-loader-aligner-top_right{position:absolute;top:0%;left:100%;transform:translate3d(-100%,-0%,0);}.sgn-loader-aligner-middle_left{position:absolute;top:50%;left:0%;transform:translate3d(-0%,-50%,0);}.sgn-loader-aligner-middle_center{position:absolute;top:50%;left:50%;transform:translate3d(-50%,-50%,0);}.sgn-loader-aligner-middle_right{position:absolute;top:50%;left:100%;transform:translate3d(-100%,-50%,0);}.sgn-loader-aligner-bottom_left{position:absolute;top:100%;left:0%;transform:translate3d(-0%,-100%,0);}.sgn-loader-aligner-bottom_center{position:absolute;top:100%;left:50%;transform:translate3d(-50%,-100%,0);}.sgn-loader-aligner-bottom_right{position:absolute;top:100%;left:100%;transform:translate3d(-100%,-100%,0);}.sgn-loader>.sgn-spinner-default:before{border:2px solid#f3f3f3;border-top:2px solid#3498db;animation-duration:2s;}.sgn-loader>.sgn-spinner-black:before{border:2px solid#ccc;border-top-color:#333;}.sgn-loader>.sgn-spinner-black-inverse:before{border:2px solid#333;border-top-color:#ccc;}.sgn-loader>.sgn-spinner-white:before{border:2px solid#222;border-top-color:#fff;}.sgn-loader>.sgn-spinner-white-inverse:before{border:2px solid#fff;border-top-color:#222;}.sgn-loader>.sgn-spinner-neon:before{border:1px solid#ccc;border-top-color:#07d;}.sgn-loader>.sgn-spinner-trimmed:before{border:1px solid transparent;border-top-color:#07d;border-bottom-color:#07d;animation-duration:.8s;animation-timing-function:ease;}.sgn-loader>.sgn-spinner-nimbus:before{border-top:4px solid#07d;border-right:4px solid transparent;}.sgn-loader>.sgn-spinner-colour:before{border:1px solid#f6f;border-top-color:#0e0;border-right-color:#0dd;border-bottom-color:#f90;}@keyframes sgn-spinner{to{transform:rotate(360deg);}} diff --git a/src/addons/SGNLoaders/components/aligners.css b/src/addons/SGNLoaders/components/aligners.css new file mode 100644 index 00000000..79552c45 --- /dev/null +++ b/src/addons/SGNLoaders/components/aligners.css @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +/********************SGN LOADER ALIGNERS********************/ +.sgn-loader-aligner { + position: absolute; +} + +.sgn-loader-align-left { + left: 0%; + transform: translate3d(0, 0%, 0); +} + +.sgn-loader-align-center { + left: 50%; + transform: translate3d(-50%, 0, 0); +} + +.sgn-loader-align-right { + text-align: right; +} + +.sgn-loader-align-top { + top: 0%; + transform: translate3d(0, 0%, 0); +} + +.sgn-loader-align-middle { + top: 50%; + transform: translate3d(0, -50%, 0); +} + +.sgn-loader-align-bottom { + top: 100%; + transform: translate3d(0, -100%, 0); +} + + +.sgn-loader-aligner-type-absolute { + position: absolute; +} + +.sgn-loader-aligner-type-relative { + position: relative; +} + +.sgn-loader-aligner-type-flex { + display: flex; + height: 100%; +} + + +.sgn-loader-aligner-type-flex.sgn-loader-aligner-top_left { + align-items: flex-start; + justify-content: flex-start; +} + +.sgn-loader-aligner-type-flex.sgn-loader-aligner-top_center { + align-items: flex-start; + justify-content: center; +} + +.sgn-loader-aligner-type-flex.sgn-loader-aligner-top_right { + align-items: flex-start; + justify-content: flex-end; +} + +.sgn-loader-aligner-type-flex.sgn-loader-aligner-middle_left { + align-items: center; + justify-content: flex-start; +} + +.sgn-loader-aligner-type-flex.sgn-loader-aligner-middle_center { + align-items: center; + justify-content: center; +} + +.sgn-loader-aligner-type-flex.sgn-loader-aligner-middle_right { + align-items: center; + justify-content: flex-end; +} + +.sgn-loader-aligner-type-flex.sgn-loader-aligner-bottom_left { + align-items: flex-end; + justify-content: flex-start; +} + +.sgn-loader-aligner-type-flex.sgn-loader-aligner-bottom_center { + align-items: flex-end; + justify-content: center; +} + +.sgn-loader-aligner-type-flex.sgn-loader-aligner-bottom_right { + align-items: flex-end; + justify-content: flex-end; +} + + +.sgn-loader-aligner-type-absolute.sgn-loader-aligner-top_left, +.sgn-loader-aligner-type-relative.sgn-loader-aligner-top_left { + top: 0%; + left: 0%; + transform: translate3d(-0%, -0%, 0); +} + +.sgn-loader-aligner-type-absolute.sgn-loader-aligner-top_center, +.sgn-loader-aligner-type-relative.sgn-loader-aligner-top_center { + top: 0%; + left: 50%; + transform: translate3d(-50%, -0%, 0); +} + +.sgn-loader-aligner-type-absolute.sgn-loader-aligner-top_right, +.sgn-loader-aligner-type-relative.sgn-loader-aligner-top_right { + top: 0%; + left: 100%; + transform: translate3d(-100%, -0%, 0); +} + +.sgn-loader-aligner-type-absolute.sgn-loader-aligner-middle_left, +.sgn-loader-aligner-type-relative.sgn-loader-aligner-middle_left { + top: 50%; + left: 0%; + transform: translate3d(-0%, -50%, 0); +} + +.sgn-loader-aligner-type-absolute.sgn-loader-aligner-middle_center, +.sgn-loader-aligner-type-relative.sgn-loader-aligner-middle_center { + top: 50%; + left: 50%; + transform: translate3d(-50%, -50%, 0); +} + +.sgn-loader-aligner-type-absolute.sgn-loader-aligner-middle_right, +.sgn-loader-aligner-type-relative.sgn-loader-aligner-middle_right { + top: 50%; + left: 100%; + transform: translate3d(-100%, -50%, 0); +} + +.sgn-loader-aligner-type-absolute.sgn-loader-aligner-bottom_left, +.sgn-loader-aligner-type-relative.sgn-loader-aligner-bottom_left { + top: 100%; + left: 0%; + transform: translate3d(-0%, -100%, 0); +} + +.sgn-loader-aligner-type-absolute.sgn-loader-aligner-bottom_center, +.sgn-loader-aligner-type-relative.sgn-loader-aligner-bottom_center { + top: 100%; + left: 50%; + transform: translate3d(-50%, -100%, 0); +} + +.sgn-loader-aligner-type-absolute.sgn-loader-aligner-bottom_right, +.sgn-loader-aligner-type-relative.sgn-loader-aligner-bottom_right { + top: 100%; + left: 100%; + transform: translate3d(-100%, -100%, 0); +} diff --git a/src/addons/SGNLoaders/components/bars/animations.css b/src/addons/SGNLoaders/components/bars/animations.css new file mode 100644 index 00000000..fbc688f8 --- /dev/null +++ b/src/addons/SGNLoaders/components/bars/animations.css @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +/********************SGN BARS ANIMATIONS********************/ +.sgn-loader > .sgn-bar.sgn-bar-animation-ease > .bar { + animation-timing-function: ease; +} + +.sgn-loader > .sgn-bar.sgn-bar-animation-easein > .bar { + animation-timing-function: ease-in; +} + +.sgn-loader > .sgn-bar.sgn-bar-animation-easeinout > .bar { + animation-timing-function: ease-in-out; +} + +.sgn-loader > .sgn-bar.sgn-bar-animation-easeout > .bar { + animation-timing-function: ease-out; +} + +.sgn-loader > .sgn-bar.sgn-bar-animation-linear > .bar { + animation-timing-function: linear; +} + +.sgn-loader > .sgn-bar.sgn-bar-animation-revert > .bar { + animation-timing-function: revert; +} diff --git a/src/addons/SGNLoaders/components/bars/bars.css b/src/addons/SGNLoaders/components/bars/bars.css new file mode 100644 index 00000000..3ad4c213 --- /dev/null +++ b/src/addons/SGNLoaders/components/bars/bars.css @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +@import url("animations.css"); +@import url("delays.css"); +@import url("sizes.css"); +@import url("speeds.css"); +@import url("keyframes.css"); +/* @import url('borders.css'); */ +.sgn-loader > .sgn-bar { + box-shadow: none; + position: relative; + display: block; + width: 100%; + height: .25rem; + overflow: hidden; + margin-bottom: 0rem; + background-color: #eeeeee; + border-radius: .25rem; +} + +.sgn-loader > .sgn-bar > .bar { + box-shadow: none; + height: .25rem; + border-radius: 0; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-pack: center; + justify-content: center; + text-align: center; + white-space: nowrap; + transition: width 2s ease-in-out; + background-size: 1rem 1rem; + color: #ffffff; + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} + +/********************SGN BARS STRIPES********************/ +.sgn-loader > .sgn-bar.sgn-bar-stripes-left > .bar { + animation: sgn-bar-stripes-left 1s linear infinite; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right > .bar { + animation: sgn-bar-stripes-right 1s linear infinite; +} + +/********************SGN BARS********************/ +.sgn-loader > .sgn-bar.sgn-bar-default > .bar { + background-color: #0d47a1; +} + +.sgn-loader > .sgn-bar.sgn-bar-black > .bar { + background-color: #000000; + background-image: linear-gradient(45deg, rgba(120, 120, 120, .15) 25%, transparent 25%, transparent 50%, rgba(120, 120, 120, .15) 50%, rgba(120, 120, 120, .15) 75%, transparent 75%, transparent); +} + +.sgn-loader > .sgn-bar.sgn-bar-black-inverse > .bar { + background-color: #000000; +} + +.sgn-loader > .sgn-bar.sgn-bar-white > .bar { + background-color: #ffffff; + background-image: linear-gradient(45deg, rgba(0, 0, 0, .15) 25%, transparent 25%, transparent 50%, rgba(0, 0, 0, .15) 50%, rgba(0, 0, 0, .15) 75%, transparent 75%, transparent); +} + +.sgn-loader > .sgn-bar.sgn-bar-white-inverse > .bar { + background-color: #ffffff; + background-image: linear-gradient(45deg, rgba(0, 0, 0, .5) 25%, transparent 25%, transparent 50%, rgba(0, 0, 0, .5) 50%, rgba(0, 0, 0, .5) 75%, transparent 75%, transparent); +} + +.sgn-loader > .sgn-bar.sgn-bar-neon > .bar { + background-color: #0077dd; +} + +.sgn-loader > .sgn-bar.sgn-bar-colour > .bar { + background-color: #ff66ff; + background-image: linear-gradient(45deg, rgba(0, 0, 14, 1) 25%, transparent 25%, transparent 50%, rgba(0, 13, 13, 1) 50%, rgba(0, 0, 249, 1) 75%, transparent 75%, transparent); +} + +.sgn-loader > .sgn-bar.sgn-bar-green > .bar { + background-color: #00c851; +} + +.sgn-loader > .sgn-bar.sgn-bar-cyan > .bar { + background-color: #33b5e5; +} + +.sgn-loader > .sgn-bar.sgn-bar-yellow > .bar { + background-color: #ffbb33; +} + +.sgn-loader > .sgn-bar.sgn-bar-red > .bar { + background-color: #ff3547; +} diff --git a/src/addons/SGNLoaders/components/bars/delays.css b/src/addons/SGNLoaders/components/bars/delays.css new file mode 100644 index 00000000..8ecd5a27 --- /dev/null +++ b/src/addons/SGNLoaders/components/bars/delays.css @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +/********************SGN BARS DELAYS********************/ +.sgn-loader > .sgn-bar.sgn-bar-delay-1x > .bar { + animation-duration: 1s; +} + +.sgn-loader > .sgn-bar.sgn-bar-delay-2x > .bar { + animation-duration: 2s; +} + +.sgn-loader > .sgn-bar.sgn-bar-delay-3x > .bar { + animation-duration: 3s; +} + +.sgn-loader > .sgn-bar.sgn-bar-delay-4x > .bar { + animation-duration: 4s; +} + +.sgn-loader > .sgn-bar.sgn-bar-delay-5x > .bar { + animation-duration: 5s; +} + +.sgn-loader > .sgn-bar.sgn-bar-delay-6x > .bar { + animation-duration: 6s; +} + +.sgn-loader > .sgn-bar.sgn-bar-delay-7x > .bar { + animation-duration: 7s; +} + +.sgn-loader > .sgn-bar.sgn-bar-delay-8x > .bar { + animation-duration: 8s; +} + +.sgn-loader > .sgn-bar.sgn-bar-delay-9x > .bar { + animation-duration: 9s; +} + +.sgn-loader > .sgn-bar.sgn-bar-delay-10x > .bar { + animation-duration: 10s; +} diff --git a/src/addons/SGNLoaders/components/bars/keyframes.css b/src/addons/SGNLoaders/components/bars/keyframes.css new file mode 100644 index 00000000..e19cbc58 --- /dev/null +++ b/src/addons/SGNLoaders/components/bars/keyframes.css @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +/********************SGN BARS KEYFRAMES********************/ +/**********STRIPES LEFT**********/ +@keyframes sgn-bar-stripes-left { + 0% { + background-position: 1rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-1x { + 0% { + background-position: 1rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-2x { + 0% { + background-position: 2rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-3x { + 0% { + background-position: 3rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-4x { + 0% { + background-position: 4rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-5x { + 0% { + background-position: 5rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-6x { + 0% { + background-position: 6rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-7x { + 0% { + background-position: 7rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-8x { + 0% { + background-position: 8rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-9x { + 0% { + background-position: 9rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-10x { + 0% { + background-position: 10rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-11x { + 0% { + background-position: 11rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-12x { + 0% { + background-position: 12rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-13x { + 0% { + background-position: 13rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-14x { + 0% { + background-position: 14rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-15x { + 0% { + background-position: 15rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-16x { + 0% { + background-position: 16rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-17x { + 0% { + background-position: 17rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-18x { + 0% { + background-position: 18rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-19x { + 0% { + background-position: 19rem 0; + } + 100% { + background-position: 0 0; + } +} + +@keyframes sgn-bar-stripes-left-20x { + 0% { + background-position: 20rem 0; + } + 100% { + background-position: 0 0; + } +} + +/**********STRIPES RIGHT**********/ +@keyframes sgn-bar-stripes-right { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 1rem 0; + } +} + +@keyframes sgn-bar-stripes-right-1x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 1rem 0; + } +} + +@keyframes sgn-bar-stripes-right-2x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 2rem 0; + } +} + +@keyframes sgn-bar-stripes-right-3x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 3rem 0; + } +} + +@keyframes sgn-bar-stripes-right-4x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 4rem 0; + } +} + +@keyframes sgn-bar-stripes-right-5x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 5rem 0; + } +} + +@keyframes sgn-bar-stripes-right-6x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 6rem 0; + } +} + +@keyframes sgn-bar-stripes-right-7x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 7rem 0; + } +} + +@keyframes sgn-bar-stripes-right-8x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 8rem 0; + } +} + +@keyframes sgn-bar-stripes-right-9x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 9rem 0; + } +} + +@keyframes sgn-bar-stripes-right-10x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 10rem 0; + } +} + +@keyframes sgn-bar-stripes-right-11x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 11rem 0; + } +} + +@keyframes sgn-bar-stripes-right-12x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 12rem 0; + } +} + +@keyframes sgn-bar-stripes-right-13x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 13rem 0; + } +} + +@keyframes sgn-bar-stripes-right-14x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 14rem 0; + } +} + +@keyframes sgn-bar-stripes-right-15x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 15rem 0; + } +} + +@keyframes sgn-bar-stripes-right-16x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 16rem 0; + } +} + +@keyframes sgn-bar-stripes-right-17x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 17rem 0; + } +} + +@keyframes sgn-bar-stripes-right-18x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 18rem 0; + } +} + +@keyframes sgn-bar-stripes-right-19x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 19rem 0; + } +} + +@keyframes sgn-bar-stripes-right-20x { + 0% { + background-position: 0rem 0; + } + 100% { + background-position: 20rem 0; + } +} diff --git a/src/addons/SGNLoaders/components/bars/sizes.css b/src/addons/SGNLoaders/components/bars/sizes.css new file mode 100644 index 00000000..ad77ad7a --- /dev/null +++ b/src/addons/SGNLoaders/components/bars/sizes.css @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +/********************SGN BARS SIZES********************/ +.sgn-loader > .sgn-bar.sgn-loader-xxxs, +.sgn-loader > .sgn-bar.sgn-loader-xxxs > .bar { + height: 4px; +} + +.sgn-loader > .sgn-bar.sgn-loader-xxs, +.sgn-loader > .sgn-bar.sgn-loader-xxs > .bar { + height: 6px; +} + +.sgn-loader > .sgn-bar.sgn-loader-xs, +.sgn-loader > .sgn-bar.sgn-loader-xs > .bar { + height: 8px; +} + +.sgn-loader > .sgn-bar.sgn-loader-sm, +.sgn-loader > .sgn-bar.sgn-loader-sm > .bar { + height: 10px; +} + +.sgn-loader > .sgn-bar.sgn-loader-md, +.sgn-loader > .sgn-bar.sgn-loader-md > .bar { + height: 12px; +} + +.sgn-loader > .sgn-bar.sgn-loader-lg, +.sgn-loader > .sgn-bar.sgn-loader-lg > .bar { + height: 14px; +} + +.sgn-loader > .sgn-bar.sgn-loader-xl, +.sgn-loader > .sgn-bar.sgn-loader-xl > .bar { + height: 16px; +} + +.sgn-loader > .sgn-bar.sgn-loader-xxl, +.sgn-loader > .sgn-bar.sgn-loader-xxl > .bar { + height: 18px; +} + +.sgn-loader > .sgn-bar.sgn-loader-xxxl, +.sgn-loader > .sgn-bar.sgn-loader-xxxl > .bar { + height: 20px; +} diff --git a/src/addons/SGNLoaders/components/bars/speeds.css b/src/addons/SGNLoaders/components/bars/speeds.css new file mode 100644 index 00000000..22e02b42 --- /dev/null +++ b/src/addons/SGNLoaders/components/bars/speeds.css @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +/********************SGN BARS SPEEDS********************/ +/**********STRIPES LEFT**********/ +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-1x > .bar { + animation-name: sgn-bar-stripes-left-1x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-2x > .bar { + animation-name: sgn-bar-stripes-left-2x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-3x > .bar { + animation-name: sgn-bar-stripes-left-3x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-4x > .bar { + animation-name: sgn-bar-stripes-left-4x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-5x > .bar { + animation-name: sgn-bar-stripes-left-5x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-6x > .bar { + animation-name: sgn-bar-stripes-left-6x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-7x > .bar { + animation-name: sgn-bar-stripes-left-7x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-8x > .bar { + animation-name: sgn-bar-stripes-left-8x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-9x > .bar { + animation-name: sgn-bar-stripes-left-9x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-10x > .bar { + animation-name: sgn-bar-stripes-left-10x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-11x > .bar { + animation-name: sgn-bar-stripes-left-11x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-12x > .bar { + animation-name: sgn-bar-stripes-left-12x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-13x > .bar { + animation-name: sgn-bar-stripes-left-13x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-14x > .bar { + animation-name: sgn-bar-stripes-left-14x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-15x > .bar { + animation-name: sgn-bar-stripes-left-15x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-16x > .bar { + animation-name: sgn-bar-stripes-left-16x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-17x > .bar { + animation-name: sgn-bar-stripes-left-17x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-18x > .bar { + animation-name: sgn-bar-stripes-left-18x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-19x > .bar { + animation-name: sgn-bar-stripes-left-19x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-left.sgn-bar-speed-20x > .bar { + animation-name: sgn-bar-stripes-left-20x; +} + +/**********STRIPES RIGHT**********/ +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-1x > .bar { + animation-name: sgn-bar-stripes-right-1x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-2x > .bar { + animation-name: sgn-bar-stripes-right-2x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-3x > .bar { + animation-name: sgn-bar-stripes-right-3x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-4x > .bar { + animation-name: sgn-bar-stripes-right-4x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-5x > .bar { + animation-name: sgn-bar-stripes-right-5x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-6x > .bar { + animation-name: sgn-bar-stripes-right-6x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-7x > .bar { + animation-name: sgn-bar-stripes-right-7x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-8x > .bar { + animation-name: sgn-bar-stripes-right-8x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-9x > .bar { + animation-name: sgn-bar-stripes-right-9x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-10x > .bar { + animation-name: sgn-bar-stripes-right-10x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-11x > .bar { + animation-name: sgn-bar-stripes-right-11x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-12x > .bar { + animation-name: sgn-bar-stripes-right-12x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-13x > .bar { + animation-name: sgn-bar-stripes-right-13x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-14x > .bar { + animation-name: sgn-bar-stripes-right-14x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-15x > .bar { + animation-name: sgn-bar-stripes-right-15x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-16x > .bar { + animation-name: sgn-bar-stripes-right-16x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-17x > .bar { + animation-name: sgn-bar-stripes-right-17x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-18x > .bar { + animation-name: sgn-bar-stripes-right-18x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-19x > .bar { + animation-name: sgn-bar-stripes-right-19x; +} + +.sgn-loader > .sgn-bar.sgn-bar-stripes-right.sgn-bar-speed-20x > .bar { + animation-name: sgn-bar-stripes-right-20x; +} diff --git a/src/addons/SGNLoaders/components/spinners/animations.css b/src/addons/SGNLoaders/components/spinners/animations.css new file mode 100644 index 00000000..d82358c6 --- /dev/null +++ b/src/addons/SGNLoaders/components/spinners/animations.css @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +/********************SGN SPINNERS ANIMATIONS********************/ +.sgn-loader > .sgn-spinner.sgn-spinner-animation-ease:before { + animation-timing-function: ease; +} + +.sgn-loader > .sgn-spinner.sgn-spinner-animation-easein:before { + animation-timing-function: ease-in; +} + +.sgn-loader > .sgn-spinner.sgn-spinner-animation-easeinout:before { + animation-timing-function: ease-in-out; +} + +.sgn-loader > .sgn-spinner.sgn-spinner-animation-easeout:before { + animation-timing-function: ease-out; +} + +.sgn-loader > .sgn-spinner.sgn-spinner-animation-steps:before { + animation-timing-function: steps; +} + +.sgn-loader > .sgn-spinner.sgn-spinner-animation-stepstart:before { + animation-timing-function: step-start; +} + +.sgn-loader > .sgn-spinner.sgn-spinner-animation-stepend:before { + animation-timing-function: step-end; +} diff --git a/src/addons/SGNLoaders/components/spinners/borders.css b/src/addons/SGNLoaders/components/spinners/borders.css new file mode 100644 index 00000000..d4ec4a91 --- /dev/null +++ b/src/addons/SGNLoaders/components/spinners/borders.css @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +/********************SGN SPINNERS BORDERS********************/ +.sgn-loader > .sgn-spinner.sgn-loader-border-xxxs:before { + border-width: 1px !important; +} + +.sgn-loader > .sgn-spinner.sgn-loader-border-xxs:before { + border-width: 2px !important; +} + +.sgn-loader > .sgn-spinner.sgn-loader-border-xs:before { + border-width: 4px !important; +} + +.sgn-loader > .sgn-spinner.sgn-loader-border-sm:before { + border-width: 6px !important; +} + +.sgn-loader > .sgn-spinner.sgn-loader-border-md:before { + border-width: 8px !important; +} + +.sgn-loader > .sgn-spinner.sgn-loader-border-lg:before { + border-width: 10px !important; +} + +.sgn-loader > .sgn-spinner.sgn-loader-border-xl:before { + border-width: 12px !important; +} + +.sgn-loader > .sgn-spinner.sgn-loader-border-xxl:before { + border-width: 14px !important; +} + +.sgn-loader > .sgn-spinner.sgn-loader-border-xxxl:before { + border-width: 16px !important; +} diff --git a/src/addons/SGNLoaders/components/spinners/sizes.css b/src/addons/SGNLoaders/components/spinners/sizes.css new file mode 100644 index 00000000..da048476 --- /dev/null +++ b/src/addons/SGNLoaders/components/spinners/sizes.css @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +/********************SGN SPINNERS SIZES********************/ +.sgn-loader > .sgn-spinner.sgn-loader-xxxs:before { + height: 20px; + width: 20px; +} + +.sgn-loader > .sgn-spinner.sgn-loader-xxs:before { + height: 30px; + width: 30px; +} + +.sgn-loader > .sgn-spinner.sgn-loader-xs:before { + height: 40px; + width: 40px; +} + +.sgn-loader > .sgn-spinner.sgn-loader-sm:before { + height: 60px; + width: 60px; +} + +.sgn-loader > .sgn-spinner.sgn-loader-md:before { + height: 80px; + width: 80px; +} + +.sgn-loader > .sgn-spinner.sgn-loader-lg:before { + height: 100px; + width: 100px; +} + +.sgn-loader > .sgn-spinner.sgn-loader-xl:before { + height: 120px; + width: 120px; +} + +.sgn-loader > .sgn-spinner.sgn-loader-xxl:before { + height: 130px; + width: 130px; +} + +.sgn-loader > .sgn-spinner.sgn-loader-xxxl:before { + height: 140px; + width: 140px; +} diff --git a/src/addons/SGNLoaders/components/spinners/speeds.css b/src/addons/SGNLoaders/components/spinners/speeds.css new file mode 100644 index 00000000..01af8376 --- /dev/null +++ b/src/addons/SGNLoaders/components/spinners/speeds.css @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +/********************SGN SPINNERS SPEEDS********************/ +.sgn-loader > .sgn-spinner.sgn-spinner-1x:before { + animation-duration: 1s; +} + +.sgn-loader > .sgn-spinner.sgn-spinner-2x:before { + animation-duration: 2s; +} + +.sgn-loader > .sgn-spinner.sgn-spinner-3x:before { + animation-duration: 3s; +} + +.sgn-loader > .sgn-spinner.sgn-spinner-4x:before { + animation-duration: 4s; +} + +.sgn-loader > .sgn-spinner.sgn-spinner-5x:before { + animation-duration: 5s; +} diff --git a/src/addons/SGNLoaders/components/spinners/spinners.css b/src/addons/SGNLoaders/components/spinners/spinners.css new file mode 100644 index 00000000..e6a43733 --- /dev/null +++ b/src/addons/SGNLoaders/components/spinners/spinners.css @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +@import url("speeds.css"); +@import url("animations.css"); +@import url("sizes.css"); +@import url("borders.css"); + +.sgn-loader > .sgn-spinner:before { + content: ""; + box-sizing: border-box; + display: inline-block; + animation-name: sgn-spinner; + animation-duration: .6s; + animation-timing-function: linear; + animation-iteration-count: infinite; + border-radius: 50%; + height: 30px; + width: 30px; + margin: 0; + padding: 0; +} + +/********************SGN SPINNERS********************/ +.sgn-loader > .sgn-spinner-default:before { + border: 2px solid #f3f3f3; + border-top: 2px solid #3498db; + animation-duration: 2s; +} + +.sgn-loader > .sgn-spinner-black:before { + border: 2px solid #cccccc; + border-top-color: #333333; +} + +.sgn-loader > .sgn-spinner-black-inverse:before { + border: 2px solid #333333; + border-top-color: #cccccc; +} + +.sgn-loader > .sgn-spinner-white:before { + border: 2px solid #222222; + border-top-color: #ffffff; +} + +.sgn-loader > .sgn-spinner-white-inverse:before { + border: 2px solid #ffffff; + border-top-color: #222222; +} + +.sgn-loader > .sgn-spinner-neon:before { + border: 1px solid #cccccc; + border-top-color: #0077dd; +} + +.sgn-loader > .sgn-spinner-trimmed:before { + border: 1px solid transparent; + border-top-color: #0077dd; + border-bottom-color: #0077dd; + animation-duration: .8s; + animation-timing-function: ease; +} + +.sgn-loader > .sgn-spinner-nimbus:before { + border-top: 4px solid #0077dd; + border-right: 4px solid transparent; +} + +.sgn-loader > .sgn-spinner-colour:before { + border: 1px solid #ff66ff; + border-top-color: #00ee00; + border-right-color: #00dddd; + border-bottom-color: #ff9900; +} + + +/********************SGN SPINNERS KEYFRAMES********************/ +@keyframes sgn-spinner { + to { transform: rotate(360deg); } +} diff --git a/src/addons/addons.css b/src/addons/addons.css index 8ffcd6ff..1ebccbcb 100644 --- a/src/addons/addons.css +++ b/src/addons/addons.css @@ -16,6 +16,7 @@ @import "noty/themes/relax.css" all and (prefers-color-scheme: light); @import "noty/themes/metroui.css" all and (prefers-color-scheme: dark); @import "PrismJS/prism.css"; +@import "SGNLoaders/SGNLoaders.css"; @import "SGNFullPage/SGNFullPage.css"; @import "SGNTimePicker/SGNTimePicker.min.css" all and (prefers-color-scheme: light); @import "SweetAlert2/sweetalert2.min.css"; diff --git a/src/addons/addons.js b/src/addons/addons.js index 57ab356f..bc71b4f4 100644 --- a/src/addons/addons.js +++ b/src/addons/addons.js @@ -20,6 +20,7 @@ import('./NavbarTransformIcons/NavbarTransformIcons.js'); import('./noty/noty.js'); import("./noty/noty.init.js"); import("./PrismJS/prism.js"); +import("./SGNLoaders/SGNLoaders.js"); import("./SGNAtom/SGNAtom.js"); import("./SGNFullPage/SGNFullPage.js"); import("./SGNGeoData/SGNGeoData.js"); diff --git a/src/css/SGNUIKit-free.css b/src/css/SGNUIKit-free.css index 2dbfa124..2d0deda4 100644 --- a/src/css/SGNUIKit-free.css +++ b/src/css/SGNUIKit-free.css @@ -115,6 +115,65 @@ main > .sgn-center-container { flex: 1; } +.user-offline { + overflow: hidden; +} + +.user-offline > * { + filter: grayscale(1); +} + +.user-offline > .overlay { + width: 100%; + height: 100%; + opacity: 1; + position: absolute; + z-index: 9999; + background-color: hsla(0, 0%, 0%, .9); + overflow: hidden; + filter: none !important; + transition: opacity, background-color .5s linear; +} + +.user-offline > .overlay.blackout { + background-color: hsla(0, 0%, 0%, 1); +} + +.user-offline > .overlay, +.user-offline > .overlay > .offline-msg { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + font-size: 1.5rem; +} + +.user-offline > .overlay > .offline-msg > .title, +.user-offline > .overlay > .offline-msg > .msg { + transition: color .5s linear; +} + +.user-offline > .overlay > .offline-msg > .msg { + color: var(--sgn-secondary, hsl(230, 0%, 30%)); +} + +.user-offline > .overlay > .offline-msg > .error, +.user-offline > .overlay > .offline-msg > .title { + color: var(--sgn-danger, hsl(0, 100%, 50%)); +} + +.user-offline > .overlay > .offline-msg > .success { + color: var(--sgn-success, hsl(130, 100%, 20%)); +} + +.user-offline > .overlay > .offline-msg > .info { + color: var(--sgn-info, hsl(190, 100%, 40%)); +} + +.user-offline > .overlay > .offline-msg > .warning { + color: var(--sgn-warning, hsl(45, 100%, 40%)); +} + :root, [class^="sgn-"], [class^="sgn-"] * { --sgn-border-radius-inner-diff: .2rem; --sgn-border-radius-xs: .2rem; diff --git a/src/css/SGNUIKit-pro.css b/src/css/SGNUIKit-pro.css index 91bf98e9..f50c31a2 100644 --- a/src/css/SGNUIKit-pro.css +++ b/src/css/SGNUIKit-pro.css @@ -115,6 +115,65 @@ main > .sgn-center-container { flex: 1; } +.user-offline { + overflow: hidden; +} + +.user-offline > * { + filter: grayscale(1); +} + +.user-offline > .overlay { + width: 100%; + height: 100%; + opacity: 1; + position: absolute; + z-index: 9999; + background-color: hsla(0, 0%, 0%, .9); + overflow: hidden; + filter: none !important; + transition: opacity, background-color .5s linear; +} + +.user-offline > .overlay.blackout { + background-color: hsla(0, 0%, 0%, 1); +} + +.user-offline > .overlay, +.user-offline > .overlay > .offline-msg { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + font-size: 1.5rem; +} + +.user-offline > .overlay > .offline-msg > .title, +.user-offline > .overlay > .offline-msg > .msg { + transition: color .5s linear; +} + +.user-offline > .overlay > .offline-msg > .msg { + color: var(--sgn-secondary, hsl(230, 0%, 30%)); +} + +.user-offline > .overlay > .offline-msg > .error, +.user-offline > .overlay > .offline-msg > .title { + color: var(--sgn-danger, hsl(0, 100%, 50%)); +} + +.user-offline > .overlay > .offline-msg > .success { + color: var(--sgn-success, hsl(130, 100%, 20%)); +} + +.user-offline > .overlay > .offline-msg > .info { + color: var(--sgn-info, hsl(190, 100%, 40%)); +} + +.user-offline > .overlay > .offline-msg > .warning { + color: var(--sgn-warning, hsl(45, 100%, 40%)); +} + :root, [class^="sgn-"], [class^="sgn-"] * { --sgn-border-radius-inner-diff: .2rem; --sgn-border-radius-xs: .2rem; diff --git a/src/css/addons/colors.css b/src/css/addons/colors.css new file mode 100644 index 00000000..9e176a5f --- /dev/null +++ b/src/css/addons/colors.css @@ -0,0 +1,6226 @@ +/* + * Copyright (c) 2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +.addon-color, +.addon-color * { + --black: hsl(0, 0%, 0%); + --grey: hsl(0, 0%, 1%); + --cod-grey: hsl(0, 0%, 4%); + --all-black: hsl(0, 0%, 9%); + --eerie-black: hsl(0, 0%, 11%); + --filmpro-black: hsl(0, 0%, 16%); + --mine-shaft: hsl(0, 0%, 20%); + --jet: hsl(0, 0%, 20%); + --davy-grey: hsl(0, 0%, 33%); + --granite-gray: hsl(0, 0%, 40%); + --dim-gray: hsl(0, 0%, 41%); + --sonic-silver: hsl(0, 0%, 46%); + --gray: hsl(0, 0%, 50%); + --spanish-gray: hsl(0, 0%, 60%); + --quick-silver: hsl(0, 0%, 65%); + --dark-gray-x11: hsl(0, 0%, 66%); + --silver-chalice: hsl(0, 0%, 67%); + --gray-x11-gray: hsl(0, 0%, 75%); + --silver: hsl(0, 0%, 75%); + --light-gray: hsl(0, 0%, 83%); + --gainsboro: hsl(0, 0%, 86%); + --cultured: hsl(0, 0%, 96%); + --white: hsl(0, 0%, 100%); + --windswept: hsl(0, 2%, 26%); + --half-bokara-grey: hsl(0, 2%, 20%); + --half-diesel: hsl(0, 4%, 20%); + --sheer-black: hsl(0, 4%, 19%); + --reddish-brownish-black: hsl(0, 5%, 11%); + --barbecue: hsl(0, 6%, 20%); + --maxwell-smart: hsl(0, 6%, 15%); + --double-barbecue: hsl(0, 11%, 14%); + --cave-rock: hsl(0, 11%, 19%); + --half-barista: hsl(0, 13%, 28%); + --earlybird: hsl(0, 17%, 27%); + --woody-brown: hsl(0, 19%, 24%); + --copper-rose: hsl(0, 20%, 50%); + --rose-taupe: hsl(0, 22%, 46%); + --tuscany: hsl(0, 24%, 68%); + --rosy-brown: hsl(0, 25%, 65%); + --very-reddish-brown: hsl(0, 26%, 9%); + --tuscan-red: hsl(0, 27%, 38%); + --gondola: hsl(0, 31%, 11%); + --jon: hsl(0, 31%, 18%); + --middle-red-purple-light: hsl(0, 33%, 49%); + --nelson-red: hsl(0, 36%, 23%); + --havana: hsl(0, 42%, 14%); + --cocoa-bean: hsl(0, 44%, 20%); + --dark-sienna: hsl(0, 50%, 16%); + --fuzzy-wuzzy: hsl(0, 50%, 60%); + --indian-red: hsl(0, 53%, 58%); + --auburn: hsl(0, 59%, 41%); + --baby-pink: hsl(0, 69%, 86%); + --barn-red: hsl(4, 97%, 25%); + --bittersweet: hsl(6, 99%, 68%); + --black-bean: hsl(10, 94%, 12%); + --blast-off-bronze: hsl(12, 27%, 52%); + --bole: hsl(9, 34%, 35%); + --burnished-brown: hsl(8, 19%, 54%); + --burnt-sienna: hsl(14, 78%, 62%); + --burnt-umber: hsl(9, 59%, 34%); + --candy-apple-red: hsl(2, 100%, 50%); + --caput-mortuum: hsl(7, 47%, 24%); + --carmine-pink: hsl(4, 81%, 59%); + --carnelian: hsl(0, 74%, 40%); + --boston-university-red: hsl(0, 100%, 40%); + --cedar-chest: hsl(8, 54%, 54%); + --cg-red: hsl(4, 74%, 54%); + --chestnut: hsl(10, 48%, 40%); + --chinese-red: hsl(11, 70%, 39%); + --cinereous: hsl(12, 12%, 54%); + --cinnabar: hsl(5, 76%, 55%); + --congo-pink: hsl(5, 90%, 72%); + --copper-penny: hsl(5, 29%, 55%); + --copper-red: hsl(14, 54%, 56%); + --coquelicot: hsl(13, 100%, 50%); + --coral-reef: hsl(6, 97%, 71%); + --dark-chestnut: hsl(10, 23%, 49%); + --dark-coral: hsl(10, 58%, 54%); + --dark-liver-horses: hsl(12, 21%, 27%); + --dark-pastel-red: hsl(9, 70%, 45%); + --firebrick: hsl(0, 68%, 42%); + --falu-red: hsl(0, 68%, 30%); + --deep-red: hsl(0, 99%, 26%); + --deep-maroon: hsl(0, 100%, 25%); + --dark-red: hsl(0, 100%, 27%); + --crimson-red: hsl(0, 100%, 30%); + --dark-candy-apple-red: hsl(0, 100%, 32%); + --coral-red: hsl(0, 100%, 63%); + --deep-chestnut: hsl(3, 45%, 50%); + --deep-coffee: hsl(1, 27%, 35%); + --dust-storm: hsl(6, 35%, 84%); + --ferrari-red: hsl(9, 100%, 50%); + --french-puce: hsl(11, 79%, 17%); + --giant-club: hsl(6, 37%, 51%); + --international-orange-engineering: hsl(3, 88%, 39%); + --international-orange-golden-gate-bridge: hsl(4, 63%, 46%); + --jelly-bean: hsl(8, 65%, 58%); + --kenyan-copper: hsl(12, 92%, 25%); + --kobe: hsl(12, 71%, 31%); + --licorice: hsl(6, 24%, 8%); + --light-salmon-pink: hsl(0, 100%, 80%); + --liver: hsl(9, 18%, 34%); + --liver-organ: hsl(12, 55%, 27%); + --maximum-red: hsl(0, 74%, 49%); + --light-coral: hsl(0, 79%, 72%); + --lust: hsl(0, 80%, 51%); + --maroon-html-css: hsl(0, 100%, 25%); + --medium-carmine: hsl(5, 54%, 45%); + --medium-vermilion: hsl(14, 68%, 54%); + --melon: hsl(7, 95%, 85%); + --middle-red: hsl(14, 69%, 67%); + --misty-rose: hsl(6, 100%, 94%); + --mordant-red-19: hsl(4, 100%, 34%); + --new-york-pink: hsl(3, 52%, 67%); + --old-burgundy: hsl(6, 19%, 22%); + --ogre-odor: hsl(6, 98%, 62%); + --orange-soda: hsl(10, 95%, 61%); + --outrageous-orange: hsl(12, 100%, 65%); + --pastel-pink: hsl(1, 47%, 76%); + --pastel-red: hsl(3, 100%, 69%); + --persian-plum: hsl(0, 60%, 27%); + --persian-red: hsl(0, 60%, 50%); + --permanent-geranium-lake: hsl(0, 75%, 53%); + --portland-orange: hsl(11, 100%, 61%); + --red: hsl(0, 100%, 50%); + --red-ryb: hsl(5, 99%, 53%); + --red-orange: hsl(3, 100%, 64%); + --redwood: hsl(6, 33%, 48%); + --rose-ebony: hsl(4, 19%, 34%); + --rufous: hsl(8, 92%, 34%); + --salmon: hsl(6, 93%, 71%); + --scarlet: hsl(8, 100%, 50%); + --silver-pink: hsl(3, 16%, 72%); + --smokey-topaz: hsl(15, 82%, 28%); + --spanish-pink: hsl(1, 78%, 86%); + --sunset-orange: hsl(4, 98%, 66%); + --sweet-brown: hsl(3, 55%, 43%); + --tart-orange: hsl(2, 96%, 63%); + --terra-cotta: hsl(10, 70%, 62%); + --tomato: hsl(9, 100%, 64%); + --vermilion-dark: hsl(8, 76%, 48%); + --vivid-auburn: hsl(2, 60%, 36%); + --vivid-tangerine: hsl(12, 100%, 77%); + --wenge: hsl(7, 10%, 36%); + --burnt-maroon: hsl(0, 91%, 14%); + --chocolate: hsl(0, 93%, 11%); + --dried-blood: hsl(0, 97%, 15%); + --diesel: hsl(0, 100%, 4%); + --very-deep-reddish-brown: hsl(0, 100%, 6%); + --rosso-corsa: hsl(0, 100%, 42%); + --snow: hsl(0, 100%, 99%); + --very-dark-brown: hsl(4, 100%, 6%); + --night-rider: hsl(11, 35%, 9%); + --coffee-bean: hsl(13, 50%, 11%); + --cocoa-brown: hsl(3, 23%, 15%); + --eclipse: hsl(12, 36%, 14%); + --livid-brown: hsl(7, 9%, 18%); + --toast-lmu-20: hsl(3, 75%, 13%); + --toorak: hsl(5, 24%, 18%); + --double-barista: hsl(8, 15%, 19%); + --rebel: hsl(13, 82%, 13%); + --beer-srm-37: hsl(1, 76%, 13%); + --hot-chocolate: hsl(9, 28%, 19%); + --marbaroda: hsl(15, 15%, 21%); + --cedar: hsl(11, 51%, 16%); + --tamarind: hsl(4, 15%, 21%); + --pms440: hsl(15, 19%, 21%); + --deep-brown: hsl(2, 100%, 13%); + --short-black: hsl(12, 42%, 18%); + --beer-srm-36: hsl(1, 81%, 14%); + --pms4975: hsl(3, 42%, 19%); + --beer-srm-35: hsl(2, 86%, 14%); + --digeridoo: hsl(9, 31%, 21%); + --stingray: hsl(7, 15%, 24%); + --barista: hsl(4, 11%, 24%); + --cowboy: hsl(4, 11%, 24%); + --rattlesnake: hsl(11, 14%, 24%); + --dark-ginger: hsl(14, 27%, 22%); + --echo: hsl(9, 11%, 25%); + --hinau: hsl(9, 32%, 21%); + --toast-lmu-25: hsl(9, 74%, 16%); + --van-cleef: hsl(11, 72%, 17%); + --baked-earth: hsl(15, 29%, 22%); + --pms439: hsl(5, 18%, 24%); + --warmed-brown: hsl(10, 26%, 23%); + --bean: hsl(10, 20%, 24%); + --beer-srm-34: hsl(1, 87%, 15%); + --rialto: hsl(1, 38%, 22%); + --rock: hsl(12, 20%, 25%); + --espresso: hsl(7, 27%, 24%); + --cherrywood: hsl(6, 26%, 24%); + --beer-srm-33: hsl(3, 82%, 17%); + --pms4695: hsl(11, 49%, 21%); + --pms497: hsl(3, 36%, 23%); + --filmpro-burnt-sienna: hsl(2, 31%, 25%); + --jarrah-tree: hsl(3, 27%, 25%); + --tomahawk: hsl(10, 12%, 29%); + --beer-srm-32: hsl(4, 87%, 17%); + --scoria: hsl(7, 44%, 23%); + --felix: hsl(13, 12%, 29%); + --pepperwood: hsl(11, 37%, 24%); + --dim-grey: hsl(0, 0%, 33%); + --dark-oak: hsl(13, 33%, 25%); + --beer-srm-31: hsl(7, 93%, 17%); + --hukanui: hsl(8, 43%, 24%); + --jarrah-stain: hsl(10, 33%, 26%); + --moccaccino: hsl(5, 34%, 26%); + --deep-scarlet: hsl(7, 100%, 17%); + --deep-vermilion: hsl(15, 100%, 17%); + --reddish-brownish-grey: hsl(0, 3%, 34%); + --congo-brown: hsl(0, 24%, 28%); + --pms438: hsl(4, 19%, 29%); + --dark-grayish-reddish-brown: hsl(0, 15%, 30%); + --red-planet: hsl(6, 57%, 23%); + --triple-lumberjack: hsl(11, 31%, 27%); + --beer-srm-30: hsl(7, 94%, 18%); + --pms1817: hsl(6, 39%, 26%); + --rough-n-tumble: hsl(13, 12%, 32%); + --meranti: hsl(12, 72%, 21%); + --rata: hsl(1, 51%, 24%); + --artefact: hsl(9, 8%, 34%); + --red-sienna: hsl(8, 39%, 27%); + --tipping-point: hsl(7, 45%, 26%); + --quarter-barista: hsl(0, 10%, 35%); + --beer-srm-29: hsl(8, 94%, 20%); + --half-felix: hsl(15, 11%, 35%); + --hairy-heath: hsl(13, 42%, 27%); + --double-lumberjack: hsl(11, 29%, 30%); + --pioneer-red: hsl(5, 52%, 26%); + --komakorau: hsl(11, 41%, 28%); + --cajun: hsl(4, 41%, 28%); + --oiled-cedar: hsl(9, 39%, 29%); + --beer-srm-28: hsl(8, 94%, 21%); + --fahrenheit: hsl(3, 41%, 29%); + --lexington: hsl(9, 31%, 31%); + --hot-n-spicy: hsl(2, 54%, 27%); + --pms483: hsl(12, 53%, 27%); + --dorado: hsl(5, 11%, 38%); + --beer-srm-27: hsl(11, 95%, 22%); + --sanguine-brown: hsl(1, 33%, 32%); + --dove-grey: hsl(0, 0%, 43%); + --pms175: hsl(14, 54%, 28%); + --kwila: hsl(8, 44%, 30%); + --pms498: hsl(7, 43%, 30%); + --patio-red: hsl(2, 38%, 31%); + --identity: hsl(0, 3%, 42%); + --reddy-brown: hsl(6, 91%, 23%); + --heatwave: hsl(5, 55%, 28%); + --kakaramea: hsl(6, 50%, 29%); + --pueblo: hsl(11, 49%, 29%); + --metallic-copper: hsl(9, 36%, 32%); + --red-oxide: hsl(4, 96%, 22%); + --mocha: hsl(9, 42%, 31%); + --cedar-wood-finish: hsl(14, 100%, 22%); + --beer-srm-26: hsl(14, 100%, 22%); + --lumberjack: hsl(10, 26%, 35%); + --quarter-felix: hsl(8, 7%, 43%); + --desperado: hsl(13, 48%, 31%); + --warm-kwila: hsl(13, 47%, 31%); + --copperhead: hsl(12, 24%, 37%); + --russett: hsl(6, 15%, 40%); + --crown-of-thorns: hsl(8, 40%, 33%); + --boulder: hsl(0, 0%, 48%); + --ricochet: hsl(0, 0%, 52%); + --double-rakaia: hsl(0, 2%, 65%); + --weathered-grey: hsl(0, 3%, 45%); + --beer-srm-25: hsl(14, 98%, 24%); + --lusty: hsl(2, 46%, 32%); + --western-red-cedar: hsl(10, 49%, 32%); + --pms499: hsl(9, 46%, 33%); + --teranova: hsl(11, 48%, 32%); + --pms1810: hsl(2, 61%, 30%); + --pms181: hsl(7, 56%, 31%); + --red-robin: hsl(8, 38%, 35%); + --beer-srm-24: hsl(14, 98%, 25%); + --sunspot: hsl(7, 47%, 34%); + --scorched-clay: hsl(11, 47%, 34%); + --raging-bull: hsl(4, 50%, 33%); + --mustang: hsl(5, 47%, 34%); + --dawnbreaker: hsl(8, 55%, 33%); + --erica: hsl(4, 48%, 34%); + --vixen: hsl(6, 50%, 34%); + --intrigue: hsl(4, 32%, 38%); + --pharlap: hsl(6, 14%, 45%); + --half-lumberjack: hsl(9, 23%, 42%); + --tall-poppy: hsl(1, 44%, 36%); + --nobel: hsl(0, 7%, 64%); + --dusty-rose: hsl(0, 15%, 45%); + --grayish-red: hsl(0, 20%, 57%); + --crossroads: hsl(0, 22%, 37%); + --coral-tree: hsl(0, 26%, 54%); + --pms5005: hsl(0, 28%, 63%); + --pms4985: hsl(0, 29%, 40%); + --copper-rust: hsl(0, 35%, 43%); + --lotus: hsl(0, 38%, 38%); + --reddish-brown: hsl(0, 39%, 25%); + --pms490: hsl(0, 41%, 25%); + --coco: hsl(0, 44%, 28%); + --pms491: hsl(0, 49%, 31%); + --deep-reddish-brown: hsl(0, 100%, 17%); + --ironstone: hsl(10, 38%, 38%); + --hurricane: hsl(5, 5%, 51%); + --crab-apple: hsl(6, 48%, 36%); + --totem-pole: hsl(3, 47%, 36%); + --mule-fawn: hsl(13, 36%, 39%); + --half-buffalo: hsl(14, 10%, 49%); + --eighth-felix: hsl(11, 6%, 51%); + --red-brown: hsl(12, 73%, 32%); + --pms437: hsl(9, 13%, 48%); + --embers: hsl(10, 49%, 37%); + --tandoori: hsl(13, 48%, 37%); + --red-berry: hsl(0, 100%, 28%); + --kubrick: hsl(6, 11%, 50%); + --tabasco: hsl(3, 45%, 38%); + --matrix: hsl(7, 35%, 41%); + --el-salva: hsl(7, 47%, 38%); + --fire: hsl(12, 55%, 36%); + --hemp: hsl(9, 11%, 51%); + --ameile: hsl(2, 34%, 42%); + --dusky-pink: hsl(7, 13%, 51%); + --tom: hsl(9, 8%, 54%); + --countdown: hsl(9, 67%, 34%); + --roller-coaster: hsl(5, 51%, 38%); + --copper-fire: hsl(11, 36%, 42%); + --promise: hsl(9, 20%, 48%); + --quarter-lumberjack: hsl(7, 17%, 50%); + --prairie-sand: hsl(7, 46%, 36%); + --cracker: hsl(5, 58%, 37%); + --tia-maria: hsl(12, 54%, 38%); + --mojo: hsl(7, 43%, 41%); + --au-chico: hsl(3, 24%, 48%); + --afterburner: hsl(3, 45%, 41%); + --fusion: hsl(5, 42%, 42%); + --reddish-grey: hsl(7, 17%, 52%); + --quarter-buffalo: hsl(10, 10%, 55%); + --toast: hsl(14, 23%, 49%); + --dry-creek: hsl(6, 13%, 55%); + --hot-august: hsl(7, 45%, 42%); + --cognac: hsl(6, 43%, 42%); + --wild-west: hsl(13, 41%, 43%); + --pms484: hsl(9, 69%, 36%); + --mexican-red: hsl(0, 44%, 42%); + --warhol: hsl(2, 24%, 49%); + --rock-spray: hsl(12, 55%, 40%); + --krakatoa: hsl(14, 45%, 42%); + --pms704: hsl(0, 60%, 39%); + --milano-red: hsl(1, 52%, 41%); + --brownish-red: hsl(9, 64%, 38%); + --burnt-red: hsl(12, 94%, 32%); + --triple-rakaia: hsl(13, 5%, 61%); + --roof-terracotta: hsl(3, 41%, 45%); + --kachow: hsl(3, 51%, 42%); + --hazy-lavender: hsl(13, 9%, 61%); + --pulse: hsl(2, 74%, 37%); + --kamikaze: hsl(8, 55%, 42%); + --triple-milestone: hsl(12, 10%, 61%); + --asteroid: hsl(13, 10%, 61%); + --cincinnati: hsl(1, 45%, 45%); + --bonfire: hsl(4, 68%, 39%); + --crail: hsl(9, 39%, 47%); + --quickstep: hsl(2, 29%, 51%); + --strong-red: hsl(0, 100%, 33%); + --strong-scarlet: hsl(8, 100%, 33%); + --strong-vermilion: hsl(15, 100%, 33%); + --moderate-red: hsl(0, 39%, 47%); + --moderate-scarlet: hsl(7, 39%, 47%); + --moderate-vermilion: hsl(15, 39%, 47%); + --apple-blossom: hsl(6, 40%, 47%); + --rust-red: hsl(13, 95%, 34%); + --alter-ego: hsl(2, 41%, 48%); + --moulin-rouge: hsl(4, 47%, 46%); + --martini: hsl(7, 10%, 65%); + --pms1805: hsl(0, 64%, 42%); + --brown-rust: hsl(14, 48%, 46%); + --del-rio: hsl(11, 15%, 64%); + --forbidden: hsl(3, 47%, 47%); + --pinkish-brown: hsl(13, 34%, 54%); + --thatch: hsl(9, 18%, 63%); + --double-milestone: hsl(11, 12%, 65%); + --foxtrot: hsl(1, 33%, 57%); + --brandy-rose: hsl(11, 29%, 60%); + --mexican-wave: hsl(11, 57%, 45%); + --bonanza: hsl(12, 34%, 57%); + --flair: hsl(5, 47%, 49%); + --dull-red: hsl(0, 50%, 49%); + --pms436: hsl(14, 18%, 68%); + --quicksand: hsl(11, 26%, 65%); + --blaze: hsl(12, 69%, 44%); + --oh-behave: hsl(9, 50%, 50%); + --flame-pea: hsl(10, 48%, 51%); + --thunderbird: hsl(7, 78%, 42%); + --sunset: hsl(4, 48%, 52%); + --contessa: hsl(5, 42%, 58%); + --pms180: hsl(6, 66%, 46%); + --balloon: hsl(10, 56%, 48%); + --clementine: hsl(9, 53%, 49%); + --brownish-pink: hsl(4, 37%, 62%); + --oriental-pink: hsl(6, 32%, 65%); + --bring-it-on: hsl(3, 54%, 50%); + --reddish: hsl(1, 53%, 51%); + --fuzzy-wuzzy-brown: hsl(1, 48%, 55%); + --orang-atan: hsl(12, 59%, 49%); + --cherish: hsl(4, 20%, 72%); + --satin-orange: hsl(12, 72%, 45%); + --sunglo: hsl(6, 50%, 56%); + --pinkish-grey: hsl(6, 22%, 72%); + --catalyst: hsl(8, 55%, 52%); + --pms694: hsl(0, 36%, 67%); + --cold-turkey: hsl(8, 18%, 75%); + --adore: hsl(2, 49%, 60%); + --daredevil: hsl(5, 58%, 51%); + --pms485-2x: hsl(4, 100%, 40%); + --half-rakaia: hsl(15, 4%, 79%); + --fireball: hsl(14, 59%, 51%); + --cheeky: hsl(3, 53%, 57%); + --eunry: hsl(11, 33%, 71%); + --urbane: hsl(12, 12%, 83%); + --soulmate: hsl(12, 23%, 75%); + --alto: hsl(7, 7%, 79%); + --very-light-grey: hsl(0, 0%, 80%); + --jive: hsl(3, 55%, 56%); + --japonica: hsl(13, 54%, 58%); + --joie-de-vivre: hsl(13, 58%, 55%); + --blanched-pink: hsl(13, 22%, 76%); + --half-milestone: hsl(11, 15%, 79%); + --pms185-2x: hsl(6, 100%, 41%); + --clam-shell: hsl(15, 31%, 74%); + --birthday-suit: hsl(15, 41%, 71%); + --oyster-pink: hsl(8, 30%, 76%); + --filmpro-orange: hsl(8, 64%, 53%); + --valencia: hsl(4, 61%, 57%); + --mercury: hsl(15, 5%, 83%); + --my-pink: hsl(8, 51%, 67%); + --pms1788-2x: hsl(9, 100%, 42%); + --pms1795: hsl(0, 69%, 50%); + --pms5015: hsl(6, 38%, 75%); + --pms485: hsl(7, 95%, 43%); + --roman: hsl(3, 62%, 60%); + --pursuit: hsl(3, 76%, 48%); + --pale-red: hsl(3, 65%, 58%); + --petite-orchid: hsl(6, 50%, 71%); + --sea-pink: hsl(2, 56%, 68%); + --pms693: hsl(3, 43%, 75%); + --sweet-as: hsl(6, 35%, 78%); + --pms5315: hsl(0, 10%, 84%); + --brown-madder: hsl(0, 71%, 51%); + --pms5235: hsl(5, 27%, 82%); + --paper-doll: hsl(2, 44%, 78%); + --cavern-pink: hsl(9, 43%, 79%); + --flamingo: hsl(8, 71%, 60%); + --pms5025: hsl(7, 43%, 80%); + --pms179: hsl(7, 76%, 52%); + --cadmium-red-deep: hsl(3, 89%, 47%); + --shilo: hsl(11, 56%, 78%); + --ebb: hsl(13, 26%, 87%); + --brilliant-scarlet: hsl(8, 76%, 61%); + --geraldine: hsl(3, 70%, 68%); + --light-scarlet: hsl(7, 66%, 73%); + --tonys-pink: hsl(14, 66%, 72%); + --light-vermilion: hsl(15, 66%, 73%); + --pale-grayish-pink: hsl(0, 49%, 81%); + --vivid-scarlet: hsl(8, 100%, 45%); + --brilliant-red: hsl(0, 76%, 61%); + --pms692: hsl(7, 50%, 82%); + --pms5175: hsl(13, 33%, 86%); + --sakura: hsl(13, 59%, 79%); + --bambina: hsl(5, 33%, 87%); + --sebedee: hsl(14, 80%, 57%); + --sweet-spot: hsl(0, 55%, 82%); + --pms501: hsl(0, 57%, 81%); + --beauty-bush: hsl(6, 58%, 81%); + --tomato-red: hsl(11, 99%, 46%); + --pms486: hsl(15, 74%, 72%); + --pms5035: hsl(12, 52%, 85%); + --pms677: hsl(0, 39%, 88%); + --trubridge-red: hsl(3, 84%, 57%); + --sweet-pink: hsl(2, 74%, 74%); + --soft-peach: hsl(4, 32%, 90%); + --pms691: hsl(13, 54%, 86%); + --whisper: hsl(0, 22%, 92%); + --glorious: hsl(3, 81%, 69%); + --pms502: hsl(3, 64%, 86%); + --pomegranate: hsl(10, 90%, 55%); + --pms196: hsl(0, 66%, 87%); + --pms503: hsl(7, 65%, 88%); + --vermillion: hsl(10, 91%, 50%); + --orangish-red: hsl(12, 96%, 49%); + --coral-candy: hsl(10, 69%, 87%); + --pink-terrace: hsl(10, 68%, 88%); + --remy: hsl(9, 61%, 91%); + --pms699: hsl(0, 78%, 86%); + --pms496: hsl(4, 75%, 87%); + --pms698: hsl(7, 73%, 88%); + --sundown: hsl(5, 85%, 82%); + --tutu: hsl(3, 60%, 93%); + --reddish-orange: hsl(12, 94%, 54%); + --pms177: hsl(1, 91%, 74%); + --pms170: hsl(10, 92%, 71%); + --pms1635: hsl(14, 92%, 70%); + --pms1625: hsl(14, 90%, 76%); + --pms176: hsl(2, 86%, 83%); + --pms169: hsl(12, 87%, 82%); + --pms705: hsl(12, 74%, 91%); + --pms805-2x: hsl(4, 94%, 57%); + --pms805: hsl(3, 93%, 65%); + --pms178: hsl(2, 93%, 66%); + --pms171: hsl(12, 94%, 60%); + --orangey-red: hsl(8, 96%, 56%); + --rose-bud: hsl(10, 92%, 81%); + --cinderella: hsl(14, 85%, 89%); + --pms706: hsl(3, 90%, 88%); + --cosmos: hsl(8, 88%, 90%); + --marshmallow: hsl(13, 88%, 91%); + --grapefruit: hsl(1, 98%, 66%); + --light-brilliant-red: hsl(0, 99%, 59%); + --orangered: hsl(13, 99%, 53%); + --orange-pink: hsl(10, 100%, 66%); + --pms811: hsl(14, 100%, 64%); + --pinkish-orange: hsl(13, 100%, 65%); + --light-brilliant-scarlet: hsl(7, 100%, 70%); + --light-brilliant-vermilion: hsl(15, 100%, 70%); + --mona-lisa: hsl(8, 100%, 77%); + --peachy-pink: hsl(8, 100%, 77%); + --very-light-scarlet: hsl(7, 100%, 81%); + --pale-salmon: hsl(14, 100%, 80%); + --very-light-vermilion: hsl(15, 100%, 81%); + --your-pink: hsl(3, 100%, 88%); + --pale-scarlet: hsl(7, 100%, 88%); + --pale-vermilion: hsl(15, 100%, 88%); + --pippin: hsl(4, 100%, 94%); + --very-pale-pink: hsl(0, 100%, 94%); + --very-pale-vermilion: hsl(14, 100%, 94%); + --very-light-pink: hsl(9, 100%, 97%); + --pinkish-white: hsl(0, 100%, 98%); + --luminous-vivid-scarlet: hsl(8, 100%, 50%); + --greenish-umber: hsl(12, 100%, 53%); + --big-bang: hsl(6, 100%, 62%); + --flesh-ochre: hsl(15, 100%, 56%); + --alloy-orange: hsl(27, 85%, 42%); + --almond: hsl(30, 52%, 87%); + --amber: hsl(45, 100%, 50%); + --amber-sae-ece: hsl(30, 100%, 50%); + --antique-brass: hsl(22, 47%, 63%); + --antique-white: hsl(34, 78%, 91%); + --apricot: hsl(24, 90%, 84%); + --atomic-tangerine: hsl(20, 100%, 70%); + --aztec-gold: hsl(38, 48%, 55%); + --banana-mania: hsl(43, 87%, 85%); + --beaver: hsl(22, 20%, 53%); + --big-foot-feet: hsl(22, 76%, 63%); + --bisque: hsl(33, 100%, 88%); + --bistre: hsl(24, 33%, 18%); + --bistre-brown: hsl(43, 73%, 34%); + --blanched-almond: hsl(36, 100%, 90%); + --bone: hsl(39, 32%, 84%); + --bright-yellow-crayola: hsl(37, 100%, 56%); + --bronze: hsl(30, 61%, 50%); + --brown-nose: hsl(28, 51%, 28%); + --brown-sugar: hsl(20, 39%, 49%); + --burlywood: hsl(34, 57%, 70%); + --burnt-orange: hsl(25, 100%, 40%); + --cadmium-orange: hsl(28, 84%, 55%); + --cafe-au-lait: hsl(26, 30%, 50%); + --cafe-noir: hsl(30, 39%, 21%); + --brown-yellow: hsl(30, 50%, 60%); + --brown-traditional: hsl(30, 100%, 29%); + --camel: hsl(33, 41%, 59%); + --carrot-orange: hsl(33, 85%, 53%); + --chamoisee: hsl(26, 28%, 49%); + --champagne: hsl(37, 72%, 89%); + --champagne-pink: hsl(25, 55%, 88%); + --chocolate-traditional: hsl(31, 100%, 24%); + --chocolate-web: hsl(25, 75%, 47%); + --chrome-yellow: hsl(39, 100%, 50%); + --coconut: hsl(19, 42%, 42%); + --coffee: hsl(25, 34%, 33%); + --copper: hsl(29, 57%, 46%); + --copper-crayola: hsl(18, 61%, 63%); + --coral: hsl(16, 100%, 66%); + --cosmic-latte: hsl(43, 100%, 95%); + --coyote-brown: hsl(32, 37%, 37%); + --dark-brown: hsl(30, 51%, 26%); + --dark-brown-tangelo: hsl(24, 27%, 42%); + --dark-goldenrod: hsl(43, 89%, 38%); + --dark-lava: hsl(27, 18%, 24%); + --dark-orange: hsl(33, 100%, 50%); + --dark-salmon: hsl(15, 72%, 70%); + --crowshead: hsl(45, 4%, 19%); + --touch-wood: hsl(45, 12%, 20%); + --dark-tan: hsl(45, 28%, 44%); + --dark-tangerine: hsl(38, 100%, 54%); + --dark-vanilla: hsl(32, 31%, 74%); + --deep-carrot-orange: hsl(19, 81%, 54%); + --deep-champagne: hsl(35, 89%, 81%); + --deep-peach: hsl(26, 100%, 82%); + --deer: hsl(28, 41%, 54%); + --desert-sand: hsl(25, 63%, 81%); + --dirt: hsl(29, 30%, 47%); + --donkey-brown: hsl(35, 44%, 28%); + --dutch-white: hsl(42, 62%, 84%); + --earth-yellow: hsl(34, 68%, 63%); + --fawn: hsl(30, 69%, 67%); + --feldspar: hsl(28, 95%, 84%); + --field-drab: hsl(42, 57%, 27%); + --flame: hsl(17, 77%, 51%); + --floral-white: hsl(40, 100%, 97%); + --grullo: hsl(34, 17%, 59%); + --french-bistre: hsl(34, 27%, 41%); + --fulvous: hsl(35, 100%, 45%); + --gamboge: hsl(39, 88%, 48%); + --gamboge-orange-brown: hsl(40, 100%, 30%); + --giants-orange: hsl(16, 99%, 55%); + --ginger: hsl(34, 100%, 35%); + --gold-fusion: hsl(43, 26%, 41%); + --golden-brown: hsl(36, 76%, 34%); + --goldenrod: hsl(43, 74%, 49%); + --grizzly: hsl(34, 70%, 31%); + --harvest-gold: hsl(40, 100%, 43%); + --heat-wave: hsl(29, 100%, 50%); + --indian-yellow: hsl(35, 71%, 62%); + --international-orange-aerospace: hsl(19, 100%, 50%); + --isabelline: hsl(30, 27%, 94%); + --khaki-html-css-khaki: hsl(37, 29%, 67%); + --lemon-curry: hsl(45, 75%, 46%); + --light-brown: hsl(28, 72%, 41%); + --light-french-beige: hsl(38, 40%, 64%); + --light-orange: hsl(30, 97%, 85%); + --light-salmon: hsl(17, 100%, 74%); + --light-taupe: hsl(26, 32%, 56%); + --linen: hsl(30, 67%, 94%); + --liver-dogs: hsl(29, 64%, 44%); + --liver-chestnut: hsl(27, 28%, 47%); + --lumber: hsl(28, 100%, 90%); + --macaroni-and-cheese: hsl(27, 100%, 77%); + --mahogany: hsl(20, 100%, 38%); + --mandarin: hsl(18, 88%, 62%); + --mango-tango: hsl(20, 100%, 63%); + --marigold: hsl(39, 83%, 52%); + --maximum-yellow-red: hsl(40, 87%, 62%); + --meat-brown: hsl(44, 77%, 56%); + --mellow-apricot: hsl(30, 90%, 72%); + --metallic-sunburst: hsl(41, 47%, 42%); + --middle-yellow-red: hsl(30, 76%, 69%); + --navajo-white: hsl(36, 100%, 84%); + --neon-carrot: hsl(31, 100%, 63%); + --ochre: hsl(30, 71%, 47%); + --old-lace: hsl(39, 85%, 95%); + --olive-drab-7: hsl(43, 32%, 18%); + --orange-color-wheel: hsl(30, 100%, 50%); + --orange-crayola: hsl(18, 100%, 61%); + --orange-pantone: hsl(21, 100%, 50%); + --orange-ryb: hsl(36, 98%, 50%); + --orange-web: hsl(39, 100%, 50%); + --orange-peel: hsl(37, 100%, 50%); + --orange-red: hsl(16, 100%, 50%); + --orioles-orange: hsl(15, 97%, 53%); + --pale-brown: hsl(30, 29%, 46%); + --pale-gold: hsl(34, 65%, 72%); + --pale-silver: hsl(21, 11%, 76%); + --pale-taupe: hsl(25, 32%, 62%); + --papaya-whip: hsl(37, 100%, 92%); + --pastel-brown: hsl(28, 22%, 42%); + --pastel-orange: hsl(35, 100%, 64%); + --peach: hsl(39, 100%, 85%); + --peach-puff: hsl(28, 100%, 86%); + --peach-yellow: hsl(39, 89%, 83%); + --pearl: hsl(42, 45%, 85%); + --persian-orange: hsl(26, 63%, 60%); + --persimmon: hsl(22, 100%, 46%); + --peru: hsl(30, 59%, 53%); + --pineapple: hsl(39, 74%, 19%); + --platinum: hsl(40, 5%, 89%); + --princeton-orange: hsl(26, 91%, 55%); + --pullman-brown-ups-brown: hsl(33, 63%, 24%); + --pullman-green: hsl(45, 36%, 17%); + --pumpkin: hsl(24, 100%, 55%); + --rajah: hsl(29, 95%, 68%); + --raw-sienna: hsl(24, 60%, 59%); + --raw-umber: hsl(33, 31%, 39%); + --ruddy-brown: hsl(25, 65%, 45%); + --russet: hsl(26, 65%, 30%); + --rust: hsl(18, 86%, 39%); + --saddle-brown: hsl(25, 76%, 31%); + --safety-orange: hsl(28, 100%, 50%); + --safety-orange-blaze-orange: hsl(24, 100%, 50%); + --sandy-brown: hsl(28, 87%, 67%); + --tuatara: hsl(30, 2%, 21%); + --ironsand: hsl(30, 4%, 22%); + --dark-ebony: hsl(30, 12%, 19%); + --very-brown: hsl(30, 26%, 9%); + --smoky-black: hsl(30, 33%, 5%); + --bokara-grey: hsl(30, 56%, 7%); + --graphite: hsl(30, 68%, 9%); + --sepia: hsl(30, 70%, 26%); + --sandy-tan: hsl(30, 95%, 85%); + --deep-saffron: hsl(30, 100%, 60%); + --peach-orange: hsl(30, 100%, 80%); + --satin-sheen-gold: hsl(43, 59%, 50%); + --seal-brown: hsl(21, 78%, 20%); + --seashell: hsl(25, 100%, 97%); + --selective-yellow: hsl(44, 100%, 50%); + --shadow: hsl(37, 19%, 45%); + --sinopia: hsl(17, 90%, 42%); + --smashed-pumpkin: hsl(16, 100%, 61%); + --spanish-orange: hsl(25, 100%, 45%); + --spicy-mix: hsl(17, 29%, 42%); + --sunglow: hsl(45, 100%, 60%); + --sunray: hsl(36, 71%, 62%); + --tan: hsl(34, 44%, 69%); + --tangelo: hsl(19, 100%, 49%); + --tangerine: hsl(33, 100%, 47%); + --tenne-tawny: hsl(25, 100%, 40%); + --tiger-eye: hsl(30, 73%, 56%); + --timberwolf: hsl(33, 11%, 84%); + --topaz: hsl(35, 100%, 74%); + --tumbleweed: hsl(24, 57%, 70%); + --ucla-gold: hsl(42, 100%, 50%); + --umber: hsl(21, 16%, 33%); + --unbleached-silk: hsl(22, 100%, 90%); + --university-of-california-gold: hsl(40, 65%, 44%); + --urobilin: hsl(44, 76%, 51%); + --university-of-tennessee-orange: hsl(31, 100%, 48%); + --van-dyke-brown: hsl(25, 44%, 28%); + --very-light-tangelo: hsl(25, 100%, 73%); + --very-pale-orange: hsl(30, 100%, 87%); + --vivid-amber: hsl(45, 100%, 40%); + --vivid-gamboge: hsl(36, 100%, 50%); + --vivid-orange: hsl(22, 100%, 50%); + --vivid-orange-peel: hsl(38, 100%, 50%); + --vivid-red-tangelo: hsl(20, 75%, 51%); + --vivid-tangelo: hsl(23, 87%, 55%); + --vivid-vermilion: hsl(19, 79%, 52%); + --wheat: hsl(39, 77%, 83%); + --willpower-orange: hsl(21, 100%, 50%); + --windsor-tan: hsl(30, 98%, 33%); + --yellow-orange: hsl(34, 100%, 63%); + --zinnwaldite-brown: hsl(23, 69%, 10%); + --asphalt: hsl(18, 52%, 5%); + --nero: hsl(18, 100%, 4%); + --acadia: hsl(42, 74%, 6%); + --very-deep-brown: hsl(29, 100%, 6%); + --creole: hsl(25, 76%, 7%); + --karaka: hsl(37, 54%, 8%); + --el-paso: hsl(41, 58%, 7%); + --blackout: hsl(16, 20%, 11%); + --eternity: hsl(38, 40%, 9%); + --kilamanjaro: hsl(18, 89%, 7%); + --black-magic: hsl(33, 72%, 8%); + --blackwood: hsl(22, 77%, 8%); + --cosmonaut: hsl(17, 10%, 14%); + --sooty: hsl(16, 23%, 13%); + --double-diesel: hsl(16, 16%, 14%); + --zeus: hsl(38, 24%, 13%); + --ivory-black: hsl(23, 11%, 15%); + --mikado: hsl(43, 48%, 12%); + --ash-brown: hsl(29, 80%, 10%); + --wood-bark: hsl(20, 19%, 16%); + --shadow-match: hsl(36, 5%, 18%); + --banjul: hsl(43, 7%, 19%); + --monkey: hsl(28, 14%, 18%); + --clinker: hsl(26, 72%, 13%); + --brown-tumbleweed: hsl(40, 59%, 14%); + --birch: hsl(41, 25%, 17%); + --dune: hsl(24, 5%, 21%); + --sambuca: hsl(23, 57%, 15%); + --filmpro-burnt-umber: hsl(17, 14%, 20%); + --bushtrack: hsl(26, 16%, 20%); + --triple-dune: hsl(43, 6%, 21%); + --bootleg: hsl(16, 38%, 17%); + --cola: hsl(29, 26%, 19%); + --pms412: hsl(23, 21%, 20%); + --deep-oak: hsl(21, 16%, 21%); + --blast-grey: hsl(40, 3%, 23%); + --english-walnut: hsl(18, 28%, 19%); + --treehouse: hsl(18, 30%, 18%); + --bark: hsl(19, 22%, 20%); + --filmpro-raw-umber: hsl(36, 14%, 22%); + --brown-pod: hsl(22, 97%, 13%); + --cork: hsl(21, 38%, 18%); + --bivouac-green: hsl(29, 27%, 20%); + --eighth-mondo: hsl(35, 9%, 53%); + --settlement: hsl(35, 10%, 59%); + --quarter-pravda: hsl(35, 13%, 66%); + --triple-mondo: hsl(35, 21%, 21%); + --masala: hsl(23, 7%, 24%); + --chocolate-brown: hsl(23, 100%, 13%); + --ironbark: hsl(18, 60%, 16%); + --dark-rum: hsl(20, 60%, 16%); + --nala: hsl(17, 24%, 21%); + --jacko-bean: hsl(34, 24%, 21%); + --longbush: hsl(45, 31%, 19%); + --merlin: hsl(30, 8%, 24%); + --triple-masala: hsl(42, 8%, 24%); + --lignite: hsl(26, 23%, 21%); + --slugger: hsl(23, 21%, 21%); + --limed-gum: hsl(44, 33%, 19%); + --iroko: hsl(29, 35%, 19%); + --rangitoto-rock: hsl(23, 16%, 23%); + --kina-brown: hsl(27, 9%, 24%); + --armadillo: hsl(35, 10%, 24%); + --half-ironsand: hsl(34, 6%, 25%); + --morocco-brown: hsl(26, 100%, 13%); + --mission-brown: hsl(17, 26%, 21%); + --tobago: hsl(23, 20%, 22%); + --double-felix: hsl(16, 16%, 23%); + --woodburn: hsl(27, 26%, 22%); + --tiri: hsl(23, 6%, 26%); + --pms4625: hsl(20, 61%, 17%); + --suburban: hsl(43, 24%, 23%); + --brown-derby: hsl(20, 55%, 18%); + --metallic-bronze: hsl(37, 46%, 20%); + --bracken: hsl(33, 90%, 15%); + --deep-bronze: hsl(38, 90%, 15%); + --mondo: hsl(28, 21%, 24%); + --double-mondo: hsl(35, 15%, 25%); + --rimutaka: hsl(38, 36%, 22%); + --space-shuttle: hsl(30, 12%, 26%); + --relic: hsl(40, 6%, 28%); + --pms1545: hsl(25, 67%, 18%); + --saddle: hsl(18, 36%, 22%); + --timberland: hsl(16, 29%, 23%); + --milk-chocolate: hsl(19, 30%, 23%); + --deep-space: hsl(34, 5%, 28%); + --indian-tan: hsl(23, 97%, 15%); + --punga: hsl(43, 59%, 19%); + --nest-egg: hsl(35, 14%, 26%); + --teak-stain: hsl(19, 31%, 23%); + --paco: hsl(23, 18%, 26%); + --double-oilskin: hsl(30, 16%, 27%); + --winchester: hsl(34, 5%, 30%); + --touchstone: hsl(45, 8%, 30%); + --brown-bramble: hsl(24, 47%, 22%); + --rambler: hsl(27, 15%, 28%); + --judge-grey: hsl(29, 24%, 26%); + --pms449: hsl(43, 38%, 24%); + --cioccolato: hsl(23, 75%, 19%); + --kakadu: hsl(36, 42%, 24%); + --electric: hsl(40, 4%, 32%); + --wireless: hsl(36, 3%, 32%); + --rocky-road: hsl(25, 20%, 28%); + --tabac: hsl(36, 13%, 31%); + --deep-tangelo: hsl(22, 100%, 17%); + --dark-vermilion: hsl(16, 39%, 25%); + --deep-gamboge: hsl(38, 100%, 17%); + --dark-tangelo: hsl(23, 39%, 25%); + --pms476: hsl(23, 35%, 26%); + --brown: hsl(30, 39%, 25%); + --millbrook: hsl(27, 27%, 27%); + --dark-gamboge: hsl(37, 39%, 25%); + --dark-grayish-vermilion: hsl(16, 15%, 30%); + --dark-grayish-brown: hsl(31, 15%, 30%); + --soho: hsl(23, 22%, 29%); + --groundbreaker: hsl(35, 17%, 30%); + --alcatraz: hsl(20, 9%, 32%); + --torque: hsl(24, 3%, 34%); + --jambalaya: hsl(24, 65%, 22%); + --carnaby-tan: hsl(24, 43%, 25%); + --pms462: hsl(39, 44%, 25%); + --baker: hsl(24, 60%, 23%); + --tinpan-alley: hsl(40, 2%, 35%); + --smokey-ash: hsl(38, 6%, 34%); + --kabul: hsl(19, 21%, 31%); + --dark-rimu: hsl(24, 43%, 26%); + --nutmeg: hsl(25, 36%, 27%); + --trailblazer: hsl(40, 42%, 26%); + --pms732: hsl(29, 81%, 21%); + --pms469: hsl(26, 70%, 22%); + --mud-brown: hsl(41, 73%, 22%); + --horses-neck: hsl(42, 67%, 23%); + --pms4485: hsl(45, 70%, 22%); + --triple-arrowtown: hsl(39, 15%, 33%); + --triple-stonewall: hsl(44, 15%, 33%); + --quincy: hsl(20, 37%, 28%); + --irish-coffee: hsl(25, 39%, 28%); + --half-mondo: hsl(34, 12%, 34%); + --pms477: hsl(18, 45%, 27%); + --pms161: hsl(30, 71%, 23%); + --drumbeat: hsl(23, 36%, 29%); + --double-buffalo: hsl(16, 18%, 33%); + --sofisticata: hsl(16, 41%, 22%); + --talisman: hsl(37, 12%, 35%); + --dallas: hsl(31, 39%, 29%); + --triple-stonehenge: hsl(30, 11%, 36%); + --pms411: hsl(30, 15%, 35%); + --dragon: hsl(42, 15%, 35%); + --karens-pewter: hsl(41, 9%, 37%); + --wombat: hsl(33, 20%, 34%); + --triple-pravda: hsl(36, 15%, 35%); + --half-masala: hsl(38, 6%, 38%); + --chicane: hsl(40, 1%, 40%); + --toast-lmu-30: hsl(18, 81%, 23%); + --nutmeg-wood-finish: hsl(31, 100%, 20%); + --catapult: hsl(23, 22%, 34%); + --spark: hsl(27, 24%, 33%); + --makara: hsl(36, 14%, 36%); + --fudge: hsl(19, 43%, 29%); + --spice: hsl(22, 39%, 30%); + --cafe-royale: hsl(30, 45%, 29%); + --soya-bean: hsl(36, 13%, 37%); + --semi-sweet-chocolate: hsl(24, 48%, 28%); + --pms1405: hsl(35, 69%, 25%); + --shingle-fawn: hsl(30, 37%, 31%); + --quarter-lignite: hsl(22, 13%, 37%); + --pms405: hsl(32, 15%, 36%); + --domino: hsl(28, 17%, 36%); + --double-stonewall: hsl(42, 16%, 36%); + --pms168: hsl(20, 73%, 25%); + --new-amber: hsl(19, 50%, 28%); + --tobacco-brown: hsl(30, 24%, 35%); + --pine-cone: hsl(24, 13%, 38%); + --brownie-points: hsl(15, 37%, 32%); + --pickled-bean: hsl(28, 49%, 29%); + --flint: hsl(39, 7%, 41%); + --double-stonehenge: hsl(34, 10%, 40%); + --gauntlet: hsl(45, 4%, 43%); + --half-oilskin: hsl(26, 12%, 40%); + --beaten-track: hsl(36, 14%, 39%); + --double-schooner: hsl(26, 8%, 42%); + --pms731: hsl(31, 84%, 24%); + --old-copper: hsl(24, 42%, 32%); + --triple-nullarbor: hsl(31, 27%, 35%); + --pms147: hsl(44, 50%, 30%); + --bandit: hsl(33, 18%, 38%); + --deep-ochre: hsl(24, 63%, 28%); + --cape-palliser: hsl(21, 43%, 32%); + --peru-tan: hsl(21, 58%, 29%); + --dakota: hsl(15, 15%, 39%); + --echidna: hsl(23, 17%, 39%); + --double-friar-grey: hsl(41, 9%, 42%); + --pms725: hsl(28, 97%, 23%); + --bull-shot: hsl(20, 46%, 31%); + --pms463: hsl(35, 51%, 30%); + --double-pravda: hsl(37, 12%, 41%); + --aluminium: hsl(34, 3%, 45%); + --toast-lmu-35: hsl(23, 75%, 26%); + --matai: hsl(26, 46%, 32%); + --buffalo: hsl(15, 15%, 40%); + --equilibrium: hsl(41, 13%, 41%); + --pablo: hsl(38, 10%, 42%); + --cigar: hsl(24, 64%, 28%); + --copper-canyon: hsl(18, 46%, 32%); + --sandstone: hsl(34, 12%, 42%); + --detroit: hsl(45, 2%, 46%); + --pms417: hsl(45, 9%, 43%); + --peanut: hsl(15, 69%, 28%); + --cumin: hsl(17, 43%, 33%); + --momentum: hsl(27, 46%, 32%); + --oak: hsl(29, 45%, 32%); + --coffee-break: hsl(24, 13%, 42%); + --riverstone: hsl(30, 8%, 44%); + --walnut: hsl(25, 45%, 33%); + --boomerang: hsl(23, 41%, 34%); + --palm-sugar: hsl(27, 37%, 35%); + --roman-coffee: hsl(23, 23%, 39%); + --double-otter: hsl(21, 19%, 40%); + --triple-colins-wicket: hsl(37, 30%, 37%); + --greyish-brown: hsl(38, 21%, 39%); + --lichen: hsl(44, 18%, 41%); + --pms478: hsl(17, 51%, 32%); + --poop-brown: hsl(44, 98%, 24%); + --pms140: hsl(42, 76%, 27%); + --tapa: hsl(34, 3%, 47%); + --cinnamon: hsl(22, 48%, 33%); + --shit-brown: hsl(42, 94%, 25%); + --pms410: hsl(24, 11%, 44%); + --concord: hsl(30, 1%, 48%); + --pms4705: hsl(19, 34%, 36%); + --fiddlesticks: hsl(44, 62%, 30%); + --double-nullarbor: hsl(32, 25%, 39%); + --half-talisman: hsl(37, 10%, 45%); + --stowaway: hsl(32, 37%, 36%); + --blast-yellow: hsl(27, 33%, 37%); + --dark-taupe: hsl(32, 24%, 40%); + --timbuktu: hsl(41, 31%, 38%); + --grey-brown: hsl(40, 21%, 41%); + --medium-brown: hsl(35, 75%, 28%); + --poop: hsl(44, 100%, 25%); + --shit: hsl(45, 100%, 25%); + --wrangler: hsl(21, 17%, 43%); + --triple-napa: hsl(35, 14%, 44%); + --aquashield-stonewall: hsl(41, 14%, 44%); + --friar-grey: hsl(43, 3%, 49%); + --korma: hsl(24, 49%, 34%); + --root-beer: hsl(21, 46%, 35%); + --brazil: hsl(34, 53%, 33%); + --sand-dune: hsl(21, 13%, 45%); + --double-colins-wicket: hsl(39, 26%, 40%); + --pms404: hsl(32, 12%, 45%); + --quarter-oilskin: hsl(27, 8%, 47%); + --quarter-mondo: hsl(38, 12%, 46%); + --arrowtown: hsl(42, 12%, 46%); + --stonehenge: hsl(32, 7%, 48%); + --pms424: hsl(44, 4%, 49%); + --dirt-brown: hsl(36, 39%, 37%); + --beer-srm-23: hsl(17, 98%, 26%); + --axis: hsl(29, 22%, 43%); + --portland: hsl(41, 8%, 48%); + --pms1685: hsl(19, 77%, 29%); + --pms1615: hsl(25, 80%, 29%); + --potters-clay: hsl(25, 35%, 38%); + --cement: hsl(33, 20%, 43%); + --charisma: hsl(22, 56%, 34%); + --dark-wood: hsl(25, 34%, 39%); + --brownish-grey: hsl(37, 17%, 45%); + --triple-perfect-taupe: hsl(29, 9%, 48%); + --triple-grey-olive: hsl(44, 18%, 45%); + --waiwherowhero: hsl(19, 51%, 35%); + --paarl: hsl(16, 43%, 37%); + --afghan-tan: hsl(37, 86%, 28%); + --dull-brown: hsl(35, 29%, 41%); + --americano: hsl(17, 10%, 48%); + --brown-ochre: hsl(20, 63%, 33%); + --magma: hsl(22, 41%, 38%); + --cocoa: hsl(25, 34%, 39%); + --pms464: hsl(35, 54%, 34%); + --lone-ranger: hsl(19, 26%, 42%); + --pravda: hsl(39, 9%, 49%); + --natural: hsl(28, 47%, 36%); + --poo-brown: hsl(42, 99%, 27%); + --taupe-grey: hsl(42, 7%, 50%); + --triumph: hsl(29, 41%, 38%); + --authentic: hsl(31, 35%, 40%); + --lodestar: hsl(34, 25%, 43%); + --double-napa: hsl(39, 13%, 48%); + --corn-harvest: hsl(45, 85%, 29%); + --ignition: hsl(31, 21%, 45%); + --half-sandstone: hsl(31, 8%, 50%); + --schooner: hsl(28, 5%, 52%); + --natural-grey: hsl(33, 5%, 52%); + --half-gauntlet: hsl(40, 1%, 54%); + --rust-brown: hsl(20, 96%, 28%); + --sienna: hsl(20, 57%, 35%); + --toast-lmu-40: hsl(28, 74%, 31%); + --orange: hsl(39, 100%, 27%); + --limed-oak: hsl(32, 25%, 44%); + --triple-malta: hsl(29, 18%, 47%); + --piston: hsl(45, 12%, 49%); + --beer-srm-22: hsl(19, 97%, 28%); + --pms1535: hsl(29, 100%, 27%); + --legend: hsl(20, 41%, 39%); + --pms4635: hsl(26, 47%, 37%); + --mckenzie: hsl(31, 43%, 38%); + --stonewashed: hsl(31, 11%, 50%); + --rusty-nail: hsl(32, 52%, 36%); + --incognito: hsl(26, 13%, 49%); + --milky-way: hsl(36, 15%, 48%); + --quarter-talisman: hsl(38, 8%, 52%); + --pms724: hsl(30, 93%, 29%); + --rope: hsl(25, 65%, 34%); + --terracotta-hit: hsl(17, 44%, 39%); + --driftwood: hsl(33, 33%, 42%); + --bullwhip: hsl(36, 38%, 41%); + --otter: hsl(21, 12%, 50%); + --squirrel: hsl(30, 14%, 49%); + --ironhide: hsl(34, 10%, 51%); + --radiance: hsl(16, 36%, 41%); + --leather: hsl(22, 26%, 45%); + --triple-rickshaw: hsl(28, 24%, 46%); + --almond-frost: hsl(19, 12%, 50%); + --nullarbor: hsl(33, 18%, 48%); + --gargoyle: hsl(32, 16%, 49%); + --cheers: hsl(37, 53%, 37%); + --alloy: hsl(41, 21%, 47%); + --beer-srm-21: hsl(19, 100%, 28%); + --gold-dust: hsl(38, 34%, 43%); + --half-taupe-grey: hsl(43, 7%, 59%); + --fortune: hsl(43, 28%, 45%); + --stonewall: hsl(35, 12%, 51%); + --eighth-oilskin: hsl(30, 7%, 54%); + --brown-red: hsl(16, 93%, 30%); + --burnished-orange: hsl(18, 43%, 40%); + --double-malta: hsl(31, 15%, 50%); + --twister: hsl(44, 27%, 45%); + --half-stonewall: hsl(45, 10%, 53%); + --pms174: hsl(16, 79%, 32%); + --jetsam-brown: hsl(31, 13%, 52%); + --double-grey-olive: hsl(45, 16%, 50%); + --heathered-grey: hsl(38, 9%, 54%); + --bullion: hsl(30, 41%, 41%); + --outback: hsl(32, 16%, 50%); + --colins-wicket: hsl(40, 23%, 47%); + --alert-tan: hsl(19, 54%, 38%); + --chelsea-gem: hsl(21, 52%, 38%); + --half-stonehenge: hsl(34, 6%, 56%); + --pms423: hsl(37, 4%, 57%); + --beer-srm-20: hsl(20, 96%, 30%); + --mars-orange: hsl(23, 76%, 33%); + --warm-brown: hsl(31, 97%, 30%); + --dark-buff: hsl(29, 46%, 41%); + --dusty-road: hsl(29, 19%, 50%); + --gamboge-orange: hsl(40, 100%, 30%); + --mojito: hsl(41, 22%, 49%); + --double-perfect-taupe: hsl(28, 10%, 55%); + --half-arrowtown: hsl(41, 11%, 55%); + --quarter-evolution: hsl(45, 10%, 55%); + --half-friar-grey: hsl(44, 5%, 57%); + --moroccan-spice: hsl(22, 49%, 40%); + --pms4715: hsl(20, 25%, 48%); + --pms409: hsl(27, 12%, 54%); + --pms403: hsl(33, 12%, 54%); + --silver-fern: hsl(32, 6%, 57%); + --hawaiian-tan: hsl(21, 56%, 38%); + --pms154: hsl(34, 94%, 31%); + --pms1395: hsl(37, 91%, 31%); + --triple-bison-hide: hsl(41, 15%, 54%); + --goldmine: hsl(34, 24%, 49%); + --treasure-chest: hsl(43, 18%, 52%); + --cargo: hsl(41, 16%, 53%); + --pms470: hsl(25, 72%, 35%); + --sunshine: hsl(29, 52%, 40%); + --brick: hsl(34, 67%, 37%); + --brownish: hsl(19, 28%, 48%); + --seismic: hsl(25, 21%, 51%); + --triple-joss: hsl(29, 17%, 53%); + --beer-srm-19: hsl(21, 96%, 31%); + --indochine: hsl(23, 50%, 41%); + --toast-lmu-45: hsl(30, 65%, 37%); + --buttered-rum: hsl(36, 55%, 40%); + --double-rickshaw: hsl(28, 22%, 51%); + --sorrell-brown: hsl(30, 24%, 50%); + --secret-road: hsl(33, 24%, 50%); + --half-nullarbor: hsl(32, 18%, 53%); + --heirloom: hsl(27, 14%, 55%); + --quarter-sandstone: hsl(34, 8%, 58%); + --piper: hsl(19, 52%, 41%); + --moscow-mule: hsl(30, 31%, 47%); + --muesli: hsl(34, 31%, 47%); + --half-stonewashed: hsl(31, 10%, 58%); + --pms160: hsl(30, 88%, 33%); + --sepia-skin: hsl(17, 42%, 44%); + --boardwalk: hsl(38, 31%, 47%); + --triple-doeskin: hsl(34, 25%, 50%); + --triple-pavlova: hsl(35, 21%, 52%); + --half-pravda: hsl(41, 10%, 58%); + --pms1605: hsl(26, 81%, 35%); + --quasar: hsl(27, 26%, 50%); + --double-bison-hide: hsl(41, 15%, 57%); + --nomad: hsl(42, 13%, 58%); + --rich-gold: hsl(21, 62%, 39%); + --desert: hsl(21, 46%, 43%); + --red-beech: hsl(23, 46%, 43%); + --earth: hsl(23, 45%, 44%); + --gold-rush: hsl(37, 25%, 51%); + --zorba: hsl(29, 12%, 59%); + --rockbottom: hsl(36, 10%, 60%); + --double-cougar: hsl(36, 11%, 55%); + --beer-srm-18: hsl(23, 96%, 32%); + --pms1255: hsl(45, 78%, 36%); + --sandal: hsl(31, 24%, 53%); + --triple-sandcastle: hsl(32, 23%, 53%); + --half-gargoyle: hsl(32, 17%, 57%); + --imagine: hsl(16, 8%, 61%); + --napa: hsl(41, 13%, 58%); + --triple-truffle: hsl(37, 10%, 60%); + --pms471-2x: hsl(25, 98%, 32%); + --hazard: hsl(20, 59%, 40%); + --triple-drought: hsl(33, 22%, 54%); + --half-colins-wicket: hsl(41, 23%, 54%); + --triple-akaroa: hsl(41, 19%, 56%); + --footloose: hsl(22, 48%, 44%); + --mai-tai: hsl(27, 54%, 42%); + --mongoose: hsl(31, 23%, 54%); + --triple-sisal: hsl(39, 20%, 56%); + --malta: hsl(35, 15%, 58%); + --routeburn: hsl(39, 16%, 58%); + --double-truffle: hsl(40, 9%, 61%); + --double-masala: hsl(40, 10%, 25%); + --craigieburn: hsl(40, 12%, 51%); + --pale-oyster: hsl(40, 14%, 53%); + --double-arrowtown: hsl(40, 15%, 38%); + --pms448: hsl(40, 30%, 25%); + --toasted-green: hsl(40, 31%, 30%); + --kumera: hsl(40, 50%, 31%); + --pms146: hsl(40, 94%, 32%); + --pms1675: hsl(19, 83%, 35%); + --roasted-orange: hsl(30, 40%, 46%); + --bronze-ii: hsl(37, 46%, 45%); + --medium-wood: hsl(25, 27%, 52%); + --sanctuary: hsl(34, 30%, 50%); + --barley-corn: hsl(38, 30%, 50%); + --double-joss: hsl(30, 18%, 58%); + --quarter-stonewall: hsl(43, 12%, 60%); + --heartwood: hsl(25, 56%, 42%); + --hot-toddy: hsl(36, 58%, 41%); + --luxor-gold: hsl(45, 58%, 41%); + --bronco: hsl(35, 18%, 58%); + --vindaloo: hsl(21, 68%, 39%); + --reno-sand: hsl(33, 78%, 37%); + --strong-gamboge: hsl(38, 100%, 33%); + --moderate-tangelo: hsl(22, 39%, 47%); + --double-kalgoorie-sands: hsl(24, 37%, 48%); + --moderate-orange: hsl(30, 39%, 47%); + --strong-amber: hsl(45, 100%, 33%); + --moderate-gamboge: hsl(38, 39%, 47%); + --grayish-vermilion: hsl(15, 20%, 57%); + --dark-sand: hsl(41, 31%, 50%); + --grayish-brown: hsl(31, 20%, 57%); + --effervescent: hsl(23, 13%, 61%); + --pms408: hsl(28, 14%, 60%); + --quarter-arrowtown: hsl(43, 11%, 62%); + --strong-tangelo: hsl(23, 100%, 33%); + --orange-roughy: hsl(16, 52%, 43%); + --strong-orange: hsl(30, 100%, 33%); + --vesuvius: hsl(17, 53%, 43%); + --sante-fe: hsl(18, 36%, 49%); + --muddy-waters: hsl(35, 36%, 49%); + --double-pavlova: hsl(40, 23%, 56%); + --viaduct: hsl(27, 9%, 63%); + --half-craigieburn: hsl(42, 13%, 61%); + --pms730: hsl(30, 46%, 46%); + --toast-lmu-50: hsl(32, 47%, 45%); + --rickshaw: hsl(28, 22%, 57%); + --triple-tea: hsl(39, 15%, 61%); + --perfect-taupe: hsl(30, 11%, 62%); + --cougar: hsl(39, 15%, 61%); + --claypot: hsl(16, 36%, 49%); + --tan-brown: hsl(32, 38%, 48%); + --intrepid: hsl(39, 50%, 45%); + --teak: hsl(37, 35%, 50%); + --backcountry: hsl(33, 28%, 55%); + --sandrift: hsl(28, 23%, 57%); + --quarter-stonehenge: hsl(32, 7%, 65%); + --beer-srm-17: hsl(24, 97%, 34%); + --bungy: hsl(28, 48%, 45%); + --zion: hsl(40, 82%, 37%); + --mustard-brown: hsl(44, 95%, 35%); + --toast-lmu-55: hsl(34, 36%, 50%); + --double-doeskin: hsl(34, 27%, 55%); + --dark-beige: hsl(40, 31%, 53%); + --double-drought: hsl(34, 22%, 58%); + --cloudy: hsl(28, 7%, 65%); + --red-stage: hsl(17, 58%, 43%); + --rose-of-sharon: hsl(17, 59%, 43%); + --mandalay: hsl(38, 73%, 39%); + --frizzell: hsl(39, 57%, 43%); + --alpine: hsl(42, 49%, 45%); + --castlepoint: hsl(39, 29%, 55%); + --pms451: hsl(45, 24%, 58%); + --rhapsody: hsl(19, 48%, 46%); + --turmeric: hsl(43, 46%, 47%); + --ayers-rock: hsl(17, 71%, 40%); + --bourbon: hsl(24, 48%, 46%); + --caramel: hsl(37, 90%, 36%); + --pms139: hsl(40, 94%, 35%); + --pms479: hsl(24, 28%, 56%); + --pms402: hsl(39, 15%, 63%); + --pms422: hsl(35, 7%, 66%); + --mandrake: hsl(45, 15%, 64%); + --beer-srm-16: hsl(27, 100%, 35%); + --oregon: hsl(26, 51%, 46%); + --santa-fe: hsl(17, 38%, 51%); + --double-akaroa: hsl(42, 20%, 62%); + --fiery-orange: hsl(19, 58%, 44%); + --orangey-brown: hsl(32, 98%, 35%); + --high-five: hsl(30, 60%, 44%); + --clay-brown: hsl(27, 49%, 47%); + --pendragon: hsl(27, 48%, 47%); + --pms4645: hsl(25, 35%, 54%); + --dust: hsl(38, 31%, 56%); + --quarter-nullarbor: hsl(33, 21%, 62%); + --sandcastle: hsl(32, 21%, 62%); + --double-sisal: hsl(38, 22%, 61%); + --quarter-gargoyle: hsl(31, 16%, 64%); + --pristine-lavender: hsl(23, 13%, 65%); + --double-tea: hsl(40, 16%, 64%); + --half-mountain-mist: hsl(34, 5%, 70%); + --quarter-stonewashed: hsl(34, 12%, 66%); + --overland: hsl(44, 16%, 64%); + --eighth-stonewall: hsl(45, 11%, 66%); + --orangish-brown: hsl(32, 97%, 35%); + --gold-coast: hsl(32, 36%, 54%); + --classius: hsl(40, 46%, 48%); + --goldie: hsl(41, 33%, 56%); + --paperback: hsl(29, 19%, 63%); + --bedrock: hsl(42, 13%, 66%); + --shelter: hsl(37, 25%, 61%); + --half-napa: hsl(41, 13%, 66%); + --omega: hsl(29, 76%, 40%); + --pms4725: hsl(22, 28%, 60%); + --triple-canterbury-clay: hsl(35, 35%, 55%); + --half-malta: hsl(32, 18%, 65%); + --bison-hide: hsl(44, 18%, 65%); + --pms414: hsl(43, 12%, 67%); + --beer-srm-15: hsl(28, 100%, 35%); + --pms1525: hsl(28, 100%, 35%); + --clay: hsl(15, 41%, 51%); + --roti: hsl(43, 47%, 49%); + --doeskin: hsl(35, 27%, 61%); + --noosa: hsl(34, 53%, 47%); + --jandal: hsl(35, 53%, 47%); + --triple-putty: hsl(36, 43%, 51%); + --papier-mache: hsl(37, 38%, 54%); + --travis: hsl(41, 36%, 56%); + --howlin-wolf: hsl(33, 27%, 61%); + --piha-sand: hsl(38, 31%, 59%); + --quarter-colins-wicket: hsl(40, 25%, 62%); + --triple-concrete: hsl(30, 1%, 71%); + --burnt-siena: hsl(26, 97%, 36%); + --double-canterbury-clay: hsl(39, 34%, 58%); + --drought: hsl(37, 22%, 64%); + --brown-orange: hsl(34, 98%, 37%); + --filmpro-yellow-oxide: hsl(34, 55%, 47%); + --fleetwood: hsl(44, 41%, 53%); + --taupe: hsl(35, 29%, 62%); + --navarone: hsl(37, 27%, 62%); + --joss: hsl(31, 20%, 66%); + --bamboo: hsl(23, 49%, 49%); + --pms723: hsl(30, 59%, 46%); + --pirate-gold: hsl(33, 63%, 45%); + --alamo: hsl(27, 38%, 56%); + --mushroom: hsl(26, 27%, 63%); + --pms207: hsl(26, 17%, 67%); + --pavlova: hsl(42, 27%, 63%); + --fantail: hsl(18, 11%, 70%); + --eighth-arrowtown: hsl(43, 12%, 69%); + --rakaia: hsl(24, 3%, 72%); + --meteor: hsl(29, 58%, 46%); + --biscuit-brown: hsl(26, 38%, 57%); + --hokey-pokey: hsl(40, 56%, 47%); + --toast-lmu-60: hsl(35, 40%, 56%); + --silk: hsl(28, 16%, 68%); + --half-perfect-taupe: hsl(30, 12%, 70%); + --smoke-tree: hsl(19, 56%, 47%); + --pms153: hsl(33, 90%, 39%); + --high-noon: hsl(39, 88%, 39%); + --nugget: hsl(43, 64%, 45%); + --wazzup: hsl(44, 67%, 44%); + --nude-brown: hsl(29, 30%, 62%); + --okey-dokey: hsl(31, 29%, 63%); + --half-cougar: hsl(41, 14%, 69%); + --pms167: hsl(24, 93%, 38%); + --pms471: hsl(24, 72%, 43%); + --adobe: hsl(18, 47%, 51%); + --fiesta: hsl(34, 62%, 46%); + --half-rickshaw: hsl(29, 24%, 66%); + --triple-parchment: hsl(38, 23%, 66%); + --serene: hsl(30, 16%, 69%); + --corkscrew: hsl(43, 15%, 69%); + --eighth-stonehenge: hsl(38, 8%, 72%); + --orange-brown: hsl(32, 100%, 37%); + --evermore: hsl(20, 50%, 50%); + --putty: hsl(42, 29%, 64%); + --milestone: hsl(17, 12%, 71%); + --triple-fossil: hsl(44, 26%, 66%); + --akaroa: hsl(40, 22%, 67%); + --tide: hsl(28, 13%, 71%); + --truffle: hsl(42, 12%, 71%); + --christine: hsl(23, 61%, 46%); + --pizza: hsl(37, 52%, 49%); + --pms1245: hsl(45, 88%, 40%); + --tussock: hsl(36, 48%, 52%); + --uluru: hsl(35, 41%, 58%); + --quarter-craigieburn: hsl(41, 16%, 70%); + --pms421: hsl(41, 11%, 72%); + --pms718: hsl(29, 100%, 37%); + --beer-srm-14: hsl(29, 99%, 38%); + --clockwork-orange: hsl(20, 59%, 47%); + --brandy-punch: hsl(28, 50%, 50%); + --kowhai: hsl(37, 48%, 52%); + --double-putty: hsl(38, 45%, 55%); + --safari: hsl(41, 41%, 58%); + --pms729: hsl(28, 44%, 57%); + --cappuccino: hsl(33, 46%, 55%); + --half-kalgoorie-sands: hsl(26, 38%, 61%); + --quarter-sorrell-brown: hsl(31, 35%, 62%); + --soul: hsl(31, 30%, 65%); + --pms465: hsl(40, 38%, 61%); + --half-doeskin: hsl(37, 27%, 67%); + --antidote: hsl(30, 22%, 69%); + --pms401: hsl(34, 18%, 70%); + --eighth-friar-grey: hsl(37, 9%, 73%); + --brick-orange: hsl(21, 91%, 40%); + --twine: hsl(33, 45%, 56%); + --toast-lmu-65: hsl(40, 29%, 66%); + --eighth-nullarbor: hsl(35, 22%, 69%); + --half-sandcastle: hsl(35, 21%, 70%); + --quarter-grey-olive: hsl(44, 16%, 72%); + --cloud: hsl(39, 12%, 73%); + --cotton-seed: hsl(35, 9%, 74%); + --matchstick: hsl(42, 31%, 66%); + --eighth-pravda: hsl(38, 14%, 73%); + --pale-slate: hsl(23, 6%, 75%); + --dixie-chick: hsl(39, 65%, 47%); + --pms4655: hsl(26, 39%, 62%); + --eighth-colins-wicket: hsl(38, 25%, 69%); + --pms452: hsl(43, 28%, 68%); + --rust-orange: hsl(25, 92%, 40%); + --geebung: hsl(34, 62%, 48%); + --tabby: hsl(35, 28%, 68%); + --sisal: hsl(42, 24%, 70%); + --triple-thorndon-cream: hsl(42, 19%, 72%); + --beer-srm-13: hsl(30, 99%, 39%); + --zest: hsl(24, 55%, 50%); + --pms145: hsl(38, 93%, 40%); + --peach-schnapps: hsl(21, 49%, 56%); + --anzac: hsl(35, 54%, 51%); + --pms131: hsl(44, 90%, 41%); + --laser: hsl(43, 48%, 57%); + --moleskin: hsl(24, 29%, 68%); + --aquashield-canterbury-clay: hsl(39, 37%, 65%); + --quarter-malta: hsl(34, 22%, 71%); + --half-joss: hsl(31, 19%, 72%); + --half-cloudy: hsl(28, 12%, 75%); + --pms413: hsl(45, 15%, 74%); + --pms159: hsl(28, 95%, 40%); + --gold-ochre: hsl(31, 68%, 46%); + --rodeo-dust: hsl(28, 37%, 65%); + --toupe: hsl(38, 40%, 64%); + --beachcomber: hsl(44, 31%, 68%); + --double-parchment: hsl(40, 24%, 71%); + --half-bison-hide: hsl(39, 20%, 73%); + --caraway: hsl(45, 22%, 72%); + --quarter-napa: hsl(43, 14%, 75%); + --double-fossil: hsl(43, 23%, 69%); + --dirty-orange: hsl(35, 94%, 40%); + --triple-white-pointer: hsl(44, 15%, 75%); + --flotsam: hsl(30, 7%, 77%); + --sour-dough: hsl(34, 30%, 70%); + --dover-white: hsl(17, 11%, 76%); + --toast-lmu-70: hsl(37, 16%, 75%); + --ecstasy: hsl(17, 57%, 50%); + --terracotta: hsl(16, 56%, 52%); + --browny-orange: hsl(32, 98%, 40%); + --beer-srm-12: hsl(32, 100%, 40%); + --golden-bell: hsl(30, 58%, 50%); + --desert-yellow: hsl(40, 80%, 44%); + --baroque: hsl(21, 45%, 62%); + --grain-brown: hsl(33, 27%, 71%); + --half-drought: hsl(36, 24%, 73%); + --quarter-cougar: hsl(34, 17%, 75%); + --terracota: hsl(16, 57%, 53%); + --mischief: hsl(16, 56%, 54%); + --red-damask: hsl(17, 55%, 54%); + --brownish-orange: hsl(30, 71%, 47%); + --sand-brown: hsl(39, 51%, 59%); + --quarter-rickshaw: hsl(29, 25%, 73%); + --half-pavlova: hsl(43, 29%, 71%); + --half-akaroa: hsl(42, 22%, 74%); + --pms1385: hsl(36, 98%, 40%); + --cameo: hsl(27, 42%, 66%); + --pms4735: hsl(24, 32%, 70%); + --vanilla: hsl(33, 32%, 70%); + --sugar-loaf: hsl(42, 24%, 74%); + --quarter-perfect-taupe: hsl(28, 14%, 77%); + --dixie: hsl(32, 61%, 50%); + --quarter-kalgoorie-sands: hsl(26, 38%, 68%); + --crusade: hsl(37, 37%, 69%); + --half-truffle: hsl(44, 13%, 77%); + --rusty-orange: hsl(24, 92%, 42%); + --afterglow: hsl(39, 61%, 50%); + --pms406: hsl(29, 20%, 76%); + --triple-blanc: hsl(39, 24%, 75%); + --quarter-joss: hsl(30, 18%, 76%); + --acropolis: hsl(41, 20%, 76%); + --whiteout: hsl(20, 6%, 80%); + --soft-amber: hsl(36, 30%, 73%); + --burning-sand: hsl(18, 54%, 60%); + --parchment: hsl(45, 25%, 75%); + --quarter-cloudy: hsl(28, 12%, 79%); + --quarter-bison-hide: hsl(44, 19%, 77%); + --chilean-fire: hsl(16, 62%, 51%); + --pms722: hsl(28, 58%, 57%); + --fuel-yellow: hsl(35, 63%, 51%); + --beethoven: hsl(24, 52%, 62%); + --cashmere: hsl(28, 38%, 71%); + --pms466: hsl(43, 41%, 69%); + --quarter-doeskin: hsl(33, 30%, 74%); + --triple-wheatfield: hsl(45, 32%, 74%); + --pms400: hsl(36, 23%, 76%); + --pms420: hsl(43, 16%, 78%); + --double-white-pointer: hsl(41, 15%, 79%); + --lighthouse: hsl(39, 13%, 79%); + --pms428: hsl(44, 11%, 80%); + --pms173: hsl(15, 83%, 45%); + --pms1595: hsl(25, 95%, 42%); + --whiskey: hsl(25, 55%, 60%); + --muka: hsl(33, 49%, 66%); + --smooth-operator: hsl(38, 44%, 68%); + --biscotti: hsl(35, 31%, 74%); + --double-spanish-white: hsl(41, 34%, 73%); + --sandspit-brown: hsl(34, 24%, 77%); + --pms717: hsl(31, 100%, 41%); + --beer-srm-11: hsl(33, 100%, 41%); + --hero: hsl(26, 64%, 53%); + --pms728: hsl(30, 50%, 66%); + --apache: hsl(39, 57%, 59%); + --very-light-brown: hsl(38, 48%, 67%); + --pms480: hsl(25, 35%, 73%); + --half-canterbury-clay: hsl(39, 40%, 71%); + --pms435: hsl(17, 24%, 77%); + --alpaca: hsl(32, 32%, 75%); + --swirl: hsl(34, 14%, 80%); + --quarter-silver-sand: hsl(40, 9%, 81%); + --tango: hsl(23, 65%, 51%); + --di-serria: hsl(26, 58%, 60%); + --wafer: hsl(17, 29%, 76%); + --eighth-napa: hsl(37, 17%, 80%); + --half-cloud: hsl(35, 17%, 80%); + --westar: hsl(40, 15%, 80%); + --gold-drop: hsl(22, 66%, 51%); + --bowman: hsl(33, 49%, 68%); + --double-biscotti: hsl(31, 40%, 73%); + --saloon: hsl(38, 42%, 72%); + --manilla: hsl(34, 33%, 75%); + --triple-spanish-white: hsl(40, 38%, 73%); + --half-sisal: hsl(42, 32%, 76%); + --aths-special: hsl(43, 29%, 77%); + --triple-merino: hsl(40, 18%, 80%); + --grenadier: hsl(20, 100%, 42%); + --double-haystack: hsl(36, 48%, 69%); + --nougat: hsl(31, 34%, 75%); + --pms453: hsl(45, 32%, 76%); + --deja-vu: hsl(31, 52%, 67%); + --eighth-kalgoorie-sands: hsl(28, 38%, 75%); + --half-caraway: hsl(41, 26%, 79%); + --quarter-rakaia: hsl(45, 5%, 84%); + --phoenix: hsl(20, 67%, 53%); + --dull-orange: hsl(29, 67%, 54%); + --pms138: hsl(39, 98%, 43%); + --galliano: hsl(44, 72%, 49%); + --pms4665: hsl(28, 46%, 72%); + --half-putty: hsl(41, 50%, 70%); + --pms4745: hsl(27, 37%, 76%); + --pearl-lavender: hsl(27, 26%, 79%); + --double-blanc: hsl(40, 28%, 79%); + --eighth-malta: hsl(38, 17%, 82%); + --quarter-truffle: hsl(37, 14%, 82%); + --triple-sea-fog: hsl(42, 11%, 83%); + --beer-srm-10: hsl(34, 97%, 43%); + --cool-copper: hsl(34, 79%, 47%); + --pinkish-tan: hsl(17, 53%, 68%); + --half-biscotti: hsl(34, 28%, 79%); + --double-wheatfield: hsl(44, 33%, 78%); + --blanc: hsl(38, 24%, 80%); + --quarter-akaroa: hsl(44, 25%, 80%); + --half-flotsam: hsl(30, 10%, 84%); + --buttercup: hsl(36, 71%, 51%); + --equator: hsl(40, 62%, 62%); + --cocoon: hsl(37, 44%, 74%); + --smooth-cream: hsl(42, 46%, 73%); + --quarter-drought: hsl(35, 28%, 80%); + --half-fossil: hsl(39, 26%, 80%); + --half-sandspit-brown: hsl(36, 21%, 82%); + --white-pointer: hsl(43, 16%, 83%); + --party-animal: hsl(32, 68%, 56%); + --swiss-coffee: hsl(21, 19%, 83%); + --quarter-milestone: hsl(19, 18%, 83%); + --tahiti-gold: hsl(24, 72%, 51%); + --fish-n-chips: hsl(40, 67%, 58%); + --essential-cream: hsl(39, 61%, 65%); + --brandy: hsl(32, 54%, 70%); + --just-right: hsl(24, 41%, 77%); + --sand: hsl(37, 47%, 74%); + --raffia: hsl(38, 46%, 75%); + --pompeii: hsl(43, 36%, 79%); + --gallery: hsl(33, 14%, 84%); + --deep-orange: hsl(21, 99%, 43%); + --sorbus: hsl(19, 71%, 54%); + --pms152: hsl(32, 100%, 43%); + --rob-roy: hsl(39, 67%, 60%); + --coyote: hsl(37, 59%, 67%); + --light-beige: hsl(42, 57%, 69%); + --blank-canvas: hsl(36, 45%, 76%); + --pms467: hsl(42, 45%, 76%); + --porcelain: hsl(30, 3%, 86%); + --pms1665: hsl(21, 96%, 44%); + --pms166: hsl(24, 100%, 43%); + --clementine-orange: hsl(17, 69%, 58%); + --dark-peach: hsl(15, 66%, 62%); + --moscato: hsl(33, 55%, 71%); + --manuka-honey: hsl(40, 58%, 69%); + --haystack: hsl(37, 48%, 75%); + --aquashield-spanish-white: hsl(40, 37%, 79%); + --pearl-bush: hsl(28, 27%, 82%); + --quarter-pavlova: hsl(44, 39%, 79%); + --eighth-bison-hide: hsl(38, 22%, 83%); + --flashback: hsl(25, 72%, 56%); + --roxy: hsl(23, 69%, 59%); + --porsche: hsl(30, 67%, 62%); + --pancho: hsl(30, 55%, 72%); + --chalky: hsl(41, 59%, 69%); + --bon-jour: hsl(23, 17%, 85%); + --house-white: hsl(40, 9%, 86%); + --fire-bush: hsl(33, 72%, 57%); + --candlelight: hsl(36, 73%, 55%); + --pms124: hsl(44, 87%, 47%); + --calico: hsl(34, 55%, 73%); + --egg-white: hsl(43, 57%, 72%); + --quarter-putty: hsl(41, 51%, 75%); + --pms481: hsl(28, 38%, 80%); + --pms434: hsl(25, 30%, 83%); + --eighth-joss: hsl(36, 24%, 84%); + --quarter-tea: hsl(38, 21%, 85%); + --albescent-white: hsl(41, 27%, 84%); + --quarter-sandspit-brown: hsl(37, 23%, 85%); + --quarter-caraway: hsl(43, 26%, 84%); + --merino: hsl(39, 22%, 85%); + --quarter-cloud: hsl(37, 18%, 86%); + --jaffa: hsl(20, 73%, 58%); + --tree-poppy: hsl(25, 74%, 56%); + --pms144: hsl(37, 96%, 45%); + --pms130-2x: hsl(38, 100%, 44%); + --manhattan: hsl(29, 63%, 69%); + --pms727: hsl(30, 55%, 75%); + --sandbar: hsl(40, 62%, 70%); + --pms4755: hsl(27, 41%, 81%); + --pms468: hsl(44, 44%, 80%); + --pms454: hsl(43, 38%, 82%); + --quarter-ecru-white: hsl(44, 21%, 86%); + --eighth-tea: hsl(36, 15%, 87%); + --half-concrete: hsl(30, 3%, 88%); + --hyperactive: hsl(19, 76%, 55%); + --mars-yellow: hsl(26, 79%, 50%); + --beer-srm-09: hsl(36, 97%, 45%); + --tulip-tree: hsl(40, 75%, 56%); + --maize: hsl(34, 63%, 70%); + --pencarrow: hsl(39, 64%, 69%); + --eighth-canterbury-clay: hsl(40, 39%, 82%); + --quarter-biscotti: hsl(34, 33%, 84%); + --eighth-drought: hsl(37, 27%, 85%); + --vista-white: hsl(36, 15%, 87%); + --mandarian-orange: hsl(23, 77%, 55%); + --carpe-diem: hsl(31, 76%, 57%); + --new-orleans: hsl(39, 64%, 71%); + --triple-solitaire: hsl(34, 51%, 78%); + --double-colonial-white: hsl(43, 58%, 75%); + --double-solitaire: hsl(37, 46%, 80%); + --cest-la-vie: hsl(19, 26%, 86%); + --quarter-sisal: hsl(41, 37%, 83%); + --quarter-fossil: hsl(41, 32%, 85%); + --wan-white: hsl(45, 13%, 88%); + --hi-jinx: hsl(24, 76%, 57%); + --west-side: hsl(25, 77%, 56%); + --pms4675: hsl(28, 53%, 78%); + --quarter-canterbury-clay: hsl(39, 51%, 79%); + --pms482: hsl(30, 41%, 83%); + --pms5245: hsl(17, 32%, 85%); + --double-chandelier: hsl(45, 52%, 79%); + --stark-white: hsl(39, 43%, 82%); + --triple-rice-cake: hsl(43, 32%, 85%); + --half-blanc: hsl(35, 25%, 86%); + --half-albescent-white: hsl(39, 25%, 86%); + --beer-srm-08: hsl(38, 97%, 46%); + --starstruck: hsl(45, 100%, 45%); + --sunkissed: hsl(40, 75%, 61%); + --chamois: hsl(39, 60%, 75%); + --half-haystack: hsl(38, 50%, 80%); + --rock-salt: hsl(39, 48%, 81%); + --dawn-pink: hsl(22, 33%, 85%); + --half-spanish-white: hsl(39, 38%, 84%); + --double-villa-white: hsl(42, 40%, 84%); + --eighth-akaroa: hsl(35, 31%, 86%); + --eighth-truffle: hsl(35, 19%, 88%); + --trinidad: hsl(20, 97%, 46%); + --brilliant-vermilion: hsl(15, 76%, 61%); + --brilliant-tangelo: hsl(22, 76%, 61%); + --brilliant-orange: hsl(30, 76%, 61%); + --lemoncello: hsl(38, 78%, 57%); + --light-tangelo: hsl(23, 66%, 73%); + --brilliant-gamboge: hsl(38, 76%, 61%); + --pale-light-grayish-vermilion: hsl(15, 49%, 81%); + --light-gamboge: hsl(38, 66%, 73%); + --light-amber: hsl(45, 66%, 73%); + --pale-light-grayish-brown: hsl(31, 49%, 81%); + --bizarre: hsl(19, 39%, 85%); + --double-rice-cake: hsl(45, 29%, 87%); + --wild-sand: hsl(40, 16%, 89%); + --pms158: hsl(28, 86%, 49%); + --pms721: hsl(28, 69%, 71%); + --vienna: hsl(43, 55%, 80%); + --eighth-putty: hsl(43, 54%, 80%); + --half-milk-white: hsl(40, 21%, 89%); + --quarter-concrete: hsl(38, 15%, 89%); + --california: hsl(28, 80%, 57%); + --lolly-scramble: hsl(32, 79%, 58%); + --corvette: hsl(33, 70%, 71%); + --light-wood: hsl(25, 60%, 78%); + --beeswax: hsl(43, 58%, 79%); + --sidecar: hsl(45, 59%, 79%); + --double-pearl-lusta: hsl(42, 49%, 83%); + --spring-wood: hsl(30, 27%, 88%); + --half-cararra: hsl(42, 34%, 87%); + --fleece: hsl(44, 34%, 87%); + --flamenco: hsl(24, 80%, 59%); + --pms472: hsl(26, 73%, 70%); + --pms130: hsl(44, 88%, 49%); + --ronchi: hsl(40, 78%, 62%); + --popcorn: hsl(42, 60%, 79%); + --solitaire: hsl(36, 49%, 84%); + --eighth-pavlova: hsl(43, 45%, 85%); + --pampas: hsl(34, 25%, 89%); + --quarter-joanna: hsl(45, 28%, 89%); + --pms165-2x: hsl(20, 100%, 46%); + --starbell: hsl(43, 79%, 63%); + --zinnwaldite: hsl(19, 60%, 80%); + --new-tan: hsl(32, 66%, 77%); + --marzipan: hsl(40, 73%, 71%); + --givry: hsl(37, 60%, 80%); + --triple-pearl-lusta: hsl(42, 50%, 84%); + --bleach-white: hsl(39, 42%, 86%); + --eighth-sisal: hsl(39, 39%, 87%); + --quarter-spanish-white: hsl(38, 38%, 87%); + --half-whiteout: hsl(22, 22%, 90%); + --cararra: hsl(44, 35%, 88%); + --quarter-blanc: hsl(37, 32%, 89%); + --pms157: hsl(31, 81%, 62%); + --tacao: hsl(28, 75%, 72%); + --dairy-cream: hsl(38, 67%, 79%); + --pms726: hsl(32, 61%, 82%); + --pms4685: hsl(28, 58%, 83%); + --aquashield-astra: hsl(40, 66%, 79%); + --chandelier: hsl(44, 60%, 83%); + --double-merino: hsl(34, 37%, 89%); + --eighth-fossil: hsl(34, 31%, 90%); + --desert-storm: hsl(32, 27%, 90%); + --quarter-milk-white: hsl(36, 22%, 91%); + --beer-srm-07: hsl(40, 98%, 47%); + --wax-flower: hsl(16, 70%, 78%); + --cream-can: hsl(42, 82%, 63%); + --negroni: hsl(29, 69%, 78%); + --enchante: hsl(31, 60%, 83%); + --quarter-haystack: hsl(34, 55%, 85%); + --anglaise: hsl(37, 55%, 85%); + --white-linen: hsl(37, 35%, 90%); + --quarter-albescent-white: hsl(39, 33%, 90%); + --half-vista-white: hsl(30, 19%, 92%); + --sun: hsl(28, 85%, 58%); + --sea-buckthorn: hsl(28, 84%, 61%); + --pms143: hsl(41, 86%, 56%); + --pms487: hsl(16, 71%, 78%); + --pms720: hsl(28, 72%, 78%); + --pot-pourri: hsl(18, 46%, 88%); + --dusty-orange: hsl(24, 86%, 58%); + --faded-orange: hsl(26, 84%, 62%); + --casablanca: hsl(36, 84%, 63%); + --baja-white: hsl(41, 64%, 84%); + --villa-white: hsl(44, 46%, 89%); + --eighth-blanc: hsl(35, 29%, 92%); + --half-black-white: hsl(40, 17%, 93%); + --half-alabaster: hsl(36, 14%, 93%); + --splash: hsl(41, 75%, 78%); + --half-solitaire: hsl(38, 53%, 88%); + --wildflower: hsl(38, 59%, 87%); + --eighth-biscotti: hsl(33, 42%, 91%); + --half-pearl-lusta: hsl(44, 48%, 89%); + --orchid-white: hsl(45, 46%, 90%); + --buttery-white: hsl(44, 45%, 90%); + --pms716: hsl(31, 90%, 51%); + --squash: hsl(41, 89%, 52%); + --pms142: hsl(42, 87%, 62%); + --mandys-pink: hsl(16, 71%, 82%); + --pms488: hsl(19, 72%, 82%); + --pms156: hsl(34, 80%, 75%); + --soft-pink: hsl(20, 68%, 84%); + --pms141: hsl(44, 84%, 68%); + --pms489: hsl(21, 66%, 85%); + --half-colonial-white: hsl(45, 66%, 85%); + --fantasy: hsl(26, 45%, 91%); + --quarter-merino: hsl(33, 26%, 93%); + --crusta: hsl(19, 87%, 64%); + --bright-spark: hsl(43, 89%, 58%); + --bardot: hsl(42, 86%, 67%); + --pink-lady: hsl(32, 72%, 83%); + --triple-dutch-white: hsl(40, 76%, 81%); + --half-popcorn: hsl(41, 68%, 85%); + --milk-punch: hsl(44, 68%, 85%); + --half-vienna: hsl(43, 67%, 86%); + --fair-pink: hsl(23, 49%, 91%); + --quarter-cararra: hsl(45, 40%, 92%); + --half-villa-white: hsl(45, 45%, 91%); + --half-chandelier: hsl(45, 63%, 87%); + --pms1505: hsl(30, 100%, 48%); + --yellow-sea: hsl(33, 90%, 58%); + --pms473: hsl(26, 79%, 79%); + --pms474: hsl(28, 77%, 81%); + --tequila: hsl(33, 78%, 80%); + --pms719: hsl(30, 76%, 82%); + --oscar: hsl(34, 77%, 82%); + --pms155: hsl(40, 77%, 81%); + --melting-moment: hsl(45, 80%, 79%); + --honeymoon: hsl(43, 76%, 82%); + --blondee: hsl(42, 72%, 85%); + --sauvignon: hsl(22, 42%, 93%); + --janna: hsl(44, 60%, 89%); + --romance: hsl(43, 39%, 93%); + --eighth-rice-cake: hsl(45, 15%, 95%); + --flesh: hsl(24, 78%, 83%); + --cherokee: hsl(39, 85%, 74%); + --sazerac: hsl(32, 71%, 86%); + --pipi: hsl(42, 71%, 86%); + --quarter-popcorn: hsl(43, 66%, 88%); + --clotted-cream: hsl(42, 65%, 89%); + --quarter-solitaire: hsl(38, 52%, 92%); + --hint-of-red: hsl(24, 33%, 94%); + --quarter-villa-white: hsl(43, 41%, 93%); + --beer-srm-06: hsl(41, 98%, 49%); + --buttermilk: hsl(44, 82%, 80%); + --provincial-pink: hsl(19, 61%, 91%); + --eighth-spanish-white: hsl(36, 53%, 93%); + --eighth-black-white: hsl(45, 31%, 95%); + --bianca: hsl(45, 48%, 92%); + --frenzee: hsl(34, 92%, 58%); + --beer-srm-05: hsl(41, 93%, 55%); + --pms116-2x: hsl(43, 94%, 51%); + --filmpro-golden-yellow: hsl(40, 93%, 57%); + --pms475: hsl(27, 80%, 84%); + --hathaway: hsl(45, 86%, 77%); + --double-dutch-white: hsl(39, 80%, 84%); + --barley-white: hsl(43, 80%, 84%); + --apricot-white: hsl(45, 64%, 91%); + --pms172: hsl(17, 98%, 49%); + --gin-fizz: hsl(42, 77%, 88%); + --chardon: hsl(26, 64%, 92%); + --bridal-heath: hsl(31, 66%, 92%); + --island-spice: hsl(37, 67%, 92%); + --pms1585: hsl(25, 95%, 50%); + --pms1645: hsl(16, 94%, 62%); + --pms1375: hsl(36, 95%, 51%); + --pms714: hsl(28, 91%, 74%); + --golden-rod: hsl(45, 95%, 50%); + --pms1555: hsl(22, 88%, 80%); + --charger: hsl(41, 93%, 64%); + --pms162: hsl(21, 87%, 82%); + --pms713: hsl(27, 88%, 81%); + --tuft-bush: hsl(21, 83%, 86%); + --golden-glow: hsl(43, 91%, 74%); + --egg-sour: hsl(36, 81%, 87%); + --derby: hsl(35, 81%, 88%); + --wisp-pink: hsl(16, 66%, 93%); + --eighth-dutch-white: hsl(43, 60%, 94%); + --filmpro-white: hsl(45, 50%, 95%); + --pms1655: hsl(20, 98%, 49%); + --pms165: hsl(24, 98%, 49%); + --sunshade: hsl(28, 95%, 63%); + --tan-hide: hsl(25, 94%, 67%); + --bridesmaid: hsl(16, 73%, 93%); + --pumpkin-orange: hsl(29, 97%, 51%); + --goddess: hsl(16, 93%, 77%); + --rose-white: hsl(19, 70%, 95%); + --half-dutch-white: hsl(42, 82%, 91%); + --early-dawn: hsl(43, 80%, 92%); + --quarter-dutch-white: hsl(45, 78%, 93%); + --pms164: hsl(20, 97%, 62%); + --orangish: hsl(19, 97%, 64%); + --pms1575: hsl(22, 97%, 63%); + --pms163: hsl(20, 96%, 71%); + --pms715: hsl(28, 97%, 64%); + --pms137: hsl(37, 98%, 53%); + --pms1565: hsl(21, 96%, 73%); + --pms150: hsl(31, 97%, 66%); + --texas-rose: hsl(32, 96%, 66%); + --vegas: hsl(33, 96%, 67%); + --pms1235: hsl(42, 97%, 53%); + --pms1365: hsl(35, 96%, 68%); + --daybreak-yellow: hsl(36, 96%, 69%); + --pms136: hsl(40, 97%, 64%); + --lightning-yellow: hsl(44, 97%, 55%); + --beer-srm-04: hsl(41, 97%, 63%); + --pms135: hsl(40, 96%, 69%); + --pms149: hsl(33, 95%, 78%); + --pms1355: hsl(36, 95%, 76%); + --serenade: hsl(29, 86%, 92%); + --honey: hsl(44, 90%, 88%); + --pearl-lusta: hsl(45, 84%, 93%); + --orangeish: hsl(23, 98%, 64%); + --april-sun: hsl(36, 100%, 50%); + --hit-pink: hsl(22, 97%, 72%); + --my-sin: hsl(34, 98%, 63%); + --butterscotch: hsl(35, 98%, 64%); + --consuela: hsl(31, 97%, 71%); + --orangey-yellow: hsl(42, 98%, 54%); + --beer-srm-03: hsl(42, 98%, 67%); + --beer-srm-02: hsl(44, 97%, 73%); + --chablis: hsl(19, 88%, 94%); + --varden: hsl(40, 91%, 91%); + --forget-me-not: hsl(35, 89%, 93%); + --koromiko: hsl(35, 99%, 66%); + --salomie: hsl(41, 98%, 77%); + --sandy-beach: hsl(30, 97%, 86%); + --karry: hsl(27, 97%, 88%); + --cape-honey: hsl(40, 98%, 82%); + --oasis: hsl(41, 96%, 90%); + --blood-orange: hsl(17, 99%, 50%); + --blaze-orange: hsl(24, 100%, 50%); + --burning-orange: hsl(18, 100%, 60%); + --outrageous: hsl(28, 100%, 50%); + --pms804-2x: hsl(26, 100%, 56%); + --luminous-vivid-orange: hsl(30, 100%, 50%); + --shirley-temple: hsl(21, 100%, 63%); + --juicy: hsl(33, 100%, 50%); + --guggenheim: hsl(19, 100%, 67%); + --pizazz: hsl(34, 100%, 50%); + --pms804: hsl(27, 100%, 61%); + --pms1495: hsl(28, 100%, 62%); + --light-brilliant-tangelo: hsl(23, 100%, 70%); + --touche: hsl(28, 100%, 67%); + --mango: hsl(35, 100%, 58%); + --pale-orange: hsl(29, 100%, 67%); + --aureoline-yellow: hsl(36, 100%, 57%); + --yellowish-orange: hsl(39, 100%, 53%); + --cadmium-yellow-light: hsl(40, 100%, 53%); + --light-brilliant-orange: hsl(30, 100%, 70%); + --rubber-duck: hsl(38, 100%, 61%); + --pms1485: hsl(28, 100%, 73%); + --pms810-2x: hsl(42, 100%, 56%); + --golden-tainoi: hsl(38, 100%, 66%); + --light-brilliant-gamboge: hsl(37, 100%, 70%); + --romantic: hsl(25, 100%, 81%); + --pms123: hsl(45, 100%, 56%); + --chardonnay: hsl(36, 100%, 74%); + --pms1225: hsl(43, 100%, 64%); + --grandis: hsl(39, 100%, 73%); + --very-light-orange: hsl(30, 100%, 81%); + --burly-wood: hsl(34, 100%, 80%); + --pms712: hsl(29, 100%, 83%); + --oopsy-daisy: hsl(41, 100%, 74%); + --pms1345: hsl(38, 100%, 78%); + --pms148: hsl(35, 100%, 80%); + --circus: hsl(35, 100%, 81%); + --light-brilliant-amber: hsl(45, 100%, 70%); + --la-luna: hsl(42, 100%, 74%); + --pms134: hsl(42, 100%, 75%); + --light-peach: hsl(30, 100%, 85%); + --pale-tangelo: hsl(23, 100%, 88%); + --very-light-gamboge: hsl(38, 100%, 81%); + --watusi: hsl(18, 100%, 91%); + --frangipani: hsl(34, 100%, 85%); + --sentimental: hsl(18, 100%, 92%); + --cream-brulee: hsl(43, 100%, 80%); + --moccasin: hsl(38, 100%, 85%); + --pale-peach: hsl(41, 100%, 84%); + --pale-gamboge: hsl(37, 100%, 88%); + --colonial-white: hsl(44, 100%, 87%); + --double-bianca: hsl(40, 100%, 94%); + --soapstone: hsl(20, 100%, 99%); + --luminous-vivid-vermilion: hsl(15, 100%, 50%); + --vermilion: hsl(18, 100%, 50%); + --adrenalin: hsl(19, 100%, 50%); + --pms811-2x: hsl(16, 100%, 54%); + --bright-orange: hsl(21, 100%, 50%); + --luminous-vivid-tangelo: hsl(23, 100%, 50%); + --acid-green: hsl(65, 76%, 43%); + --alabaster: hsl(50, 32%, 93%); + --android-green: hsl(74, 55%, 50%); + --antique-bronze: hsl(53, 55%, 26%); + --apple-green: hsl(74, 100%, 36%); + --arctic-lime: hsl(72, 100%, 54%); + --army-green: hsl(69, 44%, 23%); + --arylide-yellow: hsl(51, 74%, 67%); + --aureolin: hsl(56, 100%, 50%); + --silver-steel: hsl(60, 0%, 53%); + --tarmac: hsl(60, 0%, 43%); + --storm-dust: hsl(60, 1%, 39%); + --bombay: hsl(60, 1%, 68%); + --silver-lining: hsl(60, 1%, 49%); + --battleship-grey: hsl(60, 1%, 51%); + --star-dust: hsl(60, 2%, 62%); + --pms425: hsl(60, 3%, 37%); + --half-chicago: hsl(60, 3%, 45%); + --dark-olivish-grey: hsl(60, 3%, 34%); + --pms426: hsl(60, 4%, 16%); + --aquashield-half-tapa: hsl(60, 4%, 55%); + --sterling: hsl(60, 5%, 52%); + --yellowish-black: hsl(60, 5%, 11%); + --double-tapa: hsl(60, 5%, 39%); + --pms447: hsl(60, 6%, 23%); + --helter-skelter: hsl(60, 6%, 19%); + --yellowish-grey: hsl(60, 6%, 64%); + --double-lemon-grass: hsl(60, 9%, 50%); + --pms419: hsl(60, 10%, 14%); + --schist: hsl(60, 10%, 48%); + --warm-grey: hsl(60, 10%, 46%); + --pastel-gray: hsl(60, 10%, 79%); + --raptor: hsl(60, 11%, 31%); + --terrain: hsl(60, 11%, 64%); + --grasslands: hsl(60, 14%, 21%); + --dark-grayish-olive: hsl(60, 15%, 30%); + --old-medium-goldenrod: hsl(60, 15%, 47%); + --malachite-green: hsl(60, 16%, 51%); + --grayish-olive: hsl(60, 20%, 57%); + --style-pasifika-dry-bamboo: hsl(60, 20%, 45%); + --very-dark-olive: hsl(60, 26%, 9%); + --crisp-green: hsl(60, 29%, 45%); + --moderate-olive: hsl(60, 39%, 47%); + --secret-garden: hsl(60, 48%, 29%); + --beige: hsl(60, 56%, 91%); + --baby-powder: hsl(60, 67%, 99%); + --banana-yellow: hsl(51, 100%, 60%); + --bitter-lemon: hsl(66, 89%, 46%); + --black-olive: hsl(70, 5%, 22%); + --blond: hsl(50, 86%, 86%); + --booger-buster: hsl(63, 67%, 65%); + --brass: hsl(52, 47%, 48%); + --bronze-yellow: hsl(58, 100%, 23%); + --buff: hsl(49, 79%, 73%); + --cadmium-yellow: hsl(58, 100%, 50%); + --canary: hsl(60, 100%, 80%); + --canary-yellow: hsl(56, 100%, 50%); + --chartreuse-traditional: hsl(68, 100%, 50%); + --citrine: hsl(54, 92%, 47%); + --citron: hsl(64, 69%, 39%); + --corn: hsl(54, 95%, 67%); + --cream: hsl(57, 100%, 91%); + --cyber-yellow: hsl(50, 100%, 50%); + --daffodil: hsl(60, 100%, 60%); + --dandelion: hsl(55, 86%, 56%); + --dark-khaki: hsl(56, 38%, 58%); + --dark-yellow: hsl(52, 86%, 33%); + --deep-lemon: hsl(47, 92%, 53%); + --dodie-yellow: hsl(57, 99%, 68%); + --ecru: hsl(45, 35%, 63%); + --eggshell: hsl(46, 46%, 89%); + --electric-lime: hsl(72, 100%, 50%); + --electric-yellow: hsl(60, 100%, 60%); + --flavescent: hsl(52, 87%, 76%); + --flax: hsl(50, 76%, 72%); + --gargoyle-gas: hsl(50, 100%, 64%); + --gold-metallic: hsl(46, 65%, 52%); + --gold-web-golden: hsl(51, 100%, 50%); + --golden-poppy: hsl(46, 100%, 49%); + --golden-yellow: hsl(52, 100%, 50%); + --icterine: hsl(58, 96%, 68%); + --jasmine: hsl(47, 90%, 73%); + --jonquil: hsl(49, 91%, 52%); + --june-bud: hsl(73, 64%, 60%); + --key-lime: hsl(67, 83%, 75%); + --old-moss-green: hsl(54, 43%, 37%); + --khaki-x11-light-khaki: hsl(54, 77%, 75%); + --lemon: hsl(58, 100%, 50%); + --lemon-chiffon: hsl(54, 100%, 90%); + --lemon-glacier: hsl(60, 100%, 50%); + --lemon-lime: hsl(67, 100%, 50%); + --lemon-meringue: hsl(47, 76%, 85%); + --lemon-yellow: hsl(56, 100%, 65%); + --light-goldenrod-yellow: hsl(60, 80%, 90%); + --limerick: hsl(72, 91%, 40%); + --maximum-green-yellow: hsl(65, 75%, 61%); + --maximum-yellow: hsl(60, 95%, 60%); + --medium-champagne: hsl(48, 75%, 81%); + --medium-spring-bud: hsl(73, 55%, 70%); + --middle-green-yellow: hsl(72, 43%, 56%); + --middle-yellow: hsl(55, 100%, 50%); + --mikado-yellow: hsl(45, 100%, 52%); + --milk: hsl(72, 100%, 98%); + --mindaro: hsl(72, 90%, 75%); + --minion-yellow: hsl(52, 89%, 64%); + --misty-moss: hsl(54, 33%, 60%); + --mustard: hsl(47, 100%, 67%); + --naples-yellow: hsl(48, 94%, 67%); + --old-gold: hsl(49, 61%, 52%); + --orange-yellow: hsl(45, 91%, 69%); + --pale-goldenrod: hsl(55, 67%, 80%); + --pale-spring-bud: hsl(59, 55%, 83%); + --pastel-yellow: hsl(60, 96%, 79%); + --pear: hsl(66, 75%, 54%); + --peridot: hsl(59, 100%, 45%); + --safety-yellow: hsl(53, 98%, 47%); + --saffron: hsl(45, 90%, 57%); + --sage: hsl(55, 27%, 64%); + --sandstorm: hsl(52, 82%, 59%); + --school-bus-yellow: hsl(51, 100%, 50%); + --sizzling-sunrise: hsl(52, 100%, 50%); + --spanish-bistre: hsl(52, 44%, 35%); + --straw: hsl(54, 68%, 66%); + --sunny: hsl(60, 82%, 71%); + --titanium-yellow: hsl(58, 100%, 47%); + --vegas-gold: hsl(50, 48%, 56%); + --vivid-lime-green: hsl(74, 93%, 44%); + --vivid-yellow: hsl(53, 100%, 50%); + --volt: hsl(72, 100%, 50%); + --yellow-crayola: hsl(50, 95%, 75%); + --yellow-munsell: hsl(51, 100%, 47%); + --yellow-pantone: hsl(53, 100%, 50%); + --yellow-ryb: hsl(60, 99%, 60%); + --very-deep-olive: hsl(60, 100%, 6%); + --heart-gold: hsl(60, 100%, 25%); + --yellow: hsl(60, 100%, 50%); + --laser-lemon: hsl(60, 100%, 70%); + --very-pale-yellow: hsl(60, 100%, 87%); + --light-yellow: hsl(60, 100%, 94%); + --ivory: hsl(60, 100%, 97%); + --yellow-rose: hsl(56, 100%, 50%); + --rangoon-green: hsl(71, 22%, 10%); + --rangitoto: hsl(75, 19%, 16%); + --onion: hsl(45, 54%, 12%); + --woodrush: hsl(49, 52%, 12%); + --canopy: hsl(47, 9%, 19%); + --waiouru: hsl(68, 64%, 14%); + --dark-olive: hsl(67, 94%, 13%); + --squall: hsl(70, 5%, 22%); + --camouflage: hsl(56, 58%, 15%); + --bathurst: hsl(70, 24%, 20%); + --deep-khaki: hsl(72, 13%, 22%); + --madras: hsl(45, 94%, 13%); + --thatch-green: hsl(55, 44%, 17%); + --pms5747: hsl(66, 53%, 18%); + --bronzetone: hsl(75, 31%, 23%); + --deep-lime-green: hsl(75, 100%, 17%); + --grey-green: hsl(73, 15%, 25%); + --verdun-green: hsl(72, 52%, 21%); + --pms5815: hsl(55, 62%, 18%); + --modular-green: hsl(68, 11%, 28%); + --kelp: hsl(69, 14%, 27%); + --woodland: hsl(68, 35%, 24%); + --dark-lime-green: hsl(74, 39%, 25%); + --bronze-olive: hsl(49, 73%, 18%); + --deep-apple-green: hsl(67, 100%, 17%); + --quarter-masala: hsl(48, 2%, 45%); + --ironside-grey: hsl(48, 2%, 39%); + --rampart: hsl(48, 3%, 30%); + --top-gear: hsl(48, 16%, 12%); + --tangerine-yellow: hsl(48, 100%, 50%); + --cornsilk: hsl(48, 100%, 93%); + --dark-apple-green: hsl(67, 39%, 25%); + --green-brown: hsl(56, 93%, 17%); + --lisbon-brown: hsl(48, 18%, 28%); + --dark-grayish-lime-green: hsl(73, 15%, 30%); + --oilskin: hsl(50, 8%, 31%); + --saratoga: hsl(65, 70%, 21%); + --vault: hsl(63, 15%, 30%); + --pms378: hsl(70, 66%, 23%); + --fern-frond: hsl(69, 34%, 27%); + --deep-amber: hsl(45, 100%, 17%); + --dark-amber: hsl(46, 39%, 25%); + --deep-gold: hsl(53, 100%, 17%); + --dark-gold: hsl(53, 39%, 25%); + --dark-grayish-amber: hsl(47, 15%, 30%); + --deep-olive: hsl(60, 100%, 17%); + --hibernate: hsl(51, 22%, 29%); + --triple-tapa: hsl(55, 6%, 34%); + --west-coast: hsl(45, 32%, 27%); + --half-gravel: hsl(69, 4%, 35%); + --pms5753: hsl(71, 28%, 31%); + --hemlock: hsl(58, 23%, 30%); + --mud-green: hsl(64, 96%, 20%); + --pms450: hsl(46, 38%, 27%); + --pms581: hsl(58, 70%, 22%); + --pms418: hsl(53, 10%, 34%); + --costa-del-sol: hsl(55, 34%, 28%); + --finch: hsl(68, 17%, 34%); + --fiji-green: hsl(69, 53%, 28%); + --olive-brown: hsl(50, 94%, 20%); + --triple-stack: hsl(70, 3%, 39%); + --muddy-green: hsl(74, 40%, 33%); + --pacifika: hsl(68, 47%, 30%); + --chrome-oxide-green: hsl(74, 73%, 29%); + --pms455: hsl(48, 67%, 24%); + --filmpro-raw-sienna: hsl(46, 38%, 29%); + --evolution: hsl(50, 10%, 37%); + --olive-green: hsl(70, 94%, 25%); + --abel-tasman: hsl(45, 38%, 29%); + --greeny-brown: hsl(55, 89%, 22%); + --greenish-brown: hsl(54, 71%, 24%); + --brownish-green: hsl(62, 85%, 23%); + --acorn: hsl(50, 59%, 26%); + --pms5757: hsl(64, 45%, 30%); + --chain-reaction: hsl(50, 9%, 39%); + --traffic: hsl(72, 2%, 42%); + --murky-green: hsl(68, 79%, 27%); + --pms3995: hsl(53, 96%, 22%); + --kokoda: hsl(57, 12%, 39%); + --climate: hsl(56, 8%, 40%); + --browny-green: hsl(58, 83%, 24%); + --poop-green: hsl(66, 100%, 24%); + --crocodile: hsl(47, 17%, 38%); + --brown-green: hsl(57, 74%, 25%); + --pms385: hsl(60, 70%, 26%); + --pms377: hsl(74, 97%, 29%); + --pms133: hsl(48, 84%, 24%); + --peat: hsl(47, 14%, 39%); + --socrates: hsl(50, 12%, 40%); + --olivetone: hsl(58, 75%, 25%); + --dimension: hsl(58, 14%, 39%); + --quarter-gravel: hsl(68, 4%, 43%); + --yellow-metal: hsl(45, 34%, 33%); + --go-ben: hsl(52, 19%, 38%); + --dark-yellow-green: hsl(72, 97%, 28%); + --internet: hsl(49, 8%, 42%); + --crete: hsl(64, 49%, 32%); + --mud: hsl(46, 73%, 26%); + --swamp-green: hsl(68, 100%, 26%); + --pms5825: hsl(56, 46%, 31%); + --shit-green: hsl(65, 100%, 25%); + --pms5763: hsl(67, 22%, 40%); + --triple-delta: hsl(70, 3%, 46%); + --wasabi: hsl(71, 58%, 34%); + --strobe: hsl(48, 14%, 42%); + --synchronise: hsl(49, 10%, 43%); + --grass-hopper: hsl(54, 50%, 32%); + --ugly-green: hsl(72, 96%, 30%); + --yukon-gold: hsl(49, 88%, 26%); + --quarry-stone: hsl(46, 13%, 43%); + --industrial-silver: hsl(75, 2%, 48%); + --trendy-green: hsl(67, 68%, 32%); + --pms1265: hsl(45, 70%, 29%); + --ugly-brown: hsl(54, 95%, 25%); + --strong-lime-green: hsl(75, 100%, 33%); + --bling: hsl(45, 26%, 39%); + --rutherford: hsl(54, 18%, 42%); + --camo: hsl(75, 29%, 43%); + --cobblestone: hsl(55, 5%, 48%); + --triple-lemon-grass: hsl(58, 11%, 46%); + --pms105: hsl(53, 79%, 28%); + --drab: hsl(61, 32%, 39%); + --triple-hillary: hsl(49, 22%, 42%); + --kombi: hsl(64, 47%, 36%); + --pms620: hsl(53, 77%, 29%); + --pms392: hsl(59, 93%, 27%); + --bandicoot: hsl(57, 9%, 48%); + --castle-rock: hsl(56, 6%, 49%); + --granite-green: hsl(46, 16%, 47%); + --carat: hsl(46, 17%, 45%); + --bitter: hsl(69, 8%, 50%); + --pms4495: hsl(48, 48%, 36%); + --pms582: hsl(61, 93%, 28%); + --muddy-brown: hsl(45, 92%, 28%); + --olive-haze: hsl(47, 15%, 46%); + --wanderlust: hsl(57, 39%, 38%); + --anemone-green: hsl(68, 13%, 49%); + --awol: hsl(64, 29%, 43%); + --baby-shit-green: hsl(67, 74%, 34%); + --pms119: hsl(50, 69%, 32%); + --clay-creek: hsl(46, 21%, 44%); + --vomit-green: hsl(69, 96%, 32%); + --eighth-masala: hsl(50, 2%, 53%); + --gold: hsl(51, 100%, 27%); + --light-goldenrod: hsl(50, 29%, 42%); + --khaki: hsl(55, 28%, 43%); + --isotonic: hsl(57, 9%, 50%); + --pms5767: hsl(65, 29%, 44%); + --brown-grey: hsl(45, 15%, 48%); + --hazel: hsl(48, 71%, 33%); + --techno: hsl(49, 13%, 49%); + --pms416: hsl(54, 8%, 52%); + --pea-green: hsl(71, 81%, 37%); + --poo: hsl(48, 96%, 29%); + --baby-poop-green: hsl(64, 94%, 31%); + --icky-green: hsl(73, 67%, 41%); + --ventura: hsl(46, 44%, 39%); + --highball: hsl(58, 43%, 39%); + --westwood: hsl(73, 21%, 51%); + --moderate-lime-green: hsl(75, 39%, 47%); + --abanakee: hsl(47, 15%, 50%); + --half-cobblestone: hsl(47, 6%, 55%); + --pea-soup: hsl(63, 99%, 30%); + --baby-poop: hsl(51, 100%, 29%); + --pms384: hsl(62, 94%, 31%); + --strong-apple-green: hsl(68, 100%, 33%); + --puke-brown: hsl(48, 92%, 30%); + --pea-soup-green: hsl(68, 76%, 37%); + --barf-green: hsl(68, 98%, 34%); + --sickly-green: hsl(72, 73%, 40%); + --lemon-ginger: hsl(50, 58%, 37%); + --pms619: hsl(55, 58%, 37%); + --proton: hsl(70, 6%, 57%); + --booger-green: hsl(70, 97%, 36%); + --double-hillary: hsl(48, 18%, 50%); + --hacienda: hsl(49, 70%, 35%); + --alibi: hsl(50, 63%, 36%); + --gurkha: hsl(49, 16%, 52%); + --pms112: hsl(51, 88%, 32%); + --pms456: hsl(52, 77%, 34%); + --pms3985: hsl(55, 88%, 32%); + --pms399: hsl(55, 91%, 31%); + --lemon-grass: hsl(63, 9%, 56%); + --frontier: hsl(67, 15%, 55%); + --limelight: hsl(69, 65%, 41%); + --jewelled-yellow: hsl(48, 43%, 42%); + --archive-grey: hsl(53, 4%, 59%); + --puke-green: hsl(67, 92%, 35%); + --yellowish-brown: hsl(47, 99%, 31%); + --pms5773: hsl(64, 18%, 53%); + --impromptu: hsl(69, 67%, 42%); + --booger: hsl(73, 50%, 47%); + --green-smoke: hsl(69, 27%, 52%); + --moderate-apple-green: hsl(68, 39%, 47%); + --bright-olive: hsl(70, 96%, 37%); + --sick-green: hsl(72, 62%, 45%); + --snot-green: hsl(71, 100%, 38%); + --pms132: hsl(46, 88%, 33%); + --pms5835: hsl(56, 28%, 48%); + --pms391: hsl(60, 92%, 32%); + --grayish-lime-green: hsl(74, 20%, 57%); + --pms382-2x: hsl(72, 100%, 38%); + --reef-gold: hsl(47, 70%, 37%); + --diarrhea: hsl(49, 96%, 32%); + --triple-tana: hsl(52, 13%, 57%); + --triple-ash: hsl(50, 12%, 57%); + --dawn: hsl(51, 7%, 60%); + --citrus: hsl(68, 90%, 38%); + --pms4505: hsl(49, 33%, 47%); + --gross-green: hsl(71, 79%, 42%); + --grey-olive: hsl(48, 15%, 56%); + --vomit: hsl(61, 77%, 36%); + --locust: hsl(65, 17%, 57%); + --pms126: hsl(47, 94%, 33%); + --canvas: hsl(46, 19%, 55%); + --pms415: hsl(47, 11%, 59%); + --quarter-tapa: hsl(68, 4%, 63%); + --pms383: hsl(64, 92%, 36%); + --pea: hsl(70, 71%, 44%); + --gingko: hsl(53, 32%, 49%); + --delta-grey: hsl(52, 8%, 62%); + --puke: hsl(60, 98%, 33%); + --bud: hsl(67, 13%, 61%); + --bahia: hsl(72, 89%, 42%); + --treetops: hsl(50, 11%, 61%); + --hillary: hsl(50, 19%, 57%); + --double-ash: hsl(49, 11%, 61%); + --swordfish: hsl(55, 6%, 63%); + --foggy-grey: hsl(54, 5%, 64%); + --stun: hsl(69, 17%, 61%); + --dark-mustard: hsl(49, 94%, 34%); + --moderate-amber: hsl(45, 39%, 47%); + --strong-gold: hsl(53, 100%, 33%); + --moderate-gold: hsl(52, 39%, 47%); + --grayish-amber: hsl(46, 20%, 57%); + --double-tana: hsl(51, 14%, 60%); + --greyish: hsl(47, 10%, 62%); + --strong-olive: hsl(60, 100%, 33%); + --mustard-green: hsl(64, 96%, 36%); + --double-linen: hsl(55, 13%, 61%); + --quarter-friar-grey: hsl(47, 5%, 65%); + --happy-hour: hsl(75, 54%, 54%); + --pms118: hsl(50, 89%, 35%); + --pms111: hsl(51, 89%, 35%); + --neutral-green: hsl(52, 19%, 59%); + --pms5777: hsl(63, 25%, 57%); + --pms583: hsl(65, 90%, 38%); + --baby-poo: hsl(50, 95%, 34%); + --lucky: hsl(53, 72%, 39%); + --half-lemon-grass: hsl(64, 8%, 65%); + --snot: hsl(65, 87%, 39%); + --light-olive: hsl(73, 40%, 58%); + --baby-shit-brown: hsl(49, 86%, 36%); + --pms104: hsl(53, 87%, 36%); + --stone: hsl(47, 19%, 60%); + --flourish: hsl(63, 35%, 53%); + --yellowy-brown: hsl(47, 87%, 36%); + --pms613: hsl(54, 87%, 37%); + --pms398: hsl(57, 89%, 36%); + --bland: hsl(48, 18%, 62%); + --off-piste: hsl(48, 9%, 66%); + --quarter-taupe-grey: hsl(50, 7%, 66%); + --eagle: hsl(51, 15%, 64%); + --yellowish-green: hsl(74, 82%, 48%); + --inch-worm: hsl(75, 85%, 48%); + --half-grey-olive: hsl(47, 15%, 64%); + --husk: hsl(45, 41%, 50%); + --pms5845: hsl(53, 30%, 57%); + --vermont: hsl(68, 42%, 56%); + --iko: hsl(53, 31%, 57%); + --glitterati: hsl(47, 16%, 65%); + --la-rioja: hsl(65, 85%, 41%); + --copyrite: hsl(51, 9%, 68%); + --pebble-grey: hsl(56, 10%, 67%); + --celery: hsl(66, 48%, 53%); + --pms125: hsl(46, 90%, 37%); + --pms457: hsl(51, 88%, 38%); + --pms3975: hsl(55, 88%, 38%); + --pms618: hsl(53, 38%, 53%); + --earthstone: hsl(51, 22%, 63%); + --pms5783: hsl(60, 21%, 63%); + --bile: hsl(64, 94%, 39%); + --karma: hsl(51, 54%, 46%); + --stone-age: hsl(55, 25%, 62%); + --baby-puke-green: hsl(64, 94%, 40%); + --yellow-brown: hsl(49, 100%, 36%); + --sahara: hsl(47, 66%, 43%); + --toi: hsl(46, 23%, 63%); + --eighth-tapa: hsl(70, 4%, 71%); + --rio-grande: hsl(65, 77%, 44%); + --earls-green: hsl(53, 69%, 43%); + --chino: hsl(46, 24%, 63%); + --quarter-crisp-green: hsl(56, 30%, 60%); + --gimblet: hsl(58, 35%, 57%); + --tana: hsl(52, 14%, 68%); + --bone-white: hsl(57, 11%, 69%); + --half-foggy-grey: hsl(53, 6%, 70%); + --coromandel: hsl(45, 33%, 59%); + --half-hillary: hsl(49, 19%, 66%); + --wild-willow: hsl(67, 43%, 59%); + --mist-grey: hsl(56, 11%, 70%); + --pms390: hsl(63, 95%, 39%); + --pms382: hsl(69, 91%, 44%); + --coriander: hsl(52, 25%, 64%); + --aspiring: hsl(60, 16%, 68%); + --buddha-gold: hsl(48, 75%, 42%); + --pms4515: hsl(47, 35%, 60%); + --fawn-green: hsl(55, 25%, 65%); + --beryl-green: hsl(68, 15%, 70%); + --greenish-tan: hsl(71, 44%, 64%); + --grey-nickel: hsl(48, 10%, 71%); + --pine-glade: hsl(63, 34%, 62%); + --ash: hsl(50, 15%, 70%); + --eighth-castle-rock: hsl(54, 7%, 73%); + --half-atmosphere: hsl(68, 6%, 73%); + --fuego: hsl(69, 89%, 46%); + --ocher: hsl(48, 88%, 40%); + --muddy-yellow: hsl(54, 95%, 38%); + --kidnapper: hsl(63, 14%, 71%); + --quarter-delta: hsl(72, 4%, 74%); + --gooseberry: hsl(64, 26%, 68%); + --key-lime-pie: hsl(64, 72%, 46%); + --yellowy-green: hsl(75, 88%, 55%); + --poprock: hsl(66, 44%, 62%); + --billy-t: hsl(56, 50%, 51%); + --pms397: hsl(59, 90%, 40%); + --olive-yellow: hsl(56, 91%, 40%); + --puke-yellow: hsl(59, 87%, 41%); + --spritzer: hsl(70, 77%, 52%); + --brilliant-lime-green: hsl(75, 76%, 61%); + --nirvana: hsl(56, 32%, 65%); + --sundance: hsl(47, 50%, 54%); + --pms612: hsl(57, 100%, 38%); + --quarter-foggy-grey: hsl(52, 6%, 75%); + --kangaroo: hsl(54, 15%, 73%); + --double-concrete: hsl(60, 2%, 77%); + --ocre: hsl(47, 96%, 40%); + --pms117: hsl(48, 89%, 41%); + --funk: hsl(50, 69%, 46%); + --pms103: hsl(52, 86%, 42%); + --pms5793: hsl(60, 22%, 71%); + --pms5787: hsl(60, 28%, 69%); + --neva: hsl(65, 89%, 45%); + --las-palmas: hsl(67, 69%, 53%); + --greeny-yellow: hsl(73, 94%, 50%); + --yuma: hsl(47, 38%, 65%); + --vomit-yellow: hsl(58, 89%, 41%); + --eighth-lemon-grass: hsl(72, 8%, 77%); + --brownish-yellow: hsl(52, 97%, 40%); + --double-joanna: hsl(50, 19%, 74%); + --greenish-beige: hsl(65, 49%, 65%); + --quarter-hillary: hsl(50, 22%, 73%); + --chrome-white: hsl(51, 15%, 75%); + --titania: hsl(49, 14%, 76%); + --vivid-apple-green: hsl(68, 100%, 45%); + --yellow-ochre: hsl(46, 94%, 41%); + --half-ash: hsl(49, 14%, 76%); + --quill-grey: hsl(49, 10%, 77%); + --harp: hsl(73, 13%, 78%); + --green-mist: hsl(74, 28%, 76%); + --pms4525: hsl(47, 38%, 68%); + --pms617: hsl(54, 44%, 64%); + --pms5855: hsl(54, 36%, 69%); + --half-tana: hsl(52, 18%, 76%); + --deco: hsl(62, 45%, 66%); + --pms381: hsl(67, 76%, 52%); + --dirty-yellow: hsl(58, 91%, 42%); + --double-thorndon-cream: hsl(48, 19%, 76%); + --half-linen: hsl(51, 17%, 76%); + --sublime: hsl(71, 73%, 63%); + --greenish-yellow: hsl(71, 98%, 50%); + --moon-mist: hsl(57, 18%, 76%); + --pms584: hsl(63, 63%, 56%); + --pms389: hsl(65, 94%, 45%); + --neon-yellow: hsl(71, 100%, 51%); + --ugly-yellow: hsl(56, 99%, 41%); + --bird-flower: hsl(55, 80%, 45%); + --winter-hazel: hsl(50, 45%, 66%); + --hitchhiker: hsl(47, 30%, 74%); + --sickly-yellow: hsl(66, 78%, 53%); + --lime-yellow: hsl(72, 99%, 55%); + --alo: hsl(58, 77%, 46%); + --pms441: hsl(60, 11%, 80%); + --hypnotic: hsl(70, 61%, 70%); + --tacha: hsl(47, 56%, 60%); + --mustard-yellow: hsl(54, 91%, 43%); + --barberry: hsl(56, 74%, 47%); + --miso: hsl(51, 32%, 74%); + --zen: hsl(57, 29%, 75%); + --concrete: hsl(48, 5%, 81%); + --orinoco: hsl(62, 27%, 76%); + --rice-paper: hsl(64, 41%, 73%); + --geneva: hsl(73, 52%, 75%); + --pms606: hsl(54, 85%, 45%); + --pms5797: hsl(57, 32%, 75%); + --curiosity: hsl(69, 71%, 65%); + --tweet: hsl(53, 100%, 42%); + --white-rock: hsl(51, 27%, 77%); + --burnt-yellow: hsl(48, 92%, 44%); + --souffle: hsl(48, 54%, 64%); + --brilliant-apple-green: hsl(67, 76%, 61%); + --wattle: hsl(55, 65%, 54%); + --pms5865: hsl(51, 38%, 74%); + --pms611: hsl(57, 63%, 56%); + --ecru-white: hsl(46, 21%, 80%); + --eighth-hillary: hsl(53, 23%, 79%); + --pms5665: hsl(60, 16%, 81%); + --pms809-2x: hsl(60, 89%, 44%); + --pms380: hsl(66, 76%, 58%); + --pms388: hsl(65, 88%, 48%); + --lemon-twist: hsl(54, 48%, 70%); + --triple-black-white: hsl(49, 12%, 82%); + --half-beryl-green: hsl(70, 20%, 82%); + --pms110: hsl(49, 85%, 46%); + --tahuna-sands: hsl(48, 44%, 73%); + --quarter-linen: hsl(49, 17%, 82%); + --pms5803: hsl(56, 30%, 78%); + --helium: hsl(64, 18%, 82%); + --pms5595: hsl(72, 17%, 83%); + --pms580: hsl(68, 37%, 79%); + --pms372: hsl(74, 71%, 76%); + --quarter-tana: hsl(51, 20%, 81%); + --quarter-ash: hsl(48, 16%, 82%); + --quarter-beryl-green: hsl(60, 16%, 82%); + --bright-gold: hsl(60, 79%, 47%); + --sunflower: hsl(52, 79%, 48%); + --ying-yang: hsl(64, 30%, 80%); + --pms4535: hsl(46, 43%, 75%); + --double-travertine: hsl(49, 31%, 79%); + --loafer: hsl(55, 26%, 81%); + --pms585: hsl(63, 65%, 65%); + --ipanema: hsl(51, 67%, 58%); + --bubble-white: hsl(46, 24%, 82%); + --milk-white: hsl(48, 18%, 83%); + --sponge: hsl(56, 18%, 83%); + --light-apple-green: hsl(67, 66%, 73%); + --pale-light-grayish-lime-green: hsl(74, 49%, 81%); + --sundial: hsl(45, 72%, 52%); + --confetti: hsl(53, 69%, 57%); + --pms458: hsl(51, 63%, 64%); + --pms605: hsl(56, 86%, 47%); + --pms616: hsl(54, 49%, 74%); + --piss-yellow: hsl(58, 80%, 48%); + --pms427: hsl(50, 15%, 84%); + --pms809: hsl(61, 87%, 47%); + --tiger-lily: hsl(64, 68%, 68%); + --gold-tips: hsl(49, 84%, 47%); + --chenin: hsl(45, 62%, 66%); + --butter: hsl(48, 58%, 69%); + --sapling: hsl(50, 47%, 76%); + --daydream: hsl(56, 29%, 82%); + --citrine-white: hsl(57, 22%, 83%); + --wheatfield: hsl(46, 35%, 81%); + --half-white-rock: hsl(50, 28%, 83%); + --somerset: hsl(59, 62%, 67%); + --double-sea-fog: hsl(49, 15%, 85%); + --barely-there: hsl(48, 14%, 85%); + --ceramic: hsl(47, 12%, 86%); + --creme-de-banane: hsl(45, 67%, 63%); + --mint-julep: hsl(52, 48%, 77%); + --weathered-yellow: hsl(54, 51%, 75%); + --half-parchment: hsl(48, 32%, 82%); + --pms5875: hsl(53, 41%, 79%); + --half-ecru-white: hsl(48, 24%, 84%); + --half-titania: hsl(47, 23%, 84%); + --pms5807: hsl(55, 37%, 81%); + --eighth-tana: hsl(52, 19%, 85%); + --black-haze: hsl(47, 13%, 86%); + --pms396: hsl(61, 90%, 47%); + --pms379: hsl(65, 76%, 66%); + --pms387: hsl(65, 82%, 60%); + --party-mix: hsl(50, 74%, 55%); + --coconut-cream: hsl(49, 39%, 81%); + --whitewater: hsl(60, 8%, 87%); + --frost: hsl(66, 36%, 83%); + --pms459: hsl(53, 64%, 69%); + --pms610: hsl(56, 66%, 67%); + --pms615: hsl(53, 49%, 78%); + --travertine: hsl(49, 32%, 83%); + --half-white-pointer: hsl(51, 11%, 87%); + --half-house-white: hsl(75, 7%, 88%); + --pms586: hsl(62, 65%, 71%); + --chill-out: hsl(67, 48%, 82%); + --banana: hsl(51, 71%, 62%); + --wild-rice: hsl(52, 66%, 67%); + --brie: hsl(49, 47%, 79%); + --starship: hsl(58, 75%, 56%); + --spring-fever: hsl(58, 68%, 66%); + --eighth-ash: hsl(53, 14%, 87%); + --snow-drift: hsl(60, 11%, 88%); + --tusk: hsl(62, 50%, 80%); + --zombie: hsl(48, 57%, 75%); + --manz: hsl(56, 73%, 61%); + --primrose: hsl(56, 61%, 73%); + --half-joanna: hsl(46, 29%, 85%); + --double-barely-there: hsl(50, 18%, 87%); + --double-black-white: hsl(48, 16%, 87%); + --half-athens-grey: hsl(60, 8%, 88%); + --bavarian-cream: hsl(45, 54%, 78%); + --hampton: hsl(46, 51%, 79%); + --pms4545: hsl(46, 45%, 81%); + --first-light: hsl(56, 52%, 79%); + --half-thorndon-cream: hsl(47, 26%, 86%); + --black-white: hsl(54, 16%, 88%); + --black-squeeze: hsl(69, 12%, 89%); + --pms395: hsl(61, 86%, 49%); + --quarter-parchment: hsl(47, 32%, 86%); + --half-secrets: hsl(53, 25%, 87%); + --marble: hsl(51, 22%, 87%); + --light-khaki: hsl(69, 75%, 79%); + --brilliant-amber: hsl(45, 76%, 61%); + --vivid-gold: hsl(52, 100%, 45%); + --brilliant-gold: hsl(53, 76%, 61%); + --light-gold: hsl(53, 66%, 73%); + --pale-light-grayish-amber: hsl(46, 49%, 81%); + --arrowroot: hsl(51, 41%, 84%); + --light-yellowish-grey: hsl(60, 21%, 88%); + --pale-light-grayish-olive: hsl(60, 49%, 81%); + --brilliant-yellow: hsl(60, 76%, 61%); + --very-light-lime-green: hsl(75, 100%, 81%); + --yellow-submarine: hsl(53, 80%, 55%); + --pms3965: hsl(57, 86%, 49%); + --pms604: hsl(57, 81%, 52%); + --ragamuffin: hsl(46, 31%, 87%); + --pms587: hsl(60, 63%, 76%); + --honeysuckle: hsl(62, 79%, 67%); + --pms386: hsl(62, 80%, 65%); + --bright-lights: hsl(54, 82%, 53%); + --half-merino: hsl(48, 21%, 91%); + --quarter-thorndon-cream: hsl(48, 25%, 88%); + --narvik: hsl(46, 23%, 89%); + --half-wan-white: hsl(51, 14%, 90%); + --festival: hsl(49, 79%, 60%); + --golden-sand: hsl(47, 75%, 67%); + --mellow-yellow: hsl(47, 67%, 75%); + --pms460: hsl(51, 67%, 75%); + --pms614: hsl(51, 55%, 82%); + --orange-white: hsl(46, 41%, 86%); + --half-wheatfield: hsl(46, 38%, 87%); + --pms609: hsl(56, 67%, 75%); + --quarter-white-pointer: hsl(47, 18%, 90%); + --medium-goldenrod: hsl(60, 59%, 80%); + --lime-white: hsl(65, 37%, 88%); + --pms394: hsl(61, 84%, 57%); + --bite-me: hsl(48, 83%, 53%); + --golden-fizz: hsl(56, 82%, 56%); + --bright-sun: hsl(45, 83%, 55%); + --texas: hsl(57, 74%, 71%); + --light-brilliant-apple-green: hsl(67, 100%, 70%); + --switched-on: hsl(52, 100%, 46%); + --pms3955: hsl(57, 87%, 50%); + --half-sea-fog: hsl(53, 20%, 92%); + --filmpro-reduction-base: hsl(53, 22%, 93%); + --pms461: hsl(53, 64%, 80%); + --half-and: hsl(50, 51%, 86%); + --pms603: hsl(58, 80%, 64%); + --eighth-parchment: hsl(46, 32%, 90%); + --half-barely-there: hsl(53, 20%, 91%); + --quarter-wan-white: hsl(51, 16%, 92%); + --broom: hsl(50, 86%, 54%); + --dull-yellow: hsl(53, 81%, 65%); + --scotch-mist: hsl(49, 53%, 86%); + --sugar-cane: hsl(64, 33%, 91%); + --hive: hsl(47, 100%, 47%); + --teddy: hsl(46, 84%, 60%); + --pms608: hsl(54, 67%, 81%); + --pms3945: hsl(59, 94%, 48%); + --rice-cake: hsl(49, 35%, 90%); + --australian-mint: hsl(67, 85%, 82%); + --moon-yellow: hsl(47, 87%, 53%); + --golden-dream: hsl(52, 87%, 56%); + --portica: hsl(50, 84%, 64%); + --quarter-wheatfield: hsl(47, 38%, 91%); + --eighth-thorndon-cream: hsl(49, 27%, 92%); + --tidal: hsl(63, 83%, 76%); + --chiffon: hsl(65, 74%, 85%); + --banana-split: hsl(49, 88%, 56%); + --sandy: hsl(48, 81%, 71%); + --sahara-sand: hsl(54, 79%, 74%); + --whipped-cream: hsl(49, 49%, 89%); + --rum-swizzle: hsl(52, 51%, 89%); + --spring-sun: hsl(60, 61%, 86%); + --off-yellow: hsl(61, 88%, 60%); + --pms129: hsl(49, 87%, 59%); + --moonbeam: hsl(51, 80%, 74%); + --pms602: hsl(56, 80%, 74%); + --pms607: hsl(51, 68%, 84%); + --pms3935: hsl(58, 84%, 69%); + --pms601: hsl(56, 76%, 78%); + --quarter-pearl-lusta: hsl(46, 45%, 91%); + --pms393: hsl(58, 80%, 74%); + --half-rice-cake: hsl(49, 30%, 93%); + --quarter-black-white: hsl(48, 16%, 94%); + --manyana: hsl(48, 28%, 93%); + --filmpro-lemon-yellow: hsl(51, 89%, 56%); + --double-alabaster: hsl(60, 20%, 94%); + --very-light-apple-green: hsl(67, 100%, 81%); + --pms128: hsl(50, 87%, 67%); + --pms127: hsl(50, 83%, 74%); + --pms100: hsl(57, 85%, 72%); + --pms600: hsl(54, 76%, 82%); + --pms101: hsl(58, 89%, 62%); + --portafino: hsl(57, 80%, 78%); + --eighth-wheatfield: hsl(47, 39%, 93%); + --glistening-white: hsl(60, 27%, 94%); + --golden: hsl(47, 98%, 49%); + --fizz: hsl(48, 91%, 55%); + --energy-yellow: hsl(49, 89%, 64%); + --sandwisp: hsl(50, 81%, 80%); + --holiday: hsl(56, 89%, 64%); + --dolly: hsl(58, 87%, 70%); + --moon-glow: hsl(57, 66%, 88%); + --cumulus: hsl(59, 72%, 86%); + --mimosa: hsl(60, 67%, 88%); + --half-bianca: hsl(46, 42%, 94%); + --milan: hsl(59, 85%, 77%); + --quarter-rice-cake: hsl(47, 33%, 95%); + --hint-of-yellow: hsl(58, 63%, 90%); + --light-mustard: hsl(46, 90%, 67%); + --pms1205: hsl(48, 83%, 82%); + --pms106: hsl(54, 91%, 66%); + --half-orchid-white: hsl(46, 45%, 94%); + --quarter-alabaster: hsl(48, 24%, 96%); + --pale-apple-green: hsl(68, 100%, 88%); + --spotlight: hsl(46, 100%, 49%); + --picasso: hsl(51, 87%, 78%); + --corn-field: hsl(54, 79%, 87%); + --shalimar: hsl(59, 85%, 82%); + --white-nectar: hsl(56, 70%, 91%); + --promenade: hsl(55, 64%, 92%); + --very-pale-lime-green: hsl(74, 100%, 94%); + --kournikova: hsl(45, 93%, 65%); + --pms109: hsl(51, 95%, 53%); + --pms108: hsl(53, 95%, 53%); + --pms121: hsl(49, 92%, 71%); + --pms1215: hsl(46, 90%, 76%); + --pms115: hsl(51, 94%, 64%); + --sweet-corn: hsl(49, 92%, 72%); + --pms120: hsl(49, 91%, 74%); + --pms114: hsl(52, 94%, 64%); + --vis: hsl(47, 89%, 78%); + --pms107: hsl(54, 95%, 56%); + --pms113: hsl(52, 93%, 67%); + --pms102: hsl(56, 95%, 53%); + --pale-prim: hsl(57, 88%, 80%); + --chilean-heath: hsl(56, 69%, 92%); + --eighth-pearl-lusta: hsl(53, 43%, 96%); + --twentyfourseven: hsl(48, 95%, 62%); + --turbo: hsl(55, 100%, 49%); + --astra: hsl(45, 87%, 85%); + --yellowish: hsl(55, 94%, 69%); + --marigold-yellow: hsl(52, 95%, 71%); + --drover: hsl(50, 92%, 80%); + --buzz: hsl(54, 96%, 65%); + --light-tan: hsl(50, 91%, 83%); + --smiles: hsl(55, 94%, 72%); + --china-ivory: hsl(48, 83%, 91%); + --pms116: hsl(49, 97%, 54%); + --tinkerbell: hsl(45, 96%, 69%); + --pms122: hsl(47, 97%, 66%); + --sand-yellow: hsl(49, 96%, 69%); + --yellowish-tan: hsl(60, 95%, 75%); + --titanium-white: hsl(72, 100%, 97%); + --gorse: hsl(52, 98%, 60%); + --sandy-yellow: hsl(53, 97%, 72%); + --beer-srm-01: hsl(46, 98%, 80%); + --faded-yellow: hsl(60, 100%, 75%); + --supernova: hsl(47, 100%, 50%); + --pms810: hsl(46, 100%, 56%); + --pms803-2x: hsl(50, 100%, 54%); + --sunflower-yellow: hsl(51, 100%, 51%); + --sun-yellow: hsl(51, 100%, 57%); + --yellow-tan: hsl(48, 100%, 72%); + --cadmium-lemon: hsl(53, 100%, 51%); + --very-light-amber: hsl(45, 100%, 81%); + --light-brilliant-gold: hsl(53, 100%, 70%); + --pms803: hsl(55, 100%, 61%); + --pale-amber: hsl(45, 100%, 88%); + --dark-cream: hsl(53, 100%, 80%); + --very-light-gold: hsl(53, 100%, 81%); + --paris-daisy: hsl(55, 100%, 72%); + --very-pale-amber: hsl(46, 100%, 94%); + --pale: hsl(52, 100%, 91%); + --sunny-yellow: hsl(58, 100%, 55%); + --egg-shell: hsl(57, 100%, 88%); + --bright-yellow: hsl(60, 100%, 50%); + --butter-yellow: hsl(59, 100%, 73%); + --custard: hsl(59, 100%, 74%); + --sunshine-yellow: hsl(59, 100%, 61%); + --light-brilliant-yellow: hsl(60, 100%, 70%); + --pale-yellow: hsl(60, 100%, 76%); + --very-light-yellow: hsl(60, 100%, 81%); + --creme: hsl(60, 100%, 86%); + --off-white: hsl(60, 100%, 95%); + --yellowish-white: hsl(60, 100%, 98%); + --alien-armpit: hsl(85, 98%, 44%); + --artichoke: hsl(76, 13%, 53%); + --asparagus: hsl(93, 26%, 54%); + --avocado: hsl(81, 95%, 26%); + --bitter-lime: hsl(75, 100%, 50%); + --bright-green: hsl(96, 100%, 50%); + --bud-green: hsl(102, 37%, 55%); + --camouflage-green: hsl(91, 11%, 47%); + --chartreuse-web: hsl(90, 100%, 50%); + --chlorophyll-green: hsl(103, 100%, 50%); + --dark-moss-green: hsl(80, 45%, 25%); + --dark-olive-green: hsl(82, 39%, 30%); + --dollar-bill: hsl(98, 39%, 56%); + --ebony: hsl(97, 8%, 34%); + --french-lime: hsl(89, 98%, 61%); + --green-ryb: hsl(95, 56%, 44%); + --green-lizard: hsl(84, 90%, 58%); + --green-yellow: hsl(84, 100%, 59%); + --harlequin-green: hsl(105, 79%, 45%); + --inchworm: hsl(84, 79%, 65%); + --kelly-green: hsl(101, 78%, 41%); + --kiwi: hsl(91, 76%, 57%); + --kombu-green: hsl(103, 16%, 22%); + --laurel-green: hsl(95, 17%, 67%); + --lawn-green: hsl(90, 100%, 49%); + --maximum-green: hsl(90, 48%, 37%); + --moss-green: hsl(75, 26%, 48%); + --napier-green: hsl(100, 100%, 25%); + --nyanza: hsl(97, 100%, 93%); + --olive-drab-3: hsl(80, 60%, 35%); + --olivine: hsl(87, 33%, 59%); + --palm-leaf: hsl(88, 41%, 43%); + --pistachio: hsl(96, 42%, 61%); + --rifle-green: hsl(84, 15%, 26%); + --sap-green: hsl(93, 50%, 33%); + --sheen-green: hsl(80, 100%, 42%); + --spring-bud: hsl(80, 100%, 49%); + --spring-frost: hsl(94, 100%, 58%); + --yellow-green: hsl(80, 61%, 50%); + --marshland: hsl(94, 30%, 5%); + --gordons-green: hsl(96, 42%, 5%); + --black-forest: hsl(92, 65%, 5%); + --very-deep-chartreuse-green: hsl(91, 100%, 6%); + --green-waterloo: hsl(76, 60%, 5%); + --very-dark-chartreuse-green: hsl(90, 26%, 9%); + --pine-tree: hsl(78, 77%, 7%); + --deep-forest-green: hsl(95, 67%, 11%); + --deep-pistachio: hsl(98, 100%, 17%); + --mallard: hsl(96, 37%, 15%); + --log-cabin: hsl(88, 18%, 14%); + --green-house: hsl(101, 68%, 19%); + --green-kelp: hsl(94, 27%, 15%); + --strong-harlequin: hsl(105, 100%, 33%); + --turtle-green: hsl(79, 67%, 13%); + --heavy-metal: hsl(102, 11%, 18%); + --feverpitch: hsl(104, 29%, 20%); + --deep-chartreuse-green: hsl(90, 100%, 17%); + --army: hsl(94, 7%, 19%); + --rockpool-green: hsl(77, 7%, 19%); + --bilbao: hsl(103, 72%, 28%); + --dark-harlequin: hsl(104, 39%, 25%); + --mediterranean-olive: hsl(89, 20%, 21%); + --lush: hsl(98, 31%, 23%); + --navy-green: hsl(85, 78%, 18%); + --la-palma: hsl(103, 72%, 31%); + --dark-grass-green: hsl(95, 94%, 26%); + --clover: hsl(78, 64%, 17%); + --deep-spring-bud: hsl(82, 100%, 17%); + --terre-verte: hsl(89, 72%, 21%); + --dell: hsl(92, 68%, 23%); + --fervent-green: hsl(97, 30%, 24%); + --vivid-harlequin: hsl(105, 100%, 45%); + --dark-pistachio: hsl(97, 39%, 25%); + --olive: hsl(101, 37%, 27%); + --grass-green: hsl(98, 87%, 33%); + --strong-pistachio: hsl(98, 100%, 33%); + --pms5743: hsl(77, 32%, 22%); + --cabbage-pont: hsl(103, 13%, 26%); + --luminous-vivid-harlequin: hsl(105, 100%, 50%); + --high-country: hsl(94, 45%, 27%); + --grassy-green: hsl(96, 96%, 31%); + --topspin: hsl(95, 56%, 28%); + --green-leaf: hsl(85, 78%, 23%); + --trainspotter: hsl(90, 7%, 27%); + --butterfly-creek: hsl(90, 22%, 24%); + --dark-chartreuse-green: hsl(90, 39%, 25%); + --greenback: hsl(101, 20%, 29%); + --chartreuse: hsl(90, 100%, 27%); + --dark-spring-bud: hsl(83, 39%, 25%); + --dark-grayish-harlequin: hsl(104, 15%, 30%); + --pms574: hsl(80, 38%, 25%); + --cliffhanger: hsl(93, 6%, 29%); + --dark-grayish-chartreuse-green: hsl(89, 15%, 30%); + --knave: hsl(86, 4%, 31%); + --chalet-green: hsl(96, 29%, 34%); + --camo-green: hsl(78, 46%, 27%); + --wimbledon: hsl(87, 36%, 31%); + --pms575: hsl(90, 43%, 33%); + --vida-loca: hsl(90, 70%, 33%); + --pms375-2x: hsl(93, 100%, 37%); + --magnetic: hsl(81, 8%, 33%); + --pms371: hsl(77, 53%, 27%); + --pms370: hsl(88, 75%, 32%); + --pms369: hsl(95, 72%, 39%); + --vivid-pistachio: hsl(97, 100%, 45%); + --frog-green: hsl(93, 92%, 38%); + --pms368: hsl(98, 71%, 44%); + --chicago: hsl(77, 4%, 35%); + --panzano: hsl(81, 11%, 35%); + --kakapo: hsl(91, 60%, 37%); + --leaf-green: hsl(88, 95%, 34%); + --grass: hsl(98, 59%, 43%); + --kermit-green: hsl(89, 100%, 35%); + --dingley: hsl(93, 25%, 37%); + --glade-green: hsl(103, 23%, 41%); + --wham: hsl(102, 51%, 46%); + --barmy-army: hsl(84, 30%, 36%); + --pms576: hsl(93, 42%, 39%); + --luminous-vivid-pistachio: hsl(97, 100%, 50%); + --cinnabar-green: hsl(96, 63%, 43%); + --toxic-green: hsl(102, 73%, 52%); + --mossy-green: hsl(84, 56%, 35%); + --siam: hsl(76, 12%, 37%); + --double-trojan: hsl(90, 1%, 40%); + --pickled-aspen: hsl(90, 10%, 36%); + --limeade: hsl(90, 59%, 37%); + --strong-chartreuse-green: hsl(90, 100%, 33%); + --willow-grove: hsl(99, 11%, 41%); + --bright-lime-green: hsl(97, 99%, 51%); + --paddock: hsl(84, 14%, 39%); + --military-green: hsl(81, 33%, 36%); + --dirty-green: hsl(78, 48%, 33%); + --limed-ash: hsl(96, 5%, 41%); + --christi: hsl(86, 81%, 36%); + --cross-country: hsl(84, 30%, 38%); + --olive-drab: hsl(79, 61%, 34%); + --flat-green: hsl(99, 35%, 46%); + --strong-spring-bud: hsl(83, 100%, 33%); + --off-green: hsl(102, 33%, 48%); + --ranger: hsl(99, 13%, 45%); + --moderate-pistachio: hsl(98, 39%, 47%); + --medium-grey: hsl(100, 1%, 49%); + --double-stack: hsl(100, 1%, 44%); + --cathedral: hsl(100, 2%, 30%); + --double-gravel: hsl(100, 3%, 23%); + --oil: hsl(100, 3%, 19%); + --mangrove: hsl(100, 6%, 29%); + --earth-green: hsl(100, 9%, 19%); + --tea-green: hsl(100, 62%, 85%); + --green-apple: hsl(100, 75%, 49%); + --highland: hsl(103, 18%, 47%); + --nasty-green: hsl(94, 48%, 47%); + --leaf: hsl(89, 53%, 44%); + --khaki-green: hsl(76, 40%, 37%); + --drab-green: hsl(89, 30%, 45%); + --dull-green: hsl(104, 28%, 52%); + --vivid-chartreuse-green: hsl(90, 100%, 45%); + --moss: hsl(92, 27%, 47%); + --go: hsl(94, 39%, 49%); + --lima: hsl(86, 78%, 42%); + --montoya: hsl(77, 3%, 46%); + --koru: hsl(79, 34%, 42%); + --brilliant-harlequin: hsl(105, 76%, 61%); + --moderate-chartreuse-green: hsl(90, 39%, 47%); + --gunsmoke: hsl(80, 2%, 47%); + --sushi: hsl(79, 54%, 40%); + --windblown-green: hsl(104, 4%, 50%); + --pms376: hsl(79, 100%, 36%); + --luminous-vivid-chartreuse-green: hsl(90, 100%, 50%); + --dizzy-lizzy: hsl(88, 65%, 48%); + --double-delta: hsl(80, 2%, 51%); + --bach: hsl(86, 13%, 51%); + --woodstock: hsl(85, 24%, 49%); + --chelsea-cucumber: hsl(90, 31%, 52%); + --ravine: hsl(88, 5%, 52%); + --dark-lime: hsl(77, 99%, 36%); + --moderate-spring-bud: hsl(82, 39%, 47%); + --seagrass: hsl(98, 21%, 55%); + --avocado-green: hsl(75, 67%, 40%); + --bright-lime: hsl(89, 98%, 51%); + --eighth-gravel: hsl(80, 2%, 53%); + --grayish-harlequin: hsl(105, 20%, 57%); + --sage-green: hsl(104, 28%, 59%); + --brilliant-pistachio: hsl(98, 76%, 61%); + --pms375: hsl(81, 100%, 42%); + --jigsaw: hsl(82, 25%, 52%); + --vivid-spring-bud: hsl(82, 100%, 45%); + --grayish-chartreuse-green: hsl(89, 20%, 57%); + --greenish-grey: hsl(104, 17%, 62%); + --atlantis: hsl(80, 64%, 49%); + --chameleon: hsl(78, 42%, 51%); + --delta: hsl(80, 3%, 60%); + --washed-green: hsl(80, 9%, 55%); + --slime-green: hsl(75, 96%, 41%); + --light-grass-green: hsl(98, 90%, 68%); + --brilliant-chartreuse-green: hsl(90, 76%, 61%); + --kensington-grey: hsl(84, 3%, 61%); + --bright-yellow-green: hsl(83, 100%, 50%); + --pms5635: hsl(102, 9%, 63%); + --transmission: hsl(100, 2%, 63%); + --gossip: hsl(100, 47%, 67%); + --luminous-vivid-spring-bud: hsl(83, 100%, 50%); + --light-brilliant-pistachio: hsl(97, 100%, 70%); + --half-washed-green: hsl(81, 10%, 62%); + --lickety-split: hsl(79, 69%, 51%); + --norway: hsl(89, 22%, 64%); + --light-olive-green: hsl(76, 43%, 55%); + --anise: hsl(92, 52%, 66%); + --atmosphere: hsl(90, 2%, 66%); + --green-spring: hsl(76, 12%, 64%); + --tan-green: hsl(76, 38%, 59%); + --pms367: hsl(87, 62%, 65%); + --pms358: hsl(103, 51%, 73%); + --lime: hsl(85, 100%, 60%); + --conifer: hsl(80, 68%, 58%); + --pms429: hsl(84, 3%, 68%); + --bel-air: hsl(104, 7%, 69%); + --lemon-green: hsl(78, 98%, 49%); + --half-delta: hsl(80, 4%, 68%); + --light-pistachio: hsl(97, 66%, 73%); + --light-lime: hsl(93, 97%, 71%); + --caper: hsl(77, 34%, 63%); + --brilliant-spring-bud: hsl(82, 76%, 61%); + --pale-olive-green: hsl(83, 49%, 65%); + --pale-lime-green: hsl(90, 100%, 70%); + --light-brilliant-chartreuse-green: hsl(90, 100%, 70%); + --pms577: hsl(82, 38%, 68%); + --half-silver-chalice: hsl(105, 3%, 72%); + --light-grey-green: hsl(99, 52%, 76%); + --madang: hsl(105, 51%, 77%); + --soft-apple: hsl(84, 30%, 70%); + --pale-olive: hsl(75, 42%, 65%); + --pumice: hsl(90, 9%, 73%); + --light-chartreuse-green: hsl(90, 66%, 73%); + --light-lime-green: hsl(87, 100%, 70%); + --quarter-lemon-grass: hsl(76, 10%, 72%); + --pms442: hsl(98, 6%, 73%); + --aquashield-tasman: hsl(88, 9%, 73%); + --pms374: hsl(80, 75%, 64%); + --pixie-green: hsl(87, 29%, 73%); + --yellowgreen: hsl(76, 95%, 52%); + --pms5645: hsl(80, 11%, 73%); + --light-sage: hsl(105, 63%, 80%); + --light-harlequin: hsl(105, 66%, 73%); + --washed-out-green: hsl(103, 80%, 81%); + --clay-ash: hsl(91, 16%, 74%); + --pale-leaf: hsl(83, 24%, 73%); + --pale-lime: hsl(87, 97%, 72%); + --eighth-stack: hsl(90, 2%, 75%); + --sprout: hsl(94, 33%, 77%); + --sulu: hsl(84, 79%, 71%); + --light-yellowish-green: hsl(91, 100%, 77%); + --very-light-pistachio: hsl(98, 100%, 81%); + --pms5585: hsl(100, 13%, 78%); + --cooled-green: hsl(89, 26%, 77%); + --pms366: hsl(83, 63%, 73%); + --pale-light-grayish-harlequin: hsl(105, 49%, 81%); + --light-pea-green: hsl(88, 98%, 75%); + --light-spring-bud: hsl(82, 66%, 73%); + --light-brilliant-spring-bud: hsl(83, 100%, 70%); + --secrets: hsl(76, 12%, 76%); + --pms5655: hsl(80, 15%, 76%); + --pms578: hsl(78, 40%, 73%); + --quarter-silver-chalice: hsl(90, 2%, 78%); + --pms5517: hsl(90, 9%, 79%); + --pms579: hsl(75, 38%, 74%); + --reef: hsl(95, 100%, 82%); + --light-yellow-green: hsl(83, 97%, 75%); + --pms5527: hsl(76, 11%, 80%); + --pms373: hsl(76, 71%, 71%); + --very-pale-green: hsl(102, 94%, 86%); + --very-light-chartreuse-green: hsl(90, 100%, 81%); + --half-tasman: hsl(98, 9%, 82%); + --pale-light-grayish-chartreuse-green: hsl(89, 49%, 81%); + --grey-nurse: hsl(77, 7%, 81%); + --lucky-dip: hsl(83, 71%, 78%); + --pms365: hsl(78, 60%, 77%); + --pms5455: hsl(84, 6%, 84%); + --snowy-mint: hsl(105, 54%, 87%); + --peppermint: hsl(102, 32%, 86%); + --quarter-tasman: hsl(94, 9%, 85%); + --light-grey: hsl(100, 8%, 85%); + --pms621: hsl(80, 18%, 84%); + --light-brilliant-lime-green: hsl(75, 100%, 70%); + --aqua-haze: hsl(90, 11%, 85%); + --gin: hsl(80, 22%, 84%); + --pale-pistachio: hsl(97, 100%, 88%); + --feta: hsl(79, 21%, 85%); + --frostee: hsl(92, 27%, 86%); + --very-light-spring-bud: hsl(82, 100%, 81%); + --willow-brook: hsl(78, 32%, 86%); + --hint-of-green: hsl(100, 49%, 89%); + --catskill-white: hsl(90, 13%, 88%); + --ottoman: hsl(90, 18%, 83%); + --pale-chartreuse-green: hsl(90, 100%, 88%); + --snow-flurry: hsl(95, 100%, 91%); + --green-white: hsl(76, 22%, 90%); + --cloud-nine: hsl(98, 54%, 93%); + --saltpan: hsl(81, 37%, 93%); + --rice-flower: hsl(95, 100%, 94%); + --very-pale-chartreuse-green: hsl(91, 100%, 94%); + --carla: hsl(78, 100%, 92%); + --ash-gray: hsl(135, 8%, 72%); + --black-leather-jacket: hsl(135, 18%, 18%); + --celadon: hsl(123, 47%, 78%); + --deep-green: hsl(122, 91%, 21%); + --deep-moss-green: hsl(129, 28%, 29%); + --dolphin-gray: hsl(130, 5%, 53%); + --eton-blue: hsl(134, 31%, 69%); + --fern-green: hsl(106, 29%, 37%); + --granny-smith-apple: hsl(113, 56%, 76%); + --gray-asparagus: hsl(117, 13%, 31%); + --harlequin: hsl(105, 100%, 50%); + --iguana-green: hsl(126, 36%, 59%); + --india-green: hsl(115, 89%, 28%); + --lincoln-green: hsl(106, 89%, 18%); + --mantis: hsl(110, 44%, 58%); + --may-green: hsl(112, 38%, 41%); + --middle-green: hsl(130, 29%, 43%); + --white-metal: hsl(120, 0%, 58%); + --nickel: hsl(120, 1%, 45%); + --botany-bay: hsl(120, 1%, 22%); + --slate: hsl(120, 1%, 21%); + --silver-grey: hsl(120, 1%, 53%); + --quarter-stack: hsl(120, 2%, 69%); + --pms446: hsl(120, 2%, 29%); + --stack: hsl(120, 2%, 55%); + --pms443: hsl(120, 3%, 65%); + --dna: hsl(120, 3%, 21%); + --dark-greenish-grey: hsl(120, 3%, 34%); + --greenish-black: hsl(120, 5%, 11%); + --port-phillip: hsl(120, 7%, 42%); + --middle-earth: hsl(120, 8%, 28%); + --half-robin-egg-blue: hsl(120, 8%, 73%); + --bluegrass: hsl(120, 9%, 55%); + --pms5523: hsl(120, 9%, 85%); + --dark-grayish-green: hsl(120, 15%, 30%); + --tasman: hsl(120, 16%, 84%); + --russian-green: hsl(120, 17%, 49%); + --grayish-green: hsl(120, 20%, 57%); + --light-greenish-grey: hsl(120, 21%, 88%); + --dark-sea-green: hsl(120, 25%, 65%); + --aqua-spring: hsl(120, 31%, 93%); + --mughal-green: hsl(120, 33%, 28%); + --kermit: hsl(120, 41%, 36%); + --light-moss-green: hsl(120, 44%, 78%); + --pale-light-grayish-green: hsl(120, 49%, 81%); + --midnight-moss: hsl(120, 60%, 4%); + --pastel-green: hsl(120, 60%, 67%); + --forest-green-web: hsl(120, 61%, 34%); + --lime-green: hsl(120, 61%, 50%); + --light-green: hsl(120, 73%, 75%); + --neon-green: hsl(111, 100%, 54%); + --moderate-green: hsl(120, 39%, 47%); + --brilliant-green: hsl(120, 76%, 61%); + --pale-green: hsl(120, 93%, 79%); + --dark-green-x11: hsl(120, 100%, 20%); + --pakistan-green: hsl(120, 100%, 20%); + --ao-english: hsl(120, 100%, 25%); + --islamic-green: hsl(120, 100%, 28%); + --electric-green: hsl(120, 100%, 50%); + --screamin-green: hsl(120, 100%, 70%); + --mint-green: hsl(120, 100%, 80%); + --honeydew: hsl(120, 100%, 97%); + --slimy-green: hsl(111, 73%, 34%); + --smoke: hsl(132, 6%, 48%); + --vivid-malachite: hsl(135, 100%, 40%); + --wageningen-green: hsl(120, 55%, 45%); + --green: hsl(120, 100%, 27%); + --pms368-2x: hsl(126, 100%, 31%); + --strong-green: hsl(120, 100%, 33%); + --strong-emerald-green: hsl(128, 100%, 33%); + --strong-malachite-green: hsl(135, 100%, 33%); + --vivid-emerald-green: hsl(128, 100%, 45%); + --luminous-vivid-emerald-green: hsl(128, 100%, 50%); + --very-deep-green: hsl(120, 100%, 6%); + --deep-fir: hsl(120, 100%, 8%); + --dark-forest-green: hsl(125, 100%, 9%); + --deep-emerald-green: hsl(127, 100%, 17%); + --deep-malachite-green: hsl(135, 100%, 17%); + --racing-green: hsl(119, 100%, 14%); + --bottle-green: hsl(121, 90%, 15%); + --darkgreen: hsl(122, 87%, 15%); + --very-dark-green: hsl(116, 88%, 10%); + --forest-green: hsl(126, 84%, 15%); + --true-green: hsl(118, 95%, 30%); + --fluorescent-green: hsl(120, 100%, 52%); + --palm-green: hsl(134, 59%, 9%); + --japanese-laurel: hsl(118, 89%, 22%); + --permanent-green: hsl(130, 91%, 41%); + --vibrant-green: hsl(119, 93%, 45%); + --fluro-green: hsl(118, 100%, 50%); + --dark-fern: hsl(123, 76%, 16%); + --hunter-green: hsl(117, 78%, 14%); + --forest: hsl(118, 81%, 18%); + --deep-sap-green: hsl(113, 100%, 17%); + --san-felix: hsl(117, 87%, 21%); + --strong-sap-green: hsl(113, 100%, 33%); + --forrest-green: hsl(105, 84%, 15%); + --deep-harlequin: hsl(105, 100%, 17%); + --highlighter-green: hsl(115, 98%, 51%); + --pms802-2x: hsl(124, 76%, 46%); + --vivid-sap-green: hsl(112, 100%, 45%); + --pms361: hsl(131, 72%, 41%); + --luminous-vivid-sap-green: hsl(112, 100%, 50%); + --myrtle: hsl(115, 38%, 19%); + --hot-green: hsl(121, 100%, 57%); + --dark-emerald-green: hsl(127, 39%, 25%); + --darkish-green: hsl(131, 51%, 32%); + --kereru: hsl(109, 28%, 19%); + --kea: hsl(125, 22%, 20%); + --tree-green: hsl(110, 67%, 30%); + --pine: hsl(131, 37%, 27%); + --filmpro-emerald-green: hsl(129, 49%, 34%); + --radioactive-green: hsl(116, 96%, 55%); + --bright-light-green: hsl(131, 99%, 59%); + --filmpro-chrome-green: hsl(113, 22%, 22%); + --dark-sap-green: hsl(113, 39%, 25%); + --icon: hsl(115, 11%, 20%); + --vivid-green: hsl(112, 87%, 50%); + --landscape-green: hsl(128, 20%, 23%); + --pms362: hsl(121, 51%, 41%); + --milford-green: hsl(133, 21%, 25%); + --fern: hsl(117, 28%, 28%); + --possessed: hsl(135, 4%, 22%); + --medium-green: hsl(128, 50%, 45%); + --pms364: hsl(106, 50%, 31%); + --area: hsl(126, 36%, 37%); + --lunar-green: hsl(112, 11%, 26%); + --pms363: hsl(113, 47%, 38%); + --cobalt-green: hsl(122, 41%, 40%); + --lucky-break: hsl(106, 45%, 32%); + --green-fields: hsl(107, 31%, 30%); + --tom-thumb: hsl(112, 20%, 29%); + --poison-green: hsl(109, 98%, 54%); + --filmpro-digital-green: hsl(127, 53%, 52%); + --gecko: hsl(132, 18%, 33%); + --ozone: hsl(129, 16%, 33%); + --rivergum: hsl(113, 11%, 31%); + --moderate-emerald-green: hsl(127, 39%, 47%); + --moderate-malachite-green: hsl(135, 39%, 47%); + --fruit-salad: hsl(124, 37%, 47%); + --axolotl: hsl(110, 17%, 34%); + --light-neon-green: hsl(122, 98%, 65%); + --light-forest-green: hsl(124, 29%, 44%); + --apple: hsl(110, 47%, 45%); + --tree-frog: hsl(112, 43%, 46%); + --mid-green: hsl(114, 40%, 47%); + --leafy-green: hsl(109, 51%, 47%); + --brilliant-emerald-green: hsl(128, 76%, 61%); + --hippie-green: hsl(111, 27%, 40%); + --light-bright-green: hsl(123, 99%, 66%); + --pms5615: hsl(126, 11%, 37%); + --parsley: hsl(126, 61%, 19%); + --algae: hsl(134, 35%, 50%); + --finlandia: hsl(123, 12%, 38%); + --moderate-sap-green: hsl(113, 39%, 47%); + --cactus: hsl(116, 14%, 39%); + --dark-sage: hsl(116, 21%, 43%); + --gondwana: hsl(122, 13%, 41%); + --condor: hsl(132, 3%, 37%); + --muted-green: hsl(110, 32%, 47%); + --pms360: hsl(116, 49%, 56%); + --pms802: hsl(111, 69%, 58%); + --moderate-harlequin: hsl(105, 39%, 47%); + --groovy: hsl(105, 41%, 45%); + --lightish-green: hsl(120, 68%, 63%); + --boring-green: hsl(122, 34%, 55%); + --brilliant-sap-green: hsl(112, 76%, 61%); + --slate-green: hsl(132, 17%, 47%); + --light-brilliant-green: hsl(120, 100%, 70%); + --light-brilliant-emerald-green: hsl(127, 100%, 70%); + --light-brilliant-malachite-green: hsl(135, 100%, 70%); + --yucca: hsl(131, 7%, 44%); + --spirulina: hsl(109, 19%, 46%); + --fresh-green: hsl(109, 64%, 58%); + --epiphany: hsl(111, 22%, 49%); + --lattitude: hsl(110, 3%, 44%); + --oxley: hsl(135, 18%, 52%); + --laurel: hsl(126, 12%, 49%); + --viridian-light: hsl(121, 100%, 72%); + --soft-green: hsl(125, 40%, 60%); + --pms5625: hsl(114, 8%, 48%); + --lighter-green: hsl(113, 97%, 69%); + --dusty-green: hsl(117, 24%, 56%); + --lightgreen: hsl(122, 100%, 73%); + --green-grey: hsl(106, 14%, 50%); + --light-brilliant-sap-green: hsl(113, 100%, 70%); + --smoky-green: hsl(134, 5%, 50%); + --de-york: hsl(131, 39%, 62%); + --amulet: hsl(128, 16%, 55%); + --faded-green: hsl(113, 29%, 58%); + --greeny-grey: hsl(114, 17%, 55%); + --greyish-green: hsl(113, 19%, 57%); + --envy: hsl(129, 13%, 60%); + --light-emerald-green: hsl(127, 66%, 73%); + --light-malachite-green: hsl(135, 66%, 73%); + --light-brilliant-harlequin: hsl(105, 100%, 70%); + --easter-green: hsl(113, 97%, 74%); + --baby-green: hsl(129, 100%, 77%); + --foam-green: hsl(134, 96%, 78%); + --pewter: hsl(124, 7%, 60%); + --pms5565: hsl(129, 11%, 63%); + --light-sap-green: hsl(113, 66%, 73%); + --edward: hsl(134, 7%, 62%); + --half-stack: hsl(135, 2%, 60%); + --hospital-green: hsl(132, 59%, 75%); + --chinook: hsl(132, 38%, 72%); + --very-light-green: hsl(120, 100%, 81%); + --very-light-emerald-green: hsl(127, 100%, 81%); + --feijoa: hsl(106, 54%, 71%); + --pms359: hsl(106, 52%, 71%); + --spring-rain: hsl(107, 20%, 68%); + --pms623: hsl(132, 17%, 70%); + --light-mint-green: hsl(128, 91%, 82%); + --light-seafoam-green: hsl(130, 100%, 83%); + --very-light-sap-green: hsl(113, 100%, 81%); + --gum-leaf: hsl(132, 21%, 73%); + --pms5575: hsl(113, 12%, 71%); + --pale-light-green: hsl(105, 94%, 79%); + --zanah: hsl(117, 16%, 74%); + --light-pastel-green: hsl(111, 91%, 82%); + --rainee: hsl(113, 11%, 73%); + --pms344: hsl(133, 44%, 80%); + --pms351: hsl(132, 53%, 81%); + --very-light-harlequin: hsl(105, 100%, 81%); + --light-mint: hsl(124, 100%, 86%); + --pms558: hsl(133, 19%, 76%); + --surf: hsl(126, 25%, 78%); + --paris-white: hsl(124, 12%, 78%); + --pms622: hsl(113, 16%, 78%); + --edgewater: hsl(130, 23%, 80%); + --sea-mist: hsl(126, 18%, 80%); + --pale-emerald-green: hsl(127, 100%, 88%); + --pale-malachite-green: hsl(135, 100%, 88%); + --surf-crest: hsl(106, 23%, 79%); + --kandinsky: hsl(107, 26%, 79%); + --granny-apple: hsl(134, 41%, 84%); + --pms559: hsl(113, 18%, 80%); + --pale-sap-green: hsl(113, 100%, 88%); + --half-emerge: hsl(129, 8%, 82%); + --pms566: hsl(127, 23%, 85%); + --pale-harlequin: hsl(105, 100%, 88%); + --swans-down: hsl(135, 19%, 88%); + --aqua-squeeze: hsl(127, 14%, 88%); + --tara: hsl(117, 42%, 91%); + --very-pale-malachite-green: hsl(134, 100%, 94%); + --polar: hsl(129, 33%, 92%); + --dew: hsl(131, 30%, 93%); + --very-pale-harlequin: hsl(106, 100%, 94%); + --greenish-white: hsl(120, 100%, 98%); + --aero-blue: hsl(151, 100%, 89%); + --amazon-store: hsl(147, 35%, 35%); + --aquamarine: hsl(160, 100%, 75%); + --bangladesh-green: hsl(164, 100%, 21%); + --british-racing-green: hsl(154, 100%, 13%); + --brunswick-green: hsl(162, 48%, 20%); + --cadmium-green: hsl(154, 100%, 21%); + --cal-poly-pomona-green: hsl(137, 44%, 21%); + --cambridge-blue: hsl(140, 19%, 70%); + --castleton-green: hsl(164, 100%, 17%); + --dark-green: hsl(158, 96%, 10%); + --dark-jungle-green: hsl(162, 16%, 12%); + --dark-pastel-green: hsl(138, 97%, 38%); + --dark-spring-green: hsl(150, 66%, 27%); + --dartmouth-green: hsl(152, 100%, 22%); + --deep-aquamarine: hsl(161, 34%, 38%); + --emerald: hsl(140, 52%, 55%); + --eucalyptus: hsl(161, 65%, 55%); + --feldgrau: hsl(143, 9%, 33%); + --forest-green-traditional: hsl(149, 97%, 14%); + --go-green: hsl(156, 100%, 34%); + --green-crayola: hsl(158, 72%, 39%); + --green-ncs: hsl(160, 100%, 31%); + --green-pantone: hsl(143, 100%, 34%); + --green-pigment: hsl(149, 100%, 32%); + --green-cyan: hsl(160, 100%, 30%); + --guppie-green: hsl(150, 100%, 50%); + --hooker-green: hsl(163, 25%, 38%); + --green-munsell: hsl(163, 100%, 33%); + --illuminating-emerald: hsl(164, 49%, 38%); + --jade: hsl(158, 100%, 33%); + --jungle-green: hsl(163, 61%, 42%); + --la-salle-green: hsl(141, 88%, 25%); + --magic-mint: hsl(153, 70%, 80%); + --malachite: hsl(140, 90%, 45%); + --medium-aquamarine: hsl(154, 64%, 63%); + --medium-jungle-green: hsl(161, 31%, 16%); + --medium-sea-green: hsl(147, 50%, 47%); + --medium-spring-green: hsl(157, 100%, 49%); + --mint: hsl(158, 49%, 47%); + --mint-cream: hsl(150, 100%, 98%); + --morning-blue: hsl(153, 11%, 60%); + --mountain-meadow: hsl(161, 59%, 46%); + --north-texas-green: hsl(140, 93%, 29%); + --ocean-green: hsl(157, 48%, 52%); + --pearl-aqua: hsl(162, 51%, 69%); + --phthalo-green: hsl(151, 49%, 14%); + --sea-foam-green: hsl(149, 54%, 75%); + --sea-green: hsl(146, 50%, 36%); + --shamrock-green: hsl(156, 100%, 31%); + --shiny-shamrock: hsl(141, 29%, 51%); + --spanish-green: hsl(153, 100%, 28%); + --spanish-viridian: hsl(163, 100%, 25%); + --teal-deer: hsl(140, 61%, 75%); + --turquoise-green: hsl(142, 40%, 73%); + --ufo-green: hsl(141, 61%, 53%); + --very-light-malachite-green: hsl(135, 75%, 65%); + --xanadu: hsl(136, 8%, 49%); + --pms3425: hsl(161, 100%, 20%); + --pms349: hsl(155, 100%, 21%); + --emerald-green: hsl(159, 100%, 21%); + --watercourse: hsl(163, 100%, 22%); + --moxie: hsl(152, 100%, 22%); + --pms3415: hsl(163, 100%, 24%); + --pms348: hsl(156, 100%, 26%); + --spring-green: hsl(150, 100%, 27%); + --mother-earth: hsl(164, 100%, 28%); + --kelley-green: hsl(142, 100%, 29%); + --pms452-2x: hsl(147, 100%, 30%); + --pms355: hsl(148, 100%, 31%); + --howzat: hsl(154, 100%, 31%); + --strong-aquamarine: hsl(158, 100%, 33%); + --strong-sea-green: hsl(143, 100%, 33%); + --very-dark-spring-green: hsl(150, 26%, 9%); + --everglade: hsl(150, 39%, 18%); + --zuccini: hsl(150, 88%, 13%); + --pms356: hsl(150, 100%, 24%); + --strong-spring-green: hsl(150, 100%, 33%); + --pms3405: hsl(161, 100%, 35%); + --pms354: hsl(151, 100%, 36%); + --home-run: hsl(158, 100%, 37%); + --pms3395: hsl(164, 100%, 39%); + --vivid-malachite-green: hsl(135, 100%, 45%); + --greenish-turquoise: hsl(162, 100%, 49%); + --luminous-vivid-spring-green: hsl(150, 100%, 50%); + --luminous-vivid-aquamarine: hsl(157, 100%, 50%); + --luminous-vivid-turquoise: hsl(165, 100%, 50%); + --luminous-vivid-malachite-green: hsl(135, 100%, 50%); + --luminous-vivid-sea-green: hsl(143, 100%, 50%); + --very-deep-spring-green: hsl(149, 100%, 6%); + --burnham: hsl(162, 100%, 9%); + --kaitoke-green: hsl(147, 100%, 14%); + --crusoe: hsl(138, 100%, 14%); + --camarone: hsl(138, 100%, 17%); + --deep-sea-green: hsl(142, 100%, 17%); + --deep-spring-green: hsl(150, 100%, 17%); + --freedom: hsl(163, 100%, 19%); + --fun-green: hsl(151, 98%, 22%); + --irish-green: hsl(136, 99%, 29%); + --green-haze: hsl(158, 99%, 32%); + --shamrock: hsl(145, 99%, 35%); + --holly: hsl(159, 93%, 6%); + --cardin-green: hsl(151, 96%, 11%); + --county-green: hsl(148, 96%, 11%); + --english-holly: hsl(147, 91%, 9%); + --sherwood-green: hsl(161, 94%, 13%); + --pms3435: hsl(159, 95%, 15%); + --bright-sea-green: hsl(159, 100%, 51%); + --evergreen: hsl(154, 87%, 15%); + --salem: hsl(154, 87%, 27%); + --spruce: hsl(152, 81%, 21%); + --minty-green: hsl(149, 94%, 51%); + --green-teal: hsl(158, 88%, 38%); + --tealish-green: hsl(150, 90%, 45%); + --pms627: hsl(163, 60%, 12%); + --bush: hsl(147, 56%, 12%); + --jewel: hsl(151, 71%, 25%); + --aqua-green: hsl(157, 85%, 48%); + --robin-hood: hsl(163, 67%, 26%); + --celtic: hsl(146, 39%, 14%); + --seaweed: hsl(152, 79%, 46%); + --pioneer: hsl(160, 10%, 25%); + --pms554: hsl(160, 58%, 23%); + --bluish-green: hsl(160, 82%, 36%); + --green-pea: hsl(153, 54%, 25%); + --viridian: hsl(158, 66%, 34%); + --spearmint: hsl(144, 94%, 55%); + --dark-seafoam: hsl(156, 71%, 42%); + --dark-mint-green: hsl(151, 71%, 44%); + --wintergreen: hsl(148, 95%, 55%); + --algae-green: hsl(149, 71%, 45%); + --pms5535: hsl(152, 30%, 18%); + --botanic: hsl(139, 32%, 19%); + --pms626: hsl(155, 44%, 23%); + --pms357: hsl(139, 47%, 24%); + --greenblue: hsl(159, 70%, 45%); + --ivy-green: hsl(153, 20%, 17%); + --pms5605: hsl(146, 25%, 18%); + --pms553: hsl(153, 32%, 20%); + --greenstone: hsl(148, 50%, 28%); + --tile-green: hsl(161, 28%, 21%); + --pms567: hsl(159, 36%, 23%); + --dark-malachite-green: hsl(136, 39%, 25%); + --moroccan-palm: hsl(142, 12%, 18%); + --pms350: hsl(142, 39%, 22%); + --greenish-cyan: hsl(160, 99%, 58%); + --earthsong: hsl(147, 19%, 20%); + --nikau: hsl(142, 21%, 21%); + --roulette: hsl(154, 29%, 23%); + --jade-green: hsl(149, 61%, 43%); + --bluey-green: hsl(155, 61%, 43%); + --pms560: hsl(156, 28%, 23%); + --petanque: hsl(143, 15%, 21%); + --lamp-black: hsl(151, 21%, 23%); + --greenish-teal: hsl(155, 59%, 47%); + --stromboli: hsl(165, 30%, 28%); + --cool-green: hsl(142, 57%, 46%); + --alfresco: hsl(152, 32%, 30%); + --goblin: hsl(137, 23%, 26%); + --seaweed-green: hsl(147, 53%, 44%); + --homegrown: hsl(162, 28%, 30%); + --leprechaun: hsl(138, 29%, 30%); + --jurassic: hsl(152, 11%, 24%); + --amazon: hsl(145, 37%, 35%); + --green-room: hsl(153, 39%, 36%); + --killarney: hsl(136, 29%, 32%); + --weird-green: hsl(144, 77%, 56%); + --avatar: hsl(165, 2%, 55%); + --pms5477: hsl(165, 19%, 28%); + --strong-turquoise: hsl(165, 100%, 33%); + --caribbean-green: hsl(165, 100%, 40%); + --dark-seafoam-green: hsl(150, 48%, 46%); + --mineral-green: hsl(160, 19%, 31%); + --greenish: hsl(144, 44%, 45%); + --chateau-green: hsl(138, 45%, 45%); + --corduroy: hsl(162, 9%, 28%); + --eureka: hsl(150, 17%, 31%); + --greeny-blue: hsl(164, 46%, 48%); + --dark-grayish-malachite-green: hsl(136, 15%, 30%); + --dark-grayish-spring-green: hsl(151, 15%, 30%); + --dark-mint: hsl(141, 49%, 52%); + --moderate-sea-green: hsl(142, 39%, 47%); + --moderate-spring-green: hsl(150, 39%, 47%); + --moderate-aquamarine: hsl(158, 39%, 47%); + --nandor: hsl(143, 11%, 33%); + --como: hsl(142, 22%, 38%); + --pms5545: hsl(150, 16%, 37%); + --brilliant-malachite-green: hsl(135, 76%, 61%); + --brilliant-sea-green: hsl(142, 76%, 61%); + --brilliant-spring-green: hsl(150, 76%, 61%); + --brilliant-aquamarine: hsl(158, 76%, 61%); + --easy-rider: hsl(136, 6%, 35%); + --canyon: hsl(136, 8%, 28%); + --pms3385: hsl(158, 63%, 59%); + --light-green-blue: hsl(147, 97%, 66%); + --pms625: hsl(151, 19%, 44%); + --grey-teal: hsl(163, 24%, 49%); + --aqua-forest: hsl(140, 29%, 51%); + --scaramanga: hsl(150, 11%, 42%); + --patina: hsl(161, 19%, 48%); + --light-greenish-blue: hsl(153, 90%, 68%); + --tea: hsl(140, 29%, 53%); + --light-brilliant-sea-green: hsl(143, 100%, 70%); + --light-brilliant-spring-green: hsl(150, 100%, 70%); + --light-brilliant-aquamarine: hsl(157, 100%, 70%); + --light-brilliant-turquoise: hsl(165, 100%, 70%); + --pms5487: hsl(153, 10%, 44%); + --silver-tree: hsl(151, 35%, 55%); + --sirocco: hsl(146, 6%, 44%); + --thor: hsl(164, 9%, 45%); + --cliff-face-grey: hsl(150, 1%, 43%); + --innocence: hsl(156, 4%, 45%); + --pms346: hsl(147, 49%, 62%); + --greyish-teal: hsl(162, 19%, 53%); + --blue-smoke: hsl(159, 8%, 49%); + --acapulco: hsl(155, 24%, 56%); + --light-bluish-green: hsl(142, 97%, 73%); + --pms5555: hsl(145, 11%, 52%); + --seafoam-blue: hsl(162, 49%, 65%); + --pms556: hsl(150, 21%, 57%); + --pms338: hsl(161, 49%, 65%); + --seafoam-green: hsl(143, 91%, 73%); + --granny-smith: hsl(161, 10%, 53%); + --bay-leaf: hsl(140, 26%, 59%); + --light-aquamarine: hsl(155, 97%, 74%); + --grayish-malachite-green: hsl(135, 20%, 57%); + --grayish-spring-green: hsl(151, 20%, 57%); + --padua: hsl(145, 26%, 60%); + --light-turquoise: hsl(160, 84%, 73%); + --light-blue-green: hsl(145, 94%, 74%); + --pms624: hsl(144, 15%, 56%); + --pms563: hsl(162, 31%, 62%); + --pms570: hsl(163, 38%, 64%); + --grey-granite: hsl(137, 3%, 52%); + --cold-grey: hsl(162, 4%, 52%); + --seafoam: hsl(142, 91%, 74%); + --pale-teal: hsl(159, 41%, 65%); + --inside-back: hsl(144, 4%, 54%); + --pms353: hsl(143, 62%, 70%); + --pms444: hsl(156, 2%, 55%); + --mantle: hsl(138, 8%, 58%); + --light-spring-green: hsl(150, 66%, 73%); + --light-aqua: hsl(161, 100%, 77%); + --serenity: hsl(146, 28%, 65%); + --gannet-grey: hsl(140, 1%, 56%); + --pms3375: hsl(153, 59%, 72%); + --summer-green: hsl(140, 21%, 64%); + --light-teal: hsl(155, 61%, 73%); + --pms430: hsl(144, 2%, 58%); + --pms5497: hsl(147, 9%, 60%); + --zeal: hsl(149, 56%, 72%); + --pms345: hsl(143, 46%, 72%); + --unwind: hsl(165, 18%, 66%); + --pms352: hsl(140, 59%, 75%); + --shadow-green: hsl(164, 23%, 68%); + --pms337: hsl(156, 47%, 73%); + --tower-grey: hsl(154, 9%, 64%); + --skeptic: hsl(154, 13%, 66%); + --very-light-sea-green: hsl(142, 100%, 81%); + --very-light-spring-green: hsl(150, 100%, 81%); + --very-light-aquamarine: hsl(158, 100%, 81%); + --light-seafoam: hsl(140, 98%, 81%); + --vitra: hsl(159, 46%, 75%); + --ashanti: hsl(157, 13%, 69%); + --opal: hsl(164, 18%, 71%); + --rivendell: hsl(159, 13%, 70%); + --pms571: hsl(154, 40%, 76%); + --periglacial-blue: hsl(156, 6%, 69%); + --emerge: hsl(157, 9%, 70%); + --pms5507: hsl(136, 7%, 71%); + --ice-cold: hsl(165, 48%, 79%); + --hermitage: hsl(143, 5%, 71%); + --fringy-flower: hsl(140, 46%, 79%); + --loblolly: hsl(150, 6%, 72%); + --cruise: hsl(163, 44%, 80%); + --duck-egg-blue: hsl(150, 7%, 74%); + --nebula: hsl(146, 11%, 75%); + --pale-light-grayish-malachite-green: hsl(135, 49%, 81%); + --pale-light-grayish-spring-green: hsl(151, 49%, 81%); + --pale-aqua: hsl(163, 100%, 86%); + --tiara: hsl(150, 8%, 75%); + --fertile-mind: hsl(139, 26%, 78%); + --pms331: hsl(155, 53%, 82%); + --powder-ash: hsl(148, 11%, 76%); + --pms565: hsl(151, 30%, 80%); + --pms572: hsl(148, 40%, 81%); + --half-periglacial-blue: hsl(153, 8%, 77%); + --pale-sea-green: hsl(143, 100%, 88%); + --pale-spring-green: hsl(150, 100%, 88%); + --pale-aquamarine: hsl(157, 100%, 88%); + --half-duck-egg-blue: hsl(160, 6%, 79%); + --pms317: hsl(159, 40%, 85%); + --quarter-periglacial-blue: hsl(140, 6%, 81%); + --pms573: hsl(144, 32%, 85%); + --pms5513: hsl(138, 11%, 83%); + --humming-bird: hsl(160, 51%, 87%); + --pms332: hsl(160, 57%, 76%); + --carefree: hsl(140, 15%, 84%); + --white-ice: hsl(154, 40%, 89%); + --tranquil: hsl(165, 31%, 90%); + --clear-day: hsl(161, 33%, 91%); + --half-carefree: hsl(137, 13%, 90%); + --very-pale-spring-green: hsl(149, 100%, 94%); + --panache: hsl(140, 40%, 94%); + --blue-romance: hsl(140, 67%, 89%); + --amazonite: hsl(174, 100%, 38%); + --aurometalsaurus: hsl(183, 8%, 47%); + --ball-blue: hsl(192, 72%, 47%); + --battery-charged-blue: hsl(194, 76%, 48%); + --blizzard-blue: hsl(188, 66%, 80%); + --blue-munsell: hsl(190, 100%, 34%); + --blue-green: hsl(192, 87%, 39%); + --bondi-blue: hsl(191, 100%, 36%); + --bright-turquoise: hsl(177, 93%, 47%); + --bubbles: hsl(183, 100%, 95%); + --cadet-blue: hsl(182, 25%, 50%); + --celadon-green: hsl(174, 47%, 35%); + --cyan-process: hsl(193, 100%, 46%); + --dark-turquoise: hsl(181, 100%, 41%); + --deep-green-cyan-turquoise: hsl(165, 80%, 27%); + --deep-jungle-green: hsl(178, 100%, 15%); + --deep-space-sparkle: hsl(194, 19%, 36%); + --diamond: hsl(191, 100%, 86%); + --electric-blue: hsl(183, 100%, 75%); + --generic-viridian: hsl(168, 100%, 25%); + --green-sheen: hsl(168, 28%, 56%); + --japanese-indigo: hsl(189, 31%, 22%); + --keppel: hsl(171, 50%, 46%); + --light-blue: hsl(195, 53%, 79%); + --light-sea-green: hsl(177, 70%, 41%); + --loeen-lopen-look: hsl(183, 98%, 54%); + --maximum-blue: hsl(195, 57%, 54%); + --medium-sky-blue: hsl(190, 73%, 71%); + --medium-turquoise: hsl(178, 60%, 55%); + --metallic-seaweed: hsl(186, 87%, 29%); + --middle-blue: hsl(190, 68%, 70%); + --middle-blue-green: hsl(170, 50%, 70%); + --midnight-green-eagle-green: hsl(187, 100%, 16%); + --ming: hsl(188, 40%, 35%); + --msu-green: hsl(167, 48%, 18%); + --myrtle-green: hsl(176, 42%, 33%); + --non-photo-blue: hsl(193, 67%, 79%); + --onyx: hsl(195, 4%, 22%); + --outer-space: hsl(191, 8%, 28%); + --pacific-blue: hsl(191, 76%, 45%); + --pale-robin-egg-blue: hsl(169, 52%, 73%); + --paolo-veronese-green: hsl(168, 100%, 30%); + --persian-green: hsl(173, 100%, 33%); + --pine-green: hsl(175, 98%, 24%); + --polished-pine: hsl(166, 28%, 50%); + --powder-blue: hsl(187, 52%, 80%); + --sea-serpent: hsl(184, 58%, 55%); + --steel-teal: hsl(181, 19%, 46%); + --stormcloud: hsl(189, 15%, 36%); + --teal-blue: hsl(194, 43%, 37%); + --teal-green: hsl(179, 100%, 25%); + --tiffany-blue: hsl(178, 90%, 38%); + --tropical-rain-forest: hsl(168, 100%, 23%); + --turquoise: hsl(174, 72%, 56%); + --turquoise-blue: hsl(176, 100%, 50%); + --turquoise-surf: hsl(182, 100%, 40%); + --verdigris: hsl(177, 46%, 48%); + --viridian-green: hsl(181, 100%, 30%); + --vivid-sky-blue: hsl(192, 100%, 50%); + --waterspout: hsl(184, 88%, 81%); + --wintergreen-dream: hsl(167, 23%, 44%); + --zomp: hsl(166, 49%, 44%); + --pms634: hsl(192, 100%, 25%); + --pms323: hsl(178, 100%, 20%); + --pms336: hsl(168, 100%, 20%); + --pms315: hsl(186, 100%, 23%); + --pms342: hsl(167, 100%, 21%); + --pms3298: hsl(171, 100%, 21%); + --kitsch: hsl(189, 100%, 25%); + --pms329: hsl(176, 100%, 21%); + --pms3155: hsl(184, 100%, 23%); + --bingo: hsl(170, 100%, 23%); + --pms328: hsl(176, 100%, 23%); + --free-spirit: hsl(182, 100%, 24%); + --pms341: hsl(166, 100%, 24%); + --surfie-green: hsl(178, 100%, 24%); + --pms335: hsl(169, 100%, 24%); + --strong-cerulean: hsl(195, 100%, 33%); + --pms320-2x: hsl(181, 100%, 25%); + --pms633: hsl(190, 100%, 30%); + --pms3288: hsl(172, 100%, 25%); + --pms3295: hsl(173, 100%, 25%); + --pms314: hsl(190, 100%, 30%); + --pms3145: hsl(184, 100%, 28%); + --bowie: hsl(194, 100%, 34%); + --windfall: hsl(173, 100%, 26%); + --pms569: hsl(171, 100%, 26%); + --pms321: hsl(181, 100%, 27%); + --eastern-blue: hsl(189, 100%, 31%); + --pms327-2x: hsl(172, 100%, 27%); + --pms801-2x: hsl(193, 100%, 34%); + --hullabaloo: hsl(185, 100%, 30%); + --pms327: hsl(176, 100%, 27%); + --pms640: hsl(193, 100%, 35%); + --observatory: hsl(167, 100%, 28%); + --seeker: hsl(187, 100%, 32%); + --strong-arctic-blue: hsl(188, 100%, 33%); + --pms340: hsl(167, 100%, 30%); + --pms334: hsl(169, 100%, 30%); + --pms3285: hsl(173, 100%, 30%); + --pms313: hsl(189, 100%, 35%); + --pms3278: hsl(171, 100%, 30%); + --pms3135: hsl(185, 100%, 33%); + --origin: hsl(173, 100%, 31%); + --pms320: hsl(181, 100%, 31%); + --pms808-2x: hsl(171, 100%, 31%); + --pms632: hsl(188, 100%, 36%); + --pms639: hsl(191, 100%, 38%); + --pms306-2x: hsl(193, 100%, 41%); + --pms2995: hsl(195, 100%, 43%); + --strong-opal: hsl(173, 100%, 33%); + --pms3272: hsl(176, 100%, 33%); + --pms801: hsl(190, 100%, 40%); + --pms312: hsl(188, 100%, 39%); + --pms3268: hsl(172, 100%, 34%); + --pms339: hsl(167, 100%, 35%); + --pms3275: hsl(174, 100%, 35%); + --pms326: hsl(177, 100%, 35%); + --pms808: hsl(171, 100%, 35%); + --pms638: hsl(189, 100%, 42%); + --pms3125: hsl(185, 100%, 39%); + --pms306: hsl(190, 100%, 44%); + --pms3262: hsl(176, 100%, 38%); + --pms3265: hsl(174, 100%, 39%); + --vivid-arctic-blue: hsl(188, 100%, 45%); + --luminous-vivid-arctic-blue: hsl(188, 100%, 50%); + --vivid-turquoise: hsl(165, 100%, 45%); + --vivid-opal: hsl(172, 100%, 45%); + --luminous-vivid-opal: hsl(172, 100%, 50%); + --swamp: hsl(182, 100%, 5%); + --deep-teal: hsl(177, 100%, 10%); + --pms5463: hsl(185, 100%, 11%); + --cyprus: hsl(182, 100%, 13%); + --pms309: hsl(188, 100%, 14%); + --pms303: hsl(195, 100%, 16%); + --deep-cerulean: hsl(195, 100%, 17%); + --pms3308: hsl(169, 100%, 13%); + --pms3035: hsl(191, 100%, 16%); + --pms548: hsl(194, 100%, 17%); + --st-kilda: hsl(193, 100%, 17%); + --deep-south: hsl(188, 100%, 16%); + --pms3302: hsl(172, 100%, 14%); + --sherpa-blue: hsl(184, 100%, 15%); + --pms316: hsl(185, 100%, 15%); + --deep-arctic-blue: hsl(187, 100%, 17%); + --pms3305: hsl(170, 100%, 15%); + --dark-blue-green: hsl(173, 100%, 16%); + --pms3025: hsl(193, 100%, 21%); + --filmpro-pthalo-green: hsl(168, 100%, 17%); + --pms3165: hsl(183, 100%, 18%); + --deep-turquoise: hsl(165, 100%, 17%); + --deep-opal: hsl(173, 100%, 17%); + --pms330: hsl(175, 100%, 17%); + --maestro: hsl(188, 100%, 21%); + --petrol: hsl(186, 100%, 21%); + --cowabunga: hsl(177, 100%, 19%); + --pms308: hsl(194, 100%, 24%); + --pms3292: hsl(174, 100%, 19%); + --blue-lagoon: hsl(187, 100%, 22%); + --dark-aquamarine: hsl(179, 98%, 23%); + --bluegreen: hsl(180, 98%, 24%); + --ocean: hsl(190, 99%, 29%); + --deep-sea: hsl(169, 98%, 26%); + --bright-teal: hsl(168, 99%, 49%); + --daintree: hsl(193, 96%, 10%); + --aqua-deep: hsl(174, 97%, 15%); + --dark-teal: hsl(181, 97%, 15%); + --blue-stone: hsl(181, 98%, 19%); + --cerulean: hsl(193, 98%, 42%); + --bright-sky-blue: hsl(192, 99%, 50%); + --aqua-blue: hsl(184, 98%, 46%); + --evening-sea: hsl(174, 95%, 16%); + --mosque: hsl(182, 95%, 22%); + --manganese-blue: hsl(176, 96%, 34%); + --neon-blue: hsl(189, 100%, 51%); + --dark-aqua: hsl(181, 91%, 22%); + --pms564: hsl(170, 91%, 23%); + --gossamer: hsl(170, 93%, 32%); + --niagara: hsl(171, 93%, 33%); + --tiber: hsl(182, 80%, 12%); + --pms555: hsl(165, 88%, 23%); + --loch-ness: hsl(190, 77%, 12%); + --deep-aqua: hsl(184, 88%, 26%); + --elf-green: hsl(171, 88%, 27%); + --atoll: hsl(183, 84%, 25%); + --greenish-blue: hsl(178, 85%, 29%); + --bright-aqua: hsl(176, 95%, 51%); + --blue-chill: hsl(183, 85%, 31%); + --pms546: hsl(193, 70%, 16%); + --city-limits: hsl(176, 66%, 14%); + --aztec: hsl(168, 37%, 8%); + --firefly: hsl(191, 55%, 12%); + --eden: hsl(175, 69%, 20%); + --jackpot: hsl(168, 61%, 20%); + --genoa: hsl(175, 69%, 27%); + --dauntless: hsl(189, 70%, 29%); + --timber-green: hsl(167, 39%, 14%); + --gable-green: hsl(172, 41%, 15%); + --madagascar: hsl(175, 33%, 14%); + --bledisloe: hsl(190, 26%, 13%); + --pms5467: hsl(170, 38%, 16%); + --retro: hsl(184, 52%, 22%); + --elm: hsl(181, 63%, 30%); + --sentry: hsl(185, 18%, 13%); + --kermadec: hsl(172, 21%, 14%); + --nordic: hsl(186, 35%, 17%); + --pms562: hsl(172, 61%, 30%); + --te-papa-green: hsl(169, 38%, 19%); + --beatnik: hsl(186, 46%, 23%); + --dark-green-blue: hsl(169, 52%, 25%); + --dali: hsl(167, 72%, 44%); + --zydeco: hsl(167, 38%, 20%); + --blue-dianne: hsl(192, 44%, 22%); + --push-play: hsl(167, 45%, 24%); + --tealish: hsl(172, 68%, 44%); + --globe: hsl(175, 47%, 27%); + --pelorous: hsl(191, 66%, 42%); + --pms561: hsl(168, 46%, 27%); + --pms5473: hsl(184, 48%, 29%); + --bright-light-blue: hsl(182, 98%, 57%); + --plantation: hsl(173, 34%, 23%); + --dark-arctic-blue: hsl(187, 39%, 25%); + --dark-opal: hsl(173, 39%, 25%); + --pms311: hsl(187, 69%, 50%); + --jeepers-creepers: hsl(166, 61%, 41%); + --raglan: hsl(168, 11%, 18%); + --traccia: hsl(191, 12%, 19%); + --lochinvar: hsl(175, 52%, 36%); + --pms3115: hsl(186, 67%, 51%); + --muse: hsl(184, 41%, 30%); + --scooter: hsl(188, 66%, 51%); + --aqua-marine: hsl(165, 80%, 55%); + --meridian: hsl(180, 1%, 49%); + --dark-grey: hsl(180, 1%, 21%); + --trojan: hsl(180, 1%, 46%); + --surrender: hsl(180, 1%, 71%); + --athens-grey: hsl(180, 1%, 86%); + --pms445: hsl(180, 2%, 34%); + --half-surrender: hsl(180, 2%, 80%); + --iron: hsl(180, 2%, 80%); + --midwinter-mist: hsl(180, 2%, 80%); + --nocturnal: hsl(180, 2%, 19%); + --gravity: hsl(180, 2%, 25%); + --element: hsl(180, 3%, 18%); + --blackjack: hsl(180, 5%, 12%); + --cyanish-black: hsl(180, 5%, 11%); + --charleston-green: hsl(180, 10%, 15%); + --desaturated-cyan: hsl(180, 20%, 50%); + --dark-slate-gray: hsl(180, 25%, 25%); + --very-dark-cyan: hsl(180, 26%, 9%); + --tiki-tour: hsl(180, 29%, 19%); + --almost-black: hsl(180, 30%, 4%); + --spectra: hsl(176, 31%, 27%); + --casal: hsl(187, 38%, 30%); + --pms433: hsl(192, 9%, 21%); + --paradiso: hsl(184, 45%, 35%); + --boomtown: hsl(192, 37%, 33%); + --pms3258: hsl(171, 57%, 49%); + --espirit: hsl(186, 21%, 26%); + --oracle: hsl(181, 36%, 34%); + --isobar: hsl(173, 13%, 25%); + --retreat: hsl(187, 46%, 42%); + --william: hsl(185, 30%, 33%); + --hauraki: hsl(167, 14%, 26%); + --sea: hsl(175, 44%, 42%); + --charcoal-grey: hsl(190, 5%, 25%); + --cape-cod: hsl(173, 6%, 25%); + --mica: hsl(167, 7%, 25%); + --landmark: hsl(170, 42%, 42%); + --puerto-rico: hsl(169, 51%, 50%); + --bright-cyan: hsl(180, 99%, 63%); + --timekeeper: hsl(182, 16%, 30%); + --faded-jade: hsl(178, 29%, 37%); + --dark-grayish-cerulean: hsl(193, 15%, 30%); + --dark-grayish-turquoise: hsl(167, 15%, 30%); + --dark-grayish-cyan: hsl(180, 15%, 30%); + --aquarius: hsl(193, 53%, 52%); + --wot-eva: hsl(189, 41%, 45%); + --pms432: hsl(189, 9%, 29%); + --green-meets-blue: hsl(172, 14%, 31%); + --balderdash: hsl(189, 12%, 31%); + --pms3255: hsl(171, 64%, 56%); + --such-fun: hsl(186, 40%, 47%); + --tax-break: hsl(188, 18%, 35%); + --hippie-blue: hsl(193, 36%, 45%); + --smalt-blue: hsl(190, 17%, 35%); + --dark-green-copper: hsl(169, 23%, 38%); + --moderate-cerulean: hsl(195, 39%, 47%); + --moderate-arctic-blue: hsl(188, 39%, 47%); + --moderate-turquoise: hsl(165, 39%, 47%); + --moderate-opal: hsl(172, 39%, 47%); + --dusty-teal: hsl(170, 31%, 43%); + --pms319: hsl(181, 59%, 56%); + --viking: hsl(191, 53%, 54%); + --limed-spruce: hsl(173, 10%, 34%); + --streetwise: hsl(194, 18%, 38%); + --odyssey: hsl(172, 16%, 37%); + --cutty-sark: hsl(174, 19%, 39%); + --breaker-bay: hsl(176, 21%, 40%); + --toto: hsl(191, 37%, 50%); + --pms2985: hsl(194, 71%, 60%); + --brilliant-cerulean: hsl(195, 76%, 61%); + --brilliant-arctic-blue: hsl(187, 76%, 61%); + --brilliant-turquoise: hsl(165, 76%, 61%); + --brilliant-opal: hsl(173, 76%, 61%); + --green-copper: hsl(168, 22%, 41%); + --dark-cyanish-grey: hsl(180, 3%, 34%); + --dark-slate-grey: hsl(180, 26%, 43%); + --patriot: hsl(180, 30%, 44%); + --moderate-cyan: hsl(180, 39%, 47%); + --sabbatical: hsl(187, 17%, 40%); + --pms631: hsl(188, 50%, 55%); + --half-baked: hsl(184, 27%, 45%); + --fountain-blue: hsl(186, 44%, 54%); + --pms325: hsl(176, 52%, 56%); + --pms3252: hsl(174, 61%, 59%); + --imprint: hsl(166, 12%, 41%); + --gateway: hsl(190, 11%, 41%); + --half-smalt-blue: hsl(187, 15%, 44%); + --pms549: hsl(193, 31%, 52%); + --pms333: hsl(167, 65%, 62%); + --dull-teal: hsl(166, 25%, 50%); + --tradewind: hsl(175, 36%, 54%); + --pms5483: hsl(180, 20%, 47%); + --obelisk: hsl(186, 9%, 42%); + --pale-sky: hsl(194, 6%, 41%); + --undercover: hsl(174, 16%, 46%); + --wishlist: hsl(184, 19%, 49%); + --parachute: hsl(194, 54%, 61%); + --light-brilliant-arctic-blue: hsl(187, 100%, 70%); + --light-brilliant-opal: hsl(173, 100%, 70%); + --bounce: hsl(181, 18%, 49%); + --gothic: hsl(192, 16%, 49%); + --infinity: hsl(195, 5%, 44%); + --paradise: hsl(172, 20%, 51%); + --pms637: hsl(190, 61%, 64%); + --rolling-stone: hsl(169, 5%, 45%); + --juniper: hsl(180, 15%, 50%); + --pale-turquoise: hsl(180, 15%, 47%); + --robin: hsl(187, 97%, 71%); + --meltwater: hsl(193, 39%, 59%); + --downy: hsl(173, 51%, 63%); + --pms305: hsl(191, 66%, 66%); + --gumbo: hsl(170, 12%, 50%); + --refresh: hsl(192, 46%, 62%); + --aquamarine-blue: hsl(185, 66%, 66%); + --pms310: hsl(187, 61%, 66%); + --awash: hsl(194, 24%, 56%); + --gulf-stream: hsl(170, 29%, 58%); + --neptune: hsl(183, 24%, 57%); + --sea-nymph: hsl(170, 19%, 55%); + --kumutoto: hsl(183, 27%, 58%); + --glacier: hsl(192, 36%, 61%); + --spray: hsl(187, 75%, 70%); + --monte-carlo: hsl(166, 39%, 63%); + --pms3248: hsl(168, 50%, 65%); + --grayish-cerulean: hsl(194, 20%, 57%); + --grayish-turquoise: hsl(166, 20%, 57%); + --grayish-cyan: hsl(180, 20%, 57%); + --bermuda: hsl(168, 54%, 67%); + --pms3105: hsl(183, 56%, 68%); + --metamorphis: hsl(166, 13%, 56%); + --oslo-grey: hsl(173, 3%, 52%); + --ziggurat: hsl(186, 19%, 59%); + --onepoto: hsl(179, 48%, 67%); + --crescent: hsl(183, 8%, 55%); + --pms3242: hsl(172, 56%, 70%); + --quicksilver: hsl(170, 8%, 57%); + --destiny: hsl(177, 10%, 58%); + --forcefield: hsl(171, 6%, 56%); + --riptide: hsl(167, 51%, 69%); + --half-innocence: hsl(166, 6%, 57%); + --allusive: hsl(175, 5%, 57%); + --cascade: hsl(172, 15%, 60%); + --light-cerulean: hsl(195, 66%, 73%); + --light-arctic-blue: hsl(187, 66%, 73%); + --light-opal: hsl(173, 66%, 73%); + --submarine: hsl(180, 7%, 58%); + --pms5493: hsl(177, 18%, 62%); + --pms630: hsl(186, 45%, 69%); + --renew: hsl(166, 48%, 70%); + --pms3245: hsl(169, 58%, 71%); + --boulevard: hsl(167, 11%, 60%); + --moby: hsl(195, 27%, 65%); + --bounty: hsl(184, 7%, 60%); + --dusted-blue: hsl(191, 8%, 60%); + --botticelli: hsl(194, 18%, 64%); + --pms318: hsl(178, 52%, 72%); + --triple-surrender: hsl(195, 2%, 61%); + --pms636: hsl(186, 50%, 73%); + --sorrento: hsl(169, 12%, 65%); + --cyanish-grey: hsl(180, 6%, 64%); + --half-kumutoto: hsl(183, 30%, 70%); + --escape: hsl(194, 29%, 71%); + --morning-glory: hsl(182, 38%, 72%); + --very-light-cerulean: hsl(195, 100%, 81%); + --very-light-arctic-blue: hsl(187, 100%, 81%); + --very-light-turquoise: hsl(165, 100%, 81%); + --very-light-opal: hsl(173, 100%, 81%); + --chi: hsl(185, 22%, 69%); + --sinbad: hsl(176, 41%, 73%); + --conch: hsl(169, 10%, 66%); + --regent-st-blue: hsl(193, 43%, 74%); + --hit-grey: hsl(173, 4%, 65%); + --water-leaf: hsl(171, 62%, 77%); + --eskimo: hsl(195, 15%, 68%); + --pms551: hsl(193, 26%, 71%); + --french-pass: hsl(194, 49%, 76%); + --charlotte: hsl(189, 57%, 77%); + --pms304: hsl(185, 51%, 77%); + --casper: hsl(193, 9%, 69%); + --coastal-blue: hsl(194, 11%, 70%); + --pms5503: hsl(168, 18%, 72%); + --pms324: hsl(172, 43%, 77%); + --scandal: hsl(169, 37%, 76%); + --pms5435: hsl(191, 11%, 72%); + --jet-stream: hsl(172, 24%, 77%); + --pale-light-grayish-cerulean: hsl(194, 49%, 81%); + --pale-light-grayish-turquoise: hsl(166, 49%, 81%); + --quarter-surrender: hsl(180, 2%, 84%); + --pms5445: hsl(180, 7%, 78%); + --zircon: hsl(180, 8%, 88%); + --pms642: hsl(180, 8%, 83%); + --zumthor: hsl(180, 9%, 82%); + --jungle-mist: hsl(180, 14%, 73%); + --pms552: hsl(180, 18%, 80%); + --light-cyanish-grey: hsl(180, 21%, 88%); + --pms629: hsl(180, 33%, 77%); + --oyster-bay: hsl(180, 37%, 87%); + --pms635: hsl(180, 38%, 80%); + --mabel: hsl(180, 39%, 85%); + --pale-light-grayish-cyan: hsl(180, 49%, 81%); + --caesar: hsl(180, 58%, 25%); + --maximum-blue-green: hsl(180, 60%, 47%); + --pale-blue: hsl(180, 65%, 81%); + --java: hsl(180, 72%, 44%); + --brilliant-cyan: hsl(180, 76%, 61%); + --very-deep-cyan: hsl(180, 100%, 6%); + --rich-black: hsl(180, 100%, 13%); + --warm-black: hsl(180, 100%, 13%); + --deep-cyan: hsl(180, 100%, 17%); + --pms322: hsl(180, 100%, 22%); + --skobeloff: hsl(180, 100%, 23%); + --teal: hsl(180, 100%, 25%); + --dark-cyan: hsl(180, 100%, 27%); + --strong-cyan: hsl(180, 100%, 33%); + --robin-egg-blue: hsl(180, 100%, 40%); + --cyan: hsl(180, 100%, 40%); + --vivid-cyan: hsl(180, 100%, 45%); + --aqua: hsl(180, 100%, 50%); + --light-brilliant-cyan: hsl(180, 100%, 70%); + --very-light-cyan: hsl(180, 100%, 81%); + --celeste: hsl(180, 100%, 85%); + --light-cyan: hsl(180, 100%, 94%); + --azure-web-color: hsl(180, 100%, 97%); + --pms2975: hsl(183, 41%, 81%); + --pale-sky-blue: hsl(187, 97%, 87%); + --quarter-powder-blue: hsl(192, 8%, 76%); + --reservoir: hsl(170, 38%, 82%); + --triple-athens-grey: hsl(195, 3%, 77%); + --onahau: hsl(189, 53%, 84%); + --jagged-ice: hsl(175, 45%, 84%); + --pale-arctic-blue: hsl(188, 100%, 88%); + --pale-opal: hsl(172, 100%, 88%); + --mint-tulip: hsl(169, 69%, 86%); + --eggshell-blue: hsl(172, 100%, 88%); + --cut-glass: hsl(183, 21%, 83%); + --geyser: hsl(168, 5%, 81%); + --breeze: hsl(172, 17%, 83%); + --pms628: hsl(166, 28%, 84%); + --foam: hsl(175, 38%, 87%); + --really-light-blue: hsl(180, 100%, 92%); + --ice: hsl(173, 100%, 92%); + --very-pale-blue: hsl(179, 100%, 92%); + --ice-blue: hsl(179, 100%, 92%); + --frosted-mint: hsl(168, 100%, 93%); + --very-pale-cerulean: hsl(194, 100%, 94%); + --very-pale-turquoise: hsl(166, 100%, 94%); + --very-pale-cyan: hsl(180, 100%, 94%); + --cyanish-white: hsl(180, 100%, 98%); + --absolute-zero: hsl(217, 100%, 36%); + --aero: hsl(206, 70%, 70%); + --air-force-blue-raf: hsl(204, 30%, 51%); + --air-force-blue-usaf: hsl(220, 100%, 28%); + --air-superiority-blue: hsl(205, 39%, 60%); + --alice-blue: hsl(208, 100%, 97%); + --anti-flash-white: hsl(210, 8%, 95%); + --arsenic: hsl(206, 12%, 26%); + --azure: hsl(210, 100%, 50%); + --azureish-white: hsl(206, 53%, 91%); + --baby-blue: hsl(199, 77%, 74%); + --baby-blue-eyes: hsl(209, 74%, 79%); + --beau-blue: hsl(206, 46%, 82%); + --b-dazzled-blue: hsl(215, 53%, 38%); + --black-coral: hsl(209, 14%, 38%); + --bleu-de-france: hsl(210, 79%, 55%); + --blue-crayola: hsl(217, 99%, 56%); + --blue-ncs: hsl(197, 100%, 37%); + --blue-ryb: hsl(224, 99%, 50%); + --blue-bolt: hsl(196, 100%, 49%); + --blue-gray: hsl(210, 50%, 60%); + --blue-jeans: hsl(206, 79%, 65%); + --blue-sapphire: hsl(197, 75%, 29%); + --blue-yonder: hsl(217, 35%, 48%); + --blueberry: hsl(220, 91%, 64%); + --brandeis-blue: hsl(214, 100%, 50%); + --bright-navy-blue: hsl(210, 79%, 46%); + --brilliant-azure: hsl(210, 100%, 60%); + --button-blue: hsl(203, 85%, 54%); + --cadet: hsl(199, 16%, 39%); + --cadet-grey: hsl(205, 16%, 63%); + --capri: hsl(195, 100%, 50%); + --carolina-blue: hsl(204, 59%, 58%); + --catalina-blue: hsl(221, 90%, 25%); + --celadon-blue: hsl(196, 100%, 33%); + --celestial-blue: hsl(205, 59%, 55%); + --cerulean-blue: hsl(224, 64%, 45%); + --cerulean-frost: hsl(208, 42%, 60%); + --cg-blue: hsl(196, 100%, 32%); + --charcoal: hsl(204, 19%, 26%); + --cobalt-blue: hsl(215, 100%, 34%); + --columbia-blue: hsl(200, 34%, 83%); + --cool-black: hsl(212, 100%, 19%); + --cornflower-blue: hsl(219, 79%, 66%); + --cyan-azure: hsl(209, 40%, 51%); + --cyan-blue-azure: hsl(210, 49%, 51%); + --cyan-cobalt-blue: hsl(215, 59%, 38%); + --cyan-cornflower-blue: hsl(199, 78%, 43%); + --dark-cerulean: hsl(209, 88%, 26%); + --dark-electric-blue: hsl(206, 18%, 40%); + --dark-gunmetal: hsl(202, 15%, 14%); + --light-imperial-blue-: hsl(203, 100%, 21%); + --dark-midnight-blue: hsl(210, 100%, 20%); + --dark-pastel-blue: hsl(212, 45%, 63%); + --dark-powder-blue: hsl(220, 100%, 30%); + --dark-sky-blue: hsl(199, 47%, 69%); + --denim: hsl(213, 80%, 41%); + --dodger-blue: hsl(210, 100%, 56%); + --french-blue: hsl(203, 100%, 37%); + --french-sky-blue: hsl(212, 99%, 73%); + --fresh-air: hsl(196, 100%, 83%); + --glaucous: hsl(216, 37%, 55%); + --green-blue: hsl(209, 83%, 39%); + --gunmetal: hsl(200, 15%, 19%); + --han-blue: hsl(223, 59%, 54%); + --honolulu-blue: hsl(203, 100%, 35%); + --iceberg: hsl(207, 52%, 63%); + --international-klein-blue: hsl(223, 100%, 33%); + --jordy-blue: hsl(213, 79%, 74%); + --lapis-lazuli: hsl(210, 61%, 38%); + --light-cobalt-blue: hsl(215, 59%, 71%); + --light-cornflower-blue: hsl(201, 67%, 75%); + --light-sky-blue: hsl(203, 92%, 75%); + --light-slate-gray: hsl(210, 14%, 53%); + --light-steel-blue: hsl(214, 41%, 78%); + --little-boy-blue: hsl(212, 62%, 64%); + --maastricht-blue: hsl(212, 100%, 12%); + --maya-blue: hsl(205, 94%, 72%); + --medium-electric-blue: hsl(209, 96%, 30%); + --medium-persian-blue: hsl(203, 100%, 32%); + --moonstone-blue: hsl(199, 39%, 61%); + --new-car: hsl(223, 71%, 45%); + --ocean-boat-blue: hsl(202, 100%, 37%); + --oxford-blue: hsl(212, 100%, 14%); + --pale-cerulean: hsl(205, 55%, 75%); + --pale-cyan: hsl(200, 89%, 75%); + --pastel-blue: hsl(196, 26%, 75%); + --pewter-blue: hsl(200, 23%, 63%); + --picton-blue: hsl(200, 78%, 59%); + --prussian-blue: hsl(205, 100%, 16%); + --queen-blue: hsl(211, 38%, 42%); + --resolution-blue: hsl(224, 100%, 26%); + --rich-black-fogra29: hsl(207, 90%, 4%); + --rich-electric-blue: hsl(199, 93%, 42%); + --roman-silver: hsl(221, 8%, 55%); + --royal-azure: hsl(220, 100%, 33%); + --royal-blue: hsl(219, 100%, 20%); + --royal-blue-light: hsl(225, 73%, 57%); + --sapphire: hsl(216, 85%, 39%); + --sea-blue: hsl(197, 100%, 29%); + --shadow-blue: hsl(214, 20%, 56%); + --silver-lake-blue: hsl(212, 40%, 55%); + --silver-sand: hsl(200, 2%, 75%); + --sky-blue: hsl(197, 71%, 73%); + --slate-gray: hsl(210, 13%, 50%); + --rich-black-fogra39: hsl(210, 50%, 1%); + --pale-cornflower-blue: hsl(210, 68%, 80%); + --spanish-blue: hsl(203, 100%, 36%); + --spiro-disco-ball: hsl(195, 98%, 52%); + --star-command-blue: hsl(200, 100%, 36%); + --steel-blue: hsl(207, 44%, 49%); + --true-blue: hsl(207, 100%, 41%); + --tufts-blue: hsl(210, 71%, 56%); + --ua-blue: hsl(222, 100%, 33%); + --ucla-blue: hsl(221, 28%, 45%); + --united-nations-blue: hsl(216, 73%, 63%); + --usafa-blue: hsl(209, 100%, 30%); + --very-light-azure: hsl(208, 94%, 72%); + --vista-blue: hsl(218, 55%, 67%); + --vivid-cerulean: hsl(197, 100%, 47%); + --weldon-blue: hsl(204, 22%, 58%); + --winter-wizard: hsl(196, 100%, 81%); + --yale-blue: hsl(212, 81%, 32%); + --yankees-blue: hsl(221, 40%, 18%); + --science-blue: hsl(210, 100%, 40%); + --blue-ribbon: hsl(216, 100%, 50%); + --deep-sky-blue: hsl(195, 100%, 27%); + --captain-cook: hsl(200, 100%, 30%); + --strong-cornflower-blue: hsl(203, 100%, 33%); + --yeehaa: hsl(197, 100%, 30%); + --pms3015: hsl(197, 100%, 31%); + --pms300: hsl(205, 100%, 39%); + --vivid-azure: hsl(210, 100%, 45%); + --allports: hsl(197, 100%, 32%); + --lochmara: hsl(202, 100%, 39%); + --pms299-2x: hsl(203, 100%, 40%); + --luminous-vivid-azure: hsl(210, 100%, 50%); + --pms3005: hsl(201, 100%, 39%); + --very-deep-azure: hsl(211, 100%, 6%); + --pms2925: hsl(200, 100%, 42%); + --vivid-cornflower-blue: hsl(202, 100%, 45%); + --luminous-vivid-cornflower-blue: hsl(203, 100%, 50%); + --pms299: hsl(196, 100%, 43%); + --deep-cobalt-blue: hsl(218, 100%, 17%); + --pms289: hsl(209, 100%, 14%); + --pms282: hsl(213, 100%, 16%); + --pms281: hsl(217, 100%, 20%); + --strong-sapphire-blue: hsl(225, 100%, 33%); + --pms280: hsl(220, 100%, 25%); + --pms296: hsl(202, 100%, 14%); + --deep-azure: hsl(210, 100%, 17%); + --pms539: hsl(201, 100%, 14%); + --pms648: hsl(209, 100%, 18%); + --pms288: hsl(216, 100%, 25%); + --pms2965: hsl(200, 100%, 15%); + --pms540: hsl(206, 100%, 18%); + --pms295: hsl(209, 100%, 21%); + --pms287: hsl(217, 100%, 29%); + --deep-cornflower-blue: hsl(202, 100%, 17%); + --whale-tail: hsl(207, 100%, 20%); + --vivid-sapphire-blue: hsl(225, 100%, 45%); + --pms2955: hsl(206, 100%, 21%); + --pms541: hsl(208, 100%, 23%); + --pms294: hsl(212, 100%, 26%); + --strong-cobalt-blue: hsl(218, 100%, 33%); + --luminous-vivid-sapphire-blue: hsl(225, 100%, 50%); + --pms302: hsl(197, 100%, 21%); + --pms293: hsl(214, 100%, 36%); + --pms2945: hsl(209, 100%, 31%); + --strong-azure: hsl(210, 100%, 33%); + --medium-teal-blue: hsl(212, 100%, 35%); + --endeavour: hsl(209, 100%, 33%); + --vivid-cobalt-blue: hsl(217, 100%, 45%); + --pms301: hsl(204, 100%, 30%); + --pms2935: hsl(211, 100%, 37%); + --luminous-vivid-cobalt-blue: hsl(217, 100%, 50%); + --bright-blue: hsl(216, 99%, 50%); + --peacock-blue: hsl(199, 99%, 29%); + --blue-charcoal: hsl(211, 93%, 5%); + --marine-blue: hsl(209, 98%, 21%); + --astronaut-blue: hsl(202, 98%, 19%); + --regal-blue: hsl(205, 98%, 21%); + --darkish-blue: hsl(210, 98%, 26%); + --deep-sea-blue: hsl(201, 98%, 26%); + --orient: hsl(198, 99%, 26%); + --pms5395: hsl(199, 93%, 12%); + --bahama-blue: hsl(200, 97%, 30%); + --tangaroa: hsl(220, 90%, 12%); + --green-vogue: hsl(210, 93%, 17%); + --black-pearl: hsl(210, 79%, 7%); + --blue-whale: hsl(205, 90%, 16%); + --marine: hsl(213, 92%, 20%); + --venice-blue: hsl(202, 93%, 28%); + --tarawera: hsl(198, 84%, 17%); + --deep-sapphire: hsl(222, 86%, 22%); + --downriver: hsl(221, 81%, 19%); + --madison: hsl(220, 82%, 20%); + --twilight-blue: hsl(209, 85%, 26%); + --woodsmoke: hsl(220, 11%, 5%); + --pms655: hsl(224, 71%, 16%); + --bunker: hsl(216, 28%, 7%); + --water-blue: hsl(202, 87%, 43%); + --pms654: hsl(218, 72%, 21%); + --nice-blue: hsl(200, 83%, 38%); + --very-dark-azure: hsl(210, 26%, 9%); + --pms2768: hsl(225, 65%, 19%); + --magnum: hsl(206, 48%, 13%); + --submerge: hsl(217, 75%, 26%); + --barometer: hsl(199, 63%, 18%); + --elephant: hsl(202, 60%, 17%); + --blue-zodiac: hsl(220, 60%, 19%); + --pms2767: hsl(221, 51%, 16%); + --tory-blue: hsl(216, 79%, 37%); + --guru: hsl(199, 66%, 24%); + --light-navy: hsl(208, 73%, 30%); + --big-stone: hsl(211, 49%, 17%); + --apollo-blue: hsl(214, 65%, 25%); + --elvis: hsl(217, 75%, 35%); + --billabong: hsl(203, 48%, 17%); + --chathams-blue: hsl(202, 68%, 28%); + --blumine: hsl(201, 67%, 29%); + --regatta: hsl(216, 49%, 19%); + --into-the-blue: hsl(217, 61%, 25%); + --nile-blue: hsl(208, 53%, 21%); + --fun-blue: hsl(213, 74%, 38%); + --matisse: hsl(206, 71%, 36%); + --dark: hsl(215, 29%, 15%); + --biscay: hsl(221, 57%, 25%); + --chimney-sweep: hsl(220, 5%, 12%); + --freefall: hsl(198, 75%, 45%); + --azul: hsl(221, 84%, 52%); + --shark: hsl(223, 9%, 16%); + --daytona: hsl(223, 19%, 15%); + --style-pasifika-ocean-deep: hsl(206, 33%, 18%); + --cello: hsl(214, 50%, 24%); + --cobalt: hsl(218, 65%, 34%); + --blue-night: hsl(225, 31%, 18%); + --dark-blue-grey: hsl(203, 43%, 21%); + --cloud-burst: hsl(224, 45%, 23%); + --yarra: hsl(205, 63%, 34%); + --shipshape: hsl(208, 48%, 25%); + --crescendo: hsl(217, 33%, 20%); + --indian-ink: hsl(224, 18%, 17%); + --dark-knight: hsl(208, 21%, 17%); + --clear-blue: hsl(216, 98%, 57%); + --cinder: hsl(204, 12%, 16%); + --allegro: hsl(214, 24%, 19%); + --coast: hsl(208, 29%, 20%); + --curious-blue: hsl(201, 70%, 48%); + --aquarium: hsl(201, 32%, 21%); + --wet-n-wild: hsl(218, 52%, 30%); + --zoop-de-loop: hsl(219, 56%, 33%); + --limitless: hsl(212, 52%, 30%); + --dusk-blue: hsl(214, 58%, 35%); + --pms647: hsl(208, 53%, 32%); + --mid-blue: hsl(211, 64%, 43%); + --wine-trail: hsl(220, 7%, 16%); + --tornado: hsl(223, 21%, 19%); + --pms433-2x: hsl(223, 26%, 5%); + --dark-sapphire-blue: hsl(224, 39%, 25%); + --dark-cobalt-blue: hsl(217, 39%, 25%); + --blue-clouds: hsl(215, 40%, 25%); + --flat-medium-blue: hsl(225, 56%, 35%); + --dark-azure: hsl(210, 39%, 25%); + --dark-cornflower-blue: hsl(203, 39%, 25%); + --mariner: hsl(216, 67%, 48%); + --double-foundry: hsl(210, 5%, 16%); + --midnight-oil: hsl(218, 35%, 24%); + --wanaka: hsl(206, 42%, 27%); + --bluish: hsl(208, 64%, 45%); + --mosaic: hsl(205, 23%, 21%); + --dark-grey-blue: hsl(205, 38%, 26%); + --blueprint: hsl(220, 20%, 21%); + --optimist: hsl(203, 53%, 36%); + --foundry: hsl(220, 6%, 18%); + --filmpro-ultramarine-blue: hsl(223, 42%, 30%); + --bellbottom-blue: hsl(210, 42%, 30%); + --warrior: hsl(200, 19%, 22%); + --st-tropaz: hsl(218, 55%, 39%); + --spray-drift: hsl(205, 45%, 32%); + --rhino: hsl(220, 36%, 28%); + --lucifer: hsl(199, 35%, 28%); + --light-navy-blue: hsl(211, 49%, 36%); + --lure: hsl(205, 56%, 42%); + --double-tuna: hsl(218, 8%, 20%); + --spinnaker: hsl(207, 37%, 29%); + --gotham: hsl(207, 17%, 23%); + --san-juan: hsl(212, 38%, 30%); + --navigate: hsl(201, 32%, 28%); + --marathon: hsl(196, 35%, 29%); + --ugly-blue: hsl(204, 48%, 37%); + --calypso: hsl(198, 48%, 37%); + --grey-friars: hsl(204, 5%, 20%); + --atomic: hsl(212, 29%, 27%); + --astral: hsl(199, 52%, 41%); + --bright-charcoal: hsl(210, 2%, 20%); + --tao-grey: hsl(210, 4%, 20%); + --high-tide: hsl(217, 12%, 22%); + --peacock: hsl(196, 60%, 49%); + --a-b-sea: hsl(218, 44%, 36%); + --pms653: hsl(215, 45%, 36%); + --pms533: hsl(224, 26%, 28%); + --avalanche: hsl(215, 21%, 26%); + --chambray: hsl(223, 45%, 38%); + --filmpro-sky-blue: hsl(214, 46%, 39%); + --majestic-blue: hsl(201, 16%, 25%); + --undercurrent: hsl(198, 33%, 32%); + --windows-blue: hsl(211, 55%, 48%); + --atom: hsl(204, 4%, 23%); + --super-sonic: hsl(224, 30%, 31%); + --superhero: hsl(223, 42%, 37%); + --explorer: hsl(199, 24%, 28%); + --summer-sky: hsl(197, 72%, 55%); + --primetime: hsl(209, 50%, 44%); + --new-denim-blue: hsl(210, 12%, 25%); + --dark-slate: hsl(203, 17%, 27%); + --pms285: hsl(214, 54%, 50%); + --wind-talker: hsl(213, 21%, 29%); + --pms534: hsl(224, 33%, 34%); + --muted-blue: hsl(208, 46%, 43%); + --boston-blue: hsl(197, 51%, 47%); + --ivanhoe: hsl(204, 19%, 29%); + --wavelength: hsl(204, 38%, 38%); + --flat-blue: hsl(209, 47%, 45%); + --lightish-blue: hsl(221, 98%, 62%); + --style-pasifika-blue-whale: hsl(224, 33%, 35%); + --waterfront: hsl(199, 43%, 43%); + --half-foundry: hsl(214, 5%, 26%); + --liquid-metal: hsl(220, 7%, 26%); + --dirty-blue: hsl(197, 43%, 43%); + --pms5405: hsl(203, 30%, 35%); + --shapeshifter: hsl(221, 13%, 29%); + --jetsetter: hsl(203, 17%, 30%); + --fiord: hsl(215, 24%, 33%); + --endorphin: hsl(196, 45%, 47%); + --dark-grayish-sapphire-blue: hsl(224, 15%, 30%); + --dark-grayish-azure: hsl(209, 15%, 30%); + --quayside: hsl(223, 26%, 35%); + --mollusc: hsl(218, 6%, 28%); + --river-bed: hsl(215, 14%, 31%); + --mako: hsl(221, 11%, 30%); + --san-marino: hsl(217, 43%, 47%); + --skydiver: hsl(217, 54%, 53%); + --dalek: hsl(212, 19%, 35%); + --dusky-blue: hsl(221, 35%, 43%); + --bismark: hsl(197, 26%, 38%); + --norwester: hsl(195, 31%, 41%); + --blue-bayoux: hsl(204, 25%, 38%); + --dull-blue: hsl(208, 36%, 45%); + --cool-blue: hsl(208, 44%, 50%); + --abbey: hsl(196, 7%, 31%); + --moderate-cobalt-blue: hsl(218, 39%, 47%); + --moderate-azure: hsl(210, 39%, 47%); + --moderate-cornflower-blue: hsl(202, 39%, 47%); + --trout: hsl(225, 10%, 32%); + --compass: hsl(207, 13%, 34%); + --wedgewood: hsl(209, 28%, 42%); + --float: hsl(213, 50%, 53%); + --seachange: hsl(202, 25%, 41%); + --hemisphere: hsl(202, 44%, 52%); + --shakespeare: hsl(197, 59%, 56%); + --quantum-leap: hsl(214, 28%, 43%); + --metallic-blue: hsl(206, 29%, 43%); + --half-grey-friars: hsl(210, 4%, 32%); + --pickled-bluewood: hsl(199, 9%, 34%); + --kashmir-blue: hsl(213, 30%, 45%); + --stormy-blue: hsl(206, 32%, 46%); + --snapshot: hsl(201, 13%, 36%); + --brilliant-sapphire-blue: hsl(225, 76%, 61%); + --brilliant-cobalt-blue: hsl(218, 76%, 61%); + --brilliant-cornflower-blue: hsl(202, 76%, 61%); + --pms298: hsl(198, 70%, 60%); + --haast-shale: hsl(224, 10%, 35%); + --hammerhead: hsl(225, 13%, 36%); + --anchor: hsl(223, 38%, 51%); + --quarter-foundry: hsl(204, 3%, 33%); + --breakwater: hsl(220, 28%, 45%); + --half-new-denim-blue: hsl(208, 9%, 36%); + --lifesaver: hsl(225, 21%, 41%); + --waratah: hsl(218, 24%, 44%); + --havelock-blue: hsl(213, 63%, 59%); + --landscape-grey: hsl(210, 2%, 34%); + --half-tuna: hsl(214, 4%, 35%); + --off-blue: hsl(209, 35%, 51%); + --silvered-grey: hsl(219, 8%, 36%); + --norwegian-blue: hsl(223, 20%, 43%); + --slate-grey: hsl(204, 10%, 39%); + --kingfisher-blue: hsl(220, 22%, 45%); + --panorama: hsl(215, 26%, 47%); + --quadrant-grey: hsl(223, 9%, 38%); + --waikawa-grey: hsl(222, 27%, 48%); + --dusty-blue: hsl(208, 34%, 52%); + --horizon: hsl(201, 28%, 49%); + --danube: hsl(213, 44%, 55%); + --subzero: hsl(209, 43%, 55%); + --greyish-blue: hsl(207, 25%, 49%); + --pms646: hsl(209, 27%, 50%); + --quarter-grey-friars: hsl(213, 5%, 39%); + --shuttle-grey: hsl(218, 9%, 41%); + --elevate: hsl(209, 18%, 46%); + --pms5415: hsl(202, 19%, 46%); + --blue-grey: hsl(203, 19%, 47%); + --pms2915: hsl(202, 65%, 62%); + --nevada: hsl(205, 8%, 43%); + --hoki: hsl(196, 15%, 46%); + --soft-blue: hsl(224, 76%, 65%); + --quarter-tuna: hsl(213, 5%, 42%); + --faded-blue: hsl(213, 39%, 56%); + --light-brilliant-cobalt-blue: hsl(217, 100%, 70%); + --light-brilliant-azure: hsl(210, 100%, 70%); + --light-brilliant-cornflower-blue: hsl(203, 100%, 70%); + --light-brilliant-cerulean: hsl(195, 100%, 70%); + --pms431: hsl(198, 5%, 42%); + --escapade: hsl(209, 17%, 48%); + --pms279: hsl(219, 50%, 60%); + --pms542: hsl(209, 39%, 57%); + --malibu: hsl(200, 67%, 64%); + --weathered-blue: hsl(210, 12%, 46%); + --lynch: hsl(203, 13%, 47%); + --tsunami: hsl(204, 16%, 50%); + --bermuda-grey: hsl(205, 23%, 53%); + --grey-blue: hsl(206, 24%, 53%); + --pms652: hsl(214, 25%, 54%); + --raven: hsl(215, 5%, 46%); + --bluff: hsl(196, 9%, 49%); + --masquerade: hsl(225, 36%, 59%); + --blue-moon: hsl(202, 25%, 56%); + --steel: hsl(208, 14%, 52%); + --bluish-grey: hsl(201, 14%, 52%); + --scotty-silver: hsl(208, 16%, 54%); + --pms284: hsl(209, 59%, 66%); + --pms292: hsl(205, 60%, 66%); + --abacus: hsl(201, 12%, 52%); + --pigeon-post: hsl(206, 9%, 51%); + --pms645: hsl(208, 28%, 58%); + --greyblue: hsl(199, 30%, 59%); + --seagull: hsl(197, 49%, 64%); + --ship-cove: hsl(223, 32%, 60%); + --regent-grey: hsl(196, 6%, 50%); + --eighth-tuna: hsl(213, 4%, 50%); + --lightblue: hsl(202, 87%, 72%); + --delta-blue: hsl(218, 45%, 65%); + --grayish-sapphire-blue: hsl(225, 20%, 57%); + --grayish-azure: hsl(209, 20%, 57%); + --revolution: hsl(212, 5%, 52%); + --sword: hsl(210, 2%, 51%); + --zephyr: hsl(218, 38%, 64%); + --pms297: hsl(198, 62%, 70%); + --sky: hsl(205, 95%, 75%); + --pms5425: hsl(202, 15%, 58%); + --bali-hai: hsl(201, 18%, 59%); + --neutral-bay: hsl(216, 9%, 56%); + --bluegrey: hsl(200, 23%, 61%); + --pms550: hsl(197, 30%, 64%); + --exponent: hsl(214, 7%, 56%); + --blake: hsl(211, 37%, 66%); + --clouded-blue: hsl(198, 6%, 56%); + --bluey-grey: hsl(205, 20%, 61%); + --polo-blue: hsl(214, 39%, 67%); + --light-sapphire-blue: hsl(225, 66%, 73%); + --light-azure: hsl(210, 66%, 73%); + --instinct: hsl(201, 8%, 58%); + --anakiwa: hsl(198, 69%, 73%); + --voltage: hsl(214, 3%, 57%); + --tiebreaker: hsl(221, 15%, 61%); + --nepal: hsl(206, 29%, 66%); + --amber-grey: hsl(200, 3%, 58%); + --el-nino: hsl(208, 14%, 62%); + --half-regent-grey: hsl(197, 7%, 60%); + --smokescreen: hsl(215, 20%, 65%); + --rock-blue: hsl(217, 22%, 65%); + --pms543: hsl(205, 40%, 70%); + --pms2905: hsl(200, 55%, 73%); + --relax: hsl(217, 37%, 71%); + --pms278: hsl(211, 50%, 73%); + --pms535: hsl(223, 16%, 66%); + --pms651: hsl(215, 22%, 68%); + --pms644: hsl(211, 26%, 69%); + --oxymoron: hsl(210, 56%, 75%); + --gull-grey: hsl(205, 15%, 67%); + --frozen: hsl(203, 26%, 70%); + --light-grey-blue: hsl(206, 39%, 72%); + --silver-aluminium: hsl(200, 2%, 63%); + --very-light-cobalt-blue: hsl(218, 100%, 81%); + --very-light-cornflower-blue: hsl(202, 100%, 81%); + --grey-chateau: hsl(210, 4%, 64%); + --forecast: hsl(208, 9%, 66%); + --comfort-zone: hsl(211, 35%, 73%); + --freestyling: hsl(220, 7%, 67%); + --echo-blue: hsl(224, 29%, 72%); + --mischka: hsl(222, 8%, 67%); + --pms2717: hsl(219, 49%, 76%); + --sail: hsl(205, 65%, 79%); + --shinto: hsl(212, 22%, 71%); + --double-surrender: hsl(200, 2%, 66%); + --pms291: hsl(201, 50%, 77%); + --icebreaker: hsl(214, 23%, 73%); + --perano: hsl(223, 74%, 81%); + --time-out: hsl(215, 50%, 78%); + --metro: hsl(204, 3%, 68%); + --cloudy-blue: hsl(211, 37%, 76%); + --pms536: hsl(225, 14%, 72%); + --longitude: hsl(210, 13%, 72%); + --tropical-blue: hsl(213, 60%, 80%); + --pms2708: hsl(222, 38%, 77%); + --alaska: hsl(224, 21%, 75%); + --spindle: hsl(212, 32%, 77%); + --pms277: hsl(207, 53%, 81%); + --light-blue-grey: hsl(215, 43%, 80%); + --pms544: hsl(205, 33%, 79%); + --pale-light-grayish-sapphire-blue: hsl(225, 49%, 81%); + --pale-light-grayish-azure: hsl(209, 49%, 81%); + --half-grey-chateau: hsl(214, 5%, 74%); + --half-escape: hsl(195, 45%, 81%); + --oxygen: hsl(215, 24%, 78%); + --altitude: hsl(202, 40%, 81%); + --pms650: hsl(217, 16%, 78%); + --pms2707: hsl(212, 42%, 82%); + --breathless: hsl(215, 16%, 79%); + --pms657: hsl(223, 29%, 81%); + --pale-cobalt-blue: hsl(217, 100%, 88%); + --pale-azure: hsl(210, 100%, 88%); + --periwinkle-grey: hsl(223, 41%, 83%); + --sweetwaters: hsl(210, 30%, 82%); + --pms545: hsl(204, 27%, 82%); + --pms643: hsl(199, 16%, 81%); + --link-water: hsl(219, 18%, 81%); + --hawkes-blue: hsl(222, 43%, 88%); + --dreamer: hsl(201, 47%, 88%); + --half-iron: hsl(200, 4%, 84%); + --pms656: hsl(210, 14%, 86%); + --pattens-blue: hsl(198, 100%, 94%); + --half-breathless: hsl(222, 19%, 90%); + --very-pale-azure: hsl(211, 100%, 94%); + --lily-white: hsl(198, 100%, 95%); + --solitude: hsl(218, 22%, 93%); + --blue-bell: hsl(240, 33%, 73%); + --blue: hsl(240, 100%, 50%); + --blue-pantone: hsl(231, 100%, 33%); + --blue-pigment: hsl(240, 50%, 40%); + --bluebonnet: hsl(240, 88%, 53%); + --ceil: hsl(225, 39%, 69%); + --cool-grey: hsl(229, 16%, 61%); + --cosmic-cobalt: hsl(241, 50%, 35%); + --dark-blue-gray: hsl(240, 20%, 50%); + --dark-blue: hsl(240, 100%, 27%); + --dark-imperial-blue: hsl(230, 100%, 25%); + --dark-slate-blue: hsl(248, 39%, 39%); + --deep-koamaru: hsl(240, 33%, 30%); + --denim-blue: hsl(227, 69%, 42%); + --duke-blue: hsl(240, 100%, 31%); + --egyptian-blue: hsl(226, 82%, 36%); + --electric-ultramarine: hsl(255, 100%, 50%); + --glitter: hsl(234, 67%, 94%); + --imperial-blue: hsl(226, 100%, 29%); + --independence: hsl(231, 18%, 36%); + --indigo-dye: hsl(230, 88%, 30%); + --interdimensional-blue: hsl(253, 89%, 42%); + --iris: hsl(245, 57%, 56%); + --lavender-web: hsl(240, 67%, 94%); + --navy: hsl(240, 100%, 25%); + --medium-blue: hsl(240, 100%, 40%); + --lavender-blue: hsl(240, 100%, 90%); + --ghost-white: hsl(240, 100%, 99%); + --lavender-gray: hsl(245, 12%, 79%); + --liberty: hsl(236, 33%, 49%); + --majorelle-blue: hsl(247, 67%, 59%); + --manatee: hsl(231, 10%, 63%); + --maximum-blue-purple: hsl(240, 54%, 79%); + --medium-slate-blue: hsl(249, 80%, 67%); + --midnight-blue: hsl(240, 64%, 27%); + --ocean-blue: hsl(247, 47%, 48%); + --palatinate-blue: hsl(234, 76%, 52%); + --persian-blue: hsl(229, 74%, 42%); + --phthalo-blue: hsl(233, 100%, 27%); + --plump-purple: hsl(251, 44%, 49%); + --purple-navy: hsl(236, 24%, 40%); + --rhythm: hsl(242, 13%, 53%); + --st-patrick-blue: hsl(236, 55%, 31%); + --slate-blue: hsl(248, 53%, 58%); + --soap: hsl(249, 55%, 86%); + --space-cadet: hsl(226, 47%, 22%); + --toolbox: hsl(246, 40%, 59%); + --ube: hsl(253, 38%, 62%); + --ultramarine-blue: hsl(228, 90%, 61%); + --very-deep-blue: hsl(240, 100%, 6%); + --deep-blue: hsl(240, 100%, 17%); + --strong-blue: hsl(240, 100%, 33%); + --very-light-blue: hsl(240, 100%, 70%); + --violet-blue: hsl(229, 56%, 45%); + --wild-blue-yonder: hsl(226, 33%, 73%); + --zaffre: hsl(233, 100%, 33%); + --very-dark-blue: hsl(239, 100%, 10%); + --deep-phthalo-blue: hsl(233, 100%, 17%); + --navy-blue: hsl(225, 100%, 14%); + --dark-navy-blue: hsl(237, 100%, 9%); + --strong-phthalo-blue: hsl(233, 100%, 33%); + --deep-sapphire-blue: hsl(225, 100%, 17%); + --vivid-phthalo-blue: hsl(232, 100%, 45%); + --luminous-vivid-phthalo-blue: hsl(232, 100%, 50%); + --dark-navy: hsl(235, 100%, 10%); + --midnight-express: hsl(234, 100%, 13%); + --rich-blue: hsl(234, 98%, 49%); + --pure-blue: hsl(240, 98%, 45%); + --dark-royal-blue: hsl(238, 96%, 22%); + --vibrant-blue: hsl(227, 98%, 49%); + --darkblue: hsl(238, 94%, 20%); + --night-blue: hsl(241, 92%, 15%); + --deep-cove: hsl(229, 86%, 14%); + --cove-grey: hsl(228, 89%, 18%); + --primary-blue: hsl(241, 97%, 50%); + --deep-persian-blue: hsl(247, 100%, 17%); + --royal: hsl(235, 85%, 31%); + --pms662: hsl(233, 81%, 25%); + --black-rock: hsl(253, 89%, 10%); + --torea-bay: hsl(227, 83%, 34%); + --vulcan: hsl(231, 29%, 9%); + --arapawa: hsl(243, 80%, 24%); + --ultramarine: hsl(244, 87%, 30%); + --pms2757: hsl(238, 62%, 20%); + --strong-persian-blue: hsl(248, 100%, 33%); + --bunting: hsl(229, 57%, 19%); + --vivid-blue: hsl(234, 100%, 54%); + --deep-indigo: hsl(255, 100%, 17%); + --mirage: hsl(230, 29%, 12%); + --pms2758: hsl(234, 61%, 25%); + --bluish-black: hsl(240, 5%, 11%); + --black-pepper: hsl(240, 26%, 7%); + --lucky-point: hsl(240, 60%, 25%); + --pms2747: hsl(246, 69%, 25%); + --vivid-persian-blue: hsl(248, 100%, 45%); + --nite-life: hsl(230, 28%, 16%); + --pms2748: hsl(241, 62%, 29%); + --surfs-up: hsl(237, 36%, 19%); + --luminous-vivid-persian-blue: hsl(248, 100%, 50%); + --jacksons-purple: hsl(240, 63%, 34%); + --redemption-blue: hsl(236, 33%, 20%); + --confidante: hsl(228, 49%, 27%); + --port-gore: hsl(248, 44%, 22%); + --sonic-boom: hsl(249, 35%, 19%); + --steel-grey: hsl(250, 20%, 17%); + --shadowland: hsl(230, 7%, 16%); + --ebony-clay: hsl(234, 22%, 19%); + --blast-off: hsl(238, 39%, 25%); + --bullitt: hsl(245, 24%, 19%); + --dark-phthalo-blue: hsl(233, 39%, 25%); + --bay-of-many: hsl(227, 54%, 33%); + --quarterback: hsl(231, 20%, 20%); + --astronaut: hsl(226, 50%, 31%); + --double-revolver: hsl(255, 9%, 17%); + --charade: hsl(240, 15%, 19%); + --strong-indigo: hsl(255, 100%, 33%); + --hip-hop: hsl(247, 37%, 23%); + --valhalla: hsl(237, 21%, 21%); + --aviator: hsl(232, 35%, 25%); + --pms2766: hsl(246, 41%, 25%); + --filmpro-pthalo-blue: hsl(225, 38%, 27%); + --blue-gem: hsl(254, 82%, 30%); + --filmpro-digital-blue: hsl(246, 56%, 32%); + --dark-persian-blue: hsl(247, 39%, 25%); + --pms661: hsl(236, 52%, 37%); + --checkmate: hsl(233, 22%, 24%); + --governor-bay: hsl(234, 58%, 44%); + --galactica: hsl(230, 28%, 26%); + --pms2728: hsl(231, 58%, 45%); + --decadence: hsl(235, 36%, 30%); + --pms2756: hsl(249, 49%, 31%); + --woody-bay: hsl(231, 6%, 21%); + --believe: hsl(245, 43%, 33%); + --pms532: hsl(226, 11%, 23%); + --kudos: hsl(237, 45%, 38%); + --wicked: hsl(253, 26%, 25%); + --martinique: hsl(251, 25%, 25%); + --sputnik: hsl(226, 21%, 27%); + --black-marlin: hsl(247, 8%, 23%); + --indigo-blue: hsl(253, 76%, 39%); + --jacarta: hsl(255, 43%, 29%); + --light-royal-blue: hsl(243, 99%, 59%); + --vortex: hsl(243, 24%, 29%); + --bright-grey: hsl(226, 15%, 28%); + --catwalk: hsl(236, 11%, 27%); + --jack-in-the-box: hsl(238, 34%, 36%); + --jelly: hsl(254, 35%, 30%); + --digital-blue: hsl(235, 23%, 32%); + --magik: hsl(226, 33%, 36%); + --pms2746: hsl(253, 57%, 37%); + --minsk: hsl(251, 45%, 34%); + --wave-rider: hsl(243, 27%, 34%); + --enigma: hsl(242, 18%, 38%); + --adventure: hsl(242, 21%, 32%); + --gun-powder: hsl(237, 14%, 30%); + --east-bay: hsl(229, 32%, 37%); + --half-nocturnal: hsl(240, 1%, 27%); + --night-moves: hsl(231, 25%, 36%); + --fairground: hsl(253, 35%, 35%); + --pms2736: hsl(252, 57%, 43%); + --moderate-phthalo-blue: hsl(233, 39%, 47%); + --moderate-sapphire-blue: hsl(225, 39%, 47%); + --warm-blue: hsl(235, 67%, 58%); + --hendrix: hsl(228, 24%, 39%); + --twilight: hsl(237, 28%, 43%); + --dusk: hsl(233, 25%, 41%); + --gypsy-queen: hsl(235, 38%, 49%); + --scarpa-flow: hsl(254, 7%, 36%); + --fascinator: hsl(254, 34%, 38%); + --brilliant-phthalo-blue: hsl(232, 76%, 61%); + --jimmy-dean: hsl(230, 7%, 34%); + --gigas: hsl(255, 42%, 41%); + --blue-with-a-hint-of-purple: hsl(250, 55%, 51%); + --victoria: hsl(252, 36%, 42%); + --dark-bluish-grey: hsl(240, 3%, 34%); + --blurple: hsl(251, 59%, 51%); + --moderate-persian-blue: hsl(247, 39%, 47%); + --abracadabra: hsl(253, 29%, 40%); + --half-baltic-sea: hsl(240, 1%, 34%); + --maltese: hsl(252, 5%, 36%); + --quarter-fuscous-grey: hsl(228, 3%, 36%); + --pms660: hsl(235, 31%, 50%); + --pms2718: hsl(225, 53%, 58%); + --comet: hsl(238, 12%, 41%); + --pms2727: hsl(234, 46%, 57%); + --purpley-blue: hsl(254, 79%, 55%); + --smoky: hsl(253, 12%, 40%); + --purpleish-blue: hsl(251, 85%, 59%); + --moderate-indigo: hsl(255, 39%, 47%); + --bluey-purple: hsl(255, 54%, 52%); + --brilliant-persian-blue: hsl(248, 76%, 61%); + --dolphin: hsl(250, 11%, 42%); + --light-brilliant-phthalo-blue: hsl(233, 100%, 70%); + --light-brilliant-sapphire-blue: hsl(225, 100%, 70%); + --chetwode-blue: hsl(233, 34%, 55%); + --pms2726: hsl(249, 43%, 54%); + --dark-periwinkle: hsl(244, 55%, 60%); + --scampi: hsl(247, 29%, 51%); + --cornflower: hsl(234, 90%, 69%); + --blue-marguerite: hsl(250, 36%, 53%); + --light-indigo: hsl(250, 55%, 58%); + --storm-grey: hsl(231, 9%, 48%); + --waterloo: hsl(240, 7%, 48%); + --catch: hsl(240, 7%, 22%); + --mid-grey: hsl(240, 7%, 40%); + --tuna: hsl(240, 11%, 23%); + --dark-grayish-blue: hsl(240, 15%, 30%); + --dotcom: hsl(240, 18%, 31%); + --corn-flower-blue: hsl(240, 25%, 35%); + --storm: hsl(240, 27%, 29%); + --moderate-blue: hsl(240, 39%, 47%); + --brilliant-blue: hsl(240, 76%, 61%); + --light-brilliant-blue: hsl(240, 100%, 70%); + --light-brilliant-persian-blue: hsl(247, 100%, 70%); + --raincloud: hsl(238, 10%, 53%); + --jumbo: hsl(249, 3%, 50%); + --grayish-blue: hsl(240, 20%, 57%); + --moody-blue: hsl(246, 51%, 65%); + --pms659: hsl(228, 33%, 62%); + --rugged-lavender: hsl(235, 5%, 52%); + --beyond: hsl(226, 21%, 59%); + --kookaburra: hsl(233, 7%, 54%); + --bubblegum: hsl(248, 41%, 63%); + --light-slate: hsl(248, 100%, 72%); + --true-v: hsl(254, 55%, 65%); + --light-brilliant-indigo: hsl(255, 100%, 70%); + --light-phthalo-blue: hsl(233, 66%, 73%); + --magic-carpet: hsl(230, 50%, 70%); + --portage: hsl(228, 74%, 74%); + --periwinkle: hsl(246, 98%, 75%); + --perrywinkle: hsl(242, 65%, 73%); + --periwinkle-blue: hsl(234, 93%, 77%); + --grey-suit: hsl(248, 7%, 60%); + --light-persian-blue: hsl(247, 66%, 73%); + --stratosphere: hsl(230, 36%, 70%); + --santas-grey: hsl(244, 8%, 63%); + --logan: hsl(243, 14%, 66%); + --birdcage: hsl(242, 16%, 66%); + --pms271: hsl(255, 32%, 67%); + --very-light-phthalo-blue: hsl(233, 100%, 81%); + --very-light-sapphire-blue: hsl(225, 100%, 81%); + --lavender: hsl(254, 41%, 69%); + --vision: hsl(253, 13%, 65%); + --wistful: hsl(245, 32%, 71%); + --spun-pearl: hsl(245, 6%, 65%); + --pms2716: hsl(246, 40%, 73%); + --pms658: hsl(228, 37%, 74%); + --dull-lavender: hsl(252, 61%, 75%); + --bauhaus: hsl(233, 34%, 75%); + --very-light-persian-blue: hsl(247, 100%, 81%); + --peekablue: hsl(227, 57%, 79%); + --nemo: hsl(226, 28%, 76%); + --very-light-indigo: hsl(255, 100%, 81%); + --misty-lavender: hsl(255, 3%, 72%); + --morepork: hsl(254, 10%, 74%); + --pale-light-grayish-blue: hsl(240, 49%, 81%); + --blue-haze: hsl(249, 17%, 77%); + --lavender-grey: hsl(244, 26%, 79%); + --french-grey: hsl(240, 7%, 76%); + --poet: hsl(250, 22%, 78%); + --ghost: hsl(248, 7%, 76%); + --heartbreaker: hsl(238, 25%, 81%); + --light-periwinkle: hsl(235, 91%, 87%); + --pale-phthalo-blue: hsl(233, 100%, 88%); + --pale-sapphire-blue: hsl(225, 100%, 88%); + --zappo: hsl(247, 37%, 82%); + --pms537: hsl(228, 9%, 79%); + --fairytale: hsl(245, 24%, 81%); + --pale-persian-blue: hsl(247, 100%, 88%); + --confederate-grey: hsl(240, 22%, 83%); + --pale-indigo: hsl(255, 100%, 88%); + --pms2706: hsl(252, 18%, 84%); + --pms649: hsl(240, 2%, 84%); + --fog: hsl(249, 100%, 91%); + --designer-white: hsl(229, 16%, 86%); + --light-bluish-grey: hsl(240, 21%, 88%); + --very-pale-sapphire-blue: hsl(226, 100%, 94%); + --very-pale-indigo: hsl(254, 100%, 94%); + --pale-grey: hsl(240, 33%, 99%); + --bluish-white: hsl(240, 100%, 98%); + --amethyst: hsl(270, 50%, 60%); + --blue-magenta-violet: hsl(261, 47%, 39%); + --blue-violet: hsl(271, 76%, 53%); + --bright-lavender: hsl(272, 60%, 74%); + --bright-ube: hsl(281, 61%, 77%); + --cyber-grape: hsl(263, 31%, 37%); + --dark-lavender: hsl(270, 31%, 45%); + --dark-orchid: hsl(280, 61%, 50%); + --dark-pastel-purple: hsl(263, 56%, 64%); + --dark-violet: hsl(282, 100%, 41%); + --deep-lilac: hsl(280, 43%, 53%); + --deep-violet: hsl(270, 100%, 20%); + --electric-indigo: hsl(266, 100%, 50%); + --electric-purple: hsl(285, 100%, 50%); + --electric-violet: hsl(274, 100%, 50%); + --eminence: hsl(284, 46%, 35%); + --french-violet: hsl(279, 94%, 42%); + --grape: hsl(272, 58%, 42%); + --han-purple: hsl(255, 96%, 54%); + --indigo: hsl(275, 100%, 25%); + --ksu-purple: hsl(266, 55%, 35%); + --languid-lavender: hsl(278, 22%, 83%); + --lavender-floral: hsl(275, 57%, 68%); + --lavender-indigo: hsl(265, 79%, 63%); + --lavender-purple: hsl(267, 29%, 60%); + --light-pastel-purple: hsl(261, 45%, 73%); + --magnolia: hsl(262, 100%, 98%); + --mauve: hsl(276, 100%, 85%); + --medium-purple: hsl(260, 60%, 65%); + --middle-blue-purple: hsl(260, 37%, 60%); + --middle-red-purple: hsl(272, 75%, 12%); + --pale-lavender: hsl(255, 100%, 91%); + --pale-violet: hsl(270, 100%, 80%); + --persian-indigo: hsl(258, 74%, 27%); + --pixie-powder: hsl(260, 76%, 30%); + --purple-x11: hsl(277, 87%, 53%); + --purple-heart: hsl(270, 49%, 41%); + --purple-mountain-majesty: hsl(269, 30%, 59%); + --purple-plum: hsl(285, 41%, 52%); + --rebecca-purple: hsl(270, 50%, 40%); + --regalia: hsl(267, 48%, 34%); + --rich-lavender: hsl(276, 51%, 62%); + --rich-lilac: hsl(284, 55%, 61%); + --royal-purple: hsl(267, 35%, 49%); + --russian-violet: hsl(270, 54%, 20%); + --spanish-violet: hsl(264, 53%, 33%); + --tropical-violet: hsl(282, 47%, 76%); + --violet-color-wheel: hsl(270, 100%, 50%); + --vivid-violet: hsl(277, 100%, 50%); + --wisteria: hsl(281, 46%, 75%); + --jaguar: hsl(268, 88%, 3%); + --black-russian: hsl(261, 100%, 5%); + --very-deep-violet: hsl(269, 100%, 6%); + --very-dark-violet: hsl(270, 26%, 9%); + --haiti: hsl(258, 54%, 14%); + --tolopea: hsl(262, 94%, 14%); + --dark-indigo: hsl(258, 81%, 18%); + --deep-blue-violet: hsl(262, 100%, 17%); + --violet: hsl(269, 73%, 15%); + --pms275: hsl(260, 70%, 19%); + --paua: hsl(261, 94%, 21%); + --paris-m: hsl(260, 91%, 22%); + --midnight-purple: hsl(283, 96%, 11%); + --violent-violet: hsl(261, 77%, 21%); + --montana: hsl(277, 23%, 15%); + --bastille: hsl(272, 19%, 16%); + --cherry-pie: hsl(267, 93%, 18%); + --silhouette: hsl(283, 9%, 16%); + --baltic-sea: hsl(264, 12%, 17%); + --pms2765: hsl(265, 76%, 19%); + --pms274: hsl(258, 71%, 23%); + --pms276: hsl(256, 37%, 20%); + --bleached-cedar: hsl(277, 21%, 16%); + --pms2738: hsl(259, 100%, 28%); + --blackcurrant: hsl(278, 42%, 16%); + --showtime: hsl(267, 21%, 19%); + --rasputin: hsl(274, 15%, 18%); + --christalle: hsl(268, 95%, 22%); + --pms2755: hsl(269, 100%, 21%); + --valentino: hsl(285, 65%, 16%); + --jagger: hsl(272, 72%, 20%); + --pms5255: hsl(262, 35%, 23%); + --filmpro-purple: hsl(261, 29%, 23%); + --pms273: hsl(259, 66%, 29%); + --tarot: hsl(285, 20%, 20%); + --vivid-indigo: hsl(255, 100%, 45%); + --dark-blue-violet: hsl(263, 39%, 25%); + --pukeko: hsl(259, 41%, 27%); + --meteorite: hsl(260, 58%, 29%); + --windsor: hsl(268, 88%, 25%); + --blue-diamond: hsl(268, 93%, 24%); + --kingfisher-daisy: hsl(268, 94%, 26%); + --ship-grey: hsl(264, 8%, 25%); + --pms2745: hsl(272, 100%, 23%); + --strong-blue-violet: hsl(263, 100%, 33%); + --luminous-vivid-indigo: hsl(255, 100%, 50%); + --scarlet-gum: hsl(277, 64%, 23%); + --grapevine: hsl(283, 36%, 23%); + --pms269: hsl(277, 44%, 24%); + --pms2695: hsl(274, 46%, 25%); + --warlord: hsl(260, 10%, 28%); + --pms669: hsl(277, 35%, 26%); + --dark-grayish-indigo: hsl(256, 15%, 30%); + --pms5265: hsl(259, 24%, 31%); + --dancing-queen: hsl(269, 40%, 29%); + --funtasia: hsl(264, 38%, 32%); + --everest: hsl(270, 5%, 30%); + --dark-grayish-violet: hsl(271, 15%, 30%); + --mulled-wine: hsl(259, 17%, 33%); + --pms2735: hsl(272, 100%, 29%); + --honey-flower: hsl(276, 60%, 27%); + --pms268: hsl(275, 54%, 28%); + --daisy-bush: hsl(263, 63%, 37%); + --strong-violet: hsl(270, 100%, 33%); + --purple: hsl(271, 68%, 32%); + --pms2685: hsl(277, 100%, 27%); + --pms2617: hsl(284, 81%, 24%); + --vivid-blue-violet: hsl(263, 100%, 45%); + --blue-purple: hsl(257, 67%, 48%); + --chapta-and-verse: hsl(277, 11%, 33%); + --gobstopper: hsl(268, 41%, 35%); + --pms267: hsl(275, 79%, 31%); + --aurora: hsl(281, 11%, 34%); + --pms2607: hsl(285, 97%, 24%); + --luminous-vivid-blue-violet: hsl(263, 100%, 50%); + --purplish-blue: hsl(258, 95%, 55%); + --pms5275: hsl(258, 16%, 40%); + --mobster: hsl(268, 7%, 38%); + --butterfly-bush: hsl(256, 33%, 45%); + --purple-blue: hsl(257, 81%, 55%); + --covert: hsl(262, 14%, 41%); + --pms2597: hsl(284, 100%, 27%); + --purply-blue: hsl(262, 86%, 52%); + --pms668: hsl(280, 23%, 37%); + --burple: hsl(258, 76%, 54%); + --salt-box: hsl(278, 8%, 40%); + --strong-purple: hsl(278, 100%, 33%); + --high-society: hsl(265, 15%, 42%); + --kimberly: hsl(257, 18%, 45%); + --jupiter: hsl(279, 19%, 39%); + --pms266: hsl(272, 62%, 41%); + --moderate-blue-violet: hsl(262, 39%, 47%); + --centaurian: hsl(282, 14%, 41%); + --bluish-purple: hsl(258, 78%, 57%); + --pms814-2x: hsl(266, 47%, 47%); + --rum: hsl(284, 7%, 43%); + --affair: hsl(274, 35%, 43%); + --studio: hsl(263, 41%, 49%); + --ferris-wheel: hsl(268, 37%, 46%); + --pms2725: hsl(259, 44%, 53%); + --deluge: hsl(256, 28%, 52%); + --mamba: hsl(276, 6%, 46%); + --brilliant-indigo: hsl(255, 76%, 61%); + --labyrinth: hsl(280, 9%, 46%); + --moderate-violet: hsl(270, 39%, 47%); + --pms527: hsl(285, 67%, 36%); + --strong-mulberry: hsl(285, 100%, 33%); + --pms667: hsl(283, 15%, 47%); + --luminous-vivid-violet: hsl(270, 100%, 50%); + --grey-purple: hsl(281, 12%, 49%); + --boogie-wonderland: hsl(280, 28%, 47%); + --moderate-purple: hsl(278, 39%, 47%); + --long-shot: hsl(256, 30%, 59%); + --purpley: hsl(261, 72%, 62%); + --greyish-purple: hsl(283, 13%, 51%); + --grayish-indigo: hsl(255, 20%, 57%); + --pms272: hsl(256, 33%, 60%); + --pms2665: hsl(271, 47%, 53%); + --brilliant-blue-violet: hsl(262, 76%, 61%); + --pms5285: hsl(266, 10%, 55%); + --pms814: hsl(267, 44%, 57%); + --deep-lavender: hsl(272, 38%, 54%); + --pms2587: hsl(282, 42%, 48%); + --vivid-purple: hsl(278, 100%, 45%); + --ce-soir: hsl(277, 23%, 55%); + --pms2715: hsl(258, 45%, 64%); + --grayish-violet: hsl(271, 20%, 57%); + --dancing-girl: hsl(266, 42%, 60%); + --mountain-mist: hsl(280, 1%, 58%); + --amethyst-smoke: hsl(280, 10%, 57%); + --pms265: hsl(272, 45%, 58%); + --lilac-bush: hsl(263, 52%, 64%); + --pms2655: hsl(271, 44%, 60%); + --brilliant-violet: hsl(270, 76%, 61%); + --purple-mountain: hsl(269, 29%, 62%); + --cold-purple: hsl(262, 29%, 65%); + --light-brilliant-blue-violet: hsl(263, 100%, 70%); + --effortless: hsl(275, 9%, 62%); + --lightish-purple: hsl(274, 75%, 61%); + --lighter-purple: hsl(269, 88%, 65%); + --pms2577: hsl(284, 38%, 60%); + --east-side: hsl(278, 26%, 64%); + --marionette: hsl(285, 17%, 64%); + --bright-violet: hsl(280, 98%, 52%); + --pms2705: hsl(257, 38%, 72%); + --light-blue-violet: hsl(263, 66%, 73%); + --biloba-flower: hsl(262, 39%, 71%); + --abbey-road: hsl(261, 13%, 70%); + --brilliant-purple: hsl(278, 76%, 61%); + --light-brilliant-violet: hsl(270, 100%, 70%); + --light-urple: hsl(270, 88%, 70%); + --chatelle: hsl(284, 7%, 69%); + --pms2645: hsl(274, 41%, 69%); + --pale-purple: hsl(274, 44%, 70%); + --light-violet: hsl(270, 66%, 73%); + --lenurple: hsl(274, 47%, 71%); + --pms270: hsl(258, 29%, 76%); + --greywacke: hsl(280, 4%, 73%); + --neon-purple: hsl(283, 99%, 54%); + --bright-purple: hsl(285, 98%, 50%); + --light-purple: hsl(274, 88%, 72%); + --easter-purple: hsl(274, 99%, 72%); + --moon-raker: hsl(263, 32%, 77%); + --very-light-blue-violet: hsl(262, 100%, 81%); + --perfume: hsl(270, 41%, 76%); + --melrose: hsl(257, 35%, 80%); + --liliac: hsl(269, 97%, 77%); + --pale-light-grayish-indigo: hsl(255, 49%, 81%); + --light-brilliant-purple: hsl(277, 100%, 70%); + --pms264: hsl(274, 40%, 76%); + --pms2635: hsl(279, 36%, 76%); + --baby-purple: hsl(271, 85%, 79%); + --prelude: hsl(281, 27%, 77%); + --in-the-mauve: hsl(270, 6%, 81%); + --very-light-violet: hsl(270, 100%, 81%); + --light-mulberry: hsl(285, 66%, 73%); + --pale-light-grayish-violet: hsl(271, 49%, 81%); + --fairylight: hsl(265, 42%, 85%); + --sonique: hsl(261, 26%, 85%); + --light-brilliant-mulberry: hsl(285, 100%, 70%); + --pale-blue-violet: hsl(263, 100%, 88%); + --rolling-fog: hsl(263, 11%, 86%); + --very-light-purple: hsl(278, 100%, 81%); + --titan-white: hsl(278, 15%, 86%); + --light-lavender: hsl(267, 97%, 88%); + --snuff: hsl(269, 37%, 89%); + --blue-chalk: hsl(281, 30%, 88%); + --pale-lilac: hsl(269, 100%, 90%); + --divine: hsl(284, 44%, 87%); + --white-lilac: hsl(280, 6%, 90%); + --chalk-lavender: hsl(280, 16%, 89%); + --light-lilac: hsl(280, 100%, 89%); + --very-pale-violet: hsl(269, 100%, 94%); + --zinc-white: hsl(283, 100%, 99%); + --african-violet: hsl(288, 31%, 63%); + --bright-lilac: hsl(285, 75%, 75%); + --brilliant-lavender: hsl(290, 100%, 87%); + --byzantine: hsl(311, 58%, 47%); + --byzantium: hsl(311, 46%, 30%); + --chinese-violet: hsl(296, 17%, 45%); + --dark-byzantium: hsl(315, 24%, 29%); + --dark-magenta: hsl(300, 100%, 27%); + --dark-purple: hsl(291, 35%, 15%); + --deep-fuchsia: hsl(300, 47%, 54%); + --deep-mauve: hsl(300, 53%, 64%); + --deep-magenta: hsl(300, 100%, 40%); + --english-violet: hsl(289, 21%, 30%); + --french-lilac: hsl(290, 19%, 47%); + --fuchsia: hsl(300, 100%, 50%); + --fuchsia-pink: hsl(300, 100%, 73%); + --glossy-grape: hsl(285, 18%, 64%); + --heliotrope: hsl(286, 100%, 73%); + --heliotrope-gray: hsl(303, 10%, 63%); + --heliotrope-magenta: hsl(295, 100%, 37%); + --hot-magenta: hsl(313, 100%, 56%); + --imperial: hsl(289, 39%, 30%); + --japanese-violet: hsl(307, 29%, 28%); + --lavender-magenta: hsl(300, 76%, 72%); + --light-fuchsia-pink: hsl(305, 91%, 75%); + --light-grayish-magenta: hsl(300, 33%, 70%); + --light-medium-orchid: hsl(309, 39%, 72%); + --light-orchid: hsl(315, 55%, 78%); + --lilac: hsl(300, 26%, 71%); + --lilac-luster: hsl(311, 12%, 64%); + --mardi-gras: hsl(301, 100%, 27%); + --maximum-purple: hsl(290, 43%, 35%); + --raisin-black: hsl(300, 4%, 14%); + --medium-lavender-magenta: hsl(300, 47%, 75%); + --medium-orchid: hsl(288, 59%, 58%); + --midnight: hsl(300, 49%, 29%); + --old-lavender: hsl(304, 8%, 44%); + --orchid: hsl(302, 59%, 65%); + --palatinate-purple: hsl(308, 44%, 28%); + --pale-magenta: hsl(310, 91%, 75%); + --pastel-purple: hsl(295, 13%, 66%); + --pastel-violet: hsl(302, 32%, 70%); + --patriarch: hsl(300, 100%, 25%); + --phlox: hsl(292, 100%, 50%); + --pink-flamingo: hsl(300, 97%, 72%); + --pink-lavender: hsl(311, 33%, 77%); + --plum: hsl(307, 35%, 41%); + --purple-munsell: hsl(288, 100%, 39%); + --purple-pizzazz: hsl(312, 99%, 65%); + --purple-taupe: hsl(311, 11%, 28%); + --purpureus: hsl(288, 38%, 49%); + --quartz: hsl(313, 6%, 30%); + --razzle-dazzle-rose: hsl(315, 100%, 60%); + --razzmic-berry: hsl(308, 29%, 43%); + --rich-brilliant-lavender: hsl(291, 98%, 83%); + --thistle: hsl(300, 24%, 80%); + --steel-pink: hsl(300, 60%, 50%); + --shocking-pink-crayola: hsl(300, 100%, 72%); + --violet-ryb: hsl(286, 99%, 35%); + --vivid-mulberry: hsl(288, 90%, 47%); + --vivid-orchid: hsl(288, 100%, 50%); + --magentaish-black: hsl(300, 5%, 11%); + --very-dark-magenta: hsl(300, 26%, 9%); + --very-deep-magenta: hsl(300, 100%, 6%); + --very-dark-purple: hsl(288, 96%, 10%); + --revolver: hsl(287, 39%, 14%); + --pitch-black: hsl(300, 1%, 17%); + --jacaranda: hsl(307, 88%, 10%); + --melanzane: hsl(310, 81%, 10%); + --ab-fab: hsl(308, 30%, 15%); + --upstage: hsl(300, 23%, 16%); + --deep-purple: hsl(291, 97%, 13%); + --passion: hsl(307, 17%, 20%); + --fuscous-grey: hsl(300, 1%, 23%); + --deep-mulberry: hsl(285, 100%, 17%); + --eggplant-purple: hsl(302, 86%, 14%); + --chocolate-lounge: hsl(313, 7%, 25%); + --voodoo: hsl(313, 15%, 23%); + --loulou: hsl(305, 73%, 16%); + --clairvoyant: hsl(290, 87%, 18%); + --gravel: hsl(291, 5%, 28%); + --thriller: hsl(300, 3%, 28%); + --pms2627: hsl(285, 65%, 22%); + --bossanova: hsl(293, 12%, 27%); + --dark-mulberry: hsl(286, 39%, 25%); + --hot-purple: hsl(292, 29%, 25%); + --plum-purple: hsl(298, 88%, 17%); + --shadowy-lavender: hsl(300, 3%, 30%); + --mortar: hsl(296, 9%, 29%); + --pms525: hsl(296, 38%, 24%); + --dark-heliotrope: hsl(293, 39%, 25%); + --dark-grayish-mulberry: hsl(287, 15%, 30%); + --berlin: hsl(287, 9%, 32%); + --troubadour: hsl(296, 45%, 24%); + --deep-orchid: hsl(307, 100%, 17%); + --dark-fuchsia: hsl(314, 39%, 25%); + --dark-grayish-fuchsia: hsl(313, 15%, 30%); + --dark-magentaish-grey: hsl(300, 3%, 34%); + --dark-grayish-magenta: hsl(300, 15%, 30%); + --pms2623: hsl(297, 58%, 23%); + --ultramarine-violet: hsl(285, 51%, 29%); + --grape-purple: hsl(310, 65%, 22%); + --pms261: hsl(310, 48%, 25%); + --pms2622: hsl(308, 36%, 28%); + --fedora: hsl(288, 8%, 37%); + --pms519: hsl(306, 35%, 29%); + --pms2613: hsl(295, 73%, 25%); + --pms260: hsl(311, 55%, 26%); + --pms526: hsl(288, 57%, 30%); + --giggle: hsl(295, 38%, 31%); + --bloom: hsl(309, 10%, 40%); + --pms2603: hsl(294, 72%, 28%); + --pms2612: hsl(299, 58%, 28%); + --pms520: hsl(298, 37%, 33%); + --pms2592-2x: hsl(293, 100%, 25%); + --rich-purple: hsl(314, 100%, 22%); + --pms259: hsl(305, 68%, 27%); + --seance: hsl(285, 65%, 34%); + --darkish-purple: hsl(301, 65%, 28%); + --belladonna: hsl(312, 46%, 32%); + --pms255: hsl(310, 45%, 32%); + --purplish-grey: hsl(287, 10%, 45%); + --monsoon: hsl(315, 2%, 47%); + --bruise: hsl(313, 33%, 37%); + --muted-purple: hsl(290, 19%, 44%); + --magentaish-grey: hsl(300, 6%, 64%); + --purpley-grey: hsl(300, 9%, 54%); + --trendy-pink: hsl(300, 16%, 43%); + --pms2602: hsl(294, 84%, 30%); + --dusty-purple: hsl(293, 17%, 45%); + --centre-stage: hsl(311, 46%, 35%); + --genie: hsl(310, 36%, 38%); + --dull-purple: hsl(308, 19%, 43%); + --de-janeiro: hsl(302, 13%, 46%); + --purple-grey: hsl(303, 9%, 48%); + --pms2593: hsl(293, 55%, 37%); + --suva-grey: hsl(312, 2%, 52%); + --light-eggplant: hsl(304, 33%, 40%); + --faded-purple: hsl(289, 17%, 52%); + --cobalt-violet-deep: hsl(294, 65%, 37%); + --moderate-mulberry: hsl(285, 39%, 47%); + --strong-heliotrope: hsl(293, 100%, 33%); + --pms2592: hsl(293, 83%, 35%); + --purplish: hsl(308, 26%, 46%); + --warm-purple: hsl(303, 53%, 38%); + --nitro: hsl(306, 9%, 55%); + --purply: hsl(286, 48%, 47%); + --purpleish: hsl(310, 28%, 47%); + --taffeta: hsl(294, 20%, 53%); + --violet-eggplant: hsl(300, 80%, 33%); + --pms258: hsl(304, 32%, 46%); + --dark-lilac: hsl(290, 24%, 54%); + --quarter-sidewinder: hsl(312, 2%, 60%); + --moderate-heliotrope: hsl(292, 39%, 47%); + --grayish-mulberry: hsl(286, 20%, 57%); + --pms513: hsl(311, 64%, 38%); + --pms2583: hsl(295, 35%, 48%); + --ooh-la: hsl(288, 14%, 59%); + --barney-purple: hsl(303, 95%, 32%); + --pms254: hsl(305, 56%, 40%); + --pms248: hsl(314, 94%, 33%); + --butterfly: hsl(309, 24%, 53%); + --heather: hsl(288, 19%, 60%); + --ugly-purple: hsl(302, 43%, 45%); + --siesta: hsl(287, 7%, 63%); + --soft-purple: hsl(287, 32%, 57%); + --strong-fuchsia: hsl(315, 100%, 33%); + --strong-orchid: hsl(308, 100%, 33%); + --strong-magenta: hsl(300, 100%, 33%); + --grayish-fuchsia: hsl(314, 20%, 57%); + --grayish-magenta: hsl(300, 20%, 57%); + --pms666: hsl(288, 14%, 63%); + --moderate-fuchsia: hsl(315, 39%, 47%); + --moderate-orchid: hsl(308, 39%, 47%); + --moderate-magenta: hsl(300, 39%, 47%); + --heliotrope-grey: hsl(307, 10%, 63%); + --pms2582: hsl(292, 45%, 50%); + --dusty-lavender: hsl(306, 19%, 60%); + --barney: hsl(295, 73%, 42%); + --vibrant-purple: hsl(287, 97%, 44%); + --london-hue: hsl(307, 14%, 63%); + --pms528: hsl(286, 39%, 60%); + --pms253: hsl(304, 67%, 41%); + --ashen-lavender: hsl(300, 5%, 68%); + --pms5295: hsl(286, 8%, 68%); + --pms521: hsl(304, 22%, 63%); + --pms247: hsl(313, 100%, 36%); + --lola: hsl(292, 10%, 70%); + --pms2573: hsl(298, 32%, 61%); + --wonderland: hsl(300, 21%, 66%); + --pms2567: hsl(286, 36%, 69%); + --brilliant-mulberry: hsl(285, 76%, 61%); + --pms2572: hsl(291, 45%, 67%); + --pms522: hsl(309, 23%, 71%); + --pms665: hsl(307, 13%, 74%); + --purpley-pink: hsl(306, 56%, 51%); + --pinky-purple: hsl(305, 54%, 54%); + --vivid-heliotrope: hsl(292, 100%, 45%); + --pms246: hsl(313, 100%, 40%); + --pms529: hsl(294, 35%, 73%); + --pms2563: hsl(306, 35%, 72%); + --pms252: hsl(308, 54%, 62%); + --pms257: hsl(313, 34%, 74%); + --pms523: hsl(315, 24%, 77%); + --brilliant-heliotrope: hsl(293, 76%, 61%); + --pms538: hsl(300, 4%, 83%); + --pms530: hsl(300, 32%, 76%); + --pinkish-purple: hsl(300, 64%, 56%); + --pms2562: hsl(300, 38%, 75%); + --pink-purple: hsl(300, 67%, 58%); + --light-heliotrope: hsl(293, 66%, 73%); + --pale-light-grayish-mulberry: hsl(286, 49%, 81%); + --dreamweaver: hsl(287, 12%, 85%); + --flower-power: hsl(308, 37%, 79%); + --purpleish-pink: hsl(310, 69%, 59%); + --pms263: hsl(300, 23%, 84%); + --purple-pink: hsl(303, 72%, 56%); + --pms251: hsl(311, 54%, 75%); + --selago: hsl(293, 14%, 89%); + --vivid-fuchsia: hsl(315, 100%, 45%); + --vivid-magenta: hsl(300, 100%, 45%); + --light-fuchsia: hsl(315, 66%, 73%); + --light-magenta: hsl(300, 66%, 73%); + --very-light-mulberry: hsl(285, 100%, 81%); + --pale-light-grayish-fuchsia: hsl(314, 49%, 81%); + --light-magentaish-grey: hsl(300, 21%, 88%); + --pale-light-grayish-magenta: hsl(300, 49%, 81%); + --brilliant-fuchsia: hsl(315, 76%, 61%); + --brilliant-orchid: hsl(307, 76%, 61%); + --brilliant-magenta: hsl(300, 76%, 61%); + --light-brilliant-heliotrope: hsl(293, 100%, 70%); + --light-lavendar: hsl(285, 97%, 87%); + --purply-pink: hsl(305, 80%, 70%); + --pale-mulberry: hsl(285, 100%, 88%); + --very-light-heliotrope: hsl(293, 100%, 81%); + --pale-heliotrope: hsl(292, 100%, 88%); + --very-pale-mulberry: hsl(286, 100%, 94%); + --violet-pink: hsl(300, 96%, 68%); + --pale-mauve: hsl(303, 96%, 91%); + --luminous-vivid-orchid: hsl(308, 100%, 50%); + --light-brilliant-orchid: hsl(307, 100%, 70%); + --light-brilliant-magenta: hsl(300, 100%, 70%); + --very-light-fuchsia: hsl(315, 100%, 81%); + --very-light-orchid: hsl(307, 100%, 81%); + --very-light-magenta: hsl(300, 100%, 81%); + --pale-fuchsia: hsl(315, 100%, 88%); + --pale-orchid: hsl(308, 100%, 88%); + --very-pale-fuchsia: hsl(314, 100%, 94%); + --very-pale-magenta: hsl(300, 100%, 94%); + --magentaish-white: hsl(300, 100%, 98%); + --bright-magenta: hsl(306, 100%, 52%); + --amaranth-deep-purple: hsl(328, 57%, 40%); + --amaranth-pink: hsl(338, 75%, 78%); + --amaranth-purple: hsl(342, 63%, 41%); + --antique-fuchsia: hsl(316, 22%, 46%); + --baker-miller-pink: hsl(344, 100%, 78%); + --barbie-pink: hsl(327, 75%, 50%); + --blush: hsl(342, 66%, 62%); + --boysenberry: hsl(328, 46%, 36%); + --bright-pink: hsl(330, 100%, 50%); + --brilliant-rose: hsl(332, 100%, 67%); + --burgundy: hsl(345, 100%, 25%); + --cameo-pink: hsl(340, 62%, 84%); + --carmine-mp: hsl(342, 100%, 42%); + --carnation-pink: hsl(336, 100%, 83%); + --cerise: hsl(343, 72%, 53%); + --cerise-pink: hsl(336, 82%, 58%); + --china-pink: hsl(333, 63%, 65%); + --tawny-port: hsl(340, 27%, 31%); + --china-rose: hsl(340, 35%, 49%); + --charm-pink: hsl(340, 64%, 73%); + --cinnamon-satin: hsl(343, 52%, 59%); + --claret: hsl(343, 69%, 29%); + --classic-rose: hsl(326, 85%, 89%); + --cotton-candy: hsl(334, 100%, 87%); + --crimson-glory: hsl(344, 100%, 37%); + --cyclamen: hsl(338, 87%, 70%); + --dark-liver: hsl(330, 5%, 31%); + --dark-pink: hsl(342, 75%, 62%); + --dark-raspberry: hsl(330, 56%, 34%); + --dark-scarlet: hsl(344, 93%, 17%); + --debian-red: hsl(339, 91%, 44%); + --deep-cerise: hsl(330, 69%, 53%); + --deep-pink: hsl(328, 100%, 54%); + --deep-ruby: hsl(336, 35%, 38%); + --deep-tuscan-red: hsl(342, 21%, 33%); + --dogwood-rose: hsl(335, 80%, 47%); + --eggplant: hsl(329, 20%, 32%); + --english-lavender: hsl(338, 25%, 61%); + --fandango: hsl(320, 56%, 45%); + --fandango-pink: hsl(338, 68%, 60%); + --fashion-fuchsia: hsl(320, 100%, 48%); + --flamingo-pink: hsl(344, 95%, 77%); + --flirt: hsl(320, 100%, 32%); + --folly: hsl(341, 100%, 50%); + --french-fuchsia: hsl(334, 98%, 62%); + --french-pink: hsl(339, 97%, 71%); + --french-plum: hsl(325, 73%, 29%); + --french-rose: hsl(338, 91%, 63%); + --french-wine: hsl(344, 70%, 40%); + --frogert: hsl(322, 80%, 56%); + --fuchsia-purple: hsl(333, 59%, 51%); + --fuchsia-rose: hsl(337, 54%, 52%); + --halaya-ube: hsl(323, 29%, 31%); + --hot-pink: hsl(330, 100%, 71%); + --imperial-purple: hsl(325, 96%, 20%); + --irresistible: hsl(338, 45%, 48%); + --jazzberry-jam: hsl(328, 88%, 35%); + --kobi: hsl(329, 60%, 76%); + --lavender-blush: hsl(340, 100%, 97%); + --lavender-pink: hsl(332, 91%, 83%); + --lavender-rose: hsl(316, 92%, 81%); + --light-crimson: hsl(343, 88%, 69%); + --light-deep-pink: hsl(318, 100%, 68%); + --light-hot-pink: hsl(326, 100%, 85%); + --magenta-dye: hsl(328, 73%, 46%); + --magenta-pantone: hsl(334, 60%, 54%); + --magenta-process: hsl(326, 100%, 50%); + --magenta-haze: hsl(327, 39%, 45%); + --magenta-pink: hsl(325, 60%, 50%); + --maroon-x11: hsl(338, 57%, 44%); + --mauve-taupe: hsl(343, 21%, 47%); + --maximum-red-purple: hsl(325, 48%, 44%); + --medium-red-violet: hsl(324, 57%, 47%); + --medium-ruby: hsl(337, 45%, 46%); + --medium-violet-red: hsl(322, 81%, 43%); + --mexican-pink: hsl(327, 100%, 45%); + --middle-purple: hsl(325, 53%, 68%); + --mimi-pink: hsl(336, 100%, 93%); + --mountbatten-pink: hsl(323, 13%, 54%); + --mulberry: hsl(328, 51%, 53%); + --mystic: hsl(338, 62%, 58%); + --mystic-maroon: hsl(329, 44%, 47%); + --nadeshiko-pink: hsl(339, 80%, 82%); + --old-mauve: hsl(336, 36%, 30%); + --opera-mauve: hsl(319, 26%, 62%); + --orchid-pink: hsl(342, 67%, 85%); + --pale-magenta-pink: hsl(330, 100%, 80%); + --pale-red-violet: hsl(340, 60%, 65%); + --pansy-purple: hsl(329, 67%, 28%); + --pastel-magenta: hsl(333, 80%, 78%); + --pearly-purple: hsl(316, 35%, 56%); + --persian-pink: hsl(329, 88%, 73%); + --persian-rose: hsl(326, 99%, 58%); + --pictorial-carmine: hsl(338, 89%, 40%); + --piggy-pink: hsl(343, 89%, 93%); + --pink-pantone: hsl(328, 64%, 56%); + --pink-lace: hsl(319, 100%, 93%); + --pink-pearl: hsl(324, 55%, 79%); + --pink-raspberry: hsl(339, 100%, 30%); + --princess-perfume: hsl(324, 100%, 76%); + --puce: hsl(345, 40%, 67%); + --queen-pink: hsl(336, 38%, 85%); + --quinacridone-magenta: hsl(338, 42%, 39%); + --raspberry: hsl(337, 91%, 47%); + --raspberry-pink: hsl(330, 72%, 60%); + --razzmatazz: hsl(338, 77%, 52%); + --red-ncs: hsl(345, 98%, 39%); + --red-purple: hsl(328, 100%, 45%); + --rose-bonbon: hsl(330, 94%, 62%); + --rose-dust: hsl(344, 25%, 49%); + --rose-pink: hsl(320, 100%, 70%); + --rose-red: hsl(340, 73%, 44%); + --royal-fuchsia: hsl(321, 64%, 48%); + --ruber: hsl(339, 58%, 54%); + --rubine-red: hsl(335, 100%, 41%); + --ruby: hsl(337, 86%, 47%); + --sasquatch-socks: hsl(341, 100%, 64%); + --shampoo: hsl(318, 100%, 91%); + --shocking-pink: hsl(315, 98%, 52%); + --sky-magenta: hsl(320, 49%, 63%); + --smitten: hsl(329, 55%, 52%); + --spanish-carmine: hsl(340, 100%, 41%); + --strawberry: hsl(341, 96%, 67%); + --sugar-plum: hsl(325, 30%, 44%); + --super-pink: hsl(323, 51%, 62%); + --taupe-gray: hsl(320, 3%, 53%); + --telemagenta: hsl(334, 62%, 51%); + --tickle-me-pink: hsl(342, 95%, 76%); + --twilight-lavender: hsl(329, 31%, 41%); + --ua-red: hsl(339, 100%, 43%); + --utah-crimson: hsl(342, 100%, 41%); + --vanilla-ice: hsl(344, 81%, 76%); + --violet-red: hsl(336, 91%, 65%); + --vivid-cerise: hsl(328, 77%, 48%); + --vivid-crimson: hsl(345, 100%, 40%); + --vivid-raspberry: hsl(335, 100%, 50%); + --wild-orchid: hsl(330, 54%, 64%); + --wild-strawberry: hsl(329, 100%, 63%); + --winter-sky: hsl(331, 100%, 50%); + --very-deep-rose: hsl(331, 100%, 6%); + --very-dark-rose: hsl(330, 26%, 9%); + --loyal: hsl(344, 23%, 13%); + --cocktail: hsl(333, 24%, 15%); + --thunder: hsl(324, 11%, 18%); + --spitfire: hsl(345, 38%, 16%); + --zeppelin: hsl(317, 14%, 19%); + --blackadder: hsl(333, 11%, 20%); + --toledo: hsl(327, 100%, 11%); + --chocolate-fish: hsl(323, 18%, 19%); + --conundrum: hsl(334, 30%, 18%); + --caffeine: hsl(338, 10%, 21%); + --half-barbecue: hsl(343, 6%, 22%); + --rockstar: hsl(320, 3%, 23%); + --dark-plum: hsl(318, 97%, 13%); + --urban-legend: hsl(332, 13%, 23%); + --blackberry: hsl(328, 47%, 18%); + --barossa: hsl(321, 97%, 14%); + --castro: hsl(338, 32%, 20%); + --light-year: hsl(324, 8%, 25%); + --pms5185: hsl(335, 28%, 22%); + --half-fuscous-grey: hsl(320, 2%, 28%); + --tundora: hsl(345, 6%, 27%); + --horoscope: hsl(345, 10%, 24%); + --arthouse: hsl(341, 41%, 21%); + --matterhorn: hsl(341, 14%, 27%); + --pms5125: hsl(327, 24%, 37%); + --pms5115: hsl(327, 41%, 22%); + --transformer: hsl(334, 5%, 30%); + --moody-lavender: hsl(332, 9%, 29%); + --pms518: hsl(322, 29%, 25%); + --basalt: hsl(330, 3%, 31%); + --black-rose: hsl(344, 34%, 24%); + --encore: hsl(339, 58%, 21%); + --pms262: hsl(320, 41%, 23%); + --yasna: hsl(324, 6%, 31%); + --broadway: hsl(325, 27%, 26%); + --sidewinder: hsl(345, 5%, 32%); + --rendezvous: hsl(344, 62%, 21%); + --zulu: hsl(317, 4%, 33%); + --deep-raspberry: hsl(338, 100%, 17%); + --deep-rose: hsl(330, 100%, 17%); + --dark-rose: hsl(330, 39%, 25%); + --dark-cerise: hsl(323, 39%, 25%); + --pms5195: hsl(333, 27%, 27%); + --dark-grayish-crimson: hsl(344, 15%, 30%); + --dark-grayish-rose: hsl(329, 15%, 30%); + --verve: hsl(342, 34%, 27%); + --pms511: hsl(327, 49%, 25%); + --maroon: hsl(340, 100%, 20%); + --lip-service: hsl(334, 66%, 24%); + --nightclub: hsl(319, 100%, 20%); + --halay: hsl(323, 30%, 31%); + --minx: hsl(337, 11%, 37%); + --matakana: hsl(327, 6%, 39%); + --siren: hsl(343, 44%, 29%); + --finn: hsl(321, 40%, 29%); + --scorpion: hsl(342, 5%, 39%); + --pms229: hsl(336, 54%, 28%); + --cordite: hsl(332, 22%, 35%); + --half-sidewinder: hsl(323, 4%, 42%); + --pms222: hsl(335, 64%, 27%); + --pms690: hsl(336, 52%, 29%); + --merlot: hsl(330, 100%, 23%); + --dirty-purple: hsl(320, 22%, 37%); + --red-letter: hsl(343, 68%, 27%); + --pms209: hsl(343, 51%, 30%); + --extrovert: hsl(339, 51%, 30%); + --velvet: hsl(320, 87%, 25%); + --cosmic: hsl(325, 35%, 34%); + --innuendo: hsl(334, 6%, 44%); + --wine-red: hsl(344, 95%, 25%); + --pms242: hsl(327, 63%, 30%); + --pms216: hsl(339, 61%, 30%); + --smooch: hsl(326, 59%, 31%); + --carnival: hsl(318, 50%, 33%); + --pms683: hsl(333, 52%, 33%); + --pms249: hsl(321, 52%, 33%); + --wine: hsl(331, 98%, 25%); + --rose-bud-cherry: hsl(329, 84%, 27%); + --highlight: hsl(334, 40%, 37%); + --pms512: hsl(315, 60%, 32%); + --arabella: hsl(341, 15%, 45%); + --pms2425: hsl(320, 100%, 26%); + --graceland: hsl(316, 8%, 49%); + --disco: hsl(329, 73%, 31%); + --dark-mauve: hsl(338, 28%, 41%); + --code-red: hsl(344, 100%, 27%); + --geronimo: hsl(344, 61%, 33%); + --cannon-pink: hsl(329, 34%, 40%); + --impulse: hsl(338, 30%, 41%); + --dusky-purple: hsl(318, 20%, 45%); + --venus: hsl(339, 6%, 52%); + --medium-pink: hsl(335, 34%, 41%); + --pale-violet-red: hsl(341, 32%, 41%); + --red-wine: hsl(338, 100%, 27%); + --pms228: hsl(327, 100%, 27%); + --pms5205: hsl(336, 15%, 48%); + --pms208: hsl(341, 60%, 35%); + --pms235: hsl(325, 93%, 29%); + --sensual-red: hsl(345, 57%, 36%); + --reddish-purple: hsl(328, 88%, 30%); + --enchanted: hsl(331, 43%, 40%); + --pms221: hsl(333, 100%, 29%); + --pms1955: hsl(344, 74%, 33%); + --pms689: hsl(333, 38%, 42%); + --strikemaster: hsl(327, 17%, 50%); + --vin-rouge: hsl(344, 29%, 45%); + --lipstick: hsl(337, 55%, 38%); + --bordello: hsl(338, 38%, 43%); + --cadillac: hsl(342, 35%, 44%); + --fresh-eggplant: hsl(320, 100%, 30%); + --purple-red: hsl(332, 99%, 30%); + --berry: hsl(334, 82%, 33%); + --pms2415: hsl(317, 100%, 30%); + --sugar-and-spice: hsl(317, 23%, 50%); + --bedazzle: hsl(336, 40%, 44%); + --rock-n-roll: hsl(342, 100%, 31%); + --light-plum: hsl(322, 29%, 48%); + --cranberry: hsl(338, 100%, 31%); + --red-violet: hsl(321, 99%, 31%); + --shady-lady: hsl(330, 2%, 62%); + --pms5135: hsl(330, 16%, 50%); + --pms676: hsl(329, 100%, 31%); + --pms682: hsl(333, 33%, 47%); + --rouge: hsl(331, 47%, 43%); + --pms215: hsl(336, 94%, 33%); + --bouquet: hsl(322, 18%, 58%); + --strong-cerise: hsl(323, 100%, 33%); + --pms2405: hsl(316, 100%, 33%); + --strong-crimson: hsl(345, 100%, 33%); + --strong-raspberry: hsl(338, 100%, 33%); + --strong-rose: hsl(330, 100%, 33%); + --pms1945: hsl(344, 87%, 35%); + --grayish-crimson: hsl(345, 20%, 57%); + --grayish-rose: hsl(329, 20%, 57%); + --light-burgundy: hsl(345, 44%, 46%); + --moderate-raspberry: hsl(338, 39%, 47%); + --moderate-rose: hsl(330, 39%, 47%); + --moderate-cerise: hsl(322, 39%, 47%); + --colour-me-pink: hsl(334, 87%, 35%); + --pms234: hsl(324, 100%, 33%); + --pms220: hsl(332, 100%, 33%); + --filmpro-magenta: hsl(338, 56%, 43%); + --royal-heath: hsl(329, 53%, 44%); + --pms241: hsl(319, 100%, 34%); + --pms227: hsl(328, 100%, 34%); + --pms5145: hsl(332, 19%, 60%); + --party-dress: hsl(336, 41%, 48%); + --ajay: hsl(330, 2%, 68%); + --purplish-red: hsl(335, 94%, 35%); + --tapestry: hsl(334, 34%, 53%); + --pms688: hsl(336, 33%, 55%); + --red-tape: hsl(344, 100%, 35%); + --mesmerise: hsl(337, 16%, 65%); + --pms681: hsl(336, 32%, 58%); + --scrumptious: hsl(333, 73%, 42%); + --pms675: hsl(331, 54%, 48%); + --pms807-2x: hsl(316, 100%, 37%); + --lily: hsl(325, 22%, 69%); + --pms1935: hsl(344, 95%, 39%); + --magenta: hsl(323, 100%, 38%); + --light-mauve: hsl(341, 28%, 67%); + --pms2395: hsl(317, 100%, 38%); + --pms240: hsl(320, 86%, 41%); + --alluring: hsl(326, 17%, 72%); + --pms239-2x: hsl(323, 95%, 39%); + --viola: hsl(344, 32%, 67%); + --maverick: hsl(321, 17%, 74%); + --surf-spray-grey: hsl(345, 4%, 78%); + --pms687: hsl(340, 37%, 66%); + --pms5155: hsl(343, 22%, 74%); + --i-do: hsl(323, 14%, 77%); + --pms5305: hsl(333, 10%, 78%); + --pms214: hsl(335, 98%, 40%); + --hopbush: hsl(336, 49%, 62%); + --pms233: hsl(324, 100%, 40%); + --purplish-pink: hsl(317, 54%, 59%); + --charm: hsl(345, 49%, 64%); + --pms813-2x: hsl(322, 100%, 41%); + --muted-pink: hsl(344, 50%, 64%); + --pms674: hsl(331, 54%, 62%); + --pms680: hsl(341, 38%, 72%); + --pms206: hsl(341, 95%, 42%); + --dull-pink: hsl(343, 48%, 68%); + --pms807: hsl(316, 100%, 42%); + --pms226: hsl(329, 98%, 42%); + --pms514: hsl(320, 52%, 68%); + --pms664: hsl(335, 13%, 82%); + --dark-hot-pink: hsl(332, 99%, 43%); + --darkish-pink: hsl(338, 67%, 56%); + --pms2385: hsl(318, 71%, 51%); + --pms673: hsl(333, 58%, 71%); + --pms686: hsl(342, 47%, 77%); + --melanie: hsl(344, 40%, 80%); + --pms239: hsl(321, 75%, 50%); + --pms1925: hsl(342, 94%, 45%); + --shocking: hsl(326, 58%, 73%); + --pms524: hsl(341, 28%, 84%); + --lullaby: hsl(337, 27%, 85%); + --pms219: hsl(331, 76%, 52%); + --pms813: hsl(320, 100%, 45%); + --pms256: hsl(327, 39%, 83%); + --pms531: hsl(319, 37%, 84%); + --pms205: hsl(341, 75%, 60%); + --vivid-rose: hsl(330, 100%, 45%); + --light-raspberry: hsl(337, 66%, 73%); + --light-rose: hsl(330, 66%, 73%); + --light-cerise: hsl(322, 66%, 73%); + --pig-pink: hsl(344, 65%, 73%); + --pale-light-grayish-crimson: hsl(345, 49%, 81%); + --pale-light-grayish-rose: hsl(329, 49%, 81%); + --ditto: hsl(336, 9%, 90%); + --brilliant-crimson: hsl(345, 76%, 61%); + --brilliant-raspberry: hsl(338, 76%, 61%); + --brilliant-cerise: hsl(322, 76%, 61%); + --pms245: hsl(318, 70%, 70%); + --ballerina: hsl(332, 63%, 75%); + --pms515: hsl(327, 60%, 77%); + --pms2375: hsl(320, 75%, 67%); + --pms213: hsl(335, 88%, 49%); + --pms672: hsl(336, 60%, 79%); + --abercrombie: hsl(334, 30%, 89%); + --pms218: hsl(333, 77%, 69%); + --pms204: hsl(341, 76%, 70%); + --pms244: hsl(320, 68%, 78%); + --chantilly: hsl(343, 60%, 83%); + --pms250: hsl(323, 53%, 85%); + --pms225: hsl(327, 85%, 54%); + --pms238: hsl(324, 81%, 62%); + --illusion: hsl(343, 74%, 76%); + --pms671: hsl(341, 56%, 86%); + --prim: hsl(317, 32%, 91%); + --pms203: hsl(344, 72%, 82%); + --pms516: hsl(333, 68%, 84%); + --pms243: hsl(328, 68%, 84%); + --pms224: hsl(330, 86%, 69%); + --pms237: hsl(326, 84%, 74%); + --pms217: hsl(340, 71%, 85%); + --pms517: hsl(342, 65%, 88%); + --pms232: hsl(326, 89%, 60%); + --pms1915: hsl(345, 88%, 64%); + --cupid: hsl(343, 77%, 83%); + --amour: hsl(344, 43%, 93%); + --pink-red: hsl(342, 96%, 49%); + --rosy-pink: hsl(344, 89%, 69%); + --pms2365: hsl(336, 76%, 87%); + --pms806-2x: hsl(330, 98%, 49%); + --azalea: hsl(337, 75%, 88%); + --we-peep: hsl(336, 64%, 91%); + --pms223: hsl(331, 89%, 78%); + --pms236: hsl(331, 86%, 83%); + --pms212: hsl(338, 93%, 64%); + --warm-pink: hsl(344, 95%, 66%); + --pms231: hsl(328, 96%, 71%); + --pinky: hsl(342, 95%, 76%); + --pms812: hsl(341, 97%, 56%); + --pms812-2x: hsl(342, 98%, 51%); + --neon-pink: hsl(324, 99%, 50%); + --bubblegum-pink: hsl(324, 98%, 75%); + --rosa: hsl(345, 98%, 76%); + --luminous-vivid-rose: hsl(330, 100%, 50%); + --pms806: hsl(325, 100%, 50%); + --luminous-vivid-cerise: hsl(323, 100%, 50%); + --luminous-vivid-fuchsia: hsl(315, 100%, 50%); + --luminous-vivid-raspberry: hsl(337, 100%, 50%); + --light-brilliant-raspberry: hsl(337, 100%, 70%); + --light-brilliant-rose: hsl(330, 100%, 70%); + --light-brilliant-cerise: hsl(323, 100%, 70%); + --light-brilliant-fuchsia: hsl(315, 100%, 70%); + --bubble-gum-pink: hsl(332, 100%, 71%); + --pms211: hsl(338, 100%, 73%); + --very-light-raspberry: hsl(338, 100%, 81%); + --very-light-rose: hsl(330, 100%, 81%); + --very-light-cerise: hsl(322, 100%, 81%); + --pms210: hsl(340, 100%, 81%); + --pms230: hsl(332, 100%, 81%); + --powder-pink: hsl(337, 100%, 85%); + --pale-raspberry: hsl(337, 100%, 88%); + --pale-cerise: hsl(323, 100%, 88%); + --very-pale-rose: hsl(331, 100%, 94%); + --electric-pink: hsl(327, 100%, 51%); + --strong-pink: hsl(329, 100%, 51%); + --alabama-crimson: hsl(346, 100%, 34%); + --alizarin-crimson: hsl(355, 77%, 52%); + --amaranth: hsl(348, 78%, 53%); + --amaranth-red: hsl(356, 73%, 48%); + --american-rose: hsl(346, 100%, 51%); + --antique-ruby: hsl(350, 66%, 31%); + --awesome: hsl(347, 100%, 56%); + --bazaar: hsl(353, 14%, 53%); + --begonia: hsl(355, 93%, 71%); + --big-dip-o-ruby: hsl(345, 62%, 38%); + --bittersweet-shimmer: hsl(359, 47%, 53%); + --black-shadows: hsl(349, 11%, 72%); + --brick-red: hsl(352, 57%, 53%); + --bright-maroon: hsl(346, 71%, 45%); + --brink-pink: hsl(348, 95%, 68%); + --bubble-gum: hsl(349, 100%, 88%); + --bulgarian-rose: hsl(359, 85%, 15%); + --cadmium-red: hsl(351, 100%, 45%); + --candy-pink: hsl(355, 68%, 67%); + --cardinal: hsl(350, 73%, 44%); + --carmine: hsl(350, 100%, 29%); + --carmine-red: hsl(347, 100%, 50%); + --catawba: hsl(348, 35%, 33%); + --cherry-blossom-pink: hsl(348, 100%, 86%); + --cordovan: hsl(355, 37%, 39%); + --crimson: hsl(348, 83%, 47%); + --dark-puce: hsl(354, 15%, 27%); + --dark-terra-cotta: hsl(353, 55%, 55%); + --deep-carmine: hsl(347, 68%, 39%); + --deep-carmine-pink: hsl(357, 86%, 56%); + --deep-puce: hsl(351, 31%, 51%); + --deep-taupe: hsl(356, 15%, 43%); + --desire: hsl(352, 81%, 58%); + --dingy-dungeon: hsl(347, 60%, 48%); + --electric-crimson: hsl(345, 100%, 50%); + --english-red: hsl(356, 39%, 48%); + --english-vermillion: hsl(358, 57%, 54%); + --fiery-rose: hsl(350, 100%, 66%); + --fire-engine-red: hsl(357, 73%, 47%); + --french-raspberry: hsl(349, 64%, 48%); + --harvard-crimson: hsl(353, 100%, 39%); + --imperial-red: hsl(355, 84%, 55%); + --infra-red: hsl(348, 100%, 64%); + --japanese-carmine: hsl(355, 59%, 39%); + --jasper: hsl(359, 66%, 54%); + --ku-crimson: hsl(357, 100%, 45%); + --lava: hsl(355, 86%, 44%); + --light-carmine-pink: hsl(355, 72%, 65%); + --light-pink: hsl(351, 100%, 86%); + --madder-lake: hsl(359, 60%, 50%); + --magic-potion: hsl(349, 100%, 63%); + --mauvelous: hsl(348, 73%, 77%); + --medium-candy-apple-red: hsl(350, 95%, 45%); + --neon-fuchsia: hsl(349, 99%, 63%); + --old-rose: hsl(359, 34%, 63%); + --pale-chestnut: hsl(358, 41%, 77%); + --pale-pink: hsl(354, 76%, 92%); + --parrot-pink: hsl(353, 46%, 72%); + --pink: hsl(350, 100%, 88%); + --pink-sherbet: hsl(346, 87%, 76%); + --popstar: hsl(350, 46%, 53%); + --puce-red: hsl(353, 42%, 32%); + --radical-red: hsl(348, 100%, 60%); + --red-crayola: hsl(347, 86%, 53%); + --red-munsell: hsl(345, 100%, 47%); + --red-pigment: hsl(358, 85%, 52%); + --red-devil: hsl(353, 99%, 26%); + --red-salsa: hsl(355, 98%, 61%); + --rocket-metallic: hsl(355, 4%, 52%); + --rose-gold: hsl(351, 34%, 57%); + --rose-vale: hsl(357, 37%, 49%); + --rosewood: hsl(353, 100%, 20%); + --ruby-red: hsl(354, 80%, 34%); + --ruddy: hsl(351, 100%, 50%); + --ruddy-pink: hsl(354, 58%, 72%); + --rusty-red: hsl(352, 70%, 51%); + --salmon-pink: hsl(350, 100%, 78%); + --sangria: hsl(356, 100%, 29%); + --scarlet-dark: hsl(350, 98%, 52%); + --shimmering-blush: hsl(349, 52%, 69%); + --sizzling-red: hsl(351, 100%, 61%); + --smoky-topaz: hsl(357, 41%, 41%); + --solid-pink: hsl(352, 42%, 38%); + --spartan-crimson: hsl(359, 79%, 35%); + --spanish-crimson: hsl(345, 80%, 50%); + --spanish-red: hsl(350, 100%, 45%); + --sunburnt-cyclops: hsl(356, 100%, 63%); + --tulip: hsl(357, 100%, 76%); + --turkish-rose: hsl(347, 31%, 58%); + --ultra-red: hsl(350, 96%, 71%); + --up-maroon: hsl(359, 76%, 27%); + --upsdell-red: hsl(356, 69%, 40%); + --venetian-red: hsl(356, 92%, 41%); + --vivid-burgundy: hsl(349, 69%, 37%); + --vivid-red: hsl(357, 94%, 51%); + --toast-lmu-15: hsl(358, 47%, 11%); + --double-caffeine: hsl(350, 13%, 18%); + --beer-srm-40: hsl(359, 71%, 12%); + --aubergine: hsl(350, 20%, 18%); + --beer-srm-38: hsl(359, 78%, 13%); + --beer-srm-39: hsl(356, 75%, 13%); + --rustic-red: hsl(356, 41%, 16%); + --temptress: hsl(349, 100%, 12%); + --dark-maroon: hsl(352, 100%, 12%); + --platypus: hsl(354, 9%, 22%); + --jumpstart: hsl(350, 32%, 18%); + --black-sheep: hsl(348, 4%, 23%); + --ravishing: hsl(347, 42%, 18%); + --dark-crimson: hsl(352, 29%, 19%); + --afficionado: hsl(352, 12%, 24%); + --red-earth: hsl(347, 37%, 20%); + --crater-brown: hsl(358, 32%, 21%); + --contraband: hsl(351, 32%, 21%); + --tempo: hsl(347, 24%, 22%); + --double-sidewinder: hsl(353, 6%, 26%); + --night-owl: hsl(354, 17%, 24%); + --cab-sav: hsl(351, 23%, 24%); + --courage: hsl(352, 34%, 22%); + --velocity: hsl(349, 8%, 27%); + --bordeaux: hsl(350, 46%, 20%); + --mayhem: hsl(348, 48%, 20%); + --style-pasifika-red-soil: hsl(358, 33%, 23%); + --heath: hsl(357, 31%, 24%); + --emperor: hsl(351, 5%, 30%); + --red-baron: hsl(354, 47%, 22%); + --pms504: hsl(351, 46%, 22%); + --zibibbo: hsl(351, 38%, 23%); + --maroon-oak: hsl(351, 74%, 18%); + --lonestar: hsl(357, 39%, 23%); + --wine-berry: hsl(346, 30%, 25%); + --attitude: hsl(350, 32%, 25%); + --speed-demon: hsl(351, 52%, 22%); + --satellite: hsl(354, 13%, 30%); + --burnt-crimson: hsl(357, 45%, 24%); + --deep-amaranth: hsl(353, 100%, 17%); + --deep-crimson: hsl(345, 100%, 17%); + --renegade: hsl(353, 45%, 24%); + --dark-amaranth: hsl(353, 39%, 25%); + --don-juan: hsl(349, 7%, 33%); + --avant-garde: hsl(355, 35%, 27%); + --jazz: hsl(356, 37%, 27%); + --madam-m: hsl(348, 78%, 21%); + --buccaneer: hsl(359, 35%, 28%); + --vanquish: hsl(352, 43%, 27%); + --brunette: hsl(358, 21%, 32%); + --galaxy: hsl(350, 17%, 33%); + --breakfree: hsl(347, 60%, 25%); + --pohutukawa: hsl(352, 57%, 25%); + --pms505: hsl(349, 55%, 26%); + --deep-impact: hsl(358, 45%, 28%); + --japanese-maple: hsl(359, 37%, 29%); + --purple-brown: hsl(353, 28%, 32%); + --x-factor: hsl(348, 59%, 26%); + --zambezi: hsl(351, 10%, 37%); + --solar-flare: hsl(357, 26%, 33%); + --hot-chile: hsl(354, 49%, 28%); + --purplish-brown: hsl(353, 24%, 34%); + --livewire: hsl(352, 59%, 27%); + --matchmaker: hsl(348, 35%, 32%); + --spellbound: hsl(353, 19%, 36%); + --falcon: hsl(357, 10%, 39%); + --hot-wired: hsl(346, 49%, 29%); + --dynamite: hsl(357, 47%, 30%); + --jalapeno: hsl(351, 60%, 27%); + --razzamatazz: hsl(353, 57%, 28%); + --ferra: hsl(358, 17%, 37%); + --ribbon: hsl(351, 38%, 32%); + --eighth-barista: hsl(353, 7%, 42%); + --tosca: hsl(358, 29%, 35%); + --tamarillo: hsl(357, 46%, 31%); + --brownish-purple: hsl(346, 28%, 36%); + --blood: hsl(359, 100%, 23%); + --salsa: hsl(346, 82%, 26%); + --pms198: hsl(354, 45%, 32%); + --i-c-red: hsl(349, 58%, 30%); + --pms506: hsl(347, 53%, 31%); + --paradise-pink: hsl(347, 77%, 57%); + --empress: hsl(349, 5%, 46%); + --pms188: hsl(355, 58%, 31%); + --paprika: hsl(352, 47%, 33%); + --memory: hsl(345, 15%, 42%); + --bullseye: hsl(354, 57%, 31%); + --scarlett: hsl(353, 55%, 32%); + --lollipop: hsl(349, 52%, 33%); + --adrenalin-junkie: hsl(356, 44%, 35%); + --pms697: hsl(358, 39%, 36%); + --camelot: hsl(345, 38%, 36%); + --spicy-pink: hsl(351, 8%, 47%); + --stiletto: hsl(359, 36%, 38%); + --rosehip: hsl(345, 60%, 32%); + --shiraz: hsl(353, 53%, 34%); + --flame-red: hsl(356, 54%, 34%); + --xotic: hsl(358, 45%, 36%); + --zinger: hsl(356, 38%, 38%); + --hot-stuff: hsl(359, 31%, 40%); + --renaissance: hsl(347, 20%, 44%); + --fast-lane: hsl(352, 58%, 34%); + --old-brick: hsl(359, 46%, 37%); + --pms202: hsl(352, 57%, 35%); + --cha: hsl(358, 38%, 40%); + --opium: hsl(358, 12%, 50%); + --well-read: hsl(359, 46%, 38%); + --pms696: hsl(358, 33%, 42%); + --filmpro-deep-red: hsl(348, 60%, 35%); + --pirate: hsl(355, 51%, 37%); + --pms492: hsl(357, 48%, 38%); + --bright-red: hsl(356, 55%, 37%); + --flash-point: hsl(357, 54%, 37%); + --erotic: hsl(352, 39%, 42%); + --red-hot: hsl(356, 55%, 38%); + --guardsman-red: hsl(358, 53%, 38%); + --bona-fide: hsl(353, 13%, 53%); + --blood-red: hsl(359, 100%, 30%); + --pms194: hsl(350, 65%, 36%); + --tonto: hsl(354, 5%, 60%); + --candy-floss: hsl(349, 61%, 39%); + --roadster: hsl(354, 57%, 40%); + --pms1807: hsl(358, 54%, 41%); + --high-tea: hsl(349, 10%, 59%); + --night-shadz: hsl(346, 45%, 44%); + --light-maroon: hsl(350, 38%, 46%); + --pms201: hsl(351, 62%, 39%); + --sargent-pepper: hsl(348, 44%, 45%); + --la-bamba: hsl(355, 44%, 45%); + --pms4995: hsl(358, 24%, 53%); + --filmpro-fire-red: hsl(355, 53%, 42%); + --aphrodisiac: hsl(359, 37%, 48%); + --vintage: hsl(349, 18%, 58%); + --strong-amaranth: hsl(353, 100%, 33%); + --anticipation: hsl(352, 15%, 60%); + --dusty-grey: hsl(349, 8%, 63%); + --punch: hsl(356, 54%, 43%); + --moderate-amaranth: hsl(353, 39%, 47%); + --moderate-crimson: hsl(345, 39%, 47%); + --darkish-red: hsl(358, 97%, 34%); + --glitterbug: hsl(354, 60%, 41%); + --hippie-pink: hsl(348, 40%, 48%); + --poppy: hsl(351, 100%, 34%); + --vibe: hsl(352, 56%, 43%); + --smashing: hsl(349, 100%, 34%); + --get-reddy: hsl(358, 53%, 44%); + --bombshell: hsl(353, 57%, 43%); + --pms187: hsl(354, 71%, 40%); + --crash-hot: hsl(352, 58%, 43%); + --minnelli: hsl(348, 31%, 56%); + --del-toro: hsl(359, 72%, 40%); + --pms695: hsl(356, 32%, 56%); + --hot-spot: hsl(355, 63%, 43%); + --hibiscus: hsl(346, 54%, 46%); + --bliss: hsl(358, 52%, 46%); + --pms5215: hsl(346, 19%, 64%); + --pms703: hsl(354, 53%, 47%); + --dusty-red: hsl(357, 45%, 50%); + --dusky-rose: hsl(352, 37%, 57%); + --red-pepper: hsl(351, 83%, 40%); + --pink-swan: hsl(347, 6%, 73%); + --lipstick-red: hsl(346, 98%, 38%); + --grey-pink: hsl(347, 30%, 66%); + --miss-hussy: hsl(347, 51%, 52%); + --old-pink: hsl(350, 41%, 63%); + --greyish-pink: hsl(353, 35%, 67%); + --knock-out: hsl(346, 80%, 44%); + --careys-pink: hsl(352, 30%, 70%); + --dirty-pink: hsl(356, 43%, 64%); + --memphis-belle: hsl(352, 62%, 49%); + --flush-mahogany: hsl(360, 59%, 50%); + --pms5225: hsl(356, 23%, 74%); + --kidman: hsl(354, 17%, 76%); + --pms1797: hsl(359, 64%, 49%); + --ugly-pink: hsl(350, 47%, 63%); + --cabaret: hsl(347, 55%, 56%); + --mandy: hsl(356, 55%, 56%); + --pms500: hsl(357, 41%, 67%); + --pms186: hsl(353, 85%, 44%); + --cherry: hsl(345, 98%, 41%); + --rose: hsl(350, 53%, 60%); + --can: hsl(345, 43%, 68%); + --pms711: hsl(358, 65%, 50%); + --faded-red: hsl(358, 61%, 56%); + --pinkish: hsl(349, 55%, 62%); + --dusty-pink: hsl(352, 47%, 69%); + --mamma-mia: hsl(355, 37%, 74%); + --pms702: hsl(353, 59%, 61%); + --pms507: hsl(346, 50%, 69%); + --pink-flare: hsl(357, 32%, 78%); + --pms199: hsl(349, 77%, 48%); + --floyd: hsl(350, 46%, 73%); + --pms193: hsl(353, 55%, 68%); + --gelato: hsl(348, 33%, 79%); + --permanent-red-violet: hsl(350, 72%, 50%); + --blossom: hsl(348, 36%, 78%); + --faded-pink: hsl(346, 50%, 74%); + --boutique: hsl(347, 44%, 77%); + --pms5165: hsl(352, 27%, 83%); + --pms710: hsl(354, 72%, 57%); + --pms663: hsl(348, 21%, 86%); + --deep-blush: hsl(346, 67%, 66%); + --geranium-lake: hsl(351, 85%, 48%); + --madder-lake-deep: hsl(359, 76%, 54%); + --rose-madder: hsl(359, 76%, 55%); + --froly: hsl(356, 70%, 66%); + --pms679: hsl(349, 42%, 82%); + --pms192: hsl(346, 96%, 46%); + --carissma: hsl(348, 67%, 70%); + --vivid-amaranth: hsl(352, 100%, 45%); + --light-amaranth: hsl(353, 66%, 73%); + --brilliant-amaranth: hsl(352, 76%, 61%); + --pms701: hsl(356, 68%, 72%); + --pms508: hsl(351, 59%, 78%); + --pms185: hsl(352, 86%, 49%); + --devoted: hsl(353, 37%, 86%); + --material-girl: hsl(356, 76%, 62%); + --pms685: hsl(353, 51%, 83%); + --pms678: hsl(356, 42%, 86%); + --red-ribbon: hsl(346, 92%, 48%); + --pms197: hsl(353, 73%, 77%); + --pms684: hsl(357, 52%, 87%); + --pale-rose: hsl(350, 44%, 89%); + --pms1788: hsl(359, 86%, 55%); + --pinkish-red: hsl(345, 91%, 50%); + --wewak: hsl(354, 77%, 76%); + --pms709: hsl(353, 84%, 68%); + --pms700: hsl(356, 75%, 80%); + --pms494: hsl(356, 73%, 81%); + --pms509: hsl(355, 68%, 84%); + --pms670: hsl(356, 52%, 89%); + --pms495: hsl(357, 72%, 85%); + --pms510: hsl(356, 68%, 87%); + --pms1787: hsl(355, 89%, 60%); + --pms191: hsl(348, 89%, 62%); + --cherub: hsl(350, 60%, 90%); + --rapture: hsl(359, 91%, 62%); + --cherry-red: hsl(350, 98%, 49%); + --glamour-puss: hsl(350, 90%, 71%); + --carousel-pink: hsl(350, 67%, 92%); + --pms1775: hsl(355, 91%, 75%); + --pms708: hsl(354, 90%, 77%); + --pms1765: hsl(357, 88%, 80%); + --pms1767: hsl(356, 86%, 84%); + --pms182: hsl(358, 83%, 86%); + --carnation: hsl(357, 93%, 66%); + --red-pink: hsl(348, 95%, 57%); + --pms1777: hsl(354, 96%, 69%); + --pms190: hsl(349, 96%, 72%); + --pms183: hsl(353, 95%, 77%); + --pms1905: hsl(346, 94%, 80%); + --pms707: hsl(358, 93%, 83%); + --pms1895: hsl(350, 91%, 87%); + --pinky-red: hsl(351, 97%, 57%); + --pms1785: hsl(357, 97%, 65%); + --pms184: hsl(352, 96%, 68%); + --watermelon: hsl(354, 98%, 63%); + --wild-watermelon: hsl(349, 98%, 67%); + --blush-pink: hsl(355, 98%, 75%); + --reddish-pink: hsl(349, 99%, 58%); + --lightish-red: hsl(352, 99%, 59%); + --luminous-vivid-amaranth: hsl(352, 100%, 50%); + --light-brilliant-amaranth: hsl(353, 100%, 70%); + --light-brilliant-crimson: hsl(345, 100%, 70%); + --very-light-amaranth: hsl(353, 100%, 81%); + --very-light-crimson: hsl(345, 100%, 81%); + --pms189: hsl(350, 100%, 82%); + --pale-amaranth: hsl(353, 100%, 88%); + --pale-crimson: hsl(345, 100%, 88%); + --very-pale-crimson: hsl(346, 100%, 94%); + --cadmium-red-light: hsl(358, 100%, 51%); + --neon-red: hsl(348, 100%, 51%); + --light-red: hsl(358, 100%, 64%); + --coral-pink: hsl(359, 100%, 69%); + +} diff --git a/src/css/components/SGNForms/inputs/inline-input.css b/src/css/components/SGNForms/inputs/inline-input.css index c1ef9ad3..347151a1 100644 --- a/src/css/components/SGNForms/inputs/inline-input.css +++ b/src/css/components/SGNForms/inputs/inline-input.css @@ -1,27 +1,102 @@ /* - * Copyright (c) 2022 SGNetworks. All rights reserved. + * Copyright (c) 2022-2023 SGNetworks. All rights reserved. * * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. */ .sgn-inline-form { - display: flex; + display: inline-flex; flex-direction: row; - align-items: center; - justify-content: space-between; + align-items: stretch; + justify-content: stretch; + min-height: 100%; + max-height: 100%; border-radius: var(--sgn-border-radius-sm); - border: 1px solid var(--sgnf-border); + border: none; width: 100%; - overflow: hidden; + overflow: visible; +} + +.sgn-inline-form > * { + min-height: 100%; + max-height: 100%; + display: flex; + justify-content: center; + align-items: center; } -.sgn-inline-form > .sgn-form { +.sgn-inline-form > .sgn-form, +.sgn-inline-form > .sgn-form *:not(.sgn-input-autocomplete-box):not(.sgn-input-autocomplete-box *) { border: none; - border-radius: 0; + border-radius: 0 !important; line-height: 1; margin: 0; - flex: 1; +} + +.sgn-inline-form > .sgn-form > .sgn-input-autocomplete-box { + max-height: 220px; + position: absolute; + top: calc(100% + 2px); + width: calc(100% + 2px); + background-color: var(--sgn-accent-background); + border-radius: 0 0 var(--sgn-border-radius-sm) var(--sgn-border-radius-sm); + border: 1px solid var(--sgnf-border); + border-top-width: 0; +} + +.sgn-inline-form > .sgn-form.active > .sgn-input-autocomplete-box, +.sgn-inline-form > .sgn-form.edited > .sgn-input-autocomplete-box { + border-width: 3px; + border-top-width: 0; + width: calc(100% + (3px * 2)); + top: calc(100% + 3px); +} + +.sgn-inline-form > .sgn-form:hover > .sgn-input-autocomplete-box { + border-color: var(--sgnf-accent-hover); +} + + +.sgn-inline-form > .sgn-input-prefix, +.sgn-inline-form > .sgn-input-suffix { + background-color: var(--sgnf-background); + padding: var(--padding-sm) var(--padding-sm); + color: var(--sgnf-accent-inactive); + border-color: var(--sgn-accent-primary); + min-height: 100%; + max-height: 100%; + display: flex; + justify-content: center; +} + +.sgn-inline-form > .sgn-input-prefix { + border: 1px solid var(--sgnf-border); +} + +.sgn-inline-form > .sgn-input-suffix { + border: 1px solid var(--sgnf-border); +} + +.sgn-inline-form > .sgn-input-prefix.prefix-input, +.sgn-inline-form > .sgn-input-suffix.prefix-input { + flex: 1 1 50%; +} + +.sgn-inline-form > .sgn-input-prefix > .sgn-form, +.sgn-inline-form > .sgn-input-suffix > .sgn-form { + margin: 0; +} + +.sgn-inline-form > .sgn-input-prefix { + border-radius: var(--sgn-border-radius-sm) 0 0 var(--sgn-border-radius-sm) !important; + border-right-width: 0; +} + +.sgn-inline-form > .sgn-input-suffix, +.sgn-inline-form > *:last-child { + border-radius: 0 var(--sgn-border-radius-sm) var(--sgn-border-radius-sm) 0 !important; + border-left-width: 0; } .sgn-inline-form > .sgn-form:before, @@ -33,11 +108,6 @@ min-height: 2rem; } -.sgn-inline-form > .sgn-form > .sgn-form-wrapper > .sgn-input-prefix, -.sgn-inline-form > .sgn-form > .sgn-form-wrapper > .sgn-input-suffix { - border-color: var(--sgn-accent-primary); -} - .sgn-inline-form > .sgn-form.active > label, .sgn-inline-form > .sgn-form.edited > label, @@ -46,4 +116,4 @@ height: auto; width: auto; transform: scale(1) translateX(0) translateY(-1.6rem); -} \ No newline at end of file +} diff --git a/src/css/components/SGNForms/inputs/input.css b/src/css/components/SGNForms/inputs/input.css index eccb2748..101400c2 100644 --- a/src/css/components/SGNForms/inputs/input.css +++ b/src/css/components/SGNForms/inputs/input.css @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 SGNetworks. All rights reserved. + * Copyright (c) 2022-2023 SGNetworks. All rights reserved. * * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. @@ -40,8 +40,12 @@ select { .sgn-form { display: inline-flex; + align-items: center; + justify-content: center; flex-direction: column; - height: 100%; + min-height: 100%; + max-height: 100%; + width: 100%; position: relative; margin: var(--margin-md) 0; } @@ -50,10 +54,30 @@ select { border-radius: var(--sgn-border-radius-sm); border: 1px solid var(--sgnf-border); transition: border-width .3s linear, border-color .3s linear; +} + +.sgn-form:not(.sgn-input-checkbox):not(.sgn-input-radio):not(.sgn-input-switch):not(.sgn-select) { cursor: text; overflow: hidden; } +.sgn-form.disabled { + cursor: not-allowed !important; +} + +.sgn-form.disabled > .sgn-form-wrapper > .sgn-input-wrapper > .form-control, +.sgn-form.disabled > .sgn-form-wrapper > .sgn-input-wrapper > label, +.sgn-form.disabled > .sgn-input-autocomplete-box > li { + color: var(--sgnf-accent-disabled); + pointer-events: none !important; +} + +.sgn-form.readonly > .sgn-form-wrapper > .sgn-input-wrapper > .form-control, +.sgn-form.readonly > .sgn-form-wrapper > .sgn-input-wrapper > label, +.sgn-form.readonly > .sgn-input-autocomplete-box > li { + color: var(--sgnf-accent-readonly); +} + .sgn-form:not(.sgn-input-checkbox):not(.sgn-input-radio):not(.sgn-input-switch):not(.disabled):not([disabled]):hover { border-color: var(--sgnf-accent-hover); } @@ -70,8 +94,15 @@ select { .sgn-form > .sgn-form-wrapper > .sgn-input-wrapper { display: flex; align-items: center; - width: 100%; position: relative; + width: 100%; + min-height: 100%; + max-height: 100%; +} + +.sgn-form > .sgn-form-wrapper { + justify-content: stretch; + align-items: stretch; } .sgn-form > label, @@ -112,6 +143,8 @@ select { .sgn-form:not(.sgn-input-checkbox):not(.sgn-input-radio):not(.sgn-input-switch) > .sgn-form-wrapper > .sgn-input-wrapper > select { border: none; border-radius: var(--sgn-border-radius-sm); + min-height: 100%; + max-height: 100%; } .sgn-form > .sgn-form-wrapper > .sgn-input-prefix, @@ -119,6 +152,10 @@ select { background-color: var(--sgnf-background); padding: var(--padding-sm) var(--padding-sm); color: var(--sgnf-accent-inactive); + min-height: 100%; + max-height: 100%; + display: flex; + justify-content: stretch; } .sgn-form > .sgn-form-wrapper > .sgn-input-prefix { @@ -131,9 +168,26 @@ select { border-radius: 0 var(--sgn-border-radius-sm) var(--sgn-border-radius-sm) 0; } +.sgn-form > .sgn-form-wrapper > .sgn-input-prefix > .sgn-form, +.sgn-form > .sgn-form-wrapper > .sgn-input-suffix > .sgn-form { + margin: 0; +} + +.sgn-form > .sgn-form-wrapper > .sgn-input-prefix > .sgn-form.sgn-select, +.sgn-form > .sgn-form-wrapper > .sgn-input-suffix > .sgn-form.sgn-select { + z-index: 9999; + cursor: pointer; +} + +.sgn-form > .sgn-form-wrapper > .sgn-input-prefix > .sgn-form.sgn-select > .sgn-form-wrapper > .sgn-input-wrapper > .sgn-select-input, +.sgn-form > .sgn-form-wrapper > .sgn-input-suffix > .sgn-form.sgn-select > .sgn-form-wrapper > .sgn-input-wrapper > .sgn-select-input { + z-index: 0; + cursor: pointer; +} + .sgn-form > .sgn-form-help-block { line-height: 1; - background-color: var(--sgnf-background); + background-color: var(--sgnf-background-inactive-light); color: var(--sgnf-accent-inactive); font-size: .8rem; display: flex; @@ -156,21 +210,71 @@ select { position: relative; } -.sgn-form > .sgn-form-help-block.has-marquee > .sgn-marquee-wrapper, -.sgn-form > .sgn-form-help-block.has-marquee > .js-marquee-wrapper { +.sgn-form > .sgn-form-help-block.has-marquee > .sgn-marquee-wrapper { position: absolute; font-size: inherit; } -.sgn-form > .sgn-form-help-block.has-marquee > .sgn-marquee-wrapper > .sgn-marquee, -.sgn-form > .sgn-form-help-block.has-marquee > .js-marquee-wrapper > .js-marquee { +.sgn-form > .sgn-form-help-block.has-marquee > .sgn-marquee-wrapper > .sgn-marquee { padding: 0 20%; font-size: inherit; } -.sgn-form:not(.sgn-input-checkbox):not(.sgn-input-radio):not(.sgn-input-switch).active, -.sgn-form:not(.sgn-input-checkbox):not(.sgn-input-radio):not(.sgn-input-switch).edited, +.sgn-form > .sgn-input-autocomplete-box { + padding: 0; + opacity: 0; + pointer-events: none; + width: 100%; + max-height: 280px; + overflow-y: auto; + display: flex; + flex-direction: column; + justify-content: start; + align-items: start; + transition: border-width, border-color .3s linear; +} + +.sgn-form > .sgn-input-autocomplete-box > li { + list-style: none; + padding: var(--padding-sm) var(--padding-sm); + display: none; + width: 100%; + cursor: pointer; + border-radius: var(--sgn-border-radius-sm); + color: var(--sgn-secondary); +} + +.sgn-form.autocomplete-active > .sgn-input-autocomplete-box { + padding: var(--padding-sm) var(--padding-sm); + opacity: 1; + pointer-events: auto; + border-top: 1px solid var(--sgnf-border); +} + +.sgn-form.autocomplete-active > .sgn-input-autocomplete-box > li { + display: block; + border-radius: var(--sgn-border-radius-sm); + transition: background-color .5s linear; +} + +.sgn-form.autocomplete-active > .sgn-input-autocomplete-box > li:hover { + background-color: var(--sgn-background-primary-dark); + transition: background-color .3s linear; +} + +.sgn-form.disabled.autocomplete-active > .sgn-input-autocomplete-box, +.sgn-form.readonly.autocomplete-active > .sgn-input-autocomplete-box { + cursor: not-allowed !important; +} + +.sgn-form.readonly.autocomplete-active > .sgn-input-autocomplete-box > li { + pointer-events: none; +} + + +.sgn-form:not(.sgn-input-checkbox):not(.sgn-input-radio):not(.sgn-input-switch):not(.sgn-select).active, +.sgn-form:not(.sgn-input-checkbox):not(.sgn-input-radio):not(.sgn-input-switch):not(.sgn-select).edited, fieldset.active, fieldset.edited { border-width: 3px; @@ -187,6 +291,77 @@ fieldset.edited { border-radius: 0 calc(var(--sgn-border-radius-sm) - .2rem) calc(var(--sgn-border-radius-sm) - .2rem) 0; } +.sgn-form > .sgn-input-prefix.prefix-input, +.sgn-form > .sgn-input-suffix.prefix-input { + flex: 1 1 50%; +} + + +.sgn-form > .sgn-form-wrapper > .sgn-input-overlay, +.sgn-form > .sgn-form-wrapper > .sgn-input-wrapper.has-input-overlay-prefix > .sgn-input-overlay-prefix, +.sgn-form > .sgn-form-wrapper > .sgn-input-wrapper.has-input-overlay-suffix > .sgn-input-overlay-suffix { + color: var(--sgn-text-secondary); + font-size: 1.5rem; +} + +.sgn-form > .sgn-form-wrapper > .sgn-input-overlay { + position: absolute; + top: 50%; + bottom: 50%; + right: var(--padding-xs); + transform: translateY(-50%); +} + +.sgn-form > .sgn-form-wrapper > .sgn-input-overlay.prefix, +.sgn-form > .sgn-form-wrapper > .sgn-input-wrapper.has-input-overlay-prefix > .sgn-input-overlay-prefix { + right: unset; + left: var(--padding-xs); +} + +.sgn-form > .sgn-form-wrapper.has-input-overlay-prefix > .sgn-input-wrapper > .sgn-input-overlay, +.sgn-form > .sgn-form-wrapper.has-input-overlay-suffix > .sgn-input-wrapper > .sgn-input-overlay, +.sgn-form > .sgn-form-wrapper > .sgn-input-wrapper.has-input-overlay-prefix > .sgn-input-overlay-prefix, +.sgn-form > .sgn-form-wrapper > .sgn-input-wrapper.has-input-overlay-suffix > .sgn-input-overlay-suffix { + color: var(--sgn-text-secondary); + position: relative; + margin: 0 var(--margin-sm); + font-size: 1.5rem; +} + +.sgn-form > .sgn-form-wrapper.has-input-overlay-prefix > .sgn-input-wrapper > .form-control, +.sgn-form > .sgn-form-wrapper.has-input-overlay-suffix > .sgn-input-wrapper > .form-control, +.sgn-form > .sgn-form-wrapper > .sgn-input-wrapper.has-input-overlay-prefix > .form-control, +.sgn-form > .sgn-form-wrapper > .sgn-input-wrapper.has-input-overlay-suffix > .form-control { + padding-right: 0; +} + +.sgn-form > .sgn-form-wrapper > .sgn-input-overlay.interactive, +.sgn-form > .sgn-form-wrapper > .sgn-input-overlay-prefix.interactive, +.sgn-form > .sgn-form-wrapper > .sgn-input-overlay-suffix.interactive, +.sgn-form > .sgn-form-wrapper > .sgn-input-wrapper.has-input-overlay-prefix > .sgn-input-overlay-prefix.interactive, +.sgn-form > .sgn-form-wrapper > .sgn-input-wrapper.has-input-overlay-suffix > .sgn-input-overlay-suffix.interactive { + cursor: pointer; + z-index: 2; + transition: color .3s linear; +} + +.sgn-form > .sgn-form-wrapper > .sgn-input-overlay.interactive:hover, +.sgn-form > .sgn-form-wrapper > .sgn-input-overlay-prefix.interactive:hover, +.sgn-form > .sgn-form-wrapper > .sgn-input-overlay-suffix.interactive:hover, +.sgn-form > .sgn-form-wrapper > .sgn-input-wrapper.has-input-overlay-prefix > .sgn-input-overlay-prefix.interactive:hover, +.sgn-form > .sgn-form-wrapper > .sgn-input-wrapper.has-input-overlay-suffix > .sgn-input-overlay-suffix.interactive:hover { + color: var(--sgn-accent-secondary); +} + +.sgn-form > .sgn-form-wrapper > .sgn-input-overlay.interactive:active, +.sgn-form > .sgn-form-wrapper > .sgn-input-overlay-prefix.interactive:active, +.sgn-form > .sgn-form-wrapper > .sgn-input-overlay-suffix.interactive:active, +.sgn-form > .sgn-form-wrapper > .sgn-input-wrapper.has-input-overlay-prefix > .sgn-input-overlay-prefix.interactive:active, +.sgn-form > .sgn-form-wrapper > .sgn-input-wrapper.has-input-overlay-suffix > .sgn-input-overlay-suffix.interactive:active { + color: var(--sgn-accent-secondary-active); +} + + .sgn-form:not(.sgn-input-checkbox):not(.sgn-input-radio):not(.sgn-input-switch).active > label, .sgn-form:not(.sgn-input-checkbox):not(.sgn-input-radio):not(.sgn-input-switch).edited > label, .sgn-form:not(.sgn-input-checkbox):not(.sgn-input-radio):not(.sgn-input-switch).active > .sgn-form-wrapper > .sgn-input-wrapper > label, @@ -220,26 +395,28 @@ fieldset.edited { } -.sgn-form:not(.sgn-input-checkbox):not(.sgn-input-radio):not(.sgn-input-switch).active, -fieldset.active { +.sgn-form:not(.disabled):not(.sgn-input-checkbox):not(.sgn-input-radio):not(.sgn-input-switch).active, +.sgn-form:not(.disabled).autocomplete-active.active > .sgn-input-autocomplete-box, +fieldset:not(.disabled).active { border-color: var(--sgnf-accent-active); } -.sgn-form:not(.sgn-input-checkbox):not(.sgn-input-radio):not(.sgn-input-switch).active > label, -.sgn-form:not(.sgn-input-checkbox):not(.sgn-input-radio):not(.sgn-input-switch).active > .sgn-form-wrapper > .sgn-input-wrapper > label, -fieldset.active > legend { +.sgn-form:not(.disabled):not(.sgn-input-checkbox):not(.sgn-input-radio):not(.sgn-input-switch).active > label, +.sgn-form:not(.disabled):not(.sgn-input-checkbox):not(.sgn-input-radio):not(.sgn-input-switch).active > .sgn-form-wrapper > .sgn-input-wrapper > label, +fieldset:not(.disabled).active > legend { color: var(--sgnf-accent-active); z-index: 2; } -.sgn-form.active > .sgn-form-help-block, -.sgn-form.active > .sgn-form-wrapper > .sgn-form-help-block { +.sgn-form:not(.disabled).active > .sgn-form-help-block, +.sgn-form:not(.disabled).active > .sgn-form-wrapper > .sgn-form-help-block { background-color: var(--sgnf-background-active-light); color: var(--sgnf-accent-active); } -.sgn-form.valid, +.sgn-form:not(.sgn-input-checkbox):not(.sgn-input-radio):not(.sgn-input-switch).valid, +.sgn-form.autocomplete-active.valid > .sgn-input-autocomplete-box, fieldset.valid { border-color: var(--sgnf-accent-valid); } @@ -258,6 +435,7 @@ fieldset.valid { .sgn-form:not(.sgn-input-checkbox):not(.sgn-input-radio):not(.sgn-input-switch).invalid, +.sgn-form.autocomplete-active.invalid > .sgn-input-autocomplete-box, fieldset.invalid { border-color: var(--sgnf-accent-invalid); } diff --git a/src/css/components/components.css b/src/css/components/components.css index d8594e7a..72621940 100644 --- a/src/css/components/components.css +++ b/src/css/components/components.css @@ -5,22 +5,24 @@ * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. */ +@import "containers.css"; @import "preloaders.css"; -@import "sidebar2.css"; -@import "navbar.css"; -@import "tables.css"; -@import "cards.css"; -@import "modals.css"; @import "buttons.css"; -@import "SGNForms/SGNForms.css"; -@import "snackbar.css"; -@import "progressbars.css"; -@import "SGNLoadingDialog.css"; +@import "cards.css"; @import "code.css"; @import "ellipsify.css"; @import "listgroup.css"; +@import "modals.css"; +@import "navbar.css"; +@import "progressbars.css"; +@import "sections.css"; +@import "SGNForms/SGNForms.css"; +@import "SGNLoadingDialog.css"; +@import "sidebar2.css"; +@import "snackbar.css"; @import "tablayout.css"; +@import "tables.css"; @import "views.css"; -@import "wizard.css"; @import "windows.css"; +@import "wizard.css"; diff --git a/src/css/components/containers.css b/src/css/components/containers.css new file mode 100644 index 00000000..23585b64 --- /dev/null +++ b/src/css/components/containers.css @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022-2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +.container { + padding: 0 15px; + margin: 0 auto; + width: 100%; +} + +@media only screen and (min-width: 768px) { + .container { + max-width: 720px; + } +} + +@media only screen and (min-width: 992px) { + .container { + max-width: 960px; + } +} + +@media only screen and (min-width: 1200px) { + .container { + max-width: 1170px; + } +} + +.container-fluid { + width: 100%; + padding: 0 15px; + margin: 0 auto; +} diff --git a/src/css/components/sections.css b/src/css/components/sections.css new file mode 100644 index 00000000..ad656f96 --- /dev/null +++ b/src/css/components/sections.css @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2022-2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +section.banner, +section.banner * { + --banner-container-bg-blur-intensity: 5px; +} + +@media all and (prefers-color-scheme: light) { + section.banner, + section.banner * { + --banner-container-bg-color: hsla(0, 0%, 50%, .5); + } +} + +@media all and (prefers-color-scheme: dark) { + section.banner, + section.banner * { + --banner-container-bg-color: hsla(0, 0%, 0%, .5); + } +} + +section.banner { + /*! display: flex; */ + justify-content: center; + align-items: center; + position: relative; + overflow: hidden; +} + +section.banner > .section-img-overlay { + width: 100%; + height: 100vh; + z-index: -1; +} + +section.banner > .section-img-overlay > img { + width: 100%; + max-height: 100%; + display: flex; +} + +section.banner > .section-img-overlay.blur { + filter: blur(4px); +} + +section.banner > .container-fluid, +section.banner > .container, +section.banner > .welcome { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + color: var(--sgn-accent-primary-text); + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + overflow: visible; +} + +section.banner > .container-fluid, +section.banner > .container { + margin: 0; + padding: 0; + min-width: 100%; + min-height: 100%; + max-width: 100%; + max-height: 100%; + background-color: var(--banner-container-bg-color, hsla(210, 50%, 50%, .5)); + backdrop-filter: var(--banner-container-bg-blur-intensity, blur(5px)); +} + +section.banner > .container-fluid > .welcome, +section.banner > .container > .welcome, +section.banner > .welcome { + max-width: calc(100% - 10rem); + max-height: calc(100% - (60px * 2)); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +section.banner > .container-fluid > .welcome > h1, +section.banner > .container > .welcome > h1, +section.banner > .container-fluid > .welcome > h6, +section.banner > .container > .welcome > h6, +section.banner > .welcome > h1, +section.banner > .welcome > h6 { + margin: 0; +} + +section.banner > .container-fluid > .welcome > h1, +section.banner > .container > .welcome > h1, +section.banner > .welcome > h1 { + font-size: 3rem; + color: var(--sgn-accent-primary); +} + +section.banner > .container-fluid > .welcome > h6, +section.banner > .container > .welcome > h6, +section.banner > .welcome > h6 { + font-size: 1.4rem; + color: var(--sgn-text-secondary-light); +} + +section.banner > .container > .auto-grid, +section.banner > .container > .row, +section.banner > .container > .card { + width: 100%; +} + +section.banner > .container > .title { + color: var(--sgn-accent-primary); + mix-blend-mode: hard-light; + text-transform: uppercase; + font-size: 3.5rem; + font-family: var(--sgn-font-default-bold); +} diff --git a/src/css/utilities/autogrid.css b/src/css/utilities/autogrid.css index 4eb4f866..b42f96fd 100644 --- a/src/css/utilities/autogrid.css +++ b/src/css/utilities/autogrid.css @@ -1,10 +1,12 @@ /* - * Copyright (c) 2022 SGNetworks. All rights reserved. + * Copyright (c) 2022-2023 SGNetworks. All rights reserved. * * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. */ +@import "grids.css"; + .auto-grid { align-items: flex-start; display: flex; diff --git a/src/css/utilities/background-colors.css b/src/css/utilities/background-colors.css new file mode 100644 index 00000000..5edfc03b --- /dev/null +++ b/src/css/utilities/background-colors.css @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2022-2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +.bg-black { + background-color: var(--black) !important; +} + +.bg-grey { + background-color: var(--grey) !important; +} + +.bg-cod-grey { + background-color: var(--cod-grey) !important; +} + +.bg-all-black { + background-color: var(--all-black) !important; +} + +.bg-eerie-black { + background-color: var(--eerie-black) !important; +} + +.bg-filmpro-black { + background-color: var(--filmpro-black) !important; +} + +.bg-mine-shaft { + background-color: var(--mine-shaft) !important; +} + +.bg-jet { + background-color: var(--jet) !important; +} + +.bg-davy-grey { + background-color: var(--davy-grey) !important; +} + +.bg-granite-gray { + background-color: var(--granite-gray) !important; +} + +.bg-dim-gray { + background-color: var(--dim-gray) !important; +} + +.bg-sonic-silver { + background-color: var(--sonic-silver) !important; +} + +.bg-gray { + background-color: var(--gray) !important; +} + +.bg-spanish-gray { + background-color: var(--spanish-gray) !important; +} + +.bg-quick-silver { + background-color: var(--quick-silver) !important; +} + +.bg-dark-gray-x11 { + background-color: var(--dark-gray-x11) !important; +} + +.bg-silver-chalice { + background-color: var(--silver-chalice) !important; +} + +.bg-gray-x11-gray { + background-color: var(--gray-x11-gray) !important; +} + +.bg-silver { + background-color: var(--silver) !important; +} + +.bg-light-gray { + background-color: var(--light-gray) !important; +} + +.bg-gainsboro { + background-color: var(--gainsboro) !important; +} + +.bg-cultured { + background-color: var(--cultured) !important; +} + +.bg-white { + background-color: var(--white) !important; +} + diff --git a/src/css/utilities/colors.css b/src/css/utilities/colors.css index e834fa55..85ac0904 100644 --- a/src/css/utilities/colors.css +++ b/src/css/utilities/colors.css @@ -1,10 +1,11 @@ /* - * Copyright (c) 2022 SGNetworks. All rights reserved. + * Copyright (c) 2022-2023 SGNetworks. All rights reserved. * * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. */ +@import "background-colors.css"; @import "text-colors.css"; @import "gradients.css"; @@ -21,22 +22,6 @@ color: var(--sgn-success); } -.text-primary { - color: var(--sgn-accent-primary); -} - -.text-secondary { - color: var(--sgn-accent-secondary); -} - -.text-black { - color: hsla(0, 0%, 0%, 1); -} - -.text-white { - color: hsla(0, 0%, 100%, 1); -} - .tw-ic { color: #55acee !important; @@ -54,3 +39,29 @@ color: #4b515d !important; } + +:root { + --black: hsl(0, 0%, 0%); + --grey: hsl(0, 0%, 1%); + --cod-grey: hsl(0, 0%, 4%); + --all-black: hsl(0, 0%, 9%); + --eerie-black: hsl(0, 0%, 11%); + --filmpro-black: hsl(0, 0%, 16%); + --mine-shaft: hsl(0, 0%, 20%); + --jet: hsl(0, 0%, 20%); + --davy-grey: hsl(0, 0%, 33%); + --granite-gray: hsl(0, 0%, 40%); + --dim-gray: hsl(0, 0%, 41%); + --sonic-silver: hsl(0, 0%, 46%); + --gray: hsl(0, 0%, 50%); + --spanish-gray: hsl(0, 0%, 60%); + --quick-silver: hsl(0, 0%, 65%); + --dark-gray-x11: hsl(0, 0%, 66%); + --silver-chalice: hsl(0, 0%, 67%); + --gray-x11-gray: hsl(0, 0%, 75%); + --silver: hsl(0, 0%, 75%); + --light-gray: hsl(0, 0%, 83%); + --gainsboro: hsl(0, 0%, 86%); + --cultured: hsl(0, 0%, 96%); + --white: hsl(0, 0%, 100%); +} diff --git a/src/css/utilities/grids.css b/src/css/utilities/grids.css new file mode 100644 index 00000000..429df591 --- /dev/null +++ b/src/css/utilities/grids.css @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2023 SGNetworks. All rights reserved. + * + * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. + * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. + */ + +/*! + * Favorite Grid v.1.0 + * Author : Ali Norouzi ( https://github.com/anorouzii ) + * Licensed under MIT ( https://github.com/anorouzii/favorite-grid/blob/master/LICENSE ) +*/ + +/************* Row *************/ +.row { + /*! margin: 0 -15px; */ + width: 100%; + max-width: 100%; + display: flex; + flex-wrap: wrap; +} + +.row:after { + content: ""; + display: table; + clear: both; +} + +.row [class^="col"] { + position: relative; + min-height: 1px; + padding: 0 15px; + float: right; +} + +/************* Default column *************/ +.col-auto { + flex: 0 0 auto; + width: auto; +} + +.col { + flex: 1 0 0; +} + +.col-1 { + width: 8.33333%; +} + +.col-2 { + width: 16.66667%; +} + +.col-3 { + width: 25%; +} + +.col-4 { + width: 33.33333%; +} + +.col-5 { + width: 41.66667%; +} + +.col-6 { + width: 50%; +} + +.col-7 { + width: 58.33333%; +} + +.col-8 { + width: 66.66667%; +} + +.col-9 { + width: 75%; +} + +.col-10 { + width: 83.33333%; +} + +.col-11 { + width: 91.66667%; +} + +.col-12 { + width: 100%; +} + +/************* XLarge Device column *************/ +@media only screen and (min-width: 1200px) { + .col-xl-auto { + flex: 0 0 auto; + width: auto; + } + + .col-xl-1 { + width: 8.33333%; + } + + .col-xl-2 { + width: 16.66667%; + } + + .col-xl-3 { + width: 25%; + } + + .col-xl-4 { + width: 33.33333%; + } + + .col-xl-5 { + width: 41.66667%; + } + + .col-xl-6 { + width: 50%; + } + + .col-xl-7 { + width: 58.33333%; + } + + .col-xl-8 { + width: 66.66667%; + } + + .col-xl-9 { + width: 75%; + } + + .col-xl-10 { + width: 83.33333%; + } + + .col-xl-11 { + width: 91.66667%; + } + + .col-xl-12 { + width: 100%; + } +} + +/************* Large Device column *************/ +@media only screen and (min-width: 992px) { + .col-lg-auto { + flex: 0 0 auto; + width: auto; + } + + .col-lg-1 { + width: 8.33333%; + } + + .col-lg-2 { + width: 16.66667%; + } + + .col-lg-3 { + width: 25%; + } + + .col-lg-4 { + width: 33.33333%; + } + + .col-lg-5 { + width: 41.66667%; + } + + .col-lg-6 { + width: 50%; + } + + .col-lg-7 { + width: 58.33333%; + } + + .col-lg-8 { + width: 66.66667%; + } + + .col-lg-9 { + width: 75%; + } + + .col-lg-10 { + width: 83.33333%; + } + + .col-lg-11 { + width: 91.66667%; + } + + .col-lg-12 { + width: 100%; + } +} + +/************* Medium Device column *************/ +@media only screen and (min-width: 768px) { + .col-md-auto { + flex: 0 0 auto; + width: auto; + } + + .col-md-1 { + width: 8.33333%; + } + + .col-md-2 { + width: 16.66667%; + } + + .col-md-3 { + width: 25%; + } + + .col-md-4 { + width: 33.33333%; + } + + .col-md-5 { + width: 41.66667%; + } + + .col-md-6 { + width: 50%; + } + + .col-md-7 { + width: 58.33333%; + } + + .col-md-8 { + width: 66.66667%; + } + + .col-md-9 { + width: 75%; + } + + .col-md-10 { + width: 83.33333%; + } + + .col-md-11 { + width: 91.66667%; + } + + .col-md-12 { + width: 100%; + } +} + +/************* Small Device column *************/ +@media only screen and (min-width: 480px) { + .col-sm-auto { + flex: 0 0 auto; + width: auto; + } + + .col-sm-1 { + width: 8.33333%; + } + + .col-sm-2 { + width: 16.66667%; + } + + .col-sm-3 { + width: 25%; + } + + .col-sm-4 { + width: 33.33333%; + } + + .col-sm-5 { + width: 41.66667%; + } + + .col-sm-6 { + width: 50%; + } + + .col-sm-7 { + width: 58.33333%; + } + + .col-sm-8 { + width: 66.66667%; + } + + .col-sm-9 { + width: 75%; + } + + .col-sm-10 { + width: 83.33333%; + } + + .col-sm-11 { + width: 91.66667%; + } + + .col-sm-12 { + width: 100%; + } +} diff --git a/src/css/utilities/texts.css b/src/css/utilities/texts.css index 0a993019..f0246860 100644 --- a/src/css/utilities/texts.css +++ b/src/css/utilities/texts.css @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 SGNetworks. All rights reserved. + * Copyright (c) 2022-2023 SGNetworks. All rights reserved. * * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. @@ -12,4 +12,75 @@ .sgn-placeholder-container > .sgn-placeholder-text { font-size: 4rem; line-height: 1; -} \ No newline at end of file +} + +.text-uppercase { + text-transform: uppercase !important; +} + +.text-lowercase { + text-transform: lowercase !important; +} + +.text-capitalize { + text-transform: capitalize !important; +} + +.text-transform-none { + text-transform: none !important; +} + + +.text-align-left { + text-align: left !important; +} + +.text-align-center { + text-align: center !important; +} + +.text-align-right { + text-align: right !important; +} + +.text-align-start { + text-align: start !important; +} + +.text-align-end { + text-align: end !important; +} + +.text-align-justify { + text-align: justify !important; +} + +.text-align-justify-all { + text-align: justify-all !important; +} + +.text-align-match-parent { + text-align: match-parent !important; +} + +.text-align-inherit { + text-align: inherit !important; +} + +.text-align-initial { + text-align: initial !important; +} + +.text-align-revert { + text-align: revert !important; +} + +.text-align-unset { + text-align: unset !important; +} + + +.gradient-text { + -webkit-text-fill-color: transparent; + background-clip: text; +} diff --git a/src/js/SGNUIKit.loader.js b/src/js/SGNUIKit.loader.js index 8a7d9ffd..3349511b 100644 --- a/src/js/SGNUIKit.loader.js +++ b/src/js/SGNUIKit.loader.js @@ -5,12 +5,69 @@ * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. */ +/** + * Performs the specified action for each element in an object. + * + * @param {Object} obj + * @param {(value:any, key:string)=>void} callback A function that accepts up to three arguments. forEach calls the callback function one time for each element in the object. + */ +const forEach = (obj, callback) => { + let value; + //context = context || this; //apply the function to 'this' by default + + for(const key in obj) { + if(key !== 'length' && obj.hasOwnProperty(key)) { //to rule out inherited properties + value = obj[key]; + if(typeof callback === 'function') + callback(value, key); + } + } +} + +/** + * Appends new elements to the end of an object, and returns the new length of the object. + * @param {Object} obj + * @param {...any} items New elements to add to the object. + */ +const push = (obj, ...items) => { + let k = obj.length || 0; + + items.forEach((value) => { + obj[k] = value; + k++; + obj.length = k; + }); +} + const SGNUIKit = { isReady: false, + isInit: false, isPreloaderHeld: false, + configs: { + 'urls': { + 'api': { + 'geonames': 'https://secure.geonames.org/', + 'osm': 'https://nominatim.openstreetmap.org/' + }, + }, + 'api': { + 'geonames': '' //username + }, + 'geocoding': { + 'defaultAPI': 'osm' + } + }, components: {}, - onChangeListener: [], - onReadyListener: [], + onChangeListener: {}, + onInitListener: {}, + onReadyListener: {}, + callCounts: { + 'init': 0, + 'ready': 0, + 'config': 0, + 'component': 0, + 'holdPreloader': 0, + }, /** * This callback is called when a component is loaded/removed or the status of readiness is changed. @@ -30,14 +87,39 @@ const SGNUIKit = { /** * Add a loaded SGNUIKit component. * - * @param {JSON} value The JSON object of the loaded SGNUIKit component. + * @param {{}} config The JSON object of the SGNUIKit configuration options. + */ + set config(config) { + if(config !== undefined && config !== null && config !== "") { + this.configs = new SGNUKConfig(config); + this.callCounts.config++; + + forEach(this.onChangeListener, (listener) => listener("config", config, this.configs)); + } + }, + + /** + * Get the list of loaded SGNUIKit components. + * + * @return {Object} The JSON object of loaded SGNUIKit components, or an empty JSON object if no components loaded. + */ + get config() { + return this.configs; + }, + + /** + * Add a loaded SGNUIKit component. + * + * @param {{}} value The JSON object of the loaded SGNUIKit component. */ set component(value) { - if(value === undefined || value === null || value === "") - value = {}; - Object.assign(this.components, value); + if(value !== undefined && value !== null && value !== "") { + Object.assign(this.components, value); + this.callCounts.component++; - this.onChangeListener.forEach((listener) => listener("components", value, this.components)); + forEach(this.onChangeListener, (listener) => listener("components", value, this.components)); + //this.onChangeListener.forEach((listener) => listener("components", value, this.components)); + } }, /** @@ -49,6 +131,38 @@ const SGNUIKit = { return this.components; }, + /** + * Check if a SGNUIKit component is loaded. + * + * @param {string|number} id The ID of the SGNUIKit component to check. + */ + isComponentLoaded: function(id) { + return this.components.hasOwnProperty(id); + }, + + /** + * Set the status of readiness of SGNUIKit. + * + * @param {boolean} isInit The the status of readiness of SGNUIKit. + */ + set init(isInit) { + this.isInit = isInit; + this.callCounts.init++; + forEach(this.onChangeListener, (listener) => listener("init", this.isInit)); + + if(isInit) + forEach(this.onInitListener, (listener) => listener(isInit)); + }, + + /** + * Get the status of readiness of SGNUIKit. + * + * @return {boolean} TRUE if SGNUIKit is ready, FALSE otherwise. + */ + get init() { + return this.isInit; + }, + /** * Set the status of readiness of SGNUIKit. * @@ -56,10 +170,13 @@ const SGNUIKit = { */ set ready(isReady) { this.isReady = isReady; - this.onChangeListener.forEach((listener) => listener("ready", this.isReady)); + this.callCounts.ready++; + forEach(this.onChangeListener, (listener) => listener("ready", this.isReady)); + //this.onChangeListener.forEach((listener) => listener("ready", this.isReady)); if(isReady) - this.onReadyListener.forEach((listener) => listener(isReady)); + forEach(this.onReadyListener, (listener) => listener(isReady)); + //this.onReadyListener.forEach((listener) => listener(isReady)); }, /** @@ -78,7 +195,9 @@ const SGNUIKit = { */ set holdPreloader(hold) { this.isPreloaderHeld = hold; - this.onChangeListener.forEach((listener) => listener("holdPreloader", this.isPreloaderHeld)); + this.callCounts.holdPreloader++; + forEach(this.onChangeListener, (listener) => listener("holdPreloader", this.isPreloaderHeld)); + //this.onChangeListener.forEach((listener) => listener("holdPreloader", this.isPreloaderHeld)); }, /** @@ -94,21 +213,46 @@ const SGNUIKit = { * Set the handler for SGNUIKit OnChange event, which will be triggered when a component is loaded/removed or the status of readiness is changed. * * @param {SGNUIKitChangeCallback}listener + * @param {string|number}[id=undefined] */ - setOnChangeListener: function(listener) { - this.onChangeListener.push(listener); + setOnChangeListener: function(listener, id) { + if(typeof id !== 'string' || $.isNumeric(id)) + this.onChangeListener[id] = listener; + else + push(this.onChangeListener, listener); }, /** * Set the handler for SGNUIKit OnReady event, which will be triggered when the SGNUIKit is ready. * * @param {SGNUIKitReadyCallback}listener + * @param {string|number}[id=undefined] */ - setOnReadyListener: function(listener) { - this.onReadyListener.push(listener); + setOnInitListener: function(listener, id) { + if(typeof id !== 'string' || $.isNumeric(id)) + this.onInitListener[id] = listener; + else + push(this.onInitListener, listener); + + if(this.init) + forEach(this.onInitListener, (listener) => listener(this.isInit)); + }, + + /** + * Set the handler for SGNUIKit OnReady event, which will be triggered when the SGNUIKit is ready. + * + * @param {SGNUIKitReadyCallback}listener + * @param {string|number}[id=undefined] + */ + setOnReadyListener: function(listener, id) { + if(typeof id !== 'string' || $.isNumeric(id)) + this.onReadyListener[id] = listener; + else + push(this.onReadyListener, listener); if(this.ready) - this.onReadyListener.forEach((listener) => listener(this.ready)); + forEach(this.onReadyListener, (listener) => listener(this.isReady)); + //this.onReadyListener.forEach((listener) => listener(this.ready)); }, }; window.SGNUIKit = SGNUIKit; @@ -2127,6 +2271,160 @@ if(typeof jQuery === 'undefined') { }); } +const SUKRInstances = { + instances: {}, + onChangeListener: {}, + onCreateListener: {}, + + /** + * Add a loaded SGNUIKit component. + * + * @param {{}} value The JSON object of the loaded SGNUIKit component. + */ + set instance(value) { + if(value === undefined || value === null || value === "") + value = {}; + push(this.instances, value); + + //console.log(SGNUIKit); + + forEach(this.onChangeListener, (listener) => listener(value, this.instances)); + //SGNUIKit.setOnReadyListener(() => forEach(this.onCreateListener, (listener) => listener(this.instances)), 'sgn-ukr-create-listener'); + }, + + /** + * Get the list of loaded SGNUIKit components. + * + * @return {object} The JSON object of loaded SGNUIKit components, or an empty JSON object if no components loaded. + */ + get instance() { + return this.instances; + }, + /** + * Set the handler for SGNUIKit OnChange event, which will be triggered when a component is loaded/removed or the status of readiness is changed. + * + * @param {(newInstance:{}, instances:{})=>void}listener + * @param {string|number}[id=undefined] + */ + setOnChangeListener: function(listener, id) { + if(typeof id !== 'string' || $.isNumeric(id)) + this.onChangeListener[id] = listener; + else + push(this.onChangeListener, listener); + + forEach(this.onChangeListener, (listener) => listener('', this.instances)); + }, + + /** + * Set the handler for SGNUIKit OnChange event, which will be triggered when a component is loaded/removed or the status of readiness is changed. + * + * @param {(newInstance:{}, instances:{})=>void}listener + * @param {string|number}[id=undefined] + */ + setOnCreateListener: function(listener, id) { + if(typeof id !== 'string' || $.isNumeric(id)) + this.onCreateListener[id] = listener; + else + push(this.onCreateListener, listener); + + SGNUIKit.setOnReadyListener(() => forEach(this.onCreateListener, (listener) => listener(this.instances)), 'sgn-ukr-create-listener'); + }, +}; + +/*** + * SUKR (SGNUIKit Ready) callback is used to determine if the page is loaded and ready to use. It combines internal SGNUIKit ready events as well as jQuery `$(function(){})` callback. + *
+ * NOTE: If SGNAtom is used then, the SUKR callback will be called after the DOM is ready and the Default Page is loaded by SGNAtom. + * + * @param {(value:boolean)=>void} callback + */ +window.SUKR = (callback) => { + const SUKRinit = function() { + const plugin = this; + plugin.onReadyListener = {}; + + const callerStack = getStack()[0], + caller = `${callerStack.file.name}.${callerStack.signature}:${callerStack.line}:${callerStack.column}` || null; + + if(caller) + plugin.onReadyListener[caller] = callback; + else + push(plugin.onReadyListener, callback); + + plugin.trigger = () => { + forEach(plugin.onReadyListener, (listener) => listener(true)); + } + } + + const getStack = (search = null) => { + const regex = /^(?)? ?([a-zA-Z0-9*/<]+)? ?@?(https?:\/\/[a-z\d-_]+\.?[a-z\d-_]+[^\s:"]+):(\d+):?(\d+)?$/; + const errors = [], + stack = (new Error()).stack; + + //console.log(stack); + + function getFilenameAndExtension(path) { + if(path !== undefined) { + const filenameextension = path.replace(/^.*[\\\/]/, ''), + filename = filenameextension.substring(0, filenameextension.lastIndexOf('.')), + ext = filenameextension.split('.').pop(); + + return { + 'name': filename, + 'ext': ext + }; + } + return { + 'name': '', + 'ext': '' + }; + } + + stack.split("\n").forEach((v, i) => { + const match = v.match(regex); + let val; + if(match !== null) { + if(v.startsWith('@')) { + val = { + "signature": "", + "class": match[2], + "function": "", + "url": match[6], + "line": match[7], + "column": match[8], + 'str': v, + 'file': getFilenameAndExtension(match[6]), + }; + } else { + val = { + "signature": match[1], + "class": match[2], + "function": match[4], + "url": match[6], + "line": match[7], + "column": match[8], + 'str': v, + 'file': getFilenameAndExtension(match[6]), + }; + } + } + if(search !== undefined && search !== null) { + if(v.indexOf(search) !== -1) + errors.push(val); + } else { + if(val !== undefined && val !== '' && val.signature !== 'getStack' && val.signature !== 'SUKRinit' && val.signature !== 'SUKR' && val.signature !== 'window.SUKR') + errors.push(val); + } + }); + if(search !== undefined && search !== null) + return (errors.length > 0) ? errors[0] : null; + else + return errors; + }; + + SUKRInstances.instance = new SUKRinit(); +}; + const until = (predicateFn) => { const poll = (done) => (predicateFn() ? done() : setTimeout(() => poll(done), 500)); return new Promise(poll); @@ -2137,25 +2435,53 @@ async function pause(v) { await new Promise(resolve => setTimeout(resolve, 1000)); } -function loop(lightboxImages, index) { - if(index === lightboxImages.length) return; - lightboxImages[index].onload = function() { - console.log("image " + index + " loaded."); - loop(lightboxImages, ++index); - }; +const loop = (arr, fn, busy, err, i = 0) => { + const body = (ok, er) => { + try { + const r = fn(arr[i], i, arr); + r && r.then ? r.then(ok).catch(er) : ok(r) + } catch(e) {er(e)} + } + const next = (ok, er) => () => loop(arr, fn, ok, er, ++i) + const run = (ok, er) => i < arr.length ? new Promise(body).then(next(ok, er)).catch(er) : ok() + return busy ? run(busy, err) : new Promise(run) } -(async precallback => { - const title = document.title; - if(title !== undefined) - document.title = "Loading..."; +/*** + * @return {SGNUKConfig} + */ +const SGNUKConfig = function(config) { + const plugin = this; + const _defaults = { + 'urls': { + 'api': { + 'geonames': 'https://secure.geonames.org/', + 'osm': 'https://nominatim.openstreetmap.org/' + }, + } + } + plugin.config = { + 'api': { + 'geonames': undefined //username + }, + 'geocoding': { + 'defaultAPI': 'osm' + } + } + + const init = () => { + plugin.config = Object.assign(plugin.config, config); + plugin.config = Object.assign(plugin.config, _defaults); + } - if(window.jQuery) - $.holdReady(true); + init(); - (() => { - const css = `/* + return plugin; +}; + +((callback) => { + const css = `/* * Copyright (c) 2022 SGNetworks. All rights reserved. * * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. @@ -2181,10 +2507,12 @@ function loop(lightboxImages, index) { body { \tmargin: 0; +\tdisplay: none; } .has-preloader { \toverflow: hidden !important; +\display: block; } .sgn-preloader { @@ -2219,8 +2547,8 @@ body { .sgn-preloader > .preloader > img { -\twidth: 100%; -\theight: 100%; +\twidth: calc(var(--sgn-preloader-circles-width) + ((var(--sgn-preloader-stripes-width) + var(--sgn-preloader-circles-margin)) * 2)); +\theight: calc(var(--sgn-preloader-circles-height) + (var(--sgn-preloader-stripes-width) + var(--sgn-preloader-circles-margin))); \tmargin: var(--sgn-preloader-circles-margin); \tdisplay: flex; \tjustify-content: center; @@ -2228,6 +2556,7 @@ body { \tposition: relative; \ttop: 50%; \tleft: 50%; +\tanimation: spin 4s ease-in-out forwards infinite; } .sgn-preloader > .preloader > .spinner > img { \twidth: calc(var(--sgn-preloader-circles-width)); @@ -2359,111 +2688,293 @@ body { \t} } +@keyframes pulse { +\tfrom { +\t\ttransform: scale(.8); +\t} +\tto { +\t\ttransform: scale(1); +\t} +} + +@keyframes spin { +\t0% { +\t\ttransform: rotateY(0deg); +\t} +\t50% { +\t\ttransform: rotateY(180deg); +\t} +\t100% { +\t\ttransform: rotateY(360deg); +\t} +} `; - const head = document.head || document.getElementsByTagName("head")[0], - style = document.createElement("style"); - - head.appendChild(style); - style.type = "text/css"; - style.id = "sgn-uikit-styles"; - if(style.styleSheet) { - // This is required for IE8 and below. - style.styleSheet.cssText = css; - } else { - style.appendChild(document.createTextNode(css)); + const head = document.head || document.getElementsByTagName("head")[0], + style = document.createElement("style"); + const currentScript = document.currentScript || document.querySelector("script[src*=\"SGNUIKit.loader.js\"]"); + + head.appendChild(style); + style.type = "text/css"; + style.id = "sgn-uikit-styles"; + if(style.styleSheet) { + // This is required for IE8 and below. + style.styleSheet.cssText = css; + } else { + style.appendChild(document.createTextNode(css)); + } + let preloaderElem = document.createElement("div"); + preloaderElem.className = "sgn-preloader"; + let preloader = `\t\t\t
\n`; + const icon = currentScript.getAttribute('sgn-ui-kit-loader-icon'); + if(icon !== undefined) + preloader += `\t\t\t\tICON\n`; + preloader += `\t\t\t\t
\n`; + preloader += `\t\t\t\t\t\n`; + preloader += `\t\t\t\t\t\n`; + preloader += `\t\t\t\t\t\n`; + preloader += `\t\t\t\t\t\n`; + preloader += `\t\t\t\t\t\n`; + preloader += `\t\t\t\t\t\n`; + preloader += `\t\t\t\t\t\n`; + preloader += `\t\t\t\t\t\n`; + preloader += `\t\t\t\t
\n`; + preloader += `\t\t\t
\n`; + preloader += `\t\t\n`; + + preloaderElem.innerHTML = preloader; + + window.onload = function() { + document.body.classList.add("has-preloader"); + document.body.insertBefore(preloaderElem, document.body.firstChild); + + if(typeof callback === 'function') + callback(); + }; +})(() => { + function getFilenameAndExtension(path) { + if(path !== undefined) { + const filenameextension = path.replace(/^.*[\\\/]/, ''), + filename = filenameextension.substring(0, filenameextension.lastIndexOf('.')), + ext = filenameextension.split('.').pop(); + + return { + 'name': filename, + 'ext': ext + }; } - //console.log(style); - })(); - (() => { - let preloaderElem = document.createElement("div"); - preloaderElem.className = "sgn-preloader"; - let preloader = `\t\t\t
\n`; - //preloader += `\t\t\t\t\n`; - preloader += `\t\t\t\t
\n`; - preloader += `\t\t\t\t\t\n`; - preloader += `\t\t\t\t\t\n`; - preloader += `\t\t\t\t\t\n`; - preloader += `\t\t\t\t\t\n`; - preloader += `\t\t\t\t\t\n`; - preloader += `\t\t\t\t\t\n`; - preloader += `\t\t\t\t\t\n`; - preloader += `\t\t\t\t\t\n`; - preloader += `\t\t\t\t
\n`; - preloader += `\t\t\t
\n`; - preloader += `\t\t\n`; - - preloaderElem.innerHTML = preloader; - - window.onload = function() { - document.body.className += " has-preloader"; - document.body.insertBefore(preloaderElem, document.body.firstChild); + return { + 'name': '', + 'ext': '' }; - })(); + } - const currentScript = document.currentScript || document.querySelector("script[src*=\"SGNUIKit.loader.js\"]"); - const url = currentScript.src.split("/").slice(0, -2).join("/") + "/"; - const preload = [ - "js/i18n/SGNi18n.js", - ]; - /*if(!window.jQuery || jQuery === undefined) - preload.push('addons/jQuery/jQuery.min.js');*/ - - let filesloaded = 0; - const filestoload = preload.length; - - for(let i = 0; i < filestoload; i++) { - const script = document.createElement("script"); - script.src = url + preload[i]; - script.async = false; - script.defer = false; - currentScript.after(script); - if(i === 0) - script.id = "sgn-preload-end"; - - /*await new Promise(resolve => { - script.onload = function() { - filesloaded++; - script.onload = null; - resolve(); - }; - }).then(r => finishLoad());*/ - script.onload = function() { - filesloaded++; - SGNUIKit.component = {i: preload[i]}; - script.onload = null; - finishLoad(); + if(typeof HTMLElement.prototype.attr !== "function") { + HTMLElement.prototype.attr = function(name, value) { + if(value === undefined) { + return this.getAttribute(name); + } else + this.setAttribute(name, value); }; } - async function finishLoad() { - let progress = Math.round((filesloaded * 100) / filestoload); + if(typeof HTMLElement.prototype.fadeIn !== "function") { + HTMLElement.prototype.fadeIn = function(speed, callback) { + let _this = this; + speed = (typeof speed !== "number") ? 2000 : speed; - await new Promise(resolve => { - if(filesloaded >= filestoload) { - resolve(); + if(!_this.style.opacity) { + _this.style.opacity = (speed > 0) ? 0 : 1; } - }).then(function() { - import("./helpers/helpers.js"); - $("head > title").text(title); - if(typeof precallback === "function" && progress === 100) - precallback(); - }); + + if(speed > 0) { + const inInterval = setInterval(function() { + _this.style.opacity = Number(_this.style.opacity) + 0.02; + if(_this.style.opacity >= 1) { + clearInterval(inInterval); + + if(typeof callback === "function") + callback(_this); + } + }, speed / 50); + } else { + if(typeof callback === "function") + callback(_this); + } + }; } -})(function() { - (callback => { - const sgnuikitScript = document.currentScript || document.querySelector("script[src*=\"SGNUIKit.loader.js\"]"); - const currentScript = document.getElementById("sgn-preload-end") || sgnuikitScript; - function getScriptURL() { - return sgnuikitScript.src; + if(typeof HTMLElement.prototype.fadeOut !== "function") { + HTMLElement.prototype.fadeOut = function(speed, callback) { + let _this = this; + speed = (typeof speed !== "number") ? 2000 : speed; + + if(!_this.style.opacity) { + _this.style.opacity = (speed > 0) ? 1 : 0; + } + + if(speed > 0) { + const outInterval = setInterval(function() { + _this.style.opacity -= 0.02; + if(_this.style.opacity <= 0) { + clearInterval(outInterval); + + if(typeof callback === "function") + callback(_this); + } + }, speed / 50); + } else { + if(typeof callback === "function") + callback(_this); + } + }; + } + + (async precallback => { + const title = document.title; + if(title !== undefined) + document.title = "Loading..."; + + if(window.jQuery) + $.holdReady(true); + + const currentScript = document.currentScript || document.querySelector("script[src*=\"SGNUIKit.loader.js\"]"); + const url = currentScript.src.split("/").slice(0, -2).join("/") + "/"; + const preload = [ + "js/i18n/SGNi18n.js", + ]; + /*if(!window.jQuery || jQuery === undefined) + preload.push('addons/jQuery/jQuery.min.js');*/ + + let filesloaded = 0; + const filestoload = preload.length; + + for(let i = 0; i < filestoload; i++) { + const component = preload[i], + src = url + component, + name = 'js_' + getFilenameAndExtension(component).name; + const obj = {}; + obj[name] = component; + + if(!SGNUIKit.isComponentLoaded(name)) { + const script = document.createElement("script"); + script.src = src; + script.async = false; + script.defer = false; + currentScript.after(script); + if(i === 0) + script.id = "sgn-preload-end"; + + /*await new Promise(resolve => { + script.onload = function() { + filesloaded++; + script.onload = null; + resolve(); + }; + }).then(r => finishLoad());*/ + script.onload = function() { + filesloaded++; + SGNUIKit.component = obj; + script.onload = null; + finishLoad(); + }; + } else { + filesloaded++; + await finishLoad(); + } } - const url = getScriptURL().split("/").slice(0, -2).join("/") + "/"; + let progress = 0; + + async function finishLoad() { + progress = Math.round((filesloaded * 100) / filestoload); - setTimeout(startLoad, 5000); + await new Promise(resolve => { + if(filesloaded >= filestoload) { + resolve(); + } + }).then(function() { + import("./helpers/helpers.js"); + $("head > title").text(title); + if(typeof precallback === "function" && progress === 100) + precallback(); + }); + } + + window.addEventListener('offline', (e) => { + const getI18nString = (k, m) => m; + //if(typeof getI18nString !== 'function') + const $body = $('body'); + let offlineErrorMsg = (SGNUIKit.ready) ? getI18nString('sgn_uikit_error_user_offline_msg', `Sorry! You are currently offline. You'll be able to access the application once your internet connection is restored.`) : getI18nString('sgn_uikit_user_offline_loading_interrupted_msg', `Sorry! Initial loading is interrupted. The application will continue to load once your internet connection is restored.`); + if(progress < 100) + offlineErrorMsg = getI18nString('sgn_uikit_user_offline_preload_failed_msg', `Hooray! Your internet connection is restored, but it has broken the application's preload process, please reload the page to fix it.`); + const offlineErrorHeading = getI18nString('txt_no_internet', `No Internet!`); + + let overlayElem = document.createElement("div"); + overlayElem.className = "overlay blackout"; + let preloader = `\t\t
\n`; + preloader += `\t\t\t

${offlineErrorHeading}

\n`; + preloader += `\t\t\t
${offlineErrorMsg}
\n`; + preloader += `\t\t
\n`; + + overlayElem.innerHTML = preloader; + $('.sgn-preloader').fadeOut(1000); + $body.removeClass('has-preloader').addClass('user-offline'); + document.body.insertBefore(overlayElem, document.body.firstChild); + + //overlayElem = document.querySelector(".sgn-preloader"); + overlayElem = $(".user-offline > .overlay"); + + if(overlayElem.length > 0) { + overlayElem.fadeIn(1000); + } + }); + window.addEventListener('online', (e) => { + const getI18nString = (k, m) => m; + //if(typeof getI18nString !== 'function') + let onlineMsg = (SGNUIKit.ready) ? getI18nString('sgn_uikit_user_online_msg', `Hooray! Your internet connection is restored, you'll now be able to access the application shortly.`) : getI18nString('sgn_uikit_user_online_loading_interrupted_msg', `Hooray! Your internet connection is restored, the application will resume to load shortly.`); + if(progress < 100) + onlineMsg = getI18nString('sgn_uikit_user_online_preload_failed_msg', `Hooray! Your internet connection is restored, but it has broken the application's preload process, please reload the page to fix it.`); + const onlineHeading = getI18nString('txt_internet_connection_restored', `Internet Connection Restored!`); + + //const overlayElem = document.querySelector(".overlay"); + const $overlayElem = $(".user-offline > .overlay"); + const $heading = $overlayElem.find('.title'), + $msg = $overlayElem.find('.msg'); + let MSG_TIMEOUT = 10000; + if(typeof $.SGNSnackbar === 'function') { + MSG_TIMEOUT = 50; + $.SGNSnackbar(onlineMsg).show(); + } else { + $heading.html(onlineHeading).removeClass('error').addClass('success'); + $msg.html(onlineMsg); + } + + if($overlayElem.length > 0) { + setTimeout(() => { + $('.sgn-preloader').fadeIn(1000); + $overlayElem.fadeOut(1000, () => { + $overlayElem.remove(); + document.body.classList.remove("user-offline"); + $('body').addClass('has-preloader'); + }); + }, MSG_TIMEOUT); + } + + if(typeof precallback === "function" && progress === 100) + precallback(); + }); + })(function() { + (async callback => { + const sgnuikitScript = document.currentScript || document.querySelector("script[src*=\"SGNUIKit.loader.js\"]"); + const currentScript = document.getElementById("sgn-preload-end") || sgnuikitScript; + + function getScriptURL() { + return sgnuikitScript.src; + } + + const url = getScriptURL().split("/").slice(0, -2).join("/") + "/"; - function startLoad() { const scripts = [ "css/fonts/FontAwesome5Pro/js/all.js", "css/fonts/FontAwesome5Pro/js/v4-shims.js", @@ -2479,6 +2990,7 @@ body { "addons/noty/noty.js", "addons/noty/noty.init.js", "addons/PrismJS/prism.js", + "addons/SGNLoaders/SGNLoaders.js", "addons/SGNAtom/SGNAtom.js", "addons/SGNFullPage/SGNFullPage.js", "addons/SGNGeoData/SGNGeoData.js", @@ -2497,114 +3009,232 @@ body { "js/addons/SGNSnackbar.js", "js/addons/SGNDataTables.js", "js/addons/SGNCodeSnippet.js", + + "js/components/dropdown.js", + "js/components/marquee.js", + "js/components/modals.js", + "js/components/sidebar.js", + "js/components/tablayout.js", + "js/components/windows.js", + "js/components/wizard.js", + "js/components/forms/select.js", + "js/components/forms/inputs.js", ]; const styles = [ "css/SGNUIKit-pro.css", ]; - let filesloaded = 0, - lastScript = currentScript; - const filestoload = scripts.length + styles.length; + let scriptsLoaded = 0, stylesLoaded = 0, loaded = 0, + lastScript = currentScript; + const totalScripts = scripts.length, totalStyles = styles.length, total = totalScripts + totalStyles; - function loadScript(i) { + const loadScript = i => new Promise((resolve, reject) => { if(i === scripts.length) return; - const script = document.createElement("script"); - //script.type = 'text/javascript'; - script.src = url + scripts[i]; - script.onload = function() { - filesloaded++; - SGNUIKit.component = {i: scripts[i]}; - script.onload = null; - //console.log(`LOADED SCRIPT: ${script.src}`, `${i}/${filestoload}`); - finishLoad(); - loadScript(++i); - }; - lastScript.after(script); - lastScript = lastScript.nextElementSibling || currentScript; - } + const component = scripts[i], + src = url + component, + name = 'js_' + getFilenameAndExtension(component).name; + const obj = {}; + obj[name] = component; + + if(!SGNUIKit.isComponentLoaded(name)) { + const script = document.createElement("script"); + //script.type = 'text/javascript'; + script.src = src; + lastScript.after(script); + lastScript = lastScript.nextElementSibling || currentScript; + + script.onload = async function() { + SGNUIKit.component = obj; + script.onload = null; + scriptsLoaded++; + loaded++; + + if(scriptsLoaded === totalScripts) + resolve(i); + else + resolve(loadScript(++i)); + }; + } else { + scriptsLoaded++; + loaded++; + + if(scriptsLoaded === totalScripts) + resolve(i); + else + resolve(loadScript(++i)); + } + }); - function loadStyle(i) { - if(i === scripts.length) return; + const loadStyle = i => new Promise((resolve, reject) => { + if(i === styles.length) return; + + const component = styles[i], + src = url + component, + name = 'css_' + getFilenameAndExtension(component).name; + const obj = {}; + obj[name] = component; + + if(!SGNUIKit.isComponentLoaded(name)) { + const style = document.createElement("link"); + style.rel = "stylesheet"; + style.href = src; + //style.type = 'text/css'; + currentScript.after(style); + style.onload = async function() { + SGNUIKit.component = obj; + style.onload = null; + stylesLoaded++; + loaded++; + + if(stylesLoaded === totalStyles) + resolve(i); + else + resolve(loadStyle(++i)); + }; + } else { + stylesLoaded++; + loaded++; + + if(stylesLoaded === totalStyles) + resolve(i); + else + resolve(loadStyle(++i)); + } + }); - const style = document.createElement("link"); - style.rel = "stylesheet"; - style.href = url + styles[i]; - //style.type = 'text/css'; - style.onload = function() { - filesloaded++; - style.onload = null; + (() => { + const startLoad = new Promise(async function(resolve) { + await loadStyle(0); + await loadScript(0); + if(loaded === total) + resolve(); + }); + + startLoad.then(() => { finishLoad(); - loop(++i); - }; - currentScript.after(style); - } + }); + })(); - loadScript(0); - loadStyle(0); - function finishLoad() { - const progress = Math.round((filesloaded * 100) / filestoload); + /*function finishLoad() { + const progress = Math.round((loaded * 100) / total); - if(typeof callback === "function") { - callback(filesloaded, filestoload, progress); - } + if(typeof callback === "function") { + callback(loaded, total, progress); + } + }*/ + + async function finishLoad() { + const progress = Math.round((loaded * 100) / total); + + await new Promise(resolve => { + if(loaded === total) { + resolve(); + } + }).then(function() { + if(typeof callback === "function") + callback(loaded, total, progress); + }); } - } - })((loaded, total, progress) => { - if(progress === 100) { - import("./i18n/SGNi18n.js"); - import("./components/components.js"); - SGNUIKit.ready = true; - window.SGNUIKitReady = true; - - const left = document.querySelector("style[data-cke=\"true\"]"); - if(left !== null) - left.parentNode.removeChild(left); - - - /*setTimeout(function() { - $.holdReady(false); - jQuery.ready(); - }, 5000);*/ - } + })((loaded, total, progress) => { + if(progress === 100) { + SGNUIKit.init = true; + const styles = document.querySelector("style#sgn-uikit-styles"); + const left = document.querySelector("style[data-cke=\"true\"]"); + if(left !== null) + left.parentNode.removeChild(left); + if(styles !== null) + styles.parentNode.removeChild(styles); - SGNUIKit.setOnChangeListener((prop, value) => { - const $body = $("body"); + $.holdReady(false); + jQuery.ready(); + } + }); + }); - if(prop === 'holdPreloader') { - if(!value) { - $.holdReady(false); - jQuery.ready(); + (() => { + const finalize = (holdPreloader = false) => { + const $body = $("body"); - $body.children(".sgn-preloader").fadeOut(2000, function() { - $body.children(".sgn-preloader").remove(); - $body.removeClass("has-preloader"); + /*** + * + * @type {Object} + */ + const sgnatoms = SGNAtom.getInstance(); + + sgnatoms.setOnCreateListener((sgnatoms) => { + if(sgnatoms.length > 0) { + for(const guid in sgnatoms) { + const sgnatom = sgnatoms[guid]; + + if(sgnatom instanceof SGNAtom) { + sgnatom.SGNAtomStates.setOnReadyListener((isReady) => { + if(isReady) { + const navigator = sgnatom.core.navigator; + navigator.setOnPageLoadListener((url, code) => { + if(code === 200 || code === 201 || code === 202) { + SGNUIKit.ready = true; + SUKRInstances.setOnCreateListener((instances) => { + forEach(instances, inst => inst.trigger()); + }); + + if(!holdPreloader) { + $body.children(".sgn-preloader").fadeOut(2000, function() { + $body.children(".sgn-preloader").remove(); + $body.removeClass("has-preloader"); + }); + } + } + }); + } + }); + } + } + } else { + + /*SUKRInstances.setOnCreateListener((instances) => { + //console.log(instances); + forEach(instances, inst => { + inst.trigger(); + }); + });*/ + + SUKRInstances.setOnChangeListener((instance, instances) => { + //console.log(instances); + forEach(instances, inst => { + inst.trigger(); + }); }); + window.SGNUIKitReady = true; + SGNUIKit.ready = true; + if(SGNUIKit.ready) { + if(!holdPreloader) { + $body.children(".sgn-preloader").fadeOut(2000, function() { + $body.children(".sgn-preloader").remove(); + $body.removeClass("has-preloader"); + }); + } + } + } + }); + } + + SGNUIKit.setOnChangeListener((prop, value) => { + if(prop === 'holdPreloader') { + if(SGNUIKit.init && !value) { + finalize(true); } } else { - if(prop === 'ready' && !SGNUIKit.holdPreloader) { - //console.log(prop, value); - $.holdReady(false); - jQuery.ready(); - - $body.children(".sgn-preloader").fadeOut(2000, function() { - $body.children(".sgn-preloader").remove(); - $body.removeClass("has-preloader"); - }); + if(prop === 'init' && value) { + finalize(false); } } - }); - }); + }, 'sgn-uk-prop-change-listener'); + })(); }); -/*(async() => { - console.log("waiting for variable"); - while(progress < 100) // define the condition as you like - await new Promise(resolve => setTimeout(resolve, 1000)); - console.log("variable is defined"); - })();*/ async function getSGNI18nInstance(callback) { return new Promise((resolve, reject) => { const timeoutHandler = setTimeout(function() { diff --git a/src/js/addons/SGNCodeSnippet.js b/src/js/addons/SGNCodeSnippet.js index 2efdf6d6..ca5a89a5 100644 --- a/src/js/addons/SGNCodeSnippet.js +++ b/src/js/addons/SGNCodeSnippet.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 SGNetworks. All rights reserved. + * Copyright (c) 2022-2023 SGNetworks. All rights reserved. * * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. @@ -37,36 +37,106 @@ if(typeof jQuery === "undefined") { "xml": "XML", }; + + const fixIndents = (input, tabs = 1) => { + const tab = '\t'; + const indents = input.match(/^[^\S\n\r]*(?=\S)/gm); + const t = tab.repeat(tabs); + + if(indents[0] === '') + indents.splice(0, 1); + + if(!indents || !indents[0]) { + return input; + } + + indents.sort(function(a, b) { return a.length - b.length; }); + + if(!indents[0].length) { + return input; + } + + let s = input.replace(RegExp('^' + indents[0], 'gm'), ''); + return s.replace(RegExp(`^${tab}`, 'gm'), t); + }; + function init() { - const title = $elem.attr("sgn-snippet-title") || $elem.attr("data-snippet-title") || "Code Snippet", - langAttr = $elem.attr("sgn-snippet-lang") || $elem.attr("data-snippet-lang") || "html", - lang = langAttr.toLowerCase(); - const langTitle = langTitles[lang] || "HTML"; + let $snippet = $elem, + isMultipleSnippets = ($elem.hasClass('sgn-code-snippets')); + + if(isMultipleSnippets) { + $snippet = $elem.children('.sgn-code-snippet'); + } + + const title = $elem.attr("sgn-snippet-title") || $elem.attr("data-snippet-title") || "Code Snippet"; + + let snippetCodeTab = '', snippetCodeTabLink = '', $previewHTML = ''; + + if(isMultipleSnippets) { + $previewHTML = $snippet.first().outerHTML; - $elem.removeClass("sgn-code-snippet"); - $elem.removeAttr("sgn-snippet-title").removeAttr("data-snippet-lang").removeAttr("sgn-snippet-lang").removeAttr("data-snippet-lang"); + $snippet.each(function(i) { + const $this = $(this), + t = (i + 1); - const $html = $elem.get(0).outerHTML, - code = $html.toHtmlEntities(); + const langAttr = $this.attr("sgn-snippet-lang") || $this.attr("data-snippet-lang") || "html", + previewTab = ($this.attr("sgn-snippet-preview-tab") || $this.attr("data-snippet-preview-tab")) || false, + lang = langAttr.toLowerCase(); + const langTitle = langTitles[lang] || "HTML"; + + $this.removeClass("sgn-code-snippet"); + $this.removeAttr("sgn-snippet-title").removeAttr("data-snippet-lang").removeAttr("sgn-snippet-lang").removeAttr("data-snippet-lang").removeAttr("sgn-snippet-preview-tab").removeAttr("data-snippet-preview-tab"); + + const $html = (previewTab) ? $this.get(0).outerHTML : $this.get(0).innerHTML, + code = fixIndents($html.toHtmlEntities()); + + $previewHTML = (previewTab) ? $this.get(0).outerHTML : $previewHTML; + + snippetCodeTab += `
\n`; + snippetCodeTab += `
${code}
`; + snippetCodeTab += `
\n`; + + snippetCodeTabLink += ` ${langTitle}\n`; + }); + } else { + const langAttr = $snippet.attr("sgn-snippet-lang") || $snippet.attr("data-snippet-lang") || "html", + lang = langAttr.toLowerCase(); + const langTitle = langTitles[lang] || "HTML"; + + $snippet.removeClass("sgn-code-snippet"); + $snippet.removeAttr("sgn-snippet-title").removeAttr("data-snippet-lang").removeAttr("sgn-snippet-lang").removeAttr("data-snippet-lang"); + + const $html = $snippet.get(0).outerHTML, + code = fixIndents($html.toHtmlEntities()); + + $previewHTML = $html; + + snippetCodeTab += `
\n`; + snippetCodeTab += `
${code}
`; + snippetCodeTab += `
\n`; + + snippetCodeTabLink += ` ${langTitle}\n`; + } let html; html = `
\n`; html += (!empty(title)) ? `
${title}
` : ``; html += `
\n`; - html += `
\n`; - html += ` ${$html}`; - html += `
\n`; - html += `
\n`; - html += `
${code}
`; + html += `
\n`; + html += ` ${$previewHTML}`; html += `
\n`; + html += snippetCodeTab; html += `
\n`; html += ` \n`; html += `
\n`; - $elem.replaceWith(html); + if(isMultipleSnippets) + $elem.replaceWith(html); + else + $snippet.replaceWith(html); Prism.highlightAll(); } @@ -111,10 +181,21 @@ if(typeof jQuery === "undefined") { $_this.each(function() { const $this = $(this), data = $this.data("SGNCodeSnippet"); - const plugin = (data === undefined) ? new SGNCodeSnippet($this) : data; - $this.data("SGNCodeSnippet", plugin); + let isMultipleSnippets = $_this.parent().hasClass('sgn-code-snippets'); - $this[0]["SGNCodeSnippet"] = plugin; + if(!isMultipleSnippets) { + const plugin = (data === undefined) ? new SGNCodeSnippet($this) : data; + $this.data("SGNCodeSnippet", plugin); + + $this[0]["SGNCodeSnippet"] = plugin; + } else { + if($_this.hasClass('sgn-code-snippets')) { + const plugin = (data === undefined) ? new SGNCodeSnippet($this) : data; + $this.data("SGNCodeSnippet", plugin); + + $this[0]["SGNCodeSnippet"] = plugin; + } + } }); /** @@ -140,8 +221,8 @@ if(typeof jQuery === "undefined") { return _this; }; - $(function() { - const $snippets = $(".sgn-code-snippet"); + SUKR(() => { + const $snippets = $(".sgn-code-snippets, .sgn-code-snippet"); $snippets.SGNCodeSnippet(); }); diff --git a/src/js/addons/SGNDataTables.js b/src/js/addons/SGNDataTables.js index 8a747881..785fa367 100644 --- a/src/js/addons/SGNDataTables.js +++ b/src/js/addons/SGNDataTables.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 SGNetworks. All rights reserved. + * Copyright (c) 2022-2023 SGNetworks. All rights reserved. * * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. @@ -383,7 +383,7 @@ if(typeof jQuery === "undefined") { }); }; - $(function() { + SUKR(() => { const $datatables = $('.datatable'); $datatables.SGNDataTable({ diff --git a/src/js/components/dropdown.js b/src/js/components/dropdown.js index a639dafa..102c718e 100644 --- a/src/js/components/dropdown.js +++ b/src/js/components/dropdown.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 SGNetworks. All rights reserved. + * Copyright (c) 2022-2023 SGNetworks. All rights reserved. * * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. @@ -32,8 +32,8 @@ if(typeof jQuery === "undefined") { }); }; - $(document).ready(function() { + SUKR(() => { const $dropdowns = $('[data-toggle="dropdown"]'); $dropdowns.SGNDropdown(); }); -})(window, document, jQuery); \ No newline at end of file +})(window, document, jQuery); diff --git a/src/js/components/forms/inputs.js b/src/js/components/forms/inputs.js index 8ae04665..fe9735ab 100644 --- a/src/js/components/forms/inputs.js +++ b/src/js/components/forms/inputs.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 SGNetworks. All rights reserved. + * Copyright (c) 2022-2023 SGNetworks. All rights reserved. * * The software is an exclusive copyright of "SGNetworks" and is provided as is exclusively with only "USAGE" access. "Modification", "Alteration", "Re-distribution" is completely prohibited. * VIOLATING THE ABOVE TERMS IS A PUNISHABLE OFFENSE WHICH MAY LEAD TO LEGAL CONSEQUENCES. @@ -10,41 +10,36 @@ const SGNInput = function(element) { const plugin = this; - const _this = element, - $_this = $(_this); + const _this = element, $_this = $(_this); /** * * @param {string} find - * @param {jQuery} $elem + * @param {jQuery} [$elem] + * @param {jQuery}[$fallback] + * * @return {undefined|jQuery} */ - const sibling = (find, $elem) => { + const sibling = (find, $elem, $fallback) => { $elem = ($elem === undefined || $elem === null || $elem === '') ? $_this : $elem; - const $next = $elem.next(find), - $prev = $elem.prev(find); + const $next = $elem.next(find), $prev = $elem.prev(find); if(find === 'label') { const nodeName = ($elem.prop('nodeName')) ? $elem.prop('nodeName') : $elem[0].nodeName; - const $input = (nodeName === 'input') ? $elem : $_this, - inputID = ($input.attr('id')) ? $input.attr('id') : '', - $label = ($elem.parent().find(`label[for="${inputID}"]`)) ? $elem.parent().find(`label[for="${inputID}"]`) : ''; + const $input = (nodeName === 'input') ? $elem : $_this, inputID = ($input.attr('id')) ? $input.attr('id') : '', $label = ($elem.parent().find(`label[for="${inputID}"]`)) ? $elem.parent().find(`label[for="${inputID}"]`) : ''; if($label.length > 0) { return $label; } else { - if($next.length > 0) - return $next; - else if($prev.length > 0) - return $prev; + if($next.length > 0) return $next; else if($prev.length > 0) return $prev; } } else { - if($next.length > 0) - return $next; - else if($prev.length > 0) - return $prev; + if($next.length > 0) return $next; else if($prev.length > 0) return $prev; } + if($fallback !== undefined && $fallback.length > 0) + return $fallback; + return undefined; } const getTextWidth = (text, styles) => { @@ -91,8 +86,7 @@ const nodeName = ($_this.prop('nodeName')) ? $_this.prop('nodeName') : $_this[0].nodeName; const type = (nodeName === 'INPUT') ? $_this.attr('type').toLowerCase() : nodeName.toLowerCase(); - if($_this.hasClass('sgn-select-input')) - return ''; + if($_this.hasClass('sgn-select-input')) return ''; return (nodeName === 'INPUT') ? `sgn-input-${type}` : `sgn-${type}`; } @@ -101,8 +95,7 @@ let result, i, j; result = ''; for(j = 0; j < 32; j++) { - if(hyphen && (j === 8 || j === 12 || j === 16 || j === 20)) - result = result + '-'; + if(hyphen && (j === 8 || j === 12 || j === 16 || j === 20)) result = result + '-'; i = Math.floor(Math.random() * 16).toString(16); i = (uppercase) ? i.toUpperCase() : i.toLowerCase(); result = result + i; @@ -120,23 +113,63 @@ } } + function isValidURL(string) { + let url; + try { + url = new URL(string); + } catch(_) { + return false; + } + return url.protocol === "http:" || url.protocol === "https:"; + } + + const getObject = (obj, key) => { + const keys = key.split('.'); + //const found = []; + if(obj.length > 0) { + /*keys.forEach(k => { + if(obj.hasOwnProperty(k)) { + found.push(k); + } + }); + + const r = obj[found];*/ + while(keys.length && (obj = obj[keys.shift()])) { + if(keys.length && obj.length && obj.forEach) { // handle arrays + const remainder = keys.join('.'); + let results = []; + for(let i = 0; i < obj.length; i++) { + const x = getObject(obj[i], remainder); + if(x) results = results.concat(x); + } + return results; + } + } + return (obj) ? [obj] : undefined; //single result, wrap in array for consistency + } + }; + const init = () => { //region Variables const nodeName = ($_this.prop('nodeName')) ? $_this.prop('nodeName') : $_this[0].nodeName; const typeClass = getTypeClass(); + const inputClasses = $_this.attr('class').str_replace(['form-control', 'sgn-select-input', 'searchable'], '').trim(); let type = (nodeName === 'INPUT') ? $_this.attr('type').toLowerCase() : nodeName.toLowerCase(); let id = ($_this.attr('id') === undefined || $_this.attr('id') === null || $_this.attr('id') === '') ? $_this.attr('name') : $_this.attr('id'); id = (id === undefined || id === null || id === "") ? `sgn-${type}-` + GUID() : id; let $container = $_this.parents('.sgn-form'), - $formWrapper = $_this.parents('.sgn-form-wrapper'), - $inputWrapper = $_this.parents('.sgn-input-wrapper'); - - let $input = $_this, - $label = sibling('label'), - $prefix = sibling('.sgn-input-prefix'), - $suffix = sibling('.sgn-input-suffix'), - $helpBlock = sibling('.sgn-form-help-block'); + $formWrapper = $_this.parents('.sgn-form-wrapper'), + $inputWrapper = $_this.parents('.sgn-input-wrapper'); + + let $input = $_this, + $label = sibling('label'), + $prefix = sibling('.sgn-input-prefix'), + $suffix = sibling('.sgn-input-suffix'), + $ovPrefix = sibling('.sgn-input-overlay-prefix', null, $formWrapper.children('.sgn-input-overlay-prefix')), + $ovSuffix = sibling('.sgn-input-overlay-suffix', null, $formWrapper.children('.sgn-input-overlay-suffix')), + $autocompleteBox = sibling('.sgn-input-autocomplete-box', null, $container.children('.sgn-input-autocomplete-box')), + $helpBlock = sibling('.sgn-form-help-block', null, $container.children('.sgn-form-help-block')); //endregion if(type === 'switch' || type === 'toggle') { @@ -148,8 +181,7 @@ let $inputGroupLabel, $inputGroupHelp; - if($_this.attr('id') === undefined || $_this.attr('id') === null || $_this.attr('id') === '') - $_this.attr('id', id); + if($_this.attr('id') === undefined || $_this.attr('id') === null || $_this.attr('id') === '') $_this.attr('id', id); if($label !== undefined) { const forv = $label.attr('for'); @@ -157,10 +189,7 @@ $label.attr('for', id); } if($inputWrapper.length <= 0) { - if($input.prev('label').length > 0) - $input.prev('label').addBack().wrapAll(`
`); - else if($input.next('label').length > 0) - $input.next('label').addBack().wrapAll(`
`); + if($input.prev('label').length > 0) $input.prev('label').addBack().wrapAll(`
`); else if($input.next('label').length > 0) $input.next('label').addBack().wrapAll(`
`); $inputWrapper = $input.parents('.sgn-input-wrapper'); } else { if($label.parents('.sgn-input-wrapper').length > 0 && $input.parents('.sgn-input-wrapper').length <= 0) { @@ -187,75 +216,120 @@ $formWrapper = $inputWrapper.parents('.sgn-form-wrapper'); } - if($prefix !== undefined) { + if($prefix !== undefined && $prefix.length > 0 && !$prefix.hasClass('inline')) { $prefix.detach().prependTo($formWrapper); + if(!$formWrapper.hasClass('has-input-addon-prefix')) $formWrapper.addClass('has-input-addon-prefix'); } else { const prefix = $input.attr('sgn-input-prefix'); if(prefix !== undefined) { $prefix = $(`
${prefix}
`); $inputWrapper.before($prefix); $prefix = $inputWrapper.prev('sgn-input-prefix'); + if(!$formWrapper.hasClass('has-input-addon-prefix')) $formWrapper.addClass('has-input-addon-prefix'); } } - if($suffix !== undefined) { + if($suffix !== undefined && $suffix.length > 0 && !$suffix.hasClass('inline')) { $suffix.detach().appendTo($formWrapper); + if(!$formWrapper.hasClass('has-input-addon-suffix')) $formWrapper.addClass('has-input-addon-suffix'); } else { const suffix = $input.attr('sgn-input-suffix'); if(suffix !== undefined) { $suffix = $(`
${suffix}
`); $inputWrapper.after($suffix); $suffix = $inputWrapper.next('sgn-input-suffix'); + if(!$formWrapper.hasClass('has-input-addon-suffix')) $formWrapper.addClass('has-input-addon-suffix'); + } + } + + if($ovPrefix !== undefined && $ovPrefix.length > 0 && !$ovPrefix.hasClass('inline')) { + $ovPrefix.detach().prependTo($inputWrapper); + if(!$inputWrapper.hasClass('has-input-overlay-prefix')) $inputWrapper.addClass('has-input-overlay-prefix'); + } else { + const ovPrefix = $input.attr('sgn-input-overlay prefix'); + if(ovPrefix !== undefined) { + $ovPrefix = $(`
${ovPrefix}
`); + $inputWrapper.prepend($ovPrefix); + $ovPrefix = $inputWrapper.children('.sgn-input-overlay-prefix'); + if(!$inputWrapper.hasClass('has-input-overlay-prefix')) $inputWrapper.addClass('has-input-overlay-prefix'); + } + } + if($ovSuffix !== undefined && $ovSuffix.length > 0 && !$ovSuffix.hasClass('inline')) { + $ovSuffix.detach().appendTo($inputWrapper); + if(!$inputWrapper.hasClass('has-input-overlay-suffix')) $inputWrapper.addClass('has-input-overlay-suffix'); + } else { + const ovSuffix = $input.attr('sgn-input-overlay suffix'); + if(ovSuffix !== undefined) { + $ovSuffix = $(`
${ovSuffix}
`); + $inputWrapper.append($ovSuffix); + $ovSuffix = $inputWrapper.children('.sgn-input-overlay-suffix'); + if(!$inputWrapper.hasClass('has-input-overlay-suffix')) $inputWrapper.addClass('has-input-overlay-suffix'); } } + $_this.removeClass(inputClasses); + $inputWrapper.addClass(inputClasses); + if($container.length <= 0) { $formWrapper.wrap(`
`); $container = $formWrapper.parents('.sgn-form'); } - if($helpBlock !== undefined) { - $helpBlock.detach().appendTo($formWrapper); + if($helpBlock !== undefined && $helpBlock.length > 0) { + $helpBlock.detach().appendTo($container); } else { const helpBlock = $input.attr('sgn-input-help'); if(helpBlock !== undefined) { $helpBlock = $(`
${helpBlock}
`); $container.append($helpBlock); - $helpBlock = $container.children('.sgn-form-help-block'); } } + $helpBlock = $container.children('.sgn-form-help-block'); if($helpBlock !== undefined && $helpBlock.length > 0) { - const containerWidth = ($helpBlock.width()), - textWidth = (getTextWidth($helpBlock.text())), - boxWidth = (textWidth + containerWidth); + const containerWidth = ($helpBlock.width()), textWidth = (getTextWidth($helpBlock.text())), boxWidth = (textWidth + containerWidth); if(textWidth > containerWidth) { - const speed = parseFloat($_this.attr('sgn-input-help-scroll-speed')) || 10, - timePerPixel = 0.2; + const speed = parseFloat($_this.attr('sgn-input-help-scroll-speed')) || 10, timePerPixel = 0.2; let distance, duration; /* - Time = (Distance / Speed) - Speed = (Distance / Time) - Duration = (Speed * Distance) + Time = (Distance / Speed) + Speed = (Distance / Time) + Duration = (Speed * Distance) */ distance = uint((textWidth) / (containerWidth)); duration = uint(speed * distance); duration = Math.round(duration); - $helpBlock.marquee(); + $helpBlock.marquee(duration, 'left', true); $helpBlock.addClass('has-marquee'); - setTimeout(() => { - $helpBlock.children('.sgn-marquee-wrapper').children('.sgn-marquee').attr('style', `animation: marquee-left ${duration}s linear infinite`); - }, 10); + //setTimeout(() => $helpBlock.children('.sgn-marquee-wrapper').children('.sgn-marquee').attr('style', `animation: marquee-left ${duration}s linear infinite`), 10); } } + if($_this.prop('readonly') && !$container.hasClass('readonly')) + $container.addClass('readonly'); + if($_this.prop('disabled') && !$container.hasClass('disabled')) + $container.addClass('disabled'); + + $container.addClass(typeClass); + $label = $container.find('label'); + + if($autocompleteBox !== undefined && $autocompleteBox.length > 0) { + $autocompleteBox.detach().prependTo($container); + } else { + const autocomplete = $input.attr('searchable') || $input.attr('sgn-input-searchable') || $input.hasClass('searchable'); + if(autocomplete !== undefined) { + $autocompleteBox = $(`
`); + $container.append($autocompleteBox); + } + } + $autocompleteBox = $container.children('.sgn-input-autocomplete-box'); + if($inputGroup.length > 0) { $inputGroupLabel = $inputGroup.children('label.sgn-input-group-label'); $inputGroupHelp = $inputGroup.children('.sgn-input-group-help'); - const inputGroupLabel = $inputGroup.attr('sgn-input-group-label'), - inputGroupHelp = $inputGroup.attr('sgn-input-group-help'); + const inputGroupLabel = $inputGroup.attr('sgn-input-group-label'), inputGroupHelp = $inputGroup.attr('sgn-input-group-help'); if(inputGroupLabel !== undefined && inputGroupLabel !== null && inputGroupLabel !== '') { const inputGroupLabelHTML = ``; @@ -277,32 +351,24 @@ if($inputGroup.hasClass('labels-left')) { $label.detach().prependTo($inputWrapper); - if(!$inputWrapper.hasClass('label-left')) - $inputWrapper.addClass('label-left') + if(!$inputWrapper.hasClass('label-left')) $inputWrapper.addClass('label-left') } else { $label.detach().appendTo($inputWrapper); - if(!$inputWrapper.hasClass('label-right')) - $inputWrapper.addClass('label-right') + if(!$inputWrapper.hasClass('label-right')) $inputWrapper.addClass('label-right') } $label = $inputWrapper.children('label'); } - $container.addClass(typeClass); - $label = $container.find('label'); - const minlength = $_this.attr('minlength'); let required = ($_this.attr('required') || (minlength && minlength > 0)); if(!$_this.hasClass('sgn-select-input')) { - const requiredHTML = `*`, - optionalHTML = `*`; + const requiredHTML = `*`, optionalHTML = `*`; if(required) { - if($_this.attr('required') === undefined) - $_this.attr('required', true); + if($_this.attr('required') === undefined) $_this.attr('required', true); if(!$container.hasClass('sgn-input-radio') && !$container.hasClass('sgn-input-checkbox') && !$container.hasClass('sgn-input-switch')) { - if($label !== undefined) - $label.html(`${requiredHTML} ${$label.html()}`); + if($label !== undefined) $label.html(`${requiredHTML} ${$label.html()}`); } else { if($inputGroupLabel.length > 0 && $inputGroupLabel.find('.sgn-required').length < 1) { $inputGroupLabel.html(`${requiredHTML} ${$inputGroupLabel.html()}`); @@ -311,8 +377,7 @@ } else { if($_this.hasClass('denote') || $_this.parents().hasClass('denote')) { if(!$container.hasClass('sgn-input-radio') && !$container.hasClass('sgn-input-checkbox') && !$container.hasClass('sgn-input-switch')) { - if($label !== undefined) - $label.html(`${optionalHTML} ${$label.html()}`); + if($label !== undefined) $label.html(`${optionalHTML} ${$label.html()}`); } else { if($inputGroupLabel.length > 0 && $inputGroupLabel.find('.sgn-optional').length < 1) { $inputGroupLabel.html(`${optionalHTML} ${$inputGroupLabel.html()}`); @@ -320,68 +385,29 @@ } } } + } else { + $_this.removeClass('.form-control'); } if($_this.hasClass('ckeditor')) { let editorButtons = $_this.attr('ck-toolbar'); - editorButtons = (editorButtons !== undefined) ? editorButtons : [ - 'heading', - '|', - 'bold', - 'italic', - 'underline', - 'fontSize', - '|', - 'fontFamily', - 'fontColor', - 'fontBackgroundColor', - 'highlight', - '|', - 'subscript', - 'superscript', - 'strikethrough', - '|', - 'todoList', - 'bulletedList', - 'numberedList', - '|', - 'outdent', - 'alignment', - 'indent', - '|', - 'specialCharacters', - 'blockQuote', - 'link', - /*'insertTable', - 'imageUpload', - 'imageInsert', - 'mediaEmbed', - '|',*/ - 'findAndReplace', - '|', - 'horizontalLine', - 'htmlEmbed', - 'sourceEditing', - 'removeFormat', - '|', - 'undo', - 'redo', - '|', - 'restrictedEditingException' - ]; + editorButtons = (editorButtons !== undefined) ? editorButtons : ['heading', '|', 'bold', 'italic', 'underline', 'fontSize', '|', 'fontFamily', 'fontColor', 'fontBackgroundColor', 'highlight', '|', 'subscript', 'superscript', 'strikethrough', '|', 'todoList', 'bulletedList', 'numberedList', '|', 'outdent', 'alignment', 'indent', '|', 'specialCharacters', 'blockQuote', 'link', /*'insertTable', + 'imageUpload', + 'imageInsert', + 'mediaEmbed', + '|',*/ + 'findAndReplace', '|', 'horizontalLine', 'htmlEmbed', 'sourceEditing', 'removeFormat', '|', 'undo', 'redo', '|', 'restrictedEditingException']; let ckEditor; if(CKSource !== undefined) { const watchdog = new CKSource.EditorWatchdog(); window.watchdog = watchdog; watchdog.setCreator((element, config) => { - return CKSource.Editor - .create(element, config) - .then(editor => { - ckEditor = editor; - return editor; - }); + return CKSource.Editor.create(element, config).then(editor => { + ckEditor = editor; + return editor; + }); }); watchdog.setDestructor(editor => { @@ -389,33 +415,22 @@ }); watchdog.on('error', handleError); - watchdog - .create($_this[0], { - toolbar: { - items: editorButtons - }, - language: 'en', - /*image: { - toolbar: [ - 'imageTextAlternative', - 'imageStyle:inline', - 'imageStyle:block', - 'imageStyle:side', - 'linkImage' - ] - },*/ - table: { - contentToolbar: [ - 'tableColumn', - 'tableRow', - 'mergeTableCells', - 'tableCellProperties', - 'tableProperties' - ] - }, - licenseKey: '', - }) - .catch(handleError); + watchdog.create($_this[0], { + toolbar: { + items: editorButtons + }, language: 'en', /*image: { + toolbar: [ + 'imageTextAlternative', + 'imageStyle:inline', + 'imageStyle:block', + 'imageStyle:side', + 'linkImage' + ] + },*/ + table: { + contentToolbar: ['tableColumn', 'tableRow', 'mergeTableCells', 'tableCellProperties', 'tableProperties'] + }, licenseKey: '', + }).catch(handleError); function handleError(error) { console.error('Oops, something went wrong!'); @@ -430,10 +445,8 @@ $_this.SGNSelect(); } else if(type === 'toggle') { $inputWrapper.addClass('toggle'); - const offTXTAttr = $_this.attr('data-off'), - onTXTAttr = $_this.attr('data-on'); - const offTXT = offTXTAttr || 'Off', - onTXT = onTXTAttr || 'On'; + const offTXTAttr = $_this.attr('data-off'), onTXTAttr = $_this.attr('data-on'); + const offTXT = offTXTAttr || 'Off', onTXT = onTXTAttr || 'On'; let $toggleWrapper = sibling('.toggle-switch-bar', $_this); let $toggleLabelWrapper, $toggleTXTOff, $toggleTXTOn, $toggleHandle; @@ -448,8 +461,7 @@ let sliderWrapperHTML = `
`; let sliderTXTWrapperHTML = `
`; - let sliderTXTOffHTML = `${offTXT}`, - sliderTXTOnHTML = `${onTXT}`; + let sliderTXTOffHTML = `${offTXT}`, sliderTXTOnHTML = `${onTXT}`; let sliderSwitchHTML = `
`; if(offTXTAttr || onTXTAttr) { @@ -463,15 +475,15 @@ $toggleHandle = $toggleWrapper.children('.slider-switch'); } else { /*$_this.after(sliderWrapperHTML); - $toggleWrapper = $_this.next('.slider-wrapper'); - - $toggleWrapper.html(sliderTXTWrapperHTML); - $toggleLabelWrapper = $toggleWrapper.children('.slider-text'); - $toggleLabelWrapper.html(sliderTXTOffHTML + sliderTXTOnHTML); - $toggleTXTOff = $toggleLabelWrapper.children('.sgn-toggle-label-off'); - $toggleTXTOn = $toggleLabelWrapper.children('.sgn-toggle-label-on'); - $toggleWrapper.append(sliderSwitchHTML); - $toggleHandle = $toggleWrapper.children('.slider-switch');*/ + $toggleWrapper = $_this.next('.slider-wrapper'); + + $toggleWrapper.html(sliderTXTWrapperHTML); + $toggleLabelWrapper = $toggleWrapper.children('.slider-text'); + $toggleLabelWrapper.html(sliderTXTOffHTML + sliderTXTOnHTML); + $toggleTXTOff = $toggleLabelWrapper.children('.sgn-toggle-label-off'); + $toggleTXTOn = $toggleLabelWrapper.children('.sgn-toggle-label-on'); + $toggleWrapper.append(sliderSwitchHTML); + $toggleHandle = $toggleWrapper.children('.slider-switch');*/ let html = `