AStarManager.js 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. (function() {
  2. var nodeEnv = typeof require !== 'undefined' && typeof process !== 'undefined';
  3. var __module = nodeEnv ? module : {exports:{}};
  4. var __filename = 'preview-scripts/assets/script/manager/AStarManager.js';
  5. var __require = nodeEnv ? function (request) {
  6. return cc.require(request);
  7. } : function (request) {
  8. return __quick_compile_project__.require(request, __filename);
  9. };
  10. function __define (exports, require, module) {
  11. if (!nodeEnv) {__quick_compile_project__.registerModule(__filename, module);}"use strict";
  12. cc._RF.push(module, '3340f9i319GmJ0tJdpeE3DX', 'AStarManager');
  13. // script/manager/AStarManager.ts
  14. "use strict";
  15. Object.defineProperty(exports, "__esModule", { value: true });
  16. var AStarNode = /** @class */ (function () {
  17. /**
  18. * @param x 节点横坐标
  19. * @param y 节点纵坐标
  20. */
  21. function AStarNode(x, y) {
  22. this._x = 0;
  23. this._y = 0;
  24. this.priority = 0;
  25. this._x = x;
  26. this._y = y;
  27. }
  28. Object.defineProperty(AStarNode.prototype, "x", {
  29. get: function () { return this._x; },
  30. enumerable: false,
  31. configurable: true
  32. });
  33. Object.defineProperty(AStarNode.prototype, "y", {
  34. get: function () { return this._y; },
  35. enumerable: false,
  36. configurable: true
  37. });
  38. return AStarNode;
  39. }());
  40. var Frontier = /** @class */ (function () {
  41. function Frontier() {
  42. this.arr = []; //创建字典(数组)
  43. }
  44. Frontier.prototype.put = function (node, priority) {
  45. node.priority = priority;
  46. this.arr.push(node); //添加元素
  47. this.arr.sort(function (a, b) { return b.priority - a.priority; });
  48. };
  49. Frontier.prototype.get = function () {
  50. return this.arr.pop(); //删除元素
  51. };
  52. Object.defineProperty(Frontier.prototype, "size", {
  53. get: function () {
  54. return this.arr.length;
  55. },
  56. enumerable: false,
  57. configurable: true
  58. });
  59. Frontier.prototype.reset = function () {
  60. this.arr = [];
  61. };
  62. return Frontier;
  63. }());
  64. var AStarManager = /** @class */ (function () {
  65. // 通过private修饰符,让类无法在外部创建新的实例
  66. function AStarManager() {
  67. this.mSize = null; // 寻路地图大小
  68. this.mStart = null; // 寻路起始点坐标
  69. this.mEnd = null; // 寻路目标点坐标
  70. this.mStartNode = null; // 起始点
  71. this.mEndNode = null; // 目标点
  72. this.obstacles = {};
  73. ///////////////////////////// 寻路开始 ////////////////////
  74. // 节点池
  75. this.nodePool = {};
  76. // 探索边界
  77. this.frontier = null;
  78. // 节点来向(路径)
  79. this.cameForm = new Map();
  80. // 节点当前代价
  81. this.costSoFar = new Map();
  82. this.closeList = [];
  83. }
  84. AStarManager.Instance = function () {
  85. if (!this.instance) {
  86. this.instance = new AStarManager();
  87. }
  88. return this.instance;
  89. };
  90. ;
  91. /**
  92. * 设置地图横纵最大值
  93. * @param size 地图大小
  94. * @param start 寻路起始点
  95. * @param end 寻路目标点
  96. * @param obstacles 障碍物
  97. */
  98. AStarManager.prototype.init = function (size, start, end, obstacles) {
  99. var _this = this;
  100. if (obstacles === void 0) { obstacles = []; }
  101. this.mSize = size;
  102. this.mStart = start;
  103. this.mEnd = end;
  104. this.obstacles = {};
  105. obstacles.forEach(function (ele) {
  106. _this.setObstacles(ele.x, ele.y);
  107. });
  108. this.nodePool = {};
  109. this.mStartNode = this.createNode(this.mStart.x, this.mStart.y);
  110. this.mEndNode = this.createNode(this.mEnd.x, this.mEnd.y);
  111. };
  112. AStarManager.prototype.clean = function () {
  113. this.mStartNode = null;
  114. this.mEndNode = null;
  115. };
  116. /**
  117. * 设置障碍物
  118. * @param x 障碍物横坐标
  119. * @param y 障碍物纵坐标
  120. */
  121. AStarManager.prototype.setObstacles = function (x, y) {
  122. if (!this.checkNode(x, y))
  123. return;
  124. this.obstacles[x + "_" + y] = true;
  125. };
  126. /**
  127. * 清除障碍物
  128. * @param x 障碍物横坐标
  129. * @param y 障碍物纵坐标
  130. */
  131. AStarManager.prototype.clearObstacles = function (x, y) {
  132. delete this.obstacles[x + "_" + y];
  133. };
  134. /**
  135. * 检查是否有障碍物
  136. * @param x 障碍物横坐标
  137. * @param y 障碍物纵坐标
  138. */
  139. AStarManager.prototype.checkObstacles = function (x, y) {
  140. return this.obstacles[x + "_" + y];
  141. };
  142. /**
  143. * 检查节点是否在地图内
  144. * @param x 节点横坐标
  145. * @param y 节点纵坐标
  146. */
  147. AStarManager.prototype.checkNode = function (x, y) {
  148. return x >= 0 && y >= 0 && x <= this.mSize.width && y <= this.mSize.height;
  149. };
  150. /**
  151. * 开始寻路
  152. * @param type 寻路类型,4方向或8方向
  153. */
  154. AStarManager.prototype.run = function (type) {
  155. if (type === void 0) { type = 4; }
  156. this.mType = type;
  157. // console.log('##### 寻路开始 #####');
  158. // console.log('地图大小:', this.mSize);
  159. // console.log('寻路类型:', this.mType + '方向');
  160. // console.log(`出发点X:${this.mStart.x}_Y:${this.mStart.y}`);
  161. // console.log(`目标点:X:${this.mEnd.x}_Y:${this.mEnd.y}`);
  162. // console.log('障碍物:', this.obstacles);
  163. var start = this.mStartNode;
  164. var goal = this.mEndNode;
  165. if (this.frontier)
  166. this.frontier.reset();
  167. else
  168. this.frontier = new Frontier();
  169. this.frontier.put(start, 0); //将起始点加入openList,表示我们从这里触发,是我们第一步可以走的点
  170. this.cameForm.clear();
  171. this.cameForm.set(start, null);
  172. this.costSoFar.clear();
  173. this.costSoFar.set(start, 0);
  174. this.closeList = [];
  175. while (this.frontier.size > 0) {
  176. var curr = this.frontier.get(); // 每次都取出f值最小的节点进行查找
  177. if (curr === goal) {
  178. break;
  179. }
  180. var nextList = this.getNeighbors(curr); //从openList中取出一个点作为nextNode,获取这个点下一步所有可走的点,存入nextList
  181. for (var _i = 0, nextList_1 = nextList; _i < nextList_1.length; _i++) { //如果nextList长度为0,说明没有路可走了;长度为大于0,则将nextList中的点都放入openList
  182. var next = nextList_1[_i];
  183. if (this.closeList.indexOf(this.getNodeKey(next.x, next.y)) < 0) {
  184. var nextCost = this.costSoFar.get(curr) + this.getCost(curr, next);
  185. // console.log("next的索引:"+this.getNodeKey(next.x,next.y)+",开销:"+nextCost+"父节点索引:"+this.getNodeKey(curr.x,curr.y))
  186. if (!this.costSoFar.has(next) || nextCost < this.costSoFar.get(next)) {
  187. this.costSoFar.set(next, nextCost);
  188. var preCost = this.getCost(next, goal);
  189. this.frontier.put(next, nextCost + preCost); //内部根据开销进行了自动排序(从小到大)
  190. this.cameForm.set(next, curr);
  191. }
  192. }
  193. }
  194. this.closeList.push(this.getNodeKey(curr.x, curr.y));
  195. }
  196. };
  197. AStarManager.prototype.getPath = function () {
  198. var arr = [];
  199. var node = this.mEndNode;
  200. arr.push(node);
  201. while (this.cameForm.has(node)) {
  202. node = this.cameForm.get(node);
  203. node && arr.push(node);
  204. }
  205. return arr;
  206. };
  207. AStarManager.prototype.getNeighbors = function (node) {
  208. var neighbors = [];
  209. if (this.mType === 8) {
  210. var upright = this.getNode(node.x + 1, node.y + 1);
  211. upright && neighbors.push(upright);
  212. var upleft = this.getNode(node.x - 1, node.y + 1);
  213. upleft && neighbors.push(upleft);
  214. var downleft = this.getNode(node.x - 1, node.y - 1);
  215. downleft && neighbors.push(downleft);
  216. var downright = this.getNode(node.x + 1, node.y - 1);
  217. downright && neighbors.push(downright);
  218. }
  219. var up = this.getNode(node.x, node.y + 1);
  220. up && neighbors.push(up);
  221. var down = this.getNode(node.x, node.y - 1);
  222. down && neighbors.push(down);
  223. var left = this.getNode(node.x - 1, node.y);
  224. left && neighbors.push(left);
  225. var right = this.getNode(node.x + 1, node.y);
  226. right && neighbors.push(right);
  227. return neighbors;
  228. };
  229. AStarManager.prototype.getCost = function (node1, node2) {
  230. return cc.Vec2.distance(new cc.Vec2(node1.x, node1.y), new cc.Vec2(node2.x, node2.y));
  231. };
  232. // 寻找下一个点
  233. AStarManager.prototype.next = function () {
  234. };
  235. AStarManager.prototype.getNode = function (x, y) {
  236. if (!this.checkNode(x, y))
  237. return;
  238. if (this.checkObstacles(x, y))
  239. return;
  240. var key = this.getNodeKey(x, y);
  241. return this.nodePool[key] || this.createNode(x, y);
  242. };
  243. AStarManager.prototype.createNode = function (x, y) {
  244. var key = this.getNodeKey(x, y);
  245. this.nodePool[key] = new AStarNode(x, y);
  246. return this.nodePool[key];
  247. };
  248. AStarManager.prototype.getNodeKey = function (x, y) {
  249. return x + "_" + y;
  250. };
  251. AStarManager.instance = null;
  252. return AStarManager;
  253. }());
  254. exports.default = AStarManager;
  255. cc._RF.pop();
  256. }
  257. if (nodeEnv) {
  258. __define(__module.exports, __require, __module);
  259. }
  260. else {
  261. __quick_compile_project__.registerModuleFunc(__filename, function () {
  262. __define(__module.exports, __require, __module);
  263. });
  264. }
  265. })();
  266. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImFzc2V0cy9zY3JpcHQvbWFuYWdlci9BU3Rhck1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtJQUtJOzs7T0FHRztJQUNILG1CQUFZLENBQVEsRUFBRSxDQUFRO1FBUnRCLE9BQUUsR0FBVSxDQUFDLENBQUM7UUFDZCxPQUFFLEdBQVUsQ0FBQyxDQUFDO1FBV3RCLGFBQVEsR0FBRyxDQUFDLENBQUM7UUFIVCxJQUFJLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNaLElBQUksQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ2hCLENBQUM7SUFURCxzQkFBSSx3QkFBQzthQUFMLGNBQVMsT0FBTyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUEsQ0FBQzs7O09BQUE7SUFDekIsc0JBQUksd0JBQUM7YUFBTCxjQUFTLE9BQU8sSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFBLENBQUM7OztPQUFBO0lBVTdCLGdCQUFDO0FBQUQsQ0FkQSxBQWNDLElBQUE7QUFFRDtJQUFBO1FBQ1ksUUFBRyxHQUFlLEVBQUUsQ0FBQyxDQUFBLFVBQVU7SUFpQjNDLENBQUM7SUFoQkcsc0JBQUcsR0FBSCxVQUFJLElBQWMsRUFBRSxRQUFlO1FBQy9CLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsT0FBTztRQUM1QixJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxVQUFDLENBQUMsRUFBQyxDQUFDLElBQUcsT0FBQSxDQUFDLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxRQUFRLEVBQXZCLENBQXVCLENBQUMsQ0FBQztJQUNsRCxDQUFDO0lBQ0Qsc0JBQUcsR0FBSDtRQUNJLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFBLE1BQU07SUFDaEMsQ0FBQztJQUVELHNCQUFJLDBCQUFJ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TSxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ3BELE1BQU0sSUFBSSxTQUFTLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBRWpDLElBQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUN0RCxRQUFRLElBQUksU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUVyQyxJQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDdkQsU0FBUyxJQUFJLFNBQVMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7U0FDMUM7UUFFRCxJQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUM1QyxFQUFFLElBQUksU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUV6QixJQUFNLElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUM5QyxJQUFJLElBQUksU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUU3QixJQUFNLElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5QyxJQUFJLElBQUksU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUU3QixJQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMvQyxLQUFLLElBQUksU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUUvQixPQUFPLFNBQVMsQ0FBQztJQUNyQixDQUFDO0lBRUQsOEJBQU8sR0FBUCxVQUFRLEtBQWUsRUFBRSxLQUFlO1FBQ3BDLE9BQU8sRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFGLENBQUM7SUFFRCxTQUFTO0lBQ0YsMkJBQUksR0FBWDtJQUVBLENBQUM7SUFFTyw4QkFBTyxHQUFmLFVBQWdCLENBQVEsRUFBRSxDQUFRO1FBQzlCLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7WUFBRSxPQUFPO1FBQ2xDLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQUUsT0FBTztRQUN0QyxJQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNsQyxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdkQsQ0FBQztJQUNPLGlDQUFVLEdBQWxCLFVBQW1CLENBQVEsRUFBRSxDQUFRO1FBQ2pDLElBQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ2xDLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEdBQUcsSUFBSSxTQUFTLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3pDLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM5QixDQUFDO0lBRU8saUNBQVUsR0FBbEIsVUFBbUIsQ0FBUSxFQUFFLENBQVE7UUFDakMsT0FBVSxDQUFDLFNBQUksQ0FBRyxDQUFDO0lBQ3ZCLENBQUM7SUExTmMscUJBQVEsR0FBZ0IsSUFBSSxDQUFDO0lBMk5oRCxtQkFBQztDQTVORCxBQTROQyxJQUFBO2tCQTVOb0IsWUFBWSIsImZpbGUiOiIiLCJzb3VyY2VSb290IjoiLyIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEFTdGFyTm9kZSB7XG4gICAgcHJpdmF0ZSBfeDpudW1iZXIgPSAwO1xuICAgIHByaXZhdGUgX3k6bnVtYmVyID0gMDtcbiAgICBnZXQgeCgpIHtyZXR1cm4gdGhpcy5feDt9XG4gICAgZ2V0IHkoKSB7cmV0dXJuIHRoaXMuX3k7fVxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB4IOiKgueCueaoquWdkOagh1xuICAgICAqIEBwYXJhbSB5IOiKgueCuee6teWdkOagh1xuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHg6bnVtYmVyLCB5Om51bWJlcikge1xuICAgICAgICB0aGlzLl94ID0geDtcbiAgICAgICAgdGhpcy5feSA9IHk7XG4gICAgfVxuICAgIHByaW9yaXR5ID0gMDtcbn1cblxuY2xhc3MgRnJvbnRpZXIge1xuICAgIHByaXZhdGUgYXJyOkFTdGFyTm9kZVtdID0gW107Ly/liJvlu7rlrZflhbgo5pWw57uEKVxuICAgIHB1dChub2RlOkFTdGFyTm9kZSwgcHJpb3JpdHk6bnVtYmVyKSB7XG4gICAgICAgIG5vZGUucHJpb3JpdHkgPSBwcmlvcml0eTtcbiAgICAgICAgdGhpcy5hcnIucHVzaChub2RlKTsgLy/mt7vliqDlhYPntKAgXG4gICAgICAgIHRoaXMuYXJyLnNvcnQoKGEsYik9PmIucHJpb3JpdHkgLSBhLnByaW9yaXR5KTtcbiAgICB9XG4gICAgZ2V0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5hcnIucG9wKCk7Ly/liKDpmaTlhYPntKBcbiAgICB9XG5cbiAgICBnZXQgc2l6ZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXJyLmxlbmd0aDtcbiAgICB9XG5cbiAgICByZXNldCgpe1xuICAgICAgICB0aGlzLmFyciA9IFtdO1xuICAgIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQVN0YXJNYW5hZ2Vye1xuICAgIHByaXZhdGUgc3RhdGljIGluc3RhbmNlOkFTdGFyTWFuYWdlciA9IG51bGw7XG4gICBcbiAgICBzdGF0aWMgSW5zdGFuY2UoKSB7XG4gICAgICAgIGlmICghdGhpcy5pbnN0YW5jZSkgeyBcbiAgICAgICAgICAgIHRoaXMuaW5zdGFuY2UgPSBuZXcgQVN0YXJNYW5hZ2VyKCk7IFxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmluc3RhbmNlO1xuICAgIH07XG5cbiAgICAvLyDpgJrov4dwcml2YXRl5L+u6aWw56ym77yM6K6p57G75peg5rOV5Zyo5aSW6YOo5Yib5bu65paw55qE5a6e5L6LXG4gICAgcHJpdmF0ZSBjb25zdHJ1Y3RvcigpIHsgXG5cbiAgICB9XG4gICAgXG5cbiAgICBwcml2YXRlIG1TaXplOmNjLlNpemUgPSBudWxsOyAgLy8g5a+76Lev5Zyw5Zu+5aSn5bCPXG4gICAgcHJpdmF0ZSBtU3RhcnQ6Y2MuVmVjMiA9IG51bGw7IC8vIOWvu+i3r+i1t+Wni+eCueWdkOagh1xuICAgIHByaXZhdGUgbUVuZDpjYy5WZWMyID0gbnVsbDsgICAvLyDlr7vot6/nm67moIfngrnlnZDmoIdcblxuICAgIHByaXZhdGUgbVN0YXJ0Tm9kZTpBU3Rhck5vZGUgPSBudWxsOyAvLyDotbflp4vngrlcbiAgICBwcml2YXRlIG1FbmROb2RlOkFTdGFyTm9kZSA9IG51bGw7ICAgLy8g55uu5qCH54K5XG4gICAgLyoqXG4gICAgICog6K6+572u5Zyw5Zu+5qiq57q15pyA5aSn5YC8XG4gICAgICogQHBhcmFtIHNpemUgICAgICDlnLDlm77lpKflsI9cbiAgICAgKiBAcGFyYW0gc3RhcnQgICAgIOWvu+i3r+i1t+Wni+eCuVxuICAgICAqIEBwYXJhbSBlbmQgICAgICAg5a+76Lev55uu5qCH54K5XG4gICAgICogQHBhcmFtIG9ic3RhY2xlcyDpmpznoo3nialcbiAgICAgKi9cbiAgICBwdWJsaWMgaW5pdChzaXplOmNjLlNpemUsIHN0YXJ0OmNjLlZlYzIsIGVuZDpjYy5WZWMyLCBvYnN0YWNsZXM6Y2MuVmVjMltdID0gW10pIHtcbiAgICAgICAgdGhpcy5tU2l6ZSA9IHNpemU7XG4gICAgICAgIHRoaXMubVN0YXJ0ID0gc3RhcnQ7XG4gICAgICAgIHRoaXMubUVuZCA9IGVuZDtcbiAgICAgICAgdGhpcy5vYnN0YWNsZXMgPSB7fTtcbiAgICAgICAgb2JzdGFjbGVzLmZvckVhY2goKGVsZSkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXRPYnN0YWNsZXMoZWxlLngsIGVsZS55KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5ub2RlUG9vbCA9IHt9O1xuXG4gICAgICAgIHRoaXMubVN0YXJ0Tm9kZSA9IHRoaXMuY3JlYXRlTm9kZSh0aGlzLm1TdGFydC54LCB0aGlzLm1TdGFydC55KTtcbiAgICAgICAgdGhpcy5tRW5kTm9kZSAgID0gdGhpcy5jcmVhdGVOb2RlKHRoaXMubUVuZC54LCB0aGlzLm1FbmQueSk7XG4gICAgfVxuXG4gICAgcHVibGljIGNsZWFuKCl7XG4gICAgICAgIHRoaXMubVN0YXJ0Tm9kZSA9IG51bGw7XG4gICAgICAgIHRoaXMubUVuZE5vZGUgPSBudWxsO1xuICAgIH1cbiAgICBcbiAgICBwcml2YXRlIG9ic3RhY2xlczp7W3hfeTpzdHJpbmddOmJvb2xlYW59ID0ge307XG4gICAgLyoqXG4gICAgICog6K6+572u6Zqc56KN54mpXG4gICAgICogQHBhcmFtIHgg6Zqc56KN54mp5qiq5Z2Q5qCHXG4gICAgICogQHBhcmFtIHkg6Zqc56KN54mp57q15Z2Q5qCHXG4gICAgICovXG4gICAgcHVibGljIHNldE9ic3RhY2xlcyh4Om51bWJlciwgeTpudW1iZXIpIHtcbiAgICAgICAgaWYgKCF0aGlzLmNoZWNrTm9kZSh4LCB5KSkgcmV0dXJuO1xuICAgICAgICB0aGlzLm9ic3RhY2xlc1tgJHt4fV8ke3l9YF0gPSB0cnVlO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiDmuIXpmaTpmpznoo3nialcbiAgICAgKiBAcGFyYW0geCDpmpznoo3nianmqKrlnZDmoIdcbiAgICAgKiBAcGFyYW0geSDpmpznoo3niannurXlnZDmoIdcbiAgICAgKi9cbiAgICBwdWJsaWMgY2xlYXJPYnN0YWNsZXMoeDpudW1iZXIsIHk6bnVtYmVyKSB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLm9ic3RhY2xlc1tgJHt4fV8ke3l9YF07XG4gICAgfVxuICAgIC8qKlxuICAgICAqIOajgOafpeaYr+WQpuaciemanOeijeeJqVxuICAgICAqIEBwYXJhbSB4IOmanOeijeeJqeaoquWdkOagh1xuICAgICAqIEBwYXJhbSB5IOmanOeijeeJqee6teWdkOagh1xuICAgICAqL1xuICAgIHB1YmxpYyBjaGVja09ic3RhY2xlcyh4Om51bWJlciwgeTpudW1iZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub2JzdGFjbGVzW2Ake3h9XyR7eX1gXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDmo4Dmn6XoioLngrnmmK/lkKblnKjlnLDlm77lhoVcbiAgICAgKiBAcGFyYW0geCDoioLngrnmqKrlnZDmoIdcbiAgICAgKiBAcGFyYW0geSDoioLngrnnurXlnZDmoIdcbiAgICAgKi9cbiAgICBwdWJsaWMgY2hlY2tOb2RlKHg6bnVtYmVyLCB5Om51bWJlcikge1xuICAgICAgICByZXR1cm4geCA+PSAwICYmIHkgPj0gMCAmJiB4IDw9IHRoaXMubVNpemUud2lkdGggJiYgeSA8PSB0aGlzLm1TaXplLmhlaWdodDtcbiAgICB9XG5cbiBcbiAgICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLyDlr7vot6/lvIDlp4sgLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgICAvLyDoioLngrnmsaBcbiAgICBwcml2YXRlIG5vZGVQb29sOntbeF95OnN0cmluZ106QVN0YXJOb2RlfSA9IHt9O1xuICAgIC8vIOaOoue0oui+ueeVjFxuICAgIHByaXZhdGUgZnJvbnRpZXI6RnJvbnRpZXIgPSBudWxsO1xuICAgIC8vIOiKgueCueadpeWQkSjot6/lvoQpXG4gICAgcHJpdmF0ZSBjYW1lRm9ybTpNYXA8QVN0YXJOb2RlLCBBU3Rhck5vZGU+ID0gbmV3IE1hcCgpO1xuICAgIC8vIOiKgueCueW9k+WJjeS7o+S7t1xuICAgIHByaXZhdGUgY29zdFNvRmFyOk1hcDxBU3Rhck5vZGUsIG51bWJlcj4gPSBuZXcgTWFwKCk7XG4gICAgLy8g5a+76Lev57G75Z6LKDTmlrnlkJHmiJY45pa55ZCRKVxuICAgIHByaXZhdGUgbVR5cGU6IDR8ODtcblxuICAgIHByaXZhdGUgY2xvc2VMaXN0OnN0cmluZ1tdID0gW107XG5cbiAgICAvKipcbiAgICAgKiDlvIDlp4vlr7vot69cbiAgICAgKiBAcGFyYW0gdHlwZSDlr7vot6/nsbvlnovvvIw05pa55ZCR5oiWOOaWueWQkVxuICAgICAqL1xuICAgIHB1YmxpYyBydW4odHlwZTo0fDggPSA0KSB7XG4gICAgICAgIHRoaXMubVR5cGUgPSB0eXBlO1xuXG4gICAgICAgIC8vIGNvbnNvbGUubG9nKCcjIyMjIyDlr7vot6/lvIDlp4sgIyMjIyMnKTtcblxuICAgICAgICAvLyBjb25zb2xlLmxvZygn5Zyw5Zu+5aSn5bCPOicsIHRoaXMubVNpemUpO1xuICAgICAgICAvLyBjb25zb2xlLmxvZygn5a+76Lev57G75Z6LOicsIHRoaXMubVR5cGUgKyAn5pa55ZCRJyk7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKGDlh7rlj5HngrlYOiR7dGhpcy5tU3RhcnQueH1fWToke3RoaXMubVN0YXJ0Lnl9YCk7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKGDnm67moIfngrk6WDoke3RoaXMubUVuZC54fV9ZOiR7dGhpcy5tRW5kLnl9YCk7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKCfpmpznoo3niak6JywgdGhpcy5vYnN0YWNsZXMpO1xuXG5cbiAgICAgICAgY29uc3Qgc3RhcnQgPSB0aGlzLm1TdGFydE5vZGU7XG4gICAgICAgIGNvbnN0IGdvYWwgPSB0aGlzLm1FbmROb2RlO1xuICAgICAgICBpZiAodGhpcy5mcm9udGllcilcbiAgICAgICAgICAgIHRoaXMuZnJvbnRpZXIucmVzZXQoKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdGhpcy5mcm9udGllciA9IG5ldyBGcm9udGllcigpO1xuXG4gICAgICAgIHRoaXMuZnJvbnRpZXIucHV0KHN0YXJ0LCAwKTsvL+Wwhui1t+Wni+eCueWKoOWFpW9wZW5MaXN077yM6KGo56S65oiR5Lus5LuO6L+Z6YeM6Kem5Y+R77yM5piv5oiR5Lus56ys5LiA5q2l5Y+v5Lul6LWw55qE54K5XG5cbiAgICAgICAgdGhpcy5jYW1lRm9ybS5jbGVhcigpO1xuICAgICAgICB0aGlzLmNhbWVGb3JtLnNldChzdGFydCwgbnVsbCk7XG4gICAgICAgIHRoaXMuY29zdFNvRmFyLmNsZWFyKCk7XG4gICAgICAgIHRoaXMuY29zdFNvRmFyLnNldChzdGFydCwgMCk7XG4gICAgICAgIHRoaXMuY2xvc2VMaXN0ID0gW107XG5cbiAgICAgICAgd2hpbGUgKHRoaXMuZnJvbnRpZXIuc2l6ZSA+IDApIHtcbiAgICAgICAgICAgIGxldCBjdXJyID0gdGhpcy5mcm9udGllci5nZXQoKTsgIC8vIOavj+asoemDveWPluWHumblgLzmnIDlsI/nmoToioLngrnov5vooYzmn6Xmib5cbiAgICAgICAgICAgIGlmIChjdXJyID09PSBnb2FsKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgbmV4dExpc3QgPSB0aGlzLmdldE5laWdoYm9ycyhjdXJyKTsgLy/ku45vcGVuTGlzdOS4reWPluWHuuS4gOS4queCueS9nOS4um5leHROb2Rl77yM6I635Y+W6L+Z5Liq54K55LiL5LiA5q2l5omA5pyJ5Y+v6LWw55qE54K577yM5a2Y5YWlbmV4dExpc3RcbiAgICAgICAgICAgIGZvciAobGV0IG5leHQgb2YgbmV4dExpc3QpIHsvL+WmguaenG5leHRMaXN06ZW/5bqm5Li6MO+8jOivtOaYjuayoeaciei3r+WPr+i1sOS6hjvplb/luqbkuLrlpKfkuo4w77yM5YiZ5bCGbmV4dExpc3TkuK3nmoTngrnpg73mlL7lhaVvcGVuTGlzdFxuICAgICAgICAgICAgICAgIGlmKHRoaXMuY2xvc2VMaXN0LmluZGV4T2YodGhpcy5nZXROb2RlS2V5KG5leHQueCxuZXh0LnkpKSA8IDApe1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXh0Q29zdCA9IHRoaXMuY29zdFNvRmFyLmdldChjdXJyKSArIHRoaXMuZ2V0Q29zdChjdXJyLCBuZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJuZXh055qE57Si5byVOlwiK3RoaXMuZ2V0Tm9kZUtleShuZXh0LngsbmV4dC55KStcIizlvIDplIA6XCIrbmV4dENvc3QrXCLniLboioLngrnntKLlvJU6XCIrdGhpcy5nZXROb2RlS2V5KGN1cnIueCxjdXJyLnkpKVxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY29zdFNvRmFyLmhhcyhuZXh0KSB8fCBuZXh0Q29zdCA8IHRoaXMuY29zdFNvRmFyLmdldChuZXh0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb3N0U29GYXIuc2V0KG5leHQsIG5leHRDb3N0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHByZUNvc3QgPSB0aGlzLmdldENvc3QobmV4dCwgZ29hbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZyb250aWVyLnB1dChuZXh0LCBuZXh0Q29zdCArIHByZUNvc3QpOy8v5YaF6YOo5qC55o2u5byA6ZSA6L+b6KGM5LqG6Ieq5Yqo5o6S5bqPKOS7juWwj+WIsOWkpylcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FtZUZvcm0uc2V0KG5leHQsIGN1cnIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5jbG9zZUxpc3QucHVzaCh0aGlzLmdldE5vZGVLZXkoY3Vyci54LGN1cnIueSkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGdldFBhdGgoKSB7XG4gICAgICAgIGNvbnN0IGFyciA9IFtdO1xuICAgICAgICBsZXQgbm9kZSA9IHRoaXMubUVuZE5vZGU7XG4gICAgICAgIGFyci5wdXNoKG5vZGUpO1xuICAgICAgICB3aGlsZSAodGhpcy5jYW1lRm9ybS5oYXMobm9kZSkpIHtcbiAgICAgICAgICAgIG5vZGUgPSB0aGlzLmNhbWVGb3JtLmdldChub2RlKTtcbiAgICAgICAgICAgIG5vZGUgJiYgYXJyLnB1c2gobm9kZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFycjtcbiAgICB9XG5cbiAgICBnZXROZWlnaGJvcnMobm9kZTpBU3Rhck5vZGUpIHtcbiAgICAgICAgY29uc3QgbmVpZ2hib3JzID0gW107XG5cbiAgICAgICAgaWYgKHRoaXMubVR5cGUgPT09IDgpIHtcbiAgICAgICAgICAgIGNvbnN0IHVwcmlnaHQgPSB0aGlzLmdldE5vZGUobm9kZS54ICsgMSwgbm9kZS55ICsgMSk7XG4gICAgICAgICAgICB1cHJpZ2h0ICYmIG5laWdoYm9ycy5wdXNoKHVwcmlnaHQpO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBjb25zdCB1cGxlZnQgPSB0aGlzLmdldE5vZGUobm9kZS54IC0gMSwgbm9kZS55ICsgMSk7XG4gICAgICAgICAgICB1cGxlZnQgJiYgbmVpZ2hib3JzLnB1c2godXBsZWZ0KTtcbiAgICBcbiAgICAgICAgICAgIGNvbnN0IGRvd25sZWZ0ID0gdGhpcy5nZXROb2RlKG5vZGUueCAtIDEsIG5vZGUueSAtIDEpO1xuICAgICAgICAgICAgZG93bmxlZnQgJiYgbmVpZ2hib3JzLnB1c2goZG93bmxlZnQpO1xuICAgIFxuICAgICAgICAgICAgY29uc3QgZG93bnJpZ2h0ID0gdGhpcy5nZXROb2RlKG5vZGUueCArIDEsIG5vZGUueSAtIDEpO1xuICAgICAgICAgICAgZG93bnJpZ2h0ICYmIG5laWdoYm9ycy5wdXNoKGRvd25yaWdodCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB1cCA9IHRoaXMuZ2V0Tm9kZShub2RlLngsIG5vZGUueSArIDEpO1xuICAgICAgICB1cCAmJiBuZWlnaGJvcnMucHVzaCh1cCk7XG4gICAgICAgIFxuICAgICAgICBjb25zdCBkb3duID0gdGhpcy5nZXROb2RlKG5vZGUueCwgbm9kZS55IC0gMSk7XG4gICAgICAgIGRvd24gJiYgbmVpZ2hib3JzLnB1c2goZG93bik7XG4gICAgICAgIFxuICAgICAgICBjb25zdCBsZWZ0ID0gdGhpcy5nZXROb2RlKG5vZGUueCAtIDEsIG5vZGUueSk7XG4gICAgICAgIGxlZnQgJiYgbmVpZ2hib3JzLnB1c2gobGVmdCk7XG4gICAgICAgIFxuICAgICAgICBjb25zdCByaWdodCA9IHRoaXMuZ2V0Tm9kZShub2RlLnggKyAxLCBub2RlLnkpO1xuICAgICAgICByaWdodCAmJiBuZWlnaGJvcnMucHVzaChyaWdodCk7XG5cbiAgICAgICAgcmV0dXJuIG5laWdoYm9ycztcbiAgICB9XG5cbiAgICBnZXRDb3N0KG5vZGUxOkFTdGFyTm9kZSwgbm9kZTI6QVN0YXJOb2RlKSB7XG4gICAgICAgIHJldHVybiBjYy5WZWMyLmRpc3RhbmNlKG5ldyBjYy5WZWMyKG5vZGUxLngsIG5vZGUxLnkpLCBuZXcgY2MuVmVjMihub2RlMi54LCBub2RlMi55KSk7XG4gICAgfVxuXG4gICAgLy8g5a+75om+5LiL5LiA5Liq54K5XG4gICAgcHVibGljIG5leHQoKSB7XG4gICAgICAgIFxuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0Tm9kZSh4Om51bWJlciwgeTpudW1iZXIpOiBBU3Rhck5vZGUge1xuICAgICAgICBpZiAoIXRoaXMuY2hlY2tOb2RlKHgsIHkpKSByZXR1cm47XG4gICAgICAgIGlmICh0aGlzLmNoZWNrT2JzdGFjbGVzKHgsIHkpKSByZXR1cm47XG4gICAgICAgIGNvbnN0IGtleSA9IHRoaXMuZ2V0Tm9kZUtleSh4LCB5KTtcbiAgICAgICAgcmV0dXJuIHRoaXMubm9kZVBvb2xba2V5XSB8fCB0aGlzLmNyZWF0ZU5vZGUoeCwgeSk7IFxuICAgIH1cbiAgICBwcml2YXRlIGNyZWF0ZU5vZGUoeDpudW1iZXIsIHk6bnVtYmVyKSB7XG4gICAgICAgIGNvbnN0IGtleSA9IHRoaXMuZ2V0Tm9kZUtleSh4LCB5KTtcbiAgICAgICAgdGhpcy5ub2RlUG9vbFtrZXldID0gbmV3IEFTdGFyTm9kZSh4LCB5KTtcbiAgICAgICAgcmV0dXJuIHRoaXMubm9kZVBvb2xba2V5XTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldE5vZGVLZXkoeDpudW1iZXIsIHk6bnVtYmVyKSB7XG4gICAgICAgIHJldHVybiBgJHt4fV8ke3l9YDtcbiAgICB9XG59XG4iXX0=