UNPKG

@tolokoban/tgd

Version:

ToloGameDev library for WebGL2

432 lines 40.1 kB
/** * GLTF specs can be found here: * https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html */ import { load } from "@loaders.gl/core"; import { DracoLoader } from "@loaders.gl/draco"; import { GLTFLoader } from "@loaders.gl/gltf"; import { TgdCameraPerspective } from "./../../camera/index.js"; import { TgdDataset } from "./../../dataset/index.js"; import { TgdGeometry } from "./../../geometry/index.js"; import { tgdLoadImage, tgdLoadImageFromArrayBuffer } from "./../../loader/index.js"; import { TgdQuat, TgdTransfo, TgdVec3 } from "./../../math/index.js"; import { TgdTexture2D } from "./../../texture/index.js"; import { assertTgdFormatGltf, assertTgdTypeArrayForElements, } from "./../../types/index.js"; import { isNumber } from "./../../types/guards.js"; const EMPTY_IMAGE = new Image(); export class TgdDataGlb { static async parse(content) { const blob = new Blob([content]); const url = URL.createObjectURL(blob); const gltfWithBuffers = await load(url, GLTFLoader, { DracoLoader, decompress: true, decompressMeshes: true, loadBuffers: true, loadImages: true, }); URL.revokeObjectURL(url); const gltf = gltfWithBuffers.json; const chunks = []; for (const buffer of gltfWithBuffers.buffers) { chunks.push(buffer.arrayBuffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength)); } const images = []; for (let imageIndex = 0; imageIndex < (gltf.images ?? []).length; imageIndex++) { const image = gltf.images?.[imageIndex]; if (!image) { images.push(EMPTY_IMAGE); continue; } if (image.uri) { images.push((await tgdLoadImage(image.uri)) ?? EMPTY_IMAGE); continue; } if (typeof image.bufferView !== "number") { images.push(EMPTY_IMAGE); continue; } // const buffer = this.getBufferViewData(image.bufferView, "Uint8") const bufferView = gltf.bufferViews?.[image.bufferView]; if (!bufferView) throw new Error(`No bufferView with index #${image.bufferView}!`); images.push((await tgdLoadImageFromArrayBuffer(chunks[bufferView.buffer].slice(bufferView.byteOffset ?? 0, (bufferView.byteOffset ?? 0) + bufferView.byteLength))) ?? EMPTY_IMAGE); } return new TgdDataGlb(gltf, chunks, images, content.byteLength); } /** * @param content The binary content of a GLB file. */ constructor(json, chunks, images, fileSize) { this.chunks = chunks; this.images = images; this.fileSize = fileSize; this.cacheBufferViewDatas = new Map(); try { // const data = parseGLB(content) assertTgdFormatGltf(json); this.json = json; // this.chunks = data.chunks // this.chunkDetails = data.chunkTypes } catch (error) { const message = error instanceof Error ? error.message : JSON.stringify(error); console.error("[TgdParserGLTransfertFormatBinary::new] json:", json); throw new Error(`[TgdParserGLTransfertFormatBinary] ${message}`); } } getJson() { return structuredClone(this.json); } createTransfoFromNode(node) { const transfo = {}; if (node.rotation) { transfo.orientation = new TgdQuat(node.rotation); } if (node.translation) transfo.position = new TgdVec3(node.translation); if (node.scale) transfo.scale = new TgdVec3(node.scale); return new TgdTransfo(transfo); } createCameraByName(name) { const node = this.getNodeByNameOrThrow(name); if (typeof node.camera === "number") { const camera = this.getCamera(node.camera); if (camera.type === "perspective") { const perspective = new TgdCameraPerspective({ name, near: camera.perspective.znear, far: camera.perspective.zfar, fovy: camera.perspective.yfov, transfo: this.createTransfoFromNode(node), }); return perspective; } throw new Error("Sorry, but for now, we do not support Orthographic cameras..."); } console.error(node); throw new Error(`Node "${name}" is not of type Camera!`); } getBufferViews() { return this.json.bufferViews ?? []; } getBufferView(bufferViewIndex) { return this.json.bufferViews?.[bufferViewIndex]; } getCamera(cameraIndex) { const camera = this.json.cameras?.[cameraIndex]; if (!camera) { throw new Error(`Asset has no camera with index #${cameraIndex}!`); } return camera; } getImages() { return this.json.images ?? []; } getImage(imageIndexOrName) { const { images } = this.json; if (!images) return; if (typeof imageIndexOrName === "number") return images?.[imageIndexOrName]; return images.find((img) => img.name === imageIndexOrName); } getImageAsHTMLElement(imageIndexOrName) { const { images } = this.json; if (!images) return; if (typeof imageIndexOrName === "number") { return this.images[imageIndexOrName] ?? EMPTY_IMAGE; } for (let i = 0; i < images.length; i++) { if (images[i].name === imageIndexOrName) return this.images[i]; } throw new Error(`There is no image with name "${imageIndexOrName}" in this GLB file!\nPossible names are: ${images.map((img) => img.name).join(", ")}.`); } getScenes() { return this.json.scenes ?? []; } getScene(sceneIndex) { const scene = this.json.scenes?.[sceneIndex]; if (!scene) { throw new Error(`Asset has no scene with index #${sceneIndex}!`); } return scene; } getNodes() { return this.json.nodes ?? []; } getNode(nodeIndex) { const node = this.json.nodes?.[nodeIndex]; if (!node) { throw new Error(`Asset has no node with index #${nodeIndex}!`); } return node; } getNodeByName(nodeName) { const nodes = this.json.nodes; if (!nodes) return; for (const node of nodes) { if (node.name === nodeName) return node; } } getNodeByNameOrThrow(nodeName) { const node = this.getNodeByName(nodeName); if (node) return node; throw new Error(`Unknown node "${nodeName}"!\nAvailable names:${(this.json.nodes ?? []) .map((node, index) => `\n - ${typeof node.name === "string" ? JSON.stringify(node.name) : `#${index}`}`) .join("")}`); } getAccessor(accessorIndex = 0) { const accessor = this.json.accessors?.[accessorIndex]; if (!accessor) { throw new Error(`Asset has no accessor with index #${accessorIndex}!`); } return accessor; } getMaterial(materialIndex) { const material = this.json.materials?.[materialIndex]; if (!material) { throw new Error(`Asset has no material with index #${materialIndex}!`); } return material; } getMesh(meshIndexOrName = 0) { if (typeof meshIndexOrName !== "number" && typeof meshIndexOrName !== "string") return meshIndexOrName; const mesh = typeof meshIndexOrName === "number" ? this.json.meshes?.[meshIndexOrName] : (this.json.meshes ?? []).find((item) => item.name === meshIndexOrName); if (!mesh) return undefined; return mesh; } getMeshOrThrow(meshIndexOrName = 0) { if (typeof meshIndexOrName !== "number" && typeof meshIndexOrName !== "string") return meshIndexOrName; const mesh = typeof meshIndexOrName === "number" ? this.json.meshes?.[meshIndexOrName] : (this.json.meshes ?? []).find((item) => item.name === meshIndexOrName); if (!mesh) { throw new Error(`Asset has no mesh with index/name ${JSON.stringify(meshIndexOrName)}!\nAvailable names are: ${(this.json.meshes ?? []) .sort() .map((mesh) => mesh.name) .join(", ")}.`); } return mesh; } getMeshPrimitive(meshIndexOrName = 0, primitiveIndex = 0) { const mesh = typeof meshIndexOrName === "number" || typeof meshIndexOrName === "string" ? this.getMesh(meshIndexOrName) : meshIndexOrName; if (!mesh) { throw new Error(`Asset has no mesh with index/name ${JSON.stringify(meshIndexOrName)}!\nAvailable names are: ${(this.json.meshes ?? []).map((mesh) => mesh.name).join(", ")}.`); } const primitive = mesh.primitives[primitiveIndex]; if (!primitive) { throw new Error(`Asset has no primitive #${primitiveIndex} in mesh ${JSON.stringify(meshIndexOrName)}!`); } return primitive; } getMeshPrimitiveIndices(meshIndexOrName = 0, primitiveIndex = 0) { const primitive = this.getMeshPrimitive(meshIndexOrName, primitiveIndex); const { indices } = primitive; if (isNumber(indices)) { const accessor = this.getAccessor(indices); const elements = this.getBufferViewData(accessor.bufferView ?? 0, accessor.componentType); assertTgdTypeArrayForElements(elements); return elements; } if (indices) { const elements = indices.value; assertTgdTypeArrayForElements(elements); return elements; } return new Uint8Array(); } getAccessorByAttributeName(primitive, attribName) { const { attributes } = primitive; if (!attributes || Object.keys(attributes).length === 0) { throw new Error("No attributes found!"); } const attribute = attributes[attribName]; if (attribute === undefined) { throw new TypeError(`No attribute with name "${attribName}"!\nAvailable names are: ${Object.keys(attributes) .map((name) => JSON.stringify(name)) .join(", ")}.`); } if (isNumber(attribute)) { try { return this.getAccessor(attribute); } catch (error) { const message = error instanceof Error ? error.message : JSON.stringify(error); throw new Error(`Attribute "${attribName}" pointed to an inexisting accessor!\n${message}`); } } else { return attribute; } } createTexture2D(context, textureIndex, color = [0, 0, 0, 1]) { const gltfTex = this.json.textures?.[textureIndex]; if (!gltfTex) { throw new Error(`Asset has no texture with index #${textureIndex}!`); } const source = gltfTex.source ?? gltfTex.extensions?.EXT_texture_webp?.source ?? 0; const texture = new TgdTexture2D(context, { color }).loadBitmap(this.images[source]); return texture; } getBufferViewData(accessor, type = "Float32") { if (typeof accessor !== "number") { return this.getBufferViewData(accessor.bufferView ?? 0, accessor.componentType); } const bufferViewIndex = accessor; const fromCache = this.cacheBufferViewDatas.get(bufferViewIndex); if (fromCache) return fromCache; const { json: gltf } = this; const bufferView = gltf.bufferViews?.[bufferViewIndex]; if (!bufferView) throw new Error(`No bufferView with index #${bufferViewIndex}!`); const buffer = this.chunks[bufferView.buffer]; const byteOffset = bufferView.byteOffset ?? 0; const data = buffer.slice(byteOffset, byteOffset + bufferView.byteLength); const view = figureOutView(data, convertTypeToNumber(type ?? this.findAccessorForBufferView(bufferViewIndex)?.componentType ?? "Float32")); this.cacheBufferViewDatas.set(bufferViewIndex, view); return view; } findAccessorForBufferView(bufferViewIndex) { return (this.json.accessors ?? []).find((accessor) => accessor.bufferView === bufferViewIndex); } setAttrib(dataset, attribName, meshIndexOrName = 0, primitiveIndex = 0, primitiveAttribName) { const { json: gltf } = this; const attribute = this.getMeshOrThrow(meshIndexOrName).primitives[primitiveIndex].attributes[primitiveAttribName ?? attribName] ?? -1; if (!isNumber(attribute)) { dataset.set(attribName, attribute.value, { byteStride: attribute.size * 4, byteOffset: attribute.byteOffset, count: attribute.count, }); return; } const accessor = gltf.accessors?.[attribute]; if (!accessor) { throw new Error(`No attribute "${primitiveAttribName ?? attribName}" for primitive #${primitiveIndex} of mesh #${meshIndexOrName}!`); } const bufferViewIndex = accessor.bufferView ?? 0; const bufferView = gltf.bufferViews?.[bufferViewIndex]; if (!bufferView) { throw new Error(`No bufferView with index #${bufferViewIndex}!`); } const view = this.getBufferViewData(bufferViewIndex, accessor.componentType); dataset.set(attribName, view, { byteStride: bufferView.byteStride, byteOffset: accessor.byteOffset, count: accessor.count, }); } makeGeometry(options = {}) { const { computeNormals, meshIndex = 0, primitiveIndex = 0, attPositionName = "POSITION", attNormalName = "NORMAL", attTextureCoordsName = "TEXCOORD_0", } = options; try { const dataset = this.makeDataset(options); const elements = this.getMeshPrimitiveIndices(meshIndex, primitiveIndex); return new TgdGeometry({ computeNormalsIfMissing: computeNormals, dataset, elements, attPosition: attPositionName, attNormal: attNormalName, attUV: attTextureCoordsName, }); } catch (error) { const message = error instanceof Error ? error.message : JSON.stringify(error); throw new Error(`Error in primitive #${primitiveIndex} of mesh #${meshIndex}:\n${message}`); } } makeDataset({ meshIndex = 0, primitiveIndex = 0, attPositionName = "POSITION", attNormalName = "NORMAL", attTextureCoordsName = "TEXCOORD_0", } = {}) { const primitive = this.getMeshPrimitive(meshIndex, primitiveIndex); try { const { attributes } = primitive; if (!attributes) throw new Error("No attributes found!"); const definition = { [attPositionName]: "vec3", }; if (attributes[attNormalName] !== undefined) { definition[attNormalName] = "vec3"; } if (attributes[attTextureCoordsName] !== undefined) { definition[attTextureCoordsName] = "vec2"; } const dataset = new TgdDataset(definition); if (isNumber(attributes[attPositionName])) { dataset.set(attPositionName, returnFloat32Array(this.getBufferViewData(this.getAccessorByAttributeName(primitive, attPositionName)))); } else { dataset.set(attPositionName, attributes[attPositionName].value); } if (typeof definition[attNormalName] === "string") { dataset.set(attNormalName, isNumber(attributes[attNormalName]) ? returnFloat32Array(this.getBufferViewData(this.getAccessorByAttributeName(primitive, attNormalName))) : attributes[attNormalName].value); } if (typeof definition[attTextureCoordsName] === "string") { dataset.set(attTextureCoordsName, isNumber(attributes[attTextureCoordsName]) ? returnFloat32Array(this.getBufferViewData(this.getAccessorByAttributeName(primitive, attTextureCoordsName))) : attributes[attTextureCoordsName].value); } return dataset; } catch (error) { const message = error instanceof Error ? error.message : JSON.stringify(error); throw new Error(`Error in primitive #${primitiveIndex} of mesh ${typeof meshIndex === "number" ? `#${meshIndex}` : JSON.stringify(meshIndex)}:\n${message}`); } } } function figureOutView(data, componentType) { switch (componentType) { case 5120: return new Int8Array(data); case 5121: return new Uint8Array(data); case 5122: return new Int16Array(data); case 5123: return new Uint16Array(data); case 5125: return new Uint32Array(data); default: return new Float32Array(data); } } function convertTypeToNumber(type) { if (typeof type === "number") return type; switch (type) { case "Int8": return 5120; case "Uint8": return 5121; case "Int16": return 5122; case "Uint16": return 5123; case "Uint32": return 5125; default: return WebGL2RenderingContext.FLOAT; } } function returnFloat32Array(data) { if (data instanceof Float32Array) return data; throw new Error("We were expecting a Float32Array!"); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2x0Zi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wYXJzZXIvZ2x0Zi9nbHRmLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUNILE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQTtBQUN2QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFDL0MsT0FBTyxFQUFhLFVBQVUsRUFBd0IsTUFBTSxrQkFBa0IsQ0FBQTtBQUM5RSxPQUFPLEVBQWtCLG9CQUFvQixFQUFFLE1BQU0sYUFBYSxDQUFBO0FBR2xFLE9BQU8sRUFBRSxVQUFVLEVBQTZCLE1BQU0sY0FBYyxDQUFBO0FBQ3BFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFDM0MsT0FBTyxFQUFFLFlBQVksRUFBRSwyQkFBMkIsRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUN2RSxPQUFPLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBMEIsT0FBTyxFQUFXLE1BQU0sV0FBVyxDQUFBO0FBQ3pGLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxjQUFjLENBQUE7QUFDM0MsT0FBTyxFQUVILG1CQUFtQixFQUNuQiw2QkFBNkIsR0FFaEMsTUFBTSxZQUFZLENBQUE7QUFlbkIsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBRTVDLE1BQU0sV0FBVyxHQUFHLElBQUksS0FBSyxFQUFFLENBQUE7QUFFL0IsTUFBTSxPQUFPLFVBQVU7SUFDWixNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxPQUFvQjtRQUMxQyxNQUFNLElBQUksR0FBRyxJQUFJLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUE7UUFDaEMsTUFBTSxHQUFHLEdBQUcsR0FBRyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUNyQyxNQUFNLGVBQWUsR0FBb0IsTUFBTSxJQUFJLENBQUMsR0FBRyxFQUFFLFVBQVUsRUFBRTtZQUNqRSxXQUFXO1lBQ1gsVUFBVSxFQUFFLElBQUk7WUFDaEIsZ0JBQWdCLEVBQUUsSUFBSTtZQUN0QixXQUFXLEVBQUUsSUFBSTtZQUNqQixVQUFVLEVBQUUsSUFBSTtTQUNuQixDQUFDLENBQUE7UUFDRixHQUFHLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxDQUFBO1FBQ3hCLE1BQU0sSUFBSSxHQUFHLGVBQWUsQ0FBQyxJQUFJLENBQUE7UUFDakMsTUFBTSxNQUFNLEdBQWtCLEVBQUUsQ0FBQTtRQUNoQyxLQUFLLE1BQU0sTUFBTSxJQUFJLGVBQWUsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUMzQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLFVBQVUsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQTtRQUNuRyxDQUFDO1FBQ0QsTUFBTSxNQUFNLEdBQXVCLEVBQUUsQ0FBQTtRQUNyQyxLQUFLLElBQUksVUFBVSxHQUFHLENBQUMsRUFBRSxVQUFVLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxVQUFVLEVBQUUsRUFBRSxDQUFDO1lBQzdFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxVQUFVLENBQUMsQ0FBQTtZQUN2QyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ1QsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQTtnQkFDeEIsU0FBUTtZQUNaLENBQUM7WUFFRCxJQUFJLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQztnQkFDWixNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxZQUFZLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksV0FBVyxDQUFDLENBQUE7Z0JBQzNELFNBQVE7WUFDWixDQUFDO1lBRUQsSUFBSSxPQUFPLEtBQUssQ0FBQyxVQUFVLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQ3ZDLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUE7Z0JBQ3hCLFNBQVE7WUFDWixDQUFDO1lBRUQsbUVBQW1FO1lBQ25FLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUE7WUFDdkQsSUFBSSxDQUFDLFVBQVU7Z0JBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyw2QkFBNkIsS0FBSyxDQUFDLFVBQVUsR0FBRyxDQUFDLENBQUE7WUFFbEYsTUFBTSxDQUFDLElBQUksQ0FDUCxDQUFDLE1BQU0sMkJBQTJCLENBQzlCLE1BQU0sQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxDQUMzQixVQUFVLENBQUMsVUFBVSxJQUFJLENBQUMsRUFDMUIsQ0FBQyxVQUFVLENBQUMsVUFBVSxJQUFJLENBQUMsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxVQUFVLENBQ3ZELENBQ0osQ0FBQyxJQUFJLFdBQVcsQ0FDcEIsQ0FBQTtRQUNMLENBQUM7UUFDRCxPQUFPLElBQUksVUFBVSxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUNuRSxDQUFDO0lBU0Q7O09BRUc7SUFDSCxZQUNJLElBQVUsRUFDTyxNQUFxQixFQUNyQixNQUEwQixFQUMzQixRQUFnQjtRQUZmLFdBQU0sR0FBTixNQUFNLENBQWU7UUFDckIsV0FBTSxHQUFOLE1BQU0sQ0FBb0I7UUFDM0IsYUFBUSxHQUFSLFFBQVEsQ0FBUTtRQVpuQix5QkFBb0IsR0FBRyxJQUFJLEdBQUcsRUFHNUMsQ0FBQTtRQVdDLElBQUksQ0FBQztZQUNELGlDQUFpQztZQUNqQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsQ0FBQTtZQUN6QixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQTtZQUNoQiw0QkFBNEI7WUFDNUIsc0NBQXNDO1FBQzFDLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2IsTUFBTSxPQUFPLEdBQUcsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQTtZQUM5RSxPQUFPLENBQUMsS0FBSyxDQUFDLCtDQUErQyxFQUFFLElBQUksQ0FBQyxDQUFBO1lBQ3BFLE1BQU0sSUFBSSxLQUFLLENBQUMsc0NBQXNDLE9BQU8sRUFBRSxDQUFDLENBQUE7UUFDcEUsQ0FBQztJQUNMLENBQUM7SUFFRCxPQUFPO1FBQ0gsT0FBTyxlQUFlLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFBO0lBQ3JDLENBQUM7SUFFRCxxQkFBcUIsQ0FBQyxJQUF1QjtRQUN6QyxNQUFNLE9BQU8sR0FBK0IsRUFBRSxDQUFBO1FBQzlDLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2hCLE9BQU8sQ0FBQyxXQUFXLEdBQUcsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFBO1FBQ3BELENBQUM7UUFDRCxJQUFJLElBQUksQ0FBQyxXQUFXO1lBQUUsT0FBTyxDQUFDLFFBQVEsR0FBRyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUE7UUFDdEUsSUFBSSxJQUFJLENBQUMsS0FBSztZQUFFLE9BQU8sQ0FBQyxLQUFLLEdBQUcsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQ3ZELE9BQU8sSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUE7SUFDbEMsQ0FBQztJQUVELGtCQUFrQixDQUFDLElBQVk7UUFDM0IsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxDQUFBO1FBQzVDLElBQUksT0FBTyxJQUFJLENBQUMsTUFBTSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ2xDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1lBQzFDLElBQUksTUFBTSxDQUFDLElBQUksS0FBSyxhQUFhLEVBQUUsQ0FBQztnQkFDaEMsTUFBTSxXQUFXLEdBQUcsSUFBSSxvQkFBb0IsQ0FBQztvQkFDekMsSUFBSTtvQkFDSixJQUFJLEVBQUUsTUFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLO29CQUM5QixHQUFHLEVBQUUsTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJO29CQUM1QixJQUFJLEVBQUUsTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJO29CQUM3QixPQUFPLEVBQUUsSUFBSSxDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQztpQkFDNUMsQ0FBQyxDQUFBO2dCQUNGLE9BQU8sV0FBVyxDQUFBO1lBQ3RCLENBQUM7WUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLCtEQUErRCxDQUFDLENBQUE7UUFDcEYsQ0FBQztRQUNELE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDbkIsTUFBTSxJQUFJLEtBQUssQ0FBQyxTQUFTLElBQUksMEJBQTBCLENBQUMsQ0FBQTtJQUM1RCxDQUFDO0lBRUQsY0FBYztRQUNWLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLElBQUksRUFBRSxDQUFBO0lBQ3RDLENBQUM7SUFFRCxhQUFhLENBQUMsZUFBdUI7UUFDakMsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLGVBQWUsQ0FBQyxDQUFBO0lBQ25ELENBQUM7SUFFRCxTQUFTLENBQUMsV0FBbUI7UUFDekIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQTtRQUMvQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDVixNQUFNLElBQUksS0FBSyxDQUFDLG1DQUFtQyxXQUFXLEdBQUcsQ0FBQyxDQUFBO1FBQ3RFLENBQUM7UUFFRCxPQUFPLE1BQU0sQ0FBQTtJQUNqQixDQUFDO0lBRUQsU0FBUztRQUNMLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksRUFBRSxDQUFBO0lBQ2pDLENBQUM7SUFFRCxRQUFRLENBQUMsZ0JBQWlDO1FBQ3RDLE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFBO1FBQzVCLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTTtRQUVuQixJQUFJLE9BQU8sZ0JBQWdCLEtBQUssUUFBUTtZQUFFLE9BQU8sTUFBTSxFQUFFLENBQUMsZ0JBQWdCLENBQUMsQ0FBQTtRQUUzRSxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEtBQUssZ0JBQWdCLENBQUMsQ0FBQTtJQUM5RCxDQUFDO0lBRUQscUJBQXFCLENBQUMsZ0JBQWlDO1FBQ25ELE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFBO1FBQzVCLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTTtRQUVuQixJQUFJLE9BQU8sZ0JBQWdCLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDdkMsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLElBQUksV0FBVyxDQUFBO1FBQ3ZELENBQUM7UUFFRCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ3JDLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxnQkFBZ0I7Z0JBQUUsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQ2xFLENBQUM7UUFDRCxNQUFNLElBQUksS0FBSyxDQUNYLGdDQUFnQyxnQkFBZ0IsNENBQTRDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FDMUksQ0FBQTtJQUNMLENBQUM7SUFFRCxTQUFTO1FBQ0wsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUE7SUFDakMsQ0FBQztJQUVELFFBQVEsQ0FBQyxVQUFrQjtRQUN2QixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLFVBQVUsQ0FBQyxDQUFBO1FBQzVDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNULE1BQU0sSUFBSSxLQUFLLENBQUMsa0NBQWtDLFVBQVUsR0FBRyxDQUFDLENBQUE7UUFDcEUsQ0FBQztRQUVELE9BQU8sS0FBSyxDQUFBO0lBQ2hCLENBQUM7SUFFRCxRQUFRO1FBQ0osT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUE7SUFDaEMsQ0FBQztJQUVELE9BQU8sQ0FBQyxTQUFpQjtRQUNyQixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFBO1FBQ3pDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNSLE1BQU0sSUFBSSxLQUFLLENBQUMsaUNBQWlDLFNBQVMsR0FBRyxDQUFDLENBQUE7UUFDbEUsQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFBO0lBQ2YsQ0FBQztJQUVELGFBQWEsQ0FBQyxRQUFnQjtRQUMxQixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQTtRQUM3QixJQUFJLENBQUMsS0FBSztZQUFFLE9BQU07UUFFbEIsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUN2QixJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssUUFBUTtnQkFBRSxPQUFPLElBQUksQ0FBQTtRQUMzQyxDQUFDO0lBQ0wsQ0FBQztJQUVELG9CQUFvQixDQUFDLFFBQWdCO1FBQ2pDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDekMsSUFBSSxJQUFJO1lBQUUsT0FBTyxJQUFJLENBQUE7UUFFckIsTUFBTSxJQUFJLEtBQUssQ0FDWCxpQkFBaUIsUUFBUSx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7YUFDbEUsR0FBRyxDQUNBLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsU0FBUyxPQUFPLElBQUksQ0FBQyxJQUFJLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLEVBQUUsRUFBRSxDQUN0RzthQUNBLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUNsQixDQUFBO0lBQ0wsQ0FBQztJQUVELFdBQVcsQ0FBQyxhQUFhLEdBQUcsQ0FBQztRQUN6QixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxDQUFBO1FBQ3JELElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNaLE1BQU0sSUFBSSxLQUFLLENBQUMscUNBQXFDLGFBQWEsR0FBRyxDQUFDLENBQUE7UUFDMUUsQ0FBQztRQUVELE9BQU8sUUFBUSxDQUFBO0lBQ25CLENBQUM7SUFFRCxXQUFXLENBQUMsYUFBcUI7UUFDN0IsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxhQUFhLENBQUMsQ0FBQTtRQUNyRCxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDWixNQUFNLElBQUksS0FBSyxDQUFDLHFDQUFxQyxhQUFhLEdBQUcsQ0FBQyxDQUFBO1FBQzFFLENBQUM7UUFFRCxPQUFPLFFBQVEsQ0FBQTtJQUNuQixDQUFDO0lBRUQsT0FBTyxDQUFDLGtCQUF1RCxDQUFDO1FBQzVELElBQUksT0FBTyxlQUFlLEtBQUssUUFBUSxJQUFJLE9BQU8sZUFBZSxLQUFLLFFBQVE7WUFBRSxPQUFPLGVBQWUsQ0FBQTtRQUV0RyxNQUFNLElBQUksR0FDTixPQUFPLGVBQWUsS0FBSyxRQUFRO1lBQy9CLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLGVBQWUsQ0FBQztZQUNyQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssZUFBZSxDQUFDLENBQUE7UUFDaEYsSUFBSSxDQUFDLElBQUk7WUFBRSxPQUFPLFNBQVMsQ0FBQTtRQUUzQixPQUFPLElBQUksQ0FBQTtJQUNmLENBQUM7SUFFRCxjQUFjLENBQUMsa0JBQXVELENBQUM7UUFDbkUsSUFBSSxPQUFPLGVBQWUsS0FBSyxRQUFRLElBQUksT0FBTyxlQUFlLEtBQUssUUFBUTtZQUFFLE9BQU8sZUFBZSxDQUFBO1FBRXRHLE1BQU0sSUFBSSxHQUNOLE9BQU8sZUFBZSxLQUFLLFFBQVE7WUFDL0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsZUFBZSxDQUFDO1lBQ3JDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxlQUFlLENBQUMsQ0FBQTtRQUNoRixJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDUixNQUFNLElBQUksS0FBSyxDQUNYLHFDQUFxQyxJQUFJLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQywyQkFBMkIsQ0FDM0YsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksRUFBRSxDQUN6QjtpQkFDSSxJQUFJLEVBQUU7aUJBQ04sR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO2lCQUN4QixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FDckIsQ0FBQTtRQUNMLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQTtJQUNmLENBQUM7SUFFRCxnQkFBZ0IsQ0FDWixrQkFBdUQsQ0FBQyxFQUN4RCxjQUFjLEdBQUcsQ0FBQztRQUVsQixNQUFNLElBQUksR0FDTixPQUFPLGVBQWUsS0FBSyxRQUFRLElBQUksT0FBTyxlQUFlLEtBQUssUUFBUTtZQUN0RSxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUM7WUFDL0IsQ0FBQyxDQUFDLGVBQWUsQ0FBQTtRQUN6QixJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDUixNQUFNLElBQUksS0FBSyxDQUNYLHFDQUFxQyxJQUFJLENBQUMsU0FBUyxDQUMvQyxlQUFlLENBQ2xCLDJCQUEyQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUM5RixDQUFBO1FBQ0wsQ0FBQztRQUNELE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDLENBQUE7UUFDakQsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ2IsTUFBTSxJQUFJLEtBQUssQ0FBQywyQkFBMkIsY0FBYyxZQUFZLElBQUksQ0FBQyxTQUFTLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxDQUFBO1FBQzVHLENBQUM7UUFFRCxPQUFPLFNBQVMsQ0FBQTtJQUNwQixDQUFDO0lBRUQsdUJBQXVCLENBQ25CLGtCQUF1RCxDQUFDLEVBQ3hELGNBQWMsR0FBRyxDQUFDO1FBRWxCLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxlQUFlLEVBQUUsY0FBYyxDQUFDLENBQUE7UUFDeEUsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLFNBQVMsQ0FBQTtRQUM3QixJQUFJLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ3BCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUE7WUFDMUMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxVQUFVLElBQUksQ0FBQyxFQUFFLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQTtZQUN6Riw2QkFBNkIsQ0FBQyxRQUFRLENBQUMsQ0FBQTtZQUN2QyxPQUFPLFFBQVEsQ0FBQTtRQUNuQixDQUFDO1FBQ0QsSUFBSSxPQUFPLEVBQUUsQ0FBQztZQUNWLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUE7WUFDOUIsNkJBQTZCLENBQUMsUUFBUSxDQUFDLENBQUE7WUFDdkMsT0FBTyxRQUFRLENBQUE7UUFDbkIsQ0FBQztRQUNELE9BQU8sSUFBSSxVQUFVLEVBQUUsQ0FBQTtJQUMzQixDQUFDO0lBRUQsMEJBQTBCLENBQ3RCLFNBQXFDLEVBQ3JDLFVBQWtCO1FBRWxCLE1BQU0sRUFBRSxVQUFVLEVBQUUsR0FBRyxTQUFTLENBQUE7UUFDaEMsSUFBSSxDQUFDLFVBQVUsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUN0RCxNQUFNLElBQUksS0FBSyxDQUFDLHNCQUFzQixDQUFDLENBQUE7UUFDM0MsQ0FBQztRQUNELE1BQU0sU0FBUyxHQUFHLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQTtRQUN4QyxJQUFJLFNBQVMsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUMxQixNQUFNLElBQUksU0FBUyxDQUNmLDJCQUEyQixVQUFVLDRCQUE0QixNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQztpQkFDbkYsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO2lCQUNuQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FDckIsQ0FBQTtRQUNMLENBQUM7UUFDRCxJQUFJLFFBQVEsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1lBQ3RCLElBQUksQ0FBQztnQkFDRCxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUE7WUFDdEMsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2IsTUFBTSxPQUFPLEdBQUcsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQTtnQkFDOUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxjQUFjLFVBQVUseUNBQXlDLE9BQU8sRUFBRSxDQUFDLENBQUE7WUFDL0YsQ0FBQztRQUNMLENBQUM7YUFBTSxDQUFDO1lBQ0osT0FBTyxTQUFTLENBQUE7UUFDcEIsQ0FBQztJQUNMLENBQUM7SUFFRCxlQUFlLENBQ1gsT0FBbUIsRUFDbkIsWUFBb0IsRUFDcEIsUUFBMkMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFdkQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxZQUFZLENBQUMsQ0FBQTtRQUNsRCxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDWCxNQUFNLElBQUksS0FBSyxDQUFDLG9DQUFvQyxZQUFZLEdBQUcsQ0FBQyxDQUFBO1FBQ3hFLENBQUM7UUFFRCxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxJQUFJLENBQUMsQ0FBQTtRQUNsRixNQUFNLE9BQU8sR0FBRyxJQUFJLFlBQVksQ0FBQyxPQUFPLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUE7UUFDcEYsT0FBTyxPQUFPLENBQUE7SUFDbEIsQ0FBQztJQVNELGlCQUFpQixDQUNiLFFBQXdDLEVBQ3hDLE9BQThFLFNBQVM7UUFFdkYsSUFBSSxPQUFPLFFBQVEsS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUMvQixPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsVUFBVSxJQUFJLENBQUMsRUFBRSxRQUFRLENBQUMsYUFBYSxDQUFDLENBQUE7UUFDbkYsQ0FBQztRQUNELE1BQU0sZUFBZSxHQUFHLFFBQVEsQ0FBQTtRQUNoQyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFBO1FBQ2hFLElBQUksU0FBUztZQUFFLE9BQU8sU0FBUyxDQUFBO1FBRS9CLE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFBO1FBQzNCLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxlQUFlLENBQUMsQ0FBQTtRQUN0RCxJQUFJLENBQUMsVUFBVTtZQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsNkJBQTZCLGVBQWUsR0FBRyxDQUFDLENBQUE7UUFFakYsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUE7UUFDN0MsTUFBTSxVQUFVLEdBQUcsVUFBVSxDQUFDLFVBQVUsSUFBSSxDQUFDLENBQUE7UUFDN0MsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsVUFBVSxHQUFHLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQTtRQUN6RSxNQUFNLElBQUksR0FBRyxhQUFhLENBQ3RCLElBQUksRUFDSixtQkFBbUIsQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLHlCQUF5QixDQUFDLGVBQWUsQ0FBQyxFQUFFLGFBQWEsSUFBSSxTQUFTLENBQUMsQ0FDM0csQ0FBQTtRQUNELElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsZUFBZSxFQUFFLElBQUksQ0FBQyxDQUFBO1FBQ3BELE9BQU8sSUFBSSxDQUFBO0lBQ2YsQ0FBQztJQUVELHlCQUF5QixDQUFDLGVBQXVCO1FBQzdDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxVQUFVLEtBQUssZUFBZSxDQUFDLENBQUE7SUFDbEcsQ0FBQztJQUVELFNBQVMsQ0FDTCxPQUFtQixFQUNuQixVQUFrQixFQUNsQixrQkFBdUQsQ0FBQyxFQUN4RCxjQUFjLEdBQUcsQ0FBQyxFQUNsQixtQkFBNEI7UUFFNUIsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUE7UUFDM0IsTUFBTSxTQUFTLEdBQ1gsSUFBSSxDQUFDLGNBQWMsQ0FBQyxlQUFlLENBQUMsQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDLENBQUMsVUFBVSxDQUN0RSxtQkFBbUIsSUFBSSxVQUFVLENBQ3BDLElBQUksQ0FBQyxDQUFDLENBQUE7UUFDWCxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7WUFDdkIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUUsU0FBUyxDQUFDLEtBQUssRUFBRTtnQkFDckMsVUFBVSxFQUFFLFNBQVMsQ0FBQyxJQUFJLEdBQUcsQ0FBQztnQkFDOUIsVUFBVSxFQUFFLFNBQVMsQ0FBQyxVQUFVO2dCQUNoQyxLQUFLLEVBQUUsU0FBUyxDQUFDLEtBQUs7YUFDekIsQ0FBQyxDQUFBO1lBQ0YsT0FBTTtRQUNWLENBQUM7UUFFRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUE7UUFDNUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ1osTUFBTSxJQUFJLEtBQUssQ0FDWCxpQkFDSSxtQkFBbUIsSUFBSSxVQUMzQixvQkFBb0IsY0FBYyxhQUFhLGVBQWUsR0FBRyxDQUNwRSxDQUFBO1FBQ0wsQ0FBQztRQUVELE1BQU0sZUFBZSxHQUFHLFFBQVEsQ0FBQyxVQUFVLElBQUksQ0FBQyxDQUFBO1FBQ2hELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxlQUFlLENBQUMsQ0FBQTtRQUN0RCxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDZCxNQUFNLElBQUksS0FBSyxDQUFDLDZCQUE2QixlQUFlLEdBQUcsQ0FBQyxDQUFBO1FBQ3BFLENBQUM7UUFDRCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsZUFBZSxFQUFFLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQTtRQUM1RSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsRUFBRSxJQUFJLEVBQUU7WUFDMUIsVUFBVSxFQUFFLFVBQVUsQ0FBQyxVQUFVO1lBQ2pDLFVBQVUsRUFBRSxRQUFRLENBQUMsVUFBVTtZQUMvQixLQUFLLEVBQUUsUUFBUSxDQUFDLEtBQUs7U0FDeEIsQ0FBQyxDQUFBO0lBQ04sQ0FBQztJQUVELFlBQVksQ0FDUixVQU9JLEVBQUU7UUFFTixNQUFNLEVBQ0YsY0FBYyxFQUNkLFNBQVMsR0FBRyxDQUFDLEVBQ2IsY0FBYyxHQUFHLENBQUMsRUFDbEIsZUFBZSxHQUFHLFVBQVUsRUFDNUIsYUFBYSxHQUFHLFFBQVEsRUFDeEIsb0JBQW9CLEdBQUcsWUFBWSxHQUN0QyxHQUFHLE9BQU8sQ0FBQTtRQUNYLElBQUksQ0FBQztZQUNELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUE7WUFDekMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLHVCQUF1QixDQUFDLFNBQVMsRUFBRSxjQUFjLENBQUMsQ0FBQTtZQUN4RSxPQUFPLElBQUksV0FBVyxDQUFDO2dCQUNuQix1QkFBdUIsRUFBRSxjQUFjO2dCQUN2QyxPQUFPO2dCQUNQLFFBQVE7Z0JBQ1IsV0FBVyxFQUFFLGVBQWU7Z0JBQzVCLFNBQVMsRUFBRSxhQUFhO2dCQUN4QixLQUFLLEVBQUUsb0JBQW9CO2FBQzlCLENBQUMsQ0FBQTtRQUNOLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2IsTUFBTSxPQUFPLEdBQUcsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQTtZQUM5RSxNQUFNLElBQUksS0FBSyxDQUFDLHVCQUF1QixjQUFjLGFBQWEsU0FBUyxNQUFNLE9BQU8sRUFBRSxDQUFDLENBQUE7UUFDL0YsQ0FBQztJQUNMLENBQUM7SUFFRCxXQUFXLENBQUMsRUFDUixTQUFTLEdBQUcsQ0FBQyxFQUNiLGNBQWMsR0FBRyxDQUFDLEVBQ2xCLGVBQWUsR0FBRyxVQUFVLEVBQzVCLGFBQWEsR0FBRyxRQUFRLEVBQ3hCLG9CQUFvQixHQUFHLFlBQVksTUFPbkMsRUFBRTtRQUNGLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsY0FBYyxDQUFDLENBQUE7UUFDbEUsSUFBSSxDQUFDO1lBQ0QsTUFBTSxFQUFFLFVBQVUsRUFBRSxHQUFHLFNBQVMsQ0FBQTtZQUNoQyxJQUFJLENBQUMsVUFBVTtnQkFBRSxNQUFNLElBQUksS0FBSyxDQUFDLHNCQUFzQixDQUFDLENBQUE7WUFDeEQsTUFBTSxVQUFVLEdBQXlCO2dCQUNyQyxDQUFDLGVBQWUsQ0FBQyxFQUFFLE1BQU07YUFDNUIsQ0FBQTtZQUNELElBQUksVUFBVSxDQUFDLGFBQWEsQ0FBQyxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUMxQyxVQUFVLENBQUMsYUFBYSxDQUFDLEdBQUcsTUFBTSxDQUFBO1lBQ3RDLENBQUM7WUFDRCxJQUFJLFVBQVUsQ0FBQyxvQkFBb0IsQ0FBQyxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUNqRCxVQUFVLENBQUMsb0JBQW9CLENBQUMsR0FBRyxNQUFNLENBQUE7WUFDN0MsQ0FBQztZQUNELE1BQU0sT0FBTyxHQUFHLElBQUksVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFBO1lBQzFDLElBQUksUUFBUSxDQUFDLFVBQVUsQ0FBQyxlQUFlLENBQUMsQ0FBQyxFQUFFLENBQUM7Z0JBQ3hDLE9BQU8sQ0FBQyxHQUFHLENBQ1AsZUFBZSxFQUNmLGtCQUFrQixDQUNkLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsU0FBUyxFQUFFLGVBQWUsQ0FBQyxDQUFDLENBQ3RGLENBQ0osQ0FBQTtZQUNMLENBQUM7aUJBQU0sQ0FBQztnQkFDSixPQUFPLENBQUMsR0FBRyxDQUFDLGVBQWUsRUFBRSxVQUFVLENBQUMsZUFBZSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUE7WUFDbkUsQ0FBQztZQUNELElBQUksT0FBTyxVQUFVLENBQUMsYUFBYSxDQUFDLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQ2hELE9BQU8sQ0FBQyxHQUFHLENBQ1AsYUFBYSxFQUNiLFFBQVEsQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLENBQUM7b0JBQy9CLENBQUMsQ0FBQyxrQkFBa0IsQ0FDZCxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLDBCQUEwQixDQUFDLFNBQVMsRUFBRSxhQUFhLENBQUMsQ0FBQyxDQUNwRjtvQkFDSCxDQUFDLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDLEtBQUssQ0FDeEMsQ0FBQTtZQUNMLENBQUM7WUFDRCxJQUFJLE9BQU8sVUFBVSxDQUFDLG9CQUFvQixDQUFDLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQ3ZELE9BQU8sQ0FBQyxHQUFHLENBQ1Asb0JBQW9CLEVBQ3BCLFFBQVEsQ0FBQyxVQUFVLENBQUMsb0JBQW9CLENBQUMsQ0FBQztvQkFDdEMsQ0FBQyxDQUFDLGtCQUFrQixDQUNkLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsU0FBUyxFQUFFLG9CQUFvQixDQUFDLENBQUMsQ0FDM0Y7b0JBQ0gsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLEtBQUssQ0FDL0MsQ0FBQTtZQUNMLENBQUM7WUFDRCxPQUFPLE9BQU8sQ0FBQTtRQUNsQixDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNiLE1BQU0sT0FBTyxHQUFHLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUE7WUFDOUUsTUFBTSxJQUFJLEtBQUssQ0FDWCx1QkFBdUIsY0FBYyxZQUFZLE9BQU8sU0FBUyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsTUFBTSxPQUFPLEVBQUUsQ0FDOUksQ0FBQTtRQUNMLENBQUM7SUFDTCxDQUFDO0NBQ0o7QUFFRCxTQUFTLGFBQWEsQ0FBQyxJQUFpQixFQUFFLGFBQXFCO0lBQzNELFFBQVEsYUFBYSxFQUFFLENBQUM7UUFDcEIsS0FBSyxJQUFJO1lBQ0wsT0FBTyxJQUFJLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUM5QixLQUFLLElBQUk7WUFDTCxPQUFPLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQy9CLEtBQUssSUFBSTtZQUNMLE9BQU8sSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDL0IsS0FBSyxJQUFJO1lBQ0wsT0FBTyxJQUFJLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUNoQyxLQUFLLElBQUk7WUFDTCxPQUFPLElBQUksV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ2hDO1lBQ0ksT0FBTyxJQUFJLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQTtJQUNyQyxDQUFDO0FBQ0wsQ0FBQztBQUVELFNBQVMsbUJBQW1CLENBQUMsSUFBcUI7SUFDOUMsSUFBSSxPQUFPLElBQUksS0FBSyxRQUFRO1FBQUUsT0FBTyxJQUFJLENBQUE7SUFFekMsUUFBUSxJQUFJLEVBQUUsQ0FBQztRQUNYLEtBQUssTUFBTTtZQUNQLE9BQU8sSUFBSSxDQUFBO1FBQ2YsS0FBSyxPQUFPO1lBQ1IsT0FBTyxJQUFJLENBQUE7UUFDZixLQUFLLE9BQU87WUFDUixPQUFPLElBQUksQ0FBQTtRQUNmLEtBQUssUUFBUTtZQUNULE9BQU8sSUFBSSxDQUFBO1FBQ2YsS0FBSyxRQUFRO1lBQ1QsT0FBTyxJQUFJLENBQUE7UUFDZjtZQUNJLE9BQU8sc0JBQXNCLENBQUMsS0FBSyxDQUFBO0lBQzNDLENBQUM7QUFDTCxDQUFDO0FBRUQsU0FBUyxrQkFBa0IsQ0FBQyxJQUFhO0lBQ3JDLElBQUksSUFBSSxZQUFZLFlBQVk7UUFBRSxPQUFPLElBQUksQ0FBQTtJQUU3QyxNQUFNLElBQUksS0FBSyxDQUFDLG1DQUFtQyxDQUFDLENBQUE7QUFDeEQsQ0FBQyJ9