UNPKG

@dcl-sdk/utils

Version:

A collection of helpers to make it easier to build a Decentraland scene using the SDK 7.

352 lines 55.7 kB
import { engine, MeshRenderer, Schemas, Transform, Material, EntityState } from '@dcl/sdk/ecs'; import { Vector3, Color4, Color3 } from '@dcl/sdk/math'; import { getWorldPosition, getWorldRotation, areAABBIntersecting, areAABBSphereIntersecting, areSpheresIntersecting } from './math'; import { priority } from './priority'; export const LAYER_1 = 1; export const LAYER_2 = 2; export const LAYER_3 = 4; export const LAYER_4 = 8; export const LAYER_5 = 16; export const LAYER_6 = 32; export const LAYER_7 = 64; export const LAYER_8 = 128; export const ALL_LAYERS = 255; export const NO_LAYERS = 0; export let PLAYER_LAYER_ID = LAYER_1; function createTriggers(targetEngine) { const Trigger = engine.defineComponent('dcl.utils.Trigger', { active: Schemas.Boolean, layerMask: Schemas.Int, triggeredByMask: Schemas.Int, areas: Schemas.Array(Schemas.OneOf({ box: Schemas.Map({ position: Schemas.Vector3, scale: Schemas.Vector3 }), sphere: Schemas.Map({ position: Schemas.Vector3, radius: Schemas.Number }) })), debugColor: Schemas.Color3 }); const triggerEnterCbs = new Map(); const triggerExitCbs = new Map(); let debugDraw = false; const activeCollisions = new Map(); const debugEntities = new Map(); function updateDebugDraw(enabled) { if (!enabled) return; for (const [entity, trigger] of targetEngine.getEntitiesWith(Trigger, Transform)) { let shapes = debugEntities.get(entity); const areaCount = trigger.areas.length; while (shapes.length > areaCount) { targetEngine.removeEntity(shapes.pop()); } while (shapes.length < areaCount) { shapes.push(targetEngine.addEntity()); } const worldPosition = getWorldPosition(entity); const worldRotation = getWorldRotation(entity); for (let i = 0; i < areaCount; ++i) { const shapeSpec = trigger.areas[i]; const shape = shapes[i]; let scale; if (shapeSpec.$case == 'box') { scale = shapeSpec.value.scale; MeshRenderer.setBox(shape); } else { const radius = shapeSpec.value.radius; scale = { x: radius, y: radius, z: radius }; MeshRenderer.setSphere(shape); } Transform.createOrReplace(shape, { position: Vector3.add(worldPosition, Vector3.rotate(shapeSpec.value.position, worldRotation)), scale: scale }); const color = trigger.active ? trigger.debugColor : Color3.Black(); Material.setPbrMaterial(shape, { albedoColor: Color4.fromInts(255 * color.r, 255 * color.g, 255 * color.b, 75) }); } } } function areTriggersIntersecting(shapeWorldPos0, t0, shapeWorldPos1, t1) { for (let i = 0; i < t0.areas.length; ++i) { const t0World = shapeWorldPos0[i]; const t0Area = t0.areas[i]; if (t0Area.$case == 'box') { const t0Box = t0Area.value; const t0Min = Vector3.subtract(t0World, Vector3.scale(t0Box.scale, 0.5)); const t0Max = Vector3.add(t0Min, t0Box.scale); for (let j = 0; j < t1.areas.length; ++j) { const t1World = shapeWorldPos1[j]; const t1Area = t1.areas[j]; if (t1Area.$case == 'box') { const t1Box = t1Area.value; const t1Min = Vector3.subtract(t1World, Vector3.scale(t1Box.scale, 0.5)); const t1Max = Vector3.add(t1Min, t1Box.scale); if (areAABBIntersecting(t0Min, t0Max, t1Min, t1Max)) return true; } else { if (areAABBSphereIntersecting(t0Min, t0Max, t1World, t1Area.value.radius)) return true; } } } else { const t0Radius = t0Area.value.radius; for (let j = 0; j < t1.areas.length; ++j) { const t1World = shapeWorldPos1[j]; const t1Area = t1.areas[j]; if (t1Area.$case == 'box') { const t1Box = t1Area.value; const t1Min = Vector3.subtract(t1World, Vector3.scale(t1Box.scale, 0.5)); const t1Max = Vector3.add(t1Min, t1Box.scale); if (areAABBSphereIntersecting(t1Min, t1Max, t0World, t0Radius)) return true; } else { if (areSpheresIntersecting(t0World, t0Radius, t1World, t1Area.value.radius)) return true; } } } } return false; } function computeCollisions(entity, shapeWorldPos) { let collisions = EMPTY_IMMUTABLE_SET; const trigger = Trigger.get(entity); if (!trigger.active) return collisions; if (trigger.triggeredByMask == PLAYER_LAYER_ID) { const playerEntity = targetEngine.PlayerEntity; const playerTrigger = Trigger.get(targetEngine.PlayerEntity); if (playerEntity == entity) return collisions; if (!playerTrigger.active) return collisions; if (!(trigger.triggeredByMask & playerTrigger.layerMask)) return collisions; const intersecting = areTriggersIntersecting(shapeWorldPos.get(entity), trigger, shapeWorldPos.get(playerEntity), playerTrigger); if (intersecting) { if (collisions === EMPTY_IMMUTABLE_SET) collisions = new Set(); collisions.add(playerEntity); } } else { for (const [otherEntity, otherTrigger] of targetEngine.getEntitiesWith(Trigger, Transform)) { if (otherEntity == entity) continue; if (!otherTrigger.active) continue; if (!(trigger.triggeredByMask & otherTrigger.layerMask)) continue; const intersecting = areTriggersIntersecting(shapeWorldPos.get(entity), trigger, shapeWorldPos.get(otherEntity), otherTrigger); if (intersecting) { if (collisions === EMPTY_IMMUTABLE_SET) collisions = new Set(); collisions.add(otherEntity); } } } return collisions; } function updateCollisions() { const collisionsStarted = []; const collisionsEnded = []; const shapeWorldPositions = new Map(); for (const entity of activeCollisions.keys()) { if (targetEngine.getEntityState(entity) == EntityState.Removed || !Trigger.has(entity)) { for (const debugEntity of debugEntities.get(entity)) targetEngine.removeEntity(debugEntity); for (const collisions of activeCollisions.values()) { if (collisions.has(entity)) collisions.delete(entity); } debugEntities.delete(entity); activeCollisions.delete(entity); triggerEnterCbs.delete(entity); triggerExitCbs.delete(entity); continue; } const positions = []; const entityWorldPosition = getWorldPosition(entity); const entityWorldRotation = getWorldRotation(entity); const trigger = Trigger.get(entity); for (const shape of trigger.areas) { positions.push(Vector3.add(entityWorldPosition, Vector3.rotate(shape.value.position, entityWorldRotation))); } shapeWorldPositions.set(entity, positions); } for (const entity of activeCollisions.keys()) { const newCollisions = computeCollisions(entity, shapeWorldPositions); const oldCollisions = activeCollisions.get(entity); for (const oldCollision of oldCollisions) { if (!newCollisions.has(oldCollision)) collisionsEnded.push([entity, oldCollision]); } for (const newCollision of newCollisions) { if (!oldCollisions.has(newCollision)) collisionsStarted.push([entity, newCollision]); } activeCollisions.set(entity, newCollisions); } for (const [entity, collision] of collisionsStarted) { const callback = triggerEnterCbs.get(entity); if (callback) callback(collision); } for (const [entity, collision] of collisionsEnded) { const callback = triggerExitCbs.get(entity); if (callback) callback(collision); } } function system(dt) { updateCollisions(); updateDebugDraw(debugDraw); } targetEngine.addSystem(system, priority.TriggerSystemPriority); function triggerAreasFromSpec(areas) { if (!areas) areas = [{ type: 'box' }]; const triggerAreas = []; for (const area of areas) { if (area.type == 'box') { triggerAreas.push({ $case: 'box', value: { position: area.position ? area.position : Vector3.Zero(), scale: area.scale ? area.scale : Vector3.One() } }); } else { triggerAreas.push({ $case: 'sphere', value: { position: area.position ? area.position : Vector3.Zero(), radius: area.radius ? area.radius : 1 } }); } } return triggerAreas; } const triggersInterface = { addTrigger(entity, layerMask = NO_LAYERS, triggeredByMask = NO_LAYERS, areas, onEnterCallback, onExitCallback, debugColor) { if (layerMask < 0 || layerMask > ALL_LAYERS || !Number.isInteger(layerMask)) throw new Error(`Bad layerMask: ${layerMask}. Expected a non-negative integer no greater than ${ALL_LAYERS}`); if (triggeredByMask < 0 || triggeredByMask > ALL_LAYERS || !Number.isInteger(triggeredByMask)) throw new Error(`Bad triggeredByMask: ${triggeredByMask}. Expected a non-negative integer no greater than ${ALL_LAYERS}`); debugEntities.set(entity, []); activeCollisions.set(entity, new Set()); triggerEnterCbs.set(entity, onEnterCallback); triggerExitCbs.set(entity, onExitCallback); Trigger.createOrReplace(entity, { active: true, layerMask: layerMask, triggeredByMask: triggeredByMask, areas: triggerAreasFromSpec(areas), debugColor: debugColor ? debugColor : Color3.Red() }); }, removeTrigger(entity) { const collisions = activeCollisions.get(entity); const callback = triggerExitCbs.get(entity); for (const debugEntity of debugEntities.get(entity)) targetEngine.removeEntity(debugEntity); debugEntities.delete(entity); activeCollisions.delete(entity); triggerEnterCbs.delete(entity); triggerExitCbs.delete(entity); Trigger.deleteFrom(entity); const collidingEntities = []; for (const [otherEntity, otherEntityCollisions] of activeCollisions) { if (otherEntityCollisions.has(entity)) { otherEntityCollisions.delete(entity); collidingEntities.push(otherEntity); } } if (callback) { for (const collision of collisions) callback(collision); } for (const otherEntity of collidingEntities) { const callback = triggerExitCbs.get(otherEntity); if (callback) callback(entity); } }, oneTimeTrigger(entity, layerMask = NO_LAYERS, triggeredByMask = NO_LAYERS, areas, onEnterCallback, debugColor) { this.addTrigger(entity, layerMask, triggeredByMask, areas, function (e) { triggers.removeTrigger(entity); if (onEnterCallback) onEnterCallback(e); }, undefined, debugColor); }, enableTrigger(entity, enabled) { Trigger.getMutable(entity).active = enabled; }, isTriggerEnabled(entity) { return Trigger.get(entity).active; }, getLayerMask(entity) { return Trigger.get(entity).layerMask; }, setLayerMask(entity, mask) { if (mask < 0 || mask > ALL_LAYERS || !Number.isInteger(mask)) throw new Error(`Bad layerMask: ${mask}. Expected a non-negative integer no greater than ${ALL_LAYERS}`); Trigger.getMutable(entity).layerMask = mask; }, getTriggeredByMask(entity) { return Trigger.get(entity).triggeredByMask; }, setTriggeredByMask(entity, mask) { if (mask < 0 || mask > ALL_LAYERS || !Number.isInteger(mask)) throw new Error(`Bad layerMask: ${mask}. Expected a non-negative integer no greater than ${ALL_LAYERS}`); Trigger.getMutable(entity).triggeredByMask = mask; }, getAreas(entity) { return Trigger.get(entity).areas; }, setAreas(entity, areas) { Trigger.getMutable(entity).areas = triggerAreasFromSpec(areas); }, setOnEnterCallback(entity, callback) { triggerEnterCbs.set(entity, callback); }, setOnExitCallback(entity, callback) { triggerExitCbs.set(entity, callback); }, enableDebugDraw(enabled) { debugDraw = enabled; if (!enabled) { for (const shapes of debugEntities.values()) { for (const shape of shapes) targetEngine.removeEntity(shape); shapes.length = 0; } } }, isDebugDrawEnabled() { return debugDraw; } }; triggersInterface.addTrigger(targetEngine.PlayerEntity, PLAYER_LAYER_ID, NO_LAYERS, [{ type: 'box', scale: { x: 0.65, y: 1.92, z: 0.65 }, position: { x: 0, y: (1.92 / 2), z: 0 } }], undefined, undefined, Color3.Green()); return triggersInterface; } export const triggers = createTriggers(engine); const EMPTY_IMMUTABLE_SET = new Set(); EMPTY_IMMUTABLE_SET.add = (entity) => { debugger; throw new Error("EMPTY_SET is read only"); }; EMPTY_IMMUTABLE_SET.delete = (entity) => { throw new Error("EMPTY_SET is read only"); }; EMPTY_IMMUTABLE_SET.has = (entity) => { return false; }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJpZ2dlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy90cmlnZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQW1CLFlBQVksRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBZ0IsV0FBVyxFQUFFLE1BQU0sY0FBYyxDQUFBO0FBQzdILE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUN2RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsZ0JBQWdCLEVBQUUsbUJBQW1CLEVBQUUseUJBQXlCLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxRQUFRLENBQUE7QUFDbkksT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUVyQyxNQUFNLENBQUMsTUFBTSxPQUFPLEdBQUcsQ0FBQyxDQUFBO0FBQ3hCLE1BQU0sQ0FBQyxNQUFNLE9BQU8sR0FBRyxDQUFDLENBQUE7QUFDeEIsTUFBTSxDQUFDLE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQTtBQUN4QixNQUFNLENBQUMsTUFBTSxPQUFPLEdBQUcsQ0FBQyxDQUFBO0FBQ3hCLE1BQU0sQ0FBQyxNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUE7QUFDekIsTUFBTSxDQUFDLE1BQU0sT0FBTyxHQUFHLEVBQUUsQ0FBQTtBQUN6QixNQUFNLENBQUMsTUFBTSxPQUFPLEdBQUcsRUFBRSxDQUFBO0FBQ3pCLE1BQU0sQ0FBQyxNQUFNLE9BQU8sR0FBRyxHQUFHLENBQUE7QUFDMUIsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHLEdBQUcsQ0FBQTtBQUM3QixNQUFNLENBQUMsTUFBTSxTQUFTLEdBQUcsQ0FBQyxDQUFBO0FBRTFCLE1BQU0sQ0FBQyxJQUFJLGVBQWUsR0FBRyxPQUFPLENBQUE7QUE2QnBDLFNBQVMsY0FBYyxDQUFDLFlBQXFCO0lBQzVDLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxlQUFlLENBQUMsbUJBQW1CLEVBQUU7UUFDM0QsTUFBTSxFQUFFLE9BQU8sQ0FBQyxPQUFPO1FBQ3ZCLFNBQVMsRUFBRSxPQUFPLENBQUMsR0FBRztRQUN0QixlQUFlLEVBQUUsT0FBTyxDQUFDLEdBQUc7UUFDNUIsS0FBSyxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQztZQUNsQyxHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQztnQkFDaEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxPQUFPO2dCQUN6QixLQUFLLEVBQUUsT0FBTyxDQUFDLE9BQU87YUFDdEIsQ0FBQztZQUNGLE1BQU0sRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDO2dCQUNuQixRQUFRLEVBQUUsT0FBTyxDQUFDLE9BQU87Z0JBQ3pCLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTTthQUN0QixDQUFDO1NBQ0YsQ0FBQyxDQUFDO1FBQ0gsVUFBVSxFQUFFLE9BQU8sQ0FBQyxNQUFNO0tBQzFCLENBQUMsQ0FBQTtJQVVGLE1BQU0sZUFBZSxHQUFvRCxJQUFJLEdBQUcsRUFBRSxDQUFBO0lBQ2xGLE1BQU0sY0FBYyxHQUFtRCxJQUFJLEdBQUcsRUFBRSxDQUFBO0lBRWhGLElBQUksU0FBUyxHQUFHLEtBQUssQ0FBQTtJQUNyQixNQUFNLGdCQUFnQixHQUE2QixJQUFJLEdBQUcsRUFBRSxDQUFBO0lBQzVELE1BQU0sYUFBYSxHQUErQixJQUFJLEdBQUcsRUFBRSxDQUFBO0lBRTNELFNBQVMsZUFBZSxDQUFDLE9BQWdCO1FBQ3hDLElBQUksQ0FBQyxPQUFPO1lBQ1gsT0FBTTtRQUVQLEtBQUssTUFBTSxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsSUFBSSxZQUFZLENBQUMsZUFBZSxDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsRUFBRSxDQUFDO1lBQ2xGLElBQUksTUFBTSxHQUFHLGFBQWEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFFLENBQUE7WUFFdkMsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUE7WUFDdEMsT0FBTyxNQUFNLENBQUMsTUFBTSxHQUFHLFNBQVMsRUFBRSxDQUFDO2dCQUNsQyxZQUFZLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUcsQ0FBQyxDQUFBO1lBQ3pDLENBQUM7WUFDRCxPQUFPLE1BQU0sQ0FBQyxNQUFNLEdBQUcsU0FBUyxFQUFFLENBQUM7Z0JBQ2xDLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUE7WUFDdEMsQ0FBQztZQUVELE1BQU0sYUFBYSxHQUFHLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxDQUFBO1lBQzlDLE1BQU0sYUFBYSxHQUFHLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxDQUFBO1lBRTlDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxTQUFTLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDcEMsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQTtnQkFDbEMsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFBO2dCQUV2QixJQUFJLEtBQUssQ0FBQTtnQkFDVCxJQUFJLFNBQVMsQ0FBQyxLQUFLLElBQUksS0FBSyxFQUFFLENBQUM7b0JBQzlCLEtBQUssR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQTtvQkFDN0IsWUFBWSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQTtnQkFDM0IsQ0FBQztxQkFBTSxDQUFDO29CQUNQLE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFBO29CQUNyQyxLQUFLLEdBQUcsRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFBO29CQUMzQyxZQUFZLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFBO2dCQUM5QixDQUFDO2dCQUVELFNBQVMsQ0FBQyxlQUFlLENBQUMsS0FBSyxFQUFFO29CQUNoQyxRQUFRLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsT0FBTyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxhQUFhLENBQUMsQ0FBQztvQkFDN0YsS0FBSyxFQUFFLEtBQUs7aUJBQ1osQ0FBQyxDQUFBO2dCQUVGLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQTtnQkFDbEUsUUFBUSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxXQUFXLEVBQUUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLEdBQUcsS0FBSyxDQUFDLENBQUMsRUFBRSxHQUFHLEdBQUcsS0FBSyxDQUFDLENBQUMsRUFBRSxHQUFHLEdBQUcsS0FBSyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUE7WUFDbEgsQ0FBQztRQUNGLENBQUM7SUFDRixDQUFDO0lBRUQsU0FBUyx1QkFBdUIsQ0FDL0IsY0FBOEIsRUFDOUIsRUFBNkIsRUFDN0IsY0FBOEIsRUFDOUIsRUFBNkI7UUFFN0IsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUM7WUFDMUMsTUFBTSxPQUFPLEdBQUcsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQ2pDLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFFMUIsSUFBSSxNQUFNLENBQUMsS0FBSyxJQUFJLEtBQUssRUFBRSxDQUFDO2dCQUMzQixNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFBO2dCQUMxQixNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQTtnQkFDeEUsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFBO2dCQUU3QyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQztvQkFDMUMsTUFBTSxPQUFPLEdBQUcsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFBO29CQUNqQyxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFBO29CQUUxQixJQUFJLE1BQU0sQ0FBQyxLQUFLLElBQUksS0FBSyxFQUFFLENBQUM7d0JBQzNCLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUE7d0JBQzFCLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFBO3dCQUN4RSxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUE7d0JBRTdDLElBQUksbUJBQW1CLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxDQUFDOzRCQUNsRCxPQUFPLElBQUksQ0FBQTtvQkFDYixDQUFDO3lCQUFNLENBQUM7d0JBQ1AsSUFBSSx5QkFBeUIsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQzs0QkFDeEUsT0FBTyxJQUFJLENBQUE7b0JBQ2IsQ0FBQztnQkFDRixDQUFDO1lBQ0YsQ0FBQztpQkFBTSxDQUFDO2dCQUNQLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFBO2dCQUVwQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQztvQkFDMUMsTUFBTSxPQUFPLEdBQUcsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFBO29CQUNqQyxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFBO29CQUUxQixJQUFJLE1BQU0sQ0FBQyxLQUFLLElBQUksS0FBSyxFQUFFLENBQUM7d0JBQzNCLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUE7d0JBQzFCLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFBO3dCQUN4RSxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUE7d0JBRTdDLElBQUkseUJBQXlCLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDOzRCQUM3RCxPQUFPLElBQUksQ0FBQTtvQkFDYixDQUFDO3lCQUFNLENBQUM7d0JBQ1AsSUFBSSxzQkFBc0IsQ0FBQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQzs0QkFDMUUsT0FBTyxJQUFJLENBQUE7b0JBQ2IsQ0FBQztnQkFDRixDQUFDO1lBQ0YsQ0FBQztRQUNGLENBQUM7UUFFRCxPQUFPLEtBQUssQ0FBQTtJQUNiLENBQUM7SUFFRCxTQUFTLGlCQUFpQixDQUFDLE1BQWMsRUFBRSxhQUEwQztRQUNwRixJQUFJLFVBQVUsR0FBZ0IsbUJBQW1CLENBQUE7UUFDakQsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQTtRQUVuQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU07WUFDbEIsT0FBTyxVQUFVLENBQUE7UUFHbEIsSUFBSSxPQUFPLENBQUMsZUFBZSxJQUFJLGVBQWUsRUFBRSxDQUFDO1lBRWhELE1BQU0sWUFBWSxHQUFHLFlBQVksQ0FBQyxZQUFZLENBQUE7WUFDOUMsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDLENBQUE7WUFFNUQsSUFBSSxZQUFZLElBQUksTUFBTTtnQkFDekIsT0FBTyxVQUFVLENBQUE7WUFFbEIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNO2dCQUN4QixPQUFPLFVBQVUsQ0FBQTtZQUVsQixJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsZUFBZSxHQUFHLGFBQWEsQ0FBQyxTQUFTLENBQUM7Z0JBQ3ZELE9BQU8sVUFBVSxDQUFBO1lBRWxCLE1BQU0sWUFBWSxHQUFHLHVCQUF1QixDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFFLEVBQUUsT0FBTyxFQUFFLGFBQWEsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFFLEVBQUUsYUFBYSxDQUFDLENBQUE7WUFDbEksSUFBSSxZQUFZLEVBQUUsQ0FBQztnQkFDbEIsSUFBSSxVQUFVLEtBQUssbUJBQW1CO29CQUFFLFVBQVUsR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFBO2dCQUM5RCxVQUFVLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFBO1lBQzdCLENBQUM7UUFDRixDQUFDO2FBQU0sQ0FBQztZQUVQLEtBQUssTUFBTSxDQUFDLFdBQVcsRUFBRSxZQUFZLENBQUMsSUFBSSxZQUFZLENBQUMsZUFBZSxDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsRUFBRSxDQUFDO2dCQUM1RixJQUFJLFdBQVcsSUFBSSxNQUFNO29CQUN4QixTQUFRO2dCQUVULElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTTtvQkFDdkIsU0FBUTtnQkFFVCxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsZUFBZSxHQUFHLFlBQVksQ0FBQyxTQUFTLENBQUM7b0JBQ3RELFNBQVE7Z0JBRVQsTUFBTSxZQUFZLEdBQUcsdUJBQXVCLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUUsRUFBRSxPQUFPLEVBQUUsYUFBYSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUUsRUFBRSxZQUFZLENBQUMsQ0FBQTtnQkFDaEksSUFBSSxZQUFZLEVBQUUsQ0FBQztvQkFDbEIsSUFBSSxVQUFVLEtBQUssbUJBQW1CO3dCQUFFLFVBQVUsR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFBO29CQUM5RCxVQUFVLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFBO2dCQUM1QixDQUFDO1lBQ0YsQ0FBQztRQUNGLENBQUM7UUFLRCxPQUFPLFVBQVUsQ0FBQTtJQUNsQixDQUFDO0lBRUQsU0FBUyxnQkFBZ0I7UUFDeEIsTUFBTSxpQkFBaUIsR0FBRyxFQUFFLENBQUE7UUFDNUIsTUFBTSxlQUFlLEdBQUcsRUFBRSxDQUFBO1FBQzFCLE1BQU0sbUJBQW1CLEdBQWdDLElBQUksR0FBRyxFQUFFLENBQUE7UUFFbEUsS0FBSyxNQUFNLE1BQU0sSUFBSSxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDO1lBQzlDLElBQUksWUFBWSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsSUFBSSxXQUFXLENBQUMsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO2dCQUN4RixLQUFLLE1BQU0sV0FBVyxJQUFJLGFBQWEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFFO29CQUNuRCxZQUFZLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFBO2dCQUV2QyxLQUFLLE1BQU0sVUFBVSxJQUFJLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7b0JBQ3BELElBQUksVUFBVSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUM7d0JBQ3pCLFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUE7Z0JBQzNCLENBQUM7Z0JBRUQsYUFBYSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQTtnQkFDNUIsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFBO2dCQUMvQixlQUFlLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFBO2dCQUM5QixjQUFjLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFBO2dCQUM3QixTQUFRO1lBQ1QsQ0FBQztZQUVELE1BQU0sU0FBUyxHQUFHLEVBQUUsQ0FBQTtZQUNwQixNQUFNLG1CQUFtQixHQUFHLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxDQUFBO1lBQ3BELE1BQU0sbUJBQW1CLEdBQUcsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLENBQUE7WUFDcEQsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUVuQyxLQUFLLE1BQU0sS0FBSyxJQUFJLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDbkMsU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLG1CQUFtQixFQUFFLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsbUJBQW1CLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFDNUcsQ0FBQztZQUNELG1CQUFtQixDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUE7UUFDM0MsQ0FBQztRQUVELEtBQUssTUFBTSxNQUFNLElBQUksZ0JBQWdCLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQztZQUM5QyxNQUFNLGFBQWEsR0FBRyxpQkFBaUIsQ0FBQyxNQUFNLEVBQUUsbUJBQW1CLENBQUMsQ0FBQTtZQUNwRSxNQUFNLGFBQWEsR0FBRyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFFLENBQUE7WUFFbkQsS0FBSyxNQUFNLFlBQVksSUFBSSxhQUFhLEVBQUUsQ0FBQztnQkFDMUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDO29CQUNuQyxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUE7WUFDOUMsQ0FBQztZQUVELEtBQUssTUFBTSxZQUFZLElBQUksYUFBYSxFQUFFLENBQUM7Z0JBQzFDLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQztvQkFDbkMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUE7WUFDaEQsQ0FBQztZQUVELGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsYUFBYSxDQUFDLENBQUE7UUFDNUMsQ0FBQztRQUVELEtBQUssTUFBTSxDQUFDLE1BQU0sRUFBRSxTQUFTLENBQUMsSUFBSSxpQkFBaUIsRUFBRSxDQUFDO1lBQ3JELE1BQU0sUUFBUSxHQUFHLGVBQWUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUE7WUFDNUMsSUFBSSxRQUFRO2dCQUNYLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQTtRQUNyQixDQUFDO1FBRUQsS0FBSyxNQUFNLENBQUMsTUFBTSxFQUFFLFNBQVMsQ0FBQyxJQUFJLGVBQWUsRUFBRSxDQUFDO1lBQ25ELE1BQU0sUUFBUSxHQUFHLGNBQWMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUE7WUFDM0MsSUFBSSxRQUFRO2dCQUNYLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQTtRQUNyQixDQUFDO0lBQ0YsQ0FBQztJQUVELFNBQVMsTUFBTSxDQUFDLEVBQVU7UUFDekIsZ0JBQWdCLEVBQUUsQ0FBQTtRQUNsQixlQUFlLENBQUMsU0FBUyxDQUFDLENBQUE7SUFDM0IsQ0FBQztJQUVELFlBQVksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFBO0lBRTlELFNBQVMsb0JBQW9CLENBQUMsS0FBOEI7UUFDM0QsSUFBSSxDQUFDLEtBQUs7WUFDVCxLQUFLLEdBQUcsQ0FBQyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFBO1FBRTFCLE1BQU0sWUFBWSxHQUF1QixFQUFFLENBQUE7UUFFM0MsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUMxQixJQUFJLElBQUksQ0FBQyxJQUFJLElBQUksS0FBSyxFQUFFLENBQUM7Z0JBQ3hCLFlBQVksQ0FBQyxJQUFJLENBQUM7b0JBQ2pCLEtBQUssRUFBRSxLQUFLO29CQUNaLEtBQUssRUFBRTt3QkFDTixRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRTt3QkFDeEQsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUU7cUJBQzlDO2lCQUNELENBQUMsQ0FBQTtZQUNILENBQUM7aUJBQU0sQ0FBQztnQkFDUCxZQUFZLENBQUMsSUFBSSxDQUFDO29CQUNqQixLQUFLLEVBQUUsUUFBUTtvQkFDZixLQUFLLEVBQUU7d0JBQ04sUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUU7d0JBQ3hELE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO3FCQUNyQztpQkFDRCxDQUFDLENBQUE7WUFDSCxDQUFDO1FBQ0YsQ0FBQztRQUNELE9BQU8sWUFBWSxDQUFBO0lBQ3BCLENBQUM7SUFFRCxNQUFNLGlCQUFpQixHQUFHO1FBQ3pCLFVBQVUsQ0FDVCxNQUFjLEVBQ2QsWUFBb0IsU0FBUyxFQUM3QixrQkFBMEIsU0FBUyxFQUNuQyxLQUE4QixFQUM5QixlQUF3QyxFQUN4QyxjQUFzQyxFQUN0QyxVQUFtQjtZQUVuQixJQUFJLFNBQVMsR0FBRyxDQUFDLElBQUksU0FBUyxHQUFHLFVBQVUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDO2dCQUMxRSxNQUFNLElBQUksS0FBSyxDQUFDLGtCQUFrQixTQUFTLHFEQUFxRCxVQUFVLEVBQUUsQ0FBQyxDQUFBO1lBRTlHLElBQUksZUFBZSxHQUFHLENBQUMsSUFBSSxlQUFlLEdBQUcsVUFBVSxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxlQUFlLENBQUM7Z0JBQzVGLE1BQU0sSUFBSSxLQUFLLENBQUMsd0JBQXdCLGVBQWUscURBQXFELFVBQVUsRUFBRSxDQUFDLENBQUE7WUFFMUgsYUFBYSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUE7WUFDN0IsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxJQUFJLEdBQUcsRUFBRSxDQUFDLENBQUE7WUFDdkMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsZUFBZSxDQUFDLENBQUE7WUFDNUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsY0FBYyxDQUFDLENBQUE7WUFFMUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxNQUFNLEVBQUU7Z0JBQy9CLE1BQU0sRUFBRSxJQUFJO2dCQUNaLFNBQVMsRUFBRSxTQUFTO2dCQUNwQixlQUFlLEVBQUUsZUFBZTtnQkFDaEMsS0FBSyxFQUFFLG9CQUFvQixDQUFDLEtBQUssQ0FBQztnQkFDbEMsVUFBVSxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFO2FBQ2xELENBQUMsQ0FBQTtRQUNILENBQUM7UUFDRCxhQUFhLENBQUMsTUFBYztZQUMzQixNQUFNLFVBQVUsR0FBRyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFFLENBQUE7WUFDaEQsTUFBTSxRQUFRLEdBQUcsY0FBYyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUUzQyxLQUFLLE1BQU0sV0FBVyxJQUFJLGFBQWEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFFO2dCQUNuRCxZQUFZLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFBO1lBRXZDLGFBQWEsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUE7WUFDNUIsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1lBQy9CLGVBQWUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUE7WUFDOUIsY0FBYyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUM3QixPQUFPLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1lBRTFCLE1BQU0saUJBQWlCLEdBQUcsRUFBRSxDQUFBO1lBQzVCLEtBQUssTUFBTSxDQUFDLFdBQVcsRUFBRSxxQkFBcUIsQ0FBQyxJQUFJLGdCQUFnQixFQUFFLENBQUM7Z0JBQ3JFLElBQUkscUJBQXFCLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7b0JBQ3ZDLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQTtvQkFDcEMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFBO2dCQUNwQyxDQUFDO1lBQ0YsQ0FBQztZQUVELElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQ2QsS0FBSyxNQUFNLFNBQVMsSUFBSSxVQUFVO29CQUNqQyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUE7WUFDckIsQ0FBQztZQUVELEtBQUssTUFBTSxXQUFXLElBQUksaUJBQWlCLEVBQUUsQ0FBQztnQkFDN0MsTUFBTSxRQUFRLEdBQUcsY0FBYyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQTtnQkFDaEQsSUFBSSxRQUFRO29CQUNYLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUNsQixDQUFDO1FBQ0YsQ0FBQztRQUNELGNBQWMsQ0FDYixNQUFjLEVBQ2QsWUFBb0IsU0FBUyxFQUM3QixrQkFBMEIsU0FBUyxFQUNuQyxLQUE4QixFQUM5QixlQUF3QyxFQUN4QyxVQUFtQjtZQUVuQixJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxTQUFTLEVBQUUsZUFBZSxFQUFFLEtBQUssRUFBRSxVQUFVLENBQUM7Z0JBQ3JFLFFBQVEsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUE7Z0JBQzlCLElBQUksZUFBZTtvQkFDbEIsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQ3BCLENBQUMsRUFBRSxTQUFTLEVBQUUsVUFBVSxDQUFDLENBQUE7UUFDMUIsQ0FBQztRQUNELGFBQWEsQ0FBQyxNQUFjLEVBQUUsT0FBZ0I7WUFDN0MsT0FBTyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFBO1FBQzVDLENBQUM7UUFDRCxnQkFBZ0IsQ0FBQyxNQUFjO1lBQzlCLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLENBQUE7UUFDbEMsQ0FBQztRQUNELFlBQVksQ0FBQyxNQUFjO1lBQzFCLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxTQUFTLENBQUE7UUFDckMsQ0FBQztRQUNELFlBQVksQ0FBQyxNQUFjLEVBQUUsSUFBWTtZQUN4QyxJQUFJLElBQUksR0FBRyxDQUFDLElBQUksSUFBSSxHQUFHLFVBQVUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDO2dCQUMzRCxNQUFNLElBQUksS0FBSyxDQUFDLGtCQUFrQixJQUFJLHFEQUFxRCxVQUFVLEVBQUUsQ0FBQyxDQUFBO1lBQ3pHLE9BQU8sQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQTtRQUM1QyxDQUFDO1FBQ0Qsa0JBQWtCLENBQUMsTUFBYztZQUNoQyxPQUFPLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsZUFBZSxDQUFBO1FBQzNDLENBQUM7UUFDRCxrQkFBa0IsQ0FBQyxNQUFjLEVBQUUsSUFBWTtZQUM5QyxJQUFJLElBQUksR0FBRyxDQUFDLElBQUksSUFBSSxHQUFHLFVBQVUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDO2dCQUMzRCxNQUFNLElBQUksS0FBSyxDQUFDLGtCQUFrQixJQUFJLHFEQUFxRCxVQUFVLEVBQUUsQ0FBQyxDQUFBO1lBQ3pHLE9BQU8sQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQTtRQUNsRCxDQUFDO1FBQ0QsUUFBUSxDQUFDLE1BQWM7WUFDdEIsT0FBTyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQTtRQUNqQyxDQUFDO1FBQ0QsUUFBUSxDQUFDLE1BQWMsRUFBRSxLQUE2QjtZQUNyRCxPQUFPLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssR0FBRyxvQkFBb0IsQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUMvRCxDQUFDO1FBQ0Qsa0JBQWtCLENBQUMsTUFBYyxFQUFFLFFBQWdDO1lBQ2xFLGVBQWUsQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFBO1FBQ3RDLENBQUM7UUFDRCxpQkFBaUIsQ0FBQyxNQUFjLEVBQUUsUUFBK0I7WUFDaEUsY0FBYyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUE7UUFDckMsQ0FBQztRQUNELGVBQWUsQ0FBQyxPQUFnQjtZQUMvQixTQUFTLEdBQUcsT0FBTyxDQUFBO1lBQ25CLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDZCxLQUFLLE1BQU0sTUFBTSxJQUFJLGFBQWEsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO29CQUM3QyxLQUFLLE1BQU0sS0FBSyxJQUFJLE1BQU07d0JBQ3pCLFlBQVksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUE7b0JBQ2pDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFBO2dCQUNsQixDQUFDO1lBQ0YsQ0FBQztRQUNGLENBQUM7UUFDRCxrQkFBa0I7WUFDakIsT0FBTyxTQUFTLENBQUE7UUFDakIsQ0FBQztLQUNELENBQUE7SUFFRCxpQkFBaUIsQ0FBQyxVQUFVLENBQzNCLFlBQVksQ0FBQyxZQUFZLEVBQUUsZUFBZSxFQUFFLFNBQVMsRUFFckQsQ0FBQztZQUNBLElBQUksRUFBRSxLQUFLO1lBQ1gsS0FBSyxFQUFFLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUU7WUFDcEMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEdBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRTtTQUNyQyxDQUFDLEVBQ0YsU0FBUyxFQUFFLFNBQVMsRUFBRSxNQUFNLENBQUMsS0FBSyxFQUFFLENBQ3BDLENBQUE7SUFFRCxPQUFPLGlCQUFpQixDQUFBO0FBQ3pCLENBQUM7QUFFRCxNQUFNLENBQUMsTUFBTSxRQUFRLEdBQUcsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFBO0FBRzlDLE1BQU0sbUJBQW1CLEdBQWdCLElBQUksR0FBRyxFQUFFLENBQUE7QUFFbEQsbUJBQW1CLENBQUMsR0FBRyxHQUFHLENBQUMsTUFBYyxFQUFFLEVBQUUsR0FBRyxRQUFRLENBQUMsQ0FBQyxNQUFNLElBQUksS0FBSyxDQUFDLHdCQUF3QixDQUFDLENBQUEsQ0FBQyxDQUFDLENBQUE7QUFDckcsbUJBQW1CLENBQUMsTUFBTSxHQUFHLENBQUMsTUFBYyxFQUFFLEVBQUUsR0FBRyxNQUFNLElBQUksS0FBSyxDQUFDLHdCQUF3QixDQUFDLENBQUEsQ0FBQyxDQUFDLENBQUE7QUFDOUYsbUJBQW1CLENBQUMsR0FBRyxHQUFHLENBQUMsTUFBYyxFQUFFLEVBQUUsR0FBRyxPQUFPLEtBQUssQ0FBQSxDQUFDLENBQUMsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGVuZ2luZSwgRW50aXR5LCBJRW5naW5lLCBNZXNoUmVuZGVyZXIsIFNjaGVtYXMsIFRyYW5zZm9ybSwgTWF0ZXJpYWwsIERlZXBSZWFkb25seSwgRW50aXR5U3RhdGUgfSBmcm9tICdAZGNsL3Nkay9lY3MnXG5pbXBvcnQgeyBWZWN0b3IzLCBDb2xvcjQsIENvbG9yMyB9IGZyb20gJ0BkY2wvc2RrL21hdGgnXG5pbXBvcnQgeyBnZXRXb3JsZFBvc2l0aW9uLCBnZXRXb3JsZFJvdGF0aW9uLCBhcmVBQUJCSW50ZXJzZWN0aW5nLCBhcmVBQUJCU3BoZXJlSW50ZXJzZWN0aW5nLCBhcmVTcGhlcmVzSW50ZXJzZWN0aW5nIH0gZnJvbSAnLi9tYXRoJ1xuaW1wb3J0IHsgcHJpb3JpdHkgfSBmcm9tICcuL3ByaW9yaXR5J1xuXG5leHBvcnQgY29uc3QgTEFZRVJfMSA9IDFcbmV4cG9ydCBjb25zdCBMQVlFUl8yID0gMlxuZXhwb3J0IGNvbnN0IExBWUVSXzMgPSA0XG5leHBvcnQgY29uc3QgTEFZRVJfNCA9IDhcbmV4cG9ydCBjb25zdCBMQVlFUl81ID0gMTZcbmV4cG9ydCBjb25zdCBMQVlFUl82ID0gMzJcbmV4cG9ydCBjb25zdCBMQVlFUl83ID0gNjRcbmV4cG9ydCBjb25zdCBMQVlFUl84ID0gMTI4XG5leHBvcnQgY29uc3QgQUxMX0xBWUVSUyA9IDI1NVxuZXhwb3J0IGNvbnN0IE5PX0xBWUVSUyA9IDBcblxuZXhwb3J0IGxldCBQTEFZRVJfTEFZRVJfSUQgPSBMQVlFUl8xXG5cbmV4cG9ydCB0eXBlIFRyaWdnZXJCb3hBcmVhU3BlYyA9IHtcblx0dHlwZTogJ2JveCcsXG5cdHBvc2l0aW9uPzogVmVjdG9yMyxcblx0c2NhbGU/OiBWZWN0b3IzXG59XG5leHBvcnQgdHlwZSBUcmlnZ2VyU3BoZXJlQXJlYVNwZWMgPSB7XG5cdHR5cGU6ICdzcGhlcmUnLFxuXHRwb3NpdGlvbj86IFZlY3RvcjMsXG5cdHJhZGl1cz86IG51bWJlclxufVxuZXhwb3J0IHR5cGUgVHJpZ2dlckFyZWFTcGVjID0gVHJpZ2dlckJveEFyZWFTcGVjIHwgVHJpZ2dlclNwaGVyZUFyZWFTcGVjXG5cbmV4cG9ydCB0eXBlIFRyaWdnZXJCb3hBcmVhID0ge1xuXHRwb3NpdGlvbjogVmVjdG9yMyxcblx0c2NhbGU6IFZlY3RvcjNcbn1cbmV4cG9ydCB0eXBlIFRyaWdnZXJTcGhlcmVBcmVhID0ge1xuXHRwb3NpdGlvbjogVmVjdG9yMyxcblx0cmFkaXVzOiBudW1iZXJcbn1cbmV4cG9ydCB0eXBlIFRyaWdnZXJBcmVhID0geyAkY2FzZTogJ2JveCcsIHZhbHVlOiBUcmlnZ2VyQm94QXJlYSB9IHwgeyAkY2FzZTogJ3NwaGVyZScsIHZhbHVlOiBUcmlnZ2VyU3BoZXJlQXJlYSB9XG5cbnR5cGUgT25UcmlnZ2VyRW50ZXJDYWxsYmFjayA9IChlbnRpdHk6IEVudGl0eSkgPT4gdm9pZFxudHlwZSBPblRyaWdnZXJFeGl0Q2FsbGJhY2sgPSAoZW50aXR5OiBFbnRpdHkpID0+IHZvaWRcblxuZXhwb3J0IHR5cGUgVHJpZ2dlcnMgPSBSZXR1cm5UeXBlPHR5cGVvZiBjcmVhdGVUcmlnZ2Vycz5cblxuZnVuY3Rpb24gY3JlYXRlVHJpZ2dlcnModGFyZ2V0RW5naW5lOiBJRW5naW5lKSB7XG5cdGNvbnN0IFRyaWdnZXIgPSBlbmdpbmUuZGVmaW5lQ29tcG9uZW50KCdkY2wudXRpbHMuVHJpZ2dlcicsIHtcblx0XHRhY3RpdmU6IFNjaGVtYXMuQm9vbGVhbixcblx0XHRsYXllck1hc2s6IFNjaGVtYXMuSW50LFxuXHRcdHRyaWdnZXJlZEJ5TWFzazogU2NoZW1hcy5JbnQsXG5cdFx0YXJlYXM6IFNjaGVtYXMuQXJyYXkoU2NoZW1hcy5PbmVPZih7XG5cdFx0XHRib3g6IFNjaGVtYXMuTWFwKHtcblx0XHRcdFx0cG9zaXRpb246IFNjaGVtYXMuVmVjdG9yMyxcblx0XHRcdFx0c2NhbGU6IFNjaGVtYXMuVmVjdG9yM1xuXHRcdFx0fSksXG5cdFx0XHRzcGhlcmU6IFNjaGVtYXMuTWFwKHtcblx0XHRcdFx0cG9zaXRpb246IFNjaGVtYXMuVmVjdG9yMyxcblx0XHRcdFx0cmFkaXVzOiBTY2hlbWFzLk51bWJlclxuXHRcdFx0fSlcblx0XHR9KSksXG5cdFx0ZGVidWdDb2xvcjogU2NoZW1hcy5Db2xvcjNcblx0fSlcblxuXHR0eXBlIFRyaWdnZXJUeXBlID0ge1xuXHRcdGFjdGl2ZTogYm9vbGVhbixcblx0XHRsYXllck1hc2s6IG51bWJlcixcblx0XHR0cmlnZ2VyZWRCeU1hc2s6IG51bWJlcixcblx0XHRhcmVhczogQXJyYXk8VHJpZ2dlckFyZWE+LFxuXHRcdGRlYnVnQ29sb3I6IENvbG9yM1xuXHR9XG5cblx0Y29uc3QgdHJpZ2dlckVudGVyQ2JzOiBNYXA8RW50aXR5LCBPblRyaWdnZXJFbnRlckNhbGxiYWNrIHwgdW5kZWZpbmVkPiA9IG5ldyBNYXAoKVxuXHRjb25zdCB0cmlnZ2VyRXhpdENiczogTWFwPEVudGl0eSwgT25UcmlnZ2VyRXhpdENhbGxiYWNrIHwgdW5kZWZpbmVkPiA9IG5ldyBNYXAoKVxuXG5cdGxldCBkZWJ1Z0RyYXcgPSBmYWxzZVxuXHRjb25zdCBhY3RpdmVDb2xsaXNpb25zOiBNYXA8RW50aXR5LCBTZXQ8RW50aXR5Pj4gPSBuZXcgTWFwKClcblx0Y29uc3QgZGVidWdFbnRpdGllczogTWFwPEVudGl0eSwgQXJyYXk8RW50aXR5Pj4gPSBuZXcgTWFwKClcblxuXHRmdW5jdGlvbiB1cGRhdGVEZWJ1Z0RyYXcoZW5hYmxlZDogYm9vbGVhbikge1xuXHRcdGlmICghZW5hYmxlZClcblx0XHRcdHJldHVyblxuXG5cdFx0Zm9yIChjb25zdCBbZW50aXR5LCB0cmlnZ2VyXSBvZiB0YXJnZXRFbmdpbmUuZ2V0RW50aXRpZXNXaXRoKFRyaWdnZXIsIFRyYW5zZm9ybSkpIHtcblx0XHRcdGxldCBzaGFwZXMgPSBkZWJ1Z0VudGl0aWVzLmdldChlbnRpdHkpIVxuXG5cdFx0XHRjb25zdCBhcmVhQ291bnQgPSB0cmlnZ2VyLmFyZWFzLmxlbmd0aFxuXHRcdFx0d2hpbGUgKHNoYXBlcy5sZW5ndGggPiBhcmVhQ291bnQpIHtcblx0XHRcdFx0dGFyZ2V0RW5naW5lLnJlbW92ZUVudGl0eShzaGFwZXMucG9wKCkhKVxuXHRcdFx0fVxuXHRcdFx0d2hpbGUgKHNoYXBlcy5sZW5ndGggPCBhcmVhQ291bnQpIHtcblx0XHRcdFx0c2hhcGVzLnB1c2godGFyZ2V0RW5naW5lLmFkZEVudGl0eSgpKVxuXHRcdFx0fVxuXG5cdFx0XHRjb25zdCB3b3JsZFBvc2l0aW9uID0gZ2V0V29ybGRQb3NpdGlvbihlbnRpdHkpXG5cdFx0XHRjb25zdCB3b3JsZFJvdGF0aW9uID0gZ2V0V29ybGRSb3RhdGlvbihlbnRpdHkpXG5cblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgYXJlYUNvdW50OyArK2kpIHtcblx0XHRcdFx0Y29uc3Qgc2hhcGVTcGVjID0gdHJpZ2dlci5hcmVhc1tpXVxuXHRcdFx0XHRjb25zdCBzaGFwZSA9IHNoYXBlc1tpXVxuXG5cdFx0XHRcdGxldCBzY2FsZVxuXHRcdFx0XHRpZiAoc2hhcGVTcGVjLiRjYXNlID09ICdib3gnKSB7XG5cdFx0XHRcdFx0c2NhbGUgPSBzaGFwZVNwZWMudmFsdWUuc2NhbGVcblx0XHRcdFx0XHRNZXNoUmVuZGVyZXIuc2V0Qm94KHNoYXBlKVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGNvbnN0IHJhZGl1cyA9IHNoYXBlU3BlYy52YWx1ZS5yYWRpdXNcblx0XHRcdFx0XHRzY2FsZSA9IHsgeDogcmFkaXVzLCB5OiByYWRpdXMsIHo6IHJhZGl1cyB9XG5cdFx0XHRcdFx0TWVzaFJlbmRlcmVyLnNldFNwaGVyZShzaGFwZSlcblx0XHRcdFx0fVxuXG5cdFx0XHRcdFRyYW5zZm9ybS5jcmVhdGVPclJlcGxhY2Uoc2hhcGUsIHtcblx0XHRcdFx0XHRwb3NpdGlvbjogVmVjdG9yMy5hZGQod29ybGRQb3NpdGlvbiwgVmVjdG9yMy5yb3RhdGUoc2hhcGVTcGVjLnZhbHVlLnBvc2l0aW9uLCB3b3JsZFJvdGF0aW9uKSksXG5cdFx0XHRcdFx0c2NhbGU6IHNjYWxlXG5cdFx0XHRcdH0pXG5cblx0XHRcdFx0Y29uc3QgY29sb3IgPSB0cmlnZ2VyLmFjdGl2ZSA/IHRyaWdnZXIuZGVidWdDb2xvciA6IENvbG9yMy5CbGFjaygpXG5cdFx0XHRcdE1hdGVyaWFsLnNldFBick1hdGVyaWFsKHNoYXBlLCB7IGFsYmVkb0NvbG9yOiBDb2xvcjQuZnJvbUludHMoMjU1ICogY29sb3IuciwgMjU1ICogY29sb3IuZywgMjU1ICogY29sb3IuYiwgNzUpIH0pXG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0ZnVuY3Rpb24gYXJlVHJpZ2dlcnNJbnRlcnNlY3RpbmcoXG5cdFx0c2hhcGVXb3JsZFBvczA6IEFycmF5PFZlY3RvcjM+LFxuXHRcdHQwOiBEZWVwUmVhZG9ubHk8VHJpZ2dlclR5cGU+LFxuXHRcdHNoYXBlV29ybGRQb3MxOiBBcnJheTxWZWN0b3IzPixcblx0XHR0MTogRGVlcFJlYWRvbmx5PFRyaWdnZXJUeXBlPlxuXHQpOiBib29sZWFuIHtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHQwLmFyZWFzLmxlbmd0aDsgKytpKSB7XG5cdFx0XHRjb25zdCB0MFdvcmxkID0gc2hhcGVXb3JsZFBvczBbaV1cblx0XHRcdGNvbnN0IHQwQXJlYSA9IHQwLmFyZWFzW2ldXG5cblx0XHRcdGlmICh0MEFyZWEuJGNhc2UgPT0gJ2JveCcpIHtcblx0XHRcdFx0Y29uc3QgdDBCb3ggPSB0MEFyZWEudmFsdWVcblx0XHRcdFx0Y29uc3QgdDBNaW4gPSBWZWN0b3IzLnN1YnRyYWN0KHQwV29ybGQsIFZlY3RvcjMuc2NhbGUodDBCb3guc2NhbGUsIDAuNSkpXG5cdFx0XHRcdGNvbnN0IHQwTWF4ID0gVmVjdG9yMy5hZGQodDBNaW4sIHQwQm94LnNjYWxlKVxuXG5cdFx0XHRcdGZvciAobGV0IGogPSAwOyBqIDwgdDEuYXJlYXMubGVuZ3RoOyArK2opIHtcblx0XHRcdFx0XHRjb25zdCB0MVdvcmxkID0gc2hhcGVXb3JsZFBvczFbal1cblx0XHRcdFx0XHRjb25zdCB0MUFyZWEgPSB0MS5hcmVhc1tqXVxuXG5cdFx0XHRcdFx0aWYgKHQxQXJlYS4kY2FzZSA9PSAnYm94Jykge1xuXHRcdFx0XHRcdFx0Y29uc3QgdDFCb3ggPSB0MUFyZWEudmFsdWVcblx0XHRcdFx0XHRcdGNvbnN0IHQxTWluID0gVmVjdG9yMy5zdWJ0cmFjdCh0MVdvcmxkLCBWZWN0b3IzLnNjYWxlKHQxQm94LnNjYWxlLCAwLjUpKVxuXHRcdFx0XHRcdFx0Y29uc3QgdDFNYXggPSBWZWN0b3IzLmFkZCh0MU1pbiwgdDFCb3guc2NhbGUpXG5cblx0XHRcdFx0XHRcdGlmIChhcmVBQUJCSW50ZXJzZWN0aW5nKHQwTWluLCB0ME1heCwgdDFNaW4sIHQxTWF4KSlcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHRydWVcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0aWYgKGFyZUFBQkJTcGhlcmVJbnRlcnNlY3RpbmcodDBNaW4sIHQwTWF4LCB0MVdvcmxkLCB0MUFyZWEudmFsdWUucmFkaXVzKSlcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHRydWVcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGNvbnN0IHQwUmFkaXVzID0gdDBBcmVhLnZhbHVlLnJhZGl1c1xuXG5cdFx0XHRcdGZvciAobGV0IGogPSAwOyBqIDwgdDEuYXJlYXMubGVuZ3RoOyArK2opIHtcblx0XHRcdFx0XHRjb25zdCB0MVdvcmxkID0gc2hhcGVXb3JsZFBvczFbal1cblx0XHRcdFx0XHRjb25zdCB0MUFyZWEgPSB0MS5hcmVhc1tqXVxuXG5cdFx0XHRcdFx0aWYgKHQxQXJlYS4kY2FzZSA9PSAnYm94Jykge1xuXHRcdFx0XHRcdFx0Y29uc3QgdDFCb3ggPSB0MUFyZWEudmFsdWVcblx0XHRcdFx0XHRcdGNvbnN0IHQxTWluID0gVmVjdG9yMy5zdWJ0cmFjdCh0MVdvcmxkLCBWZWN0b3IzLnNjYWxlKHQxQm94LnNjYWxlLCAwLjUpKVxuXHRcdFx0XHRcdFx0Y29uc3QgdDFNYXggPSBWZWN0b3IzLmFkZCh0MU1pbiwgdDFCb3guc2NhbGUpXG5cblx0XHRcdFx0XHRcdGlmIChhcmVBQUJCU3BoZXJlSW50ZXJzZWN0aW5nKHQxTWluLCB0MU1heCwgdDBXb3JsZCwgdDBSYWRpdXMpKVxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZVxuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRpZiAoYXJlU3BoZXJlc0ludGVyc2VjdGluZyh0MFdvcmxkLCB0MFJhZGl1cywgdDFXb3JsZCwgdDFBcmVhLnZhbHVlLnJhZGl1cykpXG5cdFx0XHRcdFx0XHRcdHJldHVybiB0cnVlXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlXG5cdH1cblxuXHRmdW5jdGlvbiBjb21wdXRlQ29sbGlzaW9ucyhlbnRpdHk6IEVudGl0eSwgc2hhcGVXb3JsZFBvczogTWFwPEVudGl0eSwgQXJyYXk8VmVjdG9yMz4+KSB7XG5cdFx0bGV0IGNvbGxpc2lvbnM6IFNldDxFbnRpdHk+ID0gRU1QVFlfSU1NVVRBQkxFX1NFVFxuXHRcdGNvbnN0IHRyaWdnZXIgPSBUcmlnZ2VyLmdldChlbnRpdHkpXG5cblx0XHRpZiAoIXRyaWdnZXIuYWN0aXZlKVxuXHRcdFx0cmV0dXJuIGNvbGxpc2lvbnNcblxuXG5cdFx0aWYgKHRyaWdnZXIudHJpZ2dlcmVkQnlNYXNrID09IFBMQVlFUl9MQVlFUl9JRCkge1xuXHRcdFx0Ly8gY2hlY2sganVzdCBwbGF5ZXIgXG5cdFx0XHRjb25zdCBwbGF5ZXJFbnRpdHkgPSB0YXJnZXRFbmdpbmUuUGxheWVyRW50aXR5XG5cdFx0XHRjb25zdCBwbGF5ZXJUcmlnZ2VyID0gVHJpZ2dlci5nZXQodGFyZ2V0RW5naW5lLlBsYXllckVudGl0eSlcblxuXHRcdFx0aWYgKHBsYXllckVudGl0eSA9PSBlbnRpdHkpXG5cdFx0XHRcdHJldHVybiBjb2xsaXNpb25zXG5cblx0XHRcdGlmICghcGxheWVyVHJpZ2dlci5hY3RpdmUpXG5cdFx0XHRcdHJldHVybiBjb2xsaXNpb25zXG5cblx0XHRcdGlmICghKHRyaWdnZXIudHJpZ2dlcmVkQnlNYXNrICYgcGxheWVyVHJpZ2dlci5sYXllck1hc2spKVxuXHRcdFx0XHRyZXR1cm4gY29sbGlzaW9uc1xuXG5cdFx0XHRjb25zdCBpbnRlcnNlY3RpbmcgPSBhcmVUcmlnZ2Vyc0ludGVyc2VjdGluZyhzaGFwZVdvcmxkUG9zLmdldChlbnRpdHkpISwgdHJpZ2dlciwgc2hhcGVXb3JsZFBvcy5nZXQocGxheWVyRW50aXR5KSEsIHBsYXllclRyaWdnZXIpXG5cdFx0XHRpZiAoaW50ZXJzZWN0aW5nKSB7XG5cdFx0XHRcdGlmIChjb2xsaXNpb25zID09PSBFTVBUWV9JTU1VVEFCTEVfU0VUKSBjb2xsaXNpb25zID0gbmV3IFNldCgpXG5cdFx0XHRcdGNvbGxpc2lvbnMuYWRkKHBsYXllckVudGl0eSlcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gaXRlcmF0ZSBvdmVyIGZ1bGwgbGlzdCBvZiB0cmlnZ2Vyc1xuXHRcdFx0Zm9yIChjb25zdCBbb3RoZXJFbnRpdHksIG90aGVyVHJpZ2dlcl0gb2YgdGFyZ2V0RW5naW5lLmdldEVudGl0aWVzV2l0aChUcmlnZ2VyLCBUcmFuc2Zvcm0pKSB7XG5cdFx0XHRcdGlmIChvdGhlckVudGl0eSA9PSBlbnRpdHkpXG5cdFx0XHRcdFx0Y29udGludWVcblxuXHRcdFx0XHRpZiAoIW90aGVyVHJpZ2dlci5hY3RpdmUpXG5cdFx0XHRcdFx0Y29udGludWVcblxuXHRcdFx0XHRpZiAoISh0cmlnZ2VyLnRyaWdnZXJlZEJ5TWFzayAmIG90aGVyVHJpZ2dlci5sYXllck1hc2spKVxuXHRcdFx0XHRcdGNvbnRpbnVlXG5cblx0XHRcdFx0Y29uc3QgaW50ZXJzZWN0aW5nID0gYXJlVHJpZ2dlcnNJbnRlcnNlY3Rpbmcoc2hhcGVXb3JsZFBvcy5nZXQoZW50aXR5KSEsIHRyaWdnZXIsIHNoYXBlV29ybGRQb3MuZ2V0KG90aGVyRW50aXR5KSEsIG90aGVyVHJpZ2dlcilcblx0XHRcdFx0aWYgKGludGVyc2VjdGluZykge1xuXHRcdFx0XHRcdGlmIChjb2xsaXNpb25zID09PSBFTVBUWV9JTU1VVEFCTEVfU0VUKSBjb2xsaXNpb25zID0gbmV3IFNldCgpXG5cdFx0XHRcdFx0Y29sbGlzaW9ucy5hZGQob3RoZXJFbnRpdHkpXG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblxuXG5cblx0XHRyZXR1cm4gY29sbGlzaW9uc1xuXHR9XG5cblx0ZnVuY3Rpb24gdXBkYXRlQ29sbGlzaW9ucygpIHtcblx0XHRjb25zdCBjb2xsaXNpb25zU3RhcnRlZCA9IFtdXG5cdFx0Y29uc3QgY29sbGlzaW9uc0VuZGVkID0gW11cblx0XHRjb25zdCBzaGFwZVdvcmxkUG9zaXRpb25zOiBNYXA8RW50aXR5LCBBcnJheTxWZWN0b3IzPj4gPSBuZXcgTWFwKClcblxuXHRcdGZvciAoY29uc3QgZW50aXR5IG9mIGFjdGl2ZUNvbGxpc2lvbnMua2V5cygpKSB7XG5cdFx0XHRpZiAodGFyZ2V0RW5naW5lLmdldEVudGl0eVN0YXRlKGVudGl0eSkgPT0gRW50aXR5U3RhdGUuUmVtb3ZlZCB8fCAhVHJpZ2dlci5oYXMoZW50aXR5KSkge1xuXHRcdFx0XHRmb3IgKGNvbnN0IGRlYnVnRW50aXR5IG9mIGRlYnVnRW50aXRpZXMuZ2V0KGVudGl0eSkhKVxuXHRcdFx0XHRcdHRhcmdldEVuZ2luZS5yZW1vdmVFbnRpdHkoZGVidWdFbnRpdHkpXG5cblx0XHRcdFx0Zm9yIChjb25zdCBjb2xsaXNpb25zIG9mIGFjdGl2ZUNvbGxpc2lvbnMudmFsdWVzKCkpIHtcblx0XHRcdFx0XHRpZiAoY29sbGlzaW9ucy5oYXMoZW50aXR5KSlcblx0XHRcdFx0XHRcdGNvbGxpc2lvbnMuZGVsZXRlKGVudGl0eSlcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGRlYnVnRW50aXRpZXMuZGVsZXRlKGVudGl0eSlcblx0XHRcdFx0YWN0aXZlQ29sbGlzaW9ucy5kZWxldGUoZW50aXR5KVxuXHRcdFx0XHR0cmlnZ2VyRW50ZXJDYnMuZGVsZXRlKGVudGl0eSlcblx0XHRcdFx0dHJpZ2dlckV4aXRDYnMuZGVsZXRlKGVudGl0eSlcblx0XHRcdFx0Y29udGludWVcblx0XHRcdH1cblxuXHRcdFx0Y29uc3QgcG9zaXRpb25zID0gW11cblx0XHRcdGNvbnN0IGVudGl0eVdvcmxkUG9zaXRpb24gPSBnZXRXb3JsZFBvc2l0aW9uKGVudGl0eSlcblx0XHRcdGNvbnN0IGVudGl0eVdvcmxkUm90YXRpb24gPSBnZXRXb3JsZFJvdGF0aW9uKGVudGl0eSlcblx0XHRcdGNvbnN0IHRyaWdnZXIgPSBUcmlnZ2VyLmdldChlbnRpdHkpXG5cblx0XHRcdGZvciAoY29uc3Qgc2hhcGUgb2YgdHJpZ2dlci5hcmVhcykge1xuXHRcdFx0XHRwb3NpdGlvbnMucHVzaChWZWN0b3IzLmFkZChlbnRpdHlXb3JsZFBvc2l0aW9uLCBWZWN0b3IzLnJvdGF0ZShzaGFwZS52YWx1ZS5wb3NpdGlvbiwgZW50aXR5V29ybGRSb3RhdGlvbikpKVxuXHRcdFx0fVxuXHRcdFx0c2hhcGVXb3JsZFBvc2l0aW9ucy5zZXQoZW50aXR5LCBwb3NpdGlvbnMpXG5cdFx0fVxuXG5cdFx0Zm9yIChjb25zdCBlbnRpdHkgb2YgYWN0aXZlQ29sbGlzaW9ucy5rZXlzKCkpIHtcblx0XHRcdGNvbnN0IG5ld0NvbGxpc2lvbnMgPSBjb21wdXRlQ29sbGlzaW9ucyhlbnRpdHksIHNoYXBlV29ybGRQb3NpdGlvbnMpXG5cdFx0XHRjb25zdCBvbGRDb2xsaXNpb25zID0gYWN0aXZlQ29sbGlzaW9ucy5nZXQoZW50aXR5KSFcblxuXHRcdFx0Zm9yIChjb25zdCBvbGRDb2xsaXNpb24gb2Ygb2xkQ29sbGlzaW9ucykge1xuXHRcdFx0XHRpZiAoIW5ld0NvbGxpc2lvbnMuaGFzKG9sZENvbGxpc2lvbikpXG5cdFx0XHRcdFx0Y29sbGlzaW9uc0VuZGVkLnB1c2goW2VudGl0eSwgb2xkQ29sbGlzaW9uXSlcblx0XHRcdH1cblxuXHRcdFx0Zm9yIChjb25zdCBuZXdDb2xsaXNpb24gb2YgbmV3Q29sbGlzaW9ucykge1xuXHRcdFx0XHRpZiAoIW9sZENvbGxpc2lvbnMuaGFzKG5ld0NvbGxpc2lvbikpXG5cdFx0XHRcdFx0Y29sbGlzaW9uc1N0YXJ0ZWQucHVzaChbZW50aXR5LCBuZXdDb2xsaXNpb25dKVxuXHRcdFx0fVxuXG5cdFx0XHRhY3RpdmVDb2xsaXNpb25zLnNldChlbnRpdHksIG5ld0NvbGxpc2lvbnMpXG5cdFx0fVxuXG5cdFx0Zm9yIChjb25zdCBbZW50aXR5LCBjb2xsaXNpb25dIG9mIGNvbGxpc2lvbnNTdGFydGVkKSB7XG5cdFx0XHRjb25zdCBjYWxsYmFjayA9IHRyaWdnZXJFbnRlckNicy5nZXQoZW50aXR5KVxuXHRcdFx0aWYgKGNhbGxiYWNrKVxuXHRcdFx0XHRjYWxsYmFjayhjb2xsaXNpb24pXG5cdFx0fVxuXG5cdFx0Zm9yIChjb25zdCBbZW50aXR5LCBjb2xsaXNpb25dIG9mIGNvbGxpc2lvbnNFbmRlZCkge1xuXHRcdFx0Y29uc3QgY2FsbGJhY2sgPSB0cmlnZ2VyRXhpdENicy5nZXQoZW50aXR5KVxuXHRcdFx0aWYgKGNhbGxiYWNrKVxuXHRcdFx0XHRjYWxsYmFjayhjb2xsaXNpb24pXG5cdFx0fVxuXHR9XG5cblx0ZnVuY3Rpb24gc3lzdGVtKGR0OiBudW1iZXIpIHtcblx0XHR1cGRhdGVDb2xsaXNpb25zKClcblx0XHR1cGRhdGVEZWJ1Z0RyYXcoZGVidWdEcmF3KVxuXHR9XG5cblx0dGFyZ2V0RW5naW5lLmFkZFN5c3RlbShzeXN0ZW0sIHByaW9yaXR5LlRyaWdnZXJTeXN0ZW1Qcmlvcml0eSlcblxuXHRmdW5jdGlvbiB0cmlnZ2VyQXJlYXNGcm9tU3BlYyhhcmVhcz86IEFycmF5PFRyaWdnZXJBcmVhU3BlYz4pIHtcblx0XHRpZiAoIWFyZWFzKVxuXHRcdFx0YXJlYXMgPSBbeyB0eXBlOiAnYm94JyB9XVxuXG5cdFx0Y29uc3QgdHJpZ2dlckFyZWFzOiBBcnJheTxUcmlnZ2VyQXJlYT4gPSBbXVxuXG5cdFx0Zm9yIChjb25zdCBhcmVhIG9mIGFyZWFzKSB7XG5cdFx0XHRpZiAoYXJlYS50eXBlID09ICdib3gnKSB7XG5cdFx0XHRcdHRyaWdnZXJBcmVhcy5wdXNoKHtcblx0XHRcdFx0XHQkY2FzZTogJ2JveCcsXG5cdFx0XHRcdFx0dmFsdWU6IHtcblx0XHRcdFx0XHRcdHBvc2l0aW9uOiBhcmVhLnBvc2l0aW9uID8gYXJlYS5wb3NpdGlvbiA6IFZlY3RvcjMuWmVybygpLFxuXHRcdFx0XHRcdFx0c2NhbGU6IGFyZWEuc2NhbGUgPyBhcmVhLnNjYWxlIDogVmVjdG9yMy5PbmUoKVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSlcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRyaWdnZXJBcmVhcy5wdXNoKHtcblx0XHRcdFx0XHQkY2FzZTogJ3NwaGVyZScsXG5cdFx0XHRcdFx0dmFsdWU6IHtcblx0XHRcdFx0XHRcdHBvc2l0aW9uOiBhcmVhLnBvc2l0aW9uID8gYXJlYS5wb3NpdGlvbiA6IFZlY3RvcjMuWmVybygpLFxuXHRcdFx0XHRcdFx0cmFkaXVzOiBhcmVhLnJhZGl1cyA/IGFyZWEucmFkaXVzIDogMVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSlcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRyaWdnZXJBcmVhc1xuXHR9XG5cblx0Y29uc3QgdHJpZ2dlcnNJbnRlcmZhY2UgPSB7XG5cdFx0YWRkVHJpZ2dlcihcblx0XHRcdGVudGl0eTogRW50aXR5LFxuXHRcdFx0bGF5ZXJNYXNrOiBudW1iZXIgPSBOT19MQVlFUlMsXG5cdFx0XHR0cmlnZ2VyZWRCeU1hc2s6IG51bWJlciA9IE5PX0xBWUVSUyxcblx0XHRcdGFyZWFzPzogQXJyYXk8VHJpZ2dlckFyZWFTcGVjPixcblx0XHRcdG9uRW50ZXJDYWxsYmFjaz86IE9uVHJpZ2dlckVudGVyQ2FsbGJhY2ssXG5cdFx0XHRvbkV4aXRDYWxsYmFjaz86IE9uVHJpZ2dlckV4aXRDYWxsYmFjayxcblx0XHRcdGRlYnVnQ29sb3I/OiBDb2xvcjNcblx0XHQpIHtcblx0XHRcdGlmIChsYXllck1hc2sgPCAwIHx8IGxheWVyTWFzayA+IEFMTF9MQVlFUlMgfHwgIU51bWJlci5pc0ludGVnZXIobGF5ZXJNYXNrKSlcblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKGBCYWQgbGF5ZXJNYXNrOiAke2xheWVyTWFza30uIEV4cGVjdGVkIGEgbm9uLW5lZ2F0aXZlIGludGVnZXIgbm8gZ3JlYXRlciB0aGFuICR7QUxMX0xBWUVSU31gKVxuXG5cdFx0XHRpZiAodHJpZ2dlcmVkQnlNYXNrIDwgMCB8fCB0cmlnZ2VyZWRCeU1hc2sgPiBBTExfTEFZRVJTIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKHRyaWdnZXJlZEJ5TWFzaykpXG5cdFx0XHRcdHRocm93IG5ldyBFcnJvcihgQmFkIHRyaWdnZXJlZEJ5TWFzazogJHt0cmlnZ2VyZWRCeU1hc2t9LiBFeHBlY3RlZCBhIG5vbi1uZWdhdGl2ZSBpbnRlZ2VyIG5vIGdyZWF0ZXIgdGhhbiAke0FMTF9MQVlFUlN9YClcblxuXHRcdFx0ZGVidWdFbnRpdGllcy5zZXQoZW50aXR5LCBbXSlcblx0XHRcdGFjdGl2ZUNvbGxpc2lvbnMuc2V0KGVudGl0eSwgbmV3IFNldCgpKVxuXHRcdFx0dHJpZ2dlckVudGVyQ2JzLnNldChlbnRpdHksIG9uRW50ZXJDYWxsYmFjaylcblx0XHRcdHRyaWdnZXJFeGl0Q2JzLnNldChlbnRpdHksIG9uRXhpdENhbGxiYWNrKVxuXG5cdFx0XHRUcmlnZ2VyLmNyZWF0ZU9yUmVwbGFjZShlbnRpdHksIHtcblx0XHRcdFx0YWN0aXZlOiB0