UNPKG

@firestone-hs/replay-parser

Version:

This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.2.9.

207 lines 35.3 kB
import { Injectable } from '@angular/core'; import { CardType, GameTag, Zone, isBattlegrounds } from '@firestone-hs/reference-data'; import { Entity } from '../../models/game/entity'; import { GameEntity } from '../../models/game/game-entity'; import { PlayerEntity } from '../../models/game/player-entity'; import { FullEntityHistoryItem } from '../../models/history/full-entity-history-item'; import { GameHistoryItem } from '../../models/history/game-history-item'; import { PlayerHistoryItem } from '../../models/history/player-history-item'; import { ShowEntityHistoryItem } from '../../models/history/show-entity-history-item'; import { TagChangeHistoryItem } from '../../models/history/tag-change-history-item'; import * as i0 from "@angular/core"; import * as i1 from "../all-cards.service"; export class GamePopulationService { constructor(allCards) { this.allCards = allCards; } initNewEntities(game, history, entityCardIdMapping) { // Map of entityId - entity definition // TODO: should we remove here all the SETASIDE / REMOVEDFROMGAME entities? const entities = game .getLatestParsedState() .filter((entity) => ![Zone.REMOVEDFROMGAME].includes(entity.getTag(GameTag.ZONE))); // console.debug('entities reduced from', game.getLatestParsedState().size, 'to', entities.size); const entitiesAfterInit = this.initializeEntities(history, entities); const entitiesAfterFillingCardIds = this.addMissingCardIds(entitiesAfterInit, entityCardIdMapping); const entitiesAfterMissingInfo = this.completeMissingInformation(history, entitiesAfterFillingCardIds); const entitiesAfterBasicData = this.addBasicData(entitiesAfterMissingInfo); return entitiesAfterBasicData; // return Game.createGame(game, { // entities: entitiesAfterBasicData, // } as Game); // return entitiesAfterBasicData; } initializeEntities(history, entities) { let result = entities; for (const item of history) { if (item instanceof PlayerHistoryItem) { result = this.initializePlayer(item, result); } else if (item instanceof GameHistoryItem) { result = this.initializeGame(item, result); } else if (item instanceof FullEntityHistoryItem) { result = this.initializeFullEntity(item, result); } else if (item instanceof ShowEntityHistoryItem) { result = this.initializeShowEntity(item, result); } } return result; } addMissingCardIds(entitiesAfterInit, entityCardIdMapping) { return entitiesAfterInit .map((entity, entityId) => { if (!entity.cardID) { return entity.update({ cardID: entityCardIdMapping.get(entityId), }); } return entity; }) .toMap(); } initializePlayer(historyItem, entities) { // Remove the battle tag if present const playerName = historyItem.entityDefintion.name.indexOf('#') !== -1 ? historyItem.entityDefintion.name.split('#')[0] : historyItem.entityDefintion.name; const entity = PlayerEntity.create({ id: historyItem.entityDefintion.id, playerId: historyItem.entityDefintion.playerID, accountHi: historyItem.accountHi, accountLo: historyItem.accountLo, name: playerName, isMainPlayer: historyItem.isMainPlayer, }).update(historyItem.entityDefintion); return entities.set(entity.id, entity); } initializeGame(historyItem, entities) { const base = Object.assign(new GameEntity(), { id: historyItem.entityDefintion.id, buildNumber: historyItem.buildNumber, formatType: historyItem.formatType, gameType: historyItem.gameType, scenarioID: historyItem.scenarioID, }); let entity = GameEntity.create(base).update(historyItem.entityDefintion); // Battlegrounds doesn't have the right board state set at start if (isBattlegrounds(historyItem.gameType)) { // // console.log('initializing game entity with visual state', entity.tags.toJS(), entity); entity = entity.updateTag(GameTag.BOARD_VISUAL_STATE, 1); // // console.log('updated', entity.tags.toJS(), entity); } return entities.set(entity.id, entity); } initializeFullEntity(historyItem, entities) { const newAttributes = {}; // We use the ShowEntity only to update the cardID at this stage // and for a few other tags. // Since we don't stop at mulligan stage, this means that otherwise // a lot of other entities will be created if (historyItem.entityDefintion.cardID) { newAttributes.cardID = historyItem.entityDefintion.cardID; } // if (historyItem.entityDefintion.id === 73 || historyItem.entityDefintion.id === 74) { // // // console.log('enriching', historyItem); // } const entity = entities .get(historyItem.entityDefintion.id, Entity.create({ id: historyItem.entityDefintion.id })) .update(newAttributes); return entities.set(entity.id, entity); } initializeShowEntity(historyItem, entities) { const newAttributes = {}; // Same here if (historyItem.entityDefintion.cardID) { newAttributes.cardID = historyItem.entityDefintion.cardID; } // if (historyItem.entityDefintion.id === 73 || historyItem.entityDefintion.id === 74) { // // // console.log('enriching', historyItem); // } const entity = entities .get(historyItem.entityDefintion.id, Entity.create({ id: historyItem.entityDefintion.id })) .update(newAttributes); return entities.set(entity.id, entity); } completeMissingInformation(history, entities) { let result = entities; for (const item of history) { if (item instanceof TagChangeHistoryItem) { result = this.addTagInformation(item, result); } if (item instanceof ShowEntityHistoryItem) { result = this.addEntityInformation(item, result); } } return result; } addTagInformation(item, entities) { // if (item.tag.entity === 73 || item.tag.entity === 74) { // // // console.log('enriching', item); // } if (item.tag.tag === GameTag.SECRET && item.tag.value === 1) { const entity = entities.get(item.tag.entity)?.update({ tags: { [GameTag[item.tag.tag]]: 1 } }); return !!entity ? entities.set(entity.id, entity) : entities; } else if (item.tag.tag === GameTag.QUEST && item.tag.value === 1) { const entity = entities.get(item.tag.entity)?.update({ tags: { [GameTag[item.tag.tag]]: 1 } }); return !!entity ? entities.set(entity.id, entity) : entities; } else if (item.tag.tag === GameTag.PARENT_CARD) { const entity = entities .get(item.tag.entity) ?.update({ tags: { [GameTag[item.tag.tag]]: item.tag.value } }); return !!entity ? entities.set(entity.id, entity) : entities; } return entities; } addEntityInformation(item, entities) { // if (item.entityDefintion.id === 73 || item.entityDefintion.id === 74) { // // // console.log('enriching', item); // } let result = entities; if (item.entityDefintion.tags[GameTag[GameTag.SECRET]] === 1) { const entity = entities.get(item.entityDefintion.id).update({ tags: { [GameTag[GameTag.SECRET]]: 1 }, }); result = entities.set(entity.id, entity); } const newTags = { [GameTag[GameTag.CREATOR]]: item.entityDefintion.tags[GameTag[GameTag.CREATOR]], [GameTag[GameTag.TAG_SCRIPT_DATA_NUM_1]]: item.entityDefintion.tags[GameTag[GameTag.TAG_SCRIPT_DATA_NUM_1]], [GameTag[GameTag.TAG_SCRIPT_DATA_NUM_2]]: item.entityDefintion.tags[GameTag[GameTag.TAG_SCRIPT_DATA_NUM_2]], }; const finalEntity = result.get(item.entityDefintion.id).update({ tags: newTags }); return result.set(finalEntity.id, finalEntity); } addBasicData(entities) { return entities .map((value) => { if (!value.cardID) { return value; } const card = this.allCards.getCard(value.cardID); let newTags = {}; if (card) { if (card.type === 'Spell' && !value.getTag(GameTag.CARDTYPE)) { newTags = { ...value.tags, [GameTag[GameTag.CARDTYPE]]: CardType.SPELL }; } if (card.type === 'Enchantment' && !value.getTag(GameTag.CARDTYPE)) { newTags = { ...value.tags, [GameTag[GameTag.CARDTYPE]]: CardType.ENCHANTMENT }; } } return value.update({ tags: newTags }); }) .toMap(); } } GamePopulationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.1", ngImport: i0, type: GamePopulationService, deps: [{ token: i1.AllCardsService }], target: i0.ɵɵFactoryTarget.Injectable }); GamePopulationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.1", ngImport: i0, type: GamePopulationService, providedIn: 'root' }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.1", ngImport: i0, type: GamePopulationService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }], ctorParameters: function () { return [{ type: i1.AllCardsService }]; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2FtZS1wb3B1bGF0aW9uLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9yZXBsYXktcGFyc2VyL3NyYy9saWIvc2VydmljZXMvZW50aXRpZXNwaXBlbGluZS9nYW1lLXBvcHVsYXRpb24uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUV4RixPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDbEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQzNELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUMvRCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSwrQ0FBK0MsQ0FBQztBQUN0RixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sd0NBQXdDLENBQUM7QUFFekUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sMENBQTBDLENBQUM7QUFDN0UsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sK0NBQStDLENBQUM7QUFDdEYsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sOENBQThDLENBQUM7OztBQVFwRixNQUFNLE9BQU8scUJBQXFCO0lBQ2pDLFlBQW9CLFFBQXlCO1FBQXpCLGFBQVEsR0FBUixRQUFRLENBQWlCO0lBQUcsQ0FBQztJQUUxQyxlQUFlLENBQ3JCLElBQVUsRUFDVixPQUErQixFQUMvQixtQkFBd0M7UUFFeEMsc0NBQXNDO1FBQ3RDLDJFQUEyRTtRQUMzRSxNQUFNLFFBQVEsR0FBd0IsSUFBSTthQUN4QyxvQkFBb0IsRUFBRTthQUN0QixNQUFNLENBQUMsQ0FBQyxNQUFjLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM1RixpR0FBaUc7UUFDakcsTUFBTSxpQkFBaUIsR0FBd0IsSUFBSSxDQUFDLGtCQUFrQixDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQztRQUMxRixNQUFNLDJCQUEyQixHQUF3QixJQUFJLENBQUMsaUJBQWlCLENBQzlFLGlCQUFpQixFQUNqQixtQkFBbUIsQ0FDbkIsQ0FBQztRQUNGLE1BQU0sd0JBQXdCLEdBQXdCLElBQUksQ0FBQywwQkFBMEIsQ0FDcEYsT0FBTyxFQUNQLDJCQUEyQixDQUMzQixDQUFDO1FBQ0YsTUFBTSxzQkFBc0IsR0FBd0IsSUFBSSxDQUFDLFlBQVksQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1FBQ2hHLE9BQU8sc0JBQXNCLENBQUM7UUFDOUIsaUNBQWlDO1FBQ2pDLHFDQUFxQztRQUNyQyxjQUFjO1FBQ2QsaUNBQWlDO0lBQ2xDLENBQUM7SUFFTyxrQkFBa0IsQ0FBQyxPQUErQixFQUFFLFFBQTZCO1FBQ3hGLElBQUksTUFBTSxHQUFHLFFBQVEsQ0FBQztRQUN0QixLQUFLLE1BQU0sSUFBSSxJQUFJLE9BQU8sRUFBRTtZQUMzQixJQUFJLElBQUksWUFBWSxpQkFBaUIsRUFBRTtnQkFDdEMsTUFBTSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7YUFDN0M7aUJBQU0sSUFBSSxJQUFJLFlBQVksZUFBZSxFQUFFO2dCQUMzQyxNQUFNLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7YUFDM0M7aUJBQU0sSUFBSSxJQUFJLFlBQVkscUJBQXFCLEVBQUU7Z0JBQ2pELE1BQU0sR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO2FBQ2pEO2lCQUFNLElBQUksSUFBSSxZQUFZLHFCQUFxQixFQUFFO2dCQUNqRCxNQUFNLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQzthQUNqRDtTQUNEO1FBQ0QsT0FBTyxNQUFNLENBQUM7SUFDZixDQUFDO0lBRU8saUJBQWlCLENBQ3hCLGlCQUFzQyxFQUN0QyxtQkFBd0M7UUFFeEMsT0FBTyxpQkFBaUI7YUFDdEIsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxFQUFFO1lBQ3pCLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFO2dCQUNuQixPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUM7b0JBQ3BCLE1BQU0sRUFBRSxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDO2lCQUNyQixDQUFDLENBQUM7YUFDdkI7WUFDRCxPQUFPLE1BQU0sQ0FBQztRQUNmLENBQUMsQ0FBQzthQUNELEtBQUssRUFBRSxDQUFDO0lBQ1gsQ0FBQztJQUVPLGdCQUFnQixDQUFDLFdBQThCLEVBQUUsUUFBNkI7UUFDckYsbUNBQW1DO1FBQ25DLE1BQU0sVUFBVSxHQUNmLFdBQVcsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDbkQsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDaEQsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDO1FBQ3JDLE1BQU0sTUFBTSxHQUFpQixZQUFZLENBQUMsTUFBTSxDQUFDO1lBQ2hELEVBQUUsRUFBRSxXQUFXLENBQUMsZUFBZSxDQUFDLEVBQUU7WUFDbEMsUUFBUSxFQUFFLFdBQVcsQ0FBQyxlQUFlLENBQUMsUUFBUTtZQUM5QyxTQUFTLEVBQUUsV0FBVyxDQUFDLFNBQVM7WUFDaEMsU0FBUyxFQUFFLFdBQVcsQ0FBQyxTQUFTO1lBQ2hDLElBQUksRUFBRSxVQUFVO1lBQ2hCLFlBQVksRUFBRSxXQUFXLENBQUMsWUFBWTtTQUN0QixDQUFDLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUN2RCxPQUFPLFFBQVEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUN4QyxDQUFDO0lBRU8sY0FBYyxDQUFDLFdBQTRCLEVBQUUsUUFBNkI7UUFDakYsTUFBTSxJQUFJLEdBQWUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLFVBQVUsRUFBRSxFQUFFO1lBQ3hELEVBQUUsRUFBRSxXQUFXLENBQUMsZUFBZSxDQUFDLEVBQUU7WUFDbEMsV0FBVyxFQUFFLFdBQVcsQ0FBQyxXQUFXO1lBQ3BDLFVBQVUsRUFBRSxXQUFXLENBQUMsVUFBVTtZQUNsQyxRQUFRLEVBQUUsV0FBVyxDQUFDLFFBQVE7WUFDOUIsVUFBVSxFQUFFLFdBQVcsQ0FBQyxVQUFVO1NBQ2xDLENBQUMsQ0FBQztRQUNILElBQUksTUFBTSxHQUFlLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUNyRixnRUFBZ0U7UUFDaEUsSUFBSSxlQUFlLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxFQUFFO1lBQzFDLDRGQUE0RjtZQUM1RixNQUFNLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDekQseURBQXlEO1NBQ3pEO1FBQ0QsT0FBTyxRQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUVPLG9CQUFvQixDQUMzQixXQUFrQyxFQUNsQyxRQUE2QjtRQUU3QixNQUFNLGFBQWEsR0FBUSxFQUFFLENBQUM7UUFDOUIsZ0VBQWdFO1FBQ2hFLDRCQUE0QjtRQUM1QixtRUFBbUU7UUFDbkUsMENBQTBDO1FBQzFDLElBQUksV0FBVyxDQUFDLGVBQWUsQ0FBQyxNQUFNLEVBQUU7WUFDdkMsYUFBYSxDQUFDLE1BQU0sR0FBRyxXQUFXLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQztTQUMxRDtRQUNELHdGQUF3RjtRQUN4RixnREFBZ0Q7UUFDaEQsSUFBSTtRQUNKLE1BQU0sTUFBTSxHQUFXLFFBQVE7YUFDN0IsR0FBRyxDQUFDLFdBQVcsQ0FBQyxlQUFlLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLEVBQUUsV0FBVyxDQUFDLGVBQWUsQ0FBQyxFQUFFLEVBQVksQ0FBQyxDQUFDO2FBQ3BHLE1BQU0sQ0FBQyxhQUFpQyxDQUFDLENBQUM7UUFDNUMsT0FBTyxRQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUVPLG9CQUFvQixDQUMzQixXQUFrQyxFQUNsQyxRQUE2QjtRQUU3QixNQUFNLGFBQWEsR0FBUSxFQUFFLENBQUM7UUFDOUIsWUFBWTtRQUNaLElBQUksV0FBVyxDQUFDLGVBQWUsQ0FBQyxNQUFNLEVBQUU7WUFDdkMsYUFBYSxDQUFDLE1BQU0sR0FBRyxXQUFXLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQztTQUMxRDtRQUNELHdGQUF3RjtRQUN4RixnREFBZ0Q7UUFDaEQsSUFBSTtRQUNKLE1BQU0sTUFBTSxHQUFXLFFBQVE7YUFDN0IsR0FBRyxDQUFDLFdBQVcsQ0FBQyxlQUFlLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLEVBQUUsV0FBVyxDQUFDLGVBQWUsQ0FBQyxFQUFFLEVBQVksQ0FBQyxDQUFDO2FBQ3BHLE1BQU0sQ0FBQyxhQUFpQyxDQUFDLENBQUM7UUFDNUMsT0FBTyxRQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUVPLDBCQUEwQixDQUNqQyxPQUErQixFQUMvQixRQUE2QjtRQUU3QixJQUFJLE1BQU0sR0FBRyxRQUFRLENBQUM7UUFDdEIsS0FBSyxNQUFNLElBQUksSUFBSSxPQUFPLEVBQUU7WUFDM0IsSUFBSSxJQUFJLFlBQVksb0JBQW9CLEVBQUU7Z0JBQ3pDLE1BQU0sR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO2FBQzlDO1lBQ0QsSUFBSSxJQUFJLFlBQVkscUJBQXFCLEVBQUU7Z0JBQzFDLE1BQU0sR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO2FBQ2pEO1NBQ0Q7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNmLENBQUM7SUFFTyxpQkFBaUIsQ0FBQyxJQUEwQixFQUFFLFFBQTZCO1FBQ2xGLDBEQUEwRDtRQUMxRCx5Q0FBeUM7UUFDekMsSUFBSTtRQUNKLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssT0FBTyxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssS0FBSyxDQUFDLEVBQUU7WUFDNUQsTUFBTSxNQUFNLEdBQVcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLE1BQU0sQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDdkcsT0FBTyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQztTQUM3RDthQUFNLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssT0FBTyxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssS0FBSyxDQUFDLEVBQUU7WUFDbEUsTUFBTSxNQUFNLEdBQVcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLE1BQU0sQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDdkcsT0FBTyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQztTQUM3RDthQUFNLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssT0FBTyxDQUFDLFdBQVcsRUFBRTtZQUNoRCxNQUFNLE1BQU0sR0FBVyxRQUFRO2lCQUM3QixHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUM7Z0JBQ3JCLEVBQUUsTUFBTSxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ2pFLE9BQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUM7U0FDN0Q7UUFDRCxPQUFPLFFBQVEsQ0FBQztJQUNqQixDQUFDO0lBRU8sb0JBQW9CLENBQUMsSUFBMkIsRUFBRSxRQUE2QjtRQUN0RiwwRUFBMEU7UUFDMUUseUNBQXlDO1FBQ3pDLElBQUk7UUFDSixJQUFJLE1BQU0sR0FBRyxRQUFRLENBQUM7UUFDdEIsSUFBSSxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQzdELE1BQU0sTUFBTSxHQUFXLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUM7Z0JBQ25FLElBQUksRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRTthQUN0QyxDQUFDLENBQUM7WUFDSCxNQUFNLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1NBQ3pDO1FBQ0QsTUFBTSxPQUFPLEdBQWtDO1lBQzlDLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDL0UsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLHFCQUFxQixDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLHFCQUFxQixDQUFDLENBQUM7WUFDM0csQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLHFCQUFxQixDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLHFCQUFxQixDQUFDLENBQUM7U0FDM0csQ0FBQztRQUNGLE1BQU0sV0FBVyxHQUFXLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUMxRixPQUFPLE1BQU0sQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLEVBQUUsRUFBRSxXQUFXLENBQUMsQ0FBQztJQUNoRCxDQUFDO0lBRU8sWUFBWSxDQUFDLFFBQTZCO1FBQ2pELE9BQU8sUUFBUTthQUNiLEdBQUcsQ0FBQyxDQUFDLEtBQWEsRUFBRSxFQUFFO1lBQ3RCLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFO2dCQUNsQixPQUFPLEtBQUssQ0FBQzthQUNiO1lBQ0QsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ2pELElBQUksT0FBTyxHQUFrQyxFQUFFLENBQUM7WUFDaEQsSUFBSSxJQUFJLEVBQUU7Z0JBQ1QsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFO29CQUM3RCxPQUFPLEdBQUcsRUFBRSxHQUFHLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDO2lCQUN6RTtnQkFDRCxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssYUFBYSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUU7b0JBQ25FLE9BQU8sR0FBRyxFQUFFLEdBQUcsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxRQUFRLENBQUMsV0FBVyxFQUFFLENBQUM7aUJBQy9FO2FBQ0Q7WUFDRCxPQUFPLEtBQUssQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUN4QyxDQUFDLENBQUM7YUFDRCxLQUFLLEVBQUUsQ0FBQztJQUNYLENBQUM7O2tIQW5OVyxxQkFBcUI7c0hBQXJCLHFCQUFxQixjQUZyQixNQUFNOzJGQUVOLHFCQUFxQjtrQkFIakMsVUFBVTttQkFBQztvQkFDWCxVQUFVLEVBQUUsTUFBTTtpQkFDbEIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IENhcmRUeXBlLCBHYW1lVGFnLCBab25lLCBpc0JhdHRsZWdyb3VuZHMgfSBmcm9tICdAZmlyZXN0b25lLWhzL3JlZmVyZW5jZS1kYXRhJztcclxuaW1wb3J0IHsgTWFwIH0gZnJvbSAnaW1tdXRhYmxlJztcclxuaW1wb3J0IHsgRW50aXR5IH0gZnJvbSAnLi4vLi4vbW9kZWxzL2dhbWUvZW50aXR5JztcclxuaW1wb3J0IHsgR2FtZUVudGl0eSB9IGZyb20gJy4uLy4uL21vZGVscy9nYW1lL2dhbWUtZW50aXR5JztcclxuaW1wb3J0IHsgUGxheWVyRW50aXR5IH0gZnJvbSAnLi4vLi4vbW9kZWxzL2dhbWUvcGxheWVyLWVudGl0eSc7XHJcbmltcG9ydCB7IEZ1bGxFbnRpdHlIaXN0b3J5SXRlbSB9IGZyb20gJy4uLy4uL21vZGVscy9oaXN0b3J5L2Z1bGwtZW50aXR5LWhpc3RvcnktaXRlbSc7XHJcbmltcG9ydCB7IEdhbWVIaXN0b3J5SXRlbSB9IGZyb20gJy4uLy4uL21vZGVscy9oaXN0b3J5L2dhbWUtaGlzdG9yeS1pdGVtJztcclxuaW1wb3J0IHsgSGlzdG9yeUl0ZW0gfSBmcm9tICcuLi8uLi9tb2RlbHMvaGlzdG9yeS9oaXN0b3J5LWl0ZW0nO1xyXG5pbXBvcnQgeyBQbGF5ZXJIaXN0b3J5SXRlbSB9IGZyb20gJy4uLy4uL21vZGVscy9oaXN0b3J5L3BsYXllci1oaXN0b3J5LWl0ZW0nO1xyXG5pbXBvcnQgeyBTaG93RW50aXR5SGlzdG9yeUl0ZW0gfSBmcm9tICcuLi8uLi9tb2RlbHMvaGlzdG9yeS9zaG93LWVudGl0eS1oaXN0b3J5LWl0ZW0nO1xyXG5pbXBvcnQgeyBUYWdDaGFuZ2VIaXN0b3J5SXRlbSB9IGZyb20gJy4uLy4uL21vZGVscy9oaXN0b3J5L3RhZy1jaGFuZ2UtaGlzdG9yeS1pdGVtJztcclxuaW1wb3J0IHsgR2FtZSB9IGZyb20gJy4uLy4uL21vZGVscy9tb2RlbHMnO1xyXG5pbXBvcnQgeyBFbnRpdHlEZWZpbml0aW9uIH0gZnJvbSAnLi4vLi4vbW9kZWxzL3BhcnNlci9lbnRpdHktZGVmaW5pdGlvbic7XHJcbmltcG9ydCB7IEFsbENhcmRzU2VydmljZSB9IGZyb20gJy4uL2FsbC1jYXJkcy5zZXJ2aWNlJztcclxuXHJcbkBJbmplY3RhYmxlKHtcclxuXHRwcm92aWRlZEluOiAncm9vdCcsXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBHYW1lUG9wdWxhdGlvblNlcnZpY2Uge1xyXG5cdGNvbnN0cnVjdG9yKHByaXZhdGUgYWxsQ2FyZHM6IEFsbENhcmRzU2VydmljZSkge31cclxuXHJcblx0cHVibGljIGluaXROZXdFbnRpdGllcyhcclxuXHRcdGdhbWU6IEdhbWUsXHJcblx0XHRoaXN0b3J5OiByZWFkb25seSBIaXN0b3J5SXRlbVtdLFxyXG5cdFx0ZW50aXR5Q2FyZElkTWFwcGluZzogTWFwPG51bWJlciwgc3RyaW5nPixcclxuXHQpOiBNYXA8bnVtYmVyLCBFbnRpdHk+IHtcclxuXHRcdC8vIE1hcCBvZiBlbnRpdHlJZCAtIGVudGl0eSBkZWZpbml0aW9uXHJcblx0XHQvLyBUT0RPOiBzaG91bGQgd2UgcmVtb3ZlIGhlcmUgYWxsIHRoZSBTRVRBU0lERSAvIFJFTU9WRURGUk9NR0FNRSBlbnRpdGllcz9cclxuXHRcdGNvbnN0IGVudGl0aWVzOiBNYXA8bnVtYmVyLCBFbnRpdHk+ID0gZ2FtZVxyXG5cdFx0XHQuZ2V0TGF0ZXN0UGFyc2VkU3RhdGUoKVxyXG5cdFx0XHQuZmlsdGVyKChlbnRpdHk6IEVudGl0eSkgPT4gIVtab25lLlJFTU9WRURGUk9NR0FNRV0uaW5jbHVkZXMoZW50aXR5LmdldFRhZyhHYW1lVGFnLlpPTkUpKSk7XHJcblx0XHQvLyBjb25zb2xlLmRlYnVnKCdlbnRpdGllcyByZWR1Y2VkIGZyb20nLCBnYW1lLmdldExhdGVzdFBhcnNlZFN0YXRlKCkuc2l6ZSwgJ3RvJywgZW50aXRpZXMuc2l6ZSk7XHJcblx0XHRjb25zdCBlbnRpdGllc0FmdGVySW5pdDogTWFwPG51bWJlciwgRW50aXR5PiA9IHRoaXMuaW5pdGlhbGl6ZUVudGl0aWVzKGhpc3RvcnksIGVudGl0aWVzKTtcclxuXHRcdGNvbnN0IGVudGl0aWVzQWZ0ZXJGaWxsaW5nQ2FyZElkczogTWFwPG51bWJlciwgRW50aXR5PiA9IHRoaXMuYWRkTWlzc2luZ0NhcmRJZHMoXHJcblx0XHRcdGVudGl0aWVzQWZ0ZXJJbml0LFxyXG5cdFx0XHRlbnRpdHlDYXJkSWRNYXBwaW5nLFxyXG5cdFx0KTtcclxuXHRcdGNvbnN0IGVudGl0aWVzQWZ0ZXJNaXNzaW5nSW5mbzogTWFwPG51bWJlciwgRW50aXR5PiA9IHRoaXMuY29tcGxldGVNaXNzaW5nSW5mb3JtYXRpb24oXHJcblx0XHRcdGhpc3RvcnksXHJcblx0XHRcdGVudGl0aWVzQWZ0ZXJGaWxsaW5nQ2FyZElkcyxcclxuXHRcdCk7XHJcblx0XHRjb25zdCBlbnRpdGllc0FmdGVyQmFzaWNEYXRhOiBNYXA8bnVtYmVyLCBFbnRpdHk+ID0gdGhpcy5hZGRCYXNpY0RhdGEoZW50aXRpZXNBZnRlck1pc3NpbmdJbmZvKTtcclxuXHRcdHJldHVybiBlbnRpdGllc0FmdGVyQmFzaWNEYXRhO1xyXG5cdFx0Ly8gcmV0dXJuIEdhbWUuY3JlYXRlR2FtZShnYW1lLCB7XHJcblx0XHQvLyBcdGVudGl0aWVzOiBlbnRpdGllc0FmdGVyQmFzaWNEYXRhLFxyXG5cdFx0Ly8gfSBhcyBHYW1lKTtcclxuXHRcdC8vIHJldHVybiBlbnRpdGllc0FmdGVyQmFzaWNEYXRhO1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSBpbml0aWFsaXplRW50aXRpZXMoaGlzdG9yeTogcmVhZG9ubHkgSGlzdG9yeUl0ZW1bXSwgZW50aXRpZXM6IE1hcDxudW1iZXIsIEVudGl0eT4pOiBNYXA8bnVtYmVyLCBFbnRpdHk+IHtcclxuXHRcdGxldCByZXN1bHQgPSBlbnRpdGllcztcclxuXHRcdGZvciAoY29uc3QgaXRlbSBvZiBoaXN0b3J5KSB7XHJcblx0XHRcdGlmIChpdGVtIGluc3RhbmNlb2YgUGxheWVySGlzdG9yeUl0ZW0pIHtcclxuXHRcdFx0XHRyZXN1bHQgPSB0aGlzLmluaXRpYWxpemVQbGF5ZXIoaXRlbSwgcmVzdWx0KTtcclxuXHRcdFx0fSBlbHNlIGlmIChpdGVtIGluc3RhbmNlb2YgR2FtZUhpc3RvcnlJdGVtKSB7XHJcblx0XHRcdFx0cmVzdWx0ID0gdGhpcy5pbml0aWFsaXplR2FtZShpdGVtLCByZXN1bHQpO1xyXG5cdFx0XHR9IGVsc2UgaWYgKGl0ZW0gaW5zdGFuY2VvZiBGdWxsRW50aXR5SGlzdG9yeUl0ZW0pIHtcclxuXHRcdFx0XHRyZXN1bHQgPSB0aGlzLmluaXRpYWxpemVGdWxsRW50aXR5KGl0ZW0sIHJlc3VsdCk7XHJcblx0XHRcdH0gZWxzZSBpZiAoaXRlbSBpbnN0YW5jZW9mIFNob3dFbnRpdHlIaXN0b3J5SXRlbSkge1xyXG5cdFx0XHRcdHJlc3VsdCA9IHRoaXMuaW5pdGlhbGl6ZVNob3dFbnRpdHkoaXRlbSwgcmVzdWx0KTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHJlc3VsdDtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgYWRkTWlzc2luZ0NhcmRJZHMoXHJcblx0XHRlbnRpdGllc0FmdGVySW5pdDogTWFwPG51bWJlciwgRW50aXR5PixcclxuXHRcdGVudGl0eUNhcmRJZE1hcHBpbmc6IE1hcDxudW1iZXIsIHN0cmluZz4sXHJcblx0KTogTWFwPG51bWJlciwgRW50aXR5PiB7XHJcblx0XHRyZXR1cm4gZW50aXRpZXNBZnRlckluaXRcclxuXHRcdFx0Lm1hcCgoZW50aXR5LCBlbnRpdHlJZCkgPT4ge1xyXG5cdFx0XHRcdGlmICghZW50aXR5LmNhcmRJRCkge1xyXG5cdFx0XHRcdFx0cmV0dXJuIGVudGl0eS51cGRhdGUoe1xyXG5cdFx0XHRcdFx0XHRjYXJkSUQ6IGVudGl0eUNhcmRJZE1hcHBpbmcuZ2V0KGVudGl0eUlkKSxcclxuXHRcdFx0XHRcdH0gYXMgRW50aXR5RGVmaW5pdGlvbik7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHJldHVybiBlbnRpdHk7XHJcblx0XHRcdH0pXHJcblx0XHRcdC50b01hcCgpO1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSBpbml0aWFsaXplUGxheWVyKGhpc3RvcnlJdGVtOiBQbGF5ZXJIaXN0b3J5SXRlbSwgZW50aXRpZXM6IE1hcDxudW1iZXIsIEVudGl0eT4pOiBNYXA8bnVtYmVyLCBFbnRpdHk+IHtcclxuXHRcdC8vIFJlbW92ZSB0aGUgYmF0dGxlIHRhZyBpZiBwcmVzZW50XHJcblx0XHRjb25zdCBwbGF5ZXJOYW1lID1cclxuXHRcdFx0aGlzdG9yeUl0ZW0uZW50aXR5RGVmaW50aW9uLm5hbWUuaW5kZXhPZignIycpICE9PSAtMVxyXG5cdFx0XHRcdD8gaGlzdG9yeUl0ZW0uZW50aXR5RGVmaW50aW9uLm5hbWUuc3BsaXQoJyMnKVswXVxyXG5cdFx0XHRcdDogaGlzdG9yeUl0ZW0uZW50aXR5RGVmaW50aW9uLm5hbWU7XHJcblx0XHRjb25zdCBlbnRpdHk6IFBsYXllckVudGl0eSA9IFBsYXllckVudGl0eS5jcmVhdGUoe1xyXG5cdFx0XHRpZDogaGlzdG9yeUl0ZW0uZW50aXR5RGVmaW50aW9uLmlkLFxyXG5cdFx0XHRwbGF5ZXJJZDogaGlzdG9yeUl0ZW0uZW50aXR5RGVmaW50aW9uLnBsYXllcklELFxyXG5cdFx0XHRhY2NvdW50SGk6IGhpc3RvcnlJdGVtLmFjY291bnRIaSxcclxuXHRcdFx0YWNjb3VudExvOiBoaXN0b3J5SXRlbS5hY2NvdW50TG8sXHJcblx0XHRcdG5hbWU6IHBsYXllck5hbWUsXHJcblx0XHRcdGlzTWFpblBsYXllcjogaGlzdG9yeUl0ZW0uaXNNYWluUGxheWVyLFxyXG5cdFx0fSBhcyBQbGF5ZXJFbnRpdHkpLnVwZGF0ZShoaXN0b3J5SXRlbS5lbnRpdHlEZWZpbnRpb24pO1xyXG5cdFx0cmV0dXJuIGVudGl0aWVzLnNldChlbnRpdHkuaWQsIGVudGl0eSk7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIGluaXRpYWxpemVHYW1lKGhpc3RvcnlJdGVtOiBHYW1lSGlzdG9yeUl0ZW0sIGVudGl0aWVzOiBNYXA8bnVtYmVyLCBFbnRpdHk+KTogTWFwPG51bWJlciwgRW50aXR5PiB7XHJcblx0XHRjb25zdCBiYXNlOiBHYW1lRW50aXR5ID0gT2JqZWN0LmFzc2lnbihuZXcgR2FtZUVudGl0eSgpLCB7XHJcblx0XHRcdGlkOiBoaXN0b3J5SXRlbS5lbnRpdHlEZWZpbnRpb24uaWQsXHJcblx0XHRcdGJ1aWxkTnVtYmVyOiBoaXN0b3J5SXRlbS5idWlsZE51bWJlcixcclxuXHRcdFx0Zm9ybWF0VHlwZTogaGlzdG9yeUl0ZW0uZm9ybWF0VHlwZSxcclxuXHRcdFx0Z2FtZVR5cGU6IGhpc3RvcnlJdGVtLmdhbWVUeXBlLFxyXG5cdFx0XHRzY2VuYXJpb0lEOiBoaXN0b3J5SXRlbS5zY2VuYXJpb0lELFxyXG5cdFx0fSk7XHJcblx0XHRsZXQgZW50aXR5OiBHYW1lRW50aXR5ID0gR2FtZUVudGl0eS5jcmVhdGUoYmFzZSkudXBkYXRlKGhpc3RvcnlJdGVtLmVudGl0eURlZmludGlvbik7XHJcblx0XHQvLyBCYXR0bGVncm91bmRzIGRvZXNuJ3QgaGF2ZSB0aGUgcmlnaHQgYm9hcmQgc3RhdGUgc2V0IGF0IHN0YXJ0XHJcblx0XHRpZiAoaXNCYXR0bGVncm91bmRzKGhpc3RvcnlJdGVtLmdhbWVUeXBlKSkge1xyXG5cdFx0XHQvLyAvLyBjb25zb2xlLmxvZygnaW5pdGlhbGl6aW5nIGdhbWUgZW50aXR5IHdpdGggdmlzdWFsIHN0YXRlJywgZW50aXR5LnRhZ3MudG9KUygpLCBlbnRpdHkpO1xyXG5cdFx0XHRlbnRpdHkgPSBlbnRpdHkudXBkYXRlVGFnKEdhbWVUYWcuQk9BUkRfVklTVUFMX1NUQVRFLCAxKTtcclxuXHRcdFx0Ly8gLy8gY29uc29sZS5sb2coJ3VwZGF0ZWQnLCBlbnRpdHkudGFncy50b0pTKCksIGVudGl0eSk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gZW50aXRpZXMuc2V0KGVudGl0eS5pZCwgZW50aXR5KTtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgaW5pdGlhbGl6ZUZ1bGxFbnRpdHkoXHJcblx0XHRoaXN0b3J5SXRlbTogRnVsbEVudGl0eUhpc3RvcnlJdGVtLFxyXG5cdFx0ZW50aXRpZXM6IE1hcDxudW1iZXIsIEVudGl0eT4sXHJcblx0KTogTWFwPG51bWJlciwgRW50aXR5PiB7XHJcblx0XHRjb25zdCBuZXdBdHRyaWJ1dGVzOiBhbnkgPSB7fTtcclxuXHRcdC8vIFdlIHVzZSB0aGUgU2hvd0VudGl0eSBvbmx5IHRvIHVwZGF0ZSB0aGUgY2FyZElEIGF0IHRoaXMgc3RhZ2VcclxuXHRcdC8vIGFuZCBmb3IgYSBmZXcgb3RoZXIgdGFncy5cclxuXHRcdC8vIFNpbmNlIHdlIGRvbid0IHN0b3AgYXQgbXVsbGlnYW4gc3RhZ2UsIHRoaXMgbWVhbnMgdGhhdCBvdGhlcndpc2VcclxuXHRcdC8vIGEgbG90IG9mIG90aGVyIGVudGl0aWVzIHdpbGwgYmUgY3JlYXRlZFxyXG5cdFx0aWYgKGhpc3RvcnlJdGVtLmVudGl0eURlZmludGlvbi5jYXJkSUQpIHtcclxuXHRcdFx0bmV3QXR0cmlidXRlcy5jYXJkSUQgPSBoaXN0b3J5SXRlbS5lbnRpdHlEZWZpbnRpb24uY2FyZElEO1xyXG5cdFx0fVxyXG5cdFx0Ly8gaWYgKGhpc3RvcnlJdGVtLmVudGl0eURlZmludGlvbi5pZCA9PT0gNzMgfHwgaGlzdG9yeUl0ZW0uZW50aXR5RGVmaW50aW9uLmlkID09PSA3NCkge1xyXG5cdFx0Ly8gXHQvLyAvLyBjb25zb2xlLmxvZygnZW5yaWNoaW5nJywgaGlzdG9yeUl0ZW0pO1xyXG5cdFx0Ly8gfVxyXG5cdFx0Y29uc3QgZW50aXR5OiBFbnRpdHkgPSBlbnRpdGllc1xyXG5cdFx0XHQuZ2V0KGhpc3RvcnlJdGVtLmVudGl0eURlZmludGlvbi5pZCwgRW50aXR5LmNyZWF0ZSh7IGlkOiBoaXN0b3J5SXRlbS5lbnRpdHlEZWZpbnRpb24uaWQgfSBhcyBFbnRpdHkpKVxyXG5cdFx0XHQudXBkYXRlKG5ld0F0dHJpYnV0ZXMgYXMgRW50aXR5RGVmaW5pdGlvbik7XHJcblx0XHRyZXR1cm4gZW50aXRpZXMuc2V0KGVudGl0eS5pZCwgZW50aXR5KTtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgaW5pdGlhbGl6ZVNob3dFbnRpdHkoXHJcblx0XHRoaXN0b3J5SXRlbTogU2hvd0VudGl0eUhpc3RvcnlJdGVtLFxyXG5cdFx0ZW50aXRpZXM6IE1hcDxudW1iZXIsIEVudGl0eT4sXHJcblx0KTogTWFwPG51bWJlciwgRW50aXR5PiB7XHJcblx0XHRjb25zdCBuZXdBdHRyaWJ1dGVzOiBhbnkgPSB7fTtcclxuXHRcdC8vIFNhbWUgaGVyZVxyXG5cdFx0aWYgKGhpc3RvcnlJdGVtLmVudGl0eURlZmludGlvbi5jYXJkSUQpIHtcclxuXHRcdFx0bmV3QXR0cmlidXRlcy5jYXJkSUQgPSBoaXN0b3J5SXRlbS5lbnRpdHlEZWZpbnRpb24uY2FyZElEO1xyXG5cdFx0fVxyXG5cdFx0Ly8gaWYgKGhpc3RvcnlJdGVtLmVudGl0eURlZmludGlvbi5pZCA9PT0gNzMgfHwgaGlzdG9yeUl0ZW0uZW50aXR5RGVmaW50aW9uLmlkID09PSA3NCkge1xyXG5cdFx0Ly8gXHQvLyAvLyBjb25zb2xlLmxvZygnZW5yaWNoaW5nJywgaGlzdG9yeUl0ZW0pO1xyXG5cdFx0Ly8gfVxyXG5cdFx0Y29uc3QgZW50aXR5OiBFbnRpdHkgPSBlbnRpdGllc1xyXG5cdFx0XHQuZ2V0KGhpc3RvcnlJdGVtLmVudGl0eURlZmludGlvbi5pZCwgRW50aXR5LmNyZWF0ZSh7IGlkOiBoaXN0b3J5SXRlbS5lbnRpdHlEZWZpbnRpb24uaWQgfSBhcyBFbnRpdHkpKVxyXG5cdFx0XHQudXBkYXRlKG5ld0F0dHJpYnV0ZXMgYXMgRW50aXR5RGVmaW5pdGlvbik7XHJcblx0XHRyZXR1cm4gZW50aXRpZXMuc2V0KGVudGl0eS5pZCwgZW50aXR5KTtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgY29tcGxldGVNaXNzaW5nSW5mb3JtYXRpb24oXHJcblx0XHRoaXN0b3J5OiByZWFkb25seSBIaXN0b3J5SXRlbVtdLFxyXG5cdFx0ZW50aXRpZXM6IE1hcDxudW1iZXIsIEVudGl0eT4sXHJcblx0KTogTWFwPG51bWJlciwgRW50aXR5PiB7XHJcblx0XHRsZXQgcmVzdWx0ID0gZW50aXRpZXM7XHJcblx0XHRmb3IgKGNvbnN0IGl0ZW0gb2YgaGlzdG9yeSkge1xyXG5cdFx0XHRpZiAoaXRlbSBpbnN0YW5jZW9mIFRhZ0NoYW5nZUhpc3RvcnlJdGVtKSB7XHJcblx0XHRcdFx0cmVzdWx0ID0gdGhpcy5hZGRUYWdJbmZvcm1hdGlvbihpdGVtLCByZXN1bHQpO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmIChpdGVtIGluc3RhbmNlb2YgU2hvd0VudGl0eUhpc3RvcnlJdGVtKSB7XHJcblx0XHRcdFx0cmVzdWx0ID0gdGhpcy5hZGRFbnRpdHlJbmZvcm1hdGlvbihpdGVtLCByZXN1bHQpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gcmVzdWx0O1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSBhZGRUYWdJbmZvcm1hdGlvbihpdGVtOiBUYWdDaGFuZ2VIaXN0b3J5SXRlbSwgZW50aXRpZXM6IE1hcDxudW1iZXIsIEVudGl0eT4pOiBNYXA8bnVtYmVyLCBFbnRpdHk+IHtcclxuXHRcdC8vIGlmIChpdGVtLnRhZy5lbnRpdHkgPT09IDczIHx8IGl0ZW0udGFnLmVudGl0eSA9PT0gNzQpIHtcclxuXHRcdC8vIFx0Ly8gLy8gY29uc29sZS5sb2coJ2VucmljaGluZycsIGl0ZW0pO1xyXG5cdFx0Ly8gfVxyXG5cdFx0aWYgKGl0ZW0udGFnLnRhZyA9PT0gR2FtZVRhZy5TRUNSRVQgJiYgaXRlbS50YWcudmFsdWUgPT09IDEpIHtcclxuXHRcdFx0Y29uc3QgZW50aXR5OiBFbnRpdHkgPSBlbnRpdGllcy5nZXQoaXRlbS50YWcuZW50aXR5KT8udXBkYXRlKHsgdGFnczogeyBbR2FtZVRhZ1tpdGVtLnRhZy50YWddXTogMSB9IH0pO1xyXG5cdFx0XHRyZXR1cm4gISFlbnRpdHkgPyBlbnRpdGllcy5zZXQoZW50aXR5LmlkLCBlbnRpdHkpIDogZW50aXRpZXM7XHJcblx0XHR9IGVsc2UgaWYgKGl0ZW0udGFnLnRhZyA9PT0gR2FtZVRhZy5RVUVTVCAmJiBpdGVtLnRhZy52YWx1ZSA9PT0gMSkge1xyXG5cdFx0XHRjb25zdCBlbnRpdHk6IEVudGl0eSA9IGVudGl0aWVzLmdldChpdGVtLnRhZy5lbnRpdHkpPy51cGRhdGUoeyB0YWdzOiB7IFtHYW1lVGFnW2l0ZW0udGFnLnRhZ11dOiAxIH0gfSk7XHJcblx0XHRcdHJldHVybiAhIWVudGl0eSA/IGVudGl0aWVzLnNldChlbnRpdHkuaWQsIGVudGl0eSkgOiBlbnRpdGllcztcclxuXHRcdH0gZWxzZSBpZiAoaXRlbS50YWcudGFnID09PSBHYW1lVGFnLlBBUkVOVF9DQVJEKSB7XHJcblx0XHRcdGNvbnN0IGVudGl0eTogRW50aXR5ID0gZW50aXRpZXNcclxuXHRcdFx0XHQuZ2V0KGl0ZW0udGFnLmVudGl0eSlcclxuXHRcdFx0XHQ/LnVwZGF0ZSh7IHRhZ3M6IHsgW0dhbWVUYWdbaXRlbS50YWcudGFnXV06IGl0ZW0udGFnLnZhbHVlIH0gfSk7XHJcblx0XHRcdHJldHVybiAhIWVudGl0eSA/IGVudGl0aWVzLnNldChlbnRpdHkuaWQsIGVudGl0eSkgOiBlbnRpdGllcztcclxuXHRcdH1cclxuXHRcdHJldHVybiBlbnRpdGllcztcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgYWRkRW50aXR5SW5mb3JtYXRpb24oaXRlbTogU2hvd0VudGl0eUhpc3RvcnlJdGVtLCBlbnRpdGllczogTWFwPG51bWJlciwgRW50aXR5Pik6IE1hcDxudW1iZXIsIEVudGl0eT4ge1xyXG5cdFx0Ly8gaWYgKGl0ZW0uZW50aXR5RGVmaW50aW9uLmlkID09PSA3MyB8fCBpdGVtLmVudGl0eURlZmludGlvbi5pZCA9PT0gNzQpIHtcclxuXHRcdC8vIFx0Ly8gLy8gY29uc29sZS5sb2coJ2VucmljaGluZycsIGl0ZW0pO1xyXG5cdFx0Ly8gfVxyXG5cdFx0bGV0IHJlc3VsdCA9IGVudGl0aWVzO1xyXG5cdFx0aWYgKGl0ZW0uZW50aXR5RGVmaW50aW9uLnRhZ3NbR2FtZVRhZ1tHYW1lVGFnLlNFQ1JFVF1dID09PSAxKSB7XHJcblx0XHRcdGNvbnN0IGVudGl0eTogRW50aXR5ID0gZW50aXRpZXMuZ2V0KGl0ZW0uZW50aXR5RGVmaW50aW9uLmlkKS51cGRhdGUoe1xyXG5cdFx0XHRcdHRhZ3M6IHsgW0dhbWVUYWdbR2FtZVRhZy5TRUNSRVRdXTogMSB9LFxyXG5cdFx0XHR9KTtcclxuXHRcdFx0cmVzdWx0ID0gZW50aXRpZXMuc2V0KGVudGl0eS5pZCwgZW50aXR5KTtcclxuXHRcdH1cclxuXHRcdGNvbnN0IG5ld1RhZ3M6IHsgW3RhZ05hbWU6IHN0cmluZ106IG51bWJlciB9ID0ge1xyXG5cdFx0XHRbR2FtZVRhZ1tHYW1lVGFnLkNSRUFUT1JdXTogaXRlbS5lbnRpdHlEZWZpbnRpb24udGFnc1tHYW1lVGFnW0dhbWVUYWcuQ1JFQVRPUl1dLFxyXG5cdFx0XHRbR2FtZVRhZ1tHYW1lVGFnLlRBR19TQ1JJUFRfREFUQV9OVU1fMV1dOiBpdGVtLmVudGl0eURlZmludGlvbi50YWdzW0dhbWVUYWdbR2FtZVRhZy5UQUdfU0NSSVBUX0RBVEFfTlVNXzFdXSxcclxuXHRcdFx0W0dhbWVUYWdbR2FtZVRhZy5UQUdfU0NSSVBUX0RBVEFfTlVNXzJdXTogaXRlbS5lbnRpdHlEZWZpbnRpb24udGFnc1tHYW1lVGFnW0dhbWVUYWcuVEFHX1NDUklQVF9EQVRBX05VTV8yXV0sXHJcblx0XHR9O1xyXG5cdFx0Y29uc3QgZmluYWxFbnRpdHk6IEVudGl0eSA9IHJlc3VsdC5nZXQoaXRlbS5lbnRpdHlEZWZpbnRpb24uaWQpLnVwZGF0ZSh7IHRhZ3M6IG5ld1RhZ3MgfSk7XHJcblx0XHRyZXR1cm4gcmVzdWx0LnNldChmaW5hbEVudGl0eS5pZCwgZmluYWxFbnRpdHkpO1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSBhZGRCYXNpY0RhdGEoZW50aXRpZXM6IE1hcDxudW1iZXIsIEVudGl0eT4pOiBNYXA8bnVtYmVyLCBFbnRpdHk+IHtcclxuXHRcdHJldHVybiBlbnRpdGllc1xyXG5cdFx0XHQubWFwKCh2YWx1ZTogRW50aXR5KSA9PiB7XHJcblx0XHRcdFx0aWYgKCF2YWx1ZS5jYXJkSUQpIHtcclxuXHRcdFx0XHRcdHJldHVybiB2YWx1ZTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0Y29uc3QgY2FyZCA9IHRoaXMuYWxsQ2FyZHMuZ2V0Q2FyZCh2YWx1ZS5jYXJkSUQpO1xyXG5cdFx0XHRcdGxldCBuZXdUYWdzOiB7IFt0YWdOYW1lOiBzdHJpbmddOiBudW1iZXIgfSA9IHt9O1xyXG5cdFx0XHRcdGlmIChjYXJkKSB7XHJcblx0XHRcdFx0XHRpZiAoY2FyZC50eXBlID09PSAnU3BlbGwnICYmICF2YWx1ZS5nZXRUYWcoR2FtZVRhZy5DQVJEVFlQRSkpIHtcclxuXHRcdFx0XHRcdFx0bmV3VGFncyA9IHsgLi4udmFsdWUudGFncywgW0dhbWVUYWdbR2FtZVRhZy5DQVJEVFlQRV1dOiBDYXJkVHlwZS5TUEVMTCB9O1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0aWYgKGNhcmQudHlwZSA9PT0gJ0VuY2hhbnRtZW50JyAmJiAhdmFsdWUuZ2V0VGFnKEdhbWVUYWcuQ0FSRFRZUEUpKSB7XHJcblx0XHRcdFx0XHRcdG5ld1RhZ3MgPSB7IC4uLnZhbHVlLnRhZ3MsIFtHYW1lVGFnW0dhbWVUYWcuQ0FSRFRZUEVdXTogQ2FyZFR5cGUuRU5DSEFOVE1FTlQgfTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0cmV0dXJuIHZhbHVlLnVwZGF0ZSh7IHRhZ3M6IG5ld1RhZ3MgfSk7XHJcblx0XHRcdH0pXHJcblx0XHRcdC50b01hcCgpO1xyXG5cdH1cclxufVxyXG4iXX0=