UNPKG

matrix-react-sdk

Version:
382 lines (374 loc) 56.2 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.UserVote = void 0; exports.allVotes = allVotes; exports.collectUserVotes = collectUserVotes; exports.countVotes = countVotes; exports.createVoteRelations = createVoteRelations; exports.default = void 0; exports.findTopAnswer = findTopAnswer; exports.isPollEnded = isPollEnded; exports.launchPollEditor = launchPollEditor; exports.pollAlreadyHasVotes = pollAlreadyHasVotes; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var _logger = require("matrix-js-sdk/src/logger"); var _matrix = require("matrix-js-sdk/src/matrix"); var _relatedRelations = require("matrix-js-sdk/src/models/related-relations"); var _PollResponseEvent = require("matrix-js-sdk/src/extensible_events_v1/PollResponseEvent"); var _languageHandler = require("../../../languageHandler"); var _Modal = _interopRequireDefault(require("../../../Modal")); var _FormattingUtils = require("../../../utils/FormattingUtils"); var _MatrixClientContext = _interopRequireDefault(require("../../../contexts/MatrixClientContext")); var _ErrorDialog = _interopRequireDefault(require("../dialogs/ErrorDialog")); var _PollCreateDialog = _interopRequireDefault(require("../elements/PollCreateDialog")); var _MatrixClientPeg = require("../../../MatrixClientPeg"); var _Spinner = _interopRequireDefault(require("../elements/Spinner")); var _PollOption = require("../polls/PollOption"); /* Copyright 2024 New Vector Ltd. Copyright 2021 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ function createVoteRelations(getRelationsForEvent, eventId) { const relationsList = []; const pollResponseRelations = getRelationsForEvent(eventId, "m.reference", _matrix.M_POLL_RESPONSE.name); if (pollResponseRelations) { relationsList.push(pollResponseRelations); } const pollResposnseAltRelations = getRelationsForEvent(eventId, "m.reference", _matrix.M_POLL_RESPONSE.altName); if (pollResposnseAltRelations) { relationsList.push(pollResposnseAltRelations); } return new _relatedRelations.RelatedRelations(relationsList); } function findTopAnswer(pollEvent, voteRelations) { const pollEventId = pollEvent.getId(); if (!pollEventId) { _logger.logger.warn("findTopAnswer: Poll event needs an event ID to fetch relations in order to determine " + "the top answer - assuming no best answer"); return ""; } const poll = pollEvent.unstableExtensibleEvent; if (!poll?.isEquivalentTo(_matrix.M_POLL_START)) { _logger.logger.warn("Failed to parse poll to determine top answer - assuming no best answer"); return ""; } const findAnswerText = answerId => { return poll.answers.find(a => a.id === answerId)?.text ?? ""; }; const userVotes = collectUserVotes(allVotes(voteRelations)); const votes = countVotes(userVotes, poll); const highestScore = Math.max(...votes.values()); const bestAnswerIds = []; for (const [answerId, score] of votes) { if (score == highestScore) { bestAnswerIds.push(answerId); } } const bestAnswerTexts = bestAnswerIds.map(findAnswerText); return (0, _FormattingUtils.formatList)(bestAnswerTexts, 3); } function isPollEnded(pollEvent, matrixClient) { const room = matrixClient.getRoom(pollEvent.getRoomId()); const poll = room?.polls.get(pollEvent.getId()); if (!poll || poll.isFetchingResponses) { return false; } return poll.isEnded; } function pollAlreadyHasVotes(mxEvent, getRelationsForEvent) { if (!getRelationsForEvent) return false; const eventId = mxEvent.getId(); if (!eventId) return false; const voteRelations = createVoteRelations(getRelationsForEvent, eventId); return voteRelations.getRelations().length > 0; } function launchPollEditor(mxEvent, getRelationsForEvent) { const room = _MatrixClientPeg.MatrixClientPeg.safeGet().getRoom(mxEvent.getRoomId()); if (pollAlreadyHasVotes(mxEvent, getRelationsForEvent)) { _Modal.default.createDialog(_ErrorDialog.default, { title: (0, _languageHandler._t)("poll|unable_edit_title"), description: (0, _languageHandler._t)("poll|unable_edit_description") }); } else if (room) { _Modal.default.createDialog(_PollCreateDialog.default, { room, threadId: mxEvent.getThread()?.id, editingMxEvent: mxEvent }, "mx_CompoundDialog", false, // isPriorityModal true // isStaticModal ); } } class MPollBody extends _react.default.Component { // Events we have already seen constructor(props, context) { super(props, context); (0, _defineProperty2.default)(this, "seenEventIds", []); (0, _defineProperty2.default)(this, "onResponsesChange", responses => { this.setState({ voteRelations: responses }); this.onRelationsChange(); }); (0, _defineProperty2.default)(this, "onRelationsChange", () => { // We hold Relations in our state, and they changed under us. // Check whether we should delete our selection, and then // re-render. // Note: re-rendering is a side effect of unselectIfNewEventFromMe(). this.unselectIfNewEventFromMe(); }); this.state = { selected: null, pollInitialised: false }; } componentDidMount() { const room = this.context?.getRoom(this.props.mxEvent.getRoomId()); const poll = room?.polls.get(this.props.mxEvent.getId()); if (poll) { this.setPollInstance(poll); } else { room?.on(_matrix.PollEvent.New, this.setPollInstance.bind(this)); } } componentWillUnmount() { this.removeListeners(); } async setPollInstance(poll) { if (poll.pollId !== this.props.mxEvent.getId()) { return; } this.setState({ poll }, () => { this.addListeners(); }); const responses = await poll.getResponses(); const voteRelations = responses; this.setState({ pollInitialised: true, voteRelations }); } addListeners() { this.state.poll?.on(_matrix.PollEvent.Responses, this.onResponsesChange); this.state.poll?.on(_matrix.PollEvent.End, this.onRelationsChange); this.state.poll?.on(_matrix.PollEvent.UndecryptableRelations, this.render.bind(this)); } removeListeners() { if (this.state.poll) { this.state.poll.off(_matrix.PollEvent.Responses, this.onResponsesChange); this.state.poll.off(_matrix.PollEvent.End, this.onRelationsChange); this.state.poll.off(_matrix.PollEvent.UndecryptableRelations, this.render.bind(this)); } } selectOption(answerId) { if (this.state.poll?.isEnded) { return; } const userVotes = this.collectUserVotes(); const userId = this.context.getSafeUserId(); const myVote = userVotes.get(userId)?.answers[0]; if (answerId === myVote) { return; } const response = _PollResponseEvent.PollResponseEvent.from([answerId], this.props.mxEvent.getId()).serialize(); this.context.sendEvent(this.props.mxEvent.getRoomId(), response.type, response.content).catch(e => { console.error("Failed to submit poll response event:", e); _Modal.default.createDialog(_ErrorDialog.default, { title: (0, _languageHandler._t)("poll|error_voting_title"), description: (0, _languageHandler._t)("poll|error_voting_description") }); }); this.setState({ selected: answerId }); } /** * @returns userId -> UserVote */ collectUserVotes() { if (!this.state.voteRelations || !this.context) { return new Map(); } return collectUserVotes(allVotes(this.state.voteRelations), this.context.getUserId(), this.state.selected); } /** * If we've just received a new event that we hadn't seen * before, and that event is me voting (e.g. from a different * device) then forget when the local user selected. * * Either way, calls setState to update our list of events we * have already seen. */ unselectIfNewEventFromMe() { const relations = this.state.voteRelations?.getRelations() || []; const newEvents = relations.filter(mxEvent => !this.seenEventIds.includes(mxEvent.getId())); let newSelected = this.state.selected; if (newEvents.length > 0) { for (const mxEvent of newEvents) { if (mxEvent.getSender() === this.context.getUserId()) { newSelected = null; } } } const newEventIds = newEvents.map(mxEvent => mxEvent.getId()); this.seenEventIds = this.seenEventIds.concat(newEventIds); this.setState({ selected: newSelected }); } totalVotes(collectedVotes) { let sum = 0; for (const v of collectedVotes.values()) { sum += v; } return sum; } render() { const { poll, pollInitialised } = this.state; if (!poll?.pollEvent) { return null; } const pollEvent = poll.pollEvent; const pollId = this.props.mxEvent.getId(); const isFetchingResponses = !pollInitialised || poll.isFetchingResponses; const userVotes = this.collectUserVotes(); const votes = countVotes(userVotes, pollEvent); const totalVotes = this.totalVotes(votes); const winCount = Math.max(...votes.values()); const userId = this.context.getSafeUserId(); const myVote = userVotes?.get(userId)?.answers[0]; const disclosed = _matrix.M_POLL_KIND_DISCLOSED.matches(pollEvent.kind.name); // Disclosed: votes are hidden until I vote or the poll ends // Undisclosed: votes are hidden until poll ends const showResults = poll.isEnded || disclosed && myVote !== undefined; let totalText; if (showResults && poll.undecryptableRelationsCount) { totalText = (0, _languageHandler._t)("poll|total_decryption_errors"); } else if (poll.isEnded) { totalText = (0, _languageHandler._t)("right_panel|poll|final_result", { count: totalVotes }); } else if (!disclosed) { totalText = (0, _languageHandler._t)("poll|total_not_ended"); } else if (myVote === undefined) { if (totalVotes === 0) { totalText = (0, _languageHandler._t)("poll|total_no_votes"); } else { totalText = (0, _languageHandler._t)("poll|total_n_votes", { count: totalVotes }); } } else { totalText = (0, _languageHandler._t)("poll|total_n_votes_voted", { count: totalVotes }); } const editedSpan = this.props.mxEvent.replacingEvent() ? /*#__PURE__*/_react.default.createElement("span", { className: "mx_MPollBody_edited" }, " (", (0, _languageHandler._t)("common|edited"), ")") : null; return /*#__PURE__*/_react.default.createElement("div", { className: "mx_MPollBody" }, /*#__PURE__*/_react.default.createElement("h2", { "data-testid": "pollQuestion" }, pollEvent.question.text, editedSpan), /*#__PURE__*/_react.default.createElement("div", { className: "mx_MPollBody_allOptions" }, pollEvent.answers.map(answer => { let answerVotes = 0; if (showResults) { answerVotes = votes.get(answer.id) ?? 0; } const checked = !poll.isEnded && myVote === answer.id || poll.isEnded && answerVotes === winCount; return /*#__PURE__*/_react.default.createElement(_PollOption.PollOption, { key: answer.id, pollId: pollId, answer: answer, isChecked: checked, isEnded: poll.isEnded, voteCount: answerVotes, totalVoteCount: totalVotes, displayVoteCount: showResults, onOptionSelected: this.selectOption.bind(this) }); })), /*#__PURE__*/_react.default.createElement("div", { "data-testid": "totalVotes", className: "mx_MPollBody_totalVotes" }, totalText, isFetchingResponses && /*#__PURE__*/_react.default.createElement(_Spinner.default, { w: 16, h: 16 }))); } } exports.default = MPollBody; (0, _defineProperty2.default)(MPollBody, "contextType", _MatrixClientContext.default); class UserVote { constructor(ts, sender, answers) { this.ts = ts; this.sender = sender; this.answers = answers; } } exports.UserVote = UserVote; function userResponseFromPollResponseEvent(event) { const response = event.unstableExtensibleEvent; if (!response?.isEquivalentTo(_matrix.M_POLL_RESPONSE)) { throw new Error("Failed to parse Poll Response Event to determine user response"); } return new UserVote(event.getTs(), event.getSender(), response.answerIds); } function allVotes(voteRelations) { if (voteRelations) { return voteRelations.getRelations().map(userResponseFromPollResponseEvent); } else { return []; } } /** * Figure out the correct vote for each user. * @param userResponses current vote responses in the poll * @param {string?} userId The userId for which the `selected` option will apply to. * Should be set to the current user ID. * @param {string?} selected Local echo selected option for the userId * @returns a Map of user ID to their vote info */ function collectUserVotes(userResponses, userId, selected) { const userVotes = new Map(); for (const response of userResponses) { const otherResponse = userVotes.get(response.sender); if (!otherResponse || otherResponse.ts < response.ts) { userVotes.set(response.sender, response); } } if (selected && userId) { userVotes.set(userId, new UserVote(0, userId, [selected])); } return userVotes; } function countVotes(userVotes, pollStart) { const collected = new Map(); for (const response of userVotes.values()) { const tempResponse = _PollResponseEvent.PollResponseEvent.from(response.answers, "$irrelevant"); tempResponse.validateAgainst(pollStart); if (!tempResponse.spoiled) { for (const answerId of tempResponse.answerIds) { if (collected.has(answerId)) { collected.set(answerId, collected.get(answerId) + 1); } else { collected.set(answerId, 1); } } } } return collected; } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9sb2dnZXIiLCJfbWF0cml4IiwiX3JlbGF0ZWRSZWxhdGlvbnMiLCJfUG9sbFJlc3BvbnNlRXZlbnQiLCJfbGFuZ3VhZ2VIYW5kbGVyIiwiX01vZGFsIiwiX0Zvcm1hdHRpbmdVdGlscyIsIl9NYXRyaXhDbGllbnRDb250ZXh0IiwiX0Vycm9yRGlhbG9nIiwiX1BvbGxDcmVhdGVEaWFsb2ciLCJfTWF0cml4Q2xpZW50UGVnIiwiX1NwaW5uZXIiLCJfUG9sbE9wdGlvbiIsImNyZWF0ZVZvdGVSZWxhdGlvbnMiLCJnZXRSZWxhdGlvbnNGb3JFdmVudCIsImV2ZW50SWQiLCJyZWxhdGlvbnNMaXN0IiwicG9sbFJlc3BvbnNlUmVsYXRpb25zIiwiTV9QT0xMX1JFU1BPTlNFIiwibmFtZSIsInB1c2giLCJwb2xsUmVzcG9zbnNlQWx0UmVsYXRpb25zIiwiYWx0TmFtZSIsIlJlbGF0ZWRSZWxhdGlvbnMiLCJmaW5kVG9wQW5zd2VyIiwicG9sbEV2ZW50Iiwidm90ZVJlbGF0aW9ucyIsInBvbGxFdmVudElkIiwiZ2V0SWQiLCJsb2dnZXIiLCJ3YXJuIiwicG9sbCIsInVuc3RhYmxlRXh0ZW5zaWJsZUV2ZW50IiwiaXNFcXVpdmFsZW50VG8iLCJNX1BPTExfU1RBUlQiLCJmaW5kQW5zd2VyVGV4dCIsImFuc3dlcklkIiwiYW5zd2VycyIsImZpbmQiLCJhIiwiaWQiLCJ0ZXh0IiwidXNlclZvdGVzIiwiY29sbGVjdFVzZXJWb3RlcyIsImFsbFZvdGVzIiwidm90ZXMiLCJjb3VudFZvdGVzIiwiaGlnaGVzdFNjb3JlIiwiTWF0aCIsIm1heCIsInZhbHVlcyIsImJlc3RBbnN3ZXJJZHMiLCJzY29yZSIsImJlc3RBbnN3ZXJUZXh0cyIsIm1hcCIsImZvcm1hdExpc3QiLCJpc1BvbGxFbmRlZCIsIm1hdHJpeENsaWVudCIsInJvb20iLCJnZXRSb29tIiwiZ2V0Um9vbUlkIiwicG9sbHMiLCJnZXQiLCJpc0ZldGNoaW5nUmVzcG9uc2VzIiwiaXNFbmRlZCIsInBvbGxBbHJlYWR5SGFzVm90ZXMiLCJteEV2ZW50IiwiZ2V0UmVsYXRpb25zIiwibGVuZ3RoIiwibGF1bmNoUG9sbEVkaXRvciIsIk1hdHJpeENsaWVudFBlZyIsInNhZmVHZXQiLCJNb2RhbCIsImNyZWF0ZURpYWxvZyIsIkVycm9yRGlhbG9nIiwidGl0bGUiLCJfdCIsImRlc2NyaXB0aW9uIiwiUG9sbENyZWF0ZURpYWxvZyIsInRocmVhZElkIiwiZ2V0VGhyZWFkIiwiZWRpdGluZ014RXZlbnQiLCJNUG9sbEJvZHkiLCJSZWFjdCIsIkNvbXBvbmVudCIsImNvbnN0cnVjdG9yIiwicHJvcHMiLCJjb250ZXh0IiwiX2RlZmluZVByb3BlcnR5MiIsImRlZmF1bHQiLCJyZXNwb25zZXMiLCJzZXRTdGF0ZSIsIm9uUmVsYXRpb25zQ2hhbmdlIiwidW5zZWxlY3RJZk5ld0V2ZW50RnJvbU1lIiwic3RhdGUiLCJzZWxlY3RlZCIsInBvbGxJbml0aWFsaXNlZCIsImNvbXBvbmVudERpZE1vdW50Iiwic2V0UG9sbEluc3RhbmNlIiwib24iLCJQb2xsRXZlbnQiLCJOZXciLCJiaW5kIiwiY29tcG9uZW50V2lsbFVubW91bnQiLCJyZW1vdmVMaXN0ZW5lcnMiLCJwb2xsSWQiLCJhZGRMaXN0ZW5lcnMiLCJnZXRSZXNwb25zZXMiLCJSZXNwb25zZXMiLCJvblJlc3BvbnNlc0NoYW5nZSIsIkVuZCIsIlVuZGVjcnlwdGFibGVSZWxhdGlvbnMiLCJyZW5kZXIiLCJvZmYiLCJzZWxlY3RPcHRpb24iLCJ1c2VySWQiLCJnZXRTYWZlVXNlcklkIiwibXlWb3RlIiwicmVzcG9uc2UiLCJQb2xsUmVzcG9uc2VFdmVudCIsImZyb20iLCJzZXJpYWxpemUiLCJzZW5kRXZlbnQiLCJ0eXBlIiwiY29udGVudCIsImNhdGNoIiwiZSIsImNvbnNvbGUiLCJlcnJvciIsIk1hcCIsImdldFVzZXJJZCIsInJlbGF0aW9ucyIsIm5ld0V2ZW50cyIsImZpbHRlciIsInNlZW5FdmVudElkcyIsImluY2x1ZGVzIiwibmV3U2VsZWN0ZWQiLCJnZXRTZW5kZXIiLCJuZXdFdmVudElkcyIsImNvbmNhdCIsInRvdGFsVm90ZXMiLCJjb2xsZWN0ZWRWb3RlcyIsInN1bSIsInYiLCJ3aW5Db3VudCIsImRpc2Nsb3NlZCIsIk1fUE9MTF9LSU5EX0RJU0NMT1NFRCIsIm1hdGNoZXMiLCJraW5kIiwic2hvd1Jlc3VsdHMiLCJ1bmRlZmluZWQiLCJ0b3RhbFRleHQiLCJ1bmRlY3J5cHRhYmxlUmVsYXRpb25zQ291bnQiLCJjb3VudCIsImVkaXRlZFNwYW4iLCJyZXBsYWNpbmdFdmVudCIsImNyZWF0ZUVsZW1lbnQiLCJjbGFzc05hbWUiLCJxdWVzdGlvbiIsImFuc3dlciIsImFuc3dlclZvdGVzIiwiY2hlY2tlZCIsIlBvbGxPcHRpb24iLCJrZXkiLCJpc0NoZWNrZWQiLCJ2b3RlQ291bnQiLCJ0b3RhbFZvdGVDb3VudCIsImRpc3BsYXlWb3RlQ291bnQiLCJvbk9wdGlvblNlbGVjdGVkIiwidyIsImgiLCJleHBvcnRzIiwiTWF0cml4Q2xpZW50Q29udGV4dCIsIlVzZXJWb3RlIiwidHMiLCJzZW5kZXIiLCJ1c2VyUmVzcG9uc2VGcm9tUG9sbFJlc3BvbnNlRXZlbnQiLCJldmVudCIsIkVycm9yIiwiZ2V0VHMiLCJhbnN3ZXJJZHMiLCJ1c2VyUmVzcG9uc2VzIiwib3RoZXJSZXNwb25zZSIsInNldCIsInBvbGxTdGFydCIsImNvbGxlY3RlZCIsInRlbXBSZXNwb25zZSIsInZhbGlkYXRlQWdhaW5zdCIsInNwb2lsZWQiLCJoYXMiXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy92aWV3cy9tZXNzYWdlcy9NUG9sbEJvZHkudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAyNCBOZXcgVmVjdG9yIEx0ZC5cbkNvcHlyaWdodCAyMDIxIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiovXG5cbmltcG9ydCBSZWFjdCwgeyBSZWFjdE5vZGUgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9sb2dnZXJcIjtcbmltcG9ydCB7XG4gICAgTWF0cml4RXZlbnQsXG4gICAgTWF0cml4Q2xpZW50LFxuICAgIFJlbGF0aW9ucyxcbiAgICBQb2xsLFxuICAgIFBvbGxFdmVudCxcbiAgICBNX1BPTExfS0lORF9ESVNDTE9TRUQsXG4gICAgTV9QT0xMX1JFU1BPTlNFLFxuICAgIE1fUE9MTF9TVEFSVCxcbiAgICBUaW1lbGluZUV2ZW50cyxcbn0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL21hdHJpeFwiO1xuaW1wb3J0IHsgUmVsYXRlZFJlbGF0aW9ucyB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9tb2RlbHMvcmVsYXRlZC1yZWxhdGlvbnNcIjtcbmltcG9ydCB7IFBvbGxTdGFydEV2ZW50LCBQb2xsQW5zd2VyU3ViZXZlbnQgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvZXh0ZW5zaWJsZV9ldmVudHNfdjEvUG9sbFN0YXJ0RXZlbnRcIjtcbmltcG9ydCB7IFBvbGxSZXNwb25zZUV2ZW50IH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL2V4dGVuc2libGVfZXZlbnRzX3YxL1BvbGxSZXNwb25zZUV2ZW50XCI7XG5cbmltcG9ydCB7IF90IH0gZnJvbSBcIi4uLy4uLy4uL2xhbmd1YWdlSGFuZGxlclwiO1xuaW1wb3J0IE1vZGFsIGZyb20gXCIuLi8uLi8uLi9Nb2RhbFwiO1xuaW1wb3J0IHsgSUJvZHlQcm9wcyB9IGZyb20gXCIuL0lCb2R5UHJvcHNcIjtcbmltcG9ydCB7IGZvcm1hdExpc3QgfSBmcm9tIFwiLi4vLi4vLi4vdXRpbHMvRm9ybWF0dGluZ1V0aWxzXCI7XG5pbXBvcnQgTWF0cml4Q2xpZW50Q29udGV4dCBmcm9tIFwiLi4vLi4vLi4vY29udGV4dHMvTWF0cml4Q2xpZW50Q29udGV4dFwiO1xuaW1wb3J0IEVycm9yRGlhbG9nIGZyb20gXCIuLi9kaWFsb2dzL0Vycm9yRGlhbG9nXCI7XG5pbXBvcnQgeyBHZXRSZWxhdGlvbnNGb3JFdmVudCB9IGZyb20gXCIuLi9yb29tcy9FdmVudFRpbGVcIjtcbmltcG9ydCBQb2xsQ3JlYXRlRGlhbG9nIGZyb20gXCIuLi9lbGVtZW50cy9Qb2xsQ3JlYXRlRGlhbG9nXCI7XG5pbXBvcnQgeyBNYXRyaXhDbGllbnRQZWcgfSBmcm9tIFwiLi4vLi4vLi4vTWF0cml4Q2xpZW50UGVnXCI7XG5pbXBvcnQgU3Bpbm5lciBmcm9tIFwiLi4vZWxlbWVudHMvU3Bpbm5lclwiO1xuaW1wb3J0IHsgUG9sbE9wdGlvbiB9IGZyb20gXCIuLi9wb2xscy9Qb2xsT3B0aW9uXCI7XG5cbmludGVyZmFjZSBJU3RhdGUge1xuICAgIHBvbGw/OiBQb2xsO1xuICAgIC8vIHBvbGwgaW5zdGFuY2UgaGFzIGZldGNoZWQgYXQgbGVhc3Qgb25lIHBhZ2Ugb2YgcmVzcG9uc2VzXG4gICAgcG9sbEluaXRpYWxpc2VkOiBib29sZWFuO1xuICAgIHNlbGVjdGVkPzogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZDsgLy8gV2hpY2ggb3B0aW9uIHdhcyBjbGlja2VkIGJ5IHRoZSBsb2NhbCB1c2VyXG4gICAgdm90ZVJlbGF0aW9ucz86IFJlbGF0aW9uczsgLy8gVm90aW5nIChyZXNwb25zZSkgZXZlbnRzXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVWb3RlUmVsYXRpb25zKGdldFJlbGF0aW9uc0ZvckV2ZW50OiBHZXRSZWxhdGlvbnNGb3JFdmVudCwgZXZlbnRJZDogc3RyaW5nKTogUmVsYXRlZFJlbGF0aW9ucyB7XG4gICAgY29uc3QgcmVsYXRpb25zTGlzdDogUmVsYXRpb25zW10gPSBbXTtcblxuICAgIGNvbnN0IHBvbGxSZXNwb25zZVJlbGF0aW9ucyA9IGdldFJlbGF0aW9uc0ZvckV2ZW50KGV2ZW50SWQsIFwibS5yZWZlcmVuY2VcIiwgTV9QT0xMX1JFU1BPTlNFLm5hbWUpO1xuICAgIGlmIChwb2xsUmVzcG9uc2VSZWxhdGlvbnMpIHtcbiAgICAgICAgcmVsYXRpb25zTGlzdC5wdXNoKHBvbGxSZXNwb25zZVJlbGF0aW9ucyk7XG4gICAgfVxuXG4gICAgY29uc3QgcG9sbFJlc3Bvc25zZUFsdFJlbGF0aW9ucyA9IGdldFJlbGF0aW9uc0ZvckV2ZW50KGV2ZW50SWQsIFwibS5yZWZlcmVuY2VcIiwgTV9QT0xMX1JFU1BPTlNFLmFsdE5hbWUpO1xuICAgIGlmIChwb2xsUmVzcG9zbnNlQWx0UmVsYXRpb25zKSB7XG4gICAgICAgIHJlbGF0aW9uc0xpc3QucHVzaChwb2xsUmVzcG9zbnNlQWx0UmVsYXRpb25zKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFJlbGF0ZWRSZWxhdGlvbnMocmVsYXRpb25zTGlzdCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmaW5kVG9wQW5zd2VyKHBvbGxFdmVudDogTWF0cml4RXZlbnQsIHZvdGVSZWxhdGlvbnM6IFJlbGF0aW9ucyk6IHN0cmluZyB7XG4gICAgY29uc3QgcG9sbEV2ZW50SWQgPSBwb2xsRXZlbnQuZ2V0SWQoKTtcbiAgICBpZiAoIXBvbGxFdmVudElkKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKFxuICAgICAgICAgICAgXCJmaW5kVG9wQW5zd2VyOiBQb2xsIGV2ZW50IG5lZWRzIGFuIGV2ZW50IElEIHRvIGZldGNoIHJlbGF0aW9ucyBpbiBvcmRlciB0byBkZXRlcm1pbmUgXCIgK1xuICAgICAgICAgICAgICAgIFwidGhlIHRvcCBhbnN3ZXIgLSBhc3N1bWluZyBubyBiZXN0IGFuc3dlclwiLFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gXCJcIjtcbiAgICB9XG5cbiAgICBjb25zdCBwb2xsID0gcG9sbEV2ZW50LnVuc3RhYmxlRXh0ZW5zaWJsZUV2ZW50IGFzIFBvbGxTdGFydEV2ZW50O1xuICAgIGlmICghcG9sbD8uaXNFcXVpdmFsZW50VG8oTV9QT0xMX1NUQVJUKSkge1xuICAgICAgICBsb2dnZXIud2FybihcIkZhaWxlZCB0byBwYXJzZSBwb2xsIHRvIGRldGVybWluZSB0b3AgYW5zd2VyIC0gYXNzdW1pbmcgbm8gYmVzdCBhbnN3ZXJcIik7XG4gICAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cblxuICAgIGNvbnN0IGZpbmRBbnN3ZXJUZXh0ID0gKGFuc3dlcklkOiBzdHJpbmcpOiBzdHJpbmcgPT4ge1xuICAgICAgICByZXR1cm4gcG9sbC5hbnN3ZXJzLmZpbmQoKGEpID0+IGEuaWQgPT09IGFuc3dlcklkKT8udGV4dCA/PyBcIlwiO1xuICAgIH07XG5cbiAgICBjb25zdCB1c2VyVm90ZXM6IE1hcDxzdHJpbmcsIFVzZXJWb3RlPiA9IGNvbGxlY3RVc2VyVm90ZXMoYWxsVm90ZXModm90ZVJlbGF0aW9ucykpO1xuXG4gICAgY29uc3Qgdm90ZXM6IE1hcDxzdHJpbmcsIG51bWJlcj4gPSBjb3VudFZvdGVzKHVzZXJWb3RlcywgcG9sbCk7XG4gICAgY29uc3QgaGlnaGVzdFNjb3JlOiBudW1iZXIgPSBNYXRoLm1heCguLi52b3Rlcy52YWx1ZXMoKSk7XG5cbiAgICBjb25zdCBiZXN0QW5zd2VySWRzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgW2Fuc3dlcklkLCBzY29yZV0gb2Ygdm90ZXMpIHtcbiAgICAgICAgaWYgKHNjb3JlID09IGhpZ2hlc3RTY29yZSkge1xuICAgICAgICAgICAgYmVzdEFuc3dlcklkcy5wdXNoKGFuc3dlcklkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGJlc3RBbnN3ZXJUZXh0cyA9IGJlc3RBbnN3ZXJJZHMubWFwKGZpbmRBbnN3ZXJUZXh0KTtcblxuICAgIHJldHVybiBmb3JtYXRMaXN0KGJlc3RBbnN3ZXJUZXh0cywgMyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1BvbGxFbmRlZChwb2xsRXZlbnQ6IE1hdHJpeEV2ZW50LCBtYXRyaXhDbGllbnQ6IE1hdHJpeENsaWVudCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHJvb20gPSBtYXRyaXhDbGllbnQuZ2V0Um9vbShwb2xsRXZlbnQuZ2V0Um9vbUlkKCkpO1xuICAgIGNvbnN0IHBvbGwgPSByb29tPy5wb2xscy5nZXQocG9sbEV2ZW50LmdldElkKCkhKTtcbiAgICBpZiAoIXBvbGwgfHwgcG9sbC5pc0ZldGNoaW5nUmVzcG9uc2VzKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHBvbGwuaXNFbmRlZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBvbGxBbHJlYWR5SGFzVm90ZXMobXhFdmVudDogTWF0cml4RXZlbnQsIGdldFJlbGF0aW9uc0ZvckV2ZW50PzogR2V0UmVsYXRpb25zRm9yRXZlbnQpOiBib29sZWFuIHtcbiAgICBpZiAoIWdldFJlbGF0aW9uc0ZvckV2ZW50KSByZXR1cm4gZmFsc2U7XG5cbiAgICBjb25zdCBldmVudElkID0gbXhFdmVudC5nZXRJZCgpO1xuICAgIGlmICghZXZlbnRJZCkgcmV0dXJuIGZhbHNlO1xuXG4gICAgY29uc3Qgdm90ZVJlbGF0aW9ucyA9IGNyZWF0ZVZvdGVSZWxhdGlvbnMoZ2V0UmVsYXRpb25zRm9yRXZlbnQsIGV2ZW50SWQpO1xuICAgIHJldHVybiB2b3RlUmVsYXRpb25zLmdldFJlbGF0aW9ucygpLmxlbmd0aCA+IDA7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBsYXVuY2hQb2xsRWRpdG9yKG14RXZlbnQ6IE1hdHJpeEV2ZW50LCBnZXRSZWxhdGlvbnNGb3JFdmVudD86IEdldFJlbGF0aW9uc0ZvckV2ZW50KTogdm9pZCB7XG4gICAgY29uc3Qgcm9vbSA9IE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCkuZ2V0Um9vbShteEV2ZW50LmdldFJvb21JZCgpKTtcbiAgICBpZiAocG9sbEFscmVhZHlIYXNWb3RlcyhteEV2ZW50LCBnZXRSZWxhdGlvbnNGb3JFdmVudCkpIHtcbiAgICAgICAgTW9kYWwuY3JlYXRlRGlhbG9nKEVycm9yRGlhbG9nLCB7XG4gICAgICAgICAgICB0aXRsZTogX3QoXCJwb2xsfHVuYWJsZV9lZGl0X3RpdGxlXCIpLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IF90KFwicG9sbHx1bmFibGVfZWRpdF9kZXNjcmlwdGlvblwiKSxcbiAgICAgICAgfSk7XG4gICAgfSBlbHNlIGlmIChyb29tKSB7XG4gICAgICAgIE1vZGFsLmNyZWF0ZURpYWxvZyhcbiAgICAgICAgICAgIFBvbGxDcmVhdGVEaWFsb2csXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgcm9vbSxcbiAgICAgICAgICAgICAgICB0aHJlYWRJZDogbXhFdmVudC5nZXRUaHJlYWQoKT8uaWQsXG4gICAgICAgICAgICAgICAgZWRpdGluZ014RXZlbnQ6IG14RXZlbnQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCJteF9Db21wb3VuZERpYWxvZ1wiLFxuICAgICAgICAgICAgZmFsc2UsIC8vIGlzUHJpb3JpdHlNb2RhbFxuICAgICAgICAgICAgdHJ1ZSwgLy8gaXNTdGF0aWNNb2RhbFxuICAgICAgICApO1xuICAgIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTVBvbGxCb2R5IGV4dGVuZHMgUmVhY3QuQ29tcG9uZW50PElCb2R5UHJvcHMsIElTdGF0ZT4ge1xuICAgIHB1YmxpYyBzdGF0aWMgY29udGV4dFR5cGUgPSBNYXRyaXhDbGllbnRDb250ZXh0O1xuICAgIHB1YmxpYyBkZWNsYXJlIGNvbnRleHQ6IFJlYWN0LkNvbnRleHRUeXBlPHR5cGVvZiBNYXRyaXhDbGllbnRDb250ZXh0PjtcbiAgICBwcml2YXRlIHNlZW5FdmVudElkczogc3RyaW5nW10gPSBbXTsgLy8gRXZlbnRzIHdlIGhhdmUgYWxyZWFkeSBzZWVuXG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHJvcHM6IElCb2R5UHJvcHMsIGNvbnRleHQ6IFJlYWN0LkNvbnRleHRUeXBlPHR5cGVvZiBNYXRyaXhDbGllbnRDb250ZXh0Pikge1xuICAgICAgICBzdXBlcihwcm9wcywgY29udGV4dCk7XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgICAgICAgIHNlbGVjdGVkOiBudWxsLFxuICAgICAgICAgICAgcG9sbEluaXRpYWxpc2VkOiBmYWxzZSxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY29tcG9uZW50RGlkTW91bnQoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHJvb20gPSB0aGlzLmNvbnRleHQ/LmdldFJvb20odGhpcy5wcm9wcy5teEV2ZW50LmdldFJvb21JZCgpKTtcbiAgICAgICAgY29uc3QgcG9sbCA9IHJvb20/LnBvbGxzLmdldCh0aGlzLnByb3BzLm14RXZlbnQuZ2V0SWQoKSEpO1xuICAgICAgICBpZiAocG9sbCkge1xuICAgICAgICAgICAgdGhpcy5zZXRQb2xsSW5zdGFuY2UocG9sbCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByb29tPy5vbihQb2xsRXZlbnQuTmV3LCB0aGlzLnNldFBvbGxJbnN0YW5jZS5iaW5kKHRoaXMpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBjb21wb25lbnRXaWxsVW5tb3VudCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcnMoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHNldFBvbGxJbnN0YW5jZShwb2xsOiBQb2xsKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmIChwb2xsLnBvbGxJZCAhPT0gdGhpcy5wcm9wcy5teEV2ZW50LmdldElkKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNldFN0YXRlKHsgcG9sbCB9LCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmFkZExpc3RlbmVycygpO1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgcmVzcG9uc2VzID0gYXdhaXQgcG9sbC5nZXRSZXNwb25zZXMoKTtcbiAgICAgICAgY29uc3Qgdm90ZVJlbGF0aW9ucyA9IHJlc3BvbnNlcztcblxuICAgICAgICB0aGlzLnNldFN0YXRlKHsgcG9sbEluaXRpYWxpc2VkOiB0cnVlLCB2b3RlUmVsYXRpb25zIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgYWRkTGlzdGVuZXJzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnN0YXRlLnBvbGw/Lm9uKFBvbGxFdmVudC5SZXNwb25zZXMsIHRoaXMub25SZXNwb25zZXNDaGFuZ2UpO1xuICAgICAgICB0aGlzLnN0YXRlLnBvbGw/Lm9uKFBvbGxFdmVudC5FbmQsIHRoaXMub25SZWxhdGlvbnNDaGFuZ2UpO1xuICAgICAgICB0aGlzLnN0YXRlLnBvbGw/Lm9uKFBvbGxFdmVudC5VbmRlY3J5cHRhYmxlUmVsYXRpb25zLCB0aGlzLnJlbmRlci5iaW5kKHRoaXMpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHJlbW92ZUxpc3RlbmVycygpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUucG9sbCkge1xuICAgICAgICAgICAgdGhpcy5zdGF0ZS5wb2xsLm9mZihQb2xsRXZlbnQuUmVzcG9uc2VzLCB0aGlzLm9uUmVzcG9uc2VzQ2hhbmdlKTtcbiAgICAgICAgICAgIHRoaXMuc3RhdGUucG9sbC5vZmYoUG9sbEV2ZW50LkVuZCwgdGhpcy5vblJlbGF0aW9uc0NoYW5nZSk7XG4gICAgICAgICAgICB0aGlzLnN0YXRlLnBvbGwub2ZmKFBvbGxFdmVudC5VbmRlY3J5cHRhYmxlUmVsYXRpb25zLCB0aGlzLnJlbmRlci5iaW5kKHRoaXMpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgb25SZXNwb25zZXNDaGFuZ2UgPSAocmVzcG9uc2VzOiBSZWxhdGlvbnMpOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IHZvdGVSZWxhdGlvbnM6IHJlc3BvbnNlcyB9KTtcbiAgICAgICAgdGhpcy5vblJlbGF0aW9uc0NoYW5nZSgpO1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uUmVsYXRpb25zQ2hhbmdlID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICAvLyBXZSBob2xkIFJlbGF0aW9ucyBpbiBvdXIgc3RhdGUsIGFuZCB0aGV5IGNoYW5nZWQgdW5kZXIgdXMuXG4gICAgICAgIC8vIENoZWNrIHdoZXRoZXIgd2Ugc2hvdWxkIGRlbGV0ZSBvdXIgc2VsZWN0aW9uLCBhbmQgdGhlblxuICAgICAgICAvLyByZS1yZW5kZXIuXG4gICAgICAgIC8vIE5vdGU6IHJlLXJlbmRlcmluZyBpcyBhIHNpZGUgZWZmZWN0IG9mIHVuc2VsZWN0SWZOZXdFdmVudEZyb21NZSgpLlxuICAgICAgICB0aGlzLnVuc2VsZWN0SWZOZXdFdmVudEZyb21NZSgpO1xuICAgIH07XG5cbiAgICBwcml2YXRlIHNlbGVjdE9wdGlvbihhbnN3ZXJJZDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlLnBvbGw/LmlzRW5kZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB1c2VyVm90ZXMgPSB0aGlzLmNvbGxlY3RVc2VyVm90ZXMoKTtcbiAgICAgICAgY29uc3QgdXNlcklkID0gdGhpcy5jb250ZXh0LmdldFNhZmVVc2VySWQoKTtcbiAgICAgICAgY29uc3QgbXlWb3RlID0gdXNlclZvdGVzLmdldCh1c2VySWQpPy5hbnN3ZXJzWzBdO1xuICAgICAgICBpZiAoYW5zd2VySWQgPT09IG15Vm90ZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBQb2xsUmVzcG9uc2VFdmVudC5mcm9tKFthbnN3ZXJJZF0sIHRoaXMucHJvcHMubXhFdmVudC5nZXRJZCgpISkuc2VyaWFsaXplKCk7XG5cbiAgICAgICAgdGhpcy5jb250ZXh0XG4gICAgICAgICAgICAuc2VuZEV2ZW50KFxuICAgICAgICAgICAgICAgIHRoaXMucHJvcHMubXhFdmVudC5nZXRSb29tSWQoKSEsXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UudHlwZSBhcyBrZXlvZiBUaW1lbGluZUV2ZW50cyxcbiAgICAgICAgICAgICAgICByZXNwb25zZS5jb250ZW50IGFzIFRpbWVsaW5lRXZlbnRzW2tleW9mIFRpbWVsaW5lRXZlbnRzXSxcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIC5jYXRjaCgoZTogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkZhaWxlZCB0byBzdWJtaXQgcG9sbCByZXNwb25zZSBldmVudDpcIiwgZSk7XG5cbiAgICAgICAgICAgICAgICBNb2RhbC5jcmVhdGVEaWFsb2coRXJyb3JEaWFsb2csIHtcbiAgICAgICAgICAgICAgICAgICAgdGl0bGU6IF90KFwicG9sbHxlcnJvcl92b3RpbmdfdGl0bGVcIiksXG4gICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBfdChcInBvbGx8ZXJyb3Jfdm90aW5nX2Rlc2NyaXB0aW9uXCIpLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IHNlbGVjdGVkOiBhbnN3ZXJJZCB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyB1c2VySWQgLT4gVXNlclZvdGVcbiAgICAgKi9cbiAgICBwcml2YXRlIGNvbGxlY3RVc2VyVm90ZXMoKTogTWFwPHN0cmluZywgVXNlclZvdGU+IHtcbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlLnZvdGVSZWxhdGlvbnMgfHwgIXRoaXMuY29udGV4dCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBNYXA8c3RyaW5nLCBVc2VyVm90ZT4oKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29sbGVjdFVzZXJWb3RlcyhhbGxWb3Rlcyh0aGlzLnN0YXRlLnZvdGVSZWxhdGlvbnMpLCB0aGlzLmNvbnRleHQuZ2V0VXNlcklkKCksIHRoaXMuc3RhdGUuc2VsZWN0ZWQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIElmIHdlJ3ZlIGp1c3QgcmVjZWl2ZWQgYSBuZXcgZXZlbnQgdGhhdCB3ZSBoYWRuJ3Qgc2VlblxuICAgICAqIGJlZm9yZSwgYW5kIHRoYXQgZXZlbnQgaXMgbWUgdm90aW5nIChlLmcuIGZyb20gYSBkaWZmZXJlbnRcbiAgICAgKiBkZXZpY2UpIHRoZW4gZm9yZ2V0IHdoZW4gdGhlIGxvY2FsIHVzZXIgc2VsZWN0ZWQuXG4gICAgICpcbiAgICAgKiBFaXRoZXIgd2F5LCBjYWxscyBzZXRTdGF0ZSB0byB1cGRhdGUgb3VyIGxpc3Qgb2YgZXZlbnRzIHdlXG4gICAgICogaGF2ZSBhbHJlYWR5IHNlZW4uXG4gICAgICovXG4gICAgcHJpdmF0ZSB1bnNlbGVjdElmTmV3RXZlbnRGcm9tTWUoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHJlbGF0aW9ucyA9IHRoaXMuc3RhdGUudm90ZVJlbGF0aW9ucz8uZ2V0UmVsYXRpb25zKCkgfHwgW107XG4gICAgICAgIGNvbnN0IG5ld0V2ZW50czogTWF0cml4RXZlbnRbXSA9IHJlbGF0aW9ucy5maWx0ZXIoXG4gICAgICAgICAgICAobXhFdmVudDogTWF0cml4RXZlbnQpID0+ICF0aGlzLnNlZW5FdmVudElkcy5pbmNsdWRlcyhteEV2ZW50LmdldElkKCkhKSxcbiAgICAgICAgKTtcbiAgICAgICAgbGV0IG5ld1NlbGVjdGVkID0gdGhpcy5zdGF0ZS5zZWxlY3RlZDtcblxuICAgICAgICBpZiAobmV3RXZlbnRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgbXhFdmVudCBvZiBuZXdFdmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAobXhFdmVudC5nZXRTZW5kZXIoKSA9PT0gdGhpcy5jb250ZXh0LmdldFVzZXJJZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld1NlbGVjdGVkID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbmV3RXZlbnRJZHMgPSBuZXdFdmVudHMubWFwKChteEV2ZW50OiBNYXRyaXhFdmVudCkgPT4gbXhFdmVudC5nZXRJZCgpISk7XG4gICAgICAgIHRoaXMuc2VlbkV2ZW50SWRzID0gdGhpcy5zZWVuRXZlbnRJZHMuY29uY2F0KG5ld0V2ZW50SWRzKTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IHNlbGVjdGVkOiBuZXdTZWxlY3RlZCB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHRvdGFsVm90ZXMoY29sbGVjdGVkVm90ZXM6IE1hcDxzdHJpbmcsIG51bWJlcj4pOiBudW1iZXIge1xuICAgICAgICBsZXQgc3VtID0gMDtcbiAgICAgICAgZm9yIChjb25zdCB2IG9mIGNvbGxlY3RlZFZvdGVzLnZhbHVlcygpKSB7XG4gICAgICAgICAgICBzdW0gKz0gdjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3VtO1xuICAgIH1cblxuICAgIHB1YmxpYyByZW5kZXIoKTogUmVhY3ROb2RlIHtcbiAgICAgICAgY29uc3QgeyBwb2xsLCBwb2xsSW5pdGlhbGlzZWQgfSA9IHRoaXMuc3RhdGU7XG4gICAgICAgIGlmICghcG9sbD8ucG9sbEV2ZW50KSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHBvbGxFdmVudCA9IHBvbGwucG9sbEV2ZW50O1xuXG4gICAgICAgIGNvbnN0IHBvbGxJZCA9IHRoaXMucHJvcHMubXhFdmVudC5nZXRJZCgpITtcbiAgICAgICAgY29uc3QgaXNGZXRjaGluZ1Jlc3BvbnNlcyA9ICFwb2xsSW5pdGlhbGlzZWQgfHwgcG9sbC5pc0ZldGNoaW5nUmVzcG9uc2VzO1xuICAgICAgICBjb25zdCB1c2VyVm90ZXMgPSB0aGlzLmNvbGxlY3RVc2VyVm90ZXMoKTtcbiAgICAgICAgY29uc3Qgdm90ZXMgPSBjb3VudFZvdGVzKHVzZXJWb3RlcywgcG9sbEV2ZW50KTtcbiAgICAgICAgY29uc3QgdG90YWxWb3RlcyA9IHRoaXMudG90YWxWb3Rlcyh2b3Rlcyk7XG4gICAgICAgIGNvbnN0IHdpbkNvdW50ID0gTWF0aC5tYXgoLi4udm90ZXMudmFsdWVzKCkpO1xuICAgICAgICBjb25zdCB1c2VySWQgPSB0aGlzLmNvbnRleHQuZ2V0U2FmZVVzZXJJZCgpO1xuICAgICAgICBjb25zdCBteVZvdGUgPSB1c2VyVm90ZXM/LmdldCh1c2VySWQpPy5hbnN3ZXJzWzBdO1xuICAgICAgICBjb25zdCBkaXNjbG9zZWQgPSBNX1BPTExfS0lORF9ESVNDTE9TRUQubWF0Y2hlcyhwb2xsRXZlbnQua2luZC5uYW1lKTtcblxuICAgICAgICAvLyBEaXNjbG9zZWQ6IHZvdGVzIGFyZSBoaWRkZW4gdW50aWwgSSB2b3RlIG9yIHRoZSBwb2xsIGVuZHNcbiAgICAgICAgLy8gVW5kaXNjbG9zZWQ6IHZvdGVzIGFyZSBoaWRkZW4gdW50aWwgcG9sbCBlbmRzXG4gICAgICAgIGNvbnN0IHNob3dSZXN1bHRzID0gcG9sbC5pc0VuZGVkIHx8IChkaXNjbG9zZWQgJiYgbXlWb3RlICE9PSB1bmRlZmluZWQpO1xuXG4gICAgICAgIGxldCB0b3RhbFRleHQ6IHN0cmluZztcbiAgICAgICAgaWYgKHNob3dSZXN1bHRzICYmIHBvbGwudW5kZWNyeXB0YWJsZVJlbGF0aW9uc0NvdW50KSB7XG4gICAgICAgICAgICB0b3RhbFRleHQgPSBfdChcInBvbGx8dG90YWxfZGVjcnlwdGlvbl9lcnJvcnNcIik7XG4gICAgICAgIH0gZWxzZSBpZiAocG9sbC5pc0VuZGVkKSB7XG4gICAgICAgICAgICB0b3RhbFRleHQgPSBfdChcInJpZ2h0X3BhbmVsfHBvbGx8ZmluYWxfcmVzdWx0XCIsIHsgY291bnQ6IHRvdGFsVm90ZXMgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAoIWRpc2Nsb3NlZCkge1xuICAgICAgICAgICAgdG90YWxUZXh0ID0gX3QoXCJwb2xsfHRvdGFsX25vdF9lbmRlZFwiKTtcbiAgICAgICAgfSBlbHNlIGlmIChteVZvdGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYgKHRvdGFsVm90ZXMgPT09IDApIHtcbiAgICAgICAgICAgICAgICB0b3RhbFRleHQgPSBfdChcInBvbGx8dG90YWxfbm9fdm90ZXNcIik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRvdGFsVGV4dCA9IF90KFwicG9sbHx0b3RhbF9uX3ZvdGVzXCIsIHsgY291bnQ6IHRvdGFsVm90ZXMgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0b3RhbFRleHQgPSBfdChcInBvbGx8dG90YWxfbl92b3Rlc192b3RlZFwiLCB7IGNvdW50OiB0b3RhbFZvdGVzIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZWRpdGVkU3BhbiA9IHRoaXMucHJvcHMubXhFdmVudC5yZXBsYWNpbmdFdmVudCgpID8gKFxuICAgICAgICAgICAgPHNwYW4gY2xhc3NOYW1lPVwibXhfTVBvbGxCb2R5X2VkaXRlZFwiPiAoe190KFwiY29tbW9ufGVkaXRlZFwiKX0pPC9zcGFuPlxuICAgICAgICApIDogbnVsbDtcblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9NUG9sbEJvZHlcIj5cbiAgICAgICAgICAgICAgICA8aDIgZGF0YS10ZXN0aWQ9XCJwb2xsUXVlc3Rpb25cIj5cbiAgICAgICAgICAgICAgICAgICAge3BvbGxFdmVudC5xdWVzdGlvbi50ZXh0fVxuICAgICAgICAgICAgICAgICAgICB7ZWRpdGVkU3Bhbn1cbiAgICAgICAgICAgICAgICA8L2gyPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwibXhfTVBvbGxCb2R5X2FsbE9wdGlvbnNcIj5cbiAgICAgICAgICAgICAgICAgICAge3BvbGxFdmVudC5hbnN3ZXJzLm1hcCgoYW5zd2VyOiBQb2xsQW5zd2VyU3ViZXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBhbnN3ZXJWb3RlcyA9IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaG93UmVzdWx0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuc3dlclZvdGVzID0gdm90ZXMuZ2V0KGFuc3dlci5pZCkgPz8gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2hlY2tlZCA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKCFwb2xsLmlzRW5kZWQgJiYgbXlWb3RlID09PSBhbnN3ZXIuaWQpIHx8IChwb2xsLmlzRW5kZWQgJiYgYW5zd2VyVm90ZXMgPT09IHdpbkNvdW50KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8UG9sbE9wdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXk9e2Fuc3dlci5pZH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9sbElkPXtwb2xsSWR9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuc3dlcj17YW5zd2VyfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0NoZWNrZWQ9e2NoZWNrZWR9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzRW5kZWQ9e3BvbGwuaXNFbmRlZH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdm90ZUNvdW50PXthbnN3ZXJWb3Rlc31cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxWb3RlQ291bnQ9e3RvdGFsVm90ZXN9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BsYXlWb3RlQ291bnQ9e3Nob3dSZXN1bHRzfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbk9wdGlvblNlbGVjdGVkPXt0aGlzLnNlbGVjdE9wdGlvbi5iaW5kKHRoaXMpfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9KX1cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8ZGl2IGRhdGEtdGVzdGlkPVwidG90YWxWb3Rlc1wiIGNsYXNzTmFtZT1cIm14X01Qb2xsQm9keV90b3RhbFZvdGVzXCI+XG4gICAgICAgICAgICAgICAgICAgIHt0b3RhbFRleHR9XG4gICAgICAgICAgICAgICAgICAgIHtpc0ZldGNoaW5nUmVzcG9uc2VzICYmIDxTcGlubmVyIHc9ezE2fSBoPXsxNn0gLz59XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgKTtcbiAgICB9XG59XG5leHBvcnQgY2xhc3MgVXNlclZvdGUge1xuICAgIHB1YmxpYyBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHVibGljIHJlYWRvbmx5IHRzOiBudW1iZXIsXG4gICAgICAgIHB1YmxpYyByZWFkb25seSBzZW5kZXI6IHN0cmluZyxcbiAgICAgICAgcHVibGljIHJlYWRvbmx5IGFuc3dlcnM6IHN0cmluZ1tdLFxuICAgICkge31cbn1cblxuZnVuY3Rpb24gdXNlclJlc3BvbnNlRnJvbVBvbGxSZXNwb25zZUV2ZW50KGV2ZW50OiBNYXRyaXhFdmVudCk6IFVzZXJWb3RlIHtcbiAgICBjb25zdCByZXNwb25zZSA9IGV2ZW50LnVuc3RhYmxlRXh0ZW5zaWJsZUV2ZW50IGFzIFBvbGxSZXNwb25zZUV2ZW50O1xuICAgIGlmICghcmVzcG9uc2U/LmlzRXF1aXZhbGVudFRvKE1fUE9MTF9SRVNQT05TRSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRmFpbGVkIHRvIHBhcnNlIFBvbGwgUmVzcG9uc2UgRXZlbnQgdG8gZGV0ZXJtaW5lIHVzZXIgcmVzcG9uc2VcIik7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBVc2VyVm90ZShldmVudC5nZXRUcygpLCBldmVudC5nZXRTZW5kZXIoKSEsIHJlc3BvbnNlLmFuc3dlcklkcyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhbGxWb3Rlcyh2b3RlUmVsYXRpb25zOiBSZWxhdGlvbnMpOiBBcnJheTxVc2VyVm90ZT4ge1xuICAgIGlmICh2b3RlUmVsYXRpb25zKSB7XG4gICAgICAgIHJldHVybiB2b3RlUmVsYXRpb25zLmdldFJlbGF0aW9ucygpLm1hcCh1c2VyUmVzcG9uc2VGcm9tUG9sbFJlc3BvbnNlRXZlbnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICB9XG59XG5cbi8qKlxuICogRmlndXJlIG91dCB0aGUgY29ycmVjdCB2b3RlIGZvciBlYWNoIHVzZXIuXG4gKiBAcGFyYW0gdXNlclJlc3BvbnNlcyBjdXJyZW50IHZvdGUgcmVzcG9uc2VzIGluIHRoZSBwb2xsXG4gKiBAcGFyYW0ge3N0cmluZz99IHVzZXJJZCBUaGUgdXNlcklkIGZvciB3aGljaCB0aGUgYHNlbGVjdGVkYCBvcHRpb24gd2lsbCBhcHBseSB0by5cbiAqICAgICAgICAgICAgICAgICAgU2hvdWxkIGJlIHNldCB0byB0aGUgY3VycmVudCB1c2VyIElELlxuICogQHBhcmFtIHtzdHJpbmc/fSBzZWxlY3RlZCBMb2NhbCBlY2hvIHNlbGVjdGVkIG9wdGlvbiBmb3IgdGhlIHVzZXJJZFxuICogQHJldHVybnMgYSBNYXAgb2YgdXNlciBJRCB0byB0aGVpciB2b3RlIGluZm9cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbGxlY3RVc2VyVm90ZXMoXG4gICAgdXNlclJlc3BvbnNlczogQXJyYXk8VXNlclZvdGU+LFxuICAgIHVzZXJJZD86IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQsXG4gICAgc2VsZWN0ZWQ/OiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkLFxuKTogTWFwPHN0cmluZywgVXNlclZvdGU+IHtcbiAgICBjb25zdCB1c2VyVm90ZXM6IE1hcDxzdHJpbmcsIFVzZXJWb3RlPiA9IG5ldyBNYXAoKTtcblxuICAgIGZvciAoY29uc3QgcmVzcG9uc2Ugb2YgdXNlclJlc3BvbnNlcykge1xuICAgICAgICBjb25zdCBvdGhlclJlc3BvbnNlID0gdXNlclZvdGVzLmdldChyZXNwb25zZS5zZW5kZXIpO1xuICAgICAgICBpZiAoIW90aGVyUmVzcG9uc2UgfHwgb3RoZXJSZXNwb25zZS50cyA8IHJlc3BvbnNlLnRzKSB7XG4gICAgICAgICAgICB1c2VyVm90ZXMuc2V0KHJlc3BvbnNlLnNlbmRlciwgcmVzcG9uc2UpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHNlbGVjdGVkICYmIHVzZXJJZCkge1xuICAgICAgICB1c2VyVm90ZXMuc2V0KHVzZXJJZCwgbmV3IFVzZXJWb3RlKDAsIHVzZXJJZCwgW3NlbGVjdGVkXSkpO1xuICAgIH1cblxuICAgIHJldHVybiB1c2VyVm90ZXM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjb3VudFZvdGVzKHVzZXJWb3RlczogTWFwPHN0cmluZywgVXNlclZvdGU+LCBwb2xsU3RhcnQ6IFBvbGxTdGFydEV2ZW50KTogTWFwPHN0cmluZywgbnVtYmVyPiB7XG4gICAgY29uc3QgY29sbGVjdGVkID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcblxuICAgIGZvciAoY29uc3QgcmVzcG9uc2Ugb2YgdXNlclZvdGVzLnZhbHVlcygpKSB7XG4gICAgICAgIGNvbnN0IHRlbXBSZXNwb25zZSA9IFBvbGxSZXNwb25zZUV2ZW50LmZyb20ocmVzcG9uc2UuYW5zd2VycywgXCIkaXJyZWxldmFudFwiKTtcbiAgICAgICAgdGVtcFJlc3BvbnNlLnZhbGlkYXRlQWdhaW5zdChwb2xsU3RhcnQpO1xuICAgICAgICBpZiAoIXRlbXBSZXNwb25zZS5zcG9pbGVkKSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGFuc3dlcklkIG9mIHRlbXBSZXNwb25zZS5hbnN3ZXJJZHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoY29sbGVjdGVkLmhhcyhhbnN3ZXJJZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29sbGVjdGVkLnNldChhbnN3ZXJJZCwgY29sbGVjdGVkLmdldChhbnN3ZXJJZCkhICsgMSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29sbGVjdGVkLnNldChhbnN3ZXJJZCwgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3RlZDtcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFRQSxJQUFBQSxNQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxPQUFBLEdBQUFELE9BQUE7QUFDQSxJQUFBRSxPQUFBLEdBQUFGLE9BQUE7QUFXQSxJQUFBRyxpQkFBQSxHQUFBSCxPQUFBO0FBRUEsSUFBQUksa0JBQUEsR0FBQUosT0FBQTtBQUVBLElBQUFLLGdCQUFBLEdBQUFMLE9BQUE7QUFDQSxJQUFBTSxNQUFBLEdBQUFQLHNCQUFBLENBQUFDLE9BQUE7QUFFQSxJQUFBTyxnQkFBQSxHQUFBUCxPQUFBO0FBQ0EsSUFBQVEsb0JBQUEsR0FBQVQsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFTLFlBQUEsR0FBQVYsc0JBQUEsQ0FBQUMsT0FBQTtBQUVBLElBQUFVLGlCQUFBLEdBQUFYLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBVyxnQkFBQSxHQUFBWCxPQUFBO0FBQ0EsSUFBQVksUUFBQSxHQUFBYixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQWEsV0FBQSxHQUFBYixPQUFBO0FBbkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQXVDTyxTQUFTYyxtQkFBbUJBLENBQUNDLG9CQUEwQyxFQUFFQyxPQUFlLEVBQW9CO0VBQy9HLE1BQU1DLGFBQTBCLEdBQUcsRUFBRTtFQUVyQyxNQUFNQyxxQkFBcUIsR0FBR0gsb0JBQW9CLENBQUNDLE9BQU8sRUFBRSxhQUFhLEVBQUVHLHVCQUFlLENBQUNDLElBQUksQ0FBQztF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