Code coverage report for ranking/src/core.js

Statements: 98.21% (165 / 168)      Branches: 87.27% (48 / 55)      Functions: 100% (7 / 7)      Lines: 98.2% (164 / 167)      Ignored: none     

All files » ranking/src/ » core.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291    1     1 1 1 1   1 37 37 37 37 37   37 37 37 37 37 37   37 6 6     31 1     30   30 30   30 88   88   88 43 28 28   28                     15 26 26 26 26 26 22 22 21             30     1 52 52 52 52 52   52 52 52 52 52 52 52   52   52 52   52 149   149   149     149 37     112 47 47   47 47 47 47   47 47   47         47                     65 65 113 113 113 20 20 20               1 209   209 671 671 671 671 671 671 671 671   671 671           671   671 671   671   671 671   671   671 671     671 122 122 352       671     671 462             462 462             209 121     209 209 209 209         1 753 753   753 753   753 753 53 53     753 753   753     1 671 671 671 671   671 671   671 671 22   649     671 671     1 746 746 746   746 746 746     1 746 746 746 746   746 746 291   455   746 746    
'use strict';
 
Object.defineProperty(exports, '__esModule', {
  value: true
});
exports.findByScore = findByScore;
exports.findByPosition = findByPosition;
exports.setScore = setScore;
var debug = require('./debug')('ranking');
 
function findByScore(_ref) {
  var branchFactor = _ref.branchFactor;
  var node = _ref.node;
  var nodeScoreRange = _ref.nodeScoreRange;
  var query = _ref.query;
  var result = _ref.result;
 
  debug('');
  debug('query.$limit [%o]', query.$limit);
  debug('nodeScoreRange.beginAt [%o]', nodeScoreRange.beginAt);
  debug('nodeScoreRange.endAt [%o]', nodeScoreRange.endAt);
  debug('query.score.$gte [%o]', query.score.$gte);
  debug('query.score.$lte [%o]', query.score.$lte);
 
  if (nodeScoreRange.beginAt > query.score.$lte) {
    result.position += node.amount;
    return;
  }
 
  if (nodeScoreRange.endAt < query.score.$gte) {
    return;
  }
 
  var _resolveBranchInfo = resolveBranchInfo({ nodeScoreRange: nodeScoreRange, branchFactor: branchFactor });
 
  var amountLeafsPerBranch = _resolveBranchInfo.amountLeafsPerBranch;
  var amountBranches = _resolveBranchInfo.amountBranches;
 
  for (var i = amountBranches - 1; /*base 0*/i >= 0; i--) {
    debug('index loop [%o]', i);
 
    var currentNode = node.children[i];
 
    if (result.list.length < query.$limit && currentNode.amount > 0) {
      if (!currentNode.playerIds) {
        var nodeScoreRangeBeginAt = resolveInitScore({ nodeScoreRangeBeginAt: nodeScoreRange.beginAt, indexScore: i, amountLeafsPerBranch: amountLeafsPerBranch });
        var nodeScoreRange$lte = resolveMaxScore({ nodeScoreRangeBeginAt: nodeScoreRangeBeginAt, indexScore: i, amountLeafsPerBranch: amountLeafsPerBranch, amountBranches: amountBranches });
 
        findByScore({
          branchFactor: branchFactor,
          node: currentNode,
          nodeScoreRange: {
            beginAt: nodeScoreRangeBeginAt,
            endAt: nodeScoreRange$lte
          },
          query: query,
          result: result
        });
      } else {
        for (var playerIndex = 0; playerIndex < currentNode.amount; playerIndex++) {
          debug('node.children[%o].amount [%o]', i, currentNode.amount);
          debug('node.children[%o].score [%o]', i, currentNode.score);
          debug('node.children[%o].playerIds [%o]', i, currentNode.playerIds);
          result.position += 1;
          if (result.list.length < query.$limit && currentNode.score >= query.score.$gte && currentNode.score <= query.score.$lte) {
            var playerId = currentNode.playerIds[playerIndex];
            if (!query.playerId || playerId >= query.playerId.$gte && playerId <= query.playerId.$lte) {
              result.list.push({ position: result.position, score: currentNode.score, playerId: playerId });
            }
          }
        }
      }
    }
  }
  debug('node.children result [%o]', result);
}
 
function findByPosition(_ref2) {
  var branchFactor = _ref2.branchFactor;
  var node = _ref2.node;
  var nodeScoreRange = _ref2.nodeScoreRange;
  var query = _ref2.query;
  var result = _ref2.result;
 
  debug('');
  debug('query.$limit [%o]', query.$limit);
  debug('nodeScoreRange.beginAt [%o]', nodeScoreRange.beginAt);
  debug('nodeScoreRange.endAt [%o]', nodeScoreRange.endAt);
  debug('query.position.$gte [%o]', query.position.$gte);
  debug('query.position.$lte [%o]', query.position.$lte);
  debug('node.amount [%o]', node.amount);
 
  var _resolveBranchInfo2 = resolveBranchInfo({ nodeScoreRange: nodeScoreRange, branchFactor: branchFactor });
 
  var amountLeafsPerBranch = _resolveBranchInfo2.amountLeafsPerBranch;
  var amountBranches = _resolveBranchInfo2.amountBranches;
 
  for (var i = amountBranches - 1; /*base 0*/i >= 0; i--) {
    debug('index loop [%o]', i);
 
    var currentNode = node.children[i];
 
    Iif (result.list.length > query.$limit) {
      return;
    }
    if (currentNode.amount <= 0) {
      continue;
    }
 
    if (!currentNode.playerIds) {
      var nodeScoreRangeBeginAt = resolveInitScore({ nodeScoreRangeBeginAt: nodeScoreRange.beginAt, indexScore: i, amountLeafsPerBranch: amountLeafsPerBranch });
      var nodeScoreRange$lte = resolveMaxScore({ nodeScoreRangeBeginAt: nodeScoreRangeBeginAt, indexScore: i, amountLeafsPerBranch: amountLeafsPerBranch, amountBranches: amountBranches });
 
      debug('currentNode.amount [%o]', currentNode.amount);
      debug('result.list.length [%o]', result.list.length);
      debug('result.position [%o]', result.position);
      debug('currentNode.amount + result.position [%o]', currentNode.amount + result.position);
 
      var passOverNode = currentNode.amount + result.position > query.position.$lte && currentNode.amount + result.position < query.position.$gte && currentNode.amount + result.list.length < query.$limit;
      debug('passOverNode', passOverNode);
 
      Iif (passOverNode) {
        result.position += currentNode.amount;
        continue;
      }
 
      findByPosition({
        branchFactor: branchFactor,
        node: currentNode,
        nodeScoreRange: {
          beginAt: nodeScoreRangeBeginAt,
          endAt: nodeScoreRange$lte
        },
        query: query,
        result: result
      });
    } else {
      debug('node.children[%o].amount [%o]', i, currentNode.amount);
      for (var playerIndex = 0; playerIndex < currentNode.amount; playerIndex++) {
        result.position += 1;
        debug('position player [%o]', result.position);
        if (result.list.length < query.$limit && result.position >= query.position.$gte && result.position <= query.position.$lte) {
          var playerId = currentNode.playerIds[playerIndex];
          Eif (!query.playerId || playerId >= query.playerId.$gte && playerId <= query.playerId.$lte) {
            result.list.push({ position: result.position, score: currentNode.score, playerId: playerId });
          }
        }
      }
    }
  }
}
 
function setScore(_x) {
  var _again = true;
 
  _function: while (_again) {
    var _ref3 = _x;
    branchFactor = node = score = playerId = nodeScoreRange = _resolveBranchInfo3 = amountLeafsPerBranch = amountBranches = indexScore = i = undefined;
    _again = false;
    var branchFactor = _ref3.branchFactor;
    var node = _ref3.node;
    var score = _ref3.score;
    var playerId = _ref3.playerId;
    var nodeScoreRange = _ref3.nodeScoreRange;
 
    debug('');
    debug('score [%o=%o]', playerId, score);
 
    // node.rangeIndex = [nodeScoreRange.beginAt, nodeScoreRange.endAt]; //debug
    // node.rangeScore = [nodeScoreRange.beginAt + 1, nodeScoreRange.endAt + 1]; //debug
 
    // increases amount on current node before continue going deeper
    node.amount += 1;
 
    debug('nodeScoreRange.beginAt [%o]', nodeScoreRange.beginAt);
    debug('nodeScoreRange.endAt [%o]', nodeScoreRange.endAt);
 
    var _resolveBranchInfo3 = resolveBranchInfo({ nodeScoreRange: nodeScoreRange, branchFactor: branchFactor });
 
    var amountLeafsPerBranch = _resolveBranchInfo3.amountLeafsPerBranch;
    var amountBranches = _resolveBranchInfo3.amountBranches;
 
    var indexScore = resolveIndexScore({ score: score, nodeScoreRangeBeginAt: nodeScoreRange.beginAt, amountLeafsPerBranch: amountLeafsPerBranch, amountBranches: amountBranches });
 
    nodeScoreRange.beginAt = resolveInitScore({ nodeScoreRangeBeginAt: nodeScoreRange.beginAt, indexScore: indexScore, amountLeafsPerBranch: amountLeafsPerBranch });
    nodeScoreRange.endAt = resolveMaxScore({ nodeScoreRangeBeginAt: nodeScoreRange.beginAt, indexScore: indexScore, amountLeafsPerBranch: amountLeafsPerBranch, amountBranches: amountBranches });
 
    // creates children list
    if (!node.children) {
      node.children = [];
      for (var i = 0; i < amountBranches; i++) {
        node.children.push({ amount: 0 });
      }
    }
 
    node = node.children[indexScore];
 
    // in case it is a non-leaf then continues going deeper
    if (nodeScoreRange.beginAt !== nodeScoreRange.endAt) {
      _x = {
        score: score,
        playerId: playerId,
        nodeScoreRange: nodeScoreRange,
        node: node,
        branchFactor: branchFactor
      };
      _again = true;
      continue _function;
    }
 
    /*
      LEAF
     */
 
    if (!node.playerIds) {
      node.playerIds = [];
    }
 
    Eif (! ~node.playerIds.indexOf(playerId)) {
      node.amount += 1;
      node.score = score; //debug
      node.playerIds.push(playerId);
    }
  }
}
 
function resolveBranchInfo(_ref4) {
  var nodeScoreRange = _ref4.nodeScoreRange;
  var branchFactor = _ref4.branchFactor;
 
  var amountLeafsCurrentBranch = nodeScoreRange.endAt - nodeScoreRange.beginAt + 1; /*base 0*/
  var amountBranches = branchFactor;
 
  var amountLeafsPerBranch = amountLeafsCurrentBranch / branchFactor;
  if (amountLeafsPerBranch < 1) {
    amountLeafsPerBranch = 1;
    amountBranches = amountLeafsCurrentBranch;
  }
 
  debug('amountLeafsPerBranch [%o]', amountLeafsPerBranch);
  debug('amountBranches [%o]', amountBranches);
 
  return { amountLeafsPerBranch: amountLeafsPerBranch, amountBranches: amountBranches };
}
 
function resolveIndexScore(_ref5) {
  var score = _ref5.score;
  var nodeScoreRangeBeginAt = _ref5.nodeScoreRangeBeginAt;
  var amountLeafsPerBranch = _ref5.amountLeafsPerBranch;
  var amountBranches = _ref5.amountBranches;
 
  nodeScoreRangeBeginAt = Math.floor(score - nodeScoreRangeBeginAt);
  amountLeafsPerBranch = Math.floor(amountLeafsPerBranch);
 
  var indexScore = undefined;
  if (nodeScoreRangeBeginAt / amountLeafsPerBranch >= amountBranches) {
    indexScore = Math.floor(amountBranches - 1);
  } else {
    indexScore = Math.floor(nodeScoreRangeBeginAt / amountLeafsPerBranch % amountBranches);
  }
 
  debug('indexScore [%o]', indexScore);
  return indexScore;
}
 
function resolveInitScore(_ref6) {
  var nodeScoreRangeBeginAt = _ref6.nodeScoreRangeBeginAt;
  var indexScore = _ref6.indexScore;
  var amountLeafsPerBranch = _ref6.amountLeafsPerBranch;
 
  nodeScoreRangeBeginAt = Math.floor(indexScore * amountLeafsPerBranch) + nodeScoreRangeBeginAt;
  debug('nodeScoreRangeBeginAt [%o]', nodeScoreRangeBeginAt);
  return nodeScoreRangeBeginAt;
}
 
function resolveMaxScore(_ref7) {
  var nodeScoreRangeBeginAt = _ref7.nodeScoreRangeBeginAt;
  var indexScore = _ref7.indexScore;
  var amountLeafsPerBranch = _ref7.amountLeafsPerBranch;
  var amountBranches = _ref7.amountBranches;
 
  var nodeScoreRange$lte = nodeScoreRangeBeginAt + amountLeafsPerBranch - 1; /*base 0*/
  if (indexScore === amountBranches - 1 /*base 0*/) {
    nodeScoreRange$lte = Math.ceil(nodeScoreRange$lte);
  } else {
    nodeScoreRange$lte = Math.floor(nodeScoreRange$lte);
  }
  debug('nodeScoreRange$lte [%o]', nodeScoreRange$lte);
  return nodeScoreRange$lte;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9tYXhjbnVuZXMvRGV2ZWxvcG1lbnQvbWUvcmFua2luZy9zcmMvY29yZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztRQUdnQixXQUFXLEdBQVgsV0FBVztRQTBEWCxjQUFjLEdBQWQsY0FBYztRQWdFZCxRQUFRLEdBQVIsUUFBUTtBQTdIeEIsSUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDOztBQUdyQyxTQUFTLFdBQVcsQ0FBQyxJQUFxRCxFQUFFO01BQXJELFlBQVksR0FBZCxJQUFxRCxDQUFuRCxZQUFZO01BQUUsSUFBSSxHQUFwQixJQUFxRCxDQUFyQyxJQUFJO01BQUUsY0FBYyxHQUFwQyxJQUFxRCxDQUEvQixjQUFjO01BQUUsS0FBSyxHQUEzQyxJQUFxRCxDQUFmLEtBQUs7TUFBRSxNQUFNLEdBQW5ELElBQXFELENBQVIsTUFBTTs7QUFDN0UsT0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ1YsT0FBSyxDQUFDLG1CQUFtQixFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUN6QyxPQUFLLENBQUMsNkJBQTZCLEVBQUUsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQzdELE9BQUssQ0FBQywyQkFBMkIsRUFBRSxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDekQsT0FBSyxDQUFDLHVCQUF1QixFQUFFLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDakQsT0FBSyxDQUFDLHVCQUF1QixFQUFFLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7O0FBRWpELE1BQUksY0FBYyxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRTtBQUM3QyxVQUFNLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUM7QUFDL0IsV0FBTztHQUNSOztBQUVELE1BQUksY0FBYyxDQUFDLEtBQUssR0FBRyxL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QWMsR0FBRyxDQUFDLFdBQUEsQUFBVyxFQUFFO0FBQ2pELHNCQUFrQixHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQztHQUNwRCxNQUFNO0FBQ0wsc0JBQWtCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0dBQ3JEO0FBQ0QsT0FBSyxDQUFDLHlCQUF5QixFQUFFLGtCQUFrQixDQUFDLENBQUM7QUFDckQsU0FBTyxrQkFBa0IsQ0FBQztDQUMzQiIsImZpbGUiOiIvVXNlcnMvbWF4Y251bmVzL0RldmVsb3BtZW50L21lL3Jhbmtpbmcvc3JjL2NvcmUuanMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBkZWJ1ZyA9IHJlcXVpcmUoJy4vZGVidWcnKSgncmFua2luZycpO1xuXG5cbmV4cG9ydCBmdW5jdGlvbiBmaW5kQnlTY29yZSh7IGJyYW5jaEZhY3Rvciwgbm9kZSwgbm9kZVNjb3JlUmFuZ2UsIHF1ZXJ5LCByZXN1bHQgfSkge1xuICBkZWJ1ZygnJyk7XG4gIGRlYnVnKCdxdWVyeS4kbGltaXQgWyVvXScsIHF1ZXJ5LiRsaW1pdCk7XG4gIGRlYnVnKCdub2RlU2NvcmVSYW5nZS5iZWdpbkF0IFslb10nLCBub2RlU2NvcmVSYW5nZS5iZWdpbkF0KTtcbiAgZGVidWcoJ25vZGVTY29yZVJhbmdlLmVuZEF0IFslb10nLCBub2RlU2NvcmVSYW5nZS5lbmRBdCk7XG4gIGRlYnVnKCdxdWVyeS5zY29yZS4kZ3RlIFslb10nLCBxdWVyeS5zY29yZS4kZ3RlKTtcbiAgZGVidWcoJ3F1ZXJ5LnNjb3JlLiRsdGUgWyVvXScsIHF1ZXJ5LnNjb3JlLiRsdGUpO1xuXG4gIGlmIChub2RlU2NvcmVSYW5nZS5iZWdpbkF0ID4gcXVlcnkuc2NvcmUuJGx0ZSkge1xuICAgIHJlc3VsdC5wb3NpdGlvbiArPSBub2RlLmFtb3VudDtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAobm9kZVNjb3JlUmFuZ2UuZW5kQXQgPCBxdWVyeS5zY29yZS4kZ3RlKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgeyBhbW91bnRMZWFmc1BlckJyYW5jaCwgYW1vdW50QnJhbmNoZXMgfSA9IHJlc29sdmVCcmFuY2hJbmZvKHsgbm9kZVNjb3JlUmFuZ2UsIGJyYW5jaEZhY3RvciB9KTtcblxuICBmb3IgKGxldCBpID0gYW1vdW50QnJhbmNoZXMgLSAxOy8qYmFzZSAwKi8gaSA+PSAwOyBpLS0pIHtcbiAgICBkZWJ1ZygnaW5kZXggbG9vcCBbJW9dJywgaSk7XG5cbiAgICBsZXQgY3VycmVudE5vZGUgPSBub2RlLmNoaWxkcmVuW2ldO1xuXG4gICAgaWYgKHJlc3VsdC5saXN0Lmxlbmd0aCA8IHF1ZXJ5LiRsaW1pdCAmJiBjdXJyZW50Tm9kZS5hbW91bnQgPiAwKSB7XG4gICAgICBpZiAoIWN1cnJlbnROb2RlLnBsYXllcklkcykge1xuICAgICAgICBjb25zdCBub2RlU2NvcmVSYW5nZUJlZ2luQXQgPSByZXNvbHZlSW5pdFNjb3JlKHsgbm9kZVNjb3JlUmFuZ2VCZWdpbkF0OiBub2RlU2NvcmVSYW5nZS5iZWdpbkF0LCBpbmRleFNjb3JlOiBpLCBhbW91bnRMZWFmc1BlckJyYW5jaCB9KTtcbiAgICAgICAgY29uc3Qgbm9kZVNjb3JlUmFuZ2UkbHRlID0gcmVzb2x2ZU1heFNjb3JlKHsgbm9kZVNjb3JlUmFuZ2VCZWdpbkF0LCBpbmRleFNjb3JlOiBpLCBhbW91bnRMZWFmc1BlckJyYW5jaCwgYW1vdW50QnJhbmNoZXMgfSk7XG5cbiAgICAgICAgZmluZEJ5U2NvcmUoe1xuICAgICAgICAgIGJyYW5jaEZhY3RvcixcbiAgICAgICAgICBub2RlOiBjdXJyZW50Tm9kZSxcbiAgICAgICAgICBub2RlU2NvcmVSYW5nZToge1xuICAgICAgICAgICAgYmVnaW5BdDogbm9kZVNjb3JlUmFuZ2VCZWdpbkF0LFxuICAgICAgICAgICAgZW5kQXQ6IG5vZGVTY29yZVJhbmdlJGx0ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgcXVlcnksXG4gICAgICAgICAgcmVzdWx0XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZm9yIChsZXQgcGxheWVySW5kZXggPSAwOyBwbGF5ZXJJbmRleCA8IGN1cnJlbnROb2RlLmFtb3VudDsgcGxheWVySW5kZXgrKykge1xuICAgICAgICAgIGRlYnVnKCdub2RlLmNoaWxkcmVuWyVvXS5hbW91bnQgWyVvXScsIGksIGN1cnJlbnROb2RlLmFtb3VudCk7XG4gICAgICAgICAgZGVidWcoJ25vZGUuY2hpbGRyZW5bJW9dLnNjb3JlIFslb10nLCBpLCBjdXJyZW50Tm9kZS5zY29yZSk7XG4gICAgICAgICAgZGVidWcoJ25vZGUuY2hpbGRyZW5bJW9dLnBsYXllcklkcyBbJW9dJywgaSwgY3VycmVudE5vZGUucGxheWVySWRzKTtcbiAgICAgICAgICByZXN1bHQucG9zaXRpb24gKz0gMTtcbiAgICAgICAgICBpZiAocmVzdWx0Lmxpc3QubGVuZ3RoIDwgcXVlcnkuJGxpbWl0ICYmIGN1cnJlbnROb2RlLnNjb3JlID49IHF1ZXJ5LnNjb3JlLiRndGUgJiYgY3VycmVudE5vZGUuc2NvcmUgPD0gcXVlcnkuc2NvcmUuJGx0ZSkge1xuICAgICAgICAgICAgY29uc3QgcGxheWVySWQgPSBjdXJyZW50Tm9kZS5wbGF5ZXJJZHNbcGxheWVySW5kZXhdO1xuICAgICAgICAgICAgaWYgKCFxdWVyeS5wbGF5ZXJJZCB8fCAocGxheWVySWQgPj0gcXVlcnkucGxheWVySWQuJGd0ZSAmJiBwbGF5ZXJJZCA8PSBxdWVyeS5wbGF5ZXJJZC4kbHRlKSkge1xuICAgICAgICAgICAgICByZXN1bHQubGlzdC5wdXNoKHsgcG9zaXRpb246IHJlc3VsdC5wb3NpdGlvbiwgc2NvcmU6IGN1cnJlbnROb2RlLnNjb3JlLCBwbGF5ZXJJZDogcGxheWVySWQgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGRlYnVnKCdub2RlLmNoaWxkcmVuIHJlc3VsdCBbJW9dJywgcmVzdWx0KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZpbmRCeVBvc2l0aW9uKHsgYnJhbmNoRmFjdG9yLCBub2RlLCBub2RlU2NvcmVSYW5nZSwgcXVlcnksIHJlc3VsdCB9KSB7XG4gIGRlYnVnKCcnKTtcbiAgZGVidWcoJ3F1ZXJ5LiRsaW1pdCBbJW9dJywgcXVlcnkuJGxpbWl0KTtcbiAgZGVidWcoJ25vZGVTY29yZVJhbmdlLmJlZ2luQXQgWyVvXScsIG5vZGVTY29yZVJhbmdlLmJlZ2luQXQpO1xuICBkZWJ1Zygnbm9kZVNjb3JlUmFuZ2UuZW5kQXQgWyVvXScsIG5vZGVTY29yZVJhbmdlLmVuZEF0KTtcbiAgZGVidWcoJ3F1ZXJ5LnBvc2l0aW9uLiRndGUgWyVvXScsIHF1ZXJ5LnBvc2l0aW9uLiRndGUpO1xuICBkZWJ1ZygncXVlcnkucG9zaXRpb24uJGx0ZSBbJW9dJywgcXVlcnkucG9zaXRpb24uJGx0ZSk7XG4gIGRlYnVnKCdub2RlLmFtb3VudCBbJW9dJywgbm9kZS5hbW91bnQpO1xuXG4gIGNvbnN0IHsgYW1vdW50TGVhZnNQZXJCcmFuY2gsIGFtb3VudEJyYW5jaGVzIH0gPSByZXNvbHZlQnJhbmNoSW5mbyh7IG5vZGVTY29yZVJhbmdlLCBicmFuY2hGYWN0b3IgfSk7XG5cbiAgZm9yIChsZXQgaSA9IGFtb3VudEJyYW5jaGVzIC0gMTsvKmJhc2UgMCovIGkgPj0gMDsgaS0tKSB7XG4gICAgZGVidWcoJ2luZGV4IGxvb3AgWyVvXScsIGkpO1xuXG4gICAgbGV0IGN1cnJlbnROb2RlID0gbm9kZS5jaGlsZHJlbltpXTtcblxuICAgIGlmIChyZXN1bHQubGlzdC5sZW5ndGggPiBxdWVyeS4kbGltaXQpIHsgcmV0dXJuOyB9XG4gICAgaWYgKGN1cnJlbnROb2RlLmFtb3VudCA8PSAwKSB7IGNvbnRpbnVlOyB9XG5cbiAgICBpZiAoIWN1cnJlbnROb2RlLnBsYXllcklkcykge1xuICAgICAgY29uc3Qgbm9kZVNjb3JlUmFuZ2VCZWdpbkF0ID0gcmVzb2x2ZUluaXRTY29yZSh7IG5vZGVTY29yZVJhbmdlQmVnaW5BdDogbm9kZVNjb3JlUmFuZ2UuYmVnaW5BdCwgaW5kZXhTY29yZTogaSwgYW1vdW50TGVhZnNQZXJCcmFuY2ggfSk7XG4gICAgICBjb25zdCBub2RlU2NvcmVSYW5nZSRsdGUgPSByZXNvbHZlTWF4U2NvcmUoeyBub2RlU2NvcmVSYW5nZUJlZ2luQXQsIGluZGV4U2NvcmU6IGksIGFtb3VudExlYWZzUGVyQnJhbmNoLCBhbW91bnRCcmFuY2hlcyB9KTtcblxuICAgICAgZGVidWcoJ2N1cnJlbnROb2RlLmFtb3VudCBbJW9dJywgY3VycmVudE5vZGUuYW1vdW50KTtcbiAgICAgIGRlYnVnKCdyZXN1bHQubGlzdC5sZW5ndGggWyVvXScsIHJlc3VsdC5saXN0Lmxlbmd0aCk7XG4gICAgICBkZWJ1ZygncmVzdWx0LnBvc2l0aW9uIFslb10nLCByZXN1bHQucG9zaXRpb24pO1xuICAgICAgZGVidWcoJ2N1cnJlbnROb2RlLmFtb3VudCArIHJlc3VsdC5wb3NpdGlvbiBbJW9dJywgY3VycmVudE5vZGUuYW1vdW50ICsgcmVzdWx0LnBvc2l0aW9uKTtcblxuICAgICAgY29uc3QgcGFzc092ZXJOb2RlID0gKGN1cnJlbnROb2RlLmFtb3VudCArIHJlc3VsdC5wb3NpdGlvbikgPiBxdWVyeS5wb3NpdGlvbi4kbHRlICYmXG4gICAgICAgICAoY3VycmVudE5vZGUuYW1vdW50ICsgcmVzdWx0LnBvc2l0aW9uKSA8IHF1ZXJ5LnBvc2l0aW9uLiRndGUgJiZcbiAgICAgICAgIChjdXJyZW50Tm9kZS5hbW91bnQgKyByZXN1bHQubGlzdC5sZW5ndGgpIDwgcXVlcnkuJGxpbWl0O1xuICAgICAgZGVidWcoJ3Bhc3NPdmVyTm9kZScsIHBhc3NPdmVyTm9kZSk7XG5cbiAgICAgIGlmIChwYXNzT3Zlck5vZGUpIHtcbiAgICAgICAgcmVzdWx0LnBvc2l0aW9uICs9IGN1cnJlbnROb2RlLmFtb3VudDtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGZpbmRCeVBvc2l0aW9uKHtcbiAgICAgICAgYnJhbmNoRmFjdG9yLFxuICAgICAgICBub2RlOiBjdXJyZW50Tm9kZSxcbiAgICAgICAgbm9kZVNjb3JlUmFuZ2U6IHtcbiAgICAgICAgICBiZWdpbkF0OiBub2RlU2NvcmVSYW5nZUJlZ2luQXQsXG4gICAgICAgICAgZW5kQXQ6IG5vZGVTY29yZVJhbmdlJGx0ZVxuICAgICAgICB9LFxuICAgICAgICBxdWVyeSxcbiAgICAgICAgcmVzdWx0XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGVidWcoJ25vZGUuY2hpbGRyZW5bJW9dLmFtb3VudCBbJW9dJywgaSwgY3VycmVudE5vZGUuYW1vdW50KTtcbiAgICAgIGZvciAobGV0IHBsYXllckluZGV4ID0gMDsgcGxheWVySW5kZXggPCBjdXJyZW50Tm9kZS5hbW91bnQ7IHBsYXllckluZGV4KyspIHtcbiAgICAgICAgcmVzdWx0LnBvc2l0aW9uICs9IDE7XG4gICAgICAgIGRlYnVnKCdwb3NpdGlvbiBwbGF5ZXIgWyVvXScsIHJlc3VsdC5wb3NpdGlvbik7XG4gICAgICAgIGlmIChyZXN1bHQubGlzdC5sZW5ndGggPCBxdWVyeS4kbGltaXQgJiYgcmVzdWx0LnBvc2l0aW9uID49IHF1ZXJ5LnBvc2l0aW9uLiRndGUgJiYgcmVzdWx0LnBvc2l0aW9uIDw9IHF1ZXJ5LnBvc2l0aW9uLiRsdGUpIHtcbiAgICAgICAgICBjb25zdCBwbGF5ZXJJZCA9IGN1cnJlbnROb2RlLnBsYXllcklkc1twbGF5ZXJJbmRleF07XG4gICAgICAgICAgaWYgKCFxdWVyeS5wbGF5ZXJJZCB8fCAocGxheWVySWQgPj0gcXVlcnkucGxheWVySWQuJGd0ZSAmJiBwbGF5ZXJJZCA8PSBxdWVyeS5wbGF5ZXJJZC4kbHRlKSkge1xuICAgICAgICAgICAgcmVzdWx0Lmxpc3QucHVzaCh7IHBvc2l0aW9uOiByZXN1bHQucG9zaXRpb24sIHNjb3JlOiBjdXJyZW50Tm9kZS5zY29yZSwgcGxheWVySWQ6IHBsYXllcklkIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0U2NvcmUoeyBicmFuY2hGYWN0b3IsIG5vZGUsIHNjb3JlLCBwbGF5ZXJJZCwgbm9kZVNjb3JlUmFuZ2UgfSkge1xuICBkZWJ1ZygnJyk7XG4gIGRlYnVnKCdzY29yZSBbJW89JW9dJywgcGxheWVySWQsIHNjb3JlKTtcblxuICAvLyBub2RlLnJhbmdlSW5kZXggPSBbbm9kZVNjb3JlUmFuZ2UuYmVnaW5BdCwgbm9kZVNjb3JlUmFuZ2UuZW5kQXRdOyAvL2RlYnVnXG4gIC8vIG5vZGUucmFuZ2VTY29yZSA9IFtub2RlU2NvcmVSYW5nZS5iZWdpbkF0ICsgMSwgbm9kZVNjb3JlUmFuZ2UuZW5kQXQgKyAxXTsgLy9kZWJ1Z1xuXG4gIC8vIGluY3JlYXNlcyBhbW91bnQgb24gY3VycmVudCBub2RlIGJlZm9yZSBjb250aW51ZSBnb2luZyBkZWVwZXJcbiAgbm9kZS5hbW91bnQgKz0gMTtcblxuICBkZWJ1Zygnbm9kZVNjb3JlUmFuZ2UuYmVnaW5BdCBbJW9dJywgbm9kZVNjb3JlUmFuZ2UuYmVnaW5BdCk7XG4gIGRlYnVnKCdub2RlU2NvcmVSYW5nZS5lbmRBdCBbJW9dJywgbm9kZVNjb3JlUmFuZ2UuZW5kQXQpO1xuXG4gIGNvbnN0IHsgYW1vdW50TGVhZnNQZXJCcmFuY2gsIGFtb3VudEJyYW5jaGVzIH0gPSByZXNvbHZlQnJhbmNoSW5mbyh7IG5vZGVTY29yZVJhbmdlLCBicmFuY2hGYWN0b3IgfSk7XG4gIGNvbnN0IGluZGV4U2NvcmUgPSByZXNvbHZlSW5kZXhTY29yZSh7IHNjb3JlLCBub2RlU2NvcmVSYW5nZUJlZ2luQXQ6IG5vZGVTY29yZVJhbmdlLmJlZ2luQXQsIGFtb3VudExlYWZzUGVyQnJhbmNoLCBhbW91bnRCcmFuY2hlcyB9KTtcblxuICBub2RlU2NvcmVSYW5nZS5iZWdpbkF0ID0gcmVzb2x2ZUluaXRTY29yZSh7IG5vZGVTY29yZVJhbmdlQmVnaW5BdDogbm9kZVNjb3JlUmFuZ2UuYmVnaW5BdCwgaW5kZXhTY29yZSwgYW1vdW50TGVhZnNQZXJCcmFuY2ggfSk7XG4gIG5vZGVTY29yZVJhbmdlLmVuZEF0ID0gcmVzb2x2ZU1heFNjb3JlKHsgbm9kZVNjb3JlUmFuZ2VCZWdpbkF0OiBub2RlU2NvcmVSYW5nZS5iZWdpbkF0LCBpbmRleFNjb3JlLCBhbW91bnRMZWFmc1BlckJyYW5jaCwgYW1vdW50QnJhbmNoZXMgfSk7XG5cbiAgLy8gY3JlYXRlcyBjaGlsZHJlbiBsaXN0XG4gIGlmICghbm9kZS5jaGlsZHJlbikge1xuICAgIG5vZGUuY2hpbGRyZW4gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFtb3VudEJyYW5jaGVzOyBpKyspIHtcbiAgICAgIG5vZGUuY2hpbGRyZW4ucHVzaCh7IGFtb3VudDogMCB9KTtcbiAgICB9XG4gIH1cblxuICBub2RlID0gbm9kZS5jaGlsZHJlbltpbmRleFNjb3JlXTtcblxuICAvLyBpbiBjYXNlIGl0IGlzIGEgbm9uLWxlYWYgdGhlbiBjb250aW51ZXMgZ29pbmcgZGVlcGVyXG4gIGlmIChub2RlU2NvcmVSYW5nZS5iZWdpbkF0ICE9PSBub2RlU2NvcmVSYW5nZS5lbmRBdCkge1xuICAgIHJldHVybiBzZXRTY29yZSh7XG4gICAgICBzY29yZSxcbiAgICAgIHBsYXllcklkLFxuICAgICAgbm9kZVNjb3JlUmFuZ2UsXG4gICAgICBub2RlLFxuICAgICAgYnJhbmNoRmFjdG9yXG4gICAgfSk7XG4gIH1cblxuICAvKlxuICAgIExFQUZcbiAgICovXG5cbiAgaWYgKCFub2RlLnBsYXllcklkcykgeyBub2RlLnBsYXllcklkcyA9IFtdOyB9XG5cbiAgaWYgKCF+bm9kZS5wbGF5ZXJJZHMuaW5kZXhPZihwbGF5ZXJJZCkpIHtcbiAgICBub2RlLmFtb3VudCArPSAxO1xuICAgIG5vZGUuc2NvcmUgPSBzY29yZTsgLy9kZWJ1Z1xuICAgIG5vZGUucGxheWVySWRzLnB1c2gocGxheWVySWQpO1xuICB9XG59XG5cblxuZnVuY3Rpb24gcmVzb2x2ZUJyYW5jaEluZm8gKHsgbm9kZVNjb3JlUmFuZ2UsIGJyYW5jaEZhY3RvciB9KSB7XG4gIGNvbnN0IGFtb3VudExlYWZzQ3VycmVudEJyYW5jaCA9IG5vZGVTY29yZVJhbmdlLmVuZEF0IC0gbm9kZVNjb3JlUmFuZ2UuYmVnaW5BdCArIDE7LypiYXNlIDAqL1xuICBsZXQgYW1vdW50QnJhbmNoZXMgPSBicmFuY2hGYWN0b3I7XG5cbiAgbGV0IGFtb3VudExlYWZzUGVyQnJhbmNoID0gKGFtb3VudExlYWZzQ3VycmVudEJyYW5jaCkgLyBicmFuY2hGYWN0b3I7XG4gIGlmIChhbW91bnRMZWFmc1BlckJyYW5jaCA8IDEpIHtcbiAgICBhbW91bnRMZWFmc1BlckJyYW5jaCA9IDE7XG4gICAgYW1vdW50QnJhbmNoZXMgPSBhbW91bnRMZWFmc0N1cnJlbnRCcmFuY2g7XG4gIH1cblxuICBkZWJ1ZygnYW1vdW50TGVhZnNQZXJCcmFuY2ggWyVvXScsIGFtb3VudExlYWZzUGVyQnJhbmNoKTtcbiAgZGVidWcoJ2Ftb3VudEJyYW5jaGVzIFslb10nLCBhbW91bnRCcmFuY2hlcyk7XG5cbiAgcmV0dXJuIHsgYW1vdW50TGVhZnNQZXJCcmFuY2gsIGFtb3VudEJyYW5jaGVzIH07XG59XG5cblxuZnVuY3Rpb24gcmVzb2x2ZUluZGV4U2NvcmUgKHsgc2NvcmUsIG5vZGVTY29yZVJhbmdlQmVnaW5BdCwgYW1vdW50TGVhZnNQZXJCcmFuY2gsIGFtb3VudEJyYW5jaGVzIH0pIHtcbiAgbm9kZVNjb3JlUmFuZ2VCZWdpbkF0ID0gTWF0aC5mbG9vcihzY29yZSAtIG5vZGVTY29yZVJhbmdlQmVnaW5BdCk7XG4gIGFtb3VudExlYWZzUGVyQnJhbmNoID0gTWF0aC5mbG9vcihhbW91bnRMZWFmc1BlckJyYW5jaCk7XG5cblxuICBsZXQgaW5kZXhTY29yZTtcbiAgaWYgKChub2RlU2NvcmVSYW5nZUJlZ2luQXQgLyBhbW91bnRMZWFmc1BlckJyYW5jaCkgPj0gYW1vdW50QnJhbmNoZXMpIHtcbiAgICBpbmRleFNjb3JlID0gTWF0aC5mbG9vcihhbW91bnRCcmFuY2hlcyAtIDEpO1xuICB9IGVsc2Uge1xuICAgIGluZGV4U2NvcmUgPSBNYXRoLmZsb29yKG5vZGVTY29yZVJhbmdlQmVnaW5BdCAvIGFtb3VudExlYWZzUGVyQnJhbmNoICUgYW1vdW50QnJhbmNoZXMpO1xuICB9XG5cbiAgZGVidWcoJ2luZGV4U2NvcmUgWyVvXScsIGluZGV4U2NvcmUpO1xuICByZXR1cm4gaW5kZXhTY29yZTtcbn1cblxuXG5mdW5jdGlvbiByZXNvbHZlSW5pdFNjb3JlICh7IG5vZGVTY29yZVJhbmdlQmVnaW5BdCwgaW5kZXhTY29yZSwgYW1vdW50TGVhZnNQZXJCcmFuY2ggfSkge1xuICBub2RlU2NvcmVSYW5nZUJlZ2luQXQgPSBNYXRoLmZsb29yKGluZGV4U2NvcmUgKiBhbW91bnRMZWFmc1BlckJyYW5jaCkgKyBub2RlU2NvcmVSYW5nZUJlZ2luQXQ7XG4gIGRlYnVnKCdub2RlU2NvcmVSYW5nZUJlZ2luQXQgWyVvXScsIG5vZGVTY29yZVJhbmdlQmVnaW5BdCk7XG4gIHJldHVybiBub2RlU2NvcmVSYW5nZUJlZ2luQXQ7XG59XG5cblxuZnVuY3Rpb24gcmVzb2x2ZU1heFNjb3JlICh7IG5vZGVTY29yZVJhbmdlQmVnaW5BdCwgaW5kZXhTY29yZSwgYW1vdW50TGVhZnNQZXJCcmFuY2gsIGFtb3VudEJyYW5jaGVzIH0pIHtcbiAgbGV0IG5vZGVTY29yZVJhbmdlJGx0ZSA9IG5vZGVTY29yZVJhbmdlQmVnaW5BdCArIGFtb3VudExlYWZzUGVyQnJhbmNoIC0gMTsvKmJhc2UgMCovXG4gIGlmIChpbmRleFNjb3JlID09PSAoYW1vdW50QnJhbmNoZXMgLSAxLypiYXNlIDAqLykpIHtcbiAgICBub2RlU2NvcmVSYW5nZSRsdGUgPSBNYXRoLmNlaWwobm9kZVNjb3JlUmFuZ2UkbHRlKTtcbiAgfSBlbHNlIHtcbiAgICBub2RlU2NvcmVSYW5nZSRsdGUgPSBNYXRoLmZsb29yKG5vZGVTY29yZVJhbmdlJGx0ZSk7XG4gIH1cbiAgZGVidWcoJ25vZGVTY29yZVJhbmdlJGx0ZSBbJW9dJywgbm9kZVNjb3JlUmFuZ2UkbHRlKTtcbiAgcmV0dXJuIG5vZGVTY29yZVJhbmdlJGx0ZTtcbn1cbiJdfQ==