astx
Version:
super powerful structural search and replace for JavaScript and TypeScript to automate your refactoring
287 lines (252 loc) • 29.4 kB
JavaScript
import { mapValues } from 'lodash-es'
import compileMatcher, { mergeCaptures } from './compileMatcher/index.mjs'
import ensureArray from './util/ensureArray.mjs'
import forEachNode from './util/forEachNode.mjs'
export function convertWithCaptures(matches) {
return mergeCaptures(
...ensureArray(matches).map(
({ pathCaptures, arrayPathCaptures, stringCaptures }) => ({
captures: pathCaptures,
arrayCaptures: arrayPathCaptures,
stringCaptures,
})
)
)
}
export function createMatch(paths, result) {
var _paths$
if (!result) {
throw new Error('result must be defined')
}
const { captures, arrayCaptures, stringCaptures } = result
const match = Array.isArray(paths)
? {
type: 'nodes',
node:
(_paths$ = paths[0]) === null || _paths$ === void 0
? void 0
: _paths$.node,
path: paths[0],
nodes: paths.map((p) => p.node),
paths,
}
: {
type: 'node',
node: paths.node,
path: paths,
nodes: [paths.node],
paths: [paths],
}
if (captures) {
match.pathCaptures = captures
match.captures = mapValues(captures, (path) => path.node)
}
if (arrayCaptures) {
match.arrayPathCaptures = arrayCaptures
match.arrayCaptures = mapValues(arrayCaptures, (paths) =>
paths.map((path) => path.node)
)
}
if (stringCaptures) match.stringCaptures = stringCaptures
return match
}
export default function find(paths, pattern, options) {
const t = options.backend.t
const n = t.namedTypes
if (Array.isArray(pattern) && pattern.length === 1) pattern = pattern[0]
if (Array.isArray(pattern)) {
if (!n.Statement.check(pattern[0].value)) {
throw new Error(`pattern array must be an array of statements`)
}
return findStatements(paths, pattern, options)
}
const matcher = compileMatcher(pattern, options)
const matches = []
const nodeTypes = ensureArray(matcher.nodeType || 'Node')
forEachNode(t, ensureArray(paths), nodeTypes, (path) => {
var _options$matchSoFar
const result = matcher.match(
path,
(_options$matchSoFar =
options === null || options === void 0
? void 0
: options.matchSoFar) !== null && _options$matchSoFar !== void 0
? _options$matchSoFar
: null
)
if (result) matches.push(createMatch(path, result))
})
return matches
}
function findStatements(paths, pattern, options) {
var _options$matchSoFar2
const t = options.backend.t
const matchers = pattern.map((queryElem) =>
compileMatcher(queryElem, options)
)
const firstNonArrayCaptureIndex = matchers.findIndex(
(m) => !m.arrayPlaceholder
)
if (firstNonArrayCaptureIndex < 0) {
throw new Error(
`pattern would match every single array of statements, this is unsupported`
)
}
function remainingElements(matcherIndex) {
let count = 0
for (let i = matcherIndex; i < matchers.length; i++) {
if (!matchers[i].arrayPlaceholder) count++
}
return count
}
function matchElem(paths, sliceStart, arrayIndex, matcherIndex, matchSoFar) {
if (arrayIndex === paths.length || matcherIndex === matchers.length) {
return remainingElements(matcherIndex) === 0
? [matchSoFar || {}, [arrayIndex, arrayIndex]]
: null
}
const matcher = matchers[matcherIndex]
const { arrayPlaceholder } = matcher
if (arrayPlaceholder) {
if (matcherIndex === matchers.length - 1) {
return [
mergeCaptures(matchSoFar, {
arrayCaptures: {
[arrayPlaceholder]: paths.slice(sliceStart),
},
}),
[sliceStart, paths.length],
]
}
return matchElem(
paths,
sliceStart,
arrayIndex,
matcherIndex + 1,
matchSoFar
)
} else {
var _matchers
const origMatchSoFar = matchSoFar
const prevArrayPlaceholder =
(_matchers = matchers[matcherIndex - 1]) === null ||
_matchers === void 0
? void 0
: _matchers.arrayPlaceholder
const end =
prevArrayPlaceholder && matcherIndex !== firstNonArrayCaptureIndex
? paths.length - remainingElements(matcherIndex + 1)
: arrayIndex + 1
for (let i = arrayIndex; i < end; i++) {
matchSoFar = matcher.match(paths[i], origMatchSoFar)
if (!matchSoFar) continue
if (prevArrayPlaceholder) {
matchSoFar = mergeCaptures(matchSoFar, {
arrayCaptures: {
[prevArrayPlaceholder]: paths.slice(sliceStart, i),
},
})
}
const restMatch = matchElem(
paths,
i + 1,
i + 1,
matcherIndex + 1,
matchSoFar
)
if (restMatch) return [restMatch[0], [i, restMatch[1][1]]]
}
}
return null
}
const blocks = []
forEachNode(t, ensureArray(paths), ['Block'], (path) => {
blocks.push(path)
})
blocks.reverse()
const matches = []
const initialMatch =
(_options$matchSoFar2 =
options === null || options === void 0 ? void 0 : options.matchSoFar) !==
null && _options$matchSoFar2 !== void 0
? _options$matchSoFar2
: null
for (const block of blocks) {
const body = block.get('body').filter(() => true)
const end = body.length - remainingElements(firstNonArrayCaptureIndex + 1)
let sliceStart = 0
for (let arrayIndex = 0; arrayIndex < end; arrayIndex++) {
const match = matchElem(
body,
sliceStart,
arrayIndex,
firstNonArrayCaptureIndex,
initialMatch
)
if (match) {
var _result2, _result3, _result4
let result = match[0]
const start = firstNonArrayCaptureIndex > 0 ? 0 : match[1][0]
const [, end] = match[1] // make sure all * captures are present in results
// (if there are more than one adjacent *, all captured paths will be in the
// last one and the rest will be empty)
for (const matcher of matchers) {
var _result, _result$arrayCaptures
const { arrayPlaceholder } = matcher
if (!arrayPlaceholder) continue
if (
!(
(_result = result) !== null &&
_result !== void 0 &&
(_result$arrayCaptures = _result.arrayCaptures) !== null &&
_result$arrayCaptures !== void 0 &&
_result$arrayCaptures[arrayPlaceholder]
)
)
result = mergeCaptures(result, {
arrayCaptures: {
[arrayPlaceholder]: [],
},
})
}
const paths = body.slice(start, end)
const finalMatch = {
type: 'nodes',
path: paths[0],
node: paths[0].node,
paths,
nodes: paths.map((p) => p.node),
}
if (
(_result2 = result) !== null &&
_result2 !== void 0 &&
_result2.captures
) {
finalMatch.pathCaptures = result.captures
finalMatch.captures = mapValues(result.captures, (p) => p.node)
}
if (
(_result3 = result) !== null &&
_result3 !== void 0 &&
_result3.arrayCaptures
) {
finalMatch.arrayPathCaptures = result.arrayCaptures
finalMatch.arrayCaptures = mapValues(result.arrayCaptures, (paths) =>
paths.map((p) => p.node)
)
}
if (
(_result4 = result) !== null &&
_result4 !== void 0 &&
_result4.stringCaptures
) {
finalMatch.stringCaptures = result.stringCaptures
}
matches.push(finalMatch) // prevent overlapping matches
sliceStart = end
arrayIndex = end - 1
}
}
}
return matches
} //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJtYXBWYWx1ZXMiLCJjb21waWxlTWF0Y2hlciIsIm1lcmdlQ2FwdHVyZXMiLCJlbnN1cmVBcnJheSIsImZvckVhY2hOb2RlIiwiY29udmVydFdpdGhDYXB0dXJlcyIsIm1hdGNoZXMiLCJtYXAiLCJwYXRoQ2FwdHVyZXMiLCJhcnJheVBhdGhDYXB0dXJlcyIsInN0cmluZ0NhcHR1cmVzIiwiY2FwdHVyZXMiLCJhcnJheUNhcHR1cmVzIiwiY3JlYXRlTWF0Y2giLCJwYXRocyIsInJlc3VsdCIsIkVycm9yIiwibWF0Y2giLCJBcnJheSIsImlzQXJyYXkiLCJ0eXBlIiwibm9kZSIsInBhdGgiLCJub2RlcyIsInAiLCJmaW5kIiwicGF0dGVybiIsIm9wdGlvbnMiLCJ0IiwiYmFja2VuZCIsIm4iLCJuYW1lZFR5cGVzIiwibGVuZ3RoIiwiU3RhdGVtZW50IiwiY2hlY2siLCJ2YWx1ZSIsImZpbmRTdGF0ZW1lbnRzIiwibWF0Y2hlciIsIm5vZGVUeXBlcyIsIm5vZGVUeXBlIiwibWF0Y2hTb0ZhciIsInB1c2giLCJtYXRjaGVycyIsInF1ZXJ5RWxlbSIsImZpcnN0Tm9uQXJyYXlDYXB0dXJlSW5kZXgiLCJmaW5kSW5kZXgiLCJtIiwiYXJyYXlQbGFjZWhvbGRlciIsInJlbWFpbmluZ0VsZW1lbnRzIiwibWF0Y2hlckluZGV4IiwiY291bnQiLCJpIiwibWF0Y2hFbGVtIiwic2xpY2VTdGFydCIsImFycmF5SW5kZXgiLCJzbGljZSIsIm9yaWdNYXRjaFNvRmFyIiwicHJldkFycmF5UGxhY2Vob2xkZXIiLCJlbmQiLCJyZXN0TWF0Y2giLCJibG9ja3MiLCJyZXZlcnNlIiwiaW5pdGlhbE1hdGNoIiwiYmxvY2siLCJib2R5IiwiZ2V0IiwiZmlsdGVyIiwic3RhcnQiLCJmaW5hbE1hdGNoIl0sInNvdXJjZXMiOlsiLi4vc3JjL2ZpbmQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTm9kZVR5cGUsIE5vZGVQYXRoLCBOb2RlLCBTdGF0ZW1lbnQsIEJsb2NrIH0gZnJvbSAnLi90eXBlcydcbmltcG9ydCB7IG1hcFZhbHVlcyB9IGZyb20gJ2xvZGFzaCdcbmltcG9ydCBjb21waWxlTWF0Y2hlciwge1xuICBDb21waWxlZE1hdGNoZXIsXG4gIE1hdGNoUmVzdWx0LFxuICBtZXJnZUNhcHR1cmVzLFxufSBmcm9tICcuL2NvbXBpbGVNYXRjaGVyJ1xuaW1wb3J0IHsgQmFja2VuZCB9IGZyb20gJy4vYmFja2VuZC9CYWNrZW5kJ1xuaW1wb3J0IGVuc3VyZUFycmF5IGZyb20gJy4vdXRpbC9lbnN1cmVBcnJheSdcbmltcG9ydCBmb3JFYWNoTm9kZSBmcm9tICcuL3V0aWwvZm9yRWFjaE5vZGUnXG5cbmV4cG9ydCB0eXBlIE1hdGNoID0ge1xuICB0eXBlOiAnbm9kZScgfCAnbm9kZXMnXG4gIHBhdGg6IE5vZGVQYXRoXG4gIG5vZGU6IE5vZGVcbiAgcGF0aHM6IE5vZGVQYXRoW11cbiAgbm9kZXM6IE5vZGVbXVxuICBwYXRoQ2FwdHVyZXM/OiBSZWNvcmQ8c3RyaW5nLCBOb2RlUGF0aD5cbiAgY2FwdHVyZXM/OiBSZWNvcmQ8c3RyaW5nLCBOb2RlPlxuICBhcnJheVBhdGhDYXB0dXJlcz86IFJlY29yZDxzdHJpbmcsIE5vZGVQYXRoW10+XG4gIGFycmF5Q2FwdHVyZXM/OiBSZWNvcmQ8c3RyaW5nLCBOb2RlW10+XG4gIHN0cmluZ0NhcHR1cmVzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPlxufVxuXG5leHBvcnQgdHlwZSBGaW5kT3B0aW9ucyA9IHtcbiAgYmFja2VuZDogQmFja2VuZFxuICB3aGVyZT86IHsgW2NhcHR1cmVOYW1lOiBzdHJpbmddOiAocGF0aDogTm9kZVBhdGgpID0+IGJvb2xlYW4gfVxuICBtYXRjaFNvRmFyPzogTWF0Y2hSZXN1bHRcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbnZlcnRXaXRoQ2FwdHVyZXMobWF0Y2hlczogTWF0Y2ggfCBNYXRjaFtdKTogTWF0Y2hSZXN1bHQge1xuICByZXR1cm4gbWVyZ2VDYXB0dXJlcyhcbiAgICAuLi5lbnN1cmVBcnJheShtYXRjaGVzKS5tYXAoXG4gICAgICAoeyBwYXRoQ2FwdHVyZXMsIGFycmF5UGF0aENhcHR1cmVzLCBzdHJpbmdDYXB0dXJlcyB9KTogTWF0Y2hSZXN1bHQgPT4gKHtcbiAgICAgICAgY2FwdHVyZXM6IHBhdGhDYXB0dXJlcyxcbiAgICAgICAgYXJyYXlDYXB0dXJlczogYXJyYXlQYXRoQ2FwdHVyZXMsXG4gICAgICAgIHN0cmluZ0NhcHR1cmVzLFxuICAgICAgfSlcbiAgICApXG4gIClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZU1hdGNoKFxuICBwYXRoczogTm9kZVBhdGggfCBOb2RlUGF0aFtdLFxuICByZXN1bHQ6IE1hdGNoUmVzdWx0XG4pOiBNYXRjaCB7XG4gIGlmICghcmVzdWx0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdyZXN1bHQgbXVzdCBiZSBkZWZpbmVkJylcbiAgfVxuICBjb25zdCB7IGNhcHR1cmVzLCBhcnJheUNhcHR1cmVzLCBzdHJpbmdDYXB0dXJlcyB9ID0gcmVzdWx0XG4gIGNvbnN0IG1hdGNoOiBNYXRjaCA9IEFycmF5LmlzQXJyYXkocGF0aHMpXG4gICAgPyB7XG4gICAgICAgIHR5cGU6ICdub2RlcycsXG4gICAgICAgIG5vZGU6IHBhdGhzWzBdPy5ub2RlLFxuICAgICAgICBwYXRoOiBwYXRoc1swXSxcbiAgICAgICAgbm9kZXM6IHBhdGhzLm1hcCgocCkgPT4gcC5ub2RlKSxcbiAgICAgICAgcGF0aHMsXG4gICAgICB9XG4gICAgOiB7XG4gICAgICAgIHR5cGU6ICdub2RlJyxcbiAgICAgICAgbm9kZTogcGF0aHMubm9kZSxcbiAgICAgICAgcGF0aDogcGF0aHMsXG4gICAgICAgIG5vZGVzOiBbcGF0aHMubm9kZV0sXG4gICAgICAgIHBhdGhzOiBbcGF0aHNdLFxuICAgICAgfVxuICBpZiAoY2FwdHVyZXMpIHtcbiAgICBtYXRjaC5wYXRoQ2FwdHVyZXMgPSBjYXB0dXJlc1xuICAgIG1hdGNoLmNhcHR1cmVzID0gbWFwVmFsdWVzKGNhcHR1cmVzLCAocGF0aDogTm9kZVBhdGgpID0+IHBhdGgubm9kZSlcbiAgfVxuICBpZiAoYXJyYXlDYXB0dXJlcykge1xuICAgIG1hdGNoLmFycmF5UGF0aENhcHR1cmVzID0gYXJyYXlDYXB0dXJlc1xuICAgIG1hdGNoLmFycmF5Q2FwdHVyZXMgPSBtYXBWYWx1ZXMoYXJyYXlDYXB0dXJlcywgKHBhdGhzOiBOb2RlUGF0aFtdKSA9PlxuICAgICAgcGF0aHMubWFwKChwYXRoKSA9PiBwYXRoLm5vZGUpXG4gICAgKVxuICB9XG4gIGlmIChzdHJpbmdDYXB0dXJlcykgbWF0Y2guc3RyaW5nQ2FwdHVyZXMgPSBzdHJpbmdDYXB0dXJlc1xuICByZXR1cm4gbWF0Y2hcbn1cblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gZmluZChcbiAgcGF0aHM6IE5vZGVQYXRoIHwgcmVhZG9ubHkgTm9kZVBhdGhbXSxcbiAgcGF0dGVybjogTm9kZVBhdGggfCByZWFkb25seSBOb2RlUGF0aFtdLFxuICBvcHRpb25zOiBGaW5kT3B0aW9uc1xuKTogTWF0Y2hbXSB7XG4gIGNvbnN0IHQgPSBvcHRpb25zLmJhY2tlbmQudFxuICBjb25zdCBuID0gdC5uYW1lZFR5cGVzXG4gIGlmIChBcnJheS5pc0FycmF5KHBhdHRlcm4pICYmIHBhdHRlcm4ubGVuZ3RoID09PSAxKSBwYXR0ZXJuID0gcGF0dGVyblswXVxuICBpZiAoQXJyYXkuaXNBcnJheShwYXR0ZXJuKSkge1xuICAgIGlmICghbi5TdGF0ZW1lbnQuY2hlY2socGF0dGVyblswXS52YWx1ZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgcGF0dGVybiBhcnJheSBtdXN0IGJlIGFuIGFycmF5IG9mIHN0YXRlbWVudHNgKVxuICAgIH1cbiAgICByZXR1cm4gZmluZFN0YXRlbWVudHMoXG4gICAgICBwYXRocyxcbiAgICAgIHBhdHRlcm4gYXMgTm9kZVBhdGg8U3RhdGVtZW50LCBTdGF0ZW1lbnQ+W10sXG4gICAgICBvcHRpb25zXG4gICAgKVxuICB9XG5cbiAgY29uc3QgbWF0Y2hlciA9IGNvbXBpbGVNYXRjaGVyKHBhdHRlcm4gYXMgTm9kZVBhdGgsIG9wdGlvbnMpXG5cbiAgY29uc3QgbWF0Y2hlczogQXJyYXk8TWF0Y2g+ID0gW11cblxuICBjb25zdCBub2RlVHlwZXM6IHJlYWRvbmx5IE5vZGVUeXBlW10gPSBlbnN1cmVBcnJheShtYXRjaGVyLm5vZGVUeXBlIHx8ICdOb2RlJylcblxuICBmb3JFYWNoTm9kZSh0LCBlbnN1cmVBcnJheShwYXRocyksIG5vZGVUeXBlcywgKHBhdGg6IE5vZGVQYXRoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gbWF0Y2hlci5tYXRjaChwYXRoLCBvcHRpb25zPy5tYXRjaFNvRmFyID8/IG51bGwpXG4gICAgaWYgKHJlc3VsdCkgbWF0Y2hlcy5wdXNoKGNyZWF0ZU1hdGNoKHBhdGgsIHJlc3VsdCkpXG4gIH0pXG5cbiAgcmV0dXJuIG1hdGNoZXNcbn1cblxuZnVuY3Rpb24gZmluZFN0YXRlbWVudHMoXG4gIHBhdGhzOiBOb2RlUGF0aCB8IHJlYWRvbmx5IE5vZGVQYXRoW10sXG4gIHBhdHRlcm46IHJlYWRvbmx5IE5vZGVQYXRoPFN0YXRlbWVudCwgU3RhdGVtZW50PltdLFxuICBvcHRpb25zOiBGaW5kT3B0aW9uc1xuKTogTWF0Y2hbXSB7XG4gIGNvbnN0IHQgPSBvcHRpb25zLmJhY2tlbmQudFxuXG4gIGNvbnN0IG1hdGNoZXJzOiBDb21waWxlZE1hdGNoZXJbXSA9IHBhdHRlcm4ubWFwKChxdWVyeUVsZW0pID0+XG4gICAgY29tcGlsZU1hdGNoZXIocXVlcnlFbGVtLCBvcHRpb25zKVxuICApXG5cbiAgY29uc3QgZmlyc3ROb25BcnJheUNhcHR1cmVJbmRleCA9IG1hdGNoZXJzLmZpbmRJbmRleChcbiAgICAobSkgPT4gIW0uYXJyYXlQbGFjZWhvbGRlclxuICApXG5cbiAgaWYgKGZpcnN0Tm9uQXJyYXlDYXB0dXJlSW5kZXggPCAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYHBhdHRlcm4gd291bGQgbWF0Y2ggZXZlcnkgc2luZ2xlIGFycmF5IG9mIHN0YXRlbWVudHMsIHRoaXMgaXMgdW5zdXBwb3J0ZWRgXG4gICAgKVxuICB9XG5cbiAgZnVuY3Rpb24gcmVtYWluaW5nRWxlbWVudHMobWF0Y2hlckluZGV4OiBudW1iZXIpOiBudW1iZXIge1xuICAgIGxldCBjb3VudCA9IDBcbiAgICBmb3IgKGxldCBpID0gbWF0Y2hlckluZGV4OyBpIDwgbWF0Y2hlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmICghbWF0Y2hlcnNbaV0uYXJyYXlQbGFjZWhvbGRlcikgY291bnQrK1xuICAgIH1cbiAgICByZXR1cm4gY291bnRcbiAgfVxuXG4gIGZ1bmN0aW9uIG1hdGNoRWxlbShcbiAgICBwYXRoczogTm9kZVBhdGg8U3RhdGVtZW50PltdLFxuICAgIHNsaWNlU3RhcnQ6IG51bWJlcixcbiAgICBhcnJheUluZGV4OiBudW1iZXIsXG4gICAgbWF0Y2hlckluZGV4OiBudW1iZXIsXG4gICAgbWF0Y2hTb0ZhcjogTWF0Y2hSZXN1bHRcbiAgKTogW01hdGNoUmVzdWx0LCBbbnVtYmVyLCBudW1iZXJdXSB8IG51bGwge1xuICAgIGlmIChhcnJheUluZGV4ID09PSBwYXRocy5sZW5ndGggfHwgbWF0Y2hlckluZGV4ID09PSBtYXRjaGVycy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiByZW1haW5pbmdFbGVtZW50cyhtYXRjaGVySW5kZXgpID09PSAwXG4gICAgICAgID8gW21hdGNoU29GYXIgfHwge30sIFthcnJheUluZGV4LCBhcnJheUluZGV4XV1cbiAgICAgICAgOiBudWxsXG4gICAgfVxuXG4gICAgY29uc3QgbWF0Y2hlciA9IG1hdGNoZXJzW21hdGNoZXJJbmRleF1cbiAgICBjb25zdCB7IGFycmF5UGxhY2Vob2xkZXIgfSA9IG1hdGNoZXJcbiAgICBpZiAoYXJyYXlQbGFjZWhvbGRlcikge1xuICAgICAgaWYgKG1hdGNoZXJJbmRleCA9PT0gbWF0Y2hlcnMubGVuZ3RoIC0gMSkge1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgIG1lcmdlQ2FwdHVyZXMobWF0Y2hTb0Zhciwge1xuICAgICAgICAgICAgYXJyYXlDYXB0dXJlczoge1xuICAgICAgICAgICAgICBbYXJyYXlQbGFjZWhvbGRlcl06IHBhdGhzLnNsaWNlKHNsaWNlU3RhcnQpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgICBbc2xpY2VTdGFydCwgcGF0aHMubGVuZ3RoXSxcbiAgICAgICAgXVxuICAgICAgfVxuICAgICAgcmV0dXJuIG1hdGNoRWxlbShcbiAgICAgICAgcGF0aHMsXG4gICAgICAgIHNsaWNlU3RhcnQsXG4gICAgICAgIGFycmF5SW5kZXgsXG4gICAgICAgIG1hdGNoZXJJbmRleCArIDEsXG4gICAgICAgIG1hdGNoU29GYXJcbiAgICAgIClcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3Qgb3JpZ01hdGNoU29GYXIgPSBtYXRjaFNvRmFyXG4gICAgICBjb25zdCBwcmV2QXJyYXlQbGFjZWhvbGRlciA9IG1hdGNoZXJzW21hdGNoZXJJbmRleCAtIDFdPy5hcnJheVBsYWNlaG9sZGVyXG4gICAgICBjb25zdCBlbmQgPVxuICAgICAgICBwcmV2QXJyYXlQbGFjZWhvbGRlciAmJiBtYXRjaGVySW5kZXggIT09IGZpcnN0Tm9uQXJyYXlDYXB0dXJlSW5kZXhcbiAgICAgICAgICA/IHBhdGhzLmxlbmd0aCAtIHJlbWFpbmluZ0VsZW1lbnRzKG1hdGNoZXJJbmRleCArIDEpXG4gICAgICAgICAgOiBhcnJheUluZGV4ICsgMVxuICAgICAgZm9yIChsZXQgaSA9IGFycmF5SW5kZXg7IGkgPCBlbmQ7IGkrKykge1xuICAgICAgICBtYXRjaFNvRmFyID0gbWF0Y2hlci5tYXRjaChwYXRoc1tpXSwgb3JpZ01hdGNoU29GYXIpXG4gICAgICAgIGlmICghbWF0Y2hTb0ZhcikgY29udGludWVcbiAgICAgICAgaWYgKHByZXZBcnJheVBsYWNlaG9sZGVyKSB7XG4gICAgICAgICAgbWF0Y2hTb0ZhciA9IG1lcmdlQ2FwdHVyZXMobWF0Y2hTb0Zhciwge1xuICAgICAgICAgICAgYXJyYXlDYXB0dXJlczoge1xuICAgICAgICAgICAgICBbcHJldkFycmF5UGxhY2Vob2xkZXJdOiBwYXRocy5zbGljZShzbGljZVN0YXJ0LCBpKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgICAgICBjb25zdCByZXN0TWF0Y2ggPSBtYXRjaEVsZW0oXG4gICAgICAgICAgcGF0aHMsXG4gICAgICAgICAgaSArIDEsXG4gICAgICAgICAgaSArIDEsXG4gICAgICAgICAgbWF0Y2hlckluZGV4ICsgMSxcbiAgICAgICAgICBtYXRjaFNvRmFyXG4gICAgICAgIClcbiAgICAgICAgaWYgKHJlc3RNYXRjaCkgcmV0dXJuIFtyZXN0TWF0Y2hbMF0sIFtpLCByZXN0TWF0Y2hbMV1bMV1dXVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgY29uc3QgYmxvY2tzOiBOb2RlUGF0aDxCbG9jaz5bXSA9IFtdXG5cbiAgZm9yRWFjaE5vZGUodCwgZW5zdXJlQXJyYXkocGF0aHMpLCBbJ0Jsb2NrJ10sIChwYXRoOiBOb2RlUGF0aCkgPT4ge1xuICAgIGJsb2Nrcy5wdXNoKHBhdGggYXMgTm9kZVBhdGg8QmxvY2s+KVxuICB9KVxuICBibG9ja3MucmV2ZXJzZSgpXG5cbiAgY29uc3QgbWF0Y2hlczogTWF0Y2hbXSA9IFtdXG5cbiAgY29uc3QgaW5pdGlhbE1hdGNoID0gb3B0aW9ucz8ubWF0Y2hTb0ZhciA/PyBudWxsXG5cbiAgZm9yIChjb25zdCBibG9jayBvZiBibG9ja3MpIHtcbiAgICBjb25zdCBib2R5OiBOb2RlUGF0aDxTdGF0ZW1lbnQ+W10gPSBibG9jay5nZXQoJ2JvZHknKS5maWx0ZXIoKCkgPT4gdHJ1ZSlcbiAgICBjb25zdCBlbmQgPSBib2R5Lmxlbmd0aCAtIHJlbWFpbmluZ0VsZW1lbnRzKGZpcnN0Tm9uQXJyYXlDYXB0dXJlSW5kZXggKyAxKVxuICAgIGxldCBzbGljZVN0YXJ0ID0gMFxuICAgIGZvciAobGV0IGFycmF5SW5kZXggPSAwOyBhcnJheUluZGV4IDwgZW5kOyBhcnJheUluZGV4KyspIHtcbiAgICAgIGNvbnN0IG1hdGNoID0gbWF0Y2hFbGVtKFxuICAgICAgICBib2R5LFxuICAgICAgICBzbGljZVN0YXJ0LFxuICAgICAgICBhcnJheUluZGV4LFxuICAgICAgICBmaXJzdE5vbkFycmF5Q2FwdHVyZUluZGV4LFxuICAgICAgICBpbml0aWFsTWF0Y2hcbiAgICAgIClcbiAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICBsZXQgcmVzdWx0ID0gbWF0Y2hbMF1cbiAgICAgICAgY29uc3Qgc3RhcnQgPSBmaXJzdE5vbkFycmF5Q2FwdHVyZUluZGV4ID4gMCA/IDAgOiBtYXRjaFsxXVswXVxuICAgICAgICBjb25zdCBbLCBlbmRdID0gbWF0Y2hbMV1cblxuICAgICAgICAvLyBtYWtlIHN1cmUgYWxsICogY2FwdHVyZXMgYXJlIHByZXNlbnQgaW4gcmVzdWx0c1xuICAgICAgICAvLyAoaWYgdGhlcmUgYXJlIG1vcmUgdGhhbiBvbmUgYWRqYWNlbnQgKiwgYWxsIGNhcHR1cmVkIHBhdGhzIHdpbGwgYmUgaW4gdGhlXG4gICAgICAgIC8vIGxhc3Qgb25lIGFuZCB0aGUgcmVzdCB3aWxsIGJlIGVtcHR5KVxuICAgICAgICBmb3IgKGNvbnN0IG1hdGNoZXIgb2YgbWF0Y2hlcnMpIHtcbiAgICAgICAgICBjb25zdCB7IGFycmF5UGxhY2Vob2xkZXIgfSA9IG1hdGNoZXJcbiAgICAgICAgICBpZiAoIWFycmF5UGxhY2Vob2xkZXIpIGNvbnRpbnVlXG4gICAgICAgICAgaWYgKCFyZXN1bHQ/LmFycmF5Q2FwdHVyZXM/LlthcnJheVBsYWNlaG9sZGVyXSlcbiAgICAgICAgICAgIHJlc3VsdCA9IG1lcmdlQ2FwdHVyZXMocmVzdWx0LCB7XG4gICAgICAgICAgICAgIGFycmF5Q2FwdHVyZXM6IHsgW2FycmF5UGxhY2Vob2xkZXJdOiBbXSB9LFxuICAgICAgICAgICAgfSlcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHBhdGhzID0gYm9keS5zbGljZShzdGFydCwgZW5kKVxuXG4gICAgICAgIGNvbnN0IGZpbmFsTWF0Y2g6IE1hdGNoID0ge1xuICAgICAgICAgIHR5cGU6ICdub2RlcycsXG4gICAgICAgICAgcGF0aDogcGF0aHNbMF0sXG4gICAgICAgICAgbm9kZTogcGF0aHNbMF0ubm9kZSxcbiAgICAgICAgICBwYXRocyxcbiAgICAgICAgICBub2RlczogcGF0aHMubWFwKChwKSA9PiBwLm5vZGUpLFxuICAgICAgICB9XG4gICAgICAgIGlmIChyZXN1bHQ/LmNhcHR1cmVzKSB7XG4gICAgICAgICAgZmluYWxNYXRjaC5wYXRoQ2FwdHVyZXMgPSByZXN1bHQuY2FwdHVyZXNcbiAgICAgICAgICBmaW5hbE1hdGNoLmNhcHR1cmVzID0gbWFwVmFsdWVzKHJlc3VsdC5jYXB0dXJlcywgKHApID0+IHAubm9kZSlcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVzdWx0Py5hcnJheUNhcHR1cmVzKSB7XG4gICAgICAgICAgZmluYWxNYXRjaC5hcnJheVBhdGhDYXB0dXJlcyA9IHJlc3VsdC5hcnJheUNhcHR1cmVzXG4gICAgICAgICAgZmluYWxNYXRjaC5hcnJheUNhcHR1cmVzID0gbWFwVmFsdWVzKHJlc3VsdC5hcnJheUNhcHR1cmVzLCAocGF0aHMpID0+XG4gICAgICAgICAgICBwYXRocy5tYXAoKHApID0+IHAubm9kZSlcbiAgICAgICAgICApXG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlc3VsdD8uc3RyaW5nQ2FwdHVyZXMpIHtcbiAgICAgICAgICBmaW5hbE1hdGNoLnN0cmluZ0NhcHR1cmVzID0gcmVzdWx0LnN0cmluZ0NhcHR1cmVzXG4gICAgICAgIH1cblxuICAgICAgICBtYXRjaGVzLnB1c2goZmluYWxNYXRjaClcblxuICAgICAgICAvLyBwcmV2ZW50IG92ZXJsYXBwaW5nIG1hdGNoZXNcbiAgICAgICAgc2xpY2VTdGFydCA9IGVuZFxuICAgICAgICBhcnJheUluZGV4ID0gZW5kIC0gMVxuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gbWF0Y2hlc1xufVxuIl0sIm1hcHBpbmdzIjoiO0FBQ0EsU0FBU0EsU0FBVCxRQUEwQixRQUExQjtBQUNBLE9BQU9DLGNBQVA7OztBQUdFQyxhQUhGO0FBSU8sa0JBSlA7O0FBTUEsT0FBT0MsV0FBUCxNQUF3QixvQkFBeEI7QUFDQSxPQUFPQyxXQUFQLE1BQXdCLG9CQUF4Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBcUJBLE9BQU8sU0FBU0MsbUJBQVQsQ0FBNkJDLE9BQTdCLEVBQW9FO0VBQ3pFLE9BQU9KLGFBQWE7RUFDbEIsR0FBR0MsV0FBVyxDQUFDRyxPQUFELENBQVgsQ0FBcUJDLEdBQXJCO0VBQ0QsQ0FBQyxFQUFFQyxZQUFGLEVBQWdCQyxpQkFBaEIsRUFBbUNDLGNBQW5DLEVBQUQsTUFBdUU7SUFDckVDLFFBQVEsRUFBRUgsWUFEMkQ7SUFFckVJLGFBQWEsRUFBRUgsaUJBRnNEO0lBR3JFQyxjQUhxRSxFQUF2RSxDQURDLENBRGUsQ0FBcEI7Ozs7QUFTRDs7QUFFRCxPQUFPLFNBQVNHLFdBQVQ7QUFDTEMsS0FESztBQUVMQyxNQUZLO0FBR0U7RUFDUCxJQUFJLENBQUNBLE1BQUwsRUFBYTtJQUNYLE1BQU0sSUFBSUMsS0FBSixDQUFVLHdCQUFWLENBQU47RUFDRDtFQUNELE1BQU0sRUFBRUwsUUFBRixFQUFZQyxhQUFaLEVBQTJCRixjQUEzQixLQUE4Q0ssTUFBcEQ7RUFDQSxNQUFNRSxLQUFZLEdBQUdDLEtBQUssQ0FBQ0MsT0FBTixDQUFjTCxLQUFkO0VBQ2pCO0lBQ0VNLElBQUksRUFBRSxPQURSO0lBRUVDLElBQUksYUFBRVAsS0FBSyxDQUFDLENBQUQsQ0FBUCw0Q0FBRSxRQUFVTyxJQUZsQjtJQUdFQyxJQUFJLEVBQUVSLEtBQUssQ0FBQyxDQUFELENBSGI7SUFJRVMsS0FBSyxFQUFFVCxLQUFLLENBQUNQLEdBQU4sQ0FBVSxDQUFDaUIsQ0FBRCxLQUFPQSxDQUFDLENBQUNILElBQW5CLENBSlQ7SUFLRVAsS0FMRixFQURpQjs7RUFRakI7SUFDRU0sSUFBSSxFQUFFLE1BRFI7SUFFRUMsSUFBSSxFQUFFUCxLQUFLLENBQUNPLElBRmQ7SUFHRUMsSUFBSSxFQUFFUixLQUhSO0lBSUVTLEtBQUssRUFBRSxDQUFDVCxLQUFLLENBQUNPLElBQVAsQ0FKVDtJQUtFUCxLQUFLLEVBQUUsQ0FBQ0EsS0FBRCxDQUxULEVBUko7O0VBZUEsSUFBSUgsUUFBSixFQUFjO0lBQ1pNLEtBQUssQ0FBQ1QsWUFBTixHQUFxQkcsUUFBckI7SUFDQU0sS0FBSyxDQUFDTixRQUFOLEdBQWlCWCxTQUFTLENBQUNXLFFBQUQsRUFBVyxDQUFDVyxJQUFELEtBQW9CQSxJQUFJLENBQUNELElBQXBDLENBQTFCO0VBQ0Q7RUFDRCxJQUFJVCxhQUFKLEVBQW1CO0lBQ2pCSyxLQUFLLENBQUNSLGlCQUFOLEdBQTBCRyxhQUExQjtJQUNBSyxLQUFLLENBQUNMLGFBQU4sR0FBc0JaLFNBQVMsQ0FBQ1ksYUFBRCxFQUFnQixDQUFDRSxLQUFEO0lBQzdDQSxLQUFLLENBQUNQLEdBQU4sQ0FBVSxDQUFDZSxJQUFELEtBQVVBLElBQUksQ0FBQ0QsSUFBekIsQ0FENkIsQ0FBL0I7O0VBR0Q7RUFDRCxJQUFJWCxjQUFKLEVBQW9CTyxLQUFLLENBQUNQLGNBQU4sR0FBdUJBLGNBQXZCO0VBQ3BCLE9BQU9PLEtBQVA7QUFDRDs7QUFFRCxlQUFlLFNBQVNRLElBQVQ7QUFDYlgsS0FEYTtBQUViWSxPQUZhO0FBR2JDLE9BSGE7QUFJSjtFQUNULE1BQU1DLENBQUMsR0FBR0QsT0FBTyxDQUFDRSxPQUFSLENBQWdCRCxDQUExQjtFQUNBLE1BQU1FLENBQUMsR0FBR0YsQ0FBQyxDQUFDRyxVQUFaO0VBQ0EsSUFBSWIsS0FBSyxDQUFDQyxPQUFOLENBQWNPLE9BQWQsS0FBMEJBLE9BQU8sQ0FBQ00sTUFBUixLQUFtQixDQUFqRCxFQUFvRE4sT0FBTyxHQUFHQSxPQUFPLENBQUMsQ0FBRCxDQUFqQjtFQUNwRCxJQUFJUixLQUFLLENBQUNDLE9BQU4sQ0FBY08sT0FBZCxDQUFKLEVBQTRCO0lBQzFCLElBQUksQ0FBQ0ksQ0FBQyxDQUFDRyxTQUFGLENBQVlDLEtBQVosQ0FBa0JSLE9BQU8sQ0FBQyxDQUFELENBQVAsQ0FBV1MsS0FBN0IsQ0FBTCxFQUEwQztNQUN4QyxNQUFNLElBQUluQixLQUFKLENBQVcsOENBQVgsQ0FBTjtJQUNEO0lBQ0QsT0FBT29CLGNBQWM7SUFDbkJ0QixLQURtQjtJQUVuQlksT0FGbUI7SUFHbkJDLE9BSG1CLENBQXJCOztFQUtEOztFQUVELE1BQU1VLE9BQU8sR0FBR3BDLGNBQWMsQ0FBQ3lCLE9BQUQsRUFBc0JDLE9BQXRCLENBQTlCOztFQUVBLE1BQU1yQixPQUFxQixHQUFHLEVBQTlCOztFQUVBLE1BQU1nQyxTQUE4QixHQUFHbkMsV0FBVyxDQUFDa0MsT0FBTyxDQUFDRSxRQUFSLElBQW9CLE1BQXJCLENBQWxEOztFQUVBbkMsV0FBVyxDQUFDd0IsQ0FBRCxFQUFJekIsV0FBVyxDQUFDVyxLQUFELENBQWYsRUFBd0J3QixTQUF4QixFQUFtQyxDQUFDaEIsSUFBRCxLQUFvQjtJQUNoRSxNQUFNUCxNQUFNLEdBQUdzQixPQUFPLENBQUNwQixLQUFSLENBQWNLLElBQWQseUJBQW9CSyxPQUFwQixhQUFvQkEsT0FBcEIsdUJBQW9CQSxPQUFPLENBQUVhLFVBQTdCLHFFQUEyQyxJQUEzQyxDQUFmO0lBQ0EsSUFBSXpCLE1BQUosRUFBWVQsT0FBTyxDQUFDbUMsSUFBUixDQUFhNUIsV0FBVyxDQUFDUyxJQUFELEVBQU9QLE1BQVAsQ0FBeEI7RUFDYixDQUhVLENBQVg7O0VBS0EsT0FBT1QsT0FBUDtBQUNEOztBQUVELFNBQVM4QixjQUFUO0FBQ0V0QixLQURGO0FBRUVZLE9BRkY7QUFHRUMsT0FIRjtBQUlXO0VBQ1QsTUFBTUMsQ0FBQyxHQUFHRCxPQUFPLENBQUNFLE9BQVIsQ0FBZ0JELENBQTFCOztFQUVBLE1BQU1jLFFBQTJCLEdBQUdoQixPQUFPLENBQUNuQixHQUFSLENBQVksQ0FBQ29DLFNBQUQ7RUFDOUMxQyxjQUFjLENBQUMwQyxTQUFELEVBQVloQixPQUFaLENBRG9CLENBQXBDOzs7RUFJQSxNQUFNaUIseUJBQXlCLEdBQUdGLFFBQVEsQ0FBQ0csU0FBVDtFQUNoQyxDQUFDQyxDQUFELEtBQU8sQ0FBQ0EsQ0FBQyxDQUFDQyxnQkFEc0IsQ0FBbEM7OztFQUlBLElBQUlILHlCQUF5QixHQUFHLENBQWhDLEVBQW1DO0lBQ2pDLE1BQU0sSUFBSTVCLEtBQUo7SUFDSCwyRUFERyxDQUFOOztFQUdEOztFQUVELFNBQVNnQyxpQkFBVCxDQUEyQkMsWUFBM0IsRUFBeUQ7SUFDdkQsSUFBSUMsS0FBSyxHQUFHLENBQVo7SUFDQSxLQUFLLElBQUlDLENBQUMsR0FBR0YsWUFBYixFQUEyQkUsQ0FBQyxHQUFHVCxRQUFRLENBQUNWLE1BQXhDLEVBQWdEbUIsQ0FBQyxFQUFqRCxFQUFxRDtNQUNuRCxJQUFJLENBQUNULFFBQVEsQ0FBQ1MsQ0FBRCxDQUFSLENBQVlKLGdCQUFqQixFQUFtQ0csS0FBSztJQUN6QztJQUNELE9BQU9BLEtBQVA7RUFDRDs7RUFFRCxTQUFTRSxTQUFUO0VBQ0V0QyxLQURGO0VBRUV1QyxVQUZGO0VBR0VDLFVBSEY7RUFJRUwsWUFKRjtFQUtFVCxVQUxGO0VBTTBDO0lBQ3hDLElBQUljLFVBQVUsS0FBS3hDLEtBQUssQ0FBQ2tCLE1BQXJCLElBQStCaUIsWUFBWSxLQUFLUCxRQUFRLENBQUNWLE1BQTdELEVBQXFFO01BQ25FLE9BQU9nQixpQkFBaUIsQ0FBQ0MsWUFBRCxDQUFqQixLQUFvQyxDQUFwQztNQUNILENBQUNULFVBQVUsSUFBSSxFQUFmLEVBQW1CLENBQUNjLFVBQUQsRUFBYUEsVUFBYixDQUFuQixDQURHO01BRUgsSUFGSjtJQUdEOztJQUVELE1BQU1qQixPQUFPLEdBQUdLLFFBQVEsQ0FBQ08sWUFBRCxDQUF4QjtJQUNBLE1BQU0sRUFBRUYsZ0JBQUYsS0FBdUJWLE9BQTdCO0lBQ0EsSUFBSVUsZ0JBQUosRUFBc0I7TUFDcEIsSUFBSUUsWUFBWSxLQUFLUCxRQUFRLENBQUNWLE1BQVQsR0FBa0IsQ0FBdkMsRUFBMEM7UUFDeEMsT0FBTztRQUNMOUIsYUFBYSxDQUFDc0MsVUFBRCxFQUFhO1VBQ3hCNUIsYUFBYSxFQUFFO1lBQ2IsQ0FBQ21DLGdCQUFELEdBQW9CakMsS0FBSyxDQUFDeUMsS0FBTixDQUFZRixVQUFaLENBRFAsRUFEUyxFQUFiLENBRFI7OztRQU1MLENBQUNBLFVBQUQsRUFBYXZDLEtBQUssQ0FBQ2tCLE1BQW5CLENBTkssQ0FBUDs7TUFRRDtNQUNELE9BQU9vQixTQUFTO01BQ2R0QyxLQURjO01BRWR1QyxVQUZjO01BR2RDLFVBSGM7TUFJZEwsWUFBWSxHQUFHLENBSkQ7TUFLZFQsVUFMYyxDQUFoQjs7SUFPRCxDQWxCRCxNQWtCTztNQUNMLE1BQU1nQixjQUFjLEdBQUdoQixVQUF2QjtNQUNBLE1BQU1pQixvQkFBb0IsZ0JBQUdmLFFBQVEsQ0FBQ08sWUFBWSxHQUFHLENBQWhCLENBQVgsOENBQUcsVUFBNEJGLGdCQUF6RDtNQUNBLE1BQU1XLEdBQUc7TUFDUEQsb0JBQW9CLElBQUlSLFlBQVksS0FBS0wseUJBQXpDO01BQ0k5QixLQUFLLENBQUNrQixNQUFOLEdBQWVnQixpQkFBaUIsQ0FBQ0MsWUFBWSxHQUFHLENBQWhCLENBRHBDO01BRUlLLFVBQVUsR0FBRyxDQUhuQjtNQUlBLEtBQUssSUFBSUgsQ0FBQyxHQUFHRyxVQUFiLEVBQXlCSCxDQUFDLEdBQUdPLEdBQTdCLEVBQWtDUCxDQUFDLEVBQW5DLEVBQXVDO1FBQ3JDWCxVQUFVLEdBQUdILE9BQU8sQ0FBQ3BCLEtBQVIsQ0FBY0gsS0FBSyxDQUFDcUMsQ0FBRCxDQUFuQixFQUF3QkssY0FBeEIsQ0FBYjtRQUNBLElBQUksQ0FBQ2hCLFVBQUwsRUFBaUI7UUFDakIsSUFBSWlCLG9CQUFKLEVBQTBCO1VBQ3hCakIsVUFBVSxHQUFHdEMsYUFBYSxDQUFDc0MsVUFBRCxFQUFhO1lBQ3JDNUIsYUFBYSxFQUFFO2NBQ2IsQ0FBQzZDLG9CQUFELEdBQXdCM0MsS0FBSyxDQUFDeUMsS0FBTixDQUFZRixVQUFaLEVBQXdCRixDQUF4QixDQURYLEVBRHNCLEVBQWIsQ0FBMUI7OztRQUtEO1FBQ0QsTUFBTVEsU0FBUyxHQUFHUCxTQUFTO1FBQ3pCdEMsS0FEeUI7UUFFekJxQyxDQUFDLEdBQUcsQ0FGcUI7UUFHekJBLENBQUMsR0FBRyxDQUhxQjtRQUl6QkYsWUFBWSxHQUFHLENBSlU7UUFLekJULFVBTHlCLENBQTNCOztRQU9BLElBQUltQixTQUFKLEVBQWUsT0FBTyxDQUFDQSxTQUFTLENBQUMsQ0FBRCxDQUFWLEVBQWUsQ0FBQ1IsQ0FBRCxFQUFJUSxTQUFTLENBQUMsQ0FBRCxDQUFULENBQWEsQ0FBYixDQUFKLENBQWYsQ0FBUDtNQUNoQjtJQUNGO0lBQ0QsT0FBTyxJQUFQO0VBQ0Q7O0VBRUQsTUFBTUMsTUFBeUIsR0FBRyxFQUFsQzs7RUFFQXhELFdBQVcsQ0FBQ3dCLENBQUQsRUFBSXpCLFdBQVcsQ0FBQ1csS0FBRCxDQUFmLEVBQXdCLENBQUMsT0FBRCxDQUF4QixFQUFtQyxDQUFDUSxJQUFELEtBQW9CO0lBQ2hFc0MsTUFBTSxDQUFDbkIsSUFBUCxDQUFZbkIsSUFBWjtFQUNELENBRlUsQ0FBWDtFQUdBc0MsTUFBTSxDQUFDQyxPQUFQOztFQUVBLE1BQU12RCxPQUFnQixHQUFHLEVBQXpCOztFQUVBLE1BQU13RCxZQUFZLDJCQUFHbkMsT0FBSCxhQUFHQSxPQUFILHVCQUFHQSxPQUFPLENBQUVhLFVBQVosdUVBQTBCLElBQTVDOztFQUVBLEtBQUssTUFBTXVCLEtBQVgsSUFBb0JILE1BQXBCLEVBQTRCO0lBQzFCLE1BQU1JLElBQTJCLEdBQUdELEtBQUssQ0FBQ0UsR0FBTixDQUFVLE1BQVYsRUFBa0JDLE1BQWxCLENBQXlCLE1BQU0sSUFBL0IsQ0FBcEM7SUFDQSxNQUFNUixHQUFHLEdBQUdNLElBQUksQ0FBQ2hDLE1BQUwsR0FBY2dCLGlCQUFpQixDQUFDSix5QkFBeUIsR0FBRyxDQUE3QixDQUEzQztJQUNBLElBQUlTLFVBQVUsR0FBRyxDQUFqQjtJQUNBLEtBQUssSUFBSUMsVUFBVSxHQUFHLENBQXRCLEVBQXlCQSxVQUFVLEdBQUdJLEdBQXRDLEVBQTJDSixVQUFVLEVBQXJELEVBQXlEO01BQ3ZELE1BQU1yQyxLQUFLLEdBQUdtQyxTQUFTO01BQ3JCWSxJQURxQjtNQUVyQlgsVUFGcUI7TUFHckJDLFVBSHFCO01BSXJCVix5QkFKcUI7TUFLckJrQixZQUxxQixDQUF2Qjs7TUFPQSxJQUFJN0MsS0FBSixFQUFXO1FBQ1QsSUFBSUYsTUFBTSxHQUFHRSxLQUFLLENBQUMsQ0FBRCxDQUFsQjtRQUNBLE1BQU1rRCxLQUFLLEdBQUd2Qix5QkFBeUIsR0FBRyxDQUE1QixHQUFnQyxDQUFoQyxHQUFvQzNCLEtBQUssQ0FBQyxDQUFELENBQUwsQ0FBUyxDQUFULENBQWxEO1FBQ0EsTUFBTSxHQUFHeUMsR0FBSCxJQUFVekMsS0FBSyxDQUFDLENBQUQsQ0FBckI7O1FBRUE7UUFDQTtRQUNBO1FBQ0EsS0FBSyxNQUFNb0IsT0FBWCxJQUFzQkssUUFBdEIsRUFBZ0M7VUFDOUIsTUFBTSxFQUFFSyxnQkFBRixLQUF1QlYsT0FBN0I7VUFDQSxJQUFJLENBQUNVLGdCQUFMLEVBQXVCO1VBQ3ZCLElBQUksYUFBQ2hDLE1BQUQsNkRBQUMsUUFBUUgsYUFBVCxrREFBQyxzQkFBd0JtQyxnQkFBeEIsQ0FBRCxDQUFKO1VBQ0VoQyxNQUFNLEdBQUdiLGFBQWEsQ0FBQ2EsTUFBRCxFQUFTO1lBQzdCSCxhQUFhLEVBQUUsRUFBRSxDQUFDbUMsZ0JBQUQsR0FBb0IsRUFBdEIsRUFEYyxFQUFULENBQXRCOztRQUdIOztRQUVELE1BQU1qQyxLQUFLLEdBQUdrRCxJQUFJLENBQUNULEtBQUwsQ0FBV1ksS0FBWCxFQUFrQlQsR0FBbEIsQ0FBZDs7UUFFQSxNQUFNVSxVQUFpQixHQUFHO1VBQ3hCaEQsSUFBSSxFQUFFLE9BRGtCO1VBRXhCRSxJQUFJLEVBQUVSLEtBQUssQ0FBQyxDQUFELENBRmE7VUFHeEJPLElBQUksRUFBRVAsS0FBSyxDQUFDLENBQUQsQ0FBTCxDQUFTTyxJQUhTO1VBSXhCUCxLQUp3QjtVQUt4QlMsS0FBSyxFQUFFVCxLQUFLLENBQUNQLEdBQU4sQ0FBVSxDQUFDaUIsQ0FBRCxLQUFPQSxDQUFDLENBQUNILElBQW5CLENBTGlCLEVBQTFCOztRQU9BLGdCQUFJTixNQUFKLHFDQUFJLFNBQVFKLFFBQVosRUFBc0I7VUFDcEJ5RCxVQUFVLENBQUM1RCxZQUFYLEdBQTBCTyxNQUFNLENBQUNKLFFBQWpDO1VBQ0F5RCxVQUFVLENBQUN6RCxRQUFYLEdBQXNCWCxTQUFTLENBQUNlLE1BQU0sQ0FBQ0osUUFBUixFQUFrQixDQUFDYSxDQUFELEtBQU9BLENBQUMsQ0FBQ0gsSUFBM0IsQ0FBL0I7UUFDRDtRQUNELGdCQUFJTixNQUFKLHFDQUFJLFNBQVFILGFBQVosRUFBMkI7VUFDekJ3RCxVQUFVLENBQUMzRCxpQkFBWCxHQUErQk0sTUFBTSxDQUFDSCxhQUF0QztVQUNBd0QsVUFBVSxDQUFDeEQsYUFBWCxHQUEyQlosU0FBUyxDQUFDZSxNQUFNLENBQUNILGFBQVIsRUFBdUIsQ0FBQ0UsS0FBRDtVQUN6REEsS0FBSyxDQUFDUCxHQUFOLENBQVUsQ0FBQ2lCLENBQUQsS0FBT0EsQ0FBQyxDQUFDSCxJQUFuQixDQURrQyxDQUFwQzs7UUFHRDtRQUNELGdCQUFJTixNQUFKLHFDQUFJLFNBQVFMLGNBQVosRUFBNEI7VUFDMUIwRCxVQUFVLENBQUMxRCxjQUFYLEdBQTRCSyxNQUFNLENBQUNMLGNBQW5DO1FBQ0Q7O1FBRURKLE9BQU8sQ0FBQ21DLElBQVIsQ0FBYTJCLFVBQWI7O1FBRUE7UUFDQWYsVUFBVSxHQUFHSyxHQUFiO1FBQ0FKLFVBQVUsR0FBR0ksR0FBRyxHQUFHLENBQW5CO01BQ0Q7SUFDRjtFQUNGO0VBQ0QsT0FBT3BELE9BQVA7QUFDRCJ9