From a8dca53ea86354185d3e3c3897e469b871b07818 Mon Sep 17 00:00:00 2001 From: Shayla Beltran Date: Mon, 15 Jan 2024 16:21:24 -0600 Subject: [PATCH 01/19] ignore metadata files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 960d83d..b011dbb 100644 --- a/.gitignore +++ b/.gitignore @@ -74,3 +74,4 @@ crashlytics-build.properties # Temporary auto-generated Android Assets /[Aa]ssets/[Ss]treamingAssets/aa.meta /[Aa]ssets/[Ss]treamingAssets/aa/* +*.meta From cbd99a4d5c65f1f5ee747a40f9e3449562fe1bee Mon Sep 17 00:00:00 2001 From: Shayla Beltran Date: Mon, 15 Jan 2024 16:25:56 -0600 Subject: [PATCH 02/19] trying this --- Assets/Backgrounds/background v1.png.meta | 127 ------------------ Assets/Resources/Backgrounds/Background.mat | 83 ++++++++++++ .../Characters/2_kids_bottom_png.png.meta | 127 ------------------ .../all_3_kids_fixed_png_v1.png.meta | 127 ------------------ .../Cutscenes/Middle/mid_01.png.meta | 127 ------------------ .../Cutscenes/Middle/mid_02.png.meta | 127 ------------------ .../Cutscenes/Middle/mid_03.png.meta | 127 ------------------ .../Cutscenes/Middle/mid_04.png.meta | 127 ------------------ .../Cutscenes/Opening/open_01.png.meta | 127 ------------------ .../Cutscenes/Opening/open_02.png.meta | 127 ------------------ .../Cutscenes/Opening/open_03.png.meta | 127 ------------------ .../Cutscenes/Opening/open_04.png.meta | 127 ------------------ .../Cutscenes/Opening/open_05.png.meta | 127 ------------------ .../Cutscenes/Opening/open_06.png.meta | 127 ------------------ ...h coat in 2 kids in a trench coat.wav.meta | 23 ---- ...h coat in 2 kids in a trench coat.wav.meta | 23 ---- ...h coat in 2 kids in a trench coat.wav.meta | 23 ---- ...h coat in 2 kids in a trench coat.wav.meta | 23 ---- .../Resources/Music/cutscene drums.wav.meta | 23 ---- .../SoundEffects/bad arrow 1.wav.meta | 23 ---- .../SoundEffects/bad arrow 2.wav.meta | 23 ---- .../SoundEffects/bad arrow 3.wav.meta | 23 ---- .../SoundEffects/bad arrow 4.wav.meta | 23 ---- .../SoundEffects/bad arrow 5.wav.meta | 23 ---- .../SoundEffects/good arrow 1.wav.meta | 23 ---- .../SoundEffects/good arrow 2.wav.meta | 23 ---- .../SoundEffects/good arrow 3.wav.meta | 23 ---- .../SoundEffects/good arrow 4.wav.meta | 23 ---- .../SoundEffects/good arrow 5.wav.meta | 23 ---- Assets/Resources/UISprites/ArrowDown.png.meta | 127 ------------------ Assets/Resources/UISprites/ArrowLeft.png.meta | 127 ------------------ .../Resources/UISprites/ArrowRight.png.meta | 127 ------------------ Assets/Resources/UISprites/ArrowUp.png.meta | 127 ------------------ Assets/Resources/UISprites/Box1.png.meta | 127 ------------------ Assets/Resources/UISprites/Box2.png.meta | 127 ------------------ Assets/Resources/UISprites/Box3.png.meta | 127 ------------------ Assets/Resources/UISprites/NoseGoes.png.meta | 127 ------------------ .../Resources/UISprites/Restabilize.png.meta | 127 ------------------ .../UISprites/RestabilizeLow.png.meta | 127 ------------------ Assets/Resources/UISprites/X.png.meta | 127 ------------------ Assets/Resources/UISprites/Xfilled.png.meta | 127 ------------------ .../Resources/UISprites/kid 1 icon.png.meta | 127 ------------------ .../Resources/UISprites/kid 2 icon.png.meta | 127 ------------------ Assets/Resources/UISprites/kid3.png.meta | 127 ------------------ 44 files changed, 83 insertions(+), 3901 deletions(-) delete mode 100644 Assets/Backgrounds/background v1.png.meta create mode 100644 Assets/Resources/Backgrounds/Background.mat delete mode 100644 Assets/Resources/Characters/2_kids_bottom_png.png.meta delete mode 100644 Assets/Resources/Characters/all_3_kids_fixed_png_v1.png.meta delete mode 100644 Assets/Resources/Cutscenes/Middle/mid_01.png.meta delete mode 100644 Assets/Resources/Cutscenes/Middle/mid_02.png.meta delete mode 100644 Assets/Resources/Cutscenes/Middle/mid_03.png.meta delete mode 100644 Assets/Resources/Cutscenes/Middle/mid_04.png.meta delete mode 100644 Assets/Resources/Cutscenes/Opening/open_01.png.meta delete mode 100644 Assets/Resources/Cutscenes/Opening/open_02.png.meta delete mode 100644 Assets/Resources/Cutscenes/Opening/open_03.png.meta delete mode 100644 Assets/Resources/Cutscenes/Opening/open_04.png.meta delete mode 100644 Assets/Resources/Cutscenes/Opening/open_05.png.meta delete mode 100644 Assets/Resources/Cutscenes/Opening/open_06.png.meta delete mode 100644 Assets/Resources/Music/(2 kids version) 2 kids in a trench coat in 2 kids in a trench coat.wav.meta delete mode 100644 Assets/Resources/Music/(3 kids version) 2 kids in a trench coat in 2 kids in a trench coat.wav.meta delete mode 100644 Assets/Resources/Music/(filtered 2 kids version) 2 kids in a trench coat in 2 kids in a trench coat.wav.meta delete mode 100644 Assets/Resources/Music/(filtered 3 kids version) 2 kids in a trench coat in 2 kids in a trench coat.wav.meta delete mode 100644 Assets/Resources/Music/cutscene drums.wav.meta delete mode 100644 Assets/Resources/SoundEffects/bad arrow 1.wav.meta delete mode 100644 Assets/Resources/SoundEffects/bad arrow 2.wav.meta delete mode 100644 Assets/Resources/SoundEffects/bad arrow 3.wav.meta delete mode 100644 Assets/Resources/SoundEffects/bad arrow 4.wav.meta delete mode 100644 Assets/Resources/SoundEffects/bad arrow 5.wav.meta delete mode 100644 Assets/Resources/SoundEffects/good arrow 1.wav.meta delete mode 100644 Assets/Resources/SoundEffects/good arrow 2.wav.meta delete mode 100644 Assets/Resources/SoundEffects/good arrow 3.wav.meta delete mode 100644 Assets/Resources/SoundEffects/good arrow 4.wav.meta delete mode 100644 Assets/Resources/SoundEffects/good arrow 5.wav.meta delete mode 100644 Assets/Resources/UISprites/ArrowDown.png.meta delete mode 100644 Assets/Resources/UISprites/ArrowLeft.png.meta delete mode 100644 Assets/Resources/UISprites/ArrowRight.png.meta delete mode 100644 Assets/Resources/UISprites/ArrowUp.png.meta delete mode 100644 Assets/Resources/UISprites/Box1.png.meta delete mode 100644 Assets/Resources/UISprites/Box2.png.meta delete mode 100644 Assets/Resources/UISprites/Box3.png.meta delete mode 100644 Assets/Resources/UISprites/NoseGoes.png.meta delete mode 100644 Assets/Resources/UISprites/Restabilize.png.meta delete mode 100644 Assets/Resources/UISprites/RestabilizeLow.png.meta delete mode 100644 Assets/Resources/UISprites/X.png.meta delete mode 100644 Assets/Resources/UISprites/Xfilled.png.meta delete mode 100644 Assets/Resources/UISprites/kid 1 icon.png.meta delete mode 100644 Assets/Resources/UISprites/kid 2 icon.png.meta delete mode 100644 Assets/Resources/UISprites/kid3.png.meta diff --git a/Assets/Backgrounds/background v1.png.meta b/Assets/Backgrounds/background v1.png.meta deleted file mode 100644 index ee162a6..0000000 --- a/Assets/Backgrounds/background v1.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 28ec3b2ff439e40d39cc0688efb56873 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 0 - wrapV: 0 - wrapW: 0 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/Backgrounds/Background.mat b/Assets/Resources/Backgrounds/Background.mat new file mode 100644 index 0000000..59d80bc --- /dev/null +++ b/Assets/Resources/Backgrounds/Background.mat @@ -0,0 +1,83 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Background + m_Shader: {fileID: 10752, guid: 0000000000000000f000000000000000, type: 0} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: 63b518674f0844aebafbed5993dccb78, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + m_BuildTextureStacks: [] diff --git a/Assets/Resources/Characters/2_kids_bottom_png.png.meta b/Assets/Resources/Characters/2_kids_bottom_png.png.meta deleted file mode 100644 index fe07d2d..0000000 --- a/Assets/Resources/Characters/2_kids_bottom_png.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: be2d4ea90292346768ce28c622ed4c92 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/Characters/all_3_kids_fixed_png_v1.png.meta b/Assets/Resources/Characters/all_3_kids_fixed_png_v1.png.meta deleted file mode 100644 index e4d23e4..0000000 --- a/Assets/Resources/Characters/all_3_kids_fixed_png_v1.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 6206cebbb67e243c0a98af5b181d5c86 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/Cutscenes/Middle/mid_01.png.meta b/Assets/Resources/Cutscenes/Middle/mid_01.png.meta deleted file mode 100644 index 57bf2c1..0000000 --- a/Assets/Resources/Cutscenes/Middle/mid_01.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 1eac6e8b35c634d87bc4a0cc61eba858 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/Cutscenes/Middle/mid_02.png.meta b/Assets/Resources/Cutscenes/Middle/mid_02.png.meta deleted file mode 100644 index 5f1e686..0000000 --- a/Assets/Resources/Cutscenes/Middle/mid_02.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 9af2472c19bbe4e0bb210773fbb5b5b9 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/Cutscenes/Middle/mid_03.png.meta b/Assets/Resources/Cutscenes/Middle/mid_03.png.meta deleted file mode 100644 index 4d316a4..0000000 --- a/Assets/Resources/Cutscenes/Middle/mid_03.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 40e578c8971b643a089e947e74cf271c -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/Cutscenes/Middle/mid_04.png.meta b/Assets/Resources/Cutscenes/Middle/mid_04.png.meta deleted file mode 100644 index 9ab1e01..0000000 --- a/Assets/Resources/Cutscenes/Middle/mid_04.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 85403076e0cd4466785eeb894920a60d -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/Cutscenes/Opening/open_01.png.meta b/Assets/Resources/Cutscenes/Opening/open_01.png.meta deleted file mode 100644 index fca7f74..0000000 --- a/Assets/Resources/Cutscenes/Opening/open_01.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 43ef60a0231b3466da8de911b5051ca0 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/Cutscenes/Opening/open_02.png.meta b/Assets/Resources/Cutscenes/Opening/open_02.png.meta deleted file mode 100644 index 50a498b..0000000 --- a/Assets/Resources/Cutscenes/Opening/open_02.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 2ad0b8fd12328428ca573ed291414872 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/Cutscenes/Opening/open_03.png.meta b/Assets/Resources/Cutscenes/Opening/open_03.png.meta deleted file mode 100644 index 36eabbc..0000000 --- a/Assets/Resources/Cutscenes/Opening/open_03.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 03aa830862578435499a2c59e6754846 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/Cutscenes/Opening/open_04.png.meta b/Assets/Resources/Cutscenes/Opening/open_04.png.meta deleted file mode 100644 index 05a7ea5..0000000 --- a/Assets/Resources/Cutscenes/Opening/open_04.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 7ddb1331f270e4ba09e150b08fd8bf10 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/Cutscenes/Opening/open_05.png.meta b/Assets/Resources/Cutscenes/Opening/open_05.png.meta deleted file mode 100644 index c2d274f..0000000 --- a/Assets/Resources/Cutscenes/Opening/open_05.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 2f8526c4a935a4a2481ee7918c634d8e -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/Cutscenes/Opening/open_06.png.meta b/Assets/Resources/Cutscenes/Opening/open_06.png.meta deleted file mode 100644 index 9f7ccbf..0000000 --- a/Assets/Resources/Cutscenes/Opening/open_06.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 34e51a102871e4265ad1a5d0a036860f -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/Music/(2 kids version) 2 kids in a trench coat in 2 kids in a trench coat.wav.meta b/Assets/Resources/Music/(2 kids version) 2 kids in a trench coat in 2 kids in a trench coat.wav.meta deleted file mode 100644 index 4b82c2e..0000000 --- a/Assets/Resources/Music/(2 kids version) 2 kids in a trench coat in 2 kids in a trench coat.wav.meta +++ /dev/null @@ -1,23 +0,0 @@ -fileFormatVersion: 2 -guid: 04c9a12f8585f482b89e4c987157d41c -AudioImporter: - externalObjects: {} - serializedVersion: 7 - defaultSettings: - serializedVersion: 2 - loadType: 0 - sampleRateSetting: 0 - sampleRateOverride: 44100 - compressionFormat: 1 - quality: 1 - conversionMode: 0 - preloadAudioData: 0 - platformSettingOverrides: {} - forceToMono: 0 - normalize: 1 - loadInBackground: 0 - ambisonic: 0 - 3D: 1 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/Music/(3 kids version) 2 kids in a trench coat in 2 kids in a trench coat.wav.meta b/Assets/Resources/Music/(3 kids version) 2 kids in a trench coat in 2 kids in a trench coat.wav.meta deleted file mode 100644 index ce2bf4a..0000000 --- a/Assets/Resources/Music/(3 kids version) 2 kids in a trench coat in 2 kids in a trench coat.wav.meta +++ /dev/null @@ -1,23 +0,0 @@ -fileFormatVersion: 2 -guid: 1b4e561c226c4442cb149a5fade2e782 -AudioImporter: - externalObjects: {} - serializedVersion: 7 - defaultSettings: - serializedVersion: 2 - loadType: 0 - sampleRateSetting: 0 - sampleRateOverride: 44100 - compressionFormat: 1 - quality: 1 - conversionMode: 0 - preloadAudioData: 0 - platformSettingOverrides: {} - forceToMono: 0 - normalize: 1 - loadInBackground: 0 - ambisonic: 0 - 3D: 1 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/Music/(filtered 2 kids version) 2 kids in a trench coat in 2 kids in a trench coat.wav.meta b/Assets/Resources/Music/(filtered 2 kids version) 2 kids in a trench coat in 2 kids in a trench coat.wav.meta deleted file mode 100644 index b6969a3..0000000 --- a/Assets/Resources/Music/(filtered 2 kids version) 2 kids in a trench coat in 2 kids in a trench coat.wav.meta +++ /dev/null @@ -1,23 +0,0 @@ -fileFormatVersion: 2 -guid: 8ae16fd75d866476c8fb25cf2d0f618b -AudioImporter: - externalObjects: {} - serializedVersion: 7 - defaultSettings: - serializedVersion: 2 - loadType: 0 - sampleRateSetting: 0 - sampleRateOverride: 44100 - compressionFormat: 1 - quality: 1 - conversionMode: 0 - preloadAudioData: 0 - platformSettingOverrides: {} - forceToMono: 0 - normalize: 1 - loadInBackground: 0 - ambisonic: 0 - 3D: 1 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/Music/(filtered 3 kids version) 2 kids in a trench coat in 2 kids in a trench coat.wav.meta b/Assets/Resources/Music/(filtered 3 kids version) 2 kids in a trench coat in 2 kids in a trench coat.wav.meta deleted file mode 100644 index 3e41888..0000000 --- a/Assets/Resources/Music/(filtered 3 kids version) 2 kids in a trench coat in 2 kids in a trench coat.wav.meta +++ /dev/null @@ -1,23 +0,0 @@ -fileFormatVersion: 2 -guid: e308898334c3542018714759fce3b522 -AudioImporter: - externalObjects: {} - serializedVersion: 7 - defaultSettings: - serializedVersion: 2 - loadType: 0 - sampleRateSetting: 0 - sampleRateOverride: 44100 - compressionFormat: 1 - quality: 1 - conversionMode: 0 - preloadAudioData: 0 - platformSettingOverrides: {} - forceToMono: 0 - normalize: 1 - loadInBackground: 0 - ambisonic: 0 - 3D: 1 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/Music/cutscene drums.wav.meta b/Assets/Resources/Music/cutscene drums.wav.meta deleted file mode 100644 index 9989ac7..0000000 --- a/Assets/Resources/Music/cutscene drums.wav.meta +++ /dev/null @@ -1,23 +0,0 @@ -fileFormatVersion: 2 -guid: df799b0cfa2e54280800a72b41ece552 -AudioImporter: - externalObjects: {} - serializedVersion: 7 - defaultSettings: - serializedVersion: 2 - loadType: 0 - sampleRateSetting: 0 - sampleRateOverride: 44100 - compressionFormat: 1 - quality: 1 - conversionMode: 0 - preloadAudioData: 0 - platformSettingOverrides: {} - forceToMono: 0 - normalize: 1 - loadInBackground: 0 - ambisonic: 0 - 3D: 1 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/SoundEffects/bad arrow 1.wav.meta b/Assets/Resources/SoundEffects/bad arrow 1.wav.meta deleted file mode 100644 index 57d674a..0000000 --- a/Assets/Resources/SoundEffects/bad arrow 1.wav.meta +++ /dev/null @@ -1,23 +0,0 @@ -fileFormatVersion: 2 -guid: 0d2500ba27eb54096b9c880d6334353c -AudioImporter: - externalObjects: {} - serializedVersion: 7 - defaultSettings: - serializedVersion: 2 - loadType: 0 - sampleRateSetting: 0 - sampleRateOverride: 44100 - compressionFormat: 1 - quality: 1 - conversionMode: 0 - preloadAudioData: 0 - platformSettingOverrides: {} - forceToMono: 0 - normalize: 1 - loadInBackground: 0 - ambisonic: 0 - 3D: 1 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/SoundEffects/bad arrow 2.wav.meta b/Assets/Resources/SoundEffects/bad arrow 2.wav.meta deleted file mode 100644 index 820c5fc..0000000 --- a/Assets/Resources/SoundEffects/bad arrow 2.wav.meta +++ /dev/null @@ -1,23 +0,0 @@ -fileFormatVersion: 2 -guid: 280e8908c375a4760b450bde0a1ada02 -AudioImporter: - externalObjects: {} - serializedVersion: 7 - defaultSettings: - serializedVersion: 2 - loadType: 0 - sampleRateSetting: 0 - sampleRateOverride: 44100 - compressionFormat: 1 - quality: 1 - conversionMode: 0 - preloadAudioData: 0 - platformSettingOverrides: {} - forceToMono: 0 - normalize: 1 - loadInBackground: 0 - ambisonic: 0 - 3D: 1 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/SoundEffects/bad arrow 3.wav.meta b/Assets/Resources/SoundEffects/bad arrow 3.wav.meta deleted file mode 100644 index d19eb2b..0000000 --- a/Assets/Resources/SoundEffects/bad arrow 3.wav.meta +++ /dev/null @@ -1,23 +0,0 @@ -fileFormatVersion: 2 -guid: 3ea184a35b20a4300ac2b175d5a7b070 -AudioImporter: - externalObjects: {} - serializedVersion: 7 - defaultSettings: - serializedVersion: 2 - loadType: 0 - sampleRateSetting: 0 - sampleRateOverride: 44100 - compressionFormat: 1 - quality: 1 - conversionMode: 0 - preloadAudioData: 0 - platformSettingOverrides: {} - forceToMono: 0 - normalize: 1 - loadInBackground: 0 - ambisonic: 0 - 3D: 1 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/SoundEffects/bad arrow 4.wav.meta b/Assets/Resources/SoundEffects/bad arrow 4.wav.meta deleted file mode 100644 index dbea413..0000000 --- a/Assets/Resources/SoundEffects/bad arrow 4.wav.meta +++ /dev/null @@ -1,23 +0,0 @@ -fileFormatVersion: 2 -guid: 0be176ff82a614808aa053337089d816 -AudioImporter: - externalObjects: {} - serializedVersion: 7 - defaultSettings: - serializedVersion: 2 - loadType: 0 - sampleRateSetting: 0 - sampleRateOverride: 44100 - compressionFormat: 1 - quality: 1 - conversionMode: 0 - preloadAudioData: 0 - platformSettingOverrides: {} - forceToMono: 0 - normalize: 1 - loadInBackground: 0 - ambisonic: 0 - 3D: 1 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/SoundEffects/bad arrow 5.wav.meta b/Assets/Resources/SoundEffects/bad arrow 5.wav.meta deleted file mode 100644 index 94ca468..0000000 --- a/Assets/Resources/SoundEffects/bad arrow 5.wav.meta +++ /dev/null @@ -1,23 +0,0 @@ -fileFormatVersion: 2 -guid: cfb839ebcc2474fb888156ecb534fbe7 -AudioImporter: - externalObjects: {} - serializedVersion: 7 - defaultSettings: - serializedVersion: 2 - loadType: 0 - sampleRateSetting: 0 - sampleRateOverride: 44100 - compressionFormat: 1 - quality: 1 - conversionMode: 0 - preloadAudioData: 0 - platformSettingOverrides: {} - forceToMono: 0 - normalize: 1 - loadInBackground: 0 - ambisonic: 0 - 3D: 1 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/SoundEffects/good arrow 1.wav.meta b/Assets/Resources/SoundEffects/good arrow 1.wav.meta deleted file mode 100644 index 648394e..0000000 --- a/Assets/Resources/SoundEffects/good arrow 1.wav.meta +++ /dev/null @@ -1,23 +0,0 @@ -fileFormatVersion: 2 -guid: d28f3b5c03fc04e1e9996da7e241998c -AudioImporter: - externalObjects: {} - serializedVersion: 7 - defaultSettings: - serializedVersion: 2 - loadType: 0 - sampleRateSetting: 0 - sampleRateOverride: 44100 - compressionFormat: 1 - quality: 1 - conversionMode: 0 - preloadAudioData: 0 - platformSettingOverrides: {} - forceToMono: 0 - normalize: 1 - loadInBackground: 0 - ambisonic: 0 - 3D: 1 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/SoundEffects/good arrow 2.wav.meta b/Assets/Resources/SoundEffects/good arrow 2.wav.meta deleted file mode 100644 index 6b9db94..0000000 --- a/Assets/Resources/SoundEffects/good arrow 2.wav.meta +++ /dev/null @@ -1,23 +0,0 @@ -fileFormatVersion: 2 -guid: 384a2836f2946479183bad75e9056eb2 -AudioImporter: - externalObjects: {} - serializedVersion: 7 - defaultSettings: - serializedVersion: 2 - loadType: 0 - sampleRateSetting: 0 - sampleRateOverride: 44100 - compressionFormat: 1 - quality: 1 - conversionMode: 0 - preloadAudioData: 0 - platformSettingOverrides: {} - forceToMono: 0 - normalize: 1 - loadInBackground: 0 - ambisonic: 0 - 3D: 1 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/SoundEffects/good arrow 3.wav.meta b/Assets/Resources/SoundEffects/good arrow 3.wav.meta deleted file mode 100644 index ae47cc6..0000000 --- a/Assets/Resources/SoundEffects/good arrow 3.wav.meta +++ /dev/null @@ -1,23 +0,0 @@ -fileFormatVersion: 2 -guid: b86be4f814af144528c37a485c2c24b5 -AudioImporter: - externalObjects: {} - serializedVersion: 7 - defaultSettings: - serializedVersion: 2 - loadType: 0 - sampleRateSetting: 0 - sampleRateOverride: 44100 - compressionFormat: 1 - quality: 1 - conversionMode: 0 - preloadAudioData: 0 - platformSettingOverrides: {} - forceToMono: 0 - normalize: 1 - loadInBackground: 0 - ambisonic: 0 - 3D: 1 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/SoundEffects/good arrow 4.wav.meta b/Assets/Resources/SoundEffects/good arrow 4.wav.meta deleted file mode 100644 index 6814310..0000000 --- a/Assets/Resources/SoundEffects/good arrow 4.wav.meta +++ /dev/null @@ -1,23 +0,0 @@ -fileFormatVersion: 2 -guid: 7efd9b3fcec2549a78eb5e7b042ca8b7 -AudioImporter: - externalObjects: {} - serializedVersion: 7 - defaultSettings: - serializedVersion: 2 - loadType: 0 - sampleRateSetting: 0 - sampleRateOverride: 44100 - compressionFormat: 1 - quality: 1 - conversionMode: 0 - preloadAudioData: 0 - platformSettingOverrides: {} - forceToMono: 0 - normalize: 1 - loadInBackground: 0 - ambisonic: 0 - 3D: 1 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/SoundEffects/good arrow 5.wav.meta b/Assets/Resources/SoundEffects/good arrow 5.wav.meta deleted file mode 100644 index d8d9c9e..0000000 --- a/Assets/Resources/SoundEffects/good arrow 5.wav.meta +++ /dev/null @@ -1,23 +0,0 @@ -fileFormatVersion: 2 -guid: f71e16b409b3f4a6482bad09e4c64f10 -AudioImporter: - externalObjects: {} - serializedVersion: 7 - defaultSettings: - serializedVersion: 2 - loadType: 0 - sampleRateSetting: 0 - sampleRateOverride: 44100 - compressionFormat: 1 - quality: 1 - conversionMode: 0 - preloadAudioData: 0 - platformSettingOverrides: {} - forceToMono: 0 - normalize: 1 - loadInBackground: 0 - ambisonic: 0 - 3D: 1 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/UISprites/ArrowDown.png.meta b/Assets/Resources/UISprites/ArrowDown.png.meta deleted file mode 100644 index fd1911c..0000000 --- a/Assets/Resources/UISprites/ArrowDown.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: a7c8a1674e65c4d0cbb635de89565beb -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/UISprites/ArrowLeft.png.meta b/Assets/Resources/UISprites/ArrowLeft.png.meta deleted file mode 100644 index d0be3fb..0000000 --- a/Assets/Resources/UISprites/ArrowLeft.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 38724783ceb3246cdbba33673d7af8c3 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/UISprites/ArrowRight.png.meta b/Assets/Resources/UISprites/ArrowRight.png.meta deleted file mode 100644 index 32997db..0000000 --- a/Assets/Resources/UISprites/ArrowRight.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 1026ccf96dc6c408a99071b5ab420e37 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/UISprites/ArrowUp.png.meta b/Assets/Resources/UISprites/ArrowUp.png.meta deleted file mode 100644 index a2ebaa8..0000000 --- a/Assets/Resources/UISprites/ArrowUp.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: cac35ee0288bf42c9a44b25d65b35985 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/UISprites/Box1.png.meta b/Assets/Resources/UISprites/Box1.png.meta deleted file mode 100644 index fa66e39..0000000 --- a/Assets/Resources/UISprites/Box1.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 7ec814963bdf147fca4b29fd667d4493 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/UISprites/Box2.png.meta b/Assets/Resources/UISprites/Box2.png.meta deleted file mode 100644 index 0efc49a..0000000 --- a/Assets/Resources/UISprites/Box2.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 3da9af5126cb3409089b11aef8e47935 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/UISprites/Box3.png.meta b/Assets/Resources/UISprites/Box3.png.meta deleted file mode 100644 index 7f681ed..0000000 --- a/Assets/Resources/UISprites/Box3.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: b86c78eca06c64c6387b11bf599b8a9d -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/UISprites/NoseGoes.png.meta b/Assets/Resources/UISprites/NoseGoes.png.meta deleted file mode 100644 index 8ae1cff..0000000 --- a/Assets/Resources/UISprites/NoseGoes.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 472c6eb1a61f44f45b6fc25e8b11f2a7 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/UISprites/Restabilize.png.meta b/Assets/Resources/UISprites/Restabilize.png.meta deleted file mode 100644 index e342172..0000000 --- a/Assets/Resources/UISprites/Restabilize.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 99912848121d64883a0cd65a4c092481 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/UISprites/RestabilizeLow.png.meta b/Assets/Resources/UISprites/RestabilizeLow.png.meta deleted file mode 100644 index 48939f7..0000000 --- a/Assets/Resources/UISprites/RestabilizeLow.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 252d4a3ed11b44845b2ca4b4cbc55827 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/UISprites/X.png.meta b/Assets/Resources/UISprites/X.png.meta deleted file mode 100644 index d89df17..0000000 --- a/Assets/Resources/UISprites/X.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: eec99f7d9906940478029d786842ae6d -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/UISprites/Xfilled.png.meta b/Assets/Resources/UISprites/Xfilled.png.meta deleted file mode 100644 index 3bf99bc..0000000 --- a/Assets/Resources/UISprites/Xfilled.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: deef9e3207bbd488bbec282f6bfd88c9 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/UISprites/kid 1 icon.png.meta b/Assets/Resources/UISprites/kid 1 icon.png.meta deleted file mode 100644 index 2230e44..0000000 --- a/Assets/Resources/UISprites/kid 1 icon.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: f0e9885992d684ebaa5e3ada4710e78c -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/UISprites/kid 2 icon.png.meta b/Assets/Resources/UISprites/kid 2 icon.png.meta deleted file mode 100644 index ad732b4..0000000 --- a/Assets/Resources/UISprites/kid 2 icon.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 699dbd46ffdce4fecb32739f255f9471 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/UISprites/kid3.png.meta b/Assets/Resources/UISprites/kid3.png.meta deleted file mode 100644 index 9a65a73..0000000 --- a/Assets/Resources/UISprites/kid3.png.meta +++ /dev/null @@ -1,127 +0,0 @@ -fileFormatVersion: 2 -guid: 4c41b38d02ba643f0b41c45a4626fca7 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: From 5f7805e525a2ee880267528aaa180e0864c9014c Mon Sep 17 00:00:00 2001 From: Shayla Beltran Date: Mon, 15 Jan 2024 16:33:14 -0600 Subject: [PATCH 03/19] adding fonts, ui --- Assets/Scenes/MainGame.unity | 24 +- Assets/TextMesh Pro/Fonts/KGPrimaryWhimsy.ttf | Bin 0 -> 39964 bytes .../Fonts/Unicorn Fold - Display.ttf | Bin 0 -> 96500 bytes .../KGPrimaryWhimsy SDF.asset | 2816 +++++++++++++++++ .../Unicorn Fold - Display SDF.asset | 2740 ++++++++++++++++ 5 files changed, 5569 insertions(+), 11 deletions(-) create mode 100644 Assets/TextMesh Pro/Fonts/KGPrimaryWhimsy.ttf create mode 100644 Assets/TextMesh Pro/Fonts/Unicorn Fold - Display.ttf create mode 100644 Assets/TextMesh Pro/Resources/Fonts & Materials/KGPrimaryWhimsy SDF.asset create mode 100644 Assets/TextMesh Pro/Resources/Fonts & Materials/Unicorn Fold - Display SDF.asset diff --git a/Assets/Scenes/MainGame.unity b/Assets/Scenes/MainGame.unity index 0494f1d..06fec1f 100644 --- a/Assets/Scenes/MainGame.unity +++ b/Assets/Scenes/MainGame.unity @@ -823,7 +823,7 @@ SpriteRenderer: m_Size: {x: 15.6, y: 10.8} m_AdaptiveModeThreshold: 0.5 m_SpriteTileMode: 0 - m_WasSpriteAssigned: 1 + m_WasSpriteAssigned: 0 m_MaskInteraction: 0 m_SpriteSortPoint: 0 --- !u!4 &771962607 @@ -1202,7 +1202,7 @@ RectTransform: m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} + m_SizeDelta: {x: -1.24, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &1300261464 MonoBehaviour: @@ -1575,8 +1575,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: 205} - m_SizeDelta: {x: 168.8534, y: 16.9068} + m_AnchoredPosition: {x: 0, y: 180.806} + m_SizeDelta: {x: 168.854, y: 56.506} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &1698589090 MonoBehaviour: @@ -1598,10 +1598,12 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: 'Distance: 0000 meters' + m_text: 'SCORE + + 0000 meters' m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} - m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontAsset: {fileID: 11400000, guid: 33ad01eb91b6a42b4bc7e0ec655568bb, type: 2} + m_sharedMaterial: {fileID: 5430614902480215695, guid: 33ad01eb91b6a42b4bc7e0ec655568bb, type: 2} m_fontSharedMaterials: [] m_fontMaterial: {fileID: 0} m_fontMaterials: [] @@ -1625,10 +1627,10 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 15.1 - m_fontSizeBase: 36 + m_fontSize: 24 + m_fontSizeBase: 24 m_fontWeight: 400 - m_enableAutoSizing: 1 + m_enableAutoSizing: 0 m_fontSizeMin: 10 m_fontSizeMax: 72 m_fontStyle: 0 @@ -1661,7 +1663,7 @@ MonoBehaviour: m_VertexBufferAutoSizeReduction: 0 m_useMaxVisibleDescender: 1 m_pageToDisplay: 1 - m_margin: {x: 0, y: 0, z: 0, w: 0} + m_margin: {x: -0.00009918213, y: 0, z: 0, w: 0} m_isUsingLegacyAnimationComponent: 0 m_isVolumetricText: 0 m_hasFontAssetChanged: 0 diff --git a/Assets/TextMesh Pro/Fonts/KGPrimaryWhimsy.ttf b/Assets/TextMesh Pro/Fonts/KGPrimaryWhimsy.ttf new file mode 100644 index 0000000000000000000000000000000000000000..774a8c0177895414fc00ca48f59d7910cefa7a67 GIT binary patch literal 39964 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 RVhR4(4ideVNcT04^DlDt8_fU! literal 0 HcmV?d00001 diff --git a/Assets/TextMesh Pro/Fonts/Unicorn Fold - Display.ttf b/Assets/TextMesh Pro/Fonts/Unicorn Fold - Display.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ec3ead47073f090789e89f38f725e86dbedd3c85 GIT binary patch literal 96500 zcmdSC36vaHdG~#*s;jE^wR&Hsr)Q>n7R|nCMl&O6G#XiwC2O&^G4@!pY|LZa8tQ>ic!`LrO(Uygzc&T}SRX)*TsBDtNO}`in;nzVR+;hxQ-h=s$A%y*GWK z_~f5){tl%r|M=z`4<0VeWd0}Zuj2iQo2f8=SN|@r5A(Y7<~xqvbNly7e%hiK=WoCB zhJzpY#J~JNX-BW*oZq|S;5~O4W&0&)X}@~(;2k%f`|;Q2m3Eh-ly&!AcfRr1uJAvf zQQC>~ob%(m-f-hxL)O>6rBq}G=l?!WhH5%~!!PERV>91ZMdQcRsIPB-%RhU^T_3!- z@4^NnZ*=h5Qo7Xg!)NsGUbNIJYrgF}pi1g*l-+!vtJ0PJ z+x*j%Py3Meh%%K=e^}qohqii0?K(B$K8=;F#a6ypfAxVK>Pt%1ZZveR;mtg+AM(B- z=V!|De`r_o*4})5yr*UEHVt4>hhmtfJcIRYLu5wO0F_s%!TvOM5|$XRMXmL)S&i3wMzSA&TCg??HKL-I{p8Nn$*6iHt79ollC4psGp>VJp!pHo%sd#XgKXnE?g zD$6r<)X%64&p6BT$`zM~oYE{qozIMNuH4`I)fzp=z5Rge z{9~0=kMQ0nDc_`x$5b27Eu|jkyrRmeH&UO3&hy^CKz|?lD_D(>yVsahKUSTFqiXtt zDxsg|`F)ko{xRqEBP0E)p}xX(Ppe7wXVi77Vf8W9ubzYcfEv)BRWW&A{i7Nb`4Zl} zR&nLw&sB`;in+2P^3p2pJQIYCle$7}Q8%h9)i$+NU90w}Q|fAUmzq+m z)wEipX4I^jQ)|^awO;L0d)3YApt?mZsEuk=b*oM_p{i;Xci*Nu)PU;3P7JC()dSz# zRb36KimJi$UU)vP#?*FoR9&Sut83JI(Ugb^a=#YxSK`?Pkf#vxn8sejR2e%MMf!Zo zud--QN)=T>?NE2Boob$2`GoqU`g!$>>Q~g$>RI(W>bKSJB1vCXzlWv%BlU+!;Qxh` zeO3M6>Q9io7u56W&(+t|U#P!E7r%j(eT#a(dV_ksdaJsR*50I!s}t(HdY}4fb-ntq zdWO0q>Q;3d(y!D#6z}H&^%017tG`sc)Nb{*R<(Lqom21N)yLGw(f3Exd(@lNX?24- ztoEw|YMFPwC01A+Q@5)-ILgocYDpd9_;c!))X%D4R==R0P@h$wQ=d^!s$Zr43+mU^ zZ>TS-kE%!22hhf!QXfRu->E*N-lZPH6Z|6Q%<%MmJUyHg{mIk#HFZ%-Xv5mPwp%-> z-J_k>zoP$j)u|S$m1?zGtJbU2)n9C{)%04jc75%}ix>HcjUfZQz z&!^w4e_8*FYO0#6mYScQTJh<_d|JEseYb_?zl-9-`MG$7cl7>$^WZnH{pJy+{^s}o z=GJeV_{NrRNVO-ytJS}1K`oieRTrNyx)yis?>JC>xcczs!w**%t2ZA!{DiN|J@Uql4<8t; zKB0E+zlHx-?{9x%-GSmI^2P%PrfJ6~?eGy!fA|0`+}dn`qgyrj5+|9fwpO1o>O1!D z-2cS=3&khaEgUGew^uhl@ueO6pZL;3vHidS&ay6DDOddFTXM~7wz+1jm-qc%E4%kU zv99=pI`Htr(&p~{9qmut|M0`bhq;gD>!;M0UQwZ`S5~ZRR`4WfgD0`^Dee9pG{&K$ zy(kqO?H%o0=Ya+K4y@X`d;dnRv|X+=_|wvPYian&a}wlm8z+^3;k)E^;31)1JXLMOC;Dun@xmcH0lui4}YoE{Jo5folgVHa&O|6$vl`bP5so#U860dXl9mZAs z7|I4gE$a_}8Lm+KwTL_s9!uBYQ)-41-nbur4Hloq=O^Y4JOcpPsUq|{6Gs8R{*)>{ zN8!XIuQz{veGwF}nVZ=Rp4iMI+YDaW3=Y|hjoggQ+KheNjK$oHRosmC+KheMtRmO0 zH!)?K)r%DUS~xPz)0A$eY1U5{{z1<8ODg}KqF+lt0f;=MhcZRkOgTWgg>o^ zrzlTTexDM#_9@j%i#b}%anaKHB=lsHUds(_<@H+Xw?8*DjFXFMc2rA8P5yV(>W%uu z_*lI$V2qE=>63HKgEl%+(bJY=TiJ?ck9E|_nlm~wZcmKYCnm?o8oZ8bSw~w)24eM6 z($;m2U)^6yBulnGXeDDEB_~y>MMEJ=(=@~Im*VkEMCeqk@($b2ukF)y+pp_B?JMDO zKA~x5X3LH1yHWvPB9%_&K6*N3@n$d?PdGu75BegJd^H`lQ^{z$7)^Dh98C}0=eGm4 z{UhBPyLH@e>3;wCt>ZQ_FnjSO?eqH2f-CocEY~+>z~y~NcpnnpH-(`t6?IP-rd?rp z1{``F+!73y<;Zgz$z&_KBjpcKV zT3aj{)%9qm7;%P1hn&})+R>M`O(zx0m7^P$R+s72>8YjPrkRFj+nW6&|Jbc#ewrV@ zZOrCb_*4VkDl@j31g#%bZ_?MSe6lMa+dOJyPC+Y1Zy`7}Dlk|3y-cHin zNqRfk>g^=Go%HnlIAak{a^~IRH2NFqL%l6bK!#GMOi&gndnq?jPEa18JVyBhI^&1{8D~bX${dhi-?Kb5=j+T9oSjZna8@! zV_oLCx_PY2Jl16%>oSjZna8@!V_mrZYoB2(a*LWyB&VJMDSDK9FUPr;jDl&Ib|4%u ztD326J_C#A8YM$Fd|Js!QEBRqSr*mV-@c|dsiU)2xh?0nlQCN}l0n1QHqaL9?x`>2 zK%r7TAkAo|51W9}o7RQz8FV!?Z;wsNJLc-~z@|~3 z_&J~IxNuIpL;ETW*uyySZQAEn>S95RT49Bit4T%8vvPxsokd2EFs>A(97JMtq(?`3 zYS6npb=ZYE>_Q!Op$@xHhh3<{E_Q!Op$@xHhh3<{u9iCNLLGLw^16}M zUPsHXqva#ehoKKc-vfOTT6#O<^>&8d&d}Q#dOJgJXXxz=y`7=AGxTgT0Y%s`7|w`_EcbEbR?5@(&CeGB{*c9%f#5^xG05-{Uib)i)rTx(KQ`Dj|JZ(MYNP9m}@;fnZxb z9kU9Nkx_kU$Owl6{_?j(`A`fT9<7?b3*YD1QV^eEPEGh1T?H}J2)^n`Fyne+KG&(w ztkjNaQHE)izJvk%QsG~rE@`PC4kQS10mh0{ML0uDAz?bi_S&x_aD7Conu6AcIP@V7 zeTYLJ;?T#Z`Vfac#Gwyy=tCU(5Qjd*p$~EBYl%Z2;?U=6%hfcyh*m5PVjZoD=HU%Y zS;G|&*C6UhgBV1ShKj~>vaoEERO)qk1KgI)IHm>Im_Q)vh(~II7A9eRT293XejaF{ z+h#Eljm7+?-}D6w)vk2gSRxkT>1zPELMoN9Egxpim#|}%R55AjmM>e3rXzk$yYOkw z5x8d~58bw}7!TV1P{Or+5AVEj<5*j+o^*!W%!rw&=3}*Ld13cWYvYw@3<*ld!@0)V zk)a*cSRhvEUbk-ZP;r$O$(CZF+-jR%EE`;Cm>2%tXZ7E@$=2;HM+dQZJ~eUig8H)l zPOzIq_13HJujFW6_?7qgB~u^5uK^sLn72HSb=Wg9!x))ijKnZTW*8$gjFB0}$P8m- zhA}e37@1*=%rHh~7$Y;>GBU#$nPJb!7$9|cF6cdge+^LUqW1v(2k@@}x((o81Nhef zJ~M!S4d7n`_}2jbHGqE&;9qG4j~?LSTAsTC?<-hGsha`0_wl-q*D^F&3%wS(NQuF) zY!|tEG9U&(JSq0T6Ak{`!fxBe?5{wbqYo828-+rbrgf$gDKp^HOf#BIq$(zQgo1-=%dFN^MUtb||dh_xdZMrEDzcL{sx`ozJhyMx7f4e*67` z8OK5Q9uk-Fm|(^+<`5Pca-Ps0U&*zga4qO@Elq${xOM<%CR_`0)6*W;rs3K&T$337 zG+dj8YtwLT8m>*lwQ0CE4cDgO+B95i0;d-sUZeE$@R9H*D#^m3eDj?>F=dO1!nO-S_QT|ki;$|u?tD;Lb7ESlGuf$CtMZ{W+-*a1Z9!3 zmvR&31mywBW0X%&o}_%4(!`GAv@%XB&k*rGtj1k8cC<-(gWS7#40j<}U6*jzfZn(S zy0Ul@7pDyvVu)}|n3Sf|(Xu0>BTaiWI&#VT@cw@Zj1?1p%}BHjRP)1)yr#tx>G_Ug zPdTQU!LW(x!4_Bs2+cGt+izs`gy9eAdLUvau~`8>fm#=e0p(r;i=}*GkN!q0g-o+J zJJwN{+&9~`tvC9~p%bl3@4mKpJ{o-s$q1CAc|XFEgw;JZ8|rn~O& zwV+tj(->;>;t#c3bwLs`*8I{+`L;#A?Gq(`Ag zq4!gNCA1v9agi$qS&YAJ3AVEp0zUk zO(QYH3r3ub-?FTHHW3OLb|_xR+QL0ex2gg@OaqTYh1HfwwF$iD9ose%wPd&yjRgEY zt7o9wY9D%{89?AvEENXoPs{6Sg+jryoNzJLG2YjeHiG7cEnN{Slaayg1D}8WbkQ=i z>0HiEwoeUOge3yLWGxX&1pUcCqOY$rn48hIV7C1B54}+@7EDIHKGli+dKmtWVAJ0Uid#>BGHC=ue!#0D-3SFB3sXl*Myv$abNc zXoEIUv{+BJZ92)r=xvKuqVZADC9$aK=(eSJr6*pm;1DpuIiH*D^T zT(~{a=&8p-Sxw7^{4xK`Ern#H@&fq7Z~5>)g7OS|==fS2*fRg7*7#=%zI@c>%M3Gz zht$RPJfAs=5JW}teBmXXqO&ri?G!b`~ zOGef~_#3Wlzowtfy8Nj(&83UbpH0?N9dkXAczk15epM8lY+e$54cW&awIvc&3+CX7 zZQoU|^utd^EPpC&2mN-?7s2QSW63~R`$Q%+wS4cob!+lD!`6IZGn0vCOVI~D_l7k^ zP+KmWHG{Rq_2Bd12VX7Wzf#$~iC9EL6yNidp)AOo3dEh(osyp$jJMpSJX>TW9bthhRCth_YUUes4 zbthhRCtj6ctQR}oiC5j}dDZe|lwGFBGKR5?VJu@9%NWKohOvxcEMpkU7{)S&v5a9X zV;IXV!&t^JmR-YG=Hja8TopMHdK`KjTF|$LvOKzl#9fIHi|5IN1SDF~zjOvo^Qv9w z#VAbh_XxZvYFY<@tFF>% z9j2$l^mLe>4%5?NdIFPqvUQlA4tuh-EHOiF#AL2Rj=lI}xgiNo8gwT|+l!`EK>HOw z<)ZxxXuks5uYmR|h<$|zQ335&K>HQYeg(8&0qs{n`xVeWt;+{3I>=D!6q#UIr0k{K zL^(lufbtmS6O<<@U#2vXTrUzVQw7hEBe7fc;z!)}mT7O9_LgaHnf8`xZ<+R%X>XbK zmT7O9_LgaHnf8`j?Jd*ZGVS4c1o_EtQK8zvf^w> zbK3tQ_Erp;5hps((KeGv`eHqmQl)LY9MB_yfaQi~JWkBEX# zf^0qsC`gd)?&?IwwnM?j&b~@dZ{NU%XxHvtxlI4R)Vr+V-cUwMhf33Ve`7Khj%TyK z=Yj>=Xh!g}^d?^#pbb zft`X^UaMEo>J_NO6fN(EmPp!3Uca5!4+_ok5sr@xf-296=y6#iB%CzS@ zG9!r02qH6r$c!K|BZ$lhA~S->j36>2h|EY!WJVB~5%)4i=%Sx4`sr5aG3YVqw?N+l zeM^(R4f?j`Ii~&J4Q3dyXqP$CaGpO3ra5=eUw{T**1EB z&T%E@T32$8D>>(0$vIj)ON(a(LJ59yqsJ}peHlOL5=ish_oxW53~LCI$p<8+Y`A}r ztp-}6j$t1k8yB3_V2TU?Ltt&P8Cte2Cv`d4EWx#OE7Uxpk7havXGEe`PY&%W>xRjY zCO_X^8j3}N2(TUqWMYPqz=I&vKJcog`TXg&Oc=Xw_=w3wYjH3zp_*tsVp>5bBd$TS zqRxd8iIGsWZbK`Eg)psfS@47QT%)pYXJ~4CYIJafal7XCjSRH671s>~D?3+bld+`k z#N#Eswsj~_&S#x~?hAJhjprIe<%B<#?2RVPKwxpfiPkHzP$1r&)Aj6Pwb2tUWMXeX z4G9BU?m@RM{5x?yz5mK$t=rPA-px~RZ2uCJIqbOXPZOms|63}|Brn+G8*AOtV$ky*_} z4+tGowamSCSnlj$Mw`v9>d5MbZR*|Gc$PT^Q@26^+X}@hGMmbeFO-NTD*mv~iWt2a!wwXJf>m7pCpjj&mpJj*19*$V&ob?b8cXXfI6Xm8cu2Jdz- zXZY+&d6*FPPk4x81GZ7@)OLxCVm`O?@H%*i9axV(==~xA721%KO!5_)63~qVbhjj+ z8wuz}0=nT!Hxkf|1au<--AF(;63~qVbRz-XNI*9dKr8UBLi4TRvCysI@eb&n&r!Gp zp|5sl(2Z<{5t{JqazwJwwOk=XM zKL6K@7EBoc2vmf#xIEapI@wt(1%v5iMAPG;KqA*s3}*tNbhx-`-Ei2a2P{4AI2K}{ zS+Vt78WCSU$DFX!aoh2u^|po8T|GaNz#hE)9w;$j5b|%%v4_EmpVs~ZCB2=zv8Pt@ zwIO_M2w$5+u^y@DX)*dbmxs4W1Pw-S;K}ahDa!=yap=3D?-tK>h!l>d$2x?99zsD6 zAuWec&_gKbAr$lw3VH|yJ%oZDLO~CqpodV(Yud1G|MoYRJxi}YqA#j&LE zEwDQ4Ify|`1_5}7Hqe$EhW|*&(3AOcIVw(fk)@@wHJQL%Vu&p@78|NKZfT#kh<{DPzd;6-Fo#2wlDj7JQ;eYT9;NS&`d z*UlhA`&WOAe2KP3Z+9)=XEbfaD#MLR)~Y6*On;U)!(APD;=!gbn)Yv;B?j!b2WPq~ zNhhks;+)?;JX>QF-@d*Q&Fz=A@l;-?GG;Y?hb#r7XYVQm8NX#%tM>JfMXY?RO1N7+ ztutlUv;zOKQd%k^92J$4xt3P!egjMvMc)cS5+QNb(gRVW7>ZG(YZMSQ3Wyrzlu_-Uu z5yF0iupc4pM+o~7!hVFXA0g}qtzbV4#3_L|B@iv4TVXeeDabHp4Pr*z-W@0sN2p^c zG=`4NX}^}Z2|N)r;{6H6o}5U!vw!%8QP3`yA9J4{}FpHs)F#oB1r><9u zF-LN2Dr+U{#)yWDh*Net`$je#o zTK;^ZJz+P&?dE-XR!#sOcb%c>NrqpChe)j?m8$ z`Z+>BN9gAW{T!hmnS7Tt+avUIgno|D&k_1L;`PH-%lyRcw0t*VsY}5@Py{xKnI8R8 z5TZG3yNoPwPXrr4mYgbnN_Qg`6Dus13o_<3^Kz*6m8o4%l^3ej@mM(G1Mvj`7`X=F zDa{I#pcIT%vJql_ja)284Byi1kl!LPD{eSB1dsC~>3AY<5t`sfH#)P?Xeek3STV{Q zs<@yO(s1EZugC-Yg`vK#YJO(d>$itXnb=@`WdF9gOwP%??^EFe%kg({*A8YsO zN*GBN{u`PyD4~X{DA!V!DX)qoB1@7JSilMuutEi_Pys7cKqLw83lQ@n$%c(D6Er?{Sm4u}PRwmQ&Nj&+*V(&FggLV>`MKj05VvweklXT}G9 z_l06(t0xk5r?@cMK0nsR_#|A4+nIbRnyiLmxlm~dNWr8GAz7yPUozU9;k=JHdZsr{ zYK)Z_$XJAja|5YBoKc6RO@v~xRJ8MTjaoz3M|<>W-X`6q5KZU-9~m{_WHK2pY~4B= z_NTi?bD^Z+&xEq+NXjXt0YXTMX(KPekni!fLc$?W5KkD7GE-y4lf=I0BgN%KZ5RkI z6JU{NvpNEZ`Wx+BIFt-){z88`-tLfe6ieqL^-X=cuRW7b zT7hIoRX6>yj#~A?Kk9zT?;|v9-ehXouB5IDt?9|GEa?*3pC{wNWE3DUaog(No!ucP zkj!uW!+Y&0q4IoN+K!DJzQ&IE%bPY|vB-=H;NJWAcZD80G=dUB*dvFBB$3EaYnfO7 zy#4^IXZi`_KKP$KI|KM7&rb3iB9ieNk;t7l4?ctsmB<~M5rD{3dMHzr&6ER_TPXKZ z&Qczye2Vfk<@YJ#Lx*_$ov=cVqp+bBbtR9|N|&0cmuQ4Gqm2`WCkUHeVZ6MtQ8O%-Jib23Tqk?9>msGud8*Ji+TeTpA5knZ06`rTJv-5ar)BFb8kzH6?& z>h_KGl)v(t#>1!Te-{*idxCe|7p)1oV%+T}QD(|p9l9mQJc*9)0>XFel<)=MIs0SV8*iW%5214x|T!&d>C z-8`l_t>HykCN3xNt&Fq0GL0!6$VIZ9AWm)C^i>k36)1I9XHpsFh|BfcSWcRQeK^g8zZ$SeMWg$x^bq%Amff?l1ESBqcF59lAB;`bsa-Jlu1x$$Kq+wl% z(3<3UOPa%sJE*yAz1-<4rfXxGU;&1r=H!6Z>rEXpa^acV?)+eD&QQ40sK;c2*OGw> z=S*rld;C@@S)FV1+1d^MxIdjTE5(n;DzREVqUSnR_4g$VGdnUENcgLo-b+65mbJ5t zRIp@xLd+M#PoLxz6<4>pnI*pJ>Z0~ythc(R*uTHu3|P!Ew$}=J0KGIsc@)$A@s@@+jwdgsntKnKN&AzP^F4Z@9mc{NF^`M>#^doAMy# z{gh8qewFeSO4HXj@bwK>=Wd}jiG{wI<9(vqXGAmU+Ljz6j$3I2SBJ9ak&>b}mobdRmV74HVh>}nWzohk7JC?rJ&eU3<`E5Jv4^qP!&vNLEcP%K zdl-u?Sy9LtS31otP1EvL=uOa@pogLNLGOdU8@iSMDfD&JU)QX^1Nx38eJ}LAP5MpH zZ}P&!XD~%)FhyrDMQ1QYXD~%)FhyrDMQ1QYXD~%)FhyrDMQ1QY&79EZA-+QqV|OM_ z(3uwBB3gm(&Ugte9*P!#MUJrGF6t!%nL!teAY8XEQ2;Od(v8WbC0y)|=sANw$wnp; zOtxk#%h<721cQmx)w}_}mvpx&<~W_28Da*vt#_oD9n3lz!Y_6tohX8rGl^iF;G91K zUbT$;Y^8TSlM<{9NRx9%Tt~BlB*Fw(84zK_Z3MnWC_wPIAR#Xb?Ae)cN#>D%J~=d1 zENuVidv7h(=lXN3rx+R@NEklm*eiwb;82HCEZU93Ov96-*W0~)d!=01xw^eOmMMfs zcGi8RL0L7>&8h*Xx4UDL^g>FW%)?+ONzD^W=0<)c^4#4~-Z?14d^aa~gZ6gq4`9^| zM0Xz1?_a5bO*hCmziG`@hX2+#BYQUs6VZbhe5-rvS4aKo=usUlt)qT*)US^E)e-JG z>Q_ho>Zo5G^{bppxqO+dxCaP(C!J^ zJwdxCX!k_xDo@bviA%Ejc4YMgt-e!?#98Gfkk~9_5hJnW+N+k4Ah5uRX+Drfb%f4B zXT60*TTt*VwCXDO78HC73cdve--3c~LBY46;9F4eE%dSl1>b^#Z$ZJgpy2f8-sTo% zySKT8wmtQB5yBE`xx|xQ;yEnA>m}533AJ3}K9*3+CDd{WwOm3imr%8Shjh~n#bB$mN@xG?cPrh2`S-+#X`PMS|BjYX!5z24V z3cLnPd6@xtS+ezn)*W-womx0y*ZRkcy<3t2TTdr+J(f4{e6esSgars_q_>%jpM3FE z+4h-O!QT@bYb#GAEOX2tT`g)dLu!UuwZIR7;&+2x7#^U8x*qXqSv}_Bn3$0h!=T-t z7@0{X-tfIMt9Oj$SC5ufmzi-YYq^Y7@9zx;Gv%^>?8a-as`w*TA=}s3u%0yRLQikM z7I-#OHZlXN;$}Kj9L+N7vQq>3f)lHLUQi7S6r{`6`h>w5Yj{qKgSl?RzjoM^b=5vK zb>VH={n&yjaLqw=k9MnT3uGd)l`P^d4O(UezG%EmBYMvF86Zx$sbRC!N{ZT*i1;$} zwW1d`!XWyvwwW`!$Mxr~Z0ERkeNN4wg;KngUswfX7(U6dyttu$jlyOW)Cv6 zrzJCckeNNMZ0@0(mR1R!qkCCg*ALwXEh)L;&pqeIp#CrE=kF;^ZCga!7SXmvZhaAL zTSVIyxxz)XZ4tR#MB5h8wnemU5pCmM&iKdtX?wtge@jZOLp^pPgriV6wbdp-4X zJkIer?+bmm44!akEZ~zNtYGgB{@i&<2Cc0*{_z1*khp{vWy(`TU0jyC(9a#ly5S{> zBzbO+b4Eu5v5x@R$6deZoi9p}%{*NwcdqR=qtV$$wd%%zKzxLT5$$rKt*H4xZ9u?W z!nX5iB-XSRWH9z_raG9jGDAUI;5nyftY}cvLV?G`k2QyB+7r&)4O=54BO@~zydFT` zXKsIdJ22D%Ay2&H{qMVXb&zD6lBqLNB*SGB%jo?6ZwwDlPR0WPA`!lHn_~uxnR?lu z(4DZv!u$K}Sr)f3oiXc&7XM{j`~fkc$Mt`AWp=lEOVfKP9_=tiR#nOx8JR+G@%hTE z^Dz>cMJDH28Yki$gcmk^k(F*j*P-Ru!?CAXHw!&0QymdEFo8&Mg5({^akB&?BoouM zOpTfsFK)&p#E#X+#^GN|;zTZ*cUN#W!^bdFM#F@L?N=m#YwrkaTGZz^i<8BuJALF1 zlkJL={a} zXgBpT0VVVv=sitZfUMNLj-xDM61oLqg+56ALE)gqESPk*g}n{r__*u3S(495eopf9 zVWIDbz8^ZkQ5HT*T?je^eLHl^@Ce;9JX@e!Q=#JKr=Fv5zSJ*3OUzQ}76KRgO6tXC z3Vju{#59H82`%%P((hr$11-}c{oTTQlDHxCQRt)1^G-vbhJH8of=}KK{W$bl=(ElG zcR|0aNxu*Jea&+|1pT2V{SoMoxT90COz8|Nn{|`R30-?4?7CUk(~<(~TCWxgXE{si zQm!!$*hyP4%^?L@a5$D}VsshQ)6_2X{B2Ud;~#2{klGVVVwCt30~v#&H| z4hcb>(WuO^YE~#73MXYYg=G?nS}n0KDl#oe%2p+%=}tvJu}*YShPZ9%bQQxQxtkG9 ztJfI|HyY$|>RQqg2QB9qW|Y;3;b;H^&BQxk|H2M8%TuOayu}uN?Oj2~?@vejR!#M- z@|Vl$bfprQIy#l0YqTl8<~XY6&twZEK*3DXd^X5=0lqpoQWHa~mtnTS!S&ycL z3G|ui(FwDE!0!)X>!Nlj63^rUjqUY;0g~x`S|pafM7HAqbL zlj!4VhQ}Y$A6u!9&Gl24=XYmB{bp9^<65a$yP|?{i7YF17gQY~-Yz;4k*GL|8Hsy3 zBF7*y5=35vjzPzu3(%qqax8N!Qzx#j$3xydAaB|3rw8QS1M=WWp8D&X^*2CEojB{) zb9^JmH}am)EvGE>1Jpl2z1&qxYoz|Y)W28EN8OD`y9lNZf~mW|6Z~JK?4{g9IYD`V z@)+e4lqV@)rntkM=OMmBkpap(Xszy|>37g+4{EOHNZeQtowmY^LYvf^)Ng~9IH07J z3B3h+%iuE%%33Y$;GK8y&V9UdAG9PyJT45duyq+qoiafYc(a#s6XgWu0m@^PPf(tu ze3{a`;>Wq-$6W@Tq17|Z9?n6ZYtoNEKLRc0=27TJoAd{vKPc0xIL8(uZz364hoIRE zzQr$g)L4@stAoopG8}JiF`g1^R;(`v%zRQREYZhx$(AWh+seH zi0Kr=mx#|Ni0B8~^msIuoVa}=lnEtG=3;H8;iG!cP6W!`LC5Ku%j0s5bRw-~Ba){T zjm<=3aon}JRl?d#%;9Xk1rfIXmXSjvtdj9oWSag^Eo1oi;=|fk>sCP}3UC{K9 zLwY5)$se@?0rEhCsla(Hbv{HSHL8V3HrFLUYJ{R0Eh|pkHE9^fXr{H~YXI}%E&5tx z4Gy|k%BNOgKkm|hK(y$3!ov4onqiZ8k?XTlViHoGNw~GS6gdT-e^R?{u$Bc!0jq(s zaIDcB;SKoQsW#!U%(okE5;vS?&69f`BIC}VdV@pvG(K*~Y@0hh&uJ1br8Oqjc-vs| zja8Xmop>1SMkW`?5DJ=!Aj=v3K{MLrlvlN9cz9+o7Aj}f*PU7!wncH=m?Eg5S8A#nR`sm*snP3&*=Xj!&~KlQ@C95Djqx({R3JrMjVaddB^~ zy?(%Jxdn6Xr{%ZG5b`0JccS|RoP=~Q^G;&@C81U55ibO>fN5L6v@KxT7BFqH7I*>E zwt#6{z_cx3+7>Wv3z)VAOxr@sv@KxT7F^S|Kx^}~JWtC)w@{kUo2lPSy~IX6^yM1V zhv@YodVPpqAEMWX==C9beTZHkqSuG$^&xtFh+ZF}*N0lYK18n%xxGF_iz_3nEpH?} zoupUE7Z&=>&~Jv8^WO&jwkG{B^uvPHkmzPgt-Fl^@eeT9WdrLf7V|f_@E`iUnC)Az8LQa1}<@vixBSor(pGNLaueiL9ZF ze&OOJ!%4dW(Gc!`)}2VH7X-NQ;6kNbzj`Q@3OYe6q!XG=1rwc)GuU02-m$l||IDiX zRi%ldpEc57ep&Q*jAj;imj#9Ws*aA=y(PEn>#Pnov6F%(Hlk#(n>05@B% zUFZPZl;awXYvAy9=$5+|daJ0!9x`!7B{J@U#HUn-Hw1Q#aU9_|!Uu((fSzd5tD#pz zUq}58Xh8`=zYbc)OG0~NBrn2o6ZI15xRv9ryf5_a(6@^(cjZhb3VZR}O=+_Y&%Mj? zLh;&OP##=A;f)B~@Ozys1J83`8X~M==uA9Ah8Qd5igro6az*MTHWXsV9Y&;NNdwMf zdMp%4BofR3muK>Q>hy|PghToKY z3ZL(#zruD~Ojd>3LlMm&krR8)qPp0oOunVV*uqC@)83m$FPAh zfN~6=90MrF0Lro}Dr=d&Kza6*YxFF1%N9$!Em0PF_j6uoKJbyFSldpXaX6bJyp&>+{_8dG7i=cYU6_KF?jB=dRDU z?)p4;eV)7aK&>mJDFWFo-pe=^iTYq-RTz3F`K(=f^)fmG*1Boq} zaF<}V3tvzJ55UL*2X}o$Ybr~67lZvJfJQcCfrpq7;)g{H2}Z71t#CZd#BV**)iKhZ zGHqWtVzLcHq1qA8cjO`nGwEKs6_+Ip8oPK!8I6Yai-{%n#^+6eNHL4KVaZ@8QV4jJ z^yd!-Gob_bH%7;k1A{%xm6;){w=cvBpxj9a03I8hSUOv`~07`u;BqVgp z$P2xWbJlUr?a-}3tkAboFZNgHmLMO3K1RJ9@8Nh4?+blWBFZ4?bkqJysK#ipJDdxs z`Oi!zbuxmI7>&1xLDtx~g6M{6(j#*|S3G4P)%={;_2ydf%O?8eBdEXp*&#!3Gflrk z9;qJ4c8=9$jN?X9Dhb_iO1zZti;pO?rl$yCB5neVv&Blm@tIC87qrcQ9mq!;SN5BS zFS+~HI7vJ8rr!)l+HEZmwd4M=D`uuTLrMS0J;R`8C#w}4O#ap@waIN;5@A;0k>Y9;*L}0?9K>iQAz>A>dC~(cWAr z2b;wsms5!n?$wVr6LzbxUmZF0g=*)o3x{81-MO#oWTNp>I)pg*qvd!hpMLRW1LVIb z6$=xU>iq0jBE?R7=HN{;{zM>}@tf%g8yx8-6BFdSI-soJKxlQgYJqO-fdz~@W0FH>rpeR-%G8Q6d?|1JGr z@x$v`KXIe_?Ugc677mv^4)-)O7TIv$_O53|7(UfIOrS;g zW#iFGu(vB3DkneqGC}z3QXxMnf-vq7e<6Yrvsd4_I$Fv^hf0rWy^paYL9SfRMJsHN z6folLg~WPKy)XQrYiUg=9b$DvaNy>(Lv62MGpm#~F{jZ7pJzc^OQ_|2>d}>)UKs&t zBXw0cJA_$~<3>^_%PmBpyQuG?Ug%AnCvZ)& znFZrq550lojm_gN9B%=7cgf-e+XEC0r@02^63;vnAZ%-b3>nRdiKuAJKsp@EdR)T_ zTxR4erk+MwBjYkzI+G-3*||zDB+Au;>yn+-648=?R&4W_X;xV)Be)!kYMDA~5IWO^ zfdspV`uve(bmGbjcexn+agV3z6>R>L@Yf5bYn$VNU?rF6O4Zh6324;P^@)MMogA4O z*Vz~(;tS}ZWT3dJzw`lZ)d%2owy0@^Y`74yB8<{}@wR+CpRX>~^YzZITw=F&#$$a3 zeh(%)u9*pDLy1)MpH_1IhfZI2d(Z~vIOSxz(3k28v1Pu`ji(<0Q;03TLEWc)b)_UU zv(w!0cn8Q)IKRx6i^A{@7$!_ja9s3|{31wxk(L&*AhLu0BBp;4tg;A_Uj)f7g5(!L z@{1t(MUcEqF}vC4iy(QKs3uHJYsUp}oOGk`&#<{!pWE%M3qZi!oM6$dh3vE<@HsEJ zqz|hhTb8+2qYt^1{r3B?8hu!eKCDI`R-+HA(TCOO!)o+lHTtj`eOL{8k%&93chh<| ztqVN>J>VheSrGIr2zr+1Fw51>f}m$X(6b=uSrGIr2znL-Jqv=K1woTeAUF3s#CIri zbF;L#mKN92xGLFgo}|x{^m&p# zPtxZ}`aDUWCtH1m`P7KHu>h1KPr87G~d zd(&+1woWHq8{e=n>vVN?-gZT0B3~`&*$Zc@>uc%0Or{rvU_}Tk`tN&7Hk+AUJDm&$ z%&?j4a(Z_BiR85d$FboIe0?_2#LJl6%_gZ#r9*uyF!_)4y?h^v>+9VZ-4m=l6jXa*OFo+>Lju}2+G=mz=phh#O(F|%dgBs1C zMl+~UGnx7Yh!-g$X;E6+=e4$v)+8}>AFb`9wSDgI5&qvzd64pc$|otmO8E+|;sj4A-Mo`!6j5^0Tt!?)5tq5$WfXB4MO;P^ zmr=xJ6mc0vTt*R>QN(2waT!IF%r-Bn#*5Y$99fAYD{*8cj;zFyl{m5zM^@sDnN9hUhbif0l2+!% zHCB!*uawOxF_jXOxI@<6A0vlPL@R-KG^2a}?JerunT})l-DCLOWBA=;_}ycO^D+GH zG5qc^{O&RQ?lJuCG5qc^{4QA7^YzE@yT@Fcd5nv!gL4HQ38JWTYzd~kx0*T$Q48+% zLL-Py(_USYl}kfi0k$pMSC{3r5_rB;oI3EsUP}z{T5S_VaHr57qW{0q$ zYX@?@PFqgb+26lAUB9wUa-Cs(o3*{?QZ$6r_DS+qymKC}3?)uwq1CtXrl%{~l29SMa~?7(7#?DAZf-^vYS{ZT6r zkEhC^DFXY!N>_JJcfz)!MmbSgQ?*(4QV69J(V!U%MDm%Gm2Eh>X|pVvC{*#n*RT-m zhv(DD>pyP$3Vms|cCeYpUsaF^s&BF5Q8*eeN7tX8i=?B&2Zv+5i9pO}hvNg8<17@6 z4~|a^cK8jazR*7P`pJ+Jp1gI!X(VECM!CLBu@qw4HZ$TYPnAQ=gKWX(AX+}3^*?;p zz`-G#t}T1`-~fyLgbzQ~UZ?+vaFL8gzt!Y}5AAT%6gf&R*&;=f;Uo#pwGGXETe6p8 zp4)^++tlTX%L|hTX?k$zzr9Z1%S73LYRfFqL9s*Ia8qKKwo%b?L_)X5!Uv$QdCuD` z>^e7pGED}h8|@Yabw{}pUuc4xrdN=S8l+aHDG>nyIiv`95;UkWwIqIGn(;9Sm2Bun zJl$P@?|KclS;S@`qi0E~3?zf$2XLP;n zqxV$nfqn~icdPX3ah&y~y0VyZsqgei6Bv!GU9PWxN6Em4erkFbc!BrQ_5ek`Iz+IOYZq7Ug?XiH!izw6!RVjVzSZc9;m+)P z(FHMI@SH87_|F`k8$uJ$c6m!8d4Gi{xUP<>=AXMkxNIiSa(}#^m7N1tIKasXZ8=P~ zk;9gJ0k#hfwx{yh$tW8!M>~?SYB_7!iN<)jKA(%`0-0 zOny_>U~0BMH`H7ETPEB92S|y}c%W@{kry`WK&RSdA9_>&Xnw5NQDGQnME#ZV(M-k} z-jZmKmnVvu(aFhT=bBXoU1y`(PA8BGChbr*g5UwS+Y;qy@3uNy+g!g?AF+&Jw)Ri7 zY%}R@8^77R)Gw<|ExZ4kUQ#=FjyddG4Ggm2?pXBIrhSv7$RWxG%0|j2ie%)t{9PHJ zog`IlgRAUUHz_ZqdJzA#EOE457!wfy!Jlntx_mE-&^2gTeJOM&bf;&3c42?yBfGFa zyRbjIus^%7KfAC$yRbjIus^%7KfAC$yRbjZ^mxd37xu^dc8y)MxRDk&icM+eHR9V^ zf3AUWGuI?#k*Qr5t-3%;ECuNn*;c@b+(`0p+}#YuB`hV&MgG&>448-m&ZN4WY$GXK zj%AYUGgb^&R*&|?+_XZrtc&t}5ea{oL6G^zFdKcd)$n-H&-OH7$G9-4`2~5Ba(Jz& zIW;2sU|ZHN#%lm4UH@&X!stEfpEgf_J3x7d8!!8Tq)*=T@U2{|HfDuLx)F5hnBk08;96Dj%{nfqraiQ z#K`$Jb-(_y*_UQ+^JQq$%x%70F(yux3;DnNBP-rE#4M?T`L z_((=7GM-1h1(^`h%E0iNhpuV_n`#7`Y6P2Vc-|U5sYd8ZR{YioHq{6=)d)7#2sYIS zHq|`wc>&@@iiECYEIsV)SToFyHO=L~eux~Uo3fg61!X_wX39O3hbSMQ{5<6;%I{Ic z?QTO5w;|?&*VaR?hn6APl6SpJT<;RsyTtV_alK1i?-JL$#Pu$5y-Qs064$%L^)7L} zORei&;(EO`gA%1$mLfRfRC8i%2^%esMsB8yH@iIT`Ux#jyowfO<-`)L?}QdFAoSJH zS3@6#KICNzo`PAY(C1U=^C|TC6#9G$eLe;6PNC1I(C1U=^C|TC6#9IsrO&6(=Tk02 zPSM&;w0u*u<-4HoYSM3nmdtWFr!_e*w1+jkRM*zjI*Q+c61xb2Z*-FgG&_dl7m{R= zG`t1N3`;K=glwh_^TDs1S5lK*EZHo8L^_7Qk~uBF;^n)#zbe;RduJv_LPjQ3pH8J5 zqQjx6uT%=;GVD30>zN>f5=li4#scAx753+fq&$U4>|m=GBfuQHXE;bM_EEu5Ce``U zt0E-_h{J?JY*o!-WZEK&k7Qb13xv`1qH~UvWgLoxxmjGn&QrGJ3`qJ31#4jGA?!wb z^)2n~7yi&^g(daM(!Slq0FsT@S^(i@F#A*re^JI?$Ty^Z7*T(y=`jj$VVrV1#q|=s zqN%-}rk>*KNhMISVa0;38CWM@J-7jOiMf`eB!P}|lqEQiaBQVyzK7TH{zrKKBhAlz z6#Ao0`bino$Ve4l^DQ87+Qo(}cOfMMKTpjH`wzPGEW9j;!LEBOm&GubzPF(n&-Elg z#6a+b+dlXdh#^TDWNOH`2q)ns55?HuW5o*@PRT5VfC-9wl9wdk@ZOR}wZDsI!#r`v zFi57eQhB~T$Y2?3*Ot1W$E{df+=`GJ&$n&CJu-Xv9zZ?nV}N83!2md<9e;Lp837BY zqnTL1kgXAe?Ek=*)bK4faXZ0x;lzl&|p+W`%B6Gti&X!F|q@EBaukMAIa)f zHmWZ&$l`k1uXbq8g8tBThD0ohp}S z%E%lc-=I-F2^#%Q7s+>O&h+Tc8e^UB{b+B z%>Olf{UEo7z?$~Z^}}w8Qi_ZA1v2TqnKaq1{Y!&v(kFU@&$@VlINq=6|3=2ZHbx#> zSKt?!<&s4lB9*R0UjCYiX2s={B-v@gOBxxJ@6QC#2zC&eamU4sF2qoHaeb)~p+a<6 z86oJw`*Q(?`vwDJ>b(6zypY#x>>cuM0GRD-YmDEv8b%Z+3dPYvJnv&&X{wPPymqjw z#J7Lw!ANxKp1BBn*wqsl02WUb(t*z2M!0)N%H24G9S;a>5$^&3lqRwa7SP}9L`na? z))UQzcWyrXTQ@MumGL#{AJHT`PT8bm8Vt81C6YA?llfc!_(-}hE1@cOkY+_!8X=O6 zQ_rvr!v-#DhC{-pW%XY(B*T$GcTbTBSmC?afoVpd*QlPAS(?(yBbcOA9txQP3KuwXhiI%p~|g%+Q-3N2OjJqWVX6HJg9y6`?e#ZcaKJ02S*7 z%S#9fut8-1jt)C)M)MJHaw=ifHWZ2QwM~`%g=8v!VHxzq=!~!*kH*k`#mf9*7LzG|AqfovENqg!Jwl;<2%% zRJ2%F%U+~BSj;RU{j_D)clNS=1;+L6uCtts`S0~S$6q4$Gy?u!W=`%i%_k}O$gb30 zPNb7CfwwKv8f@VzY+^e$P!c+2QhJ+*C*|%OOy1r`gqD~nV-QXZsZXn=QzI;VY<)o}2!2%ixZjsB)761W zsuq?nh%j^jayrC{5XRm{&`H$ONG9w9RmWp}W0lC&S|ZN20da=w@fa)qG`=W@6qs;~ z2$bwG5dNQdQq4}V?-$AOrmcOOwbQxTi7qTVOGg4Go4v8gW90eke|?!Rb&4Bi7hAp2 zUo7kkO>e#W(ey<9p!v9yq=S zj_-lvd*JvUIKBst?}6ic;P@Umz6Xvs*Y>{v@gl|L_@iWIih~|tZI%v z=7?3z5v!UbRy9Ygimhz{&2zNq%}KbkA^+_if4ml389&mx2bjrDhQ60;znA+H`c2Ty zU3MM?xjqVVeH7&SD9H6ukn5u$*GECFkAhs~OV%F+xjqVVeH7&SXbZVM3UYnaMXu7~ z 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 literal 0 HcmV?d00001 diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials/KGPrimaryWhimsy SDF.asset b/Assets/TextMesh Pro/Resources/Fonts & Materials/KGPrimaryWhimsy SDF.asset new file mode 100644 index 0000000..20cf2a3 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/KGPrimaryWhimsy SDF.asset @@ -0,0 +1,2816 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!28 &-4571599219975028377 +Texture2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: KGPrimaryWhimsy SDF Atlas + m_ImageContentsHash: + serializedVersion: 2 + Hash: 00000000000000000000000000000000 + m_ForcedFallbackFormat: 4 + m_DownscaleFallback: 0 + m_IsAlphaChannelOptional: 0 + serializedVersion: 2 + m_Width: 512 + m_Height: 512 + m_CompleteImageSize: 262144 + m_MipsStripped: 0 + m_TextureFormat: 1 + m_MipCount: 1 + m_IsReadable: 0 + m_IsPreProcessed: 0 + m_IgnoreMipmapLimit: 0 + m_MipmapLimitGroupName: + m_StreamingMipmaps: 0 + m_StreamingMipmapsPriority: 0 + m_VTOnly: 0 + m_AlphaIsTransparency: 0 + m_ImageCount: 1 + m_TextureDimension: 2 + m_TextureSettings: + serializedVersion: 2 + m_FilterMode: 1 + m_Aniso: 1 + m_MipBias: 0 + m_WrapU: 0 + m_WrapV: 0 + m_WrapW: 0 + m_LightmapFormat: 0 + m_ColorSpace: 0 + m_PlatformBlob: + image data: 262144 + _typelessdata: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090b0f121416130e0c07000000000000000000000000000000000000000000040b0c100f0e0b080100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c1315120b09020000000000000000000000000000000000000000000000000000000000000003090c101417181715110c0a0400000000000000000000000000000000000000000000000000000000000003090b0f0e0b08010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b0d0e0b08010000000000000000000000000000000000000000000000000000000000000000000000000000000000030703000000000000000000000000000000000000000006090400000000000000000000000000000000000000000000000000000000000000000000000000000000050b0d0e0b0902000000000000000000000000000000000000000000000000000000000000070b1216140d0b050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040b0c101417161e2124272a2b2823211a0f030000000000000000000000000000000000000c181f22252523201c140b09020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b0d0f1215161617161412100c0b040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c181f22282a27201d150a00000000000000000000000000000000000000000000000000000000080b161e2125292c2d2c2a26221f180c080100000000000000000000000000000000000000000000000000000a161e212423201c14080300000000000000000000000000000000000000000000000000000000000000000000000000000000000000070d18202223201c140800000000000000000000000000000000000000000000000000000000000000000000000000060c0e181c180e0c0700000000000000000000000000010a10121c1e190c0a040000000000000000000000000000000000000000000000000000000000000000000000070d19202224201d150a00000000000000000000000004070200000000000000000000000008131c20272c29221f180d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000c181f2226292c283236393c3f403e39362d1e160a00000000000000000000000000000003111d2a34373b3a38353026201d150a000000000000000000000000000000000000000000000000000000000000000000000000000000000000040b0c13181f2225272a2b2b2c2b292725221f1815100b0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004121c2a33373e403c3631271a0c0000000000000000000000000000000000000000030300000005101b222832363b3f4142413f3c37332a201d1509000000000000000000000000000000000000000000000005131b28323639393530261e170b00000000000000000000000000000000000000000000000000000000000000000000020406060401010f1a212b343738353026181002000000000000000000000000000000000000000000000000000000000000000000000e1a21232d312e23211a0f010000000000000000000005131d252731332e211f170c0000000000000000000000000000000000000000000000000000000000000000010f1a212b3438393632281a130500000000000000050b0d191d170d0b05000000000000000008182530353c413f37342a1d1002000000000000000000000000000000000000000000000000000000000000000000000000000007151d2a34373b3e4139454b4e525455534e4a3d32281a0a000000000000000000000000000011212f3b474c504f4d4b43363632281a11030000000000000000000000000000000000000000000000000000000000000000000000000001080c181f22282a34373a3d3f404141403f3d3a37342a2b25201d150c0903000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012222f3a474c5355524b45382a1c0c00000000000000000000000000000002080b13181812100e19202e3739464b505456575755514c473a35312719110100000000000000000000000000000000000000000113233039454b4f4e4b433633291b0b0000000000000000000000000000000000000000000000000000000000060b0d13171a1b1b1916111f2d363b484c4e4b43362e20100000000000000000000000000000000000000000000000000000000000000000010f1f2c353843464339362d1f0f00000000000000000007152330393c4649443633291c0c000000000000000000000000000000000000000000000000000000000000000f202d363c484d4e4b45383123130000000000000e1920222f322c221f180d00000000000008182636434a5256544c473b2e201000000000000000000000000000000000000000000000000000000000000000000000000000001525323b474c5053575a57606467696b68635b4b453828160300000000000000000000000008182f3f4b59616564636054524b45382e211306000000000000000000000000000000000000000000000000000000000000000000000109141d202a34373e3b474c4f5255555656565452504c473b403a363127211e160b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1e2f404c5861686a676056473a2a18040000000000000000000000000009151d20282d2d27241e2b353e4b4f576165696c6d6c6a666158524b44372f1d1509000000000000000000000000000000000000000a1e30414d5760646360544b46392917030000000000000000000000000000000000000000000000000000090e192023292d2f30302e2b262d3d4a4e59626360544b3e2e1b08000000000000000000000000000000000000000000000000000000000000000f1f2d3d494e585c584e4a3d2d1d0d0000000000000000152532414d525b5e594c463a2917040000000000000000000000000000000000000000000000000000000000071a2d3e4a4e5a626360564e41311d0d000000000e1e2b353844474237342a1d0e0000000001142636435460676b6962594a3e2e18080000000000000000000000000000000000000000000000000000000000000000000000000c1c32434f596165696c6f7276797c7f807d796e605645321e090000000000000000000000001325364b5d65777a7a78746f6760564b3f31241305000000000000000000000000000000000000000000000000000000000000000009151d2631353b474c5358596264676a6b6b6c6b69676561595955504b44373632281b0d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000005192b3c4c5e66777d7f7c74615947341f0a00000000000000000000000009192731363d43423c39303c484d5c646d767b7e8182817f7c77706760554b3f3127190a0000000000000000000000000000000000001025394d5f67757978746b615746331e0a00000000000000000000000000000000000000000000000005121d242b35383e4244454643413b3b4a5b6370777873645c4b37220a000000000000000000000000000000000000000000000000000000000000071a2d3d4a5b636d716d635b4a3b2b18050000000000000d1d32434f5f6771736e615846331f0e00000000000000000000000000000000000000000000000000000000000d21364a5c647177797568604e3c2b190500000c1c2b3c484d595c574c473b2b1e0e000000081c30435460727c817e77645c4a36251300000000000000000000000000000000000000000000000000000000000000000000000417293a4f6169777b7e8184888b8e919495938c8274604b36210b0000000000000000000000071c304354657b8a908f8d89847d74655d4e42312313020000000000000000000000000000000000000000000000000000000000000f19273137444b525961686d72777a7c7f808081807e7c7a77736f6a656055534b46392a1d0d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000b2035485a667c899395918677614c37220d000000000000000000000009192737444b535858514d404c5a626e7a8289909496979694918b857d74655d4b4437281a0a000000000000000000000000000000000215273852677d8a8e8e888075614b36210c00000000000000000000000000000000000000000000000d182030383c494d5357595b5b5956504b596379858c8d887a644f3828160300000000000000000000000000000000000000000000000000000000000c21364a5b63798286827963594834200b000000000005182b3b4f61697d86888376614c3c2c1906000000000000000000000000000000000000000000000000000000031628384e647a858d8e897e685a4834200b0008182a3a485a626e726c6259483c2b190500000b20354b607383919694897a645443301c07000000000000000000000000000000000000000000000000000000000000000000000a1f334658697f8b9093969a9d9faba7a9aaab9f937e69533e291400000000000000000000000b20354a6073869ca8a4a89e9a92867b68604e413120100000000000000000000000000000000000000000000000000000000008131c2d37444b5560676f777d82878c8f92949596969594928f8c8884807a756e686157483b2a180500000000000000000000000000000000000000000000000000000000000000000000000000000000071a2d3d4d62788a9ea8aaa496816c573b2a180500000000000000000002152737445560686d6d675f4f5e6678838f979ea8a9abacacaaab9f9a92867b6b60554538281909000000000000000000000000000000091d31455671869ca9a79e9584705a45301b05000000000000000000000000000000000000000002101d2b34404c515a62686c6f70706e6b666062778a9aa2a69b85705645321e0900000000000000000000000000000000000000000000000000000000000e24394e637989989b988977624d37220d00000000000b20344859697f919b9e98826d5a4935200c000000000000000000000000000000000000000000000000000000091e32455671869ba3a79e8c78624d38220d001325364758627883878177625a4835200b000010263b50657b90a1aba79b8673604a35200b000000000000000000000000000000000000000000000000000000000000000000000c21364c61768b9faaa8acafb2b5bcc9bec9bcad97826d58422d1800000000000000000000000d23384d62788da4b5c6b9b4afa49c8c7e685f4e3e2e1a0a00000000000000000000000000000000000000000000000000000b1825303e4a556068747c848b93989da5a4a7aaaaabababa9a7a5a69d99958f89837d75625948341f0b000000000000000000000000000000000000000000000000000000000000000000000000000000000821364a5c6d8298a8b9c2b39e88735947341f0b000000000000000000081d31445560747d82827c6960687c8998a0adb4b9c6c1c2c1c9bcb4b0a49c8c80736056453727150200000000000000000000000000000b20364b60758a9fb4b8b09b86705b46311b06000000000000000000000000000000000000000412212e3b484d5e6670787e8284858583807b756c7b90a8b4b59f8b76604b36210b00000000000000000000000000000000000000000000000000000000041a2f44596f8499a7b1a795806b56402b1601000000000d22374d62778b9fb0b39f8c78634d3b2a180400000000000000000000000000000000000000000000000000000b21364b60768ba4b5b8ab907a65503b25100d1c304354617687999c978878624d3a2917040014293e54697e93a9bfb5a38e79634e39240e0000000000000000000000000000000000000000000000000000000000000000000010253b50657a90aabbc8c1c4c1bfbcbcc0cac5b09b85705b3b2a1805000000000000000000000e24394e63798ea7b9c1c1c7c2b6aa9f927d685c4b382816020000000000000000000000000000000000000000000000000c1b2936434a5c64737d87929a9faaadb2b7c3bcbfc0c0c1c0bebcc4b7b2aeaaa89e99938877624c37220d00000000000000000000000000000000000000000000000000000000000000000000000000000008182f3f4e64798c9fb4c6ccb8a78c77624c37220d0000000000000000000b20364b607484929897917e697e8c9ea7b2bec6bab4b0aeafb3b8c5c2b6ab9f958374605544311d1200000000000000000000000000000e24394e63798eaabbc2ad98836d58432e18030000000000000000000000000000000000000212222f3f4b59626f7c858d9397999a9b98969089817d92a7c6bcab8e79634e39240e00000000000000000000000000000000000000000000000000000000091e33485e73889db3c5af99846f5a442f1a05000000000e23384e63788da3b5bcab97816c5947341f0b00000000000000000000000000000000000000000000000000000e23384e63788da3c2c6a38e79634e39240e1d2f3f4a60728399a5b1a699846f5846331f0a0012273d52677c92a7c3c2a8937e6953362614010000000000000000000000000000000000000000000000000000000000000000000f243a4f647a8fa5b7b3b1aeaca9a7a7acb9c9b39e89745947341f0b000000000000000000000b21364b6075899eabacacb2b6c3bbb49f8b7a645645321e0a00000000000000000000000000000000000000000000000c1c29394654606a7a85929ca5afb4bbc8c3bec4b8b3b0b0afafb1b3b5bcc9c1c6b9b4aea696816b56412c160100000000000000000000000000000000000000000000000000000000000000000000000000001325364b5d6f8499abbccfd5c5a5907a65503b251000000000000000000011263b51667b90a2adad9d887c8c9faab9c3b6b2a89f9b999a9ea7adb4bcbcb4a1998373604b40301a0a0000000000000000000000000012273c51677c91a6c8bfaa95806a55402b150000000000000000000000000000000000000010202f404c5d657784919aa2a8acaeb0b0aeaba89e96929bacc0c9a6917c67513c271200000000000000000000000000000000000000000000000000000000081e33485d73889db2c5b09b86705b46311b00000000000c2135495b70859bb0c3b49f8a77614c392816030000000000000000000000000000000000000000000000000010253b50657a90a5bab9a88c76614c3721192b3b4b5d6a7f94a1b3c3b59f8b76614c36210c000d22374d62778ca5b7c3ae99836e5443301c080000000000000202010000000000000000000000000000000000000000000000000b20354b6074879da59e9b99979492929bacc8b9a78c77624c37220d00000000000000000000091e324556697e909696979ca4afbbbbaa9c8674604b382815020000000000000000000000000000000000000000000b1b293a475761727f8c9ba3b2b6c3c6b9b4ada8a3a69d9b9b9a9a9c9e9faba8acb1b5c2c4af9a856f5a45301a0500000000000000000000000000000000000000000000000000000000000000000000000000071c304354657b90a1b3c9d9d3bea8937e69533e291400000000000000000011263c51667b91abbcb7a69d8a9faabbbeb2a59d9289868485888f989fabb7bfb3a197816d5e4c38281502000000000000000000000000152a3f546a7f94a9bfbda7927d68523d28130000000000000000000000000000000000000c1c2d3e4c5e667b889aa2b0b4c0c1c4c3c3c3c6b9b4aba7acb9cabfaa947f6a553f2a1500000000000000000000000000000000000000000000000000000000071c31465c71869bb1c6b29d87725d3827150200000000061a2c3d52677c91a5b7baa995806a5746321e090000000000000000000000000000000000000000000000000013283d52687d92a7bdb49e89745847331f27374859657b8c9fb4bfc0b49f8a76614c36210c000b2034485972879db2c7b39e8974604b35200b00050b0d1215171716130f0b080100000000000000000000000000000000000000081d314455657b878a898684817f7d7d92aabbc5a58f7a65503a251000000000000000000000021628384f60697b81818287949dafbdb6a4947f695645321d090000000000000000000000000000000000000000081829394758617583959faab5c1c0b4b0a89e98938e8b888685858587898b8f92969ca4a7acab98836e59432e1904000000000000000000000000000000000000000000000000000000000000000000000000021527384a6072859bb0bfd0e7d7c1ac97826c57422d170000000000000000000c22374c61778b9fb4c4b7ab9fabbbbeb2a098877d75706e6f747a838c9da6b7bfb19f917c665645321d09000000000000000000000002172c42576c8197acc1c8a58f7a65503a2510000000000000000000000000000000000004182a3a4a5c667c8c9da6b4c0c7bab4b0aeaeb1b5bcc9c1bcc0cad7c2ad98826d58432d1800000000000000000000000000000000000000000000000000000000051a30455a6f859aafc4b49e89745645311d0900000000000f20354b6074879db2c6b39e8975614b37261401000000000000000000000000000000000000000000000000152a40556a7f95aabfb19c87725c3a291d3144556277889eaabbc4b3a2957f6a5746331e0a0005192b3b586d8298adc2b9a78e79644f39240f0d182022272b2c2d2c2924201d1509060000000000000000000000000000000000011527374b5d65727573716f6c6a67758a9fb4bda8937e68533e291300000000000000000000000a1a32424f5e666b6c6c737f949fb0c2b39e8875604b36200c0000000000000000000000000000000000000001142636465761768599a1b4bbc2b5b1a29a9189837e79767371707070717376797d81868c9297998d7b66503b261100000000000000000000000000000000000000000000000000000000000000000000000000091d314556677d92a3b5c9dfe2dac5b09a85705b3b2b180500000000000000000a1f33475871869bb0c6c9bcb4bcc3b2a0988275686056595460646e7b889da5b7bdb29d8774604b36200e0000000000000000000000041a2f44596f8499aec4bbaa8d77624d38220d00000000000000000000000000000000000a1f334758647a8a9eaab7c3b7b2a99f9a99999c9fabb4bbc8d3e1dbc5b09b85705b3a2a180400000000000000000000000000000000000000000000000000000003192e43586e8398adc3b9a88b75604b36200b0000000000081d314455697f94a8b9b8a7937e695544311d08000000000000000000000000000000000000000000000002182d42576d8297acc2af9a846f5a452f30404b6073849aa6b8c8b7a69a8472604b39291703000013283d53687d92a8c4c5a9947f695437261c202b34373c404242413e3a353127211a0e040000000000000000000000000000000009192e3f4b4f5560555c5957545672879db2c1ab96816c56412c17000000000000000000000000142432404c50565754606c8196a6b8b8a7917c67513a2a1804000000000000000000000000000000000000091c3043546175859ba3b3bfbbb4a39b90857c756e696460575b5b5a5a5c566064686c71777d82847d675e4c38230d0500000000000000000000000000000000000000000000000000000000000000000000000417293a4b6074879db2c1cecaced9c8b39e8973594834200b000000000000000004182a3a556b8095aac5d6cfcacab6a598827261574b4538434a4f5d6578879daabbb7a5927d68533c2b190600000000000000000000031628385c71869bb1c6b49f8a75604b35200b00000000000000000000000000000000071a2d3d4c6176889da8b9bfb2a59d928a858383878c969faab6c3d3dec8b39e89735847331f0a00000000000000000000000000000000000000000000000000000002172c42576c8197acc1c6a28c77624d37220d0000000000011527374c6176899eb3c5b29d8774604b3520110000000000000000000000000000000000000000000000051a2f445a6f8499afc2ac97826d57422c3c4d5e6b8096a2b4c4bbaa9d8877615443301b0b0000000e23384e63788da6b8c4ae99846f55443130353b484d5255575756534f4b4437352c1f170c0000000000000000000000000000000010212e3737444b44374442385a6f8499afc4af99846f5a3928160300000000000000000000000614222f383b4136434b6176889eb3c5ae99846e5947341f0a000000000000000000000000000000000009192e3f4b6072839aa3b5c1b9aa9f95867b70676056534e4b453946454538454b4f53575962676d6f675f4d40342b20190e020000000000000000000000000000000000000000000000000000000000000000000a1f334658697e94a5b7c8bbb4bbc8ccb8a78c77624c37220d00000000000000000010253a4f657a8fa7b9cce0d4c3b29c877560544639322830353f4b5a647a8b9fb4c3b09b86715a4835200b00000000000000000000091e32455673899eb3c7b29d87725544311d08000000000000000000000000000000000c21364a5b6c8197a6b7bfb2a199877d75706e6e7178808b9da5b6c3d3ccb8a78c77614c37220c00000000000000000000000000000000000000000000000000000000152b40556a8095aabfb8a38e79634e39240e000000000000091e3346576b8196aabbb7a5927d67523f2f1c08000000000000000000000000000000000000000000000417293a5c71879cb1bfaa95806a554038495a667c919eb0c0bfb49f8c7b655947362614000000000c2135495b73889db3c8b39e8974604b36434a525962676a6c6c6b686460554e493d33291c0f01000000000000000000000000000003101b2226313531262f2c41566c8196abc1b29d88725745321e0900000000000000000000000003111c23262c263346576b8095aac2b49f8b77614c37220c00000000000000000000000000000000021527374b5d6a7f95a1b3c1b9a89e8c7f74655d514b4538393636393b3b393633363a3d3b484c52575a5258554d483b352b1d150a0000000000000000000000000000000000000000000000000000000000000005192b3b4c6176899eb3c3bbaa9faabbcec5a5907b65503b26100000000000000000000b20354b6074899eb3c9decbb7a5917c66564536291e161c202e3c4a5c6b8095aabbb5a38d78624d38230d000000000000000000000b21364b60768ba7b8c4af9a856f5a37261401000000000000000000000000000000021528384e63798c9fb4c3b2a199837568605659595a626b79879ca5b6c7d6c5a48f7a654f3a25100000000000000000000000000000000000000000000000000000000014293e54697e93a9bebaa5907a65503b2510000000000000031729394d62788b9fb4c3b19b86715d4c38230f000000000000000000000000000000000000000000000a1f33465874899eb4bda8927d68533d45566378899eb3bcc3b3a1947f695d4b3a2a180800000000061a2c3d596e8398aec3b9a88e79644f4b54606770777c808182817e79746c635b4c473a2d1f12040000000000000000000000000000000809141d201d141a293e53687e93a8bdb59f8b76604b36210b0000000000000000000000000000090f11161729394e63788da4b6bbaa927c67523d271200000000000000000000000000000000081d314455657b8c9fb4bfb9a89e8a7c6a60554b3f36343738454b4e50504f4c463a3a372e34373d4b5d656e6b62594d483c31271a0e0000000000000000000000000000000000000000000000000000000000000b203448596b8095a7b8c2b49f8a9fb4c5bea9937e69543e2914000000000000000000081d3144556e8398aec3d8c7b29d8774604b3828180b0307111e2d3d4d62778b9fb4c1a7927d68523d2813000000000000000000000e23384d63788da2c5c2ad97826d58422d1800000000000000000000000000000000091d3245566d8297aabbb7a599837261574b45383c494d5b6377879ca9bacdbda7927d68523d28130000000000000000000000000000000000000000000000000000000012273d52677c92a7bcbca6917c67513c2712000000000000000b2035485a6e8398adc0b5a3907b65503e2d1a070000000000000000000000000000000000000000000c21364c61768ba8b9baa5907b6550424b6075859ba8b9c7b7a5998372604a3f2e1c0c00000000000014293e54697e93a9c5c6a9947e69545d65727c858b9195979796938f8881796d61584a3d2f2212020000000000000000000000000000000001080b080110253b50657a90a5c6bcab8e79644e39240f0000000000000000000000000000000000000b2135495b72879cb1c8ab96816c56372715010000000000000000000000000000031729394b6074869cabbcbbaa9e8a7a665e4b4437333b484c535660636565646158564f4b3e36364a5b657b8380786d625a4b45382c1e1103000000000000000000000000000000000000000000000000000000071a2d3d4d62788a9fb4c5b5a4957f95a7b8c1ac97826c57422d170000000000000000000114263753687d92a8c2d2c1ac97826c5544311a0a000000000f2034485970859ab0c1ab96816c56412c170000000000000000000010253a50657a8fa5babfaa95806a55402b15000000000000000000000000000000000b20364b6075899eb3c4b29d87756054463932282b353d4a59647a8b9fb4c8c0ab95806b56402b160000000000000000000000000000000000000000000000000000000011263b50667b90a5bbbda8937e68533e29130000000000000005192b3c4f647a8fa2b4c1af9a846f5c4a36210e0000000000000000000000000000000000000000000e24394e63798ea3c6baa5907b655c4e606d8297a3b5c6baa99d8776615443302110000000000000000f24394e64798ea7b9c4ae99846f606b7b86919a9fabaaacacaba8a79e978c8276635b4c402f21100000000000000000000000000000000000000000000d22374d62778ca8b9c9a7927c67523d2712000000000000000000000000000000000000061a2c3d576c8196acc1b09a85705544311d0800000000000000000000000000000a1e334657697f94a4b5c1b49f8c7b655c4c40313a474c5962696f75797a7a7976726b645c4f4a3e4e63798b98958b82786a6056493c2f22120500000000000000000000000000000000000000000000000000000821364a5b6d8297a9bac0b19c8674889eb3c5b09b85705b3b2b18050000000000000000000d22374d62778ca4b5c9bda8937d6853372614000000000005182b3b566c8196abc1ae99836e59442e190000000000000000000012273d52677c92a7bcbda8927d68533d28130000000000000000000000000000000011263c51667c91a7b9b7a6917c67574536291e1619202d3b4a5c6b8096aabbc3ae99836e59362614010000000000000000000000000000000000000000000000000000000f24394f64798ea4b9bfaa957f6a55402a1500000000000000000e22364a5c70859ab0c3b3a18e79644e3c2b1905000000000000000000000000000000000000000011263b51667b90a6bbc8b39e897a655d687e929fb1c2beb49f8b7a64584736251303000000000000000b20354b6074899eb3c9b49e897373808c9ca4afb4bcc9c1c1c0c5b8b3ab9f978779665e4c3f2e1e0e00000000000000000000000000000000000000000b20354a6074899eb4bfaa95806a55402b150000000000000000000000000000000000000012273d52677c92a7c6b49f8975604b35200b00000000000000000000000000011527374b6176899eb3c2b5a3957f6a5d4c3e30414d58616c777e858a8e90908e8b87817a6f645c4b596e8399a9aa9f978a7f74635a4c403023120400000000000000000000000000000000000000000000000008182e3f4e63798c9fb4c7b3a2907b70859aafc5b39e8974594834200b0000000000000000000b2034485971869cb1c6bca7917c67523c2712000000000000152b40556a8095aabfaf9a846f5a452f1a00000000000000000000152a3f546a7f94a9bfbba5907b66503b261100000000000000000000000000000001162c41566b8196abc5b39d8874604b3928180b03060f1d2d3e4c61778b9fb4c6b19c86715443301c080000000000000000000000000000000000000000000000000000000d23384d62788da2c7c1ab96816c56412c170100000000000000071b2d3e51667c91a5b6bfad98826d5a4835200c000000000000000000000000000000000000000013283e53687d93a8bdccb8a79e8a7b677a8b9fb4bec3b2a0937e695c4a3a2918080000000000000000081c3043546f8499afc4b9a88f7a82959fabb5c2c8c8bbb4b3b5bcc9c9bcb4a59d8a7c665d4b3c2c190900000000000000000000000000000000000000071c30435471869bb1c3ae98836e59362614010000000000000000000000000000000000000e23384d63788da8b9baa98d78634d38230e00000000000000000000000000081d3144556a7f94a7b8bfb09b8573604b3f36434b5f6777818b939a9faaa5a5a4a49c968f847a6a6062778b9fb4bbb4a89f948578665e4d413022110100000000000000000000000000000000000000000000001325364b5d6f8499abbcbcab9a846f6c8196acc1b9a78c77624d37220d00000000000000000005192b3b566b8196abc6bda7927d6852362513000000000003162839566b8196abc0af9a846f5a452f1a00000000000000000002172c42576c8197acc1c6a38e79634e39240e000000000000000000000000000000051a2f445a6f8499afc1ac97826c5544311b0a000000000f1f34475970869bb0c5b49f8a75604b35200b0000000000000000000000000000000000000000000000000000000c21364b61768ba9bac2ad98836d58432e180300000000000000001020354b6073879cb2c5b49f8b78624d3a29170400000000000000000000000000000000000000162b40556b8095aac0d5c5b8a89e8a7c879ca9bac7b6a498826e604f3e2e1c0c00000000000000000001142636546a7f94a9c7c6b29d8798a0b4bcc4b8b3aaaa9f9e9fababb4b9c3b6a89e8b7b655b493726140100000000000000000000000000000000000000132536586e8398adc3b19c86715443301c080000000000000000000000000000000000000b20354a6074899eb4c7a5907a65503b2510000000000000000000000000000b20354b6074889db3c5b3a18f7b655544314354606b7d89969fa9afb4bbc8bac2b6b1aba29a8c7f72687d92aabbcec6bab4a39b8a7c675f4d402f1f0f00000000000000000000000000000000000000000000071c304354657b90a1b3c7b49f8c7964687d93a8bdc5a5907b65503b26100000000000000000000010263b50657b90a8bac0ab96816b5443301c0b00000000081e3245576f849aafc2ad98836d58432e1800000000000000000004192f44596e8499aec3b9a88b76614c36210c000000000000000000000000000000071c31465c71869bb1bea8937e6953372614000000000004182a3b576c8197acc1baa98d78624d38230d0000000000000000000000000000000000000000000000000001010a1e334657748a9fb4c4af9a846f5a452f1a050000000000000000081c304354697e93a7b8bbaa96816c5847331f0a00000000000000000000000000000000000003182d43586d8298adc2d7d5c6b9a89f919ca5b6c7baa99c8676614c42322010000000000000000000000010253a4f657a8fa9bacbb7a59da5b2bebeb2a69e958e8a898b8f969ea8b3bfb9a99e8979635544311d0a00000000000000000000000000000000000000152b40556a8095aabfb49f8a75604b35200b000000000000000000000000000000000000071c30435470869bb0bda7927d68523d28130000000000000000000000000316283851667c91a6b8c3af99846f5d4b37434b607280929ea8b4bac7bfb9b7b7babfc7c0b4aa9f9583758298adc8cec5c1c1b5a89e8b7d675e4c3d2d1b0a0000000000000000000000000000000000000000021527384a6072859bb0bfbaa997826d5c647a8fa4c3bea9947e69543f2914000000000000000000000b20364b6075899fb4c7b29c8773604a39291a0d04030b1829394b6075899eb4c7aa95806a55402b15000000000000000000021528385b71869bb0c6b49e89745846331f0a000000000000000000000000000000071d32475c72879cb1bca7927c67523d2712000000000000162b41566b8096abc0c7a5907b66503b26110000000000000000000000000000000000000000040b0c11151616151729395e73889eb3c6b09b86715b46311c000000000000000000011426364b6175899eb3c7b49e8a76614c382816020000000000000000000000000000000000001325365a70859aafc5d7cdc9c6bab4a6b2b6c3beb49f8b7a6457463324140200000000000000000000000b20364b6075899fb4c9c3b7b2b7c3bcb0a0988880797574757a808a99a1b1bdb8a79b8573604b3827150200000000000000000000000000000000000012283d52677d92a7bcbaa98d78634d38230e00000000000000000000000000000000000000132536586d8298adbfaa957f6a55402a15000000000000000000000000091e3245566e8499aec4b7a5907b66503f4050616d82969eb3b9c3b6b2aaa4a2a1a4aab1b6c2bbb4a19983879db2c8bdb1acb3b8b9a99f8c7c665b4a3928160300000000000000000000000000000000000000091d314556677d91a3b5c4b49f8a78624d61768ba5b7c2ac97826d57422d1800000000000000000000091d3245566f8499aec4b6a5917c665746382a1f17171e28364657687d92a8b9baa9907b66513b2611000000000000000000091d32455673889eb3c7b19c87725c3a291704000000000000000000000000000000071c31475c71869cb1bda8937d685337261401000000000417293a576c8197acc1bea9937e69543e2914000000000000000000000000000000000002090c181f22272a2b2b2a2732475d72879cb2c7b29d88725d38281602000000000000000000081e3246576b8095a9bab9a8947f6a5645321e080000000000000000000000000000000000071c30435472879cb2c7c7bab4bac7c9bcc7cac3b2a0927e685c4a39291706000000000000000000000000091d31455670859aafc5d4cbc7cbbfb09e9682766a63605560646b7783979fb1bfb5a3937e695645311d090000000000000000000000000000000000000f243a4f64798fa4c4c7a6907b66513b261100000000000000000000000000000000000000152a40556a7f95aabfac97816c57422c170902000000000000000000000b21364b60758a9fb4c7b29d8773604a394c5e6a7f94a0b0bcbab4a59c958f8c8c8f959ca4b4babfb3a1999da6b7c7b19f979da6b1baaa9e8a79635745321e0f000000000000000000000000000000000000031729394b6074879db2c1b8a695806b59485772889db2c5b09b85705b3b2b19050000000000000000000215283854697e93a9c3c3b29d87756156483b332a29333946546175879db2c6b49f8a76614c36210c00000000000001080b0c20364b60758a9fb5c4af9a856f5a45301a00000000000000000000000000000000051a2f455a6f849aafc1ac97826c5544311d0c000000000b1f3347586f859aafc4c1ac96816c57412c17000000000000000000000000000000000a151d202a34373c3f40403f3c38465b70869bb0c5b49e89745645321e09000000000000000000031628394c62778b9fb4c6b39d8875604b36261401000000000000000000000000000000000b20354a60758a9fb4c9baa99fa9b5c1d2dccab6a598826d604e3d2d1b0b0000000000000000000000000002152738556a8095aac8d8dfd7c7b3a196806d61584e4b444b4f5962728197a1b3c1b39d8874604b36200b0000000000000000000000000000000000000c21364c61768ba6b8bea9947e69543f29140000000000000000000000000000000000000012283d52677d92a7bcad98836e58432a201d150a07000000000000000011263b51667b90a9bac8ab96806b54434557667c8d9fb5beb8a89f93877f7a77777a7f87939fa9babfb3aeb2b7c4baa9978188979fafb9a89c8675604b3d2d1a0700000000000000000000000000000000000a1e334657697e93a5b6c2b39e8876614b3b596f8499aec4b39e8974594834200b000000000000000000000e23384e63788da5b6cab7a599837462594c473a39464b5761728298a5b7beae98836e5746331e0a000000000009141d202223384d63788dabbcc2ad97826d58422d180300000000000000000000000000000001162c41566b8196abc6b29d8774604b3a2a1b0e06050e1b2b3b4c61768a9fb4c9c4af9a846f5a382816030000000000000000000000000002111a2731363b474c5154565655514d495a6f849aafc4b9a88b76604b36210b000000000000000000000b203448596d8298adc0b8a6937e685443301c08000000000000000000000000000000000c22374c61778ca9bac9b49f899ba3b5c2d2c7b29d8776604b4231231305000000000000000000000000000010263b50657b90aabbcee2cdbaa999836f624c473a3531353b485460728399a8b9b7a6927d67523626140100000000000000000000000000000000000a1e33465773889db3c2ac97826d57422d180000000000000000000000000000000000000010253a4f657a8fa4c9af99846f5a473a363127221b1008000000000001162c41566b8196abc7bbaa8f7a6550364b6075879dabbcb8a69e8a7e746a646262656a747e8b9fa8bac6c3c8cbc9b49f8a737581959eafb6a496816c5b4a36210f0000000000000000000000000000000005182b3b4c6176889eb3c3b6a4937e68574640566b8095abc0b9a88c77624d37220d000000000000000000000c2135495b72879db2c7c3b3a19984776a61585958576168758298a0b2c3b2a08f7a644f3929170300000004111926313537353b50657a90a5c9c0aa95806b55402b160b0801000000000000000000000000000011263c51667b91a8b9b7a5927d675847392b201919202b394859697f94a9bacec7b29d88725645321e090000000000000000000000000a151d2e38454b535961666a6b6b6a67635b596e8398aec3c6a28c77624d37220d0000000000000000000005182b3b4e63798ea2b4c4b19c8773604b352010000000000000000000000000000000000f24394f64798ea4c7bda7927d859ba4b5c2cab49f8c7d675f4e4131231306000000000000000000000000000c21364b61768a9fb4cadfc9b49f8b77624d443329201d202a36435462778a9eb4c4ae99836e5443301c080000000000000000000000000000000000031729395b70859ab0c5b09a85705b3a2a18040000000000000000000000000000000000000d22374d62778cabbcb09b85706158514b4538362e231c110300000005182a3b5a70859aafc5b49f8a76604b4354697e94a6b7baa99e887a6860554f4d4c4f5560697b8a9fb4c0d0dddac5b09a8570606c7f95a0b2b49f8c79634e3d2d1a070000000000000000000000000000000b203448596b8095a7b8c0b19c8674604b393d52677c92a7c8c6a5907b66503b261100000000000000000000061a2c3d576c8197acc8d0bfb3a29a887f77716e6e71767d8798a0b2beb8a698826e5c4b371b0b0000000011222f37444b4c4b4452687d92a7bdbda8937e68533e2922201c1418100e09000000000000000000000b21364b6075899eb4c3b29d87766157483c352b2b343c48576277899eb3c7d8cab59f8b76604b36210b00000000000000000000000a1a27313f4b56606870777c7f80807f7c78726a6c8197acc1b9a38e79644e39240f00000000000000000000000d21364a5b6f849aafc2b6a4917c66513f2e1b0800000000000000000000000000000011273c51667c91a6bbc8a48e7a76869ca4b6c3bbaa9f8c7d685f4e4231241406000000000000000000000000091e32465770869bb0c5d7c2ac97826d5948341f170c080d18263648596c8196abc8b49e8974604b35200b000000000000000000000000000000000000182d42576d8297acc2b39e88735847331f0a0000000000000000000000000000000000000b20354b60758a9fb4b39e897e776e6660564f4a3e372e21110100000b1f34485973899eb3c6b19c867157454a6073879db2c4b49f8b7a645c4b4437373737444b5d687d92a2b4c8dcd6c0ab96816b56616e8298a7b9aa99846f5b4a3621090000000000000000000000000000071a2d3d4d62778a9fb4c5b4a2917c66554431394e63798eaabbbea9947e69543f2914000000000000000000000011263c51667c91aabbced0c0b3a79e948b868383868a929da5b2bebbaa9d8876614c3e2e1b000000000a1a2f404c55606160555b6a7f95aabfbba6917b66513c3a373530262d26231c11030000000000000000091e3245566c8197aabbb7a69a8475625a4d493c3b484d5a6275859ba8b9cce3cfbcab8e79634e39240e0000000000000000000009192738454b5d65747d858c9194959594918d877f778095aabfbaa5907b65503b26100000000000000000000000071a2d3d51667b90a4b6c2b09b85705d4b37220f00000000000000000000000000000014293e54697e93a9bebbaa8c776277869ca5b6c3bbaa9f8d7d68604e4231241406000000000000000000000003162839566b8196abc9d7c6a6907b66513b2b180400000008182b3b4f64798faabbb9a88d78634d38230e000000000000000000000000000000000000142a3f54697f94a9beb8a78c77614c37220c000000000000000000000000000000000000081d31445573889db2b9a79e938b837c756c645c504b3f2e1f0f00000d22374c62778ca7b8c3ae98836e593950657a8fa5b7b8a795806a5c4b3e3127222227313f4e606f849aafc5d6d4c4a6917c67514c6177899eb3b3a18e79634e37271502000000000000000000000000000c21364a5b6d8297a8babcab9a84705e4c3727364b60758a9fb4c2ac97826d5736251300000000000000000000000c21364b61768a9fb4c9dfd0c5b8b3ab9f9b99989b9fa9b2b6c3baaa9f8c7c665847332010000000021528384c5e6674777573706e8297acc2b9a38e796454514f4d4b4336433b382f21110300000000000000031628384d63788b9fb4c1b4a29a84786b625a5a5a59626b78859ba3b5c6d6e2dac9a6917c67513c2712000000000000000000091927374556606b7b87929ba3a6a9ababaaa6a49c9589859bb0c6bca7917c67523c27120000000000000000000000000f20354a6073869cb1c4b4a38f7a654f3d2c1a060000000000000000000000000001162b41566b8096abc0b49f8a75606277879da5b7c4bbab9f8d7e68604e4231241406000000000000000000000011263c51667c91abbccdbaa88b76614b36210d00000000000d20364b60758a9fb4c6a58f7a65503a251000000000000000000000000000000000000011263c51667b91a6c8c5a48f7a654f3a2510000000000000000000000000000000000000011527375b71869bb0c5b9b3aa9f999188817a71655d4b3d2d1a07000f24394e64798ea3c5c0ab95806b5640566b8095abc3b39e8975604b3e2e1d150d0d151d314250657b90a7b8cccbb7a68d77624d47596b8095abbcac97826c5544311d08000000000000000000000000081c2e3f4e63798c9fb4c6b59f8d7a644f402f1d31455671879cb1c5b09b85705443301c07000000000000000000000a1e32465770859aafc5dae3d5ccc9bcb4b1aeadb0b4bac7c1b5a99f8c7d675e4c3a2a1702000000091d324556667c898c8a888583879db2c7b6a18c776b6967646260545b58504c3f2f211100000000000000000a2035495a6b8096a3b5c0b4a29a8a8078736f707277808a9ba3b5c1cac9ced8bfaa947f6a553f2a1500000000000000000114263744556074808d9da5b0b4c1bfc0c0bfc2b6b1a89e9ba3b5c9bea8937e69533e2914000000000000000000000000071c304354687d92a6b8c1ae99836e5b4935210d0000000000000000000000000003192e43586e8398adc3b29d887354596278879da6b7c4bcab9f8d7e68604e4231241402000000000000000000000c21374c61768b9fb5c9b49f89745746331e0a0000000000081d31445573889db2bba6907b66513b26110000000000000000000000000000000000000e23384e63788daabbbda8937d68533e2813000000000000000000000000000000000000001a2f445a6f8499afc1c2c8bbb4aea79e978f867b655b4a36210c0011263b50667b90a5bbbea9947f6954455a6f849aafc1ac97826c5745322010010000011320354b6074899eb3c8c8b39d88735a483b4d62778c9fb5b39e8975604b36200b0000000000000000000000000923374b5d6f8399aabbbaa998826d5c4a3622152738586e8398adc3b49e8974604a35200b0000000000000000000003162939546a7f94a9c4d4dbcdc4c1bdc3c6c3c3c6c3c2b5b1a39b8b7d675f4d402f1c0c000000000b20364b6075889da79f9d9b989da5b6cac3ae9882817e7c79777572706d655d4c3f2e1c080000000000000006192c3c4b6074859ba7b8c0b4a89e958d888585878c959ea8b5c1bbb4b4bac7c2ad97826d58422d180000000000000000081d314455607383969fabb6c3c7c6b9b4b4b4bcc9c6b9b4b0b5c1d2bfaa957f6a55402a15000000000000000000000000001325364b6075889eb3c7b59f8c79634e3b2b1805000000000000000000000000011426375b70859bb0c5b09b86705b485a6378889da6b8c5bcab9f8d7e69604e42311f0b000000000000000000000a1f33475871869cb1c6b49f8a75604b35200b00000000000a1f33475874899eb3c9a5907b66503b26110000000000000000000000000000000000000b20364b60758a9fb4c0ab96816b56412c1600000000000000000000000000000000000002172d42576c8297a3a8adb2b7c3c5b8b3aca39b8b79634e39240e0012273c52677c91a7bcbda8937d6853485d72889db2bca7927c67523928160200000000081c3043546f8499afc4c3ae99836e593c34485970859bb0b8a7907b66503b261100000000000000000000000919304150657b8fa1b3c5b49f8b78624d3e2d1b152a3f556a7f94aabfb9a88d77624d38220d00000000000000000000000f24394e64798ea6b7cbcdbdb0aca8aeb0b2b2b1aea9a49c92857a675f4d4130221200000000000f24394f64798ea6b7b4b2b0adb2b6c3d4c6b2a0989694918f8c8a8885827b655d4b37230e00000000000000000e1d3145566378899ea7b7c3b9b4aaa69d9a9a9ca4aab4b9c5b8aa9f9fa9bac5b09b85705b3a2a1804000000000000061a2c3d4b60738298a1b5bcc3b6b2a8a89e9e9fabaeb5bcc9c6c9d2d6c1ac96816c57412c1702000000000000000000000000081d3245566a7f95a9babcab97826d594834200b000000000000000000000000081d31445572889db2c3ae99836e593c495a6379889ea7b8c5bcab9f8d7e69604e3a26110000000000000000000004172a3a576c8197acc1baa98d78624d36261401000000000c21374c61768b9fb5bcab8e79644f39240f000000000000000000000000000000000000081d31445572879cb2c4ae99846f59382816020000000000000000000000000000000000000e23384e6379858d93989da5b2b6c3c8c1b5a997816c57422d170012273c52677c91a7bcbda8927d68534a5f74899fb4b9a48f7a644f3a250f000000000001142636586d8297adc2c8a9947f6a543f2b3b556b8095aac5ab95806b56402b1600000000000000000000021527374d5f70859bb0bfb8a796806b5a4835201011263c51667c91a6c6c6a5907b66503b261100000000000000000000000d21364a5c73889db3c8c4b09f9693989b9d9d9c99948e867d73645c4d413023120400000000000e24394e63798ea6b7c5bdc0c3c7cad4e1cfbeb2aeaba9a6a4aa9f9d9b988d7b65503a2510000000000000000002152738495a647a899da5b4bcc9c4b7b2afafb2b6c3c9bfb3a79e8a8b9fb4c8b39e89735847331f0a0000000000000c2135495b6a7f94a0b2bfbcb4a59c938d89898a90999fabb7c3d3e0d8c3ad98836e58432e1903000000000000000000000000021528384c61778a9fb4c9b49f8b77624c3929170300000000000000000000000b20354b60758a9fb4c1ac96816c57413c495b6379899ea7b9c6bcab9f937e68533e2813000000000000000000000012273d52677c92a7c3c7a8937e695443301c120600000b1b2e3e51677c91abbcb59f8b76614c36210c00000000000000000000000000000000000002152737596f8499aec4b29d87725645321e090000000000000000000000000000000000000c2135495b6370787e83888e9ca5b6cad2c7af9a856f5a45301a0012273c51677c91a6bcbea8937e69534a5f748a9fb4baa48f7a654f3a2510000000000003162839586d8298adc2bbaa8f7a65503a273c51677c91a6bcb09a85705b3a2a1704000000000000000000081d314455677c91a3b5c3b39e8976614c3c2b19020d23384d62788da8b9bea9947f69543f2a140000000000000000000000071a2d3e586d8297adc9c1ac96817e8386888887837f79716860554a3e302313050000000000000b20354b6073889da6a5a8abafb4c0d1dccfc6c2c0c0bebcc8bbb4b2b0ab99846f59442f1a0400000000000000000a1a2c3c4a5c647987969fabb4bac7c5c4c5c5c9bcb5afa199897b849ab0c5b8a78c77614c37220c0000000000071a2d3e4e63798b9fb4bebcab9f95877e787474767b838d9da5b6c2d3d9c4af9a846f5a452f1a05000000000000000000000000000a1f3447596c8297abbcbaa995806b5746331e0900000000000000000000000d22374d62778caabbbfa9947f6a543f2c3d4a5b647a899ea8b9c6bcae99836e59442e1904000000000000000000000d22374d62778ca5b6c6b19c8673604b3f30201913141b29394a5c6f8499aec9b29c87725846331f0a00000000000000000000000000000000000000162c41566b8196abc0b49f8a76604b36210b000000000000000000000000000000000000061a2c3d494e5a62686d7279879cb2c7ccbead98836d58432e180011263b51667b90a6bbbfaa947f6a55495e73899eb3bca7917c67523929160300000000091e3245576f859aafc4b49f8a76614b36243a4f64798fa4b9b39e89735847331f0a0000000000000000031729394b6074879cb2c1b6a5937e695846331e0e000b20354a6074899eb4c2ad97826d5836251300000000000000000000000012273d52677c92abbcc4af9a846f6e717372716e69645c524b44372d20130500000000000000081c304354667c888d9093969aa2b4c8cfbeb2adaaadafb2b4bac7bbc5b19c87725c47321d070000000000000000000e1e2d3e4a5b6376818c989fa9adb0b1b1b0acab9f999083786c8197acc1c5a48f7a644f3a250f00000000000d21364a5c6f849aa9babcab9f8d807469625a5761666e7a879ca4b6c5d6c6b19b86715c46311c000000000000000000000000000004182a3a4e63798c9fb5c7b39e8976614b37271502000000000000000000000f253a4f647a8fa4c8bca7927d67523d282d3d4a5c647b8a9ea8babbaa95806b55402b1600000000000000000000000b2034485972879db2c7b5a4937e695d4c40352b28292f3a4657647a8fa1b3c1ac96816c573a2917040000000000000000000000000000000000000013293e53687e93a8bdbcab8e79634e39240e000000000000000000000000000000000000000e1f2c353c494d5f6779869ca5b6cabcafa0917c66513c2611000f24394e64798ea3c6c2ac97826d57375b71869bb0c2ac97826d5746321e10020000081528384b6076899fb4c6b19c867157463222384d62778da2b7b8a78c76614c37210c00000000000000000a1e334657697e93a5b6c1b29c8774604b3a29170000071c30435470869bb0c5b09b86705443301c0700000000000000000000000c21374c61778b9fb4c9b49f8a75605b5d5d5c59544e4a3d353126190f010000000000000000011426364c5e6674787b7d80849aafc4c6b2a09895989a9c9fa9a4a6a9a798836e59432e19040000000000000000000010202d3d4957616c7a828a92979b9c9c9a97928c847b6f62687e93a8bdbda7927d68523d281300000000021628384e64798ea2b4c2b59f8d7d6b60554d49464b505c6476869ca7b9ccc7b29d88725d3928160300000000000000000000000000000c2135495b6f8499aec1b9a7947f695544311d080000000000000000000012273c52677c91a7bcbaa5907a65503b251f2d3e4b5c657b8a9fa9aa9f8b78624d38230d000000000000000000000005182b3b586d8298adc2c2b49f8b7b665e4d483c3e3e404c586175869cb1bfb5a38f7a644f3a250f000000000000000000000000000000000000000010253b50657a90a5c6c9a7917c67523c271200000000000000000000000000000000000000000f1f32424f61697d8a9ca4b5c3b9b49e95826d5e4c38240f000c22374c61778ca8b9c5af9a85705544576c8196acc7b39e8876614b3e2d1d1510121826324556677d92a8bac1ac97826c57392922374d62778ca2b7c5a38d78634e38230e0000000000000005182b3b4b6176889eb3c3b4a3917c675544311c0c000000132536576d8297acc2b49e8974604a35200b00000000000000000000000a1f33475870859bb0c5baa9907b6650484847443f39362d201d1409000000000000000000000008182f404c55606265686b7a8fa4bac2ad9882808285878a8c8e9193938979634e39240e000000000000000000000002101f2c39464c5c646d767d8285878785827d786f665e50657a8fa5c5c0ab95806b56402b1600000000091e3245566d8297adc0b5a4957f6a5f4b44373533363e4b586278899eb3c4c9b49f89745745321e090000000000000000000000000000061a2c3d50657b90a3b5c5b29d8774604b36201200000000000000000000142a3f54697f94a9bec6a38d78634e382310202e3e4b5d657c8b97978c7d675a4935200b00000000000000000000000013283d53687d92a8c4cdbaa99e8a7c6d625a555353565e6676849ba4b6bdb09b85715c4b37220d00000000000000000000000000000000000000000d22374d62778ca8b9bfaa957f6a55402a1500000000000000000000000000000000000000071a2d3d4f61697f8d9ea8b5c2b7a89e918072604a402f1d09000a1f33475874899eb3c9b49e8975604b51667b90a9bab8a7947f6a5c4a3e312725272d36434b6074879db2c6c6a8927d68533d2823384d62788da2b7b9a48f79644f3a240f000000000000000b203448596b8095a6b8bfb09b85705f4d3727150000000014293e54697e93a9beb9a88d78624d38230d000000000000000000000004172a3a556a8095aac5c7ab96816b563b2b322e2a24211a0f08010000000000000000000000000012222f37444b4d5053657a8fa5babca7927d6b6d6f727577797c7e7d78635b4a36210c000000000000000000000000010f1b29333e4a4f5861686d707272706d68625a504c4c61778ca7b8c3ae99836e59362614010000000b21364b60758a9fb4c6b19c8674604b413127201e212e3a485a687e93a6b8cbbaa98b76604b36210b0000000000000000000000000000000f23374b5d71869bb1c4b7a6927d6752402f1c09000000000000000001172c41566c8196abc1b9a88b76614b36210c10202e3f4c5d657a828179675f4d3c2b19060000000000000000000000000e23384e63788da6b7cbc7b9a89e8d8278706b68696b727c879ba2b4c2b19f907b65503e2e1b0800000000000000000000000000000000000000000b2034485974899eb4c3ad98836e58362513000000000000000000000000000000000000000c21364a5b697e939fabb9c0b4a59d8a7d6b605443302212000004182a3a5a6f859aafc4b9a88f7a644f4b61768a9fb4c5b49f8b7a645c4b45383b3c3d4a54606c8197a5b6cab9a88e79634e3923243a4f64798fa4b9b9a48f79644f3a240f000000000000061a2c3d4c62778a9fb4c5b2a08f7a644f413019090000000010253b50657b90a5c5c6a6907b66513b26110000000000000000000000000f253a4f647a8fa7b8c6b19c86715948342019140f0d0700000000000000000000000000000000041219263135383b50657a8fa5babca6917c67585a5460616466696862594a3d2d1a0700000000000000000000000000000b171e2d363a474c53585b5c5c5b57524d483c38475973889eb3c6b19c86715443301c0800000010253b50657b90a9bab9a8927c675544311d15090a101c2b3c4b6074889eb3c8c7a28d77624d38220d000000000000000000000000000000081c2f3f52677d92a6b7c4b19c86715e4c382310000000000000000004192e44596e8399aec3b39e89745746321e0a0211212f3f4c5c646c6c635b4d41311e0e000000000000000000000000000c2135495b73889db3c8d6c6b9ab9f978c85807d7e8087919da5b4c0b6a497816c5d4c38201000000000000000000000000000000000000000000005182b3b5c71869bb1c6b19b86715443301c070000000000000000000000000000000000000e23394e63798c9fb4bcbdb0a29a8779675f4a4336251304000000162b40566b8095abc6c6aa95806b5546576c8196a9babaa99d887a696056525051545b637380969fb1c3c9b39e8974604b3520273c51677c91a6bcc9a48e79644f39240f0000000000000c2135495b6c8297a8babbaa98836e5d4b37231200000000000d22374c62778ca6b8bea9947f69543f2a140000000000000000000000000b20354b6074899eb3c8b5a48c77624c37220d0000000000000000000000000000000000000000000009141d20253b50657a90a5babba6917c665136434a4c4f5154534d483b2d1f0f0000000000000000000000000000000003101b222933373d4246474745423d38352b2a3a5b70859ab0c5b49f8975604b35200b000000142a3f54697f94a9c7b49e8974604b372715020000000d1d3144556c8197acc1b9a48e79644f39240f000000000000000000000000000000001120364b6074889db2c6b5a4907b66503e2d1b0700000000000000021528385b71869bb0c6b19c87725c39291603000311212f3e4a4f57574e4a3d3123130000000000000000000000000000061a2c3d596e8398aec3d8d6c9bcb5ab9f9a959393969ca5b2b7c2b6a59c8675604b3f2f1c0200000000000000000000000000000000000000000000192e43586e8398adc3b49f8974604a35200b00000000000000000000000000000000000014293f54697e94aabbbfb09f968476635b4d41302518080000000011263b50667b90a8b9c7b29c87725d4c4d62788b9fb4c0b8a69d8a7f746c6765676a707984969eb0bdcec4af9a846f5443301c2838556b8095aac0bcab8d78624d38230d0000000000081b2e3f4e63798c9fb4c5b49f8b78634d3f2e1b0400000000000b1f34475973889eb3c2ad97826d58362513000000000000000000000000081d3144556e8398aec3c2a7927d6752362614010000000000000000000000000000000000000000000001080f253a4f647a8fa4b9bca7917c67523c303537393c3e3e37342b1d0f01000000000000000000000000000000000000070c171f21282d303232302d282220192d42576d8297acc2baa98d78624d38230d000000172c41576c8196acc1af9a846f5544311909000000000215273753697e93a8bebaa5907b65503b261000000000000000000000000000000000081d3144556a7f94a8b9c2af9a84705c4a36220e00000000000000091d32455673889eb3c4af9a856f5a45301a0000000311202d363a424239362d1f130500000000000000000000000000000014293e53697e93a8c5d6dacfcac9bcb4b0aaa8a8abb2b6c3beb2a49c87786357453221110000000000000000000000000000000000000000000000152b40556a8095aabfbaa98d78624d38230d00000000000000000000000000000000000014293e53697e93a8c8b3a196817361584a3d301c130800000000000b20364b6075899eb4c9b6a5907b655048596b8095a2b4c4b8a89e9488817c7a7c7f858c9aa2b0bccdd5c0aa95806b5536261e3245566f849aafc4b59f8a75604b36200b00000000000922374b5d6e8399aabbb9a796816c5a4935201000000000000005182a3b5a6f859aafc4b09b86715443301c0700000000000000000000000114263753687d92a8c2c2ad98836d5443301c080000000000000000000000000000000000000000000000000e23394e63788ea3b8bca7927d67523d28202224272928222019100e080000000000000000000000000000000000000000040a0c13181b1d1d1b18130d0b14293f54697e94a9bec7a5907b65503b2610000000182d43586d8298adc2ac97826d5737271500000000000012273c52677c91a7bcbca7927c67523d271200000000000000000000000000000000021527374c61768a9eb4c9b4a28f7a644f3c2c19060000000000000b20364b60758a9fb5c2ad98826d58432d180300000002101b22242d2c24211a0f01000000000000000000000000000000000f24394e64798ea7b9ccc9bcb5b3b8c5c5c0bdbec0c5c1b5b0a0988678635a4939281603000000000000000000000000000000000000000000000012273d52677c92a7bcc7a5907b66503b261100000000000000000000000000000000000012273d52677c92a7bcae99846e6055473a2d1f1200000000000000091d3145566e8398adc3c3af99846f5d4b4b6073849aa6b6c2b9b4a69d96929091949a9fabb3c0cddad4c3a6917b66513c2621364b60758a9fb4c7b29d87725645311d0900000000091930404f657a8fa1b3c3b39e8976614c3c2c190200000000000000172c41566c8196abc1b49f8974604a35200b0000000000000000000000000d22374d62778ca4b5c8b39e8874604b35200b0000000000000000000000000000000000000000000000000d22374c62778ca1c5bda8937e68533e29130c0f131e2528302e25231c11030000000000000000000000000000000000000000000003060707060200000011263b51667b90a6c7bea8937e69533e2914000000182d42586d8297adc2ac97826d5738281502000000000013283d52687d92a7bdbea8937e69533e29140000000000000000000000000000000000091f3347586c8196abbcc0ae98836e5a4935200c0000000000000e23384d63788dabbcc0ab95806b56402b16010000000000070d0f17170e0c070000000000000000000000000000000000000b20354b6074899eb3c9bcab9f9ea7adb2b5bcb8b3b0aba39b9083766259493c2c1b0a0000000000000000000000000000000000000000000000000f24394f64798ea4c4bea9937e69543e291400000000000000000000000000000000000011263b50667b90a5c8af9a85705a44372a1c0f01000000000000000215273851667b90a5b6c7b3a18f7b655544556278879ca4b3bfc4b7b3aba7a5a6a9afb4bcc9d0dedfcab6a58c77614c37222b3c51667c91a9bac3ae98836e5938271502000000011527374d5f70859bb0bfb7a5947f695847331e0e000000000000000013283d53687d92a8c9baa88d78624d38230d0000000000000000000000000b2034485971869cb1c6b8a78f79644f3a240f0000000000000000000000000000000000000000000000000b20364b60758ba7b8c0aa95806b55402b16031323303a3d45433a372e2113050000000000000000000000000000000000000000000000000000000000000e23384d63788da9bac1ac96816c57412c17000000162b41566b8096abc0af9a856f5645321d0a000000000114263654697e94a9bebfaa95806a55402b1500000000000000000000000000000000000417293a4d62788c9fb4cab49f8b78634d3a2a1804000000000010253a50657a8fa5c9bea8937e69533e29140000000000000000000202000000000000000000000000000000000000000000081c3043546f8499aec4b59f8d8891989c9faba79e9a958e857b6e6158483b2c1e0e000000000000000000000000000000000000000000000000000c21364b61768ba6b7c1ac97826c57422d170000000000000000000000000000000000000e23384e63788daabbb19c87725c3929190c000000000000000000000b20354a6073879cb2c3bfb19b8573604b48596278869aa1b2b7c3c8c1bcbabcbfc5c4bdc3c6cfdcc7b29d87725947342034485a6e8399aec7c2a9947e69543f291400000000081d314455677c91a3b4c1b29d8774604b3a2a170000000000000000000f253a4f647a8fabbcc6a6907b66513b261100000000000000000000000005182b3b566b8096abc6c5aa957f6a553a2917040000000000000000000000000000000000000000000000091d32455673889eb3c2ac97826d57372715112130414d525a58504b3f3123130000000000000000000000000000000000000000000000000000000000000b20354b60758a9fb4c4af9a846f5a38281602000013293e53687e93a8c4b39e8975604b382715040000000a1c3043546d8298adc2c1ac97816c57422c170200000000000000000000000000000000000c2035495a6e8399aec1bbaa97816c5947341f0a000000000012283d52677d92a7bcbba6917c66513c2711000000000000000000000000000000000000000000000000000000000000000001142636546a7f94a9c5bcab8d787c83878a8b8b8885807970665e4c473a2b1d0e00000000000000000000000000000000000000000000000000000a1e33465773889db3c5af9a85705a3a2a170400000000000000000000000000000000000b20364b60758a9fb4b49e89745746331e0a00000000000000000000071c304354697e93a5b7c9b5a3957f6a5d4b4859627684929da5aeb3b8c5bac6b9b4afa8aeb2bfcfc2ad98836d583a2a2d3d4d62788b9fb4cab6a48d78634e38230e000000031629394b6074869cb1c1b5a3927d675645321c0c0000000000000000000c21364b61768b9fb5bfa9947f6a543f2a150000000000000000000000000010253b50657b90a8b9c5b09a85705846331f0a0000000000000000000000000000000000000000000000021528385b70859ab0c5b09b85705544311d1c2f3f4d5f67706e655d4d41311b0b0000000000000000000000000000000000000000000000000000000000081d31445572879cb1c7b29d87725645321e0900000f24394f64798ea6b8b9a8927d675645311f180d0c0f1b29394b6074879db2c7c3ad98836e58432e1903000000000000000000000000000000000006192c3c4f657a8fa3b4c8b49f8a77614c3928160300000000152a3f556a7f94aabfc8a48f79644f3a240f0000000000000000000000000000000000000000000000000000000000000000000f253a4f647a8fa7b9b3a38e79676e7275767673706b645c504c40332a1c0d000000000000000000000000000000000000000000000000000000031729395a70859aafc5b39e88735847331f0a0000000000000000000000000000000000081d31445572879db2b9a88b76614b36210c00000000000000000000001325364b6075879db2c1c1b49f8c7b655b494858616f7d8791989ea7a4a5a4a89e9a9399a1b2c6c8a9937e69543e28384a5b6c8297aabbc7b19c87725b4935210c0000000a1e324657687e93a4b6bfb09b8572604a382815000000000000000000000a1e32465772879db2c2ad98826d58362614010000000000000000000000000b20364b6075899eb4c9b49f8b76614c36210c000000000000000000000000000000000000000000000000172d42576c8297acc1b49f8975604b352023384c5d677d85837b675f4d392916030000000000000000000000000000000000000000000000000000000001142637596e8499aec3b49f8a76604b36210b00000b20354b6074889db3c6b19c8674604b43342a2322242d394657667c91a5b7cbc4af9a856f5a45301a050000000000000000000000000000000000000e22374b5d70859bb0c3baa995806a5745321e0900000002172d42576c8297acc1bbaa8c77624d37220d0000000000000000000000000000000000000000000000000000000000000000000b20364b6074899eaba29a8573605855606061575b564f4a3e382f1f170c0000000000000000000000000000000000000000000000000000000000172d42576c8297acc1b8a68c76614c37210c0000000000000000000000000000000000021527375a6f8499afc6a38d78634e38230e0000000000000000000000081e324556687d92a3b4c6bbaa9e8979635a4a474c5f68747c83898c8f908f8d89847d8399aeb9b9aa8f7a644f3a32455663798c9fb4c8baa9947f69543d2c1a060000031628394b6175889db3c2b3a18f7b655443301a0a0000000000000000000003162939596e8499aec3b09b86715443301c08000000000000000000000000091d3145566f8499aec4bbaa917c66513c271100000000000000000000000000000000000000000000000014293e54697e93a9c4baa98f7a654f3a2a304150657b909a988d7d675746321e0a0000000000000000000000000000000000000000000000000000000000162c41566b8196abc0bcab8e79634e39240e0000081c3043546c8196aabbb6a495806b614c473a3837393e4a576175879db2c3d4c6b19c86715c47311c00000000000000000000000000000000000000081b2e3f52677c91a5b7c7b39e8875604b372614010000041a2f44596f8499aec4b49f8a75604b35200b000000000000000000000000000000000000000000000000000000000000000000081d314455697e8c908d8477625544444b4b4b46394039362d231c1104000000000000000000000000000000000000000000000000000000000000142a3f54697f94a9bec4a48f7a644f3a250f000000000000000000000000000000000000172c41576c8196acbaa5907a65503b25100000000000000000000000021628384b6073859ba8bac8b8a79d8778645c4d414e5560676e73777a7b7a78746f687d919ea7a89e8b75604b36444b6074859babbcc6b49f8a77614c37220f000000091e3245576a8095a6b8bbaa99836e5d4b362513000000000000000000000000162b40556b8095aac0b49f8975604b35200b0000000000000000000000000215273853697e93a8c3c8ac97826c573d2c1a0600000000000000000000000000000000000000000000000f24394f64798ea6b7c7ac96816c5947383f4d5f70859bafab9e8976614b36210c000000000000000000000000000000000000000000000000000000000013293e53687e93a8bdc9a6917c67513c27120000011426364d62788c9fb4c2b09e947f6e6159514d4c4e525c64758399a5b6caddc8b29d88735d39291603000000000000000000000000000000000000001020354b6074879db2c5b8a7937e695544311d080000031629395c71869cb1c6b29d88735544311d08000000000000000000000000000000000000000000000000000000000000000000021527374f6069787b786f625947373136363632282b24221b1009000000000000000000000000000000000000000000000000000000000000000011263c51667b91a6c8bda8927d68533d281300000000000000000000000000000000000014293e54697e93a9bca7927c67523d27120000000000000000000000000a1c30435463798a9fb4bdc5b7a59d887a675f4c47444b515959626565656260545f697e898f8f8a7f695645434b626c8197a3b5c9b9a896816c5947341f0a0000000b21364b6076899eb4c4b49f8b79634e3f2e180800000000000000000000000012273d52677c92a7c8baa98d78634d38230e000000000000000000000000000e23384d63788da5b6c7b29d87725b4935210c00000000000000000000000000000000000000000000000b20354a6074889db3c8b39e8977614f4e505d677d92a2b4b9a7907b66513b2611000000000000000000000000000000000000000000000000000000000010263b50657b90a5c7bfa9947f6a543f2a15000000082035495a6b8096a5b6bcae9d9482776c66626163686f798599a1b3c3d3dfc9b49f8a745746321e0a00000000000000000000000000000000000000081d314455697e94a7b9c5b29d8774604b35201100000a1e32465774899eb3c5b09b86705b3726140100000000000000000000000000000000000000000000000000000000000000000000091932424f5a6265635b4c473b2a1d2021211e16160f0d07000000000000000000000000000000000000000000000000000000000000000000000e23384e63788daabbc0ab96806b56412b1600000000000000000000000000000000000011263c51667b91a6bba9947f69543f2a1400000000000000000000000001142636495b687e939fb1c0c3b7a69d8a7d6e61594b45383b484c4f504f4d4a434f61697579797569614f4754606b80959fb1c2c1b39e8977624c3a2a18040000000c21364c61768a9fb4b9a897816c5b49352111000000000000000000000000000e24394e63798eaabbc7a6917b66513c2611000000000000000000000000000c2035495a72879cb2c7b7a58d78634e38230e0000000000000000000000000000000000000000000000071c3043546d8297adc2b9a898826e6563656d7b8a9eb4c0b4a38f7a644f3a250f00000000000000000000000000000000000000000000000000000000000d22384d62788da9bac2ad97826d58422d1800000006192b3c4b6075879da9babbaea0988a817b7877797d848c9ba3b3bfc8cbd5cdbaa98b76614b36210c00000000000000000000000000000000000000011426374b6176899eb3c8b6a5917c67523f2e1c08000c21364b61768ba7b9c3ae99836e59442e190000000000000000000000000000000000000000000000000000000000000000000000001424323c484d504d493c342a1d0d0b0b0c090300000000000000000000000000000000000000000000000000000000000000000000000000000b20364b60758a9fb4c3ae99846e5938271502000000000000000000000000000000000010253a4f657a8fa4baab96806b56412b160100000000000000000000000008182c3c4e606c8197a2b4c0c4b7a99f9282776960564c473a373a3b3a383530424f5660646460564f4b59617280959eafbdc6b4a3947e695948341c0c000000000a1f3346586c81969fa99e8a77614c3d2c1a03000000000000000000000000000b20364b60758a9fb4bfa9947f6a543f2a150000000000000000000000000006192c3c576c8197acc7c3a9937e695439281603000000000000000000000000000000000000000000000013253650667b90a4b6c6b2a098837a787b828c9ea8b9beb09b8573604a35200b00000000000000000000000000000000000000000000000000000000000b20354b6075899fb4c5b09b85705b3a2a17040000000e1e324557657b8b9faababeb2a89f97918d8c8e92999faab5c1b8b3b8c5d5c7a28d78624d38230d0000000000000000000000000000000000000000091e3346576b8096aabbc3b09b85715d4b37230e000e23394e63788ea3c5c1ac96816c57412c1702000000000000000000000000000000000000000000000000000000000000000000000006141e2b35383b38352c1f180d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081d31445572879cb2c7b29c87725645311d0900000000000000000000000000000000000e24394e63798ea3b8ac97826c57422d1702000000000000000000000000000e1e31424b6073849aa2b4c0c7bab4a098897e75696158524c473a3e3b39373638454b4f4f4b4d5560687783959eafbcc8b9a89b8573604b3b2a1800000000000417293a4b6073808a8f8c7d675947341f0f0000000000000000000000000000081d31445571869cb1c2ad98836d58362614010000000000000000000000000011263c51667b91a9bac4af99846f5746321e0900000000000000000000000000000000000000000000000b20354a6073869cb1bfbeb2a0988f8d90979faab9c3b2a08f7b655443301c070000000000000000000000000000000000000000000000000000000000081c30435471869cb1c6b39e88735847331f0a000000031628394b5d667c8c9fa9b6c2bab4aca6a2a1a3a7afb4bbbfb3a69ea6b8c9b9a48e79644f39240f0000000000000000000000000000000000000000031729394d62788b9fb4cab5a3907b65503b25100010253b50657a90aabbc2aa947f6a553f2a1500000000000000000000000000000000000000000000000000000000000000000000000000000e192022262321190e0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002152737596f8499aec4b49f8a75604b36200b00000000000000000000000000000000000d22384d62778da2b7ad98826d58432d18030000000000000000000000000000141d3144556175849aa2b1bdcdbeb2a79e93877f776e6761585853514e4c4b4c4c4f52565a626a747e8999a1b0bcc9bbaa9e8978625544311d0d0000000000000c1d314455606b777a78675f4d3b2a1801000000000000000000000000000002152737586d8398adc2b19b86715443301c08000000000000000000000000000c21364b61768a9fb4c9b49f8a76614b36210c0000000000000000000000000000000000000000000000071c304354677c91a1b3c2bfb2aea4a3a5acb4bbc4b7a598836e5d4b36251300000000000000000000000000000000000000000000000000000000000001142636586e8398adc7b8a78c76614c37210c000000000a1b2e3f4c5e677d8b9ca4b3b8c4c1bbb7b6b8bdc4c3b6b2a199889eabbcc6a5907b66503b26110000000000000000000000000000000000000000000b2034485a6e8398adbfc0ab96816c56412c17000c21374c61768b9fabaaa4927d68523d2813000000000000000000000000000000000000000000000000000000000000000000000000000000050b0d100e0c06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000162c41566b8196abc0bbaa8e79634e39230e00000000000000000000000000000000000d22384d62778da2b7ad98826d58432d18030000000000000000000000000000011527374657617584979fb4bac7c5b8b3a69d948a837d76726d6966646161616164676b71787f88939ea7b3bfc8bbab9f8c7c665a493727150000000000000001152737444b596165625a4d41301d0c00000000000000000000000000000000152a3f556a7f94aac9b49f8975604b35200b00000000000000000000000000091e3246576f859aafc8baa98f7a654f3a25100000000000000000000000000000000000000000000000001325364d5f6f8399a4b5c2c6c3bab8bac2cac1b5a69d8777614c3f2e180800000000000000000000000000000000000000000000000000000000000000152a3f546a7f94a9b7b49f8a75604b36200b0000000000112130404d5f677986949ea6afb4bac7bac5b8b3ada59d9283778d9fb3b6a8907b65503b261000000000000000000000000000000000000000000005192b3c4f647a8ea1b2b1a2937e69533e2914000a1f334758687e8c9395918676614c37210c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013283e53687d93a8bdc8a6917c67513c271200000000000000000000000000000000000e23384e63788da3b8ac97826d57422d1802000000000000000000000000000000091929394657607481939fa9b5c1ccc4b7b2a99f98928b87827e7b7977767677797c80868d959da6b3b9c5c5b8aa9f8d7e685e4c3c2b19090000000000000000091927313b474c504d493c302313000000000000000000000000000000000011263c51667b91abbcb6a68d77624d38220d000000000000000000000000000316283954697f94aabbb6a58f7a644f3a240f000000000000000000000000000000000000000000000000081830414c6176869ca4b4b9c6c1c2c2c3b6b2a39b887963594734211100000000000000000000000000000000000000000000000000000000000000000d23384d62788b9da6a49a85705645321d09000000000003122230414d5b63757f88939a9fa9a5a5a4a79e9891877d727084979ea49c8a77624c37220d000000000000000000000000000000000000000000000d22364a5c6f83989d9b948473604b35200b000417293a4e6068787e7f7c73615847331f0a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080b0e0e0b080100000000000000000000000000000000000000000000000000000000000000000000000010253a50657a8fa5c6bfaa947f6a553f2a15000000000000000000000000000000000010263b50657b90a5baab95806b56402b1601000000000000000000000000000000000b1b29394556606d7e8b9ba3b3b8c5cbc7bab4aeab9f9c9893908e8c8b8c8c8e92959ca4aab3b7c4ccc0b4a79e8c7e68604e402f1e0e0000000000000000000009151d2a34373a38352c1e130500000000000000000000000000000000000d22374c62778c9fa8a49c8875604b36200b00000000000000000000000000000e23384d63788b9faba69c8773604b35200b00000000000000000000000000000000000000000000000000121f334758627886959ea8aaacadada9a49c938578635b4a3a2a180300000000000000000000000000000000000000000000000000000000000000000b2035495a667c888f8f8679634d38281502000000000000041323303d4a57616a757e848a8d8f908f8c88837c746760617682898b877c66594834200b00000000000000000000000000000000000000000000071b2d3e4c61768288867f74605544311d0800000c1c31424e5a62696a666055473a2a17040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008141c202324201d150900000000000000000000000000000000000000000000000000000000000000000000000d22374d62778ca8b9c2ad98836d583625130000000000000000000000000000000004182a3b54697f94a9bea9937e69543e29140000000000000000000000000000000000000b1b2838454b60687985939ea7b3b9c5c8c9c9bcb5b1ada8a6a3a1a0a1a1a4a7abb1b5c2c8cbc5b8b3a29a897c68604e42312212000000000000000000000000010c181f22252320190e000000000000000000000000000000000000000b1f3447596c818f92908679635645321d0900000000000000000000000000000c2035495a697f8c9392887a645443301c080000000000000000000000000000000000000000000000000004182a3a485a627580899195979897948f877e73625a4a3d2d1c0c00000000000000000000000000000000000000000000000000000000000000000006192b3c4c5e66757a7a74635b49351a0a000000000000000005131f2d39464b5660686f75787a7a7976736d6660554a58616d747572665e4c3b2b18050000000000000000000000000000000000000000000000101f334758616d72716a605645372715010000001424313c494d5455514b44372a1c0c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000311182630353839353127190d000000000000000000000000000000000000000000000000000000000000000000000b2034485974899eb4c6b09b86715443301c07000000000000000000000000000008141f3447596f8499afc3a5907b66503b2611000000000000000000000000000000000000000a1a2731424e5b63737e89949ea7b0b4c0c3c9cac7c2bebbb9b6b6b6b6b9bcc0c6c9c8c4b7b2a79e928478665e4e42312414040000000000000000000000000000040b0c100d0c06000000000000000000000000000000000000000005182a3b52636c7a7d7a73635b4a38281502000000000000000000000000000006192c3c4f6169797d7c76645c4a3626140100000000000000000000000000000000000000000000000000000c1c2b3c4857606a757b808282827e7a72696055493c2d1f0f00000000000000000000000000000000000000000000000000000000000000000000000e1e2f404c566064646055493c2c1900000000000000000000010f1b283238454b53556063656564615858514b443a474c57566056514c402f1d0d00000000000000000000000000000000000000000000000004172a3a474c585d5c554b45382719090000000006141e2c35383e403c353126190c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000305050211212f36434b4e4e4b44372b1d0d00000000000000000000000000000000000000000000000000000000000000000005182b3b5b71869bb0c6b49e8974604a35200b00000000000000000000000003111c2332404c61778b9fb4b6a58c77624d37220d00000000000000000000000000000000000000000a151d313d4a556069767f89929aa2a8aeb4b9c6c1c3c6c8c9caccc9c7c5c1c5b8b3ada69d94887d72625a4c4031231406000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1d3445525d65686560544a3d2d1a0a000000000000000000000000000000000e1e32434f5c64686761584a3e2d1808000000000000000000000000000000000000000000000000000000000d1d2b39454b5660666a6c6d6d69645d534b44372c1e0f0100000000000000000000000000000000000000000000000000000000000000000000000012222f38454b4f4f4b44372c1e0e0000000000000000000000000b161e28323637444b4e50504f4c473a3c36312a333738454b4538382f221200000000000000000000000000000000000000000000000000000c1c2a33374348463f3631271a0a000000000000000e192023292a26201d1409000000000000000000000000000000000000000000000000000000000000000000000000000000000001080b0f14181a1b1a202f3f4b546063636055483b2b18050000000000000000000000000000000000000000000000000000000000030a0c10182e43586d8398adc2b9a88d77624d38220d00000000000000000000000816212e37424f5e6c8196aabbb29c8772594834200b00000000000000000000000000000000000000000002141f2d37444b57616a757d858d93999ea8a7abaeb1b3b4b4b9b4b2b0aca8a79e9890887f75686054483c2f2213050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001727343f4b4f53504b43362d1f0f0000000000000000000000000000000000001424323d4a4e53524c463a2d20100000000000000000000000000000000000000000000000000000000000000d1b283238454b5155575858544f4b3f353126190e000000000000000000000000000000000000000000000000000000000000000000000000000004121a2832363a3a363127190e0000000000000000000000000000030a161e21273135383a3b3a37332a27201d171f212832363228241c12040000000000000000000000000000000000000000000000000000000c171f212e33312a201d150a000000000000000000060c0d1415110b0801000000000000000000000000000000000000000000000000000000000000000000000000000000000508141c2025292d30302f2e3e4b5d657378797462594834200b000000000000000000000000000000000000000000000000000000000b171e21262a2840556a8095aabfc6a5907b65503b261000000000000000000000031626343f4b5060697d8d9fb4c0ab96816c563b2b180500000000000000000000000000000000000000000000010f19263139464b57606770787e84898e9296999b9e9f9fa89e9d9a97938e88837b746961574a43362b1e1204000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000917212e373a3d3b353026180f0100000000000000000000000000000000000006141f2d36393e3d3633291c1002000000000000000000000000000000000000000000000000000000000000000a161e2832363c404243423f3a372e201d140900000000000000000000000000000000000000000000000000000000000000000000000000000000000a161e212525201d1509000000000000000000000000000000000003090b151d2023252524211f17110b08040a0c151d201d150a09000000000000000000000000000000000000000000000000000000000000040a0c181d1c150b0902000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010d181f2630353a3f43454544414a5c657b878d8e8777624d37220f000000000000000000000000000000000000000000000000000004121b2933363b3f394652677c92a7bcbea8937e69533e29140000000000000000000011213445515d65707e8c9fabbcb4a28e7a644f39240f0000000000000000000000000000000000000000000000000009141d293339454b525a62686e75797d81848688898a8a898785827e79746d6660554b46393025180e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003101b22252825201c1408000000000000000000000000000000000000000000010f1a21242827211f170c00000000000000000000000000000000000000000000000000000000000000000000030a161e21262b2d2d2d2925221b1008010000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090b0f0f0b080200000000000000000000000000000000000000000001080b0e10100f0c0a0400000000000002090b0902000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008141c2a3436434b4f54585a5a5a5652647a8b9ca4a597816c573d2c1a060000000000000000000000000000000000000000000000000012222f39464c505458576164798ea4b9c1ac97816c57422c17020000000000000000091c2f4051636c7b85939faabbbcab9a84705c4a36220d0000000000000000000000000000000000000000000000000000010b171e2832363c484d53556063686c6e71737475757472706c69646054504b443732281c130800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080e1013100b0801000000000000000000000000000000000000000000000000070d0f13120c0a040000000000000000000000000000000000000000000000000000000000000000000000000002090b1115171818140f0d08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c0d0b05000000000000000000000000000000000b1826303b474c546064696d6f706f6b676a8095aab6b29d88735b4935210c000000000000000000000000000000000000000000000000091d2f404c576165696e72767a7f94a9bec4af9a856f5a45301a0500000000000000000e23384c5e6c818f9ba3b4bbc0b59f8d7a654f3e2d1b0700000000000000000000000000000000000000000000000000000000030a161e212b353837444b4e5256595c5e5f5460545d5b57534f4b43363531261e160b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090f111a1c1c1b1b191816130f0c0a04000000000000000000000000000000000000000000000000000000000000000001080b1116130b09020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080c171f212220180d08000000000000000000000000000b1b2936434b59626b747a7e82858584817d767e92a8c8b7a68d78634e38230e0000000000000000000000000000000000000000000000000f24384c5e66767b7f83878b8f949daec2c8b29d88735d48331e08000000000000000010263b50657b909fb0b5c1c0b4a297816c5d4b3720100000000000000000000000000000000000000000000000000000000000000003090e192023273135393d414446494a434a434845423e39353026201d1409030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070b0f13161719181614100c0a030000000000000000000000000000000000000000000000000000000000000000050b0d0e0c0a04000000000000000000000000000000000000000000000000000000000000000000070d0f1515110b0801000000000000000000000000000000000000000000000000000000000000000000000004121d24262f313131302e2d2b2825211f17110b090200000000000000000000000000000000000000000000000000000009141d20272b29201d150a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002101b222a333737342b231c1103000000000000000000000b1b2939465460697780888f94989a9a9996928a859bb1c6c4a8937e6953372614010000000000000000000000000000000000000000000004182a3a51667c8a9094989c9faba9aebbcbc9b49f8a745f4a351f0a0000000000000000162b40556b8095aabdc7bab4a29a8474604b3f2e1b0200000000000000000000000000000000000000000000000000000000000000000000060b0d151d2024282c2f31332530353025302d2924201c140b0801000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000708131c2024282b2d2e2d2b2926211e170b0801000000000000000000000000000000000000000000000000000000000d18202224211f170b05000000000000000000000000000000000000000000000000000000000002101b22242a2b26201c14080000000000000000000000000000000000000000000000000000000000000000000513222f383c44464646454442403d3a37332927201d150a070000000000000000000000000000000000000000000000000c192631353c403e3632281a0a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010202e373a474c4d483b382f211100000000000000000009192939465761727f8a959da6a9adafafafaba99f9ba3b5c9c3ae99836e5544311d08000000000000000000000000000000000000000000000a1f33475872879ca9a9adb1b4bcc9cac7c9bcb29d87725d48321d080000000000000000162b40556b8095aabab4a99f958476615645322110000000000000000000000000000000000000000000000000000000000000000000000000000001080b0e1317191c1e131c201c131b17140f0b08010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f1a21253035393e40424342413f3b363329201c14080000000000000000000000000000000000000000000000000008171d2b3437393633291f180d0000000000000000000000000000000000000000000000000000000210202d36393f403b353026180c0000000000000000000000000000000000000000000000000000000000000000132331404c51595c5c5b5a595755524f4c473a3c363228211a0f060000000000000000000000000000000000000000000c1d2a37444b5155534b4538281502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009192e3e4b4f58616259504b3f2f1a0a00000000000000011527374657617584949ea8b3b7c4c2c4c4c4c7bab4b1b5c1d2c9b39e8974604b35200b000000000000000000000000000000000000000000000c22374c61778ca5b6c7c3c2bfc9bcb4b2aeab9f95806a55402b1500000000000000000010253a4f657a8fa0a99f978b807361584738281602000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104070000070b070000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e19212d3636434a4e53565758575654504b463935302618110200000000000000000000000000000000000000000000001727343b484d4e4c463a342a1d0d000000000000000000000000000000000000000000000000000010202e3e4a4f5555514b43362a1c0c0000000000000000000000000000030402000000000000000000000000000a1a31414e5e666f717170706e6d6b6864615857514b4538362d211a0f0200000000000000000000000000000000000004182a3b475560666b68605645321d1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021527374b5c6471767772655d4b38281502000000000000081d3144556175849aa2b4b9c6c3b6b2afafb1b4bcc9c6c9d2e0ccb9a78f7a644f3a240f000000000000000000000000000000000000000000000c21364b61768a9fb4b3b0ada9a6ab9f9d99948c8173604b35200b0000000000000000000e23374b5d6d8291928a82786b6055473a291a0a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000141e2c353d4a4e546064686b6c6e6d6b69656157514b43362f1d150a0000000000000000000000000000000000000000000b1b34455159626361584c483b2a1a0a000000000000000000000000000000000000000000000000081b2e3e4b5c646a6a666054473a2a180400000000000000000000060c0e181917110b08010000000000000000021527384e5f687c84868686858382807d7a76716c6660564e4a3d352c1d150a00000000000000000000000000000000000b1f34475961737c807e74604b3f2e1b08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081d314455647b868c8c877b655645321d090000000000071b2d3e4b6073849ba2b3c0bbb4aba59d9a9a9c9fabb2b6c3cddbd6c5aa947f6a55382816030000000000000000000000000000000000000000000a1e3346576f8499a39e9b9794918e8a87837f786c605544311d08000000000000000000081c2e3f4b60727c7d766d625a4b4437291c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b0d11100b080100000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c11110b090200000000000000000000000008131c323c494d5b636c74797d80828382807e7b766f6660544c3f31271a0b000000000000000000000000000000000000000317293951636c7779766e6259483828150200000000000000000000000000000000000000000000000d22374b5c647a7f807b73615947341f0a0000000000000000000e1920232d2f2c26201c140800000000000000091d314556687d91999b9b9b9a999795928f8c86817c756c635b4e493d31271a0e000000000000000000000000000000011527374c617785919593836e5d4b3722110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b20364b6074899ba3a59c8975604b36200b00000000000d22364a5c6a8095a2b4c0b7aa9f968d878484868b939da5b0bdcbdac4af9a856f5645321e09000000000000000000000000000000000000000000031729394d6278868a8885827f7c7975726e69625a4b443727150100000000000000000000111c30435460666761584d493c3127190c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d181f222625201d150900000000000000000000000000000000000000000000000000000000000000000000030a0c1014171f212627201d150a0000000000000000000008182530424f5b636f7981888e93959798979694908a847c73655d4b4538281b0b0000000000000000000000000000000000000a1e3346576c818c8e8a8377625645321d0900000000000000000000000000000000000000000000000f253a4f647a8d9495908577614c37220c00000000000000000e1e2c35384244413c353026180e0000000000000b20364b6075889eaeb1b1b0afaeacaaa7a4a49c97918981796e635b4b45382b1e100200000000000000000000000000081d31445570859aa3aaa18f7a644f3f2e1c0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e23394e63788ea7b5b6a78d78634e38230e0000000006192c3c4f647a8c9fb4c0b7a69d8c8178726f6f71767e87969faebbcbc9b49f8a75604b36210b000000000000000000000000000000000000000000000b2035485a62717573706d6a6663605659544d493c31271909000000000000000000000001142636434b51524c473a352c1d1509000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006141d2a34373b3a35312719100200000000000000000000000000000000000000000000000000000002090b0f14171e21252a2a33373b3c3631271a0d000000000000000000132536434a606979848e979da6a8abacadacaba9a99f9991867b6c60564639281a0a00000000000000000000000000000000000c21364b61768b9faa9f988674604b36200b0000000000000000000000000000000000000000000000152a40556a7f95abaaa396816c57412c170200000000000008182c3c494d585957514b43362c1e0e000000000010253a4f657a8fa7b8c6c6c5c5c3c2c0bdc2b6b1aca79e978c83796a6056483c2e2010020000000000000000000000000b20354b60758a9fb4bfaf9a846f5d4b372311000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010253b50657a90a5c5c5a28d77624d38220d000000000c2035495a6e8399aabbb8a79d887a6b635b5a5a5861687481939daebdcdbaa9907b65503b26100000000000000000000000000000000000000000000006192b3c484d5560555b5854514e4b45383f38352c1d15090000000000000000000000000008182630353c3d37332a20190e010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001424323b474c504f4b44372e20100000000000000000000000000000000000000000000002080b0f13161e2125292933363a3f3a474c50514b45382a1d0d000000000000010f1c304354606c7e8a99a1acb3b7c4c0c1c0c2c0c7bab4afa49c908174615746382715020000000000000000000000000000000010263b50657b90aabbb4a4907b66503b26110000000000000000000000000000000000000000000003182e43586d8398adc1ac97816c57422c1702000000000000132536495a636d6e6c666054493c2c19060000000013283d53687d92a8c5c6b9b4b0b0b0b2b4bac7c1c5b8b3ab9f988b8074625a4b3f2e2010000000000000000000000000081d3144556e8399aebfb4a28f7a65503f2f1c080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012273d52677c92a7bcb9a88b76604b36210b000000000d23384d62788c9fb4c0b39e8979645c4e493d3a474c56606c7f939fb1c4c7ab96806b563a2a1704000000000000000000000000000000000000000000000e1e2b3537444b4437423f3c393632282a2320190e0100000000000000000000000000000008141c202728211f170c06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1c32424f5962666560554b3e2e18080000000000000000000000000000000001080b0e13151d2024282832363a3e39464b505458586166666056483b2a180500000000000f1f31424a607281939fa9b3bfc6b9b4afadabacafb4bac7c2b5b19f978475615645311d1200000000000000000000000000000001142636556a7f95aac8b6a58c77624d37220d0000000000000000000000000000000000000000000005182b3b5b71869bb0bea9937e69543e2914000000000000071c30435463788284817b73635b4935210800000000152a3f546a7f94a9bfb9a89e9a9b9b9d9fa9a6acb2b7c4bcb5aa9f958578645d4b3e2d1e0e0000000000000000000000011527374e64798ea1b3c0af9a84705d4b3823110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014293f54697e94a9beb49e89745645321e0900000003162838566b8095abbcb4a2917c675b4a3e352c2a3338454b616c8197a6b8c6b09b86715847331f0a00000000000000000000000000000000000000000000000e192026313531262d2a2723201d15140d0c0600000000000000000000000000000000000001080b11120c0a04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004172a3a4f6169777b7a74645c4b36261401000000000000000000000001080b10141c202328273136393e38454b4f5358576165696e72767b7c74625948341f1000000000071a2d3d4e606c81969fb4babfb2aea89e9a9896979a9fa9b1b6c2bdb1a29a8474604b402f19090000000000000000000000000000081c3043546f849aafc4b29d8772594834200b000000000000000000000000000000000000000000000b2034485974899eb4c6a5907b66503b26110000000000031628384a607285979996918679634d36251300000001162b41566b8096abc0b49e8a85858688898d91969da6afb4c0bbb4a39b887b645c4a3c2c190900000000000000000000000922364a5c6e8399aebfb4a2907b6550402f1c09000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001162c41566b8196abc0b29c87725d38281602000000091e32455670859bb0c9b09a85705f4d3d2d211a171f2832424c6176889eb3c8b49f8b77614c37210c0000000000000000000000000000000000000000000000000609141d201d141815110e0b090200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1f334758697f8b908f877a645443301c080000000000000000000008141c2025263035393d37444b4f5357566064696d71767a7f83878c90918577624c3e2d1b070000000c21364a5b687e939fb0bdb7b2a199908985828182848a929ca4b5bcc0b4a297816c5e4c37271501000000000000000000000000000b20354b6074899eb3c2ad98826d583b2b1805000000000000000000000000000000000000000000000d22374d62778ca8b9baa88d78624d38220d0000000000091e324556677d92a3aeaca49c87725443301c07000002172c42576c8197acc1af9a847070707274787c8188909aa2b2b7c2b5a69e8a7a645a493727150200000000000000000000071b2d3e4f647a8ea1b3c0b09b85705e4c382312000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003182e43586d8398adc2b09b85705b46301b000000000b21364b60768a9fb4c4a7917c675241301f1006040a151f3346586b8096abc9bcab917c67513c2712000000000000000000000000000000000000000000000000000001080b080100000000000000000000000000000000000000000000000000000000000000000000000000000000080d0f1618150c0a0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c21374c61768b9faaa59d8873604b35200b00000000000000000210182630353a36434b4e5257556064686d71757a7e82878b8f94989da5a5a39a846f5c4a36220d0000081b2e3e4e63798b9fb4bdb6a59d8f837b75706d6b6d6f767d86959fabbbc0b19f907c665544311d08000000000000000000000000000f24394e64798ea8b9c5a8937d68533e2813000000000000000000000000000000000000000000000010253b50657a90a5c6b49f8974604a35200b0000000004182a3b4b6075879db2c1c2b49e8974604a35200b000003182e43586d8398adc2ae99836e5b5b5d5a62666c737b85919da6b4c0b8a89e8978625544311d0e00000000000000000000001022364a5c6f8399aebfb4a2907b6650402f1d0900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000051a30455a6f859aafc3ae99846e59442f19040000000f243a4f64798fa9bab8a68c77614c372212000000000417293a4f647a8fabbcc9ac97816c573c2b1906000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002101b22252c2e2a211f170c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000011263c51667b91a9bab7a68b76614c36210c000000000000000110212e36434b4f56546063686c7075797d82868a8f93989c9faba9adb2b6c1b4a28f79644f3a240f00000d22374b5c70849aa9bab6a49c877a6e656055585657576167747f8d9faabbbdb29d8774604b35200e0000000000000000000000000013293e53687e93a8c6b8a78e79634e39230e000000000000000000000000000000000000000000000013293e53687e93a8bdb19b86715443301c07000000000b1f3447596a7f94a6b7cbb8a695806b5443301c070000041a2f44596f8499aec2ad97826d58463c484d51546066707c889aa2b3c0b8a79b8574604b3c2b190500000000000000000000071b2d3e4f647a8ea1b3c0b09b85705e4c38241200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021528385c71879cb1c1ac97826c57422d170200000011263c51667b91a6c7b39e88735947341f0a00000000000b21364b60768a9fb4c7b29c87725a4835200b0000000000000000000000000000000000000000000000000000070d0f181c1d1c1915100c0a04000000000000000000000000000000000000000000000000000000000614202e373a41433f3633291c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000003162838566b8096abc7b39e88735746331e0a000000000000000f1f2e3f4b5460656b7074797d81868a8e93979b9faaa8adb1b4bcc9c3c6c2c8bba7927d68523d281300000f253a4f647a8fa2b4b9a79c8677645d504b44374139464b55606a7c8c9fb4bfb6a5927d67523c2b1905000000000000000000000005182a3b586d8298adc2b39e8974604a35200b0000000000000000000000000000000000000000000001172c41566c8196abc1ad98836d5836251300000000061a2c3d4c6177899eb4c4c2b39e8876614c362513000000051b30455a70859aafc1ab96816c56412b353836434a515e6677849aa2b3c2b5a395806a5a4835200c00000000000000000000001022364a5c6f8499aebfb4a3907b665140301808000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000091d32455674899eb3c0aa95806b55402b160000000012273c52677c91a7bcb29d87725443301c070000000000091e32455774899eb4c9b6a58d78624d38230d00000000000000000000000000000000000000000000000002101b22242d3133312e2a26221f1815110c0a0400000000000000000000000000000000000000000000021424323e4b4f5658554c463a291b0b00000000000000000000000000000000000000000000000000000000000000000000000000000000091e32455670859bb0c3ae99836e5939291703000000000000071a2d3d4b5d65737a8085898e92969b9fa9a8acb1b4bbc8c2c6c2c8bbb4b1ada8aa9f907b65503b26100006192c3c576c8297acc0b39e897863594b3f3531272c283237444b5e687e93a1b3c3b09b85705a4835200b00000000000000000000000b1f34485972879db2c4ae99846f5443301c0700000000000000000000000000000000000000000000021628385a6f8499afbfaa957f6a55402a1500000000082136495b6c8197a8b9c9b5a4937e685746331808000000071c31465c71869bb1bfaa957f6a55402a2023253035404d596174849aa4b6c1b49f8a78624d3a2a180400000000000000000000071b2d3e4f647a8ea1b3c1b09b85715e4c3625130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b20364b60758ba7b9bea9937e69543e29140000000011263c51667b91a6c8b49e8974604a35200b00000000000b20354b60758a9fb4cac3a8927d685336251300000000000000000000000000000000000000000000000513202d363a42464846433f3b37332a2b26211f170c0000000000000000000000000000000000000000000c1f32424f5c646b6d6a615846392916030000000000000000000000000000000000000000000000000000000000000000000000000000000b21364b60768a9fb4c8a9947f69543f2a14000000000000000c21364a5b657b868f969a9ea8a7acb0b4bac7c2c6c2c9bcb4b1ada9aa9f9c98938f8a806b5d4c38230e000c2135495b73889db3b9a8947f6a5a493b2e201d1516161e2731404e606f8499abbcb59f8b78624d38220d00000000000000000000000d22374c62778ca5b6c7a9947f6a543625130000000000000000000000000000000000000000000000091e32455672879db2c9a7917c67523c271200000008182f3f4e63798c9fb4c6bfb19c8673604b39291700000000081d32485d72879db2bea9937e69543e29140d131c20303a47566175869cabbcbaa997826d5947341f0a00000000000000000000001022364a5c6f8499aebfb5a3917c665443301c0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d23384d62788da2c5bca7917c67523c2712000000000f24394f64798eaabbb9a88d78634d38271502000000011527374e64798eabbccfc3ad98836e5443301c07000000000000000000000000000000000000000000011323303e4a4f585b5d5b5854504c473a403c37332a1c11030000000000000000000000000000000000050b0d263b4f60697a81837f76615746321e0a00000000000000000000000000000000000000000000000000000000000000000000000000000010253a50657a8fa9babbaa8f7a654f3a2510000000000000000e24394e63798b9ba3abb0b4b9c6c1c5c3c9bcb5b1ada9ab9f9c98938f8a86827e7a756b62503f2f1c08000e23384d63788da6b8b49e8976614c3c2c1d100801000309151d31424e63798c9fb5bcab937d68533e2813000000000000000000000011273c51667c91a6c3baa98f7a654f3a251000000000000000000000000000000000000000000000000b21364b60768a9fb4bcab8e79634e39240e0000011426364b5d6f8499aabbc8b3a1907b655544311b0b00000000021527385e73889eb3bca7927d67523d2812000007121c2a384657647a8c9fb4c7b49f8a77614c37220c0000000000000000000000071b2d3e4f647a8fa1b3c1b19b8673604a36251300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f253a4f647a8fa4b9baa5907a65503b2510000000000c21364b61768a9fb4c6a9947f695645311d13080106121d314455697f94a9c9d9c8b39e8874604a35200b0000000000000000000000000000000000000000000a1e30414d5c646d7172716e6a6561585955514c473a2f2111000000000000000000000000000000060d182022273e53697e8f9698948775614b36211b100a01000000000000000000000000000000000000000000000000000000000000000000000001142636556a7f94aac7b49f8a75604b36210b00000000000000172c41576c8196a9b5c1c5c9c9bcb5b2ada9ab9f9c98948f8b87827e7a76716d696460575044332111000012283d52677d92a7c0af9a846f5846331e0e000000000000011421364a5b70859bb0c9ad98826d583727150100000000000000000002162838566b8196abc0b49f8a75604b36200b00000000000000000000000000000000000000000000000e24394e63798eabbcb49f8a76604b36210b0000081c304354657b90a1b3c8bbaa99846f5e4c3726140000000000091d314556748a9fb4bba6917b66513c2611000000000c1a29394a5c6d8297abbcbaa9947f69543a2a180400000000000000000000001022364a5c6f8499afbfb5a3917c675443301c080000000000000000000000000000000000000000000000000000000000000000000000000000000000000011273c51667c91a6bbc9a38e79634e39240e00000000091e32465771869bb0c8b29c8774604b4130251c141a21303f4b6074879db2c7ddcbb8a68e79644e39240f0000000000000000000000000000000000000000001025394d5f677a82868886837f7b77736e6a6661584c3f2f1c09000000000000000000000000020e1a212b343738455d72879dabada5907b66513b362d251e130700000000000000000000000000000000000000000000000000000000000000000000081c3043546f8499afc4b09b86705645321e09000000000000001a2f445a6f8499afc7ccbbafaaab9f9c98948f8b87837e7a76716d6965615758534f4b453933261603000012283d52677d92a2acab95806a553a29170000000000000000071a2d3d556a7f95aabfb19c87715544311d08000000000000000000091e32455670859bb0c5b09a85705645321d09000000000000000000000000000000000000000000000012273c51677c91a6c9b29d87725645321e0900031628394b6073869bb1bfc5b49f8c79634e402f190900000000000b20364b60758ba9babaa48f7a654f3a251000000000000b1b2d3e4d63788c9fb5c7b09b85705847331f0a0000000000000000000000071b2e3e4f647a8fa1b3c2b19c8673604a3626140100000000000000000000000000000000000000000000000000000000000000000000000000000000000013293e53687e93a8bdbcab8c77614c37220c0000000003162839556a7f95aabbb6a595806a5f4a433630262c35404d5d6a7f95a5b7cbdfd5c5a9947e695437271502000000000000000000000000000000000000000012273d52677d8f979b9d9b9894908c8884807b76655d4c38230e00000000000000000000000a151d2c353b484c54566074899fb4c3a6917b66564f4a3e3930211a0f0100000000000000000000000000000000000000000000000000000000000000000b20354b6074899eb3c1ab96816c563828160200000000000000182e43586d8398adc2c2af9d94908b87837e7a76726d6965615758544f4b46393e3a3632281b16080000000b21364b6074849297978d79634e39230e00000000000000000011263b51667b90a6bbb49f8a75604b35200b0000000000000000000b21364b60758a9fb4c9ab95806b56382815020000000000000000000000000000000000000000000000152a3f556a7f94aabfaf99846f5a3828160200091e324557687d92a3b5c9b9a797816c5b493621110000000000000c22374c61778ca1c7b8a38e79634e39240e000000000000102035495a6f849aafc4b49f8b77614c37220c0000000000000000000000001022374b5c6f8499afbfb5a4917c675443301c090000000000000000000000000000000000000000000000000000070b0c0d0c0b08020004030100000000152b40556a8095aabfb49f8a75604b35200b00000000000d22384d62788b9fb4c3b49f8d7d6960544b43363d494e5e667b8c9fb4c3d4e0d9c4af99846f5544311d080000000000000000000000000000000000000005182b3b5a6f8499adb0b2b0ada9a5a69d9995918a7c65503b2610000000000000000000000e1a28323d494e59626970757a8fa9babba5907c716c645c524d41362d1f1204000000000000000000000000000000000000000000000000000000000000000f24394e64798ea8b9c3a7917c67523c27120000000000000000152a3f556a7f94aabfbfaa947f7b76726e696561575854504b46393e3a3632282925211e160a0000000000091e32455660747d82817a645b4a36210c0000000000000000000f24394e64798ea3b9bbaa8d78634d38230e00000000000000000010253a4f657a8fa9babcab907b66513b2611000000000000000000000000000000000000000000000003182d43586d8298adc0ab96816b56412c160005182a3b4b6075889db2c1c3b39e8977614c3d2c1a030000000000000e23384d63788da2b8c8a28d77624d38220d00000000000006192c3c53697e93a8c6bcab917b66513c2611000000000000000000000000071b2e3e4f647a8fa1b3c2b19c8673604b37261401000000000000000000000000000000000000000000000908131c20222222201d151b1918161413110f182d42576d8297acc2b39e88735443301c0800000000000b2035485a6d8298a8b9bcab9f8c7f7266605458585b636d7c8b9faabbccc8ccd5c9b49e8975604b36200b000000000000000000000000000000000000000b2034485973889db3c6c7c6c3bfc4b7b2aeaaa89b85715b3625130000000000000000000e1e2b38454b5b636d777e858a8f98a9c7cab49f8c86817a71675f4e4a3d3022130600000000000000000000000000000000000000000000000000000000000014293e53697e93a8c6b7a58c77624d37220d000000000000000010263b50657b90a5c3b9a48e796561585854504c46393f3a3632292925211e16140f0b090300000000000002162838455560676d6c645d4b3d2d1a070000000000000000000e23394e63788ea3b8c8a48e79644f39240f000000000000000000142a3f54697f94a9c7b59f8b76614c37210c000000000000000000000000000000000000000000000005182a3b5b70869bb0bda8937d68533e2813000b1f3447596a7f95a6b7cab6a5947f695947341f0f000000000000000f24394e64798ea3b9bbaa8b76614b36210c000000000000000e23394e63788ea8b9c9aa95806b55402b16000000000000000000000000001022374b5c6f8499afc0b6a4927d675544311d09000000000000000000000000000000000000000004121c24253035373837363127302f2d2b2a282624232f44596f8499aec4b19c87715c36261401000000000005192b3c4d62788a9eb4bcbbaa9f94857b746f6d6e717982919fa9bac5b8b3b8c5cdb9a88f7a65503a2510000000000000000000000000000000000000000d22374c62778ca6b8c8bbb4b4b9c6bec1c3c6b59f8a755443301c07000000000000000d1d2b3c4856606b79828b949a9fa9a9b6c7cfbcab9f9b968f867c70635b4c40312413030000000000000000000000000000000000000000000000000000000006192c3c586e8398adc3b29d8872594834200b00000000000000000c21374c61768ca5b6bea8937e6953463a3f3a3633292925211e1614100c09030000000000000000000000000a1a2837444b5257574f4b3f2e1f0f0000000000000000000010253a50657a8fa5babaa48f7a654f3a2510000000000000000006192c3c596e8399aec3b19c86715847331f0a00000000000000000000000000000000000000000000000b1f34485974899eb3c5a58f7a65503a2510071a2d3d4c62778a9eb4c4c0b29d8774604b3a2a18010000000000000010253a50657a8fa5bab49f8a755746331e0a000000000000000b20354b6074899eb4c3ae99836e59442e1900000000000000000000000000081b2e3e4f647a8fa2b3c2b29c8773604b372715010000000000000000000000000000000000000512222f3836434a4c4d4c4b4437464442413f3d3b3a3836365b71869bb0c4af9a856f5a45301a000000000000000e2034485a687d929eafbdbbb4a29b9089848283868d98a0b4bac3b6a79ea7b4bab4a5937e69533e29140000000000000000000000000000000000000011263b51667b90a6c4bbaa9f9ea8a5a9acb0b3b49e8974604a35200b00000000000009192a3b485a6274808b989faaafb4bac7c7d4d9c9bcb4b1aba39b918479665e4e42312111000000000000000000000000000000000000000000000000000000000c2035495a73889db2c3ad98836e583b2b190500000000000000000a1f33475872879cb2c2ad98826d583a2a2925211e1714100c0a030000000000000000000000000000000000000a192731363d42423a372e20100100000000000000000008182d3d54697e93a9bec6a48f79644f3a240f00000000000000000c2135495b73889eb3c1ac97826c573a29170903000000000000000000000000000000000000000000000d22374c62778ca8b9b8a78c77614c37220c0821364a5b6c8297a8b9c9b4a2917c675645321c0c000000000000000011263c51667b91a6bbb39e89735e3929170300000000000000081c30435470869bb0c5b19c86715c37271502000000000000000000000000001022374b5c6f849aafc0b6a4927d685544311d0a000000000000000000000000000000000001122330404c51546061626160555d5b5958565452514f4d4b465473889db2c3ad98836e58432e190300000000000005192b3c4e5f6a80959fb4bac0b4b0a79e9997989ba3adb2bec2b5a59d89969fa99f988776614c37220c00000000000000000000000000000000000000152a3f556a7f94aabfb49f8b898d9094979a9e9f98826d5443301c070000000000011527374859627885969faab4bbc8c0c7cad3ddd0c7c3bec6c1b5b1a29a8a7c68604e3f2e1c0c0000000000000000000000000000000000000000000000000000000d23384d62788da6b7c7a9937e69543e291400000000000000000004172a3a586e8398adc3b19c87725847331f100c0a0300000000000000000000000000000000000000000000000009151d20272d2c25221b1002000000000000000000061426364a5b70859bb0c5b9a88c77624d37220d00000000000000000e23384d63788da6b8c4a7927d67523d25211e160a07000000000000000000000000000000000000000010253a50657a8fa5c6b39e89735947341f08182f3f4e63798c9fb4c6bcab9a85705f4d38281500000000000000000012273d52677c92a7bcb29c87725d47321d000000000000000001142636596e8398aec3b49e89745544311d0800000000000000000000000000081b2e3e4f647a8fa2b3c3b29d8774604b38271502000000000000000000000000000000000a1d30414d5e666f74777777757472706e6d6b6968666462615760758a9fb4c1ac96816c57412c1702000000000000000d1d314150626c81939fa9b4c1c5b8b3aeadadb1b5c1c9bcb5a49c8777818b8d8a8377625847331f0a0000000000000000000000000000000000000417293a596e8399aec3af9a8472787b7e8285898a8476614c362513000000000000081d3144556277879ba3b4bbc5b8b3abb1b6c2d0bfb3aea9b1b5c2c0b4a89e8d7e685d4b3a2a1704000000000000000000000000000000000000000000000000000012283d52677d92a7c4baa98f79644f3a240f0000000000000000000014293f54697e94a9c9b6a48c76614c37210c0000000000000000000000000000000000000000000000000000000002080b1218170f0d080000000000000000040a0f1a2130435463798ea3b4c9b49e8975604b35200b000000000000000013283d52687d92a7c5b7a68d78624d4336363228211a0f0700000000000000000000000000000000000013283e53687d93a8bdb09b85705b3b2a181426364c5d6f8499aabbc6b59f8d7a644f41301a0a00000000000000000013293e53687e93a8bdb09b86715b46311c060000000000000000172c41576c8196acc1b9a88b75604b36200b00000000000000000000000000001022374b5d6f849aafc0b6a5927d685645311d0a000000000000000000000000000000001024394d5f677c84898c8d8c8b8987858482807f7d7b7978767473778caabbbfaa947f6a553f2a150000000000000000001323334452636c7e8b9ba3afb4bbc8c4c2c3c4c7bab4ab9f978678626c7678766e6259483a2a18040000000000000000000000000000000000000a1f33465872879db2c0ab96816b6266696c7073756f61584733180800000000000417293a4b6073859ba5b5c1bbb4a69e969ca4b6c7b3a199949ba3b2b7c4b9ab9f8c7b655847331f0d0000000000000000000000000000000000000000000000000004172a3a576c8297acc1b49f8975604b36200b0000000000000000000010253a50657a8fabbcc2a5907b66503b2611000000000000000000000000000000000000000000000000000000000000000002020000000000000000030d0b171f212c35434b6073859ab0c1c5ae99846f5544311d08000000000000000417293a576c8297acc1b29d8873636054514b4538362d211a0f0300000000000000000000000000000001162c41566b8196abc0ad97826d58422d2924304354657b90a1b3c8baa898826d5c4a36231200000000000000000000152a3f546a7f94a9bfaf9a846f5a452f1a050000000000000001162b40566b8095abc0c6a18c77614c37220c0000000000000000000000000000081b2e3f4f657a8fa2b4c3b29d8774604b38281502000000000000000000000000000004182a3a51677d909a9ea8a2a1a79e9c9b9997969492908f8d8b8a88869cb1c8bda8937d68533e281300000000000000000005152534455260687a85909a9faaacafb0b0aeaba99f998d8275625a58616360574d483b2b1c0c000000000000000000000000000000000000000c21364c61768ba5b6c8a7927d68525054575b5e5f5a4c473a2a170000000000000a1f3346586a7f94a3b5c3b9aa9f958881869cb1c3ae99837e86919da6b4c1bbaa9e8876614c3b2b18050000000000000000000000000000000000000000000000000a1f33475872879cb1c5b09a85705544311d08000000000000000000000c21364b61768b9fb4bfaa95806a553625130000000000000000000000000000000000000000000000000000000000000000000000000000000000071520282933363d494e616a7f95a2b4c8b9a7937e685337261401000000000000000a1f33465871869cb1c6b29d877e79746d6760564e4a3d362d1e170b000000000000000000000000000002152738596f8499aebea9947f695446423e3a394b6073869bb1bfc4b49f8a78624d3e2d1b0400000000000000000000162b40556b8095aac0ae98836e59432e19040000000000000000152b40556a8095aabfb7a28c77624d37220d0000000000000000000000000000001022374b5d6f849aafc0b7a5937e685645321d0a00000000000000000000000000000a1f34475972879cafb4b9c6c5b9b3b2b0aeadaba9a7a6a4a2a99f9d9ca4b6cabba6917c66513c27110000000000000000000007172734424e5c64707b848b9196999b9b9996918a83796d605748474c4d4b4539342b1d0d000000000000000000000000000000000000000010253a50657a8fa5c3bbaa8e79644e3b3f4245494a4537332a1c0c0000000000000c21364c61768a9eb4c1b9a79e8c807572879cb1c0ab95806b717c879ba3b4c2b8a796816b594834200b0000000000000000000000000000000000000000000000000c21374c61778b9fb5c0ab95806b563727150200000000000000000000091e32465771869cb1c4af99846f5443301c07000000000000000000000000000000000000000000000000000000000000000000000000000000041525333c3a464c515b636f7f959dafc0c4b39e8976614b36210c00000000000000000c21364c61768b9fb5cab6a59d928e88837c756c635b4e4a3d33291b1002000000000000000000000000091d31455672879cb2bba6917b665d5b58544f4a57687d92a3b5c9b7a695806a59483420100000000000000000000002172c41576c8196acc1ac97826d57422d18020000000000000000162b40556b8095aac0b7a28c77624d37220d000000000000000000000000000000081b2e3f4f657a8fa2b4c3b29d8775604b38281602000000000000000000000000000c22374c61778ca4b6c9cdc3c0c1c3c5c5c3c2c0bebdbbb9c7bab4b2b1b6c2d3b9a48f7a644f3a250f0000000000000000000000091724313e4a4e5d656f767c8184868684807c766e645c4b453933373836322820180d00000000000000000000000000000000000000000014293f54697e94a9beb49f8a75604b36292d30343530211f170c0000000000000014293f54697e94a8b9c0b39e897a6b6074899eb3bea9937e695e6676849ba4b6c5b49f8a77624d37220d00000000000000000000000000000000000000000000000011263c51667c91abbcc3a6917c66513c2611000000000000000000000003162839586d8297adc2b39e8974604a35200b0000000000000000000000000000000000000000000000000000000000000000000000000000001222334350555861666e7984959eafbcc8b7a695806b5746321e0a000000000000000011263b50667b90abbccfc3b6b2a8a69e98918981796e635b4c46392d20130500000000000000000000000b20364b60758a9fb4b8a28d797472706d6964606075889db2c2c1b39d8875614b3b2b19020000000000000000000003182d43586d8298adc0ab96806b56412b16010000000000000001162c41566b8196abc0c7a18c77624c37220d000000000000000000000000000000001022374b5d6f849aafc0b7a6937e695645321e0a000000000000000000000000000f243a4f64798fa4c2cdbcb0abacaeb0b2b3b9c5b9babcbec0c1c3c5c7cad3d7c7a28d78634d38230e0000000000000000000000000614202d363f4b505861666c6f70706f6b6661574e4a3d32281f2123211e160a0500000000000000000000000000000000000000000002162838586d8298adc2b19c86715645311d171b1e201a0c0a040000000000000002172d42576c8297acc4b4a2917c665c60768ba8b9bca7927c6752586176869cb1c1baa9937e6954372715010000000000000000000000000000000000000000000003162838566b8096abc9b6a58c77614c37220c00000000000000000000000013293e53687e93a8c7b8a78d78634e38230e00000000000000000000000000000000000000000000000000000000000000000000000000000a1d304050616a72767c838b9aa2afbcc9bbaa9d8775614b392916030000000000000001142637556b8095aac9cfc6c3c4c5b8b3ada89e978c83796c61574a3e30231406000000000000000000000e23394e63788eaabbc9b49f8b898886827e7a736c7f95a6b7c9b5a3927d685746321d0d000000000000000000000004192f44596e8499aebfaa947f6a553f2a15000000000000000003182d43586d8298adc2baa98b76604b36210b00000000000000000000000000000000081b2e3f4f657a8fa2b4c4b29d8875604b3928160300000000000000000000000011273c51667c91a6bbc6b09e9597999b9c9ea7a2a3a5a7a9aaacaeb0b3b9c6cdbaa98b76614c36210c0000000000000000000000000002101b222f383a464c51575a5b5b5956514b4639362d1e160a0c0e0b09030000000000000000000000000000000000000000000000091e32455671869cb1c2ad98826d583827150206090a050000000000000000000000142a3f54697f94a6b5b09a85705e4d62788da2c6baa5907a65504758657b90a3b5c7af9a846f5544311d0800000000000000000000000000000000000000000000091e32455670859bb0c5b29c87725947341f0a0000000000000000000000000f243a4f64798fa9bac5a7927d67523d281200000000000000000000000000000000000000000000000000000000000000000000000000000f24394d5e6a7f878b91999faab4c0cfbcab9f8c7b655746321b0b0000000000000000081d3144556f859aafc4beb2adafb3b8c5c6b9b4ab9f998c8176645c4d413224140500000000000000000011273c51667c91a6c8cdbaa99f9e9d9b97938f88818a9eb4c4c0b19b8573604b392816000000000000000000000000051a30455a6f859aafbda8937e68533e29130000000000000000051a2f455a6f849aafc4b49f8a745745321e0900000000000000000000000000000000001023374b5d6f849aafc0b7a6947e695745321e0b00000000000000000000000013283e53687d93a8bdb9a8958082848587898b8c8e9092939597999b9ea8b9c9b49f89745746331e0a00000000000000000000000000000007111c232933363c4144464644413c363228211a0f0300000000000000000000000000000000000000000000000000000000000b21364b60758a9fb4bea9947e69543f2914000000000000000000000000000000000c21374c6176889ba3a5937d68534f64798fa4b9c9a38e79634e3a4b5d71869bb1c6b49f8a75604b35200b000000000000000000000000000000000000000000000b21364b60768a9fb4c2ad98826d583a2a18040000000000000000000000000b20364b60758a9fb4c1ac97816c57382816030000000000000000000000000000000000000000000000000000000000000000000000000011273c51667c919c9fabaeb4bbc8d0cab59f8d7e685d4b3928160000000000000000000b20354b6075899eb4c9b2a098999ea7acb3b8c5bcb5aa9f96877a675f4f42322313010000000000000000152a3f546a7f94a9bfd7c7bab4b4b2b0ada9a69d969ea8b9c7b3a2907b655443301b0b000000000000000000000000061c31465b71869bb0bca7927c67523d271200000000000000000417293a5c71869bb1c6b29d88735d392816030000000000000000000000000000000000081c2e3f50657a8fa2b4c4b39d8875604b392916030000000000000000000000152a40556a7f95aabfb49e89746c6e7072747577797b7c7e808284858a9eb3c7b29d88725d392917030000000000000000000000000000000000080b171f21272c2f31312f2b27211e160b07000000000000000000000000000000000000000000000000000000000000000f243a4f64798faabbc4a5907b65503b2610000000000000000000000000000000000a1f3347586379858e908775604b51667b91a6bbbcab8c77614c373f556a8095aabfbbaa8d77624d38220d0000000000000000000000000000000000000000000010253a50657a8faabbc6a8937e68533e291300000000000000000000000000091d31455671869bb0c6b09b86715645321e0900000000000000000000000000000000000000000000000000000000000000000000000004192e44596e8399aeb5bcc9caced8d3bda8937e68604e413021110000000000000000000f24394f64798ea8b9c3ad988284888f969ea6b2b7c4bbb4a59d8b7d69604f41301f0f0000000000000003182d42586d8297adc2c7bdbababcbfc1c2c4b7b2abb4b9c6c4af9a846f604e41312111000000000000000000000000081d32475d72879cb2bba5907b66503b261100000000000000000a1f33475873889db2c5b09a85705b45301b000000000000000000000000000000000000001123374b5d70849aafc0b8a6947f695746321e0b0000000000000000000002172c42576c8197acc1b29d87725d595b5d566062646567696b6c6e708499afc4b09b86715b46311c0000000000000000000000000000000000000000040a0c11171a1b1b1a16110c090300000000000000000000000000000000000000000000000000000000000000000013283e53687d93a8c8b7a68c77614c37220c0000000000000000000000000000000004172a3a495b6372797a7560574553687d93a8bdb49f8a75604b353c51677c91a6bcc8a48f7a644f3a250f00000000000000000000000000000000000000000001142637556a7f95aac8b9a88e79634e39240e0000000000000000000000000002152738576c8197acc1b49f8a76604b36210b000000000000000000000000000000000000000000000000000000000000000000000000061c31465b71869bb0c4babdc2c8ccd6c7b29d877b675f4d3f2f1c0c000000000000000014293e53697e93a8c6b6a58c776f747a8188939da6b4bbc3b6a99f8d7e695f4d3d2d190900000000000004182a3a5b70859bb0c5b7aaa4a5a7a9acafb4b9c6c1c9cdd7c9b49f8b7e685f4e3f2e1b0b0000000000000000000000011527375e73889db3b9a48f7a644f3a250f00000000000000000c21374c61768ca6b7c2ad98826d58432d1803000000000000000000000000000000000000081c2e3f50657b8fa2b4c4b39e8875614b3929170300000000000000000004192e44596e8399aec3b09b86715b464638454b4d4e50525455575c71869bb1c4af99846f5a442f1a05000000000000000000000000000000000000000000000002050606040100000000000000000000000000000000000000000000000000000000000000000000000001142637576c8197acc1b39d88735947341f0a00000000000000000000000000000000000c1c2c3d495460646560564539556a7f95aabfb39e88735443303a4f657a8fa4babba6907b66513b2611000000000000000000000000000000000000000000081d3144556f849aafc4b49e8974604b35200b000000000000000000000000000013283d53687d92a8c6bbaa8f7a654f3a251000000000000000000000000000000000000000000000000000000000000000000000000003192e43586e8398a6a3a5a8adb3b8c5cab7a59d8b7d675d4b3a2a170400000000000005182b3b586e8398adc3b29c87725960656c757e88959faab6c3baab9f8d7d675b4a3726140100000000000a1f34475973899eb3c4aa998f909194979a9ea8a9b1b6c2c7cebbaa9f927d685d4b3929170300000000000000000000081d31445574899fb4b8a38e78634e39230e000000000000000010253b50657a90a5c4bfaa947f6a553f2a1500000000000000000000000000000000000000001123374b5d70849aafc0b8a7947f6a5746331e0c000000000000000000061b30465b70859bb0c4af99846f5a443027313637393b3d3e40445573889db3c2ad97826d58422d18030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081d31445570859bb0c4af99846f5a3a2a18040000000000000000000000000000000000000f1f2c36434a4e504b453842576c8197acc1b19c86715c36263b50667b90a5bbbba5907b66503b26110000000000000000000000000000000000000000000b20354b6075899eb3c4af9a846f5443301c0800000000000000000000000000000e24394e63798ea8b9c8a9947e69543f2914000000000000000000000000000000000000000000000000000000000000000000000000000e23394e6379888d8e9093989ea7b3b8c3b7a99f8c7b655847331f0d0000000000000b2034485972889db2c2ad98826d584a4f56606975808c9da5b5c1bcab9f8b79635544311d0900000000000c22374c61778ca7b8b8a68f7b7a7c7f8285898e949ca4afb3bfc8bbb49f8c7b655746331e0d000000000000000000000b20354b60758aa9bac7a18c77624c37220d000000000000000014293f54697e94a9bec2a5907b66503b26110000000000000000000000000000000000000000081c2e3f50657b90a2b4c5b39e8976614c3a2917040000000000000000031729395d72879db2c2ad98826d58432d151d202224262729354b60758a9fb4c0ab96806b56412b160100000000000000000000000000000000000000000000000000040a0c0e0b09030000000000000000000000000000000000000000000000000000000000000000000b20354b6075899fb4c0ab95806b56402b1600000000000000000000000000000000000000010f18253035393b36322844596e8399aec3af9a856f5a452b3c53687d93a8bdc4a48f7a654f3a25100000000000000000000000000000000000000000000f24394e64798ea8b9c9aa95806a553626140100000000000000000000000000000b20354b6075899eb4c3ae98836e593b2b18050000000000000000000000000000000000000000000000000000000000000000000000000c2135495b637378787a7e8389939ea7b4c0baaa9d8876614c3b2a180500000000000d22374d62778ca5b7c6a8937e68533e38454b56606b7b879ba3b5c2baa99c8673604b372614010000000010253a4f657a8fa4c5b39e887365676a6c7075797f868f99a1b2b7c4bbaa9d8776614c3b2a18050000000000000000000c21374c61768ca1c7baa98b76604b36210b00000000000000061a2c3d586d8298adc2b6a48c77614c37220c0000000000000000000000000000000000000000001123374b5d70859aafc0b8a7957f6a5846331f0c00000000000000000a1e33465774899fb4c1ab96816c56412c17090b0d0f101222374c62778cabbcbea9947f69543f2a14000000000000000000000000000000000000000000000000040c181f2224211e160a00000000000000000000000000000000000000000000000000000000000000000e23394e63788ea9bac7a7927c67523d271200000000000000000000000000000000000000000008131c202425211e30465b70859bb0c2ad98836d584336485a6e8398adc3b8a68c77624d37220d00000000000000000000000000000000000000000014293e54697e93a9c6bcab907b66503b2611000000000000000000000000000000081d31445570859ab0c5b29d8872594834200b000000000000000000000000000000000000000000000000000000000000000000000000061a2c3d495460636365686d757e899aa2b4c2b8a697816c5948341f0b000000000012273c52677c91a7c3b9a88e79644e39283238454b5d6576859ba4b6c6b5a4937e685544311d080000000013283d53687d92a8bdaf9a85705a52545755606469717a84919da6b6c3b7a595806b5948341f0b0000000000000000000d23384d62788da2b7b49f8a745645321e09000000000000000c2135495b72879cb2c6b19c86715847331f0a000000000000000000000000000000000000000000081c2e3f50657b90a2b4c5b39e8976614c3a2a1704000000000000000c21364b61768ba8babfaa947f6a553f2a1500000000000f24394e64798ea3c9bca7927d67523d281200000000000000000000000000000000070b0d0b0903000c181f2a3437393632281b140600000000000000000000000000000000000000000000000000000000000012273d52677c92a7c7baa98e78634e39230e0000000000000000000000000000000000000000000000070b0f100b1628395d72879cb2c1ab96816c5638455462788b9fb4c8b39e8873594834200b000000000000000000000000000000000000000006192c3c596e8398aec3b59f8b76614c36210c00000000000000000000000000000001142637566b8196abc0b7a58c77624c37220d000000000000000000000000000000000000000000000000000000000000000000000000000f1f2c36434a4d4e505357606877849aa3b5c4b49f8a77624c37220d0000000003162839566c8196abc1b49e8975604b35201e28323f4b586176869ca8b9c2b29d8774604b35200b00000001162b41566b8096abc0ac97826c57423f37444b4e545c646f7c889ca5b6c3b49f8a77624c37220d0000000000000000000e24394e63798ea3b8b39d88735e38281602000000000000011426364e63788da5b6c5ab96816c563a2a1804000000000000000000000000000000000000000000001123374b5d70859ab0c0b9a795806a5847331f0c000000000000000e23384d63788da2c6bda8937d68533e2813000000000011263b50667b90a5bbbba5907b66503b2611000000000000000000000000000008131c2022211e160c1c2a333a474c4e4b4539312414000000000000000000000000000000000000000000000000000000000001162c41566b8196abc0b49f8a75604b35200b000000000000000000000000000000000000000000000000000000091e32465774899eb4bfa9947f6a544a5660728399a9babfad98826d583b2b190500000000000000000000000000000000000000000c2035495a73889db2c6b19c86715846331f0a0000000000000000000000000000000012273d52677c92a7c5c3a6917c66513c27110000000000000000000000000000000000000000000000000000000000060c0e15150e0c06010f1825303538393b39454b596275859ba9babaa9937e68533e291300000000091e32455771869bb0c4af9a856f5544311d0a161e2e3a475863798a9eb4c3b7a5907b66513b261100000002152737596e8499aebea9947e69543f2a263135393e4a4f5e6678879ca5b7baa9947f6a553b2b1805000000000000000010253a4f657a8fa4bab19c87725c47321d00000000000000081c3043546a7f95aac3b8a7907b66503b26110000000000000000000000000000000000000000000000081c2f3f50657b90a2b4c5b39e8976614c3a2a180400000000000010253a4f657a8fa4babca6917c67513c2712000000000013283d52687d92a7bdb9a48e79644f39240f000000000000000000000000061418253035373632281a2a3a474c59616360574e42311b0a0000000000000000000000000000000000000000000000000000000005192b3c5a6f859aafc4b09b86715544311d080000000000000000000000000000000000000000000000000000000c21364b61768ba8b9bda8927d68535c64748197a1b3c7b3a1907b65503b25100000000000000000000000000000000000000000000e23384d63788da6b7c1ac97826c573a291704000000000000000000000000000000000e23384d63788da7b8c0ab95806b56372614010000000000000000000000000000000000000000000000000000010f1a21232a2a2320190e0008131c2023232528323b485762788b9fb4c7ae99846e59362513000000000b21364b60768a9fb4c0aa95806b553726140102101c2a3a495b697e93a5b7c3ac97826d57372715010000081d31445572879cb1c7a5907b66503b26141d20242e36404c5a6277879db2c4b19c8772594834200b000000000000000011263b51667b90a6bbb09b85705b46301b060000000000021628384b6073879db2c7b39e8874604b35200b0000000000000000000000000000000000000000000000001123384b5d70859ab0c0b9a895806b5847331f0d00000000000012273c51677c91a6bcbaa58f7a65503a25100000000000152a3f546a7f94a9bfc5a28c77624d37220d00000000000000000000000715243136434a4c4b453834364758616e77797568604e392816030000000000000000000000000000000000000000000000000000000b2035485a73899eb3c2ac97826d57372614010000000000000000000000000000000000000000000000000000010e23384d63788da2c6bba6907b66656e7a85979fb1bfbaa999846f5d4b37230e00000000000000000000000000000000000000000013283d52687d92a7c4c5a7927d68523d281300000000000000000000000000000000000c2035495a73899eb3c5af9a85705544311d080000000000000000000000000000000000000000000000000007151f2c35393f4038352c1e0e0000070b0e0e10161e2b39495a6d8297adc2b29d87725443301c0700000010253a50657a8faabbc2a6907b66513b26110000000c1c2c3c4b6074879db2c7b29c87725544311d0800000b20364b60758a9fb4baa98d78624d38230d080b101b22303c4859667c91a6b7b6a48c77624c37220d000000000000000012273c52677c91a7bcaf99846f5a442f1a050000000003111e324556677d92a5b7bfac96816c5544311d08000000000000000000000000000000000000000000000000081c2f3f50657b90a2b4c6b49e8a77614c3b2a1805000000000014293e53697e93a8bec9a38e78634e39230e0000000001172c41566c8196abc1b9a78b75604b36200b0000000000000000000003152533424e5460626056514443546176838b8e8a7e685745321e1812100a0100000000000000000000000000000000000000000000000d22384d62788da7b8bea8937e69533e2914000000000000000000000000000000000000000000000000000208141c253a4f647a8fa4b9b9a48f7a717a838d9ba3b1bdbcab9f8b78634d3f2f1c08000000000000000000000000000000000000000004182a3a576d8297acc2b8a78d78634e38230e000000000000000000000000000000000006192c3c5a6f849aafc4b49e8975604b35200b000000000000000000000000000000000000000000000000041525333d494e54554d493c2c1b0b000000000000030d1b2c3c51677c91a6bcb49f8a75604a35200b000000132536556a7f94aac8b6a48c77614c37220c000000000e1d3144556a7f95aabfb49f8a75604b35200b00000e23384e63788daabbb49f8974604a35200b00000007121e2b3b4b6074889db3c2a6907b66513b2611000000000000000013283e53687d93a8bdad98836e58432e19030000000613212f404b6075879db2c3b3a18e79634e37271501000000000000000000000000000000000000000000000000001123384c5d70859bb0c1b9a896806b5947341f0d0000000000162b40556b8095aac0bcab8c77624c37220d0000000003192e43586e8398adc3b39e89745645311d09000000000000000000000d2033435060687377756b62514a607285999fa99f8a75604b362a2d27251e13050000000000000000000000000000000000000000000011273c51667c91a6c5c3a58f7a65503a25100000000000000000000000000000000000000000000000000a161e2630353951667c91a6bbc0ab9681868f999fabb5c1b8b39f8d7d685a493521110000000000000000000000000000000000000000000a1f33475872879cb1c7b39e88735b4935210c000000000000000000000000000000000000162b40556b8095aac0b9a88e79634e39240e00000000000000000000000000000000000000000000000011223343505b636a6a635a4939281603000000000000000e24394e63798ea3b8bcab8b76614b36210c0000071c3043546f8499aec4b19c87725847331f0a000000000215273750657a8fa5babcab8c77624d37220d000011263c51667b91a6c8b19b86715443301c0700000000000e1c3043546f8499afbda8937d68533e28130000000000000000142a3f54697f94a9beac97816c57422c170001080e1920313f4c5e6c8196a5b7beae99846f5b4a3619090000000000000000000000000000010204050001080b0c0e0f11121c2f3f50657b90a3b4c6b49f8a77624c3b2b180500000002182d42576d8297acc2b59f8a75604b35200b00000000051b30455a70859aafc5b19c87725c382715020000000000000000000013283c50616a7e878c8a806b5c4c62778ca3b4baa98f7a654f3b3f433d3930231305000000000000000000000000000000000000000000152b40556a8095aabfb7a58b76614c36210c0000000000000000000000000000000000000000000003131a283236434b5157687e93a8bdc4b09e969ca4aeb5bcbfb3a79e917e685f4e3c2c19030000000000000000000000000000000000000000000c22374c61778ca4b6c4ae99846f593d2c1a0600000000000000000000000000000000000011273c51667c91a6c4c6a8937d68533e28130000000000000000000000000000000000000000000000091c2f4050616a797f7f78635746321e09000000000000000d23384d62788da2b7c4a18c76614c37210c00000b20354a6074899eb3c2ad97826d583a2a180400000000000d23384d62788da2b7c5a18c77624c37220d0000142a3f54697f94a9bead98836e583625130000000000000417293a596e8398aebea9947e69543f29140000000000000000152b40556a8095aabfab95806b56402b1615151d202b35414e5d667c8d9fb5c3b2a08f7a644f3d2d1a000000000000000000040a0c1113151618191b1c141d202223242627292a384c5e70859bb0c1baa896816b594834200c000000041a2f44596f8499aec4b39e89745544311d0800000000031628385c72879cb1c5b09a85705b45301b0000000000000000000000152a3f556a7f939da59f8e79644f60758a9fb4c7a8937d6853515458524d41302313010000000000000000000000000000000000000004182a3a596e8499aec3b29d87725846331f0a0000000000000000000000000000000000000000000b171e3138454b5460666e768298adc2cdbcb0abb1b6c2c0b4afa199897d68604e41311e0e00000000000000000000070b0d0c0a0400000000000011273c51667c91a6c2c8aa947f6a553f2a15000000000000000000000000000000000000000d22374d62778ca6b7c2ac97826d5739291703000000000000000000000000000000000000000000000f23384c5e6a7f8c94958875614b372715030000000000041628394f647a8fa4b9b8a68b75604b36200b00000e23394e63788ea7b8c6a8937d68533e28130000000000000d23384d62788da2b7b8a78b76614b36210c0002182d42576d8297acbfaa95806a55402b1500000000070c171f33465870859aafc9a7927d68523d28130000000000000000172c41566c8196abbea9947f69543f2a292a2731353c494d60687b8b9fabbcb8a798826d5c4b371f0f00000000000000000c171f2127292a2c2d2e303126313537383a3b3c3e3f414050667b90a3b4c6b49f8a77624c3a2a18040000061c31465b71869bb0c6b29c87725d3727150100000000091e32455674899eb3c3ae99836e59442e1904000000000000000000071c31475c71869cb1b7a9937e69545571869cb1c1ab96816c62666a6d675f4d41301e0a000000000000000000000000000000000000000a1f33475873889db2c3ae99846e593a29170400000000000000000000000000000000000000000c1b2933414d566069737b838a98a0b2c5dacdc4c0c3b7b2aaa29a8f8478675f4e4231231300000000000000000008131c2023211f17130e0c060003162839566b8196abc0bbaa8f7a65503a2510000000000000000000000000000000000000000b2034485973889db3c6b19c86715746331e0a0000000000000000000000000000000000000000000011263b50667b909faaa6937e685544311e160b0500070c171f3246576a8095aabfb39e88735645321d09000013283d53687d92a8c5b9a88e79634e39240e040000070b121d2b3c50657b90a5bab39e89735746321e0a000417293a5b70859ab0c9a7917c67523c2715141415131c202a33434c61768a9fb4bcab907b65503b26100000000000000000182d42586d8297adbda8937d68533f3f3e3f37444b505a626e7d8b9fa9babcab9e8977614c3e2e1b01000000000000000e1c2a33373c3e3f414244454637444b4c4d4f505253545657595e70859bb0c5baa996816c5847331f0a000004172a3a5d73889db2c5b09b85705b46301b00000000000b21364b60768ba8b9c1ac97816c57422c17020000000000000002101b222f455a6f849aafc2ad97826d58586e8398adc3af9a8474787b7f827d675f4d392509000000000000000000000000000000000000000c22374c61778ca6b7bfaa95806a55402b1500000000000000000000000000000000000000000c1c2939464b5f67757e8790999fa9b2beced0c5b8b3aca59d958d847a6f625a4d413124140500000000000000000c18253035383633292823211a15101e32455770869bb0c5b49f8a76614b36210c0000000000000000000000000000000000000005192b3b596e8499aec3b49f8b76614c36210c00000000000000000000000000000000000000000000152a3f556a7f94aabbb29d8774604b42322820191c1b222933434b6175879db2c8af9a846f5a382815020003182d42586d8297adc2b49e8974604b35211f171c131c2023303b485a6b8096abc0af9a85705a39291603000a1f33475873889eb3bcab8e79644e39252a292a2b2530353a474c616c8196a9bab49f8b76614c36210c0000000000000000192e43596e8398aebca7917c675755545355575560656e7883929fa9babeb59f8d7c665947342010000000000000000e1f2c3a474c5153555657595a5c5d55606163646667686a6b6d6e6f717b90a5bbc7b49f8a77614c37220c00000a1f334758748a9fb4c4ae99846f59442f1a04000000000d23384d62788da2c6bfaa95806a55402b15000000000000000715202d363a41566c8196abc1b09b867166696d7f94aabfb49f8b898d909498927d67523727150200000000000000000000000000000000000010263b50657b90a5c4c6a6917c67513c2712000000000000000000000000000000000000000a1a293a4657616e7d87949da5aeb4bac7ced0bfb3a79e978f8780786f655d4d483c3023140600000000000000000c1c2936434a4d4c463a3d38352c2a2521364b60768a9fb4c6b09b86715746321e090000000000000000000000000000000000000000152a40556a7f95aabfbcab907b65503b2510000000000000000000000000000000000000000000000f24394e64798ea2b4b6a595806b604b4639352b312d363a474c616c8196a6b7bbaa947e69543f29140000071c31475c71869cb1c4af9a846f54433b37332a3125303538404d5962788a9eb4c2ab95806b56402b1600000c21374c61768ca7b8b49f8a76604b43363f3e3f4036434a4f58616e7f949fb0c5b09a85705746331e0a00000000000000001a2f455a6f849aafbaa5907b6f6c6a69696a6c6f757a838b99a1b4babeb1a095806b5e4c3a2a1802000000000000061a2c3d49586166686a6b6d6e70717274757778797b7c7e7f8082838586879db2c7cdbaa9947f69543f2a1400000c21374c61768ca9bac6ad97826d58422d1803000000000f253a4f647a8fa4b9bea8937e69533e2914000000000000001525333e4a4f5458687d92a8bdb49f8b787b7f82869cb1c7baa99f9ea8a6a9ad9c87725544311d08000000000000000000000000000000000000142a3f54697f94a9beb9a88d78634d38230e000000000000000000000000000000000000021628384658617582929da6b2b7c3c1c4cedcc7b3a19989827a736b635b4f4b3f342b1d120500000000000000000417293a47546062615857534e493d3f3a363b50657a90aabbc1ac96816c5739281603000000000000000000000000000000000000000011263b50667b90a5c3c9aa947f6a553f2a15000000000000000000000000000000000000000000000d21364a5c6f849aafbfb59f8d7e6c61574d483c463e4a4e58616d7f949fb0c4b49f8b77624c37220d00000a1f344a5f74899fb4bfaa95806a5c56514c473a4636434a4d545f6777869ca8b9b6a48f7a644f3a240f00000e24394e63798ea3c5b29d87726360545754535455565460646c7683949daebdb8a7937e69533929170300000000000000001b30465b70859bb0c5b29d8784817f7f7e7f8184898f989faab3bfbbb4a0978172604b402f1c0c000000000000000c2135495b63767c7e7f818283858688898a8c8d8f909193949697989a9b9da5b7cad7c7af9a856f5a45301a05000b21364b60768a9faeafa896816c56412c17010000000011273c51667c91a6bbbca6917c67513c271200000000000008183343505c646a6d717a8fa4b9baa99f8d9094979ca4b6cac7bab4b3b9c6bfb59f8a75604b36200b000000000000000000000000000000000003162839586e8398adc3b49e8974604a35200b000000000000000000000000000000000000091e32455661768698a0b2b7c2b6b1acb1bdcec4af9983736c6560544e493d372e20190d000000000000000000000a1f33475861727876726d68635b59544f4b45556a7f95aac8c4a7927c67523d27120000000000000000000000000000000000000000000c21374c61778ca5b6c3ae99846e593c2b1906000000000000000000000000000000000000000000071a2d3e50657b8fa1b2bcab9f93817569625a5c5b5d5c646b7682949daebdb7a697816c5948341f0b00000b20354a60758aa6b8c4ae99837a726b6661585c5c5b54606269707c889ca4b5c1b19c86715c4b37220d00000f243a4f64798fa4c3b39e897f79746f6c6a69696a6c6f7479818a99a1aebbbfb39e8975614b36210c000000000000000000192f44596e8399aec3b7a59d9a979494939496999ea8adb4bbc2b5aa9f94827260544330221200000000000000000e23384e6379899193949697999a9b9d9ea8a1a2a4a5a7a8a9abacaeafb1b2b7c3d4d6c7b29d88725d48331d0800091e3245566c8192999a958a7a644f39240f000000000013293e53687e93a8c0c0a58f7a65503a251000000000000114263650616a7a7f83868a9fb4c9c7bab4a2a6a9adb1b6c2d3d8cec9c9c8bbb4b19e88735544311d080000000000000000000000000000000000091e32465772879cb1c5b09b85705443301c07000000000000000000000000000000000006192b3c4b6074849aa4b2beb9b3a49c969fb1c4c1ab96816c554f4a4336352c221b100500000000000000000000000c21374c6176868d8b87827d78736e6a656056556f849aafc4b7a68d78624d3823130e0b070000000000000000000000000000000000000a1f33475872879db2c7b39e88735a4935200b000000000000000000000000000000000000000000000f23374b5d6e8399a6b7bcb59f96887f78737171727479808997a0aebbbcab9d8876614c3b2a18050000091e33495e73889eb3c8b3a1998f87807b77737171707174787e85919da6b5c2b5a3927d68523e2e1b0700000d23384d62788da5b7b8a79e958e8984817f7e7f808185898e979ea8b2bfc1b3a1937e685746321e0900000000000000000013293e53687e93a5b7c3b7b2afacaaa9a8aaacafb4b9c6c4b7b2a49c8c7f6d605443362614040000000000000000162c41566b8196a7a8aaabacaeafb1b2b4b9c6b8b9bbbcbdbfc0c2c3c4c3c2c1c0bfc6b9b09b86715b46311c0600031628384a60727d84848077645c4a36220d000000000011263b50667b90a2adaca28e78634e39230e0000000000081c3043546a7f8f94989b9fa9bacdd7cdc9b7bbbec2c1c1c4cddbcab9aca7aa9f9c95816b563727150200000000000000000000000000000000000c21364b61768b9fb4c1ac97816c573625130000000000000000000000000000000000000b2035485a6b8095a2b4c2b5a79e93878196acc1bfaa947f6a5537353025211a0f0800000000000000000000000002172c42576c8197a49f9c97928d88847f7a75706b73899eb4c8b39d88735a48352a2823201c13100b09020000000000000000000000000004172a3a586e8398adc3b8a68d78624d38230d00000000000000000000000000000000000000000000081c2e3f4c6177889da7b7bdb0a69d948d89878687898e959ea7b1bebbab9f8d7c665746331d0d00000004192e44596e8399aebebfb3aea49c96908c8987868687898d939ba3b3b8c4b9a79b8573604b3520100000000b2035495a72879db2c1b8b3aaa79e9a9694939495969a9ea7acb4b9c6bfb3a3998372604a392816030000000000000000000b21364b6075879da8b5c2c3c4c1bfbebebfc1c3c8bbb4afa69d93867b69614b4336261808000000000000000000182d43586d8298adc4bfc0c1c0bfbebcbbbab9b8b7b6bbb4b3b2b1b0afaeadacabaaa8a89e927d68523d28130000000a1c30435460686e6f6b62594a3e2d1b0700000000000b20364b607484929797918473604b35200b00000000000b20354b6074899ea9adb1b4bac7d7e9e1cac5b9b3b0acabb0bdcdc0ac9b928d8a878073604b36200b00000000000000000000000000000000000010253a4f657a8fabbcc9a8937d68533e28130000000000000000000000000000000000011426364d62788a9fb4c0b5a49c897e757c91a6bbbda8927d68533d281c1308060000000000000000000000000000081d32475d72879cb2b5b1aca8a79e99948f8a85817f94a8b9c3ae99836e594c473a3d3835302525211e160a0b020000000000000000000000142a3f54697f94a9c9c4a7917c67523c27120000000000000000000000000000000000000000000000111f344759647a899da5b3c0b7b2a9a79e9c9b9c9ea8aab3b9c2b6aa9f8d7e685e4c392917000000000010253b50657b90a0b5bcc9c3b6b2aba6a79e9c9b9b9c9fa9a9b0b5c1c3b6a89e8978635443301c0800000006192b3c546a7f94a3b3bfc6c5b8b3afaca9a8a9aaabafb3b9c5c9c5b8b3a1998575615443301b0b00000000000000000000091e324557647a8a9ca4aaadafb2b3b3b3b3b1aeabaa9f9a91887e73655d4f43302618080000000000000000000014293f54697e94a6aeadacabaaa9a8a7a6a5a4a3a2a1aa9f9e9d9c9b9a99989796959390897e695f4e3a251100000000132536434a53595a564c483b2d2010000000000000091d31455660757d82827c73605443301c0800000000000b21364b60768ba4b6c2c1bdbac9ced8cabaada79e9b97969eb0c4bca7927d7875726a605544311d0800000000000000000000000000000000000014293e53697e93a8c9bcab8f7a644f3a250f0000000000000000000000000000000000081c3043546c8197a9bab7a59c867868687d93a8bdbba6907b66513b2611080b0d0b08010000000000000000000000081d32485d72879db2c2c1c2c5b8b3aea9a99f9b96949daec6bea9947e6b66615858534e4a43363a363228261e13060000000000000000000010253a50657a8fabbcc1ab96816c56382715020000000000000000000000000000000000000000000004182a3a4a5c6479879aa2b2b7c3c5b8b3b1b0b2b4b9c6c3b7b2a49c8b7e68604e402f1b0b00000000000e23384b5d6d82979fabb2b6c3c0c0c5b8b3b1b1b0b1b4bac7c5c6bab4a59c8a7b645a4936261401000000000e20364b60748599a1acb0b4bac7bec0bfbebebfc1c3c1c9bcb5b0a79e9383766157463625130000000000000000000000031628394b5c647a869095989a9c9e9e9e9e9b9996918a857c746960554b3f321c140800000000000000000000000c21364c61768899999897969594939291908f8e8d8c8b8a8988878685848381807f7e7b7569604f41311e0b0000000008182530353d44454037342a1d100200000000000002152738455660686d6c67605544362614010000000000091e32455671869cb1afaca8a5b4bac7c0ad9c928985828196abc4b9a48f79646055554b4437322515050000000000000000000000000000000002152737576d8297acc2b59f8b76614b36210c00000000000000000000000000000000000b20354b6074899eb3c7b29d8776625a6a7f94aabfc9a48e79644f3924151d2022201d14090100000000000000000003182d42586d8297a3a7acb0b4bbc8c3c7bab4b0aba9aebbcbc6b19b85807c77726d68636054544f4b45383a312413030000000000000000000c21364b61768b9fb4c5b09b85705645311d0900000000000000000000000000000000000000000000000c1c2d3e4a5b637784919da5aeb3b8c5bdbdbdc5b8b3ada59d93867a68604e42312212000000000000081c2f3f4b6073818c969ca5a6abafb3b8c4babbbcbcbcc7bab4afa89f958779645d4b3c2c18080000000000091d3245566176838f969b9fa9a6a9abadaeafafafaeaca9ab9f9b92897e72615846392918080000000000000000000000000a1b2e3e4b5c64727b80838587898989888683817c76706760554b44372e2114010000000000000000000000000a1f334658647a8384838281807f7e7d7c7b7a7978777575737271706f6e6d6c6b6a686560564f4232231301000000000008131c20282f2f2b221f180d0000000000000000000a1a2838454b535857524b44372618080000000000000216283852677d919c9a9793909fa9babda7927d74706c768ca6b7bda8927d685355595c544f4332231301000000000000000000000000000000081d31445571869bb1c6b29c87725746321e0900000000000000000000000000000000000e24394e63798ea7b8baa9927d6758576c8196acc1bcab8c77624d3722273135373531261d15090000000000000000000d22374d6278868d92969b9faaa9aeb2b7c4c0c0bec2cbd8c9b5a39b96918c87827d78746f6a656056534e423121110000000000000000000a1e33465771879cb1c6b49f8a75604b36200b00000000000000000000000000000000000000000000000010202d3d4a59626f7d8791989ea7a5a8a8a7a5a79e9891877e74645c4e423124130400000000000000111d314455606c7981878c91969a9da6a3a5a6a7a7a6a5a99f9a938a8075635b4b3f2e1e0e000000000000021528384758616f7a81868a8d91939698999a9a9a999694908b867d75696054463a291b0b000000000000000000000000000010202e3e4a5460656b6e707273737373716e6b666158524b44373126191002000000000000000000000000000417293a4a5c646e6f6e6d6c6b6a696766656463626160565e5d5c5b5a595857565553504b4538322414050000000000000000070b13191a160d0b0500000000000000000000000a1a2832363d42423c353126190900000000000000000a25394d5f697f8785817e7b8b9fb4bfa9947f6a5b5873889db3c0ab96816b676b6f7169614f41311e0a0000000000000000000000000000000b20364b60758a9fb4c3ae98836e5939281603000000000000000000000000000000000012273c52677c91a7c5b49f8a75604b586e8398adc3b59f8a75604b362c37444b4c4b44373127190900000000000000000b203448596271787d81868a8f94999da6a7abb0b4bac7c3c7c2b5b1aba6a49c97928d88847f7a757168604e3f2e1c08000000000000000003172939586d8298adc2baa98f79644f3a240f00000000000000000000000000000000000000000000000002101f2d3b484c5f67747b83888d90929392908d88837c746960564a3e31241406000000000000000001152737444b5c646c72777c8184888b8e9091929291908d8a847d776b60574a3d2e201000000000000000000a1a2a3a474c5d656c7175787b7e81828485858483817f7b76716860564a4336291b0b0000000000000000000000000000000210202d36434a5055585a5d5e5e5e5e5c5956514c463a3631271d1409000000000000000000000000000000000c1c2d3e4a4e59595857565554535251504f4e4d4c4b45384847464544434241403e3b3632281a14060000000000000000000000000405010000000000000000000000000000000a161e21282d2d27201d14090000000000000000000a1e30414f616972706c6871869cb1c2ad98826d585a6f849aafc4af9a84797c8084877f695f4d3a25100000000000000000000000000000000f24394e64798ea9babfaa947f6a553f2a1500000000000000000000000000000000000014293f54697e94a9beb09b867055445a70859aafc5b39e89735544313c4955606260554b44372715010000000000000005192b3b484d5a62676c71767a7f83888d91969b9fa9a9adb2b7c3c0c0c2b6b1ada8a79e99948f8a867e685d4b37230e00000000000000000014293e53697e93a8c8c7a9937e69543e291400000000000000000000000000000000000000000000000000010f1d2a34414d5560666e74787b7d7e7d7b78746d6760554b45382d20140600000000000000000000091927313e4a4e575962676b6f7376787a7c7d7c7c7b78756f6861584b45392d1f10020000000000000000000c1c2a333f4b505755606366696b6d6e6f6f6f6e6c6a666158534b45383025180b00000000000000000000000000000000000210182530353b40434547494949494644413c363329201d15090100000000000000000000000000000000000010202d36394444434241403f3e3d3c3b3a393837363228333231302f2e2c2b2a2926201d150a00000000000000000000000000000000000000000000000000000000000000000003090b131817120b08010000000000000000000001132332434f545c5a57586e8398adc3b19b86716a6e728196abc1b3a29a8e9295999c927d67523d281200000000000000000000000000000013283d52687d92a7c7c5a6917b66513c2611000000000000000000000000000000000000152a40556a7f95aabfaf99846f5a375c71879cb1c6b19c87715c3735495b637477746a605544311d0b00000000000000000d1d2b343c494d5257566065696e73777c81858a8f93989da5a6abb0b4bac7c2c5b8b3aea9a99f9b8f7b654f3a25100000000000000000000f243a4f647a8faabbc2ad98836d583929160300000000000000000000000000000000000000000000000000000d181f3037444b515460636668686865636054524b443732281a100200000000000000000000000009151d2d36393b484d51565a576163656667676765626055534c473a32281b0f0100000000000000000000000c171f2e373a37444b4d51545658595a5a5a595754504c463a3632281c1308000000000000000000000000000000000000000008131c20252b2e303234343433312e2c27211f170b0802000000000000000000000000000000000000000002101b22242e2f2e2d2c2b2a2928272625242322201d151d1c1b1a191817161513100b0902000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000514253239454b5459576a7f95aabfb49f8a7c8083868c9fb4cac0b3afa3a7aaaeb09b85705b46311b060000000000000000000000000000132536576c8196acc1b9a78d77624d38220d000000000000000000000000000000000000152a3f546a7f94a9bfaf9a846f54445573899eb3c4af9a856f5a453b4d6379888c887f73604b3929170300000000000000000d19202c35383d38454b4f54595a62676b70757a7e83888c91969a9fa9a8adb2b6c3c0c7bab4ad98826d58432e180000000000000000000b20364b60758a9fb4c7b29d87725746321e0a00000000000000000000000000000000000000000000000000000005131926313536434a4e50535352504e4b43363631271e160a00000000000000000000000000000001101b22242b34373c4139464b4e5051525251504d4b443737332a1e160a000000000000000000000000000004111c2325263135383c3e41434445454544413f3b363329211e160a000000000000000000000000000000000000000000000000070b1016191b1d1e1e1e1e1c1916110c0a0400000000000000000000000000000000000000000000000000070d0f191a1918171615141211100f0e0d0c0b0902000706050403020100000000000000000000000000000000000000000000000000000000000000000000000000040a0c0d0b05000000050b0d0f0b0801000000000000000000091e32455760696e72757f94a9bebaa99f9195989c9faabbced0c7c4b8bcc0c9b29d88735d48331e0800000000000000000000000000071c30435470859ab0c5b39e89745a4835200b00000000000000000000000000000000000013283d53687d92a8c8b39d8874604b60758a9fb5c2ad98836d584348596e8398a69e95816c5746331e0a000000000000000000050e192023272832363a3f3c484d5256566064696e72777c8085898e93989ca5a6aaafb4b9af9a85705a45301b000000000000000000091d32455671869bb0c0b4a28b76614b36210c000000000000000000000000000000000000000000000000000000000009141d20253035383b3d3e3d3b38353026201d150902000000000000000000000000000000000000070d0f182022272c283236393b3c3d3d3c3b38353126211f170c030000000000000000000000000000000000080e10141d202326292c2d2f30302f2e2c2a26211f170c0903000000000000000000000000000000000000000000000000000000000003050809090909070401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040c171f212220180d010d18202224201d150900000000000000031729394b60757f84878b949daec2c7bab4a6aaaeb1b4bbc8d9e3dcc5c5b8b3b0ab9a85705a45301b05000000000000000000000000000b20354a6074899eb4c5af9a85705a3c2b190500000000000000000000000000000000000010263b50657b90aabbb7a6907b655462778cabbcc0ab96816b56404c62778b9fb4b39f8b76614c36210c0000000000000000000000060c0d12161e21252a2b35383c38454b4f54585962666b7075797e82878c91959a9ea8a596816c57412c1700000000000000000002152838576c8197a8a9a29a84705746321e0a00000000000000000000000000000000000000000000000000000000000001080b131c2023262829282623201c140b08020000000000000000000000000000000000000000000000050b0d1216161e212325272827272623201d140c0a040000000000000000000000000000000000000000000001080b0e11141618191a1a1a191715110c0a040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c0c0a040000000000000000000000000b171f29333737342b1c141d2b343739353127190f0100000000000a1e3346576e8394999d9fabaebbcbd7cdc9bcbfc3c1bebfc2ccd9c5b4a7a79e9a978d7c66513c261100000000000000000000000000000e23384d63788da8b9c1ab96816c56412c17000000000000000000000000000000000000000c21364b61768a9fb4c4b09b85726064798ea3c9bea9947f69544c5e6d8297aabbb49e8975604b36200b00000000000000000000000000000003090b1014192022272832363a3e3b484c5156556064696d72777b8085898e8f8777624d37220d000000000000000000000e23394e63798a94948f8476614c3929160300000000000000000000000000000000000000000000000000000000000000000000070b0e11131313100e0b08010000000000000000000000000000000000000000000000000000000000000003090c0e1011121212100d0b080100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c0f0d0b05000000000000000000000000000000000000090c181f22221f180c070000000000000000000b1b29333a474c4d483b3026333b484d4e4b44372c1f0f00000000000c21364c61768a9faeb2b4bcc9cbe2e7d5c4b8b3afaca9a9afbbccbba7968d8885827a665e4c38240f000000000000000000000000000012273c52677c91a7c6c8a8927d68533d2813000000000000000000000000000000000000000a1e32465770859ab0c2b5a3957f6a657b90a5babca7927d67525e667c8d9fb4baa996816b5645311d090000000000000000000000000000000000000000050b0d12151d2025292b34373c37444b4f53585961666b6f74797a7562594834200b000000000000000000000c2136495b63797e7f7a70615847331b0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080b141a1b1917161412100e0d0b080100040200000000000000000000000000000000000000000000000000050b0d0e0c060000000000000000000000030c171f21242220190e04000000000000000000000000000004121d242a333737342a211a0f010000000000000417293a464c586162594b433643505962646055493d2c1808000000000d22374c62778ca5b6c0bcb9b6c9cdd7cbb8a69e9a9794949dafc2b7a28d7873706c645c4c402f1d090000000000000000000000000001162b40566b8095abc0bbaa8e79644f39240f000000000000000000000000000000000000000316293952677c91a4b6c1af9d947f747d92a7bcbaa5907b65626d7c8a9eabbcb49f8a77624c3827150200000000000000000000000000000000000000000000000002090b0f1418202227273135393e3a474c5155546063656056483b2b180500000000000000000000061a2c3d495b636969655d4c473a2a170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b0d0d0b050000000000000000000000000000000000000000000000000000000000000002080b0d0c0b040000000000000000000000000000000000000000000000000000000000000000000000000000000000000009151d202a30302e2d2b2927252422201d141b1917151312100e0c0b07000001000000000000000000000000050d1820222320190e0000000000000000000a161e2933363938352b1f170c0000000000000000000000000112222f383a474c4c473a362d1f0f0000000000000a1f334658616e76776d60544350616a777974635b49362513000000000b1f34475972879cadaba7a4a1b4bac7c8b39e8885827e7f94a9c5b9a48f7a645b574f4b3e2f2212000000000000000000000000000005182b3b5a6f8499afc4b49f8a75604b36200b00000000000000000000000000000000000000000b20354b6073869caabbbcaf9d94858297adc2b8a38e796f78828d9ea8b9b5a396806b5948341a0a000000000000000000000000000000000000000000000000000000000000050b0d11151d2024292a34373c36434b4e4f4b45382b1d0d0000000000000000000000000f1f2c3c494d5454504b3f332a1c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090d181f22221f180d060000000000000000000000000000000000000000000000000000000509151d2023221f180c000000000000000000000000000000000000000000000000000000000000000000000000000000000009192731363f45454442403e3c3b3937353126302e2c2a2927252321201c131b160b080200000000000000000d19202b343738352c1c13080000000000000a1a28323a464c4f4d483c332a1c0c00000000000000000000000f202f404c51586161594e4a3d2d1a0700000000021628384c6176828b8c8272604b5f6a7f8c8e8779635443301c0700000005182a3b51677c919895928e8b9fa9babba6907c706c69778ca6b8bda8937e6853423a372e20120400000000000000000000000000000b2034485973889eb3c6b19c86715645321d090000000000000000000000000000000000000000081c304354647a8b9fb4bcbbafa29a97a0b1c5c0aa9580848b989fabb9b8a79b8574604b3b2a18000000000000000000000000000000000000000000000000000000000000000000000001080b0f14181f2226263035393a3632281a0d00000000000000000000000000010f1e2c35383f3f3a372e1f170c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004121d242a343737342a211a0f010000000000000000000000000000000000000000000000000d18202731363837342a1d1709000000000000000000000000000000000000000000000000000000000000000000000000000002152737444b545a5b5957555452504e4c4b4437454342403e3c3a3837353025302b201d15090000000000000d1d2b343b484d4d493c302518080000000003162838454b586164625a4c473a2a1704000000000000000000071a2d3e4c5e6671777771635b4a36210c00000000091e3245566e83989fa0947f695b677d919fa49c8673604a35200b000000000d24394d5f677c82807d79768b9fb4bea9947f69575973889eb3c6ac97826d57422d221b10020000000000000000000000000000000d22374d62778ca6b8c2ad98836d58382815020000000000000000000000000000000000000000011426364a5c687e939fabb8c0b4afadb1becec3af9e95999faab5bcb6a79e8979635645321d0d00000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c11141c202425211e160a000000000000000000000000000000000e192123292a25231c110400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000312222f383b484c4c483b352c1f0f00000000000000000000000000000000000000000000000d1d2b3437444b4d4c473b3527170000000000000000000000000000000000000000000000000000000000000000000000000000081d31445560696f706e6c6b696765636260555c5a5957555351504e4c4a433645413631271909000000000a1a2b3c484d5962635a4a4336251300000000091e324556606d7679776f615847331f100000000000000000000d21364a5c667c868c8c8679634e39230e000000000b21364b60768a9fb4b49f8b796378899eb3b5a48d78634e38230e000000000a1d30404d5f676d6b676471869bb1c2ad97826d585a6f849aabb1a899836e59442f1908000000000000000000000000000000000011263b51667b90a6c4bea9947f69543f2a140000000000000000000000000000000000000000000008182e3e4e60687e8d9ea7b3bfc5c2c5cedcccbcafaaafb4bbbbb4a49c897a645b4938281500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080b0e100b0902000000000000000000000000000000000000060c0e1414100e080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011212f404c51596262594e493d2c1b0b0000000000000000000000000000000000000000000a1b2b3b484c55606261595245351b0b00000000000000000000000000000000000000000000000000000000000000000000000004182a3a4b60737f85858382807e7c7a7977757371706e6c6a686765636160545c5b564b4437271502000003162838485a627077786d605443301c0d00000417293a4b6074828b8e8d8476614c3e2e1b0800000000000000000f24394e64798c9ca4a39a846f5a452f1a00000000091e32455670859ba9baa99c8676849ba7b9b49e8976614c37210c0000000000122230414d51585652586d8298adc5b09b86715b50657b8d999b988a7b654f3a2510000000000000000000000000000000000000152a3f556a7f94aabfc4a5907b66503b26110000000000000000000000000000000000000000000000102031424e60687c8999a1aeb4bbc8d8e5d7cdc9c0c7bab4aa9f978679645c4a3d2c1a0a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081c2f3f4c5e6672777771635b493929170300000000000000000000000000000000000000031628394859626d7578776c63523928160300000000000000000000000000000000000000000000000000000000000000000000000a1f3347586c81949a9a9997959391908e8c8a89878583817f7e7c7a7876757371706b605544311d090000091e3245566278848c8d8272604a3b2b1805000a1f3346586d82979faaa29a84705c4b37220d000000000000000012273d52677c92abb6b39e88735e37271502000000021628384e63798b9fb4b5a49c879ba2b4b3a2937e685847331f0a000000000004122330393c43403f54697e94a6b1af9e88735e4c5e657b83868379655d4b37220e00000000000000000000000000000000000417293a596e8399aec3b8a68c77624c37220d000000000000000000000000000000000000000000000002142431424e5e6678838f999faabbced7c7bab4b0aca99f988c8175635b4a3e2d1f0f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080d0f13120c0a030000000000000000000000000000000000000000000000000000000000000000000000000000060c0e100c0a04000000000000000000000000000000000000000000000000000000000000000000000000000000000e23384b5d667c878c8c8579635746331e0a00000000000000000000000000000000000000091e324557627782898d8c816c5746321e0900000000000000000000000000000000000000000000000000000000000000000000000c22374c61778a9fafb0aeacaaa9a7a5a3ab9f9e9c9a98979593918f8d8c8a8886858073604b37271501000b21364b6075879aa2a0937e695948342012000c21364c61768a9fb4bbb4a28f7a644f3a250f000000000000000011273c51667c91a6c9b49f8a745544311d08000000000a21364a5b6a7f94a3b5b5a49ca4b4b9a79a8472604a3a29170400000000000004121d24272d2b374c617788989c9a927f6a55404c5d656e716d635b4b3f2e1b0800000000000000000000000000000000000a1f33465872879db2c7b39e88735948341f0b00000000000000000000000000000000000000000000000006142431404c5a626e7a838c9fb4c9cdbaa99f9b97928a83796c61574a3d2d20100100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101b22252927211e170b0000000000000000000000000000000000000000000000000000000000000000000000070f1a212325221f180c00000000000000000000000000000000000000000000000000000000000000000000000000000010253b50657b8c9ca5a39b8776614c36210c000000000000000000000000000000000000000b21364b607587979ea89f8b76614b36210c00000000000000000000000000000000000000000000000000000000000000000000000f253a4f647a8faabbc5c3c1c0bebcbac9bcb4b3b1afaeacaaa8a6a5a3aa9f9d9c9a95806b5544311d080013283d53687d92a5b4b39e8977624d402f1b0b0e24394e63798eaabbcec0a8927d68533d2813000000000000000011263b50667b90a5bbbaa98b75604b36200b00000000071a2d3d4b6073859ba9bab6b1b6bfb39e8978625443301c0c0000000000000000000a1012181f34475963798387857d6a61503c3f4c50595c584e4a3d2e21100000000000000000000000000000000000000c21364c61768ba5b6c4af9a846f5a3b2a1805000000000000000000000000000000000000000000000000000614222f3c484d5d656e798eabbcc9b49f8b85827c766e635b4b46392d1f10020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b171f2e373a3e3c3633291b0b0000000000000000000000000000000000000000000000000000000000000000010f1a212c36393a37342a1c1507000000000000000000000000000000000000000000000000000000000000000000000000061b30455b70859aaab6b5a5927d68533d2813000000000000000000000000000000000000000e23394e63788ea5b4b9ab8e79634e39240e00000000000000000000000000000000000000000000000000000000000000000000000d23384d62788da1b3c0d0d7d5d3d1d0c7c4bbbcbec0c1c1bfbdbcbac8bbb4b3b1b09e8975604b35200b0014293f54697e94a7b9b9a898836e5e4c3929160c21374c61768b9fb5bfb5a38f7a65503a2510000000000000000010253a4f657a8fa4bac7a18c76614c37210c00000000000f1d31445563798b9fb4c0c7c2b3a1927d6759483625130000000000000000000000000004182a3a495b636e726f675f5043332f383b44464339362d1f100300000000000000000000000000000000000010253a50657a8fa5c3c0ab96806b56412b1f18110f09000000000000000000000000000000000000000000000004121d2b343f4b4f61778b9fb5b8ac9681716d6761584e4a3d32281b0f010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1b29333e4b4f53524b4639291b0b000000000000000000000000000000000000000000000000000000000000000f1f2d363d494e504c473a3325150200000000000000000000000000000000070d0f140e0c06000000000000000000000000091e34495e73899eb3c8c3ad97826d58422d18030000000000000000000000000000000000000c21364b61768ba7b8c9a6917c66513c271100000000000000000000000000000000000000000000000000000000000000000000000b2035485a6e8399a2b3c2d2e2e3d0bfb3afa5a7a9aaacaeafb1b3b4bbc8b9bbc8b8a68c77624d37220d000d22374c6277899eb3c1b2a0917c665746321e101f3347586e8398a1a6a39b8572604a35200b00000000000000000f24394f64798ea4b9b7a28d77624d38220d000000000001142637495b6a7f94a2b4bbb3a499836e5f4d3b2b180800000000000000000000000000000c1c2c3d494e585c5a524d4133251c23262e312e24211a0f010000000000000000000000000000000000000014293f54697e94a9bec8a7927d67523d37332a26231c110400000000000000000000000000000000000000000000000d19202e3747586f84999fa69e917c6657524c473a362d1e160b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000417293a464c5c646867615746392917030000000000000000000000000000000000000000000000000000000000071a2d3d4a4e5b636561595043332010000000000000000000000000000002101b22242923211a0f0100000000000000000000071c32475c71879cb1bebaab96816c57412c17020000000000000000000000000000000000000a1e33465773899eb3bea9947e69543f2914000000000000000000000000000000000000000000000000000000000000000000000006192b3c4b6074849aa4b5c4d4dcc7b3a1999092939597989a9c9d9faaa2a4a6a7aa9e8874604b36200b000b1f344759697e93a3b5bfb29d8775614b3e2d19172a3a4c6175838e918f8578625443301c0700000000000000000e23394e63788ea3b8b8a38e78634e39230e00000000000009192c3d4b607384979faaa1998677614c41311d0d000000000000000000000000000000000f1f2c35394347453d39302315080e10191c180e0c07000000000000000000000000000000000000000002152838586d8298adc2bbaa8e796356514c473a3b382f221103000000000000000000000000000000000000000000000005101b2a3a4c6177838b8c887e695e4c3d373329211a0f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1f334658616f7a7e7c75615746331e0a00000000000000000000000000000000000000000000000000000000000c21364a5b6371787a776a61503e2d1b070000000000000000000000000614202d36393e38352c1f120500000000000000000000152a3f546a7f94a0a8a99f8c7a644f3a240f00000000000000000000000000000000000000031729395b71869bb0c1ac97816c57422c170000000000000000000000000000000000000000000000000000000000000000000000000e1d3245566175869ca6b7c6d6c4af99847c7c7e8082838587888a8b8d8f9092938c7d675544311d080005182a3b4b6073859babbcb7a596816c5c4a3726141e334657616f787c7a726259483625130000000000000000000d22384d62778da2b7b9a48f79644f3a240f000000000000000f1d3144556175828a8e8c83766159473423130000000000000000000000000000000000010f1a21232e323027251e13050000000407030000000000000000000000000000000000000000000000091d32455671869cb1c6b49f8b75706b66615858504c402f2211000000000000000000000000000000000000000000000000000c1f344759616e76777469604e402f211f170c07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c21364c6176838f93918775614b36210c00000000000000000000000000000000000000000000000000000000000e24394e6379868e8f8b7f6a5c4a36220d0000000000000000000000041424323e4a4f534e493d302312000000000000000000000b20364b6073828f93928a7d675c4a36220d0000000000000000000000000000000000000000192e44596e8399aec3af99846f5a3726140100000000000000000000000000000000000000000000000000000000000000000000000215283846576278889da8b9c8c7b3a1917c67696b6c6e7071737576787a7b7d7d78675f4d3727150200000d1c304354647a8c9fb4c3b49f8c7a645544311d172939464c5b6366646054483b2b18080000000000000000000c22374c61778ca1b6baa5907b65503b261000000000000000011426374657616d7679776f6158473a2a180500000000000000000000000000000000000000060c0e191d1a12100a010000000000000000000000000000000000000000000000000000000000000b20364b60758a9fb4cabbaa9f8a85807b77726d665e4c402f1c0900000000000000000000000000000000000000000000000004182a3a474c57616260544e423122120a04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002172c41576c8196a1a8a5937e68533e281300000000000000000000000000000000000000000000000000000000031729395b70859aa4aa9f8e79644f39240f0000000000000000000002122232434f5c6469635b4d41301b0b000000000000000000081d314455606d7a7e7c77675f4d3e2d1b070000000000000000000000000000000000000001162c41566b8196abc0b29c87725544311d080000000000000000000000000000000000000000000000000000000000000000000000000a1a29394859647a8a9eaabbcebfb49e8a79635757595a5c5e58616364666868635a4d41301909000000011426364a5c6c8196a6b7bbaa9b8573604b3c2b191b29333d494e514f4a43362b1d0d000000000000000000000b21364b60768babbcbba6917c66513c2711000000000000000009192939464b58616462594c473a2a1c0c0000000000000000000000000000000000000000000000030705000000000000000000000000000000000000000000000000000000000000000000000e23384d63788daabbcec8baa89f9a95918c87827c665e4c38230f000000000000000000000000000000000000000000000000000c1c2a3439464b4d4b43363124140400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061b30465b70859bb0bfad98836d583b2a18050000000000000000000000000000000000000000000000000000000a1e33465774899eb4bba7927d67523d281200000000000000000000102030404f61697a7e79675f4d39291703000000000000000002152737444b5c64696761584d4130201000000000000000000000000000000000000000000014293e53697e93a8beb49f8a75604b35200b000000000000000000000000000000000000000000000000000000000000000000000000000b1b2b3b4a5c667c8c9fb4becdb9a89c8675614b4145473a464c4d4f5152534d493c302313000000000008182d3e4c6176889db3c0b5a3947e695a48352012171e2c35393c3a353025180d00000000000000000000000b20354a60758a9fb5bca7927d67523d28120000000000000000000b1b29333a464c4e4c483b33291c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d22374d62778ca4b5c5cac6bab4afaba6a59c98907b66503b261100000000000000000000000000000000000000000000000000000c181f28323637353026181406000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003182e43586d8398adc2b29d87725947341f0b0000000000000000000000000000000000000000000000000000000c21364c61768ba8b9bca7917c67523c27120000000000000000000e1e2e3e4d5e697f8e938b7d675746331e0a000000000000000000091927313e4b4f53524c473a352b1e0e00000000000000000000000000000000000000000011263c51667b91a6bbbbaa8d78624d38230d00000000000000000000000000000000000000000000000000000000000000000000000000000d1d2d3d4c5e697f94a0b2c1c6b6a498826d5f4d3c2b293336383a3b3d3e38352c1e1305000000000000101e334657677d92a2b3c1b49e8a78624d40301b0b0f1a21232724201c1308000000000000000000000000071c30435474899fb4bda8937e68533e2913000000000000000000000b171e2933363937342b1f170c0000000000000000000000000000000000000000070d0f120e0c0700000000000000000000000000000000000000000000000000000000000000000000000b2034485971869ca7b1b5bcc9c2c5c0c3b6b2ad98836e59432e19040000000000000000000000000000000000000000000000000000040b161e2122201c1408000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014293f54697e94a9c9b6a58c77624c37220d0000000000000000000000000000000000000000000000000000000e23394e63788ea3c6baa48f7a654f3a251000000000000000000c1c2b3c4a5c667c8d9fa99e8976614c36210c0000000000000000000009151d2e3a474c5458554d483c2b1c0c00000000000000000000000000000000000000000e24394e63798ea3c5c8a5907a65503b25100000000000000000000000000000000000000000000000000000000000000000000000000000000f1f2f404f616d8298a3b5c4c2b2a0927d675a4937261f2123252628282320190e0000000000000000031729394d5f6f849aa9bab9a899836e5f4d39291703060c0e110f0b070000000000000000000000000000001325495e73899eb3bfa9947f6a543f2a150000000000000000000000030b171f21242220180d040000000000000000000000000000000000000004101b22242824211a0f0100000000000000000000000000000000000000000000000000000000000000000005182b3b4f647a89949c9faba9adb1b4bcc9c8b09b86705b46311b060000000000000000000000000000000000000000000000000000000003090c0d0b080100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010253a50657a8fabbcc3a6917c66513c261100000000000000000000000000000000000000000000000000000010263b50657b90a5bac5a28d78624d38230d000000000000000a1a293a495a647a8b9fabb9a8917c67513c271200000000000000000000081b2e3f4b5961696d6b625a483a2a1804000000000000000000000000000000000000000c21364b61768ba7b8bda8937d68533e281300000000000000000000000000000000000000000000000000000000000000000000000000000001112232434b6074859ba6b7c8beb39e8978625544311d0e0e0f1113130e0c06000000000000000000000b1b30414d63788b9fb4c3b3a1917c675746331e10000000000000000000000000000000000000000000001d33485d72889db2c0aa95806b55402b1600000000000000000000000000040a0c0f0d0b0500000000000000000000000000000000000000000c171f2d36393d39362d1f11030000000000000000000000000000000000000000000000000000000000000000000d22364a5c64767f868b9094989c9faba8acaa98836e58432e190300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c21364c61768b9fb5c0ab95806b5637271501000000000000000000000000000000000000000000000000000013283d52687d92a7bdb8a78b76604b36210b0000000000000215273847586278889ea9babcab937e69533e2914000000000000000000000e22374b5d65777f828078625847331f0a000000000000000000000000000000000000000a1e32465773899eb3c0ab96806b56412b160100000000000000000000000000000000000000000000000000000000000000000000000000000004141e3245566277889daabbccb9a89b8573604b3c2c1906000000000000000000000000000000000000132135495b6a8095a5b6bfb29d8876614c3e2e19090000000000000000000000000000000000000000071d32475c72879cb1c1ab96816c56412c170100000000000000000000000000000000000000000000000000000000000000000000000000000c1c29333e4a4e524e4a3d2f2111000000000000000000000000000000000000000000000000000000000000000000071b2d3e4a58616a71767b7f83878b8f9397988c7a644f3a250f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070c0e1718140b0903000000000000000000000000000000000000000a1e33465772879cb2c5af9a85705544311d080000000000000000000000000000000000000000000000000000152a3f556a7f94aabfb39e89735645321e09000000000005131d3145566176869ca6b8bdb59f8c7a644f3a250f0000000000000000000010253a4f657b899498958877614c37220c00000000000000000000000000000000000000031629395b71869bb0c3ae98836e59432e190000000000000000000000000000000000000000000000000000000000000000000000000000000000021628384859657b8c9fb4c0c6b4a3947f695a4935201300000000000000000000000000000000000006192c3c4b6074879cb2beb7a697816c5c4b3727150100000000000000000000000000000000000000071c31465c71869bb1c2ac97826d57422d18020000000000000000000000000001080b0801000000000000000000000000000000000000000417293a474c5c6467635b4c3f2f180800000000000000000000000000000000000000000000000000000000000000000010202d3a474c55586165696d72767a7e82827c665c4b37220d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010f1a21242c2e29211e160a00000000000000000000000000000000000003172939586e8398adc3b49f8975604b35200b0000000000000000000000000000000000000000000000000002172c42576c8197acc1b19c86715c382816020000000003132333444b6074849aa4b6c0b19f947f695c4b37220d000000000000000000051a30455a6f859aa7ada6927d68523d28130400000000000000000000000000000000000000192e44596e8399aec3b19b86715c3a2a170400000000000000000000000000000000000000000000000000000000000000000000000000000000000a1a2b3b4b5d6a7f94a2b4c4c1b49f8a78634d42311b0b0000000000000000000000000000000000000e1d324556657b90a0b2c4b49f8c7a645544311d0e00000000000000000000000000000000000000061b30455b70859ab0c3ad98836e58432e190300000000000000000000000209141d201d14090900000000000000000000000000000000000a1f334758616f797d79655d4c36261401000000000000000000000000000000000000000000000000000000000000000002101c2a33373a474c505458576165696c6d665e4c3e2e1b080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010f1f2d363941433e3632281b0b000000000000000000000000000000000000152a3f546a7f94a9bfbaa88e79644e39240f00000000000000000000000000000000000000000000000000041a2f44596f8499aec4af9a846f5a452f1a00000000011121314150626d8298a2b4c2b4a297816d614f3e2e1b08000000000000000000051b30455a70859aafc4ab96816b56412c1f180e0c0600000000000000000000000000000001162c41566b8196abc0b39e89745847331f0a0000000000000000000102000000000000000000000000000000000000000000000000000000000000000d1d2e3f4b6072849aa6b8cbbaa99a846f604e392917030000000000000000000000000000000000021528384c5e6e8398a8b9bcab9c8673604b3c2c1906000000000000000000000000000000000000051a2f455a6f849aafc4af99846f5a442f1a050000000000000000000009151d2631353126241d1204000000000000000000000000000005182b3b4c6176838e928c7b655443301c08000000000000000000000000000000000000000000000000000000000000000000000c171f212933373b3f39464b4f535758504c402f20100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002030403000f1f2d3d4a4e5758544b4539291b0b000000000000000000000000000000000010263b50657b90a5c3c6a8937e68533e291300000000000000000000000000000000000000000000000000021527385c71869bb1c2ad97826d58422d18030000000f1f2f3f4e5f6a8095a0b2c0b6a49a8473604b433220100000000000000000000003192e43586e8398adc3ae98836e594337332a23211a0f06000000000000000000000000000014293e53697e93a8beb9a88c77614c37210c000200040a0c0f111416170d0b060000000000000000000000000000000000000000000000000000000000101c3043546277889eb3bec7b4a2927d685746331e0d0000000000000000000000000000000000000a1a2f404c6277899eb3c1b5a4947f6a5a4935201300000000000000000000000000000000000004192e44596e8399aec3b09a85705b45301b060000000000000000000919273137444b44373830221204000000000000000000000000000b203448596f8399a1aa9c8673604b3626140100000000000000000000000000000000000000000000000000000000000000000000040a0c171f21252a2832363a3e42433b382f221102000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070b0f1317181918151a2d3d4a5b636c6d6960574639291703000000000000000000000000000000000c21374c61768ca5b7c2ad98826d583a2a1804000000000000000000000000000000000000000000000000091d31455673889eb3c0aa95806b55402b160000000d1d2c3d4b5d687d929eafbeb8a79c8676615544312515020000000000000000000001172c41566c8196abc1b09b85705b4f4c473a38352c211a0f0100000000000000000000000011263b51667b90a6bbc6a48f79644f3a241215181a181f222427292c2c2320190e00000000000000000000000000000000000000000000000000000000011426364859667b909fb1c4c0b39e8876614c3b2b18050000000000000000000000000000000000001120344859697e93a3b5c2b49f8a78624d41301c0c000000000000000000000000000000000003182e43586d8398adc2b19b86715c46311c07000000000000000008182737444b556055514c40302212000000000000000000000000000d22374d62778ca1b3b6a4917c675443301c0800000000000000000000000000000000000000000000000000000000000000000000000000040a0c1014161e2125292d2d26231c1103000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000408131c2024282c2e2e2d2a27364a5b637981837e75615746331e0a000000000000000000000000000000000a1f33475872879db2c7b29c87725847331f0a0000000000000000000000000000000000000000000000000b20364b60758a9fb5bea8937e69533e291400000a1b2a3b495b657b8c9fb4bcbaa99e897863584737271507000000000000000000000000152a3f556a7f94aabfb29d877267656158564e493d362c1f140200000000000000000000000e24394e63798ea3c5bca7927c67523d27282a2d2f2a3437393c3e414138352b1e0e0000000000000000000000000000000000000000000000000000000008182a3b4c5e6d8297a6b8cbb8a695806b594834200e00000000000000000000000000000000000005182b3b4b6073859babbcbaa999846f5f4d3a2917040000000000000000000000000000000002182d42576d8297acc2b29c87725d47321d0000000000000000001325364455606c7571665e4c40301d090000000000000000000000000c21364b61768a9fb4c2b19c8673604b36261401000000000000000000000000000000000000000000000000000000000000000000000000000000000003090c10141718110f0900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b171f253035393e42434443403c364e63798b9698938676614c36210c0000000000000000000000000000000004172a3a596e8399aec3b6a58c77614c37220c0000000000000000000000000000000000000000000000000d23384d62788dabbcbba6917c66513c2711000818283948596379899eaabbbcb49f8b7b655a493a2919090000000000000000000000000013283d53687d92a8bdb49f8b7e7c7a77726b635b4e493d321e160a000000000000000000000c21364b61768ba7b8bfaa947f6a553f3a3d3f42453a474c4f515456574d493c2b1b0b000000000000000000000000000000000000000000000000000000000d1d2f404c6176889db3bfc5b49f8a77624d3c2b19050000000000000000000000000000000000000d1d314455647a8c9fb4c4b3a1927d675847331f110000000000000000000000000000000001172c41566c8196abc1b39d88735e4826140100000000000005131c3043546073818a867c665e4c39240d0000000000000000000000000a1e3246576c8197aabbb6a4917c675443301c0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003141b293336434a4e535758595855524c546c8196a9ada4937d68533e28130000000000000000000000000000000000152a3f556a7f94aabfc3a6907b66513b261100000000000000000000000000000000000000000000000010253a4f657a8fa4c9c9a48f79644f3a240f0114263645576277879da7b9beb09e927d685d4b3c2c1c0c000000000000000000000000000011263b51667b90a6bbbbaa9f92918f8c8781796e635b4f4332281a0a0000000000000000000a1e32465773889eb3c2ad97826d584d505255575a5c59616466696b6c625a493a29170400000000000000000000000000000000000000000000000000000000111f334758677c91a1b3c7baa897826c5a4835200b000000000000000000000000000000000000011426374a5c6c8197a6b8bfb39e8876614c3f2e1a0a00000000000000000000000000000001162b40566b8095abc0b49f89745443301c08000000000004132332434a607282979f9c8d7c66513b2b18050000000000000000000000031629394d62788b9fb4c2b19c8673604b36261401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c0f12120c090300000000000000000000060c0e11100e0b09020000000000000000000000000000000000000000000000000000000000000000000b161e313a464c546064686c6d6e6d6a67616074889db3c2a9947f69543f2a14000000000000000000000000000000000011263b51667b90a6c4c0aa95806b5536261401000000000000000000000000000000000000000000000012273c52677c91a7bcbcab8c77624d37220d121c3043546075859ba5b7c1b2a095806b5f4e3f2e1e0e0000000000000000000000000000000f24394f64798ea4c5c8bbb4a8a7a4a49c968c837969614b45382819090000000000000000031629395b71869bb0c5af9a8570606265676a6d6f727477797c7e818178625846331f0a000000000000000000000000000000000000000000000000000000000417293a4d5f6e8399a9bac6b49f8b78624d3929160300000000000000000000000000000000000009192d3e4c6176889db3c0b8a697826d5d4b38271502000000000000000000000000000000152a40556a7f95aabfbaa88a75604b35200b0000000002112230414f616b8096a0b4ab9d8772594834200b0000000000000000000000000b2035485a6d8297aabbb6a4917c675443301c08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c171f21252727211e160b00000000000000010f1a2123262524211e16100b0801000000000000000000000000000000000000000000000000000000000b1b2832424e58616a73797d818383827f7c77707b90a6b7b6a48e79644e39240f00000000000000000000000000000000000d22374c62778ca6b7c4af9a856f5443301c08000000000000000000000000000000000000000000000014293f54697e94a9beb49f8a75604b3520122232424b60728399a3b5c3b5a3988272604a41312111000000000000000000000000000000000d22374c62778ca7b8cccec9bdbcc2b6b1ab9f988b7f6e605645372715010000000000000000192e43596e8398aec3b29d887375787a7d7f828487898c8e919396968776614c36210c00000000000000000000000000000000000000000000000000000000000c1c30414d62788a9fb4c5bbaa96806b5746321e0a00000000000000000000000000000000000000101f334658677d92a2b4c4b59f8d7b655645311d0e00000000000000000000000000000014293f54697e94a9bec6a18b76614c36210c0000000010202f404d5f697f949eb0beb6a58c77624d37220d00000000000000000000000005192b3c4d63788b9fb4c2b19c8673604b36261401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c171f212933373a3c3c3632281b0b000000000006131f2c35383c3a3936322826201d150903000000000000000000000000000000000000000000000000000b1b2939464b6068767f878e939798999895918b85859bb0c4b19c86715c4a36220d00000000000000000000000000000000000b1f34475973889db2c8b49e8974604b35200b0000000000000000000000000000000000000000000001162c41566b8196abc0b39d88735544311d2030404f616c8196a1b3c1b7a59b857460544330231303000000000000000000000000000000000b1f34485973899eb3bac7b7b7babfc6c9bcb4aa9f948374605544311d130000000000000001162c41566b8196abc0b59f8d888a8d8f9294979a9c9fa8a4a6a9aba5947f6a543f2a15000000000000000000000000000000000000000000000000000000000000122035485a6b8095a7b8c8b39e8976614b362110000000000000000000000000000000000000000417293a4d5f6f849aa9babcab9c8674604b3d2c1a06000000000000000000000000000013293e53687e93a8bdb7a28c77624d37220d0000000e1e2e3e4c5e677d8d9fb5bcbaa99d8775604b36200b000000000000000000000000000e2035495a6d8298abbcb6a4917c675443301c08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000131c2933363a474c4f51514b4639281b0b000000001324313d494e51504e4b45383b3531271e170b0000000000000000000000000000000000000000000000091929394657616e7e89949da5a8acadaeadaaab9f9a9ba3b4c1aa947f6a553e2d1b07000000000000000000000000000000000005182a3b596f8499aec4b9a88e79634e39240e0000000000000000000000000000000000000000000003192e43586e8398adc3b19b86715c37271e2d3e4c5e697e939fb0bfb9a89d877762564536251305000000000000000000000000000000000005182a3b566b80959fa9a2a2a2a5a9b1b6c2c8bbb4a1998373604b41301d0c0000000000000014293e53697e93a8bebcab9f9d9faba5a7aaacafb1b4bac6bbbec3ae99846f59442f1a04000000000000000000000000000000000000000000000000000000000005192b3c4b6176899eb3c5b9a7937e69533e2d1b07000000000000000000000000000000000000000c1c30414e63798b9fb4c3b6a4957f6a5b49352113000000000000000000000000000012283d52677d92a7bcb8a38d78634e38230e000005192b3c4a5c667c8c9fabbcbcab9f8b7a645645321d090000000000000000000000000006192c3c4e63798c9fb4c2b19c8673604b3626140100000000000000000000000000000000000000000000000000000000000000000000000000000000000008131c303a464c545861646767615746392816030000091931424e5b63666563605657504b443733291b13040000000000000000000000000000000000000000011426374657617583939ea7b2b7c3c1c2c3c2c9bcb4b0b0b4c1b5a38d78624d38231507000000000000000000000000000000000000152b40556a8095aabfc6a8937d68533e281300000000000000000000000000000000000000000000001325365b70859bb0c4ae99846f59442f2b3c4a5c667c8d9fb4bdbcab9e8a7a64594838281808000000000000000000000000000000000000000d20354b6073818a8d8d8d8d8f949ca4b2b7c4bfb3a197826d5f4d3b2a180400000000000011263b51667b90a6bbc9bcb5b2b4bcc9bcbfc2c4c1bec8bbb4b2afab98836e58432e19030000000000000000000000000000000000000000000000000000000000000e1e3346576a7f94a7b8c5b29c87725c4a36220d0000000000000000000000000000000000000000132135495b6b8095a5b6c2b49f8b79634e41311c0c0000000000000000000000000012273c51677c91a6bcb9a48e79644f39240f00000b2035485a647a8a9eaabbbcb49f8d7c665c4b3828150200000000000000000000000000000e2135495b6e8398aebfb6a4917c675443301c08000000000000000000000000000000000000000000000000000000000000000000000000000000000008182530414d58616971767a7c7c75615746321e0900021527374e6068797b7a7976716c6560554b4639301f170c00000000000000000000000000000000000000081d31445561758498a0b3b8c5c9c1c7bab4b4bbc8c9c5c5c8c6b09b867160504333251404000000000000000000000000000000000011263c51667c91a6c5c2ad97826d583c2b1909000000000000000000000000000000000000000000071c30435472889db2c1ac97826c573f2f3a485a647a8a9fabbcbdb49f8d7c665c4a3b2a1a0a0000000000000000000000000000000000000000081d314455606c75787878787a7f86919da6b4c0bfb1a0917d675947341f0c0000000000000e24394e63798ea3c5d5cfcac8c2bfc9bcb5b2afaca9a6aa9f9d9996907c66513c271100000000000000000000000000000000000000000000000000000000000000031729394b6176899eb3c8b6a48e79644f3924100000000000000000000000000000000000000000061a2c3d4b6075879db2bfbaa99a846f5f4e3a2a180400000000000000000000000011263b51667b90a6bbbaa5907a65503b251000000d22384d6278899ea8b9beb09e937e695e4c3e2e1a0a000000000000000000000000000000061a2c3d4e64798ea1b3c2b19c8673604b3626140100000000000000000000000000000000000000000000000000000000000000000000000000000000132536434a5f67767f868b8f91918675614b36210c00081d314455687e8c918f8e8a86817b746961574d41332a1c0f0100000000000000000000000000000000071b2d3e4b6073839aa2b2bfc6bab4aca5a99f9faaa8b4b9c6d7cab49f8c7e6a61504332221201000000000000000000000000000000000d22384d62778da6b8c7b19c87725a483727150100000000000000000000000000000000000000000b20354a60758a9fb4bfaa95806a5d4b3c46586278889da8bac0b19f937e695e4c3d2d1d0d00000000000000000000000000000000000000000001152737444b566063636262656a717c889ba2b4c1beb39e8977614c3a2a170400000000000c21364b61768ba7b8ccc6b9b4ada9a6ab9f9d9a9794918d8a8784817b665e4c39240f00000000000000000000000000000000000000000000000000000000000000000b1e3246576b8095aabbc3ab96806b563e2d1b0700000000000000000000000000000000000000000f1e324556667b90a0b2c6b4a2927d685847331f1100000000000000000000000010253a50657a8fa5babba6917b66513c2611000013283d53687d92a7b9c0b2a096806b604e4030201000000000000000000000000000000000000f21364a5c6f8399aec0b6a4917c675443301c080000000000000000000000000000000000000000000000000000000000000000000000000000000c1c304354606c7d89949b9faba6a4947f6a553f2a15000b20364b6074889daba5aa9f9c9690877f76675f4c473a2d1f10020000000000000000000000000000000d22364a5c6b8095a1b3c0c0b3a89f97908b898a8d939ea8b9cdcfbcab9f937f6a614f40301f0f000000000000000000000000000000000b2034485a73889eb3c8b59f8c78625544311d1200000000000000000000000000000000000000000d22374c62778ca9bac9b49f8a7b655a49556176869ca6b8c2b3a297816c614f402f1f0f00000000000000000000000000000000000000000000000919273138454b4e4d4d4d50545e6676849ba3b5c6b8a796816b5847331f0a0000000000091e32465773889eb3c8b9a89e9794918e8b8885827e7b7875726f6c655d4c40301d090000000000000000000000000000000000000000000000000000000000000000031629394d62788b9fb4c7b29d87725c4a36220d0000000000000000000000000000000000000000031628384c5e6e8398a8b9c0b39e8977614c3f2f1a0a00000000000000000000000f243a4f64798fa4b9bca7927c67523d271200000f24394e64798ea0b3b4a2988272604a42312212020000000000000000000000000000000000071a2d3e4f647a8fa2b3c2b19c8673604b36261401000000000000000000000000000000000000000000000000000000000000000000000000000c1c30414a607280929ea7b1b4bcc2b09a85705b45301b000e23394e63788ea6b8c8bbb4b1aca59d94887d6f61584a3d2e20100200000000000000000000000000091c2f404f647a8c9fb4bfbeb2a29a8a827b767475787e8a9eb4c9d9c9bcb49d947f695e4d3d2d1a0a000000000000000000000000000000061a2c3d5b70859ab0c5bcab9b8573604b40301e0e000000000000000000000000000000000000000f24394f64798ea4c7cdbaa89e897862576073849aa4b6c4b6a49a8473604b423222120100000000000000000000000000000000000000000000000009151d283236383838383a404c586175859ba8bac5b49e8a76614c37210c0000000000031628395b71869bb0c6b49e8a827f7c7976736f6c69666360565a56504b3f302212000000000000000000000000000000000000000000000000000000000000000000000b203448596f8499aec7b6a58e79644f39240f0000000000000000000000000000000000000000000a1a2f404d62778a9eb4c2b8a798826d5d4b38281602000000000000000000000e24394e63798ea3b8bda8937d68533e281300000d22364a5c6d82959d9f98847460544330241404000000000000000000000000000000000000000f22364a5c6f849aafc4b6a4917c675443301c0800000000000000000000000000000000000000000000000000000000000000000000000004182a3a4d5f6b80969eb3b9c5c4bec2b09b86715b46311c000e23384d63788da5b6c7bec1c6c3b7b2a69d928376635b4b3f2e2010000000000000000000000000000f23384c5e70859baabbc1b2a09884786c6560566063788da8b9cdc9c6c9bbb59f8d7c665b4a3828150200000000000000000000000000000c2135495b72889db2c7c9b4a296806b5e4c3c2c1a0a00000000000000000000000000000000000011263c51667b91a6bbd7c6b8a79c8675616d8298a2b4c2b8a69c8676615544312414040000000000000000000000000000000000000000000000000000010a161e212323232325303a475763798a9fb4c8b9a8947f69543a2a17040000000000192e43596e8398aec3b39e89746a676360575a5754514e4b4538413b372e21120400000000000000000000000000000000000000030a0c0d0b0700000000000000000005192b3b51677c91a9bac3aa947f6a55362513000000000000000000000000000000000000000000001220344859697f94a3b5c5b2a0907b655645321e0f000000000000000000000d23384d62788da2b7bea9947e69543f29140000071b2d3e4b60737f888982766156453625130600000000000000000000000000000000000000000c2035495a6f8499aec4c2b19c8673604b3626140100000000000000000000000000000000000000000000000000000000000000000000000a1f344759677d929eb0bdbfb3aea9a8a496816b56412c16000c2035495a72879ca9a9a9abb1b6c2c4b7b3a1998779645d4b3e2d1e0e000000000000000000000005182b3b50667b90a2b4c8b5a3988273625a504b45556a7f95aac6c2b5b1b5c2bcab9e8a79635645321d0f00000000000000000000000000000e23384e63788da5b7cbd1c0b09e917c665a4938281502000000000000000000000000000000000013293e53687e93a8bdd3d5c5b5a49983758095a0b2c0baa99e887862584637271506000000000000000000000000000000000000000000000000000000000003090b0e0e0d0d121c2939495b6b8096aabbc6b09a85705847331f0a0000000001162b41566b8096abc0b9a78c7761514e4b4539423f3c383631272c25231c1103000000000000000000000000000000000000060b161e2122201c130800000000000000000d21364b60768a9fb4c4af9a846f5443301c0700000000000000000000000000000000000000000005182b3b4b6073869babbcbeb29c8674604b3d2c18080000000000000000000d22374c62778ca1b7bfaa95806a55402b15000000101d314455606a73756d615847382818080000000000000000000000000000000000000000031729394d63788c9fb4cac9b6a4917c675443301c08000000000000000000000000000000000000000000000000000000000000000000000417293a4c6177899eb3bcbab4a1999493918676614c37220c0006192c3c50657b8b939493969ca4b0b4c0bfb3a59d897b645c4a3c2b1909000000000000000000000b203448596f8499afc0bbaa9b85736055483c364a5c72879cb1c7b5a49ca4b3c0b9a89c8674604b3d2c1a060000000000000000000000000114263653687e93a8c3d4dbcdbcb39e8978625645321d130100000000000000000000000000000000162b40556b8095aac0d5dfd2c2b3a19985959eafbebcb49f8b7b655a493a29190900000000000000000000000000000000000000000000000509080000000000000000000000000c1b2c3c4c61778b9fb4cab49f8b77614c37210c000000000014293e53697e93a8bec5a48f7a644f3a3632282d292623201d1517100e08000000000000000000000000000000000000000e192029323637353025180b00000000000000091e3245576f8499afc4b49e8974604a35200b000000000000000000000000000000000000000000000d1d314455647a8d9fb5c5b6a495806b5b493625130000000000000000000c21364c61768ba1c7c0ab96816b56412c1601000001142637444b555460544c473a291a0a0000000000000000000000000000000000000000000a1e3346576c8196abbccfd3c2b19c8673604b362614010000000000000000000000000000000000000000000000000000000000000000000a1f3347586c8196a7b8baa99f90847e7e7b74615847331f0a00000e23384c5d65787e7f7e81868f9aa2b4bbc3b7a79e8a7a645a48372715020000000000000000000d22374d62778b9fb4cab49f8c79645544372b394f64798ea4b6baa99c869aa2b3c3b5a495806b5b49362111000000000000000000000000081c3043546e8399aec3cfc6c3c6b9a79b8574604b41301f0f00000000000000000000000000000003182d42586d8297adc2d4cac7cabfb3a29aa2afbcbeaf9e927d675d4b3c2b1b0b000000000000000000000000000000000000000000090f111b1e1d15130d030000000000000000000e1f3447596f849aafc4bbaa917c66513c2611000000000011263b51667b90a6bbbca7927d67523d281e161714110e0b0902000000000000000000000000000000000000000000000e1e2c3539464b4c4a4336291b0b00000000000003162839556a7f94aabfb9a88d78624d38230d00000000000000000000000000000000000000000000011426374b5c6c8197a6b8c3b49f8b79635443301c0d00000000000000000b20354b60758aa9bac1ac97826c57422d1702000000091926313536434a433633291c0c000000000000000000000000000000000000000000001325364b6176899eb3c9d9dec9b6a4917c675443301c080000000000000000000000000000000000000000000000000000000000000000000c21374c61768a9fb4c3b49f8b7c6f6968666056473a2a18040000091c2f3f4c5a626869696c717a85939faab9c5b9a89d8878625544311d1000000000000000000013253653697e93abbcc1ac96816c5c4a37272c41566b8196abc2b49f8b76849aa5b6c2b49f8b79634e3f2e1c0800000000000000000000000b20354b6074899eb3c8bfb2aeb2bfb5a397816c5f4d3d2c1b0a0000000000000000000000000000051a2f455a6f849aafc4c3b6b2b4bbc0b4b0b4c0c1b2a095806a5f4d3f2e1e0e000000000000000000000000000000000000000004121d24263034322a28201507000000000000000004182a3a556a7f94aabfc8aa957f6a55402a1500000000000e23394e63788ea3c5bfaa95806a55402b1503000000000000000000000000000000000000000000000000000000000d1d2c3c494d5761626054463929160300000000000011263b50667b90a5bbc6a5907b66503b2611000000000000000000000000000000000000000000000009192e3e4c6176889eb3c0bbaa9a8472604a3b2a180500000000000000081d314455748a9fb4c2ad98836d58432e18030000000009141d2025303530251f170c00000000000000000000000000000000000000000000071c304354697e93a8b9ccdddbd3c2b19c8673604b36261401000000000000000000000000000000000000000000000000000000000000000316293952687d92a8bab7a5947f695e5453514b45382a1c0c0000000011212f3c494d535454565d65727e8c9ea7b9c6b7a69b8574604b3e2d180800000000000000071c3043546f8499aec9b5a38e79634e3d2d1932485d72879db2c8af99846f76879cabbcbbaa9a846f5d4b37231000000000000000000000000f243a4f64798fa7b8c5b2a098a0b2c0b19f927d675b493928160300000000000000000000000000031729395c71879cb1c6b6a59d9faabbc8c5c8c7b4a3988272604a41302110000000000000000000000000000000000000000007152230383c4549483f3c33251502000000000000000011263b51667b90a6bbc2ad97826d58422d1800000000000c21364b61768ba7b8c2ad98836d58432e180000000000000000000000000000000000000000000000000000000005182b3b495a636f767772615746321e0a0000000000000e23394e63788ea3b8bda7927d68523d2813000000000000000000000000000000000000000000000000101f334758687d92a2b4c8b4a2937e685947341f1100000000000000011426495e74899eb3c3ae99846e59442f1904000000000001080b131c201c13080400000000000000000000000000000000000000000000000b20354a6073879cb2c6d2c9c5c9c9b6a4917c675443301c08000000000000000000000000000000000000000000000000000000000000000a1e3246576f8499aec6b29d8774604b403e3c3632281a0c000000000003111e2b35383e3f3e3f4b5460697b899ea8b9c4b5a396806b5c4a362614010000000000000b20354a6074899eb3c5b09b85705b49361f1f344a5f74899fb3b7aa937d68657b8c9fb4c5b3a2907b65503e2d1b0700000000000000000002162838546a7f94a9c5b8a7988398a2b3bdb49e8a79635745321e13010000000000000000000000000a1e33465774899eb4c7b29d878c9fb4becfcebaa99b8574605443302313020000000000000000000000000000000000000000152533404c515a5e5d55504333201000000000000000000e24394e63798ea3b8c4af99846f5a442f1a0000000000091e32465773889eb3c5b09b86705b3a2917040000000000000000000000000000000000000000000000000000000b203448596378848b8c8575614b36210c0000000000000c22374c61778ca1b6bea9947f69543f2a140000000000000000000000000000000000000000000000000417293a4e5f70849aaabbc0b39e8977624c402f1b0a000000000000001e33485d73889db2c5af9a85705a45301b05000000000000000000070b0700000000000000000000000000000000000000000000000000061a2c3d51667b90a4b6cac1b5b0b5c1c2b19c8673604b362614010000000000000000000000000000000000000000000000000000000000000c21364b61768a9fb4c4aa957f6a5544312926211e160a00000000000000000e192023292a292e36434a5d657a8a9eabbcc1b49f8c7a645443301c090000000000000d23384d62788da7b9bfaa947f6a553d2c1a182d42586d82969ea69d8b77625d6b8196a7b8c0b09a85705c4a36220b000000000000000000091e3245566f859aafc4b39e8974849aa6b7b9a89c8675604b4231200f0000000000000000000000000c21364b61768ba8b9c1ac96817f94a0b2c2c9b49f8a776256453625130500000000000000000000000000000000000000000c1c3343505e667073726a61503f2e1b08000000000000000e23394e63788ea3b8c5af9a85705a45301b0000000000031628395b71869bb0c6b39e88735846331f0a0000000000000000000000000000000002040000000000000000000d22374c627788999fa3927d68523828160300000000000c21374c61768ca1b6bfaa957f6a55402a15000000000000000000000000000000000002090b1115120c0a0c1c31414e63798b9fb4c3b9a798826e5e4c392816030000000000081d32475d72879cb2c6b09b86715b46311c06000000000000000000000000000000000000000000000000000000000000000000000000000c2135495b6f849aafc3c7b5a39ba3b5c2b6a4917c675443301c0800000000000000000000000000000000000000000000000000000000000011263b51667b90a9bab7a68e79634e372715110b090200000000000000000000060b0d1314141825303f4b5c667c8d9fb4c0bcab9b8573604b37261401000000000011263c51667b91a6c5c6a6907b66513b26110b20364b607380898b887d67594b6176899eb3c5b4a28e79644f3929170300000000000000000b21364b60758a9fb4c3ad98836e77889dabbcb5a498826d604e3e2d1b0b00000000000000000000000e23394e63788ea3c6bfa9947f6e8298a4b5c5baa997816c604e3f2f1e0e0000000000000000000000000000000000000004172a3a50616a7c8589877f6a5d4b37220d000000000000000f24394e64798ea3b9c4af9a856f5a45301a000000000000192e43596e8398aec3b8a78b76614c36210c00000000000000000001080b0d1012151819110f0900000000000013293e53687e93a6b5ae98836e5645321e0e00000000000d22384d62778da2b7bfaa95806a55402b15000000000000000000000000000000000a151d20272a28211e17132136495b6b8095a5b7c5b2a0907b665745321e0f0000000000071c31475c71869cb1c6b19c87725c47321d0000000000000000000000050b0d1518160f0d0700000000000000000000000000000000000417293a4e63798c9fb5cabaa99b869ba4b6c2b19c8673604b362614010000000000000000000000000000000000000000000000000000000000152a3f546a7f94a9c7b29d88735b49361909000000000000000000000000000000000000000008131c2e3e4c5e6a7f94a2b4c7b5a3927d675544311d08000000000013293e53687e93a8bdbaa88c77624d37220d081d314455606b737673675f4d46576a7f94a7b9c0ad98826d5746331e0a000000000000000010263b50657b90a9bac2a7927d68657b8d9fb4c0b2a0927e685c4a392917030000000000000000000010263b50657b90a5babda7927d6875869ca7b8c7b19f937e685d4b3c2c1c0c0000000000000000000000000000000000000a1f3347586a80919a9e9d8f7a644f3a250f0000000000000012273c52677c91a7bcc3ae99846e59442f19000000000001162b41566b8096abc0c5a48e79644f39240f0001080b0d10131518141d202225282a2d2e26241d12040000000011263c51667b91a7b8b39e8975604b3c2c1c0e0300000214263650657a90a5babfaa947f6a553f2a150000000000000000000000000000000e1a2832363c403d3633291b1a2c3d4b6075879db2bfbeb29d8775604b3d2d180800000000061b30465b70859bb0c5b29d88735d482513000000000000000000000d1820222a2e2c24211a0f010000000000000000000000000000000a1f3346586c8197abbcc9b49f8b77869cb1c3b6a4917c675443301c080000000000000000000000000000000000000000000000000000000003182d43586d8298adc2ae98836e593d2c1a000000000000000000000000000000000000000000000011202f404b6073849aa9bac1b29c8773604b3520100000000000162b40556b8095aac0b49f8974594834200b02152737444b56566056524d41394b6176899eb3c9b49f8a76614b36210c000000000000000417293a566b8095abc7b5a48c77625d6a7f95a2b4beb49f8b7a645746331e140200000000000000000013283d52687d92a7bdbaa5907b656278899eaabbbdb49f8c7b655b493a29190900000000000000000000000000000000000c21374c61768b9fafb3aa95806a553a2917040000000000071a2d3e556b8095aac0c1ac97816c57422c1700000000000014293e53697e93a8bebca7917c67523c271618151d202325282b2d263135383a3d4042443c382f2212030000000b20364b6075899eb3b8a7947f695a493a2c1e171111161e3043546a7f95aabfc8a8937d68533e281300000000000000000000000000000e1e2c38454b5155524b46392d201e324557667c90a1b3c6b6a596806b5b4a36261401000000051a30455a6f859aafc4b49e89745443301c0700000000000000000d1d2b34373f434139362d1f120400000000000000000000000000011426364c61768a9eb4c9bfad97826d7d92a5b6c2b19c8673604b36261401000000000000000000000000000000000000000000000000000000021527385b71869bb0bfa9947f6a543f2a15000000000000000000000000000000000000000000000002111c30435463798b9fb4c5b6a4927d67523e2d1b0700000000172c41576c8196acc1b39e88735e3b2b180500091927313638454b45383a313246576c8297acc4baa8927d6852372715020000000000000a1f33475871869bb0c6b19c8671594b6072849aa6b8baa99c8776614c42322010000000000000000000152a3f556a7f94aabfc6a38e78635a657b8c9fb4bebbaa9e897963584637261401000000000000000000000000000000000d22374c62778ca6b7c4af9a846f5847331f0d00000000011121364a5c71869cb1c6c4a9937e69543e291400000000000011263b51667b90a6bbbfaa947f6a553f2a2b2d273135383b3d404237444b4d5052555759514c402f2111000000091d3245566c8197acbeb39e89786358493c3329262628323f4b6073879cb1c7bbaa907a65503b25100000000000000000000000000006192c3c495660666a6761574a3e2d1928394c5e6e8399a8b9c3b49f8c79635443301c09000000041a2f44596f8499aec4b49f8a75604a35200b000000000000000d1d2b3b484c5558564e4a3d30231200000000000000000000000000081c304354697f94a8b9c7b3a18e796374879cb2c4b6a4917c675443301c08000000000000000000000000000000000000000000000000000000091d31455674899eb3c9a6907b66513b261100000000000000000000000000000000000000000000000001142636495b6b8096a7b9c3b09b85705c4a36220800000000182d42576d8297acc2b29d87725d48321d00000009151d202832363228251e293950657a8fa6b7c6ae99846f5544311d080000000000000c21374c61768b9fb4c7ab96816b5643546277889dabbcb6a598836e604f3e2e1c0c0000000000000002172c42576c8197acc1baa88b76614c5d697f94a0b2c2b8a79c8676615544311d13030000000000000000000000000000000b1f34475973889db2c8b49f8a76614c3c2b1b100a090b151d30414e64798ea4b5c9b8a68f79644f3a240f0000000000000e23394e63788ea3c5c2ad97826d58423d404337444b4d505255585a55606265676a6d6e665e4c3f2e1c080000021528384f647a8ea0b2b9a79c8676635a4b46393b3b38454b5d687e93a4b6cab49f8a76614b36210c000000000000000000000000000c2035495a62747c7f7d75645c4a37261b2f404d62788a9eb4c2bbaa9b8573604b37271502000003192e43586e8398adc3bcab8b76614b36210c00000000000005192b3c4859626a6d6b645c4d41301d0a0000000000000000000000000b20354b6073879db2c6c2af9a846f5b687d93a6b7c2b19c8673604b3626140100000000000000000000000000000000000000000000000000000b20364b60758ba8b9bcab8d78634e38230e0000000000000000000000000000000000000000000000000008182c3c4c6176899eb3c7b4a38e79644e36261401000000182d42576d8297acc2b19c87725c47321d0000000002080b161e211e160a0b20354a6074889db2c8b49e8975604b36200b00000000000012273c51677c91abbcbaa9907b6550364859657b8d9fb4c0b2a0937e695c4b3a2a180800000000000004192f44596e8499aec3b49f897458464f616e8298a4b5c5b6a49a8373604b4231211100000000000000000000000000000005182a3b586d8398adc5baa9947f695a483a2d221f1d202731404d5f6f849aafc2c9b39e8874604b35200b0000000000000b21364b60768ba6b8c5b09a85705b505355585b55606265686a6d707275777a7d7f82837c665d4b37230e0000000a22364a5c6e8398a8b9b5a49c86786a61575451515256606a7b8b9fb4c2c0af99846f5746321e0a000000000000000000000000071a2d3d4d627886919592887a645544311d2034485a697f94a4b5c8b4a3937e695544311d08000003182d42586d8297adc2b7a18c77624c37220d0000000000000b2034485a62777f838179675f4d3924100000000000000000000000071a2d3d51667c91a5b6c9b5a4907b65506074879db2c4b6a4917c675443301c0800000000000000000000000000000000000000000000000000000d22374c62778ca1c6b49f8a75604b36200b00000000000000000000000000000000000000000000000000000e1e3346576a7f95a9bac1ac96816c5443301c08000000172c41566c8196abc1b29d88725d3b2b180500000000000003090b090300071c3043546d8297adc2b9a88f7a65503a2510000000000005192b3c576c8197acc9b49f8a75604b363b4b5d6a8095a2b4bfb49f8b7a645847362513000000000000021527375b71869bb0c6b29c87725d3a434b6075869ca7b8c2b3a196816c604e3f2e1e0e00000000000000000000000000000012273c52677c91a7b8c7b39e897862584a3e3734323637444b5e677d92a1b3c7bcab96816c5544311d08000000000000091e32455773889eb3c8b39d88736365686b6d707275787a7d808285878a8d8f929597998c7b654f3a2510000000071b2d3e4c6277899eb3bcb5a49c8a7f766d696666686c757f8c9fa9bac7b4a2907b6650392916030000000000000000000000000c21364a5b71869ca4aaa69d8773604b3520192b3c4b6073869cabbcc1b39e8975604b36200b000002172c41576c8196acc1b8a28d78634d38230e0000000000000d22384d6278889498968d7d67513c271200000000000000000000000c21364a5b6f849aafc3c4b19c86715e4c56697e93a6b8c2b19c8673604b36261401000000000000000000000000000000000000000000000000000e24394e63798ea3b8b39d88735645311d090000000000000000000000000000000000000000000000000000031729394c61768a9fb4c8b39d8874604b35200b000000162b40556b8095aac0b49f8974594834200b0000000000000000000000000013253652687d92a7c4c6a9947f69543f2a1400000000000b2035485a72879cb2c4af99846f5645322f3f4b6073849aa6b8bbaa9d8776615443301c110000000000081d31445573889db3c5af9a85705a453245576278899eaabbbfb09f937e685d4b3c2c1b0b00000000000000000000000000000b21364b6075889eb3c4b8a79b8576645c524c47454b4e55606a7c8c9fb4bfc5b59f8c79634e37261401000000000000031628395b70869bb0c5b8a68c76787a7d808285888a8d909295979a9d9faaa5a7aaacaa9a846f5a452f1a050000001020344859687d929eafbdb6a89f958a837e7b7b7d8188949faabac7baa99a84705e4c381b0b000000000000000000000000000e23394e63798ea4b5c3b6a58e79644e39240f1d314455657a8d9fb5c2b3a18b76614c36210c000001162b41566b8096abc6bfa38e79644e39240f00000000000014293e54697e93a6adab9a846f5a45301a0000000000000000000004172a3a4e63798ea2b4c8b8a6927d6852404b6075889eb3c5b6a4917c675443301c080000000000000000000000000000000000000000000000000010253a50657a8fa5bab09b86715b382715020000000000000000000000000000000000000000000000000000000b1f3347586d8297acc3b7a68f7a65503a251000000013293e53687e93a8bdbaa98c77624c37220d000000000000000000000000000d22384d62788da6b7c3ad98836e5836251300000000000d22384d62788da4b6c3a9937e695438281d3144556277889eabbcb7a5998372604a3f2e1d0d000000000b20364b60758a9fb5c2ad98836d58432839495a657b8c9fb4bebdb49f8c7b655a493929180800000000000000000000000000091e3245566a8095a6b7c5b4a39b867a6e6761595660636a747f8c9faabbccb9a798826d5b493519090000000000000000192e43596e8398aec3c4b59f8c8d909295989a9d9faaa5a7aaadafb2b4bbc8bcbfc8b39e88735e49331e0900000005182b3b4e606a80959fb4babab4a89f9893909092979ea6b4bbc8bcb49f8a7a644e402f1c000000000000000000000000000010253a4f657a8faabbcbbcab907b65503b26101527374b5d6d8297a6ada499836f5846331f0a00000014293f54697e94a8b2b1a18d78634d38230e000000000002172c41576c8196acc5af9a85705a45301b000000000000000000000a1f3347586d8297acc0c7b39d8875604b3645566a7f94a7b8c2b19c8673604b3626140100000000000000000000000000000000000000000000060a16263b50667b90a5bbae99846f59442f1a0000000000000000000000000000000000000000000000000000000004172a3a4f647a8fa5b6c4ab96806b563a2a1704000011263b50667b90a5c5c7a5907b65503b2510000000000000000000000000000b2035485a73889db3c7b19c87725443301c070000000013283d53687d92a8c3b7a58d78634e38231426374859657b8d9fb5c0b3a1947f6a5d4b3b2a19090000000d22384d62778dabbcc0ab96806b56412b2b3c4c5d697f94a0b2c2bbaa9e897862574636261401000000000000000000000000031628384b6175889dabbcc1b4a49c8d837c77747475797f86959faabbc8bbb39e8977624d3d2c1a000000000000000001162b41566b8096abc0cfbcab9faba5a8aaadb0b2b4bbc8bdbfc2c4c1bec7bab4b1aeaa9c86715c47321c07000000000d1d314150616c81929fa9b5c1bab4ada9a6a6a7acb3b8c4c5b8ab9f927d675c4a36221100000000000000000000000000000c21374c61778a9fb3b7b29f8b77624d37220d09192e3f4c6176879697938677624d3a2917040000000c22374c61778a999d9c958372604a35200b000000000004192f44596e8499aec3ad98836e58432e19000000000000000000011527374c61778a9fb4c9baa9947f6a564532384b6176899eb3c6b6a4917c675443301c080000000000000000000000000000000000000000070e192128323c51667b91a6bbad97826d58422d1803000000000000000000000000000000000000000000000000000000000c22364a5c72879cb2c6b19b86715847331f0a00000d23384d62788da6b8bfa9947f6a543828160300000000000000000000000005192b3c5b70869bb0c5b49f8a75604a35200b000000071a2d3d586d8398adc2b29d87725b49352109192b3b4c5e6b8095a2b4bfb49f8c7b6559483726140100000f253a4f647a8fa4c9bea9947e69543f291e2f3f4f616e8298a3b5c5b8a79c8675615443301c13030000000000000000000000000a1e324657667c8d9fb5bcc2b6ab9f99918c8a898b8e959ca4b4bbc8bcb49d917c675948341f0f00000000000000000013293e53687e93a8c4d4c9bcb5bcc9bdc0c2c5c5c2bfc9bcb4b2afaca8a5a99f9c98958f7e68533e29130000000000001323334351626c7e8b9ba3b1b5c2c2bebbbbbdc1c8c7bab4a79e8d7f695f4d3d2d1a0400000000000000000000000000000a1f3347586b80949ea69d94806b594834200b00101f334758627780827e74625948341c0c000000000a1f34475963798388877f74605443301c070000000000031628395c71869bb1c0ab96806b56412b16000000000000000000081d3144556a7f94a9bac9b49f8a77614c38283346576a8095a8b9c2b19c8673604b36261401000000000000000000000000000000000008131c202c3538454b52677c91a6bcab96816b56412c160100000000000000000000000000000000000000000000000000000000071b2e3e556b8095aac6b59f8b77614c37210c00000b2035485a73889eb3c4af99846f5645321e0900000000000000000000000000192e43596e8398aec3baa98c77624c37220d0000000c21364a5b73889db3c8ac97826c573d2c1a060d1d2f404b6073849aa7b8bbaa9d8877625544311d08000012273c52677c91a7bcbca7917c67523c27122132434b6075859ba7b8c5b6a4998372604b41312110000000000000000000000000031629394c5e6a80959eb4bac7bcb5aea7aa9f9ea7a3aab1b6c2c4b7ab9f937f695f4d3b2b180100000000000000000010253a4f657a8fa6b7caccc9c6c3c0bdc5b8b3b0ada9a6ab9f9d999693908d898683807a68604e3b261100000000000005152534445160687a85919ca4aaafb3b8c4c4b8b3afa99f96897c69614f41301f0f00000000000000000000000000000004172a3a4a60727f888c887f6b62513b2b18050004172a3a4759626b6d686056483b2b18000000000004182a3a4a5b636e73716a605645362513000000000000091e32465773899eb3bea9937e69543e29140000000000000000000b20354b6074879db2c7bcab97816c5847331a29394c61768a9eb4c7b6a4917c675443301c08000000000000000000000000000000000c182530353c494d566068707e93a9beaa947f6a553f2a1500000000000000000000000000000000000000000000000000000000000010253a4f657a8fa8b9bcab917b66513c2611000006192b3c596f8499aec4b49f8a75604b36210e00000000000000000000000001162b41566b8096abc0c7a38e79634e39240e0000000e24394e63798ea6b7bbaa917c67513c27120000111d3144556277899eabbcb7a69a8473604b35200b000014293f54697e94a9bebaa48f7a654f3a2510151e3245576278899eaabbc2b3a196806b604e3f2e1e0e0000000000000000000000000b1b2f4050616b80939fa9b3bfc6c3c8bbb4b3b9c5bfc7c6b9b4a69d8d7e69614f40301d0d000000000000000000000b20354b6074889db0b4b9b3b1aeaaa7a4a79e9b9794918e8a8784817e7b7874716e6b645d4e42311f0b0000000000000007162634424e5c64707c868e959a9da6a2a1a69d99938a8176665e4f4332231301000000000000000000000000000000000c1c304354606a74777469615144341d0d0000000c1c2a3b474c5658534b45382b1d0d0000000000000c1c2d3d4a4e595d5c554b45382818080000000000000c21364b61768ba7b8bca6917c67513c27120000000000000000071b2d3e51677c91a5b7cab59f8c78634e3a2a171f3347586b8096a9bac2b19c8673604b3626140100000000000000000000000000000c1c2a36434a515b636b757d85939caebea8937e69533e29140000000000000000000000000000000000000000000000000000000000000b20354b6075899eb3c9aa957f6a55402a1500000014293f54697e94a9c3baa9927c67523c2b1906000000000000000000000000152a3f546a7f94a9bfbaa48f7a654f3a251000000115273754697e93a9c4b49f8b76614c36210c0000011426374859667c8d9fb5c0b4a2947f6a553f2a150000162c41566b8196abc0c5a28d78624d38230d03162839495a657b8c9fb4bebfb09e927d685d4b3c2b1c0c0000000000000000000000001222334351626b7e8b99a1abb1b5bcc9bbbcbbc5b8b3aea89e95887b69604f433222120000000000000000000000081d314455677d919b9fa89e9c9895928f8c8885827f7c7976726f6c696562605459554f4b3f312414020000000000000000081624313e4a4e5e6671797f85888b8c8c8c88847e766c61584d4032251405000000000000000000000000000000000000132536434a54606160544f4334261600000000000d1d2a343741423e3632281a0d00000000000000000f1f2d3639444847403632281a0a000000000000000e23394e63788ea3c5c9a48f7a644f3a250f00000000000000000d22364a5c70859ab0c3c1ae99836e5b49351c0c172a3a4c62778a9fb4c8b6a4917c675443301c080000000000000000000000000004172a3a475460666f788189929ba3aebbbca7927d67523d2812000000000000000000000000000000000000000000000000000000000000081d3144556f849aafc3ae99846e593727150200000e23394e63788ea5b6c7af9a846f5a4835200d000000000000000000000000152a3f556a7f94aabfbaa5907b65503b26100000081d3144556f8499aec4b09b85705846331f0a00000009192b3b4c5e6b8096a2b4c0b09b86705b46311b0600192e43586e8398adc3b8a78b76604b36210b000a1b2b3c4c5d697f94a0b2c1bcb49f8b7b655a483a2a17040000000000000000000000041525344451606879838e959c9faba5a5a6a5a3a79e9992898076655d4f42322515040000000000000000000000011527374d5f677c868a8a898683807d7a7673706d6a666360565a5753504d4a4336403a372e201406000000000000000000000613202d36404d515b636a707376777776736f6861584c473a30221406000000000000000000000000000000000000000818253036434a4c4b4336322516080000000000000d181f222b2d29211e160a000000000000000000010f1a21242f33322a201d150a000000000000000011263b50667b90a5bbbcab8d77624d38220d0000000000000004182a3b4f64798ea2b4c8b5a38f7a65503d2c1a000c1f3447596c8196aabbc2b19c8673604b35200b000000000000000000000000000a1f33475861727c848c969ea7b0b4c1c7c1a6917c66513c271100000000000000000000000000000000000000000000000000000000000001152737566b8095abc0b29d87725544311d0800000c2135495b72879cb2c7b59f8c78624d3b2a18050000000000000000000000152a3f556a7f94aabfbaa5907a65503b251000000b20354b6075899eb4c5aa957f6a553a291704000000000d1d2f404b6073849ba7b2a697826d57422d1802001b30455b70859ab0c5b39e89735645321e0900000e1e2f3f4f616d8298a3b5c5baa99e8878625847331f0a00000000000000000000000007162634424e5b636e7980868b8e8f9091908e8c88837d756b61584c3f3224150700000000000000000000000000091930414d5f6771757574716e6b686461585b5854514e4b4538413e3b383530252b25221b100200000000000000000000000002101b2230393d494e555a5761626261585a534c473a332a1c120400000000000000000000000000000000000000000008131c253035373530261814070000000000000000050b0d1618130b0902000000000000000000000000070c0e191e1c150b090200000000000000000013283e53687d93a8bdb49f8a75604b35200b000000000000000b1f3447596d8298adc0c3b09b85715d4b371f0e0005182a3b4d62788b9fb4c8b6a4917c6752362614010000000000000000000000011426374c617685919a9fabb3b8c5c3b7b2aca3907b65503b26100000000000000000000000000000000000000000000000000000000000000012273c51677c91a6bcb49f8a75604b36200b0000061a2c3d556b8095aac0bcab95806b5947341f0e0000000000000000000000152a3f556a7f94aabfbaa58f7a65503a2510000010253a4f657a8fa8b9b8a78f7a644f3a240f000000000000121d3144556278899b9d988878624d38220d00001d32475d72879cb2c6b19c86715c38281602000000112132434b6075859ba7b8c7b8a69c8676614c37210c00000000000000000000000000081624313d494e5b636b7176797a7b7c7b7977736e6761574c463a2f211406000000000000000000000000000000132330414d515b5560555c5955524f4c473a423f3c393632282c292622201c13160f0d080000000000000000000000000000000007121d242c36394039464c4d4c4c473a3e37332a1f170c0000000000000000000000000000000000000000000000000008131c2022201c14080000000000000000000000000001030000000000000000000000000000000000000004080700000000000000000000000000162b40556b8095aac0b29d88735544311d08000000000000021527374c61778a9fb4c9b7a5927d67523f2e1c0000000d2034485a6d8297aabbc2b19c86715443301c080000000000000000000000081d3144556e8398a3afb5bcc1b4b0a9a59d97908574604b36200b000000000000000000000000000000000000000000000000000000000000000f24394e64798ea3c6bbaa8d78634d38230e0000000f23394e63798ea2b4c9b49e8a77624c3c2c190600000000000000000002172c42576c8197acc1c7a38e79644e39240f0003162939556a7f95aac6b39e8974604b35200b00000000000001152737485a647a85878278625a4834200b00001a30455a6f849aa8adac9a846f5a452f1a0000000003141e3245576278899eaabbc5b6a4927c67523d2712000000000000000000000000000006141f2c353d494e565760646566676663615859524b463933291b11030000000000000000000000000000000005132330393c37444b443743403d3a37332a2d2a2724211e161714100d0b070000000000000000000000000000000000000000000000090f1a21232a293336373737332929211f170c0400000000000000000000000000000000000000000000000000000000070b0c0b0801000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003182d43586d8298adc2b09b86705b37271501000000000000081d3144556a7f95a9bac6b29d8774604b35201100000005192b3c4d63788b9fb4c2b49f8a75604b35200b00000000000000000000000b20354b60758a9fb4c1cac8b4a39b938d87817b73605645321d09000000000000000000000000000000000000000000000000000000000000000c21364b61768ba8b9c8a5907b66503b26110000000c2136495b70859ab0c3b9a897816c5a4935201402000000000000000005182b3b5a6f859aafc4baa98c77624c37220d000a1e32465770859ab0c3ad98836e5443301c080000000000000009192b3c4a5c6470726d625a483c2b190500000f253a4f647a8a9498968f7e68533d2813000000000003162839485a657b8c9fb4beb8a7917b66513c2611000000000000000000000000000000010f1a212c353939454b4e505051504e4c473a3d3632281f170b0000000000000000000000000000000000000004121d242726313531262e2b2825211f171815110e0b090200000000000000000000000000000000000000000000000000000000000000060c0e15171e212222211f17130c0a040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011426365a70859aafc3ae99836e59442e19000000000000000b20364b6074889db3c7b9a8947f695544311d08000000000d2035495a6d8298a7aca498836e5443301c0800000000000000000000000c21364b61768ba5b6cadbc5b09b857f79726c666055453828150200000000000000000000000000000000000000000000000000000000000000091e32465774899eb3bda7927d68523d2813000000061a2c3d51677c91a4b6c6b49f8b78634d4231201000000000000000000b2034485972889db2c7b49f8a75604b35200b000c21364b61768a9fb4c0a8927d68533626140100000000000000000d1d2d3e4a4e5b5d584d483c2b1d0d0000000d22374b5c64777f83817a68604e3a26110000000000000a1b2b3c4b5d697f94a0b2aa9e8876614b36210c0000000000000000000000000000000000060f1a2123283236393a3b3c3b3937332a28211e160b04000000000000000000000000000000000000000000000a1012141d201d141916130f0c0a04000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a0c0d0d0c0a04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008080200000000000000000000000000000000000000081c30435472879db2c1ac96816c57412c17020000000000000f253a4f647a8fa6b7c6b49e8976614c372715010000000006192c3c4d6379899697938677624c3626140100000000000000000000000a1e33465772879cb2bcccc8b39d887b6b6055504b4437281a0a0000000000000000000000000000000000000000000000000000000000000000031628395d72879db2bea9947f69543f2a14000000000f20354b6073879cb2c1bbaa9a846f604e3e2d1d0d000000000000000d22374c62778b9fb5c6b19c86715544311d080010253a50657a8fa9b7b4a28c77624d37220d0000000000000000000010202d363946484338352b1e0e00000000081b2e3e4b59616a6d6c645c4e42311e0b000000000000000e1e2f3f4f616d82979d9a8c7c665746331e0a00000000000000000000000000000000000000060c0e161e21242526272624211f17120c090300000000000000000000000000000000000000000000000000000001080b080100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b11131d1e170c0a04000000000000000000000000000000000b20354b60758a9fb4bea9947f69543f2a14000000000000000d23384d62788da0b1b3a896816c58463319090000000000000e2135495b637981827e756259473418080000000000000000000000000317293953687d929eb3b9c6b7a69d8d80746259493d2c1b0b000000000000000000000000000000000000000000000000000000000000000000001c31465b71869bb0c0ab95806b56402b1600000000081d314455677c91a3b5c8b4a2937e685c4a3b2b1c0e0000000000061a2c3d53687e93abbcc2ad98836d5837261401000d22384d62788b9da5a49a8470594834200b0000000000000000000002101b222430322d2220190e00000000000010202e3b474c5558574f4b3e312413020000000000000000112132434b60758288857a665e4c392917030000000000000000000000000000000000000000000003090b0f101112110e0c0a040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080b0f121313110e0b0801000000000000000000000000000000000000000000000000000000000000000000000000000000000006131e262832332d211f170c0000000000000000000000000000000d22374d62778ca9babca7927c67523d2712000000000000000b2035485a6d82939b9d9a8a78624d3a29170000000000000006192c3c495b636c6d686057473b2a1800000000000000000000000000000b263a4e606b80919ea8b5c1b7ab9f968577635b49392916030000000000000000000000000000000000000000000000000000000000000000051a2f445a6f8499afc1ab96816c56412c1700000000011426374a6072859baabbc0b49f8b7a6459483a2b1e11050000010f2136495b6f849aafc9c2a8937e68533e291300000b2035485a667c878d8d8679634e3b2b1905000000000000000000000000070d0f1b1d180d0b050000000000000002101d2a34373f43413a372e20130600000000000000000003141e324557606d7270645d4c40301b0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c0e12141514120e0b070000000000000000000000000000000000000000000000000000000000000000000001080b151d20242729282623201c1408080000000000000000000000000000000000000000000000000000000000000000000000000000011324313a3d48484237332a1c0c00000000000000000000000000000f253a4f647a8fa4c7baa58f7a65503a25100000000000000006192b3c4a60727e8688847b655a48341b0b00000000000000000e1e2c3c494d5757534b45392a1d0d00000000000000000000000000000b1e314251626b7d899ba3b1bdbcb5a39b8779635746321e0a000000000000000000000000000000000000000000000000000000000000000004192f44596e8499aec1ac97826c57422d170000000000091c304354647a8c9fb4c2baa99d87776259483c2f20180e0d121f2f404e63798c9fb4cab5a48d78634e38230e000005192b3c4c5e6673787871635b49351d0d000000000000000000000000000000000608030000000000000000000000000c181f222a2e2c25221b1002000000000000000000000003162839454b585d5a4f4b3f302212000000000000000000000000000000000000000000000000000000000000000000000000040a0c0b0902000000000000000000000000000000060c0e171a160f0d0700000000000000000000000000000000000000000000050b0e19202327292a292723201c13080700000000000000000000000000000000000000000000000000000000000009141d202731363a3c3e3d3c38353026231c11070000000000000000000000000000000000000000000000000000000000000000000000000f1f31424e535d5d574c473a2a1c0c0000000000000000000000000012273c52677c91a7bcc5a28d78634d38230e00000000000000000e1c304354606971736f655d4b3c2b19000000000000000000000e1e2c353841423e3632281b0d0000000000000000000000000000000213243444515f677885969fb3b9c1b4a69d8775614b36210c000000000000000000000000000000000000000000000000000000000000000004192e44596e8399aec2ad97826d58422d180000000000001325364a5c6b8196a3b5c6b7a69c8677625a4c3f342b232224303d4c5e6f8499aabbc7b19c86715b4935210c0000000e1e2f404c546063625a4e493d2c1a000000000000000000000000000000000000000000000000000000000000000000040b0c1518170f0d0800000000000000000000000000000a1b2832364248453a372e20120400000000000000000000000000000000000000000000000000000000000000000000070c171f21201d150a000000000000000000000000010f1a21232c2f2b24211a0f01000000000000000000000000000000000000030d1920222c35383c3e3f3f3c39353025221b1007000000000000000000000000000000000000000000000000000004121926313537444b4f525353514d4b4336372e211a0f01000000000000000000000000000000000000000000000000000000000000000000071a2d3d4e606872736c6158473a2a1704000000000000000000000000142a3f54697f94a9beb8a78b76604b36210b000000000000000000132536434a545c5e5a504b3f2e1d0d00000000000000000000000e1921232c2d28211e160a000000000000000000000000000000000006162634414d5a637481919ea8b5c2b7a5927d68523d2813000000000000000000000000000000000000000000000000000000000000000004192e43596e8398aec1ac97826c57422d1700000000000008182d3e4b6074859ba8b9c4b5a49c8678655d4d483b393739404c5b667c91a1b3c8baa9947f6a543d2c1a060000000012222f36434a4d4d493c352c1f0f0000000000000000000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000a161e212d333025221b1002000000000000000000000000000000060c0e110d0b06000000000000000000000008131c202a33373631271a150700000000000000000003111f2c363941444139362d1f1205000000000000000000000000000000000b171e2b34373c494d51545454524e4a4336362d211a0f0100000000000000000000000000000000000000000000000c171f2f37444b5155606467686866636054504b3f362d20150200000000000000000000000000000000000000000000000000000000000000000c21364a5b687e87888276615847331f0a000000000000000000000002172c41576c8196acc1b39e88735645321e0900000000000000000008182530353e4648453a372e211100000000000000000000000000060c0e1718130b090300000000000000000000000000000000000000081623303c4956606c7c899ca4b5c3a9947f69543f2a14000000000000000000000000000000000000000000000000000000000000000003192e43586e8398adc1ac97816c57422c1700000000000000101d32455663798a9eaabbc2b5a49c887b6d6259524e4d4e535e6679899eb3bfc5b49f8a77614c37220e00000000000412182530353838352b211a0f010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090b181d1b0f0d08000000000000000000000000000000020f1a2123262320190e01000000000000000008182530353a474c4b453833251504000000000000000011212f3d494e5759564e4a3d302312000000000000000000000000000004121b29333b484d555a6367696a69676360544f4a3e362d1f13010000000000000000000000000000000000000000010f1c2933404c5560666f75797c7e7d7b78746d655d4e4a3e331d150a00000000000000000000000000000000000000000000000000000000000006192b3c4e63798c9d9d978776614c37210c000000000000000000000004192f44596e8499aec3b19b86715c382816020000000000000000000008131c202931333025231c110300000000000000000000000000000000020200000000000000000000000000000000000000000000000004121e2c38454b5f6778869cb1bea8937e69533e29140000000000000000000000000000000000000000000000000000000000000000041a2f44596f8499aec0ab96806b56412b160000000000000002152838495b667c8c9fb4bbc2b6a69d8d82776e6763626368707c899ea7b9ccb8a796816c5847331f0a0000000000000008131c20232320190e0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003080500000000000000000000000000000000000a151d2c36393c38352b1d140900000000000000132536434a535861605650433322120000000000000008182f3f4c5b636c6f6b645c4d41301b0b0000000000000000000000000613222f39464c59626a72787c7e7f7e7c78746d645c4e4a3d311d140900000000000000000000000000000000000002101f2c3a474c5e66737c84898f919392918d89827b70645c504332281a0a00000000000000000000000000000000000000000000000000000000000b2035485a6e8398abb2a596816c56412c170000000000000000000000031628395c71869bb1c4ae99846f59442f1a00000000000000000000000000070b141c1e1a100e08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1a2832414d5a6c8197acbda8927d68533d28130000000000000000000000000000000000000000000000000000000000000000061b31465b70869bb0bfaa947f6a553f2a1500000000000000000a1a2c3d4c5e687e939db4bbc4b7ab9f978b837d7877797d85919ea7b9c5beb39e8977614c3a2a1804000000000000000000070b0e0d0b060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1a28323d494e514d493c312619090000000000071c30435460697376756a6250402f1c090000000000011426364c5d657981848079675f4d392816030000000000000000000006142431404c57616c787f878d91939494918e88827a6f635b4e4231261909000000000000000000000000000000000110202e3d4958616e7c8691999fa8a7a8a8a6a89e978f847a6a614b453828180800000000000000000000000000000000000000000000000000000004172a3a4d62788b9fb4c2ad98826d58432d180000000000000000000000091e32465773899eb3c1ac97826c57422d170200000000000000000000000000000007090500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a151d303c586d8398adbba6917c66513c2711000000000000000000000000000000000000000000000000000000000000000005182a3b5d72879db2bda8937d68533e28130000000000000000000f1f2f404e60697f939faab9c5bcb5aa9f98928e8c8e929aa2b3b9c5c0b2a0927d685847331c0c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002152838454b5b6366625a4b4437261401000000000b20354a60727e888c89806a5e4c38230f0000000000081c304354657b8b9699968b7d675746321e0900000000000000000003142432424e5e6676818b949ca4a6a9a9a9a7a69e978e847968604b44372614010000000000000000000000000000000f1f2e3e4b5b637683919ca4aeb4bac6bdbdc6b9b3ada29a8c7f6d6056453626140100000000000000000000000000000000000000000000000000000a1f3347586c8196aabbb5a4907b65503b261000000000000000000000000c21364b61768ba7b8bfaa957f6a55402a1500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021a2f44596f8499aec9a48f79644f3a240f00000000000000000000000000000000000000000000000000000000000000000b1f34475974899eb3c8a6907b66513b261100000000000000000001122231424f61697e8c9ea7b4c0c8bbb4ada7a3a2a3a8afb4c0ccc0b4a298826d604e3a2a18000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090b1216140d0b050000000000000000000000000000000000000000000000000000000000000000000000000000091d324556606e797b786d605544311d0800000000152a40556a7f939da69e907b66503b261100000000000b20354b6073879da9aea99e8975614b36210c000000000000000000112132434f60687c88969faab2b6c3bebfbec5b8b3aca19a8b7e6d605544311d1501000000000000000000000000000c1d2d3d4b5c64798798a0b1b6c2c9c6c1bfbfc3c8c9c0b4ab9f948274605443301c1300000000000000000000000000000000000000000000000000021628384c61768a9eb4c4b19c86715d4c38230e00000000000000000000000e23394e63788ea3c5bda7927d68523d281300000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c0f0f0c0a0400000000000000000000000000000000000000000000061b30455b70859ab0bcab8c77624d37220d00000000000000000000000000000000000000000000000000000000000000000d22374c62778ca8b9bbaa8e79634e39230e0000000000000000000004142432434f60687c899aa2b3b7c4c9c3bcb8b7b8bdc5c8c8bbb4a29a8475604b42311c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a151d20272b292220190e000000000000000000000000000000000000000000000000000000000000000000000000000b20364b6074828e918c8173604b35200b000000061c31465b71869bb0b7ab96816b56412c1601000000000e24394e63798ea5b7c7b9a88f7a654f3a251000000000000000000d1d2f3f4f61697e8c9da6b4bbc8c5bdb9b7b8bbc1c8bfb3a99f928173604b4333200f00000000000000000000000008182a3b4a5c647b899da5b2bec6c2b5b1acaaaaadb3b7c4c9bcb4a0988272604b41301d0d000000000000000000000000000000000000000000000000091e3245566a7f95a8b9b7a6927d68523f2f1c09000000000000000000000011263b50667b90a5bbbaa5907b65503b26100000000000000000000000000000000000000000000000000000000000000000000000000000060b171f212424221f180e0c0600000000000000000000000000000000000000071c31475c71869cb1b49f8a75604b35200b000000000000000000000000000000000000000000000000000000000000000011263c51667b91a6c6b49f8a76604b36210b000000000000000000000006142432424e5e667884929da6b1b5c2c2c5c7c7c5c8bbb4aa9f958475615745322313000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1a2731363c403e38352b1e0e00000000000000000000000000000000000000000000000000000000000000000000000014293e54697e93a0ab9f957f6a55402a15000000051a30455a6f859aafc2ad98836d58432e1803000000000f24394f64798ea7b8c7b8a68e79644e39240f0000000000000005182b3b4c5d697f929faab7c4c0b4b0a8a4a2a2a6acb4bac6bab49f97816c61503e2d180800000000000000000000011426364759647a899ea7b7c3bfb2aea49c979495989da6b2b6c3beb2a097816c5f4d3c2b190500000000000000000000000000000000000000000000011426364b6075889eb3c6b39d8874604b36201100000000000000000000000013283e53687d93a8bdc6a38e78634e39230e000000000000000000000000000000000000000000000000000000000000000000000000000e19202933363a3937332a2320190e010000000000000000000000000000000000081d33485d72889db2b39e88735544311d080000000000000000000000000000000000000000000000000000000000000003162839556a8095aabfb19c87715645321e0900000000000000000000000006142431404c5a62727d88939ca4a9adb0b1b2b0adaa9f998b8073615746392816050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1d2b38454b5155544d483c2b1d0d00000000000000000000000000000000000000000000000000000000000000000000001a2f455a6f849aafbcb19c87725c39291603000003182d43586d8298adc2af99846f5a442f1a05000000000b21364b6075889ea9b0ab9e8873604b35200b000000000000000b20344859657b8d9fb4bbc2b5b1a29a938f8c8d91979fa8b2bebeb19f947f6a5c4a36251300000000000000000000081c3043546177889da7b9c5b8b3a0988e86817f808388919da5b2bebfb19f927d675a4834201000000000000000000000000000000000000000000000081c304354687e93a6b8baa8947f6a5645311d09000000000000000000000000162b40556b8095aac0b9a88b76614c36210c0000000000000000000000000000000000000000000000000000000000000000000000010f1e2b353a464c4f4f4c473a38352c1d140900000000000000000000000000000000071c30435474899eb3b19b86715c3727150100000000000000000000000000000000000000000000000000000000000000091e3245576f8499afc2ad98826d5838281603000000000000000000000000000614222f3c48546068757e868d93989b9c9c9b97938b83796b60554639291b0a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005182b3b485660676b69625a483b2b1805000000000000000000000000000000000000000000000000000000000000000000001b30455a70859aafc5b49f8a745746321e0a000001162b41566b8096abc0b09b86705b46311b0600000000091e324556667c8a969b998d7c665443301c08000000000000071a2d3e4d6277889eabbcbeb2a39b8f857e7977787b818a98a0aebbbdb49f8c7a645443301c07000000000000000005192b3c4b6073849aa6b7c3b7a79e918379716c6a6a6e747c8798a0b1bebdb39e8978624d3e2e1b080000000000000000000000000000000000000000000b20354b6073879cb2c4b49f8a77614c38271502000000000000000000000003182d43586d8298adc2b49e89745746331e0a00000000000000000000000000000000000000000000000000000000000000000000000f1f2d3c484d586164646158564d493c312619090000000000000000000000000000000b20354a60758a9fb4af99846f5a442f1a00000000000000000000000000000000000000000000000000000000000000000b21364b6076899fb4c2a8927d68533d281300000000000000000000000000000004121e2b36434a56606871787e8286878785827e776e635b4b4437291b0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b2034485962747c807e7862594834200b000000000000000000000000000000000000000002090b0f0d0b0500000000000000192e43596e8398aec3bbaa8b76614b36210c000000142a3f54697f94a9beb29c87725d47321d0000000000021628384c5e66798186837b665e4c362614010000000000000d21364a5c6e8398a6b8bfb2a098857a7068646263666c7782939daebbbbaa9b8572604a35200d00000000000000000b2035485a697e94a2b4c4b7a59d897c6e635b575555556066758297a0b1c0b9a799836e5c4b37220f0000000000000000000000000000000000000000081c2e3f51677c91a5b6bcab97816c5847331a0a000000000000000000000000011426365a70859aafc5b19c87715c39291703000000000000000000000000000000000000000000000000000000000000000000000c1d2d3d4a5a626e76797977726c635a4b443726140100000000000000000000000000000c21364b61768babbcae98836e59432e1904000000000000000000000000000000000000000000000000000000000000071a2d3d51677c91a8bab6a48d78624d38230d00000000000000000000000000000000000e18253038454b535b63696d707272706d6862594e493d3126190b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d22374d6277869195938977624d37220d000000000000000000000000000000000000000a151d20242220180d040000000000172c42576c8197acc1c8a28d77624d38220d00000013283d53687d92a8bdb39e89735e3828160200000000000e1e2f404c5b636c706e655d4c40301808000000000000011426364e64798ea0b2c5b3a1988274645d534f4d4d5159626d7e939dafc0b4a2917c67513b2a1805000000000000071a2d3e4d62788a9eb4c0b8a69d8779665e4e4a3d3f37444b5760728297a2b4c5b3a18f7a644f3d2d1a07000000000000000000000000000000000000000e23374b5d70859bb0c3b49f8c78634d3a2a1700000000000000000000000000081c30435472879db2c4af9a846f5a452f1a0000000000000000000000000000000000000000000000000000000000000000000004182a3b4a5b6378838b8f8e8c8781786b605544311d1301000000000000000000000000000c21374c61768ca1b6ad98836e58432e19030000000000000000000000000000000000000000000000000000000000000b21364a5b6f849aafc6b19c86715a4935200b00000000000000000000000000000000000008131c2832363c494d54585b5c5d5b58534d483b362c1d1409000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000182e43586d8298a4aaa7947e69543f29140000000000000000000000000000000000000c1a2731363a37342b1f170c00000000152b40556a8095aabfb9a38e79644e39240f00000011273c51667c91a6bbb49f8a755645321e090000000006192c3c4a5c646d716f68605544311d1200000000000000081c3043546c8297acbeb9a79a837260564b3f3a37383b474c606a7f94a2b4c0ae99846f5948341f0b0000000000000d21364a5c6d8298a8b9bcab9e8878635b4c40362d2a26313945546073849aa8b9bfaf9a846f5b4a362109000000000000000000000000000000000000061a2c3d50657a8fa3b4c1ae99836e5b49351c0c000000000000000000000000000b20354b60758a9fb4c2ad97826d58422d1803000000000000000000000000000000000000000000000000000000000000000000091f344759637989999faba4a49c968c8073604b41311e0b000000000000000000000000000c22374c61778ca1b6ad98826d58432d180300000000000000000000000000000000000000000000000000000000000b1b2f404e63798ea2b4bcab957f6a553c2b190600000000000000000000000000000000000000000a161e212c35383e4346474746423e37342b211a0f01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b30455b70859ab0c2ad98826d5837261401000000000000000000000000000000000c1c2938454b4f4d483b33291c0c00000014293e53697e93a8bebaa5907a65503b251000000010253b50657a90a5babcab8b76604b36210b000000000c2135495b647a8286847d73604b3c2b19060000000000000b20354b6074889eb3c8b39e8976615445382e2422232a34424a6072859bb0c2b49f8b77624c37220d000000000005192b3c4e64798c9fb5c3b59f8d7b655a493d2f211a15141d2836445562788a9eb4c5b4a28e79634e3727150200000000000000000000000000000000000c2136495b6f8499aec1b5a38f7a65503c2c1900000000000000000000000000000d22374d62778caabbc0aa95806b55402b16000000000000000000000000000000000000000000000000000000000000000000091930404c6177879da7b4bcc3b6b2ab9f96826e5f4e3a250f000000000000000000000000000c21364b61768babbcad98836d58432e1800000000000000000000000000000000000000000000000000000000000818293a4c5e6f8399aec0b59f8c78634e38230e0000000000000000000000000000000000000000000003090e192123292d313232302d282220180d06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000182d42586d8297adc2b19b86715544311d080000000000000000000000000000000417293a4756606462594c463a291909000012273c51677c91a6bcbca6917c67513c27120000000f253a4f647a8fa4b9b6a18c76614c37210c000000000e23384d63788b989b9a92826d5a4835200b0000000000000e24394e63798ea6b8c6aa95806b584736281a100d0e181f304354657a8fa4b6bbaa927d68533d281300000000000b2034485a6e8398abbcb7a597816c5d4b3c2c1f120700010a182737485a697f94a7b8c0ab96816c5544311d080000000000000000000000000000000005182b3b4e63798c9fb5c3b09b85715d4b371e0e00000000000000000000000000000f253a4f647a8fa4c8bda8937d68533e28130000000000000000000000000000000000000000000000000000000000000000011527374c5e6f849aa5b7c5c2bec6c9bcb4a0927d68523d2c1a060000000000000000000000000b20354a60758a9fb5af9a846f5a3a2a17040000000000000000000000000000000000000000000000000000000a1826364658667b90a1b3c0af99846f5b4935210c00000000000000000000000000000000000000000000000000060c0e14181b1d1d1b18130d0b050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000152a3f546a7f94a9bfb49f8975604b35200b0000000000000000000000000000000a1f334758617479776e615846372614010010253a50657a8fa5babda8937d68533e28130000000e24394e63798ea3b8b7a28d77624d38220d0000000012273c51677c91a9b0afa08d78624d38230d00000000000012283d52677d92a7c5b9a88e79634e3a2a180a000000051325364b5d72879cb1c8ac97826c57422d1702000000000d22384d62788b9fb4c4b29d8775614b3f2f1e0e000000000009192b3c4b6075889eb3c8b39e8975604b36200b000000000000000000000000000000000b203448596d8297abbcb7a5927c67523f2e1c00000000000000000000000000000012273c52677c91a7bcbba6907b66513b26110000000000000000000000000000000000000000000000000000000000000000081d314455667c91a2b4beb2ada8b0b5c1beb19c86715b4935210c000000000000000000000000071c30435473889eb3b29d87725847331f0a00000000000000000000000000000000000000000000000000040f1a283643546176879db2bfb4a2907b66503d2c1a06000000000000000000000000000000000000000000000000000000000003060708060300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011263c51667b91a6c7baa98d78634d38230e0000000000000000000000000000071a2d3d4c6176868f8b8376615544311d08000e23394e63788ea3c9bfa9947f6a543f2a150000000e24394e63798ea3b8b8a38d78634e38230e0000000013283e53687d93a8c7bea5907b65503b2610000000000000152a3f556a7f94aabfb49e8974604a35200c000000000008182e3f576d8297acc2af9a846f5a452f1a05000000071b2d3e556a8095aabbb7a6927d685746322111000000000000000d1e3245566a8095aac1b8a78e79644f39240f000000000000000000000000000000031729394d62778b9fb4c6b29d8774604b352011000000000000000000000000000000142a3f54697f94a9bec7a38e79644e39240f00000000000000000000000000000000000000000000000000000000000000000b20354b6074879cb2beb2a098939ba3b5c9b6a48e78634e39230e000000000000000000000000001325365b70869bb0b59f8b77614c3721100000000000000000000000000000000000000000000000000c181f2d38455460728399a6b7bdb09a85705e4c381f0e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e23384e63788da9bac7a6917c66513c271100000000000000000000000000000921364a5b6c8197a49f988573604b35200b000c22374c61778cabbcc0ab96806b56412b160100000e24394e63798ea3b8b9a48e79644f39240f00000000152a3f556a7f94aabfc8a38e79634e39240e000000000001172c41566c8196abc1b29d87725443301c07000000000000142a3f54697f94a9beb09b86715b46311c060000000d22364a5c72879cb2c8b39d8875604b3929160300000000000000031628384e63788da3b5b5a48e79644f39240f0000000000000000000000000000000a1e3346576b8096a9bab9a8947f695544311d08000000000000000000000000000002172c41576c8196acc1baa98c77614c37220c00000000000000000000000000000000000000000002090b0c0b080100000005182a3b51667c91a4b6b2a098827e859babbcc2a7927d67523d281200000000000000000000000000182d42586d8297adbcab917c67523f2e1d1107000000000000000000000000000000000000000005131c2a343d4a5660728197a1b3c3b19f8f7a644f402f1c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010202000000000000000000000000000000000000000000000000000000000b20354b60748a9fb4bfaa947f6a553f2a150000000000000000000000000009192f404e63798c9fb4b5a3917c67523c2712000b20354b60758a9fb4c2ac97826d57422d180200000f24394e64798ea3b9b9a48e79644f39240f00000002172c41576c8196acc1bbaa8c77614c37220c000000000001162c41566b8196abc0b29d87725544311d08000000000000152a3f546a7f94a9bfb09b86705b46311b060000000f24394f64798ea5b6c1a9947f6a5645321b0b0000000000000000000a2135495b71869baba69c8673604b35200b0000000000000000000000000000021527384c6176899eb3c7b49e8976614c37271501000000000000000000000000000004192f44596e8499aec3b49f8a745847331f0a0000000000000000000000000000000000040b0c14151d2021201d1516110b0b1f3447596f8499aebcab98836e69778c9fb4bea9947e69543f29140000000000000000000000000014293e54697e93a9c3af99846f5d4b3b2e221b10020000000000000000000000000000000000031323313a474c5b637482979fb1bfb7a597816c5c4b3722110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080b0f1316181716120c0a040000000000000000000000000000000000000000000000081d31445571879cb1c2ad98836d58372614010000000000000000000000011426374c5e6f849aaabbb7a5927d67523d281200081c30435473889eb3c3ae99836e59442e1900000010253a4f657a8fa4bab9a48e79644f39240f00000003192e43586e8398adc3b49f8a75604a35200b000000000000152a40556a7f95aabfb49f8a75604b35200f000000000008182d3e566c8196abc1ae99846e59442f1904000000132536546a7f94a9c3b5a38c77624d38281500000000000000000000061a2c3d51667c8c94928779635443301c080000000000000000000000000000091d314556697f94a8b9bbaa96816c5846331909000000000000000000000000000000031629395c71869bb1c6b29d87725d3a2a1804000000000000000000000000000000070c181f222a283236363531272c26211e22374c62778b9fb4b59f8c79635973889db2bfa9947f6a543f2a15000000000000000000000000000e24394e63798ea5b7b3a18f7b65594b3f362e20160800000000000000000000000000000000112131414e59616c798698a0b1bdbaa99d8775614b3e2e1b040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090b141d2024282b2d2d2b27211f170c0700000000000000000000000000000000000000000001142637596e8398aec3b19c86715544311d080000000000000000000000081d314455667b90a1b3c1b29d8774604b36200b00011426365c71879cb1c5b09a85705b3d2d1a07000011263c51667b91a6bbb8a38e79634e39240e000000051a30455a6f859aafc4b29d88735443301c0700000000000012273d52677c92a7c3bbaa8f7a65503d2d1b0b000000081325364a5c71869bb1c8ab96816b56412c16010000071c3043546f859aafc4b19b86715948341a0a00000000000000000000000e24384c5e667a7e7d76635b4a3626140100000000000000000000000000001325364b6074889db2c6b49f8b78624d3a2917000000000000000000000000000000000a1e32465773899eb3c5af9a85705a45301b0000000000000000000000000000020f1a212a34373f38454b4c4b4437413b3632283d52677d92aabbaf9a85705b5d72879cb2c8a8937d68533e2813000000000000000000000000000c21364a5b72879db2bfb29d8777655d4f4a3e342616030000000000000000000000000000081c2e3f4e5f6877818b9ca4b2bebcab9f8a7a645746322010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a151d20263135393e404242403c37332a221b10040000000000000000000000000000000000000000162b40556b8095aac0b49f8a75604b35200b00000000000000000000031729394b6073869cb1bfb5a3927d675645321d0900001b30455a70859aafc5b39e89735b4a36210e000013283e53687d93a8bdc5a28d77624d38220d000000011426365c71869cb1c6b09b86715b362513000000000000000e23384d63788da5b6c8ac97826d5b4a39291b110f101825304354647a8ea3b5bbaa917c67523c27120000000b20354a6074899eb4bfaa95806a553b2b18000000000000000000000000091d2f404c5c64696861584a3d2d18080000000000000000000000000000071c304354687d92a6b7c0ae98836e5a48351b0b000000000000000000000000000000000c21364b61768ba7b8c2ad98836d58432e180300000000000000000000000009151d2d363b474c545a56606160555a56504b45383b586d8297adc3a8937e69535d72889db2bbaa907b66503b261100000000000000000000000000071a2d3d556a7f94a8b9b7a59d877b6e645c514534211100000000000000000000000000000e23374b5d687d89969faab5c2bbab9f8d7d675c4a39291602000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008141c27313637444b4e5356575755524c473a362e1f170c0000000000000000000000000000000000000012273d52677c92a7c9baa98d78634e38230e000000000000000000000a1e334657687e93a4b6bfb09b8572604a382815020004192e43596e8398aec3b8a78e79634e3c2c1a0a00132536556b8095aac0b9a78b76614b36210c000000081c30435473889eb3c4ae99846f59442f1a000000000000000c2035495a72879cb2c7b49f8c79635746392e2524262d36434a6072849aafc1b49f8b77614c37210c0000000e23384d63788da8b9c5a48f7a654f3a25100000000000000000000000000012222f3e4a4f54534c463a2d1f0f0000000000000000000000000000000b20354a6073869cb1c4b4a28f7a644f3c2b1900000000000000000000000000000000000e23394e63788ea3c5c0ab96806b56412b160100000000000000000000000c1927313d4a4e5961696f73757675736f6b6660564e495972879db2b7a58d78624d5c71879cb1b39f8b77614c37220c00000000000000000000000000000f22374c61778a9eb4c2b7a59d8d837a6c63513f2f1c080000000000000000000000000010253b50657b8d9ea8b4bbc4b8aa9f8d7e685f4d3e2d1b0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c18263038454b51556064686b6d6c6b6761584f4a3e33291c0f0100000000000000000000000000000000000f24394f64798eabbcc7a6917c66513c271100000000000000000006192b3c4c6176889eb3c2b2a18f7a655443301a0a000002172c41576c8196acc1c5ab96816c5a4938271a0f1c3043546e8499aec3b39e89745746331e0a0000000b20354b60758a9fb4c2ac97826d57422d180200000000000006192c3c556a7f95a9babbaa9b857561574b3f3a393b3d4a54606b7f95a2b4bfae99846f5847331f0a00000011273c51667c91a6c6b8a78c76614c37210c000000000000000000000000000412202d36393f3d3633291c0f010000000000000000000000000000071b2e3e51667b90a4b5c3b09b85705c4b371e0e000000000000000000000000000000000011263b50667b90a5bbbea9937e69543e291400000000000000000000000c1c2a37444b5b636d777f84888b8b8a8885817b756d635b61778ca5b7b29d87725a49556b80959e9e96826d5947341f0a00000000000000000000000000000a1f3447596a7f95a3b5c3b7ab9f998f816c5d4c38230e00000000000000000000000002172d42576c8297abb9c6bfb2a69e8c7e68604e4130201000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1c2a36434b5660666e74797d808282807c776e645c4c463a2d1f1002000000000000000000000000000000000b21364b60768b9fb5bfaa957f6a55402a150000000000000000000b2035485a6b8096a6b8bbaa99836e5d4b36251300000000152a40556a7f95aabfc9b49f8a78635645382d2524354a6074889eb3c6b19b86715c392917030000000c22374c61778caabbc0aa95806b55402b1600000000000000000e22374c62778a9fb4c3b5a39a8375655d54504f50545b637280959eafc0b3a18f7a65503a2a170400000014293f54697e94a9beb39e88735847331f0a000000000000000000000000000002101b22242928211f170c000000000000000000000000000000000d22364a5c70859aafc2b6a5917c66513e2e1b00000000000000000000000000000000000013283e53687d93a8bdbba6917c66513c2711000000000000000000000c1d2a3a4755606a79838a949a9ea6ab9f9e9a96908a82796a667b90a6c3ae98836e593c4b60748189898174604b3a2a1804000000000000000000000000000004182a3a4b6074859ba6b7c4bcb5ae9f907b65503b261000000000000000000000000004192e44596e8399aec2b5b1a199887b68604e4231231302000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1d2b3a47546068747c83898e9395979795918b837a6d61584a3d2d201000000000000000000000000000000000091e32455772879db2c3ad98836e583727150200000000000000081b2e3e4d62788b9fb4c5b49f8b78634d3f2e18080000000013293e53687e93a8bdcdbaa89a847460564a3d3a394150657a8fa7b8c2ad98826d58432d18000000000e23394e63788ea3c8bea8937e69533e291400000000000000000b1f3448596b8096a5b7c1b3a19a867b6f6965646569707984959eafbcb8a799836e5d4b371c0c00000001162c41566b8196abc0b09b85705b3a2a170400000000000000000000000000000000070d0f14130c0a040000000000000000000000000000000006192c3c4f647a8fa2b4c5b29c8773604b352010000000000000000000000000000000000000162b40556b8095aac0c8a48f79644f3a240f0000000000000000000a1a2a3b47586174808b989fa9afb3b8bcb5b3afaba89f978b7f758095aabea9947f69543f4556606c74736c605645321c0c000000000000000000000000000000000c1d3145566379889da6b2bfcabdab95806b56402b1601000000000000000000000000152b40556a8095a7afa49c918377655d4e4231241405000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1c2b3b485861737d8791999ea8a8abacacaaaa9f998f8276635b4a3e2d1e0e000000000000000000000000000000031628395a6f8499afc4b19c86715544311d110d0b05000000000a22374b5c6e8398a9bab9a796816c5b49352111000000000012273c51677c91a6bcd7c6b4a2988274635b534f4e505f6e8399aec5c2a8937e69533e29140000000010253b50657a90a5babba6917c66513c2711000000000000000005182a3b4b6175879da9babfb3a49c8f847e7a797b7e858c9aa2afbcbbaa9e8977624d3f2e1c0000000003182d43586d8298adc2ad98836e58432e1900000000000000000000000000000000000000000000000000000000000000000000000000000000000c2035495a6e8398aec0b8a7937e695443301c08000000000000000000000000000000000000182d43586d8298adc2bbaa8c77624d37220d0000000000000000021628384759617685959faab4bac7c3bfbfc0c5c4c6bab4aa9f9583839aafc4a5907a65503b38454b575e5e564b45382816000000000000000000000000000000000002152738495b647a8899a1aeb4bbab96816c56412c17010000000000000000000000000d22374c6277899a9a91867c6e62594b3f31241406000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000417293a4859627684929da5aeb4b9c6c0c2c1c8bbb4ae9f978779645c4a3c2b1a0a000000000000000000000000000000172c41566c8196abc1b49f8a75604b362a2622201917130f0c1a30414f647a8fa0b2c3b39e8976614c3c2c1903000000000010253a50657a8fa5bacfd1c0b2a09885796f686464666d7d92a1b2c6b5a48d78634d38230e0000000012273c52677c91a7bcb9a48f7a644f3a250f000000000000000006141e324657647a8a9fb4c9c2b6b1a29a948f8e90949a9fabb4c0b9aa9f8c7b6559483421110000000004192f44596e8499aec1ac97826c57422d170200000000000000000000000000000000000000000000000000000000000000000000000000000004182a3a4d63788c9fb4c8b39e8975614b362614010000000000000000000000000000000000001b30455b70859ab0c5b49f8a75604b35200b0000000000000000081e3245566177869ba3b4bbc6b9b4aeaaaaabb0b4bbc8c8bbb4a1999aa2b3b8a68c77614c37283236414949413632281a0a0000000000000000000000000000000000000a1a2c3d4a5c6476838f999faaa3927d67523d2712000000000000000000000000000b1f344859647a84847c73665e4d483b2e2113060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000091f3347586278879aa2b2b7c3c5c3b7b2b0b1b4bbc8beb1a59c897a645a4838281502000000000000000000000000000013283e53687d93a8bdbbaa8e78634e373f3b37342b2c28252128384d5f70859bb0beb7a5947f695847331e0e0000000000000e23394e63788ea3c8d9decfbfb2a39b8e847e7a797b828d9fb5bfc2b19c86715b4935210c0000000014293e53697e93a8bec6a28d78624d38230d0000000000000003142432434f5e6677859bb0c5d3cac0b4afa9a5a4a5a9b0b5bcc0b4a79e8c7d675d4b3b2b180300000000051a2f455a6f849aafc1ab96816c56412c17010000000000000000000000000000000000000000000000000000000000000000000000000000000a1f3447596c8197abbcbbaa95806b5746321808000000000000000000000000000000000000001d33485d72889db2c7b29d88735544311d080000000000000008182f404b6074859ba4b5c1bab4a89e999594969b9faab1bdccbfb2aeafb3c0b39e88735847331f1d202c34342c211e160a00000000000000000000000000000000000000000f1f2d3e4a58616e7a848b93938574604b36200b0000000000000000000000000005182a3b4a5c646f6f6760544c40342b1d11030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000091930404c6176869ca5b4c0c1b5b0a8a59d9b9c9faab4bac3b6a79e8978625645321d11000000000000000000000000000010253a4f657a8fa4c5c8a6917c67555854504d483b413e3a36334556677d92a3b4c1b29d8774604b3a2a17000000000000000c22374c61778caabbcee2dbcfc1b5b1a199938f8e90989fabbcc7b6a4927d68533c2c190600000000162b40556b8095aac0b9a88b76604b36210b00000000000000112132424f61697c899ba3b4c8d6d0d1c8c4bebab9babec5cac5b4a29a897c675f4d3f2e1d0d0000000000051a2f455a6f849aafc1ac96816c57412c17020000000000000000000000000000000000000000000000000000000000000000000000000000031628394c61778a9fb4c9b49f8b77624d39281600000000000000000000000000000000000000001d32485d72879db2bab09b85705b37261401000000000000011426364c5e6c8196a3b5c2b6a89f948983807f81858b979fb4b9c6c6c3c4c7c4af9a856f5a3a2a17090b171f1e170b0902000000000000000000000000000000000000000000010f202d3a474c5c646f777e7e76615645311d0900000000000000000000000000000d1d2d3e4a4f5a5a514a43362f20180d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011426374d5e6e8298a4b6c3bcb4a39b938c8886878a959fa9b7c3b8a79b8574604b402f1909000000000000000000000000000c22374c61778ca7b8c0ab968074716d696662595a57534f4b464b6075879db2c1b4a3917c675645321c0c000000000000000b20354b60758a9fb4cad0c7c3bec8bfb3afa8a4a3a5adb5bcc8baa99c8674604b36200e0000000002172d42576c8297acc1b39e89745645321e090000000000000a1b2f3f4f60697f8d9ea7b4c1c8c1bbb8b7b8bbc1c8cbd5daccb8a79a8478665e4d41302111000000000000041a2f44596f8499aec2ac97826d57422d18000000000000000000000000000000000000000000000000000000000000000000000000000000091e3246576b8095a9bac0ad98826d5948341b0b0000000000000000000000000000000000000000172c41566c81969fa99f95806a55402b1500000000000000081c304354667b909fb0c2b6a59d8a7f766e6a6a6b707882909ea8b9c7d7d9d6c1ac97816c57422c1700000209090100000000000000000000000000000000000000000000000000010f1c2a333e4b4f596268696157463827150200000000000000000000000000000010202d363945453c35302518120500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081d314455667c91a0b2c2bcab9f93857e7772707177808b9da5b7c4b5a397816c5e4c372715020000000000000000000000000a1f34475973889eb3c8b09e968a86827f7b7773706c68646157596a7f94a5b7bfb09b85705f4d3828150000000000000000081c30435473889eb3c8bfb3aea9b3b8c4c4bdb9b9bbc2c9c3b7aa9f8b7a645544311d080000000004192e44596e8399aec3b19c87725c382816030000000000031628394b5d697e939fabb8c5b8b3aba6a3a2a3a6abb3b8c4cdc8b39e8977635a4c403023120300000000000004192e43596e8398aec3ae99846e593625130000000000000000000000000000000000000000000000000000000000000000000000000000011426374b6175899eb3c7b4a28e79644e3b2b180000000000000000000000000000000000000000000b20364b6073818a8d8a8173604b35200b000000000000000b20354b6073869cb1bdb7a69d87796961575555565a626d7c8a9ea9bacde2d3bea9947e69543f29140000000000000000000000000000000000000000000000000000000000000000000c181f2e373b484c53544c4639291a0a0000000000000000000000000000000002101b2224302f27201c13080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b20354b6073869cb1bec0b49f8d7e706861595b59626a79879da6b7c1b19f907b665544311d0c00000000000000000000000004182a3a5b70859ab0c5bcb0a99f9b9894908c8985817d7a76726e778a9eb4c3b2a08f7a654f41301a0a0000000000000000011426365c71879cb1c6b3a199939da6aeb3b8c5bac7bab4afa59d8c7d675c4b3727150200000000061b30455b70859ab0c5af9a85705a45301b000000000000091e324557657b8c9fb4bcbdb0a79e96908e8c8e91969ea6b4bac6b8a79a8473604b3b2b18050000000000000002172c41576c8196acc1b19b86715443301c0700000000000000000000000000000000000000000000000000000000000000000000000000081d314455697e93a7b8c2af9a846f5c4a361d0d000000000000000000000000000000000000000000081d314455606c7578756c605544311d080000000000000215283851667c91a4b6c0b39d8878635b4c46393f3c494d5e667b8b9fb4c3d4d1bba6917c66513c27110000000000000000000000000000000000000000000000000000000000000000000004101b222a34373e3e3633291b0b00000000000000000000000000000000000000070d0f1a1a120b07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000215273751667c91a4b6c8b4a2937e6960534c473b474c5b6378889da9babdb19c8674604b3a291704000000000000000000000000172d42576c8297acc1cdc7bab4b1ada9a5a79e9a96938f8b8784849aa8b9bbaa98836e5d4b372313000000000000000000001a30455a6f859aafc3ae99837e8891999ea7a4a5a5a99f9992877b675f4d3e2e19090000000000021527385d72879cb2c3ad98836e58432e190300000000011527374b6075879daabbbaad9f9689817b7877787c8188939fa8b8c4b4a2947f6a594834200a0000000000000000152a3f556a7f94aabfb49e8974604a35200b000000000000000000000000000000000405010000000000000000000000000000000000000b20354b6074879db2c5b6a4907b66513e2d1a0000000000000000000000000000000000000000000002152737444b56606260564b4437271501000000000000091d3245566e8399aec2b3a2907c665a493c33292a2b35404c5d6a7f94a5b7cbd5c5a38e79644e39240f000000000000000000000000000000000000000000000000000000000000000000000000080d181f222929211e170b0000000000000000000000000000000000000000000000050500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081d3144556e8399aec2c2af9a846f614f4237342a343d4a5a647a8a9fb4c1b6a4947e695847331f0a00000000000000000000000014293f54697e94a9bed3d4cac7c3c2bec5b8b3afaca8ab9f9d999aa2b4c5b49f8b78634d3f2e1b0500000000000000000003192e43586e8398adc3af9a856f757c83888c8f8f8f8d8a847d74655d4d41302010000000000000091d31455674899eb3c1ab96816c56412c170100000000081d3144556a7f94a5b6bdad9c9381766c66636263666c747e8a9ea6b8c0b49f8a77624c382815020000000000000012273d52677c92a7c7b9a88e78634e39230e00000000000000000000000000080e101a1b160d0b060000000000000000000000000000081c2f3f52677d92a5b7c5b19c8673604a35200f00000000000000000000000000000000000000000000000919273138454b4d4b453831271909000000000000000b20364b6075899fb4c4af9a846f5e4c3c2c1e171519202f3f4b6074879db2c7ccb8a78b76614c36210c0000000000000000000000000000000000000000000000000000000000000000000000000000050b0d13140c0a030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b20364b6075899fb4c9b6a48f7a654f4232221f181f2d3c4a5c697e93a3b4c2b39e8976614c38281502000000000000000000000011263b50667b90a5c6d4c3b7b2aeb2b7c3bec1c5c1c9bcb5b2aeafb4c0b8a796816c5a493521100000000000000000000002172c41576c8196acc1b19c867160676e73777a7a7a78756f6860554b3f302313020000000000000b20364b60758ba7b9bfa9947f6a543f2a1500000000000b20354b6074889db3c3b09f937e6c6157514e4d4e5156606979889eaabbbaa896816b5645321d09000000000000000e24394e63798ea9bac6a8937e6853372614010000000000000000000003111c23252f302c2320190e000000000000000000000000000e23384c5d71869bb1c3b8a6937e685443301c0700000000000000000000000000000000000000000000000009151d283236383632281d150900000000000000000f243a4f64798fa8bac5a6917c6651402f1e0e030006121d3144556a8095aabfc8b39e89735846331f0a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a0c1315130f0b090200000000000000000000000000000000000000000000000000000000000001080b0c0a030000000000000000000000000000000000000000000000000000000000000f253a4f647a8fa8bac7b19c87725d4b3724140b050f1e2d3e4a6072859bb0bfb9a8947f6a5645321d0900000000000000000000000d23384d62788da8bacab7a59d999da5a4a8acb0b4b9c6cac7c3c5c8c3b39e8976614c3c2c19020000000000000000000000152a40556a7f95aabfb39d88735e51595962656565626055534b44372e211305000000000000000d22374d62778ca2c5bca7927d67523d2812000000000011263b50667b90a6b7b9a796816c604c463939373938454b5b647a8c9fb4c6b39e8975604b36200b000000000000000b20364b60758a9fb4c2ad98836d5544311d080000000000000000000311212f383b44454138352b1e100200000000000000000000071a2d3d50657b90a3b5c7b39e8875604b3625130000000000000000000000000000000000000000000000000000020a161e2123201d150a0100000000000000000012283d52677d92a7c6b8a68c77614c37211200000000021527374f657a8fa4bac6b09b86715b3a2917040000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090c0d0e0d0b0600000000000000000000000b161e21282a2824211e160b080200000000000000000000000000000000000000000000000000070b141c20211e1618130f0b080200000000000000000000000000000000000000000000000014293e53697e93a8c6c0ab95806b563f2e1b06000000101c304354647a8fa1b3c6b39d8875604b36201000000000000000000000000b20354a6074899fb4c7b29d8784888b8f93979b9ea8a8adbacadacab6a5947e695847331e0e00000000000000000000000013293e53687e93a8bdb49f8a7457463b484d4f50504d4b443736312719110300000000000000000f24394f64798ea4b9baa5907b65503b26100000000002172c41576c8196acc4b39e8976614c42332923222327313d4a5c6b8096abbcb8a7907b65503b261000000000000000081d31445570859ab0c5b39d8874604b35200d00000000000000000011212f3f4b50595a564d483c2e2010000000000000000000000d21364a5c6f849aafc1baa995806a56453218080000000000000000000000000000000000000000000000000000000002090b0d0b0902000000000000000000000014293e54697e93a9beb39e88735847331f0a00000000000c21364c61768ba1b6c3ae98836e59432e1900000000000000000000000000000000000000000000000000000000000000000000000000000000060c0e14161e2122242320190e0000000000000000000c1b2932363d3f3d3a363228201d15090000000000000000000000000000000000000000000008131c202630353632292d2824201d15130e0b080100000000000000000000000000000000000000172c41576c8196acc1c8a5907b66503b261100000000001325364a5c6f8499afc1b8a6937d68533e2d1b0700000000000000000000071c30435471869bb1c6b19c867172767a7e8285898d939cadc1d1c1b29d8774604b3a2a170000000000000000000000000012273c51677c91a6bcbaa98b76614c3634373a3a3a38353126201d15090000000000000000000011263b50667b90a5bbc8a38e79634e39240e00000000061b31465b70869bb0c2ad98826d5846331e170e0d0e151d2d3e4d62788b9fb4c5aa95806a55402b150000000000000002152737556a8095aac3b8a6907b66513b2b18050000000000000009192e3f4b5d656f706b625a4b3e2e1808000000000000000005192b3c4e64798ea2b3c9b49f8a77614c382816000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014293f54697e94a9beb29d87725d3b2a180500000000000c21364c61768ba1b6c0ab96806b56412b160100000000000000000000000000000000000000000000000000000000000000000000000001080e19212329283236383938352b1e17090000000000000c1c2939464b5255524f4b453836312719120100000000000000000000000000000000000000081825303536434b4b4639423e393631272824201d14120e0b07000000000000000000000000000000192e44596e8399aec3bbaa8c77624d37220d000000000008182e3e4f657a8fa3b5c4b19c86715c4a3622090000000000000000000000132536586d8398adc2b49f8a75606165696c7075787e93a8bdc8b4a3917c675645311c0c0000000000000000000000000010253a50657a8fa5bac7a28d78624d38232225252523201d140b0802000000000000000000000012283d52677d92a7bcbbaa8c77614c37220c00000000091e34495e73899eb3bda8937d68533a29170300000002102035485a72879cb1c3ad98836e58432e1903000000000000000f253a4f647a8fa5b7c4ae99836e594834200f000000000000011426374b5d657b84858178645c4b36261401000000000000000b2035485a6d8298adc0bcab97826d5947341a0a000000000000000000000000000000000000000000090e101819130b0700000000000000000000000000000000000013283d53687d92a8bdb39e89735947341f0900000000000e23384d63788da2b8bea8937e69533e291400000000000000000000000000000000000000000000000000000000000000000000000009141d202c35383e39464b4d4e4d493c35271702000000000417293a465761686a68646056524b4437301d1509000000000000000000000000000000000000132536434a53546061575c57534f4b44373d393531262723201c13120d0b06000000000000000000001b30455b70859ab0c5b49f8a75594834200b0000000000001022374b5d71869bb0c6b5a48e79644e3727150200000000000000000000152a40556a7f95aabfbaa98d78634e4f535754606c8196acc1beb09b85705f4d38271500000000000000000000000000000e23384e63788da3c8b9a48f79644f3a240f1010100d0b08010000000000000000000000000000142a3f54697f94a9beb49f8a75604a35200b000000000b20354a60758a9fb5bba6917b66513c2611000000000005192b3c596e8499aec3af99846f5a442f1a05000000000000000b20354a6073879db2c9b49f8b77624c3e2d1b0a00000000000c1d314455657b8c999a96897a645443301c080000000000000417293a4d62788b9fb4cab59f8c79634e3b2a18000000000000000000000000000000000000000003111c23262d2e28201c13080000000000000000000000000000000010263b50657b90a5c2b8a78c77624c3727150100000009192d3d52677d92a7bcbba6917c66513c2711000000000000000000000000000000000000000000000000000000000000000000000312192631353c494d545957616263625a5245352010000000000a1f33465861757d7f7d79756f6760554d403127190900000000000000000000000000000000071c304354606871757674716d6864605557524e4b44373d383530252723201916110b080200000000001c31465b71869bb0c6b39e89735e3b2b1805000000000000081b2e3f53687d92a8bac2ab96816c5544311d080000000000000000000012273c51677c91a6c8c7a6917c67513c3e404e63798b9fb4c7b2a08f7a644f41301a0a00000000000000000000000000000c21374c61768caabbbba6907b66513b2611000000000000000000000000000000000000000001162b41566b8096abc0b29d88735443301c07000000000b20354a60758aa7b9bba6907b66513b261100000000000417293a5a6f8499afc4af99846f5a442f1a0500000000000000071c3043546b8096abbcbbaa97816c5c4a3928190a0000040e1c2c3d4b6073869caaafa79c8773604b35200b0000000000000a1f3347586c8196aabbc2af99846f5b49361d0c000000000000000000000000000000000000000715212f383b42443d35302518090000000000000000000000000000000c22374c61778ca4b5c5a8937e685544311d1308070d1927374a5b6e8399aec3c7a48e79644f39240f0000000000000000000000000000000000000000000000000000000000000000000b171e2f37444b525b63696f72767779786d63523e2d1b070000000c21364c6176869294928f8a847c74675f4b44372718080000000000000000000000000000000b20354a60727d868a8b8986827d7975706c6863605556524e4a43363c38352b2b26201d1509000000001b31465b70869bb0c5b29d88735d48331e00000000000000001021364b61768a9fb4c8b39e8875604b36200b000000000000000000000e24394e63798eaabbbfaa957f6a5540374c5e6f8499aabbbaa998836e5c4b3723120000000000000000000000000000000b20354a60758a9fb4bca7927d67523d2812000000000000000000000000000000000000000003182d42586d8297adc2b09b86715b3625130000000000091f34495e74899eb3bea8937e69533929170300000000081f33465871869bb1c2ad98826d58432d180300000000000000001325364d62788c9fb5c8b49f8c7a64574537281a1515181f2c3a495b687e93a4b5c5b4a28c77614c37220c0000000000021628384c6176899eb4c8b5a4907b65503d2c1a0000000000000000000000000000000000000000152533404c505759524a433627190900000000000000000000000000000a1f34475971869cb1c8b19c8674604b4030251f1c202b37445563798d9fb5cabaa98c77624c37220d00000000000000000000000000000000000000000000000000000000000000010f1b2933404c55606770787e84888a8d8e8d816d5c4a36220d000001162b41566b8096a4aaa7a99f9992877c6c60554436251300000000000000000000000000000013293e53687e929c9fa89f9b97938e8a86817d7975706c6763605456514d493c403c363127190a0000001b30455b70859ab0c5b39e88735e38281602000000000000000a1e3346576d8298adc6b8a7907b6650362513000000000000000000000b20364b60758a9fb4c3ae98836e59384455657b90a1b3c5b49f8b78624d3e2e1b05000000000000000000000000000000071c30435473889db3bea9947e69543f29140000000000000000000000000000000000000000051a2f445a6f8499afc4ae99846f59442f1a0000000000071c31465c71869bb1c2ad98836d5746331e100100000918293a4c61768b9fb4c8aa95806a55402b15000000000000000000082035495a6e8399abbcbbaa9c8675605545382f2a2a2a343c495863798a9eb4c2bcab9a846f5947341f0a0000000000091e3245566a7f94a8b9c4b19c86715d4c381f0f000000000000000000000000000000000000000b1b3343505e656d6e68605444372715010000000000000000000000000004182a3a54697f94aabbb5a4947f695e4a43363330353b48556073859babbcc9b49f8a75604a35200b00000000000000000000000000000000000000000000000000000000000002101f2c39464c5e66737c858d93999d9faba39f8e79644e39240f0000061b30465b70859bb0c2c7bab4afa59d918173605443301c0d0000000000000000000000000006192b3c5a6f8499afb4bab4b1aca8a99f9b97928e8985817d78746f6b67625a5a55514b4437271a0a00001a2f44596f8499aec4b49e89745645321e09000000000000000317293951667b91a8b9c5ac97816c5443301c07000000000000000000091d31455672879cb2c6b19c877156454b6073869cb1bfb8a796816b5a4935201000000000000000000000000000000000001325365c71869cb1c0ab95806b56402b160100000000000000000000000000000000000000061c31465b71869bb0c2ac97826d57422d18020000000003182d42586d8297adc6b49e8a76614b3e2d1d1510111927364658697e93abbcbbaa917c66513c261100000000000000000006192c3c4e64798d9fb5c5b5a498827360564c3f40403a474c5b6376869ca8b9c7b59f8d7a644f3a2a180400000000011426364b6075889db3c6b7a6927d68523f2f1c010000000000000000000000000000000000000316293950616a7b82837d72605544311d1400000000000000000000000000000d22374c62778b9fb4c2b49f8c7d6a60544c47434a4e5962738298a3b5c9c7b29d87725443301c0700000000000000000000000000000000000000000000000000000000000210212e3d4957616d7b86919aa2a9aeb2b5bcbda9937e69543e2914000004192e44596e8399a9b1b4bbc8c3b7b29f978272604a3c2b19050000000000000000000000000b2035495a73889eb3c8cdc9c6c2c7bab4b0aca7a89e9a96928d8985807c78736f6b666055453827150200182d43586d8298adc2b9a88b76604b36210b00000000000000000b21364b6075899eb4c8b29d8874604a35200b00000000000000000002152738596e8499aec3b49f8a75604b57687e93a4b5c3b39e8976614c3c2c190200000000000000000000000000000000001a30455a6f859aafc1ac97826c57422d170200000000000000000000000000000000000000031729395d72889db2c0aa95806b55402b1600000000000012273c51677c91a8b9b9a895806a5c4a3d312726262d3744546176889db3c9b49f8b76614c36210c000000000000000000000e21364a5c6d8298a7b8c2b2a0988275655d5755555759616a79869ca4b5c6baa998836e5c4a361c0c0000000000081c304354687e93a6b8c6b39d8874604b362011000000000000000000000000000000000000000a1e3246576a7f909799928273604b42311c0c000000000000000000000000000b203448596d8297a7b9bbaa9f8c7f726761585460636b778398a0b2c1d2c5af9a85705a36251300000000000000000000000000000000000000000000000000000000000010202e3f4b5b637682909ca4b0b4c0c4c2c0c1bea9947e69543f29140000000f253a4f647b8b969c9faab4bac6bdb1a0947f695a483420090000000000000000000000000d23384d62788da7b8ccc7c4b6babec2c6c5c1c6b9b4b0aba7a79e9a96918d8884807b74605645311d0900162c41566b8196abc0c6a28d77624d38220d0000000000000000091e3245566e8398aec3b7a68e79644f39240f00000000000000000000162b41566b8096abc0bbaa8e79634e6176889eb3c2b6a5947e695847331e0e000000000000000000000000000000000003192e43586e8398adc3ae99836e59442e1904000000000000000000000000000000000000000a1e33465774899fb4bda8937e68533e29130000000000000b21364b6075899eb4c6b49f8a7a645b4b44373b3c3e4a5560728399a6b7c0af99846f5846331f0a00000000000000000000071a2d3e4c6277899eb3bdbeb2a098867b726d6a6a6c7077808a9ca4b5c2bfb49f8a78634d3e2d1b0000000000000b20354b6073879cb1c4baa8947f6a5645311d09000000000000000000000000000000000000000c21364b61768a9facaea098826d604e3a2a180400000000000000000000000005182b3b4c6177899eb3bdbbaa9f94867d7773727478808999a1b2becfd8c2ad98836d58432e1800000000000000000000000000000000000000000000000000000000000e1e2d3e4b5d65798798a0b1b5c2c4b8b3adababac9f8e79644f39240f0000000d22374b5d647a81868b959fa8b8c5beb49f8a78624d37261401000000000000000000000012273c52677c91a7c5c0b4afa1a5a9adb1b4bbc8c0c4c5c1c5b9b3afaba6a79e9995918574604b36200b00152a3f556a7f94aabfb9a48f7a644f3a250f00000000000000000216283852687d92a7c2c4aa957f6a553828160300000000000000000013283d52687d92a7bdc8a7917c675a6b8096a6b8c0b29c8774604b3a291700000000000000000000000000000000000002172c41576c8196acc1b09a85705b45301b00000000000000000000000000000000000000000c21364b61768ba9babba6917c66513c2711000000000000091e3245566d8297a9babaa99d8779686055525051545c64748298a1b3c4b4a2907b66503a29170400000000000000000000000f1f344759677d929fb1bfbeb2a49c9087827f7f81858b959ea8b5c2c0b3a1937e685a49352010000000000004182a3b51667c91a4b6c9b49f8a76614c38271502000000000000000000000000000000000000000c21364c61768a9fabbbb2a0937e695947341f0a000000000000000000000000000d1f344759687e939fb0bebbb4a49c928b8887898e969ea7b3bfcfdcd5c0ab95806b56402b16010000000000000000000000000000000000000000000000000000000a1b2c3c4a5c657b899da5b2bec1b5b1a69d9895969792816d5c4a36220d000000081b2e3f4b5c646c71777f8a9ea7b8ccbaa896806b5544311d080000000000000000000001142637566b8196abc0b4a29a8c9094989c9faaa7abafb3b8c5bfc2c4c0c5b8b3afaaa3927d67523d28120013283d53687d92a8bdbca7927c67523d27120000000000000000000d22374c62778ca4b5c5af9a85705645321e090000000000000000000f243a4f647a8fa4c4c0aa95806b62788b9fb4c4b4a2917c675645311c0c00000000000000000000000000000000000000152a40556a7f95aabfb19c87715c36251300000000000000000000000000000000000000000e23384d63788da2c7b9a48f7a644f3a250f000000000000021628384d62788b9fb4c1b7a69d8a7d746c6765666a707a8598a0b2bfb9a89a84705e4c381c0c00000000000000000000000005182a3b4d5f6c8197a1b2bfc2b5b1a59c979595979b9faab4b9c6c1b4a299836e604e3c2c190200000000000b1f34475970859bb0c2bcab96816c5847331a0a00000000000000000000000000000000000000000a1f334658697f8d9faabbb49e8a77614c3722100000000000000000000000000004182a3b4e606c8196a0b4bbc2b5b1ab9f9d9c9ea8abb3b9c5c7cad4d3bea8937e69533e291400000000000000000000000000000000000000000000000000000003162839495b647a8a9ea7b6c3bbb4a39b9188838081817d73604b3e2d1b070000000010202e3e4a4f5759616a7a899eb3c0c6b39e8874604b35200b00000000000000000000081d31445570859ab0c4af9a84777b7f82868a8e92969a9ea7a5a9adb1b4bbc8c1c4c1ab96816c56412c170010253b50657a90a5c8bfaa947f6a553f2a150000000000000000000b2034485971869cb1c6b49f8a75604b36210b0000000000000000000c21364c61768ba6b7c3ae99836e6e8398a9babeb09a85705f4d382715000000000000000000000000000000000000000013293e53687e93a8bdb39e88735443301c07000000000000000000000000000000000000000f253a4f647a8fa4b9c5a28d78624d38230d000000000000000a2035485a6b8095a3b5c4b7a89e9287817c7b7b7f858f9ba3b2bebcb49e8a79634e402f1c00000000000000000000000000000d1d30414b60738399a1b5bcc9c3b6b2acaaaaacb0b4bbc8c9bdb0a39b8475614b42311e0e0000000000000c22374c61778ca3b4c8b49f8c78634d3a2a170000000000000000000000000000000000000000000417293a4f61697d8c9fb4b9a895806a553e2d1b07000000000000000000000000000c1d31424a607282949faab6c2c9bcb5b2b1b3b9c6c8bbb4b2b6c3d4bba6917c66513c27110000000000000000000000000000000000000000000000000000000a1e3245576379899ea8b8c5b9aa9f94867c746d6b6c6c6860554431201000000000000210202d36393b474c5c667c90a2b4c7b8a78f7a644f3a250f000000000000000000000b20354b6075899eb4c0ab96806b65696d7175797d8184888c9094989c9faaa8abafb3aa95806a55402b15000d23384d62788daabbc2ad97826d58422d1800000000000000000005182b3b566c8196abc9baa9907b65503b25100000000000000000000a1e33465773889db3c7b29c87727a8fa0b2c7b2a08f7a644f41301a0a000000000000000000000000000000000000000011273c51667c91a6bbb49f8a75604a35200b0000000000000000000000000000000000000011263c51667b91a6bbb9a78b76604b36210b0000000000000006192b3c4b6175859ba6b6c3b9b3a59d96919091949ba3b1b5c1bbaf9e927d675b49352211000000000000000000000000000000131d314455607483959fabb6c2cac7c2bfbfc1c5cac8c1b5b09f968575615746322414000000000000000b20364b6074889eaab2aa99836e5a49351c0c000000000000000000000000000000000000000000000b1b32434f5f6a7f95a5b7b29c87725c4a36220d0000000000000000000000000000141c30435460727f8c9ca4b0b5c1c0c1c2c0c5b8b3aa9f9da5b6cac8a48f79644f3a240f00000000000000000000000000000000000000000000000000000a1b2f404b6075869ca7b8c5b8a79e8c7f73666054565657534b443726140200000000000002101b22242a343e4c5e6f849aafc4c5a9947e69543f2914000000000000000000000e24394e63798ea8b9c5a6917c67515458566064676b6f73777b7f83878a8e92969a9e9d8b79634e39230e000b20354b60758a9fb4c5b09a85705b3929170300000000000000000011273c51667c91abbcc7aa95806b55362614010000000000000000031729395a6f859aafc4b49f8b75859bb0bebaa998836e5c4b37231200000000000000000000000000000000000000000010253a4f657a8fa4babbaa8c76614c37210c0000000000000000000000000000000000000013283e53687d93a8bdb39e89745645321e0900000000000000000e1e3246576277889da5b3bfc3b6b2aba7a5a6a9b0b4c1c5b8b39d94806b5f4d3d2c1a040000000000000000000000000000000115273745566072808d9ca4afb4bbc8bfbfbec5b8b3ada39b9081746157463929160600000000000000081d314455667c8c999d9b8c7a644f3c2c19000000000000000000000000000000000000000000000000142432414b6074879db2b6a58e79644f39240f0000000000000000000000000000001325364354606a7b86929ba3a7abacadaba8a69e978a879db2c7bbaa8c77624c37220d00000000000000000000000000000000000000000000000000031628394c5e6d8297a4b5c5b8a79e897b6a60554b433641423d3531261909000000000000000000070d0f181f2f4052677d92a7c7c2ac97826d57422d180200000000000000000013283d53687d92a8c6b8a78d78624d3f38454b4e52565a5962666a6d7175797d818588887e685b4a36210c00081d31445572879db2c7b39d88735746331e0a0000000000000000000c21374c61768b9fb5c4af9a846f5443301c08000000000000000000172c42576c8197acc1bcab968196a3b5c5b49f8b78624d3e2e1b040000000000000000000000000000000000000000000e23384e63788da3c8c8a38d78634e38230e00000000000000000000000000000000000000152a3f556a7f94aabfb19c87725c38281603000000000000000003162839485963798799a1b3b8c4c7c1bcbabbbfc5c8bbb4a69e917f6b625141301f0e0000000000000000000000000000000000091928384554606b7b86929a9faaa9a9aaa9a6a79e9890857b6c60564639291b0b0000000000000000021527374c5e667a8387867c665c4a361e0e00000000000000000000000000000000000000000000000006141d3144556a7f94aac3a8937e68533e291300000000000000000000000000000008182536434a5d65747d868d9296979796938f8881788196abc2b49f8a75604b35200b00000000000000000000000000000000000000000000000000091e324557667b909fb1c2baa99e897a655d4b443730262c2c28201d140900000000000000000000000000041122384d62788da9bac4ae99846f59442f1a04000000000000000002162838576c8297acc1b39e89735a4935273136393d413b484d505458566064686c70737368604e3d2d1a0700011527375a6f8499afc4b7a68b76614c36210c0000000000000000000a1f33475871869cb1c6b39e8974604b35200b00000000000000000014293e53697e93a8bec9b59f8a9fb5c1b8a796806b5a49352010000000000000000000000000000000000000000000000c21374c61768caabbb9a48f7a644f3a250f00000000000000000000000000000000000000172c41566c8196abc1af9a85705a45301b000000000000000000000b1b2b3b4a5b637683939da6afb4bac7bcc9bcb5b1aa9f97887d6a615144332313000000000000000000000000000000000000000a1a2836434b5d65737c858b9093949494918e88827b70655d4b4538291b0b00000000000000000000091930404c5c646e7271665e4c3e2e1b0000000000000000000000000000000000000000000000000000011527374f647a8fa4b9ac97816c57422c1700000000000000000000000000000000081825303f4b55606871777d808182817e7a746c6b8096a4adae9d88735443301c0800000000000000000000000000000000000000000000000004172a3a4b6075879db2bebeb49f8b7b655c4b3f31261c141717130b08010000000000000000000000000000000b20354a6075899fb4c5b09b85705b46301b060000000000000000091e32455671869bb1c4af9a846f5a3c2c191d2024282c2b34373b3f38454b4f53565a5e5d524e41311f0f000000172c41566c8196abc1c4a48e79644f39240f00000000000000000004172a3a576d8297acc2b9a88e79634e39240e00000000000000000010253b50657b90a5c6cfbcab9fabbcc3b39e8976614c3c2b1902000000000000000000000000000000000000000000000b20354a60758a9fb4bba6917b66513c261100000000000000000000000000000000000000192e43586e8398adc3ad98836e58432e1903000000000000000000000d1d2d3d4a5861737e88929a9fa9a6a7a7ab9f9c948b8276675f4f433326160500000000000000000000000000000000000000000a1826303f4b55606770777b7e7f7f7f7c79746d655d504c3f32281a0b0000000000000000000000001222303e4b4f595d5b514c402f20100000000000000000000000000000000000000000000000000000000d22384d62778da2b7ae99836e59442e19000000000000000000000000000000000008131c2e37444b525a62676b6c6d6b6965605462778692989894836e59362614010000000000000000000000000000000000000000000000000a1f3347586a7f94a5b7c4b2a0927d685d4b3e2e1d140901000200000000000000000000000000000000000000071c30435473889db2c5b09b85705b46301b0600000000000000000b21364b60758a9fb4c0ab96806b56412b16090b0f1216182022262a283236393d414549483d3a3123130100000013283d53687d92a8bdbca7927c67523d27120000000000000000000013283d53687d92a8c6c6a8927d68533d28130000000000000000000d22374d62778ca8b9ccc9bcb5bcc9b6a4937e695846331e0e0000000000000000000000000000000000000000000000071c30435473889db3baa7927d68523d2813000000000000000000000000000000000000001a2f44596f8499aebaab96816c56412c170100000000000000000000000f1f2d3a47546068757d848a8f9192918f8b867f776d61584d41322516080000000000000000000000000000000000000000000008141c2e37444b52586165696a6a6967646055504c3f382f1d150a000000000000000000000000000412202e373a4448463b382f2212020000000000000000000000000000000000000000000000000000000d22384d62778da2b7ae99846e59442f190000000000000000000000000000000000000011192731353c484d5256575856534f4b485962737d82837e75614b36210c000000000000000000000000000000000000000000000000031628394c6176899eb3c3b8a698826d604e3f2e2011010000000000000000000000000000000000000000000000001325365d72879cb2c5af9a85705a45301b0500000000000000000f253a4f647a8faabbc5a6917c67513c27120000000000050b0d1115161e2124282c30333328251e1305000000000f253a4f647a8fa4c3c0aa95806b55402b16000000000000000000000e24394e63798ea8b9c1ac96816c573625130000000000000000000b2034485974899eb3c9dacfcacfc0b29c8774604b3a2917000000000000000000000000000000000000000000000000001325365b70859aa9a99f907b65503b261000000000000000000000000000000000000000172c41566c8196a1a99f927d67523d2812000000000000000000000000010f1c2a36434b5660686f75797c7d7c7a76716962594c473a302315070000000000000000000000000000000000000000000000000111192631353a474c5054545554514e4b4437382f231c110200000000000000000000000000000002101b22252f323126241c120400000000000000000000000000000000000000000000000000000005192b3c50657b90a5baad98836e58432e19000000000000000000000000000000000000000009151d202b34383d414242413e3a353b485560676d6e69615746321e09000000000000000000000000000000000000000000000000091e3245576b8095a8b9c1b39d8876614c4131211002000000000000000000000000000000000000000000000000021628385d72889db2c3ae99846e59442f1904000000000000000014293e54697e93a9c8b8a78d78624d38230d0000000000000000000002090b0f13171b1e1e13110b0100000000000c21364c61768ba5b7c3ae99836e59382815020000000000000000000b20354b6074899eb4c5b09b85705443301c07000000000000000005182b3b5b70869bb0c5dbe3dac9b4a2917c665544311c0c0000000000000000000000000000000000000000000000000011263c51667c8b91918a7f6a5d4c38230e000000000000000000000000000000000000000c21374c6176838c8e8a8173604b36200b00000000000000000000000000000c18263038454b52566064666767656158544c483b332a1c130500000000000000000000000000000000000000000000000000000009141d202a33373b3e3f3f3f3c39353126231c110900000000000000000000000000000000000000080d0f191d1c110f0900000000000000000000000000000000000000000000000000000000000b2035485a6c8196abc5aa957f6a55402a1500000000000000000000000000000000000000000001080d192022282b2c2d2c2925202a37444b525859544b46392816030000000000000000000000000000000000000000000000000b21364b6075899eb3c6b5a3927d6758463323130200000000000000000000000000000000000000000000000000091e32455674899eb3c2ac97826d57422d1802000000000000000417293a586d8398adc2b39e89735a4935200c000000000000000000000000000000010509080000000000000000000a1e33465772889db2c7b19c87725645321d09000000000000000000081c30435470859bb0c5b49e8974604a35200b000000000000000000182d42586d8297adc2d7e3cfbcab9a85705e4d37271500000000000000000000000000000000000000000000000000000f24384c5e66777c7c776a61503f2f1c08000000000000000000000000000000000000000a1f334758616e7779766c605544311d0800000000000000000000000000000008141c28323638454b4f5152524f4c473a37342a1f170c00000000000000000000000000000000000000000000000000000000000001080c171f2126292a2a2a2724201d14090800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d22384d62788a9fb4b9a7907b66503b2611000000000000000000000000000000000000000000000000050b0d121617181614100d192731353d43433f3632281b0b000000000000000000000000000000000000000000000000071a2d3d53687e93a7b8c1b09b85705f4d3a29170500000000000000000000000000000000000000000000000000000b21364b60768ba7b9bfaa95806a55402b1500000000000000000a1f33475872879cb2c4af9a846f5a3c2c19060000000000000000000000000000000000000000000000000000000003172939596f8499aec4b49f8a75604b36200b00000000000000000001142636576c8197acc1b9a88d78634d38230e000000000000000000152a3f546a7f94a9bfd4d7c7b59f8d7a644f403019090000000000000000000000000000000000000000000000000000091d2f404c5962676761595043332111000000000000000000000000000000000000000004172a3a474c59626361574b443727150200000000000000000000000000000000010a151d202832363a3c3d3c3a37332a221f180d0400000000000000000000000000000000000000000000000000000000000000000000040a0c1014151514120f0b080100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002172c42576c8197a8bab39e8975604b36200b000000000000000000000000000000000000000000000000000000000102030100000009151d20282d2e29211e160b000000000000000000000000000000000000000000000000000c21364a5b71869bb1c5b4a3907b655041301c0c0000000000000000000000000000000000000000000000000000000e23384d63788da2c5c9a7927d67523d281200000000000000000c21374c61768ca5b6c0ab96806b56412b16000000000000000000000000000000000000000000000000000000000000162b40556b8095aac0bbaa8e79644e39240f0000000000000000000013293e53687e93a8bdc6a6917b66513c261100000000000000000011263c51667b91a6c6d7cdbaa998826e5c4a3622120000000000000000000000000000000000000000000000000000000012222f3b474c52514c473b332515030000000000000000000000000000000000000000000c1c2a333b484c4e4b4639312719090000000000000000000000000000000000000002090b151d202427282725211f170d0b050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000162b40556b8095a4afa595806b5645311d0900000000000000000000000000000000000000000000000000000000000000000000000001080b121819140c090300000000000000000000000000000000000000000000000000000e23394e63798ea3b5c4b09b85705d4b3723130000000000000000000000000000000000000000000000000000000011263b51667b90a6bbbcab8f79644f3a240f000000000000000010263b50657b90a5c3c5a6917c67513c271200000000000000000000000000000000000000000000000000000000000012273c52677c91a7c6c8a7927d67523d2812000000000000000000000f253a4f647a8fa4c4bfa9947f6a543f2a150000000000000000000e23384e63788da8b9cdc4b49f8b78624d3e2e1b040000000000000000000000000000000000000000000000000000000004121d2a34373c3c37342a1d150700000000000000000000000000000000000000000000000c171f2a3437393633291d1509000000000000000000000000000000000000000000000002090b0f111212100c0a0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080a07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c21364c6176869599978775614b38271502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005192b3c566b8095abc1b7a6917c66513f2f1c0500000000000000000000000000000000000000000000000000000000142a3f54697f94a9beb49f8a76604b36210b0000000000000000152a3f556a7f94aabfb8a78d78624d3823120d0b050000000000000000000000000000000000000000000000000000000e23384e63788da8bac0ab96816b56362513000000000000000000000c21364c61768ba6b7c2ad98826d58432d180000000000000000000b20354b6074899eb4c0b6a696806b5a48352010000000000000000000000000000000000000000000000000000000000000000d181f222727221f180c0000000000000000000000000000000000000000000000000000040d181f2224211e170b02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070b141d1f1c140b08010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1f33465861767f848278625746321a0a0000000000000000000000000000000000000000070d0f14130d0b0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b2035485a71869cb1c6b29d8874604b3520110000000000000000000000000000000000000000000000000000000004182a3a586e8398adc3b19c87725745321e090000000000000005192b3c596e8499aec3b39e89735a4935262722201915110c0a04000000000000000000000000000000000000000000000b20354b6074899fb4c4af9a856f5443301c070000000000000000000a1e33465773889db2c5b09b86705b3b2a18050000000000000000081d3144556c8197a2a8a49c8876614c3c2b19020000000000000000000000000000000000000000000000000000000000000000050b0d12120c0b040000000000000000000000000000000000000000000000000000000000050b0d0e0c0a030000000000000000000000000000000000000000000000000000000000000000000000000000000000070600000000000000000000000000010b101317110b07000000000000000000000000000000000000000000000000000000000008131c202a32343229201c140800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000417293a4658616a6f6d625a483929160000000000000000000000000000000000000003101b222429282220180d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d22384d62788da4b6c3ab95806b5544311d08000000000000000000000000000000000000000000000000000000000a1f34475972879cb2c2ad97826d5839281603000000000000000b2034485a73889db3c4af9a846f5a4b43363c38352b2a26221f1812100a01000000000000000000000000000000000000081c30435470859bb0c5b39e8974604a35200b000000000000000000031729395a6f849aafc4b39e89745947341f0b0000000000000000011426374c6175848f92908679635846331e0e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c141c1b0e0c0700000000000000000005131e25282d26201c1308030000000000000000000000000000000000000000000000000008182530353f484a473f353026180800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1c293a464c555a584d483c2b1b0b0000000000000000000000000000000000000b161e2d36393e3e37342b1d12040000000000000000070b0f120e0c06000000000000000000000000000000000000000000000000000013293e53687e93a8c2b6a58e79634e37261401000000000000000000000000000000000000000000000000000000000c22374c61778ca4b6c4a8937d68533e281300000000000000000d22384d62778da6b7c0ab96806b63605456514d483c403b37342a27251d1305000000000000000000000000000000000001142636576c8196acc1b9a78d78634d38230e00000000000000000000172c41566c8196abc1b9a88c77624c37220d000000000000000000091e33465761707a7d7a73635b4a3a2917000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a0c11120d0b06000000000000000000000000000000000000000000000000000000000000000000000000070c181f222a313024211a0f01000000000000071523313a3d423b3530251e170b060000000000000000000000000000000000000000000000132536434a545d5f5c544b433626140100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1c29333640444238352b1e0e0000000000000000000000000000000000000b1b29323e4a4f54534d483b30221200000000000008131c20242723211a0f02000000000000000000000000000000000000000000000005182a3b586d8398adc2b29d87725b4a361909000000000000000000000000000000000000000000000000000000000011273c51667c91a6c3b7a68d78634e38230e000000000000000012273c51677c91a6c4c4af99837d7874706b67625a5955514c473a3c3930231305000000000000000000000000000000000013283d52687d92a7c6c5a7927c67523d27120000000000000000000013293e53687e93a8bdc6a48f7a654f3a251000000000000000000003172939464c5d65686560544a3d2d1b0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b171e2126272320190e00000000000000000000000000000000000000000000000000000000000000000408131c202a34373f464539362d1f0f000000000000152533414e5257504a43363329211a0f080100000000000000000000000000000000000000071c304354606972747169605443301c0e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c171f212a2f2d2220190e00000000000000000000000000000000000003162939464b5c64696862594c40301b0b000000010f182530353a3c39362c1d150a000000000000000000000000000000000000000000000b1f34475972879db2c1ac96816c573d2d1a000000000000000000000000000000000000000000000000000000000005182b3b576c8196acc1b29d88735b4935210c0000000000000001142636566b8095abc0c7b3a199928e8985807c78736f6a66615959524d4130231201000000000000000000000000000000000e23394e63788ea8b9c1ab96816c563828150200000000000000000010263b50657b90a5c7bda7927d68523d2813000000000000000000000b1b29333f4b5053504b43362d1f0f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004121b2933363b3c38352b1e160800000000000000000000000000000000000000000000000000000000070c181f2530353a474c545c5b4e4a3d2d1d0d000000000e1f3343505f686c6660544c4639352c201c14080400000000000000000000000000000000021527384a60727f8789867f72604b3c2b1906000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c151a180d0b05000000000000000000000000000000000000000a1e324657616e797e7d77665e4c3929170300000f1f2c36434a4f514e493d31271a0a0000000000000000000000000000000000000000000d22374c62778ca5b6c5a7917c67523c271200000000000000000000000000000000000000000000000000000000000b2034485971869cb1c2ad98826d583d2c1a0600000000000000081c3043546f859aafc4d0bfb3afa7a89e9a96918d88847f7b77726e675f4d41301d0a000000000000000000000000000000000b20354a6074899eb3c5b09b85705645321d090000000000000000000d22384d62788da9bac0ab95806b56402b1600000000000000000000000b171e2e373a3d3b353026180f010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012223039464b50514d493c332616000000000000000000000000000000000000000000000000000408131c202a3436434a505961697170635b4a3b2b18050000061a2c3d50616a7d827b736961574e493d3530261f170c070000000000000000000000000000091d3145566a80949d9f9c94816c5a4835200b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071a2d3d4b6175838e93938b7c665746331e0a000b1b2c3d4954606467635b4b4538271502000000000000000000000000000000000000000010263b50657b90a5c3b8a78c77624d37220d00000000000000000000000000000000000000000000000000000000000d22374c62778ca4b5c2a7927d67523d281200000000000000000b20354b6074899eb3c9cfcac7c4c6b9b4afaba6a69e9995908c87837d675f4d39251000000000000000000000000000000000071c3043546f849aafc4b49f8a75604b36200b0000000000000000000b20354b60758a9fb4c3ae98836e59432e1900000000000000000000000003111c23252825201c140800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1a30404d57616667625a5144331c0c00000000000000000000000000000000000000000000070c181f2530353a474c5460656e777f86857963594834200b00000c2135495b6a7f929790877e766c635b514b43363329211a0f080100000000000000000000000b20364b6075899eb2b4b19f8c78624d38230d0000000000000000000000000000000000000104050503000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c21364a5b6d8197a1a9a99e8976614c36210c03162839495b6372797c796d605645311d09000000000000000000000000000000000000000014293e54697e93a9beb39e8873594834200b000000000000000000000000000000000000000000000000000000000012283d52677d92a7c2b6a48c77624d37220d00000000000000000e23394e63788ea8b9c9bcb5b2b5bcc9c2c5c0c5b8b3aeaaa6a59d98917d67523c27120000000000000000000000000000000000132536556b8095aac9baa98f7a644f3a250f000000000000000000081c30435471879cb1c9b19b86715c46311c0000000000000000000000000000080e1013100b08010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021527384d5f67767b7c786b62513a2a18040000000000000000000000000000000000000508131c202a3436434a50596169737b838a949b9a8877624c37220d00000e23384e63788b9faca49c938981796f6660544c463a362d201d1409040000000000000000000e23384e63788da8b9c9bcab917c67513c2712000000000000000000000000000001080b11161a1b1a1815100b090200000000000000000000000000000000000000000000000000000000000000000000000000000000000000081b2e3e4e63798c9fb4bfb9a7927d68533d2813091e3246576379868f918e8274604b36200d0000000000000000000000000000000000000002172d42576c8297acc1af9a85705a3b2b190500000000000000000000000000000000000000000000000000000000071a2d3d586d8298adc2b19c8771594834200b000000000000000013283d52687d92a7c6bcab9f9c9faba9adb1b4bbc8c1c4bfc3b7b2ae99846e59442f19040000000000000000000000000000000011263b50667b90abbcc7a9947e695436251300000000000000000001142636596e8398abb8af9a85705a45301b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000091d314556677d8990918c806b5847331f0a00000000000000000000000000000000060d181f2530353b474c5460656e777f8790989fa9b1a696816b56412c16010014293f54697e94aabbb6b2a89e968c847c736961584e4a3d3531261f170c01000000000000000d23384d62788da3b5c3b6a5907a65503b25100000000000000000000000000009141d20262b2f30302e2b26211e160a070002090b0e0d0b060000000000000000000000000000000000000000000000000000000000000000000822374b5c6e8399abbccfc5ac97826d57392916172a3a4b6175879ca4a6a0947f6a543b2b1905000000000000000000000000000000000000051a30455a6f859aafc1ac97826c57422d1700000000000000000000000000000000000000000000000000000000000c21364a5b73889db2c8ac96816c573b2b18050000000000000002152738576c8197acc1b59f8d878b8f94989c9faaa8acb0b4bac7c7b09b86705b46311b06000000000000000000000000000000000c21364c61768b9fb5c3ae99836e5443301c0700000000000000000010253b50657b8d9da69f947f6a543f2a1500000000000000000000000000000001080b0c0b09020001000000000000000000000000000000000000000000000000000000000001080b0d0d0b050000000000000003070400000000000000000000000000000000000000000b20364b60758a9ea7ab9f8c77614c37220c0000000000000000000000000000000e19202a3436434a5059616a737b838a949ca4adb4bac4b09b86705b46311b0600152a3f556a7f94a8b3b9c5b9b4ab9f9a91877f766c635b514b4437332a1d14090000000000000b2035485a71859ba5aba69d8773604b35200b00000000000000000000000213192631353b4144454543403b363228211a0f151d20232320190e0700000000000000000000000000000000000000000000000000000000000008182f404f647a8fa1b3c9d9c6b19c86715746321e1f3347586a7f95a5b5beb29d8873594834200b000000000000000000000000000000000000031729395d72879cb2bfaa957f6a55402a1500000000000000000000000000000000000000000000000000000000000e23394e63798ea6b7bbaa917b66513c26110000000000000000091d31455671869bb0c6b29c8772767a7e82868a8f93979b9fa9a7aba998826d58432e1803000000000000000000000000000000000a1f33465871869cb1c6b39e8874604a35200b0000000000000000000e23374b5d677d888d8b8174604b36200b000000000000000000000000000008141c2022201d15191614110f0c0a040002000000000000000000000000000000000000000009151d2023221f180d030000070c0e191c1a0f0d0800000000000000000000000000000000000d22374d62778ca8b8bcab8e79634e39240e0000000000000000000000000002101e2c353b474c5460656e777f8790989fa9b2b6c3c1b5b0a799846f5a442f1a05000e24394e63798a969ea7b1b6c2bcb5afa59d948a81796f6660554c473a31261909000000000006192b3c4d6379879296938879635443301c080000000000000000000009151d3037444b5156595a5a5855504b4538362d1e2731363938352b211a0f01000000000000000000000000000000000000000000000000000000001325364c5e70849aafbfd0dfcab49f8a76614b36212b3c4c6176899eb3c3cbb7a68c77624d37220d0000000000000000000000000000000000000a1e334657748a9fb4bda8937d68533e2813000000000000000000000000000000000000000000000000000000000215273754697e93a9c4b49f8a76614c36210c00000000000000000b20364b60758a9fb4c3ad98836e6165696d71767a7e82868a8e9296968b7a644e39240f00000000000000000000000000000000000417293a576c8197acc1b8a78e78634e39230e000000000000000000081c2f3f4d5f677478766c605645311d09000000000000000000000000021018263035373631272e2c292724221f181a181513100e0b090200000000000000000000000412192731353837342a1e160b0f1a21232e312f25221b10020000000000000000000000000000000d22374d62778ca2c6c9a38e79644e39240f0000000000000000000000000010202d3c494d59626a737b838b949ca5aeb4bac6bab4aca39b92897b654f3a251000000c21364a5b63788089939ca4afb5bcc3b6b2a89e978e847c746a61584b443726140100000000000e2135495b63767d817e76635b4a3626140100000000000000000009192731414d5560666b6f706f6d6a6560564e4a3d3238454b4e4d493c362d1f0f000000000000000000000000000000000000000000000000000000071c304354667b90a2b4c8dde2cebbaa8f7a65503a2534485a6b8196a8b9ccd4c4a6917c67513c27120000000000000000000000000000000000000c21364c61768ba9babba6907b66513b261100000000000000000000000000000000000000000000000000000000081d3144556f8499aec4b09b85705746331e0a00000000000000000f243a4f64798fa9babfa9947f6a54505458566064686c7175797d81817a645c4a36210d00000000000000000000000000000000000012273d52677c92a7c2c5a8937d68533e281300000000000000000000112130414d55606261574b453827150200000000000000000000000010202e36434b4c4b453843413e3c3937342a2f2d2a282523201d151913110b0100000000000012222f37444b4d4c483b32291b1f2d36394347443a372e201104000000000000000000050b0d12141422374d62778ca2b7b9a38e79644e39241111110f0d0700000000000000071b2d3e4a5a626e777f8790989faab2b6c3c2b6b1a89f978f867d75655d4b37230e0000071a2d3d4a5a626b757e8690999fabb4b9c6b9b4aca29a91877f766a605544311d0c000000000006192c3c495761686b6961584a3d2d180800000000000000000008182737444b5f67747b8084858583807b756d635b4b464e566063625a4e4a3d2d1a0700000000000000000000000000000000000000000000000000011426374a6072859bb0c0d1d9dbd9c8a9947f69543f2c3d4d62788a9fb4c6d6d5c0ab96806b563726140100000000000000000000000000000000000d23384d62788da2c7b9a48f79644f3a240f000000000000000000000000000000000000000000000000000000000b20364b6075899eb4c6aa95806a5539291703000000000000000014293e53697e93a8c7c3a5907b65503b3f38454b4f5357556064686b6c645c4a3d2d1a070000000000000000000000000000000000000d22374d62778ca4b6b9ac97826c57422d17020000000000000000000313233037444b4d4b463931271a0a000000000000000000000000071b2e3e4a54606160565b595654514f4c473a4542403d3b383632282e28251e1305000000000e1e2f404c55606262594b4639292d3d4a4e585c594f4b3e2f221100000000000000000d18202227292929374d62778ca2b7b9a38e79644e392626262624221b100200000000000d22364a5c6478838b949da5aeb4bbc7bab4ada49c938a827a716861574b3f2e1c080000000f1f2d3c494d576168737b848c979ea8b2b7c3c0b4afa59d948a7f73604b3a29170400000000000e1e2c39464c5256534c473a2d1f0f000000000000000000001325364455606d7d879096999a9a9895908a82796c6157606875787871635b4a36210c00000000000000000000000000000000000000000000000000081d314455677c91a3b5c9c7c3c7d0c3ae99836e593b35495b6d8297a9bacde4dac5af9a85705544311d0800000000000000000000000000000000000f24394e64798ea3b9b8a38e78634e39230e0000000000000000000000000000000000000000000000000000000010253a50657a8fa8b9b9a88f7a65503a2510000000000000000003172939586d8298adc2b7a58c77614c37292832363a3e37444b4e5256574f4a3e2d1f0f000000000000000000000000000000000000000b2034485971869ca9a89e937e68533e28130000000000000000000000051319273136383633291d150a000000000000000000000000000d22364a5c6473777573706e6b69666461595c5a575552504d4b4538433d3a31231305000005192b3c4c5e667478776e615746373c4a5b636e716f645c4c402f1e0e0000000000010f1d2b34373d3e3e3e3e4d62778ca2b7b9a38e79644e3c3b3b3b3b3a362e201507000000000f24394f647a8a989faab2b6c3c3b7b2a99f988f867e766d645c534b46392e211100000000010f1e2b3539464b5460666f79818a949da5afb4c0c3b7b2a99f94806b5846331f0a0000000000000e1b2933363d413e37332a1c0f01000000000000000000071c304354607382919da6abaeafafadaaa99f978c817563687e898e8d8679634e39240e000000000000000000000000000000000000000000000000021628384b6073869cb1c1bfb3aeb3bfc8b29d887359483e4e63798c9fb4c7d7dbdec9b49e8975604b35200b00000000000000000000000000000000000f243a4f64798fa4b9b7a28d78624d38230d0000000000000000000000000000000000000000000000000000000417293a556b8095aac6b49e8975604b36200b00000000000000000a1e33465772879cb1c7b29d88725847331f161e212429273136393d41413a362d2010010000000000000000000000000000000000000005182b3b51667c8a90908a7f69604e3a26110000000000000000000000000009151d2023211e170b020000000000000000000000000005192b3c4f647a888c8a888683817e7c797774726f6d6a68656360565b59534e4231231301000b2035485a667c888d8c8375615544485a63798386847a665e4c3c2b1906000000000f1f2d3b484d52545454545462778ca2b7b9a38e79645151515150504f4a3e332515000000061b30455b70859aa8b4bbc8c4b7b2a59d948a837a716961584f4a3e3632291b11030000000000000e1920283236434a505b636c767f87919aa2b4c2cac7bab49f8a76614c36210c0000000000030a161e2121282c29211f170c00000000000000000000061a2c3d4a607282979fb2b7c4c4c5c4c2c7bab4ab9f978779768b9ea8a49c86715c47321c070000000000000000000000000000000000000000000000091e324556687d93a4b6c3b3a199a1b3c8b7a68c77624d4a5c6e8399aabbcecac6c9cdb9a88e79644e39240f00000000000000000000000000000000000f253a4f647a8fa4b9b6a18c77614c37220c0000000000000000000000000000000000000000000000000000000a1f33465870859bb0c4af99846f5544311d0800000000000000000c21364c61768b9fb5c3ae99836e593a2a1704090b0f13151d2024282c2c24221b10020000000000000000000000000000000000000000000d24384c5e66767b7b7669614f42311f0b000000000000000000000000000002080b0d0c0a030000000000000000000000000000000b2035485a71869ca69f9d9b989693918e8c898784827f7d7a787573716e68604e41301e0a000d22384d62788b9da6a0988373604b4d62788a989c998b7c665a49352011000000071a2d3d4a596267696969696969788ca2b7b9a38e7967666666666666645c5043331c0c00000a1f344a5f74899fb4c6cecbb7a69d90877f776e655d544c463a362d211e160b000000000000000000060b161e2530353d494e586169747c849aa4b5c9d7cdbaa98e78634e39230e000000000b171e283236363329261f140400000000000000000000000c2136495b6a7f94a0b1bec7bab4b0afb1b6c2c9bcb5a59d888096a9b9b49f89745f4a341f0a00000000000000000000000000000000000000000000031729394b6075879db2c2b6a5998499aabbc4a6917c66514f647a8fa1b2c8bbb4b0b5c1c6a8937d68533e281300000000000000000000000000000000000f253a4f647a8fa4b9b6a08b76614b36210c0000000000000000000000000000000000000000000000000000000c21364c61768b9fb4c4a9947e695437271502000000000000000010253b50657a90abbcbfaa957f6a55402a15000000000002080b0f1316170f0d070000000000000000000000000000000000000000000000091c2f404c5861666561574f43322414020000000000000000000000000000000000000000000000000000000000000000000000000d22384d62778da4b5b5b3b0aeaba9a6a4a99f9c9a979592908d8a8886837d685f4d3925100012273c51677c91a6b7b2a2957f6a5a556a8095a8b1a99e8978624d3f2e1c0800000c21364a5b63777c7e7e7e7e7e7e7f95aabfbea9947f7c7c7b7b7b7b7b7a6a61503a2a170400091e33485e73889db3c2cec8b29d887b726a6159504b3f363329221b100a030000000000000000000000000308131c202c353a464c55606a78869cb1c6cbbeb49f8a76604b36210b0000000b1b293338454b4c463a3b32241406000000000000000000071b2d3e4e63798b9fb4bec1b4a99f9b9a9ca4aab4bac3b6a69e969eb0c7b19c87715c47321c07000000000000000000000000000000000000000000000a1e334657697f94a6b7c1b29c87768b9fb4c0ab95806b565e6f849aafbfbbaa9f9ba3b5c2ac97826d5739291703000000000000000000000000000000000f24394f64798ea4b9b6a18b76614c36210c00000000000000000000000000000000000000000000000000000011273c51667c91aabbb8a68e79634e39240e000000000000000000152a3f546a7f94a9c9c4a6907b66513b261100000000000000000000010200000000000000000000000000000000000000000000000000000012222f3a474c50504b463932251506000000000000000000000000000000000000000000000000000000000000000000000000000d23384d62788da5b7c6bec1c3c0bebbc7bab4b1afacaaa7a5ab9f9e9b98927d67523d2712000c21374c6176889da8b9b49f8b786252677d92a0b2b9a89a846f5d4b37230e00000e24394e63798992939393939393959eafc3c2ae9d94919191909090908f7f6a5847331f0a0002172c41576c8196a4b1becbb7a6998378686054493c30251f170c0700000000000000000000000000000000030f1825303a474c5d65747f8a9ca4b5c4b7b3a096806b5745321e09000003172939464b56606158534f423224140000000000000000000d22364a5c6f8499a9bac3b4a39b8b8685878c959fa9b6c3b8b3abb0bcc3ad98836e58432e190300000000000000000000000000000000000000000004182a3b4c6176899eb3c4b4a3917c71869bb1c5af9a857054657b90a2b4c7b49f8c869bb0c6b19c86715746331e0a000000000000000000000000000000000e23394e63788ea3c9b6a18c77614c37220c000000000000000000000000000000000000000000000000000006192b3c576c8197acc8b39e8874604a35200b000000000000000005182b3b596e8399aec3b8a68c77624d37220d00000000000000000000000000000000000000000000000000000000000000000000000000000004121c2a33373b3b3633291b150700000000000000000000000000000000000000000000000000000000000000000000000000000b20354a6073879da8a6a9abaeb1b3b9c5bbbec0c3c2bfbdc9bcb5b3b0ae99846e59442f19000a1f334758647a8a9eb3baa996816c5460728298a2b4b3a28f7a65503a25100000182d43586d8298a7a9a9a9a9a9a9aaafbccccbbbaea9a6a6a6a6a6a5a59f8a76614c37210c00000c21374c61768697a0b3b8c4b3a199897e72625a4a43362c1d14090000000000000000000000000000000a161e2d36434a58616d7b86949fa9b5bdb1a69d918273604b3928160300000a1e334657616d75767369604f42321909000000000000000417293a4f647a8ea1b3c7b7a59b8577716f7277808a9da5b6c4c8c0c4cdbfaa957f6a55402a15000000000000000000000000000000000000000000000b1f3447596a8095a7b8bfb09b85706c8197acc1b49e89746072859bb0c0baa997817f94a9c8b49f8b76614b36210c000000000000000000000000000000000d22374c62778cabbcb8a38e78634e39230e00000000000000000000000000000000000000000000000000000b2035485a72879cb2c2ad98836d5443301c0700000000000000000b2034485973889db2c8b39d8873594834200b00000000000000000000000000000000000000000000000000000000000000000000000000000000000c171f212626211e170b00000000000000000000000000000000000000000000000000000000000000000000000000000000071c304354667c898e919496999b9ea7a3a6a8abaeb0b3b8c5bbbdc0c2af9a846f5a452f1a000417293a4a5c687d92a4b6b39e887460546073859bb0c0ad98826d583c2b1905001b30455b70859ab0c5bebebebebebfc3ccdad9cbc2bebcbbbbbbbbbbbaa98f7b65503a251000000a1f334758617682919da6b2beb3a89e938478696054493d3126190f01000000000000000000000003111b28323d4a54606877828d9ca4b4bab6b29f97887c6e605544311b0a0000081b2e3e4b6175828a8b887e69604f372614010000000000000a1f3346586d8297adbfc0b29d877662595a59626b79879da6b7c9dad8d7c7a6917c66513c271100000000000000000000000000000000000000000005192b3c4c61778a9eb4c5b2a08f7a64677d92a7c5b9a88e79677c91a3b5c7b49f8b787b8faabbbcab907a65503b2510000000000000000000000000000000000b20354b60758a9fb5baa58f7a65503a251000000000000000000000000000000000000000000000000000000d23384d62788da5b6c3a8927d68533625130000000000000000000d22374c62778ca6b7c4af99846f5a3b2b180e0b0700000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c11100c0a030000000000000000000000000000000000000000000000000000000000000000000000000000000000001325364c5e6675797c7e818486898b8e919396989b9ea6a3a5a8abada4947f6a553f2a1500000c1c2d3e4b6073869cb1b8a68d78634e55647a8ea3b5b29d88735a4834200b00182d43586d8298adb2b2b2b3b3b3b3b8c5d6d6c9bfbbb6b6b6b6b6c0b4a38e79634e39230e00000417293a4758616d7c8898a0b3b8b9b3a29a8a7e72635b4b44372d1f13060000000000000000000111212e39454b5b63727d89979fabb6bbb4a59c908276665e4b443727150000000d22374b5c6f83989fa69d937e695544311d080000000000000c21364c61768a9fb4c9b4a2907b6658483b484d5b6377889dabbccfe1cdbaa98d78634d38230e0000000000000000000000000000000000000000000b2035485a6c8196a8b9bbaa98836e5d63788da6b8c6a8927d73869cb1c1baa997816c768a9fb4c9a9947f6a543f2a1500000000000000000000000000000000081d31445573889db3bda8927d68533d2813000000000000000000000000000000000000000000000000000013283e53687d93a8c3b6a48d78624d38220d00000000000000000011263c51667c91a6c4c0aa95806b5540272823201c13120d0b060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008182f404c57606467696c6e717476797b7e818386888b8d90939597938675614b36210c000000101c3043546a8095aac5a7927d68524a5c71869bb1b7a68d77624d38220d0010253b50657b909b9d9d9d9d9d9e9ea7b8ccc9b8aba6a0a0a1a1a1a1a29a85705b4935210c0000000c1c293a464c5e667683919ea7b3bfb4a89e9384796960554a3d3124130100000000000000000f1f2e3f4b57606b7984929ea7b5bcb5aa9f96877b6d61584d40312719090000000f253a4f647a8fa1b4b7b29e8874604b35200b00000000000114263752677d92a9bac6b09b85705e4c3a2b343d4959657b8d9fb5cadec9b49f8975604b35200b0000000000000000000000000000000000000000061a2c3d4d62788b9fb4c5b49f8b78634d5a73889eb3c1ac97817e93a4b6c6b49f8a776271869bb1c3ae99836e593b2b1905000000000000000000000000000000011426375a70859aafc0ab96806b563727150100000000000000000000000000000000000000000000000003192e43586e8398adc9b29c87725a4835200b000000000000000000132536556b8095aac0c9a6917c665144373d383530252723201915110d0b050000000000000000000000000000000000000000000000000000040a0c0f0e0c060000000000000000000000050b0d121414141313131313121212121212111111111111110f0d07000000000000000013233039454b4d4f515456595c58616366696b6e707376787b7d80827e75615746321e0a0000000114263651667b91a6bbaa947f6a553e566b8096abc4a5907b65503b2610000e23374b5d687e868788888888888990a2c8bfab9a908b8b8b8c8c8c8c8578624d3d2c1a06000000000c1b2933404c58616e7d8999a1b3b9b9b4a29a8b7f73635b4e4231200f00000000000000071a2d3d4b5d6575808b9aa2b3b8bab4a49c8c8075655d4c463a301d15090000000014293f54697e94a9bfcbb8a78d77624d38220d0000000000081d3144556e8399aec7b9a8927c6752402f1c202c3b4b5d6e8398aec5d6c6b09b86715443301c0800000000000000000000000000000000000000000c2136495b6d8297a9bab9a796816c5a49596e8499aec3b19c86889db2c2baa896816c596c8197acc1b29d8873594834200b00000000000000000000000000000000172d42576c8297acc1af9a856f5544311d08000000000000000000000000000000000000000000000000061b30455b70859aabb6ac97816c573c2b19050000000000000000071c3043546f849aafc4bcab8d7864605557524e4a43363c38352b2b26221f1815100c0a0400000000000000000000000000000000000000010c181f222523211a0e0600000000000000000d1820222729292929282828282828272727272726262626262624221b100200000000000c1c30414d57606261575c59575552504e515356595b57606366686b6d6961574639291603000000000f253a4f647a8fa4b9ab95806b564053697e93a8bca6917c67513c271200081c2e3f4e606871727273737373728aa0b5bba6907c7676767677777770625a48341f0f0000000000000b171f2f3a474c5f677783929ea8b4c0b4a99f94857968604e3e2d1a070000000000000c21364a5b657b87969faab4c0b4a99f95867a6b60574b3f33291c1202000000000012273c52677c91a7b8c0b49f8a76614b36210c00000000000b20354b6074899eb3c9b49e8975604b3621120f1d2e3f50657a8fa7b9ccc2ad97826d583626140100000000000000000000000000000000000000071b2e3e4e63798c9fb4c3b39e8976614c3c546a7f94a9c8b6a49c9da6b7c6b49f8a776252687d92a7c5b7a68c77624d37220d0000000000000000000000000000000013283e53687d93a8c4b49e8975604b35200b0000000000000000000000000000000000000000000000000012273d52677d8d9ca59f907b65503b25100000000000000000000b20354a6074899eb3c8b49f8c7e7975706c6763605456514d483c403b37342a2a25211f170b000000000000000000000000000000000009141d2a33373a38352c211a0e0000000000010f1d2b34373d3e3e3e3e3e3e3d3d3d3d3d3c3c3c3c3c3c3b3b3b3b3a362e20150700000004172a3a4d5f6775787674716f6c6a67656360565c595754525050535658544b4639291b0b000000000011263b50667b90a5bbaa95806b553654697e94a9bca7927c67523d27120000112131424e535c5d5d5d5e5e54758aabbcbba5907b66616161616261584d483c2b19010000000000000004121c2a33414d59626f7d899aa2b4babab4a39b8b7e685c4a36210d0000000000000e23394e63798b9da5b4bbb9b4a39b8b7f74645c4b45392f1f170c000000000000000c21364b6176889ea8a9a297826d5746321e0a00000000000f243a4f64798fa8b9c3ad98836e5645321e09001020354b6075899eb3c9bea9947f69543f2a1400000000000000000000000000000000000000000d22364a5c6e8399abbcb7a5947f6958473a50657a8faabbc2b6b1b2b7c4b9a896806b594e63788da7b8c4a6917c67513c2712000000000000000000000000000000000e23394e63788ea6b8b9a88f7a6550382816020000000000000000000000000000000000000000000000061425394d5f677c878c8a806b5d4b38230e0000000000000000000d22384d62788da7b8ccbcab9f938e8a85817d7874706b67625a5a55514c473b3f3b3633291b15070000000000000000000000000000091926313a474c4f4e493d352c1f0e000000000f1f2d3b484d525453535353535352525252525251515151515050504f4a3e3325150000000a1f334758677d8a8d8b898684827f7d7a787673716e6c6a67656260565b534e4231201000000000000e1e3041556a7f94aac7a8937e685343546c8197acc4a5907a65503b25100000031424313b3e46484848484a5f758a9fb4bba6907b66514c4c4c4c4c473a342b1d0d000000000000000000000c171f303b484c60687884939fa8b4c0b5a99f8d79644e39240f000000000001162b40566b8095a9b7bfb3a89e9385796a60554a3e32281b110400000000000000000a1e334657657b899294908475604b39291603000000000014293f54697e94a9c6c3a7927d67523828160300081d31445570869bb0c5c5a5907b66503b261100000000000000000000000000000000000000091c2f3f4f647a8fa1b2c1b29d8775604b3a364b60768a9fb4cacac7c8cbc5b49e8976614c4a6074899eb3c0ab96806b56372614010000000000000000000000000000000c2135495b73889eb3c6ab96816c5645321e0900000000000000000000000000000000000000000000021424313b484d5e667276756b62513f2f1c080000000000000000000f243a4f64798fa4c0d0c9bcb4a8a99f9b96928d8985807c78736f6a6662595954504c463a3325150100000000000000000000000001142637444b586164635b4e493d2c1b0a0000071a2d3d4a596267696969686868686867676767676766666666666666645c5043331c0c00000c21374c6176899ea9a79e9c99979492908d8b888684817f7c7a7875737068604e3e2e1b0700000006192c3c4d5f71869bb0baa9907b65504a6073879db2b7a68d78634d38230e00000006141f262931323333354a5f748a9fb4bba6917c66513c37373737332a20190d00000000000000000000000004131d2b34424e5a62727e8a9aa2b4babaab937e69543e2914000000000001162c41566b8196abb8b3a19a8a7e73635b4b44372d1e160a00000000000000000000031729394c5d65777d7f7b73605745321b0b000000000003162839586d8398adc2b6a58c77624c37220d000001142637596e8499aec3b9a78c77624d37220d000000000000000000000000000000000000000e23384c5d6f849aafbfb5a3927d6756453232455771869bb0c6dbdcddccb8a795806a584743546f8499afc4af9a85705544311d08000000000000000000000000000000061a2c3d576d8297acc4b39e8975604b37271502000000000000000000000000000000000000000000102031424e59626766616160565144342111000000000000000000000d22374d62778ca2b4c0c8cbcac7bab4b0aca7a89e9a96918d8884807b77726e6a6561585043331f0f000000000000000000000000081d314455606c777a7871635b4939281603000c21364a5b63777c7e7e7e7e7d7d7d7d7d7d7c7c7c7c7c7b7b7b7b7b7b7a6a61503a2a17040010263b50657b90a8b9b9b3b1aeacaaa7a5a2a79e9b999694928f8d8a88857e685c4a36220d0000000c2035495a677d91a3b5b49f8a75604b5a677c91a5b6b39d88735b4935210c00000000020b11131c1d1d1f344a5f74899fb4bca6917c67513c272222211f170c050000000000000000000000000000000d1820313c485460697884949fa9b5a7927d68533d281300000000000011263b51667b90a0a79e928478696054493d31271910030000000000000000000000000b1b2f3f4c5861686966605445392816000000000000091e32465772879cb1c7b29d8772594834200b0000031628385a6f859aafc4b39e8974594834200b00000000000000000000000000000000000004182a3a50657b90a2b4bfb09b8572604a38282839576c8196acc1d6e7d5c5b39e8976614c3a36556a8095aac9b49e8975604b35200b0000000000000000000000000000000011263b51667b90a6b7b8a7927d685544311d0e0000000000000000000000000000000000000000071b2e3e4e6068787c7c76675f4d3e34261603000000000000000000000b203448596f849aa2adb3b8c4bfc3c7c5c1c6b9b3afaba6a69e9995908c88837f7b766a61503d2c1a0600000000000000000000000b20354b6073818b8f8d8579635745321e09000e24394e637989929393939393939292929292919191919191909090908f7f6a5847331f0a0010253a50657a8fa8b9c6bdc0c2c1bfbcbac5b8b3b1aeaca9a7a5ab9f9d9b8f7a644f3a240f0000000e23384d63788a9eb4beae99836e564d6278889eb3bfad97826d583c2c1906000000000000000007080a1f34495f74899eb4bca7917c67523c27120d0c0a0400000000000000000000000000000000000005131e2b36434a5a63737f8b9ba39e8977614c37220c0000000000000f24384c5e6e829194897d6f625a4b43362c1d150900000000000000000000000000000011212f3a474c5254514b4336281b0a0000000000000c21364b61768b9fb5c2ad98836d583b2b18050000091e32455672879cb1c5b09a85705b3b2b19050000000000000000000000000000000000000a1f33475870859bb0c0b3a18f7b655443301a273d52677d92a7c4d5e0ccb8a7947f6a5846333b50667b90abbcb9a88e79634e39240e000000000000000000000000000000000b20354b6074889db3c5b29d8774604b3c2c1a0a000000000000000000000000000000000000000d22364a5c687e8b9191897d675c4b37220d000000000000000000000005192b3b4c61778590989ea6a6aaadb1b4bcc9c1c5c5c0c5b8b3afaaa6a59d9994908b806a5b4935210c0000000000000000000003162839556a80959faaa39b8775604b36210b00182d43586d8298a7a9a8a8a8a8a8a8a7a7a7a7a7a7a6a6a6a6a6a5a5a59f8a76614c37210c000b21364b6075899ea8a6a8abadb0b2b4bbc8bcbfc1c3c1bfbcc9bcb5b3aa95806a55402b1500000012273d52677c92a8b9b2a08f7a654f556b8095a7b8b3a18f7a644f3a240f0000000000000000000000091f34495e74899eb3c3a7927c67523d27120000000000000000000000000000000000000000000000000e1825303c4954606979858d897c655947341f0b000000000000091c2f404b60727c7f77685f4d483c3026180f020000000000000000000000000000000003111c2a33373d3f3b353026180a000000000000000f243a4f647a8fabbcbea9947f69543f2a140000000b21364b60768a9fb4c1ac97826c57422d17000000000000000000000000000000000000000c22374c61778ca3b5bbaa99836f5d4b36251323384d62788da6b8cbd5c4b39e8875614b3a29374c61768b9fb5c6a8937d68533e281300000000000000000000000000000000081d3144556b8095a9bab7a5947f695a4938281a0b0000000000000000000000000000000000000f243a4f647a8f9faaa79e8c7a644f3a250f0000000000000000000000000d1f34475961727b83888c9094989c9faba8acb0b4b9c6bfc3c4bfc3b7b2aea9aa9f8c79634e38230e00000000000000000000091e32455773889eb3bbb5a5927d67523d2712001b30455b70859ab0c5bebebdbdbdbdbdbcbcbcbcbcbcbbbbbbbbbbbbbaa98f7b65503a251000091e324557677d898e909395989a9d9faaa4a7a9acaeb1b4b9c6bbbebeaa95806a55402b150000000c22374c61778a9ea8a498836e5d4b53687d92a3b0a699836f5c4a36220d0000000000000000000000051b30455a70859aa9ada5927d68523d28130000000000000000000000000000000000000000000000000008131c2c36434b5b63747875655e4c3b2a180400000000000000121c30435460676962594e41352b1c140800000000000000000000000000000000000000000c181f22282a26201c1408000000000000000013283d53687d92a8c9c7a5907b66503b26110000000f243a4f64798fabbcbea8937e69533e2914000000000000000000000000000000000000000a1f33475872879ca7af9f8c79634e3f2e18082035495a73889db3c8cbb7a6947f695746321f33475872879cb1c2ac97826d5739291603000000000000000000000000000000011527374d62778a9fb4c3b49f8a7862564538291b0f0400000000000000000000000000000003182d43586d8298adbbb8aa97826d58422d1803000000000000000000000004182a3b475460666d73777b7f83878a8f93979b9ea8a6aaaeb2b7c3bec2c3c8bbab927d68523d2813000000000000000000000b21364b60768ba7b8ccc3a9947f6a543f2a1500182d43586d8298adb2b2b2b3b3b3b3b4b4b4b4bbb5b5b5b6b6b6b6c0b4a38e79634e39230e00031628394d5f6775797b7e808385888a8d8f929497999c9ea8a3a6a8aaa0907b65503b25100000000a1f344759677d8a92928676614c3f4b607485959a988877624c3e2d1b0700000000000000000000000010253a50657b8a9698948776614c37220c0000000000000000000000000000000000000000000000000000000e1826303d4a55606360564c402f1d0c000000000000000001142636434b52544c473b3120190e0100000000000000000000000000000000000000000000040a0c1314110b0801000000000000000001162c41566b8196abc0baa98d77624d38220d00000013283d53687d92a8c9c4a58f7a65503a25100000000000000000000000000000000000000004182a3a4f647b89969995816c5b4935211106192c3c596e8399aec1c1b39d8875604b392917293a586d8297adc2b19c86715746321e0a0000000000000000000000000000000009203448596c8196a8b9baa89b8574605646392d1f170b0000000000000000000000000000061b30455b70859ab0c6c5ae99846e59442f19040000000000000000000000000c1d2a36434a51585962666a6e72767a7d8185898d9195999da5a5a9acb0b4baa8927c67523d271200000000000000000000091e32455773889eb3bcb5a5927c67523d27120010253b50657b909b9d9d9d9d9e9e9e9e9f9f9faaa0a0a0a0a1a1a1a1a29a85705b4935210c00000a1b30414d56606366686b6d707275777a7c7f818487898b8e91939590826d5d4b37230e00000004182a3a4d5f67777d7d7561584633455660757f858378635947342010000000000000000000000000000e23374b5d657980837f76615847331f0a0000000000000000000000000000000000000000000000000000000008141c2d37444b4e4b45382f21110000000000000000000008182630353c3f37342a1d1306000000000000000000000000000000000000000000000000000000000000000000000000000000000001142636596e8499aec3b49f8974604a35200b000001172c41566c8196abc1b8a68c77614c37220c00000000000000000000000000000000000000000c22374b5c647881848074604b3d2c1a030013283d53687d92a3b4b4a3937e695645321b13293e53687e93a8c6b49f8b76614b36210c0000000000000000000000000000000005182b3b4c6277899eb4c1b5a399837461574a3d33291b110300000000000000000000000003182d42586d8297a8b4b5a7957f6a55402a1500000000000000000000000000000c182530353b3b484d515558576064686c7074787c8084878b8f93979b9fa99f8a77614c37220c0000000000000000000003162839556a80959faba49c8775604b36210b000e23374b5d687e868788888888898989898a8a8a8a8b8b8b8b8c8c8c8c8578624d3d2c1a0600000013233038454b4e515356585b55606265676a6c6f717476797b7e807b6d64523f2e1c08000000000c1c30414d596268686057463a29384557606a706e635a493b2a180200000000000000000000000000081c2e3f4b5b636b6d6a6157473a2a18040000000000000000000000000000000000000000000000000000000000010f19273135383632281a1103000000000000000000000008141c20272a221f180d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000081c30435472879cb1c6b19c87715443301c07000005182b3b5a70859aafc5b39d88735847331f0a0000000000000000000000000000000000000000081b2e3e4b5a626c6f6b605645311f0f00000b20364b607485989f9f9a8574604b3828160f24394e64798ea8b9bcab8f7a65503a251000000000000000000000000000000000000d20344859697e93a3b4c1b3a1998375645c4c463a2e2111000000000000000000000000000e23394e63798a9aa2a39b8976614c37210c00000000000000000000000000000008131c20262b34373b3f39454b4f5357546063676a6e72767a7e82868a8d8a7d675947341f0b00000000000000000000000b20354b6073818c908e8679635645321e0900081c2e3f4e60687172727373737374747474757575757676767677777770625a48341f0f0000000005131a283236393b3e404337444b4d4f525457595c58616366696a655e52453521110000000000001223303b484d53534b4539291b2839454b555b594d493c2c1d0d00000000000000000000000000000011212e3d494e5658544c46392a1c0c000000000000000000000000000000000000000000000000000000000000000009151d2023201d150a000000000000000000000000000001080b12140d0b0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b20354b60758a9fb4c4ae99846f593625130000000b2034485973889eb3c4af9a846f5a3a2a180400000000000000000000000000000000000000000010202e3c494d565a564b45382715010000091d3245566176828a8a8478625645311a0a0b20354b6075899eb4b5a8937d68533e2813000000000000000000000000000000000005182b3b4b6073859ba7b8bfb3a19986796c61584b3f2e1b0b0000000000000000000000000c21364a5b657b858c8c8579635847331f0a0000000000000000000000000000000000070b11182022262a2832363a3e36434a4d515559586165696d71757876675f4d3b2a18040000000000000000000000081d314455606c787b7973635b49382816030000112131424e535c5d5d5d5e5e5e5e5f5f5f5f54606060616161616261584d483c2b19010000000000000a161e212426292b2e263135383a3d3f42443a464c4e515355504c403527170300000000000005121d2b34373d3d3632281b0b1b28323640454338352c1e0e0000000000000000000000000000000003111f2c353841433f3633291b0c0000000000000000000000000000000000000000000000000000000000000000000001080b0e0b0902000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d22384d62778da9bac1ac97816c57422c170000000d22374d62778ca7b8c1ab96816c56412c170000000000000000000000000000000000000000000002101e2b35384144403631271a0a000000021528384758616d75766f625a4838271500081d3144556f8499a7a49c8978624d38220d0000000000000000000000000000000000000d1c3043546278899eaabbbfb3a49c8c8176655d4b392917030000000000000000000000071a2d3d4b5d6570767771635b493a2a17040000000000000000000000000000000000000000050b0d1115161e212428253035383c403a464c50545755606261574d41301d0c00000000000000000000000001152737444b5a6266646054493d2c1a0a000000031424313b3e4648484848494949494a4a4a434b4b4b4b4c4c4c4c4c473a342b1d0d000000000000000003090b0e11131618141d202225272a2c2f293336393c3e403b382f2117090000000000000000000d1820222828211e160a000a161e212a302e2320190e000000000000000000000000000000000000010f1a21232b2e2a211e170b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010253a4f657a8fa4c5bfa9947f6a543f2a1500000011263b50667b90a5c5c9a8927d68533d28130000000000000000000000000000000000000000000000000e1920232c2f2b201d150a00000000000a1a2a3a474c566061574d483c2b1a0a00011426374f647a898f8d867a645a4835200b00000000000000000000000000000000000001142636485a667c8c9fabbac2b6aa9f96887b655746331e0a0000000000000000000000000f1f2e3f4b4f586161594d493c2c1c0c000000000000000000000000000000000000000000000000000003090b0f13131c2023272b2933363a3e37444b4d4b46393023130000000000000000000000000000091927313c484d504f4b43362c1f0f000000000006141f262931323333333334343434352630353636363637373737332a20190d000000000000000000000000000000010001080b0d101215171a171f212426292b26231c11030000000000000000000000050b0d13130b090300000003090b151b190e0c06000000000000000000000000000000000000000000060c0e1618150c0a030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040b0c0f0f0f0c0a0400000000000000000000000000000000000000000000000000000000000000000000000010263b50657b90a7b5b9a7927d67523d2812000000152a3f546a7f94a9bfbcab8f7a644f3a240f00000000000000000000000000000000000000000000000000060b0d171a160b0902000000000000000c1c2a3338454b4b4639342b1d0d0000000922364a5c6475797871645c4a3c2b19050000000000000000000000000000000000000008182b3c4c5e677d8d9fa9b8c5bbb4a69d8976614c36210c0000000000000000000000000110212e373a474c4c473b352c1e0e000000000000000000000000000000000000000000000000000000000000000000070b0e1215171f212529273135383633291b130500000000000000000000000000000009151d2b35383b39353026180f01000000000000020b11131c1d1d1e1e1e1e1f1f1f1f141c2020212121212222211f170c05000000000000000000000000000000000000000000000000000200040a0c0e111415100e090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080b12181f22242524211f17120b090300000000000000000000000000000000000000000000000000000000000000000c21364c6176899a9fa89e8e79644e39240f000003182e43586d8398adc2b59f8b76614b36210c0000000000000000000000000000000000000000000000000000000001050100000000000000000000000c171f27313636322820190d00000000071b2e3e4a576064635b4e4a3e2d1e0e0000000000000000000000000000000000000000000e1e2f404d5f677d8b9ea7b3bfc4b7a7907b66503b26110000000000000000000000000003101b222a333737342a21190e000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c1014151d2023211e170b000000000000000000000000000000000000010e1920222624201c140800000000000000000000000007080808090909090a0a0001080b0b0b0c0c0c0c0d0c0a0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070b10171a1d1e1d1a160f0d070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000209151d20272a3437393a3937332927211e160a040000000000000000000000000000000000000000000000000000000000000a1f3346586379848b8d897f6a5c4a36220d0000071c31475c71869cb1c6b29d87725746321e0a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a151d20211e160b0500000000000010202e39454b4f4e493d362d200f0000000000000000000000000000000000000000000000112230414d5f677b8999a1b2b6bea7927c67523d2712000000000000000000000000000000080c171f21221f180c0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080b0d0c0a03000000000000000000000000000000000000000000050b0d110f0b080100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000308050200000000000000000000000000000000000000000000000000000000000000000000000000000000000108131c20252c2f3233322f2b24221b100800000000000000000000000000000000000000000000000000000000000000000000000000000000000009151d2731353c3b474c4f4f4e4c473a3d3632281f170c00000000000000000000000000000000000000000000000000000000000417293a495b63707678746a614f3e2d1b070000081d32475d72879cb2c3ae99846f593929160300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090b0c0903000000000000000002101b2832363a38352c211a0f01000000000000000000000000000000000000000000000004132331414d5d657783919ca5aea08d78634e38230e0000000000000000000000000000000000040a0c0c0b0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070b0d0f10100f0c0b04000000000000000000000000000000000000000000000000000000000000000003090c191e1b17130f0c0903000000000000000000000000000000000000000000000000000000000000000000000008141c2530353a4145484847444039362d231c11010000000000000000000000000000000000000000000000000000000000000000000000000000021019273137444b51585961646464615858524b4539332a1c1302000000000000000000000000000000000000000000000000000000000c1c2c3d494e58616260554f4332201000000003192e43586e8398a6aea4947f69543f2a1400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a161e212423211a0f070000000000000000000000000000000000000000000000000000051323313f4b59626e7c87929995826d5b4935210c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c1316150e0c06000000000000000000000000000000000000000000000000000002090b11131c202224252524221f18110b08010000000000000000000000000000000000000000000000000000000b161e212e33302c2825211e1615120e0b0801000000000000000000000000000000000000000000000000000000010f18263036434a50575a5d5d5c5a554f4a3e372e1d15090000000000000000000000000000000000000000000000000000000000000000000000000614202d37444b5560676e7377797a7976736e6760574c473a301d1509000000000000000000000000000000000000000000000000000000000f1f2c363a474c4d4b443732251502000000000d23384d6278889699958675614b36210c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090b0f0e0c0600000000000000000000000000000000000000000000000000000000000513212e3b484c5f67747d848073604b3d2c1a06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000106040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c171f21282c2a2320190e0000000000000000000000000000000000000000000000060a151d2026253035373a3a3b3937342a26201c1408000000000000000000000000000000000000000000000000000b1b283236434845413e3a3632282b2723201c1414100c0a0400000000000000000000000000000000000000000004121f2d36434b5460656c6f7273726f6b645c504b3f3127190a00000000000000000000000000000000000000000000000000000000000000000000081624323e4a556069747c83888c8e8f8e8c88837c756b61584d4131271909000000000000000000000000000000000000000000000000000000010f1a212a33373835312719150700000000000c2035495a627780848077615746331e0a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003111d2a34414d5560686f6b605544311f0f000000000000000000000000000000000000000000000000000000000000000000000000000000000002090b161b1916120d0c06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003111c2a33373e413f38352c1e0e0000000000000000000000000000000000000000040e1a212731363b36434a4c4f50504f4c473b3b3530261812030000000000000000000000000000000000000000000003162839464b585d5a57534f4b4639403c383530262925211f1716120f0b09020000000000000000000000000000061423303d4a546068737a818487888784807971655d4b4437281a0a000000000000000000000000000000000000000000000000000000000000000008162634424f5c64747e8891989ea6a4a4a3a69d9892898076675f4b443727190900000000000000000000000000000000000000000000000000000000060c171f2123201d15090000000000000006192c3c4959626b6e6b6159473929170300000000000000000000000000000000000000000000000000070b0b0b080100000000000000000000000000000000000000000000000000040a09080604030100000000000000000000000000000000000000000000000000000000000000000000000000000d181f3037444b5359554b4437271501000000000000000000000000000000000000000000000000000000000000000000000000000000000a151d202c312f2b2723201917120e0b0801000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011212f3a474c5356554d493c2c1e0e0000000000000000000000000000000000000c171f2c3538454b515654606264656564615958504b4336301e160b000000000000000000000000000000000000000000091e324657616e73706c686461575955514e4b43363e3b37332a2b2824201d150a09000000000000000000000004142431414d5c64737e878f969a9d9d9c99958e867b6c6055453828190900000000000000000000000000000000000000000000000000000000000006162634445160697a86939da6adb3b8c4b9c4b7b3ada89e95887d6c605544372715020000000000000000000000000000000000000000000000000000000000040a0c0d0b08010000000000000000000e1e2c3b484c5659554c473a2a1b0b000000000000000000000000000000000000000000050b0d14131c2020201d14160f0d07000000000000000000000000000000000000040a0c1a1f1e1d1b1918161413110f0e0c0a04000504020000000000000000000000000000000000000000000000000000000512192731353d44403631271909000000000000000000000000000000000000000000000000000000000000000000000000000000000a1a273136414644403c38352c2c2824201d15130f0b09030000000000000000000000000000000000000000000000000001080b0b08010000000000000000000000000000000008182f404c5861686b6a635a493c2c1906000000000000000000000000000000010f1c29333d494e5660666b707477797a7a7977736d6660544d4032281b0b0000000000000000000000000000000000000005182b3b4b6175828885817d7a76726e6a676360545754504c473a413d39363127231c1103000000000000000001122231424e5f677a85939da5acafb2b2b1afaaa39b8f81736056453726140100000000000000000000000000000000000000000000000000000000031424344451626b7e8b9ca4b3b7c4c7c2bebec0c4c8c6b9b3a79e928173605544311d14000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1d2b343741444037342a1c0c0000000000000000000000000000000000000000070d19202229253035363531262b24221b10080100000000000000000000000000000c181f222f343432302f2d2b2a28262523211f171c1b19171614130f0d08000000000000000000000000000000000000000000000009151d20282f2b201d15090000000000000000000000000000000000000000000000000000000000000000000000000000000002152738454b565b5955514d493c413d393531272925211e1614100c0a040000000000000000000000000000000000000709141d20201d15090300000000000000000000000000011426364c5e65767d817f78635a4935200c000000000000000000000000000002101f2d3a474c5b636d757b8185898c8f8f908e8c88827b73675f4b4639291b0b0000000000000000000000000000000000000b203448596d82979d9a96938f8b8783807c7875706d696561585a56524e4b4538382f211101000000000000000f1f30404e60687d8a9ba3b2b7c3c4c7c8c7c4c1b5b09f968374605544311d11000000000000000000000000000000000000000000000000000000001121324251626b80939faab6c2c3b7b2aca9a8aaafb3b9c6c5b8b39f978373604b42311e0e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1820222b2f2b221f180c0000000000000000000000000000000000000004101b222b34383e36434a4b4b4437403a362e201c14080000000000000000000000000c1c2a333744494947464442413f3d3c3a3836332932302e2c2b292825221b10020000000000000000000000000000000000000000000001080b131a160b08020000000000000000000000000000000000000000000000000000000000000000000000000000000000091d314556606b706e6b67625a5a56524e4b44373e3a3632282a26211f1715110d0b05000000000000000000000002101b222631353531271e160b000000000000000000000000081c304354657c899396948a78624d38230d000000000000000000000000000010202e3d4a58616c79828990969b9fa9a4a5a5a4a69d9890877c6d6157463929190900000000000000000000000000000000000d22374c62778b9fb2afaca8ab9f9c9995918d8986827e7a77736f6b67646056504c402f1f0f0000000000000a1a2d3d4d5f687e8d9fa8b5c1c8c5bdb8b6b7bdc8c9bdb0a1998373604b3f2e190900000000000000000000000000000000000000000000000000000b1b2e3f4f606b80969eb4bbc2b6b1a59d979493959a9ea8b1b6c2bdb1a197826d604e3c2b190600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b0d1619160c0a04000000000000000000000000000000000000000c171f2e373c484d545954606060555a554f4a3e35302618100200000000000000000004182a3a474c595f5e5d5b5958565452514f4d4c463a47454342403e3d3a372e20130500000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b20364b6074808684807c7874706c6763605557534f4b45393f3b37332a2b26222019160f0d070000000000000110202e3737444b4b443732291b0b00000000000000000000000b20354b6073879da8aba8947f69543f2a14000000000000000000000000000e1e2e3e4b5b6376818b979ea7abb0b4bac7babac4b7b2ada59c918275615746372614010000000000000000000000000000000010263b50657b90aabbc1c1c9bcb5b2aeaaa6a89f9b9793908c8884807d797571655e4c3d2d1a0700000000021527384a5b677d8d9fabbac6c0b4b0a8a3a1a2a8b2b7c4bfb3a195806b5d4b37271501000000000000000000000000000000000000000000000000031729394b5d697e939eb0bcbdb0a49c9187827e7e808489929ca4b5bcbfb1a0937e685a4935201000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002101c2a333e4b4f5a62696e72757575736f6b645c524b43362d20130500000000000000000a1f334758616f747372706e6d6b696866646361585e5c5a59575554524f4b3e3023130100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003172939566c81969b9995918d8985817d7975716c686460575854504c473a403c38352b2b24221b1002000000000f202e3e4b4f556060554b46392916030000000000000000000417293a50667b90a5b7c6ad98826d5837261401000000000000000000000005192b3c4b5c647987979faab3b8c5c5bfbbb9b8babfc6c8c3b6b2a0988575615544311d0f000000000000000000000000000000000e23394e63788ea0a8acafb3b8c5bec3bfc6bab4b0aca9a5a69d9996928e8a867c655b4a36210c00000000091d31455663798b9fabbcc4b8b3a29a928e8b8d939da6b5c1bfb59f8d7b655544311d090000000000000000000000000000000000000000000000000a1e334657657b8c9fb4bcbcb59e96867c736d69696b6f757d86969fabbcbeb49f8a78624d3e2d1b070000000000000000000000000000000000000000000000000000000002080b0802000000000000000000000000000000000000000000000000000000000000000000000000000311202d3a474c5c646e787e83878a8b8a8885807a716860544a3e30231406000000000000000c22374c617683898987858482807f7d7b7a7876757371706e6c6b6968645c4d41301e0a000000000000000000000000000000000000000000060c0e1619160d0b050000000000000000000000000000000000000000000000000000000000000000000000000000000a1e33465774899eb0aeaaa6a79e9a96928e8a86827e7a76726d696561585955514d483c413a362e2011030000071a2d3e4b5c647075756e615746321e0a0000000000000000000a1f3347586e8398adc3c6b19b86715544311d0800000000000000000000000b2035485a647a8a9ca5b4bbc8c0b4b0aaa6a4a3a5a9b1b5c2cabeb2a39a8473604b3d2d1a070000000000000000000000000000000c2135495b6d828e93969a9ea7a5a9b0b4c0cdc9c5c2bec4b7b3afaba7aa9f9b8b79634e39230e00000005182a3b4b6074869ba9bac3b7a69e91857d7976777e879ba3b5c4bcab9c8674604b3727150100000000000000000000000000000000000000000000071a2d3e4b6175879daabbbcab9f93817466605454535557606875818d9fb5bdbaa899836e5c4a36220c00000000000000000000000000000000000000000000000000030c09151d201d15090b010000000000000000000000000000000000000000000000000000000000000000000111212e3e4a58616d7a838b93999d9faa9f9d9a958f867d73645c4d4131241405000000000000172d42576c81979e9e9c9b9997969492918f8d8b8a8887858381807e7d7a675f4d39250800000000000000000000000000000000000000010f1a21232c2e2b2220180d00000000000000000000000000000000000000000000000000000000000000000000000000000c21364c61768ba7b9c3c0c5b9b3afaba7a99f9b97938f8b87837f7b77726e6a66625a5a564f4a3e2e211100000d21364a5c647a858a898275614b36210c0000000000000000000c21374c61768a9fb4c9c9b49f8975604b35200b000000000000000000000a1d30414d6278889da8b6c3c0b4afa29a94918e8e90949ca4b3b8c4c1b4a295806b5b4a36210f000000000000000000000000000000061a2c3d53646d797e8185888c90949aa2b4c8d3c3b6b2b4bcc9c0c0c8bbb4aa937e69543e29140000000b1f3448596a8095a3b5c5b7a59d887c70686361626876859ba6b7c9b5a4927d685544311d08000000000000000000000000000000000000000000000d21364a5c6c8197a5b7beb59f8d7e6c60564a43363e39454b56606c7f949fb0c3b3a18e7a644f3b2a1804000000000000000000000000000000000000000000000006141f272731363127251e130500000000000000000000000000000000000000000000000000000000000000000f1f2e3f4b5c6476828f999fabaeb2b4bbb5b3afaaa49c92867a675f4e423123130100000000001d33485d72889db2b3b2b0aeadaba9a7a6a4a2aa9f9d9c9a98979593928f7d675236251300000000000000000000000000000000000005131f2c353841434037342b1d0d000000000000000000000000000000000000000000000000000000000000000000000000000b20354b60758a9fb4cad5d6ccc9c5c1c7bab4b0aca8ab9f9c9894908c8884807c77736f6b645c4b3f2e1c08000f24394e647a8b9a9f9f95806a55402b150000000000000000071a2d3d53697e93a9bacdcdbaa98d78634e38230e000000000000000000001025394d5f70849aa6b7c6bdb1a29a8e857f7b79797a7f86919da6b6c3c0b49f8c79634e3d2c1a060000000000000000000000000000000f1f3546535c64686c7073777b7e849ab0c5c5b6a59d9faba7abafb3b7bbaa937e69543e2914000004182a3b4c62778a9fb4c2b9a79d8778675f534e4c4d586277889db2c0c2b29d8774604b35200d000000000000000000000000000000000000000000081b2e3f4e64798c9fb4c3b2a0947f69604b4538302529283238454b616c8196a5b6bfad98836e5947341f0b00000000000000000000000708000000000000000000011425323b37444b44373a312314060000000000000000000000000000000000000000000000000000000000000a1a2c3d4b5d657a8898a0aeb4bcc9bcb8b6b6b8bdc2b5b1a49c8b7d68604e42311f0f00000000001e33485d73889db2c6bfc1c3c2c0bebdbbb9c8bbb4b3b1afaeacaaa9a79c87725443301c0700000000000000000000000000000000011323303d494e5659554c483b2b1909000000000000000000000000000000000000000000000000000000000000000000000000081d31445570869bb0c5d6d7c7bab4b4bac7c0c4c1c9bcb4b1ada9a5a59d9995918d8884807a655d4b37230e00162b40556b8095a9b5b09b85705b3c2b1905000000000000000c21364a5b71869bb0c7d7d7c7a6917c66513c2711000000000000000000071a2d3d52677c91a2b4c4bfb19f968479706a666463656a717c889ca5b6c7bbaa99846f5b49362108000000000000000000000000000000011828353e4a4e53575a5962656b8196abc0b8a78f878a8e92969a9da6aa9f8b78624d38230d00000b1f3447596c8197a8babfb39e8979635a4d4039363a4859667c91a2b4c8b6a5917c66513b2b180500000000000000000000000000000000000000000e22374b5d6f849aabbcb8a698826e614f4231271c1314161e2832434b6075879cb2c5b49f8a77614c37220c0000000000000002090b151c1d13110b0100000000000f1f32434f54556055524e41312414020000000000000000000000000000000000000000000000000000000003162838495b657b8a9da6b2bebbb4aea7a3a0a0a3a8b0b5c1b5aa9f8d7e68604e3d2c1a0a00000000192e44596e8399a8a8aaacaeafb1b3b4bbc8babbbdbfc1c2c3c1c0beb49f8a72604a35200b000000000000000000000000000000000a1e30414d5b636b6e6b6259483727150200000000000000000000000000000000000000000000000000000000000000000000000114263753697e93a7b9cccdbaa99f9fa9a7abafb3b8c5bfc3c2bec3b7b2aeaaa6a79e9a968d7b65503a251000152a3f546a7f94a9c7b39e89745a4834200b000000000000021527374e63798ea3b5c9e5d4bfaa957f6a55402a150000000000000000000c21364a5b71869cb1c0c8b3a1968172635b55514f4e50545e6678879ca9bac8b3a18e79634e362513000000000000000000000000000000000a18202d36393e413b484c5a6f849aafc4b39e897376797d8184888c908b7d675a4935200c00001325364c61778b9fb4c6b2a1917c665b493c3024212a3b4c5e6f849aafc2c3af9a846f594834200b0000000000000000000000000000000000000005192b3c4f657a8fa2b3c1b39e8877614c43321d150a0000030a161e324556677d92a7b8baa9937e68533828150200000000000a151d202a323328251e1305000000071a2d3d4f616974757268604e42311f0b00000000000000000000000000000000000000000000000000000000091e3245566379899ea8b7c0b4aa9f99928d8b8b8e939ba3b4b9bbab9f927e685b49382715020000000f24394e647a8a91939597989a9c9d9faaa3a4a6a8aaabadafb1b2b4b29d87725443301c07000000000000000000000000000000001025394d5f677981838077625544311d080000000000000000000000000000000000000000000000000000000000000000000000000b21364b6075899eb3c9c9b49f8b8a8e92969a9ea6a5a9adb1b4bcc9c1c3bfc5b8b3afab98836d58432e180011263c51667b91a6c7b9a88d77624d38220d000000000000081d3144556c8196abc1d2e4d8c3ad98836e583727150200000000000000000e24394e63798ea4b6cabbaa9a847260544a3d3c39393b404c5963798b9fb4c5bfac96816c5443301c0700000000000000000000000000000000010f1a2124292c2b34485973889eb3c5af9a85706064686b6f73777a78675f4d3c2c190600071c3043546a7f94a9babbaa99836e5e4c3c2c1e120d1d2f4050657b90a4b6cab59f8c77624d37220d000000000000000000000000000000000000000b2035485a6e8399aec0b5a3917c675847332514020000000000021628384b6074889eb3c7af9a846f5645321d09000000000a1a2731363f47483d3a3123150000000d21364a5c697f898b877d68604e3a261100000000000000000000000000000000000000000000000000000006192c3c4b6075869ca7b9bdb1a29a8c837d787676787e85929ea8b8bcb49f8a79635645311d090000000d21364a5c64777c7e8081838586888a8c8d8f91939496989a9b9d9f9d937e6954362513000000000000000000000000000000000012273d52677d8b9698958674604b36200b000000000000000000000000000000000000000000000000000000000000000000000000091e3245566d8297adc5c8b39e8874797c8084888c9094989c9faba8acb0b4b9c6bfc7af9a85705a45301b000e23384d63788da9bac6a5907b66503b26110000000000000b20364b6074889eb3c8dddfdcc6b19c86715544311d080000000000000000152a40556a7f95aac2cab49f8c78625443362d26242425303b495b6a7f95a7b8c8b39d8874604a35200b000000000000000000000000000000000000070d0f131722374d62778ca7b8c1ab96816c564f52565a586165625a4d41311e0e00000b20354a6073879db2c7b49f8c78624d40301e0e00001223374b5d72869cb1c7bcab937e6953382816020000000000000000000000000000000000000d22384d62788b9fb4c2b09b85715f4d3a2a1807000000000000000a1d3144556c8197acc1b49f8a75604b36200b00000009192738454b545c5d524e41331c1308071a2d3d4e64798c9ea49c927e68533e29130000000000000000000000000000000000000000000000000000000c2135495b6b8096a4b5c5b19f9784786e676361616368707d8a9ea7b8baa89b8574604b372715020000071a2d3e4a596267696a6c6e7071737576787a7c7d7f818384868889877f6a604f3b180800000000000000000000000000000000091e33495e73889ea9aea4907b65503b2510000000000000000000000000030a0c12100b0801000000000000000000000000000000000216283850667b90a7b8ccb8a7907b66676b6f73777b7f83878a8f93979b9ea8a6aaaea997826d57422d18000b20354b6075899fb4bea9947f69543f2a14000000000005182a3b51667c91a6b8cbcacacfc9b49f8a75604b36200b0000000000000003192e43586e8398adc3c3ae99836e5a49362518110f0e121d2c3d4b6075889eb3c8b7a68f7a644f3a240f0000000000000000000000000000000000000000000011263b51667b90a6c5c8a7927d68523d3d413a474c504d483c3123130000000f253a4f647a8fa5b6c4ad98836e5a49352212000000081c2e3f556a8095aac4c9af9a846f5645321e09000000000000000000000000000000000005192b3c556a7f94abbcb6a4917c665141301c0c00000000000000000215273751667b90a6c3baa98f7a644f3a250f0000011527374556606a7172685f50433025180921364a5c6e8399abb6b09a85705b45301b0600000000000000000000000000000000000000000000000000031628394d63788b9fb4c2c1ac978173635b524e4b4b4e535f6779899eaabbb5a3937e695544311d080000000f202d3b474c52535557595a5c546061636566686a6c6d6f717274726a614f42321f0000000000000000000000000000000000081e33485d73889db2c3aa947f6a553f2a1500000000000000000000000b171e212725201c1408000000000000000000000000000000000b20354b6074889eb3c8c5ad97826d56565a5962666a6e7276797d8185898d919598988b79634e39240e00081c30435471869cb1c2ad97826d5836251300000000000b1f3447596e8499aec5bcb5b5bcc9bbaa8e79634e39230e00000000000000061b31465b70869bb0c5bda7927d68523c2c1808000000000f1d3245566b8196abc5c4a9947f69543f2a1400000000000000000000000000000000000000000000152a3f556a7f94aabfbbaa8e79644f39282c2a33373b38342b1d130500000012283d52677d92a7bdb8a6907b65503c2c1904000000001124394f64798ea6b7c9b49f8a75604b36210b00000000000000000000000000000000000b2035485a71869cb1c9b19c8673604a352012000000000006070503000c21374c61768ca5b7c7a8937e69533e29140000081d31445560747f87877d6a614a433627192d3d4e64798c9fb5c0ad98826d58432d180300000000000000000000000000000000000000000000000000091e3246576d8297aabbcec6b19b857a6b60564a3e3639414d5b657b8c9fb4c1b39d8874604b36200b000000010f1d2a34373c3e4042434536434a4c4e4f51535556585a5c5d5f5d544f43322414020000000000000000000000000000000004192f44596e8499aec3ae99836e593b2b18050000000000000000000e1b2933363d3a353026180c000000000000000000000000000000081d3144556c8197acc4c9b39e8975604b3b484c505458576064686c7074787c8083837b655b4a36210c0001142636586e8398adc3b09b86705443301c07000000000d22374c62778b9fb4bcab9f9fabbcc8a7917c67523c271200000000000000071c31475c71869cb1c6c8a38d78634e38230e0000000000021528384e63798ea7b8c3ae98836e59432e1900000000000000000000000000000000000000000003172939596e8398aec3b49f8a75604b362116171f21252220190d00000000000f24394e64798e9fb2b39e8874604b35200e00000000000d22364a5c73889db2c8baa98f7a65503a251000000000000000000000000000000000000d22384d62788da4b6bcab937e695443301c0700010a10121c1c1a1816131f33475872889db2c1ab96816c56412c1701000b20354b607383949c9d927f6c6054443728364a5c6e8399abbcb4a28f7a644f3a250f00000000000000000000000000000000000000000000000000000c21364b6176899eb4c8d8c9b5a39b8c8074645c4b4538303d4b5d6c8196a9bab7a6917c66513c261100000000000d181f2227292b2c2e3025303537383a3c3e3f41434546484a483f3c32251506000000000000000000000000000000000000152a40556a7f95aabfb29d8873594834200b00000000000000000e1e2b39464c52504b4336291c0c00000000000000000000000000000115273750657a90a6b7cbb9a7917c66513834373b3f39454b4f5357546063676a6e6e655d4b3d2d1a070000152a40556a7f95aabfb49e8974604a35200b000000071b2e3e54697f94aabbb59f8c8d9fb5c0aa95806b55402b1600000000000000061b30465b70859bb0c5bbaa8b76614c36210c0000000000000b20354a6074899eb3c6b19c87715c3a2a170400000000000000000000000000000000000000000a1e33465772879cb2c6b19c87715645321e09040a0c100d0b050000000000000d21364a5c6c81949c9e96806b5544311d080000000000071b2d3e586d8297adc2c7a9947f69543f2a14000000000000000000000000000000000013283e53687d93a8c2b49f8b77624c3625130005131e25273132302d2b2826293a5b70859ab0c3ae99846e59442f19040012273c52677c91a2b1b29d958172605545383d4e64798c9fb5c1af9a85705c4b37220d000000000000000000000000000000000000000000000000000011263c51667c91a8b9cdcac7c1b5aa9f95867a6b60564b3f323f4c62778a9fb4c4ad97826d58392917030000000000050b0d12141517191b131c2021232527282a2c2e2f313334332a272015070000000000000000000000000000000000000011263b51667b90a6c4b7a68c77624d37220d000000000000000e1e2c3c48576167656054463a29170400000000000000000000000000000b20354b6074889db3c8c5ad98836d56453222262a2832363a3e36434a4d51555959504b3f2f1f0f00000012273c51677c91a6c8b9a88d78624d38230d0000000d22374b5c71869cb1c6af9a84879db2c3ae99836e5938281602000000000000051a2f445a6f8499afb9b49f8a75604b35200b000000000000071c3043546f8499aec4b49f89745847331f0a00000000000000000000000000000000000000000c21364b61768b9fb5c2ad98836d583828160200000000000000000000000000071a2d3e4a60727f87898375614b3726140100000000000014293e53697e93a8c8c3ad98836e583a2a170400000000000000000000000000000002152838586d8298adc2b09b8670594734180800132330393c46474542403e3b3943586e8398adc3b09b85705b46301b0600162b40556b8095a9babcaf9f9682736056464a5c6e8399abbcb5a3907b66503e2e1b080000000000000000000000000000000000000000000000000001162b41566b8096abc6c3b7b2b5bcbbb4a49c8c8074655d4b463948596f8499aec4b29d87725746331e0a000000000000000000000002040000070b0c0e1011131517181a1c1d1f1d15130d0300000000000000000000000000000000000000000d22374d62778ca6b7c4a6917c66513c26110000000000010f1e2c3c495a62767c7a73615846331f0d0000000000000000000000000000081c3043546c8196acc3c9b49e8975604b36211115161e212428253035383c4043433b382f2111010000000e23394e63788eaabbc6a6907b66513b26110000031628384f647a8fa4b6b9a8927d8399aec4b29c87725645321e090000000000000014293e54697e939ea7a79c86715443301c0800000000000000132536566b8096abc0baa88c76614c37210c000000000000000000000000000000000000000010253a4f657a8fabbcbfa9947f6a543f2a150000000000000000000000000000000f1c304354606972746e615746321909000000000000000f243a4f64798faabbc7b29d87725847331f0a000000000000000000000000000000091d32455671869cb1c0ab95806b563b2a18000e1f30414d525b5c5a585553504e4c576d8297acc2b19c87715c47321c07000e24394e63798b9faababdb0a098837461574e64798c9fb5c3b19b86715e4c3820100000000000000000000000000000000000000000000000000000041a2f44596f8499aec4b7a59d9fabb6c2b5aa9f96867b6c61574b3f53697e93a8c5b7a58b76614b36210c000000000000000000000000000000000000000000000001030507080a080000000000000000000000000000000000000000000000000b2034485973889db3c0aa95806b55402b1600000000010f1f2c3c495a627887928f8476614c3b2b190500000000000000000000000000011426364f657a8fa5b7cbb9a8917c67513929160303090b0f13131c2023272b2e2e25231c1103000000000b20364b60758a9fb4bfa9947f6a543f2a150000091e3245566c8197acc2b49e89758096abc0b49f8a76604b36210b000000000000000b20354a60727f898f8f897c6650362614010000000000000014293f54697e94a9bec6a28d78624d38230d000000000000000000000000000000000000000014293e53697e93a8c9c5a5907b66503b261100000000000000000000000000000000132536434a545d5e594b4639291600000000000000000b20364b60758a9fb4c9b6a58c77614c37210c0000000000000000000000000000000b20364b60758a9fb4c9a6917c66513c2711061a2c3d4d5f6771716f6d6b68666361586c8197acc1b29d87725d48321d08000c21364a5b677d8c9fa9babeb2a1998475615c6e8399abbcb6a4917c6751402f1c020000000000000000000000000000000000000000000000000000071c31465c71869bb1c6b29d878c9ca4b4bbbbb4a49c8c8175655d4c4f647a8fa6b8c1a38e79644e39240f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005182b3b596f8499aec4af9a846f5a3c2c19060000010f1f2c3d495a6378879da5a298836e594834200b00000000000000000000000000000b20354a6073879db2c7c6ae98836e5746321e0a000000000000070b0e12151919100e08000000000000081d31445571879cb1c2ad98826d5836261401000b21364b6075899eb3c3ad98826d7d92a7bdbcab8e79644e39240f00000000000000071c304354606a75797a75665e4c381808000000000000000012273d52677c92a7bcb8a38e79634e39240e0000000000000000000000000000000000000001152737576d8297acc2b8a78c77624d37220d0000000000000000000000000000000008182530353f4749443632291b0b0000000000000000091d32455671879cb1c6c3a5907a65503b25100000000000000000000000000000000e23384e63788daabbbcab8d78634d38230e0c2135495b677d86878582807d7b797674718197acc1b29d87725d48321d0800071a2d3d4d5f677c8b9fa9b9bfb3a29a857764798c9fb5c4b29c8773604b352011000000000000000000000000000000000000000000000000000000071d32475c72879cb1bea9947f7a86959faab5c1b6ab9f96877b6c61576074889ea8aaa38e79644f39240f0000000000000000050a080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000152b40556a8095aabfb39e89735a4935200c00010f1f2d3d495b6378879da5b6b59f8b77624d37220d0000000000000000000000000000071c3043546b8196abc3c9b49f8a76614b36210c0000000000000000000000040400000000000000000002152737596e8398aec3b19b86715443301c0805192b3c52677d92a7b9b7a5907b657a8fa4c4c9a7927d67523d28120000000000000000132536434a5660646561574c402f1c00000000000000000012273c52677c91a7bcb9a48f79644f3a240f00000000000000000000000000000000000000081d31445571869bb0c6b39e8873594834200b000000000000000000000000000000000008131c202932342e211e160b00000000000000000002152838596e8399aec3bda8937d68533e281300000000000000000000000000000011263b50667b90a5c8b49f8a75604b36200b0e23384e63798c9b9c9a979593908e8b8987889db3c7b29c87725d47321d0800000f1f30414d5e667c8b9ea8b9c0b4a39b86778399abbcb7a6927d685443301c08000000000000000000000000000000000000000000000000000000071c31465c71869bb1bfaa95806a74808c9ba3b4b9bcb4a59d8d8176665e657c899295918573604b35200b0000000000070c0e1a1f1d140b07000000000000000000000000000000000000000000000000000000000000000000000000000000000011263c51667c91a6c4b8a78d78634d38230e02101f2d3d4a5b6379889da6b7bfb3a18e79634e39240e0000000000000000000000000000001325364f647a8fa5b6cabaa9927c67523a29170400000000000000000000000000000000000000000000152b40556a8095aabfb49f8975604b35200b0b2035485a6f849aafc5b29d877361768ba6b7c0ab95806b56402b1600000000000000000818253038454b4f4f4b46392f221100000000000000000013283e53687d93a8bdc9a38e79634e39240e000000000000000000000000000000000000000b20354b60758a9fb4c4af9a846f5a3b2b180500000000000000000000000000000000000000070b141d1f190c0a030000000000000000000000162b41566b8096abc0c0ab96816b56412c1600000000000000000000000000000013283d52687d92a7bdb39d88735645311d09152a3f556a7f94aab1afadaaa8a5a3a89e9c9da6b7c6b19c86715c47311c07000001122330404c5e657b8a9ea7b8c1b5a49c888d9fb5c5b29d8874604b36261401000000000000000000000000000000000000000000000000000000041a2f44596f8499aec3ae98836e606b7985949ea8b3bfb6ab9f97877b6c6065767d807c73605544311d08000000010f1a21243034332a201c13080000000000000000000000000000000000000000000000000000000000000000000000000000000d22384d62778da6b8c5a7927c67523d271210202d3d4a5b6379889da6b7bfb3a199836e5b4a36210c0000000000000000000000000000000822364a5c72879db2c7c7ae99836e5846331f0a0000000000000000000000000000000000000000000012273d52677c92a7c8baa98d78634d38230e1325364d62788b9fb4c0aa95806b5773889db2c4ae99846f5939291603000000000000000008131c2832363a3a3632281b1103000000000000000004182a3a566b8095abc0bcab8d78624d38230d000000000000000000000000000000000000000e24394e63798ea9bac0ab96816b56412c160000000000000000000000000000000000000000000000080904000000000000000000000000000013283d53687d92a8bdc4ae99846f5936251300000000000000000000000000000014293f54697e94a9beb19c86715c38271502162b40566b8095abc1c1c2c0bdbbc6b9b4b1b3b7c4c9af9a846f5a452f1a050000000412222f404c5d657a899ea7b8c2b6a69d9fabbcb8a7947e6956453118080000000000000000000000000000000000000000000000000000000001162b41566b8096abc6b39e8975605c64737e8a99a1b3b8bcb5a59d8d81746061686a67605544372614010000000f1f2d3639454a483f353025180800000000000000000000000000000000000000000000000000000000000000000000000000000b2034485a73889eb3c0ab96816b56372614202d3e4a5b6379889da6b7bfb3a1998374604b3d2d1a07000000000000000000000000000000071b2e3e566b8095abc2c9b49f8a76614c36210c000000000000000000000000000000000000000000000f24394e64798eaabbc7a6917c66513c27111c3043546a7f95abbcb4a28d78635a6f849aafc4b29d87725746321e0a000000000000000000000a161e212425211e160b000000000000000000000a1f33475870859aafc5b49f8a75604b36200b0000000000000000000000000000000000000012283d52677d92a7c7c8a7927d68523d28130000000000000000000000000000000000000000000000000000000000000000000000000000000010253a50657a8fa5c9c7b29c87725443301c070000000000000000000000000000152b40556a8095aabfb09b85705b46301b0012273c51677c91a3a9acaeb0b3b4bcc9bcbec0c2c7baab96816c56412c1701000000000412212f3f4b5c647a899da6b7c4b7b3b5bcc6b39e8975614b38271500000000000000000000000000000000000000000000000000000000000011263c51667c91a8bab8a7927d67575560697884929ea7b2beb7ab9f968374605355524b44372719090000000c1c2d3d4a4e5a5f5d544a43362513000000000000000000000000000000000000000000000000000000000000000000000000000005192b3c5a6f8499afc4b09a85705544311d2e3e4a5c6479889ea6b7bfb3a1998374605645321f0f00000000000000000000000000000000001024394e64798ea4b6cabaa9927d68523a2a17040000000000000000000000000000000000000000000b20364b60758a9fb4bfaa947f6a553f2a1520354a6073879db2c7b09a85705a566c8196abc1b59f8b76614b36210c000000000000000000000003090b0f100c0903000000000000000000000417293a4c61778b9fb4c7b19c87725544311d0800000000000000000000000000000000000001162c41566b8196abc0bbaa8e79644e39240f000000000000000000000000000000000000000000000000000000000000000000000000000000000e23384d63788dabbcc9b49f8a75604a35200b0000000000000000000000000000162b40556b8095aac0b09a85705b45301b060b20364b607485919496999b9d9faba4a6a9abacaca99f8d7a644e39240f0000000000000311212e3e4b5c6479889da6b7c3c8cacdb9a8957f6a5746321a0a0000000000000000000000000000000000000000000000000000000000000b21364b60758a9fb4c5b29d877561554b5a626f7d8898a0b2b7bcb5a197826d5c4a3c35312719090000000417293a4a5b636f747269605443301c130000000000000000000000000000000000000000000000000000000000000000000000000000162b40556b8095aac0b49f8975604b352e3e4a5c647a899ea6b8bfb3a19983746056453828150100000000000000000000000000000000000d21364a5c72879cb1c7c7af99846f5847331f0a000000000000000000000000000000000000000000091d32455672879cb2c2ad98836d58372717293950657a8fa5b6baa9937d685353687d92a8bdbcab8f7a644f3a240f000000000000000000000000000000040a0c0e0c0a030000000000010a161f334658697f94aabbc6ac97826d573727150200000000000000000000000000000000000005192b3c5a6f859aafc4b49f8a75604b36200b000000000000000000000000000000000000000000000000000000000000000000000000000000000b20364b60758a9fb5cabbaa8c77614c37220c0000000000000000000000000000152b40556a8095aabfb09b86705b46311b00081d31445560757c7f818386888a8d8f9193969797948b7e685c4a36220d000000000000000311202e3e4a5b6379879da5b7cadec9b49e8976614c43331c13080000000000000000000000000000000000000000000000000000000000091e3245576d8297abbcb7a599837361584b4d5f677782909da5b7bfb1a08e79644e39241d1509000000000a1f33465863798489877f72604a41311c0c0000000000000000000000000000000000000000000000000000000000000000000000000011273c51667c91a6c5baa88e79634e393e4b5c647a899ea7b8bfb3a199837460564538281a0a000000000000000000000000000000000000071a2d3e556a8095aac2cab49f8b77614c37210d00000000000000000000000000000000000000000002152838596e8499aec3b19c86715544311e3346576d8298adc3b49f8a76614c4f647a8fa4c4c9a8927d68533d281300000000000000000000000000060c171f2123211e1613100f0e10151d2832434c6176889eb3c8b9a8917c67523c2712000000000000000000000000000000000000000b2034485a73889eb3c6b19c86715645311d0900000000000000000000000000000000000000000000000000000000000000000000000000000000091d31455673889db3c8c8a38e79644e39240f0000000000000000000000000000152a3f556a7f94aabfb19c87725c3a2a170402152737455660666a6c6e707375777a7c7e8082827f7868604e3e2d1b0700000000000000000210202d3d4a5b6378879db2c7dccab49f8c7e696150443025180900000000000000000000000000000000000000000000000000000000031628394e63798c9fb4c2b3a19983766960555258616d7c879db2c7bea9937e69543e29140100000000000c21364c6176899a9f9d94816c5f4e3a2a17040000000000000000000000000000000000000000000000000000000000000000000000000d22384d62788da7b8c6a8927d68533f4b5c647a899ea7b8bfb3a199837460564538281a0a00000000000000000000000000000000000000000f23394e63798ea4b5c9bbaa937d68533b2a1805000000000000000000000000000000000000000000162b40566b8095abc0b49f8a75604b3521364b61768a9fb4c4ad98836d57464c61768ba6b7c0ab96816b56412c160000000000000000000000000e1a212a3337383632292825242325273138454b616d8298a6b8c7b49e8975604b36210b000000000000000000000000000000000000000d22384d62778da7b8c2ad98826d583827150200000000000000000000000000000000000000000000000000000000000000000000000000000000021527385b71869bb0c6bba6907b66513b2611000000000000000000000000000013293e53687e93a8bdb39e89745847331f0a0009192838454b515457595b5560626467696b6d6c69625a4e423120100000000000000000000002101f2d3d495a657a8fa5bacfcfbcab9f937f6b624a433626190a000000000000000000000000000000000000000000000000000000000a21364a5b6d8297a4b6bfb3a199897e746d6764666c79869bb1c6bbaa937d68533e281300000000000012273c51677c91a7b4b29f927d685847331f0a0000000000000000000000000000000000000000000000000000000000000000000000000b2035485a73889eb3c1ac97826c574b5d657b8a9ea7b8bfb3a199837460564538281a0a0000000000000000000000000000000000000000000c2136495b71869cb1c6c8af9a846f5947341f0b00000000000000000000000000000000000000000012283d52677d92a7c9baa98d78634e382c3d53687d92a8bab7a6907b655039465873889db3c4af9a846f5a3a291704000000000000000000000e1f2c353a474c4d4b46393e3b39393a37444b56606c7f95a0b2c4baa996816c5645321e090000000000000000000000000000000000000011263c51667b91a6c5bea9947f69543f2a140000000000000000000000000000000000000000000000000000000000000000000000000000000000001a2f455a6f849aafc4bda8937d68533e2813000000000000000000000000000012273c51677c91a6c9b9a78c76614c37210c00000a1a2832363c3f414437444b4d4f5154565757544d483c312414020000000000000000000000010f2035495a6d8297adc2d7d9c9bcb49d94806c60544437281a0b000000000000000000000000000000000000000000000000000000071a2d3d4b6175869ca8b9bfb3a79e9389827c7a7c828b9ba3b5c1b49f8b78624d38220d0000000000000d22384d62788a9faabbb39e8976614c37210e00000000000000000000000000000000000000000000000000000000000000000000000005192b3c5a6f849aafc4b09b8671565d657b8a9ea8b9bfb3a199837460564538281a0a00000000000000000000000000000000000000000000061a2c3d556a7f94aac1cab49f8b77624c37220d0000000000000000000000000000000000000000000f24394f64798eabbcc7a6917c67513c35495b70859bb0c6b29d8874604b353a5a6f849aafc4b29d88735846331f0a0000000000000000000d1d2c3d494e58616361575753504e4e50535560677581959eafbec1b49f8b78624d3828160300000000000000000000000000000000000000152a40556a7f95aabfc4a5907b65503b2610000000000000000000000000000000000000000000000000000000000000000000000000000000000003192e43586e8398adc3bfaa947f6a553f2a1500000000000000000000000000000f24394f64798eabbcc5a5907b65503b25100000000a161e21272a2c2e273135383a3c3e4142423f38352b1e140600000000000000000000000005192b3c4d62788b9fb4cac7c4c4c8bbae9e95817260554538281b0c0000000000000000000000000000000000000000000000000000000f1e33465763798a9ea8b7c3b8b3a79e98918f91979fa9b5c1b5a396806b5a4834200b0000000000000b2035485a667c8c9fb4b9a7957f6a553c2b1905000000000000000000000000000000000000000000000000000000000000000000000000162b40566b8095abc0b49f8a7560657b8a9ea8b9bfb3a199837460564538281a0a0000000000000000000000000000000000000000000000000f23384d63788da3b5c9bcab937e69533b2b190500000000000000000000000000000000000000000c21364b61768b9fb5bfaa957f6a5540374e63788da2b4c1ab95806b54433041576c8196acc1b7a68b76614c36210c000000000000000005182b3b495b6370767876716c6865646365686d747d87979fafbcc4b5a3957f6a5948341a0a0000000000000000000000000000000000000003172939596e8399aec3b8a68c77624c37220d000000000000000000000000000000000000000000000000000000000000000000000000000000000002172c42576c8197acc1c0ab96806b56412b1601000000000000000000000000000c21364b61768b9fb5bfaa957f6a553828150200000003090b11151719151d30393c45423b382f2a2220190e00000000000000000000000000000b2034485a6c8297aabbbfb3aeafb4c0bcb09f96827360564639291c0d0000000000000000000000000000000000000000000000000000031729394a5b657c8a9da5b5bcc5b8b3ada7a4a6acb4babdb1a39b8574604b3c2b190500000000000005192b3c4c5e6a7f95a6b7b29d87725a4835200b00000000000000000000000000000000000000000000000000000000000000000000000012273c51677c91a6c5bbaa8f7a657b8a9ea8b9bfb3a199837460564538281a0a000000000000000000000000000000000000000000000000000c2135495b71869bb1c6c9b09a8570594834200b0000000000000000000000000000000000000000091e32465772889db2c3ae98836e593844556b8095abc0b4a38d79634e36263e53687e93a8bdc4a48f7a654f3a251000000000000000000b203448596379848b8d8b87827d7a79787a7d8288929ca5b1bdc3b7a69b8574604b3b2b1900000000000000000000000000000000000000000a1e33465772879db2c7b39d88735947341f0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000152b40556a8095aabfc1ac97826c57422d170200000000000000000000000000091e32465772879db2c4af9a846f5645321d090000000000000000000b1b30414d525a57504c3f342b1d0d000000000000000000000000000005182b3b4d62788b9fb4c8b3a1999aa2b3bfbdb1a09883746157473a2a1d0d00000000000000000000000000000000000000000000000000000b1b2d3d4c5d657987979fabb4bbc8c2bcb9bbc8bbb4af9f978576615645321d0d00000000000000000e1e30404b6075889db2b6a58d78624d38220d0000000000000000000000000000000000000000000000000000000000000000000000000d23384d62788da7b8c8a8937e7b8b9fa8b9bfb3a199837460564538281a0a000000000000000000000000000000000000000000000000000006192c3c546a7f94a9c1cab59f8c77624d37220e0000000000000000000000000000000000000000031628395a6f8499afc4b19c877156454b6074889db2c7b09b85705b4935253a50657a8fa5c5bda8937e68533e291300000000000000000d22374d6277889a9fab9f9c9793908e8e8f92979ea7b2b6c3c0b4a59d8877625645311d0d00000000000000000000000000000000000000000c21364c61768b9fb5c4af9a846f5a3b2a180500000000000000000000000000000000000000000000000000000000000000000000000000000000000014293e54697e93a9bec3ad98836e58432e19030000000000000000000000000003162839586d8398adc2b49e8975604b36200d0000000000000000031628394d5f67706c655d4c483b2b1c0c000000000000000000000000000b203448596c8197a9bac0ae99838499a1b2bebeb2a19984756158473b2a180500000000000000000000000000000000000000000000000000000f1f2f3f4c5b6377828d999faaacb0b1b1b0acaa9f998f827461584738281500000000000000000000121e3245566c8196abc3a7917c67523c27120000000000000000000000000000000000000000000000000000000000000000000000000c2035495a73899eb3c6b19c868a9fa9babfb3a199837460564538281a0a000000000000000000000000000000000000000000000000000000000e23384d62788da3b4c8bcab947e69543c2b19060000000000000000000000000000000000000000162c41566b8196abc0b49f8a75604b50667b90a6b7baa9937e68533d2c21374c61778ca6b8c1ac96816c57412c170000000000000001172c41566c8196a6b5bcb5b1aca8a5a3a3a5a8adb3b8c5c6b9b3a29a877963594838271500000000000000000000000000000000000000000010253a4f657a8fabbcc0ab96806b56412b160000000000000000000000000000000000000000000000000000000000000000000000000000000000000012283d52677d92a7bcc4af99846f5a442f1a05000000000000000000000000000013293e53687e93a8c2b9a8917c67523b2b1805000000000000000a1e324657677d85827b6f6259483a291704000000000000000000000004182a3b4d62778a9fb4c7b4a28f7a758398a0b1bdbfb3a29a8476625947341f0e00000000000000000000000000000000000000000000000000000111212f3d4a59616d7a838a92969a9b9c9a97938b847a6d6056473a291a0a000000000000000000000316283851677c91a6bca9947f6a543f2a1500000000000000000000000000000000000000000000000000000000000000000000000006192c3c5a6f859aafc4b5a49c9fa9babfb3a199837460564538281a0a00000000000000000000000000000000000000000000000000000000000b2035485a70859bb0c9c9b09b85705a4935200b000000000000000000000000000000000000000013283d53687d92a8bdbbaa8e79634e586e8398aec4b49f8a76614c37211f33475873889eb3c5af9a85705a3b2a1804000000000000071d32475c72879cb1c4cfcac6c1bdbab9b8babdc2c6c4b8b3a89e948477635b493b2b1a0a00000000000000000000000000000000000000000014293e53697e93a8c9c7a7927d67523d28120000000000000000000000000000000000000000000000000000000000000000000000000000000000000011263b51667b90a6bbc5b09a85705b45301b0600000000000000000000000000000d23384d62788da3b5c6af99846f594834200e0000000000000a1b2d3e4b6175889a97908477625847331f0a00000000000000000000000b1f3447596c8196a9bac1af9a846f607382979fb0bcc0b3a39b8677624c3c2b1906000000000000000000000000000000000000000000000000000003111f2d3a474c5c646e777d8185868785827e776f655d4b4538291c0c0000000000000000000000000f253a4f647a8fa4b9aa95806b55402b1600000000000000000000000000000000000000000000000000000000000000000000000000162b41566b8096abc0c2b5b1b4babfb3a199837460564538281a0a00000000000000000000000000000000000000000000000000000000000006192b3c54697e94abbcc9b5a38d78624d38230e00000000000000000000000000000000000000000f253a4f647a8fa4c4c8a7917c675261768a9fb4c4ae98836e5847331f172a3a5a70859aafc5b39e88735947341f0b0000000000000a1f354a5f748a9fb4c9c7bab4b4bbc8babac7bab4b0aca69d95897f736259493c2c1d0d00000000000000000000000000000000000000000001152737576d8297acc2baa98e79634e39240e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f253a4f647a8fa4b9c6b09b86715b46311c0600000000000000000000000000000b2035495a71869bb1c8b49f8b77624d3c2c180800000000081828394a5c6b8095a6aca29a8776614c37210c0000000000000000000004172a3a4c61778a9fb4c7b5a3907b6555607281969eafbbc1b4a49b85715a4935200b000000000000000000000000000000000000000000000000000000010f1c2a343e4b4f5861686c707171706d6861594f4b3f32281a0c0000000000000000000000000010263b50657b90a5baab95806b56402b160000000000000000000000000000000000000000000000000000000000000000000000000012273c52677c91a7c6d2c9c6c9bfb3a199837460564538281a0a00000000000000000000000000000000000000000000000000000000000000000e22374d62778c9fb5cac1a9947f6a543d2c1a06000000000000000000000000000000000000000c21364c61768ba6b7c0aa95806b55697e93a9bab7a6907b66513a2917172c42576c8197acc1b8a78c77614c37220c000000000000091f34495e74899eb3c9baa99f9faaa4a4a5a4a99f9b9690888077696055483b2c1e0e00000000000000000000000000000000000000000000081d31445571869bb0c6b49f8a75604b36200b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e23384e63788da3b8c6b19c87715c47321c07000000000000000000000000000006192b3c546a7f94aabbbbaa96816c5a49362513010000091425364557647a8b9fb4c0b4a5917c67513c2712000000000000000000000a1f3347586b8096a9bac2b09b85705d4b54606c80949db5bcc2b5a38d78624d38230d00000000000000000000000000000000000000000000000000000000000c181f2e373a474c52575b5c5c5b57534c473b372e1e160a000000000000000000000000000c1c2e3f54697e93a9c8a9937e69543e2914000000000000000000000000000000000000000000000000000000000000000000000000071523384d63788da8b9ccded0bfb3a199837460564538281a0a0000000000000000000000000000000000000000000000000000000000000000000b2034485970859ab0c8c6b19b86715b4935210c000000000000000000000000000000000000000a1f33465873889db3c3ae99836e5c71869bb1c7b39d8874604b35200c14293e53697e93a8bec5a5907a65503b2510000000000000081d33485d72889db2c7b49f8b8b8d8e8f8f8e8d8a86817b746a61594b44372b1d0e00000000000000000000000000000000000000000000000b20354b60758a9fb4c6b19b86715544311d08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d22374d62778ca2c8c7b29d87725d48321d070b0c0e0e0c060000000000000000000e22374c62778b9fb4c8b49f8b78635443301c14080d19263143546075869caabbc3b39d8876614b36210c000000000000000000021527374c61768a9eb4c7b6a4917c66513f434b626b7f939fabb2aa9e8976614b36210c00000000000000000000000000000000000000000000000000000000000004101b222a33373d4145464745423e37342a221b10030000000000000000000000000004182a3a4b5d6f849aafbbaa917b66513c2611000000000000000000000000000000000000000000000000000000000000000000000007152532434a6074899eb3c9d0bfb3a199837460564538281a0a0000000000000000000000000000000000000000000000000000000000000000000005182b3b53697e93aabbc9b5a38d78634e38230f000000000000000000000000000000000000000417293a5a6f849aafc4b19c877264798ea3b5c1ab96806b5544311d0810253b50657a90a5c5bea8937e69533e2914000000000000071c31465c71869bb1c3ae98837377797a7a797775716c6560554c473b3127190d0000000000000000000000000000000000000000000000000e24394e63798ea9bac2ad98826d5837271502000000000000000000000000000000000000000000000000000000000000000000000000000000000000020c21364b61768baabbc8b39d88735e4833131c2021232321190e02000000000000000b1f3448596e8398abbcbaa99a8472604a4130261f202b37444b60728399a4b6c8b6a4937e685746321e0a000000000000000000081d3144556b8095a8b9c3b19c8673604a35304451616a7e8d9c9d988c7d675746331e0a0000000000000000000000000000000000000000000000000000000000000000080c181f22282c303132302d29221f180c080000000000000000000000000000000a1f344759657b8fa2b3b49f8b76614c36210c0000000000000000000000000000000000000000000000000000000000000000000007152532434f61697e93a8b9ccc7b3a199837460564538281a0a0000000000000000000000000000000000000000000000000000000000000000000000000d22374c62778b9fb4cac1aa957f6a553d2d1a0700000000000000000000000000000000000000172c41576c8196acc1b49f8a756c8196abc1b5a38e79634e372614010d22374c62778ca7b8c1ac97826c57422d17000000000000051a30455a6f859aafc4af9a8570626465656462605557504b4437342a1d1509000000000000000000000000000000000000060c0e110f0b0912283d52677d92a7c7bea9947e69543f2914000000000000000000000000000000000000000000000000000000000000000000000000040a0c1012131517191e324657758a9fb4c9b39e89745e4927253035373838352c1d150a00000000000005182a3b4e63798c9fb5c6b3a2947f6a5f4b433634363b4855606c8196a1b2c2bcab9c8774604b392916030000000000000000000b20364b6075899eb3c6b7a5927d685443301c34435060697d8687837a675f4d3929170300000000000000000000000000000000000000000000000000000000000000000000040a0c13171b1c1c1b18130c0b0400000000000000000000000000000000000c22374c6177889db2c0af9a85705846331f0a00000000000000000000000000000000000000000000000000000000000000000007152533434f61697f939daec6d6c4af99837460564538281a0a000000000000000000000000000000000000000000000000000000000000000000000000000b1f3447596f849aafc8c6b19c86715b4a36210c0000000000000000000000000000000000000013293e53687e93a8bdbbaa8e7974889eb3c8b09b86715b4a361909000b1f34485973899eb3c5b09a85705b3b2b1905000000000004192e44596e8399aec3b19c87715c4f4f504f4d4b44373b3631271f180c010000000000000000000000000000000000010f1a21232724201d152c41566b8196abc0c4a5907b65503b251000000000000000000000000000000000000000000000000000000000000000000000010c171f212527292b2d2e3028395e73899eb3c8b49f8a7455444647434a4c4d4d493c32281a0a0000000000000d21364a5b6d8298a8b9c0b59f8d7d6a60544c474b4f59627381969fb0bfc1b49f8c7b655544311b0b000000000000000000000c21364b61768ba1b2b3b19d8774604b3625132533424f5f6771726e645c4d41301b0b00000000000000000000000000000000000000000000000000000000000000000000000000000002060707060200000000000000000000000000000000000000000012273d52677c92a6b7b4a3917c66513a2917040000000000000000000000000000000000000000000000000000000000000000071525334350616a7f949daebbcbd0bba5907b66564538281a0a000000000000000000000000000000000000000000000000000000000000000000000000000005182a3b53687d93aabbc9b6a48e79634e3924100000000000000000000000000000000000000010253a50657a8fa5c5c8a7927d7c91a7b8bbaa937e69533d2d1a000005182a3b5b70859ab0c5b39e8974594834200b000000000002182d42576d8297acc2b39e887355443a3a393836312726201d15090400000002040608020000000000000000000005131f2c35383c393631272b3c5a6f859aafc4b7a68c77614c37220c00000000000000000000000000000000000000000000000000000000000000000008141c2933373a3c3e4042444639465d72879cb2c7bbaa8a75605a5b5d54606163635b4b45382815020000000000071a2d3d4c6277899eb3bebcab9f8d7f7367615960656c7784969fb0bdc2b4a395806b5d4b3727150000000000000000000000091e3246576e83959c9e9c937e685544311808152432414d525c5d584f4a3e302313000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d23384d62788c9faca69b8572604a35200c0000000000000000000000000000000000000000000000000000000000000000081626334350616a7f949daebbcbe0d4bfaa947f6a5538281a0a000000000000000000000000000000000000000000000000000000000000000000000000000000000d21374c61778b9fb4cac2aa95806b553e2d1b070000000000000000000000000000000000000c22374c61778ca7b8c0ab95808399aec5b49f8b77614c37220f000000172d42576c8297acc1b9a78c77624d37220d000000000001162b41566b8096abc0b49f8a75604b35252422201d15100b080b0d0f11131517191b1e180b0801000000000000001323313d494e514f4b45383e485a73889eb3c8b39d88735847331f0a0000000000000000000000000000000000000000000000000000000000000000081826303a474c4f51535557595b5d576171869bb0c6b6a18b766d6f707273757678786f605645321d090000000000000f20344859687e93a0b2c0bcab9f94857d7775757a818a9aa2b1bdc4b6a49b8574604b3f2e19090000000000000000000000031628394b6074808789867e72604b3727150006142330393d4748433a362d201305000000000000000000000000000000000000000000020608090806030000000000000000000000000000000000000000000000000000000000000000000000000000000c2035495a6a7f8f96968878625443301c0700000000000000000000000000000000000000000000000000000000000000081626334450616a7f949daebbccc9ccd6c3ae99836e593b2b180500000000000000000000000000000000000000000000000003090b0f0e0c060000000000000000000a1f3347586f8499afc7c7b29c87725c4a36220d0000000000000000000000000000000000000a1f34475973889eb3c5b09b858c9fb4c5ae99836e5847331f0a00000014293e54697e93a9bec5a5907b66503b2611000000000000152a3f556a7f94aabfbcab8c77614c37220f111315171a141d20222426282a2d2f31332d201d150900000000000a1a31414e5b636664605657534f62778da7b8c4af99846f5a3a2a1814100c0a0400000000000000000000000000000000000000000000000000000001142636434b58616567686a6c6e7072747678859bb0c5c2ac978283848687898a8c8d8d8374604b36200b00000000000005182b3b4e606d8298a2b4c0bcb5a39b928c8a8b8f969fa9b4c0c1b5a69c8676615544312110000000000000000000000000000b1d314556606a72747169605443301909000005131e252831322e24221b100200000000000000000000000000000000000003090b12171b1d1e1e1c18130c0b04000000000000000000000000000000000000000000000000000000000000000000000006192c3c50616a7a818178625a4836251300000000000000000000000000000000000000000000000000000000000000081626344451626b80959dafbbc5b9b3b9c5c8b29d8873594834200b00000000000000000000000000000000000000000000000a161e212423201916120e0b080100000004172a3a52687d92a9bacab6a48e79644f39241000000000000000000000000000000000000004182a3a5b70859ab0c5b5a39b9faabbb8a6917c66513a2a180400000010263b50657b90a5c5bea9947e69543f291400000000000013293e53687e93a8bdc9a38e78634e39232426292b2d2f26313537393b3e4042444648423531271909000000021528384e5f68797c7975716d6864667b91a6c5c0ab95806b564032282a25211f170c0000000000000000000000000000000000000000000000000000081c304354606d767a7c7e8082838587898b8d9ba3b4c8c5b19f9798999b9c9e9faba2a195806b56402b16010000000000000d1d31424b6074849aa2b2bec1b5b1a7aa9faaa4abb4bac7beb2a39b8778625847372715030000000000000000000000000002152738454b555d5e5c544b4336261400000000010a10121c1d190f0d07000000000000000000000000000000000000070a161e21272d30333333312d28221f180c06000000000000000000000000000000000000000000000000000000000000000000000e1e3343505d656c6c625a483c2b1808000000000000000000000000000000000000000000000000000000000000001626344451626b80959eafbbc1b4a79ea7b9cbb7a68c77624c37220d00000000000000000000000000000000000000000003111a2832363938352c2c2723201c14130e0b080c21364c61768a9fb4c9c3ab96806b563e2e1b07000000000000000000000000000000000000172d42576c8297acc1c1b5b0b4bbc8b39e8874604b36200c000000000d22374d62778ca7b9c2ad97826d5836251300000000000012273d52677c92a7bcbaa58f7a65503a373a3c3e40424437444b4c4f51535557595b5d574b44372715010000091d324556687d8c918e8a86827e7a757f95aabfbca7927c67524b45383f3b3633291c14060000000000000000000000000000000000000000000000000b20354b6072818b8f91939597999b9d9ea8a2b0b4c1d1cebdb1acadafb0b2b3b4bcbfb29d87725d48321d0800000000000000131e32455661758498a0b3b8c5c6c8bbb4bbc8c1c9c3b6b2a0988577625a483a2a19090000000000000000000000000000000a1a273136404749473e3530261808000000000000000007080300000000000000000000000000000000000000040f1a212832363c424648494846423d37342a211a0f010000000000000000000000000000000000000000000000000000000000000000001525333f4b4f57574d483c2b1e0e00000000000000000000000000000000000000000000000000000000000008131c344451626b80959eafbcc1b4a39b899eb3c6c4a6917b66513c261100000000000000000000000000000000000000000011212f38454b4f4d493c413d383530262824201d141f3346586e8499aec7c7b29d87725c4b37220800000000000000000000000000000000000014293e54697e93a9bed2c9c5cacec2ab96816c5544311d08000000000b2034485974899eb3c5b09b86705443301c07000000000011263b50667b90a5bbbca6917c67514b4d4f51535557595b5560626466686a6c6e70736d605544311d0b00000b20364b6075899eabaa9f9b97938f8a8a9eb4c9b8a38e79686460565854504c463a32241400000000000000000000000000000000000000000000000011263b50667b909faba6a8aaacaeb0b2b4b9c6c5c8cecac8c6c5c2c2c0bebdbbb9c7bab39d88735e48331e0900000000000000031628384657617482919ea7b2b6c3c0c2c2c0c0b4b0a59d9082756259483c2b1c0c00000000000000000000000000000000000a151d202b32343129201c14080000000000000000000000000000000000000000000000000000000000000c171f2d3639454b52575b5d5e5d5b58534c473b362c1d140900000000000000000000000000000000000000000000000000000000000000000715212e373a414138352b1e0e000000000000000000000000000000000000000000000000000000000000081825304451626b80959eafbcc1b4a39b857a8fa8babfaa95806a55402b1500000000000000000000000000000000000000000b1b2f3f4c566064635a5a56524e4b43363d3935312628293a52677c92a9bacab7a58f7a644f36251300000000000000000000000000000000000010263b50657b90a5c5d6dddbdfc9b5a48e79644e372715020000000005182b3b5b70859bb0c5b49e8974604a35200b00000000000f243a4f64798fa4b9bda8937e685560626466686a6c6f71737577797b7d7f828486888273604b39281603000f253a4f647a8fa8b9bbb4b1aca8aa9f9ea8b9cdc1ac97817d7975716d696561584f42321d0d0000000000000000000000000000000000000000000000152a40556a7f95aabcc9bdbfc1c3c1c0bebdbbb9c8bbb4b3b1b0aeacaba9a7a6a4a3a99f97826d58422d180300000000000000000a1a29394656606d7d88949ca5a8abacacaba7a29a92877b6e6157483b2b1e0e0000000000000000000000000000000000000002090b151d1f1c140b08010000000000000000000000000000000000000000000000000000000000010f1c29333d4a4e5760676c70727373716d6861594e493d3126190d000000000000000000000000000000000000000000000000000000000000000003111c23252c2c2320190e00000000000000000000000000000000000000000000000000000000000008182536434a636c80969eb0bcc1b4a39b857573899fb4c4af99846f5a3c2b1905000000000000000000000000000000000000031729394c5d6575797874706b6763605457524e4b44373e39364b61768a9fb4c9c3ab96816c5443301c0700000000000000000000000000000000000d22374d62778ca7b9cce0ead8c8b19c86715c4a361909000000000000182d42576d8297acc2b9a88d78624d38230d00000000000e23384e63788da3c6bfaa957f71737577797b7e80828486888a8c8e90939597999b9d95806b5746321e09000f243a4f64798fa6b4bbc8c0c2c8bbb4b4b9c6d6c4b19f97928e8a86827f7b7669604f3b2b18050000000000000000000000000000000000000000000014293e53697e93a9bab4b3b1afaeacaba9a7a6a4a2aa9f9e9c9a9997959492918f8d8c8a8275614c36210c000000000000000000000b1b2938454b5f67757f878e9296979795928d857c74665e4b46392b1d0e000000000000000000000000000000000000000000000000080907000000000000000000000000000000000000000000000000000000000000000003111f2d3a474c5b636d757c828588888886827d776e635b4b44372a1d0d000000000000000000000000000000000000000000000000000000000000000000080e1017170d0b06000000000000000000000000000000000000000000000000000000000000081825364354606c81969eb0bcc1b4a39b85756170859bb0c5b39e88735a4835200b0000000000000000000000000000000000000a1e334657657b898e8d8985817c7874706c6863605557534f4b46576e8398aec6c8b29d8873604a35200b00000000000000000000000000000000000b2034485974899eb3c9dee2cebbaa947e69543e2d1a0000000000000014293f54697e94a9c8c6a6917b66513c261100000000000c21374c61768ca8b9c7b29d8786888a8c8f91939597999b9d9faaa4a6a8aaacaeb0b29e8976614b36210c000b20364b6074889b9faaa7abafb3b8c4bec2c6cacebdb1aca8aa9f9c9894908c7e69594834200b000000000000000000000000000000000000000000000d22384d62788b9faa9f9d9c9a9997959492908f8d8c8a8887858382807f7d7b7a7876746d615746331e0a00000000000000000000000b1a2832414d57616972797d808282807d78706760564c4032281b0d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111212f3d4a58616c79828991979b9d9e9d9b97928b83796b6055483b2a1c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081826364354607281969fb0bcc1b4a39b857561576c8196acc1b8a78d78624d38220d0000000000000000000000000000000000000c21364c6176889ea7a79e9a96928d8985817d7975706c6864605657677c91a8b9cbb7a68f7a654f372614010000000000000000000000000000000005182b3b5b70859bb0c5dadfcab49f8b77614c37220f0000000000000011263b50667b90aabbbca9947e69543f291400000000000a1f33475874899eb4c9b7a59d9b9e9faba4a6a8aaacaeb0b3b4bbc8bbbdbfc1c3c5b9a88e79644f39240f00081d314455657b858a8e92969a9ea6a5a9adb1b4bbc8c0c1c8bbb4b1ada9ab9f8b77624c37220d000000000000000000000000000000000000000000000b2035485a687e8a8b8a8887858382807e7d7b7a7876757371706e6d6b69686664636160544c46392917030000000000000000000000000a151d3039464b545b63686b6d6d6b67625a524b45382f1e160b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1f2f3f4b5b6376818b989ea8acb0b2b3b2b0adaa9f988c80736259483a2a1a0a00000000000000000000000000000000000000000000000003050504010000000000000000000000000000000000000000000000000000000000000000000000000000091826364354607281979fb0bdc1b4a39b8575615752687d92a7c7c5a6917c67513c271200000000000000000000000000000000000012273c51677c91a6b8b9b3afaba7a89e9a96928e8986817d7975716d6876899eb4c9c4ac97816c5544311d080000000000000000000000000000000000182d42576d8297acc2d7d5c5ae99846e5947341f0b000000000000000d22374c62778b9fa9ab9f907b65503b2610000000000004172a3a5b70859bb0c9c3b7b2b1b3b4bcc9bbbdbfc1c4c5c3c2c0bebcbac9bcb5b3b1a58e79634e39240e00021527374b5d657075797d8184888c9094989c9faaa7abafb3b8c5bfc2c9baa9917c66513c27110000000000000000000000000000000000000000000005192b3c4e60687676757371706e6c6b69686664636160545c5b5957565452514f4e4c4b433633291b0b000000000000000000000000000002131b2932363d4a4e5356575756524d483c3631271a12030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1b2d3d4b5d657987969faab4b9c6c1bdbdbec2c8bbb4aa9f9584776258473827150200000000000000000000000000000000000000070b0f14181a1a1917120c0b04000000000000000000000000000000000000000000000000000000000000000000091926364354607281979fb1bdc1b4a39b85756157464e63798ea9bac0ab95806b5636251300000000000000000000000000000000000013293e53687e93a8bfc4c8c5c0c6b9b4b0aca7a99f9b97938e8a86827e7a8399aec3c8b39e8874604b35200b0000000000000000000000000000000000142a3f54697f94a9bed4ccb8a7917c67513b2a1804000000000000000b1f3448596b808f94938c7f6a5e4c38230e000000000000162b40556b8095abbcc6c6c4c2c0bebdbbb9c6b9b4b2b0aeacaaa9a7a5a3ab9f9e9c988774604b35200b000009192e3f4b4f556063676b6f73777b7f83868a8e92969a9ea7a5a9adb1b4a6907b65503b261000000000000000000000000000000000000000000000000e1e31424e576061585e5c5a5957565452514f4d4c4a4336454442403f3d3c3a38373530261e170b00000000000000000000000000000000000b161e212d36393d414242403d38342b201d150a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000031729394a5c657b8a9da6b4bbc3b6b2aca8a7a8adb3b8c5bbb4a29a8776615645311d0f000000000000000000000000000000000308131c20242a2d2f302e2c28221f180c08010000000000000000000000000000000000000000000000000000000000091927374454607281979fb1bdc1b4a39b8575615746394b60758a9fb4c4af9a856f5443301c07000000000000000000000000000000000010253a4f657a8fa1aaaeb2b7c4bec3c7c5c1c7bab4b0aca8a99f9b97938f99a1b3c6cbb8a6907a65503b2510000000000000000000000000000000000011263b51667b90a6c6d7c8b39e8975604b36200c000000000000000005182a3b50626b7a7f7e786a6150402f1c090000000000000e23384e63788c9fafb1b0afadaba9a7a6a4a2a89e9c9b9997959392908e8c8a89878278625544311d0800000010212e3737444b4e52565a596266696d7175797d8184888c9094989c9e9b8875604b36210b00000000000000000000000000000000000000000000000014243139454b4c463a47454442403f3d3b3a3837353025302e2d2b2a2826252321201c14080300000000000000000000000000000000000000030a0f1a2123282b2d2d2b282220190d090200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1e334657647a8b9ea8b7c2b5b1a59c96939293989ea7b4bac0b4a59a8474604b3d2d1a0700000000000000000000000000000b171e253035393f42444544413d37342a201c1408000000000000000000000000000000000000000000000000000000011527374455607282979fb1bdc1b4a39b84756157463931445570869bb0c5b39e8974604a35200b00000000000000000000000000000000000b20354a6072839095999da6a5a9adb1b4bcc9c1c5c5c1c7bab4b1aca8a4aeb3bfcfd5c4ab96806b56412b1601000000000000000000000000000000000d23384d62788da8b9cdc0ac96816c5645311d090000000000000000000d1d3344505d656969635b5043332111000000000000000c2135495b6c81939a9c9b9998969492908e8d8b8987858482807e7c7a79777573716d625a493727150100000003101b22273136393d413b484c505458566064686b6f73777b7f8387898579635645321e0900000000000000000000000000000000000000000000000006141b28323636332932302e2d2b292826252321201c131b1918161413110f0e0c0b0801000000000000000000000000000000000000000000000000070c0e1316181816120d0b0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071b2d3e4b6175869ca9b9bdb1a49c9087817e7d7e8288949fa9b8c3b4a296816c5b4a36210c00000000000000000000000002131b293336434a4f54585a5a5956524c473b35302618100200000000000000000000000000000000000000000000000000081d31445560738298a0b1bec1b4a39b847561574639292737576c8197acc1b9a78d78634e38230e0000000000000000000000000000000000071c30435460737b8084888c9094989c9faba8acb0b4bac7c0c4c6c2bdb9c3c6cfdddac5b09b85705b46301b06000000000000000000000000000000000b20354a6074899eb4bfb3a28e7a644f38271502000000000000000000001626333f4b4f54544d493c3325150300000000000000061a2c3d4b60727e8486868482807f7d7b7977767472706e6d6b696765636260555c584d493c2b19090000000000000809151d2024282c2a34373b3f38454b4e52565a5962666a6d717470635b4a3828160300000000000000000000000000000000000000000000000000000a161e21211f171c1b1917161413110f0e0c0b070000040201000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d22364a5c6d8297a4b6bdb19f97867b726c6868696d757f8b9ea7b8c0b49f8c79634e3a2a1804000000000000000000000a151d3139464b546064696d6f6f6e6c676159514b43362d2014060000000000000000000000000000000000000000000000000b20354b60738298a0b2bec1b4a39b847561574639291b283d53687d92a8c7c5a7927d67523d2712000000000000000000000000000000000000132536435460666b6f73777b7f83878b8f93979b9fa9a7abafb3b8c5bfc3c7cad3d3c7b19c87725c47321d0700000000000000000000000000000000071c3043546f8499a6a7a19a84705c4a361a0a00000000000000000000000816212e373a3f3e38352c1e15070000000000000000000e1c30435460686f71716f6d6b696866646260565d5b5957555452504e4c4b44374338352b1e0e00000000000000000002080b0e1216181f22262a273136393d413b484d5054585c5f5b4e4a3d2d1a0a0000000000000000000000000000000000000000000000000000000003090b0c0a04000504020100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060a080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000417293a4f647a8c9fb5c2b19f978173655d575352535760697a899eaabbbbaa98836e5847331f0a0000000000000000000c1a2832414e57616a73797f82848583817d77706660544a3e32241608000000000000000000000000000000000000000000000014293e54697e93a0b2bec1b4a39b847561574639291b0f24394f64798ea9bac1ab96816c5637261401000000000000000000000000000000000008182636434b505559596165696e72767a7e8286898e92969a9ea7a6aaaeb2b6c3bec1b09a85705b45301b0600000000000000000000000000000000001325364e63798891928e8477624c3e2d1b0000000000000000000000000003101b22252a292321190e000000000000000000000001142636434b535a5c5b5a58565452514f4d4b4538464442403e3d3b39373531262e2320190e00000000000000000000000000000000050b0d1114151d2024282c2b34373b3f4347494639362d1f0f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090f111b1f1d14120c0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1f3346586e8398abbcb6a497816d60554b3f3e3d39454b5c657b8c9fb4c8b49f8b77614c37220c00000000000000000c1c2a38454b5f68767f878e9497999a9996928b857c73645c4f423426160700000000000000000000000000000000000000000000152a3f556a7f94abbcc1b4a39b847561574639291b0b0b20364b60758a9fb4c5b09a85705544311d0800000000000000000000000000000000000008182630353b403b474c505458576064686c7075787c8084888c9095999da5a5a9aba3947f6a553f2a150000000000000000000000000000000000000821364a5b63767c7d796f625947342010000000000000000000000000000000080e1014140e0c060000000000000000000000000008182630353e4547464443413f3d3b3938363228302f2d2b2927252422201d14180d0b060000000000000000000000000000000000000000000002090b0f1316182022262a2e32343024211a0f0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090b1013151514110d0b0500000000000000000000000000000000000000000000000000000000000000000000000000000000000004121d242630353329261f1406000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c21364c61768a9fb4c4b19c8675604b44372f292828323e4b5d6c8196aabbbbaa927d68533d2813000000000000000a1a2a3a4756606d7d88949da5a9adafafaeabab9f9a91857a69605144342515030000000000000000000000000000000000000000000e23394e63798c9fb1b3a39b847561574639291b0b00091d31455671869bb0c6b49f8975604b35200b0000000000000000000000000000000000000008141c20262b2a34373b3f39454b4f5357556063676b6f73777b7f83878b8f9396928575614b36210c000000000000000000000000000000000000071a2d3d4a57616767635b4c473b2a18020000000000000000000000000000000000000000000000000000000000000000000000000008141c20283031312f2d2b2a28262422211e161b1918161412100e0d0b08010000000000000000000000000000000000000000000000000000000000000000050b0d1115181c1f1b0e0c07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070b151d2025282a2a29262220190d0a04000000000000000000000000000000000000000000050b0d100c0b04000000000000000000000614222f383c464a483e3b3224140100000000000000000000000000000000000000000000000000000000000000000000000000000000000012273c52677c91a9bab7a6917c6756453226191313161e2e3f4c62778b9fb4c8ad98836d58432e18030000000000021527384758617482929ea7b2b6c3c2c2c2c3c9bcb4afa39b8c7e6b6251433221110000000000000000000000000000000000000000000c21364a5b6b80929c9e97847561574639291b0b000002152738576d8297acc2baa88e79634e39240e000000000000000000000000000000000000000001080b1116181f22262a2832363a3e37444b4e52565a5962666a6e72767a7e807d74615746321e0a000000000000000000000000000000000000000f1f2d39464b51524e493d342a1d0d00000000000000000000000000000000000000000000000000000000000000000000000000000001080b131a1c1c1a18161413110f0d0b090200040200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008131c202832363a3d3f3f3e3b38342b211f170c010000000000000000000000000000000000000e19202225221f180c000000000000000002142432404c515b5f5d534f42321f0f000000000000000000000000000000000000000000000000000000000000000000000000000000000002172c41576c8196acc7b39d8874604b38281609000003111f3448596f849aafc4b19c86715c47311c0700000000000b1d31455661768498a0b3b8c5bcb4b0adacafb3b9c5c1b5aa9f93806b614f3f2e1a0a0000000000000000000000000000000000000000071a2d3d51626b7d8689827561574639291b0b0000000013293e53687e93a8c8c6a7927d68523d281300000000000000000000000000000000000000000000000000040b0c1014161e212529263135393d413b484d515559586165696b676056463929160300000000000000000000000000000000000000010f1b2933363c3d39352c1f180d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005070605030100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002060708060400000000000000000000000000000000000000000000000000000000000000000000000000000003111825303538454b4f53555453514d483c37332a1d150900000000000000000000000000000008161e2b35383a37342a1c13080000000000000c1f32424f5e6670747269604f3d2c1a0600000000000000000000000000000000000000000000000000000000000000000000000000000000051a2f455a6f849aafc2ad98826d5443301a0a0000000005182a3b556a8095aabfb39e89745e49341f09000000000b1b31414b6074849aa3b2beb9b4ab9f9b98979a9ea7b0b4c1bbb49e947f6a5d4b3828150200000000000000000000000000000000000000000f1f334451606871736d61574639291b0b00000000000f243a4f64798faabbc1ac97816c5738271502000000000000000000000000000000000000000000000000000000000003090b0f13141d2023272b2b34373b403a464c505456524b4538291b0b000000000000000000000000000000000000000000000b171e21272823211a0f05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080b11171b1d1d1c1916110c0a030000000000000000000000000000000000000000000000000000000000000000000b161e2e36434a50566065686a6a6966625a554c473a3127190d00000000000000000000000000041626343c484d504c473b30251808000000000012273b4f60697c858a877e695b4935210c00000000000000000000000000000000000000000000000000000000000000000000000000000000071c31475c71869cb1bfaa947f6a5536261400000000000013283d52687d92a7bdb49f8a755f4a35200a000000031629394e5f6d8298a2b4c1b5a89e958b8683828489919ba3afbbbcb49f8d7b655645321d08000000000000000000000000000000000000000001162633424e535c5e574b4639291b0b0000000000000b21364b60758a9fb4c5b09b86705645311d090000000000000000000000000000000000000000000000000000000000000000000001080b0e1216192022262a2933363a3e413d3631271a0b000000000000000000000000000000000000000000000000030a0c12120e0c0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008141c20262c303232312f2b26211e160b080000000000000000040300000000000000000000000000000000000000000d1b28323f4b5460666e757a7d7f7f7e7b77716a61584b44372b1d0f01000000000000000000000012223445515a626561594a43362513000000000014293e54697e919b9f9d8e79634e39230e00000000000000000000000000000000000000000000000000000000000000000000000000000000081d32475d72879cb2bea8937e69533e291400000000000013283e53687d93a8bdb49f8a745f4a351f0a0000000a1e324657687d92a0b2c0b4a39b8a7f77706d6d6f757c85949dafbcbcab9d8774604b362614010000000000000000000000000000000000000000081623313a3d4749423633291b0b00000000000000091e32455671869cb1c6b49f8a75604b36200b00000000000000000000000000000000000000000000000000000000000000000000000000000000050b0d1115171f2125292b28201d150a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000070b0b0c0c0b08010000000000000000000000000000000000000000000000000000000000000210182630353b424547474644403c363229231c11060000010a101219180f0d07000000000000000000000000000000000e1d2b39464b5d65727b838a8f92949493908d867f766a6055483b2d1f0f010000000000000000000a1d304051636c787a776b605443301c07000000061c31465b71869bb0b4a8927d68533d281300000000000000000000000000000000000000000000000000000000000000000000000000000000071c31475c71869cb1c0aa95806b553a29170400000000061a2c3d556b8095aac0b29d88735d48331e080000001325364b6175889eb3beb4a39b85776a62595857556066727f949eafc2b7a5937e695443301c0800000000000000000000000000000000000000000005131e252831342d211e170b000000000000000002162838586d8297adc6baa98e79644f39240f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c101416120b090200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b0d1114181a131c20212121201d1519150f0d070000000000000000000000000000000000000000000000000513202e36434b50575b5c5d5b5955514b4639372e20190e05131d25272f2e24221b1002000000000000000000000000000e1f2c3c4857616c7b8590999fa9a8aaa9a8a6a49c948a7f7362594a3d2d1f0f0000000000000000000f24394d5e6c818c8f8a8072604a35200b000000051a2f445a6f8499afc0aa95806b55402b1600000000000000000000000000000000000000000000000000000000000000000000000000000000051a30455a6f859aafc4ae99846f5847331f0f01000004122135495b70859bb0c5af9a85705a45301b050000071c304354697f94a6b8b8a79b857462594c483b37444b54606b8095a4b5c3b29d8773604b35200b00000000000000000000000000000000000000000000010b11131c1e180c0a030000000000000000000014293e53697e93a8b4b3a5917c67523c2712000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080b0f1112120f0c0a040000000000000000000000000000000000000000000000040a0c1116192022262a2d302530353636363531272e2a24221b100a030000000000000000000000000000000000000000031323303f4b5460666c707272716e6b666157504b3f352b1e162330393c444339362d20100100000000000000000000000e1e2c3d495a6275818f9ba3aeb4bac7bfbfbec2b5b1a89e948577635b4a3d2c1c0c000000000000000011273c51667c919faa9f947f6a5539281603000002172c41576c8196acc1ad98826d58432d180000000000000000000000000000000000000000000000000000000000000000000000000000000002172c42576c8197acc8b49f8a76614c3d2d1d141010171f30414e63798c9fb4c4ab96806b56412b160100000b20354a6073879db2c5b39e89776156483b342a273136434b6073869cb1c3b7a5907b65503b26100000000000000000000000000000000000000000000000000000070902000000000000000000000000000d22374c6277899a9f9e978776614c37210c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c1317150e0c0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080b151d202427272724211f17100b07000000000000000000000000000000000000000b171f21272b2b35383c3f424536434a4b4c4b4b4437433f39362d211e170b00000000000000000000000000000000000000112130414d5d64737b818587878684807b766e655d4d493c2f2634414d5259584e4a3e2d1f0f000000000000000000000b1b2c3c495b637885979fb0b5c1c8c0bab7b7b9bdc5c6b9b4a39b8879635b493a2a170400000000000000172c42576c8197acbbb29d88735745321e0900000014293e54697e93a9beaf9a85705a362513000000000000000000000000000000000000000000000000000000000000000000000000000000000012273d52677d92aabbbaa995806b5c4a3c312625252933404d5f6e8398abbcb8a6907b65503b26100000000f24394f64798ea5b6baa9937e695947382b1f18151d25314455667c91a4b6c3ab95806b56402b160000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1f344859657b8589888277625847331f0a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c171f21282c2a23211a0e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009151d20273136393c3c3c3a37332925201c130801000000000000000000000000000006141b2933363c413c484d5154575a5c546060616160555c58544e4a3e3633291b12040000000000000000000000000000000008182e3f4d5f677a8690979a9c9c9b9995918a837b6f625a4c403444515f676e6d645c4a3d2c1a06000000000000000003162939495a6379889ba3b1bdc5b8b3aba5a2a2a4a8b0b4c0c1b5a69d8879635847331f1300000000000000182e43586d8398adc2b7a68b76604b36210b00000011263b51667b90a6bbb29d87725443301c07000000000000000000000000000000000000000000000000000000000000000000000000000000000c22374c61778b9fb4c7b49f8a7a645a4b44373a3a3a464c5e677d92a0b2c5b39d8874604b35200b000000142a3f54697f94a9c3b49f8a75604b3b2a1a0d0501081527374a6073879cb2b4a695806a55402b1500000000000000000000000000000000000000000000000000000000000000000000000000000000000005182a3b4b5d657074736d6259473a2a17040000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1c2933373e414038352c1f120400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003121927313537444b4e5152514f4c473a3b3530251d1409000000000000000000000000021424323a464c51565a5a6266696d6f7274757676767573716e6a645c544b4639302216080000000000000000000000000000001325364b5d677d8b9ca4acb0b1b2b0aeaaa99f988f8478665e4c4451626b7c84827a645b4936210c00000000000000000c1e3246576278889da6b5c2bab4a79e96908d8c8e939aa2b2b7c3b7a69d8776614c41311b0b000000000000162b40556b8095aac0c4a38d78634e38230e0000000f24394e64798ea3c7b49f8a75604a35200b000000000000000000000000000000000000000000000000000000000000000000000000000000000a1f3347586e8399aebebaa99d8778686055514f505258616c7c8b9fb4beb8a795806a5544311d08000003182e43586d8398adc2af99846f5745321d0c00000000091c304354687e939e9e998878624d38220d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1d2e3f4b4f5b5f5e574c473b2a1c0c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1d2b3a474c5356554e493d30221200000000000000000000010402000000000000000000000000000000000000000000000000000000000000000000000000000000000b171e3037444b5255606466676764615856504a43363126190f0100000000000000000000102132424f5861666b6f73787b7f828587898a8b8b8b8a8986837f79726961574d403326160800000000000000000000000000071c304354657b8c9faab5c1b5b0abaaacb2b6b4aea29a897c665d4a626c809199988b79634e39230e000000000000000c1c30414b6175869ca6b7c4b7a99f9588817b7877797e85909da5b4c1b6a599836f5f4e3a291704000000000013283d53687d92a8bdbba5907b66503b26110000000c21374c61768ca9babaa98c77624c37220d0000000000000000000000000000000000000000000000000000000000000000000000000000000004182a3a4f647a8fa0b2c3b7a59d8a7d746b666565686d76818d9fa9babdb39e8976614c372715010000061b30455b70859ab0c0ab96806b563928160000000000001325364b60728088898379635a4834200b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010212e373a454a494237342a1d0d00000000000000000000000000000000000000000000000000000000000000000000000000000000000005182b3b485861686c6a635b4d40301d0a000000000000060c0e161917110f090000000000000000000000000000000001000000000000000000000000000000000000000c1b2933404d5560676f75797c7c7c7976716c6560544b44372d1f13050000000000000000081b2e3f4f6069767c8084898d9194979a9c9e9faba1a0a79e9c98948e877f76665e5044332616040000000000000000000000000b20354a6073869caabbbab4a39b9694969da5b2b7b3a89e8b7b65606c80969eaea997816c57422c170000000000000417293a4d5f6e8298a4b5c3b6a69d8b80756b6562626468707b879ba3b4c2b3a1927d685846331f0b000000000010253b50657a90a5c8bda8937d68533e28130000000a1f33475874899fb4c7a38e79644e39240f00000000000000000000000000000000000000000000000000000000000000000000000000000000000c22374b5c6e8398a5b7c3b7a89e9286807b7a7a7d8289969fabbac0b19f927d675846331909000000071c31465c71869bb1bea9947f69543f2a14000000000000081c304354606b73746e635b493c2b1905000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002101b22253034332d221f180d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b2034485962767d817f79665e4d39240f00000000000e1920232b2e2d26231c110400000000000000000000070d0f1516120b080100000000000000000000000000000c1c2a39464b5f67747c848a8e9191918f8c87817a736860554a3d30231406000000000000000e22374b5d697e8a91969a9ea7a6a9acafb1b3b5bcb6c5b8b3b1ada9a59d94887c6b62504433221200000000000000000000000011263b50667b90a4b6baa99f9186817f8187919da5b4b9a99e89777381969eb0bbad98836e58432e190000000000000a1f334658677d92a0b2c2b6a59d887a6a6057504d4d4f535d6576859ba4b6bfb39e8976614c39291703000000000d23384d62788daabbc0aa95806b55402b1600000004172a3a5d73889db2bba5907b66503b26110000000000000000000000000000000000000000000000000000000000000000000000000000000000081b2e3e4c6177879da8b8c5b9b4a49c95908f8f92989ea8b4bcbeb2a297816c5f4d3a291700000000061b31465b70869bb0c0ab95806b5638281502000000000003142636434b565e5f594e493d2c1d0d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080e101b1f1e180d0b0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d22374c6277879396958b7c66513c271100000002101e2c35384043423b382f2216080000000000000002101b22242a2c27201d14090000000000000000000000000c1c2a3a4757616d7c8791999fa9a6a7a6a4a49c9690877d73635b4d413224140500000000000010253a4f657a8f9fa9abafb3b8c5bec0bcc8bbb4b3b4b9c6bbc1c3c3b7b2a69d91806b625040301b0b0000000000000000000005192b3c596e8399aec0b49f8b7c716c6a6c737c879aa2b4b8a7978281969fb0baae9d907c66513b2611000000000005192b3c4c6176899eb3beb8a79d8778645c4b45393837393f4c586176869ca9bab8a795806b5746331e0a000000000b20354b60758a9fb4c2ad98826d58432d18000000001c31465c71869bb1bda7927d68523d2813000000000000000000000000000000000000000000000000000000000000000000000000000000000000101f34475963798a9ea7b5c1c2b6b1aaa6a4a5a7adb3b9c6bbb4a0988474604b41301b0b00000000041a2f44596f8499aec3ae99836e5645321d0c000000000a161e212630354149494438352c1f0f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060a0902000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014293e53697e93a6aba99b85705b46301b06000010202e3c494d565957504c403426160100000000000614202d363940413c353126190a000000000000000000000919293a4759617582919ca4aeb4bac7bcbcc2b6b1aba49c928579675f4f42322313020000000000172c42576c8197acbac7c4c7bab4afaba7a3aa9f9e9ea8a2a6acb3b8c5c4b7b29e95806b5e4d392917030000000000000000000b2034485a73899eb3b4a2917c665e565554606676849aa2b4b1a097979fb1bcb59c937f695e4c38240f00000000000b2034485a6b8196a7b8beb39e8978635a4a3e32282322242f3a475863798b9fb4c5b49e8976614c36210e00000000081d31445572879db2c5af9a85705a362614010000061b30455b70859ab0bfa9947f6a543f2a1500000000000000000000000000000000000000000000000000000000000000000000000000000000000004182a3b4a5b657b899ba3b3b9c6c7c0bbbababdc2c7bfb3aa9f958274605645322313000000000001162c41566b8196abc7b49e8975604b3a2a190c04000a1b2832364349443a362e2f23211a0f01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002172c42576c8197acc4b09b86705b46311b060009192e3e4b5a636b6e6c665e5145341f0f00000000021424313e4a4f5556524b4437281a0a000000000000000001152737475861778598a0b2b6c3c9c3bdbab9babec3c3b6b2a39b8b7d69614f4131201000000000001a2f44596f8499aec4c5b9b3a99f9a95918d8b8a89898b8d91969ea7b4b9c6bcaf9e917c665746331e090000000000000000000d22384d62778da7b8af9a85705e4c4036434a586175849ba8b9b1adacb1bcab9f937e69614f402f1d0900000000031729394d62788b9fb4c5b2a0917c675a493c2d1e160d0d111c2a3a495b6a7f94a7b8b9a8937e69533c2c1906000000011527375a6f859aafc4b29d87725443301c080000051a2f455a6f849aafc1ab96816c56412c17010000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1d2d3d4b5d657885949ea8b0b4bcc9bdbcc3b7b2aca1998c80726056453828150500000000000011263b50667b90a9bab9a8937e68584737291f18181a2839454b595e5a4f4a3e3022120600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c1316120b0903000000000000000000000000000000000000000000000000000000000000000000011527375a6f849aafc3ae98836e59432e1904021527374b5c64788083827b6c63513d2c1a060000000b1f31424e5c646a6b676055453828150200000000000000081d3144556176869ba3b2bec7bab4ada8a4a4a4a9aeb4bbc1b5a99f927f69604e3e2d1a0a00000000192e44596e8399aec3b9a79e918a84807c787675737476787b8188949ea8b6c2bcb39e8876614c37271501000000000000000011263b50667b90a5c5a8937d6853403025303a465762778a9eb4c9c2c9bcab9f8d7e69604f4332221200000000000a1e3346576b8196a9bab8a798826d5f4d3c2c1e10030000000c1c2c3d4b6075889eb3c6b19c86715a4935200c00000000182d42576d8297acc2b49f8a75604b35200b0000041a2f44596f8499aec2ad98826d58432d1803000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1f2f3f4b5a62747f89939a9faba7a8a7a5a59d968e84796a60544538281a0a000000000000000b21364b60758a9fb4c6b39d88766155463a332a2d2d384557606e736f645c4d40301c0c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b171f21282b27211e160a0000000000000000000000000000000000000000000000000000000000000000081d31445572879db2c0ab95806b56402b1601081d314455647a8b95989790816c5b4935210c00000011263a4e60687a7f817c73605645321d09000000000000071b2d3e4b6073849aa4b5c2bcb4a99f98938f8f8f93999faab4bcbab49d927e685c4a38281502000000172d42576c8297acc1b39e897d766f6b6763616054576062666c757e8a9ca4b6c5b8a6957f6a5544311d08000000000000000011273c51667c91a6b9a38e79644e3924131c293948596a7f95aabfcfbcab9f8d7e68604f423224140400000000000c21364c6176899eb4c6b39e8976614c40301e0e0000000000000f1e3245576b8196abc1b5a48d78634d38230e00000000152a3f556a7f94aabfbbaa8c77624d37220d0000051a2f455a6f849aafc3ae99846e59442f1904000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111212f3c4856606a767e858b8f919292908d8881796f635b4a4336281a0a0000000000000000091e3245566e8398abbcb7a699837361584c473a423e4a5660758388847a665e4d3a291704000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1b2933363e403d3632281a10020000000000000000000000000000000000000000000000000000000000000b20354b60758a9fb4bda8937d68533e281305182a3b4b6074869ca9aeac9f8d79634e38230e00000114263753687e8d9596918474604b36200b0000000000000d22364a5c6a8095a2b4c2b7ab9f968b837e7a797a7e838b969fabb8bbb49f8b7a645645321d0a000000142a3f54697f94a9beb49f8a75615756524e4c4a43454b4d5156606978869ca7b8c4b39e8874604b35200b000000000000000012273c52677c91a7b7a28c77624d3722121d3144556175869cb1c6cab49f8d7d68604e4232241406000000000004182a3a53687d92a8b9b9a895806a584633221200000000000000031628394e63798da3b5c2a9947f69543626140100000012273d52677c92a7bcc8a48f7a654f3a25100000051b30455a70859aafc4af99846f5a442f1a05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003111e2b38454b57616970767a7c7d7d7b77726c645c4e4a3d3025180a000000000000000000031628384e64798c9fb5c4b3a19983766861585958595c647483989e998c7c665846331f0a000000000000000000000000000000000000000000000000000000000000000000000000070c0e13110b0802000000000000000000000000000e1e2c3a464c5355524b45382d20100000000000000000000000000000000000000000000000000000000000000e23384d63788daabbc8a5907b65503b2610091f344859697f94a4b6c7bda9947f69543929170300081d31445571869cababa2917c66513c27110000000000091d30404f647a8c9fb4c0b7a69d8c81776e68656465696e77808d9ea7b8baa99c8674604b38281502000011263c51667b91a6c8baa98d78624d393c3836353032363838454b5a6377899eb3c5b8a6917b66513c2611000000000000000012273d52677c92a7b6a18c76614c37212232434b60738399a4b5c9c4af9a856f604e42312414060000000000000a1f34475970859ab0c6b49e8976614c3a29170400000000000000000a2135495b70859bb0c4ae99846f5443301c080000000f243a4f64798fa4c6bca7927d67523626140100011527375c71869bb1c4af9a846f5a452f1a05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1a273139464c5457616467686765625a574e4a3e362d1c130800000000000000000000000a21364a5c6e8399a7b8bfb3a199887e77716e6d6f727a8599a1b3aa9e8976614c36210c00000000000000000000000000000000000000000000000000000000000000000000020f1a21242827201d1509000000000000000000000006192c3c495861686b6760564a3e2d1a0a000000000000000000000000000000000000000000000000000000000011263b50667b90a5c8bbaa8d78624d38230d192e3f4c62778a9eb4c2d3c4af9a856f5746331e0a000b20354b60758a9fb4c0a7927d67523d281200000000000f24394d5e70859baabbb7a59d887a6b6259534f4f4f5459626b7b899ea8b9b6a4947e695645321d0900000e23384e63788daabbc7a5907a65503b272321201c1e212328323c4959687d92a7b9c5ac97816c57362513000000000000000011263b50667b90a5b8a38d78634e382330404f616c8197a1b3c2d2c7b19c87725c4131241406000000000000000c22374c61778b9fb4c2ab96816b5847331c0c000000000000000000061a2c3d566b8096abc0b39e8974604b35200b0000000c22374c61778ca8b9c1ac96816c5443301c0b00081d31445572889db2c4ae99846f59442f1a0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a151d29333639464b4f525352504d483c39362d211a0f00000000000000000000000000071a2d3d4d6277899eabbcbfb3a69e938b86848284878e9ba3b3bfb7a68f7a65503a25100000000000000000000000000000000000000000000000000000000000000000000a161e2d36393e3c363127190d000000000000000000000c2035495a62767e807c75645c4a382816020000000000000000000000000000000000000000000000000000000014293e53697e93a8beb49f8a75604b35201426374b5d6d8298a8b9ccdfc9b49f8a76614b36210c000d23384d62788daabbc7a58f7a65503a251000000000081c2e3f51667c91a3b4baa99d8778645c4c473b3a3a3a3b484c5d657a8a9eb4bfb39e8875604b36200b00000b20354b60758a9fb4bda8937d68533e28130c0b07090b0d161e2c3b4b6075899eb3c7b19c87725443301c07000000000000000f24394e64798ea3c5a58f7a65503a2d3e4c5e697f949fb1bfc1c4c9b49e89745443301c07000000000000000012283d52677d92abbcb6a48e79634e3a2917000000000000000000000011263c51667c91a6c6b9a78d78624d38230d0000000b1f34475974899eb4c7b29d8774604b39291a0e0b20354b60758a9fb4c2ad98836d58432e1803000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b171e212932363a3c3d3d3b38342b24211a0f070000000000000000000000000000000f20344859667c8d9fabbbc4b8b3aa9f9c9997999ca4b0b5c1baaa9d8875614b36210c00000000000000000000000000000000000000000000000000000000000000000a1a28323d4a4e53514b44372b1d0d0000000000000000021527384d627887939592877a645645321e0900000000000000000000000000000000000000000000000000000001172c41566c8196abc1b29d87725544311d1d314455657a8fa0b2c6d6e1cebbaa917c66513c27110011263b50667b90a5c8baa98d77624d38220d000000000e23374b5d71869bb1c1b49f8a79635a4b3e342a2524252a343f4b5c677d91a1b3b8a7927d67523828160300081d31445572879cb1c0ab96806b56412b16000000000000020e1e3245566e8399aec3b49f8a75604a35200b000000000000000d22374c62778ca7b8a8937e68533e3c4a5c667c8d9fb4bab4abb0bdb59f8a75604a35200b000000000000000417293a586d8298adc9b19c87725b4a361c0c00000000000000000000000c21374c61778ca8b9c5a6907b66513b261100000004182a3b5c71869cb1c6b6a5917c665746382b1f1824394e63798eaabbc1ab96816c56412c17010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a0c161e2125272828262220190f0d07000000000000000000000000000000000005182b3b4c5e687e8d9faab6c3c8bbb4b1aeadaeb1b6c2c2b6a99f8c7b655746321e0a0000000000000000000000000000000000000000000000000000000000000002162838454b5b6368666055483c2b190500000000000000091d3145566e8399a5aaa69d8775604b37261401000000000000000000000000000000000000000000000000000001142637596f8499aec4af9a846f5a3727172a3a4b6073869bb1becdc9cdd7c8ac97826c573d2d1a0714293e53697e93a8beb49f8a75604b35200b0000000316283950657a8fa3b5b7a6937e695b4a3c2e1f18100f10181f2e3e4d5f6f8499afc3af99846f5645321e090001152737596e8499aec3ae99836e593625130000000000000002162838556a7f95aabfbbaa8c77614c37220c000000000000000b1f34475973889eb3ac97826d573c485a647a8a9fabbaa99f969eb0bcab8b76604b36210b000000000000000a1f33465872879cb1c1ac96816c573d2d1a0000000000000000000000000a1f33475874899eb3bea9947e69543f291400000000192f44596e8499aec3c3b29d87766156483c342a303f53687e93a8c8c8a8937e69533e2914000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a0c0f121312100d0b050000000000000000000000000000000000000000000d1d2f404e60687d8b9ca4b2b6c3c3c6c3c2c4c4c4b7b3a49c8b7d675d4b3929160300000000000000000000000000000000000000000000000000000000000000091e324556606d797d7c74625a48342011000000000000000b20364b60758b9fb4c3b7a5937e685544311d080000000000000000000000000000000000000000000000000000081d31445572879cb1c1ac97826c57422d1f334758687e93a3b5c6bab4bac6c8b29d88735b4a36210c172c41566c8196abc1b29c87725443301c08000000091e3246576e8398adc1b29d8874604b3d2d1e1005000000051120304150657b90a5b7b49f8a75604b36210b0000162b41566b8096abc0b19c86715443301c070000000000000014293e53697e93a8bebbaa8c77624c37220d0000000000000005182a3b5a6f849aafb29d87725a48576278889da8baa99f8b8196abbcab8b75604b36200b000000000000000c21364c61768b9fb5c8a7917c67523c271200000000000000000000000004172a3a5c72879cb1c0ab96806b56412b1601000001172c41566c8196abc1cab7a5998374625a4c473b404c5d6f849aafc4bbaa907b65503b2510000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000112231424e5f677a87939da5aaaeb1b2b2b2afaca69d94867a675f4d3f2e1b0b0000000000000000000000000000000000000000000000000000000000000004182a3a4b6074828e93918678624d3f2e1c080000000000000e23384e63788dabbccfc3b29d8774604b35201200000000000000000000000000000000000000000000000000000b20354b60758a9fb4bfa9947f6a543f2a2d3e4c6176899eb3c1baa89fa8b8c5b7a68e79634e39240e1527375a6f8499afc4af99846f5a362614010000000c21364b61768a9fb4c8aa947f6a5645311f0f000000000000021320354a6074879db2bbaa8f7a65503a2510000013283d53687d92a8bdb49f8974604a35200b0000000000000013253654697e93a9beb49f8a75604b35200b0000000000000000162b41566b8096abb6a58d7862556175869ca6b7aa9f8b7b7b90a5b59f8a755544311d08000000000000000f253a4f647a8fabbcbbaa8d78634e38230e000000000000000000000000001a30455a6f859aafc2ad97826d58422d180300000014293e54697e93a9bed4c3b3a19984786a615959595e667b8fa2b4cab49f8a76614b36210c0000000000000000000001020405060001080b0c0d0e1011121314161718191a1c1b100e08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004142431414d5c64747e878f95999b9d9d9d9a9690887e74645c4d4130211100000000000000000000000000000000000000000000000000000000000000000a1f3447596c8197a0a8a49b85715d4b37230d00000000000011263b51667b90a6c9d9cab6a5927d6752402f1c09000000000000000000000000000000000000000000000000000d23384d62788da9babca6917c67513c25364a5c6c8197a7b8c0b49f899ea7b8c4a9947f69543929171d31445572879cb2c1ac97816c57422c170000000013253652677c92a8babbaa8e79644e3827150100000000000000071c3043546e8398adc8a8937e68533e2913000010253a4f657a8fa4c5baa88c77624d37220d0000000000000a1c3043546c8197acc1b29c87725443301c08000000000000000011263b51667b90a9baa8927d6860738399a4b5b49f8c7c677c91a7b39e88735e372715020000000000000013283d52687d92a7c9b49f8a75604b35200b00000000000000000000000004192e43596e8398aec3ae98836e59432e190400000011263c51667b91a6bbd0d0bfb3a29a8a7f77716e6e727c899eb3c0c3af9a856f5746321e0900000000000001080b111618191a1b1c141c20212224252627282a2b2c2d2f30313025231c110300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061423303e4b566069737a80838688888785817b746960564b3e3023120300000000000000000000000000000000000000000000000000000000000000000c22374c61778b9fb4beb5a3907b65503b2b1805000000000014293e54697e93a9bed3d3c3b19b86715e4c3823100000000000000000000000000000000000000000000000000010263b50657b90a5c7c5a48e79644f39304354647a8c9fb4c5b4a2927d899eb3c5af9a85705746331e20354b60758a9fb4bea9947f69543f2a14000000071c3043546d8398adc6b49f8a75604b36200b000000000000000000132536546a7f94a9bfab96806b56412b1600000c21374c61778ca7b8c6a58f7a65503a251000000000000c1a2a3a4a6073879db2c3ac97826d573626140100000000000000000b21364b60768a9fb4ae99836e6c8197a1b3af9d927d68697f94a9b19c86715c47311c0000000000000000152b40556a8095aabfb29d88725544311d0800000000000000000000000004192f44596e8499aec3ae98836e59432e19040000000e24394e63798ea3c5d5ddd0c0b4a89e958b86838487919ea7b8c9b6a4927d675239281603000000000009151d20272b2d2e2f31322630353638393a3b3d3e3f404143444546463b382f211100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000513202e38454b5460656b6e717373726f6c6560554b45382e20120400000000000000000000000000000000000000000000000000000000000000000011263b50667b90aabbcec1ae98836e59483420090000000002172c41576c8196acc1d6dec9b5a3907b66503e2e1b0800000000000000000000000000000000000000000000000013293e53687e93a8bdb8a78c76614c373a4a6072859babbcbcab9a85708398aec3b49f8a76614c362123384d63788daabbbba6917c66513c27110000000b20354a6074889eb3c8b39e89735544311d0800000000000000000014293e53697e93a8beac97826d57422d1800000a1f33475873889eb3bda8927d68533d281300000008121c2a384758677c91a5b6b7a5917c66513c2711000000000000000000091e3245576f849aafb49f8a757f949fb1b19f947f6a5f6d8298adae99846e59442f190400000000000002172c41576c8196acc1b09b86715b37271501000000000000000000000000051a2f445a6f8499afc3ae99836e59442e19040000000c21364b61768ba6b8cbd7cdc9c6b9b4aa9f9c98999ca4b3b8c5bcab9c8774604b36200b00000000000c192731353c40424345464748434b4c4d4e4f51525354555758595a5b5b504b3f2f1c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002101a273136434a4f55595c5d5d5d5a57504b443732281a100200000000000000000000000000000000000000000000000000000000000000000000152a3f546a7f94a9c8d8cab49f8b77624d37271501000000011426375a6f8499afc4d9dfd2c2af9a85705c4b37220f000000000000000000000000000000000000000000000001162c41566b8196abc0b39e89735847334658687d92a3b4c5b49f8c7a687d92a8c2bbaa917c66513c27263b50667b90a5c8c5a38e79644e39240f0000000e23394e63798ea6b8c9b49f8a75604a35200b00000000000000000013293e53687e93a8bdad97826d58422d18000004172a3a5b70859bb0c0ab95806b56402b16060b111c23303a47566176889db2c2b29d8774604b35200b0000000000000000000316283953687e93a9baa998828d9fb4b3a197816c615b73889db2ab95806b56402b160100000000000003182e43586d8398adc2af9a846f5a452f1a00000000000000000000000000011527375a70859aafc2ad98826d58432d1803000000091e32465773889eb3c8c7bab4b4bbc8bbb4b1aeaeb1b6c2c7bab49f8d7b665544311d08000000000c1c2a37444b515657595a5b5c5d546061626365666768696b6c6d6e6f7170655d4b3a2917040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a151d2530353a40444648484845413b3531271e160a000000000000000000000000000000000000000000000000000000000000000000000002162838586e8398adc3d8cebbaa957f6a5544311d08000000081d31445572879cb2c7cfcacfc8b4a28f7a644f3d2c1a060000000000000000000000000000000000000000000000132536596e8499aec3b09b86715b3a3d4c6176889eb3c1b9a797826d62778ca4b6c8ac97826d573d2d293e54697e93a9beb8a78b76614c36210c00000013283d52687d92a7c4cebaa98e79634e362614010000000000000005182b3b566b8096abc0ac96816c57412c17000000182d42576d8297acc2ae98836e59432e191920232f38404c586174849aa6b7b6a4947e695544311d08000000000000000000000c21364c61768a9fb4b2a0989fabb5a4998373604e63798ea6b7a7917c67523c27120000000000000004192e44596e8399aec3ae99846f59442f1a04000000000000000000000000081d31445571869cb1c1ac96816c57412c1702000000031628395b70869bb0c5baa99f9faab4bac7c3c3c3c3c7bab4a99f937f6a5e4c3727150200000004172a3a475560666b6d6e6f70717374757677797a7b7c7d7f808182848586857b655847331f0a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000208131c20252b2e31333332302c26201d150902000000000000000000000000000000000000000000000000000000000000000000000000091e32455671879cb1c6dcd8c8b29d8874604b35200e0000000b20354b60758a9fb4c9bcb4bcc9c0ae99836e5b4936210e00000000000000000000000000000000000000000000071c30435471869cb1c3ae98836e59434a5b6c8196a6b8c2b39e8977615971869cb1c6b29d88735b4a362c41576c8196acc1b39e88735746331e0a000002172c41576c8196acc1d8c7a8937e695443301c10020000000000010f203448596f8499afc9a9947f69543f2a14000000142a3f54697f94a9beb19b86715c3b2a282b35383f4b505e6676849aa2b4bbaa9c8674604b37271501000000000000000000000a1f3346586e8398aebeb2adb4b8a69c86756155556b8095aab6a58c77624d37220d0000000000000004192e43596e8398aec3ae99846e59442f19040000000000000000000000000b20354b60758a9fb4bfaa957f6a55402a150000000000192e43586e8398adc3b49f8b8a989fa9abaeb0afaeaaa99f988b7e6a6150402f1909000000000a1f33475861737c80828384868788898a8b8d8e8f90929394959698999a9b9b8976614c37210c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070b1016191c1e1e1d1a17100b080100000000000000000000000000000000000000000000000000000000000000000000000000000b21364b60758a9fb4cadfdfcbb7a6917c66513d2c1a0600000d23384d62788daabbbcab9fabb6c3b59f8c79634e3c2b19050000000000000000000000000000000000000000000b20354a6074899fb4c0ab95806b56414e63798c9fb4c4b6a4937e6959566b8196abc7b7a68e79634e3927375a6f8499afc4b09b86715b392917030000021527385a70859aafc5dac7b19c8673604b3d2d20130900000007121f2e3f4d62778b9fb4bcab907b66513b261100000011263c51667b91a6c8b49e89745947393d3c484d545d65707c889aa2b4bcb49f8b7a64554431190900000000000000000000000417293a50657a8fa3b4c5c2bbaa9e887862574b5d72879cb2b29c8772594834200b0000000000000003192e43586e8398adc3af9a856f5a45301a000000000000000000000000000e23394e63788ea9babca7927d67523d28120000000001162b40566b8095abc8b29c8679828a9196999b9a9995918a82786960504333221100000000000c21374c617685919597989a9b9c9d9e9faba2a3a4a6a7a8a9aaacadaeafb0a7937d68533e28130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040708080805020000000000000000000000000000000000000000000000000000000000000000000000000000000000000f24394f64798eaabbcedbd8d4c4af9a846f5b4935210a000010263b50657b90a5c8b49f8b9da5b6bcab98826d5a4835200c0000000000000000000000000000000000000000000d22374d62778ca9babda8937d68534d5f70849aaabbbfb19c8674604b50667b90a9bac4a9947f6a543a31445572879cb2c3ad98836e58432e19000000091d31455673889db2c8ddcab6a4927d685b4a3e31231c1413141b222f3d4b5d6b8096aabbb59f8b76614c37210c0000000e23384e63788daabbb9a88c77614c4e52575a626a717b85919da6b4bcaf9e937e685d4b372715000000000000000000000000000c23374b5d70859bb0c5c9b49f8b7b655a484f647a8fa5b6ab96816c563b2b18050000000000000002182d42576d8297acc2b19b86715c3a2a170400000000000000000000000012273c51677c91a6c7c3a48f7a654f3a2510000000000013283d53687d92aab1ab9c86716d767c8183858583807c766d635a4f42332515030000000000152a40556a7f95a3abacaeafb0b1b2b4b5bcb7b8babbbcbdbec0c1c2c2c0c2ab95806b56402b1601000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013283d53687d92a8c8cfc6c3cacab59f8c78634e382816030013293e53687e93a8bdaf9983879db2c4b49f8b78624d3a2a1804000000000000000000000000000000000000000010253a50657a8fa5c7c8a5907b655057677d91a2b4c7b3a1907b6555444b60758a9fb4c5af9a85705846364b60758a9fb4c0ab95806b56402b160100000b20364b60758a9fb5cadfd3c2b49e8a79645c4e42382f2928292d36404c5b657b8c9fb4c5b09b85705847331f0a0000000b20354b60758a9fb4c6a48f7a646163686d71787f86909ba3b3b7b9b49e95806b604e3f2e190900000000000000000000000009192b3b4a5c697f94a9bebea9947e695d4b46576d8297adb7a6907b65503b2510000000000000000001162b41566b8096abc0b39e89735847331f0a0000000000000000000000061a2c3d566c8196abc1b6a58c76614c37210c00000000000d22384d62788b9a9c998d7d675761676b6e706f6e6b6661574d493c32241507000000000000182d42576d8297acc1c2c3c4c5c6c8c9c0bdbbbab8c7bab4b2b1afaeadabaaa4927d68533d28130000000000000000000000000000000000000000000000000000000000000000000000000002090b1418160d0b050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002172c41576c8196acc1bfb3aeb5bcbcab96816b5645321e0901162c41566b8196abc0ac96817e93a6b7bbaa96816c5847331f0b000000000000000000000000000000000000000013283d53687d92a8bdbbaa8d78624d6175879db2c0baa999836e5e4c3745566f8499afc4b49f8a76614c384e63788daabbbda8937d68533e28130000000d22374d62778cabbccfe3e1cdb9a89d887a6860504c3f3e3e3e3e4a4f5e6679889daabbb9a7937e69533a2a1704000000081d31445572879cb1bca7927d7376797d82868d949ca4b0b4c1b9a89e92806b625142312010000000000000000000000000011426374859647a8a9eb4c9b7a28c77624d3f4c61768a9fb4b29d8874604b35200b00000000000000000014293f54697e94a9beb8a78c76614c37210c00000000000000000000000c2135495b72879cb2c7b29d87725847331f0a00000000000b2035485a667c8487837b675f4d4b5156595b5a5955514b4639352c1e14060000000000000013293e53687e93a5b7c5d6d9dbcdbcb0aba7a6a4a3a1a99f9d9c9a99979694918675614b36210c0000000000000000000000000000000000000000000000000000000000000000000000000a151d20292e2b2220190e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005192b3c5a70859aafc5b3a1999fabbcb39e8975604b36211000132536596e8499aebea9947e74889db3c5b49f8a77614c3928160300000000000000000000000000000000000001162b40566b8095abc0b49f8a75605b6b8095a6b7c4b49f8b78634d402f3854697e94a9c3bbaa917c67513c51667b90a6c8c8a5907a65503b25100000000f24394e64798ea3c9dad7cdc9c6b7a69d8a7d70655d57535353575c646e7c899da6b7c2b39e8976614b36210c0000000001152737596e8499aec3b39d88888b8e92979ca4a9b1b5c2c8c9b49e8a7d6a6251443127190b000000000000000000000000081d3144556277889da8b9cabda8937d6853384f64798fa4b0a796806b5544311d0800000000000000000011263b51667b90a6c5c5a5907b66503b261100000000000000000000011426374e63788ea5b6c2ad98836d583a291704000000000005192b3c4c5e666f726e655d4d41363c4144464544403c36332920190e0000000000000000000b21364b6075879da7b8c5d5d8c4b09e9692918f8e8c8b898886858482817f7c75615746331e0a00000000000000000000000000000000000000000000000000000000000000000000000a1a2832363e434038352b1e1002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b2035485a74899eb3c3ae99838d9fb5b8a7927d68533e2d1b071c30435471869cb1bba6917c6a7f94a7b9baa895806a5746321e0900000000000000000000000000000000000004192e43596e8398aec3b29d87725563788b9fb4c4b7a695806b5a493523394e63798ea5b7c8ac97826d573e54697e93a9bebbaa8d78624d38230d00000010253b50657a90a5bad7c7bab4bac4b7a89e92847b726d6968696c717983909ea7b7c4b5a4947f6a5746331e0a0000000000162b41566b8096abc0b7a69d9ea6a3a7acb1b5c2c6c9d2dbc6b09b857c70645c4b4437291b0b00000000000000000000061a2c3d4b6073849aa6b8bcb5bcaf99846f56454b607586969a988977624d372614010000000000000000000e23384d63788da7b9bfaa957f6a5539291603000000000000000000081d3144556a7f94a9c3c0a7927d68523d2813000000000000000e1e2f404c505a5c59504b3f3121272c2e30302e2b27211e170b0600000000000000000000091e3245566379899ea7b8c5d5c0ab96807d7b7a787776747371706e6d6b6a66615746392917030000000000000000000000000000000000000000000000000000000000000000000009192838454b5358564d483c2e2010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d22384d62788da7b9c7a7927d8399afc4b09b85715c4a36220c20354a6074899fb4c5a38e796476899eb3c6b39e8975614b37271502000000000000000000000000000000000005182a3b5c71869bb1c4af9a846f5e6f8499a9bac1b39d8875614b3c2c2136495b72889db2c7b39d88735c4a576c8196acc1b49f8a75604b35200b00000011273c51667c91a6bbcdbaa99fa9b9c6b9b4a29a9087827e7d7e82868e98a0b3b8c5b9a89c8674604b39291703000000000013283d53687d92a8bdc4b7b3b3b8c5bdc2c4c3c2c2c4c6c9c9b5a39b90857a6b60554639291a0a0000000000000000000c2135495b6a7f94a2b4b4ab9fabb49f8a75604b455662778185837a645948341909000000000000000000000b20354b6074899eb3c4af99846f5746321e0a0000000000000000000b20354b6074879db2c7b4a28c77624c37220d000000000000000011222f383b4547443a372e21131216191b1a1916110c0a03000000000000000000000000031628384a5b647a899ea7b8c5c7b29d87786665636260565d5c5a59585655514b4639291b0b0000000000000000000000000000000000000000000000000000000000000000000001152737455660696d6b625a4b3e2e1b0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011263c51667b91a6c5baa98e797c91a6b7b5a38f7a644f3a291722374d62778ca8bab8a78b76616b8095a9bab8a7947e695544311d0800000000000000000000000000000000000b1f34485974899eb4c1ac97826c667c91a1b3c7b4a3927d675746321e1a2c3d576d8297acc8b7a68e79644e5a6f849aafc4b29d87725544311d0800000012283d52677d92a7bcc9b49f8a9ea8b7c4c0b4afa49c97939393979ca4adb2bec5b9a89e8a79635645311b0b00000000000010253a4f657a8fa4c5d4cbc8c3c6b9b4b1aeadadacaeb1b4b9c1b5b0a39b8c80736157463827150200000000000000091c2f404e63798b9fb4b4a29a8c9fb5a9907b6550384859626c706d645c4a3b2b180000000000000000000000081c3043546f8499afc4b49f8a76614b36210e00000000000000000b1b2f4051677c91a5b6c6b09b8570594834200b000000000000000004111c23262f322e25231c11030001040605040000000000000000000000000000000000000a1a2d3d4a5c647a899ea7b8c5b7a59d887a655d4c4b453847454442413f3c3633291b0b0000000000000000000000000000000000000000000000000000000000000000000000081d31445560747e838078645c4b37220d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000152a3f556a7f94aabfb49f8a7573889db2c1ad97826d5847331f253a50657a8fa5c6b39e89735761778a9fb4c5b29d8774604b36251300000000000000000000000000000000000d22374c62778ca8b9bfa9947f6a75879db2bfbcab9b8572604a39291612273c51677c91aabbc4a9947f6a545572879db2c4af9a846f5a3726140100000013283e53687d93a8bdbba6917c8a9da6b2bec8c2b6b1aca8a8a8acb1b5c2c6c0b4a79e8a7a645b49382715000000000000000c22374c61778ca7b8ccbfb3aea5a89e9c99989797999b9ea8abb3b8b4ab9f958375615645311d10000000000000000f23384c5e6f849aa9b9a79a848399aeab96806b56373b484c575b584e4a3d2d1d0d000000000000000000000001142636556a7f94aac3baa9927d67523c2c1906000000000000031629394c5e70859ab0c3b9a8937d68533b2b180500000000000000000000090f111a1d19100e080000000000000000000000000000000000000000000000000000000f1f2d3e4a5c647a899ea7b8c3b7a69e8a7b665e4e413231302f2d2c2a27211e170b0000000000000000000000000000000000000000000000000000000000000000000000000b20354b6073849398958a7b644f3b2a18050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003162839596e8398aec3b19b86716a8095aabbb49f8a76614c3625283d53687d92a8bdb09b86715b596c8197aabbb7a6927d685443301c070000000000000000000000000000000010253a4f657a8fa4c6bca6917c6a7f95a5b6c6b59f8d7a645443301b0b0c21364c61768b9fb4c5b09a85705860758a9fb4c1ac97826c57422d170000000013283e53687d93a8bdb6a18c767a8798a0b0b4c1c9c7c2bebdbec1c6cac5b8b3a29a897a645c4b3d2c1a0a000000000000000a1f33475873889eb3c8b3a199908c8986848382828486898f969ea7b4bbb4a1998474604b3f2e1b080000000000091c2f4050667b90a2b4b39e89787d92a8b09b8570554431343741454339362d1f0f000000000000000000000000000e24394e63798ea5b6c7af99846f5a49352010000000000002101e324657667c91a2b4c8b49e8a76614c36210d00000000000000000000000000000507040000000000000000000000000000000000000000000000000000000000000110202d3e4a5c647a899ea6b8c4b8a89e8b7c685f4f43331c14181615110c0a030000000000000000000000000000000000000000000000000000000000000000000000000012273c51677c91a2ada89c86715948341f0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000091e32465772879cb2c2ad97826d62788b9fb4baa9947e695443302b40556b8095aac0ae98836e594d62788b9fb4c4b19c8673604a3520110000000000000000000000000000000013283d52687d92a7bdc5a48e79788a9fb4c3b9a897826d5c4a362513000a1f33465870859bb0c5b49f8a766163788daabbbfa9947f6a543f2a150000000013283e53687d93a8bdb7a18c776476838f9ba3adb3b9c5bfc0bfc9bcb5b0a79e938478645c4b3e2e1f0f000000000000000004182a3a5b70859bb0c3ae99837b7774716f6e6d6d6f71757a8089969faabab3a297816c5d4b37220e00000000000f23384c5e70859bb0b4a3937e68788da5b49f8a75604b3620222c302e24211a0f01000000000000000000000000000c21364a5b72879db2c8b49f8b78634d3e2e1b0b00000000112030404b6175879db2c0bbaa96816c5846331f0a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000210202d3e4a5c6479889ea6b8c4b9a99f8c7d696151443026180a000000000000000000000000000000000000000000000000000000000000000000000000000000000000162c41566b8196abc0b6a48c77624c37220d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c21364b61768a9fb4bea9937e695a6f8499aec3b29c8773604a352e43586e8398adc0ab96806b56485a6d8298abbcb6a4917c66513f2e1c08000000000000000000000000000000162b40556b8095aac0b9a78c768399a9bac2b39e8977624c3e2d1808000417293a556a7f95aac5bbaa917c67667b90a6c8bca6917c67513c27120000000013283d53687d92a8bdb7a28d7862616e7a858f989ea7a7aaabaaa9ab9f9b93897e72625a4a3e2e201001000000000000000000182d42586d8297adc0ab96816b62595c59585857595560656b76818c9fa9bab59f8d7a644f3c2b190500000005182a3b50667b90a3b5b09b85726072879db2a98e79644f39240f171b180f0d07000000000000000000000000000000071a2d3d556a7f95aabbbbaa97826d5c4b39291a0c0308131c2e3e4c5e6c8196a5b7c6b49f8b78624d3a291704000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000210202d3d4a5b6379889ea6b7c4baaa9f8d7f6b624b4336281a0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000162b41566b8096abc0c2a38e78634e39230e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f253a4f647a8fabbcc3a58f7a6551667b90a5b7b6a4907b65503b2b3a5b71869bb0bda8937e68533c4e63798c9fb5c2b09b85705d4b372310000000000000000000000000000003192e43586e8398adc3b39e897b90a1b2c7b6a4947f6959473420100000000f243a4f647a8fa7b8c8ad97826d697e94a9bec5a48e79644f39240f0000000011273c51667c91a6bbb9a38e79644e5d65707a82898e9294959593908b857e75686054483c2e20100200000000000000000000152a3f546a7f94a9bfae99846e59483b4443424237444b5058616c7c8b9fb4bcab99846f5a4835200b0000000b1f3448596e8399aeb3a18f7a64546e8398aea7927d68523d2813020603000000000000000000000000000000000000000f22374d62778b9fb4c8b59f8d7a64574638291e161d25303f4b5c667c8d9fb5c3b9a897816c5a49351c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010f1f2d3d4a5b6379889da6b7c4bbab9f94806c60544538291b0c00000000000000000000000000000000000000000000000000000000000000000000000000000000152a3f556a7f94aabfb9a48f79644f3a240f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013283e53687d93a8c9b7a58c76614c6073879db2c3ae99836e594834475874899eb3c9a5907b65503b4a5b6e8399aec0b5a3907b65503e2d1b070000000000000000000000000004172a3a5b71869bb0c6b19c86869cb1bfbfb19c8674604b3b2a18020000000b20354b6074889eb3c8b39d88746c8197acc1b9a78c76614c37210c0000000010253a4f657a8fa4c9baa5907b65504b4f5d646d74797d7f80807e7b76706961574a43362b1e1002000000000000000000000011263c51667b91a6c8b19c87725544312f2e2d2d2731363a474c5e697f94a6b8b49f8b78624d38220d0000000d22374c62778b9fb4ae99846f5d556a8095aaab96806b56412b16010000000000000000000000000000000000000000000b203448596d8298aabbbcab9c86756156473a32293136434a5d657a8a9eabbcc0b49e8a77624c3c2b190000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010f1f2d3d4a5b6379889da6b7c4bcb59e958172605646392a1c0d00000000000000000000000000000000000000000000000000000000000000000000000000000014293e54697e93a9bebaa5907a65503b251000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000132536576c8197acc1b29d88725847546a7f94aabbb49f8b78624d374c61778ca7b9bcab8d78634d383d4f647a8fa2b4c1af9a846f5c4a36220e000000000000000000000000000a1f33475874899eb3c9b49f8b9ca4b6c7b3a1907b665544311d0d00000000081c3043546e8398adc3b7a68e796f849aafc4b39e89745847331f0a000000000e23384e63788dabbcbda8927d68533d3f4b4f556064676a6b6a69666158534b46393025180e000000000000000000000000000e23384e63788daabbb49f8a75604b3520191818151d202a33404b6075889eb3bcab927d68523d281300000215273854697e93aab7a5907b655053687d92a8ae99846e59442f190400000000000000000000000000000000000000000005182b3b4d63788b9fb4c3b6a499837461584b4639444b5460697b899ea8b9c4b4a2937e695947341e0e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010f1f2d3d4a5b6379889da6b7c4bcb09f9782746157473a2b1d0f010000000000000000000000000000000000000000000000000000000000000000000000000013283d52687d92a7bdbba6917b66513c2611000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071c30435470859bb0c3ae99846e593a4c62778b9fb4bbaa95806a55444f64798fa4c5b49f8a75604b36374b5c70859aafc1b3a18e79644f3c2c19060000000000000000000000000c21374c61778ca7b9ccbbaa9faab6c2baa999836f5e4c37271500000000000114263652687d92a7c2c4aa947f72879db2c6b19b86715c3a2a1704000000000b21364b60768a9fb4c1ab96816c563a2e3737444b4f5255565554504c473a3632281c130800000000000000000000000000000b20364b60758a9fb4bbaa8d78634d38230e030002080c171f3245566d8297adc9ac96816c57412c170200091d3145566f8499aeb29d87725d4b50667b90a5b09b86715b46311c00000000000000000000000000000000000000000000000d2035495a6c8196a5b7c3b3a19984766861575a556066727e8b9ea7b9c6b8a69a8472604a3b2a180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010f1f2d3d495b6379889da6b7c4bdb1a09884756158483c2c1f100200000000000000000000000000000000000000000000000000000000000000000000000011273c51667c91a6bbbca7927d67523d28120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b20354a6074899eb4bfaa95806a554048596e8399aec3b39d8874604b52677c92a7bcb29d88735645312e3e50667b90a3b5bfad98836e5a4935200d0000000000000000000000000f243a4f64798fa4c5d6c8bbb4bbc8c4b49f8b78634d402f19090000000000000d22374d62778ca4b5c5b09a85748a9fb4c3ae98836e59432e190000000000091e32455672879cb1c5b09b857058473322263135393d3f40403e3b37332a211e160b00000000000000000000000000000000081d31445572879cb1c8a5907b66503b261100000000000415283853697e93a8beae99836e59442e1904000b20364b6075899eb4ab96816b563f4e63788ea3b29d88735d482513000000000000000000000000000000000000000000000006192c3c4b6175879daabbbfb3a29a887e76706f70757b85939fa9b9c5baa99e8877625443301d0d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010f1f2c3d495b6379889da6b7c3bfb2a29a8576625a493d2d201103000000000000000000000000000000000000000000000000000000000000000000000010253b50657a90a5babda8937e68533e29130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e23384d63788da8b9c6a6917c66513c3b50657b90a5b6b7a6917c6751556a7f95aabfaf9a85705a382723384c5e71869bb1c3b49f8c78634d3b2a1805000000000000000000000012273d52677c92a7bcd1d9cecacecbb7a696806b5b49352212000000000000000b2034485971869cb1c6b49f8b7a8fabbcc0ab96806b56412b16010000000003162838596e8398aec3b49f8b77614c3721141d2024282a2b2b2926211f170c0903000000000000000000000000000000000002152737596e8499aebea9937e69543e2914000000000008182a3b53687d93a8bdaf9a846f5a452f1a05000f24394f64798ea8b9a6917c66513c4c62778ca1b49f8a745443301c0700000000000000000000000000000000000000000000000e1e324657657b8c9fb4bcc0b3a69d938a86848589909ba3b4bac7baaa9f8b7b6559483625130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010f1f2c3d495b6378879da5b7c3c0b4a39b8678635b4a3e2f211204000000000000000000000000000000000000000000000000000000000000000000000f24394f64798ea4b9bea9947f69543f2a1400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011273c51667c91a6c6b9a88d78634d38354a6073879cb2c4af9a85705b586d8298adc2ad97826d58422d1c2f4052677c91a5b6bcab97816c5948341f0b0000000000000000000000152a40556a7f95aabfd4ebe2dfd1c1b39d8876614b3c2c19040000000000000005182b3b566b8096abc6bbaa988398adc9bda8937e68533e2913000000000000152a3f546a7f94a9c3bbaa927d68533f2e18080b0f1215161514110c0a04000000000000000000000000000000000000000000162b41566b8096abc0ac96816c57412c17000000030c18253447596d8297acc2ae99846f59442f1a040012273c52677c91a7c6a38d78634e384c62778ca1baa98a75604a35200b0000000000000000000000000000000000000000000000031629394b5d697e939eb5bcc4b7b3a99f9b999a9ea7b0b5c1c4b8a99f8c7d675d4b3b2b18080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080b0d0e10111f2c3d495a6378879da5b7c3c1b5a49c8779645c4b3f2f2212010000000000000000000000000000000000000000000000000000000000000000000e23384d63788da2b8bfaa95806a55402b15000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000152b40556a8095aabfb49e8974604a353043546a7f94a9bab4a28e79635b70859bb0bfaa957f6a55402a1520354b6073879cb2c4b49f8a77624c3a29170400000000000000000003182d43586d8298adc2d7edecdac9b5a3927d685746331e0e00000000000000000010263b50657b90a8bac8b49f8a9fb4c9c8a5907b65503b26100000000000000e24394e63798ea5b6c8b09b85705d4b362614010000000100000000000000000000000000000000000000000000000000000013283d53687d92a8bdaf9a846f5a38281502090b171e2a36434c61778a9eb4c2ac97826d57422d18020014293e53697e93a8b7a28d77624d394e63788ea3c49f8a755443301c070000000000000000000000000000000000000000000000000b1b2e3f4f606b80949fabb8c5c7bab4b0afb0b3b8c5c9bfb3a69e8b7d675f4d3f2e1d0d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009141d202324252627282c3c495a6378879da5b7c3c2b6a59d897a655d4c402f1f0f0000000000000000000000000000000000000000000000000000000000000000000d22374c62778ca1c7c0ab96816b56412c16010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003172939596e8399aec3b09a857054433025364c61778a9fb4c0ac96816c5773889eb3bca7927d67523d28121c304354687e93a6b7baa996806b5846331f0a000000000000000000031729395b70859bb0c5daf0e3cfbcab9b8572604a392917000000000000000000000b20364b6075899fb4c9baa99fa9bacebbaa8d78634d38230e0000000000000c21364a5b72879db2c7b4a38f7a655443301c110200000000000000000000000000000000000000000000000000000000000010253a4f657a8fa4c5b29d87725645321d151d2029333a4754606e8399a8b9c0a9947e69543f2914000013293e53687e93a8baa5907b65503e51667c91a6b7a68a75604a251300000000000000000000000000000000000000000000000000001021324250626b7f8d9ea7b4bbc8c9c5c4c5c8c7c2b5b1a199887b675f4d4030211100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004111926313538393a3b3c3e3f403c495a6278879da5b6c3c3b7a79e8a7b665e4c3d2d1a0700000000000000000000000000000000000000000000000000000000000000000b21364b60768ba9bac2ac97826d57422d1802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1e33465772879db2c1ac96816c5736251f3447596e8398adc2b39e897561768ba6b8c7a48f7a654f3a25101426364b6075889db2c5b39e8976614c3828160200000000000000000a1e33465773889eb3c8dde8d6c6b59f8d7a645443301b0b00000000000000000000091d3245566f8499afc4c7bab4bac7cab49f8a75604b36200b000000000000071a2d3d566c8196abc0c1b09b8573604b3f2f20120400000000000000000000000000000000000000000000000000000000000c22374c61778ca7b8b49f8a75604b362a28323639464c5861728096a1b2c6b4a28e79634e39230e000012273c51677c91a6c2ab96806b5c525c6d8298adb39d88735e48331e0000000000000000000000000000000000000000000000000000031424334450616a7c88979faab0b4bbc8c3b6b2aca49c908377655d4d413022120300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011222f37444b4d4e4f50525354555657595a6278879da5b6cac5b8a89e8b7c665c4a36210d0000000000000000000000000000000000000000000000000000000000000000091e324556748a9fb4c3ad98836e58432e190000000000000000050b0d16160e0c07000000000000000000000000000000000000000000000000000000000000000000000000000c21364c61768b9fb5c8a8937d68533e28182a3a50657a8fa4b6b9a7937d68798ea3c4baa98c77624d37220d081d324556697f94a7b8b9a8947f6a5645321e0900000000000000000c21364c61768ba7b8cce0e1ccb9a897826d5c4b36251300000000000000000000000215283854697e93a9c3d4cec9ced8c7b29d87725544311d08000000000000000f24394f64798ea2b4c8b4a3947f695d4b3e2f1f170b070000000000000000000000000000000000000000000000000000000a1f33475873899eb3bcab8e78634e3e4038454b5157616a7683969eb0bfbfb09b85705b4a36210c00000e23384e63788da4b6b49f8b7a6b67697a8b9fb4b09b85705b46301b06000000000000000000000000000000000000000000000000000006162633434f5e6677828b949b9faaa3a3a59d978f867b6f62594b3f302313040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1e2f404c5560626365666768696a6c6d6e6f707178879db2c7d5c6b9a99f8b7a644e39240f0000000000000000000000000000000000000000000000000000000000000000031628385e73899eb3c4af99846f5a3b2a18050000000000000e1920222b2b24211a0f01000000000000000000000000000000000000000000000000000000000000000000000010253a4f657a8fabbcbbaa8f79644f3a240f23374b5d72869cb1c5b19b86717c91a6bcb49f8a75604a35200b021528384b6176899eb3c6b39d8875604b37261401000000000000000f24394f64798ea4c5d5e6d3c3b49e8977624c3e2e18080000000000000000000000000e23384e63788da5b7cadfdfe2dac4af9a856f5a37271502000000000000000d22364a5c70859ab0bfc1b49f8b7b655c4c403329201c13120f0b090200000000000000000000000000000000000000000004182a3a5b70859bb0c9a6917b66535455575660666d767f8999a1b0bdc3b3a1907b65503d2d1a0700000c2135495b72879cb1baa99f8b817c7f889eaabbac97826c57422d170200000000000000000000000000000000000000000000000000000008162532404d59626d787f868a8e8e8e8b87827a71665e4c473b2e21130500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006192b3c4c5e667478797a7b7c7d7e80818283848587878a9fb4c9ded6c7baa999836e59442e190400000000000000000000000000000000000000000000000000000000000000001d32485d72879db2c7b29c87725947341f0b0000000003111e2b3538404039362d1f12040000000000000000000000000000000000000000000000000000000000000000000014293e53697e93a8c9b49f8a76604b36210b1c2e3f54697e94a9bab5a38f7a7f94a9bfb19c87725443301c07000a1e3246576b8095a8bab8a6937e685544311d080000000000000012273c52677c91a7bcd1dfcab6a5947f695948342010000000000000000000000000000c2135495b72879db2c7dcf2ecd7c2ac97826d57422d180000000000000000071b2d3e50657b8fa1b2c5baa99e897a665e4c463a3530252724201d150a000000000000000000000000000000000000000000182d42586d8297adbea9947f6968696a6c70757b8289959ea7b3bfc4b6a599846f5d4c381f0f000000061a2c3d52687d92a1b3baa99f9691949ea6b8b7a6907b65503b26100000000000000000000000000000000000000000000000000000000000071522303b474c5a626a717578797876726c655d514c40342a1d1103000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b2035485a667c878d8e8f9091939495969798999b9c9d9fa8bacde1e5d7c7b29d88735d48331e0800000000000000000000000000000000000000000000000000000000000000071c31465c71869bb1c6b49f8b77624c3929170500000312212e3c484d55554e4a3d30231200000000000000000000000000000000000000000000000000000000000000000001142636576c8297acc1b19c87715645321e091121374c61768a9fb4c1ad98828197acc2af99846f5a3625130000031629394c61778a9fb4c4b29d8774604b35201200000000000000152a3f556a7f94aabfd4d0bfb29c8774604b3b2a180200000000000000000000000000061a2c3d576c8297acc8d8eae9d4bfaa947f6a553f2a150000000000000000001023374b5d6e8399a7b8c7b9a79e8a7c6c61584e4a43363d393632281a0e0000000000000000000000000000000000000000152a3f546a7f94a9bfb09a847e7d7e7f82858990979ea7b3b9c5c0b4a69c8776614c3f2f1c01000000000f20354a60728399a2b3b9b4aba7a9b3b8bbb29d8773604b35200b00000000000000000000000000000000000000000000000000000000000004121d2a343c484d555660636463615757504b3f382f1f180d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d23384d62788a9da5a3a4a5a7a8a9aaabacaeafb0b1b2b4bac6d7d3d1d9c9b39d88735e48331e0900000000000000000000000000000000000000000000000000000000000000051b30455a70859aafc5bcab947e695746331f180d0c171e303f4b5a626b6b635b4d41301b0b0000000000000000000000000000000000000000000000000000000000000000081c30435470869bb0c2ad98836d58382816030a1f3347586d8298adc2b49f8b869cb1c1ac97816c57422c170000000b1f3347586c8196aabbb6a5927d6752402f1c09000000000003182d42586d8297adc2d8c8b3a1907c665645311d0d00000000000000000000000000000011273c51667c91aabbcee2e7d1bca7927c67523d2712000000000000000000081c2e3f4c6277899eaabbc5b9a89e9081766c64605455524f4b45382c1e0e0000000000000000000000000000000000000011273c51667c91a6c0b4a29a93939395979b9fa8adb3b9c5c5b8b3a29a88796358473321110000000000071c304354617584949ea7aeb3b9c5c1b4b09d917d675443301c0800000000000000000000000000000000000000000000000000000000000000000d181f2b353838454b4e4e4e4b46393a372e241c12050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014293e54697e93a8b6c3babbbcbdbebfc1c2c3c4c5c5c4c3c1c0bfbdbcc8bbab99846f59442f1a040000000000000000000000000000000000000000000000000000000000000004192f44596e8499aec3c9b39d8876614c44342a23222933414d5d6578808079675f4d39291603000000000000000000000000000000000000000000000000000000000000000b20354b6075899fb4bfa9947f6a543f2a150004172a3a4f657a8fa4b5baa99f9ca4b5bea9947f69543f2a1400000004182a3a4d62788b9fb4c3b19b86715e4c3823100000000000031628395b70859ab0c5cebbaa99846f5e4c382715000000000000000000000000000000000c21364c61768a9fb4cadfe8d6c6a48f79644f3a240f00000000000000000000111f344759657b8c9fabbbc6b9b49f97898179746e6a67646056493c2c19060000000000000000000000000000000000000d23384d62788da2b3c0b4b0a8a8a9aaacb0b4bac6c8c3b7b2a79e948477635b493a2a1703000000000000132536465761737f8992999ea7a3a3a39b907f6a5f4d36261401000000000000000000000000000000000000000000000000000000000000000000050e19202328323639393936322925231c1109000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000152a3f556a7f94aabfc0bfbebcbbbab8c8bbb4b3b2b0afaeacaba9a8a7a5aa9f8d7b65503a2510000000000000000000000000000000000000000000000000000000000000000003182d43586d8298adc2cbb8a698826d624c483b383739464c5f677b8995958c7d675746321e0a000000000000000000000000000000000000000000000000000000000000000e23384e63788da8bac4a5907b66503b261100000c22374b5d71869cb1c6bab4b1b5c2bca6917c67513c2712000000000c2035485a6d8298abbcb5a3907b66503e2e1b0800000000091e32465773889db3c8c4b49f8b79634e402f1a0a000000000000000000000000000000000a1e33465770859ab0c5dae1ccb9a88c77614c37220c0000000000000000000005182a3b4b5d687e8d9faab8c5bdb1a89e968e8883807c7974635a4935200c0000000000000000000000000000000000000b2035495a6f849aa7b6c3c5bebdbebfc1c4c1c4b7b3aca59d95897e746259493d2c1c0c000000000000000818283946556069757d83898c8e8e8b857b6a615041301808000000000000000000000000000000000000000000000000000000000000000000000000060b0d151d20232423211e16100e08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010253a50657a8fa1acabaaa8a7a6a4a3a2aa9f9e9c9b9a989796949392908f8b7f695d4b37230e000000000000000000000000000000000000000000000000000000000000000002172c42576c8197acc1d5c4b2a095806e6259504d4c5057616c7d8b9ea7aa9e8976614b36210c0000000000000000000000000000000000000000000000000000000000000012273c52677c91a7c6b8a68c77624c37220d0000081b2e3f53697e93a8bacdc9c6c9d2c5a48e79644f39240f0000000005192b3c4e63798c9fb5c2af9a85705c4b37220f000000000c21364b61768ba6b7c8b8a696816b5b49352212000000000000000000000000000000000003172939556a7f94aac5d5dec9b49e89745947341f0a00000000000000000000000d1d2f3f4e60687e8c9ea7b3bfc6b9b4aca69e9895928e8778634d38230e00000000000000000000000000000000000006192b3c4d6378899ca4b0b4bbbcb5b3b1afaca8a69d9790877f76696055473b2c1f0f0000000000000000000b1b2837444b5761686e747779797670665e50433323120000000000000000000000000000000000000000000000000000000000000000000000000000000002090b0e0f0e0c0a0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e23374b5d6e83949796959392908f8e8c8b8a888786848382807f7e7c7b7a7769614f3f2e1c08000000000000000000000000000000000000000000000000000000000000000001162b40566b8095abc0d5cebeb09e9583776c666261656b7681919fa9b9b9a7907a65503b251000000000000000000000000000000000000000000000000000000000000000162b40556b8095aac0b39d88735948341f0b0000001021364c61768a9fb4c9dedbdeccb9a78c76614c37210c00000000000e2135495b6e8399aec0b4a28f7a644f3d2d1a070000000c21364b61768a9fafb3b19e8876614c3d2c1a040000000000000000000000000000000000000f24394f64798ea7b8ccdbc6b19c86715c3a2a1804000000000000000000000000112131424e60687c8999a1b1b5c2c9c4b8b3adaaa7a597826d58422d18030000000000000000000000000000000000000e2035495a637986939b9faaab9f9e9c9a97928e88827b746a61584b44372a1d0f01000000000000000000000b19263139464b5254606263636158504c4033251505000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081c2e3f4b60747e82817f7e7d7b7a797776757372706f6e6c6b6a6867666461584f4232211100000000000000000000000000000000000000000000000000000000000000000000152a3f546a7f94a9bfd4dccdbcb0a0988a817b78777a8089979fb4bac3b2a08e78634e39230e0000000000000000000000000000000000000000000000000000000000000417293a596f8499aec4af9a846f5a3b2a18050000000a1e3346576d8297acc1d2e4dec9b39e89745847331f0a0000000000061a2c3d4f647a8fa2b4c0ae99836e5b4a36210e000000091e3246576b80929a9d9b927d675746331f0f000000000000000000000000000000000000000b20354a6074889eb3c8d8c3ae99836e59442e190000000000000000000000000003132431424e5e657783909ca4aeb4bbc8c6c3bfc3b09b85705b46301b0600000000000000000000000000000000000006192c3c4a5b63747e868a8b8b8a898784817d79746d6660544c463a3127190d0000000000000000000000000009141d28323636434a4c4e4e4c463a382f221507000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080e1013110b0902000000000000000000000000000000000000000000000000040b0c1417160e0c07000000000000000000000000000000000000000000111d31455660696c6b6a69676665636261575e5d5b5a595756545352504f4c473a322414030000000000000000000000000000000000000000000000000000000000000000000013293e53687e93a8bdd3d6ccc9bfb2a89f96908d8c90959ea7b1bdc4b6a598826d5b4935210c0000000000000000000000000000000000000000000000000000000000000a1f33475872889db2c0ab96806b56412b1600000000031729394f647a8fa3b5c9dddbc6b19b86715c3a2917040000000000000f22364a5c6f849aafc1b59f8c79634e3c2b190500000316283951626b7d8588867d685f4d3929170100000000000000000000000000000000000000071c3043546d8398adc9dac0ab96816b56412c16010000000000000000000000000006142431404c59626e7b8690999faaacb1b4bbbdad98836e58432e1903000000000000000000000000000000000000000e1e2d3d4a566069717576767574726f6c68636054514b433633291d1509000000000000000000000000000000010b161e21253035373939363329231c1103000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101b22252827201d150a000000000000000000000000000000000000000000000c181f222a2d2b24211a0f010000000000000000000000000000000000000002152738454b545756555352514f4e4d4b46394746454342413f3e3d3b3a37332a1c1406000000000000000000000000000000000000000000000000000000000000000000000012273d52677c92a7bcd6c6b9b4b9c6bab4aca5a2a1a5abb3b9c5c1b5a69c8776614c3d2c1a060000000000000000000000000000000000000000000000000000000000000c21374c61768ca5b7c7a7927c67523d271200000000000b22364a5c71869bb0c6d6d8c3ae99836e59442e1900000000000000071b2e3e50657b90a3b5bcab98826d5a4835200b0000000b1b3444515f6770737168604e41301b0b00000000000000000000000000000000000000000013253652677d92abbccfbea8937e69533e29140000000000000000000000000000000614212f3b484c5e66737b848a91979b9faaa59f917c66513c26110000000000000000000000000000000000000000000f1f2d38454b545460616160545c5a57534e4a43363530261f170b0200000000000000000000000000000000000003090c131c20222424211f170b090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c181f2e373a3e3c3631271a0c00000000000000000000000000000000000000000d1d2a34373f424039362d1f1406000000000000000000000000000000000000000a1a2731363f4241403e3d3b3a393736322832312f2e2d2b2a29272625221f180c0000000000000000000000000000000000000000000000000000000000000000000000000011263c51667b91a6bbccb9a89ea8b4b9c6c1bbb7b6bac0c9c5b8b3a39b8879635847331f0f0000000000000000000000000000000000000000000000000000000000000010253a50657a8fa5c3baa98e78634e39230e0000000000071b2d3e53687d93a8b9ccd6c0ab96816b56412c1601000000000000001023384c5d71859bb0c2b49f8b78624d39291603000000162634414d525a5e5c524e41312313000000000000000000000000000000000000000000000d22374c62778b9fb5c5bea5907b66503b26110000000000000000000000000000000003111d2b34404c5460666f767c82868a8d908f816d5e4c38240f000000000000000000000000000000000000000000010f1a28323636434a4c4b4b433645423d39353025201c140804000000000000000000000000000000000000000000000000070b0d0e0e0c0a04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1d2a343f4b4f53514b4538291c0c0000000000000000000000000000000000000d1d2b3b474c5457554e4a3d31241402000000000000000000000000000000000000000a151d20292d2c2a292826252422211e161d1b1a191716151312110f0c0a04000000000000000000000000000000000000000000000000000000000000000000000000000010253a50657a8fa5bac9b49e89949ea8b0b4bbc8bbc6b9b4afa79e948578635b493a2a17010000000000000000000000000000000000000000000000000000000000000014293e54697e93a9beb49f8a75604b35200b0000000000001021364b6176899eb4c9d3bea8937e69533e29140000000000000000091c2f3f51677c91a4b6bbaa96816c5746321e0a00000008162330393d4548463d3a31231305000000000000000000000000000000000000000000000b1f34485971869baeb0aea08d78624d38220d0000000000000000000000000000000000000d18202f36434a505861676c7175787b7a6d6352402f1d0900000000000000000000000000000000000000000000000a151d2025303536363530262f2c2824201c130b08010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004182a3b474c5d6568666056473a2917040000000000000000000000000000000005182b3b485961696c6b635b4e42311f0b000000000000000000000000000000000000000002090b14171615141211100e0d0c0903000605040201000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f24394e64798ea3c0bda48e7a7f89939b9faaa5a6a5a89e9992887e73625a493c2c1c0c0000000000000000000000000000000000000000000000000000000000000001152737586d8297adc2b09b86715544311d080000000000000a1e3246576c8197acc1d1c9a6907b66513b26110000000000000000001120354b6073869cb1c3b49f8976614b36210c0000000005131e252730333128251e1305000000000000000000000000000000000000000000000005182a3b54697f92999b9992826e5a4835200b000000000000000000000000000000000000000512182530353a464c525755606365645d52453522120000000000000000000000000000000000000000000000000002090b131c202121201c141a17130e0b070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c11141719191816130f0b08010000000000000000000000000000000000000b1f34475961707a7d7c74615847331f0a000000000000000000000000000000000b2034485962777f82807968604e3a2611000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c22374c61778ca2acab9f8c776a767e858a8f9091908d89847d75696055483c2c1e0e0000000000000000000000000000000000000000000000000000000000000000081d31445571869bb0c2ac97826d5737261401000000000000031629394e64798ea3b4c8bcab8d78634e38230e000000000000000000081c304354687d92a5b7b49f8b77614c37210c0000000000010a10121b1e1c13110b01000000000000000000000000000000000000000000000000000d273b4f61697d8385837d73604b3c2b190500000000000000000000000000000000000000000008131c202933363c37444b4d504f4b3f352717040000000000000000000000000000000000000000000000000000000000070b0c0c0b08010002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c171f21262a2c2e2e2e2c2924201d140907000000000000000000000000000000000c22374c6177858f93918676614c37210c000000000000000000000000000000000d22374d6277899497958c7e68533e281300000000000000000000000000000000000000000001080b0e1011100e0b0902000000000000000000000000000000000000000000000000000000000000040a0c161a19110f0900000000000000000000000000000000000b1f3447596f849397968f816c59616870767a7b7b7a78746f6860574b44372b1d0e0000000000000000000000000000000000000000000000000000000000000000000b20354b60758a9fb4c9a8937e69533e291400000000000000000b21364a5c70859bb0c3b59f8b76604b36210b000000000000000000011426364b6074879da89f95816c5847331f0a00000000000000000005090700000000000000000000000000000000000000000000000000000000000c2032434f5f676e706e67605544311e0e000000000000000000000000000000000000000000000000070b171f2127273136383b3a372e20170900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040c171f212a33373b3f42434443413e39353126211a0f050000000000000000000000000001172c41566c8196a3a8a4937e69543e291400000000000000000000000000000000152a40556a7f95a7acaa9d88725d48331d080000000000000000000000000000000000050b0d151d202325262523201d150d0b0500000000000000000000000000000000000000000000000000000c171f212b2f2e27241d120400000000000000000000000000000004182a3b4b60757d82807a6c63514b53566064666665636054524b45393126190d000000000000000000000000000000000000000000000000000000000000000000000e23394e63798ea9babcab8f7a654f3a25100000000000000000071a2d3d52687d92a5b2b09d87725645321e0900000000000000000000081d314556657b8a8e8a8073604b3a2a1704000000000000000000000000000000000000000000000000000000000000000000000000000000000003142532414d52595b59524b44372614000000000000000000000000000000000000000000000000000000040a0c12151d20232625221b1002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c11120e0c0600000000000000000000000000000000000000000c181f2933363a474c51545758595856534f4b4437362d20190d00000000000000000000000004192f44596e8499aec1ac96816c57412c1700000000000000000000000000000004182a3b596e8499aec5b29d88725d48331d08000000000000000000000000000000050e192022273135383a3b3b383632282220190d0700000000000000000000000000000000000000000000000c1c2a33374045433c39302215070000000000000000000000000000000c1e32455760686c6b645d51453638454b4f5051504d4b43363632281d1409000000000000000000000000000000000000000000000000000000000000000000000012273d52677c92a7c7b59f8b76614b36210c0000000000000000000f21364b607587989d9a917e68533828160200000000000000000000021527384b5d657679766b605544311c0c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000007142330393d4446443d35312619090000000000000000000000000000000000000000000000000000000000000002080b0e100f0d08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b171f2127282320190e000000000000000000000000000000000003141c2a343a464c54586166696c6e6e6d6b686460554e4a3d342b1d120400000000000000000000041a2f44596f8499aec1ac97816c57422c170000000000000000000000000000000b1f34475973889db2c4ae99846f59442f1a0400000000000000000000000000000d19202b353837444b4d5050504e4b453837342b211a0f0300000000000000000000000000000000010200000a1b2a3a474c555a58514d4033251500000000000000000000000000000003162839454b5357564f4b3f34212832363a3b3c3b38353026211e160a01000000000000000000000000000000000000000000000000000000000000000000000001162b41566b8096abc0b29d87725746331e0a000000000000000000091e32455663788387857c68604e3a1a0a0000000000000000000000000a1a2f3f4b58616461574b4437261400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005131e25272e302e27201d140900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006141b2933363c3d38352c1e130600000000000000000000000000000b161e313a474c58616970777b7f81838383817e79746c635b4d483c30221406000000000000000000051a2f445a6f8499afc1ac97816c57422c170000000000000000000000000000000c22374c61778ca6b7c0aa95806b55402b160000000000000000000000000005131d2b343c484d55556063656665636056544d483b362d1e160a000000000000000000000000050b0d1617110f1628394758616b6f6e665e5044331b0b0000000000000000000000000000000a1b2832363e42413a372e2017161e212526262523201c140b090300000000000000000000000000000000000000000000000000000000000000000000000000031729395a6f8499afc3ae99836e593929170300000000000000000003162838495a636e7270675f4e42311e000000000000000000000000000011212f3a474c4e4b46393126190900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a1012191b19120b080100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070b0b0801000000000000000000000000000000000000000000000000000000000000000000000001090b07000000000000000000000000000000000000021424313a464c51524d493c312413020000000000000000000000000c1b2832424e59616c767e858b90949798999896938e8882796e625a4d40322514060000000000000000051a30455a6f859aafc1ac96816c57412c1700000000000000000000000000000011263b50667b90a5c4c5a6917c66513c2711000000000000000000000000061423303c484d5a626a7075787a7b7a7875706a62594e4a3e32281b0e000000000000000000000d1820222b2d26241e32455761768084837c6a6250392917030000000000000000000000000000000a161e21282d2b25221b100203090b0f1111100e0b0801000000000000000000000000000000000000000000000000000000000000000000000000000000000a1e33465773889db3c9aa957f6a55402a1500000000000000000000000a1a2c3c494d595d5b514d40312413020000000000000000000000000003111c293337393633291d1409000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b0d13131c20201c141a140e0c06000000000000000000000000000000000000000000000000000000030a0c161e201c110f09000000000000000000000000000000102131424e58616667635a4e42311e0b00000000000000000000000c1c2939464b606877818a939b9faba9acadaeadaba8a79e978e8378665e4f433224140200000000000000051b30455a70859aafc1ac96816c57412c17000000000000000000000000000000152a3f556a7f94aabfb8a78d78624d38220d000000000000000000000005142432414d5a626e787f858a8d8f90908d8a857f786f645c4b45392b1e0e0000000000000002101d2b343740423b382f364b607587959a9891806a5746331e0a0b12100e08000000000000000000000003090b1317160f0d0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c21364b61768ba4b5bcab917b66513c26110000000000000000000000000e1e2c35384348453c3930221306000000000000000000000000000000000c171f2124211e170b0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005090a0a09060200000000000000000000000000000000000000000000000000000000000000060d181f22292530353530262f292321190e070000000000000000000000000000000000000000000000000b161e212b33353126231c1104000000000000000000000000081b2e3f4e6068767c7d7868604e3a260b000000000000000000000a1a293a4757616e7e89969fa9b0b5bcc9c1c2c1c2c0c5b8b3aca098897c69614f4231201000000000000000061b30455b70859ab0c1ac96816c57412c17000000000000000000000000000004172a3a596e8399aec3b39e88735a4835200b0000000000000000000000122332424f5f6778838b949a9faaa5a5a5a99f9a948b84796d6057483c2b1c0c00000000000010202d3b484c5657514c40394f64798ea5afad9f8a76614c36211e212726231c110200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b20354a6073869ba3a69f8c77624c37220d000000000000000000000000000e1920232e323027241d1204000000000000000000000000000000000000040a0c0f0c0a0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070d0f161b1e1f1f1e1b18130d0b0600000000000000000000000000000000000000000000000000000e19202a34373e36434a4b4336443f38352c201c13080000000000000000000000000000000000000000000b1b29323641494a473b382f22110000000000000000000000000e22374b5d687e8a91928d7e6853392916030000000000000000021528384758617583939ea7b4bac7c6b9b3afadacadb0b4bbc8beb2a79e8d7f69604e3e2e1909000000000000061b30465b70859bb0c1ac96816c57412c1700000000000000000000000000000a1f33475872879db2c4af9a846f5a3c2b1905000000000000000000000e1e30414f60697d89989faab0b4bbc8bbc7bab4afab9f998d8275625a483a2a18040000000008182d3e4a59626b6c665e4b454e63798ea3c3baa98e79634e392832363c3b382f1d150a0000000000000000000000000000040a0c161b1a12100a0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071c3043546278858e918e816c5947341f0b0000000000000000000000000000060c0e191d1b12100a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008101b22242b3033343533302d282320190e090200000000000000000000000000000000000000000008131c2c353b474c5359546060545d59544d493c35302518110300000000000000000000000000000000000003162939464b565e605c504c402f1b0a000000000000000000000010253a4f657a8d9ea8ab9d87725746321e0a0000000000000000091d32455661768598a0b3b9c5b9b4aba89e9a9896989b9faab3b8c5b9ab9f937e685c4b372715010000000000061b31465b70869bb0c1ab96816c56412c1700000000000000000000000000000c21374c61768ca5b7c0ab96806b56412b160000000000000000000005192b3c4d5f697e8d9ea8b4bbbcb4b1aeaeb1b3b9c6bcb4ab9f978678625847331f12000000001325364a5c647780827c6d60564f64798ea4b9c7a38d78634e3838454b52504c3f31271a0a0000000000000000000000000c171f212b302f27251d130500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000132536495a6271797c796c62513b2a1805000000000000000000000000000000000004080600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004111c232d36394045484a4a4846423e38352b201d150a000000000000000000000000000000000000000a1825303c494d5962686e72757575726f69635b514a43362e1e160b00000000000000000000000000000000000a1e324657616b737571665e4c392816030000000000000000000014293e53697e93abb9b7a58b76614b36210c00000000000000081c2f3f4b6074859ba3b2bfbcb4a89e968e8985828183858b939ea7b4c0bcb49f8c7a645544311d080000000000061c31465b71869bb0c1ab96816c56412c17000000000000000000000000000010263b50657b90a5c3c6a7917c67523c2712000000000000000000000b2035485a677d919fabb9bdb1ab9f9b99999b9ea8aab3b9bcb5a49c8776614c40301d090000071c304354647a899597908274625a64798fa4b9b7a28d78624d434a566067655d4b4538271502000000000000000000000d1c2933364046453c393023150700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008182c3c494d5c6466635b5144341d0d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c181f2e373e4a4e555a5e5f5f5e5b57534d493c3632281a1201000000000000000000000000000000000a1b2836434a5a636d777e83878a8a8a87847e78706760544b3f32281b0f0100000000000000000000000000000417293a4b617580888a867c665745321e090000000000000000000012273c52677c91a7c9c3a38e78634e39230e000000000000000e23374b5d6d8297a3b4c1b8ab9f96898179746f6d6c6d70767e899aa2b4c0bbaa9c8674604b35200e0000000000071c31465c71869bb1c1ab96816c56412c170000000000000000000000000000142a3f54697f94a9beb9a88d78634e38230e000000000000000000000d22384d6278899eb3bcbcb59f978b86838386898f959ea8b2beb5a59a846f5e4c39240b00000b20354a6072869ca8ac9f97857865647a8fa4b9b7a28d77624d546067757c7b6f605645311d090000000000000000000d1d2a3a464c555b5a524d41332515020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1e2c353e4a4f514e4a3d3426160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003111c2a333f4b505c646b7073747473706d68625a534b4538301c140800000000000000000000000000000a1a28394554606a78828a93999c9faa9f9d99948d857c72655d4b46392c1f1002000000000000000000000000000a1f3346587084969ea49c8975604b36210b000000000000000000000f253a4f647a8fa4c9bba5907b66503b2611000000000000071b2d3e50657b90a0b1c1b8a79e8d81766b64605458575858616976849aa2b4c5b5a4927d67523c2b190600000000071c31475c71869cb1c0ab96816b56412c160000000000000000000000000003172939586e8398adc3b49e8974604a35200b00000000000000000001162b40566b8095a7b9bcab9f928278716e6e71747a808998a0b2beb4a2917c66513a291704000e23384d63788da4b6beb1a39b897b6a7a8fa4bab7a18c77625e66727d8791908374604b36200b000000000000000005182a3b4758616b706f675f5043332010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e19202d36393c39362d1f16080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000715212f3a474c5d657079808588898a8885827d78716860564d403026180800000000000000000000000002152838455760727f8b989fa9aeb2b4bbb4b2aea9a29a91867b6d6157493d2e2011030000000000000000000000000c21364c61768ba2b3b5a88f7a644f3a250f000000000000000000000d22384d62778dabbcbda8937d68533e28130000000000000d22364a5c71869bb1beb9a89e897b6c61584f4a4336413a464c586174849aa7b9c2b09b85705a4835200b00000000071c32475c71879cb1c0ab96816b56412c16000000000000000000000000000a1e33465772879cb2c5b09a85705443301c0700000000000000000003182d42586d8297adc0b59f8d7d6d625a59595460646b778298a0b2c0b09b85705846331f0a000e23384d63788d9fabb9c1b5a79e8d7f7b90a5bab6a18c76646f7b86929da5a1947f69543f2a1400000000000000000b1f34475962768085847d6a61503f2e18080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006101b22242724211a0f0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007152532404c58616e7b858e959a9d9f9f9d9b97938d867e74665e4b433626140100000000000000000000000c1d324556607583949fa9b4bac7c7c2bfc0c3c4c0b4b0a49c908275635b4b3e2e21110100000000000000000000000b20354a60758a9fb4c6a7917c67523c2712000000000000000000000b20364b60758a9fb4c0aa95806b55402b160000000000000f243a4f647a8fa3b5c6b49e8a7a655e4c473a3530252c29333a47566278899eb3c9b5a38d78624d38230d00000000071d32475c72879cb1c0ab96816b56412c16000000000000000000000000000c21364c61768b9fb5c1ab96816c56362513000000000000000000000012283d52677d92a2b3a5957f6a5f4d483c36434a4f59626e8298adc2b5a38b76614c36210c000c2035495a6a7f8d9ea8b6c2b8ab9f94869cb1c7b6a08b757a84909ba3b2b7b09b86715b46311c00000000000000021527374c627786959b9a91806a5d4b362513000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070d0f110e0c070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003152533434f5e6576828f9aa2aaafb3b4b4b3b0aca8a39b93877c6c605443301c14000000000000000000000c1c31414b60748399a1b4bac7c3b6b2acaaaaadb3b7c4c2b5b19f978679645c4b3f2e1f0f0000000000000000000000071c30435472879db2bea9947f69543f2a1400000000000000000000081d31445573889db3c2ad98826d58432d18000000000000162c41566b8196abc1b9a8937e695c4c403329201c1317171f2a38485a6b8095abbcc1a8937e69533e291400000000081d32475d72879cb2c0ab96816b56412c160000000000000000000000000010253a50657a8fabbcc7a7927d67523d281200000000000000000000000b20354b607384979e9d8774604b413e3c3a39383b484e63798ea3b8c1a38e78634e39230e0006192c3c50616a7c8a9ca4b2bfbcb4a49ca4b6cac3ae99838d9aa2b1b5c2beb29d87725d48321d00000000000000081d3144556d8298a4b0af9e8f7a645443301c0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d20334350616a7b8898a0b0b4c0c5c6c2c0c0c2c2c1b5b0a59d918172604b42311d0c000000000000000004172a3a4d5f6d8297a2b3bfbfb3afa49c979595989da6afb3c0bdb1a49c897a655d4b3d2d1d0d00000000000000000000001325365b70859ab0c1ac96816c57412c1702000000000000000000021527375b71869bb0c5af9a85705a3625130000000000001b30455b70859ab0c5b39e8975604b3e2f1f170c070000040c1a2b3c4d62788b9fb4c3ad98836e58432e1900000000081d32485d72879db2c0ab96806b56412b160000000000000000000000000014293f54697e94a9c9baa98e79634e39240e0000000000000000000000081c30435461758189877a6456555553514f4e4e4e5054657b90a5bab9a88d77624d38220d00000e1e3343505e66798698a0b4bbc2b6b1b6c2d3c6b2a1999fabb4c0c0b4b0a096806b56412c16000000000000000b20364b6075899fb4c3bcb09b8572604a39291703000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080e101616100e08000000000000000000000000000000050b0d12100b0801000000000000000000000000000000000000000000050b0d0e0b09020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013273c50616a7f8d9da6b2bec9bcb4b1adabaaadb1b5bcc3b7b29f97826d604e3b2a1804000000000000000a1f334758677d92a0b1c0bcb4a19a8f87827f808388909aa2b2b7c2b5a79e8a7b655c4a3b2a190900000000000000000000192e43586e8398adc3ae99846e59442f190000000000000000000000192f44596e8499aec3b29d87725443301c0700000000001e34495e73899eb3c7ae99846e5645312011040000000000000e2034485a71869bb1c6b19c87725c36251300000000081d33485d72889db2c0ab96806b56412b1600000000000000000305030003162839586d8298adc2b49f8a75604b35200b0000000000000000000000011426364657616c7372676a6b6b6a6866656363636568728399aec4b39e8974604a35200b000000152533404c5b637583949faab8c5c7cad3e0cfbfb2aeb5bcc3b6b2a29a8f8274604b36200b000000000000000f253a4f647a8fa8bacdc9b5a3927d685746331e0e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111c23252b2b25231c11030000000000000000000000000e1920222725201c1408000000000000000000000000000000000000020d18202224201d150a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000152a3f556a7f949fabb8c4b9b3ab9f9c989695989c9fabb2bebdb1a0937e695947341f0900000000000005182a3b4c6176899eb3bebcab9f94847a726d6a6b6e747b84909da6b4c0b8a89e897a64594837271501000000000000000001162c41566b8196abc0b09b86715b3828160200000000000000000002172c41576c8196acc1b49f8a75604a35200b00000000001a2f455a6f849aa9b4ac97826c57382715020000000000000005192b3c586d8398adc2b49f89745443301c07000000081e33485d73889db2c0ab96806b56412b160000000000060c0e181b1814101e32455771879cb1c5b09b86705544311d0800000000000000000000000a1b2a3b474c5f6771787c7f80807f7d7c7a7978787a7d8499a1b3c2ae99846f5443301c07000000071522303d4957616e7f8c9ea7b8c9d9e5edddcfc6c3c5b8b3a49c91857a6d605645321d090000000000000114263654697f94a9c6d7d2c1b39d8876614b3c2c1906000000000000000000000000000000000000000000000000000000000000000000000000000000000009141d2e373a40403a372e21130500000000000000000007151e2b35383c3b353026180e000000000000000000000000000000000a151d2b3437393631271a1204000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071c31475c71869cb1bcc0b4a89e948b8782818083868c98a0b5bcbeb49e8a77614c3727150100000000000b1f3447596c8196a7b8c0b49f8d7f6f645c5755555460656f7c889aa2b3bfb9a79d8877625544311d1000000000000000000014293f54697e94a9beb39e88735645321e0900000000000000000000152a3f546a7f94a9bfbaa98c77624c37220d00000000000f24394f647a8b999f9f947e69543f2914000000000000000002152737576c8196acc1baa98a75604a35200b000000091e33495e73889eb3c0ab95806b56402b16000000000e1920232e302d292622364b60768a9fb4c1ac97816c573727150100000000000000000000031628394759616f7d868d919495959493918f8e8d8d8f929aa2b3bfb6a4927d6752362513000000000004121f2c39464b616a7b899eabbccfe3f7ede2d2c2b5a79e93877c70645c4b4538281502000000000000081c3043546f8499aec4d9e0cbb7a695806b5a4935201100000000000000000000000000000000000000000000000000000000000000000000000000000000091926313f4b505556504b3f3123130100000000000000031525333c484d52504b43362c1e0e00000000000000000000000000000a1a27313b484c4e4b45382f22120200000000000000000000050b0d0e0b080100000000000000000000000000000000000000000000000000000000000002172c42576c8197a6b4b2a29b897f77716d6b6b6d717982939fabbcb9a896806b5544311d0800000000000d22374c62778a9fb4c5b3a2937e69614f4a3e4036434b505e66768499a1b2bfb7a69a8473604b3e2d1808000000000000000012273c52677c91a7bcb8a68b76604b36210b0000000000000000000012283d52677d92a7bcc7a48f79644f3a240f00000000000d22364a5c6479848a8a8376614c36210c0000000000000000091d3144556e8398aec3b49f8a745443301c07000000091e34495e73899eb3c0ab95806b56402b160000000e1e2c35384345433f3b373a4f647a8faabbc8a8937d68533e28130000000000000000000000091e324557617784929ba3a7aaabaaaaa8a6a4a3a3a3a5a7afb4c0b6a79c8673604b35200b00000000021018253038454b58616c7b8a9fb4cadff4f3dec9b5a49c897e74665e4f4b3e32281a0a000000000000000b20354b6074899eb3c8dedad5c4b49f8b78634d3f2f1909000000000000000000000000000000000000000000000000000000000000000000000000000001142637444b5d656b6b655d4e41311e0b0000000000000011213343505a6267656054493c2c1f0e00000000000000000000000002152738454b59626360564c402f20100000000000000000070d19202223201d14090000000000000000000000000000000000000000000000000000000000000c22374c617787999fa19984786a6259585655585b636d7f8d9fb5c5b39d8874604b35200b00000000071a2d3d556a7f95a9babaa99a846f614f43362e2a263035404c5861748398a0b2c2b4a295806a5c4a362513000000000000000010253a4f657a8fa4c9c5a28d78634d38230e0000000000000000000010253b50657a90a5babca6917c67513c27120000000000071b2d3e4a5b636f75756e615846331f0a000000000000000a1929394b6075889eb3c7b29c87725d36251300000000091f34495e74899eb3c0ab95806b56402b1600000a1a2c3c494d585a5854504c4753697e93a8c8bbaa8e79644f39240f0500000000000000000004172a3a4b6075869aa2b0b5c1bab6b5b5b7b9bab8b8b8babdc2b5b1a49c897a645544311d080000000412202e36434a56606a77818c9fabbccfe3f7f1dbc6b19c86766960554d40372e1d150a00000000000000000e24394e63798ea7b8ccc8c5c7cabaa999836e5d4b3726140100000000000000000000000000000000000000000000000000000000000000000000000000081d314455606e7a80807b68604e3a2511000000000000081c2e3f50616a787c7b73635a493d2c1c0c0000000000000000000000091d314556606e777974665e4c3e2d1b070000000000010f1a212b343738353126191406000000000000000000000000000000000000000000000000000000000b1f3447596277838b8c837462594c473b41403d4a4e616c8196a6b8b8a68f7a654f3a2510000000000c21364a5b72879cb1c7b49f8b79634e4232221b15141c202f3a475660738298a4b5c0b49f8c7a645443301c0a000000000000000d23384d62788dabbcbaa5907a65503b2510000000000000000000000e23384d63788da2c5bea9947e69543f291400000000000010202d3d4a4e546060554c463a2917040000000000010e1a28374657677c91a7b8c4ac97826c57422d17000000000a1f34495f74899eb4c0ab95806b56402b160002152738495a636d706d696561595a6d8297adc2b49f8a75604b362220190f0d070000000000000a1f3347586b8096a4b3c0b3afa5a19fa0a1a3a5a6a7a8a8a7a6a49c938679645c4a3727150100000012222f3e4b546067757f89969faabbc9d9e4eff3dec9b5a4988274625a4c3f321c130800000000000000000014293e53697e93a8c5c0b4afb2b7c3b3a1907b655544311d0c000000000000000000000000000000000000000000000000000000000000000000000000000b20354b6073828f95958f7d68523d28130000000000000e23374b5d6a7f8b91908678635b493a291704000000000000000000000b20364b6074838c8e887c665c4a36220d00000000000f1f2d363b484d4e4b44373224140300000000000000000001080b08010000000000000000000000000004182a3b4859626e76776e6056483b342a2c2b2d36424b6176889eb3c4aa957f6a55402a15000000000e24394e63798ea4b6c3ac97816c5b4935241407000108121c2a3845556075869ca7b8bbaa9b8572604a382715020000000000000b20364b60758a9fb5bda7927d68523d2813000000000000000000000b21364b60768ba7b8c1ab96816c56412c1701000000000002101f2d3636434b4b443733291b0b000000000009141d2b3845556175879db2c5b8a6907b66503b2611000000000a1f344a5f74899fb4c0aa95806b55402b1600091d31455663788385827e7b77736f71869bb1c6b19b867156453c37342b24211a0f01000000000c21374c61778a9fb4c1b3a29a908b8a8a8c8e909192929392908c867e74635b4a3d2d1909000000091c2f404c5c64727d87949ea7b4bbc8c5c9d2dfeae2d2c2b2a0988578655d4f43302518080000000000000006192c3c586e8398adc3b4a29a9da5b7bfb19c8673604b3a29170400000000000000000000000000000000000000000000000000000000000000000000000012283d52677d92a0aaab9b85705b38281603000000000010253a4f657a8f9faaa49c8879635846331f1000000000000000000000142a3f54697f94a0a69d8c7a644e39240f00000000071a2d3d4a4e59626360554f4232221100000000000000070b151d201d150b080100000000000000000000000c1d2b3b484d586162594b45382b302f2c2823213346576c8297acc1ae99836e59442f190000000014293e54697e93a9c2b6a58f7a644f3d2c1a0600000000000c1a283745576278899eb3c0b5a3927d675645311d08000000000000081d31445573889eb3bfaa947f6a553f2a1500000000000000000000091e32455773899eb3c3ae99836e59442e1900000000000000010f1a212630353531261f170b0000000003101926313c495660738298a5b7c1b39e8874604b36200b000000000a1f354a5f748a9fb4c0aa95806b55402b16000b20364b607486989a9894908c8884808b9fb4c2ad97826d5456514d483b39362d1f0f0000000013283e53687e93a9bab5a39a847b76757577797b7b7c7d7e7d7b7771686055493d2d1f0f000000000f23384c5e667a85929da5b3b9c5b9b4b0b5c1d2d8cec9c8beb2a39b897b69614a43362513000000000000000c2035495a73889db3c5af9a84879db2c0b5a4937e685847331f0f000000000000000000000000000000000000000000000000000000000000000000000000152a3f556a7f94aabeb39e88735645321e090000000000152a40556a7f95a8b6b5a69d8776614c3e2d1b07000000000000000005182b3b5b71869bb0b7aa97816c57422c17020000000c21364a5b637177787469604f402f1c090000000008131c202731353127201d150900000000000000000000000d1d2b343a464c4d483b4043454544413d38352c3951667c91a6bbb29c87725d38281603000001142637596e8398aec3b29d87725d4b371f0e000000000000000a192839495a677c91a2b3c1b29d8774604b362513000000000000021527375c71869bb1c1ac97826c57422d1702000000000000000000031628395c71869cb1c5b09b86705b3828150200000000000000000708141c20201d140904000000000b171e2d37444b5a62748298a0b2c3b5a3937e685645311d09000000000a20354a5f758a9fb4c0aa95806b55402b160010253b50657a90a4afada9a5a69d9a969faabbbfaa957f726f6b666259594e4a3d2d1e0e000004192e44596e8399aec7b09b8572656158606264656667686968666259534b44372c1f0f010000000011263b50667c8c9ba3b2b7c3bcb4a89e9ba3b5c9c7bab4b3b8c1b5a79e8c7f6d605443301c070000000000000e23384d63788da6b7c6a9947f7d91a2b4c2b39e8976614c3d2c1a06000000000000000000000000000000000000000000000000000000000000000000000013283e53687d93a8bdb8a78b76604b36210b00000000000e24394e63798a9ca4b6b6a598826d5c4a36220b00000000000000000b2034485974899eb4c8ad98836d58432e18030000011426374e6379868c8d897e695e4c38230f000000081825303537444b4437353127190900000000000000000000000d18202b3436434b5055595a5b5957524d493c394e64798ea3b9b49e89745645321e090000081d31445572879cb1c1ac97826c573f2e1b0000000000000000000a1b2b3c4d5f6f849aaabbb7a5927d685443301c07000000000000192f44596e8499aec3af99846f5a442f1a00000000000000000000001a2f445a6f8499afc4b39d88735645321d090000000000000000000001080b0b08010000000008131c29333e4a556069788598a0b2bfb8a79b8573604b3827150200000000081c304354758aaabbbfaa95806a55402b150012273c51677c91a6bfc2bec4b8b3afabb4bbc8c3af9d958984807c77736e645c4a3c2b190500081d32475d72879cb2bea9937e69544c464b4c4e505152535352514c483b363127190e0000000000001a2f455a6f849aaab5c1c0b3ab9f9789859bb0c5baa99f9ea6b5c1b8aa9f948272604a35200b00000000000013283d52687d92a7c4baa88f7a70849aaabbb8a796816c5b49362112000000000000000000000000000000000000000000000000000000000000000000000011263c51667b91a6bbc5a28d78634d38230e00000000000c21364a5b647a869ca6b7b2a08e7a644f39291703000000000000000d22374d62778ca8b9c0ab96806b56412b16010000081d31445570859ba3a79e907b66503b2611000000132536434a55556055554b44372715010000000000000000000c1926313b484d5460656a6e70706e6c67625a544c4d62778ca2b7b9a88b76604b36210b00000b20354b60758a9fb4bea9937e69543e2914000000000000000000000e1e30414e63798b9fb4c3b19c8673604a35200b000000000002172c42576c8197acc1b19c87715c39291703000001080b0d101215171a2d42576d8297acc2b59f8a75604b36200b000000000000000000000000000000000000031018253039464c5c64737e8a9ba3b2beb8a99e8978635443301a0a00000000000b20354b60758aa0b5bfaa95806a55402b15000e23384e63788da1abafb3b8c5c0c4c0c9ced8ccbcafa79e9a95918c88837a645a4835200b00081e33485d73889db2bda8937d685343333537393b3c404c505b5a524d41331d150900000000000000192e43596e8398aebcb5b1a29a8c82777f94a9beb49f8b889ba3b2bebbb4a0917c66513c2611000000000005182a3b586d8297adc2b49f897564798c9fb4c5b49f8b79634e402f1a0a000000000000000000000000000000000000000000000000000000000000000000000f243a4f64798fa4b9baa58f7a65503a25100000000000071a2d3d4a5c6477889db2bead97826d5746331e0a0000000000000010253a50657a8fa5c6bda8927d68533d28130000000b20354b60758a9fb4b9a9937e69543e29140000071c304354606a7275736a605544311d0800000000000000000e1c2a37444b59626b747b8083858584817d787169615863788da2b8c6a18c76614c37210c00000c22374c61778caabbbaa5907a65503b25100000000000000000000000122135495b6c8197acc0b6a4907b6550392816030000000000152a3f556a7f94aabfb39e89745746331e131618151d202225282a2d2f2a40556a7f95aabfbcab8d78634d38230e00000000000000000000000000000000000b171e2d36434a57616b7a85939ea8b5c1b5a79e8b7b655a493626140000000000000b20364b60758ba0b5bfaa95806a55402b15000c2135495b6e8391959a9ea7a6abb1b5c1d2e7dacfc5b8b3afaba6a69d998a78624d38220d00061c31465b71869bb0c5af9a8570614b4639383937444b5e66716f675f5144331e0e0000000000000011263b50667b909faba49c9084796d697f94a9beb39e89788598a0b4bcbea8937e68533e291300000000000b1f34485972879cb2c4af9a846f5c6c8197a7b8bbaa9a846f5e4c382715020000000000000000000000000000000000000000000000000000000000000000000d22384d62778da2c5bca7927d67523d28120000000000000f1f2d3d4a59657b90a3b5b49f8a76614c36210c0000000000000013283e53687d93a8bdc7a58f7a65503a25100000000e23384d63788daabbc9a6917c67513c271200000b20354a60727f878a887f73604b35200b000000000000000e1e2b3a475560697780889095989a9a9996928d867f766a64798ea3b9b6a18c77614c37220c00000e23394e63788ea3c8b8a38d78634e38230e0000000000000000000000061a2c3d4e63798ea2b4c2ad98826d5745321e09000000000013283d52687d92a7bdb9a88b76614c3626282b2e273135383a3d3f42443a4753687d92a8bdc9a5907a65503b251000000000000000000000000000000002101b29333e4a54606776818c9ba3b4b9bbb4a49c897b655d4b3c2c18080000000000000b21364b60768ba0b5bfaa95806a55402b1500061a2c3d4b60737c8084898d91959ba3b5c9d4c9bcb5bcc9c3c0c4b7b3a895806b55402b160001162c41566b8196abbfb4a2947f6c61574f4e4e5155606a7b86847c6b62513c2c19060000000000000f23384c5e6a7f8d9792867b6f635b6a7f94a9bfb39e88737582949fabb39f8e79644e39240f00000000000d22374c62778ca5b6c7aa947f6a556176899eb3c2b3a1907c665645311d0c0000000000000000000000000000000000000000000000000000000000000000000b20364b60758ba7b9bfa9947f6a543f2a15000000000000010f1f2d3a4c5e71859bb0baa9907b66503b261100000000000001162b41566b8096abc0baa98c77624d37220d00000011263b50667b90a5c8bcab8e79634e39240e000011273c51667c919da59d95806a55402b150000000000000c1c2b3c485861737e89959da6aaaeafb0aeaca7a39b94897f757c91a6bbc6a18b76614c36210c00000f24394f64798ea4b9b7a28d78624d38230d0000000000000000000000000f21364a5b70859ab0c6b49f8a75604b36210b000000000010263b50657b90a5bac6a38e78634e393b3e404337444b4d4f5255575a5c5861667b90a5bbbda7927d68523d281300000000000000000000000000000714202e39464b5c64727d88969faab5c1b6aa9f958678655d4b3f2e1e0e000000000000000c21364b61768ba0b6bfaa957f6a55402a1500000f1d31445560666b6f73787c80859bb1c6c4b7ab9faba9aeb2b7c3bfac97826c57422d1700000e23394e63798ea0b2c0ae9d9481756a656363666b747f8b9b9a91806b5a4935200c000000000000091c2f4050616a7a817d73665e4e556a7f94aabfb39d8873606e7f8c9b9d95826d5c4a36210d000000000012273c52677c91a7c3baa98f7a654f58697e93a4b5bfb29c8774604b3b2a18040000000000000000000000000000000000000000000000000000000000000000091d32455674899eb3c1ac96816c57412c1702000000000000010f1c2f40546a7f94a9c7aa95806a55402b1500000000000000132536596e8399aec3b49f8974604a35200b00000014293e53697e93a8beb49f8a76604b36210b0000162b40556b8095aab7af9a846f5a452f1a00000000000818293a485a627685949ea8b2b7c4c3c5c5c3c1c2b5b1a79e94848196abc1b9a88b75604b36200b00000f24394f64798ea4b9b7a28c77624d37220d000000000000000000000000071a2d3d52677c91a8b9baa9917c66513c271100000000000e23394e63788ea3c6bba5907b66504e505355585b55606265676a6c6f727477797f93a9bebfaa957f6a55402a1500000000000000000000000000081625323f4b57616c7a85929da6b4bbbcb4a49c8c8074625a4b3f2e211000000000000000000c21364c61768ba1b6bfaa957f6a55402a15000001142637444b51565a5a62676b8095abc0b7a69d8c9094989da5a5a8a1927d67523d271200000c2136495b6e8398a7b8bbae9f97887f7a78797b8187949fa9af9f8b78634d38230e0000000000000011223343505d656c6860554c40556a7f95aabfb29d88735d616a7b86888073604b3e2d1a07000000000417293a576c8196acc1b49f8a75604b4b6074869cb1bfb6a4947f695947341f100000000000000000000000000000000000000000000000000000000000000000021528385c72879cb1c3ae99836e59442e1900000000000000000011263b50657b90a5baad98826d58432d18030000000000071c30435471869cb1c6b19c86715443301c07000002172c42576c8197acc1b29d87725645321e090003192e43586e8398adc3ad98836e58432e19000000000013253646586278869ba3b4b9c6c4b7b3b0afb1b4bcc9c5b8b3a29a969eb0c9b49e89745544311d0800000e24394e63798ea3b8b7a28c77624d37220d000000000000000000000000000f21364b6075899eb4c7ad97826d583b2b1805000000000c21364c61768ba8b9bda8937d68606366686b6d707275777a7d7f828487898c8e939daec1c2ac97826d57422d1802000000000000000000000008162633434f5d6475818c9aa2b3b7c0b3ab9f96867a6b6056493c2e21100300000000000000000c21374c61768ca1b6bfaa957f6a55402a1500000009192631353c403c484d546f859aafc4b29d88767a7f83878c9093908372604a35200b0000061a2c3d4c6277899ea7b6bdb1a69d958f8d8e91969da5b4bab4a5917b66513c261100000000000000031525333f4b4f57524b443740556a7f95aabfb29d88725d4f5d6571736a60554431200f00000000000a1f33465871869bb1c5af9a857056454455657b90a1b3c3b39e8977614c3e2d1b0700000000000000000000000000000000000000000000000000000000000000001b30455a70859aafc5b09b86715b3727150200000000000000000f24394e64798ea3b9ae99846e59442f190400000000000b20354a6074899fb4c3ae99836e5936251300000006192b3c5a70859aafc4ae99846f59382816020005182b3b5b71869bb0bfaa95806a55402b1500000000071c3043546176879ca4b4c1bbb4aba69d9a9a9c9fabb3b7c4c0b4afabb0bdc7b29c87725d3727150200000d22374d62778ca2c4b8a38e79634e39240e00000000000000000000000000091e3245566e8399aec3b29d8772594834200b000000000a1e33465774899eb4c0aa95807376787b7d808385888a8d8f929497999c9fa8a4a9aebbcbc4af99846f5a442f1a000000000000000000000005162634445061697a87979fabb4c0b5b1a29a8c8175645c4b45382c1e10020000000000000000000c22374c61778ca1b6bfaa947f6a553f2a150000000009141d20262b2b354a6074899eb3c4ae99846f65696e72777b7e7b6e605443301c070000000f1f344759647a899ca4b4bab7b2aaa4a3a3a6abb2b7bab4a39b8775614b36210c00000000000000000715212e373a423d35312640556a8095aabfb29d87725d3f4c505c5e554b443726140100000000000c21364c61768b9fb4c7aa95806a5538374c5d6e8399a9bab9a897826d5c4a3622120000000000000000000000000000000000000000000000000000000000000003192e43586e8398adc3b39d88735544311d08000000000000000114263650657a90a5baae98836e59432e190400000000000d22384d62778da9bac0ab96806b56412b160000000b2035485a73899eb3c0ab95806b56402b1600000b2034485974899eb3c9a7917c67523c271200000004182a3b4a60728399a5b6c2b6aa9f968e888585868b939da6b3c0c8c4c1c4cdc5b09a85705b45301b0000000b21364b60768ba6b7baa5907b65503b2610000000000000000000000000000216283853697e93a8c8b7a58c77624d37220d00000000031729395c72879cb1c7b39e89888b8e909395989a9d9faaa4a7aaacafb1b4bac6bec1cbdcc6b19c87715c3a291704000000000000000000001323344451626b7f8c9da5b4bcb8b3a49c9084796b60564b3e32281a0e00000000000000000000000d22374c62778ca1b7bfaa947f6a553f2a15000000000001080b111623384e63788da7b9c0aa95806b55545958616669655d4a433625130000000005182a3b4a5c647a86969fa9b1b5bcc9b8b8bbc3b6b2a99f958577625746321e0a00000000000000000003111c23252c28201d2a3f556a7f94aabab29c87725d47383b464840353126190900000000000011263b51667b90abbcbaa98f7a65503a2f3f4d62788b9fb4c4b49f8c7a644e41301a0a00000000000000000000000000000000000000000000000000000000000001172c41566c8196abc1b49f8a75604b36200b00000000000000081c3043546a7f94a9c8ab96806b56412b1601000000000010253b50657a90a5c7bda8937d68533e28130000000d23384d62788da7b8c7a7927c67523d271200000d22374d62778ca7b9bcab8e79644e39240f0000000b1f344759697f94a1b3c2b5a49c8b817973707071767e889aa2b3c0d0d6d8d7c2ad97826d58422d18030000091e32455673889db3bea8937e69533e291400000000000000000000000000000f24394e64798eaabbc3a6917c67513c271200000000001a30455a6f859aafc4b8a79e9ea7a3a5a8aaadb0b2b4bbc8bcbfc1c4c6c3c1bebcbec1cbc9b49e89745847331f0a0000000000000000000d1d314151626b80949faab6bcb4a69e92867b6f645c4b45382e1d150a0000000000000000000000000d22374d62778ca2b7bfaa947f6a553f2a1500000000000000000012273d52677d92a7c5c6a6917c67513f3a474c5053504b3f3025180800000000000d1d2d3e4a5c6475818a959b9faba8aaaaa8a6a59c958a7f74625948392916030000000000000000000000080e1017130b11263b51667b909fa99f97836e59432e2631332b201d140900000000000003162838566b8095abc9b49f8a75604b362135495a6b8095a6b7bcab9a84705f4d38281603000000000000000000000000000000000000000000000000000000000000152a3f546a7f94a9bfbcab8d77624d38220d000000000000000b20354b6073869cb1bbaa927d67523d281200000000000013293e53687e93a8bdc8a5907a65503b251000000011273c51667c91a6c5baa98e79634e39240e000010263b50657b90a5c5b59f8b76604b36210b0000001325364c6177899eb4bfb5a49c86796c635b5b5a58616876849aa2b4c4d4e7d4bfaa947f6a553f2a15000000021628385a70859aafc2ac97826d573c2b1905000000000000000000000000000b20364b60758a9fb4bfaa947f6a553f2a150000000003182d43586d8298adc2c5b8b3b3b8c5bbbdc0c2c5c5c2c0bdbbc5b8b3b1aeaba9a6a9aebbcdb9a88c76614c37210c000000000000000005182a3b4d5f6b80959eb4bbb8ab9f97887d73665e4e4a3d32281a1002030a0c0b0801000000000000000d22384d62778da2b7bfaa947f6a553f2a15000000000000000001142637566c8196abc1b9a88d78634d382a33373b3e3b372f1c13080000000000000010202d3e4a57606b777f868b9093949493918d8780776a6056483b2b1b0b0000000000000000000000000000000200000f24384c5e6c818a8d8a8176614c3621101c1e150b080100000000000000091e32455670859bb0c5b09a85705645321e2b3c4b6175889db2c0b4a2917c675645321e0900000000000000000000000000000000000000000000000000000000000013283d52687d92a7bdc9a48f7a654f3a25100000000000000012283d52677d92a4b6b49f8b77614c37210c000000000001162c41566b8196abc0bbaa8d77624d38220d000003162939566b8096abc0b49f8a75604b35200b000014293f54697e94a9beb29d87725645321e090000071c3043546a8095a8b9b9a89c8676635b4e4a3d3a474c586173849aa6b7cbdfd8c8a7917c67523c271200000000172c41576c8196acc1b19c87725a4834200b00000000000000000000000000091d31455672879cb1c2ad98836d58432e180300000000162b40556b8095aac0d6ccc8c6c1bfbcc8bbb4b2b0adaaa8a5a3a79e9b99969491939caec1c6a38e79644e39240f00000000000000000b1f344759677d929eb0bcb7a79e8c81766860544c40362d1e160a070b161e21201d14090400000000000e23384d63788da2b8bfa9947f6a543f2a150000000000000000081d31445570859bb0c5b49e8974604a35201f22262925231c110000000000000000000210202d39454b59616a71777b7e7f7f7e7b78726b62594b45382b1d0d00000000000000000000000000000000000000091d2f4051626c7678756c615846331f0a070900000000000000000000000b21364b60768a9fb4c8aa95806b553828161e324657677d92a2b4c0b29d8775604b36210b00000000000000000000000000000000000000000000000000000000000011263b50667b90a5bbbca7917c67523c271200000000000000152a3f546a7f94a6b2aa99836e5847331f0a000000000001142637596e8499aec3b49f8a75604a35200b00000a1e32465770859bb0c5b09b85705544311d080004172a3a586d8398adc2ae99846f593828160300000b20354a6073889db2c6b39e89786358493d362d29333a46556176889db3c5d6cebbaa8e79634e39240e0000000012273c52677c91a7c2b6a48d77624d38221000000000000000000000000000021527385a6f859aafc4b09a85705b45301b060000000013293e53687e93a8bdd2c1b5b1acaaa7a4aa9f9d9a989593908e8b898683817e7c7e93a9bebba6917b66513c261100000000000000031628394c6277899eb3bcb7a59d897b6c61584b43362f211a0f03101b222932363531261f170c000000000e23384e63788da3b8bfa9947f6a543f2a1500000000000000000b20354b6075899fb4c5b09a85705443301c0a0c1114100e08000000000000000000000002101b28323a474c55596166696a6a6966625a554c483b31271a0d000000000000000000000000000000000000000000122234445158616360564c463a2917040000000000000000000000000010253a50657a8fa9babbaa907b65503b26101628394d5f70859babbcb7a5927d67523d28120000000000000000000000000000000000000000000000000000000000000f24394e64798ea3c9bea9947e69543f2914000000000000000c21374c617688989d9c8b79644e3a2a17040000000000081d31445572879cb1c7b39e89735443301c0700000c21364b61768a9fb4c9ab96816c5637271501000a1f33475872879cb1c0aa95806b55402b160000000f24394f64798ea6b7baa9947f6a5a493a2c211a171f29374758687d92a7b9cccab49f8a75604b36200b000000000d22374d62778ca4b5c2a8937e68533e2e1b0700000000000000000000000000192e43586e8398adc3b19c87715c47321c070000000011263c51667b91a6bbc9b5a39b9794928f8d8a888583807d7b787673716e6c6967798ea3c6bea8937e69533e291400000000000000091e3246576c8196a7b9b8a79d8778655e4c463a30261811070010202d3639464b4b4437332a1c0c0000000e23394e63788ea3b8bfa9947f6a543f2a1500000000000000000e24394e63798ea9bac1ac96816c5736251300000000000000000000000000000000000000000a161e2a34373a474c5053555553514d483c37342b1d150a00000000000000000000000000000000000000000000041626343a464c4d4b453833291c0c0000000000000000000000000001152737556a7f95aac7b49f8a76604b36210b0b1b30414f647a8c9fb4b4a2917b66513c26110000000000000000000000000000000000000000000000000000000000000d22374c62778cabbcc0ab96816b56412c16010000000000000a1f33475862788288877c665c4a361c0c0000000000000b20354b60758a9fb4c9b39e89745847331f0a000114263751667b91aabbbcab917c67523c271200000c21374c61778b9fb5c6a6917c67513c271200000014293e54697e93a9c4b49f8a76614c3c2c1c0f07040c19293a4b6075899eb3c9c7b19c87725645311d09000000000b2034485971869cb1c6b09b85715c4b37220e00000000000000000000000003192e43586e8398adc3b39d88735e48331e09000000000f24394f64798ea4c8c6b19b85817f7c7a777572706d6b68666361575c59565461768ba8b9c0ab95806b56402b16010000000000000c21364b61768a9fb4c3b39e8979635a4c4033291c14080000071b2d3e4a4f576160554c473a2a190900000e24394e63798ea3b8bea9947f69543f2a14000000000000000013283d53687d92a8c7c8a8927d68533d2813000000000000000000000000000000000000000000030c181f222a34373b3e3f3f3e3c38352b2220180d0200000000000000000000000000000000000000000000000008161b293336383631271f170c0000000000000000000000000000081d3144556f849aafc4b09b85705745321e09001322364a5c6d8297a39f978472604a35200b0000000000000000000000000000000000000000000000000000000000000b20354b60758a9fb4c3ae98836e59432e190000000000000004172a3a485a626d7272665e4d3d2d1a000000000000000d23384d62788da9baccb9a78c77614c37221100081d3144556c8297acc8b59f8b77614c37220c000011273c51667c91abbcb9a88d78634d38230e000002172c42576c8197acc1af9a85705846331e0e000000000c1d3145566e8398adc3c3ae99836e59382715020000000005192b3b556b8095aac2b5a38f7a644f3c2b1905000000000000000000000003182e43586d8398adc2b39e89735e49341e09000000000d22374c62778caabbbea9947f6c6a67656260555b585553504e4b46394441465774899eb4c2ad98836d58432e180000000000000012273c52677c91a8bab7a5937e685b493c2f1f170c010000000d22364a5c647176756d61584737271501000f24394e64798ea3b9bea9947f69543f2a140000000000000002152838576c8297acc1bbaa8e79644f39240f0000000000000000000000000000000000000000000000040a0c181f2226292a2a29262320190e0b05000000000000000000000000000000000000000000000000000000000b171f2123201d150a040000000000000000000000000000000b20354b6075899eb4c7ab95806b563928160300071b2d3e4c6176858d8a8275615443301c07000000000000000000000000000000000000000000000000000000000000081d31445573889eb3c5b09b85705b36261401000000000000000c1c2b3c484d585d5c514d40301f0f0000000000000011263b50667b90a5c7d6c5a7917c67523f2e1c0d0b20354b6074889eb3c6b19b86715947341f0b00061a2c3d576c8196acc9b49e8974604a35200b0000041a2f44596f8499aec0ab96816b563a2917000000000002152738556a8095aabfc0aa95806b55402b160000000000000f24394f64798ea4b5c1ad98826d5a48352011000000000000000000000003182e43586d8398adc2b39e89745e49341f09000000000b20354a60758a9fb4c1ab96816c56524f4d4b443743403e3b393632282e29395c71879cb1c5b09a85705b37261401000000000002172c41576c8196acc6b29d8774604b3d2c1e110400000000001325364f647a868b8a8276615544311d08000f24394f64798ea4b9bea9947f69543f2a1400000000000000091d32455671869bb0c6b49f8a75604b36200b0000000000000000000000000000000000000000000000000000040a0c1114151514110d0b060000000000000000000000000000000000000000000000000000000000000000040a0c0e0b090200000000000000000000000000000000000d22384d62778da2b4baa9907b66503b2611000000101f334658617277766d61574636251300000000000000000000000000000000000000000000000000000000000000011426375c71869cb1c6b29d88725443301c0800000000000000000e1e2b35384348473c39302212010000000000000014293e53697e93a8bed3c4af99846f5d4b3a2b1d1a2e3f51667c91a7b8c1ac97816c573b2a1805000c2136495b72879cb2c5b09a85705443301c070000051a2f455a6f849aafbea9947f69543f2a1400000000000014293e54697e93a9bec9a7927c67523d27120000000000000d22364a5c71869cb1c6b49f8b78624d3f2e19090000000000000000000000132536596f8499aec4b39e88735e49331e0900000000071c30435472889db2c3ae99846e59443a383531262e2b282623211e161a2f455a6f849aafc4b29d88725544311d080000000000051a2f445a6f8499afc1ac97826c5544311f0f000000000000071c3043546f849aa49f988674604b35200b000f243a4f64798fa4b9bea9947f69543f2a14000000000000000b20364b60758a9fb4c6b19c86715645321d09000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b20354a607285979faa9f8a76614b36210c0000000417293a4654606261574b463928180800000000000000000000000000000000000000000000000000000000000000001a2f455a6f849aafc4b49f8a75604b35200b0000000000000000000e1920222d333227241d12040000000000000001172c41566c8196abc1d6c7b3a18f7b6559483b3229384b5d6f849aafc5c5af9a85705947341f0c001325364e63798ea5b6c7ab95806b56362513000000041a2f44596f8499aebfaa95806a55382815020000000001152737556a7f95aabfbcab8e79644e39240f000000000000071b2d3e54697e93a8b9baa998836e5d4b37261401000000000000000000071c30435472879cb1c7b19c87725c47321d0700000000001325365b70859bb0c5b19b86715c392922201d14181613110e0c0903182d42576d8297acc2b49f8a75604b35200b0000000000051b30455a70859aafbfaa947f6a55372715010000000000000b20354a6074899eb4b4a48e79634e39240e000f253a4f647a8fa4b9bea9947e69543f2914000000000000000b21364b60768a9fb3b8ad98826d5838281502000000000000000000000000000000000000000000070a050000000000000000000000000005080704000000000000000000000000000000000000060c0e0f0c0a040000000000000000000000000000040a0c0f0e0b0700000000000000071c3043546175828a8e8b7e695746321e0a000000000b1b2936434a4d4b463932281b0b000000000000000000000000000000000000000000000000000000000000000003182d43586d8298adc2bbaa8c77624c37220d00000000000000000000050b0d181d1d110f0a000000000000000000011527375a6f8499afc4d9d0bfb29d877762594b45394656657a8fa2b3c7cab49f8b77624c3a2917071c3043546a8095aac3baa9907b66513b261100000002172d42576c8297acc1ad98836e5645321d0c000000000b1d3144556e8398aec3b59f8b76604b36210b000000000000001021364c6176899eb4c6b2a08f7b655544311d110000000000000000000b20354a6074899fb4c5b09b85705b46301b060000000000192e43596e8398aec3b39e89735746321e0b08010000000000000000152b40556a8095aabfbbaa8d77624d38220d0000000000051a2f445a6f8499afc0aa95806b55372614010000000000010f22384d62778da8b9b59f8b76614c36210c0010253a4f657a8fa4babea9947e69543f291400000000000000091e3245576e83969ea69e937e69543e291400000000000000000000000000000000000000090f111d201a0c0a0300000000000002090b131a1d1c19120b0902000000000000000000000000050e19212325221f180c0200000000050601000000000b171f212523201c13080000000000001325364657616d76797669604f3929160300000000000b18253035383633291e160b00000000000000000000000000000000000000000000000000000000000000000001162b41566b8096abc0c8a48f79644f3a240f00000000000000000000000000030807000000000000000000000000081d31445572879cb2c7dcdfcab6a59b857869605656576175869cb1c0d0cebbaa947f6a5847331f1620354a6073879cb2c7b49f8a76614b36210c0000000014293e53697e93a8c1b39e8975604b3a29190c03060e1b2a3b4b6074889eb3c7b29d87725745321e09000000000000000a1f3346586b8096a8babeb19b8573604b3f2e1e0e00000000000000000e23384d63788da9bac2ad98826d58432d18030000000001172c41566c8196abc1b8a78b76614b36210c0000000000000000000013283d53687d92a8bdc8a48f7a654f3a2510000000000002182d42576d8297acc2ad98836e5544311d0d0200000007111f304152677d92a7c6b29c87725846331f0a0010253a50657a8fa5babea9947e69543f291400000000000000031628394b617580888b898174604b36210b000000000000000000000000000000000004121d2426323530211e170b000000000a151d20292f32322e28201d150a000000000000000000000e19202c35383a37342a1d150a090b151b1b160c0a04151b2933363a393530251810020000000008182939464b58616361574f42321b0b0000000000000008131c2022211e170b03000000000000000000000000000000000000000000000000000000000000000000000014293f54697e94a9bebba6917c66513c2711000000000000000000000000000000010708030000000000000000000b20354b60758a9fb4cacfcac8c3b5a39b897e756e6b6d768399a4b5c9dbd8c8b39e8976614c423228304150667b90a5b6c7af9a846f5746321e0a000000000e23384e63788da3b5b9a7927d68584637291e1619202c394859687d92a6b8c4ae99846f5939281603000000000000000417293a4c62778a9fb4c4b5a395806a5d4b3c2b1d0d00000000000004182a3a53697e93a8c7c9aa947f6a553f2a1500000000000014293f54697e94a9bec5a38e78634e39230e0000000000000000000011263b50667b90a5bbbca7927c67523d271200000000000014293e54697e93a9c4b29d8874604b3a2a1d151212131c202e3d4d5f70859bb0c4ac97826d573a2917040010253b50657a90a5babea9937e69543e291400000000000000000a1e324657616b7376746c605645321e09000000000000000000000000000000000212222f383b474a453633291b0b00000e1a2731363e454747443d3631271a1002000000000000000e1e2b353c494d4f4c473a32281a1e212a30302b211f1725333a464c4f4e4a43362d201000000000000b1b29333a464c4e4b463932241400000000000000000000070b0d0c0a030000000000000000000000000000000000000000000000000000000000000000000000000012273d52677c92a7c5c8a8937e69533e2914000000000000000000000000030a0c161d1e190e0c060000000000000e23384d63788daabbc9bcb5b3b7c1b5a79e93898380828999a1b3c2c9c6bcbfb8a797826d604b45383e4d5f70859ab0c3baa9937e685339291603000000000c2135495b71869bb1c4b39d88766155473a32282b353c49576277889db3c4c0ab96806b56412b160000000000000000000c203448596a8095a6b7c1b49f8c7b655a483b2b1d100100000000081f3447596f8499afc4bcab907b66503b261100000000000012273c52677c91a7bcbba5907b66503b2611000000000000000000000e23394e63788ea3c6bea9947f69543f2a140000000000000f243a4f647a8fa6b7b7a6917c6758473b312727272530353f4b5b677c91a2b4b7a6917c66513c2611000010263b50657b90a5bec1a9937e69543e2914000000000000000003162839464b56576060544b45382816030000000000000000000000000000000010202f404c515c5f5a4c4639291703111e2b38454b535a5d5c59524b45382d201103000000000009192b3c484d5b636461594b45382832363f45464037332a3343505861646360544a3e2d1d0c00000000000b171e293336393632281b1406000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010253b50657a90a7b4b4aa96806b56412b1601000000000000000000000b161e212b32332e2320190e000000000011263b51667b90a6c8bcab9f9da6b6c2b8b3a79e9995989ea7b3bfc1b5b0a7acb9b1a0937e6b605652515c677d92a2b4c9b49f8a76614c37210c0000000000061a2c3d54697f94a6b8b7a69a847361584b45383c484d5a6275849aa6b7cbbda7927d68523d281300000000000000000005182b3b4b6175889db2bebbaa9e89786259483b2d1c1408010008182b3b4c61778a9fb4c9b49f8b76614c36210c00000000000010253a4f657a8fa4c9bda8937d68533e2813000000000000000000000c21364c61768ba8b9c1ac96816c57412c170200000000000b20354b6074889db3c4b29d887662594b45383d3c36434a4f5d6579899eb3c0b39d8874604b35200b00000e23384d63788da0aeaea3917c67513c27120000000000000000000b1b28323639454b4a433632281a0a00000000000000000000000000000000071b2d3e4c5e6672756f615746331e13212e3c485660686f72716e6760564a3e2e21110000000001142637485a6270787a776c60564539454b555a5b564c473a4250616a767a7873645c4a3b2a18040000000000030c171f2124211e160b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c21364b6175899b9f9f9a8c7b654f3a2510000000000000000000000b1b2932364047484338352c1e0e0000000014293e53697e93a8c6b59f8d889ca4b2bec5b8b3aeabadb3b8c5c1b5a39b919bacbdb59f8d80756c67666c7a8a9eb3c0bead98826d5847331f0a0000000000000e21364c6176889eb3c1b3a29a837668605659595a626b78859aa2b4c4d4c4a48f7a644f3a240f000000000000000000000d1e324657667c90a0b1c2b8a79c867762594a3e30261d151318253648596b8196a9bac7b09a85705846331f0a0000000000000d23384d62788dabbcc0aa95806b55402b16000000000000000000000a1e33465774899eb4c3ae99846e59442f19000000000000081c3043546b8096a9bab7a69b8577686056535251545460646d7b899ea7b8b5a4947e695544311d0800000c2035495a6e82929899938574604b36210b000000000000000000000b161e212832363530251e160a00000000000000000000000000000000000d22364a5c667c878a8475614c36251d313f4b5a62747e848787837d74645c4b3f2e1e0e000000081d3144556278858d8f8b8174604b4557606a70706b6158474e606a808a8f8e867a645947341f0b00000000000000040a0c0e0c090300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1e324657657b868a8a847a655d4b37220e0000000000000000000a1a2939464b565c5d584d493c2c1e0e00000014293f54697e94a8b1b09c86788698a0afb4c0c2c3c0c2c8c8bbb4a39b857c919fb0bcab9f9688817c7c818a9ea8b9c5b2a08e7a644f3a2a17040000000000000a1e334657687e93a3b4c0b3a19a887e75706e6e7178808a9ba3b4c0d1cbb7a68b76614c36210c00000000000000000000031628394c5e6d8297a4b6c5b6a49c8677645c4b43363127282b36435462778a9fb4c7baa9937e69543a2917040000000000000b20364b60758a9fb5c2ad98836d58432e1800000000000000000000031729395c71879cb1c6b19b86715c392816030000000000011426364d62788a9fb4c1b5a39b897d756d696767696d747a828d9ea7b8baa99c8674604b37271501000006192c3c4b60737d83837e74605645321e09000000000000000000000003090c161e21201c1308030000000000000000000000000000000000000f243a4f647a8c9c9f95806b54433031424e5d657885939a9c9c9992867a655d4b3c2b190600000b20354b6073869ba3ab9f97816c575660757f85858076625953687e939fa9a49c8977614c37220c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000031629394b5d657175746f645c4b3f2e1a0a0000000000000000021628384657616b72736e635a493c2c190600000e23384d63798a989c9b93806a7682909aa2a9adb0b3b3b3b0aa9f9685776c8196a3b5bcb5a69e969191969fa8b9c6b9a798836e5c4a361c0c00000000000000031729394b6073859ba5b7bfb3a69d938a858383878c959fa9b5c1d1ddc8b29d88735746331e0a00000000000000000000000b1b2f404b6175869ca8b9c3b6a49c877a6960544b44373d3c495460728399a9bac7b49f8a77614c37220c00000000000000091d32455673889eb3c5b09a85705b37261401000000000000000000001a2f455a6f849aafc4b39e89735746321e09000000000000082034485a6a8095a3b4c2b5a79e9288827e7c7c7f82888f989fabb8bcab9f8b79635645311909000000000e1d31445560686e6e6960564538281602000000000000000000000000000003090b0b07000000000000000000000000000000000000000004192e43596e8398aab29d8873604a37444b60687b889ba3afb2b1aea49c8a7b655a4835200e000010253b50657b90a4b4bcb49f8a7661607485949a9b958777625c71869cb1bab6a7947f69543f291400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1b2e3f4b4f59626869666054453828160300000000000000091e32455661758087888378635b4935210c00000c2135495b63798287857e7260616d7b858e93989b9d9e9d9a958b8175616074859ba3b2beb8b3aba7a6abb4bac6bcab9e8978624d3e2d1b0000000000000000000b1d3144556277879da7b6c2b7b2a99f9a98999c9fabb4bac7d2dfd9c4af9a846f5a39291703000000000000000000000000121e32465763798a9ea9bac2b6a59d8b7f736760555452545a62728196a1b3c7baa997826d5947341f0a00000000000000021528385c71869bb1c6b29d88725544311d0800000000000000000002182d42576d8297acc2b8a78b76614b36210c00000000000005192b3c4b6074859ba4b5c1b8b3a69e9893929194979da6adb5bcb8b39f8d7e685b4a382715000000000001142637444b535959544b4538281a0a00000000000000000000000000000000000000000000000000000000000000000000000000000000051a30455a6f859aafb7a68f7a65504a55606b7e8c9ea6b5b5b2b3b8b6a89e8978624d3c2c19060012283d52677d92a7c2cebbaa8d7863687e93a3afb0a597816c5f74899eb4c9c5ab96816c56412c17000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005182b3b4d5f67777d7f7b73605645321e0a000000000000000b21364b607485959c9d988979634d38230e000006192c3c495b636d72706960544c5e6670797e8286888988857f786c60575661768598a0b2b7c3c1bcbbc1c9c4b7ab9f8d7c665a48352010000000000000000000011426374759647a899ca4b2bec7bab4afaeaeb1b5bcc9c3c0c4cdd6c1ab96816c56412c170000000000000000000000000003162839495b657b8b9faabac3b7a99f94867c746d6968696f7883969fb1bfc1b49f8b78624d3a2a180400000000000000001a2f44596f8499aec4b49f8a75604b35200b00000000000000000000152b40556a8095aabfc5a38e78634e39230e000000000000000d1d3144556277869ba3b4bac4b8b3ada8a7a6a9adb2b7c4beb2a79e917e68604e3d2d1a0a00000000000009192631353d43443e3632281a0a000000000000000000000000000000000000000000000000000000000000000000000000000000000000152a40556a7f95a8b9ae98836e6160647380939faab5ab9f9d9ea7b3b8a799836e5b4935210c0010253a50657b8fa4b5beb49f8a76616d8398adc1c3b19c87715c71869cb1bbb7a7947e69543f291400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b20344859677d8a9294908474604b3827150200000000000014293e53697e93a3b1b2a798826d58432e180300000e1e2c3d494e585c5b544b43404c505b63696d71737473706a625a4b454758617582919da5afb4b9c6bab4afa69d8d7e685e4d3c2b19020000000000000000000009192a3b4a5c64788698a0afb5bcc9c4c3c3c4c8bbb4adabb0bccdbda8937d68533e281300000000000000000000000000000b1b2c3d4b5d677d8c9fa9b8c4bab4a49c9188827e7d7f848c99a1b1bdc5b5a395806b5a49351c0c000000000000000002172d42576c8297acc1bbaa8d77624d38220d0000000000000000000013283d53687d92a8c9baa5907b65503b261000000000000000021527374759627785959fa9b2b7c4c2bebcbcbec2c7bab4ada098897c68604e41311f0f000000000000000009141d20282e2e29201d150a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c21374c61778a9eb4b2a0947f76757a84959eb4ab9f968c888999a1b3b2a18d78634d38230e000b20354b6073869ba3a5a097816c576d8298adbfc1b19b86715c687e939faaa59d8977614c37220c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d22374c62778a9fa8a9a297816c5645311d09000000000003182d43586d8298adc1c5b29d88725d48331d080000000f1f2c35384347463e35302f383d4a4e54585b5e5e5e5b554d493c323a4757606e7d87929a9ea8a2a99f9a93887b68604e40301e0e0000000000000000000000000d1d2d3e4a5a6375828f999fabadafb0b0aeacaa9f98969eb0c4c4a48f7a654f3a25100000000000000000000000000000000f1f2f3f4d5f677c8b9ea6b4c0c2b5b1a69d97939294999faab3bfc5b8a79b8574604b3c2b1900000000000000000000152a40556a7f95aabfc8a48f7a654f3a25100000000000000000000011263b50667b90abbcb9a8937d68533e2813000000000000000009192a3b47596274808b959da6a9adb0b1b2b1aeaca99f988f8378665e4e423123130100000000000000000001080b131919140b090200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1f3347586b8196a6b8af9d948b8a8f9aa2b0a99f8d817772748399aebfa9947f6a543f2a1500081c3043546278858e908d82746052677d92a1aeaea395806b56606b808b908f877a645947341f0a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013283e53687d93a8bac0b39e8975604b36200b000000000001172c41566c8196abbcc0b19c87725c47321d07000000010f1a21232e323029201c1c232d36393e4346484948454038352b1e2a39454b5f67747d84898b8d8c8a857e75655d4e42312212000000000000000000000000000010202d3c4957616d7b848c9397999b9b9996918b838096abc9b8a68c77614c37210c00000000000000000000000000000001112130414d5e667b889aa2b4b9c6c4b7b3ada9a7a9aeb4bbc8c3b6a79e8979635645311e0e0000000000000000000013283d53687d92a8bdbca7927c67523d2712000000000000000000000d22374d62778c9faba79e8f7b65503a25100000000000000000000d1d2a3b4756606b7880888f94989b9c9c9c9997928a827a6e625a4c40312414050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004172a3a4c6177889eb3bbafab9f9faaafb4a69e8b7d6c6158657b90a5c5ae99836e59442e190001142636485a6272797b786d60564b607283939999948575614b51626b777b7a74645c4a3a2a1804000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014293f54697e94a9c0c9b8a68c77624d37220d0000000000000f253a4f647a8f9eacaca295806a55402b15000000000000060c0e181d1b140b08090f1a2124292d31333433302a2320190e1b2832414d5660676f7476777675706860564b3f31231304000000000000000000000000000002101e2c39464c5d656f777d8284868684817c776e7f94abb8b39e88735847331f0a0000000000000000000000000000000003122330404c5d657884939ea8b4b9c6c8c2bebdbec4cac8bbb4a59c897a645b49382715000000000000000000000010263b50657b90a5c8bfa9947f6a543f2a15000000000000000000000b203448596a7f8c9090897d675d4b37230e000000000000000000000d1d2a38454b5a626b747a7f838686878684817c766d645c4d483c2f2214060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1f344759667c919fb4babcb5b4b8b3a39b887a675f4c4b60768ba7b8b09b86715b46311c000008182b3c4854606466625a4b45435460737e84847f7561574644515962666460554a3e2e1c0c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f253a4f647a8fa2b4b4ab9e8874604b35200b0000000000000d22374b5d6a80909797918474604b36210b0000000000000000000307060000000000070c0e14181c1e1f1e1b150d0b06000a161e3038454b525a576162616054534b45382f21130500000000000000000000000000000000000e1b29333f4b505962686d6f70706f6c6761657b8d9ea6a899846e593a2a17040000000000000000000000000000000000051222303f4b5a62737e89969ea8afb4bbc8bdbdc3b6b2aa9f968779645c4a3c2c1a0a00000000000000000000000e23394e63788eaabbc0ac97826d57422d180200000000000000000005182b3b50616a777b7a75675f4d3f2e1c0800000000000000000000000d1a27313c484d556065696d707172716f6c6761584f4a3e352b1e12040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004182a3a4c5e6c81959fa9abaca9a79e948578645c4d41455773889eafaa99846f59442f1a0000000e1e2b36434a4f504d493c3236445560686e6f6960574639333b484c504f4b44372e2010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b20354b607384999f9f9a8d7d675443301c08000000000000081b2e3f50626a7b82827c73605645321e0900000000000000000000000000000000000000000003060909090600000000000003131a2731363d39464b4d4c4b43363632281a1103000000000000000000000000000000000000000b171e2e373b484d53585a5b5b5957524c5d677d8890918a7b644f3a250f000000000000000000000000000000000000000412212e3c4854606977818a939a9faaa7a8a8a6a59c958b8075635b4a3e2d1e0e0000000000000000000000000c21364b61768b9facaba296806b56412b1601000000000000000000000d1d3343505962666560564d41312111000000000000000000000000000a151d2b3537444b5054585b5c5d5c5957524c473a362d20190e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1c2f404a6072808b9396969491887f73625a4b3e3039576c81959a998c7b65503b2510000000000e18253035393b38352b1d2737444b535959544b4539291d2b34373b3a35312719100200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081c3043546176838a8a857b675f4d362614010000000000000010203344505e666c6d676055453828160200000000000000000000000000000000000000000000000000000000000000000000000a151d20282933363837353026211e160a0000000000000000000000000000000000000000000003111c232b34373e4244464644413c3f4d5f67757b7c77645d4b37220d000000000000000000000000000000000000000003111d2b36434b59616c767e848a8f929393908d8780786b6157493d2d2010000000000000000000000000000a1e3346576c81939796908475614b36210c0000000000000000000000001525333b484d51504b4538312313030000000000000000000000000000020e19202631353a3f434647474744423d373329221b1005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000121c304354606a787e81817f7c756a6055483c2e20364b60747f85837b655d4b37230e000000000008131c2024262320190e192731353e44443f3632281b0d1820222625201d1509000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011426364758616e757570665e4d41301808000000000000000002152533404c505757524b4437281a0a0000000000000000000000000000000000000000000000000000000000000000000000000002090b12171e212221201c140b090200000000000000000000000000000000000000000000000000080d182022282d2f31312f2c2730404d5660656661594b3f2e1b08000000000000000000000000000000000000000000000d1826303a474c5761686f76797c7d7d7b78726b62594b46392c1f100200000000000000000000000000031729394b60737e82817b73615746331e0a00000000000000000000000007151d2b34373b3b3632281a130500000000000000000000000000000000000609141d20252a2e313132312f2c27211f170c07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000132536434a5a62696b6c6a6660564b44372b1e1d314556606a706e655d4b3f2e1c0800000000000000070b0f110d0b060009151d20292f2f2a211e160a00050b0d110f0b0801000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008182a3a474c55606055504c40302313000000000000000000000715222f383b42423c353126190a000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a0c0d0c0b0801000000000000000000000000000000000000000000000000000000000000050b0d13181a1b1b1a1712223038454b50514c473a2e201000000000000000000000000000000000000000000000000008141c2a3439464c5357616467686866625a564d483b32291b0f010000000000000000000000000000000b1d31445560686c6c666054463929170300000000000000000000000000000d1820222625211e160a00000000000000000000000000000000000000000001080b1014181b1c1d1c1a17120c0a040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081825303c484d53565754514b45383127190e152738454b555a59504b3f2e2111000000000000000000000000000000000001080b13191a140b0903000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1c2a3337444b4b4437382f221305000000000000000000000003111c23262d2d27201d14090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003050606040204121a2832363b3c37342a1c100200000000000000000000000000000000000000000000000000010c181f29333639464b4f525353514d493c37342b1e160b000000000000000000000000000000000001152737444b535756514b4336291b0b00000000000000000000000000000000050b0d11100b0903000000000000000000000000000000000000000000000000000000030607080704020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008131c2b34383e41413f3c3632281d1509000a1a2731364045443a372e21110300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c171f273136363127231c11030000000000000000000000000000090f111718120b0801000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a151d202627221f180c0000000000000000000000000000000000000000000000000000000000040b171e212832363a3d3e3e3b38352b2220190d030000000000000000000000000000000000000009192731353e42413b353026180b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d192022292c2c2a27201d150a010000000a151d202a302e25231c1103000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000409151d20201d15090900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090b10110c0a040000000000000000000000000000000000000000000000000000000000000000030a0c161e2124272828262320190e0b050000000000000000000000000000000000000000000009151d20282d2c26201c140800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b0d14161715110b090200000000000002090b151b19100e08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080b0b080200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090c0f121313110d0b06000000000000000000000000000000000000000000000000000001080b131717110b080100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + m_StreamData: + serializedVersion: 2 + offset: 0 + size: 0 + path: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 71c1514a6bd24e1e882cebbe1904ce04, type: 3} + m_Name: KGPrimaryWhimsy SDF + m_EditorClassIdentifier: + hashCode: 518353248 + material: {fileID: 5430614902480215695} + materialHashCode: 1246836672 + m_Version: 1.1.0 + m_SourceFontFileGUID: e00db9ee920964f58a0daa8e78ca6c4e + m_SourceFontFile_EditorRef: {fileID: 12800000, guid: e00db9ee920964f58a0daa8e78ca6c4e, type: 3} + m_SourceFontFile: {fileID: 0} + m_AtlasPopulationMode: 0 + m_FaceInfo: + m_FaceIndex: 0 + m_FamilyName: KG Primary Whimsy + m_StyleName: Regular + m_PointSize: 87 + m_Scale: 1 + m_UnitsPerEM: 1024 + m_LineHeight: 93.03223 + m_AscentLine: 67.88379 + m_CapLine: 52 + m_MeanLine: 33 + m_Baseline: 0 + m_DescentLine: -25.148438 + m_SuperscriptOffset: 67.88379 + m_SuperscriptSize: 0.5 + m_SubscriptOffset: -25.148438 + m_SubscriptSize: 0.5 + m_UnderlineOffset: -8.496094 + m_UnderlineThickness: 4.248047 + m_StrikethroughOffset: 13.2 + m_StrikethroughThickness: 4.248047 + m_TabWidth: 22 + m_GlyphTable: + - m_Index: 3 + m_Metrics: + m_Width: 0 + m_Height: 0 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 0 + m_HorizontalAdvance: 21.578125 + m_GlyphRect: + m_X: 0 + m_Y: 0 + m_Width: 0 + m_Height: 0 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 4 + m_Metrics: + m_Width: 34.15625 + m_Height: 52.671875 + m_HorizontalBearingX: 2.203125 + m_HorizontalBearingY: 52.25 + m_HorizontalAdvance: 37.21875 + m_GlyphRect: + m_X: 369 + m_Y: 138 + m_Width: 35 + m_Height: 54 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 5 + m_Metrics: + m_Width: 35.515625 + m_Height: 54.8125 + m_HorizontalBearingX: 2.296875 + m_HorizontalBearingY: 51.578125 + m_HorizontalAdvance: 40.1875 + m_GlyphRect: + m_X: 240 + m_Y: 380 + m_Width: 36 + m_Height: 56 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 6 + m_Metrics: + m_Width: 26.25 + m_Height: 26.25 + m_HorizontalBearingX: 2.125 + m_HorizontalBearingY: 32.796875 + m_HorizontalAdvance: 30.15625 + m_GlyphRect: + m_X: 258 + m_Y: 274 + m_Width: 27 + m_Height: 27 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 7 + m_Metrics: + m_Width: 26.25 + m_Height: 6.625 + m_HorizontalBearingX: 2.125 + m_HorizontalBearingY: 23.109375 + m_HorizontalAdvance: 30.84375 + m_GlyphRect: + m_X: 148 + m_Y: 295 + m_Width: 27 + m_Height: 8 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 8 + m_Metrics: + m_Width: 7.5625 + m_Height: 7.5625 + m_HorizontalBearingX: 0.9375 + m_HorizontalBearingY: 7.3125 + m_HorizontalAdvance: 10.03125 + m_GlyphRect: + m_X: 128 + m_Y: 295 + m_Width: 9 + m_Height: 9 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 9 + m_Metrics: + m_Width: 28.375 + m_Height: 53.109375 + m_HorizontalBearingX: 0.515625 + m_HorizontalBearingY: 52 + m_HorizontalAdvance: 29.0625 + m_GlyphRect: + m_X: 383 + m_Y: 6 + m_Width: 29 + m_Height: 54 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 10 + m_Metrics: + m_Width: 38.0625 + m_Height: 53.34375 + m_HorizontalBearingX: 2.96875 + m_HorizontalBearingY: 52.5 + m_HorizontalAdvance: 43.328125 + m_GlyphRect: + m_X: 287 + m_Y: 377 + m_Width: 40 + m_Height: 54 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 11 + m_Metrics: + m_Width: 8.75 + m_Height: 52.328125 + m_HorizontalBearingX: 2.546875 + m_HorizontalBearingY: 52.078125 + m_HorizontalAdvance: 14.015625 + m_GlyphRect: + m_X: 415 + m_Y: 137 + m_Width: 10 + m_Height: 54 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 12 + m_Metrics: + m_Width: 33.984375 + m_Height: 54.296875 + m_HorizontalBearingX: 1.28125 + m_HorizontalBearingY: 52.34375 + m_HorizontalAdvance: 36.953125 + m_GlyphRect: + m_X: 323 + m_Y: 139 + m_Width: 35 + m_Height: 55 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 13 + m_Metrics: + m_Width: 33.8125 + m_Height: 55.390625 + m_HorizontalBearingX: 1.28125 + m_HorizontalBearingY: 52.5 + m_HorizontalAdvance: 37.890625 + m_GlyphRect: + m_X: 186 + m_Y: 73 + m_Width: 35 + m_Height: 56 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 14 + m_Metrics: + m_Width: 33.390625 + m_Height: 51.921875 + m_HorizontalBearingX: 1.875 + m_HorizontalBearingY: 52.765625 + m_HorizontalAdvance: 36.953125 + m_GlyphRect: + m_X: 418 + m_Y: 71 + m_Width: 35 + m_Height: 53 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 15 + m_Metrics: + m_Width: 35.859375 + m_Height: 55.8125 + m_HorizontalBearingX: 0.59375 + m_HorizontalBearingY: 52.078125 + m_HorizontalAdvance: 37.640625 + m_GlyphRect: + m_X: 171 + m_Y: 314 + m_Width: 37 + m_Height: 57 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 16 + m_Metrics: + m_Width: 35.421875 + m_Height: 56.421875 + m_HorizontalBearingX: 2.46875 + m_HorizontalBearingY: 53.359375 + m_HorizontalAdvance: 38.484375 + m_GlyphRect: + m_X: 146 + m_Y: 384 + m_Width: 36 + m_Height: 58 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 17 + m_Metrics: + m_Width: 34.40625 + m_Height: 53.53125 + m_HorizontalBearingX: 1.1875 + m_HorizontalBearingY: 51.828125 + m_HorizontalAdvance: 37.125 + m_GlyphRect: + m_X: 372 + m_Y: 72 + m_Width: 35 + m_Height: 54 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 18 + m_Metrics: + m_Width: 34.40625 + m_Height: 54.453125 + m_HorizontalBearingX: 2.71875 + m_HorizontalBearingY: 51.65625 + m_HorizontalAdvance: 38.578125 + m_GlyphRect: + m_X: 292 + m_Y: 206 + m_Width: 36 + m_Height: 55 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 19 + m_Metrics: + m_Width: 31.265625 + m_Height: 53.53125 + m_HorizontalBearingX: 3.140625 + m_HorizontalBearingY: 51.484375 + m_HorizontalAdvance: 37.21875 + m_GlyphRect: + m_X: 340 + m_Y: 6 + m_Width: 32 + m_Height: 55 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 20 + m_Metrics: + m_Width: 10.109375 + m_Height: 23.875 + m_HorizontalBearingX: 3.40625 + m_HorizontalBearingY: 31.6875 + m_HorizontalAdvance: 16.390625 + m_GlyphRect: + m_X: 369 + m_Y: 270 + m_Width: 11 + m_Height: 25 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 21 + m_Metrics: + m_Width: 24.125 + m_Height: 25.5625 + m_HorizontalBearingX: 2.890625 + m_HorizontalBearingY: 35.421875 + m_HorizontalAdvance: 28.71875 + m_GlyphRect: + m_X: 296 + m_Y: 272 + m_Width: 26 + m_Height: 27 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 22 + m_Metrics: + m_Width: 27.1875 + m_Height: 19.796875 + m_HorizontalBearingX: 2.640625 + m_HorizontalBearingY: 28.546875 + m_HorizontalAdvance: 30.921875 + m_GlyphRect: + m_X: 186 + m_Y: 281 + m_Width: 28 + m_Height: 21 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 23 + m_Metrics: + m_Width: 24.046875 + m_Height: 25.65625 + m_HorizontalBearingX: 2.296875 + m_HorizontalBearingY: 34.75 + m_HorizontalAdvance: 29.5625 + m_GlyphRect: + m_X: 333 + m_Y: 272 + m_Width: 25 + m_Height: 26 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 24 + m_Metrics: + m_Width: 32.28125 + m_Height: 54.890625 + m_HorizontalBearingX: 1.703125 + m_HorizontalBearingY: 52.59375 + m_HorizontalAdvance: 35.6875 + m_GlyphRect: + m_X: 229 + m_Y: 140 + m_Width: 33 + m_Height: 56 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 25 + m_Metrics: + m_Width: 39.671875 + m_Height: 55.140625 + m_HorizontalBearingX: 2.046875 + m_HorizontalBearingY: 52.421875 + m_HorizontalAdvance: 43.671875 + m_GlyphRect: + m_X: 178 + m_Y: 214 + m_Width: 40 + m_Height: 56 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 26 + m_Metrics: + m_Width: 34.921875 + m_Height: 55.390625 + m_HorizontalBearingX: 2.125 + m_HorizontalBearingY: 52.078125 + m_HorizontalAdvance: 38.234375 + m_GlyphRect: + m_X: 193 + m_Y: 382 + m_Width: 36 + m_Height: 57 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 27 + m_Metrics: + m_Width: 36.625 + m_Height: 53.609375 + m_HorizontalBearingX: 1.953125 + m_HorizontalBearingY: 50.890625 + m_HorizontalAdvance: 41.296875 + m_GlyphRect: + m_X: 339 + m_Y: 205 + m_Width: 38 + m_Height: 54 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 28 + m_Metrics: + m_Width: 34.078125 + m_Height: 54.546875 + m_HorizontalBearingX: 2.203125 + m_HorizontalBearingY: 52.671875 + m_HorizontalAdvance: 37.890625 + m_GlyphRect: + m_X: 326 + m_Y: 72 + m_Width: 35 + m_Height: 55 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 29 + m_Metrics: + m_Width: 40.265625 + m_Height: 57.4375 + m_HorizontalBearingX: 2.46875 + m_HorizontalBearingY: 53.359375 + m_HorizontalAdvance: 44.9375 + m_GlyphRect: + m_X: 76 + m_Y: 245 + m_Width: 41 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 30 + m_Metrics: + m_Width: 37.390625 + m_Height: 53.625 + m_HorizontalBearingX: 2.71875 + m_HorizontalBearingY: 52.34375 + m_HorizontalAdvance: 41.71875 + m_GlyphRect: + m_X: 273 + m_Y: 140 + m_Width: 39 + m_Height: 55 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 31 + m_Metrics: + m_Width: 37.984375 + m_Height: 53.359375 + m_HorizontalBearingX: 2.125 + m_HorizontalBearingY: 51.828125 + m_HorizontalAdvance: 42.984375 + m_GlyphRect: + m_X: 325 + m_Y: 310 + m_Width: 39 + m_Height: 54 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 32 + m_Metrics: + m_Width: 39.9375 + m_Height: 55.390625 + m_HorizontalBearingX: 0.765625 + m_HorizontalBearingY: 51.828125 + m_HorizontalAdvance: 41.46875 + m_GlyphRect: + m_X: 214 + m_Y: 450 + m_Width: 41 + m_Height: 56 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 33 + m_Metrics: + m_Width: 36.109375 + m_Height: 55.0625 + m_HorizontalBearingX: 0.59375 + m_HorizontalBearingY: 52 + m_HorizontalAdvance: 37.640625 + m_GlyphRect: + m_X: 219 + m_Y: 313 + m_Width: 37 + m_Height: 56 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 34 + m_Metrics: + m_Width: 45.875 + m_Height: 53.1875 + m_HorizontalBearingX: 1.28125 + m_HorizontalBearingY: 53.1875 + m_HorizontalAdvance: 48.765625 + m_GlyphRect: + m_X: 267 + m_Y: 312 + m_Width: 47 + m_Height: 54 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 35 + m_Metrics: + m_Width: 38.390625 + m_Height: 54.546875 + m_HorizontalBearingX: 1.109375 + m_HorizontalBearingY: 51.234375 + m_HorizontalAdvance: 40.859375 + m_GlyphRect: + m_X: 179 + m_Y: 146 + m_Width: 39 + m_Height: 56 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 36 + m_Metrics: + m_Width: 31.4375 + m_Height: 56.328125 + m_HorizontalBearingX: 2.125 + m_HorizontalBearingY: 52.671875 + m_HorizontalAdvance: 35.515625 + m_GlyphRect: + m_X: 143 + m_Y: 78 + m_Width: 32 + m_Height: 57 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 37 + m_Metrics: + m_Width: 52.671875 + m_Height: 57.515625 + m_HorizontalBearingX: 1.875 + m_HorizontalBearingY: 52.84375 + m_HorizontalAdvance: 56.15625 + m_GlyphRect: + m_X: 81 + m_Y: 386 + m_Width: 54 + m_Height: 58 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 38 + m_Metrics: + m_Width: 42.390625 + m_Height: 57.1875 + m_HorizontalBearingX: 1.28125 + m_HorizontalBearingY: 53.53125 + m_HorizontalAdvance: 44.6875 + m_GlyphRect: + m_X: 117 + m_Y: 315 + m_Width: 43 + m_Height: 58 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 39 + m_Metrics: + m_Width: 39.5 + m_Height: 52.515625 + m_HorizontalBearingX: 2.640625 + m_HorizontalBearingY: 50.984375 + m_HorizontalAdvance: 43.84375 + m_GlyphRect: + m_X: 162 + m_Y: 453 + m_Width: 41 + m_Height: 53 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 40 + m_Metrics: + m_Width: 32.203125 + m_Height: 54.796875 + m_HorizontalBearingX: 1.53125 + m_HorizontalBearingY: 51.484375 + m_HorizontalAdvance: 35.515625 + m_GlyphRect: + m_X: 232 + m_Y: 73 + m_Width: 33 + m_Height: 56 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 41 + m_Metrics: + m_Width: 39 + m_Height: 56.25 + m_HorizontalBearingX: 2.375 + m_HorizontalBearingY: 51.40625 + m_HorizontalAdvance: 43.578125 + m_GlyphRect: + m_X: 83 + m_Y: 159 + m_Width: 40 + m_Height: 57 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 42 + m_Metrics: + m_Width: 37.984375 + m_Height: 54.453125 + m_HorizontalBearingX: 2.375 + m_HorizontalBearingY: 52.84375 + m_HorizontalAdvance: 41.890625 + m_GlyphRect: + m_X: 276 + m_Y: 73 + m_Width: 39 + m_Height: 55 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 43 + m_Metrics: + m_Width: 35.4375 + m_Height: 54.796875 + m_HorizontalBearingX: 1.015625 + m_HorizontalBearingY: 52.078125 + m_HorizontalAdvance: 37.890625 + m_GlyphRect: + m_X: 266 + m_Y: 447 + m_Width: 36 + m_Height: 56 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 44 + m_Metrics: + m_Width: 37.890625 + m_Height: 55.828125 + m_HorizontalBearingX: 1.953125 + m_HorizontalBearingY: 53.359375 + m_HorizontalAdvance: 42.65625 + m_GlyphRect: + m_X: 93 + m_Y: 78 + m_Width: 39 + m_Height: 57 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 45 + m_Metrics: + m_Width: 38.921875 + m_Height: 55.578125 + m_HorizontalBearingX: 1.015625 + m_HorizontalBearingY: 53.53125 + m_HorizontalAdvance: 41.125 + m_GlyphRect: + m_X: 128 + m_Y: 227 + m_Width: 39 + m_Height: 57 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 46 + m_Metrics: + m_Width: 39.6875 + m_Height: 55.140625 + m_HorizontalBearingX: 1.609375 + m_HorizontalBearingY: 53.609375 + m_HorizontalAdvance: 43.25 + m_GlyphRect: + m_X: 153 + m_Y: 6 + m_Width: 41 + m_Height: 56 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 47 + m_Metrics: + m_Width: 62.703125 + m_Height: 58.125 + m_HorizontalBearingX: 2.71875 + m_HorizontalBearingY: 53.53125 + m_HorizontalAdvance: 67.125 + m_GlyphRect: + m_X: 6 + m_Y: 395 + m_Width: 64 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 48 + m_Metrics: + m_Width: 45.1875 + m_Height: 59.046875 + m_HorizontalBearingX: 1.28125 + m_HorizontalBearingY: 53.1875 + m_HorizontalAdvance: 47.578125 + m_GlyphRect: + m_X: 6 + m_Y: 324 + m_Width: 46 + m_Height: 60 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 49 + m_Metrics: + m_Width: 32.546875 + m_Height: 56 + m_HorizontalBearingX: 2.546875 + m_HorizontalBearingY: 53.359375 + m_HorizontalAdvance: 36.28125 + m_GlyphRect: + m_X: 134 + m_Y: 146 + m_Width: 34 + m_Height: 57 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 50 + m_Metrics: + m_Width: 42.484375 + m_Height: 57.6875 + m_HorizontalBearingX: 1.4375 + m_HorizontalBearingY: 54.625 + m_HorizontalAdvance: 45.28125 + m_GlyphRect: + m_X: 63 + m_Y: 316 + m_Width: 43 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 51 + m_Metrics: + m_Width: 27.609375 + m_Height: 68.8125 + m_HorizontalBearingX: 1.53125 + m_HorizontalBearingY: 58.875 + m_HorizontalAdvance: 23.53125 + m_GlyphRect: + m_X: 6 + m_Y: 87 + m_Width: 29 + m_Height: 69 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 52 + m_Metrics: + m_Width: 28.375 + m_Height: 53.109375 + m_HorizontalBearingX: 0.59375 + m_HorizontalBearingY: 52 + m_HorizontalAdvance: 29.484375 + m_GlyphRect: + m_X: 388 + m_Y: 203 + m_Width: 29 + m_Height: 54 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 53 + m_Metrics: + m_Width: 25.65625 + m_Height: 68.8125 + m_HorizontalBearingX: 0.59375 + m_HorizontalBearingY: 60.234375 + m_HorizontalAdvance: 27.703125 + m_GlyphRect: + m_X: 6 + m_Y: 6 + m_Width: 27 + m_Height: 70 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 54 + m_Metrics: + m_Width: 25.984375 + m_Height: 8.078125 + m_HorizontalBearingX: 2.046875 + m_HorizontalBearingY: 5.015625 + m_HorizontalAdvance: 28.71875 + m_GlyphRect: + m_X: 479 + m_Y: 317 + m_Width: 27 + m_Height: 10 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 55 + m_Metrics: + m_Width: 33.390625 + m_Height: 34.578125 + m_HorizontalBearingX: 2.375 + m_HorizontalBearingY: 33.140625 + m_HorizontalAdvance: 38.828125 + m_GlyphRect: + m_X: 466 + m_Y: 63 + m_Width: 34 + m_Height: 36 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 56 + m_Metrics: + m_Width: 33.640625 + m_Height: 55.5625 + m_HorizontalBearingX: 1.359375 + m_HorizontalBearingY: 51.65625 + m_HorizontalAdvance: 37.125 + m_GlyphRect: + m_X: 205 + m_Y: 6 + m_Width: 34 + m_Height: 56 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 57 + m_Metrics: + m_Width: 29.984375 + m_Height: 31.59375 + m_HorizontalBearingX: 1.875 + m_HorizontalBearingY: 31.515625 + m_HorizontalAdvance: 32.625 + m_GlyphRect: + m_X: 459 + m_Y: 369 + m_Width: 31 + m_Height: 33 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 58 + m_Metrics: + m_Width: 35.25 + m_Height: 53.6875 + m_HorizontalBearingX: 1.875 + m_HorizontalBearingY: 51.3125 + m_HorizontalAdvance: 39.171875 + m_GlyphRect: + m_X: 292 + m_Y: 6 + m_Width: 37 + m_Height: 55 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 59 + m_Metrics: + m_Width: 31.515625 + m_Height: 31.359375 + m_HorizontalBearingX: 1.875 + m_HorizontalBearingY: 31.015625 + m_HorizontalAdvance: 33.90625 + m_GlyphRect: + m_X: 435 + m_Y: 317 + m_Width: 33 + m_Height: 33 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 60 + m_Metrics: + m_Width: 29.90625 + m_Height: 55.3125 + m_HorizontalBearingX: 2.71875 + m_HorizontalBearingY: 51.90625 + m_HorizontalAdvance: 33.984375 + m_GlyphRect: + m_X: 250 + m_Y: 6 + m_Width: 31 + m_Height: 56 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 61 + m_Metrics: + m_Width: 33.21875 + m_Height: 48.859375 + m_HorizontalBearingX: 1.953125 + m_HorizontalBearingY: 33.5625 + m_HorizontalAdvance: 36.703125 + m_GlyphRect: + m_X: 116 + m_Y: 455 + m_Width: 35 + m_Height: 50 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 62 + m_Metrics: + m_Width: 28.125 + m_Height: 54.796875 + m_HorizontalBearingX: 2.203125 + m_HorizontalBearingY: 50.546875 + m_HorizontalAdvance: 32.546875 + m_GlyphRect: + m_X: 229 + m_Y: 207 + m_Width: 29 + m_Height: 56 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 63 + m_Metrics: + m_Width: 10.875 + m_Height: 40.015625 + m_HorizontalBearingX: 3.40625 + m_HorizontalBearingY: 40.265625 + m_HorizontalAdvance: 16.484375 + m_GlyphRect: + m_X: 6 + m_Y: 465 + m_Width: 12 + m_Height: 41 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 64 + m_Metrics: + m_Width: 17.078125 + m_Height: 59.0625 + m_HorizontalBearingX: 0.9375 + m_HorizontalBearingY: 43.421875 + m_HorizontalAdvance: 19.109375 + m_GlyphRect: + m_X: 46 + m_Y: 245 + m_Width: 19 + m_Height: 60 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 65 + m_Metrics: + m_Width: 30.671875 + m_Height: 51.828125 + m_HorizontalBearingX: 1.703125 + m_HorizontalBearingY: 51.578125 + m_HorizontalAdvance: 33.640625 + m_GlyphRect: + m_X: 423 + m_Y: 6 + m_Width: 32 + m_Height: 53 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 66 + m_Metrics: + m_Width: 11.890625 + m_Height: 51.921875 + m_HorizontalBearingX: 2.046875 + m_HorizontalBearingY: 52.171875 + m_HorizontalAdvance: 15.890625 + m_GlyphRect: + m_X: 436 + m_Y: 184 + m_Width: 12 + m_Height: 53 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 67 + m_Metrics: + m_Width: 50.640625 + m_Height: 36.015625 + m_HorizontalBearingX: 3.3125 + m_HorizontalBearingY: 34.578125 + m_HorizontalAdvance: 56.421875 + m_GlyphRect: + m_X: 54 + m_Y: 465 + m_Width: 51 + m_Height: 37 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 68 + m_Metrics: + m_Width: 28.71875 + m_Height: 34.234375 + m_HorizontalBearingX: 2.296875 + m_HorizontalBearingY: 33.046875 + m_HorizontalAdvance: 32.875 + m_GlyphRect: + m_X: 338 + m_Y: 375 + m_Width: 30 + m_Height: 36 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 69 + m_Metrics: + m_Width: 30.40625 + m_Height: 30.84375 + m_HorizontalBearingX: 1.875 + m_HorizontalBearingY: 30.671875 + m_HorizontalAdvance: 34.328125 + m_GlyphRect: + m_X: 416 + m_Y: 361 + m_Width: 32 + m_Height: 32 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 70 + m_Metrics: + m_Width: 36.1875 + m_Height: 45.203125 + m_HorizontalBearingX: -0.59375 + m_HorizontalBearingY: 34.5 + m_HorizontalAdvance: 38.0625 + m_GlyphRect: + m_X: 466 + m_Y: 6 + m_Width: 37 + m_Height: 46 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 71 + m_Metrics: + m_Width: 44.765625 + m_Height: 45.453125 + m_HorizontalBearingX: 2.296875 + m_HorizontalBearingY: 31.859375 + m_HorizontalAdvance: 37.8125 + m_GlyphRect: + m_X: 459 + m_Y: 214 + m_Width: 46 + m_Height: 46 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 72 + m_Metrics: + m_Width: 28.109375 + m_Height: 31.515625 + m_HorizontalBearingX: 3.40625 + m_HorizontalBearingY: 30.75 + m_HorizontalAdvance: 34.578125 + m_GlyphRect: + m_X: 451 + m_Y: 413 + m_Width: 29 + m_Height: 32 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 73 + m_Metrics: + m_Width: 28.71875 + m_Height: 32.625 + m_HorizontalBearingX: 1.78125 + m_HorizontalBearingY: 31.859375 + m_HorizontalAdvance: 32.28125 + m_GlyphRect: + m_X: 370 + m_Y: 448 + m_Width: 30 + m_Height: 33 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 74 + m_Metrics: + m_Width: 26.171875 + m_Height: 47.921875 + m_HorizontalBearingX: 1.53125 + m_HorizontalBearingY: 47.15625 + m_HorizontalAdvance: 29.3125 + m_GlyphRect: + m_X: 332 + m_Y: 442 + m_Width: 27 + m_Height: 49 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 75 + m_Metrics: + m_Width: 31.6875 + m_Height: 33.234375 + m_HorizontalBearingX: 2.546875 + m_HorizontalBearingY: 31.953125 + m_HorizontalAdvance: 37.296875 + m_GlyphRect: + m_X: 391 + m_Y: 278 + m_Width: 33 + m_Height: 34 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 76 + m_Metrics: + m_Width: 27.015625 + m_Height: 32.375 + m_HorizontalBearingX: 1.703125 + m_HorizontalBearingY: 33.390625 + m_HorizontalAdvance: 30.15625 + m_GlyphRect: + m_X: 451 + m_Y: 456 + m_Width: 28 + m_Height: 33 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 77 + m_Metrics: + m_Width: 44.015625 + m_Height: 33.984375 + m_HorizontalBearingX: 1.609375 + m_HorizontalBearingY: 32.453125 + m_HorizontalAdvance: 46.984375 + m_GlyphRect: + m_X: 450 + m_Y: 271 + m_Width: 45 + m_Height: 35 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 78 + m_Metrics: + m_Width: 29.3125 + m_Height: 33.296875 + m_HorizontalBearingX: 2.203125 + m_HorizontalBearingY: 32.109375 + m_HorizontalAdvance: 33.046875 + m_GlyphRect: + m_X: 375 + m_Y: 323 + m_Width: 30 + m_Height: 35 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 79 + m_Metrics: + m_Width: 31.703125 + m_Height: 46.5625 + m_HorizontalBearingX: 1.609375 + m_HorizontalBearingY: 31.09375 + m_HorizontalAdvance: 35.515625 + m_GlyphRect: + m_X: 464 + m_Y: 155 + m_Width: 33 + m_Height: 48 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 80 + m_Metrics: + m_Width: 29.90625 + m_Height: 32.625 + m_HorizontalBearingX: 2.203125 + m_HorizontalBearingY: 32.703125 + m_HorizontalAdvance: 33.3125 + m_GlyphRect: + m_X: 379 + m_Y: 404 + m_Width: 31 + m_Height: 33 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 81 + m_Metrics: + m_Width: 6.875 + m_Height: 52.34375 + m_HorizontalBearingX: 2.71875 + m_HorizontalBearingY: 51.828125 + m_HorizontalAdvance: 12.40625 + m_GlyphRect: + m_X: 313 + m_Y: 442 + m_Width: 8 + m_Height: 53 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 83 + m_Metrics: + m_Width: 27.1875 + m_Height: 65.421875 + m_HorizontalBearingX: -2.296875 + m_HorizontalBearingY: 61.09375 + m_HorizontalAdvance: 29.3125 + m_GlyphRect: + m_X: 44 + m_Y: 167 + m_Width: 28 + m_Height: 67 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 84 + m_Metrics: + m_Width: 28.046875 + m_Height: 65.25 + m_HorizontalBearingX: 2.546875 + m_HorizontalBearingY: 59.046875 + m_HorizontalAdvance: 28.03125 + m_GlyphRect: + m_X: 6 + m_Y: 246 + m_Width: 29 + m_Height: 67 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 85 + m_Metrics: + m_Width: 15.71875 + m_Height: 11.546875 + m_HorizontalBearingX: 1.703125 + m_HorizontalBearingY: 31.265625 + m_HorizontalAdvance: 19.96875 + m_GlyphRect: + m_X: 436 + m_Y: 135 + m_Width: 17 + m_Height: 13 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 87 + m_Metrics: + m_Width: 26.078125 + m_Height: 67.203125 + m_HorizontalBearingX: 1.875 + m_HorizontalBearingY: 60.75 + m_HorizontalAdvance: 28.890625 + m_GlyphRect: + m_X: 6 + m_Y: 167 + m_Width: 27 + m_Height: 68 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 88 + m_Metrics: + m_Width: 27.015625 + m_Height: 66.9375 + m_HorizontalBearingX: 0.765625 + m_HorizontalBearingY: 60.65625 + m_HorizontalAdvance: 29.984375 + m_GlyphRect: + m_X: 44 + m_Y: 6 + m_Width: 28 + m_Height: 68 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 89 + m_Metrics: + m_Width: 12.828125 + m_Height: 38.3125 + m_HorizontalBearingX: 2.296875 + m_HorizontalBearingY: 31.859375 + m_HorizontalAdvance: 20.21875 + m_GlyphRect: + m_X: 29 + m_Y: 465 + m_Width: 14 + m_Height: 39 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 90 + m_Metrics: + m_Width: 10.1875 + m_Height: 18.609375 + m_HorizontalBearingX: 1.703125 + m_HorizontalBearingY: 11.8125 + m_HorizontalAdvance: 15.546875 + m_GlyphRect: + m_X: 428 + m_Y: 248 + m_Width: 11 + m_Height: 19 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 91 + m_Metrics: + m_Width: 9.25 + m_Height: 18.859375 + m_HorizontalBearingX: 3.40625 + m_HorizontalBearingY: 40.78125 + m_HorizontalAdvance: 16.734375 + m_GlyphRect: + m_X: 479 + m_Y: 338 + m_Width: 10 + m_Height: 20 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 92 + m_Metrics: + m_Width: 21.0625 + m_Height: 19.1875 + m_HorizontalBearingX: 3.40625 + m_HorizontalBearingY: 44.9375 + m_HorizontalAdvance: 28.890625 + m_GlyphRect: + m_X: 225 + m_Y: 281 + m_Width: 22 + m_Height: 20 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 97 + m_Metrics: + m_Width: 58.28125 + m_Height: 59.5625 + m_HorizontalBearingX: 2.046875 + m_HorizontalBearingY: 57.515625 + m_HorizontalAdvance: 63.640625 + m_GlyphRect: + m_X: 83 + m_Y: 6 + m_Width: 59 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 98 + m_Metrics: + m_Width: 28.71875 + m_Height: 32.109375 + m_HorizontalBearingX: 5.1875 + m_HorizontalBearingY: 44.265625 + m_HorizontalAdvance: 38.40625 + m_GlyphRect: + m_X: 411 + m_Y: 448 + m_Width: 29 + m_Height: 33 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 101 + m_Metrics: + m_Width: 27.953125 + m_Height: 12.15625 + m_HorizontalBearingX: 1.953125 + m_HorizontalBearingY: 31.953125 + m_HorizontalAdvance: 31.4375 + m_GlyphRect: + m_X: 370 + m_Y: 492 + m_Width: 29 + m_Height: 13 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 112 + m_Metrics: + m_Width: 28.984375 + m_Height: 9 + m_HorizontalBearingX: 1.609375 + m_HorizontalBearingY: 8.75 + m_HorizontalAdvance: 32.109375 + m_GlyphRect: + m_X: 410 + m_Y: 492 + m_Width: 30 + m_Height: 10 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 118 + m_Metrics: + m_Width: 11.890625 + m_Height: 12.5 + m_HorizontalBearingX: 2.46875 + m_HorizontalBearingY: 43.25 + m_HorizontalAdvance: 15.640625 + m_GlyphRect: + m_X: 436 + m_Y: 159 + m_Width: 13 + m_Height: 14 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 342 + m_Metrics: + m_Width: 34.921875 + m_Height: 61.84375 + m_HorizontalBearingX: 3.484375 + m_HorizontalBearingY: 56.15625 + m_HorizontalAdvance: 40.1875 + m_GlyphRect: + m_X: 46 + m_Y: 85 + m_Width: 36 + m_Height: 63 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 343 + m_Metrics: + m_Width: 11.296875 + m_Height: 55.140625 + m_HorizontalBearingX: 2.125 + m_HorizontalBearingY: 53.265625 + m_HorizontalAdvance: 16.0625 + m_GlyphRect: + m_X: 269 + m_Y: 207 + m_Width: 12 + m_Height: 56 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 344 + m_Metrics: + m_Width: 32.375 + m_Height: 32.453125 + m_HorizontalBearingX: 3.734375 + m_HorizontalBearingY: 39.078125 + m_HorizontalAdvance: 40.53125 + m_GlyphRect: + m_X: 464 + m_Y: 110 + m_Width: 34 + m_Height: 34 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + m_CharacterTable: + - m_ElementType: 1 + m_Unicode: 32 + m_GlyphIndex: 3 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 33 + m_GlyphIndex: 343 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 34 + m_GlyphIndex: 92 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 35 + m_GlyphIndex: 344 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 36 + m_GlyphIndex: 342 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 37 + m_GlyphIndex: 4 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 38 + m_GlyphIndex: 5 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 39 + m_GlyphIndex: 91 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 40 + m_GlyphIndex: 84 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 41 + m_GlyphIndex: 83 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 42 + m_GlyphIndex: 98 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 43 + m_GlyphIndex: 6 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 44 + m_GlyphIndex: 90 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 45 + m_GlyphIndex: 7 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 46 + m_GlyphIndex: 8 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 47 + m_GlyphIndex: 9 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 48 + m_GlyphIndex: 10 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 49 + m_GlyphIndex: 11 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 50 + m_GlyphIndex: 12 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 51 + m_GlyphIndex: 13 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 52 + m_GlyphIndex: 14 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 53 + m_GlyphIndex: 15 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 54 + m_GlyphIndex: 16 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 55 + m_GlyphIndex: 17 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 56 + m_GlyphIndex: 18 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 57 + m_GlyphIndex: 19 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 58 + m_GlyphIndex: 20 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 59 + m_GlyphIndex: 89 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 60 + m_GlyphIndex: 21 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 61 + m_GlyphIndex: 22 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 62 + m_GlyphIndex: 23 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 63 + m_GlyphIndex: 24 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 64 + m_GlyphIndex: 97 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 65 + m_GlyphIndex: 25 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 66 + m_GlyphIndex: 26 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 67 + m_GlyphIndex: 27 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 68 + m_GlyphIndex: 28 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 69 + m_GlyphIndex: 29 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 70 + m_GlyphIndex: 30 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 71 + m_GlyphIndex: 31 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 72 + m_GlyphIndex: 32 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 73 + m_GlyphIndex: 33 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 74 + m_GlyphIndex: 34 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 75 + m_GlyphIndex: 35 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 76 + m_GlyphIndex: 36 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 77 + m_GlyphIndex: 37 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 78 + m_GlyphIndex: 38 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 79 + m_GlyphIndex: 39 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 80 + m_GlyphIndex: 40 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 81 + m_GlyphIndex: 41 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 82 + m_GlyphIndex: 42 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 83 + m_GlyphIndex: 43 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 84 + m_GlyphIndex: 44 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 85 + m_GlyphIndex: 45 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 86 + m_GlyphIndex: 46 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 87 + m_GlyphIndex: 47 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 88 + m_GlyphIndex: 48 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 89 + m_GlyphIndex: 49 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 90 + m_GlyphIndex: 50 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 91 + m_GlyphIndex: 51 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 92 + m_GlyphIndex: 52 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 93 + m_GlyphIndex: 53 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 94 + m_GlyphIndex: 85 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 95 + m_GlyphIndex: 54 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 96 + m_GlyphIndex: 118 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 97 + m_GlyphIndex: 55 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 98 + m_GlyphIndex: 56 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 99 + m_GlyphIndex: 57 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 100 + m_GlyphIndex: 58 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 101 + m_GlyphIndex: 59 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 102 + m_GlyphIndex: 60 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 103 + m_GlyphIndex: 61 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 104 + m_GlyphIndex: 62 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 105 + m_GlyphIndex: 63 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 106 + m_GlyphIndex: 64 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 107 + m_GlyphIndex: 65 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 108 + m_GlyphIndex: 66 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 109 + m_GlyphIndex: 67 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 110 + m_GlyphIndex: 68 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 111 + m_GlyphIndex: 69 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 112 + m_GlyphIndex: 70 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 113 + m_GlyphIndex: 71 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 114 + m_GlyphIndex: 72 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 115 + m_GlyphIndex: 73 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 116 + m_GlyphIndex: 74 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 117 + m_GlyphIndex: 75 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 118 + m_GlyphIndex: 76 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 119 + m_GlyphIndex: 77 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 120 + m_GlyphIndex: 78 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 121 + m_GlyphIndex: 79 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 122 + m_GlyphIndex: 80 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 123 + m_GlyphIndex: 87 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 124 + m_GlyphIndex: 81 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 125 + m_GlyphIndex: 88 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 126 + m_GlyphIndex: 101 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 160 + m_GlyphIndex: 3 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8230 + m_GlyphIndex: 112 + m_Scale: 1 + m_AtlasTextures: + - {fileID: -4571599219975028377} + m_AtlasTextureIndex: 0 + m_IsMultiAtlasTexturesEnabled: 0 + m_ClearDynamicDataOnBuild: 0 + m_UsedGlyphRects: + - m_X: 0 + m_Y: 0 + m_Width: 38 + m_Height: 81 + - m_X: 0 + m_Y: 81 + m_Width: 40 + m_Height: 80 + - m_X: 38 + m_Y: 0 + m_Width: 39 + m_Height: 79 + - m_X: 0 + m_Y: 161 + m_Width: 38 + m_Height: 79 + - m_X: 0 + m_Y: 240 + m_Width: 40 + m_Height: 78 + - m_X: 38 + m_Y: 161 + m_Width: 39 + m_Height: 78 + - m_X: 40 + m_Y: 79 + m_Width: 47 + m_Height: 74 + - m_X: 77 + m_Y: 0 + m_Width: 70 + m_Height: 72 + - m_X: 0 + m_Y: 318 + m_Width: 57 + m_Height: 71 + - m_X: 40 + m_Y: 239 + m_Width: 30 + m_Height: 71 + - m_X: 0 + m_Y: 389 + m_Width: 75 + m_Height: 70 + - m_X: 0 + m_Y: 459 + m_Width: 23 + m_Height: 52 + - m_X: 23 + m_Y: 459 + m_Width: 25 + m_Height: 50 + - m_X: 48 + m_Y: 459 + m_Width: 62 + m_Height: 48 + - m_X: 57 + m_Y: 310 + m_Width: 54 + m_Height: 70 + - m_X: 70 + m_Y: 239 + m_Width: 52 + m_Height: 70 + - m_X: 75 + m_Y: 380 + m_Width: 65 + m_Height: 69 + - m_X: 110 + m_Y: 449 + m_Width: 46 + m_Height: 61 + - m_X: 111 + m_Y: 309 + m_Width: 54 + m_Height: 69 + - m_X: 140 + m_Y: 378 + m_Width: 47 + m_Height: 69 + - m_X: 156 + m_Y: 447 + m_Width: 52 + m_Height: 64 + - m_X: 77 + m_Y: 153 + m_Width: 51 + m_Height: 68 + - m_X: 87 + m_Y: 72 + m_Width: 50 + m_Height: 68 + - m_X: 122 + m_Y: 221 + m_Width: 50 + m_Height: 68 + - m_X: 122 + m_Y: 289 + m_Width: 20 + m_Height: 20 + - m_X: 142 + m_Y: 289 + m_Width: 38 + m_Height: 19 + - m_X: 165 + m_Y: 308 + m_Width: 48 + m_Height: 68 + - m_X: 187 + m_Y: 376 + m_Width: 47 + m_Height: 68 + - m_X: 208 + m_Y: 444 + m_Width: 52 + m_Height: 67 + - m_X: 128 + m_Y: 140 + m_Width: 45 + m_Height: 68 + - m_X: 137 + m_Y: 72 + m_Width: 43 + m_Height: 68 + - m_X: 147 + m_Y: 0 + m_Width: 52 + m_Height: 67 + - m_X: 172 + m_Y: 208 + m_Width: 51 + m_Height: 67 + - m_X: 173 + m_Y: 140 + m_Width: 50 + m_Height: 67 + - m_X: 180 + m_Y: 275 + m_Width: 39 + m_Height: 32 + - m_X: 213 + m_Y: 307 + m_Width: 48 + m_Height: 67 + - m_X: 219 + m_Y: 275 + m_Width: 33 + m_Height: 31 + - m_X: 234 + m_Y: 374 + m_Width: 47 + m_Height: 67 + - m_X: 260 + m_Y: 441 + m_Width: 47 + m_Height: 67 + - m_X: 180 + m_Y: 67 + m_Width: 46 + m_Height: 67 + - m_X: 199 + m_Y: 0 + m_Width: 45 + m_Height: 67 + - m_X: 223 + m_Y: 134 + m_Width: 44 + m_Height: 67 + - m_X: 226 + m_Y: 67 + m_Width: 44 + m_Height: 67 + - m_X: 244 + m_Y: 0 + m_Width: 42 + m_Height: 67 + - m_X: 223 + m_Y: 201 + m_Width: 40 + m_Height: 67 + - m_X: 252 + m_Y: 268 + m_Width: 38 + m_Height: 38 + - m_X: 263 + m_Y: 201 + m_Width: 23 + m_Height: 67 + - m_X: 267 + m_Y: 134 + m_Width: 50 + m_Height: 66 + - m_X: 270 + m_Y: 67 + m_Width: 50 + m_Height: 66 + - m_X: 286 + m_Y: 0 + m_Width: 48 + m_Height: 66 + - m_X: 286 + m_Y: 200 + m_Width: 47 + m_Height: 66 + - m_X: 317 + m_Y: 133 + m_Width: 46 + m_Height: 66 + - m_X: 320 + m_Y: 66 + m_Width: 46 + m_Height: 66 + - m_X: 334 + m_Y: 0 + m_Width: 43 + m_Height: 66 + - m_X: 261 + m_Y: 306 + m_Width: 58 + m_Height: 65 + - m_X: 290 + m_Y: 266 + m_Width: 37 + m_Height: 38 + - m_X: 281 + m_Y: 371 + m_Width: 51 + m_Height: 65 + - m_X: 319 + m_Y: 304 + m_Width: 50 + m_Height: 65 + - m_X: 327 + m_Y: 266 + m_Width: 36 + m_Height: 37 + - m_X: 333 + m_Y: 199 + m_Width: 49 + m_Height: 65 + - m_X: 363 + m_Y: 132 + m_Width: 46 + m_Height: 65 + - m_X: 366 + m_Y: 66 + m_Width: 46 + m_Height: 65 + - m_X: 377 + m_Y: 0 + m_Width: 40 + m_Height: 65 + - m_X: 363 + m_Y: 264 + m_Width: 22 + m_Height: 36 + - m_X: 382 + m_Y: 197 + m_Width: 40 + m_Height: 65 + - m_X: 409 + m_Y: 131 + m_Width: 21 + m_Height: 65 + - m_X: 412 + m_Y: 65 + m_Width: 46 + m_Height: 64 + - m_X: 417 + m_Y: 0 + m_Width: 43 + m_Height: 64 + - m_X: 460 + m_Y: 0 + m_Width: 48 + m_Height: 57 + - m_X: 460 + m_Y: 57 + m_Width: 45 + m_Height: 47 + - m_X: 458 + m_Y: 104 + m_Width: 45 + m_Height: 45 + - m_X: 430 + m_Y: 129 + m_Width: 28 + m_Height: 24 + - m_X: 458 + m_Y: 149 + m_Width: 44 + m_Height: 59 + - m_X: 430 + m_Y: 153 + m_Width: 24 + m_Height: 25 + - m_X: 430 + m_Y: 178 + m_Width: 23 + m_Height: 64 + - m_X: 453 + m_Y: 208 + m_Width: 57 + m_Height: 57 + - m_X: 422 + m_Y: 242 + m_Width: 22 + m_Height: 30 + - m_X: 307 + m_Y: 436 + m_Width: 19 + m_Height: 64 + - m_X: 444 + m_Y: 265 + m_Width: 56 + m_Height: 46 + - m_X: 326 + m_Y: 436 + m_Width: 38 + m_Height: 60 + - m_X: 385 + m_Y: 272 + m_Width: 44 + m_Height: 45 + - m_X: 332 + m_Y: 369 + m_Width: 41 + m_Height: 47 + - m_X: 369 + m_Y: 317 + m_Width: 41 + m_Height: 46 + - m_X: 429 + m_Y: 311 + m_Width: 44 + m_Height: 44 + - m_X: 473 + m_Y: 311 + m_Width: 38 + m_Height: 21 + - m_X: 473 + m_Y: 332 + m_Width: 21 + m_Height: 31 + - m_X: 410 + m_Y: 355 + m_Width: 43 + m_Height: 43 + - m_X: 453 + m_Y: 363 + m_Width: 42 + m_Height: 44 + - m_X: 373 + m_Y: 398 + m_Width: 42 + m_Height: 44 + - m_X: 364 + m_Y: 442 + m_Width: 41 + m_Height: 44 + - m_X: 364 + m_Y: 486 + m_Width: 40 + m_Height: 24 + - m_X: 404 + m_Y: 486 + m_Width: 41 + m_Height: 21 + - m_X: 405 + m_Y: 442 + m_Width: 40 + m_Height: 44 + - m_X: 445 + m_Y: 407 + m_Width: 40 + m_Height: 43 + - m_X: 445 + m_Y: 450 + m_Width: 39 + m_Height: 44 + m_FreeGlyphRects: + - m_X: 38 + m_Y: 79 + m_Width: 2 + m_Height: 2 + - m_X: 38 + m_Y: 239 + m_Width: 2 + m_Height: 1 + - m_X: 40 + m_Y: 310 + m_Width: 17 + m_Height: 8 + - m_X: 57 + m_Y: 380 + m_Width: 18 + m_Height: 9 + - m_X: 23 + m_Y: 509 + m_Width: 87 + m_Height: 2 + - m_X: 48 + m_Y: 507 + m_Width: 62 + m_Height: 4 + - m_X: 75 + m_Y: 449 + m_Width: 35 + m_Height: 10 + - m_X: 70 + m_Y: 309 + m_Width: 41 + m_Height: 1 + - m_X: 111 + m_Y: 378 + m_Width: 29 + m_Height: 2 + - m_X: 23 + m_Y: 510 + m_Width: 133 + m_Height: 1 + - m_X: 140 + m_Y: 447 + m_Width: 16 + m_Height: 2 + - m_X: 40 + m_Y: 153 + m_Width: 37 + m_Height: 8 + - m_X: 77 + m_Y: 72 + m_Width: 10 + m_Height: 7 + - m_X: 77 + m_Y: 221 + m_Width: 45 + m_Height: 18 + - m_X: 142 + m_Y: 308 + m_Width: 23 + m_Height: 1 + - m_X: 165 + m_Y: 376 + m_Width: 22 + m_Height: 2 + - m_X: 187 + m_Y: 444 + m_Width: 21 + m_Height: 3 + - m_X: 87 + m_Y: 140 + m_Width: 41 + m_Height: 13 + - m_X: 128 + m_Y: 208 + m_Width: 44 + m_Height: 13 + - m_X: 172 + m_Y: 275 + m_Width: 8 + m_Height: 14 + - m_X: 180 + m_Y: 307 + m_Width: 33 + m_Height: 1 + - m_X: 213 + m_Y: 374 + m_Width: 21 + m_Height: 2 + - m_X: 234 + m_Y: 441 + m_Width: 26 + m_Height: 3 + - m_X: 147 + m_Y: 67 + m_Width: 33 + m_Height: 5 + - m_X: 180 + m_Y: 134 + m_Width: 43 + m_Height: 6 + - m_X: 173 + m_Y: 207 + m_Width: 50 + m_Height: 1 + - m_X: 223 + m_Y: 268 + m_Width: 29 + m_Height: 7 + - m_X: 267 + m_Y: 200 + m_Width: 19 + m_Height: 1 + - m_X: 270 + m_Y: 133 + m_Width: 47 + m_Height: 1 + - m_X: 286 + m_Y: 66 + m_Width: 34 + m_Height: 1 + - m_X: 219 + m_Y: 306 + m_Width: 42 + m_Height: 1 + - m_X: 286 + m_Y: 266 + m_Width: 4 + m_Height: 2 + - m_X: 261 + m_Y: 371 + m_Width: 20 + m_Height: 3 + - m_X: 290 + m_Y: 304 + m_Width: 29 + m_Height: 2 + - m_X: 317 + m_Y: 199 + m_Width: 16 + m_Height: 1 + - m_X: 320 + m_Y: 132 + m_Width: 43 + m_Height: 1 + - m_X: 333 + m_Y: 264 + m_Width: 30 + m_Height: 2 + - m_X: 363 + m_Y: 197 + m_Width: 19 + m_Height: 2 + - m_X: 366 + m_Y: 131 + m_Width: 43 + m_Height: 1 + - m_X: 377 + m_Y: 65 + m_Width: 35 + m_Height: 1 + - m_X: 417 + m_Y: 64 + m_Width: 43 + m_Height: 1 + - m_X: 458 + m_Y: 64 + m_Width: 2 + m_Height: 40 + - m_X: 412 + m_Y: 129 + m_Width: 18 + m_Height: 2 + - m_X: 409 + m_Y: 196 + m_Width: 21 + m_Height: 1 + - m_X: 508 + m_Y: 0 + m_Width: 3 + m_Height: 208 + - m_X: 505 + m_Y: 57 + m_Width: 6 + m_Height: 151 + - m_X: 503 + m_Y: 104 + m_Width: 8 + m_Height: 104 + - m_X: 502 + m_Y: 149 + m_Width: 9 + m_Height: 59 + - m_X: 454 + m_Y: 153 + m_Width: 4 + m_Height: 55 + - m_X: 453 + m_Y: 178 + m_Width: 5 + m_Height: 30 + - m_X: 422 + m_Y: 196 + m_Width: 8 + m_Height: 46 + - m_X: 382 + m_Y: 262 + m_Width: 40 + m_Height: 2 + - m_X: 281 + m_Y: 436 + m_Width: 26 + m_Height: 5 + - m_X: 444 + m_Y: 242 + m_Width: 9 + m_Height: 23 + - m_X: 385 + m_Y: 262 + m_Width: 37 + m_Height: 10 + - m_X: 327 + m_Y: 303 + m_Width: 58 + m_Height: 1 + - m_X: 363 + m_Y: 300 + m_Width: 22 + m_Height: 4 + - m_X: 319 + m_Y: 369 + m_Width: 13 + m_Height: 2 + - m_X: 369 + m_Y: 300 + m_Width: 16 + m_Height: 17 + - m_X: 429 + m_Y: 272 + m_Width: 15 + m_Height: 39 + - m_X: 510 + m_Y: 0 + m_Width: 1 + m_Height: 311 + - m_X: 500 + m_Y: 265 + m_Width: 11 + m_Height: 46 + - m_X: 369 + m_Y: 363 + m_Width: 41 + m_Height: 6 + - m_X: 410 + m_Y: 317 + m_Width: 19 + m_Height: 38 + - m_X: 494 + m_Y: 332 + m_Width: 17 + m_Height: 31 + - m_X: 495 + m_Y: 332 + m_Width: 16 + m_Height: 179 + - m_X: 453 + m_Y: 355 + m_Width: 20 + m_Height: 8 + - m_X: 332 + m_Y: 416 + m_Width: 41 + m_Height: 20 + - m_X: 373 + m_Y: 363 + m_Width: 37 + m_Height: 35 + - m_X: 364 + m_Y: 416 + m_Width: 9 + m_Height: 26 + - m_X: 260 + m_Y: 510 + m_Width: 251 + m_Height: 1 + - m_X: 260 + m_Y: 508 + m_Width: 104 + m_Height: 3 + - m_X: 307 + m_Y: 500 + m_Width: 57 + m_Height: 11 + - m_X: 326 + m_Y: 496 + m_Width: 38 + m_Height: 15 + - m_X: 404 + m_Y: 507 + m_Width: 107 + m_Height: 4 + - m_X: 485 + m_Y: 407 + m_Width: 26 + m_Height: 104 + - m_X: 415 + m_Y: 398 + m_Width: 38 + m_Height: 9 + - m_X: 415 + m_Y: 398 + m_Width: 30 + m_Height: 44 + - m_X: 445 + m_Y: 494 + m_Width: 66 + m_Height: 17 + - m_X: 484 + m_Y: 450 + m_Width: 27 + m_Height: 61 + m_fontInfo: + Name: + PointSize: 0 + Scale: 0 + CharacterCount: 0 + LineHeight: 0 + Baseline: 0 + Ascender: 0 + CapHeight: 0 + Descender: 0 + CenterLine: 0 + SuperscriptOffset: 0 + SubscriptOffset: 0 + SubSize: 0 + Underline: 0 + UnderlineThickness: 0 + strikethrough: 0 + strikethroughThickness: 0 + TabWidth: 0 + Padding: 0 + AtlasWidth: 0 + AtlasHeight: 0 + atlas: {fileID: 0} + m_AtlasWidth: 512 + m_AtlasHeight: 512 + m_AtlasPadding: 5 + m_AtlasRenderMode: 4165 + m_glyphInfoList: [] + m_KerningTable: + kerningPairs: [] + m_FontFeatureTable: + m_GlyphPairAdjustmentRecords: [] + fallbackFontAssets: [] + m_FallbackFontAssetTable: [] + m_CreationSettings: + sourceFontFileName: + sourceFontFileGUID: e00db9ee920964f58a0daa8e78ca6c4e + pointSizeSamplingMode: 0 + pointSize: 87 + padding: 5 + packingMode: 0 + atlasWidth: 512 + atlasHeight: 512 + characterSetSelectionMode: 0 + characterSequence: 32 - 126, 160, 8203, 8230, 9633 + referencedFontAssetGUID: + referencedTextAssetGUID: + fontStyle: 0 + fontStyleModifier: 0 + renderMode: 4165 + includeFontFeatures: 0 + m_FontWeightTable: + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + fontWeights: [] + normalStyle: 0 + normalSpacingOffset: 0 + boldStyle: 0.75 + boldSpacing: 7 + italicStyle: 35 + tabSize: 10 +--- !u!21 &5430614902480215695 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: KGPrimaryWhimsy SDF Material + m_Shader: {fileID: 4800000, guid: 68e6db2ebdc24f95958faec2be5558d6, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: -4571599219975028377} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _CullMode: 0 + - _Diffuse: 0.5 + - _FaceDilate: 0 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 6 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 0.8333333 + - _ScaleRatioB: 0.6770833 + - _ScaleRatioC: 0.6770833 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 512 + - _TextureWidth: 512 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} + m_BuildTextureStacks: [] diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials/Unicorn Fold - Display SDF.asset b/Assets/TextMesh Pro/Resources/Fonts & Materials/Unicorn Fold - Display SDF.asset new file mode 100644 index 0000000..25563b3 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/Unicorn Fold - Display SDF.asset @@ -0,0 +1,2740 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &-8391673362897697182 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Unicorn Fold - Display SDF Material + m_Shader: {fileID: 4800000, guid: 68e6db2ebdc24f95958faec2be5558d6, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 4630459078269078491} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _CullMode: 0 + - _Diffuse: 0.5 + - _FaceDilate: 0 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 6 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 1 + - _ScaleRatioB: 1 + - _ScaleRatioC: 1 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 512 + - _TextureWidth: 512 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} + m_BuildTextureStacks: [] +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 71c1514a6bd24e1e882cebbe1904ce04, type: 3} + m_Name: Unicorn Fold - Display SDF + m_EditorClassIdentifier: + hashCode: 0 + material: {fileID: -8391673362897697182} + materialHashCode: 0 + m_Version: 1.1.0 + m_SourceFontFileGUID: b3719c21c97934973897cf36693afbcf + m_SourceFontFile_EditorRef: {fileID: 12800000, guid: b3719c21c97934973897cf36693afbcf, type: 3} + m_SourceFontFile: {fileID: 0} + m_AtlasPopulationMode: 0 + m_FaceInfo: + m_FaceIndex: 0 + m_FamilyName: Unicorn Fold Display - Personal + m_StyleName: Display + m_PointSize: 80 + m_Scale: 1 + m_UnitsPerEM: 1020 + m_LineHeight: 89.803925 + m_AscentLine: 60.39216 + m_CapLine: 59 + m_MeanLine: 39 + m_Baseline: 0 + m_DescentLine: -19.607843 + m_SuperscriptOffset: 60.39216 + m_SuperscriptSize: 0.5 + m_SubscriptOffset: -19.607843 + m_SubscriptSize: 0.5 + m_UnderlineOffset: -9.803922 + m_UnderlineThickness: 3.9215686 + m_StrikethroughOffset: 15.6 + m_StrikethroughThickness: 3.9215686 + m_TabWidth: 20 + m_GlyphTable: + - m_Index: 3 + m_Metrics: + m_Width: 0 + m_Height: 0 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 0 + m_HorizontalAdvance: 19.609375 + m_GlyphRect: + m_X: 0 + m_Y: 0 + m_Width: 0 + m_Height: 0 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 4 + m_Metrics: + m_Width: 26.984375 + m_Height: 50.828125 + m_HorizontalBearingX: 0.546875 + m_HorizontalBearingY: 50.671875 + m_HorizontalAdvance: 27.21875 + m_GlyphRect: + m_X: 352 + m_Y: 274 + m_Width: 28 + m_Height: 52 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 5 + m_Metrics: + m_Width: 29.34375 + m_Height: 53.171875 + m_HorizontalBearingX: 4.78125 + m_HorizontalBearingY: 52.9375 + m_HorizontalAdvance: 37.09375 + m_GlyphRect: + m_X: 288 + m_Y: 220 + m_Width: 31 + m_Height: 54 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 6 + m_Metrics: + m_Width: 19.296875 + m_Height: 36.078125 + m_HorizontalBearingX: 3.0625 + m_HorizontalBearingY: 35.921875 + m_HorizontalAdvance: 24.9375 + m_GlyphRect: + m_X: 429 + m_Y: 349 + m_Width: 20 + m_Height: 37 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 7 + m_Metrics: + m_Width: 25.875 + m_Height: 65.5625 + m_HorizontalBearingX: 2.75 + m_HorizontalBearingY: 36.3125 + m_HorizontalAdvance: 33.015625 + m_GlyphRect: + m_X: 86 + m_Y: 6 + m_Width: 27 + m_Height: 67 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 8 + m_Metrics: + m_Width: 30.4375 + m_Height: 40.9375 + m_HorizontalBearingX: 3.921875 + m_HorizontalBearingY: 40.78125 + m_HorizontalAdvance: 38.4375 + m_GlyphRect: + m_X: 359 + m_Y: 464 + m_Width: 32 + m_Height: 42 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 9 + m_Metrics: + m_Width: 11.296875 + m_Height: 51.453125 + m_HorizontalBearingX: 4.234375 + m_HorizontalBearingY: 51.296875 + m_HorizontalAdvance: 17.875 + m_GlyphRect: + m_X: 295 + m_Y: 147 + m_Width: 12 + m_Height: 53 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 10 + m_Metrics: + m_Width: 21.09375 + m_Height: 38.03125 + m_HorizontalBearingX: 3.0625 + m_HorizontalBearingY: 37.875 + m_HorizontalAdvance: 26.671875 + m_GlyphRect: + m_X: 396 + m_Y: 349 + m_Width: 22 + m_Height: 39 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 11 + m_Metrics: + m_Width: 24.390625 + m_Height: 51.140625 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 50.671875 + m_HorizontalAdvance: 29.71875 + m_GlyphRect: + m_X: 354 + m_Y: 401 + m_Width: 25 + m_Height: 52 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 12 + m_Metrics: + m_Width: 28.078125 + m_Height: 50.828125 + m_HorizontalBearingX: 2.828125 + m_HorizontalBearingY: 50.671875 + m_HorizontalAdvance: 35.0625 + m_GlyphRect: + m_X: 330 + m_Y: 211 + m_Width: 29 + m_Height: 52 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 13 + m_Metrics: + m_Width: 28.234375 + m_Height: 50.828125 + m_HorizontalBearingX: 4.46875 + m_HorizontalBearingY: 50.671875 + m_HorizontalAdvance: 34.59375 + m_GlyphRect: + m_X: 312 + m_Y: 285 + m_Width: 29 + m_Height: 52 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 14 + m_Metrics: + m_Width: 26.671875 + m_Height: 36.703125 + m_HorizontalBearingX: 4.234375 + m_HorizontalBearingY: 36.546875 + m_HorizontalAdvance: 32.15625 + m_GlyphRect: + m_X: 417 + m_Y: 399 + m_Width: 27 + m_Height: 38 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 15 + m_Metrics: + m_Width: 20.234375 + m_Height: 36.078125 + m_HorizontalBearingX: 3.21875 + m_HorizontalBearingY: 35.921875 + m_HorizontalAdvance: 26.359375 + m_GlyphRect: + m_X: 364 + m_Y: 96 + m_Width: 21 + m_Height: 37 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 16 + m_Metrics: + m_Width: 45.796875 + m_Height: 36.546875 + m_HorizontalBearingX: 3.84375 + m_HorizontalBearingY: 36.390625 + m_HorizontalAdvance: 52.703125 + m_GlyphRect: + m_X: 443 + m_Y: 66 + m_Width: 47 + m_Height: 38 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 17 + m_Metrics: + m_Width: 30.4375 + m_Height: 41.09375 + m_HorizontalBearingX: 4.625 + m_HorizontalBearingY: 40.703125 + m_HorizontalAdvance: 38.59375 + m_GlyphRect: + m_X: 316 + m_Y: 464 + m_Width: 32 + m_Height: 42 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 18 + m_Metrics: + m_Width: 25.578125 + m_Height: 51.0625 + m_HorizontalBearingX: 4.703125 + m_HorizontalBearingY: 50.515625 + m_HorizontalAdvance: 30.046875 + m_GlyphRect: + m_X: 316 + m_Y: 401 + m_Width: 27 + m_Height: 52 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 19 + m_Metrics: + m_Width: 32.46875 + m_Height: 39.765625 + m_HorizontalBearingX: 0.9375 + m_HorizontalBearingY: 39.609375 + m_HorizontalAdvance: 33.40625 + m_GlyphRect: + m_X: 396 + m_Y: 105 + m_Width: 34 + m_Height: 41 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 20 + m_Metrics: + m_Width: 27.765625 + m_Height: 81.265625 + m_HorizontalBearingX: -13.25 + m_HorizontalBearingY: 50.4375 + m_HorizontalAdvance: 18.28125 + m_GlyphRect: + m_X: 6 + m_Y: 6 + m_Width: 29 + m_Height: 82 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 21 + m_Metrics: + m_Width: 50.59375 + m_Height: 40.9375 + m_HorizontalBearingX: 4.15625 + m_HorizontalBearingY: 40.703125 + m_HorizontalAdvance: 58.28125 + m_GlyphRect: + m_X: 312 + m_Y: 348 + m_Width: 51 + m_Height: 42 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 22 + m_Metrics: + m_Width: 28.46875 + m_Height: 40.46875 + m_HorizontalBearingX: 1.09375 + m_HorizontalBearingY: 40.15625 + m_HorizontalAdvance: 30.90625 + m_GlyphRect: + m_X: 339 + m_Y: 147 + m_Width: 29 + m_Height: 42 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 23 + m_Metrics: + m_Width: 33.34375 + m_Height: 40.15625 + m_HorizontalBearingX: 1.328125 + m_HorizontalBearingY: 40 + m_HorizontalAdvance: 34.125 + m_GlyphRect: + m_X: 396 + m_Y: 53 + m_Width: 34 + m_Height: 41 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 24 + m_Metrics: + m_Width: 9.109375 + m_Height: 50.828125 + m_HorizontalBearingX: 4.9375 + m_HorizontalBearingY: 50.671875 + m_HorizontalAdvance: 18.984375 + m_GlyphRect: + m_X: 374 + m_Y: 337 + m_Width: 11 + m_Height: 52 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 25 + m_Metrics: + m_Width: 26.96875 + m_Height: 38.90625 + m_HorizontalBearingX: 2.984375 + m_HorizontalBearingY: 38.671875 + m_HorizontalAdvance: 34.046875 + m_GlyphRect: + m_X: 325 + m_Y: 96 + m_Width: 28 + m_Height: 40 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 26 + m_Metrics: + m_Width: 29.171875 + m_Height: 40.46875 + m_HorizontalBearingX: 0.46875 + m_HorizontalBearingY: 40.234375 + m_HorizontalAdvance: 30.125 + m_GlyphRect: + m_X: 402 + m_Y: 462 + m_Width: 30 + m_Height: 42 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 27 + m_Metrics: + m_Width: 28.78125 + m_Height: 66.75 + m_HorizontalBearingX: 4.078125 + m_HorizontalBearingY: 34.984375 + m_HorizontalAdvance: 36.859375 + m_GlyphRect: + m_X: 60 + m_Y: 88 + m_Width: 29 + m_Height: 67 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 28 + m_Metrics: + m_Width: 27.765625 + m_Height: 70.828125 + m_HorizontalBearingX: 2.75 + m_HorizontalBearingY: 35.921875 + m_HorizontalAdvance: 34.28125 + m_GlyphRect: + m_X: 46 + m_Y: 6 + m_Width: 29 + m_Height: 71 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 29 + m_Metrics: + m_Width: 25.65625 + m_Height: 65.71875 + m_HorizontalBearingX: 4.46875 + m_HorizontalBearingY: 35.921875 + m_HorizontalAdvance: 32.390625 + m_GlyphRect: + m_X: 6 + m_Y: 262 + m_Width: 27 + m_Height: 66 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 30 + m_Metrics: + m_Width: 32.703125 + m_Height: 59.84375 + m_HorizontalBearingX: -0.625 + m_HorizontalBearingY: 59.53125 + m_HorizontalAdvance: 27.53125 + m_GlyphRect: + m_X: 180 + m_Y: 150 + m_Width: 34 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 31 + m_Metrics: + m_Width: 39.53125 + m_Height: 59.609375 + m_HorizontalBearingX: 4.546875 + m_HorizontalBearingY: 59.453125 + m_HorizontalAdvance: 46.125 + m_GlyphRect: + m_X: 126 + m_Y: 260 + m_Width: 41 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 32 + m_Metrics: + m_Width: 29.484375 + m_Height: 59.609375 + m_HorizontalBearingX: 3.6875 + m_HorizontalBearingY: 59.453125 + m_HorizontalAdvance: 33.796875 + m_GlyphRect: + m_X: 197 + m_Y: 78 + m_Width: 31 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 33 + m_Metrics: + m_Width: 25.40625 + m_Height: 59.765625 + m_HorizontalBearingX: 3.453125 + m_HorizontalBearingY: 59.609375 + m_HorizontalAdvance: 32.234375 + m_GlyphRect: + m_X: 239 + m_Y: 78 + m_Width: 26 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 34 + m_Metrics: + m_Width: 26.4375 + m_Height: 59.609375 + m_HorizontalBearingX: 4.9375 + m_HorizontalBearingY: 59.453125 + m_HorizontalAdvance: 36.15625 + m_GlyphRect: + m_X: 212 + m_Y: 330 + m_Width: 28 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 35 + m_Metrics: + m_Width: 19.59375 + m_Height: 59.609375 + m_HorizontalBearingX: 2.28125 + m_HorizontalBearingY: 59.453125 + m_HorizontalAdvance: 22.671875 + m_GlyphRect: + m_X: 251 + m_Y: 330 + m_Width: 20 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 36 + m_Metrics: + m_Width: 21.796875 + m_Height: 59.609375 + m_HorizontalBearingX: 3.84375 + m_HorizontalBearingY: 59.453125 + m_HorizontalAdvance: 29.171875 + m_GlyphRect: + m_X: 260 + m_Y: 6 + m_Width: 23 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 37 + m_Metrics: + m_Width: 29.09375 + m_Height: 59.6875 + m_HorizontalBearingX: 4.78125 + m_HorizontalBearingY: 59.453125 + m_HorizontalAdvance: 34.90625 + m_GlyphRect: + m_X: 131 + m_Y: 332 + m_Width: 30 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 38 + m_Metrics: + m_Width: 30.671875 + m_Height: 59.84375 + m_HorizontalBearingX: 4.3125 + m_HorizontalBearingY: 59.53125 + m_HorizontalAdvance: 36.546875 + m_GlyphRect: + m_X: 97 + m_Y: 406 + m_Width: 31 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 39 + m_Metrics: + m_Width: 30.046875 + m_Height: 59.453125 + m_HorizontalBearingX: 5.25 + m_HorizontalBearingY: 59.296875 + m_HorizontalAdvance: 34.828125 + m_GlyphRect: + m_X: 218 + m_Y: 6 + m_Width: 31 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 40 + m_Metrics: + m_Width: 37.96875 + m_Height: 59.453125 + m_HorizontalBearingX: 5.5625 + m_HorizontalBearingY: 59.296875 + m_HorizontalAdvance: 43.6875 + m_GlyphRect: + m_X: 100 + m_Y: 84 + m_Width: 39 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 41 + m_Metrics: + m_Width: 24.46875 + m_Height: 59.609375 + m_HorizontalBearingX: 3.6875 + m_HorizontalBearingY: 59.453125 + m_HorizontalAdvance: 31.53125 + m_GlyphRect: + m_X: 225 + m_Y: 150 + m_Width: 26 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 42 + m_Metrics: + m_Width: 42.125 + m_Height: 59.609375 + m_HorizontalBearingX: 4.78125 + m_HorizontalBearingY: 59.21875 + m_HorizontalAdvance: 51.0625 + m_GlyphRect: + m_X: 43 + m_Y: 413 + m_Width: 43 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 43 + m_Metrics: + m_Width: 26.75 + m_Height: 59.6875 + m_HorizontalBearingX: 4.625 + m_HorizontalBearingY: 59.453125 + m_HorizontalAdvance: 35.921875 + m_GlyphRect: + m_X: 179 + m_Y: 404 + m_Width: 28 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 44 + m_Metrics: + m_Width: 22.578125 + m_Height: 59.921875 + m_HorizontalBearingX: 3.375 + m_HorizontalBearingY: 59.6875 + m_HorizontalAdvance: 27.140625 + m_GlyphRect: + m_X: 218 + m_Y: 402 + m_Width: 23 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 45 + m_Metrics: + m_Width: 35.84375 + m_Height: 59.6875 + m_HorizontalBearingX: 1.25 + m_HorizontalBearingY: 59.53125 + m_HorizontalAdvance: 36.703125 + m_GlyphRect: + m_X: 132 + m_Y: 156 + m_Width: 37 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 46 + m_Metrics: + m_Width: 26.046875 + m_Height: 60.15625 + m_HorizontalBearingX: 1.25 + m_HorizontalBearingY: 59.84375 + m_HorizontalAdvance: 27.375 + m_GlyphRect: + m_X: 217 + m_Y: 258 + m_Width: 27 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 47 + m_Metrics: + m_Width: 45.1875 + m_Height: 59.453125 + m_HorizontalBearingX: 4.859375 + m_HorizontalBearingY: 59.296875 + m_HorizontalAdvance: 54.59375 + m_GlyphRect: + m_X: 68 + m_Y: 262 + m_Width: 47 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 48 + m_Metrics: + m_Width: 27.921875 + m_Height: 60.078125 + m_HorizontalBearingX: 1.640625 + m_HorizontalBearingY: 59.765625 + m_HorizontalAdvance: 30.90625 + m_GlyphRect: + m_X: 172 + m_Y: 332 + m_Width: 29 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 49 + m_Metrics: + m_Width: 40.953125 + m_Height: 59.6875 + m_HorizontalBearingX: 1.875 + m_HorizontalBearingY: 59.53125 + m_HorizontalAdvance: 41.40625 + m_GlyphRect: + m_X: 79 + m_Y: 166 + m_Width: 42 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 50 + m_Metrics: + m_Width: 33.265625 + m_Height: 60.15625 + m_HorizontalBearingX: 1.71875 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 34.28125 + m_GlyphRect: + m_X: 173 + m_Y: 6 + m_Width: 34 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 51 + m_Metrics: + m_Width: 40.953125 + m_Height: 59.6875 + m_HorizontalBearingX: 1.484375 + m_HorizontalBearingY: 59.53125 + m_HorizontalAdvance: 43.921875 + m_GlyphRect: + m_X: 78 + m_Y: 334 + m_Width: 42 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 52 + m_Metrics: + m_Width: 34.90625 + m_Height: 59.6875 + m_HorizontalBearingX: -0.15625 + m_HorizontalBearingY: 59.453125 + m_HorizontalAdvance: 33.40625 + m_GlyphRect: + m_X: 150 + m_Y: 78 + m_Width: 36 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 53 + m_Metrics: + m_Width: 37.734375 + m_Height: 59.6875 + m_HorizontalBearingX: 1.015625 + m_HorizontalBearingY: 59.53125 + m_HorizontalAdvance: 34.515625 + m_GlyphRect: + m_X: 124 + m_Y: 6 + m_Width: 38 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 54 + m_Metrics: + m_Width: 28.546875 + m_Height: 60 + m_HorizontalBearingX: 5.09375 + m_HorizontalBearingY: 59.84375 + m_HorizontalAdvance: 36.9375 + m_GlyphRect: + m_X: 139 + m_Y: 404 + m_Width: 29 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 55 + m_Metrics: + m_Width: 26.359375 + m_Height: 59.6875 + m_HorizontalBearingX: 3.765625 + m_HorizontalBearingY: 59.53125 + m_HorizontalAdvance: 30.90625 + m_GlyphRect: + m_X: 178 + m_Y: 258 + m_Width: 28 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 56 + m_Metrics: + m_Width: 44.3125 + m_Height: 32.390625 + m_HorizontalBearingX: 4.859375 + m_HorizontalBearingY: 45.09375 + m_HorizontalAdvance: 54.4375 + m_GlyphRect: + m_X: 339 + m_Y: 51 + m_Width: 46 + m_Height: 34 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 57 + m_Metrics: + m_Width: 44.3125 + m_Height: 32.390625 + m_HorizontalBearingX: 4.859375 + m_HorizontalBearingY: 45.09375 + m_HorizontalAdvance: 54.4375 + m_GlyphRect: + m_X: 339 + m_Y: 6 + m_Width: 46 + m_Height: 34 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 58 + m_Metrics: + m_Width: 44.3125 + m_Height: 32.390625 + m_HorizontalBearingX: 4.859375 + m_HorizontalBearingY: 45.09375 + m_HorizontalAdvance: 54.4375 + m_GlyphRect: + m_X: 443 + m_Y: 115 + m_Width: 46 + m_Height: 34 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 59 + m_Metrics: + m_Width: 44.3125 + m_Height: 32.390625 + m_HorizontalBearingX: 4.859375 + m_HorizontalBearingY: 45.09375 + m_HorizontalAdvance: 54.4375 + m_GlyphRect: + m_X: 443 + m_Y: 160 + m_Width: 46 + m_Height: 34 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 60 + m_Metrics: + m_Width: 44.3125 + m_Height: 32.390625 + m_HorizontalBearingX: 4.859375 + m_HorizontalBearingY: 45.09375 + m_HorizontalAdvance: 54.4375 + m_GlyphRect: + m_X: 443 + m_Y: 205 + m_Width: 46 + m_Height: 34 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 61 + m_Metrics: + m_Width: 44.3125 + m_Height: 32.390625 + m_HorizontalBearingX: 4.859375 + m_HorizontalBearingY: 45.09375 + m_HorizontalAdvance: 54.4375 + m_GlyphRect: + m_X: 443 + m_Y: 250 + m_Width: 46 + m_Height: 34 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 62 + m_Metrics: + m_Width: 44.3125 + m_Height: 32.390625 + m_HorizontalBearingX: 4.859375 + m_HorizontalBearingY: 45.09375 + m_HorizontalAdvance: 54.4375 + m_GlyphRect: + m_X: 443 + m_Y: 295 + m_Width: 46 + m_Height: 34 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 63 + m_Metrics: + m_Width: 44.3125 + m_Height: 32.390625 + m_HorizontalBearingX: 4.859375 + m_HorizontalBearingY: 45.09375 + m_HorizontalAdvance: 54.4375 + m_GlyphRect: + m_X: 460 + m_Y: 340 + m_Width: 46 + m_Height: 34 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 64 + m_Metrics: + m_Width: 44.3125 + m_Height: 32.390625 + m_HorizontalBearingX: 4.859375 + m_HorizontalBearingY: 45.09375 + m_HorizontalAdvance: 54.4375 + m_GlyphRect: + m_X: 460 + m_Y: 385 + m_Width: 46 + m_Height: 34 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 65 + m_Metrics: + m_Width: 44.3125 + m_Height: 32.390625 + m_HorizontalBearingX: 4.859375 + m_HorizontalBearingY: 45.09375 + m_HorizontalAdvance: 54.4375 + m_GlyphRect: + m_X: 455 + m_Y: 430 + m_Width: 46 + m_Height: 34 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 66 + m_Metrics: + m_Width: 38.90625 + m_Height: 18.203125 + m_HorizontalBearingX: 1.640625 + m_HorizontalBearingY: 31.6875 + m_HorizontalAdvance: 42.046875 + m_GlyphRect: + m_X: 167 + m_Y: 228 + m_Width: 40 + m_Height: 19 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 67 + m_Metrics: + m_Width: 11.921875 + m_Height: 61.96875 + m_HorizontalBearingX: 1.640625 + m_HorizontalBearingY: 58.203125 + m_HorizontalAdvance: 15.140625 + m_GlyphRect: + m_X: 44 + m_Y: 262 + m_Width: 13 + m_Height: 63 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 68 + m_Metrics: + m_Width: 23.296875 + m_Height: 62.125 + m_HorizontalBearingX: 1.484375 + m_HorizontalBearingY: 58.671875 + m_HorizontalAdvance: 26.75 + m_GlyphRect: + m_X: 43 + m_Y: 339 + m_Width: 24 + m_Height: 63 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 69 + m_Metrics: + m_Width: 60.25 + m_Height: 66.265625 + m_HorizontalBearingX: 1.953125 + m_HorizontalBearingY: 60.625 + m_HorizontalAdvance: 65.40625 + m_GlyphRect: + m_X: 6 + m_Y: 184 + m_Width: 62 + m_Height: 67 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 70 + m_Metrics: + m_Width: 56.234375 + m_Height: 47.21875 + m_HorizontalBearingX: 1.5625 + m_HorizontalBearingY: 57.09375 + m_HorizontalAdvance: 59.21875 + m_GlyphRect: + m_X: 443 + m_Y: 6 + m_Width: 57 + m_Height: 49 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 71 + m_Metrics: + m_Width: 41.8125 + m_Height: 73.109375 + m_HorizontalBearingX: 1.953125 + m_HorizontalBearingY: 62.984375 + m_HorizontalAdvance: 46.671875 + m_GlyphRect: + m_X: 6 + m_Y: 99 + m_Width: 43 + m_Height: 74 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 72 + m_Metrics: + m_Width: 51.921875 + m_Height: 59.375 + m_HorizontalBearingX: 1.5625 + m_HorizontalBearingY: 60.703125 + m_HorizontalAdvance: 55.0625 + m_GlyphRect: + m_X: 252 + m_Y: 402 + m_Width: 53 + m_Height: 60 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 73 + m_Metrics: + m_Width: 26.046875 + m_Height: 30.046875 + m_HorizontalBearingX: 1.484375 + m_HorizontalBearingY: 58.59375 + m_HorizontalAdvance: 29.09375 + m_GlyphRect: + m_X: 218 + m_Y: 474 + m_Width: 27 + m_Height: 31 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 74 + m_Metrics: + m_Width: 36.796875 + m_Height: 57.40625 + m_HorizontalBearingX: 1.875 + m_HorizontalBearingY: 60.859375 + m_HorizontalAdvance: 40.46875 + m_GlyphRect: + m_X: 276 + m_Y: 78 + m_Width: 38 + m_Height: 58 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 75 + m_Metrics: + m_Width: 28.40625 + m_Height: 31.140625 + m_HorizontalBearingX: 1.640625 + m_HorizontalBearingY: 58.046875 + m_HorizontalAdvance: 30.671875 + m_GlyphRect: + m_X: 256 + m_Y: 473 + m_Width: 30 + m_Height: 33 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 76 + m_Metrics: + m_Width: 18.515625 + m_Height: 56.78125 + m_HorizontalBearingX: 1.5625 + m_HorizontalBearingY: 57.484375 + m_HorizontalAdvance: 21.5625 + m_GlyphRect: + m_X: 294 + m_Y: 6 + m_Width: 20 + m_Height: 58 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 77 + m_Metrics: + m_Width: 18.4375 + m_Height: 56.78125 + m_HorizontalBearingX: 1.5625 + m_HorizontalBearingY: 57.484375 + m_HorizontalAdvance: 21.5625 + m_GlyphRect: + m_X: 282 + m_Y: 292 + m_Width: 19 + m_Height: 58 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 78 + m_Metrics: + m_Width: 20.796875 + m_Height: 58.578125 + m_HorizontalBearingX: 1.5625 + m_HorizontalBearingY: 57.640625 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 255 + m_Y: 222 + m_Width: 22 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 79 + m_Metrics: + m_Width: 21.03125 + m_Height: 58.578125 + m_HorizontalBearingX: 1.484375 + m_HorizontalBearingY: 57.640625 + m_HorizontalAdvance: 24.234375 + m_GlyphRect: + m_X: 262 + m_Y: 150 + m_Width: 22 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 80 + m_Metrics: + m_Width: 24.953125 + m_Height: 64.234375 + m_HorizontalBearingX: 1.875 + m_HorizontalBearingY: 61.328125 + m_HorizontalAdvance: 28.46875 + m_GlyphRect: + m_X: 6 + m_Y: 339 + m_Width: 26 + m_Height: 65 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 81 + m_Metrics: + m_Width: 24.71875 + m_Height: 64.15625 + m_HorizontalBearingX: 1.640625 + m_HorizontalBearingY: 61.25 + m_HorizontalAdvance: 28.234375 + m_GlyphRect: + m_X: 6 + m_Y: 415 + m_Width: 26 + m_Height: 65 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 84 + m_Metrics: + m_Width: 11.6875 + m_Height: 11.140625 + m_HorizontalBearingX: 1.875 + m_HorizontalBearingY: 13.015625 + m_HorizontalAdvance: 15.140625 + m_GlyphRect: + m_X: 31 + m_Y: 491 + m_Width: 13 + m_Height: 13 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 85 + m_Metrics: + m_Width: 13.65625 + m_Height: 21.328125 + m_HorizontalBearingX: 1.484375 + m_HorizontalBearingY: 12.234375 + m_HorizontalAdvance: 16.78125 + m_GlyphRect: + m_X: 144 + m_Y: 476 + m_Width: 15 + m_Height: 23 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 86 + m_Metrics: + m_Width: 14.671875 + m_Height: 50.1875 + m_HorizontalBearingX: 1.5625 + m_HorizontalBearingY: 41.640625 + m_HorizontalAdvance: 17.796875 + m_GlyphRect: + m_X: 390 + m_Y: 400 + m_Width: 16 + m_Height: 51 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 87 + m_Metrics: + m_Width: 11.296875 + m_Height: 40.703125 + m_HorizontalBearingX: 1.5625 + m_HorizontalBearingY: 41.640625 + m_HorizontalAdvance: 14.4375 + m_GlyphRect: + m_X: 370 + m_Y: 200 + m_Width: 12 + m_Height: 42 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 91 + m_Metrics: + m_Width: 48.796875 + m_Height: 9.953125 + m_HorizontalBearingX: 1.484375 + m_HorizontalBearingY: 8.625 + m_HorizontalAdvance: 51.84375 + m_GlyphRect: + m_X: 79 + m_Y: 238 + m_Width: 50 + m_Height: 11 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 93 + m_Metrics: + m_Width: 34.671875 + m_Height: 34.671875 + m_HorizontalBearingX: 1.5625 + m_HorizontalBearingY: 42.515625 + m_HorizontalAdvance: 37.875 + m_GlyphRect: + m_X: 396 + m_Y: 6 + m_Width: 36 + m_Height: 36 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 97 + m_Metrics: + m_Width: 34.75 + m_Height: 26.828125 + m_HorizontalBearingX: 1.5625 + m_HorizontalBearingY: 35.375 + m_HorizontalAdvance: 37.875 + m_GlyphRect: + m_X: 97 + m_Y: 478 + m_Width: 36 + m_Height: 28 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 101 + m_Metrics: + m_Width: 14.75 + m_Height: 19.765625 + m_HorizontalBearingX: 1.5625 + m_HorizontalBearingY: 57.25 + m_HorizontalAdvance: 17.875 + m_GlyphRect: + m_X: 140 + m_Y: 228 + m_Width: 16 + m_Height: 21 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 102 + m_Metrics: + m_Width: 29.65625 + m_Height: 19.84375 + m_HorizontalBearingX: 1.5625 + m_HorizontalBearingY: 57.25 + m_HorizontalAdvance: 32.78125 + m_GlyphRect: + m_X: 55 + m_Y: 485 + m_Width: 31 + m_Height: 21 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 104 + m_Metrics: + m_Width: 31.84375 + m_Height: 35.6875 + m_HorizontalBearingX: 1.875 + m_HorizontalBearingY: 39.140625 + m_HorizontalAdvance: 35.453125 + m_GlyphRect: + m_X: 396 + m_Y: 157 + m_Width: 33 + m_Height: 37 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 105 + m_Metrics: + m_Width: 31.84375 + m_Height: 35.84375 + m_HorizontalBearingX: 2.515625 + m_HorizontalBearingY: 39.296875 + m_HorizontalAdvance: 36.390625 + m_GlyphRect: + m_X: 396 + m_Y: 205 + m_Width: 33 + m_Height: 37 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 110 + m_Metrics: + m_Width: 31.296875 + m_Height: 35.765625 + m_HorizontalBearingX: 1.5625 + m_HorizontalBearingY: 36.625 + m_HorizontalAdvance: 34.046875 + m_GlyphRect: + m_X: 396 + m_Y: 301 + m_Width: 32 + m_Height: 37 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 111 + m_Metrics: + m_Width: 9.265625 + m_Height: 51.84375 + m_HorizontalBearingX: 1.71875 + m_HorizontalBearingY: 46.671875 + m_HorizontalAdvance: 12.546875 + m_GlyphRect: + m_X: 318 + m_Y: 147 + m_Width: 10 + m_Height: 53 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 112 + m_Metrics: + m_Width: 30.75 + m_Height: 35.6875 + m_HorizontalBearingX: 1.796875 + m_HorizontalBearingY: 36.546875 + m_HorizontalAdvance: 34.125 + m_GlyphRect: + m_X: 396 + m_Y: 253 + m_Width: 32 + m_Height: 37 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 124 + m_Metrics: + m_Width: 22.671875 + m_Height: 7.21875 + m_HorizontalBearingX: 4.625 + m_HorizontalBearingY: 28.46875 + m_HorizontalAdvance: 31.921875 + m_GlyphRect: + m_X: 170 + m_Y: 496 + m_Width: 24 + m_Height: 8 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 141 + m_Metrics: + m_Width: 29.890625 + m_Height: 8.859375 + m_HorizontalBearingX: 1.5625 + m_HorizontalBearingY: 12.859375 + m_HorizontalAdvance: 33.015625 + m_GlyphRect: + m_X: 170 + m_Y: 476 + m_Width: 31 + m_Height: 9 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + - m_Index: 147 + m_Metrics: + m_Width: 13.03125 + m_Height: 14.203125 + m_HorizontalBearingX: 1.484375 + m_HorizontalBearingY: 38.59375 + m_HorizontalAdvance: 16.234375 + m_GlyphRect: + m_X: 6 + m_Y: 491 + m_Width: 14 + m_Height: 15 + m_Scale: 1 + m_AtlasIndex: 0 + m_ClassDefinitionType: 0 + m_CharacterTable: + - m_ElementType: 1 + m_Unicode: 32 + m_GlyphIndex: 3 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 33 + m_GlyphIndex: 67 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 34 + m_GlyphIndex: 102 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 35 + m_GlyphIndex: 70 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 36 + m_GlyphIndex: 71 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 37 + m_GlyphIndex: 72 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 38 + m_GlyphIndex: 74 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 39 + m_GlyphIndex: 101 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 40 + m_GlyphIndex: 76 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 41 + m_GlyphIndex: 77 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 42 + m_GlyphIndex: 75 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 43 + m_GlyphIndex: 93 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 44 + m_GlyphIndex: 85 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 45 + m_GlyphIndex: 124 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 46 + m_GlyphIndex: 84 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 47 + m_GlyphIndex: 112 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 48 + m_GlyphIndex: 57 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 49 + m_GlyphIndex: 56 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 50 + m_GlyphIndex: 58 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 51 + m_GlyphIndex: 59 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 52 + m_GlyphIndex: 60 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 53 + m_GlyphIndex: 61 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 54 + m_GlyphIndex: 62 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 55 + m_GlyphIndex: 63 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 56 + m_GlyphIndex: 64 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 57 + m_GlyphIndex: 65 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 58 + m_GlyphIndex: 87 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 59 + m_GlyphIndex: 86 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 60 + m_GlyphIndex: 104 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 61 + m_GlyphIndex: 97 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 62 + m_GlyphIndex: 105 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 63 + m_GlyphIndex: 68 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 64 + m_GlyphIndex: 69 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 65 + m_GlyphIndex: 51 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 66 + m_GlyphIndex: 40 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 67 + m_GlyphIndex: 36 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 68 + m_GlyphIndex: 54 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 69 + m_GlyphIndex: 32 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 70 + m_GlyphIndex: 44 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 71 + m_GlyphIndex: 55 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 72 + m_GlyphIndex: 31 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 73 + m_GlyphIndex: 35 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 74 + m_GlyphIndex: 46 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 75 + m_GlyphIndex: 37 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 76 + m_GlyphIndex: 50 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 77 + m_GlyphIndex: 47 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 78 + m_GlyphIndex: 43 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 79 + m_GlyphIndex: 41 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 80 + m_GlyphIndex: 39 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 81 + m_GlyphIndex: 33 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 82 + m_GlyphIndex: 38 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 83 + m_GlyphIndex: 48 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 84 + m_GlyphIndex: 30 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 85 + m_GlyphIndex: 34 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 86 + m_GlyphIndex: 49 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 87 + m_GlyphIndex: 42 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 88 + m_GlyphIndex: 45 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 89 + m_GlyphIndex: 53 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 90 + m_GlyphIndex: 52 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 91 + m_GlyphIndex: 78 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 92 + m_GlyphIndex: 110 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 93 + m_GlyphIndex: 79 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 94 + m_GlyphIndex: 73 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 95 + m_GlyphIndex: 91 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 96 + m_GlyphIndex: 147 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 97 + m_GlyphIndex: 25 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 98 + m_GlyphIndex: 13 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 99 + m_GlyphIndex: 10 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 100 + m_GlyphIndex: 12 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 101 + m_GlyphIndex: 6 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 102 + m_GlyphIndex: 18 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 103 + m_GlyphIndex: 28 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 104 + m_GlyphIndex: 5 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 105 + m_GlyphIndex: 9 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 106 + m_GlyphIndex: 20 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 107 + m_GlyphIndex: 11 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 108 + m_GlyphIndex: 24 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 109 + m_GlyphIndex: 21 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 110 + m_GlyphIndex: 17 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 111 + m_GlyphIndex: 15 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 112 + m_GlyphIndex: 29 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 113 + m_GlyphIndex: 7 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 114 + m_GlyphIndex: 14 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 115 + m_GlyphIndex: 22 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 116 + m_GlyphIndex: 4 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 117 + m_GlyphIndex: 8 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 118 + m_GlyphIndex: 23 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 119 + m_GlyphIndex: 16 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 120 + m_GlyphIndex: 19 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 121 + m_GlyphIndex: 27 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 122 + m_GlyphIndex: 26 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 123 + m_GlyphIndex: 80 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 124 + m_GlyphIndex: 111 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 125 + m_GlyphIndex: 81 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 126 + m_GlyphIndex: 66 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8230 + m_GlyphIndex: 141 + m_Scale: 1 + m_AtlasTextures: + - {fileID: 4630459078269078491} + m_AtlasTextureIndex: 0 + m_IsMultiAtlasTexturesEnabled: 0 + m_ClearDynamicDataOnBuild: 0 + m_UsedGlyphRects: + - m_X: 0 + m_Y: 0 + m_Width: 40 + m_Height: 93 + - m_X: 0 + m_Y: 93 + m_Width: 54 + m_Height: 85 + - m_X: 40 + m_Y: 0 + m_Width: 40 + m_Height: 82 + - m_X: 0 + m_Y: 178 + m_Width: 73 + m_Height: 78 + - m_X: 54 + m_Y: 82 + m_Width: 40 + m_Height: 78 + - m_X: 80 + m_Y: 0 + m_Width: 38 + m_Height: 78 + - m_X: 0 + m_Y: 256 + m_Width: 38 + m_Height: 77 + - m_X: 0 + m_Y: 333 + m_Width: 37 + m_Height: 76 + - m_X: 0 + m_Y: 409 + m_Width: 37 + m_Height: 76 + - m_X: 0 + m_Y: 485 + m_Width: 25 + m_Height: 26 + - m_X: 25 + m_Y: 485 + m_Width: 24 + m_Height: 24 + - m_X: 37 + m_Y: 333 + m_Width: 35 + m_Height: 74 + - m_X: 38 + m_Y: 256 + m_Width: 24 + m_Height: 74 + - m_X: 62 + m_Y: 256 + m_Width: 58 + m_Height: 72 + - m_X: 37 + m_Y: 407 + m_Width: 54 + m_Height: 72 + - m_X: 49 + m_Y: 479 + m_Width: 42 + m_Height: 32 + - m_X: 72 + m_Y: 328 + m_Width: 53 + m_Height: 72 + - m_X: 73 + m_Y: 160 + m_Width: 53 + m_Height: 72 + - m_X: 73 + m_Y: 232 + m_Width: 61 + m_Height: 22 + - m_X: 120 + m_Y: 254 + m_Width: 52 + m_Height: 72 + - m_X: 94 + m_Y: 78 + m_Width: 50 + m_Height: 72 + - m_X: 118 + m_Y: 0 + m_Width: 49 + m_Height: 72 + - m_X: 126 + m_Y: 150 + m_Width: 48 + m_Height: 72 + - m_X: 134 + m_Y: 222 + m_Width: 27 + m_Height: 32 + - m_X: 161 + m_Y: 222 + m_Width: 51 + m_Height: 30 + - m_X: 144 + m_Y: 72 + m_Width: 47 + m_Height: 72 + - m_X: 167 + m_Y: 0 + m_Width: 45 + m_Height: 72 + - m_X: 174 + m_Y: 144 + m_Width: 45 + m_Height: 72 + - m_X: 191 + m_Y: 72 + m_Width: 42 + m_Height: 72 + - m_X: 212 + m_Y: 0 + m_Width: 42 + m_Height: 72 + - m_X: 91 + m_Y: 400 + m_Width: 42 + m_Height: 72 + - m_X: 91 + m_Y: 472 + m_Width: 47 + m_Height: 39 + - m_X: 125 + m_Y: 326 + m_Width: 41 + m_Height: 72 + - m_X: 133 + m_Y: 398 + m_Width: 40 + m_Height: 72 + - m_X: 166 + m_Y: 326 + m_Width: 40 + m_Height: 72 + - m_X: 172 + m_Y: 252 + m_Width: 39 + m_Height: 72 + - m_X: 138 + m_Y: 470 + m_Width: 26 + m_Height: 34 + - m_X: 164 + m_Y: 470 + m_Width: 42 + m_Height: 20 + - m_X: 173 + m_Y: 398 + m_Width: 39 + m_Height: 72 + - m_X: 206 + m_Y: 324 + m_Width: 39 + m_Height: 72 + - m_X: 211 + m_Y: 252 + m_Width: 38 + m_Height: 72 + - m_X: 164 + m_Y: 490 + m_Width: 35 + m_Height: 19 + - m_X: 219 + m_Y: 144 + m_Width: 37 + m_Height: 72 + - m_X: 233 + m_Y: 72 + m_Width: 37 + m_Height: 72 + - m_X: 254 + m_Y: 0 + m_Width: 34 + m_Height: 72 + - m_X: 212 + m_Y: 396 + m_Width: 34 + m_Height: 72 + - m_X: 245 + m_Y: 324 + m_Width: 31 + m_Height: 72 + - m_X: 212 + m_Y: 468 + m_Width: 38 + m_Height: 42 + - m_X: 246 + m_Y: 396 + m_Width: 64 + m_Height: 71 + - m_X: 250 + m_Y: 467 + m_Width: 41 + m_Height: 44 + - m_X: 249 + m_Y: 216 + m_Width: 33 + m_Height: 70 + - m_X: 256 + m_Y: 144 + m_Width: 33 + m_Height: 70 + - m_X: 270 + m_Y: 72 + m_Width: 49 + m_Height: 69 + - m_X: 288 + m_Y: 0 + m_Width: 31 + m_Height: 69 + - m_X: 276 + m_Y: 286 + m_Width: 30 + m_Height: 69 + - m_X: 282 + m_Y: 214 + m_Width: 42 + m_Height: 65 + - m_X: 289 + m_Y: 141 + m_Width: 23 + m_Height: 64 + - m_X: 312 + m_Y: 141 + m_Width: 21 + m_Height: 64 + - m_X: 306 + m_Y: 279 + m_Width: 40 + m_Height: 63 + - m_X: 306 + m_Y: 342 + m_Width: 62 + m_Height: 53 + - m_X: 324 + m_Y: 205 + m_Width: 40 + m_Height: 63 + - m_X: 346 + m_Y: 268 + m_Width: 39 + m_Height: 63 + - m_X: 310 + m_Y: 395 + m_Width: 38 + m_Height: 63 + - m_X: 310 + m_Y: 458 + m_Width: 43 + m_Height: 53 + - m_X: 348 + m_Y: 395 + m_Width: 36 + m_Height: 63 + - m_X: 353 + m_Y: 458 + m_Width: 43 + m_Height: 53 + - m_X: 368 + m_Y: 331 + m_Width: 22 + m_Height: 63 + - m_X: 384 + m_Y: 394 + m_Width: 27 + m_Height: 62 + - m_X: 396 + m_Y: 456 + m_Width: 41 + m_Height: 53 + - m_X: 437 + m_Y: 0 + m_Width: 68 + m_Height: 60 + - m_X: 390 + m_Y: 0 + m_Width: 47 + m_Height: 47 + - m_X: 333 + m_Y: 0 + m_Width: 57 + m_Height: 45 + - m_X: 333 + m_Y: 45 + m_Width: 57 + m_Height: 45 + - m_X: 319 + m_Y: 90 + m_Width: 39 + m_Height: 51 + - m_X: 390 + m_Y: 47 + m_Width: 45 + m_Height: 52 + - m_X: 358 + m_Y: 90 + m_Width: 32 + m_Height: 48 + - m_X: 333 + m_Y: 141 + m_Width: 40 + m_Height: 53 + - m_X: 437 + m_Y: 60 + m_Width: 58 + m_Height: 49 + - m_X: 390 + m_Y: 99 + m_Width: 45 + m_Height: 52 + - m_X: 437 + m_Y: 109 + m_Width: 57 + m_Height: 45 + - m_X: 390 + m_Y: 151 + m_Width: 44 + m_Height: 48 + - m_X: 364 + m_Y: 194 + m_Width: 23 + m_Height: 53 + - m_X: 437 + m_Y: 154 + m_Width: 57 + m_Height: 45 + - m_X: 437 + m_Y: 199 + m_Width: 57 + m_Height: 45 + - m_X: 390 + m_Y: 199 + m_Width: 44 + m_Height: 48 + - m_X: 437 + m_Y: 244 + m_Width: 57 + m_Height: 45 + - m_X: 390 + m_Y: 247 + m_Width: 43 + m_Height: 48 + - m_X: 437 + m_Y: 289 + m_Width: 57 + m_Height: 45 + - m_X: 390 + m_Y: 295 + m_Width: 43 + m_Height: 48 + - m_X: 390 + m_Y: 343 + m_Width: 33 + m_Height: 50 + - m_X: 411 + m_Y: 393 + m_Width: 38 + m_Height: 49 + - m_X: 423 + m_Y: 343 + m_Width: 31 + m_Height: 48 + - m_X: 454 + m_Y: 334 + m_Width: 57 + m_Height: 45 + - m_X: 454 + m_Y: 379 + m_Width: 57 + m_Height: 45 + - m_X: 449 + m_Y: 424 + m_Width: 57 + m_Height: 45 + m_FreeGlyphRects: + - m_X: 40 + m_Y: 82 + m_Width: 14 + m_Height: 11 + - m_X: 25 + m_Y: 509 + m_Width: 24 + m_Height: 2 + - m_X: 37 + m_Y: 479 + m_Width: 12 + m_Height: 6 + - m_X: 38 + m_Y: 330 + m_Width: 34 + m_Height: 3 + - m_X: 62 + m_Y: 328 + m_Width: 10 + m_Height: 5 + - m_X: 54 + m_Y: 160 + m_Width: 19 + m_Height: 18 + - m_X: 73 + m_Y: 254 + m_Width: 47 + m_Height: 2 + - m_X: 80 + m_Y: 78 + m_Width: 14 + m_Height: 4 + - m_X: 94 + m_Y: 150 + m_Width: 32 + m_Height: 10 + - m_X: 126 + m_Y: 222 + m_Width: 8 + m_Height: 10 + - m_X: 118 + m_Y: 72 + m_Width: 26 + m_Height: 6 + - m_X: 144 + m_Y: 144 + m_Width: 30 + m_Height: 6 + - m_X: 72 + m_Y: 400 + m_Width: 19 + m_Height: 7 + - m_X: 120 + m_Y: 326 + m_Width: 5 + m_Height: 2 + - m_X: 125 + m_Y: 398 + m_Width: 8 + m_Height: 2 + - m_X: 161 + m_Y: 252 + m_Width: 11 + m_Height: 2 + - m_X: 133 + m_Y: 470 + m_Width: 5 + m_Height: 2 + - m_X: 172 + m_Y: 324 + m_Width: 34 + m_Height: 2 + - m_X: 138 + m_Y: 504 + m_Width: 26 + m_Height: 7 + - m_X: 206 + m_Y: 396 + m_Width: 6 + m_Height: 2 + - m_X: 206 + m_Y: 470 + m_Width: 6 + m_Height: 41 + - m_X: 138 + m_Y: 509 + m_Width: 74 + m_Height: 2 + - m_X: 199 + m_Y: 490 + m_Width: 13 + m_Height: 21 + - m_X: 138 + m_Y: 510 + m_Width: 112 + m_Height: 1 + - m_X: 246 + m_Y: 467 + m_Width: 4 + m_Height: 1 + - m_X: 174 + m_Y: 216 + m_Width: 75 + m_Height: 6 + - m_X: 212 + m_Y: 216 + m_Width: 37 + m_Height: 36 + - m_X: 249 + m_Y: 286 + m_Width: 27 + m_Height: 38 + - m_X: 256 + m_Y: 214 + m_Width: 26 + m_Height: 2 + - m_X: 270 + m_Y: 141 + m_Width: 19 + m_Height: 3 + - m_X: 282 + m_Y: 279 + m_Width: 24 + m_Height: 7 + - m_X: 276 + m_Y: 355 + m_Width: 30 + m_Height: 41 + - m_X: 289 + m_Y: 205 + m_Width: 35 + m_Height: 9 + - m_X: 324 + m_Y: 268 + m_Width: 22 + m_Height: 11 + - m_X: 276 + m_Y: 395 + m_Width: 34 + m_Height: 1 + - m_X: 291 + m_Y: 467 + m_Width: 19 + m_Height: 44 + - m_X: 346 + m_Y: 331 + m_Width: 22 + m_Height: 11 + - m_X: 368 + m_Y: 394 + m_Width: 16 + m_Height: 1 + - m_X: 396 + m_Y: 509 + m_Width: 115 + m_Height: 2 + - m_X: 384 + m_Y: 456 + m_Width: 12 + m_Height: 2 + - m_X: 288 + m_Y: 69 + m_Width: 45 + m_Height: 3 + - m_X: 319 + m_Y: 0 + m_Width: 14 + m_Height: 90 + - m_X: 358 + m_Y: 138 + m_Width: 32 + m_Height: 3 + - m_X: 387 + m_Y: 138 + m_Width: 3 + m_Height: 193 + - m_X: 373 + m_Y: 138 + m_Width: 17 + m_Height: 56 + - m_X: 333 + m_Y: 194 + m_Width: 31 + m_Height: 11 + - m_X: 364 + m_Y: 247 + m_Width: 26 + m_Height: 21 + - m_X: 385 + m_Y: 247 + m_Width: 5 + m_Height: 84 + - m_X: 390 + m_Y: 393 + m_Width: 21 + m_Height: 1 + - m_X: 435 + m_Y: 47 + m_Width: 2 + m_Height: 296 + - m_X: 434 + m_Y: 151 + m_Width: 3 + m_Height: 192 + - m_X: 433 + m_Y: 247 + m_Width: 4 + m_Height: 96 + - m_X: 505 + m_Y: 0 + m_Width: 6 + m_Height: 334 + - m_X: 495 + m_Y: 60 + m_Width: 16 + m_Height: 274 + - m_X: 494 + m_Y: 109 + m_Width: 17 + m_Height: 225 + - m_X: 433 + m_Y: 334 + m_Width: 21 + m_Height: 9 + - m_X: 423 + m_Y: 391 + m_Width: 31 + m_Height: 2 + - m_X: 437 + m_Y: 469 + m_Width: 74 + m_Height: 42 + - m_X: 437 + m_Y: 442 + m_Width: 12 + m_Height: 69 + - m_X: 411 + m_Y: 442 + m_Width: 38 + m_Height: 14 + - m_X: 506 + m_Y: 424 + m_Width: 5 + m_Height: 87 + - m_X: 449 + m_Y: 391 + m_Width: 5 + m_Height: 33 + m_fontInfo: + Name: + PointSize: 0 + Scale: 0 + CharacterCount: 0 + LineHeight: 0 + Baseline: 0 + Ascender: 0 + CapHeight: 0 + Descender: 0 + CenterLine: 0 + SuperscriptOffset: 0 + SubscriptOffset: 0 + SubSize: 0 + Underline: 0 + UnderlineThickness: 0 + strikethrough: 0 + strikethroughThickness: 0 + TabWidth: 0 + Padding: 0 + AtlasWidth: 0 + AtlasHeight: 0 + atlas: {fileID: 0} + m_AtlasWidth: 512 + m_AtlasHeight: 512 + m_AtlasPadding: 5 + m_AtlasRenderMode: 4165 + m_glyphInfoList: [] + m_KerningTable: + kerningPairs: [] + m_FontFeatureTable: + m_GlyphPairAdjustmentRecords: [] + fallbackFontAssets: [] + m_FallbackFontAssetTable: [] + m_CreationSettings: + sourceFontFileName: + sourceFontFileGUID: b3719c21c97934973897cf36693afbcf + pointSizeSamplingMode: 0 + pointSize: 80 + padding: 5 + packingMode: 0 + atlasWidth: 512 + atlasHeight: 512 + characterSetSelectionMode: 0 + characterSequence: 32 - 126, 160, 8203, 8230, 9633 + referencedFontAssetGUID: + referencedTextAssetGUID: + fontStyle: 0 + fontStyleModifier: 0 + renderMode: 4165 + includeFontFeatures: 0 + m_FontWeightTable: + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + fontWeights: [] + normalStyle: 0 + normalSpacingOffset: 0 + boldStyle: 0.75 + boldSpacing: 7 + italicStyle: 35 + tabSize: 10 +--- !u!28 &4630459078269078491 +Texture2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Unicorn Fold - Display SDF Atlas + m_ImageContentsHash: + serializedVersion: 2 + Hash: 00000000000000000000000000000000 + m_ForcedFallbackFormat: 4 + m_DownscaleFallback: 0 + m_IsAlphaChannelOptional: 0 + serializedVersion: 2 + m_Width: 512 + m_Height: 512 + m_CompleteImageSize: 262144 + m_MipsStripped: 0 + m_TextureFormat: 1 + m_MipCount: 1 + m_IsReadable: 0 + m_IsPreProcessed: 0 + m_IgnoreMipmapLimit: 0 + m_MipmapLimitGroupName: + m_StreamingMipmaps: 0 + m_StreamingMipmapsPriority: 0 + m_VTOnly: 0 + m_AlphaIsTransparency: 0 + m_ImageCount: 1 + m_TextureDimension: 2 + m_TextureSettings: + serializedVersion: 2 + m_FilterMode: 1 + m_Aniso: 1 + m_MipBias: 0 + m_WrapU: 0 + m_WrapV: 0 + m_WrapW: 0 + m_LightmapFormat: 0 + m_ColorSpace: 0 + m_PlatformBlob: + image data: 262144 + _typelessdata: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080b11161a1c1b19140d0b0500000000000000000000000000000000000000000000000000000000060c0e151a1d1d1b17100b070000000000000000000000000000000000000000000000000000000000000000000000000000050b0d0f0d0b050000000000000000000000000000000000030a0c0d0b080100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070b0b0c0c0b0b0b0c0c0c0d0d0e0e0d0d0c0a030002000000000000000000000000000000000000070b0d0d0b080100000000000000000000000000000000000000000000000000000000000000000000000000000000000002090b0d0c0a0400000000000000000000000000000000000000000000000000050b0d100e0c060000000000000000000000000000000000000000000000000000000000000000070d0f0d070d0f0f0d0f0d0c100c0b100d0b0f0d0f0d0e0e0f0e0c0a0c0e0f0d0b100c0d0f0e0c0600000000000000000000000000000000000000000000000000000000000000040a0c0d0b080200000000000000000000000000000000000000000000000000000000000000000002080b0d0b090300000000000000000000000002090b0d0b08010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008141c20262c2f31302e29221f180d03000000000000000000000000000000000000000000000000050e1920232a2f3232302c25201c130800000000000000000000000000000000000000000000000000000000000000000000050d192022252220190e0700000000000000000000000000030b171e2122201c1408000000000000000000000000000000000000000000000000000000000000000000000000000000060b0d1418131c20212121202021212122222223232322211e161b17140f0b0801000000000000000000000008131c202222201d1409000000000000000000000000000000000000000000000000000000000000000000000000000000090a161e2122221f180c07000000000000000000000000000000000000000000050d1920222523211a0f0700000000000000000000000000000000000000000000000000000000010f1a2124211b222424212421212521202522202422242124232423211f21232422202522222423211a0f01000000000000000000000000000000000000000000000000000000080c171f2122201d15090100000000000000000000000000000000000000000000000000000000000209151d2022211e160a060000000000000000040a151d2022201d1509030000000000000000000000000000000000000000000000000000000000000000000000000000000000000112182630353b41444646433e37342a1e160b000000000000000000000000000000000000000000000d18202c35383f45474845423a353025181201000000000000000000000000000000000000000000000000000000000000000d19202b34383a38352b211a0f01000000000000000000000b161e293336383530261812040000000000000000000000000000000000000000000000000000000000000000000000050e192023292d253035363736353536363737373838383837363229302d2924201c1408000000000000000005131825303537373531261c1308000000000000000000000000000000000000000000000000000000000000000000000001111c232832363837342a201c13080000000000000000000000000000000000000d181f2b34373b38352c211a0f0100000000000000000000000000000000000000000000000000000f1f2d3639362d363939363936363a36353a37353936393639383938363335383936363a37373a39352c1f0f0000000000000000000000000000000000000000000000000003111c232a3337383631271d14090000000000000000000000000000000000000000000000000000000a161e2731363736322820190e0000000000000c171f273136373531271e170b0000000000000000000000000000000000000000000000000000000000000000000000000000000009141d3036434b50565a5b5b59534c483b32281b0f0100000000000000000000000000000000000003111d2b343c494d555a5c5d5b57504a43362f1d140900000000000000000000000000000000000000000000000000000000000d1d2b343c484d4f4d483c362d1f0f0000000000000000000b1b293239464b4d4b43362f2216080000000000000000000000000000000000000000000000000000000000000000000d181f2b35383f4336434a4b4c4b4a4b4b4c4c4c4c4d4d4e4d4c4b463945423e3a35302618140600000000000413233136434a4c4d4b44373025180800000000000000000000000000000000000000000000000000000000000000000008141c2f3838454b4d4c473a3530251808000000000000000000000000000000000d1d2a343b484d504e493d362d1f0f01000000000000000000000000000000000000000000000000071a2d3d4a4e4a3e4a4f4e4a4e4a4c504b4a4f4d4a4f4a4e4a4e4d4e4d4c46494e4f4a4b504c4b4f4e493d2c1c0c00000000000000000000000000000000000000000000000311212e373a474c4d4b443731261909000000000000000000000000000000000000000000000000000a1a283237444b4d4b4539352b1e0e000000000c1c293338454b4c4b443733291b0b000000000000000000000000000000000000000000000000000000000000000000000000000009192631414d5460666b6f71706e6962594b46392c1f1002000000000000000000000000000000000412222f3b484c5a636a6f7272706c6560544c40312619090000000000000000000000000000000000000000000000000000000a1a2b3c484d5a6264625a4e4a3d2d1d0d0000000000000003162939464b57616260544c4034261608000000000000000000000000000000000000000000000000000000000000000d1d2a343c484d54585b546060616160606061616162626363626261575d5a57544f4b43363224140600000000122231414e5460626260554a43362513000000000000000000000000000000000000000000000000000000000000000008182630404c505660626159544a433625180800000000000000000000000000000b1b2a3b484c596265635b4e4a3d2d1f0f0000000000000000000000000000000000000000000000000d21364a5c645c4d5c64645c645c61656160656260645c645c6363646361585b63645c6065615c64635b493a2917040000000000000000000000000000000000000000000011222f3f4b5058616260554b4437261401000000000000000000000000000000000000000000000008182838454b55606260574d483c2b1d0d00000b1b293a464c56606260554c4639291a0a00000000000000000000000000000000000000000000000000000000000000000000000009192637444b5f67737b81848685837e776c6157493d2d201000000000000000000000000000000002122330404c59626e787f84878785817a73665e4b44372619090000000000000000000000000000000000000000000000000002152738485a6270777a7870635b4a3b2b19050000000000000a1e324657616d767773665e51443426160500000000000000000000000000000000000000000000000000000000000b1b2a3b484c5a62696d707375767676757576767677777778787877767472706c696460544f423224140300000a1d30404e5f68737777746a605443301c0e00000000000000000000000000000000000000000000000000000000000001142636434b5e656f757777726960544336251300000000000000000000000000031629394859626e777a7870645c4a3d2c1a0600000000000000000000000000000000000000000000000f24394e6479645f677979647964767a76757a78747964796579787978766165797968757a77697a79635847331f0a00000000000000000000000000000000000000000008182f404c5d65707677756b605544311d0a00000000000000000000000000000000000000000000001325364556606c7577766f625a483b2a1805031629394658616c7577756c6157463827150200000000000000000000000000000000000000000000000000000000000000000000011426374455606c7c879096999b9b98938a8175635b4a3e2d1d0d0000000000000000000000000000102030414d5e6677838c949a9c9d9a978f877c6c60554437261401000000000000000000000000000000000000000000000000091d3145566278848d8f8d85796359483420080000000000011527374b6175828a8d877c6b62514433231300000000000000000000000000000000000000000000000000000000031729394859626e787e8286888a8b8c8b8a8a8b8b8c8c8c8d8d8d8d8c8b898885827e7a7469604f43321f0c00001024394d5f687d878c8c887f72604a3d2c1a0600000000000000000000000000000000000000000000000000000000000e1c304354606c7b848a8d8c877e72605443301c0f0000000000000000000000000a1e3246576277838c908d857a645b4936210c0000000000000000000000000000000000000000000003182d42586d826d677d807f78826d7f7d82807c8278836e827b817e837f7a657a817f7d7d7d847e7b8076614c37210c0000000000000000000000000000000000000000011426364c5e667b858c8d898073604b38281602000000000000000000000000000000000000000000071c304354607481898c8a8478625947341f0f0a1e324657617681898c898175615645311d0b00000000000000000000000000000000000000000000000000000000000000000000091d314455607381919ca4abafb0b0aea99f968679645c4a3c2b180800000000000000000000000009192d3e4d5f677c89989fabafb1b2b0aca49c918173605544311d120000000000000000000000000000000000000000000000000b20364b6074869aa2a4a39b8978624d3625130000000000081d3144556e82979fa59d91806b625041301d0d0000000000000000000000000000000000000000000000000000000a1e3346576277838d94989b9d9faaa1a09fa0a0a1a1a1a1a2a2a3a2a1a99f9d9a97938f887e69614f3b271200071b2d3e51677c919da5a79e94806b5b4935210c000000000000000000000000000000000000000000000000000000000e1e31424b607281909a9faaa59d938272604a3d2c1a060000000000000000000005182a3b4b61758599a1a5a39b8b79634e39230e0000000000000000000000000000000000000000000004192f44596e847f7c8082827e826d7f8178826d7d7c846f827f7975837f7a697e7a72827c817a8281837c67523d27120000000000000000000000000000000000000000081c304354667c8c9ba3a89e957f6a5645321e090000000000000000000000000000000000000000000b20354a607283969ea89f998777624c3d2d1a0c21364b617585969fa89f978474604b3a291704000000000000000000000000000000000000000000000000000000000000000009192f3f4b607382979fb2b6c3b9b9c5c7bab4a49c897a645a483626140100000000000000000000011527374a5c677d8c9ea7b4bcc9b7bec5c2b6b19f978273604b40301b0b000000000000000000000000000000000000000000000012273c52677c91a4b4c0b4a797826d5443301c07000000000b20354b60758a9fb4b7b29e95806b5f4d3b2b190500000000000000000000000000000000000000000000000000000c21364b61768799a1a9adb0b2b4bbb6b6b5b5b5b6b6b6b7b7b8b8b7c7bab4b2afaca9a69e937e69543f2914000d22364a5c72879cb2b7b8b39f8c78634e38230e00000000000000000000000000000000000000000000000000000006192b3c4e606b80969fafb4bbb7b2a0957f6a5b49352112000000000000000000000b1f3447596b8095a3b3bfb5a999836e59442f190400000000000000000000000000000000000000000000182d42586d826d8278828278837f80817e7b81817586828078817f817f7a697e796d827c81807a818277624c37220d00000000000000000000000000000000000000000b20354b6073879daab5b9b39e8975604b36210b00000000000000000000000000000000000000000012273c51677c91a1b4b9b4a599836e5b4a3621152a40556a7f95a3b4bab4a2947f6a5846331f0a01080b0b0b0b0b070000000000000000000000000000000000000000000000011527374b5d6b8095a0b1bdb4b0a4a4b1b5c2c2b6a79e8978625443301c0b00000000000000000000081d314455647a8a9faab9bbb4a9a2a8b4bcc9bdb1a096816c5e4c3929160300000000000000000000000000000000000000000003182d42586d8297adc2d1c5b39e8974604a35200b000000000d22374d62778caabbcabcaf9e917d675948342011000000000000000000000000000000000000000000000000000010253a50657b8fa5b2bfc2c5c8caced9cbcacacbcbcbcccccccdcdcdd7cdc9c7c5c1c5b8b29d88735d48331e000f24394f64798ea4b6caccbcab947f6a543f2a150000000000000000000000000000000000000000000000000000000b2035485a687e939eb0bdc9cecabeb49f8b79634e402f1d090000000000000000031729394c62778a9fb4c2d0c7b49e89745f49341f0a0000000000000000000000000000000000000000000a162b40566b80807c676d6d626e6a6b6c69666c6c61716c6b626c6a6d7f7a667c78697e696c6a646c6c625947341f0b00000000000000000000000000000000000000000f24394f64798ea5b7c8ccb8a7917c66513c2711000000000000000000000000000000000000000005182e43586d8298adbfcdc3b3a18e79634e38281631475c71869cb1c1cdc0b49e8976614c36211e141c20212120201c13150d0b05000000000000000000000000000000000000081d314455657b909eb0beb4a29b8e8e9ca4b5c6c5b8a79b8573604b392917030000000000000000011426364b6073869ca9babbaa9f948d939fabbccfbfb09f917c665746321e0b000000000000000000000000000000000000000000061b30455b70859ab0c5daccb9a88c77624c37220d000000000d22374c62778ca8b9cdccbcb39e8978624d3f2f1909000000000000000000000000000000000000000000000000000d22374d62778a9da5b2b7c3d4dfe2ebe0d8d0cdcacacbcbd9cfcac9c8c6c3c1bec4b7b2a69b85715b46311c0013293e53687e93a8c3d3d9c9ac97826d57422d180200000000000000000000000000000000000000000000000000081b2e3f4d62788a9fb4bccdcdc9bec3baa99a84705e4c38241100000000000000000a1e3346576b8095a9bacddec9b49e89745f49341f0a00000000000000000000000000000000000000000a1a28323650626b6b675f58584d59545657535157574b5c57564d57546169645e666361696156554f56574c473b2a1805000000000000000000000000000000000000000012273c52677c91a7c3d4d5c5aa947f6a553f2a15000000000000000000000000000000000000010d182030455a6f859aafc4dacfbfac97816c5645322a33485e73889db3c8ddccb9a8947e69543e2e332630353636363530252a221f180d00000000000000000000000000000000000b20354b6074869cb1bcb6a59b847979869ca8b9ccc5b4a3937e695746331e090000000000000000081c304354697e93a4b5c0b49f8c7f787e8d9fb4c6cdbdb29d8875614b392917030000000000000000000000000000000000000000071c31475c71869cb1c6dbd6c6a38e78634e39230e000000000b20354b6075899eb4c9deccb9a798836e5d4b372614010000000000000000000000000000000000000000000000000b20344859657b87909da5b7cadff5e3d3c5bcb8b5b5b5b6b6bcb4b3b2b1aeaba8a5a69d97887a644e39240f00152a40556a7f95aabfd4d9c4ae99846f59442f1a04000000000000000000000000000000000000000000000000000e22374b5d6e8399a9bacdc6b9b4a8adb2b4a2907c66513f2e1c08000000000000000c21364c6176899eb3c7d7d7c6b09b85705b46301b060000000000000000000000000000000000000002162838454b575a5e5b554e493d38433f40413e3b4142364642403842434f544f4c514d4f544f42403a414237342a1d0d00000000000000000000000000000000000000000013293e53687e93a8bdd3d6c1ac97816c57422c17020000000000000000000000000000000009151d2b343742586d8297adc8d8dec9b39e8975604b3f3f3f465b71869bb0c6dbd6c6b19c86715c4b374849434b4b4b4b4a43363f37342a1d1204000000000000000000000000000004182a3a52677d92a4b6c3b29c87756464788a9eb4c9d1c1b39e8976614c37261401000000000000000b20354b6073879db2c2b4a2927d6a626c8196a8b9cdcbb7a695806a5746331e0a0000000000000000000000000000000000000000081d32475d72879cb2c7dcceb9a48e79644f39240f00000000081c30435470859ab0c7d7d6c5b2a0907b655544311d0a00000000000000000000000000000000000000000000000005182b3b4b5d65737b879db2c7d7ead8c5b5a8a29fa0a0a0a1ab9f9e9d9c999693908c888177645c4a36220d00162b40556b8095aac0d5dac4af9a856f5a45301a0500000000000000000000000000000000000000000000000005182b3b4f657a8fa1b3c7c8b9a89e9398a0b2b19b86715d4b37230a000000000000081c2e3f53697e93a7b9cce1cdbaa8937e69533e29140000000000000000000000000000000000000000091e324556606c6f73706a635b534c473b4038454b453839373435313538353f39363c383b3e3b322b252c2d221f180d00000000000000000000000000000000000000030404152a3f556a7f94aabfd4d7c1ac97826c57422d1702000000000000000000000000000000091927313b484d5356677c91aabbcee0ccb9a7927d675554545454556b8095aac9d9dec9b5a48f7a64555d5e5f546060606060545a544c473b30221200000000000000000000000000000a1f34475970859bb0c2b6a5917c66575a6a8095abbccfccb9a7947f6a5544311d080000000000000011263b50667b90a5b7c8b09b8570604d61768a9eb4c9d4c4b39e8976614b36210e0000000000000000000000000000000000000000071c31475c71869cb1c6dbcfb9a48f7a644f3a250f000000000114263654697e93a9bacde1cfbeb19c8673604b382816020000000000000000000000000000000000000000000000000d1d2e3f4b5460667b90a9bacde2d0bca8978d8a8a8b8b8c8b8a89888684817e7a77736c62594a3e2d1b0700162b40566b8095abc0d5dac4af9a856f5a45301a050000000000000000000000000000000000000000000000000b203448596e8398aebfcebbaa9e8a7e8298a3b4a3907b65503828160300000000000e23374b5d71869cb1c5d6dec9b49f8a76614c37210c00000000000000000000000000000000000000000b21364b60768285888580797169615956564c5660564d4f4d484b44494e4a484d4c46393e35404337342a1d0d0b0500000000000000000000000000000000060c0e15191919192b40566b8095abc0d5d6c1ac96816c57412c17100e0d0b080100000000000000000001152737444b5962686b6d768a9fb4cadfd6c5b09a85706a6a6a69696a6a7a8fabbccfe3d2c2ae99837371727374757576767575736f6a62594c40301d0d000000000000000000000000000c22374c61778b9fb5c7b29c8773604a4d62778b9fb4cad6c5b29d8874604b35200b00000000000003162839576c8196acc3bbaa917c675247586d8297adc4d5ccb9a7937e69533c2c190600000000000000000000000000000000000000061b31465b70869bb0c5dbcfbaa58f7a65503a251000000000000c21374c61778a9fb4c9dedec9b6a4927d685645321e0b0000000000000000000000000000000000000000000000000011212e36434b60758a9fb4c9dfcdb8a28d79757576767676757473716e6c69656259574c483b2d20100000162b40566b8095abc0d5d9c4af9a846f5a452f1a050000000000000000000000000000000000000000000000000d22374d62778b9fb4cac7b49f8c7c6973859bb0ae98836e5645321e09000000000216283850657a8fa4b6cae4d1c1ac97826d5847331f0a0000000000000000000000000000000000000000091e324556606c6f777f898e867e77706c6b616376675f64625960555b63605962615758544b56584c473b2a1909000000000000000000000000000000020e1920232a2e2f2f2f2e41566b8096abc0d5d6c1ab96816c56412c26252322201c14080700000000000000081d314455606c777e8182849aaabbcee2ddc8b4a297817f7f7f7f7f7f7f7f8c9fb4cadfdbc7b3a19988868788898a8a8b8b8b8a88847f77665e4c3b2a180500000000000000000000000012273d52677c92abbcc0ab95806b5443485970859aafc5dacbb7a6907b6651362614010000000000091e32465772879cb1c7b49f8a76614c3a50657a90a6b8cbd6c5b19b86715a4935200c00000000000000000000000000000000000000051b30455a70859aafc5dad0baa5907b65503b261000000000000a1f3347586d8297adc0d0e3d3c2b29d8775604b3a2917040000000000000000000000000000000000000000000000000311182631455672879cb2c7dccab5a08a7560606061616160545d5c595653504c483b37342a1d10020000162b41566b8096abc0d5d9c4af99846f5a442f1a05000000000000000000000000000000000000000000000004172a3a54697e94aabbcdbaa997816c5e657a8fa5b49f8a75604b36210b00000000091e3245566d8297acc2d3ddc8b4a38e79644e3a291704000000000000000000000000000000000000000002162838454b5759616976808a938a8581807679887d697977667567677872647776616e69606b6e61594737271c13080000000000000000000000000a151d2c35383f434444444343566b8196abc0d6d6c0ab96816b56413c3b3a3937353026211a0f010000000006192c3c4b6073818b9396979aa2b4c8d8eae4d1c0b19f9794949494949494959fabbccfe3e2d0bfb3a69d9b9c9d9e9faaa0a0a0a69d9a948a7c665947341f0b000000000000000000000001162c41566b8196abc9c4a6907b6651363b53687e93a8c7d7d4c4ad97826d5443301c0800000000000c21364b61768b9fb5c5b09b86705746354a6074889db3c8ddc9b5a38d78624d38230d00000000000000000000000000000000000000041a2f44596f8499aec4d9d0bba5907b66503b2611000000000004172a3a4e64798ea2b3c7dcdfcbb7a6947f695846331f0d0000000000000000000000000000000000000000000000000000081527385b70869bb0c5dbcbb6a18c76614c4b4b4c4b4a43484744413e3b37342b221f180d00000000162b41566b8096abc0d5d9c4ae99846f59442f1a0400000000000000000000000000000000000000000000000a1f33475870859ab0c8c9b49f8a77614c5d72879cb2a9907b66513b2611000000000b21364b6075899eb3c9ded8c8b09b85705c4a361c0c000000000000000000000000000000000000000000000a1a2832363b474c58616b777e8a948a7f70859a887e8a857b897d7d8a8079898477837e75808377615544353025180a000000000000000000000a1a28323c494d55585959595958586c8197acc1d6d5c0ab96806b565251504f4e4c4b4336362d2011040000000c2035495a6d82969faaabadafb4c0d1e6f6efdecebdb1acaaa9a9a9a9a9a9aab4bcc9d9ebedddd0c4b7b3b1b2b3b4b4bbb5b5c4b7b3afa89e8a77624c37220d0000000000000000000000041a2f44596f8499aec4b7a68c77614c37384e63788da9bacdddc8b39e8874604b35200b00000000000f243a4f647a8fabbcc1ac97816c57393043546e8398adc3d8d2c1a8937e69533e29140000000000000000000000000000000000000004192e43596e8398aec3d8d0bba6907b66513b26110000000000000c21364a5c6f849aafc0d0e3d4c4b39e8976614c3b2b180500000000000000000000000000000000000000000000000000001b30455b70859ab0c5daccb7a18c77624c37363736353025312f2c29252220180d0b050000000000162c41566b8196abc0d6d9c4ae99846f59442f1a0400000000000000000000000000000000000000000000000c21374c61778b9fb4cac4ad98836e5947566b8095abaa95806b55402b160000000013253651667c91a7b9cce0cebbaa927d68523e2d1a0000000000000000000000000000000000000000000000000a161e212a343a4a5b657b86867f776a6c819684949c86898a89888885869c89888985858281857360534a4336281a0a000000000000000002152838454b5a636a6e6e6e6e6e6d6d6f8499aec4d9d5c0ab96806b6767676665636260544e4a3e2f22110000000e23384d63788da0b4bbc8c2c5c8d1deeefffdebdbcec5c1bfbfbfbebebfbfbfcacfd9e7f7fbede2d5cbc8c6c7c8c9caced8cbd5cbc8c6b9a8927d67523d28120000000000000000000000031628395c72879cb1c7b29d8873584733354b6075899fb4c9decbb8a68e79634e39240e000000000012273c52677c91a7c9bea9937e69543e2536556a7f94aabfd4d8c3ad98836e583928160300000000000000000000000000000000000003182d43586d8298adc2d7d0bba6917b66513c2611000000000000071a2d3d4f657a8fa2b3c7dce0ccb8a795806b594834200e00000000000000000000000000000000000000000000000000051a30455a6f859aafc4daccb7a28d77624d38222121201c131c191714100d0b050000000000000000162c41566b8196abc0d6d9c3ae99846e59442f1904000000000000000000000000000000000000000000000012273c51677c91aabbcbb7a6907b66503a50657a8faaae99846e59392917030000071c3043546d8297adc5d6dfcab49f8b76614c37210f0000000000000000000000000000000000000000000000000002090c1823394e63798a7b70827e69647a8e878298838697828b917c889882889580888975817e72686054453828160300000000000000091d324556606c787f83848484838282838c9fb4cadfddc7b29d877e7d7c7c7b7a7877746e645c4c402f1808000012273c52677c91a7beced9d7dadce3eaedeff5f9ebe0d9d7d4d4d4d4d4d4d4d4dfe3ebeef0f6fff2e7e0dddbdcdddedfe2dfdedcd9d2c9bcab937d68533e28130000000000000000000000091e32465774899eb3c5af9a85705a3a2a30435471869bb1c6dbd5c5a8937d68533e2813000000000014293e54697e93a9bebba6917b66513c273c51677c91a6c9dadcc7b29d87725745321e0900000000000000000000000000000000000003182d42586d8297adc2d7d1bca6917c67513c2712000000000000000f22374b5d6f849aafbfcfe7d5c5b49f8a77624c3d2c1a06000000000000000000000000000000000000000000000000051a2f445a6f8499afc4d9cdb8a38d78634e38230e0c0b070000040100000000000000000000000000172c41566c8196abc1d6d8c3ae99836e59442e19040000000000000000000000000000000000000000000002162838566c8196abc8c8b29d8874604b364b60758a9fb29d87725746331e0a00000b20354a6074889eb3c8cdd7c4af9a846f5847331f0a0000000000000000000000000000000000000000000000000000000014293f54697e897571868978656e83947f878c7e8a897f94837b8c8a7c8b897d8b818593877e72605645321e10000000000000071b2d3e4b6074818c9498999999989897999faabbcee2dfcab7a59d93929291908f8e8c89837a665e4c362614010010253b50657a90a8b9cbd4d2d3d4d4d5d8dbe2edfbf4eeece9dfd8d5d5d5d5d5d5d5d5d9dbe2edfbfaf4efe4dddbcedacfcac8c6c4c2b5b19f8c78634d38230e00000000000000000000000c21364b61768ba8b9c3ae98836e59432e2636586d8398adc2d8d6c1ac96816c57412c170200000001162b40566b8095abc0c8a48e79644f3924394e64798eabbccfdfcab59f8b76604b36210b00000000000000000000000000000000000002182d42576d8297acc2d7d1bca7917c67523c271200000000000000081b2e3f4f647a8fa1b3c9d9e1cdbaa897816c5b4935211000000000000000000000000000000000000000000000000004192f44596e8499aec3d9ceb8a38e79634e39240e0000000000000000000000000000000000000000172c41566c8196abc1d6d8c3ae98836e59432e190400000000000000000000000000000000000000000000091e32455671869bb0c6c2ac97826d554432455671869cb1a58b76614c36210c00000f24394e64798ea6b4b4bac7c3a8937e68533a2917040000000000000000000000000000000000000000000000000000000011273c51667c917d677d92877b6f788a897d92877e9383828a7a7f94837d928480937e7f86918374604b3e2e1b0700000000000d22364a5c6e82969fabadaeaeaeaeadadaeb4bbc8d9ebe6d4c3b7b2a8a7a7a6a5a4a3a89e998b7c665443301c08000c21364b6176899eb3b7c4bdbebebfc0c3c6cfddecfafcebdacdc4c0c0c0c0c0c0c0c0c3c7d0ddedfdefdfd1c8c5b8b8bcb5b3b1aeaaa49c917f695a4935200c00000000000000000000000e23384e63788da3c6c1ac96816c57412c2a3f556a7f94aabfd4d9c4af9a846f5a452f1a0000000003182d42586d8297adc2bbaa8c77624d3722364b60768b9fb5cadfcfbcab8e79644e39240f00000000000000000000000000000000000002172d42576c8297acc1d7d2bca7927d67523d281200000000000000001022364a5c6e8399abbccfe3d7c6b49f8b79634e3e2e1b07000000000000000000000000000000000000000000000004192e43596e8398aec3d8ceb9a48e79644f39240f0000000000000000000000000000000000000000172c41566c8196abc1d6d8c3ae98836e59432e1904000000000000000000000000000000000000000000000b21364b60758a9fb4cac6a7927c6752372838596f8499aea28d78634d38230e000014293f54697e94a99f9fa9bab6a58c77624d37220d00000000000000000000000000000000000000000000000000000000081c2e3f4b60758889786c819790847b809580818877817f7686898486907b80867686877e797c89826d5c4a36220d00000000000f24394f647a8ea0b4bcc9c3c3c3c3c2c2c4caced9e6f6f1e1d4cac7bdbcbcbcbbbac6b9b4aa9d8773604b35200b000a1e334657697e929da6a6a7a8a9aaaaaeb2bfcfdcecf3dfcdbcb0ababababababababaeb3bfd0dfefe4d1c1b4b0a3a2ab9f9e9c99958f867c69614f3c2c190600000000000000000000000f253a4f647a8fa4c0c5aa947f6a553f2a273c51667c91a6c9dadcc7b29c87725d3a2a170400000004192f44596e8499aec3b49f8a75604b362032455772889db2c7dddac9a6917b66513c261100000000000000000000000000000000000002172c42576c8197acc1d6d2bda8937d68533e28130000000000000000071b2e3e4e63798c9fb4c7d8e2cebbaa98836e5c4a362211000000000000000000000000000000000000000000000003182e43586d8398adc2d8cfb9a48f7a644f3a250f0000000000000000000000000000000000000000172c41576c8196acc1d6d8c3ae98836e59432e1904000000000000000000000000000000000000000000000f253a4f647a8faabbcdb9a88d78634d382d42576c8297aca48f79644f3a240f0004172a3a596e83999f8a8a9fb4b29d8772594834200b000000000000000000000000000000000000000000000000000000000e23374b5d65777e93867675858b879089988b7e7e7b7a6a61767e787586877679887b848275677b8b79644f3a240f000000000013283e53687d93a8becfd9d9d9d9d8d7d7d9dfe2ebf6fffff1e6dfddd2d2d1d1d0cfd6cdc8b6a58d78634d38230e00031729394f60697e888e90929394949598a0b2becfe2edd8c4b09e969595959595959599a1b3c1d1e4ddc8b4a39b8e8d8c8a8987847f7a71665e4f43321e0e0000000000000000000000000d22374c62778ca2b4b8a6917c66513c2723394e63788eabbccfdec9b49f89745847331f0a00000002172d42576c8297acbfb09b85705544311d28395a6f859aafc4dad3bea8937e69533e291400000000000000000000000000000000000001172c41566c8196abc1d6d3bea9937e69543e29140000000000000000001021364a5b6d8298a9bacee2d8c8b2a08f7a644f402f18080000000000000000000000000000000000000000000003182d42586d8297adc2d7cfbaa58f7a65503a25100000000000000000000000000000000000000000172c41576c8196acc1d6d8c3ae98836e59432e19040000000000000000000000000000000000000000000013283e53687d93a8c8c9b49e8974604a352b40556a8095aaa5907b65503b2610000a1f33475872889d907b8095abad98836d583b2b18050000000000000000000000000000000000000000000000000000000010253a50657b88738195877b7a8b747b7f828b9486868578706b686263798a81778986726d615d6d827c67523c2712000000000012273c52677c91a8b9c7ced8d0d1d2d3d5d8dfe3ecf7fffff2e7dfddd9d9d9dadadbdbdbcebbaa8f79644f3a240f00000b1b32424f606873797b7d7e7f7f808398a0b2c6daebd5c0ab9680808080808080808399a3b5c9dddbc5b09b857978777573716f6a645c514c40322514000000000000000000000000000b2034485970849aa9aa9e8875604b362121364b60768a9fb5cadfcdbaa98c76614c37210c0000000011263b51667b90a1aaa1947e69543727152c42576c8197acc1d6d5c0ab95806b56402b1601000000000000000000000000000000000001162c41566b8196abc0d6d4bfaa947f6a553f2a15000000000000000000071a2d3d4d62788b9fb4c6d7e6cfbeaf9a84705e4c3625130000000000000000000000000000000000000000000002182d42576d8297acc2d7d0bba5907b66503b26110000000000000000000000000000000000000000172c42576c8197acc1d6d8c3ae98836e59432e190705010000000000000000000000000000000000000001162c41566b8196aba5aab19b8671544330283d53687d92a8a6917c66513c2711000c21374c61768c9c8775869cb1a9937e69543e2914000000000000000000000000000000000000000000000000000000000c1d2a43586e83927d73808b908c806b666a6d7d92807983868581786860687e826d7b816c544b4f647974604b36211204000000000c21374c61768a9ea9b4bbc8bbbcbdbebfc2cacfdae7f7f2e2d4cbc8c4c4c4c5c5c5c6c6beb49f8b76614c37210c000000142432424e546063666869696a6b6e8298adc2d3e5cdb8a38e796b6b6b6b6b6b6b72859bb0c6d7dec9b39e8976636160555c59554f4a3e382f2214070000000000000000000000000005182b3b4f647a8a95968c7c665645321e1e32455673889db3c8ddd7c7a38e79644e39240f000000000f24384c5e6e839195918373604b352014293e54697e93a9bed3d8c2ad98836d58432e1803000000000000000000000000000000000001162b41566b8096abc0d5d5c0ab95806b56402b16010000000000000000000f2035485a6c8196a8bacde1dcc8b4a2907b665443301c0900000000000000000000000000000000000000000002172c42576c8197acc1d6d0bba6917b66513c26110000000000000000000000000000000000000000172c42576c8197acc1d6d8c3ae98836e59432e1b1c1a16100e0800000000000000000000000000000000041a2f44596f84999a9099ae99836e593625263b50657b90a5a5907b65503b2610000f243a4f64798f947f7a8fa4b5a48f7a644f3a250f00000000000000000000000000000000000000000000000000000004182a3b4752677d9288766b797f7d737b72605f697e7b807c7d838b8b7e6874827560656c6251464b5c646056483b2f2212020000000a1f334758677d8b999faaa5a6a7a8a9aaadb5bcc9daece7d4c4b7b2aeafafafb0b0b1b0aca097816d5847331f0a0000000614243136434a4e515253545555657a8fa4b6caded4bfa9947f6a555656565654687d92a8b9cde0ccb9a7927d68524b443744403a362d241d12040000000000000000000000000000000d22364a5c647980817a665e4c3828161628385b70859ab0c5dad0bba6907b66513b261100000000091d2f404b60727c7f7b72605544311d11263c51667b91a6bbd0dac5af9a85705a45301b00000000000000000000000000000000000000162b40556b8095aac0d5d6c1ac97816c57422c170200000000000000000006192b3c4c62778a9fb4c5d6e3d1c0b19b8672604a37261401000000000000000000000000000000000000000001172c41566c8196abc1d6d1bca6917c67513c27120000000000000000000000000000000000000000172d42576c8297acc1d7d8c3ae98836e59432e3031302c25231c11090000000000000000000000000000011426365c71869a847b90a596816b56412c24394e63798ea9a48f7a644f3a250f0012273c52677c918e798096abbaa98c77614c37210c0000000000000000000000000000000000000000000000000000000b1f344759616a708496816c636a697f8a806b61757a676a78746e7884927d7e927d676161584c5761686b6962594c402f20100000000417293a4d5f6779838a8e909192939495989fabbccfe3dfcbb7a69d99999a9a9a9b9b9b978f8274604b3a29170400000000061318253035393b3d3e3f3f4b5d72869cb1c7d7ddc7b29d8774604b4040364b6176899eb4c9ded6c5b09b85705b4a36262f2a24221b17110b09020000000000000000000000000000071b2d3e4a5b636b6c645c4c402f1a0a182d43586d8298adc2d7d3bda8937e68533e29130000000000121c30435460676a666054443726140f24394e64798ea3c6d6dcc7b29c87725d3a2a1804000000000000000000000000000000000000152b40556a8095aabfd5d7c2ad98826d58432d1803000000000000000000000e1f3448596b8095a7b8cce0dec9b5a3917c675544311d09000000000000000000000000000000000000000001162b41566b8096abc0cad4bca7927c67523d27120000000000000000000000000000000000000000172d42576c8297acc1d7d8c3ae98836e594342464745413a372e241c1203000000000000000000000000081c3043547388947f7b91a6947f69543f2a20364b60758a9fa88e78634e39230e0013283e53687d938874869cb1b49f89745847331f0a0000000000000000000000000000000000000000000000000000000c22374c6177807678898c7c665b738888847f6d82897c7b8a806a7a80848b7d8d89777677665e61757d807e77665e4c3e2d1b070000000c1c30414d5b636e76797a7b7c7d7e80828d9fb5cadfddc8b29d888484848585868686827b6e605645321c0c0000000000000008131c20242628292a2e3f54697f94a9bacddfcab7a5917c675138283246576d8297adc2d3ddc8b4a38e79634e38282a2b2d2f2f2c26201d150a000000000000000000000000000010202d3d494e56564f4a3e2f221100152b40556a8095aabfd5d5c0ab95806b56402b16010000000001142636434b5155514a43362619090c21374c61768ca8b9cddfc9b49f8a745947341f0a000000000000000000000000000000000000152a3f556a7f94aabfd4d8c3ae98836e59432e19040000000000000000000005182a3b4c6176899eb3c4d4e5d2c2b19c8673604b372715010000000000000000000000000000000000000000162b40556b8095aab2b7c3bda7927d68523d28130000000000000000000000000000000000000000182d42576d8297acc2d7d8c3ae98836e5951575b5c5a56504b3f382f1e160b00000000000000000000000b20354b60758a917c7f94a7927d68523d281d3145566f84999f8a75604b36210b0014293e53697e9385758a9fb4b19c87725c3a2a17040000000000000000000000000000000000000000000000000000000d22384d62778d88807f8a8979666c81947f847f8d84868689857e8688838985829885898a7c667285808088897c665c4a36220b000000001223303d4a4e57616465666768696a72879cb1c7dcd1bca6917c6f6f6f70707071716c655d4b45382816000000000000000005131e252a3437393a39394c61778a9fb4c9dfd4c3ae98836e56453229394f657a8fa4b6caded1c1ac96816c56453e3f41424444423c3631271a0f0100000000000000000000000002101f2c3538404139362d2011040013283e53687d93a8bdd2d7c2ad97826d58422d1803000000000008182630353c403c3530251809000a1f33475874899eb4c9decdbaa98c77614c37220c000000000000000000000000000001080b0d142a3f54697f94a9bed4d9c4ae99846f59442f1a0400000000000000000000000d1f3346586a7f94a6b7cbdfdecab6a4927d675544311d090000000000000000000000000000000000000000152a40556a7f959f9da5b7bda8937e68533e29130000000000000000000000000000000000000000182d42576d8297acc2d7d8c3ae98836e60666d70716f6b655d514c4032281b0d000000000000000000000c21364b61768b8e798297a6907b66513b261527384f647a8a8c7f695745321e090013283e53687d9381798eaabbaf9a856f5a45301a000000000000000000000000000000000000000000000000000000000b2034485a6a7f868a8e9196887c7979898978858a8b7d879a84848a88808a9580889883858a787a8f7c7d77838a7a644f3929170300000005121f2d3639464b4f50515253545b71869bb0c6dbcfb9a48f7a645a5a5a5b5b5c5b57504b3f32281a0a0000000000000008162330393a474c4f4f4e4e4d586d8298adc6d7dec9b49e8975604b3d47474b5d72869cb1c7dcdec8b39e89756052535456585a5a57514b45382c1f0f00000000000000000000000000010f1a21232b2c24221b1002000011263c51667b91a6bbd0d9c4ae99846f59442f1a0400000000000008141c20272a26201c1308000004172a3a5d72879cb2c7dcd7c7a38e79644e39240f0000000000000000000000000709151d202223293e53697e93a8bed3dac5af9a85705a45301b0500000000000000000000000417293a4b6075889db3c3d3e5d3c2b29c8774604b3727150200000000000000000000000000000000000000152a3f546a7f948c879db2bea9937e69543e29140000000000000000000000000000000000000000182d42586d8297adc2d7d8c2ad98826d757c82858685817a71665e4b46392b1d0d0000000000000000000d22374c62778c8b76859aa48e79644f39240f22374b5c64757769614f392816030013283d52687d92807b90a5c8ae99846e59442f190400000000000000000000000000000000000000000000000000000005192b3c50616a7175797c808d9086868999877e849a87798795808497827e93897f94897e86837e939092827484846f5746331e0a00000000010f1a21283236393b3c3d3e475c71869cb1c6dbcfb9a48f7a644f454545464646423a372e1e160a0000000000000001162634414d525961646464636362657a8fa8b9cde1cdb9a8917c675b5a5c5d5d5d697f94a9bed4e0ccb8a7927d6767686a6b6d6f6f6c666056493d2c1b0b0000000000000000000000000000060c0e16170f0d07000000000f24394f64798ea4c9dadbc6b09b86715b46311c000000000000000001080b1215110b0700000000001b30455b70859ab0c5dad0bba6917b66513c26110000000000000000000001101b222731353738363d52677d92a7bcd2dbc5b09b86705b46311b060000000000000000000000000c1e324557687e93a5b6cadfdfcab6a5927d685544311d0a0000000000000000000000000000000000000014293f54697e9483798ea3b8a9947f69543f2a140000000000000000000000000000000000000000182d42586d8297adc2d7dac5b09b847f8891979b9c9a968f867b6e6157483b2b1d0c00000000000000000d23384d62788d8974879da38d78634e38230e1b2e3e4b576161584f43321b0a000012273c52677c917f7c91a6bbae99836e59442e1904000000000000000000000000000000000000000000000000000000000d1d33435055566063666b7e8c86777383917c7684978278878c7d84937e7f9486818a847f947f94868385707a8c76614b36210c000000000000070b161e212425262732475c71879cb1c6dcceb9a48f79644f3a30303131312d25231c110300000000000000000f1f3445515f677177797a7978787777788a9eb4c9ded6c6b29d8779706f7172727273788da2b8cde8d6c5b29c867c7c7e7f80828484817c74635b4939281603000000000000000000000000000000000101000000000000000d22374d62778cabbccfddc8b29d88735d3a2917040000000000000000000000000000000000000004192e44596e8399aec3d8d2bda8927d68533d281300000000000000000009141d2e3737444b4d4d4b4551667c91a6bbd1dbc6b19c86715c47311c07000000000000000000000000031628394b6074879db2c2d2e5d3c3b29d8774604b3828150200000000000000000000000000000000000014293e53697e9382798ea4b9aa947f6a553f2a150000000000000000000000000000000000000000182d42586d8297adc2d7ddc8b4a39b949da6acb0b1afaba39b9082756259483b2a1a0a000000000000000e23384d63788d8774899fa28d78624d38230d10202e39464b4c473a32251500000011263c51667b917f7c91a6bbae99836e59442e190400000000000000000000000000000000000000000000000000000000001525333c38454b4e5160687b89887a77878a7a7584937e78878a7b858d798195808489838a8183908c7e69748978634d38230e000000000000000003090c0f10111d32475d72879cb2c7dcceb9a48e79644f39241b1b1c1c17100e08000000000000000000071a2d3d51636c7d868c8e8f8e8e8d8d8c8d9ea8b9cde1dfcbb7a59d8c858586878788888a9fb4c9def3decab6a49c919293949697999997918679635746321e09000000000000000000000000000000000000000000000000000b20364b60758a9fb5cadfc9b49f8a745847331f0a0000000000000000000000000000000000000002172c42576c8197acc1d6d4bea9947f69543f2a140000000000000000091926313e4b4f55606262605651657b90a5bad0dcc7b29d87725d48321d08000000000000000000000000000a1d314455677d92a4b5c9dedfcab7a5937e685645321d0a00000000000000000000000000000000000013283e53687d93817a90a5baaa95806a55402b150000000000000000000000000000000000000000182d43586d8298adc2d7e4d1c1b4b0a9b3b5b1aeb3b8c1b5b1a0988577625947382816020000000000000e23384e63788d85758ba9a18c77624c37220d02101b28323637332a1c150700000010253a4f657a8f807a90a5c9ae98836e59432e190400000000000000000000000000000000000000000000000000000000000715202828323639414e5d6578848b7f7989887875848c7c78878878817373857d77877786826e7b7c6960718674604b36200b00000000000000000000000000081d32485d72879db2c7dcd7c6a38e78634e39230e060706020000000000000000000000000c21364a5b6c81929ba3a4a4a3a3a2a2a1a2b4b9c6d7e9e6d4c3b7aa9f9a9a9c9c9c9d9d9fa8bacde1f6e6d3c3b6b2a6a7a8a9abadafafaca49c8775614b36210c00000000000000000000000000000000000000000000000000081d31445573899eb3c8decebaa98c76614c37210c000000000000000000000000000000070b0d0d0b162b40556b8095aac0d5d5c0ab95806b56402b160100000000000009192637444b5c646e757778756f66647a8fa4b9cfddc8b39d88735e48331e0000000000000000000000000000021527374b6073869cb1c0d1e4d4c3b29d8774604b38281603000000000000000000000000000000000013283d52687d92807c91a6bcab96806b56412b160100000000000000000000000000000000000000182d43586d8298adc2d7d8dfd1c8c5bbaea39b999ea6b4bbbeb2a39b8777615645321e110000000000000e23384e63788d85768ca1a18c76614c37210c00000b161e21221f180c00000000000e23384d63788d82798eabbcaf99846f5a442f1a00000000000000000000000000000000000000000000000000000000000000030d0a151d2024313f4c5a6273808c857f8986777d89897a7a8985797a7e777262756175746066665e617779645544311d0800000000000000000000000000081d32475d72879cb2c7dccdb9a88c77624c37220d000000000000000000000000000000000e23394e63798e9fb1b5c1b9b9b8b8b7b6b7c9cdd7e4f4f2e2d4c8bbb4b0afb1b2b2b2b3b4bac6d7e9fcf1e1d3cac7bcbcbdbfc0c2c4c4c2b5a5927d67523d281200000000000000000000000000000000000000000000000000021527375d72879cb2c7dcd8c7a38d78634e38230e0000000000000000000000000708131c202222201d293e54697e93a9bed3d7c1ac97826c57422d17020000000000011426374455606b7a83898c8d8a847c6f798ea3b8cedec9b39e89745e492513000000000000000000000000000000091c304354667c91a2b4c8dddfcbb7a6937e695645321e0a000000000000000000000000000000000012273d52677c927f7d92a7bcab96816c56412c170100000000000000000000000000000000000000182e43586d8398adb8bcc6d4e3d1c0ae9d94868388949faabac1b5a59b8574604b3f2e180800000000000e23384e63788d84778ca1a18c76614c37210c000b171f212d2e2220180d000000000c21364c61768b85758a9fb4b09b86715b3a29170400000000000000000000000000000000000000000000000000000000000000000002090b13212f3c4855606a798592889c867779868f8382898d837f696055605660605550514d5961645c4a3727150200000000000000000000000000061b31465b70869bb0c5dbc9b49e8974594834200b0000000000000000000000000000000013293e53687e93a8bdc9d2cfcecdcdcccccddee1e9f4fffff2e6d9cecac5c4c6c7c7c7c8c9cdd7e4f5fffff1e6dedcd1d1d3d4d5d7d9d9d2c3ab95806b56402b1600000000000000000000000000000000000000000000000000001c31465b71869bb0c6dbcfb9a48f7a644f3a250f00000000000000000000020f1a2125303537383531273d52677d92a7bcd2d8c3ae98836e59432e19040000000000081d3144556073818d989ea8a99f9a91847d92a7bcd1dfcab49f8a755443301c070000000000000000000000000000011426364c5e70859bb0c0d1e4d4c4b39d8875604b382816030000000000000000000000000000000012273c51677c917e7d92a8bdac97816c57422c170200000000000000000000000000000000000000182e43586d8398ada3a9b6c6dcc8b4a2947f716e757f8c9fa9bac3b4a397816c5d4b36261401000000000e23384e63788d84778ca1a18c77614c37220c0b1b293336424337342b1d0d0000000a1f33465874898974879cb2b39e88735846331f0a00000000000000000000000000000000000000000000000000000000000000000000000003111d2b37444b5b63707d88939a85707786877279887b69614a444b454b4b44373c3a474c4e4a3e2d1909000000000000000000000000000003182e43586d8398adc2d3c5b09b86705b3b2b18050000000000000000000000000000000014293e54697e93a9c2d2dbdcdddddededfdfdfe3ece5f3f5f3edebe2dfdadadbdcdcdddddee1e9e1e4f4f7fdf9f3f1e6e8e0ded3d3d2d0c8bbaa947e69543f291400000000000000000000000000000000000000000000000000051a30455a6f859aafc4dad0bba6907b66513b26110000000000000000000a151d2d3636434a4c4d4b44373b51667b90a6bbd0dac4af9a856f5a45301a0500000000081c2e3f4b607382969fabb4b9bab4afa29a929bacc0d4e2cebbaa8a75604a35200b00000000000000000000000000000008182f4050657b8fa2b4c8dddfcbb7a6947e695645321e0a0000000000000000000000000000000011263c51667b917e7e93a8bdac97826d57422d180200000000000000000000000000000000000000192e43586e83989d8e97a9bcdac5af9a84706156606a7c8b9fa9bac1b59f8d7b655443301c08000000000d22384d62778d85778ca1a28d78624d38230d17293a464c57584d483b2b180500000417293a5c72878e788297adb8a68b76614c36210c00000000000000000000000000000000000000000000000000000000000000000000000000000d1926313d4a4e5f67757e88806b6277806b637773604b4331353236353127272a343739362d20100000000000000000000000000000000012273d52677d92a4b6c3b8a7957f6a55402a15000000000000000000000000000000000011263b50667b90a4b5c2c5c7c8c8c9c9c9cacacfdacfdee0ded8dae1ece7dbd3d1cfcececdcdcccccfdfe2eaf6fff4e4d6ccc9bebebdc0b4aa9f8b78624d37220d0000000000000000000000000000000000000000000000000004192e43596e8398aec3d8d2bca7927d67523d281200000000000000000a1a27313e4a4e546062626055524b4f657a8fa4bacfdbc6b19b86715c46311c00000000000e23374b5d6b8096a1b5bcc9cdcec9c0b3afa7acb9cadcead8b5a08b75604b36200b000000000000000000000000000000001223374b5d70859bb0c5dae7d4c4b39d8875604b3828160200000000000000000000000000000011263b50667b907d7e93a9bead98826d58432d180300000000000000000000000000000000000000192e43586e839888798ea3b8d4c4a7927d6752454b5e667b8b9fabbcbcab9c8673604b352010000000000d22374c62778c85768ba1a38e79634e39240e1f334658616d6d625948342009000000192e44596e83937e7c91a9baa48f7a654f3a251000000000000000000000000000000000000000000000000000000000000000000000000000000009141d2d36414d56606975726059626b625962605544311d201e21201d1511181f2224221b1002000000000000000000000000000000000b21364b6075869ca5aaa79e8877614c37220c00000000000000000000000000000000000b20354b6073869ca4adb0b2b2b3b3b4b4b4b5bcb5bac8ccc9c3c6cfdcd7c9bfbbb9b9b8b8b8b7b7bac9ced8e6f6e8d6c5b9b3a9a9a7a4a29a8c7d67594834200b0000000000000000000000000000000000000000000000000002182d42576d8297acc2d7d3bea8937e69533e2914000000000000000a1b2838454b5c646d747777757067605563788ea3b8cdddc7b29d88725d37271502000000071b2e3e50657b8d9fb5bfcad4dfddcfd0c7c4bcc0cad7e7e0cbb6a08b76614b36210c0000000000000000000000000000000c1c2c3c4b5c6c8197acc1d6ece0cbb7a6937e695645321e0a00000000000000000000000000000010253a50657a8f7d7e93a9beae98836e59432e190400000000000000000000000000000000000000192e43586e839886758ba0b5cbb7a68c77614c37404c5d677d8d9fb4c0b6a4917c67523e2d1b070000000c21364c61768b86758ba9a48f7a654f3a251021364c6176828277624d372715010001162b40566b809584768a9fb4a9947f695438281602000000000000000000000000000000000000000000000000000000000000000000000000000000010f1a213138454b55606054484c5651484d4b443726140b090b0b080100040a0c0f0d07000000000000000000000000000000000000091e324556637887919493897b655847331f0a0000000000000000000000000000000000081c30435462788692989b9c9d9e9e9f9f9f9faba0a5b3b8b3adb2becfc9b9aca6a4a4a3a3a2a2a1a5b4bbc8d8eae0ccb9a79e9493928f8c847a675f4d3b2b19050000000000000000000000000000000000000000000000000001172c41566c8196abc1c6cfbfaa957f6a55402a15000000000000031628394556606c7982888c8d8a857d736262778ca2c8d8dec9b49e89745544311d080000000d22374b5c70859baba7b2b7c3cbc7bac2c5ced1d4dce7f5e1cbb6a18c76614c37210c00000000000000000000000000000a1a2a3a495a647a8b9fb4c9def1e7d5c4b29d8875604b3828150200000000000000000000000000000f253a4f647a8f7e7e93a8beae99846e59442f190400000000000000000000000000000000000000192e43596e839885778ca1b6c8b39d88735847332f3f4d5f6a7f95a2b4c2b19c86715c4a36220d0000000b20364b60758b8874899fa6907b66513b26162b41566b809698836e5544311d08000012283d52677d928b778398aeae99846f5645321e09000000000000000000000000000000000000000000000000000000000000000000000000000000000007131a283237444b4a433637413d343735312619090000000000000000000000000000000000000000000000000000000000000003162838495a63747c7f7d76655d4b3a2a1804000000000000000000000000000000000001142636485a62737d838687888889898a8a8a8a8b909ea79e98a0b2c4bfac9b918f8e8e8e8d8d8c8f9faabbcee2dec9b39e897e7e7d7a776f645c4d41301d0d000000000000000000000000000000000000000000000000000001162b40566b8095abadb2bec1ab96816c56412c17010000000000081e3245576074818c989ea7aa9f9a92857762768baabbcee1cdb9a88b75604b36200b0000011426374f647a8fa39f929da5b7b7b2a5acb1bdcddbebfcf6e1ccb6a18c77614c37220c000000000000000000000000000818283847586278889ea9b6c3d3e6f2dfcbb7a6937e695645321d0a00000000000000000000000000000f24394f64798e7e7d93a8bdaf9a846f5a452f1a0500000000000000000000000000000000000000192e43596e839883788da2b8c4af9a856f5a3a2a2130414b6073849aa9bab5a48f7a644f3a240f000000081d31445574898a74879da7927d68523d281a2f455a6f849a9e8975604b35200b00000f24394e64798e947f7c91a6b49f8975604b36210c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a161e263135353025222b292022201d14090000000000000000000000000000000000000000000000000000000000000000000a1a2c3c495660676a6861584b3f2e1c0c0000000000000000000000000000000000000008182b3c485560676e70727373747474757575757b899e8a8398a6b7bba6917c7a7979787877777b8b9fb4c9dfd8c2ad98836d69686561584e4a3e30231300000000000000000000000000000000000000000000000000000000152a40556a7f959998a0b2c2ad98826d58432d180300000000081830414b607584969fabb3b8bbb4afa39b8676758a9fb4cadfd7c6a18b76614c36210c0000081d3144556c81969f8d7d879db2a59d8f979fb0bdcddeeeffe1ccb7a28c77624d37220d0000000000000000000000000114263645566176869c949da5b6cadfe2e7d4c4b29d8875604b38271502000000000000000000000000000e23394e63788e7e7d92a8bdaf9a85705a45301b0500000000000000000000000000000000000000192e44596e839882798ea3b9c3ae98836e59432e191c30435463788b9fb4c2ac96816c573d2c1a060000021527375c72878c77859aa9947e69543f291b30455a70859aa88f79644f3a240f00000b20354b6074899e8985959eafa8917c66513a2a1804000000000000000000000000000000000000000000000000000000000000000000000000000000000000000309141d20201c130d16140b0d0b080100000000000000000000000000000000000000000000000000000000000000000000000e1e2c38454b5255534c473a2e21110000000000000000000000000000000000000000000e1e2b37444b52585b5d5d5e5e5f5f5f546060697e948774889db2c9a5907b666463636362626d8297adc2d2dec8b39e897661524f4c473a362d20130500000000000000000000000000000000000000000000000000000000142a3f54697f94838298adc2ae99836e59442e1904000000011426364d5f6e8398a2b4bcc9cccecac1b4a4988273899eb3c8deccb7a28c77624d37220d00000b20354b6074889e988277899fb29d877a82969fb0c0d1e7f7e2cdb7a28d78624d38230d000000000000000000000002101c3043546074859b8b7e879db2c7caced8dfcbb7a6937e685645311d09000000000000000000000000000e23384d63788d7f7c92a7bcb09b86705b46311b0600000000000000000000000000000000000000192e44596e8397827a8fa4b9c2ad98826d58432d18142636495a6b8095a9bab29d88735b4935210c0000001b30455b7085907b8196ab96816b56412c1b30465b70859ba7917c67523c27120000081c3043546e839998828095a9ad98836e5847331f0a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080b0b070000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1a2832363c3f3e37332a1c1103000000000000000000000000000000000000000000000e192731353d4346474849494a4a4a434a4c61778a8f798095abbcad98836e594e4e4d4d4f647a8fa4b5c9deccb8a7957f6a553e37332a211a0f01000000000000000000000000000000000000000000000000000000000014293e53697e937f7d92a7bcaf9a846f5a452f1a05000000081c304354677d91a0b1b5c2d2dfddcfd1c2b2a08f7a879db2c7ddcdb8a28d78634d38230e00000f253a4f647a8f9f8c788196a8a5907c666d8196a2b4c9daece2cdb8a38d78634e38230e0000000000000000000000102030414b607283998d7d77889eb3b2b4bbc8d8d4c4b29d8774604b372715020000000000000000000000000d22384d62778d807c91a6bbb19b86715c46311c0700000000000000000000000000000000000000192e44596e8397817a8fa4bac3ad98836e58432e1908182c3c4c61778a9fb4b7a68d78634e38230e000004192e43596e83947f7d92a798836e58432e1c31465b71869ba9947e69543f291400000114263653697e939a85758a9fb49f8a77614c3828160200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a151d20272a28211f170c0000000000000000000000000000000000000000000000000009151d20282e3132333334343525303547586e839782788c9fb5b49f8b77624c3938384b5c71869cb1c7d7d5c5b29d87725c4a3622170c070000000000000000000000000000000000000000000000000000000000000013283d53687d92807b91a6bbb09a85705b45301b060000000b20354b6073879c9e9ca4b5c9cac7babfcabeb19c87889db2c8ddceb8a38e79634e39240e0000152a3f546a7f94998476899eb29c87725e6072849aabbccfe3e3cdb8a38e78634e39230e000000000000000000000d1d2d3e4d5f6b8095937e76869ca6a59d9faabbcedfcbb7a6937e685544311d090000000000000000000000000c22374c61778c807b90a6bbb19c87725c47321d0700000000000000000000000000000000000000192f44596e8496817a8fa5bac5b09a85705b3d2d1a070e1f3447596d8298adc4a8937d68533e2813000001162b40566b8095868399a59b86705b3b2b1831475c71869cab96806b56412b160000000e23384e63788da29a899ea9baa9947f6a5645321e0b000000000000000000000000000000000000000000000000000000070d0f0d070d0f0f0d0f0d0c100c0b100d0b0f0d0f0d0e0e0f0e0c0a0c0e0f0d0b100c0d0f0e0c06000000000000000000000000000000000000000000000000000000000002090b1215130c0a0400000000000000000000000000000000000000000000000000000001080b12191b1d1e1e1f1f1f131c2a3a51667b918976859ab0bbaa937e68533e292e3e54697e93a9bacddfcab6a58f79644f3a240f00000000000000000000000000000000000000000000000000000000000000000012273d52677c92817a8fa5bab19b86715c46311c0700000215283851667b909e8a869cb1c3b7b2a5aab5bcb6a49c9da6b7cbdfcfb9a48f7a644f3a250f0003162838596f8499917c7e93a8ab96816c565463798d9fb5cadfe3ceb9a38e79644e39240f00000000000000000008182a3b4a5c677d92958074849aa4aa9d878c9fb4c3d4d4c4b29d8774604b3727150200000000000000000000000c21364c61768b817a90a5bab29d87725d48321d0800000000000000000000000000000000000000192f44596e8496817a90a5bac8b39d88735b4a36210804182a3b52677c91a7c5ac97826c57422d1700000013283d53687d929681879d9e89745948342032475c71879cac97816c57422c170000000c2135495b71869ca79ea7b8c7b39d8875604b39291603000000000000000000000000000000000000000000000000010f1a2124211b222424212421212521202522202422242124232423211f21232422202522222423211a0f01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306080809090a00000c20354b607487927d7d92a8c2ae99846f59442f21374c61768a9fb4c9dfd3c3aa95806b55402b1600000000000000000000000000000000000000000000000000000000000000000011273c51667c9182798ea4b9b29c87725d47321d080000091d3245566d8298947f7c91a6b7a59d8f959fabbcb6b1b2b7c4d4e7cfbaa5907a65503b251000091e32455672879d8a768499afa6917c6651495b6f8499aec4d9e4ceb9a48f79644f3a240f0000000000000000011426364759647a8b9882748298a2b49f8b798096a5b7cadfcab7a5937d685544311d0900000000000000000000000b21364b60768b82798fa4b9b29d88735d48331e08000000000000000000000000000000000000001a2f44596f8496817a90a5bacbb8a68e79634e362513000c22374c61778ca7b9b09b85705b38281502000010253a50657a8f917c7e93a78c77624d372232475c71879cad97826d58422d18000000061a2c3d54697f94aab3b8c5cbb7a6937e695746321e0d0000000000000000000000000000000000000000000000000f1f2d3639362d363939363936363a36353a37353936393639383938363335383936363a37373a39352c1f0f000000000000000000000000000000000000000000000000000001080b0d0c0a0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000081d3144556a7f95857b90a4b5b39e88735e49341f3347586d8398adbfd0d9c4af9a846f5a452f1a05000000000000000000000000000000000000000000000000000000000000000011263b50667b9083788ea3b8b39d88735e48331e0900000b20364b6075899e8a76849aafb29d877a808d9fb5c0c7c8cbd4e2e5d0bba6907b66513b2611000b21364b60768b9c8674899eb3a78c77624d3d52687d92a7c7d7e9cfbaa48f7a654f3a251000000000000000000c1c3043546277889b84748096a0b2a595806b75879db2bfd0d4c3b29d8774604b37271501000000000000000000000b20354a60758a83798ea3b8b39e88735e49331e09000000000000000000000000000000000000001a2f44596f8497827a8fa4bad5c4a9947f695443301c090b1f34475974899eb3b39e88735645321d0900000d22374d62778c9d87869ca5907b65503b2632475c71879cad98826d58432d18000000000f22374c62778b9fb4cad6d4c4b39d8875614b3b2b190500000000000000000000000000000000000000000000071a2d3d4a4e4a3e4a4f4e4a4e4a4c504b4a4f4d4a4f4a4e4a4e4d4e4d4c46494e4f4a4b504c4b4f4e493d2c1c0c00000000000000000000000000000000000000000000000009141d2022211e170b030000000000000000000000000000000000000000000000000000000000000000000000000000000000011426374c62778a9b86869cb1b7a68a75604a35172a3a4f647a8fa1b3c6d6c6b19b86715c46311c07000000000000000000000000000000000000000000000000000000000000000010253a50657a8f83788da3b8b39e89745e49341f09000010253b50657a909882798ea2b4a4907b666a7f94a2b4c9dadfe7f2e6d1bca7917c67523c2712000e23384d63788d9984768ba7b39e89735948384d62788da9bacde1cfbaa5907a65503b2510000000000000000c1c2e3f4b6072849a87777f949eb0b29d877460667c91a1b3c6d7cab7a5927d685544311d0900000000000000000000071c304354748a8a889db2c7b39e89745e49341f00000000000000000000000000000000000000001a2f44596f849782798ea4b9cec7b29c8773604a37261404182a3b5c71869bb1b8a78b75604b36200b00000b2034485973889e9d9ca4aa947f6a553f2a32475d72879cac97826d57422d18000000000b1f3447596e8399aec0d0e0cbb7a695806b594834200f000000000000000000000000000000000000000000000d21364a5c645c4d5c64645c645c61656160656260645c645c6363646361585b63645c6065615c64635b493a291704000000000000000000000000000000000000000000031119263135383633291e160a000000000000000000000000000000000000000000000000000000000000000000000000000000000009203448596c8195807b90a5b39d88735e48331e22374b5c6f8499a8b9c9c3af9a846f5a452f1a0500000000000000000000000000000000000000000000000000000000000000000f243a4f64798f83788da2b8b49f89745f4a341f0a0000152b40556a8095907b8095abb19c86715e6073859babbccfe3f8ffe7d2bda7927d68523d2813000f24394e64798e9883778ca2b09b86715b3b354a6074899fb4c9ded0bba5907b66503b261100000000000004172a3a4b5d6a7f948a7a7c8d9fb5b2a0907b66565e6f8399a8bacdd4c3b29d8774604b37261401000000000000000000001325495f748984798da3b8b49f89745f4a251300000000000000000000000000000000000000001a2f445a6f849883798ea3b8cecab6a5917c665544311d0e1b30465b70859bb0c5a28d77624d38220d000005182b3b5a6f849aafb1b6ae99836e593c2b33485d72889dac97816c57422c170000000005182a3b50657b8fa2b4c8dcd5c4b49f8a78624d3d2d1a070000000000000000000000000000000000000000000f24394e6479645f677979647964767a76757a78747964796579787978766165797968757a77697a79635847331f0a00000000000000000000000000000000000000000011212f37444b4d4c463932281b0a0000000000000000000000000000000000000000000000000000000000000000000000000000000005182b3b4d62788989869cb1a898826d58432d181b2e3e4d63788a9eabb4b4a5947f69543f29140000000000000000000000000000000000000000000000000000000000000000000f24394e64798e84788da2b7b49f89745f4a341f0a00031628395a6f849a8975869cb1a9947f695454647a8d9fb5cadff4fde8d2bda8937d68533e28130010253a4f657a8f9782788da2ae99846e594430435472879cb2c7dcd0bba6917b66513c26110000000000000c1f334758657b8c927d798a9eabb6a598826d5e4c4d62788a9fb4c2d3cab6a5927d685544311d09000000000000000000001e34495e7389878096abc0b49f8a755443301c07000000000000000000000000000000000000001a2f445a6f849883788da3b8cdd3c3b19c8673604b3c2c1a1527375b70859ab0c7a28d78624d38230d000000162b40566b8095abc9c8b29d88735a483527375d73889dab96806b56412b1600000000000d23374b5d6f849aafbfd0e1cdbaa997826d5b4a362111000000000000000000000000000000000000000003182d42586d826d677d807f78826d7f7d82807c8278836e827b817e837f7a657a817f7d7d7d847e7b8076614c37210c00000000000000000000000000000000000000000e1e2f3f4b55606261574b4539281603000000000000000000000000000000000000000000000000000000000000000000000000000000000d2034485a657b89999fa39b8a78624d38220d102035495a677d8d9b9f9e988775614b36210c0000000000000000000000000000000000000000000000000000000000000000000e24394e63798e84788da2b7b49f8a745f4a351f0a00091e32465773889b86768b9fb5a88e79634e4a5c6f8499afc4d9eeffe8d3bda8937e68533e2913000f253a4f647a8f9681788ea3ad98836d584325365b71869bb0c6dbd1bca6917c67513c271200000000000c1d30414c617688968176869ca8b9a99c8776614c40485a6a7f94a4b6c9d4c3b29c8773604b372614010000000000000000081e33485d73889d969eb0c3bbaa8a75604a35200b000000000000000000000000000000000000001a2f455a6f849984788da2b7d1c8c4b5a4937e685a4938281d31445572879db2baa98c77624d37220d00000012273c51677c91abbccbb7a68d78624d3831445574899ea9947f69543f2a140000000000081c2e3f4f647a8fa1b3c7d7d7c7b49f8c79634e3f2e1c080000000000000000000000000000000000000004192f44596e847f7c8082827e826d7f8178826d7d7c846f827f7975837f7a697e7a72827c817a8281837c67523d27120000000000000000000000000000000000000006192b3c4b5d657477766d605745321e140000000000000000000000000000000000000000000000000000000000000000000000000000000005192b3c4b5d6579848a8b867b655a4835200b06192c3c4d5f677c858a898378625746321e090000000000000000000000000000000000000000000000000000000000000000000e23394e63788e83788da3b8b49f8a745f4a351f0a000c21364b61768b9883788dabb49e8975604b3e52687d92a7c9daecffe8d3bea8937e69533e2914000e23394e63788e9782788da2ac97826d574232475c71879cb1c6dcd1bca7927c67523d27120000000004182a3b4d5f6e829884748399a4b6b49f8b7a645746333c4b6074869cb1bfcfcab6a5927d675544311d080000000000000000081d32485d72879dabb0bccdb5a08b75604b36200b000000000000000000000000000000000000001a2f455a6f849984778ca2b7c0b4afb1b49e8a786356453228364b60758a9fb4b49f8a74604b35200b0000000d22374c62778b9fb4cac4a7927d67523d354b60758a9fa7927d67523d28120000000000001122374b5c6f8499a9bacde1cfbcab99836f5d4b3723120000000000000000000000000000000000000000182d42586d826d8278828278837f80817e7b81817586828078817f817f7a697e796d827c81807a818277624c37220d000000000000000000000000000000000000000b2035485a657b878d8a8275604b42311b0b000000000000000000000000000000000000000000000000000000000000000000000000000000000d1d2f3f4b5b636f767671655d4b3c2b1905000e1e30414d5e667074746e625a48392816030000000000000000000000000000000000000000000000000000000000000000000e23384e63788d83798ea3b8b49f8a755f4a35200a000e23384d63788d9782798ea4b19c87715443394e63798eabbccfe3f8e8d3bea9937e69543e2914000c22374c61778c9883778ca9ad97826d584231475c71869cb1c6dbd2bda7927d68523d2813000000000a1f344759677c9188778095a1b3b19f937e685c4a3929314455657b90a0b2c7d3c3b29c8773604b3626140100000000000000071d32475c72879cb1c7cdcbb6a08b76614b36210c000000000000000000000000000000000000001a2f455a6f849a85778ca1b6b4a29a9ca4a89b8574604b4538394e63788daabbb09b86715544311d080000000b1f34475970859aafc7c2ac97826d573d384d63788daba5907a65503b2510000000000000081b2e3e4e63798b9fb4bfd0d9c9b3a18f7b6550402f1d090000000000000000000000000000000000000a162b40566b80807c676d6d626e6a6b6c69666c6c61716c6b626c6a6d7f7a667c78697e696c6a646c6c625947341f0b00000000000000000000000000000000000005192b3c4d62788a9da69f97836e604e392816030000000000000000000000000000000000000000000000000000000000000000000000000000000011212f3c494d566061574f4b3f2e1e0e000000132330404c505b5f5f594d483c2b1b0b000000000000000000000000000000000000000000000000000000000000000000000e23384d63788d82798ea4b9b59f8a75604a35200b000f24394f64798e97817a8fa4af9a85705a36364b60758a9fb5cadff4e9d4bea9947f69543f2a14000b20354b60758a9a8575899fad98826d584331465b70869bb0c5dbd2bda8937d68533e28130000000a1a30404c6177888b7a7c8d9fb5b4a297816d604e3e2d1b27374b5d6e8398a9bacdcab6a4927d675443301c0800000000000000071c31465c71869bb1c6dbcbb6a18c76614c37210c000000000000000000000000000000000000001a30455a6f859a86758ba0b5af9a84869caaa398826d60564d4b57687d93a8c0ab95806b563727150100000005182a3b53697e93a9bac7b29d87725b493c51677c91a6a78d78624d38220d00000000000000102135495b697f94a1b3c2d3d0bfb09b85705e4c38240f00000000000000000000000000000000000a1a28323650626b6b675f58584d59545657535157574b5c57564d57546169645e666361696156554f56574c473b2a18050000000000000000000000000000000000000b2035485a6d8297a8b7b4a1937e685746321e0a0000000000000000000000000000000000000000000000000000000000000000000000000000000003111e2c3538454b4b4639372e2110000000000513222f383b464a494338342b1d0d00000000000000000000000000000000000000000000000000000000000000000000000d23384d62788d827a8fa4b9bcab8a75604a35200b0010253a4f657a8f96817a8fa5ae99846f594432455673889eb3c8ddf3e9d4bfa9947f6a543f2a1500081d31445573889d8873879caf99846f5a3c2b3b5c71869cb1c6dbd3bda8937e68533e29130000021628384c5e6e83937e79899eabb7a69b8474604b4231200f192e3f4d62788a9fb4c3d3c3b19c8673604b35201100000000000000061b31465b70869bb0c5dbccb7a28c77624d37220d000000000000000000000000000000000000001a30455a6f859a8a8298abbcaa95807a8c9fb4a09781746962606475869cb1b4a28e79634e39230e00000000000d22374c61778a9fb4c9b7a58d79634e3e556b8095aa9e89745a4835200b00000000000000061a2c3d4b60728399a4b6c3d3c9b5a3907b66513b26110000000000000000000000000000000002162838454b575a5e5b554e493d38433f40413e3b4142364642403842434f544f4c514d4f544f42403a414237342a1d0d00000000000000000000000000000000000004172a3a4d62788b9fb4c6bfb39e8875614b3828160200000000000000000000000000000000000000000000000000000000000000000000000000000000000e1921283236363329221b1002000000000003111c23263035342e2220190d0000000000000000000000000000000000000000000000000000000000000000000000000d22384d62778d817a8fa5bab59f8a75604a35200b000f243a4f64798f9782798fa4ae99846e594428385c72879cb1c7dcf1e9d4bfaa947f6a553f2a1500011426375a6f849a8c778398ad9d88735a4835485973889db3c8ddd3bea9937e69543e29140000091e324556667c918d7f869ca7b9a99d877762564531241401112035485a6a8095a5b7cbcab6a4927d67523f2e1c08000000000000001b30455b70859ab0c5dacdb8a28d78634d38230e080000000000000000000000000000000000001b30455a70859a897b8b9fb5aa957f6a7f95a2b19f97877e78767a849aa4b6ab9a846f5b4935210c00000000000b1f3447596d8297abbcc3ad98826d5c4a5c71869bae99846f593c2b190500000000000000000e1c3043546176869ca5b6c3d1c1af9a846f5a452f1a05000000000000000000000000000000091e324556606c6f73706a635b534c473b4038454b453839373435313538353f39363c383b3e3b322b252c2d221f180d000000000000000000000000000000000000000a1f3347586c8196aabbcecbb8a6947f695645321e09000000000000000000000000000000000000000000000000000000000000000000000000000000000000060a161e21211e170b08000000000000000000090f111b1f1f190d0b05000000000000000000000000000000000000000000000000000000000000000000000000000d22374d62778c817b90a5bab49f8a755f4a35200a000e23384e63788d9883788ea3ae99846e594431465b71869bb0c6dbf0ead4bfaa957f6a55402a150000152b40556a8095917b7e94a9a68d78624d384c62778ca6b8cbe0d4bea9947f69543f2a1400000b21364b60758786788b9ca4b5b49f8b7a645948382715060005192b3c4b6075879db2c0d1c2b19c86715d4b37230e000000000006141a27455a6f849aafc4d9cdb8a38e78634e3929221b1002000000000000000000000000000000001b30455a70859a88778c9fb5a9947f6a72849aa4b1a59d938d8b8f9aa2b4b59f8d7a644f3d2c1a06000000000004182a3b4e63798c9fb5c4b49f8c79645464798ea3ab947e69543f29140000000000000000000114263647586278879ca4b4c0c9b49f89745f4a341f0a0000000000000000000000000000000b21364b60768285888580797169615956564c5660564d4f4d484b44494e4a484d4c46393e35404337342a1d0d0b0500000000000000000000000000000000000000011527374c61768a9fb4c8d8d5c5b39d8875604b372614010000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090b0c0a030000000000000000000000000000060a0a04000000000000000000000000000000000000000000000000000000000000000000000000000000000d22374c62778c807b90a6bbb49f8a745f4a351f0a000c22374c61778c9a85768ba8ae99846f594431465c71869bb1c6dbf0ead5bfaa95806a55402b1500000f24394e64798e9681798ea6a8937e68533b52677d92a7c4d5e7d4bfaa947f6a553f2a1500061a2c3d53697e93848196aab5b09e927d675c4a3b2a1a0a0000000e1e324557677d92a2b4c9c9b5a4907b65503b251000000000001424313845596e8399aec3d8ceb9a48e79644f473a372e2010000000000000000000000000000000001b30455a70859a9d8c9fabbca9937e696176869ca4b1b2a8a2a0a4b0b4b2a296816c5c4a361f0f000000000000000c2135495b6e8298a6b8bcab9a84726772849aaf9f8c78624d38220d000000000000000000000818293a485a6278869aa2b4b9b39e89735e49341e09000000000000000000000000000000091e324556606c6f777f898e867e77706c6b616376675f64625960555b63605962615758544b56584c473b2a19090000000000000000000000000000000000000000081d3144556a7f94a8bacde6e0cbb7a6937e685544311d0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c22374c61778c807c91a6bbb49f8a745f4a351f0a000b20354b60748a9c8774899eaf9a856f5a4527375d72879db2c7dcf2ead5c0aa95806b55402b1600000d21364a5c72869c8772889daf9a846f5947586e8399aec3d8ead5bfaa95806a55402b15000c2135495b72879d9a969fb0b3a196806b5f4d3e2d1d0d00000000031628394d5f70859aabbccfc2ac96816c57412c17000000000e1e31424e56606e8398adc3d8cfbaa48f7a6561584f4b3f2e1b08000000000000000000000000000000192e44596e8399aea2b5bcc6a8927d685862778697a0b0b4c0b5c3b7b2a0988473604b3e2d1b0100000000000000061a2c3d4d6277889ea7b6b4a298827d8399a2af9a846f5a4835200b00000000000000000000000c1c2b3c495a627784959ea8a397826d58422d180300000000000000000000000000000002162838454b5759616976808a938a8581807679887d697977667567677872647776616e69606b6e61594737271c13080000000000000000000000000000000000000b20354b6074879db2c6d7e6e7d5c4b29d8774604b35200f0000000000000000000000000000000000000000000000000000030a0c0b09020000000000000000000000000000000001080b0d0e0d0b090300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c21374c61768c848298aec3b49f89745f4a341f0a00081c30435472889d8a75869bb09c86715c3c31445574899eb3c9def3ead5c0aa95806b55402b160000071a2d3d53697e93937e869cb19f8b77614c61768a9fb4c9deead5c0ab95806b56402b16000e23384e63788da5afacb0b4a3998372604b413020100000000000000a1b30414e647a8c9fb4c0c5ad98836d58432e1800000006192c3c4e6068757b879db2c8ddd6c0ab9680777672645d4b37220d000000000000000000000000000000152a40556a7f95aabecaccb9a8907b665059627582909aa2a7a9a8a59d9383756155443120100000000000000000000f20344859647a899da5b3b2a0989299a1b09f8f7a644f3c2b19050000000000000000000000000d1d2c3c495961737f898e8e8576614c36210c00000000000000000000000000000000000a1a2832363b474c58616b777e8a948a7f70859a887e8a857b897d7d8a8079898477837e75808377615544353025180a0000000000000000000000000000000006192b3c51677c91a5b4bbc8d8eadfcab7a5917c66513d2d1a0700000000000000000000000000000000000000000000070d0f171e21201d150e0c0700000000000000000000070d0f151d20222322211e16130c0a04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c21364c61768b848399aec3b49f89745f4a341f0a00011426365a6f84998d788298ad9e89745a48354b60758a9fb5cadff4ead5c0aa95806b55402b160000000f21364b6176899e8a8298a2aa95806b5b697e94a8bacde1ebd6c0ab96816b56412c16000f253a4f647a8fa7b9bcb4a29a857561544330231302000000000000001322364a5c6b8196a2b5b6a7947f6a543f2a150000000c2035495a687e898f9da6b7cac9c7c5b09e968c8c877b644f3a250f0000000000000000000000000000000f24394f64798ea0b4bcb9b39e8975614b4857616d7b858d9294938f877e6e6157463727150200000000000000000005182b3b4b5c64798799a1b0b2ada7afb4a196816c5c4b371e0e00000000000000000000000000000e1e2c3a4755606a75797972615846331f0a0000000000000000000000000000000000000a161e212a343a4a5b657b86867f776a6c819684949c86898a89888885869c89888985858281857360534a4336281a0a0000000000000000000000000000000b2035495a6f849a9f9faabbcee2e6d4c3af9a84705b4a36210a000000000000000000000000000000000000000001101b222429333636312724211a0f03000000000000070f1a212427313537383736322828211f170c0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c21364b61768b7f7e93a8bdb39e89745e49341f090000152a3f556a7f94917c7e93a8a88d78624d394e63798eabbccfe3f8e9d4bfa9947f6a543f2a150000000a1e3246576a80958975859ab09f8a786979899eb3c6d7e9ebd6c1ac96816c57412c17000b21364b6075899ea8ab9f968476615746362614050000000000000000071b2d3e4b607484999fa49c8977624c37220d0000000d23384d62788d9ea7afb2b3b4b4b2b0aeaba9a1a598836d58432e180300000000000000000000000000000d22364a5c6d82979faba79e937e69574639464b5d6570787d7f7e7a7368604c463929190900000000000000000000000d1d2e3e4b5b637784919ba3a7a8a89e958374604b3e2e1b000000000000000000000000000000000e1c2a37444b566064646054463a2917040000000000000000000000000000000000000002090c1823394e63798a7b70827e69647a8e878298838697828b917c889882889580888975817e72686054453828160300000000000000000000000000011426364d62788c9f8c8b9fb4c9dff1dcc8b4a28e79634e3828160300000000000000000000000000000000000009141d2d363a39464b4b453839362d1e170b00000001101b222d363937444b4c4d4d4b45393d3633291f170c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b20364b60758b8a889eb3c7b29d87725d48321d0800000e24394e63798e9681798fa4a7927d67523a52687d92a7c9daecf7e8d3bea8937e69533e2914000000031629394c6176899882879db2a99c867e879ca8b9cce1e8ecd7c1ac97826c57422d1700091e324557667c8a93948c80746158463929180800000000000000000000101d3245566176838b8c877b645947341f0b0000000b20354b60738390969a9d9e9f9e9d9b999694918f8b7c66513c2711000000000000000000000000000000071b2d3e4b6074828b908f897e69604e3929333f4b505a626769686460544e4233291b0b0000000000000000000000000010202e3d4959616f7c868d92939089807360564531201000000000000000000000000000000000000c19273138454b4f4e4a4336291c0c000000000000000000000000000000000000000000000014293f54697e897571868978656e83947f878c7e8a897f94837b8c8a7c8b897d8b818593877e72605645321e1000000000000000000000000000081c3043546b8095937e7e92a8bdd2dcdfd1c0ac96816c5645321e090000000000000000000000000000000000091926313e4a4f5857616056574e4a3d33291b0e0009151d2e373e4a4e565560626362605759524c463a33291c10020000000000000000000000000000000000000000000000000000000000000000000000000000000000091d31455674899e9ea7b8c5b09b86705b46311b0600000c21364a5b71869c867d92a8ae98836e5847586e8399aec3d1dfe2e7d4c4a6917c66513c2711000000000b1e334657697f94989da5b7b6a49c939ca5b6c6c9ccd6e4d7c2ad97826d58422d1800031628394c5e66777e7f796b6056463a291b0b0000000000000000000000021528384658616e767772645d4b3b2a1805000000081d31445560727b818488898a89888683817e7c7a76665e4c39240f00000000000000000000000000000000101e324556606d777a7a7569604e42311b1e2f373c494d5254534f4b4336311e170b000000000000000000000000000002101f2c3b474c5f6771787d7e7b776b6055453827150200000000000000000000000000000000000009151d2832363939353025180c00000000000000000000000000000000000000000000000011273c51667c917d677d92877b6f788a897d92877e9383828a7a7f94837d928480937e7f86918374604b3e2e1b070000000000000000000000000b20354b6074889d89758499aec3c7c7cad4c9b39e8975604b36210f0000000000000000000000000000000001142637444b5c646d737675726c635b4c46392b1e0e1927313e4b4f5c646b717577787776726e6861584c473a2e20100200000000000000000000000000000000000000000000000000000000000000000000000000000000021527385b70859ab0b8c5c7ae99846e59442f19040000071a2d3d53697e939c888a9eb49f8a76614c61778a9fb4c8bccaced9cbb7a68d78634e38230e00000000031729394b6074869ca7b7c3c2b6b1a8b2b6b2adb4b9c6d6dac9ac97816c57422c1700000a1b2f404c5962696a635b4b4538291c0c000000000000000000000000000a1a293a464c586162594f4b3f2e1d0d0000000001142637445460666c6f7274757472706e6c69676561574c40301d090000000000000000000000000000000003162838454b5961656560564e42312414111c232c35383d3f3e3a35302618130300000000000000000000000000000000010f1d2a34404d515b6367686661584b4437271a0a0000000000000000000000000000000000000000010a151d202424201c1308000000000000000000000000000000000000000000000000081c2e3f4b60758889786c819790847b809580818877817f7686898486907b80867686877e797c89826d5c4a36220d00000000000000000000000316283950657b909580788c9fb5b6b2b2b7c3ccb9a7927d68523d2c1a060000000000000000000000000000000c1d314455606b7a83898b8b8781796d6157493c2b1d2837444b5c646f7980868a8c8d8c8b88837d766b61584a3e2e20100000000000000000000000000000000000000000000000000000000000000000000000000000000000152b40556a8095aabfcdbaa9947e69543f2914000000000f21364b617689937e7e92a8a995806b5b6a8095a9b8b3a7b4bbc8c4b29d8874604a35200b00000000000b1d3245566379899ea6b4c0c7c7c6bab4a0989ea8b9c9cebcab947f69543f2a1400000011222f3b484c54544e4a3d32281a0c0000000000000000000000000000000c1c29333a464c4d483b372e201000000000000009192636434a51565a5d5e5f5f5d5b59565452504c46393022120000000000000000000000000000000000000a1a28323b474c504f4b45383124140600080e192023282a2925201c140800000000000000000000000000000000000000000c181f30393d494e5253514c473a3127190a000000000000000000000000000000000000000000000002090b0f0f0b0700000000000000000000000000000000000000000000000000000e23374b5d65777e93867675858b879089988b7e7e7b7a6a61767e787586877679887b848275677b8b79644f3a240f0000000000000000000000091e3246576d82988a778297abb6a59c9da5b7cac5b09a85705b4936210a00000000000000000000000000000c1d32424b6073808d989ea7a59d978c8276625a493b2a384555606b7a848e959b9fa9a2a2a59d99928a8076645c4a3e2d1c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000e24394e63798ea1b3bfb49f8a77624c37220d000000000a1e3246576b8095848095aab49f8b796a798b9fb4a69e919faabab7a696806b5443301c070000000000021528384a5b6379889aa2adb1b2b0a89f93838a9eabb8bbb49f8c79634e38230e00000003111d2a34373e3f39362d1e160a00000000000000000000000000000000000c171f29333637342b221b10020000000000000009182530353b414548494a49484644413f3c3a3633291b1204000000000000000000000000000000000000000a161e2a34373b3a3632281a140600000000060c0d1214130f0b08010000000000000000000000000000000000000000000004121d242c35383d3e3b37332a1d150900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010253a50657b88738195877b7a8b747b7f828b9486868578706b686263798a81778986726d615d6d827c67523c271200000000000000000000000c21364b6176899883778a9fb4b29c87879db2c3c8b4a28e79634e3828150200000000000000000000000004182a3b4f606d82969fabb3b8b7b2ab9f9786786259483745566073808c9aa2abb0b4bac7c3b7b2aea89e95877a645c4a3a2917040000000000000000000000000000000000000000000000000000000000000000000000000000000c21364a5b6f8499a5a8a196806b594834200b00000000031629394c6176899b959eafbaa99d8880879da9b39e887c8c9fa9a69d8876614c362513000000000000000a1a2d3d4a5b63788490989c9d9b958a7e6d7d8d9ea7aa9f96816c5b4935210c00000000000d181f22292a23211a0f0200000000000000000000000000000000000000040c171f212220180d080000000000000000000008131c20262c2f3334353433312e2c292725211e170b00000000000000000000000000000000000000000000030c181f222525211e160a000000000000000000000000000000000000000000000000000000000000000000000000000000000a0e1a2123282926211f170c010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1d2a43586e83927d73808b908c806b666a6d7d92807983868581786860687e826d7b816c544b4f647974604b3621120400000000000000000004172a3a52677c928f7a7f94a9b8a6907b7e92a5b6cac0ab96816c5645321d090000000000000000000000000b1f344759697e93a0b5bcc9cccac9bcb5a49c877762554454607483969fabb4c0c6c9cdd7d4cbc7c6b9b4a59d8b7a645847331f0b000000000000000000000000000000000000000000000000000000000000000000000000000000071a2d3d4d6278879193908374604b3b2b180500000000000b1f3347586a7f94a3afbcc7b7a69d959da5b6a695806a7e8a9392887a64584733180800000000000000000f1f2d3d4a5a62707b8387888580776960677d888f908b8072604b3d2c1a06000000000000050b0d14150e0c070000000000000000000000000000000000000000000000040a0c0d0b050000000000000000000000000000070b11171a1d1f201f1d1b19171412100c0a0300000000000000000000000000000000000000000000000000040b0c10100b090300000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c0e1213110c0a040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004182a3b4752677d9288766b797f7d737b72605f697e7b807c7d838b8b7e6874827560656c6251464b5c646056483b2f22120200000000000000000a1f3347586f84998773879cb2b39e887373879cb2c3c8b39e8975604b36200f0000000000000000000000011426364c6177899eb4b3b5bcc9cac7c0c2b6a59a8473604b60728399a1b4bcc9d0cbc8bcbdc9ccd6d7cdc3b7a99d8876614c392917030000000000000000000000000000000000000000000000000000000000000000000000000000000f2035485a62747c7e7b72605645321d0d0000000000000417293a4b6074859ba7b7c4c4b7b3aab2b6ab9d88756168787d7d75645c4a3a2a17000000000000000000010f1f2d3c494d5e666d7273706a62594f5f67747a7b776b605443301f0f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1f344759616a708496816c636a697f8a806b61757a676a78746e7884927d7e927d676161584c5761686b6962594c402f201000000000000000000c21374c61768a947f7a90a4b6ac97816c687d92a5b6cab8a7927d67523d2c1a0600000000000000000000081c3043546a8095a8a79e9fabbcb6b1abb3b8b4a2947f6a5d6b8095a1b3bfcfd5c4b8b3a6a8b4b9c6d5e1d4c7b7a696806b5746331e0a00000000000000000000000000000000000000000000000000000000000000000000000000000005192b3c48566066696660544538281500000000000000000c1d3144556378899da6b4c0c7c8c5b9b39f8d7c66575a62686761574a3d2d1c0c00000000000000000000010f1e2c35404c50585c5d5b554c48414d5660656561584b43362614010000000000000000000000000000000000000000000000000000000000000000000000000000000001030405050607080001080b0c0c0d0e0e0c0a0400000000000000000000000000000000000000000000040a0c0d0e0e0e0e0e0e0d0d0d0d0d0c0c0c0c0b0b08010000000000000000000000000000000000000000000000000000030a0c0d0c09030000000000000000000000000000000000000000000000000000000000000000030a0c0e0f0e0c0a0400000000000000000000000000000000000000000000000000000000000000000000000000000000000c22374c6177807678898c7c665b738888847f6d82897c7b8a806a7a80848b7d8d89777677665e61757d807e77665e4c3e2d1b0700000000000005192b3b53687d938b778398adb7a58f7a656074879cb2c3c5af9a85705b4935210a000000000000000000000b20354b6074879da69e898d9fb5a49c969ea7b3b49f8a77657a8c9fb4bfd0d5c4b8a69e91929ea8b8c5d5e5d4c4b49f8a76614c36210c000000000000000000000000000000000000000000000000000000000000000000000000000000000e1e2b38454b5153504a4336281a0a000000000000000002152737495a6379889ba2aeb2b2b0a79e927f6a5e4c484d53524b46392d1f0f000000000000000000000000000e19202f383b434748464037343038454b4f504c473a3026180800000000000000000000000000000000000000000000000000000000000000000000000002090b10141718191a1b1b1c1d1e141c202122222323221f18120c0a0400000000000000000000000000000000070b171f212323232323232323232322222221212120201d141a12100a01000000000000000000000000000000000000010a0b171e2123211e160b0a0100000000070b0700000000000000000000000000000000000000050b0d161e21242424211f17130c0a03000000000000000000000000000000000000000000000000000000000000000000000000000d22384d62778d88807f8a8979666c81947f847f8d84868689857e8688838985829885898a7c667285808088897c665c4a36220b0000000000000b2034485970859984768a9fb4b29d87736055687d92a5b7c8b4a28d78634e382715020000000000000000000f243a4f647a8fa59e8876869bb19c86808899a1b3a8978174869cabbccfdac9b8a69d887c7d8a9ea7b8c8d8e1cdbaa9927d67523d2712000000000000000000000000000000000000000000000000000000000000000000000000000000000e1e2c3c484d565a59524d4134271704000000000000000009192c3c495b63788591989c9d9b94897d6a614f4035383e3d3632291b0f01000000000000000000000000000006121c23262e3233302b22201a2731363a3b37332a1c14080000000000000000000000000000000000000000000000000000000000000000000000050a161e21252a2c2d2e2f3031313233263035363738383837332a28211f170c0500000000000000000000000008131c2029333638383838383838383838383737373636363531263027251e13050000000000000000000000000000000002131e2529333638363228251e13020008131c201c1308000000000000000000000000000000030e192022293236393a3937332928211e170b0400000000000207070300000000000000000000000000000000000000000000000000000b2034485a6a7f868a8e9196887c7979898978858a8b7d879a84848a88808a9580889883858a787a8f7c7d77838a7a644f3929170300000000000d22374d62778c927c7d93a9baab95806b544b6074879db2c4c0ab96806b5645311d0900000000000000000014293f54697e94a5937d798c9fa38f7a6b778399a1b49f8b8499a4b6c9d9cfbcab9d887867687a899eaabbcee2d7c7ad98836e583a2a1704000000000000000000000000000000000000000000000000000000000000000000000000000006192c3c495a626c6f6e675f52453422120000000000000000000e1e2c3d495a62737c838788857f76675f4f433220222828211e160b000000000000000000000000000000000000090f11181d1e1b150d0b0a151d202526221f180c0100000000000000000000000000000000000000000000000000000000000000000000000e19202832363b3f41434344454647484849434b4b4c4d4e4d4c473a3d37332a20190d0000000000000000000008182530353a464c4d4e4e4e4d4d4d4d4d4d4d4d4c4c4c4b4b4b4449453d393023150700000000000000000000000000000a151d303a39464b4d4b46393a311e16131825303530251816080000000000000000000000000b171e2b353839464b4e4f4e4c473a3d3633291f170c00070d0f181c1c180e0c07000000000000000000000000000000000000000000000005192b3c50616a7175797c808d9086868999877e849a87798795808497827e93897f94897e86837e939092827484846f5746331e0a00000000061a2c3d54697f948976859ab0b6a48e79644e4455697e93a6b8c8b39e8875604b36200e000000000000000004192e43596e83989d8775859aab9b86715c62738399a3a99f99a1b3c2d3dfcab59f8d7b655a5c647a8c9fb4c8d8dcc7b29d87725847331f0a00000000000000000000000000000000000000000000000000000000000000000000000000000c2035495a63788184837c6c635240301d090000000000000000000f1f2c3c485460666e7273706a61584d413225150d13120c0a0300000000000000000000000000000000000000000000030708060000000002090b10100c0a04000000000000000000000000000000000000000000000000000000000000000000000003101e2b3538454b50545658595a5a5b5c5d5e5e54606161626363615859524c473a342b1d0e000000000000000000132536434a545861626363636363636262626262616161616060555e5a524d41332515000000000000000000000000000a1a2832414d525761626157524d413228243136434a433634261605000000000000000000010f1b29333c484d555761636463615859524c4639332a1c121b22242d31322d24211a0f01000000000000000000000000000000000000000000000d1d33435055566063666b7e8c86777383917c7684978278878c7d84937e7f9486818a847f947f94868385707a8c76614b36210c000000000c2135495b71869782788c9fb5b19c86715c4a374b6075889eb3c5b8a6917c67523c2c190600000000000000021628385c71869b937e798fa2aa95806a55556074859ba9b4aeb3bfd0e0d8c3ae98836e5d4b4b5c6b8095aabbcedfcab7a58c77614c37210c0000000000000000000000000000000000000000000000000000000000000000000000000006192c3c4d637888969a9891816c5e4c38240e000000000000000000010f1e2b36434b51595d5d5b554c473a302315070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010212e3c484d566065696c6d6e6f7070717273747475767777787877736e6761584d483c2c1e0e00000000000000071c3043546069727678787878787878787878777777767676757575736f675f5044331b0a00000000000000000000000a1a2838454b5f677176787671675f4b453832424e546054514434210e0000000000000000010f1f2d39464c5a626b717679797976736e6861574c473a30202d36394246474339362d1f1103000000000000000000000000000000000000000000001525333c38454b4e5160687b89887a77878a7a7584937e78878a7b858d798195808489838a8183908c7e69748978634d38230e000000000e23384e63788d907a7f95abbcaa947f6a553d3245566a7f94a7b9c5af9a846f5a4935200b00000000000000091e32455674899e8b778297ada6907b6651455663798b9fb4c6c7d0dde6d1bba6917c66513f3e4c61778b9fb4c9dfd4c3a48f7a644f3a250f000000000000000000000000000000000000000000000000000000000000000000000000000c2135495b6f849aa6afae9f917c66513c2c1906000000000000000000000e182630353c434748463f37332a1c13050000000000000000000000000000000000000000000000000000000000000000000000040a0c0d0c0a0300000000000000000000000000000000000000000000000000000000000000000000000000081b2e3f4b5a626c757b7f818283848586868788898a8a8b8c8d8d8d8c88837d776d625a493c2c19060000000000000b20354a60727e878b8d8d8d8d8d8d8d8d8d8d8d8c8c8c8b8b8b8a8a88847d6a625039281603000000000000000000021528384556606e7d868b8d8b867d6e605645434f6068756b62513d291400000000000000000f1f2d3d4a57616c7880868b8e8f8e8c88837d766b61584d41353e4a4f575c5c584e4a3d2f2211000000000000000000000000000000000000000000000715202828323639414e5d6578848b7f7989887875848c7c78878878817373857d77877786826e7b7c6960718674604b36200b000000081b2e3e556b80958775879cb2b4a38d78624d3828384c6176899eb3c7b59f8c78634d392917030000000000000b21364b60758b9a8575899eb3a38d78634e384a5b6b8096a8b9cde1ede2cdb8a38d78634e383447596f859aafc4dad2bda7927d68523d2813000000000000000000000000000000000000000000000000000000000000000000000000000e23384d63788da2b4c5bdb19b86715b4935210c000000000000000000000008141c20272e3233302a211f170c0000000000000000000000000000000000000000000000000000000000000000000000070c171f2123211e160b0500000000000000040a0c0d0b09020000000000000000000000000000000000000000000e22374b5d657882899094969898999a9b9c9d9d9e9fa9a0a1a2a3a2a79e98928b8278635a4935200c00000000000014293e53697e939ca4a2a3a3a3a2a2a2a2a2a2a2a2a1a1a1a0a0aa9f9e9a92806a5745321e09000000000000000000081d324556607483929b9faba39b928274604b4f61697e89806b56412c16000000000000000c1c2d3d4a5b6376818b959ca4a3a4a3a69d99928a8076675f4b494d5c646d71716d635b4c402f1b0b00000000000000000000000000000000000000000000030d0a151d2024313f4c5a6273808c857f8986777d89897a7a8985797a7e777262756175746066665e617779645544311d080000000d22374b5c728795807a8fa5b6b09b85705a4935203346576b8095a9babcab96816c5746331e080000000000000d22374c62778c95807a8fa8b9aa8b76614b363d4c6177899eb4c9def2e0cbb6a18b76614c362a3a576d8297acc2d7d4bfa9947f6a543f2a150000000000000000000000000000000000000000000000000000000000000000000000000013283d52687d92a7c0d1c9b5a38d78634d38230e00000000000000000000000001080b11191d1e1b150c0a040000000000000000000000000000000000000000000000000000000000000000000002101b222933363836322920180d000000070c0e171f2122201d1517110b0902000000000000000000000000000000031628394f657b8a979ea8a9abadaeafafb0b1b2b3b3b4bab6b6b7b8c5b8b3aeaa9f988878634d38230e000000000001162b40566b8095abb6c3b8b8b8b8b8b8b7b7b7b7b7b6b6b6b6b5bbb4b3af9f8a76604b36210b000000000000000008182f404b60748499a1b0b5bcb5b1a097826d5f5d697f929b85705b46301b0000000000000417293a4a5b637987969faab1b5c2b9c4b7b2aea99f96897c6c605a626e7a8286878279665e4c3929170300000000000000000000000000000000000000000000000002090b13212f3c4855606a798592889c867779868f8382898d837f696055605660605550514d5961645c4a372715020000011527374f647a8f907c8197acbbaa937e69543c2c1929394c62778b9fb4c9b39e8976614b3626140100000000000d23384d62788d927c7e93a8b49f8a755746323347586c8297acc4d5e7dfcab5a08a75604b352b41566b8096abc0d5d6c0ab96816b56412c1600000000000000000000000000000000000000000000000000000000000000000000000001162b40566b8095abc0d5d2c1a6917c67513c27120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010202e373a464c4d4b4639342b1d0d030f1a21232a3337373632282c26201d150a0600000000000000000000000000091e32455771869ca8b4b9c6c1c2c3c4c5c5c6c7c8c9c9ced8cccccdd5ccc8c8bbb4a698836e58432e190300000000000e23394e63798ea5b7cacdd5c4b8b3a8a8aaabacadaeafb0b1b2b4b9b4b2a18c77614c37220c00000000000000011426364c5e6c8196a2b2bfcacfc9beb1a0927d67657b8d9f98836e59432e190000000000000a1f3347586379899da5b4bbc8c9d2ced4cbc8c7bab4a79e9181756e78838c979b9c988b7c665746331e0a00000000000000000000000000000000000000000000000000000003111d2b37444b5b63707d88939a85707786877279887b69614a444b454b4b44373c3a474c4e4a3e2d1909000000081d3144556c81968986979fb1b49f8b77624c37220e203448596d8297abbcb9a8937e695443301c0800000000000e23384e63788d8f7a8196abb49e89745f39282a3a4f647a8fa6b7cbe0dfcab59f8a755544312c41576c8196acc1d6d7c1ac97826c57422d1700000000000000000000000000000000000000000000000000000000000000000000000001172c41566c8196abc4d3cebbaa917c66513c271100000000000000000000000000000000000000000000000000000000060c0e14181a1917110b080100000000000000000000000000000000000e1e2e3e4b4f58616261574d483b2b19171e2d36393a474c4d4b4538413b36322820190e0300000000000000000000000b21364b60768ba4b5c6cdd6d6d7d7cdc9c7c8c9caced8cdcecfd0d0d9cfcac7c7bab09b86705b46311b0600000000000c21364a5b72879db2c7dccbb8a69d939394969798999a9b9c9d9ea89f9c95836f5947341f0a00000000000000081c304354667c909fb0c0cfc9c6bcc4beb39e887774879dab95806a55402b150000000000061a2c3d4c6176879da7b6c3cec7c4bfc1c7cad3d7cdc5b9b39f9786838b989fabb1b1a99e8876614c36210c00000000000000000000000000000000000000000000000000000000000d1926313d4a4e5f67757e88806b6277806b637773604b4331353236353127272a343739362d2010000000000b20354b607488937e7d92a7bdaf9a846f5948341f0b182b3b4e63798c9fb5c6b29c8773604b35201100000000000e23384e63788d8c778399aeb49e89745f492720354a6074889db3c8dddfcab59f8a75604a352d42576d8297acc2d7d7c2ad97826d58422d180000000000000000000000000000000000000000000000000000000000000000000000000013283e53687d93a6b6c2bbb49f8b77624d37220d0000000000000000000000000000000000000000000000000000070f1a21232a2e302e2c26201d150900000000000000000000000000000006192c3c4b5c64717678766e625948372729333d4a4e5758616260565b56514b4538352b1e160a000000000000000000000d22374c62778ca6b7cbdfe9e9d7c6bab4b2b3b3b4bbc8b8b9babbbbc9bcb4b2ada99f947f6a543f2a15000000000000071a2d3d5d72879cb2c7dcc8b39d887e7e7f8081828384858688898a8a878075604b3a2a1804000000000000000b20354b6073869cb1bdcdc1b5b0a7aeb3b8a69a848196a5a48f7a644f3a240f00000000000c2135495b6d8297a5b7c5ccbfb3afaaabb1b6c2cad4d6ccbdb1a49c989faab5bcc9c7b8a7927d67523d271200000000000000000000000000000000000000000000000000000000000009141d2d36414d56606975726059626b625962605544311d201e21201d1511181f2224221b10020000000316283950667b909a84869cb1baa9927d68523b2a18050d2135495b6f8499aec1b6a5917c66513f2e1c08000000000e23384d63788d8b76859ab0b49f8a745544311d3043546d8298adc2d7e0cab5a08b75604b362e43586d8398adc2d8d7c2ad97826d58422d18000000000000000000000000000000000000000000000000000000000000000000000000000c21364c6176889ca4a8aa9f95806b594834200b00000000000000000000000000000000000000000000000002101b222c35383f434544413b3531271c1308000000000000000000000000000c2035495a647a858b8d8a83776255443139464b5b636d7376777574706c6660564d483c32281a0e0000000000000000000b20354a6074889db2c8ddf2e1cdbaa89f9d9d9e9faaa1a2a4a5a5a5a4ab9f9c98928a8073604b35200b000000000000001e33485e73889db3c8d9c4af9a846f696a6b6c6d6e6f707173747575726b605745321c0c00000000000000071a2d3e52677d92a4b6c9c4b5a39b9199a1b3b4a29a969fb19c8773604a35200b00000000000e23394e63798c9fb4c3ccbbaea19a94969ca4b2b7c3d4e0cec2b5b1adb4bbc8cfdad4c3a9947f69543f2a1400000000000000000000000000000000000000000000000000000000000000010f1a213138454b55606054484c5651484d4b443726140b090b0b080100040a0c0f0d070000000000091e3245576d8298a29a9ca4b5b49f8a76614c36210d00061a2c3d50657a8fa3b5c3b09b85705d4b37230f000000000d22384d62778d8a75869cb1baa98a75604b3520253653697e93a8bed3e0cbb6a18b76614c362e43596e8398aec3d8d7c1ac97826c57422d17000000000000000000000000000000000000000000000000000000000000000000000000000a1e3346576379868f93928b8072604b3b2b180500000000000000000000000000000000000000000000000115202d363d494e54585a5956504b44373025180c0000000000000000000000001325364d62788a9ba3aa9f998674604b3c4857616c7982888c8c8b8985817b756c625a4b45382c1e100200000000000000071c3043546b8196abc6d6e8dec9b49f8a8788898a8b8c8d8e8f90908f8d8a87827d776b605544311d08000000000000091e33485e73889db3c8d9c4af9a846f5a55565758595a5b5c5d55606055554b4539281600000000000000000d21364a5c71869bb0c2cbb8a69b857c8399a3b4b4afacb0a6927d685443301c070000000006192c3c576c8196abbccfc1ae9d94847f8186909da5b7c5d5e0d2c9c6c3c9ced8e3d2c5b7a5917c66513c271100000000000000000000000000000000000000000000000000000000000000000007131a283237444b4a433637413d343735312619090000000000000000000000000000000000000b21364b6075899eb4b0b1b5c2ae98836e5746331e0a00000f23374b5d71869bb1c5b4a38f7b65503d2d1a070000000d22374c62778c8974879cb1c7a18b76614c3621253a4f657a8fa4bacfe1ccb7a18c77624c372f44596f8499aec4d9d6c0ab96816b56412c1600000000000000000000000000000000000000000000000000000000000000000000000000031729394a5b63737a7d7c776b605443301d0d000000000000000000000000000000000000000000000008141c323e4a4e5b63696d6f6e6c6660554a43362a1c0e00000000000000000000071c3043546d8297a8b5bbb4a4927d68534a5a6275818c979ea6a2a79e9a96908981786b6056493c2d201000000000000000001325364f647a8fa8b9cce1dac5b09a8572737475757778797a7b7b7a7875726d6861594b4437261401000000000000081e33485d73889db2c8dac5af9a85705a454142434445464737444b4b44373632281b0a00000000000000000f24394e64798ea3b5c9c4b39d88766773859bb0c1c5c4b29d8874604b36251300000000000c2035495a73889db3c9c9b5a3947f6f6a6c727c879da6b8cbe0e5dedbd8dfe2dacdc1b5a79d8774604b36200b00000000000000000000000000000000000000000000000000000000000000000000000a161e263135353025222b292022201d14090000000000000000000000000000000000000011273c51667c91a8b9c5c6c9b8a7917c6651392917030000081c2e3f53687d92a7b8c1af99846f5b4a36210c0000000c21364b61768b8a75869bb1b7a28c77624d372223384d62788da2c7d8eacdb8a28d78634d3830455a6f859aafc4dad5bfaa95806a55402b1500000000000000000000000000000000000000000000000000000000000000000000000000000b1b2d3d4a556065686762594b43362614000000000000000000000000000000000000000000000008182630434f5c646f797f838583817b74686054473a2b1e0e0000000000000000000b20354a6074899eb3c6cec2af9a846f5a5c647886979fabb3b8c5b9b3b0aba89e968b8075635a4a3e2d1e0e000000000000000b20354b6075899eb3c9dedcc8b4a2907b655556606163646566666463605658534c473a3126190900000000000000081d32485d72879db2c7dbc5b09b86705b46312c2d2e2f3031263135353126211e160a0000000000000000061a2c3d566b8196abc1cbb7a6937d6858657a8fa3b5c9b7a6937e69564531180800000000000e23384d63788da6b7cbc6b09b85726055565e6677889eb3c8ddf3f3f1edf1e1cdbcb0a39b897a645645321d090000000000000000000000000000000000000000000000000000000000000000000000000309141d20201c130d16140b0d0b08010000000000000000000000000000000000000000162c41566b8196abc6d6dbc8b39e8975604b36200b000000001121364b6075889eb3c8b3a18e79634e39240e0000000b20354a60748a8b76859bb0b8a38d78634e382321364b60768ba9bacee2ceb8a38e79634e3930455b70859ab0c5dad4bea9947f69543f2a140000000000000000000000000000000000000000000000000000000000000000000000000000000f1f2d37444b5053524d483b302618080000000000000000000000000000000000000000000001142636434b616a7a848d94989a999690887e726159493c2b1b0b00000000000000000d23384d62788da7b8ccddc8b39e88735c647a889ca4b4bcc9cbd5ccc9c5c6b9b4aa9f968678645c4a3c2b1a0a000000000000081d3144556e8399aec7d7e3d1c0b19c8673604b4b4c4d4f5050504f4e4b45383d37342a1d14090000000000000000071d32475c72879cb1c7dbc6b19b86715c46311c18191a1b1c141d20201d140b09030000000000000000000c2135495b72879cb2c7c8b29d8874604b5d70859bb0c5b29d8875604b38271500000000000010263b50657b90a5c4d4bea9937e69544c5b63758399a6b8cbe0f5fffff9e6d3c3b09e958578645c4a38281502000000000000000000000000000000000000000000000000000000000000000000000000000001080b0b070000010000000000000000000000000000000000000000000000000000192e43586e8398adc3d8cebeac97816c5645311d0900000000091e3245566c8196abbfbfab96806b56412b16000000071c30435474898c778499aeb9a48e79644f39241e324556748a9fb4c9dfcfb9a48f7a644f3a31465b71869bb0c6dbd2bda8937d68533e2813000000000000000000000000000000000000000000000000000000000000000000000000000000010f192631353a3e3d37342b1c140800000000000000000000000000000000000000000000000a1c304354606d7f8c9aa1a9adafaeaba69e938477625a4939291703000000000000000f24394e64798ea3c5d6dfc9b49f8a74647a8a9da6b6c2c9c6c1bec0c2c8cbccc8bbb4a49c887a645a483828160200000000000115273752687d92a9bacde1dec9b5a4927d6857463738393a3b3b3a3836312728221f180c01000000000000000000071c31465c71869bb1c6dbc6b19c87715c47321c070405060001080b0b08010000000000000000000000000e23384e63788da5b6cac2aa957f6a554454697f94a9beac97816c5645321a0a00000000000012273c51677c91a6bcceb9a48f79644f5d65798699a1b3c5d5e7f4f3f5f3dfcab6a5958074625a4a3e2d1a0a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000172c41576c8196acbdc9c1b1a08e79644e3827150200000000021628384e63798ea1b3c0ad98836d58432e18000000001325485d73888f7a8197acbaa5907a65503b251628385e73889eb3c8ddd0baa5907b65503b31475c71869cb1c6dbd1bca7917c67523c2712000000000000000000000000000000000000000000000000000000000000000000000000000000000009141d202528272220180d0100000000000000000000000000000000000000000000000a1a30404b607282949faab3bfbbbcc3c4b8b3a29a8778625746331e13000000000000000f243a4f64798fa4b9cedec9b49e897478889da8b7c4c1b5b1aca9aaadb2b7c4c8cec2b6a69e8878625645321e0f0000000000000c21374c61768a9fb4c7d8e5d2c2b39d8875614b3b2b242526262523201d15130c0a040000000000000000000000061b31465b70869bb0c5dbc7b29c87725d47321d080000000000000000000000000000000000000000000014293e53697e93a8c3cab6a48d78634d4054697f94a9beab96806b563828150000000000000011273c51667c91a6bbceb9a38e79645e667c899ca4b3bfd0e3e2dfdee0e8dcc7b29d87726055493c2d2010000000000000000000000000000000000000000000000000000002080b0e0e0b09020000000000000000000000000000000000000000040a0c0e0c0a040000000000000000000000000010263b50657b909fb1b4b2a397826d5c4a361a0a0000000000000a21364a5b6f8399a5aca2937e69533e2914000000001c32475c7187917c7f94a9bba6917b66513c261d32485d72879db2c7dcd1bba6917c66513c32475d72879cb2c7dcd0bba5907b66503b261100000000000000000000000000000000000000000000000000000000000000000000000000000000000001080b1013120d0b05000000000000000000000000000000000000000000000000021527384d5e6c8197a0b4bbb4b0a6a7b3b8c5c0b4a59c8675614c41301b0a0000000000000f243a4f64798fa4b9cedec8b39e8875859ba6b7c1b5b0a39b979495979da6afb4c0cdc5b8a69c8674604b3d2d1a0700000000000a1f3347586c8196a9bacee2e0cbb7a695806a594834201011110f0e0b0902000000000000000000000000000000061b30455b70859ab0c5dac7b29d88725d48331d0800000000000000000000000000000000000000000004172a3a586e8398adc3c7b19c87725b494d5e70859bb0c3ae99836e59392916030000000000000f243a4f64798fa4c3d3bca6917c67667c8b9ea7b6c2d0ddd8cec9c8ccd5dfcab6a58e79634e372b1e1002000000000000000000000000000000070c0e131515110c0a0309151d202424211e160a07000000000000000000000000000000050b0d171f2123211f170c0903000000000000000000000e23384c5d6d81939c9f9d968575614b3d2d1a00000000000000071a2d3d4d6278879396928474604b36200b000000061b30455b708597818197adc6a7927c67523d271c31465c71869bb1c6dbd1bca7927c67523d33485d73889db2c8ddcfb9a48f7a644f3a250f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000091d314556667c919fb1beb4a29b90929ea6b8c9c3b6a499836e5f4d3928160300000000000f253a4f647a8fa4b9cfdec9b49f8b879ba3b5bdb1a39b8f86817f8082888f9aa2b4bac7c4b5a495806b5b4a36210d000000000004172a3a4d62788b9fb4c5d6e7d5c4b49f8a77624d3e2d1b07000000000000000000000000000000000000000000051a30455a6f859aafc4dac8b39d88735e48331e090000000000000000000000000000000000000000000a1f33475873889db2c8c1ac96816c574556667c91a3b4c7b29c87725746321e0a0000000000000c21364c61768ba4b6cac1ac97816c7c8c9fa9b9c5d3e0d2c7bab4b3b8c5d5d3c3ab96806b563d2c1a060000000000000000000000000000090f1a2124292b2a26211e16192731363939363228221b10020000000000000000000000000d1820222a333738373329211e160a000000000000000000081c2f3f52636d7e868a888075615746331f0f00000000000000000f2035485a62767e817d74605544311d08000000051a2f445a6f84998b879ca8b9a8937d68533e281b30455a70859aafc5dad2bda8937d68533e34495e73899eb3c8decdb8a38d78634e38230e0000000000000000000000000000000000000000000000000000000000000000000000000000000000070b0b080100000000000000000000000000000000000000000000000000000000000b20364b6074879db2bdb6a49b847b7c889eabbccfc2b3a1927d675745321e0800000000000f253a4f647a8fa4b9cfe1cdbaa99f9ca4b5bcb09f97857a716c696b6d737a84939fa9bac7c2b49f8b79634e3b2b180500000000000c2035485a6b8196a7b8cce0e1cdbaa897826d5c4a362212000000000000000000000000000000000000000000041a2f44596f8499aec4d9c8b39e89735e49341e090000000000000000000000000000000000000000000c21374c61768ca6b7cbc7a7917c67524b6074879db2c1cab59f8b76614b36210c0000000000000a1f33465872879cb2c7c9b39e897d8c9faabac7d6ddcfc2b5a99f9ea7b8ccddc7b29d87725b4935210c00000000000000000000000001111c232d36393e403f3c3632293037444b4e4e4b4538362d20110300000000000000000006131d2b34373a474c4d4c473a3632281b0d000000000000000000112135455260687174726b61574639291701000000000000000006192b3c485761696c686055443727150200000003192e43586e83988775899eb3a9937e69543e29192f44596e8499aec3d9d3bea9947e69543f30435474899fb4c9ded7c6a18c77624c37220d00000000000000000000000000000000000000000000000000000000000000000000000000000708131c20201c14080900000000000000000000000000000000000000000000000000000417293a52677c91a5b7c3b19c867566677b8c9fb4cad0bfb29d8775604b362513000000000010253a4f657a8fa4bacfe9d7c7bab4b1b6bdb09e968174645c575455585d65707e8b9fa9bacdbbaa98826d594834200b000000000005192b3c4c6176899eb3c3d4e6d7c6b59f8d7a644e402f1909000000000000000000000000000000000000000004192e44596e8399aec3d8c9b49e89745f49341f0000000000000000000000000000000000000000000010253a50657a8fa5c4cebaa98d78624d56697e93a5b6cacfbcab8f7a644f3a250f0000000000000417293a576c8197acc2ccb9a79e929faabbc8d7daccbfb2a49c8a899eb3c0d1cab7a58d78634e38230e000000000000000000000009151d2f383d4a4e535554514b4639404c5560636360564f4a3e2f21110000000000000000081624313b484c565861636158554b45392b1d0d000000000000000003172735424e535c5f5d564b4639291b0b000000000000000000000e1e2b39464c5457534b44372719090000000002172d42576c82978c7c899eb3a9947f6a543f2a182d42576d8297acc2d7d4bfaa957f6a5540354a60758aa9bacde1cdbaa88b75604b36200b00000000000000000000000000000000000000000000000000000000000000000000000002101b22253035353026241d12040000000000000000000000000000000000000000000000000a1f3346586f849aafc3b7a5917c67575d6d8298adc2d3cbb7a6937e695443301c070000000010253a4f657a8fa4bacfe4e5d7cdc9c7bfb19f96806d60564b3e3f403f4b5060687b8b9fb4bfc8b49f8b77624d37220d0000000000000e1f334758697f94a5b7cadfe3cfbcab9a846f5e4c372715010000000000000000000000000000000000000003192e43586e8398adc3d8c9b49f8a745f4a27150200000000000000000000000000000000000000000013293e53687e93a8b8c9b49f8a75604b6075889db2c3d4dac9a8937d68533e28130000000000000010253a50657a8fa4b6cac5b9b3a7b4bbc8d8daccbcafa09886787a8fa2b4c8d4c3a8927d68533d28130000000000000000000009192731404c505b63686a6a6661574b4c5e66747979756f645c4b3f2f180800000000000006162633424e59626b72767876726a6057483b2b1c0c0000000000000000091724313a3e474a48413632291b0b0000000000000000000000000e1b2933363e413d3631271909000000000001162b41566b80969f919ea7b8a9947f69543f2a162b40556b8095aac0d5d5c0ab96806b5641364b61768ba0c6d7dec9b49f89745645311d0900000000000000000000000000000000000000000000000000000000000000000000000210202d3636434a4b4336393022140600000000000000000000000000000000000000000000000c21364c61768a9fb4c7b29d8773604a4f647a8fa4b6cad4c4b29c8773604a35200b0000000010253a50657a8fa5bacfe4f5e9e1d4c4b3a197816c624b45382e2a2b2e37424e5d677d91a0b2c6bbaa927d67523d281200000000000004172a3a4b6074879db2c1d2e4dac9b4a2907c665544311d0b0000000000000000000000000000000000000003182d43586d8298adc2d7cab59f8a755544311d08000000000000000000000000000000000000000002172c42576c8197aca3a9b19c87715553687d92a6b7cbe1d6c1ac97816c57422c17000000000000000b20354a6073869cb1c2d2ccc9bdcaced8daccbcaf9e9582756370859aafc4d4c0ab96816b56412c1601000000000000000008182737444b5e6671797e807f7b766a605d667c888e8e8a847a655d4b362513000000000000132433445060687780878c8d8c877f756259483a2a1704000000000000000006141f26283235332b211e160b00000000000000000000000000000b171e21292c28201d15090000000000000013283e53687d93a8a7b3b8c4a8927d68533d2813283e53687d93a8c2d2d5c5aa947f6a553f364c61768ba8bacdddc8b29d88735d38271502000000000000000000000000000000000000000000000000000000000000000000000010202e3e4a4e54606054514c40312414000000000000000000000000000000000000000000000012273c51677c91aabbc9ab96806b54434b5c72879cb1c7dccab6a4907b65503b26100000000010253a50657a8fa5bacfe4fff4dfcbb7a6998373604b4432281a14161c23313f4d5f6e8398aec2c8ac96816c57412c17020000000000000c1d324556677d92a3b5c9dde7d0c0b19c8674604b3929170300000000000000000000000000000000000002172d42576c8297acc1d7cfbcab8b75604b36200b0000000000000000000000000000000000000000011426365a70859a9c8e98ae99836e595c71869bb1c4c9cdd7c5b09a85705b38281502000000000000071c304354687d92a4b5c9deded2dfe2dcccbcaf9e95806e6157667c91a6b7cbc3ae99836e59442e190400000000000000001325364455606c7b868e93959491898074657b8d9da6aa9f9a8b7b655443301c07000000000d1d314250626b7e89969da5a2a59c948678625847331f12000000000000000000020b11131c1f1d160c0a0300000000000000000000000000000000030a0c1417130b080200000000000000000f24394e64798ea4b6c9cbb8a68f7a644f3a250f24394e64798ea4b5c9ccb8a7917c66513c33465874899fb4c9dac9b09b85705b46311b0000000000000000000000000000000000000000000000000000000000000000000000071b2e3e4a5c646f757571665e4e42311d0d00000000000000000000000000000000000000000001162b41566b8096abc8bcab907b6550363e566b8096abc0d5d3c3ac96816c573c2b190500000010253a50657a8fa5bacfe4f7e4d1c0b39d8876615544311d150a000008142130414e63798da4b5c2ad98826d58432d1803000000000000021528384a6072859bb0bfd0e6decab6a4937e685746331e0e00000000000000000000000000000000000002172c41576c8196acc1d6dab6a08b76614b36210c0000000000000000000000000000000000000000081c30435472889c87798ea396806b5664798ea3b5bab4bac7c8b29d88735645321d09000000000000001325364b6073869cb1c6dcf1e7efdfcebeaf9e95806a624b4b6074889db3c8c4af9a846f5a452f1a0500000000000000071c304354607381909ba3a8aaa9a89e95857a879dabb7bbb4a99c8773604a35200b00000005182b3b4e606b80939ea8b2b7c3b6b2a49c8676614c40301909000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d22364a5c71869cabbbbdb39e8874604b35200b21364a5c71869cabbbbfb39e8975614b36293a5c71869bb1c3cfbcab96816c57412c1702000000000000000000000000000000000000000000000000000000000000000000000d22364a5c647a84898a867c68604e3b2a18050000000000000000000000000000000000000000011426365a6f849aafc4b59f8b76614c363c51667c91a6c5d6dcc7b19c87725a4835200b00000010253b50657a90a5bacfe5f1ddc8b4a2917c665847372614020000000003132135495b71869cb1c2ad98826d58432d1803000000000000000a1c304354657b90a1b3c8d8e5d3c2b39e8876614c3c2b1905000000000000000000000000000000000001162c41566b8196abc0d6ccb6a18c77614c37220c0406070001080b0b0700000000000000000000000b20354b60758a98827a8fa4947e69556a7f95aab3a99fa9bacab59f8a75604b36200b00000000000000081d314455667c91a6bbd0e6f8e4d1c1b19f95806b61504444556b8095aabbc5af9a85705a45301b0500000000000006192c3c4a607282979fb0b5c1bfc6b9b3a39b8f9da5b7c9cec7b6a48e78634e39230e0000000b20344859687e929eb4b9c6cad3cac2b6a49a846f5e4d372614010000000000000000000000040a0c0c0a0300000000000000000000000000000000000000000000000000000000000000000000071b2d3e50667b8d9faaaa9f947e695544311d081a2d3e50657b8d9faaaba1947f6a5746322a3f556a7f94a5b7bcb49f8c79644e39240f00000000000000000000000000000000000000000000000000000000000000000000071a2d3d4f647a8a999f9f9b8d7e685947341f0b0000000000000000000000000000000000000000081c30435472889db2c7b29d8772574633384d62788da7b9ccdecab6a48d78624d38220d00000010253b50657a90a5bacfe5efdac5b09a85705e4c3a2a1909000000000000061a2c3d586e8398adc5aa947f6a553f2a150000000000000000001325364b5d6f8499aabbcee2e0cbb8a695806b5a48352010000000000000000000000000000000000001162b40566b8095abc0d5ccb7a28c77624d3722181a1b1d1e141d20201c13160c0a040000000000000c21374c61768c947f7d92a7927c67576d8297aca1998a9fb4c9bcab8d78634d38230e00000000000000021527384c61778ca1b6cce1f2ddc8b4a397816d62504333374d62788b9fb4c8af99846f5a442f1a050000000000000c2035495a697f94a0b1bdc9d2d5d6ccc1b5b0a4b2b7c3d4e2d3c2a6907b66513b2611000004172a3a4d62778a9eb4bcccd6dfdfd2d3c2b3a1917c665544311d08000000000000000000000c171f21211e170b0700000000000000000000000000030a0c100f0b08010000000000000000000000001023384c5e697e8c94948f8172604a372614010f23374b5d687e8c9596918373604b392821364c6176879da5ab9f95806b5c4a36220d000000000000000000000000000000000000000000000000000000000000000000000c21364a5b71859ba8b4b4ab9e8a77624c37220d00000000000000000000000000000000000000000b20354b60758a9fb4c4af99846f5a392935485a74899eb3c9ded3c2a6917c66513c271100000010263b50657b90a5bad0e5e5d0bba5907b6650402f1c0c0000000000000003162838576c8297acb8a7907b65503b261000000000000000000008182f3f4e63798b9fb4c5d5e7d5c5b49f8a78624d3e2d1b070000000000000000000000000000000000152a40556a7f95aabfd4cdb8a38d78634e382c2d2f3032332631353530252b211f170c00000000000e23384d63788d917c8095a5907b66546a7f949d95837b8fa5bac9a5907b65503b261000000000000000091d314556667c91a6bbd1e6f0dbc5b09b8574604b44332035485a6e8398aabbac97826c57422d1702000000000005182b3b4d63788a9f9ca4b6c7d7dad8cfd2c9c6bac7cad4e1e6d1bca7917c67523c271200000a1f3347586c8197a8a6acb9c9cec9bdbcc9bfb29d8773604b35200d000000000000000008161c2a3337363329211a0f01000000000000000000020b161e212524201c14080000000000000000000000091c2f404f6069797f7f7a6d60544330190900081c2e3f4e60687980817c6e605544311b1e33465763798790918c8072604a3e2d1b07000000000000000000000000000000000000000000000000000000000000000000000e23394e63798ea3b5c6c9b9a8937e69533e291400000000000000000000000000000000000000000d22374c62778caabbc1ac97826c57422d2b3c5b70859ab0c5dad4bfaa957f6a55402a1500000010263b50657b90a5bad0e5e0cbb6a08b76614b3625180c06000000000004101e3245566f8499aeb39e8975604b36200b00000000000000000000112135495b6c8196a7b8cce0e1cdbaa998826d5c4a3622110000000000000000000000000000000000152a3f546a7f94a9bfd4ceb9a48e79644f4042434446474849444b4a43364037332a1c0f010000000f24394e64798e8f798298a48f7a644f607481878074788da2c5bda8927d68533d281300000000000005182b3b4b6074869cb1c7d9e7efd9c4af9a8473604a402f1f2b3c4e63798b9fab9f907b65503b25100000000000000b203448596d82989a879ca9bacdc6c3bac4c7d0cfdcdfe6f1e7d2bca7927d67523d281200000c21374c61778a9f9d919bacc8bbb4a7a7b3b9b6a5917c67513b2a1805000000000000001626343a474c4c4639362d1f1205000000000000000a151d2932363a3a35302618080000000000000000000000112232424f5b63696a645c4a43362513000000112131424e5b636a6b665e4b44372614172939495b63747b7c786b605443302010000000000000000000000000000000000000000000000000000000000000000000000012273c51677c91a6c1d2d6c6ac97816c57422c1703000000000000000000000000000000000000000f24394e64798ea3c8bfaa95806a55402b2d42576c8297acc1d7d8c2ad98836d58432e1800000011263b50667b90a5bbd0e5e3ceb8a38e796354433629211a1614131314181f2d3d4b6075899eb3aa96816c5645321d0900000000000000000000061a2c3d4c6176899eb3c2d3e5d7c7b59f8d7a644f3f2f18080000000000000000000000000000000014293f54697e94a9bed3d0bba5907b6654565758595b5c5d5e556060545c564c473a2d1f0f0000000f253a4f647a8f8d78849aa38e79634e56606d726a60768ba7b9c0aa95806b55402b160000000000000b203448596a7f94a4b4bcc9d9ebdcc7b3a195806a5e4c3d2c2135495b697e8c938f816d5d4b37230e0000000000000d22374d62778b9a84758a9fb4beb2ada4afb3bfd0ddedf9ffe7d2bda8927d68533d2813000417293a53697e939d887c91a6bbaa9f92929ea7b9af9a846f5948341f0b0000000000000c1c344451586161574e4a3d3023130500000000000d1a273139464b4f4f4b433626140100000000000000000000031424323d4a4e54554f4b3e30251808000000031424313d494e5556514c40312619090b1b2c3d4956606667625a4a4336251302000000000000000000000000000000000000000000000000000000000000000000000013283d52687d92a7bdd2d8c3ad98836e58432e1e160d0b060000000000000000000000000000000010263b50657b90a5c4c4a9937e69543e292a3f54697f94a9bed4dbc5b09b86705b39291603000011263b50667b90a5bbd0e5eed9c4ae9983726054473a352c2b292828292a333e4a5b687e93a7b49f8b78634d3828150200000000000000000000000f1f334758697e93a4b6c9dee3cfbcab9a846f5d4c3625130000000000000000000000000000000013293e53687e93a8bdd3d3bea9947f69696b6c6d6f7072737475757573716b61584a3d2d1a07000010253b50657a908b76869ba28d78624d454b575d555674899eb3c2ad97826d58422d18030000000005182a3b4d62778a9d8f9fabbccfdfd3d0bfb49f8d7c665b493a292c3d4f6069797d7a6d63523f2e1c080000000000061a2c3d556a7f948f7a7e94a9bab2a0988f99a1b3bfd0e1f1ffe8d3bda8937e68533e2913000a1f33465870859a937e7b90a5b49f8c7d7d899eaab49f8b77624c37220d000000000004182a3a51626b77766f635b4d41312313030000000d1d2a38454b57616564605443301c0a000000000000000000000006141f2d36393f3f3a372e1c1308000000000006141f2c353840413c38301d140900000f1f2c38454b51524d483c3025180800000000000000000000000000000000000000000000000000000000000000000000000813283d52687d92a7bdd2d8c3ae99836e59443632282320190e0900000000000000000000000000000f24394f64798ea6b7b7a6907a65503b25263c51667b91a6bbd0ddc8b39e88735746321e0a000011263b51667b90a6bbd0e5f0dbc7b3a196817261584e493d413e3d3e3e3a474c5c64798a9eb4a697826d5a49351a0a0000000000000000000000000417293a4b6074869cb1bfd0e0dac9b3a2907b655443301c0a00000000000000000000000000000013283d53687d92a8bdd2dcc7b29d877d7e80818284858788898a8a8a88868076635b4a36210c000011263b51667b908a74879da18c77624c37364248385c72879cb1c3ae99846e59442f1904000000000b1f3447596c8196877b8c9fb4cacabec7cabcab9e8979635846372732424f5b6368655d52453521110000000000000c2135495b72879b8575889eb3b7a698827a8399a1b3c3d3e6f9e9d3bea9947e69543f2914000c21364c61768a9d8775869bb0ab95806b677b8c9fb4aa927d68523d281300000000000a1f3347586b808b8b8479675f4d4131221100000d1d2b3b4856606b767a7a73604b392816030000000000000000000000010f1a21232a2a25221b100000000000000000010f1a21232b2c26241d1201000000010f1a2832363b3c38352b1c13080000000000000000000000000000000000000000000000000000000000000000000007101b222b3d52687d92a7bdd2d9c4af9a846f5a4f4b453838352b241d12070000000000000000000000000b20354b6074879dabab9d8875604b362123394e63788ea3c6d6e0ccb8a78b76614b36210c000011263b51667b90a6bbd0e5f6e2d0bfb09f9682766a635b5956535353535658616b7a889da8b39e8877614c3c2c1900000000000000000000000000000c1d314455657b90a1b3c8ccc8ccc0b19b8572604a38271502000000000000000000000000000012283d52677d92a7bcd2dfcab7a59d9293959798999b9c9d9e9faa9f9e9b958879634e39240e000012273c51677c918873889ea18c77614c37222d32455a70859aafc5af9a85705a45301b05000000000d22374c62778a927d7b90abbcbbb4a8b2b7c3b9a79c8676615544311d323d494e534f4b3f352717030000000000000e23394e63788e927d7d92a6b8b29d887465738399a5b6cadfefe9d4bfa9947f6a543f2a150011263b50667b90947f7a8fa3b49f8b77625d6b8096a6ad98826d5837271501000000000c22374c61778c9f9f9a8a7d675f4d402f1e0e0c1c2b3b4859627480898f8f826e5745321e0900000000000000000000000000070c0e14150f0d080000000000000000000000060c0e1516110f09000000000000000a151d2026272220190e0000000000000000000000000000000000000000000000000000000000000000000004101b222e373c4852687d92a7bdd2dcc6b19c867168646056544d483c382f221b100100000000000000000000081d314455667c8d98988d7c665745321e21364b61768ba8b9cce1d5c5a38e78634e39230e000011263b51667b90a6bbd0e5ffedddcdbdb0a098887f78736e6b696868696b6f77818b9da6b09e917c675847331e0e0000000000000000000000000000011527374c5e6f8399aabbb8b3b8c5b5a3927d675645311d0b000000000000000000000000000012273c52677c91a7bcc9d1d4c3b7b2a7a9abacadaeb0b1b2b3b4bbb4b3b1a696816c57412c17020012273c52677c918873899ea18c77614c3722192e43586e8398adc3b19b86715c46311c00000000071b2e3e556a80958774869cb1bbaa9f939da5b6c3b6a49a8373604b4231202c36393e3a372e2117090000000000000014293e54697e938a76849aafc4aa947f6a566175879cb2c1d2e4ead4bfaa957f6a55402a1500152a3f556a7f948c778398adb09b8570594b6176889db19c87725544311d08000000000d22384d62778da8b5a89f8d7d675e4c3c2b1a1b2a3a4859627785959ea89f8b76604b36210b00000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000002090b11120d0b05000000000000000000000000000000000000000000000000000000000000000000000c171f2e363f4b4f5a626a7f94a9bed4dfcab59f8d817d7976706a625a514c40372e1d1409000000000000000000011527374c5e667b83827b665e4d3928161e32465774899eb3c9ded0bba5907b66503b2611000011263c51667b91a6bbd0e6fbfbebdbcdbeb2a69e958e8883807e7d7d7e80848b969fa9b1a095806b5f4d3a2a180000000000000000000000000000000009192f404e63798b9fb4a79ea7b8c1b29d8774604b392917030000000000000000000000000011263c51667b91a6b0b5c1d1cfc8bbb4b3b3b2b2b2b2b3b3b2b1aeaca9a79e917c66513c2611000011263c51667b918873889ea18c77614c3722172c41576c8196acc1b29d88725d372614010000000d22364a5c7287947f7b90a4b5b49f8c7e879ca5b6c2b3a196816c604e3e2d1c21232825231c11030000000000000003192e43586e839885768a9fb4b8a78e79634e57657b90a3b5c9ddead5c0aa95806b55402b1600172d42576c82978674899eb3aa957f6a554657697e93a99f8a74604b35200b000000000b20354b6075899eb4baab9f8d7c665a483828283947586278879ba3b4b9aa8e79634e39240e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004111c2a333e4a4f5d656e78808a9eb3c9dee3cfbcab9f97928f8a857f786f665e4f4b3e3126190a000000000000000000091930404c5d656d6d655d4d40301b0a1629395c71879cb1c6dcd2bda8927d68533d2813000011263c51667b91a6bbd0e6fbfff9ebdccfc4b8b3aaa69d989693929393959a9faab4b49f978272604b40301c0c0000000000000000000000000000000000112135495b6b8096a49c899ea6b8b7a5937e695746331e0d0000000000000000000000000010263b50657b90a39ba3b5c5bfb3aa9f9e9e9d9d9c9d9e9d9d9b9997948f897d675e4c38240f000011263b50667b908873889da28c77624d3722152a3f556a7f94aabfb39e89745544311d080000000f243a4f647a8f8b778398aebbaa97816c77879ca6b7bfb19f927e685c4a3a2a190e13100e08000000000000000000061c31465b718696817a8faabbb39e8974604a4c5d70859bb0c5dbebd5c0ab96806b56412b1600192e43596e839782798ea7b9a5907b6650394d62778ca7aa8d78624d38230d00000000081d3144556e8399aec3bcab9e8978625645323746576176869ca5b5c1b7a68d77624d38220d000000000000000000000000070d0f0d070d0f0f0d0f0d0c100c0b100d0b0f0d0f0d0e0e0f0e0c0a0c0e0f0d0b100c0d0f0e0c0600000000000000000000000000000000000000000000000000000000000000000000000715222f3a474c5c64707a838c959ea8b9cce1ecdac9bcb5aca8aa9f9a948c847b71645c4b4437281b0a0000000000000000001222303f4b5058584f4b3f302212001a2f445a6f8499afc4d9d4bfaa957f6a55402a15000011273c51667c91a6bbd1e6fbfffaece1d4cac7c3c4b7b2aeaba8a8a8a8abafb4b5a99f938172605443302212000000000000000000000000000000000000061a2c3d4b6175889c8776889eb3c3b39e8876614c3b2b180500000000000000000000000010253a50657a8f9b869ba7b9b3a1998b8988888787888988878684827e7a74675f4d402f1d09000010253a50657a8f8973889da38d78634e382314293f54697e94a9beb59f8a75604b35200b000000132536556b809586758a9fb4b49f8b78626278879da7b8bdb49f8b7a64594737261401000000000000000000000000081e33485d7388937e7c92a7c8af99846f54433f546a7f94a9bfd4e9d6c1ab96816c56412c17001a2f445a6f84947f7c91a6bbaa8c77624d37485973899ea58f7a65503a2510000000000114263751667c91a5b7c9b8a79b8574604b3e44556175859ba4b6c3c6b29d88735a4834200b00000000000000000000010f1a2124211b222424212421212521202522202422242124232423211f21232422202522222423211a0f01000000000000000000000000000000000000000000000000000000000000000008162532404c58616d7a848f999fabb3b9c6d6e8f7e7dacfcac2c8bbb4afab9f9a90857a6b60554539281a0a00000000000000000412212f373b43433a372e21120402182d42576d8297acc2d7d6c1ac97816c57422c17020011273c51667c91a6bbd1e6f5ffecdccfc3b7b2aeb1b6c2c3c0bebdbdc6b9b3ab9f988a7e6c60544336261404000000000000000000000000000000000000000e1e324657677d928f7a7f94a6b7b8a795806b594834200f0000000000000000000000000f243a4f64798f8874899eb3ae998373737373727272737372716f6c696560564d413022120000000f243a4f64798f8974879da38e79644e392413283e53687d93a8bdbcab8b76604b36210b0000071c3043546f8496817a90a9baae99836e5a5a6379899ea9babaa99d8777615544311d100000000000000000000000000a1f34495f7489917c7e93a9beab96806b56363b51667b90a6bbd0e5d6c1ac97816c57422c17001b30455b7085937e7d92a8b49f8a75604b353b5b70859ba7917c67523c271200000000000b20354b6074879db2c4c5b5a396806b5c4a546073839aa3b5c2cdb9a895806b553c2b1905000000000000000000000f1f2d3639362d363939363936363a36353a37353936393639383938363335383936363a37373a39352c1f0f0000000000000000000000000000000000000000000000000000000000000006162633434f5e6676828d9aa2aeb4bcc9ccd6e4f4fff7ece3dfd7d8cec9c9bcb5afa39b8d807360574538281502000000000000000003111c23252e2d25221b10030000152b40556a8095aabfd5d8c3ae99836e59442e19040012273c51677c91a6bcd1dae1ece2cfbeb2a59d999ca4b3b8c5d3d2ccb9a89e968c837868604b43362618080000000000000000000000000000000000000000031629394d5f70849a8575889db2c2b49f8a77624c3d2c1a0600000000000000000000000e24394e63798e87758a9fb4ac97826c555e5d5d5d5d5e5e5d5c595754504b4538302313040000000e24394e63798e8a75869ba58f7a65503a2512273d52677c92a7bcb6a08b76614b36210c00000b20354a607489927d7f94a9bcab927c6752495b657b8b9fb4bcb7a59a8473604b3e2d1b070000000000000000000000081c304354758a8f7a8095aabda8937d68533e384e63788da3c8d9ebd7c2ac97826d57422d18001b30465b7085927d7e93a9b39d887354433043586d8298a7927d68523d28130000000000081d314455697e93a6b7cbc1b49f8c7a645560728298a1b3c1d1c3b49e8a77614c37220d00000000000000000000071a2d3d4a4e4a3e4a4f4e4a4e4a4c504b4a4f4d4a4f4a4e4a4e4d4e4d4c46494e4f4a4b504c4b4f4e493d2c1c0c0000000000000000000000000000000000000000000000000000000000001324334451616a7c88989fabb4c0cacfd9e1e8f4fffffff1e5dedcdddfdfdacfcac1b5ab9f968375605645321d1200000000000000000000080e101818100f12120f0b0813283d53687d92a8bdd2dac5b09a85705b45301b000012273c51677c91a6bcc2c6cfdcd5c4b2a098878387919ea7b6c3d3c9b39e8980796e625a4e4230261808000000000000000000000000000000000000000000000b1b30414e64798c8f7a7e93a4b6baa897816c5b4935211000000000000000000000000e23384e63788d85768baabbac97826d5737484847484948484644423f3a3631271a1305000000000d22374c62778c8c778499a6917c67513c2712263c51667b91a6bbb6a08b76614b36210c00000d23384d62788d8f7a8297adb59f8b76614c3d4b5d677d929eafbfb4a295806b5c4a36221000000000000000000000000b20354b60758a8e798196abbca7917c67523c364b60768baabbcee2d7c2ad98826d58432d18001a30455a6f85917c7f94aab29c87725d362641576c8196a8937e69533e29140000000000011527374b6075889db3c2cfbcab9b8573606c8196a0b2bfd0cab7a5947f6a5847331f0a000000000000000000000d21364a5c645c4d5c64645c645c61656160656260645c645c6363646361585b63645c6065615c64635b493a291704000000000000000000000000000000000000000000000000000000000d1d314251626b7f8d9ea6b5bcc9d1dfe3ebf4f7fefffff1e0d3cac7c8cbd4dddfdfd2c9bcb5a19a8474604b41301a0a00000000000000000000010a0f1a2124272724201d15263b50667b90a5bbd0dcc7b29c87725d372614010012273c52677c91a7a9adb2becfcbb8a69882746e727c899da5b6c2c9b39e8977635b4d493c311c14080000000000000000000000000000000000000000000000001321364a5c6c81968574869cb1c0b49f8c79634e3e2e1b08000000000000000000000d22384d62778d84778ca2c8ad97826d584233323233343332312f2d2925201d150a0000000000000b20354b60758a8e798197a8937e68533e2913263b50657b90a5bab6a18b76614c36210c000010253b50657a908d77849aafb29d87725846333f4d5f6a8095a1b3c0b49f8c7a644f3e2d1b0700000000000000000000081c30435474898e798096abbba6907b66513b324556758a9fb4cadfd8c3ae98836e59432e1900192e44596e83927d7e94a9b29c87725d473240556b8095a9947e69543f2914000000000000091e324556687e93a4b6cac9b5a3937e6b7f949fb0becfd0c0b29d8775604b3a2a1804000000000000000000000f24394e6479645f677979647964767a76757a78747964796579787978766165797968757a77697a79635847331f0a00000000000000000000000000000000000000000000000000000005182b3b4e606b80949fabb8c5cfdadfddd4cddfe3ebf7f9e5d3c2b6b1b2b7c4c7cbd4e1dacfbfb3a297816c5f4d38281603000000000000000001131e252d36393c3d3a35312724394f64798ea4b9cedec8b39e89735544311d080012273c52677c919d9398a0b2c6c8b39e887661555f6778879ca4b6c4b9a796816c5a48352c1e130100000000000000000000000000000000000000000000000000071a2d3d4c617688917c7b90a2b3bbaa99836e5c4b372212000000000000000000000c22374c61778c83788da3b8ad98836d58432e1d1d1d1e1e1d1c1a1714100b090200000000000000081c3043547388927d7e93a895806b56402b16253b50657a90a5bab6a18b76614c36210c000013283d52687d928c77859bb0ae99846f593a2930414a60728399a5b6bbaa9a84705c4a36220800000000000000000000011426485e73888f7a8095aabaa58f7a65503a28385f74899eb4c9ded8c3ae99836e59442e1900182d42586d82937e7d93a8b29d88735d3a293f556a7f94a9947f69543f2a14000000000000031628384b6074869cb1bfcfc1b49f8a80949dafbdcdd7c7b4a2917c675645321c0c0000000000000000000003182d42586d826d677d807f78826d7f7d82807c8278836e827b817e837f7a657a817f7d7d7d847e7b8076614c37210c0000000000000000000000000000000000000000000000000000000b20344859687e929eb4bcc9d5e3d4cbc7beb8cacfd9e7f7decab6a49c9da6aab2b7c3cdd7e3d0c0b19f917c675645321e090000000000000009151d30393e4a4e51524f4b443733384d62778da2c6d7dfcab59f8a75604b35200b0012273c52677c91937e8298adc2c1ac96816c57464d5a6377869ca6b7c5b49f8b78624d3a2917040000000000000000000000000000000000000000000000000000000f1f334758687d928775849aaabbb2a18f7a644f402f1c090000000000000000000c21364c61768b83798ea3b8ae98836e59432e190808090908070402000000000000000000000000011426365b708696817a8fa498836e59432e19263b50657b90a5bab6a18c76614c37210c000014293f54697e948b76869bb0ad98836e58432e1c3043546176879cabbcb4a28f7a644f36251300000000000000000000001d32475d7287907b7f94a9baa58f7a65503a33485e73889db3c8ddd9c4ae99846f59442f1a00152a40556a7f95807b90a6b49e897458473340556a8095a9947e69543f2914000000000000000a1d314455667c90a1b2c6cdbaa89f969eafbbcce2cdbaa99a846f5f4d382816000000000000000000000004192f44596e847f7c8082827e826d7f8178826d7d7c846f827f7975837f7a697e7a72827c817a8281837c67523d27120000000000000000000000000000000000000000000000000000000d22374d62778a9fb4bccfd9dacfc3b7b2a9a3b4bcc9d9ebdcc7b19c86888e959da5b4bac7d6decebdb29d8875604b36210f00000000000009192731414d525c6467676460554c463a4b60768ba8b9cde1cfbcab8c76614c37210c0012273d52677c92907b8196abc1c6a6907b6651393c49596278879da9babaa997816c5846331f0a0000000000000000000000000000000000000000000000000000000417293a4a607285947f798b9fb4bfb09a85705e4c3823110000000000000000000b20364b60758b82798ea4b9ae99846e59442f19040000000000000000000000000000000000000000192e44596e8399878297a49b86715b3a2a18263b50667b90a5bbb6a18c76614c37210c0000142a3f54697f948c77859aafad97826d58422d1325364658647a8d9fb5c0ac97816c5443301c07000000000000000000051a2f455a6f84917c7d92a8bba6907b66513b32475d72879cb2c7dcd9c4af9a846f5a452f1a0012283d52677d9283788da8b9a88c76614c3741566b8096a9937e69543e291400000000000000011527374c5e6e8399a8b9ccc6bab4abb0bcccd9d2c1b49f8b79634e41301a0a000000000000000000000000182d42586d826d8278828278837f80817e7b81817586828078817f817f7a697e796d827c81807a818277624c37220d000000000000000000000000000000000000000000000000000000152b40556a8095a8bacde3d6c9bcb5a59d948e9fabbccfe3ccb7a18c7773788087949fa9b9c6d6dfcbb7a6947f6a543d2d1a070000000001152737444b5f6772797c7c7a746b61584c455674899eb4c9dedab8a28d78634d38230e0012273d52677c928f798297adc2baa88d78624d382c3b485a647a8b9fb4c1b49e8a76614c36210d000000000000000000000000000000000000000000000000000000000c1c304354647a8c89778196a6b7b4a2907b66503f2f1c090000000000000000091d314556758a82798fa4b9ae99846f59442f1a040000000000000000000000000000000000000001172c41566c81969882869c9e89745947341f263b51667b90a6bbc5a08b76614b36210c0000142a3f54697f948e798398aead98836e58432e1918293a4a5c6d8297aabbb29d8874604a35200b00000000000000000002172c41576c81947f7b90a5c9a7927c67523d30435472889db2c7dddac4af9a856f5a45301a000f243a4f647a8f8774899eb3a48e79644f393b586d8298a8937e68533e2913000000000000000009192f404d6278899eb3bfcfcdc9c0c4cddad7c7b5a3947f6a5b493523120000000000000000000000000a162b40566b80807c676d6d626e6a6b6c69666c6c61716c6b626c6a6d7f7a667c78697e696c6a646c6c625947341f0b0000000000000000000000000000000000000000000000000000001325365c71869cb1c6d7d2c5b9ab9f96877f798c9fb4cadfcbb6a18b7661636a747f8a9ea8b9cde1d4c4b19c87725b4a36210c000000000b1d314455606d7d878e91928f888076655e4e5d73889db2c8ddceb9a48e79644f39240f0012273d52677c928d788398aec3b49f8975604a35202b3c4a5c697e93a3b5b9a8937e69543b2a1805000000000000000000000000000000000000000000000000000000001325364a5c6d82978276889db2c0b09b85705d4c38231100000000000000000215274a5f748982798fa4b9af9a846f5a452f1a05000000000000000000000000000000000000000013293e53687e93937e7c91a88c77614c3722263c51667b91a6bbb9a78a75604b35200b000013283d52687d92907b8196abb09a85705b3c2c190b1b2d3e4d62788b9fb4b7a68d78634d38230e0000000000000000000014293e53697e9382788dabbca9947f6a543f354a60758a9fb4c9dfdac5b09a85705b45301b000b21364b60758a8c77849aafa8937e685338475971869ca7917c67523c27120000000000000000001220344859687d92a1b2c4c5c1bec1cbe1cdbaa99b8573604b3d2c1a0500000000000000000000000a1a28323650626b6b675f58584d59545657535157574b5c57564d57546169645e666361696156554f56574c473b2a18050000000000000000000000000000000000000000000000000000071c304354758a9fb4cacdc2b5a79e8d817569748a9fb4c9dfccb6a18c77614e56606a7b8a9eb4c0d1decab6a48e79634e39240e0000000b1b31424b607382929ca4a6a7a79e95887c685f5c71869cb1c6dbd0baa5907b65503b26100012283d52677d928c77849aafc4b39d88735443301c1d2d3e4b6073859bb0c1b19b86715948341f0b0000000000000000000000000000000000000000000000000000000008182e3e4c617789907b7c91a2b4b4a3907b65503f2f1c0800000000000000001e34495e738982798ea4b9af9a85705a45301b05000000000000000000000000000000000000000010253a4f657a8f9e89859ba48f7a644f3a25273c51677c91a6bcb39e89745544311d08000010253b50657a90947f7d92a7b39e89735a4935200c10203448596e8399aec4a7927c67523d2712000000000000000000000f253a4f647a8f85748a9fb4ad97826d583a384d62778da9bacde2dbc5b09b86705b46311b00091e3245567085917c7e94a9ad98826d56454c62778b9fa5907b65503b261000000000000000000005192b3b4e5f6e8399a6b7b1aca9aebbcbbfb49f8b79635544311f0e000000000000000000000002162838454b575a5e5b554e493d38433f40413e3b4142364642403842434f544f4c514d4f544f42403a414237342a1d0d0000000000000000000000000000000000000000000000000000000b20354a6074899eb4c2b9b4a49c897c6c605774899eb4c9deccb7a28c77624d454b5d657b90a2b4c8dcd3c2a7927d68523d281300000417293a4e606d8298a0b2b6c3c5b8b3a69e8d7e685e70859aafc5dad1bca6917c67513c27120012283d52677d928c76859aafc5b29d87725d372715101c304354647a8fa3b4b59f8b77624c37220d0000000000000000000000000000000000000000000000000000000000101f344759697e938675849aa9bab09a85705d4b37231000000000000000081e33485d738883798ea3b9b09b85705b46301b0600000000000000000000000000000000000000000c21364c61768ba69e9ba3a8927d68533d28293e53687e93a8bdb19c87725c3727150100000d22374d62778c9882798ea6b8a78d78624d38231105192b3b53687e93a8bda9947f6a543f2a15000000000000000000000b20354b607589897b8b9fb4b19b867158473c51667c91a6c7d7eadbc6b19b86715c46311c0002162838546a7f9482788da2b39e8975604b53687e93aba98d78624d38230d000000000000000000000d1d31414c6176879db29f97939daec9b3a1937e695b4a372715000000000000000000000000091e324556606c6f73706a635b534c473b4038454b453839373435313538353f39363c383b3e3b322b252c2d221f180d00000000000000000000000000000000000000000000000000000000071c3043546d8298a4a8a89e948679665e4b5e73889eb3c8ddcdb7a28d78624d383f4c5e70859aafc5dad4bfaa957f6a55402a1500000a1f334658687d92a0b2bec4ced5ccc4b8ab9f8d7c666f8499aec4d9d2bda8927d68533d28130013283d52687d928b76859ab0c5b39d88735544311d081426364b5d70859bb0bcab927d68523d2813000000000000000000000000000000000000000000000000000000000004182a3a4b607386947f788b9fb4b4a2907b65503e2d1b07000000000000081d32485d728783788ea3b8b19b86715c46311c0700000000000000000000000000000000000000000a1f33465873889db2b0b5ac97826d5739292a40556a7f95aabfaf99846f5a442f1a0000000b2034485972879c8872889eb3a8937e6953402f1b0b10253b50657a90a5baab95806b56402b1601000000000000000000081d3144556f849988899eb3b49f8b77614c3d566b8196abc0d6ebdbc6b19c86715c47311c00000d22384d62788b897c92a1b3a7917c66515c70859bb09f8974604b35200b000000000000000000000013203448596c8196a397817e93a9bcab99836e604e3d2d19090000000000000000000000000b21364b60768285888580797169615956564c5660564d4f4d484b44494e4a484d4c46393e35404337342a1d0d0b050000000000000000000000000000000000000000000000000000000000001325364c627786909391897f74635b4c405d73889db2c8ddcdb8a28d78634d39464b5c6e8398aec3d8d5c0aa95806b55402b1600000c21364c6176899eb3aaacb1bdc8c5b8c9bcab9e8a796d8398adc2d8d3bea9937e69543e29140013283d52687d928b76859bb0c5b59f8a75604b36200b08182e3f52687d92abbcad97826d583726140100000000000000000000000000000000000000000000000000000000000c1d314455657b8f8a788095a5b7af9a85705c4a36220c000000000000071c32475c718784788da2b8b19c87715c47321c0700000000000000000000000000000000000000000417293a5a6f8499afc4c6b19c86715746332c41576c8196acc0ab96806b56412b1601000005182b3b576c81978d798398adb09b86715e4c39291b15253650657b90a5baaa957f6a55402a15000000000000000000000115273753687e937f7e92a8bcab927d67524a5b71869cb1c6dbf1dcc7b19c87725c47321d00000b2035485a6f849a888399a8af9a846f5d647a8fa2af9a85705443301c08000000000000000000000d1d30414c6277899e9b85748499afb49f8b77624c42311f0f00000000000000000000000000091e324556606c6f777f898e867e77706c6b616376675f64625960555b63605962615758544b56584c473b2a190900000000000000000000000000000000000000000000000000000000000000081f34475962747b7e7b76696055493d475c72879cb1c7dcceb8a38e79634e5257616a7a8b9fb4c9dfd8c7a9947e69543f29140004182a3a54697e93a79e95969fb1b4b0a2acb0b9a89a84748297acc1d7d4bfaa947f6a553f2a150013283d52687d928b76869bb0c5bcab8e79634e39230f001022374c62778b9fb5b19b86715544311d080000000000000000000000000000000000000000000000000205060708011426374b5d6d82988375879db2b4a28e7a644f3a2a17040000000000061c31465b718684778ca2b7b29d87725d48321d080003090c0e101213120d0b05000000000000000000162b40556b8095aac7cab49f8b76614b362e43586d8398adc9a7927d68523d2813000000000f243a4f647a8f9781849aa9b5a3907b665746392e28324354697e94a9c4a8937d68533e281300000000000000000000000c21364c61768a848096abc9af9a84705c4e63798ea4b5c9def2dcc7b29d87725d48321d000005192b3c50657b908576899eb4a2907b6b6f8399afa9947f69543626140100000000000000000005182a3b4d5f6e83999e89787f94a1b3bcab8e7a645746321e120000000000000000000000000002162838454b5759616976808a938a8581807679887d697977667567677872647776616e69606b6e61594737271c1308000000000000000000000000000000000000000000000000000000000005182a3b47566066696661574b44372c465b71869bb0c6dbcfbaa48f7a6561676d767f8a9fa9bacde2cebaa9907b66513b2611000a1f34475971869ca495808196aca39b8d969fb4b4a2927d8196acc1d6d5c0aa95806b55402b160013283d53687d928b76869bb0c5c9a9937e69543d2c1a060b1f34475972879cb1b49f8975604b35200b000000000000000000000000000000000000000000080e10181a1b1d1d1d1c192e3f4c627789927d8298a2b4ad97826d5847331f080000000000061b30465b708585768ca1b6b39d88735e48331e171a161e2123252728272220180d020000000000000011263b50667b90a9bacdbcab907a65503b293a5a6f849aafbcab8f79644f3a240f000000000d22364a5c70859b97838b9fb4b29d877561574b3f38454b6073869bb1b8a68f79644f3a240f00000000000000000000000a1f3346586e8398969eb0c3b4a28f7a645e6e8398aec2d2e5f2ddc8b29d88735d48331e0000000e23384c5e70858d818b9fb4b39e89808399a1b3a18d78634e38230e000000000000000000000d1f344859677d929f8d7b7b8c9fb4bfc9b19c8675614b402f1d0c000000000000000000000000000a1a2832363b474c58616b777e8a948a7f70859a887e8a857b897d7d8a8079898477837e75808377615544353025180a00000000000000000000000000000000000000000000000000000000000d1d2a38454b5153514b463931272a455a6f859aafc4dad1bca7927d71777c8289949fa9bac7d7d8c8b49f8a76614b36210c000c22374c61778ca49c8674859bb09b857881919ea8b39d888399aec4d9d6c1ab96816c56412c170013283d53687d928c76859ab0c5c4af9a846f5b4935210e05182a3b596e8499aebaa98d78624d38230d0000000000000000000000000000000000000003111c23252d2f31323332312f2c344859687e939282849ab0b49f8a76614c3625130000000000051a30455a6f8586768babbcb39e89735e49342a2c2f283236383b3c3d3c37342b1d150a0000000000000c21364b61768a9fb4c9c9aa947f6a553a33465872889db2b59f8b76614b36210c00000000071b2d3e50657b8d8d788297adb7a59a8475655d585656606b7f94a3b5b39d8874604b35200b00000000000000000000000417293a4e64798c9fb5bccdc0b09b85746a7c8d9fb5cadff0f2ddc8b39d88735e48331e000000091c2f404f647a8c969fa9bab8a79e9599a1b3ab99846f5b4935210c0000000000000000000d1d30414c6277899e958077889daabbcecab6a497816d5e4c3b2a1804000000000000000000000000000a161e212a343a4a5b657b86867f776a6c819684949c86898a89888885869c89888985858281857360534a4336281a0a00000000000000000000000000000000000000000000000000000000000d1a2731363b3e3c36322932363a47596e8499aec3d9ddc7b29d87868b91989ea8b4bac7d7e2cebbaa98836d5746321e090011273c51667c91a6927c7c91a2a38f7a646c7c8a9eaaa69d99a1b3c7dbd7c1ac97826c57422d170013283e53687d938c77859aafc4cab59f8c79634e3d2c1a06172c41576c8196acc7a48f7a644f3a250f0000000000000000000000000000000000000513212e373a4245464748474644413e3b4b60738596807b8fa5baa9947f695443301c0700000000001a2f44596f8487748a9fb5b49f89745f4a3d3f414439464b4e505253524d483b32281a0a00000000000a1e3246576e8399aec3c4af99846f5847364c61768ba5b7b19b86715746331e0a00000000001023374b5d6c819785869cb1c3b4a29a867b726d6b6d75808d9fb5b9a796806b5544311d080000000000000000000000000c22364a5c6e8399a9bacdc9b5a39b857f899eabbccfe3ecf3dec8b39e89735e49341e000000001122374b5c6b8096a2b4c0c5b8b3abaeb3b49f8c7a644f3d2c1a06000000000000000005182a3b4d5f6e83999a8474849aa6b7c8c9cdc2b19f907c665947341f14010000000000000000000000000002090c1823394e63798a7b70827e69647a8e878298838697828b917c889882889580888975817e72686054453828160300000000000000000000000000000000000000000000000000000000000a151d20262926293339464b5358616f849aafc4d9dfcbb7a59d9c9fabadb4b9c6cdd7e0cebeb49f8b78634d3928160300152b40556a80959d8875869bb09b86715c5e667c8c9fb4b3aeb3bfd0e2d8c2ad98826d58432e180013283e53687d938d778499afc4cfbcab97816c5b49352113162b41566b8096abbba6907b66513b26110000000000000000000000000000000000011323303f4b50575a5b5c5d5d5c595753504c5463798b96899eb4c7b29d8773604a35200b000000000a152e44596e8389768a9fb4b49f8a755f50525457595c5761636567686762594b4538281502000000000316293951677c91a5b7c9b49f8b77614c3850657b90a5c3ab96816b56392917030000000000081c2e3f4b6175869b9ca4b6cac0b4a49c8f8782808288959fabbcb39e8976614c37261401000000000000000000000000071b2d3e4e63798a9fb4becfc1b4a39b949ea7b9c9cacfdae7dec9b49e89745f49341f00000000071b2e3e4b6073849aa2b5bcc9c8c9bcb4a095806b5c4a361f0f0000000000000000000c1f344859677d929d88778095a2b4b0a5b4bac6bdb39e8877614c42311f0f0000000000000000000000000000000014293f54697e897571868978656e83947f878c7e8a897f94837b8c8a7c8b897d8b818593877e72605645321e1000000000000000000000000000000000000000000000000000000000000002090c1826303a474c57616870777f8c9fb4cadfe6d4c3b7b2b1b5bcc9c9ccd6e1d6ccbdb1a0947f695a49351b0b0000182d42576d829795807a8fa3ab96806b564c5e697f94a3b5c4c7d0ddedd8c3ae98836e59432e190013283e53687d938d788499aec3dac9b49f8b79634e42311f162b40566b8095abbca7917c67523c271200000000000000000000000000000000000a1e30414d5d656d6f70727272716f6c696561585b6b80959ea8b9cab6a5907b66503828160200000a1a28323e586e8398879ca7b8b49f8a756466686a6c6f717376787a7c7d7c776b605645321d0e00000000000b20354b6074879db2c3bbaa947f6a5645566d8297acb7a58f7a65503a251000000000000000111e3346576277879ca4b3c0cdc2b5b1a59c9796989ea6b5bbb49d917d6758473319090000000000000000000000000000102135495b697e93a0b2bfcfc1b4b0aab3b9b5b1b5bcc9daddc8b39e88735e49331e0000000000101d314455617584969fabb1b2b1ab9f958273604b3e2d1b0100000000000000000c1c30414c6277899e907b7b8d9fb4a39b909fa8bacbb8a699836f604e3d2c190900000000000000000000000000000011273c51667c917d677d92877b6f788a897d92877e9383828a7a7f94837d928480937e7f86918374604b3e2e1b070000000000000000000000000000000000000000000000000000000000000e1c2936434b58616b757e858b949faabbcee2f2e2d4cbc7c6cacfdadee0dacfc5b9b39f96826d614f3c2c190000001a2f455a6f849a8f798197aca7917c6752404b6073859bb0c1d2e2edeed8c3ae99836e59442e190013293e53687e938e788398aec3cbc8bbaa99846f604e3d2d1c2d43586d8298adc7a58f7a65503a251000000000000000000000000000000000001025394d5f677b8284868788878684817e7a76736f6b75879cb1c6d3c3ae98836e5645321e090002152838454b5c6f858975899eb3bbaa907c797b7d7f818486898b8d909192918a8074604b3c2b190500000000081d314455697e93a5b6c8b29d8774604b6074899eb3b29d8773604a35200b000000000000000317293948596378869aa2b4bac7c9c3b6b2adabadb3b8b6aa9f947f6a5f4d3a2a17000000000000000000000000000000061a2c3d4a60728298a1b5bcc9c8c5c9bcb5a39b9fabbccfd6c6b19b86715c46311c00000000000215273746576174818c969b9d9c968c8073605544312010000000000000000004172a3a4d5f6e8399978176889daba89b857b8a9fb4bec4b3a1937e685b493727150200000000000000000000000000081c2e3f4b60758889786c819790847b809580818877817f7686898486907b80867686877e797c89826d5c4a36220d00000000000000000000000000000000000000000000000000000000000e1e2c3a47546068768089939a9faab4bbc8d8eafef2e6dfdddbdfdfdbd6ccc9bcb5a79e928173604b43321e0e0000001b31465b70869b8975879cb2a48f7a654f3a4455657b90a3b5c9ddf5eed9c4ae99846f59442f1a0013293e53687e938e798298adc5b8b3aeb2a1927d685b4a3a2c2c3c5b70859bb0baa98d78634e38230e000000000000000000000000000000000012273c52677d8d979a9b9c9d9c9b9996938f8c8884817e8095aabfd5c9b49e8975604b36210b00091d324556606d7a8a8d7f8c9fb4c8ab9a908f90929496999b9ea7a3a5a7a8a99f96836f5a4835200b00000000011426374b6074879cb2bcb7a595806b606b8095a7b8a895806a5443301c0700000000000000000b1b2b3b495a637684959fa9b4bbc8c5c6c2c0c3b7b2a59c8c7f6a615041301c0c000000000000000000000000000000000e1c304354607383959fabb4bbbab4ab9f96868d9fb5bec5b9a896816b56412c16000000000000091929394656606c798186888681796b605544372614020000000000000000081f334758677d919d87758298a6b39e8978687e92a0b2c2bfb49f8a79635544311d10000000000000000000000000000e23374b5d65777e93867675858b879089988b7e7e7b7a6a61767e787586877679887b848275677b8b79644f3a240f000000000000000000000000000000000000000000000000000000000c1c2c3c495861737e88959ea7afb4bbc8ced8e6f6fff9ebe0d8d9cecac6c5b8b3ab9f98897e6c605544312515000000001c31475c71869b86768ca5b6a38d78634e38374c5d70859bb0c7d8eaeed9c4af99846f5a442f1a0014293e53697e938f798297acb8a69e99a1b49e8a796358493d38495b73889db3b49f8a75604b36210b0000000000000000000000000000000003192e43586e8398a9afb0b1b2b2b1aeaca8a5a69d999693959eafc3d7cdb9a88f7a654f3a2510000b20364b6074828d9f9f949faabbceb8aba6a4a5a7a9acaeb1b3b8c5babcc7bab4a18d78624d38220d0000000000091d314556667c909eb0bdb49f8c7d757d8c9fb4b49e8a76614c362513000000000000000000000d1d2c3c495861737f8b989faaadafb1b0afaaa59d94877b6961504333231200000000000000000000000000000000000013253644556073808d999faaa99f998d81757f95a0abada79e8978624d38220d000000000000000b1b2938454b5b636c7173716c635b4b4437261909000000000000000008182e3f4c6176889e8c7a7c91a0b19f917d67606d8298a4b6c6baa89b8574604b3e2d1a0a00000000000000000000000010253a50657b88738195877b7a8b747b7f828b9486868578706b686263798a81778986726d615d6d827c67523c271200000000000000000000000000000000000000000000000000000008182a3a495a627683939ea7b3b8c5caced9e2eaf6ffffebdbcdc4c8bbb4b1aba79e968c837768604b4437261407000000001d32475d72879883798fa4c3a28d77624d382f3f53687d93a9bacee2efd9c4af9a846f5a452f1a0014293e53697e938f7b8197acb39e888399a5a89d8776635b504d4f63788da6b8af9a85705645321e0900000000000000000000000000000000000f243a4f647a8b999fabaeb3b9c5c1c1bec4b7b2afaba8aaafbcccd2d7c6a8937e68533e29130010263b50657b909fabb4aab4bbc8d9c8bebbb9bbbdbfc1c4c6c8cccacacac9c6b7a68d78634d38230e0000000000021527384c5e6b80969fb2b7aa9f928a919faab5a495806a584733180800000000000000000000000e1e2c3a4755606a79828b92989a9c9b999590877f74655d4f4333251505000000000000000000000000000000000000081827374455606b7a848a8e8d8a837a6c60728290969894897b655a4835200b00000000000000000b1a28323d494e575c5d5c574e493d312619090000000000000000001325364b5d6d8298968077889eb3a397816c5f4b6175869ca8b9c6b5a395806b5c4a38281502000000000000000000000c1d2a43586e83927d73808b908c806b666a6d7d92807983868581786860687e826d7b816c544b4f647974604b362112040000000000000000000000000000000000000000000000000000132536475962788799a1b3b8c5ccd6dfe2dfe2eaf5fff2e2cdbdb0abaa9f9b968f8981786e62594e423126190900000000001e33485d738896817c91a7b7a18c77624c3722364c61768a9fb4c9dfefdac5af9a85705a45301b0014293e53697e939a84889db2b09b8576879da9a59c86796c6562646e8298adb8a6937e68533828160200000000000000000000000000000000000d22374b5c6479838b92989ea7a7abafb2b4bac7babbbcbdbdbdbdbdbdc0aa947f6a553f2a15000d22384d62788b9fabb1b6c2bcbebebebebdbcbbbab9b8b7b6b5bcb4b4b4b4b2a89d8774604b35200b0000000000000a1a2f404a607281929da6aeb4aa9faab4b3a69c8674604b3a2a17000000000000000000000000000e1c2937444b5b636d777d8285878684807b746960564b3f32251507000000000000000000000000000000000000000009192737444b5c646f767878756e645c54606d7b81827f77655d4c3c2b19050000000000000000000a161e2c3639414648474139352c1d1409000000000000000000071c304354657b8f9c86758399a6a79b8574604b465763798a9eb4bdc1b49f8c7a645645321d0f00000000000000000004182a3b4752677d9288766b797f7d737b72605f697e7b807c7d838b8b7e6874827560656c6251464b5c646056483b2f221202000000000000000000000000000000000000000000000000071c3043546177869ca5b3bfccd5e0dfd8cec9ced8e5f5e7d5c4b09f96908a86817a746c635b4c483b311d14090000000000001e33495e7388947f7e93a9b7a28c77624d37223346586f849aafc4daefdac5b09a85705b45301b0014293e54697e93947f849aafaf9a856f7a8a9fb4a49c8b817a777a8398a0b2b39e8875614b36210c000000000000000000000000000000000000071b2e3e4b5b636e777d83898d92969a9d9fa9a3a5a6a7a7a7a7a7a7a7a7a2927c67523d2712000b2035485a687e8d969ca4a5a7a8a9a9a8a8a7a6a5a4a3a2a1a0ab9f9f9f9f9c978a7b655544311d0800000000000000121c304354606c7d8891989fa8a6a9a8a19a8878625544311c0c00000000000000000000000000000c1927313d494e5962686d7071716f6b6560554b45382e21140700000000000000000000000000000000000000000000091927313e4b4f5660636360564f4b434b5d656c6d6a62594c3f2f1e0e0000000000000000000000020f1a21232c3133312c23211a0f01000000000000000000000b20354a6072869b8b797d92a1b39e897863564539495b677d929fb1c0bbaa9c8674604b3d2d180800000000000000000b1f344759616a708496816c636a697f8a806b61757a676a78746e7884927d7e927d676161584c5761686b6962594c402f20100000000000000000000000000000000000000000000000031628384a6072849aa4b6c3d0e0d9cfcac7bab4bac7d8eae0cbb8a696817b76716b6560554d493c342b1d1301000000000000001e33485e7388937e7f95aab7a28d78624d3823293a54697f94a9c9d9ebdac5b09b85705b46301b0014293e54697e93927e8197acaf99846f677d929db5a99f978f8d8f98a0b2b4a2937e695746321e090000000000000000000000000000000000000010202e3d4a4e5962686e74787d8185878a8c8e8f9091929292929292928e8373604b35200b0005192b3c4e60687a81878c909293949493939291908f8d8c8b8b8a8a8a8a8a878178655d4b372614010000000000000000132536434a5f67757c83898d9193938e8478625a483727150000000000000000000000000000000009151d2c353b484c52585a5c5b5a55504b443732281a110300000000000000000000000000000000000000000000000009151d2e3738454b4e4e4b453837303f4b505658554c473b2f21110000000000000000000000000000060c0e171c1e1c170e0c060000000000000000000000071a2d3d52677c91978277899eb39e917c665a49382c3d4d5f6c8197a2b4c3b5a495806b5b4a36251300000000000000000c22374c6177807678898c7c665b738888847f6d82897c7b8a806a7a80848b7d8d89777677665e61757d807e77665e4c3e2d1b0700000000000000000000000000000000000000000000091e324556687e93a2b4c3d3dfd2c9bcb4ada99fa9bacee2ddc8b39d887365615756504b4437352c20180d0000000000000000001d33485d7288927d8096abb8a38e78634e3923253a50657a8fabbccfe3dbc6b09b86715b46311c0014293e54697e939c92979fb1ae99846e5f697f939fabb4aca5a2a4aeb2b4a59a8473604b392816030000000000000000000000000000000000000002101f2d363b474c52546063676c6f727476797a7b7c7d7d7d7d7d7d7c796f605544311d0800000e1e31424e5c646c72777a7d7e7e7e7e7d7d7c7a79787776757575757574726c635a4b3f2f190900000000000000000008182530414d5660676e75787c7e7d796f6259483c2b19090000000000000000000000000000000000010f1a212a34373d4345474644403b3531261d150a00000000000000000000000000000000000000000000000000000001101b222832363938363228221c2e373b41433f37342a1d11030000000000000000000000000000000000000000000000000000000000000000000000000c21364a5b70859b8785879da7a195806b5e4c3c2c1f30414b6074849aa5b7c2b49f8c79635443301c09000000000000000d22384d62778d88807f8a8979666c81947f847f8d84868689857e8688838985829885898a7c667285808088897c665c4a36220b000000000000000000000000000000000000000000000b21364b6075889eb3c0d1dfd2c1b5ab9f978f8b9fb4c9dfdec8b39e8973554b46393a35312721190e05000000000000000000001d32475c7287927d8095aab9a48f7a644f3a2521364b61768b9fb4cadfdbc6b19b86715c46311c0013283d53687d92a8a7acb1bdad98826d5861697e8d9ea7b3b8c4c2b5b1a29a8776615443301b0b000000000000000000000000000000000000000000010f1a212a343736434a4e52565a5d58616365666768686868686867645c4b44372715010000001424313e4a4f56586165676969696968676665646362616060545f5f5f5d574d493c2f2111000000000000000000000008131c3038454b51556063666968635b4d483b2b1e0e0000000000000000000000000000000000000000060d181f22282d3032312f2b26201d140902000000000000000000000000000000000000000000000000000000000000080a161e212323211e160a111c23252c2d2a221f180d00000000000000000000000000000000000000000000000000000000000000000000000000000e24394e63798e8d788196a5a4998372604b40301e131d3144556177879da7b9bbaa9b8572604a372614010000000000000b2034485a6a7f868a8e9196887c7979898978858a8b7d879a84848a88808a9580889883858a787a8f7c7d77838a7a644f3929170300000000000000000000000000000000000000000012283d52677d92a7b8ccdbd2c1b5a39b8c827a7c91a6c8d9dfcab59f8a75604b35292f27251e13060000000000000000000000001c31465b7186937e7f94a9baa5907b65503b261e32465771869cb1c6dcdcc6b19c87715c47321c000f243a4f647a8fa4b6c8c5bdaa95806b554f60697c89959ea6a5a5a49c938478625847362614000000000000000000000000000000000000000000000000070d181f22253035383d41453a474c4e505152525252525252524f4a3e31271909000000000614202d36393a474c505253545453535251504f4e4d4c4b4a434a4a4a474238352c1e110300000000000000000000000000131a28323637444b4e5154534e4a3d342b1d0e0000000000000000000000000000000000000000000000050b0d13181b1c1c1a16100b08010000000000000000000000000000000000000000000000000000000000000000000003090b0e0e0b09020000080e101718150d0b05000000000000000000000000000000000000000000000000000000000000000000000000000002152838566c81969b858d9fa69c86766154433022120215273747596379899ea9bab4a3927d675544311d0800000000000005192b3c50616a7175797c808d9086868999877e849a87798795808497827e93897f94897e86837e939092827484846f5746331e0a000000000000000000000000000000000000000005182b3b5a6f8499acb1bdcec9b5a39b85796d64788daabbcee2cfbcab8c77614c3743443d393023160800000000000000000000001a30455a6f85947f7e93a8bca6917c67513c27162939586d8298adc2d7dcc7b19c87725c47321d000d22374b5c72869caab7b9b39e8e79644e424f5e667680888e908f8d867e73625a483a2a18080000000000000000000000000000000000000000000000000000050b0d131c2023282c302a3337393a3b3c3d3d3d3d3d3d3d39362d1d150900000000000002101b22242a33373b3d3e3f3f3e3e3d3c3b3a383736363530253535322c2320190e000000000000000000000000000000000a161e21273136383c3e3e39362d20190d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000091d32455672879da39b9fa69d8878625846362614040009192a3b4a5b657b8b9faabab29d8774604b35200b000000000000000d1d33435055566063666b7e8c86777383917c7684978278878c7d84937e7f9486818a847f947f94868385707a8c76614b36210c00000000000000000000000000000000000000000b2034485973899d979fb1c5c7b09b8574635b60758a9fb4cadfdac9a38e78634e4d595a524d413426160600000000000000000000192f44596e8396817b91a6bba8927d68533d28152b40556a8095aabfd5dcc7b29c87725d47321d00071b2e3e50657b8c9da6a79e94816c5c4a36404c58616b74797b7a7871686055483c2b1c0c00000000000000000000000000000000000000000000000000000000000000070b0e12171a171f21242526272828282828282724221b1001000000000000000000070d0f181f22252829292929282827252423222120201c13201f1d170e0c0600000000000000000000000000000000000002090b151d202327292823211a0f05000000000000000000000000000000000000000000000000000000000000000000000000050b0d0c0a04000000000000000000000000000000000001080b0c0b070000000000000000000000000000000000000000000000040a0c0d0e0e0d0b070000000000000000000000000000000000000000000000000000000000000000000b20364b60758a9fb5b0a69d8879635a483a2918080000000c1d2d3d4b5d667c8c9fa9b7a58f7a654f3a251000000000000000001525333c38454b4e5160687b89887a77878a7a7584937e78878a7b858d798195808489838a8183908c7e69748978634d38230e00000000000000000000000000000000000000000d22374d62778c878297acc2baa98f7a65564a5573889db2c8ddcfbaa58f7a6559626e6f675f514434241400000000000000000000182d42586d829783798ea3b9a9937e69543e2914283d52687d92a7bdd2dcc7b29c87725d47321d00001023374b5d667c878e8e897f73604b3d2d303a474c5460636665625a534b44372b1e0e0000000000000000000000000000000000000000000000000000000000000000000000000100040a0c0e101112131313131313120f0d070000000000000000000000000000040a0c101214141414131211100f0e0d0c0b0b0700000a080200000000000000000000000000000000000000000000000002080b0e1114130e0c07000000000000000000000000000000000000000000000000000000000000000000000000070d182022211f170c07000000000000000000000000000409151d2022201c1308040000000000000000000000000000000000070d0f171f2123232322201c130d0b0500000000000000000000000000000000000000000000000000000000000b20364b60748a9faaa29a8879635b4a3c2b1b0b00000000000f1f2e3f4c5e667c8b9ea7a8927c67523d271200000000000000000715202828323639414e5d6578848b7f7989887875848c7c78878878817373857d77877786826e7b7c6960718674604b36200b00000000000000000000000000000000000000000e24394e63798e83798da3c5b49f8975604b385b71869bb0c6dbd1bba6917c66627783847d6c625142321d0c000000000000000000172c41566c819685788da2c0aa947f6a553f2a15253b50657a90a5bacfdcc7b29c87725d47321d0000081c2e3f4c5e667478787469605544311f1c2a3336434b4e50504d483c353126190e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008131c202b343737332a221b1002000000000000000000000c171f273135373530251f170c000000000000000000000000000003101b22242a333738383837353025221f180d03000000000000000000000000000000000000000000000000000000081d3144556c819294908477635b4a3d2d1e0e0000000000000111212f404c5e667c8994968a78624d38230d000000000000000000030d0a151d2024313f4c5a6273808c857f8986777d89897a7a8985797a7e777262756175746066665e617779645544311d0800000000000000000000000000000000000000000e23394e63788e85768ba7b8b49f89745746445a6f8499afc4d9d2bda8937d686e82989992806c604f3b2a18040000000000000000152b40556a80959b8d9aa2b4ab95806b56402b1624394e64798ea3b9cedcc7b29c87725d47321d00000011212f404c5560636360544b443726140c171f263035393b3a38352b201d1409000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070b0d0d0b05000000000000000000000000000000000000000000000000000000000000000000000000030a0c0d0c0a0300000000000000000000000000000000000000000000060c0e16191b1c1d1e1e1d1c1b1a17120b08010000000000000000000008182530353b484d4c473a362e20100100000000000000000c1c2a3337444b4c4a4336332a1c0c0000000000000000000000000b171e2d36393a474c4d4e4d4c4a433637342a1e160a0000000000000000000000000000000000000000000000000000021527374b60737d7f7b6f62594a3d2d1f0f00000000000000000312222f404c5e66777f817a645a4835200b00000000000000000000000002090b13212f3c4855606a798592889c867779868f8382898d837f696055605660605550514d5961645c4a3727150200000000000000000000000000000000000000000e23384d63788d8773889eb3baa88b76614b43586d8398adc2d8d4bfaa947f6a73889eaf9e937e695947341f0a000000000000000014293f54697f948f7a849aafab96816c56412c1723384d62788da2c6d6dcc7b19c87725c47321d0000000312222f37444b4e4e4b433631261909000408141c202426252220190e0801000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000208131c20232220190e0700000000000000000000000000000000000000000000000000000000000000010a0b161e2123211e160b0b010000000000000000000000000000000000010e1920232b2f30313233333231302f2d27201d1409000000000000000000132536434a54596261584f4a3e2e1f0f000000000000000b1b2a3a474c55606160544c473a2a1909000000000000000000000e1b29333e4a4f575861626363626054554c473b32281b0f0100000000000000000000000000000000000000000000000000091d31445560676a655d4c473b2d1f0f010000000000000000000412222f404c5962696c645c4b3c2b190600000000000000000000000000000003111d2b37444b5b63707d88939a85707786877279887b69614a444b454b4b44373c3a474c4e4a3e2d19090000000000000000000000000000000000000000000b20354b60758a8c778499afc6a5907b655038566c8196abc1d6d6c1ab96816c748a9fb4b49e8a77614c382715020000000000000013283d53687d92927d8297acac97816c57422c1721374c61768ca8b9cddbc6b09b86715b46311c0000000004121926313539393530261d14090000000001080b0e11100d0b0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009151d2530353838352b221b10020000000000000000000000000000000000000000000000000000000002131e2529323638363229251e130200000000000000000000000000000008141c2c35384044454648494948474645423c353126190d00000000000000071c304354606973777771645c4a3d2d1a070000000000031629394758616d7577746d6158473727150100000000000000000e1e2b39464b5c646c72767878787774706a62594b45392d1f110300000000000000000000000000000000000000000000000001152737444b5255504b3f342a1d0f0100000000000000000000000412222f3b474c54564f4b3e2e1e0e0000000000000000000000000000000000000d1926313d4a4e5f67757e88806b6277806b637773604b4331353236353127272a343739362d201000000000000000000000000000000000000000000000081d3144557186917b7f94a9c0ac96816c5645556a7f95aabfd4d8c2ad98836d72889db2b9a896816c5645311d090000000000000012273c52677c919b92979fb1ad97826d58422d181f33475874899eb4c9d9c4af99846f5a442f1a00000000000009141d202323201c140801000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000919273136434a4d4d483c362d201000000000000000000000000000000000000000000000000000000009151d303939464b4d4b46393a311d150a00000000000000000000000000081826303c494d55595b5c5d5e5e5d5c5b5a57524b44372b1d0d000000000006192c3c4a60727e888c8c857a645b4a36210d00000000000a1e324657617682898c898276615544311d08000000000000000e1e2b3c4857616d7a82888c8d8d8d8c89857f776b60574a3d2f21110300000000000000000000000000000000000000000000000009192731353d3f3b372f1f180d000000000000000000000000000004111d2a34373f413a372e2010000000000000000000000000000000000000000009141d2d36414d56606975726059626b625962605544311d201e21201d1511181f2224221b10020000000000000000000000000000000000000000000001142637576c819782788da2b4b39e8975604b53697e93a8bed3d9c4af99846f70859ab0c6b49e8975604b36200b0000000000000010253b50657b90a5a7acb1bdac97826d57422d18172a3a5b71869bb0c6d7c7ab96816c56412c170000000000000001080b0e0e0b0801000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002152737444b546062625a4f4a3e2d1f0e0000000000000000000000000000000000000000000000000009192731414d525761626157524e4131271a0a000000000000000000000001142636434b5a636b6e70717273737271706f6c676055483c2b1909000000000c2035495a6b80939ea6a39b8a79634e3b2a1805000000000c21364b617585979fa89e988573604b35200b0000000000000c1c2b3c485a6275828c979da5a2a3a2a99f9a948a8075635b4c402f21110100000000000000000000000000000000000000000000000009151d20282a25231c110500000000000000000000000000000000000d181f222a2c24221b1002000000000000000000000000000000000000000000010f1a213138454b55606054484c5651484d4b443726140b090b0b080100040a0c0f0d070000000000000000000000000000000000000000000000000011263b50667b908975859ab0b9a7947f695952677d92a7bcd2dbc6b09b86716e8499aec3b9a8907b65503b2610000000000000000d22384d62788da4b6c2c5c0aa947f6a553f2a15182d43586d8298adc2cdbaa9927d67523d28120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081d314455606a74787871645c4a3d2c1a06000000000000000000000000000000000000000000000009192737444b5f677076787671685f4b453827150200000000000000000000081c304354606a788084858687888887868584827c73625a48372614010000000d23384d62788c9fb3b8b5a89a846f5948341f0b00000003162839546a7f94a3b4b9b4a3917c66513c261100000000000417293a485a627886979fabb2b7c3b8c7bab4b0a99f968679655e4c3f2f1f0f0000000000000000000000000000000000000000000000000001080b1215100e080000000000000000000000000000000000000000050b0d14170f0d070000000000000000000000000000000000000000000000000007131a283237444b4a433637413d3437353126190900000000000000000000000000000000000000000000000000000000000000000000000000000b20364b607589927d7c91a3b5b39e89776254667b90a6bbd0ddc7b29d88726f8499afc4c6aa95806b55402b16000000000000000b2035485a71869cb1bdc6b4a28e79634e39240e12273c52677c91a4b5bfb49f8a76614c36210c00000000000000000000000000000000000000000000000000000000000000000000000001080b0d0b0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071b2d3e4b60737f898d8d867a645b4935210a00000000000000000000000000000000000000000000011527374455606d7d858a8d8b867d6e605645311d13000000000000000000031628394b6072808c95999a9b9d9e9e9d9c9b9a97918578625544311d08000000152a3f546a7f94abbccbc6b4a28c77624c37220d000000091e32465771869cb1c1cdc1ad98836e58432e1900000000000b1f3346586278879ca4b5bcc9cbd4cdd7cdc9c7bab4a49c8a7c655d4c3d2c19090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a161e263135353025222b292022201d1409000000000000000000000000000000000000000000000000000000000000000000000000000000091d3145566d82978674869babb9a799837260657a8fa4bacfdec9b49e897471869cb1c6c2ad97826d58422d180300000000000005192b3c52677d929fb1b3a89a85705b4a36210c0b20364b6074869ca7ada195806a5846331f0a000000000000000000000000000000000000000000000000000000000000000000000008141c20221f180d0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d22364a5c6d82959ea7a49c8979634e38271502000000000000000000000000000000000000000000081d314455607382919b9faba49c928274604b41301b0b0000000000000000091e3246576a7f959faaaeb0b1b2b3b3b2b1b0afaca39b8573604b35200b000000182d42586d8297adc9d9d1c0a5907a65503b25100000000c21364b61768a9fb4cadcc7b19c87725c47321d000000000b1b31424c6176869ca5b5c2cac5bfbdbec2c8ccd5cdc2b6a89e8b7b655b49372715010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c1214120e0c06000000000000000000000000000000000000000000000000000000000000000309141d20201c130d16140b0d0b080100000000000000000000000000000000000000000000000000000000000000000000000000000000021527384e63798e937d7a8d9fb5b3a196816c64798ea3b9cee1cdb9a88b75788c9fb5cac4ae99846f59442f1a04000000000000000e25394d5f6d81939c9e9a8a7a644e3d2d1a07091d3145566379899598928373604b3a29170400000000000000000000000000000000000000000000000000000000000000000000081826303537342a231c11010000000000000000000000000000000000000000000004030000000000000000000000000000000000000000000f24394f64798e9fb3b9b5a798836e5645311d09000000000000000000000000000000000000000008182f3f4b60738398a0b0b4bcb5b1a097826d5f4d39281603000000000000000c21364b61768a9fb4bbc8c5c6c7c8c8c7c6c5c4c2b5a3917c66513c2611000000182d42586d8297adc2d7d1bca7927c67523d27120000000d22374d62788cabbccfdec9b49e89745f49341f000000031729394e606f8399a4b6c3bcb5b0aaa8a9adb3b8c5ccd3c6b9a99e8a79635544311d08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080c171f2127292823211a0f050000000000000000000000000000000000000000000000000000000000000001080b0b0700000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a21364a5b6f849a88768197a3b5b09f968175798ea3b8cee9d6c6a38e79849aabbccfc2ad98826d58432d1803000000000000000a1e30414a60727e8789847a645c4a361f0f00021527384a5b637780827d72605544311c0c0000000000000000000000000000000000000000000000000000000000000000000001142636434b4c483b382f1c1408000000000000000000000000000000000000090f111a180d0b05000000000000000000000000000000000000162b40556b8095aabeccc5b49f8b75604b36200b00000000000000000000000000000000000000011426364b5d6b8096a1b2becacfc9beb1a0927d675746321e0c000000000000000f24394e64798ea8bacdd9dadbdcdddddcdbdad9d2c1ad98826d58432d18030000172d42576c8297acbdc8cbbda8937d68533e28130000000d22384d62788da2c9d9dfc9b49f8a745f4a351f0000000a1e334657687e93a1b3c0b4ab9f9a959394979ea7b3b8c5d0c7b9a89b8573604b35200d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000609151d202933363c3e3d38352c20190e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071a2d3d4f647a8c988374859ba6b8b09f97868196abc0d6ebdcc7b29d879aa2b4c9d8c8ab96806b56412b16010000000000000001131c304354606972746f645c4a3e2d1b0100000a1a2d3d4a59626b6d686054443727150000000000000000000000000000000000000000000000000000000000000000000000081c304354606259504b3f3026180a00000000000000000000000000000004121d24262f2d2220190e0000000000000000000000000000000003182d43586d8298adc2d7cfbcab8d78634e38230e00000000000000000000000000000000000000081c304354657b8d9fb5bfcfc7c4bbc3beb29d8775614b3a2a17040000000000000e23384e63788da6b7c8d2cfcfcecdcfdadde4efdac4af9a856f5a45301a050000172c41576c8196aca8b2b7c4a8937e68533e29130000000d23384d62788da2b7cddfc9b49f8a745f4a351f0000000c21364b61768a9eb4b7b2a29a8c85807d7e8288939ea7b3bfd0c6b5a3927d68523b2b1805000000000000000000000000000000000000000000000000000000000000000000000000000002090e19202731363a464c5154524e493d352b1e0e000000000000000000000000070d0f0d070d0f0f0d0f0d0c100c0b100d0b0f0d0f0d0e0e0f0e0c0a0c0e0f0d0b100c0d0f0e0c060000000000000000000000000000000000000000000000000000000000000000000f22364a5c6c8197937e78889da8b8b1a49c969eb0c4d8eddfcab6a59da5b4c0d1cebbaa917c67513c271200000000000000000000132536434a535c5e5a4f4a3e2d2010000000000f1f2d3b484c5558534b433627190900000000000000000000000000000000000000000000000000000000000000000000000b20354b60737771655d4b4336281a0a000000000000000000000000000614222f383b444338352b1e0e00000000000000000000000000000004192e43596e8398aec3d8d9c9a58f7a65503a2510000000000000000000000000000000000000000b20354b6073869cabbccfc0b3afa6aeb3b7a695806b5847331f0b0000000000000b20354a6073879daab5c2bab9b9b8b9c5c8d1dfdcc6b19c87715c47321c000000162c41566b81969c929da6b7a8937e68533e29130000000d23384d62788da2b7cddfc9b49f8a745f4a351f00000011263b50667b90a8b3a59d918479706a68696d757e8999a1b3c0d0c1b19c8671594834200b000000000000000000000000000000000000000000000000000000000000000000000000060a151d202c3537444b515861676967635b4d483c2b1909000000000000000000010f1a2124211b222424212421212521202522202422242124232423211f21232422202522222423211a0f0100000000000000000000000000000000000000000000000000000000000000071b2d3e4c6176879d8b7b7a8a9ea7b7b6b1abb0bccde0f3e6d4c3b6b2b6c3d1d8c8b49f8a76614c36210c0000000000000000000008182530353e47494539362d20100200000000010f1d2b343740433d3530261809000000000000000000000000000000000000000000000000000000000000000000000000162c41566b808c867b6b60544538281a0a000000000000000000000005142431404c5159584d483c2b1905000000000000000000000000000004192e43596e8398aec3d8d0bba6907b66513b2611000000000000000000000000000000000000071a2d3e52677d92a4b5c9c3b3a29a9099a1b3b49f8a76614c392816030000000000071c304354667c8c9ca4a5a5a4a3a3a4b0b4c1d1ddc8b39d88735e392917030000162b40566b8095927d889db2a8937e69533e29140000000d23384d62788da2b7cddec9b49f89745f4a341f00000011263b50667b90a19e94877c6f645c555354566069778399a2b3c6c9b5a48c77624c37220d00000000000000000000000000000000000000000000000000000000000000000001080f1a212731363c494d5560676f767c7e7d7870625a483726140100000000000000000f1f2d3639362d363939363936363a36353a37353936393639383938363335383936363a37373a39352c1f0f0000000000000000000000000000000000000000000000000000000000000000101f334758647a8b9e8a7a7a899da6b7c7c0c4cddbebfcf1e1d4cac7cad4e2cebbaa98826d5746331e0a000000000000000000000008131c202932343024221b1002000000000000000d1820222b2d28201c1408000000000000000000000000000000000000000000000000000000000000000000000000001a2f445a6f84999c8d80726056453828190900000000000000000000122331424e5e666f6d625a4835200b000000000000000000000000000003182e43586d8398adc2d8d1bba6917c66513c27110000000000000000000000000000000000000d21364a5c71869bb0c2cbb7a59a847b8399a3b5a895806a5746321e090000000000001325364d5e667b868c8f8f8f8e8e8f9ba3b4c8dfc9b49f8a745746331e0a0000152b40556a80958b74869bb0a9937e69543e29140000000d23384d62788da2b7cddec9b49f89745f4a341f0000000b20364b6074838c897f75675f4e4a3d3e38454b596273849aafb1b5c2a5907b66503b2611000000000000000000000000000000000000000000000000000000000000000408141c202c3538454b525a636b747c848b9193928d8578625544311d0800000000000000071a2d3d4a4e4a3e4a4f4e4a4e4a4c504b4a4f4d4a4f4a4e4a4e4d4e4d4c46494e4f4a4b504c4b4f4e493d2c1c0c0000000000000000000000000000000000000000000000000000000000000004172a3a4a5c677d8d9e8a7b78889dabb0bccddfebf9fffff1e6dfdcdfe1cebeb49f8b78624d3929170300000000000000000000000000070b141d1f1a0f0d0700000000000000000000050b0d1618130b08010000000000000000000000000000000000000000000000000000000000000000000000000000172c41576c8196ab9f9583746056453727150100000000000000000e1e30414e60687c848278624d38220d000000000000000000000000000003182d42586d8297adc2d7d1bca7917c67523c27120000000000000000000000000000000000000f24394e64798ea3b5c9c4b29d87756673859bb1b39e8975614b36210d000000000000081830404d5d6571777a7a7a79787a859bb0c5dacebbaa8b76614b36210c0000152a3f556a7f948a74879cb2a9947f69543f2a140000000d23384d62788da2b7cddec9b49e89745f49341f000000081d314455606f77746a60564d40362d2828323b4855657b90a49ca4b5a7917c67523c27120000000000000000000000000000000000000000000000000000000000070c171f2630353d494e5660676f788088919a9faaa9a7a29a8673604b35200b000000000000000d21364a5c645c4d5c64645c645c61656160656260645c645c6363646361585b63645c6065615c64635b493a291704000000000000000000000000000000000000000000000000000000000000000c1c2d3e4d5f677d8c9e8b7d838d959eb0c3d8ecfffffffff7ebe3d7cdbdb1a0947f6a5a49351b0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014293e53697e93a8b5a1998374605544311d150400000000000006192c3c4d5f687e8d9998846f5a442f1a050000000000000000000000000002172c42576c8197acc1d6d2bda7927d68523d28130000000000000000000000000000000000061a2c3d566c8196abc1cbb7a6927d6757657b90a3b5a7927d67523b2a18050000000000001222303f4c5059626565646463687e93a8bdd2d8c8a28d77624d38220d0000142a3f54697f948873889eb3aa947f6a553f2a150000000d23384d62788da2b7cddec9b49e89745f49341f00000002152737444b596260554b45383021222b3437404c5663788e8f868fa7a6907b66513b2611000000000000000000000000000000000000000000000000000001080f1a21293336434b515b636b757c848c969ea6afb4bbc8c0b4a4907b66513b2611000000000000000f24394e6479645f677979647964767a76757a78747964796579787978766165797968757a77697a79635847331f0a0000000000000000000000000000000000000000000000000000000000000000102030414d5f677c899a928c788095abc0d5e5f0fefff7e7d9cfc6b9b49f97826d61503c2c19000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090b0d0b08010000000000000000000000000000000000000000000f243a4f647a8fa6b7b3a2998373604b43322211000000000000092035495a677d919fab9e88735e49331e090000000000000000000000000001172c41566c8196abc1d6d2bda8937d68533e281300000000000000000000000000000000000c2136495b72879db2c7c8b39d8874604b5d71869bb0af9a846f5948341f0b0000000000000412212f383b484d50504f4e51677c91a6bcd1ceb9a48f79644f3a240f000014293e54697e938774899fb4aa95806a55402b150000000d23384d62788da2b7cddec9b39e89745e49341f00000000091927313b474c4b443732282b34373b484c535e667583998974899ea58d78634d38230e0000000000000000000000000000000000000000000000000009141d202d363a474c5460666f788188919a9fabb3b8c4caced9d1c2a9947f69543f2a1400000000000003182d42586d826d677d807f78826d7f7d82807c8278836e827b817e837f7a657a817f7d7d7d847e7b8076614c37210c000000000000000000000000000000000000000000000000000000000000000002132330414d5e667884929a848096abc9c9d2e0eefeebd9c9bcb4a89e938174604b43331e0e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a151d2023201d140900000000000000000000000000000000000000000b20354a6073889db2c0b3a197816d614f402f1e0e0000000009192f404d6378899eb3b29d87725d48321d080000000000000000000000000001162b40566b8095abc0d5d3bea8937e69533e291400000000000000000000000000000000000e23394e63798ea5b6cac4ab95806b554453697e93a8b49f8b77624c37220d0000000000000003111c232b34373a3a3a3a4f657a8fa4bacfd1bba6917c66513c2711000013293e53687e9386758aa9baab95806b56402b160100000d23384d62788da2b7cddec9b39e89745e49341f000000000009151d2a343735312b35383b484d53596269717b87999b86758a9f9c87725b4935210c00000000000000000000000000000000000000000000000313192631353d4a4e586169737c848d969ea7afb5bcc9cbd5dfddd3c7b7a5917c66513c271100000000000004192f44596e847f7c8082827e826d7f8178826d7d7c846f827f7975837f7a697e7a72827c817a8281837c67523d271200000000000000000000000000000000000000000000000000000000000000000005132330404c5962727d8692969fabb1b5c2d0deeee3cfbcab9f988a7e6c60564531251500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004121a28323638353126191002000000000000000000000000000000000000071c3043546c8196abbcbfb19f947f695e4c3c2b19090000011426374c5e6f8499a8b9ae99846e59442f19040000000000000000000000000000152b40556a8095aabfd5d3bea9947e69543f2914000000000000000000000000000000000014293e54697e93a9c3cbb8a68f79644f374d63788da8b9aa927d68523d2813000000000000000000090d182022252525384d62788da2c6d7d3bda8937e68533e2913000013283d53687d9286758aa0b5ab96816c56412c170100000d23384d62788da2b7cddec8b39e89735e49341e000000000000020d181f2933363c484d5459626970777e86909c9f917c7c91a5947f6a553c2c1906000000000000000000000000000000000000000000000a161e3037444b515b636c767f87919aa2abb3b8c5cacfdae0ded2c9c3b6a99d8774604b36200b00000000000000182d42586d826d8278828278837f80817e7b81817586828078817f817f7a697e796d827c81807a818277624c37220d000000000000000000000000000000000000000000000000000000000000000000000513222f3b48546067737c848b949ca4b4c0d0e3dfcab49f8d827868604b453827150700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000212223038454b4d4b44372e2010000000000000000000000000000000000000001325364e63798c9fb5cabeb49f8d7c665a483727150100081d314455667b90a1b3bbaa937e69533e2914000000000000000000000000000000152a3f556a7f94aabfd4d4bfa9947f6a543f2a150000000000000000000000000000000006192c3c596e8399aec3c8b39e8874604a354a6074899eb4ad97826d583b2a180500000000000000000000050b0d101021364b60768ba8bacdd5bfaa95806a55402b15000012283d52677d9286758ba0b5ac97826d57422d180200000d23384d62788da2b7cddec8b39e89735e49341e0000000000000e1a283239464c535a626970777e858b939ca49d8c7e76879d9d8775604b36210e000000000000000000000000000000000000000000000a1a2832414d5560667079828a949da5afb4c0c8ccd5dfdfd6ccc8c1b5b0a59c8b7a645544311d080000000000000a162b40566b80807c676d6d626e6a6b6c69666c6c61716c6b626c6a6d7f7a667c78697e696c6a646c6c625947341f0b000000000000000000000000000000000000000000000000000000000000000000000004121d2b36434a5460676f777e869aa2b4c8dcd2bca7927d6d625a4e4231271a0a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000102130404d56606260554b3e2e1c0c000000000000000000000000000000000000082136495b6e8399aec0cfbcab9e8978625544311d11011527374b6073869cb1bfb49f8b77614c37220c00000000000000000000000000000014293f54697e94a9bed3d4bfaa957f6a55402a15000000000000000000000000000000000c2035495a73899eb3c8c3ad98836e544330435470869bb0b29d87725947341f0b0000000000000000000000000000091e32455774899fb4c9d7c1ac97826c57422d17020012273d52677c9286768ba0b5ad98836d58432e180300000d23384d62788da2b7cddec8b39e89735e49341e00000000010f1f2c38454b57616970787e858c939a9fa59d93877b77859b9f8b7b655745321e0900000000000000000000000000000000000000000003162838454b5f67747c848e979fa8b2b6c3c7d0dde0dacfcac5b8b3aca39b92877b645c4b3727150200000000000a1a28323650626b6b675f58584d59545657535157574b5c57564d57546169645e666361696156554f56574c473b2a1805000000000000000000000000000000000000000000000000000000000000000000000000000d18253036434b5259626973849aafc9d9d5c5a18c77624d483c311d150a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1b2e3f4d5e66757874645c4b3a2a17040000000000000000000000000000000000061a2c3d4f647a8fa2b4c8c9b8a79b8573604b3f2e1c0c1d314455687e93a4b6c0ae98836e5947341f0b00000000000000000000000000000014293e53697e93a8bed3d5c0ab95806b56402b16010000000000000000000000000000000d23384d62788da7b8ccbea9937e6954362536586d8297adb6a58c77624c37220d0000000000000000000000000000031628395d72889db2c6c9c3ae99846e59442f19040012273c51677c9186768ba0b5ae99836e59442e190400000d23384d62788da2b7cdddc8b39e88735e49331e000000000f1f2c3d4956606a767e858d949b9fa99f9890877e747b889b9e8c7d675d4b39281603000000000000000000000000000000000000000000091e324556606e7d87919aa2acb4bac6cad4dcded6ccc9bcb5afa79e968e857d74645d4b3e2e1909000000000002162838454b575a5e5b554e493d38433f40413e3b4142364642403842434f544f4c514d4f544f42403a414237342a1d0d00000000000000000000000000000000000000000000000000000000000000000000000000000008131c2630353b484d55677c92abbccfccb8a78b76614b362b1e1402000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000031629394b5d667c898d877a645847331f0f0000000000000000000000000000000000000f22374b5c70859ab0c1d2c5b4a395806b5d4b3a291726374b6074879db2c2b3a28e7a644f3b2a180400000000000000000000000000000013283e53687d93a8bdd2d6c0ab96816b56412c160100000000000000000000000000000012273c51677c91a6c5d5c4a48f7a644f3a2b40556b8095aac3a58f7a65503a25100000000000000000000000000000001b31465b70869bb0b1b5c1b09b86705b46311b000011263c51667b9186758aabbcaf99846f5a442f1a0500000d23384d62788da2b7cdddc8b39e88735e49331e0000000b1b2c3d495b63757f8a939ba3a99f99928a837b737a84909d98887b675f4d3f2e1b0a0000000000000000000000000000000000000000000a1d30404b607482929ca5afb4c0c9cdd7dfdfd3c9c5b8b3ab9f9a92898179706760554b3f2e2010000000000000091e324556606c6f73706a635b534c473b4038454b453839373435313538353f39363c383b3e3b322b252c2d221f180d00000000000000000000000000000000000000000000000000000000000000000000000000000000000008141c202b34374c61778b9fb4c8c8b39e88735746321e0e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1e324657657b8c9ea69d8876614c3d2c1a060000000000000000000000000000000000081b2e3e51667b90a3b5c9d1c1b49f8c7b655847331f314455687d92a5b7c1af9a846f5c4a361d0c0000000000000000000000000000000012283d52677d92a7bcd2d6c1ac96816c57412c1702000000000000000000000000000000152b40556a8095aab8c6b8a68c76614c37293e53697e93a8bda8937e68533e29130000000000000000000000000000051a30455a6f859a9b9ba3b5b29d87725d372715020011263b50667b9087758a9fb4af9a85705a45301b0500000d23384d62788da2b7cdddc8b39d88735e48331e000003162839495b637986959ea89f99928a847c76777f868f99988e8277655d4d41302111000000000000000000000000000000000000000000000f24394d5e6e8398a0b2b6c3c8d1dee1d9cfcac2b6b1a79e968c847d756c645c524b44372e2010020000000000000b21364b60768285888580797169615956564c5660564d4f4d484b44494e4a484d4c46393e35404337342a1d0d0b05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080d18203347586e8399aabbc1af99846f5a3929160300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071a2d3d4b6175879daab7a697826d5b493521080000000000000000000000000000000000001024384c5e71859bb0c0d1cfbcab9d8776614c4130364b6073879cb2c3b5a3907b65503e2d1b000000000000000000000000000000000012273c52677c91a7bcd1d7c1ac97826c57422d1702000000000000000000000000000003182e43586d8398ada3b1b39e8873584733273c51667c91a6bbac96816c57412c170000000000000000000000000000041a2f44596f849985859bb1b39e89745544311d080010253b50657a908774899fb4b09b86705b46311b0600000d23384d62788da2b7c7cac8b29d88735d48331e0000091e3246576379899ca49f958a847d76777d848b949a938a837a6e62594b3f302313030000000000000000000000000000000000000000000011273c51667c91a1b2becad3dce3dccfc9bcb4aea49c938980786f6760564e4a3d35312719100200000000000000091e324556606c6f777f898e867e77706c6b616376675f64625960555b63605962615758544b56584c473b2a190900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005182a3a4e63798b9fabafa3927d68523d281300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d21364a5c6c8196a5b6c4b59f8c79634e362513000000000000000000000000000000000000091c2f4050667b90a2b4c8d9c9b7a698836e5f4d3b4354677d92a4b6c2b09b85705d4b372010000000000000000000000000000000000011263c51667b91a6bbd0d7c2ad97826d58422d18030000000000000000000000000000011426365b70869b978d9ca49a85705b3a29253b50657a90a5baaf9a846f5a372614010000000000000000000000000004192e43596e83937e7e93a9b9a88b75604b36200b0010253a4f657a8f8874899eb3b09b86715b46311c0600000d23384d62788da2a8b2b7c3b29d88735d48331e00021527374b6175879da49c8a8077767d848b929a938b857e776e645c4c473b2f21130500000000000000000000000000000000000000000000041a2f44596f8499aebfcfdfe6f1e2cfbeb2ab9f9990867e756b635a524b4538362d201d150900000000000000000002162838454b5759616976808a938a8581807679887d697977667567677872647776616e69606b6e61594737271c130800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c2136495b687e8d999a958573604b35200b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081b2e3f4e64798c9fb4c3cfbcab96816c5443301c070000000000000000000000000000000000001223384c5e70859aafbfd0d4c4b2a0927d6759484a6073869cb1c3b6a4917c66513f2f1c02000000000000000000000000000000000011263b50667b90a5bbd0d8c2ad98836d58432e18030000000000000000000000000000081c30435473889d8d78869c97826d57422d243a4f64798fa4b9b29d87725544311d080000000000000000000000000003182d42586d82947e7d92a7c6a18c76614c37210c000f243a4f64798f8873889eb3b19c86715c47311c0700000d23384d62788d9c939da5b7b29d88725d48331d00081d3144556b8095a59c867978828a929a948c857e77706861584f4a3e342a1c14080000000000000000000000000000000000000000000000081d32485d72879db2c7dcd6d9e0dac6b2a0988c837b716860574d493c363228211a0f080100000000000000000000000a1a2832363b474c58616b777e8a948a7f70859a887e8a857b897d7d8a8079898477837e75808377615544353025180a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061a2c3d4e60687b84858076615544311d08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e22374b5d6f849aaabbcedac9b39d8873604a35200b000000000000000000000000000000000000091c2f404f657a8fa1b3c9dacfbeb39e8977624d51677c91a4b6c3b19c8673604a35201100000000000000000000000000000000000010253b50657a90a5bacfd8c3ae99836e59442e190400000000000000000000000000000b20354b60758a9d8773889e947f6a543f2a23394e63788ea3b8b49f8a75604b35200b0000000000000000000000000002172c42576c8195807c91a6b7a28d77624d38220d000f24394e64798e8974889db2b19c86715c47311c0700000d23384d62788d937e879db2b29d87725d48321d000b20364b6075889e9c8f7a7e8a979c91877f7770696259534c474b4d4c463a3026180800000000000000000000000000000000000000000000071d32475c72879cb1c9c6c1c4ced8c3ad9882786e655d534b4539352c211e160a070000000000000000000000000000000a161e212a343a4a5b657b86867f776a6c819684949c86898a89888885869c89888985858281857360534a4336281a0a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1f31424e5e656e706b61584637271501000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081c2e3f4f657a8fa2b3c8d9dfcbb7a68f79644f3a240f000000000000000000000000000000000000001122374b5d6f8499abbccfe0ccb9a799836e5f5e71869bb1c2b7a5927d675443301c070000000000000000000000000000000000000f253a4f647a8fa4b9cfd9c4ae99846f59442f1a0400000000000000000000000000000c22374c61778c9984778ca6927d67523d2822374d62778ca2c8bbaa8d77624d38220d0000000000000000000000000002172c42576c8196817b90a5b8a38e78634e39230e000e23394e63788e8974879db2b19c86715c47311c0700000d23384d62788d8b74859bb0b29c87725d47321d000f253a4f647a8fa7937e86939f9a877c736a6259534c483d4a55606361584b433626140100000000000000000000000000000000000000000002182d42576d8297abb6b1acb1bdcfbca7917c6960504c3f36322820190e090200000000000000000000000000000000000002090c1823394e63798a7b70827e69647a8e878298838697828b917c889882889580888975817e72686054453828160300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001132431404c50595a564c463a291909000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e23374b5d70849aafc0d0e6e7d4c4aa957f6a553a2a1704000000000000000000000000000000000000081b2e3f4e64798d9fb5c8d8d6c5b3a1917d67667c90a3b5c4b29d8774604b362513000000000000000000000000000000000000000f24394f64798ea4b9ced9c4af9a846f5a452f1a0500000000000000000000000000000e23384d63788d96817a8fa4907b65503b2621364b61768baabbc8a58f7a65503a25100000000000000000000000000002172c41576c8196827a8fa4b9a48f79644f3a240f000d23384d62788d8a75879cb1b19c86715c47311c0700000e23384e63788d8a75869cb1b19c87725c47321d0013283d53687d92a08b75869b9a83766660544d483b373a4a5c647478766d605443301c08000000000000000000000000000000000000000000000f24394e64798c9fa49c969fb5bcc9b49f8c7e6b624b4437281b0c0600000000000000000000000000000000000000000000000014293f54697e897571868978656e83947f878c7e8a897f94837b8c8a7c8b897d8b818593877e72605645321e10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613212f383b4445403633291b0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071a2d3d50657b90a2b4c8deeeefdac5b09b85705847331f0a000000000000000000000000000000000000001021364a5c6e8398aabbcee2d0bfb39e887670859bb0c1b7a6937e695544311808000000000000000000000000000000000000000e24394e63798ea3b8cedac5af9a85705a45301b0500000000000000000000000000000e24394e63798e937e7d92a48e79644f39241e324657748a9fb4bca7927d67523d28120000000000000000000000000001172c41566c8196827a8fa4b9a5907a65503b2510000c21374c61768c957f899eb4b19b86715c46311c0700000e23394e63788e8974879cb2b19c87715c47321c0014293e54697e93a99681889d887561574a4336342b384758647a878d8b8272604b35200b000000000000000000000000000000000000000000000d22364a5c6c81969c8681939fabbcbbaa9f93806d605545392a1c0e00000000000000000000000000000000000000000000000011273c51667c917d677d92877b6f788a897d92877e9383828a7a7f94837d928480937e7f86918374604b3e2e1b070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003111c23262f302b211f170b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c21364a5b6f849aafc0d1e3dcdadfcab49f8b76614c37210c00000000000000000000000000000000000000071a2d3d4d63788b9fb4c7d7e0cbb8a697827b90a3b4c5b39d8875604b37271500000000000000000000000000000000000000000e23384d63788da2b8cddbc5b09b86705b46311b0600000000000000000000000000000f243a4f64798f917c7f94a28d78634d38231628395e73889eb3bfa9947f6a543f2a150000000000000000000000000001162c41566b819682798fa4b9a6917b66513c2611000b20354b60758a937e899eb4b09b85705b46301b0600000e24394e63798e8873889db3b19c86715c47311c0013283d52687d92a79e969d97826d57463930252b3946566176889da59f907b65503b261000000000000000000000000000000000000000000000071b2d3e4b6073839886767e8d9fabbabbb49e9582736057473a2c1e1002000000000000000000000000000000000000000000081c2e3f4b60758889786c819790847b809580818877817f7686898486907b80867686877e797c89826d5c4a36220d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090e10191b160c0a04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005182b3b4e63798ea2b3c7ded1c8c5c8cfbcab917c67513c271200000000000000000000000000000000000000000f2135495b6d8297a9bacde1d5c4b1a097879db2c1b8a7947f69564532190900000000000000000000000000000000000000000d22384d62778da2b7ccdbc6b19b86715c46311c07000000000000000000000000000010253a4f657a8f8f7a8196a28d77624d38221d32475d72879cb2c0ab96816b56412c160100000000000000000000000001172c41566c819682798ea4b9a6917c67513c271200081c30435473888c76869cb1af9a856f5a45301a0500000f24394e64798e8773899eb3b19b86715c46311c000f253a4f647a8fa7b0abae99846f5b49392d313b48576174849aa6b6ab96816b56412c160100000000000000000000000000000000000000000000101d3144556073829686777e8d9fa9b9bcb0a09783756158493c2d20120400000000000000000000000000000000000000000e23374b5d65777e93867675858b879089988b7e7e7b7a6a61767e787586877679887b848275677b8b79644f3a240f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b203448596d8298adc0d0d1c0b4b0b4c0c9ac97826c573c2c19060000000000000000000000000000000000000006192c3c4d62778a9fb4c4d5e2cebeb1a59da5b7c6b39e8875614b3828160000000000000000000000000000000000000000000c22374c61778ca1b6ccdcc7b19c87725c47321d07000000000000000000000000000010253b50657a908e798298a18c77624c37221c31465b71869bb0c2ad98836d58432e180300000000000000000000000002172c41576c819682798ea3b9a6917c67513c271200011426365b70859b889ca4b5ad98836e58432e190300000f24394f64798e8774899eb3b09b86715b46311c000b20354b6074899eb3c7b49f8b7963574a3d444b596275849aa2b4c4ac97816c57422c1702000000000000000000000000000000000000000000000215273744556072819587797d8b9ea7b7beb1a1998576625a4a3e2f2213060000000000000000000000000000000000000010253a50657b88738195877b7a8b747b7f828b9486868578706b686263798a81778986726d615d6d827c67523c271200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c0e10121314141313110f0d0b080200000000000000000000000000000000000000000000000000000000000000000000000000000000000000031629394d62778b9fb4c9d9c8b4a29aa2b3c0b29d87725a4935200c00000000000000000000000000000000000000000e203448596b8095a6b8cbe0dccec3b7b2b7c3b9a8957f6a5746321a0a0000000000000000000000000000000000000000000c21364c61768ba1b6dadcc7b29d87725d48321d08000000000000000000000000000011263b51667b908d788399a18c76614c37211a2f455a6f849aafc4af9a846f5a452f1a0500000000000000000000000002172c41576c819682798fa4b9a6917c66513c27110000172d42576c82979da6b5c2ab96806b56412b160100000f243a4f64798f8774899eb3b09b86715b46311c00081d3144556c8196a9babbaa9b8575645c5855606877859aa2b4c0baa9937e68533e2913000000000000000000000000000000000000000000000000091927374454606c7f93887a7b899da6b5bfb3a39b8678645c4c403124140600000000000000000000000000000000000c1d2a43586e83927d73808b908c806b666a6d7d92807983868581786860687e826d7b816c544b4f647974604b362112040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060b0d14171f212426272929292928272523201d1515100c0a0400000000000000000000000000000000000000000000000000000000000000000000000000000a1e3246576b8095aabbcecebbaa9a859aa2b3b7a58d78634d38230e000000000000000000000000000000000000000005182b3b4b6176889eb3c2d3e5e1d4cac7cac7b39e8976614c392916000000000000000000000000000000000000000000000b21364b60768babbcc8ccc8b39d88735e48331e09000000000000000000000000000011263c51667b918d788499a18c76614c3721192e43596e8398aec3b19b86715c46311c0700000000000000000000000002172c42576c8197817a8fa4baa6917b66513c2611000013283d53687d92abb8c4c3a8927d68533d28130000000f253a4f647a8f8774899eb4b09b86705b46311b00011426374d62788a9fb4bfb5a39b8579716d6e747d889ba3b4c0c0b49f8a77614c37220c0000000000000000000000000000000000000000000000000009192736434a616a7e8d8a7b79889ba3b2beb4a49c887a665e4e423224150700000000000000000000000000000004182a3b4752677d9288766b797f7d737b72605f697e7b807c7d838b8b7e6874827560656c6251464b5c646056483b2f2212020000000000000000000000000000000000000000000000000000000000000000000000000000000003090e192023292a3337393b3d3e3e3f3e3d3c3a383631272a26211f17130e0c06000000000000000000000000000000000000000000000000000000000000000000011426374b6176899eb3c8d8cab49f8c78849aafc3a8937e68533726140100000000000000000000000000000000000000000d1e334657687e93a4b6cadeeee6dfddcdbaa995806b5846331b0b00000000000000000000000000000000000000000000091e324556758a9fb2b3b8c5b39e89735e49341e00000000000000000000000000000011263c51667b918d788499a28c77624d3722172d42576c8297acc1b29d87725d48321d0000000000000000000000000002172c42576c8196817a90a5baa6917b66513c261100000d22374d62778c9fb5cab6a58d78634d38230e00000010253a4f657a8f8774899eb3b09b85705b46301b0000092035485a6a7f94a1b3c0b5a39b8e86828388929ea6b4c1c2b4a2957f6a5947341f0b000000000000000000000000000000000000000000000000000009182530435060687d8c8b7d788598a0b5bcb6a69e8a7c68604f433225150700000000000000000000000000000b1f344759616a708496816c636a697f8a806b61757a676a78746e7884927d7e927d676161584c5761686b6962594c402f20100000000000000000000000000000000000000000000000000000000000000000000000000000010a161e212b35383e3a474c4e50525354545352514f4d4b44373f3b3633292823211a130d0b050000000000000000000000000000000000000000000000000000000000081d314455697e93a7b9ccd3c2ae98836e7d92aabbae99836e5544311d080000000000000000000000000000000000000000031729394b6074869cb1c0d1e7f7f4dec9b49f8a77614c3a291700000000000000000000000000000000000000000000000216284a5f748a9f9d9ea7b8b49f89745f4a271502000000000000000000000000000011263b50667b908d788499a28d78634d3823162b40566b8095abc0b39e89735e3827150200000000000000000000000003182d42586d8296817b90a5bba6907b66513b261100000b2034485970859aafbdb29d87725a4935200c00000010253a50657a8f8873889eb3b09a85705b45301b000005192b3c4b60728399a2b2bfb5b1a39b98999ea6b3b8c4c0b4a49a8473604b3b2a180400000000000000000000000000000000000000000000000000000008131c33424e5f677c8a8d7f7582959fabbab8a89e8c7e69614f4332251504000000000000000000000000000c22374c6177807678898c7c665b738888847f6d82897c7b8a806a7a80848b7d8d89777677665e61757d807e77665e4c3e2d1b0700000000000000000000000000000000000000000000000000000000000000000000000009141d2832363c484d54585861636567686969686866646260555955504c463a3e38352c282220180d040000000000000000000000000000000000000000000000000000000b20354b6074879db2c5d6cab6a48f7a65768b9fb4b39e8974604b35200b0000000000000000000000000000000000000000000b1d314455667c91a2b4c9daeceed8c3ae99836e5947341c0c0000000000000000000000000000000000000000000000001f34495e74899d87899eb3b49f8a755544311d08000000000000000000000000000010253a50657a8f8d788398a38e79634e3924142a3f54697f94a9beb49f8a745645311d0900000000000000000000000004192e43596e8395807b91a6bba5907b66503b2611000005192b3b50667b909ea7a0937e68533c2c19060000000f253a4f647a8f8873889db2af9a85705a45301b0000000e1c30435461758498a0b3b8c1b5b0adaeb3b8c5c7bab4a29a8677625544311d0c000000000000000000000000000000000000000000000000000000000000152431414d5e667b89948275808d9fa9b7b9aa9f927f6a614f43322212000000000000000000000000000d22384d62778d88807f8a8979666c81947f847f8d84868689857e8688838985829885898a7c667285808088897c665c4a36220b00000000000000000000000000000000000000000000000000000000000000000000010f19263138454b535a62696e7277797b7c7e7e7e7e7d7c7a7875726e6a65615858534e493d3e37342b1f180c00000000000000000000000000000000000000000000000000081b2e3e52677c91a5b7cad8c8b19c86715d70859aafb9a78f7a644f3a250f000000000000000000000000000000000000000000011527374c5e70859aabbccfe3ead5bfaa95806a553c2c19060000000000000000000000000000000000000000000000091e33495e7388917c8096abbcab8b75604b36200b00000000000000000000000000000f24394f64798e8e798298a48e79644f392413283e53687d93a8bdbaa98b75604b36200b000000000000000000000000051a2f445a6f8495807c91a6baa58f7a65503a25100000000d23384c5e6c808f928e8272604a35200e000000000f243a4f64798f8974879db2af9a856f5a45301a000000011426364657617583939ea7b2b7c4c2c3c5c6b9b4a99f9484766259473726140000000000000000000000000000000000000000000000000000000000000006142330404c5d6479879885777d8a9da6b5bbb49d947f6a614f402f1a0a0000000000000000000000000b2034485a6a7f868a8e9196887c7979898978858a8b7d879a84848a88808a9580889883858a787a8f7c7d77838a7a644f39291703000000000000000000000000000000000000000000000000000000000000000001141f2d37444b56606870787e83878c8e90929393949392918f8d8a87837f7b76726d68635b58534d483b342a1c0e0000000000000000000000000000000000000000000000000d22374b5c70859bb0c3d4cebbaa937e6954697e94a9c2aa957f6a5539291703000000000000000000000000000000000000000000091930404f647a8d9fb5cadfedd8c3ad98836e5a493520110000000000000000000000000000000000000000000000081d33485d72888f7a8196acb6a08b76614b36210c00000000000000000000000000000e23384e63788d8f7a8196a5907a65503b2512283d52677d92a7bcc7a18c76614c37210c000000000000000000000000061b30455b7085947f7c92a7b9a48e79644f39240f000000091c2f4051626c7a7d796d605443301c07000000000f24394e64798e8974879cb1af9a846f5a452f1a00000000081829394657616e7e89959da6aaaeb0afaca89e978a7f736158473b2a190900000000000000000000000000000000000000000000000000000000000000000513222f3f4b5b63778599877a7a889ba3b5bbae9d947f6a5e4c38281602000000000000000000000005192b3c50616a7175797c808d9086868999877e849a87798795808497827e93897f94897e86837e939092827484846f5746331e0a0000000000000000000000000000000000000000000000000000000000000008141c323d4a556068757d858c93989da5a3a5a7a8a9a9a8a7a6a4aa9f9c9894908b87827d78736d6862594c473a2b1e0e0000000000000000000000000000000000000000000004182a3a4f647a8fa3b5c9dfc9b49f8b77614d63788da4b6af9a85705746331e0a000000000000000000000000000000000000000000001222364a5c6e8398adc4d4e7dfc9b49f8b78624d3f2e180800000000000000000000000000000000000000000000071d32475c72878e798298adb6a18c77614c37220c00000000000000000000000000000d22374c62778c917c7f94a7927d67523d2812273c51677c91a6bcb7a18c77624c37220d000000000000000000000000071c31465c7186947e7d92a7b8a38e78634e39230e0000000011223444515c6467645c4a4336251300000000000e23394e63798e8a75869cb1ae99846f59442f1a00000000000b1b2939464b6068767f888f95999b9a97928981786a6055463a2a1d0d000000000000000000000000000000000000000000000000000000000000000000000411202e3d4959627583978a7d77859babb0bbb59f8d7c665645321e090000000000000000000000000d1d33435055566063666b7e8c86777383917c7684978278878c7d84937e7f9486818a847f947f94868385707a8c76614b36210c00000000000000000000000000000000000000000000000000000000000008182630424f5c64737d88939a9fabadb2b7c3babcbdbebebdbdbbc8bbb4b1aeaaab9f9c98938d88837d776e6159483c2b19050000000000000000000000000000000000000000000a1f3347586d8298adc1d1d6c5ae99846e58495b72879cb1b49f8a76614b36210c00000000000000000000000000000000000000000000071b2e3e4e63788da6b7cbd4e2cebbaa98836e5d4b36261401000000000000000000000000000000000000000000071c31475c71868d788399aeb7a28c77624d37220d00000000000000000000000000000b21364b60768b937e7d92a7947f69543f2a14263b50667b90a5bbb7a28d78624d38230d000000000000000000000000081d32475d728796808196abb7a28d77624d38220d00000000051626343e4b4f524f4b4639352c1e10020000000d23384d62788d8b75869bb0ad98836e58432e190000000000000b1b2932424e58616a747a80848585827d766c635a4b4437291c0d00000000000000000000000000000000000000000000000000000000000000000000000002101f2c3b4857617382958d807d8c969eb0bcab9d8875604b36210b000000000000000000000000001525333c38454b4e5160687b89887a77878a7a7584937e78878a7b858d798195808489838a8183908c7e69748978634d38230e000000000000000000000000000000000000000000000000000000000008182636434b60697a86939da6b0b5bcc9c7cad4d0d1d3d3d3d3d2d1d8cecac7c3c9bcb5b1ada8a69d98938b8377625a4835200f0000000000000000000000000000000000000000011426364c61778a9fb4c9dfccb9a7917c67513c566b8196abbbaa917c66513625130000000000000000000000000000000000000000000000102135495b73889db3b7c4d4d8c8b2a08f7b655443301c0a000000000000000000000000000000000000000000061b31465b70868c77849aafb8a28d78634d38230e0000000000000000000000000000091e32455674899782798ea996816b56412c16253a50657a8fa5bab8a28d78634d38230e000000000000000000000000091e33485e73889c87879db2b6a18c76614c37210c000000001323303f4c5059626361574d493c2d20100000000c21364c61768b8b76859bb0ac97826c57422d17000000000000000b161e313a474c5460646a6e70706d6861574d493c3127190c0000000000000000000000000000000000000000000000000000000000000000000000000000010f1d2b394655606d8092958d788096abc9b7a6937e68533e2913000000000000000000000000000715202828323639414e5d6578848b7f7989887875848c7c78878878817373857d77877786826e7b7c6960718674604b36200b00000000000000000000000000000000000000000000000000000000011426364354606d7e8b9ca4b2b7c4cacfdadcded8d3d0cdcccbcccdced1d3d8dcd8dacfcac7c2c4b7b2adaa9f988778624d3d2d1a0700000000000000000000000000000000000000081c3043546a7f94a9bacddec9b39e8975604b3a50657a8fa7b8ac97826d5443301c07000000000000000000000000000000000000000000000b21364b60758a9e9da6b7cbdfcfbeb09b8573604b392816030000000000000000000000000000000000000000061b30455b70858c77859aafb8a38e78634e39230e0000000000000000000000000000021628385c72879b85738a9f98836d58432e18243a4f64798fa4b9b8a28d78634d38230e000000000000000000000000031628385f7489927d7f94a9bbaa8b75604b36200b0000000c1d30414d5d65717779766e625a4a3e2d1a0a00000a1e334657748a8c76859aafab95806b56402b16000000000000000003141c2a3336434b4f55595b5a57524c4639352c1d150900000000000000000000000000000000000000000000000000000000000000000000000000000000000d1b2937444b626a7e8c9b858399afc4c4ae99836e59442e190400000000000000000000000000030d0a151d2024313f4c5a6273808c857f8986777d89897a7a8985797a7e777262756175746066665e617779645544311d0800000000000000000000000000000000000000000000000000000002101c304354607281939fa9b6c2cbd4dfdfd5ccc8c3bebbb8b7b6b6b7b9bbbec2c7cad4d9dfdcd7d4cbc8c8bbb4a59a84705b4a36210c000000000000000000000000000000000000000b20354b6073879db2c7d7d4c4ac97826d5645354b6075899eb3b39d8874604a35200b000000000000000000000000000000000000000000081b2e3e51677c9188889db3c8ddddc9b5a3927d685745321e0b0000000000000000000000000000000000000000051a2f455a6f848c77859aafb9a48e79644f39240f0000000000000000000000000000001a2f455a6f849a8b808a9f9b85705b3b2a18253a50657a8fa5bab7a28d78624d38230d000000000000000000000000091e324556758a9b85869cb1b49f8a755645321d09000004182a3b4d5f677b868c8e8a8378645c4a3828160200031729395e73889580889db3a9947f69543f2a14000000000000000000000c171f2630353a40444645423d36332920190e01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b192731435060687c899899a1b2b7b8ae99846e59442f19040000000000000000000000000000000002090b13212f3c4855606a798592889c867779868f8382898d837f696055605660605550514d5961645c4a37271502000000000000000000000000000000000000000000000000000000102031424b607282979fb4bac7d3dfd8cec9c5b8b3ada9a6a3a2a1a1a2a3a6a9adb2b7c3c4c9ced8dcdfddd8cec3b4a28e79634e39240e00000000000000000000000000000000000006192c3c51667b90a5b7cadfcbb7a68f7a6550383144556d8398adb7a68e79644f39240f0000000000000000000000000000000000000000000d22374b5c7085917c7f94a9bed4e4d2c1b39d8875604b392917030000000000000000000000000000000000000004192f44596e848c77859aafb9a48f7a644f3a250f000000000000000000000000000002172d42576c82979b8581979e89735947341f263b50667b90a5bbb7a28c77624d37220d0000000000000000000000000b21364b60768ba39b9ca4b6b39e89745e3828150200000b1f344759677d8d9ba3aa9f99897a645645321e0900001c32475c71879580889db3a7917c67523c271200000000000000000000000408141c20252b2f30302d28211e170b060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009151d33424e5e6577828b979da6a79e917d67523c2712000000000000000000000000000000000000000003111d2b37444b5b63707d88939a85707786877279887b69614a444b454b4b44373c3a474c4e4a3e2d19090000000000000000000000000000000000000000000000000000000a1a2e3e4e606d8197a0b1bdcdd7e1d0c8bbb4ada79e9894908e8d8c8c8d8e9194989da5a9afb4bac7c7cad3d5d8d0c0a6917b66513c26110000000000000000000000000000000000000c2035495a6f8499afc3d4ddc8b29d8874604b35273752677c92aabbaa957f6a553c2b19060000000000000000000000000000000000000006192b3c4f647a8f8576879db2c8d3e1dfcbb7a6947f695746331e0c0000000000000000000000000000000000000004192e43596e838c77859aafbaa58f7a65503a251000000000000000000000000000000014293f54697e949984768a9f8c77624c3722273c51667c91a6bbbcab8c77614c37220c0000000000000000000000000c21374c61768ca1b0b1b6c2b39d88735e48331e0000000c22374c61778a9eabb5bbb4a79d8775604b36210b00051b30455a70858c77859bb0a48e79644f39240f0000000000000000000000000001080b0f15191b1b18130c0a030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001152431404c59626d7881888c8c897f695f4d392510000000000000000000000000000000000000000000000d1926313d4a4e5f67757e88806b6277806b637773604b4331353236353127272a343739362d2010000000000000000000000000000000000000000000000000000000021628384b5c687e939fb1becee2d7cdbfb3aa9f988f88837e7b7877767778797c7e83878d939a9fa9acb2b6c3c0c2c2b4a28e79634e39230e0000000000000000000000000000000000021628384d62788c9fb5cadfd4c3ab96816c54433021364c61768a9fb4b19b86715a4835200b000000000000000000000000000000000000000b2035485a6e838f7a7f94a6b2b6c3d3e5d4c4b39e8976614b3a29170400000000000000000000000000000000000003182d43586d828c77849aafbaa5907b65503b261000000000000000000000000000000011263b50667b909f8d849aa98f7a65503a25283d52677d92a7bcb49f8a75604b35200b0000000000000000070c0e131322384d62778da2b7c6c9c7b29c87725d47321d08000014293e53697e93a8b9c9cec5b7a5917c67513c27120003182e43586d8398899ba3b4a68b76614c36210c000000000000000000000000000000000000040605020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613212f3b484c5a636c7376777469614f41301d0a000000000000000000000000000000000000000000000009141d2d36414d56606975726059626b625962605544311d201e21201d1511181f2224221b1002000000000000000000000000000000000000000000000000000000091e324556647a8b9fb4bdcedcd5c7bab4a1998b837a746e696663626161626466696d72787e848a91979ca5a7abadaca49a846f5b4936210c0000000000000000000000000000000000091e3245566b8096abbccfdfcab6a58f7a644f36261f33465870859aafb5a38d78624d38230d0000000000000000000000000000000000000417293a4d62788a8476899e9f9ca5b6c7d8e0ccb8a7957f6a5847331f0b00000000000000000000000000000000000002182d42576d828d788499aebba6907b66513b26110000000000000000000000000000000d22384d62778da79f9aa2a8937e68533e29293e53697e93a8beb39e88735544311d08000000000000040f1a2124282826384e63788da3b8cddbc6b19b86715c46311c070001172c41566c8196abc6d6e2d4c3aa957f6a55402a150000162b40556b80959ea7b4b39e88735846331f0a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003111d2a343c494d5758616260544f4332231301000000000000000000000000000000000000000000000000010f1a213138454b55606054484c5651484d4b443726140b090b0b080100040a0c0f0d070000000000000000000000000000000000000000000000000000000006192b3c4b6074879ca9bacedcd5c5b8a99f9283786e65605454514e4d4c4c4d4e5154585a62696f767c82878c91969896928677624d3d2c1a0600000000000000000000000000000000000b21364b6075889eb3c9cddcc7b29d87725c4b371817293a54697e94a9c1a9947e69543b2a180500000000000000000000000000000000000a1f3346586c818e797f959f8c879ca9bacee2d5c5b39e8976614c39291703000000000000000000000000000000000002172c41576c818d788398aebba6917c66513c27110000000000000000000000000000000b2034485a73889eb3afb3ac97826c573a292a3f556a7f94aabfb09b86715b3726140100000000000c181f2d36393d3e3b394f64798ea4b9cedac5b09b85705b46301b060001162b40566b8095abbfccd5ccbcab947e69543f2914000012273c52677c91aab8c5ae99846f593a291704000000000000000000000000000000000000000000000000000000000000000000000000000000000001080b0b090200000000000000000000000000000000000000000000000000000000000000000d181f2c35383a474c4d4b43363225140500000000000000000000000000000000000000000000000000000007131a283237444b4a433637413d3437353126190900000000000000000000000000000000000000000000000000000000000000000000000000000000000b2035495a6a7f95a5b6c7d8d7c7b8a79e8b7d6f625a504b43363b3938373738393c3f3c484d545761666c72777c8083817d74625948341f0f000000000000000000000000000000000005182b3b52677d92a7acb0bdcdc2ab95806b563e2e1b0e23384e63788da4b6b09a85705947341f0b00000000000000000000000000000000011527374c6176898476899e9580798b9fb4c3d3e0ccb9a795806b5746331e0a000000000000000000000000000000000001162b41566b808e798398adbca7927c67523d271200000000000000000000000000000005192b3c5a6f849aafc4c6b19c86715846332b41566b8096abc0ad97826d58422d1800000000000c1c2a333d4a4e5353504d4f657a8fa4bacfd9c4af9a846f5a452f1a05000011263b50667b90a1b3b8c5b9b39f8c79634e39230e00000c21364c61768b9fb4baa9937e69543e2914000000000000000000000000000000000000000000000000000000000000000000000000000000060c0e141d20201d150a0a01000000000000000000000000000000000000000000000000000000000000050e192023293337373530261814070000000000000000000000000000000000000000000000000000000000000a161e263135353025222b292022201d1409000000000000000000000000000000000000000000000000000000000000000000000000000000000006192c3c4d62788a9fb4c3d3e2cdbaa99e897b675f4d4f504e4b453836312722232427292b353839464b51575962676b6d6c676055483b2b180100000000000000000000000000000000000b203448596f849a96969fb0c4b6a48e79644e3924100c2135495b72879cb1b49f8b77624c37220d00000000000000000000000000000000081d314455697f8f7a7e949f8b786b8095a5b6cadfd6c5b39e8976614b382815020000000000000000000000000000000000162b40556b808f798297acbda7927d68523d281300000000000000000000000000000000162b40556b8095aac7cab49f8b76614c362e43586d8398adc6a9937e69543e29140000000009192a3a474c5b63686866625a667b90a5bbd0d9c4ae99846f59442f1a0400000f23384c5e6f83959ea7a5a79e94806b5b4936210c00000a1f3346586f8399a7ac9f8a77624c37220d00000000000000000000000000000000000000000000000000000000000000000000000000000e192023263135363228251e130500000000000000000000000000000000000000000000000000000000000000060c0e171f2122201c14080000000000000000000000000000000000000000000000000000000000000000000309141d20201c130d16140b0d0b08010000000000000000000000000000000000000000000000000000000000000000000000000000000000000c2135495b6d8298a9bacde1cfbfb49f8b7b655d57616465636056524b4538301f18111a28323f4b4f565959565052565857524b44372b1d0d0000000000000000000000000000000000000d22374d62778b96808196acc1b19c87725c4a36210d061a2c3d566b8096abbcab937e68533a2a17040000000000000000000000000000001325364b6074878575889d97816c6074879cb2becfe0ccb9a7947f695645321d080000000000000000000000000000000000152a3f556a7f8f7a8197acbda8937d68533e28130000000000000000000000000000000010263b50657b90a9bacdbcab907b66503b28395a70859aafb9a88f7a654f3a2510000000011426374758616f797d7d7b7874717d92a7bdd2d8c3ae99836e59442e19040000091c2f404b60747f888e908f897f72604a3d2c1a0600000417293a4e6379899597917f695948341f0b00000000000000000000000000000000000000000000000000000000000000000000000006141e2c353837444b4b45383930231507000000000000000000000000000000000000000000000000000000000000000000040a0c0d0b080100000000000000000000000000000000000000000000000000000000000000000000000001080b0b07000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004172a3a4d63788c9fb4c7d7d6c6b3a1927d675d656f76797a79756f6760564d41332a1c2838454b5d656c6e6e6b655d4f4a3e3d363127190d000000000000000000000000000000000000071a2d3e546a7f948b778398adc1aa957f6a553d2d1a070010253a4f657a8fa7b8af9a846f5847331f0a0000000000000000000000000000071c304354677d917c7d929f8a776256657b90a0b2c5d5d6c5b39d8875604b362614010000000000000000000000000000010214293f54697e907b8196abbea8937e69533e2914090706030000000000000000000000000c21364b61768a9fb4c9c9aa95806a553a32465772879db2b49e8975604b36200b000000081d3144556176838e9293908d8986889db3c8ddd8c3ad98836e58432e1903000000111d314556606a74787b797569605443301f0f000000000b2135495b637880827c69614f3b2a18050000000000000000000000000000000000000000000000000000000000000000000000051424313c494d5755606056524d4133251502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1f3347586d8297abbccfe1ccb9a899836e606b7b848b8f908e8a847d74675f4c473a2e364556606c7a818483807a70645c4b45382b1d0f010000000000000000000000000000000000000d21364a5c71869984768a9fb4b5a38d78634e38230f00000b20354b6074889eb3b49f8b77614c37210c00000000000000000000000000000b20354a6073868774869b96806b594b5d6d8298a7b8ccdfcbb7a6937d685443301c08000000000000000000050b0d1215161819293e53697e907b8095abbea9947e69543f291e1e1d1b1815100b080100000000000000091e3246576e8398aec3c5af9a85705847364b61768b9fb4ae99846f5544311d080000000b20354b60738599a1a8a8a5a79e9b9da6b8cbe0d7c2ad97826d58422d180300000002152738454b546063656460564a433625130100000000061a2c3d495a626b6d665e4f43321d0d000000000000000000000000000000000000000000000000000000000000000000000000132331424e5a636c72757571675f50433320100000000000000000000000070c0e1213110c0a030000000000000000000000000000000000000000000000000000000000000000000000000000070d0f0d070d0f0f0d0f0d0c100c0b100d0b0f0d0f0d0e0e0f0e0c0a0c0e0f0d0b100c0d0f0e0c0600000000000000000000000000000000000000000000000000000000000000000c21374c61778a9fb4c9d9d6c5b39e89776272808f9a9faaa5a99f9a92877d6e61584b3f43546074818f969998958f847a6b6056483b2c1f0f0100000000000000000000000000000000000f24394e64798e917c7e93a9bab19b86715b4935210c0000081d3144556d8298adbbaa927d68533a291704000000000000000000000000081c2f3f51667c917e7a909e8976614c3f4c6177899eb3c0d1d4c4b29c8773604b35201100000000000000000d192022272a2c2d2e2f3d53687d927d8196abbfa9947f6a543f33333332302d2a26201d15090000000000000316283951667c91a5b6cab49f8b76614c3950657a90abbca9947e69543727150200000012273c52677c91a3b3bfbdc5b9b3b0b3b8c4d5e7d6c1ac96816c57412c1702000000000a1a273136434b4e504f4b4538302518080000000000000e1f2c3c484d5657514c403225140000000000000000000000000000000000000000000000000000000000000000000000000a1a31414e60687881878a8a867d6a61503e2d1b070000000000000000050f1a2124282826211e170c0a03000000000000000000000000000000000000000000000000000000000000000000010f1a2124211b222424212421212521202522202422242124232423211f21232422202522222423211a0f01000000000000000000000000000000000000000000000000000000000005192b3c54697e93a9bacee0ccb9a7957f6a6b80959eafb4bbc7bab4afa59d918376655d4e4b607283979fabaeaeaba29a8c80746259493d2d1f0f00000000000000000000000000000000071a2d3d556b80958875869bb0c1a9947f6a543d2c1a0600000114263751677c91a9baae99846f5846331f0a0000000000000000000000000e23384b5d708589768499957f6a5847344759687d92a2b4c7d8cab6a5917c6752402f1c09000000000006141d2b34383c3f414243454652677d9288899eb4bfaa95806a55484849484745423f3b35312719090000000000000b20354b6073879cb2c1bbaa947f695645576c8196acb5a48e79634e39240e00000001172c41566c8196abc1d0d2d6ccc9c6c8cbd5e2e9d4bfaa947f6a553f2a150000000000000a151d263035393b3a3631271c130800000000000000000e1d2b343840423c382f2214070000000000000000000000000000000000000000000000000000000000000000000000021628384d5f687e8b969d9f9f9c927f6a5c4a36220d000000000000000d18202d36393d3e3b363329211e160b07000000000000000000000000000000000000000000000000000000000000000f1f2d3639362d363939363936363a36353a37353936393639383938363335383936363a37373a39352c1f0f00000000000000000000000000000000000000000000000000000000000b2035485a71869bb1c7d8dec9b39e8976647a8c9fb4bccabfb3aea7a9b1b2a098887b685f5a6a7f95a1b1bdc3c3c0b4aa9f968577635b4a3d2d1e0e0000000000000000000000000000000c21364a5b72879681798ea3b5b4a38d78624d38220f000000000c21364b61768a9fb4b49f8a76614c36210c0000000000000000000000071b2e3e50657b9081788c9e8876614b3a2a3a4a6072849aa9baced3c3b19b86715e4c38231000000000021424323c484d51555657595a5b5c677c917c8096abc0ab95806b5d5d5e5e5e5c5b5855504b44372715010000000000081c304354687d92a3b5c8b29d8774604c6075899eb3b19c86715b4a36210c00000001172c41566c8196abbfcfd7dadddedbdde0e7ece7d1c1a6917c66513c2711000000000000000208141c20232624201d150a00000000000000000000000d1920222b2d26241d1204000000000000000000000000000000000000000000000000000000000000000000000000091e324556677d929fa9b2b5b5b19f8d7a644f39240f0000000000000d1d2b343d4a4e5253504b4639363229221b100a04000000000000000000000000000000000000000000000000000000071a2d3d4a4e4a3e4a4f4e4a4e4a4c504b4a4f4d4a4f4a4e4a4e4d4e4d4c46494e4f4a4b504c4b4f4e493d2c1c0c000000000000000000000000000000000000000000000000000000000d22384d62788da3b5c9e5d2c1ab96806b6e8398abbccfc1b3a19991939ba3b0a69e8b7d6962788b9fb4bfced9cac1c8bbb4a39b8779635b4a3c2c1b0b00000000000000000000000000000e24394e63798e8e798196abc1b09b85705a4835200b000000000a1e3246576f8499afbaa9927d675239291603000000000000000000000d22364a5c6f848a788196937e695746331c30435463798b9fb4c3d3c9b5a3907b66503e2e1b070000000c1f32424f5a62676a6b6d6e6f7072737e9382859bb0c2ac978173727373737372706d6a65605544311d080000000000011426364b6073859babbcb7a596806b616a8095a7b8a7947f69543d2d1a070000000011263b51667b90a1b2bfc2c5c8cbd4d0d2d5d7d7c9b4a38c77624d37220d00000000000000000001080b0e100f0b090200000000000000000000000000050b0d1618110f0900000000000000000000000000000000000000000000000000000000000000000000000000000b21364b6075899eb3bac7cacabcab97816c57422c17000000000008182b3b484c5b636768666157534b4639362d211f170b08000000000000000000000000000000000000000000000000000d21364a5c645c4d5c64645c645c61656160656260645c645c6363646361585b63645c6065615c64635b493a29170400000000000000000000000000000000000000000000000000000013293e53687e93a8c1d2ddc9b5a38d796375899fb4bcc9b5a399837c7e86909ba3a99f927f6c8197a9bacdddcabaada8afb3b4a69d8979635b493929170300000000000000000000000005192b3c556a80958674889db3bcab937e69543c2b1905000000000316293953687e93abbcae99836e5746321e0a000000000000000000071a2d3d4f647a8f83768a9d8774604b3929172536495b6a8095a5b6cad2c1af9a85705c4a36220c00000012273b4f6069787c7f81828384868788939c989ba3b5c5b19f978888888888888785827f7b73604b35200b000000000000081d314455647a8c9fb4bcb49f8d7e767d8c9fb4b39e8976614c36210f00000000000f24384c5e6f8398a0a8adb0b3b7c4bbbdc0c2c6b9ab9b8570594834200b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011263b51667b90a7b8ccd7dfdac9af9a85705a45301b000000000114263648596270797d7d7b76706861574f4a3e363329221b100902000000000000000000000000000000000000000000000f24394e6479645f677979647964767a76757a78747964796579787978766165797968757a77697a79635847331f0a000000000000000000000000000000000000000000000000000004172a3a596e8399aec3d8dbc6b09b867164798ea89fabbab19b85726769717b85939fa89f8d808b9fb4c7d7d5c5ad9c939aa1afb7a79d8879635746331e150200000000000000000000000b2034485a7186947e7b91a6b8b49f8b77624c37220e0000000000000d22374d62778b9fb5b49f8a76614b36210c0000000000000000000921364a5c6e838f7b7f94917c675544311b0b182c3d4b6074879cb2bdcec8b4a28f7a644f3b2a1804000014293e54697e8d91949697989a9b9c9ea6adadb0b5c1cebdb1a69d9d9d9d9e9d9c9a97949084705b45301b060000000000011426374b5c6a7f949eb3b7ab9f938b929faab4a2937e695846331f0a0000000000091c2f404b6175838d93979a9da6a3a5a8aaadaca89e8d7b65503b2b1805000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000405030000000000000002080b0d0c0a03000000000000000013293e53687e93a8c5d5e8ecdac9af9a846f5a452f1a00000000081c3043546277848e9293908a857d766c645c534c463a372e211e160a050000000000000000000000000000000000000003182d42586d826d677d807f78826d7f7d82807c8278836e827b817e837f7a657a817f7d7d7d847e7b8076614c37210c00000000000000000000000000000000000000000000000000000a1f33475873889db2c8dddac9aa95806a677c919e8a9fa8a9947f6954545d65737e8a9da59f959fa9bacde0cbb8a6937e84959eb4b8a69c8675614b4332201000000000000000000000000d22384d62778d8d788398adc4af9a856f594834200b0000000000000b2034485971869bb0baa9917c6752382715020000000000000009192f3f4e64798c9283899a846f5f4d372715000f1d324556657b909fb1c4d1c0ad98826d5947341f0b00000f24394e647a8690979c9faaa7abaeb1b3b4bcc9babbbcbdc4b7b3b2b2b3b3b3b1b0aca59d89745e49341f0900000000000009192e3e4f616b80919da6aeb4a8a1a8b4b5a59a8473604b3a291704000000000000121e324657616e787e8285888b8e9093959797938a7d675d4b371d0d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070d0f16191a18130c0a04000409151d2023211e170b0600000000000012273c51677c91a9bacddadbcfbcab96816b56412c16000000000b20354b6073859aa2a7a8aa9f9a9289827a716861584f4b3f36322820190d08000000000000000000000000000000000004192f44596e847f7c8082827e826d7f8178826d7d7c846f827f7975837f7a697e7a72827c817a8281837c67523d271200000000000000000000000000000000000000000000000000000c21374c61768ca6b7cbdfcfbcab8f7a65687d9289768a9fa6917b66513f4c54606879879ca4aab4bac7d7ddc8b39e88737280929fa9b6a499836e614f3e2d18080000000000000000000215273753687d938675899eb3bbaa937d68533b2b180500000000000005182b3b556a7f95aac3ad98836e5645311d09000000000000011527374c5d6f84927d82978b79634e4130190900021528384b5d6d8297a6b7c9c9b49f8b77614c37220c00000d21364a5c64737b82868a8e9296999b9d9faba4a5a6a7a7a8a9a9a9a9a9a8a5a59d9791877c66503b261100000000000000001020324351626b7d8892999fa9a6a9ab9f998777625544311b0b0000000000000003162839464b5a63696d707376787b7d8082817e77675f4d3f2e1c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f1a21242b2f302d29211f170c181f2731363836332920190e00000000000c21374c61768a9fb4bcc9c6bdb59f8c7a644e39240f0000000010253a50657a8fa3b4c0c8bbb4afa89e978e867e766d645d534b4538342b231c110902000000000000000000000000000000182d42586d826d8278828278837f80817e7b81817586828078817f817f7a697e796d827c81807a818277624c37220d000000000000000000000000000000000000000000000000000010253a50657a8fa5c4d4dfcab59f8b7661677c918974879ca5907b66503b36434b5b6377869ca6b8cbd7e5dbc6b19c8671606b7d8b9fa9b2a1947f695c4a362513000000000000000000081d3144556e83947f7b91a8b9b49f8a77614c37210d00000000000000000f24394e64798ea5b7b49e8975604b36200b0000000000000e1d314455657b90937e8796816c5b4a3623120000000a1a2f3f4c6176889dabbccebbaa927d68523d28130000071a2d3d4a5560666c7175797d808486888a8c8e9090919293939394949493908c87817b74665e4c38230f00000000000000000215253344515f67757d848a8e9194928c83766259483727150000000000000000000b1b28323c494d53585b57606366686b6d6c6861584d4130211100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e19202d3639404445433e37332a1c2a3437444b4d4b4639352c1e0e000000000a1f3347586a7f949fabb0b0ad9f96806b5c4a36210d0000000013283d52687d92a7c1d1d8cec9c6b9b4aca39b938a827a716860564d483c372e201d150a000000000000000000000000000a162b40566b80807c676d6d626e6a6b6c69666c6c61716c6b626c6a6d7f7a667c78697e696c6a646c6c625947341f0b000000000000000000000000000000000000000000000000000012273d52677c92a7bcd1dcc7b29c877257657a8f8b76859aa9947f69543727303d49596278889eb3c0d0e3dcc7b19c87725c5f677b8b9faab49f8c7a645443301c0b00000000000000000b20364b6075898d788298adc6af99846f5847331f0a00000000000000000d21364a5c72879db2b9a8907b665036261401000000000e1e2f404b6073869c9c939d8776614c3d2d1a0500000000111f334658667b8d9fb5c0c8ad98836e58432e190300000f1f2d37444b5057566063676b6f71737577797a7b7c7d7e7e7e7e7e7e7d7b77726c6660564c402f1c0900000000000000000007162633414d5660686f76797c7e7d786e6158483b2b1909000000000000000000000b161e2c35383e4239454b4e5053555857534c473a3023130300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003111e2c353e4a4e55595a58534c473a303a474c55606261574d493c2c1b0b00000004172a3a4f616b808d979b9b978f8173604b3d2d1a070000000010253a4f657a8fa3b5c5d2dddfd6ccc9c1b5b1a89f978f867d756b625a504b3f3632281a1303000000000000000000000a1a28323650626b6b675f58584d59545657535157574b5c57564d57546169645e666361696156554f56574c473b2a1805000000000000000000000000000000000000000000000000000014293e54697e93a9bed3dac5af9a85705a60758a8f7a8196ac99836e5544311d2c3b485a667c91a2b4c8dcdec9b39e8974584d5d667c8c9fb4aa9b8572604a3a2917040000000000000010253a50657a8f8675899eb3baa9927d67523a2a17040000000000000000071a2d3d576c8196acc5ac97826c5443301c0800000006192c3c4c5e6a7f94a4b49f8d7b655746331f0f00000000000417293a4c5e6b8095a2b4c3b29d87725d48321d080000010f192631353b38454b4e5256595c55606264656667686969696969696866625957514b45382f221100000000000000000000000816233038454b52576064676967635b4c473a2b1d0d000000000000000000000000030e192023292d283236393b3e4042423e37332a1c13050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000211212f3c494d5c646b6e6f6d6861584b434759616d7578766f635a49392816030000000c1c324351626b7a818686827a6c605544311f0f00000000000b20354b6073859ba7b5c1c9d2dee0ded2c9c6bab4ada39b928880786e655d534b4538301e160a000000000000000002162838454b575a5e5b554e493d38433f40413e3b4142364642403842434f544f4c514d4f544f42403a414237342a1d0d000000000000000000000000000000000000000000000000000000152b40556a8095aabfd5d8c3ae98836e59566f84937e7d92aa9e8975604b35201d2b3c4d5e6f849aafc5d5e0ccb9a78b76614c4c5e687e93a0b2a3927d685846331f0b00000000000001142637556a7f957f7b90a7b9b49f8a76614c36210c0000000000000000000010253b50657b90a7b8b39e8874604b35200b0000000c2035495a667c8c9fb4a195806a5d4b392917010000000000000c1c2f404b6073849aa5b6b39d88735e48331e090000000009141d2026273136393d414437444b4d4f5051525253545454545453504d483b3c3632281a110300000000000000000000000005131a28323639454b4e5154524e493d332a1c0d000000000000000000000000000000060c0e1418161e212326282b2d2c28221f180c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010202f3f4c5a636f79808485827e76696054586177828a8d8b8478635746321e090000000015253344515c646c70716d655d4b44372614010000000000081c3043546379899ba3b1b5c1c8ccd6dcded7cdc9c1b5b1a79e958b837a716860564d4132281b0a00000000000000091e324556606c6f73706a635b534c473b4038454b453839373435313538353f39363c383b3e3b322b252c2d221f180d00000000000000000000000000000000000000000000000000000000152b40556a8095aabfd5d7c2ad98826d5853687d9283778b9fa8907b65503b2b181e304051667c91a7b8cce0d6c5a5907a6550404e606d8298a5b39e8876614c392816030000000000081d3144556f848e798297adc5ae99836e5746331e0a000000000000000000000b20354b6074899eb3b8a68f7a654f3a25100000000e23384d63788a9eaaa1998373604b3f2f1b0b0000000000000000111d3144556277879ca4a799836e59442e1904000000000001080b11151d2024282b2f27313537393b3b3c3d3e3e3e3f3f3f3e3b37342b26201d150a000000000000000000000000000000000a161e21283236393c3f3d38352c1f180c00000000000000000000000000000000000000000003090b0e1113161817130c0a0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1a2d3e4c5d6578848e95999a98938a7f7260617686979fa99f9a8775614b36210c00000000071626333e4a4f575b5b584f4b3f3126190900000000000001142636495b637985919ba3acb3b8c5c8d1dee0ded2c9c5b8b3aa9f988f867d74675f4b45392818080000000000000b21364b60768285888580797169615956564c5660564d4f4d484b44494e4a484d4c46393e35404337342a1d0d0b050000000000000000000000000000000000000000000000000000000000152a40556a7f95aabfd4d8c3ad98836e584c61768a8a76859aad98836d594834201220354b6074889eb3c8ddd4bfaa947f6a553c424c6176879db2a695806a5746321e0900000000000b20354b6075898774889eb3b9a8917c67523929170300000000000000000000081d3144556d8298adc3ab96816b563d2d1a07000014293f54697e94a8a097837460554431211100000000000000000001152737475962788690928979634e39230e0000000000000000000002090b0e12161a151d202224252627282929292929292826222019110b090200000000000000000000000000000000000003090b161e212427292823211a0f04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021528384a5c657b8999a1aaaeafada99f9482726b8095a4b4bab5a5937e69543e291400000000000816202d3639424646423a372e1d1409000000000000000008182c3d495b63707c868e969ea7b0b4c0c9ccd6ddded5ccc8bbb4aea39b92887d6d605745362614010000000000091e324556606c6f777f898e867e77706c6b616376675f64625960555b63605962615758544b56584c473b2a1909000000000000000000000000000000000000000000000000000000000000142a3f54697f94a9bed4d9c3ae99846e5946586d82927d7c91a59f8a77624c3d2c181d3144556e8398aec3d8dbc5b09b85705a48354658657b90a2b39e8975614b36210f00000000000f24394f64798e888197a7b8b49e8975604b36210b00000000000000000000000115273751667b90a5b7b29d87725c4a36210d00000f24394f647a8c938e8274605645372614030000000000000000000009192a3b495a62747b7d77635b4936210c000000000000000000000000000000010001080b0d0f1011121314141414141413110d0b050000000000000000000000000000000000000000000000000003090b0f1214120e0c0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090b0c0b080100000000000000000000000001080b0d0c0a03000000000000000000000000091d324556647a8a9ea7b3bfc3c4c7bab4a0958072879db2c2cec3b09b85705b39281603000000000002101b22242c31312d25221b1001000000000000000000000f1f2c3d494e5e6671798189929aa2abb3b9c5c9d2dfe0d9cecac2b5b1a69d928275605443301c08000000000002162838454b5759616976808a938a8581807679887d697977667567677872647776616e69606b6e61594737271c13080000000000000000000000000000000000000000000000000000000012283d52677d92a7bcd2dbc6b19b86715c3c4e63798e8675879ca996816c5b49362514263754697e94a9bed3ddc8b4a38d78624d383a4c5e6f849aafa7937e68533d2c1a060000000014293e54697e927d879cb2c5ad98836d5745321e090000000000000000000000000b20354b6073879db2b6a58e79644e39240f00000d22364a5c647a7e796d605645382819090000000000000000000000000d1d2c3c49556066686159493d2c1a0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070a151d2021201c14080000000000000000000008141c2022211e170b04000000000000000000021628384b6074869ca8b9c5d0d9dad7cdbeb49f8c7c8c9fb4cadec9b49f89745745321e0900000000000000070d0f171b1c18100e08000000000000000000000000010f1f2c35404d515c646c757d858e969ea7b0b5c1c9cdd7e2dfd2c9c4b7b3a0988372604b35200b0000000000000a1a2832363b474c58616b777e8a948a7f70859a887e8a857b897d7d8a8079898477837e75808377615544353025180a00000000000000000000000000000000000000000000000000000010253b50657a90a5c6d6dec8b39e89735a484a5b6f84917c7c91a29f8b79635443301c273c51667c91a6bbd1e4d1c1a9947e69543c2f404f647a8fa1b09b85705b4935210c00000003182e43586d838a77889db2b8a7917b665139281603000000000000000000000000081c3043546a7f94a9baaa947f6a553f2a150000071b2d3e4a5c6469645c4b4538281a0a00000000000000000000000000000e1e2c37444b51524c473b2c1f0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070b121a1d1f1d1a1715120f0c0a030000000000000000000000000000010f1a2127313637353026181305000000000000041218263035383633291f180c0000000000000000091e324556697f94a4a6b4bbc8d0c7c3c6c9bbaa9f919faabbcee1cdbaa98b76604b36210b000000000000000000000206060300000000000000000000000000000000010f1a2130393e4a4e56606770798189929ba3adb4bac7ced8e6ded4cbbeb2a1927d68523d2813000000000000000a161e212a343a4a5b657b86867f776a6c819684949c86898a89888885869c89888985858281857360534a4336281a0a00000000000000000000000000000000000000000000000000000e23384d63788da8b9cce0ccb8a78d78624d3d4e63798b8775849aa79a8472604a413024394f64798ea4c7d7e9dbc5b09b85705a4835374b5c6f849aafa38d78634e38230e00000005182b3b5b71869b8c9da6b7b39e8975604b36200b00000000000000000000000000011426364c61778a9fb4af99846f5a442f1a00000010202d3e4a4f534e4a3e32281a0a000000000000000000000000000000000e192731353b3d37342a1d0f01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008131c20272f3334322f2d2a2724211e17140c0a04000000000000000000010f1f2d3638454b4c4b433630231304000000000312222f36434b4d4c4639342a1d0c000000000000000b21364b6075889d9e919faabbbfb3aeb1b5c2bbb4a6b4bbc8d9e9d7c7a18c76614c37210c000000000000000000000000000000000000000000000000000000000000000006121d242d3638454b525b636c757d858e979fa9b4bbc8d8eae7dfcfbfb09b85705b46301b060000000000000002090c1823394e63798a7b70827e69647a8e878298838697828b917c889882889580888975817e726860544538281603000000000000000000000000000000000000000000000000000b20354a6074899eb4c9ded5c5a6917c67513c4a5b6c81957f78899ea2957f6a5f4d4132374c61778ca9bacde1ddc8b4a38d78624d382e3e52677d92a8a9947f69543827150200000b2034485974899ea1b2b7c1ac97816c5544311d080000000000000000000000000000081f3447596d8298adb19b86715c46311c0000000210202d363a3e39362d1e160a00000000000000000000000000000000000009151d202628221f180c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009182530353d4448494745423f3c393633292a211f170b00000000000000000f1f2d3d4a4e56606160544d413022120000000011212f404c54606261574c473b2a1c0c00000000000215283852677c919e8a7c8b9fb4b2a1999ba3b2bfc9bbcaced9e6e1ccb7a18c77624c37220d000000000000000000000000000000000000000000000000000000000000000000000a101b222832363d494e5660687079828a949faabbced9d6dcdec9b49e89745f49341f0a0000000000000000000014293f54697e897571868978656e83947f878c7e8a897f94837b8c8a7c8b897d8b818593877e72605645321e1000000000000000000000000000000000000000000000000000071c30435470859aafc5dad7c1ac97826c573e3d4c6176878c7a7c8d9f9f8d7d675f4f4334475974899fb4c9dee4d1c1a9947e69543a2a364b6176899eaf9a85705645311d0900000d22374d62778ca7b9c8c8b4a38e7a644f37271502000000000000000000000000000004182a3b4f657a8f9fa998836e58432e190000000002101b22242924221b1003000000000000000000000000000000000000000001080b11130c0b0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009192736434a52595d5e5c5a5754524f4b46393f3633291b0f010000000000061a2c3d4a5b636f757674675f4d402f1a0a000008182e3f4c5e667377766e6159473a29170400000000091d3245566f84999580798eaab2a199838699a1b2c1d2dfe2ebf6e1ccb7a28c77624d37220d000000000000000000000000000000000000000000000000000000000000000000000000070a161e212c3638454b525c646d777f8b9fb4cac4c1c6cac9b39e89745e49341f090000000000000000000011273c51667c917d677d92877b6f788a897d92877e9383828a7a7f94837d928480937e7f86918374604b3e2e1b0700000000000000000000000000000000000000000000000000132536566b8096abc7d7ddc8b29d88735c4a364758657b8c87777f949e9f8c7d69614d483b5d72879cb2c7dcefdac5b09b85705847333246576e8398ad9f8a75604b36200b00000c22374c61778caabbcec2b09b85705c4a361909000000000000000000000000000000000c23374b5d6d8191948b7a644f3a250f000000000000070d0f140f0d07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001152737445460676f7274726f6c6a676461575a544c463a2c1f0f00000000000c2135495b6379848a8c887d675e4c38271502001325364b5d667c878d8a8377615846331f0b000000000b20364b6075899f8a768399aeae99836e748299a3b5c9d9ebfeffe2cdb7a28d78624d38230d000000000000000000000000000000000000000000000000000000000000000000000000000002090f1a212832363e4a4f5f677c91aabbbdb0acb1b6beaf99846f5a442f1a05000000000000000000081c2e3f4b60758889786c819790847b809580818877817f7686898486907b80867686877e797c89826d5c4a36220d0000000000000000000000000000000000000000000000000011263b50667b90a9bacddfcbb7a68e79644e383a4b5d6a7f95857580949d9f8d7f6e6259505972879db2c7dcf2dfcab59f8b77614c37283954697e93a9a98f7a644f3a250f00000b20354a60758a9fb4c7b6a4917c67523e2d1b0000000000000000000000000000000000081c2e3f4a60727c7f79645c4b37220d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081d31445560727d8488898784827f7c79767370696158493d2c1a0a000000011426374e63798a999fa69d907c665645311d09071c304354657b8c9da69f988676614c3928160300000010253a50657a8f9883778b9fb4a38e79636075859babbccfe3f7f8e2cdb8a38d78634e38230e0000000000000000000000000000000000000000000000000000000000000000000000000000000000060c1a2836434b616a7d8c9fb4bcb59f969ca4b1a0907b66503b2611000000000000000000000e23374b5d65777e93867675858b879089988b7e7e7b7a6a61767e787586877679887b848275677b8b79644f3a240f000000000000000000000000000000000000000000000000000b21364b60768a9fb4c9dfd4c4aa95806b5645313f50616d819784757f949e9f9483776c6563778b9fb4cadff2e3cfbcab917c67513c273a4f657a8faba8927d68533d28130000071c30435472879db2baa99c8673604b352010000000000000000000000000000000000000111c30435460676a635b4b3e2e1b0800000000000000000000000000000000000000000000070c0e14150f0d07000000000000000000000000000000000000000000000000000000000000000000040a0c11141514110c0a04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011426374b60738392999d9e9c9a9794918e8b88857f76635b49382816030000081d3144556e8398a8b4b7b29d8774604b36200b0b20354a6073869caab7b4a497816c5746321e0900000014293f54697e94917b7e93abb09b85705b56647a8c9fb4cadff4ffe3ceb8a38e79634e39240e00000000000000000000000000000000000000000000000000000000000000000000000000000000000e1c2a384554606c7f8d9faabbab9f9381869ca297826d5e4c38230f0000000000000000000010253a50657b88738195877b7a8b747b7f828b9486868578706b686263798a81778986726d615d6d827c67523c271200000000000000000000000000000000000000000000000000091e3245576f8499afc8d8ddc8b39d8875604b3633434b60738397857780959da19989817b788298abbccfdadde0dac9ac97816c573929364b61768a9fab96806b56412b16010000132536576d8297a5a99f8b7a645443301c0800000000000000000000000000000000000000132536434a51554e493d2e2010000000000000000000000000000000000000000000040f1a2124292a24211a0f010000000000000000000000000000000000000000000000000000000000070c171f2126292a2926211f170c0900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081d3144556a7f94a1aeb2b3b1afaca9a7a4a69d9a948779635645321e0900000b20354b6075899eb4c6cab7a5927d68523d28130f24394f64798ea4b5c8c2b49f8a76614b36210c000003182d42586d82978b76849aafaa957f6a554a5c6e8399aec9daecffe3ceb9a48e79644f39240f00000000000000000000000000000000000000000000000000000000000000000000000000000002101e2b3a4756607281949fabbaaa9f8d7e76869c9a8474604b402f1c090000000000000000000c1d2a43586e83927d73808b908c806b666a6d7d92807983868581786860687e826d7b816c544b4f647974604b362112040000000000000000000000000000000000000000000000000316283953687d92aabbcee0cbb7a6927d6752403031445560738194878684879da89e96908e98a0b2c9c8c5c8cbd5c7b19c877257463332465773899ead98826d58432d180300000d22384d62788792948b7d675c4a362614010000000000000000000000000000000000000008182530353c3f39362c1f100200000000000000000000000000000000000000000c171f2d36393e3f39362d201305000000000000000000000000030000000000000000000000000008131c202a33373c3e403e3c373329231c120600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b20354b6074889eb3bfc7c9c7c4c1bfbcc4b8b3afa59d8775604b36210b00000d22374d62778ca8b9cdd4c3ae99846f593a2a1813283d53687d92a8c2d2cdbaa9907a65503b25100000051b30455a70859a8674899eb3a5907b65503e51667c91abbccfe3f8e4cfb9a48f7a644f3a250f000000000000000000040a0c0f0f0b09030000000000000000000000000000000000000000000311202d3c4858617483969fb5b9a99f8c7d77869c98847561564532221100000000000000000004182a3b4752677d9288766b797f7d737b72605f697e7b807c7d838b8b7e6874827560656c6251464b5c646056483b2f2212020000000000000000000000000000000000000000000000000c21374c61768a9fb4c9dfd5c4b09b85705f4d3828374455606d7f8c958076899eb3aca5a3adb2bec0b4b0b3b8c4cab59f8b76614c3628395d72879dae99836e59442e190400000b2035485a62757d7f79675f4d3e2d180800000000000000000000000000000000000000000008131c20272a23211a0f0100000000000000000000000000000000000000000e1c2a333d4a4e53544e4a3e3023130000000000000000040a0c1519160d0b05000000000000000211182530353a474c51545553514c473a382f20190e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f253a4f647a8fa6b8cbdddedcd9d7d4d1d5cbc8c3b6a5927d67523d281200000e24394e63798ea3c6d6ddc8b39d88735947341f152a40556a7f95aabfd4d7c7a8927d68533d28130000071c32475c71879883788da7b9a88c77624c374c61768b9fb5cadff4e4cfbaa58f7a65503a251000000000000000090c171f212424211e160a010000000000000000000000000000000000000513222f3e4a5a62768499a1b1b7a79e8b7d79879c968274615746382815030000000000000000000b1f344759616a708496816c636a697f8a806b61757a676a78746e7884927d7e927d676161584c5761686b6962594c402f20100000000000000000000000000000000000000000000000000a1f3347586e8398aec2d3ddc9b5a3917c675645322737444b616a7a8795869ca8b9c8bab8c2c6b9b3a29b9da6b6c3bcab8d78634d3831465c71869bae99846f59442f1a04000005192b3c485761676a635b4d41302010000000000000000000000000000000000000000000000000070b12150e0c060000000000000000000000000000000000000000000e1e2b3a474c5b63696a645c4d413019090000000000000c171f212a2e2b2220180d00000000000a161e2e36434a51586166696a69666158504c40352c1e1204000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013283e53687d93a8c4d5e7eee3dcd9d4d7dcdfddd3c3ab96816c56412c1701000f243a4f64798fa4b9cedfcbb7a68c77614c3722152b40556a8095aabfd5d4bea9947f69543f2a140000081d32485d728795807a8fa4b49e8974594734465872879db2c7dcf2e5d0baa5907b65503b2610000000000000121d242a333739393632281d14090000000000000000000000000000000007142331404c5c6478869ba2b2b5a59d897b7a899d94817260564639281a0a000000000000000000000c22374c6177807678898c7c665b738888847f6d82897c7b8a806a7a80848b7d8d89777677665e61757d807e77665e4c3e2d1b0700000000000000000000000000000000000000000000000417293a50657b90a4b6c9ded1c1b29d8775604b3f2e2631434f5c6475808a979faaaeb2b3b2aea89e9385889da5b3b59f8b77614c3731465b70869bad98836e58432e19030000000e1e2b39464b52554e493d302313020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1b2b3c4858616e797e7f79675f4d37271501000000000c1c2a333740434037342b1d0e0000000e1a28323f4b5460676f767b7e7f7e7c766f665e4d493c2f22120400000000000000000000000000000000000000000000000000000000000000000000000000000000000000152a3f546a7f94a9bfd4e9ded0c7c4bfc2c7cacfcabdaa95806b55402b1600000f243a4f64798fa4b9cee7d4c4a48e79644f3924142a3f54697f94a9bed4d5bfaa95806a55402b150000081e33485d7388947e7c91a6b29c87725d3b2a3a5b71869bb0c6dbf0e5d0bba6907b66513b26110000000008131c30393a474c4f4f4b453831261909000000000000000000000000000007152532414e5e667a889ca4b4b2a39b87797c8a9e8d7f6c60544538281b0b00000000000000000000000d22384d62778d88807f8a8979666c81947f847f8d84868689857e8688838985829885898a7c667285808088897c665c4a36220b0000000000000000000000000000000000000000000000000c23374b5d71869cb1c3d3dfcab7a5957f6a5d4b3b2a1d323e4b57616b78828b93999d9e9c9993897e74788799a1a39a846f584733293a5d72889dac97816c57422c1702000000000e1b2932363d3f38352c1f130500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003172939485a6276838e93948d7d675544311d080000000c1c2a3a474c5558554c483b2c1f0e010f1e2b38454b5d65727c848b91939593918a847b70625a4c402f221200000000000000000000000000000000000000000000000000000000000000000000000000000000000000162b40556b8095aac0d5e3d0c0b3afaaadb2b5bcb6b29f8f7a654f3a251000000f24394f64798ea4b9cee3d0bba5907b66503b2614293e53697e93a8bed3d6c1ab96816c56412c170100091e33495e7388937e7c91a6b09b86715b4631455a6f849aafc4d9efe6d1bba6917c66513c271100000008182530404d515861646460564b443726140100000000000000000000000005152533434f5f687c8a9da6b6b5a09885777d8c9e8c7d69614b4336281a0b0000000000000000000000000b2034485a6a7f868a8e9196887c7979898978858a8b7d879a84848a88808a9580889883858a787a8f7c7d77838a7a644f392917030000000000000000000000000000000000000000000000081c2f3f52677d92a4b6caded4c3b49f8c7b6559473828202e39464b5a626d777e84878887847e7668606377848c8c8578624d3a2a33475874899fa9947f69543f2a140000000000000b161e21272a23211a0f01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1e33465762788798a0a8ab9d8774604b35200b000004182a3a4758616a6e6b6259493d2c1a101f2d3c4956606b7b86919a9faba9aaa8aa9f9a908578665e4c402f1f0e000000000000000000000000000000000000000000000000000000000000000000000000000000000002172c41576c8196acc1d6dcc7b3a29a94989c9faba59c93816c5d4b37220e00000f24394e64798ea3b9cee3d2bca7927d67523d2813283d52687d92a7bdd2d7c2ad97826d58422d180300081d33485d7288937e7c91a6b09a85705b453044596e8399aec3d8eee6d1bca7917c67523c2712000000132536434a5e6670767979756b605544311d12000000000000000000000001132333435061697d8c9ea8b7ab9f9582757f8d9d8a7c675f4f433026180a0000000000000000000000000005192b3c50616a7175797c808d9086868999877e849a87798795808497827e93897f94897e86837e939092827484846f5746331e0a0000000000000000000000000000000000000000000000001120354b6073879cb2c0d1e2cebbaa9d887762564538281b28323c484d5962696f7273726f6961574a59626f767771625a483421374c61768ca9ab907b66503b261100000000000000030a0c12150e0c0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1b2f404b6175869ca5b2bfb7a58d78624d38230d00000a1f33475861767f838077635b493521212e3d4a5a6274818c9ca4afb4bcc9bfc8bbb4afa29a897c665e4c3d2c18080000000000000000000000000000000000000000000000000000000000000000000000000000000003182d42586d8297adc2d7d9c4af9a847f82878a8c8b877e6c63523f2e1b0800000e23394e63788ea3b8cde3d4bea9947f69543f2a14273c52677c91a7bcd1d8c3ae98836e59432e190400061b31465b708695807a90a5b09b86715b463144596f8499aec4d9eee7d2bca7927d67523d28120000071c304354606c7c858b8e8e898073604b402f1d09000000000000000000000f1f304150616a7f929faab7a89e8d7f7582959c887a655e4d41321c14080000000000000000000000000000000d1d33435055566063666b7e8c86777383917c7684978278878c7d84937e7f9486818a847f947f94868385707a8c76614b36210c000000000000000000000000000000000000000000000000081d314455677c91a2b4c7d7d8c8b7a69a8474605645382a1d1e2b343b484d54595d5e5d59534c463b484c586162594d483c2b253b50657a90a59f8b77624c37220d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000417293a4c5e6d8297a4b6c3cfc3a48f79644f3a240f000417293a4c6176879598958879634e3e2d2f3f4b5b637886969fabb5c2cacfd9d4d8cecac0b4a89e8b7c665b493626140100000000000000000000000000000000000000000000000000000000000000000000000000000004192e44596e8399aec3d8d1bca7917c6a6d7275777672686052453421100000000e23384e63788da3b8cde2d6c0ab96816b56412c16263b51667b90a6bbd0dac4af9a856f5a45301a050004192e44596e839782788daab19c87725c3a2a455a6f849aafc4d9efe7d2bda8927d68533d2813000417293a4a607281919b9faba89e95826d5e4c38240f00000000000000000008182c3d4d5f6a7f949db4b4a59d8a7c7785989b8778645c4c403023150100000000000000000000000000000000001525333c38454b4e5160687b89887a77878a7a7584937e78878a7b858d798195808489838a8183908c7e69748978634d38230e000000000000000000000000000000000000000000000000011426374d5f70849aa9bacde1d4c4b4a29a83746056483b2d1c19202b34373e44484947443e36332b343a474c4d483b342b1d2f3f556a8095aa9b86715947341f0b00000000000000000000000000000001020203030404050506060707080809090001080b0b0c0c0d0d0e0e0f0f101010111112110e0c06000000000000000000000000081f334658667c919fb1c2d3cab6a58d78624d38230d000a1f3347586d8297a5ada69a846f5c4a363f4b5d6579889ca4b4bcc9d2dfdedcd7dbdddfd1c6b9a99f8a79635443301c08000000000000000000000000000000000000000000000000000000000000000000000000000000051a2f455a6f849aafc4d9cfbaa5907a65585660616158534e42342717030000000d23384d62788da2b7cde2d8c3ae98836e59382815253a50657a8fa5bacfdbc6b09b86715b46311c060002172c41576c819685768a9fb49f8974594734375b70859ab0c5daefe8d3bea8937e69533e2914000a1f3346586a7f959fb0b5bcb9b4a0917c66513c2611000000000000000000132536495b677d919daeb4a39b877a7a889b9a8577625a4a3e2f2113050000000000000000000000000000000000000715202828323639414e5d6578848b7f7989887875848c7c78878878817373857d77877786826e7b7c6960718674604b36200b00000000000000000000000000000000000000000000000000091930404e63798b9fb4bfd0e1d1c0b3a299837462594a3e302618182022292f3233322f29211e182029333737342b201926374c5d71869caa95806b553b2a1805000000000000000000040a0c1113161717181819191a1a1a1b1b1c1c1d1d1e1e1f141c20212121222223232424252526262727262321190e0800000000000000000008182e3e4c6176889db3bdced5c4b29d87725a4935200b000c21374c61768b9fb4c3b4a28e79644e404c5d657b899da6b6c2cfd9dfd3cac6c2c6c9d2dfd6c7baa89b8573604b35200c000000000000000000000000000000000000000000000000000000000000000000000000000000061b30465b70859bb0c5dacfb9a48f7a644f454b4c4c463a3a31241709000000000d22374d62778ca2b7cce1dbc6b19b86715645321d24394f64798ea4b9cedcc7b29c87725d47321d00000013293e53687e938974869cb1a88c77614c37445572889db2c7ddf2e9d3bea9947e69543f2914000c21364c61768a9fb4bdcacfcdbead98826d58432e180000000000000000071c30435463798a9fb4b0ab9b85777d8b9d9883756159493c2d2011030000000000000000000000000000000000000000030d0a151d2024313f4c5a6273808c857f8986777d89897a7a8985797a7e777262756175746066665e617779645544311d080000000000000000000000000000000000000000000000000000122135495b697f94a1b3c3d4ded0c0b3a1998577645c4b43362c1f170d141a1d1e1d1a140c0a050c171f21222018141d314455657b90a4a68f7a654f3a25100000000000000000060c181f2226292b2c2c2d2d2e2e2f2f3030313132323333343426303536363737383839393a3a3b3b3b3c3c3b38352c231c1103000000000000011426364b5c6c8197a6b7cbe0cbb8a6937e69543c2b19060010253a50657a8faabbc9c0ab96806b554d5e667b8a9ea7b7c4b7c6c9cbc2b6b1adb1b5c1cedcd7c6b4a3917c66513a2a17040000000000000000000000000000000000000000000000000000000000000000000000000000071c32475c71879cb1c6dcceb8a38e79634e393637363329261f140600000000000c22374c61778ca1b6cce1dfc9b49f8a75604b362023394e63788ea3b8cdddc8b39d88735e4825130000000e23394e63798e8d788297aca5907b65503b4b60758a9fb4cadff4e9d4bfa9947f6a543f2a150011273c51667c91a9bacddfe3dac5b09a85705b45301b00000000000000000b20354a6072859aa9b09e958c7e80929f9682736157473b2c1e100200000000000000000000000000000000000000000000000002090b13212f3c4855606a798592889c867779868f8382898d837f696055605660605550514d5961645c4a372715020000000000000000000000000000000000000000000000000000061a2c3d4b6072849aa5b7c5d6ded0bfb3a39b887a696054493d332a1e160a050008040000000000040a0c0d0c181f32414b6073859bb19e8874604b35200b000000000000000e1a212a33373b3e404142424343444444454546464747484849494a434b4b4c4c4c4d4d4e4e4f4f5050515151514d493c382f2112040000000000081c304354647a8c9fb4c4d4d5c5b39d8875604b36210e000011263b50667b90a5a5b4bab39d8874605f677c8b9ea8b9b4b0a1b1b5b7b2a49c979ba3b1bdcee2d1c1b09a85705847331f0a0000000000000000000000000000000000000000000000000000000000000000000000000000081d33485d72889db2c7ddcdb7a28d78624d382322211f170b0b020000000000000c21374c61768ca1b6cbe1e2cebbaa8e79644f392422384d62778da2b7ccdec9b49e89745443301c0700000b20354a607488937e7c91aaa9947f69543a4d63788dabbccfe3f7ead4bfaa957f6a55402a150013293e53687e93a8c5d5e8e9d8c7af99846f5a442f1a000000000000000011273c51667c91a2b4ab9580788d959f938072605546392a1d0e000000000000000000000000000000000000000000000000000000000003111d2b37444b5b63707d88939a85707786877279887b69614a444b454b4b44373c3a474c4e4a3e2d1909000000000000000000000000000000000000000000000000000000000f1c3043546176879da7b8c6d6ddd0c1b4a69d8b7f73635b4c473a322820190e0b080100010100040a0c161e2a33434f5f6b8096a3a9957f6a5544311d08000000000004121f2c353a474c515355565757585859595a5a5b5b5c5c5d5d5e5e5e5f546060616162626363646465656566666766635b504b3f30221200000000011426374b6073869babbccfe0cbb8a6947f695645321e0900000f24394f64798e9c909fa9b7a6937f6f707d8c9fa9b9b4a29a8c9ca4a69d92868286979fb1c4d4dfcab59f8b76614c37210c0000000000000000000000000000000000000000000000000000000000000000000000000000031628395e74899eb3c9deccb7a18c77624c37220d0c0a040000000000000000000c21364b61768ba0b6cbe0ead8c8a8937d68533e2822374c61778ca1b6ccdfcab59f8a75604a35200b0000071c3043546e839984768a9fae99846f584752677d92a7c9d9ebfeead5c0ab95806b56402b160011263c51667c91a7b8ccd6d7cdbaa995806b55402b160000000000000002182d42576d8297acc0af9983859b9d8c7e6b60544437291b0c00000000000000000000000000000000000000000000000000000000000000000d1926313d4a4e5f67757e88806b6277806b637773604b4331353236353127272a343739362d201000000000000000000000000000000000000000000000000000000000000114263647586379899ea8b9c6d5dfd1c4b7a99f9485796b61584b4539352b24201d1518161618171f2129323a474c61697d929eb49f8a77614c37271501000000000012222f3d494e586166686b6c6c6d6d6e6e6f6f6f7070717172727373747475757676767777787879797a7a7b7b7c7c7b7871655d4d40301808000000081d314455677d92a3b5c9d9d4c4b39e8875604b3828160300000b20364b60758a867b8b9fb4b49f8d8485929faab7aa9f958477869c99887d736d738197a6b7cbdfcfbcab917b66513c26110000000000000000000000000000000000000000000000000000000000000000000000000000091e324557758a9fb4c9cdd7c7a08b76614b36210c0000000000000000000000000b20364b60758ba0b5daececd7c2ad97826d583e2d21364c61768ba1b6cbe3cfbcab8b76604b36210b00000013253651677c918b7c8a9fb49f8a76614c5a6e8399aec3d8eeffebd6c0ab96816b56412c16000c21364b6175889eb3b9c6c6bab49f8b78624d38230d0000000000000003182d43586d8298adb9b3a1999b97887b69604a433627190b0000000000000000000000000000000000000000000000000000000000000000000009141d2d36414d56606975726059626b625962605544311d201e21201d1511181f2224221b100200000000000000000000000000000000000000000000000000000000000008182a3a4a5b657b8a9ea8b8c4d2e3d4c7bab4a39b8b80766a60574d483c393531272d2b2c2d2a333739464b58616d7f8c9fb4a997826d594734190900000000000d1d2f404c5b636e777b7e80818182828383848485858686878788888989898a8a8b8b8c8c8d8d8e8e8f8f9090909191908d867b665e4d3626140100000b20354b6073879db2c1d2dfcbb7a6947f695745321a0a000000091d324556708589778095a1b4ab9f999ba3b4b2a69d8b7f7f818d9583766760546175879db2c1d2d7c7a8937d68533e281300000000000000000000000000000000000000000000000000000000000000000000000000000b21364b60768baaadb4bac6baa98a75604b35200b0000000000000000000000000b20354b60758aabbccfe3f2ddc8b29d88735c4a3621364b60768ba0b5cbecdab5a08b76604b36210b0000000b20354b6074889d898399a6a9947f6a5762788b9fb4c9dff4fcebd6c1ac96816c57412c1700091e324657677d929ea8acaca89f937e695a4935200c000000000000000011263c51667c919ea7a59d978c8176655d4f4230251809000000000000000000000000000000000000000000000000000000000000000000000000010f1a213138454b55606054484c5651484d4b443726140b090b0b080100040a0c0f0d070000000000000000000000000000000000000000000000000000000000000000000c1c2d3d4b5d657b8a9ea6b5c1cfdad7cdc1b4a99f96897f756b625a544e4b4437424141423a474c5157616a7782949faab49f8a78634d3b2a18000000000005182a3b4c5e6679838b90939596979798989999999a9a9b9b9c9c9d9d9e9e9f9faba0a1a1a1a2a2a3a3a4a4a5a5a6a6a6a6a39b8c7c665443301c080005182b3b52677c91a5b6cadfd1c1b29d8875614b392816000000000215283853687d92837583969fabb1afb0b2ada098887a7886978d7f7261584a4657687d93a3b5c4cdbaa9917c67513c271200000000000000000000000000000000000000000000000000000000000000000000000000000d22374c62778ca0989fa8bab49f89745443301c08000000000000000000000000081c304354758a9fb5cadff4dfcbb7a68e79644f3929364b60768ba0b5cbe0cbb5a08b76604b36210b000000081d3144556b80958773889db39e8875626c8197aabbced8dfeaecd7c1ac97826c57422d1700031628394d5f677d89939797938a7e69614f3c2c190600000000000000000f24384c5e697e898d8c8781796c61584b3f321c130800000000000000000000000000000000000000000000000000000000000000000000000000000007131a283237444b4a433637413d3437353126190900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1f2e3f4b5d657a889ba3b5bcc9d4e1d1c7bab4a79e94898078706a6360555957565658595861666e767f8998a0b4b3a1947f6a5a49351d0c00000000000b1f344859667c8a999faba8aaabacacadadaeaeafafb0b0b1b1b2b2b3b3b3b4b4bcb5b6b6b7b7b8b8b9b9babababbbbbcc1b5aa9d8873604b35200b000b2034485970859aafc3d3d7c7b4a3927d675746321b0a00000000000c21364b617588968074808c979c9e9f9c988f83777b899b897b6a6054473a394b6073859ba6b4bab49f8a77624c37220d00000000000000000000000000000000000000000000000000000000000000000000000000000e23384d63788d98838a9fb4b39e89735e492614010000000000000000000000000114264a5f758a9fb4cadff4e7d4c4ab96816c574632364b61768ba0b6cbe2cdbaa98b75604b36200b000000011527374d62788a96818a9eb4a69781777d8c9fb4c8c0c3ccdaead7c2ad97826d58422d1800000b1b30414d5f67777e81827e7768604f42321e0e000000000000000000091d2f404f6069747776726c635b4c473a2e2114000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a161e263135353025222b292022201d14090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110212e3f4b5c647885969fabb7c3cdd7d7cdc5b9b3a79e968b857f7975716e6d6b6b6d6e72777b838a949ea8b2b4a3998373604b3c2c190000000000000d22374c62778a9fa9b4bcc9c0c1c1c2c2c3c3c4c4c4c5c5c6c6c7c7c8c8c9c9cacfd9cbcbcccccdcdcececfcfd0d0d1d1d2c8b7a68d78634e38230e000d22374c62778b9fb5cadfcdbaa99b8572604a392816000000000000091e324657677c91968377798186898987837a76818c968578655e4a43362a3144556379889aa2a99f95806b5947341f0b00000000000000000000000000000000000000000000000000000000000000000000000000000e24394e63798e8b76859bb0b29d88725d48331d00000000000000000000000000001f354a5f748a9fb4c9dfe7f2dec8b39e8976614b3b374c61778ca1b6ccdfc9b49f8a745645311d090000000009203448596b8095969ea8b9b19f978c929faab5b0aaafbcccdfd8c3ad98836e58432e19000000132330414d5861686c6c6962594e423224140000000000000000000000122232424f5560626158574e4a3d332a1c110300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000309141d20201c130d16140b0d0b080100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000211212e3e4a5a6274818d9da5b4bac7cdd7d6ccc5b8b3ab9f9b948e8a86838280818284878c91989fa8b3b9b4a29a8575615544311e0e00000000000012283d52677d92a8bac7cfd9d5d6d6d7d7d8d8d9d9dadadbdbdcdcdddddedededfe3ebe0ece3dfdfdededddddcdbdbdadad8cdbaa98e79634e39240e0011263b50667b90abbccfcfbeb49f8a79635443301b0b000000000000031628394d5f6b8095998a817975747474788088968d8174625a4c403025182737495b6379858c8e8a8072604a3b2a180500000000000000000000000000000000000000000000000000000000000000000000000000000f24394f64798e8a75879cb1b19c87715c47321c070000000000000000000000000a1f34495f74899eb4c8cbd4e2e0ccb8a7947f695948364e63788ea3b8cdddc8b39e88735e382715020000000005192b3b4b6075869ca8b9c6bdb1aca2a7b4b5a39b959eafc3d8d8c3ae98836e59432e19000000051323303a474c535757544c483b3124140600000000000000000000000414243237444b4d4c473a39362d1f180c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080b0b070000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000311202d3c4856606c7b87959fa9b4bac7cbd4d6ccc9bcb4b0a9a99f9b9897969697999da5a6adb4bab4aa9f9584756157463726140000000000000013283d52687d92aabbcbd5d5d5d5d5d4d4d4d3d3d2d2d1d1d0d0d0cfcfcececdcdcccccbdacfcac9c9c8c8c7c7c6c6c5c4c3bcb49f8a76604b36210b0012273c52677c91a7c2cdbeb2a0937e695b4936251300000000000000000b1b304151626b7f8c9a968f8987878a8e9593877b6c6055483c2f1c1309192c3d495b63707779766b605443301d0d0000000000000000000000000000000000000000000000000000000000000000000000000000000f253a4f647a8f8974889db2b09b86715b46311c06000000000000000000000000091e34495e73899eb3b2b7c4d4cec5c5b39e897762544350667b90a5bbd0dcc7b19c87725c47321d0000000000000d1e324557647a8a9fa9b8c5c5c2b7c3b6a69b858095aac0d5d9c3ae99846e59442f190000000005131c2a33373e42423e37342b1d1406000000000000000000000000000614192631353837332a24211a0f040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002101d2b38454b5d6575808a969fa9b2b7c4c9ccd6cfcac5c7bab4b1aeacababadaeb2b6c3c1b5b0a29a8c807361574639291909000000000000000d23384d62788b9fb3b8c4c0c0c0c0bfbfbebebdbdbdbcbcbbbbbabab9b9b9b8b8b7b7b6b6bcb5b4b4b3b3b2b1b1b0b0afaeab9e95806b5745321e090010253a4f657a8fa4b4bab4a0988272604a3d2c18080000000000000000001223334451616a7a858e94979897948f877e74655d4b44372b1e1100000e1f2c3d494e59626461584a433625130000000000000000000000000000000000000000000000000000000000000000000000000000000010253b50657a908874899eb3b09a85705b45301b06000000000000000000000000091e33485e73889d9f9da6b7cbbdb1acb4a7998372604b556a7f94aabfd4d9c4ae99846f59442f1a040000000000031628394a5c667c8b9ea7b4b9c5b9b3a59c87777e93a8bdd2d9c4af99846f5a442f1a0000000000000c181f22292c2d292220180d000000000000000000000000000000000009141d2022211f170e0c0700000000000000000000000000000000000000000000000000000000000000000000060c0e0c070d0f0f0d0e0c0c0f0b0b100d0c0e0c0e0c0e0e0e0d0c0a0c0e0f0d0b0f0c0d0f0e0c060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1a28323f4c56606a77818a959da6adb4b9c6c6caced7cdc9c6c3c2c0c0c2c3c7bab4ada39b90847a6a60554639291b0b00000000000000000c2035495a697f919ea6a9aaababaaaaa9a9a9a8a8a7a7a6a6a6a5a5a4a4a3a3a2a2a1a1a0ab9f9f9e9e9d9d9c9c9b9b9a98968e8073604b39281603000b20354b6074869aa2a99f958273605443301f0f000000000000000000000516263343505d6570797e8283827f7a736960564b3f3127190e000000000f1f2c353b484d4f4c463a302518080000000000000000000000000000000000000000000000000000000000000000000000000000000011263b50667b9087748a9fb4af99846f5a442f1a05000000000000000000000000081d33485d72889d8d889db2c8b19f979faaa196806c605b70859ab0c5dad6c1ab96816c56412c17010000000000000a1b2d3e4c5e667b89969ea8a5a79e968778687d92a7bdd2dac4af9a856f5a45301a00000000000000040a0c131717140d0b050000000000000000000000000000000000000001080b0d0c0a040000000000000000000000000000000000000000000000000000000000000000000000000e192023201b222424212320212521202522212321232123232322211e21232422202521222423211a0f0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a161e2f38454b59626c777f8890989ea8abb1b4bbc8bfc0c1c1c0bfc6b9b4aea99f9890857b6f645c4b4437291b0b00000000000000000006192c3c4f61697d889094959696959594949393929292919190908f8f8f8e8e8d8d8c8c8b8b8a8a8989888887868685858381796b605544311b0a0000081d3144556278848d8f8a8072605544362513010000000000000000000000081625333f4b4f5b63696c6e6d6a6560544b45382e1d15090000000000010f1a212b3437393633291c1308000000000000000000000000000000000000000000000000000000000000000000000000000000000011263c51667b9187758a9fb5ae99836e59442e1904000000000000000000000000081d32475d72879b85778ca1b7ac97828c9fb49e96817468798c9fb5cadfd3c2a7927d68523d2813000000000000000010202f404c5d657781898f908e89807563677c92a7bcd1dac5af9a85705a45301b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1e2c3538352d363939363835363a36353a37353835383639393837363235383936363a36373a39352c1f0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002111a28323b484d59626a747b828990969c9faaa8aaabacacaba9a7a89e99938a837b73655d4f4a3e3127190b00000000000000000000000e1e32434f5f67747b7f808080807f7f7f7e7e7d7d7c7c7b7b7b7a7a797978787777767675757474737372727171706f6e6b645c4b4437261400000001152737485a6270787a766b60544437271808000000000000000000000000000715212e373d4a4e54575957544f4a433632281a11020000000000000000060d18202224211f170b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000012273c51677c9186758aabbcad98836d58432e1803000000000000000000000000071c32475c71879984778da2b7a7927d8196a7b09f97867d859babbccfdecab6a48d78624d38220d00000000000000000212222f3f4c59616c75797b79756b6157667c91a6bbd1dac5b09b85705b46301b00000000000000000000000000000000000000000000000000000000000000000000050b0d0b09030000000000000000000000000000000000000000000000000000000000000000000000000006192c3c494d493e4a4f4e4a4d494b4f4b4a4f4d494e494d494e4e4d4d4b46494e4f4a4b4f4c4b4f4e493d2c1c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a161e2b343b474c5560666d757b81868a8f92949697979694928e89847e766e6560544c3f362d1d150900000000000000000000000000152532414d5660666a6b6b6b6b6a6a696968686867676666656564646463636262616160555f5f5e5e5d5c5c5b5b5a59564e4a3e312619090000000009192b3c484d5a626461574b433627190900000000000000000000000000000002101b222d36393f4243423f3a3530251d150a000000000000000000000000050b0d0f0c0a04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011273c51667c9186758ba0b5ac97826d57422d1802000000000000000000000000071c31475c71869883798ea3b8a7927d76899eb3b1a49c939ba3b4c9dad7c6b19c87725a4835200b0000000000000000000412212f3b474c556064666460554b51667b91a6bbd0dbc5b09b86705b46311b00000000000000000000000000000000000000000000000000000000000000000a0d181f22211e160a0600000000000000000000000000000000000000000000000000000000000000000000000c2035495a635a4d5c64645c635a6164606065625b635b635b6363636261575b63645c6064615c64635b493a29170400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d18202a3437444b515660656b7176797d7f808282817f7c79756f686158504a43362f221b100100000000000000000000000000000715233038454b515455565655555454545353525251515150504f4f4e4e4d4d4c4c4b4b444a494948484747464645434139362d1d14090000000000000e1e2b353c494d4f4b463930261809000000000000000000000000000000000000080f1a2124292d2e2d2a25201c1308020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011273c51667c9186758ba0b5ac97816c57422c1702000000000000000000000000061c31465b718697827a8fa4b9a7927d687d92a1b3b5b1a8b0b4c1d1e1cdb9a8947e69543c2b19050000000000000000000003111d2a3437444b4f504f4b443750667b90a5bbd0dbc6b19b86715c46311c00000000000000000000000000000000000000000000000000000000000004121d242a3437363228211a0f010000000000000000000000000000000000000000000000000000000000000000000e23384d6378635f677979647863757a76757a78637863786579787877756165797968757a76697a79635847331f0a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050d181f27313538454b5056566064686a6b6c6c6b6a67636055534c473a353025181107000000000000000000000000000000000005131a2731363b3f40414140403f3f3e3e3d3d3d3c3c3b3b3a3a3a393938383737363631273434333332313130302e2c24211a0f0100000000000000000e19202b35383a3633291c1408000000000000000000000000000000000000000000070c0e1417191815100b070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011263c51667b9186758aaabbab96816c56412c1701000000000000000000000000061b30465b708596817b90a5baa7927d676f8399a4b6c3bdc5c8d1decebfb49e8a76614c36210e000000000000000000000000000c181f2731363a3b3936313b50657b90a5bad0dbc6b19c86715c47311c000000000000000000000000000000000000000000000000000000000004122230393b474c4b4538352c1f10020000000000000000000000000000000000000000000000000000000000000003182d42586d826d677d807f78826d7f7d81807c8278836e827b817e837f7a657a827e7d7d7d847e7c8076614c37210c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000509151d202832363b38454b4f53555657575654524e4b4437373329201c13080000000000000000000000000000000000000000000a151d20262a2b2b2b2b2a2a2a29292828272726262625252424232322222121201d151f1e1e1d1d1c1c1b1a19160f0d070000000000000000000000050e19202325211e170b010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011263c51667b9187758a9fb4ab96816b56412c1601000000000000000000000000051b30455a708596807b90a5bba7927d686176869ca5b3bfc9cdcdc9bdb1a1947f695846331f0a00000000000000000000000000000409151d2024262420253a50657a8fa5bacfdcc6b19c87715c47321c0000000000000000000000000000000000000000000000000000000000122230404d51596260564e493d2e20110300000000000000000000000000000000000000000000000000000000000004192f44596e847f7c8082837d826d7e8178826d7d7c846f827e7975837f7a697e7a72827c817a8281837c67523d27120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080b161e21262832363a3d3f414242413f3d39353127211f170c0700000000000000000000000000000000000000000000000002090b111516161616151514141313131212111110100f0f0f0e0e0d0d0c0c0b0802000909080707060605040100000000000000000000000000000000060b0d0f0c0a0300000000000000000000000000000000000000000000000000000000000000000000000000000002090b0d0c0a04000000000000000000000000000000000000000000000000000000040a0c0e0c0a040000000000000000000000000000000000000000000011263b51667b908774899fb4ab95806b56402b1601000000000000000000000000051a2f455a6f8496807b90a5bba8937d685862788799a1aeb4bab9b4ae9f978372604a3a2917040000000000000000000000000000000002080b0f110f10253a4f657a8fa4bacfdcc7b19c87725c47321d00000000000000000000000000000000000000000000000000000000091c2f404d5f677277766f635b4b3e2e211103000000000000000000000000000000000000000000000000000000000000182d42586d826d8278818178837f7f817e7b81817586817f77817f817f7a697e796d827d817f7a818277624d37220d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090b10161e2124282a2b2d2d2c2a2724201d150c0a040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090a161e2123211f170c0b0200000000000000000000000000000000000000000000040c171f2123211f17150e0c0600000000000000000000000000000000000011263b50667b908874899eb3aa95806b55402b1600000000000000000000000000041a2f44596f8495807b90a6bba8937e69535a62778391999fa9a89e998f8174605443301c0c00000000000000000000000000000000000000000000000f24394f64798ea4b9cedcc7b29d87725d48321d000000000000000000000000000000000000000000000000000000000f24384c5e677c878c8b8479645c4b3f2e211002000000000000000000000000000000000000000000000000000000000a162b40566b80807c676c6c636e6a6a6c69666c6c61716c6a626c6a6d7f7a667c78697e696c6a646b6d62594834200b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090b0f13151617171615120e0b08010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b0d0d0b070000000000000000000000000000000000000000000000000008070000000000000000000000000000000000000000000001111c2328323638363329261e130000000000000000000000000000000000000000000c171f2a3337383633292a23211a0f060000000000000000000000000000000010253b50657a908873889db3ab95806b56402b160100000000000000000000000004192e44596e8395807b90a6bba9947e69544959626f7c848a8c8c89837a6d6056453625130000000000000000000000000000000000000000000000000e24394e63798ea3b8ceddc7b29d88725d48331d0000000000000000000000000000000000000000000000000000000011263b51667c8d9da59f99897b655d4b3f2e20100000000000000000000000000000000000000000000000000000000a1a28323650626b6b675f57574d59545557535157574b5c57544d57556169645e666361696157554f56574d483b2b1805000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090d18202222201c130801000000000000000000000000000000000000000a10121e1d0f0d0700000000000000000000000000000000000008141c2f3838454b4d4c463a3a311c13080000000000000000000000000000000000000c1c29333a474c4e4c463a3f39352c20190e0000000000000000000000000000000f243a4f64798f8974889db2ab96806b56412b160100000000000000000000000003182e43586d8396817b90a5baaa947f6a553b474c5e666e747777756e655d4b45382718080000000000000000000000000000000000000000000000000d23384d62788da2c7d7ddc7b29d88725d48331d000000000000000000000000000000000000000000000000000000061b31465b70859babb7b5a79e8a7b655d4b3e2d1e0e0000000000000000000000000000000000000000000000000002162838454b575a5e5b554e493d38433f3f413e3b41423646423f3742434f544f4c514d4f544f42403a414237342b1d0d000000000000000000000000000000000000000000000000000000000000000000070b13191b180f0d070000000000000000000000000000000000000000000000000000000000060c0d161a1a160f0d070000000000000000000000000000000102000000000000000000000000000000050b0d0c09030000000000000000000000000000040a050000000000000000000000000004121d242b3437373530251d14090000000000000000000000000000000004121d2427333224211a0f0100000000000000000000000000000008182630404c505660626158534e4230251808000000000000000000000000000000000a1a293a474c58616361585a544e493d352c1e1103000000000000000000000000000e24394e63798e8a74879cb2ab96816c56412c170100000000000000000000000003182d42586d8297817a8fa5baaa95806a554034404c515959616260554f4b3f31271a0a000000000000000000000000000000000000000000000000000c21374c61768ca9bacddcc7b29c87725d47321d0000000000000000000000000000000000000000000000000000000a1f34495f74899eb4c9c5b9a89e8a7b655c4a3c2b1b0b000000000000000000000000000000000000000000000000091e324556606c6f73706a635b534c473b4038454b453839373435313538353f39363c383b3e3b322a252c2d2220180d000000000000000000000000000000000000000000000000000000000000000008131c20282f302d24221b100200000000000000000000000000000000000000000000000000000e1920232b2f2f2c24221b100100000000000000000000040a0c16180f0d0700000000000000000000030d192022211e160b00000000000000000000030a0c191f1b0d0b050000000000000000000312222f383b484d4d4a433631261909000000000000000000000000000001122330393c484739362d1f0f000000000000000000000000000001142636434b5e65707578767268604a43362513000000000000000000000000000000021528384758616e76787673706a635b4d493c2e2111000000000000000000000000000d23384d62788d8a75879cb1ac96816c57412c170200000000000000000000000002172d42576c8297827a8fa4b9ab96806b56412b2f383c3a474c4d4b4437372e1d150a00000000000000000000000000000000000000000000000000000b20354a6074899fb4c9d7c7b19b86715c46311c000000000000000000000000000000000000000000000000000000071c32475c71869cb1c3d3c6b9a89e8a7a645a483929190900000000000000000000000000000000000000000000000b21364b60768285888580797169615956564c5660564d4f4d484b44494d4b484c4c46393e35404437342a1d0d0b05000000000000000000000000000000000000000000000000000000000000000008182530353d44454239362d201306000000000000000000000000000000000000000000000006141e2c35384044454139362d1c140800000000000000000c171f212b2d24221b1002000000000000000b171e2b34383632281b1204000000000000000b161e212e34302220180d000000000000000011212f404c5159626260544b4437261401000000000000000000000000000f1f30414d515d5c4e4a3d2d1a0a000000000000000000000000000d1c304354606c7b858a8d8b877e6d605443301c0f0000000000000000000000000000091d3245566176838b8d8b89857f796f625a4b3f2e1e0e0000000000000000000000000c22374c61778c8f7a889db2ac97826c57422d170200000000000000000000000002172c41576c819682798ea3b9ac96816c57412c1d24262a343737353126231c1102000000000000000000000000000000000000000000000000000000071c3043546e8399abbcc7baa996816c57412c1700000000000000000000000000000000000000000000000000000000142a3f54697f94a5b6cad6c6b9a89d88786257463726140100000000000000000000000000000000000000000000091e324556606c6f777f898e867e77706c6b616375675f64625960555a62605962615758534b55594c483b2a1909000000000000000000000000000000000000000000000000000000000000000000132536434a52595b574f4a3e31241300000000000000000000000000000000000000000000061424323c494d55595a564e4a3e302618080000000000000c1c29333641423a362d20100100000000000b1b29333c484d4b46393022120000000000000b1b293236444a4537342b1d0d00000000000008182f3f4c5e66727777746a605544311d10000000000000000000000000071a2d3d4d5f677372645c4a3827150200000000000000000000000d1d30414b607281909a9faaa49c938272604a3d2d1a0700000000000000000000000006192c3c4b607484999faba79e9a948e8478655d4b3c2c190900000000000000000000000c21364b61768b9a848a9fb4ad98836d58432e180300000000000000000000000001162c41566b819683788ea3b8ac97826c57422d170f11181f2222201d1409080000000000000000000000000000000000000000000000000000000000001325364f647a8d9fabada99f8b78624d38220d000000000000000000000000000000000000000000000000000000000b20364b6074879db2bdced6c6b7a69c8675615544311d140400000000000000000000000000000000000000000002162838454b5759616976808a938a8581807679877d697977667567677873647776616e69606a6e62594837271c1308000000000000000000000000000000000000000000000000000000000000071c30435460686e706d645c4e42311f0e000000000000000000000000000000000000000000142432424f5a626b6f6f6b645c4b4336261401000000000818293a464c56574f4a3e2d1f0f0000000003172939464b5a6261574c40301b0b0000000003162939464b595f5a4c483b2b180500000000001325364c5d667c878c8c897f73604b3e2d1b0700000000000000000000000c21364a5b677d88867a645645311d090000000000000000000005182b3b4d5f6b80959fafb4bbb6b1a0947f6a5b4a3621120000000000000000000000000c2035495a6b8096a2b4aaa2abafa9a199897b655b4937271501000000000000000000000b20354a60758a8c77859ab0ae99846f59442f1a0400000000000000000000000001162b40566b809584788da2b7ad97826d58422d180300040a0c0d0b080100000000000000000000000000000000000000000000000000000000000000000822364a5c687e8c9598958a7c665a4835200b00000000000000000000000000000000000000000000000000000000091d324556667c909fb1c2d3d5c4b5a4998373604b42322212010000000000000000000000000000000000000000000a1a2832363b474c58616b777e8a948a7f70859a887e8a857b897d7c8a8079898477837e75808377625544353025180a00000000000000000000000000000000000000000000000000000000091d2f404a60727d8485827a68604e3d2c1a06000000000000000000000000000000000000000c1c31424f61697880848481796c605443301c0e000000001325364658616b6d645c4a3d2d1a070000000a1e33465761707776665e4c392917030000000a1e324657616e747062594834201000000000071c304354657b8c9ca5a79e95816c5c4a36220d00000000000000000000031628394e63798b9d9c8774604b36200b000000000000000000000b20344859677d919eb0bdcacecabeb49f8b79634e40301d0900000000000000000000011426364d62788b9faa9f948d969fb0b3a89e8a79635544311d0c00000000000000000000071c304354738899838a9eb4af9a85705a45301b0500000000000000000000000000152b40556a809584778ca2b7ad98836e58432e190300000000000000000000000000000000000000000000000000000000000000000000000000000000071b2d3e4e60687980827f77665e4c3c2b190500000000000000000000000000000000000000000000000000000000021528384c5e6d8197a4b6c6d6d2c2b3a196816c604f402f1f0f000000000000000000000000000000000000000000000a161e212a343a495a657b86867f776a6c819684949c86898a89888a85869c89888986848281857360534a4336281a0a0000000000000000000000000000000000000000000000000000000f24384c5e6d8292999a978d7e685b4935210c0000000000000000000000000000000000000417293a4e60697e8b95999a968c8172604b3c2b19050000071c304354617680827a645c4a36210c0000031628394b6175848d8a7c665746331e0a000005182b3b4b617583898477624c3e2e1b080000000b20354a6073879daab6b9b39f8e79644e39240f00000000000000000000091e3246576e8399aaa5927d6752392816030000000000000000071a2d3d4d62778a9eb4bccdccc9bfc3bbaa9a85705e4c38241100000000000000000000081c3043546b8095aa9f8c7f788196a2b4b9a89b8573604b3a2a1804000000000000000000001325365b71869b999ea8b9b19b86715c46311c0000000000000000000000000000152a3f546a7f9485768ca1b6ae98836e59432e19040000000000000000000000000000000000000000000000000000000000000000000000000000000000102031424e5b636b6d6a62594c40301e0e0000000000000000000000000000000000000000000000000000000000000a1a2f404b6175869ca8b9cde1d0bfb09f937e695e4c3d2d1d0d0000000000000000000000000000000000000000000002090c1823384d6378897b70827e69647a8e878298838697828b927d889882889681898875817f726860544538281603000000000000000000000000000000000000000000000000000114263651667c90a0aeb0ab9f8c79634e38230e0000000000000000000000000000000000000a1f334658687e939faaaeafab9f95806b5a4835200b00000b20354a60728496978b7a644e3a29170400091e3246576b8096a29e8976614c36210e00000b203448596c81979f99846f5c4b37220d00000010253a4f657a8fa5b7c8ccbdab96816c56412c17010000000000000000000c21364b61768a9fb4ae99846f5745321e0900000000000000000c21364a5b6d8297a8b9cdc5b9b3a9aeb3b4a2917c66513f2e1c080000000000000000000b20354b6074889d9f8c7c6a6372849aabbcb5a3947f6a5847331f0a000000000000000000001a2f44596f8499aeb4b9c6b29d87725d392916030000000000000000000000000014293f54697e9485778ca1b7ae99846e59442f19040000000000000000000000000000000000000000000000000000000000000000000000000000000000021424313d494e5658554d483b3022120000000000000000000000000000000000000000000000000000000000000000121e32465763798a9eb4bccdddcdbdb49f8c7c665b4a3b2a1a0a00000000000000000000000000000000000000000000000012283d52677d897571868978656e83947f878c7e8a897f94847b8c8a7c8b897d8b818594877e72605645321e1000000000000000000000000000000000000000000000000000081c3043546f8499aebec9bbaa97816c57422c170200000000000000000000000000000000000c21364c6176899eb3bbc8c9bcb49f8b78624d38220d000010253a50657a8fa2a999846f5846331f0a000c21364b6176899eb4a7947f6a543c2c1906000d22374d62778b9fb4a18f7a644f3a250f00000013293e53687e93a8c3d4d9c4af99846f5a442f1a0500000000000000000011263b51667b90a9bab49f8a76604b36210b000000000000000417293a4e63798c9fb4c6c7b9a79e9499a1b3b19b86715d4b37230a00000000000000000010263b50657b90a6957f6a5e5463798c9fb5c1b49e8977614c38281502000000000000000002172d42576c8297acc1cdc9b49f89745746321e0a0100000000000000000000000014293e54697e939b899eb3c4af99846f5a442f1a0500000000000000000000000000000000000000000000000000000000000000000000000000000000000006141f2c353840434037342b1d1204000000000000000000000000000000000000000000000000000000000000000003162839495b677d919eb0c0d0e2cebbaa9e8a7963594838281603000000000000000000000000000000000000000000000010253a4f657a8f7d677d92877b6f788a897d92877e938382917c7f94837d928480937e7f86908374604b3e2e1b070000000000000000000000000000000000000000000000000b20354b6075899fb4c9d9c8b19b86715c46311c07000000000000000000000000000000000012283d52677d92a8b9ccd8dacebbaa927d68533d28130001162b41566b8096abb59f8b76614c36210c0011263c51667c91a8b9b29d87725a4935200c0014293e54697e93aabbab96806b5638281502000013293e53687e93a8bdd3dac5b09b85705b46301b06000000000000000001162b41566b8096abc7baa98f7a65503a2510000000000000000a1f3347586d8298abbccdbaa99e897f8399a3b4a38f7a6550382816030000000000000003162939566b80969e8975604b4a5b6f8499afc4b9a895806b5645321d09000000000000000000152b40556a8095aabfd5cdbaa88b76614b36211716130d0b05000000000000000013293e53687e93898197acc1af9a846f5a452f1a0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000010f1a21232b2d2a2220180d00000000000000000000000000000000000000000000000000000000000000000000000b1b2c3d4d5f6b8096a2b4c3d4d5c4b8a89d8777625645321e1504000000000000000000000000000000000000000000081b2e3f4b60738789786c819790847b809581818877817f76868a8686907b80867786877e797c89826d5c4a36220d0000000000000000000000000000000000000000000000000d22374c62778ca8bacdddc8b29d88735d48331e080000000000000000000000000000000000162b40556b8095aac6d6e8ead8c8a9947f69543f2a1400051a2f455a6f849aafbcab907b65503b261000152b40556a8095aac6b6a58d78624d38230d031729395a6f8499afc8b09b85705645321d09000013283d52687d92a7bdd2dbc6b19b86715c46311c07000000000000000004192e44596e8399aec3c7a7927d68523d2813000000000000000c21374c61768a9fb4c9c7b49f8b7a6a72859bb0ad98826d5645321e09000000000000000a1e32465770869b98826d57453d50657b90a6b7c6b39e8875604b36200b00000000000000000013283e53687d93a8bdd2d7c6a28d78634d382c2c2b292220190e0000000000000013283d52687d92887f94a9bfaf9a856f5a45301a05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c0e1618150d0b05000000000000000000000000000000000000000000000000000000000000000000000000000f1f30414b6073849aa5b7c7cbb8a69e8f9b8574604b433322120100000000000000000000000000000000000000000e22374b5d65777c91867675858b88908a998c7f7e7b7a6a61767e787586877678877c848275667a8c79644f3a240f0000000000000000000000000000000000000000000000000e23384d63788da2c6d7ddc8b29d88735d48331e080000000000000000000000000000000001162b41566b8096abc7d7e2dfcfbcab927d68523d281300031629395d73889db2c9aa957f6a55402a1504192e43596e8398aec3c3a7927d68523d28130a1e33465773889db3c8b49f8a75604b36200b000012273c52677c91a7bcd1dcc6b19c87715c47321c070000000000000000051a2f455a6f849aafc4bda8937d68533e28130000000000000417293a54697e93a9bacdbaa995806a5c657b90a5b49e8975604b36210b000000000000000c21364b61768a9f937e695439354a6074889db2c8b8a7917c66513c271100000000000000000011263b51667b90a6bbd0cfbaa48f7a654f404141403e38352b1e1608000000000011273c51667c919d949daec3ad98836e58432e19030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001121d3144556176879da9bac8b39e887b8798826e6150402f1f0f000000000000000000000000000000000000000010253a4f657b88758094877b7a8b747b7f838c9486868578706b686263798a81778987726d615c6d827c67523c27120000000000000000000000000000000000000000000000000e23384e63788da3b8cddcc7b29d87725d48321d08000000000000000000000000000000000013293e53687e93a9bacacecabeb49f8c78624d37220d000a1e324657748a9fb4c2ad98836d58432e18061b31465b70869bb0c5c1ab96816c56412c170c21364b61768ba6b8cbbaa98f7a644f3a250f000011273c51667c91a6bbd1dcc7b29d87725d48321d080000000000000000051a30455a6f859aafc4bda8927d68533d28130000000000000a1f33475870859ab0c7c9b49f8a76614c5d72879cb2a8907b65503b2610000000000000000f243a4f647a8faa8f7a65503a3043546d8398adc2c5ac97826d573929170300000000000000000f243a4f64798fa4b9ced1bca6917c675455565656534d483c332616070000000010253a4f657a8fa8a9aebbc6ab96816c56412c170100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c0d0b0500000000000000000000000000000000000000000000000000000000011426374758647a8a9fb4bcb8a6927d7989947f6a5e4c3d2c1b0b0000000000000000000000000000000000000c1d2a43586d83917c6b7f8a908b806b666a6e7d92807882858581786860687e826d7b816c544b4f657a74604b3621120400000000000000000000000000000000000000000000000e24394e63798ea3b8cedcc7b29c87725d47321d0800000000000000000000000000000000000d22374c62778a9fb1b6bbb4b0a096816c594834200b000c21364b61768ba9bac4af9a856f5a45301a011527375d72879db2c7c4af9a856f5a45301a0e23394e63788ea3c4d5c7a9937e69543e2914000011263b51667b90a6bbd0ddc8b39d88735e48331e090000000000000000051b30455a70859aafc5bda7927d68523d28130000000000000c21374c61768b9fb4cac5ad98836e5847566b8095abaa957f6a553625130000000000000012273d52677c92a28d78624d38253654697e93a9c8c7b29c87725746331e0a00000000000000000d22384d62778da2b7dad4bfaa947f6b696a6b6c6b68625a5044332515000000000c21364b61768a9fb4c1c8b9a8927d67523d2712000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080c171f212220180d0b02000000000000000000000000000000000000000000000000000009192a3a4a5c677d919eb0bfb49f8c7b7b8b8d7c665b49392918080000000000000000000000000000000004182a3b4752677d9287756a787d7c737b72605f697e7b7f7c7d818a8b7e6874827560656c6251464b5d656056473a2f221202000000000000000000000000000000000000000000000f24394f64798ea4b9cedcc6b19c87715c47321c0700000000000000000000000000000000000b20344859687e919ca4aa9f9b918273604b3b2b1905000c21364c61768ba1c7c6b19c87715c47321c081d31445574899eb4c9c7b29c87725d3727150f253a4f647a8fa4b9cfc1ab96816c56412c17010010253b50657a90a5bacfdec8b39e89735e49341e000000000000000000061b30465b70859bb0c5bca7927d67523d281200000000000012273c52677c91aabbccb9a7917c66513a4f647a8fa9af9a846f5443301c07000000000000152a40556a7f95a18c76614c37253a4f647a8faabbcab59f8b76614c36210c00000000000000000b21364b60768babbccfdec8b39e89807f7f8181807e786b625043321a0a0000000a1e3246576b8096a3b1b2af9e8976614b36210c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002101b2229333637342b261f140600000000000000000000000000000000000000000000000000000c1c2d3e4d5f6b8095a1b3bbaa9e89797d928979635746362614010000000000000000000000000000000b1f344759616b708496806b6268697f8a806b61757a676a78746c7785927d7e927d686060554b5761696c6961584c402f2010000000000000000000000000000000000000000000000f253a4f647a8fa4b9cfdbc6b19b86715c46311c07000000000000000000000000000000000005182b3b4e60687c868c8c8a857c6d605544311d0d00000c21364c61768ba1b6c8b29d88735d48331e0b20354b60758aa8b9cdc9b49f89745544311d10263b50657b90a5bad0c3ad98836e58432e19030010253a4f657a8fa4bacfdec9b49f89745f4a2715020000000000000000061b31465b70869bb0c5bca7927c67523d2712000000000003162839576c8297acc8c9b39e8975604b364b60758a9fb39e8974604a35200b000000000000172c42576c8197a08b75604b3620364b60758a9fb4cabcab8f7a654f3a251000000000000000000b20354a60758a9fb5cadfccb8a79e969495969695938b806b614f382815020000031629394c617585959c9d9a907e685746331e0a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000210212e373a464c4c483b3a312415070000000000000000000000000000000000000000000000000000102030414b60728399a4b6b9a79d877681978675615443301c120100000000000000000000000000000c22374c6177817678898d7b655a738888857f6d828a7c7b8a806b7a81858b7d8d88777574655d61757e827e76665e4c3e2d1b0700000000000000000000000000000000000000000010253a50657a8fa5bacfdbc6b09b86715b46311c060000000000000000000000000000000000000d1d31424e5f677277777670675f4b443727150000000c21364c61768ba1b6c9b39e89745e3828160c22374c61778ca1c6d6cdbaa98b75604b362011263b51667b90a6bbd0c5af9a85705a45301b05000f243a4f64798fa4b9cedfcab49f8a755544311d080000000000000000061c31465b71869bb0c6bca7917c67523c27120000000000091e32465771869bb1c6c4ae99846f564531445571879cb1a78c77614c37220c000000000000182e43586d8398a08b76604b362131455672879cb2c7c9a8937e69533e29140000000000000000071c30435474899eb4c9ded6c5b8b3aba9aaabababaa9f947f6a5645321d090000000b1e3346576175808688857c68604e3929170300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010202e3f4b4f58616259534e42332515010000000000000000000000000000000000000000000000000002131c3043546175869ca7b8b6a599837485998372604b41301f0f00000000000000000000000000000d22384d62778d89807e8a8878666c81947f847f8d86868789857e858883898582988589887b657385808088897c665c4a36220b00000000000000000000000000000000000000000010263b50657b90a5bad0dac5b09b85705b46301b0600000000000000000000000000000000000000142431414d515861626056514d41312719090000000c21364c61768ba1b6cab49f8a755645321e0e23384d63788da2b8cdd7c7a18b76614c362112273c52677c91a7bcd1c7b19c87725c47321d07000f24394e64798ea3b9cee3cfbcab8b75604b36200b0000000000000000071c31465c71869bb1c6bca6917c67513c271200000000000c21364b61768a9fb4cabfa9947f6a54382737596f8499aea38e79644e39240f000000000000192f44596e8499a18b76614c36212738596f8499aec4c2ac97826d57422d180000000000000000001325485d73889db2c8dde3d6ccc8c0bebfc0c1c8bbb39e8975604b36200b000000031729394657616a71736f665e4e42311b0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008182e3f4b5d657176777368605043331f0f00000000000000000000000000000000000000000000000000000114263646576378899ea9bab3a19580778895806b5f4d3d2d1c0c000000000000000000000000000b2034485a6a7f868a8e9196877b79798a8979868a937e879a84848a88818a9580889883868a787a8f7c7d77838b7a644f39291703000000000000000000000000000000000000000011263c51667b91a6bbd0dac5b09a85705b45301b060000000000000000000000000000000000000b1b2d3e4a5760686c6b665e4b4539281609000000000c21364b61768ba0b6cebbaa8b76604b36210f24394e64798ea3b9cecbb6a18c76614c372113283d52687d92a7bdd2c7b29d88725d48331d08000e23384e63788da3b8cdebd9b6a08b76614b36210c0000000000000000071c31475c71869cb1c6bca7917c67523c271200000000000f253a4f647a8faabbcec4a48f7a654f3a2c41566c8196aba5907b66503b2611010000000000192f44596e8499a18c77614c37222c41566b8196abc0c5b09b85705b3929170300000000000000001b30465b70859bb0c9daeae8e0ded6d4d4d6d6d8ccb9a88e79634e39240e000000000b1b2939464b555c5d5a514c40312413000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001325364b5d657b868b8c887e6a61503d2d1a07000000000000000000000000000000000000000000000000000008182939495a657b8b9fabbcb59f8d7c7b8c917d675b4a3a2a180800000000000000000000000005192b3c50616a7175797c808d9088888a99877d869c87798795808497827f94897f948b7d86847e939092827384846f5746331e0a000000000000000000000000000000000000000012273c51677c91a6bcd1dac4af9a856f5a45301a050000000000000000000000000000000000031628394a5c64757d81817c6f605745321e0d000000000b20354b60758aaabbceb6a18c77614c372210253a4f657a8fa4bacfcbb6a18c76614c372113293e53687e93a8bdd3c8b29d88735d48331e08000d23384d62788da2b7cde1ccb6a18c77614c37220c0000000000000000071c32475c71879cb1c6bca7927d67523d2812000000000013283e53687d93a8c8c4b8a68b76614c36363f54697f94a9a8927d68533d261c140800000000182d43586d8298a28d78624d3823293e54697e93a9bec8b39e88735746331e0a0000000000000000162b40556b8095abbcced8d4d5d6d7d7d6d5d4d2c6b6a48d78634e38230e00000000000b1b293336404748453b382f221306000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071c304354647b8b9ba3a69d937f6a5b4a36210c0000000000000000000000000000000000000000000000000000000b1b2c3c4b5d677d8d9fb5bcab9e89787f958a79635847362614010000000000000000000000000d1d33435055566063666b7e8c86787483917c7786978278878c7d84937e7f94868196887f947f95878385707a8c76614b36210c000000000000000000000000000000000000000012273d52677c92a7bcd1d9c4af99846f5a442f1a050000000000000000000000000000000000091e324657647a88939696918475604b3b2b1805000000081d314455758a9fb4cab8a28d78634d382311263b50667b90a5bbd0ccb6a18c77614c3722142a3f54697f94a9bed4c8b39e88735e49331e09000d22374d62778ca2b7cce1ccb7a28c77624d37220d0000000000000000081d32475d72879cb2c7bda7927d68523d28130000000001162c41566b8196ababb0b39e88735846454b5257677c92a7a9947f6954443730261808000000172c42576c8197a48e79644f3924273d52677c92a7bccbb8a68b76614b36210c00000000000000000e23384d63788c9fb4bbc8bfc0c1c2c1c0bfbec1b5a89c8773604a35200b0000000000000b171e212b32333026241d1204000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b20354a6073869ca9b5b7b29f8b79634e39240e000000000000000000000000000000000000000000000000000000000e1e2e3f4d5f6a7f95a0b2b8a79a8474849a8776615443301c10000000000000000000000000001525333c38454b4e5160687b89887a77878a7a7786937e78878a7b858d79819580848a848a8183908c7e69748978634d38230e000000000000000000000000000000000000000013283d53687d92a8bdd2d9c4ae99846f59442f1a0400000000000000000000000000000000000c21364b6175889da6acaba297826d594834200b000000011426495f74899eb4c9b8a38e78634e392311273c51667c91a6bbd1ccb6a18c77614c3722152a40556a7f95aabfd4c8b39e89735e49341e09000c21374c61768ca1b6cbe1cdb8a28d78634d38230e0000000000000000081e33485d73889db2c8bda8927d68533d28130000000004192e44596e839995969eb09a85705b475760676c6e7d92a7a8937e6960554b43362614010000142a3f54697f94a5907b65503b26253b50657a90a5bad5c4a38e79644e39240f00000000000000000c2035495a6c81969faaa9aaabacadacabaaa9a8a39b8a7b655443301c0700000000000000030a0c151c1e1a110f090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f24394e64798ea4b5c7c8bbaa95806b56402b1601000000000000000000000000000000000000000000000000000000001021304150616d8298a2b4b4a2958077889a8472604b3e2e1a0a0000000000000000000000000715202828323639414e5d6578848b7f7989887877868c7c78878878817473857e77877685826e7b7c6960718674604b36200b000000000000000000000000000000000000000013293e53687e93a8bdd3d8c3ae99836e59442e1904000000000000000000000000000000000013283e53687d93a6b7c4c0b49f8b77624d37220d000000001e34495e73899eb3c8b9a48e79644f392412283d52677d92a7bcd2ccb7a18c77624c3722162b40566b8095abc0d5c9b39e89745e49341f09000c21364b61768ba0b6daecceb8a38e79634e39240e0000000000000000091e33495e73889eb3c8bda8937d68533e281300000000061c31465b718695808096ab98836d585961757c81848a9eb4af9a84797468605443301c0c000011263b50667b90a5917c67523c2724394e63798ea3b8cebca6917c67513c2712000000000000000006192c3c4b6073808b91939495969797969594938e857a655d4b36251300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012273c51677c91a6a6b0b4c1ad97826d58422d18030000000000000000000000000000000000000000000000000000000002132333434b6074849aa4b6b59f8d7c7b8c95806a5c4b38281602000000000000000000000000030d0a151d2024313f4c5a6273808c857f8986777e8a897a7b8985797a7e777262756176746066665e617779645544311d08000000000000000000000000000000000000000014293f54697e94a9bed3d8c3ad98836e58432e19030000000000000000000000000000000002172c41576c8196acc4d5cebbaa917c67513c2712000000081e33485d73889db2c8b9a48f7a644f3a2513293e53687e93a8bdd3ccb7a18c77624c3722172c41576c8196acc1d6c9b49e89745f49341f0a000b20364b60758babbccfe3ceb9a48e79644f39240f0000000000000000021527385e74899eb3c9bda8927d68533d281300000000031628395d7388907b8095ab96806b566177879197999ea8b9b4a29a8d887e72604b3a291704000d22374d62778ca5947f69543f2a23384e63788da3b8cabea8937e69533e29140000000000000000000e1d314455606b777c7e7f8081828281807f7d7971645c4b3f2e180800000000000000000000000000000000000000000000000000000000000000000001080b0d0c0a03000000000000000205040100000000000000000000000000000000000000000000000013283e53687d939a909ba3b4ae99836e59442e1904000000000000000000000000000000000000000000000000000000000005151d3145566176869ca7b8ab9e897780958c7a645645321e0900000000000000000000000000000002090b13212f3c4855606a798592889c867779868f8382898d847f696055605761605550514d5961645c4a372715020000000000000000000000000000000000000000152a3f546a7f94a9bfd4d7c2ad97826d58422d18030000000000000000000000000000000004192e44596e8399aec3d8d8c8a8927d68533d2813000000081d32475d72879cb2c7baa58f7a65503a2514293f54697e94a9bed3ccb7a28c77624d3722182d42576d8297acc2d7c9b49f89745f4a341f0a00081d314455758a9fb5cadfcfbaa48f7a654f3a25100100000000000000091d31455674899fb4c9bda7927d68523d281300000000091e324557748a8c778499a9937e6954687e93a5acaeb4b9c6c0b4afa69d93826e5847331f0a000b2034485972879d947f6a543f2a23384d62788da2b2b6c3aa95806a55402b1500000000000000000001152737444b596166696a6b6c6d6c6b6a6968645c4f4a3e2e211100000000000000000000000000000000000000000000000000000000000000000109151d2022211e170b080001080b11171a1a16100e0800000000000000000000000000000000000000000014293e53697e93907b859bb0af9a856f5a45301a050000000000000000000000000000000000000000000000000000000000000215273847586378899ea9b8a79a8474859a8674604b37271501000000000000000000000000000000000003111d2b37444b5b63707d88939a85707786877279887b69614a444b464b4b44373c3a474c4e4a3e2d1909000000000000000000000000000000000000000000152b40556a8095aabfd5d6c1ac97816c57422c170200000000000000000000000000000000051a2f455a6f849aafc4d9d2bca7927d67523d2812000000071c32475c71879cb1c6baa5907b65503b26152a3f546a7f94a9bfd4ccb7a28c77624d3722182e43586d8398adc2d8c9b49f89745f4a341f0a000215274a5f74899fb4c9decfbaa5907a65503b251716161514141413141420364b60758ba9bacdbca7927d67523d2812000000000b21364b60768b8974879ca7927c6752687d92a2aaaeb2b5bcc9c8bbb4b19f8a76614c37210c0005192b3b556a7f94927c67523d2722374d62778c9e9ca5b6ac97816c57422c1702000000000000000000091927313b474c51545556575857565554534f4a3e362d2011030000000000000000000000000000000000000000000000000000000000000009141d27313538363329221b10151d20272c2f2f2c25231c11070000000000000000000000000000000000000014293e53697e938c778499afb09b86705b46311b06000000000000000000000000000000000000000000000000000000000000000a1a293a495a657b8b9fabb4a297818193937e695544311d08000000000000000000000000000000000000000d1926313d4a4e5f67757e88806b6277806b637773604b4331353236353127272a343739362d201000000000000000000000000000000000000000000001162b40566b8095abc0d5d6c1ab96816c56412c170100000000000000000000000000000000051b30455a70859aafc5dad1bca7927c67523d2712000000061c31465b71869bb0c6bba6907b66513b26152a3f556a7f94aabfd4ccb7a28d77624d3822192f44596e8499aec3d9c9b49f89745f4a341f0a00001f34495e74899eb3c9ded0bba6907b66513b2c2c2b2b2a2a292929292a2a374c61778ca1c7d7bca7927c67523d2712000000000c22374c61778c86758a9fa6907b66516074849095999d9faba3a3aa9f9c958673604b35200b00000d20364b6074818174604b362122374c62778c89879cb2ad97826d58422d18030000000000000000000009151d2a34373c3e3f4041424241403f3e39362d221b1002000000000000000000000000000000000000000000000000000000000000000919263137444b4d4c4639372e212731353c424444413a372e221b1002000000000000000000000000000000000013283e53687d938b76859bb0b19c86715c47311c0700000000000000000000000000000000000000000000000000000000000000000c1c2c3c4b5d677d8d9fb5b19f97857e8c8774604b35200b000000000000000000000000000000000000000009141d2d36414d56606975726059626b625962605544311d201e21201d1511181f2224221b100200000000000000000000000000000000000000000001172c41566c8196abc1d6d5c0ab95806b56402b160100000000000000000000000000000000061b30465b70859bb0c5dad1bca6917c67513c2712000000061b30455b70859ab0c5bba6917b66513c26152a40556a7f95aabfd4cdb7a28d78624d38231a2f455a6f849aafc4d9c9b49e89745f49341f0a00091e33495e73889eb3c8ddd1bca6917c67514242414140403f3e3e3e3e3f40404d63788da2b8cdbca7917c67523c2712000000000d23384d62788d84778caaa48f7a644f5660727b7f83878a8c8d8e8d8a868076615443301c080000091d324556606c6c605645321e22374c62778c827a8fa4ad97826d58422d18030000000000000000000000010c181f2227292a2b2c2d2d2c2b2a2824221b1007000000000000000000000000000000000000000000000000000000000000000001142637444b55606261574f4b3f2f37444b51575a5956504b3f362d2014060000000000000000000000000000000012283d52677d928a75869cb1b19c87715c47321c070000000000000000000000000000000000000000000000000000000000000000000e1e2e3f4d5f6a7f949eb5b39d887a89907b65503b2610000000000000000000000000000000000000000000010f1a213138454b55606054484c5651484d4b443726140b0a0c0b080100040a0c0f0d07000000000000000000000000000000000000000000000002172d42576c8297acc1d7d4bfaa957f6a55402a150000000000000000000000000000000000061b31465b70869bb0c5dbd1bba6917c66513c2711000000051a2f455a6f849aafb3b8a6917b66513c26152b40556a8095aabfd5cdb7a28d78624d38231b30455a70859aafc5dac9b49e89745f49341f0a00081e33485d73889db2c8ddd1bca7927c675857575656555554545353545455555664798ea4b9cebca6917c67513c2712040000000e24394e63798e82798ea4a38e79644e455460656a6e72767778797876716b61584736261401000002152838454b57574b4538281622374d62778c83788da3ad97826d58422d180300000000000000000000000000040b0c11141516171817161514130f0d0700000000000000000000000000000000000000000000000000000000000000000000081d314455606b75777670655d4c3f4b5560666c6f6f6b655d4f4a3e3124140600000000000000000000000000000011273c51667c918974879db2b29c87725d47321d08000000000000000000000000000000000000000000000000000000000000000000001021304150616c80949faba69d909e947f6a553f2a15000000000000000000000000000000000000000000000007131a283237444b4a433637413d3437353126190900000000000000000000000000000000000000000000000000000000000000000000000003182d43586d8298adc2d7d4bea9947f69543f2a1515130d0b05000000000000000000000000071c31465c71869bb1c6dbd0bba6907b66513b261100000004192f44596e84999d9da6a6907b66513b26162b40556b8095aac0d5cdb8a28d78634d38231b30455a70859aafc5dac9b39e89745e49341f0900081d32475d72879cb2c7dcd4bea9947f6e6d6d6c6c6b6b6a6969696869696a6b6b6d7c90a6bbd0bca7927c67523b2f22120000000f243a4f64798f817a90a5a38e78634e36434a5055595660626364636056564c473a2a1808000000000a1a28323642413632281a0d22374d62778c84778ca2ad97826d58422d180300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005182b3b4b607380898d8b857b655d4e5d65747c818484817a70645c4e4231241301000000000000000000000000000010253b50657a908974889db2b29d87725d48321d0800000000000000000000000000000000000000000000000000000000000000000000021323334351626c7f8d9ea7b3a5aa957f6a55402a15000000000000000000000000000000000000000000000000000a161e263135353025222b292022201d14090000000000000000000000000000000000000000000000000000000000000000000000000004192e43596e8398aec3d8d3bea9937e69543e292b2b282220190d0500000000000000000000071c31475c71869cb1c6dbd0bba5907b66503b261100000003192e43586e839887889da6907b66513b26162b40566b8095abc0d5ccb7a28d77624d38221b30455b70859ab0c5dac8b39e89735e49341e0900071c32475c71879cb1c6dcdec8b39e89838282818180807f7f7e7e7e7e7f7f808182879cb2c7d4bfaa957f6a594c402f1a0a00000f253a4f647a8f807b91a6a28d78634d3830353b4038454b4c4e4e4d4b453837332a1c0c0000000000000a151d202c2c211e160a0d22384d62778d85768ba1ac97826d57422d1802000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0c10100b0902000000000000000000000000000b203448596c81959ea8a39b8b7b6560687b8791979999968f857a68604e42311f0f00000000000000000000000000000f243a4f64798f8973889db2b29d88735d48331e080000000000000000000000000000000000000000000000000000000000000000000000051525344451616a7d89999fab9f8f7a644f3a240f00000000000000000000000000000000000000000000000000000309141d20201c130d16140b0d0b0801000000000000000000000000000000000000000000000000000000000000000000000000000004192f44596e8499aec3d9d2bda8937d68533e3d40403d38342b20190e000000000000000000071d32475c72879cb1c7dccfbaa5907a65503b251000000002182d42576d82927d7f94a5907b66503b26162b40566b8095abc0d5ccb7a18c77624c37221b30455b70859ab0c5dac8b39e89735e49341e0900071c31465c71869bb1c6dbe0ccb8a79e9998979796969595949393939394959596979ca5b6caddc8b29d8877665e4c38281602000f243a4f64798f7f7c91a6a38d78634e382320262a28323637383938363228211f170c000000000000000002090b17170b0902000d22384d62778d86758ba0ac97826d57422d180200000000000000000000000000000000000000000000000000000000000000000000000000000000000c171f212525201d150a0000000000000000000000000d22374d62778b9fb3b9b4a99c8672687e8d9da6acafaeaba39b8b7e68604e3d2d1a07000000000000000000000000000e23384e63788d8973889db3b39e88735e49331e090000000000000000000000000000000000000000000000000000000000000000000000000716263443505f6778838b8f8b7f6a5c4b37220d0000000000000000000000000000000000000000000000000000000001080b0b070000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000051a2f455a6f849aafc4d9d2bca7927d67524c525555534d483c352b1e110300000000000000081d32475d72879cb2c7dccfbaa58f7a65503a251000000002172c41576c81917b8095a5907b66503b26162b40556b8095aac0d5cbb6a18c76614c37211b30455b70859ab0c5dac8b39d88735e48331e0900061b30465b70859bb0c5dae8d5c5b8b3aeadacacababaaaaa9a9a8a8a9a9aaaaabacb2b6c3d3dfcbb7a69d897c665645321e09000f24394f64798e7f7c91a6a38e79634e39240e101a273136424237342a1e160c0a040000000000000000000000000202000000000d22384d62778d86758ba0ac97826d57422d180200000000000000000000000000000000000000000000000000000000000000000000000000000008131c2933373a3a3632281a13050000000000000000000013283e53687d93aabbccc7b6a48f7a7a8b9fabb7c4c4c4c1b4a99f937e685b4a362111000000000000000000000000000d22374d62778c8973889db3b39e89735e49341e090000000000000000000000000000000000000000000000000000000000000000000000000008162533414d5a626e777a776a61503e2e1b070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061b30455b70859ab0c5dad1bca6917c675962676a6a68625a4d483c2e211102000000000000081d33485d72889db2c7ddcfb9a48f7a644f3a250f00000001162b41566b808f7a8196a5907a65503b25152a40556a7f95aabfd4cbb6a08b76614b36211b30465b70859bb0c5dac7b29d88725d48331d0800051b30455a70859aafc5daefe3d5ccc8bfbfc0c1c1c0c0bfbebebebdbebebfc0c0c2c7cad3e1e7d4c4b7a79e8a75604b36210b000e23394e63788e7f7c91a6a48f79644f3a240f152738454b57584c473b2a180400000000000000000000000000000000000000000d23384d62788d86758aa0ad98836d58432e18030000000000000000000000000000000000000000000000000000000000000000000000000000081825303a474c504f4b453831231406000000000000000001172c41566c8196abc8d8d3c2aa957f869caabbc9d4d9d9d1c7bab49f8b79634e3f2f1c080000000000000000000000000c21374c61768c8974889db2b49e89745f49341f000000000000000000000000000000000000000000000000000000000000000000000000000000071523303c484d59626562595043332010000000000000000000000000070d0f0d070d0f0f0d0f0d0c100c0b100d0b0f0d0f0d0e0e0f0e0c0a0c0e0f0d0b100c0d0f0e0c060000000000000000000000000000000000000000000000000000000000061b31465b70869bb0c5dbd0bba6917b666e777d80807d786e625a4b3f2e2010000000000000091e33485e73889db3c8ddceb9a48e79644f39240f00000000152b40556a808e798298a48f7a644f3a25152a3f556a7f94aabfd4cab5a08b75604b36201b30455a70859aafc5dac7b19c87725c47321d0700051a2f455a6f849aafc4d9dad5c5b8b3aaaaabacacadaeaeaeaeafafb0b2b3b5bcb8c5c8d1dfe3cfbcab9f9884705645321e09000d23384d62788d807b90a6a5907a65503b25101d314556606c6d615947341f0a00000000000000000000000000000000000000000d23384d62788d86758aa0ae99846e59442f19040000000000000000000000000000000000000000000000000000000000000000000000000000132536434a5861656560564e41322414010000000000000004192e44596e8399aec3d8d7c3af9d959ca4b6c8c8c3c9ced8d8cebbaa9b85705d4c38230b0000000000000000000000000b21364b60768b8974879db2b49f8a745f4a26140100000000000000000000000000000000000000000000000000000000000000000000000000000005121e2b353b474c504d483b3325150200000000000000000000010f1a2124211b222424212421212521202522202422242124232423211f21232422202522222423211a0f01000000000000000000000000000000000000000000000000000000071c31475c71869cb1c6dbceb9a48e7a78838b929595928d8378655d4b3e2d1b0b0000000000091e33495e73889eb3c8ddceb8a38e79634e39240e00000000142a3f54697f8d788399a38e79634e3924152a3f546a7f94a9bfd4cebaa98a755645311d1a2f445a6f8499afc4d9c6b19c86715c47311c070004192f44596e8499aebabec8ccb8a79e959596969798999999999a9a9b9c9e9faba2b0b4c1d1dfcab49f8d8275614b38281602000c22374c61778c817a90a5a6917b66513c261120364b6074818277614c38281603000000000000000000000000000000000000000d23384d62788d86758a9faf9a856f5a45301a0500000000000000000000000000000000000000000000000000000000000000000000000000071c304354606a767a7a75685f4f4232200f00000000000000061b30455b70859ab0c5dadeccbbafaab1b6c2b8b3aeb4bbc8d8d8c8b5a3907b65503929170300000000000000000000000b20354a60758a8a75879cb1b49f8a755443301c0800000000000000000000000000000000000000000000000000000000000000000000000000000000000e19202a34373a37342b1d150700000000000000000000000f1f2d3639362d363939363936363a36353a37353936393639383938363335383936363a37373a39352c1f0f000000000000000000000000000000000000000000000000000000071d32475c72879cb1c7dcdac5b09a858a989faaaaaaa8a098897b655c4a3928160300000000091f34495e74899eb3c9decdb8a28d78634d38230e0000000014293e53697e8d788499a28d78624d382314293f54697e94a9bed3c9b49f8a745f4a2715192e43596e8398aec3d8c6b09b86715b46311c060004192e43596e8398aea5aab7c8b39e897f7f808182838484848484858687898a8c8d9ba3b4c8d5c0aa95806d615746321a0a00000b20364b60758a82798ea4a7927d67523d2814293e54697e9397836e5645321e09000000000000000000000000000000000000000e23384d63788d86758ba0b09b86705b46311b0600000000000000000000000000000000000000000000000000000000000000000000000005182a3b4a60727f8a8f8f897d69604f3e2d1a07000000000000061b31465b70869bb0c5dbeadaccc3bfc7c3b7a79e999faabbcee2d1c1ae99846f5746331e0a0000000000000000000000071c304354748a8b75869bb1bcab8a75604b35200b000000000000000000000000000000000000000000000000000000000000000000000000000000000000050d181f22252220190d000000000000000000000000071a2d3d4a4e4a3e4a4f4e4a4e4a4c504b4a4f4d4a4f4a4e4a4e4d4e4d4c46494e4f4a4b504c4b4f4e493d2c1c0c0000000000000000000000000000000000000000000000000000081d33485d72889db2c7ddddc8b4a29a9fa9b4bbc8bfbfb2a79e8a7a645746321e0c000000000a1f34495f74899eb4c9ceccb7a28d77624d38220d0000000013283d53687d8d778499a18c77624c372214293e54697e93a9bed3c9b49e89745f49341f182d43586d8298adc2d7c5b09a85705b45301b060003182e43586d83989c8f99aac2ac97826d6a6b6c6d6e6e6f6f6f6f70707274757778859bb0c5cfbaa5907a655046392916000000081d314455738884778caaa8937e69533e29192e44596e83999f8a76604b36210b000000000000000000000000000000000000000e23384d63788d85768ba0b19c86715c47311c070000000000000000000000000000000000000000000000000000000000000000000000000b1f3448596b80949fa9a79e927e695c4a36210f000000000000071c31465c71869bb1c6dbf0eaded7d8c8b7a59d89848b9fb4c2d3dfc9b49f8a76614c36210c00000000000000000000000013254a5f74898b76859bb0b5a08b76604b36210b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b0d100d0b05000000000000000000000000000d21364a5c645c4d5c64645c645c61656160656260645c645c6363646361585b63645c6065615c64635b493a29170400000000000000000000000000000000000000000000000000091e33485e73889db3c8dde4d1c0b4b0b4bac7ced8d5cfc5b8a89d8775614b3a2a18040000000a1f354a5f748a9facb1bdceb7a18c77624c37220d0000000012273d52677c8c77849aa08b76614b362113283e53687d93a8bdd2c8b39e89735e49341e172c42576c8197acc1d6c4af9a856f5a45301a050002182d42576d8297867a8fa5baae98836e5956575758595959595a5a5b5d5560616d8297acc2ceb9a48f79644f3a291b0b000000021527375c718686758a9faa957f6a55402a1b30455a70859aaa8e79634e39240e000000000000000000000000000000000000000e23384e63788d85768ca1b29d87725d48321d080000000000000000000000000000000000000000000000000000000000000000000000000d22374c62778b9fb4bab8b39f8c7a644e3d2c1a060000000000071c32475c71879cb1c6dcf1fbf7e2cebbaa9d87786e7d92a4b6cadecebaa9917c67523c27120000000000000000000000001f34495e74898c76859aafb6a18b76614c36210c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f24394e6479645f677979647964767a76757a78747964796579787978766165797968757a77697a79635847331f0a00000000000000000000000000000000000000000000000000091f34495e74899eb3c9dee2ded1c8c5c9cdc9c6c9d2e0d5c6b7a596806b5947341f0a000000081c304354758a9f979fb1c4b6a18c76614c37210c0000000012273c52677c8c77849aab8a75604b352012283d52677d92a7bcd2c8b39d88735e48331e162c41566b8196abc0d6c4ae99846f59442f1a040002172c42576c819784788da2b7ae99836e59444142434444444445454637444b576c8297acc1ceb8a38e79634e39240e00000000001a2f455a6f848975869cac97816c57422c1b30465b70859ba6917c66513c2711000000000000000000000000000000000000000e23394e63788e84778ca1b39d88735e48331e0900000000000000000000000000000000000000000000000000000000000000000000000012273c52677c91aabbcdccbbaa99836f5b4935210b0000000000081d32475d72879cb2c7dcf1feead8c8b49f8c7a646073869cb1c7dcd8c7ac96816c573625130000000000000000000000091e34495e73898c77849aafb6a18c77614c37220c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090b0d0b08010000000000000000000000000003182d42586d826d677d807f78826d7f7d82807c8278836e827b817e837f7a657a817f7d7d7d847e7b8076614c37210c000000000000000000000000000000000000000000000000000a1f344a5f74899fb4c3c7d0dde4ddd4c6b9b4b1b5c2cbd9d4c3b49f8a77614c37220e0000000b20354b60758a8b8197acc1b5a08b76604b36210b0000000012273c51677c8d7784999f8a755443301c12273c51677c91a6bcd1c7b29d88725d48331d152b40556a8095aabfd5c3ad98836e58432e19030001172c41566c819683798ea3b8ae99846f59442f2d2e2f2f2f2f2f3031263142576c8297acc1cdb8a38d78634e38230e0000000003182d43586d828d798297ad99836e5936261431465b71869ba9947f69543f2a14000000000000000000000000000000000000000e24394e63798e84778da2b49e89745f49341f0a00000000000000000000000000000000000000000000000000000000000000000000000012283d52677d92a7c3d3d8c8b59f8c79634e3929170300000000081d32485d72879db2c7dcf2f7e2cebbaa97816c5c546a8095aac4d5dbc5b09b86705443301c0700000000000000000000091e33485e73888d788499aeb7a28c77624d37220d0000000000000000000000000000000000000000000000000000000000000000000000000000000000040a151d2022201c140800000000000000000000000004192f44596e847f7c8082827e826d7f8178826d7d7c846f827f7975837f7a697e7a72827c817a8281837c67523d271200000000000000000000000000000000000000000000000000081d314455758a9fb3aeb3bfd0e5d4c3b7a89e9ca4aebbcbe1cdbaa9947f6a553c2b190500000b20364b60758b86738aa0b5bcab8a75604b35200b0000000011273c51667c8d7884999f8a745f4a261411263b51667b90a6bbd0c7b19c87725c47321d152a3f546a7f94a9bfd4c2ac97826d57422d18020001162b40566b8095817a8fa5baaf9a846f5a452f1a19191a1a1a1a1b1b142d42576c8297acc1ccb7a28d77624d38220d0000000001162b40566b809582859bab9c86715443301c31475c71869cab96816c56412c17010000000000000000000000000000000000000f24394e64798e83788da3b49e89745f49341f0a0000000000000000000000000000000000000000000000000000000000000000000000000f24394e64798ea5b6cadfcfbcab97826c5746331e0a00000000081e33485d73889db2c8ddf2f4dfcab49f8b78624d4e63798ea6b8cbdec9b49f8974604a35200b00000000000000000000091e33485e73888d798399aeb7a28d78624d38230d000000000000000000000000000000000000000000000000000000000000000000000000000000000c171f283236373530261815070000000000000000000000182d42586d826d8278828278837f80817e7b81817586828078817f817f7a697e796d827c81807a818277624c37220d000000000000000000000000000000000000000000000000000b20364b60758ba89e99a1b3c7d8c7b7a59d8a86949daec6d7d7c7b19c86715a4835200b00000c21364b61768b85768ca1b6b59f8a75604b35200b0000000011263c51667b8e7883989f89745443301c10253b50657a90a5bacfc6b19c87715c47321c14293e54697e93a9bed3c1ab96816c56412c17010000152b40556a8095807b90a6bbaf9a85705a45301b0504040404050500182d42576d8297acc2ccb6a18c77614c37220c000000000014293e54697e938a808c9f9f8975604b352032475c72879cad97826d58422d18030000000000000000000000000000000000000f24394f64798e83798ea3b29d88735d48331e080000000000000000000000000000000000000000000000000000000000000000000000000d22364a5c72879db2c6d6dac9b49e8a76614c36210e00000000091e33495e73889eb3c8ddf3edd8c3ae98836e5a484a5b73889eb3c8ddcdbaa98c77624c37220d0000000000000000040a0c1e33485d73889983899eb3b8a38d78634e3823100b07000000000000000000000000000000000000000000000000000000000000000000000000010f1c2a3338454b4d4b4336332515070000000000000000000a162b40566b80807c676d6d626e6a6b6c69666c6c61716c6b626c6a6d7f7a667c78697e696c6a646c6c625947341f0b000000000000000000000000000000000000000000000000000c21364b61768b9e8a8399aec3cebaa99d8778717f94a8bacddec9b5a48d78624d38220d00000c21374c61768c84778da2b7bcab8b76614b36210c0000000011263b51667b8e7982989f8a75604b35200f253a4f647a8fa4b9cfc6b19c86715c47311c13283d53687d92a8bdd2c0aa95806b55402b16000000152a3f556a7f94807c91a6bbb09b85705b46301b0600000000000002182d42576d8297acc2cbb6a08b76614b36210c000000000011263b50667b908a76849aa98d78624d382332485d72879dae98836e59432e19040000000000000000000000000000000000000f253a4f647a8f82798ea3b19c87725c47321d07000000000000000000000000000000000000000000000000000000000000000000000000071b2d3e54697e93a8b9cce1cdb9a8937e68533c2c1906000000091f34495e74899eb3c9def3e7d2bda7927d68523c3d5b70859ab0c5dad7c7a48f7a644f3a250f000000000001080c181f222533485d7388927e869bb0b8a38e79634e392c26201c130800000000000000000000000000000000000000000000000000000000000000000002101f2d3a474c5660626054504333251500000000000000000a1a28323650626b6b675f58584d59545657535157574b5c57564d57546169645e666361696156554f56574c473b2a1805000000000000000000000000000000000000000000000000000c22374c61778c9883798da3b8c5b49f8b7a6461768a9fb4c9ded2c2a7927d67523d281200000c22374c61778c83798ea3b8b5a08b75604b36200b0000000011273c51667c8f798297aa8c77624c37220f24394e64798ea3b9cec6b19c86715c36251312273d52677c92a7bcd1bfa9947f6a543f2a15000000142a3f54697f947f7c91a7bcb09b86715b46311c0600000000000003182d42586d8297adc2cebbaa8a75604b35200b00000000000d22384d62778d9a85889ea6917c66513c2633485d72889dae99846f59442f1a0400000000000000000000000000000000000010263b50657b90837b90a5b09b86715b46311c06000000000000000000000000000000000000000000000000000000000000000000000000001021364b6176899eb4c9ded7c6b09b86715a4935200c0000000a1f344a5f74899fb4c9def4e4cfbaa48f7a654f3a42576c8297acc1d7d0bba5907b66503b26110000000008141c202a33373a3d375d7288907b849aafb9a48e79644f45413b353025180e000000000000000000000000000000000000000000000000000000000000000110202d3d4a58616d7577746a615043331b0a00000000000002162838454b575a5e5b554e493d38433f40413e3b4142364642403842434f544f4c514d4f544f42403a414237342a1d0d00000000000000000000000000000000000000000000000000000d22374d62778c9882798ea3b9b8a7957f6a5c576e8399aec3d9d6c1ac96816c57412c1700000d22374d62778c82798fa4b9bbaa8a755544311d080000000012273c52677c8f7a8197a48e79644f39240f23384e63788da3b8cdc8b29d88735443301c11273c51667c91a6bbd1bea8937e69533e291400000014293e53697e937f7d92a7bcb19c86715c47311c0700000000000003182e43586d8398adc2cab49f8a755544311d0800000000000b2035485a74899e9a9ea6aa95806a55402b33485d73889dae99846e59442f190400000000000000000000000000000000000012273c51677c9189879db2af9a85705a45301b05000000000000000000000000000000000000000000000000000000000000000000000000000a1e3246576c8297acc1d2ddc9b5a38d78634d38230e000000071c304354758a9fb4cadff4e2cdb8a28d78634d3840566b8095abc0d5d0bba6917b66513c261100000008182630353a474c5053555572889d909aa2b4baa48f7a655d5b57504a43362c1e0e0000000000000000000000000000000000000000000000000000000000000f1f2d3e4a5b6376828a8c897f6a6150392816030000000000091e324556606c6f73706a635b534c473b4038454b453839373435313538353f39363c383b3e3b322b252c2d221f180d0000000000000000000000000000000000000000000000000000000d23384d62788d97827a8fa4b9b39e8875604b53697e93a8c7d7dac5af9a85705a37271501000d22384d62778d827a8fa4bab49f8a745f4a2715020000000012273d52677c907a8196a6917c66513c271123384d62788da2b7cdc9b49f8a75604a352011263b50667b90a5bbd0bca7927d67523d281200000013283e53687d937f7d92a7bdb29c87725d47321d0800000000000003192e43586e8398adc3c9b39e89745e49271501000000000005192b3c5a70859aafb3b8ae99846f593c2c33485d73889dad98836e58432e190300000000000000000000000000000000000013283d52687d92827a8fa4ae99846e59442f190400000000000000000000000000000000000000000000000000000000000000000000000000031629394f64798ea3b5c9ddd2c1aa947f6a553b2a180500000b20354a60758aaabbcee2f7e0cbb6a08b76614b3640556a7f95aabfd4d1bba6917c66513c2711000008182636434b53586165686a6d73899ea5afb4c0bda8937e7472706c656054493c2c1909000000000000000000000000000000000000000000000000000000000d1d2c3d4a5c647987989fa89e947f6a5745321e0900000000000b21364b60768285888580797169615956564c5660564d4f4d484b44494e4a484d4c46393e35404337342a1d0d0b05000000000000000000000000000000000000000000000000000000000e23394e63788e96817a90a5baab96816c56454e64798ea9bacdddc8b39d88735544311d08000e23384d63788d817a8fa5bab49e89745f49341f000000000013283d52687d907b8096aa957f6a55402a1522374d62778ca2b7cccdbaa98d77624d382210253b50657a90a5bacfbba6907b66513b261100000013283d52687d927f7d92a7bcb29d88735d48331e0800000000000004192e43596e8398aec3c8b39d88735e48331e00000000000000162b40566b8095abc7c8b39e88735b493533485e73889dac97826c57422d170200000000000000000000000000000000000014293e53697e93878298adac96816c57412c170200000000000000000000000000000000000000000000000000000000000000000000000000000b22364a5c71869bb0c6dbdbc6b09b86715947341f0b00000b21364b60768ba0b5d9ebf7e2cebbaa8a75604b353f54697f94a9bed4cfbaa5907a65503b251000011426364354606871777a7d8082869ca8b9c5c8d1c1ad9c938a8785817b72625a493727150100000000000000000000000000000000000000000000000000000a1a2a3b495b647a8a9da5b4b9b49e8976604b36210b0000000000091e324556606c6f777f898e867e77706c6b616376675f64625960555b63605962615758544b56584c473b2a190900000000000000000000000000000000000000000000000000000000000f24394e64798e96807b90a5bba5907b6650384b60758a9fb4c9dfcab49f8a75604b35200b000e23384e63788d817a90a5bab39e89735e49341e090000000013283e53687d927d8197ac99836e593b2b1822384d62778da2b7ccd7c7a5907b66503b2611263b50667b90a5bbd5c4a38e79644e39240f00000012273c52677c917f7c92a7bcb39e89735e49341e0000000000000003192e43586e8398adc3c7b29d87725d48321d0800000000000011263c51667b91a9bacbb8a68d78634d382a3b5e73889daa95806a55402b1500000000000000000000000000000000000000152a3f546a7f949c98a0b2a9947f6a543f2a15000000000000000000000000000000000000000000000000000000000000000000000000000000071b2d3e54697e93a9c2d3dfcab59f8b77624c37220d00000c21364b61768ba0b6cbe0f4dfcab49f8a7554433040556a8095aabfd5d5c5a38e79644e39240f00081c30435460727d868c8f9295989ca4b6c6d6dcddcbbaada99f9d9a96908578625544311d08000000000000000000000000000000000000000000000000000818283847596379899ea8b6c3cdb9a88d78624d38230d000000000002162838454b5759616976808a938a8581807679887d697977667567677872647776616e69606b6e61594737271c13080000000000000000000000000000000000000000000000000000000f243a4f64798f95807c91a6c6a28d77624d38445571879cb1c6dccfbcab8c76614c37210c000e24394e63798e817a90a5bab39d88735e48331e090000000014293e53697e9388899eb29d87725948342023384d63788da2b8cdd5bfaa95806a553b2a18263b51667b90a6bbcbb8a68b76614c36210c00000011273c51667c917f7c91a6bcb49f89745f4a27150200000000000003182d42586d8297adc2c6b19c86715c47311c070000000000000c21364c61768a9fb4c9c4a8927d68533d34475974899fa8937e68533e291300000000000000000000000000000000000002172c41576c8196acadb2bea7927c67523d2712000000000000000000000000000000000000000000000000000000000000000000000000000000001023384d62788da4b6c8cccfbcab927d67523d281200000c21374c61768ca1b6cbe0e7dec9b49f897456453241566c8196abc1d6ccb8a78c76614c37210c000b20354b607283929ba3a5a8aaadb1b6c2d3e4f4e8d8cbc7bab4b2b0aca39b8774604b35200b0000000000000000000000000000000000000000000000000013253645566277879da7b8c6d4c6b49f8a75604b36200b0000000000000a1a2832363b474c58616b777e8a948a7f70859a887e8a857b897d7d8a8079898477837e75808377615544353025180a000000000000000000000000000000000000000000000000000010253a4f657a8f947f7c92a7baa88a75604b35375a6f8499afc4d9d9b7a28c77624d37220d000f24394e64798e817a8fa4bab29d88725d48331d080000000014293f54697e917c8095aaa58c77624c372224394e64798ea3b9cedac5b09b85705947341f273c51667c91a6bbc8b39d88735746331e0a00000011263b51667b90807b91a6bbb59f8a755544311d0800000000000002172d42576c8297acc1c5b09b86705b46311b060000000000000a1e3346576f849aafc7c2ad97826d583e374c61778ca8a5907a65503b251000000000000000000000000000000000000004192e44596e8399aec2c6c7a48f7a654f3a2510000000000000000000000000000000000000000000000000000000000000000000000000000000000b2035495a71879cb1b3b8c5c9ad97826d583a2a1704000d22374c62778ca1b7c8cbd5e1cdbaa98b76604b3636586d8398adc2d8c8b39e89735847331f0a0011263b51667b90a1b1b5c1bdbfc2c6c9d3e0f0fff6e8e5d7cdc9c7c5c1b4a58f7a654f3a2510000000000000000000000000000000000000000000000003111c3043546074859ba5b7c5d5cdb9a898826d5645311d09000000000000000a161e212a343a4a5b657b86867f776a6c819684949c86898a89888885869c89888985858281857360534a4336281a0a0000000000000000000000000000000000000000000000000010263b50657b90947f7d92a7b49f897455443143586d8398adc2d8ccb7a28c77624d37220d000f243a4f64798f82798fa4b9b29d87725d48321d0800000000152a3f546a7f9484859bb0a7927c67523625263b50667b90a5bbd0dfcab59f8b77624c3722293e54697e93a9bec4af9a856f5a3929170300000010253b50657a90817b90a5babcab8b75604b36200b00000000000001162c41566b8196abc0c5af9a85705a45301b050000000000000317293953697e93a9bac7b29d87725c4a3b50667b90a5a68c77624d37220d000000000000000000000000000000000000011426375b70869bb0c5cdbaa98d78624d38230d0000000000000000000000000000000000000000000000000000000000000000000000000000000006192b3c566b8096a79ea7b3bfb19c87725847331f0a000d22384d62778da2b2b3b8c4d5d7c7a28d78624d38435471869bb1c6dac5af9a85705a3a2917040013293e53687e93a8bdc8ccd5d3d5d7dee1e9f5fffff1e6dfd9cecac9bcb4a18d78634e38230e0000000000000000000000000000000000000000000001112131414a60728298a3b4c3d4d1c0b49e8a78624d38271502000000000000000002090c1823394e63798a7b70827e69647a8e878298838697828b917c889882889580888975817e72686054453828160300000000000000000000000000000000000000000000000011263b51667b90947f7d92a7b29d88735d372742576d8297acc2d7cfbcab8c76614c37210c000f253a4f647a8f82798ea3b9b19c87725c47321d0700000000152a40556a7f959a9ba3b4ac97826c544330283d53687d92a8bdd2cec5bcab927d68533b2b2c41566b8196abc0c9ab95806b56402b160000000010253a4f657a8f817a8fa5bab6a08b76614b36210c00000000000000152a3f556a7f94aabfc4ae99846f59442f1a04000000000000000c22374c61778a9fb4c9b7a58f7a644f3d556a8095aa9e8873594834200b000000000000000000000000000000060c0e151d31445573889db2c8c9b49f8a75604b35200b000000000000000000000000000000000000000000000000000000000000000000000000000000000010253b50657b909e8999a1b3b59f8b76614c37210c000e23384d63788da59d9da6b8cbcfbaa48f7a654f3a4b6074899fb4c9d7c7ab96806b56412b1600000f253a4f647a8f9faeb3b8c5bdc0c2c9cdd7e4f5f1e1d3cac8bbb4b1ab9f97836e5b4935210c000000000000000000000000000000000000000000000f1f2e3f4e606b8095a0b2c1d1d6c6b4a2937e695a48341a0a00000000000000000000000014293f54697e897571868978656e83947f878c7e8a897f94837b8c8a7c8b897d8b818593877e72605645321e1000000000000000000000000000000000000000000000000011273c51667c91947f7c92a7b19c87715c473242586d8297adc2d7cab59f8a75604b35200b0010253a50657a8f83788ea3b8b19c86715c47311c0700000000162b40556b8095aab0aa9faa9d8773604a352b40556b8095aac0cebdb1acaf99846f5948342839596e8399aec3bcab917c66513c2711000000000f243a4f64798f82798fa4b9b6a18c76614c37210c0000000000000013283e53687d93a8bdc3ae98836e59432e1904000000000000000a1f3347586d8298adbec3ad98826d5b495a70859aae99846f593b2b180500000000000000000000000000010f1a21232a2d354b60758a9fb4cac6b19c86715544311f170c000000000000000000000000000000000000000000000000000000000000000000000000000000000c21364c61768b8d798399aebcab907a65503b2510000e23394e63788e9d87889db3c8d4bea9947f6954394f64798ea9bacdcdbaa9917b66513c261100000d22374b5c6c8190999ea7a6a8aaadb4bac6d7e9e6d3c3b6b2aa9f9b968c8174604b3d2c1a060000000000000000000000000000000000000000000c1c2c3d4b5d687e929eb0becfe1ccb9a89a8473604b3c2b190000000000000000000000000011273c51667c917d677d92877b6f788a897d92877e9383828a7a7f94837d928480937e7f86918374604b3e2e1b07000000000000000000000000000000000000000000000012273c52677c91957f7c91a7b09b86715b463143596e8398aec3d8c9b39e89745544311d080010253b50657a9084788da2b8b09b86715b46311c0600000001162b40566b8095abb49f8a9da5907b65503e2d3d5a6f8499afc4c7b19f979f9f8b78624d3732455771879cb1c6b59f8b77624c37220d000000000e24394e63798e83798ea3b8b7a18c77624c37220d0000000000000011273c51667c91a6c9c2ad98826d58432d18030000000000000004182a3a4f647a8ea0b2c4b49f8c79635662788c9fa9947f6a543f2a150000000000000000000000000002101f2c35384043364d62778caabbcec3ae99836e593737332a1c160800000000000000000000000000000000000000000000000000000000000000000000000000000a1f3346587287957f7b90a6b7a8937e68533e2913000f24394e64798e927d7f94aabfd4c4af9a846f5746556a7f94aac7d7c9b49f8a76604b36210b0000081b2e3e52636c7b83888d909395989fa8bacde1dfcab6a59c908a8681796c605645321f0f0000000000000000000000000000000000000000000a1a2a3a495b657b8c9fb4bccddccdbcb49e8a78625443301d0d000000000000000000000000081c2e3f4b60758889786c819790847b809580818877817f7686898486907b80867686877e797c89826d5c4a36220d000000000000000000000000000000000000000000000012283d52677d9295807c91a6b19c86715c3b2b3a5a70859aafc5dac7b19c87725c372614010011263b50667b9084778da2b7b09b85705b46301b0600000001162b40566b8095abac9781879d98836e5c4a36495b73889eb3c8baa9978297a3957f6a5544364b60768a9fb4c5b09b86705948341f0b000000000e23384e63788d83798da2b8b7a28d77624d38220d000000000000000f243a4f64798fabbcc1ac97826c57422d170200000000000000000c22364a5c6e8398a6b7bbaa9c8674686e8298aba28e79634e39230e0000000000000000000000000010212e3d494e55585a54647a8fa4c8d9c0ab95806b56504c473a34261600000000000000000000000000000000000000000000000000000000000000000000000000000417293a596e83988875889db2ab96816c56412c17000f243a4f64798f917b8095aac0d5c9b49f8a76614b5b70859bb0c5d4c3ae99836e5745321e0900000010203445525e666e73787b7e80828a9fb4c9dedcc7b29c877b76716b635b4b453828150100000000000000000000000000000000000000000215283847586379899eaabbcedad0c0b09e927d675a49362614000000000000000000000000000e23374b5d65777e93867675858b879089988b7e7e7b7a6a61767e787586877679887b848275677b8b79644f3a240f000000000000000000000000000000000000000000000013283d53687d9296807b90a5b39e8873594834465873889db2c8d9c4ae99846f59442f1a000011263b51667b9085778ca1b7b09a85705b45301b0600000001162b40566b8095abab907b7f959f8c7a644e434e63788da7b8c9b49f8a76859b9d8774604b3e4f657a8faabbc0aa947f6a553b2a1805000000000d22384d62778d888399aec3b7a28d78624d38230d000000000000000c21364c61768b9fb5c0ab96816b56412c16010000000000000000071b2d3e4c6177889da8b9b5a49b857d8298a0ab9a85705b4935210c000000000000000000000000081b2e3f4b5b636a6d6f71738095aac0d2bca7927d6b686561585144341d0d0000000000000000000000000000000000000000000000000000000000000000000000000000152a40556a7f958e798297acae99836e59442e190010253a4f657a8f8f7a8196acc1d6cdbaa9947e695963798ea3b4c8cab6a5917c66513928160300000002172734404c51595b6366686b6d8297adc2d7d4bfaa947f6a6157564e493d32281a0a000000000000000000000000000000000000000004121d3245566176879ca7b8c8d8d3c3b3a296806b5f4d3c2b18080000000000000000000000000010253a50657b88738195877b7a8b747b7f828b9486868578706b686263798a81778986726d615d6d827c67523c2712000000000000000000000000000000000000000000000013293e53687e9396817a90a5b8a68c77624c374c61768b9fb5cad6c5aa957f6a55402a15000011273c51667c9185768ca1b6af9a856f5a45301a0500000000162b40556b8095aa9f8b76778b9f9a8470614b55697e93a9c5c1ae99836e7d92a5937e685c4a566b8095aac8b3a28d79634e38230e00000000000c21364b61768b867d92a7bdc8a28d78634d38230e000000000000000a1f33465873889db2bfaa957f6a55402a1500000000000000000000101f344759647a8a9ea7b5b5a39b9298a0b49f8c7a644f3d2c1a060000000000000000000000000e22374b5d65797f82848689959eafc3d6c5af9a84817e7b776c62513b2b18050000000000000000000000000000000000000000000000000000000000000000000000000013283d53687d92947f7c91a6b09b85705b46301b0010253b50657a908e798298adc2d7d7c7b39e8877626f8399aec1d1c2b29d8774604b35200b00000000000917222f383b3c494d5153576c8196acc1d6d4bfa9947f6a54463939352c1d150a000000000000000000000000000000000000000001122233434b6074849aa5b4c1d1d6c6b6a59a8473604b41301e0e000000000000000000000000000c1d2a43586e83927d73808b908c806b666a6d7d92807983868581786860687e826d7b816c544b4f647974604b362112040000000000000000000000000000000000000000000014293e54697e9397827a8fa4c5a6917c67513c50667b90abbccfccb8a78f7a65503a2510000012273c51677c91877c91a6bbaf99846f5a442f1a0500000000162b40556b8095aa9c87726d8297a2947f6c616074879cb2c8b5a3917c6674879d9e8a7a645c6075889eb3c1af9a846f5b4935210c00000000000a1e3246577489867a8ea4b9bbaa8c77624d37220d000000000000000417293a5a6f8499afc1a8927d68533d28130000000000000000000004182a3b4b5c657b899ba3b2b5b0a8adb4a396816c5c4a361f0f0000000000000000000000000010253a4f657a8c95989a9c9ea8afbcbfc1c3b4a29a9693908b806c594834200b0000000000000000000000000000000000000000000000000000000000000000000000000011263c51667b919883788eaab29d87725d48321d0011263b50667b908d788399aec3cac7bfb8a79a84777f95a1b3c7c8b5a4937e685544311d0800000000000004121c24262c35383b41566c8196abc1d6d4bfaa957f6a55402823211a0f020000000000000000000000000000000000000000000f1f304050616d8298909ba3b4c8c9b9a89c87766155443123130000000000000000000000000004182a3b4752677d9288766b797f7d737b72605f697e7b807c7d838b8b7e6874827560656c6251464b5c646056483b2f221202000000000000000000000000000000000000000000142a3f54697f949883798ea3b9ac97816c573f566b8095abc9dac8b39e8974604b35200b000012273d52677c92898399afc3ae99846e59442f190400000000162b40556b8095aa98826d62788a9f9f8d8176748095a5b6bbaa9b857360687e93a39d887a6e6e8095a6b8b5a3907b65503d2c1a060000000000031629395c71869b8e98a9c8b49f8a75604b36200b000000000000000013283e53687d93a7b4a38d78634d38230e00000000000000000000000c1d2e3e4b5d657985939da6a9aaab9f978475614b3e2e1b01000000000000000000000000000b21364b6074828c93999da5a4a6a8aaacaeafb0afaba8aa9f8c77624d37220d000000000000000000000000000000000000000000000000000000000000000000000000000f243a4f64798f9b86758a9fb39e89735e49341e0011263c51667b918d788499aec3b6b2aaafb4a29a8b959eafbfcebbaa9c8673604b372715010000000000000000090f111921232c41566b8196abc0d6d5c0aa95806b55402b160c06000000000000000000000000000000000000000000000b1b2c3d4c5e6a7f958a7b859bb0c5bcab9e8a7963584737261405000000000000000000000000000b1f344759616a708496816c636a697f8a806b61757a676a78746e7884927d7e927d676161584c5761686b6962594c402f2010000000000000000000000000000000000000000000152a3f556a7f949983788da3b8b29d87725d4b5b71869cb1c6d2c1ac97826c5544311d08000012273d52677c9286768ba0b5ae98836e59432e190400000000162b40556b8095a8937e695a6b8095a29f968a88959eafbcb49f8c7a64546073859ba69d8b83838d9fb5baa99b85705d4c381f0f00000000000000152a3f556a7f94a5a9b6b9aa9a846f5645321d0900000000000000000c21364b6176899ea99b85705a4935200c00000000000000000000000010202e3f4b5b63737e878f9395928b81756157463220100000000000000000000000000000091e324556606d787e83878b8e91939597999a9b9c9c9c9b988975604b36210b000000000000000000000000000000000000000000000000000000000000000000000000000d23384d62788d9d8873899eb39e89745f49341f0012273c51677c918d778499aeb6a59c949dafb4ab9fabafbccfbdb49f8c7b655544311909000000000000000000000000060c162b41566b8096abc0d5d6c0ab96816b56412c16010000000000000000000000000000000000000000000008182939495b667c8d8c7c7a8a9fb4bfb59f8d7c665b4a3a2a190900000000000000000000000000000c22374c6177807678898c7c665b738888847f6d82897c7b8a806a7a80848b7d8d89777677665e61757d807e77665e4c3e2d1b070000000000000000000000000000000000000000152b40556a80959b857c91a6bbb6a58f7a655563798ea4b6cac9b5a38f7a644f37261401000011263c51667b918c8499afc2ad98836d58432e180300000000152b40556a8095a38e78634e6074849aa3a99f9ea6afb9b49e947f6a5c4b5563798a9eaa9f99999fabbcb49f8a79634e3f2f1c01000000000000000c22374c6177879ca5a8a79e8b7a644f3828150200000000000000000a1e334657677d8c918a7a644f3c2c19060000000000000000000000000211212e3d49556068737a7e7f7d776c61574639281602000000000000000000000000000002162838454b5a62696e7276797c7e808183858686878786827a645745321e09000000000000000000000000000000000000000000000000000000000000000000000000000d22374c62778c9e8973889db29f8a755f4a35200012273d52677c928c77849aafb29c877f949fb1bcb5bcc9c9bcb59f947f6a5d4b372715000000000000000000000000000000162b40556b8095aac0d5d6c1ac96816c57412c1702000000000000000000000000000000000000000000001325364657637989937e78889ea9bab2a195806a5e4c3d2d1c0c0000000000000000000000000000000d22384d62778d88807f8a8979666c81947f847f8d84868689857e8688838985829885898a7c667285808088897c665c4a36220b0000000000000000000000000000000000000000162b40556b80959e89849aafc5c3b09b8573606e8399aec2d1c1b09b85715d4b37190900000010253a50657a8f9f99a1b3c6ab96816c56412c17010000000012283d52677d929b86715b495661768599a1b0b3b7b2a89e92806b614f3e4a5b667d8c9ea7aeaeb5b6b29f937e695b4936211100000000000000000a1f334758637987909391897c665c4b371a0a000000000000000000031729394d5f67797c78645c4a361e0e000000000000000000000000000003111f2c37444b546065696a6862594b4639291b0b000000000000000000000000000000000a1a28323c484d545958616467696a6c6e6f70717172706d645c4a39281603000000000000000000000000000000000000000000000000000000000000000000000000000d22374c62778c9e8973889db29f8a755f4a35200013283d53687d928c77849aafb09b857381979fb0b5c1bcb4ab9f95816c614f3f2e1909000000000000000000000000000000152a3f556a7f94aabfd4d7c1ac97826c57422d17020000000000000000000000000000000000000000010f1c304354617586968176869ca6b8b5a4998372604a40301f0f000000000000000000000000000000000b2034485a6a7f868a8e9196887c7979898978858a8b7d879a84848a88808a9580889883858a787a8f7c7d77838a7a644f3929170300000000000000000000000000000000000000162b40566b80959984788da3b8c9b5a39680737f94a1b3c7c7b4a3917c67513f2e1b000000000c22374c61778ca2afb3bfb9a8927d68533d281300000000000c21364c6176898a7b65503d4758617583929b9fa69d968a7e6b625143323d4d5e667c89989fa9a5a59c92816c604f3d2c1a03000000000000000004182a3a4a5b63747b7e7c76665e4c3e2e1b00000000000000000000000b1b30414d5b6367625a4a3e2d1b00000000000000000000000000000000010f19273136434b4f5455534d483b32291b0b0000000000000000000000000000000000000a161e2b35383e3a464c4f51535557595a5b5c5c5c5b584f4a3e2d1b0a00000000000000000000000000000000000000000000000000000000000000000000000000000d22384d62778d9c8774899eb49e89745f49341f0013293e53687e938d778499afaf9a856f7281919ba3a5ab9f9a8d7f72604a433221100000000000000000000000000000000014293e54697e93a9c7d7d5c0aa95806b55402b160000000000000000000000000000000000000000000f1f30404a6072839984748399a4b6b8a79c8675615443302212010000000000000000000000000000000005192b3c50616a7175797c808d9086868999877e849a87798795808497827e93897f94897e86837e939092827484846f5746331e0a00000000000000000000000000000000000000162b40566b80959e89849aafc4d2c1b09e9688949daebfcebaa99b85705f4d392010000000000a1f34475970859aa9b6b7b29e8975614b36210c00000000000a1e334657637978655d4b373a475761727d858a8b88817868605144332530404d5e6678828a8e908d877d6c635142321f0f000000000000000000000c1c2d3d4a556066696761584c402f20100000000000000000000000001323303d494e514d483c2d201000000000000000000000000000000000000009151d2630353a3e403d37342b1e160b0000000000000000000000000000000000000000020e19202229293336393c3e4042444546474747464339362d20100000000000000000000000000000000000000000000000000000000000000000000000000000000f24394e64798e9b86758ba8b39e88735e49331e0014293e54697e938d788499aeae99846f606d7c868d908f8b847a6a605443302515020000000000000000000000000000000011273c51667c91a9bacdd0c0a8937e68533e291300000000000000000000000000000000000000000b1b2c3d4c5e6a809588778095a1b3bbaa9e8978635746362513040000000000000000000000000000000000000d1d33435055566063666b7e8c86777383917c7684978278878c7d84937e7f9486818a847f947f94868385707a8c76614b36210c00000000000000000000000000000000000000162b40556b8095a79e9aa2b4c7c4b8bdb0a69da6aebbcbbdb49f8b7a644e41301d020000000004182a3a4f647a8b9ca4a69d927d675746321e0a000000000003172939495b63635b4b3f2e293946546068707575736c62594e423326162230404c5a626d76797a7872675f51443424140100000000000000000000000f1f2d37444b5053524c463a2f22120200000000000000000000000005131f2c36393c38352b1e1002000000000000000000000000000000000000000108141c2025292a282220180d030000000000000000000000000000000000000000000000050b0d14171f212427292b2c2e3031313232312d24221b100200000000000000000000000000000000000000000000000000000000000000000000000000000010253b50657a909782798ea3b19c87725c47321d00142a3f54697f948e788398aeae99836e595e6671787a7a776f645c4a433625130700000000000000000000000000000000000c21364c61768a9fb4bfc2b3a28e79634e39240e0000000000000000000000000000000000000008182939495b667c8d8c7b7c8d9fb5bcb49f8c7b655a493929180800000000000000000000000000000000000000001525333c38454b4e5160687b89887a77878a7a7584937e78878a7b858d798195808489838a8183908c7e69748978634d38230e0000000000000000000000000000000000000014293f54697e94a9b3afb4c0b4afa3b1b5b8b3b8c4cabcb09f937e695c4a3623120000000000000c22374b5c657b868b8c887d675f4d392916030000000000000b1b2c3d494e4e493d2e211b2936434a5254606056564d483b3124160812222f3c484d58616465635b524d4134261606000000000000000000000000010f192731353b3e3c3633291c12040000000000000000000000000000010f1a2123272220190e000000000000000000000000000000000000000000000001080b101415130d0b050000000000000000000000000000000000000000000000000000000000040a0c0f12141517191a1b1c1c1d1b180f0d07000000000000000000000000000000000000000000000000000000000000000000000000000000000013283d53687d92947f7c92a7af9a856f5a45301a00152a3f556a7f948e798298adad98836d584c515a62656561594f4b3e302518080000000000000000000000000000000000000a1e3346576b8095a1acada49a846f5b4a36210c000000000000000000000000000000000000001325364657637989947f78899eabbcb09e937e685d4b3c2c1b0b0000000000000000000000000000000000000000000715202828323639414e5d6578848b7f7989887875848c7c78878878817373857d77877786826e7b7c6960718674604b36200b0000000000000000000000000000000000000010253a4f657a8fa3b5c4c2b4a29a8e9ba3b4b9c6c2b6b19e95816c604f3e2d1a04000000000000071b2e3e4c5d6572767773675f4d41301b0b00000000000000000f1f2c353838352c1f110b1825303536434b4b453837342b1d13060004121e2b353a464c4f504d493c393023160800000000000000000000000000000009151d20262927211f170c000000000000000000000000000000000000060c0e120d0b05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000132536566b80958f7a8196acad98826d58432d1800152a40556a7f958f798297acad97826d58423c484d50504c473a372e1c130800000000000000000000000000000000000000031729394b607483909697938678624d3d2d1a070000000000000000000000000000000000000b1c304354617586998374859ba7b9b3a196806b604e3f2f1e0e0000000000000000000000000000000000000000000000030d0a151d2024313f4c5a6273808c857f8986777d89897a7a8985797a7e777262756175746066665e617779645544311d08000000000000000000000000000000000000000b20354b6073869ba6b1b1a49a847985959ea8a8a7a49c908072604a4232200f000000000000000010202f3f4c5058616259524d41302313000000000000000000010f1a212323211a0e000008131c202630353632282220190d00000000000e1920293336393b38352c251e1305000000000000000000000000000000000001080b1114120c0a04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090b0d0d0b07000000000000000000000000000000000000000000000000000000000001080b0c0d0e0c0b080200000000000000000000000000000000000000071c3043546f84998975879cb2aa957f6a55402a1500162b40556b80958f7a8197acac97816c57422b35383b3a37342a221b10000000000000000000000000000000000000000000000b1d324556606e7b81827e75625948341f0f0000000000000000000000000000000000000b1b2f404a6072839987768096a3b5b5a3998372604b4231211100000000000000000000000000000000000000000000000000000002090b13212f3c4855606a798592889c867779868f8382898d837f696055605660605550514d5961645c4a3727150200000000000000000000000000000000000000081d314455637988969c9c968676637480899093928e867c6b6054433024140100000000000000000211212f383a464c4c483b3a302313050000000000000000000000060c0e0e0c060000000000070b141c20201d150d0b0500000000000000050b171f2124252321190e0a01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080a151d202322201c13080400000000070d0f12100a010000000000000000000000060c0e14141d2022222322201d15170d0b050000000000000000000000000000000b20354a6074899983788da4b6a6917c66513c271100162b40566b8095907a8196abab96816c56412c20222525221f180c08000000000000000000000000000000000000000000000002152838454b5e666c6d696157483b2b19010000000000000000000000000000000000031729394c5e6a80958c7a7c8d9fb5b7a69b85756154433024130300000000000000000000000000000000000000000000000000000000000003111d2b37444b5b63707d88939a85707786877279887b69614a444b454b4b44373c3a474c4e4a3e2d19090000000000000000000000000000000000000000011426374a5b637781878780756158606a767b7e7d7971665e4a43362513060000000000000000000003111c2329333637342a251e13050000000000000000000000000000000000000000000000000001080b0b0902000000000000000000000000040a0c0f100e0c060000000000000000000000000000000000000000000000000000060c0e0f0b0903000000000000000000000000000002080b0d0b090300000000000000000000000000000000000000000001080b0d0e0e0b08020000000000000000000000000000000000000000000000000002101b2228323638373530251f180c0002101b222427251e13050000000000000000070f1a212329263135373838373631272c2220190e00000000000000000000000000000e24394e63798e917c7f95aab7a68d78634d38230e00162b40566b8095907b8096abab95806b56402b160d10100c0a0400000000000000000000000000000000000000000000000000000a1a2832404c515758534b46392b1d0d0000000000000000000000000000000000000a1e334657667c8d947f77899eabbaa99d8878625746362614060000000000000000000000000000000000000000000000000000000000000000000d1926313d4a4e5f67757e88806b6277806b637773604b4331353236353127272a343739362d20100000000000000000000000000000000000000000000009192d3d4a59626c72726b6157474b5761666968645c504c403025180800000000000000000000000000090c171f21221f180d0a0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090e19202324211e160a01000000000000000000000009151d2023211e160a0100000000000000000000000000000000050b0d141d20222323201d150e0c060000000000000000000000000000000000000000000715212e3738454b4d4d4a4336342a1d1010202e363a3c39302313040000000000010f1a212c35393f37444b4c4d4d4c4b44374238352b1e1306000000000000000000000006192c3c546a7f948975879db2b39d88735a4935200c00162b40566b8095927d8197acaa95806a55402b150000000000000000000000000000000000000000000000000000000000000000000a151d2f383b41423e3632291b0d000000000000000000000000000000000000071b2d3e4b617587998374849aa7b8ab9f8b7a645a4839291808000000000000000000000000000000000000000000000000000000000000000000000009141d2d36414d56606975726059626b625962605544311d201e21201d1511181f2224221b100200000000000000000000000000000000000000000000000f1f2d3b484d565c5c564b463939464b5053524f4a3e382f1c130800000000000000000000000000000000040a0c0d0b05000000000000000000000000000000000000000000000000000001080b0d0c0a03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004111c232c3538393632281d14090000000000000000051319273136383632281d140900000000000000000000000000020d1820222631353739383631272320190e04000000000000000000000000000000000000051525323f4b4f5660626260544c473b2e201d2e3e4a4f524d41302212000000000512202d363d494e545955606162636160555c574d483c31241300000000000000000000000c2035495a70859b8a849aa5b6ad98836e583c2c190600162b40566b80959d88899eb4a9947f6a543f2a150000000000000000000000000000000000000000000000000000000000000000000002121c24262c2d29211e160b000000000000000000000000000000000000000d22364a5c6c819688778095a2b4b59f8d7d675c4a3c2b1b0b00000000000000000000000000000000000000000000000000000000000000000000000000010f1a213138454b55606054484c5651484d4b443726140b090b0b080100040a0c0f0d0700000000000000000000000000000000000000000000000000010f1d2b3437414747413633292832363b3e3d39362d231c120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008141c2022211e170b0100000000000000000000000000000000000000000000000000000000000000000000000000000000000311222f383c494d4f4b4539312619090000000000000213233037444b4d4b45383126190900000000000000000000000a151d2b343737444b4d4e4d4b443738352c1f170c0000000000000000000000000000000000132332434f5d656f757877746c61594b3f2e2b3b4a5c64675f4d402f1d090000011223303e4a4e5b63696f7275777778777574716c625a4e42311e0e000000000000000000021528384d63788d897b899fb4bcab937e68533e28130000162b40566b8095917c8095aaa9937e69543e2914000000000000000000000000000000000000000000000000000000000000000000000000090f111718140c0a030000000000000000000000000000000000000005192b3c4f647a8c96847d8d9fb4b1a0947f6a5f4d3e2d1d0d0000000000000000000000000000000000000000000000000000000000000000000000000000000007131a283237444b4a433637413d34373531261909000000000000000000000000000000000000000000000000000000000000000000000000000000000d1820222c32322c211e17161e2126292824221b1009000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010f18263035383633291d14090000000000000000000000000000000000000000000000000000000000000000000000000000000011212f404c505a636460574b44372614010000000000102030414d55606260564b44372614010000000000000000000c1a28323b484c5455606263636055554d493c332a1c100200000000000000000000000000000e1e31424f616a7a848a8d8c888177645d4b3f344859647a7c675e4c38240f00000a1d30414d5c646e797e84878a8c8d8d8c8b8986817868604e3c2b19060000000000000000091d3245566a809582798c9fb5b59f8b77624c37220d0000162b40566b80959a84859bb0a8937d68533e2813000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b2034485a7085968181939fabb2a097826d615041302010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a161e263135353025222b292022201d1409000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b0d171d1d160c0a0303090c1114130f0d0700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1f2c36434b4d4c4639312619090000000000000000000000000000000000000000000000000000000000000000000000000000081c2e3f4c5e66727879756b605544311d0e00000000071b2e3e4d5f677478756b605544311d0800000000000000000c1c2a38454b59626a707577787875716b635a4c473a2e20110300000000000000000000000006192c3c4e606a7f8d9a9faaa79e96887b655d4b3c4d62778a907c66513b261100001024394d5f677a838e94999d9faaa2a2a1a89f9c978b7e685a4935200b00000000000000011527374b6075889d8c899eabbcb09b8570594834200b0000152a3f546a7f94a19a9ba3b4a7907b66513b26110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090b0d0b080100000000000000000d22384d62788b917c859bb0b1a1988273604b433323120200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000309141d20201c130d16140b0d0b0801000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061a2c3d4954606261574b4437261401000000000000000000000000000000000000000000000000050b0d0c0a04000000000000000e23374b5d667c878d8e8a8073604b3c2c19060000000d22374b5c677d898d898073604b35200b000000000000000b1b2a3a4756606b777f85898c8e8d8a8680786d61584b3e2f21110000000000000000000000000c2035495a687e929fabb4b7b2b2a69d8b7b655a48576c819797816c57422c17020012273c51677d8c99a1a9aeb2b4bbc8b8c6bab4b1a99f8b78624d38230d00000000000000081d314455687d92a69f9ea8b9baa9937e69543b2b180500000e23394e63798ea1afb0b4b39e8976614b36210c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a151d2022201d14090300000000000013283d52687d929b919ba3b49f97837360554431251505000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080b0b0700000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080d0f181c1e1c18100e090000000000000000000000000000000000000000070b0d0e0c0a040000000000000000000000000000000000000c2136495b637377766c605544311d1000000000000000000000000000000000000000000000010d192022221f180c000000000005192b3c50657b8c9da5a99f95816c5b4935210c0000011426374f647a8c9ea79e937e69543e29140000000000000316293947596174808a949b9fa9a3aa9f9c958c8276645c4b3f2f1d0d00000000000000000000091c2f404d63788a9eb4bcb0a59d9da6a99e8978624d61768a9f99846f5a442f1a0500182e43586d8398a4b1b5c1c7caced8cdd7cdc9c0b4a6907b65503b2610000000000000031628394b6074879cb2b4b4b9c6b49f8a76614c37210d0000000c2136495b6f8399a3acaba095806b5746321e09000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1920273136383531261e170b000000000012283d52677d92a9a6b0ab9f948173605544372614070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001101b22252d3233312d26231c110a0100000000000000000000000000000108131c202324211f170c07000000000000000000000000000000071a2d3d4e6379878d8a8173604b3f2e1b08000000000000000000000000000000000000000009141d2b343737332a1c16080000000b2034485a71869baab7bab49f8c78634d38230e0000081d3144556f8499aab8b09a85705b45301b000000000002101e324657617785969fa9b0b4bac7bbb4b1ab9f97887a655d4b3b2b18050000000000000000000f23384c5e70859ba8b9b09e958788919ea79a846f5f667b91a99a85705a45301b05000d23384d627886939ba3b4bac7d8ead7c7bab4aba29a8875614b36210c000000000000091e324557687d92a5b6cac9cdc0ad98836e5847331f0a000000061a2c3d4c617685929796908273604b392816030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1d2b3438454b4d4b443733291b0b000000000d22374d62788b9fa9a39b8c7f6d6055443727190900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070d0f0d070d0f0f0d0f0d0c100c0b100d0b0f0d0f0d0e0e0f0e0c0a0c0e0f0d0b100c0d0f0e0c06000000000000000000000000000000000000000000000000000009151d2e373a42474846423b382f251e130500000000000000000000000008141c2530353839373329221b1002000000000000000000000000000c21364a5b71869ca59f95806b5d4b37221100000000000000000000000000000000000000091926313b484d4c473a3426160200000d22384d62778da3b5c8cdbcab947f69543f2a1400000b20354b6075899fb4c8b19c86715c47311c0000000000102032424b6175869ba3b4bab4b0abaaaeb4bbbcb5a69e8a7b65594834200f0000000000000000071b2d3e50667b90a2b4b7a6958072737c8a9ea2917c676a8095aa9a85705a45301b05000b2035495a62747e868f9fa9bacee2cdbaa99f968f8478635746321e0a000000000005182b3b4b6075889db2c3d3dec8b4a28f7a644f3a2a1704000000000f1f33465861737d82817b6e605544311b0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1c2b3b484d56606260554c4639291a0a0000000b20344859687e8a908e857b6a614b4437271909000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010f1a2124211b222424212421212521202522202422242124232423211f21232422202522222423211a0f010000000000000000000000000000000000000000000000091927313f4b4f585c5d5c57504c3f3930231507000000000000000000000918263036434a4d4e4c473a362e2011030000000000000000000000000e23394e63798ea4b5b49f8d7a644f3f2e1c08000000000000000000000000000000000001142637444b59626158514434201000000f24394f64798ea4c1d2dac9ac97826c57422d1702000e24394e63798ea8bac4ae99846f59442f1a0000000008182d3e4f606e8399a4b5b6b2a29a9695999faab3bfb8a89e8977624d3d2d1a07000000000000000d22364a5c70859aafc0b39d8875605f677c8d9f9c86736f8499ae9a85705a45301b050006192b3c49556068717b8b9fb4c9dfc9b49f8b807a70635a493929160300000000000b203448596a7f95a6b7cbe1d1c1b09a85705d4b371c0c00000000000417293a465460676c6c655d4b4437261400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004172a3a4859626e7577746c61574638281602000005192b3b4e6068777b7971655d504331271909000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1f2d3639362d363939363936363a36353a37353936393639383938363335383936363a37373a39352c1f0f0000000000000000000000000000000000000000000008182737444b5d646d7173716d655d524d4133261500000000000000000009192736434b5460626361584f4a3e2f211100000000000000000000000013293e53687e93a8c2bcab9b85705d4b37230e0000000000000000000000000000000000081d314455606e77776c62513e2e1b07000f243a4f647a8fa4b9ced9c3ae99846e59442f19040012283d52677d92a7c6c4aa957f6a55402a15000000011426364a5c697e93a1b2b5a59d8f858080848b9aa1b3bfb8a799846f5b4a36210c000000000000000f24394f647a8ea2b4c7aa95806b564d5e6b8096a4917c73889daf9a85705a45301b0500000e1e2b37444b535c71869bb0c6dbc5b09b8570645c4d493c2c1b0b0000000000061a2c3d4c62778a9eb4c4d4ddc8b4a3907c66513f2e1b000000000000000b1b2936434b525756504c3f312619090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1f3347586278838a8d8a8175615645321e090000000d1d31424e596266635b504b3f331d150900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071a2d3d4a4e4a3e4a4f4e4a4e4a4c504b4a4f4d4a4f4a4e4a4e4d4e4d4c46494e4f4a4b504c4b4f4e493d2c1c0c0000000000000000000000000000000000000000011426364455606c7a82868886827b71675f5044331c0c0000000000000002152737445460697378797670645c4c3f2f1b0a0000000000000000000000152a3f556a7f94aabfc9b5a38f7b65503c2b1905000000000000000000000000000000001325364b6073828c8b816c5c4b37220d000f24394f64798ea4b9cedac4af9a856f5a45301a0503162839566c8196abc1b7a68e79644f39240f000000081c304354647a8b9fb4b5a39b877a706b6b6f788399a1b3c5b3a18e79634e39240e000000000000061a2c3d566b8096abc0baa98f7a644f404b6175889e9a84778ca6af9a85705a45301b050000000e192731363e5a70859aafc5dac5b09b85705b4a3e352c1e0e0000000000000c2135495b6c8297a8b9cde2cfbfb09b85705e4c38201000000000000000000b182630353d42413b382f1d1409000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c21374c617686989fa99f978574604b36210b000000001324313b474c504e4a3d372e21150100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d21364a5c645c4d5c64645c645c61656160656260645c645c6363646361585b63645c6065615c64635b493a29170400000000000000000000000000000000000000081c3043546073818f979c9d9b9790867d6b62503a2a1804000000000000081d31445560727e888d8e8c857a655d4c3928160300000000000000000000152a3f546a7f94a9bfd1c1ae99846f5a4835200b000000000000000000000000000000071c304354677d92a09f8f7a644f3a240f000e24394e63798ea3b8cedac5b09b85705b46301b06091e32455770859bb0c5b39d8873604a35200b0000031628384b6073869ba9b5a39b8577655d56555a62738399abbcbfac96816c573726140100000000000c2136495b72879cb2c7b49f8a75604b364657697f949f8d7f94aaaf9a856f5a45301a050000000009151d2f455a6f849aafc4d9c6b09b86715b462d20190e000000000000071b2d3e4e63798c9fb4c6d7d4c4b2a08f7a654f402f1d0200000000000000000008141c20282d2c26231c11010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002152738566b8095a4b4bab4a3927d68523d28130000000006131d2a34373b39362d231c11030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f24394e6479645f677979647964767a76757a78747964796579787978766165797968757a77697a79635847331f0a000000000000000000000000000000000000071b2d3e4b607282979fadb1b2b1aca49c91806b5847331f0a000000000004172a3a4b607383939da6a3a29a8b7b655745321e090000000000000000000013283d52687d92a7bdd2cab49f8b78624d3822100000000000000000000000000000000b20354a6073869cb1a8927d68533d2813000e23384e63788da3b8cddbc6b09b86715b46311c060b21364b60768a9fb4c3ac97826d5443301c070000091e324556687d92a3b5a59b857661594b3f3c485562788c9fb5c7b29c87725544311d0800000000000e23394e63798ea5b6c6b09b8671554431394c61778b9f9f8a9fb4af9a846f5a452f1a050000000000021a2f44596f8499aec4d9c6b19c86715c47311c06000000000000000d22364a5c6e8398aabbced8c7b7a698836e5d4b372212000000000000000000000001080b121717100e08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000091d31455672879db2c3cdc1af9a856f5a45301a0500000000000d181f222624211a0f080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003182d42586d826d677d807f78826d7f7d82807c8278836e827b817e837f7a657a817f7d7d7d847e7b8076614c37210c0000000000000000000000000000000000000d22364a5c6b8095a0b1bdc6c8c6c2b5b19f8b77614c37220c00000000000a1f3347586b8096a1b2b7c0b4a99d8875604b36210b0000000000000000000010263b50657b90a5c6d7cfbcab957f6a553e2d1b070000000000000000000000000006192b3c51667b90a4b5a7927c67523d2712000d22384d62778da2b7ccdcc6b19c87715c47321c0114263750657b90a9bab6a58f7a65503625130000000b21364b6075879db2a69c87776158473b2e2b37485a72889db2c7b49f8a75604b35200b000000000013283e53687d93a8c3c2ac97826d5737273447596f8499a99fa9baaf99846f5a442f1a05000000000004192e43596e8398aec3d8c7b19c87725c47321d0700000000000006192c3c4f647a8c9fb5c8d9cebaa99d8877614c3f2e1c0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b20364b60758a9fb5caddc8b39d88735e48331e09000000000000050b0d110e0c0700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004192f44596e847f7c8082827e826d7f8178826d7d7c846f827f7975837f7a697e7a72827c817a8281837c67523d27120000000000000000000000000000000000081c2e3f4f647a8c9fb4becedcd5ccc4b8b3a48d78634e38230e00000000000c21374c61778a9fb4bfcbd1c7b7a6927d67523d2812000000000000000000000d23384d62788da8b9cdd9c9b29c87725c4a362208000000000000000000000000000b2035495a6f8499afb8a78e7a644f39240f000d22374c62778ca1b7ccdcc7b29c87725d47321d081d3144556c8196abc7b29c8773604a35200b00000012273d52677c92a6a89d88786359473a2a1d1f34475973889db3c8bcab8b76614c36210c0000000001142637576d8297acc2bfaa947f6a553f2a2a3a54697e94a9b4bac7ae99846e59442f1904000000000003182e43586d8398adc2d8c7b29d88725d48331d080000000000000c2135495b6e8399abbccfcfbbb49f8b7b6559473421110000000000000000000000000001080b0d0c0a04000000000000000000000000000000000606000000000000000000000000000000000000000000000000000000000000000c21364c61768babbccfdec9b39e89745e49341f090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000182d42586d826d8278828278837f80817e7b81817586828078817f817f7a697e796d827c81807a818277624c37220d00000000000000000000000000000000000e23374b5d70859baabbcedcd5c5b8b3a69e948673604b35200b000000000012273d52677c92a9bacddfe5d5c4ab96816b56412c16010000000000000000000b20354a6074899eb4c9decab6a58e79644f362513000000000000000000000000000d23384d62788c9fb4b39e8874604b35200b000c21374c61768ca1b6cbdcc7b29d87725d48321d0b20354b6074889db2baa9947f6a5443301c07000003182d43586d8298a79e8a7a645a493b2a1c0c22374c61778ca6b7cab59f8a75604b36200b00000000081d31445571869bb1c6bca7927d67523d2824394e63798ea6b8cbc3ae98836e59432e1904000000000002182d42576d8297acc2d7c8b39d88735e48331e090000000000000e23384d63788c9fb5c9c9bcb59d927d675d4b3b2a180300000000000000000000000008141c2022221f180c060000000000000000000003090b151b1b130b07000000000000000000000000000003080700000000000000000000000c21364c61768ba1b6dadec9b49e89745f49341f0a0000000000000000000000000002090b0d0d0b080200000000000000000000000000000000000000000000000000040b0c0d0b090300000000000000000000000000000a162b40566b80807c676d6d626e6a6b6c69666c6c61716c6b626c6a6d7f7a667c78697e696c6a646c6c625947341f0b00000000000000000000000000000000021628384f657a8fa3b4c8d9d7c6b8a79e91887f75615443301c080000000000152a3f546a7f94a9c7d7eae6d8c8ab96816b56412c1601000000000000000000071c30435470859aafc5dad3c3ab96806b5443301c070000000000000000000000071b2d3e566b8095abbcad98826d5544311d08000c21364b61768ba0b6d9ddc7b29d88725d48331d1a2d3d51667b90a6b7b49f8a77624c36251300000004192e44596e83999d897b645c4a3c2c1d0c182f4052687d92a7c4c8b29d88735544311d08000000000b20354b60758a9fb4c9bba5907b66503b2621364a5b73889db3c8c2ad98836d58432e1803000000000002172c42576c8197acc1d6c8b39e89735e49341e0000000000000013283d53687d92abbcc8bbab9f947f6a5f4d3f2e1d0c00000000000000000000000311182630353737342a20190e00000000000000000a161e212a303028201c1308000000000000000000060c0e181d1c150b0902000000000000000c21364c61768ba1b6cbdec9b49e89745f49341f0a0000000000000000000000070b151d202322201d1509080000000000000000000000000000000000000000060b0d181f2223211e160b0802000000000000000000000a1a28323650626b6b675f58584d59545657535157574b5c57564d57546169645e666361696156554f56574c473b2a180500000000000000000000000000000000091e3245566e8398adc1d1e1cdb9a89e897c746961574636261401000000000013283e53687d93abbccfddd3cabbaa937e69533e29140000000000000000000000132536556b8095aac8d9ddc7b29d8773604a35200b00000000000000000000000d22364a5c72879db2baa9917c675137261401000b20354b60758aabbccfddc8b29d88735d48331e21364a5b6e8399aebaa996816c594834180800000000142a3f54697f90887a645c4b3e2d1e0e1325364c5e70859bb0c5c8ae98836e5937271502000000000e23384d63788daabbceb9a48f7a644f3a251a2d3d596e8499aec3c2ac97826d57422d1802000000000001172c41566c8196abc1d6c9b49f89745f4a26140100000000000013283d52687d92a9b9b5aa9f8d7f6a61504130211100000000000000000000000011212e36434b4d4c473a352c1e0e0000000000000b1a2832363f46453e3530251808000000000000000e1921232e32312a201d150a0000000000000c21364c61768ba1b6cbdec9b49e89745f49341f0a00000000000000000008131c202731363838363127231c110000000000000000000000000000000000000e1920232a343738363228201d1509000000000000000002162838454b575a5e5b554e493d38433f40413e3b4142364642403842434f544f4c514d4f544f42403a414237342a1d0d00000000000000000000000000000000000b21364b6075899eb4c9ded5c5b49e8a796760554b46392818080000000000000d23384d62788c9fb5c1c7c3b6b29f8b78624d38220d000000000000000000000011263b50667b90aabbcedfcab7a58f7a644f36261401000000000000000000000f243a4f647a8fa5b7b49f8a76614b36210c0000081d314455758a9fb4caddc8b39d88735e48331b2f3f4e63798c9fb4b49f8b78624d3b2a1800000000000b20354b60737b76645c4b3e2e2010071c304354667b90a3b4c8bbaa937e68533e2813000000000010263b50657b90a5c8d8b9a48e79644f3924152a40556a7f95aabfc1ac97816c57422c1702000000000001162b40566b8095abc0d5cab49f8a755544311d080000000000000d22374d62788b9ea89f9a8b7d696150433323130300000000000000000000000e1e2e3f4b54606261594d493c2c1b0b000000000b1b2938454b555b5b534a43362518080000000003111e2c35384348463f3631271a0a00000000000c21364c61768ba1b6cbdec9b49e89745f49341f0a00000000000000000e1825303538454b4d4d4b4437372f1c1308000000000000000000000000000006141e2b35383b474c4d4b4539363127190e00000000000000091e324556606c6f73706a635b534c473b4038454b453839373435313538353f39363c383b3e3b322b252c2d221f180d00000000000000000000000000000000000011263b51667b90a8b9cde0ccb8a7947f695b4b443732281b0b000000000000000b2035485a6d8298a3b1b2ada49c927f6a5a4835200b00000000000000000000000c21364c61768b9fb4cadfd4c3ab96816c5443301c08000000000000000000061a2c3d566b8096abc3af99846f5746321e0a00000115274a5f74899fb4c9dec8b39e89735e493429394c5d6e8399abb8a797816c5948341d0d0000000000081d314455606661584a3d2e2010031729394a6072859bb0c1cab49f8b77624d37220d000000000013283d53687d92a8bdceb8a38e79634e392411263b51667b90a6c9c1ab96816c56412c1701000000000000152b40556a8095aabfd5cebbaa8a75604b35200b0000000000000b20344859677d898e8b8479675f4f4333251505000000000000000000000006192c3c4b5d6573777770635a49392816030000031629394656606a7070686054433625130000000011212e3c494d585d5c544b4538281b0a000000000c21364c61768ba1b6cbdec9b49e89745f49341f0a000000000000010f1e2b36434a52566062626055504b3f30251808000000000000000000000000081624323c484d575961626057534b44372b1e0e0000000000000b21364b60768285888580797169615956564c5660564d4f4d484b44494e4a484d4c46393e35404337342a1d0d0b0500000000000000000000000000000000000001162b41566b8096abc6d7dec8b39e8975604b3d31271e160b000000000000000006192b3c4c617685949c9d978f877d6a61503c2b190500000000000000000000000a1e33465770869bb0c5dbddc8b29d8874604b35200b0000000000000000000c2136495b72879cb2bcab937e6853392916030000001f34495e74899eb3c9dec9b39e89745e4934334657657b90a1b3b39e8976614c3b2b1900000000000001152737444b514c473a2d1f10020a1e334657677d92a3b5c9c2af99846f594834200b0000000000152b40556a8095aabfceb9a48e79644f39240f23384e63788dabbcc0ab96806b56412b1601000000000000152a3f546a7f94a9bfd4d9b5a08b76604b36210b00000000000005192b3b4d5f677579776f635b4d41322515070000000000000000000000000c2035495a657b878c8c8578635746321e0900000a1e32465761757f85857e72605443301c0b00000c1c2e3f4b5b636d72716a605645392816030000000c21364c61768ba1b6cbdec9b49e89745f49341f0a0000000000000f1f2c3c485460676f757877756f655d4a43362618080000000000000000000006162634424f5a626c7377787671696055483c2b1d0d0000000000091e324556606c6f777f898e867e77706c6b616376675f64625960555b63605962615758544b56584c473b2a190900000000000000000000000000000000000000031629395a6f859aafc4dad8c8ac97826c5745321d150903000000000000000000000e1f33465861747f8688827a73685f5043331e0e00000000000000000000000003172939556a8095aac4d5dfcbb7a68f7a65503626140100000000000000000e23394e63798ea5b6b49f8b77624c37220d000000091e33495e73889eb3c8ddc9b49f89745f4a32434c6176879db2b4a3927d685847331d0d0000000000000009192731353b37332a1c0f010a1a2d3e4b6176889db3b7c4b6a4917c66513b2b18050000000002172c42576c8197acc1cfbaa48f7a654f3a251020364b60758a9fb5c0ab95806b56402b160100000000000014293f54697e94a9bed3cbb6a18c76614c37210c000000000000000d1d30414d57606461594e4a3d30231507000000000000000000000000011426374d62788a9ca5a39b8775614b36210d00071b2d3e4b617584949b9a938272604a3929170304182a3a4b5d65798287867f74605745321e0e0000000c21364c61768ba1b6cbdec9b49e89745f49341f0a00000000000c1c2c3d495a62727c848a8d8d8a847b6b60544336261401000000000000000000142434445161697881888c8d8b867e74625a483c2b19090000000002162838454b5759616976808a938a8581807679887d697977667567677872647776616e69606b6e61594737271c130800000000000000000000000000000000000a1e32465773889eb3c8decebbaa917b6651392816020000000000000000000000000417293a4656606a71726d6560544e4133251500000000000000000000000000000f243a4f64798fa6b7cbe0d4c4ac96816c5443301c080000000000000005182a3b546a7f94a9c3b09a8570594834200b000000081e33485d73889db2c8ddc9b49f8a745443404f616d8298a5b7a89b8572604a3a2a1700000000000000000009151d2026211f170c00021528384a5c6b80969b9da6b7b19c8673604a35200d000000000003182e43586d8398adc2d0baa5907b65503b26101d32455673889db3c0ab95806b56402b160100000000000014293e53697e93a8bed3ccb7a18c77624c37220d000000000000000013233039454b4e4c473b362d1f130500000000000000000000000000081d3144556c8196a8b6b5a5947f6a553c2b19050d22364a5c6d8298a2b0b0a0937e695746331e0a0a1f344759657b8a989d9b948475604b3c2b190500000c21364c61768ba1b6cbdec9b49e89745f49341f0a0000000004182a3a495b637885919a9fa9a99f99908072605443301c1000000000000000000e1e314251626c7e8a969da6a2a39b938678625a4837261401000000000a1a2832363b474c58616b777e8a948a7f70859a887e8a857b897d7d8a8079898477837e75808377615544353025180a000000000000000000000000000000000c21364b61768ba7b8ccdfc9b49f8a76614b36210c00000000000000000000000000000c1c2938454b555c5d58504a43363123150700000000000000000000000000000b20354a6074889db3c8ddddc8b39d8874604b35200b000000000000010b1f34485970859bb0bcab937e69543b2b1805000000081d32475d72879cb2c7dccebbaa8a75604b4c5e697f94a0b2b49e8a78635443301c0c0000000000000000000001080b110c0a0400000c1d324556647a8c9b86889db3a5927d675443301c07000000000004192f44596e8499aec3d0bba6917b66513c26111528385c72879cb1c0aa95806b55402b160000000000000013283e53687d93a8bdd2ccb7a28d77624d38220d000000000000000005131b2832363937342a211a0f0100000000000000000000000000000b20354b6074889eb3c6c3b29d87725a4834200b0f24394f647a8ea0b2c0beb39e8976614b36210c0c22374c6177889ea8b2b1a296816c5a4835200b00000c21364c61768ba1b6cbdec9b49e89745f49341f0a000000000a1f3347586379889ba3afb4babab4af9e968272604b3e2d1b0700000000000006192b3c4e606c80939fa9b3b7c1b5b0a49c8878625544311d0800000000000a161e212a343a4a5b657b86867f776a6c819684949c86898a89888885869c89888985858281857360534a4336281a0a0000000000000000000000000000000e23384d63788da2c5d5dbc6b19b86715746321e090000000000000000000000000000000c1a2832363f4748423a353025181305000000000000000000000000000000071c3043546d8297acc6d7e0cbb7a68f7a65503626140c0e10121415171822374c62778b9fb5b59f8c77624d37220d00000000071c32475c71879cb1c6dcd8b5a08b76604b5d667c8d9fb4b1a0927d675a49362513000000000000000000000000000000000000000c1d2f3f4b6074869c8675849aaf9d8774604b362513000000000000051b30455a70859aafc5d1bca7927c67523d27121c31465b71869bb0c0ab95806b56402b160100000000000013283d52687d92a7bdd2cdb8a38d78634e38230e000000000000000000000a161e2124221f180c07000000000000000000000000000000000f243a4f64798fa7b8cccab6a58d77624d38220d152737576c8197acbecfccb9a7927d67523d2812152737566b8095a7b8c6c0b49f8b78624d38220d00000c21364c61768ba1b6cbdec9b49e89745f49341f0a000000081c2f3f4c6176879da6b4c1c9cecdc9bcb0a0947f6a5c4a3622110000000000000b2035495a687e939eb4bac7cbd2c9c2b5a69b8573604b36261401000000000002090c1823394e63798a7b70827e69647a8e878298838697828b917c889882889580888975817e72686054453828160300000000000000000000000000000e23394e63788ea3b8cdd7c2ac97826d5739281603000000000000000000000000000000000a161e212a31332d2d29221f180c000000000000000000000000000000000013253651667c91a8bacde1d5c4ac96816c5443302022232527292a2c2d283953687d93abbcb09b8570594834200b00000000071c31465c71869bb1c6dbcbb6a18c76615c657b8a9fabb4a297826d5f4d3c2c180800000000000000000000000000000000000008182a3b4b5d6b80968b7a7d92a2a4937e685544311808000000000000061c31465b71869bb0c6d2bda8927d68533d28131b30465b70859bb0c0ab96816b56412c160100000000000012273d52677c92a7bcd1ceb8a38e79634e39240e000000000000000000000003090b0f0c0b0400000000000000000000000000000000000013283d52687d92a7c5d5d3c3a5907b65503b26101d31445572879cb2c7dcd6c5ad98826d58432d181d31445572879cb1c5d5cebaa995806b55402b1600000c21364c61768ba1b6cbdec9b49e89745f49341f0a0000000e23384b5d6e8398a5b7c4d1dfe1dedacdbeb49f8c7a644f3f2e1c080000000005182b3b4d62788a9fb4bdc8d1dfdfd2d2c4b5a3937e685443301c08000000000000000014293f54697e897571868978656e83947f878c7e8a897f94837b8c8a7c8b897d8b818593877e72605645321e1000000000000000000000000000000f24394e64798ea3b9ced5c5a8937d68533e28130000000000000000000000000000000000000a151d2f383b41423f37332a1c0f010000000000000000000000000000000b21364b6075899fb4c9deddc8b39d8874604b353537393b3c3e4041434446576e8499aebaa8947e69543b2b190900000000061b31465b70869bb0c5dbccb7a28c7762647a8a9ea8b6a49a8474604b41301e0e000000000000000000000000000000000000001325364759657b8c947f77899eb19c8673604b37271500000000000000071c32475c71879cb1c6d3bea9937e69543e29141c31465c71869bb1c1ab96816c56412c170100000000000012273c51677c91a6bcd1ceb9a48e79644f39240f000000000000000000000000000000000000000000000000000000000000000000000000152a3f556a7f94aabfd4d2bda8927d68533d281320364b60758a9fb5cadfdbc6b19c86715c38281520364b60758a9fb5cadfd8c7b09b85705b46301b00000c21364c61768ba1b6cbdec9b49e89745f49341f0a0000071a2d3d50657b90a0a9b0b4c1d1cdc9c4c9ccbbaa9a846f5d4b37230a000000000b203448596d8298a8a9b0b4c1cec9bdbfc9c1b29d8773604b35200b000000000000000011273c51667c917d677d92877b6f788a897d92877e9383828a7a7f94837d928480937e7f86918374604b3e2e1b07000000000000000000000000000f24394f64798ea4b9ceccb8a78e79634e39230e00000000000000000000000000000000000a1a2731404c505657544c473a2d1f0f000000000000000000000000000000091e3245566e8399aec8d9e0cbb7a68f7a6550434b4c4e5052535556585a5b6176899eb4b49f8a76614c3f31271909000000061b30455b70859ab0c5dacdb8a38d78647a899ea8b7a69c8676615645322313000000000000000000000000000000000000000c1c3043546177889b85748399a7a1907b65554431190900000000000000081d33485d72889db2c7d4bfa9947f6a543f2a151d32475c72879cb1c1ac97816c57422c170200000000000011263c51667b91a6bbd0cfbaa48f7a654f3a2510000000000000000000000000000000000000000000000000000000000000000000000000162b40556b8095aac0d5d4bfaa947f6a553f2a1521374c61768cabbccfe3dec9b39e89745645321d21364c61768babbccfe3ddc8b39d88735e39291703000c21364c61768ba1b6cbdec9b49e89745f49341f0a00000c21364a5b70859a9d949ba3b4c7bab4afb3b9c6b4a28f7a654f382816020000000d22374d62778b9f9d949ba3b4bbb4a8aab4bbb7a5907a65503b251000000000000000081c2e3f4b60758889786c819790847b809580818877817f7686898486907b80867686877e797c89826d5c4a36220d0000000000000000000000050f1a253a4f647a8fa4b9cfc8b39e8874604a35200b0000000000000000000000000000000002152738454b5e666b6c6961584a3d2d1b0b00000000000000000000000000000316283852687d92aabbcee2d5c4ac96816c5b546061636567696a6c6d6f70727e92a8b9b09b8570655d4b44372715020000051a2f455a6f849aafc4d9cfbaa48f7b7a899ea7b6a59d8878625847382815050000000000000000000000000000000000000c1c2e3f4a6072849a8b797d92a1a999836e5d4c3726140000000000000000091e33495e73889eb3c8d5bfaa95806a55402b151e33485d73889db2c2ac97826d57422d180200000000000011263b50667b90a5bbd0cfbaa5907a65503b2510000000000000000000000000000000000000000000000000000000000000000000000000152b40556a8095aabfd5d5c0ab95806b56402b1621364b61768ba0b6d9ebe1ccb9a88b75604b362021364c61768ba1b6daecdfc9b49f8a745746331e0a000c21364c61768ba1b6cbdec9b49e89745f49341f0a00000e24394e63798ea2947f859bb0baa99f9a9ea8b8c0ad98826d5645321e09000005182a3b54697e94a3947f859bb0aa9f93959faabbab96816c56362513000000000000000e23374b5d65777e93867675858b879089988b7e7e7b7a6a61767e787586877679887b848275677b8b79644f3a240f000000000000000000000d18202c354153687d92a8bdd6c5ad98836e5443301c0700000000000000000000000000000000091d314556606e7b81827e77645c4a39281603000000000000000000000000000f1f2d374c61768b9fb4cadfdec9b49e8a7972737577787a7c7e7f8182848688929cadc6b49f8b7f7a6e605544311d080000041a2f44596f8499aec4d9d7c2ad98828a9ea7b5a59c8778635a483a291a0a0000000000000000000000000000000000000417293a4b5d6a7f94947f788a9eb49f8b78634d3f2f190900000000000000000a1f34495f74899eb4c9d7c0ab95806b56402b161527385e74899eb3c2ad98836d58432e180300000000000010253a50657a8fa5bacfd0bba5907b66503b2611000000000000000000000000000000000000000000000000000000000000000000000000152a3f556a7f94aabfcad3c1ab96816c56412c1720354b60758aaabbcee2e8d6c6a18c77624c372220364b60758babbccfe3e2cebaa98b76614b36210c000c21364c61768ba1b6cbdec9b49e89745f49341f0a0005182b3b566b80969b8574879db2b49f8b85899ea6b8b39e8975604b36210b00000b1f34485971869b9b8574879db29f8c7d808c9fb4b09a85705443301c0700000000000010253a50657b88738195877b7a8b747b7f828b9486868578706b686263798a81778986726d615d6d827c67523c27120000000000000000000d1d2b343d494e5f6e8399aec3ccb9a7917c665136251300000000000000000000000000000000021527374b60748390969794897a645746321e0900000000000000000000000009192d3d4a556070869bb0c5dbe1ccb9a89e8b87888a8c8e909193959698999b9da5adbacebbaa9f958f8374604b36200b000004192e44596e8399aec3d8dac5b2a0989ea8b2a39b8778635a493c2b1c0c00000000000000000000000000000000000000091f334758647a8c9b8575849aa8a4957f6a5b493521110000000000000000000a1f354a5f748a9fb4bac7c0ab96816b56412c161d314556758a9fb4c3ae99836e59442e19040000000000000f253a4f647a8fa4b9cfd1bba6917c66513c2711000000000000000000000000000000000000000000000000000000000000000000000000142a3f54697f94a9b2b6c3c2ac97826d57422d181d314455758a9fb4cadfe2cdb8a38d78634e38231d324556758a9fb5cadfead8c7a28d77624d38220d000c21364c61768ba1b6c8cbc9b49e89745f49341f0a000b2034485972879c907b7e93a5b5a38f7b6f79889eaab9a8907b66503b261100000d22374c62778ca3907b7e93a5ab96816b6a7d929eb49e8974604a35200b00000000000c1d2a43586e83927d73808b908c806b666a6d7d92807983868581786860687e826d7b816c544b4f647974604b36211204000000000000000b1b2b3b484d5b636d7d8d9fb5cac6b39e8975604b36200b00000000000000000000000000000000081d3144556b8095a1abaca79c8675614b3727150200000000000000000000011426374a5b63737e899eb3c9dee8d6c6b9aa9f9c9d9faaa3a5a7a8aaabadafb0b2b7c3cad8c8bbb4aaa18f7a644f3a250f000003192e43586e8398adc3d8e1cfbeb2adb4b4a0988577625a493c2c1e0e0000000000000000000000000000000000000009192e3f4c6176879d8c7a7e93a2aa9c8674604b3c2c1903000000000000000000081d314455758aa99fa9bac1ac96816c57412c1720364b60758baabbc4af99846f5a442f1a050000000000000f24394f64798ea4b9c4c7bca7917c67523c271200000000000000000000000000000000000000000000000000000000000000000000000014293f54697e94999ca5b6c2ad98836d58432e181426495f74899eb4c9dee4ceb9a48f79644f3a2415284a5f74899fb4c9dee3ceb9a38e79644e39240f000c21364c61768ba1b1b3b8c4b49e89745f49341f0a000d22374d62778c9c8774879db2b09b86715d657b8b9fb4aa95806b55402b16000011263c51667c919c8775879db2a38d78635f6b8096a29f8a75604b35200b0000000004182a3b4752677d9288766b797f7d737b72605f697e7b807c7d838b8b7e6874827560656c6251464b5c646056483b2f2212020000000000031729394859626e79828c9fabbccdb9a896816c5645311d09000000000000000000000000000000000b20364b6075899eb4bfc5b6a4947f6a5544311d0800000000000000000000081d314455637986929ea8b9cce1e9e4d6c8bbb4b2b3b4bbc8babcbebfc1c2c4c5c7cbd4d2c9c3b6b2aa9f8b78624d37220d000003182d43586d8298adc2d7e1dccfc5bcab9f9482746259483c2c1e0e00000000000000000000000000000000000000021527374b5d6d8297968177899eb39f8c7a645645311e0e000000000000000000000b20354b60758a9b8a9fb4c1ac97816c57422c1721374c61768ca1b6c5af9a85705a45301b050000000000000e24394e63798ea3a7afb4c0a7927d67523d281200000000000000000000000000000000000000000000000000000000000000000000000014293e53697e9384879cb2c3ae98836e59432e191e33485e73889db3c8dde5d0baa5907b65503b261e33495e73889eb3c8dde5cfbaa5907a65503b2510000c21364c61768ba49c9da6b8b49e89745f49341f0a0012273c51677c91947f7c91a5b7a9947f69545d6a7f94a5af9a856f5a3a29170400162b40556b8095947f7c91a5b09b85705b4b6074849493816c5443301c08000000000b1f344759616a708496816c636a697f8a806b61757a676a78746e7884927d7e927d676161584c5761686b6962594c402f201000000000000a1e3346576277838d979faabbc9bdb49e8a77624c38271502000000000000000000000000000000000e23384d63788da8b9ccd3c2b39d8874604b36200c000000000000000000000b20354b6074879ca4b3b9c6cfd9d4dee0d8cecac7c5bab8b8b7b6bcb5b4b2b1b4bac7d2c1b5b1a59c978c7e68594834200b000002172d42576c8297acb8c9cdd7dfcab49f8d7f6d6056483b2b1e0e0000000000000000000000000000000000000000081d314455657a8d9d88768298a7a495806b5c4a38271500000000000000000000000b20364b60758b85788da2b7ac97826c57422d1722374c62778ca1b7c5b09b86705b46311b060000000000000e23384e63788d9b919aa2b4a8937d68533e281300000000000000000000000000000000000000000000000000000000000000000000000013293e53687e907b8196acc1ae99836e59442e191d32475c72879cb1c7dce6d1bca6917c67513c271d32475d72879cb2c7dce6d1bba6917c66513c2711000c21364c61768b9c86889db3b49e89745f49341f0a00152b40556a80958e798298adb8a78e79634e4b6074879db29d88735846331f0a00192e43596e83988e798298adab95806b56455660757e7e73604b36261401000000000c22374c6177807678898c7c665b738888847f6d82897c7b8a806a7a80848b7d8d89777677665e61757d807e77665e4c3e2d1b07000000000c21364b61758799a1adb4bbc8bcb09f927e685948341a0a00000000000000000000000000000000000d22374c62778ca7b8cce0cbb8a6917c66513a2a18040000000000000000000b21364b60768a9fa4a6acb4bcc9bfc9ccd6d1c1b4b0a4a3a3a2a1ab9f9e9d9c9fa9bac9b5a39b8d87827968604e3b2b1905000002172c41576c8196aca3b4bac6d7c4ae99846f6056483c2e2011030000000000000000000000000000000000000005192b3b4b6074869c927d7a8fa0ab9c8674604b3e2d1a0a00000000000000000000000b21364b60768b83788da2b8ac97826d57422d1822374d62778ca2b7c6b19c86715c47311c070000000000000d23384d62788d917c849aafa8937e69533e291400000000000000000000000000000000000000000000000000000000000000000000000013293e53687e8e798297adc2ae99846e59442f191b31465b70869bb0c5dbe7d2bda8927d68533d281c31465b71869bb0c6dbe7d2bda7927d68523d2813000c21364c61768b907c8096abb49f89745f4a341f0a00182e43586d83988a75879cb2b39e88735b4a44556a7f94aaa68b76614c36210c001b30455b70859a8974879cb2a5907b665e5c585760696860554431180800000000000d22384d62778d88807f8a8979666c81947f847f8d84868689857e8688838985829885898a7c667285808088897c665c4a36220b00000000142a3f54697f94a5b3bfcacec1b09e95816c604e3b2a180000000000000000000000000000000000000b20354a6074899eb3c8ded5c4ae99836e5847331f0a000000000000000000091e3245566b808d8e90969fabafaab3b9c5c8b4a39b8f8e8d8d8c8b8a8988868b9fb4c3b19b8579726c635b4e42311d0d00000001162c41566b81969e8e9fa8bacdc7b3a1988275625a4b3e2e2112040000000000000000000000000000000000000b203448596a7f949a8475869cb19f8c7a6456453220100000000000000000000000000c21364b61768b82798fa4b9ad97826d58422d1822384d62778da2b7c7b29d87725d48321d080000000000000d22374d62778c8d788399aea9947e69543f291400000000000000000000000000000000000000000000000000000000000000000000000013283e53687d8d788399aec3ae99846f59442f1a1a30455a6f859aafc4dae8d3bea8937e69533e291a30455a6f859aafc4dae8d3bea9937e69543e2914000c21364c61768b8f7a8197acb49f89745f4a341f0a001b30455a70859a87748a9fb4af99846f5a3d374f647a8fa6aa8d78624d38230d001d32475d72879c87748a9fb4a18c777173716d665e54534b443727150000000000000b2034485a6a7f868a8e9196887c7979898978858a8b7d879a84848a88808a9580889883858a787a8f7c7d77838a7a644f39291703000003192e43586e8398adc3d0d9c9b5a3958072604a42311d0d000000000000000000000000000000000000071c3043546d8297acc3d4dfc9b49f8b77614c37220f0000000000000000000316283851626b78797b818d9f9d949ea7b9c5b09b857b7978777776757473718499aeb6a48e79645b574e493d3124140000000001162b40566b80958a788a9fb4bfb3afafa0988578645c4b3f2f2212040000000000000000000000000000000005192b3c4d62788a9f8b787f94a4a596806b5c4b382815020000000000000000000000000c21364b61768b817b90a5baad98826d58432d1823384d63788da2b8c8b39d88735e48331e000000000000000c22374c61778c8c76859aafa9947f6a543f2a1500000000000000000000000000000000000000000000000000000000000000000000000013283e53687d8c77849aafc4af99846f5a442f1a192e44596e8399aec3d8e9d4bea9947f69543f2a192f44596e8499aec3d9e9d4bfaa947f6a553f2a15000c21364c61768b8e798297adb49f89745f4a341f0a001c32475c71879b86768baabbab96806b5641354b6074889d9f8a75604b36210b001e33485e73889a85768baabbaf9a84878887827b6e6158473828190900000000000005192b3c50616a7175797c808d9086868999877e849a87798795808497827e93897f94897e86837e939092827484846f5746331e0a000002182d42576d8297acc5c8c3c6b09b8671605443302413000000000000000000000000000000000000000013253650657a8fa5b7cadfcebbaa937e69533d2d1a070000000000000000000a1a3444515a6264666c7e93947f899eb3c5af9a8570636362616160545c72879db2b29c87725c4a3d38352c1f14060000000000152b40556a80958774899fb4b3a1999aa2a39b897a655d4c40302212040000000000000000000000000000000b2035485a6c81979580788a9eb29c8775604b3e2e1a0a080d0f150d0b050000000000000c21364b61768b807c91a6bbad98826d58432d1823384e63788da3b8c9b39e89745e492513000000000000000c21364b61768b8a75869bb1aa95806a55402b1500000000000000000000000000000000000000000000000000000000000000000000000013293e53687e8b76859ab0c4af9a846f5a452f1a182d43586d8298adc2d7ead4bfaa957f6a55402a182d43586d8298adc2d7ebd5c0ab96806b56412b16000c21364c61768b8e788398aeb49f8a745f4a351f0a001e33485d73889a85768ca1b6a8937e68533e304354687e9293846f5645321e09001e34495e73899984768ca1b6b4a29a9c9e9c98908376615645321d0c000000000000000d1d33435055566063666b7e8c86777383917c7684978278878c7d84937e7f9486818a847f947f94868385707a8c76614b36210c00000012283d52677d92a7b8b3aeb3b5a3937e695b4935211300000000000000000000000000000000000000000b20354a6073879db2c7ddd8c8b09b86715b4a362109000000000000000000001626343c484d4f516071858e798196abc1b49f8b77624e4d4c4b4a4e64798ea5b7ac96816c573e2d23211a0f01000000000000152a3f556a7f9486758ba8baaf998385949fa79e8a7b665e4c403022120300000000000000000000000000031729394d62788b9f8a758298a8a2917c665645322010101b22252a2220180d00000000000c21364c61768b7f7c91a7bcad98826d58432d1823384e63788da3b8c9b49f8a745443301c070000000000000b20364b60758b8974879cb2ab95806b56402b1601000000000000000000000000000000000000000000000000000000000000000000000014293e53697e8b76859bb0c5b09a85705b392816172c41576c8196acc1d6ead5c0ab95806b56402b172c42576c8197acc1d6ebd6c1ac96816c57412c17000c21364c61768b8d788499aeb49f8a745f4a351f00001e34495e73899a84778ca1b6a6917b66513c26364a60727d7e76614c38281603001e33485e73889883778ca1b6bcab9f99969ba3a1998474604b3a2a1804000000000000001525333c38454b4e5160687b89887a77878a7a7584937e78878a7b858d798195808489838a8183908c7e69748978634d38230e0000000c21364b6175889ea79e99a1b3b49f8b79634e4130190900000000000000000000000000000000000000071c3043546b8095aac1d1ddc9b5a38e79634e3726140100000000000000000008161d2b3438394252677c9281788ea3b4bcab947e69543d37363d556b8095aab8a7907b66513b26110c06000000000000000014293f54697e9485778ca1c6aa95806f7f8d9fa89e8b7c665e4c402f2111030000000000000000000000000a1e3346576c81969a858798a0ab9a84705e4c38281610202e373a3f37342b1d0d000000000c21364c61768b7f7d92a7bcac97826d57422d1823384e63788da3b8cebaa98a75604a35200b0000000000000b20354a60758a8973889db2ab96816b56412c1601000000000000000000000000000000000000000000000000000000000000000000000014293e53697e8b76859bb0c5b29c87725745321e162c41566b8196abc0d6ebd6c1ab96816c56412c172c41566b8196abc0d6ebd7c2ac97826d57422d18000c21364c61768b8d778499afb49f8a755f4a251300001e33485d73889a85768babbca5907b65503b26304354606769615847331a0a00001d32475d72879883768babbcb59f8d848185979fa295806a5847331f0a000000000000000715202828323639414e5d6578848b7f7989887875848c7c78878878817373857d77877786826e7b7c6960718674604b36200b000000091e324657697f949e898499a5b6a99a84705f4d37261401000000000000000000000000000000000000001325364d63788da3b4c8ddd2c1ab96806b5544311d0800000000000000000000000d19202224364b6075888875859bb0c5b09b86715b493535495b72879cb1b39e8875604b36200b0000000000000000000014293e53697e9383788da2b8aa95806b697d8c9fa99f8c7c665e4c402f21110300000000000000000000000c21364b6176899a85768a9fb49f8d7a644f40301a0a1b2e3e4b4f554d483b2b1b0b0000000c21364c61768b7e7d92a8bdac97826c57422d1723384d63788da2b8d8b5a08b76604b36210b000000000000071c304354748a8873889db3ac97816c57422c1702000000000000000000000000000000000000000000000000000000000000000000000014293e54697e8b76859bb0c5b49f8a76604b3621162b40566b8095abc0d5ead7c2ac97826d57422d182b40566b8095abc0d5ead7c2ad98826d58432d18000c21364c61768b8c778499afbbaa8a755443301c07001c31475c71869b86758a9fb4a48f7a654f3a252536434a52534c473a2a170000001b30465b70859984758a9fb4a9927d6e6c738197a29e8977614c37220c0000000000000000030d0a151d2024313f4c5a6273808c857f8986777d89897a7a8985797a7e777262756175746066665e617779645544311d08000000031628394b6074869b8674879cb2b4a2927d675544311d0800000000000000000000000000000000000000082035495a70859bb0c6d7ddc8b39d8874604b35200c000000000000000000000000050b0d1d3145566b80917c7d92a6b8b5a38d78634e38394e63798ea4b6ad97826d5544311d080000000000000000000013283e53687d9383788ea3b8ab96806b5f677d8d9faa9f8b7c665e4c3f2f21110200000000000000000004182a3b53697e939e89859ba9ab98826d5c4a3622121628394b5c646a6259483a29170400000c21364c61768b7e7d92a8bdac97816c57422c1723384d63788da2b8cbb6a18b76614c36210c000000000000001325495f74898873899eb3ac97826d57422d1802000000000000000000000000000000000000000000000000000000000000000000000014293f54697e8b76859bb0c5bbaa907a65503828162b40556a8095aabfd5ead8c3ae99836e593828152b40556a8095aabfd5ead8c3ad98836e58432e19000c21364c61768b8c77849aafb59f8a75604a35200b001b30455a70859a8873889db2a5907a65503b2530414d525d565144342313010000192e43586e83988673889db29f897460546073859ba8937e68533e2913000000000000000000000002090b13212f3c4855606a798592889c867779868f8382898d837f696055605660605550514d5961645c4a37271502000000000b1d324556647a8c917c7c91a3b5b19c8673604b35200f0000000000000000000000000000000000000006192c3c53687d93a8bacde0cbb7a6907b66513a29170400000000000000000000000000021527384e63788d8575889eb3c1aa95806a553e3b546a7f94a9bcab917c6752372715020000000000000000000013283d52687d9282798ea3b9ac96816c575f687e939da99f8b7c655d4b3f2e20100200000000000000000b1f34475970859aa79e9ba2b49f8c78624d3e2d1b091e324557647a7f77625846331f0a00000c21364c61768b7e7d92a7bdac96816c57412c1723384d62788da2b7ccb7a18c77624c37220d000000000000001e34495e73898874899eb3ad98826d58432d18030000000000000000000000000000000000000000000000000000000000000000000000152a3f546a7f8b76859aafc5c8ab96816c5645321e2b40556b8095aac0d5eadbc6b09b86715645321d2b40556a8095aabfd5ead8c3ad98836e58432e19000c21364c61768b8c77849aafb5a08a75604b35200b00182d42586d82978b76859aafa6907b66513b26394d5f67736b625141311e0a0000152b40556a80958974859aaf9f8a75604b5563788b9f99846f593b2a18050000000000000000000000000003111d2b37444b5b63707d88939a85707786877279887b69614a444b454b4b44373c3a474c4e4a3e2d19090000000000021528384a5c6a80958673869bb0b6a4927c67523d2c1a06000000000000000000000000000000000000000e21364c61768a9fb4c9ded5c4ae98836e5847331f0a00000000000000000000000000000a2135495b70858f798095a9bab29c87725c4a485970869bb0b49f8b77614c37210c000000000000000000000012273d52677c9282798fa4b9ac97826c574e606a7f949fa99f8b7b655d4b3f2e201000000000000000000c22374c61778b9fb5b3b0b4ae98836e5a493520100b21364b60758a948776614c38271502000c21364c61768b7f7d92a7bcab96816b56412c1622374d62778ca2b7ccb7a28d77624d38220d000000000000091e33485e73888873899eb3ae98836e59432e19040000000000000000000000000000000000000000000000000000000000000000000000152a3f556a7f8c778499afc4c8b39e8975604b37262b40566b8095abc0d5eadfc9b49f8a75604b36202b40556b8095aac0d5ead8c2ad98836d58432e18000c21364c61768b8d778499afb5a08b75604b36200b00152a3f546a7f948f798196aba7927d67523d293a52677d88806b5f4d3a2509000012273c51677c918d788196abaa8d78624d495b6e83989e89745947341f0b0000000000000000000000000000000d1926313d4a4e5f67757e88806b6277806b637773604b4331353236353127272a343739362d2010000000000000000a1a2d3e4b607485937d7b91a3b5b09a85705b4935210c000000000000000000000000000000030d13151f1e3346576d8298adc3d3dfc9b49f8a76614c37210f0000000000000000000000000000061a2c3d52677c9183778a9fb4b6a48f7a644f4d62778b9fb5b09b86705847331f0a000000000000000000000011273c51667c9182798fa4b9ad97826d584250616c8197a1a99f8a7b655d4b3e2d1e0e0000000000000011273c51667c91abbcc9c5b7a58f7a654f3c2c19020f24394f64798ea596806b5645311d09000c21364c61768b7f7c91a7bcaa95806b55402b1622374c61778ca1b6ccb8a38d78634e38230e000000000000081d32485d72878873889eb3ae99846e59442f19040000000000000000000000000000000000000000000000000000000000000000000000152b40556a808d788499aec3ccb8a7927d685544312c41566c8196abc1d6ebe2cebbaa907b66513c2b2b40566b8095abc0d5ead7c2ad97826d58422d18000c21364c61768b8d788499aeb5a08b76604b36210b0011263c51667c91937e7c91aaaa95806a553933465871869b927d675237271501000c22374c61778c927d7c91aaa7917c67523c556a7f95a78c77624c37220d0000000000000000000000000000000009141d2d36414d56606975726059626b625962605544311d201e21201d1511181f2224221b10020000000000000000101d314455657a8f8775869bb1b4a28d78634e38230e0000000000000000000000000000071520282a3432293950657a8fa5b6cadfcdbaa9937e68533d2c1a0600000000000000000000000000000e20354b6074878b788297aabbac97816c5653697e93abbcaa95806b553a2a1704000000000000000000000011263b51667b9082798ea4b9ad98836d5843434b60738399a4a89e8a7b645c4a3c2b1b0b000000000000162b40556b8095aac9dac7b29d87725d4b371e0e000f253a4f647a8fa49e8975604b36200b000c21364c61768b807c91a6bba9947f6a543f2a1521364b61768ba0c7d7b8a38e79634e39240e000000000000071d32475c72878973889db2af99846f5a442f1a050000000000000000000000000000000000000000000000000000000000000000000000162b40566b808d788398aec3d5c5b19c8673604b392943586d8298adc2d7edead8c8ad98836e5a49352c42576c8197acc1d6ebd6c1ac96816c57412c17000c21364c61768b8e788398aeb5a08b76604b36210b000c22374c61778b9883768a9faf9a846f5746364c61768b9f9b86715544311d08000b1f34475971869882768a9fac96816c573f53697e93a48f7a644f3a250f0000000000000000000000000000000000010f1a213138454b55606054484c5651484d4b443726140b090b0b080100040a0c0f0d0700000000000000000000021527374b5d6f83927d7c91a6b7a9947f6a543b2a1805000000000000000000000000041525333c404a4739354a6073879cb2c9dad7c7b09b85705b4935210c0000000000000000000000000000081d314455697f9481788b9fb4b39e897560586f849aafb9a88f7a654f3a251000000000000000000000000010263b50657b9082798ea3b9ae98836e59433144556175869ca6a89e8a7a645a48392917030000000003182d43586d8298adc2d7c2ac97826d573f2e1b00000f253a4f647a8fa4a78f7a644f3a250f000c21364c61768b807b90a5bba9937e69543e291420354b60758aa9bacdb9a48f79644f3a240f000000000000071c31475c71868974879db2af9a85705a45301b050000000000000000000000000000000000000000000000000000000000000000000000162c41566b818e798298adc2d7c9b6a4927d685746323a5a6f8499afc4d9eef4dfcab49f8b78624d403036586e8398adc3d8ead4bfaa957f6a55402a15000c21364b61768b8e798298adb5a08b76604b36210b000a1f34475971869c8975859aaf9f8a76614b3b51667b90ab9f8a75604b35200b0004182a3b566b80958975859aaf9c87725d4b556b8095a5907b66503b26110000000000000000000000000000000000000007131a283237444b4a433637413d3437353126190900000000000000000000000000000000000000000000000009192e3f4f647a8f8675889db2b09b85705947341f0b0000000000000000000000001222334350555f5d4f4a43546a7f94abbccfddc9b5a38e79634e3923100000000000000000000000000000011527374c6176898a778398abb9a7927d6761768b9fb4b39e8975604b35200b00000000000000000000000010253a50657a8f83798ea3b8ae99846f5944263746576278889eaba89d8878625746331e1100000000041a2f44596f8499aec4d3bda8937e68533e291300000f243a4f64798fa4a7927d68523d2813000c21364c61768b817a8fa5baa8927d68533d28131d314455748a9fb4c9baa48f7a654f3a2510000000000000061b31465b70868a75879cb1b09b85705b46301b060000000000000000000000000000000000000000000000000000000000000000000000172c41576c818f798297acc2d7d3c2b39d8875614b43475872889db2c7ddf2f7e2cebbaa98826d5e4c3d435470859bb0c5dae8d3bda8937e68533e2913000c21364b61768b8f798297acb6a08b76614b36210c0004182a3a566c8196947f859ba9a9917c67523d566b8196aba88b76614c36210c00000e24394e63798e947f859ba9a58f7a654f5e70859ba6917c67513c27120000000000000000000000000000000000000000000a161e263135353025222b292022201d140900000000000000000000000000000000000000000000000000001122374b5d71868f7a8095abb49f8b77624c37220d0000000000000000000000091d304050616a7472645c4a4d62788c9fb5cadfd1c1aa95806b553e2e1b080000000000000000000000000000091e3346576b819680798c9fb5af9a8570687d92aabbae99836e5544311d080000000000000000000000000f243a4f64798f83788da2b8af9a856f5a45302939485a657b8d9fb4a69c8675614c402f1c09000000051a2f445a6f8499afc4d0bba5907b66503b261100000f24394f64798ea4a8937d68533e2813000c21364c61768b82798fa4b9a7927c67523d27121426495e73899eb3c8baa5907b65503b2610000000000000061b30455b70858a75869bb1b09b86715b46311c060000000000000000000000000000000000000000000000000000000000000000000000172d42576c828f7a8196acc1d4cac7b7a697816c614b4c61768ca5b7cadff4ece1d8c8b2a0917c665b4a4a6074899eb4c9deead7c7a6917c66513c2711000b20364b60758b8f7a8197acb6a08b76614b36210c00000f243a4f647a8f9d94838b9fae99846f594a5c71869cb19f89745846331f0a00000c21364a5b71869c94838b9fad98826d5e657b90a3a6917b66513c2611000000000000000000000000000000000000000000000309141d20201c130d16140b0d0b0801000000000000000000000000000000000000000000000000000000081b2e3f54697e9382778b9fb4ab927d68523d281300000000000000000000000f24384c5e6a7f89877a6456485a70859aafc7d7dcc7b29d87725c4b3722090000000000000000000000000000031729394d62788a89768399aeb4a28e796f8499aec3a8937e6853372715010000000000000000000000000f24394e64798e84778da2b7b09b85705b46301b2b3c4b5d6a8095a2b4a498826d5e4c38231000000003192e43586e8398adc3cfbaa58f7a65503a2510000010263b50657b90a5a6917c67513c2712000b21364b60768b83798ea3b8a6907b66513b26111d32485d72879db2c7bba6917b66513c2611000000000000051a2f455a6f848b76859bb0b19c87715c47321c070000000000000000000000000000000000000000000000000000000000000000000000182d42576d82907b8196abc0c3b6b2b6b19f95806b6054677d92a7c3d4e6ecdccfc6c2beb39e8a79645c4e64798ea8b9cce1e2cdbaa98d78634e38230e000b20354b60758a907a8196abb6a08b76614b36210c00000d22364a5c71869c8d788297ac9f8b77625464798ea4b19b86715c3a2917040000071a2d3d52687d928d788297ac9f8d7c6a77879db2a78e79644f39240f00000000000000000000000000000000000000000000000001080b0b07000001000000000000000000000000000000000000000000000000000000000000000000001023384d62788d8975859ab0ac97826d57392816030000000000000000000215273851667c919f9c8775604b52687d92a9bacddfcab6a58f7a644f3726140100000000000000000000000000000b203448596d82957f7a8fa2b3ac9781758a9fb4b7a58d78634d38230e000000000000000000000000000e23384e63788d85778ca1b6b19c86715c47311c1e2e3f4b6073849aa4b2a0907b66503e2e1b08000001162b41566b8096abc0d0bba6907b66513b2611000013283d52687d92a7a58f7a65503a251000091e324556748983798ea3b8a48f7a644f3a250f1c31465c71869bb1c6bca6917c67513c2712000000000000041a2f44596f848c77859aafb29c87725d47321d080000000000000000000000000000000000000000000000000000000000000000000000182d42586d82947f8399aec3b6a59da5b5af9e958073646f849aafc4daefe3cfbeb2adb3b8a89d887a68606c8196acc6d6e8dfc9b49f8a74604b35200b00081d314455758a907b8096abb6a08b76614b36210c0000071b2e3e54697e939a84859bb0aa96806b6073849aafac97816c57422c17000000000f20354b6074879a84859bb0ab9e8a7f859ba5b39e8975604b36200b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b2035485a7186917c7e93abb19c86715745321e09000000000000000000091d3145566f848b8b9f947f69554b61768a9fb4c9ded4c3ac96816c5544311d08000000000000000000000000000005192b3b4d62788b8976849aafb49f8a8096a9bab29d87725a4935200c000000000000000000000000000d23384d62788d85768ba0c6b19c87725c47321d111d3144556176869ca6b19c86715c4b37220d00000012273d52677d92a7c1d2bea9947e69543c2b190606192c3c576c8196aca78c77624d37220d00021628385d72878a879cb2c9a38e78634e39230e1b30455b70859ab0c5bca7927d67523d28120000000000060c192e44596e838d788499aeb29d88725d48331d060000000000000000000000000000000000000000000000000000000000000000000000182d42576d829785889db3c8b29d879ba3b5af9e9684797d92a2b4c8dce7d5c5b2a0989ea7b8a69d8a7d7277899eb3c9deefdac5af9a85705544311d08000115274a5f758a927d8197acb6a08b76614b36210c0000001021364b6175899e9a9ba3b5b49f8c7c708095a2b4a7917c66513c271100000000081d314455677c919a9ba3b5b9a89e949ba3b5aa97826d5544311d0800000000000000070d0f0d070d0f0f0d0f0d0c100c0b100d0b0f0d0f0d0e0e0f0e0c0a0c0e0f0d0b100c0d0f0e0c060000000000000000000000000000000000000006192b3c576c819682778a9fb49f8a76604b36210b0000000000000000000b20364b60758a7e7f949d8874604b576e8399aec8d8ddc8b39e8874604b35200b0000000000000000000000000000000d2035495a6d82947f7a8fa3b5a89f969eb0c7ac97826c573c2c1906000000000000000000000000000d22374d62778c86758aa8b9b29d87725d48321d0114263747586278889da6a48f7a644f3a250f0000000d22384d62788da3b5c9c4af99846f5a49352013092035495a71869cb19e8974594834200b00001b30455b708586798ea3bcab8c77624c37220d192f44596e8499aec3bca7927d67523d2812000000000e1920232743586d839884899eb3b39e88735e493321190e00000000000000000000000000000000000000000000000000000000000000000000162c41566b81907b8196abbbaa8e79859babbcb0a29a8f929cadc0d0e3e0cbb8a69882899eb3b8a89e9287879da8b9cce1e3d1c0aa947f6a5537261401000020354a5f758a9d88899eb4c7a08b76614b36210c0000000a1e324657697f94a4b0b5c1bbaa9f8c86959eafb39e8975604b36200b00000000011527374d5f6e8399a5b5c1c6b9b4a9b0b5b49f8b78634d372715020000000000010f1a2124211b222424212421212521202522202422242124232423211f21232422202522222423211a0f0100000000000000000000000000000000000012273c51677c91897b899eb4aa8f7a654f3a25100000000000000000000e23384d63788d7f7c92a6917c665152677d92aabbcee0cbb8a68f7a65503a251000000000000000000000000000000006192c3c4e63798c8875869bb1bab4abb0bcbbaa917c67513c271200000000000000000000000000000c21374c61768c8774899eb4b29d88735d48331e000919293a495a63798799a1927c67523d27120000000b2035485a71869bb0c5cab49f8c78624d42311e192a3a4d63788da4ae99846e593b2b18050003192e43586e83877c91a7b59f8a75604b36200b172c41576c8196acc1bca6917c67513c2712000002101e2c35383744586d82927d869bb1b49f89745f3a38352c1e12040000000000000000000000000000000000000000000000000000000000000000152a3f546a7f9485889db2b49f8a747b8d9fb5c0b3afa4a7adbacadee7d5c4b39e88757f94a3b5b9b4a49c9da5b6c6d6e8dcc8b4a28e79634e39230e00000a1f354a5f748a917c8196abbaa98b75604b36200b000000031629394b6074869ca8bac8c8bbab9f9ba3afb8a695806b5645311d090000000000091930414c6176879da5b3bfc6c8c8bbb4a0947f6a5a493519090000000000000f1f2d3639362d363939363936363a36353a37353936393639383938363335383936363a37373a39352c1f0f0000000000000000000000000000000000000d22374c62778c98838499aea8937e69533e29140000000000000000000e23394e63788e817a8fab99846e594c61768a9fb4c9dfd5c5ab96806b56392917030000000000000000000000000000000e2135495b6e839985879ba3b5c9c0c3cab49f8b76614c36210c00000000000000000000000000000c21364b61768b988398a8b9b39e88735e49331e00000c1c2c3c495b6377838c8776614c37220c00000005192b3c53697e93a7b8ccbcab98836e604e41322b3747596b8095aaa9937e69533e2914000000152a3f546a7f94919bacb39e89735544311d0814293f54697e94a9bec8a5907b66503b2611000010212e3c494d5755606c81907b8499afb49f8a7458554d493c302212000000000000000000000000000000000000000000000000000000000000000012273c51677c919b9da6b7b29c87726c8197a3b5c3c4b9bdc0cad8ebe0cbb8a6947f6a73859ba8b9c2b6b1b2b6c3d4e4e2d0c0af9a85705b4935210c00000a1f344a5f74899983869cb1b49f8a745645311d09000000000b1d31445563798a9faabac7c9bcb4b0b4bcab9e8876614c38271502000000000000121f33475863788799a1adb1b2b0aa9f958272604a3c2c19000000000000071a2d3d4a4e4a3e4a4f4e4a4e4a4c504b4a4f4d4a4f4a4e4a4e4d4e4d4c46494e4f4a4b504c4b4f4e493d2c1c0c00000000000000000000000000000000000b1f344859728795807e93a8ac96816c57412c170000000000000000000c21374c61768c85768b9f9f8b77624c586f8499afc8d8dbc6b19c86715746331e0a000000000000000000000000000000061a2c3d4e64798e8974869bb0c6d5dac5b09a85705846331f0a00000000000000000000000000000b20364b60758b8a7a8a9fb4b49e89745f4927150200000e1e2c3d4959626e7674615847331f0a000000000e21364b6175899eb3c3c9b2a0927e685f4b463b48556177899eb39f8a77614c37220c00000010263b50657b90abacb9b19c86715c3727150211263b51667b90a6c3bbaa8e79634e39240e00081b2e3f4b5a636c727578849a9099a1b3b59f8c766d6a635b4d40301d0a000000000000000000000000000000000000000000000000000000000000000d23384d62788da5b2b7c4ad98826d6075859ba5b6c3cfd9d5dce2d9cfbcb39d88766163798a9eaabbc8c7c7cad4e1e2d4c4b4a2917c66513d2c1a060000081e33485d73889d999ca4b5b29c87725d3827150200000000021527374a5b677d8c9fa9b5c1c6c7c6b9ab9f8d7c665746331a0a000000000000000417293a495a6377838f979c9d9b968b8072605443301e0e0000000000000d21364a5c645c4d5c64645c645c61656160656260645c645c6363646361585b63645c6065615c64635b493a2917040000000000000000000000000000000005182a3b586d82978a8a9fb4af9a846f5a3b2a180400000000000000000a1f33475872888975879caa947f6a5552687d92aabbcedfcab49f8b76614c36210c000000000000000000000000000000000f22364a5c6f849782879db2c7dcd5c5aa947f6a553a2917040000000000000000000000000000081d314455758a8a77899eb4b49f8a745645311d090000000f1f2c3b484c58616056473a2a180400000000091e3246576a7f94a5b6c8beb49f8c7d6b6157575962738298a7aa98826d5847331f0a0000000c21364c61768b9fb5c3ae98836e59432e19000d22374c62778ca5b7b49f8a76614b36210c000e22374b5d657881878a8d9aa2a5afb3bfbcab9c86827f78665e4d39240f000000000000000000000000000000000000000000000000000000000000000c2035495a72879cb2c5bbaa927d68566278879ca4b4bcc9ccd5cdc9bcb49e927d67585b667c8c9faab7c4ccd6d7d8cec3b6a69a846f5e4c381f0f00000003182e43586d8298a9b1b5bbaa97826d57422d1800000000000009192d3d4d5f677d8a9ba3adb0b1afa89e8d7e695e4c3929170000000000000000000c1c2c3c4959616f7a8287888680796b605443362513000000000000000f24394e6479645f677979647964767a76757a78747964796579787978766165797968757a77697a79635847331f0a000000000000000000000000000000000013283d52687d929f9fa8bab39d88735947341f0b000000000000000004172a3a586d828f7a8096ab9d8774604c61768a9fb4c9dfcfbcab907b65503b251000000000000000000000000000000000071b2d3e4f647a8f979da5b6cadfccb8a78f79644f3a240f0000000000000000000000000000000215274a5f74899f8c9ea8b9baa98b75604b36200b000000010f1d2a343a474c4b45382a1c0c0000000000031628394b6074879daabbcebbaa9f8d80766e6c6f788398a0b49f8b78634d3a2a18040000000a1f33465872879cb1c2aa957f6a55402a15000b1f34485972879db2b19c86715746321e090010253a4f657a8b969d9fabafb3c0c4c7d0c9b6a49c97948b7d66513c27110000000000000000000000000000000000000000000000000000000000000006192c3c556a7f95a7b8b49f8b77624c5a627886979fabb3b8c5bab4ab9f95806b5f4d4c5e677d8c9da6b3b8c5c1c8bbb4a59d8877624d40301d01000000000e23384d63798b9fa9adaa9f8c79634e38230e000000000000000f1f30404d5e66798590979b9c9a94897c69604f402f1b0b000000000000000000000e1e2c3b474c5d656d7173716b635b4b433626180800000000000003182d42586d826d677d807f78826d7f7d82807c8278836e827b817e837f7a657a817f7d7d7d847e7b8076614c37210c00000000000000000000000000000000000e23384d63788da6b4bac6b7a68c77614c37220c00000000000000000013283d53687d9281798fa3a5927d6756586f8499afc7d8d9c9a8937e68533e291300000000000000000000000000000000001022374b5d6f849aafb6c3d4ddc8b39e8874604b35200b000000000000000000000000000000001e33495e73889ea1b4b9c6b7a68b75604b36200b00000000000d181f2a33373631271a0c000000000000000b1e324556657b8c9fb4bcc8bbab9f95898382848b99a1b1a195806b5b49351c0c000000000417293a566b8095a9b5a48f7a65503a25100005182a3b586d8298aaac97816c57392816030014293e54697e93a4afb3b8c5bbbdbebebebec2b6b1adaa9b86715c46311c00000000000000000000000000000000000000000000000000000000000000000e21364c6176899eaba396816c5948485a6275828c979ea7a4a99f998c806b625141404d5f677b88959ea7aaacabaa9f97877963594834221200000000000c2135495b677d8b9598958c7d675b4935210c0000000000000001122230404d5b63717b828687857f77665e4f423222120000000000000000000000000e1d2a343f4b4f585c5d5b564e493d302618080000000000000004192f44596e847f7c8082827e826d7f8178826d7d7c846f827f7975837f7a697e7a72827c817a8281837c67523d271200000000000000000000000000000000000c2035495a73889db3c8d5c4a5907b65503b26100000000000000000000c21374c61768a8875859bb09d87746052687d92a9baced5c0ab96806b56412b160000000000000000000000000000000000081b2e3f4f647a8fa1b3c7d7d5c5ad98836d5443301c08000000000000000000000000000000061b31465b70869bb0c3cdc5b29d88735645311d09000000000000050c171f21201d150a0000000000000000021628384b5d687e939fabb8c4bcb5a79e99979a9fa9b3a0978372604a3c2c190000000000000d22384d62788b9fa89c86715d4b37230e00000f24394f647a8c9d9d8e7a644f39240f00000d22374d62778693999ea7a4a6a7a8a9a9a9a9a9a9ab9f99836f59442f1a00000000000000000000000000000000000000000000000000000000000000000a1f334658667c8c98958575604b3b3c4857616d7982888d8f8d8a837a6a6151443430414d5d6575808991959796928b8176635b493b2b1804000000000006192c3c4d5f677880828078675f4d3d2c1a060000000000000000041222303d4a4e5e666d71726f6a61594d4032241404000000000000000000000000000c181f2e373a424748464138352c1c1408000000000000000000182d42586d826d8278828278837f80817e7b81817586828078817f817f7a697e796d827c81807a818277624c37220d000000000000000000000000000000000006192c3c586e8398adc3d4bfa9947f6a543929170c0a030000000000000a1f3347586e84927d7c91a3a5947f6a5961768a9fb4c9d8c3ad98836e58432e190000000000000000000000000000000000001022364a5c6e8399a9bacdccb8a7917c67523626140100000000000000000000000000000000152a3f546a7f94a5b5c2b7a797816c57382715020000000000000000040a0c0b0902000000000000000000000a1a2e3f4e60697e8d9da6b2b7c3b9b3aeacafb3a79e928273605443301e0e0000000000000b2035485a6a7f8f938979634e3f2e1c0800000d22364a5c677d88887e685c4a36220d00000b2034485962757e84898c8e919293949494949494918b8478624d38220d00000000000000000000000000000000000000000000000000000000000000000417293a4c5e667b828075615745322b39464b5b636c74787978766e645c5043342623303f4b57616b757b8082817d776c6158493d2c1d0d000000000000000e1e30404d5a626a6d6b635a4d41301f0e0000000000000000000004121f2d36404c51585b5c5a554c473a3022140600000000000000000000000000000004101b22252d3233312b23211a0f010000000000000000000a162b40566b80807c676d6d626e6a6b6c69666c6c61716c6b626c6a6d7f7a667c78697e696c6a646c6c625947341f0b00000000000000000000000000000000000013293e53687e93a8c2d2c5af9a857057463325211e170b00000000000417293a50657b908775859bab9e897762586f8499aec7d8c4ae99846f59442f1a000000000000000000000000000000000000071b2e3e4e63798b9fb4c2c5b39e8875604b36200b00000000000000000000000000000000000c21364b6175879ca4a8a59d8979634d38230e0000000000000000000000000000000000000000000000000000102131424f60697c88949da5a8abacaba8a69d95897d6d6055443625130000000000000005192b3c50616a7b7e78635b4a362111000000071b2d3e4d5f67737368604e3e2d1b07000005182b3b485761686f7377797b7d7e7e7f7f7f7f7e7c776f625a4834200b0000000000000000000000000000000000000000000000000000000000000000000b1b2f404c5d656d6b61574639281b29323d4a4e546062646360564f4a3e33251613212e39464b5660666b6c6b6862594c473a2c1f0f0000000000000000001222303c484d5558554d493c302313000000000000000000000000010f1a212f383b424647453f37342a1c1204000000000000000000000000000000000000080e10181c1e1c160e0c06000000000000000000000a1a28323650626b6b675f58584d59545657535157574b5c57564d57546169645e666361696156554f56574c473b2a18050000000000000000000000000000000000000d23384d62788da4b5c9cab49f8b76614c363a3633291b0c00000000000c23384c5d7185947f7a8c9fa898826d5f677d92a9bacec5af9a85705a45301b00000000000000000000000000000000000000102135495b6a7f94a3b5b8a696806b5645321d0900000000000000000000000000000000000a1e324657637886909390877b655b4935210c000000000000000000000000000000000000000000000000000002142432424f5e66767f878e93969796938e887f7668604b443727180800000000000000000e1e3343505d6568625a4a3d2d1a0300000000102031414d525d5d534e42312010000000000d1d2b39464b535a5861646668696969696969696761594d483c2b19050000000000000000000000000000000000000000000000000000000000000000000012222f3f4b4f58554b4639291b0b161e2d3636434a4d4f4e4b4538362d20150703111b293338454b51555756524c473b33291c0f0100000000000000000004121e2b353840434038352c1e1305000000000000000000000000000007121d24262d3132302a221f180c0000000000000000000000000000000000000000000000000000000000000000000000000000000002162838454b575a5e5b554e493d38433f40413e3b4142364642403842434f544f4c514d4f544f42403a414237342a1d0d000000000000000000000000000000000000000b2035495a71869cb1c8cebbaa927d67544d504b4639291c0c00000000091c2f3f50657b9089788095a2a0917d6761768a9fb4c9c5b09a85705b45301b00000000000000000000000000000000000000061a2c3d4b6073869ba7a79e8876614c38281502000000000000000000000000000000000003162939495a63737b7e7b75655d4b3c2c190600000000000000000000000000000000000000000000000000000006142432404c57616a73797e8081817e79736a61584e4231271909000000000000000000001525333f4b50534d493c2d1f0f0000000000021323313a3d48483e3a3124140200000000000d1b2832363e3a474c4f515253545454545454514c473b342b1d0d00000000000000000000000000000000000000000000000000000000000000000000000412212e373a43403633291b0b00030f1a21253035383a38363228221b10020000000b171e2832363c4042413d37342a1f170c000000000000000000000000000e1920222b2d2b2320190e000000000000000000000000000000000000090f11181c1d1a150c0a040000000000000000000000000000000000000000000000000000000000000000000000000000000000091e324556606c6f73706a635b534c473b4038454b453839373435313538353f39363c383b3e3b322b252c2d221f180d000000000000000000000000000000000000000006192b3c546a7f94aabbcec8b09b85736062656157473a291704000000001123384c5d6d82988575849aa49e8979636f849aafc4c3ae99846e59442f1900000000000000000000000000000000000000000e1d3144556379899493897a645847331a0a000000000000000000000000000000000000000b1b2c3c49546065696660574b3f2e1e0e00000000000000000000000000000000000000000000000000000000000614222f39464c546064686b6c6b696460544c473a311d150900000000000000000000000715212e373a3e38352b1e0f0100000000000005131e2528333329261f1406000000000000000b161e21292a3337393c3d3e3f3f3f3f3f3f3c37342a20190d0000000000000000000000000000000000000000000000000000000000000000000000000003111c23252d2b211e170b000000000708131c20232423211e160a07000000000000030a161e21262b2d2c28221f180d04000000000000000000000000000000050b0d1518160e0c0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b21364b60768285888580797169615956564c5660564d4f4d484b44494e4a484d4c46393e35404337342a1d0d0b05000000000000000000000000000000000000000000000e22384d62788b9fb4cac9b5a3927d71787a75615847331f0a00000000091c2f3f4c617787968176869ca59d87786a7f94a9bfc5ab96806b56412b160000000000000000000000000000000000000000011527374a5b63787f7e77645c4b3a2a170000000000000000000000000000000000000000000e1e2c36434b5053514b45392e21110000000000000000000000000000000000000000000000000000000000000004121b293336434a4f53565756534f4a4336332a1c13020000000000000000000000000003111c2325292320190e000000000000000000010a10121e1e13110b0200000000000000000003090c13181f2224262829292a2a2a2a2927221f180c0500000000000000000000000000000000000000000000000000000000000000000000000000000000080e1018160c0a030000000000000000070b0d0f0e0b09030000000000000000000003090b11161716130d0b0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080b0d0c0a04000000000000000000000000000000000000000000000000000000000000091e324556606c6f777f898e867e77706c6b616376675f64625960555b63605962615758544b56584c473b2a190900000000000000000000000000000000000000000000000b2034485a6e8398aebecfc1b39e89868d8f8776614c37210c0000000000111f344759647a8b947f77879ba39d887c7e93a8bdb9a7907b66513b261100000000000000000000000000000000000000000009192d3d4a5962696962594b3e2e1c0c000000000000000000000000000000000000000000000e182630353b3e3b3632281b11030000000000000000000000000000000000000000000000000000000000000000000b171e253035393e4142413e393530251f170c0000000000000000000000000000000000080e10130d0b06000000000000000000000000000008080000000000000000000000000000000000040a0c0f111314141414141414120c0b040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c0e1515110b090200000000000000000000000000000000000008141c2022211f170c060000000000000000000000000000000000000000000000000000000002162838454b5759616976808a938a8581807679887d697977667567677872647776616e69606b6e61594737271c130800000000000000000000000000000000000000000005192b3c4f647a8fa0b2c6ccb9a89e9ba3a5947f69543f2a14000000000004182a3a4a5c667c8b8d7e77859ba69d918c9fb4c5b39e8975604b36210b000000000000000000000000000000000000000000000f1f2d3b484d54544c483b2e201000000000000000000000000000000000000000000000000008141c20262926211e160a0000000000000000000000000000000000000000000000000000000000000000000000000308131c2024292b2c2c2924201c130804000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b0d0e0b0902000000000000000000000000000000000000000000000000000000000003090b0d0b080200000000000000000000040a0c0b080100000000000000000000010f1a21232a2b27201d150a0000000000000000000000000000000614182630353836332920190e000000000000000000000000000000000000000000000000000000000a1a2832363b474c58616b777e8a948a7f70859a887e8a857b897d7d8a8079898477837e75808377615544353025180a0000000000000000000000000000000000000000000d22364a5c6e8298a8b9c9c6b9b3b0b5ad98836e58432e190000000000000c1c2d3e4c5e667b8a937f7688969fa99faabbb8a696816b5645321e0900000000000000000000000000000000000000000000010f1d2b34373f3e37342a1d10020000000000000000000000000000000000000000000000000001080b1014110b090300000000000000000000000000000000000000000000000000000000000000000000000000000000070b0f13161716140f0b070000000000000000000000000000000000000000000000000000000000050b0d0d0b050000000000000000000000000000000000000000000000000000000000000000090f111718150d0b050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a0d19202223201d150a0000000000000000000000000000000000000000000000000000040a161e2122201d150904000000000000060c171f21201d1409020000000000000005131f2c35393f403c3631271a10030000000000000000000000000715243136434b4d4c463a352c1e0e000000000000000000000000000000000000000000000000000000000a161e212a343a4a5b657b86867f776a6c819684949c86898a89888885869c89888985858281857360534a4336281a0a0000000000000000000000000000000000000000071b2d3e4d6277899eabbccfccc9c6c3ae99836e59442e190000000000000010202f404c5d657985948688818b9fb4bbb7a99e8876614c382816030000000000000000000000000000000000000000000000000d1920222a29221f180d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d181f22221f180d040000000000000000000000000000000000000000000000000000000002121d24262c2d2a221f180d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005131e252b3437393631271a130500000000000000000000000000000000000000000000000c181f283236383631271f180c000000000e19202933363531261d15090000000000001323313d494e5455514b45382e2112040000000000000000000001152533424e54606261584d493c2c1c0c0000000000000000000000000000000000000000000000000000000002090c1823394e63798a7b70827e69647a8e878298838697828b917c889882889580888975817e72686054453828160300000000000000000000000000000000000000001020344859667c8d9fb4bcc9d1cebeab96816c56412c17000000000000000212222f3f4b5b6374808b87788196abaca69d8b7c665847331a0a0000000000000000000000000000000000000000000000000000050b0d14140d0b05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090b0d0c0a0400000000000000000000000000000000000000000000000202000000000000000000000000000000040b0c0b090200000000000000000000000000000b171e2a343737342a1f180c000000000000000000000000000000000000000000000000000009151d2f383b42433f37342a1d12040000000000000000000000000000050b0d1113110e0c060000000000000000000000000000000000000008162330393b484d4e4b4538312313030000000000000000000000000000000000000000000c1c2a3439454b4d4b4437342a1c0c00000e1e2c353a464c4b443731271909000000000c1c31414e5b636a6a6660564b3f2f2212030000000000000000000f1f33435060687477766f625a493a2a180400000000000000000000000000000000000000000000000000000000000014293f54697e897571868978656e83947f878c7e8a897f94837b8c8a7c8b897d8b818593877e72605645321e10000000000000000000000000000000000000000005182b3b4c5e6a7f939fabb4c0bab4a0907b65503b251000000000000000000412212f3d4956606b78838a8b97989792887b665e4c3a29170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070b101515110b0801080a161e2123211f170c08010000000000000000000000000000000000070c0e18180f0d0700000000000000000000050c181f22211e160a0000000000000000000000000b1b29333b474c4c483b342a1d0c00000000000000000000000000000000000000000000000009192731404c515758544c473b2f2212000000000000000000000000080d18202226282723211a0f090300000000000000000000000000000001162634414d5259626360564e41312211000000000000000000000000000000000000000009192a3a474c57606260554c473a2a1c0c0c1c2c3c494d586160554b443727150200000417293a4e6068797f807c74655d4c402f21110000000000000000061a2c3d50616a7e888d8b8478625847331f0800000000000000000000000000000000000000000000000000000000000011273c51667c917d677d92877b6f788a897d92877e9383828a7a7f94837d928480937e7f86918374604b3e2e1b0700000000000000000000000000000000000000000d1d30404f616a7e8c9aa2a5a99f96826e5d4b37230e00000000000000000003111f2c38454b5a626e767d8183817d75655d4c402f1c0c0000000000000000000000000000000000000000000000000000000002090b0f0e0b0801000000000000000000000000000000070b0d0c0a0300000000000000000000000008131c20252a2a26201d141c2328323638363329201d14090000000000000000000000000000010f1a21242d2d24211a0f01000000000000000d18202a34373632281a110400000000000000000003172939464c596262594c473b2a18040000000000000000000000000000000000000000000002152737444b5e666c6d6a62594c402f1e0e00000000000000000003101b222b34373c3d3c39362c211e160b00000000000000000000000000000f1f3444515f6771777875685f4e402f1c09000000000000000000000000000000000000021527374759616e7677756d6159473a2a17182a3a495a637176746b605544311d0800000a1f334758687e8c949591877b665e4c402f1e0e000000000000000c2135495b6a7f939da69f9a8876614c3626140100000000000000000000000000000000000000000000000000000000081c2e3f4b60758889786c819790847b809580818877817f7686898486907b80867686877e797c89826d5c4a36220d000000000000000000000000000000000000000000122232434f60687a858c90908a8073604b3f2f1c0800000000000000000000000e1a28323c494d5861686c6e6c6760574b3f2f2212000000000000000000000000000000000000000000000000000000010a151d202423201c140800000000000000000000000008131c2022211e170b000000000000000000000c182530353b3f403b3531262e3738454b4d4c463a353126190c000000000000000000000000000f1f2d3639424239362d1f0f0000000000000d1d2b343b474c4b45382f22110000000000000000000a1e334657616f777770615947341f1100000000000000000000000000000000000000000000081d314455606e7b81827f77665e4c3c2c1906000000000000000715212e373b484d5152514e493d3632281b13030000000000000000000000071a2d3d51626b7d868c8e897d685e4c38230f000000000000000000000000000000000000081d3144556177838b8d8a8277615847331f1f3347586378858b898073604b36200b00000c21374c61768a9faaaaa59d8c7c665e4c3c2b19090000000000000e23384e63798c9fb3b7b5a696816c5443301c08000000000000000000000000000000000000000000000000000000000e23374b5d65777e93867675858b879089988b7e7e7b7a6a61767e787586877679887b848275677b8b79644f3a240f00000000000000000000000000000000000000000004152532424e5c6470777b7a776b605544312111000000000000000000000000000a151d2c353a474c52575857524b45392f211204000000000000000000000000000000000000000000000000000008141c28323639383530261811030000000000000000051318253035373633291b1507000000000000000c1c2a36434a505555514b44373f4b4f5660626158534b4437291c0c00000000000000000000000c1c2d3d4a4e57574e4a3d2d1d0d0000000005182b3b484c596160564c402f1b0b000000000000000a1d30414c6175838c8c8477614c3f2e1c080000000000000000000000000000000000000000021527374b607382909798948a7c665a49352012000000000000071525333f4b4f5962666866635b544b4639311e160a000000000000000000000c21364a5b6b80929ca4a79e907b66503b26110000000000000000000000000000000000000b20364b607485999fa99f978676614c37212a3a4c6176879ba39e957f6a55382816030010253b50657a90a9bac3b6aa9f8b7c655a48372614010000000000152a3f556a7f94abbccbc4b49e8974604b35200b0000000000000000000000000000000000000000000000000000000010253a50657b88738195877b7a8b747b7f828b9486868578706b686263798a81778986726d615d6d827c67523c271200000000000000000000000000000000000000000000071524313e4b4f5962656561584b44372614030000000000000000000000000000020e19202933373d4243423d3632281b110300000000000000000000000000000000000000000000000000000818263038454b4e4d4b43362f2111020000000000000715233136434a4d4b463933251505000000000004172a3a475460656a6a666055474e5d656f75787671696055463a2a1c0c00000000000000000004172a3a4a5b636d6d645c4a3b2b18050000000b2034485962707775665e4c392816030000000000001024394d5f6f8399a1a29a846f5d4b37230e0000000000000000000000000000000000000000081d3144556b8095a0acada89e8a78624d41301909000000000215253343505d6570777b7d7c78726961574e4132281b0a0000000000000000000e23394e63798e9eb1b5b8af9a846f5a45301a05000000000000000000000000000000000012283d52677d92a3b4bab4a495806a5539293447596d8298a5b5b29d88735645321e090010253b50657a90a5c2d2c8baa99e8978625544311d0b0000000000182e43586d8398adc9daccb9a88d78634e38230e0000000000000000000000000000000000000000000000000000000c1d2a43586e83927d73808b908c806b666a6d7d92807983868581786860687e826d7b816c544b4f647974604b36211204000000000000000000000000000000000000000000000614202e373b484d50504c473a312619090000000000000000000000000000000000060c171f21282c2e2c27211e160a00000000000000000000000000000000000000000000000000000001142636434b5660646360544c3f2f2110000000000004152533414e5460626157504333231201000000000a1f33475861727a7f7f7b73615860687b848b8d8b867e736158473a2a180800000000000000000a1f334758637982827a64594834200b000005192b3b4c6277858c897c665746321e0900000000000114263751677c91a1b3b4a2907b65503b251000000000000000000000000000000000000000000b20364b6075899eb4bec6b9a89a846f5f4d372715010000001020324350616a7b858c9192918e877e75685f4b4539281a0a0000000000000000152a3f556a7f94aabcc9c9b39e89745e49341f090000000000000000000000000000000000192e44596e8399aec1cec2b29d8872574633374c61778b9fb4c3b7a68b75604b36210b000d22384d62788da4b5c9d7c7b9a79a8473604b3a29170400000000192e44596e8399aec3c8d1c6a5907a65503b2510000000000000000000000000000000000000000000000000000004182a3b4752677d9288766b797f7d737b72605f697e7b807c7d838b8b7e6874827560656c6251464b5c646056483b2f2212020000000000000000000000000000000000000000000002101b222b34373b3b37332a1d14090000000000000000000000000000000000000000040a0c13171917120b090300000000000000000000000000000000000000000000000000000000081c304354606a75797873655d4c3f2e1b080000000012223343505f687377766a615041301d0a000000031729394c61768490949590847661687e8c9a9faba49c93847661584736251300000000000000000c21374c61768997978977624c37220d00000b203448596e8398a39e8975614b36210c0000000000081d3144556f849aafbfc0aa957f6a55402a1500000000000000000000000000000000000000000d22384d62778da8b9cdd6c6b4a2917c675544311d0a0000071b2d3e4f616a7f8d9aa2a6a7a6a59d94887d6d6057453828190900000000000003192e43586e8398adc3c9c9b49e89745f49341f0a00000000000000000000000000000000001d32475d72879cb2c7dccbb7a58b76614b363d52677d92abbccfc4a28d78624d38230d000b2035485a71869cb1c3d4d6c5b4a2937e685846331f0a00000000192e43596e8398aeafb4c0bba6917c66513c271100000000000000000000000000000000000000000000000000000b1f344759616a708496816c636a697f8a806b61757a676a78746e7884927d7e927d676161584c5761686b6962594c402f2010000000000000000000000000000000000000000000000000080d1820222625221f180c010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071a2d3d4b607280898e8d877b655d4b37220f0000000a1a2f4050616a7d888c8a7f6a5f4d3924100000000a1e3346576d8298a2aaaaa29a846f7a8b9faab5bcb6b1a29a8576615443301c0c0000000000000013253654697e93a7a796806b563a2a1704000d22374d62778b9fb4a7927d685339281603000000000b20354b6075899eb4c9c0ab95806b56402b1601000000000000000000000000000000000000000b21364b60768a9fb4cadfd0c0b29c8774604b38281603000d22364a5c6a7f949fabb4c0bdc3b7b2a79e928275605645372614010000000000061b31465b70869babb1b5c1b49e89745f49341f0a00000000000000000000000000000000001f34495e74899eb3c9ded4c3a28c77624d3739586d8298adc9cbb8a68b76614b36210c0005192b3c53687e93a5b7cadfd1c0b39e8876614c38281502000000182e43586d83989f9aa2b4bca6917c67513c271200000000000000000000000000000000000000000000000000000c22374c6177807678898c7c665b738888847f6d82897c7b8a806a7a80848b7d8d89777677665e61757d807e77665e4c3e2d1b0700000000000000000000000000000000000000000000000000050b0d10100c0a04000000000000000000000000000000000000000000030a0c0b0801000000000000000000000001080b0d0e0d0b050000000000000000000000000000000c21364a5b6c81959ea8a49c8b7b654f3d2d1a0700021628384c5e6a7f929da69f917c67513c27120000000c21364b61768a9fb4c0c0b4a2907b859baabbc8cfcac0b4a39a8472604a3a2a18040000000000071c3043546f859aafb29c87725847331f0a0012273d52677d92abbcae99846f5745321e09000000000e23394e63798ea8b9cdbea9947e69543f29140000000000000000000000000000000000000000091e3245566f859aafc2d2decab6a4937e685645321e0c06192b3c4f647a8c9fb4bcc9d1d2d4cac5b8b3a0978474605544311d0f0000000000031628395d73889d969ba3b5b49e89745f49341f0a000000000000000000000000000000000020354a60758a9fb5cadfcdb7a28d78624d38465772879cb1c7c8b39e88735746321e0900000e20364b6074879db2c0d1e0cbb8a6957f6a5645321d09000000182d42586d82978b859aafbca7917c67523c271200000000000000000000000000000000000000000000000000000d22384d62778d88807f8a8979666c81947f847f8d84868689857e8688838985829885898a7c667285808088897c665c4a36220b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090f11171e21201d14090a00000000000000070b151d202323222018130b080100000000000000000000000e24394e63798c9fb4b9b6a99b85715b4a36210c00091e324556667c8d9fb3b7ad98836d58432e1803000011263c51667c91a9bacdd0c0b59f8b9ba3b5c8bbc1c5cec1b3a1947e695947341f0c00000000000b20354a6074899eb4b6a58c76614c37210c02172c41576c8196acc9b49f8a76604b36210b0000000012273c52677c91a7c6d7bca7927d67523d281200000000000000000000000000000000000000000316283851677c91a4b5c9ded3c3b29d8875604b3a29170b2035495a6f849aaabbcedad8cec9c2c7cabeb1a2998373604b3d2d1a0700000000091e324657748a9680859bb1b49e89745f49341f0a00000000000000000000000000000000001f354a5f748a9fb4c9dfcdb8a38d78634e384b61768b9fb5cac9ad98836e58392816030000091d314556677c91a2b4c8ddd5c5b39e8875604b36200b000000182d42576d829784778ca1b7a8927d68533d281300000000000000000000000000000000000000000000000000000b2034485a6a7f868a8e9196887c7979898978858a8b7d879a84848a88808a9580889883858a787a8f7c7d77838a7a644f3929170300000000000000000000070c0e151b1d1d1a130b0902000000000000000000000000000000000000000000000000000000121d2426293336353126241d120400000008131c20273135383837342b28201d150900000000000000000000152a3f556a7f94abbccdc7b5a38e79634e39230e0417293a4b6075879dabbcc4ae99846f59442f1a040000142a3f54697f94a9c7d7e3cfbcab9fabb5b5b0a6acb1bdcebfb49e8a77614c3a291704000000000d22384d62788da8b9c3a58f7a65503a2510011527375b70859ab0c5baa9907b66513b261100000000152b40556a8095aabfcfbaa5907a65503b25100000000000000000000000000000000000000000000b20354b6073869cb1c0d1dfcbb7a6947f6a5847331f0d23384d62788da2b3c8d9d8c7bab4adb2b6c3c0b2a1947f6a5b4a362110000000000c21364b61768b8e798398adb39e89745e49341f0900000000000000000000000000000000001f34495f74899eb4c9deceb8a38e79634e3a50657a8fabbccfbcab927d67523d2812000000021527384d5f70859ab0bfcfe0cbb8a6927d6752382816020000172c42576c819784778ca2b7a9947e69543f291400000000070d0f12100b0802000000000000000000000000000005192b3c50616a7175797c808d9086868999877e849a87798795808497827e93897f94897e86837e939092827484846f5746331e0a0000000000000000070f1a21242b3032322f28201d150a00000000000000000000000000000000000000000000000008131c2f383c39464c4b443739301f170b000c1825303537444b4d4e4d483b3d353127190f010000000000000000182d42586d8297adc9dad2c1a7927c67523d27120a1f3346586a7f94a5b7c9c1ab95806b56402b16010001172c41566c8196abc1d6ecdac9bcb5bcb5a39b90979fb1bfcdb9a896816c5846331f0a0000000010253a50657a8fa5c6bea8937e69533e2914081d31445573889db2c8c7a9947f6a543f2a1500000000132536586e8398adc3d6c6a38d78634e38230e000000000000000000000000000000000000000000081c304354667c90a2b4c8dcd4c4b39e8976614c3b2b18293e53697e93a8c0d0e2cebaa99f989ca5b1bdbfb49f8b79634e3f2e1b080000000d22374c62778c8d788499aeb39e88735e49331e0900000000000000000000000000000000001e34495e73899eb3c8deceb9a38e79644e3f54697f94a9c9cab59f8b77614c37220c000000000a1a30414f647a8fa1b3c7dbd5c4ae99836e5645321e090000172c41566c819684778da2b7ab96816b56412c16000004101b22242825201d150900000000000000000000000000000d1d33435055566063666b7e8c86777383917c7684978278878c7d84937e7f9486818a847f947f94868385707a8c76614b36210c000000000000010f1a212d363940454847443d3631271a0f0100000000000000000000000000000000000000000008182530404c515a57616055514d4133291b0c1c2936434a525560626362595a524b44372d1f0f0100000000000000192e44596e8399aec3d8d3bda8937e68533e29131527384c6176899eb3c3c8b4a38f7a644f3a240f000002172d42576c8297acc1d7ece7dacfcab9a89b857b8197a1b3c9c6b49f8a76614c36210e0000000011273c51667c91a6bbc1ac96816c57412c170b20354b60758a9fb4cac2ac97826d57422d18020000071c30435471869cb1c6cdb9a88b76614b36210c000000000000000000000000000000000000000000011426364c5e70859ab0bfd0e0ccb8a795806b594834202d43586d8298adc2d7dfc9b49f8b8287979fb0bdbaa99a84705d4b37220d0000000e23384d63788d8c76859aafb39d88735e48331e0900000000000000000000000000000000001e33495e73889eb3c8ddceb9a48e79644f3e596e8399aec3c8b09b85705947341f0a00000000001222374b5c6e8399aec2d3dec9b49f8975604b36210b0000162b41566b809684788da2b8ae99846e59392816030c171f2d36393d3b363127190f01000000000000000000000000001525333c38454b4e5160687b89887a77878a7a7584937e78878a7b858d798195808489838a8183908c7e69748978634d38230e0000000000000f1f2d363d4a4e555a5d5c59524b45382d1f0f000000000000000000000000000000000000000000132536434a5e666f74767570675f4c463a2a1c293a475460677075787877746f6860554a3d2d1f0f00000000000000192e43596e8398aec3d8d3bea8937e69533e29141d3145566a7f95a7b9ccc1b09b85705c4b37220d000003182d42586d8297adc2d7ecf7ebd9c9b39e897766728399abbccdbaa9937e69533c2c190600000012273c52677c91a7bcc3ad98836e58432e190d22374d62778cabbccfc5af9a85705a45301b0500000b20354a6074899fb4c9c9b49e89745746331e0a0000000000000000000000000000000000000000000008182f404f647a8fa1b3c9d9d6c5b49f8a77624d3c2c30455b70859ab0c5dad4bfaa957f6d7581969fb0bfb4a28f7a654f3b2a180500000e23394e63788e8a75869bb1b29d88735d48331e0800000000000000000000000000000000001d33485d72889db2c7ddceb9a48f79644f4a5c73889eb3c8bbaa957f6a553a2a18040000000000081b2e3e50657b90a4b6cadecdbaa98e79634e39230e0000162b40566b809583788da2b8b19c87715745321e0c1c29333e4a4f52504b44372d1f0f000000000000000000000000000715202828323639414e5d6578848b7f7989887875848c7c78878878817373857d77877786826e7b7c6960718674604b36200b00000000000e1e2d3d4a4e5b636a7072726f6860564a3d2d1e0e00000000000000000000000000000000000000091c304354606c7c848a8b8a857c6e6158473a2a39475861727d858a8d8d8c89847d73635b4a3d2d1b0b000000000000182d43586d8298adc2d7d3bea9947e69543f291420364b6075889eb3c5c9b5a3907c66513e2e1b07000003192e43586e8398adc3d8edf7e3cfbcab95806a5963798c9fb4cac7b19b86715a4935200c00000012273c51677c91a6bcc4af9a856f5a45301a0e23384e63788da3c9d9c7b19c87725c47321d0700000d22374c62778ca9bacdc7b19c87725c3929170300000000000000000000000000000000000000000000001222374b5d6e8399abbccfe1cdbaa997816c5b493531465c71869bb1c6dbd2bca7927d67606c8196a1b3c0ae99846f5947341f0b00000f24394e64798e8a75879cb1b29d88725d48331d0800000000000000000000000000000000001d32485d72879db2c7dccfbaa48f7a654f4e64798ea6b8c9b49f8b78624d38220d000000000000001020354a6073879cb1c6d7d7c7a5907b65503b26100000152b40556a809584778da2b7b49f8a76604b362117293a464c5c64676560554a3d2d190900000000000000000000000000030d0a151d2024313f4c5a6273808c857f8986777d89897a7a8985797a7e777262756175746066665e617779645544311d080000000006192c3c4a5b63707980858787847d74635b4a3c2b1909000000000000000000000000000000000009192e3e4a607281919a9fa99f9a918376615947384657617684929a9fa9a3a89e9a928579635b4a3a2917040000000000172d42576c8297acc1d7d4bfa9947f6a543f2a1b2e3e52677d92a6b8cbc2b09b85715e4c38201000000004192e44596e8399aec3d8eef4dfcab49f8b77624c5b6f8499aec6c9b5a38d78634d38230e00000011263c51667b91a6bbc6b19c86715c47311c0f24394e64798ea3b9cec8b29d88735d48331e0000000f243a4f64798fa4c7d7c5b09a85705b45301b000000000000000000000000000000000000000000000000081b2e3f4e63798c9fb4c7d7d7c7b49f8b78634d3e2d455b70859ab0c5dad1bca7927c675260728399a6b7b49f8b77624c37220d00000f243a4f64798f8a74879cb2b29d87725d48321d0800000000000000000000000000000000001d32475c72879cb1c7dccfbaa5907a6550556b8095aac5bcab99836e5a4835200b00000000000000071c304354697e93a8b9cdd6c6a48f7a654f3a25100000152a3f556a7f9484778ca1b7bbaa8f7a654f3a251f334658616f797d7a74635b4a3726140100000000000000000000000000000002090b13212f3c4855606a798592889c867779868f8382898d837f696055605660605550514d5961645c4a37271502000000000c2135495b6379858e959a9d9c99928679635a4837271502000000000000000000000000000000021527374a5c6b80969fafb4b6b1afa19986776156454b6175859aa2afab9f9c9da6afa39b8979635846331f0e0000000000172c41576c8196acc1d6d5bfaa95806a55402b22374b5c70859ab0c5c9b5a3917c6651402f1d02000000051a2f445a6f8499afc4d9eeefdac4af9a846f594851667c91a8b9cdc2a9947e695437261401000011263b51667b90a6bbc7b29c87725d47321d10253a4f657a8fa4bacfc8b39e89735e49261401000011273c51667c91a6bbd1c3ae99846e59442f19040000000000000000000000000000000000000000000000001021364a5b6d8297a9bacde2cebbaa98836e5c4a3643596e8398aec3d8d4bfaa947f6a55546176889db2bcab937e6853362513000010253a4f657a8f8974879db2b29c87725d47321d0800000000000000000000000000000000001c31475c71869cb1c6dbd0bba5907b66506074889db2c5b59f8d7a644f3c2b190500000000000000001325364c61768a9eb4c4cdb9a88e79634e39240e0000142a3f54697f9485768ca1b6c8a9947f69543828293a4c6176848e92908779635544311d0800000000000000000000000000000000000003111d2b37444b5b63707d88939a85707786877279887b69614a444b454b4b44373c3a474c4e4a3e2d190900000000000e23384d63798a9ba3aaafb2b1aea49c8878625544311d0d000000000000000000000000000000081d314455647a8c9fb4bbaea49c9ea6a49b8574604b5e6e8298a3b4a79e8c8788919fa9a79d8776614c3c2b190600000000162b41566b8096abc0d5d5c0ab96806b56412b2f404f647a8fa2b4c8bcab9b8672604a35201200000000051a30455a6f859aafc4daefe8d3bda8937e68533b4b6075899eb4c9c4af99846f5544311d08000010253b50657a90a5bac7b29d88725d48331d10263b50657b90a5bad0c9b49f8a745544311d08000014293e54697e93a9bed3c2ad98826d58432d1803000000000000000000000000000000000000000000000000071a2d3d4d62788b9fb4c6d6d8c8b59f8d7a644f3f40566b8095abc8d8d8c2ad98836d584658667b90a2b4af9a846f5443301c070010253a4f657a8f8974889db2b19c87725c47321d0e0b080100000000000000000000000000001c31465b71869bb0c6dbd0bba6917b6657687d92a6b7b8a797826d5c4b371e0e000000000000000000081f3346586c8196a6b8c9b49e8975604b36200b000014293f54697e9486768baabbc4ae99846f5645323346586e8399a1a7a59c8773604b35200b00000000000000000000000000000000000000000d1926313d4a4e5f67757e88806b6277806b637773604b4331353236353127272a343739362d2010000000000003192e43586e8398a8b4c1c5c7c7c2b5a69b8574604b3b2b180500000000000000000000000000000b20364b6074869cabbcae9d948788949da3947f6a59667c91a0b2b39e897a71737c8b9fb4a597816c5a4935200800000000152b40556a8095aabfd5d6c1ac97816c574228384c5e70849aafc0c4b59f8d7b655443301c0700000000061b30465b70859bb0c5daf0ead8c8a38e78634e3945566e8398aec3c9b49e8975604b35200b000010253a4f657a8fa4bac8b29d88735d48331e11273c51667c91a6bbd1cdbaa98a75604b35200b0001162b40566b8095abc0d5c1ac96816c57412c1702000000000000000000000000000000000000000000000000000f2035485a6b8196a8b9cce1cfbcab9a846f5d4b3b51667b90aabbcedcc7b19c87725a494c5e70859ab0b39e8974604a35200b0010253a4f657a8f8974889db2b19c86715c47312623201c140d0b0500000000000000000000001b30465b70859bb0c5dad1bca7917c676176889db3bdb39e8977614c3e2e1b000000000000000000000417293a4c6176889db3bbae99846e5645311d09000014293e53697e9387758a9fb4c9b49f8975604b36364c61768b9fb4bfb6a5907b65503b251000000000000000000000000000000000000000000009141d2d36414d56606975726059626b625962605544311d201e21201d1511181f2224221b10020000000000071c32475c71879cb1b6c2c9d2dcd2c4b5a3957f6a594834200b00000000000000000000000000081b2e3f52687d92a4b5b5a4947f71747f949e9e8a776273869cb1b9a8937e685c5e6a7f94aab49f8b78624d36251300000000152a3f556a7f94aabfd4d7c2ad97826d5842324556667b90a2b4c8b8a697826d5d4b3625130000000000061c31465b71869bb0c6dbf0e2cebbaa8b76604b363853687d93a8c5ccb9a88e78634e39230e00000f24394f64798ea4b9c8b39e88735e49331e12283d52677d92a7bcd2d7c7a18b76614c36210c0002172c41576c8196acc1d5bfaa95806a55402b15000000000000000000000000000000000000000000000000000005192b3c4c6176899eb3c4d5dac9b3a2907b6550404b61768a9fb4c9dfcab6a48d78634d4051667c91a8b9a88d78634e38230e000f253a4f647a8f8a74879cb2b19b86715c463e3c393530262220190d010000000000000000001b30455a70859aafc5dad2bca7927d676d8298a6b7b19f917c66594734201000000000000000000000000b1f334658677d919faa9f907b655038271502000013283d52687d928873899eb3c8baa8907b665037394e63788eabbccfc3a9947f6a543f2a1500000000000000000000000000000000000000000000010f1a213138454b55606054484c5651484d4b443726140b090b0b080100040a0c0f0d07000000000000000014293e53697e909ca4b1b5c1d1dfd2c2b49f8a77624d392916030000000000000000000000000d22374b5d71869bb0c2b19c867260606a8095a297826c7c90a4b5b49e8975604b4d62778ca5b7aa96816b5443301c0700000014293f54697e94a9bed3d8c2ad98836d58433e4b6074869cb1c0beb39e8876614c3f2e18080000000000071c32475c71879cb1c6dcf1dfcab49f8a75564532384d63788da7b8ccc6a7927c67523d271200000e23394e63788ea3b8c8b39e89735e49341e13283e53687d93a8bdd2ccb7a18c77624c37220d0003182d42586d8297adc2d3bea9947e69543f29140000000000000000000000000000000000000000000000000000000e1f3347586a7f94a6b8cbe0d0c0b09b85705f4d46576e8398adc0d0d3c2aa947f6a57454b6075899eb4a6917c66513c2711000f253a4f647a8f8a75879cb1b09b86715b5654514e4b433638342b1d150900000000000000001a2f455a6f849aafc4d9d2bda8937d6a7f94a0b2b6a497816c5e4d3b2a180200000000000000000000000417293a4d5f6b808c908b7f695d4b371a0a00000012273c51677c918974879cb2c7c6ac97816c5544394e63788ea3c9d9c1ab96816c56412c1700000000000000000000000000000000000000000000000007131a283237444b4a433637413d3437353126190900000000000000000000000000000000000000000012263b4f60697c86909ba3b5c1d1e1cdbaa996816c5746321e0a0000000000000000000000000f253a4f647a8fa3b5bcab927d68544b6072859a9f8b788399aec2ae99846e5745485972879db2b29d8773604a35200b00000013293e53687e93a8bdd3d8c3ae98836e59374a5c6b8096a4b6c2b2a0927d675847332111000000000000081d32475d72879cb2c7dcf1dec8b39e89735e382835495a73889eb3c8c0ab96816b56412c1600000d23384d62788da2b7c9b49e89745f49341f14293e53697e93a8bed3cdb8a28d78634d38230e0004192e43596e8398aec3d2bda8927d68533d281300000000000000000000000000000000000000000000000000000004172a3a4b6175889db3c3d3ddc9b5a3917c6755444f64798ea2b4c7d8c8b39e8875604b44556e8499aea8927d68533d2813000f243a4f64798f8a75869bb1b29d87726e6c6966636054544d483c31271909000000000000001a2f44596f8499aec4d9d3bda8937e7f949dafbaa99c8675604b40301d0c000000000000000000000000000c1c304150626b787b7769614f3f2f1c0000000011263b50667b908b75869bb0c6c8b39e8875604b384d62788da2c8d8c2ad98836d58432e1800000000000000000000000000000000000000000000000000000a161e263135353025222b292022201d1409000000000000000000000000000000000000000000000c1f32424f5e66737b859ba3b5c8d9d7c7b49e8976614b36210c0000000000000000000000061a2c3d576c8297acc1b59f8b77614c4354647a8fa298838c9fb4bea9937e6954393b596e8499aeb7a58f7a644f3a250f00000013283d53687d92a8bdd2d9c3ae99846e594455647a8c9fb4c2b6a498826e5f4d3a291703000000000000081e33485d73889db2c8ddf2dcc7b29d87725d48322c3c5a6f849aafc4c4ae99846f5937271501000d22374c62778ca1b7c9b49f8a745f4a251314293f54697e94a9bed3ceb8a38e79634e39240e00051a2f445a6f8499afc4d2bda8927d68533d2813000000000000000000000000000000000000000000000000000000000c1e324657697e93a5b6cadfd2c1b19c8673604b4a5c6f849aa9bacecbb8a6947f6a5c4a556a7f95aaa9947f69543f2a14000f24394e64798e8b76869bb0b7a58f8683817e7b78746f69625a4b4437271501000000000000192e44596e8399aec3d8dfc9b49f8a949daebbb49f8b7a64574532221200000000000000000000000000000013233344505a636662594f433221110000000010253a4f657a8f8c77859aafc4ccb8a7917b66513c4c61768caabbcec3ad98836e58432e190000000000000000000000000000000000000000000000000000000309141d20201c130d16140b0d0b0801000000000000000000000000000000000000000000000002142432404c54606575859baabbcee1cdb9a8927d67523d281200000000000000000000000c2135495b72879db2c7b19c87725947364b5c6f849aa0989faabbbba5907b66503b42576c8197acc3ab96816c563a291704000012273d52677c92a7bcd1d9c4af9a846f5a4b6074869caabbbaa89c8675614b41301c0c00000000000000091e33495e73889eb3c8ddf0dbc6b19b86715c46312c41566c8196abc1c7b29c87725544311d08000c21364c61768ba1b6cab49f8a755443301c152a3f546a7f94a9bfd4ceb8a38e79634e39240e00051a2f445a6f8499afc4d2bda8927d68533d28130c0d0e0d0b0801000000000000000000000000000000000000000000031628394b6074879cb2c1d2decab6a4927d6856454e63798b9fb4c1d1c4b49f8b7a645a54697e94a9a9937e69543e2914000e23394e63788e8c76859ab0c3b6a49c999693918e89847e786c605544311d08000000000000192e43596e8398aec3c8cbcdbaa99fa9aebbb09e937e695c4a39281604000000000000000000000000000000051626333c494d504d483b32251403000000000f24394e64798e8d788398aec3d5c5ae99836e5a494a60758a9fb4c9c1ac97826c57422d17000000000000000000000000000000000000000000000000000000000001080b0b070000010000000000000000000000000000000000000000000000000000000000000614222f36434a5763798c9fb4cadfd6c6ad98826d5837271501000000000000000000000e23384e63788da5b7c3ad98836e583a2e3e51667c91a7adb4bbc8c7a28d78634d3840566b8095abc0b19c87725846331f0a000011273c51667c91a6bbd1dac4af9a856f5a5b6a7f95a4b5bcb49f8a7963574633231300000000000000000a1f34495f74899eb4c9deefdac5af9a85705a4530293e54697e93a9becab49f8a75604b35200b000b20364b60758baabbcebbaa8a75604a3520152a40556a7f95aabfd4cdb8a38e78634e39230e0004192f44596e8499aec3d2bda8927d68533d282021222322201d150b0903000000000000000000000000000000000000000b1d314455677d92a3b5c9ddd3c2b29d8775604b4a5b6a7f95a3b5c3cdbaa99d8878655d6c8197aca7927d67523d2812000e23384d63788d8c77859aafc4c2b6b1aeaba9a6a89e9a938b8173604b35200b000000000000182e43586d8398adb2b3b8c4c7bab4babcb59f95806b604f3e2d1b0a000000000000000000000000000000000008161e2c35383b37342b1d140700000000000d23384d62788d8f798297acc2d7cab49f8c78624d435473889db2c8c0ab96806b56412b160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041218253039495b6d8298adc5d5dcc7b29c87725544311d080000000000000000000014293e53697e93a8c3bfa9947f6a543f2a364b6075889eb3c8cecebaa98b76614c363f556a7f94aabfb59f8b76614c36210c000011263b51667b90a6bbd0dac5b09a85705563798b9fb4beb09e927d675b4a392917050000000000000000071c304354748a9fb4c9dfe7d9c3ae99846e59442f273c51667c91a6bbcebbaa8c77624d37220d00081d314455758a9fb4cab5a08b75604b3620162b40556b8095aac0d5cdb8a38e78634e39230e0004192e43596e8398aec3d2bda8927d68533d303536383837353127211e160a000000000000000000000000000000000000021527374a6072859bb1c0d1dfcbb7a6947f6958464b6074859ba5b6c4c7b7a69d887b7177899eb3a68e79644e39240f000d22384d62778d8d778499afc4cec5c2c2c1bec6b9b4afaa9f96806b56412b16010000000000182d42576d8297a69d9da6b8cbcdc9bcab9f94816c62514232201000000000000000000000000000000000000000000e192023262220180d000000000000000c21364c61768b907b8196abc0cac7bcab96816c59475c71869bb1c6c8a8937e68533e291300000000000000070d0f0d070d0f0f0d0f0d0c100c0b100d0b0f0d0f0d0e0e0f0e0c0a0c0e0f0d0b100c0d0f0e0c06000000000000000000000000000000000000000000000008131c2c3d50657a8fa7b8ccdfcab49f8a75604b35200b00000000000000000001142637586d8298adc2bca7917c67523c273144556d8297acc2d7c9b49f8a745746333e53697e93a8bebcab907b65503b2510000010253b50657a90a5bacfdbc5b09b86706073859ba9bab2a096806b5f4d3d2d1b0b0000000000000000000b20354a60748aa9bac8cbd4d7c2ad97826d58422d253a4f657a8fa4bad8c8a48e79644f39240f00021527495f74899eb4c9b6a08b76614b3621162b40566b8095abc0d5cdb8a38d78634e38230e0003182d43586d8298adc2d2bda8927d685336434b4c4d4e4d4b44373632281b0a000000000000000000000000000000000000091c304354667b90a2b4c8dcd4c4b39e8976614c44556177879ca6b5c2c4b7a69e9087889ea7b39d8874604b35200b000c22374c61778c8d788399aec3bdb1acadb0b3b4bab4b3b1ad9c86715c47311c000000000000172d42576c82979d87889db3c8ddcab59f8d7f6c63524433241402000000000000000000000000000000000000000000060c0e110d0b0500000000000000000a1f3346587489937e8297acc3b6b2b6b49e8a77614c5b70859bb0c5bbaa8f7a644f3a240f0000000000010f1a2124211b222424212421212521202522202422242124232423211f21232422202522222423211a0f0100000000000000000000000000000000000000000000000f20354a6074889eb3c8ddcebbaa8d78634d38230e000000000000000000081d31445571869bb1c6baa48f7a654f3a25273753687d92a8bdd2c8b39d88735e39293e53687d93a8bdc9a9947f6a543f2a15000010253a4f657a8fa4bacfdbc6b19b86716a7f94a3b5b3a2988272604a41301f0f000000000000000000000b21364b60768ba0b4b2b7c4d4c0ab95806b56402b23394e63788ea3c9dabba6917b66513c261100001e33495e73889eb1b4b9a18b76614c3621162c41566b8196abc0d6cdb8a38d78634e38230e0002182d42576d8297acc2d2bda8927d685a5c5460616263626055544b45392816030000000000000000000000000000000000001325364c5e6f849aafbfcfe0ccb8a795806b594847596378889ca4b3bfc5b8b3a49c9ea6b8a796806b5443301c08000c21364b61768b9681879cb2c7b19f97989b9d9fa99f9e9c98917f69543f2a150a0000000000172c41576c8196927d7f94aabfd1bca7917c6a61524535261606000000000000000000000000000000000000000000000000000000000000000000000000000417293a5c72879c87889db2b6a59da5b6a897816c5d5b70859bb0c5b49f8a75604b36210b00000000000f1f2d3639362d363939363936363a36353a37353936393639383938363335383936363a37373a39352c1f0f0000000000000000000000000000000000000000000000071c3043546e8499aec3d9d8c8a5907b66503b26110000000000000000000b20354b6075899fb4c9b7a28d78624d382324394e63798ea3b8cec6b19c86715c47313e53687d93a8bdc3ad98836e58432e1900000f243a4f64798fa4b9cedbc6b19c86717a8b9fb4b5a39a847360544330231301000000000000000000000c21364c61768ba99f9da6b7cbbea9937e69543e2922374c61778cabbccfbca7927d67523d281200081d33485d72889d9c9ea8a18c76614c3721172c41566c8196abc1d6cdb8a38d78634e38230e0001162c41566b8196abc0d2bda8937e6c6f71747576777877757069605745321e0900000000000000000000000000030606040008182f404f647a8fa1b2c8d9d5c5b49f8a77624c3c495a63788699a1b2b7c3c2b5b1b3b8ab9e8976614c36261401000b20354b60758a9681879db2c2ac97818286888a8a8a8987837c69614f3631271a0c00000000162c41566b8196917b8095aac0d5c1ac97816c60544437281b0c00000000000000000000000000000000000000000000000000000000000000000000000000001b30455a7085937e7e93a9b29d879da5b49f8c7b655973889db2c8af9a85705645321e0900000000071a2d3d4a4e4a3e4a4f4e4a4e4a4c504b4a4f4d4a4f4a4e4a4e4d4e4d4c46494e4f4a4b504c4b4f4e493d2c1c0c0000000000000000000000000000000000000000000000132536556a7f94aac9dad2bda7927d68523d28130000000000000000000e23384d63788da9bacdb6a18c77614c372222374c62778ca1b7ccc6b09b86715b46313d53687d92a8bdc6b19b86715c3a2a1704000e24394e63798ea3b8cedcc7b19c8677879da9b5a39b85756155443625160b00000000000000000000000d22374c62778c9f8b889db2c8bca7917c67523c2720354b60758a9fb5cabea8937e69533e291400071d32475c72879c868a9ea18c76614c3721162c41566b8196abc0d6cdb8a28d78634d38230e0000152a3f556a7f94aabfd4c6b19c86818487898a8b8d8d8c89857e75604b36210b000000000000000000030a0c13191b1c19150d1122364a5c6e8399aabbcee1cdbaa897816c5b493c495a627583919da5abafb1b1aea79e8d7c6658473318080000081d314455748a8f7b8398aeb6a18b766d707374757573716e665e4f4f4b45382a1c0c000000162b40566b80958f7a8196acc1d6c5b19f96817260554639291c0c00000000000000000000000000000000000000000000000000000000000000000000000003182e43586d839885859bb0a48f7a879db2ab9d877762778ca6b7bbaa937e695338281603000000000d21364a5c645c4d5c64645c645c61656160656260645c645c6363646361585b63645c6065615c64635b493a2917040000000000000000000000000000000000000000000010263b50657b90abbccfd3bda8937e68533e291300000000000000000010263b50657b90a5c7d7b6a08b76614b362121364b61768ba0b6cbc5b09b86705b46313d52687d92a7bdc9b49e89745847331f0a000e23384e63788da3b8cdddc8b29d88869ba5b6b19b867661574e4a3e32281b10020000000000000000000d22384d62778d97827b8fa5babaa58f7a65503a251c304354748a9fb4c9bfa9947f6a543f2a1500071c31465c71868f7a8298a18b76614c3621162c41566b8196abc0d6cdb8a28d78634d38230e00081b2e3e556b8095aac0d5c9b5a49c96999c9e9faba2a3a99f9a93826d58422d1800000000000000000b171e21292e30312f2a23201b2e3e4e63798c9fb4c7d7d7c6b49f8b78634d3e3c4857616e7c8790969a9c9c9993897c665e4c3a2a17000000011426495e74899d888c9fb4b6a18c77615b5e5f605f5e5c58546065656056473a2a17040000152b40556a80958e798298adc2d7cebdb09f9682736157473a2a1c0c000000000000000000000000000000000000000000000000000000000000000000000001162b41566b80969b9ba2b4ab8d787c91a1b3a59b85777d92a7c4b49f8b77624d37220d00000000000f24394e6479645f677979647964767a76757a78747964796579787978766165797968757a77697a79635847331f0a000000000000000000000000000000000000000000000c21364c61768b9fb5cad4bea9947f69543f2a1400000000000000000013283d53687d92a8bdcab5a08b75604b362020364b60758ba0b5cac5b09a85705b45303d52677d92a7bccdb9a88c76614c37210c000d23384d62788da2b7cddfcbb7a69d9ba3b4c3ac97817b756d645c4b46392e20100300000000000000000e23384e63788d95807b90a6bbc7a38d78634e38231426495f74899eb4c9bfaa947f6a553f2a1500061b30465b70858d788399a18b76614c3621162b41566b8096abc0d5ccb7a28c77624d37220d000d22374b5c70859ab0c5cdd2c2b5b1acafb1b3b5bcc3b7b2ada39a846f5a452f1a00000000000005131b2933363e434646443f38352c2135495b6d8297a9bacde1cebbaa98836e5c4a3639464b5f67737b81858686837e76665e4c402f1c0c000000001e33485d73889d9d9faabbb7a28d77624d484a4a4a49465761737a7a74615847331f0d0000152a3f556a7f948d788399aec3cbc8c1bdb0a09883756158473a2a1d0d000000000000000000000000000000000000000000000000000000000000000000000014293e53697e93a8b0b4b59f8a756e8399a5b5a39b88899eb3b9a897826c594834200b0000000003182d42586d826d677d807f78826d7f7d82807c8278836e827b817e837f7a657a817f7d7d7d847e7b8076614c37210c000000000000000000000000000000000000000000000a1f33465871869cb1c6d5bfaa95806a55402b15010000000000000000152a40556a7f95aabfcbb6a08b76614b362121364b61768ba0b6cbc5af9a85705a45303d53687d92a8bdd6c6a38e79634e39240e000d22374c62778ca1b7cce7d4c4b7b2b0b4c1c5b19f97908a83796c61574b3e2e211002000000000000000e24394e63798e947e7d92a7bdbaa98b76614c36211e33495e73889eb3c8bfa9947f6a543f2a1500051a30455a6f858c77849aa08b76614b3621162b41566b8096abc0d5cbb6a18c76614c37210c000f253a4f647a8fa2b4b4bac7cdc5b8b3b0aeacaaa7a4a59d98908579634e39240e00000000000715233039464c53585b5b59544d493c342c3d4d62778a9fb4c5d6d8c8b59f8d7a644f3f2f32414d5460666c7071716e6961574c402f221200000000071c32475c71879cb1b4bbc8b8a38e79634e3935353043546175858f8f8676614c3b2a180500142a3f54697f948d788499aec4b7b2acb1bdb2a19a85766158473b2a1d0d000000000000000000000000000000000000000000000000000000000000000000000f253a4f647a8fa7b8c8b29d88736177879da6b4a69d9ea7b8a99e8a77624c3b2b18050000000004192f44596e847f7c8082827e826d7f8178826d7d7c846f827f7975837f7a697e7a72827c817a8281837c67523d2712000000000000000000000000000000000000000000000417293a566b8196abc5d6c1ac97816c573a2a1d150900000000000002172d42576c8297acc1ccb6a18c77614c372221374c61768ca1b6cbc5b09b85705b46303e54697e93a9becfbaa58f7a65503a2510000c21374c61768ca1b6cbe1e2d4cbc8c5c8d1cebdb1aca99f988c8175645c4b3f2e2010000000000000000f243a4f64798f927d7e94a9beb49f89745746331e1e33485d73889db2c8bfa9947f6a543f2a1500041a2f44596f848b76869ba08b76614b3621162b41566b8096abc0d5cfbcab8b76604b36210b000f243a4f647a8fa29e9fa9babdb0a69e9b999794928f8c88827b72635b4a36210c0000000005152533414d5761686e70716e6a625a4c473b3448596b8096a7b9cce0cfbcab9a846f5d4b37233036434b50565a5c5c59544b46392f22120400000000061b31465b70869bb0c5ced9b9a48f7a644f3a2520354a6072849aa3a499836e5948341f0b0014293e54697e938d778499aeb7a69d969fb1bdb3a39b86766159473b2a1c0c0000000000000000000000000000000000000000000000000000000000000000000b20364b6075899eb3bead98836e596379889aa2adb1b2b0a79e8b7b655948341d0d000000000000182d42586d826d8278828278837f80817e7b81817586828078817f817f7a697e796d827c81807a818277624c37220d000000000000000000000000000000000000000000000011263b50667b90a7b8ccc4af9a846f59473731271912050000000004192e44596e8399aec3ccb7a28c77624d372222374c62778ca1b7ccc6b19b86715c46313f546a7f94a9bfd1bca6917c67513c2712000c21364b61768ba0b6d9ebf2e7dfddd7cdc9bdb7b9c7bab4ab9f97877a655d4b3e2d1b0b00000000000010253a4f657a8f907b8095aac0b29d88725d3929171d33485d72889db2c7bea9947f69543f2a140004192e43596e838a75879cab8b76604b3621162b40566b8095abc0d5cab49f8a755645321e09000d22374b5c70859a898a9fb4b09f96888684817f7c7976726d6660544a3d2d1a070000000012233343505f67767e838586847f786d61594c403b4c6176899eb3c4d4dac9b3a2907b65504030192630353b41454747443e3633291b11040000000000051a2f445a6f8499afc4d9d0bba5907b66503b26263b50657b90a2b3b3a18c77624c37220d0013293e53687e938c77849aafb29d8881969fb1beb4a49c86776259473a2a190900000000000000000000000000000001080b0e0f0d0c06000000000000000000091d3245566b8096a3aaa0907b66505b63788490989c9d9b95897c655d4c3b2b180000000000000a162b40566b80807c676d6d626e6a6b6c69666c6c61716c6b626c6a6d7f7a667c78697e696c6a646c6c625947341f0b00000000000000000000000000000000000000000000000b20364b6075899eb3c8c9b49f8b7761554b443730231203000000051b30455a70859aafc5cdb7a28d78624d382322384d62778da2b7ccc7b19c87725c473240556a8095aabfd3bda8937e68533e2913000b20354b60758aaabbcedee1e9e9d7c6bab4a8a2a4acb4babcb4a59c8a7b655c4a39281603000000000010263b50657b908f7a8196acc1b09b86705b46311b1e33485e73889db3c8bea9947e69543f29140003182d43586d828a74879c9f8a75604a3520162b40556b8095aac0d5c9b49e89745f3828160200071b2e3e566b81927e7f95aaab968173706e6c6a6764615858504a43362d1f0f000000000a1b304150616a7d8993989b9b99948c8277665e4f4347586a7f94a6b7cbdfd0c0b09b85705f4d3727151c20262c3031312e29211e170b0000000000000003192e43586e8398adc3d8d1bca7927c67523d272b40556a8095aac0bfa38e79634e39240e0013283d53687d928c77849aafaf9a846f8197a0b2beb5a49c8677625847372715010000000000000000000000000508141c2023252320190e0700000000000000021528384c617685929591826e5e4c4a5a62707b838788857f76655e4c3f2f1d0d00000000000a1a28323650626b6b675f58584d59545657535157574b5c57564d57546169645e666361696156554f56574c473b2a18050000000000000000000000000000000000000000000000091d3145566d8297acc0cebbaa9882736660554d41302111000000061b31465b70869bb0c5cdb8a38e78634e392323384d63788da2b8cdc7b29d88725d483341566b8096abc0d4bfaa947f6a553f2a1500081d314455758a9fb4b8c9cdd7e1cdbaa89f938d8f969fa9b6c3b6a89e8a7a645746321e0f000000000011263b51667b908e798297adc2ae99846f59442f1a1e34495e73899eb3c8bea9947e69543f29140002172d42576c828974879d9e89745443301c152a3f556a7f94aabfd4c8b39e88735e49331e000000152a3f546a7f917c7f95aaa8937d685b595755524f4c5962645d5043331909000000031628394d5f6a7f929ea8adb0b0aeab9f98887c696150434b6075889db2c2d3ddc9b5a3917c675544311d0a0b11171b1c1c19140c0a03000000000000000002172c42576c8197acc1d6d3bea9937e69543e292636586d8398adc2baa88d77624d38220d0012283d52677d928d778499afaf9a846f728298a0b2beb5a49c8676615544311d0900000000000000000000000d181f263035383a38352c221b10020000000000000a1f33465861757d807c72604a403c484d5e666d7273706a61584c402f2111000000000002162838454b575a5e5b554e493d38433f40413e3b4142364642403842434f544f4c514d4f544f42403a414237342a1d0d0000000000000000000000000000000000000000000000000215273850657a8fa2b4c7c8b2a098857c74675f4d402f1c090000071c31475c71869cb1c6ceb9a38e79644e392423394e63788ea3b8cdc8b39e89735e493442576c8197acc1d5bfaa95806a55402b15000115274a5f74899fb4a3b4bac6d5c4b49f8a7e787a818b9ca5b5c2b9a89c8675614b3d2d1a070000000012273c51677c918d788398aec2ac97826d57422d181f34495f74899eb4c9bda8937d68533e28130002172c41576c818974889d9e88735e49251314293f54697e94a9bed3c7b29d87725d48321d08000013283e53687d917c8095aaa7927d685244423f3d485962777a6a6150372715010000091e324557677d919db4b9c6c5c6c9bcb4a69e917f6a61504556687e93a4b6caded2c1b19c8674604b3828160300010507070400000000000000000000000000152b40556a8095aabfd5d5c0ab95806b56402b30435471869bb0c6b49f8975604b35200b0012273c52677c918d788499aeaf9a856f60738298a0b2beb6a49a8473604b37261401000000000000000002101d2a3436434b4d4f4d493c362d20100100000000000417293a465660686a67605443302b35404c50585c5d5b554c473a2f2111030000000000091e324556606c6f73706a635b534c473b4038454b453839373435313538353f39363c383b3e3b322b252c2d221f180d00000000000000000000000000000000000000000000000000000a23374b5d70859ba9bac8beb2a39b91887d675e4c38230e0000071d32475c72879cb1c7cfb9a48f7a644f3a2524394f64798ea4b9cec9b49f89745f382843586d8298adc2d5c0ab95806b56402b1600001f34495e74899e9e8e9fa8bacbb8a6927d6862646c79879ca4b5c3b6a497816c5c4a3621100000000012273d52677c928d778499afc0ab96816b56412c161d314556748a9fb4c9bca6917c67513c27120001162c41566b818974889d9d87725d48321d13293e53687e93a8bdd3c6b19c87715c47321c07000012273c52677c917c7f94aaa7927d68523d2c2a374d62778a8f7f6a5544311d0800000b21364b6075879db2bcccd6dadbd9cfc5b8b39d947f6a5f4d4b6074869cb1c1d2decab6a4937d685645321e0c0000000000000000000000000000000000000013283d52687d92a7c8d8d7c2ad98826d58432d354b6074899fb4c6b09b86715443301c080011263c51667b918e788398aeb09a85705560738298a0b1bdb4a2947f695544311d08000000000000000010202e3b474c54606364625a4f4a3e2d1f0f0000000000000b1b2938454b5355514a43362519202f383b434748464037332a1c11030000000000000b21364b60768285888580797169615956564c5660564d4f4d484b44494e4a484d4c46393e35404337342a1d0d0b05000000000000000000000000000000000000000000000000000000081c2e3f4e63798b9faab8c5c1b5b0a69d8d7b65503b26100000081d33485d72889db2c7d4baa58f7a65503a25253a4f657a8fa4bacfcab59f8a7556453244596e8399aec3d6c1ab96816c56412c1700091e33495e73889e8a788a9fb4c8b39e8874604d4f5b6377869ca4b6c3b49f8c79644e3e2d1b0700000013283d53687d928c77849aafbfaa95806a55402b1520364b60758ba9bacebaa58f7a65503a25100001162b40566b808974879d9c86715c47311c13283d52687d92a7bdd2c5b09b86705b46311b06000011263b50667b907d7e93a9a7927d67523d28253b50657a909e8874604b35200b000316283853687d93a6b7cbe1d8cec9bbbdc8cbbbae9d917d675b4a55677c91a3b5c9ddd3c2b29d8875604b3a29170400000000000000000000000000000000000010253a50657a8faabbcedac5b09a85705b3b2a394e64798ea8bac2ad97826d58362614010011263b50667b908e798298adb09b86705b55607382979fb4bab39e8874604b35200b000000000000000d1d2e3e4b59626c74787a7871645c4a3d2d1a070000000000000b1a2832363d403c3530251808111c23262e3233302a211f170c0000000000000000091e324556606c6f777f898e867e77706c6b616376675f64625960555b63605962615758544b56584c473b2a190900000000000000000000000000000000000000000000000000000000001121364a5b667c8c9ea6b8cbc9c4b7ab9a85705a45301b0500091e33495e73889eb2b7c3bba5907b66503b26263b50657b90a5bad0cfbcab8b76604b36455a6f849aafc4d6c1ac97816c57422c1700081d33485d72889d8774899eb4c2ad98826d55443d49596276869ca8b9bcab99846f5c4a36220b00000013293e53687e938c77859aafbea9947f69543f2a1422384d62778da2c7d8b8a38e79634e39240e0000152b40556a808a75879c9b86705b46311b12273c52677c91a7bcd1c4af9a846f5a452f1a0500000f24394f64798e7e7d92a7a7927d67523d2824394f64798ea68f7a65503a251000091e32455670859ab0c4d4d8c8bbb4a6a7b3b7c4bbb49f8a7963544a6072859bb0c0d0dfcbb7a6947f695846331f0d0000000000000000000000000000000000000c21364b61768a9fb4caddc8b39d88735948343b54697e93a9c6c5a9947e69543f2914000010253a50657a8f8f798297acb09b86715b4455607281939fa9b2a68e79634e39240e00000000000005182a3b4b5c647781888d8f8d867a645b4a36210b000000000000000a161e21282b27201c13080000090f11181d1e1b150c0a0400000000000000000002162838454b5759616976808a938a8581807679887d697977667567677872647776616e69606b6e61594737271c1308000000000000000000000000000000000000000000000000000000071a2d3d4c5e667b889eb3c8ddd4c9b39e89745e49341f0900091f34495e74899e9da5b7c5a6917b66513c26263c51667b91a6bbd0dab6a18b76614c36465b70859bb0c5d7c2ac97826d57422d1800081d32475d72879c86758aa8b9bfaa947f6a55372c3b485863798a9eb4bfb3a18e7a644f39291703000014293f54697e948c76859ab0bda8937e68533e2913253a4f647a8fa4b9d6c5a28c77624d37220d0000152a3f556a7f8a75869c9a85705b45301b11263b51667b90a6bbd0c3ad98836e58432e190300000d22374c62778c807b91a6a8937e68533e2923384d63788da2947e69543f2914000b21364b60768a9fb4c9dfcebbaa9f90929da6b4c0baa89b8572604a54657b90a2b3c9dad4c4b39e8976614c3b2b180500000000000000000000000000000000000a1e33465770859bb0c9d9cbb7a68c77624c3747596f859aafc4b8a68e79644f39240f00000f253a4f647a8f8f7a8197acb19c86715c374454606d7e8b989d9b8976614c36210c0000000000000b1f344859647a88969ea7a4a39b8a79634e392917030000000000000003090b1315120b07000000000000000307080600000000000000000000000000000a1a2832363b474c58616b777e8a948a7f70859a887e8a857b897d7d8a8079898477837e75808377615544353025180a0000000000000000000000000000000000000000000000000000000f1f30404c5d6b8095abc0ced8c8b39d88735e48331e0900071c304354748a908790a7b9a7917c67523c27273c52677c91a7bcd1ccb6a18c77614c37465c71869bb1c6d7c2ad97826d58422d1800071c32475c71879a85768ba1c6bea9947f69543f2a2b3a4a5b677d92a1b2bfad97826d5746331e0a0000152a3f546a7f948b76859bb0bca7927d67523d2812273c51667c91a6bbccb9a78b76604b36210b0000152a3f546a7f8b76869b9a85705a45301b10253b50657a90a5bacfc1ac97826c57422d170200000b20354b60758a82798ea4a9947f6a543f2a21374c61768ca197826c57422d17000f253a4f647a8faabbcedfc9b49f8b7c7d889aa2b3bfb4a2927d68554b5d6f849aabbccfe0ccb8a795806b594834200e000000000000000000000000000000000003172939556a7f95abbccfd5c4a6917c67513b4c61778b9fb4c8b39e8874604a35200b00000f24394e64798e907a8196abb19c87715c4736434b6068798288867b655846331f0a0000000000000d22374c6277899ea6b3b8c1b5a89a846f5746331e0a00000000000000000000000000000000000000000000000000000000000000000000000000000000000a161e212a343a4a5b657b86867f776a6c819684949c86898a89888885869c89888985858281857360534a4336281a0a0000000000000000000000000000000000000000000000000000081d31445563798a9eadb4bbc8c0ae98836e59432e1904000b20354a60748a8874899eb3a7927d67523d28283d52687d92a7bdd2ccb7a18c77624c37475c71869cb1c6d8c2ad98836d58432e1800071c31465c71869984778da2b7bea9947f69543f2a1c2d3d4d5f6e8399a9bab49f8a76614c36210c0000152b40556a80958b76869bb0bba6917c66513c2713293e53687e93a8bdc9b39e89745745321e090000152a40556a7f8b76859b9b86715b36261410253a4f657a8fa4bacfc0ab96806b56412b16010000081c304354738884778ca7aa95806b55402b20354b60758aa89a85705a45301b0012273c52677c91a7c8d8dbc5b09b867068778499a1b3c0b29d8774604b4f647a8d9fb5c8d8d6c5b49f8a77624d3c2c190600000000000000000000000000000000000d22384d62788b9fb4c9dac3ae98836e5948576a7f94aabbc2ad98826d5443301c0700000e23384e63788d907b8096abb29c87725d472630424e5b636d7271655d4b3a291704000000000001162c41566b8096a7b8c5ccd2c6b49f8a76614b36210c00000000000000000000000000000000000000000000000000000000000000000000000000000000000002090c1823394e63798a7b70827e69647a8e878298838697828b917c889882889580888975817e72686054453828160300000000000000000000000000000000000000000000000005182b3b4b6074859ba0989faabbb4a2907b65503b251000000b21364b60768b87748a9fb4a8937d68533e28283e53687d93a8bdd2ccb7a28c77624d37475c71879cb1c6d8c3ad98836e58432e1900061b31465b70869983788da2b8bea9947f69543f2a141f30414d62788a9fb4baa9917c67513c27120000162b40566b80958b75869bb0bba5907b66503b26162b41566b8096abc0c6b19c86715c392816030000162b40556b808c77859a9d87725443301c0f243a4f64798fa4b9cebfa9947f6a543f2a15000000011426365a70858774899eac97816c57422c1d31445574899e9c86715c47311c0013293e53687e93a8bdd3dbc6b09b86715962748399a4b5b7a5917c67524a5c6e8398aabbcee1cdbaa997826c5b4935210d00000000000000000000000000000000000b2035485a6f8499abbccfc9b49f8b7762546175889db2c8b5a4907b65503625130000000d23384d62788d937e8095abb29d88725d48331c313d494e585d5b4f4b3f2e1c0c000000000000071c31465c71869bb1c5d5e0e2cebbaa8d78634d38230e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014293f54697e897571868978656e83947f878c7e8a897f94837b8c8a7c8b897d8b818593877e72605645321e100000000000000000000000000000000000000000000000000b203448596a7f94a198828b9fb4aa9a85705d4b37230e00000c21374c61768c86758aa9baa8937e69533e29283d53687d92a8bdd2ccb7a28c77624d37475d72879cb2c7d8c3ae99836e59442e1900051b30455a70859883788da3b8bfaa947f6a553f2a15132034485a6b8096a9baad98826d583b2b190500162c41566b81968a75869bb1baa5907a65503b251629395a6f8499afc4c3ae99846e59442f19000001162b40566b808c77849a9f8a75604b35200f24394e64798ea3b9cebda8937e68533e291300000000172d42576c828a75859aae99846f5936261426375d73889d9c87725d47321d0011263b51667b90a6c5d6ddc7b29d887254566175869caabbaf9a846f58464d63788b9fb4c6d7d7c7b49f8c78634d3b2b18050000000000000000000000000000000005192b3c4f647a8d9fb5c4cebbaa96816b68738298a6b7beb19c8673604a35200b0000000c22374c61778c9d88899eb3b39d88735e48331e1f2c36394348463a372e211000000000000000081d33485d72889db2c7ddecdfcbb7a58c77614c37220c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011273c51667c917d677d92877b6f788a897d92877e9383828a7a7f94837d928480937e7f86918374604b3e2e1b070000000000000000000000000000000000000000000005182a3b4d62778a9e998375899eb49f8c7a644f3f2f1c0800000d22374c62778c85768ba0c7a9947f69543f2a273c52677c91a7bcd1cfbcab8b76614c36485d72879db2c7d9c3ae99846e59442f1900051a2f455a6f849883788ea3b8c0ab96806b5636251305192b3c4c61778a9fb4b29d8873594834200b00172c42576c81978a75869cb1b9a48f7a644f3a251e32465772879db2c7c1ab96816c56412c17010001162b41566b808d788499a98d78624d38230e24394e63798ea3b8cebca7927c67523d27120000000014293f54697e8d788197ac9c87725443301c32475c72879c9d88735d48331e000e23384e63788da7b9b9c9c9b49f8a74604a5764798c9fb4b49f8a76614c495b6c8197a8bacde1cebbaa97826d594834200a00000000000000000000000000000000000e22374b5c6d8298a6b7c7c8b59f8d807d8498a0b2c2b2a0917c665443301c070000000c21364c61768b937d7f94a9b39e88735e49331e0f1a21232e333125221b100200000000000000061b30465b70859bb0c2d0d7cfc1b29d87725947341f0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081c2e3f4b60758889786c819790847b809580818877817f7686898486907b80867686877e797c89826d5c4a36220d000000000000000000000000000000000000000000000b1f3448596d82979f8b788095a8a395806b5c4a3621110000000d23384d62788d85778ca1b6aa947f6a553f2a263b50667b90a5c9dacab49f8a75604a35485d72879db2c7d9c4af99846f5a442f1a00041a2f44596f849883798ea3b8c3ae99846e5443301c070d1f3447596e8399aeb7a68c77624d37220d00182d42576d82978b75879cb2b9a48e79644f392421364b61768b9fb5cabda8937e68533e2913000001172c41566c818f7b8399a7917c67523c2712243a4f64798fa4b9cebba5907b66503b26110000000011263b50667b907c7e93a89f8a75604b352031465b71869b9d87725d48321d000b20354b6075899eb3a4b3b9baa98d78634e4a5c6d8297acbbaa917c66513c4c62778a9fb4c5d6d9c8b49f8b77624c3828150200000000000000000000000000000000081b2e3e4c6277889da9bac7bcab9f96929aa2b2beb5a498836e5e4c362513000000000b20354b60758a9a84849ab0b39d88735e48331e00060c0e181d1c100e0800000000000000000000142a3f54697f94a4b4c0c2bfb2a3947f6a553b2a180400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e23374b5d65777e93867675858b879089988b7e7e7b7a6a61767e787586877679887b848275677b8b79644f3a240f000000000000000000000000000000000000000000000d22374c62778b9f9681778a9ea99b8574604b3e2e1b030000000e23384d63788d84778ca2b7aa947f6a553f2a24394e64798eabbccfc8b39e8973544330475d72879cb2c7d9c4af9a846f5a452f1a0004192e44596e839883798ea3b8c8b39d8874604a35200d04182a3a53687d93a8c4a6917c66513c271100182e43586d83989d879ca5b6b8a38e79634e3924243a4f64798fabbccfc4a5907b65503b2610000002172c42576c819788899fac96816c573d2c1a253a4f657a8fa4bad4c3a38e78634e39230e000000000c22374c61778c817a8fa9a98d78624d382231465b71869b9c86715c47311c00081d3144556e83999f8e9ea8b9a8927d68533d4e63798ea2b4aa957f6a554048596b8095a7b8cce0cebaa995806b5645321d090000000000000000000000000000000000101f344759647a8b9fa9b7c4bcb5aba7b0b4beb2a49c8675614c402f180800000000081d31445573889e9a9aa2b4b19c86715c47321c07000000030806000000000000000000000000000b21364b6075869aa2abacaaa1998574604b36200c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010253a50657b88738195877b7a8b747b7f828b9486868578706b686263798a81778986726d615d6d827c67523c2712000000000000000000000000000000000000000000071b2d3e556b80959f8a778197a89f8b79635544312010000000000e23384d63788d84778ca2b7a9947f6a543f2a21364b61768b9fb5cac7b29d87725d4825475c72879cb1c7dac5af9a85705a45301b0003182e43586d839883788da3b8cbb7a68f7a644f3b2b18050f253a4f647a8fa4b9aa957f6a55402a1500192e43596e83988975899eb3b9a38e79644e3924293e53687e93a8c9cbb7a68c77624c37220d000002182d42576d828f7b8297ad9d87725b493521263b50657b90a5bacab7a58b76614b36210c000000000b1f34475972878675899fa7917c67523c2731465c71869b9a85705b45301b000114263753687e938b79899eb3ad98826d57464a5b70859aafad98836e58433b4c6176899eb3c3d3d8c7b39e8875604b36200c000000000000000000000000000000000005182a3b4a5c667c8b9da6b4b9c6bfc9bcb4afa0988677625746332212000000000001152737586d8297abb0b4baaa96816c57412c170200000000000000000000000000000000000000091e3245566277848f9597958f8375615645311d0900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1d2a43586e83927d73808b908c806b666a6d7d92807983868581786860687e826d7b816c544b4f647974604b3621120400000000000000000000000000000000000000000d22364a5c72879d9681778b9fa796806b5b4a37271502000000000e23384d63788d84778da2b7a9947f6a543f2a1e32465772879cb1c6c2af99846f5a4431475c71869cb1c6dac5b09b85705b46301b0003182d42586d829784788da2b7d5c4ac97826d59483420120d22384d62778da2b7ad98836d58432e18001a2f44596f84998c7e8b9fb4b9a48f79644f3a242a3b586d8298adc2c8b29d8873594834200b000003182d43586d829882879cb2a58d78634e3823283d52677d92a7bcc7b29d88725746321e0a0000000004182a3b586e838a76849aab96816c5639292b3b5d72889d98836e58432e1900000c21364c61768a8d788297adb49e8975614b3d546a7f94a9b09a85705b45334658697f94a5b6cadfccb8a7917c66513a29170400000000000000000000000000000000000d1d2e3e4c5e667a87969ea8a9aaa9ab9f998f8275625948392917040000000000000f24394f647a8c9faaada99f8b79644e39240f0000000000000000000000000000000000000000031628384759626f7a8082807a6e615746382715020000000000000000000000000000000000000000000000000000000000000000000000000000000000000004182a3b4752677d9288766b797f7d737b72605f697e7b807c7d838b8b7e6874827560656c6251464b5c646056483b2f221202000000000000000000000000000000000000000f24394e64798e9f8b778196a99e8976614c3d2d190900000000000e23384d63788d84778da2b7a9947f69543f2a162939566b8095a8b9b5a3937e68533e31465c71869bb1c6dbc5b09b86705b46311b0002172d42576c829784778ca2b7ccc9b49f8b77624d402f1d0d22374d62778ca2b7af9a85705a45301b001a2f455a6f849a9f939faabbbaa5907a65503b2534475972879db2c7c9ae99836e593b2b1805000003192e43586e8398989ca5b6a9947e69543c2b2a3f546a7f94a9bfc3ae99846e5939291603000000000014293e54697e927c7e93a99b867157463334485974899e96806b56412b1600000a1f3346586d8295807a8fa1b3a8947f6a5a494f657a8fa4b19c87725c47293a4b6074879db2beced5c5ae99836e5846331f0a000000000000000000000000000000000000102030404c5c6476818990939594918b847a6d6157483b2b1b0b000000000000000d22364a5c687e8b9598958b7d675c4a36210d0000000000000000000000000000000000000000000a1a2a3b474c5d656b6d6b645c4b4639291a0a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1f344759616a708496816c636a697f8a806b61757a676a78746e7884927d7e927d676161584c5761686b6962594c402f201000000000000000000000000000000000000001142637556a7f949883768a9fab95806b5847331f0f0000000000000e23384d63788d84778ca2b7a9947f69543f2a1422374c62778a9ea9a39b8573604b3531465b71869bb0c6dbc6b19b86715c46311c0002172c41576c819685778ca1b6cccdbaa998826d5e4c3b2b1b22374c62778ca1b7b09b85705b46301b001b30455a70859aafa9b4bbc8bca7927c67523d27374c61778ca5b6cabcab937e69543e291400000004192e44596e8399adb2b3afb09b85705a49352637576c8196acc1c6aa957f6a55402a150000000000000e23394e63798e84768a9f9f8b76614c36374d62778ca8937e68533e291300000417293a4d63788b89768399a6b49e8a7863574c61768ba1b19c87725c4732324556657b90a0b1c4d5c9b49f8a76614c36210c000000000000000000000000000000000000021222303e4a58616c767b7e7f7e7c776f655d4b46392b1d0d0000000000000000071b2d3e4e60687880827f78675f4d3d2d1a07000000000000000000000000000000000000000000000d1d2a343f4b505657554f4b3e33291b0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c22374c6177807678898c7c665b738888847f6d82897c7b8a806a7a80848b7d8d89777677665e61757d807e77665e4c3e2d1b070000000000000000000000000000000000081d3144556f849a907b7e93a99f8b78624d3a2917010000000000000e23384d63788d85778ca1b6a9947e69543f29141f344859677d8a908e85786255443130465b70859bb0c5dac6b19c87715c47321c0001162b41566b809685768ba1b6d4cac7b2a0907c665948392923384d63788da2b8af9a85705a45301b001b31465b70869bb0bec9ced8bea9947f695437273751667c91a6c3cab59f8c77624d37220d000000041a2f44596f8499aeb3a1999fa38d78624d3731445570859ab0c5baa88f7a65503a25100000000000000c21364a5b72878c77859aaa927c67523c3b51667b91a88e79644f39240f0000000c2035495a6c81968177889da6a89b8575615863788da2b19c86715c473128384c5e6d8297a6b8c8cebaa9917c66513c2711000000000000000000000000000000000000000412202d3a474c576165696a696661594f4b3f33291b0d00000000000000000000102031424e5a636a6d6a625a4d41301f0f0000000000000000000000000000000000000000000000000d181f2e373a4042403a372e1e170b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d22384d62778d88807f8a8979666c81947f847f8d84868689857e8688838985829885898a7c667285808088897c665c4a36220b00000000000000000000000000000000000b20354b6075899d8774879cb09b85705a49351c0c000000000000000e23384d63788d85768ba1b6a9937e69543e2914182a3b4d5f67777b7972625a48372730455b70859ab0c5dac7b29c87725d47321d0000162b40556b809586758ba0c6c3b7b2b2b39e8878625746372a3b50657a90a5baac97826d57422d18001c31465c71869bb1c6dbe2d8c3ad98836e55443144556c8196abc1c3b09b8570594834200b000000051a2f455a6f849aafaf99848d9f947f6a5544354b6075899eb4c9b49f8975604b36200b000000000000071a2d3d54697e948a89979f9a846f5a4948596d82989e8974604b35200b00000006192c3c4b6175868d7d7a889da5a39a847665667c91a6ae99836e59442e1a2f404c6176889daabbcec7ab95806b56402b16010000000000000000000000000000000000000002101c2a3339464b50545554514c473b372e1e170b0000000000000000000000021324313c494d5558554d493c302313010000000000000000000000000000000000000000000000000005111c23252b2d2b24221b100300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b2034485a6a7f868a8e9196887c7979898978858a8b7d879a84848a88808a9580889883858a787a8f7c7d77838a7a644f39291703000000000000000000000000000000000f24394f64798e96807a8fa4aa947f6a553c2b1900000000000000000e23384d63788d86768ba0b5a8927d68533d28130d1d30414d596166646054483c2b1930455a70859aafc5dac7b29d88725d48331d0000152a40556a7f9586758aa8b9b7a59d9da5a69c86756155473a3d53687d92a8c1a8937e69533e2914001d32475c72879cb1c7dcf1ddc8b39e8874604b3a4b6074889db2c8b7a5937d68533b2b1905000000051b30455a70859aafa88e7a859b9c8774604b3c4e63798ea8b9c4ae99836e5645311d09000000000000000f21364b6175888d7982979f8c78634d4c6277899e99846f5443301c08000000000e1e32465763798a8b7d788799a1a29a867a7b879cb2aa947f6a553f2a151f334758657b8c9fb4bcc5ad98826d58432d18030000000000000000000000000000000000000000000c171f2832363b3e403f3c37342a231c11030000000000000000000000000006131e2c353840434038352b1e130500000000000000000000000000000000000000000000000000000000080e101618160f0d070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005192b3c50616a7175797c808d9086868999877e849a87798795808497827e93897f94897e86837e939092827484846f5746331e0a0000000000000000000000000000000014293e54697e938f7a8196aba78e79644f39240f00000000000000000e23384d63788d86758aaabba7927c67523d2712001323303b474c504f4a43362b1e1a30455a6f859aafc4dac8b29d88735d48331e0000152a3f546a7f948774899eb4b29d87879daaa49983736158504f5b6d8297adb5a38d78624d38230d001d32485d72879db2c7dcf2e0cbb8a6917c67584755677d92a6b7c1b29d8774604b36200d00000000061b30465b70859bb09e89737e93a4927d685b4954697e93a9c6b8a6917c66513827150200000000000000091e324657687d92838196ab98826d5f606d8298a8937d68533626140100000000031628394a5b657c8b8d7e7683959ea49c8f909ca5b5a38f7a644f3a240f172a3a4b5d687e939fabb3a7957f6a55402a150000000000000000000000000000000000000000000000040b161e2126292a2927221f180c0800000000000000000000000000000000000e1920232b2d2a2320190e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1d33435055566063666b7e8c86777383917c7684978278878c7d84937e7f9486818a847f947f94868385707a8c76614b36210c00000000000000000000000000000002162838586e83988873889db29e8974604b35200b00000000000000000e23384d63788d87758a9fb4a6917b66513c26110005131d2a34373b39353025180e1a2f44596f8499aec4d9c7b29d88725d48331d000014293e54697e93988398a8b9ae9883798b9fb4a19983766c656469798a9fb4b09b85705a4935200b001e33485d73889db2c8ddf0e5d5c5b29d877661586073869cb1c4b4a3937e685544311d0800000000061c31465b71869bb09a857076889e9e8a79635b5d70859ab0c4b39e8874604b35200b0000000000000000031628394b60738699969fb0a0927d70758298a09f8a76614c37210c0000000000000b1b2d3d4c5e667c8a93817480959da6a4a5b2b6ab9b86715c4a36220d0c1c2f3f4e60697e8c9a9e9a8977624c37220d0000000000000000000000000000000000000000000000000003090c10141514110c0b040000000000000000000000000000000000000000060c0e1518150d0b0600000000000000000000000000000000000000000000000000000000000000000000000000000000000002080b0d0e0e0d0c0b080100060504030201000000000000000000000000000000000000000000000000000000000000001525333c38454b4e5160687b89887a77878a7a7584937e78878a7b858d798195808489838a8183908c7e69748978634d38230e000000000000000000000000000000091e32455672879c867e93a6ae99846e5443301c0800000000000000000e23384d63788d8774899fb4a5907b65503b26100000000c181f222624201c130800192e43586e8398adc3d8c7b29c87725d47321d000013293e53687e938a7a8a9fb4ae98836e7f94a1b2a19989817a797e899ea9b5a4917c67513c2b1906001d33485d72889db2c7dde0d2c9c6b7a59b8576696b7f94a4b5b8a79b8573604b3727150200000000071c31475c71869cab96816c6a7f94a59d87796b6a7b90a2b4b7a6947f695544311d080000000000000000000b1c304354647a8b9faab7b59f8d858898a0a796816c5847331f0a000000000000000f1f2f404c5e667a8797868288889da5b7b6b29f8d7b65503e2e1b0700112131424f60697b8589857a645947341f0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090b13151d202223232221201d141d1c1a1918171614110d0b0500000000000000000000000000000000000000000000000000000715202828323639414e5d6578848b7f7989887875848c7c78878878817373857d77877786826e7b7c6960718674604b36200b0000000000000000000000000000000b21364b60758a9680869bb0a9947e69543626140100000000000000000e23384d63788d8873899eb3a48f7a644f3a250f00000000040b0c110f0b07000002182d42576d8297acc2d7c6b19c87715c47321c000013283d53687d928a77899eb4ae98836e6e8399a2b3a79e96908f939ea7b9aa9c8672604a35200e00001c31475c71869cb1c6dbd2c2b5b1a6b4a39b877e818d9fb5b8a99e89786255443119090000000000071c31475c71869cab927d676074879ca59d89817f899eb3bdb29d8775604b37271501000000000000000000011426364a5c677d8c9da6afab9f9b9da6b39e8977614c3a291704000000000000000111212f404c5c64768291958076889da9a59d917f695d4b382010000003142432424f5d65707370645c4a3b2a180500000000000000000000000000000000000000040a0c0d0b080100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000303010000000000000000000000050b0d0c0a030000000000000000000000000a161e212827313638383838373531263231302f2d2c2b2a26221f180d0300000000000000000000000000000000000000000000000000030d0a151d2024313f4c5a6273808c857f8986777d89897a7a8985797a7e777262756175746066665e617779645544311d080000000000000000000000000000000f24394f64798e8d78849aafa78e79644e39240f0000000000000000000e23384d63788d89758a9eb4a38e79644e39240f0000000000000000000000000001172c41566c8196abc1d6c5b09b86705b46311b000012273d52677c929f8c9ea8b9ae98836e60758499a1b3b3aba5a4a9b3b8aa9f8b7a645443301c0700001a2f445a6f8499afc5d4c8b5a49c919faaa59d93969fabb4a79e8b7c665a48372715000000000000051b30455a70859a9f8b776256657b8b9fa89e96949ea7b8b19f927d675645321909000000000000000000000008182d3e4d5f677b88939a9faaa8aaab9f927d675947341c0c0000000000000000000312222f3e4a58616e7c878e848b95938f877c69614f3f2f1c02000000061424323f4b505b5e5b4f4a3e2d1d0d000000000000000000000000000000000000030c171f2122201d1509000000000000000000000001080b0e0e0b08010000000000000000000000000000000000000000070b1016181916110c09030000000000020d181f22211e160b000000000000000000000c1a2832363e37444b4d4d4e4d4c4b4448474645444341403f3c37342a1e160a00000000000000000000000000000000000000000000000000000002090b13212f3c4855606a798592889c867779868f8382898d837f696055605660605550514d5961645c4a3727150200000000000000000000000000000013283d53687d929e899aa1b39e8974604b35200b0000000000000000000d22374d62778c918991a8b9a28d78624d38230d0000000000000000000000000000162b40556b8095aac0d5c4af99846f5a442f1a000010253a50657a8fa5a1b4b9c6ae98836e57617583939ea8b1b4bbb4b1a69d8c7d675c4a362513000000152a3f546a7f94a7b7c3baaa9c867b8c9faab2a9abafaa9f98897c665e4c3c2b190900000000000002182d42576d82979a846f594b5d687e8d9fa9abaab3b8b4a297816c5f4d38281600000000000000000000000000102030414d5d65757e858b909395948c7f695f4d3b2a1800000000000000000000000412202d3a474c5e6673797d80807e7a73665e4f4332211100000000000614212f373b4549453a362d20100000000000000000000000000000000000000b171e29333638353127191305000000000000000009141d202323201c1408000000000000000000000000000000000008131c20252b2e2e2c27211e160b0100000a151d2a34373632291b1406000000000000000c1c2a38454b535a5560626363626160555e5c5b5a5958575654514c483b32281b0a000000000000000000000000000000000000000000000000000000000003111d2b37444b5b63707d88939a85707786877279887b69614a444b454b4b44373c3a474c4e4a3e2d190900000000000000000000000000000002162838576c8196a79ea7b3ae99846e5443301c080000000000000000000b21364b60758b8a7f8a9fb4aa8b76614c36210c0000000000000000000000000000142a3f54697f94a9bed4c2ad98826d58432d1800000d23384d62788da4b5c9cdc0ab96816c565761727e89949b9faa9f9b94887c675f4d3e2e18080000000c22374c6177899da5a9a99f8c7b677d8c989d9f9e9a948b8277665e4c402f1d0d000000000000000012273c52677c918d7a644f3f4e60687d8b9aa2a7a8aa9f968474604b41301a0a00000000000000000000000000021223303f4b56606870777b7d807f7969614f41301d0c00000000000000000000000002101c2a33404c546064686a6b696560544d403225150300000000000003111c232530343024221b100200000000000000000000000000000000000b1b29333a464c4d4b44373023130100000000000412192631353839353026181205000000000000000000000000000311182530353a404343413c3632281d15090a1a28323b484c4b463931241403000000000004182a3a475660686f7375777878777675747372716f6e6d6c6b696662594b45392816030000000000000000000000000000000000000000000000000000000000000d1926313d4a4e5f67757e88806b6277806b637773604b4331353236353127272a343739362d201000000000000000000000000000000000091e32455671869bb0b3b8c5a9947f695436261401000000000000000000091e32455774898b7f8b9fb49f8a75604a35200b000000000000000000000000000013283d52687d92a7bdd2c0ab96816b56412c1600000b2035495a71869cb1bbc0b4a2907b655046546068767f868a8c8a867f76665e4d41302010000000000a1f334758647b879194928a7d675f677983888988857f786d62594c402f22110000000000000000000b21364b6074827e685d4b37424e5f6879848d9193918b81746056453123130000000000000000000000000000000512212f38454b53586165686b6a635b4f433223130000000000000000000000000000000c181f2f36434a4f525555544f4a433630221507000000000000000000080e101b1e1b0f0d0700000000000000000000000000000000000003172939464c58616260554d4130200f000000000312222f37444b4e4e4b43363023140600000000000000000000000614212e36434a5055585856514b4639312719152838454b596261574e4231211100000000000a1f33475861747e84888a8d8d8d8d8c8a8988878685848281807f7b776c605745321e100000000000000000000000000000000000000000000000000000000000000009141d2d36414d56606975726059626b625962605544311d201e21201d1511181f2224221b1002000000000000000000000000000000000b21364b60758a9fb4c8ccbaa98f7a644f3a250f00000000000000000000031628395c71869b949fa9b39e89735443301c07000000000000000000000000000011263b50667b90a5bbd0bea9947f69543f2a14000006192b3c51677c919faaa8a29a8473604b36434a58616a71757675716a61574c40302313020000000004182a3a4b5c64757b7e7d77675f4d5b636d7374736f6a625a4d483b2f221104000000000000000000091e324556606d68604e3f2e31414e5b636f787c7e7c776b605645382715050000000000000000000000000000000003111a2832363a474c505355544e4a3d3225140500000000000000000000000000000000041218253035393d40403e3a353025181204000000000000000000000000000609060000000000000000000000000000000000000000000a1e334657616d767774675f4d3e2d1a0700000011212f404c5560636360544d4132241401000000000000000000051424323f4b5460656b6d6e6b6661574b44372b1d324556606d777668604e3f2f1909000000000c22374c61768693999d9faba2a3a2a1a89f9d9c9b9a9998969594918b8175604b3e2d1b0700000000000000000000000000000000000000000000000000000000000000010f1a213138454b55606054484c5651484d4b443726140b090b0b080100040a0c0f0d0700000000000000000000000000000000060c10253a4f657a8faabbcec9b49f8975604b36200b0000000000000000000000192e44596e8399a9b4bab19c87725c3625130000000000000000000000000000000f24394f64798ea4c9d7c7a7917c67523c27120000000e24394d5f697f8b92938f847761544330303a474c555460616055544c46392f2213050000000000000c1c2e3e4b566066696861594d414a4e585d5f5e5a544d483c342b1d11030000000000000000000002162838454b58534e42312023313d494e5a6367696761584b4538281a0a000000000000000000000000000000000000000a161e212a33373b3e403f39362d1f14060000000000000000000000000000000000000008131c2024282b2b2925201c13080000000000000000000000000000000000000000000000000000000000000000000000000000091d2f404c6175828a8d887d675c4a36210f000009192f3f4c5e6674787873675f4f42321f0f000000000000000001132332424f5d65737a808383817c756a6055483c2d3e4b6074828c8a7e685d4c37261401000001142636586d8298a4afb2b4bcc9b8b7c6bab4b3b1b0afaeadacaba9aa9f97836e5c4a36220d00000000000000000000000000000000000000000000000000000000000000000007131a283237444b4a433637413d34373531261909000000000000000000000000000000000000000000000000000000010f1a21232b3b54697e94a9c8d8c4af9a856f5544311d080000000000000000000001162b40566b8095abc0c5af9a85705a45301b0000000000000000000000000000000d22374d62778cabbccdbaa98e79644f39240f0000000a1d30414f6169787d7e7a7061594736261c29333736434b4c4b44373633291b1204000000000000000010202e38454b5154534c473b30363943484a49453f38352b20180d000000000000000000000000000a1a283236423e3b312414131f2c363c494d5253514c473a32281a0a00000000000000000000000000000000000000000003090c171f2125282b2a24211a0f0100000000000000000000000000000000000000000000070b0f13151614100b07000000000000000000000000000000000000000000000000000000000000000000000000000000000f24384c5e6f84989fa69e8d7a644e3d2d1a07011527374b5d667c878d8e877d69604f3d2d1a07000000000000000f1f31424f60697b868f9598989691887f73625a493d4a5c6c8197a09f8d7b655544311d080000081c30435474899eb4c2c8cacfd9cdccd7cdc9c8c7c6c4c3c2c1c0c8bbb4a18e79644f39240f00000000000000000000000000000000000000000000000000000000000000000000000a161e263135353025222b292022201d14090000000000000000000000000000000000000000000000000000000a181f2c353938485970859aafc5d3c2aa957f6a5537271502000000000000000000000011273c51667c91a6c2c2ad98826d58432d180300000000000000000000000000000b20364b60758a9fb4c9b49f8a75604b36200b00000000122332434f5a626869655d4c473a2a180c171f2126303537363127211e170b0000000000000000000002101a2832363c3f3d37342a1d21242e333433302a2320190e050000000000000000000000000000000a161e212d29261f1406010f1a212c35383c3e3c37332a1d150a00000000000000000000000000000000000000000000000000040a0c101316150e0c07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011263b51667b90a2b4b8ab9a85705b4a36210c081d314455657b8c9da5a69d917e695b4a36210c000000000000061a2c3d4e60697e8d9ca4aaadadaba79e948578635b494f647a8c9fb4ab9c8673604b35200b00000b20354b60758a9fb4cadddfe3ebe2e2e9e1dedddcdbdad9d7d6d5d9cebfa8927d68533d28130000000000000000000000000000000000000000000000000000000000000000000000000309141d20201c130d16140b0d0b0801000000000000000000000000000000000000000000000000000000001828363d494e4d4c62778b9fb4cacab6a48e79634e39240e0000000000000000000000000d22374d62778ca4b6c5aa947f6a553f2a15000000000000000000000000000000091d31455672879cb1c5b09b86705544311d0800000000041425323c484d53534f4b3f342a1c0c00040a0c141c2021201d150c0a03000000000000000000000000000a161e21262928221f180c0c0e181e1f1e1a150d0b0600000000000000000000000000000000000002090b1813110b02000000060e192023272927211f170c02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000906000000000000000000000000000000000000000000000000000000000000000000000000000000000417293a586d8298adc0c9b4a28e79634e39240e0b20354b6074879daab7b7b29f8c79634e39240e0000000000000c2135495b687e929fabb5c2c2c3c5b8b3a39b88796359576c8297abbcb5a4907b65503b25100000081c30435472879cb1c5d6e8f7fefff2e2d4cbc8c7c7c7c7c7c7c7c6c5b7a6917b66513c2611000000000000000000000000000000000000000000000000000000000000000000000000000001080b0b070000010000000000000000000000000000000000000000000000000000000000000000000d1d3646535b63625a6b8095abbccfc6b19c87725b4a36210c0000000000000000000000000b2034485972879cb1b8a6907a65503b251000000000000000000000000000000002152738586d8297adbeab96806b5637271502000000000007141e2b35383d3e3a372e1f180c000000000001080b0c0b0802000000000000000000000000000000000003090b1114130c0b0400000003080a09050000000000000000000000000000000000000000000000000003000000000000000000060c0e1214120c0a040000000000000000000000000000000000000000000000000000000000000000000000000000000607030000000000000000000000000000000000000000000000020b11131e1b0c0a04000000000000000000000000000000000000000000000000000000000000000000000000000a1f33475873899eb3c8d1c0a9937e69543e291411263b51667b90a5b6c8cbbbaa98826d583a2a180400000000061a2c3d4e63798b9fb4b3b9c5d6d8d5ccc1b5a69d8777625973889db2c9c2ac96816c57372614010001142636566b8095a7b8cce0edf4f2e7d4c4b7b2b2b2b2b2b2b2b2b1afa79d8874604b36200b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005182a3b53646d787872768a9eb4c9cdbaa8947f69543d2d1a0700000000000000000000000005182b3b556a8095a8b39e8874604b36200b0000000000000000000000000000000011263c51667c91a5b2a08e79634e39240e00000000000000000e192022282925221b100400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090b141b1c180e0c070000000000000000000000000000000000000006131e26283330221f180c0000000000000000000000000000000000000000000000000000000000000000000000000c21374c61768ca7b8ccd7c1ac97826c57422d17172c41566c8196abc3d3d8c8b39e88735847331f0a000000000c2135495b6f8499a99f9ea7b9ccd1c8c5c9c4b7a69a847262778ca6b7cbc5b09b86705544311d0800000c22374c6177899eb3bfcfe2dfdddfcbb7a69d9c9c9c9c9c9c9c9c9a95897a645544311d080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1f3448596d828e8d87879ca8b9cdc5b49f8a77614c37220f00000000000000000000000000000d22374c62778a9fa1947f6a5544311d08000000000000000000000000000000000b20364b6074879da398836e5b4a36210c000000000000000000050b0d1314100e08000000000000000000000000000000000000000000000000000000000000000000000000000000000606000000000000000000000000000000000000000002080b151d1e1a0f0d080000080d0f181a170e0c0600010a1012191a160c0a040000000000000000000000000000000000000000010200000000000000000000000a161e212a30322e24211a0f0100000000000000000000000000000000031324313a3d484537342a1c0c00000000000000000000000000000000000000000000000000000000000000000000000f24394e64798ea3c5c8cbc4ae99846f59442f1a1a2f445a6f8499afc4d9e0ccb8a78c77614c37220c000000000e23394e63798c9f9f8b899eb3c9c0b4afb3b9c4b4a2937e697a8fa5c4d4c9b49f8975604b35200b00000b1f344759677d92a1b2c4d4cbc7cac8b29d888787878787878787857f76645c4a372715020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d22374c62778ca0a49c9ca5b6c6ccb8a796816b5947341f0a00000000000000000000000000000b20344859677d8a8e8373604b3727150200000000000000000000000000000000091d314556647a878c8577624c3d2d1a07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080b151b1b150c0a0400000000000000000000000000000009151d202b32332f25221b10101b22252d302c23211a0f121d25272f302b221f180c00000000000000000000000000000000070c0e1617130b09020000000000000c1a2832363f46474339362d1f1103000000000000000000000000000000112131424e535e5b4c473a2a1804000000000000000000000000000000000000000000000000000000000000000000000f243a4f64798fa4b5b2b7c4b09b86705b46311b1b30455a70859aafc5dae8d5c5a38e78634e39230e000000071a2d3d576c8197a5947e7d91a7beb2a29a9ea7b1bdb49f8b787e93a8bdd3cdbaa98d77624d38220d000004182a3b4d5f6e8399a6b8c3b7b2b5bcaa947f7272727272727271706a61584a3e2d19090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011263b50667b90a5b6b1b2b6c3cebdb39e8877614c3a2a1804000000000000000000000000000005182b3b4d5f6776786f6055443119090000000000000000000000000000000000021527384a5c64737773625947341f0f00000000000000000001080b0f111313141414141414141313121211100f0f0e0d0c0b09020007050000000000000000000000000009151d202a30302b221f180c000000000000000000000000000919273136404748443a372e20202e373a43454238352c1f2330393c44454037332a1c0f01000000000000000000000000010f1a21242b2c28201d150a000000000c1c2a38454b545b5c584e4a3d2f2111000000000000000000000000010009192f3f4e60687370615947341f0a0c13130c0a03000000000000000000000000000000000000000000000000000000000f24394e64798eab9f9da6b7b19c86715c47311c1a2f455a6f849aafc4d9e4cfbaa48f7a654f3a25100000000c21364a5b73889d9d8774859ab0b2a0988589979fb5baa999838197acc1d7d7c7a48f79644f3a240f0000000c1d30414c6176889db3b7a59d9fabb49f8b7a64565d5d5d5d5c5a554c473a2d2010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012273c51677c91a6c3c7c7cacebfb19f927d675947341c0c000000000000000000000000000000000d1d30414d5861635b4b44372715000000000000000000000000000000000000000a1a2d3e4a5460626054473b2a1801000000000000000009151d2024272828292929292929292928272726252524232221201d151e1c1b150c0903000000000000000009192731363f46454037332a1c12040000000000000000000002152737444b555d5d5a4f4b3e2f303e4b4f585a574e493d2f34414d52595a554c473a2c1f0f000000000000000000000005131f2d363940423d3631271a0d000004172a3a4756606970716d635b4c402f1a0a000000000000000003090b161a1426374b5d687e888477614c38271e212829211e170b0000000000000000000000000000000000000000000000000000000e24394e63798e9f8d889db2b19c87715c47321c1a2f44596f8499aec4d9e6d0bba6917b66513c26110000000e24394e63798ea6937d7b90a2b4ad9882707681939fabb3a1998c9fb5cadfd0bba5907b66503b261100000000131f334758667c909fb29d878d9fb5a99c8675604b40474747454037332a1c100200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f24394e64798ea5b6c9d2c9bdb1a197816c5f4d3a2a180000000000000000000000000000000000001223303a474c4e493d31271909000000000000000000000000000000000000000010202d36434a4c4a43362a1d0d00000000000000051319273135393c3d3e3e3f3f3f3f3e3e3e3d3d3c3b3b3a393837373632283331302a211e160b00000000000002152737444b555b5b554c473a2f221305000000000000000000081d314455606a72736f645c4c40404d5c646d6f6c635b4c4044515f676e6f6b6158493d2c1808000000000000000000001323303d4a4e5657524b45382b1d0d000a1f33475861747f85878279655e4c382816030000000000000a161e212b2f2c314455657b8c9d96816c56453133363d3e3633291b0b00000000000000000000000000000000000000000000000000000e23394e63788e9983798da3b29c87725d47321d192e44596e8399aec3d8e7d2bda7927d68523d281300000014293e53697e939e89768499afb6a48e7964616c7e8d9fb5b3ab9fabbccfe3d0bba6907b66513b26110000000004182a3a4c5e6d8197a58e797f95a2b4a496816c5e4c3a2a32302a211f170c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b20354a6073879dabb7c2b5b19f978373604b41301c0c00000000000000000000000000000000000005121c2a333739362c1d150900000000000000000000000000000000000000000002101825303537353025180d000000000000000715233037444b4f515253535454545454535353525151504f4e4e4d4c4b45384847453f3632281b0d0000000000081d314455606a70706a61584c403023130300000000000000071b2d3e4b6073808788847a665e4c4d5e667a82858179665e4c51626b7c83858076635b493626140100000000000000000b1b30414d5b636b6c686056483c2b1c0c1b2e3f4c617685949b9c988b7c655645321e0900000000000a1b2832364045423b4b6073869caa9e8975604b39464b52534c4639291703000000000000000000000000000000000000000000000000000e23384d63788d9883798ea3b29d88725d48331d182d43586d8298adc2d7e9d3bea9947e69543f2914000002172c41576c81969782778c9fb5b19c86715c4c606a7f94a2b4bcb5bcc9daecd0bba6917b66513c261100000000000c1c2f404b6175879d9b8574849aa7b09f907b665847331f1b150c0a040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071c304354667c8d9da6a4a49c9181736055443123130000000000000000000000000000000000000000000c171f2123211a0f0100000000000000000000000000000000000000000000000008131c2022201c13080000000000000000152533414d55606466686869696969696969686867676665646463626160565e5d5c5a544b46392a1d0d000000061a2c3d4b60737f85858077665e4d41302111000000000000000d22364a5c6e82959c9d998b7c665855667c8c989a978a7c66595b6b8091999a958879635443301c0800000000000000031729394d5f677980817d74625a483a291722374b5d6f8399a3b0b1a99d8875604b36210b0000000003162839454b565a575051667c91a4b6a88f7a654f4b57616868615746331e0a000000000000000000000000000000000000000000000000000d22374c62778c97827a8fa4b39d88735e48331e172d42576c8297acc1d7ead5c0aa95806b55402b160000051a2f445a6f8499907b7e93abbcab96816c56424a6072849aa8bacacfdae7e5d0baa5907b65503b2610000000000000121e324657647a8c9f947f78899eb3b39d8876614c41301e0e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001325364c5e677c888e8f8c867c6c6055443727150500000000000000000000000000000000000000000000040a0c0e0c0600000000000000000000000000000000000000000000000000000000070b0d0b070000000000000000000e1e3343505f6774797c7d7d7e7e7e7e7e7e7e7e7d7c7c7b7a7a797877767575747371706a6157483b2a180500000c2136495b6d82949b9a95897c675f4d3f2e1d0d0000000000000f243a4f647a8fa0b2b2aa9e8976616074889eaaafa99e8a786263798c9faeafa69c8673604b35200b000000000000000a1e334657677d8c9597928678625847331f27374f657a8fa1b3c1c7b7a6907b66503b261100000000091e324557606b6f6c65606d8298adc2a8937d68556069767d7e75614c36210c000000000000000000000000000000000000000000000000000c21364c61768b96817b90a5b39e89735e49341e162c41566b8196abc0d6ebd6c1ac96816c57412c170200071c32475c71879c8b768499aec9a7927d67523d435462788a9fb4c5d5e7f7e4cfbaa58f7a65503a2510000000000000031629394b5d6b80959f8b797d91a1b3a698836e5f4d3c2b1808000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008182f404d5f6773797a7771675f4b44372719090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006192c3c50616a7d878e919293939494949493939392929190908f8e8d8c8c8b8a898886857f75625948341f0c00000e23394e63798ea0b0b0a79e8d7d675d4b3c2b1905000000000013293e53687e93a8bec8b8a7927d6764798ea6b8c7b9a895806a697e93abbcc4b5a4907b65503b2610000000000000000c21364c6176899eaaaca49c8676614c3f2e3144556d8297adbfd0d4c4a9937e69543e2914000000000b21364b60758084817b7373889db3c1ac96816c68747e889293846f5a45301a050000000000000000000000000000000000000000000000000b20364b60758b95807b91a6b49e89745f492614152b40556a8095aabfd5ead8c2ad98836d58432e180300081e33485d73889c8773889db3baa5907a65503b36495a6a8095a7b8cce0f5e4ceb9a48f79644f3a240f000000000000000b1b2e3f4b6073859b9b85738399a7b2a0927d675a48362614010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000122230404d546063646259514d4131271909000000000000000000000000000000000000000000000000000000000000000000000000000000000000080e101516110f0900000000000000070d0f14140e0c060000000000000c2035495a6a7f929da5a6a7a8a8a9a9a9a9a9a8a8a8a7a6a6a5a4a3a3a2a1aa9f9e9d9c9a948677624c3b2a18040013283e53687d93a8bec5b8ab9f8c7b655a48342013000000000013283d53687d92a8c1d2c2a9947f6963798eaabbcec6ae98836e697e93a9c4d2c2a8937e69533e29140000000000000010253b50657a909c9ea7b5a498826d5d4b37354b6074899eb3c9ded4c4a7927d68523d281300000000152a3f556a7f949a9790868196a6b7c5af9a84747d87939ea79e89735e49341e090000000000000000000000000000000000000000000000000b20354a60758a95807c91a6b49f8a745443301c142a3f54697f94a9bed4e9d9c4af99846f5a442f1a05000a1f34495f74899883778ca6b7b9a38e79644e392c3c4b6175889eb3c8ddf0e3cdb8a38e78634e39230e0000000000000000101d31445563798a9e957f77899eb3b39e8978625443301c1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000412223036434b4e4f4d483b39301d1509000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c23252a2c26231c110400000004101b2224292a23211a0e00000000000e23384d63788b9fb2b7c3bdbdbebebebebebebebdbdbcbcbbbab9b9b8b7b6bbb4b3b2b1afa499836e5947341f0b0012283d52677d92a7c2d3c9bbaa9e8978624d41311a0a000000000f24394f647a8ea3b5c3b5a4917b6661768a9fb4c5bbaa97816c667b90a6b8c5b6a5917c66513c26110000000000000010253b50657a9087899eb3b2a08f7a644f3f3b50657b90a7b9ccdfcbb7a68e79634e39240e00000003182e43586d8398adaca49c969eb0c4c9b49f8b88929ca5b3ae99836e59442e1904000000000000000000000000000000000000000000000000071c304354758a95807c91a6bbaa8a75604b352013283e53687d93a8bdd2e8dac5b09b85705b46301b0600071c304354758a9681798ea4c4b8a38e78634e39233246576a8095aac2d3e5e2cdb7a28d78624d38230d000000000000000001152737495b687e929f8b7a7d92a2b4a89a8473604b3e2d1b0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041218263035393a37342b241d120100000000000000000000000000000000000000000000000000000000000000000000000000000000000e19202e373a40413b382f221406000c181f2d36393e3f38352c1f110300000013283d52687d92aabbcbd4d2d2d3d3d3d3d3d3d3d3d2d1d1d0cfcfcecdccd8cecac9c8c6c2b59f8b77614c37220c000e23394e63798ea4b6cad8c8b9a79a846f5f4d382815020000000d22364a5c71859ba6aca59c867460576f8499a7aeaa9f8c79646075889daaafa79d8774604b36200b000000000000000d23384d62788d7e7d92a6b8af9a846f5d4b3d566c8196abc5d6ddc8b39d8873604a35200b00000000152a3f546a7f94a9bab5b1abb0bccdcdbaa99f9da5b2b6b3a18f7b65503a251000000000000000000000000000000000000000000000000000081d314455758a957f7c91a7b5a08b76604b362112273d52677c92a7bcd1e7dbc6b19b86715c46311c07000b20354a60758a947f7b90a6bbb8a28d78634d382329394d62788da4b6cadee1ccb7a18c77624c37220d00000000000000000009192c3c4e606e83999c8674859aaab4a2947f6a5c4a3928160300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008141c2024252220180d0a0100000000000000000000000000000000000000000000000000000000000000000000000000000000010f1e2c353f4b505556504c403224140e1d2a343e4a4f54544e493d2f211100000013283d52687d92aabbc9d1d6d6d7d7d8d8d9d9d9dadadbdbdcdcdddddddededfdfdedddbcfbcab8e79644f39240f000c21364a5b72879cb1c4d5d6c5b3a1927d675645321d09000000071b2d3e4e637988949794877863554e6379899699968c7d685c56667c8b979a97897a645645321d09000000000000000c2035495a72878674889eb3b4a2907b6550495b72879db2c7dcd7c7ac97826c5443301c07000000091927374c62778a9fb4c8c6c0c4cddad7c7bab4b2b7c3bbaa99836e5d4b37291b0e0000000000000000000000000000000000000000000000000b20354b60758a947f7c91a7b7a28c77624d372211263c51667b91a6bbd0e6dcc7b19c87725c47321d07000b20354b60758a947e7c91a6bcb7a28d78624d38232035495a71879cb1c6dce0cbb6a18b76614c36210c000000000000000000000e1e31424c6176889d947f798c9fb4b49f8b7a645746321e120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080b0e0f0d0b05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1f2d3c494d5d656a6b665e4f43321b1e2c3b474c5c646969635b4c3f2f1c0800000d22374d62788b9fabb4c1c0c1c1c2c2c3c3c4c4c5c5c5c6c6c7c7c8c8c9c9c9ced8d4cac3b3a28c77614c37220c00071a2d3d54697f94a6b8cbe0d0bfb29d8774604b36201100000000102135495b63777e827f76635a49495b637881848179685f4e4c5e667982858178645c4a382815020000000000000006192c3c54697f8e798095abbcb09a85705e4e63798ea5b6cadfcdbaa9907b665136251300000008182737444b596a7f95aabbced6d8e0ebe5d7cdc9c7cbcab49f8b7863554b46392b1e0e00000000000000000000000000000000000000000000000b21364b60768b95807c91a6b9a48f79644f3a2410263b50657b90a5bad0e5ddc7b29d88725d48331d08000b20354b60758a937e7c91a7bcb8a38d78634e3823192b3c586d8297adc2d7e0cbb5a08b76604b36210b0000000000000000000000131f334758657b8d9f8a788196a6b7aa9c8675614b40301c0c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1b2d3d4a5a62707a7f817b69614f39282c3c4959616f797e7f79655d4c38230c00000b20344859687e8d9ba3a8abacacadadaeaeaeafafb0b0b1b1b2b2b2b3b3b4b4bbb5c3b7b2a59a846f5947341f0a00000f21364c6176889eb3c2d2dfcab7a5937e69533f2e1c08000000061a2c3d495861696c696157493c3d495a626c6e6c645c4e41404c5c646d706c625a4a3e2d1a0a0000000000000000000e21364c61768982788c9fb4b4a2907b65546a7f94a9c3d3dec9b49f8a75604b36210b00000013253644556069737d8b9fb4cadff4f3fff5eae2dfddddc8b39d8876706a6157493c2b1906000000000000000000000000000000000000000000000c21374c61768c95807b91a6bba7927d67523d2812253a4f657a8fa4bacfe4ddc8b39e88735e49331e0900081c304354758a947f7c91a6bbb8a38e78634e392313283e53687d93a8bdd2e2cebbaa8a75604a35200b000000000000000000000004172a3a4c5d6b8096998376889db2b6a497816c5e4c3a2a1804000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090c1317110f090000000000000000000000000000000003060500000000000000000000000000000000031629394a5b6378858f9596907f695746323a495a6277838e93948b7b65503a2a17040005192b3b4e60687c858e9296979797989899999a9a9b9b9b9c9c9d9d9e9e9f9faaa0a0a59d958778624d3a2a180400000a1e334657687e93a4b5c9ded4c3b19c87725d4b37230e000000000f1f2c3a474c5457544c46392c2c3c494d5659574e4a3d312f3d4a4e575a574d483c2d2010000000000000000000000a1e3346576b8089768398aec0b09b85705e70859bb0c5dad9c9ae99846e5645321e090000071c30435460737f87919faabbcee2f7fffffffdf6f4f2e0cbb8a69d8b867f75625a4935200b000000000000000000000000000000000000000000000d22374d62778c96817b90a5bbac97816c573f2e1b253a4f647a8fa4b9cfe4dec8b39e89735e49341e09000114264a5f748995807b90a5bab9a38e79644e392411263b50667b90a5bbd0dfcab49f8a755443301c070000000000000000000000000c1c2f3f4b6074859b917c7c91a1b3b19f917c665847331f10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b161e21292c26241d120400000000000000000000050b0d14181b1a150c0a040000000000000000000000000b1e3246576379899ba3aaab9e8976614b36465862788799a1a9aa9c86715847331f0a00000d1d31424e5e6670797d81818282838384848485858686878788888889898a8a8b8b8b878077625a49351c0c000000031729394b6073869cb1c0d1decab6a48f7a65503a251000000000010f1c2a33373f423f3633291b1e2b353841444139362d1f1f2d363942454238352b1e100200000000000000000000031729394c62778a7f798fa2b4b5a3907c66778b9fb4cadfcfbcab937d68533828160300000b20354a607282949da5b4bbc8d9ebfefffffffffffffae7d5c4b8aa9f9b958778624d38230d000000000000000000000000000000000000000000000e23384d63788d96817a8fa5bab29d87725d4b3722253a4f647a8fa4b9cfe4ddc8b39d88735e48331e0900001e34495e73899781798fa4c8baa48f7a654f3a251024394e63798ea3b8cedec9b49f89745f4a25130000000000000000000000000000111d31455663798a9d8775849aa9bab39e8877614c3f2e1b080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003111b2832363e413c382f22120200000000000000000d182022292e30302b211f170c000000000000000000000b1b2f3f4b6175879da7b4c1b9a78e79644f414c6176879ca5b3bfb5a48c77614c37210c000000142431404c505c64686b6c6c6d6d6e6e6f6f70707071717272737374747475757675726b6159493c2c1900000000000b1d314455667b90a2b4c8ddd3c2ab96816c563828150200000000000c181f22292d2a211e170b0e1920232c2f2c24211a0f0f1a21242d302c2320190e000000000000000000000000000b1f3448596d828875859ab0c1b19c86737d92abbccfdfcab49f8b77624c37220d0000000f253a4f647a8fa0b2b7c3ced9e6f6fffffffffffffffff2e2d5c8bbb4b0a599846f5a442f1a050000000000000000000000000000000000000000000f24394e64798e97827a8fa4b9b6a58f7a654f3c2b253a4f647a8fa4b9cfe4ddc7b29d88725d48331d0800081e33485d73889984778caabbbba6907b66513b261122374c62778ca1b7ccdec9b49f89745f4a341f000000000000000000000000000002152738495b697e939580788b9fb4b8a797826d5d4b3722110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000115212f39464b5357514c402f201000000000000007141d2b34373e4345454037332a1c0e0000000000000000031729394c5d6c8197a5b6c5d1c3a5907b66504d5f6d8298a5b6c3cfbcab8e79634e39240e0000000614222f383e4a4e5356575758585959595a5a5b5b5c5c5d5d5d5e5e5f5f5560606056564c473b2c1e0e0000000000011426374c5e70859ab0c5d5dcc7b19c87725645321d09000000000000040a0c1417140c0a030000060b0d1719170f0d070000070d0f181b170d0b06000000000000000000000000000005182a3b4e63798b7d7b90a3b5b5a4937e8399aec9d9dac5b09a85705947341f0b00000012273c51677c91a6bdc7d0e2ebf6fffffffffffffffffae9d9cbc1c3b7b2a599846f5a442f1a0500000000000000000000000000000000000000000010253a4f657a8f9782798ea4b9c3ad97826d5a4835253b50657a90a5bacfe5dcc7b29c87725d47321d0800071d32475c72879b86728a9fb4bca7927c67523d271221374c61768ca1b6cbdec9b49f89745f4a341f00000000000000000001080b141b161e212c3d4e606f83998b798196a8b9b1a08f7a654f402f1c090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009141d323f4c5761686c665e4c3e2d1b0700000000071525323b484d54585b5a554c473a2c1e0e00000000000000091e334657657b909fb1c3d4cab6a58d78634e59677d92a0b2c3d3cab49f8b76614b36210c0000000004111c232d36393d414242424343444445454646464747484849494a4a444b4b4b453837342a1d0e0000000000000009192f4052677d92a6b8cbdfcab59f8b75604b36200b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d2135495b6e838774869bb1c2b49f8b8b9fb4c9ded2c2a9947f69543b2a18050000000e23394e63798e9fafb3bfccdaeafcfffffffffffffff1ddcbbbaea9a59d948779634d38230e0000000000000000000000000000000000000000000010263b50657b909883798ea3b8cab49f8b78624d3f2e3c51667c91a6bbd1e6dcc6b19c87715c47321c0700061b31465b70869b8a7c8b9fb4bda8937e68533e291321364b61768ba0b6cbdfc9b49f8a745f4a2614010000000000000009141d2029302832363738424c6277899c86858a9eb4beb09a85705e4c38230e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009192631434f5d65757e817c665c4a36220d00000000152532434f5962696d706f6a6158493c2c1906000000000009192e3f4c6176879db2bdced4c4b29d87725b4d6277899eb3becfd5c4b09a85705746321e0a000000000000090f1a2124282c2c2d2d2e2e2f2f2f303031313232333333343427313636363228221f180c0000000000000000001220364b6075889eb3c8d8cfbcab8d77624d38220d00000000000000060c0e1215171819191919191a1a1918161512100b080100000000000000000000000000000000000000000000061a2c3d4f647a8f7c7c91a4b6bbaa9f9fa9bacddec9b5a48d78634d38230e000000000c2136495b6c819099a1afbcccdff2ffffffffffffffebd6c1ae9d938d877f75635b4935210c0000000000000000000000000000000000000000000011263c51667b919883788da3b8cebbaa98826d5d4b3a3d53687d92a8bdd2e7dac5b09b85705b46301b0600051a30455a6f859a9d888a9fb4bfa9947f6a543f2a1521364b61768ba0b6cbdfcab59f8a755544311d080000000000000b192631353e4538454b4c4d4e4e59667c9195807b90a5bab4a2907b66503c2b19050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008182637444b616a7b8893968d7a644f39240f0000000d1d32434f6169777e8385858076635a4935201000000000011426374b5d6d8297a5b7cbdfcbb7a6937e69545e6e8399a7b9cce0cbb8a6937d68533929160300000000000d1820273136393a3b3b3b3a3a393939383837373636322834333231302f2d2c2a23211a0f01000000000000000000091d3145566b8095aabbcecebbaa8c76614c37210c0000000000080f1a2123282a2c2d2e2e2e2e2e2f2f2e2d2c2a2825201d1509000000000000000000000000000000000000000000000f22374b5c6f848673869cb1c3bbb4b4bac7d7dbc6b19c86715a4935200c00000000061a2c3d52636c7b84959eafc3d7f3f5fbfffffffffee8d3bea9937e78746a6157493c2c19060000000000000000000000000000000000000000000012273c52677c919983798ea3b8d8c8b2a0907b6558473a566b8196abc0d6ebd8c3ae98836e59432e19040004192e44596e8399917c8095abc0ab96806b56412b1621364c61768ba1b6cbe3cfbcab8a75604b35200b00000000000b1b2937444b535b5d56606162636363636d8298888196abc1c0af99846f5a4835200b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011426364455606c7f8d9da6ab937d68533e2813000005192b3c4f616a7f8a93989a9a958878634d3e2e1b07000000081d314455657a8d9fb5c3d4d4c4b29d88756056667c91a1b2c5d6d6c5b39e8875604b36210b0000000003111d2b3438454b4e4f5050504f4f4f4e4e4e4d4d4c4c4b454a49484746454443413f39352c1c14080000000000000000021527384d62778b9fb4c6cab49f8a75604b35200b00000003111c232c35383d404243434343434444444342413f3d3a3531271910020000000000000000000000000000000000000000071b2e3e50657b907c7d92a5b6cac9c9cdd7e5d2c1aa947f6a553c2c190600000000000f1f3545525d656f8095aac0d5dde0e7f3fff9f0eae7d3bea9937e6960544b46392c1e0e000000000000000000000000000000000000000000000012273d52677c929f8c879db2c8cbc8beb29d8776615647586f849aafc4d9ebd6c1ac96816c57412c17020003182d42586d829798828298adc1ac97826c57422d1721364c61768ba1b6cbecdab6a08b76614b36210c00000000031729394655606970737476777878787979797d929e969eb0c4cab49f8b78624d38220d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004121c304354607381949fabb5a48f7a65503a251000000b2034485a6a7f949fa9adb0afa69b85715c4b37220d0000021527384b6073869cabbccfdfcbb7a6937e69566075889db2bfcfe0ccb9a7947f6a5645321e090000000011212f3b484d566063656565656564646463636262616160565f5e5d5c5b5a595856544e493d3026180800000000000000000a203448596d8297a8b9c4b19c86715544311d0800000011212e373d494e525557585959595959595959575654524f4b44372e20100000000000000000000000000000000000000000001023374b5d70858675879cb2c3d4dee1e9ddc9b5a38d78634d38230e000000000000011727353f4c6177889db2c8cbc8cbd5e3f3e8dcd5d2d6c9b49e8a78624d3d32281b0e00000000000000000000000000000000000000000000000012283d52677d929e888398adc4b7b3b4b7a69a8474615861768a9fb4c9dfe9d6c6a9947e69543f2914000001172c41566c8196a09898a0b2c3ad98836e58432e1921364b61768ba0b6daeccbb6a18c76614c37210c000000000a1e33465761737e85888a8b8c8d8d8e8e8e8e929bb3abb0bdcdcfbcab947f6a543626140100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001122232434b607282979fb4bcb19c8673604a35200b00000d22384d62788b9fb4bac7c5c4b5a38f7a644f3a240f0000091d314556687d92a4b5c9dad3c3b29d87756056697e93a6b7cbddd4c3b39e8976614c382816030000000c1c2f3f4c59626c75797a7b7b7a7a797979787878777776757574737272706f6e6d6c69635b4b43362614010000000000000005182b3b4c62778a9eb4b5a695806a553726140100000d1d2e3f4b505b63676a6c6d6e6e6e6e6e6f6f6e6d6b6a676560554b3e2e1a0a0000000000000000000000000000000000000000081c2f3f51667c917c7d92a5b7cadff4ead8c8b09b86715a4935200c000000000000000a1f3347586c8197a6b7c5b8b3b8c5d5e7d8cac0bdc1c5b9a897826d5b4a36210b0000000000000000000000000000000000000000000000000012283d52677d929d877f94a9b7a69d9faab4a29a847667697e93a9bacde2e1cdb9a88f79644f3a240f000000152b40556a8095aaadadb2bec4ae99846f59442f1a20364b60758babbccfe3ccb7a28c77624d37220d000000031628384b617584939a9d9fa9a1a2a3a3a3a3a3a7acb9c1c4cddbd9c9af9a846f5443301c080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1f30404f616c8197a0b1bdb3a1907b665443301c070000142a3f54697f94aabbcdd7dad2c1a8937e68533e291300000b20364b6074879db2c2d2decab6a4937e68566075889db2c4d4dfcab6a5947f6a5746331a0a0000000417293a4c5d657781898e8f9090908f8f8e8e8e8d8d8c8c8b8b8a8989888786858482817f796c605443301c0b00000000000000000d20344859687e939ea49c8876614c37210c000005192b3c4b5d6571787d7f8182838383838384848382817f7d7a74645c4b3827150200000000000000000000000000000000000000001120354a6073868675879db2c7ddeae2cebbaa947e69543c2c1906000000000000000c22374c61778b9fb4b6b2a69ea6b8cbe0cabaada8acb1bdb49f8c79634e39230e0000000000000000000000000000000000000000000000000011273c51667c91a59d949daeb39d888c9fb4b3a29a877c7a899eb3c7d7eadec9b49e8975604b35200b00000014293f54697e94a9bec2c5cfc4af9a846f5a452f1a20354a60758a9fb5cadfcdb7a28d78624d38230d000000091e3245566d8297a2b0b2b4bac7b7b8b8b8b8b8bcc0cad6d8e0ebdec9b49f8975604b35200b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009192c3d4c5e6a7f949fb1beb9a899846f5e4c362513000003182d43586d8298adc8d8e9ebd9c8a9947f6a543f2a150004182a3a53687d93a5b7cae0d0c0b29c87746053697e93a6b7cbe2d0c0b29d8774604b392917000000000a1f334658657b8a979fa8a4a5a5a5a4a4a4a3a3a3a2a2a1a1ab9f9f9e9d9c9b9a999896948c8172604b392917030000000000000005182b3b4e60697f898b867a645847331f0a00000b2034485a657b868d929597989898989899999998979694928f887a645645311d090000000000000000000000000000000000000000071c304354677c907c7e93a8bbccdedfc9b49f8b77614c37220e000000000000000012283d52677d92aab4a59d8f889eb3c7d7c0ad9c92979fb2b6ab96806b56412b160100000000000000000000000000000000000000000000000010253b50657a90a5b2a9aebba8927e7f95a5b6b3a59d918f9ea7b8cce5e6d3c3ae99836e5544311d0800000012283d52677d92a7bcd2dadac4af9a856f5a45301a1c30435473899eb3c8deccb7a28d77624d38220d0000000b21364b60758a9fb4c0c8c9ced8cdcdcdcececed2d4dce3dfdddad7ccb9a88b76614c36210c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001142637495b667c8d9fb5bdbeb49e8a78624d402f1808000002172c42576c8197acc1d1dedecebbaa927d68533d2813000a1f34475970859bb0c3d4d6c6b3a2917c66555b71869cb1c4d4d7c6b3a2917c665645321b0b000000000c21364c6176899ea8b4bac6babababab9b9b9b8b8b7b7b6b6bcb4b4b3b2b1b0afaeadabab9f95806b5746331e0a00000000000000000d1d31424f6169757671645c4a3a2a170400000d22384d62788b9ca4a7aaacadaeaeaeaeaeaeaeaeacaba9a7a69d8774604b36200b0000000000000000000000000000000000000000001325364b6073868684959dafc3d7d4c3ae99836e5947341f0a0000000000000001162b40566b8095a99f95877a7c90a9bacdbda8927e81909ca5aa98836e59432e19040000000000000000000000000000000000000000000000000e23384e63788dabbcbec2c6a6917c75879caabbb7b2a7a4b3b8c5d5e8dfcab6a5907b66503727150100000010253a50657a8fa5c3d3e6d9c4af99846f5a442f1a1325365c71879cb1c6dcd4c3a18c77624c37220d0000000e23384d63788da9bacddddfe1dedddbdad8d6d5d3d1dacfcac8c5c7bab49e8975604b36200b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081d31445563798a9eabbcc2b2a0937e685a483522110000000011273c51667c91a3b4c2c9c9beb49f8b78624d38220d000c22374c61778ca3b5c9e1ccb9a89a846f5e4e63788da4b5c9e1cdbaa89a846f5e4d382815000000000011273c51667c91a7b8c6cdd7d0d0cfcfcecececdcdcdccccd9cfcac9c8c7c7c5c4c3c2c9bcb49f8a76614b36210c000000000000000000142432434f566061574e4a3d2d1c0c00000012273c52677c91a9b5c2bfc1c2c3c3c3c3c3c4c4c3c2c0bfc4b7a58e79634e39230e000000000000000000000000000000000000000000081c304354667b907f7f95aabfd4cab7a5917c66513a2a1804000000000000000011263b51667c8d928b807565758a9fb4c9c4a48e7a6c7c8791958c7c66513b2611000000000000000000000000000000000000000000000000000b21364b60768b9fb5cacdb9a88e79647a8b9fb4bcc7bcb9c8ccd5e3dfcfbfb29d8773604b35200b000000000d22374c62778ca5b6cadfd7c6ad97826d58422d181a30455a6f859aafc4dacbb7a58b76604b36210b0000000c21374c61768ca2b4c5ccd5ccc9c7c6c4c3c1bfbebcc9bcb5b3b0ada99f96806b5645311d09000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b20354b6073869ca8b9c4b5a498826e604e3c2b1903000000000b20354b6073859ba4b1b4b4afa096816b5a4835200b0010253a50657a8fa5c1d2cebdb49e8a78624d52677c92a7c2d2cebdb49f8a78624d40301a0a000000000013283d53687d92a8becfd9dadadbdbdcdcdddddededfe2eaebe3dfdededddcdbdad9d7d9cdbaa98e79634e39240e0000000000000000000614243238454b4c4639362d1f0f000000000f24394e64798e9faaadb0b3b5bcc9babbbcbcbdbdbdbcc9bcb4a38d78624d38230d000000000000000000000000000000000000000000011426364c5e6e83848095aabfcebfb29d8774604b35200c0000000000000000000f24384c5e667a7d786b60566f849aafc6b8a68c766166747c807a665e4c38240f00000000000000000000000000000000000000000000000000091e32455671869bb1c6c9b49e897560697f949eb0bccdd7dee0e2dfd0c1b3a1917c665443301c08000000000b2034485972879cb2c3d3cdbaa8937e68533e2913172c42576c8197acc7d8c7b29d88725745321e090000000a1f33475870859aa7b3b8c5b9b4b2b1afaeacaaa8a6a4ab9f9d9b97938a8073604b382715020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010253a50657a8fa4b5c6b8a69c8675614b42311e0e0000000000081d314455627886949c9f9e9a918273604b3c2b19050011263b51667b90a6c0ccbeb19f927d685a4853687d92a8c1cdbeb19f937e685a493522120000000000000f24394e64798ea0b2bec3c5c5c6c6c7c7c8c8c9c9caced8cbcbcccccdcdcececfd0d0d2c7b6a48d78624d38230d0000000000000000000006141a283236363329211a0f01000000000d22364a5c6a7f8b93989b9d9faba3a5a6a7a7a7a8a7a7a7ab9f998572604a35200b0000000000000000000000000000000000000000000008182f404c627788959eafc3bdb1a1937e685544311d08000000000000000000091d2f404c5c6468625a4b54697f94a8bab39e8873585560676a645c4c402f1d090000000000000000000000000000000000000000000000000002162838566b8196abbfc3ad98836e55616b80959eb4bac7cbd4cecabfb3a399836e5e4d362614010000000005182b3b556a7f94a5b6c4c0b49f8a76614c37210c12283d52677d92a9bacec5ae99846f59392816030000000417293a4e637989979ea7a1a89e9d9c9a98979593918f8d8a8885827e776b605544311a0a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012283d52677d92a7beb9a89d887863574632241300000000000001142637485a62757f868989857c6d605544311e0e00000e23394e63798ea2b4b9b4a097816d604e3c4f657a8fa3b5bab4a097816d604e3c2b19040000000000000d21364a5c6e8298a0aaaeafb0b0b1b1b2b2b3b3b4b4bbb5b6b6b7b7b8b8b9b9bababbc1b5a99c86725a4835200b0000000000000000000000000a151d20211e170b07000000000000071b2d3e50616a777d8285888a8d8e909192929292929291918b8378625443301c0700000000000000000000000000000000000000000000001220344859657b8b9da5a9a79f978372604a372715010000000000000000000012222f3e4b4f524d483c4c61768a9fabae99846e59444b52554f4b3e2f22120000000000000000000000000000000000000000000000000000000f24394e64798ea1b3b7a5917c665151626b80939fa9b2b7c4bbb4afa1998575614b403018080000000000000d21364c6176879ca6afaea295806b5847331f0a0c22374c61778a9fb4c5b8a7927d68523d281300000000000c21364a5b637882888b8c8a898886858381807e7c7a787573706d6962594b443726140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f24394e64798ea0aba79e8a7a645a49392816060000000000000009192b3c485760697174746f665e4b443726140000000c2136495b6f84989fa89e958273604b42374b5d71859ba4a99f958273604b42311e0e00000000000000071a2d3d4b6074828e95999a9b9b9c9c9d9d9e9e9f9faaa0a0a1a1a2a2a3a3a4a5a5a6a6a39b8b7b65503c2b19060000000000000000000000000002090b0c0a0300000000000000000010203343505962686d70737678797a7c7c7d7d7d7d7c7c7b776f62594836251300000000000000000000000000000000000000000000000005182b3b4b5d657a879093928c817560544330190900000000000000000000000412202e373a3d3835334758677d8d9c9b907b66503b363c403a372e2012040000000000000000000000000000000000000000000000000000000d22364a5c6e8399a6aa9d8774604b4451626b7e8a969da6a4aa9f99918376615746332212000000000000000a1e334657637988969a99938474604b3a2a17040b1f3447596d8298a7afaa9e8975604b36210b0000000000071a2d3d4a5a626c737676757472716f6e6c6a6967656260565b58534d483b312619090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d22364a5c6e82919693897b655c4a3c2c1b0b0000000000000000000e1e2b39454b545c5f5f5a514d4031261909000000061a2c3d4c6176828a8d897f73605544312e3f4e6379868e8f8a7f726055443124140000000000000000000f1e324556606d798084858586868787888889898a8a8b8b8c8c8d8d8e8e8f8f9090908d857b655d4b371e0e0000000000000000000000000000000000000000000000000000000000021525333b484d53585b566062646566676768686867676662594d483b2b1808000000000000000000000000000000000000000000000000000d1d2e3f4b5c64747b7e7d776c6057453625130000000000000000000000000002101b22242822202a3a4d5f687d86867d685e4c3820272b24221b100200000000000000000000000000000000000000000000000000000000071b2d3e4d62788896978c7c65564531445160687881888c8e8d8a847c6e615847392917040000000000000003172939495b63778084837e73605645311c0c0004182a3b4d627889969a988c7d675645321e090000000000000f1f2d3c484d5758616160555d5c5a59575553514f4d4b4538423e37342b1d140900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071b2d3e4a60727c817e77655d4b3e2d1e0e00000000000000000000000e1b2832363f474a49453c39301d140900000000000f1f334658616d7678756a60554437272135495b6373787a766a6054443727150600000000000000000002162838454b5c646b6e7070717172727373747475757576767777787879797a7b7b7b7870655d4b3f2f1c0000000000000000000000000000000000000000000000000000000000000007151d2b34373e4338454b4d4e505152525253525252514c483b342b1d0d00000000000000000000000000000000000000000000000000000011212e3e4b566066696762594b4539281808000000000000000000000000000000070d0f130d0c1c30414e5f687171685f4e402f1c12150f0d0700000000000000000000000000000000000000000000000000000000000000102035485a627881827b655e4c382733424e59626c73777978766f665e4c473a2a1b0b0000000000000000000b1b2c3d4959626b6f6e686055453827150000000c2035495a62788185827a675f4d38281602000000000000010f1e2b35383a464c4c4b443747454342403e3c3a383631272d292220180d01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c30435460676b6961594b3f2e200f000000000000000000000000000a161e212a3134343027241d12010000000000000417293a464c57616360564b443727191a2c3d495460636461574b433627190900000000000000000000000a1a28323e4a4e55595a5b5b5c5c5d5d5e5e5f546060616162626363646465656666635a504b3f2f21110000000000000000000000000000000000000000000000000000000000000000000d182022282d28323638393b3c3d3d3d3d3d3d3c3c37342b20190d000000000000000000000000000000000000000000000000000000000311202e38454b5054524d483b32281b0a00000000000000000000000000000000000000000000132331414e525c5b524e4131221100000000000000000000000000000000000000000000000000000000000000000000000005192b3c485a626c6d655d4c402f1a24313b484d56596264636057514c40332a1c0c00000000000000000000000f1f2c3b474c565a59534b4437271a0a00000006192c3c495a626c6f6d645c4d41301a0a0000000000000000000e1920222933363735312631302e2c2b29272523201d1518140d0b05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000132536434a5256544c473b2e211001000000000000000000000000000003090b141c1f1f1a110f090000000000000000000b1b293339464b4d4b4538312619090e1f2c36434a4e4f4b463930261809000000000000000000000000000a161e2d363940444546464747484849494a434a4b4b4c4c4d4d4e4e4f505051514d493c372e21110300000000000000000000000000000000000000000000000000000000000000000000050b0d1318161e212324252727282828282727262220180d0500000000000000000000000000000000000000000000000000000000000002101a2731363b3e3d37342b1e160a0000000000000000000000000000000000000000000000051323313a3d47463d3a31231304000000000000000000000000000000000000000000000000000000000000000000000000000e1e2b3c484d57584f4b3f2f2111141d2b34373b484d4f4e4b453939301f170c000000000000000000000000010f1d2a34374145443e353126190a00000000000e1e2c3c494d575a584f4b3e3023120000000000000000000000050b0d171f2121201d141c1a1917151412100d0b0902000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008182530353c413e37342a1d100300000000000000000000000000000000000000070a0a05000000000000000000000000000b171f293336383631271d140900000e18253035393a3632291c140800000000000000000000000000000002101b22242b2f30303131323233333425303536363737383839393a3a3b3b3b38352c231c11030000000000000000000000000000000000000000000000000000000000000000000000000000000003090b0d0f101112121313131212110d0b05000000000000000000000000000000000000000000000000000000000000000000000a151d202629282220180d030000000000000000000000000000000000000000000000000005131e2528323128251e13050000000000000000000000000000000000000000000000000000000000000000000000000000000e1e2b353841423a372e211103000d1920222b34373938363228241d12040000000000000000000000000000000d181f222b2f2e28201d1409000000000000000e1e2c35384145433a372e2012050000000000000000000000000000040a0c0c0b080100050402000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008131c20272c29221f180c000000000000000000000000000000000000000000000000000000000000000000000000000000040b171e2123201d150a010000000008131c202325211e160b01000000000000000000000000000000000000070d0f16191b1b1c1c1d1d1e1e1f131c20202121222223232424252626262320190e08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090b1114120d0b0500000000000000000000000000000000000000000000000000000000010b10131c1c13110b0100000000000000000000000000000000000000000000000000000000000000000000000000000000000e1920222c2d25221b1003000000050b0d1920222423211e160a09000000000000000000000000000000000000050b0d161a19130b08010000000000000000000e1920232c302d25221b1002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070b1216140c0b04000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a0c0e0b09020000000000000000070b0e0f0c0a030000000000000000000000000000000000000000000000000405060607070808090000070b0b0c0c0d0d0e0e0f0f101011110e0c06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b0d1718100e080000000000000000050b0d0f0e0b090300000000000000000000000000000000000000000000000105040000000000000000000000000000060c0d171a180f0d0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + m_StreamData: + serializedVersion: 2 + offset: 0 + size: 0 + path: From 609face6f56c29786725104b72b8a1d09c183534 Mon Sep 17 00:00:00 2001 From: Shayla Beltran Date: Mon, 15 Jan 2024 16:36:20 -0600 Subject: [PATCH 04/19] title screen update 1 --- Assets/Scenes/TitleScreen.unity | 38 +++++++++---------- .../Unicorn Fold - Display SDF.asset | 10 ++--- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Assets/Scenes/TitleScreen.unity b/Assets/Scenes/TitleScreen.unity index bf9cd0d..a2b4d54 100644 --- a/Assets/Scenes/TitleScreen.unity +++ b/Assets/Scenes/TitleScreen.unity @@ -274,17 +274,17 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: Story Mode + m_text: STORY MODE m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} - m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontAsset: {fileID: 11400000, guid: ab9839b62254e44d28f162b0bf1c05b5, type: 2} + m_sharedMaterial: {fileID: -8391673362897697182, guid: ab9839b62254e44d28f162b0bf1c05b5, type: 2} m_fontSharedMaterials: [] m_fontMaterial: {fileID: 0} m_fontMaterials: [] m_fontColor32: serializedVersion: 2 - rgba: 4281479730 - m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + rgba: 4279834952 + m_fontColor: {r: 0.2830189, g: 0.097454615, b: 0.097454615, a: 1} m_enableVertexGradient: 0 m_colorMode: 3 m_fontColorGradient: @@ -309,7 +309,7 @@ MonoBehaviour: m_fontSizeMax: 72 m_fontStyle: 0 m_HorizontalAlignment: 2 - m_VerticalAlignment: 512 + m_VerticalAlignment: 1024 m_textAlignment: 65535 m_characterSpacing: 0 m_wordSpacing: 0 @@ -597,7 +597,7 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 945921320} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 334.70187, z: 0} + m_LocalPosition: {x: 0, y: 344, z: 0} m_LocalScale: {x: 1080, y: 216, z: 10.8} m_ConstrainProportionsScale: 0 m_Children: @@ -925,7 +925,7 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: 0} + m_AnchoredPosition: {x: 0.004, y: -0.11} m_SizeDelta: {x: 1030.8848, y: 338.31967} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &1183132290 @@ -948,17 +948,17 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: Entrenched + m_text: ENTRENCHED m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} - m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontAsset: {fileID: 11400000, guid: ab9839b62254e44d28f162b0bf1c05b5, type: 2} + m_sharedMaterial: {fileID: -8391673362897697182, guid: ab9839b62254e44d28f162b0bf1c05b5, type: 2} m_fontSharedMaterials: [] m_fontMaterial: {fileID: 0} m_fontMaterials: [] m_fontColor32: serializedVersion: 2 - rgba: 4278190080 - m_fontColor: {r: 0, g: 0, b: 0, a: 1} + rgba: 4279834952 + m_fontColor: {r: 0.2830189, g: 0.097454615, b: 0.097454615, a: 1} m_enableVertexGradient: 0 m_colorMode: 3 m_fontColorGradient: @@ -1354,17 +1354,17 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: Endless Mode + m_text: ENDLESS MODE m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} - m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontAsset: {fileID: 11400000, guid: ab9839b62254e44d28f162b0bf1c05b5, type: 2} + m_sharedMaterial: {fileID: -8391673362897697182, guid: ab9839b62254e44d28f162b0bf1c05b5, type: 2} m_fontSharedMaterials: [] m_fontMaterial: {fileID: 0} m_fontMaterials: [] m_fontColor32: serializedVersion: 2 - rgba: 4281479730 - m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + rgba: 4279834952 + m_fontColor: {r: 0.2830189, g: 0.097454615, b: 0.097454615, a: 1} m_enableVertexGradient: 0 m_colorMode: 3 m_fontColorGradient: @@ -1389,7 +1389,7 @@ MonoBehaviour: m_fontSizeMax: 72 m_fontStyle: 0 m_HorizontalAlignment: 2 - m_VerticalAlignment: 512 + m_VerticalAlignment: 1024 m_textAlignment: 65535 m_characterSpacing: 0 m_wordSpacing: 0 diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials/Unicorn Fold - Display SDF.asset b/Assets/TextMesh Pro/Resources/Fonts & Materials/Unicorn Fold - Display SDF.asset index 25563b3..bd72854 100644 --- a/Assets/TextMesh Pro/Resources/Fonts & Materials/Unicorn Fold - Display SDF.asset +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/Unicorn Fold - Display SDF.asset @@ -73,9 +73,9 @@ Material: - _OutlineWidth: 0 - _PerspectiveFilter: 0.875 - _Reflectivity: 10 - - _ScaleRatioA: 1 - - _ScaleRatioB: 1 - - _ScaleRatioC: 1 + - _ScaleRatioA: 0.8333333 + - _ScaleRatioB: 0.6770833 + - _ScaleRatioC: 0.6770833 - _ScaleX: 1 - _ScaleY: 1 - _ShaderFlags: 0 @@ -120,9 +120,9 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 71c1514a6bd24e1e882cebbe1904ce04, type: 3} m_Name: Unicorn Fold - Display SDF m_EditorClassIdentifier: - hashCode: 0 + hashCode: 711393253 material: {fileID: -8391673362897697182} - materialHashCode: 0 + materialHashCode: 1650280741 m_Version: 1.1.0 m_SourceFontFileGUID: b3719c21c97934973897cf36693afbcf m_SourceFontFile_EditorRef: {fileID: 12800000, guid: b3719c21c97934973897cf36693afbcf, type: 3} From 3388ee9d263061eeedfdebc9f05bba9fd1f2f0f3 Mon Sep 17 00:00:00 2001 From: Alec Bargher Date: Mon, 15 Jan 2024 16:39:18 -0600 Subject: [PATCH 05/19] alec: updated ordering --- Assets/Prefabs/ArrowDownDDR.prefab | 2 +- Assets/Prefabs/ArrowLeftDDR.prefab | 2 +- Assets/Prefabs/ArrowRightDDR.prefab | 2 +- Assets/Prefabs/ArrowUpDDR.prefab | 2 +- Assets/Prefabs/Box.prefab | 2 +- Assets/Prefabs/DDR.prefab | 6 +++--- Assets/Prefabs/NoseGoes.prefab | 2 +- Assets/Prefabs/Passerby.prefab | 2 +- Assets/Prefabs/Reaction.prefab | 2 +- Assets/Prefabs/Restabilize.prefab | 8 ++++---- ProjectSettings/TagManager.asset | 3 +++ 11 files changed, 18 insertions(+), 15 deletions(-) diff --git a/Assets/Prefabs/ArrowDownDDR.prefab b/Assets/Prefabs/ArrowDownDDR.prefab index 7e29ca1..ecb24d8 100644 --- a/Assets/Prefabs/ArrowDownDDR.prefab +++ b/Assets/Prefabs/ArrowDownDDR.prefab @@ -73,7 +73,7 @@ SpriteRenderer: m_LightmapParameters: {fileID: 0} m_SortingLayerID: 0 m_SortingLayer: 0 - m_SortingOrder: 0 + m_SortingOrder: 40 m_Sprite: {fileID: 21300000, guid: a7c8a1674e65c4d0cbb635de89565beb, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 diff --git a/Assets/Prefabs/ArrowLeftDDR.prefab b/Assets/Prefabs/ArrowLeftDDR.prefab index d9b676b..550ded5 100644 --- a/Assets/Prefabs/ArrowLeftDDR.prefab +++ b/Assets/Prefabs/ArrowLeftDDR.prefab @@ -73,7 +73,7 @@ SpriteRenderer: m_LightmapParameters: {fileID: 0} m_SortingLayerID: 0 m_SortingLayer: 0 - m_SortingOrder: 0 + m_SortingOrder: 40 m_Sprite: {fileID: 21300000, guid: 38724783ceb3246cdbba33673d7af8c3, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 diff --git a/Assets/Prefabs/ArrowRightDDR.prefab b/Assets/Prefabs/ArrowRightDDR.prefab index 6f03e91..c74b0fc 100644 --- a/Assets/Prefabs/ArrowRightDDR.prefab +++ b/Assets/Prefabs/ArrowRightDDR.prefab @@ -73,7 +73,7 @@ SpriteRenderer: m_LightmapParameters: {fileID: 0} m_SortingLayerID: 0 m_SortingLayer: 0 - m_SortingOrder: 0 + m_SortingOrder: 40 m_Sprite: {fileID: 21300000, guid: 1026ccf96dc6c408a99071b5ab420e37, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 diff --git a/Assets/Prefabs/ArrowUpDDR.prefab b/Assets/Prefabs/ArrowUpDDR.prefab index 936e669..f69d18e 100644 --- a/Assets/Prefabs/ArrowUpDDR.prefab +++ b/Assets/Prefabs/ArrowUpDDR.prefab @@ -73,7 +73,7 @@ SpriteRenderer: m_LightmapParameters: {fileID: 0} m_SortingLayerID: 0 m_SortingLayer: 0 - m_SortingOrder: 0 + m_SortingOrder: 40 m_Sprite: {fileID: 21300000, guid: cac35ee0288bf42c9a44b25d65b35985, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 diff --git a/Assets/Prefabs/Box.prefab b/Assets/Prefabs/Box.prefab index 72e7c7c..83fa376 100644 --- a/Assets/Prefabs/Box.prefab +++ b/Assets/Prefabs/Box.prefab @@ -74,7 +74,7 @@ SpriteRenderer: m_LightmapParameters: {fileID: 0} m_SortingLayerID: 0 m_SortingLayer: 0 - m_SortingOrder: 0 + m_SortingOrder: 40 m_Sprite: {fileID: 21300000, guid: 7ec814963bdf147fca4b29fd667d4493, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 diff --git a/Assets/Prefabs/DDR.prefab b/Assets/Prefabs/DDR.prefab index f07a0b1..4399447 100644 --- a/Assets/Prefabs/DDR.prefab +++ b/Assets/Prefabs/DDR.prefab @@ -240,7 +240,7 @@ SpriteRenderer: m_LightmapParameters: {fileID: 0} m_SortingLayerID: 0 m_SortingLayer: 0 - m_SortingOrder: 0 + m_SortingOrder: 10 m_Sprite: {fileID: 7482667652216324306, guid: 311925a002f4447b3a28927169b83ea6, type: 3} m_Color: {r: 1, g: 0, b: 0, a: 0} m_FlipX: 0 @@ -370,7 +370,7 @@ SpriteRenderer: m_LightmapParameters: {fileID: 0} m_SortingLayerID: 0 m_SortingLayer: 0 - m_SortingOrder: 0 + m_SortingOrder: 4 m_Sprite: {fileID: 7482667652216324306, guid: 311925a002f4447b3a28927169b83ea6, type: 3} m_Color: {r: 0.6886792, g: 0.6886792, b: 0.6886792, a: 1} m_FlipX: 0 @@ -500,7 +500,7 @@ SpriteRenderer: m_LightmapParameters: {fileID: 0} m_SortingLayerID: 0 m_SortingLayer: 0 - m_SortingOrder: 0 + m_SortingOrder: 10 m_Sprite: {fileID: 7482667652216324306, guid: 311925a002f4447b3a28927169b83ea6, type: 3} m_Color: {r: 0.4245283, g: 0.4245283, b: 0.4245283, a: 1} m_FlipX: 0 diff --git a/Assets/Prefabs/NoseGoes.prefab b/Assets/Prefabs/NoseGoes.prefab index cda7121..8d21317 100644 --- a/Assets/Prefabs/NoseGoes.prefab +++ b/Assets/Prefabs/NoseGoes.prefab @@ -72,7 +72,7 @@ SpriteRenderer: m_LightmapParameters: {fileID: 0} m_SortingLayerID: 0 m_SortingLayer: 0 - m_SortingOrder: 0 + m_SortingOrder: 40 m_Sprite: {fileID: 21300000, guid: 472c6eb1a61f44f45b6fc25e8b11f2a7, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 diff --git a/Assets/Prefabs/Passerby.prefab b/Assets/Prefabs/Passerby.prefab index 8aa1d09..e1b2959 100644 --- a/Assets/Prefabs/Passerby.prefab +++ b/Assets/Prefabs/Passerby.prefab @@ -27,7 +27,7 @@ Transform: m_GameObject: {fileID: 5218877918674348293} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 110, y: -20, z: -1.5} - m_LocalScale: {x: 5.5, y: 5.5, z: 0.6772} + m_LocalScale: {x: 5.5, y: 5.5, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} diff --git a/Assets/Prefabs/Reaction.prefab b/Assets/Prefabs/Reaction.prefab index 54512bd..4286c4c 100644 --- a/Assets/Prefabs/Reaction.prefab +++ b/Assets/Prefabs/Reaction.prefab @@ -220,7 +220,7 @@ SpriteRenderer: m_LightmapParameters: {fileID: 0} m_SortingLayerID: 0 m_SortingLayer: 0 - m_SortingOrder: 0 + m_SortingOrder: 4 m_Sprite: {fileID: 7482667652216324306, guid: 311925a002f4447b3a28927169b83ea6, type: 3} m_Color: {r: 0.6886792, g: 0.6886792, b: 0.6886792, a: 1} m_FlipX: 0 diff --git a/Assets/Prefabs/Restabilize.prefab b/Assets/Prefabs/Restabilize.prefab index 5f8b269..2a0be76 100644 --- a/Assets/Prefabs/Restabilize.prefab +++ b/Assets/Prefabs/Restabilize.prefab @@ -238,7 +238,7 @@ SpriteRenderer: m_LightmapParameters: {fileID: 0} m_SortingLayerID: 0 m_SortingLayer: 0 - m_SortingOrder: 0 + m_SortingOrder: 10 m_Sprite: {fileID: 7482667652216324306, guid: 311925a002f4447b3a28927169b83ea6, type: 3} m_Color: {r: 0.59607846, g: 0.59607846, b: 0.59607846, a: 1} m_FlipX: 0 @@ -368,7 +368,7 @@ SpriteRenderer: m_LightmapParameters: {fileID: 0} m_SortingLayerID: 0 m_SortingLayer: 0 - m_SortingOrder: 0 + m_SortingOrder: 10 m_Sprite: {fileID: 7482667652216324306, guid: 311925a002f4447b3a28927169b83ea6, type: 3} m_Color: {r: 0.6886792, g: 0.6886792, b: 0.6886792, a: 1} m_FlipX: 0 @@ -498,7 +498,7 @@ SpriteRenderer: m_LightmapParameters: {fileID: 0} m_SortingLayerID: 0 m_SortingLayer: 0 - m_SortingOrder: 0 + m_SortingOrder: 10 m_Sprite: {fileID: 7482667652216324306, guid: 311925a002f4447b3a28927169b83ea6, type: 3} m_Color: {r: 0.59607846, g: 0.59607846, b: 0.59607846, a: 1} m_FlipX: 0 @@ -628,7 +628,7 @@ SpriteRenderer: m_LightmapParameters: {fileID: 0} m_SortingLayerID: 0 m_SortingLayer: 0 - m_SortingOrder: 0 + m_SortingOrder: 10 m_Sprite: {fileID: 7482667652216324306, guid: 311925a002f4447b3a28927169b83ea6, type: 3} m_Color: {r: 0.59607846, g: 0.59607846, b: 0.59607846, a: 1} m_FlipX: 0 diff --git a/ProjectSettings/TagManager.asset b/ProjectSettings/TagManager.asset index aed7f5b..5a95a54 100644 --- a/ProjectSettings/TagManager.asset +++ b/ProjectSettings/TagManager.asset @@ -38,6 +38,9 @@ TagManager: - - m_SortingLayers: + - name: GameOverlay + uniqueID: 811454683 + locked: 0 - name: Default uniqueID: 0 locked: 0 From 28cbfed3e6db5c1ff3d3ea4c7cea08fdcd59760c Mon Sep 17 00:00:00 2001 From: Alec Bargher Date: Mon, 15 Jan 2024 16:43:27 -0600 Subject: [PATCH 06/19] alec: fixing on fix --- Assets/Prefabs/NoseGoes.prefab | 2 +- Assets/Scenes/MainGame.unity | 10 +++++----- Assets/Scenes/TitleScreen.unity | 12 ++++++------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Assets/Prefabs/NoseGoes.prefab b/Assets/Prefabs/NoseGoes.prefab index cda7121..dbcbf9c 100644 --- a/Assets/Prefabs/NoseGoes.prefab +++ b/Assets/Prefabs/NoseGoes.prefab @@ -78,7 +78,7 @@ SpriteRenderer: m_FlipX: 0 m_FlipY: 0 m_DrawMode: 0 - m_Size: {x: 1, y: 1} + m_Size: {x: 2, y: 2} m_AdaptiveModeThreshold: 0.5 m_SpriteTileMode: 0 m_WasSpriteAssigned: 1 diff --git a/Assets/Scenes/MainGame.unity b/Assets/Scenes/MainGame.unity index 06fec1f..fa2be97 100644 --- a/Assets/Scenes/MainGame.unity +++ b/Assets/Scenes/MainGame.unity @@ -414,8 +414,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: 0.25} - m_SizeDelta: {x: 0, y: 0.5} + m_AnchoredPosition: {x: -0.09600067, y: 0.39899993} + m_SizeDelta: {x: -0.1930008, y: 0.7979002} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &422719939 MonoBehaviour: @@ -823,7 +823,7 @@ SpriteRenderer: m_Size: {x: 15.6, y: 10.8} m_AdaptiveModeThreshold: 0.5 m_SpriteTileMode: 0 - m_WasSpriteAssigned: 0 + m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 --- !u!4 &771962607 @@ -1602,8 +1602,8 @@ MonoBehaviour: 0000 meters' m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: 33ad01eb91b6a42b4bc7e0ec655568bb, type: 2} - m_sharedMaterial: {fileID: 5430614902480215695, guid: 33ad01eb91b6a42b4bc7e0ec655568bb, type: 2} + m_fontAsset: {fileID: 11400000, guid: 457290c6967df4058b0816dfa0a9c07a, type: 2} + m_sharedMaterial: {fileID: 5430614902480215695, guid: 457290c6967df4058b0816dfa0a9c07a, type: 2} m_fontSharedMaterials: [] m_fontMaterial: {fileID: 0} m_fontMaterials: [] diff --git a/Assets/Scenes/TitleScreen.unity b/Assets/Scenes/TitleScreen.unity index a2b4d54..7253511 100644 --- a/Assets/Scenes/TitleScreen.unity +++ b/Assets/Scenes/TitleScreen.unity @@ -276,8 +276,8 @@ MonoBehaviour: m_Calls: [] m_text: STORY MODE m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: ab9839b62254e44d28f162b0bf1c05b5, type: 2} - m_sharedMaterial: {fileID: -8391673362897697182, guid: ab9839b62254e44d28f162b0bf1c05b5, type: 2} + m_fontAsset: {fileID: 11400000, guid: f4ed1b3c9f33b431b9598dea573e1e24, type: 2} + m_sharedMaterial: {fileID: -8391673362897697182, guid: f4ed1b3c9f33b431b9598dea573e1e24, type: 2} m_fontSharedMaterials: [] m_fontMaterial: {fileID: 0} m_fontMaterials: [] @@ -950,8 +950,8 @@ MonoBehaviour: m_Calls: [] m_text: ENTRENCHED m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: ab9839b62254e44d28f162b0bf1c05b5, type: 2} - m_sharedMaterial: {fileID: -8391673362897697182, guid: ab9839b62254e44d28f162b0bf1c05b5, type: 2} + m_fontAsset: {fileID: 11400000, guid: f4ed1b3c9f33b431b9598dea573e1e24, type: 2} + m_sharedMaterial: {fileID: -8391673362897697182, guid: f4ed1b3c9f33b431b9598dea573e1e24, type: 2} m_fontSharedMaterials: [] m_fontMaterial: {fileID: 0} m_fontMaterials: [] @@ -1356,8 +1356,8 @@ MonoBehaviour: m_Calls: [] m_text: ENDLESS MODE m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: ab9839b62254e44d28f162b0bf1c05b5, type: 2} - m_sharedMaterial: {fileID: -8391673362897697182, guid: ab9839b62254e44d28f162b0bf1c05b5, type: 2} + m_fontAsset: {fileID: 11400000, guid: f4ed1b3c9f33b431b9598dea573e1e24, type: 2} + m_sharedMaterial: {fileID: -8391673362897697182, guid: f4ed1b3c9f33b431b9598dea573e1e24, type: 2} m_fontSharedMaterials: [] m_fontMaterial: {fileID: 0} m_fontMaterials: [] From b93449e9698d88bc6de4e7162932ae619ed0a9d0 Mon Sep 17 00:00:00 2001 From: Alec Bargher Date: Mon, 15 Jan 2024 16:48:38 -0600 Subject: [PATCH 07/19] alec: updated score display script --- Assets/Scripts/ScoreDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/Scripts/ScoreDisplay.cs b/Assets/Scripts/ScoreDisplay.cs index e58b905..9ffdb90 100644 --- a/Assets/Scripts/ScoreDisplay.cs +++ b/Assets/Scripts/ScoreDisplay.cs @@ -16,7 +16,7 @@ void Start() // Update is called once per frame void Update() { - string msg = "Distance: " + ((int)GM.distance).ToString("D4") + " meters"; + string msg = "SCORE\n" + ((int)GM.distance).ToString("D4") + " meters"; textMeshPro.text = msg; // textMeshPro.text = GM.distance.ToString(); From 48ececb416cfd72c22668567ead3b55311a072c5 Mon Sep 17 00:00:00 2001 From: Alec Bargher Date: Mon, 15 Jan 2024 16:59:35 -0600 Subject: [PATCH 08/19] alec: suspicion display --- Assets/Prefabs/SuspicionDisplay.prefab | 306 +++++++++++++++++++++++++ Assets/Scenes/MainGame.unity | 101 +++++--- Assets/Scripts/SuspicionDisplay.cs | 37 +++ 3 files changed, 415 insertions(+), 29 deletions(-) create mode 100644 Assets/Prefabs/SuspicionDisplay.prefab create mode 100644 Assets/Scripts/SuspicionDisplay.cs diff --git a/Assets/Prefabs/SuspicionDisplay.prefab b/Assets/Prefabs/SuspicionDisplay.prefab new file mode 100644 index 0000000..1f35f42 --- /dev/null +++ b/Assets/Prefabs/SuspicionDisplay.prefab @@ -0,0 +1,306 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &5545561582669020061 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1778751237143144694} + - component: {fileID: 1401832155063273930} + m_Layer: 0 + m_Name: X0 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1778751237143144694 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5545561582669020061} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -3, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 2510839935639341050} + m_RootOrder: -1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &1401832155063273930 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5545561582669020061} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_Sprite: {fileID: 21300000, guid: eec99f7d9906940478029d786842ae6d, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 2, y: 2} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 +--- !u!1 &5564701349567195144 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7761281448259568609} + - component: {fileID: 3368348124751408562} + m_Layer: 0 + m_Name: X1 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &7761281448259568609 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5564701349567195144} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 2510839935639341050} + m_RootOrder: -1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &3368348124751408562 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5564701349567195144} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_Sprite: {fileID: 21300000, guid: eec99f7d9906940478029d786842ae6d, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 2, y: 2} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 +--- !u!1 &6158635692141977267 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2510839935639341050} + - component: {fileID: 4752253549048502595} + m_Layer: 0 + m_Name: SuspicionDisplay + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2510839935639341050 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6158635692141977267} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1778751237143144694} + - {fileID: 7761281448259568609} + - {fileID: 7175579540028949779} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &4752253549048502595 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6158635692141977267} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 19c1fb6ed15814ab9b7855f61e34e10c, type: 3} + m_Name: + m_EditorClassIdentifier: + spriteRenderer0: {fileID: 1401832155063273930} + spriteRenderer1: {fileID: 3368348124751408562} + spriteRenderer2: {fileID: 6994831585121176476} + unfilled: {fileID: 21300000, guid: eec99f7d9906940478029d786842ae6d, type: 3} + filled: {fileID: 21300000, guid: deef9e3207bbd488bbec282f6bfd88c9, type: 3} +--- !u!1 &8786400383916557390 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7175579540028949779} + - component: {fileID: 6994831585121176476} + m_Layer: 0 + m_Name: X2 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &7175579540028949779 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8786400383916557390} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 3, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 2510839935639341050} + m_RootOrder: -1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &6994831585121176476 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8786400383916557390} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_Sprite: {fileID: 21300000, guid: eec99f7d9906940478029d786842ae6d, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 2, y: 2} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 diff --git a/Assets/Scenes/MainGame.unity b/Assets/Scenes/MainGame.unity index fa2be97..8104719 100644 --- a/Assets/Scenes/MainGame.unity +++ b/Assets/Scenes/MainGame.unity @@ -1780,37 +1780,11 @@ Canvas: m_SortingLayerID: 0 m_SortingOrder: 0 m_TargetDisplay: 0 ---- !u!1 &2011311694 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2011311695} - m_Layer: 0 - m_Name: SuspicionDisplay - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &2011311695 +--- !u!4 &2011311695 stripped Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} + m_CorrespondingSourceObject: {fileID: 2510839935639341050, guid: b1a22c27c086f482682a6be61d67659e, type: 3} + m_PrefabInstance: {fileID: 450778178251381823} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2011311694} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 888627985} - m_RootOrder: -1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &2082967018 GameObject: m_ObjectHideFlags: 0 @@ -2008,3 +1982,72 @@ MonoBehaviour: m_OnValueChanged: m_PersistentCalls: m_Calls: [] +--- !u!1001 &450778178251381823 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 888627985} + m_Modifications: + - target: {fileID: 2510839935639341050, guid: b1a22c27c086f482682a6be61d67659e, type: 3} + propertyPath: m_RootOrder + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 2510839935639341050, guid: b1a22c27c086f482682a6be61d67659e, type: 3} + propertyPath: m_LocalScale.x + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 2510839935639341050, guid: b1a22c27c086f482682a6be61d67659e, type: 3} + propertyPath: m_LocalScale.y + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 2510839935639341050, guid: b1a22c27c086f482682a6be61d67659e, type: 3} + propertyPath: m_LocalPosition.x + value: 25 + objectReference: {fileID: 0} + - target: {fileID: 2510839935639341050, guid: b1a22c27c086f482682a6be61d67659e, type: 3} + propertyPath: m_LocalPosition.y + value: 17 + objectReference: {fileID: 0} + - target: {fileID: 2510839935639341050, guid: b1a22c27c086f482682a6be61d67659e, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2510839935639341050, guid: b1a22c27c086f482682a6be61d67659e, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2510839935639341050, guid: b1a22c27c086f482682a6be61d67659e, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2510839935639341050, guid: b1a22c27c086f482682a6be61d67659e, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2510839935639341050, guid: b1a22c27c086f482682a6be61d67659e, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2510839935639341050, guid: b1a22c27c086f482682a6be61d67659e, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2510839935639341050, guid: b1a22c27c086f482682a6be61d67659e, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2510839935639341050, guid: b1a22c27c086f482682a6be61d67659e, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6158635692141977267, guid: b1a22c27c086f482682a6be61d67659e, type: 3} + propertyPath: m_Name + value: SuspicionDisplay + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: b1a22c27c086f482682a6be61d67659e, type: 3} diff --git a/Assets/Scripts/SuspicionDisplay.cs b/Assets/Scripts/SuspicionDisplay.cs new file mode 100644 index 0000000..7c8809f --- /dev/null +++ b/Assets/Scripts/SuspicionDisplay.cs @@ -0,0 +1,37 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class SuspicionDisplay : MonoBehaviour +{ + private GameManager GM; + public SpriteRenderer spriteRenderer0; + public SpriteRenderer spriteRenderer1; + public SpriteRenderer spriteRenderer2; + public Sprite unfilled; + public Sprite filled; + + // Start is called before the first frame update + void Start() + { + GM = GameManager.instance; + spriteRenderer0.sprite = unfilled; + spriteRenderer1.sprite = unfilled; + spriteRenderer2.sprite = unfilled; + } + + // Update is called once per frame + void Update() + { + if (GM.numStrikes >= 0) { + spriteRenderer0.sprite = filled; + } + if (GM.numStrikes >= 1) { + spriteRenderer1.sprite = filled; + } + if (GM.numStrikes >= 2) { + spriteRenderer2.sprite = filled; + } + + } +} From 9d48d90f53595c340c8a62791bde4d8cf0a28c73 Mon Sep 17 00:00:00 2001 From: Alec Bargher Date: Mon, 15 Jan 2024 17:10:33 -0600 Subject: [PATCH 09/19] alec: working --- Assets/Scenes/MainGame.unity | 101 +++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/Assets/Scenes/MainGame.unity b/Assets/Scenes/MainGame.unity index 8104719..5fb4601 100644 --- a/Assets/Scenes/MainGame.unity +++ b/Assets/Scenes/MainGame.unity @@ -1493,6 +1493,107 @@ Transform: m_Father: {fileID: 519420032} m_RootOrder: -1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1001 &1507187762 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 4377794324176431307, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_Name + value: DialogueStuff + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_Pivot.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_Pivot.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_RootOrder + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_SizeDelta.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} --- !u!1 &1663833397 GameObject: m_ObjectHideFlags: 0 From 099ed7f39e74db86421cfff92252f6815ec5cbe3 Mon Sep 17 00:00:00 2001 From: Alec Bargher Date: Mon, 15 Jan 2024 17:16:13 -0600 Subject: [PATCH 10/19] adding dialogue stuff --- Assets/Ink/CHANGELOG.md | 108 + Assets/Ink/Demos/Basic Demo/Basic Demo.unity | 728 ++++ Assets/Ink/Demos/Basic Demo/Ink/story.ink | 19 + Assets/Ink/Demos/Basic Demo/Ink/story.json | 1 + .../Demos/Basic Demo/Prefabs/Button.prefab | 265 ++ .../Ink/Demos/Basic Demo/Prefabs/Text.prefab | 118 + .../Basic Demo/Scripts/BasicInkExample.cs | 110 + .../Scripts/Editor/BasicInkExampleEditor.cs | 26 + .../Basic Demo/Scripts/QuitGameOnKeypress.cs | 10 + .../Ink/Documentation/API Documentation.pdf | Bin 0 -> 84720 bytes .../Ink for Unity Package Documentation.pdf | Bin 0 -> 41949 bytes .../Auto Compiler/InkPostProcessor.cs | 212 ++ .../Ink/Editor/Core/Compiler/InkCompiler.cs | 822 +++++ .../Core/Compiler/UnityInkFileHandler.cs | 23 + .../Editor/Core/Ink Library/InkCompilerLog.cs | 64 + Assets/Ink/Editor/Core/Ink Library/InkFile.cs | 333 ++ .../Ink/Editor/Core/Ink Library/InkLibrary.cs | 552 +++ .../Editor/Core/Ink Settings/InkSettings.cs | 144 + .../Core/Ink Settings/InkSettingsEditor.cs | 151 + Assets/Ink/Editor/Core/InkEditorUtils.cs | 372 ++ Assets/Ink/Editor/InkEditor.asmdef | 16 + .../InkPreBuildValidationCheck.cs | 62 + .../Tools/File Icons/InkBrowserIcons.cs | 189 + .../Resources/InkChildIcon-Large.psd | Bin 0 -> 29759 bytes .../File Icons/Resources/InkChildIcon.psd | Bin 0 -> 24016 bytes .../Resources/InkCompileManualIcon.psd | Bin 0 -> 95600 bytes .../Resources/InkDefaultTemplate.txt | 3 + .../File Icons/Resources/InkErrorIcon.psd | Bin 0 -> 81094 bytes .../Resources/InkFileIcon-Large.psd | Bin 0 -> 884643 bytes .../Resources/InkFileIcon-retina.psd | Bin 0 -> 29421 bytes .../File Icons/Resources/InkFileIcon.psd | Bin 0 -> 83098 bytes .../File Icons/Resources/InkTodoIcon.psd | Bin 0 -> 76048 bytes .../Resources/InkUnknownFileIcon.psd | Bin 0 -> 24714 bytes .../File Icons/Resources/InkWarningIcon.psd | Bin 0 -> 66606 bytes .../Tools/Ink Inspector/DefaultAssetEditor.cs | 60 + .../Ink Inspector/DefaultAssetInspector.cs | 19 + .../Tools/Ink Inspector/InkInspector.cs | 462 +++ .../Player Window/InkHistoryContentItem.cs | 93 + .../Tools/Player Window/InkPlayerWindow.cs | 3058 +++++++++++++++++ .../InkUnityIntegrationStartupWindow.cs | 111 + Assets/Ink/Extras/Sublime3Syntax.zip | Bin 0 -> 11784 bytes Assets/Ink/InkLibs/Ink-Libraries.asmdef | 6 + .../Ink/InkLibs/InkCompiler/CharacterRange.cs | 54 + .../Ink/InkLibs/InkCompiler/CharacterSet.cs | 53 + .../InkLibs/InkCompiler/CommandLineInput.cs | 12 + Assets/Ink/InkLibs/InkCompiler/Compiler.cs | 212 ++ Assets/Ink/InkLibs/InkCompiler/FileHandler.cs | 24 + .../InkParser/CommentEliminator.cs | 93 + .../InkCompiler/InkParser/InkParser.cs | 182 + .../InkParser/InkParser_AuthorWarning.cs | 28 + .../InkParser/InkParser_CharacterRanges.cs | 64 + .../InkParser/InkParser_Choices.cs | 228 ++ .../InkParser/InkParser_CommandLineInput.cs | 129 + .../InkParser/InkParser_Conditional.cs | 288 ++ .../InkParser/InkParser_Content.cs | 210 ++ .../InkCompiler/InkParser/InkParser_Divert.cs | 208 ++ .../InkParser/InkParser_Expressions.cs | 512 +++ .../InkParser/InkParser_Include.cs | 76 + .../InkCompiler/InkParser/InkParser_Knot.cs | 239 ++ .../InkCompiler/InkParser/InkParser_Logic.cs | 442 +++ .../InkParser/InkParser_Sequences.cs | 231 ++ .../InkParser/InkParser_Statements.cs | 163 + .../InkCompiler/InkParser/InkParser_Tags.cs | 63 + .../InkParser/InkParser_Whitespace.cs | 112 + .../InkStringConversionExtensions.cs | 18 + .../ParsedHierarchy/AuthorWarning.cs | 20 + .../InkCompiler/ParsedHierarchy/Choice.cs | 290 ++ .../ParsedHierarchy/Conditional.cs | 71 + .../ConditionalSingleBranch.cs | 158 + .../ParsedHierarchy/ConstantDeclaration.cs | 46 + .../ParsedHierarchy/ContentList.cs | 78 + .../InkCompiler/ParsedHierarchy/Divert.cs | 403 +++ .../ParsedHierarchy/DivertTarget.cs | 172 + .../InkCompiler/ParsedHierarchy/Expression.cs | 307 ++ .../ParsedHierarchy/ExternalDeclaration.cs | 30 + .../InkCompiler/ParsedHierarchy/FlowBase.cs | 439 +++ .../InkCompiler/ParsedHierarchy/FlowLevel.cs | 11 + .../ParsedHierarchy/FunctionCall.cs | 242 ++ .../InkCompiler/ParsedHierarchy/Gather.cs | 51 + .../ParsedHierarchy/INamedContent.cs | 9 + .../ParsedHierarchy/IWeavePoint.cs | 15 + .../InkCompiler/ParsedHierarchy/Identifier.cs | 13 + .../ParsedHierarchy/IncludedFile.cs | 20 + .../InkCompiler/ParsedHierarchy/Knot.cs | 35 + .../InkCompiler/ParsedHierarchy/List.cs | 53 + .../ParsedHierarchy/ListDefinition.cs | 139 + .../InkCompiler/ParsedHierarchy/Number.cs | 53 + .../InkCompiler/ParsedHierarchy/Object.cs | 363 ++ .../InkCompiler/ParsedHierarchy/Path.cs | 192 ++ .../InkCompiler/ParsedHierarchy/Return.cs | 39 + .../InkCompiler/ParsedHierarchy/Sequence.cs | 206 ++ .../InkCompiler/ParsedHierarchy/Stitch.cs | 14 + .../InkCompiler/ParsedHierarchy/Story.cs | 508 +++ .../ParsedHierarchy/StringExpression.cs | 70 + .../InkCompiler/ParsedHierarchy/Tag.cs | 27 + .../InkCompiler/ParsedHierarchy/Text.cs | 24 + .../ParsedHierarchy/TunnelOnwards.cs | 92 + .../ParsedHierarchy/VariableAssignment.cs | 123 + .../ParsedHierarchy/VariableReference.cs | 152 + .../InkCompiler/ParsedHierarchy/Weave.cs | 730 ++++ .../InkCompiler/ParsedHierarchy/Wrap.cs | 28 + .../Ink/InkLibs/InkCompiler/Plugins/Plugin.cs | 21 + .../InkCompiler/Plugins/PluginManager.cs | 68 + Assets/Ink/InkLibs/InkCompiler/Stats.cs | 68 + .../InkCompiler/StringParser/StringParser.cs | 685 ++++ .../StringParser/StringParserState.cs | 171 + Assets/Ink/InkLibs/InkRuntime/CallStack.cs | 443 +++ Assets/Ink/InkLibs/InkRuntime/Choice.cs | 56 + Assets/Ink/InkLibs/InkRuntime/ChoicePoint.cs | 89 + Assets/Ink/InkLibs/InkRuntime/Container.cs | 366 ++ .../Ink/InkLibs/InkRuntime/ControlCommand.cs | 182 + .../Ink/InkLibs/InkRuntime/DebugMetadata.cs | 76 + Assets/Ink/InkLibs/InkRuntime/Divert.cs | 149 + Assets/Ink/InkLibs/InkRuntime/Error.cs | 24 + Assets/Ink/InkLibs/InkRuntime/Flow.cs | 93 + Assets/Ink/InkLibs/InkRuntime/Glue.cs | 13 + .../Ink/InkLibs/InkRuntime/INamedContent.cs | 10 + Assets/Ink/InkLibs/InkRuntime/InkList.cs | 614 ++++ .../InkLibs/InkRuntime/JsonSerialisation.cs | 722 ++++ .../Ink/InkLibs/InkRuntime/ListDefinition.cs | 75 + .../InkRuntime/ListDefinitionsOrigin.cs | 53 + .../InkLibs/InkRuntime/NativeFunctionCall.cs | 508 +++ Assets/Ink/InkLibs/InkRuntime/Object.cs | 250 ++ Assets/Ink/InkLibs/InkRuntime/Path.cs | 277 ++ Assets/Ink/InkLibs/InkRuntime/Pointer.cs | 70 + Assets/Ink/InkLibs/InkRuntime/Profiler.cs | 394 +++ Assets/Ink/InkLibs/InkRuntime/PushPop.cs | 13 + Assets/Ink/InkLibs/InkRuntime/SearchResult.cs | 18 + Assets/Ink/InkLibs/InkRuntime/SimpleJson.cs | 647 ++++ Assets/Ink/InkLibs/InkRuntime/StatePatch.cs | 66 + Assets/Ink/InkLibs/InkRuntime/Story.cs | 2918 ++++++++++++++++ .../Ink/InkLibs/InkRuntime/StoryException.cs | 24 + Assets/Ink/InkLibs/InkRuntime/StoryState.cs | 1341 ++++++++ .../InkLibs/InkRuntime/StringJoinExtension.cs | 28 + Assets/Ink/InkLibs/InkRuntime/Tag.cs | 27 + Assets/Ink/InkLibs/InkRuntime/Value.cs | 405 +++ .../InkLibs/InkRuntime/VariableAssignment.cs | 27 + .../InkLibs/InkRuntime/VariableReference.cs | 51 + .../Ink/InkLibs/InkRuntime/VariablesState.cs | 417 +++ Assets/Ink/InkLibs/InkRuntime/Void.cs | 10 + Assets/Ink/LICENCE.md | 12 + Assets/Ink/README.md | 164 + Assets/Prefabs/DialogueManager.prefab | 51 + Assets/Prefabs/DialogueStuff.prefab | 532 +++ Assets/Prefabs/dialogue button.prefab | 204 ++ Assets/Scenes/MainGame.unity | 96 +- Assets/Scripts/DialogueData.cs | 18 + Assets/Scripts/DialogueManager.cs | 107 + Assets/Scripts/DialoguePopUp.cs | 54 + Assets/Scripts/NewBehaviourScript.cs | 18 + Assets/Scripts/dialogue.ink.json | 1 + Assets/Scripts/dialogue.send_ink.json | 1 + ProjectSettings/InkSettings.asset | 24 + 153 files changed, 29751 insertions(+), 1 deletion(-) create mode 100644 Assets/Ink/CHANGELOG.md create mode 100644 Assets/Ink/Demos/Basic Demo/Basic Demo.unity create mode 100644 Assets/Ink/Demos/Basic Demo/Ink/story.ink create mode 100644 Assets/Ink/Demos/Basic Demo/Ink/story.json create mode 100644 Assets/Ink/Demos/Basic Demo/Prefabs/Button.prefab create mode 100644 Assets/Ink/Demos/Basic Demo/Prefabs/Text.prefab create mode 100644 Assets/Ink/Demos/Basic Demo/Scripts/BasicInkExample.cs create mode 100644 Assets/Ink/Demos/Basic Demo/Scripts/Editor/BasicInkExampleEditor.cs create mode 100644 Assets/Ink/Demos/Basic Demo/Scripts/QuitGameOnKeypress.cs create mode 100644 Assets/Ink/Documentation/API Documentation.pdf create mode 100644 Assets/Ink/Documentation/Ink for Unity Package Documentation.pdf create mode 100644 Assets/Ink/Editor/Core/Compiler/Auto Compiler/InkPostProcessor.cs create mode 100644 Assets/Ink/Editor/Core/Compiler/InkCompiler.cs create mode 100644 Assets/Ink/Editor/Core/Compiler/UnityInkFileHandler.cs create mode 100644 Assets/Ink/Editor/Core/Ink Library/InkCompilerLog.cs create mode 100644 Assets/Ink/Editor/Core/Ink Library/InkFile.cs create mode 100644 Assets/Ink/Editor/Core/Ink Library/InkLibrary.cs create mode 100644 Assets/Ink/Editor/Core/Ink Settings/InkSettings.cs create mode 100644 Assets/Ink/Editor/Core/Ink Settings/InkSettingsEditor.cs create mode 100644 Assets/Ink/Editor/Core/InkEditorUtils.cs create mode 100644 Assets/Ink/Editor/InkEditor.asmdef create mode 100644 Assets/Ink/Editor/Tools/Build Validation/InkPreBuildValidationCheck.cs create mode 100644 Assets/Ink/Editor/Tools/File Icons/InkBrowserIcons.cs create mode 100644 Assets/Ink/Editor/Tools/File Icons/Resources/InkChildIcon-Large.psd create mode 100644 Assets/Ink/Editor/Tools/File Icons/Resources/InkChildIcon.psd create mode 100644 Assets/Ink/Editor/Tools/File Icons/Resources/InkCompileManualIcon.psd create mode 100644 Assets/Ink/Editor/Tools/File Icons/Resources/InkDefaultTemplate.txt create mode 100644 Assets/Ink/Editor/Tools/File Icons/Resources/InkErrorIcon.psd create mode 100644 Assets/Ink/Editor/Tools/File Icons/Resources/InkFileIcon-Large.psd create mode 100644 Assets/Ink/Editor/Tools/File Icons/Resources/InkFileIcon-retina.psd create mode 100644 Assets/Ink/Editor/Tools/File Icons/Resources/InkFileIcon.psd create mode 100644 Assets/Ink/Editor/Tools/File Icons/Resources/InkTodoIcon.psd create mode 100644 Assets/Ink/Editor/Tools/File Icons/Resources/InkUnknownFileIcon.psd create mode 100644 Assets/Ink/Editor/Tools/File Icons/Resources/InkWarningIcon.psd create mode 100644 Assets/Ink/Editor/Tools/Ink Inspector/DefaultAssetEditor.cs create mode 100644 Assets/Ink/Editor/Tools/Ink Inspector/DefaultAssetInspector.cs create mode 100644 Assets/Ink/Editor/Tools/Ink Inspector/InkInspector.cs create mode 100644 Assets/Ink/Editor/Tools/Player Window/InkHistoryContentItem.cs create mode 100644 Assets/Ink/Editor/Tools/Player Window/InkPlayerWindow.cs create mode 100644 Assets/Ink/Editor/Tools/Startup Window/InkUnityIntegrationStartupWindow.cs create mode 100644 Assets/Ink/Extras/Sublime3Syntax.zip create mode 100644 Assets/Ink/InkLibs/Ink-Libraries.asmdef create mode 100644 Assets/Ink/InkLibs/InkCompiler/CharacterRange.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/CharacterSet.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/CommandLineInput.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/Compiler.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/FileHandler.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/InkParser/CommentEliminator.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_AuthorWarning.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_CharacterRanges.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Choices.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_CommandLineInput.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Conditional.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Content.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Divert.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Expressions.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Include.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Knot.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Logic.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Sequences.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Statements.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Tags.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Whitespace.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/InkStringConversionExtensions.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/AuthorWarning.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Choice.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Conditional.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ConditionalSingleBranch.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ConstantDeclaration.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ContentList.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Divert.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/DivertTarget.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Expression.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ExternalDeclaration.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/FlowBase.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/FlowLevel.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/FunctionCall.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Gather.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/INamedContent.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/IWeavePoint.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Identifier.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/IncludedFile.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Knot.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/List.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ListDefinition.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Number.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Object.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Path.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Return.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Sequence.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Stitch.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Story.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/StringExpression.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Tag.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Text.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/TunnelOnwards.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/VariableAssignment.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/VariableReference.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Weave.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Wrap.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/Plugins/Plugin.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/Plugins/PluginManager.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/Stats.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/StringParser/StringParser.cs create mode 100644 Assets/Ink/InkLibs/InkCompiler/StringParser/StringParserState.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/CallStack.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/Choice.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/ChoicePoint.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/Container.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/ControlCommand.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/DebugMetadata.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/Divert.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/Error.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/Flow.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/Glue.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/INamedContent.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/InkList.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/JsonSerialisation.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/ListDefinition.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/ListDefinitionsOrigin.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/NativeFunctionCall.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/Object.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/Path.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/Pointer.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/Profiler.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/PushPop.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/SearchResult.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/SimpleJson.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/StatePatch.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/Story.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/StoryException.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/StoryState.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/StringJoinExtension.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/Tag.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/Value.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/VariableAssignment.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/VariableReference.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/VariablesState.cs create mode 100644 Assets/Ink/InkLibs/InkRuntime/Void.cs create mode 100644 Assets/Ink/LICENCE.md create mode 100644 Assets/Ink/README.md create mode 100644 Assets/Prefabs/DialogueManager.prefab create mode 100644 Assets/Prefabs/DialogueStuff.prefab create mode 100644 Assets/Prefabs/dialogue button.prefab create mode 100644 Assets/Scripts/DialogueData.cs create mode 100644 Assets/Scripts/DialogueManager.cs create mode 100644 Assets/Scripts/DialoguePopUp.cs create mode 100644 Assets/Scripts/NewBehaviourScript.cs create mode 100644 Assets/Scripts/dialogue.ink.json create mode 100644 Assets/Scripts/dialogue.send_ink.json create mode 100644 ProjectSettings/InkSettings.asset diff --git a/Assets/Ink/CHANGELOG.md b/Assets/Ink/CHANGELOG.md new file mode 100644 index 0000000..4e3419d --- /dev/null +++ b/Assets/Ink/CHANGELOG.md @@ -0,0 +1,108 @@ +## Version 1.1.8 (11th July 2023): +- Update the demo scene to Unity 2020.3.25f1 to improve compatibility with more recent versions +- Fixes a missing GUIStyle in the Ink Player Window in recent versions of Unity +- Optimise the Ink Player Window for large projects +- Automatically populate the changelog on the startup window + +## Version 1.1.7 (20th Feb 2023): +- Rework of the plugin's INCLUDE hierarchy system, allowing for previously unhandled valid setups +- Changes the OpenInEditor function to use AssetDatabase.OpenAsset, which correctly uses the OS file editor +- Prevents the Ink Player Window from showing itself when scripts are recompiled + +## Version 1.1.5 (2nd December 2022): +- Adds InkSettings.suppressStartupWindow, which can be used to prevent this window from appearing (requested for some CI/CD pipelines) +- Adds links to Discord for community support in help menu, startup window and setting menu +- Fixes an issue where InkSettings ScriptableObjects wouldn't be unloaded +- Updates build documentation for this plugin + +## Version 1.1.1 (20th October 2022): +- Updates ink to 1.1.1. +- The InkCompiler.OnCompileInk event now fires once when the compilation stack completes and returns an array of compiled files +- Fixes some async threading issues when compiling +- Adds JSON formatting for save states copied or saved via the Ink Player Window +- Use the Unity Progress API to show compilation. Useful for large ink projects! +- Included files now show their own included files in the Inspector +- Various optimisations + +## Version 1.0.2: +- Fix a very rare but quite nasty compilation bug + +## Version 🎉1.0.0🎉: +- Update ink to 1.0.0 +- Ink Editor Window: Allow resizing (some) panels +- Ink Editor Window: Named content panel +- Ink Editor Window: Improved performance for large stories +- Allow compiling include files that don't have the .ink file extension +- Remove ability to use a custom inklecate (legacy compiler) +- Fixes settings menu on 2020+ +- Improved migration from earlier versions +- Moved persistent compilation tracking code from InkLibrary into InkCompiler +- Use Unity's new ScriptableSingleton for InkLibrary, InkSettings and InkCompiler on 2020+ + +## Version 0.9.71: +- Resolves some compilation issues + +## Version 0.9.60: +- Moved InkLibrary and InkSettings from Assets into Library and ProjectSettings + - InkLibrary should no longer be tracked in source control + - Changes to InkSettings must be migrated manually + - The InkLibrary and InkSettings files in your project folder should be deleted +- Added a divertable list of knots, stitches and other named content to the Ink Editor Window, replacing the Diverts subpanel + +## Version 0.9.4 +Bug fixes + +## Version 0.9.24 +- Updates ink to latest +- Various improvements to the ink player window +- Performance improvements and bug fixes for projects with multiple ink files. +- Easier workflow for manual compilation in-game +- Minor package updates and fixes + +## Version 0.9.2 +- Updates ink to 0.9.2 +- Better tethering for Ink Window +- Minor package updates and fixes + +## Version 0.9.1 +- Updates ink to 0.9.1 +- Minor package updates and fixes + +## Version 0.8.3 +- Updates ink to 0.8.3 +- Minor package updates and fixes + +## Version 0.8.2 +- Unity 2018 compatibility + +## Version 0.8.1 +- Updates ink to 0.8.1 +- Fixes some rare compilation issues +- Tooltips and other minor features + +## Version 0.7.6 +- Compatability for Unity 2017.X + +## Version 0.7.5 +- Updates ink to version 0.7.5 +- Option to delay compilation when ink changes are detected in play mode (enabled by default) +- Adds ability to run functions and profile from player window + +## Version 0.7.4 +- Update Ink to 0.7.4 +- Add tooltips to player window +- Improve performance +- Fix compilation issues on larger projects +- Stability fixes +- Don't show compiler shell in windows + +## Version 0.7.1 +- Update to Unity 5.6 +- Reduced the amount of data saved in InkLibrary by storing metadata in EditorPrefs +- Split some parts of InkLibrary into InkSettings ScriptableObject + +## VersionAdded in 0.7.0 +- Update Ink to 0.7 +- New icon for manually compiled +- Improved ink library editor +- Improved the ease of tethering your game's Story object to the Ink Player Window via an Editor GUI field and improvements to player window \ No newline at end of file diff --git a/Assets/Ink/Demos/Basic Demo/Basic Demo.unity b/Assets/Ink/Demos/Basic Demo/Basic Demo.unity new file mode 100644 index 0000000..d96360a --- /dev/null +++ b/Assets/Ink/Demos/Basic Demo/Basic Demo.unity @@ -0,0 +1,728 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &1104190021 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1104190022} + - component: {fileID: 1104190024} + - component: {fileID: 1104190023} + - component: {fileID: 1104190025} + m_Layer: 5 + m_Name: Help + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1104190022 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1104190021} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1908123727} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 286.5, y: 0} + m_SizeDelta: {x: 346, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1104190023 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1104190021} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 18 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Check the readme file for more information! +--- !u!222 &1104190024 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1104190021} + m_CullTransparentMesh: 0 +--- !u!114 &1104190025 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1104190021} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1741964061, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 0 + m_VerticalFit: 2 +--- !u!1 &1300920510 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1300920511} + - component: {fileID: 1300920513} + - component: {fileID: 1300920512} + - component: {fileID: 1300920514} + m_Layer: 5 + m_Name: Edit the story! + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1300920511 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1300920510} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1908123727} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 286.5, y: 0} + m_SizeDelta: {x: 573, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1300920512 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1300920510} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 18 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: "When you're done, try editing the story.ink to change the story; and the\r + BasicInkExample script to change what Unity does with it!" +--- !u!222 &1300920513 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1300920510} + m_CullTransparentMesh: 0 +--- !u!114 &1300920514 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1300920510} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1741964061, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 0 + m_VerticalFit: 2 +--- !u!1 &1482195891 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1482195896} + - component: {fileID: 1482195895} + - component: {fileID: 1482195893} + - component: {fileID: 1482195892} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1482195892 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1482195891} + m_Enabled: 1 +--- !u!124 &1482195893 +Behaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1482195891} + m_Enabled: 1 +--- !u!20 &1482195895 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1482195891} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &1482195896 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1482195891} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -456, y: -470, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2009679605} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1767420452 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1767420453} + - component: {fileID: 1767420455} + - component: {fileID: 1767420454} + - component: {fileID: 1767420456} + m_Layer: 5 + m_Name: Press Play + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1767420453 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1767420452} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1908123727} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 286.5, y: 0} + m_SizeDelta: {x: 365, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1767420454 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1767420452} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 18 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Press the Play button at the top of the screen! +--- !u!222 &1767420455 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1767420452} + m_CullTransparentMesh: 0 +--- !u!114 &1767420456 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1767420452} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1741964061, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 0 + m_VerticalFit: 2 +--- !u!1 &1908123722 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1908123727} + - component: {fileID: 1908123726} + - component: {fileID: 1908123725} + - component: {fileID: 1908123723} + - component: {fileID: 1908123724} + - component: {fileID: 1908123728} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1908123723 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1908123722} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 4 + m_Spacing: 10 + m_ChildForceExpandWidth: 0 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 1 + m_ChildControlHeight: 0 +--- !u!114 &1908123724 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1908123722} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7ce0d8573e1b2ff42af74cb80f3e5ece, type: 3} + m_Name: + m_EditorClassIdentifier: + key: 27 +--- !u!223 &1908123726 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1908123722} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 1 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &1908123727 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1908123722} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_Children: + - {fileID: 1767420453} + - {fileID: 1300920511} + - {fileID: 1104190022} + m_Father: {fileID: 2009679605} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &1908123728 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1908123722} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!1 &1949950323 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1949950326} + - component: {fileID: 1949950325} + - component: {fileID: 1949950324} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1949950324 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1949950323} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1949950325 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1949950323} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 10 +--- !u!4 &1949950326 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1949950323} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &2009679603 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2009679605} + - component: {fileID: 2009679604} + - component: {fileID: 2009679606} + m_Layer: 0 + m_Name: Scene Controller + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &2009679604 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2009679603} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 66e957d58a4584a8894329531ec0b096, type: 3} + m_Name: + m_EditorClassIdentifier: + inkJSONAsset: {fileID: 4900000, guid: 6cf48bb6d89824cc69e35b43f9a1aca6, type: 3} + canvas: {fileID: 1908123726} + textPrefab: {fileID: 11456674, guid: 1aab6ef84d87c416f8f0b3e1ef3d77d2, type: 3} + buttonPrefab: {fileID: 11455116, guid: 37c108a6c38964f79a6621eccb33ddc1, type: 3} +--- !u!4 &2009679605 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2009679603} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 456, y: 470, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1482195896} + - {fileID: 1908123727} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2009679606 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2009679603} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7ce0d8573e1b2ff42af74cb80f3e5ece, type: 3} + m_Name: + m_EditorClassIdentifier: + key: 27 diff --git a/Assets/Ink/Demos/Basic Demo/Ink/story.ink b/Assets/Ink/Demos/Basic Demo/Ink/story.ink new file mode 100644 index 0000000..26a6db8 --- /dev/null +++ b/Assets/Ink/Demos/Basic Demo/Ink/story.ink @@ -0,0 +1,19 @@ +- I looked at Monsieur Fogg +* ... and I could contain myself no longer. + 'What is the purpose of our journey, Monsieur?' + 'A wager,' he replied. + * * 'A wager!'[] I returned. + He nodded. + * * * 'But surely that is foolishness!' + * * * 'A most serious matter then!' + - - - He nodded again. + * * * 'But can we win?' + 'That is what we will endeavour to find out,' he answered. + * * * 'A modest wager, I trust?' + 'Twenty thousand pounds,' he replied, quite flatly. + * * * I asked nothing further of him then[.], and after a final, polite cough, he offered nothing more to me. <> + * * 'Ah[.'],' I replied, uncertain what I thought. + - - After that, <> +* ... but I said nothing[] and <> +- we passed the day in silence. +- -> END \ No newline at end of file diff --git a/Assets/Ink/Demos/Basic Demo/Ink/story.json b/Assets/Ink/Demos/Basic Demo/Ink/story.json new file mode 100644 index 0000000..8f1868a --- /dev/null +++ b/Assets/Ink/Demos/Basic Demo/Ink/story.json @@ -0,0 +1 @@ +{"inkVersion":21,"root":[[["^I looked at Monsieur Fogg","\n",["ev",{"^->":"0.g-0.2.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"s":["^... and I could contain myself no longer.",{"->":"$r","var":true},null]}],["ev",{"^->":"0.g-0.3.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-1","flg":18},{"s":["^... but I said nothing",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"0.g-0.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.2.s"},[{"#n":"$r2"}],"\n","^'What is the purpose of our journey, Monsieur?'","\n","^'A wager,' he replied.","\n",[["ev",{"^->":"0.g-0.c-0.11.0.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"s":["^'A wager!'",{"->":"$r","var":true},null]}],["ev",{"^->":"0.g-0.c-0.11.1.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^.'","/str","/ev",{"*":".^.^.c-1","flg":22},{"s":["^'Ah",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"0.g-0.c-0.11.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.0.s"},[{"#n":"$r2"}],"^ I returned.","\n","^He nodded.","\n",[["ev",{"^->":"0.g-0.c-0.11.c-0.10.0.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"s":["^'But surely that is foolishness!'",{"->":"$r","var":true},null]}],["ev",{"^->":"0.g-0.c-0.11.c-0.10.1.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-1","flg":18},{"s":["^'A most serious matter then!'",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"0.g-0.c-0.11.c-0.10.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.0.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["ev",{"^->":"0.g-0.c-0.11.c-0.10.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.1.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^He nodded again.","\n",["ev",{"^->":"0.g-0.c-0.11.c-0.10.g-0.2.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-2","flg":18},{"s":["^'But can we win?'",{"->":"$r","var":true},null]}],["ev",{"^->":"0.g-0.c-0.11.c-0.10.g-0.3.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-3","flg":18},{"s":["^'A modest wager, I trust?'",{"->":"$r","var":true},null]}],["ev",{"^->":"0.g-0.c-0.11.c-0.10.g-0.4.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^.","/str","/ev",{"*":".^.^.c-4","flg":22},{"s":["^I asked nothing further of him then",{"->":"$r","var":true},null]}],{"c-2":["ev",{"^->":"0.g-0.c-0.11.c-0.10.g-0.c-2.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.2.s"},[{"#n":"$r2"}],"\n","^'That is what we will endeavour to find out,' he answered.","\n",{"->":".^.^.^.^.^.g-0"},{"#f":5}],"c-3":["ev",{"^->":"0.g-0.c-0.11.c-0.10.g-0.c-3.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.3.s"},[{"#n":"$r2"}],"\n","^'Twenty thousand pounds,' he replied, quite flatly.","\n",{"->":".^.^.^.^.^.g-0"},{"#f":5}],"c-4":["ev",{"^->":"0.g-0.c-0.11.c-0.10.g-0.c-4.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.4.s"},[{"#n":"$r2"}],"^, and after a final, polite cough, he offered nothing more to me. ","<>","\n",{"->":".^.^.^.^.^.g-0"},{"#f":5}],"#f":5}]}],{"#f":5}],"c-1":["ev",{"^->":"0.g-0.c-0.11.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.1.s"},[{"#n":"$r2"}],"^,' I replied, uncertain what I thought.","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^After that, ","<>","\n",{"->":"0.g-1"},{"#f":5}]}],{"#f":5}],"c-1":["ev",{"^->":"0.g-0.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.3.s"},[{"#n":"$r2"}],"^ and ","<>","\n",{"->":"0.g-1"},{"#f":5}],"#f":5,"#n":"g-0"}],{"g-1":["^we passed the day in silence.","\n",["end",["done",{"#f":5,"#n":"g-3"}],{"#f":5,"#n":"g-2"}],{"#f":5}]}],"done",{"#f":1}],"listDefs":{}} \ No newline at end of file diff --git a/Assets/Ink/Demos/Basic Demo/Prefabs/Button.prefab b/Assets/Ink/Demos/Basic Demo/Prefabs/Button.prefab new file mode 100644 index 0000000..9eb92c8 --- /dev/null +++ b/Assets/Ink/Demos/Basic Demo/Prefabs/Button.prefab @@ -0,0 +1,265 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &105558 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 4 + m_Component: + - 224: {fileID: 22491254} + - 222: {fileID: 22256872} + - 114: {fileID: 11418596} + - 114: {fileID: 11455116} + - 114: {fileID: 11420252} + - 114: {fileID: 11438922} + m_Layer: 5 + m_Name: Button + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &134058 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 4 + m_Component: + - 224: {fileID: 22447082} + - 222: {fileID: 22289712} + - 114: {fileID: 11421544} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &11418596 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 105558} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 +--- !u!114 &11420252 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 105558} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1741964061, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 2 + m_VerticalFit: 2 +--- !u!114 &11421544 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 134058} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Button +--- !u!114 &11438922 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 105558} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -405508275, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 5 + m_Right: 5 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 +--- !u!114 &11455116 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 105558} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 11418596} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!222 &22256872 +CanvasRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 105558} +--- !u!222 &22289712 +CanvasRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 134058} +--- !u!224 &22447082 +RectTransform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 134058} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_Children: [] + m_Father: {fileID: 22491254} + m_RootOrder: 0 + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!224 &22491254 +RectTransform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 105558} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_Children: + - {fileID: 22447082} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 0} + propertyPath: m_Enabled + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_HorizontalFit + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_VerticalFit + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Padding.m_Left + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Padding.m_Right + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Padding.m_Top + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Padding.m_Bottom + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Spacing + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 105558} + m_IsPrefabParent: 1 diff --git a/Assets/Ink/Demos/Basic Demo/Prefabs/Text.prefab b/Assets/Ink/Demos/Basic Demo/Prefabs/Text.prefab new file mode 100644 index 0000000..e2ccad7 --- /dev/null +++ b/Assets/Ink/Demos/Basic Demo/Prefabs/Text.prefab @@ -0,0 +1,118 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &162960 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 22481992} + - component: {fileID: 22265584} + - component: {fileID: 11456674} + - component: {fileID: 11422042} + - component: {fileID: 11400932} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &22481992 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 162960} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 160, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &22265584 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 162960} + m_CullTransparentMesh: 0 +--- !u!114 &11456674 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 162960} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 20 + m_FontStyle: 1 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 40 + m_Alignment: 1 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: +--- !u!114 &11422042 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 162960} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -405508275, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &11400932 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 162960} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1741964061, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 0 + m_VerticalFit: 2 diff --git a/Assets/Ink/Demos/Basic Demo/Scripts/BasicInkExample.cs b/Assets/Ink/Demos/Basic Demo/Scripts/BasicInkExample.cs new file mode 100644 index 0000000..b80769a --- /dev/null +++ b/Assets/Ink/Demos/Basic Demo/Scripts/BasicInkExample.cs @@ -0,0 +1,110 @@ +using System; +using Ink.Runtime; +using UnityEngine; +using UnityEngine.UI; + +// This is a super bare bones example of how to play and display a ink story in Unity. +public class BasicInkExample : MonoBehaviour { + public static event Action OnCreateStory; + + void Awake () { + // Remove the default message + RemoveChildren(); + StartStory(); + } + + // Creates a new Story object with the compiled story which we can then play! + void StartStory () { + story = new Story (inkJSONAsset.text); + if(OnCreateStory != null) OnCreateStory(story); + RefreshView(); + } + + // This is the main function called every time the story changes. It does a few things: + // Destroys all the old content and choices. + // Continues over all the lines of text, then displays all the choices. If there are no choices, the story is finished! + void RefreshView () { + // Remove all the UI on screen + RemoveChildren (); + + // Read all the content until we can't continue any more + while (story.canContinue) { + // Continue gets the next line of the story + string text = story.Continue (); + // This removes any white space from the text. + text = text.Trim(); + // Display the text on screen! + CreateContentView(text); + } + + // Display all the choices, if there are any! + if(story.currentChoices.Count > 0) { + for (int i = 0; i < story.currentChoices.Count; i++) { + Choice choice = story.currentChoices [i]; + Button button = CreateChoiceView (choice.text.Trim ()); + // Tell the button what to do when we press it + button.onClick.AddListener (delegate { + OnClickChoiceButton (choice); + }); + } + } + // If we've read all the content and there's no choices, the story is finished! + else { + Button choice = CreateChoiceView("End of story.\nRestart?"); + choice.onClick.AddListener(delegate{ + StartStory(); + }); + } + } + + // When we click the choice button, tell the story to choose that choice! + void OnClickChoiceButton (Choice choice) { + story.ChooseChoiceIndex (choice.index); + RefreshView(); + } + + // Creates a textbox showing the the line of text + void CreateContentView (string text) { + Text storyText = Instantiate (textPrefab) as Text; + storyText.text = text; + storyText.transform.SetParent (canvas.transform, false); + } + + // Creates a button showing the choice text + Button CreateChoiceView (string text) { + // Creates the button from a prefab + Button choice = Instantiate (buttonPrefab) as Button; + choice.transform.SetParent (canvas.transform, false); + + // Gets the text from the button prefab + Text choiceText = choice.GetComponentInChildren (); + choiceText.text = text; + + // Make the button expand to fit the text + HorizontalLayoutGroup layoutGroup = choice.GetComponent (); + layoutGroup.childForceExpandHeight = false; + + return choice; + } + + // Destroys all the children of this gameobject (all the UI) + void RemoveChildren () { + int childCount = canvas.transform.childCount; + for (int i = childCount - 1; i >= 0; --i) { + Destroy (canvas.transform.GetChild (i).gameObject); + } + } + + [SerializeField] + private TextAsset inkJSONAsset = null; + public Story story; + + [SerializeField] + private Canvas canvas = null; + + // UI Prefabs + [SerializeField] + private Text textPrefab = null; + [SerializeField] + private Button buttonPrefab = null; +} diff --git a/Assets/Ink/Demos/Basic Demo/Scripts/Editor/BasicInkExampleEditor.cs b/Assets/Ink/Demos/Basic Demo/Scripts/Editor/BasicInkExampleEditor.cs new file mode 100644 index 0000000..c38167b --- /dev/null +++ b/Assets/Ink/Demos/Basic Demo/Scripts/Editor/BasicInkExampleEditor.cs @@ -0,0 +1,26 @@ +using Ink.Runtime; +using Ink.UnityIntegration; +using UnityEditor; +using UnityEngine; + +[CustomEditor(typeof(BasicInkExample))] +[InitializeOnLoad] +public class BasicInkExampleEditor : Editor { + static bool storyExpanded; + static BasicInkExampleEditor () { + BasicInkExample.OnCreateStory += OnCreateStory; + } + + static void OnCreateStory (Story story) { + // If you'd like NOT to automatically show the window and attach (your teammates may appreciate it!) then replace "true" with "false" here. + InkPlayerWindow window = InkPlayerWindow.GetWindow(true); + if(window != null) InkPlayerWindow.Attach(story); + } + public override void OnInspectorGUI () { + Repaint(); + base.OnInspectorGUI (); + var realTarget = target as BasicInkExample; + var story = realTarget.story; + InkPlayerWindow.DrawStoryPropertyField(story, ref storyExpanded, new GUIContent("Story")); + } +} diff --git a/Assets/Ink/Demos/Basic Demo/Scripts/QuitGameOnKeypress.cs b/Assets/Ink/Demos/Basic Demo/Scripts/QuitGameOnKeypress.cs new file mode 100644 index 0000000..30b1ac5 --- /dev/null +++ b/Assets/Ink/Demos/Basic Demo/Scripts/QuitGameOnKeypress.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +public class QuitGameOnKeypress : MonoBehaviour { + + public KeyCode key = KeyCode.Escape; + + void Update () { + if(Input.GetKeyDown(key)) Application.Quit(); + } +} \ No newline at end of file diff --git a/Assets/Ink/Documentation/API Documentation.pdf b/Assets/Ink/Documentation/API Documentation.pdf new file mode 100644 index 0000000000000000000000000000000000000000..bb60e5065c0f7584b68424e032f9b1288eafb0ff GIT binary patch literal 84720 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 CPj_(u literal 0 HcmV?d00001 diff --git a/Assets/Ink/Documentation/Ink for Unity Package Documentation.pdf b/Assets/Ink/Documentation/Ink for Unity Package Documentation.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b21080c53ee170796a016c854800bff20ef762db GIT binary patch literal 41949 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 Nq0`ce$~;B?{{Y5BP167X literal 0 HcmV?d00001 diff --git a/Assets/Ink/Editor/Core/Compiler/Auto Compiler/InkPostProcessor.cs b/Assets/Ink/Editor/Core/Compiler/Auto Compiler/InkPostProcessor.cs new file mode 100644 index 0000000..1d7f2f6 --- /dev/null +++ b/Assets/Ink/Editor/Core/Compiler/Auto Compiler/InkPostProcessor.cs @@ -0,0 +1,212 @@ +// Automatically creates JSON files from an ink placed within the Assets/Ink folder. +using UnityEngine; +using UnityEditor; +using System.IO; +using Debug = UnityEngine.Debug; +using System.Collections.Generic; +using System.Linq; + +namespace Ink.UnityIntegration { + + public class InkPostProcessor : AssetPostprocessor { + // Several assets moved at the same time can cause unity to call OnPostprocessAllAssets several times as a result of moving additional files, or simply due to minor time differences. + // This queue tells the compiler which files to recompile after moves have completed. + // Not a perfect solution - If Unity doesn't move all the files in the same attempt you can expect some error messages to appear on compile. + private static List queuedMovedInkFileAssets = new List(); + + // We should make this a stack, similar to GUI.BeginDisabledGroup. + public static bool disabled = false; + // I'd like to make this a public facing setting sometime. Options are async or immediate. + public static bool compileImmediatelyOnImport = false; + // Recompiles any ink files as a result of an ink file (re)import + private static void OnPostprocessAllAssets (string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) { + if(disabled) return; + if(deletedAssets.Length > 0) { + OnDeleteAssets(deletedAssets); + } + if(movedAssets.Length > 0) { + OnMoveAssets(movedAssets); + } + if(importedAssets.Length > 0) { + // Assets that are renamed are both moved and imported. We do all the work in OnMoveAssets, so do nothing here. + var importedAssetsThatWerentRenames = importedAssets.Except(movedAssets).ToArray(); + OnImportAssets(importedAssetsThatWerentRenames); + } + #if !UNITY_2020_1_OR_NEWER + if(InkLibrary.created) + #endif + InkLibrary.Clean(); + } + + private static void OnDeleteAssets (string[] deletedAssets) { + bool deletedInk = false; + foreach (var deletedAssetPath in deletedAssets) { + if(InkEditorUtils.IsInkFile(deletedAssetPath)) { + deletedInk = true; + break; + } + } + if(!deletedInk) + return; + +// bool alsoDeleteJSON = false; +// alsoDeleteJSON = EditorUtility.DisplayDialog("Deleting .ink file", "Also delete the JSON file associated with the deleted .ink file?", "Yes", "No")); + List masterFilesAffected = new List(); + for (int i = InkLibrary.instance.inkLibrary.Count - 1; i >= 0; i--) { + var inkFile = InkLibrary.instance.inkLibrary[i]; + // If this file was deleted... + if(inkFile.inkAsset == null) { + // Mark the master files to be recompiled (note that those files might also have been deleted) + if(!inkFile.isMaster) { + foreach(var masterInkAsset in inkFile.masterInkAssets) { + if(masterInkAsset != null) { + var masterInkFile = InkLibrary.GetInkFileWithFile(masterInkAsset); + if(!masterFilesAffected.Contains(masterInkFile)) + masterFilesAffected.Add(masterInkFile); + } + } + } + // Delete the associated json file + if(InkSettings.instance.handleJSONFilesAutomatically) { + var assetPath = AssetDatabase.GetAssetPath(inkFile.jsonAsset); + if(assetPath != null && assetPath != string.Empty) { + AssetDatabase.DeleteAsset(assetPath); + } + } + // Finally, remove it from the ink library + InkLibrary.RemoveAt(i); + } + } + + // After deleting files, we might have broken some include references, so we rebuild them. There's probably a faster way to do this, or we could probably just remove any null references, but this is a bit more robust. + InkLibrary.RebuildInkFileConnections(); + + foreach(var masterInkFile in masterFilesAffected) { + if(InkSettings.instance.ShouldCompileInkFileAutomatically(masterInkFile)) { + InkCompiler.CompileInk(masterInkFile); + } + } + } + + private static void OnMoveAssets (string[] movedAssets) { + if (!InkSettings.instance.handleJSONFilesAutomatically) + return; + + List validMovedAssets = new List(); + for (var i = 0; i < movedAssets.Length; i++) { + if(!InkEditorUtils.IsInkFile(movedAssets[i])) + continue; + validMovedAssets.Add(movedAssets[i]); + queuedMovedInkFileAssets.Add(movedAssets[i]); + + } + // Move compiled JSON files. + // This can cause Unity to postprocess assets again. + foreach(var inkFilePath in validMovedAssets) { + InkFile inkFile = InkLibrary.GetInkFileWithPath(inkFilePath); + if(inkFile == null) continue; + if(inkFile.jsonAsset == null) continue; + + string jsonAssetPath = AssetDatabase.GetAssetPath(inkFile.jsonAsset); + + string movedAssetDir = Path.GetDirectoryName(inkFilePath); + string movedAssetFile = Path.GetFileName(inkFilePath); + string newPath = InkEditorUtils.CombinePaths(movedAssetDir, Path.GetFileNameWithoutExtension(movedAssetFile)) + ".json"; + + // On moving an ink file, we either recompile it, creating a new json file in the correct location, or we move the json file. + if(InkSettings.instance.ShouldCompileInkFileAutomatically(inkFile)) { + // We have to delay this, or it doesn't properly inform unity (there's no version of "ImportAsset" for delete); I guess it doesn't want OnPostprocessAllAssets to fire recursively. + EditorApplication.delayCall += () => { + AssetDatabase.DeleteAsset(jsonAssetPath); + AssetDatabase.Refresh(); + }; + } else { + if (string.IsNullOrEmpty(AssetDatabase.ValidateMoveAsset(jsonAssetPath, newPath))) { + Debug.Assert(newPath==inkFile.jsonPath); + EditorApplication.delayCall += () => { + AssetDatabase.MoveAsset(jsonAssetPath, newPath); + AssetDatabase.ImportAsset(newPath); + AssetDatabase.Refresh(); + inkFile.FindCompiledJSONAsset(); + }; + // Debug.Log(jsonAssetPath+" to "+newPath); + } else { + // This will fire if the JSON file is also moved with the ink - in this case the json file will be in movedAssets. + // Debug.Log($"Failed to move asset from path '{jsonAssetPath}' to '{newPath}'."); + } + } + } + // Check if no JSON assets were moved (as a result of none needing to move, or this function being called as a result of JSON files being moved) + if(queuedMovedInkFileAssets.Count > 0) { + List filesToCompile = new List(); + + // Add the old master file to the files to be recompiled + foreach(var inkFilePath in queuedMovedInkFileAssets) { + InkFile inkFile = InkLibrary.GetInkFileWithPath(inkFilePath); + if(inkFile == null) continue; + foreach(var masterInkFile in inkFile.masterInkFilesIncludingSelf) { + if(InkSettings.instance.ShouldCompileInkFileAutomatically(masterInkFile) && !filesToCompile.Contains(masterInkFile)) + filesToCompile.Add(masterInkFile); + } + } + + InkLibrary.RebuildInkFileConnections(); + + // If rebuilding connections caused a file that was previously considered a master file to no longer be, then we remove it. + for (int i = filesToCompile.Count - 1; i >= 0; i--) + if(!filesToCompile[i].isMaster) + filesToCompile.RemoveAt(i); + + // Add the new file to be recompiled + foreach(var inkFilePath in queuedMovedInkFileAssets) { + InkFile inkFile = InkLibrary.GetInkFileWithPath(inkFilePath); + if(inkFile == null) continue; + + foreach(var masterInkFile in inkFile.masterInkFilesIncludingSelf) { + if(InkSettings.instance.ShouldCompileInkFileAutomatically(masterInkFile) && !filesToCompile.Contains(masterInkFile)) + filesToCompile.Add(masterInkFile); + } + } + + queuedMovedInkFileAssets.Clear(); + + + // Compile any ink files that are deemed master files a rebuild + InkCompiler.CompileInk(filesToCompile.ToArray(), compileImmediatelyOnImport); + } + } + + private static void OnImportAssets (string[] importedAssets) { + List importedInkAssets = new List(); + string inklecateFileLocation = null; + foreach (var importedAssetPath in importedAssets) { + if(InkEditorUtils.IsInkFile(importedAssetPath)) + importedInkAssets.Add(importedAssetPath); + else if (Path.GetFileName(importedAssetPath) == "inklecate" && Path.GetExtension(importedAssetPath) == "") + inklecateFileLocation = importedAssetPath; + } + if(importedInkAssets.Count > 0) + PostprocessInkFiles(importedInkAssets); + if(inklecateFileLocation != null) + PostprocessInklecate(inklecateFileLocation); + } + + private static void PostprocessInklecate (string inklecateFileLocation) { + // This should probably only recompile files marked to compile automatically, but it's such a rare case, and one where you probably do want to compile. + // To fix, one day! + Debug.Log("Inklecate updated. Recompiling all Ink files..."); + InkEditorUtils.RecompileAll(); + } + + private static void PostprocessInkFiles (List importedInkAssets) { + if(EditorApplication.isPlaying && InkSettings.instance.delayInPlayMode) { + foreach(var fileToImport in importedInkAssets) { + InkCompiler.AddToPendingCompilationStack(fileToImport); + } + } else { + InkLibrary.CreateOrReadUpdatedInkFiles (importedInkAssets); + InkCompiler.CompileInk(InkCompiler.GetUniqueMasterInkFilesToCompile (importedInkAssets).ToArray()); + } + } + } +} \ No newline at end of file diff --git a/Assets/Ink/Editor/Core/Compiler/InkCompiler.cs b/Assets/Ink/Editor/Core/Compiler/InkCompiler.cs new file mode 100644 index 0000000..d31ba5b --- /dev/null +++ b/Assets/Ink/Editor/Core/Compiler/InkCompiler.cs @@ -0,0 +1,822 @@ +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Threading; +using Debug = UnityEngine.Debug; + +namespace Ink.UnityIntegration { + // Ink Compiler handles the compilation of Ink Files, storing and logging todos, warnings and errors. + // It manages a queue of items, ensuring that each file is completed in sequence. + + // Ink compilation is handled automatically when ink files change (via InkPostProcessor), but you can also manually trigger compilation. + // The simplest usage is InkCompiler.CompileInk(inkFile). + // You can also specify if the compilation should be immediate or async, and provide a callback for when the queue completes. + // Logs are fired when compilation begins and completes. + + // To ensure that compilation always completes reliably, this class also manages delaying entering play mode and cancels builds kicked off while mid-compile. + + // InkCompiler is designed as a ScriptableObject and is saved to the Library folder so that the queue persists across compilation. + // The way we currently handle threads isn't great. I'd love for a member of the community to find a better way to do it! + #if UNITY_2020_1_OR_NEWER + [FilePath("Library/InkCompiler.asset", FilePathAttribute.Location.ProjectFolder)] + public class InkCompiler : ScriptableSingleton { + #else + public class InkCompiler : ScriptableObject { + #endif + #region Legacy ScriptableSingleton + #if !UNITY_2020_1_OR_NEWER + public static bool created { + get { + return (_instance != (UnityEngine.Object) null); + } + } + private static InkCompiler _instance; + public static InkCompiler instance { + get { + if(!created) + LoadOrCreateInstance(); + return _instance; + } private set { + if(_instance == value) return; + _instance = value; + } + } + + static string absoluteSavePath { + get { + return System.IO.Path.GetFullPath(System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(),"Library","InkCompiler.asset")); + } + } + public static void LoadOrCreateInstance () { + InternalEditorUtility.LoadSerializedFileAndForget(absoluteSavePath); + if(created) { + if(InkEditorUtils.isFirstCompile) { + ClearCompilationStacks(); + } + } else { + instance = ScriptableObject.CreateInstance(); + instance.hideFlags = HideFlags.HideAndDontSave; + } + } + public void Save (bool saveAsText) { + InternalEditorUtility.SaveToSerializedFileAndForget((UnityEngine.Object[]) new InkCompiler[1] {this}, absoluteSavePath, saveAsText); + } + + protected InkCompiler () { + if (created) + Debug.LogError((object) "ScriptableSingleton already exists. Did you query the singleton in a constructor?"); + else { + instance = this; + } + } + #endif + #endregion + + + #region Public Facing + // If any items are queued, compiling, or complete! + // If any items are in the queue, one is guaranteed to be compiling (or should begin to or complete imminently). + public static bool executingCompilationStack { + get { + return instance.compilationStack.Count > 0; + } + } + + // This runs once when the compilation stack completes. + public delegate void OnCompleteInkCompliationStackEvent (InkFile[] inkFiles); + public static event OnCompleteInkCompliationStackEvent OnCompileInk; + + + [Serializable] + public enum CompilationStackItemState { + // Default state, item is about to be queued for compilation + Queued, + + // Item is now owned by the thread pool and being compiled + Compiling, + + // Compilation has finished, item to be processed for errors and result handled + Complete, + } + + + public static void CompileInk (params InkFile[] inkFiles) { + CompileInk(inkFiles, false, null); + } + public static void CompileInk (InkFile[] inkFiles, bool immediate, Action onComplete = null) { + if(inkFiles == null || inkFiles.Length == 0) return; + #if UNITY_2019_4_OR_NEWER + if(!disallowedAutoRefresh) { + disallowedAutoRefresh = true; + try { + AssetDatabase.DisallowAutoRefresh(); + } catch (Exception e) { + Debug.LogWarning("Failed DisallowAutoRefresh "+e); + } + } + #endif + + InkLibrary.Validate(); + if(onComplete != null) onCompleteActions.Add(onComplete); + StringBuilder filesCompiledLog = new StringBuilder("Files compiled:"); + foreach (var inkFile in inkFiles) filesCompiledLog.AppendLine().Append(inkFile.filePath); + + StringBuilder outputLog = new StringBuilder (); + outputLog.Append ("Ink compilation started at "); + outputLog.AppendLine (DateTime.Now.ToLongTimeString ()); + outputLog.Append (filesCompiledLog.ToString()); + Debug.Log(outputLog); + + foreach(var inkFile in inkFiles) { + CompileInkInternal (inkFile, immediate); + } + } + + + public static void SetBuildBlocked () { + buildBlocked = true; + } + + + public static void AddToPendingCompilationStack (string filePath) { + if(!instance.pendingCompilationStack.Contains(filePath)) { + instance.pendingCompilationStack.Add(filePath); + instance.Save(true); + } + } + + public static void RemoveFromPendingCompilationStack (InkFile inkFile) { + bool anyChange = false; + anyChange = instance.pendingCompilationStack.Remove(inkFile.filePath) || anyChange; + foreach(var includeFile in inkFile.includesInkFiles) { + anyChange = instance.pendingCompilationStack.Remove(includeFile.filePath) || anyChange; + } + if(anyChange) + instance.Save(true); + } + + public static bool AnyOfStateInCompilationStack (CompilationStackItemState state) { + foreach(var compilationStackItem in instance.compilationStack) { + if(compilationStackItem.state == state) + return true; + } + return false; + } + public static int CountOfStateInCompilationStack (CompilationStackItemState state) { + int count = 0; + foreach(var compilationStackItem in instance.compilationStack) { + if(compilationStackItem.state == state) + count++; + } + return count; + } + static CompilationStackItem GetCurrentlyCompilingFile () { + foreach(var compilationStackItem in instance.compilationStack) { + if(compilationStackItem.state == CompilationStackItemState.Compiling) { + return compilationStackItem; + } + } + return null; + } + + public static bool IsInkFileOnCompilationStack (InkFile inkFile) { + foreach(var compilationStackItem in instance.compilationStack) { + if(compilationStackItem.inkFile == inkFile) + return true; + } + return false; + } + + // Find all the master ink files in a list of assets given by path. + public static List GetUniqueMasterInkFilesToCompile (List importedInkAssets) { + List masterInkFiles = new List(); + foreach (var importedAssetPath in importedInkAssets) { + foreach(var masterInkFile in GetMasterFilesIncludingInkAssetPath(importedAssetPath)) { + if (!masterInkFiles.Contains(masterInkFile) && InkSettings.instance.ShouldCompileInkFileAutomatically(masterInkFile)) { + masterInkFiles.Add(masterInkFile); + } + } + } + return masterInkFiles; + + // An ink file might actually have several owners! Return them all. + IEnumerable GetMasterFilesIncludingInkAssetPath (string importedAssetPath) { + InkFile inkFile = InkLibrary.GetInkFileWithPath(importedAssetPath); + // Trying to catch a rare (and not especially important) bug that seems to happen occasionally when opening a project + // It's probably this - I've noticed it before in another context. + Debug.Assert(InkSettings.instance != null, "No ink settings file. This is a bug. For now you should be able to fix this via Assets > Rebuild Ink Library"); + // I've caught it here before + Debug.Assert(inkFile != null, "No internal InkFile reference at path "+importedAssetPath+". This is a bug. For now you can fix this via Assets > Rebuild Ink Library"); + Debug.Assert(inkFile != null); + return inkFile.masterInkFilesIncludingSelf; + } + } + #endregion + + + #region Static Private Variables + // If we just blocked a build because of an ink compile + static bool buildBlocked = false; + // If we just blocked entering play mode because of an ink compile + static bool playModeBlocked = false; + + + // Track if we've currently locked compilation of Unity C# Scripts + static bool hasLockedUnityCompilation = false; + + // When compiling we call AssetDatabase.DisallowAutoRefresh. + // We NEED to remember to re-allow it or unity stops registering file changes! + // The issue is that you need to pair calls perfectly, and you can't even use a try-catch to get around it. + // So - we cache if we've disabled auto refresh here, since this persists across plays. + static bool disallowedAutoRefresh { + get => SessionState.GetBool("InkLibraryDisallowedAutoRefresh", false); + set => SessionState.SetBool("InkLibraryDisallowedAutoRefresh", value); + } + + // Actions that are passed into the CompileInk function, to run and then clear when we complete the compilation stack. + // To recieve an event each time the stack completes, see OnCompileInk. + static List onCompleteActions = new List(); + + // Thread lock + static bool compileThreadActive { + get { + lock(_compileThreadActiveLock) { + return _compileThreadActive; + } + } + set { + lock(_compileThreadActiveLock) { + _compileThreadActive = value; + } + } + } + static bool _compileThreadActive; + static object _compileThreadActiveLock = new object(); + #endregion + + #if UNITY_2020_2_OR_NEWER + // ID for the Unity Progress API, which shows progress of the compile in the bottom right of Unity. + static int compileProgressID; + #endif + + #region Serialized Private Variables + // If InkSettings' delayInPlayMode option is true, dirty files are added here when they're changed in play mode + // This ensures they're remembered when you exit play mode and can be compiled + // TODO - It might be safer for this to track the DefaultAsset for the ink file, rather than the path? + [SerializeField] + List pendingCompilationStack = new List(); + + // The state of files currently being compiled. + [SerializeField] + List compilationStack = new List(); + #endregion + + [System.Serializable] + class CompilationStackItem { + public CompilationStackItemState state = CompilationStackItemState.Queued; + public bool immediate; + public InkFile inkFile; + public string compiledJson; + public string inkAbsoluteFilePath; + public string jsonAbsoluteFilePath; + public List logOutput = new List(); + public List unhandledErrorOutput = new List(); + public DateTime startTime; + public DateTime endTime; + + public float timeTaken { + get { + if(state == CompilationStackItemState.Complete) return (float)(endTime - startTime).TotalSeconds; + else return (float)(DateTime.Now - startTime).TotalSeconds; + } + } + + public CompilationStackItem () {} + + // Sets errors, warnings and todos to the ink file, and logs them to the console. + public void SetOutputLog () { + inkFile.errors.Clear(); + inkFile.warnings.Clear(); + inkFile.todos.Clear(); + + foreach(var childInkFile in inkFile.includesInkFiles) { + childInkFile.unhandledCompileErrors.Clear(); + childInkFile.errors.Clear(); + childInkFile.warnings.Clear(); + childInkFile.todos.Clear(); + } + + foreach(var output in logOutput) { + if(output.type == ErrorType.Error) { + inkFile.errors.Add(output); + Debug.LogError("Ink "+output.type+" for "+Path.GetFileName(inkFile.filePath)+": "+output.content + " (at "+output.relativeFilePath+":"+output.lineNumber+")", inkFile.inkAsset); + } else if (output.type == ErrorType.Warning) { + inkFile.warnings.Add(output); + Debug.LogWarning("Ink "+output.type+" for "+Path.GetFileName(inkFile.filePath)+": "+output.content + " (at "+output.relativeFilePath+" "+output.lineNumber+")", inkFile.inkAsset); + } else if (output.type == ErrorType.Author) { + inkFile.todos.Add(output); + if(InkSettings.instance.printInkLogsInConsoleOnCompile) + Debug.Log("Ink Log for "+Path.GetFileName(inkFile.filePath)+": "+output.content + " (at "+output.relativeFilePath+" "+output.lineNumber+")", inkFile.inkAsset); + } + } + } + } + + + #region Init, Update, Saving + // Ensure we save the InkCompiler state when we save assets. + class AssetSaver : UnityEditor.AssetModificationProcessor { + static string[] OnWillSaveAssets(string[] paths) { + InkCompiler.instance.Save(true); + return paths; + } + } + + // This is called when Unity recompiles. + [InitializeOnLoadMethod] + static void OnProjectLoadedInEditor() { + #if UNITY_2017_1_OR_NEWER + EditorApplication.playModeStateChanged += OnPlayModeChange; + #else + EditorApplication.playmodeStateChanged += LegacyOnPlayModeChange; + #endif + EditorApplication.update += Update; + // I really don't know if this can fire, since it assumes that it compiled so can't have been locked. But safety first! + EditorApplication.UnlockReloadAssemblies(); + #if UNITY_2019_4_OR_NEWER + // This one, on the other hand, seems to actually occur sometimes - presumably because c# compiles at the same time as the ink. + if(disallowedAutoRefresh) { + disallowedAutoRefresh = false; + try { + AssetDatabase.AllowAutoRefresh(); + } catch (Exception e) { + Debug.LogWarning("Failed AllowAutoRefresh "+e); + } + } + #endif + } + + // Update loop, using the EditorApplication.update callback. + private static void Update () { + #if UNITY_2020_1_OR_NEWER + // If we're not compiling but have locked C# compilation then now is the time to reset + if (!executingCompilationStack && hasLockedUnityCompilation) { + hasLockedUnityCompilation = false; + EditorApplication.UnlockReloadAssemblies(); + } + #else + // If we're not compiling but have locked C# compilation then now is the time to reset + if ((!InkLibrary.created || !compiling) && hasLockedUnityCompilation) { + hasLockedUnityCompilation = false; + EditorApplication.UnlockReloadAssemblies(); + } + if(!InkLibrary.created) + return; + #endif + + // If we're working through the stack. This is true as soon as an item is added to the stack. + if(executingCompilationStack) { + // Check for timeouts, in case of an unhandled bug with this system/the ink compiler! + for (int i = instance.compilationStack.Count - 1; i >= 0; i--) { + var compilingFile = instance.compilationStack [i]; + if (compilingFile.state == CompilationStackItemState.Compiling) { + if (compilingFile.timeTaken > InkSettings.instance.compileTimeout) { + // TODO - Cancel the thread if it's still going. Not critical, since its kinda fine if it compiles a bit later, but it's not clear. + compileThreadActive = false; + RemoveCompilingFile(i); + Debug.LogError("Ink Compiler timed out for "+compilingFile.inkAbsoluteFilePath+".\nCompilation should never take more than a few seconds, but for large projects or slow computers you may want to increase the timeout time in the InkSettings file.\nIf this persists there may be another issue; or else check an ink file exists at this path and try Assets/Recompile Ink, else please report as a bug with the following error log at this address: https://github.com/inkle/ink/issues\nError log:\n"+string.Join("\n",compilingFile.unhandledErrorOutput.ToArray())); + TryCompileNextFileInStack(); + } + } + } + + // When all files have compiled, run the complete function. + if(!AnyOfStateInCompilationStack(CompilationStackItemState.Compiling)) { + if(!AnyOfStateInCompilationStack(CompilationStackItemState.Queued)) { + OnCompleteCompilationStack(); + } else { + // We used to avoid calling this here in favour of calling it CompileInkThreaded but it seems that it doesn't run when called there, for some reason. + // If someone can make this work please let me know! + TryCompileNextFileInStack(); + } + } + // When the current item being compiled using threads has finished, we set compileThreadActive to false. + // Here we then set the compiling file's state from Compiling to Complete. + // This roundabout way of doing things ensures that all CompilationStackItem code runs entirely outside of the thread. + else if(!compileThreadActive) { + for (int i = instance.compilationStack.Count - 1; i >= 0; i--) { + var compilingFile = instance.compilationStack [i]; + if (compilingFile.state == CompilationStackItemState.Compiling) { + CompleteCompilingFile(compilingFile); + break; + } + } + } + } + + + // We don't show a progress bar on Linux (there appeared to be a Unity bug on an earlier version), so skip this step there. + #if !UNITY_EDITOR_LINUX + UpdateProgressBar(); + #endif + } + #endregion + + + #region Compilation + + // Move files from the pendingCompilationStack to the compilationStack + static void CompilePendingFiles () { + InkLibrary.CreateOrReadUpdatedInkFiles (instance.pendingCompilationStack); + foreach (var pendingMasterFile in GetUniqueMasterInkFilesToCompile(instance.pendingCompilationStack)) + CompileInk(pendingMasterFile); + } + + /// + /// Starts a System.Process that compiles a master ink file, creating a playable JSON file that can be parsed by the Ink.Story class + /// + /// Ink file. + private static void CompileInkInternal (InkFile inkFile, bool immediate) { + if(inkFile == null) { + Debug.LogError("Tried to compile ink file but input was null."); + return; + } + if(!inkFile.isMaster) + Debug.LogWarning("Compiling InkFile which is an include. Any file created is likely to be invalid. Did you mean to call CompileInk on inkFile.master?"); + + // If we've not yet locked C# compilation do so now + if (!hasLockedUnityCompilation) + { + hasLockedUnityCompilation = true; + EditorApplication.LockReloadAssemblies(); + } + + RemoveFromPendingCompilationStack(inkFile); + if(IsInkFileOnCompilationStack(inkFile)) { + UnityEngine.Debug.LogWarning("Tried compiling ink file, but file is already compiling. "+inkFile.filePath); + return; + } + + string inputPath = InkEditorUtils.CombinePaths(inkFile.absoluteFolderPath, Path.GetFileName(inkFile.filePath)); + Debug.Assert(inkFile.absoluteFilePath == inputPath); + + CompilationStackItem pendingFile = new CompilationStackItem + { + inkFile = InkLibrary.GetInkFileWithAbsolutePath(inputPath), + inkAbsoluteFilePath = inputPath, + jsonAbsoluteFilePath = inkFile.absoluteJSONPath, + state = CompilationStackItemState.Queued, + immediate = immediate + }; + + if(instance.compilationStack.Count == 0) OnBeginCompilationStack(); + instance.compilationStack.Add(pendingFile); + instance.Save(true); + + TryCompileNextFileInStack(); + } + + private static void TryCompileNextFileInStack () { + if(!executingCompilationStack) return; + if(AnyOfStateInCompilationStack(CompilationStackItemState.Compiling)) return; + + // Find the next file to compile! + CompilationStackItem fileToCompile = null; + foreach(var compilationItem in instance.compilationStack) { + if(compilationItem.state == CompilationStackItemState.Queued) { + fileToCompile = compilationItem; + break; + } + } + + // If a file was found, compile it according to its settings. + if(fileToCompile != null) { + BeginCompilingFile(fileToCompile); + if(fileToCompile.immediate) { + CompileInkThreaded(fileToCompile); + CompleteCompilingFile(fileToCompile); + } else { + if(EditorApplication.isCompiling) Debug.LogWarning("Was compiling scripts when ink compilation started! This seems to cause the thread to cancel and complete, but the work isn't done. It may cause a timeout."); + compileThreadActive = true; + ThreadPool.QueueUserWorkItem(CompileInkThreaded, fileToCompile); + // CompleteCompilingFile is called in Update when compileThreadActive becomes false. + } + } + } + + // Removes a file from the compilation stack. + static void RemoveCompilingFile (int index) { + instance.compilationStack.RemoveAt(index); + instance.Save(true); + // Progress bar prevents delayCall callback from firing in Linux Editor, locking the + // compilation until it times out. Let's just not show progress bars in Linux Editor + #if !UNITY_EDITOR_LINUX + if (instance.compilationStack.Count == 0) EditorUtility.ClearProgressBar(); + #endif + } + + // Marks a CompilationStackItem as Compiling + private static void BeginCompilingFile(CompilationStackItem item) { + if(item.state != CompilationStackItemState.Queued) { + Debug.LogError("Cannot begin compiling ink file because it is "+item.state+"! This is most likely a threading bug. Please report this!"); + return; + } + item.state = CompilationStackItemState.Compiling; + item.startTime = DateTime.Now; + #if UNITY_2020_2_OR_NEWER + Progress.SetStepLabel(compileProgressID, item.inkFile.filePath); + Progress.Report(compileProgressID, instance.compilationStack.IndexOf(item), instance.compilationStack.Count); + #endif + } + + // Marks a CompilationStackItem as Complete + private static void CompleteCompilingFile(CompilationStackItem item) { + if(item.state != CompilationStackItemState.Compiling) { + Debug.LogError("Cannot complete compiling ink file because it is "+item.state+"! This is most likely a threading bug. Please report this!"); + return; + } + item.state = CompilationStackItemState.Complete; + item.endTime = DateTime.Now; + if (item.timeTaken > InkSettings.instance.compileTimeout * 0.6f) + Debug.LogWarning ("Compilation for "+Path.GetFileName(item.inkFile.filePath)+" took over 60% of the time required to timeout the compiler. Consider increasing the compile timeout on the InkSettings file."); + + // If there's nothing left to compile, we can mark the stack as done! + if(!AnyOfStateInCompilationStack(CompilationStackItemState.Compiling) && !AnyOfStateInCompilationStack(CompilationStackItemState.Queued)) + OnCompleteCompilationStack(); + } + + // Runs a new instance of Ink.Compiler, performing the actual compilation process! + // Can be run from a thread or syncronously. + // Ink is not threadsafe, and so this function should never be run twice simultaneously. + // For this reason, this function doesn't set CompilationStackItem.state. + private static void CompileInkThreaded(object itemObj) { + CompilationStackItem item = (CompilationStackItem) itemObj; + if(item.state != CompilationStackItemState.Compiling) Debug.LogError("File passed to CompileInkThreaded is not in Compiling state."); + + var inputString = File.ReadAllText(item.inkAbsoluteFilePath); + var compiler = new Compiler(inputString, new Compiler.Options + { + countAllVisits = true, + fileHandler = new UnityInkFileHandler(Path.GetDirectoryName(item.inkAbsoluteFilePath)), + errorHandler = (string message, ErrorType type) => { + InkCompilerLog log; + if(InkCompilerLog.TryParse(message, out log)) { + if(string.IsNullOrEmpty(log.relativeFilePath)) log.relativeFilePath = Path.GetFileName(item.inkAbsoluteFilePath); + item.logOutput.Add(log); + } else { + Debug.LogWarning("Couldn't parse log "+message); + } + } + }); + + try { + var compiledStory = compiler.Compile(); + if (compiledStory != null) + item.compiledJson = compiledStory.ToJson(); + } catch (SystemException e) { + item.unhandledErrorOutput.Add(string.Format( + "Ink Compiler threw exception \nError: {0}\n---- Trace ----\n{1}\n--------\n", e.Message, + e.StackTrace)); + } + + // This MUST be the very last thing to occur in this function! + compileThreadActive = false; + } + + // When the compilation stack first gains an item + private static void OnBeginCompilationStack () { + #if UNITY_2020_2_OR_NEWER + compileProgressID = Progress.Start("Compiling Ink", null, Progress.Options.None, -1); + #endif + } + + // When all files in stack have been compiled. + // This is called via update because Process events run in another thread. + // It's now also called via CompleteCompilingFile, which enables immediate mode compliation to run synchronously! + private static void OnCompleteCompilationStack () { + if(AnyOfStateInCompilationStack(CompilationStackItemState.Queued)) { + Debug.LogError("OnCompleteCompilationStack was called, but a file is now in the queue!"); + return; + } + if(AnyOfStateInCompilationStack(CompilationStackItemState.Compiling)) { + Debug.LogError("OnCompleteCompilationStack was called, but a file is now compiling!"); + return; + } + // Clone and clear the list. This is a surefire way to ensure the list is cleared in case of unhandled errors in this code. + // A Try-catch would be better but I'm debugging blind as I write this and the nuclear option will definitely work! + List compilationStack = new List(instance.compilationStack); + instance.compilationStack.Clear(); + instance.Save(true); + + + + // Create and import compiled files + AssetDatabase.StartAssetEditing(); + foreach (var compilingFile in compilationStack) { + // Complete status is also set when an error occured, in these cases 'compiledJson' will be null so there's no import to process + if (compilingFile.compiledJson == null) continue; + + // Write new compiled data to the file system + File.WriteAllText(compilingFile.jsonAbsoluteFilePath, compilingFile.compiledJson, Encoding.UTF8); + if(compilingFile.inkFile.inkAsset != null) AssetDatabase.ImportAsset(compilingFile.inkFile.jsonPath); + } + AssetDatabase.StopAssetEditing(); + + + // Sets output info for each InkFile (todos, warnings and errors); produces and fires the post-compliation log + bool errorsFound = false; + StringBuilder filesCompiledLog = new StringBuilder("Files compiled:"); + foreach (var compilingFile in compilationStack) { + if(compilingFile.inkFile.inkAsset != null) { + // Load and store a reference to the compiled file + compilingFile.inkFile.FindCompiledJSONAsset(); + + filesCompiledLog.AppendLine().Append(compilingFile.inkFile.filePath); + filesCompiledLog.Append(string.Format(" ({0}s)", compilingFile.timeTaken)); + if(compilingFile.unhandledErrorOutput.Count > 0) { + filesCompiledLog.Append(" (With unhandled error)"); + StringBuilder errorLog = new StringBuilder (); + errorLog.Append ("Unhandled error(s) occurred compiling Ink file "); + errorLog.Append ("'"); + errorLog.Append (compilingFile.inkFile.filePath); + errorLog.Append ("'"); + errorLog.AppendLine ("! You may be able to resolve your issue by using Edit > Rebuild Ink Library."); + errorLog.AppendLine ("Please report following error(s) as a bug:"); + foreach (var error in compilingFile.unhandledErrorOutput) + errorLog.AppendLine (error); + Debug.LogError(errorLog); + compilingFile.inkFile.unhandledCompileErrors = compilingFile.unhandledErrorOutput; + errorsFound = true; + } else { + compilingFile.SetOutputLog(); + bool errorsInEntireStory = false; + bool warningsInEntireStory = false; + foreach(var inkFile in compilingFile.inkFile.includesInkFiles) { + if(inkFile.hasErrors) { + errorsInEntireStory = true; + } + if(inkFile.hasWarnings) { + warningsInEntireStory = true; + } + } + if(errorsInEntireStory) { + filesCompiledLog.Append(" (With error)"); + errorsFound = true; + } + if(warningsInEntireStory) { + filesCompiledLog.Append(" (With warning)"); + } + } + } else { + filesCompiledLog.AppendLine().Append(compilingFile.inkAbsoluteFilePath); + filesCompiledLog.Append(" (With post-compile missing file error)"); + Debug.LogError("Ink file at "+compilingFile.inkAbsoluteFilePath+" was not found after compilation"); + } + } + + StringBuilder outputLog = new StringBuilder (); + if(errorsFound) { + outputLog.Append ("Ink compilation completed with errors at "); + outputLog.AppendLine (DateTime.Now.ToLongTimeString ()); + outputLog.Append (filesCompiledLog.ToString()); + Debug.LogError(outputLog); + } else { + outputLog.Append ("Ink compilation completed at "); + outputLog.AppendLine (DateTime.Now.ToLongTimeString ()); + outputLog.Append (filesCompiledLog.ToString()); + Debug.Log(outputLog); + } + + + // Clean up locks and progress bars + #if UNITY_2020_2_OR_NEWER + Progress.Remove(compileProgressID); + compileProgressID = -1; + #endif + + #if !UNITY_EDITOR_LINUX + EditorUtility.ClearProgressBar(); + #endif + + #if UNITY_2019_4_OR_NEWER + if(disallowedAutoRefresh) { + disallowedAutoRefresh = false; + try { + AssetDatabase.AllowAutoRefresh(); + } catch (Exception e) { + Debug.LogWarning("Failed AllowAutoRefresh "+e); + } + } + #endif + + // This is now allowed, if compiled manually. I've left this code commented out because at some point we might want to track what caused a file to compile. + // if(EditorApplication.isPlayingOrWillChangePlaymode && InkSettings.instance.delayInPlayMode) { + // Debug.LogError("Ink just finished recompiling while in play mode. This should never happen when InkSettings.instance.delayInPlayMode is true!"); + // } + + buildBlocked = false; + + + // Fires completion events + foreach(var onCompleteAction in onCompleteActions) { + if(onCompleteAction != null) onCompleteAction(); + } + onCompleteActions.Clear(); + + if (OnCompileInk != null) { + InkFile[] inkFilesCompiled = new InkFile[compilationStack.Count]; + for (int i = 0; i < compilationStack.Count; i++) { + inkFilesCompiled[i] = compilationStack[i].inkFile; + } + if(OnCompileInk != null) OnCompileInk (inkFilesCompiled); + } + + + // If we wanted to enter play mode but were blocked because of ink compliation, enter play mode now. + if(playModeBlocked) { + playModeBlocked = false; + if(!errorsFound) { + // Delaying gives the editor a frame to clear the progress bar. + EditorApplication.delayCall += () => { + Debug.Log("Compilation completed, entering play mode."); + EditorApplication.isPlaying = true; + }; + } else { + Debug.LogWarning("Play mode not entered after ink compilation because ink had errors."); + } + } + + } + #endregion + + + #region Progress Bar + static void UpdateProgressBar () { + if(instance.compilationStack.Count == 0) return; + if(buildBlocked || playModeBlocked || EditorApplication.isPlaying) ShowProgressBar(); + else EditorUtility.ClearProgressBar(); + } + + public static void ShowProgressBar () { + int numCompiling = CountOfStateInCompilationStack(CompilationStackItemState.Compiling); + var compilingFile = GetCurrentlyCompilingFile(); + string message = ""; + if(compilingFile == null) message += "Compiling..."; + else message += "Compiling "+compilingFile.inkFile.inkAsset.name+" for "+compilingFile.timeTaken+"s"; + message += "\n.Ink File "+(instance.compilationStack.Count-numCompiling)+" of "+instance.compilationStack.Count+"."; + if(playModeBlocked) message += " Will enter play mode when complete."; + EditorUtility.DisplayProgressBar("Compiling Ink...", message, GetEstimatedCompilationProgress()); + } + + public static float GetEstimatedCompilationProgress () { + if(!executingCompilationStack) return 1; + float progress = 0; + foreach (var compilingFile in instance.compilationStack) { + if (compilingFile.state == CompilationStackItemState.Compiling) + progress += compilingFile.timeTaken / InkSettings.instance.compileTimeout; + if (compilingFile.state == CompilationStackItemState.Complete) + progress += 1; + } + progress /= instance.compilationStack.Count; + return progress; + } + #endregion + + + #region Prevent entering Play Mode while mid-compile + #if UNITY_2017_1_OR_NEWER + static void OnPlayModeChange (PlayModeStateChange mode) { + if(mode == PlayModeStateChange.EnteredEditMode && instance.pendingCompilationStack.Count > 0) + CompilePendingFiles(); + if(mode == PlayModeStateChange.ExitingEditMode && executingCompilationStack) + BlockPlayMode(); + if(mode == PlayModeStateChange.EnteredPlayMode && executingCompilationStack) + EnteredPlayModeWhenCompiling(); + } + #else + static void LegacyOnPlayModeChange () { + if(!EditorApplication.isPlayingOrWillChangePlaymode && EditorApplication.isPlaying && instance.pendingCompilationStack.Count > 0) + CompilePendingFiles(); + if(EditorApplication.isPlayingOrWillChangePlaymode && !EditorApplication.isPlaying && compiling) + BlockPlayMode(); + if(EditorApplication.isPlayingOrWillChangePlaymode && EditorApplication.isPlaying && compiling) + EnteredPlayModeWhenCompiling(); + } + #endif + + static void BlockPlayMode () { + EditorApplication.isPlaying = false; + var percentage = String.Format("{0:P0}.", GetEstimatedCompilationProgress()); + Debug.LogWarning("Delayed entering play mode because Ink is still compiling ("+percentage+"). Will enter play mode on completion."); + playModeBlocked = true; + } + + static void EnteredPlayModeWhenCompiling () { + Debug.LogError("Entered Play Mode while Ink was still compiling! Your story will not be up to date. Recommend exiting and re-entering play mode.\nWe normally delay entering play mode when compiling, so you've found an edge case!"); + } + #endregion + } +} \ No newline at end of file diff --git a/Assets/Ink/Editor/Core/Compiler/UnityInkFileHandler.cs b/Assets/Ink/Editor/Core/Compiler/UnityInkFileHandler.cs new file mode 100644 index 0000000..96e07fb --- /dev/null +++ b/Assets/Ink/Editor/Core/Compiler/UnityInkFileHandler.cs @@ -0,0 +1,23 @@ +using Ink; +using System.IO; + +// Utility class for the ink compiler, used to work out how to find include files and their contents +public class UnityInkFileHandler : IFileHandler { + private readonly string rootDirectory; + + public UnityInkFileHandler(string rootDirectory) + { + this.rootDirectory = rootDirectory; + } + + public string ResolveInkFilename(string includeName) + { + // Convert to Unix style, and then use FileInfo.FullName to parse any ..\ + return new FileInfo(Path.Combine(rootDirectory, includeName).Replace('\\', '/')).FullName; + } + + public string LoadInkFileContents(string fullFilename) + { + return File.ReadAllText(fullFilename); + } +} \ No newline at end of file diff --git a/Assets/Ink/Editor/Core/Ink Library/InkCompilerLog.cs b/Assets/Ink/Editor/Core/Ink Library/InkCompilerLog.cs new file mode 100644 index 0000000..bd3b7a4 --- /dev/null +++ b/Assets/Ink/Editor/Core/Ink Library/InkCompilerLog.cs @@ -0,0 +1,64 @@ +using System.Text.RegularExpressions; +using Debug = UnityEngine.Debug; + +namespace Ink.UnityIntegration +{ + [System.Serializable] + public class InkCompilerLog { + public Ink.ErrorType type; + public string content; + public string relativeFilePath; + public int lineNumber; + + public InkCompilerLog (Ink.ErrorType type, string content, string relativeFilePath, int lineNumber = -1) { + this.type = type; + this.content = content; + this.relativeFilePath = relativeFilePath; + this.lineNumber = lineNumber; + } + + public string GetAbsoluteFilePath (InkFile masterInkFile) { + Debug.Log(masterInkFile.absoluteFolderPath); + Debug.Log(relativeFilePath); + return System.IO.Path.Combine(masterInkFile.absoluteFolderPath, relativeFilePath); + } + + public static bool TryParse (string rawLog, out InkCompilerLog log) { + var match = _errorRegex.Match(rawLog); + if (match.Success) { + Ink.ErrorType errorType = Ink.ErrorType.Author; + string relativeFilePath = null; + int lineNo = -1; + string message = null; + + var errorTypeCapture = match.Groups["errorType"]; + if( errorTypeCapture != null ) { + var errorTypeStr = errorTypeCapture.Value; + if(errorTypeStr == "AUTHOR" || errorTypeStr == "TODO") errorType = Ink.ErrorType.Author; + else if(errorTypeStr == "WARNING") errorType = Ink.ErrorType.Warning; + else if(errorTypeStr == "ERROR") errorType = Ink.ErrorType.Error; + else Debug.LogWarning("Could not parse error type from "+errorTypeStr); + } + + var filenameCapture = match.Groups["filename"]; + if (filenameCapture != null) + relativeFilePath = filenameCapture.Value; + + var lineNoCapture = match.Groups["lineNo"]; + if (lineNoCapture != null) + lineNo = int.Parse (lineNoCapture.Value); + + var messageCapture = match.Groups["message"]; + if (messageCapture != null) + message = messageCapture.Value.Trim(); + log = new InkCompilerLog(errorType, message, relativeFilePath, lineNo); + return true; + } else { + Debug.LogWarning("Could not parse InkFileLog from log: "+rawLog); + log = null; + return false; + } + } + private static Regex _errorRegex = new Regex(@"(?ERROR|WARNING|TODO):(?:\s(?:'(?[^']*)'\s)?line (?\d+):)?(?.*)"); + } +} \ No newline at end of file diff --git a/Assets/Ink/Editor/Core/Ink Library/InkFile.cs b/Assets/Ink/Editor/Core/Ink Library/InkFile.cs new file mode 100644 index 0000000..f82af4d --- /dev/null +++ b/Assets/Ink/Editor/Core/Ink Library/InkFile.cs @@ -0,0 +1,333 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEngine; + +namespace Ink.UnityIntegration { + // Helper class for ink files that maintains INCLUDE connections between ink files + [Serializable] + public class InkFile { + // Master files are those that can be compiled + public bool isMaster => !isIncludeFile || isMarkedToCompileAsMasterFile; + // Typically master files are simply those that aren't INCLUDED by another file, but they can also be marked to master files. + public bool isMarkedToCompileAsMasterFile => InkSettings.instance.includeFilesToCompileAsMasterFiles.Contains(inkAsset); + public bool compileAutomatically => InkSettings.instance.filesToCompileAutomatically.Contains(inkAsset); + // A reference to the ink file + public DefaultAsset inkAsset; + + //specify json destination folder (if None, default to same folder as ink file) + public DefaultAsset jsonAssetDirectory; + + // The compiled json file. Use this to start a story. + public TextAsset jsonAsset; + + // The file path relative to the Assets folder (Assets/Ink/Story.ink) + public string filePath { + get { + if(inkAsset == null) + return null; + + return InkEditorUtils.SanitizePathString(AssetDatabase.GetAssetPath(inkAsset)); + } + } + + // The full file path (C:/Users/Inkle/HeavensVault/Assets/Ink/Story.ink) + public string absoluteFilePath { + get { + if(inkAsset == null) + return null; + return InkEditorUtils.UnityRelativeToAbsolutePath(filePath); + } + } + + public string absoluteFolderPath { + get { + return InkEditorUtils.SanitizePathString(Path.GetDirectoryName(absoluteFilePath)); + } + } + + // The path of any compiled json file. Relative to assets folder. + public string jsonPath { + get { + var _filePath = filePath; + Debug.Assert(!string.IsNullOrEmpty(_filePath), "File path for ink file is null! The ink library requires rebuilding. Asset: "+inkAsset); + + DefaultAsset jsonFolder = jsonAssetDirectory; + if (jsonFolder == null) // no path specified for this specific file + { + if(InkSettings.instance.defaultJsonAssetPath != null) + { + // use default path in InkSettings + jsonFolder = InkSettings.instance.defaultJsonAssetPath; + } + + if (jsonFolder == null) + { + //fallback to same folder as .ink file + jsonFolder = AssetDatabase.LoadAssetAtPath(Path.GetDirectoryName(_filePath)); + } + } + + Debug.Assert(jsonFolder != null, "JSON folder not found for ink file at path. File Path: "+_filePath+". Asset: "+inkAsset); + + string jsonPath = AssetDatabase.GetAssetPath(jsonFolder); + Debug.Assert(Directory.Exists(jsonPath), "JSON folder path is not a directory! Json Path: "+jsonPath+". Asset: "+inkAsset); + string strJsonAssetPath = InkEditorUtils.CombinePaths(jsonPath, Path.GetFileNameWithoutExtension(_filePath)) + ".json"; + return strJsonAssetPath; + } + } + + public string absoluteJSONPath { + get { + if(inkAsset == null) + return null; + return InkEditorUtils.UnityRelativeToAbsolutePath(jsonPath); + } + } + + + + + + + // Fatal unhandled errors that should be reported as compiler bugs. + public List unhandledCompileErrors = new List(); + public bool hasUnhandledCompileErrors { + get { + return unhandledCompileErrors.Count > 0; + } + } + + public List recursiveIncludeErrorPaths = new List(); + public bool hasRecursiveIncludeErrorPaths { + get { + return recursiveIncludeErrorPaths.Count > 0; + } + } + + // Fatal errors caused by errors in the user's ink script. + public List errors = new List(); + public bool hasErrors { + get { + return errors.Count > 0; + } + } + + public List warnings = new List(); + public bool hasWarnings { + get { + return warnings.Count > 0; + } + } + + public List todos = new List(); + public bool hasTodos { + get { + return todos.Count > 0; + } + } + + public bool requiresCompile { + get { + if(!isMaster) return false; + return jsonAsset == null || hasUnhandledCompileErrors || lastEditDate > lastCompileDate; + } + } + + /// + /// Gets the last compile date of the story. + /// + /// The last compile date of the story. + public DateTime lastCompileDate { + get { + if(isMaster) { + if(jsonAsset == null) + return default(DateTime); + + string fullJSONFilePath = InkEditorUtils.UnityRelativeToAbsolutePath(AssetDatabase.GetAssetPath(jsonAsset)); + return File.GetLastWriteTime(fullJSONFilePath); + } else { + return default(DateTime); + } + } + } + + /// + /// Gets the last edit date of the file. + /// + /// The last edit date of the file. + public DateTime lastEditDate { + get { + return File.GetLastWriteTime(absoluteFilePath); + } + } + + public List masterInkAssets = new List(); + public IEnumerable masterInkFiles { + get { + foreach(var masterInkAsset in masterInkAssets) { + yield return InkLibrary.GetInkFileWithFile(masterInkAsset); + } + } + } + public IEnumerable masterInkFilesIncludingSelf { + get { + // A file can be both a master file AND be included by many other files. Return all the master files fitting this description. + if(isMaster) yield return this; + foreach(var masterInkFile in masterInkFiles) { + yield return masterInkFile; + } + } + } + + // Is this ink file included by another ink file? + public bool isIncludeFile { + get { + return masterInkAssets.Count > 0; + } + } + + + // The files referenced by this file via the INCLUDE keyword + // We cache the paths of the files to be included for performance, giving us more freedom to refresh the actual includes list without needing to parse all the text. + public List localIncludePaths = new List(); + // The asset references for the included files. Unlike localIncludePaths this contains include files + public List includes = new List(); + // The InkFiles of the includes of this file + public List includesInkFiles { + get { + List _includesInkFiles = new List(); + foreach(var child in includes) { + if(child == null) { + Debug.LogError("Error compiling ink: Ink file include in "+filePath+" is null.", inkAsset); + continue; + } + _includesInkFiles.Add(InkLibrary.GetInkFileWithFile(child)); + } + return _includesInkFiles; + } + } + + + + + + public InkFile (DefaultAsset inkAsset) { + Debug.Assert(inkAsset != null); + this.inkAsset = inkAsset; + + ParseContent(); + // Should we run FindCompiledJSONAsset here? + } + + public void FindCompiledJSONAsset () { + Debug.Assert(inkAsset != null); + jsonAsset = AssetDatabase.LoadAssetAtPath(jsonPath); + } + + public void ClearAllHierarchyConnections() { + masterInkAssets.Clear(); + includes.Clear(); + } + + + + + + + +// // Returns the contents of the .ink file. + public string GetFileContents () { + if(inkAsset == null) { + Debug.LogWarning("Ink file asset is null! Rebuild library using Assets > Rebuild Ink Library"); + return ""; + } + return File.ReadAllText(absoluteFilePath); + } + + // Parses the ink file and caches any information we may want to access without incurring a performance cost. + // Currently this only scans for includePaths, which are later used by InkLibrary.RebuildInkFileConnections. + public void ParseContent () { + localIncludePaths.Clear(); + localIncludePaths.AddRange(InkIncludeParser.ParseIncludes(GetFileContents())); + } + + public static class InkIncludeParser { + static Regex _includeRegex; + static Regex includeRegex { + get { + if(_includeRegex == null) { + _includeRegex = new Regex (@"^\s*INCLUDE\s+([^\r\n]+)\r*$", RegexOptions.Multiline); + } + return _includeRegex; + } + } + public static IEnumerable ParseIncludes (string inkContents) { + return FindIncludes (EliminateComments(inkContents)); + } + + static string EliminateComments(string inkStr) { + var sb = new StringBuilder (); + int idx = 0; + while(idx < inkStr.Length) { + var commentStarterIdx = inkStr.IndexOf ('/', idx); + // Final string? + if (commentStarterIdx == -1 || commentStarterIdx >= inkStr.Length-2 ) { + sb.Append (inkStr.Substring (idx, inkStr.Length - idx)); + break; + } + sb.Append (inkStr.Substring (idx, commentStarterIdx - idx)); + var commentStarter = inkStr.Substring (commentStarterIdx, 2); + if (commentStarter == "//" || commentStarter == "/*") { + int endOfCommentIdx = -1; + // Single line comments + if (commentStarter == "//") { + endOfCommentIdx = inkStr.IndexOf ('\n', commentStarterIdx); + if (endOfCommentIdx == -1) + endOfCommentIdx = inkStr.Length; + else if (inkStr [endOfCommentIdx - 1] == '\r') + endOfCommentIdx = endOfCommentIdx - 1; + } + // Block comments + else if (commentStarter == "/*") { + endOfCommentIdx = inkStr.IndexOf ("*/", idx); + if (endOfCommentIdx == -1) + endOfCommentIdx = inkStr.Length; + else + endOfCommentIdx += 2; + // If there are *any* newlines, we should add one in here, + // so that lines are spit up correctly + if (inkStr.IndexOf ('\n', commentStarterIdx, endOfCommentIdx - commentStarterIdx) != -1) + sb.Append ("\n"); + } + // Skip over comment + if (endOfCommentIdx > -1) + idx = endOfCommentIdx; + } + // Normal slash we need, not a comment + else { + sb.Append ("/"); + idx = commentStarterIdx + 1; + } + } + return sb.ToString (); + } + static IEnumerable FindIncludes(string str) { + MatchCollection matches = includeRegex.Matches(str); + foreach (Match match in matches) + { + var capture = match.Groups [1].Captures [0]; + yield return capture.Value; + } + } + } + + + public override string ToString () { + return string.Format ("[InkFile: filePath={0}]", filePath); + } + } +} \ No newline at end of file diff --git a/Assets/Ink/Editor/Core/Ink Library/InkLibrary.cs b/Assets/Ink/Editor/Core/Ink Library/InkLibrary.cs new file mode 100644 index 0000000..8b49921 --- /dev/null +++ b/Assets/Ink/Editor/Core/Ink Library/InkLibrary.cs @@ -0,0 +1,552 @@ +using UnityEngine; +using UnityEditor; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Debug = UnityEngine.Debug; + +/// +/// Holds a reference to an InkFile object for every .ink file detected in the Assets folder. +/// Provides helper functions to easily obtain these files. +/// +namespace Ink.UnityIntegration { + #if UNITY_2020_1_OR_NEWER + [FilePath("Library/asset", FilePathAttribute.Location.ProjectFolder)] + public class InkLibrary : ScriptableSingleton, IEnumerable { + #else + public class InkLibrary : ScriptableObject, IEnumerable { + #endif + // Ink version. This should really come from the core ink code. + public static System.Version inkVersionCurrent = new System.Version(1,1,1); + public static System.Version unityIntegrationVersionCurrent = new System.Version(1,1,8); + + static string absoluteSavePath { + get { + return System.IO.Path.GetFullPath(System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(),"Library","asset")); + } + } + + #if !UNITY_2020_1_OR_NEWER + public static bool created { + get { + // If it's null, there's no InkLibrary loaded + return (_instance != (Object) null); + } + } + private static InkLibrary _instance; + public static InkLibrary instance { + get { + if(!created) + LoadOrCreateInstance(); + return _instance; + } private set { + if(_instance == value) return; + _instance = value; + } + } + + + // This occurs on recompile, creation and load (note that data has not necessarily been loaded at this point!) + protected InkLibrary () { + if (created) + Debug.LogError((object) "ScriptableSingleton already exists. Did you query the singleton in a constructor?"); + else { + instance = this; + } + } + + public static void LoadOrCreateInstance () { + InternalEditorUtility.LoadSerializedFileAndForget(absoluteSavePath); + if(created) { + if(InkEditorUtils.isFirstCompile) { + Validate(); + } + } else { + instance = ScriptableObject.CreateInstance(); + instance.hideFlags = HideFlags.HideAndDontSave; + Rebuild(); + } + } + + public void Save (bool saveAsText) { + if(!created) return; + InternalEditorUtility.SaveToSerializedFileAndForget((Object[]) new InkLibrary[1] {instance}, absoluteSavePath, saveAsText); + } + + static void EnsureCreated () { + if(!created) LoadOrCreateInstance(); + } + #endif + + public class AssetSaver : UnityEditor.AssetModificationProcessor { + static string[] OnWillSaveAssets(string[] paths) { + instance.Save(true); + return paths; + } + } + + public List inkLibrary = new List(); + Dictionary inkLibraryDictionary = new Dictionary(); + + public int Count { + get { + return inkLibrary.Count; + } + } + public InkFile this[int key] { + get { + return inkLibrary[key]; + } set { + inkLibrary[key] = value; + } + } + IEnumerator IEnumerable.GetEnumerator() { + return inkLibrary.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() { + return inkLibrary.GetEnumerator(); + } + + void OnValidate () { + BuildLookupDictionary(); + // This is experimental! I'd like to see if it fixes the issue where assets have not yet been imported. + EditorApplication.delayCall += () => { + Validate(); + }; + } + // After recompile, the data associated with the object is fetched (or whatever happens to it) by this point. + void OnEnable () { + // Deletes the persistent version of this asset that we used to use prior to 0.9.71 + if(!Application.isPlaying && EditorUtility.IsPersistent(this)) { + var path = AssetDatabase.GetAssetPath(this); + if(!string.IsNullOrEmpty(path)) { + #if !UNITY_2020_1_OR_NEWER + if(_instance == this) _instance = null; + #endif + AssetDatabase.DeleteAsset(path); + AssetDatabase.Refresh(); + return; + } + } + } + + static void BuildLookupDictionary () { + instance.inkLibraryDictionary.Clear(); + foreach(var inkFile in instance.inkLibrary) { + instance.inkLibraryDictionary.Add(inkFile.inkAsset, inkFile); + } + } + + /// + /// Checks if the library is corrupt and rebuilds if necessary. Returns true if the library was valid + /// + public static bool Validate () { + if(RequiresRebuild()) { + Rebuild(); + Debug.LogWarning("InkLibrary was invalid and has been rebuilt. This can occur if files are moved/deleted while the editor is closed. You can ignore this warning."); + return false; + } else { + return true; + } + } + + /// + /// Checks if the library is corrupt and requires a Rebuild. + /// This can happen when asset IDs change, causing the wrong file to be referenced. + /// This occassionally occurs from source control. + /// This is a fairly performant check. + /// + static bool RequiresRebuild () { + #if !UNITY_2020_1_OR_NEWER + EnsureCreated(); + #endif + foreach(var inkFile in instance.inkLibrary) { + if(inkFile == null) { + return true; + } + if(inkFile.inkAsset == null) { + // This can occur when the asset has not yet been imported! + return true; + } + if(!instance.inkLibraryDictionary.ContainsKey(inkFile.inkAsset)) { + return true; + } + foreach(var include in inkFile.includes) { + if(include == null) { + return true; + } + if(!instance.inkLibraryDictionary.ContainsKey(include)) { + return true; + } + } + } + return false; + } + + /// + /// Removes and null references in the library + /// + public static bool Clean () { + bool wasDirty = false; + for (int i = instance.Count - 1; i >= 0; i--) { + InkFile inkFile = instance[i]; + if (inkFile.inkAsset == null) { + RemoveAt(i); + wasDirty = true; + } + } + return wasDirty; + } + + static void Add (InkFile inkFile) { + instance.inkLibrary.Add(inkFile); + SortInkLibrary(); + instance.inkLibraryDictionary.Add(inkFile.inkAsset, inkFile); + } + public static void RemoveAt (int index) { + var inkFile = instance.inkLibrary[index]; + instance.inkLibrary.RemoveAt(index); + instance.inkLibraryDictionary.Remove(inkFile.inkAsset); + } + static void SortInkLibrary () { + instance.inkLibrary = instance.inkLibrary.OrderBy(x => x.filePath).ToList(); + } + + /// + /// Updates the ink library. Executed whenever an ink file is changed by InkToJSONPostProcessor + /// Can be called manually, but incurs a performance cost. + /// + public static void Rebuild () { + // Disable the asset post processor in case any assetdatabase functions called as a result of this would cause further operations. + InkPostProcessor.disabled = true; + + // Clear the old data + instance.inkLibrary.Clear(); + instance.inkLibraryDictionary.Clear(); + + // Reset the asset name + instance.name = "Ink Library "+unityIntegrationVersionCurrent.ToString(); + + // Add any new file connections (if any are found it replaces the old library entirely) + string[] inkFilePaths = GetAllInkFilePaths(); + bool inkLibraryChanged = false; + List newInkLibrary = new List(inkFilePaths.Length); + for (int i = 0; i < inkFilePaths.Length; i++) { + InkFile inkFile = GetInkFileWithAbsolutePath(inkFilePaths [i]); + // If the ink library doesn't have a representation for this file, then make one + if(inkFile == null) { + inkLibraryChanged = true; + string localAssetPath = InkEditorUtils.AbsoluteToUnityRelativePath(inkFilePaths [i]); + DefaultAsset inkFileAsset = AssetDatabase.LoadAssetAtPath(localAssetPath); + // If the ink file can't be found, it might not yet have been imported. We try to manually import it to fix this. + if(inkFileAsset == null) { + AssetDatabase.ImportAsset(localAssetPath); + inkFileAsset = AssetDatabase.LoadAssetAtPath(localAssetPath); + if(inkFileAsset == null) { + // If this occurs as a result assets not having been imported before OnValidate => Validate we should return immediately and set a flag to true. + // If an asset import is detected immediately after this via InkPostProcessor, then this rebuild may (will?) have been unnecessary anyway. + // At time of writing (11/05/21) I've not done this and am locally toying with EditorApplication.delayCall in OnValidate. + Debug.LogWarning("Ink File Asset not found at "+localAssetPath+". This can occur if the .meta file has not yet been created. This issue should resolve itself, but if unexpected errors occur, rebuild Ink Library using Assets > Recompile Ink"); + continue; + } + } + inkFile = new InkFile(inkFileAsset); + } + newInkLibrary.Add(inkFile); + } + if(inkLibraryChanged) { + instance.inkLibrary = newInkLibrary; + SortInkLibrary(); + } + BuildLookupDictionary(); + + RebuildInkFileConnections(); + + foreach (InkFile inkFile in instance.inkLibrary) inkFile.FindCompiledJSONAsset(); + + // if(InkSettings.instance.handleJSONFilesAutomatically) DeleteUnwantedCompiledJSONAssets(); + + instance.Save(true); + + // Re-enable the ink asset post processor + InkPostProcessor.disabled = false; + Debug.Log("Ink Library was rebuilt.\n"+instance.inkLibrary.Count+" ink files are currently tracked."); + } + + // To be used when adding .ink files. + // This process is typically handled by CreateOrReadUpdatedInkFiles, called from InkPostProcessor; but it may be desired to remove/disable the post processor. + // In those cases, this is the correct way to ensure the ink library correctly processes the file. + public static InkFile AddNewInkFile (DefaultAsset asset) { + Debug.Assert(asset != null); + // First, check if we've already got it in the library! + foreach(var _inkFile in instance) + if(_inkFile.inkAsset == asset) + return _inkFile; + // If not + var inkFile = new InkFile(asset); + inkFile.FindCompiledJSONAsset(); + Add(inkFile); + RebuildInkFileConnections(); + return inkFile; + } + + // This is called from InkPostProcessor after ink file(s) has been added/changed. + public static void CreateOrReadUpdatedInkFiles (List importedInkAssets) { + for (int i = 0; i < importedInkAssets.Count; i++) { + string importedAssetPath = importedInkAssets[i]; + InkFile inkFile = GetInkFileWithPath(importedAssetPath); + if(inkFile == null) { + DefaultAsset asset = AssetDatabase.LoadAssetAtPath(importedAssetPath); + if(asset == null) { + // This file wasn't found! This is a rare bug. We remove the file from the list in this case, preventing it from causing further bugs. + importedInkAssets.RemoveAt(i); + i--; + Debug.LogWarning("InkLibrary failed to load ink file at "+importedAssetPath+". It has been removed from the list of files. You can ignore this warning."); + } else { + // New file; create and add InkFile to represent it. Content is read in InkFile constructor. + inkFile = new InkFile(asset); + inkFile.FindCompiledJSONAsset(); + Add(inkFile); + } + } else { + // Read content + inkFile.ParseContent(); + } + } + // Now we've updated all the include paths for the ink library we can create master/child references between them. + RebuildInkFileConnections(); + } + + // Finds absolute file paths of all the ink files in Application.dataPath + private static string[] GetAllInkFilePaths () { + string[] inkFilePaths = Directory.GetFiles(Application.dataPath, "*.ink", SearchOption.AllDirectories); + for (int i = 0; i < inkFilePaths.Length; i++) { + inkFilePaths [i] = InkEditorUtils.SanitizePathString(inkFilePaths [i]); + } + return inkFilePaths; + } + + // All the master files + public static IEnumerable GetMasterInkFiles () { + if(instance.inkLibrary == null) yield break; + foreach (InkFile inkFile in instance.inkLibrary) { + if(inkFile.isMaster) + yield return inkFile; + } + } + + public static IEnumerable GetInkFilesMarkedToCompileAsMasterFiles () { + if(instance.inkLibrary == null) yield break; + foreach (InkFile inkFile in instance.inkLibrary) { + if(inkFile.isMaster) + yield return inkFile; + } + } + + // All the master files which are dirty and are set to compile + public static IEnumerable GetFilesRequiringRecompile () { + foreach(InkFile inkFile in GetInkFilesMarkedToCompileAsMasterFiles ()) { + if(InkSettings.instance.ShouldCompileInkFileAutomatically(inkFile) && inkFile.requiresCompile) + yield return inkFile; + } + } + + // All the master files which are set to compile + public static IEnumerable FilesCompiledByRecompileAll () { + foreach(InkFile inkFile in GetInkFilesMarkedToCompileAsMasterFiles ()) { + if(InkSettings.instance.ShouldCompileInkFileAutomatically(inkFile)) + yield return inkFile; + } + } + + /// + /// Gets the ink file from the .ink file reference. + /// + /// The ink file with path. + /// File asset. + /// Adds the file if missing from inkLibrary. + public static InkFile GetInkFileWithFile (DefaultAsset file, bool addIfMissing = false) { + if(instance.inkLibrary == null) return null; + + if (!file) { + Debug.LogError("Can't add null file."); + return null; + } + + if(instance.inkLibraryDictionary == null) { + Debug.LogWarning("GetInkFileWithFile: inkLibraryDictionary was null! This should never occur, but is handled following a user reported bug. If this has never been seen long after 12/08/2020, it can be safely removed"); + BuildLookupDictionary(); + } + foreach(InkFile inkFile in instance.inkLibrary) { + if(inkFile.inkAsset == file) { + return inkFile; + } + } + + var missingFileHasProperFileExtension = Path.GetExtension(AssetDatabase.GetAssetPath(file)) == InkEditorUtils.inkFileExtension; + if (addIfMissing) { + InkFile newFile = new InkFile(file); + instance.inkLibrary.Add(newFile); + if(missingFileHasProperFileExtension) Debug.Log(file + " missing from ink library. Adding it now."); + else Debug.LogWarning("File "+file + " is missing the .ink extension, but is believed to be an ink file. All ink files should use the .ink file extension! A common effect of this is forcing the InkLibrary to rebuild unexpectedly when the file is detected as an include of another file."); + return newFile; + } + + System.Text.StringBuilder listOfFiles = new System.Text.StringBuilder(); + foreach(InkFile inkFile in instance.inkLibrary) { + listOfFiles.AppendLine(inkFile.ToString()); + } + if(missingFileHasProperFileExtension) Debug.LogWarning (file + " missing from ink library. Please rebuild.\nFiles in Library:\n"+listOfFiles); + else Debug.LogWarning (file + " is missing from ink library. It is also missing the .ink file extension. All ink files should use the .ink file extension! \nFiles in Library:\n"+listOfFiles); + return null; + } + + /// + /// Gets the ink file with path relative to Assets folder, for example: "Assets/Ink/myStory.ink". + /// + /// The ink file with path. + /// Path. + public static InkFile GetInkFileWithPath (string path) { + if(instance.inkLibrary == null) return null; + foreach(InkFile inkFile in instance.inkLibrary) { + if(inkFile.filePath == path) { + return inkFile; + } + } + return null; + } + + /// + /// Gets the ink file with absolute path. + /// + /// The ink file with path. + /// Path. + public static InkFile GetInkFileWithAbsolutePath (string absolutePath) { + if(instance.inkLibrary == null) return null; + foreach(InkFile inkFile in instance.inkLibrary) { + if(inkFile.absoluteFilePath == absolutePath) { + return inkFile; + } + } + return null; + } + + public static InkFile GetInkFileWithJSONFile (TextAsset inkJSONAsset) { + if(instance.inkLibrary == null) return null; + foreach(InkFile inkFile in instance.inkLibrary) { + if(inkFile.jsonAsset == inkJSONAsset) { + return inkFile; + } + } + return null; + } + + /// + /// Rebuilds which files are master files and the connections between the files. + /// INCLUDE is always relative to the master file. This means that every file should be assumed to be a master file until proven otherwise. + /// + /// We might consider updating this to allow rebuilding connections for specific files, since the most common case this is called is when a single file changes. + /// The upside is that we wouldn't trigger warnings/errors that this function throws, for unrelated files. It's a bit risky so I've not done it yet. + public static void RebuildInkFileConnections () { + // Resets the connections between files + foreach (InkFile inkFile in instance.inkLibrary) { + inkFile.recursiveIncludeErrorPaths.Clear(); + inkFile.ClearAllHierarchyConnections(); + } + + + // A dictionary which contains a list of all the ink files that INCLUDE a given ink file. + // Once this is done we can determine which files are master files, and then assert that any INCLUDED files actually exist. + Dictionary> includedFileOwnerDictionary = new Dictionary>(); + Dictionary> recursiveIncludeLogs = new Dictionary>(); + // Traverses each file to any file paths referenced using INCLUDE, using the original file as the source path when dealing with nested INCLUDES. + // Since not all of the files are guaranteed to be master files, we don't assert that the files actually exist at this time. + foreach (InkFile inkFile in instance.inkLibrary) { + BuildIncludeHierarchyAsIfMasterFile(inkFile, inkFile, recursiveIncludeLogs); + // Recurse ink file includes for a (potential) master ink file, adding them to the file's list of includes if they exist + static void BuildIncludeHierarchyAsIfMasterFile(InkFile potentialMasterInkFile, InkFile currentInkFile, Dictionary> recursiveIncludeLogs) { + if(currentInkFile.localIncludePaths.Count == 0) + return; + foreach (var includePath in currentInkFile.localIncludePaths) { + var includedFile = FindIncludedFile(potentialMasterInkFile.filePath, includePath); + // Assets may not actually exist. + // A typical and expected example is when an included file in a subfolder from it's master file has an INCLUDE, since file paths are always relative to the master file. + if (includedFile != null) { + // We probably only need to show this error for files that are later proved to be master files + if (potentialMasterInkFile == includedFile || potentialMasterInkFile.includes.Contains(includedFile.inkAsset)) { + if(!recursiveIncludeLogs.ContainsKey(potentialMasterInkFile)) recursiveIncludeLogs.Add(potentialMasterInkFile, new List()); + recursiveIncludeLogs[potentialMasterInkFile].Add(currentInkFile); + continue; + } + Debug.Assert(includedFile.inkAsset != null); + potentialMasterInkFile.includes.Add(includedFile.inkAsset); + BuildIncludeHierarchyAsIfMasterFile(potentialMasterInkFile, includedFile, recursiveIncludeLogs); + } + } + + static InkFile FindIncludedFile(string masterFilePath, string includePath) { + string localIncludePath = InkEditorUtils.CombinePaths(Path.GetDirectoryName(masterFilePath), includePath); + // This enables parsing ..\ and the like. Can we use Path.GetFullPath instead? + var fullIncludePath = new FileInfo(localIncludePath).FullName; + localIncludePath = InkEditorUtils.AbsoluteToUnityRelativePath(fullIncludePath); + DefaultAsset includedInkFileAsset = AssetDatabase.LoadAssetAtPath(localIncludePath); + if(includedInkFileAsset != null) { + return GetInkFileWithFile(includedInkFileAsset); + } + return null; + } + } + + foreach (var includedFile in inkFile.includes) { + var includedInkFile = GetInkFileWithFile(includedFile); + if(!includedFileOwnerDictionary.ContainsKey(includedInkFile)) includedFileOwnerDictionary.Add(includedInkFile, new List()); + includedFileOwnerDictionary[includedInkFile].Add(inkFile); + } + } + + // Now we've established which files are INCLUDED we can tidy up by detecting and removing non-master files. + // It's not a master file then we remove all references to it as a master file in the includedFileOwnerDictionary. + // We don't clear the includes list for those files (even though referenced files may be null), because the user may mark isMarkedToCompileAsMasterFile true at a later date. + foreach (InkFile inkFile in instance.inkLibrary) { + var isMasterFile = !includedFileOwnerDictionary.ContainsKey(inkFile) || includedFileOwnerDictionary[inkFile].Count == 0 || inkFile.isMarkedToCompileAsMasterFile; + if (!isMasterFile) { + foreach (var includedFileOwners in includedFileOwnerDictionary) { + if(includedFileOwners.Key != inkFile) includedFileOwners.Value.Remove(inkFile); + } + } + } + + // Master ink files and includedFileOwnerDictionary are now valid collections denoting master files and their includes. The final step is to add the masters in any included files. + foreach (InkFile inkFile in instance.inkLibrary) { + if (!includedFileOwnerDictionary.ContainsKey(inkFile) || includedFileOwnerDictionary[inkFile].Count == 0 || inkFile.isMarkedToCompileAsMasterFile) { + foreach (var includedFile in inkFile.includes) { + var includedInkFile = GetInkFileWithFile(includedFile); + includedInkFile.masterInkAssets.Add(inkFile.inkAsset); + } + + } + } + + // Error logs for any master files that wanted to add recursive includes + foreach (var recursiveIncludeLog in recursiveIncludeLogs) { + if (recursiveIncludeLog.Key.isMaster) { + recursiveIncludeLog.Key.recursiveIncludeErrorPaths.AddRange(recursiveIncludeLog.Value.Select(x => x.filePath)); + var files = string.Join("\n", recursiveIncludeLog.Key.recursiveIncludeErrorPaths); + Debug.LogError("Recursive INCLUDE found in "+recursiveIncludeLog.Key.filePath+" at "+(recursiveIncludeLog.Value.Count == 1 ? "file:\n" : "files:\n")+files); + } + } + } + + // Deletes any JSON ink assets that aren't expected to exist because their ink files aren't expected to be compiled + public static void DeleteUnwantedCompiledJSONAssets() { + foreach (InkFile inkFile in instance.inkLibrary) { + if(!inkFile.isMaster && inkFile.jsonAsset != null) { + AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(inkFile.jsonAsset)); + inkFile.jsonAsset = null; + } + } + } + } +} \ No newline at end of file diff --git a/Assets/Ink/Editor/Core/Ink Settings/InkSettings.cs b/Assets/Ink/Editor/Core/Ink Settings/InkSettings.cs new file mode 100644 index 0000000..624bdb6 --- /dev/null +++ b/Assets/Ink/Editor/Core/Ink Settings/InkSettings.cs @@ -0,0 +1,144 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using Debug = UnityEngine.Debug; + +/// +/// Holds a reference to an InkFile object for every .ink file detected in the Assets folder. +/// Provides helper functions to easily obtain these files. +/// ScriptableSingleton doesn't reload when the backing file changes, which means if you pull changes via source control you need to make unity recompile before it'll load the change. +/// +namespace Ink.UnityIntegration { + // #if UNITY_2020_1_OR_NEWER + // [FilePath("ProjectSettings/InkSettings.asset", FilePathAttribute.Location.ProjectFolder)] + // public class InkSettings : ScriptableSingleton { + // #else + public class InkSettings : ScriptableObject { + // #endif + // #if !UNITY_2020_1_OR_NEWER + public static bool created { + get { + // If it's null, there's just no InkSettings asset in the project + return _instance != null; + } + } + static string absoluteSavePath { + get { + return System.IO.Path.GetFullPath(System.IO.Path.Combine(Application.dataPath,"..","ProjectSettings","InkSettings.asset")); + + } + } + public static void SaveStatic (bool saveAsText) { + UnityEditorInternal.InternalEditorUtility.SaveToSerializedFileAndForget(new[] { instance }, absoluteSavePath, saveAsText); + } + public void Save (bool saveAsText) { + UnityEditorInternal.InternalEditorUtility.SaveToSerializedFileAndForget((UnityEngine.Object[]) new InkSettings[1] {this}, absoluteSavePath, saveAsText); + } + + private static InkSettings _instance; + public static InkSettings instance { + get { + if(_instance == null) { + Object[] objects = UnityEditorInternal.InternalEditorUtility.LoadSerializedFileAndForget(absoluteSavePath); + if (objects != null && objects.Length > 0) { + instance = objects[0] as InkSettings; + } else { + instance = ScriptableObject.CreateInstance(); + instance.Save(true); + } + // Oh gosh Unity never unloads ScriptableObjects once created! This fixes it but is more of an expensive call than I like. + // I've commented this out in favour of a callback approach - see OnEnable. Left this for posterity in case we need to return to this. + // foreach (var settings in Resources.FindObjectsOfTypeAll()) { + // if(settings == instance) continue; + // DestroyImmediate(settings); + // } + } + return _instance; + } private set { + if(_instance == value) return; + _instance = value; + } + } + // #endif + + public class AssetSaver : UnityEditor.AssetModificationProcessor { + static string[] OnWillSaveAssets(string[] paths) { + InkSettings.instance.Save(true); + return paths; + } + } + + + + public DefaultAsset templateFile; + public string templateFilePath { + get { + if(templateFile == null) return ""; + else return AssetDatabase.GetAssetPath(templateFile); + } + } + + + public DefaultAsset defaultJsonAssetPath; + [UnityEngine.Serialization.FormerlySerializedAs("compileAutomatically")] + public bool compileAllFilesAutomatically = true; + public List includeFilesToCompileAsMasterFiles = new List(); + public List filesToCompileAutomatically = new List(); + public bool delayInPlayMode = true; + public bool handleJSONFilesAutomatically = true; + + public int compileTimeout = 30; + + public bool printInkLogsInConsoleOnCompile; + + public bool suppressStartupWindow; + + #if UNITY_EDITOR && !UNITY_2018_1_OR_NEWER + [MenuItem("Edit/Project Settings/Ink", false, 500)] + public static void SelectFromProjectSettings() { + Selection.activeObject = instance; + } + #elif UNITY_EDITOR && UNITY_2018_1_OR_NEWER + public static SerializedObject GetSerializedSettings() { + return new SerializedObject(instance); + } + #endif + + public bool ShouldCompileInkFileAutomatically (InkFile inkFile) { + return compileAllFilesAutomatically || (inkFile.isMaster && filesToCompileAutomatically.Contains(inkFile.inkAsset)); + } + + + void OnEnable () { + // Oh gosh Unity never unloads ScriptableObjects once created! We destroy these objects before we recompile so there's only ever one in memory at once. + AssemblyReloadEvents.beforeAssemblyReload += () => { + DestroyImmediate(this); + }; + // Validate the includeFilesToCompileAsMasterFiles list. + for (int i = includeFilesToCompileAsMasterFiles.Count - 1; i >= 0; i--) { + if(includeFilesToCompileAsMasterFiles[i] == null) { + includeFilesToCompileAsMasterFiles.RemoveAt(i); + Debug.LogError("REMOVE "+includeFilesToCompileAsMasterFiles.Count); + } + } + // Validate the filesToCompileAutomatically list. + for (int i = filesToCompileAutomatically.Count - 1; i >= 0; i--) { + if(filesToCompileAutomatically[i] == null) { + filesToCompileAutomatically.RemoveAt(i); + } + } + // Deletes the persistent version of this asset that we used to use prior to 0.9.71 + if(!Application.isPlaying && EditorUtility.IsPersistent(this)) { + var path = AssetDatabase.GetAssetPath(this); + if(!string.IsNullOrEmpty(path)) { + #if !UNITY_2020_1_OR_NEWER + if(_instance == this) _instance = null; + #endif + AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(this)); + AssetDatabase.Refresh(); + return; + } + } + } + } +} diff --git a/Assets/Ink/Editor/Core/Ink Settings/InkSettingsEditor.cs b/Assets/Ink/Editor/Core/Ink Settings/InkSettingsEditor.cs new file mode 100644 index 0000000..f5f1b74 --- /dev/null +++ b/Assets/Ink/Editor/Core/Ink Settings/InkSettingsEditor.cs @@ -0,0 +1,151 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +namespace Ink.UnityIntegration { + + [CustomEditor(typeof(InkSettings))] + public class InkSettingsEditor : Editor { + + #pragma warning disable + protected InkSettings data; + + public void OnEnable() { + data = (InkSettings) target; + } + + public override void OnInspectorGUI() { + serializedObject.Update(); + + DrawSettings(serializedObject); + + if (GUI.changed && target != null) { + EditorUtility.SetDirty(target); + ((InkSettings) target).Save(true); + } + serializedObject.ApplyModifiedProperties(); + } + + #if UNITY_2018_1_OR_NEWER + [SettingsProvider] + public static SettingsProvider CreateInkSettingsProvider() { + // First parameter is the path in the Settings window. + // Second parameter is the scope of this setting: it only appears in the Project Settings window. + var provider = new SettingsProvider("Project/Ink", SettingsScope.Project) { + // By default the last token of the path is used as display name if no label is provided. + label = "Ink", + // Create the SettingsProvider and initialize its drawing (IMGUI) function in place: + guiHandler = (searchContext) => { + // Drawing the SO makes them disabled, and I have no idea why. Drawing manually until fixed. + // var settings = InkSettings.GetSerializedSettings(); + DrawSettings(InkSettings.instance); + }, + + // Populate the search keywords to enable smart search filtering and label highlighting: + // keywords = new HashSet(new[] { "Number", "Some String" }) + }; + return provider; + } + #endif + + static void DrawSettings (InkSettings settings) { + EditorGUI.BeginChangeCheck(); + + EditorGUI.indentLevel++; + DrawVersions(); + EditorGUILayout.Separator(); + + var cachedLabelWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 260; + + EditorGUILayout.LabelField(new GUIContent("Settings"), EditorStyles.boldLabel); + if(settings.templateFile == null) + DrawTemplateMissingWarning(); + settings.templateFile = (DefaultAsset)EditorGUILayout.ObjectField(new GUIContent("Ink Template", "Optional. The default content of files created via Assets > Create > Ink."), settings.templateFile, typeof(DefaultAsset)); + + settings.defaultJsonAssetPath = (DefaultAsset)EditorGUILayout.ObjectField(new GUIContent("New JSON Path", "By default, story JSON files are placed next to the ink. Drag a folder here to place new JSON files there instead."), settings.defaultJsonAssetPath, typeof(DefaultAsset)); + settings.compileAllFilesAutomatically = EditorGUILayout.Toggle(new GUIContent("Compile All Ink Automatically", "When disabled, automatic compilation can be enabled on a per-story basis via the inspector for a master story file. This can be helpful when you have several stories in a single project."), settings.compileAllFilesAutomatically); + settings.delayInPlayMode = EditorGUILayout.Toggle(new GUIContent("Delay compilation if in Play Mode", "When enabled, ink compilation is delayed if in play mode. Files will be compiled on re-entering edit mode."), settings.delayInPlayMode); + settings.printInkLogsInConsoleOnCompile = EditorGUILayout.Toggle(new GUIContent("Print ink TODOs in console on compile", "When enabled, ink lines starting with TODO are printed in the console."), settings.printInkLogsInConsoleOnCompile); + settings.handleJSONFilesAutomatically = EditorGUILayout.Toggle(new GUIContent("Handle JSON Automatically", "Whether JSON files are moved, renamed and deleted along with their ink files."), settings.handleJSONFilesAutomatically); + settings.compileTimeout = EditorGUILayout.IntField(new GUIContent("Compile Timeout", "The max time the compiler will attempt to compile for in case of unhanded errors. You may need to increase this for very large ink projects."), settings.compileTimeout); + settings.suppressStartupWindow = EditorGUILayout.Toggle(new GUIContent("Suppress Startup Window", "Prevent the \"what's new\" (the one that appears if you click the \"Show changelog\" button above) appearing when the version of this plugin has changed and Unity is opened. This can be useful for CI/CD pipelines, where auto-launching editor windows can fail to load due to a Unity bug."), settings.suppressStartupWindow); + + EditorGUIUtility.labelWidth = cachedLabelWidth; + + EditorGUILayout.Separator(); + DrawRequestButton(); + + EditorGUI.indentLevel--; + + if (EditorGUI.EndChangeCheck()) { + EditorUtility.SetDirty(settings); + settings.Save(true); + } + } + + static void DrawSettings (SerializedObject settings) { + DrawVersions(); + EditorGUILayout.Separator(); + + var cachedLabelWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 260; + EditorGUI.BeginChangeCheck(); + + EditorGUILayout.LabelField(new GUIContent("Settings"), EditorStyles.boldLabel); + if(settings.FindProperty("templateFile").objectReferenceValue == null) + DrawTemplateMissingWarning(); + + EditorGUILayout.PropertyField(settings.FindProperty("templateFile"), new GUIContent("Ink Template", "Optional. The default content of files created via Assets > Create > Ink.")); + EditorGUILayout.PropertyField(settings.FindProperty("defaultJsonAssetPath"), new GUIContent("New JSON Path", "By default, story JSON files are placed next to the ink. Drag a folder here to place new JSON files there instead.")); + EditorGUILayout.PropertyField(settings.FindProperty("compileAllFilesAutomatically"), new GUIContent("Compile All Ink Automatically", "When disabled, automatic compilation can be enabled on a per-story basis via the inspector for a master story file. This can be helpful when you have several stories in a single project.")); + EditorGUILayout.PropertyField(settings.FindProperty("delayInPlayMode"), new GUIContent("Delay compilation if in Play Mode", "When enabled, ink compilation is delayed if in play mode. Files will be compiled on re-entering edit mode.")); + EditorGUILayout.PropertyField(settings.FindProperty("printInkLogsInConsoleOnCompile"), new GUIContent("Print ink TODOs in console on compile", "When enabled, ink lines starting with TODO are printed in the console.")); + EditorGUILayout.PropertyField(settings.FindProperty("handleJSONFilesAutomatically"), new GUIContent("Handle JSON Automatically", "Whether JSON files are moved, renamed and deleted along with their ink files.")); + EditorGUILayout.PropertyField(settings.FindProperty("compileTimeout"), new GUIContent("Compile Timeout", "The max time the compiler will attempt to compile for in case of unhanded errors. You may need to increase this for very large ink projects.")); + EditorGUILayout.PropertyField(settings.FindProperty("suppressStartupWindow"), new GUIContent("Suppress Startup Window", "Prevent the \"what's new\" (the one that appears if you click the \"Show changelog\" button above) appearing when the version of this plugin has changed and Unity is opened. This can be useful for CI/CD pipelines, where auto-launching editor windows can fail to load due to a Unity bug.")); + + if(EditorGUI.EndChangeCheck()) { + settings.ApplyModifiedProperties(); + } + EditorGUIUtility.labelWidth = cachedLabelWidth; + + EditorGUILayout.Separator(); + DrawRequestButton(); + } + + + static void DrawVersions () { + EditorGUILayout.LabelField(new GUIContent("Version Info"), EditorStyles.boldLabel); + EditorGUI.BeginDisabledGroup(true); + EditorGUILayout.TextField(new GUIContent("Plugin version", "The version of the Ink Unity Integration package."), InkLibrary.unityIntegrationVersionCurrent.ToString()); + EditorGUILayout.TextField(new GUIContent("Ink version", "The version of ink that is included by the Unity package, used to compile and play ink files."), InkLibrary.inkVersionCurrent.ToString()); + EditorGUILayout.TextField(new GUIContent("Ink story format version", "Significant changes to the Ink runtime are recorded by the story format version.\nCompatibility between different versions is limited; see comments at Ink.Runtime.Story.inkVersionCurrent for more details."), Ink.Runtime.Story.inkVersionCurrent.ToString()); + EditorGUILayout.TextField(new GUIContent("Ink save format version", "Version of the ink save/load system.\nCompatibility between different versions is limited; see comments at Ink.Runtime.StoryState.kInkSaveStateVersion for more details."), Ink.Runtime.StoryState.kInkSaveStateVersion.ToString()); + EditorGUI.EndDisabledGroup(); + if (GUILayout.Button("Show changelog", GUILayout.Width(140))) { + InkUnityIntegrationStartupWindow.ShowWindow(); + } + } + + static void DrawRequestButton() { + EditorGUILayout.LabelField(new GUIContent("Support + Requests"), EditorStyles.boldLabel); + + EditorGUILayout.LabelField("Is there a setting you'd like? Or a feature you'd like to request?"); + // EditorGUILayout.BeginVertical(GUILayout.Width(220)); + EditorGUILayout.BeginHorizontal(); + if(GUILayout.Button("Reach us on Discord", GUILayout.Width(220))) { + Application.OpenURL("https://discord.gg/inkle"); + } + if(GUILayout.Button("Submit an issue on GitHub", GUILayout.Width(220))) { + Application.OpenURL("https://github.com/inkle/ink-unity-integration/issues/new"); + } + EditorGUILayout.EndHorizontal(); + // EditorGUILayout.EndVertical(); + } + + static void DrawTemplateMissingWarning () { + EditorGUILayout.HelpBox("Template not found. Ink files created via Assets > Create > Ink will be blank.", MessageType.Info); + } + } +} \ No newline at end of file diff --git a/Assets/Ink/Editor/Core/InkEditorUtils.cs b/Assets/Ink/Editor/Core/InkEditorUtils.cs new file mode 100644 index 0000000..eb02eaf --- /dev/null +++ b/Assets/Ink/Editor/Core/InkEditorUtils.cs @@ -0,0 +1,372 @@ +using UnityEngine; +using UnityEditor; +using System; +using System.IO; +using System.Text; +using System.Linq; +using Ink.Runtime; +using UnityEditor.ProjectWindowCallback; +using UnityEditor.Callbacks; +using Path = System.IO.Path; + +namespace Ink.UnityIntegration { + [InitializeOnLoad] + public static class InkEditorUtils { + class CreateInkAssetAction : EndNameEditAction { + public override void Action(int instanceId, string pathName, string resourceFile) { + var text = ""; + if(File.Exists(resourceFile)) { + StreamReader streamReader = new StreamReader(resourceFile); + text = streamReader.ReadToEnd(); + streamReader.Close(); + } + var assetPath = CreateScriptAsset(pathName, text); + var asset = AssetDatabase.LoadAssetAtPath(assetPath); + ProjectWindowUtil.ShowCreatedAsset(asset); + } + } + public const string inkFileExtension = ".ink"; + const string lastCompileTimeKey = "InkIntegrationLastCompileTime"; + + private static Texture2D _inkLogoIcon; + public static Texture2D inkLogoIcon { + get { + if(_inkLogoIcon == null) { + _inkLogoIcon = Resources.Load("InkLogoIcon"); + } + return _inkLogoIcon; + } + } + + [MenuItem("Assets/Rebuild Ink Library", false, 200)] + public static void RebuildLibrary() { + InkLibrary.Rebuild(); + } + + [MenuItem("Assets/Recompile Ink", false, 201)] + public static void RecompileAll() { + var filesToRecompile = InkLibrary.FilesCompiledByRecompileAll().ToArray(); + string logString = filesToRecompile.Any() ? + "Recompile All will compile "+string.Join(", ", filesToRecompile.Select(x => Path.GetFileName(x.filePath)).ToArray()) : + "No valid ink found. Note that only files with 'Compile Automatic' checked are compiled if not set to compile all files automatically in InkSettings file."; + Debug.Log(logString); + InkCompiler.CompileInk(filesToRecompile); + } + + public static void RecompileAllImmediately() { + var filesToRecompile = InkLibrary.FilesCompiledByRecompileAll().ToArray(); + string logString = filesToRecompile.Any() ? + "Recompile All Immediately will compile "+string.Join(", ", filesToRecompile.Select(x => Path.GetFileName(x.filePath)).ToArray()) : + "No valid ink found. Note that only files with 'Compile Automatic' checked are compiled if not set to compile all files automatically in InkSettings file."; + Debug.Log(logString); + InkCompiler.CompileInk(filesToRecompile, true, null); + } + + + + [MenuItem("Assets/Create/Ink", false, 120)] + public static void CreateNewInkFileAtSelectedPathWithTemplateAndStartNameEditing () { + string fileName = "New Ink.ink"; + string filePath = AssetDatabase.GenerateUniqueAssetPath(Path.Combine(GetSelectedPathOrFallback(), fileName)); + CreateNewInkFileAtPathWithTemplateAndStartNameEditing(filePath, InkSettings.instance.templateFilePath); + } + + public static void CreateNewInkFileAtPathWithTemplateAndStartNameEditing (string filePath, string templateFileLocation) { + if(Path.GetExtension(filePath) != inkFileExtension) filePath += inkFileExtension; + ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance(), filePath, InkBrowserIcons.inkFileIcon, templateFileLocation); + } + + public static DefaultAsset CreateNewInkFileAtPath (string filePath, string text) { + if(Path.GetExtension(filePath) != inkFileExtension) filePath += inkFileExtension; + var assetPath = CreateScriptAsset(filePath, text); + return AssetDatabase.LoadAssetAtPath(assetPath); + } + + static string CreateScriptAsset(string pathName, string text) { + string fullPath = Path.GetFullPath(pathName); + fullPath = fullPath.Replace('\\', '/'); + var assetRelativePath = fullPath; + if(fullPath.StartsWith(Application.dataPath)) { + assetRelativePath = fullPath.Substring(Application.dataPath.Length-6); + } + var directoryPath = Path.GetDirectoryName(fullPath); + if(!Directory.Exists(directoryPath)) + Directory.CreateDirectory(directoryPath); + UTF8Encoding encoding = new UTF8Encoding(true, false); + StreamWriter streamWriter = null; + streamWriter = new StreamWriter(fullPath, false, encoding); + streamWriter.Write(text); + streamWriter.Close(); + AssetDatabase.ImportAsset(assetRelativePath); + return assetRelativePath; + } + + + + private static string GetSelectedPathOrFallback() { + string path = "Assets"; + foreach (UnityEngine.Object obj in Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.Assets)) { + path = AssetDatabase.GetAssetPath(obj); + if (!string.IsNullOrEmpty(path) && File.Exists(path)) { + path = Path.GetDirectoryName(path); + break; + } + } + return path; + } + + + + [MenuItem("Help/Ink/About")] + public static void OpenAbout() { + Application.OpenURL("https://github.com/inkle/ink#ink"); + } + + [MenuItem("Help/Ink/Writing Tutorial...")] + public static void OpenWritingDocumentation() { + Application.OpenURL("https://github.com/inkle/ink/blob/master/Documentation/WritingWithInk.md"); + } + + [MenuItem("Help/Ink/API Documentation...")] + public static void OpenAPIDocumentation() { + Application.OpenURL("https://github.com/inkle/ink/blob/master/Documentation/RunningYourInk.md"); + } + + [MenuItem("Help/Ink/Discord (Community + Support...")] + public static void OpenDiscord() { + Application.OpenURL("https://discord.gg/inkle"); + } + + [MenuItem("Help/Ink/Donate...")] + public static void Donate() { + Application.OpenURL("https://www.patreon.com/inkle"); + } + + [PostProcessBuildAttribute(-1)] + public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject) { + if(!Debug.isDebugBuild) { + var color = EditorGUIUtility.isProSkin ? "#3498db" : "blue"; + Debug.Log("Thanks for using ink, and best of luck with your release!\nIf you're doing well, please help fund the project via Patreon https://www.patreon.com/inkle"); + } + } + + public static TextAsset CreateStoryStateTextFile (string jsonStoryState, string defaultPath = "Assets/Ink", string defaultName = "storyState") { + string name = AssetDatabase.GenerateUniqueAssetPath(Path.Combine(defaultPath, defaultName+".json")); + if(!string.IsNullOrEmpty(defaultPath)) name = name.Substring(defaultPath.Length+1); + string fullPathName = EditorUtility.SaveFilePanel("Save Story State", defaultPath, name, "json"); + if(fullPathName == "") + return null; + using (StreamWriter outfile = new StreamWriter(fullPathName)) { + outfile.Write(jsonStoryState); + } + + if(fullPathName.StartsWith(Application.dataPath)) { + string relativePath = AbsoluteToUnityRelativePath(fullPathName); + AssetDatabase.ImportAsset(relativePath); + TextAsset textAsset = AssetDatabase.LoadAssetAtPath(relativePath); + return textAsset; + } + else return null; + } + + public static bool StoryContainsVariables (Story story) { + return story.variablesState.GetEnumerator().MoveNext(); + } + + public static bool CheckStoryIsValid (string storyJSON, out Exception exception) { + try { + new Story(storyJSON); + } catch (Exception ex) { + exception = ex; + return false; + } + exception = null; + return true; + } + + public static bool CheckStoryIsValid (string storyJSON, out Story story) { + try { + story = new Story(storyJSON); + } catch { + story = null; + return false; + } + return true; + } + + public static bool CheckStoryIsValid (string storyJSON, out Exception exception, out Story story) { + try { + story = new Story(storyJSON); + } catch (Exception ex) { + exception = ex; + story = null; + return false; + } + exception = null; + return true; + } + + public static bool CheckStoryStateIsValid (string storyJSON, string storyStateJSON) { + Story story; + if(CheckStoryIsValid(storyJSON, out story)) { + try { + story.state.LoadJson(storyStateJSON); + } catch { + return false; + } + } + return true; + } + + // Returns a sanitized version of the supplied string by: + // - swapping MS Windows-style file separators with Unix/Mac style file separators. + // If null is provided, null is returned. + public static string SanitizePathString(string path) { + if (path == null) { + return null; + } + return path.Replace('\\', '/'); + } + + // Combines two file paths and returns that path. Unlike C#'s native Paths.Combine, regardless of operating + // system this method will always return a path which uses forward slashes ('/' characters) exclusively to ensure + // equality checks on path strings return equalities as expected. + public static string CombinePaths(string firstPath, string secondPath) { + Debug.Assert(firstPath != null); + Debug.Assert(secondPath != null); + return SanitizePathString(firstPath+"/"+secondPath); + } + + public static string AbsoluteToUnityRelativePath(string fullPath) { + return SanitizePathString(fullPath.Substring(Application.dataPath.Length-6)); + } + + public static string UnityRelativeToAbsolutePath(string filePath) { + return InkEditorUtils.CombinePaths(Application.dataPath, filePath.Substring(7)); + } + + /// + /// Draws a property field for a story using GUILayout, allowing you to attach stories to the player window for debugging. + /// + /// Story. + /// Label. + public static void DrawStoryPropertyField (Story story, GUIContent label) { + Debug.LogWarning("DrawStoryPropertyField has been moved from InkEditorUtils to InkPlayerWindow"); + } + + /// + /// Draws a property field for a story using GUI, allowing you to attach stories to the player window for debugging. + /// + /// Position. + /// Story. + /// Label. + public static void DrawStoryPropertyField (Rect position, Story story, GUIContent label) { + Debug.LogWarning("DrawStoryPropertyField has been moved from InkEditorUtils to InkPlayerWindow"); + } + + /// + /// Checks to see if the given path is an ink file or not, regardless of extension. + /// + /// The path to check. + /// True if it's an ink file, otherwise false. + public static bool IsInkFile(string path) { + string extension = Path.GetExtension(path); + if (extension == InkEditorUtils.inkFileExtension) { + return true; + } + + return String.IsNullOrEmpty(extension) && InkLibrary.instance.inkLibrary.Exists(f => f.filePath == path); + } + + + + /// + /// Opens an ink file in the associated editor at the correct line number. + /// TODO - If the editor is inky, this code should load the master file, but immediately show the correct child file at the correct line. + /// + public static void OpenInEditor (InkFile inkFile, InkCompilerLog log) { + var targetFilePath = log.GetAbsoluteFilePath(inkFile); + // EditorUtility.OpenWithDefaultApp(targetFilePath); + AssetDatabase.OpenAsset(inkFile.inkAsset, log.lineNumber); + // Unity.CodeEditor.CodeEditor.OSOpenFile(); +#if UNITY_2019_1_OR_NEWER + + // This function replaces OpenFileAtLineExternal, but I guess it's totally internal and can't be accessed. + // CodeEditorUtility.Editor.Current.OpenProject(targetFilePath, lineNumber); + // #pragma warning disable + // UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal(targetFilePath, log.lineNumber); + // #pragma warning restore +#else + UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal(targetFilePath, log.lineNumber); +#endif + } + /// + /// Opens an ink file in the associated editor at the correct line number. + /// TODO - If the editor is inky, this code should load the master file, but immediately show the correct child file at the correct line. + /// + public static void OpenInEditor (string masterFilePath, string subFilePath, int lineNumber) { + if(!string.IsNullOrEmpty(subFilePath) && Path.GetFileName(masterFilePath) != subFilePath) { + Debug.LogWarning("Tried to open an ink file ("+subFilePath+") at line "+lineNumber+" but the file is an include file. This is not currently implemented. The master ink file will be opened at line 0 instead."); + lineNumber = 0; + } + #if UNITY_2019_1_OR_NEWER + // This function replaces OpenFileAtLineExternal, but I guess it's totally internal and can't be accessed. + // CodeEditorUtility.Editor.Current.OpenProject(masterFilePath, lineNumber); + #pragma warning disable + UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal(masterFilePath, lineNumber); + #pragma warning restore + #else + UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal(masterFilePath, lineNumber); + #endif + } + + + + + public static string FormatJson(string json) { + const string INDENT_STRING = " "; + + int indentation = 0; + int quoteCount = 0; + var result = + from ch in json + let quotes = ch == '"' ? quoteCount++ : quoteCount + let lineBreak = ch == ',' && quotes % 2 == 0 ? ch + Environment.NewLine + String.Concat(Enumerable.Repeat(INDENT_STRING, indentation)) : null + let openChar = ch == '{' || ch == '[' ? ch + Environment.NewLine + String.Concat(Enumerable.Repeat(INDENT_STRING, ++indentation)) : ch.ToString() + let closeChar = ch == '}' || ch == ']' ? Environment.NewLine + String.Concat(Enumerable.Repeat(INDENT_STRING, --indentation)) + ch : ch.ToString() + select lineBreak == null + ? openChar.Length > 1 + ? openChar + : closeChar + : lineBreak; + + return String.Concat(result); + } + + + // If this plugin is installed as a package, returns info about it. + public static UnityEditor.PackageManager.PackageInfo GetPackageInfo() { + var packageAssetPath = "Packages/com.inkle.ink-unity-integration"; + if (AssetDatabase.IsValidFolder(packageAssetPath)) return UnityEditor.PackageManager.PackageInfo.FindForAssetPath(packageAssetPath); + else return null; + } + + // Gets the root directory of this plugin, enabling us to find assets within it. + // Less efficent if not installed as a package because the location/folder name is not known. + public static string FindAbsolutePluginDirectory() { + var packageInfo = GetPackageInfo(); + if (packageInfo != null) { + return packageInfo.resolvedPath; + } else { + // Find the InkLibs folder. We assume that it exists in the top level of the plugin folder. We use this folder because it has a fairly unique name and is essential for the plugin to function. + string[] guids = AssetDatabase.FindAssets("t:DefaultAsset", new[] {"Assets"}).Where(g => AssetDatabase.GUIDToAssetPath(g).EndsWith("/InkLibs")).ToArray(); + if (guids.Length > 0) { + var assetPathOfInkLibsFolder = AssetDatabase.GUIDToAssetPath(guids[0]); + var rootPluginFolder = assetPathOfInkLibsFolder.Substring(0, assetPathOfInkLibsFolder.Length - "/InkLibs".Length); + return Path.GetFullPath(Path.Combine(Application.dataPath, "..", rootPluginFolder)); + } + } + return null; // If no folder is found + } + } +} \ No newline at end of file diff --git a/Assets/Ink/Editor/InkEditor.asmdef b/Assets/Ink/Editor/InkEditor.asmdef new file mode 100644 index 0000000..c4d7d6d --- /dev/null +++ b/Assets/Ink/Editor/InkEditor.asmdef @@ -0,0 +1,16 @@ +{ + "name": "InkEditor", + "references": [ + "Ink-Libraries" + ], + "optionalUnityReferences": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [] +} \ No newline at end of file diff --git a/Assets/Ink/Editor/Tools/Build Validation/InkPreBuildValidationCheck.cs b/Assets/Ink/Editor/Tools/Build Validation/InkPreBuildValidationCheck.cs new file mode 100644 index 0000000..30e0cf8 --- /dev/null +++ b/Assets/Ink/Editor/Tools/Build Validation/InkPreBuildValidationCheck.cs @@ -0,0 +1,62 @@ +using UnityEngine; +using UnityEditor; +using UnityEditor.Build; +using System.Text; +using Ink.UnityIntegration; +using System.Linq; +#if UNITY_2018_1_OR_NEWER +using UnityEditor.Build.Reporting; +#endif + +class InkPreBuildValidationCheck : +#if UNITY_2018_1_OR_NEWER +IPreprocessBuildWithReport +#else +IPreprocessBuild +#endif +{ + public int callbackOrder { get { return 0; } } + + #if UNITY_2018_1_OR_NEWER + public void OnPreprocessBuild(BuildReport report) { + PreprocessValidationStep(); + } + #else + public void OnPreprocessBuild(BuildTarget target, string path) { + PreprocessValidationStep(); + } + #endif + + static void PreprocessValidationStep () { + // If we're compiling, we've throw an error to cancel the build. Exit out immediately. + if(!AssertNotCompiling()) return; + EnsureInkIsCompiled(); + } + + // Prevent building if ink is currently compiling. + // Ideally we'd force it to complete instantly. + // It seems you can do this with WaitHandle.WaitAll but I'm out of my depth! + // Info here - https://stackoverflow.com/questions/540078/wait-for-pooled-threads-to-complete + static bool AssertNotCompiling () { + if(InkCompiler.executingCompilationStack) { + StringBuilder sb = new StringBuilder("Ink is currently compiling!"); + var errorString = sb.ToString(); + InkCompiler.SetBuildBlocked(); + if(UnityEditor.EditorUtility.DisplayDialog("Ink Build Error!", errorString, "Ok")) { + Debug.LogError(errorString); + } + return false; + } + return true; + } + + // Immediately compile any files that aren't compiled and should be. + static void EnsureInkIsCompiled () { + var filesToRecompile = InkLibrary.GetFilesRequiringRecompile(); + if(filesToRecompile.Any()) { + if(InkSettings.instance.compileAllFilesAutomatically) { + InkCompiler.CompileInk(filesToRecompile.ToArray(), true, null); + } + } + } +} \ No newline at end of file diff --git a/Assets/Ink/Editor/Tools/File Icons/InkBrowserIcons.cs b/Assets/Ink/Editor/Tools/File Icons/InkBrowserIcons.cs new file mode 100644 index 0000000..9cfe82a --- /dev/null +++ b/Assets/Ink/Editor/Tools/File Icons/InkBrowserIcons.cs @@ -0,0 +1,189 @@ +using System.IO; +using UnityEditor; +using UnityEngine; + +/* +* This script allows you to set custom icons for folders in project browser. +* Recommended icon sizes - small: 16x16 px, large: 64x64 px; +*/ + +namespace Ink.UnityIntegration { + [InitializeOnLoad] + public class InkBrowserIcons { + private static bool isRetina { + get { + float unityVersion = float.Parse(Application.unityVersion.Substring (0, 3)); + return Application.platform == RuntimePlatform.OSXEditor && unityVersion >= 5.4f; + } + } + private const float largeIconSize = 64f; + + private static Texture2D _inkFileIcon; + public static Texture2D inkFileIcon { + get { + if(_inkFileIcon == null) { + if(isRetina) { + _inkFileIcon = Resources.Load("InkFileIcon-retina"); + } else { + _inkFileIcon = Resources.Load("InkFileIcon"); + } + } + return _inkFileIcon; + } + } + private static Texture2D _inkFileIconLarge; + public static Texture2D inkFileIconLarge { + get { + if(_inkFileIconLarge == null) { + _inkFileIconLarge = Resources.Load("InkFileIcon-large"); + } + return _inkFileIconLarge; + } + } + private static Texture2D _errorIcon; + public static Texture2D errorIcon { + get { + if(_errorIcon == null) { + _errorIcon = Resources.Load("InkErrorIcon"); + } + return _errorIcon; + } + } + private static Texture2D _warningIcon; + public static Texture2D warningIcon { + get { + if(_warningIcon == null) { + _warningIcon = Resources.Load("InkWarningIcon"); + } + return _warningIcon; + } + } + private static Texture2D _todoIcon; + public static Texture2D todoIcon { + get { + if(_todoIcon == null) { + _todoIcon = Resources.Load("InkTodoIcon"); + } + return _todoIcon; + } + } + private static Texture2D _manualIcon; + public static Texture2D manualIcon { + get { + if(_manualIcon == null) { + _manualIcon = Resources.Load("InkCompileManualIcon"); + } + return _manualIcon; + } + } + private static Texture2D _childIcon; + public static Texture2D childIcon { + get { + if(_childIcon == null) { + _childIcon = Resources.Load("InkChildIcon"); + } + return _childIcon; + } + } + private static Texture2D _childIconLarge; + public static Texture2D childIconLarge { + get { + if(_childIconLarge == null) { + _childIconLarge = Resources.Load("InkChildIcon-Large"); + } + return _childIconLarge; + } + } + private static Texture2D _unknownFileIcon; + public static Texture2D unknownFileIcon { + get { + if(_unknownFileIcon == null) { + _unknownFileIcon = Resources.Load("InkUnknownFileIcon"); + } + return _unknownFileIcon; + } + } + + static InkBrowserIcons() { + EditorApplication.projectWindowItemOnGUI += OnDrawProjectWindowItem; + } + + static void OnDrawProjectWindowItem(string guid, Rect rect) { + string path = AssetDatabase.GUIDToAssetPath(guid); + if (InkEditorUtils.IsInkFile(path)) { + DefaultAsset asset = AssetDatabase.LoadAssetAtPath(path); + DrawInkFile(InkLibrary.GetInkFileWithFile(asset), rect); + } + } + + static void DrawInkFile (InkFile inkFile, Rect rect) { + bool isSmall = rect.width > rect.height; + if (isSmall) { + rect.width = rect.height; + } else { + rect.height = rect.width; + } + if (rect.width >= largeIconSize) { + DrawLarge(inkFile, rect); + } else { + DrawSmall(inkFile, rect); + } + } + + static void DrawLarge (InkFile inkFile, Rect rect) { + var offset = (rect.width - largeIconSize) * 0.5f; + rect = new Rect(rect.x + offset, rect.y + offset, largeIconSize, largeIconSize); + if(inkFileIconLarge != null) + GUI.DrawTexture(rect, inkFileIconLarge); + + Rect miniRect = new Rect(rect.center, rect.size * 0.5f); + if(inkFile == null) { + if(unknownFileIcon != null) { + GUI.DrawTexture(miniRect, unknownFileIcon); + } + } else { + if(inkFile.hasErrors && errorIcon != null) { + GUI.DrawTexture(miniRect, errorIcon); + } else if(inkFile.hasWarnings && warningIcon != null) { + GUI.DrawTexture(miniRect, warningIcon); + } else if(inkFile.hasTodos && todoIcon != null) { + GUI.DrawTexture(miniRect, todoIcon); + } + if(inkFile.isIncludeFile && childIcon != null) { + GUI.DrawTexture(new Rect(rect.x, rect.y, rect.width * 0.5f, rect.height * 0.5f), childIconLarge); + } + } + } + + static void DrawSmall (InkFile inkFile, Rect rect) { + if(inkFileIcon != null) + GUI.DrawTexture(rect, inkFileIcon); + + if(inkFile == null) { + if(unknownFileIcon != null) { + GUI.DrawTexture(new Rect(rect.x, rect.y, unknownFileIcon.width, unknownFileIcon.height), unknownFileIcon); + } + } else { + if (inkFile.isMaster) { + if (!InkSettings.instance.ShouldCompileInkFileAutomatically(inkFile)) { + GUI.DrawTexture(new Rect(rect.x, rect.y + rect.size.y * 0.5f, rect.size.x * 0.5f, rect.size.y * 0.5f), manualIcon); + + } + + Rect miniRect = new Rect(rect.center, rect.size * 0.5f); + if(inkFile.hasErrors && errorIcon != null) { + GUI.DrawTexture(miniRect, errorIcon); + } else if(inkFile.hasWarnings && warningIcon != null) { + GUI.DrawTexture(miniRect, warningIcon); + } else if(inkFile.hasTodos && todoIcon != null) { + GUI.DrawTexture(miniRect, todoIcon); + } + } + + if(inkFile.isIncludeFile && childIcon != null) { + GUI.DrawTexture(new Rect(rect.x, rect.y, childIcon.width, childIcon.height), childIcon); + } + } + } + } +} \ No newline at end of file diff --git a/Assets/Ink/Editor/Tools/File Icons/Resources/InkChildIcon-Large.psd b/Assets/Ink/Editor/Tools/File Icons/Resources/InkChildIcon-Large.psd new file mode 100644 index 0000000000000000000000000000000000000000..a3c63c392db1665bfb7d7f708a6b93cb7c0617e7 GIT binary patch literal 29759 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 C2F6kV literal 0 HcmV?d00001 diff --git a/Assets/Ink/Editor/Tools/File Icons/Resources/InkChildIcon.psd b/Assets/Ink/Editor/Tools/File Icons/Resources/InkChildIcon.psd new file mode 100644 index 0000000000000000000000000000000000000000..c31c8bc9cc6f4d9863e4e04914f668c5ab3bb135 GIT binary patch literal 24016 zcmeHP2YggTx1YN;Wz$1w0hWXiiYdG4Aqhz~l_Vr2p^Cz0_hz$X8+Uh;fG9;o1#CzM zktS6^QHqFC6;VWr6czmfNK-_VDsA7Hxm#{R{PuhA^ZnlYe!soRoqOh-GiT2Hr{3A$ z+|=BPDnudn62QZU++K*!vWAaN%`GkyURV+-+g+` z{!hGxriKk0g?k4QSr07h_i9G}CX-TCPg|rlv_@;ljQH)Noe@&4Ix}KuQdxYNNkP|X zi^el_)%bzcs`2%zG<8J(ET4>~^d`MYPg|7ICcVyJPH)PLP^yhJbUM(O9Ty=bDwg`p zh#V}C4lApWDvS&*O^Qv3QN_z-(&Xe=Sz=Ohvg|RbJYFV`i--T@7+GR^QgXUHMQXny zvV4HbVAQqgm3amB>>!pIQD?E3(&OS98yjOA6Jm{wCQg=?mWIv9+FMGN4CTB(lb1W%itjeg5Yf_rxWU=va zPRo!m129QfFtpNQWU7ruT^3vNiaMjkXs$Dwq>8F!X|FP+N^8K3-WhSN6SzEZ*`o85 z7CH+MN{)$7jFF{P%Vp_FY3Ye+edA^6@$noZtY#}4Wl$SxrA67oiX5!Orza$)%M-X( zTIja6V^nKv$NfuIT$*+p8F3h94(y~(F=DOw?y5tra@K~)%IHX?t5tEdj@Hu#iy3M} z*0M&_s`OeTqgPt8lqQo-t5V`hk83cf?Nw=V)J;a5OZD&e8fv+$%;|WW%}B40YpeO0 zE%^=5GVLwB&6MWqaV9#hk~SNyjEc^0032M+-QFn6%F>GsW{c9GqKosgz@1pFR-GO% zPlaxnk{F*Nk55jO$x`D}6Y_J@Qd9EMz#@X>gr~O~3 z0<*H=->iT%cg_3XsQ`I;d`h}3(J?6hUsZss<*MqG1`VywigPqt2jf4f&fJf5|I<2a zV

W?pUITl(UId!-g~cUB#b%&M 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%0DiczxU6Do|K)8cpddsQ`{zr|eWhs^3 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 zio¨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

RVvToVDspCfs=-H_av=^n) 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 literal 0 HcmV?d00001 diff --git a/Assets/Ink/Editor/Tools/File Icons/Resources/InkFileIcon-retina.psd b/Assets/Ink/Editor/Tools/File Icons/Resources/InkFileIcon-retina.psd new file mode 100644 index 0000000000000000000000000000000000000000..ff7517e03d73e3ee32740fa550d3f60fd91c99ab GIT binary patch literal 29421 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 P9zT=t;FL#}2 literal 0 HcmV?d00001 diff --git a/Assets/Ink/Editor/Tools/File Icons/Resources/InkFileIcon.psd b/Assets/Ink/Editor/Tools/File Icons/Resources/InkFileIcon.psd new file mode 100644 index 0000000000000000000000000000000000000000..0ca7d971f51caf11e0cc5addb25cd3f077385e92 GIT binary patch literal 83098 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 H-2MLnsrl_3 literal 0 HcmV?d00001 diff --git a/Assets/Ink/Editor/Tools/File Icons/Resources/InkTodoIcon.psd b/Assets/Ink/Editor/Tools/File Icons/Resources/InkTodoIcon.psd new file mode 100644 index 0000000000000000000000000000000000000000..bb5d8a7bfad4a831a539a43ddd896e6a4fc179e6 GIT binary patch literal 76048 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%0DcU+ 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 G)6BnkT?fMe literal 0 HcmV?d00001 diff --git a/Assets/Ink/Editor/Tools/File Icons/Resources/InkUnknownFileIcon.psd b/Assets/Ink/Editor/Tools/File Icons/Resources/InkUnknownFileIcon.psd new file mode 100644 index 0000000000000000000000000000000000000000..17c620c66ca3fbe31dc81939118b62908aff2ffc GIT binary patch literal 24714 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 literal 0 HcmV?d00001 diff --git a/Assets/Ink/Editor/Tools/File Icons/Resources/InkWarningIcon.psd b/Assets/Ink/Editor/Tools/File Icons/Resources/InkWarningIcon.psd new file mode 100644 index 0000000000000000000000000000000000000000..f01ac785642892997c25befde9b57b2c78c9fc34 GIT binary patch literal 66606 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 literal 0 HcmV?d00001 diff --git a/Assets/Ink/Editor/Tools/Ink Inspector/DefaultAssetEditor.cs b/Assets/Ink/Editor/Tools/Ink Inspector/DefaultAssetEditor.cs new file mode 100644 index 0000000..5289271 --- /dev/null +++ b/Assets/Ink/Editor/Tools/Ink Inspector/DefaultAssetEditor.cs @@ -0,0 +1,60 @@ +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace Ink.UnityIntegration { + [CustomEditor(typeof(DefaultAsset), true)] + public class DefaultAssetEditor : Editor { + + private DefaultAssetInspector inspector; + + private void OnEnable () { + inspector = FindObjectInspector (); + if(inspector != null) { + inspector.editor = this; + inspector.serializedObject = serializedObject; + inspector.target = target; + inspector.OnEnable(); + } + } + + private void OnDisable () { + if(inspector != null) + inspector.OnDisable(); + } + + protected override void OnHeaderGUI () { + if(inspector != null) { + inspector.OnHeaderGUI(); + } + else + base.OnHeaderGUI(); + } + + public override void OnInspectorGUI () { + if(inspector != null) { + GUI.enabled = true; + inspector.OnInspectorGUI(); + } + else + base.OnInspectorGUI(); + } + + private DefaultAssetInspector FindObjectInspector () { + var assembly = Assembly.GetExecutingAssembly(); + var assetPath = AssetDatabase.GetAssetPath(target); + foreach(var type in assembly.GetTypes()) { + if(type.IsSubclassOf(typeof(DefaultAssetInspector))) { + DefaultAssetInspector objectInspector = (DefaultAssetInspector)Activator.CreateInstance(type); + if(objectInspector.IsValid(assetPath)) { + objectInspector.target = target; + return objectInspector; + } + } + } + return null; + } + } +} \ No newline at end of file diff --git a/Assets/Ink/Editor/Tools/Ink Inspector/DefaultAssetInspector.cs b/Assets/Ink/Editor/Tools/Ink Inspector/DefaultAssetInspector.cs new file mode 100644 index 0000000..70816a0 --- /dev/null +++ b/Assets/Ink/Editor/Tools/Ink Inspector/DefaultAssetInspector.cs @@ -0,0 +1,19 @@ +using UnityEngine; +using UnityEditor; + +namespace Ink.UnityIntegration { + public abstract class DefaultAssetInspector { + // Reference to the actual editor we draw to + public Editor editor; + // Shortcut to the target object + public Object target; + // Shortcut to the serializedObject + public SerializedObject serializedObject; + + public abstract bool IsValid(string assetPath); + public virtual void OnEnable () {} + public virtual void OnDisable () {} + public virtual void OnHeaderGUI () {} + public virtual void OnInspectorGUI() {} + } +} \ No newline at end of file diff --git a/Assets/Ink/Editor/Tools/Ink Inspector/InkInspector.cs b/Assets/Ink/Editor/Tools/Ink Inspector/InkInspector.cs new file mode 100644 index 0000000..b8f0a4d --- /dev/null +++ b/Assets/Ink/Editor/Tools/Ink Inspector/InkInspector.cs @@ -0,0 +1,462 @@ +using UnityEngine; +using UnityEditor; +using System; +using System.IO; +using System.Linq; +using System.Collections.Generic; +using UnityEditorInternal; +using Object = UnityEngine.Object; + +namespace Ink.UnityIntegration { + public class InkInspector : DefaultAssetInspector { + + private InkFile inkFile; + private ReorderableList includesFileList; + private ReorderableList mastersFileList; + private ReorderableList errorList; + private ReorderableList warningList; + private ReorderableList todosList; + private string cachedTrimmedFileContents; + private const int maxCharacters = 16000; + + public override bool IsValid(string assetPath) { + return Path.GetExtension(assetPath) == InkEditorUtils.inkFileExtension; + } + + public override void OnHeaderGUI () { + GUILayout.BeginHorizontal(); + GUILayout.Space(38f); + GUILayout.BeginVertical(); + GUILayout.Space(19f); + GUILayout.BeginHorizontal(); + + GUILayoutUtility.GetRect(10f, 10f, 16f, 35f, EditorStyles.layerMaskField); + GUILayout.FlexibleSpace(); + + EditorGUI.BeginDisabledGroup(inkFile == null); + if (GUILayout.Button("Open", EditorStyles.miniButton)) { + AssetDatabase.OpenAsset(inkFile.inkAsset, 3); + GUIUtility.ExitGUI(); + } + EditorGUI.EndDisabledGroup(); + + GUILayout.EndHorizontal(); + GUILayout.EndVertical(); + GUILayout.EndHorizontal(); + + Rect lastRect = GUILayoutUtility.GetLastRect(); + Rect rect = new Rect(lastRect.x, lastRect.y, lastRect.width, lastRect.height); + Rect iconRect = new Rect(rect.x + 6f, rect.y + 6f, 32f, 32f); + GUI.DrawTexture(iconRect, InkBrowserIcons.inkFileIconLarge); + Rect childIconRect = new Rect(iconRect.x, iconRect.y, 16f, 16f); + if(inkFile == null) { + GUI.DrawTexture(childIconRect, InkBrowserIcons.unknownFileIcon, ScaleMode.ScaleToFit); + } else if(inkFile.isIncludeFile) { + GUI.DrawTexture(childIconRect, InkBrowserIcons.childIconLarge, ScaleMode.ScaleToFit); + } + + Rect titleRect = new Rect(rect.x + 44f, rect.y + 6f, rect.width - 44f - 38f - 4f, 16f); + titleRect.yMin -= 2f; + titleRect.yMax += 2f; + GUI.Label(titleRect, editor.target.name, EditorStyles.largeLabel); + } + + public override void OnEnable () { + Rebuild(); + InkCompiler.OnCompileInk += OnCompileInk; + } + + public override void OnDisable () { + InkCompiler.OnCompileInk -= OnCompileInk; + } + + void OnCompileInk (InkFile[] inkFiles) { + // We could probably be smarter about when we rebuild - only rebuilding if the file that's shown in the inspector is in the list - but it's not frequent or expensive so it's not important! + Rebuild(); + } + + void Rebuild () { + cachedTrimmedFileContents = ""; + string assetPath = AssetDatabase.GetAssetPath(target); + inkFile = InkLibrary.GetInkFileWithPath(assetPath); + if(inkFile == null) + return; + + if (inkFile.includes.Count > 0) CreateIncludeList (); + else includesFileList = null; + + if (inkFile.masterInkAssets.Count > 0) CreateMastersList (); + else mastersFileList = null; + + errorList = CreateErrorList(); + warningList = CreateWarningList(); + todosList = CreateTodoList(); + + cachedTrimmedFileContents = inkFile.GetFileContents(); + cachedTrimmedFileContents = cachedTrimmedFileContents.Substring(0, Mathf.Min(cachedTrimmedFileContents.Length, maxCharacters)); + if(cachedTrimmedFileContents.Length >= maxCharacters) + cachedTrimmedFileContents += "...\n\n<...etc...>"; + } + + void CreateIncludeList () { + List includeTextAssets = inkFile.includes; + includesFileList = new ReorderableList(includeTextAssets, typeof(DefaultAsset), false, true, false, false); + includesFileList.drawHeaderCallback = (Rect rect) => { + EditorGUI.LabelField(rect, "Included Files"); + }; + includesFileList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => { + DefaultAsset childAssetFile = ((List)includesFileList.list)[index]; + if(childAssetFile == null) { + Debug.LogError("Ink file in include list is null. This should never occur. Use Assets > Recompile Ink to fix this issue."); + EditorGUI.LabelField(rect, new GUIContent("Warning: Ink File in include list is null. Use Assets > Recompile Ink to fix this issue.")); + return; + } + InkFile childInkFile = InkLibrary.GetInkFileWithFile(childAssetFile); + if(childInkFile == null) { + Debug.LogError("Ink File for included file "+childAssetFile+" not found. This should never occur. Use Assets > Recompile Ink to fix this issue."); + EditorGUI.LabelField(rect, new GUIContent("Warning: Ink File for included file "+childAssetFile+" not found. Use Assets > Recompile Ink to fix this issue.")); + return; + } + Rect iconRect = new Rect(rect.x, rect.y, 0, 16); + if(childInkFile.hasErrors || childInkFile.hasWarnings) { + iconRect.width = 20; + } + Rect objectFieldRect = new Rect(iconRect.xMax, rect.y, rect.width - iconRect.width - 80, 16); + Rect selectRect = new Rect(objectFieldRect.xMax, rect.y, 80, 16); + if(childInkFile.hasErrors) { + EditorGUI.LabelField(iconRect, new GUIContent(InkBrowserIcons.errorIcon)); + } else if(childInkFile.hasWarnings) { + EditorGUI.LabelField(iconRect, new GUIContent(InkBrowserIcons.warningIcon)); + } + EditorGUI.BeginDisabledGroup(true); + EditorGUI.ObjectField(objectFieldRect, childAssetFile, typeof(Object), false); + EditorGUI.EndDisabledGroup(); + if(GUI.Button(selectRect, "Select")) { + Selection.activeObject = childAssetFile; + } + }; + } + + void CreateMastersList () { + List mastersTextAssets = inkFile.masterInkAssets; + mastersFileList = new ReorderableList(mastersTextAssets, typeof(DefaultAsset), false, true, false, false); + mastersFileList.drawHeaderCallback = (Rect rect) => { + EditorGUI.LabelField(rect, "Master Files"); + }; + mastersFileList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => { + DefaultAsset masterAssetFile = ((List)mastersFileList.list)[index]; + if(masterAssetFile == null) { + Debug.LogError("Ink file in masters list is null. This should never occur. Use Assets > Recompile Ink to fix this issue."); + EditorGUI.LabelField(rect, new GUIContent("Warning: Ink File in masters list is null. Use Assets > Recompile Ink to fix this issue.")); + return; + } + InkFile masterInkFile = InkLibrary.GetInkFileWithFile(masterAssetFile); + if(masterInkFile == null) { + Debug.LogError("Ink File for master file "+masterAssetFile+" not found. This should never occur. Use Assets > Recompile Ink to fix this issue."); + EditorGUI.LabelField(rect, new GUIContent("Warning: Ink File for master file "+masterAssetFile+" not found. Use Assets > Recompile Ink to fix this issue.")); + return; + } + Rect iconRect = new Rect(rect.x, rect.y, 0, 16); + if(masterInkFile.hasErrors || masterInkFile.hasWarnings) { + iconRect.width = 20; + } + Rect objectFieldRect = new Rect(iconRect.xMax, rect.y, rect.width - iconRect.width - 80, 16); + Rect selectRect = new Rect(objectFieldRect.xMax, rect.y, 80, 16); + if(masterInkFile.hasErrors) { + EditorGUI.LabelField(iconRect, new GUIContent(InkBrowserIcons.errorIcon)); + } else if(masterInkFile.hasWarnings) { + EditorGUI.LabelField(iconRect, new GUIContent(InkBrowserIcons.warningIcon)); + } + EditorGUI.BeginDisabledGroup(true); + EditorGUI.ObjectField(objectFieldRect, masterAssetFile, typeof(Object), false); + EditorGUI.EndDisabledGroup(); + if(GUI.Button(selectRect, "Select")) { + Selection.activeObject = masterAssetFile; + } + + + // foreach(var masterInkFile in inkFile.masterInkFiles) { + // EditorGUILayout.BeginHorizontal(); + // if(masterInkFile.hasErrors) { + // GUILayout.Label(new GUIContent(InkBrowserIcons.errorIcon), GUILayout.Width(20)); + // } else if(masterInkFile.hasWarnings) { + // GUILayout.Label(new GUIContent(InkBrowserIcons.warningIcon), GUILayout.Width(20)); + // } + // EditorGUI.BeginDisabledGroup(true); + // EditorGUILayout.ObjectField("Master Ink File", masterInkFile.inkAsset, typeof(Object), false); + // EditorGUI.EndDisabledGroup(); + // if(GUILayout.Button("Select", GUILayout.Width(80))) { + // Selection.activeObject = masterInkFile.inkAsset; + // } + // EditorGUILayout.EndHorizontal(); + // } + }; + } + + ReorderableList CreateErrorList () { + var reorderableList = new ReorderableList(inkFile.errors, typeof(string), false, true, false, false); + reorderableList.drawHeaderCallback = (Rect rect) => { + EditorGUI.LabelField(rect, new GUIContent(InkBrowserIcons.errorIcon), new GUIContent("Errors")); + }; + reorderableList.elementHeight = 26; + reorderableList.drawElementCallback = (rect, index, isActive, isFocused) => DrawLogItem(rect, index, isActive, isFocused, (List)reorderableList.list); + return reorderableList; + } + + ReorderableList CreateWarningList () { + var reorderableList = new ReorderableList(inkFile.warnings, typeof(string), false, true, false, false); + reorderableList.drawHeaderCallback = (Rect rect) => { + EditorGUI.LabelField(rect, new GUIContent(InkBrowserIcons.warningIcon), new GUIContent("Warnings")); + }; + reorderableList.elementHeight = 26; + reorderableList.drawElementCallback = (rect, index, isActive, isFocused) => DrawLogItem(rect, index, isActive, isFocused, (List)reorderableList.list); + return reorderableList; + } + + ReorderableList CreateTodoList () { + var reorderableList = new ReorderableList(inkFile.todos, typeof(string), false, true, false, false); + reorderableList.drawHeaderCallback = (Rect rect) => { + EditorGUI.LabelField(rect, "To do"); + }; + reorderableList.elementHeight = 26; + reorderableList.drawElementCallback = (rect, index, isActive, isFocused) => DrawLogItem(rect, index, isActive, isFocused, (List)reorderableList.list); + return reorderableList; + } + + void DrawLogItem (Rect rect, int index, bool isActive, bool isFocused, List logsList) { + Rect logRect = new Rect(rect.x, rect.y, rect.width - 80, 16); + Rect locationRect = new Rect(rect.x, rect.y+16, rect.width - 80, 10); + Rect buttonRect = new Rect(logRect.xMax, rect.y, 80, rect.height-2); + InkCompilerLog log = logsList[index]; + GUI.Label(logRect, log.content); + GUI.Label(locationRect, "("+log.relativeFilePath+":"+log.lineNumber+")", filePathAndLineNumberStyle); + string openLabel = "Open"; + if(GUI.Button(buttonRect, openLabel)) { + InkEditorUtils.OpenInEditor(inkFile, log); + } + } + static GUIStyle _filePathAndLineNumberStyle; + static GUIStyle filePathAndLineNumberStyle { + get { + if(_filePathAndLineNumberStyle == null) { + _filePathAndLineNumberStyle = new GUIStyle(EditorStyles.centeredGreyMiniLabel); + _filePathAndLineNumberStyle.alignment = TextAnchor.MiddleLeft; + } + return _filePathAndLineNumberStyle; + } + } + + public static void DrawLayoutInkLine (InkFile inkFile, int lineNumber, string label) { + GUILayout.BeginHorizontal(); + GUILayout.Label(label); + string openLabel = "Open"+ (lineNumber == -1 ? "" : " ("+lineNumber+")"); + if(GUILayout.Button(openLabel, GUILayout.Width(80))) { + InkEditorUtils.OpenInEditor(inkFile.filePath, null, lineNumber); + } + GUILayout.EndHorizontal(); + } + + public override void OnInspectorGUI () { + editor.Repaint(); + serializedObject.Update(); + if(inkFile == null) { + EditorGUILayout.HelpBox("Ink File is not in library.", MessageType.Warning); + if(GUILayout.Button("Rebuild Library")) { + InkLibrary.Rebuild(); + Rebuild(); + } + return; + } + + + if(InkCompiler.IsInkFileOnCompilationStack(inkFile)) { + EditorGUILayout.HelpBox("File is compiling...", MessageType.Info); + return; + } + + if(inkFile.isIncludeFile) { + EditorGUI.BeginChangeCheck(); + var newCompileAsIfMaster = EditorGUILayout.Toggle(new GUIContent("Should also be Master File", "This file is included by another ink file. Typically, these files don't want to be compiled, but this option enables them to be for special purposes."), InkSettings.instance.includeFilesToCompileAsMasterFiles.Contains(inkFile.inkAsset)); + if(EditorGUI.EndChangeCheck()) { + if(newCompileAsIfMaster) { + InkSettings.instance.includeFilesToCompileAsMasterFiles.Add(inkFile.inkAsset); + EditorUtility.SetDirty(InkSettings.instance); + } else { + InkSettings.instance.includeFilesToCompileAsMasterFiles.Remove(inkFile.inkAsset); + EditorUtility.SetDirty(InkSettings.instance); + } + } + EditorApplication.RepaintProjectWindow(); + } + + if(inkFile.isMaster) { + EditorGUILayout.BeginVertical(EditorStyles.helpBox); + DrawMasterFileHeader(); + + EditorGUILayout.Space(); + + // There's no point letting users compile when recursive INCLUDE files exist, so hide anything else while they exist! + if(inkFile.hasRecursiveIncludeErrorPaths) { + EditorGUILayout.HelpBox("A recursive INCLUDE connection exists in this ink file's INCLUDE hierarchy.\nThe offending INCLUDE(s) can be found at the following file(s):\n"+string.Join("\n", inkFile.recursiveIncludeErrorPaths.Select(x => "• "+x)), MessageType.Error); + } else { + if(inkFile.hasUnhandledCompileErrors) { + EditorGUILayout.HelpBox("Last compiled failed", MessageType.Error); + } if(inkFile.hasErrors) { + EditorGUILayout.HelpBox("Last compiled had errors", MessageType.Error); + } else if(inkFile.hasWarnings) { + EditorGUILayout.HelpBox("Last compile had warnings", MessageType.Warning); + } else if(inkFile.jsonAsset == null) { + EditorGUILayout.HelpBox("Ink file has not been compiled", MessageType.Warning); + } + if(inkFile.requiresCompile && GUILayout.Button("Compile")) { + InkCompiler.CompileInk(inkFile); + } + + DrawCompileErrors(); + DrawErrors(); + DrawWarnings(); + DrawTODOList(); + } + + DrawIncludedFiles(); + EditorGUILayout.EndVertical(); + + EditorGUILayout.Space(); + } + + if (inkFile.isIncludeFile) { + EditorGUILayout.BeginVertical(EditorStyles.helpBox); + EditorGUILayout.LabelField(new GUIContent("Include File", InkBrowserIcons.childIconLarge, "This file is included by at least one other file"), EditorStyles.boldLabel); + DrawListOfMasterFiles(); + EditorGUILayout.EndVertical(); + + EditorGUILayout.Space(); + } + + DrawFileContents (); + + + serializedObject.ApplyModifiedProperties(); + } + + void DrawMasterFileHeader () { + EditorGUILayout.LabelField(new GUIContent("Master File", "This file is a master file and can be compiled"), EditorStyles.boldLabel); + + if(inkFile.jsonAsset != null && inkFile.errors.Count == 0 && GUILayout.Button("Play")) { + InkPlayerWindow.LoadAndPlay(inkFile.jsonAsset); + } + + EditorGUILayout.Space(); + + EditorGUI.BeginDisabledGroup(true); + EditorGUILayout.ObjectField("JSON Asset", inkFile.jsonAsset, typeof(TextAsset), false); + EditorGUI.EndDisabledGroup(); + DrawEditAndCompileDates(inkFile); + if(!InkSettings.instance.compileAllFilesAutomatically) { + EditorGUI.BeginChangeCheck(); + var newCompileAutomatically = EditorGUILayout.Toggle(new GUIContent("Compile Automatially", "If true, this file recompiles automatically when any changes are detected."), InkSettings.instance.ShouldCompileInkFileAutomatically(inkFile)); + if(EditorGUI.EndChangeCheck()) { + if(newCompileAutomatically) { + InkSettings.instance.filesToCompileAutomatically.Add(inkFile.inkAsset); + EditorUtility.SetDirty(InkSettings.instance); + } else { + InkSettings.instance.filesToCompileAutomatically.Remove(inkFile.inkAsset); + EditorUtility.SetDirty(InkSettings.instance); + } + } + EditorApplication.RepaintProjectWindow(); + } + +// if(!checkedStoryForErrors) { +// if(GUILayout.Button("Check for errors")) { +// GetStoryErrors(); +// } +// } else { +// if(exception != null) { +// EditorGUILayout.HelpBox("Story is invalid\n"+exception.ToString(), MessageType.Error); +// } else { +// EditorGUILayout.HelpBox("Story is valid", MessageType.Info); +// } +// } + } + + void DrawListOfMasterFiles() { + if(mastersFileList != null && mastersFileList.count > 0) { + mastersFileList.DoLayoutList(); + } + } + + void DrawEditAndCompileDates (InkFile masterInkFile) { + string editAndCompileDateString = ""; + DateTime lastEditDate = inkFile.lastEditDate; + editAndCompileDateString += "Last edit date "+lastEditDate.ToString(); + if(masterInkFile.jsonAsset != null) { + DateTime lastCompileDate = masterInkFile.lastCompileDate; + editAndCompileDateString += "\nLast compile date "+lastCompileDate.ToString(); + if(lastEditDate > lastCompileDate) { + if(EditorApplication.isPlaying && InkSettings.instance.delayInPlayMode) { + editAndCompileDateString += "\nWill compile on exiting play mode"; + EditorGUILayout.HelpBox(editAndCompileDateString, MessageType.Info); + } else { + EditorGUILayout.HelpBox(editAndCompileDateString, MessageType.Warning); + } + } else { + EditorGUILayout.HelpBox(editAndCompileDateString, MessageType.None); + } + } else { + EditorGUILayout.HelpBox(editAndCompileDateString, MessageType.None); + } + } + + void DrawIncludedFiles () { + if(includesFileList != null && includesFileList.count > 0) { + includesFileList.DoLayoutList(); + } + } + + void DrawCompileErrors () { + if(inkFile.unhandledCompileErrors.Count == 0) + return; + EditorGUILayout.BeginVertical(GUI.skin.box); + EditorGUILayout.HelpBox("Compiler bug prevented compilation of JSON file. Please help us fix it by reporting this as a bug.", MessageType.Error); + EditorGUILayout.BeginHorizontal(); + if(GUILayout.Button("Report via Github")) { + Application.OpenURL("https://github.com/inkle/ink-unity-integration/issues/new"); + } + if(GUILayout.Button("Report via Email")) { + Application.OpenURL("mailto:info@inklestudios.com"); + } + EditorGUILayout.EndHorizontal(); + foreach(string compileError in inkFile.unhandledCompileErrors) { + GUILayout.TextArea(compileError); + } + EditorGUILayout.EndVertical(); + } + + void DrawErrors () { + if(errorList != null && errorList.count > 0) { + errorList.DoLayoutList(); + } + } + + void DrawWarnings () { + if(warningList != null && warningList.count > 0) { + warningList.DoLayoutList(); + } + } + + void DrawTODOList () { + if(todosList != null && todosList.count > 0) { + todosList.DoLayoutList(); + } + } + + void DrawFileContents () { + float width = EditorGUIUtility.currentViewWidth-50; + float height = EditorStyles.wordWrappedLabel.CalcHeight(new GUIContent(cachedTrimmedFileContents), width); + EditorGUILayout.BeginVertical(EditorStyles.textArea); + EditorGUILayout.SelectableLabel(cachedTrimmedFileContents, EditorStyles.wordWrappedLabel, GUILayout.ExpandHeight(true), GUILayout.Width(width), GUILayout.Height(height)); + EditorGUILayout.EndVertical(); + } + } +} \ No newline at end of file diff --git a/Assets/Ink/Editor/Tools/Player Window/InkHistoryContentItem.cs b/Assets/Ink/Editor/Tools/Player Window/InkHistoryContentItem.cs new file mode 100644 index 0000000..29e2033 --- /dev/null +++ b/Assets/Ink/Editor/Tools/Player Window/InkHistoryContentItem.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using Ink.Runtime; +using UnityEngine; + +namespace Ink.UnityIntegration.Debugging { + [System.Serializable] + public class InkHistoryContentItem { + public enum ContentType { + PresentedContent, + ChooseChoice, + PresentedChoice, + EvaluateFunction, + CompleteEvaluateFunction, + ChoosePathString, + Warning, + Error, + DebugNote + } + + public string content; + public List tags; + public ContentType contentType; + // Creating a datetime from a long is slightly expensive (it can happen many times in a frame). To fix this we cache the result once converted. + [SerializeField] JsonDateTime _serializableTime; + [NonSerialized] bool hasDeserializedTime; + [NonSerialized] DateTime _time; + public DateTime time { + get { + if (!hasDeserializedTime) { + _time = _serializableTime; + hasDeserializedTime = true; + } + return _time; + } private set { + _time = value; + _serializableTime = value; + } + } + + InkHistoryContentItem (string text, ContentType contentType) { + this.content = text; + this.contentType = contentType; + this.time = DateTime.Now; + } + InkHistoryContentItem (string text, List tags, ContentType contentType) { + this.content = text; + this.tags = tags; + this.contentType = contentType; + this.time = DateTime.Now; + } + + public static InkHistoryContentItem CreateForContent (string choiceText, List tags) { + return new InkHistoryContentItem(choiceText, tags, InkHistoryContentItem.ContentType.PresentedContent); + } + public static InkHistoryContentItem CreateForPresentChoice (Choice choice) { + return new InkHistoryContentItem(choice.text.Trim(), choice.tags, InkHistoryContentItem.ContentType.PresentedChoice); + } + public static InkHistoryContentItem CreateForMakeChoice (Choice choice) { + return new InkHistoryContentItem(choice.text.Trim(), choice.tags, InkHistoryContentItem.ContentType.ChooseChoice); + } + public static InkHistoryContentItem CreateForEvaluateFunction (string functionInfoText) { + return new InkHistoryContentItem(functionInfoText, InkHistoryContentItem.ContentType.EvaluateFunction); + } + public static InkHistoryContentItem CreateForCompleteEvaluateFunction (string functionInfoText) { + return new InkHistoryContentItem(functionInfoText, InkHistoryContentItem.ContentType.CompleteEvaluateFunction); + } + public static InkHistoryContentItem CreateForChoosePathString (string choosePathStringText) { + return new InkHistoryContentItem(choosePathStringText, InkHistoryContentItem.ContentType.ChoosePathString); + } + public static InkHistoryContentItem CreateForWarning (string warningText) { + return new InkHistoryContentItem(warningText, InkHistoryContentItem.ContentType.Warning); + } + public static InkHistoryContentItem CreateForError (string errorText) { + return new InkHistoryContentItem(errorText, InkHistoryContentItem.ContentType.Error); + } + public static InkHistoryContentItem CreateForDebugNote (string noteText) { + return new InkHistoryContentItem(noteText, InkHistoryContentItem.ContentType.DebugNote); + } + + struct JsonDateTime { + public long value; + public static implicit operator DateTime(JsonDateTime jdt) { + return DateTime.FromFileTime(jdt.value); + } + public static implicit operator JsonDateTime(DateTime dt) { + JsonDateTime jdt = new JsonDateTime(); + jdt.value = dt.ToFileTime(); + return jdt; + } + } + } +} \ No newline at end of file diff --git a/Assets/Ink/Editor/Tools/Player Window/InkPlayerWindow.cs b/Assets/Ink/Editor/Tools/Player Window/InkPlayerWindow.cs new file mode 100644 index 0000000..bc1a152 --- /dev/null +++ b/Assets/Ink/Editor/Tools/Player Window/InkPlayerWindow.cs @@ -0,0 +1,3058 @@ +using UnityEngine; +using UnityEditorInternal; +using UnityEditor; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Linq; +using Ink.Runtime; +using Ink.UnityIntegration.Debugging; + +namespace Ink.UnityIntegration { + + ///

+ /// Ink player window. Tests stories in an editor window. + /// Stories may be attached at runtime. InkPlayerWindow.DrawStoryPropertyField may be used for this. + /// + public class InkPlayerWindow : EditorWindow { + #region User Facing + + public static bool visible {get; private set;} + public static bool isOpen {get; private set;} + public static bool attached {get; private set;} + + + // Fires when story is set. Handy if you want to perform actions on the story as soon as it's tethered. + public static Action OnDidSetStory; + + // Overrides the action triggered by buttons that display story.currentChoices. + public static Action OnChooseChoiceIndexOverride; + + + // Overrides the "Divert" button for named content. Allows for custom ChoosePathString functionality. + public static Action OnDivertOverride; + // Overrides the "Divert" button label. Can be handy for making it clear that Divert has been overridden in different contexts. + public static Func OnDivertLabelOverride; + + + // Allows injecting right click context options into the story content view. + public delegate void ContextMenuDelegate(GenericMenu contextMenu, InkHistoryContentItem content); + public static List contextMenuDelegates = new List(); + + + + public static InkPlayerParams playerParams = InkPlayerParams.Standard; + public static PlayerOptions playerOptions = new PlayerOptions(); + + + + // Create or get the window. If creating, dock it on the same panel as the inspector. + [MenuItem("Window/Ink Player %#i", false, 2300)] + public static InkPlayerWindow GetWindow () { + return GetWindow(true); + } + + public static InkPlayerWindow GetWindow (bool focus) { + Type windowType = typeof(Editor).Assembly.GetType("UnityEditor.InspectorWindow"); + return GetWindow(windowTitle, focus, windowType); + } + + + + + + // Entry point for loading and playing a story. + public static void LoadAndPlay (TextAsset storyJSONTextAsset, bool focusWindow = true) { + GetWindow(focusWindow); + if(InkPlayerWindow.story != null) { + if(EditorUtility.DisplayDialog("Story in progress", "The Ink Player Window is already playing a story. Would you like to stop it and load the new story?", "Stop and load", "Cancel")) { + InkPlayerWindow.Stop(); + InkPlayerWindow.Play(storyJSONTextAsset); + } + } else { + InkPlayerWindow.Play(storyJSONTextAsset); + } + } + + public static void LoadAndPlay (string storyJSON, bool focusWindow = true) { + GetWindow(focusWindow); + if(InkPlayerWindow.story != null) { + if(EditorUtility.DisplayDialog("Story in progress", "The Ink Player Window is already playing a story. Would you like to stop it and load the new story?", "Stop and load", "Cancel")) { + InkPlayerWindow.Stop(); + InkPlayerWindow.Play(storyJSON); + } + } else { + InkPlayerWindow.Play(storyJSON); + } + } + + // Handy utility for the common case of not wanting to show the ink player window when game view is maximised + public static bool GetGameWindowIsMaximised () { + var gameViewType = typeof(EditorWindow).Assembly.GetType("UnityEditor.GameView"); + var gameWindow = EditorWindow.GetWindow(gameViewType); + return gameWindow == null ? false : gameWindow.maximized; + } + + + // Loads an existing story to the player window. Handy for debugging stories running in games in editor. + public static void Attach (Story story) { + Attach(story, InkPlayerWindow.InkPlayerParams.DisableInteraction); + } + public static void Attach (Story story, InkPlayerParams inkPlayerParams) { + Clear(); + playerOptions.continueAutomatically = false; + playerOptions.chooseAutomatically = false; + playerParams = inkPlayerParams; + attached = true; + attachedWhileInPlayMode = EditorApplication.isPlaying; + InkPlayerWindow.story = story; + + // Clear the last loaded story setup on attaching stories. We don't NEED to do this but it's never really helpful and often seems like a bug. + InkPlayerWindowState.Instance.lastStoryJSONAssetPath = null; + InkPlayerWindowState.Instance.lastStoryWasPlaying = false; + + // This allows reconstructing the story so it can be used after recompile. However, it can be expensive to run so there's a good argument for not running it on play! + // var lastTime = Time.realtimeSinceStartup; + // storyJSON = InkPlayerWindow.story.ToJson(); + // File.WriteAllText(System.IO.Path.Combine(System.IO.Path.GetTempPath(), "AttachedStory.json"), storyJSON); + // Debug.Log("Wrote to "+System.IO.Path.Combine(System.IO.Path.GetTempPath(), "AttachedStory.json")+" in "+(Time.realtimeSinceStartup-lastTime)); + } + + // Detaches the attached story + public static void Detach () { + DetachInstance(); + } + + + /// + /// Draws a property field for a story using GUILayout, allowing you to attach stories to the player window for debugging. + /// An example of how this is used is found in the Demo scene. + /// + /// Story. + /// Label. + public static void DrawStoryPropertyField (Story story, ref bool expanded, GUIContent label) { + DrawStoryPropertyField(story, InkPlayerParams.DisableInteraction, ref expanded, label); + } + public static void DrawStoryPropertyField (Story story, InkPlayerParams playerParams, ref bool expanded, GUIContent label, bool interactable = false) { + EditorGUILayout.BeginHorizontal(); + expanded = EditorGUILayout.Foldout(expanded, label, true); + // var lastRect = GUILayoutUtility.GetLastRect(); + // GUILayout.BeginArea(new Rect(lastRect.x+200,lastRect.y,lastRect.width-200,lastRect.height)); + // Debug.Log(lastRect); + // GUI.Box(lastRect,""); + // GUILayout.BeginArea(lastRect); + if(EditorApplication.isPlaying) { + if(story != null) { + // InkPlayerWindow window = InkPlayerWindow.GetWindow(false); + if(InkPlayerWindow.attached && InkPlayerWindow.story == story) { + if(GUILayout.Button("Detach", GUILayout.Width(80))) { + InkPlayerWindow.Detach(); + } + } else { + if(GUILayout.Button("Attach", GUILayout.Width(80))) { + InkPlayerWindow.Attach(story, playerParams); + } + } + // EditorGUI.BeginDisabledGroup(visible); + if(GUILayout.Button(InkPlayerWindow.isOpen ? "Show Player Window" : "Open Player Window", GUILayout.Width(140))) { + InkPlayerWindow.GetWindow(); + } + } else { + EditorGUI.BeginDisabledGroup(true); + GUILayout.Button("Story cannot be null to attach to editor"); + EditorGUI.EndDisabledGroup(); + } + } else { + EditorGUI.BeginDisabledGroup(true); + GUILayout.Button("Enter play mode to attach to editor", GUILayout.Width(220)); + EditorGUI.EndDisabledGroup(); + } + // GUILayout.EndArea(); + EditorGUILayout.EndHorizontal(); + if(expanded) { + + if(story != null) { + EditorGUI.indentLevel++; + EditorGUI.BeginDisabledGroup(!interactable); + // Draw can continue + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.Toggle("Can Continue", story.canContinue); + if(GUILayout.Button("Continue")) { + story.Continue(); + } + EditorGUILayout.EndHorizontal(); + + // Draw current text + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PrefixLabel("Current Text"); + EditorGUILayout.TextArea(story.currentText, wordWrappedTextArea); + EditorGUILayout.EndHorizontal(); + + // Draw current choices + foreach(var choice in story.currentChoices) { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Choice "+choice.index, choice.text); + if(GUILayout.Button(new GUIContent("Choose"))) { + if(OnChooseChoiceIndexOverride != null) OnChooseChoiceIndexOverride(choice.index); + else story.ChooseChoiceIndex(choice.index); + } + EditorGUILayout.EndHorizontal(); + } + EditorGUI.EndDisabledGroup(); + EditorGUI.indentLevel--; + } + } + } + + + + /// + /// Draws a property field for a story using GUI, allowing you to attach stories to the player window for debugging. + /// + /// Position. + /// Story. + /// Label. + public static void DrawStoryPropertyField (Rect position, Story story, GUIContent label) { + position = EditorGUI.PrefixLabel(position, label); + InkPlayerWindow.GetWindow(false); + if(EditorApplication.isPlaying && story != null/* && story.state != null*/) { + if(InkPlayerWindow.attached && InkPlayerWindow.story == story) { + if(GUI.Button(position, "Detach")) { + InkPlayerWindow.Detach(); + } + } else { + if(GUI.Button(position, "Attach")) { + InkPlayerWindow.Attach(story); + } + } + } else { + EditorGUI.BeginDisabledGroup(true); + GUI.Button(position, "Enter play mode to attach to editor"); + EditorGUI.EndDisabledGroup(); + } + } + + + + + + // Allows you to change what the ink player does/is allowed to do when a story is loaded. + // Especially handy for attached stories, where performance is critical or play controls might interfere with the game + // TODO: Show these params somewhere slightly out of the way (debug mode for the window?) so you can fiddle with them mid-game if you really need to + public struct InkPlayerParams { + public bool disablePlayControls; + public bool disableUndoHistory; + public bool disableChoices; + public bool disableStateLoading; + public bool disableSettingVariables; + public bool profileOnStart; + + public static InkPlayerParams Standard { + get { + return new InkPlayerParams(); + } + } + public static InkPlayerParams DisableInteraction { + get { + var inkPlayerParams = new InkPlayerParams(); + inkPlayerParams.disablePlayControls = true; + inkPlayerParams.disableUndoHistory = true; + inkPlayerParams.disableChoices = true; + inkPlayerParams.disableStateLoading = true; + inkPlayerParams.disableSettingVariables = true; + inkPlayerParams.profileOnStart = false; + return inkPlayerParams; + } + } + } + + + // Allows telling the story to play automatically. + [System.Serializable] + public class PlayerOptions { + public bool continueAutomatically = true; + public bool chooseAutomatically = false; + public float continueAutomaticallyTimeInterval = 0.1f; + public float chooseAutomaticallyTimeInterval = 0.1f; + } + + #endregion + + + + + + static string storyJSON; + static DateTime currentStoryJSONLastEditDateTime; + + private static Story _story; + public static Story story { + get { + return _story; + } private set { + if(_story != null) { + OnUnsetStory(); + } + _story = value; + if(_story != null) { + OnSetStory(); + } + } + } + + + private static TextAsset _storyStateTextAsset; + public static TextAsset storyStateTextAsset { + get { + return _storyStateTextAsset; + } set { + if(_storyStateTextAsset == value) + return; + _storyStateTextAsset = value; + if(_storyStateTextAsset != null) + storyStateValid = InkEditorUtils.CheckStoryStateIsValid(storyJSONTextAsset.text, storyStateTextAsset.text); + } + } + + + + + + [System.Serializable] + public class InkPlayerWindowState { + static string settingsEditorPrefsKey = typeof(InkPlayerWindowState).Name +" Settings"; + public static event Action OnCreateOrLoad; + static InkPlayerWindowState _Instance; + public static InkPlayerWindowState Instance { + get { + if(_Instance == null) LoadOrCreateAndSave(); + return _Instance; + } + } + + static InkPlayerWindowState LoadOrCreateAndSave () { + Load(); + if(_Instance == null) CreateAndSave(); + return _Instance; + } + + public static void CreateAndSave () { + _Instance = new InkPlayerWindowState(); + Save(_Instance); + if(OnCreateOrLoad != null) OnCreateOrLoad(); + } + + public static void Save () { + Save(_Instance); + } + + public static void Save (InkPlayerWindowState settings) { + string data = JsonUtility.ToJson(settings); + EditorPrefs.SetString(settingsEditorPrefsKey, data); + } + + static void Load () { + if(!EditorPrefs.HasKey(settingsEditorPrefsKey)) return; + string data = EditorPrefs.GetString(settingsEditorPrefsKey); + try { + _Instance = JsonUtility.FromJson(data); + if(_Instance != null) if(OnCreateOrLoad != null) OnCreateOrLoad(); + } catch { + Debug.LogError("Save Data was corrupt and could not be parsed. New data created. Old data was:\n"+data); + CreateAndSave(); + } + } + + public string lastStoryJSONAssetPath; + public bool lastStoryWasPlaying; + public TextAsset TryGetLastStoryJSONAsset () { + if(lastStoryJSONAssetPath == null) return null; + var asset = AssetDatabase.LoadAssetAtPath(lastStoryJSONAssetPath); + if(asset == null) { + lastStoryJSONAssetPath = null; + Save(); + } + return asset; + } + + public StoryPanelState storyPanelState = new StoryPanelState() {showing=true}; + public BaseStoryPanelState choicePanelState = new BaseStoryPanelState() {showing=true}; + public BaseStoryPanelState storyStatePanelState = new BaseStoryPanelState(); + public BaseStoryPanelState profilerPanelState = new BaseStoryPanelState(); + public BaseStoryPanelState saveLoadPanelState = new BaseStoryPanelState(); + // public DivertPanelState divertPanelState = new DivertPanelState(); + public NamedContentPanelState namedContentPanelState = new NamedContentPanelState(); + public FunctionPanelState functionPanelState = new FunctionPanelState(); + // public FunctionPanelState.FunctionParams functionParams = new FunctionPanelState.FunctionParams(); + public VariablesPanelState variablesPanelState = new VariablesPanelState(); + public ObservedVariablesPanelState observedVariablesPanelState = new ObservedVariablesPanelState(); + } + + + private const string windowTitle = "Ink Player"; + + static bool attachedWhileInPlayMode {get; set;} + + static TextAsset _storyJSONTextAsset; + static TextAsset storyJSONTextAsset { + get { + return _storyJSONTextAsset; + } set { + if(_storyJSONTextAsset == value) return; + _storyJSONTextAsset = value; + if (_storyJSONTextAsset != null) { + InkPlayerWindowState.Instance.lastStoryJSONAssetPath = AssetDatabase.GetAssetPath(storyJSONTextAsset); + string fullJSONFilePath = InkEditorUtils.UnityRelativeToAbsolutePath(InkPlayerWindowState.Instance.lastStoryJSONAssetPath); + currentStoryJSONLastEditDateTime = File.GetLastWriteTime(fullJSONFilePath); + } else { + InkPlayerWindowState.Instance.lastStoryJSONAssetPath = null; + } + InkPlayerWindowState.Save(); + } + } + + + + + + // This tracks the story state each time the user advances the story so that we can undo/redo + static UndoHistory storyStateHistory = new UndoHistory(); + // This tracks the story output so we can view it in the content panel + static List storyHistory = new List(); + + + static Exception playStoryException; + static bool storyStateValid = false; + + +// WindowState windowState = new WindowState(); +// public class WindowState { + static Vector2 _scrollPosition; + static Vector2 scrollPosition { + get { + return _scrollPosition; + } set { + if(_scrollPosition == value) return; + _scrollPosition = value; + } + } +// } + + + + [System.Serializable] + public class BaseStoryPanelState { + public bool showing; + [SerializeField] + Vector2 _scrollPosition; + public Vector2 scrollPosition { + get { + return _scrollPosition; + } set { + if(_scrollPosition == value) return; + _scrollPosition = value; + // Deselect lines on scrolling because otherwise unity does weird things with the selection + // Disabled because it was deselecting the search field as you typed + // GUI.FocusControl(null); + } + } + + public float y; + public float height = 200; + } + + [System.Serializable] + public class StoryPanelState : BaseStoryPanelState { + public DisplayOptions displayOptions = new DisplayOptions(); + public string searchString = string.Empty; + + public const float minScrollRectHeight = 30; + public const float maxScrollRectHeight = 480; + + public enum AutoScrollMode { + WhenAtBottom, + Always, + Off + } + // Controls when story view should scroll to the bottom when the story view changes. + public AutoScrollMode autoScrollMode = AutoScrollMode.WhenAtBottom; + } + + + [System.Serializable] + public class NamedContentPanelState : BaseStoryPanelState { + public string searchString = string.Empty; + } + + // [System.Serializable] + // public class DivertPanelState : BaseStoryPanelState { + // public string divertCommand = String.Empty; + // } + + static ReorderableList functionInputList; + [System.Serializable] + public class FunctionPanelState : BaseStoryPanelState { + [System.Serializable] + public class FunctionParams { + [System.Serializable] + public class FunctionInput { + public enum FunctionInputType { + Float, + Int, + String, + Bool, + InkVariable, + InkListVariable + } + public FunctionInputType type; + public float floatValue; + public int intValue; + public string stringValue; + public bool boolValue; + public string inkVariablePath; + public object inkVariableValue; + public InkList inkListVariableValue; + public string inkListVariablePath; + + public void RefreshInkVariableValue (Story story) { + if(!string.IsNullOrWhiteSpace(inkVariablePath)) inkVariableValue = story.variablesState[inkVariablePath]; + else inkVariableValue = null; + } + public void RefreshInkListVariableValue (Story story) { + inkListVariableValue = null; + try { + if(!string.IsNullOrWhiteSpace(inkListVariablePath)) + inkListVariableValue = Ink.Runtime.InkList.FromString(inkListVariablePath, story); + } catch {} + } + + public override int GetHashCode () { + switch(type) { + case FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.Float: + return floatValue.GetHashCode(); + case FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.Int: + return intValue.GetHashCode(); + case FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.String: + return stringValue != null ? stringValue.GetHashCode() : 0; + case FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.Bool: + return boolValue.GetHashCode(); + case FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.InkVariable: + return inkVariablePath != null ? inkVariablePath.GetHashCode() : 0; + case FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.InkListVariable: + return inkListVariablePath != null ? inkListVariablePath.GetHashCode() : 0; + default: + Debug.LogWarning("No hash code for type: "+type); + return 1; + } + } + } + public string functionName = String.Empty; + public List inputs = new List(); + + public int GetInputHashCode () { + int hash = 19; + if(!string.IsNullOrEmpty(functionName)) hash = hash * 31 + functionName.GetHashCode(); + foreach(var item in inputs) hash = (hash * 31) + item.GetHashCode(); + return hash; + } + } + public FunctionParams functionParams = new FunctionParams(); + public int testedFunctionHash; + public DateTime testedFunctionTime; + public object functionReturnValue = null; + } + + [System.Serializable] + public class VariablesPanelState : BaseStoryPanelState { + public string searchString = string.Empty; + public List expandedVariables = new List(); + } + public class ObservedVariablesPanelState : BaseStoryPanelState { + // The cache is used to restore observed variables when the user exits play mode. + public List restorableObservedVariableNames = new List(); + public Dictionary observedVariables = new Dictionary(); + } + + [System.Serializable] + public class DisplayOptions { + [Flags] + public enum VisibilityOptions { + Warnings = 1 << 0, + Errors = 1 << 1, + Content = 1 << 2, + PresentedChoices = 1 << 3, + SelectedChoice = 1 << 4, + Function = 1 << 5, + ChoosePathString = 1 << 6, + DebugNotes = 1 << 7, + TimeStamp = 1 << 8, + EmptyEntries = 1 << 9, + Tags = 1 << 10, + } + public VisibilityOptions visibilityOptions = VisibilityOptions.Warnings | VisibilityOptions.Errors | VisibilityOptions.Content; + + public bool displayWarningsInConsole = true; + public bool displayErrorsInConsole = true; + } + + static GUIStyle searchTextFieldStyle; + static GUIStyle searchCancelButtonStyle; + + internal static DateTime dateTimeNow; + + + static float lastOnGUITime = -1f; + static float lastUpdateTime = -1f; + + + + // Lots of bits to do with the story view scroll rect + public enum AutoScrollSmoothingMode { + NONE, + Snap, + Smooth + } + + static float storyScrollRectBottom; + static bool storyScrollSnappedToBottom; + static AutoScrollSmoothingMode storyScrollMarkedForBottom; + static AutoScrollSmoothingMode storyScrollMarkedForSelectedLine; + static InkHistoryContentItem selectedLine; + + static bool mainScrollViewActive; + + static bool doingAutoscroll; + static float autoscrollTarget; + static float autoscrollVelocity; + static float autoscrollSmoothTime = 0.225f; + + + + static float timeUntilNextAutomaticChoice = 0; + static float timeUntilNextAutomaticContinue = 0; + + + + // TODO - find a way to restore tethered stories after recompile. This is tricky because we don't have a reference to the json, and stories aren't serialized. + // We should probably save the story to this path - but watch out for giant stories. + // var jsonStr = story.ToJson (); + // https://docs.microsoft.com/en-us/dotnet/api/system.io.path.gettemppath + // Directory.temporaryFolder + void OnEnable () { + if(isOpen) return; + isOpen = true; + + InkPlayerWindowState.OnCreateOrLoad += () => { + // InkPlayerWindowState.Instance.functionPanelState.functionParams = InkPlayerWindowState.Instance.functionParams; + BuildFunctionInputList(); + }; + + BuildFunctionInputList(); + + EditorApplication.update += Update; + + if(story == null && !EditorApplication.isPlayingOrWillChangePlaymode) { + var lastLoadedStory = InkPlayerWindowState.Instance.TryGetLastStoryJSONAsset(); + if(lastLoadedStory != null) { + if(InkPlayerWindowState.Instance.lastStoryWasPlaying) { + LoadAndPlay(lastLoadedStory, false); + } else { + TryPrepareInternal(lastLoadedStory); + } + } + } + } + + void OnDisable () { + EditorApplication.update -= Update; + } + + private void OnBecameVisible() { + visible = true; + if(doingAutoscroll) { + InkPlayerWindowState.Instance.storyPanelState.scrollPosition = new Vector2(InkPlayerWindowState.Instance.storyPanelState.scrollPosition.x, autoscrollTarget); + doingAutoscroll = false; + } + } + + void OnBecameInvisible () { + visible = false; + } + + void OnDestroy () { + isOpen = false; + Clear(); + } + + private static void Update () { + var time = Time.realtimeSinceStartup; + var deltaTime = 0f; + if(lastUpdateTime != -1) + deltaTime = time - lastUpdateTime; + lastUpdateTime = time; + + if(story != null) { + timeUntilNextAutomaticChoice -= deltaTime; + if(story.currentChoices.Count > 0 && playerOptions.chooseAutomatically) { + if(timeUntilNextAutomaticChoice <= 0) { + MakeRandomChoice(); + timeUntilNextAutomaticChoice = playerOptions.chooseAutomaticallyTimeInterval; + } + } + if(story.canContinue && playerOptions.continueAutomatically) { + timeUntilNextAutomaticContinue -= deltaTime; + if(timeUntilNextAutomaticContinue <= 0) { + if(playerOptions.continueAutomaticallyTimeInterval == 0) { + story.ContinueMaximally(); + } else { + ContinueStory(); + } + timeUntilNextAutomaticContinue = playerOptions.continueAutomaticallyTimeInterval; + } + } + } + } + + + + + + + static void OnDidContinue () { + AddStoryContent(story.currentText.Trim(), story.currentTags); + if(story.currentChoices != null) { + foreach(var choice in story.currentChoices) { + AddToHistory(InkHistoryContentItem.CreateForPresentChoice(choice)); + } + } + AddWarningsAndErrorsToHistory(); + } + static void OnMakeChoice (Choice choice) { + AddToHistory(InkHistoryContentItem.CreateForMakeChoice(choice)); + AddWarningsAndErrorsToHistory(); + } + static void OnEvaluateFunction (string functionName, object[] arguments) { + StringBuilder sb = new StringBuilder(functionName); + if(arguments != null && arguments.Length > 0) { + sb.Append(" with args: "); + for (int i = 0; i < arguments.Length; i++) { + if(arguments[i] == null) sb.Append("NULL"); + else { + sb.Append(arguments[i]); + sb.Append(" ("); + sb.Append(arguments[i].GetType().Name); + sb.Append(")"); + } + if(i < arguments.Length-1) sb.Append(", "); + } + } + AddToHistory(InkHistoryContentItem.CreateForEvaluateFunction(sb.ToString().Trim())); + AddWarningsAndErrorsToHistory(); + } + static void OnCompleteEvaluateFunction (string functionName, object[] arguments, string textOutput, object result) { + StringBuilder sb = new StringBuilder(functionName); + if(arguments != null && arguments.Length > 0) { + sb.Append(" with args: "); + for (int i = 0; i < arguments.Length; i++) { + if(arguments[i] == null) sb.Append("NULL"); + else { + sb.Append(arguments[i]); + sb.Append(" ("); + sb.Append(arguments[i].GetType().Name); + sb.Append(")"); + } + if(i < arguments.Length-1) sb.Append(", "); + } + bool hasTextOutput = textOutput != null && textOutput != string.Empty; + if(hasTextOutput) sb.Append(" text output is: "+textOutput); + if(result != null) sb.Append(" result is: "+result); + if(!hasTextOutput && result == null) sb.Append("has no output"); + } + AddToHistory(InkHistoryContentItem.CreateForCompleteEvaluateFunction(sb.ToString().Trim())); + AddWarningsAndErrorsToHistory(); + } + static void OnChoosePathString (string pathString, object[] arguments) { + StringBuilder sb = new StringBuilder("ChoosePathString: "); + sb.Append(pathString); + if(arguments != null) { + sb.Append(" with args: "); + for (int i = 0; i < arguments.Length; i++) { + if(arguments[i] == null) sb.Append("NULL"); + else { + sb.Append(arguments[i]); + sb.Append(" ("); + sb.Append(arguments[i].GetType().Name); + sb.Append(")"); + } + if(i < arguments.Length-1) sb.Append(", "); + } + } + AddToHistory(InkHistoryContentItem.CreateForChoosePathString(sb.ToString().Trim())); + AddWarningsAndErrorsToHistory(); + } + static void OnLoadState () { + OnDidContinue(); + } + + static void AddWarningsAndErrorsToHistory () { + if(story.hasWarning) { + foreach(var warning in story.currentWarnings) { + AddToHistory(InkHistoryContentItem.CreateForWarning(warning.Trim())); + if(InkPlayerWindowState.Instance.storyPanelState.displayOptions.displayWarningsInConsole) { + Debug.LogWarning("Ink Warning: "+warning.Trim()); + } + } + } + if(story.hasError) { + foreach(var error in story.currentErrors) { + AddToHistory(InkHistoryContentItem.CreateForError(error.Trim())); + if(InkPlayerWindowState.Instance.storyPanelState.displayOptions.displayErrorsInConsole) { + Debug.LogError("Ink Error: "+error.Trim()); + } + } + } + } + + + + + + static void DetachInstance () { + attached = false; + story = null; + } + + + static void Play (TextAsset storyJSONTextAsset) { + Play(storyJSONTextAsset, InkPlayerParams.Standard); + } + static void Play (TextAsset storyJSONTextAsset, InkPlayerParams inkPlayerParams) { + if(TryPrepareInternal(storyJSONTextAsset)) { + InkPlayerWindow.playerParams = inkPlayerParams; + PlayInternal(); + } + } + static void Play (string storyJSON) { + Play(storyJSON, InkPlayerParams.Standard); + } + static void Play (string storyJSON, InkPlayerParams inkPlayerParams) { + if(TryPrepareInternal(storyJSON)) { + InkPlayerWindow.playerParams = inkPlayerParams; + PlayInternal(); + } + } + + + static void PlayInternal () { + story = new Story(storyJSON); + } + + // Loads the story, ready to be played + static bool TryPrepareInternal (TextAsset newStoryJSONTextAsset) { + // This forces a refresh + storyJSONTextAsset = null; + storyJSONTextAsset = newStoryJSONTextAsset; + if(storyJSONTextAsset == null || !InkEditorUtils.CheckStoryIsValid(storyJSONTextAsset.text, out playStoryException)) + return false; + storyJSON = storyJSONTextAsset.text; + return true; + } + static bool TryPrepareInternal (string newStoryJSON) { + if(!InkEditorUtils.CheckStoryIsValid(storyJSON, out playStoryException)) + return false; + InkPlayerWindow.storyJSONTextAsset = null; + InkPlayerWindow.storyJSON = newStoryJSON; + return true; + } + + static void OnUnsetStory () { + // Unsubscribe from all story events we subscribed to + _story.onDidContinue -= OnDidContinue; + _story.onMakeChoice -= OnMakeChoice; + _story.onEvaluateFunction -= OnEvaluateFunction; + _story.onCompleteEvaluateFunction -= OnCompleteEvaluateFunction; + _story.onChoosePathString -= OnChoosePathString; + _story.state.onDidLoadState -= OnLoadState; + + // Clear any exceptions related to the story we were storing + playStoryException = null; + + // Clear the history + ClearStoryHistory(); + + // Unobserve all observed variables. + foreach(var observedVariableName in InkPlayerWindowState.Instance.observedVariablesPanelState.restorableObservedVariableNames) + UnobserveVariable(observedVariableName, false); + InkPlayerWindowState.Instance.observedVariablesPanelState.observedVariables.Clear(); + + InkPlayerWindowState.Instance.lastStoryWasPlaying = false; + + InkPlayerWindowState.Save(); + } + + + static void OnSetStory () { + // Allow function fallbacks so we can subscribe to them and avoid throwing errors. + _story.allowExternalFunctionFallbacks = true; + + // Subscribe to all story events we'll use + _story.onDidContinue += OnDidContinue; + _story.onMakeChoice += OnMakeChoice; + _story.onEvaluateFunction += OnEvaluateFunction; + _story.onCompleteEvaluateFunction += OnCompleteEvaluateFunction; + _story.onChoosePathString += OnChoosePathString; + _story.state.onDidLoadState += OnLoadState; + + if(OnDidSetStory != null) OnDidSetStory(story); + + // Recalculate function ink variables + foreach(var input in InkPlayerWindowState.Instance.functionPanelState.functionParams.inputs) { + if(input.type == FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.InkVariable) { + input.RefreshInkVariableValue(story); + } else if(input.type == FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.InkListVariable) { + input.RefreshInkListVariableValue(story); + } + } + + // Reobserve variables + var variablesToObserve = new List(InkPlayerWindowState.Instance.observedVariablesPanelState.restorableObservedVariableNames); + InkPlayerWindowState.Instance.observedVariablesPanelState.observedVariables.Clear(); + InkPlayerWindowState.Instance.observedVariablesPanelState.restorableObservedVariableNames.Clear(); + foreach(var observedVariableName in variablesToObserve) { + if(_story.variablesState.Contains(observedVariableName)) { + var observedVariable = ObserveVariable(observedVariableName, true); + observedVariable.AddValueState(_story.variablesState[observedVariableName]); + } + } + + RefreshVisibleHistory(); + RefreshVisibleVariables(); + + if(!attached) + InkPlayerWindowState.Instance.lastStoryWasPlaying = true; + InkPlayerWindowState.Save(); + + if(playerParams.profileOnStart) isProfiling = true; + + PingAutomator(); + } + + + static void PingAutomator () { + if(playerParams.disablePlayControls) return; + if(story == null) return; + if(story.canContinue && playerOptions.continueAutomatically) { + TryContinue(); + } else if(story.currentChoices.Count > 0 && playerOptions.chooseAutomatically) { + MakeRandomChoice(); + } + } + + + static void Stop () { + Clear (); + } + + // This function's role isn't clear. It's used both when restarting a story and when clearing it entirely. We should probably have two separate functions. + static void Clear () { + // InkPlayerWindowState.Instance.observedVariablesPanelState.restorableObservedVariableNames.Clear(); + + // Clear the variable panel search + RefreshVisibleVariables(); + + story = null; + } + + static void Restart () { + Stop(); + if(storyJSONTextAsset != null) + Play(storyJSONTextAsset); + else if(storyJSON != null) + Play(storyJSON); + else + Debug.LogError("Can't restart because no text asset or cached JSON exists"); + } + + static bool CanRestart() { + return storyJSONTextAsset != null || storyJSON != null; + } + + static void ContinueStory () { + story.Continue(); + } + + static void AddStoryContent (string content, List tags) { + AddToHistory(InkHistoryContentItem.CreateForContent(content, tags)); + if(!playerParams.disableUndoHistory) AddToStateHistory(); + } + + static void AddToHistory (InkHistoryContentItem content) { + storyHistory.Add(content); + RefreshVisibleHistory(); + if(GetShouldAutoScrollOnStoryChange()) + ScrollToBottom(); + } + + static void AddToStateHistory () { + InkPlayerHistoryItem historyItem = new InkPlayerHistoryItem(story.state.ToJson(), new List(storyHistory)); + storyStateHistory.AddToUndoHistory(historyItem); + } + + static void ClearStoryHistory () { + storyHistory.Clear(); + storyStateHistory.Clear(); + RefreshVisibleHistory(); + ScrollToBottom(); + } + + static void CopyStoryHistoryToClipboard () { + StringBuilder sb = new StringBuilder("Story Log\n"); + foreach(InkHistoryContentItem content in storyHistory) { + sb.AppendLine(); + sb.Append(content.time.ToShortDateString()); + sb.Append(" "); + sb.Append(content.time.ToLongTimeString()); + sb.Append(" ("); + sb.Append(content.contentType.ToString()); + sb.Append(") "); + sb.Append(content.content); + } + GUIUtility.systemCopyBuffer = sb.ToString(); + } + static void Undo () { + InkPlayerHistoryItem item = storyStateHistory.Undo(); + story.state.LoadJson(item.inkStateJSON); + storyHistory = new List(item.storyHistory); + RefreshVisibleHistory(); + if(GetShouldAutoScrollOnStoryChange()) + ScrollToBottom(); + } + + static void Redo () { + InkPlayerHistoryItem item = storyStateHistory.Redo(); + story.state.LoadJson(item.inkStateJSON); + storyHistory = new List(item.storyHistory); + RefreshVisibleHistory(); + if(GetShouldAutoScrollOnStoryChange()) + ScrollToBottom(); + } + + static void SaveStoryState (string storyStateJSON) { + AddToHistory(InkHistoryContentItem.CreateForDebugNote("Saved state")); + + // Text asset can be null if we attached to an existing story rather than loading our own + string dirPath = string.Empty; + string storyName = "story"; + if( storyJSONTextAsset != null ) { + dirPath = System.IO.Path.GetDirectoryName(AssetDatabase.GetAssetPath(storyJSONTextAsset)); + storyName = storyJSONTextAsset.name; + } + + var newStateAsset = InkEditorUtils.CreateStoryStateTextFile(storyStateJSON, dirPath, storyName+"_SaveState"); + if(!playerParams.disableStateLoading) + storyStateTextAsset = newStateAsset; + } + + static void LoadStoryState (string storyStateJSON) { + storyHistory.Clear(); + storyStateHistory.Clear(); + AddToHistory(InkHistoryContentItem.CreateForDebugNote("Loaded state")); + story.state.LoadJson(storyStateJSON); + } + + static bool GetShouldAutoScrollOnStoryChange () { + if(InkPlayerWindowState.Instance.storyPanelState.autoScrollMode == StoryPanelState.AutoScrollMode.Off) return false; + if(InkPlayerWindowState.Instance.storyPanelState.autoScrollMode == StoryPanelState.AutoScrollMode.Always) return true; + if(InkPlayerWindowState.Instance.storyPanelState.autoScrollMode == StoryPanelState.AutoScrollMode.WhenAtBottom && storyScrollSnappedToBottom) return true; + return false; + } + + static void ScrollToBottom (bool instant = false) { + storyScrollMarkedForBottom = instant ? AutoScrollSmoothingMode.Snap : AutoScrollSmoothingMode.Smooth; + } + + static void ScrollToSelectedLine (bool instant = false) { + storyScrollMarkedForSelectedLine = instant ? AutoScrollSmoothingMode.Snap : AutoScrollSmoothingMode.Smooth; + } + + static void TryContinue () { + if(!story.canContinue) + return; + // if(playerOptions.continueAutomatically) { + // while (story.canContinue) { + // ContinueStory(); + // } + // } else { + ContinueStory(); + // } + } + void OnGUI () { + HandleDragAndDrop(); + if(searchTextFieldStyle == null) searchTextFieldStyle = GUI.skin.FindStyle("ToolbarSearchTextField") ?? GUI.skin.FindStyle("ToolbarSeachTextField"); + if(searchCancelButtonStyle == null) searchCancelButtonStyle = GUI.skin.FindStyle("ToolbarSearchCancelButton") ?? GUI.skin.FindStyle("ToolbarSeachCancelButton"); + + dateTimeNow = DateTime.Now; + var time = Time.realtimeSinceStartup; + var deltaTime = 0f; + if(lastOnGUITime != -1) + deltaTime = time - lastOnGUITime; + lastOnGUITime = time; + + if(doingAutoscroll) { + var newY = Mathf.SmoothDamp(InkPlayerWindowState.Instance.storyPanelState.scrollPosition.y, autoscrollTarget, ref autoscrollVelocity, autoscrollSmoothTime, Mathf.Infinity, deltaTime); + InkPlayerWindowState.Instance.storyPanelState.scrollPosition = new Vector2(InkPlayerWindowState.Instance.storyPanelState.scrollPosition.x, newY); + if(Mathf.Abs(InkPlayerWindowState.Instance.storyPanelState.scrollPosition.y - autoscrollTarget) < 0.1f) { + doingAutoscroll = false; + } + } + + this.Repaint(); + + var lw = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 200; + + scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); + + if(story == null && attached) + DetachInstance(); + + DisplayHeader(); + + if(playStoryException == null) { + DisplayStoryControlGroup(); + } else { + DisplayErrors(); + } + + if(story != null && story.state != null) { + DrawStoryHistory(); + DrawChoices(); + DrawStoryState(); + DrawProfilerData(); + DrawSaveLoad(); + DrawNamedContent(); + // DrawDiverts(); + DrawFunctions(); + DrawVariables(); + InkPlayerWindowState.Save(); + } else { + // EditorGUILayout.BeginVertical(GUILayout.Width(position.width * 0.6f)); + GUILayout.Space(40); + EditorGUILayout.LabelField("Use this window to play and debug ink stories", EditorStyles.boldLabel); + GUILayout.Space(10); + EditorGUILayout.LabelField("You can tether your story as it runs in Play Mode to this window, allowing you to view and edit variables and divert in real time!", EditorStyles.wordWrappedLabel); + GUILayout.Space(20); + if(GUILayout.Button("View Documentation")) { + Application.OpenURL("https://github.com/inkle/ink-unity-integration/blob/master/Documentation/InkPlayerWindow.md"); + } + // EditorGUILayout.EndVertical(); + } + + var lastRectMaxY = GUILayoutUtility.GetLastRect().yMax; + EditorGUILayout.EndScrollView(); + if (Event.current.type == EventType.Repaint) { + var scrollRectMaxY = GUILayoutUtility.GetLastRect().yMax; + mainScrollViewActive = lastRectMaxY >= (scrollRectMaxY-3); + } + + EditorGUIUtility.labelWidth = lw; + } + + void DisplayHeader () { + if(attached) { + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); + var headerTitle = new System.Text.StringBuilder("Attached"); + if(attachedWhileInPlayMode != EditorApplication.isPlaying) { + playerParams = InkPlayerParams.Standard; + if(attachedWhileInPlayMode) headerTitle.Append(" (Ex-play-mode story)"); + } + GUILayout.Label(new GUIContent(headerTitle.ToString(), attachedStoryIcon, "This story reference has been attached from elsewhere")); + if (GUILayout.Button(new GUIContent("Detach", "Detach from the loaded external story"), EditorStyles.toolbarButton)) { + Detach(); + } + EditorGUILayout.EndHorizontal(); + } else { + EditorGUILayout.BeginVertical(); + EditorGUI.BeginChangeCheck(); + storyJSONTextAsset = EditorGUILayout.ObjectField("Story JSON", storyJSONTextAsset, typeof(TextAsset), false) as TextAsset; + if(EditorGUI.EndChangeCheck()) { + if(storyJSONTextAsset == null) { + story = null; + } else { + Stop(); + Play(storyJSONTextAsset); + } + } + if(CanRestart()) { + string fullJSONFilePath = InkEditorUtils.UnityRelativeToAbsolutePath(AssetDatabase.GetAssetPath(storyJSONTextAsset)); + var updatedStoryJSONLastEditDateTime = File.GetLastWriteTime(fullJSONFilePath); + if (currentStoryJSONLastEditDateTime != updatedStoryJSONLastEditDateTime ) { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.HelpBox ("Story JSON file has changed. Reload or restart to play updated story.", MessageType.Warning); + EditorGUILayout.BeginVertical(); + if(GUILayout.Button(new GUIContent("Reload", restartIcon, "Reload and restart the current story, which has been updated."))) { + var storyStateJSON = story.state.ToJson(); + Play(storyJSONTextAsset, InkPlayerWindow.playerParams); + story.state.LoadJson(storyStateJSON); + } + if(GUILayout.Button(new GUIContent("Restart", restartIcon, "Restart the current story"))) { + Restart(); + } + EditorGUILayout.EndVertical(); + EditorGUILayout.EndHorizontal(); + } + } + EditorGUILayout.EndVertical(); + } + } + + void DisplayErrors () { + EditorGUILayout.HelpBox(playStoryException.Message, MessageType.Error); + } + + void DisplayStoryControlGroup () { + EditorGUILayout.BeginHorizontal (EditorStyles.toolbar); + + if(story == null) { + EditorGUI.BeginDisabledGroup(storyJSONTextAsset == null); + if(GUILayout.Button(new GUIContent("Start", playIcon, "Run the story"), EditorStyles.toolbarButton)) { + var playerParams = InkPlayerParams.Standard; + playerParams.profileOnStart = InkPlayerWindow.playerParams.profileOnStart; + Play(storyJSONTextAsset, playerParams); + } + EditorGUI.EndDisabledGroup(); + } else { + EditorGUI.BeginDisabledGroup(playerParams.disablePlayControls); + if(GUILayout.Button(new GUIContent("Stop", stopIcon, "Stop the story"), EditorStyles.toolbarButton)) { + Stop(); + } + EditorGUI.BeginDisabledGroup(!CanRestart()); + if(GUILayout.Button(new GUIContent("Restart", restartIcon, "Restarts the story"), EditorStyles.toolbarButton)) { + Restart(); + } + EditorGUI.EndDisabledGroup(); + EditorGUI.EndDisabledGroup(); + } + + GUILayout.FlexibleSpace(); + + // Profiler button + if( story != null ) { + var profileButtonTitle = new GUIContent( + isProfiling ? "Stop Profiling" : "Profile", + profilerIcon, + (isProfiling ? "Stop" : "Start") + " Profiling"); + isProfiling = GUILayout.Toggle(isProfiling, profileButtonTitle, EditorStyles.toolbarButton); + + } else { + var profileButtonTitle = new GUIContent("Profile On Start", profilerIcon, "Immediately start the profiler when the story starts."); + playerParams.profileOnStart = GUILayout.Toggle(playerParams.profileOnStart, profileButtonTitle, EditorStyles.toolbarButton); + } + GUILayout.FlexibleSpace(); + + // Undo/Redo + if(story != null) { + EditorGUI.BeginDisabledGroup(playerParams.disableUndoHistory || !storyStateHistory.canUndo); + if(GUILayout.Button(new GUIContent("Undo", undoIcon, "Undo the last continue or choice"), EditorStyles.toolbarButton, GUILayout.Width(46))) { + Undo(); + } + EditorGUI.EndDisabledGroup(); + EditorGUI.BeginDisabledGroup(playerParams.disableUndoHistory || !storyStateHistory.canRedo); + if(GUILayout.Button(new GUIContent("Redo", redoIcon, "Redo the last continue or choice"), EditorStyles.toolbarButton, GUILayout.Width(46))) { + Redo(); + } + EditorGUI.EndDisabledGroup(); + } + + GUILayout.FlexibleSpace(); + + EditorGUI.BeginDisabledGroup(playerParams.disablePlayControls); + EditorGUI.BeginChangeCheck(); + var newContinueAutomatically = GUILayout.Toggle(playerOptions.continueAutomatically && !playerParams.disablePlayControls, new GUIContent("Auto-Continue", "Continues content automatically"), EditorStyles.toolbarButton); + if(EditorGUI.EndChangeCheck()) { + if(!playerParams.disablePlayControls) playerOptions.continueAutomatically = newContinueAutomatically; + PingAutomator(); + } + + EditorGUI.BeginChangeCheck(); + var newChooseAutomatically = GUILayout.Toggle(playerOptions.chooseAutomatically && !playerParams.disablePlayControls, new GUIContent("Auto-Choice", "Makes choices automatically"), EditorStyles.toolbarButton); + if(EditorGUI.EndChangeCheck()) { + if(!playerParams.disablePlayControls) playerOptions.chooseAutomatically = newChooseAutomatically; + } + EditorGUI.EndDisabledGroup(); + EditorGUILayout.LabelField(new GUIContent(timeIntervalIcon, "Time between automatic choices"), GUILayout.Width(16)); + playerOptions.continueAutomaticallyTimeInterval = playerOptions.chooseAutomaticallyTimeInterval = GUILayout.HorizontalSlider(playerOptions.continueAutomaticallyTimeInterval, 1f, 0f, GUILayout.Width(80)); + GUILayout.EndHorizontal(); + } + + + + + + #region Story + void DrawStoryHistory () { + DisplayStoryHeader(); + if(InkPlayerWindowState.Instance.storyPanelState.showing) + DisplayStoryBody (); + } + + void DisplayStoryHeader () { + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); + + InkPlayerWindowState.Instance.storyPanelState.showing = EditorGUILayout.Foldout(InkPlayerWindowState.Instance.storyPanelState.showing, "Content", true); + + if(GUILayout.Button(new GUIContent("Clear", clearIcon, "Clears the output"), EditorStyles.toolbarButton, GUILayout.ExpandWidth(false))) { + ClearStoryHistory(); + } + GUILayout.Space(12); + if(GUILayout.Button(new GUIContent("Copy", /*copyToClipboardIcon, */"Copy the output to clipboard"), EditorStyles.toolbarButton, GUILayout.ExpandWidth(false))) { + CopyStoryHistoryToClipboard(); + } + + GUILayout.Space(12); + { + var lw = EditorGUIUtility.labelWidth; + var autoScrollGUIContent = EditorGUIUtility.IconContent("ScrollRect Icon"); + autoScrollGUIContent.tooltip = "Autoscroll Mode"; + EditorGUIUtility.labelWidth = 20; + InkPlayerWindowState.Instance.storyPanelState.autoScrollMode = (StoryPanelState.AutoScrollMode)EditorGUILayout.EnumPopup(autoScrollGUIContent, InkPlayerWindowState.Instance.storyPanelState.autoScrollMode, EditorStyles.toolbarPopup, GUILayout.Width(130)); + EditorGUIUtility.labelWidth = lw; + } + + + GUILayout.Space(12); + EditorGUI.BeginChangeCheck(); + DrawVisibilityOptions(); + if(EditorGUI.EndChangeCheck()) { + RefreshVisibleHistory(); + if(GetShouldAutoScrollOnStoryChange()) + ScrollToBottom(); + } + void DrawVisibilityOptions () { + var lw = EditorGUIUtility.labelWidth; + var visibilityOptionsGUIContent = EditorGUIUtility.IconContent("d_ViewToolOrbit"); + visibilityOptionsGUIContent.tooltip = "Visiblity Options"; + EditorGUIUtility.labelWidth = 20; + Enum newVisibilityOptions = EditorGUILayout.EnumFlagsField(visibilityOptionsGUIContent, InkPlayerWindowState.Instance.storyPanelState.displayOptions.visibilityOptions, EditorStyles.toolbarDropDown, GUILayout.Width(80)); + EditorGUIUtility.labelWidth = lw; + InkPlayerWindowState.Instance.storyPanelState.displayOptions.visibilityOptions = (DisplayOptions.VisibilityOptions)(int)Convert.ChangeType(newVisibilityOptions, typeof(DisplayOptions.VisibilityOptions)); + + // TODO: tooltips for options. I'd REALLY like for it not to show "Mixed ..." in the box mais c'est la vie + // TODO: Add a "default" option in the dropdown + // See: + // https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/EditorGUI.cs#L3561 + // But a lot of the code is internal. + + // var enumValue = InkPlayerWindowState.Instance.storyPanelState.displayOptions.visibilityOptions; + // var style = EditorStyles.toolbarDropDown; + // var position = EditorGUILayout.GetControlRect(true, 18, style, GUILayout.Width(80)); + + // var enumType = typeof(DisplayOptions.VisibilityOptions); + // var includeObsolete = false; + // var label = GUIContent.none; + // var displayNames = Enum.GetNames(typeof(DisplayOptions.VisibilityOptions)); + // // var flagValues = new int[]; + + // var id = GUIUtility.GetControlID(0, FocusType.Keyboard, position); + // position = EditorGUI.PrefixLabel(position, id, label); + + // InkPlayerWindowState.Instance.storyPanelState.displayOptions.visibilityOptions = (DisplayOptions.VisibilityOptions)EditorGUI.MaskField(position, (int)enumValue, displayNames, style); + } + + bool changed = DrawSearchBar(ref InkPlayerWindowState.Instance.storyPanelState.searchString); + if(changed) { + RefreshVisibleHistory(); + if(selectedLine != null) ScrollToSelectedLine(true); + else ScrollToBottom(); + } + + EditorGUILayout.EndHorizontal(); + } + + static bool ShouldShowContentWithSearchString (string contentString, string searchString) { + if(StringContains(contentString, searchString, StringComparison.OrdinalIgnoreCase)) return true; + return false; + } + + static bool ShouldShowContent (InkHistoryContentItem content, DisplayOptions.VisibilityOptions visibilityOpts) { + switch(content.contentType) { + case InkHistoryContentItem.ContentType.PresentedContent: { + if((visibilityOpts & DisplayOptions.VisibilityOptions.Content) != 0) { + if(content.content.Length == 0 && (visibilityOpts & DisplayOptions.VisibilityOptions.EmptyEntries) == 0) return false; + else return true; + } else return false; + } + case InkHistoryContentItem.ContentType.ChooseChoice: + return (visibilityOpts & DisplayOptions.VisibilityOptions.SelectedChoice) != 0; + case InkHistoryContentItem.ContentType.PresentedChoice: + return (visibilityOpts & DisplayOptions.VisibilityOptions.PresentedChoices) != 0; + case InkHistoryContentItem.ContentType.DebugNote: + return (visibilityOpts & DisplayOptions.VisibilityOptions.DebugNotes) != 0; + case InkHistoryContentItem.ContentType.Warning: + return (visibilityOpts & DisplayOptions.VisibilityOptions.Warnings) != 0; + case InkHistoryContentItem.ContentType.Error: + return (visibilityOpts & DisplayOptions.VisibilityOptions.Errors) != 0; + case InkHistoryContentItem.ContentType.ChoosePathString: + return (visibilityOpts & DisplayOptions.VisibilityOptions.ChoosePathString) != 0; + case InkHistoryContentItem.ContentType.EvaluateFunction: + return (visibilityOpts & DisplayOptions.VisibilityOptions.Function) != 0; + default: break; + } + return false; + } + + static List visibleHistory = new List(); + static void RefreshVisibleHistory () { + visibleHistory.Clear(); + bool doingSearch = !string.IsNullOrWhiteSpace(InkPlayerWindowState.Instance.storyPanelState.searchString); + var visibilityOpts = InkPlayerWindowState.Instance.storyPanelState.displayOptions.visibilityOptions; + var count = storyHistory.Count; + for(int i = 0; i < count; i++) { + var content = storyHistory[i]; + if(doingSearch && !ShouldShowContentWithSearchString(content.content, InkPlayerWindowState.Instance.storyPanelState.searchString)) continue; + if(!ShouldShowContent(content, visibilityOpts)) continue; + visibleHistory.Add(content); + } + } + + void DisplayStoryBody () { + float contentMarginXY = 4; + float contentSpacing = 8; + + var timestampWidth = 58; + var contentTypeWidth = 26; + var tagsWidth = 160; + + var visibilityOptions = InkPlayerWindowState.Instance.storyPanelState.displayOptions.visibilityOptions; + bool showTimestamp = (visibilityOptions & DisplayOptions.VisibilityOptions.TimeStamp) != 0; + bool showTags = (visibilityOptions & DisplayOptions.VisibilityOptions.Tags) != 0; + + var lastRect = GUILayoutUtility.GetLastRect(); + var containerWidth = position.width - GUI.skin.verticalScrollbar.fixedWidth; + if(mainScrollViewActive) containerWidth -= GUI.skin.verticalScrollbar.fixedWidth; + + var lineWidth = containerWidth - contentMarginXY * 2; + + var contentWidth = lineWidth; + if(showTimestamp) { + contentWidth -= timestampWidth; + contentWidth -= contentSpacing; + } + contentWidth -= contentTypeWidth; + contentWidth -= contentSpacing; + if(showTags) { + contentWidth -= tagsWidth; + contentWidth -= contentSpacing; + } + float totalHeight = 0; + float[] heights = new float[storyHistory.Count]; + int selectedLineIndex = -1; + float selectedLineY = -1; + + for(int i = 0; i < visibleHistory.Count; i++) { + var content = visibleHistory[i]; + heights[i] = EditorStyles.wordWrappedLabel.CalcHeight(new GUIContent(content.content), contentWidth); + if(showTags) { + var tagsHeight = EditorStyles.wordWrappedLabel.CalcHeight(new GUIContent(GetTagsString(content.tags)), tagsWidth); + heights[i] = Mathf.Max(heights[i], tagsHeight); + } + heights[i] += contentMarginXY * 2; + if(content == selectedLine) { + selectedLineIndex = i; + selectedLineY = totalHeight; + } + totalHeight += heights[i]; + } + + void OnRefreshSelectedLine () { + float _totalHeight = 0; + for(int i = 0; i < visibleHistory.Count; i++) { + var content = visibleHistory[i]; + if(content == selectedLine) { + selectedLineIndex = i; + selectedLineY = _totalHeight; + } + _totalHeight += heights[i]; + } + } + + if(Event.current.type == EventType.Repaint) { + InkPlayerWindowState.Instance.storyPanelState.y = lastRect.yMax; + } + + var viewportRect = new Rect(0, lastRect.yMax, position.width, InkPlayerWindowState.Instance.storyPanelState.height); + if(mainScrollViewActive) viewportRect.width -= GUI.skin.verticalScrollbar.fixedWidth; + var containerRect = new Rect(0,0,containerWidth, totalHeight); + + + var showScrollToBottomButton = (totalHeight - viewportRect.height) - (doingAutoscroll ? autoscrollTarget : InkPlayerWindowState.Instance.storyPanelState.scrollPosition.y) > 100; + var scrollToBottomButtonRect = new Rect(viewportRect.center.x - 80, viewportRect.yMax-40, 160, 32); + + if(showScrollToBottomButton) { + EditorGUIUtility.AddCursorRect(scrollToBottomButtonRect, MouseCursor.Link); + if(Event.current.type == EventType.MouseDown && Event.current.button == 0 && scrollToBottomButtonRect.Contains(Event.current.mousePosition)) { + GUI.FocusControl(null); + ScrollToBottom(); + Event.current.Use(); + } + } + + storyScrollRectBottom = totalHeight - viewportRect.height; + + + var newScrollPos = GUI.BeginScrollView(viewportRect, InkPlayerWindowState.Instance.storyPanelState.scrollPosition, containerRect, false, true); + if(newScrollPos != InkPlayerWindowState.Instance.storyPanelState.scrollPosition) { + doingAutoscroll = false; + InkPlayerWindowState.Instance.storyPanelState.scrollPosition = newScrollPos; + storyScrollSnappedToBottom = storyScrollRectBottom - InkPlayerWindowState.Instance.storyPanelState.scrollPosition.y < 0.1f; + } + + var y = 0f; + var panelTop = InkPlayerWindowState.Instance.storyPanelState.scrollPosition.y; + var panelBottom = InkPlayerWindowState.Instance.storyPanelState.scrollPosition.y + viewportRect.height; + // int numShown = 0; + // var log = ""; + + // This appears to be necessary, else the selected text moves around when scrolling! + // if(doingAutoscroll) { + // GUI.FocusControl(null); + // } + + + + for(int i = 0; i < visibleHistory.Count; i++) { + var endY = y + heights[i]; + if(panelTop <= endY && panelBottom >= y) { + // if(numShown == 0) { + // log += "Total space "+totalHeight+" Scroll "+InkPlayerWindowState.Instance.storyPanelState.storyScrollPosition.y+" Space "+y+", showing: "; + // } + var content = visibleHistory[i]; + var lineContainerRect = new Rect(0, y, containerWidth, heights[i]); + var lineRect = new Rect(lineContainerRect.x + contentMarginXY, lineContainerRect.y + contentMarginXY, lineContainerRect.width - contentMarginXY * 2, lineContainerRect.height - contentMarginXY * 2); + + GUIStyle lineStyle = null; + if(selectedLine == content) lineStyle = historyItemBGStyleSelected.guiStyle; + else lineStyle = i % 2 == 0 ? historyItemBGStyleDark.guiStyle : historyItemBGStyleLight.guiStyle; + + GUI.Box(lineContainerRect, GUIContent.none, lineStyle); + EditorGUIUtility.AddCursorRect(lineContainerRect, MouseCursor.ArrowPlus); + if(Event.current.type == EventType.MouseDown && lineContainerRect.Contains(Event.current.mousePosition)) { + if(Event.current.button == 0) { + selectedLine = content; + OnRefreshSelectedLine(); + // To avoid disruption, only scroll when the line is close to the edge of the panel + var targetY = GetTargetScrollPositionToCenterStoryLine(i, false); + if(Mathf.Abs(targetY-InkPlayerWindowState.Instance.storyPanelState.scrollPosition.y) > viewportRect.height * 0.225f) { + ScrollToSelectedLine(); + } + Event.current.Use(); + } + } + string textToDisplay = String.Empty; + + var x = lineRect.x; + if(showTimestamp) { + var timeRect = new Rect(x, lineRect.y, timestampWidth, lineRect.height); + DisplayLineTime(timeRect, content); + x += timestampWidth; + x += contentSpacing; + } + var iconRect = new Rect(x, lineRect.y, contentTypeWidth, lineRect.height); + DisplayLineIcon(iconRect, content); + x += contentTypeWidth; + x += contentSpacing; + + var contentRect = new Rect(x, lineRect.y, contentWidth, lineRect.height); + DisplayLine(contentRect, content); + x += contentWidth; + x += contentSpacing; + if(showTags) { + var tagsRect = new Rect(x, lineRect.y, tagsWidth, lineRect.height); + DisplayTags(tagsRect, content); + x += tagsWidth; + x += contentSpacing; + } + + if(Event.current.type == EventType.MouseDown && lineContainerRect.Contains(Event.current.mousePosition)) { + if(Event.current.button == 1) { + if(GUI.GetNameOfFocusedControl() != content.GetHashCode().ToString()) { + GUI.FocusControl(null); + var contextMenu = new GenericMenu(); + contextMenu.AddItem(new GUIContent("Copy"), false, () => { + GUIUtility.systemCopyBuffer = content.content; + }); + foreach(var contextMenuDelegate in contextMenuDelegates) { + contextMenuDelegate(contextMenu, content); + } + contextMenu.ShowAsContext(); + Event.current.Use(); + } + } + } + + // log += i+", "; + } + y = endY; + } + + var lineX = contentMarginXY; + if(showTimestamp) { + lineX += timestampWidth; + lineX += contentSpacing * 0.5f; + GUI.Box(new Rect(lineX, 0, 1, containerRect.height), "", dividerLineStyle.guiStyle); + lineX += contentSpacing * 0.5f; + } + + lineX += contentTypeWidth; + lineX += contentSpacing * 0.5f; + GUI.Box(new Rect(lineX, 0, 1, containerRect.height), "", dividerLineStyle.guiStyle); + lineX += contentSpacing * 0.5f; + + if(showTags) { + lineX += contentWidth; + lineX += contentSpacing * 0.5f; + GUI.Box(new Rect(lineX, 0, 1, containerRect.height), "", dividerLineStyle.guiStyle); + lineX += contentSpacing * 0.5f; + } + + GUI.EndScrollView(); + + if(showScrollToBottomButton) { + GUI.Box(scrollToBottomButtonRect, "Scroll to bottom", GUI.skin.button); + } + + GUILayout.Space(viewportRect.height); + + + + if(Event.current.type == EventType.Layout) { + if(storyScrollMarkedForBottom != AutoScrollSmoothingMode.NONE) { + var targetPosition = totalHeight - viewportRect.height; + if(storyScrollMarkedForBottom == AutoScrollSmoothingMode.Smooth) { + doingAutoscroll = true; + autoscrollTarget = targetPosition; + } else if(storyScrollMarkedForBottom == AutoScrollSmoothingMode.Snap) { + doingAutoscroll = false; + InkPlayerWindowState.Instance.storyPanelState.scrollPosition = new Vector2(InkPlayerWindowState.Instance.storyPanelState.scrollPosition.x, targetPosition); + } + autoscrollVelocity = 0; + storyScrollSnappedToBottom = true; + storyScrollMarkedForBottom = AutoScrollSmoothingMode.NONE; + } + if(storyScrollMarkedForSelectedLine != AutoScrollSmoothingMode.NONE && selectedLineIndex != -1) { + var targetPosition = GetTargetScrollPositionToCenterStoryLine(selectedLineIndex); + if(storyScrollMarkedForSelectedLine == AutoScrollSmoothingMode.Smooth) { + doingAutoscroll = true; + autoscrollTarget = targetPosition; + } else if(storyScrollMarkedForSelectedLine == AutoScrollSmoothingMode.Snap) { + doingAutoscroll = false; + InkPlayerWindowState.Instance.storyPanelState.scrollPosition = new Vector2(InkPlayerWindowState.Instance.storyPanelState.scrollPosition.x, targetPosition); + } + autoscrollVelocity = 0; + storyScrollSnappedToBottom = (storyScrollRectBottom+viewportRect.height * 0.5f) - targetPosition < 0.1f; + storyScrollMarkedForSelectedLine = AutoScrollSmoothingMode.NONE; + } + } + + float GetTargetScrollPositionToCenterStoryLine (int lineIndex, bool clamped = true) { + var targetY = (selectedLineY + heights[lineIndex] * 0.5f) - viewportRect.height * 0.5f; + if(clamped) targetY = Mathf.Clamp(targetY, 0, totalHeight - viewportRect.height); + return targetY; + } + } + + static ColoredBackgroundGUIStyle _historyItemBGStyleDark; + static ColoredBackgroundGUIStyle historyItemBGStyleDark { + get { + if(_historyItemBGStyleDark == null) _historyItemBGStyleDark = new ColoredBackgroundGUIStyle(new Color(0.8470589f,0.8470589f,0.8470589f,1), new Color(0.21f,0.21f,0.21f,1f), new Color(0.92f,0.92f,0.92f,1), new Color(0.3f,0.3f,0.3f,1f)); + return _historyItemBGStyleDark; + } + } + + static ColoredBackgroundGUIStyle _historyItemBGStyleLight; + static ColoredBackgroundGUIStyle historyItemBGStyleLight { + get { + if(_historyItemBGStyleLight == null) _historyItemBGStyleLight = new ColoredBackgroundGUIStyle(new Color(0.8745099f,0.8745099f,0.8745099f,1f), new Color(0.23f,0.23f,0.23f,1f), new Color(0.92f,0.92f,0.92f,1), new Color(0.3f,0.3f,0.3f,1f)); + return _historyItemBGStyleLight; + } + } + + static ColoredBackgroundGUIStyle _historyItemBGStyleSelected; + static ColoredBackgroundGUIStyle historyItemBGStyleSelected { + get { + if(_historyItemBGStyleSelected == null) _historyItemBGStyleSelected = new ColoredBackgroundGUIStyle(new Color(0.3920879f,0.6161963f,0.9339623f,1f), new Color(0.243137255f,0.37254902f,0.588235294f,1f)); + return _historyItemBGStyleSelected; + } + } + + static ColoredBackgroundGUIStyle _dividerLineStyle; + static ColoredBackgroundGUIStyle dividerLineStyle { + get { + if(_dividerLineStyle == null) _dividerLineStyle = new ColoredBackgroundGUIStyle(new Color(0.85f,0.85f,0.85f,1f), new Color(0.25f,0.25f,0.25f,1f)); + return _dividerLineStyle; + } + } + + void DisplayLineTime (Rect rect, InkHistoryContentItem content) { + EditorGUI.LabelField(rect, new GUIContent(content.time.ToLongTimeString())); + } + + void DisplayLineIcon (Rect rect, InkHistoryContentItem content) { + var visibilityOptions = InkPlayerWindowState.Instance.storyPanelState.displayOptions.visibilityOptions; + if(content.contentType == InkHistoryContentItem.ContentType.ChooseChoice && (visibilityOptions & DisplayOptions.VisibilityOptions.SelectedChoice) != 0) { + var icon = new GUIContent("*", "Selected Choice"); + EditorGUI.LabelField(rect, icon); + } else if(content.contentType == InkHistoryContentItem.ContentType.PresentedChoice && (visibilityOptions & DisplayOptions.VisibilityOptions.PresentedChoices) != 0) { + var icon = new GUIContent("*?", "Presented Choice"); + EditorGUI.LabelField(rect, icon); + } else if(content.contentType == InkHistoryContentItem.ContentType.EvaluateFunction && (visibilityOptions & DisplayOptions.VisibilityOptions.Function) != 0) { + var icon = new GUIContent("f(x)", "Took Function"); + EditorGUI.LabelField(rect, icon); + } else if(content.contentType == InkHistoryContentItem.ContentType.ChoosePathString && (visibilityOptions & DisplayOptions.VisibilityOptions.ChoosePathString) != 0) { + var icon = new GUIContent("->", "Took Path"); + EditorGUI.LabelField(rect, icon); + } else if(content.contentType == InkHistoryContentItem.ContentType.DebugNote && (visibilityOptions & DisplayOptions.VisibilityOptions.DebugNotes) != 0) { + var icon = new GUIContent("//", "Debug Note"); + EditorGUI.LabelField(rect, icon); + } else if(content.contentType == InkHistoryContentItem.ContentType.Warning && (visibilityOptions & DisplayOptions.VisibilityOptions.Warnings) != 0) { + var icon = EditorGUIUtility.IconContent("console.warnicon.sml"); + icon.tooltip = "Warning"; + EditorGUI.LabelField(rect, icon); + } else if(content.contentType == InkHistoryContentItem.ContentType.Error && (visibilityOptions & DisplayOptions.VisibilityOptions.Errors) != 0) { + var icon = EditorGUIUtility.IconContent("console.erroricon.sml"); + icon.tooltip = "Error"; + EditorGUI.LabelField(rect, icon); + } else { + // var icon = EditorGUIUtility.IconContent("console.infoicon.sml"); + // EditorGUI.LabelField(rect, icon); + } + } + + void DisplayLine (Rect rect, InkHistoryContentItem content) { + if (content.content.Length == 0) return; + float timeSinceLastWrite = (float)(dateTimeNow - content.time).TotalSeconds; + var revealTime = 0.8f; + var l = Mathf.InverseLerp(revealTime, 0, timeSinceLastWrite); + var newColor = new Color(GUI.color.r, GUI.color.g, GUI.color.b, 0); + var color = Color.Lerp(GUI.color, newColor, l); + var oldGUIColor = GUI.color; + GUI.color = color; + GUI.SetNextControlName(content.GetHashCode().ToString()); + EditorGUI.SelectableLabel(rect, content.content, EditorStyles.wordWrappedLabel); + GUI.color = oldGUIColor; + } + + void DisplayTags (Rect rect, InkHistoryContentItem content) { + if (content.tags == null || content.tags.Count == 0) return; + float timeSinceLastWrite = (float)(dateTimeNow - content.time).TotalSeconds; + var revealTime = 0.8f; + var l = Mathf.InverseLerp(revealTime, 0, timeSinceLastWrite); + var newColor = new Color(GUI.color.r, GUI.color.g, GUI.color.b, 0); + var color = Color.Lerp(GUI.color, newColor, l); + var oldGUIColor = GUI.color; + GUI.color = color; + GUI.SetNextControlName(content.GetHashCode().ToString()); + EditorGUI.SelectableLabel(rect, GetTagsString(content.tags), EditorStyles.wordWrappedLabel); + GUI.color = oldGUIColor; + } + + string GetTagsString (List tags) { + return (tags == null || tags.Count == 0) ? string.Empty : string.Join("\n", tags); + } + #endregion + + + + + + + #region Choices + void DrawChoices () { + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); + InkPlayerWindowState.Instance.choicePanelState.showing = EditorGUILayout.Foldout(InkPlayerWindowState.Instance.choicePanelState.showing, "Choices", true); + EditorGUILayout.EndHorizontal(); + if(InkPlayerWindowState.Instance.choicePanelState.showing) + DisplayChoices (); + } + + void DisplayChoices () { + EditorGUI.BeginDisabledGroup(playerParams.disableChoices); + GUILayout.BeginVertical(); + if(story.canContinue) { + EditorGUI.BeginDisabledGroup(playerOptions.continueAutomatically); + if(GUILayout.Button(new GUIContent("Continue", "Continues once"))) { + ContinueStory(); + } + if(GUILayout.Button(new GUIContent("Continue Maximally", "Continues until the next choice"))) { + while(story.canContinue) { + ContinueStory(); + } + } + EditorGUI.EndDisabledGroup(); + } else if(story.currentChoices.Count > 0) { + EditorGUI.BeginDisabledGroup(playerOptions.chooseAutomatically); + foreach(Choice choice in story.currentChoices) { + GUILayout.BeginHorizontal(); + StringBuilder sb = new StringBuilder(); + sb.Append("Index: "); + sb.AppendLine(choice.index.ToString()); + sb.Append("Tags: "); + if (choice.tags == null) { + sb.Append("NONE"); + } else { + for (var index = 0; index < choice.tags.Count; index++) { + var tag = choice.tags[index]; + sb.Append(tag); + if (index < choice.tags.Count - 1) sb.Append(", "); + else sb.AppendLine(); + } + } + sb.Append("SourcePath: "); + sb.Append(choice.sourcePath.Trim()); + if(GUILayout.Button(new GUIContent(choice.text.Trim(), sb.ToString()))) { + MakeChoice(choice); + } + GUILayout.EndHorizontal(); + } + EditorGUI.EndDisabledGroup(); + } else { + GUILayout.Label("Reached end of story"); + } + + GUILayout.EndVertical(); + EditorGUI.EndDisabledGroup(); + } + + static void MakeRandomChoice () { + MakeChoice(story.currentChoices[UnityEngine.Random.Range(0, story.currentChoices.Count)]); + } + + static void MakeChoice (Choice choice) { + if(OnChooseChoiceIndexOverride != null) OnChooseChoiceIndexOverride(choice.index); + else story.ChooseChoiceIndex(choice.index); + if(!playerParams.disableUndoHistory) AddToStateHistory(); + TryContinue(); + } + #endregion + + + + + + #region StoryState + static void DrawStoryState () { + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); + InkPlayerWindowState.Instance.storyStatePanelState.showing = EditorGUILayout.Foldout(InkPlayerWindowState.Instance.storyStatePanelState.showing, "Story State", true); + EditorGUILayout.EndHorizontal(); + if(InkPlayerWindowState.Instance.storyStatePanelState.showing) + DrawStoryStatePanel (); + } + + static void DrawStoryStatePanel () { + GUILayout.BeginVertical(); + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PrefixLabel("Story Seed"); + EditorGUILayout.LabelField(story.state.storySeed.ToString()); + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PrefixLabel("Current Turn Index"); + EditorGUILayout.LabelField(story.state.currentTurnIndex.ToString()); + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PrefixLabel("Current Path String"); + if(story.canContinue) EditorGUILayout.LabelField(story.state.currentPathString); + else EditorGUILayout.LabelField("(Always blank when story.canContinue is false)"); + EditorGUILayout.EndHorizontal(); + + GUILayout.EndVertical(); + } + #endregion + + + + #region SaveLoad + static void DrawSaveLoad () { + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); + InkPlayerWindowState.Instance.saveLoadPanelState.showing = EditorGUILayout.Foldout(InkPlayerWindowState.Instance.saveLoadPanelState.showing, "Save/Load", true); + EditorGUILayout.EndHorizontal(); + if(InkPlayerWindowState.Instance.saveLoadPanelState.showing) + DrawSaveLoadPanel (); + } + + static void DrawSaveLoadPanel () { + GUILayout.BeginVertical(); + + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Copy To Clipboard")) { + GUIUtility.systemCopyBuffer = InkEditorUtils.FormatJson(story.state.ToJson()); + } + if (GUILayout.Button("Save As...")) { + SaveStoryState(InkEditorUtils.FormatJson(story.state.ToJson())); + } + EditorGUILayout.EndHorizontal(); + + EditorGUI.BeginDisabledGroup(playerParams.disableStateLoading); + EditorGUILayout.BeginHorizontal(); + EditorGUI.BeginChangeCheck(); + storyStateTextAsset = EditorGUILayout.ObjectField("Load Story State JSON File", storyStateTextAsset, typeof(TextAsset), false) as TextAsset; + EditorGUI.BeginDisabledGroup(storyStateTextAsset == null); + if (GUILayout.Button("Load")) { + LoadStoryState(storyStateTextAsset.text); + } + EditorGUI.EndDisabledGroup(); + EditorGUILayout.EndHorizontal(); + if(storyStateTextAsset != null && !storyStateValid) { + EditorGUILayout.HelpBox("Loaded story state file is not valid.", MessageType.Error); + } + GUILayout.EndVertical(); + EditorGUI.EndDisabledGroup(); + } + #endregion + + + + + + + #region Diverts + void DrawNamedContent () { + DrawNamedContentHeader(); + if(InkPlayerWindowState.Instance.namedContentPanelState.showing) + DrawNamedContentPanel (); + } + + void DrawNamedContentHeader () { + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); + InkPlayerWindowState.Instance.namedContentPanelState.showing = EditorGUILayout.Foldout(InkPlayerWindowState.Instance.namedContentPanelState.showing, "Named Content", true); + + EditorGUI.BeginDisabledGroup(!InkPlayerWindowState.Instance.namedContentPanelState.showing); + bool changed = DrawSearchBar(ref InkPlayerWindowState.Instance.namedContentPanelState.searchString); + if(changed) InkPlayerWindowState.Instance.namedContentPanelState.scrollPosition = Vector2.zero; + EditorGUI.EndDisabledGroup(); + + EditorGUILayout.EndHorizontal(); + } + + void DrawNamedContentPanel () { + float contentMarginX = 4; + float contentMarginY = 0; + float indentChangeVerticalSpacing = 6; + + var lastRect = GUILayoutUtility.GetLastRect(); + var containerWidth = position.width - GUI.skin.verticalScrollbar.fixedWidth; + if(mainScrollViewActive) containerWidth -= GUI.skin.verticalScrollbar.fixedWidth; + + float totalHeight = 0; + + List rects = new List(); + List paths = new List(); + { + AddContainer(string.Empty, story.mainContentContainer); + void AddContainer (string currentPath, Container container, int indent = 0) { + if(container == null || container.namedOnlyContent == null) return; + + var lastTotalHeight = totalHeight; + indent++; + foreach(var contentKVP in container.namedOnlyContent) { + var newPath = currentPath.Length == 0 ? contentKVP.Key : currentPath+"."+contentKVP.Key; + AddContent(newPath, contentKVP, indent); + } + indent--; + if(lastTotalHeight != totalHeight) totalHeight += indentChangeVerticalSpacing; + } + void AddContent (string currentPath, KeyValuePair contentKVP, int indent = 0) { + if(SearchStringMatch(currentPath, InkPlayerWindowState.Instance.namedContentPanelState.searchString)) { + var itemHeight = EditorGUIUtility.singleLineHeight; + itemHeight += contentMarginY * 2; + + rects.Add(new Rect(indent*8, totalHeight, containerWidth-indent*8, itemHeight)); + totalHeight += itemHeight; + paths.Add(currentPath); + } + + var namedContainer = contentKVP.Value as Container; + AddContainer(currentPath, namedContainer, indent); + } + } + totalHeight -= indentChangeVerticalSpacing; + + if(Event.current.type == EventType.Repaint) { + InkPlayerWindowState.Instance.namedContentPanelState.y = lastRect.yMax; + } + var viewportRect = new Rect(0, lastRect.yMax, position.width, InkPlayerWindowState.Instance.namedContentPanelState.height); + if(mainScrollViewActive) viewportRect.width -= GUI.skin.verticalScrollbar.fixedWidth; + var containerRect = new Rect(0,0,containerWidth, totalHeight); + + var newScrollPos = GUI.BeginScrollView(viewportRect, InkPlayerWindowState.Instance.namedContentPanelState.scrollPosition, containerRect, false, true); + if(newScrollPos != InkPlayerWindowState.Instance.namedContentPanelState.scrollPosition) { + doingAutoscroll = false; + InkPlayerWindowState.Instance.namedContentPanelState.scrollPosition = newScrollPos; + } + + var panelTop = InkPlayerWindowState.Instance.namedContentPanelState.scrollPosition.y; + var panelBottom = InkPlayerWindowState.Instance.namedContentPanelState.scrollPosition.y + viewportRect.height; + + for(int i = 0; i < paths.Count; i++) { + if(panelTop <= rects[i].yMax && panelBottom >= rects[i].yMin) { + var content = paths[i]; + var lineContainerRect = rects[i]; + var lineRect = new Rect(lineContainerRect.x + contentMarginX, lineContainerRect.y + contentMarginY, lineContainerRect.width - contentMarginX * 2, lineContainerRect.height - contentMarginY * 2); + DrawNamedContentItem(lineRect, content); + } + } + + GUI.EndScrollView(); + GUILayout.Space(viewportRect.height); + } + + static GUIContent defaultDivertLabel = new GUIContent("Divert"); + void DrawNamedContentItem (Rect rect, string currentPath) { + EditorGUI.LabelField(rect, new GUIContent(currentPath, "Path")); + EditorGUI.LabelField(new Rect(rect.xMax-200, rect.y, 32, rect.height), new GUIContent(story.state.VisitCountAtPathString(currentPath).ToString(), "Read count")); + if(GUI.Button(new Rect(rect.xMax-168, rect.y, 80, rect.height), OnDivertLabelOverride == null ? defaultDivertLabel : OnDivertLabelOverride(currentPath))) { + if(OnDivertOverride != null) { + OnDivertOverride(currentPath); + } else { + // This is a bit horrible tbh. Not all the paths we show are valid for diverting, but we don't really have a way of testing it. + // Additionally, doing this can brick the story, so it's important we prevent it. + // We test by creating an entirely new story and running it, and checking for errors in the flow. + // The result is that this function is really slow :( + var hadError = false; + try { + // We might optimise this by caching story.ToJson() - we could use this in other places too. + var tmpStory = new Story(story.ToJson()); + tmpStory.allowExternalFunctionFallbacks = true; + var state = story.state.ToJson(); + tmpStory.state.LoadJson(state); + tmpStory.ChoosePathString(currentPath); + tmpStory.ContinueMaximally(); + } catch (Exception e) { + Debug.LogWarning("Could not divert to "+currentPath+"! Only Knots and Stitches can be diverted to. Is this a function? Alternatively, the path might lead to an error, which we prevent from occuring in this tool to safeguard the state.\n"+e.ToString()); + hadError = true; + } finally { + if(!hadError) { + story.ChoosePathString(currentPath); + AddToHistory(InkHistoryContentItem.CreateForDebugNote("Diverted to '"+currentPath+"'")); + } + } + } + } + + if(Event.current.type == EventType.MouseDown && Event.current.button == 1 && rect.Contains(Event.current.mousePosition)) { + var contextMenu = new GenericMenu(); + contextMenu.AddItem(new GUIContent("Copy Path"), false, () => { + GUIUtility.systemCopyBuffer = currentPath; + }); + contextMenu.ShowAsContext(); + Event.current.Use(); + } + } + #endregion + + + #region Functions + void DrawFunctions () { + DrawFunctionsHeader(); + if(InkPlayerWindowState.Instance.functionPanelState.showing) + DrawFunctionsPanel (); + } + + void DrawFunctionsHeader () { + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); + InkPlayerWindowState.Instance.functionPanelState.showing = EditorGUILayout.Foldout(InkPlayerWindowState.Instance.functionPanelState.showing, "Functions", true); + EditorGUILayout.EndHorizontal(); + } + + void DrawFunctionsPanel () { + GUILayout.BeginVertical(); + + DrawFunctionInput(); + DrawFunctionOutput(); + + GUILayout.EndVertical(); + } + + void DrawFunctionInput () { + // TODO - Autocomplete function names using this, which I should add to Story.cs ( ask joe first! ) + // public IEnumerable allFunctionNames { + // get { + // return mainContentContainer.namedContent.Keys; + // } + // } + + var functionParams = InkPlayerWindowState.Instance.functionPanelState.functionParams; + + GUILayout.BeginVertical(GUI.skin.box); + EditorGUI.BeginChangeCheck(); + functionParams.functionName = EditorGUILayout.TextField("Function Name", functionParams.functionName); + if(EditorGUI.EndChangeCheck()) { + InkPlayerWindowState.Instance.functionPanelState.testedFunctionHash = 0; + InkPlayerWindowState.Instance.functionPanelState.testedFunctionTime = default(DateTime); + InkPlayerWindowState.Instance.functionPanelState.functionReturnValue = null; + } + functionInputList.DoLayoutList(); + bool functionIsValid = functionParams.functionName != String.Empty && story.HasFunction(functionParams.functionName); + EditorGUI.BeginDisabledGroup(!functionIsValid); + + Story.ExternalFunction externalFunction; + var isExternalFunction = story.TryGetExternalFunction(functionParams.functionName, out externalFunction); + if (GUILayout.Button(new GUIContent(isExternalFunction ? "Execute (External)" : "Execute", "Runs the function"))) { + AddToHistory(InkHistoryContentItem.CreateForDebugNote("Execute function '"+functionParams.functionName+"'")); + string outputContent = null; + object[] allInput = new object[functionParams.inputs.Count]; + for (int i = 0; i < functionParams.inputs.Count; i++) { + var input = functionParams.inputs[i]; + object obj = null; + switch(input.type) { + case FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.Float: + obj = input.floatValue; + break; + case FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.Int: + obj = input.intValue; + break; + case FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.String: + obj = input.stringValue; + break; + case FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.Bool: + obj = input.boolValue; + break; + case FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.InkVariable: + obj = input.inkVariableValue; + break; + case FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.InkListVariable: + obj = input.inkListVariableValue; + break; + } + allInput[i] = obj; + } + if(isExternalFunction) { + OnEvaluateFunction(functionParams.functionName, allInput); + InkPlayerWindowState.Instance.functionPanelState.functionReturnValue = externalFunction (allInput); + OnCompleteEvaluateFunction(functionParams.functionName, allInput, null, InkPlayerWindowState.Instance.functionPanelState.functionReturnValue); + } else { + InkPlayerWindowState.Instance.functionPanelState.functionReturnValue = story.EvaluateFunction(functionParams.functionName, out outputContent, allInput); + } + if(outputContent != null) + AddStoryContent(outputContent, null); + + InkPlayerWindowState.Instance.functionPanelState.testedFunctionHash = functionParams.GetInputHashCode(); + InkPlayerWindowState.Instance.functionPanelState.testedFunctionTime = dateTimeNow; + } + EditorGUI.EndDisabledGroup(); + GUILayout.EndVertical(); + } + + void DrawFunctionOutput () { + float timeSinceLastWrite = (float)(dateTimeNow - InkPlayerWindowState.Instance.functionPanelState.testedFunctionTime).TotalSeconds; + var revealTime = 0.8f; + var l = Mathf.InverseLerp(revealTime, 0, timeSinceLastWrite); + var newColor = new Color(GUI.color.r, GUI.color.g, GUI.color.b, 0); + var color = Color.Lerp(GUI.color, newColor, l); + var oldGUIColor = GUI.color; + GUI.color = color; + + var functionParams = InkPlayerWindowState.Instance.functionPanelState.functionParams; + + bool functionIsValid = functionParams.functionName != String.Empty && story.HasFunction(functionParams.functionName); + if(functionIsValid && functionParams.GetInputHashCode() == InkPlayerWindowState.Instance.functionPanelState.testedFunctionHash) { + GUILayout.BeginVertical(GUI.skin.box); + if(InkPlayerWindowState.Instance.functionPanelState.functionReturnValue == null) { + EditorGUILayout.LabelField("Output (Null)"); + } else if(InkPlayerWindowState.Instance.functionPanelState.functionReturnValue is string) { + EditorGUILayout.TextField("Output (String)", (string)InkPlayerWindowState.Instance.functionPanelState.functionReturnValue); + } else if(InkPlayerWindowState.Instance.functionPanelState.functionReturnValue is float) { + EditorGUILayout.FloatField("Output (Float)", (float)InkPlayerWindowState.Instance.functionPanelState.functionReturnValue); + } else if(InkPlayerWindowState.Instance.functionPanelState.functionReturnValue is int) { + EditorGUILayout.IntField("Output (Int)", (int)InkPlayerWindowState.Instance.functionPanelState.functionReturnValue); + } else if(InkPlayerWindowState.Instance.functionPanelState.functionReturnValue is bool) { + EditorGUILayout.Toggle("Output (Bool)", (bool)InkPlayerWindowState.Instance.functionPanelState.functionReturnValue); + } else if(InkPlayerWindowState.Instance.functionPanelState.functionReturnValue is InkList) { + EditorGUILayoutInkListField(new GUIContent("Output (InkList)"), (InkList)InkPlayerWindowState.Instance.functionPanelState.functionReturnValue); + } else { + EditorGUILayout.LabelField("Function returned unexpected type "+InkPlayerWindowState.Instance.functionPanelState.functionReturnValue.GetType().Name+"."); + } + GUILayout.EndVertical(); + } + GUI.color = oldGUIColor; + } + + void BuildFunctionInputList () { + var functionParams = InkPlayerWindowState.Instance.functionPanelState.functionParams; + + functionInputList = new ReorderableList(functionParams.inputs, typeof(FunctionPanelState.FunctionParams.FunctionInput), true, true, true, true); + functionInputList.drawHeaderCallback = (Rect rect) => { + EditorGUI.LabelField(rect, "Inputs"); + }; + functionInputList.elementHeight = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing * 2; + functionInputList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => { + var input = functionParams.inputs[index]; + Rect typeRect = new Rect(rect.x, rect.y, 80, EditorGUIUtility.singleLineHeight); + input.type = (FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType)EditorGUI.EnumPopup(typeRect, input.type); + Rect inputRect = new Rect(rect.x + 90, rect.y, rect.width - 90, EditorGUIUtility.singleLineHeight); + switch(input.type) { + case FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.Float: + input.floatValue = EditorGUI.FloatField(inputRect, input.floatValue); + break; + case FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.Int: + input.intValue = EditorGUI.IntField(inputRect, input.intValue); + break; + case FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.String: + input.stringValue = EditorGUI.TextField(inputRect, input.stringValue); + break; + case FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.Bool: + input.boolValue = EditorGUI.Toggle(inputRect, input.boolValue); + break; + case FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.InkVariable: + { + var halfInput = new Rect(inputRect.x, inputRect.y, Mathf.RoundToInt(inputRect.width * 0.5f) - 5, inputRect.height); + var halfInput2 = new Rect(inputRect.x + Mathf.RoundToInt(inputRect.width * 0.5f) + 5, inputRect.y, Mathf.RoundToInt(inputRect.width * 0.5f) - 10, inputRect.height); + EditorGUI.BeginChangeCheck(); + input.inkVariablePath = EditorGUI.TextField(halfInput, input.inkVariablePath); + if(EditorGUI.EndChangeCheck()) input.RefreshInkVariableValue(story); + + EditorGUI.BeginDisabledGroup(true); + DrawVariable(halfInput2, GUIContent.none, input.inkVariableValue); + EditorGUI.EndDisabledGroup(); + } + break; + case FunctionPanelState.FunctionParams.FunctionInput.FunctionInputType.InkListVariable: + { + var halfInput = new Rect(inputRect.x, inputRect.y, Mathf.RoundToInt(inputRect.width * 0.5f) - 5, inputRect.height); + var halfInput2 = new Rect(inputRect.x + Mathf.RoundToInt(inputRect.width * 0.5f) + 5, inputRect.y, Mathf.RoundToInt(inputRect.width * 0.5f) - 10, inputRect.height); + EditorGUI.BeginChangeCheck(); + input.inkListVariablePath = EditorGUI.TextField(halfInput, input.inkListVariablePath); + if(EditorGUI.EndChangeCheck()) input.RefreshInkListVariableValue(story); + EditorGUI.BeginDisabledGroup(true); + DrawVariable(halfInput2, GUIContent.none, input.inkListVariableValue); + EditorGUI.EndDisabledGroup(); + } + break; + } + }; + } + #endregion + + + + + #region Variables + void DrawVariables () { + EditorGUILayout.BeginVertical(); + if(InkEditorUtils.StoryContainsVariables(story)) { + DrawVariablesHeader(); + if(InkPlayerWindowState.Instance.variablesPanelState.showing) + DrawVariablesPanel (); + + if(InkPlayerWindowState.Instance.observedVariablesPanelState.observedVariables.Count > 0) { + DrawObservedVariablesHeader(); + if(InkPlayerWindowState.Instance.observedVariablesPanelState.showing) + DrawObservedVariablesPanel (); + } + } + EditorGUILayout.EndVertical(); + } + + void DrawVariablesHeader () { + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); + InkPlayerWindowState.Instance.variablesPanelState.showing = EditorGUILayout.Foldout(InkPlayerWindowState.Instance.variablesPanelState.showing, "Variables", true); + + EditorGUI.BeginDisabledGroup(!InkPlayerWindowState.Instance.variablesPanelState.showing); + bool changed = DrawSearchBar(ref InkPlayerWindowState.Instance.variablesPanelState.searchString); + if(changed) { + RefreshVisibleVariables(); + InkPlayerWindowState.Instance.variablesPanelState.scrollPosition = Vector2.zero; + } + EditorGUI.EndDisabledGroup(); + + EditorGUILayout.EndHorizontal(); + } + + void DrawVariablesPanel () { + GUILayout.BeginVertical(GUI.skin.box, GUILayout.ExpandHeight(true)); + InkPlayerWindowState.Instance.variablesPanelState.scrollPosition = EditorGUILayout.BeginScrollView(InkPlayerWindowState.Instance.variablesPanelState.scrollPosition); + string variableToChange = null; + object newVariableValue = null; + foreach(string variable in visibleVariables) { + DrawObservableVariable(variable, ref variableToChange, ref newVariableValue); + } + if(variableToChange != null) { + AddToHistory(InkHistoryContentItem.CreateForDebugNote("Change '"+variableToChange+"' from '"+story.variablesState[variableToChange]+"' to '"+newVariableValue+"'")); + story.variablesState[variableToChange] = newVariableValue; + variableToChange = null; + newVariableValue = null; + } + + EditorGUILayout.EndScrollView(); + GUILayout.EndVertical(); + } + + static List visibleVariables = new List(); + static void RefreshVisibleVariables () { + visibleVariables.Clear(); + if(story == null) return; + bool doingSearch = !string.IsNullOrWhiteSpace(InkPlayerWindowState.Instance.variablesPanelState.searchString); + foreach(string variable in story.variablesState) { + if(doingSearch && !ShouldShowContentWithSearchString(variable, InkPlayerWindowState.Instance.variablesPanelState.searchString)) continue; + visibleVariables.Add(variable); + } + } + + // TODO - only draw those that are visible in the scroll rect, as we do for content. Important for performance on larger projects. + void DrawObservableVariable (string variable, ref string variableToChange, ref object newVariableValue) { + if(!SearchStringMatch(variable, InkPlayerWindowState.Instance.variablesPanelState.searchString)) + return; + EditorGUILayout.BeginHorizontal(); + object variableValue = story.variablesState[variable]; + if(DrawVariableLayout(new GUIContent(variable, variableValue.GetType().Name), variable, ref variableValue, "observable")) { + variableToChange = variable; + newVariableValue = variableValue; + } + + if(InkPlayerWindowState.Instance.observedVariablesPanelState.observedVariables.ContainsKey(variable)) { + if(GUILayout.Button(new GUIContent(unobserveIcon, "Un-observe this variable"), GUILayout.Width(24))) { + UnobserveVariable(variable, true); + } + } else { + if(GUILayout.Button(new GUIContent(observeIcon, "Click to observe this variable, tracking changes"), GUILayout.Width(24))) { + var observedVariable = ObserveVariable(variable, true); + observedVariable.AddValueState(variableValue); + } + } + EditorGUILayout.EndHorizontal(); + } + + static ObservedVariable ObserveVariable (string variableName, bool alsoAddToCache) { + if(InkPlayerWindowState.Instance.observedVariablesPanelState.observedVariables.ContainsKey(variableName)) return InkPlayerWindowState.Instance.observedVariablesPanelState.observedVariables[variableName]; + var observedVariable = new ObservedVariable(variableName); + observedVariable.variableObserver = (_variableName, newValue) => { + observedVariable.AddValueState(newValue); + }; + story.ObserveVariable(variableName, observedVariable.variableObserver); + InkPlayerWindowState.Instance.observedVariablesPanelState.observedVariables.Add(variableName, observedVariable); + if(alsoAddToCache) { + InkPlayerWindowState.Instance.observedVariablesPanelState.restorableObservedVariableNames.Add(variableName); + if(InkPlayerWindowState.Instance.observedVariablesPanelState.observedVariables.Count != InkPlayerWindowState.Instance.observedVariablesPanelState.restorableObservedVariableNames.Count) { + Debug.LogError(InkPlayerWindowState.Instance.observedVariablesPanelState.observedVariables.Count +" "+ InkPlayerWindowState.Instance.observedVariablesPanelState.restorableObservedVariableNames.Count); + InkPlayerWindowState.Instance.observedVariablesPanelState.restorableObservedVariableNames.Clear(); + InkPlayerWindowState.Instance.observedVariablesPanelState.observedVariables.Clear(); + } + } + return observedVariable; + } + + // The cache is used to restore observed variables when the user exits play mode. + static void UnobserveVariable (string variableName, bool alsoRemoveFromCache) { + if(!InkPlayerWindowState.Instance.observedVariablesPanelState.observedVariables.ContainsKey(variableName)) return; + + var observedVariable = InkPlayerWindowState.Instance.observedVariablesPanelState.observedVariables[variableName]; + story.RemoveVariableObserver(observedVariable.variableObserver, variableName); + InkPlayerWindowState.Instance.observedVariablesPanelState.observedVariables.Remove(variableName); + if(alsoRemoveFromCache) { + InkPlayerWindowState.Instance.observedVariablesPanelState.restorableObservedVariableNames.Remove(variableName); + if(InkPlayerWindowState.Instance.observedVariablesPanelState.observedVariables.Count != InkPlayerWindowState.Instance.observedVariablesPanelState.restorableObservedVariableNames.Count) { + Debug.LogError(InkPlayerWindowState.Instance.observedVariablesPanelState.observedVariables.Count +" "+ InkPlayerWindowState.Instance.observedVariablesPanelState.restorableObservedVariableNames.Count); + InkPlayerWindowState.Instance.observedVariablesPanelState.restorableObservedVariableNames.Clear(); + InkPlayerWindowState.Instance.observedVariablesPanelState.observedVariables.Clear(); + } + } + } + + bool DrawVariableLayout (GUIContent guiContent, string variableName, ref object variableValue, string expandedIDModifier) { + var lastVariableValue = variableValue; + var anythingChanged = false; + EditorGUILayout.BeginHorizontal(); + if(variableValue is string) { + EditorGUI.BeginDisabledGroup(playerParams.disableSettingVariables); + variableValue = EditorGUILayout.DelayedTextField(guiContent, (string)variableValue); + anythingChanged = (string)lastVariableValue != (string)variableValue; + EditorGUI.EndDisabledGroup(); + } else if(variableValue is float) { + EditorGUI.BeginDisabledGroup(playerParams.disableSettingVariables); + variableValue = EditorGUILayout.FloatField(guiContent, (float)variableValue); + anythingChanged = (float)lastVariableValue != (float)variableValue; + EditorGUI.EndDisabledGroup(); + } else if(variableValue is int) { + EditorGUI.BeginDisabledGroup(playerParams.disableSettingVariables); + variableValue = EditorGUILayout.IntField(guiContent, (int)variableValue); + anythingChanged = (int)lastVariableValue != (int)variableValue; + EditorGUI.EndDisabledGroup(); + } else if(variableValue is bool) { + EditorGUI.BeginDisabledGroup(playerParams.disableSettingVariables); + variableValue = EditorGUILayout.Toggle(guiContent, (bool)variableValue); + anythingChanged = (bool)lastVariableValue != (bool)variableValue; + EditorGUI.EndDisabledGroup(); + } else if(variableValue is InkList) { + anythingChanged = EditorGUILayoutInkListField(guiContent, (InkList)variableValue, variableName+expandedIDModifier); + } else if(variableValue is Ink.Runtime.Path) { + var c = new GUIContent(((Ink.Runtime.Path)variableValue).ToString()+" (Ink.Runtime.Path)"); + EditorGUILayout.LabelField(guiContent, c); + } else if(variableValue == null) { + EditorGUILayout.LabelField(guiContent, new GUIContent("InkPlayerError: Variable is null")); + } else { + EditorGUILayout.LabelField(guiContent, new GUIContent("InkPlayerError: Variable is of unexpected type "+variableValue.GetType().Name+".")); + } + EditorGUILayout.LabelField(variableValue.GetType().Name, EditorStyles.miniLabel, GUILayout.Width(80)); + EditorGUILayout.EndHorizontal(); + return anythingChanged; + } + + object DrawVariable (Rect rect, GUIContent variable, object variableValue) { + if(variableValue is string) { + variableValue = EditorGUI.TextField(rect, variable, (string)variableValue); + } else if(variableValue is float) { + variableValue = EditorGUI.FloatField(rect, variable, (float)variableValue); + } else if(variableValue is int) { + variableValue = EditorGUI.IntField(rect, variable, (int)variableValue); + } else if(variableValue is InkList) { + var c = new GUIContent(variable); + var inkList = (InkList)variableValue; + c.text += " (InkList)"; + if(inkList.Any()) { + bool first = true; + foreach(var item in inkList) { + if(!first) c.text += ", "; + c.text += item.ToString(); + first = false; + } + } else { + c.text += " Empty"; + } + EditorGUI.LabelField(rect, c); + } else if(variableValue is Ink.Runtime.Path) { + var c = new GUIContent(((Ink.Runtime.Path)variableValue).ToString()+" (Ink.Runtime.Path)"); + EditorGUI.LabelField(rect, c); + } else if(variableValue == null) { + EditorGUI.LabelField(rect, variable, new GUIContent("InkPlayerError: Variable is null")); + } else { + EditorGUI.LabelField(rect, variable, new GUIContent("InkPlayerError: Variable is of unexpected type "+variableValue.GetType().Name+".")); + } + return variableValue; + } + + void DrawObservedVariablesHeader () { + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); + InkPlayerWindowState.Instance.observedVariablesPanelState.showing = EditorGUILayout.Foldout(InkPlayerWindowState.Instance.observedVariablesPanelState.showing, "Observed Variables", true); + EditorGUILayout.EndHorizontal(); + } + + void DrawObservedVariablesPanel () { + List allToRemove = new List(); + foreach(var observedVariable in InkPlayerWindowState.Instance.observedVariablesPanelState.observedVariables) { + bool removeVariable = DrawObservedVariable(observedVariable.Value); + if(removeVariable) + allToRemove.Add(observedVariable.Key); + } + foreach(var toRemove in allToRemove) { + UnobserveVariable(toRemove, true); + } + } + + bool DrawObservedVariable (ObservedVariable observedVariable) { + GUILayout.BeginHorizontal(); + observedVariable.expanded = EditorGUILayout.Foldout(observedVariable.expanded, observedVariable.variable, true); + if(GUILayout.Button(new GUIContent(unobserveIcon, "Un-observe this variable"), GUILayout.Width(24))) { + return true; + } + GUILayout.EndHorizontal(); + + if(observedVariable.expanded) { + GUILayout.BeginVertical(GUILayout.ExpandHeight(false)); + observedVariable.scrollPosition = EditorGUILayout.BeginScrollView(observedVariable.scrollPosition, GUI.skin.box); + + foreach(var value in observedVariable.values) { + DrawVariableLayout(new GUIContent(value.dateTime.ToLongTimeString()), observedVariable.variable, ref value.state, "observed"+value.GetHashCode().ToString()); + } + + EditorGUILayout.EndScrollView(); + GUILayout.EndVertical(); + } + + return false; + } + #endregion + + + + + + #region Profiler + static bool isProfiling { + get { + return _currentStoryProfiler != null; + } + set { + var shouldBeProfiling = value; + if( shouldBeProfiling != isProfiling ) { + if( _currentStoryProfiler == null ) { + _currentStoryProfiler = story.StartProfiling(); + } else { + story.EndProfiling(); + _profilerResultRootNode = _currentStoryProfiler.rootNode; + + Debug.Log(_currentStoryProfiler.StepLengthReport()); + + _previousStoryProfiler = _currentStoryProfiler; + _currentStoryProfiler = null; + } + } + } + } + static ProfileNode _profilerResultRootNode; + static Ink.Runtime.Profiler _currentStoryProfiler; + static Ink.Runtime.Profiler _previousStoryProfiler; + + void DrawProfilerData() { + + // Don't show profiler data at all if you've never clicked Profile button + if( _profilerResultRootNode == null && !isProfiling ) return; + + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); + InkPlayerWindowState.Instance.profilerPanelState.showing = EditorGUILayout.Foldout(InkPlayerWindowState.Instance.profilerPanelState.showing, "Profiler data", true); + GUILayout.FlexibleSpace(); + if( _previousStoryProfiler != null && GUILayout.Button("Save mega log", EditorStyles.toolbarButton) ) { + + var path = EditorUtility.SaveFilePanel( + "Save mega log", + "", + "megalog.txt", + "txt"); + if( path != null && path.Length > 0 ) + File.WriteAllText(path, _previousStoryProfiler.Megalog()); + + } + EditorGUILayout.EndHorizontal(); + + if(InkPlayerWindowState.Instance.profilerPanelState.showing) { + if(isProfiling) { + EditorGUILayout.LabelField("Click 'Stop Profiling' to show profiling results.", EditorStyles.centeredGreyMiniLabel); + } else { + DisplayProfileDataNode(_profilerResultRootNode); + } + } + } + + void DisplayProfileDataNode(ProfileNode node) { + var key = node.key; + if( key == null ) { + if( node == _profilerResultRootNode ) + key = "TOTAL"; + else + key = "?"; + } + + var nodeText = key + ": " + node.ownReport; + + if( node.hasChildren ) { + node.openInUI = EditorGUILayout.Foldout(node.openInUI, nodeText, true); + + if( node.openInUI ) { + EditorGUI.indentLevel++; + + foreach(var childNode in node.descendingOrderedNodes) + DisplayProfileDataNode(childNode.Value); + + EditorGUI.indentLevel--; + } + } else { + EditorGUILayout.LabelField(nodeText); + } + } + #endregion + + + + + + BaseStoryPanelState resizingPanel; + // float height = 50; + Rect GetResizeArea (float x, float width, float centerY) { + float height = 10; + return new Rect(x, centerY-Mathf.RoundToInt(height * 0.5f), width, height); + } + void HandleDragAndDrop () { + // Rect area1 = GUILayoutUtility.GetRect (0.0f, height, GUILayout.ExpandWidth (true)); + // Rect area2 = GUILayoutUtility.GetRect (0.0f, 50.0f, GUILayout.ExpandWidth (true)); + // GUI.Box (area1, "Add Trigger"); + // GUI.Box (area2, "Add Trigger"); + + // if (Event.current.type == EventType.DragUpdated) { + // DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + // Event.current.Use(); + // } else if (Event.current.type == EventType.DragPerform) { + // // To consume drag data. + + // DragAndDrop.AcceptDrag(); + // foreach (var obj in DragAndDrop.objectReferences) { + // if(obj is TextAsset && System.IO.Path.GetExtension(AssetDatabase.GetAssetPath(obj)) == ".json") { + // Play(obj as TextAsset); + // } + // } + // } + + if (resizingPanel != null && Event.current.type == EventType.MouseUp) { + resizingPanel = null; + Event.current.Use(); + } + HandlePanelResize(InkPlayerWindowState.Instance.storyPanelState, StoryPanelState.minScrollRectHeight, StoryPanelState.maxScrollRectHeight); + HandlePanelResize(InkPlayerWindowState.Instance.namedContentPanelState, StoryPanelState.minScrollRectHeight, StoryPanelState.maxScrollRectHeight); + } + void HandlePanelResize (BaseStoryPanelState panel, float minHeight, float maxHeight) { + var resizeArea = GetResizeArea(0, position.width, panel.y+panel.height); + EditorGUIUtility.AddCursorRect(resizeArea, MouseCursor.ResizeVertical); + + if (Event.current.type == EventType.MouseDown) { + if(resizeArea.Contains(Event.current.mousePosition)) { + resizingPanel = panel; + Event.current.Use(); + } + } + if (resizingPanel == panel) { + if(Event.current.type == EventType.MouseDrag) { + var targetHeight = panel.height + Event.current.delta.y; + panel.height = Mathf.Clamp(targetHeight, minHeight, maxHeight); + Event.current.Use(); + } + } + } + + #region Utils + static bool StringContains(string str, string toCheck, StringComparison comp) { + if(toCheck.Length == 0) return false; + return str.IndexOf(toCheck, comp) >= 0; + } + + static bool DrawSearchBar (ref string searchString) { + var lastString = searchString; + searchString = GUILayout.TextField(searchString, searchTextFieldStyle); + if (GUILayout.Button("", searchCancelButtonStyle)) { + searchString = string.Empty; + } + return lastString != searchString; + } + + static bool SearchStringMatch (string content, string searchString) { + return string.IsNullOrWhiteSpace(searchString) || StringContains(content, searchString, StringComparison.OrdinalIgnoreCase); + } + + + static bool EditorGUILayoutInkListField (GUIContent guiContent, InkList inkList, string expandedVariableKey = null) { + var anythingChanged = false; + // if(inkList.Any()) { + var show = expandedVariableKey == null ? true : InkPlayerWindowState.Instance.variablesPanelState.expandedVariables.Contains(expandedVariableKey); + var c = new GUIContent(guiContent); + c.text += " (InkList with "+inkList.Count+" entries)"; + EditorGUILayout.BeginVertical(); + + EditorGUI.BeginChangeCheck(); + show = EditorGUILayout.Foldout(show, c, true); + if(EditorGUI.EndChangeCheck() && expandedVariableKey != null) { + if(show) InkPlayerWindowState.Instance.variablesPanelState.expandedVariables.Add(expandedVariableKey); + else InkPlayerWindowState.Instance.variablesPanelState.expandedVariables.Remove(expandedVariableKey); + } + + if(show) { + EditorGUI.indentLevel++; + var isOrigin = inkList.origins == null; + var list = isOrigin ? inkList : inkList.all; + List> toAdd = null; + List toRemove = null; + foreach(var item in list) { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField(new GUIContent(item.Key.fullName)); + // Disabled until I can be bothered to integrate this into the change detection system + var contains = inkList.Contains(item); + var newContains = EditorGUILayout.Toggle(contains, GUILayout.Width(100)); + if(contains != newContains) { + if(newContains) { + if(toAdd == null) toAdd = new List>(); + toAdd.Add(item); + } else { + if(toRemove == null) toRemove = new List(); + toRemove.Add(item.Key); + } + anythingChanged = true; + } + EditorGUI.BeginDisabledGroup(true); + EditorGUILayout.IntField(item.Value, GUILayout.Width(100)); + EditorGUI.EndDisabledGroup(); + EditorGUILayout.EndHorizontal(); + } + if(toAdd != null) + foreach(var item in toAdd) + inkList.Add(item.Key, item.Value); + if(toRemove != null) + foreach(var item in toRemove) + inkList.Remove(item); + EditorGUI.indentLevel--; + } + EditorGUILayout.EndVertical(); + // } else { + // var c = new GUIContent(guiContent); + // c.text += " (InkList)"; + // EditorGUILayout.PrefixLabel(c); + // EditorGUILayout.LabelField("Empty"); + // } + return anythingChanged; + } + + // static void EditorGUILayoutInkListField (string text, InkList inkList) { + // EditorGUILayoutInkListField(new GUIContent(text), inkList); + // } + + // static void EditorGUILayoutInkListField (GUIContent content, InkList inkList) { + // EditorGUILayout.BeginVertical(GUI.skin.box); + // EditorGUILayout.LabelField("InkList with "+inkList.Count+" values:", EditorStyles.boldLabel); + // foreach(var item in inkList) { + // EditorGUILayout.LabelField(item.Key.ToString()+" ("+item.Value.ToString()+")"); + // } + // EditorGUILayout.EndVertical(); + // } + static void EditorGUIInkListField (Rect rect, GUIContent content, InkList inkList, string variableName) { + EditorGUI.PrefixLabel(rect, content); + if(inkList.Any()) { + if(GUILayout.Button("Log Contents")) { + string log = "Log for InkList "+variableName+":"; + foreach(var item in inkList) + log += item.ToString() + " / "; + Debug.Log(log); + } + } else { + EditorGUI.LabelField(rect, "Empty"); + } + } + #endregion + + + + + static GUIStyle _wordWrappedTextArea; + static GUIStyle wordWrappedTextArea { + get { + if(_wordWrappedTextArea == null) { + _wordWrappedTextArea = new GUIStyle(EditorStyles.textArea); + _wordWrappedTextArea.wordWrap = true; + } + return _wordWrappedTextArea; + } + } + + static Texture _profilerIcon; + static Texture profilerIcon { + get { + if(_profilerIcon == null) { + _profilerIcon = EditorGUIUtility.IconContent("UnityEditor.ProfilerWindow").image; + // Profiler.CPU + // Record Off + // Record On + } + return _profilerIcon; + } + } + + static Texture _playIcon; + static Texture playIcon { + get { + if(_playIcon == null) { + _playIcon = EditorGUIUtility.IconContent("PlayButton").image; + } + return _playIcon; + } + } + static Texture _stopIcon; + static Texture stopIcon { + get { + if(_stopIcon == null) { + _stopIcon = EditorGUIUtility.IconContent("PreMatQuad").image; + } + return _stopIcon; + } + } + static Texture _restartIcon; + static Texture restartIcon { + get { + if(_restartIcon == null) { + _restartIcon = EditorGUIUtility.IconContent("Refresh").image; + } + return _restartIcon; + } + } + static Texture _attachedStoryIcon; + static Texture attachedStoryIcon { + get { + if(_attachedStoryIcon == null) { + _attachedStoryIcon = EditorGUIUtility.IconContent("UnityEditor.FindDependencies").image; + } + return _attachedStoryIcon; + } + } + static Texture _saveIcon; + static Texture saveIcon { + get { + if(_saveIcon == null) { + _saveIcon = EditorGUIUtility.IconContent("SaveAs").image; + } + return _saveIcon; + } + } + static Texture _clearIcon; + static Texture clearIcon { + get { + if(_clearIcon == null) { + _clearIcon = EditorGUIUtility.IconContent("d_Grid.EraserTool").image; + // d_back + } + return _clearIcon; + } + } + static Texture _copyToClipboardIcon; + static Texture copyToClipboardIcon { + get { + if(_copyToClipboardIcon == null) { + _copyToClipboardIcon = EditorGUIUtility.IconContent("Clipboard").image; + } + return _copyToClipboardIcon; + } + } + static Texture _undoIcon; + static Texture undoIcon { + get { + if(_undoIcon == null) { + _undoIcon = EditorGUIUtility.IconContent("d_back").image; + // d_back + // Animation.PrevKey + } + return _undoIcon; + } + } + static Texture _redoIcon; + static Texture redoIcon { + get { + if(_redoIcon == null) { + _redoIcon = EditorGUIUtility.IconContent("d_forward").image; + // d_forward + // Animation.NextKey + } + return _redoIcon; + } + } + static Texture _warningIcon; + static Texture warningIcon { + get { + if(_warningIcon == null) { + _warningIcon = EditorGUIUtility.IconContent("console.warnicon.sml").image; + } + return _warningIcon; + } + } + static Texture _errorIcon; + static Texture errorIcon { + get { + if(_errorIcon == null) { + _errorIcon = EditorGUIUtility.IconContent("console.erroricon.sml").image; + } + return _errorIcon; + } + } + static Texture _functionIcon; + static Texture functionIcon { + get { + if(_functionIcon == null) { + _functionIcon = EditorGUIUtility.IconContent("d_StyleSheet Icon").image; + } + return _functionIcon; + } + } + static Texture _timeIntervalIcon; + static Texture timeIntervalIcon { + get { + if(_timeIntervalIcon == null) { + _timeIntervalIcon = EditorGUIUtility.IconContent("UnityEditor.AnimationWindow").image; + } + return _timeIntervalIcon; + } + } + static Texture _observeIcon; + static Texture observeIcon { + get { + if(_observeIcon == null) { + _observeIcon = EditorGUIUtility.IconContent("d_animationvisibilitytoggleon").image; + } + return _observeIcon; + } + } + static Texture _unobserveIcon; + static Texture unobserveIcon { + get { + if(_unobserveIcon == null) { + _unobserveIcon = EditorGUIUtility.IconContent("d_animationvisibilitytoggleoff").image; + } + return _unobserveIcon; + } + } + } + + // Keeps a history of state changes for an ink variable. Handy for debugging. + public class ObservedVariable { + public string variable; + public Story.VariableObserver variableObserver; + public List values = new List(); + public bool expanded = true; + public Vector2 scrollPosition = Vector2.zero; + + public class ObservedVariableState { + public object state; + public DateTime dateTime; + public ObservedVariableState (object state) { + // Make sure to clone any object ref types! (just InkList at time of writing) + if(state is InkList) state = new InkList((InkList)state); + this.state = state; + dateTime = InkPlayerWindow.dateTimeNow; + } + } + + public ObservedVariable (string variable) { + this.variable = variable; + } + public void AddValueState (object value) { + values.Add(new ObservedVariableState(value)); + } + } + + + public class ColoredBackgroundGUIStyle { + public GUIStyle guiStyle; + public ColoredBackgroundGUIStyle (Color color) : this (color, color) {} + public ColoredBackgroundGUIStyle (Color colorFree, Color colorPro) { + guiStyle = new GUIStyle(); + + var texture = new Texture2D( 1, 1 ); + texture.SetPixel(0, 0, EditorGUIUtility.isProSkin ? colorPro : colorFree); + texture.Apply(); + guiStyle.normal.background = texture; + } + public ColoredBackgroundGUIStyle (Color colorFree, Color colorPro, Color hoverColorFree, Color hoverColorPro) { + guiStyle = new GUIStyle(); + + var texture = new Texture2D( 1, 1 ); + texture.SetPixel(0, 0, EditorGUIUtility.isProSkin ? colorPro : colorFree); + texture.Apply(); + guiStyle.normal.background = texture; + + var hoverTexture = new Texture2D( 1, 1 ); + hoverTexture.SetPixel(0, 0, EditorGUIUtility.isProSkin ? hoverColorPro : hoverColorFree); + hoverTexture.Apply(); + guiStyle.hover.background = hoverTexture; + } + } + + + [System.Serializable] + public class UndoHistory where T : class { + + private int _undoHistoryIndex; + public int undoHistoryIndex { + get { + return _undoHistoryIndex; + } set { + _undoHistoryIndex = Mathf.Clamp(value, 0, undoHistory.Count-1); + if(OnChangeHistoryIndex != null) OnChangeHistoryIndex(undoHistory[undoHistoryIndex]); + } + } + + public List undoHistory; + public int maxHistoryItems = 100; + + public bool canUndo { + get { + return undoHistory.Count > 0 && undoHistoryIndex > 0; + } + } + + public bool canRedo { + get { + return undoHistory.Count > 0 && undoHistoryIndex < undoHistory.Count - 1; + } + } + + public delegate void OnUndoEvent(T historyItem); + public event OnUndoEvent OnUndo; + + public delegate void OnRedoEvent(T historyItem); + public event OnRedoEvent OnRedo; + + public delegate void OnChangeHistoryIndexEvent(T historyItem); + public event OnChangeHistoryIndexEvent OnChangeHistoryIndex; + + public delegate void OnChangeUndoHistoryEvent(); + public event OnChangeUndoHistoryEvent OnChangeUndoHistory; + + public UndoHistory () { + undoHistory = new List(); + _undoHistoryIndex = -1; + } + + public UndoHistory (int maxHistoryItems) : this () { + this.maxHistoryItems = Mathf.Clamp(maxHistoryItems, 1, int.MaxValue); + } + + public virtual void AddToUndoHistory (T state) { + if(undoHistory.Count > 0 && undoHistory.Count - (undoHistoryIndex + 1) > 0) { + undoHistory.RemoveRange(undoHistoryIndex + 1, undoHistory.Count - (undoHistoryIndex + 1)); + } + + if(undoHistory.Count >= maxHistoryItems) { + undoHistory.RemoveAt (0); + _undoHistoryIndex--; + } + + undoHistory.Add (state); + _undoHistoryIndex++; + + if(OnChangeUndoHistory != null) OnChangeUndoHistory(); + } + + public virtual void Clear () { + undoHistory.Clear(); + _undoHistoryIndex = -1; + if(OnChangeUndoHistory != null) OnChangeUndoHistory(); + } + + public virtual T Undo () { + if(!canUndo) { + if(undoHistory.Count > 0) + return default(T); + } else { + undoHistoryIndex--; + if(OnUndo != null) OnUndo(undoHistory[undoHistoryIndex]); + } + return undoHistory[undoHistoryIndex]; + } + + public virtual T Redo () { + if(!canRedo) { + if(undoHistory.Count > 0) + return default(T); + } else { + undoHistoryIndex++; + if(OnRedo != null) OnRedo(undoHistory[undoHistoryIndex]); + } + return undoHistory[undoHistoryIndex]; + } + + protected virtual void ApplyHistoryItem (T historyItem) {} + } + + public class InkPlayerHistoryItem { + public string inkStateJSON; + public List storyHistory; + + public InkPlayerHistoryItem (string inkStateJSON, List storyHistory) { + this.inkStateJSON = inkStateJSON; + this.storyHistory = storyHistory; + } + } +} \ No newline at end of file diff --git a/Assets/Ink/Editor/Tools/Startup Window/InkUnityIntegrationStartupWindow.cs b/Assets/Ink/Editor/Tools/Startup Window/InkUnityIntegrationStartupWindow.cs new file mode 100644 index 0000000..4e6eb6c --- /dev/null +++ b/Assets/Ink/Editor/Tools/Startup Window/InkUnityIntegrationStartupWindow.cs @@ -0,0 +1,111 @@ +using System; +using System.IO; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEngine; + +namespace Ink.UnityIntegration { + [InitializeOnLoad] + public class InkUnityIntegrationStartupWindow : EditorWindow { + const string editorPrefsKeyForVersionSeen = "Ink Unity Integration Startup Window Version Confirmed"; + const int announcementVersion = 2; + + Vector2 scrollPosition; + static int announcementVersionPreviouslySeen; + static string changelogText; + + static InkUnityIntegrationStartupWindow () { + EditorApplication.delayCall += TryCreateWindow; + } + + static void TryCreateWindow() { + if (InkSettings.instance.suppressStartupWindow) return; + announcementVersionPreviouslySeen = EditorPrefs.GetInt(editorPrefsKeyForVersionSeen, -1); + if(announcementVersion != announcementVersionPreviouslySeen) { + ShowWindow(); + } + } + + public static void ShowWindow () { + InkUnityIntegrationStartupWindow window = GetWindow(typeof(InkUnityIntegrationStartupWindow), true, "Ink Update "+InkLibrary.unityIntegrationVersionCurrent, true) as InkUnityIntegrationStartupWindow; + window.minSize = new Vector2(200, 200); + var size = new Vector2(520, 320); + window.position = new Rect((Screen.currentResolution.width-size.x) * 0.5f, (Screen.currentResolution.height-size.y) * 0.5f, size.x, size.y); + EditorPrefs.SetInt(editorPrefsKeyForVersionSeen, announcementVersion); + } + + void OnEnable() { + var packageDirectory = InkEditorUtils.FindAbsolutePluginDirectory(); + changelogText = File.ReadAllText(Path.Combine(packageDirectory, "CHANGELOG.md")); + } + + void OnGUI () + { + EditorGUILayout.BeginVertical(); + var areaSize = new Vector2(90,90); + GUILayout.BeginArea(new Rect((position.width-areaSize.x)*0.5f, 15, areaSize.x, areaSize.y)); + EditorGUILayout.BeginVertical(); + EditorGUILayout.LabelField(new GUIContent(InkEditorUtils.inkLogoIcon), GUILayout.Width(areaSize.x), GUILayout.Height(areaSize.x*((float)InkEditorUtils.inkLogoIcon.height/InkEditorUtils.inkLogoIcon.width))); + GUILayout.Space(5); + EditorGUILayout.LabelField("Version "+InkLibrary.unityIntegrationVersionCurrent, EditorStyles.centeredGreyMiniLabel); + EditorGUILayout.LabelField("Ink version "+InkLibrary.inkVersionCurrent, EditorStyles.centeredGreyMiniLabel); + EditorGUILayout.EndVertical(); + GUILayout.EndArea(); + + + GUILayout.Space(20+areaSize.y); + + if(announcementVersionPreviouslySeen == -1) { + EditorGUILayout.BeginVertical(GUI.skin.box); + EditorGUILayout.LabelField("New to ink?", EditorStyles.boldLabel); + EditorGUILayout.EndVertical(); + } + + { + EditorGUILayout.BeginHorizontal(); + + if (GUILayout.Button("About Ink")) { + Application.OpenURL("https://www.inklestudios.com/ink/"); + } + if (GUILayout.Button("❤️Support Us!❤️")) { + Application.OpenURL("https://www.patreon.com/inkle"); + } + if (GUILayout.Button("Discord Community+Support")) { + Application.OpenURL("https://discord.gg/inkle"); + } + if (GUILayout.Button("Close")) { + Close(); + } + EditorGUILayout.EndHorizontal(); + } + + EditorGUILayout.Space(); + + if(changelogText != null) { + scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); + + var versionSections = Regex.Split(changelogText, "## "); // Split markdown text into version sections + foreach (var section in versionSections) { + if (string.IsNullOrWhiteSpace(section)) continue; + + var lines = section.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); // Split each section into lines + var version = lines[0]; // First line is version + + EditorGUILayout.BeginVertical(GUI.skin.box); + EditorGUILayout.LabelField($"{version}", EditorStyles.boldLabel); + for (int i = 1; i < lines.Length; i++) { + var bulletPoint = lines[i].TrimStart('-').TrimStart(' '); + EditorGUILayout.LabelField($"• {bulletPoint}", EditorStyles.wordWrappedLabel); + } + + EditorGUILayout.EndVertical(); + } + + EditorGUILayout.EndScrollView(); + } + EditorGUILayout.Space(); + + EditorGUILayout.EndVertical(); + } + } +} \ No newline at end of file diff --git a/Assets/Ink/Extras/Sublime3Syntax.zip b/Assets/Ink/Extras/Sublime3Syntax.zip new file mode 100644 index 0000000000000000000000000000000000000000..93bb887928cd67e5e9fb5a5b6f9b41e51e922c28 GIT binary patch literal 11784 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 AIRF3v literal 0 HcmV?d00001 diff --git a/Assets/Ink/InkLibs/Ink-Libraries.asmdef b/Assets/Ink/InkLibs/Ink-Libraries.asmdef new file mode 100644 index 0000000..988193b --- /dev/null +++ b/Assets/Ink/InkLibs/Ink-Libraries.asmdef @@ -0,0 +1,6 @@ +{ + "name": "Ink-Libraries", + "references": [], + "includePlatforms": [], + "excludePlatforms": [] +} \ No newline at end of file diff --git a/Assets/Ink/InkLibs/InkCompiler/CharacterRange.cs b/Assets/Ink/InkLibs/InkCompiler/CharacterRange.cs new file mode 100644 index 0000000..40ae689 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/CharacterRange.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Ink +{ + /// + /// A class representing a character range. Allows for lazy-loading a corresponding character set. + /// + public sealed class CharacterRange + { + public static CharacterRange Define(char start, char end, IEnumerable excludes = null) + { + return new CharacterRange (start, end, excludes); + } + + /// + /// Returns a character set instance corresponding to the character range + /// represented by the current instance. + /// + /// + /// The internal character set is created once and cached in memory. + /// + /// The char set. + public CharacterSet ToCharacterSet () + { + if (_correspondingCharSet.Count == 0) + { + for (char c = _start; c <= _end; c++) + { + if (!_excludes.Contains (c)) + { + _correspondingCharSet.Add (c); + } + } + } + return _correspondingCharSet; + } + + public char start { get { return _start; } } + public char end { get { return _end; } } + + CharacterRange (char start, char end, IEnumerable excludes) + { + _start = start; + _end = end; + _excludes = excludes == null ? new HashSet() : new HashSet (excludes); + } + + char _start; + char _end; + ICollection _excludes; + CharacterSet _correspondingCharSet = new CharacterSet(); + } +} diff --git a/Assets/Ink/InkLibs/InkCompiler/CharacterSet.cs b/Assets/Ink/InkLibs/InkCompiler/CharacterSet.cs new file mode 100644 index 0000000..7e0eef2 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/CharacterSet.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; + +namespace Ink +{ + + public class CharacterSet : HashSet + { + public static CharacterSet FromRange(char start, char end) + { + return new CharacterSet ().AddRange (start, end); + } + + public CharacterSet () + { + } + + public CharacterSet(string str) + { + AddCharacters (str); + } + + public CharacterSet(CharacterSet charSetToCopy) + { + AddCharacters (charSetToCopy); + } + + public CharacterSet AddRange(char start, char end) + { + for(char c=start; c<=end; ++c) { + Add (c); + } + return this; + } + + public CharacterSet AddCharacters(IEnumerable chars) + { + foreach (char c in chars) { + Add (c); + } + return this; + } + + public CharacterSet AddCharacters (string chars) + { + foreach (char c in chars) { + Add (c); + } + return this; + } + + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/CommandLineInput.cs b/Assets/Ink/InkLibs/InkCompiler/CommandLineInput.cs new file mode 100644 index 0000000..88f1dfe --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/CommandLineInput.cs @@ -0,0 +1,12 @@ +namespace Ink +{ + public class CommandLineInput + { + public bool isHelp; + public bool isExit; + public int? choiceInput; + public int? debugSource; + public string debugPathLookup; + public object userImmediateModeStatement; + } +} \ No newline at end of file diff --git a/Assets/Ink/InkLibs/InkCompiler/Compiler.cs b/Assets/Ink/InkLibs/InkCompiler/Compiler.cs new file mode 100644 index 0000000..dab1dda --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/Compiler.cs @@ -0,0 +1,212 @@ +using System; +using System.Collections.Generic; +using Ink; + +namespace Ink +{ + public class Compiler + { + public class Options + { + public string sourceFilename; + public List pluginDirectories; + public bool countAllVisits; + public Ink.ErrorHandler errorHandler; + public Ink.IFileHandler fileHandler; + } + + public Parsed.Story parsedStory { + get { + return _parsedStory; + } + } + + public Compiler (string inkSource, Options options = null) + { + _inputString = inkSource; + _options = options ?? new Options(); + if( _options.pluginDirectories != null ) + _pluginManager = new PluginManager (_options.pluginDirectories); + } + + public Parsed.Story Parse() + { + _parser = new InkParser(_inputString, _options.sourceFilename, OnParseError, _options.fileHandler); + _parsedStory = _parser.Parse(); + return _parsedStory; + } + + public Runtime.Story Compile () + { + if( _pluginManager != null ) + _inputString = _pluginManager.PreParse(_inputString); + + Parse(); + + if( _pluginManager != null ) + _parsedStory = _pluginManager.PostParse(_parsedStory); + + if (_parsedStory != null && !_hadParseError) { + + _parsedStory.countAllVisits = _options.countAllVisits; + + _runtimeStory = _parsedStory.ExportRuntime (_options.errorHandler); + + if( _pluginManager != null ) + _runtimeStory = _pluginManager.PostExport (_parsedStory, _runtimeStory); + } else { + _runtimeStory = null; + } + + return _runtimeStory; + } + + public class CommandLineInputResult { + public bool requestsExit; + public int choiceIdx = -1; + public string divertedPath; + public string output; + } + public CommandLineInputResult HandleInput (CommandLineInput inputResult) + { + var result = new CommandLineInputResult (); + + // Request for debug source line number + if (inputResult.debugSource != null) { + var offset = (int)inputResult.debugSource; + var dm = DebugMetadataForContentAtOffset (offset); + if (dm != null) + result.output = "DebugSource: " + dm.ToString (); + else + result.output = "DebugSource: Unknown source"; + } + + // Request for runtime path lookup (to line number) + else if (inputResult.debugPathLookup != null) { + var pathStr = inputResult.debugPathLookup; + var contentResult = _runtimeStory.ContentAtPath (new Runtime.Path (pathStr)); + var dm = contentResult.obj.debugMetadata; + if( dm != null ) + result.output = "DebugSource: " + dm.ToString (); + else + result.output = "DebugSource: Unknown source"; + } + + // User entered some ink + else if (inputResult.userImmediateModeStatement != null) { + var parsedObj = inputResult.userImmediateModeStatement as Parsed.Object; + return ExecuteImmediateStatement(parsedObj); + + } else { + return null; + } + + return result; + } + + CommandLineInputResult ExecuteImmediateStatement(Parsed.Object parsedObj) { + var result = new CommandLineInputResult (); + + // Variable assignment: create in Parsed.Story as well as the Runtime.Story + // so that we don't get an error message during reference resolution + if (parsedObj is Parsed.VariableAssignment) { + var varAssign = (Parsed.VariableAssignment)parsedObj; + if (varAssign.isNewTemporaryDeclaration) { + _parsedStory.TryAddNewVariableDeclaration (varAssign); + } + } + + parsedObj.parent = _parsedStory; + var runtimeObj = parsedObj.runtimeObject; + + parsedObj.ResolveReferences (_parsedStory); + + if (!_parsedStory.hadError) { + + // Divert + if (parsedObj is Parsed.Divert) { + var parsedDivert = parsedObj as Parsed.Divert; + result.divertedPath = parsedDivert.runtimeDivert.targetPath.ToString(); + } + + // Expression or variable assignment + else if (parsedObj is Parsed.Expression || parsedObj is Parsed.VariableAssignment) { + var evalResult = _runtimeStory.EvaluateExpression ((Runtime.Container)runtimeObj); + if (evalResult != null) { + result.output = evalResult.ToString (); + } + } + } else { + _parsedStory.ResetError (); + } + + return result; + } + + public void RetrieveDebugSourceForLatestContent () + { + foreach (var outputObj in _runtimeStory.state.outputStream) { + var textContent = outputObj as Runtime.StringValue; + if (textContent != null) { + var range = new DebugSourceRange (); + range.length = textContent.value.Length; + range.debugMetadata = textContent.debugMetadata; + range.text = textContent.value; + _debugSourceRanges.Add (range); + } + } + } + + Runtime.DebugMetadata DebugMetadataForContentAtOffset (int offset) + { + int currOffset = 0; + + Runtime.DebugMetadata lastValidMetadata = null; + foreach (var range in _debugSourceRanges) { + if (range.debugMetadata != null) + lastValidMetadata = range.debugMetadata; + + if (offset >= currOffset && offset < currOffset + range.length) + return lastValidMetadata; + + currOffset += range.length; + } + + return null; + } + + public struct DebugSourceRange + { + public int length; + public Runtime.DebugMetadata debugMetadata; + public string text; + } + + // Need to wrap the error handler so that we know + // when there was a critical error between parse and codegen stages + void OnParseError (string message, ErrorType errorType) + { + if( errorType == ErrorType.Error ) + _hadParseError = true; + + if (_options.errorHandler != null) + _options.errorHandler (message, errorType); + else + throw new System.Exception(message); + } + + string _inputString; + Options _options; + + + InkParser _parser; + Parsed.Story _parsedStory; + Runtime.Story _runtimeStory; + + PluginManager _pluginManager; + + bool _hadParseError; + + List _debugSourceRanges = new List (); + } +} diff --git a/Assets/Ink/InkLibs/InkCompiler/FileHandler.cs b/Assets/Ink/InkLibs/InkCompiler/FileHandler.cs new file mode 100644 index 0000000..51a60bb --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/FileHandler.cs @@ -0,0 +1,24 @@ +using System.IO; + +namespace Ink +{ + public interface IFileHandler + { + string ResolveInkFilename (string includeName); + string LoadInkFileContents (string fullFilename); + } + + public class DefaultFileHandler : Ink.IFileHandler { + public string ResolveInkFilename (string includeName) + { + var workingDir = Directory.GetCurrentDirectory (); + var fullRootInkPath = Path.Combine (workingDir, includeName); + return fullRootInkPath; + } + + public string LoadInkFileContents (string fullFilename) + { + return File.ReadAllText (fullFilename); + } + } +} diff --git a/Assets/Ink/InkLibs/InkCompiler/InkParser/CommentEliminator.cs b/Assets/Ink/InkLibs/InkCompiler/InkParser/CommentEliminator.cs new file mode 100644 index 0000000..9d0cfee --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/InkParser/CommentEliminator.cs @@ -0,0 +1,93 @@ + +namespace Ink +{ + /// + /// Pre-pass before main ink parser runs. It actually performs two main tasks: + /// - comment elimination to simplify the parse rules in the main parser + /// - Conversion of Windows line endings (\r\n) to the simpler Unix style (\n), so + /// we don't have to worry about them later. + /// + public class CommentEliminator : StringParser + { + public CommentEliminator (string input) : base(input) + { + } + + public string Process() + { + // Make both comments and non-comments optional to handle trivial empty file case (or *only* comments) + var stringList = Interleave(Optional (CommentsAndNewlines), Optional(MainInk)); + + if (stringList != null) { + return string.Join("", stringList.ToArray()); + } else { + return null; + } + } + + string MainInk() + { + return ParseUntil (CommentsAndNewlines, _commentOrNewlineStartCharacter, null); + } + + string CommentsAndNewlines() + { + var newlines = Interleave (Optional (ParseNewline), Optional (ParseSingleComment)); + + if (newlines != null) { + return string.Join ("", newlines.ToArray()); + } else { + return null; + } + } + + // Valid comments always return either an empty string or pure newlines, + // which we want to keep so that line numbers stay the same + string ParseSingleComment() + { + return (string) OneOf (EndOfLineComment, BlockComment); + } + + string EndOfLineComment() + { + if (ParseString ("//") == null) { + return null; + } + + ParseUntilCharactersFromCharSet (_newlineCharacters); + + return ""; + } + + string BlockComment() + { + if (ParseString ("/*") == null) { + return null; + } + + int startLineIndex = lineIndex; + + var commentResult = ParseUntil (String("*/"), _commentBlockEndCharacter, null); + + if (!endOfInput) { + ParseString ("*/"); + } + + // Count the number of lines that were inside the block, and replicate them as newlines + // so that the line indexing still works from the original source + if (commentResult != null) { + return new string ('\n', lineIndex - startLineIndex); + } + + // No comment at all + else { + return null; + } + } + + CharacterSet _commentOrNewlineStartCharacter = new CharacterSet ("/\r\n"); + CharacterSet _commentBlockEndCharacter = new CharacterSet("*"); + CharacterSet _newlineCharacters = new CharacterSet ("\n\r"); + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser.cs b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser.cs new file mode 100644 index 0000000..fb53a39 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser.cs @@ -0,0 +1,182 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace Ink +{ + public partial class InkParser : StringParser + { + public InkParser(string str, string filenameForMetadata = null, Ink.ErrorHandler externalErrorHandler = null, IFileHandler fileHandler = null) + : this(str, filenameForMetadata, externalErrorHandler, null, fileHandler) + { } + + InkParser(string str, string inkFilename = null, Ink.ErrorHandler externalErrorHandler = null, InkParser rootParser = null, IFileHandler fileHandler = null) : base(str) { + _filename = inkFilename; + RegisterExpressionOperators (); + GenerateStatementLevelRules (); + + // Built in handler for all standard parse errors and warnings + this.errorHandler = OnStringParserError; + + // The above parse errors are then formatted as strings and passed + // to the Ink.ErrorHandler, or it throws an exception + _externalErrorHandler = externalErrorHandler; + + _fileHandler = fileHandler ?? new DefaultFileHandler(); + + if (rootParser == null) { + _rootParser = this; + + _openFilenames = new HashSet (); + + if (inkFilename != null) { + var fullRootInkPath = _fileHandler.ResolveInkFilename (inkFilename); + _openFilenames.Add (fullRootInkPath); + } + + } else { + _rootParser = rootParser; + } + + } + + // Main entry point + public Parsed.Story Parse() + { + List topLevelContent = StatementsAtLevel (StatementLevel.Top); + + // Note we used to return null if there were any errors, but this would mean + // that include files would return completely empty rather than attempting to + // continue with errors. Returning an empty include files meant that anything + // that *did* compile successfully would otherwise be ignored, generating way + // more errors than necessary. + return new Parsed.Story (topLevelContent, isInclude:_rootParser != this); + } + + protected List SeparatedList (SpecificParseRule mainRule, ParseRule separatorRule) where T : class + { + T firstElement = Parse (mainRule); + if (firstElement == null) return null; + + var allElements = new List (); + allElements.Add (firstElement); + + do { + + int nextElementRuleId = BeginRule (); + + var sep = separatorRule (); + if (sep == null) { + FailRule (nextElementRuleId); + break; + } + + var nextElement = Parse (mainRule); + if (nextElement == null) { + FailRule (nextElementRuleId); + break; + } + + SucceedRule (nextElementRuleId); + + allElements.Add (nextElement); + + } while (true); + + return allElements; + } + + protected override string PreProcessInputString(string str) + { + var inputWithCommentsRemoved = (new CommentEliminator (str)).Process(); + return inputWithCommentsRemoved; + } + + protected Runtime.DebugMetadata CreateDebugMetadata(StringParserState.Element stateAtStart, StringParserState.Element stateAtEnd) + { + var md = new Runtime.DebugMetadata (); + md.startLineNumber = stateAtStart.lineIndex + 1; + md.endLineNumber = stateAtEnd.lineIndex + 1; + md.startCharacterNumber = stateAtStart.characterInLineIndex + 1; + md.endCharacterNumber = stateAtEnd.characterInLineIndex + 1; + md.fileName = _filename; + return md; + } + + protected override void RuleDidSucceed(object result, StringParserState.Element stateAtStart, StringParserState.Element stateAtEnd) + { + // Apply DebugMetadata based on the state at the start of the rule + // (i.e. use line number as it was at the start of the rule) + var parsedObj = result as Parsed.Object; + if ( parsedObj) { + parsedObj.debugMetadata = CreateDebugMetadata(stateAtStart, stateAtEnd); + return; + } + + // A list of objects that doesn't already have metadata? + var parsedListObjs = result as List; + if (parsedListObjs != null) { + foreach (var parsedListObj in parsedListObjs) { + if (!parsedListObj.hasOwnDebugMetadata) { + parsedListObj.debugMetadata = CreateDebugMetadata(stateAtStart, stateAtEnd); + } + } + } + + var id = result as Parsed.Identifier; + if (id != null) { + id.debugMetadata = CreateDebugMetadata(stateAtStart, stateAtEnd); + } + } + + protected bool parsingStringExpression + { + get { + return GetFlag ((uint)CustomFlags.ParsingString); + } + set { + SetFlag ((uint)CustomFlags.ParsingString, value); + } + } + + protected bool tagActive + { + get { + return GetFlag ((uint)CustomFlags.TagActive); + } + set { + SetFlag ((uint)CustomFlags.TagActive, value); + } + } + + protected enum CustomFlags { + ParsingString = 0x1, + TagActive = 0x2 + } + + void OnStringParserError(string message, int index, int lineIndex, bool isWarning) + { + var warningType = isWarning ? "WARNING:" : "ERROR:"; + string fullMessage; + + if (_filename != null) { + fullMessage = string.Format(warningType+" '{0}' line {1}: {2}", _filename, (lineIndex+1), message); + } else { + fullMessage = string.Format(warningType+" line {0}: {1}", (lineIndex+1), message); + } + + if (_externalErrorHandler != null) { + _externalErrorHandler (fullMessage, isWarning ? ErrorType.Warning : ErrorType.Error); + } else { + throw new System.Exception (fullMessage); + } + } + + IFileHandler _fileHandler; + + Ink.ErrorHandler _externalErrorHandler; + + string _filename; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_AuthorWarning.cs b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_AuthorWarning.cs new file mode 100644 index 0000000..6e73e59 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_AuthorWarning.cs @@ -0,0 +1,28 @@ +using Ink.Parsed; + +namespace Ink +{ + public partial class InkParser + { + protected AuthorWarning AuthorWarning() + { + Whitespace (); + + var identifier = Parse (IdentifierWithMetadata); + if (identifier == null || identifier.name != "TODO") + return null; + + Whitespace (); + + ParseString (":"); + + Whitespace (); + + var message = ParseUntilCharactersFromString ("\n\r"); + + return new AuthorWarning (message); + } + + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_CharacterRanges.cs b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_CharacterRanges.cs new file mode 100644 index 0000000..3ac3962 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_CharacterRanges.cs @@ -0,0 +1,64 @@ +using Ink.Parsed; +using System; +using System.Text; +using System.Collections.Generic; +using System.Linq; + +namespace Ink +{ + public partial class InkParser + { + public static readonly CharacterRange LatinBasic = + CharacterRange.Define ('\u0041', '\u007A', excludes: new CharacterSet().AddRange('\u005B', '\u0060')); + public static readonly CharacterRange LatinExtendedA = CharacterRange.Define('\u0100', '\u017F'); // no excludes here + public static readonly CharacterRange LatinExtendedB = CharacterRange.Define('\u0180', '\u024F'); // no excludes here + public static readonly CharacterRange Greek = + CharacterRange.Define('\u0370', '\u03FF', excludes: new CharacterSet().AddRange('\u0378','\u0385').AddCharacters("\u0374\u0375\u0378\u0387\u038B\u038D\u03A2")); + public static readonly CharacterRange Cyrillic = + CharacterRange.Define('\u0400', '\u04FF', excludes: new CharacterSet().AddRange('\u0482', '\u0489')); + public static readonly CharacterRange Armenian = + CharacterRange.Define('\u0530', '\u058F', excludes: new CharacterSet().AddCharacters("\u0530").AddRange('\u0557', '\u0560').AddRange('\u0588', '\u058E')); + public static readonly CharacterRange Hebrew = + CharacterRange.Define('\u0590', '\u05FF', excludes: new CharacterSet()); + public static readonly CharacterRange Arabic = + CharacterRange.Define('\u0600', '\u06FF', excludes: new CharacterSet()); + public static readonly CharacterRange Korean = + CharacterRange.Define('\uAC00', '\uD7AF', excludes: new CharacterSet()); + public static readonly CharacterRange Latin1Supplement = + CharacterRange.Define('\u0080', '\u00FF', excludes: new CharacterSet()); + + private void ExtendIdentifierCharacterRanges(CharacterSet identifierCharSet) + { + var characterRanges = ListAllCharacterRanges(); + + foreach (var charRange in characterRanges) + { + identifierCharSet.AddCharacters(charRange.ToCharacterSet()); + } + } + + /// + /// Gets an array of representing all of the currently supported + /// non-ASCII character ranges that can be used in identifier names. + /// + /// + /// An array of representing all of the currently supported + /// non-ASCII character ranges that can be used in identifier names. + /// + public static CharacterRange[] ListAllCharacterRanges() { + return new CharacterRange[] { + LatinBasic, + LatinExtendedA, + LatinExtendedB, + Arabic, + Armenian, + Cyrillic, + Greek, + Hebrew, + Korean, + Latin1Supplement, + }; + } + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Choices.cs b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Choices.cs new file mode 100644 index 0000000..3a54834 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Choices.cs @@ -0,0 +1,228 @@ +using Ink.Parsed; +using System.Diagnostics; + +namespace Ink +{ + public partial class InkParser + { + protected Choice Choice() + { + bool onceOnlyChoice = true; + var bullets = Interleave (OptionalExclude(Whitespace), String("*") ); + if (bullets == null) { + + bullets = Interleave (OptionalExclude(Whitespace), String("+") ); + if (bullets == null) { + return null; + } + + onceOnlyChoice = false; + } + + // Optional name for the choice + Identifier optionalName = Parse(BracketedName); + + Whitespace (); + + // Optional condition for whether the choice should be shown to the player + Expression conditionExpr = Parse(ChoiceCondition); + + Whitespace (); + + // Ordinarily we avoid parser state variables like these, since + // nesting would require us to store them in a stack. But since you should + // never be able to nest choices within choice content, it's fine here. + Debug.Assert(_parsingChoice == false, "Already parsing a choice - shouldn't have nested choices"); + _parsingChoice = true; + + ContentList startContent = null; + var startTextAndLogic = Parse (MixedTextAndLogic); + if (startTextAndLogic != null) + startContent = new ContentList (startTextAndLogic); + + + ContentList optionOnlyContent = null; + ContentList innerContent = null; + + // Check for a the weave style format: + // * "Hello[."]," he said. + bool hasWeaveStyleInlineBrackets = ParseString("[") != null; + if (hasWeaveStyleInlineBrackets) { + + EndTagIfNecessary(startContent); + + var optionOnlyTextAndLogic = Parse (MixedTextAndLogic); + if (optionOnlyTextAndLogic != null) + optionOnlyContent = new ContentList (optionOnlyTextAndLogic); + + + Expect (String("]"), "closing ']' for weave-style option"); + + EndTagIfNecessary(optionOnlyContent); + + var innerTextAndLogic = Parse (MixedTextAndLogic); + if( innerTextAndLogic != null ) + innerContent = new ContentList (innerTextAndLogic); + } + + Whitespace (); + + EndTagIfNecessary(innerContent ?? startContent); + + // Finally, now we know we're at the end of the main choice body, parse + // any diverts separately. + var diverts = Parse(MultiDivert); + + _parsingChoice = false; + + Whitespace (); + + // Completely empty choice without even an empty divert? + bool emptyContent = !startContent && !innerContent && !optionOnlyContent; + if (emptyContent && diverts == null) + Warning ("Choice is completely empty. Interpretting as a default fallback choice. Add a divert arrow to remove this warning: * ->"); + + // * [] some text + else if (!startContent && hasWeaveStyleInlineBrackets && !optionOnlyContent) + Warning ("Blank choice - if you intended a default fallback choice, use the `* ->` syntax"); + + if (!innerContent) innerContent = new ContentList (); + + EndTagIfNecessary(innerContent); + + // Normal diverts on the end of a choice - simply add to the normal content + if (diverts != null) { + foreach (var divObj in diverts) { + // may be TunnelOnwards + var div = divObj as Divert; + + // Empty divert serves no purpose other than to say + // "this choice is intentionally left blank" + // (as an invisible default choice) + if (div && div.isEmpty) continue; + + innerContent.AddContent (divObj); + } + } + + // Terminate main content with a newline since this is the end of the line + // Note that this will be redundant if the diverts above definitely take + // the flow away permanently. + innerContent.AddContent (new Text ("\n")); + + var choice = new Choice (startContent, optionOnlyContent, innerContent); + choice.identifier = optionalName; + choice.indentationDepth = bullets.Count; + choice.hasWeaveStyleInlineBrackets = hasWeaveStyleInlineBrackets; + choice.condition = conditionExpr; + choice.onceOnly = onceOnlyChoice; + choice.isInvisibleDefault = emptyContent; + + return choice; + + } + + protected Expression ChoiceCondition() + { + var conditions = Interleave (ChoiceSingleCondition, ChoiceConditionsSpace); + if (conditions == null) + return null; + else if (conditions.Count == 1) + return conditions [0]; + else { + return new MultipleConditionExpression (conditions); + } + } + + protected object ChoiceConditionsSpace() + { + // Both optional + // Newline includes initial end of line whitespace + Newline (); + Whitespace (); + return ParseSuccess; + } + + protected Expression ChoiceSingleCondition() + { + if (ParseString ("{") == null) + return null; + + var condExpr = Expect(Expression, "choice condition inside { }") as Expression; + DisallowIncrement (condExpr); + + Expect (String ("}"), "closing '}' for choice condition"); + + return condExpr; + } + + protected Gather Gather() + { + object gatherDashCountObj = Parse(GatherDashes); + if (gatherDashCountObj == null) { + return null; + } + + int gatherDashCount = (int)gatherDashCountObj; + + // Optional name for the gather + Identifier optionalName = Parse(BracketedName); + + var gather = new Gather (optionalName, gatherDashCount); + + // Optional newline before gather's content begins + Newline (); + + return gather; + } + + protected object GatherDashes() + { + Whitespace (); + + int gatherDashCount = 0; + + while (ParseDashNotArrow () != null) { + gatherDashCount++; + Whitespace (); + } + + if (gatherDashCount == 0) + return null; + + return gatherDashCount; + } + + protected object ParseDashNotArrow() + { + var ruleId = BeginRule (); + + if (ParseString ("->") == null && ParseSingleCharacter () == '-') { + return SucceedRule (ruleId); + } else { + return FailRule (ruleId); + } + } + + protected Identifier BracketedName() + { + if (ParseString ("(") == null) + return null; + + Whitespace (); + + Identifier name = Parse(IdentifierWithMetadata); + if (name == null) + return null; + + Whitespace (); + + Expect (String (")"), "closing ')' for bracketed name"); + + return name; + } + + bool _parsingChoice; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_CommandLineInput.cs b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_CommandLineInput.cs new file mode 100644 index 0000000..a04ef17 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_CommandLineInput.cs @@ -0,0 +1,129 @@ + +namespace Ink +{ + public partial class InkParser + { + // Valid returned objects: + // - "help" + // - int: for choice number + // - Parsed.Divert + // - Variable declaration/assignment + // - Epression + // - Lookup debug source for character offset + // - Lookup debug source for runtime path + public CommandLineInput CommandLineUserInput() + { + CommandLineInput result = new CommandLineInput (); + + Whitespace (); + + if (ParseString ("help") != null) { + result.isHelp = true; + return result; + } + + if (ParseString ("exit") != null || ParseString ("quit") != null) { + result.isExit = true; + return result; + } + + return (CommandLineInput) OneOf ( + DebugSource, + DebugPathLookup, + UserChoiceNumber, + UserImmediateModeStatement + ); + } + + CommandLineInput DebugSource () + { + Whitespace (); + + if (ParseString ("DebugSource") == null) + return null; + + Whitespace (); + + var expectMsg = "character offset in parentheses, e.g. DebugSource(5)"; + if (Expect (String ("("), expectMsg) == null) + return null; + + Whitespace (); + + int? characterOffset = ParseInt (); + if (characterOffset == null) { + Error (expectMsg); + return null; + } + + Whitespace (); + + Expect (String (")"), "closing parenthesis"); + + var inputStruct = new CommandLineInput (); + inputStruct.debugSource = characterOffset; + return inputStruct; + } + + CommandLineInput DebugPathLookup () + { + Whitespace (); + + if (ParseString ("DebugPath") == null) + return null; + + if (Whitespace () == null) + return null; + + var pathStr = Expect (RuntimePath, "path") as string; + + var inputStruct = new CommandLineInput (); + inputStruct.debugPathLookup = pathStr; + return inputStruct; + } + + string RuntimePath () + { + if (_runtimePathCharacterSet == null) { + _runtimePathCharacterSet = new CharacterSet (identifierCharSet); + _runtimePathCharacterSet.Add ('-'); // for c-0, g-0 etc + _runtimePathCharacterSet.Add ('.'); + + } + + return ParseCharactersFromCharSet (_runtimePathCharacterSet); + } + + CommandLineInput UserChoiceNumber() + { + Whitespace (); + + int? number = ParseInt (); + if (number == null) { + return null; + } + + Whitespace (); + + if (Parse(EndOfLine) == null) { + return null; + } + + var inputStruct = new CommandLineInput (); + inputStruct.choiceInput = number; + return inputStruct; + } + + CommandLineInput UserImmediateModeStatement() + { + var statement = OneOf (SingleDivert, TempDeclarationOrAssignment, Expression); + + var inputStruct = new CommandLineInput (); + inputStruct.userImmediateModeStatement = statement; + return inputStruct; + } + + CharacterSet _runtimePathCharacterSet; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Conditional.cs b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Conditional.cs new file mode 100644 index 0000000..c1f60ec --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Conditional.cs @@ -0,0 +1,288 @@ +using System.Collections.Generic; +using System.Linq; +using Ink.Parsed; + +namespace Ink +{ + public partial class InkParser + { + protected Conditional InnerConditionalContent() + { + var initialQueryExpression = Parse(ConditionExpression); + var conditional = Parse(() => InnerConditionalContent (initialQueryExpression)); + if (conditional == null) + return null; + + return conditional; + } + + protected Conditional InnerConditionalContent(Expression initialQueryExpression) + { + List alternatives; + + bool canBeInline = initialQueryExpression != null; + bool isInline = Parse(Newline) == null; + + if (isInline && !canBeInline) { + return null; + } + + // Inline innards + if (isInline) { + alternatives = InlineConditionalBranches (); + } + + // Multiline innards + else { + alternatives = MultilineConditionalBranches (); + if (alternatives == null) { + + // Allow single piece of content within multi-line expression, e.g.: + // { true: + // Some content that isn't preceded by '-' + // } + if (initialQueryExpression) { + List soleContent = StatementsAtLevel (StatementLevel.InnerBlock); + if (soleContent != null) { + var soleBranch = new ConditionalSingleBranch (soleContent); + alternatives = new List (); + alternatives.Add (soleBranch); + + // Also allow a final "- else:" clause + var elseBranch = Parse (SingleMultilineCondition); + if (elseBranch) { + if (!elseBranch.isElse) { + ErrorWithParsedObject ("Expected an '- else:' clause here rather than an extra condition", elseBranch); + elseBranch.isElse = true; + } + alternatives.Add (elseBranch); + } + } + } + + // Still null? + if (alternatives == null) { + return null; + } + } + + // Empty true branch - didn't get parsed, but should insert one for semantic correctness, + // and to make sure that any evaluation stack values get tidied up correctly. + else if (alternatives.Count == 1 && alternatives [0].isElse && initialQueryExpression) { + var emptyTrueBranch = new ConditionalSingleBranch (null); + emptyTrueBranch.isTrueBranch = true; + alternatives.Insert (0, emptyTrueBranch); + } + + // Like a switch statement + // { initialQueryExpression: + // ... match the expression + // } + if (initialQueryExpression) { + + bool earlierBranchesHaveOwnExpression = false; + for (int i = 0; i < alternatives.Count; ++i) { + var branch = alternatives [i]; + bool isLast = (i == alternatives.Count - 1); + + // Matching equality with initial query expression + // We set this flag even for the "else" clause so that + // it knows to tidy up the evaluation stack at the end + + // Match query + if (branch.ownExpression) { + branch.matchingEquality = true; + earlierBranchesHaveOwnExpression = true; + } + + // Else (final branch) + else if (earlierBranchesHaveOwnExpression && isLast) { + branch.matchingEquality = true; + branch.isElse = true; + } + + // Binary condition: + // { trueOrFalse: + // - when true + // - when false + // } + else { + + if (!isLast && alternatives.Count > 2) { + ErrorWithParsedObject ("Only final branch can be an 'else'. Did you miss a ':'?", branch); + } else { + if (i == 0) + branch.isTrueBranch = true; + else + branch.isElse = true; + } + } + } + } + + // No initial query, so just a multi-line conditional. e.g.: + // { + // - x > 3: greater than three + // - x == 3: equal to three + // - x < 3: less than three + // } + else { + + for (int i = 0; i < alternatives.Count; ++i) { + var alt = alternatives [i]; + bool isLast = (i == alternatives.Count - 1); + if (alt.ownExpression == null) { + if (isLast) { + alt.isElse = true; + } else { + if (alt.isElse) { + // Do we ALSO have a valid "else" at the end? Let's report the error there. + var finalClause = alternatives [alternatives.Count - 1]; + if (finalClause.isElse) { + ErrorWithParsedObject ("Multiple 'else' cases. Can have a maximum of one, at the end.", finalClause); + } else { + ErrorWithParsedObject ("'else' case in conditional should always be the final one", alt); + } + } else { + ErrorWithParsedObject ("Branch doesn't have condition. Are you missing a ':'? ", alt); + } + + } + } + } + + if (alternatives.Count == 1 && alternatives [0].ownExpression == null) { + ErrorWithParsedObject ("Condition block with no conditions", alternatives [0]); + } + } + } + + // TODO: Come up with water-tight error conditions... it's quite a flexible system! + // e.g. + // - inline conditionals must have exactly 1 or 2 alternatives + // - multiline expression shouldn't have mixed existence of branch-conditions? + if (alternatives == null) + return null; + + foreach (var branch in alternatives) { + branch.isInline = isInline; + } + + var cond = new Conditional (initialQueryExpression, alternatives); + return cond; + } + + protected List InlineConditionalBranches() + { + var listOfLists = Interleave> (MixedTextAndLogic, Exclude (String ("|")), flatten: false); + if (listOfLists == null || listOfLists.Count == 0) { + return null; + } + + var result = new List (); + + if (listOfLists.Count > 2) { + Error ("Expected one or two alternatives separated by '|' in inline conditional"); + } else { + + var trueBranch = new ConditionalSingleBranch (listOfLists[0]); + trueBranch.isTrueBranch = true; + result.Add (trueBranch); + + if (listOfLists.Count > 1) { + var elseBranch = new ConditionalSingleBranch (listOfLists[1]); + elseBranch.isElse = true; + result.Add (elseBranch); + } + } + + return result; + } + + protected List MultilineConditionalBranches() + { + MultilineWhitespace (); + + List multipleConditions = OneOrMore (SingleMultilineCondition); + if (multipleConditions == null) + return null; + + MultilineWhitespace (); + + return multipleConditions.Cast().ToList(); + } + + protected ConditionalSingleBranch SingleMultilineCondition() + { + Whitespace (); + + // Make sure we're not accidentally parsing a divert + if (ParseString ("->") != null) + return null; + + if (ParseString ("-") == null) + return null; + + Whitespace (); + + Expression expr = null; + bool isElse = Parse(ElseExpression) != null; + + if( !isElse ) + expr = Parse(ConditionExpression); + + List content = StatementsAtLevel (StatementLevel.InnerBlock); + if (expr == null && content == null) { + Error ("expected content for the conditional branch following '-'"); + + // Recover + content = new List (); + content.Add (new Text ("")); + } + + // Allow additional multiline whitespace, if the statements were empty (valid) + // then their surrounding multiline whitespacce needs to be handled manually. + // e.g. + // { x: + // - 1: // intentionally left blank, but newline needs to be parsed + // - 2: etc + // } + MultilineWhitespace (); + + var branch = new ConditionalSingleBranch (content); + branch.ownExpression = expr; + branch.isElse = isElse; + return branch; + } + + protected Expression ConditionExpression() + { + var expr = Parse(Expression); + if (expr == null) + return null; + + DisallowIncrement (expr); + + Whitespace (); + + if (ParseString (":") == null) + return null; + + return expr; + } + + protected object ElseExpression() + { + if (ParseString ("else") == null) + return null; + + Whitespace (); + + if (ParseString (":") == null) + return null; + + return ParseSuccess; + } + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Content.cs b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Content.cs new file mode 100644 index 0000000..0cc7fd8 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Content.cs @@ -0,0 +1,210 @@ +using Ink.Parsed; +using System.Text; +using System.Collections.Generic; +using System.Linq; + +namespace Ink +{ + public partial class InkParser + { + void TrimEndWhitespace(List mixedTextAndLogicResults, bool terminateWithSpace) + { + // Trim whitespace from end + if (mixedTextAndLogicResults.Count > 0) { + var lastObjIdx = mixedTextAndLogicResults.Count - 1; + var lastObj = mixedTextAndLogicResults[lastObjIdx]; + if (lastObj is Text) { + var text = (Text)lastObj; + text.text = text.text.TrimEnd (' ', '\t'); + + if (terminateWithSpace) + text.text += " "; + + // No content left at all? trim the whole object + else if( text.text.Length == 0 ) { + mixedTextAndLogicResults.RemoveAt(lastObjIdx); + + // Recurse in case there's more whitespace + TrimEndWhitespace(mixedTextAndLogicResults, terminateWithSpace:false); + } + } + } + } + + protected List LineOfMixedTextAndLogic() + { + // Consume any whitespace at the start of the line + // (Except for escaped whitespace) + Parse (Whitespace); + + var result = Parse(MixedTextAndLogic); + if (result == null || result.Count == 0) + return null; + + // Warn about accidentally writing "return" without "~" + var firstText = result[0] as Text; + if (firstText) { + if (firstText.text.StartsWith ("return")) { + Warning ("Do you need a '~' before 'return'? If not, perhaps use a glue: <> (since it's lowercase) or rewrite somehow?"); + } + } + if (result.Count == 0) + return null; + + var lastObj = result [result.Count - 1]; + if (!(lastObj is Divert)) { + TrimEndWhitespace (result, terminateWithSpace:false); + } + + EndTagIfNecessary(result); + + // If the line doens't actually contain any normal text content + // but is in fact entirely a tag, then let's not append + // a newline, since we want the tag (or tags) to be associated + // with the line below rather than being completely independent. + bool lineIsPureTag = result.Count > 0 && result[0] is Parsed.Tag && ((Parsed.Tag)result[0]).isStart; + if( !lineIsPureTag ) + result.Add (new Text ("\n")); + + Expect(EndOfLine, "end of line", recoveryRule: SkipToNextLine); + + return result; + } + + protected List MixedTextAndLogic() + { + // Check for disallowed "~" within this context + var disallowedTilda = ParseObject(Spaced(String("~"))); + if (disallowedTilda != null) + Error ("You shouldn't use a '~' here - tildas are for logic that's on its own line. To do inline logic, use { curly braces } instead"); + + // Either, or both interleaved + var results = Interleave(Optional (ContentText), Optional (InlineLogicOrGlueOrStartTag)); + + // Terminating divert? + // (When parsing content for the text of a choice, diverts aren't allowed. + // The divert on the end of the body of a choice is handled specially.) + if (!_parsingChoice) { + + var diverts = Parse (MultiDivert); + if (diverts != null) { + + // May not have had any results at all if there's *only* a divert! + if (results == null) + results = new List (); + + // End previously active tag if necessary + EndTagIfNecessary(results); + + TrimEndWhitespace (results, terminateWithSpace:true); + + results.AddRange (diverts); + } + + } + + if (results == null) + return null; + + return results; + } + + protected Parsed.Text ContentText() + { + return ContentTextAllowingEcapeChar (); + } + + protected Parsed.Text ContentTextAllowingEcapeChar() + { + StringBuilder sb = null; + + do { + var str = Parse(ContentTextNoEscape); + bool gotEscapeChar = ParseString(@"\") != null; + + if( gotEscapeChar || str != null ) { + if( sb == null ) { + sb = new StringBuilder(); + } + + if( str != null ) { + sb.Append(str); + } + + if( gotEscapeChar ) { + char c = ParseSingleCharacter(); + sb.Append(c); + } + + } else { + break; + } + + } while(true); + + if (sb != null ) { + return new Parsed.Text (sb.ToString ()); + + } else { + return null; + } + } + + // Content text is an unusual parse rule compared with most since it's + // less about saying "this is is the small selection of stuff that we parse" + // and more "we parse ANYTHING except this small selection of stuff". + protected string ContentTextNoEscape() + { + // Eat through text, pausing at the following characters, and + // attempt to parse the nonTextRule. + // "-": possible start of divert or start of gather + // "<": possible start of glue + if (_nonTextPauseCharacters == null) { + _nonTextPauseCharacters = new CharacterSet ("-<"); + } + + // If we hit any of these characters, we stop *immediately* without bothering to even check the nonTextRule + // "{" for start of logic + // "|" for mid logic branch + if (_nonTextEndCharacters == null) { + _nonTextEndCharacters = new CharacterSet ("{}|\n\r\\#"); + _notTextEndCharactersChoice = new CharacterSet (_nonTextEndCharacters); + _notTextEndCharactersChoice.AddCharacters ("[]"); + _notTextEndCharactersString = new CharacterSet (_nonTextEndCharacters); + _notTextEndCharactersString.AddCharacters ("\""); + } + + // When the ParseUntil pauses, check these rules in case they evaluate successfully + ParseRule nonTextRule = () => OneOf (ParseDivertArrow, ParseThreadArrow, EndOfLine, Glue); + + CharacterSet endChars = null; + if (parsingStringExpression) { + endChars = _notTextEndCharactersString; + } + else if (_parsingChoice) { + endChars = _notTextEndCharactersChoice; + } + else { + endChars = _nonTextEndCharacters; + } + + string pureTextContent = ParseUntil (nonTextRule, _nonTextPauseCharacters, endChars); + if (pureTextContent != null ) { + return pureTextContent; + + } else { + return null; + } + + } + + CharacterSet _nonTextPauseCharacters; + CharacterSet _nonTextEndCharacters; + CharacterSet _notTextEndCharactersChoice; + CharacterSet _notTextEndCharactersString; + + + + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Divert.cs b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Divert.cs new file mode 100644 index 0000000..4ce1831 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Divert.cs @@ -0,0 +1,208 @@ +using System.Collections.Generic; +using Ink.Parsed; + + +namespace Ink +{ + public partial class InkParser + { + protected List MultiDivert() + { + Whitespace (); + + List diverts = null; + + // Try single thread first + var threadDivert = Parse(StartThread); + if (threadDivert) { + diverts = new List (); + diverts.Add (threadDivert); + return diverts; + } + + // Normal diverts and tunnels + var arrowsAndDiverts = Interleave ( + ParseDivertArrowOrTunnelOnwards, + DivertIdentifierWithArguments); + + if (arrowsAndDiverts == null) + return null; + + diverts = new List (); + + EndTagIfNecessary(diverts); + + // Possible patterns: + // -> -- explicit gather + // ->-> -- tunnel onwards + // -> div -- normal divert + // ->-> div -- tunnel onwards, followed by override divert + // -> div -> -- normal tunnel + // -> div ->-> -- tunnel then tunnel continue + // -> div -> div -- tunnel then divert + // -> div -> div -> -- tunnel then tunnel + // -> div -> div ->-> + // -> div -> div ->-> div (etc) + + // Look at the arrows and diverts + for (int i = 0; i < arrowsAndDiverts.Count; ++i) { + bool isArrow = (i % 2) == 0; + + // Arrow string + if (isArrow) { + + // Tunnel onwards + if ((string)arrowsAndDiverts [i] == "->->") { + + bool tunnelOnwardsPlacementValid = (i == 0 || i == arrowsAndDiverts.Count - 1 || i == arrowsAndDiverts.Count - 2); + if (!tunnelOnwardsPlacementValid) + Error ("Tunnel onwards '->->' must only come at the begining or the start of a divert"); + + var tunnelOnwards = new TunnelOnwards (); + if (i < arrowsAndDiverts.Count - 1) { + var tunnelOnwardDivert = arrowsAndDiverts [i+1] as Parsed.Divert; + tunnelOnwards.divertAfter = tunnelOnwardDivert; + } + + diverts.Add (tunnelOnwards); + + // Not allowed to do anything after a tunnel onwards. + // If we had anything left it would be caused in the above Error for + // the positioning of a ->-> + break; + } + } + + // Divert + else { + + var divert = arrowsAndDiverts [i] as Divert; + + // More to come? (further arrows) Must be tunnelling. + if (i < arrowsAndDiverts.Count - 1) { + divert.isTunnel = true; + } + + diverts.Add (divert); + } + } + + // Single -> (used for default choices) + if (diverts.Count == 0 && arrowsAndDiverts.Count == 1) { + var gatherDivert = new Divert ((Parsed.Object)null); + gatherDivert.isEmpty = true; + diverts.Add (gatherDivert); + + if (!_parsingChoice) + Error ("Empty diverts (->) are only valid on choices"); + } + + return diverts; + } + + protected Divert StartThread() + { + Whitespace (); + + if (ParseThreadArrow() == null) + return null; + + Whitespace (); + + var divert = Expect(DivertIdentifierWithArguments, "target for new thread", () => new Divert(null)) as Divert; + divert.isThread = true; + + return divert; + } + + protected Divert DivertIdentifierWithArguments() + { + Whitespace (); + + List targetComponents = Parse (DotSeparatedDivertPathComponents); + if (targetComponents == null) + return null; + + Whitespace (); + + var optionalArguments = Parse(ExpressionFunctionCallArguments); + + Whitespace (); + + var targetPath = new Path (targetComponents); + return new Divert (targetPath, optionalArguments); + } + + protected Divert SingleDivert() + { + var diverts = Parse (MultiDivert); + if (diverts == null) + return null; + + // Ideally we'd report errors if we get the + // wrong kind of divert, but unfortunately we + // have to hack around the fact that sequences use + // a very similar syntax. + // i.e. if you have a multi-divert at the start + // of a sequence, it initially tries to parse it + // as a divert target (part of an expression of + // a conditional) and gives errors. So instead + // we just have to blindly reject it as a single + // divert, and give a slightly less nice error + // when you DO use a multi divert as a divert taret. + + if (diverts.Count != 1) { + return null; + } + + var singleDivert = diverts [0]; + if (singleDivert is TunnelOnwards) { + return null; + } + + var divert = diverts [0] as Divert; + if (divert.isTunnel) { + return null; + } + + return divert; + } + + List DotSeparatedDivertPathComponents() + { + return Interleave (Spaced (IdentifierWithMetadata), Exclude (String ("."))); + } + + protected string ParseDivertArrowOrTunnelOnwards() + { + int numArrows = 0; + while (ParseString ("->") != null) + numArrows++; + + if (numArrows == 0) + return null; + + else if (numArrows == 1) + return "->"; + + else if (numArrows == 2) + return "->->"; + + else { + Error ("Unexpected number of arrows in divert. Should only have '->' or '->->'"); + return "->->"; + } + } + + protected string ParseDivertArrow() + { + return ParseString ("->"); + } + + protected string ParseThreadArrow() + { + return ParseString ("<-"); + } + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Expressions.cs b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Expressions.cs new file mode 100644 index 0000000..106f895 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Expressions.cs @@ -0,0 +1,512 @@ +using System; +using Ink.Parsed; +using System.Collections.Generic; + +namespace Ink +{ + public partial class InkParser + { + protected class InfixOperator + { + public string type; + public int precedence; + public bool requireWhitespace; + + public InfixOperator(string type, int precedence, bool requireWhitespace) { + this.type = type; + this.precedence = precedence; + this.requireWhitespace = requireWhitespace; + } + + public override string ToString () + { + return type; + } + } + + protected Parsed.Object TempDeclarationOrAssignment() + { + Whitespace (); + + bool isNewDeclaration = ParseTempKeyword(); + + Whitespace (); + + Identifier varIdentifier = null; + if (isNewDeclaration) { + varIdentifier = (Identifier)Expect (IdentifierWithMetadata, "variable name"); + } else { + varIdentifier = Parse(IdentifierWithMetadata); + } + + if (varIdentifier == null) { + return null; + } + + Whitespace(); + + // += -= + bool isIncrement = ParseString ("+") != null; + bool isDecrement = ParseString ("-") != null; + if (isIncrement && isDecrement) Error ("Unexpected sequence '+-'"); + + if (ParseString ("=") == null) { + // Definitely in an assignment expression? + if (isNewDeclaration) Error ("Expected '='"); + return null; + } + + Expression assignedExpression = (Expression)Expect (Expression, "value expression to be assigned"); + + if (isIncrement || isDecrement) { + var result = new IncDecExpression (varIdentifier, assignedExpression, isIncrement); + return result; + } else { + var result = new VariableAssignment (varIdentifier, assignedExpression); + result.isNewTemporaryDeclaration = isNewDeclaration; + return result; + } + } + + protected void DisallowIncrement (Parsed.Object expr) + { + if (expr is Parsed.IncDecExpression) + Error ("Can't use increment/decrement here. It can only be used on a ~ line"); + } + + protected bool ParseTempKeyword() + { + var ruleId = BeginRule (); + + if (Parse (Identifier) == "temp") { + SucceedRule (ruleId); + return true; + } else { + FailRule (ruleId); + return false; + } + } + + protected Parsed.Return ReturnStatement() + { + Whitespace (); + + var returnOrDone = Parse(Identifier); + if (returnOrDone != "return") { + return null; + } + + Whitespace (); + + var expr = Parse(Expression); + + var returnObj = new Return (expr); + return returnObj; + } + + protected Expression Expression() { + return Expression(minimumPrecedence:0); + } + + // Pratt Parser + // aka "Top down operator precedence parser" + // http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/ + // Algorithm overview: + // The two types of precedence are handled in two different ways: + // ((((a . b) . c) . d) . e) #1 + // (a . (b . (c . (d . e)))) #2 + // Where #1 is automatically handled by successive loops within the main 'while' in this function, + // so long as continuing operators have lower (or equal) precedence (e.g. imagine some series of "*"s then "+" above. + // ...and #2 is handled by recursion of the right hand term in the binary expression parser. + // (see link for advice on how to extend for postfix and mixfix operators) + protected Expression Expression(int minimumPrecedence) + { + Whitespace (); + + // First parse a unary expression e.g. "-a" or parethensised "(1 + 2)" + var expr = ExpressionUnary (); + if (expr == null) { + return null; + } + + Whitespace (); + + // Attempt to parse (possibly multiple) continuing infix expressions (e.g. 1 + 2 + 3) + while(true) { + var ruleId = BeginRule (); + + // Operator + var infixOp = ParseInfixOperator (); + if (infixOp != null && infixOp.precedence > minimumPrecedence) { + + // Expect right hand side of operator + var expectationMessage = string.Format("right side of '{0}' expression", infixOp.type); + var multiaryExpr = Expect (() => ExpressionInfixRight (left: expr, op: infixOp), expectationMessage); + if (multiaryExpr == null) { + + // Fail for operator and right-hand side of multiary expression + FailRule (ruleId); + + return null; + } + + expr = SucceedRule(ruleId, multiaryExpr) as Parsed.Expression; + + continue; + } + + FailRule (ruleId); + break; + } + + Whitespace (); + + return expr; + } + + protected Expression ExpressionUnary() + { + // Divert target is a special case - it can't have any other operators + // applied to it, and we also want to check for it first so that we don't + // confuse "->" for subtraction. + var divertTarget = Parse (ExpressionDivertTarget); + if (divertTarget != null) { + return divertTarget; + } + + var prefixOp = (string) OneOf (String ("-"), String ("!")); + + // Don't parse like the string rules above, in case its actually + // a variable that simply starts with "not", e.g. "notable". + // This rule uses the Identifier rule, which will scan as much text + // as possible before returning. + if (prefixOp == null) { + prefixOp = Parse(ExpressionNot); + } + + Whitespace (); + + // - Since we allow numbers at the start of variable names, variable names are checked before literals + // - Function calls before variable names in case we see parentheses + var expr = OneOf (ExpressionList, ExpressionParen, ExpressionFunctionCall, ExpressionVariableName, ExpressionLiteral) as Expression; + + // Only recurse immediately if we have one of the (usually optional) unary ops + if (expr == null && prefixOp != null) { + expr = ExpressionUnary (); + } + + if (expr == null) + return null; + + if (prefixOp != null) { + expr = UnaryExpression.WithInner(expr, prefixOp); + } + + Whitespace (); + + var postfixOp = (string) OneOf (String ("++"), String ("--")); + if (postfixOp != null) { + bool isInc = postfixOp == "++"; + + if (!(expr is VariableReference)) { + Error ("can only increment and decrement variables, but saw '" + expr + "'"); + + // Drop down and succeed without the increment after reporting error + } else { + // TODO: Language Server - (Identifier combined into one vs. list of Identifiers) + var varRef = (VariableReference)expr; + expr = new IncDecExpression(varRef.identifier, isInc); + } + + } + + return expr; + } + + protected string ExpressionNot() + { + var id = Identifier (); + if (id == "not") { + return id; + } + + return null; + } + + protected Expression ExpressionLiteral() + { + return (Expression) OneOf (ExpressionFloat, ExpressionInt, ExpressionBool, ExpressionString); + } + + protected Expression ExpressionDivertTarget() + { + Whitespace (); + + var divert = Parse(SingleDivert); + if (divert == null) + return null; + + if (divert.isThread) + return null; + + Whitespace (); + + return new DivertTarget (divert); + } + + protected Number ExpressionInt() + { + int? intOrNull = ParseInt (); + if (intOrNull == null) { + return null; + } else { + return new Number (intOrNull.Value); + } + } + + protected Number ExpressionFloat() + { + float? floatOrNull = ParseFloat (); + if (floatOrNull == null) { + return null; + } else { + return new Number (floatOrNull.Value); + } + } + + protected StringExpression ExpressionString() + { + var openQuote = ParseString ("\""); + if (openQuote == null) + return null; + + // Set custom parser state flag so that within the text parser, + // it knows to treat the quote character (") as an end character + parsingStringExpression = true; + + List textAndLogic = Parse (MixedTextAndLogic); + + Expect (String ("\""), "close quote for string expression"); + + parsingStringExpression = false; + + if (textAndLogic == null) { + textAndLogic = new List (); + textAndLogic.Add (new Parsed.Text ("")); + } + + else if (textAndLogic.Exists (c => c is Divert)) + Error ("String expressions cannot contain diverts (->)"); + + return new StringExpression (textAndLogic); + } + + protected Number ExpressionBool() + { + var id = Parse(Identifier); + if (id == "true") { + return new Number (true); + } else if (id == "false") { + return new Number (false); + } + + return null; + } + + protected Expression ExpressionFunctionCall() + { + var iden = Parse(IdentifierWithMetadata); + if (iden == null) + return null; + + Whitespace (); + + var arguments = Parse(ExpressionFunctionCallArguments); + if (arguments == null) { + return null; + } + + return new FunctionCall(iden, arguments); + } + + protected List ExpressionFunctionCallArguments() + { + if (ParseString ("(") == null) + return null; + + // "Exclude" requires the rule to succeed, but causes actual comma string to be excluded from the list of results + ParseRule commas = Exclude (String (",")); + var arguments = Interleave(Expression, commas); + if (arguments == null) { + arguments = new List (); + } + + Whitespace (); + + Expect (String (")"), "closing ')' for function call"); + + return arguments; + } + + protected Expression ExpressionVariableName() + { + List path = Interleave (IdentifierWithMetadata, Exclude (Spaced (String (".")))); + + if (path == null || Story.IsReservedKeyword (path[0].name) ) + return null; + + return new VariableReference (path); + } + + protected Expression ExpressionParen() + { + if (ParseString ("(") == null) + return null; + + var innerExpr = Parse(Expression); + if (innerExpr == null) + return null; + + Whitespace (); + + Expect (String(")"), "closing parenthesis ')' for expression"); + + return innerExpr; + } + + protected Expression ExpressionInfixRight(Parsed.Expression left, InfixOperator op) + { + Whitespace (); + + var right = Parse(() => Expression (op.precedence)); + if (right) { + + // We assume that the character we use for the operator's type is the same + // as that used internally by e.g. Runtime.Expression.Add, Runtime.Expression.Multiply etc + var expr = new BinaryExpression (left, right, op.type); + return expr; + } + + return null; + + } + + private InfixOperator ParseInfixOperator() + { + foreach (var op in _binaryOperators) { + + int ruleId = BeginRule (); + + if (ParseString (op.type) != null) { + + if (op.requireWhitespace) { + if (Whitespace () == null) { + FailRule (ruleId); + continue; + } + } + + return (InfixOperator) SucceedRule(ruleId, op); + } + + FailRule (ruleId); + } + + return null; + } + + protected Parsed.List ExpressionList () + { + Whitespace (); + + if (ParseString ("(") == null) + return null; + + Whitespace (); + + // When list has: + // - 0 elements (null list) - this is okay, it's an empty list: "()" + // - 1 element - it could be confused for a single non-list related + // identifier expression in brackets, but this is a useless thing + // to do, so we reserve that syntax for a list with one item. + // - 2 or more elements - normal! + List memberNames = SeparatedList (ListMember, Spaced (String (","))); + + Whitespace (); + + // May have failed to parse the inner list - the parentheses may + // be for a normal expression + if (ParseString (")") == null) + return null; + + return new List (memberNames); + } + + protected Identifier ListMember () + { + Whitespace (); + + Identifier identifier = Parse (IdentifierWithMetadata); + if (identifier == null) + return null; + + var dot = ParseString ("."); + if (dot != null) { + Identifier identifier2 = Expect (IdentifierWithMetadata, "element name within the set " + identifier) as Identifier; + identifier.name = identifier.name + "." + identifier2?.name; + } + + Whitespace (); + + return identifier; + } + + void RegisterExpressionOperators() + { + _maxBinaryOpLength = 0; + _binaryOperators = new List (); + + // These will be tried in order, so we need "<=" before "<" + // for correctness + + RegisterBinaryOperator ("&&", precedence:1); + RegisterBinaryOperator ("||", precedence:1); + RegisterBinaryOperator ("and", precedence:1, requireWhitespace: true); + RegisterBinaryOperator ("or", precedence:1, requireWhitespace: true); + + RegisterBinaryOperator ("==", precedence:2); + RegisterBinaryOperator (">=", precedence:2); + RegisterBinaryOperator ("<=", precedence:2); + RegisterBinaryOperator ("<", precedence:2); + RegisterBinaryOperator (">", precedence:2); + RegisterBinaryOperator ("!=", precedence:2); + + // (apples, oranges) + cabbages has (oranges, cabbages) == true + RegisterBinaryOperator ("?", precedence: 3); + RegisterBinaryOperator ("has", precedence: 3, requireWhitespace:true); + RegisterBinaryOperator ("!?", precedence: 3); + RegisterBinaryOperator ("hasnt", precedence: 3, requireWhitespace: true); + RegisterBinaryOperator ("^", precedence: 3); + + RegisterBinaryOperator ("+", precedence:4); + RegisterBinaryOperator ("-", precedence:5); + RegisterBinaryOperator ("*", precedence:6); + RegisterBinaryOperator ("/", precedence:7); + + RegisterBinaryOperator ("%", precedence:8); + RegisterBinaryOperator ("mod", precedence:8, requireWhitespace:true); + + + } + + void RegisterBinaryOperator(string op, int precedence, bool requireWhitespace = false) + { + _binaryOperators.Add(new InfixOperator (op, precedence, requireWhitespace)); + _maxBinaryOpLength = Math.Max (_maxBinaryOpLength, op.Length); + } + + List _binaryOperators; + int _maxBinaryOpLength; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Include.cs b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Include.cs new file mode 100644 index 0000000..9490c2f --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Include.cs @@ -0,0 +1,76 @@ +using Ink.Parsed; +using System.Collections.Generic; +using System.IO; + + +namespace Ink +{ + public partial class InkParser + { + protected object IncludeStatement() + { + Whitespace (); + + if (ParseString ("INCLUDE") == null) + return null; + + Whitespace (); + + var filename = (string) Expect(() => ParseUntilCharactersFromString ("\n\r"), "filename for include statement"); + filename = filename.TrimEnd (' ', '\t'); + + // Working directory should already have been set up relative to the root ink file. + var fullFilename = _rootParser._fileHandler.ResolveInkFilename (filename); + + if (FilenameIsAlreadyOpen (fullFilename)) { + Error ("Recursive INCLUDE detected: '" + fullFilename + "' is already open."); + ParseUntilCharactersFromString("\r\n"); + return new IncludedFile(null); + } else { + AddOpenFilename (fullFilename); + } + + Parsed.Story includedStory = null; + string includedString = null; + try { + includedString = _rootParser._fileHandler.LoadInkFileContents(fullFilename); + } + catch { + Error ("Failed to load: '"+filename+"'"); + } + + + if (includedString != null ) { + InkParser parser = new InkParser(includedString, filename, _externalErrorHandler, _rootParser); + includedStory = parser.Parse(); + } + + RemoveOpenFilename (fullFilename); + + // Return valid IncludedFile object even if there were errors when parsing. + // We don't want to attempt to re-parse the include line as something else, + // and we want to include the bits that *are* valid, so we don't generate + // more errors than necessary. + return new IncludedFile (includedStory); + } + + bool FilenameIsAlreadyOpen(string fullFilename) + { + return _rootParser._openFilenames.Contains (fullFilename); + } + + void AddOpenFilename(string fullFilename) + { + _rootParser._openFilenames.Add (fullFilename); + } + + void RemoveOpenFilename(string fullFilename) + { + _rootParser._openFilenames.Remove (fullFilename); + } + + InkParser _rootParser; + HashSet _openFilenames; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Knot.cs b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Knot.cs new file mode 100644 index 0000000..d124243 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Knot.cs @@ -0,0 +1,239 @@ +using System.Collections.Generic; +using Ink.Parsed; +using System.Linq; + +namespace Ink +{ + public partial class InkParser + { + protected class NameWithMetadata { + public string name; + public Runtime.DebugMetadata metadata; + } + + protected class FlowDecl + { + public Identifier name; + public List arguments; + public bool isFunction; + } + + protected Knot KnotDefinition() + { + var knotDecl = Parse(KnotDeclaration); + if (knotDecl == null) + return null; + + Expect(EndOfLine, "end of line after knot name definition", recoveryRule: SkipToNextLine); + + ParseRule innerKnotStatements = () => StatementsAtLevel (StatementLevel.Knot); + + var content = Expect (innerKnotStatements, "at least one line within the knot", recoveryRule: KnotStitchNoContentRecoveryRule) as List; + + return new Knot (knotDecl.name, content, knotDecl.arguments, knotDecl.isFunction); + } + + protected FlowDecl KnotDeclaration() + { + Whitespace (); + + if (KnotTitleEquals () == null) + return null; + + Whitespace (); + + + Identifier identifier = Parse(IdentifierWithMetadata); + Identifier knotName; + + bool isFunc = identifier?.name == "function"; + if (isFunc) { + Expect (Whitespace, "whitespace after the 'function' keyword"); + knotName = Parse(IdentifierWithMetadata); + } else { + knotName = identifier; + } + + if (knotName == null) { + Error ("Expected the name of the " + (isFunc ? "function" : "knot")); + knotName = new Identifier { name = "" }; // prevent later null ref + } + + Whitespace (); + + List parameterNames = Parse (BracketedKnotDeclArguments); + + Whitespace (); + + // Optional equals after name + Parse(KnotTitleEquals); + + return new FlowDecl () { name = knotName, arguments = parameterNames, isFunction = isFunc }; + } + + protected string KnotTitleEquals() + { + // 2+ "=" starts a knot + var multiEquals = ParseCharactersFromString ("="); + if (multiEquals == null || multiEquals.Length <= 1) { + return null; + } else { + return multiEquals; + } + } + + protected object StitchDefinition() + { + var decl = Parse(StitchDeclaration); + if (decl == null) + return null; + + Expect(EndOfLine, "end of line after stitch name", recoveryRule: SkipToNextLine); + + ParseRule innerStitchStatements = () => StatementsAtLevel (StatementLevel.Stitch); + + var content = Expect(innerStitchStatements, "at least one line within the stitch", recoveryRule: KnotStitchNoContentRecoveryRule) as List; + + return new Stitch (decl.name, content, decl.arguments, decl.isFunction ); + } + + protected FlowDecl StitchDeclaration() + { + Whitespace (); + + // Single "=" to define a stitch + if (ParseString ("=") == null) + return null; + + // If there's more than one "=", that's actually a knot definition (or divert), so this rule should fail + if (ParseString ("=") != null) + return null; + + Whitespace (); + + // Stitches aren't allowed to be functions, but we parse it anyway and report the error later + bool isFunc = ParseString ("function") != null; + if ( isFunc ) { + Whitespace (); + } + + Identifier stitchName = Parse(IdentifierWithMetadata); + if (stitchName == null) + return null; + + Whitespace (); + + List flowArgs = Parse(BracketedKnotDeclArguments); + + Whitespace (); + + return new FlowDecl () { name = stitchName, arguments = flowArgs, isFunction = isFunc }; + } + + + protected object KnotStitchNoContentRecoveryRule() + { + // Jump ahead to the next knot or the end of the file + ParseUntil (KnotDeclaration, new CharacterSet ("="), null); + + var recoveredFlowContent = new List(); + recoveredFlowContent.Add( new Parsed.Text("" ) ); + return recoveredFlowContent; + } + + protected List BracketedKnotDeclArguments() + { + if (ParseString ("(") == null) + return null; + + var flowArguments = Interleave(Spaced(FlowDeclArgument), Exclude (String(","))); + + Expect (String (")"), "closing ')' for parameter list"); + + // If no parameters, create an empty list so that this method is type safe and + // doesn't attempt to return the ParseSuccess object + if (flowArguments == null) { + flowArguments = new List (); + } + + return flowArguments; + } + + protected FlowBase.Argument FlowDeclArgument() + { + // Possible forms: + // name + // -> name (variable divert target argument + // ref name + // ref -> name (variable divert target by reference) + var firstIden = Parse(IdentifierWithMetadata); + Whitespace (); + var divertArrow = ParseDivertArrow (); + Whitespace (); + var secondIden = Parse(IdentifierWithMetadata); + + if (firstIden == null && secondIden == null) + return null; + + + var flowArg = new FlowBase.Argument (); + if (divertArrow != null) { + flowArg.isDivertTarget = true; + } + + // Passing by reference + if (firstIden != null && firstIden.name == "ref") { + + if (secondIden == null) { + Error ("Expected an parameter name after 'ref'"); + } + + flowArg.identifier = secondIden; + flowArg.isByReference = true; + } + + // Simple argument name + else { + + if (flowArg.isDivertTarget) { + flowArg.identifier = secondIden; + } else { + flowArg.identifier = firstIden; + } + + if (flowArg.identifier == null) { + Error ("Expected an parameter name"); + } + + flowArg.isByReference = false; + } + + return flowArg; + } + + protected ExternalDeclaration ExternalDeclaration() + { + Whitespace (); + + Identifier external = Parse(IdentifierWithMetadata); + if (external == null || external.name != "EXTERNAL") + return null; + + Whitespace (); + + var funcIdentifier = Expect(IdentifierWithMetadata, "name of external function") as Identifier ?? new Identifier(); + + Whitespace (); + + var parameterNames = Expect (BracketedKnotDeclArguments, "declaration of arguments for EXTERNAL, even if empty, i.e. 'EXTERNAL "+funcIdentifier+"()'") as List; + if (parameterNames == null) + parameterNames = new List (); + + var argNames = parameterNames.Select (arg => arg.identifier?.name).ToList(); + + return new ExternalDeclaration (funcIdentifier, argNames); + } + + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Logic.cs b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Logic.cs new file mode 100644 index 0000000..df8b04f --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Logic.cs @@ -0,0 +1,442 @@ +using System.Collections.Generic; +using System.Linq; +using Ink.Parsed; + +namespace Ink +{ + public partial class InkParser + { + + protected Parsed.Object LogicLine() + { + Whitespace (); + + if (ParseString ("~") == null) { + return null; + } + + Whitespace (); + + // Some example lines we need to be able to distinguish between: + // ~ temp x = 5 -- var decl + assign + // ~ temp x -- var decl + // ~ x = 5 -- var assign + // ~ x -- expr (not var decl or assign) + // ~ f() -- expr + // We don't treat variable decl/assign as an expression since we don't want an assignment + // to have a return value, or to be used in compound expressions. + ParseRule afterTilda = () => OneOf (ReturnStatement, TempDeclarationOrAssignment, Expression); + + var result = Expect(afterTilda, "expression after '~'", recoveryRule: SkipToNextLine) as Parsed.Object; + + // Prevent further errors, already reported expected expression and have skipped to next line. + if (result == null) return new ContentList(); + + // Parse all expressions, but tell the writer off if they did something useless like: + // ~ 5 + 4 + // And even: + // ~ false && myFunction() + // ...since it's bad practice, and won't do what they expect if + // they're expecting C's lazy evaluation. + if (result is Expression && !(result is FunctionCall || result is IncDecExpression) ) { + + // TODO: Remove this specific error message when it has expired in usefulness + var varRef = result as VariableReference; + if (varRef && varRef.name == "include") { + Error ("'~ include' is no longer the correct syntax - please use 'INCLUDE your_filename.ink', without the tilda, and in block capitals."); + } + + else { + Error ("Logic following a '~' can't be that type of expression. It can only be something like:\n\t~ return\n\t~ var x = blah\n\t~ x++\n\t~ myFunction()"); + } + } + + // Line is pure function call? e.g. + // ~ f() + // Add extra pop to make sure we tidy up after ourselves. + // We no longer need anything on the evaluation stack. + var funCall = result as FunctionCall; + if (funCall) funCall.shouldPopReturnedValue = true; + + // If the expression contains a function call, then it could produce a text side effect, + // in which case it needs a newline on the end. e.g. + // ~ printMyName() + // ~ x = 1 + returnAValueAndAlsoPrintStuff() + // If no text gets printed, then the extra newline will have to be culled later. + // Multiple newlines on the output will be removed, so there will be no "leak" for + // long running calculations. It's disappointingly messy though :-/ + if (result.Find() != null ) { + result = new ContentList (result, new Parsed.Text ("\n")); + } + + Expect(EndOfLine, "end of line", recoveryRule: SkipToNextLine); + + return result as Parsed.Object; + } + + protected Parsed.Object VariableDeclaration() + { + Whitespace (); + + var id = Parse (Identifier); + if (id != "VAR") + return null; + + Whitespace (); + + var varName = Expect (IdentifierWithMetadata, "variable name") as Identifier; + + Whitespace (); + + Expect (String ("="), "the '=' for an assignment of a value, e.g. '= 5' (initial values are mandatory)"); + + Whitespace (); + + var definition = Expect (Expression, "initial value for "); + + var expr = definition as Parsed.Expression; + + if (expr) { + if (!(expr is Number || expr is StringExpression || expr is DivertTarget || expr is VariableReference || expr is List)) { + Error ("initial value for a variable must be a number, constant, list or divert target"); + } + + if (Parse (ListElementDefinitionSeparator) != null) + Error ("Unexpected ','. If you're trying to declare a new list, use the LIST keyword, not VAR"); + + // Ensure string expressions are simple + else if (expr is StringExpression) { + var strExpr = expr as StringExpression; + if (!strExpr.isSingleString) + Error ("Constant strings cannot contain any logic."); + } + + var result = new VariableAssignment (varName, expr); + result.isGlobalDeclaration = true; + return result; + } + + return null; + } + + protected Parsed.VariableAssignment ListDeclaration () + { + Whitespace (); + + var id = Parse (Identifier); + if (id != "LIST") + return null; + + Whitespace (); + + var varName = Expect (IdentifierWithMetadata, "list name") as Identifier; + + Whitespace (); + + Expect (String ("="), "the '=' for an assignment of the list definition"); + + Whitespace (); + + var definition = Expect (ListDefinition, "list item names") as ListDefinition; + + if (definition) { + + definition.identifier = varName; + + return new VariableAssignment (varName, definition); + } + + return null; + } + + protected Parsed.ListDefinition ListDefinition () + { + AnyWhitespace (); + + var allElements = SeparatedList (ListElementDefinition, ListElementDefinitionSeparator); + if (allElements == null) + return null; + + return new ListDefinition (allElements); + } + + protected string ListElementDefinitionSeparator () + { + AnyWhitespace (); + + if (ParseString (",") == null) return null; + + AnyWhitespace (); + + return ","; + } + + protected Parsed.ListElementDefinition ListElementDefinition () + { + var inInitialList = ParseString ("(") != null; + var needsToCloseParen = inInitialList; + + Whitespace (); + + var name = Parse (IdentifierWithMetadata); + if (name == null) + return null; + + Whitespace (); + + if (inInitialList) { + if (ParseString (")") != null) { + needsToCloseParen = false; + Whitespace (); + } + } + + int? elementValue = null; + if (ParseString ("=") != null) { + + Whitespace (); + + var elementValueNum = Expect (ExpressionInt, "value to be assigned to list item") as Number; + if (elementValueNum != null) { + elementValue = (int) elementValueNum.value; + } + + if (needsToCloseParen) { + Whitespace (); + + if (ParseString (")") != null) + needsToCloseParen = false; + } + } + + if (needsToCloseParen) + Error("Expected closing ')'"); + + return new ListElementDefinition (name, inInitialList, elementValue); + } + + protected Parsed.Object ConstDeclaration() + { + Whitespace (); + + var id = Parse (Identifier); + if (id != "CONST") + return null; + + Whitespace (); + + var varName = Expect (IdentifierWithMetadata, "constant name") as Identifier; + + Whitespace (); + + Expect (String ("="), "the '=' for an assignment of a value, e.g. '= 5' (initial values are mandatory)"); + + Whitespace (); + + var expr = Expect (Expression, "initial value for ") as Parsed.Expression; + if (!(expr is Number || expr is DivertTarget || expr is StringExpression)) { + Error ("initial value for a constant must be a number or divert target"); + } + + // Ensure string expressions are simple + else if (expr is StringExpression) { + var strExpr = expr as StringExpression; + if (!strExpr.isSingleString) + Error ("Constant strings cannot contain any logic."); + } + + + var result = new ConstantDeclaration (varName, expr); + return result; + } + + protected Parsed.Object InlineLogicOrGlueOrStartTag() + { + return (Parsed.Object) OneOf (InlineLogic, Glue, StartTag); + } + + protected Parsed.Glue Glue() + { + // Don't want to parse whitespace, since it might be important + // surrounding the glue. + var glueStr = ParseString("<>"); + if (glueStr != null) { + return new Parsed.Glue (new Runtime.Glue ()); + } else { + return null; + } + } + + protected Parsed.Object InlineLogic() + { + if ( ParseString ("{") == null) { + return null; + } + + var wasParsingString = parsingStringExpression; + var wasTagActive = tagActive; + + Whitespace (); + + var logic = (Parsed.Object) Expect(InnerLogic, "some kind of logic, conditional or sequence within braces: { ... }"); + if (logic == null) { + parsingStringExpression = wasParsingString; + return null; + } + + DisallowIncrement (logic); + + ContentList contentList = logic as ContentList; + if (!contentList) { + contentList = new ContentList (logic); + } + + Whitespace (); + + Expect (String("}"), "closing brace '}' for inline logic"); + + // Allow nested strings and logic + parsingStringExpression = wasParsingString; + + // Difference between: + // + // 1) A thing # {image}.jpg + // 2) A {red #red|blue #blue} sequence. + // + // When logic ends in (1) we still want tag to continue. + // When logic ends in (2) we want to auto-end the tag. + // Side note: we simply disallow tags within strings. + if( !wasTagActive ) EndTagIfNecessary(contentList); + + return contentList; + } + + protected Parsed.Object InnerLogic() + { + Whitespace (); + + // Explicitly try the combinations of inner logic + // that could potentially have conflicts first. + + // Explicit sequence annotation? + SequenceType? explicitSeqType = (SequenceType?) ParseObject(SequenceTypeAnnotation); + if (explicitSeqType != null) { + var contentLists = (List) Expect(InnerSequenceObjects, "sequence elements (for cycle/stoping etc)"); + if (contentLists == null) + return null; + return new Sequence (contentLists, (SequenceType) explicitSeqType); + } + + // Conditional with expression? + var initialQueryExpression = Parse(ConditionExpression); + if (initialQueryExpression) { + var conditional = (Conditional) Expect(() => InnerConditionalContent (initialQueryExpression), "conditional content following query"); + return conditional; + } + + // Now try to evaluate each of the "full" rules in turn + ParseRule[] rules = { + + // Conditional still necessary, since you can have a multi-line conditional + // without an initial query expression: + // { + // - true: this is true + // - false: this is false + // } + InnerConditionalContent, + InnerSequence, + InnerExpression, + }; + + bool wasTagActiveAtStartOfScope = tagActive; + + // Adapted from "OneOf" structuring rule except that in + // order for the rule to succeed, it has to maximally + // cover the entire string within the { }. Used to + // differentiate between: + // {myVar} -- Expression (try first) + // {my content is jolly} -- sequence with single element + foreach (ParseRule rule in rules) { + int ruleId = BeginRule (); + + Parsed.Object result = ParseObject(rule) as Parsed.Object; + if (result) { + + // Not yet at end? + if (Peek (Spaced (String ("}"))) == null) + FailRule (ruleId); + + // Full parse of content within braces + else { + return (Parsed.Object) SucceedRule (ruleId, result); + } + + } else { + FailRule (ruleId); + } + } + + return null; + } + + protected Parsed.Object InnerExpression() + { + var expr = Parse(Expression); + if (expr) { + expr.outputWhenComplete = true; + } + return expr; + } + + protected Identifier IdentifierWithMetadata() + { + var id = Identifier(); + if( id == null ) return null; + + // InkParser.RuleDidSucceed will add DebugMetadata + return new Identifier { name = id, debugMetadata = null }; + } + + // Note: we allow identifiers that start with a number, + // but not if they *only* comprise numbers + protected string Identifier() + { + // Parse remaining characters (if any) + var name = ParseCharactersFromCharSet (identifierCharSet); + if (name == null) + return null; + + // Reject if it's just a number + bool isNumberCharsOnly = true; + foreach (var c in name) { + if ( !(c >= '0' && c <= '9') ) { + isNumberCharsOnly = false; + break; + } + } + if (isNumberCharsOnly) { + return null; + } + + return name; + } + + CharacterSet identifierCharSet { + get { + if (_identifierCharSet == null) { + (_identifierCharSet = new CharacterSet ()) + .AddRange ('A', 'Z') + .AddRange ('a', 'z') + .AddRange ('0', '9') + .Add ('_'); + // Enable non-ASCII characters for story identifiers. + ExtendIdentifierCharacterRanges (_identifierCharSet); + } + return _identifierCharSet; + } + } + + private CharacterSet _identifierCharSet; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Sequences.cs b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Sequences.cs new file mode 100644 index 0000000..b9156e8 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Sequences.cs @@ -0,0 +1,231 @@ +using System.Collections.Generic; +using System.Linq; +using Ink.Parsed; + +namespace Ink +{ + public partial class InkParser + { + protected Sequence InnerSequence() + { + Whitespace (); + + // Default sequence type + SequenceType seqType = SequenceType.Stopping; + + // Optional explicit sequence type + SequenceType? parsedSeqType = (SequenceType?) Parse(SequenceTypeAnnotation); + if (parsedSeqType != null) + seqType = parsedSeqType.Value; + + var contentLists = Parse(InnerSequenceObjects); + if (contentLists == null || contentLists.Count <= 1) { + return null; + } + + return new Sequence (contentLists, seqType); + } + + protected object SequenceTypeAnnotation() + { + var annotation = (SequenceType?) Parse(SequenceTypeSymbolAnnotation); + + if(annotation == null) + annotation = (SequenceType?) Parse(SequenceTypeWordAnnotation); + + if (annotation == null) + return null; + + switch (annotation.Value) + { + case SequenceType.Once: + case SequenceType.Cycle: + case SequenceType.Stopping: + case SequenceType.Shuffle: + case (SequenceType.Shuffle | SequenceType.Stopping): + case (SequenceType.Shuffle | SequenceType.Once): + break; + + default: + Error("Sequence type combination not supported: " + annotation.Value); + return SequenceType.Stopping; + } + + return annotation; + } + + protected object SequenceTypeSymbolAnnotation() + { + if(_sequenceTypeSymbols == null ) + _sequenceTypeSymbols = new CharacterSet("!&~$ "); + + var sequenceType = (SequenceType)0; + var sequenceAnnotations = ParseCharactersFromCharSet(_sequenceTypeSymbols); + if (sequenceAnnotations == null) + return null; + + foreach(char symbolChar in sequenceAnnotations) { + switch(symbolChar) { + case '!': sequenceType |= SequenceType.Once; break; + case '&': sequenceType |= SequenceType.Cycle; break; + case '~': sequenceType |= SequenceType.Shuffle; break; + case '$': sequenceType |= SequenceType.Stopping; break; + } + } + + if (sequenceType == (SequenceType)0) + return null; + + return sequenceType; + } + + CharacterSet _sequenceTypeSymbols = new CharacterSet("!&~$"); + + protected object SequenceTypeWordAnnotation() + { + var sequenceTypes = Interleave(SequenceTypeSingleWord, Exclude(Whitespace)); + if (sequenceTypes == null || sequenceTypes.Count == 0) + return null; + + if (ParseString (":") == null) + return null; + + var combinedSequenceType = (SequenceType)0; + foreach(var seqType in sequenceTypes) { + combinedSequenceType |= seqType.Value; + } + + return combinedSequenceType; + } + + protected object SequenceTypeSingleWord() + { + SequenceType? seqType = null; + + var word = Parse(IdentifierWithMetadata); + if (word != null) + { + switch (word.name) + { + case "once": + seqType = SequenceType.Once; + break; + case "cycle": + seqType = SequenceType.Cycle; + break; + case "shuffle": + seqType = SequenceType.Shuffle; + break; + case "stopping": + seqType = SequenceType.Stopping; + break; + } + } + + if (seqType == null) + return null; + + return seqType; + } + + protected List InnerSequenceObjects() + { + var multiline = Parse(Newline) != null; + + List result = null; + if (multiline) { + result = Parse(InnerMultilineSequenceObjects); + } else { + result = Parse(InnerInlineSequenceObjects); + } + + return result; + } + + protected List InnerInlineSequenceObjects() + { + var interleavedContentAndPipes = Interleave (Optional (MixedTextAndLogic), String ("|"), flatten:false); + if (interleavedContentAndPipes == null) + return null; + + var result = new List (); + + // The content and pipes won't necessarily be perfectly interleaved in the sense that + // the content can be missing, but in that case it's intended that there's blank content. + bool justHadContent = false; + foreach (object contentOrPipe in interleavedContentAndPipes) { + + // Pipe/separator + if (contentOrPipe as string == "|") { + + // Expected content, saw pipe - need blank content now + if (!justHadContent) { + + // Add blank content + result.Add (new ContentList ()); + } + + justHadContent = false; + } + + // Real content + else { + + var content = contentOrPipe as List; + if (content == null) { + Error ("Expected content, but got " + contentOrPipe + " (this is an ink compiler bug!)"); + } else { + result.Add (new ContentList (content)); + } + + justHadContent = true; + } + } + + // Ended in a pipe? Need to insert final blank content + if (!justHadContent) + result.Add (new ContentList ()); + + return result; + } + + protected List InnerMultilineSequenceObjects() + { + MultilineWhitespace (); + + var contentLists = OneOrMore (SingleMultilineSequenceElement); + if (contentLists == null) + return null; + + return contentLists.Cast ().ToList(); + } + + protected ContentList SingleMultilineSequenceElement() + { + Whitespace (); + + // Make sure we're not accidentally parsing a divert + if (ParseString ("->") != null) + return null; + + if (ParseString ("-") == null) + return null; + + Whitespace (); + + + List content = StatementsAtLevel (StatementLevel.InnerBlock); + + if (content == null) + MultilineWhitespace (); + + // Add newline at the start of each branch + else { + content.Insert (0, new Parsed.Text ("\n")); + } + + return new ContentList (content); + } + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Statements.cs b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Statements.cs new file mode 100644 index 0000000..0b622f2 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Statements.cs @@ -0,0 +1,163 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Ink.Parsed; + +namespace Ink +{ + public partial class InkParser + { + protected enum StatementLevel + { + InnerBlock, + Stitch, + Knot, + Top + } + + protected List StatementsAtLevel(StatementLevel level) + { + // Check for error: Should not be allowed gather dashes within an inner block + if (level == StatementLevel.InnerBlock) { + object badGatherDashCount = Parse(GatherDashes); + if (badGatherDashCount != null) { + Error ("You can't use a gather (the dashes) within the { curly braces } context. For multi-line sequences and conditions, you should only use one dash."); + } + } + + return Interleave( + Optional (MultilineWhitespace), + () => StatementAtLevel (level), + untilTerminator: () => StatementsBreakForLevel(level)); + } + + protected object StatementAtLevel(StatementLevel level) + { + ParseRule[] rulesAtLevel = _statementRulesAtLevel[(int)level]; + + var statement = OneOf (rulesAtLevel); + + // For some statements, allow them to parse, but create errors, since + // writers may think they can use the statement, so it's useful to have + // the error message. + if (level == StatementLevel.Top) { + if( statement is Return ) + Error ("should not have return statement outside of a knot"); + } + + return statement; + } + + protected object StatementsBreakForLevel(StatementLevel level) + { + Whitespace (); + + ParseRule[] breakRules = _statementBreakRulesAtLevel[(int)level]; + + var breakRuleResult = OneOf (breakRules); + if (breakRuleResult == null) + return null; + + return breakRuleResult; + } + + void GenerateStatementLevelRules() + { + var levels = Enum.GetValues (typeof(StatementLevel)).Cast ().ToList(); + + _statementRulesAtLevel = new ParseRule[levels.Count][]; + _statementBreakRulesAtLevel = new ParseRule[levels.Count][]; + + foreach (var level in levels) { + List rulesAtLevel = new List (); + List breakingRules = new List (); + + // Diverts can go anywhere + rulesAtLevel.Add(Line(MultiDivert)); + + // Knots can only be parsed at Top/Global scope + if (level >= StatementLevel.Top) + rulesAtLevel.Add (KnotDefinition); + + rulesAtLevel.Add(Line(Choice)); + + rulesAtLevel.Add(Line(AuthorWarning)); + + // Gather lines would be confused with multi-line block separators, like + // within a multi-line if statement + if (level > StatementLevel.InnerBlock) { + rulesAtLevel.Add (Gather); + } + + // Stitches (and gathers) can (currently) only go in Knots and top level + if (level >= StatementLevel.Knot) { + rulesAtLevel.Add (StitchDefinition); + } + + // Global variable declarations can go anywhere + rulesAtLevel.Add(Line(ListDeclaration)); + rulesAtLevel.Add(Line(VariableDeclaration)); + rulesAtLevel.Add(Line(ConstDeclaration)); + rulesAtLevel.Add(Line(ExternalDeclaration)); + + // Global include can go anywhere + rulesAtLevel.Add(Line(IncludeStatement)); + + // Normal logic / text can go anywhere + rulesAtLevel.Add(LogicLine); + rulesAtLevel.Add(LineOfMixedTextAndLogic); + + // -------- + // Breaking rules + + // Break current knot with a new knot + if (level <= StatementLevel.Knot) { + breakingRules.Add (KnotDeclaration); + } + + // Break current stitch with a new stitch + if (level <= StatementLevel.Stitch) { + breakingRules.Add (StitchDeclaration); + } + + // Breaking an inner block (like a multi-line condition statement) + if (level <= StatementLevel.InnerBlock) { + breakingRules.Add (ParseDashNotArrow); + breakingRules.Add (String ("}")); + } + + _statementRulesAtLevel [(int)level] = rulesAtLevel.ToArray (); + _statementBreakRulesAtLevel [(int)level] = breakingRules.ToArray (); + } + } + + protected object SkipToNextLine() + { + ParseUntilCharactersFromString ("\n\r"); + ParseNewline (); + return ParseSuccess; + } + + // Modifier to turn a rule into one that expects a newline on the end. + // e.g. anywhere you can use "MixedTextAndLogic" as a rule, you can use + // "Line(MixedTextAndLogic)" to specify that it expects a newline afterwards. + protected ParseRule Line(ParseRule inlineRule) + { + return () => { + object result = ParseObject(inlineRule); + if (result == null) { + return null; + } + + Expect(EndOfLine, "end of line", recoveryRule: SkipToNextLine); + + return result; + }; + } + + + ParseRule[][] _statementRulesAtLevel; + ParseRule[][] _statementBreakRulesAtLevel; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Tags.cs b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Tags.cs new file mode 100644 index 0000000..4046b8b --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Tags.cs @@ -0,0 +1,63 @@ +using System.Text; +using System.Collections.Generic; +using System.Linq; + +namespace Ink +{ + public partial class InkParser + { + protected Parsed.Object StartTag () + { + Whitespace (); + + if (ParseString ("#") == null) + return null; + + if( parsingStringExpression ) { + Error("Tags aren't allowed inside of strings. Please use \\# if you want a hash symbol."); + // but allow us to continue anyway... + } + + var result = (Parsed.Object)null; + + // End previously active tag before starting new one + if( tagActive ) { + var contentList = new Parsed.ContentList(); + contentList.AddContent(new Parsed.Tag { isStart = false }); + contentList.AddContent(new Parsed.Tag { isStart = true }); + result = contentList; + } + + // Otherwise, just start a tag, no need for a content list + else { + result = new Parsed.Tag { isStart = true }; + } + + tagActive = true; + + Whitespace (); + + return result; + } + + protected void EndTagIfNecessary(List outputContentList) + { + if( tagActive ) { + if( outputContentList != null ) + outputContentList.Add(new Parsed.Tag { isStart = false }); + tagActive = false; + } + } + + protected void EndTagIfNecessary(Parsed.ContentList outputContentList) + { + if( tagActive ) { + if( outputContentList != null ) + outputContentList.AddContent(new Parsed.Tag { isStart = false }); + tagActive = false; + } + } + } + } + + diff --git a/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Whitespace.cs b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Whitespace.cs new file mode 100644 index 0000000..96031e7 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/InkParser/InkParser_Whitespace.cs @@ -0,0 +1,112 @@ +using System.Collections.Generic; + +namespace Ink +{ + public partial class InkParser + { + // Handles both newline and endOfFile + protected object EndOfLine() + { + return OneOf(Newline, EndOfFile); + } + + // Allow whitespace before the actual newline + protected object Newline() + { + Whitespace(); + + bool gotNewline = ParseNewline () != null; + + // Optional \r, definite \n to support Windows (\r\n) and Mac/Unix (\n) + + if( !gotNewline ) { + return null; + } else { + return ParseSuccess; + } + } + + protected object EndOfFile() + { + Whitespace(); + + if (!endOfInput) + return null; + + return ParseSuccess; + } + + + // General purpose space, returns N-count newlines (fails if no newlines) + protected object MultilineWhitespace() + { + List newlines = OneOrMore(Newline); + if (newlines == null) + return null; + + // Use content field of Token to say how many newlines there were + // (in most circumstances it's unimportant) + int numNewlines = newlines.Count; + if (numNewlines >= 1) { + return ParseSuccess; + } else { + return null; + } + } + + protected object Whitespace() + { + if( ParseCharactersFromCharSet(_inlineWhitespaceChars) != null ) { + return ParseSuccess; + } + + return null; + } + + protected ParseRule Spaced(ParseRule rule) + { + return () => { + + Whitespace (); + + var result = ParseObject(rule); + if (result == null) { + return null; + } + + Whitespace (); + + return result; + }; + } + + protected object AnyWhitespace () + { + bool anyWhitespace = false; + while (OneOf (Whitespace, MultilineWhitespace) != null) { + anyWhitespace = true; + } + return anyWhitespace ? ParseSuccess : null; + } + + protected ParseRule MultiSpaced (ParseRule rule) + { + return () => { + + AnyWhitespace (); + + var result = ParseObject (rule); + if (result == null) { + return null; + } + + AnyWhitespace (); + + return result; + }; + } + + private CharacterSet _inlineWhitespaceChars = new CharacterSet(" \t"); + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/InkStringConversionExtensions.cs b/Assets/Ink/InkLibs/InkCompiler/InkStringConversionExtensions.cs new file mode 100644 index 0000000..47f07b8 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/InkStringConversionExtensions.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; + +namespace Ink +{ + public static class InkStringConversionExtensions + { + public static string[] ToStringsArray(this List list) { + int count = list.Count; + var strings = new string[count]; + + for(int i = 0; i < count; i++) { + strings[i] = list[i].ToString(); + } + + return strings; + } + } +} diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/AuthorWarning.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/AuthorWarning.cs new file mode 100644 index 0000000..e61805b --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/AuthorWarning.cs @@ -0,0 +1,20 @@ + +namespace Ink.Parsed +{ + public class AuthorWarning : Parsed.Object + { + public string warningMessage; + + public AuthorWarning(string message) + { + warningMessage = message; + } + + public override Runtime.Object GenerateRuntimeObject () + { + Warning (warningMessage); + return null; + } + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Choice.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Choice.cs new file mode 100644 index 0000000..4b2934f --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Choice.cs @@ -0,0 +1,290 @@ +using System.Text; + +namespace Ink.Parsed +{ + public class Choice : Parsed.Object, IWeavePoint, INamedContent + { + public ContentList startContent { get; protected set; } + public ContentList choiceOnlyContent { get; protected set; } + public ContentList innerContent { get; protected set; } + + public string name + { + get { return identifier?.name; } + } + public Identifier identifier { get; set; } + + public Expression condition { + get { + return _condition; + } + set { + _condition = value; + if( _condition ) + AddContent (_condition); + } + } + + public bool onceOnly { get; set; } + public bool isInvisibleDefault { get; set; } + + public int indentationDepth { get; set; }// = 1; + public bool hasWeaveStyleInlineBrackets { get; set; } + + // Required for IWeavePoint interface + // Choice's target container. Used by weave to append any extra + // nested weave content into. + public Runtime.Container runtimeContainer { get { return _innerContentContainer; } } + + + public Runtime.Container innerContentContainer { + get { + return _innerContentContainer; + } + } + + public override Runtime.Container containerForCounting { + get { + return _innerContentContainer; + } + } + + // Override runtimePath to point to the Choice's target content (after it's chosen), + // as opposed to the default implementation which would point to the choice itself + // (or it's outer container), which is what runtimeObject is. + public override Runtime.Path runtimePath + { + get { + return _innerContentContainer.path; + } + } + + public Choice (ContentList startContent, ContentList choiceOnlyContent, ContentList innerContent) + { + this.startContent = startContent; + this.choiceOnlyContent = choiceOnlyContent; + this.innerContent = innerContent; + this.indentationDepth = 1; + + if (startContent) + AddContent (this.startContent); + + if (choiceOnlyContent) + AddContent (this.choiceOnlyContent); + + if( innerContent ) + AddContent (this.innerContent); + + this.onceOnly = true; // default + } + + + public override Runtime.Object GenerateRuntimeObject () + { + _outerContainer = new Runtime.Container (); + + // Content names for different types of choice: + // * start content [choice only content] inner content + // * start content -> divert + // * start content + // * [choice only content] + + // Hmm, this structure has become slightly insane! + // + // [ + // EvalStart + // assign $r = $r1 -- return target = return label 1 + // BeginString + // -> s + // [(r1)] -- return label 1 (after start content) + // EndString + // BeginString + // ... choice only content + // EndEval + // Condition expression + // choice: -> "c-0" + // (s) = [ + // start content + // -> r -- goto return label 1 or 2 + // ] + // ] + // + // in parent's container: (the inner content for the choice) + // + // (c-0) = [ + // EvalStart + // assign $r = $r2 -- return target = return label 2 + // EndEval + // -> s + // [(r2)] -- return label 1 (after start content) + // inner content + // ] + // + + _runtimeChoice = new Runtime.ChoicePoint (onceOnly); + _runtimeChoice.isInvisibleDefault = this.isInvisibleDefault; + + if (startContent || choiceOnlyContent || condition) { + _outerContainer.AddContent (Runtime.ControlCommand.EvalStart ()); + } + + // Start content is put into a named container that's referenced both + // when displaying the choice initially, and when generating the text + // when the choice is chosen. + if (startContent) { + + // Generate start content and return + // - We can't use a function since it uses a call stack element, which would + // put temporary values out of scope. Instead we manually divert around. + // - $r is a variable divert target contains the return point + _returnToR1 = new Runtime.DivertTargetValue (); + _outerContainer.AddContent (_returnToR1); + var varAssign = new Runtime.VariableAssignment ("$r", true); + _outerContainer.AddContent (varAssign); + + // Mark the start of the choice text generation, so that the runtime + // knows where to rewind to to extract the content from the output stream. + _outerContainer.AddContent (Runtime.ControlCommand.BeginString ()); + + _divertToStartContentOuter = new Runtime.Divert (); + _outerContainer.AddContent (_divertToStartContentOuter); + + // Start content itself in a named container + _startContentRuntimeContainer = startContent.GenerateRuntimeObject () as Runtime.Container; + _startContentRuntimeContainer.name = "s"; + + // Effectively, the "return" statement - return to the point specified by $r + var varDivert = new Runtime.Divert (); + varDivert.variableDivertName = "$r"; + _startContentRuntimeContainer.AddContent (varDivert); + + // Add the container + _outerContainer.AddToNamedContentOnly (_startContentRuntimeContainer); + + // This is the label to return to + _r1Label = new Runtime.Container (); + _r1Label.name = "$r1"; + _outerContainer.AddContent (_r1Label); + + _outerContainer.AddContent (Runtime.ControlCommand.EndString ()); + + _runtimeChoice.hasStartContent = true; + } + + // Choice only content - mark the start, then generate it directly into the outer container + if (choiceOnlyContent) { + _outerContainer.AddContent (Runtime.ControlCommand.BeginString ()); + + var choiceOnlyRuntimeContent = choiceOnlyContent.GenerateRuntimeObject () as Runtime.Container; + _outerContainer.AddContentsOfContainer (choiceOnlyRuntimeContent); + + _outerContainer.AddContent (Runtime.ControlCommand.EndString ()); + + _runtimeChoice.hasChoiceOnlyContent = true; + } + + // Generate any condition for this choice + if (condition) { + condition.GenerateIntoContainer (_outerContainer); + _runtimeChoice.hasCondition = true; + } + + if (startContent || choiceOnlyContent || condition) { + _outerContainer.AddContent (Runtime.ControlCommand.EvalEnd ()); + } + + // Add choice itself + _outerContainer.AddContent (_runtimeChoice); + + // Container that choice points to for when it's chosen + _innerContentContainer = new Runtime.Container (); + + // Repeat start content by diverting to its container + if (startContent) { + + // Set the return point when jumping back into the start content + // - In this case, it's the $r2 point, within the choice content "c". + _returnToR2 = new Runtime.DivertTargetValue (); + _innerContentContainer.AddContent (Runtime.ControlCommand.EvalStart ()); + _innerContentContainer.AddContent (_returnToR2); + _innerContentContainer.AddContent (Runtime.ControlCommand.EvalEnd ()); + var varAssign = new Runtime.VariableAssignment ("$r", true); + _innerContentContainer.AddContent (varAssign); + + // Main divert into start content + _divertToStartContentInner = new Runtime.Divert (); + _innerContentContainer.AddContent (_divertToStartContentInner); + + // Define label to return to + _r2Label = new Runtime.Container (); + _r2Label.name = "$r2"; + _innerContentContainer.AddContent (_r2Label); + } + + // Choice's own inner content + if (innerContent) { + var innerChoiceOnlyContent = innerContent.GenerateRuntimeObject () as Runtime.Container; + _innerContentContainer.AddContentsOfContainer (innerChoiceOnlyContent); + } + + if (this.story.countAllVisits) { + _innerContentContainer.visitsShouldBeCounted = true; + } + + _innerContentContainer.countingAtStartOnly = true; + + return _outerContainer; + } + + public override void ResolveReferences(Story context) + { + // Weave style choice - target own content container + if (_innerContentContainer) { + _runtimeChoice.pathOnChoice = _innerContentContainer.path; + + if (onceOnly) + _innerContentContainer.visitsShouldBeCounted = true; + } + + if (_returnToR1) + _returnToR1.targetPath = _r1Label.path; + + if (_returnToR2) + _returnToR2.targetPath = _r2Label.path; + + if( _divertToStartContentOuter ) + _divertToStartContentOuter.targetPath = _startContentRuntimeContainer.path; + + if( _divertToStartContentInner ) + _divertToStartContentInner.targetPath = _startContentRuntimeContainer.path; + + base.ResolveReferences (context); + + if( identifier != null && identifier.name.Length > 0 ) + context.CheckForNamingCollisions (this, identifier, Story.SymbolType.SubFlowAndWeave); + } + + public override string ToString () + { + if (choiceOnlyContent != null) { + return string.Format ("* {0}[{1}]...", startContent, choiceOnlyContent); + } else { + return string.Format ("* {0}...", startContent); + } + } + + Runtime.ChoicePoint _runtimeChoice; + Runtime.Container _innerContentContainer; + Runtime.Container _outerContainer; + Runtime.Container _startContentRuntimeContainer; + Runtime.Divert _divertToStartContentOuter; + Runtime.Divert _divertToStartContentInner; + Runtime.Container _r1Label; + Runtime.Container _r2Label; + Runtime.DivertTargetValue _returnToR1; + Runtime.DivertTargetValue _returnToR2; + Expression _condition; + } + +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Conditional.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Conditional.cs new file mode 100644 index 0000000..2343df2 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Conditional.cs @@ -0,0 +1,71 @@ +using System.Collections.Generic; +using System.Linq; +using Ink.Runtime; + +namespace Ink.Parsed +{ + public class Conditional : Parsed.Object + { + public Expression initialCondition { get; private set; } + public List branches { get; private set; } + + public Conditional (Expression condition, List branches) + { + this.initialCondition = condition; + if (this.initialCondition) { + AddContent (condition); + } + + this.branches = branches; + if (this.branches != null) { + AddContent (this.branches.Cast ().ToList ()); + } + + } + + public override Runtime.Object GenerateRuntimeObject () + { + var container = new Runtime.Container (); + + // Initial condition + if (this.initialCondition) { + container.AddContent (initialCondition.runtimeObject); + } + + // Individual branches + foreach (var branch in branches) { + var branchContainer = (Container) branch.runtimeObject; + container.AddContent (branchContainer); + } + + // If it's a switch-like conditional, each branch + // will have a "duplicate" operation for the original + // switched value. If there's no final else clause + // and we fall all the way through, we need to clean up. + // (An else clause doesn't dup but it *does* pop) + if (this.initialCondition != null && branches [0].ownExpression != null && !branches [branches.Count - 1].isElse) { + container.AddContent (Runtime.ControlCommand.PopEvaluatedValue ()); + } + + // Target for branches to rejoin to + _reJoinTarget = Runtime.ControlCommand.NoOp (); + container.AddContent (_reJoinTarget); + + return container; + } + + public override void ResolveReferences (Story context) + { + var pathToReJoin = _reJoinTarget.path; + + foreach (var branch in branches) { + branch.returnDivert.targetPath = pathToReJoin; + } + + base.ResolveReferences (context); + } + + Runtime.ControlCommand _reJoinTarget; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ConditionalSingleBranch.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ConditionalSingleBranch.cs new file mode 100644 index 0000000..3f66636 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ConditionalSingleBranch.cs @@ -0,0 +1,158 @@ + +using System.Collections.Generic; + +namespace Ink.Parsed +{ + public class ConditionalSingleBranch : Parsed.Object + { + // bool condition, e.g.: + // { 5 == 4: + // - the true branch + // - the false branch + // } + public bool isTrueBranch { get; set; } + + // When each branch has its own expression like a switch statement, + // this is non-null. e.g. + // { x: + // - 4: the value of x is four (ownExpression is the value 4) + // - 3: the value of x is three + // } + public Expression ownExpression { + get { + return _ownExpression; + } + set { + _ownExpression = value; + if (_ownExpression) { + AddContent (_ownExpression); + } + } + } + + // In the above example, match equality of x with 4 for the first branch. + // This is as opposed to simply evaluating boolean equality for each branch, + // example when shouldMatchEqualtity is FALSE: + // { + // 3 > 2: This will happen + // 2 > 3: This won't happen + // } + public bool matchingEquality { get; set; } + + public bool isElse { get; set; } + + public bool isInline { get; set; } + + public Runtime.Divert returnDivert { get; protected set; } + + public ConditionalSingleBranch (List content) + { + // Branches are allowed to be empty + if (content != null) { + _innerWeave = new Weave (content); + AddContent (_innerWeave); + } + } + + // Runtime content can be summarised as follows: + // - Evaluate an expression if necessary to branch on + // - Branch to a named container if true + // - Divert back to main flow + // (owner Conditional is in control of this target point) + public override Runtime.Object GenerateRuntimeObject () + { + // Check for common mistake, of putting "else:" instead of "- else:" + if (_innerWeave) { + foreach (var c in _innerWeave.content) { + var text = c as Parsed.Text; + if (text) { + // Don't need to trim at the start since the parser handles that already + if (text.text.StartsWith ("else:")) { + Warning ("Saw the text 'else:' which is being treated as content. Did you mean '- else:'?", text); + } + } + } + } + + var container = new Runtime.Container (); + + // Are we testing against a condition that's used for more than just this + // branch? If so, the first thing we need to do is replicate the value that's + // on the evaluation stack so that we don't fully consume it, in case other + // branches need to use it. + bool duplicatesStackValue = matchingEquality && !isElse; + if ( duplicatesStackValue ) + container.AddContent (Runtime.ControlCommand.Duplicate ()); + + _conditionalDivert = new Runtime.Divert (); + + // else clause is unconditional catch-all, otherwise the divert is conditional + _conditionalDivert.isConditional = !isElse; + + // Need extra evaluation? + if( !isTrueBranch && !isElse ) { + + bool needsEval = ownExpression != null; + if( needsEval ) + container.AddContent (Runtime.ControlCommand.EvalStart ()); + + if (ownExpression) + ownExpression.GenerateIntoContainer (container); + + // Uses existing duplicated value + if (matchingEquality) + container.AddContent (Runtime.NativeFunctionCall.CallWithName ("==")); + + if( needsEval ) + container.AddContent (Runtime.ControlCommand.EvalEnd ()); + } + + // Will pop from stack if conditional + container.AddContent (_conditionalDivert); + + _contentContainer = GenerateRuntimeForContent (); + _contentContainer.name = "b"; + + // Multi-line conditionals get a newline at the start of each branch + // (as opposed to the start of the multi-line conditional since the condition + // may evaluate to false.) + if (!isInline) { + _contentContainer.InsertContent (new Runtime.StringValue ("\n"), 0); + } + + if( duplicatesStackValue || (isElse && matchingEquality) ) + _contentContainer.InsertContent (Runtime.ControlCommand.PopEvaluatedValue (), 0); + + container.AddToNamedContentOnly (_contentContainer); + + returnDivert = new Runtime.Divert (); + _contentContainer.AddContent (returnDivert); + + return container; + } + + Runtime.Container GenerateRuntimeForContent() + { + // Empty branch - create empty container + if (_innerWeave == null) { + return new Runtime.Container (); + } + + return _innerWeave.rootContainer; + } + + public override void ResolveReferences (Story context) + { + _conditionalDivert.targetPath = _contentContainer.path; + + base.ResolveReferences (context); + } + + Runtime.Container _contentContainer; + Runtime.Divert _conditionalDivert; + Expression _ownExpression; + + Weave _innerWeave; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ConstantDeclaration.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ConstantDeclaration.cs new file mode 100644 index 0000000..3852bcd --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ConstantDeclaration.cs @@ -0,0 +1,46 @@ +//using System.Collections.Generic; + +namespace Ink.Parsed +{ + public class ConstantDeclaration : Parsed.Object + { + public string constantName + { + get { return constantIdentifier?.name; } + } + public Identifier constantIdentifier { get; protected set; } + public Expression expression { get; protected set; } + + public ConstantDeclaration (Identifier name, Expression assignedExpression) + { + this.constantIdentifier = name; + + // Defensive programming in case parsing of assignedExpression failed + if( assignedExpression ) + this.expression = AddContent(assignedExpression); + } + + public override Runtime.Object GenerateRuntimeObject () + { + // Global declarations don't generate actual procedural + // runtime objects, but instead add a global variable to the story itself. + // The story then initialises them all in one go at the start of the game. + return null; + } + + public override void ResolveReferences (Story context) + { + base.ResolveReferences (context); + + context.CheckForNamingCollisions (this, constantIdentifier, Story.SymbolType.Var); + } + + public override string typeName { + get { + return "Constant"; + } + } + + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ContentList.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ContentList.cs new file mode 100644 index 0000000..737875e --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ContentList.cs @@ -0,0 +1,78 @@ +using System.Collections.Generic; +using System.Text; + +namespace Ink.Parsed +{ + public class ContentList : Parsed.Object + { + public bool dontFlatten { get; set; } + + public Runtime.Container runtimeContainer { + get { + return (Runtime.Container) this.runtimeObject; + } + } + + public ContentList (List objects) + { + if( objects != null ) + AddContent (objects); + } + + public ContentList (params Parsed.Object[] objects) + { + if (objects != null) { + var objList = new List (objects); + AddContent (objList); + } + } + + public ContentList() + { + } + + public void TrimTrailingWhitespace() + { + for (int i = this.content.Count - 1; i >= 0; --i) { + var text = this.content [i] as Text; + if (text == null) + break; + + text.text = text.text.TrimEnd (' ', '\t'); + if (text.text.Length == 0) + this.content.RemoveAt (i); + else + break; + } + } + + public override Runtime.Object GenerateRuntimeObject () + { + var container = new Runtime.Container (); + if (content != null) { + foreach (var obj in content) { + var contentObjRuntime = obj.runtimeObject; + + // Some objects (e.g. author warnings) don't generate runtime objects + if( contentObjRuntime ) + container.AddContent (contentObjRuntime); + } + } + + if( dontFlatten ) + story.DontFlattenContainer (container); + + return container; + } + + public override string ToString () + { + var sb = new StringBuilder (); + sb.Append ("ContentList("); + sb.Append(string.Join (", ", content.ToStringsArray())); + sb.Append (")"); + return sb.ToString (); + } + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Divert.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Divert.cs new file mode 100644 index 0000000..f87ce8d --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Divert.cs @@ -0,0 +1,403 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Ink.Parsed +{ + public class Divert : Parsed.Object + { + public Parsed.Path target { get; protected set; } + public Parsed.Object targetContent { get; protected set; } + public List arguments { get; protected set; } + public Runtime.Divert runtimeDivert { get; protected set; } + public bool isFunctionCall { get; set; } + public bool isEmpty { get; set; } + public bool isTunnel { get; set; } + public bool isThread { get; set; } + public bool isEnd { + get { + return target != null && target.dotSeparatedComponents == "END"; + } + } + public bool isDone { + get { + return target != null && target.dotSeparatedComponents == "DONE"; + } + } + + public Divert (Parsed.Path target, List arguments = null) + { + this.target = target; + this.arguments = arguments; + + if (arguments != null) { + AddContent (arguments.Cast ().ToList ()); + } + } + + public Divert (Parsed.Object targetContent) + { + this.targetContent = targetContent; + } + + public override Runtime.Object GenerateRuntimeObject () + { + // End = end flow immediately + // Done = return from thread or instruct the flow that it's safe to exit + if (isEnd) { + return Runtime.ControlCommand.End (); + } + if (isDone) { + return Runtime.ControlCommand.Done (); + } + + runtimeDivert = new Runtime.Divert (); + + // Normally we resolve the target content during the + // Resolve phase, since we expect all runtime objects to + // be available in order to find the final runtime path for + // the destination. However, we need to resolve the target + // (albeit without the runtime target) early so that + // we can get information about the arguments - whether + // they're by reference - since it affects the code we + // generate here. + ResolveTargetContent (); + + + CheckArgumentValidity (); + + // Passing arguments to the knot + bool requiresArgCodeGen = arguments != null && arguments.Count > 0; + if ( requiresArgCodeGen || isFunctionCall || isTunnel || isThread ) { + + var container = new Runtime.Container (); + + // Generate code for argument evaluation + // This argument generation is coded defensively - it should + // attempt to generate the code for all the parameters, even if + // they don't match the expected arguments. This is so that the + // parameter objects themselves are generated correctly and don't + // get into a state of attempting to resolve references etc + // without being generated. + if (requiresArgCodeGen) { + + // Function calls already in an evaluation context + if (!isFunctionCall) { + container.AddContent (Runtime.ControlCommand.EvalStart()); + } + + List targetArguments = null; + if( targetContent ) + targetArguments = (targetContent as FlowBase).arguments; + + for (var i = 0; i < arguments.Count; ++i) { + Expression argToPass = arguments [i]; + FlowBase.Argument argExpected = null; + if( targetArguments != null && i < targetArguments.Count ) + argExpected = targetArguments [i]; + + // Pass by reference: argument needs to be a variable reference + if (argExpected != null && argExpected.isByReference) { + + var varRef = argToPass as VariableReference; + if (varRef == null) { + Error ("Expected variable name to pass by reference to 'ref " + argExpected.identifier + "' but saw " + argToPass.ToString ()); + break; + } + + // Check that we're not attempting to pass a read count by reference + var targetPath = new Path(varRef.pathIdentifiers); + Parsed.Object targetForCount = targetPath.ResolveFromContext (this); + if (targetForCount != null) { + Error ("can't pass a read count by reference. '" + targetPath.dotSeparatedComponents+"' is a knot/stitch/label, but '"+target.dotSeparatedComponents+"' requires the name of a VAR to be passed."); + break; + } + + var varPointer = new Runtime.VariablePointerValue (varRef.name); + container.AddContent (varPointer); + } + + // Normal value being passed: evaluate it as normal + else { + argToPass.GenerateIntoContainer (container); + } + } + + // Function calls were already in an evaluation context + if (!isFunctionCall) { + container.AddContent (Runtime.ControlCommand.EvalEnd()); + } + } + + + // Starting a thread? A bit like a push to the call stack below... but not. + // It sort of puts the call stack on a thread stack (argh!) - forks the full flow. + if (isThread) { + container.AddContent(Runtime.ControlCommand.StartThread()); + } + + // If this divert is a function call, tunnel, we push to the call stack + // so we can return again + else if (isFunctionCall || isTunnel) { + runtimeDivert.pushesToStack = true; + runtimeDivert.stackPushType = isFunctionCall ? Runtime.PushPopType.Function : Runtime.PushPopType.Tunnel; + } + + // Jump into the "function" (knot/stitch) + container.AddContent (runtimeDivert); + + return container; + } + + // Simple divert + else { + return runtimeDivert; + } + } + + + // When the divert is to a target that's actually a variable name + // rather than an explicit knot/stitch name, try interpretting it + // as such by getting the variable name. + public string PathAsVariableName() + { + return target.firstComponent; + } + + + void ResolveTargetContent() + { + if (isEmpty || isEnd) { + return; + } + + if (targetContent == null) { + + // Is target of this divert a variable name that will be de-referenced + // at runtime? If so, there won't be any further reference resolution + // we can do at this point. + var variableTargetName = PathAsVariableName (); + if (variableTargetName != null) { + var flowBaseScope = ClosestFlowBase (); + var resolveResult = flowBaseScope.ResolveVariableWithName (variableTargetName, fromNode: this); + if (resolveResult.found) { + + // Make sure that the flow was typed correctly, given that we know that this + // is meant to be a divert target + if (resolveResult.isArgument) { + var argument = resolveResult.ownerFlow.arguments.Where (a => a.identifier.name == variableTargetName).First(); + if ( !argument.isDivertTarget ) { + Error ("Since '" + argument.identifier + "' is used as a variable divert target (on "+this.debugMetadata+"), it should be marked as: -> " + argument.identifier, resolveResult.ownerFlow); + } + } + + runtimeDivert.variableDivertName = variableTargetName; + return; + + } + } + + targetContent = target.ResolveFromContext (this); + } + } + + public override void ResolveReferences(Story context) + { + if (isEmpty || isEnd || isDone) { + return; + } + + if (targetContent) { + runtimeDivert.targetPath = targetContent.runtimePath; + } + + // Resolve children (the arguments) + base.ResolveReferences (context); + + // May be null if it's a built in function (e.g. TURNS_SINCE) + // or if it's a variable target. + var targetFlow = targetContent as FlowBase; + if (targetFlow) { + if (!targetFlow.isFunction && this.isFunctionCall) { + base.Error (targetFlow.identifier + " hasn't been marked as a function, but it's being called as one. Do you need to delcare the knot as '== function " + targetFlow.identifier + " =='?"); + } else if (targetFlow.isFunction && !this.isFunctionCall && !(this.parent is DivertTarget)) { + base.Error (targetFlow.identifier + " can't be diverted to. It can only be called as a function since it's been marked as such: '" + targetFlow.identifier + "(...)'"); + } + } + + // Check validity of target content + bool targetWasFound = targetContent != null; + bool isBuiltIn = false; + bool isExternal = false; + + if (target.numberOfComponents == 1 ) { + + // BuiltIn means TURNS_SINCE, CHOICE_COUNT, RANDOM or SEED_RANDOM + isBuiltIn = FunctionCall.IsBuiltIn (target.firstComponent); + + // Client-bound function? + isExternal = context.IsExternal (target.firstComponent); + + if (isBuiltIn || isExternal) { + if (!isFunctionCall) { + base.Error (target.firstComponent + " must be called as a function: ~ " + target.firstComponent + "()"); + } + if (isExternal) { + runtimeDivert.isExternal = true; + if( arguments != null ) + runtimeDivert.externalArgs = arguments.Count; + runtimeDivert.pushesToStack = false; + runtimeDivert.targetPath = new Runtime.Path (this.target.firstComponent); + CheckExternalArgumentValidity (context); + } + return; + } + } + + // Variable target? + if (runtimeDivert.variableDivertName != null) { + return; + } + + if( !targetWasFound && !isBuiltIn && !isExternal ) + Error ("target not found: '" + target + "'"); + } + + // Returns false if there's an error + void CheckArgumentValidity() + { + if (isEmpty) + return; + + // Argument passing: Check for errors in number of arguments + var numArgs = 0; + if (arguments != null && arguments.Count > 0) + numArgs = arguments.Count; + + // Missing content? + // Can't check arguments properly. It'll be due to some + // other error though, so although there's a problem and + // we report false, we don't need to report a specific error. + // It may also be because it's a valid call to an external + // function, that we check at the resolve stage. + if (targetContent == null) { + return; + } + + FlowBase targetFlow = targetContent as FlowBase; + + // No error, crikey! + if (numArgs == 0 && (targetFlow == null || !targetFlow.hasParameters)) { + return; + } + + if (targetFlow == null && numArgs > 0) { + Error ("target needs to be a knot or stitch in order to pass arguments"); + return; + } + + if (targetFlow.arguments == null && numArgs > 0) { + Error ("target (" + targetFlow.name + ") doesn't take parameters"); + return; + } + + if( this.parent is DivertTarget ) { + if (numArgs > 0) + Error ("can't store arguments in a divert target variable"); + return; + } + + var paramCount = targetFlow.arguments.Count; + if (paramCount != numArgs) { + + string butClause; + if (numArgs == 0) { + butClause = "but there weren't any passed to it"; + } else if (numArgs < paramCount) { + butClause = "but only got " + numArgs; + } else { + butClause = "but got " + numArgs; + } + Error ("to '" + targetFlow.identifier + "' requires " + paramCount + " arguments, "+butClause); + return; + } + + // Light type-checking for divert target arguments + for (int i = 0; i < paramCount; ++i) { + FlowBase.Argument flowArg = targetFlow.arguments [i]; + Parsed.Expression divArgExpr = arguments [i]; + + // Expecting a divert target as an argument, let's do some basic type checking + if (flowArg.isDivertTarget) { + + // Not passing a divert target or any kind of variable reference? + var varRef = divArgExpr as VariableReference; + if (!(divArgExpr is DivertTarget) && varRef == null ) { + Error ("Target '" + targetFlow.identifier + "' expects a divert target for the parameter named -> " + flowArg.identifier + " but saw " + divArgExpr, divArgExpr); + } + + // Passing 'a' instead of '-> a'? + // i.e. read count instead of divert target + else if (varRef != null) { + + // Unfortunately have to manually resolve here since we're still in code gen + var knotCountPath = new Path(varRef.pathIdentifiers); + Parsed.Object targetForCount = knotCountPath.ResolveFromContext (varRef); + if (targetForCount != null) { + Error ("Passing read count of '" + knotCountPath.dotSeparatedComponents + "' instead of a divert target. You probably meant '" + knotCountPath + "'"); + } + } + } + } + + if (targetFlow == null) { + Error ("Can't call as a function or with arguments unless it's a knot or stitch"); + return; + } + + return; + } + + void CheckExternalArgumentValidity(Story context) + { + string externalName = target.firstComponent; + ExternalDeclaration external = null; + var found = context.externals.TryGetValue(externalName, out external); + System.Diagnostics.Debug.Assert (found, "external not found"); + + int externalArgCount = external.argumentNames.Count; + int ownArgCount = 0; + if (arguments != null) { + ownArgCount = arguments.Count; + } + + if (ownArgCount != externalArgCount) { + Error ("incorrect number of arguments sent to external function '" + externalName + "'. Expected " + externalArgCount + " but got " + ownArgCount); + } + } + + public override void Error (string message, Object source = null, bool isWarning = false) + { + // Could be getting an error from a nested Divert + if (source != this && source) { + base.Error (message, source); + return; + } + + if (isFunctionCall) { + base.Error ("Function call " + message, source, isWarning); + } else { + base.Error ("Divert " + message, source, isWarning); + } + } + + public override string ToString () + { + if (target != null) + return target.ToString (); + else + return "-> "; + } + + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/DivertTarget.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/DivertTarget.cs new file mode 100644 index 0000000..c1223a4 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/DivertTarget.cs @@ -0,0 +1,172 @@ + +namespace Ink.Parsed +{ + public class DivertTarget : Expression + { + public Divert divert; + + public DivertTarget (Divert divert) + { + this.divert = AddContent(divert); + } + + public override void GenerateIntoContainer (Runtime.Container container) + { + divert.GenerateRuntimeObject(); + + _runtimeDivert = (Runtime.Divert) divert.runtimeDivert; + _runtimeDivertTargetValue = new Runtime.DivertTargetValue (); + + container.AddContent (_runtimeDivertTargetValue); + } + + public override void ResolveReferences (Story context) + { + base.ResolveReferences (context); + + if( divert.isDone || divert.isEnd ) + { + Error("Can't Can't use -> DONE or -> END as variable divert targets", this); + return; + } + + Parsed.Object usageContext = this; + while (usageContext && usageContext is Expression) { + + bool badUsage = false; + bool foundUsage = false; + + var usageParent = usageContext.parent; + if (usageParent is BinaryExpression) { + + // Only allowed to compare for equality + + var binaryExprParent = usageParent as BinaryExpression; + if (binaryExprParent.opName != "==" && binaryExprParent.opName != "!=") { + badUsage = true; + } else { + if (!(binaryExprParent.leftExpression is DivertTarget || binaryExprParent.leftExpression is VariableReference)) { + badUsage = true; + } + if (!(binaryExprParent.rightExpression is DivertTarget || binaryExprParent.rightExpression is VariableReference)) { + badUsage = true; + } + } + foundUsage = true; + } + else if( usageParent is FunctionCall ) { + var funcCall = usageParent as FunctionCall; + if( !funcCall.isTurnsSince && !funcCall.isReadCount ) { + badUsage = true; + } + foundUsage = true; + } + else if (usageParent is Expression) { + badUsage = true; + foundUsage = true; + } + else if (usageParent is MultipleConditionExpression) { + badUsage = true; + foundUsage = true; + } else if (usageParent is Choice && ((Choice)usageParent).condition == usageContext) { + badUsage = true; + foundUsage = true; + } else if (usageParent is Conditional || usageParent is ConditionalSingleBranch) { + badUsage = true; + foundUsage = true; + } + + if (badUsage) { + Error ("Can't use a divert target like that. Did you intend to call '" + divert.target + "' as a function: likeThis(), or check the read count: likeThis, with no arrows?", this); + } + + if (foundUsage) + break; + + usageContext = usageParent; + } + + // Example ink for this case: + // + // VAR x = -> blah + // + // ...which means that "blah" is expected to be a literal stitch target rather + // than a variable name. We can't really intelligently recover from this (e.g. if blah happens to + // contain a divert target itself) since really we should be generating a variable reference + // rather than a concrete DivertTarget, so we list it as an error. + if (_runtimeDivert.hasVariableTarget) + Error ("Since '"+divert.target.dotSeparatedComponents+"' is a variable, it shouldn't be preceded by '->' here."); + + // Main resolve + _runtimeDivertTargetValue.targetPath = _runtimeDivert.targetPath; + + // Tell hard coded (yet variable) divert targets that they also need to be counted + // TODO: Only detect DivertTargets that are values rather than being used directly for + // read or turn counts. Should be able to detect this by looking for other uses of containerForCounting + var targetContent = this.divert.targetContent; + if (targetContent != null ) { + var target = targetContent.containerForCounting; + if (target != null) + { + // Purpose is known: used directly in TURNS_SINCE(-> divTarg) + var parentFunc = this.parent as FunctionCall; + if( parentFunc && parentFunc.isTurnsSince ) { + target.turnIndexShouldBeCounted = true; + } + + // Unknown purpose, count everything + else { + target.visitsShouldBeCounted = true; + target.turnIndexShouldBeCounted = true; + } + + } + + // Unfortunately not possible: + // https://github.com/inkle/ink/issues/538 + // + // VAR func = -> double + // + // === function double(ref x) + // ~ x = x * 2 + // + // Because when generating the parameters for a function + // to be called, it needs to know ahead of time when + // compiling whether to pass a variable reference or value. + // + var targetFlow = (targetContent as FlowBase); + if (targetFlow != null && targetFlow.arguments != null) + { + foreach(var arg in targetFlow.arguments) { + if(arg.isByReference) + { + Error("Can't store a divert target to a knot or function that has by-reference arguments ('"+targetFlow.identifier+"' has 'ref "+arg.identifier+"')."); + } + } + } + } + } + + // Equals override necessary in order to check for CONST multiple definition equality + public override bool Equals (object obj) + { + var otherDivTarget = obj as DivertTarget; + if (otherDivTarget == null) return false; + + var targetStr = this.divert.target.dotSeparatedComponents; + var otherTargetStr = otherDivTarget.divert.target.dotSeparatedComponents; + + return targetStr.Equals (otherTargetStr); + } + + public override int GetHashCode () + { + var targetStr = this.divert.target.dotSeparatedComponents; + return targetStr.GetHashCode (); + } + + Runtime.DivertTargetValue _runtimeDivertTargetValue; + Runtime.Divert _runtimeDivert; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Expression.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Expression.cs new file mode 100644 index 0000000..ad75202 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Expression.cs @@ -0,0 +1,307 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Ink.Parsed +{ + public abstract class Expression : Parsed.Object + { + public bool outputWhenComplete { get; set; } + + public override Runtime.Object GenerateRuntimeObject () + { + var container = new Runtime.Container (); + + // Tell Runtime to start evaluating the following content as an expression + container.AddContent (Runtime.ControlCommand.EvalStart()); + + GenerateIntoContainer (container); + + // Tell Runtime to output the result of the expression evaluation to the output stream + if (outputWhenComplete) { + container.AddContent (Runtime.ControlCommand.EvalOutput()); + } + + // Tell Runtime to stop evaluating the content as an expression + container.AddContent (Runtime.ControlCommand.EvalEnd()); + + return container; + } + + // When generating the value of a constant expression, + // we can't just keep generating the same constant expression into + // different places where the constant value is referenced, since then + // the same runtime objects would be used in multiple places, which + // is impossible since each runtime object should have one parent. + // Instead, we generate a prototype of the runtime object(s), then + // copy them each time they're used. + public void GenerateConstantIntoContainer(Runtime.Container container) + { + if( _prototypeRuntimeConstantExpression == null ) { + _prototypeRuntimeConstantExpression = new Runtime.Container (); + GenerateIntoContainer (_prototypeRuntimeConstantExpression); + } + + foreach (var runtimeObj in _prototypeRuntimeConstantExpression.content) { + container.AddContent (runtimeObj.Copy()); + } + } + + public abstract void GenerateIntoContainer (Runtime.Container container); + + Runtime.Container _prototypeRuntimeConstantExpression; + } + + public class BinaryExpression : Expression + { + public Expression leftExpression; + public Expression rightExpression; + public string opName; + + public BinaryExpression(Expression left, Expression right, string opName) + { + leftExpression = AddContent(left); + rightExpression = AddContent(right); + this.opName = opName; + } + + public override void GenerateIntoContainer(Runtime.Container container) + { + leftExpression.GenerateIntoContainer (container); + rightExpression.GenerateIntoContainer (container); + + opName = NativeNameForOp (opName); + + container.AddContent(Runtime.NativeFunctionCall.CallWithName(opName)); + } + + public override void ResolveReferences (Story context) + { + base.ResolveReferences (context); + + // Check for the following case: + // + // (not A) ? B + // + // Since this easy to accidentally do: + // + // not A ? B + // + // when you intend: + // + // not (A ? B) + if (NativeNameForOp (opName) == "?") { + var leftUnary = leftExpression as UnaryExpression; + if( leftUnary != null && (leftUnary.op == "not" || leftUnary.op == "!") ) { + Error ("Using 'not' or '!' here negates '"+leftUnary.innerExpression+"' rather than the result of the '?' or 'has' operator. You need to add parentheses around the (A ? B) expression."); + } + } + } + + string NativeNameForOp(string opName) + { + if (opName == "and") + return "&&"; + + if (opName == "or") + return "||"; + + if (opName == "mod") + return "%"; + + if (opName == "has") + return "?"; + + if (opName == "hasnt") + return "!?"; + + return opName; + } + + public override string ToString () + { + return string.Format ("({0} {1} {2})", leftExpression, opName, rightExpression); + } + } + + public class UnaryExpression : Expression + { + public Expression innerExpression; + public string op; + + // Attempt to flatten inner expression immediately + // e.g. convert (-(5)) into (-5) + public static Expression WithInner(Expression inner, string op) { + + var innerNumber = inner as Number; + if( innerNumber ) { + + if( op == "-" ) { + if( innerNumber.value is int ) { + return new Number( -((int)innerNumber.value) ); + } else if( innerNumber.value is float ) { + return new Number( -((float)innerNumber.value) ); + } + } + + else if( op == "!" || op == "not" ) { + if( innerNumber.value is int ) { + return new Number( (int)innerNumber.value == 0 ); + } else if( innerNumber.value is float ) { + return new Number( (float)innerNumber.value == 0.0f ); + } else if( innerNumber.value is bool ) { + return new Number( !(bool)innerNumber.value ); + } + } + + throw new System.Exception ("Unexpected operation or number type"); + } + + // Normal fallback + var unary = new UnaryExpression (inner, op); + return unary; + } + + public UnaryExpression(Expression inner, string op) + { + this.innerExpression = AddContent(inner); + this.op = op; + } + + public override void GenerateIntoContainer(Runtime.Container container) + { + innerExpression.GenerateIntoContainer (container); + + container.AddContent(Runtime.NativeFunctionCall.CallWithName(nativeNameForOp)); + } + + public override string ToString () + { + return nativeNameForOp + innerExpression; + } + + string nativeNameForOp + { + get { + // Replace "-" with "_" to make it unique (compared to subtraction) + if (op == "-") + return "_"; + if (op == "not") + return "!"; + return op; + } + } + } + + public class IncDecExpression : Expression + { + public Identifier varIdentifier; + public bool isInc; + public Expression expression; + + public IncDecExpression(Identifier varIdentifier, bool isInc) + { + this.varIdentifier = varIdentifier; + this.isInc = isInc; + } + + public IncDecExpression (Identifier varIdentifier, Expression expression, bool isInc) : this(varIdentifier, isInc) + { + this.expression = expression; + AddContent (expression); + } + + public override void GenerateIntoContainer(Runtime.Container container) + { + // x = x + y + // ^^^ ^ ^ ^ + // 4 1 3 2 + // Reverse polish notation: (x 1 +) (assign to x) + + // 1. + container.AddContent (new Runtime.VariableReference (varIdentifier?.name)); + + // 2. + // - Expression used in the form ~ x += y + // - Simple version: ~ x++ + if (expression) + expression.GenerateIntoContainer (container); + else + container.AddContent (new Runtime.IntValue (1)); + + // 3. + container.AddContent (Runtime.NativeFunctionCall.CallWithName (isInc ? "+" : "-")); + + // 4. + _runtimeAssignment = new Runtime.VariableAssignment(varIdentifier?.name, false); + container.AddContent (_runtimeAssignment); + } + + public override void ResolveReferences (Story context) + { + base.ResolveReferences (context); + + var varResolveResult = context.ResolveVariableWithName(varIdentifier?.name, fromNode: this); + if (!varResolveResult.found) { + Error ("variable for "+incrementDecrementWord+" could not be found: '"+varIdentifier+"' after searching: "+this.descriptionOfScope); + } + + _runtimeAssignment.isGlobal = varResolveResult.isGlobal; + + if (!(parent is Weave) && !(parent is FlowBase) && !(parent is ContentList)) { + Error ("Can't use " + incrementDecrementWord + " as sub-expression"); + } + } + + string incrementDecrementWord { + get { + if (isInc) + return "increment"; + else + return "decrement"; + } + } + + public override string ToString () + { + if (expression) + return varIdentifier + (isInc ? " += " : " -= ") + expression.ToString (); + else + return varIdentifier + (isInc ? "++" : "--"); + } + + Runtime.VariableAssignment _runtimeAssignment; + } + + public class MultipleConditionExpression : Expression + { + public List subExpressions { + get { + return this.content.Cast ().ToList (); + } + } + + public MultipleConditionExpression(List conditionExpressions) + { + AddContent (conditionExpressions); + } + + public override void GenerateIntoContainer(Runtime.Container container) + { + // A && B && C && D + // => (((A B &&) C &&) D &&) etc + bool isFirst = true; + foreach (var conditionExpr in subExpressions) { + + conditionExpr.GenerateIntoContainer (container); + + if (!isFirst) { + container.AddContent (Runtime.NativeFunctionCall.CallWithName ("&&")); + } + + isFirst = false; + } + } + } + +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ExternalDeclaration.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ExternalDeclaration.cs new file mode 100644 index 0000000..9094500 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ExternalDeclaration.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; + +namespace Ink.Parsed +{ + public class ExternalDeclaration : Parsed.Object, INamedContent + { + public string name + { + get { return identifier?.name; } + } + public Identifier identifier { get; set; } + public List argumentNames { get; set; } + + public ExternalDeclaration (Identifier identifier, List argumentNames) + { + this.identifier = identifier; + this.argumentNames = argumentNames; + } + + public override Ink.Runtime.Object GenerateRuntimeObject () + { + story.AddExternal (this); + + // No runtime code exists for an external, only metadata + return null; + } + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/FlowBase.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/FlowBase.cs new file mode 100644 index 0000000..17aca42 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/FlowBase.cs @@ -0,0 +1,439 @@ +using System.Collections.Generic; + +namespace Ink.Parsed +{ + // Base class for Knots and Stitches + public abstract class FlowBase : Parsed.Object, INamedContent + { + public class Argument + { + public Identifier identifier; + public bool isByReference; + public bool isDivertTarget; + } + + public string name + { + get { return identifier?.name; } + } + public Identifier identifier { get; set; } + public List arguments { get; protected set; } + public bool hasParameters { get { return arguments != null && arguments.Count > 0; } } + public Dictionary variableDeclarations; + + public abstract FlowLevel flowLevel { get; } + public bool isFunction { get; protected set; } + + public FlowBase (Identifier name = null, List topLevelObjects = null, List arguments = null, bool isFunction = false, bool isIncludedStory = false) + { + this.identifier = name; + + if (topLevelObjects == null) { + topLevelObjects = new List (); + } + + // Used by story to add includes + PreProcessTopLevelObjects (topLevelObjects); + + topLevelObjects = SplitWeaveAndSubFlowContent (topLevelObjects, isRootStory:this is Story && !isIncludedStory); + + AddContent(topLevelObjects); + + this.arguments = arguments; + this.isFunction = isFunction; + this.variableDeclarations = new Dictionary (); + } + + List SplitWeaveAndSubFlowContent(List contentObjs, bool isRootStory) + { + var weaveObjs = new List (); + var subFlowObjs = new List (); + + _subFlowsByName = new Dictionary (); + + foreach (var obj in contentObjs) { + + var subFlow = obj as FlowBase; + if (subFlow) { + if (_firstChildFlow == null) + _firstChildFlow = subFlow; + + subFlowObjs.Add (obj); + _subFlowsByName [subFlow.identifier?.name] = subFlow; + } else { + weaveObjs.Add (obj); + } + } + + // Implicit final gather in top level story for ending without warning that you run out of content + if (isRootStory) { + weaveObjs.Add (new Gather (null, 1)); + weaveObjs.Add (new Divert (new Path (Identifier.Done))); + } + + var finalContent = new List (); + + if (weaveObjs.Count > 0) { + _rootWeave = new Weave (weaveObjs, 0); + finalContent.Add (_rootWeave); + } + + if (subFlowObjs.Count > 0) { + finalContent.AddRange (subFlowObjs); + } + + return finalContent; + } + + protected virtual void PreProcessTopLevelObjects(List topLevelObjects) + { + // empty by default, used by Story to process included file references + } + + public struct VariableResolveResult + { + public bool found; + public bool isGlobal; + public bool isArgument; + public bool isTemporary; + public FlowBase ownerFlow; + } + + public VariableResolveResult ResolveVariableWithName(string varName, Parsed.Object fromNode) + { + var result = new VariableResolveResult (); + + // Search in the stitch / knot that owns the node first + var ownerFlow = fromNode == null ? this : fromNode.ClosestFlowBase (); + + // Argument + if (ownerFlow.arguments != null ) { + foreach (var arg in ownerFlow.arguments) { + if (arg.identifier.name.Equals (varName)) { + result.found = true; + result.isArgument = true; + result.ownerFlow = ownerFlow; + return result; + } + } + } + + // Temp + var story = this.story; // optimisation + if (ownerFlow != story && ownerFlow.variableDeclarations.ContainsKey (varName)) { + result.found = true; + result.ownerFlow = ownerFlow; + result.isTemporary = true; + return result; + } + + // Global + if (story.variableDeclarations.ContainsKey (varName)) { + result.found = true; + result.ownerFlow = story; + result.isGlobal = true; + return result; + } + + result.found = false; + return result; + } + + public void TryAddNewVariableDeclaration(VariableAssignment varDecl) + { + var varName = varDecl.variableName; + if (variableDeclarations.ContainsKey (varName)) { + + var prevDeclError = ""; + var debugMetadata = variableDeclarations [varName].debugMetadata; + if (debugMetadata != null) { + prevDeclError = " ("+variableDeclarations [varName].debugMetadata+")"; + } + Error("found declaration variable '"+varName+"' that was already declared"+prevDeclError, varDecl, false); + + return; + } + + variableDeclarations [varDecl.variableName] = varDecl; + } + + public void ResolveWeavePointNaming () + { + // Find all weave points and organise them by name ready for + // diverting. Also detect naming collisions. + if( _rootWeave ) + _rootWeave.ResolveWeavePointNaming (); + + if (_subFlowsByName != null) { + foreach (var namedSubFlow in _subFlowsByName) { + namedSubFlow.Value.ResolveWeavePointNaming (); + } + } + } + + public override Runtime.Object GenerateRuntimeObject () + { + Return foundReturn = null; + if (isFunction) { + CheckForDisallowedFunctionFlowControl (); + } + + // Non-functon: Make sure knots and stitches don't attempt to use Return statement + else if( flowLevel == FlowLevel.Knot || flowLevel == FlowLevel.Stitch ) { + foundReturn = Find (); + if (foundReturn != null) { + Error ("Return statements can only be used in knots that are declared as functions: == function " + this.identifier + " ==", foundReturn); + } + } + + var container = new Runtime.Container (); + container.name = identifier?.name; + + if( this.story.countAllVisits ) { + container.visitsShouldBeCounted = true; + } + + GenerateArgumentVariableAssignments (container); + + // Run through content defined for this knot/stitch: + // - First of all, any initial content before a sub-stitch + // or any weave content is added to the main content container + // - The first inner knot/stitch is automatically entered, while + // the others are only accessible by an explicit divert + // - The exception to this rule is if the knot/stitch takes + // parameters, in which case it can't be auto-entered. + // - Any Choices and Gathers (i.e. IWeavePoint) found are + // processsed by GenerateFlowContent. + int contentIdx = 0; + while (content != null && contentIdx < content.Count) { + + Parsed.Object obj = content [contentIdx]; + + // Inner knots and stitches + if (obj is FlowBase) { + + var childFlow = (FlowBase)obj; + + var childFlowRuntime = childFlow.runtimeObject; + + // First inner stitch - automatically step into it + // 20/09/2016 - let's not auto step into knots + if (contentIdx == 0 && !childFlow.hasParameters + && this.flowLevel == FlowLevel.Knot) { + _startingSubFlowDivert = new Runtime.Divert (); + container.AddContent(_startingSubFlowDivert); + _startingSubFlowRuntime = childFlowRuntime; + } + + // Check for duplicate knots/stitches with same name + var namedChild = (Runtime.INamedContent)childFlowRuntime; + Runtime.INamedContent existingChild = null; + if (container.namedContent.TryGetValue(namedChild.name, out existingChild) ) { + var errorMsg = string.Format ("{0} already contains flow named '{1}' (at {2})", + this.GetType().Name, + namedChild.name, + (existingChild as Runtime.Object).debugMetadata); + + Error (errorMsg, childFlow); + } + + container.AddToNamedContentOnly (namedChild); + } + + // Other content (including entire Weaves that were grouped in the constructor) + // At the time of writing, all FlowBases have a maximum of one piece of "other content" + // and it's always the root Weave + else { + container.AddContent (obj.runtimeObject); + } + + contentIdx++; + } + + // CHECK FOR FINAL LOOSE ENDS! + // Notes: + // - Functions don't need to terminate - they just implicitly return + // - If return statement was found, don't continue finding warnings for missing control flow, + // since it's likely that a return statement has been used instead of a ->-> or something, + // or the writer failed to mark the knot as a function. + // - _rootWeave may be null if it's a knot that only has stitches + if (flowLevel != FlowLevel.Story && !this.isFunction && _rootWeave != null && foundReturn == null) { + _rootWeave.ValidateTermination (WarningInTermination); + } + + return container; + } + + void GenerateArgumentVariableAssignments(Runtime.Container container) + { + if (this.arguments == null || this.arguments.Count == 0) { + return; + } + + // Assign parameters in reverse since they'll be popped off the evaluation stack + // No need to generate EvalStart and EvalEnd since there's nothing being pushed + // back onto the evaluation stack. + for (int i = arguments.Count - 1; i >= 0; --i) { + var paramName = arguments [i].identifier?.name; + + var assign = new Runtime.VariableAssignment (paramName, isNewDeclaration:true); + container.AddContent (assign); + } + } + + public Parsed.Object ContentWithNameAtLevel(string name, FlowLevel? level = null, bool deepSearch = false) + { + // Referencing self? + if (level == this.flowLevel || level == null) { + if (name == this.identifier?.name) { + return this; + } + } + + if ( level == FlowLevel.WeavePoint || level == null ) { + + Parsed.Object weavePointResult = null; + + if (_rootWeave) { + weavePointResult = (Parsed.Object)_rootWeave.WeavePointNamed (name); + if (weavePointResult) + return weavePointResult; + } + + // Stop now if we only wanted a result if it's a weave point? + if (level == FlowLevel.WeavePoint) + return deepSearch ? DeepSearchForAnyLevelContent(name) : null; + } + + // If this flow would be incapable of containing the requested level, early out + // (e.g. asking for a Knot from a Stitch) + if (level != null && level < this.flowLevel) + return null; + + FlowBase subFlow = null; + + if (_subFlowsByName.TryGetValue (name, out subFlow)) { + if (level == null || level == subFlow.flowLevel) + return subFlow; + } + + return deepSearch ? DeepSearchForAnyLevelContent(name) : null; + } + + Parsed.Object DeepSearchForAnyLevelContent(string name) + { + var weaveResultSelf = ContentWithNameAtLevel (name, level:FlowLevel.WeavePoint, deepSearch: false); + if (weaveResultSelf) { + return weaveResultSelf; + } + + foreach (var subFlowNamePair in _subFlowsByName) { + var subFlow = subFlowNamePair.Value; + var deepResult = subFlow.ContentWithNameAtLevel (name, level:null, deepSearch: true); + if (deepResult) + return deepResult; + } + + return null; + } + + public override void ResolveReferences (Story context) + { + if (_startingSubFlowDivert) { + _startingSubFlowDivert.targetPath = _startingSubFlowRuntime.path; + } + + base.ResolveReferences(context); + + // Check validity of parameter names + if (arguments != null) { + + foreach (var arg in arguments) + context.CheckForNamingCollisions (this, arg.identifier, Story.SymbolType.Arg, "argument"); + + // Separately, check for duplicate arugment names, since they aren't Parsed.Objects, + // so have to be checked independently. + for (int i = 0; i < arguments.Count; i++) { + for (int j = i + 1; j < arguments.Count; j++) { + if (arguments [i].identifier?.name == arguments [j].identifier?.name) { + Error ("Multiple arguments with the same name: '" + arguments [i].identifier + "'"); + } + } + } + } + + // Check naming collisions for knots and stitches + if (flowLevel != FlowLevel.Story) { + // Weave points aren't FlowBases, so this will only be knot or stitch + var symbolType = flowLevel == FlowLevel.Knot ? Story.SymbolType.Knot : Story.SymbolType.SubFlowAndWeave; + context.CheckForNamingCollisions (this, identifier, symbolType); + } + } + + void CheckForDisallowedFunctionFlowControl() + { + if (!(this is Knot)) { + Error ("Functions cannot be stitches - i.e. they should be defined as '== function myFunc ==' rather than public to another knot."); + } + + // Not allowed sub-flows + foreach (var subFlowAndName in _subFlowsByName) { + var name = subFlowAndName.Key; + var subFlow = subFlowAndName.Value; + Error ("Functions may not contain stitches, but saw '"+name+"' within the function '"+this.identifier+"'", subFlow); + } + + var allDiverts = _rootWeave.FindAll (); + foreach (var divert in allDiverts) { + if( !divert.isFunctionCall && !(divert.parent is DivertTarget) ) + Error ("Functions may not contain diverts, but saw '"+divert.ToString()+"'", divert); + } + + var allChoices = _rootWeave.FindAll (); + foreach (var choice in allChoices) { + Error ("Functions may not contain choices, but saw '"+choice.ToString()+"'", choice); + } + } + + void WarningInTermination(Parsed.Object terminatingObject) + { + string message = "Apparent loose end exists where the flow runs out. Do you need a '-> DONE' statement, choice or divert?"; + if (terminatingObject.parent == _rootWeave && _firstChildFlow) { + message = message + " Note that if you intend to enter '"+_firstChildFlow.identifier+"' next, you need to divert to it explicitly."; + } + + var terminatingDivert = terminatingObject as Divert; + if (terminatingDivert && terminatingDivert.isTunnel) { + message = message + " When final tunnel to '"+terminatingDivert.target+" ->' returns it won't have anywhere to go."; + } + + Warning (message, terminatingObject); + } + + protected Dictionary subFlowsByName { + get { + return _subFlowsByName; + } + } + + public override string typeName { + get { + if (isFunction) return "Function"; + else return flowLevel.ToString (); + } + } + + public override string ToString () + { + return typeName+" '" + identifier + "'"; + } + + Weave _rootWeave; + Dictionary _subFlowsByName; + Runtime.Divert _startingSubFlowDivert; + Runtime.Object _startingSubFlowRuntime; + FlowBase _firstChildFlow; + + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/FlowLevel.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/FlowLevel.cs new file mode 100644 index 0000000..5bbdce0 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/FlowLevel.cs @@ -0,0 +1,11 @@ +namespace Ink.Parsed +{ + public enum FlowLevel + { + Story, + Knot, + Stitch, + WeavePoint // not actually a FlowBase, but used for diverts + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/FunctionCall.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/FunctionCall.cs new file mode 100644 index 0000000..d3d40f5 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/FunctionCall.cs @@ -0,0 +1,242 @@ +using System.Collections.Generic; + +namespace Ink.Parsed +{ + public class FunctionCall : Expression + { + public string name { get { return _proxyDivert.target.firstComponent; } } + public Divert proxyDivert { get { return _proxyDivert; } } + public List arguments { get { return _proxyDivert.arguments; } } + public Runtime.Divert runtimeDivert { get { return _proxyDivert.runtimeDivert; } } + public bool isChoiceCount { get { return name == "CHOICE_COUNT"; } } + public bool isTurns { get { return name == "TURNS"; } } + public bool isTurnsSince { get { return name == "TURNS_SINCE"; } } + public bool isRandom { get { return name == "RANDOM"; } } + public bool isSeedRandom { get { return name == "SEED_RANDOM"; } } + public bool isListRange { get { return name == "LIST_RANGE"; } } + public bool isListRandom { get { return name == "LIST_RANDOM"; } } + public bool isReadCount { get { return name == "READ_COUNT"; } } + + public bool shouldPopReturnedValue; + + public FunctionCall (Identifier functionName, List arguments) + { + _proxyDivert = new Parsed.Divert(new Path(functionName), arguments); + _proxyDivert.isFunctionCall = true; + AddContent (_proxyDivert); + } + + public override void GenerateIntoContainer (Runtime.Container container) + { + var foundList = story.ResolveList (name); + + bool usingProxyDivert = false; + + if (isChoiceCount) { + + if (arguments.Count > 0) + Error ("The CHOICE_COUNT() function shouldn't take any arguments"); + + container.AddContent (Runtime.ControlCommand.ChoiceCount ()); + + } else if (isTurns) { + + if (arguments.Count > 0) + Error ("The TURNS() function shouldn't take any arguments"); + + container.AddContent (Runtime.ControlCommand.Turns ()); + + } else if (isTurnsSince || isReadCount) { + + var divertTarget = arguments [0] as DivertTarget; + var variableDivertTarget = arguments [0] as VariableReference; + + if (arguments.Count != 1 || (divertTarget == null && variableDivertTarget == null)) { + Error ("The " + name + "() function should take one argument: a divert target to the target knot, stitch, gather or choice you want to check. e.g. TURNS_SINCE(-> myKnot)"); + return; + } + + if (divertTarget) { + _divertTargetToCount = divertTarget; + AddContent (_divertTargetToCount); + + _divertTargetToCount.GenerateIntoContainer (container); + } else { + _variableReferenceToCount = variableDivertTarget; + AddContent (_variableReferenceToCount); + + _variableReferenceToCount.GenerateIntoContainer (container); + } + + if (isTurnsSince) + container.AddContent (Runtime.ControlCommand.TurnsSince ()); + else + container.AddContent (Runtime.ControlCommand.ReadCount ()); + + } else if (isRandom) { + if (arguments.Count != 2) + Error ("RANDOM should take 2 parameters: a minimum and a maximum integer"); + + // We can type check single values, but not complex expressions + for (int arg = 0; arg < arguments.Count; arg++) { + if (arguments [arg] is Number) { + var num = arguments [arg] as Number; + if (!(num.value is int)) { + string paramName = arg == 0 ? "minimum" : "maximum"; + Error ("RANDOM's " + paramName + " parameter should be an integer"); + } + } + + arguments [arg].GenerateIntoContainer (container); + } + + container.AddContent (Runtime.ControlCommand.Random ()); + + } else if (isSeedRandom) { + if (arguments.Count != 1) + Error ("SEED_RANDOM should take 1 parameter - an integer seed"); + + var num = arguments [0] as Number; + if (num && !(num.value is int)) { + Error ("SEED_RANDOM's parameter should be an integer seed"); + } + + arguments [0].GenerateIntoContainer (container); + + container.AddContent (Runtime.ControlCommand.SeedRandom ()); + + } else if (isListRange) { + if (arguments.Count != 3) + Error ("LIST_RANGE should take 3 parameters - a list, a min and a max"); + + for (int arg = 0; arg < arguments.Count; arg++) + arguments [arg].GenerateIntoContainer (container); + + container.AddContent (Runtime.ControlCommand.ListRange ()); + + } else if( isListRandom ) { + if (arguments.Count != 1) + Error ("LIST_RANDOM should take 1 parameter - a list"); + + arguments [0].GenerateIntoContainer (container); + + container.AddContent (Runtime.ControlCommand.ListRandom ()); + + } else if (Runtime.NativeFunctionCall.CallExistsWithName (name)) { + + var nativeCall = Runtime.NativeFunctionCall.CallWithName (name); + + if (nativeCall.numberOfParameters != arguments.Count) { + var msg = name + " should take " + nativeCall.numberOfParameters + " parameter"; + if (nativeCall.numberOfParameters > 1) + msg += "s"; + Error (msg); + } + + for (int arg = 0; arg < arguments.Count; arg++) + arguments [arg].GenerateIntoContainer (container); + + container.AddContent (Runtime.NativeFunctionCall.CallWithName (name)); + } else if (foundList != null) { + if (arguments.Count > 1) + Error ("Can currently only construct a list from one integer (or an empty list from a given list definition)"); + + // List item from given int + if (arguments.Count == 1) { + container.AddContent (new Runtime.StringValue (name)); + arguments [0].GenerateIntoContainer (container); + container.AddContent (Runtime.ControlCommand.ListFromInt ()); + } + + // Empty list with given origin. + else { + var list = new Runtime.InkList (); + list.SetInitialOriginName (name); + container.AddContent (new Runtime.ListValue (list)); + } + } + + // Normal function call + else { + container.AddContent (_proxyDivert.runtimeObject); + usingProxyDivert = true; + } + + // Don't attempt to resolve as a divert if we're not doing a normal function call + if( !usingProxyDivert ) content.Remove (_proxyDivert); + + // Function calls that are used alone on a tilda-based line: + // ~ func() + // Should tidy up any returned value from the evaluation stack, + // since it's unused. + if (shouldPopReturnedValue) + container.AddContent (Runtime.ControlCommand.PopEvaluatedValue ()); + } + + public override void ResolveReferences (Story context) + { + base.ResolveReferences (context); + + // If we aren't using the proxy divert after all (e.g. if + // it's a native function call), but we still have arguments, + // we need to make sure they get resolved since the proxy divert + // is no longer in the content array. + if (!content.Contains(_proxyDivert) && arguments != null) { + foreach (var arg in arguments) + arg.ResolveReferences (context); + } + + if( _divertTargetToCount ) { + var divert = _divertTargetToCount.divert; + var attemptingTurnCountOfVariableTarget = divert.runtimeDivert.variableDivertName != null; + + if( attemptingTurnCountOfVariableTarget ) { + Error("When getting the TURNS_SINCE() of a variable target, remove the '->' - i.e. it should just be TURNS_SINCE("+divert.runtimeDivert.variableDivertName+")"); + return; + } + + var targetObject = divert.targetContent; + if( targetObject == null ) { + if( !attemptingTurnCountOfVariableTarget ) { + Error("Failed to find target for TURNS_SINCE: '"+divert.target+"'"); + } + } else { + targetObject.containerForCounting.turnIndexShouldBeCounted = true; + } + } + + else if( _variableReferenceToCount ) { + var runtimeVarRef = _variableReferenceToCount.runtimeVarRef; + if( runtimeVarRef.pathForCount != null ) { + Error("Should be "+name+"(-> "+_variableReferenceToCount.name+"). Usage without the '->' only makes sense for variable targets."); + } + } + } + + public static bool IsBuiltIn(string name) + { + if (Runtime.NativeFunctionCall.CallExistsWithName (name)) + return true; + + return name == "CHOICE_COUNT" + || name == "TURNS_SINCE" + || name == "TURNS" + || name == "RANDOM" + || name == "SEED_RANDOM" + || name == "LIST_VALUE" + || name == "LIST_RANDOM" + || name == "READ_COUNT"; + } + + public override string ToString () + { + var strArgs = string.Join (", ", arguments.ToStringsArray()); + return string.Format ("{0}({1})", name, strArgs); + } + + Parsed.Divert _proxyDivert; + Parsed.DivertTarget _divertTargetToCount; + Parsed.VariableReference _variableReferenceToCount; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Gather.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Gather.cs new file mode 100644 index 0000000..ca86acf --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Gather.cs @@ -0,0 +1,51 @@ + +namespace Ink.Parsed +{ + public class Gather : Parsed.Object, IWeavePoint, INamedContent + { + public string name + { + get { return identifier?.name; } + } + public Identifier identifier { get; set; } + public int indentationDepth { get; protected set; } + + public Runtime.Container runtimeContainer { get { return (Runtime.Container) runtimeObject; } } + + public Gather (Identifier identifier, int indentationDepth) + { + this.identifier = identifier; + this.indentationDepth = indentationDepth; + } + + public override Runtime.Object GenerateRuntimeObject () + { + var container = new Runtime.Container (); + container.name = name; + + if (this.story.countAllVisits) { + container.visitsShouldBeCounted = true; + } + + container.countingAtStartOnly = true; + + // A gather can have null content, e.g. it's just purely a line with "-" + if (content != null) { + foreach (var c in content) { + container.AddContent (c.runtimeObject); + } + } + + return container; + } + + public override void ResolveReferences (Story context) + { + base.ResolveReferences (context); + + if( identifier != null && identifier.name.Length > 0 ) + context.CheckForNamingCollisions (this, identifier, Story.SymbolType.SubFlowAndWeave); + } + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/INamedContent.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/INamedContent.cs new file mode 100644 index 0000000..fa14449 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/INamedContent.cs @@ -0,0 +1,9 @@ + +namespace Ink.Parsed +{ + public interface INamedContent + { + string name { get; } + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/IWeavePoint.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/IWeavePoint.cs new file mode 100644 index 0000000..4155823 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/IWeavePoint.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace Ink.Parsed +{ + public interface IWeavePoint + { + int indentationDepth { get; } + Runtime.Container runtimeContainer { get; } + List content { get; } + string name { get; } + Identifier identifier { get; } + + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Identifier.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Identifier.cs new file mode 100644 index 0000000..5f76529 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Identifier.cs @@ -0,0 +1,13 @@ +namespace Ink.Parsed { + public class Identifier { + public string name; + public Runtime.DebugMetadata debugMetadata; + + public override string ToString() + { + return name; + } + + public static Identifier Done = new Identifier { name = "DONE", debugMetadata = null }; + } +} diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/IncludedFile.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/IncludedFile.cs new file mode 100644 index 0000000..5eee99b --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/IncludedFile.cs @@ -0,0 +1,20 @@ + +namespace Ink.Parsed +{ + public class IncludedFile : Parsed.Object + { + public Parsed.Story includedStory { get; private set; } + + public IncludedFile (Parsed.Story includedStory) + { + this.includedStory = includedStory; + } + + public override Runtime.Object GenerateRuntimeObject () + { + // Left to the main story to process + return null; + } + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Knot.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Knot.cs new file mode 100644 index 0000000..a39a44c --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Knot.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; + +namespace Ink.Parsed +{ + public class Knot : FlowBase + { + public override FlowLevel flowLevel { get { return FlowLevel.Knot; } } + + public Knot (Identifier name, List topLevelObjects, List arguments, bool isFunction) : base(name, topLevelObjects, arguments, isFunction) + { + } + + public override void ResolveReferences (Story context) + { + base.ResolveReferences (context); + + var parentStory = this.story; + + // Enforce rule that stitches must not have the same + // name as any knots that exist in the story + foreach (var stitchNamePair in subFlowsByName) { + var stitchName = stitchNamePair.Key; + + var knotWithStitchName = parentStory.ContentWithNameAtLevel (stitchName, FlowLevel.Knot, false); + if (knotWithStitchName) { + var stitch = stitchNamePair.Value; + var errorMsg = string.Format ("Stitch '{0}' has the same name as a knot (on {1})", stitch.identifier, knotWithStitchName.debugMetadata); + Error(errorMsg, stitch); + } + } + } + + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/List.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/List.cs new file mode 100644 index 0000000..db48d85 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/List.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; + +namespace Ink.Parsed +{ + public class List : Parsed.Expression + { + public List itemIdentifierList; + + public List (List itemIdentifierList) + { + this.itemIdentifierList = itemIdentifierList; + } + + public override void GenerateIntoContainer (Runtime.Container container) + { + var runtimeRawList = new Runtime.InkList (); + + if (itemIdentifierList != null) { + foreach (var itemIdentifier in itemIdentifierList) { + var nameParts = itemIdentifier?.name.Split ('.'); + + string listName = null; + string listItemName = null; + if (nameParts.Length > 1) { + listName = nameParts [0]; + listItemName = nameParts [1]; + } else { + listItemName = nameParts [0]; + } + + var listItem = story.ResolveListItem (listName, listItemName, this); + if (listItem == null) { + if (listName == null) + Error ("Could not find list definition that contains item '" + itemIdentifier + "'"); + else + Error ("Could not find list item " + itemIdentifier); + } else { + if (listName == null) + listName = ((ListDefinition)listItem.parent).identifier?.name; + var item = new Runtime.InkListItem (listName, listItem.name); + + if (runtimeRawList.ContainsKey (item)) + Warning ("Duplicate of item '"+itemIdentifier+"' in list."); + else + runtimeRawList [item] = listItem.seriesValue; + } + } + } + + container.AddContent(new Runtime.ListValue (runtimeRawList)); + } + } +} diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ListDefinition.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ListDefinition.cs new file mode 100644 index 0000000..2010d1a --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/ListDefinition.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Ink.Parsed +{ + public class ListDefinition : Parsed.Object + { + public Identifier identifier; + public List itemDefinitions; + + public VariableAssignment variableAssignment; + + public Runtime.ListDefinition runtimeListDefinition { + get { + var allItems = new Dictionary (); + foreach (var e in itemDefinitions) { + if( !allItems.ContainsKey(e.name) ) + allItems.Add (e.name, e.seriesValue); + else + Error("List '"+identifier+"' contains dupicate items called '"+e.name+"'"); + } + + return new Runtime.ListDefinition (identifier?.name, allItems); + } + } + + public ListElementDefinition ItemNamed (string itemName) + { + if (_elementsByName == null) { + _elementsByName = new Dictionary (); + foreach (var el in itemDefinitions) { + _elementsByName [el.name] = el; + } + } + + ListElementDefinition foundElement; + if (_elementsByName.TryGetValue (itemName, out foundElement)) + return foundElement; + + return null; + } + + public ListDefinition (List elements) + { + this.itemDefinitions = elements; + + int currentValue = 1; + foreach (var e in this.itemDefinitions) { + if (e.explicitValue != null) + currentValue = e.explicitValue.Value; + + e.seriesValue = currentValue; + + currentValue++; + } + + AddContent (elements); + } + + public override Runtime.Object GenerateRuntimeObject () + { + var initialValues = new Runtime.InkList (); + foreach (var itemDef in itemDefinitions) { + if (itemDef.inInitialList) { + var item = new Runtime.InkListItem (this.identifier?.name, itemDef.name); + initialValues [item] = itemDef.seriesValue; + } + } + + // Set origin name, so + initialValues.SetInitialOriginName (identifier?.name); + + return new Runtime.ListValue (initialValues); + } + + public override void ResolveReferences (Story context) + { + base.ResolveReferences (context); + + context.CheckForNamingCollisions (this, identifier, Story.SymbolType.List); + } + + public override string typeName { + get { + return "List definition"; + } + } + + Dictionary _elementsByName; + } + + public class ListElementDefinition : Parsed.Object + { + public string name + { + get { return identifier?.name; } + } + public Identifier identifier; + public int? explicitValue; + public int seriesValue; + public bool inInitialList; + + public string fullName { + get { + var parentList = parent as ListDefinition; + if (parentList == null) + throw new System.Exception ("Can't get full name without a parent list"); + + return parentList.identifier + "." + name; + } + } + + public ListElementDefinition (Identifier identifier, bool inInitialList, int? explicitValue = null) + { + this.identifier = identifier; + this.inInitialList = inInitialList; + this.explicitValue = explicitValue; + } + + public override Runtime.Object GenerateRuntimeObject () + { + throw new System.NotImplementedException (); + } + + public override void ResolveReferences (Story context) + { + base.ResolveReferences (context); + + context.CheckForNamingCollisions (this, identifier, Story.SymbolType.ListItem); + } + + public override string typeName { + get { + return "List element"; + } + } + } +} diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Number.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Number.cs new file mode 100644 index 0000000..be67bfd --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Number.cs @@ -0,0 +1,53 @@ + +namespace Ink.Parsed +{ + public class Number : Parsed.Expression + { + public object value; + + public Number(object value) + { + if (value is int || value is float || value is bool) { + this.value = value; + } else { + throw new System.Exception ("Unexpected object type in Number"); + } + } + + public override void GenerateIntoContainer (Runtime.Container container) + { + if (value is int) { + container.AddContent (new Runtime.IntValue ((int)value)); + } else if (value is float) { + container.AddContent (new Runtime.FloatValue ((float)value)); + } else if(value is bool) { + container.AddContent (new Runtime.BoolValue ((bool)value)); + } + } + + public override string ToString () + { + if (value is float) { + return ((float)value).ToString(System.Globalization.CultureInfo.InvariantCulture); + } else { + return value.ToString(); + } + } + + // Equals override necessary in order to check for CONST multiple definition equality + public override bool Equals (object obj) + { + var otherNum = obj as Number; + if (otherNum == null) return false; + + return this.value.Equals (otherNum.value); + } + + public override int GetHashCode () + { + return this.value.GetHashCode (); + } + + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Object.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Object.cs new file mode 100644 index 0000000..381a11e --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Object.cs @@ -0,0 +1,363 @@ +using System.Collections.Generic; +using System.Text; + +namespace Ink.Parsed +{ + public abstract class Object + { + public Runtime.DebugMetadata debugMetadata { + get { + if (_debugMetadata == null) { + if (parent) { + return parent.debugMetadata; + } + } + + return _debugMetadata; + } + + set { + _debugMetadata = value; + } + } + private Runtime.DebugMetadata _debugMetadata; + + public bool hasOwnDebugMetadata { + get { + return _debugMetadata != null; + } + } + + public virtual string typeName { + get { + return GetType().Name; + } + } + + public Parsed.Object parent { get; set; } + public List content { get; protected set; } + + public Parsed.Story story { + get { + Parsed.Object ancestor = this; + while (ancestor.parent) { + ancestor = ancestor.parent; + } + return ancestor as Parsed.Story; + } + } + + private Runtime.Object _runtimeObject; + public Runtime.Object runtimeObject + { + get { + if (_runtimeObject == null) { + _runtimeObject = GenerateRuntimeObject (); + if( _runtimeObject ) + _runtimeObject.debugMetadata = debugMetadata; + } + return _runtimeObject; + } + + set { + _runtimeObject = value; + } + } + + // virtual so that certian object types can return a different + // path than just the path to the main runtimeObject. + // e.g. a Choice returns a path to its content rather than + // its outer container. + public virtual Runtime.Path runtimePath + { + get { + return runtimeObject.path; + } + } + + // When counting visits and turns since, different object + // types may have different containers that needs to be counted. + // For most it'll just be the object's main runtime object, + // but for e.g. choices, it'll be the target container. + public virtual Runtime.Container containerForCounting + { + get { + return this.runtimeObject as Runtime.Container; + } + } + + public Parsed.Path PathRelativeTo(Parsed.Object otherObj) + { + var ownAncestry = ancestry; + var otherAncestry = otherObj.ancestry; + + Parsed.Object highestCommonAncestor = null; + int minLength = System.Math.Min (ownAncestry.Count, otherAncestry.Count); + for (int i = 0; i < minLength; ++i) { + var a1 = ancestry [i]; + var a2 = otherAncestry [i]; + if (a1 == a2) + highestCommonAncestor = a1; + else + break; + } + + FlowBase commonFlowAncestor = highestCommonAncestor as FlowBase; + if (commonFlowAncestor == null) + commonFlowAncestor = highestCommonAncestor.ClosestFlowBase (); + + + var pathComponents = new List (); + bool hasWeavePoint = false; + FlowLevel baseFlow = FlowLevel.WeavePoint; + + var ancestor = this; + while(ancestor && (ancestor != commonFlowAncestor) && !(ancestor is Story)) { + + if (ancestor == commonFlowAncestor) + break; + + if (!hasWeavePoint) { + var weavePointAncestor = ancestor as IWeavePoint; + if (weavePointAncestor != null && weavePointAncestor.identifier != null) { + pathComponents.Add (weavePointAncestor.identifier); + hasWeavePoint = true; + continue; + } + } + + var flowAncestor = ancestor as FlowBase; + if (flowAncestor) { + pathComponents.Add (flowAncestor.identifier); + baseFlow = flowAncestor.flowLevel; + } + + ancestor = ancestor.parent; + } + + pathComponents.Reverse (); + + if (pathComponents.Count > 0) { + return new Path (baseFlow, pathComponents); + } + + return null; + } + + public List ancestry + { + get { + var result = new List (); + + var ancestor = this.parent; + while(ancestor) { + result.Add (ancestor); + ancestor = ancestor.parent; + } + + result.Reverse (); + + return result; + } + } + + public string descriptionOfScope + { + get { + var locationNames = new List (); + + Parsed.Object ancestor = this; + while (ancestor) { + var ancestorFlow = ancestor as FlowBase; + if (ancestorFlow && ancestorFlow.identifier != null) { + locationNames.Add ("'" + ancestorFlow.identifier + "'"); + } + ancestor = ancestor.parent; + } + + var scopeSB = new StringBuilder (); + if (locationNames.Count > 0) { + var locationsListStr = string.Join (", ", locationNames.ToArray()); + scopeSB.Append (locationsListStr); + scopeSB.Append (" and "); + } + + scopeSB.Append ("at top scope"); + + return scopeSB.ToString (); + } + } + + // Return the object so that method can be chained easily + public T AddContent(T subContent) where T : Parsed.Object + { + if (content == null) { + content = new List (); + } + + // Make resilient to content not existing, which can happen + // in the case of parse errors where we've already reported + // an error but still want a valid structure so we can + // carry on parsing. + if( subContent ) { + subContent.parent = this; + content.Add(subContent); + } + + return subContent; + } + + public void AddContent(List listContent) where T : Parsed.Object + { + foreach (var obj in listContent) { + AddContent (obj); + } + } + + public T InsertContent(int index, T subContent) where T : Parsed.Object + { + if (content == null) { + content = new List (); + } + + subContent.parent = this; + content.Insert (index, subContent); + + return subContent; + } + + public delegate bool FindQueryFunc(T obj); + public T Find(FindQueryFunc queryFunc = null) where T : class + { + var tObj = this as T; + if (tObj != null && (queryFunc == null || queryFunc (tObj) == true)) { + return tObj; + } + + if (content == null) + return null; + + foreach (var obj in content) { + var nestedResult = obj.Find (queryFunc); + if (nestedResult != null) + return nestedResult; + } + + return null; + } + + + public List FindAll(FindQueryFunc queryFunc = null) where T : class + { + var found = new List (); + + FindAll (queryFunc, found); + + return found; + } + + void FindAll(FindQueryFunc queryFunc, List foundSoFar) where T : class + { + var tObj = this as T; + if (tObj != null && (queryFunc == null || queryFunc (tObj) == true)) { + foundSoFar.Add (tObj); + } + + if (content == null) + return; + + foreach (var obj in content) { + obj.FindAll (queryFunc, foundSoFar); + } + } + + public abstract Runtime.Object GenerateRuntimeObject (); + + public virtual void ResolveReferences(Story context) + { + if (content != null) { + foreach(var obj in content) { + obj.ResolveReferences (context); + } + } + } + + public FlowBase ClosestFlowBase() + { + var ancestor = this.parent; + while (ancestor) { + if (ancestor is FlowBase) { + return (FlowBase)ancestor; + } + ancestor = ancestor.parent; + } + + return null; + } + + public virtual void Error(string message, Parsed.Object source = null, bool isWarning = false) + { + if (source == null) { + source = this; + } + + // Only allow a single parsed object to have a single error *directly* associated with it + if (source._alreadyHadError && !isWarning) { + return; + } + if (source._alreadyHadWarning && isWarning) { + return; + } + + if (this.parent) { + this.parent.Error (message, source, isWarning); + } else { + throw new System.Exception ("No parent object to send error to: "+message); + } + + if (isWarning) { + source._alreadyHadWarning = true; + } else { + source._alreadyHadError = true; + } + + } + + public void Warning(string message, Parsed.Object source = null) + { + Error (message, source, isWarning: true); + } + + // Allow implicit conversion to bool so you don't have to do: + // if( myObj != null ) ... + public static implicit operator bool (Object obj) + { + var isNull = object.ReferenceEquals (obj, null); + return !isNull; + } + + public static bool operator ==(Object a, Object b) + { + return object.ReferenceEquals (a, b); + } + + public static bool operator !=(Object a, Object b) + { + return !(a == b); + } + + public override bool Equals (object obj) + { + return object.ReferenceEquals (obj, this); + } + + public override int GetHashCode () + { + return base.GetHashCode (); + } + + bool _alreadyHadError; + bool _alreadyHadWarning; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Path.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Path.cs new file mode 100644 index 0000000..7a17bd3 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Path.cs @@ -0,0 +1,192 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Ink.Parsed +{ + public class Path + { + public FlowLevel baseTargetLevel { + get { + if (baseLevelIsAmbiguous) + return FlowLevel.Story; + else + return (FlowLevel) _baseTargetLevel; + } + } + + public bool baseLevelIsAmbiguous { + get { + return _baseTargetLevel == null; + } + } + + public string firstComponent { + get { + if (components == null || components.Count == 0) + return null; + + return components [0].name; + } + } + + public int numberOfComponents { + get { + return components.Count; + } + } + + public string dotSeparatedComponents { + get { + if( _dotSeparatedComponents == null ) { + _dotSeparatedComponents = string.Join(".", components.Select(c => c?.name)); + } + + return _dotSeparatedComponents; + } + } + string _dotSeparatedComponents; + + public List components { get; } + + public Path(FlowLevel baseFlowLevel, List components) + { + _baseTargetLevel = baseFlowLevel; + this.components = components; + } + + public Path(List components) + { + _baseTargetLevel = null; + this.components = components; + } + + public Path(Identifier ambiguousName) + { + _baseTargetLevel = null; + components = new List (); + components.Add (ambiguousName); + } + + public override string ToString () + { + if (components == null || components.Count == 0) { + if (baseTargetLevel == FlowLevel.WeavePoint) + return "-> "; + else + return ""; + } + + return "-> " + dotSeparatedComponents; + } + + public Parsed.Object ResolveFromContext(Parsed.Object context) + { + if (components == null || components.Count == 0) { + return null; + } + + // Find base target of path from current context. e.g. + // ==> BASE.sub.sub + var baseTargetObject = ResolveBaseTarget (context); + if (baseTargetObject == null) { + return null; + + } + + // Given base of path, resolve final target by working deeper into hierarchy + // e.g. ==> base.mid.FINAL + if (components.Count > 1) { + return ResolveTailComponents (baseTargetObject); + } + + return baseTargetObject; + } + + // Find the root object from the base, i.e. root from: + // root.sub1.sub2 + Parsed.Object ResolveBaseTarget(Parsed.Object originalContext) + { + var firstComp = firstComponent; + + // Work up the ancestry to find the node that has the named object + Parsed.Object ancestorContext = originalContext; + while (ancestorContext != null) { + + // Only allow deep search when searching deeper from original context. + // Don't allow search upward *then* downward, since that's searching *everywhere*! + // Allowed examples: + // - From an inner gather of a stitch, you should search up to find a knot called 'x' + // at the root of a story, but not a stitch called 'x' in that knot. + // - However, from within a knot, you should be able to find a gather/choice + // anywhere called 'x' + // (that latter example is quite loose, but we allow it) + bool deepSearch = ancestorContext == originalContext; + + var foundBase = TryGetChildFromContext (ancestorContext, firstComp, null, deepSearch); + if (foundBase != null) + return foundBase; + + ancestorContext = ancestorContext.parent; + } + + return null; + } + + // Find the final child from path given root, i.e.: + // root.sub.finalChild + Parsed.Object ResolveTailComponents(Parsed.Object rootTarget) + { + Parsed.Object foundComponent = rootTarget; + for (int i = 1; i < components.Count; ++i) { + var compName = components [i].name; + + FlowLevel minimumExpectedLevel; + var foundFlow = foundComponent as FlowBase; + if (foundFlow != null) + minimumExpectedLevel = (FlowLevel)(foundFlow.flowLevel + 1); + else + minimumExpectedLevel = FlowLevel.WeavePoint; + + + foundComponent = TryGetChildFromContext (foundComponent, compName, minimumExpectedLevel); + if (foundComponent == null) + break; + } + + return foundComponent; + } + + // See whether "context" contains a child with a given name at a given flow level + // Can either be a named knot/stitch (a FlowBase) or a weave point within a Weave (Choice or Gather) + // This function also ignores any other object types that are neither FlowBase nor Weave. + // Called from both ResolveBase (force deep) and ResolveTail for the individual components. + Parsed.Object TryGetChildFromContext(Parsed.Object context, string childName, FlowLevel? minimumLevel, bool forceDeepSearch = false) + { + // null childLevel means that we don't know where to find it + bool ambiguousChildLevel = minimumLevel == null; + + // Search for WeavePoint within Weave + var weaveContext = context as Weave; + if ( weaveContext != null && (ambiguousChildLevel || minimumLevel == FlowLevel.WeavePoint)) { + return (Parsed.Object) weaveContext.WeavePointNamed (childName); + } + + // Search for content within Flow (either a sub-Flow or a WeavePoint) + var flowContext = context as FlowBase; + if (flowContext != null) { + + // When searching within a Knot, allow a deep searches so that + // named weave points (choices and gathers) can be found within any stitch + // Otherwise, we just search within the immediate object. + var shouldDeepSearch = forceDeepSearch || flowContext.flowLevel == FlowLevel.Knot; + return flowContext.ContentWithNameAtLevel (childName, minimumLevel, shouldDeepSearch); + } + + return null; + } + + FlowLevel? _baseTargetLevel; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Return.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Return.cs new file mode 100644 index 0000000..2acb78d --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Return.cs @@ -0,0 +1,39 @@ +namespace Ink.Parsed +{ + public class Return : Parsed.Object + { + public Expression returnedExpression { get; protected set; } + + public Return (Expression returnedExpression = null) + { + if (returnedExpression) { + this.returnedExpression = AddContent(returnedExpression); + } + } + + public override Runtime.Object GenerateRuntimeObject () + { + var container = new Runtime.Container (); + + // Evaluate expression + if (returnedExpression) { + container.AddContent (returnedExpression.runtimeObject); + } + + // Return Runtime.Void when there's no expression to evaluate + // (This evaluation will just add the Void object to the evaluation stack) + else { + container.AddContent (Runtime.ControlCommand.EvalStart ()); + container.AddContent (new Runtime.Void()); + container.AddContent (Runtime.ControlCommand.EvalEnd ()); + } + + // Then pop the call stack + // (the evaluated expression will leave the return value on the evaluation stack) + container.AddContent (Runtime.ControlCommand.PopFunction()); + + return container; + } + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Sequence.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Sequence.cs new file mode 100644 index 0000000..b628280 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Sequence.cs @@ -0,0 +1,206 @@ +using System.Collections.Generic; + +namespace Ink.Parsed +{ + [System.Flags] + public enum SequenceType + { + Stopping = 1, // default + Cycle = 2, + Shuffle = 4, + Once = 8 + } + + public class Sequence : Parsed.Object + { + + public List sequenceElements; + public SequenceType sequenceType; + + public Sequence (List elementContentLists, SequenceType sequenceType) + { + this.sequenceType = sequenceType; + this.sequenceElements = new List (); + + foreach (var elementContentList in elementContentLists) { + + var contentObjs = elementContentList.content; + + Parsed.Object seqElObject = null; + + // Don't attempt to create a weave for the sequence element + // if the content list is empty. Weaves don't like it! + if (contentObjs == null || contentObjs.Count == 0) + seqElObject = elementContentList; + else + seqElObject = new Weave (contentObjs); + + this.sequenceElements.Add (seqElObject); + AddContent (seqElObject); + } + } + + // Generate runtime code that looks like: + // + // chosenIndex = MIN(sequence counter, num elements) e.g. for "Stopping" + // if chosenIndex == 0, divert to s0 + // if chosenIndex == 1, divert to s1 [etc] + // + // - s0: + // + // divert to no-op + // - s1: + // + // divert to no-op + // - s2: + // empty branch if using "once" + // divert to no-op + // + // no-op + // + public override Runtime.Object GenerateRuntimeObject () + { + var container = new Runtime.Container (); + container.visitsShouldBeCounted = true; + container.countingAtStartOnly = true; + + _sequenceDivertsToResove = new List (); + + // Get sequence read count + container.AddContent (Runtime.ControlCommand.EvalStart ()); + container.AddContent (Runtime.ControlCommand.VisitIndex ()); + + bool once = (sequenceType & SequenceType.Once) > 0; + bool cycle = (sequenceType & SequenceType.Cycle) > 0; + bool stopping = (sequenceType & SequenceType.Stopping) > 0; + bool shuffle = (sequenceType & SequenceType.Shuffle) > 0; + + var seqBranchCount = sequenceElements.Count; + if (once) seqBranchCount++; + + // Chosen sequence index: + // - Stopping: take the MIN(read count, num elements - 1) + // - Once: take the MIN(read count, num elements) + // (the last one being empty) + if (stopping || once) { + //var limit = stopping ? seqBranchCount-1 : seqBranchCount; + container.AddContent (new Runtime.IntValue (seqBranchCount-1)); + container.AddContent (Runtime.NativeFunctionCall.CallWithName ("MIN")); + } + + // - Cycle: take (read count % num elements) + else if (cycle) { + container.AddContent (new Runtime.IntValue (sequenceElements.Count)); + container.AddContent (Runtime.NativeFunctionCall.CallWithName ("%")); + } + + // Shuffle + if (shuffle) { + + // Create point to return to when sequence is complete + var postShuffleNoOp = Runtime.ControlCommand.NoOp(); + + // When visitIndex == lastIdx, we skip the shuffle + if ( once || stopping ) + { + // if( visitIndex == lastIdx ) -> skipShuffle + int lastIdx = stopping ? sequenceElements.Count - 1 : sequenceElements.Count; + container.AddContent(Runtime.ControlCommand.Duplicate()); + container.AddContent(new Runtime.IntValue(lastIdx)); + container.AddContent(Runtime.NativeFunctionCall.CallWithName("==")); + + var skipShuffleDivert = new Runtime.Divert(); + skipShuffleDivert.isConditional = true; + container.AddContent(skipShuffleDivert); + + AddDivertToResolve(skipShuffleDivert, postShuffleNoOp); + } + + // This one's a bit more complex! Choose the index at runtime. + var elementCountToShuffle = sequenceElements.Count; + if (stopping) elementCountToShuffle--; + container.AddContent (new Runtime.IntValue (elementCountToShuffle)); + container.AddContent (Runtime.ControlCommand.SequenceShuffleIndex ()); + if (once || stopping) container.AddContent(postShuffleNoOp); + } + + container.AddContent (Runtime.ControlCommand.EvalEnd ()); + + // Create point to return to when sequence is complete + var postSequenceNoOp = Runtime.ControlCommand.NoOp(); + + // Each of the main sequence branches, and one extra empty branch if + // we have a "once" sequence. + for (var elIndex=0; elIndex _sequenceDivertsToResove; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Stitch.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Stitch.cs new file mode 100644 index 0000000..a4ac723 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Stitch.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace Ink.Parsed +{ + public class Stitch : FlowBase + { + public override FlowLevel flowLevel { get { return FlowLevel.Stitch; } } + + public Stitch (Identifier name, List topLevelObjects, List arguments, bool isFunction) : base(name, topLevelObjects, arguments, isFunction) + { + } + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Story.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Story.cs new file mode 100644 index 0000000..cca1b5e --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Story.cs @@ -0,0 +1,508 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.CompilerServices; +using System.Diagnostics; + +[assembly: InternalsVisibleTo("tests")] + +namespace Ink.Parsed +{ + public class Story : FlowBase + { + public override FlowLevel flowLevel { get { return FlowLevel.Story; } } + + /// + /// Had error during code gen, resolve references? + /// Most of the time it shouldn't be necessary to use this + /// since errors should be caught by the error handler. + /// + internal bool hadError { get { return _hadError; } } + internal bool hadWarning { get { return _hadWarning; } } + + public Dictionary constants; + public Dictionary externals; + + // Build setting for exporting: + // When true, the visit count for *all* knots, stitches, choices, + // and gathers is counted. When false, only those that are direclty + // referenced by the ink are recorded. Use this flag to allow game-side + // querying of arbitrary knots/stitches etc. + // Storing all counts is more robust and future proof (updates to the story file + // that reference previously uncounted visits are possible, but generates a much + // larger safe file, with a lot of potentially redundant counts. + public bool countAllVisits = false; + + public Story (List toplevelObjects, bool isInclude = false) : base(null, toplevelObjects, isIncludedStory:isInclude) + { + // Don't do anything much on construction, leave it lightweight until + // the ExportRuntime method is called. + } + + // Before this function is called, we have IncludedFile objects interspersed + // in our content wherever an include statement was. + // So that the include statement can be added in a sensible place (e.g. the + // top of the file) without side-effects of jumping into a knot that was + // defined in that include, we separate knots and stitches from anything + // else defined at the top scope of the included file. + // + // Algorithm: For each IncludedFile we find, split its contents into + // knots/stiches and any other content. Insert the normal content wherever + // the include statement was, and append the knots/stitches to the very + // end of the main story. + protected override void PreProcessTopLevelObjects(List topLevelContent) + { + var flowsFromOtherFiles = new List (); + + // Inject included files + int i = 0; + while (i < topLevelContent.Count) { + var obj = topLevelContent [i]; + if (obj is IncludedFile) { + + var file = (IncludedFile)obj; + + // Remove the IncludedFile itself + topLevelContent.RemoveAt (i); + + // When an included story fails to load, the include + // line itself is still valid, so we have to handle it here + if (file.includedStory) { + + var nonFlowContent = new List (); + + var subStory = file.includedStory; + + // Allow empty file + if (subStory.content != null) { + + foreach (var subStoryObj in subStory.content) { + if (subStoryObj is FlowBase) { + flowsFromOtherFiles.Add ((FlowBase)subStoryObj); + } else { + nonFlowContent.Add (subStoryObj); + } + } + + // Add newline on the end of the include + nonFlowContent.Add (new Parsed.Text ("\n")); + + // Add contents of the file in its place + topLevelContent.InsertRange (i, nonFlowContent); + + // Skip past the content of this sub story + // (since it will already have recursively included + // any lines from other files) + i += nonFlowContent.Count; + } + + } + + // Include object has been removed, with possible content inserted, + // and position of 'i' will have been determined already. + continue; + } + + // Non-include: skip over it + else { + i++; + } + } + + // Add the flows we collected from the included files to the + // end of our list of our content + topLevelContent.AddRange (flowsFromOtherFiles.ToArray()); + + } + + public Runtime.Story ExportRuntime(ErrorHandler errorHandler = null) + { + _errorHandler = errorHandler; + + // Find all constants before main export begins, so that VariableReferences know + // whether to generate a runtime variable reference or the literal value + constants = new Dictionary (); + foreach (var constDecl in FindAll ()) { + + // Check for duplicate definitions + Parsed.Expression existingDefinition = null; + if (constants.TryGetValue (constDecl.constantName, out existingDefinition)) { + if (!existingDefinition.Equals (constDecl.expression)) { + var errorMsg = string.Format ("CONST '{0}' has been redefined with a different value. Multiple definitions of the same CONST are valid so long as they contain the same value. Initial definition was on {1}.", constDecl.constantName, existingDefinition.debugMetadata); + Error (errorMsg, constDecl, isWarning:false); + } + } + + constants [constDecl.constantName] = constDecl.expression; + } + + // List definitions are treated like constants too - they should be usable + // from other variable declarations. + _listDefs = new Dictionary (); + foreach (var listDef in FindAll ()) { + _listDefs [listDef.identifier?.name] = listDef; + } + + externals = new Dictionary (); + + // Resolution of weave point names has to come first, before any runtime code generation + // since names have to be ready before diverts start getting created. + // (It used to be done in the constructor for a weave, but didn't allow us to generate + // errors when name resolution failed.) + ResolveWeavePointNaming (); + + // Get default implementation of runtimeObject, which calls ContainerBase's generation method + var rootContainer = runtimeObject as Runtime.Container; + + // Export initialisation of global variables + // TODO: We *could* add this as a declarative block to the story itself... + var variableInitialisation = new Runtime.Container (); + variableInitialisation.AddContent (Runtime.ControlCommand.EvalStart ()); + + // Global variables are those that are local to the story and marked as global + var runtimeLists = new List (); + foreach (var nameDeclPair in variableDeclarations) { + var varName = nameDeclPair.Key; + var varDecl = nameDeclPair.Value; + if (varDecl.isGlobalDeclaration) { + + if (varDecl.listDefinition != null) { + _listDefs[varName] = varDecl.listDefinition; + variableInitialisation.AddContent (varDecl.listDefinition.runtimeObject); + runtimeLists.Add (varDecl.listDefinition.runtimeListDefinition); + } else { + varDecl.expression.GenerateIntoContainer (variableInitialisation); + } + + var runtimeVarAss = new Runtime.VariableAssignment (varName, isNewDeclaration:true); + runtimeVarAss.isGlobal = true; + variableInitialisation.AddContent (runtimeVarAss); + } + } + + variableInitialisation.AddContent (Runtime.ControlCommand.EvalEnd ()); + variableInitialisation.AddContent (Runtime.ControlCommand.End ()); + + if (variableDeclarations.Count > 0) { + variableInitialisation.name = "global decl"; + rootContainer.AddToNamedContentOnly (variableInitialisation); + } + + // Signal that it's safe to exit without error, even if there are no choices generated + // (this only happens at the end of top level content that isn't in any particular knot) + rootContainer.AddContent (Runtime.ControlCommand.Done ()); + + // Replace runtimeObject with Story object instead of the Runtime.Container generated by Parsed.ContainerBase + var runtimeStory = new Runtime.Story (rootContainer, runtimeLists); + + runtimeObject = runtimeStory; + + if (_hadError) + return null; + + // Optimisation step - inline containers that can be + FlattenContainersIn (rootContainer); + + // Now that the story has been fulled parsed into a hierarchy, + // and the derived runtime hierarchy has been built, we can + // resolve referenced symbols such as variables and paths. + // e.g. for paths " -> knotName --> stitchName" into an INKPath (knotName.stitchName) + // We don't make any assumptions that the INKPath follows the same + // conventions as the script format, so we resolve to actual objects before + // translating into an INKPath. (This also allows us to choose whether + // we want the paths to be absolute) + ResolveReferences (this); + + if (_hadError) + return null; + + runtimeStory.ResetState (); + + return runtimeStory; + } + + public ListDefinition ResolveList (string listName) + { + ListDefinition list; + if (!_listDefs.TryGetValue (listName, out list)) + return null; + return list; + } + + public ListElementDefinition ResolveListItem (string listName, string itemName, Parsed.Object source = null) + { + ListDefinition listDef = null; + + // Search a specific list if we know its name (i.e. the form listName.itemName) + if (listName != null) { + if (!_listDefs.TryGetValue (listName, out listDef)) + return null; + + return listDef.ItemNamed (itemName); + } + + // Otherwise, try to search all lists + else { + + ListElementDefinition foundItem = null; + ListDefinition originalFoundList = null; + + foreach (var namedList in _listDefs) { + var listToSearch = namedList.Value; + var itemInThisList = listToSearch.ItemNamed (itemName); + if (itemInThisList) { + if (foundItem != null) { + Error ("Ambiguous item name '" + itemName + "' found in multiple sets, including "+originalFoundList.identifier+" and "+listToSearch.identifier, source, isWarning:false); + } else { + foundItem = itemInThisList; + originalFoundList = listToSearch; + } + } + } + + return foundItem; + } + } + + void FlattenContainersIn (Runtime.Container container) + { + // Need to create a collection to hold the inner containers + // because otherwise we'd end up modifying during iteration + var innerContainers = new HashSet (); + + foreach (var c in container.content) { + var innerContainer = c as Runtime.Container; + if (innerContainer) + innerContainers.Add (innerContainer); + } + + // Can't flatten the named inner containers, but we can at least + // iterate through their children + if (container.namedContent != null) { + foreach (var keyValue in container.namedContent) { + var namedInnerContainer = keyValue.Value as Runtime.Container; + if (namedInnerContainer) + innerContainers.Add (namedInnerContainer); + } + } + + foreach (var innerContainer in innerContainers) { + TryFlattenContainer (innerContainer); + FlattenContainersIn (innerContainer); + } + } + + void TryFlattenContainer (Runtime.Container container) + { + if (container.namedContent.Count > 0 || container.hasValidName || _dontFlattenContainers.Contains(container)) + return; + + // Inline all the content in container into the parent + var parentContainer = container.parent as Runtime.Container; + if (parentContainer) { + + var contentIdx = parentContainer.content.IndexOf (container); + parentContainer.content.RemoveAt (contentIdx); + + var dm = container.ownDebugMetadata; + + foreach (var innerContent in container.content) { + innerContent.parent = null; + if (dm != null && innerContent.ownDebugMetadata == null) + innerContent.debugMetadata = dm; + parentContainer.InsertContent (innerContent, contentIdx); + contentIdx++; + } + } + } + + public override void Error(string message, Parsed.Object source, bool isWarning) + { + ErrorType errorType = isWarning ? ErrorType.Warning : ErrorType.Error; + + var sb = new StringBuilder (); + if (source is AuthorWarning) { + sb.Append ("TODO: "); + errorType = ErrorType.Author; + } else if (isWarning) { + sb.Append ("WARNING: "); + } else { + sb.Append ("ERROR: "); + } + + if (source && source.debugMetadata != null && source.debugMetadata.startLineNumber >= 1 ) { + + if (source.debugMetadata.fileName != null) { + sb.AppendFormat ("'{0}' ", source.debugMetadata.fileName); + } + + sb.AppendFormat ("line {0}: ", source.debugMetadata.startLineNumber); + } + + sb.Append (message); + + message = sb.ToString (); + + if (_errorHandler != null) { + _hadError = errorType == ErrorType.Error; + _hadWarning = errorType == ErrorType.Warning; + _errorHandler (message, errorType); + } else { + throw new System.Exception (message); + } + } + + public void ResetError() + { + _hadError = false; + _hadWarning = false; + } + + public bool IsExternal(string namedFuncTarget) + { + return externals.ContainsKey (namedFuncTarget); + } + + public void AddExternal(ExternalDeclaration decl) + { + if (externals.ContainsKey (decl.name)) { + Error ("Duplicate EXTERNAL definition of '"+decl.name+"'", decl, false); + } else { + externals [decl.name] = decl; + } + } + + public void DontFlattenContainer (Runtime.Container container) + { + _dontFlattenContainers.Add (container); + } + + + + void NameConflictError (Parsed.Object obj, string name, Parsed.Object existingObj, string typeNameToPrint) + { + obj.Error (typeNameToPrint+" '" + name + "': name has already been used for a " + existingObj.typeName.ToLower() + " on " +existingObj.debugMetadata); + } + + public static bool IsReservedKeyword (string name) + { + switch (name) { + case "true": + case "false": + case "not": + case "return": + case "else": + case "VAR": + case "CONST": + case "temp": + case "LIST": + case "function": + return true; + } + + return false; + } + + public enum SymbolType : uint + { + Knot, + List, + ListItem, + Var, + SubFlowAndWeave, + Arg, + Temp + } + + // Check given symbol type against everything that's of a higher priority in the ordered SymbolType enum (above). + // When the given symbol type level is reached, we early-out / return. + public void CheckForNamingCollisions (Parsed.Object obj, Identifier identifier, SymbolType symbolType, string typeNameOverride = null) + { + string typeNameToPrint = typeNameOverride ?? obj.typeName; + if (IsReservedKeyword (identifier?.name)) { + obj.Error ("'"+name + "' cannot be used for the name of a " + typeNameToPrint.ToLower() + " because it's a reserved keyword"); + return; + } + + if (FunctionCall.IsBuiltIn (identifier?.name)) { + obj.Error ("'"+name + "' cannot be used for the name of a " + typeNameToPrint.ToLower() + " because it's a built in function"); + return; + } + + // Top level knots + FlowBase knotOrFunction = ContentWithNameAtLevel (identifier?.name, FlowLevel.Knot) as FlowBase; + if (knotOrFunction && (knotOrFunction != obj || symbolType == SymbolType.Arg)) { + NameConflictError (obj, identifier?.name, knotOrFunction, typeNameToPrint); + return; + } + + if (symbolType < SymbolType.List) return; + + // Lists + foreach (var namedListDef in _listDefs) { + var listDefName = namedListDef.Key; + var listDef = namedListDef.Value; + if (identifier?.name == listDefName && obj != listDef && listDef.variableAssignment != obj) { + NameConflictError (obj, identifier?.name, listDef, typeNameToPrint); + } + + // We don't check for conflicts between individual elements in + // different lists because they are namespaced. + if (!(obj is ListElementDefinition)) { + foreach (var item in listDef.itemDefinitions) { + if (identifier?.name == item.name) { + NameConflictError (obj, identifier?.name, item, typeNameToPrint); + } + } + } + } + + // Don't check for VAR->VAR conflicts because that's handled separately + // (necessary since checking looks up in a dictionary) + if (symbolType <= SymbolType.Var) return; + + // Global variable collision + VariableAssignment varDecl = null; + if (variableDeclarations.TryGetValue(identifier?.name, out varDecl) ) { + if (varDecl != obj && varDecl.isGlobalDeclaration && varDecl.listDefinition == null) { + NameConflictError (obj, identifier?.name, varDecl, typeNameToPrint); + } + } + + if (symbolType < SymbolType.SubFlowAndWeave) return; + + // Stitches, Choices and Gathers + var path = new Path (identifier); + var targetContent = path.ResolveFromContext (obj); + if (targetContent && targetContent != obj) { + NameConflictError (obj, identifier?.name, targetContent, typeNameToPrint); + return; + } + + if (symbolType < SymbolType.Arg) return; + + // Arguments to the current flow + if (symbolType != SymbolType.Arg) { + FlowBase flow = obj as FlowBase; + if( flow == null ) flow = obj.ClosestFlowBase (); + if (flow && flow.hasParameters) { + foreach (var arg in flow.arguments) { + if (arg.identifier?.name == identifier?.name) { + obj.Error (typeNameToPrint+" '" + name + "': Name has already been used for a argument to "+flow.identifier+" on " +flow.debugMetadata); + return; + } + } + } + } + } + + ErrorHandler _errorHandler; + bool _hadError; + bool _hadWarning; + + HashSet _dontFlattenContainers = new HashSet(); + + Dictionary _listDefs; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/StringExpression.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/StringExpression.cs new file mode 100644 index 0000000..189222d --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/StringExpression.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ink.Parsed +{ + public class StringExpression : Parsed.Expression + { + public bool isSingleString { + get { + if (content.Count != 1) + return false; + + var c = content [0]; + if (!(c is Text)) + return false; + + return true; + } + } + + public StringExpression (List content) + { + AddContent (content); + } + + public override void GenerateIntoContainer (Runtime.Container container) + { + container.AddContent (Runtime.ControlCommand.BeginString()); + + foreach (var c in content) { + container.AddContent (c.runtimeObject); + } + + container.AddContent (Runtime.ControlCommand.EndString()); + } + + public override string ToString () + { + var sb = new StringBuilder (); + foreach (var c in content) { + sb.Append (c.ToString ()); + } + return sb.ToString (); + } + + // Equals override necessary in order to check for CONST multiple definition equality + public override bool Equals (object obj) + { + var otherStr = obj as StringExpression; + if (otherStr == null) return false; + + // Can only compare direct equality on single strings rather than + // complex string expressions that contain dynamic logic + if (!this.isSingleString || !otherStr.isSingleString) { + return false; + } + + var thisTxt = this.ToString (); + var otherTxt = otherStr.ToString (); + return thisTxt.Equals (otherTxt); + } + + public override int GetHashCode () + { + return this.ToString ().GetHashCode (); + } + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Tag.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Tag.cs new file mode 100644 index 0000000..c37a4ae --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Tag.cs @@ -0,0 +1,27 @@ + +namespace Ink.Parsed +{ + public class Tag : Parsed.Object + { + + public bool isStart; + public bool inChoice; + + public override Runtime.Object GenerateRuntimeObject () + { + if( isStart ) + return Runtime.ControlCommand.BeginTag(); + else + return Runtime.ControlCommand.EndTag(); + } + + public override string ToString () + { + if( isStart ) + return "#StartTag"; + else + return "#EndTag"; + } + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Text.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Text.cs new file mode 100644 index 0000000..f1b59bc --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Text.cs @@ -0,0 +1,24 @@ + +namespace Ink.Parsed +{ + public class Text : Parsed.Object + { + public string text { get; set; } + + public Text (string str) + { + text = str; + } + + public override Runtime.Object GenerateRuntimeObject () + { + return new Runtime.StringValue(this.text); + } + + public override string ToString () + { + return this.text; + } + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/TunnelOnwards.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/TunnelOnwards.cs new file mode 100644 index 0000000..ba68685 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/TunnelOnwards.cs @@ -0,0 +1,92 @@ +using System.Collections.Generic; + +namespace Ink.Parsed +{ + public class TunnelOnwards : Parsed.Object + { + public Divert divertAfter { + get { + return _divertAfter; + } + set { + _divertAfter = value; + if (_divertAfter) AddContent (_divertAfter); + } + } + Divert _divertAfter; + + public override Runtime.Object GenerateRuntimeObject () + { + var container = new Runtime.Container (); + + // Set override path for tunnel onwards (or nothing) + container.AddContent (Runtime.ControlCommand.EvalStart ()); + + if (divertAfter) { + + // Generate runtime object's generated code and steal the arguments runtime code + var returnRuntimeObj = divertAfter.GenerateRuntimeObject (); + var returnRuntimeContainer = returnRuntimeObj as Runtime.Container; + if (returnRuntimeContainer) { + + // Steal all code for generating arguments from the divert + var args = divertAfter.arguments; + if (args != null && args.Count > 0) { + + // Steal everything betwen eval start and eval end + int evalStart = -1; + int evalEnd = -1; + for (int i = 0; i < returnRuntimeContainer.content.Count; i++) { + var cmd = returnRuntimeContainer.content [i] as Runtime.ControlCommand; + if (cmd) { + if (evalStart == -1 && cmd.commandType == Runtime.ControlCommand.CommandType.EvalStart) + evalStart = i; + else if (cmd.commandType == Runtime.ControlCommand.CommandType.EvalEnd) + evalEnd = i; + } + } + + for (int i = evalStart + 1; i < evalEnd; i++) { + var obj = returnRuntimeContainer.content [i]; + obj.parent = null; // prevent error of being moved between owners + container.AddContent (returnRuntimeContainer.content [i]); + } + } + } + + // Supply the divert target for the tunnel onwards target, either variable or more commonly, the explicit name + var returnDivertObj = returnRuntimeObj as Runtime.Divert; + if( returnDivertObj != null && returnDivertObj.hasVariableTarget ) { + var runtimeVarRef = new Runtime.VariableReference (returnDivertObj.variableDivertName); + container.AddContent(runtimeVarRef); + } else { + _overrideDivertTarget = new Runtime.DivertTargetValue (); + container.AddContent (_overrideDivertTarget); + } + + } + + // No divert after tunnel onwards + else { + container.AddContent (new Runtime.Void ()); + } + + container.AddContent (Runtime.ControlCommand.EvalEnd ()); + + container.AddContent (Runtime.ControlCommand.PopTunnel ()); + + return container; + } + + public override void ResolveReferences (Story context) + { + base.ResolveReferences (context); + + if (divertAfter && divertAfter.targetContent) + _overrideDivertTarget.targetPath = divertAfter.targetContent.runtimePath; + } + + Runtime.DivertTargetValue _overrideDivertTarget; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/VariableAssignment.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/VariableAssignment.cs new file mode 100644 index 0000000..34e281e --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/VariableAssignment.cs @@ -0,0 +1,123 @@ +using System.Collections.Generic; + +namespace Ink.Parsed +{ + public class VariableAssignment : Parsed.Object + { + public string variableName + { + get { return variableIdentifier.name; } + } + public Identifier variableIdentifier { get; protected set; } + public Expression expression { get; protected set; } + public ListDefinition listDefinition { get; protected set; } + + public bool isGlobalDeclaration { get; set; } + public bool isNewTemporaryDeclaration { get; set; } + + public bool isDeclaration { + get { + return isGlobalDeclaration || isNewTemporaryDeclaration; + } + } + + public VariableAssignment (Identifier identifier, Expression assignedExpression) + { + this.variableIdentifier = identifier; + + // Defensive programming in case parsing of assignedExpression failed + if( assignedExpression ) + this.expression = AddContent(assignedExpression); + } + + public VariableAssignment (Identifier identifier, ListDefinition listDef) + { + this.variableIdentifier = identifier; + + if (listDef) { + this.listDefinition = AddContent (listDef); + this.listDefinition.variableAssignment = this; + } + + // List definitions are always global + isGlobalDeclaration = true; + } + + public override Runtime.Object GenerateRuntimeObject () + { + FlowBase newDeclScope = null; + if (isGlobalDeclaration) { + newDeclScope = story; + } else if(isNewTemporaryDeclaration) { + newDeclScope = ClosestFlowBase (); + } + + if( newDeclScope ) + newDeclScope.TryAddNewVariableDeclaration (this); + + // Global declarations don't generate actual procedural + // runtime objects, but instead add a global variable to the story itself. + // The story then initialises them all in one go at the start of the game. + if( isGlobalDeclaration ) + return null; + + var container = new Runtime.Container (); + + // The expression's runtimeObject is actually another nested container + if( expression != null ) + container.AddContent (expression.runtimeObject); + else if( listDefinition != null ) + container.AddContent (listDefinition.runtimeObject); + + _runtimeAssignment = new Runtime.VariableAssignment(variableName, isNewTemporaryDeclaration); + container.AddContent (_runtimeAssignment); + + return container; + } + + public override void ResolveReferences (Story context) + { + base.ResolveReferences (context); + + // List definitions are checked for conflicts separately + if( this.isDeclaration && listDefinition == null ) + context.CheckForNamingCollisions (this, variableIdentifier, this.isGlobalDeclaration ? Story.SymbolType.Var : Story.SymbolType.Temp); + + // Initial VAR x = [intialValue] declaration, not re-assignment + if (this.isGlobalDeclaration) { + var variableReference = expression as VariableReference; + if (variableReference && !variableReference.isConstantReference && !variableReference.isListItemReference) { + Error ("global variable assignments cannot refer to other variables, only literal values, constants and list items"); + } + } + + if (!this.isNewTemporaryDeclaration) { + var resolvedVarAssignment = context.ResolveVariableWithName(this.variableName, fromNode: this); + if (!resolvedVarAssignment.found) { + if (story.constants.ContainsKey (variableName)) { + Error ("Can't re-assign to a constant (do you need to use VAR when declaring '" + this.variableName + "'?)", this); + } else { + Error ("Variable could not be found to assign to: '" + this.variableName + "'", this); + } + } + + // A runtime assignment may not have been generated if it's the initial global declaration, + // since these are hoisted out and handled specially in Story.ExportRuntime. + if( _runtimeAssignment != null ) + _runtimeAssignment.isGlobal = resolvedVarAssignment.isGlobal; + } + } + + + public override string typeName { + get { + if (isNewTemporaryDeclaration) return "temp"; + else if (isGlobalDeclaration) return "VAR"; + else return "variable assignment"; + } + } + + Runtime.VariableAssignment _runtimeAssignment; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/VariableReference.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/VariableReference.cs new file mode 100644 index 0000000..f0359aa --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/VariableReference.cs @@ -0,0 +1,152 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Ink.Parsed +{ + public class VariableReference : Expression + { + // - Normal variables have a single item in their "path" + // - Knot/stitch names for read counts are actual dot-separated paths + // (though this isn't actually used at time of writing) + // - List names are dot separated: listName.itemName (or just itemName) + public string name { get; private set; } + + public Identifier identifier { + get { + // Merging the list of identifiers into a single identifier. + // Debug metadata is also merged. + if (pathIdentifiers == null || pathIdentifiers.Count == 0) { + return null; + } + + if( _singleIdentifier == null ) { + var name = string.Join (".", path.ToArray()); + var firstDebugMetadata = pathIdentifiers.First().debugMetadata; + var debugMetadata = pathIdentifiers.Aggregate(firstDebugMetadata, (acc, id) => acc.Merge(id.debugMetadata)); + _singleIdentifier = new Identifier { name = name, debugMetadata = debugMetadata }; + } + + return _singleIdentifier; + } + } + Identifier _singleIdentifier; + + public List pathIdentifiers; + public List path { get; private set; } + + // Only known after GenerateIntoContainer has run + public bool isConstantReference; + public bool isListItemReference; + + public Runtime.VariableReference runtimeVarRef { get { return _runtimeVarRef; } } + + public VariableReference (List pathIdentifiers) + { + this.pathIdentifiers = pathIdentifiers; + this.path = pathIdentifiers.Select(id => id?.name).ToList(); + this.name = string.Join (".", pathIdentifiers); + } + + public override void GenerateIntoContainer (Runtime.Container container) + { + Expression constantValue = null; + + // If it's a constant reference, just generate the literal expression value + // It's okay to access the constants at code generation time, since the + // first thing the ExportRuntime function does it search for all the constants + // in the story hierarchy, so they're all available. + if ( story.constants.TryGetValue (name, out constantValue) ) { + constantValue.GenerateConstantIntoContainer (container); + isConstantReference = true; + return; + } + + _runtimeVarRef = new Runtime.VariableReference (name); + + // List item reference? + // Path might be to a list (listName.listItemName or just listItemName) + if (path.Count == 1 || path.Count == 2) { + string listItemName = null; + string listName = null; + + if (path.Count == 1) listItemName = path [0]; + else { + listName = path [0]; + listItemName = path [1]; + } + + var listItem = story.ResolveListItem (listName, listItemName, this); + if (listItem) { + isListItemReference = true; + } + } + + container.AddContent (_runtimeVarRef); + } + + public override void ResolveReferences (Story context) + { + base.ResolveReferences (context); + + // Work is already done if it's a constant or list item reference + if (isConstantReference || isListItemReference) { + return; + } + + // Is it a read count? + var parsedPath = new Path (pathIdentifiers); + Parsed.Object targetForCount = parsedPath.ResolveFromContext (this); + if (targetForCount) { + + targetForCount.containerForCounting.visitsShouldBeCounted = true; + + // If this is an argument to a function that wants a variable to be + // passed by reference, then the Parsed.Divert will have generated a + // Runtime.VariablePointerValue instead of allowing this object + // to generate its RuntimeVariableReference. This only happens under + // error condition since we shouldn't be passing a read count by + // reference, but we don't want it to crash! + if (_runtimeVarRef == null) return; + + _runtimeVarRef.pathForCount = targetForCount.runtimePath; + _runtimeVarRef.name = null; + + // Check for very specific writer error: getting read count and + // printing it as content rather than as a piece of logic + // e.g. Writing {myFunc} instead of {myFunc()} + var targetFlow = targetForCount as FlowBase; + if (targetFlow && targetFlow.isFunction) { + + // Is parent context content rather than logic? + if ( parent is Weave || parent is ContentList || parent is FlowBase) { + Warning ("'" + targetFlow.identifier + "' being used as read count rather than being called as function. Perhaps you intended to write " + targetFlow.name + "()"); + } + } + + return; + } + + // Couldn't find this multi-part path at all, whether as a divert + // target or as a list item reference. + if (path.Count > 1) { + var errorMsg = "Could not find target for read count: " + parsedPath; + if (path.Count <= 2) + errorMsg += ", or couldn't find list item with the name " + string.Join (",", path.ToArray()); + Error (errorMsg); + return; + } + + if (!context.ResolveVariableWithName (this.name, fromNode: this).found) { + Error("Unresolved variable: "+this.ToString(), this); + } + } + + public override string ToString () + { + return string.Join(".", path.ToArray()); + } + + Runtime.VariableReference _runtimeVarRef; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Weave.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Weave.cs new file mode 100644 index 0000000..42048e1 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Weave.cs @@ -0,0 +1,730 @@ +using System.Collections.Generic; + +namespace Ink.Parsed +{ + // Used by the FlowBase when constructing the weave flow from + // a flat list of content objects. + public class Weave : Parsed.Object + { + // Containers can be chained as multiple gather points + // get created as the same indentation level. + // rootContainer is always the first in the chain, while + // currentContainer is the latest. + public Runtime.Container rootContainer { + get { + if (_rootContainer == null) { + GenerateRuntimeObject (); + } + + return _rootContainer; + } + } + Runtime.Container currentContainer { get; set; } + + public int baseIndentIndex { get; private set; } + + // Loose ends are: + // - Choices or Gathers that need to be joined up + // - Explicit Divert to gather points (i.e. "->" without a target) + public List looseEnds; + + public List gatherPointsToResolve; + public class GatherPointToResolve + { + public Runtime.Divert divert; + public Runtime.Object targetRuntimeObj; + } + + public Parsed.Object lastParsedSignificantObject + { + get { + if (content.Count == 0) return null; + + // Don't count extraneous newlines or VAR/CONST declarations, + // since they're "empty" statements outside of the main flow. + Parsed.Object lastObject = null; + for (int i = content.Count - 1; i >= 0; --i) { + lastObject = content [i]; + + var lastText = lastObject as Parsed.Text; + if (lastText && lastText.text == "\n") { + continue; + } + + if (IsGlobalDeclaration (lastObject)) + continue; + + break; + } + + var lastWeave = lastObject as Weave; + if (lastWeave) + lastObject = lastWeave.lastParsedSignificantObject; + + return lastObject; + } + } + + public Weave(List cont, int indentIndex=-1) + { + if (indentIndex == -1) { + baseIndentIndex = DetermineBaseIndentationFromContent (cont); + } else { + baseIndentIndex = indentIndex; + } + + AddContent (cont); + + ConstructWeaveHierarchyFromIndentation (); + } + + public void ResolveWeavePointNaming () + { + var namedWeavePoints = FindAll (w => !string.IsNullOrEmpty (w.name)); + + _namedWeavePoints = new Dictionary (); + + foreach (var weavePoint in namedWeavePoints) { + + // Check for weave point naming collisions + IWeavePoint existingWeavePoint; + if (_namedWeavePoints.TryGetValue (weavePoint.name, out existingWeavePoint)) { + var typeName = existingWeavePoint is Gather ? "gather" : "choice"; + var existingObj = (Parsed.Object)existingWeavePoint; + + Error ("A " + typeName + " with the same label name '" + weavePoint.name + "' already exists in this context on line " + existingObj.debugMetadata.startLineNumber, (Parsed.Object)weavePoint); + } + + _namedWeavePoints [weavePoint.name] = weavePoint; + } + } + + void ConstructWeaveHierarchyFromIndentation() + { + // Find nested indentation and convert to a proper object hierarchy + // (i.e. indented content is replaced with a Weave object that contains + // that nested content) + int contentIdx = 0; + while (contentIdx < content.Count) { + + Parsed.Object obj = content [contentIdx]; + + // Choice or Gather + if (obj is IWeavePoint) { + var weavePoint = (IWeavePoint)obj; + var weaveIndentIdx = weavePoint.indentationDepth - 1; + + // Inner level indentation - recurse + if (weaveIndentIdx > baseIndentIndex) { + + // Step through content until indent jumps out again + int innerWeaveStartIdx = contentIdx; + while (contentIdx < content.Count) { + var innerWeaveObj = content [contentIdx] as IWeavePoint; + if (innerWeaveObj != null) { + var innerIndentIdx = innerWeaveObj.indentationDepth - 1; + if (innerIndentIdx <= baseIndentIndex) { + break; + } + } + + contentIdx++; + } + + int weaveContentCount = contentIdx - innerWeaveStartIdx; + + var weaveContent = content.GetRange (innerWeaveStartIdx, weaveContentCount); + content.RemoveRange (innerWeaveStartIdx, weaveContentCount); + + var weave = new Weave (weaveContent, weaveIndentIdx); + InsertContent (innerWeaveStartIdx, weave); + + // Continue iteration from this point + contentIdx = innerWeaveStartIdx; + } + + } + + contentIdx++; + } + } + + // When the indentation wasn't told to us at construction time using + // a choice point with a known indentation level, we may be told to + // determine the indentation level by incrementing from our closest ancestor. + public int DetermineBaseIndentationFromContent(List contentList) + { + foreach (var obj in contentList) { + if (obj is IWeavePoint) { + return ((IWeavePoint)obj).indentationDepth - 1; + } + } + + // No weave points, so it doesn't matter + return 0; + } + + public override Runtime.Object GenerateRuntimeObject () + { + _rootContainer = currentContainer = new Runtime.Container(); + looseEnds = new List (); + + gatherPointsToResolve = new List (); + + // Iterate through content for the block at this level of indentation + // - Normal content is nested under Choices and Gathers + // - Blocks that are further indented cause recursion + // - Keep track of loose ends so that they can be diverted to Gathers + foreach(var obj in content) { + + // Choice or Gather + if (obj is IWeavePoint) { + AddRuntimeForWeavePoint ((IWeavePoint)obj); + } + + // Non-weave point + else { + + // Nested weave + if (obj is Weave) { + var weave = (Weave)obj; + AddRuntimeForNestedWeave (weave); + gatherPointsToResolve.AddRange (weave.gatherPointsToResolve); + } + + // Other object + // May be complex object that contains statements - e.g. a multi-line conditional + else { + AddGeneralRuntimeContent (obj.runtimeObject); + } + } + } + + // Pass any loose ends up the hierarhcy + PassLooseEndsToAncestors(); + + return _rootContainer; + } + + // Found gather point: + // - gather any loose ends + // - set the gather as the main container to dump new content in + void AddRuntimeForGather(Gather gather) + { + // Determine whether this Gather should be auto-entered: + // - It is auto-entered if there were no choices in the last section + // - A section is "since the previous gather" - so reset now + bool autoEnter = !hasSeenChoiceInSection; + hasSeenChoiceInSection = false; + + var gatherContainer = gather.runtimeContainer; + + if (gather.name == null) { + // Use disallowed character so it's impossible to have a name collision + gatherContainer.name = "g-" + _unnamedGatherCount; + _unnamedGatherCount++; + } + + // Auto-enter: include in main content + if (autoEnter) { + currentContainer.AddContent (gatherContainer); + } + + // Don't auto-enter: + // Add this gather to the main content, but only accessible + // by name so that it isn't stepped into automatically, but only via + // a divert from a loose end. + else { + _rootContainer.AddToNamedContentOnly (gatherContainer); + } + + // Consume loose ends: divert them to this gather + foreach (IWeavePoint looseEndWeavePoint in looseEnds) { + + var looseEnd = (Parsed.Object)looseEndWeavePoint; + + // Skip gather loose ends that are at the same level + // since they'll be handled by the auto-enter code below + // that only jumps into the gather if (current runtime choices == 0) + if (looseEnd is Gather) { + var prevGather = (Gather)looseEnd; + if (prevGather.indentationDepth == gather.indentationDepth) { + continue; + } + } + + Runtime.Divert divert = null; + + if (looseEnd is Parsed.Divert) { + divert = (Runtime.Divert) looseEnd.runtimeObject; + } else { + divert = new Runtime.Divert (); + var looseWeavePoint = looseEnd as IWeavePoint; + looseWeavePoint.runtimeContainer.AddContent (divert); + } + + // Pass back knowledge of this loose end being diverted + // to the FlowBase so that it can maintain a list of them, + // and resolve the divert references later + gatherPointsToResolve.Add (new GatherPointToResolve{ divert = divert, targetRuntimeObj = gatherContainer }); + } + looseEnds.Clear (); + + // Replace the current container itself + currentContainer = gatherContainer; + } + + void AddRuntimeForWeavePoint(IWeavePoint weavePoint) + { + // Current level Gather + if (weavePoint is Gather) { + AddRuntimeForGather ((Gather)weavePoint); + } + + // Current level choice + else if (weavePoint is Choice) { + + // Gathers that contain choices are no longer loose ends + // (same as when weave points get nested content) + if (previousWeavePoint is Gather) { + looseEnds.Remove (previousWeavePoint); + } + + // Add choice point content + var choice = (Choice)weavePoint; + currentContainer.AddContent (choice.runtimeObject); + + // Add choice's inner content to self + choice.innerContentContainer.name = "c-" + _choiceCount; + currentContainer.AddToNamedContentOnly (choice.innerContentContainer); + _choiceCount++; + + hasSeenChoiceInSection = true; + } + + // Keep track of loose ends + addContentToPreviousWeavePoint = false; // default + if (WeavePointHasLooseEnd (weavePoint)) { + looseEnds.Add (weavePoint); + + + var looseChoice = weavePoint as Choice; + if (looseChoice) { + addContentToPreviousWeavePoint = true; + } + } + previousWeavePoint = weavePoint; + } + + // Add nested block at a greater indentation level + public void AddRuntimeForNestedWeave(Weave nestedResult) + { + // Add this inner block to current container + // (i.e. within the main container, or within the last defined Choice/Gather) + AddGeneralRuntimeContent (nestedResult.rootContainer); + + // Now there's a deeper indentation level, the previous weave point doesn't + // count as a loose end (since it will have content to go to) + if (previousWeavePoint != null) { + looseEnds.Remove (previousWeavePoint); + addContentToPreviousWeavePoint = false; + } + } + + // Normal content gets added into the latest Choice or Gather by default, + // unless there hasn't been one yet. + void AddGeneralRuntimeContent(Runtime.Object content) + { + // Content is allowed to evaluate runtimeObject to null + // (e.g. AuthorWarning, which doesn't make it into the runtime) + if (content == null) + return; + + if (addContentToPreviousWeavePoint) { + previousWeavePoint.runtimeContainer.AddContent (content); + } else { + currentContainer.AddContent (content); + } + } + + void PassLooseEndsToAncestors() + { + if (looseEnds.Count == 0) return; + + // Search for Weave ancestor to pass loose ends to for gathering. + // There are two types depending on whether the current weave + // is separated by a conditional or sequence. + // - An "inner" weave is one that is directly connected to the current + // weave - i.e. you don't have to pass through a conditional or + // sequence to get to it. We're allowed to pass all loose ends to + // one of these. + // - An "outer" weave is one that is outside of a conditional/sequence + // that the current weave is nested within. We're only allowed to + // pass gathers (i.e. 'normal flow') loose ends up there, not normal + // choices. The rule is that choices have to be diverted explicitly + // by the author since it's ambiguous where flow should go otherwise. + // + // e.g.: + // + // - top <- e.g. outer weave + // {true: + // * choice <- e.g. inner weave + // * * choice 2 + // more content <- e.g. current weave + // * choice 2 + // } + // - more of outer weave + // + Weave closestInnerWeaveAncestor = null; + Weave closestOuterWeaveAncestor = null; + + // Find inner and outer ancestor weaves as defined above. + bool nested = false; + for (var ancestor = this.parent; ancestor != null; ancestor = ancestor.parent) + { + + // Found ancestor? + var weaveAncestor = ancestor as Weave; + if (weaveAncestor != null) + { + if (!nested && closestInnerWeaveAncestor == null) + closestInnerWeaveAncestor = weaveAncestor; + + if (nested && closestOuterWeaveAncestor == null) + closestOuterWeaveAncestor = weaveAncestor; + } + + + // Weaves nested within Sequences or Conditionals are + // "sealed" - any loose ends require explicit diverts. + if (ancestor is Sequence || ancestor is Conditional) + nested = true; + } + + // No weave to pass loose ends to at all? + if (closestInnerWeaveAncestor == null && closestOuterWeaveAncestor == null) + return; + + // Follow loose end passing logic as defined above + for (int i = looseEnds.Count - 1; i >= 0; i--) { + var looseEnd = looseEnds[i]; + + bool received = false; + + // This weave is nested within a conditional or sequence: + // - choices can only be passed up to direct ancestor ("inner") weaves + // - gathers can be passed up to either, but favour the closer (inner) weave + // if there is one + if(nested) { + if( looseEnd is Choice && closestInnerWeaveAncestor != null) { + closestInnerWeaveAncestor.ReceiveLooseEnd(looseEnd); + received = true; + } + + else if( !(looseEnd is Choice) ) { + var receivingWeave = closestInnerWeaveAncestor ?? closestOuterWeaveAncestor; + if(receivingWeave != null) { + receivingWeave.ReceiveLooseEnd(looseEnd); + received = true; + } + } + } + + // No nesting, all loose ends can be safely passed up + else { + closestInnerWeaveAncestor.ReceiveLooseEnd(looseEnd); + received = true; + } + + if(received) looseEnds.RemoveAt(i); + } + } + + void ReceiveLooseEnd(IWeavePoint childWeaveLooseEnd) + { + looseEnds.Add(childWeaveLooseEnd); + } + + public override void ResolveReferences(Story context) + { + base.ResolveReferences (context); + + // Check that choices nested within conditionals and sequences are terminated + if( looseEnds != null && looseEnds.Count > 0 ) { + var isNestedWeave = false; + for (var ancestor = this.parent; ancestor != null; ancestor = ancestor.parent) + { + if (ancestor is Sequence || ancestor is Conditional) + { + isNestedWeave = true; + break; + } + } + if (isNestedWeave) + { + ValidateTermination(BadNestedTerminationHandler); + } + } + + foreach(var gatherPoint in gatherPointsToResolve) { + gatherPoint.divert.targetPath = gatherPoint.targetRuntimeObj.path; + } + + CheckForWeavePointNamingCollisions (); + } + + public IWeavePoint WeavePointNamed(string name) + { + if (_namedWeavePoints == null) + return null; + + IWeavePoint weavePointResult = null; + if (_namedWeavePoints.TryGetValue (name, out weavePointResult)) + return weavePointResult; + + return null; + } + + // Global VARs and CONSTs are treated as "outside of the flow" + // when iterating over content that follows loose ends + bool IsGlobalDeclaration (Parsed.Object obj) + { + + var varAss = obj as VariableAssignment; + if (varAss && varAss.isGlobalDeclaration && varAss.isDeclaration) + return true; + + var constDecl = obj as ConstantDeclaration; + if (constDecl) + return true; + + return false; + } + + // While analysing final loose ends, we look to see whether there + // are any diverts etc which choices etc divert from + IEnumerable ContentThatFollowsWeavePoint (IWeavePoint weavePoint) + { + var obj = (Parsed.Object)weavePoint; + + // Inner content first (e.g. for a choice) + if (obj.content != null) { + foreach (var contentObj in obj.content) { + + // Global VARs and CONSTs are treated as "outside of the flow" + if (IsGlobalDeclaration (contentObj)) continue; + + yield return contentObj; + } + } + + + var parentWeave = obj.parent as Weave; + if (parentWeave == null) { + throw new System.Exception ("Expected weave point parent to be weave?"); + } + + var weavePointIdx = parentWeave.content.IndexOf (obj); + + for (int i = weavePointIdx+1; i < parentWeave.content.Count; i++) { + var laterObj = parentWeave.content [i]; + + // Global VARs and CONSTs are treated as "outside of the flow" + if (IsGlobalDeclaration (laterObj)) continue; + + // End of the current flow + if (laterObj is IWeavePoint) + break; + + // Other weaves will be have their own loose ends + if (laterObj is Weave) + break; + + yield return laterObj; + } + } + + public delegate void BadTerminationHandler (Parsed.Object terminatingObj); + public void ValidateTermination (BadTerminationHandler badTerminationHandler) + { + // Don't worry if the last object in the flow is a "TODO", + // even if there are other loose ends in other places + if (lastParsedSignificantObject is AuthorWarning) { + return; + } + + // By now, any sub-weaves will have passed loose ends up to the root weave (this). + // So there are 2 possible situations: + // - There are loose ends from somewhere in the flow. + // These aren't necessarily "real" loose ends - they're weave points + // that don't connect to any lower weave points, so we just + // have to check that they terminate properly. + // - This weave is just a list of content with no actual weave points, + // so we just need to check that the list of content terminates. + + bool hasLooseEnds = looseEnds != null && looseEnds.Count > 0; + + if (hasLooseEnds) { + foreach (var looseEnd in looseEnds) { + var looseEndFlow = ContentThatFollowsWeavePoint (looseEnd); + ValidateFlowOfObjectsTerminates (looseEndFlow, (Parsed.Object)looseEnd, badTerminationHandler); + } + } + + // No loose ends... is there any inner weaving at all? + // If not, make sure the single content stream is terminated correctly + else { + + // If there's any actual weaving, assume that content is + // terminated correctly since we would've had a loose end otherwise + foreach (var obj in content) { + if (obj is IWeavePoint) return; + } + + // Straight linear flow? Check it terminates + ValidateFlowOfObjectsTerminates (content, this, badTerminationHandler); + } + } + + void BadNestedTerminationHandler(Parsed.Object terminatingObj) + { + Conditional conditional = null; + for (var ancestor = terminatingObj.parent; ancestor != null; ancestor = ancestor.parent) { + if( ancestor is Sequence || ancestor is Conditional ) { + conditional = ancestor as Conditional; + break; + } + } + + var errorMsg = "Choices nested in conditionals or sequences need to explicitly divert afterwards."; + + // Tutorialise proper choice syntax if this looks like a single choice within a condition, e.g. + // { condition: + // * choice + // } + if (conditional != null) { + var numChoices = conditional.FindAll().Count; + if( numChoices == 1 ) { + errorMsg = "Choices with conditions should be written: '* {condition} choice'. Otherwise, "+ errorMsg.ToLower(); + } + } + + Error(errorMsg, terminatingObj); + } + + void ValidateFlowOfObjectsTerminates (IEnumerable objFlow, Parsed.Object defaultObj, BadTerminationHandler badTerminationHandler) + { + bool terminated = false; + Parsed.Object terminatingObj = defaultObj; + foreach (var flowObj in objFlow) { + + var divert = flowObj.Find (d => !d.isThread && !d.isTunnel && !d.isFunctionCall && !(d.parent is DivertTarget)); + if (divert != null) { + terminated = true; + } + + if (flowObj.Find () != null) { + terminated = true; + break; + } + + terminatingObj = flowObj; + } + + + if (!terminated) { + + // Author has left a note to self here - clearly we don't need + // to leave them with another warning since they know what they're doing. + if (terminatingObj is AuthorWarning) { + return; + } + + badTerminationHandler (terminatingObj); + } + } + + bool WeavePointHasLooseEnd(IWeavePoint weavePoint) + { + // No content, must be a loose end. + if (weavePoint.content == null) return true; + + // If a weave point is diverted from, it doesn't have a loose end. + // Detect a divert object within a weavePoint's main content + // Work backwards since we're really interested in the end, + // although it doesn't actually make a difference! + // (content after a divert will simply be inaccessible) + for (int i = weavePoint.content.Count - 1; i >= 0; --i) { + var innerDivert = weavePoint.content [i] as Divert; + if (innerDivert) { + bool willReturn = innerDivert.isThread || innerDivert.isTunnel || innerDivert.isFunctionCall; + if (!willReturn) return false; + } + } + + return true; + } + + // Enforce rule that weave points must not have the same + // name as any stitches or knots upwards in the hierarchy + void CheckForWeavePointNamingCollisions() + { + if (_namedWeavePoints == null) + return; + + var ancestorFlows = new List (); + foreach (var obj in this.ancestry) { + var flow = obj as FlowBase; + if (flow) + ancestorFlows.Add (flow); + else + break; + } + + + foreach (var namedWeavePointPair in _namedWeavePoints) { + var weavePointName = namedWeavePointPair.Key; + var weavePoint = (Parsed.Object) namedWeavePointPair.Value; + + foreach(var flow in ancestorFlows) { + + // Shallow search + var otherContentWithName = flow.ContentWithNameAtLevel (weavePointName); + + if (otherContentWithName && otherContentWithName != weavePoint) { + var errorMsg = string.Format ("{0} '{1}' has the same label name as a {2} (on {3})", + weavePoint.GetType().Name, + weavePointName, + otherContentWithName.GetType().Name, + otherContentWithName.debugMetadata); + + Error(errorMsg, (Parsed.Object) weavePoint); + } + + } + } + } + + // Keep track of previous weave point (Choice or Gather) + // at the current indentation level: + // - to add ordinary content to be nested under it + // - to add nested content under it when it's indented + // - to remove it from the list of loose ends when + // - it has indented content since it's no longer a loose end + // - it's a gather and it has a choice added to it + IWeavePoint previousWeavePoint = null; + bool addContentToPreviousWeavePoint = false; + + // Used for determining whether the next Gather should auto-enter + bool hasSeenChoiceInSection = false; + + int _unnamedGatherCount; + + int _choiceCount; + + + Runtime.Container _rootContainer; + Dictionary _namedWeavePoints; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Wrap.cs b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Wrap.cs new file mode 100644 index 0000000..8b9b2b5 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/ParsedHierarchy/Wrap.cs @@ -0,0 +1,28 @@ + +namespace Ink.Parsed +{ + public class Wrap : Parsed.Object where T : Runtime.Object + { + public Wrap (T objToWrap) + { + _objToWrap = objToWrap; + } + + public override Runtime.Object GenerateRuntimeObject () + { + return _objToWrap; + } + + T _objToWrap; + } + + // Shorthand for writing Parsed.Wrap and Parsed.Wrap + public class Glue : Wrap { + public Glue (Runtime.Glue glue) : base(glue) {} + } + public class LegacyTag : Wrap { + public LegacyTag (Runtime.Tag tag) : base (tag) { } + } + +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/Plugins/Plugin.cs b/Assets/Ink/InkLibs/InkCompiler/Plugins/Plugin.cs new file mode 100644 index 0000000..0a54e57 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/Plugins/Plugin.cs @@ -0,0 +1,21 @@ +using System; + +namespace Ink +{ + public interface IPlugin + { + // Hooks: if in doubt use PostExport, since the parsedStory is in a more finalised state. + + void PreParse(ref string storyContent); + + // Hook for immediately after the story has been parsed into its basic Parsed hierarchy. + // Could be useful for modifying the story before it's exported. + void PostParse(ref Parsed.Story parsedStory); + + // Hook for after parsed story has been converted into its runtime equivalent. Note that + // during this process the parsed story will have changed structure too, to take into + // account analysis of the structure of Weave, for example. + void PostExport(Parsed.Story parsedStory, ref Runtime.Story runtimeStory); + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/Plugins/PluginManager.cs b/Assets/Ink/InkLibs/InkCompiler/Plugins/PluginManager.cs new file mode 100644 index 0000000..fa3f42e --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/Plugins/PluginManager.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; + +namespace Ink +{ + public class PluginManager + { + public PluginManager (List pluginDirectories) + { + _plugins = new List (); + + foreach (string pluginName in pluginDirectories) + { + foreach (string file in Directory.GetFiles(pluginName, "*.dll")) + { + foreach (Type type in Assembly.LoadFile(Path.GetFullPath(file)).GetExportedTypes()) + { + if (typeof(IPlugin).IsAssignableFrom(type)) + { + _plugins.Add((IPlugin)Activator.CreateInstance(type)); + } + } + } + } + } + + public string PreParse(string storyContent) + { + object[] args = new object[] { storyContent }; + + foreach (var plugin in _plugins) + { + typeof(IPlugin).InvokeMember("PreParse", BindingFlags.InvokeMethod, null, plugin, args); + } + + return (string)args[0]; + } + + public Parsed.Story PostParse(Parsed.Story parsedStory) + { + object[] args = new object[] { parsedStory }; + + foreach (var plugin in _plugins) + { + typeof(IPlugin).InvokeMember("PostParse", BindingFlags.InvokeMethod, null, plugin, args); + } + + return (Parsed.Story)args[0]; + } + + public Runtime.Story PostExport(Parsed.Story parsedStory, Runtime.Story runtimeStory) + { + object[] args = new object[] { parsedStory, runtimeStory }; + + foreach (var plugin in _plugins) + { + typeof(IPlugin).InvokeMember("PostExport", BindingFlags.InvokeMethod, null, plugin, args); + } + + return (Runtime.Story)args[1]; + } + + List _plugins; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/Stats.cs b/Assets/Ink/InkLibs/InkCompiler/Stats.cs new file mode 100644 index 0000000..2f5d566 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/Stats.cs @@ -0,0 +1,68 @@ + +namespace Ink { + public struct Stats { + + public int words; + public int knots; + public int stitches; + public int functions; + public int choices; + public int gathers; + public int diverts; + + public static Stats Generate(Ink.Parsed.Story story) { + var stats = new Stats(); + + var allText = story.FindAll(); + + // Count all the words across all strings + stats.words = 0; + foreach(var text in allText) { + + var wordsInThisStr = 0; + var wasWhiteSpace = true; + foreach(var c in text.text) { + if( c == ' ' || c == '\t' || c == '\n' || c == '\r' ) { + wasWhiteSpace = true; + } else if( wasWhiteSpace ) { + wordsInThisStr++; + wasWhiteSpace = false; + } + } + + stats.words += wordsInThisStr; + } + + var knots = story.FindAll(); + stats.knots = knots.Count; + + stats.functions = 0; + foreach(var knot in knots) + if (knot.isFunction) stats.functions++; + + var stitches = story.FindAll(); + stats.stitches = stitches.Count; + + var choices = story.FindAll(); + stats.choices = choices.Count; + + // Skip implicit gather that's generated at top of story + // (we know which it is because it isn't assigned debug metadata) + var gathers = story.FindAll(g => g.debugMetadata != null); + stats.gathers = gathers.Count; + + // May not be entirely what you expect. + // Does it nevertheless have value? + // Includes: + // - DONE, END + // - Function calls + // - Some implicitly generated weave diverts + // But we subtract one for the implicit DONE + // at the end of the main flow outside of knots. + var diverts = story.FindAll(); + stats.diverts = diverts.Count - 1; + + return stats; + } + } +} \ No newline at end of file diff --git a/Assets/Ink/InkLibs/InkCompiler/StringParser/StringParser.cs b/Assets/Ink/InkLibs/InkCompiler/StringParser/StringParser.cs new file mode 100644 index 0000000..6feed54 --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/StringParser/StringParser.cs @@ -0,0 +1,685 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Diagnostics; +using System.Text; + +namespace Ink +{ + public class StringParser + { + public delegate object ParseRule(); + + public delegate T SpecificParseRule() where T : class; + + public delegate void ErrorHandler(string message, int index, int lineIndex, bool isWarning); + + public StringParser (string str) + { + str = PreProcessInputString (str); + + state = new StringParserState(); + + if (str != null) { + _chars = str.ToCharArray (); + } else { + _chars = new char[0]; + } + + inputString = str; + } + + public class ParseSuccessStruct {}; + public static ParseSuccessStruct ParseSuccess = new ParseSuccessStruct(); + + public static CharacterSet numbersCharacterSet = new CharacterSet("0123456789"); + + protected ErrorHandler errorHandler { get; set; } + + public char currentCharacter + { + get + { + if (index >= 0 && remainingLength > 0) { + return _chars [index]; + } else { + return (char)0; + } + } + } + + public StringParserState state { get; private set; } + + public bool hadError { get; protected set; } + + // Don't do anything by default, but provide ability for subclasses + // to manipulate the string before it's used as input (converted to a char array) + protected virtual string PreProcessInputString(string str) + { + return str; + } + + //-------------------------------- + // Parse state + //-------------------------------- + + protected int BeginRule() + { + return state.Push (); + } + + protected object FailRule(int expectedRuleId) + { + state.Pop (expectedRuleId); + return null; + } + + protected void CancelRule(int expectedRuleId) + { + state.Pop (expectedRuleId); + } + + protected object SucceedRule(int expectedRuleId, object result = null) + { + // Get state at point where this rule stared evaluating + var stateAtSucceedRule = state.Peek(expectedRuleId); + var stateAtBeginRule = state.PeekPenultimate (); + + + // Allow subclass to receive callback + RuleDidSucceed (result, stateAtBeginRule, stateAtSucceedRule); + + // Flatten state stack so that we maintain the same values, + // but remove one level in the stack. + state.Squash(); + + if (result == null) { + result = ParseSuccess; + } + + return result; + } + + protected virtual void RuleDidSucceed(object result, StringParserState.Element startState, StringParserState.Element endState) + { + + } + + protected object Expect(ParseRule rule, string message = null, ParseRule recoveryRule = null) + { + object result = ParseObject(rule); + if (result == null) { + if (message == null) { + message = rule.Method.Name; + } + + string butSaw; + string lineRemainder = LineRemainder (); + if (lineRemainder == null || lineRemainder.Length == 0) { + butSaw = "end of line"; + } else { + butSaw = "'" + lineRemainder + "'"; + } + + Error ("Expected "+message+" but saw "+butSaw); + + if (recoveryRule != null) { + result = recoveryRule (); + } + } + return result; + } + + protected void Error(string message, bool isWarning = false) + { + ErrorOnLine (message, lineIndex + 1, isWarning); + } + + protected void ErrorWithParsedObject(string message, Parsed.Object result, bool isWarning = false) + { + ErrorOnLine (message, result.debugMetadata.startLineNumber, isWarning); + } + + protected void ErrorOnLine(string message, int lineNumber, bool isWarning) + { + if ( !state.errorReportedAlreadyInScope ) { + + var errorType = isWarning ? "Warning" : "Error"; + + if (errorHandler == null) { + throw new System.Exception (errorType+" on line " + lineNumber + ": " + message); + } else { + errorHandler (message, index, lineNumber-1, isWarning); + } + + state.NoteErrorReported (); + } + + if( !isWarning ) + hadError = true; + } + + protected void Warning(string message) + { + Error(message, isWarning:true); + } + + public bool endOfInput + { + get { return index >= _chars.Length; } + } + + public string remainingString + { + get { + return new string(_chars, index, remainingLength); + } + } + + public string LineRemainder() + { + return (string) Peek (() => ParseUntilCharactersFromString ("\n\r")); + } + + public int remainingLength + { + get { + return _chars.Length - index; + } + } + + public string inputString { get; private set; } + + + public int lineIndex + { + set { + state.lineIndex = value; + } + get { + return state.lineIndex; + } + } + + public int characterInLineIndex + { + set { + state.characterInLineIndex = value; + } + get { + return state.characterInLineIndex; + } + } + + public int index + { + // If we want subclass parsers to be able to set the index directly, + // then we would need to know what the lineIndex of the new + // index would be - would we have to step through manually + // counting the newlines to do so? + private set { + state.characterIndex = value; + } + get { + return state.characterIndex; + } + } + + public void SetFlag(uint flag, bool trueOrFalse) { + if (trueOrFalse) { + state.customFlags |= flag; + } else { + state.customFlags &= ~flag; + } + } + + public bool GetFlag(uint flag) { + return (state.customFlags & flag) != 0; + } + + //-------------------------------- + // Structuring + //-------------------------------- + + public object ParseObject(ParseRule rule) + { + int ruleId = BeginRule (); + + var stackHeightBefore = state.stackHeight; + + var result = rule (); + + if (stackHeightBefore != state.stackHeight) { + throw new System.Exception ("Mismatched Begin/Fail/Succeed rules"); + } + + if (result == null) + return FailRule (ruleId); + + SucceedRule (ruleId, result); + return result; + } + + public T Parse(SpecificParseRule rule) where T : class + { + int ruleId = BeginRule (); + + var result = rule () as T; + if (result == null) { + FailRule (ruleId); + return null; + } + + SucceedRule (ruleId, result); + return result; + } + + public object OneOf(params ParseRule[] array) + { + foreach (ParseRule rule in array) { + object result = ParseObject(rule); + if (result != null) + return result; + } + + return null; + } + + public List OneOrMore(ParseRule rule) + { + var results = new List (); + + object result = null; + do { + result = ParseObject(rule); + if( result != null ) { + results.Add(result); + } + } while(result != null); + + if (results.Count > 0) { + return results; + } else { + return null; + } + } + + public ParseRule Optional(ParseRule rule) + { + return () => { + object result = ParseObject(rule); + if( result == null ) { + result = ParseSuccess; + } + return result; + }; + } + + // Return ParseSuccess instead the real result so that it gets excluded + // from result arrays (e.g. Interleave) + public ParseRule Exclude(ParseRule rule) + { + return () => { + object result = ParseObject(rule); + if( result == null ) { + return null; + } + return ParseSuccess; + }; + } + + // Combination of both of the above + public ParseRule OptionalExclude(ParseRule rule) + { + return () => { + ParseObject(rule); + return ParseSuccess; + }; + } + + // Convenience method for creating more readable ParseString rules that can be combined + // in other structuring rules (like OneOf etc) + // e.g. OneOf(String("one"), String("two")) + protected ParseRule String(string str) + { + return () => ParseString (str); + } + + private void TryAddResultToList(object result, List list, bool flatten = true) + { + if (result == ParseSuccess) { + return; + } + + if (flatten) { + var resultCollection = result as System.Collections.ICollection; + if (resultCollection != null) { + foreach (object obj in resultCollection) { + Debug.Assert (obj is T); + list.Add ((T)obj); + } + return; + } + } + + Debug.Assert (result is T); + list.Add ((T)result); + } + + + public List Interleave(ParseRule ruleA, ParseRule ruleB, ParseRule untilTerminator = null, bool flatten = true) + { + int ruleId = BeginRule (); + + var results = new List (); + + // First outer padding + var firstA = ParseObject(ruleA); + if (firstA == null) { + return (List) FailRule(ruleId); + } else { + TryAddResultToList(firstA, results, flatten); + } + + object lastMainResult = null, outerResult = null; + do { + + // "until" condition hit? + if( untilTerminator != null && Peek(untilTerminator) != null ) { + break; + } + + // Main inner + lastMainResult = ParseObject(ruleB); + if( lastMainResult == null ) { + break; + } else { + TryAddResultToList(lastMainResult, results, flatten); + } + + // Outer result (i.e. last A in ABA) + outerResult = null; + if( lastMainResult != null ) { + outerResult = ParseObject(ruleA); + if (outerResult == null) { + break; + } else { + TryAddResultToList(outerResult, results, flatten); + } + } + + // Stop if there are no results, or if both are the placeholder "ParseSuccess" (i.e. Optional success rather than a true value) + } while((lastMainResult != null || outerResult != null) + && !(lastMainResult == ParseSuccess && outerResult == ParseSuccess) && remainingLength > 0); + + if (results.Count == 0) { + return (List) FailRule(ruleId); + } + + return (List) SucceedRule(ruleId, results); + } + + //-------------------------------- + // Basic string parsing + //-------------------------------- + + public string ParseString(string str) + { + if (str.Length > remainingLength) { + return null; + } + + int ruleId = BeginRule (); + + // Optimisation from profiling: + // Store in temporary local variables + // since they're properties that would have to access + // the rule stack every time otherwise. + int i = index; + int cli = characterInLineIndex; + int li = lineIndex; + + bool success = true; + foreach (char c in str) { + if ( _chars[i] != c) { + success = false; + break; + } + if (c == '\n') { + li++; + cli = -1; + } + i++; + cli++; + } + + index = i; + characterInLineIndex = cli; + lineIndex = li; + + if (success) { + return (string) SucceedRule(ruleId, str); + } + else { + return (string) FailRule (ruleId); + } + } + + public char ParseSingleCharacter() + { + if (remainingLength > 0) { + char c = _chars [index]; + if (c == '\n') { + lineIndex++; + characterInLineIndex = -1; + } + index++; + characterInLineIndex++; + return c; + } else { + return (char)0; + } + } + + public string ParseUntilCharactersFromString(string str, int maxCount = -1) + { + return ParseCharactersFromString(str, false, maxCount); + } + + public string ParseUntilCharactersFromCharSet(CharacterSet charSet, int maxCount = -1) + { + return ParseCharactersFromCharSet(charSet, false, maxCount); + } + + public string ParseCharactersFromString(string str, int maxCount = -1) + { + return ParseCharactersFromString(str, true, maxCount); + } + + public string ParseCharactersFromString(string str, bool shouldIncludeStrChars, int maxCount = -1) + { + return ParseCharactersFromCharSet (new CharacterSet(str), shouldIncludeStrChars); + } + + public string ParseCharactersFromCharSet(CharacterSet charSet, bool shouldIncludeChars = true, int maxCount = -1) + { + if (maxCount == -1) { + maxCount = int.MaxValue; + } + + int startIndex = index; + + // Optimisation from profiling: + // Store in temporary local variables + // since they're properties that would have to access + // the rule stack every time otherwise. + int i = index; + int cli = characterInLineIndex; + int li = lineIndex; + + int count = 0; + while ( i < _chars.Length && charSet.Contains (_chars [i]) == shouldIncludeChars && count < maxCount ) { + if (_chars [i] == '\n') { + li++; + cli = -1; + } + i++; + cli++; + count++; + } + + index = i; + characterInLineIndex = cli; + lineIndex = li; + + int lastCharIndex = index; + if (lastCharIndex > startIndex) { + return new string (_chars, startIndex, index - startIndex); + } else { + return null; + } + } + + public object Peek(ParseRule rule) + { + int ruleId = BeginRule (); + object result = rule (); + CancelRule (ruleId); + return result; + } + + public string ParseUntil(ParseRule stopRule, CharacterSet pauseCharacters = null, CharacterSet endCharacters = null) + { + int ruleId = BeginRule (); + + + CharacterSet pauseAndEnd = new CharacterSet (); + if (pauseCharacters != null) { + pauseAndEnd.UnionWith (pauseCharacters); + } + if (endCharacters != null) { + pauseAndEnd.UnionWith (endCharacters); + } + + StringBuilder parsedString = new StringBuilder (); + object ruleResultAtPause = null; + + // Keep attempting to parse strings up to the pause (and end) points. + // - At each of the pause points, attempt to parse according to the rule + // - When the end point is reached (or EOF), we're done + do { + + // TODO: Perhaps if no pause or end characters are passed, we should check *every* character for stopRule? + string partialParsedString = ParseUntilCharactersFromCharSet(pauseAndEnd); + if( partialParsedString != null ) { + parsedString.Append(partialParsedString); + } + + // Attempt to run the parse rule at this pause point + ruleResultAtPause = Peek(stopRule); + + // Rule completed - we're done + if( ruleResultAtPause != null ) { + break; + } else { + + if( endOfInput ) { + break; + } + + // Reached a pause point, but rule failed. Step past and continue parsing string + char pauseCharacter = currentCharacter; + if( pauseCharacters != null && pauseCharacters.Contains(pauseCharacter) ) { + parsedString.Append(pauseCharacter); + if( pauseCharacter == '\n' ) { + lineIndex++; + characterInLineIndex = -1; + } + index++; + characterInLineIndex++; + continue; + } else { + break; + } + } + + } while(true); + + if (parsedString.Length > 0) { + return (string) SucceedRule (ruleId, parsedString.ToString ()); + } else { + return (string) FailRule (ruleId); + } + + } + + // No need to Begin/End rule since we never parse a newline, so keeping oldIndex is good enough + public int? ParseInt() + { + int oldIndex = index; + int oldCharacterInLineIndex = characterInLineIndex; + + bool negative = ParseString ("-") != null; + + // Optional whitespace + ParseCharactersFromString (" \t"); + + var parsedString = ParseCharactersFromCharSet (numbersCharacterSet); + if(parsedString == null) { + // Roll back and fail + index = oldIndex; + characterInLineIndex = oldCharacterInLineIndex; + return null; + } + + int parsedInt; + if (int.TryParse (parsedString, out parsedInt)) { + return negative ? -parsedInt : parsedInt; + } + + Error("Failed to read integer value: " + parsedString + ". Perhaps it's out of the range of acceptable numbers ink supports? (" + int.MinValue + " to " + int.MaxValue + ")"); + return null; + } + + // No need to Begin/End rule since we never parse a newline, so keeping oldIndex is good enough + public float? ParseFloat() + { + int oldIndex = index; + int oldCharacterInLineIndex = characterInLineIndex; + + int? leadingInt = ParseInt (); + if (leadingInt != null) { + + if (ParseString (".") != null) { + + var afterDecimalPointStr = ParseCharactersFromCharSet (numbersCharacterSet); + return float.Parse (leadingInt+"." + afterDecimalPointStr, System.Globalization.CultureInfo.InvariantCulture); + } + } + + // Roll back and fail + index = oldIndex; + characterInLineIndex = oldCharacterInLineIndex; + return null; + } + + // You probably want "endOfLine", since it handles endOfFile too. + protected string ParseNewline() + { + int ruleId = BeginRule(); + + // Optional \r, definite \n to support Windows (\r\n) and Mac/Unix (\n) + // 2nd May 2016: Always collapse \r\n to just \n + ParseString ("\r"); + + if( ParseString ("\n") == null ) { + return (string) FailRule(ruleId); + } else { + return (string) SucceedRule(ruleId, "\n"); + } + } + + private char[] _chars; + } +} + diff --git a/Assets/Ink/InkLibs/InkCompiler/StringParser/StringParserState.cs b/Assets/Ink/InkLibs/InkCompiler/StringParser/StringParserState.cs new file mode 100644 index 0000000..44cfbfa --- /dev/null +++ b/Assets/Ink/InkLibs/InkCompiler/StringParser/StringParserState.cs @@ -0,0 +1,171 @@ + +namespace Ink +{ + public class StringParserState + { + public int lineIndex { + get { return currentElement.lineIndex; } + set { currentElement.lineIndex = value; } + } + + public int characterIndex { + get { return currentElement.characterIndex; } + set { currentElement.characterIndex = value; } + } + + public int characterInLineIndex { + get { return currentElement.characterInLineIndex; } + set { currentElement.characterInLineIndex = value; } + } + + public uint customFlags { + get { return currentElement.customFlags; } + set { currentElement.customFlags = value; } + } + + public bool errorReportedAlreadyInScope { + get { + return currentElement.reportedErrorInScope; + } + } + + public int stackHeight { + get { + return _numElements; + } + } + + public class Element { + public int characterIndex; + public int characterInLineIndex; + public int lineIndex; + public bool reportedErrorInScope; + public int uniqueId; + public uint customFlags; + + public Element() { + + } + + public void CopyFrom(Element fromElement) + { + _uniqueIdCounter++; + this.uniqueId = _uniqueIdCounter; + this.characterIndex = fromElement.characterIndex; + this.characterInLineIndex = fromElement.characterInLineIndex; + this.lineIndex = fromElement.lineIndex; + this.customFlags = fromElement.customFlags; + this.reportedErrorInScope = false; + } + + // Squash is used when succeeding from a rule, + // so only the state information we wanted to carry forward is + // retained. e.g. characterIndex and lineIndex are global, + // however uniqueId is specific to the individual rule, + // and likewise, custom flags are designed for the temporary + // state of the individual rule too. + public void SquashFrom(Element fromElement) + { + this.characterIndex = fromElement.characterIndex; + this.characterInLineIndex = fromElement.characterInLineIndex; + this.lineIndex = fromElement.lineIndex; + this.reportedErrorInScope = fromElement.reportedErrorInScope; + this.customFlags = fromElement.customFlags; + } + + static int _uniqueIdCounter; + } + + public StringParserState () + { + const int kExpectedMaxStackDepth = 200; + _stack = new Element[kExpectedMaxStackDepth]; + + for (int i = 0; i < kExpectedMaxStackDepth; ++i) { + _stack [i] = new Element (); + } + + _numElements = 1; + } + + public int Push() + { + if (_numElements >= _stack.Length) + throw new System.Exception ("Stack overflow in parser state"); + + var prevElement = _stack [_numElements - 1]; + var newElement = _stack[_numElements]; + _numElements++; + + newElement.CopyFrom (prevElement); + + return newElement.uniqueId; + } + + public void Pop(int expectedRuleId) + { + if (_numElements == 1) { + throw new System.Exception ("Attempting to remove final stack element is illegal! Mismatched Begin/Succceed/Fail?"); + } + + if ( currentElement.uniqueId != expectedRuleId) + throw new System.Exception ("Mismatched rule IDs - do you have mismatched Begin/Succeed/Fail?"); + + // Restore state + _numElements--; + } + + public Element Peek(int expectedRuleId) + { + if (currentElement.uniqueId != expectedRuleId) + throw new System.Exception ("Mismatched rule IDs - do you have mismatched Begin/Succeed/Fail?"); + + return _stack[_numElements-1]; + } + + public Element PeekPenultimate() + { + if (_numElements >= 2) { + return _stack [_numElements - 2]; + } else { + return null; + } + } + + // Reduce stack height while maintaining currentElement + // Remove second last element: i.e. "squash last two elements together" + // Used when succeeding from a rule (and ONLY when succeeding, since + // the state of the top element is retained). + public void Squash() + { + if (_numElements < 2) { + throw new System.Exception ("Attempting to remove final stack element is illegal! Mismatched Begin/Succceed/Fail?"); + } + + var penultimateEl = _stack [_numElements - 2]; + var lastEl = _stack [_numElements - 1]; + + penultimateEl.SquashFrom (lastEl); + + _numElements--; + } + + public void NoteErrorReported() + { + foreach (var el in _stack) { + el.reportedErrorInScope = true; + } + } + + protected Element currentElement + { + get { + return _stack [_numElements - 1]; + } + } + + private Element[] _stack; + private int _numElements; + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/CallStack.cs b/Assets/Ink/InkLibs/InkRuntime/CallStack.cs new file mode 100644 index 0000000..06b5e66 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/CallStack.cs @@ -0,0 +1,443 @@ +using System.Collections.Generic; +using System.Linq; +using System.Diagnostics; + +namespace Ink.Runtime +{ + public class CallStack + { + public class Element + { + public Pointer currentPointer; + + public bool inExpressionEvaluation; + public Dictionary temporaryVariables; + public PushPopType type; + + // When this callstack element is actually a function evaluation called from the game, + // we need to keep track of the size of the evaluation stack when it was called + // so that we know whether there was any return value. + public int evaluationStackHeightWhenPushed; + + // When functions are called, we trim whitespace from the start and end of what + // they generate, so we make sure know where the function's start and end are. + public int functionStartInOuputStream; + + public Element(PushPopType type, Pointer pointer, bool inExpressionEvaluation = false) { + this.currentPointer = pointer; + this.inExpressionEvaluation = inExpressionEvaluation; + this.temporaryVariables = new Dictionary(); + this.type = type; + } + + public Element Copy() + { + var copy = new Element (this.type, currentPointer, this.inExpressionEvaluation); + copy.temporaryVariables = new Dictionary(this.temporaryVariables); + copy.evaluationStackHeightWhenPushed = evaluationStackHeightWhenPushed; + copy.functionStartInOuputStream = functionStartInOuputStream; + return copy; + } + } + + public class Thread + { + public List callstack; + public int threadIndex; + public Pointer previousPointer; + + public Thread() { + callstack = new List(); + } + + public Thread(Dictionary jThreadObj, Story storyContext) : this() { + threadIndex = (int) jThreadObj ["threadIndex"]; + + List jThreadCallstack = (List) jThreadObj ["callstack"]; + foreach (object jElTok in jThreadCallstack) { + + var jElementObj = (Dictionary)jElTok; + + PushPopType pushPopType = (PushPopType)(int)jElementObj ["type"]; + + Pointer pointer = Pointer.Null; + + string currentContainerPathStr = null; + object currentContainerPathStrToken; + if (jElementObj.TryGetValue ("cPath", out currentContainerPathStrToken)) { + currentContainerPathStr = currentContainerPathStrToken.ToString (); + + var threadPointerResult = storyContext.ContentAtPath (new Path (currentContainerPathStr)); + pointer.container = threadPointerResult.container; + pointer.index = (int)jElementObj ["idx"]; + + if (threadPointerResult.obj == null) + throw new System.Exception ("When loading state, internal story location couldn't be found: " + currentContainerPathStr + ". Has the story changed since this save data was created?"); + else if (threadPointerResult.approximate) + storyContext.Warning ("When loading state, exact internal story location couldn't be found: '" + currentContainerPathStr + "', so it was approximated to '"+pointer.container.path.ToString()+"' to recover. Has the story changed since this save data was created?"); + } + + bool inExpressionEvaluation = (bool)jElementObj ["exp"]; + + var el = new Element (pushPopType, pointer, inExpressionEvaluation); + + object temps; + if ( jElementObj.TryGetValue("temp", out temps) ) { + el.temporaryVariables = Json.JObjectToDictionaryRuntimeObjs((Dictionary)temps); + } else { + el.temporaryVariables.Clear(); + } + + callstack.Add (el); + } + + object prevContentObjPath; + if( jThreadObj.TryGetValue("previousContentObject", out prevContentObjPath) ) { + var prevPath = new Path((string)prevContentObjPath); + previousPointer = storyContext.PointerAtPath(prevPath); + } + } + + public Thread Copy() { + var copy = new Thread (); + copy.threadIndex = threadIndex; + foreach(var e in callstack) { + copy.callstack.Add(e.Copy()); + } + copy.previousPointer = previousPointer; + return copy; + } + + public void WriteJson(SimpleJson.Writer writer) + { + writer.WriteObjectStart(); + + // callstack + writer.WritePropertyStart("callstack"); + writer.WriteArrayStart(); + foreach (CallStack.Element el in callstack) + { + writer.WriteObjectStart(); + if(!el.currentPointer.isNull) { + writer.WriteProperty("cPath", el.currentPointer.container.path.componentsString); + writer.WriteProperty("idx", el.currentPointer.index); + } + + writer.WriteProperty("exp", el.inExpressionEvaluation); + writer.WriteProperty("type", (int)el.type); + + if(el.temporaryVariables.Count > 0) { + writer.WritePropertyStart("temp"); + Json.WriteDictionaryRuntimeObjs(writer, el.temporaryVariables); + writer.WritePropertyEnd(); + } + + writer.WriteObjectEnd(); + } + writer.WriteArrayEnd(); + writer.WritePropertyEnd(); + + // threadIndex + writer.WriteProperty("threadIndex", threadIndex); + + if (!previousPointer.isNull) + { + writer.WriteProperty("previousContentObject", previousPointer.Resolve().path.ToString()); + } + + writer.WriteObjectEnd(); + } + } + + public List elements { + get { + return callStack; + } + } + + public int depth { + get { + return elements.Count; + } + } + + public Element currentElement { + get { + var thread = _threads [_threads.Count - 1]; + var cs = thread.callstack; + return cs [cs.Count - 1]; + } + } + + public int currentElementIndex { + get { + return callStack.Count - 1; + } + } + + public Thread currentThread + { + get { + return _threads [_threads.Count - 1]; + } + set { + Debug.Assert (_threads.Count == 1, "Shouldn't be directly setting the current thread when we have a stack of them"); + _threads.Clear (); + _threads.Add (value); + } + } + + public bool canPop { + get { + return callStack.Count > 1; + } + } + + public CallStack (Story storyContext) + { + _startOfRoot = Pointer.StartOf(storyContext.rootContentContainer); + Reset(); + } + + + public CallStack(CallStack toCopy) + { + _threads = new List (); + foreach (var otherThread in toCopy._threads) { + _threads.Add (otherThread.Copy ()); + } + _threadCounter = toCopy._threadCounter; + _startOfRoot = toCopy._startOfRoot; + } + + public void Reset() + { + _threads = new List(); + _threads.Add(new Thread()); + + _threads[0].callstack.Add(new Element(PushPopType.Tunnel, _startOfRoot)); + } + + + // Unfortunately it's not possible to implement jsonToken since + // the setter needs to take a Story as a context in order to + // look up objects from paths for currentContainer within elements. + public void SetJsonToken(Dictionary jObject, Story storyContext) + { + _threads.Clear (); + + var jThreads = (List) jObject ["threads"]; + + foreach (object jThreadTok in jThreads) { + var jThreadObj = (Dictionary)jThreadTok; + var thread = new Thread (jThreadObj, storyContext); + _threads.Add (thread); + } + + _threadCounter = (int)jObject ["threadCounter"]; + _startOfRoot = Pointer.StartOf(storyContext.rootContentContainer); + } + + public void WriteJson(SimpleJson.Writer w) + { + w.WriteObject(writer => + { + writer.WritePropertyStart("threads"); + { + writer.WriteArrayStart(); + + foreach (CallStack.Thread thread in _threads) + { + thread.WriteJson(writer); + } + + writer.WriteArrayEnd(); + } + writer.WritePropertyEnd(); + + writer.WritePropertyStart("threadCounter"); + { + writer.Write(_threadCounter); + } + writer.WritePropertyEnd(); + }); + + } + + public void PushThread() + { + var newThread = currentThread.Copy (); + _threadCounter++; + newThread.threadIndex = _threadCounter; + _threads.Add (newThread); + } + + public Thread ForkThread() + { + var forkedThread = currentThread.Copy(); + _threadCounter++; + forkedThread.threadIndex = _threadCounter; + return forkedThread; + } + + public void PopThread() + { + if (canPopThread) { + _threads.Remove (currentThread); + } else { + throw new System.Exception("Can't pop thread"); + } + } + + public bool canPopThread + { + get { + return _threads.Count > 1 && !elementIsEvaluateFromGame; + } + } + + public bool elementIsEvaluateFromGame + { + get { + return currentElement.type == PushPopType.FunctionEvaluationFromGame; + } + } + + public void Push(PushPopType type, int externalEvaluationStackHeight = 0, int outputStreamLengthWithPushed = 0) + { + // When pushing to callstack, maintain the current content path, but jump out of expressions by default + var element = new Element ( + type, + currentElement.currentPointer, + inExpressionEvaluation: false + ); + + element.evaluationStackHeightWhenPushed = externalEvaluationStackHeight; + element.functionStartInOuputStream = outputStreamLengthWithPushed; + + callStack.Add (element); + } + + public bool CanPop(PushPopType? type = null) { + + if (!canPop) + return false; + + if (type == null) + return true; + + return currentElement.type == type; + } + + public void Pop(PushPopType? type = null) + { + if (CanPop (type)) { + callStack.RemoveAt (callStack.Count - 1); + return; + } else { + throw new System.Exception("Mismatched push/pop in Callstack"); + } + } + + // Get variable value, dereferencing a variable pointer if necessary + public Runtime.Object GetTemporaryVariableWithName(string name, int contextIndex = -1) + { + if (contextIndex == -1) + contextIndex = currentElementIndex+1; + + Runtime.Object varValue = null; + + var contextElement = callStack [contextIndex-1]; + + if (contextElement.temporaryVariables.TryGetValue (name, out varValue)) { + return varValue; + } else { + return null; + } + } + + public void SetTemporaryVariable(string name, Runtime.Object value, bool declareNew, int contextIndex = -1) + { + if (contextIndex == -1) + contextIndex = currentElementIndex+1; + + var contextElement = callStack [contextIndex-1]; + + if (!declareNew && !contextElement.temporaryVariables.ContainsKey(name)) { + throw new System.Exception ("Could not find temporary variable to set: " + name); + } + + Runtime.Object oldValue; + if( contextElement.temporaryVariables.TryGetValue(name, out oldValue) ) + ListValue.RetainListOriginsForAssignment (oldValue, value); + + contextElement.temporaryVariables [name] = value; + } + + // Find the most appropriate context for this variable. + // Are we referencing a temporary or global variable? + // Note that the compiler will have warned us about possible conflicts, + // so anything that happens here should be safe! + public int ContextForVariableNamed(string name) + { + // Current temporary context? + // (Shouldn't attempt to access contexts higher in the callstack.) + if (currentElement.temporaryVariables.ContainsKey (name)) { + return currentElementIndex+1; + } + + // Global + else { + return 0; + } + } + + public Thread ThreadWithIndex(int index) + { + return _threads.Find (t => t.threadIndex == index); + } + + private List callStack + { + get { + return currentThread.callstack; + } + } + + public string callStackTrace { + get { + var sb = new System.Text.StringBuilder(); + + for(int t=0; t<_threads.Count; t++) { + + var thread = _threads[t]; + var isCurrent = (t == _threads.Count-1); + sb.AppendFormat("=== THREAD {0}/{1} {2}===\n", (t+1), _threads.Count, (isCurrent ? "(current) ":"")); + + for(int i=0; i"); + } + } + } + + + return sb.ToString(); + } + } + + List _threads; + int _threadCounter; + Pointer _startOfRoot; + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/Choice.cs b/Assets/Ink/InkLibs/InkRuntime/Choice.cs new file mode 100644 index 0000000..bc97b78 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/Choice.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +namespace Ink.Runtime +{ + /// + /// A generated Choice from the story. + /// A single ChoicePoint in the Story could potentially generate + /// different Choices dynamically dependent on state, so they're + /// separated. + /// + public class Choice : Runtime.Object + { + /// + /// The main text to presented to the player for this Choice. + /// + public string text { get; set; } + + /// + /// The target path that the Story should be diverted to if + /// this Choice is chosen. + /// + public string pathStringOnChoice { + get { + return targetPath.ToString (); + } + set { + targetPath = new Path (value); + } + } + + /// + /// Get the path to the original choice point - where was this choice defined in the story? + /// + /// A dot separated path into the story data. + public string sourcePath; + + /// + /// The original index into currentChoices list on the Story when + /// this Choice was generated, for convenience. + /// + public int index { get; set; } + + public Path targetPath; + + public CallStack.Thread threadAtGeneration { get; set; } + public int originalThreadIndex; + + public bool isInvisibleDefault; + + public List tags; + + public Choice() + { + } + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/ChoicePoint.cs b/Assets/Ink/InkLibs/InkRuntime/ChoicePoint.cs new file mode 100644 index 0000000..d212dea --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/ChoicePoint.cs @@ -0,0 +1,89 @@ +using System.ComponentModel; + +namespace Ink.Runtime +{ + /// + /// The ChoicePoint represents the point within the Story where + /// a Choice instance gets generated. The distinction is made + /// because the text of the Choice can be dynamically generated. + /// + public class ChoicePoint : Runtime.Object + { + public Path pathOnChoice { + get { + // Resolve any relative paths to global ones as we come across them + if (_pathOnChoice != null && _pathOnChoice.isRelative) { + var choiceTargetObj = choiceTarget; + if (choiceTargetObj) { + _pathOnChoice = choiceTargetObj.path; + } + } + return _pathOnChoice; + } + set { + _pathOnChoice = value; + } + } + Path _pathOnChoice; + + public Container choiceTarget { + get { + return this.ResolvePath (_pathOnChoice).container; + } + } + + public string pathStringOnChoice { + get { + return CompactPathString (pathOnChoice); + } + set { + pathOnChoice = new Path (value); + } + } + + public bool hasCondition { get; set; } + public bool hasStartContent { get; set; } + public bool hasChoiceOnlyContent { get; set; } + public bool onceOnly { get; set; } + public bool isInvisibleDefault { get; set; } + + public int flags { + get { + int flags = 0; + if (hasCondition) flags |= 1; + if (hasStartContent) flags |= 2; + if (hasChoiceOnlyContent) flags |= 4; + if (isInvisibleDefault) flags |= 8; + if (onceOnly) flags |= 16; + return flags; + } + set { + hasCondition = (value & 1) > 0; + hasStartContent = (value & 2) > 0; + hasChoiceOnlyContent = (value & 4) > 0; + isInvisibleDefault = (value & 8) > 0; + onceOnly = (value & 16) > 0; + } + } + + public ChoicePoint (bool onceOnly) + { + this.onceOnly = onceOnly; + } + + public ChoicePoint() : this(true) {} + + public override string ToString () + { + int? targetLineNum = DebugLineNumberOfPath (pathOnChoice); + string targetString = pathOnChoice.ToString (); + + if (targetLineNum != null) { + targetString = " line " + targetLineNum + "("+targetString+")"; + } + + return "Choice: -> " + targetString; + } + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/Container.cs b/Assets/Ink/InkLibs/InkRuntime/Container.cs new file mode 100644 index 0000000..a8a122b --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/Container.cs @@ -0,0 +1,366 @@ +using System; +using System.Diagnostics; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.ComponentModel; + +namespace Ink.Runtime +{ + public class Container : Runtime.Object, INamedContent + { + public string name { get; set; } + + public List content { + get { + return _content; + } + set { + AddContent (value); + } + } + List _content; + + public Dictionary namedContent { get; set; } + + public Dictionary namedOnlyContent { + get { + var namedOnlyContentDict = new Dictionary(); + foreach (var kvPair in namedContent) { + namedOnlyContentDict [kvPair.Key] = (Runtime.Object)kvPair.Value; + } + + foreach (var c in content) { + var named = c as INamedContent; + if (named != null && named.hasValidName) { + namedOnlyContentDict.Remove (named.name); + } + } + + if (namedOnlyContentDict.Count == 0) + namedOnlyContentDict = null; + + return namedOnlyContentDict; + } + set { + var existingNamedOnly = namedOnlyContent; + if (existingNamedOnly != null) { + foreach (var kvPair in existingNamedOnly) { + namedContent.Remove (kvPair.Key); + } + } + + if (value == null) + return; + + foreach (var kvPair in value) { + var named = kvPair.Value as INamedContent; + if( named != null ) + AddToNamedContentOnly (named); + } + } + } + + public bool visitsShouldBeCounted { get; set; } + public bool turnIndexShouldBeCounted { get; set; } + public bool countingAtStartOnly { get; set; } + + [Flags] + public enum CountFlags + { + Visits = 1, + Turns = 2, + CountStartOnly = 4 + } + + public int countFlags + { + get { + CountFlags flags = 0; + if (visitsShouldBeCounted) flags |= CountFlags.Visits; + if (turnIndexShouldBeCounted) flags |= CountFlags.Turns; + if (countingAtStartOnly) flags |= CountFlags.CountStartOnly; + + // If we're only storing CountStartOnly, it serves no purpose, + // since it's dependent on the other two to be used at all. + // (e.g. for setting the fact that *if* a gather or choice's + // content is counted, then is should only be counter at the start) + // So this is just an optimisation for storage. + if (flags == CountFlags.CountStartOnly) { + flags = 0; + } + + return (int)flags; + } + set { + var flag = (CountFlags)value; + if ((flag & CountFlags.Visits) > 0) visitsShouldBeCounted = true; + if ((flag & CountFlags.Turns) > 0) turnIndexShouldBeCounted = true; + if ((flag & CountFlags.CountStartOnly) > 0) countingAtStartOnly = true; + } + } + + public bool hasValidName + { + get { return name != null && name.Length > 0; } + } + + public Path pathToFirstLeafContent + { + get { + if( _pathToFirstLeafContent == null ) + _pathToFirstLeafContent = path.PathByAppendingPath (internalPathToFirstLeafContent); + + return _pathToFirstLeafContent; + } + } + Path _pathToFirstLeafContent; + + Path internalPathToFirstLeafContent + { + get { + var components = new List(); + var container = this; + while (container != null) { + if (container.content.Count > 0) { + components.Add (new Path.Component (0)); + container = container.content [0] as Container; + } + } + return new Path(components); + } + } + + public Container () + { + _content = new List (); + namedContent = new Dictionary (); + } + + public void AddContent(Runtime.Object contentObj) + { + content.Add (contentObj); + + if (contentObj.parent) { + throw new System.Exception ("content is already in " + contentObj.parent); + } + + contentObj.parent = this; + + TryAddNamedContent (contentObj); + } + + public void AddContent(IList contentList) + { + foreach (var c in contentList) { + AddContent (c); + } + } + + public void InsertContent(Runtime.Object contentObj, int index) + { + content.Insert (index, contentObj); + + if (contentObj.parent) { + throw new System.Exception ("content is already in " + contentObj.parent); + } + + contentObj.parent = this; + + TryAddNamedContent (contentObj); + } + + public void TryAddNamedContent(Runtime.Object contentObj) + { + var namedContentObj = contentObj as INamedContent; + if (namedContentObj != null && namedContentObj.hasValidName) { + AddToNamedContentOnly (namedContentObj); + } + } + + public void AddToNamedContentOnly(INamedContent namedContentObj) + { + Debug.Assert (namedContentObj is Runtime.Object, "Can only add Runtime.Objects to a Runtime.Container"); + var runtimeObj = (Runtime.Object)namedContentObj; + runtimeObj.parent = this; + + namedContent [namedContentObj.name] = namedContentObj; + } + + public void AddContentsOfContainer(Container otherContainer) + { + content.AddRange (otherContainer.content); + foreach (var obj in otherContainer.content) { + obj.parent = this; + TryAddNamedContent (obj); + } + } + + protected Runtime.Object ContentWithPathComponent(Path.Component component) + { + if (component.isIndex) { + + if (component.index >= 0 && component.index < content.Count) { + return content [component.index]; + } + + // When path is out of range, quietly return nil + // (useful as we step/increment forwards through content) + else { + return null; + } + + } + + else if (component.isParent) { + return this.parent; + } + + else { + INamedContent foundContent = null; + if (namedContent.TryGetValue (component.name, out foundContent)) { + return (Runtime.Object)foundContent; + } else { + return null; + } + } + } + + public SearchResult ContentAtPath(Path path, int partialPathStart = 0, int partialPathLength = -1) + { + if (partialPathLength == -1) + partialPathLength = path.length; + + var result = new SearchResult (); + result.approximate = false; + + Container currentContainer = this; + Runtime.Object currentObj = this; + + for (int i = partialPathStart; i < partialPathLength; ++i) { + var comp = path.GetComponent(i); + + // Path component was wrong type + if (currentContainer == null) { + result.approximate = true; + break; + } + + var foundObj = currentContainer.ContentWithPathComponent(comp); + + // Couldn't resolve entire path? + if (foundObj == null) { + result.approximate = true; + break; + } + + currentObj = foundObj; + currentContainer = foundObj as Container; + } + + result.obj = currentObj; + + return result; + } + + public void BuildStringOfHierarchy(StringBuilder sb, int indentation, Runtime.Object pointedObj) + { + Action appendIndentation = () => { + const int spacesPerIndent = 4; + for(int i=0; i (); + + foreach (var objKV in namedContent) { + if (content.Contains ((Runtime.Object)objKV.Value)) { + continue; + } else { + onlyNamed.Add (objKV.Key, objKV.Value); + } + } + + if (onlyNamed.Count > 0) { + appendIndentation (); + sb.AppendLine ("-- named: --"); + + foreach (var objKV in onlyNamed) { + + Debug.Assert (objKV.Value is Container, "Can only print out named Containers"); + var container = (Container)objKV.Value; + container.BuildStringOfHierarchy (sb, indentation, pointedObj); + + sb.AppendLine (); + + } + } + + + indentation--; + + appendIndentation (); + sb.Append ("]"); + } + + public virtual string BuildStringOfHierarchy() + { + var sb = new StringBuilder (); + + BuildStringOfHierarchy (sb, 0, null); + + return sb.ToString (); + } + + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/ControlCommand.cs b/Assets/Ink/InkLibs/InkRuntime/ControlCommand.cs new file mode 100644 index 0000000..a4e59d4 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/ControlCommand.cs @@ -0,0 +1,182 @@ +using System; + +namespace Ink.Runtime +{ + public class ControlCommand : Runtime.Object + { + public enum CommandType + { + NotSet = -1, + EvalStart, + EvalOutput, + EvalEnd, + Duplicate, + PopEvaluatedValue, + PopFunction, + PopTunnel, + BeginString, + EndString, + NoOp, + ChoiceCount, + Turns, + TurnsSince, + ReadCount, + Random, + SeedRandom, + VisitIndex, + SequenceShuffleIndex, + StartThread, + Done, + End, + ListFromInt, + ListRange, + ListRandom, + BeginTag, + EndTag, + //---- + TOTAL_VALUES + } + + public CommandType commandType { get; protected set; } + + public ControlCommand (CommandType commandType) + { + this.commandType = commandType; + } + + // Require default constructor for serialisation + public ControlCommand() : this(CommandType.NotSet) {} + + public override Object Copy() + { + return new ControlCommand (commandType); + } + + // The following static factory methods are to make generating these objects + // slightly more succinct. Without these, the code gets pretty massive! e.g. + // + // var c = new Runtime.ControlCommand(Runtime.ControlCommand.CommandType.EvalStart) + // + // as opposed to + // + // var c = Runtime.ControlCommand.EvalStart() + + public static ControlCommand EvalStart() { + return new ControlCommand(CommandType.EvalStart); + } + + public static ControlCommand EvalOutput() { + return new ControlCommand(CommandType.EvalOutput); + } + + public static ControlCommand EvalEnd() { + return new ControlCommand(CommandType.EvalEnd); + } + + public static ControlCommand Duplicate() { + return new ControlCommand(CommandType.Duplicate); + } + + public static ControlCommand PopEvaluatedValue() { + return new ControlCommand (CommandType.PopEvaluatedValue); + } + + public static ControlCommand PopFunction() { + return new ControlCommand (CommandType.PopFunction); + } + + public static ControlCommand PopTunnel() { + return new ControlCommand (CommandType.PopTunnel); + } + + public static ControlCommand BeginString() { + return new ControlCommand (CommandType.BeginString); + } + + public static ControlCommand EndString() { + return new ControlCommand (CommandType.EndString); + } + + public static ControlCommand NoOp() { + return new ControlCommand(CommandType.NoOp); + } + + public static ControlCommand ChoiceCount() { + return new ControlCommand(CommandType.ChoiceCount); + } + + public static ControlCommand Turns () + { + return new ControlCommand (CommandType.Turns); + } + + public static ControlCommand TurnsSince() { + return new ControlCommand(CommandType.TurnsSince); + } + + public static ControlCommand ReadCount () + { + return new ControlCommand (CommandType.ReadCount); + } + + public static ControlCommand Random () + { + return new ControlCommand (CommandType.Random); + } + + public static ControlCommand SeedRandom () + { + return new ControlCommand (CommandType.SeedRandom); + } + + public static ControlCommand VisitIndex() { + return new ControlCommand(CommandType.VisitIndex); + } + + public static ControlCommand SequenceShuffleIndex() { + return new ControlCommand(CommandType.SequenceShuffleIndex); + } + + public static ControlCommand StartThread() { + return new ControlCommand (CommandType.StartThread); + } + + public static ControlCommand Done() { + return new ControlCommand (CommandType.Done); + } + + public static ControlCommand End() { + return new ControlCommand (CommandType.End); + } + + public static ControlCommand ListFromInt () { + return new ControlCommand (CommandType.ListFromInt); + } + + public static ControlCommand ListRange () + { + return new ControlCommand (CommandType.ListRange); + } + + public static ControlCommand ListRandom () + { + return new ControlCommand (CommandType.ListRandom); + } + + public static ControlCommand BeginTag () + { + return new ControlCommand (CommandType.BeginTag); + } + + public static ControlCommand EndTag () + { + return new ControlCommand (CommandType.EndTag); + } + + public override string ToString () + { + return commandType.ToString(); + } + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/DebugMetadata.cs b/Assets/Ink/InkLibs/InkRuntime/DebugMetadata.cs new file mode 100644 index 0000000..1d06f30 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/DebugMetadata.cs @@ -0,0 +1,76 @@ +using System; + +namespace Ink.Runtime +{ + public class DebugMetadata + { + public int startLineNumber = 0; + public int endLineNumber = 0; + public int startCharacterNumber = 0; + public int endCharacterNumber = 0; + public string fileName = null; + public string sourceName = null; + + public DebugMetadata () + { + } + + // Currently only used in VariableReference in order to + // merge the debug metadata of a Path.Of.Indentifiers into + // one single range. + public DebugMetadata Merge(DebugMetadata dm) + { + var newDebugMetadata = new DebugMetadata(); + + // These are not supposed to be differ between 'this' and 'dm'. + newDebugMetadata.fileName = fileName; + newDebugMetadata.sourceName = sourceName; + + if (startLineNumber < dm.startLineNumber) + { + newDebugMetadata.startLineNumber = startLineNumber; + newDebugMetadata.startCharacterNumber = startCharacterNumber; + } + else if (startLineNumber > dm.startLineNumber) + { + newDebugMetadata.startLineNumber = dm.startLineNumber; + newDebugMetadata.startCharacterNumber = dm.startCharacterNumber; + } + else + { + newDebugMetadata.startLineNumber = startLineNumber; + newDebugMetadata.startCharacterNumber = Math.Min(startCharacterNumber, dm.startCharacterNumber); + } + + if (endLineNumber > dm.endLineNumber) + { + newDebugMetadata.endLineNumber = endLineNumber; + newDebugMetadata.endCharacterNumber = endCharacterNumber; + } + else if (endLineNumber < dm.endLineNumber) + { + newDebugMetadata.endLineNumber = dm.endLineNumber; + newDebugMetadata.endCharacterNumber = dm.endCharacterNumber; + } + else + { + newDebugMetadata.endLineNumber = endLineNumber; + newDebugMetadata.endCharacterNumber = Math.Max(endCharacterNumber, dm.endCharacterNumber); + } + + return newDebugMetadata; + } + + public override string ToString () + { + if (fileName != null) { + return string.Format ("line {0} of {1}", startLineNumber, fileName); + } else { + return "line " + startLineNumber; + } + + } + + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/Divert.cs b/Assets/Ink/InkLibs/InkRuntime/Divert.cs new file mode 100644 index 0000000..5c15a68 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/Divert.cs @@ -0,0 +1,149 @@ +using System.Text; + +namespace Ink.Runtime +{ + public class Divert : Runtime.Object + { + public Path targetPath { + get { + // Resolve any relative paths to global ones as we come across them + if (_targetPath != null && _targetPath.isRelative) { + var targetObj = targetPointer.Resolve(); + if (targetObj) { + _targetPath = targetObj.path; + } + } + return _targetPath; + } + set { + _targetPath = value; + _targetPointer = Pointer.Null; + } + } + Path _targetPath; + + public Pointer targetPointer { + get { + if (_targetPointer.isNull) { + var targetObj = ResolvePath (_targetPath).obj; + + if (_targetPath.lastComponent.isIndex) { + _targetPointer.container = targetObj.parent as Container; + _targetPointer.index = _targetPath.lastComponent.index; + } else { + _targetPointer = Pointer.StartOf (targetObj as Container); + } + } + return _targetPointer; + } + } + Pointer _targetPointer; + + + public string targetPathString { + get { + if (targetPath == null) + return null; + + return CompactPathString (targetPath); + } + set { + if (value == null) { + targetPath = null; + } else { + targetPath = new Path (value); + } + } + } + + public string variableDivertName { get; set; } + public bool hasVariableTarget { get { return variableDivertName != null; } } + + public bool pushesToStack { get; set; } + public PushPopType stackPushType; + + public bool isExternal { get; set; } + public int externalArgs { get; set; } + + public bool isConditional { get; set; } + + public Divert () + { + pushesToStack = false; + } + + public Divert(PushPopType stackPushType) + { + pushesToStack = true; + this.stackPushType = stackPushType; + } + + public override bool Equals (object obj) + { + var otherDivert = obj as Divert; + if (otherDivert) { + if (this.hasVariableTarget == otherDivert.hasVariableTarget) { + if (this.hasVariableTarget) { + return this.variableDivertName == otherDivert.variableDivertName; + } else { + return this.targetPath.Equals(otherDivert.targetPath); + } + } + } + return false; + } + + public override int GetHashCode () + { + if (hasVariableTarget) { + const int variableTargetSalt = 12345; + return variableDivertName.GetHashCode() + variableTargetSalt; + } else { + const int pathTargetSalt = 54321; + return targetPath.GetHashCode() + pathTargetSalt; + } + } + + public override string ToString () + { + if (hasVariableTarget) { + return "Divert(variable: " + variableDivertName + ")"; + } + else if (targetPath == null) { + return "Divert(null)"; + } else { + + var sb = new StringBuilder (); + + string targetStr = targetPath.ToString (); + int? targetLineNum = DebugLineNumberOfPath (targetPath); + if (targetLineNum != null) { + targetStr = "line " + targetLineNum; + } + + sb.Append ("Divert"); + + if (isConditional) + sb.Append ("?"); + + if (pushesToStack) { + if (stackPushType == PushPopType.Function) { + sb.Append (" function"); + } else { + sb.Append (" tunnel"); + } + } + + sb.Append (" -> "); + sb.Append (targetPathString); + + sb.Append (" ("); + sb.Append (targetStr); + sb.Append (")"); + + return sb.ToString (); + } + } + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/Error.cs b/Assets/Ink/InkLibs/InkRuntime/Error.cs new file mode 100644 index 0000000..38a5dc5 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/Error.cs @@ -0,0 +1,24 @@ +namespace Ink +{ + /// + /// Callback for errors throughout both the ink runtime and compiler. + /// + public delegate void ErrorHandler(string message, ErrorType type); + + /// + /// Author errors will only ever come from the compiler so don't need to be handled + /// by your Story error handler. The "Error" ErrorType is by far the most common + /// for a runtime story error (rather than compiler error), though the Warning type + /// is also possible. + /// + public enum ErrorType + { + /// Generated by a "TODO" note in the ink source + Author, + /// You should probably fix this, but it's not critical + Warning, + /// Critical error that can't be recovered from + Error + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/Flow.cs b/Assets/Ink/InkLibs/InkRuntime/Flow.cs new file mode 100644 index 0000000..37da8ec --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/Flow.cs @@ -0,0 +1,93 @@ +using System.Collections.Generic; + +namespace Ink.Runtime +{ + public class Flow { + public string name; + public CallStack callStack; + public List outputStream; + public List currentChoices; + + public Flow(string name, Story story) { + this.name = name; + this.callStack = new CallStack(story); + this.outputStream = new List(); + this.currentChoices = new List(); + } + + public Flow(string name, Story story, Dictionary jObject) { + this.name = name; + this.callStack = new CallStack(story); + this.callStack.SetJsonToken ((Dictionary < string, object > )jObject ["callstack"], story); + this.outputStream = Json.JArrayToRuntimeObjList ((List)jObject ["outputStream"]); + this.currentChoices = Json.JArrayToRuntimeObjList((List)jObject ["currentChoices"]); + + // choiceThreads is optional + object jChoiceThreadsObj; + jObject.TryGetValue("choiceThreads", out jChoiceThreadsObj); + LoadFlowChoiceThreads((Dictionary)jChoiceThreadsObj, story); + } + + public void WriteJson(SimpleJson.Writer writer) + { + writer.WriteObjectStart(); + + writer.WriteProperty("callstack", callStack.WriteJson); + writer.WriteProperty("outputStream", w => Json.WriteListRuntimeObjs(w, outputStream)); + + // choiceThreads: optional + // Has to come BEFORE the choices themselves are written out + // since the originalThreadIndex of each choice needs to be set + bool hasChoiceThreads = false; + foreach (Choice c in currentChoices) + { + c.originalThreadIndex = c.threadAtGeneration.threadIndex; + + if (callStack.ThreadWithIndex(c.originalThreadIndex) == null) + { + if (!hasChoiceThreads) + { + hasChoiceThreads = true; + writer.WritePropertyStart("choiceThreads"); + writer.WriteObjectStart(); + } + + writer.WritePropertyStart(c.originalThreadIndex); + c.threadAtGeneration.WriteJson(writer); + writer.WritePropertyEnd(); + } + } + + if (hasChoiceThreads) + { + writer.WriteObjectEnd(); + writer.WritePropertyEnd(); + } + + + writer.WriteProperty("currentChoices", w => { + w.WriteArrayStart(); + foreach (var c in currentChoices) + Json.WriteChoice(w, c); + w.WriteArrayEnd(); + }); + + + writer.WriteObjectEnd(); + } + + // Used both to load old format and current + public void LoadFlowChoiceThreads(Dictionary jChoiceThreads, Story story) + { + foreach (var choice in currentChoices) { + var foundActiveThread = callStack.ThreadWithIndex(choice.originalThreadIndex); + if( foundActiveThread != null ) { + choice.threadAtGeneration = foundActiveThread.Copy (); + } else { + var jSavedChoiceThread = (Dictionary ) jChoiceThreads[choice.originalThreadIndex.ToString()]; + choice.threadAtGeneration = new CallStack.Thread(jSavedChoiceThread, story); + } + } + } + } +} \ No newline at end of file diff --git a/Assets/Ink/InkLibs/InkRuntime/Glue.cs b/Assets/Ink/InkLibs/InkRuntime/Glue.cs new file mode 100644 index 0000000..cfdfb25 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/Glue.cs @@ -0,0 +1,13 @@ +namespace Ink.Runtime +{ + public class Glue : Runtime.Object + { + public Glue() { } + + public override string ToString () + { + return "Glue"; + } + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/INamedContent.cs b/Assets/Ink/InkLibs/InkRuntime/INamedContent.cs new file mode 100644 index 0000000..3e45199 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/INamedContent.cs @@ -0,0 +1,10 @@ + +namespace Ink.Runtime +{ + public interface INamedContent + { + string name { get; } + bool hasValidName { get; } + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/InkList.cs b/Assets/Ink/InkLibs/InkRuntime/InkList.cs new file mode 100644 index 0000000..fd1efa3 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/InkList.cs @@ -0,0 +1,614 @@ +using System.Collections.Generic; +using System.Text; + +namespace Ink.Runtime +{ + /// + /// The underlying type for a list item in ink. It stores the original list definition + /// name as well as the item name, but without the value of the item. When the value is + /// stored, it's stored in a KeyValuePair of InkListItem and int. + /// + public struct InkListItem + { + /// + /// The name of the list where the item was originally defined. + /// + public readonly string originName; + + /// + /// The main name of the item as defined in ink. + /// + public readonly string itemName; + + /// + /// Create an item with the given original list definition name, and the name of this + /// item. + /// + public InkListItem (string originName, string itemName) + { + this.originName = originName; + this.itemName = itemName; + } + + /// + /// Create an item from a dot-separted string of the form "listDefinitionName.listItemName". + /// + public InkListItem (string fullName) + { + var nameParts = fullName.Split ('.'); + this.originName = nameParts [0]; + this.itemName = nameParts [1]; + } + + public static InkListItem Null { + get { + return new InkListItem (null, null); + } + } + + public bool isNull { + get { + return originName == null && itemName == null; + } + } + + /// + /// Get the full dot-separated name of the item, in the form "listDefinitionName.itemName". + /// + public string fullName { + get { + return (originName ?? "?") + "." + itemName; + } + } + + /// + /// Get the full dot-separated name of the item, in the form "listDefinitionName.itemName". + /// Calls fullName internally. + /// + public override string ToString () + { + return fullName; + } + + /// + /// Is this item the same as another item? + /// + public override bool Equals (object obj) + { + if (obj is InkListItem) { + var otherItem = (InkListItem)obj; + return otherItem.itemName == itemName + && otherItem.originName == originName; + } + + return false; + } + + /// + /// Get the hashcode for an item. + /// + public override int GetHashCode () + { + int originCode = 0; + int itemCode = itemName.GetHashCode (); + if (originName != null) + originCode = originName.GetHashCode (); + + return originCode + itemCode; + } + } + + /// + /// The InkList is the underlying type that's used to store an instance of a + /// list in ink. It's not used for the *definition* of the list, but for a list + /// value that's stored in a variable. + /// Somewhat confusingly, it's backed by a C# Dictionary, and has nothing to + /// do with a C# List! + /// + public class InkList : Dictionary + { + /// + /// Create a new empty ink list. + /// + public InkList () { } + + /// + /// Create a new ink list that contains the same contents as another list. + /// + public InkList(InkList otherList) : base(otherList) + { + var otherOriginNames = otherList.originNames; + if( otherOriginNames != null ) + _originNames = new List(otherOriginNames); + + if (otherList.origins != null) + { + origins = new List(otherList.origins); + } + } + + /// + /// Create a new empty ink list that's intended to hold items from a particular origin + /// list definition. The origin Story is needed in order to be able to look up that definition. + /// + public InkList (string singleOriginListName, Story originStory) + { + SetInitialOriginName (singleOriginListName); + + ListDefinition def; + if (originStory.listDefinitions.TryListGetDefinition (singleOriginListName, out def)) + origins = new List { def }; + else + throw new System.Exception ("InkList origin could not be found in story when constructing new list: " + singleOriginListName); + } + + public InkList (KeyValuePair singleElement) + { + Add (singleElement.Key, singleElement.Value); + } + + /// + /// Converts a string to an ink list and returns for use in the story. + /// + /// InkList created from string list item + /// Item key. + /// Origin story. + public static InkList FromString(string myListItem, Story originStory) { + var listValue = originStory.listDefinitions.FindSingleItemListWithName (myListItem); + if (listValue) + return new InkList (listValue.value); + else + throw new System.Exception ("Could not find the InkListItem from the string '" + myListItem + "' to create an InkList because it doesn't exist in the original list definition in ink."); + } + + + /// + /// Adds the given item to the ink list. Note that the item must come from a list definition that + /// is already "known" to this list, so that the item's value can be looked up. By "known", we mean + /// that it already has items in it from that source, or it did at one point - it can't be a + /// completely fresh empty list, or a list that only contains items from a different list definition. + /// + public void AddItem (InkListItem item) + { + if (item.originName == null) { + AddItem (item.itemName); + return; + } + + foreach (var origin in origins) { + if (origin.name == item.originName) { + int intVal; + if (origin.TryGetValueForItem (item, out intVal)) { + this [item] = intVal; + return; + } else { + throw new System.Exception ("Could not add the item " + item + " to this list because it doesn't exist in the original list definition in ink."); + } + } + } + + throw new System.Exception ("Failed to add item to list because the item was from a new list definition that wasn't previously known to this list. Only items from previously known lists can be used, so that the int value can be found."); + } + + /// + /// Adds the given item to the ink list, attempting to find the origin list definition that it belongs to. + /// The item must therefore come from a list definition that is already "known" to this list, so that the + /// item's value can be looked up. By "known", we mean that it already has items in it from that source, or + /// it did at one point - it can't be a completely fresh empty list, or a list that only contains items from + /// a different list definition. + /// + public void AddItem (string itemName) + { + ListDefinition foundListDef = null; + + foreach (var origin in origins) { + if (origin.ContainsItemWithName (itemName)) { + if (foundListDef != null) { + throw new System.Exception ("Could not add the item " + itemName + " to this list because it could come from either " + origin.name + " or " + foundListDef.name); + } else { + foundListDef = origin; + } + } + } + + if (foundListDef == null) + throw new System.Exception ("Could not add the item " + itemName + " to this list because it isn't known to any list definitions previously associated with this list."); + + var item = new InkListItem (foundListDef.name, itemName); + var itemVal = foundListDef.ValueForItem(item); + this [item] = itemVal; + } + + /// + /// Returns true if this ink list contains an item with the given short name + /// (ignoring the original list where it was defined). + /// + public bool ContainsItemNamed (string itemName) + { + foreach (var itemWithValue in this) { + if (itemWithValue.Key.itemName == itemName) return true; + } + return false; + } + + // Story has to set this so that the value knows its origin, + // necessary for certain operations (e.g. interacting with ints). + // Only the story has access to the full set of lists, so that + // the origin can be resolved from the originListName. + public List origins; + public ListDefinition originOfMaxItem { + get { + if (origins == null) return null; + + var maxOriginName = maxItem.Key.originName; + foreach (var origin in origins) { + if (origin.name == maxOriginName) + return origin; + } + + return null; + } + } + + // Origin name needs to be serialised when content is empty, + // assuming a name is availble, for list definitions with variable + // that is currently empty. + public List originNames { + get { + if (this.Count > 0) { + if (_originNames == null && this.Count > 0) + _originNames = new List (); + else + _originNames.Clear (); + + foreach (var itemAndValue in this) + _originNames.Add (itemAndValue.Key.originName); + } + + return _originNames; + } + } + List _originNames; + + public void SetInitialOriginName (string initialOriginName) + { + _originNames = new List { initialOriginName }; + } + + public void SetInitialOriginNames (List initialOriginNames) + { + if (initialOriginNames == null) + _originNames = null; + else + _originNames = new List(initialOriginNames); + } + + /// + /// Get the maximum item in the list, equivalent to calling LIST_MAX(list) in ink. + /// + public KeyValuePair maxItem { + get { + KeyValuePair max = new KeyValuePair(); + foreach (var kv in this) { + if (max.Key.isNull || kv.Value > max.Value) + max = kv; + } + return max; + } + } + + /// + /// Get the minimum item in the list, equivalent to calling LIST_MIN(list) in ink. + /// + public KeyValuePair minItem { + get { + var min = new KeyValuePair (); + foreach (var kv in this) { + if (min.Key.isNull || kv.Value < min.Value) + min = kv; + } + return min; + } + } + + /// + /// The inverse of the list, equivalent to calling LIST_INVERSE(list) in ink + /// + public InkList inverse { + get { + var list = new InkList (); + if (origins != null) { + foreach (var origin in origins) { + foreach (var itemAndValue in origin.items) { + if (!this.ContainsKey (itemAndValue.Key)) + list.Add (itemAndValue.Key, itemAndValue.Value); + } + } + + } + return list; + } + } + + /// + /// The list of all items from the original list definition, equivalent to calling + /// LIST_ALL(list) in ink. + /// + public InkList all { + get { + var list = new InkList (); + if (origins != null) { + foreach (var origin in origins) { + foreach (var itemAndValue in origin.items) + list[itemAndValue.Key] = itemAndValue.Value; + } + } + return list; + } + } + + /// + /// Returns a new list that is the combination of the current list and one that's + /// passed in. Equivalent to calling (list1 + list2) in ink. + /// + public InkList Union (InkList otherList) + { + var union = new InkList (this); + foreach (var kv in otherList) { + union [kv.Key] = kv.Value; + } + return union; + } + + /// + /// Returns a new list that is the intersection of the current list with another + /// list that's passed in - i.e. a list of the items that are shared between the + /// two other lists. Equivalent to calling (list1 ^ list2) in ink. + /// + public InkList Intersect (InkList otherList) + { + var intersection = new InkList (); + foreach (var kv in this) { + if (otherList.ContainsKey (kv.Key)) + intersection.Add (kv.Key, kv.Value); + } + return intersection; + } + + /// + /// Fast test for the existence of any intersection between the current list and another + /// + public bool HasIntersection(InkList otherList) + { + foreach (var kv in this) + { + if (otherList.ContainsKey(kv.Key)) + return true; + } + return false; + } + + /// + /// Returns a new list that's the same as the current one, except with the given items + /// removed that are in the passed in list. Equivalent to calling (list1 - list2) in ink. + /// + /// List to remove. + public InkList Without (InkList listToRemove) + { + var result = new InkList (this); + foreach (var kv in listToRemove) + result.Remove (kv.Key); + return result; + } + + /// + /// Returns true if the current list contains all the items that are in the list that + /// is passed in. Equivalent to calling (list1 ? list2) in ink. + /// + /// Other list. + public bool Contains (InkList otherList) + { + if( otherList.Count == 0 || this.Count == 0 ) return false; + foreach (var kv in otherList) { + if (!this.ContainsKey (kv.Key)) return false; + } + return true; + } + + /// + /// Returns true if the current list contains an item matching the given name. + /// + /// Other list. + public bool Contains(string listItemName) + { + foreach (var kv in this) + { + if (kv.Key.itemName == listItemName) return true; + } + return false; + } + + /// + /// Returns true if all the item values in the current list are greater than all the + /// item values in the passed in list. Equivalent to calling (list1 > list2) in ink. + /// + public bool GreaterThan (InkList otherList) + { + if (Count == 0) return false; + if (otherList.Count == 0) return true; + + // All greater + return minItem.Value > otherList.maxItem.Value; + } + + /// + /// Returns true if the item values in the current list overlap or are all greater than + /// the item values in the passed in list. None of the item values in the current list must + /// fall below the item values in the passed in list. Equivalent to (list1 >= list2) in ink, + /// or LIST_MIN(list1) >= LIST_MIN(list2) && LIST_MAX(list1) >= LIST_MAX(list2). + /// + public bool GreaterThanOrEquals (InkList otherList) + { + if (Count == 0) return false; + if (otherList.Count == 0) return true; + + return minItem.Value >= otherList.minItem.Value + && maxItem.Value >= otherList.maxItem.Value; + } + + /// + /// Returns true if all the item values in the current list are less than all the + /// item values in the passed in list. Equivalent to calling (list1 < list2) in ink. + /// + public bool LessThan (InkList otherList) + { + if (otherList.Count == 0) return false; + if (Count == 0) return true; + + return maxItem.Value < otherList.minItem.Value; + } + + /// + /// Returns true if the item values in the current list overlap or are all less than + /// the item values in the passed in list. None of the item values in the current list must + /// go above the item values in the passed in list. Equivalent to (list1 <= list2) in ink, + /// or LIST_MAX(list1) <= LIST_MAX(list2) && LIST_MIN(list1) <= LIST_MIN(list2). + /// + public bool LessThanOrEquals (InkList otherList) + { + if (otherList.Count == 0) return false; + if (Count == 0) return true; + + return maxItem.Value <= otherList.maxItem.Value + && minItem.Value <= otherList.minItem.Value; + } + + public InkList MaxAsList () + { + if (Count > 0) + return new InkList (maxItem); + else + return new InkList (); + } + + public InkList MinAsList () + { + if (Count > 0) + return new InkList (minItem); + else + return new InkList (); + } + + /// + /// Returns a sublist with the elements given the minimum and maxmimum bounds. + /// The bounds can either be ints which are indices into the entire (sorted) list, + /// or they can be InkLists themselves. These are intended to be single-item lists so + /// you can specify the upper and lower bounds. If you pass in multi-item lists, it'll + /// use the minimum and maximum items in those lists respectively. + /// WARNING: Calling this method requires a full sort of all the elements in the list. + /// + public InkList ListWithSubRange(object minBound, object maxBound) + { + if (this.Count == 0) return new InkList(); + + var ordered = orderedItems; + + int minValue = 0; + int maxValue = int.MaxValue; + + if (minBound is int) + { + minValue = (int)minBound; + } + + else + { + if( minBound is InkList && ((InkList)minBound).Count > 0 ) + minValue = ((InkList)minBound).minItem.Value; + } + + if (maxBound is int) + maxValue = (int)maxBound; + else + { + if (minBound is InkList && ((InkList)minBound).Count > 0) + maxValue = ((InkList)maxBound).maxItem.Value; + } + + var subList = new InkList(); + subList.SetInitialOriginNames(originNames); + foreach(var item in ordered) { + if( item.Value >= minValue && item.Value <= maxValue ) { + subList.Add(item.Key, item.Value); + } + } + + return subList; + } + + /// + /// Returns true if the passed object is also an ink list that contains + /// the same items as the current list, false otherwise. + /// + public override bool Equals (object other) + { + var otherRawList = other as InkList; + if (otherRawList == null) return false; + if (otherRawList.Count != Count) return false; + + foreach (var kv in this) { + if (!otherRawList.ContainsKey (kv.Key)) + return false; + } + + return true; + } + + /// + /// Return the hashcode for this object, used for comparisons and inserting into dictionaries. + /// + public override int GetHashCode () + { + int ownHash = 0; + foreach (var kv in this) + ownHash += kv.Key.GetHashCode (); + return ownHash; + } + + List> orderedItems { + get { + var ordered = new List>(); + ordered.AddRange(this); + ordered.Sort((x, y) => { + // Ensure consistent ordering of mixed lists. + if( x.Value == y.Value ) { + return x.Key.originName.CompareTo(y.Key.originName); + } else { + return x.Value.CompareTo(y.Value); + } + }); + return ordered; + } + } + + /// + /// Returns a string in the form "a, b, c" with the names of the items in the list, without + /// the origin list definition names. Equivalent to writing {list} in ink. + /// + public override string ToString () + { + var ordered = orderedItems; + + var sb = new StringBuilder (); + for (int i = 0; i < ordered.Count; i++) { + if (i > 0) + sb.Append (", "); + + var item = ordered [i].Key; + sb.Append (item.itemName); + } + + return sb.ToString (); + } + } +} diff --git a/Assets/Ink/InkLibs/InkRuntime/JsonSerialisation.cs b/Assets/Ink/InkLibs/InkRuntime/JsonSerialisation.cs new file mode 100644 index 0000000..8dbf847 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/JsonSerialisation.cs @@ -0,0 +1,722 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Ink.Runtime +{ + public static class Json + { + public static List JArrayToRuntimeObjList(List jArray, bool skipLast=false) where T : Runtime.Object + { + int count = jArray.Count; + if (skipLast) + count--; + + var list = new List (jArray.Count); + + for (int i = 0; i < count; i++) { + var jTok = jArray [i]; + var runtimeObj = JTokenToRuntimeObject (jTok) as T; + list.Add (runtimeObj); + } + + return list; + } + + public static List JArrayToRuntimeObjList(List jArray, bool skipLast=false) + { + return JArrayToRuntimeObjList (jArray, skipLast); + } + + public static void WriteDictionaryRuntimeObjs(SimpleJson.Writer writer, Dictionary dictionary) + { + writer.WriteObjectStart(); + foreach(var keyVal in dictionary) { + writer.WritePropertyStart(keyVal.Key); + WriteRuntimeObject(writer, keyVal.Value); + writer.WritePropertyEnd(); + } + writer.WriteObjectEnd(); + } + + + public static void WriteListRuntimeObjs(SimpleJson.Writer writer, List list) + { + writer.WriteArrayStart(); + foreach (var val in list) + { + WriteRuntimeObject(writer, val); + } + writer.WriteArrayEnd(); + } + + public static void WriteIntDictionary(SimpleJson.Writer writer, Dictionary dict) + { + writer.WriteObjectStart(); + foreach (var keyVal in dict) + writer.WriteProperty(keyVal.Key, keyVal.Value); + writer.WriteObjectEnd(); + } + + public static void WriteRuntimeObject(SimpleJson.Writer writer, Runtime.Object obj) + { + var container = obj as Container; + if (container) { + WriteRuntimeContainer(writer, container); + return; + } + + var divert = obj as Divert; + if (divert) + { + string divTypeKey = "->"; + if (divert.isExternal) + divTypeKey = "x()"; + else if (divert.pushesToStack) + { + if (divert.stackPushType == PushPopType.Function) + divTypeKey = "f()"; + else if (divert.stackPushType == PushPopType.Tunnel) + divTypeKey = "->t->"; + } + + string targetStr; + if (divert.hasVariableTarget) + targetStr = divert.variableDivertName; + else + targetStr = divert.targetPathString; + + writer.WriteObjectStart(); + + writer.WriteProperty(divTypeKey, targetStr); + + if (divert.hasVariableTarget) + writer.WriteProperty("var", true); + + if (divert.isConditional) + writer.WriteProperty("c", true); + + if (divert.externalArgs > 0) + writer.WriteProperty("exArgs", divert.externalArgs); + + writer.WriteObjectEnd(); + return; + } + + var choicePoint = obj as ChoicePoint; + if (choicePoint) + { + writer.WriteObjectStart(); + writer.WriteProperty("*", choicePoint.pathStringOnChoice); + writer.WriteProperty("flg", choicePoint.flags); + writer.WriteObjectEnd(); + return; + } + + var boolVal = obj as BoolValue; + if (boolVal) { + writer.Write(boolVal.value); + return; + } + + var intVal = obj as IntValue; + if (intVal) { + writer.Write(intVal.value); + return; + } + + var floatVal = obj as FloatValue; + if (floatVal) { + writer.Write(floatVal.value); + return; + } + + var strVal = obj as StringValue; + if (strVal) + { + if (strVal.isNewline) + writer.Write("\\n", escape:false); + else { + writer.WriteStringStart(); + writer.WriteStringInner("^"); + writer.WriteStringInner(strVal.value); + writer.WriteStringEnd(); + } + return; + } + + var listVal = obj as ListValue; + if (listVal) + { + WriteInkList(writer, listVal); + return; + } + + var divTargetVal = obj as DivertTargetValue; + if (divTargetVal) + { + writer.WriteObjectStart(); + writer.WriteProperty("^->", divTargetVal.value.componentsString); + writer.WriteObjectEnd(); + return; + } + + var varPtrVal = obj as VariablePointerValue; + if (varPtrVal) + { + writer.WriteObjectStart(); + writer.WriteProperty("^var", varPtrVal.value); + writer.WriteProperty("ci", varPtrVal.contextIndex); + writer.WriteObjectEnd(); + return; + } + + var glue = obj as Runtime.Glue; + if (glue) { + writer.Write("<>"); + return; + } + + var controlCmd = obj as ControlCommand; + if (controlCmd) + { + writer.Write(_controlCommandNames[(int)controlCmd.commandType]); + return; + } + + var nativeFunc = obj as Runtime.NativeFunctionCall; + if (nativeFunc) + { + var name = nativeFunc.name; + + // Avoid collision with ^ used to indicate a string + if (name == "^") name = "L^"; + + writer.Write(name); + return; + } + + + // Variable reference + var varRef = obj as VariableReference; + if (varRef) + { + writer.WriteObjectStart(); + + string readCountPath = varRef.pathStringForCount; + if (readCountPath != null) + { + writer.WriteProperty("CNT?", readCountPath); + } + else + { + writer.WriteProperty("VAR?", varRef.name); + } + + writer.WriteObjectEnd(); + return; + } + + // Variable assignment + var varAss = obj as VariableAssignment; + if (varAss) + { + writer.WriteObjectStart(); + + string key = varAss.isGlobal ? "VAR=" : "temp="; + writer.WriteProperty(key, varAss.variableName); + + // Reassignment? + if (!varAss.isNewDeclaration) + writer.WriteProperty("re", true); + + writer.WriteObjectEnd(); + + return; + } + + // Void + var voidObj = obj as Void; + if (voidObj) { + writer.Write("void"); + return; + } + + // Legacy tag + var tag = obj as Tag; + if (tag) + { + writer.WriteObjectStart(); + writer.WriteProperty("#", tag.text); + writer.WriteObjectEnd(); + return; + } + + // Used when serialising save state only + var choice = obj as Choice; + if (choice) { + WriteChoice(writer, choice); + return; + } + + throw new System.Exception("Failed to write runtime object to JSON: " + obj); + } + + public static Dictionary JObjectToDictionaryRuntimeObjs(Dictionary jObject) + { + var dict = new Dictionary (jObject.Count); + + foreach (var keyVal in jObject) { + dict [keyVal.Key] = JTokenToRuntimeObject(keyVal.Value); + } + + return dict; + } + + public static Dictionary JObjectToIntDictionary(Dictionary jObject) + { + var dict = new Dictionary (jObject.Count); + foreach (var keyVal in jObject) { + dict [keyVal.Key] = (int)keyVal.Value; + } + return dict; + } + + // ---------------------- + // JSON ENCODING SCHEME + // ---------------------- + // + // Glue: "<>", "G<", "G>" + // + // ControlCommand: "ev", "out", "/ev", "du" "pop", "->->", "~ret", "str", "/str", "nop", + // "choiceCnt", "turns", "visit", "seq", "thread", "done", "end" + // + // NativeFunction: "+", "-", "/", "*", "%" "~", "==", ">", "<", ">=", "<=", "!=", "!"... etc + // + // Void: "void" + // + // Value: "^string value", "^^string value beginning with ^" + // 5, 5.2 + // {"^->": "path.target"} + // {"^var": "varname", "ci": 0} + // + // Container: [...] + // [..., + // { + // "subContainerName": ..., + // "#f": 5, // flags + // "#n": "containerOwnName" // only if not redundant + // } + // ] + // + // Divert: {"->": "path.target", "c": true } + // {"->": "path.target", "var": true} + // {"f()": "path.func"} + // {"->t->": "path.tunnel"} + // {"x()": "externalFuncName", "exArgs": 5} + // + // Var Assign: {"VAR=": "varName", "re": true} // reassignment + // {"temp=": "varName"} + // + // Var ref: {"VAR?": "varName"} + // {"CNT?": "stitch name"} + // + // ChoicePoint: {"*": pathString, + // "flg": 18 } + // + // Choice: Nothing too clever, it's only used in the save state, + // there's not likely to be many of them. + // + // Tag: {"#": "the tag text"} + public static Runtime.Object JTokenToRuntimeObject(object token) + { + if (token is int || token is float || token is bool) { + return Value.Create (token); + } + + if (token is string) { + string str = (string)token; + + // String value + char firstChar = str[0]; + if (firstChar == '^') + return new StringValue (str.Substring (1)); + else if( firstChar == '\n' && str.Length == 1) + return new StringValue ("\n"); + + // Glue + if (str == "<>") return new Runtime.Glue (); + + // Control commands (would looking up in a hash set be faster?) + for (int i = 0; i < _controlCommandNames.Length; ++i) { + string cmdName = _controlCommandNames [i]; + if (str == cmdName) { + return new Runtime.ControlCommand ((ControlCommand.CommandType)i); + } + } + + // Native functions + // "^" conflicts with the way to identify strings, so now + // we know it's not a string, we can convert back to the proper + // symbol for the operator. + if (str == "L^") str = "^"; + if( NativeFunctionCall.CallExistsWithName(str) ) + return NativeFunctionCall.CallWithName (str); + + // Pop + if (str == "->->") + return Runtime.ControlCommand.PopTunnel (); + else if (str == "~ret") + return Runtime.ControlCommand.PopFunction (); + + // Void + if (str == "void") + return new Runtime.Void (); + } + + if (token is Dictionary) { + + var obj = (Dictionary < string, object> )token; + object propValue; + + // Divert target value to path + if (obj.TryGetValue ("^->", out propValue)) + return new DivertTargetValue (new Path ((string)propValue)); + + // VariablePointerValue + if (obj.TryGetValue ("^var", out propValue)) { + var varPtr = new VariablePointerValue ((string)propValue); + if (obj.TryGetValue ("ci", out propValue)) + varPtr.contextIndex = (int)propValue; + return varPtr; + } + + // Divert + bool isDivert = false; + bool pushesToStack = false; + PushPopType divPushType = PushPopType.Function; + bool external = false; + if (obj.TryGetValue ("->", out propValue)) { + isDivert = true; + } + else if (obj.TryGetValue ("f()", out propValue)) { + isDivert = true; + pushesToStack = true; + divPushType = PushPopType.Function; + } + else if (obj.TryGetValue ("->t->", out propValue)) { + isDivert = true; + pushesToStack = true; + divPushType = PushPopType.Tunnel; + } + else if (obj.TryGetValue ("x()", out propValue)) { + isDivert = true; + external = true; + pushesToStack = false; + divPushType = PushPopType.Function; + } + if (isDivert) { + var divert = new Divert (); + divert.pushesToStack = pushesToStack; + divert.stackPushType = divPushType; + divert.isExternal = external; + + string target = propValue.ToString (); + + if (obj.TryGetValue ("var", out propValue)) + divert.variableDivertName = target; + else + divert.targetPathString = target; + + divert.isConditional = obj.TryGetValue("c", out propValue); + + if (external) { + if (obj.TryGetValue ("exArgs", out propValue)) + divert.externalArgs = (int)propValue; + } + + return divert; + } + + // Choice + if (obj.TryGetValue ("*", out propValue)) { + var choice = new ChoicePoint (); + choice.pathStringOnChoice = propValue.ToString(); + + if (obj.TryGetValue ("flg", out propValue)) + choice.flags = (int)propValue; + + return choice; + } + + // Variable reference + if (obj.TryGetValue ("VAR?", out propValue)) { + return new VariableReference (propValue.ToString ()); + } else if (obj.TryGetValue ("CNT?", out propValue)) { + var readCountVarRef = new VariableReference (); + readCountVarRef.pathStringForCount = propValue.ToString (); + return readCountVarRef; + } + + // Variable assignment + bool isVarAss = false; + bool isGlobalVar = false; + if (obj.TryGetValue ("VAR=", out propValue)) { + isVarAss = true; + isGlobalVar = true; + } else if (obj.TryGetValue ("temp=", out propValue)) { + isVarAss = true; + isGlobalVar = false; + } + if (isVarAss) { + var varName = propValue.ToString (); + var isNewDecl = !obj.TryGetValue("re", out propValue); + var varAss = new VariableAssignment (varName, isNewDecl); + varAss.isGlobal = isGlobalVar; + return varAss; + } + + // Legacy Tag with text + if (obj.TryGetValue ("#", out propValue)) { + return new Runtime.Tag((string)propValue); + } + + // List value + if (obj.TryGetValue ("list", out propValue)) { + var listContent = (Dictionary)propValue; + var rawList = new InkList (); + if (obj.TryGetValue ("origins", out propValue)) { + var namesAsObjs = (List)propValue; + rawList.SetInitialOriginNames (namesAsObjs.Cast().ToList()); + } + foreach (var nameToVal in listContent) { + var item = new InkListItem (nameToVal.Key); + var val = (int)nameToVal.Value; + rawList.Add (item, val); + } + return new ListValue (rawList); + } + + // Used when serialising save state only + if (obj ["originalChoicePath"] != null) + return JObjectToChoice (obj); + } + + // Array is always a Runtime.Container + if (token is List) { + return JArrayToContainer((List)token); + } + + if (token == null) + return null; + + throw new System.Exception ("Failed to convert token to runtime object: " + token); + } + + public static void WriteRuntimeContainer(SimpleJson.Writer writer, Container container, bool withoutName = false) + { + writer.WriteArrayStart(); + + foreach (var c in container.content) + WriteRuntimeObject(writer, c); + + // Container is always an array [...] + // But the final element is always either: + // - a dictionary containing the named content, as well as possibly + // the key "#" with the count flags + // - null, if neither of the above + var namedOnlyContent = container.namedOnlyContent; + var countFlags = container.countFlags; + var hasNameProperty = container.name != null && !withoutName; + + bool hasTerminator = namedOnlyContent != null || countFlags > 0 || hasNameProperty; + + if( hasTerminator ) + writer.WriteObjectStart(); + + if ( namedOnlyContent != null ) { + foreach(var namedContent in namedOnlyContent) { + var name = namedContent.Key; + var namedContainer = namedContent.Value as Container; + writer.WritePropertyStart(name); + WriteRuntimeContainer(writer, namedContainer, withoutName:true); + writer.WritePropertyEnd(); + } + } + + if (countFlags > 0) + writer.WriteProperty("#f", countFlags); + + if (hasNameProperty) + writer.WriteProperty("#n", container.name); + + if (hasTerminator) + writer.WriteObjectEnd(); + else + writer.WriteNull(); + + writer.WriteArrayEnd(); + } + + static Container JArrayToContainer(List jArray) + { + var container = new Container (); + container.content = JArrayToRuntimeObjList (jArray, skipLast:true); + + // Final object in the array is always a combination of + // - named content + // - a "#f" key with the countFlags + // (if either exists at all, otherwise null) + var terminatingObj = jArray [jArray.Count - 1] as Dictionary; + if (terminatingObj != null) { + + var namedOnlyContent = new Dictionary (terminatingObj.Count); + + foreach (var keyVal in terminatingObj) { + if (keyVal.Key == "#f") { + container.countFlags = (int)keyVal.Value; + } else if (keyVal.Key == "#n") { + container.name = keyVal.Value.ToString (); + } else { + var namedContentItem = JTokenToRuntimeObject(keyVal.Value); + var namedSubContainer = namedContentItem as Container; + if (namedSubContainer) + namedSubContainer.name = keyVal.Key; + namedOnlyContent [keyVal.Key] = namedContentItem; + } + } + + container.namedOnlyContent = namedOnlyContent; + } + + return container; + } + + static Choice JObjectToChoice(Dictionary jObj) + { + var choice = new Choice(); + choice.text = jObj ["text"].ToString(); + choice.index = (int)jObj ["index"]; + choice.sourcePath = jObj ["originalChoicePath"].ToString(); + choice.originalThreadIndex = (int)jObj ["originalThreadIndex"]; + choice.pathStringOnChoice = jObj ["targetPath"].ToString(); + return choice; + } + public static void WriteChoice(SimpleJson.Writer writer, Choice choice) + { + writer.WriteObjectStart(); + writer.WriteProperty("text", choice.text); + writer.WriteProperty("index", choice.index); + writer.WriteProperty("originalChoicePath", choice.sourcePath); + writer.WriteProperty("originalThreadIndex", choice.originalThreadIndex); + writer.WriteProperty("targetPath", choice.pathStringOnChoice); + writer.WriteObjectEnd(); + } + + static void WriteInkList(SimpleJson.Writer writer, ListValue listVal) + { + var rawList = listVal.value; + + writer.WriteObjectStart(); + + writer.WritePropertyStart("list"); + + writer.WriteObjectStart(); + + foreach (var itemAndValue in rawList) + { + var item = itemAndValue.Key; + int itemVal = itemAndValue.Value; + + writer.WritePropertyNameStart(); + writer.WritePropertyNameInner(item.originName ?? "?"); + writer.WritePropertyNameInner("."); + writer.WritePropertyNameInner(item.itemName); + writer.WritePropertyNameEnd(); + + writer.Write(itemVal); + + writer.WritePropertyEnd(); + } + + writer.WriteObjectEnd(); + + writer.WritePropertyEnd(); + + if (rawList.Count == 0 && rawList.originNames != null && rawList.originNames.Count > 0) + { + writer.WritePropertyStart("origins"); + writer.WriteArrayStart(); + foreach (var name in rawList.originNames) + writer.Write(name); + writer.WriteArrayEnd(); + writer.WritePropertyEnd(); + } + + writer.WriteObjectEnd(); + } + + public static ListDefinitionsOrigin JTokenToListDefinitions (object obj) + { + var defsObj = (Dictionary)obj; + + var allDefs = new List (); + + foreach (var kv in defsObj) { + var name = (string) kv.Key; + var listDefJson = (Dictionary)kv.Value; + + // Cast (string, object) to (string, int) for items + var items = new Dictionary (); + foreach (var nameValue in listDefJson) + items.Add(nameValue.Key, (int)nameValue.Value); + + var def = new ListDefinition (name, items); + allDefs.Add (def); + } + + return new ListDefinitionsOrigin (allDefs); + } + + static Json() + { + _controlCommandNames = new string[(int)ControlCommand.CommandType.TOTAL_VALUES]; + + _controlCommandNames [(int)ControlCommand.CommandType.EvalStart] = "ev"; + _controlCommandNames [(int)ControlCommand.CommandType.EvalOutput] = "out"; + _controlCommandNames [(int)ControlCommand.CommandType.EvalEnd] = "/ev"; + _controlCommandNames [(int)ControlCommand.CommandType.Duplicate] = "du"; + _controlCommandNames [(int)ControlCommand.CommandType.PopEvaluatedValue] = "pop"; + _controlCommandNames [(int)ControlCommand.CommandType.PopFunction] = "~ret"; + _controlCommandNames [(int)ControlCommand.CommandType.PopTunnel] = "->->"; + _controlCommandNames [(int)ControlCommand.CommandType.BeginString] = "str"; + _controlCommandNames [(int)ControlCommand.CommandType.EndString] = "/str"; + _controlCommandNames [(int)ControlCommand.CommandType.NoOp] = "nop"; + _controlCommandNames [(int)ControlCommand.CommandType.ChoiceCount] = "choiceCnt"; + _controlCommandNames [(int)ControlCommand.CommandType.Turns] = "turn"; + _controlCommandNames [(int)ControlCommand.CommandType.TurnsSince] = "turns"; + _controlCommandNames [(int)ControlCommand.CommandType.ReadCount] = "readc"; + _controlCommandNames [(int)ControlCommand.CommandType.Random] = "rnd"; + _controlCommandNames [(int)ControlCommand.CommandType.SeedRandom] = "srnd"; + _controlCommandNames [(int)ControlCommand.CommandType.VisitIndex] = "visit"; + _controlCommandNames [(int)ControlCommand.CommandType.SequenceShuffleIndex] = "seq"; + _controlCommandNames [(int)ControlCommand.CommandType.StartThread] = "thread"; + _controlCommandNames [(int)ControlCommand.CommandType.Done] = "done"; + _controlCommandNames [(int)ControlCommand.CommandType.End] = "end"; + _controlCommandNames [(int)ControlCommand.CommandType.ListFromInt] = "listInt"; + _controlCommandNames [(int)ControlCommand.CommandType.ListRange] = "range"; + _controlCommandNames [(int)ControlCommand.CommandType.ListRandom] = "lrnd"; + _controlCommandNames [(int)ControlCommand.CommandType.BeginTag] = "#"; + _controlCommandNames [(int)ControlCommand.CommandType.EndTag] = "/#"; + + for (int i = 0; i < (int)ControlCommand.CommandType.TOTAL_VALUES; ++i) { + if (_controlCommandNames [i] == null) + throw new System.Exception ("Control command not accounted for in serialisation"); + } + } + + static string[] _controlCommandNames; + } +} + + diff --git a/Assets/Ink/InkLibs/InkRuntime/ListDefinition.cs b/Assets/Ink/InkLibs/InkRuntime/ListDefinition.cs new file mode 100644 index 0000000..94370bd --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/ListDefinition.cs @@ -0,0 +1,75 @@ +using System.Collections.Generic; + +namespace Ink.Runtime +{ + public class ListDefinition + { + public string name { get { return _name; } } + + public Dictionary items { + get { + if (_items == null) { + _items = new Dictionary (); + foreach (var itemNameAndValue in _itemNameToValues) { + var item = new InkListItem (name, itemNameAndValue.Key); + _items [item] = itemNameAndValue.Value; + } + } + return _items; + } + } + Dictionary _items; + + public int ValueForItem (InkListItem item) + { + int intVal; + if (_itemNameToValues.TryGetValue (item.itemName, out intVal)) + return intVal; + else + return 0; + } + + public bool ContainsItem (InkListItem item) + { + if (item.originName != name) return false; + + return _itemNameToValues.ContainsKey (item.itemName); + } + + public bool ContainsItemWithName (string itemName) + { + return _itemNameToValues.ContainsKey (itemName); + } + + public bool TryGetItemWithValue (int val, out InkListItem item) + { + foreach (var namedItem in _itemNameToValues) { + if (namedItem.Value == val) { + item = new InkListItem (name, namedItem.Key); + return true; + } + } + + item = InkListItem.Null; + return false; + } + + public bool TryGetValueForItem (InkListItem item, out int intVal) + { + return _itemNameToValues.TryGetValue (item.itemName, out intVal); + } + + public ListDefinition (string name, Dictionary items) + { + _name = name; + _itemNameToValues = items; + } + + string _name; + + // The main representation should be simple item names rather than a RawListItem, + // since we mainly want to access items based on their simple name, since that's + // how they'll be most commonly requested from ink. + Dictionary _itemNameToValues; + } +} diff --git a/Assets/Ink/InkLibs/InkRuntime/ListDefinitionsOrigin.cs b/Assets/Ink/InkLibs/InkRuntime/ListDefinitionsOrigin.cs new file mode 100644 index 0000000..9fc3389 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/ListDefinitionsOrigin.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; + +namespace Ink.Runtime +{ + public class ListDefinitionsOrigin + { + public List lists { + get { + var listOfLists = new List (); + foreach (var namedList in _lists) { + listOfLists.Add (namedList.Value); + } + return listOfLists; + } + } + + public ListDefinitionsOrigin (List lists) + { + _lists = new Dictionary (); + _allUnambiguousListValueCache = new Dictionary(); + + foreach (var list in lists) { + _lists [list.name] = list; + + foreach(var itemWithValue in list.items) { + var item = itemWithValue.Key; + var val = itemWithValue.Value; + var listValue = new ListValue(item, val); + + // May be ambiguous, but compiler should've caught that, + // so we may be doing some replacement here, but that's okay. + _allUnambiguousListValueCache[item.itemName] = listValue; + _allUnambiguousListValueCache[item.fullName] = listValue; + } + } + } + + public bool TryListGetDefinition (string name, out ListDefinition def) + { + return _lists.TryGetValue (name, out def); + } + + public ListValue FindSingleItemListWithName (string name) + { + ListValue val = null; + _allUnambiguousListValueCache.TryGetValue(name, out val); + return val; + } + + Dictionary _lists; + Dictionary _allUnambiguousListValueCache; + } +} diff --git a/Assets/Ink/InkLibs/InkRuntime/NativeFunctionCall.cs b/Assets/Ink/InkLibs/InkRuntime/NativeFunctionCall.cs new file mode 100644 index 0000000..b610651 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/NativeFunctionCall.cs @@ -0,0 +1,508 @@ +using System; +using System.Collections.Generic; + +namespace Ink.Runtime +{ + public class NativeFunctionCall : Runtime.Object + { + public const string Add = "+"; + public const string Subtract = "-"; + public const string Divide = "/"; + public const string Multiply = "*"; + public const string Mod = "%"; + public const string Negate = "_"; // distinguish from "-" for subtraction + + public const string Equal = "=="; + public const string Greater = ">"; + public const string Less = "<"; + public const string GreaterThanOrEquals = ">="; + public const string LessThanOrEquals = "<="; + public const string NotEquals = "!="; + public const string Not = "!"; + + + + public const string And = "&&"; + public const string Or = "||"; + + public const string Min = "MIN"; + public const string Max = "MAX"; + + public const string Pow = "POW"; + public const string Floor = "FLOOR"; + public const string Ceiling = "CEILING"; + public const string Int = "INT"; + public const string Float = "FLOAT"; + + public const string Has = "?"; + public const string Hasnt = "!?"; + public const string Intersect = "^"; + + public const string ListMin = "LIST_MIN"; + public const string ListMax = "LIST_MAX"; + public const string All = "LIST_ALL"; + public const string Count = "LIST_COUNT"; + public const string ValueOfList = "LIST_VALUE"; + public const string Invert = "LIST_INVERT"; + + public static NativeFunctionCall CallWithName(string functionName) + { + return new NativeFunctionCall (functionName); + } + + public static bool CallExistsWithName(string functionName) + { + GenerateNativeFunctionsIfNecessary (); + return _nativeFunctions.ContainsKey (functionName); + } + + public string name { + get { + return _name; + } + protected set { + _name = value; + if( !_isPrototype ) + _prototype = _nativeFunctions [_name]; + } + } + string _name; + + public int numberOfParameters { + get { + if (_prototype) { + return _prototype.numberOfParameters; + } else { + return _numberOfParameters; + } + } + protected set { + _numberOfParameters = value; + } + } + + int _numberOfParameters; + + public Runtime.Object Call(List parameters) + { + if (_prototype) { + return _prototype.Call(parameters); + } + + if (numberOfParameters != parameters.Count) { + throw new System.Exception ("Unexpected number of parameters"); + } + + bool hasList = false; + foreach (var p in parameters) { + if (p is Void) + throw new StoryException ("Attempting to perform operation on a void value. Did you forget to 'return' a value from a function you called here?"); + if (p is ListValue) + hasList = true; + } + + // Binary operations on lists are treated outside of the standard coerscion rules + if( parameters.Count == 2 && hasList ) + return CallBinaryListOperation (parameters); + + var coercedParams = CoerceValuesToSingleType (parameters); + ValueType coercedType = coercedParams[0].valueType; + + if (coercedType == ValueType.Int) { + return Call (coercedParams); + } else if (coercedType == ValueType.Float) { + return Call (coercedParams); + } else if (coercedType == ValueType.String) { + return Call (coercedParams); + } else if (coercedType == ValueType.DivertTarget) { + return Call (coercedParams); + } else if (coercedType == ValueType.List) { + return Call (coercedParams); + } + + return null; + } + + Value Call(List parametersOfSingleType) + { + Value param1 = (Value) parametersOfSingleType [0]; + ValueType valType = param1.valueType; + + var val1 = (Value)param1; + + int paramCount = parametersOfSingleType.Count; + + if (paramCount == 2 || paramCount == 1) { + + object opForTypeObj = null; + if (!_operationFuncs.TryGetValue (valType, out opForTypeObj)) { + throw new StoryException ("Cannot perform operation '"+this.name+"' on "+valType); + } + + // Binary + if (paramCount == 2) { + Value param2 = (Value) parametersOfSingleType [1]; + + var val2 = (Value)param2; + + var opForType = (BinaryOp)opForTypeObj; + + // Return value unknown until it's evaluated + object resultVal = opForType (val1.value, val2.value); + + return Value.Create (resultVal); + } + + // Unary + else { + + var opForType = (UnaryOp)opForTypeObj; + + var resultVal = opForType (val1.value); + + return Value.Create (resultVal); + } + } + + else { + throw new System.Exception ("Unexpected number of parameters to NativeFunctionCall: " + parametersOfSingleType.Count); + } + } + + Value CallBinaryListOperation (List parameters) + { + // List-Int addition/subtraction returns a List (e.g. "alpha" + 1 = "beta") + if ((name == "+" || name == "-") && parameters [0] is ListValue && parameters [1] is IntValue) + return CallListIncrementOperation (parameters); + + var v1 = parameters [0] as Value; + var v2 = parameters [1] as Value; + + // And/or with any other type requires coerscion to bool (int) + if ((name == "&&" || name == "||") && (v1.valueType != ValueType.List || v2.valueType != ValueType.List)) { + var op = _operationFuncs [ValueType.Int] as BinaryOp; + var result = (bool)op (v1.isTruthy ? 1 : 0, v2.isTruthy ? 1 : 0); + return new BoolValue (result); + } + + // Normal (list • list) operation + if (v1.valueType == ValueType.List && v2.valueType == ValueType.List) + return Call (new List { v1, v2 }); + + throw new StoryException ("Can not call use '" + name + "' operation on " + v1.valueType + " and " + v2.valueType); + } + + Value CallListIncrementOperation (List listIntParams) + { + var listVal = (ListValue)listIntParams [0]; + var intVal = (IntValue)listIntParams [1]; + + + var resultRawList = new InkList (); + + foreach (var listItemWithValue in listVal.value) { + var listItem = listItemWithValue.Key; + var listItemValue = listItemWithValue.Value; + + // Find + or - operation + var intOp = (BinaryOp)_operationFuncs [ValueType.Int]; + + // Return value unknown until it's evaluated + int targetInt = (int) intOp (listItemValue, intVal.value); + + // Find this item's origin (linear search should be ok, should be short haha) + ListDefinition itemOrigin = null; + foreach (var origin in listVal.value.origins) { + if (origin.name == listItem.originName) { + itemOrigin = origin; + break; + } + } + if (itemOrigin != null) { + InkListItem incrementedItem; + if (itemOrigin.TryGetItemWithValue (targetInt, out incrementedItem)) + resultRawList.Add (incrementedItem, targetInt); + } + } + + return new ListValue (resultRawList); + } + + List CoerceValuesToSingleType(List parametersIn) + { + ValueType valType = ValueType.Int; + + ListValue specialCaseList = null; + + // Find out what the output type is + // "higher level" types infect both so that binary operations + // use the same type on both sides. e.g. binary operation of + // int and float causes the int to be casted to a float. + foreach (var obj in parametersIn) { + var val = (Value)obj; + if (val.valueType > valType) { + valType = val.valueType; + } + + if (val.valueType == ValueType.List) { + specialCaseList = val as ListValue; + } + } + + // Coerce to this chosen type + var parametersOut = new List (); + + // Special case: Coercing to Ints to Lists + // We have to do it early when we have both parameters + // to hand - so that we can make use of the List's origin + if (valType == ValueType.List) { + + foreach (Value val in parametersIn) { + if (val.valueType == ValueType.List) { + parametersOut.Add (val); + } else if (val.valueType == ValueType.Int) { + int intVal = (int)val.valueObject; + var list = specialCaseList.value.originOfMaxItem; + + InkListItem item; + if (list.TryGetItemWithValue (intVal, out item)) { + var castedValue = new ListValue (item, intVal); + parametersOut.Add (castedValue); + } else + throw new StoryException ("Could not find List item with the value " + intVal + " in " + list.name); + } else + throw new StoryException ("Cannot mix Lists and " + val.valueType + " values in this operation"); + } + + } + + // Normal Coercing (with standard casting) + else { + foreach (Value val in parametersIn) { + var castedValue = val.Cast (valType); + parametersOut.Add (castedValue); + } + } + + return parametersOut; + } + + public NativeFunctionCall(string name) + { + GenerateNativeFunctionsIfNecessary (); + + this.name = name; + } + + // Require default constructor for serialisation + public NativeFunctionCall() { + GenerateNativeFunctionsIfNecessary (); + } + + // Only called internally to generate prototypes + NativeFunctionCall (string name, int numberOfParameters) + { + _isPrototype = true; + this.name = name; + this.numberOfParameters = numberOfParameters; + } + + // For defining operations that do nothing to the specific type + // (but are still supported), such as floor/ceil on int and float + // cast on float. + static object Identity(T t) { + return t; + } + + static void GenerateNativeFunctionsIfNecessary() + { + if (_nativeFunctions == null) { + _nativeFunctions = new Dictionary (); + + // Why no bool operations? + // Before evaluation, all bools are coerced to ints in + // CoerceValuesToSingleType (see default value for valType at top). + // So, no operations are ever directly done in bools themselves. + // This also means that 1 == true works, since true is always converted + // to 1 first. + // However, many operations return a "native" bool (equals, etc). + + // Int operations + AddIntBinaryOp(Add, (x, y) => x + y); + AddIntBinaryOp(Subtract, (x, y) => x - y); + AddIntBinaryOp(Multiply, (x, y) => x * y); + AddIntBinaryOp(Divide, (x, y) => x / y); + AddIntBinaryOp(Mod, (x, y) => x % y); + AddIntUnaryOp (Negate, x => -x); + + AddIntBinaryOp(Equal, (x, y) => x == y); + AddIntBinaryOp(Greater, (x, y) => x > y); + AddIntBinaryOp(Less, (x, y) => x < y); + AddIntBinaryOp(GreaterThanOrEquals, (x, y) => x >= y); + AddIntBinaryOp(LessThanOrEquals, (x, y) => x <= y); + AddIntBinaryOp(NotEquals, (x, y) => x != y); + AddIntUnaryOp (Not, x => x == 0); + + AddIntBinaryOp(And, (x, y) => x != 0 && y != 0); + AddIntBinaryOp(Or, (x, y) => x != 0 || y != 0); + + AddIntBinaryOp(Max, (x, y) => Math.Max(x, y)); + AddIntBinaryOp(Min, (x, y) => Math.Min(x, y)); + + // Have to cast to float since you could do POW(2, -1) + AddIntBinaryOp (Pow, (x, y) => (float) Math.Pow(x, y)); + AddIntUnaryOp(Floor, Identity); + AddIntUnaryOp(Ceiling, Identity); + AddIntUnaryOp(Int, Identity); + AddIntUnaryOp (Float, x => (float)x); + + // Float operations + AddFloatBinaryOp(Add, (x, y) => x + y); + AddFloatBinaryOp(Subtract, (x, y) => x - y); + AddFloatBinaryOp(Multiply, (x, y) => x * y); + AddFloatBinaryOp(Divide, (x, y) => x / y); + AddFloatBinaryOp(Mod, (x, y) => x % y); // TODO: Is this the operation we want for floats? + AddFloatUnaryOp (Negate, x => -x); + + AddFloatBinaryOp(Equal, (x, y) => x == y); + AddFloatBinaryOp(Greater, (x, y) => x > y); + AddFloatBinaryOp(Less, (x, y) => x < y); + AddFloatBinaryOp(GreaterThanOrEquals, (x, y) => x >= y); + AddFloatBinaryOp(LessThanOrEquals, (x, y) => x <= y); + AddFloatBinaryOp(NotEquals, (x, y) => x != y); + AddFloatUnaryOp (Not, x => (x == 0.0f)); + + AddFloatBinaryOp(And, (x, y) => x != 0.0f && y != 0.0f); + AddFloatBinaryOp(Or, (x, y) => x != 0.0f || y != 0.0f); + + AddFloatBinaryOp(Max, (x, y) => Math.Max(x, y)); + AddFloatBinaryOp(Min, (x, y) => Math.Min(x, y)); + + AddFloatBinaryOp (Pow, (x, y) => (float)Math.Pow(x, y)); + AddFloatUnaryOp(Floor, x => (float)Math.Floor(x)); + AddFloatUnaryOp(Ceiling, x => (float)Math.Ceiling(x)); + AddFloatUnaryOp(Int, x => (int)x); + AddFloatUnaryOp(Float, Identity); + + // String operations + AddStringBinaryOp(Add, (x, y) => x + y); // concat + AddStringBinaryOp(Equal, (x, y) => x.Equals(y)); + AddStringBinaryOp (NotEquals, (x, y) => !x.Equals (y)); + AddStringBinaryOp (Has, (x, y) => x.Contains(y)); + AddStringBinaryOp (Hasnt, (x, y) => !x.Contains(y)); + + // List operations + AddListBinaryOp (Add, (x, y) => x.Union (y)); + AddListBinaryOp (Subtract, (x, y) => x.Without(y)); + AddListBinaryOp (Has, (x, y) => x.Contains (y)); + AddListBinaryOp (Hasnt, (x, y) => !x.Contains (y)); + AddListBinaryOp (Intersect, (x, y) => x.Intersect (y)); + + AddListBinaryOp (Equal, (x, y) => x.Equals(y)); + AddListBinaryOp (Greater, (x, y) => x.GreaterThan(y)); + AddListBinaryOp (Less, (x, y) => x.LessThan(y)); + AddListBinaryOp (GreaterThanOrEquals, (x, y) => x.GreaterThanOrEquals(y)); + AddListBinaryOp (LessThanOrEquals, (x, y) => x.LessThanOrEquals(y)); + AddListBinaryOp (NotEquals, (x, y) => !x.Equals(y)); + + AddListBinaryOp (And, (x, y) => x.Count > 0 && y.Count > 0); + AddListBinaryOp (Or, (x, y) => x.Count > 0 || y.Count > 0); + + AddListUnaryOp (Not, x => x.Count == 0 ? (int)1 : (int)0); + + // Placeholders to ensure that these special case functions can exist, + // since these function is never actually run, and is special cased in Call + AddListUnaryOp (Invert, x => x.inverse); + AddListUnaryOp (All, x => x.all); + AddListUnaryOp (ListMin, (x) => x.MinAsList()); + AddListUnaryOp (ListMax, (x) => x.MaxAsList()); + AddListUnaryOp (Count, (x) => x.Count); + AddListUnaryOp (ValueOfList, (x) => x.maxItem.Value); + + // Special case: The only operations you can do on divert target values + BinaryOp divertTargetsEqual = (Path d1, Path d2) => { + return d1.Equals (d2); + }; + BinaryOp divertTargetsNotEqual = (Path d1, Path d2) => { + return !d1.Equals (d2); + }; + AddOpToNativeFunc (Equal, 2, ValueType.DivertTarget, divertTargetsEqual); + AddOpToNativeFunc (NotEquals, 2, ValueType.DivertTarget, divertTargetsNotEqual); + + } + } + + void AddOpFuncForType(ValueType valType, object op) + { + if (_operationFuncs == null) { + _operationFuncs = new Dictionary (); + } + + _operationFuncs [valType] = op; + } + + static void AddOpToNativeFunc(string name, int args, ValueType valType, object op) + { + NativeFunctionCall nativeFunc = null; + if (!_nativeFunctions.TryGetValue (name, out nativeFunc)) { + nativeFunc = new NativeFunctionCall (name, args); + _nativeFunctions [name] = nativeFunc; + } + + nativeFunc.AddOpFuncForType (valType, op); + } + + static void AddIntBinaryOp(string name, BinaryOp op) + { + AddOpToNativeFunc (name, 2, ValueType.Int, op); + } + + static void AddIntUnaryOp(string name, UnaryOp op) + { + AddOpToNativeFunc (name, 1, ValueType.Int, op); + } + + static void AddFloatBinaryOp(string name, BinaryOp op) + { + AddOpToNativeFunc (name, 2, ValueType.Float, op); + } + + static void AddStringBinaryOp(string name, BinaryOp op) + { + AddOpToNativeFunc (name, 2, ValueType.String, op); + } + + static void AddListBinaryOp (string name, BinaryOp op) + { + AddOpToNativeFunc (name, 2, ValueType.List, op); + } + + static void AddListUnaryOp (string name, UnaryOp op) + { + AddOpToNativeFunc (name, 1, ValueType.List, op); + } + + static void AddFloatUnaryOp(string name, UnaryOp op) + { + AddOpToNativeFunc (name, 1, ValueType.Float, op); + } + + public override string ToString () + { + return "Native '" + name + "'"; + } + + delegate object BinaryOp(T left, T right); + delegate object UnaryOp(T val); + + NativeFunctionCall _prototype; + bool _isPrototype; + + // Operations for each data type, for a single operation (e.g. "+") + Dictionary _operationFuncs; + + static Dictionary _nativeFunctions; + + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/Object.cs b/Assets/Ink/InkLibs/InkRuntime/Object.cs new file mode 100644 index 0000000..8a5c41b --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/Object.cs @@ -0,0 +1,250 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Ink.Runtime +{ + /// + /// Base class for all ink runtime content. + /// + public /* TODO: abstract */ class Object + { + /// + /// Runtime.Objects can be included in the main Story as a hierarchy. + /// Usually parents are Container objects. (TODO: Always?) + /// + /// The parent. + public Runtime.Object parent { get; set; } + + public Runtime.DebugMetadata debugMetadata { + get { + if (_debugMetadata == null) { + if (parent) { + return parent.debugMetadata; + } + } + + return _debugMetadata; + } + + set { + _debugMetadata = value; + } + } + + public Runtime.DebugMetadata ownDebugMetadata { + get { + return _debugMetadata; + } + } + + // TODO: Come up with some clever solution for not having + // to have debug metadata on the object itself, perhaps + // for serialisation purposes at least. + DebugMetadata _debugMetadata; + + public int? DebugLineNumberOfPath(Path path) + { + if (path == null) + return null; + + // Try to get a line number from debug metadata + var root = this.rootContentContainer; + if (root) { + Runtime.Object targetContent = root.ContentAtPath (path).obj; + if (targetContent) { + var dm = targetContent.debugMetadata; + if (dm != null) { + return dm.startLineNumber; + } + } + } + + return null; + } + + public Path path + { + get + { + if (_path == null) { + + if (parent == null) { + _path = new Path (); + } else { + // Maintain a Stack so that the order of the components + // is reversed when they're added to the Path. + // We're iterating up the hierarchy from the leaves/children to the root. + var comps = new Stack (); + + var child = this; + Container container = child.parent as Container; + + while (container) { + + var namedChild = child as INamedContent; + if (namedChild != null && namedChild.hasValidName) { + comps.Push (new Path.Component (namedChild.name)); + } else { + comps.Push (new Path.Component (container.content.IndexOf(child))); + } + + child = container; + container = container.parent as Container; + } + + _path = new Path (comps); + } + + } + + return _path; + } + } + Path _path; + + public SearchResult ResolvePath(Path path) + { + if (path.isRelative) { + + Container nearestContainer = this as Container; + if (!nearestContainer) { + Debug.Assert (this.parent != null, "Can't resolve relative path because we don't have a parent"); + nearestContainer = this.parent as Container; + Debug.Assert (nearestContainer != null, "Expected parent to be a container"); + Debug.Assert (path.GetComponent(0).isParent); + path = path.tail; + } + + return nearestContainer.ContentAtPath (path); + } else { + return this.rootContentContainer.ContentAtPath (path); + } + } + + public Path ConvertPathToRelative(Path globalPath) + { + // 1. Find last shared ancestor + // 2. Drill up using ".." style (actually represented as "^") + // 3. Re-build downward chain from common ancestor + + var ownPath = this.path; + + int minPathLength = Math.Min (globalPath.length, ownPath.length); + int lastSharedPathCompIndex = -1; + + for (int i = 0; i < minPathLength; ++i) { + var ownComp = ownPath.GetComponent(i); + var otherComp = globalPath.GetComponent(i); + + if (ownComp.Equals (otherComp)) { + lastSharedPathCompIndex = i; + } else { + break; + } + } + + // No shared path components, so just use global path + if (lastSharedPathCompIndex == -1) + return globalPath; + + int numUpwardsMoves = (ownPath.length-1) - lastSharedPathCompIndex; + + var newPathComps = new List (); + + for(int up=0; up(ref T obj, T value) where T : Runtime.Object + { + if (obj) + obj.parent = null; + + obj = value; + + if( obj ) + obj.parent = this; + } + + /// Allow implicit conversion to bool so you don't have to do: + /// if( myObj != null ) ... + public static implicit operator bool (Object obj) + { + var isNull = object.ReferenceEquals (obj, null); + return !isNull; + } + + /// Required for implicit bool comparison + public static bool operator ==(Object a, Object b) + { + return object.ReferenceEquals (a, b); + } + + /// Required for implicit bool comparison + public static bool operator !=(Object a, Object b) + { + return !(a == b); + } + + /// Required for implicit bool comparison + public override bool Equals (object obj) + { + return object.ReferenceEquals (obj, this); + } + + /// Required for implicit bool comparison + public override int GetHashCode () + { + return base.GetHashCode (); + } + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/Path.cs b/Assets/Ink/InkLibs/InkRuntime/Path.cs new file mode 100644 index 0000000..428b2fc --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/Path.cs @@ -0,0 +1,277 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Diagnostics; +using Ink.Runtime; + +namespace Ink.Runtime +{ + public class Path : IEquatable + { + static string parentId = "^"; + + // Immutable Component + public class Component : IEquatable + { + public int index { get; private set; } + public string name { get; private set; } + public bool isIndex { get { return index >= 0; } } + public bool isParent { + get { + return name == Path.parentId; + } + } + + public Component(int index) + { + Debug.Assert(index >= 0); + this.index = index; + this.name = null; + } + + public Component(string name) + { + Debug.Assert(name != null && name.Length > 0); + this.name = name; + this.index = -1; + } + + public static Component ToParent() + { + return new Component (parentId); + } + + public override string ToString () + { + if (isIndex) { + return index.ToString (); + } else { + return name; + } + } + + public override bool Equals (object obj) + { + return Equals (obj as Component); + } + + public bool Equals(Component otherComp) + { + if (otherComp != null && otherComp.isIndex == this.isIndex) { + if (isIndex) { + return index == otherComp.index; + } else { + return name == otherComp.name; + } + } + + return false; + } + + public override int GetHashCode () + { + if (isIndex) + return this.index; + else + return this.name.GetHashCode (); + } + } + + public Component GetComponent(int index) + { + return _components[index]; + } + + public bool isRelative { get; private set; } + + public Component head + { + get + { + if (_components.Count > 0) { + return _components.First (); + } else { + return null; + } + } + } + + public Path tail + { + get + { + if (_components.Count >= 2) { + List tailComps = _components.GetRange (1, _components.Count - 1); + return new Path(tailComps); + } + + else { + return Path.self; + } + + } + } + + public int length { get { return _components.Count; } } + + public Component lastComponent + { + get + { + var lastComponentIdx = _components.Count-1; + if( lastComponentIdx >= 0 ) + return _components[lastComponentIdx]; + else + return null; + } + } + + public bool containsNamedComponent { + get { + foreach(var comp in _components) { + if( !comp.isIndex ) { + return true; + } + } + return false; + } + } + + public Path() + { + _components = new List (); + } + + public Path(Component head, Path tail) : this() + { + _components.Add (head); + _components.AddRange (tail._components); + } + + public Path(IEnumerable components, bool relative = false) : this() + { + this._components.AddRange (components); + this.isRelative = relative; + } + + public Path(string componentsString) : this() + { + this.componentsString = componentsString; + } + + public static Path self { + get { + var path = new Path (); + path.isRelative = true; + return path; + } + } + + public Path PathByAppendingPath(Path pathToAppend) + { + Path p = new Path (); + + int upwardMoves = 0; + for (int i = 0; i < pathToAppend._components.Count; ++i) { + if (pathToAppend._components [i].isParent) { + upwardMoves++; + } else { + break; + } + } + + for (int i = 0; i < this._components.Count - upwardMoves; ++i) { + p._components.Add (this._components [i]); + } + + for(int i=upwardMoves; i _components; + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/Pointer.cs b/Assets/Ink/InkLibs/InkRuntime/Pointer.cs new file mode 100644 index 0000000..66fec9a --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/Pointer.cs @@ -0,0 +1,70 @@ +using Ink.Runtime; + +namespace Ink.Runtime +{ + /// + /// Internal structure used to point to a particular / current point in the story. + /// Where Path is a set of components that make content fully addressable, this is + /// a reference to the current container, and the index of the current piece of + /// content within that container. This scheme makes it as fast and efficient as + /// possible to increment the pointer (move the story forwards) in a way that's as + /// native to the internal engine as possible. + /// + public struct Pointer + { + public Container container; + public int index; + + public Pointer (Container container, int index) + { + this.container = container; + this.index = index; + } + + public Runtime.Object Resolve () + { + if (index < 0) return container; + if (container == null) return null; + if (container.content.Count == 0) return container; + if (index >= container.content.Count) return null; + return container.content [index]; + + } + + public bool isNull { + get { + return container == null; + } + } + + public Path path { + get { + if( isNull ) return null; + + if (index >= 0) + return container.path.PathByAppendingComponent (new Path.Component(index)); + else + return container.path; + } + } + + public override string ToString () + { + if (container == null) + return "Ink Pointer (null)"; + + return "Ink Pointer -> " + container.path.ToString () + " -- index " + index; + } + + public static Pointer StartOf (Container container) + { + return new Pointer { + container = container, + index = 0 + }; + } + + public static Pointer Null = new Pointer { container = null, index = -1 }; + + } +} \ No newline at end of file diff --git a/Assets/Ink/InkLibs/InkRuntime/Profiler.cs b/Assets/Ink/InkLibs/InkRuntime/Profiler.cs new file mode 100644 index 0000000..5de70a1 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/Profiler.cs @@ -0,0 +1,394 @@ +using System; +using System.Diagnostics; +using System.Collections.Generic; +using System.Text; +using System.Linq; + +namespace Ink.Runtime +{ + /// + /// Simple ink profiler that logs every instruction in the story and counts frequency and timing. + /// To use: + /// + /// var profiler = story.StartProfiling(), + /// + /// (play your story for a bit) + /// + /// var reportStr = profiler.Report(); + /// + /// story.EndProfiling(); + /// + /// + public class Profiler + { + /// + /// The root node in the hierarchical tree of recorded ink timings. + /// + public ProfileNode rootNode { + get { + return _rootNode; + } + } + + public Profiler() { + _rootNode = new ProfileNode(); + } + + /// + /// Generate a printable report based on the data recording during profiling. + /// + public string Report() { + var sb = new StringBuilder(); + sb.AppendFormat("{0} CONTINUES / LINES:\n", _numContinues); + sb.AppendFormat("TOTAL TIME: {0}\n", FormatMillisecs(_continueTotal)); + sb.AppendFormat("SNAPSHOTTING: {0}\n", FormatMillisecs(_snapTotal)); + sb.AppendFormat("OTHER: {0}\n", FormatMillisecs(_continueTotal - (_stepTotal + _snapTotal))); + sb.Append(_rootNode.ToString()); + return sb.ToString(); + } + + public void PreContinue() { + _continueWatch.Reset(); + _continueWatch.Start(); + } + + public void PostContinue() { + _continueWatch.Stop(); + _continueTotal += Millisecs(_continueWatch); + _numContinues++; + } + + public void PreStep() { + _currStepStack = null; + _stepWatch.Reset(); + _stepWatch.Start(); + } + + public void Step(CallStack callstack) + { + _stepWatch.Stop(); + + var stack = new string[callstack.elements.Count]; + for(int i=0; i + /// Generate a printable report specifying the average and maximum times spent + /// stepping over different internal ink instruction types. + /// This report type is primarily used to profile the ink engine itself rather + /// than your own specific ink. + /// + public string StepLengthReport() + { + var sb = new StringBuilder(); + + sb.AppendLine("TOTAL: "+_rootNode.totalMillisecs+"ms"); + + var averageStepTimes = _stepDetails + .GroupBy(s => s.type) + .Select(typeToDetails => new KeyValuePair(typeToDetails.Key, typeToDetails.Average(d => d.time))) + .OrderByDescending(stepTypeToAverage => stepTypeToAverage.Value) + .Select(stepTypeToAverage => { + var typeName = stepTypeToAverage.Key; + var time = stepTypeToAverage.Value; + return typeName + ": " + time + "ms"; + }) + .ToArray(); + + sb.AppendLine("AVERAGE STEP TIMES: "+string.Join(", ", averageStepTimes)); + + var accumStepTimes = _stepDetails + .GroupBy(s => s.type) + .Select(typeToDetails => new KeyValuePair(typeToDetails.Key + " (x"+typeToDetails.Count()+")", typeToDetails.Sum(d => d.time))) + .OrderByDescending(stepTypeToAccum => stepTypeToAccum.Value) + .Select(stepTypeToAccum => { + var typeName = stepTypeToAccum.Key; + var time = stepTypeToAccum.Value; + return typeName + ": " + time; + }) + .ToArray(); + + sb.AppendLine("ACCUMULATED STEP TIMES: "+string.Join(", ", accumStepTimes)); + + return sb.ToString(); + } + + /// + /// Create a large log of all the internal instructions that were evaluated while profiling was active. + /// Log is in a tab-separated format, for easy loading into a spreadsheet application. + /// + public string Megalog() + { + var sb = new StringBuilder(); + + sb.AppendLine("Step type\tDescription\tPath\tTime"); + + foreach(var step in _stepDetails) { + sb.Append(step.type); + sb.Append("\t"); + sb.Append(step.obj.ToString()); + sb.Append("\t"); + sb.Append(step.obj.path); + sb.Append("\t"); + sb.AppendLine(step.time.ToString("F8")); + } + + return sb.ToString(); + } + + public void PreSnapshot() { + _snapWatch.Reset(); + _snapWatch.Start(); + } + + public void PostSnapshot() { + _snapWatch.Stop(); + _snapTotal += Millisecs(_snapWatch); + } + + double Millisecs(Stopwatch watch) + { + var ticks = watch.ElapsedTicks; + return ticks * _millisecsPerTick; + } + + public static string FormatMillisecs(double num) { + if( num > 5000 ) { + return string.Format("{0:N1} secs", num / 1000.0); + } if( num > 1000 ) { + return string.Format("{0:N2} secs", num / 1000.0); + } else if( num > 100 ) { + return string.Format("{0:N0} ms", num); + } else if( num > 1 ) { + return string.Format("{0:N1} ms", num); + } else if( num > 0.01 ) { + return string.Format("{0:N3} ms", num); + } else { + return string.Format("{0:N} ms", num); + } + } + + Stopwatch _continueWatch = new Stopwatch(); + Stopwatch _stepWatch = new Stopwatch(); + Stopwatch _snapWatch = new Stopwatch(); + + double _continueTotal; + double _snapTotal; + double _stepTotal; + + string[] _currStepStack; + StepDetails _currStepDetails; + ProfileNode _rootNode; + int _numContinues; + + struct StepDetails { + public string type; + public Runtime.Object obj; + public double time; + } + List _stepDetails = new List(); + + static double _millisecsPerTick = 1000.0 / Stopwatch.Frequency; + } + + + /// + /// Node used in the hierarchical tree of timings used by the Profiler. + /// Each node corresponds to a single line viewable in a UI-based representation. + /// + public class ProfileNode { + + /// + /// The key for the node corresponds to the printable name of the callstack element. + /// + public readonly string key; + + + #pragma warning disable 0649 + /// + /// Horribly hacky field only used by ink unity integration, + /// but saves constructing an entire data structure that mirrors + /// the one in here purely to store the state of whether each + /// node in the UI has been opened or not /// + public bool openInUI; + #pragma warning restore 0649 + + /// + /// Whether this node contains any sub-nodes - i.e. does it call anything else + /// that has been recorded? + /// + /// true if has children; otherwise, false. + public bool hasChildren { + get { + return _nodes != null && _nodes.Count > 0; + } + } + + /// + /// Total number of milliseconds this node has been active for. + /// + public int totalMillisecs { + get { + return (int)_totalMillisecs; + } + } + + public ProfileNode() { + + } + + public ProfileNode(string key) { + this.key = key; + } + + public void AddSample(string[] stack, double duration) { + AddSample(stack, -1, duration); + } + + void AddSample(string[] stack, int stackIdx, double duration) { + + _totalSampleCount++; + _totalMillisecs += duration; + + if( stackIdx == stack.Length-1 ) { + _selfSampleCount++; + _selfMillisecs += duration; + } + + if( stackIdx+1 < stack.Length ) + AddSampleToNode(stack, stackIdx+1, duration); + } + + void AddSampleToNode(string[] stack, int stackIdx, double duration) + { + var nodeKey = stack[stackIdx]; + if( _nodes == null ) _nodes = new Dictionary(); + + ProfileNode node; + if( !_nodes.TryGetValue(nodeKey, out node) ) { + node = new ProfileNode(nodeKey); + _nodes[nodeKey] = node; + } + + node.AddSample(stack, stackIdx, duration); + } + + /// + /// Returns a sorted enumerable of the nodes in descending order of + /// how long they took to run. + /// + public IEnumerable> descendingOrderedNodes { + get { + if( _nodes == null ) return null; + return _nodes.OrderByDescending(keyNode => keyNode.Value._totalMillisecs); + } + } + + void PrintHierarchy(StringBuilder sb, int indent) + { + Pad(sb, indent); + + sb.Append(key); + sb.Append(": "); + sb.AppendLine(ownReport); + + if( _nodes == null ) return; + + foreach(var keyNode in descendingOrderedNodes) { + keyNode.Value.PrintHierarchy(sb, indent+1); + } + } + + /// + /// Generates a string giving timing information for this single node, including + /// total milliseconds spent on the piece of ink, the time spent within itself + /// (v.s. spent in children), as well as the number of samples (instruction steps) + /// recorded for both too. + /// + /// The own report. + public string ownReport { + get { + var sb = new StringBuilder(); + sb.Append("total "); + sb.Append(Profiler.FormatMillisecs(_totalMillisecs)); + sb.Append(", self "); + sb.Append(Profiler.FormatMillisecs(_selfMillisecs)); + sb.Append(" ("); + sb.Append(_selfSampleCount); + sb.Append(" self samples, "); + sb.Append(_totalSampleCount); + sb.Append(" total)"); + return sb.ToString(); + } + + } + + void Pad(StringBuilder sb, int spaces) + { + for(int i=0; i + /// String is a report of the sub-tree from this node, but without any of the header information + /// that's prepended by the Profiler in its Report() method. + /// + public override string ToString () + { + var sb = new StringBuilder(); + PrintHierarchy(sb, 0); + return sb.ToString(); + } + + Dictionary _nodes; + double _selfMillisecs; + double _totalMillisecs; + int _selfSampleCount; + int _totalSampleCount; + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/PushPop.cs b/Assets/Ink/InkLibs/InkRuntime/PushPop.cs new file mode 100644 index 0000000..42a29bf --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/PushPop.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace Ink.Runtime +{ + public enum PushPopType + { + Tunnel, + Function, + FunctionEvaluationFromGame + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/SearchResult.cs b/Assets/Ink/InkLibs/InkRuntime/SearchResult.cs new file mode 100644 index 0000000..e3a8c24 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/SearchResult.cs @@ -0,0 +1,18 @@ +using System; +namespace Ink.Runtime +{ + // When looking up content within the story (e.g. in Container.ContentAtPath), + // the result is generally found, but if the story is modified, then when loading + // up an old save state, then some old paths may still exist. In this case we + // try to recover by finding an approximate result by working up the story hierarchy + // in the path to find the closest valid container. Instead of crashing horribly, + // we might see some slight oddness in the content, but hopefully it recovers! + public struct SearchResult + { + public Runtime.Object obj; + public bool approximate; + + public Runtime.Object correctObj { get { return approximate ? null : obj; } } + public Container container { get { return obj as Container; } } + } +} diff --git a/Assets/Ink/InkLibs/InkRuntime/SimpleJson.cs b/Assets/Ink/InkLibs/InkRuntime/SimpleJson.cs new file mode 100644 index 0000000..7494410 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/SimpleJson.cs @@ -0,0 +1,647 @@ +using System; +using System.Text; +using System.Collections.Generic; +using System.IO; + +namespace Ink.Runtime +{ + /// + /// Simple custom JSON serialisation implementation that takes JSON-able System.Collections that + /// are produced by the ink engine and converts to and from JSON text. + /// + public static class SimpleJson + { + public static Dictionary TextToDictionary (string text) + { + return new Reader (text).ToDictionary (); + } + + public static List TextToArray(string text) + { + return new Reader(text).ToArray(); + } + + class Reader + { + public Reader (string text) + { + _text = text; + _offset = 0; + + SkipWhitespace (); + + _rootObject = ReadObject (); + } + + public Dictionary ToDictionary () + { + return (Dictionary)_rootObject; + } + + public List ToArray() + { + return (List)_rootObject; + } + + bool IsNumberChar (char c) + { + return c >= '0' && c <= '9' || c == '.' || c == '-' || c == '+' || c == 'E' || c == 'e'; + } + + bool IsFirstNumberChar(char c) + { + return c >= '0' && c <= '9' || c == '-' || c == '+'; + } + + object ReadObject () + { + var currentChar = _text [_offset]; + + if( currentChar == '{' ) + return ReadDictionary (); + + else if (currentChar == '[') + return ReadArray (); + + else if (currentChar == '"') + return ReadString (); + + else if (IsFirstNumberChar(currentChar)) + return ReadNumber (); + + else if (TryRead ("true")) + return true; + + else if (TryRead ("false")) + return false; + + else if (TryRead ("null")) + return null; + + throw new System.Exception ("Unhandled object type in JSON: "+_text.Substring (_offset, 30)); + } + + Dictionary ReadDictionary () + { + var dict = new Dictionary (); + + Expect ("{"); + + SkipWhitespace (); + + // Empty dictionary? + if (TryRead ("}")) + return dict; + + do { + + SkipWhitespace (); + + // Key + var key = ReadString (); + Expect (key != null, "dictionary key"); + + SkipWhitespace (); + + // : + Expect (":"); + + SkipWhitespace (); + + // Value + var val = ReadObject (); + Expect (val != null, "dictionary value"); + + // Add to dictionary + dict [key] = val; + + SkipWhitespace (); + + } while ( TryRead (",") ); + + Expect ("}"); + + return dict; + } + + List ReadArray () + { + var list = new List (); + + Expect ("["); + + SkipWhitespace (); + + // Empty list? + if (TryRead ("]")) + return list; + + do { + + SkipWhitespace (); + + // Value + var val = ReadObject (); + + // Add to array + list.Add (val); + + SkipWhitespace (); + + } while (TryRead (",")); + + Expect ("]"); + + return list; + } + + string ReadString () + { + Expect ("\""); + + var sb = new StringBuilder(); + + for (; _offset < _text.Length; _offset++) { + var c = _text [_offset]; + + if (c == '\\') { + // Escaped character + _offset++; + if (_offset >= _text.Length) { + throw new Exception("Unexpected EOF while reading string"); + } + c = _text[_offset]; + switch (c) + { + case '"': + case '\\': + case '/': // Yes, JSON allows this to be escaped + sb.Append(c); + break; + case 'n': + sb.Append('\n'); + break; + case 't': + sb.Append('\t'); + break; + case 'r': + case 'b': + case 'f': + // Ignore other control characters + break; + case 'u': + // 4-digit Unicode + if (_offset + 4 >=_text.Length) { + throw new Exception("Unexpected EOF while reading string"); + } + var digits = _text.Substring(_offset + 1, 4); + int uchar; + if (int.TryParse(digits, System.Globalization.NumberStyles.AllowHexSpecifier, System.Globalization.CultureInfo.InvariantCulture, out uchar)) { + sb.Append((char)uchar); + _offset += 4; + } else { + throw new Exception("Invalid Unicode escape character at offset " + (_offset - 1)); + } + break; + default: + // The escaped character is invalid per json spec + throw new Exception("Invalid Unicode escape character at offset " + (_offset - 1)); + } + } else if( c == '"' ) { + break; + } else { + sb.Append(c); + } + } + + Expect ("\""); + return sb.ToString(); + } + + object ReadNumber () + { + var startOffset = _offset; + + bool isFloat = false; + for (; _offset < _text.Length; _offset++) { + var c = _text [_offset]; + if (c == '.' || c == 'e' || c == 'E') isFloat = true; + if (IsNumberChar (c)) + continue; + else + break; + } + + string numStr = _text.Substring (startOffset, _offset - startOffset); + + if (isFloat) { + float f; + if (float.TryParse (numStr, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out f)) { + return f; + } + } else { + int i; + if (int.TryParse (numStr, out i)) { + return i; + } + } + + throw new System.Exception ("Failed to parse number value: "+numStr); + } + + bool TryRead (string textToRead) + { + if (_offset + textToRead.Length > _text.Length) + return false; + + for (int i = 0; i < textToRead.Length; i++) { + if (textToRead [i] != _text [_offset + i]) + return false; + } + + _offset += textToRead.Length; + + return true; + } + + void Expect (string expectedStr) + { + if (!TryRead (expectedStr)) + Expect (false, expectedStr); + } + + void Expect (bool condition, string message = null) + { + if (!condition) { + if (message == null) { + message = "Unexpected token"; + } else { + message = "Expected " + message; + } + message += " at offset " + _offset; + + throw new System.Exception (message); + } + } + + void SkipWhitespace () + { + while (_offset < _text.Length) { + var c = _text [_offset]; + if (c == ' ' || c == '\t' || c == '\n' || c == '\r') + _offset++; + else + break; + } + } + + string _text; + int _offset; + + object _rootObject; + } + + + public class Writer + { + public Writer() + { + _writer = new StringWriter(); + } + + public Writer(Stream stream) + { + _writer = new System.IO.StreamWriter(stream, Encoding.UTF8); + } + + public void WriteObject(Action inner) + { + WriteObjectStart(); + inner(this); + WriteObjectEnd(); + } + + public void WriteObjectStart() + { + StartNewObject(container: true); + _stateStack.Push(new StateElement { type = State.Object }); + _writer.Write("{"); + } + + public void WriteObjectEnd() + { + Assert(state == State.Object); + _writer.Write("}"); + _stateStack.Pop(); + } + + public void WriteProperty(string name, Action inner) + { + WriteProperty(name, inner); + } + + public void WriteProperty(int id, Action inner) + { + WriteProperty(id, inner); + } + + public void WriteProperty(string name, string content) + { + WritePropertyStart(name); + Write(content); + WritePropertyEnd(); + } + + public void WriteProperty(string name, int content) + { + WritePropertyStart(name); + Write(content); + WritePropertyEnd(); + } + + public void WriteProperty(string name, bool content) + { + WritePropertyStart(name); + Write(content); + WritePropertyEnd(); + } + + public void WritePropertyStart(string name) + { + WritePropertyStart(name); + } + + public void WritePropertyStart(int id) + { + WritePropertyStart(id); + } + + public void WritePropertyEnd() + { + Assert(state == State.Property); + Assert(childCount == 1); + _stateStack.Pop(); + } + + public void WritePropertyNameStart() + { + Assert(state == State.Object); + + if (childCount > 0) + _writer.Write(","); + + _writer.Write("\""); + + IncrementChildCount(); + + _stateStack.Push(new StateElement { type = State.Property }); + _stateStack.Push(new StateElement { type = State.PropertyName }); + } + + public void WritePropertyNameEnd() + { + Assert(state == State.PropertyName); + + _writer.Write("\":"); + + // Pop PropertyName, leaving Property state + _stateStack.Pop(); + } + + public void WritePropertyNameInner(string str) + { + Assert(state == State.PropertyName); + _writer.Write(str); + } + + void WritePropertyStart(T name) + { + Assert(state == State.Object); + + if (childCount > 0) + _writer.Write(","); + + _writer.Write("\""); + _writer.Write(name); + _writer.Write("\":"); + + IncrementChildCount(); + + _stateStack.Push(new StateElement { type = State.Property }); + } + + + // allow name to be string or int + void WriteProperty(T name, Action inner) + { + WritePropertyStart(name); + + inner(this); + + WritePropertyEnd(); + } + + public void WriteArrayStart() + { + StartNewObject(container: true); + _stateStack.Push(new StateElement { type = State.Array }); + _writer.Write("["); + } + + public void WriteArrayEnd() + { + Assert(state == State.Array); + _writer.Write("]"); + _stateStack.Pop(); + } + + public void Write(int i) + { + StartNewObject(container: false); + _writer.Write(i); + } + + public void Write(float f) + { + StartNewObject(container: false); + + // TODO: Find an heap-allocation-free way to do this please! + // _writer.Write(formatStr, obj (the float)) requires boxing + // Following implementation seems to work ok but requires creating temporary garbage string. + string floatStr = f.ToString(System.Globalization.CultureInfo.InvariantCulture); + if( floatStr == "Infinity" ) { + _writer.Write("3.4E+38"); // JSON doesn't support, do our best alternative + } else if (floatStr == "-Infinity") { + _writer.Write("-3.4E+38"); // JSON doesn't support, do our best alternative + } else if ( floatStr == "NaN" ) { + _writer.Write("0.0"); // JSON doesn't support, not much we can do + } else { + _writer.Write(floatStr); + if (!floatStr.Contains(".") && !floatStr.Contains("E")) + _writer.Write(".0"); // ensure it gets read back in as a floating point value + } + } + + public void Write(string str, bool escape = true) + { + StartNewObject(container: false); + + _writer.Write("\""); + if (escape) + WriteEscapedString(str); + else + _writer.Write(str); + _writer.Write("\""); + } + + public void Write(bool b) + { + StartNewObject(container: false); + _writer.Write(b ? "true" : "false"); + } + + public void WriteNull() + { + StartNewObject(container: false); + _writer.Write("null"); + } + + public void WriteStringStart() + { + StartNewObject(container: false); + _stateStack.Push(new StateElement { type = State.String }); + _writer.Write("\""); + } + + public void WriteStringEnd() + { + Assert(state == State.String); + _writer.Write("\""); + _stateStack.Pop(); + } + + public void WriteStringInner(string str, bool escape = true) + { + Assert(state == State.String); + if (escape) + WriteEscapedString(str); + else + _writer.Write(str); + } + + void WriteEscapedString(string str) + { + foreach (var c in str) + { + if (c < ' ') + { + // Don't write any control characters except \n and \t + switch (c) + { + case '\n': + _writer.Write("\\n"); + break; + case '\t': + _writer.Write("\\t"); + break; + } + } + else + { + switch (c) + { + case '\\': + case '"': + _writer.Write("\\"); + _writer.Write(c); + break; + default: + _writer.Write(c); + break; + } + } + } + } + + void StartNewObject(bool container) + { + + if (container) + Assert(state == State.None || state == State.Property || state == State.Array); + else + Assert(state == State.Property || state == State.Array); + + if (state == State.Array && childCount > 0) + _writer.Write(","); + + if (state == State.Property) + Assert(childCount == 0); + + if (state == State.Array || state == State.Property) + IncrementChildCount(); + } + + State state + { + get + { + if (_stateStack.Count > 0) return _stateStack.Peek().type; + else return State.None; + } + } + + int childCount + { + get + { + if (_stateStack.Count > 0) return _stateStack.Peek().childCount; + else return 0; + } + } + + void IncrementChildCount() + { + Assert(_stateStack.Count > 0); + var currEl = _stateStack.Pop(); + currEl.childCount++; + _stateStack.Push(currEl); + } + + // Shouldn't hit this assert outside of initial JSON development, + // so it's save to make it debug-only. + [System.Diagnostics.Conditional("DEBUG")] + void Assert(bool condition) + { + if (!condition) + throw new System.Exception("Assert failed while writing JSON"); + } + + public override string ToString() + { + return _writer.ToString(); + } + + enum State + { + None, + Object, + Array, + Property, + PropertyName, + String + }; + + struct StateElement + { + public State type; + public int childCount; + } + + Stack _stateStack = new Stack(); + TextWriter _writer; + } + + + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/StatePatch.cs b/Assets/Ink/InkLibs/InkRuntime/StatePatch.cs new file mode 100644 index 0000000..2cc5640 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/StatePatch.cs @@ -0,0 +1,66 @@ +using System.Collections.Generic; + +namespace Ink.Runtime +{ + public class StatePatch + { + public Dictionary globals { get { return _globals; } } + public HashSet changedVariables { get { return _changedVariables; } } + public Dictionary visitCounts { get { return _visitCounts; } } + public Dictionary turnIndices { get { return _turnIndices; } } + + public StatePatch(StatePatch toCopy) + { + if( toCopy != null ) { + _globals = new Dictionary(toCopy._globals); + _changedVariables = new HashSet(toCopy._changedVariables); + _visitCounts = new Dictionary(toCopy._visitCounts); + _turnIndices = new Dictionary(toCopy._turnIndices); + } else { + _globals = new Dictionary(); + _changedVariables = new HashSet(); + _visitCounts = new Dictionary(); + _turnIndices = new Dictionary(); + } + } + + public bool TryGetGlobal(string name, out Runtime.Object value) + { + return _globals.TryGetValue(name, out value); + } + + public void SetGlobal(string name, Runtime.Object value){ + _globals[name] = value; + } + + public void AddChangedVariable(string name) + { + _changedVariables.Add(name); + } + + public bool TryGetVisitCount(Container container, out int count) + { + return _visitCounts.TryGetValue(container, out count); + } + + public void SetVisitCount(Container container, int count) + { + _visitCounts[container] = count; + } + + public void SetTurnIndex(Container container, int index) + { + _turnIndices[container] = index; + } + + public bool TryGetTurnIndex(Container container, out int index) + { + return _turnIndices.TryGetValue(container, out index); + } + + Dictionary _globals; + HashSet _changedVariables = new HashSet(); + Dictionary _visitCounts = new Dictionary(); + Dictionary _turnIndices = new Dictionary(); + } +} diff --git a/Assets/Ink/InkLibs/InkRuntime/Story.cs b/Assets/Ink/InkLibs/InkRuntime/Story.cs new file mode 100644 index 0000000..213d785 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/Story.cs @@ -0,0 +1,2918 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.Diagnostics; + +namespace Ink.Runtime +{ + /// + /// A Story is the core class that represents a complete Ink narrative, and + /// manages the evaluation and state of it. + /// + public class Story : Runtime.Object + { + /// + /// The current version of the ink story file format. + /// + public const int inkVersionCurrent = 21; + + // Version numbers are for engine itself and story file, rather + // than the story state save format + // -- old engine, new format: always fail + // -- new engine, old format: possibly cope, based on this number + // When incrementing the version number above, the question you + // should ask yourself is: + // -- Will the engine be able to load an old story file from + // before I made these changes to the engine? + // If possible, you should support it, though it's not as + // critical as loading old save games, since it's an + // in-development problem only. + + /// + /// The minimum legacy version of ink that can be loaded by the current version of the code. + /// + const int inkVersionMinimumCompatible = 18; + + /// + /// The list of Choice objects available at the current point in + /// the Story. This list will be populated as the Story is stepped + /// through with the Continue() method. Once canContinue becomes + /// false, this list will be populated, and is usually + /// (but not always) on the final Continue() step. + /// + public List currentChoices + { + get + { + // Don't include invisible choices for external usage. + var choices = new List(); + foreach (var c in _state.currentChoices) { + if (!c.isInvisibleDefault) { + c.index = choices.Count; + choices.Add (c); + } + } + return choices; + } + } + + /// + /// The latest line of text to be generated from a Continue() call. + /// + public string currentText { + get { + IfAsyncWeCant ("call currentText since it's a work in progress"); + return state.currentText; + } + } + + /// + /// Gets a list of tags as defined with '#' in source that were seen + /// during the latest Continue() call. + /// + public List currentTags { + get { + IfAsyncWeCant ("call currentTags since it's a work in progress"); + return state.currentTags; + } + } + + /// + /// Any errors generated during evaluation of the Story. + /// + public List currentErrors { get { return state.currentErrors; } } + + /// + /// Any warnings generated during evaluation of the Story. + /// + public List currentWarnings { get { return state.currentWarnings; } } + + /// + /// The current flow name if using multi-flow functionality - see SwitchFlow + /// + public string currentFlowName => state.currentFlowName; + + /// + /// Is the default flow currently active? By definition, will also return true if not using multi-flow functionality - see SwitchFlow + /// + public bool currentFlowIsDefaultFlow { get { return state.currentFlowIsDefaultFlow; } } + + /// + /// Names of currently alive flows (not including the default flow) + /// + + public List aliveFlowNames { get { return state.aliveFlowNames; } } + + /// + /// Whether the currentErrors list contains any errors. + /// THIS MAY BE REMOVED - you should be setting an error handler directly + /// using Story.onError. + /// + public bool hasError { get { return state.hasError; } } + + /// + /// Whether the currentWarnings list contains any warnings. + /// + public bool hasWarning { get { return state.hasWarning; } } + + /// + /// The VariablesState object contains all the global variables in the story. + /// However, note that there's more to the state of a Story than just the + /// global variables. This is a convenience accessor to the full state object. + /// + public VariablesState variablesState{ get { return state.variablesState; } } + + public ListDefinitionsOrigin listDefinitions { + get { + return _listDefinitions; + } + } + + /// + /// The entire current state of the story including (but not limited to): + /// + /// * Global variables + /// * Temporary variables + /// * Read/visit and turn counts + /// * The callstack and evaluation stacks + /// * The current threads + /// + /// + public StoryState state { get { return _state; } } + + /// + /// Error handler for all runtime errors in ink - i.e. problems + /// with the source ink itself that are only discovered when playing + /// the story. + /// It's strongly recommended that you assign an error handler to your + /// story instance to avoid getting exceptions for ink errors. + /// + public event Ink.ErrorHandler onError; + + /// + /// Callback for when ContinueInternal is complete + /// + public event Action onDidContinue; + /// + /// Callback for when a choice is about to be executed + /// + public event Action onMakeChoice; + /// + /// Callback for when a function is about to be evaluated + /// + public event Action onEvaluateFunction; + /// + /// Callback for when a function has been evaluated + /// This is necessary because evaluating a function can cause continuing + /// + public event Action onCompleteEvaluateFunction; + /// + /// Callback for when a path string is chosen + /// + public event Action onChoosePathString; + + /// + /// Start recording ink profiling information during calls to Continue on Story. + /// Return a Profiler instance that you can request a report from when you're finished. + /// + public Profiler StartProfiling() { + IfAsyncWeCant ("start profiling"); + _profiler = new Profiler(); + return _profiler; + } + + /// + /// Stop recording ink profiling information during calls to Continue on Story. + /// To generate a report from the profiler, call + /// + public void EndProfiling() { + _profiler = null; + } + + // Warning: When creating a Story using this constructor, you need to + // call ResetState on it before use. Intended for compiler use only. + // For normal use, use the constructor that takes a json string. + public Story (Container contentContainer, List lists = null) + { + _mainContentContainer = contentContainer; + + if (lists != null) + _listDefinitions = new ListDefinitionsOrigin (lists); + + _externals = new Dictionary (); + } + + /// + /// Construct a Story object using a JSON string compiled through inklecate. + /// + public Story(string jsonString) : this((Container)null) + { + Dictionary rootObject = SimpleJson.TextToDictionary (jsonString); + + object versionObj = rootObject ["inkVersion"]; + if (versionObj == null) + throw new System.Exception ("ink version number not found. Are you sure it's a valid .ink.json file?"); + + int formatFromFile = (int)versionObj; + if (formatFromFile > inkVersionCurrent) { + throw new System.Exception ("Version of ink used to build story was newer than the current version of the engine"); + } else if (formatFromFile < inkVersionMinimumCompatible) { + throw new System.Exception ("Version of ink used to build story is too old to be loaded by this version of the engine"); + } else if (formatFromFile != inkVersionCurrent) { + System.Diagnostics.Debug.WriteLine ("WARNING: Version of ink used to build story doesn't match current version of engine. Non-critical, but recommend synchronising."); + } + + var rootToken = rootObject ["root"]; + if (rootToken == null) + throw new System.Exception ("Root node for ink not found. Are you sure it's a valid .ink.json file?"); + + object listDefsObj; + if (rootObject.TryGetValue ("listDefs", out listDefsObj)) { + _listDefinitions = Json.JTokenToListDefinitions (listDefsObj); + } + + _mainContentContainer = Json.JTokenToRuntimeObject (rootToken) as Container; + + ResetState (); + } + + /// + /// The Story itself in JSON representation. + /// + public string ToJson() + { + //return ToJsonOld(); + var writer = new SimpleJson.Writer(); + ToJson(writer); + return writer.ToString(); + } + + /// + /// The Story itself in JSON representation. + /// + public void ToJson(Stream stream) + { + var writer = new SimpleJson.Writer(stream); + ToJson(writer); + } + + void ToJson(SimpleJson.Writer writer) + { + writer.WriteObjectStart(); + + writer.WriteProperty("inkVersion", inkVersionCurrent); + + // Main container content + writer.WriteProperty("root", w => Json.WriteRuntimeContainer(w, _mainContentContainer)); + + // List definitions + if (_listDefinitions != null) { + + writer.WritePropertyStart("listDefs"); + writer.WriteObjectStart(); + + foreach (ListDefinition def in _listDefinitions.lists) + { + writer.WritePropertyStart(def.name); + writer.WriteObjectStart(); + + foreach (var itemToVal in def.items) + { + InkListItem item = itemToVal.Key; + int val = itemToVal.Value; + writer.WriteProperty(item.itemName, val); + } + + writer.WriteObjectEnd(); + writer.WritePropertyEnd(); + } + + writer.WriteObjectEnd(); + writer.WritePropertyEnd(); + } + + writer.WriteObjectEnd(); + } + + /// + /// Reset the Story back to its initial state as it was when it was + /// first constructed. + /// + public void ResetState() + { + // TODO: Could make this possible + IfAsyncWeCant ("ResetState"); + + _state = new StoryState (this); + _state.variablesState.variableChangedEvent += VariableStateDidChangeEvent; + + ResetGlobals (); + } + + void ResetErrors() + { + _state.ResetErrors (); + } + + /// + /// Unwinds the callstack. Useful to reset the Story's evaluation + /// without actually changing any meaningful state, for example if + /// you want to exit a section of story prematurely and tell it to + /// go elsewhere with a call to ChoosePathString(...). + /// Doing so without calling ResetCallstack() could cause unexpected + /// issues if, for example, the Story was in a tunnel already. + /// + public void ResetCallstack() + { + IfAsyncWeCant ("ResetCallstack"); + + _state.ForceEnd (); + } + + void ResetGlobals() + { + if (_mainContentContainer.namedContent.ContainsKey ("global decl")) { + var originalPointer = state.currentPointer; + + ChoosePath (new Path ("global decl"), incrementingTurnIndex: false); + + // Continue, but without validating external bindings, + // since we may be doing this reset at initialisation time. + ContinueInternal (); + + state.currentPointer = originalPointer; + } + + state.variablesState.SnapshotDefaultGlobals (); + } + + public void SwitchFlow(string flowName) + { + IfAsyncWeCant("switch flow"); + if (_asyncSaving) throw new System.Exception("Story is already in background saving mode, can't switch flow to "+flowName); + + state.SwitchFlow_Internal(flowName); + } + + public void RemoveFlow(string flowName) + { + state.RemoveFlow_Internal(flowName); + } + + public void SwitchToDefaultFlow() + { + state.SwitchToDefaultFlow_Internal(); + } + + + /// + /// Continue the story for one line of content, if possible. + /// If you're not sure if there's more content available, for example if you + /// want to check whether you're at a choice point or at the end of the story, + /// you should call canContinue before calling this function. + /// + /// The line of text content. + public string Continue() + { + ContinueAsync(0); + return currentText; + } + + + /// + /// Check whether more content is available if you were to call Continue() - i.e. + /// are we mid story rather than at a choice point or at the end. + /// + /// true if it's possible to call Continue(). + public bool canContinue { + get { + return state.canContinue; + } + } + + /// + /// If ContinueAsync was called (with milliseconds limit > 0) then this property + /// will return false if the ink evaluation isn't yet finished, and you need to call + /// it again in order for the Continue to fully complete. + /// + public bool asyncContinueComplete { + get { + return !_asyncContinueActive; + } + } + + /// + /// An "asnychronous" version of Continue that only partially evaluates the ink, + /// with a budget of a certain time limit. It will exit ink evaluation early if + /// the evaluation isn't complete within the time limit, with the + /// asyncContinueComplete property being false. + /// This is useful if ink evaluation takes a long time, and you want to distribute + /// it over multiple game frames for smoother animation. + /// If you pass a limit of zero, then it will fully evaluate the ink in the same + /// way as calling Continue (and in fact, this exactly what Continue does internally). + /// + public void ContinueAsync (float millisecsLimitAsync) + { + if( !_hasValidatedExternals ) + ValidateExternalBindings (); + + ContinueInternal (millisecsLimitAsync); + } + + void ContinueInternal (float millisecsLimitAsync = 0) + { + if( _profiler != null ) + _profiler.PreContinue(); + + var isAsyncTimeLimited = millisecsLimitAsync > 0; + + _recursiveContinueCount++; + + // Doing either: + // - full run through non-async (so not active and don't want to be) + // - Starting async run-through + if (!_asyncContinueActive) { + _asyncContinueActive = isAsyncTimeLimited; + + if (!canContinue) { + throw new Exception ("Can't continue - should check canContinue before calling Continue"); + } + + _state.didSafeExit = false; + _state.ResetOutput (); + + // It's possible for ink to call game to call ink to call game etc + // In this case, we only want to batch observe variable changes + // for the outermost call. + if (_recursiveContinueCount == 1) + _state.variablesState.batchObservingVariableChanges = true; + } + + // Start timing + var durationStopwatch = new Stopwatch (); + durationStopwatch.Start (); + + bool outputStreamEndsInNewline = false; + _sawLookaheadUnsafeFunctionAfterNewline = false; + do { + + try { + outputStreamEndsInNewline = ContinueSingleStep (); + } catch(StoryException e) { + AddError (e.Message, useEndLineNumber:e.useEndLineNumber); + break; + } + + if (outputStreamEndsInNewline) + break; + + // Run out of async time? + if (_asyncContinueActive && durationStopwatch.ElapsedMilliseconds > millisecsLimitAsync) { + break; + } + + } while(canContinue); + + durationStopwatch.Stop (); + + // 4 outcomes: + // - got newline (so finished this line of text) + // - can't continue (e.g. choices or ending) + // - ran out of time during evaluation + // - error + // + // Successfully finished evaluation in time (or in error) + if (outputStreamEndsInNewline || !canContinue) { + + // Need to rewind, due to evaluating further than we should? + if( _stateSnapshotAtLastNewline != null ) { + RestoreStateSnapshot (); + } + + // Finished a section of content / reached a choice point? + if( !canContinue ) { + if (state.callStack.canPopThread) + AddError ("Thread available to pop, threads should always be flat by the end of evaluation?"); + + if (state.generatedChoices.Count == 0 && !state.didSafeExit && _temporaryEvaluationContainer == null) { + if (state.callStack.CanPop (PushPopType.Tunnel)) + AddError ("unexpectedly reached end of content. Do you need a '->->' to return from a tunnel?"); + else if (state.callStack.CanPop (PushPopType.Function)) + AddError ("unexpectedly reached end of content. Do you need a '~ return'?"); + else if (!state.callStack.canPop) + AddError ("ran out of content. Do you need a '-> DONE' or '-> END'?"); + else + AddError ("unexpectedly reached end of content for unknown reason. Please debug compiler!"); + } + } + + state.didSafeExit = false; + _sawLookaheadUnsafeFunctionAfterNewline = false; + + if (_recursiveContinueCount == 1) + _state.variablesState.batchObservingVariableChanges = false; + + _asyncContinueActive = false; + if(onDidContinue != null) onDidContinue(); + } + + _recursiveContinueCount--; + + if( _profiler != null ) + _profiler.PostContinue(); + + // Report any errors that occured during evaluation. + // This may either have been StoryExceptions that were thrown + // and caught during evaluation, or directly added with AddError. + if( state.hasError || state.hasWarning ) { + if( onError != null ) { + if( state.hasError ) { + foreach(var err in state.currentErrors) { + onError(err, ErrorType.Error); + } + } + if( state.hasWarning ) { + foreach(var err in state.currentWarnings) { + onError(err, ErrorType.Warning); + } + } + ResetErrors(); + } + + // Throw an exception since there's no error handler + else { + var sb = new StringBuilder(); + sb.Append("Ink had "); + if( state.hasError ) { + sb.Append(state.currentErrors.Count); + sb.Append(state.currentErrors.Count == 1 ? " error" : " errors"); + if( state.hasWarning ) sb.Append(" and "); + } + if( state.hasWarning ) { + sb.Append(state.currentWarnings.Count); + sb.Append(state.currentWarnings.Count == 1 ? " warning" : " warnings"); + } + sb.Append(". It is strongly suggested that you assign an error handler to story.onError. The first issue was: "); + sb.Append(state.hasError ? state.currentErrors[0] : state.currentWarnings[0]); + + // If you get this exception, please assign an error handler to your story. + // If you're using Unity, you can do something like this when you create + // your story: + // + // var story = new Ink.Runtime.Story(jsonTxt); + // story.onError = (errorMessage, errorType) => { + // if( errorType == ErrorType.Warning ) + // Debug.LogWarning(errorMessage); + // else + // Debug.LogError(errorMessage); + // }; + // + // + throw new StoryException(sb.ToString()); + } + } + } + + bool ContinueSingleStep () + { + if (_profiler != null) + _profiler.PreStep (); + + // Run main step function (walks through content) + Step (); + + if (_profiler != null) + _profiler.PostStep (); + + // Run out of content and we have a default invisible choice that we can follow? + if (!canContinue && !state.callStack.elementIsEvaluateFromGame) { + TryFollowDefaultInvisibleChoice (); + } + + if (_profiler != null) + _profiler.PreSnapshot (); + + // Don't save/rewind during string evaluation, which is e.g. used for choices + if (!state.inStringEvaluation) { + + // We previously found a newline, but were we just double checking that + // it wouldn't immediately be removed by glue? + if (_stateSnapshotAtLastNewline != null) { + + // Has proper text or a tag been added? Then we know that the newline + // that was previously added is definitely the end of the line. + var change = CalculateNewlineOutputStateChange ( + _stateSnapshotAtLastNewline.currentText, state.currentText, + _stateSnapshotAtLastNewline.currentTags.Count, state.currentTags.Count + ); + + // The last time we saw a newline, it was definitely the end of the line, so we + // want to rewind to that point. + if (change == OutputStateChange.ExtendedBeyondNewline || _sawLookaheadUnsafeFunctionAfterNewline) { + RestoreStateSnapshot (); + + // Hit a newline for sure, we're done + return true; + } + + // Newline that previously existed is no longer valid - e.g. + // glue was encounted that caused it to be removed. + else if (change == OutputStateChange.NewlineRemoved) { + DiscardSnapshot(); + } + } + + // Current content ends in a newline - approaching end of our evaluation + if (state.outputStreamEndsInNewline) { + + // If we can continue evaluation for a bit: + // Create a snapshot in case we need to rewind. + // We're going to continue stepping in case we see glue or some + // non-text content such as choices. + if (canContinue) { + + // Don't bother to record the state beyond the current newline. + // e.g.: + // Hello world\n // record state at the end of here + // ~ complexCalculation() // don't actually need this unless it generates text + if (_stateSnapshotAtLastNewline == null) + StateSnapshot (); + } + + // Can't continue, so we're about to exit - make sure we + // don't have an old state hanging around. + else { + DiscardSnapshot(); + } + + } + + } + + if (_profiler != null) + _profiler.PostSnapshot (); + + // outputStreamEndsInNewline = false + return false; + } + + + + + // Assumption: prevText is the snapshot where we saw a newline, and we're checking whether we're really done + // with that line. Therefore prevText will definitely end in a newline. + // + // We take tags into account too, so that a tag following a content line: + // Content + // # tag + // ... doesn't cause the tag to be wrongly associated with the content above. + enum OutputStateChange + { + NoChange, + ExtendedBeyondNewline, + NewlineRemoved + } + OutputStateChange CalculateNewlineOutputStateChange (string prevText, string currText, int prevTagCount, int currTagCount) + { + // Simple case: nothing's changed, and we still have a newline + // at the end of the current content + var newlineStillExists = currText.Length >= prevText.Length && prevText.Length > 0 && currText [prevText.Length - 1] == '\n'; + if (prevTagCount == currTagCount && prevText.Length == currText.Length + && newlineStillExists) + return OutputStateChange.NoChange; + + // Old newline has been removed, it wasn't the end of the line after all + if (!newlineStillExists) { + return OutputStateChange.NewlineRemoved; + } + + // Tag added - definitely the start of a new line + if (currTagCount > prevTagCount) + return OutputStateChange.ExtendedBeyondNewline; + + // There must be new content - check whether it's just whitespace + for (int i = prevText.Length; i < currText.Length; i++) { + var c = currText [i]; + if (c != ' ' && c != '\t') { + return OutputStateChange.ExtendedBeyondNewline; + } + } + + // There's new text but it's just spaces and tabs, so there's still the potential + // for glue to kill the newline. + return OutputStateChange.NoChange; + } + + + /// + /// Continue the story until the next choice point or until it runs out of content. + /// This is as opposed to the Continue() method which only evaluates one line of + /// output at a time. + /// + /// The resulting text evaluated by the ink engine, concatenated together. + public string ContinueMaximally() + { + IfAsyncWeCant ("ContinueMaximally"); + + var sb = new StringBuilder (); + + while (canContinue) { + sb.Append (Continue ()); + } + + return sb.ToString (); + } + + public SearchResult ContentAtPath(Path path) + { + return mainContentContainer.ContentAtPath (path); + } + + public Runtime.Container KnotContainerWithName (string name) + { + INamedContent namedContainer; + if (mainContentContainer.namedContent.TryGetValue (name, out namedContainer)) + return namedContainer as Container; + else + return null; + } + + public Pointer PointerAtPath (Path path) + { + if (path.length == 0) + return Pointer.Null; + + var p = new Pointer (); + + int pathLengthToUse = path.length; + + SearchResult result; + if( path.lastComponent.isIndex ) { + pathLengthToUse = path.length - 1; + result = mainContentContainer.ContentAtPath (path, partialPathLength:pathLengthToUse); + p.container = result.container; + p.index = path.lastComponent.index; + } else { + result = mainContentContainer.ContentAtPath (path); + p.container = result.container; + p.index = -1; + } + + if (result.obj == null || result.obj == mainContentContainer && pathLengthToUse > 0) + Error ("Failed to find content at path '" + path + "', and no approximation of it was possible."); + else if (result.approximate) + Warning ("Failed to find content at path '" + path + "', so it was approximated to: '"+result.obj.path+"'."); + + return p; + } + + // Maximum snapshot stack: + // - stateSnapshotDuringSave -- not retained, but returned to game code + // - _stateSnapshotAtLastNewline (has older patch) + // - _state (current, being patched) + + void StateSnapshot() + { + _stateSnapshotAtLastNewline = _state; + _state = _state.CopyAndStartPatching(); + } + + void RestoreStateSnapshot() + { + // Patched state had temporarily hijacked our + // VariablesState and set its own callstack on it, + // so we need to restore that. + // If we're in the middle of saving, we may also + // need to give the VariablesState the old patch. + _stateSnapshotAtLastNewline.RestoreAfterPatch(); + + _state = _stateSnapshotAtLastNewline; + _stateSnapshotAtLastNewline = null; + + // If save completed while the above snapshot was + // active, we need to apply any changes made since + // the save was started but before the snapshot was made. + if( !_asyncSaving ) { + _state.ApplyAnyPatch(); + } + } + + void DiscardSnapshot() + { + // Normally we want to integrate the patch + // into the main global/counts dictionaries. + // However, if we're in the middle of async + // saving, we simply stay in a "patching" state, + // albeit with the newer cloned patch. + if( !_asyncSaving ) + _state.ApplyAnyPatch(); + + // No longer need the snapshot. + _stateSnapshotAtLastNewline = null; + } + + /// + /// Advanced usage! + /// If you have a large story, and saving state to JSON takes too long for your + /// framerate, you can temporarily freeze a copy of the state for saving on + /// a separate thread. Internally, the engine maintains a "diff patch". + /// When you've finished saving your state, call BackgroundSaveComplete() + /// and that diff patch will be applied, allowing the story to continue + /// in its usual mode. + /// + /// The state for background thread save. + public StoryState CopyStateForBackgroundThreadSave() + { + IfAsyncWeCant("start saving on a background thread"); + if (_asyncSaving) throw new System.Exception("Story is already in background saving mode, can't call CopyStateForBackgroundThreadSave again!"); + var stateToSave = _state; + _state = _state.CopyAndStartPatching(); + _asyncSaving = true; + return stateToSave; + } + + /// + /// See CopyStateForBackgroundThreadSave. This method releases the + /// "frozen" save state, applying its patch that it was using internally. + /// + public void BackgroundSaveComplete() + { + // CopyStateForBackgroundThreadSave must be called outside + // of any async ink evaluation, since otherwise you'd be saving + // during an intermediate state. + // However, it's possible to *complete* the save in the middle of + // a glue-lookahead when there's a state stored in _stateSnapshotAtLastNewline. + // This state will have its own patch that is newer than the save patch. + // We hold off on the final apply until the glue-lookahead is finished. + // In that case, the apply is always done, it's just that it may + // apply the looked-ahead changes OR it may simply apply the changes + // made during the save process to the old _stateSnapshotAtLastNewline state. + if ( _stateSnapshotAtLastNewline == null ) { + _state.ApplyAnyPatch(); + } + + _asyncSaving = false; + } + + + + void Step () + { + bool shouldAddToStream = true; + + // Get current content + var pointer = state.currentPointer; + if (pointer.isNull) { + return; + } + + // Step directly to the first element of content in a container (if necessary) + Container containerToEnter = pointer.Resolve () as Container; + while(containerToEnter) { + + // Mark container as being entered + VisitContainer (containerToEnter, atStart:true); + + // No content? the most we can do is step past it + if (containerToEnter.content.Count == 0) + break; + + + pointer = Pointer.StartOf (containerToEnter); + containerToEnter = pointer.Resolve() as Container; + } + state.currentPointer = pointer; + + if( _profiler != null ) { + _profiler.Step(state.callStack); + } + + // Is the current content object: + // - Normal content + // - Or a logic/flow statement - if so, do it + // Stop flow if we hit a stack pop when we're unable to pop (e.g. return/done statement in knot + // that was diverted to rather than called as a function) + var currentContentObj = pointer.Resolve (); + bool isLogicOrFlowControl = PerformLogicAndFlowControl (currentContentObj); + + // Has flow been forced to end by flow control above? + if (state.currentPointer.isNull) { + return; + } + + if (isLogicOrFlowControl) { + shouldAddToStream = false; + } + + // Choice with condition? + var choicePoint = currentContentObj as ChoicePoint; + if (choicePoint) { + var choice = ProcessChoice (choicePoint); + if (choice) { + state.generatedChoices.Add (choice); + } + + currentContentObj = null; + shouldAddToStream = false; + } + + // If the container has no content, then it will be + // the "content" itself, but we skip over it. + if (currentContentObj is Container) { + shouldAddToStream = false; + } + + // Content to add to evaluation stack or the output stream + if (shouldAddToStream) { + + // If we're pushing a variable pointer onto the evaluation stack, ensure that it's specific + // to our current (possibly temporary) context index. And make a copy of the pointer + // so that we're not editing the original runtime object. + var varPointer = currentContentObj as VariablePointerValue; + if (varPointer && varPointer.contextIndex == -1) { + + // Create new object so we're not overwriting the story's own data + var contextIdx = state.callStack.ContextForVariableNamed(varPointer.variableName); + currentContentObj = new VariablePointerValue (varPointer.variableName, contextIdx); + } + + // Expression evaluation content + if (state.inExpressionEvaluation) { + state.PushEvaluationStack (currentContentObj); + } + // Output stream content (i.e. not expression evaluation) + else { + state.PushToOutputStream (currentContentObj); + } + } + + // Increment the content pointer, following diverts if necessary + NextContent (); + + // Starting a thread should be done after the increment to the content pointer, + // so that when returning from the thread, it returns to the content after this instruction. + var controlCmd = currentContentObj as ControlCommand; + if (controlCmd && controlCmd.commandType == ControlCommand.CommandType.StartThread) { + state.callStack.PushThread (); + } + } + + // Mark a container as having been visited + void VisitContainer(Container container, bool atStart) + { + if ( !container.countingAtStartOnly || atStart ) { + if( container.visitsShouldBeCounted ) + state.IncrementVisitCountForContainer (container); + + if (container.turnIndexShouldBeCounted) + state.RecordTurnIndexVisitToContainer (container); + } + } + + List _prevContainers = new List(); + void VisitChangedContainersDueToDivert() + { + var previousPointer = state.previousPointer; + var pointer = state.currentPointer; + + // Unless we're pointing *directly* at a piece of content, we don't do + // counting here. Otherwise, the main stepping function will do the counting. + if (pointer.isNull || pointer.index == -1) + return; + + // First, find the previously open set of containers + _prevContainers.Clear(); + if (!previousPointer.isNull) { + Container prevAncestor = previousPointer.Resolve() as Container ?? previousPointer.container as Container; + while (prevAncestor) { + _prevContainers.Add (prevAncestor); + prevAncestor = prevAncestor.parent as Container; + } + } + + // If the new object is a container itself, it will be visited automatically at the next actual + // content step. However, we need to walk up the new ancestry to see if there are more new containers + Runtime.Object currentChildOfContainer = pointer.Resolve(); + + // Invalid pointer? May happen if attemptingto + if (currentChildOfContainer == null) return; + + Container currentContainerAncestor = currentChildOfContainer.parent as Container; + + bool allChildrenEnteredAtStart = true; + while (currentContainerAncestor && (!_prevContainers.Contains(currentContainerAncestor) || currentContainerAncestor.countingAtStartOnly)) { + + // Check whether this ancestor container is being entered at the start, + // by checking whether the child object is the first. + bool enteringAtStart = currentContainerAncestor.content.Count > 0 + && currentChildOfContainer == currentContainerAncestor.content [0] + && allChildrenEnteredAtStart; + + // Don't count it as entering at start if we're entering random somewhere within + // a container B that happens to be nested at index 0 of container A. It only counts + // if we're diverting directly to the first leaf node. + if (!enteringAtStart) + allChildrenEnteredAtStart = false; + + // Mark a visit to this container + VisitContainer (currentContainerAncestor, enteringAtStart); + + currentChildOfContainer = currentContainerAncestor; + currentContainerAncestor = currentContainerAncestor.parent as Container; + } + } + + string PopChoiceStringAndTags(ref List tags) + { + var choiceOnlyStrVal = (StringValue) state.PopEvaluationStack (); + + while( state.evaluationStack.Count > 0 && state.PeekEvaluationStack() is Tag ) { + if( tags == null ) tags = new List(); + var tag = (Tag)state.PopEvaluationStack (); + tags.Insert(0, tag.text); // popped in reverse order + } + + return choiceOnlyStrVal.value; + } + + Choice ProcessChoice(ChoicePoint choicePoint) + { + bool showChoice = true; + + // Don't create choice if choice point doesn't pass conditional + if (choicePoint.hasCondition) { + var conditionValue = state.PopEvaluationStack (); + if (!IsTruthy (conditionValue)) { + showChoice = false; + } + } + + string startText = ""; + string choiceOnlyText = ""; + var tags = (List)null; + + if (choicePoint.hasChoiceOnlyContent) { + choiceOnlyText = PopChoiceStringAndTags(ref tags); + } + + if (choicePoint.hasStartContent) { + startText = PopChoiceStringAndTags(ref tags); + } + + // Don't create choice if player has already read this content + if (choicePoint.onceOnly) { + var visitCount = state.VisitCountForContainer (choicePoint.choiceTarget); + if (visitCount > 0) { + showChoice = false; + } + } + + // We go through the full process of creating the choice above so + // that we consume the content for it, since otherwise it'll + // be shown on the output stream. + if (!showChoice) { + return null; + } + + var choice = new Choice (); + choice.targetPath = choicePoint.pathOnChoice; + choice.sourcePath = choicePoint.path.ToString (); + choice.isInvisibleDefault = choicePoint.isInvisibleDefault; + choice.tags = tags; + + // We need to capture the state of the callstack at the point where + // the choice was generated, since after the generation of this choice + // we may go on to pop out from a tunnel (possible if the choice was + // wrapped in a conditional), or we may pop out from a thread, + // at which point that thread is discarded. + // Fork clones the thread, gives it a new ID, but without affecting + // the thread stack itself. + choice.threadAtGeneration = state.callStack.ForkThread(); + + // Set final text for the choice + choice.text = (startText + choiceOnlyText).Trim(' ', '\t'); + + return choice; + } + + // Does the expression result represented by this object evaluate to true? + // e.g. is it a Number that's not equal to 1? + bool IsTruthy(Runtime.Object obj) + { + bool truthy = false; + if (obj is Value) { + var val = (Value)obj; + + if (val is DivertTargetValue) { + var divTarget = (DivertTargetValue)val; + Error ("Shouldn't use a divert target (to " + divTarget.targetPath + ") as a conditional value. Did you intend a function call 'likeThis()' or a read count check 'likeThis'? (no arrows)"); + return false; + } + + return val.isTruthy; + } + return truthy; + } + + /// + /// Checks whether contentObj is a control or flow object rather than a piece of content, + /// and performs the required command if necessary. + /// + /// true if object was logic or flow control, false if it's normal content. + /// Content object. + bool PerformLogicAndFlowControl(Runtime.Object contentObj) + { + if( contentObj == null ) { + return false; + } + + // Divert + if (contentObj is Divert) { + + Divert currentDivert = (Divert)contentObj; + + if (currentDivert.isConditional) { + var conditionValue = state.PopEvaluationStack (); + + // False conditional? Cancel divert + if (!IsTruthy (conditionValue)) + return true; + } + + if (currentDivert.hasVariableTarget) { + var varName = currentDivert.variableDivertName; + + var varContents = state.variablesState.GetVariableWithName (varName); + + if (varContents == null) { + Error ("Tried to divert using a target from a variable that could not be found (" + varName + ")"); + } + else if (!(varContents is DivertTargetValue)) { + + var intContent = varContents as IntValue; + + string errorMessage = "Tried to divert to a target from a variable, but the variable (" + varName + ") didn't contain a divert target, it "; + if (intContent && intContent.value == 0) { + errorMessage += "was empty/null (the value 0)."; + } else { + errorMessage += "contained '" + varContents + "'."; + } + + Error (errorMessage); + } + + var target = (DivertTargetValue)varContents; + state.divertedPointer = PointerAtPath(target.targetPath); + + } else if (currentDivert.isExternal) { + CallExternalFunction (currentDivert.targetPathString, currentDivert.externalArgs); + return true; + } else { + state.divertedPointer = currentDivert.targetPointer; + } + + if (currentDivert.pushesToStack) { + state.callStack.Push ( + currentDivert.stackPushType, + outputStreamLengthWithPushed:state.outputStream.Count + ); + } + + if (state.divertedPointer.isNull && !currentDivert.isExternal) { + + // Human readable name available - runtime divert is part of a hard-written divert that to missing content + if (currentDivert && currentDivert.debugMetadata.sourceName != null) { + Error ("Divert target doesn't exist: " + currentDivert.debugMetadata.sourceName); + } else { + Error ("Divert resolution failed: " + currentDivert); + } + } + + return true; + } + + // Start/end an expression evaluation? Or print out the result? + else if( contentObj is ControlCommand ) { + var evalCommand = (ControlCommand) contentObj; + + switch (evalCommand.commandType) { + + case ControlCommand.CommandType.EvalStart: + Assert (state.inExpressionEvaluation == false, "Already in expression evaluation?"); + state.inExpressionEvaluation = true; + break; + + case ControlCommand.CommandType.EvalEnd: + Assert (state.inExpressionEvaluation == true, "Not in expression evaluation mode"); + state.inExpressionEvaluation = false; + break; + + case ControlCommand.CommandType.EvalOutput: + + // If the expression turned out to be empty, there may not be anything on the stack + if (state.evaluationStack.Count > 0) { + + var output = state.PopEvaluationStack (); + + // Functions may evaluate to Void, in which case we skip output + if (!(output is Void)) { + // TODO: Should we really always blanket convert to string? + // It would be okay to have numbers in the output stream the + // only problem is when exporting text for viewing, it skips over numbers etc. + var text = new StringValue (output.ToString ()); + + state.PushToOutputStream (text); + } + + } + break; + + case ControlCommand.CommandType.NoOp: + break; + + case ControlCommand.CommandType.Duplicate: + state.PushEvaluationStack (state.PeekEvaluationStack ()); + break; + + case ControlCommand.CommandType.PopEvaluatedValue: + state.PopEvaluationStack (); + break; + + case ControlCommand.CommandType.PopFunction: + case ControlCommand.CommandType.PopTunnel: + + var popType = evalCommand.commandType == ControlCommand.CommandType.PopFunction ? + PushPopType.Function : PushPopType.Tunnel; + + // Tunnel onwards is allowed to specify an optional override + // divert to go to immediately after returning: ->-> target + DivertTargetValue overrideTunnelReturnTarget = null; + if (popType == PushPopType.Tunnel) { + var popped = state.PopEvaluationStack (); + overrideTunnelReturnTarget = popped as DivertTargetValue; + if (overrideTunnelReturnTarget == null) { + Assert (popped is Void, "Expected void if ->-> doesn't override target"); + } + } + + if (state.TryExitFunctionEvaluationFromGame ()) { + break; + } + else if (state.callStack.currentElement.type != popType || !state.callStack.canPop) { + + var names = new Dictionary (); + names [PushPopType.Function] = "function return statement (~ return)"; + names [PushPopType.Tunnel] = "tunnel onwards statement (->->)"; + + string expected = names [state.callStack.currentElement.type]; + if (!state.callStack.canPop) { + expected = "end of flow (-> END or choice)"; + } + + var errorMsg = string.Format ("Found {0}, when expected {1}", names [popType], expected); + + Error (errorMsg); + } + + else { + state.PopCallstack (); + + // Does tunnel onwards override by diverting to a new ->-> target? + if( overrideTunnelReturnTarget ) + state.divertedPointer = PointerAtPath (overrideTunnelReturnTarget.targetPath); + } + + break; + + case ControlCommand.CommandType.BeginString: + state.PushToOutputStream (evalCommand); + + Assert (state.inExpressionEvaluation == true, "Expected to be in an expression when evaluating a string"); + state.inExpressionEvaluation = false; + break; + + // Leave it to story.currentText and story.currentTags to sort out the text from the tags + // This is mostly because we can't always rely on the existence of EndTag, and we don't want + // to try and flatten dynamic tags to strings every time \n is pushed to output + case ControlCommand.CommandType.BeginTag: + state.PushToOutputStream (evalCommand); + break; + + case ControlCommand.CommandType.EndTag: { + + // EndTag has 2 modes: + // - When in string evaluation (for choices) + // - Normal + // + // The only way you could have an EndTag in the middle of + // string evaluation is if we're currently generating text for a + // choice, such as: + // + // + choice # tag + // + // In the above case, the ink will be run twice: + // - First, to generate the choice text. String evaluation + // will be on, and the final string will be pushed to the + // evaluation stack, ready to be popped to make a Choice + // object. + // - Second, when ink generates text after choosing the choice. + // On this ocassion, it's not in string evaluation mode. + // + // On the writing side, we disallow manually putting tags within + // strings like this: + // + // {"hello # world"} + // + // So we know that the tag must be being generated as part of + // choice content. Therefore, when the tag has been generated, + // we push it onto the evaluation stack in the exact same way + // as the string for the choice content. + if( state.inStringEvaluation ) { + + var contentStackForTag = new Stack (); + int outputCountConsumed = 0; + + for (int i = state.outputStream.Count - 1; i >= 0; --i) { + var obj = state.outputStream [i]; + + outputCountConsumed++; + + var command = obj as ControlCommand; + if (command != null) { + if( command.commandType == ControlCommand.CommandType.BeginTag ) { + break; + } else { + Error("Unexpected ControlCommand while extracting tag from choice"); + break; + } + + } + + if( obj is StringValue) + contentStackForTag.Push (obj); + } + + // Consume the content that was produced for this string + state.PopFromOutputStream (outputCountConsumed); + + var sb = new StringBuilder(); + foreach(StringValue strVal in contentStackForTag) { + sb.Append(strVal.value); + } + + var choiceTag = new Tag(state.CleanOutputWhitespace(sb.ToString())); + + // Pushing to the evaluation stack means it gets picked up + // when a Choice is generated from the next Choice Point. + state.PushEvaluationStack(choiceTag); + } + + // Otherwise! Simply push EndTag, so that in the output stream we + // have a structure of: [BeginTag, "the tag content", EndTag] + else { + state.PushToOutputStream (evalCommand); + } + break; + } + + + // Dynamic strings and tags are built in the same way + case ControlCommand.CommandType.EndString: { + + // Since we're iterating backward through the content, + // build a stack so that when we build the string, + // it's in the right order + var contentStackForString = new Stack (); + var contentToRetain = new Stack(); + + int outputCountConsumed = 0; + for (int i = state.outputStream.Count - 1; i >= 0; --i) { + var obj = state.outputStream [i]; + + outputCountConsumed++; + + var command = obj as ControlCommand; + if (command != null && command.commandType == ControlCommand.CommandType.BeginString) { + break; + } + + if( obj is Tag ) + contentToRetain.Push(obj); + + if( obj is StringValue ) + contentStackForString.Push (obj); + } + + // Consume the content that was produced for this string + state.PopFromOutputStream (outputCountConsumed); + + // Rescue the tags that we want actually to keep on the output stack + // rather than consume as part of the string we're building. + // At the time of writing, this only applies to Tag objects generated + // by choices, which are pushed to the stack during string generation. + foreach(var rescuedTag in contentToRetain) + state.PushToOutputStream(rescuedTag); + + // Build string out of the content we collected + var sb = new StringBuilder (); + foreach (var c in contentStackForString) { + sb.Append (c.ToString ()); + } + + // Return to expression evaluation (from content mode) + state.inExpressionEvaluation = true; + state.PushEvaluationStack (new StringValue (sb.ToString ())); + break; + } + + case ControlCommand.CommandType.ChoiceCount: + var choiceCount = state.generatedChoices.Count; + state.PushEvaluationStack (new Runtime.IntValue (choiceCount)); + break; + + case ControlCommand.CommandType.Turns: + state.PushEvaluationStack (new IntValue (state.currentTurnIndex+1)); + break; + + case ControlCommand.CommandType.TurnsSince: + case ControlCommand.CommandType.ReadCount: + var target = state.PopEvaluationStack(); + if( !(target is DivertTargetValue) ) { + string extraNote = ""; + if( target is IntValue ) + extraNote = ". Did you accidentally pass a read count ('knot_name') instead of a target ('-> knot_name')?"; + Error("TURNS_SINCE expected a divert target (knot, stitch, label name), but saw "+target+extraNote); + break; + } + + var divertTarget = target as DivertTargetValue; + var container = ContentAtPath (divertTarget.targetPath).correctObj as Container; + + int eitherCount; + if (container != null) { + if (evalCommand.commandType == ControlCommand.CommandType.TurnsSince) + eitherCount = state.TurnsSinceForContainer (container); + else + eitherCount = state.VisitCountForContainer (container); + } else { + if (evalCommand.commandType == ControlCommand.CommandType.TurnsSince) + eitherCount = -1; // turn count, default to never/unknown + else + eitherCount = 0; // visit count, assume 0 to default to allowing entry + + Warning ("Failed to find container for " + evalCommand.ToString () + " lookup at " + divertTarget.targetPath.ToString ()); + } + + state.PushEvaluationStack (new IntValue (eitherCount)); + break; + + + case ControlCommand.CommandType.Random: { + var maxInt = state.PopEvaluationStack () as IntValue; + var minInt = state.PopEvaluationStack () as IntValue; + + if (minInt == null) + Error ("Invalid value for minimum parameter of RANDOM(min, max)"); + + if (maxInt == null) + Error ("Invalid value for maximum parameter of RANDOM(min, max)"); + + // +1 because it's inclusive of min and max, for e.g. RANDOM(1,6) for a dice roll. + int randomRange; + try { + randomRange = checked(maxInt.value - minInt.value + 1); + } catch (System.OverflowException) { + randomRange = int.MaxValue; + Error("RANDOM was called with a range that exceeds the size that ink numbers can use."); + } + if (randomRange <= 0) + Error ("RANDOM was called with minimum as " + minInt.value + " and maximum as " + maxInt.value + ". The maximum must be larger"); + + var resultSeed = state.storySeed + state.previousRandom; + var random = new Random (resultSeed); + + var nextRandom = random.Next (); + var chosenValue = (nextRandom % randomRange) + minInt.value; + state.PushEvaluationStack (new IntValue (chosenValue)); + + // Next random number (rather than keeping the Random object around) + state.previousRandom = nextRandom; + break; + } + + case ControlCommand.CommandType.SeedRandom: + var seed = state.PopEvaluationStack () as IntValue; + if (seed == null) + Error ("Invalid value passed to SEED_RANDOM"); + + // Story seed affects both RANDOM and shuffle behaviour + state.storySeed = seed.value; + state.previousRandom = 0; + + // SEED_RANDOM returns nothing. + state.PushEvaluationStack (new Runtime.Void ()); + break; + + case ControlCommand.CommandType.VisitIndex: + var count = state.VisitCountForContainer(state.currentPointer.container) - 1; // index not count + state.PushEvaluationStack (new IntValue (count)); + break; + + case ControlCommand.CommandType.SequenceShuffleIndex: + var shuffleIndex = NextSequenceShuffleIndex (); + state.PushEvaluationStack (new IntValue (shuffleIndex)); + break; + + case ControlCommand.CommandType.StartThread: + // Handled in main step function + break; + + case ControlCommand.CommandType.Done: + + // We may exist in the context of the initial + // act of creating the thread, or in the context of + // evaluating the content. + if (state.callStack.canPopThread) { + state.callStack.PopThread (); + } + + // In normal flow - allow safe exit without warning + else { + state.didSafeExit = true; + + // Stop flow in current thread + state.currentPointer = Pointer.Null; + } + + break; + + // Force flow to end completely + case ControlCommand.CommandType.End: + state.ForceEnd (); + break; + + case ControlCommand.CommandType.ListFromInt: + var intVal = state.PopEvaluationStack () as IntValue; + var listNameVal = state.PopEvaluationStack () as StringValue; + + if (intVal == null) { + throw new StoryException ("Passed non-integer when creating a list element from a numerical value."); + } + + ListValue generatedListValue = null; + + ListDefinition foundListDef; + if (listDefinitions.TryListGetDefinition (listNameVal.value, out foundListDef)) { + InkListItem foundItem; + if (foundListDef.TryGetItemWithValue (intVal.value, out foundItem)) { + generatedListValue = new ListValue (foundItem, intVal.value); + } + } else { + throw new StoryException ("Failed to find LIST called " + listNameVal.value); + } + + if (generatedListValue == null) + generatedListValue = new ListValue (); + + state.PushEvaluationStack (generatedListValue); + break; + + case ControlCommand.CommandType.ListRange: { + var max = state.PopEvaluationStack () as Value; + var min = state.PopEvaluationStack () as Value; + + var targetList = state.PopEvaluationStack () as ListValue; + + if (targetList == null || min == null || max == null) + throw new StoryException ("Expected list, minimum and maximum for LIST_RANGE"); + + var result = targetList.value.ListWithSubRange(min.valueObject, max.valueObject); + + state.PushEvaluationStack (new ListValue(result)); + break; + } + + case ControlCommand.CommandType.ListRandom: { + + var listVal = state.PopEvaluationStack () as ListValue; + if (listVal == null) + throw new StoryException ("Expected list for LIST_RANDOM"); + + var list = listVal.value; + + InkList newList = null; + + // List was empty: return empty list + if (list.Count == 0) { + newList = new InkList (); + } + + // Non-empty source list + else { + // Generate a random index for the element to take + var resultSeed = state.storySeed + state.previousRandom; + var random = new Random (resultSeed); + + var nextRandom = random.Next (); + var listItemIndex = nextRandom % list.Count; + + // Iterate through to get the random element + var listEnumerator = list.GetEnumerator (); + for (int i = 0; i <= listItemIndex; i++) { + listEnumerator.MoveNext (); + } + var randomItem = listEnumerator.Current; + + // Origin list is simply the origin of the one element + newList = new InkList (randomItem.Key.originName, this); + newList.Add (randomItem.Key, randomItem.Value); + + state.previousRandom = nextRandom; + } + + state.PushEvaluationStack (new ListValue(newList)); + break; + } + + default: + Error ("unhandled ControlCommand: " + evalCommand); + break; + } + + return true; + } + + // Variable assignment + else if( contentObj is VariableAssignment ) { + var varAss = (VariableAssignment) contentObj; + var assignedVal = state.PopEvaluationStack(); + + // When in temporary evaluation, don't create new variables purely within + // the temporary context, but attempt to create them globally + //var prioritiseHigherInCallStack = _temporaryEvaluationContainer != null; + + state.variablesState.Assign (varAss, assignedVal); + + return true; + } + + // Variable reference + else if( contentObj is VariableReference ) { + var varRef = (VariableReference)contentObj; + Runtime.Object foundValue = null; + + + // Explicit read count value + if (varRef.pathForCount != null) { + + var container = varRef.containerForCount; + int count = state.VisitCountForContainer (container); + foundValue = new IntValue (count); + } + + // Normal variable reference + else { + + foundValue = state.variablesState.GetVariableWithName (varRef.name); + + if (foundValue == null) { + Warning ("Variable not found: '" + varRef.name + "'. Using default value of 0 (false). This can happen with temporary variables if the declaration hasn't yet been hit. Globals are always given a default value on load if a value doesn't exist in the save state."); + foundValue = new IntValue (0); + } + } + + state.PushEvaluationStack (foundValue); + + return true; + } + + // Native function call + else if (contentObj is NativeFunctionCall) { + var func = (NativeFunctionCall)contentObj; + var funcParams = state.PopEvaluationStack (func.numberOfParameters); + var result = func.Call (funcParams); + state.PushEvaluationStack (result); + return true; + } + + // No control content, must be ordinary content + return false; + } + + /// + /// Change the current position of the story to the given path. From here you can + /// call Continue() to evaluate the next line. + /// + /// The path string is a dot-separated path as used internally by the engine. + /// These examples should work: + /// + /// myKnot + /// myKnot.myStitch + /// + /// Note however that this won't necessarily work: + /// + /// myKnot.myStitch.myLabelledChoice + /// + /// ...because of the way that content is nested within a weave structure. + /// + /// By default this will reset the callstack beforehand, which means that any + /// tunnels, threads or functions you were in at the time of calling will be + /// discarded. This is different from the behaviour of ChooseChoiceIndex, which + /// will always keep the callstack, since the choices are known to come from the + /// correct state, and known their source thread. + /// + /// You have the option of passing false to the resetCallstack parameter if you + /// don't want this behaviour, and will leave any active threads, tunnels or + /// function calls in-tact. + /// + /// This is potentially dangerous! If you're in the middle of a tunnel, + /// it'll redirect only the inner-most tunnel, meaning that when you tunnel-return + /// using '->->', it'll return to where you were before. This may be what you + /// want though. However, if you're in the middle of a function, ChoosePathString + /// will throw an exception. + /// + /// + /// A dot-separted path string, as specified above. + /// Whether to reset the callstack first (see summary description). + /// Optional set of arguments to pass, if path is to a knot that takes them. + public void ChoosePathString (string path, bool resetCallstack = true, params object [] arguments) + { + IfAsyncWeCant ("call ChoosePathString right now"); + if(onChoosePathString != null) onChoosePathString(path, arguments); + if (resetCallstack) { + ResetCallstack (); + } else { + // ChoosePathString is potentially dangerous since you can call it when the stack is + // pretty much in any state. Let's catch one of the worst offenders. + if (state.callStack.currentElement.type == PushPopType.Function) { + string funcDetail = ""; + var container = state.callStack.currentElement.currentPointer.container; + if (container != null) { + funcDetail = "("+container.path.ToString ()+") "; + } + throw new System.Exception ("Story was running a function "+funcDetail+"when you called ChoosePathString("+path+") - this is almost certainly not not what you want! Full stack trace: \n"+state.callStack.callStackTrace); + } + } + + state.PassArgumentsToEvaluationStack (arguments); + ChoosePath (new Path (path)); + } + + void IfAsyncWeCant (string activityStr) + { + if (_asyncContinueActive) + throw new System.Exception ("Can't " + activityStr + ". Story is in the middle of a ContinueAsync(). Make more ContinueAsync() calls or a single Continue() call beforehand."); + } + + public void ChoosePath(Path p, bool incrementingTurnIndex = true) + { + state.SetChosenPath (p, incrementingTurnIndex); + + // Take a note of newly visited containers for read counts etc + VisitChangedContainersDueToDivert (); + } + + /// + /// Chooses the Choice from the currentChoices list with the given + /// index. Internally, this sets the current content path to that + /// pointed to by the Choice, ready to continue story evaluation. + /// + public void ChooseChoiceIndex(int choiceIdx) + { + var choices = currentChoices; + Assert (choiceIdx >= 0 && choiceIdx < choices.Count, "choice out of range"); + + // Replace callstack with the one from the thread at the choosing point, + // so that we can jump into the right place in the flow. + // This is important in case the flow was forked by a new thread, which + // can create multiple leading edges for the story, each of + // which has its own context. + var choiceToChoose = choices [choiceIdx]; + if(onMakeChoice != null) onMakeChoice(choiceToChoose); + state.callStack.currentThread = choiceToChoose.threadAtGeneration; + + ChoosePath (choiceToChoose.targetPath); + } + + /// + /// Checks if a function exists. + /// + /// True if the function exists, else false. + /// The name of the function as declared in ink. + public bool HasFunction (string functionName) + { + try { + return KnotContainerWithName (functionName) != null; + } catch { + return false; + } + } + + /// + /// Evaluates a function defined in ink. + /// + /// The return value as returned from the ink function with `~ return myValue`, or null if nothing is returned. + /// The name of the function as declared in ink. + /// The arguments that the ink function takes, if any. Note that we don't (can't) do any validation on the number of arguments right now, so make sure you get it right! + public object EvaluateFunction (string functionName, params object [] arguments) + { + string _; + return EvaluateFunction (functionName, out _, arguments); + } + + /// + /// Evaluates a function defined in ink, and gathers the possibly multi-line text as generated by the function. + /// This text output is any text written as normal content within the function, as opposed to the return value, as returned with `~ return`. + /// + /// The return value as returned from the ink function with `~ return myValue`, or null if nothing is returned. + /// The name of the function as declared in ink. + /// The text content produced by the function via normal ink, if any. + /// The arguments that the ink function takes, if any. Note that we don't (can't) do any validation on the number of arguments right now, so make sure you get it right! + public object EvaluateFunction (string functionName, out string textOutput, params object [] arguments) + { + if(onEvaluateFunction != null) onEvaluateFunction(functionName, arguments); + IfAsyncWeCant ("evaluate a function"); + + if(functionName == null) { + throw new System.Exception ("Function is null"); + } else if(functionName == string.Empty || functionName.Trim() == string.Empty) { + throw new System.Exception ("Function is empty or white space."); + } + + // Get the content that we need to run + var funcContainer = KnotContainerWithName (functionName); + if( funcContainer == null ) + throw new System.Exception ("Function doesn't exist: '" + functionName + "'"); + + // Snapshot the output stream + var outputStreamBefore = new List(state.outputStream); + _state.ResetOutput (); + + // State will temporarily replace the callstack in order to evaluate + state.StartFunctionEvaluationFromGame (funcContainer, arguments); + + // Evaluate the function, and collect the string output + var stringOutput = new StringBuilder (); + while (canContinue) { + stringOutput.Append (Continue ()); + } + textOutput = stringOutput.ToString (); + + // Restore the output stream in case this was called + // during main story evaluation. + _state.ResetOutput (outputStreamBefore); + + // Finish evaluation, and see whether anything was produced + var result = state.CompleteFunctionEvaluationFromGame (); + if(onCompleteEvaluateFunction != null) onCompleteEvaluateFunction(functionName, arguments, textOutput, result); + return result; + } + + // Evaluate a "hot compiled" piece of ink content, as used by the REPL-like + // CommandLinePlayer. + public Runtime.Object EvaluateExpression(Runtime.Container exprContainer) + { + int startCallStackHeight = state.callStack.elements.Count; + + state.callStack.Push (PushPopType.Tunnel); + + _temporaryEvaluationContainer = exprContainer; + + state.GoToStart (); + + int evalStackHeight = state.evaluationStack.Count; + + Continue (); + + _temporaryEvaluationContainer = null; + + // Should have fallen off the end of the Container, which should + // have auto-popped, but just in case we didn't for some reason, + // manually pop to restore the state (including currentPath). + if (state.callStack.elements.Count > startCallStackHeight) { + state.PopCallstack (); + } + + int endStackHeight = state.evaluationStack.Count; + if (endStackHeight > evalStackHeight) { + return state.PopEvaluationStack (); + } else { + return null; + } + + } + + /// + /// An ink file can provide a fallback functions for when when an EXTERNAL has been left + /// unbound by the client, and the fallback function will be called instead. Useful when + /// testing a story in playmode, when it's not possible to write a client-side C# external + /// function, but you don't want it to fail to run. + /// + public bool allowExternalFunctionFallbacks { get; set; } + + public bool TryGetExternalFunction(string functionName, out ExternalFunction externalFunction) { + ExternalFunctionDef externalFunctionDef; + if(_externals.TryGetValue (functionName, out externalFunctionDef)) { + externalFunction = externalFunctionDef.function; + return true; + } else { + externalFunction = null; + return false; + } + } + + + public void CallExternalFunction(string funcName, int numberOfArguments) + { + ExternalFunctionDef funcDef; + Container fallbackFunctionContainer = null; + + var foundExternal = _externals.TryGetValue (funcName, out funcDef); + + // Should this function break glue? Abort run if we've already seen a newline. + // Set a bool to tell it to restore the snapshot at the end of this instruction. + if( foundExternal && !funcDef.lookaheadSafe && _stateSnapshotAtLastNewline != null ) { + _sawLookaheadUnsafeFunctionAfterNewline = true; + return; + } + + // Try to use fallback function? + if (!foundExternal) { + if (allowExternalFunctionFallbacks) { + fallbackFunctionContainer = KnotContainerWithName (funcName); + Assert (fallbackFunctionContainer != null, "Trying to call EXTERNAL function '" + funcName + "' which has not been bound, and fallback ink function could not be found."); + + // Divert direct into fallback function and we're done + state.callStack.Push ( + PushPopType.Function, + outputStreamLengthWithPushed:state.outputStream.Count + ); + state.divertedPointer = Pointer.StartOf(fallbackFunctionContainer); + return; + + } else { + Assert (false, "Trying to call EXTERNAL function '" + funcName + "' which has not been bound (and ink fallbacks disabled)."); + } + } + + // Pop arguments + var arguments = new List(); + for (int i = 0; i < numberOfArguments; ++i) { + var poppedObj = state.PopEvaluationStack () as Value; + var valueObj = poppedObj.valueObject; + arguments.Add (valueObj); + } + + // Reverse arguments from the order they were popped, + // so they're the right way round again. + arguments.Reverse (); + + // Run the function! + object funcResult = funcDef.function (arguments.ToArray()); + + // Convert return value (if any) to the a type that the ink engine can use + Runtime.Object returnObj = null; + if (funcResult != null) { + returnObj = Value.Create (funcResult); + Assert (returnObj != null, "Could not create ink value from returned object of type " + funcResult.GetType()); + } else { + returnObj = new Runtime.Void (); + } + + state.PushEvaluationStack (returnObj); + } + + /// + /// General purpose delegate definition for bound EXTERNAL function definitions + /// from ink. Note that this version isn't necessary if you have a function + /// with three arguments or less - see the overloads of BindExternalFunction. + /// + public delegate object ExternalFunction(object[] args); + + /// + /// Most general form of function binding that returns an object + /// and takes an array of object parameters. + /// The only way to bind a function with more than 3 arguments. + /// + /// EXTERNAL ink function name to bind to. + /// The C# function to bind. + /// The ink engine often evaluates further + /// than you might expect beyond the current line just in case it sees + /// glue that will cause the two lines to become one. In this case it's + /// possible that a function can appear to be called twice instead of + /// just once, and earlier than you expect. If it's safe for your + /// function to be called in this way (since the result and side effect + /// of the function will not change), then you can pass 'true'. + /// Usually, you want to pass 'false', especially if you want some action + /// to be performed in game code when this function is called. + public void BindExternalFunctionGeneral(string funcName, ExternalFunction func, bool lookaheadSafe = true) + { + IfAsyncWeCant ("bind an external function"); + Assert (!_externals.ContainsKey (funcName), "Function '" + funcName + "' has already been bound."); + _externals [funcName] = new ExternalFunctionDef { + function = func, + lookaheadSafe = lookaheadSafe + }; + } + + object TryCoerce(object value) + { + if (value == null) + return null; + + if (value is T) + return (T) value; + + if (value is float && typeof(T) == typeof(int)) { + int intVal = (int)Math.Round ((float)value); + return intVal; + } + + if (value is int && typeof(T) == typeof(float)) { + float floatVal = (float)(int)value; + return floatVal; + } + + if (value is int && typeof(T) == typeof(bool)) { + int intVal = (int)value; + return intVal == 0 ? false : true; + } + + if (value is bool && typeof(T) == typeof(int)) { + bool boolVal = (bool)value; + return boolVal ? 1 : 0; + } + + if (typeof(T) == typeof(string)) { + return value.ToString (); + } + + Assert (false, "Failed to cast " + value.GetType ().Name + " to " + typeof(T).Name); + + return null; + } + + // Convenience overloads for standard functions and actions of various arities + // Is there a better way of doing this?! + + /// + /// Bind a C# function to an ink EXTERNAL function declaration. + /// + /// EXTERNAL ink function name to bind to. + /// The C# function to bind. + /// The ink engine often evaluates further + /// than you might expect beyond the current line just in case it sees + /// glue that will cause the two lines to become one. In this case it's + /// possible that a function can appear to be called twice instead of + /// just once, and earlier than you expect. If it's safe for your + /// function to be called in this way (since the result and side effect + /// of the function will not change), then you can pass 'true'. + /// Usually, you want to pass 'false', especially if you want some action + /// to be performed in game code when this function is called. + public void BindExternalFunction(string funcName, Func func, bool lookaheadSafe=false) + { + Assert(func != null, "Can't bind a null function"); + + BindExternalFunctionGeneral (funcName, (object[] args) => { + Assert(args.Length == 0, "External function expected no arguments"); + return func(); + }, lookaheadSafe); + } + + /// + /// Bind a C# Action to an ink EXTERNAL function declaration. + /// + /// EXTERNAL ink function name to bind to. + /// The C# action to bind. + /// The ink engine often evaluates further + /// than you might expect beyond the current line just in case it sees + /// glue that will cause the two lines to become one. In this case it's + /// possible that a function can appear to be called twice instead of + /// just once, and earlier than you expect. If it's safe for your + /// function to be called in this way (since the result and side effect + /// of the function will not change), then you can pass 'true'. + /// Usually, you want to pass 'false', especially if you want some action + /// to be performed in game code when this function is called. + public void BindExternalFunction(string funcName, Action act, bool lookaheadSafe=false) + { + Assert(act != null, "Can't bind a null function"); + + BindExternalFunctionGeneral (funcName, (object[] args) => { + Assert(args.Length == 0, "External function expected no arguments"); + act(); + return null; + }, lookaheadSafe); + } + + /// + /// Bind a C# function to an ink EXTERNAL function declaration. + /// + /// EXTERNAL ink function name to bind to. + /// The C# function to bind. + /// The ink engine often evaluates further + /// than you might expect beyond the current line just in case it sees + /// glue that will cause the two lines to become one. In this case it's + /// possible that a function can appear to be called twice instead of + /// just once, and earlier than you expect. If it's safe for your + /// function to be called in this way (since the result and side effect + /// of the function will not change), then you can pass 'true'. + /// Usually, you want to pass 'false', especially if you want some action + /// to be performed in game code when this function is called. + public void BindExternalFunction(string funcName, Func func, bool lookaheadSafe=false) + { + Assert(func != null, "Can't bind a null function"); + + BindExternalFunctionGeneral (funcName, (object[] args) => { + Assert(args.Length == 1, "External function expected one argument"); + return func( (T)TryCoerce(args[0]) ); + }, lookaheadSafe); + } + + /// + /// Bind a C# action to an ink EXTERNAL function declaration. + /// + /// EXTERNAL ink function name to bind to. + /// The C# action to bind. + /// The ink engine often evaluates further + /// than you might expect beyond the current line just in case it sees + /// glue that will cause the two lines to become one. In this case it's + /// possible that a function can appear to be called twice instead of + /// just once, and earlier than you expect. If it's safe for your + /// function to be called in this way (since the result and side effect + /// of the function will not change), then you can pass 'true'. + /// Usually, you want to pass 'false', especially if you want some action + /// to be performed in game code when this function is called. + public void BindExternalFunction(string funcName, Action act, bool lookaheadSafe=false) + { + Assert(act != null, "Can't bind a null function"); + + BindExternalFunctionGeneral (funcName, (object[] args) => { + Assert(args.Length == 1, "External function expected one argument"); + act( (T)TryCoerce(args[0]) ); + return null; + }, lookaheadSafe); + } + + + /// + /// Bind a C# function to an ink EXTERNAL function declaration. + /// + /// EXTERNAL ink function name to bind to. + /// The C# function to bind. + /// The ink engine often evaluates further + /// than you might expect beyond the current line just in case it sees + /// glue that will cause the two lines to become one. In this case it's + /// possible that a function can appear to be called twice instead of + /// just once, and earlier than you expect. If it's safe for your + /// function to be called in this way (since the result and side effect + /// of the function will not change), then you can pass 'true'. + /// Usually, you want to pass 'false', especially if you want some action + /// to be performed in game code when this function is called. + public void BindExternalFunction(string funcName, Func func, bool lookaheadSafe = false) + { + Assert(func != null, "Can't bind a null function"); + + BindExternalFunctionGeneral (funcName, (object[] args) => { + Assert(args.Length == 2, "External function expected two arguments"); + return func( + (T1)TryCoerce(args[0]), + (T2)TryCoerce(args[1]) + ); + }, lookaheadSafe); + } + + /// + /// Bind a C# action to an ink EXTERNAL function declaration. + /// + /// EXTERNAL ink function name to bind to. + /// The C# action to bind. + /// The ink engine often evaluates further + /// than you might expect beyond the current line just in case it sees + /// glue that will cause the two lines to become one. In this case it's + /// possible that a function can appear to be called twice instead of + /// just once, and earlier than you expect. If it's safe for your + /// function to be called in this way (since the result and side effect + /// of the function will not change), then you can pass 'true'. + /// Usually, you want to pass 'false', especially if you want some action + /// to be performed in game code when this function is called. + public void BindExternalFunction(string funcName, Action act, bool lookaheadSafe=false) + { + Assert(act != null, "Can't bind a null function"); + + BindExternalFunctionGeneral (funcName, (object[] args) => { + Assert(args.Length == 2, "External function expected two arguments"); + act( + (T1)TryCoerce(args[0]), + (T2)TryCoerce(args[1]) + ); + return null; + }, lookaheadSafe); + } + + /// + /// Bind a C# function to an ink EXTERNAL function declaration. + /// + /// EXTERNAL ink function name to bind to. + /// The C# function to bind. + /// The ink engine often evaluates further + /// than you might expect beyond the current line just in case it sees + /// glue that will cause the two lines to become one. In this case it's + /// possible that a function can appear to be called twice instead of + /// just once, and earlier than you expect. If it's safe for your + /// function to be called in this way (since the result and side effect + /// of the function will not change), then you can pass 'true'. + /// Usually, you want to pass 'false', especially if you want some action + /// to be performed in game code when this function is called. + public void BindExternalFunction(string funcName, Func func, bool lookaheadSafe=false) + { + Assert(func != null, "Can't bind a null function"); + + BindExternalFunctionGeneral (funcName, (object[] args) => { + Assert(args.Length == 3, "External function expected three arguments"); + return func( + (T1)TryCoerce(args[0]), + (T2)TryCoerce(args[1]), + (T3)TryCoerce(args[2]) + ); + }, lookaheadSafe); + } + + /// + /// Bind a C# action to an ink EXTERNAL function declaration. + /// + /// EXTERNAL ink function name to bind to. + /// The C# action to bind. + /// The ink engine often evaluates further + /// than you might expect beyond the current line just in case it sees + /// glue that will cause the two lines to become one. In this case it's + /// possible that a function can appear to be called twice instead of + /// just once, and earlier than you expect. If it's safe for your + /// function to be called in this way (since the result and side effect + /// of the function will not change), then you can pass 'true'. + /// Usually, you want to pass 'false', especially if you want some action + /// to be performed in game code when this function is called. + public void BindExternalFunction(string funcName, Action act, bool lookaheadSafe=false) + { + Assert(act != null, "Can't bind a null function"); + + BindExternalFunctionGeneral (funcName, (object[] args) => { + Assert(args.Length == 3, "External function expected three arguments"); + act( + (T1)TryCoerce(args[0]), + (T2)TryCoerce(args[1]), + (T3)TryCoerce(args[2]) + ); + return null; + }, lookaheadSafe); + } + + /// + /// Bind a C# function to an ink EXTERNAL function declaration. + /// + /// EXTERNAL ink function name to bind to. + /// The C# function to bind. + /// The ink engine often evaluates further + /// than you might expect beyond the current line just in case it sees + /// glue that will cause the two lines to become one. In this case it's + /// possible that a function can appear to be called twice instead of + /// just once, and earlier than you expect. If it's safe for your + /// function to be called in this way (since the result and side effect + /// of the function will not change), then you can pass 'true'. + /// Usually, you want to pass 'false', especially if you want some action + /// to be performed in game code when this function is called. + public void BindExternalFunction(string funcName, Func func, bool lookaheadSafe=false) + { + Assert(func != null, "Can't bind a null function"); + + BindExternalFunctionGeneral (funcName, (object[] args) => { + Assert(args.Length == 4, "External function expected four arguments"); + return func( + (T1)TryCoerce(args[0]), + (T2)TryCoerce(args[1]), + (T3)TryCoerce(args[2]), + (T4)TryCoerce(args[3]) + ); + }, lookaheadSafe); + } + + /// + /// Bind a C# action to an ink EXTERNAL function declaration. + /// + /// EXTERNAL ink function name to bind to. + /// The C# action to bind. + /// The ink engine often evaluates further + /// than you might expect beyond the current line just in case it sees + /// glue that will cause the two lines to become one. In this case it's + /// possible that a function can appear to be called twice instead of + /// just once, and earlier than you expect. If it's safe for your + /// function to be called in this way (since the result and side effect + /// of the function will not change), then you can pass 'true'. + /// Usually, you want to pass 'false', especially if you want some action + /// to be performed in game code when this function is called. + public void BindExternalFunction(string funcName, Action act, bool lookaheadSafe=false) + { + Assert(act != null, "Can't bind a null function"); + + BindExternalFunctionGeneral (funcName, (object[] args) => { + Assert(args.Length == 4, "External function expected four arguments"); + act( + (T1)TryCoerce(args[0]), + (T2)TryCoerce(args[1]), + (T3)TryCoerce(args[2]), + (T4)TryCoerce(args[3]) + ); + return null; + }, lookaheadSafe); + } + + /// + /// Remove a binding for a named EXTERNAL ink function. + /// + public void UnbindExternalFunction(string funcName) + { + IfAsyncWeCant ("unbind an external a function"); + Assert (_externals.ContainsKey (funcName), "Function '" + funcName + "' has not been bound."); + _externals.Remove (funcName); + } + + /// + /// Check that all EXTERNAL ink functions have a valid bound C# function. + /// Note that this is automatically called on the first call to Continue(). + /// + public void ValidateExternalBindings() + { + var missingExternals = new HashSet(); + + ValidateExternalBindings (_mainContentContainer, missingExternals); + _hasValidatedExternals = true; + + // No problem! Validation complete + if( missingExternals.Count == 0 ) { + _hasValidatedExternals = true; + } + + // Error for all missing externals + else { + var message = string.Format("ERROR: Missing function binding for external{0}: '{1}' {2}", + missingExternals.Count > 1 ? "s" : string.Empty, + string.Join("', '", missingExternals.ToArray()), + allowExternalFunctionFallbacks ? ", and no fallback ink function found." : " (ink fallbacks disabled)" + ); + + Error(message); + } + } + + void ValidateExternalBindings(Container c, HashSet missingExternals) + { + foreach (var innerContent in c.content) { + var container = innerContent as Container; + if( container == null || !container.hasValidName ) + ValidateExternalBindings (innerContent, missingExternals); + } + foreach (var innerKeyValue in c.namedContent) { + ValidateExternalBindings (innerKeyValue.Value as Runtime.Object, missingExternals); + } + } + + void ValidateExternalBindings(Runtime.Object o, HashSet missingExternals) + { + var container = o as Container; + if (container) { + ValidateExternalBindings (container, missingExternals); + return; + } + + var divert = o as Divert; + if (divert && divert.isExternal) { + var name = divert.targetPathString; + + if (!_externals.ContainsKey (name)) { + if( allowExternalFunctionFallbacks ) { + bool fallbackFound = mainContentContainer.namedContent.ContainsKey(name); + if( !fallbackFound ) { + missingExternals.Add(name); + } + } else { + missingExternals.Add(name); + } + } + } + } + + /// + /// Delegate definition for variable observation - see ObserveVariable. + /// + public delegate void VariableObserver(string variableName, object newValue); + + /// + /// When the named global variable changes it's value, the observer will be + /// called to notify it of the change. Note that if the value changes multiple + /// times within the ink, the observer will only be called once, at the end + /// of the ink's evaluation. If, during the evaluation, it changes and then + /// changes back again to its original value, it will still be called. + /// Note that the observer will also be fired if the value of the variable + /// is changed externally to the ink, by directly setting a value in + /// story.variablesState. + /// + /// The name of the global variable to observe. + /// A delegate function to call when the variable changes. + public void ObserveVariable(string variableName, VariableObserver observer) + { + IfAsyncWeCant ("observe a new variable"); + + if (_variableObservers == null) + _variableObservers = new Dictionary (); + + if( !state.variablesState.GlobalVariableExistsWithName(variableName) ) + throw new Exception("Cannot observe variable '"+variableName+"' because it wasn't declared in the ink story."); + + if (_variableObservers.ContainsKey (variableName)) { + _variableObservers[variableName] += observer; + } else { + _variableObservers[variableName] = observer; + } + } + + /// + /// Convenience function to allow multiple variables to be observed with the same + /// observer delegate function. See the singular ObserveVariable for details. + /// The observer will get one call for every variable that has changed. + /// + /// The set of variables to observe. + /// The delegate function to call when any of the named variables change. + public void ObserveVariables(IList variableNames, VariableObserver observer) + { + foreach (var varName in variableNames) { + ObserveVariable (varName, observer); + } + } + + /// + /// Removes the variable observer, to stop getting variable change notifications. + /// If you pass a specific variable name, it will stop observing that particular one. If you + /// pass null (or leave it blank, since it's optional), then the observer will be removed + /// from all variables that it's subscribed to. If you pass in a specific variable name and + /// null for the the observer, all observers for that variable will be removed. + /// + /// (Optional) The observer to stop observing. + /// (Optional) Specific variable name to stop observing. + public void RemoveVariableObserver(VariableObserver observer = null, string specificVariableName = null) + { + IfAsyncWeCant ("remove a variable observer"); + + if (_variableObservers == null) + return; + + // Remove observer for this specific variable + if (specificVariableName != null) { + if (_variableObservers.ContainsKey (specificVariableName)) { + if( observer != null) { + _variableObservers [specificVariableName] -= observer; + if (_variableObservers[specificVariableName] == null) { + _variableObservers.Remove(specificVariableName); + } + } + else { + _variableObservers.Remove(specificVariableName); + } + } + } + + // Remove observer for all variables + else if( observer != null) { + var keys = new List(_variableObservers.Keys); + foreach (var varName in keys) { + _variableObservers[varName] -= observer; + if (_variableObservers[varName] == null) { + _variableObservers.Remove(varName); + } + } + } + } + + void VariableStateDidChangeEvent(string variableName, Runtime.Object newValueObj) + { + if (_variableObservers == null) + return; + + VariableObserver observers = null; + if (_variableObservers.TryGetValue (variableName, out observers)) { + + if (!(newValueObj is Value)) { + throw new System.Exception ("Tried to get the value of a variable that isn't a standard type"); + } + var val = newValueObj as Value; + + observers (variableName, val.valueObject); + } + } + + /// + /// Get any global tags associated with the story. These are defined as + /// hash tags defined at the very top of the story. + /// + public List globalTags { + get { + return TagsAtStartOfFlowContainerWithPathString (""); + } + } + + /// + /// Gets any tags associated with a particular knot or knot.stitch. + /// These are defined as hash tags defined at the very top of a + /// knot or stitch. + /// + /// The path of the knot or stitch, in the form "knot" or "knot.stitch". + public List TagsForContentAtPath (string path) + { + return TagsAtStartOfFlowContainerWithPathString (path); + } + + List TagsAtStartOfFlowContainerWithPathString (string pathString) + { + var path = new Runtime.Path (pathString); + + // Expected to be global story, knot or stitch + var flowContainer = ContentAtPath (path).container; + while(true) { + var firstContent = flowContainer.content [0]; + if (firstContent is Container) + flowContainer = (Container)firstContent; + else break; + } + + // Any initial tag objects count as the "main tags" associated with that story/knot/stitch + bool inTag = false; + List tags = null; + foreach (var c in flowContainer.content) { + + var command = c as Runtime.ControlCommand; + if( command != null ) { + if( command.commandType == Runtime.ControlCommand.CommandType.BeginTag ) { + inTag = true; + } else if( command.commandType == Runtime.ControlCommand.CommandType.EndTag ) { + inTag = false; + } + } + + else if( inTag ) { + var str = c as Runtime.StringValue; + if( str != null ) { + if( tags == null ) tags = new List(); + tags.Add(str.value); + } else { + Error("Tag contained non-text content. Only plain text is allowed when using globalTags or TagsAtContentPath. If you want to evaluate dynamic content, you need to use story.Continue()."); + } + } + + // Any other content - we're done + // We only recognise initial text-only tags + else { + break; + } + } + + return tags; + } + + /// + /// Useful when debugging a (very short) story, to visualise the state of the + /// story. Add this call as a watch and open the extended text. A left-arrow mark + /// will denote the current point of the story. + /// It's only recommended that this is used on very short debug stories, since + /// it can end up generate a large quantity of text otherwise. + /// + public virtual string BuildStringOfHierarchy() + { + var sb = new StringBuilder (); + + mainContentContainer.BuildStringOfHierarchy (sb, 0, state.currentPointer.Resolve()); + + return sb.ToString (); + } + + string BuildStringOfContainer (Container container) + { + var sb = new StringBuilder (); + + container.BuildStringOfHierarchy (sb, 0, state.currentPointer.Resolve()); + + return sb.ToString(); + } + + private void NextContent() + { + // Setting previousContentObject is critical for VisitChangedContainersDueToDivert + state.previousPointer = state.currentPointer; + + // Divert step? + if (!state.divertedPointer.isNull) { + + state.currentPointer = state.divertedPointer; + state.divertedPointer = Pointer.Null; + + // Internally uses state.previousContentObject and state.currentContentObject + VisitChangedContainersDueToDivert (); + + // Diverted location has valid content? + if (!state.currentPointer.isNull) { + return; + } + + // Otherwise, if diverted location doesn't have valid content, + // drop down and attempt to increment. + // This can happen if the diverted path is intentionally jumping + // to the end of a container - e.g. a Conditional that's re-joining + } + + bool successfulPointerIncrement = IncrementContentPointer (); + + // Ran out of content? Try to auto-exit from a function, + // or finish evaluating the content of a thread + if (!successfulPointerIncrement) { + + bool didPop = false; + + if (state.callStack.CanPop (PushPopType.Function)) { + + // Pop from the call stack + state.PopCallstack (PushPopType.Function); + + // This pop was due to dropping off the end of a function that didn't return anything, + // so in this case, we make sure that the evaluator has something to chomp on if it needs it + if (state.inExpressionEvaluation) { + state.PushEvaluationStack (new Runtime.Void ()); + } + + didPop = true; + } else if (state.callStack.canPopThread) { + state.callStack.PopThread (); + + didPop = true; + } else { + state.TryExitFunctionEvaluationFromGame (); + } + + // Step past the point where we last called out + if (didPop && !state.currentPointer.isNull) { + NextContent (); + } + } + } + + bool IncrementContentPointer() + { + bool successfulIncrement = true; + + var pointer = state.callStack.currentElement.currentPointer; + pointer.index++; + + // Each time we step off the end, we fall out to the next container, all the + // while we're in indexed rather than named content + while (pointer.index >= pointer.container.content.Count) { + + successfulIncrement = false; + + Container nextAncestor = pointer.container.parent as Container; + if (!nextAncestor) { + break; + } + + var indexInAncestor = nextAncestor.content.IndexOf (pointer.container); + if (indexInAncestor == -1) { + break; + } + + pointer = new Pointer (nextAncestor, indexInAncestor); + + // Increment to next content in outer container + pointer.index++; + + successfulIncrement = true; + } + + if (!successfulIncrement) pointer = Pointer.Null; + + state.callStack.currentElement.currentPointer = pointer; + + return successfulIncrement; + } + + bool TryFollowDefaultInvisibleChoice() + { + var allChoices = _state.currentChoices; + + // Is a default invisible choice the ONLY choice? + var invisibleChoices = allChoices.Where (c => c.isInvisibleDefault).ToList(); + if (invisibleChoices.Count == 0 || allChoices.Count > invisibleChoices.Count) + return false; + + var choice = invisibleChoices [0]; + + // Invisible choice may have been generated on a different thread, + // in which case we need to restore it before we continue + state.callStack.currentThread = choice.threadAtGeneration; + + // If there's a chance that this state will be rolled back to before + // the invisible choice then make sure that the choice thread is + // left intact, and it isn't re-entered in an old state. + if ( _stateSnapshotAtLastNewline != null ) + state.callStack.currentThread = state.callStack.ForkThread(); + + ChoosePath (choice.targetPath, incrementingTurnIndex: false); + + return true; + } + + + // Note that this is O(n), since it re-evaluates the shuffle indices + // from a consistent seed each time. + // TODO: Is this the best algorithm it can be? + int NextSequenceShuffleIndex() + { + var numElementsIntVal = state.PopEvaluationStack () as IntValue; + if (numElementsIntVal == null) { + Error ("expected number of elements in sequence for shuffle index"); + return 0; + } + + var seqContainer = state.currentPointer.container; + + int numElements = numElementsIntVal.value; + + var seqCountVal = state.PopEvaluationStack () as IntValue; + var seqCount = seqCountVal.value; + var loopIndex = seqCount / numElements; + var iterationIndex = seqCount % numElements; + + // Generate the same shuffle based on: + // - The hash of this container, to make sure it's consistent + // each time the runtime returns to the sequence + // - How many times the runtime has looped around this full shuffle + var seqPathStr = seqContainer.path.ToString(); + int sequenceHash = 0; + foreach (char c in seqPathStr) { + sequenceHash += c; + } + var randomSeed = sequenceHash + loopIndex + state.storySeed; + var random = new Random (randomSeed); + + var unpickedIndices = new List (); + for (int i = 0; i < numElements; ++i) { + unpickedIndices.Add (i); + } + + for (int i = 0; i <= iterationIndex; ++i) { + var chosen = random.Next () % unpickedIndices.Count; + var chosenIndex = unpickedIndices [chosen]; + unpickedIndices.RemoveAt (chosen); + + if (i == iterationIndex) { + return chosenIndex; + } + } + + throw new System.Exception ("Should never reach here"); + } + + // Throw an exception that gets caught and causes AddError to be called, + // then exits the flow. + public void Error(string message, bool useEndLineNumber = false) + { + var e = new StoryException (message); + e.useEndLineNumber = useEndLineNumber; + throw e; + } + + public void Warning (string message) + { + AddError (message, isWarning:true); + } + + void AddError (string message, bool isWarning = false, bool useEndLineNumber = false) + { + var dm = currentDebugMetadata; + + var errorTypeStr = isWarning ? "WARNING" : "ERROR"; + + if (dm != null) { + int lineNum = useEndLineNumber ? dm.endLineNumber : dm.startLineNumber; + message = string.Format ("RUNTIME {0}: '{1}' line {2}: {3}", errorTypeStr, dm.fileName, lineNum, message); + } else if( !state.currentPointer.isNull ) { + message = string.Format ("RUNTIME {0}: ({1}): {2}", errorTypeStr, state.currentPointer.path, message); + } else { + message = "RUNTIME "+errorTypeStr+": " + message; + } + + state.AddError (message, isWarning); + + // In a broken state don't need to know about any other errors. + if( !isWarning ) + state.ForceEnd (); + } + + void Assert(bool condition, string message = null, params object[] formatParams) + { + if (condition == false) { + if (message == null) { + message = "Story assert"; + } + if (formatParams != null && formatParams.Count() > 0) { + message = string.Format (message, formatParams); + } + + throw new System.Exception (message + " " + currentDebugMetadata); + } + } + + DebugMetadata currentDebugMetadata + { + get { + DebugMetadata dm; + + // Try to get from the current path first + var pointer = state.currentPointer; + if (!pointer.isNull) { + dm = pointer.Resolve().debugMetadata; + if (dm != null) { + return dm; + } + } + + // Move up callstack if possible + for (int i = state.callStack.elements.Count - 1; i >= 0; --i) { + pointer = state.callStack.elements [i].currentPointer; + if (!pointer.isNull && pointer.Resolve() != null) { + dm = pointer.Resolve().debugMetadata; + if (dm != null) { + return dm; + } + } + } + + // Current/previous path may not be valid if we've just had an error, + // or if we've simply run out of content. + // As a last resort, try to grab something from the output stream + for (int i = state.outputStream.Count - 1; i >= 0; --i) { + var outputObj = state.outputStream [i]; + dm = outputObj.debugMetadata; + if (dm != null) { + return dm; + } + } + + return null; + } + } + + int currentLineNumber + { + get { + var dm = currentDebugMetadata; + if (dm != null) { + return dm.startLineNumber; + } + return 0; + } + } + + public Container mainContentContainer { + get { + if (_temporaryEvaluationContainer) { + return _temporaryEvaluationContainer; + } else { + return _mainContentContainer; + } + } + } + + Container _mainContentContainer; + ListDefinitionsOrigin _listDefinitions; + + struct ExternalFunctionDef { + public ExternalFunction function; + public bool lookaheadSafe; + } + Dictionary _externals; + Dictionary _variableObservers; + bool _hasValidatedExternals; + + Container _temporaryEvaluationContainer; + + StoryState _state; + + bool _asyncContinueActive; + StoryState _stateSnapshotAtLastNewline = null; + bool _sawLookaheadUnsafeFunctionAfterNewline = false; + + int _recursiveContinueCount = 0; + + bool _asyncSaving; + + Profiler _profiler; + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/StoryException.cs b/Assets/Ink/InkLibs/InkRuntime/StoryException.cs new file mode 100644 index 0000000..5b0a20f --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/StoryException.cs @@ -0,0 +1,24 @@ +namespace Ink.Runtime +{ + /// + /// Exception that represents an error when running a Story at runtime. + /// An exception being thrown of this type is typically when there's + /// a bug in your ink, rather than in the ink engine itself! + /// + public class StoryException : System.Exception + { + public bool useEndLineNumber; + + /// + /// Constructs a default instance of a StoryException without a message. + /// + public StoryException () { } + + /// + /// Constructs an instance of a StoryException with a message. + /// + /// The error message. + public StoryException(string message) : base(message) {} + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/StoryState.cs b/Assets/Ink/InkLibs/InkRuntime/StoryState.cs new file mode 100644 index 0000000..36fd1b2 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/StoryState.cs @@ -0,0 +1,1341 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; +using System.IO; + +namespace Ink.Runtime +{ + /// + /// All story state information is included in the StoryState class, + /// including global variables, read counts, the pointer to the current + /// point in the story, the call stack (for tunnels, functions, etc), + /// and a few other smaller bits and pieces. You can save the current + /// state using the json serialisation functions ToJson and LoadJson. + /// + public class StoryState + { + /// + /// The current version of the state save file JSON-based format. + /// + // + // Backward compatible changes since v8: + // v10: dynamic tags + // v9: multi-flows + public const int kInkSaveStateVersion = 10; + const int kMinCompatibleLoadVersion = 8; + + /// + /// Callback for when a state is loaded + /// + public event Action onDidLoadState; + + /// + /// Exports the current state to json format, in order to save the game. + /// + /// The save state in json format. + public string ToJson() { + var writer = new SimpleJson.Writer(); + WriteJson(writer); + return writer.ToString(); + } + + /// + /// Exports the current state to json format, in order to save the game. + /// For this overload you can pass in a custom stream, such as a FileStream. + /// + public void ToJson(Stream stream) { + var writer = new SimpleJson.Writer(stream); + WriteJson(writer); + } + + /// + /// Loads a previously saved state in JSON format. + /// + /// The JSON string to load. + public void LoadJson(string json) + { + var jObject = SimpleJson.TextToDictionary (json); + LoadJsonObj(jObject); + if(onDidLoadState != null) onDidLoadState(); + } + + /// + /// Gets the visit/read count of a particular Container at the given path. + /// For a knot or stitch, that path string will be in the form: + /// + /// knot + /// knot.stitch + /// + /// + /// The number of times the specific knot or stitch has + /// been enountered by the ink engine. + /// The dot-separated path string of + /// the specific knot or stitch. + public int VisitCountAtPathString(string pathString) + { + int visitCountOut; + + if ( _patch != null ) { + var container = story.ContentAtPath(new Path(pathString)).container; + if (container == null) + throw new Exception("Content at path not found: " + pathString); + + if( _patch.TryGetVisitCount(container, out visitCountOut) ) + return visitCountOut; + } + + if (_visitCounts.TryGetValue(pathString, out visitCountOut)) + return visitCountOut; + + return 0; + } + + public int VisitCountForContainer(Container container) + { + if (!container.visitsShouldBeCounted) + { + story.Error("Read count for target (" + container.name + " - on " + container.debugMetadata + ") unknown."); + return 0; + } + + int count = 0; + if (_patch != null && _patch.TryGetVisitCount(container, out count)) + return count; + + var containerPathStr = container.path.ToString(); + _visitCounts.TryGetValue(containerPathStr, out count); + return count; + } + + public void IncrementVisitCountForContainer(Container container) + { + if( _patch != null ) { + var currCount = VisitCountForContainer(container); + currCount++; + _patch.SetVisitCount(container, currCount); + return; + } + + int count = 0; + var containerPathStr = container.path.ToString(); + _visitCounts.TryGetValue(containerPathStr, out count); + count++; + _visitCounts[containerPathStr] = count; + } + + public void RecordTurnIndexVisitToContainer(Container container) + { + if( _patch != null ) { + _patch.SetTurnIndex(container, currentTurnIndex); + return; + } + + var containerPathStr = container.path.ToString(); + _turnIndices[containerPathStr] = currentTurnIndex; + } + + public int TurnsSinceForContainer(Container container) + { + if (!container.turnIndexShouldBeCounted) + { + story.Error("TURNS_SINCE() for target (" + container.name + " - on " + container.debugMetadata + ") unknown."); + } + + int index = 0; + + if ( _patch != null && _patch.TryGetTurnIndex(container, out index) ) { + return currentTurnIndex - index; + } + + var containerPathStr = container.path.ToString(); + if (_turnIndices.TryGetValue(containerPathStr, out index)) + { + return currentTurnIndex - index; + } + else + { + return -1; + } + } + + public int callstackDepth { + get { + return callStack.depth; + } + } + + // REMEMBER! REMEMBER! REMEMBER! + // When adding state, update the Copy method, and serialisation. + // REMEMBER! REMEMBER! REMEMBER! + + public List outputStream { + get { + return _currentFlow.outputStream; + } + } + + + + public List currentChoices { + get { + // If we can continue generating text content rather than choices, + // then we reflect the choice list as being empty, since choices + // should always come at the end. + if( canContinue ) return new List(); + return _currentFlow.currentChoices; + } + } + public List generatedChoices { + get { + return _currentFlow.currentChoices; + } + } + + // TODO: Consider removing currentErrors / currentWarnings altogether + // and relying on client error handler code immediately handling StoryExceptions etc + // Or is there a specific reason we need to collect potentially multiple + // errors before throwing/exiting? + public List currentErrors { get; private set; } + public List currentWarnings { get; private set; } + public VariablesState variablesState { get; private set; } + public CallStack callStack { + get { + return _currentFlow.callStack; + } + // set { + // _currentFlow.callStack = value; + // } + } + + public List evaluationStack { get; private set; } + public Pointer divertedPointer { get; set; } + + public int currentTurnIndex { get; private set; } + public int storySeed { get; set; } + public int previousRandom { get; set; } + public bool didSafeExit { get; set; } + + public Story story { get; set; } + + /// + /// String representation of the location where the story currently is. + /// + public string currentPathString { + get { + var pointer = currentPointer; + if (pointer.isNull) + return null; + else + return pointer.path.ToString(); + } + } + + public Runtime.Pointer currentPointer { + get { + return callStack.currentElement.currentPointer; + } + set { + callStack.currentElement.currentPointer = value; + } + } + + public Pointer previousPointer { + get { + return callStack.currentThread.previousPointer; + } + set { + callStack.currentThread.previousPointer = value; + } + } + + public bool canContinue { + get { + return !currentPointer.isNull && !hasError; + } + } + + public bool hasError + { + get { + return currentErrors != null && currentErrors.Count > 0; + } + } + + public bool hasWarning { + get { + return currentWarnings != null && currentWarnings.Count > 0; + } + } + + public string currentText + { + get + { + if( _outputStreamTextDirty ) { + var sb = new StringBuilder (); + + bool inTag = false; + foreach (var outputObj in outputStream) { + var textContent = outputObj as StringValue; + if (!inTag && textContent != null) { + sb.Append(textContent.value); + } else { + var controlCommand = outputObj as ControlCommand; + if( controlCommand != null ) { + if( controlCommand.commandType == ControlCommand.CommandType.BeginTag ) { + inTag = true; + } else if( controlCommand.commandType == ControlCommand.CommandType.EndTag ) { + inTag = false; + } + } + } + } + + _currentText = CleanOutputWhitespace (sb.ToString ()); + + _outputStreamTextDirty = false; + } + + return _currentText; + } + } + string _currentText; + + // Cleans inline whitespace in the following way: + // - Removes all whitespace from the start and end of line (including just before a \n) + // - Turns all consecutive space and tab runs into single spaces (HTML style) + public string CleanOutputWhitespace(string str) + { + var sb = new StringBuilder(str.Length); + + int currentWhitespaceStart = -1; + int startOfLine = 0; + + for (int i = 0; i < str.Length; i++) { + var c = str[i]; + + bool isInlineWhitespace = c == ' ' || c == '\t'; + + if (isInlineWhitespace && currentWhitespaceStart == -1) + currentWhitespaceStart = i; + + if (!isInlineWhitespace) { + if (c != '\n' && currentWhitespaceStart > 0 && currentWhitespaceStart != startOfLine) { + sb.Append(' '); + } + currentWhitespaceStart = -1; + } + + if (c == '\n') + startOfLine = i + 1; + + if (!isInlineWhitespace) + sb.Append(c); + } + + return sb.ToString(); + } + + public List currentTags + { + get + { + if( _outputStreamTagsDirty ) { + _currentTags = new List(); + + bool inTag = false; + var sb = new StringBuilder (); + + foreach (var outputObj in outputStream) { + var controlCommand = outputObj as ControlCommand; + + if( controlCommand != null ) { + if( controlCommand.commandType == ControlCommand.CommandType.BeginTag ) { + if( inTag && sb.Length > 0 ) { + var txt = CleanOutputWhitespace(sb.ToString()); + _currentTags.Add(txt); + sb.Clear(); + } + inTag = true; + } + + else if( controlCommand.commandType == ControlCommand.CommandType.EndTag ) { + if( sb.Length > 0 ) { + var txt = CleanOutputWhitespace(sb.ToString()); + _currentTags.Add(txt); + sb.Clear(); + } + inTag = false; + } + } + + else if( inTag ) { + var strVal = outputObj as StringValue; + if( strVal != null ) { + sb.Append(strVal.value); + } + } + + else { + var tag = outputObj as Tag; + if (tag != null && tag.text != null && tag.text.Length > 0) { + _currentTags.Add (tag.text); // tag.text has whitespae already cleaned + } + } + + } + + if( sb.Length > 0 ) { + var txt = CleanOutputWhitespace(sb.ToString()); + _currentTags.Add(txt); + sb.Clear(); + } + + _outputStreamTagsDirty = false; + } + + return _currentTags; + } + } + List _currentTags; + + public string currentFlowName { + get { + return _currentFlow.name; + } + } + + public bool currentFlowIsDefaultFlow { + get { + return _currentFlow.name == kDefaultFlowName; + } + } + + public List aliveFlowNames { + get { + + if( _aliveFlowNamesDirty ) { + _aliveFlowNames = new List(); + + if (_namedFlows != null) + { + foreach (string flowName in _namedFlows.Keys) { + if (flowName != kDefaultFlowName) { + _aliveFlowNames.Add(flowName); + } + } + } + + _aliveFlowNamesDirty = false; + } + + return _aliveFlowNames; + } + } + + List _aliveFlowNames; + + public bool inExpressionEvaluation { + get { + return callStack.currentElement.inExpressionEvaluation; + } + set { + callStack.currentElement.inExpressionEvaluation = value; + } + } + + public StoryState (Story story) + { + this.story = story; + + _currentFlow = new Flow(kDefaultFlowName, story); + + OutputStreamDirty(); + _aliveFlowNamesDirty = true; + + evaluationStack = new List (); + + variablesState = new VariablesState (callStack, story.listDefinitions); + + _visitCounts = new Dictionary (); + _turnIndices = new Dictionary (); + + currentTurnIndex = -1; + + // Seed the shuffle random numbers + int timeSeed = DateTime.Now.Millisecond; + storySeed = (new Random (timeSeed)).Next () % 100; + previousRandom = 0; + + + + GoToStart(); + } + + public void GoToStart() + { + callStack.currentElement.currentPointer = Pointer.StartOf (story.mainContentContainer); + } + + internal void SwitchFlow_Internal(string flowName) + { + if(flowName == null) throw new System.Exception("Must pass a non-null string to Story.SwitchFlow"); + + if( _namedFlows == null ) { + _namedFlows = new Dictionary(); + _namedFlows[kDefaultFlowName] = _currentFlow; + } + + if( flowName == _currentFlow.name ) { + return; + } + + Flow flow; + if( !_namedFlows.TryGetValue(flowName, out flow) ) { + flow = new Flow(flowName, story); + _namedFlows[flowName] = flow; + _aliveFlowNamesDirty = true; + } + + _currentFlow = flow; + variablesState.callStack = _currentFlow.callStack; + + // Cause text to be regenerated from output stream if necessary + OutputStreamDirty(); + } + + internal void SwitchToDefaultFlow_Internal() + { + if( _namedFlows == null ) return; + SwitchFlow_Internal(kDefaultFlowName); + } + + internal void RemoveFlow_Internal(string flowName) + { + if(flowName == null) throw new System.Exception("Must pass a non-null string to Story.DestroyFlow"); + if(flowName == kDefaultFlowName) throw new System.Exception("Cannot destroy default flow"); + + // If we're currently in the flow that's being removed, switch back to default + if( _currentFlow.name == flowName ) { + SwitchToDefaultFlow_Internal(); + } + + _namedFlows.Remove(flowName); + _aliveFlowNamesDirty = true; + } + + // Warning: Any Runtime.Object content referenced within the StoryState will + // be re-referenced rather than cloned. This is generally okay though since + // Runtime.Objects are treated as immutable after they've been set up. + // (e.g. we don't edit a Runtime.StringValue after it's been created an added.) + // I wonder if there's a sensible way to enforce that..?? + public StoryState CopyAndStartPatching() + { + var copy = new StoryState(story); + + copy._patch = new StatePatch(_patch); + + // Hijack the new default flow to become a copy of our current one + // If the patch is applied, then this new flow will replace the old one in _namedFlows + copy._currentFlow.name = _currentFlow.name; + copy._currentFlow.callStack = new CallStack (_currentFlow.callStack); + copy._currentFlow.currentChoices.AddRange(_currentFlow.currentChoices); + copy._currentFlow.outputStream.AddRange(_currentFlow.outputStream); + copy.OutputStreamDirty(); + + // The copy of the state has its own copy of the named flows dictionary, + // except with the current flow replaced with the copy above + // (Assuming we're in multi-flow mode at all. If we're not then + // the above copy is simply the default flow copy and we're done) + if( _namedFlows != null ) { + copy._namedFlows = new Dictionary(); + foreach(var namedFlow in _namedFlows) + copy._namedFlows[namedFlow.Key] = namedFlow.Value; + copy._namedFlows[_currentFlow.name] = copy._currentFlow; + copy._aliveFlowNamesDirty = true; + } + + if (hasError) { + copy.currentErrors = new List (); + copy.currentErrors.AddRange (currentErrors); + } + if (hasWarning) { + copy.currentWarnings = new List (); + copy.currentWarnings.AddRange (currentWarnings); + } + + + // ref copy - exactly the same variables state! + // we're expecting not to read it only while in patch mode + // (though the callstack will be modified) + copy.variablesState = variablesState; + copy.variablesState.callStack = copy.callStack; + copy.variablesState.patch = copy._patch; + + copy.evaluationStack.AddRange (evaluationStack); + + if (!divertedPointer.isNull) + copy.divertedPointer = divertedPointer; + + copy.previousPointer = previousPointer; + + // visit counts and turn indicies will be read only, not modified + // while in patch mode + copy._visitCounts = _visitCounts; + copy._turnIndices = _turnIndices; + + copy.currentTurnIndex = currentTurnIndex; + copy.storySeed = storySeed; + copy.previousRandom = previousRandom; + + copy.didSafeExit = didSafeExit; + + return copy; + } + + public void RestoreAfterPatch() + { + // VariablesState was being borrowed by the patched + // state, so restore it with our own callstack. + // _patch will be null normally, but if you're in the + // middle of a save, it may contain a _patch for save purpsoes. + variablesState.callStack = callStack; + variablesState.patch = _patch; // usually null + } + + public void ApplyAnyPatch() + { + if (_patch == null) return; + + variablesState.ApplyPatch(); + + foreach(var pathToCount in _patch.visitCounts) + ApplyCountChanges(pathToCount.Key, pathToCount.Value, isVisit:true); + + foreach (var pathToIndex in _patch.turnIndices) + ApplyCountChanges(pathToIndex.Key, pathToIndex.Value, isVisit:false); + + _patch = null; + } + + void ApplyCountChanges(Container container, int newCount, bool isVisit) + { + var counts = isVisit ? _visitCounts : _turnIndices; + counts[container.path.ToString()] = newCount; + } + + void WriteJson(SimpleJson.Writer writer) + { + writer.WriteObjectStart(); + + // Flows + writer.WritePropertyStart("flows"); + writer.WriteObjectStart(); + + // Multi-flow + if( _namedFlows != null ) { + foreach(var namedFlow in _namedFlows) { + writer.WriteProperty(namedFlow.Key, namedFlow.Value.WriteJson); + } + } + + // Single flow + else { + writer.WriteProperty(_currentFlow.name, _currentFlow.WriteJson); + } + + writer.WriteObjectEnd(); + writer.WritePropertyEnd(); // end of flows + + writer.WriteProperty("currentFlowName", _currentFlow.name); + + writer.WriteProperty("variablesState", variablesState.WriteJson); + + writer.WriteProperty("evalStack", w => Json.WriteListRuntimeObjs(w, evaluationStack)); + + + if (!divertedPointer.isNull) + writer.WriteProperty("currentDivertTarget", divertedPointer.path.componentsString); + + writer.WriteProperty("visitCounts", w => Json.WriteIntDictionary(w, _visitCounts)); + writer.WriteProperty("turnIndices", w => Json.WriteIntDictionary(w, _turnIndices)); + + + writer.WriteProperty("turnIdx", currentTurnIndex); + writer.WriteProperty("storySeed", storySeed); + writer.WriteProperty("previousRandom", previousRandom); + + writer.WriteProperty("inkSaveVersion", kInkSaveStateVersion); + + // Not using this right now, but could do in future. + writer.WriteProperty("inkFormatVersion", Story.inkVersionCurrent); + + writer.WriteObjectEnd(); + } + + + void LoadJsonObj(Dictionary jObject) + { + object jSaveVersion = null; + if (!jObject.TryGetValue("inkSaveVersion", out jSaveVersion)) { + throw new Exception ("ink save format incorrect, can't load."); + } + else if ((int)jSaveVersion < kMinCompatibleLoadVersion) { + throw new Exception("Ink save format isn't compatible with the current version (saw '"+jSaveVersion+"', but minimum is "+kMinCompatibleLoadVersion+"), so can't load."); + } + + // Flows: Always exists in latest format (even if there's just one default) + // but this dictionary doesn't exist in prev format + object flowsObj = null; + if (jObject.TryGetValue("flows", out flowsObj)) { + var flowsObjDict = (Dictionary)flowsObj; + + // Single default flow + if( flowsObjDict.Count == 1 ) + _namedFlows = null; + + // Multi-flow, need to create flows dict + else if( _namedFlows == null ) + _namedFlows = new Dictionary(); + + // Multi-flow, already have a flows dict + else + _namedFlows.Clear(); + + // Load up each flow (there may only be one) + foreach(var namedFlowObj in flowsObjDict) { + var name = namedFlowObj.Key; + var flowObj = (Dictionary)namedFlowObj.Value; + + // Load up this flow using JSON data + var flow = new Flow(name, story, flowObj); + + if( flowsObjDict.Count == 1 ) { + _currentFlow = new Flow(name, story, flowObj); + } else { + _namedFlows[name] = flow; + } + } + + if( _namedFlows != null && _namedFlows.Count > 1 ) { + var currFlowName = (string)jObject["currentFlowName"]; + _currentFlow = _namedFlows[currFlowName]; + } + } + + // Old format: individually load up callstack, output stream, choices in current/default flow + else { + _namedFlows = null; + _currentFlow.name = kDefaultFlowName; + _currentFlow.callStack.SetJsonToken ((Dictionary < string, object > )jObject ["callstackThreads"], story); + _currentFlow.outputStream = Json.JArrayToRuntimeObjList ((List)jObject ["outputStream"]); + _currentFlow.currentChoices = Json.JArrayToRuntimeObjList((List)jObject ["currentChoices"]); + + object jChoiceThreadsObj = null; + jObject.TryGetValue("choiceThreads", out jChoiceThreadsObj); + _currentFlow.LoadFlowChoiceThreads((Dictionary)jChoiceThreadsObj, story); + } + + OutputStreamDirty(); + _aliveFlowNamesDirty = true; + + variablesState.SetJsonToken((Dictionary < string, object> )jObject["variablesState"]); + variablesState.callStack = _currentFlow.callStack; + + evaluationStack = Json.JArrayToRuntimeObjList ((List)jObject ["evalStack"]); + + + object currentDivertTargetPath; + if (jObject.TryGetValue("currentDivertTarget", out currentDivertTargetPath)) { + var divertPath = new Path (currentDivertTargetPath.ToString ()); + divertedPointer = story.PointerAtPath (divertPath); + } + + _visitCounts = Json.JObjectToIntDictionary((Dictionary)jObject["visitCounts"]); + _turnIndices = Json.JObjectToIntDictionary((Dictionary)jObject["turnIndices"]); + + currentTurnIndex = (int)jObject ["turnIdx"]; + storySeed = (int)jObject ["storySeed"]; + + // Not optional, but bug in inkjs means it's actually missing in inkjs saves + object previousRandomObj = null; + if( jObject.TryGetValue("previousRandom", out previousRandomObj) ) { + previousRandom = (int)previousRandomObj; + } else { + previousRandom = 0; + } + } + + public void ResetErrors() + { + currentErrors = null; + currentWarnings = null; + } + + public void ResetOutput(List objs = null) + { + outputStream.Clear (); + if( objs != null ) outputStream.AddRange (objs); + OutputStreamDirty(); + } + + // Push to output stream, but split out newlines in text for consistency + // in dealing with them later. + public void PushToOutputStream(Runtime.Object obj) + { + var text = obj as StringValue; + if (text) { + var listText = TrySplittingHeadTailWhitespace (text); + if (listText != null) { + foreach (var textObj in listText) { + PushToOutputStreamIndividual (textObj); + } + OutputStreamDirty(); + return; + } + } + + PushToOutputStreamIndividual (obj); + + OutputStreamDirty(); + } + + public void PopFromOutputStream (int count) + { + outputStream.RemoveRange (outputStream.Count - count, count); + OutputStreamDirty (); + } + + + // At both the start and the end of the string, split out the new lines like so: + // + // " \n \n \n the string \n is awesome \n \n " + // ^-----------^ ^-------^ + // + // Excess newlines are converted into single newlines, and spaces discarded. + // Outside spaces are significant and retained. "Interior" newlines within + // the main string are ignored, since this is for the purpose of gluing only. + // + // - If no splitting is necessary, null is returned. + // - A newline on its own is returned in a list for consistency. + List TrySplittingHeadTailWhitespace(Runtime.StringValue single) + { + string str = single.value; + + int headFirstNewlineIdx = -1; + int headLastNewlineIdx = -1; + for (int i = 0; i < str.Length; i++) { + char c = str [i]; + if (c == '\n') { + if (headFirstNewlineIdx == -1) + headFirstNewlineIdx = i; + headLastNewlineIdx = i; + } + else if (c == ' ' || c == '\t') + continue; + else + break; + } + + int tailLastNewlineIdx = -1; + int tailFirstNewlineIdx = -1; + for (int i = str.Length-1; i >= 0; i--) { + char c = str [i]; + if (c == '\n') { + if (tailLastNewlineIdx == -1) + tailLastNewlineIdx = i; + tailFirstNewlineIdx = i; + } + else if (c == ' ' || c == '\t') + continue; + else + break; + } + + // No splitting to be done? + if (headFirstNewlineIdx == -1 && tailLastNewlineIdx == -1) + return null; + + var listTexts = new List (); + int innerStrStart = 0; + int innerStrEnd = str.Length; + + if (headFirstNewlineIdx != -1) { + if (headFirstNewlineIdx > 0) { + var leadingSpaces = new StringValue (str.Substring (0, headFirstNewlineIdx)); + listTexts.Add(leadingSpaces); + } + listTexts.Add (new StringValue ("\n")); + innerStrStart = headLastNewlineIdx + 1; + } + + if (tailLastNewlineIdx != -1) { + innerStrEnd = tailFirstNewlineIdx; + } + + if (innerStrEnd > innerStrStart) { + var innerStrText = str.Substring (innerStrStart, innerStrEnd - innerStrStart); + listTexts.Add (new StringValue (innerStrText)); + } + + if (tailLastNewlineIdx != -1 && tailFirstNewlineIdx > headLastNewlineIdx) { + listTexts.Add (new StringValue ("\n")); + if (tailLastNewlineIdx < str.Length - 1) { + int numSpaces = (str.Length - tailLastNewlineIdx) - 1; + var trailingSpaces = new StringValue (str.Substring (tailLastNewlineIdx + 1, numSpaces)); + listTexts.Add(trailingSpaces); + } + } + + return listTexts; + } + + void PushToOutputStreamIndividual(Runtime.Object obj) + { + var glue = obj as Runtime.Glue; + var text = obj as Runtime.StringValue; + + bool includeInOutput = true; + + // New glue, so chomp away any whitespace from the end of the stream + if (glue) { + TrimNewlinesFromOutputStream(); + includeInOutput = true; + } + + // New text: do we really want to append it, if it's whitespace? + // Two different reasons for whitespace to be thrown away: + // - Function start/end trimming + // - User defined glue: <> + // We also need to know when to stop trimming, when there's non-whitespace. + else if( text ) { + + // Where does the current function call begin? + var functionTrimIndex = -1; + var currEl = callStack.currentElement; + if (currEl.type == PushPopType.Function) { + functionTrimIndex = currEl.functionStartInOuputStream; + } + + // Do 2 things: + // - Find latest glue + // - Check whether we're in the middle of string evaluation + // If we're in string eval within the current function, we + // don't want to trim back further than the length of the current string. + int glueTrimIndex = -1; + for (int i = outputStream.Count - 1; i >= 0; i--) { + var o = outputStream [i]; + var c = o as ControlCommand; + var g = o as Glue; + + // Find latest glue + if (g) { + glueTrimIndex = i; + break; + } + + // Don't function-trim past the start of a string evaluation section + else if (c && c.commandType == ControlCommand.CommandType.BeginString) { + if (i >= functionTrimIndex) { + functionTrimIndex = -1; + } + break; + } + } + + // Where is the most agressive (earliest) trim point? + var trimIndex = -1; + if (glueTrimIndex != -1 && functionTrimIndex != -1) + trimIndex = Math.Min (functionTrimIndex, glueTrimIndex); + else if (glueTrimIndex != -1) + trimIndex = glueTrimIndex; + else + trimIndex = functionTrimIndex; + + // So, are we trimming then? + if (trimIndex != -1) { + + // While trimming, we want to throw all newlines away, + // whether due to glue or the start of a function + if (text.isNewline) { + includeInOutput = false; + } + + // Able to completely reset when normal text is pushed + else if (text.isNonWhitespace) { + + if( glueTrimIndex > -1 ) + RemoveExistingGlue (); + + // Tell all functions in callstack that we have seen proper text, + // so trimming whitespace at the start is done. + if (functionTrimIndex > -1) { + var callstackElements = callStack.elements; + for (int i = callstackElements.Count - 1; i >= 0; i--) { + var el = callstackElements [i]; + if (el.type == PushPopType.Function) { + el.functionStartInOuputStream = -1; + } else { + break; + } + } + } + } + } + + // De-duplicate newlines, and don't ever lead with a newline + else if (text.isNewline) { + if (outputStreamEndsInNewline || !outputStreamContainsContent) + includeInOutput = false; + } + } + + if (includeInOutput) { + outputStream.Add (obj); + OutputStreamDirty(); + } + } + + void TrimNewlinesFromOutputStream() + { + int removeWhitespaceFrom = -1; + + // Work back from the end, and try to find the point where + // we need to start removing content. + // - Simply work backwards to find the first newline in a string of whitespace + // e.g. This is the content \n \n\n + // ^---------^ whitespace to remove + // ^--- first while loop stops here + int i = outputStream.Count-1; + while (i >= 0) { + var obj = outputStream [i]; + var cmd = obj as ControlCommand; + var txt = obj as StringValue; + + if (cmd || (txt && txt.isNonWhitespace)) { + break; + } + else if (txt && txt.isNewline) { + removeWhitespaceFrom = i; + } + i--; + } + + // Remove the whitespace + if (removeWhitespaceFrom >= 0) { + i=removeWhitespaceFrom; + while(i < outputStream.Count) { + var text = outputStream [i] as StringValue; + if (text) { + outputStream.RemoveAt (i); + } else { + i++; + } + } + } + + OutputStreamDirty(); + } + + // Only called when non-whitespace is appended + void RemoveExistingGlue() + { + for (int i = outputStream.Count - 1; i >= 0; i--) { + var c = outputStream [i]; + if (c is Glue) { + outputStream.RemoveAt (i); + } else if( c is ControlCommand ) { // e.g. BeginString + break; + } + } + + OutputStreamDirty(); + } + + public bool outputStreamEndsInNewline { + get { + if (outputStream.Count > 0) { + + for (int i = outputStream.Count - 1; i >= 0; i--) { + var obj = outputStream [i]; + if (obj is ControlCommand) // e.g. BeginString + break; + var text = outputStream [i] as StringValue; + if (text) { + if (text.isNewline) + return true; + else if (text.isNonWhitespace) + break; + } + } + } + + return false; + } + } + + public bool outputStreamContainsContent { + get { + foreach (var content in outputStream) { + if (content is StringValue) + return true; + } + return false; + } + } + + public bool inStringEvaluation { + get { + for (int i = outputStream.Count - 1; i >= 0; i--) { + var cmd = outputStream [i] as ControlCommand; + if (cmd && cmd.commandType == ControlCommand.CommandType.BeginString) { + return true; + } + } + + return false; + } + } + + public void PushEvaluationStack(Runtime.Object obj) + { + // Include metadata about the origin List for list values when + // they're used, so that lower level functions can make use + // of the origin list to get related items, or make comparisons + // with the integer values etc. + var listValue = obj as ListValue; + if (listValue) { + + // Update origin when list is has something to indicate the list origin + var rawList = listValue.value; + if (rawList.originNames != null) { + if( rawList.origins == null ) rawList.origins = new List(); + rawList.origins.Clear(); + + foreach (var n in rawList.originNames) { + ListDefinition def = null; + story.listDefinitions.TryListGetDefinition (n, out def); + if( !rawList.origins.Contains(def) ) + rawList.origins.Add (def); + } + } + } + + evaluationStack.Add(obj); + } + + public Runtime.Object PopEvaluationStack() + { + var obj = evaluationStack [evaluationStack.Count - 1]; + evaluationStack.RemoveAt (evaluationStack.Count - 1); + return obj; + } + + public Runtime.Object PeekEvaluationStack() + { + return evaluationStack [evaluationStack.Count - 1]; + } + + public List PopEvaluationStack(int numberOfObjects) + { + if(numberOfObjects > evaluationStack.Count) { + throw new System.Exception ("trying to pop too many objects"); + } + + var popped = evaluationStack.GetRange (evaluationStack.Count - numberOfObjects, numberOfObjects); + evaluationStack.RemoveRange (evaluationStack.Count - numberOfObjects, numberOfObjects); + return popped; + } + + /// + /// Ends the current ink flow, unwrapping the callstack but without + /// affecting any variables. Useful if the ink is (say) in the middle + /// a nested tunnel, and you want it to reset so that you can divert + /// elsewhere using ChoosePathString(). Otherwise, after finishing + /// the content you diverted to, it would continue where it left off. + /// Calling this is equivalent to calling -> END in ink. + /// + public void ForceEnd() + { + callStack.Reset(); + + _currentFlow.currentChoices.Clear(); + + currentPointer = Pointer.Null; + previousPointer = Pointer.Null; + + didSafeExit = true; + } + + // Add the end of a function call, trim any whitespace from the end. + // We always trim the start and end of the text that a function produces. + // The start whitespace is discard as it is generated, and the end + // whitespace is trimmed in one go here when we pop the function. + void TrimWhitespaceFromFunctionEnd () + { + Debug.Assert (callStack.currentElement.type == PushPopType.Function); + + var functionStartPoint = callStack.currentElement.functionStartInOuputStream; + + // If the start point has become -1, it means that some non-whitespace + // text has been pushed, so it's safe to go as far back as we're able. + if (functionStartPoint == -1) { + functionStartPoint = 0; + } + + // Trim whitespace from END of function call + for (int i = outputStream.Count - 1; i >= functionStartPoint; i--) { + var obj = outputStream [i]; + var txt = obj as StringValue; + var cmd = obj as ControlCommand; + if (!txt) continue; + if (cmd) break; + + if (txt.isNewline || txt.isInlineWhitespace) { + outputStream.RemoveAt (i); + OutputStreamDirty (); + } else { + break; + } + } + } + + public void PopCallstack (PushPopType? popType = null) + { + // Add the end of a function call, trim any whitespace from the end. + if (callStack.currentElement.type == PushPopType.Function) + TrimWhitespaceFromFunctionEnd (); + + callStack.Pop (popType); + } + + // Don't make public since the method need to be wrapped in Story for visit counting + public void SetChosenPath(Path path, bool incrementingTurnIndex) + { + // Changing direction, assume we need to clear current set of choices + _currentFlow.currentChoices.Clear (); + + var newPointer = story.PointerAtPath (path); + if (!newPointer.isNull && newPointer.index == -1) + newPointer.index = 0; + + currentPointer = newPointer; + + if( incrementingTurnIndex ) + currentTurnIndex++; + } + + public void StartFunctionEvaluationFromGame (Container funcContainer, params object[] arguments) + { + callStack.Push (PushPopType.FunctionEvaluationFromGame, evaluationStack.Count); + callStack.currentElement.currentPointer = Pointer.StartOf (funcContainer); + + PassArgumentsToEvaluationStack (arguments); + } + + public void PassArgumentsToEvaluationStack (params object [] arguments) + { + // Pass arguments onto the evaluation stack + if (arguments != null) { + for (int i = 0; i < arguments.Length; i++) { + if (!(arguments [i] is int || arguments [i] is float || arguments [i] is string || arguments [i] is bool || arguments [i] is InkList)) { + throw new System.ArgumentException ("ink arguments when calling EvaluateFunction / ChoosePathStringWithParameters must be int, float, string, bool or InkList. Argument was "+(arguments [i] == null ? "null" : arguments [i].GetType().Name)); + } + + PushEvaluationStack (Runtime.Value.Create (arguments [i])); + } + } + } + + public bool TryExitFunctionEvaluationFromGame () + { + if( callStack.currentElement.type == PushPopType.FunctionEvaluationFromGame ) { + currentPointer = Pointer.Null; + didSafeExit = true; + return true; + } + + return false; + } + + public object CompleteFunctionEvaluationFromGame () + { + if (callStack.currentElement.type != PushPopType.FunctionEvaluationFromGame) { + throw new Exception ("Expected external function evaluation to be complete. Stack trace: "+callStack.callStackTrace); + } + + int originalEvaluationStackHeight = callStack.currentElement.evaluationStackHeightWhenPushed; + + // Do we have a returned value? + // Potentially pop multiple values off the stack, in case we need + // to clean up after ourselves (e.g. caller of EvaluateFunction may + // have passed too many arguments, and we currently have no way to check for that) + Runtime.Object returnedObj = null; + while (evaluationStack.Count > originalEvaluationStackHeight) { + var poppedObj = PopEvaluationStack (); + if (returnedObj == null) + returnedObj = poppedObj; + } + + // Finally, pop the external function evaluation + PopCallstack (PushPopType.FunctionEvaluationFromGame); + + // What did we get back? + if (returnedObj) { + if (returnedObj is Runtime.Void) + return null; + + // Some kind of value, if not void + var returnVal = returnedObj as Runtime.Value; + + // DivertTargets get returned as the string of components + // (rather than a Path, which isn't public) + if (returnVal.valueType == ValueType.DivertTarget) { + return returnVal.valueObject.ToString (); + } + + // Other types can just have their exact object type: + // int, float, string. VariablePointers get returned as strings. + return returnVal.valueObject; + } + + return null; + } + + public void AddError(string message, bool isWarning) + { + if (!isWarning) { + if (currentErrors == null) currentErrors = new List (); + currentErrors.Add (message); + } else { + if (currentWarnings == null) currentWarnings = new List (); + currentWarnings.Add (message); + } + } + + void OutputStreamDirty() + { + _outputStreamTextDirty = true; + _outputStreamTagsDirty = true; + } + + // REMEMBER! REMEMBER! REMEMBER! + // When adding state, update the Copy method and serialisation + // REMEMBER! REMEMBER! REMEMBER! + + + Dictionary _visitCounts; + Dictionary _turnIndices; + bool _outputStreamTextDirty = true; + bool _outputStreamTagsDirty = true; + + StatePatch _patch; + + Flow _currentFlow; + Dictionary _namedFlows; + const string kDefaultFlowName = "DEFAULT_FLOW"; + bool _aliveFlowNamesDirty = true; + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/StringJoinExtension.cs b/Assets/Ink/InkLibs/InkRuntime/StringJoinExtension.cs new file mode 100644 index 0000000..d650fae --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/StringJoinExtension.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ink.Runtime +{ + public static class StringExt + { + public static string Join(string separator, List objects) + { + var sb = new StringBuilder (); + + var isFirst = true; + foreach (var o in objects) { + + if (!isFirst) + sb.Append (separator); + + sb.Append (o.ToString ()); + + isFirst = false; + } + + return sb.ToString (); + } + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/Tag.cs b/Assets/Ink/InkLibs/InkRuntime/Tag.cs new file mode 100644 index 0000000..14f904d --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/Tag.cs @@ -0,0 +1,27 @@ +using System; + +namespace Ink.Runtime +{ + // New version of tags is dynamic - it constructs the tags + // at runtime based on BeginTag and EndTag control commands. + // Plain text that's in the output stream is turned into tags + // when you do story.currentTags. + // The only place this is used is when flattening tags down + // to string in advance, during dynamic string generation if + // there's a tag embedded in it. See how ControlCommand.EndString + // is implemented in Story.cs for more details + comment + public class Tag : Runtime.Object { + public string text { get; private set; } + + public Tag (string tagText) + { + this.text = tagText; + } + + public override string ToString () + { + return "# " + text; + } + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/Value.cs b/Assets/Ink/InkLibs/InkRuntime/Value.cs new file mode 100644 index 0000000..f870dff --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/Value.cs @@ -0,0 +1,405 @@ +using System.ComponentModel; +using System.Collections.Generic; + +namespace Ink.Runtime +{ + // Order is significant for type coersion. + // If types aren't directly compatible for an operation, + // they're coerced to the same type, downward. + // Higher value types "infect" an operation. + // (This may not be the most sensible thing to do, but it's worked so far!) + public enum ValueType + { + // Bool is new addition, keep enum values the same, with Int==0, Float==1 etc, + // but for coersion rules, we want to keep bool with a lower value than Int + // so that it converts in the right direction + Bool = -1, + // Used in coersion + Int, + Float, + List, + String, + + // Not used for coersion described above + DivertTarget, + VariablePointer + } + + public abstract class Value : Runtime.Object + { + public abstract ValueType valueType { get; } + public abstract bool isTruthy { get; } + + public abstract Value Cast(ValueType newType); + + public abstract object valueObject { get; } + + public static Value Create(object val) + { + // Implicitly lose precision from any doubles we get passed in + if (val is double) { + double doub = (double)val; + val = (float)doub; + } + + if( val is bool ) { + return new BoolValue((bool)val); + } else if (val is int) { + return new IntValue ((int)val); + } else if (val is long) { + return new IntValue ((int)(long)val); + } else if (val is float) { + return new FloatValue ((float)val); + } else if (val is double) { + return new FloatValue ((float)(double)val); + } else if (val is string) { + return new StringValue ((string)val); + } else if (val is Path) { + return new DivertTargetValue ((Path)val); + } else if (val is InkList) { + return new ListValue ((InkList)val); + } + + return null; + } + + public override Object Copy() + { + return Create (valueObject); + } + + protected StoryException BadCastException (ValueType targetType) + { + return new StoryException ("Can't cast "+this.valueObject+" from " + this.valueType+" to "+targetType); + } + } + + public abstract class Value : Value + { + public T value { get; set; } + + public override object valueObject { + get { + return (object)value; + } + } + + public Value (T val) + { + value = val; + } + + public override string ToString () + { + return value.ToString(); + } + } + + public class BoolValue : Value + { + public override ValueType valueType { get { return ValueType.Bool; } } + public override bool isTruthy { get { return value; } } + + public BoolValue(bool boolVal) : base(boolVal) + { + } + + public BoolValue() : this(false) {} + + public override Value Cast(ValueType newType) + { + if (newType == valueType) { + return this; + } + + if (newType == ValueType.Int) { + return new IntValue (this.value ? 1 : 0); + } + + if (newType == ValueType.Float) { + return new FloatValue (this.value ? 1.0f : 0.0f); + } + + if (newType == ValueType.String) { + return new StringValue(this.value ? "true" : "false"); + } + + throw BadCastException (newType); + } + + public override string ToString () + { + // Instead of C# "True" / "False" + return value ? "true" : "false"; + } + } + + public class IntValue : Value + { + public override ValueType valueType { get { return ValueType.Int; } } + public override bool isTruthy { get { return value != 0; } } + + public IntValue(int intVal) : base(intVal) + { + } + + public IntValue() : this(0) {} + + public override Value Cast(ValueType newType) + { + if (newType == valueType) { + return this; + } + + if (newType == ValueType.Bool) { + return new BoolValue (this.value == 0 ? false : true); + } + + if (newType == ValueType.Float) { + return new FloatValue ((float)this.value); + } + + if (newType == ValueType.String) { + return new StringValue("" + this.value); + } + + throw BadCastException (newType); + } + } + + public class FloatValue : Value + { + public override ValueType valueType { get { return ValueType.Float; } } + public override bool isTruthy { get { return value != 0.0f; } } + + public FloatValue(float val) : base(val) + { + } + + public FloatValue() : this(0.0f) {} + + public override Value Cast(ValueType newType) + { + if (newType == valueType) { + return this; + } + + if (newType == ValueType.Bool) { + return new BoolValue (this.value == 0.0f ? false : true); + } + + if (newType == ValueType.Int) { + return new IntValue ((int)this.value); + } + + if (newType == ValueType.String) { + return new StringValue("" + this.value.ToString(System.Globalization.CultureInfo.InvariantCulture)); + } + + throw BadCastException (newType); + } + } + + public class StringValue : Value + { + public override ValueType valueType { get { return ValueType.String; } } + public override bool isTruthy { get { return value.Length > 0; } } + + public bool isNewline { get; private set; } + public bool isInlineWhitespace { get; private set; } + public bool isNonWhitespace { + get { + return !isNewline && !isInlineWhitespace; + } + } + + public StringValue(string str) : base(str) + { + // Classify whitespace status + isNewline = value == "\n"; + isInlineWhitespace = true; + foreach (var c in value) { + if (c != ' ' && c != '\t') { + isInlineWhitespace = false; + break; + } + } + } + + public StringValue() : this("") {} + + public override Value Cast(ValueType newType) + { + if (newType == valueType) { + return this; + } + + if (newType == ValueType.Int) { + + int parsedInt; + if (int.TryParse (value, out parsedInt)) { + return new IntValue (parsedInt); + } else { + return null; + } + } + + if (newType == ValueType.Float) { + float parsedFloat; + if (float.TryParse (value, System.Globalization.NumberStyles.Float ,System.Globalization.CultureInfo.InvariantCulture, out parsedFloat)) { + return new FloatValue (parsedFloat); + } else { + return null; + } + } + + throw BadCastException (newType); + } + } + + public class DivertTargetValue : Value + { + public Path targetPath { get { return this.value; } set { this.value = value; } } + public override ValueType valueType { get { return ValueType.DivertTarget; } } + public override bool isTruthy { get { throw new System.Exception("Shouldn't be checking the truthiness of a divert target"); } } + + public DivertTargetValue(Path targetPath) : base(targetPath) + { + } + + public DivertTargetValue() : base(null) + {} + + public override Value Cast(ValueType newType) + { + if (newType == valueType) + return this; + + throw BadCastException (newType); + } + + public override string ToString () + { + return "DivertTargetValue(" + targetPath + ")"; + } + } + + // TODO: Think: Erm, I get that this contains a string, but should + // we really derive from Value? That seems a bit misleading to me. + public class VariablePointerValue : Value + { + public string variableName { get { return this.value; } set { this.value = value; } } + public override ValueType valueType { get { return ValueType.VariablePointer; } } + public override bool isTruthy { get { throw new System.Exception("Shouldn't be checking the truthiness of a variable pointer"); } } + + // Where the variable is located + // -1 = default, unknown, yet to be determined + // 0 = in global scope + // 1+ = callstack element index + 1 (so that the first doesn't conflict with special global scope) + public int contextIndex { get; set; } + + public VariablePointerValue(string variableName, int contextIndex = -1) : base(variableName) + { + this.contextIndex = contextIndex; + } + + public VariablePointerValue() : this(null) + { + } + + public override Value Cast(ValueType newType) + { + if (newType == valueType) + return this; + + throw BadCastException (newType); + } + + public override string ToString () + { + return "VariablePointerValue(" + variableName + ")"; + } + + public override Object Copy() + { + return new VariablePointerValue (variableName, contextIndex); + } + } + + public class ListValue : Value + { + public override ValueType valueType { + get { + return ValueType.List; + } + } + + // Truthy if it is non-empty + public override bool isTruthy { + get { + return value.Count > 0; + } + } + + public override Value Cast (ValueType newType) + { + if (newType == ValueType.Int) { + var max = value.maxItem; + if( max.Key.isNull ) + return new IntValue (0); + else + return new IntValue (max.Value); + } + + else if (newType == ValueType.Float) { + var max = value.maxItem; + if (max.Key.isNull) + return new FloatValue (0.0f); + else + return new FloatValue ((float)max.Value); + } + + else if (newType == ValueType.String) { + var max = value.maxItem; + if (max.Key.isNull) + return new StringValue (""); + else { + return new StringValue (max.Key.ToString()); + } + } + + if (newType == valueType) + return this; + + throw BadCastException (newType); + } + + public ListValue () : base(null) { + value = new InkList (); + } + + public ListValue (InkList list) : base (null) + { + value = new InkList (list); + } + + public ListValue (InkListItem singleItem, int singleValue) : base (null) + { + value = new InkList { + {singleItem, singleValue} + }; + } + + public static void RetainListOriginsForAssignment (Runtime.Object oldValue, Runtime.Object newValue) + { + var oldList = oldValue as ListValue; + var newList = newValue as ListValue; + + // When assigning the emtpy list, try to retain any initial origin names + if (oldList && newList && newList.value.Count == 0) + newList.value.SetInitialOriginNames (oldList.value.originNames); + } + } + +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/VariableAssignment.cs b/Assets/Ink/InkLibs/InkRuntime/VariableAssignment.cs new file mode 100644 index 0000000..1c3a433 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/VariableAssignment.cs @@ -0,0 +1,27 @@ +using System.ComponentModel; + +namespace Ink.Runtime +{ + // The value to be assigned is popped off the evaluation stack, so no need to keep it here + public class VariableAssignment : Runtime.Object + { + public string variableName { get; protected set; } + public bool isNewDeclaration { get; protected set; } + public bool isGlobal { get; set; } + + public VariableAssignment (string variableName, bool isNewDeclaration) + { + this.variableName = variableName; + this.isNewDeclaration = isNewDeclaration; + } + + // Require default constructor for serialisation + public VariableAssignment() : this(null, false) {} + + public override string ToString () + { + return "VarAssign to " + variableName; + } + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/VariableReference.cs b/Assets/Ink/InkLibs/InkRuntime/VariableReference.cs new file mode 100644 index 0000000..7403312 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/VariableReference.cs @@ -0,0 +1,51 @@ +namespace Ink.Runtime +{ + public class VariableReference : Runtime.Object + { + // Normal named variable + public string name { get; set; } + + // Variable reference is actually a path for a visit (read) count + public Path pathForCount { get; set; } + + public Container containerForCount { + get { + return this.ResolvePath (pathForCount).container; + } + } + + public string pathStringForCount { + get { + if( pathForCount == null ) + return null; + + return CompactPathString(pathForCount); + } + set { + if (value == null) + pathForCount = null; + else + pathForCount = new Path (value); + } + } + + public VariableReference (string name) + { + this.name = name; + } + + // Require default constructor for serialisation + public VariableReference() {} + + public override string ToString () + { + if (name != null) { + return string.Format ("var({0})", name); + } else { + var pathStr = pathStringForCount; + return string.Format("read_count({0})", pathStr); + } + } + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/VariablesState.cs b/Assets/Ink/InkLibs/InkRuntime/VariablesState.cs new file mode 100644 index 0000000..7ddab78 --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/VariablesState.cs @@ -0,0 +1,417 @@ +using System; +using System.Collections.Generic; + +namespace Ink.Runtime +{ + /// + /// Encompasses all the global variables in an ink Story, and + /// allows binding of a VariableChanged event so that that game + /// code can be notified whenever the global variables change. + /// + public class VariablesState : IEnumerable + { + public delegate void VariableChanged(string variableName, Runtime.Object newValue); + public event VariableChanged variableChangedEvent; + + public StatePatch patch; + + public bool batchObservingVariableChanges + { + get { + return _batchObservingVariableChanges; + } + set { + _batchObservingVariableChanges = value; + if (value) { + _changedVariablesForBatchObs = new HashSet (); + } + + // Finished observing variables in a batch - now send + // notifications for changed variables all in one go. + else { + if (_changedVariablesForBatchObs != null) { + foreach (var variableName in _changedVariablesForBatchObs) { + var currentValue = _globalVariables [variableName]; + variableChangedEvent (variableName, currentValue); + } + } + + _changedVariablesForBatchObs = null; + } + } + } + bool _batchObservingVariableChanges; + + // Allow StoryState to change the current callstack, e.g. for + // temporary function evaluation. + public CallStack callStack { + get { + return _callStack; + } + set { + _callStack = value; + } + } + + /// + /// Get or set the value of a named global ink variable. + /// The types available are the standard ink types. Certain + /// types will be implicitly casted when setting. + /// For example, doubles to floats, longs to ints, and bools + /// to ints. + /// + public object this[string variableName] + { + get { + Runtime.Object varContents; + + if (patch != null && patch.TryGetGlobal(variableName, out varContents)) + return (varContents as Runtime.Value).valueObject; + + // Search main dictionary first. + // If it's not found, it might be because the story content has changed, + // and the original default value hasn't be instantiated. + // Should really warn somehow, but it's difficult to see how...! + if ( _globalVariables.TryGetValue (variableName, out varContents) || + _defaultGlobalVariables.TryGetValue(variableName, out varContents) ) + return (varContents as Runtime.Value).valueObject; + else { + return null; + } + } + set { + if (!_defaultGlobalVariables.ContainsKey (variableName)) + throw new StoryException ("Cannot assign to a variable ("+variableName+") that hasn't been declared in the story"); + + var val = Runtime.Value.Create(value); + if (val == null) { + if (value == null) { + throw new Exception ("Cannot pass null to VariableState"); + } else { + throw new Exception ("Invalid value passed to VariableState: "+value.ToString()); + } + } + + SetGlobal (variableName, val); + } + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + /// Enumerator to allow iteration over all global variables by name. + /// + public IEnumerator GetEnumerator() + { + return _globalVariables.Keys.GetEnumerator(); + } + + public VariablesState (CallStack callStack, ListDefinitionsOrigin listDefsOrigin) + { + _globalVariables = new Dictionary (); + _callStack = callStack; + _listDefsOrigin = listDefsOrigin; + } + + public void ApplyPatch() + { + foreach(var namedVar in patch.globals) { + _globalVariables[namedVar.Key] = namedVar.Value; + } + + if(_changedVariablesForBatchObs != null ) { + foreach (var name in patch.changedVariables) + _changedVariablesForBatchObs.Add(name); + } + + patch = null; + } + + public void SetJsonToken(Dictionary jToken) + { + _globalVariables.Clear(); + + foreach (var varVal in _defaultGlobalVariables) { + object loadedToken; + if( jToken.TryGetValue(varVal.Key, out loadedToken) ) { + _globalVariables[varVal.Key] = Json.JTokenToRuntimeObject(loadedToken); + } else { + _globalVariables[varVal.Key] = varVal.Value; + } + } + } + + /// + /// When saving out JSON state, we can skip saving global values that + /// remain equal to the initial values that were declared in ink. + /// This makes the save file (potentially) much smaller assuming that + /// at least a portion of the globals haven't changed. However, it + /// can also take marginally longer to save in the case that the + /// majority HAVE changed, since it has to compare all globals. + /// It may also be useful to turn this off for testing worst case + /// save timing. + /// + public static bool dontSaveDefaultValues = true; + + public void WriteJson(SimpleJson.Writer writer) + { + writer.WriteObjectStart(); + foreach (var keyVal in _globalVariables) + { + var name = keyVal.Key; + var val = keyVal.Value; + + if(dontSaveDefaultValues) { + // Don't write out values that are the same as the default global values + Runtime.Object defaultVal; + if (_defaultGlobalVariables.TryGetValue(name, out defaultVal)) + { + if (RuntimeObjectsEqual(val, defaultVal)) + continue; + } + } + + + writer.WritePropertyStart(name); + Json.WriteRuntimeObject(writer, val); + writer.WritePropertyEnd(); + } + writer.WriteObjectEnd(); + } + + public bool RuntimeObjectsEqual(Runtime.Object obj1, Runtime.Object obj2) + { + if (obj1.GetType() != obj2.GetType()) return false; + + // Perform equality on int/float/bool manually to avoid boxing + var boolVal = obj1 as BoolValue; + if( boolVal != null ) { + return boolVal.value == ((BoolValue)obj2).value; + } + + var intVal = obj1 as IntValue; + if( intVal != null ) { + return intVal.value == ((IntValue)obj2).value; + } + + var floatVal = obj1 as FloatValue; + if (floatVal != null) + { + return floatVal.value == ((FloatValue)obj2).value; + } + + // Other Value type (using proper Equals: list, string, divert path) + var val1 = obj1 as Value; + var val2 = obj2 as Value; + if( val1 != null ) { + return val1.valueObject.Equals(val2.valueObject); + } + + throw new System.Exception("FastRoughDefinitelyEquals: Unsupported runtime object type: "+obj1.GetType()); + } + + public Runtime.Object GetVariableWithName(string name) + { + return GetVariableWithName (name, -1); + } + + public Runtime.Object TryGetDefaultVariableValue (string name) + { + Runtime.Object val = null; + _defaultGlobalVariables.TryGetValue (name, out val); + return val; + } + + public bool GlobalVariableExistsWithName(string name) + { + return _globalVariables.ContainsKey(name) || _defaultGlobalVariables != null && _defaultGlobalVariables.ContainsKey(name); + } + + Runtime.Object GetVariableWithName(string name, int contextIndex) + { + Runtime.Object varValue = GetRawVariableWithName (name, contextIndex); + + // Get value from pointer? + var varPointer = varValue as VariablePointerValue; + if (varPointer) { + varValue = ValueAtVariablePointer (varPointer); + } + + return varValue; + } + + Runtime.Object GetRawVariableWithName(string name, int contextIndex) + { + Runtime.Object varValue = null; + + // 0 context = global + if (contextIndex == 0 || contextIndex == -1) { + if (patch != null && patch.TryGetGlobal(name, out varValue)) + return varValue; + + if ( _globalVariables.TryGetValue (name, out varValue) ) + return varValue; + + // Getting variables can actually happen during globals set up since you can do + // VAR x = A_LIST_ITEM + // So _defaultGlobalVariables may be null. + // We need to do this check though in case a new global is added, so we need to + // revert to the default globals dictionary since an initial value hasn't yet been set. + if( _defaultGlobalVariables != null && _defaultGlobalVariables.TryGetValue(name, out varValue) ) { + return varValue; + } + + var listItemValue = _listDefsOrigin.FindSingleItemListWithName (name); + if (listItemValue) + return listItemValue; + } + + // Temporary + varValue = _callStack.GetTemporaryVariableWithName (name, contextIndex); + + return varValue; + } + + public Runtime.Object ValueAtVariablePointer(VariablePointerValue pointer) + { + return GetVariableWithName (pointer.variableName, pointer.contextIndex); + } + + public void Assign(VariableAssignment varAss, Runtime.Object value) + { + var name = varAss.variableName; + int contextIndex = -1; + + // Are we assigning to a global variable? + bool setGlobal = false; + if (varAss.isNewDeclaration) { + setGlobal = varAss.isGlobal; + } else { + setGlobal = GlobalVariableExistsWithName (name); + } + + // Constructing new variable pointer reference + if (varAss.isNewDeclaration) { + var varPointer = value as VariablePointerValue; + if (varPointer) { + var fullyResolvedVariablePointer = ResolveVariablePointer (varPointer); + value = fullyResolvedVariablePointer; + } + + } + + // Assign to existing variable pointer? + // Then assign to the variable that the pointer is pointing to by name. + else { + + // De-reference variable reference to point to + VariablePointerValue existingPointer = null; + do { + existingPointer = GetRawVariableWithName (name, contextIndex) as VariablePointerValue; + if (existingPointer) { + name = existingPointer.variableName; + contextIndex = existingPointer.contextIndex; + setGlobal = (contextIndex == 0); + } + } while(existingPointer); + } + + + if (setGlobal) { + SetGlobal (name, value); + } else { + _callStack.SetTemporaryVariable (name, value, varAss.isNewDeclaration, contextIndex); + } + } + + public void SnapshotDefaultGlobals () + { + _defaultGlobalVariables = new Dictionary (_globalVariables); + } + + void RetainListOriginsForAssignment (Runtime.Object oldValue, Runtime.Object newValue) + { + var oldList = oldValue as ListValue; + var newList = newValue as ListValue; + if (oldList && newList && newList.value.Count == 0) + newList.value.SetInitialOriginNames (oldList.value.originNames); + } + + public void SetGlobal(string variableName, Runtime.Object value) + { + Runtime.Object oldValue = null; + if( patch == null || !patch.TryGetGlobal(variableName, out oldValue) ) + _globalVariables.TryGetValue (variableName, out oldValue); + + ListValue.RetainListOriginsForAssignment (oldValue, value); + + if (patch != null) + patch.SetGlobal(variableName, value); + else + _globalVariables [variableName] = value; + + if (variableChangedEvent != null && !value.Equals (oldValue)) { + + if (batchObservingVariableChanges) { + if (patch != null) + patch.AddChangedVariable(variableName); + else if(_changedVariablesForBatchObs != null) + _changedVariablesForBatchObs.Add (variableName); + } else { + variableChangedEvent (variableName, value); + } + } + } + + // Given a variable pointer with just the name of the target known, resolve to a variable + // pointer that more specifically points to the exact instance: whether it's global, + // or the exact position of a temporary on the callstack. + VariablePointerValue ResolveVariablePointer(VariablePointerValue varPointer) + { + int contextIndex = varPointer.contextIndex; + + if( contextIndex == -1 ) + contextIndex = GetContextIndexOfVariableNamed (varPointer.variableName); + + var valueOfVariablePointedTo = GetRawVariableWithName (varPointer.variableName, contextIndex); + + // Extra layer of indirection: + // When accessing a pointer to a pointer (e.g. when calling nested or + // recursive functions that take a variable references, ensure we don't create + // a chain of indirection by just returning the final target. + var doubleRedirectionPointer = valueOfVariablePointedTo as VariablePointerValue; + if (doubleRedirectionPointer) { + return doubleRedirectionPointer; + } + + // Make copy of the variable pointer so we're not using the value direct from + // the runtime. Temporary must be local to the current scope. + else { + return new VariablePointerValue (varPointer.variableName, contextIndex); + } + } + + // 0 if named variable is global + // 1+ if named variable is a temporary in a particular call stack element + int GetContextIndexOfVariableNamed(string varName) + { + if (GlobalVariableExistsWithName(varName)) + return 0; + + return _callStack.currentElementIndex; + } + + Dictionary _globalVariables; + + Dictionary _defaultGlobalVariables; + + // Used for accessing temporary variables + CallStack _callStack; + HashSet _changedVariablesForBatchObs; + ListDefinitionsOrigin _listDefsOrigin; + } +} + diff --git a/Assets/Ink/InkLibs/InkRuntime/Void.cs b/Assets/Ink/InkLibs/InkRuntime/Void.cs new file mode 100644 index 0000000..340570d --- /dev/null +++ b/Assets/Ink/InkLibs/InkRuntime/Void.cs @@ -0,0 +1,10 @@ +namespace Ink.Runtime +{ + public class Void : Runtime.Object + { + public Void () + { + } + } +} + diff --git a/Assets/Ink/LICENCE.md b/Assets/Ink/LICENCE.md new file mode 100644 index 0000000..8145292 --- /dev/null +++ b/Assets/Ink/LICENCE.md @@ -0,0 +1,12 @@ +# License + +**ink** and this package is released under the MIT license. Although we don't require attribution, we'd love to know if you decide to use **ink** a project! Let us know on [Twitter](http://www.twitter.com/inkleStudios) or [by email](mailto:info@inklestudios.com). + +### The MIT License (MIT) +Copyright (c) 2016 inkle Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Assets/Ink/README.md b/Assets/Ink/README.md new file mode 100644 index 0000000..e11742e --- /dev/null +++ b/Assets/Ink/README.md @@ -0,0 +1,164 @@ +# ink-Unity integration + +This Unity package allows you to integrate inkle's [ink narrative scripting language](http://www.inklestudios.com/ink) with Unity and provides tools to **compile**, **play** and **debug** your stories. + +# Overview + + - **Using ink in your game**: Allows running and controlling ink files in Unity via the [C# runtime API](https://github.com/inkle/ink/blob/master/Documentation/RunningYourInk.md). + + - **ink player**: Provides a powerful [Ink Player Window](https://github.com/inkle/ink-unity-integration/blob/master/Documentation/InkPlayerWindow.md) for playing and debugging stories. + + - **Auto compilation**: Instantly creates and updates a JSON story file when a `.ink` is updated. + + - **Inspector tools**: Provides an icon for ink files, and a custom inspector that provides information about a file. + +# Getting started + +## :inbox_tray: Installation +There are 4 different ways to install this plugin: + +### :star:As a .UnityPackage:star: +This will import the source into your Assets folder. This is a good option if you intend to edit the source for your own needs. +* [Download the latest .UnityPackage](https://github.com/inkle/ink-unity-integration/releases). +* Open the downloaded file to import it into your Unity project. + +### As a UPM Package +Installing via a package allows you to easily update via Unity's Package Manager window. This is best if you don't need to edit the source. +* When installed via UPM, demo projects can be imported from Packages > Ink Unity Integration > Demos + +#### Via Package Manager +* Add the following line to PROJECT ROOT/Packages/manifest.json: +`"com.inkle.ink-unity-integration": "https://github.com/inkle/ink-unity-integration.git#upm"` +#### OpenUPM +* Navigate to [OpenUPM](https://openupm.com/packages/com.inkle.ink-unity-integration/) and follow their instructions +* The project will have installed at Packages > Ink Unity Integration. + + +### From GitHub +* You can clone/download/fork the project on [GitHub](https://github.com/inkle/ink-unity-integration). +* The easiest way to download it is to click the green Code button and select Download ZIP +* Install by moving the folder Packages/Ink to anywhere in your Unity project's Assets folder + +### Via the Asset Store + +onvinience a .UnityPackage is hosted at the [Unity Asset Store](https://assetstore.unity.com/packages/tools/integration/ink-unity-integration-60055). +**This version is updated rarely, and so is not recommended.** +This will import the source into your Assets folder. This is a good option if you intend to edit the source for your own needs. + + + +## :video_game: Demos +This project includes a demo scene, providing a simple example of how to control an ink story with C# code using Unity UI. + +(If you imported this package as a UPM, then you must first import the demos from Packages > Ink Unity Integration > Demos) + +To run a demo, double-click the scene file at the root of the demo folder to open it, and press the Play button at the top of the screen to start it. + +## :page_facing_up: C# API +The C# API provides all you need to control ink stories in code; advancing your story, making choices, diverting to knots, saving and loading, and much more. + +[It is documented in the main ink repo](https://github.com/inkle/ink/blob/master/Documentation/RunningYourInk.md#getting-started-with-the-runtime-api). + +For convenience, the package also creates an (**Help > Ink > API Documentation**) menu option. + +## :pencil2: Writing ink +For more information on writing with **ink**, see [the documentation in the main ink repo](https://github.com/inkle/ink). + +For convenience, the package also creates an (**Help > Ink > Writing Tutorial**) menu option. + + +## :question: Further Help +For assistance with writing or code, [Inkle's Discord forum](https://discord.gg/tD8Am2K) is full of lovely people who can help you out! + +To keep up to date with the latest news about ink [sign up for the mailing list](http://www.inklestudios.com/ink#signup). + + +# Features + +## Compilation + +Ink files must be compiled to JSON before they can be used in-game. +**This package compiles all edited ink files automatically.** +By default, compiled files are created next to their ink file. + +### Editor Compilation +This package provides tools to automate this process when a .ink file is edited. + +**Disabling auto-compilation**: You might want to have manual control over ink compilation. If this is the case, you can disable "Compile ink automatically" in the InkSettings file or delete the InkPostProcessor class. + +**Manual compilation**: If you have disabled auto-compilation, you can manually compile all ink files using the **Assets > Recompile Ink** menu item, individually via the inspector of an ink file, or via code using InkCompiler.CompileInk(). + +**Play mode delay**: By default, ink does not compile while in play mode. This can be disabled in the InkSettings file. + +### In-game Compilation + +The compiler is included in builds (See [WebGL best practices](#WebGLBestPractices) for information on removing it), enabling you to allow the editing of ink files as part of your game. + + +## Ink Player Window + +The Ink Player Window (**Window > Ink Player**) allows you to play stories in an editor window, and provides functionality to edit variables on the fly, test functions, profile performance, save and load states, and divert. + +To play a story, click the "play" button shown on the inspector of a compiled ink file, or drag a compiled ink story TextAsset into the window. + +**Editor Attaching**: Attaching the InkStory instance used by your game to the Ink Player window allows you to view and edit your story as it runs in game. + +See BasicInkExampleEditor.cs in the Examples folder for an example of how to: +* Show an attach/detach button on an inspector +* Automatically attach on entering play mode + +[More information on using and extending Ink Player Window](https://github.com/inkle/ink-unity-integration/blob/master/Documentation/InkPlayerWindow.md) + + +## Inspector tools + +This package replaces the icon for ink files to make them easier to spot, and adds a custom inspector for a selected ink file. + +**The Inspector**: Selecting an ink file displays its last compile time; lists any include files; and shows any errors, warnings or todos. It also shows a Play button which runs the story in the Ink Player Window. + + +# Visual Scripting Support + +## Bolt +There is currently no support for Bolt, Unity's official visual scripting tool. If you're interested in building one, we'd love to see it! + +## PlayMaker +There's [unofficial support for PlayMaker here.](https://github.com/inkle/ink-unity-integration/issues/22) + + +We'd love to see this supported more if you'd like to assist the effort! + + +# Source control tips + +When you edit ink files, the compiler will also update the corresponding compiled .json file. If no compiled file existed before, Unity will also create a meta file for it. It is recommended that you always commit both ink and json files at the same time to avoid the file being re-compiled by your team members. + +Adding or removing ink files will also make changes to the InkLibrary file, and we could recommend authors also commit this file for the same reasons. + + +# WebGL best practices + +WebGL builds should be as small as possible. The ink compiler is included in builds, but is typically only used in the editor. +If your game doesn't require compiling ink at runtime we recommend adding a .asmdef at Ink Unity Integration > InkLibs > InkCompiler that only functions in the editor. + + +# FAQ + +* Is the Linux Unity Editor supported? + + *Yes!* + +* What versions of Unity are supported? + + We support 2020 LTS and above. + Until version 1.1.1 we supported 2018 LTS, which should also work going back to at least Unity 5. + +# Support us!:heart: + +Ink is free, forever; but we'd really appreciate your support! +If you're able to give back, generous donations at our [Patreon](https://www.patreon.com/inkle) mean the world to us. + +# License + +**ink** and this package is released under the MIT license. Although we don't require attribution, we'd love to know if you decide to use **ink** a project! Let us know on [Twitter](http://www.twitter.com/inkleStudios) or [by email](mailto:info@inklestudios.com). +View the full licence [Here](https://github.com/inkle/ink-unity-integration/blob/master/LICENCE.md) diff --git a/Assets/Prefabs/DialogueManager.prefab b/Assets/Prefabs/DialogueManager.prefab new file mode 100644 index 0000000..e9890a5 --- /dev/null +++ b/Assets/Prefabs/DialogueManager.prefab @@ -0,0 +1,51 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &7654403229796820117 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2163307194011049650} + - component: {fileID: 5354627409228272216} + m_Layer: 0 + m_Name: DialogueManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2163307194011049650 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7654403229796820117} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 27.540693, y: 165.78679, z: -0.4255345} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &5354627409228272216 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7654403229796820117} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: baeacdef8c51d431cb317d350535b8b2, type: 3} + m_Name: + m_EditorClassIdentifier: + inkFile: {fileID: 4900000, guid: 040cc6b8f90434e928bccaf51969533e, type: 3} + textBox: {fileID: 0} + customButton: {fileID: 2521414687830936938, guid: 824fbfe62be7a43d38b8f1be771f845e, type: 3} + optionPanel: {fileID: 0} + stabilityScoreText: {fileID: 0} diff --git a/Assets/Prefabs/DialogueStuff.prefab b/Assets/Prefabs/DialogueStuff.prefab new file mode 100644 index 0000000..e3792d2 --- /dev/null +++ b/Assets/Prefabs/DialogueStuff.prefab @@ -0,0 +1,532 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &2344326775981503531 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1892878980278354526} + - component: {fileID: 335888878014152629} + - component: {fileID: 310674692767767407} + m_Layer: 5 + m_Name: Name Tag + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1892878980278354526 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2344326775981503531} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 7351494636387755289} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 110, y: -22.4} + m_SizeDelta: {x: 200, y: 60} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &335888878014152629 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2344326775981503531} + m_CullTransparentMesh: 0 +--- !u!114 &310674692767767407 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2344326775981503531} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 12800000, guid: 8a2b9e2a607dd2143b58c44bc32410b4, type: 3} + m_FontSize: 15 + m_FontStyle: 1 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 48 + m_Alignment: 3 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'PLAYER + +' +--- !u!1 &2794497249239431220 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 144660869696758851} + - component: {fileID: 2848264366658777705} + - component: {fileID: 4312551014405324082} + m_Layer: 5 + m_Name: stability stuff + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &144660869696758851 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2794497249239431220} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 7883933290476873554} + m_RootOrder: -1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 355, y: 154} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &2848264366658777705 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2794497249239431220} + m_CullTransparentMesh: 1 +--- !u!114 &4312551014405324082 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2794497249239431220} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.9433962, g: 0.47294688, b: 0.10234961, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'yapa yapp + +' +--- !u!1 &4377794324176431307 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7883933290476873554} + - component: {fileID: 242217265014989012} + - component: {fileID: 6753299980349986304} + - component: {fileID: 311965439917340050} + m_Layer: 5 + m_Name: DialogueStuff + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7883933290476873554 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4377794324176431307} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 7351494636387755289} + - {fileID: 8282291422581756329} + - {fileID: 144660869696758851} + m_Father: {fileID: 0} + m_RootOrder: 6 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!223 &242217265014989012 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4377794324176431307} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_VertexColorAlwaysGammaSpace: 0 + m_AdditionalShaderChannelsFlag: 25 + m_UpdateRectTransformForStandalone: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!114 &6753299980349986304 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4377794324176431307} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 + m_PresetInfoIsWorld: 0 +--- !u!114 &311965439917340050 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4377794324176431307} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!1 &5937569427954943023 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8282291422581756329} + - component: {fileID: 5160086748376883853} + - component: {fileID: 2090263245294452933} + - component: {fileID: 4922411626918625697} + m_Layer: 5 + m_Name: Choice Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &8282291422581756329 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5937569427954943023} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 7883933290476873554} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 100} + m_SizeDelta: {x: 300, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &5160086748376883853 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5937569427954943023} + m_CullTransparentMesh: 0 +--- !u!114 &2090263245294452933 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5937569427954943023} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.2830189, g: 0.18923134, b: 0.07876469, a: 0.392} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!114 &4922411626918625697 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5937569427954943023} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 4 + m_Spacing: 0 + m_ChildForceExpandWidth: 0 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 0 + m_ChildControlHeight: 0 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!1 &7885653136519091279 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6064645731754799944} + - component: {fileID: 3608404113259717674} + - component: {fileID: 6948670203615628517} + m_Layer: 5 + m_Name: Message + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6064645731754799944 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7885653136519091279} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 7351494636387755289} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: -40} + m_SizeDelta: {x: 250, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &3608404113259717674 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7885653136519091279} + m_CullTransparentMesh: 0 +--- !u!114 &6948670203615628517 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7885653136519091279} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.2206746, g: 0.8207547, b: 0.39761987, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 12800000, guid: 8a2b9e2a607dd2143b58c44bc32410b4, type: 3} + m_FontSize: 20 + m_FontStyle: 1 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 48 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Test +--- !u!1 &8141364504974403150 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7351494636387755289} + - component: {fileID: 7914433775748976784} + - component: {fileID: 4515468928176879988} + m_Layer: 5 + m_Name: Textbox + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7351494636387755289 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8141364504974403150} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1892878980278354526} + - {fileID: 6064645731754799944} + m_Father: {fileID: 7883933290476873554} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0} + m_AnchorMax: {x: 0.5, y: 0} + m_AnchoredPosition: {x: 0, y: 150} + m_SizeDelta: {x: 300, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7914433775748976784 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8141364504974403150} + m_CullTransparentMesh: 0 +--- !u!114 &4515468928176879988 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8141364504974403150} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: faa2e126ae2f51d4eb1ac576f1fa9c7c, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 diff --git a/Assets/Prefabs/dialogue button.prefab b/Assets/Prefabs/dialogue button.prefab new file mode 100644 index 0000000..fe4f207 --- /dev/null +++ b/Assets/Prefabs/dialogue button.prefab @@ -0,0 +1,204 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &2521414687830936938 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3641471828285570015} + - component: {fileID: 4579809809626504831} + - component: {fileID: 8391325085340875459} + - component: {fileID: 5890500627057891389} + m_Layer: 5 + m_Name: dialogue button + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &3641471828285570015 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2521414687830936938} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 8724492508350343416} + m_Father: {fileID: 0} + m_RootOrder: -1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 72.655, y: -34.86302} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &4579809809626504831 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2521414687830936938} + m_CullTransparentMesh: 1 +--- !u!114 &8391325085340875459 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2521414687830936938} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!114 &5890500627057891389 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2521414687830936938} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 8391325085340875459} + m_OnClick: + m_PersistentCalls: + m_Calls: [] +--- !u!1 &7040451970875863923 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8724492508350343416} + - component: {fileID: 6116209217220558052} + - component: {fileID: 3741503991585050455} + m_Layer: 5 + m_Name: Text (Legacy) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &8724492508350343416 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7040451970875863923} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 3641471828285570015} + m_RootOrder: -1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &6116209217220558052 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7040451970875863923} + m_CullTransparentMesh: 1 +--- !u!114 &3741503991585050455 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7040451970875863923} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Button diff --git a/Assets/Scenes/MainGame.unity b/Assets/Scenes/MainGame.unity index 5fb4601..41b5294 100644 --- a/Assets/Scenes/MainGame.unity +++ b/Assets/Scenes/MainGame.unity @@ -123,6 +123,79 @@ NavMeshSettings: debug: m_Flags: 0 m_NavMeshData: {fileID: 0} +--- !u!1001 &365832063 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 2163307194011049650, guid: aa60d7f00730243bead3e76930966657, type: 3} + propertyPath: m_RootOrder + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 2163307194011049650, guid: aa60d7f00730243bead3e76930966657, type: 3} + propertyPath: m_LocalPosition.x + value: 27.540693 + objectReference: {fileID: 0} + - target: {fileID: 2163307194011049650, guid: aa60d7f00730243bead3e76930966657, type: 3} + propertyPath: m_LocalPosition.y + value: 165.78679 + objectReference: {fileID: 0} + - target: {fileID: 2163307194011049650, guid: aa60d7f00730243bead3e76930966657, type: 3} + propertyPath: m_LocalPosition.z + value: -0.4255345 + objectReference: {fileID: 0} + - target: {fileID: 2163307194011049650, guid: aa60d7f00730243bead3e76930966657, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2163307194011049650, guid: aa60d7f00730243bead3e76930966657, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2163307194011049650, guid: aa60d7f00730243bead3e76930966657, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2163307194011049650, guid: aa60d7f00730243bead3e76930966657, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2163307194011049650, guid: aa60d7f00730243bead3e76930966657, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2163307194011049650, guid: aa60d7f00730243bead3e76930966657, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2163307194011049650, guid: aa60d7f00730243bead3e76930966657, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5354627409228272216, guid: aa60d7f00730243bead3e76930966657, type: 3} + propertyPath: textBox + value: + objectReference: {fileID: 1507187765} + - target: {fileID: 5354627409228272216, guid: aa60d7f00730243bead3e76930966657, type: 3} + propertyPath: optionPanel + value: + objectReference: {fileID: 1507187764} + - target: {fileID: 5354627409228272216, guid: aa60d7f00730243bead3e76930966657, type: 3} + propertyPath: stabilityScoreText + value: + objectReference: {fileID: 1507187763} + - target: {fileID: 7654403229796820117, guid: aa60d7f00730243bead3e76930966657, type: 3} + propertyPath: m_Name + value: DialogueManager + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: aa60d7f00730243bead3e76930966657, type: 3} --- !u!1 &380789506 GameObject: m_ObjectHideFlags: 0 @@ -1515,7 +1588,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} propertyPath: m_RootOrder - value: 5 + value: 6 objectReference: {fileID: 0} - target: {fileID: 7883933290476873554, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} propertyPath: m_AnchorMax.x @@ -1594,6 +1667,27 @@ PrefabInstance: m_AddedGameObjects: [] m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} +--- !u!114 &1507187763 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 4312551014405324082, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + m_PrefabInstance: {fileID: 1507187762} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &1507187764 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 5937569427954943023, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + m_PrefabInstance: {fileID: 1507187762} + m_PrefabAsset: {fileID: 0} +--- !u!1 &1507187765 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 8141364504974403150, guid: a327b4b862d8d43e8aa2ca9d79e4a1b4, type: 3} + m_PrefabInstance: {fileID: 1507187762} + m_PrefabAsset: {fileID: 0} --- !u!1 &1663833397 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/DialogueData.cs b/Assets/Scripts/DialogueData.cs new file mode 100644 index 0000000..d29d5fa --- /dev/null +++ b/Assets/Scripts/DialogueData.cs @@ -0,0 +1,18 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class DialogueData : MonoBehaviour +{ + // Start is called before the first frame update + void Start() + { + + } + + // Update is called once per frame + void Update() + { + + } +} diff --git a/Assets/Scripts/DialogueManager.cs b/Assets/Scripts/DialogueManager.cs new file mode 100644 index 0000000..5ec8631 --- /dev/null +++ b/Assets/Scripts/DialogueManager.cs @@ -0,0 +1,107 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; +using Ink.Runtime; + +public class DialogueManager : MonoBehaviour +{ + public TextAsset inkFile; + public GameObject textBox; + public GameObject customButton; + public GameObject optionPanel; + public Text stabilityScoreText; // UI Text element to display stability score + + private Story story; + private Text nametag; + private Text message; + private int stabilityScore = 10; // Initial stability score, adjust as needed + + // Start is called before the first frame update + void Start() + { + story = new Story(inkFile.text); + nametag = textBox.transform.GetChild(0).GetComponent(); + message = textBox.transform.GetChild(1).GetComponent(); + stabilityScoreText.text = "Stability: " + stabilityScore.ToString(); + } + + private void Update() + { + if (Input.GetKeyDown(KeyCode.Space)) + { + if (story.canContinue) + { + nametag.text = "Character Name"; // Replace with actual character name + AdvanceDialogue(); + + if (story.currentChoices.Count != 0) + { + StartCoroutine(ShowChoices()); + } + } + else + { + FinishDialogue(); + } + } + } + + private void FinishDialogue() + { + Debug.Log("End of Dialogue! Final Stability Score: " + stabilityScore); + // Additional logic based on final stability score + } + + void AdvanceDialogue() + { + string currentSentence = story.Continue(); + stabilityScore = (int)story.variablesState["stability"]; + stabilityScoreText.text = "Stability: " + stabilityScore.ToString(); + ParseTags(); + StopAllCoroutines(); + StartCoroutine(TypeSentence(currentSentence)); + } + + IEnumerator TypeSentence(string sentence) + { + message.text = ""; + foreach (char letter in sentence.ToCharArray()) + { + message.text += letter; + yield return null; + } + } + + IEnumerator ShowChoices() + { + Debug.Log("Choices available."); + List _choices = story.currentChoices; + optionPanel.SetActive(true); + + foreach (Choice choice in _choices) + { + GameObject tempButton = Instantiate(customButton, optionPanel.transform); + tempButton.transform.GetChild(0).GetComponent().text = choice.text; + tempButton.GetComponent

JuQRsywHyH*gLbPC^KYBjo%3+plbuui=$gwZN>>!OTMk)dF3DADT5@sk!V4c5;2g7B zN>WZ%a^$ILIR&zOcO#4Qo?MZfmZp%)$fTZ{lcq?_Pf1G7 zho!axCUtwxuHs;K2)Cu9Tp0ecm~A%zmJ7>ucvFaTzA8Kdf^)k2JBb$M`a2DCZFw@` zqT!bIz~vSqu7U?HE*frW4_s~`;wpIH;-cY}_Q2&9BCdi5E-o5wX%Ad(A>t}{;Nqg; zmiEBq79y^K2QDreZfOr(ZXx0-c;Moq;gt}{;Nqg;miEBq z79y^K2QDreZfOr(ZXx0-c;Moq;g3<5BkL&O)ZGaQEjc~MQ!tnl@PVSb%B#ROlES4Bx2kP-fBkrY)S z8d;DPnXoD3V{&RkjF`#QSqyfMBsEs8&Z0FClOXpd+KRH_CG1J%e%J&r1_D=!gE=KG zC#QAIAa9Q~6()8cTySlCRh0IU|6h z%XF@)USkJ>MF~|F<|@D&av-}>EtRT`)|zZ%Gxm^Ng^b}5Uasy@ySdex+GwA^eIaU3R5Y-KT+8!5I`dqYEdR?X99hQ(<B+bWfgU5aYtvoD@k>o#Jx!f0c$%N_YwR(0DCh; zJfeG(aEnk}Z7oQ25Q+$gvU8R#Sm@-)K|-Ms5IS^lX()typq)c(-hnv6J)HHrb;!Sj z#jUw){NIrgEU;|+Tp8xq28#~jx!Le82I zbiz?SE+~C{pSy)k;kZEq@iQ(^b<=mSS^Jby=xnko9t~TPS=+n;>3~Fh zwy=pjiG#px~tZ~{@Dm6};EeoWCjO}MuN#ySg^g1ixMXm@4C3Q>@UTA~@Zfoj| zC71@^sU3!zf#pEM=s|t1CEcCS-_==*2HW+osLTpH(}dyCPOZ!<0UEI6g<0zd=h$hv zk^zd?=MB_aimUB(4P&gd+vhbHbOUkwz;<4!ql+E%655*avLq$MJOv%qKdGwG#W>1Nb*;nF3r!(BXH`lT{P8 z&yQ6pNnRa*&bHK57qMyi!)Ws`><{rlP3PqU4L>6r4>M^Usb^4!~^-{O8{?St>9-;2V7XrxYnr9+JX3T#9O7 zWj+RJ4_(=M1!AnEfUI0Juy%>Da~vs#5{UuADl{Jb3Tqo0RyvM!x%L%L1MnX>xop}P zSpVboPy^bL)nsm>p%~CZFTzQ!qS1CLl3VRrJOR_ z`Tl+Ulk8s9IBQ1XM5477mqd%ypjFaZlm7z$eg1y_ZvFxO4*pgo)qv`u3|fay{QCII@%J4uXIYiN!5-i`fWBaX84%hZQW#C+$ebX}ff1RO z78_KtmYPJjEvh<*cUF|*j)&vO@}c953N$Hg^)55p${)06mrYOi~Iw+ z=Bo&Od{|{=8dyC6eh6Xp8vs3{BkBsXM=vOo93`WEC>!OY0jL~S?!(cOfO;L$gV&8{ z0-B7bp&95^GzTq2Z=w}w4SEM{LR--ev>SbfzC?%7ar8a3jq~UibPe4?_b7@IQ+`wk z)sgB(MNxezIh9IfQTbFURY?t}MpGKfKv}5?)U(tKY8JJST1Ks<-lIOGc2ftaBhye_<+yf|JeFNasctL8ny)9}Xf#`C7~Ugpi`E$6+>+rrz;`;vE@ z*UbBccax9!zWgwLcYX{%m9OBJ^GEP&`3(OV{&fCa{&M~X{&uMAWBg|R75<+Bksw4M z6~sXMED{VBs03pL&j@A;77Eq~wg~nKjtR~Pt_dCr{ePyaS2r)YSAo|EFN4<UGiUo_C;kly|y!xwqPT zocAlT}xXy05Qqgm0SfAYZNTB;WbI z@A`i3d&c)qNwB1kL?Ia|u}WT+td{JOd@H%`=jYecFWYZ~pT+NGzqNjQ{eJYj;~(N5 z>tF1z_Mhm#$bXCfQU9v}-T_eoIRQ@wj1QO_@P5G80apUO1A7K40+oT!1TG5vFz{sH z&7hDVSx|Y9K4@mpx}XC=mx9H?J%jUu)xlGPR|M}3J{Q6di40MMs6w6%SsC(a$oWuF zXmn_C=$OzMq3?tq3cc1YxLsnqA?=#lEo%31yXG){SkJKHFkRRyVVlBEgxzi5rF~9& zy8VmoH?%+6{&t7X9kM&n9j15K*x`7GyB(z+^E=jee68cwjz4q~bn4S-P^ZRDOFDhp z=}PC&&iy*8I#2Jssq=T?yzoBZmEli?uLwUFezQy0E`?o8T^4lN+vQ5vu&&u%$8??D z^^>lbyM=Vi>Za{ByW7rgKTF$5bEG=yeCa;vweI2Fi@IC8FYA7&`@M+hh`|w4A~r_+ z5a|<{8d)1TJ91CtwI1Dil=Ya(#&4*j~$febZaiJGFOx?>BlM?!)Vo)Tge`qCQ{u<@HVOtL^(n-y@F+ zA4_}8@YwRlPR2-La$*`{*2kQQ4T~*}of5k>_G(;@xDj!$#qE!K7@rici(eW4y)0NZ zKsH6TUG|5(k6a~RB>yJCFQFh|V#2nB-xK>L(uqqFPbGyUl_fo&v?u97a!N9jydn8= zN{^J$DT`B1riP|gq|QwJJWZIEn>I0RN7|q1$?2B#P3gb&i|JS2Z(YAj8POSZ#>$Ly znGu=F%w?I)S<#^k)6b2T?Um&x6nds~sN zcv`V5kDphVH$CrAesKQa{Dt{H7DN7U5Zu3Ym2W9 zNEz_-fPE#BlB$x0C1*?flrp8;%Xno2%3d!!JuqsZVc^zsR9;;Edif6((G_DWJ{lw% zR557LpbM3<$_bVGt3s+qRjsSKRh?V?O7-`HdkwY@-ZLa%$jBjUhuj{TH+0s}=3#Ne zo*wq)@J_?E!?%qPj~Fsy)rgyq=RZE@@$(~-Mot@f;)&=dnw~iDWTz)}PkuZqV3cyy z`=f=UhmKx1`o6MUxmt8pw?uu5SU8wziOwpJ($K0+juU}nn(+$;a)O+bi>pwIE8|n@Fj9raQ#v`V_rfH_; zvFT&yjJ?K`Fssaz`3dtjODHUL4qAIzpR=B6$ZA;BaHnxd@g(O7N8GsXY_APnbO6%+onfFMEc1rskPF6C)>1op^py;iNT_eJ0mW{%T76lvz`5 zJUjH+?Nhr3=pKR^ES`Cm-G+`BUE*Pve)U+s1E zgWs}$J9ur_we!C-zuW$pdA;NH)i)Av?73NS^T%8ITla2Hzti!~nm<$j+<$lI-HZ1c z?~Cuxf6)8E_J<`8Puui18|>F9$y$I9ArJPs&>yQ|;{kRgLk`2njX(STMKmb(oe^lt zeq(kknteyZ0$4+!)!7IQo`g{8E`*lA9R;)mo_P6PosD=23CK)fJ|A4J)HfPzxCeN=z&QV5GLxWHk2@e#!n2t{Hq zZy#T%(3V2j^W{5)frt`Ne4cO zu5x!xLLxKeh(a7StLoaB-&N+Mu;rVc?V0y_wK{*#3QKbPql3@Vf4o0+?=kDS>jlxX zS3dW_oPFQ?bmOhfpB_Jdb4YE&w7ILce0Ji(t(3x{n#Sknt=_u-nxR4=;@57NrW)~ghB7)nlP+}mb7uOSE)RKP^a7Sb452%Er9oR$|4 zZ3EFv=WjbW3H~j{2MGu-7c<~39+$F!*eJlZ4e-TT8#GFQFas;V)rmwh71KCh>Yhy^$N&nN2X4y5u^Q4%=^mo4HP}23`@|6t=0dn#o=O#1r9mwHq(| z8EE|BVXO(aH+V@i)mlA`e)}2F zl>;@w>X_KRleOxw$%DcpC&xtwM70j=R`b=A&M66+1hrlzPf3VR)OAkj+FBKrG)~6}vNoP~byTE69j{JMC+cZe3CXnrSGQFXyRidRn*mr z35ijr4%A3J@~Xl@`cF%Zz8yHwEO?d1laQdO%II|ZUK3!CCi||kq%M4tMy(j4)+Hrt zBh|eoKo1rpH<{wVft^DVb$V4|q&lQ$H;CgN8ynTRcQ3!*9v*()NzNdpOsY4rjUu-GPqXcz^iukI`S=BUd32Z9mMi)c z+ripcOhKynax^6M^RTai#Z%Svjn!d*PLixq9P!*H!_;q8gi6L5AIoi2qtfcsr1`F` zCDoT7{~{+U!+Wr^Dw6E3TO`d0>Zn&06`&TeDi@2bqSO9TyCUy$MW4-oVvIWR&*l@6 z6{mVO6J64H{X~^k-8~w1@YfTa$g^Uh%FM<2B0l!NpbK=W3IApXbpI>!{x>_oud|m@ zn$Z7$b%4ckBV$yF(dwvf3dv|C!2hZ~`^%Z`Z}eFe%jf_4?h*%H#mP^auPaTK|Ja&t zUV^J$=gjD*oh&n|b8u38l6GKHl)9VOtBR_?7HfUgf({7|4%H@&kBwJ%>lv%l#H%Ki zFI)~=W$AErihh7lU@z_Er%zKEZbY^bJKbff9(tnb-nU}Q^ zvnr~Su&S#%S~AmE)n!&ibrM!}RYyx^8mqd@s;ExFs;=s2$xLHamsu6nNm$iY9W9w@ ztm-nWqB;qyx~iikGmTYUW>r)tVO3Xkv}C5Ss>`g3>Lje{s*aY-G*)$)RZ*RURbAE5 zl9|S;F0(4Cld!6*I$AQ*Sk+}#MRgKZbyY`8W*V!y%&MqP!m6(7Xvs`tRhL;6)k#>@ zRUIvvX{_optD-sytGcSAB{PjxU1n8OCt+1rb+lxrv8v0gis~e+>Z*>G%rsVYnN?Ap zgjHSD(UO_QsxGrCs*|v)t2$aT(^%DIRz-CZR&`ZJOJ*9Yy3DGmPQt3L>S)PKV^x<~ z71c@nsk&-fp2}4x;!)g*c;;4oqPH`DqW2QMUGWj08m^_$;(^k^$$Cw)9zc5{3DxPt z#^DiEP7#u*SF00~69_?Rx(3H!-9)$NA5e|@8nOFc1 zP$Z2HQ|ps8gU7uY38XU%Wm=Ymf8&{)g)ueLvt*_rR;;GROpP38(<5G=Xp+czTyku@ zJ~olF1m1~L2M-+CUuUzQfvE7#(|{5f77@GlT$utuLKH3E$sr!{AWMC%5c zGr`)#U`r-ZZ^;Z87q2s821V;9m@~Z+;(MAi(4&QQkI1-alOjYdu_1kW1VbAB2=|aE zxjZTSY*5i57kBn zjU*2I&oxq;q#2IK4MWL7V-uq#^|=sY2xRJ!q}L}U#3v<2n~FF~7!sizytV`%5*r;; z9#Km|KsGZyJ>hP9LzIE_#Z`uf;!Rin^!rO3=VGc9m%voA8C!PFWY_kDsus$zSgF{SnhfNTe;bZD2>PyBfJ<*i1wxk8I{gmabOru)NaA>(N zGqMt`nWP+n8D0jxAiSP%1P5-S~I z9xOcXpu^MfYTdB-0W{oY73#6)IDqTnHsFB=IM`4+Nr;x?@?YJ4Tf9D?!g9uyUlB4;7hQ45 zb5OSmt$B6C#`l%LXt`sQ zdb}!`Px4L^)LMNNY1E_>_rL^e}c6|RBAC&A!C*ma`s(Gy&g|~me_CrBG zE=m`ffb{nmT}>l3S}d{l`GB{XsMk>X9?}i85D=D0^GJheG2M*Pyf%(T5lTBY!{{K*&k`>(xy>z+|cf(w5Ljo6z6X< zC{`a5Zc2~SCJiz1x0#R_KZxvu_0EY}V6UN8(4nf)#>F+1Ugbzm= za@y>k5IbxT(pdX#@^x`xBm?m|J2@tp;G9OAJcML+1N`22ZEtELXlxrNa4(7Y+qy@p zcwLQ=4${Yj_Z7?9j!^4HkUU(5D0R#3d>uIv)0=xL(ePC|nIKY$;T)5Q?=Uu*-GDEnhG!#{>tXV6CIDV)hKgl7!QUtU zX96z~$1WqCVAs^Hn_U;X0r(EW$J5T=ElIF zg1fxz;$xCxoVjO$&6=pp#e#`tQK0HynbP(H+YPpRZFkz{+5Tv|naOQ;*lw}iZ<|AD zlgz!jcB0L-4S`-0SsdCBE72%dDX%G?NI7#`Re+EL)CU*~daQu3KNg&%nZ(xwd3Vgn zYI#Uvq&t7BlP_a5zY`5(cN>Y$RHI)ku(xs<3z&&HgQiwFQ8A`!!`Rl#aNzD+U~TST zXr?oklOLI^ogmWL(ZwDhV0<|*@+b(8gy4Ui3yjg&>mqGgG)WZA!D@5*M$=E**nEtRd1t&?q)?Ud!o z4#`f+&daXJ?#N1PY;Bxv8rU?qdC5j$<8Ra5roTu(!uJJ@!V?RZWRJiS{$>Gwi>y-)R3c#?B@C`wk8cjU3uJ_+f00ba>NYio~gb?Q=PVTy4QKV z&g427bvD#FSm(N{lj}>a!LBOTX|9W0x4Is8HP)?P*Q4&>x(Rh>*IijRukO`)j`d!u z*Q;Jsz4z*6)!S9?Vtw2CZR!WtkF5W0{jci(T>nx7hX(B$gfw`w!K?RP0lp6Yx;82*P2dj`eoCfn_hph!HZp9jC^tCi|b!J z)y$^Z%gu%~o6;<++5Tq6<}I4{X|8GhS@T`ZueWH_BB;fiE#|k_-r`!z`YpS)jBPo; z<&Ktx@`m#6@_6||`EGe}t7fhGwn}cbwAF!Dk6X8EJ+$>Zt=G0b)23z{|2E^>%y08k zn_{A?Sq%vy)^u#w3jx&bhTaMb|LL1w_DZj_x82h z2eyB!{j&B)J2-Uk?-1AFiw^lO+q~@aa?Hz%UOw2-rlW7i*p6RxJoJkFD*>-0zOw9< ztM?9+2*&jY>c^%~mi^Im6rx9%O?dsXk^K0bY>^vUgO-?x9?kNX}EX&w?8vLd9o zpI^VJ{dV_v?jP3w^ZpkGygWcVVB0{Of&B)4GVu37Z3iU|+B}#I4jKH(;4`7^Lf;Dg z;WdZXLSI|-+T|f0L;f{nZ&>}XH^Nqi-4E{(J~#aI(Dp-b#+PV?%^}#PEof5l>WuRm)VyaUtUtk1LK0j$9B~6crRTKkAygt9qXL%J{D1=Z(J_ z-8K4?=xZ^7F&Qz}V}oNqkG=h7-#3@M`5Bj*W3R(KehYRrPE~7#!dTadYkF*O}~`dC-vL6 zYrY-#_HXYf-pXAJ}~m`@w+^y*~Wx z!?KxCGk=+-oRu-_$?VA4zkKBJ(ZY{}IpgOXnCmKm(QO$|K6u>e43Zxov~y=%>~H|3=0P=-13>*XX&3k`8?+Hf<-+RtzFz~@rR2a zd=d4<;V*-}T(hM4l37biGGjAOEbX&&)3TSAWn?*IO~|_Z)v&Mje(nGDif@{JGwYku z<%!D;-wye9_X@uiD^@mJId_%Ks^nGIz8mvh{_38qx2);3X6f2SYiDJ%?BwjibrI{1 zt?$47rw#ra)_mXg`^6jUZ=AVFwrSF);>|Ie4O>QTIkdIk)}OX@*|zZq_aB!3*y_hc zISq5>Zm+rhz3sw|$vcd>n%wI5ZRG?;5e|=lbJ+SGZ-@z^U0r}ewy?SW-;lRT?kMumU z=V-{$Uke5m96C1i*oos~jvG!yow#~3{^adb6HYxoo%*}|?=#Q1p2;}d?Ci309nP&a z_!@G~_dLJ}T4wqXxKdi&qY(l=1X~`&*w9qQ2IMmKB|dGDcE*+5@9-dIKkHF+oqcX7ARaT{Z$T0waHg&>rE1;70yW4UjM`#z#}aAho$?~wBj%ueOy%YE^E zH9UX(k;Bt~=dnw{p7AEWs0EqgM`mEMSCFi87&{A@a6-7jocSv#-v}Ov{7vS_X3ab0KrXS#@)%HOiuwQALN zsqO0G;@ZH)#iap#xik=q)U6H!A(z#yfd*vS%33pe)epw_4Y?_k8=~1|-4GA%}{++{T^PzB4a4 ztYM_i`*vFg62S2#pPvpxh^!Z)dJXl}t1p;Ec(w%XEFuV}n6oXfvn~r{#*PUqXD&%T zm@qW_@Z(n|)s7o=XzQ&hXKutbEw~goI&g2p%X`O79T}re$T!v+?f#Zy*^$?x*Uc__ zJ-DU7>JNG2;;bU|jQgb{c278U;>D!U*4=e;ueIM3xG&N-DzN09z?Qu}X5ONcXC|&r zt~c%6l8@&(wM*EP^IQG38|O^eBQW)AA#U@(nitZxgWJ52ej#r2hRiDu7@j@(*63@y zn>BkfJHq+K%Htcq@p<5}=7hj*yxhTU`O#@B1U9GR&mZkB*`Hr>CbO`iZ?nULOIIx0 z5qa{-j}yGgUMeUo7(LYJS@`r>7}?&wlhd&$=!gZlN)D%n-0 zC|h6p`p=IO6JFWi>U#WK@aB#0?~UvFn)A9vUzF94{<^Hr^l!KBE~kw_Gu`vHE_`U* zc6zl&ot*tbz=5}BZ2Tzcux>%Lz&>(3-f~@O*7(3x_3sZ3pS+{s%;xJm9(&IFvTfTg zS9dghaPf~}g=<#)oH49;)a5NPm$$AddD*E06x?q}PX30ugNjBpF{FE}e|cm6xKYP9 z9!y-a{otF+=JlH{9J*ufjyHNtpEc+6178^ZmMgt|_h(F9d0b|{=VIZpD`j^V^~oA; z?D$64jbHEf$y`vM)edPpHTX#O>9>#E){Iau{Qh|V!5^$%{oVAVUw!qN|Gi6*qi3Zb zQopdS;MA^N3vaKx5qK#<_=-a_N1j)e`cfB#|N*WWbRdhYWx4{v_`oxna^*S6aPSj*S2oDTQa-tLrN zIxTC#@lH`2>V7$+%LhvipIp6m^|{YWzAbHO^jwhbKBcfuaA}%xbghQhPktOX?a=(z z%?n50IvsuI+S(&~1@_&V_uF<;ly#mQ_f}cHAk!ot(b+bzAqVjYk>=F5KE}@k7tcU5*NDXZxiohx-kIdgnu;<-%dJ5(ljYVY^%xqJ3oUn^bPXWXNcQwM(BYozzcxw?r3y5?g) z>U!$@x*G!XUb|rZ?eBK~@t}d-@80-PepwweH7RlFZ<^ot`jz|^GI;*p8`2t(BcJbk`my4!u^4)go^#|$4yx$CYscHW91tmWmZgQw|ix>JwwOoJn zSk7+?lhe*k{bLu&ycjbHpK_)PN2P9#8*|0s`+655WGmdh zT7Grz?J4hRrhTJdIVNiRlGp#WR=56iSzO}SdJZlfmBs6di#+$g`B~WDPnvd2D($!2 zxX9Zub!_3tw@WF7O`aQdG1PN%Jz4@W#0ajxX+ z8|N;p{qD;Z#@;i(b31cn@mnq3-aN*hXdQ3*&g!_lZ2gZ7Cp$j;tjMu`QSCFGZq6+E zwCB2YUI{O*iT>ek;PA&o`b}N&uPer)Wph3>F7HzNqmy&4lswF>k+eMN+K4^VU;5%e zR@wL4XTP3Q=GX1JlSgk}eY9}tvd8ORJo4oQ=bx`k@LD|GcV)bB$BldQf5$3$rvCMo z!_FOzj~`p`%Gm(NL#vX*ZH@@c>He(13pd8ya#gPDuya>dt!9l5eKfkmxAomTH_be` z);KDyVB1Gs72l|nI~rHjTYl>DKKs+X&ySusZR(u+9&NjMmHCyNyHV%6T{fEsHg{ha z-nY%M^_}+VCJ3zEp``*Vp8rbH?dePI*I6_6<+9*g4eI93+O;nFakovz4;OqoVf@gO zlU&YC>osT7@wXI{e7l~z63~0mcgrrn(SKH_6+4Yvw9SreT_do7wt-=5y9unhzm33F zEj+n&!}u0`?T`FCVdHPpA06A!d}7LHK9?>W`E=OEs9~o^mJUz7FR(+}JtdFcejHpl zedykKwca|TiySi0PQ7u*>Esvdh233do+ArHlZYz~-5s!F)Z}6QiN)8qEe3;Da~ho% z*xMdOttKqFFw6OmQr$PV9;fv>zGTs~Uj_Ca#=*pA3!o5F8noywWh@>tx*wMJb{cWzSu z#2T+BVaZEQ1rF`_^ORX@udSWX<*U3C)BDf4Rp`69#93e;j9u1m$lbNK4<0M~_0U@- zT@y>&g>IO-E4bw4{%>sDb3KRft-KmTs0 z`hWhw(eIk?{Yo?@aUsWx~@%8(?a1*??;gMYjUp^dmvuIb~UYD4>5<{WGl5u-h zesX)l^|d97KP_w`u#2?{r!{KwYuA3?rH+1OdGnus9TTY=d3E!n&0We`9$H)4x_DYn z!Ofznk&2bSpPBn>_K%*?ann8;nm8lr-paU+=Qg(Wt_T0|!IBFTzgw*MZtb;$`mm#g zooxFW-#nA--ma|U4fN9*MdBOo5#!Gtxx4P}x({BsaN^gM?OxkDr%vMe$J+~T=Cphg zGj&Lzf5H!KI^+b(y^>EH-~avGuTI@KeeI9wJ4>d21=C#n===GFQ{O6jBfD(%mE=Z0 zBorJQId^x-rfD}EIPb7(6&k0hFeo6lx*6$ z`pYkpZ1xNvn6%;1!7E+gxV)oR$)MWY1so_!d%F@$*M9I8^7`EyrXxsq88_}O6rVUa`nMi%i(x5Kha{z@M~v!^o+W={iE&r zz@ukM*KV4g|9bqkbGPRj_bgf6eAv?Wj=Ox3dfcn|LD!;Yce=)Zv~Js`k=Kr%Dw=+I zc;U3U1@~6{A-d}V6OP~c>eHJ)yfb;?sDnG@b2mhd4*j?u7PrV9n+|H1ai@qI5eC26 zOR5Cu_n^nlu6&DIsmAI4(_Iv#ievC0>~?Ph7ct>oWa=uB%U+ zyW#fDOk>O2U5tZvP1(NT(&mJCmsQK(m2cg9Z{iQof&N1R%@V(F*Ha+@C8m=)J} zkKd_dJ}Wv1C;86572gQcuakUNT!(e%KLd@!4>EGxnTWxUGkSbUMBM#IFP-JL=EOBtH%$r@jEE8rufB$Nb&2r>_v0>O<8*rjSY|<{4k3g zG+LP_Pt*O2d17-SrjZ}vW_Y^E?BE+AA3_qygDx(uVmbS=RTiPOfxqMq}WM&?oHfG+O7k$yMzSJIm zCGFM8M2@kC397`{kRkk+#ggpmFlJ=Koa)>!HMN$ zq;?HS;)j=NP~G&$b+D8tnBYuDWsXv6yU8$qwbS4q6zQ<3P z9#l_QQg9OZ(=d9v*SP+1j#ggb7*&-=KT+QNCmsDX1CZ!pI{GQWsO|{~x;W?qZQvFQ z+m*0SUB%Wu1?GSn&>)wz5?X}Sy}F3QsTTU9tB5(l^NdN?n=hz=0X;{9uEJGDbQ~gG zLC^Ezy*nu6O!#pKAV@jI{{=M@rJH2=L`&Tz1fbd3;3xL?ccbTKLo&rjkfSZJ)&rhH`lxOl=- zizpwPI6j5)`0#vOVjS6tIUldnjIWT7j3@pz@Zo>NLl=_}g-l<3`02*TWF7x49eHnj zEcRA|0xD4mAELy^DW2XxA0C^arc=e;kG1wX;8MFEmqVB6843!LgYz7pqLpkHAj_ZF z#tFR5fWCu|J3gehU-3D@>}b5yO-C9hQK(jYV+`76Q%Q03QDfR%Ckp(bH~xHtNqE^n zQDfng!eVgH<$ETR&WVYPEZ-7*$7vB3)UTzO@WjQU9TuK4fZD-FM|g@}ZaR8r!%!3c zoau~0A8l+Dj$a{G2|op20Y*foqj7Ao7RTdFC*>(kxW3xSiFECrsP8V}x+jXb?ulVU zFscf06O(fEVKHho>aw7m6sA&P z`bqI>j+QGq0ZQR$HclGGs&yhj6v-rm`J(6^^(G9K2VknmxqC{iPCiTGn^FtAb0F|Q&cFqrzo3~qIaxT zryqbG3qeOF>Pbck6{c5d^-qI)B}P3B3`00Ibq_V-PpK=gAaM8bdbL&_;Eph50Ra;8 z?l>jecajFDtiRF$aQjmiNz=!2$g&JTH48LfuI;E=qPu8-gzGGUS3iUIw=OI^=Jb%QY4ak)6%0b z)IRZOkA;RzK>CDi@$O`(awTVylt^_of9{?LjRz*WW-e#7u@$vkGvk4%z8Wzayhg8Y` z6vI^U$!cjP(uT{(ID;*Cv}MhW`!Pd4|b* z$UUAmdK&(s(bGyDk~lsI08zaP4$%!xv~-3dEGB6pfy;p?%gxKfU$ib>PMTmOljA_M z$w>WI&R8s#Qhs7HTZ-845B{JHt#aNHsT3E=4!;O^%m)lY>~=7rhZddx0QD}aFf=`o5y8H#ybuPo;eNekdpL>?yJ$ZTxl z)K!s_r-`Wia%-8qBrTb)rVFo;r|FA6=D?9X%lV+DbrVl@@-7xtsGtWxxhMMct)>1r zElf|qCE?_7GWIca4m^syRVT%uB+<0Y$|p!?yNKG(#p1#6I&+O%axK$@YhHp zd1HAqp@y=7&_x)ntf8!_bXK}3UD=rSY&4r9ToUY9mLO-#mGuN$v1EU>TEh!Al(!Wj zl0#x@A1Zu>5M0U6tGF;Ia6HpXLjH;3{z_>Qi$86rNc4P7A`4OsOnNi6e{w=>B?F-c zinR#Z`6q_ri){>l907;blW`0?*7Sg|M`fM;8@xRKL0(?}ATMt-FRsM!81*2EOdD_U z8TbUNFeA*HJj<@E(hjIn2bdK<2ujA&7Z``}jP7>yVLhnwXYTbX?et7@W~J?sY4(5C z<_Hev(_15Ka4T<&6jg1DM4-4S!h}Y$iu(fdzDHWe05`)b?}gBeiaR02Q~MyS8qe4T zDJt%P6o0h?s>c53uXjIH?tQ?SZ-&b4e5%;@D5~7`D5}`=DE?%}V_poLxKUbc@wrXQ zQdHVsNM^*ne{oyKcLJhwCb|BK-l}A*!FY<@vJK;~5WNZyk(P&+-zb`WU`bo%Ew%y= zQ^rol9s@%wQbqeH$)M=5No@8jgR!ng#?iK;oZU%owWS&fVj?0RARfLuSZA|wK6y}YUsf~k@dLUqNTzP3KIJsu$r@|)7;y9E4 zQr>yy?uX=~V7|~M#bFbU$enz=o6M!+j;*@PNG|e{%PC3Z&w=HX#0lyCPC3evmL3r| ziV8gEN*%;qXp8*>$KbYGBo;Y~hE1A!##T|$U!{wQjZ%p&Hm2WL6~fKK1~D&*O0P8j z_}2ItZdZ3q>5*75$BUD@IH8B}@b#i)apSX08j3Iky^m3&Hjb{+BeDEq7y<`w0=Vn& z09q2#CNJdQu;z=M##%kG~f= zCt(&ivDGoBs{&)OSU{btb}w))MM`yp1p88_9felsoiR==5kH>Uk^g&>=!6O7nfG>0E^c0BjAyO7AS9G&gQK z@&csvSBDUx*b->y*NO@JM2v*PwLvBHU~G-Fl~~jynjuLzr6IkWiXQ_ZF4EDDavUki zPtS-ajpz`Jj82+xnCTP|ekF+#PuQ4G5%G7C{f|FIH1iy9hjeNvh#HH(AUbhV;g60X z;loerIpACnj^E%NZTuTK2OB!6=fK}cC!Q6e7puwWtWX1@75_{;#7wo%57p(j4&*e0 z;fKUXymv&@{Xcb5?|EO+Sk4yE23D899YuVHjU1cmSlo-HyRjbl(0gJu(mMjB6K9c_ zg(}&K6XpNM+sdq$E82>jcce{_KfltcLkHFzZzgJhHzC!-d9A1ax!@f}uK0-Gl&XU_ zE7r!}n32n_sp}$Q10#^5+h$c?Hm` z%+{vQ@_Szjiv`oRW(^6BY)eoq(X2(sT>-ACTYWF0Qe6+RMVmpVK^{yvkrU7RD# z7GxLQ9wPsM$r_&iNSGzaPB(mn{6i*l*f(34DaiIYmhe1VJWKdcV2dgDh_NvC;d!>@Lm^FITPXJ!Z&La|m?5x{rN}*DvYO{9D?4AajOW>eGy%^M zO`u#UlQ|br*7mwH4qhV95@rbR2{w4yoxsZQ5dB%6J!iwStk3(xyMnB*m|4y<-y$QR zl6yRNuNLK4=zGFD*u?YnLY`j8)2Dd)6zEx_cZIhF8NKMKFHeOamBLdgNG;~6#YpAw z)OMtf^VD&quJP10r0($4T}&nK5Ia5rT*UeTD=lm=z|+!lhxBLVmceq%qpX%?;ly6(Tl1QV zOy6>=t<2^eUx^L05}TK4JWC=j;@8V9;!jxlCBCu)0QX=dcMnF9dr-nmuESQ*k&wwv zjzufV!|fQ$-Hx&3c06Pzm*fl4L6JF{9F`iCuk6r}!}AAsc>drH4>?2^xI=V-J4A4p znip_~sh~MIOmL{`{mdPzpX-rB1&7P=6Yg+*;z$k`9J1GLafj^I5OT=KVcQ})Y;tng z;LwdUIdmh*p(B@Xg30BZ$X!0Tg|*FYVQq2?t8yN>o0)#d@&-C63 zVY%RV@7ggqro9`IV=DTt=y?b0zyEX%h_+z;wraqt0jmbA8u(AvfYl@TPxl6>{r|}$ zz}j}J2CN#eYQU-iQ3FDnRQmMYQU-is|Nm)HNZUr>*=Te%Ck!UJa6mi zC+q1aWjbGQTr?IR@(yZt5tfRm>3jSw~0_*7~@!+)e^pol6{J(MfsV2_xH^yoH zhWOCa9Q4oCbQPcNAV@=g=AX{}H^7^hMJmEdDe>A6bQK|$b1$H-7ZA(0IimT>@vjAI ziD=ku@M(>7E2QXOD`46pI=36HZop8AzKK%G)3r6HqHhZgm2QnsOMIHKro45{@J;E) z{7Pv{s);$>6mm5Im3SpM>4kLCh^L#d7g4e~IJbZlZQj9yQ$i3^o8@VR8RIn+| zj#$m?Ts8TEP=;J)kO2X+Wv-bI1eqZSuUXaj#jckCWtq1qxrNE(#gBvs zD0K!*Z{o_U(|zNM&<5%mA1M zuymtvPaw!uf#oA_pgdDv#qmEDbOq&dalJ>d2o8$?EFG{+4ol~-RKN^7NjDsr%YnI< z!R99jcUQP8aEJkrOhB>;!h)`$ic3(&E(msqAew79g9tT48M~oh4$I`Q2*5G{GjLcw zho$~OD&NDH65%Wb4$8d}-z7c`0>EU1XM_zYI8}%YYjRvq{4h!P2AixX- z(ET-{OXV=lacJfkvrSTSJf9G1&r8U*u-IEA)xSTTpC1D1{Vpa)&WOd()k%8Q9* zF2YN>{*Df~CfH)$5{G#^c+UJ9M~XWb8q9>D<+4ea^B6%0D^QB&wj#y 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 literal 0 HcmV?d00001 diff --git a/Assets/Ink/Editor/Tools/File Icons/Resources/InkFileIcon-Large.psd b/Assets/Ink/Editor/Tools/File Icons/Resources/InkFileIcon-Large.psd new file mode 100644 index 0000000000000000000000000000000000000000..372812b2785e8eaa5480cf1af8fb63c02e633e86 GIT binary patch literal 884643 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