@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.7 kB
JavaScript
import { Injectable } from '@angular/core';
import { CardType, GameTag, Zone, isBattlegrounds } from '@firestone-hs/reference-data';
import { Map } from 'immutable';
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: Map({ [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: Map({ [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: Map({ [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.get(GameTag[GameTag.SECRET]) === 1) {
const entity = entities.get(item.entityDefintion.id).update({
tags: Map().set(GameTag[GameTag.SECRET], 1),
});
result = entities.set(entity.id, entity);
}
const newTags = Map()
.set(GameTag[GameTag.CREATOR], item.entityDefintion.tags.get(GameTag[GameTag.CREATOR]))
.set(GameTag[GameTag.TAG_SCRIPT_DATA_NUM_1], item.entityDefintion.tags.get(GameTag[GameTag.TAG_SCRIPT_DATA_NUM_1]))
.set(GameTag[GameTag.TAG_SCRIPT_DATA_NUM_2], item.entityDefintion.tags.get(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 = Map();
if (card) {
if (card.type === 'Spell' && !value.getTag(GameTag.CARDTYPE)) {
newTags = value.tags.set(GameTag[GameTag.CARDTYPE], CardType.SPELL);
}
if (card.type === 'Enchantment' && !value.getTag(GameTag.CARDTYPE)) {
newTags = value.tags.set(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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2FtZS1wb3B1bGF0aW9uLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9yZXBsYXktcGFyc2VyL3NyYy9saWIvc2VydmljZXMvZW50aXRpZXNwaXBlbGluZS9nYW1lLXBvcHVsYXRpb24uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUN4RixPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ2hDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNsRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDM0QsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQy9ELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLCtDQUErQyxDQUFDO0FBQ3RGLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQUV6RSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwwQ0FBMEMsQ0FBQztBQUM3RSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSwrQ0FBK0MsQ0FBQztBQUN0RixPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSw4Q0FBOEMsQ0FBQzs7O0FBUXBGLE1BQU0sT0FBTyxxQkFBcUI7SUFDakMsWUFBb0IsUUFBeUI7UUFBekIsYUFBUSxHQUFSLFFBQVEsQ0FBaUI7SUFBRyxDQUFDO0lBRTFDLGVBQWUsQ0FDckIsSUFBVSxFQUNWLE9BQStCLEVBQy9CLG1CQUF3QztRQUV4QyxzQ0FBc0M7UUFDdEMsMkVBQTJFO1FBQzNFLE1BQU0sUUFBUSxHQUF3QixJQUFJO2FBQ3hDLG9CQUFv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TlcscUJBQXFCO3NIQUFyQixxQkFBcUIsY0FGckIsTUFBTTsyRkFFTixxQkFBcUI7a0JBSGpDLFVBQVU7bUJBQUM7b0JBQ1gsVUFBVSxFQUFFLE1BQU07aUJBQ2xCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBDYXJkVHlwZSwgR2FtZVRhZywgWm9uZSwgaXNCYXR0bGVncm91bmRzIH0gZnJvbSAnQGZpcmVzdG9uZS1ocy9yZWZlcmVuY2UtZGF0YSc7XHJcbmltcG9ydCB7IE1hcCB9IGZyb20gJ2ltbXV0YWJsZSc7XHJcbmltcG9ydCB7IEVudGl0eSB9IGZyb20gJy4uLy4uL21vZGVscy9nYW1lL2VudGl0eSc7XHJcbmltcG9ydCB7IEdhbWVFbnRpdHkgfSBmcm9tICcuLi8uLi9tb2RlbHMvZ2FtZS9nYW1lLWVudGl0eSc7XHJcbmltcG9ydCB7IFBsYXllckVudGl0eSB9IGZyb20gJy4uLy4uL21vZGVscy9nYW1lL3BsYXllci1lbnRpdHknO1xyXG5pbXBvcnQgeyBGdWxsRW50aXR5SGlzdG9yeUl0ZW0gfSBmcm9tICcuLi8uLi9tb2RlbHMvaGlzdG9yeS9mdWxsLWVudGl0eS1oaXN0b3J5LWl0ZW0nO1xyXG5pbXBvcnQgeyBHYW1lSGlzdG9yeUl0ZW0gfSBmcm9tICcuLi8uLi9tb2RlbHMvaGlzdG9yeS9nYW1lLWhpc3RvcnktaXRlbSc7XHJcbmltcG9ydCB7IEhpc3RvcnlJdGVtIH0gZnJvbSAnLi4vLi4vbW9kZWxzL2hpc3RvcnkvaGlzdG9yeS1pdGVtJztcclxuaW1wb3J0IHsgUGxheWVySGlzdG9yeUl0ZW0gfSBmcm9tICcuLi8uLi9tb2RlbHMvaGlzdG9yeS9wbGF5ZXItaGlzdG9yeS1pdGVtJztcclxuaW1wb3J0IHsgU2hvd0VudGl0eUhpc3RvcnlJdGVtIH0gZnJvbSAnLi4vLi4vbW9kZWxzL2hpc3Rvcnkvc2hvdy1lbnRpdHktaGlzdG9yeS1pdGVtJztcclxuaW1wb3J0IHsgVGFnQ2hhbmdlSGlzdG9yeUl0ZW0gfSBmcm9tICcuLi8uLi9tb2RlbHMvaGlzdG9yeS90YWctY2hhbmdlLWhpc3RvcnktaXRlbSc7XHJcbmltcG9ydCB7IEdhbWUgfSBmcm9tICcuLi8uLi9tb2RlbHMvbW9kZWxzJztcclxuaW1wb3J0IHsgRW50aXR5RGVmaW5pdGlvbiB9IGZyb20gJy4uLy4uL21vZGVscy9wYXJzZXIvZW50aXR5LWRlZmluaXRpb24nO1xyXG5pbXBvcnQgeyBBbGxDYXJkc1NlcnZpY2UgfSBmcm9tICcuLi9hbGwtY2FyZHMuc2VydmljZSc7XHJcblxyXG5ASW5qZWN0YWJsZSh7XHJcblx0cHJvdmlkZWRJbjogJ3Jvb3QnLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgR2FtZVBvcHVsYXRpb25TZXJ2aWNlIHtcclxuXHRjb25zdHJ1Y3Rvcihwcml2YXRlIGFsbENhcmRzOiBBbGxDYXJkc1NlcnZpY2UpIHt9XHJcblxyXG5cdHB1YmxpYyBpbml0TmV3RW50aXRpZXMoXHJcblx0XHRnYW1lOiBHYW1lLFxyXG5cdFx0aGlzdG9yeTogcmVhZG9ubHkgSGlzdG9yeUl0ZW1bXSxcclxuXHRcdGVudGl0eUNhcmRJZE1hcHBpbmc6IE1hcDxudW1iZXIsIHN0cmluZz4sXHJcblx0KTogTWFwPG51bWJlciwgRW50aXR5PiB7XHJcblx0XHQvLyBNYXAgb2YgZW50aXR5SWQgLSBlbnRpdHkgZGVmaW5pdGlvblxyXG5cdFx0Ly8gVE9ETzogc2hvdWxkIHdlIHJlbW92ZSBoZXJlIGFsbCB0aGUgU0VUQVNJREUgLyBSRU1PVkVERlJPTUdBTUUgZW50aXRpZXM/XHJcblx0XHRjb25zdCBlbnRpdGllczogTWFwPG51bWJlciwgRW50aXR5PiA9IGdhbWVcclxuXHRcdFx0LmdldExhdGVzdFBhcnNlZFN0YXRlKClcclxuXHRcdFx0LmZpbHRlcigoZW50aXR5OiBFbnRpdHkpID0+ICFbWm9uZS5SRU1PVkVERlJPTUdBTUVdLmluY2x1ZGVzKGVudGl0eS5nZXRUYWcoR2FtZVRhZy5aT05FKSkpO1xyXG5cdFx0Ly8gY29uc29sZS5kZWJ1ZygnZW50aXRpZXMgcmVkdWNlZCBmcm9tJywgZ2FtZS5nZXRMYXRlc3RQYXJzZWRTdGF0ZSgpLnNpemUsICd0bycsIGVudGl0aWVzLnNpemUpO1xyXG5cdFx0Y29uc3QgZW50aXRpZXNBZnRlckluaXQ6IE1hcDxudW1iZXIsIEVudGl0eT4gPSB0aGlzLmluaXRpYWxpemVFbnRpdGllcyhoaXN0b3J5LCBlbnRpdGllcyk7XHJcblx0XHRjb25zdCBlbnRpdGllc0FmdGVyRmlsbGluZ0NhcmRJZHM6IE1hcDxudW1iZXIsIEVudGl0eT4gPSB0aGlzLmFkZE1pc3NpbmdDYXJkSWRzKFxyXG5cdFx0XHRlbnRpdGllc0FmdGVySW5pdCxcclxuXHRcdFx0ZW50aXR5Q2FyZElkTWFwcGluZyxcclxuXHRcdCk7XHJcblx0XHRjb25zdCBlbnRpdGllc0FmdGVyTWlzc2luZ0luZm86IE1hcDxudW1iZXIsIEVudGl0eT4gPSB0aGlzLmNvbXBsZXRlTWlzc2luZ0luZm9ybWF0aW9uKFxyXG5cdFx0XHRoaXN0b3J5LFxyXG5cdFx0XHRlbnRpdGllc0FmdGVyRmlsbGluZ0NhcmRJZHMsXHJcblx0XHQpO1xyXG5cdFx0Y29uc3QgZW50aXRpZXNBZnRlckJhc2ljRGF0YTogTWFwPG51bWJlciwgRW50aXR5PiA9IHRoaXMuYWRkQmFzaWNEYXRhKGVudGl0aWVzQWZ0ZXJNaXNzaW5nSW5mbyk7XHJcblx0XHRyZXR1cm4gZW50aXRpZXNBZnRlckJhc2ljRGF0YTtcclxuXHRcdC8vIHJldHVybiBHYW1lLmNyZWF0ZUdhbWUoZ2FtZSwge1xyXG5cdFx0Ly8gXHRlbnRpdGllczogZW50aXRpZXNBZnRlckJhc2ljRGF0YSxcclxuXHRcdC8vIH0gYXMgR2FtZSk7XHJcblx0XHQvLyByZXR1cm4gZW50aXRpZXNBZnRlckJhc2ljRGF0YTtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgaW5pdGlhbGl6ZUVudGl0aWVzKGhpc3Rvcnk6IHJlYWRvbmx5IEhpc3RvcnlJdGVtW10sIGVudGl0aWVzOiBNYXA8bnVtYmVyLCBFbnRpdHk+KTogTWFwPG51bWJlciwgRW50aXR5PiB7XHJcblx0XHRsZXQgcmVzdWx0ID0gZW50aXRpZXM7XHJcblx0XHRmb3IgKGNvbnN0IGl0ZW0gb2YgaGlzdG9yeSkge1xyXG5cdFx0XHRpZiAoaXRlbSBpbnN0YW5jZW9mIFBsYXllckhpc3RvcnlJdGVtKSB7XHJcblx0XHRcdFx0cmVzdWx0ID0gdGhpcy5pbml0aWFsaXplUGxheWVyKGl0ZW0sIHJlc3VsdCk7XHJcblx0XHRcdH0gZWxzZSBpZiAoaXRlbSBpbnN0YW5jZW9mIEdhbWVIaXN0b3J5SXRlbSkge1xyXG5cdFx0XHRcdHJlc3VsdCA9IHRoaXMuaW5pdGlhbGl6ZUdhbWUoaXRlbSwgcmVzdWx0KTtcclxuXHRcdFx0fSBlbHNlIGlmIChpdGVtIGluc3RhbmNlb2YgRnVsbEVudGl0eUhpc3RvcnlJdGVtKSB7XHJcblx0XHRcdFx0cmVzdWx0ID0gdGhpcy5pbml0aWFsaXplRnVsbEVudGl0eShpdGVtLCByZXN1bHQpO1xyXG5cdFx0XHR9IGVsc2UgaWYgKGl0ZW0gaW5zdGFuY2VvZiBTaG93RW50aXR5SGlzdG9yeUl0ZW0pIHtcclxuXHRcdFx0XHRyZXN1bHQgPSB0aGlzLmluaXRpYWxpemVTaG93RW50aXR5KGl0ZW0sIHJlc3VsdCk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHRcdHJldHVybiByZXN1bHQ7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIGFkZE1pc3NpbmdDYXJkSWRzKFxyXG5cdFx0ZW50aXRpZXNBZnRlckluaXQ6IE1hcDxudW1iZXIsIEVudGl0eT4sXHJcblx0XHRlbnRpdHlDYXJkSWRNYXBwaW5nOiBNYXA8bnVtYmVyLCBzdHJpbmc+LFxyXG5cdCk6IE1hcDxudW1iZXIsIEVudGl0eT4ge1xyXG5cdFx0cmV0dXJuIGVudGl0aWVzQWZ0ZXJJbml0XHJcblx0XHRcdC5tYXAoKGVudGl0eSwgZW50aXR5SWQpID0+IHtcclxuXHRcdFx0XHRpZiAoIWVudGl0eS5jYXJkSUQpIHtcclxuXHRcdFx0XHRcdHJldHVybiBlbnRpdHkudXBkYXRlKHtcclxuXHRcdFx0XHRcdFx0Y2FyZElEOiBlbnRpdHlDYXJkSWRNYXBwaW5nLmdldChlbnRpdHlJZCksXHJcblx0XHRcdFx0XHR9IGFzIEVudGl0eURlZmluaXRpb24pO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRyZXR1cm4gZW50aXR5O1xyXG5cdFx0XHR9KVxyXG5cdFx0XHQudG9NYXAoKTtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgaW5pdGlhbGl6ZVBsYXllcihoaXN0b3J5SXRlbTogUGxheWVySGlzdG9yeUl0ZW0sIGVudGl0aWVzOiBNYXA8bnVtYmVyLCBFbnRpdHk+KTogTWFwPG51bWJlciwgRW50aXR5PiB7XHJcblx0XHQvLyBSZW1vdmUgdGhlIGJhdHRsZSB0YWcgaWYgcHJlc2VudFxyXG5cdFx0Y29uc3QgcGxheWVyTmFtZSA9XHJcblx0XHRcdGhpc3RvcnlJdGVtLmVudGl0eURlZmludGlvbi5uYW1lLmluZGV4T2YoJyMnKSAhPT0gLTFcclxuXHRcdFx0XHQ/IGhpc3RvcnlJdGVtLmVudGl0eURlZmludGlvbi5uYW1lLnNwbGl0KCcjJylbMF1cclxuXHRcdFx0XHQ6IGhpc3RvcnlJdGVtLmVudGl0eURlZmludGlvbi5uYW1lO1xyXG5cdFx0Y29uc3QgZW50aXR5OiBQbGF5ZXJFbnRpdHkgPSBQbGF5ZXJFbnRpdHkuY3JlYXRlKHtcclxuXHRcdFx0aWQ6IGhpc3RvcnlJdGVtLmVudGl0eURlZmludGlvbi5pZCxcclxuXHRcdFx0cGxheWVySWQ6IGhpc3RvcnlJdGVtLmVudGl0eURlZmludGlvbi5wbGF5ZXJJRCxcclxuXHRcdFx0YWNjb3VudEhpOiBoaXN0b3J5SXRlbS5hY2NvdW50SGksXHJcblx0XHRcdGFjY291bnRMbzogaGlzdG9yeUl0ZW0uYWNjb3VudExvLFxyXG5cdFx0XHRuYW1lOiBwbGF5ZXJOYW1lLFxyXG5cdFx0XHRpc01haW5QbGF5ZXI6IGhpc3RvcnlJdGVtLmlzTWFpblBsYXllcixcclxuXHRcdH0gYXMgUGxheWVyRW50aXR5KS51cGRhdGUoaGlzdG9yeUl0ZW0uZW50aXR5RGVmaW50aW9uKTtcclxuXHRcdHJldHVybiBlbnRpdGllcy5zZXQoZW50aXR5LmlkLCBlbnRpdHkpO1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSBpbml0aWFsaXplR2FtZShoaXN0b3J5SXRlbTogR2FtZUhpc3RvcnlJdGVtLCBlbnRpdGllczogTWFwPG51bWJlciwgRW50aXR5Pik6IE1hcDxudW1iZXIsIEVudGl0eT4ge1xyXG5cdFx0Y29uc3QgYmFzZTogR2FtZUVudGl0eSA9IE9iamVjdC5hc3NpZ24obmV3IEdhbWVFbnRpdHkoKSwge1xyXG5cdFx0XHRpZDogaGlzdG9yeUl0ZW0uZW50aXR5RGVmaW50aW9uLmlkLFxyXG5cdFx0XHRidWlsZE51bWJlcjogaGlzdG9yeUl0ZW0uYnVpbGROdW1iZXIsXHJcblx0XHRcdGZvcm1hdFR5cGU6IGhpc3RvcnlJdGVtLmZvcm1hdFR5cGUsXHJcblx0XHRcdGdhbWVUeXBlOiBoaXN0b3J5SXRlbS5nYW1lVHlwZSxcclxuXHRcdFx0c2NlbmFyaW9JRDogaGlzdG9yeUl0ZW0uc2NlbmFyaW9JRCxcclxuXHRcdH0pO1xyXG5cdFx0bGV0IGVudGl0eTogR2FtZUVudGl0eSA9IEdhbWVFbnRpdHkuY3JlYXRlKGJhc2UpLnVwZGF0ZShoaXN0b3J5SXRlbS5lbnRpdHlEZWZpbnRpb24pO1xyXG5cdFx0Ly8gQmF0dGxlZ3JvdW5kcyBkb2Vzbid0IGhhdmUgdGhlIHJpZ2h0IGJvYXJkIHN0YXRlIHNldCBhdCBzdGFydFxyXG5cdFx0aWYgKGlzQmF0dGxlZ3JvdW5kcyhoaXN0b3J5SXRlbS5nYW1lVHlwZSkpIHtcclxuXHRcdFx0Ly8gLy8gY29uc29sZS5sb2coJ2luaXRpYWxpemluZyBnYW1lIGVudGl0eSB3aXRoIHZpc3VhbCBzdGF0ZScsIGVudGl0eS50YWdzLnRvSlMoKSwgZW50aXR5KTtcclxuXHRcdFx0ZW50aXR5ID0gZW50aXR5LnVwZGF0ZVRhZyhHYW1lVGFnLkJPQVJEX1ZJU1VBTF9TVEFURSwgMSk7XHJcblx0XHRcdC8vIC8vIGNvbnNvbGUubG9nKCd1cGRhdGVkJywgZW50aXR5LnRhZ3MudG9KUygpLCBlbnRpdHkpO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIGVudGl0aWVzLnNldChlbnRpdHkuaWQsIGVudGl0eSk7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIGluaXRpYWxpemVGdWxsRW50aXR5KFxyXG5cdFx0aGlzdG9yeUl0ZW06IEZ1bGxFbnRpdHlIaXN0b3J5SXRlbSxcclxuXHRcdGVudGl0aWVzOiBNYXA8bnVtYmVyLCBFbnRpdHk+LFxyXG5cdCk6IE1hcDxudW1iZXIsIEVudGl0eT4ge1xyXG5cdFx0Y29uc3QgbmV3QXR0cmlidXRlczogYW55ID0ge307XHJcblx0XHQvLyBXZSB1c2UgdGhlIFNob3dFbnRpdHkgb25seSB0byB1cGRhdGUgdGhlIGNhcmRJRCBhdCB0aGlzIHN0YWdlXHJcblx0XHQvLyBhbmQgZm9yIGEgZmV3IG90aGVyIHRhZ3MuXHJcblx0XHQvLyBTaW5jZSB3ZSBkb24ndCBzdG9wIGF0IG11bGxpZ2FuIHN0YWdlLCB0aGlzIG1lYW5zIHRoYXQgb3RoZXJ3aXNlXHJcblx0XHQvLyBhIGxvdCBvZiBvdGhlciBlbnRpdGllcyB3aWxsIGJlIGNyZWF0ZWRcclxuXHRcdGlmIChoaXN0b3J5SXRlbS5lbnRpdHlEZWZpbnRpb24uY2FyZElEKSB7XHJcblx0XHRcdG5ld0F0dHJpYnV0ZXMuY2FyZElEID0gaGlzdG9yeUl0ZW0uZW50aXR5RGVmaW50aW9uLmNhcmRJRDtcclxuXHRcdH1cclxuXHRcdC8vIGlmIChoaXN0b3J5SXRlbS5lbnRpdHlEZWZpbnRpb24uaWQgPT09IDczIHx8IGhpc3RvcnlJdGVtLmVudGl0eURlZmludGlvbi5pZCA9PT0gNzQpIHtcclxuXHRcdC8vIFx0Ly8gLy8gY29uc29sZS5sb2coJ2VucmljaGluZycsIGhpc3RvcnlJdGVtKTtcclxuXHRcdC8vIH1cclxuXHRcdGNvbnN0IGVudGl0eTogRW50aXR5ID0gZW50aXRpZXNcclxuXHRcdFx0LmdldChoaXN0b3J5SXRlbS5lbnRpdHlEZWZpbnRpb24uaWQsIEVudGl0eS5jcmVhdGUoeyBpZDogaGlzdG9yeUl0ZW0uZW50aXR5RGVmaW50aW9uLmlkIH0gYXMgRW50aXR5KSlcclxuXHRcdFx0LnVwZGF0ZShuZXdBdHRyaWJ1dGVzIGFzIEVudGl0eURlZmluaXRpb24pO1xyXG5cdFx0cmV0dXJuIGVudGl0aWVzLnNldChlbnRpdHkuaWQsIGVudGl0eSk7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIGluaXRpYWxpemVTaG93RW50aXR5KFxyXG5cdFx0aGlzdG9yeUl0ZW06IFNob3dFbnRpdHlIaXN0b3J5SXRlbSxcclxuXHRcdGVudGl0aWVzOiBNYXA8bnVtYmVyLCBFbnRpdHk+LFxyXG5cdCk6IE1hcDxudW1iZXIsIEVudGl0eT4ge1xyXG5cdFx0Y29uc3QgbmV3QXR0cmlidXRlczogYW55ID0ge307XHJcblx0XHQvLyBTYW1lIGhlcmVcclxuXHRcdGlmIChoaXN0b3J5SXRlbS5lbnRpdHlEZWZpbnRpb24uY2FyZElEKSB7XHJcblx0XHRcdG5ld0F0dHJpYnV0ZXMuY2FyZElEID0gaGlzdG9yeUl0ZW0uZW50aXR5RGVmaW50aW9uLmNhcmRJRDtcclxuXHRcdH1cclxuXHRcdC8vIGlmIChoaXN0b3J5SXRlbS5lbnRpdHlEZWZpbnRpb24uaWQgPT09IDczIHx8IGhpc3RvcnlJdGVtLmVudGl0eURlZmludGlvbi5pZCA9PT0gNzQpIHtcclxuXHRcdC8vIFx0Ly8gLy8gY29uc29sZS5sb2coJ2VucmljaGluZycsIGhpc3RvcnlJdGVtKTtcclxuXHRcdC8vIH1cclxuXHRcdGNvbnN0IGVudGl0eTogRW50aXR5ID0gZW50aXRpZXNcclxuXHRcdFx0LmdldChoaXN0b3J5SXRlbS5lbnRpdHlEZWZpbnRpb24uaWQsIEVudGl0eS5jcmVhdGUoeyBpZDogaGlzdG9yeUl0ZW0uZW50aXR5RGVmaW50aW9uLmlkIH0gYXMgRW50aXR5KSlcclxuXHRcdFx0LnVwZGF0ZShuZXdBdHRyaWJ1dGVzIGFzIEVudGl0eURlZmluaXRpb24pO1xyXG5cdFx0cmV0dXJuIGVudGl0aWVzLnNldChlbnRpdHkuaWQsIGVudGl0eSk7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIGNvbXBsZXRlTWlzc2luZ0luZm9ybWF0aW9uKFxyXG5cdFx0aGlzdG9yeTogcmVhZG9ubHkgSGlzdG9yeUl0ZW1bXSxcclxuXHRcdGVudGl0aWVzOiBNYXA8bnVtYmVyLCBFbnRpdHk+LFxyXG5cdCk6IE1hcDxudW1iZXIsIEVudGl0eT4ge1xyXG5cdFx0bGV0IHJlc3VsdCA9IGVudGl0aWVzO1xyXG5cdFx0Zm9yIChjb25zdCBpdGVtIG9mIGhpc3RvcnkpIHtcclxuXHRcdFx0aWYgKGl0ZW0gaW5zdGFuY2VvZiBUYWdDaGFuZ2VIaXN0b3J5SXRlbSkge1xyXG5cdFx0XHRcdHJlc3VsdCA9IHRoaXMuYWRkVGFnSW5mb3JtYXRpb24oaXRlbSwgcmVzdWx0KTtcclxuXHRcdFx0fVxyXG5cdFx0XHRpZiAoaXRlbSBpbnN0YW5jZW9mIFNob3dFbnRpdHlIaXN0b3J5SXRlbSkge1xyXG5cdFx0XHRcdHJlc3VsdCA9IHRoaXMuYWRkRW50aXR5SW5mb3JtYXRpb24oaXRlbSwgcmVzdWx0KTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHJlc3VsdDtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgYWRkVGFnSW5mb3JtYXRpb24oaXRlbTogVGFnQ2hhbmdlSGlzdG9yeUl0ZW0sIGVudGl0aWVzOiBNYXA8bnVtYmVyLCBFbnRpdHk+KTogTWFwPG51bWJlciwgRW50aXR5PiB7XHJcblx0XHQvLyBpZiAoaXRlbS50YWcuZW50aXR5ID09PSA3MyB8fCBpdGVtLnRhZy5lbnRpdHkgPT09IDc0KSB7XHJcblx0XHQvLyBcdC8vIC8vIGNvbnNvbGUubG9nKCdlbnJpY2hpbmcnLCBpdGVtKTtcclxuXHRcdC8vIH1cclxuXHRcdGlmIChpdGVtLnRhZy50YWcgPT09IEdhbWVUYWcuU0VDUkVUICYmIGl0ZW0udGFnLnZhbHVlID09PSAxKSB7XHJcblx0XHRcdGNvbnN0IGVudGl0eTogRW50aXR5ID0gZW50aXRpZXMuZ2V0KGl0ZW0udGFnLmVudGl0eSk/LnVwZGF0ZSh7IHRhZ3M6IE1hcCh7IFtHYW1lVGFnW2l0ZW0udGFnLnRhZ11dOiAxIH0pIH0pO1xyXG5cdFx0XHRyZXR1cm4gISFlbnRpdHkgPyBlbnRpdGllcy5zZXQoZW50aXR5LmlkLCBlbnRpdHkpIDogZW50aXRpZXM7XHJcblx0XHR9IGVsc2UgaWYgKGl0ZW0udGFnLnRhZyA9PT0gR2FtZVRhZy5RVUVTVCAmJiBpdGVtLnRhZy52YWx1ZSA9PT0gMSkge1xyXG5cdFx0XHRjb25zdCBlbnRpdHk6IEVudGl0eSA9IGVudGl0aWVzLmdldChpdGVtLnRhZy5lbnRpdHkpPy51cGRhdGUoeyB0YWdzOiBNYXAoeyBbR2FtZVRhZ1tpdGVtLnRhZy50YWddXTogMSB9KSB9KTtcclxuXHRcdFx0cmV0dXJuICEhZW50aXR5ID8gZW50aXRpZXMuc2V0KGVudGl0eS5pZCwgZW50aXR5KSA6IGVudGl0aWVzO1xyXG5cdFx0fSBlbHNlIGlmIChpdGVtLnRhZy50YWcgPT09IEdhbWVUYWcuUEFSRU5UX0NBUkQpIHtcclxuXHRcdFx0Y29uc3QgZW50aXR5OiBFbnRpdHkgPSBlbnRpdGllc1xyXG5cdFx0XHRcdC5nZXQoaXRlbS50YWcuZW50aXR5KVxyXG5cdFx0XHRcdD8udXBkYXRlKHsgdGFnczogTWFwKHsgW0dhbWVUYWdbaXRlbS50YWcudGFnXV06IGl0ZW0udGFnLnZhbHVlIH0pIH0pO1xyXG5cdFx0XHRyZXR1cm4gISFlbnRpdHkgPyBlbnRpdGllcy5zZXQoZW50aXR5LmlkLCBlbnRpdHkpIDogZW50aXRpZXM7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gZW50aXRpZXM7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIGFkZEVudGl0eUluZm9ybWF0aW9uKGl0ZW06IFNob3dFbnRpdHlIaXN0b3J5SXRlbSwgZW50aXRpZXM6IE1hcDxudW1iZXIsIEVudGl0eT4pOiBNYXA8bnVtYmVyLCBFbnRpdHk+IHtcclxuXHRcdC8vIGlmIChpdGVtLmVudGl0eURlZmludGlvbi5pZCA9PT0gNzMgfHwgaXRlbS5lbnRpdHlEZWZpbnRpb24uaWQgPT09IDc0KSB7XHJcblx0XHQvLyBcdC8vIC8vIGNvbnNvbGUubG9nKCdlbnJpY2hpbmcnLCBpdGVtKTtcclxuXHRcdC8vIH1cclxuXHRcdGxldCByZXN1bHQgPSBlbnRpdGllcztcclxuXHRcdGlmIChpdGVtLmVudGl0eURlZmludGlvbi50YWdzLmdldChHYW1lVGFnW0dhbWVUYWcuU0VDUkVUXSkgPT09IDEpIHtcclxuXHRcdFx0Y29uc3QgZW50aXR5OiBFbnRpdHkgPSBlbnRpdGllcy5nZXQoaXRlbS5lbnRpdHlEZWZpbnRpb24uaWQpLnVwZGF0ZSh7XHJcblx0XHRcdFx0dGFnczogTWFwPHN0cmluZywgbnVtYmVyPigpLnNldChHYW1lVGFnW0dhbWVUYWcuU0VDUkVUXSwgMSksXHJcblx0XHRcdH0pO1xyXG5cdFx0XHRyZXN1bHQgPSBlbnRpdGllcy5zZXQoZW50aXR5LmlkLCBlbnRpdHkpO1xyXG5cdFx0fVxyXG5cdFx0Y29uc3QgbmV3VGFnczogTWFwPHN0cmluZywgbnVtYmVyPiA9IE1hcDxzdHJpbmcsIG51bWJlcj4oKVxyXG5cdFx0XHQuc2V0KEdhbWVUYWdbR2FtZVRhZy5DUkVBVE9SXSwgaXRlbS5lbnRpdHlEZWZpbnRpb24udGFncy5nZXQoR2FtZVRhZ1tHYW1lVGFnLkNSRUFUT1JdKSlcclxuXHRcdFx0LnNldChcclxuXHRcdFx0XHRHYW1lVGFnW0dhbWVUYWcuVEFHX1NDUklQVF9EQVRBX05VTV8xXSxcclxuXHRcdFx0XHRpdGVtLmVudGl0eURlZmludGlvbi50YWdzLmdldChHYW1lVGFnW0dhbWVUYWcuVEFHX1NDUklQVF9EQVRBX05VTV8xXSksXHJcblx0XHRcdClcclxuXHRcdFx0LnNldChcclxuXHRcdFx0XHRHYW1lVGFnW0dhbWVUYWcuVEFHX1NDUklQVF9EQVRBX05VTV8yXSxcclxuXHRcdFx0XHRpdGVtLmVudGl0eURlZmludGlvbi50YWdzLmdldChHYW1lVGFnW0dhbWVUYWcuVEFHX1NDUklQVF9EQVRBX05VTV8yXSksXHJcblx0XHRcdCk7XHJcblx0XHRjb25zdCBmaW5hbEVudGl0eTogRW50aXR5ID0gcmVzdWx0LmdldChpdGVtLmVudGl0eURlZmludGlvbi5pZCkudXBkYXRlKHsgdGFnczogbmV3VGFncyB9KTtcclxuXHRcdHJldHVybiByZXN1bHQuc2V0KGZpbmFsRW50aXR5LmlkLCBmaW5hbEVudGl0eSk7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIGFkZEJhc2ljRGF0YShlbnRpdGllczogTWFwPG51bWJlciwgRW50aXR5Pik6IE1hcDxudW1iZXIsIEVudGl0eT4ge1xyXG5cdFx0cmV0dXJuIGVudGl0aWVzXHJcblx0XHRcdC5tYXAoKHZhbHVlOiBFbnRpdHkpID0+IHtcclxuXHRcdFx0XHRpZiAoIXZhbHVlLmNhcmRJRCkge1xyXG5cdFx0XHRcdFx0cmV0dXJuIHZhbHVlO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRjb25zdCBjYXJkID0gdGhpcy5hbGxDYXJkcy5nZXRDYXJkKHZhbHVlLmNhcmRJRCk7XHJcblx0XHRcdFx0bGV0IG5ld1RhZ3MgPSBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XHJcblx0XHRcdFx0aWYgKGNhcmQpIHtcclxuXHRcdFx0XHRcdGlmIChjYXJkLnR5cGUgPT09ICdTcGVsbCcgJiYgIXZhbHVlLmdldFRhZyhHYW1lVGFnLkNBUkRUWVBFKSkge1xyXG5cdFx0XHRcdFx0XHRuZXdUYWdzID0gdmFsdWUudGFncy5zZXQoR2FtZVRhZ1tHYW1lVGFnLkNBUkRUWVBFXSwgQ2FyZFR5cGUuU1BFTEwpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0aWYgKGNhcmQudHlwZSA9PT0gJ0VuY2hhbnRtZW50JyAmJiAhdmFsdWUuZ2V0VGFnKEdhbWVUYWcuQ0FSRFRZUEUpKSB7XHJcblx0XHRcdFx0XHRcdG5ld1RhZ3MgPSB2YWx1ZS50YWdzLnNldChHYW1lVGFnW0dhbWVUYWcuQ0FSRFRZUEVdLCBDYXJkVHlwZS5FTkNIQU5UTUVOVCk7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHJldHVybiB2YWx1ZS51cGRhdGUoeyB0YWdzOiBuZXdUYWdzIH0pO1xyXG5cdFx0XHR9KVxyXG5cdFx0XHQudG9NYXAoKTtcclxuXHR9XHJcbn1cclxuIl19