react-planner-viewer
Version:
react-planner-viewer is a React Component for view plans builded with react-planner in 2D mode
268 lines (228 loc) • 26.1 kB
JavaScript
;
/**
* UTILS
*/
function sub(v1, v2) {
return [v1[0] - v2[0], v1[1] - v2[1]];
}
function mod(n, m) {
return (n % m + m) % m;
}
/**
* CYCLES
*/
function compute_ev_mapping(EV) {
var ev_mapping = EV.map(function (ev) {
return {
ev: ev,
color: 0,
direction: -1
};
});
return ev_mapping;
}
function compute_angle(P, V) {
var point = sub(V, P);
var angle = Math.atan2(point[1], point[0]);
return angle;
}
function compute_incidences(V, EV) {
var incidences = V.map(function (vertex, i) {
var incidence = [];
EV.forEach(function (edge, j) {
var endpoint;
var position;
if (edge[0] === i) {
endpoint = edge[1];
position = 1;
}
if (edge[1] === i) {
endpoint = edge[0];
position = 0;
}
endpoint !== undefined && incidence.push({
index: j,
endpoint: endpoint,
angle: compute_angle(vertex, V[endpoint]),
edge: edge,
position: position
});
});
incidence.sort(function (i1, i2) {
return i2.angle - i1.angle;
});
return incidence;
});
return incidences;
}
function get_starting_edge(incidences, ev_mapping) {
var e;
var position;
var direction;
for (e = 0; e < ev_mapping.length; e += 1) {
if (ev_mapping[e].color < 2) {
direction = -1 * ev_mapping[e].direction;
color(ev_mapping, e, direction);
return {
edge: e,
direction: direction,
position: direction === -1 ? 0 : 1
};
}
}
}
function get_next_edge(incidences, edge, position, EV) {
var items = incidences[EV[edge][position]];
//console.log(items, incidences, EV, edge, position);
var n_items = items.length;
var item;
var out;
var j;
for (j = 0; j < n_items; j += 1) {
item = items[j];
if (item.index === edge) {
out = items[mod(j + 1, items.length)];
return {
edge: out.index,
vertex: out.endpoint,
position: out.position,
direction: out.position ? 1 : -1
};
}
}
}
function color(ev_mapping, index, direction) {
ev_mapping[index].color += 1;
ev_mapping[index].direction = direction;
}
function find_cycles(V, EV) {
var ev_mapping = compute_ev_mapping(EV);
var incidences = compute_incidences(V, EV);
var V_cycles = [];
var E_cycles = [];
var dir_E_cycles = [];
var V_cycle;
var E_cycle;
var dir_E_cycle;
var next;
var counter = 0;
var start = get_starting_edge(incidences, ev_mapping);
while (start !== undefined) {
V_cycle = [EV[start.edge][mod(start.position + 1, 2)], EV[start.edge][start.position]];
E_cycle = [start.edge];
dir_E_cycle = [start.direction];
next = get_next_edge(incidences, start.edge, start.position, EV);
while (next.edge !== start.edge) {
V_cycle.push(next.vertex);
E_cycle.push(next.edge);
dir_E_cycle.push(next.direction);
color(ev_mapping, next.edge, next.direction);
next = get_next_edge(incidences, next.edge, next.position, EV);
}
E_cycles.push(E_cycle);
V_cycles.push(V_cycle);
dir_E_cycles.push(dir_E_cycle);
//console.log('############## CYCLE ', ++counter)
//console.log('EDGES:', E_cycle)
//console.log('VERTICES:', V_cycle)
//console.log('START', 'edge:', start.edge, 'position:', start.position)
//console.log('COUNTER:', ev_mapping.map(e => e.color), ev_mapping.map(e => e.color).reduce((a, b) => a + b));
//console.log('\n')
start = get_starting_edge(incidences, ev_mapping);
}
return {
v_cycles: V_cycles,
e_cycles: E_cycles,
dir_e_cycles: dir_E_cycles,
ev_mapping: ev_mapping
};
}
function find_short_cycles_indexes(v_cycles, e_cycles) {
var indexes = [];
var e_cycle;
var v_cycle;
var i;
for (i = 0; i < e_cycles.length; i += 1) {
e_cycle = e_cycles[i];
v_cycle = v_cycles[i];
if (e_cycle.length < 3 || v_cycle[0] !== v_cycle[v_cycle.length - 1]) {
indexes.push(i);
}
}
return indexes;
}
function find_inner_cycles(V, EV) {
var cycles = find_cycles(V, EV);
var v_cycles = cycles.v_cycles;
var e_cycles = cycles.e_cycles;
var short_cycles_indexes = find_short_cycles_indexes(v_cycles, e_cycles);
short_cycles_indexes.forEach(function (indx) {
v_cycles.splice(indx, 1);
e_cycles.splice(indx, 1);
});
var dir_e_cycles = cycles.dir_e_cycles;
var rooms_values = cycles.e_cycles.map(function (cycle, i) {
return cycle.map(function (edge, j) {
var v1;
var v2;
var dir = dir_e_cycles[i][j] > 0;
if (dir > 0) {
v1 = EV[edge][0];
v2 = EV[edge][1];
} else {
v1 = EV[edge][1];
v2 = EV[edge][0];
}
return (V[v2][0] - V[v1][0]) * (V[v2][1] + V[v1][1]);
});
});
var rooms_sums = rooms_values.map(function (room) {
return room.reduce(function (a, b) {
return a + b;
});
});
var positive_count = rooms_sums.filter(function (sum) {
return sum > 0;
}).length;
var negative_count = rooms_sums.length - positive_count;
var rm_neg = positive_count >= negative_count ? 1 : -1;
return {
v_cycles: cycles.v_cycles.filter(function (v, i) {
return rm_neg * rooms_sums[i] > 0;
}),
e_cycles: cycles.e_cycles.filter(function (v, i) {
return rm_neg * rooms_sums[i] > 0;
}),
ev_mapping: cycles.ev_mapping
};
}
// export default find_inner_cycles;
module.exports = find_inner_cycles;
/**
* DATA
*/
// var V = [[0.5774, 1.0], [1.0, 1.0], [1.1547, 0.0], [1.0, 0.0], [0.0, 0.0], [0.0, 0.732], [1.0, 0.1547], [0.732, 0.0], [1.0491, 0.183], [-0.317, 0.549], [1.0, 0.268], [0.183, -0.3169], [0.5491, 1.049], [0.4642, 1.0], [0.0, -0.4226], [0.0, 1.0]]
// var EV = [[0, 1], [2, 3], [5, 4], [7, 6], [2, 8], [3, 6], [4, 9], [0, 10], [9, 5], [8, 10], [7, 11], [12, 13], [6, 8], [6, 10], [4, 7], [4, 11], [4, 14], [5, 15], [11, 14], [0, 12], [13, 15], [0, 13], [1, 10], [3, 7], [5, 13]]
// var V = [[0,0],[10,0],[10,10],[0,10], [100,100],[110,100],[110,110],[100,110], [5,0], [5,10]]
// var V = [[0,0.5],[12,-0.7],[14,14],[-2,10], [103,106],[117,98],[96,112],[104,109], [5.5,0.8], [4.8,10.5]]
// var EV = [[3,9],[9,2],[2,1],[1,8],[8,0],[0,3],[8,9]] // IT WORKS
// var EV = [[3,9],[9,2],[2,1],[1,8],[8,0],[0,3],[8,9], [5,6], [6,7], [2,5]] // IT DOESN'T WORK
// var EV = [[3,2],[2,1],[1,0],[0,3]] // IT WORKS
// var EV = [[2,3],[1,2],[0,1],[3,0]] // IT WORKS
// var EV = [[2,3],[1,2],[0,1],[3,0],[6,7],[5,6],[4,5],[7,4]] // IT WORKS
// var EV = [[3,2],[2,1],[1,0],[0,3],[7,6],[6,5],[5,4],[4,7]] // IT WORKS
// var V = [[2,5],[5,6],[10,6.8],[23,8],[9.6,11.3],[20,15],[25,16],[29,18],[30,22],[4,11],[6,10],[24,25],[18,20],[27,7]]
// var EV = [[0,1],[10,0],[9,10],[9,1],[1,2],[4,2],[3,13],[2,3],[4,5],[5,6],[6,7],[12,5],[12,11],[11,6],[11,8],[7,8],[9,4]]
/**
* MAIN
*/
// var cycles_data = find_inner_cycles(V, EV)
// console.log('############## OUTPUT')
// console.log('EDGES:')
// console.log(cycles_data.e_cycles)
// console.log('\n')
// console.log('VERTICES:')
// console.log(cycles_data.v_cycles)
// console.log('\n')
// console.log(cycles_data.ev_mapping.every(m => m.color === 2))
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9ncmFwaC1jeWNsZXMuanMiXSwibmFtZXMiOlsic3ViIiwidjEiLCJ2MiIsIm1vZCIsIm4iLCJtIiwiY29tcHV0ZV9ldl9tYXBwaW5nIiwiRVYiLCJldl9tYXBwaW5nIiwibWFwIiwiZXYiLCJjb2xvciIsImRpcmVjdGlvbiIsImNvbXB1dGVfYW5nbGUiLCJQIiwiViIsInBvaW50IiwiYW5nbGUiLCJNYXRoIiwiYXRhbjIiLCJjb21wdXRlX2luY2lkZW5jZXMiLCJpbmNpZGVuY2VzIiwidmVydGV4IiwiaSIsImluY2lkZW5jZSIsImZvckVhY2giLCJlZGdlIiwiaiIsImVuZHBvaW50IiwicG9zaXRpb24iLCJ1bmRlZmluZWQiLCJwdXNoIiwiaW5kZXgiLCJzb3J0IiwiaTEiLCJpMiIsImdldF9zdGFydGluZ19lZGdlIiwiZSIsImxlbmd0aCIsImdldF9uZXh0X2VkZ2UiLCJpdGVtcyIsIm5faXRlbXMiLCJpdGVtIiwib3V0IiwiZmluZF9jeWNsZXMiLCJWX2N5Y2xlcyIsIkVfY3ljbGVzIiwiZGlyX0VfY3ljbGVzIiwiVl9jeWNsZSIsIkVfY3ljbGUiLCJkaXJfRV9jeWNsZSIsIm5leHQiLCJjb3VudGVyIiwic3RhcnQiLCJ2X2N5Y2xlcyIsImVfY3ljbGVzIiwiZGlyX2VfY3ljbGVzIiwiZmluZF9zaG9ydF9jeWNsZXNfaW5kZXhlcyIsImluZGV4ZXMiLCJlX2N5Y2xlIiwidl9jeWNsZSIsImZpbmRfaW5uZXJfY3ljbGVzIiwiY3ljbGVzIiwic2hvcnRfY3ljbGVzX2luZGV4ZXMiLCJzcGxpY2UiLCJpbmR4Iiwicm9vbXNfdmFsdWVzIiwiY3ljbGUiLCJkaXIiLCJyb29tc19zdW1zIiwicm9vbSIsInJlZHVjZSIsImEiLCJiIiwicG9zaXRpdmVfY291bnQiLCJmaWx0ZXIiLCJzdW0iLCJuZWdhdGl2ZV9jb3VudCIsInJtX25lZyIsInYiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBOzs7O0FBSUEsU0FB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QUFpQkwsV0FBV00sTUFBWCxDQUFrQjtBQUFBLFdBQU9DLE1BQU0sQ0FBYjtBQUFBLEdBQWxCLEVBQWtDdEMsTUFBdkQ7QUFDQSxNQUFJdUMsaUJBQWlCUixXQUFXL0IsTUFBWCxHQUFvQm9DLGNBQXpDOztBQUVBLE1BQUlJLFNBQVVKLGtCQUFrQkcsY0FBbEIsR0FBbUMsQ0FBbkMsR0FBdUMsQ0FBQyxDQUF0RDs7QUFFQSxTQUFPO0FBQ0x2QixjQUFVUSxPQUFPUixRQUFQLENBQWdCcUIsTUFBaEIsQ0FBdUIsVUFBQ0ksQ0FBRCxFQUFJeEQsQ0FBSjtBQUFBLGFBQVd1RCxTQUFTVCxXQUFXOUMsQ0FBWCxDQUFWLEdBQTJCLENBQXJDO0FBQUEsS0FBdkIsQ0FETDtBQUVMZ0MsY0FBVU8sT0FBT1AsUUFBUCxDQUFnQm9CLE1BQWhCLENBQXVCLFVBQUNJLENBQUQsRUFBSXhELENBQUo7QUFBQSxhQUFXdUQsU0FBU1QsV0FBVzlDLENBQVgsQ0FBVixHQUEyQixDQUFyQztBQUFBLEtBQXZCLENBRkw7QUFHTGYsZ0JBQVlzRCxPQUFPdEQ7QUFIZCxHQUFQO0FBS0Q7O0FBRUQ7QUFDQXdFLE9BQU9DLE9BQVAsR0FBaUJwQixpQkFBakI7O0FBRUE7Ozs7QUFJQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJncmFwaC1jeWNsZXMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFVUSUxTXG4gKi9cblxuZnVuY3Rpb24gc3ViICh2MSwgdjIpIHtcbiAgcmV0dXJuIFt2MVswXSAtIHYyWzBdLCB2MVsxXSAtIHYyWzFdXVxufVxuXG5mdW5jdGlvbiBtb2QgKG4sIG0pIHtcbiAgcmV0dXJuICgobiAlIG0pICsgbSkgJSBtXG59XG5cbi8qKlxuICogQ1lDTEVTXG4gKi9cblxuZnVuY3Rpb24gY29tcHV0ZV9ldl9tYXBwaW5nIChFVikge1xuICB2YXIgZXZfbWFwcGluZyA9IEVWLm1hcChmdW5jdGlvbiAoZXYpIHtcbiAgICByZXR1cm4ge1xuICAgICAgZXY6IGV2LFxuICAgICAgY29sb3I6IDAsXG4gICAgICBkaXJlY3Rpb246IC0xXG4gICAgfVxuICB9KVxuXG4gIHJldHVybiBldl9tYXBwaW5nXG59XG5cbmZ1bmN0aW9uIGNvbXB1dGVfYW5nbGUgKFAsIFYpIHtcbiAgdmFyIHBvaW50ID0gc3ViKFYsIFApXG4gIHZhciBhbmdsZSA9IE1hdGguYXRhbjIocG9pbnRbMV0sIHBvaW50WzBdKVxuICByZXR1cm4gYW5nbGVcbn1cblxuZnVuY3Rpb24gY29tcHV0ZV9pbmNpZGVuY2VzIChWLCBFVikge1xuICB2YXIgaW5jaWRlbmNlcyA9IFYubWFwKGZ1bmN0aW9uICh2ZXJ0ZXgsIGkpIHtcbiAgICB2YXIgaW5jaWRlbmNlID0gW11cbiAgICBFVi5mb3JFYWNoKGZ1bmN0aW9uIChlZGdlLCBqKSB7XG4gICAgICB2YXIgZW5kcG9pbnRcbiAgICAgIHZhciBwb3NpdGlvblxuXG4gICAgICBpZiAoZWRnZVswXSA9PT0gaSkge1xuICAgICAgICBlbmRwb2ludCA9IGVkZ2VbMV1cbiAgICAgICAgcG9zaXRpb24gPSAxXG4gICAgICB9XG5cbiAgICAgIGlmIChlZGdlWzFdID09PSBpKSB7XG4gICAgICAgIGVuZHBvaW50ID0gZWRnZVswXVxuICAgICAgICBwb3NpdGlvbiA9IDBcbiAgICAgIH1cblxuICAgICAgZW5kcG9pbnQgIT09IHVuZGVmaW5lZCAmJiBpbmNpZGVuY2UucHVzaCh7XG4gICAgICAgIGluZGV4OiBqLFxuICAgICAgICBlbmRwb2ludDogZW5kcG9pbnQsXG4gICAgICAgIGFuZ2xlOiBjb21wdXRlX2FuZ2xlKHZlcnRleCwgVltlbmRwb2ludF0pLFxuICAgICAgICBlZGdlOiBlZGdlLFxuICAgICAgICBwb3NpdGlvbjogcG9zaXRpb25cbiAgICAgIH0pXG4gICAgfSlcblxuICAgIGluY2lkZW5jZS5zb3J0KGZ1bmN0aW9uIChpMSwgaTIpIHtcbiAgICAgIHJldHVybiBpMi5hbmdsZSAtIGkxLmFuZ2xlXG4gICAgfSlcblxuICAgIHJldHVybiBpbmNpZGVuY2VcbiAgfSlcblxuICByZXR1cm4gaW5jaWRlbmNlc1xufVxuXG5mdW5jdGlvbiBnZXRfc3RhcnRpbmdfZWRnZSAoaW5jaWRlbmNlcywgZXZfbWFwcGluZykge1xuICB2YXIgZVxuICB2YXIgcG9zaXRpb25cbiAgdmFyIGRpcmVjdGlvblxuICBmb3IgKGUgPSAwOyBlIDwgZXZfbWFwcGluZy5sZW5ndGg7IGUgKz0gMSkge1xuICAgIGlmIChldl9tYXBwaW5nW2VdLmNvbG9yIDwgMikge1xuICAgICAgZGlyZWN0aW9uID0gLTEgKiBldl9tYXBwaW5nW2VdLmRpcmVjdGlvblxuICAgICAgY29sb3IoZXZfbWFwcGluZywgZSwgZGlyZWN0aW9uKVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZWRnZTogZSxcbiAgICAgICAgZGlyZWN0aW9uOiBkaXJlY3Rpb24sXG4gICAgICAgIHBvc2l0aW9uOiBkaXJlY3Rpb24gPT09IC0xID8gMCA6IDFcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gZ2V0X25leHRfZWRnZSAoaW5jaWRlbmNlcywgZWRnZSwgcG9zaXRpb24sIEVWKSB7XG4gIHZhciBpdGVtcyA9IGluY2lkZW5jZXNbRVZbZWRnZV1bcG9zaXRpb25dXVxuICAvL2NvbnNvbGUubG9nKGl0ZW1zLCBpbmNpZGVuY2VzLCBFViwgZWRnZSwgcG9zaXRpb24pO1xuICB2YXIgbl9pdGVtcyA9IGl0ZW1zLmxlbmd0aFxuICB2YXIgaXRlbVxuICB2YXIgb3V0XG4gIHZhciBqXG4gIGZvciAoaiA9IDA7IGogPCBuX2l0ZW1zOyBqICs9IDEpIHtcbiAgICBpdGVtID0gaXRlbXNbal1cbiAgICBpZiAoaXRlbS5pbmRleCA9PT0gZWRnZSkge1xuICAgICAgb3V0ID0gaXRlbXNbbW9kKGogKyAxLCBpdGVtcy5sZW5ndGgpXVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZWRnZTogb3V0LmluZGV4LFxuICAgICAgICB2ZXJ0ZXg6IG91dC5lbmRwb2ludCxcbiAgICAgICAgcG9zaXRpb246IG91dC5wb3NpdGlvbixcbiAgICAgICAgZGlyZWN0aW9uOiBvdXQucG9zaXRpb24gPyAxIDogLTFcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gY29sb3IgKGV2X21hcHBpbmcsIGluZGV4LCBkaXJlY3Rpb24pIHtcbiAgZXZfbWFwcGluZ1tpbmRleF0uY29sb3IgKz0gMVxuICBldl9tYXBwaW5nW2luZGV4XS5kaXJlY3Rpb24gPSBkaXJlY3Rpb25cbn1cblxuZnVuY3Rpb24gZmluZF9jeWNsZXMgKFYsIEVWKSB7XG4gIHZhciBldl9tYXBwaW5nID0gY29tcHV0ZV9ldl9tYXBwaW5nKEVWKVxuICB2YXIgaW5jaWRlbmNlcyA9IGNvbXB1dGVfaW5jaWRlbmNlcyhWLCBFVilcbiAgdmFyIFZfY3ljbGVzID0gW11cbiAgdmFyIEVfY3ljbGVzID0gW11cbiAgdmFyIGRpcl9FX2N5Y2xlcyA9IFtdXG4gIHZhciBWX2N5Y2xlXG4gIHZhciBFX2N5Y2xlXG4gIHZhciBkaXJfRV9jeWNsZVxuICB2YXIgbmV4dFxuICB2YXIgY291bnRlciA9IDBcbiAgdmFyIHN0YXJ0ID0gZ2V0X3N0YXJ0aW5nX2VkZ2UoaW5jaWRlbmNlcywgZXZfbWFwcGluZylcblxuICB3aGlsZSAoc3RhcnQgIT09IHVuZGVmaW5lZCkge1xuICAgIFZfY3ljbGUgPSBbRVZbc3RhcnQuZWRnZV1bbW9kKHN0YXJ0LnBvc2l0aW9uICsgMSwgMildLCBFVltzdGFydC5lZGdlXVtzdGFydC5wb3NpdGlvbl1dXG4gICAgRV9jeWNsZSA9IFtzdGFydC5lZGdlXVxuICAgIGRpcl9FX2N5Y2xlID0gW3N0YXJ0LmRpcmVjdGlvbl1cbiAgICBuZXh0ID0gZ2V0X25leHRfZWRnZShpbmNpZGVuY2VzLCBzdGFydC5lZGdlLCBzdGFydC5wb3NpdGlvbiwgRVYpXG4gICAgd2hpbGUgKG5leHQuZWRnZSAhPT0gc3RhcnQuZWRnZSkge1xuICAgICAgVl9jeWNsZS5wdXNoKG5leHQudmVydGV4KVxuICAgICAgRV9jeWNsZS5wdXNoKG5leHQuZWRnZSlcbiAgICAgIGRpcl9FX2N5Y2xlLnB1c2gobmV4dC5kaXJlY3Rpb24pXG4gICAgICBjb2xvcihldl9tYXBwaW5nLCBuZXh0LmVkZ2UsIG5leHQuZGlyZWN0aW9uKVxuICAgICAgbmV4dCA9IGdldF9uZXh0X2VkZ2UoaW5jaWRlbmNlcywgbmV4dC5lZGdlLCBuZXh0LnBvc2l0aW9uLCBFVilcbiAgICB9XG4gICAgRV9jeWNsZXMucHVzaChFX2N5Y2xlKVxuICAgIFZfY3ljbGVzLnB1c2goVl9jeWNsZSlcbiAgICBkaXJfRV9jeWNsZXMucHVzaChkaXJfRV9jeWNsZSlcblxuICAgIC8vY29uc29sZS5sb2coJyMjIyMjIyMjIyMjIyMjIENZQ0xFICcsICsrY291bnRlcilcbiAgICAvL2NvbnNvbGUubG9nKCdFREdFUzonLCBFX2N5Y2xlKVxuICAgIC8vY29uc29sZS5sb2coJ1ZFUlRJQ0VTOicsIFZfY3ljbGUpXG4gICAgLy9jb25zb2xlLmxvZygnU1RBUlQnLCAnZWRnZTonLCBzdGFydC5lZGdlLCAncG9zaXRpb246Jywgc3RhcnQucG9zaXRpb24pXG4gICAgLy9jb25zb2xlLmxvZygnQ09VTlRFUjonLCBldl9tYXBwaW5nLm1hcChlID0+IGUuY29sb3IpLCBldl9tYXBwaW5nLm1hcChlID0+IGUuY29sb3IpLnJlZHVjZSgoYSwgYikgPT4gYSArIGIpKTtcbiAgICAvL2NvbnNvbGUubG9nKCdcXG4nKVxuXG4gICAgc3RhcnQgPSBnZXRfc3RhcnRpbmdfZWRnZShpbmNpZGVuY2VzLCBldl9tYXBwaW5nKVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICB2X2N5Y2xlczogVl9jeWNsZXMsXG4gICAgZV9jeWNsZXM6IEVfY3ljbGVzLFxuICAgIGRpcl9lX2N5Y2xlczogZGlyX0VfY3ljbGVzLFxuICAgIGV2X21hcHBpbmc6IGV2X21hcHBpbmdcbiAgfVxufVxuXG5mdW5jdGlvbiBmaW5kX3Nob3J0X2N5Y2xlc19pbmRleGVzICh2X2N5Y2xlcywgZV9jeWNsZXMpIHtcbiAgdmFyIGluZGV4ZXMgPSBbXTtcbiAgdmFyIGVfY3ljbGU7XG4gIHZhciB2X2N5Y2xlO1xuICB2YXIgaTtcblxuICBmb3IgKGkgPSAwOyBpIDwgZV9jeWNsZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICBlX2N5Y2xlID0gZV9jeWNsZXNbaV07XG4gICAgdl9jeWNsZSA9IHZfY3ljbGVzW2ldO1xuICAgIGlmICgoZV9jeWNsZS5sZW5ndGggPCAzKSB8fCAodl9jeWNsZVswXSAhPT0gdl9jeWNsZVt2X2N5Y2xlLmxlbmd0aCAtIDFdKSkge1xuICAgICAgaW5kZXhlcy5wdXNoKGkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBpbmRleGVzO1xufVxuXG5mdW5jdGlvbiBmaW5kX2lubmVyX2N5Y2xlcyAoViwgRVYpIHtcbiAgdmFyIGN5Y2xlcyA9IGZpbmRfY3ljbGVzKFYsIEVWKTtcbiAgdmFyIHZfY3ljbGVzID0gY3ljbGVzLnZfY3ljbGVzO1xuICB2YXIgZV9jeWNsZXMgPSBjeWNsZXMuZV9jeWNsZXM7XG4gIHZhciBzaG9ydF9jeWNsZXNfaW5kZXhlcyA9IGZpbmRfc2hvcnRfY3ljbGVzX2luZGV4ZXModl9jeWNsZXMsIGVfY3ljbGVzKTtcbiAgc2hvcnRfY3ljbGVzX2luZGV4ZXMuZm9yRWFjaChpbmR4ID0+IHtcbiAgICB2X2N5Y2xlcy5zcGxpY2UoaW5keCwgMSk7XG4gICAgZV9jeWNsZXMuc3BsaWNlKGluZHgsIDEpO1xuICB9KVxuICB2YXIgZGlyX2VfY3ljbGVzID0gY3ljbGVzLmRpcl9lX2N5Y2xlcztcbiAgdmFyIHJvb21zX3ZhbHVlcyA9IGN5Y2xlcy5lX2N5Y2xlcy5tYXAoKGN5Y2xlLCBpKSA9PiBjeWNsZS5tYXAoZnVuY3Rpb24gKGVkZ2UsIGopIHtcbiAgICB2YXIgdjE7XG4gICAgdmFyIHYyO1xuXG4gICAgdmFyIGRpciA9IGRpcl9lX2N5Y2xlc1tpXVtqXSA+IDBcblxuICAgIGlmIChkaXIgPiAwKSB7XG4gICAgICB2MSA9IEVWW2VkZ2VdWzBdO1xuICAgICAgdjIgPSBFVltlZGdlXVsxXTtcbiAgICB9IGVsc2Uge1xuICAgICAgdjEgPSBFVltlZGdlXVsxXTtcbiAgICAgIHYyID0gRVZbZWRnZV1bMF07XG4gICAgfVxuXG4gICAgcmV0dXJuIChWW3YyXVswXSAgLSBWW3YxXVswXSkgKiAoVlt2Ml1bMV0gKyBWW3YxXVsxXSk7XG4gIH0pKTtcblxuICB2YXIgcm9vbXNfc3VtcyA9IHJvb21zX3ZhbHVlcy5tYXAocm9vbSA9PiByb29tLnJlZHVjZSgoYSwgYikgPT4gYSArIGIpKVxuXG4gIHZhciBwb3NpdGl2ZV9jb3VudCA9IHJvb21zX3N1bXMuZmlsdGVyKHN1bSA9PiBzdW0gPiAwKS5sZW5ndGg7XG4gIHZhciBuZWdhdGl2ZV9jb3VudCA9IHJvb21zX3N1bXMubGVuZ3RoIC0gcG9zaXRpdmVfY291bnQ7XG5cbiAgdmFyIHJtX25lZyA9ICBwb3NpdGl2ZV9jb3VudCA+PSBuZWdhdGl2ZV9jb3VudCA/IDEgOiAtMTtcblxuICByZXR1cm4ge1xuICAgIHZfY3ljbGVzOiBjeWNsZXMudl9jeWNsZXMuZmlsdGVyKCh2LCBpKSA9PiAocm1fbmVnICogcm9vbXNfc3Vtc1tpXSkgPiAwICksXG4gICAgZV9jeWNsZXM6IGN5Y2xlcy5lX2N5Y2xlcy5maWx0ZXIoKHYsIGkpID0+IChybV9uZWcgKiByb29tc19zdW1zW2ldKSA+IDAgKSxcbiAgICBldl9tYXBwaW5nOiBjeWNsZXMuZXZfbWFwcGluZ1xuICB9XG59XG5cbi8vIGV4cG9ydCBkZWZhdWx0IGZpbmRfaW5uZXJfY3ljbGVzO1xubW9kdWxlLmV4cG9ydHMgPSBmaW5kX2lubmVyX2N5Y2xlc1xuXG4vKipcbiogREFUQVxuKi9cblxuLy8gdmFyIFYgPSBbWzAuNTc3NCwgMS4wXSwgWzEuMCwgMS4wXSwgWzEuMTU0NywgMC4wXSwgWzEuMCwgMC4wXSwgWzAuMCwgMC4wXSwgWzAuMCwgMC43MzJdLCBbMS4wLCAwLjE1NDddLCBbMC43MzIsIDAuMF0sIFsxLjA0OTEsIDAuMTgzXSwgWy0wLjMxNywgMC41NDldLCBbMS4wLCAwLjI2OF0sIFswLjE4MywgLTAuMzE2OV0sIFswLjU0OTEsIDEuMDQ5XSwgWzAuNDY0MiwgMS4wXSwgWzAuMCwgLTAuNDIyNl0sIFswLjAsIDEuMF1dXG4vLyB2YXIgRVYgPSBbWzAsIDFdLCBbMiwgM10sIFs1LCA0XSwgWzcsIDZdLCBbMiwgOF0sIFszLCA2XSwgWzQsIDldLCBbMCwgMTBdLCBbOSwgNV0sIFs4LCAxMF0sIFs3LCAxMV0sIFsxMiwgMTNdLCBbNiwgOF0sIFs2LCAxMF0sIFs0LCA3XSwgWzQsIDExXSwgWzQsIDE0XSwgWzUsIDE1XSwgWzExLCAxNF0sIFswLCAxMl0sIFsxMywgMTVdLCBbMCwgMTNdLCBbMSwgMTBdLCBbMywgN10sIFs1LCAxM11dXG5cbi8vIHZhciBWID0gW1swLDBdLFsxMCwwXSxbMTAsMTBdLFswLDEwXSwgWzEwMCwxMDBdLFsxMTAsMTAwXSxbMTEwLDExMF0sWzEwMCwxMTBdLCBbNSwwXSwgWzUsMTBdXVxuLy8gdmFyIFYgPSBbWzAsMC41XSxbMTIsLTAuN10sWzE0LDE0XSxbLTIsMTBdLCBbMTAzLDEwNl0sWzExNyw5OF0sWzk2LDExMl0sWzEwNCwxMDldLCBbNS41LDAuOF0sIFs0LjgsMTAuNV1dXG4vLyB2YXIgRVYgPSBbWzMsOV0sWzksMl0sWzIsMV0sWzEsOF0sWzgsMF0sWzAsM10sWzgsOV1dIC8vIElUIFdPUktTXG4vLyB2YXIgRVYgPSBbWzMsOV0sWzksMl0sWzIsMV0sWzEsOF0sWzgsMF0sWzAsM10sWzgsOV0sIFs1LDZdLCBbNiw3XSwgWzIsNV1dIC8vIElUIERPRVNOJ1QgV09SS1xuLy8gdmFyIEVWID0gW1szLDJdLFsyLDFdLFsxLDBdLFswLDNdXSAvLyBJVCBXT1JLU1xuLy8gdmFyIEVWID0gW1syLDNdLFsxLDJdLFswLDFdLFszLDBdXSAvLyBJVCBXT1JLU1xuLy8gdmFyIEVWID0gW1syLDNdLFsxLDJdLFswLDFdLFszLDBdLFs2LDddLFs1LDZdLFs0LDVdLFs3LDRdXSAvLyBJVCBXT1JLU1xuLy8gdmFyIEVWID0gW1szLDJdLFsyLDFdLFsxLDBdLFswLDNdLFs3LDZdLFs2LDVdLFs1LDRdLFs0LDddXSAvLyBJVCBXT1JLU1xuXG4vLyB2YXIgViA9IFtbMiw1XSxbNSw2XSxbMTAsNi44XSxbMjMsOF0sWzkuNiwxMS4zXSxbMjAsMTVdLFsyNSwxNl0sWzI5LDE4XSxbMzAsMjJdLFs0LDExXSxbNiwxMF0sWzI0LDI1XSxbMTgsMjBdLFsyNyw3XV1cbi8vIHZhciBFViA9IFtbMCwxXSxbMTAsMF0sWzksMTBdLFs5LDFdLFsxLDJdLFs0LDJdLFszLDEzXSxbMiwzXSxbNCw1XSxbNSw2XSxbNiw3XSxbMTIsNV0sWzEyLDExXSxbMTEsNl0sWzExLDhdLFs3LDhdLFs5LDRdXVxuXG4vKipcbiogTUFJTlxuKi9cblxuLy8gdmFyIGN5Y2xlc19kYXRhID0gZmluZF9pbm5lcl9jeWNsZXMoViwgRVYpXG4vLyBjb25zb2xlLmxvZygnIyMjIyMjIyMjIyMjIyMgT1VUUFVUJylcbi8vIGNvbnNvbGUubG9nKCdFREdFUzonKVxuLy8gY29uc29sZS5sb2coY3ljbGVzX2RhdGEuZV9jeWNsZXMpXG4vLyBjb25zb2xlLmxvZygnXFxuJylcbi8vIGNvbnNvbGUubG9nKCdWRVJUSUNFUzonKVxuLy8gY29uc29sZS5sb2coY3ljbGVzX2RhdGEudl9jeWNsZXMpXG4vLyBjb25zb2xlLmxvZygnXFxuJylcbi8vIGNvbnNvbGUubG9nKGN5Y2xlc19kYXRhLmV2X21hcHBpbmcuZXZlcnkobSA9PiBtLmNvbG9yID09PSAyKSlcblxuIl19