diff --git a/3rd-Party-Notice.md b/3rd-Party-Notice.md new file mode 100644 index 0000000..3f638c0 --- /dev/null +++ b/3rd-Party-Notice.md @@ -0,0 +1,32 @@ +# 3rd party assets used in this project + +## NaughtyAttributes + +NaughtyAttributes is an extension for the Unity Inspector. + +It expands the range of attributes that Unity provides so that you can +create powerful inspectors without the need of custom editors or property +drawers. It also provides attributes that can be applied to non-serialized +fields or functions. + +It is implemented by replacing the default Unity Inspector. This means +that if you have any custom editors, NaughtyAttributes will not work with +them. All of your custom editors and property drawers are not affected +in any way. + +* License: MIT +* Source: https://github.com/dbrizov/NaughtyAttributes + +## FluentAssertions + +Fluent API for asserting the results of unit tests that targets .NET +Framework 4.5, 4.7, .NET Standard 1.3, 1.6 and 2.0. Supports the unit +test frameworks MSTest, MSTest2, Gallio, NUnit, XUnit, MBunit, MSpec, +and NSpec. + +The version contained here is stripped down to remove all parts of the +library that are inherently incompatible with Unity's interpretation +of C# and their runtime libraries. + +* License: Apache License 2.0 +* Source: https://github.com/fluentassertions/fluentassertions/ diff --git a/Assembly-CSharp-firstpass.csproj.DotSettings b/Assembly-CSharp-firstpass.csproj.DotSettings new file mode 100644 index 0000000..f3a4b90 --- /dev/null +++ b/Assembly-CSharp-firstpass.csproj.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/Assets/Plugins.meta b/Assets/Plugins.meta new file mode 100644 index 0000000..441f095 --- /dev/null +++ b/Assets/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1143ea67f80f30d4eb91287bd083a8a4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions.meta b/Assets/Plugins/FluentAssertions.meta new file mode 100644 index 0000000..f323f7c --- /dev/null +++ b/Assets/Plugins/FluentAssertions.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ca263302667a4bf4cb87fe0aa1a77aec +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core.meta b/Assets/Plugins/FluentAssertions/Core.meta new file mode 100644 index 0000000..53d4248 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b221e90a28450b04f8aec26231827895 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/AndConstraint.cs b/Assets/Plugins/FluentAssertions/Core/AndConstraint.cs new file mode 100644 index 0000000..06b21cc --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/AndConstraint.cs @@ -0,0 +1,23 @@ +using System.Diagnostics; + +namespace FluentAssertions +{ + [DebuggerNonUserCode] + public class AndConstraint + { + private readonly T parentConstraint; + + /// + /// Initializes a new instance of the class. + /// + public AndConstraint(T parentConstraint) + { + this.parentConstraint = parentConstraint; + } + + public T And + { + get { return parentConstraint; } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/AndConstraint.cs.meta b/Assets/Plugins/FluentAssertions/Core/AndConstraint.cs.meta new file mode 100644 index 0000000..aa99ceb --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/AndConstraint.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8e6a47299cda6a04f886f40d493bb813 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/AndWhichConstraint.cs b/Assets/Plugins/FluentAssertions/Core/AndWhichConstraint.cs new file mode 100644 index 0000000..1fb2093 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/AndWhichConstraint.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using FluentAssertions.Common; +using FluentAssertions.Formatting; + +namespace FluentAssertions +{ + /// + /// Constraint which can be returned from an assertion which matches a condition and which will allow + /// further matches to be performed on the matched condition as well as the parent constraint. + /// + /// The type of the original constraint that was matched + /// The type of the matched object which the parent constraint matched + public class AndWhichConstraint : AndConstraint + { + private readonly Lazy matchedConstraint; + + public AndWhichConstraint(TParentConstraint parentConstraint, TMatchedElement matchedConstraint) + : base(parentConstraint) + { + this.matchedConstraint = + new Lazy(() => matchedConstraint); + } + + public AndWhichConstraint(TParentConstraint parentConstraint, IEnumerable matchedConstraint) + : base(parentConstraint) + { + this.matchedConstraint = + new Lazy( + () => SingleOrDefault(matchedConstraint)); + } + + private static TMatchedElement SingleOrDefault( + IEnumerable matchedConstraint) + { + TMatchedElement[] matchedElements = matchedConstraint.ToArray(); + + if (matchedElements.Count() > 1) + { + string foundObjects = string.Join(Environment.NewLine, + matchedElements.Select( + ele => "\t" + Formatter.ToString(ele))); + + string message = string.Format( + "More than one object found. FluentAssertions cannot determine which object is meant. Found objects:{0}{1}", + Environment.NewLine, + foundObjects); + + Services.ThrowException(message); + } + + return matchedElements.Single(); + } + + /// + /// Returns the single result of a prior assertion that is used to select a nested or collection item. + /// + public TMatchedElement Which + { + get { return matchedConstraint.Value; } + } + + /// + /// Returns the single result of a prior assertion that is used to select a nested or collection item. + /// + /// + /// Just a convenience property that returns the same value as . + /// + public TMatchedElement Subject + { + get { return Which; } + } + } +} + diff --git a/Assets/Plugins/FluentAssertions/Core/AndWhichConstraint.cs.meta b/Assets/Plugins/FluentAssertions/Core/AndWhichConstraint.cs.meta new file mode 100644 index 0000000..98a177f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/AndWhichConstraint.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c8307fb9bef0c0a4d865164b701628c3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/AssertionOptions.cs b/Assets/Plugins/FluentAssertions/Core/AssertionOptions.cs new file mode 100644 index 0000000..481e32a --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/AssertionOptions.cs @@ -0,0 +1,58 @@ +#region + +using System; +using FluentAssertions.Common; +using FluentAssertions.Equivalency; + +#endregion + +namespace FluentAssertions +{ + /// + /// Holds any global options that control the behavior of FluentAssertions. + /// + public static class AssertionOptions + { + private static EquivalencyAssertionOptions defaults = new EquivalencyAssertionOptions(); + + static AssertionOptions() + { + EquivalencySteps = new EquivalencyStepCollection(); + } + + public static EquivalencyAssertionOptions CloneDefaults() + { + return new EquivalencyAssertionOptions(defaults); + } + + /// + /// Defines a predicate with which the determines if it should process + /// an object's properties or not. + /// + /// + /// Returns true if the object should be treated as a value type and its + /// must be used during a structural equivalency check. + /// + public static Func IsValueType = type => + (type.Namespace == typeof (int).Namespace) && + !type.IsSameOrInherits(typeof(Exception)); + + /// + /// Allows configuring the defaults used during a structural equivalency assertion. + /// + /// + /// An action that is used to configure the defaults. + /// + public static void AssertEquivalencyUsing( + Func defaultsConfigurer) + { + defaults = defaultsConfigurer(defaults); + } + + /// + /// Represents a mutable collection of steps that are executed while asserting a (collection of) object(s) + /// is structurally equivalent to another (collection of) object(s). + /// + public static EquivalencyStepCollection EquivalencySteps { get; private set; } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/AssertionOptions.cs.meta b/Assets/Plugins/FluentAssertions/Core/AssertionOptions.cs.meta new file mode 100644 index 0000000..c442954 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/AssertionOptions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 673bfff1b81f6c6468c0957ecf933787 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Collections.meta b/Assets/Plugins/FluentAssertions/Core/Collections.meta new file mode 100644 index 0000000..cb7d8f6 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Collections.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c5b22091f289dd74bbe255baa5f43351 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Collections/CollectionAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Collections/CollectionAssertions.cs new file mode 100644 index 0000000..c8e4165 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Collections/CollectionAssertions.cs @@ -0,0 +1,1373 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using FluentAssertions.Common; +using FluentAssertions.Execution; +using FluentAssertions.Primitives; + +namespace FluentAssertions.Collections +{ + /// + /// Contains a number of methods to assert that an is in the expected state. + /// + public abstract class CollectionAssertions : ReferenceTypeAssertions + where TAssertions : CollectionAssertions + where TSubject : IEnumerable + { + /// + /// Asserts that the collection does not contain any items. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeEmpty(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .WithExpectation("Expected {context:collection} to be empty{reason}, ") + .ForCondition(!ReferenceEquals(Subject, null)) + .FailWith("but found {0}.", Subject) + .Then + .Given(() => Subject.Cast()) + .ForCondition(collection => !collection.Any()) + .FailWith("but found {0}.", collection => collection); + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the collection contains at least 1 item. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeEmpty(string because = "", params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} not to be empty{reason}, but found {0}.", Subject); + } + + IEnumerable enumerable = Subject.Cast(); + + Execute.Assertion + .ForCondition(enumerable.Any()) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} not to be empty{reason}."); + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the collection is null or does not contain any items. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeNullOrEmpty(string because = "", params object[] becauseArgs) + { + var nullOrEmpty = ReferenceEquals(Subject, null) || !Subject.Cast().Any(); + + Execute.Assertion.ForCondition(nullOrEmpty) + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected {context:collection} to be null or empty{reason}, but found {0}.", + Subject); + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the collection is not null and contains at least 1 item. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeNullOrEmpty(string because = "", params object[] becauseArgs) + { + return NotBeNull(because, becauseArgs) + .And.NotBeEmpty(because, becauseArgs); + } + + /// + /// Asserts that the collection does not contain any duplicate items. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint OnlyHaveUniqueItems(string because = "", params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to only have unique items{reason}, but found {0}.", Subject); + } + + IGrouping groupWithMultipleItems = Subject.Cast() + .GroupBy(o => o) + .FirstOrDefault(g => g.Count() > 1); + + if (groupWithMultipleItems != null) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to only have unique items{reason}, but item {0} is not unique.", + groupWithMultipleItems.Key); + } + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the collection does not contain any null items. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotContainNulls(string because = "", params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} not to contain nulls{reason}, but collection is ."); + } + + object[] values = Subject.Cast().ToArray(); + for (int index = 0; index < values.Length; index++) + { + if (ReferenceEquals(values[index], null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} not to contain nulls{reason}, but found one at index {0}.", index); + } + } + + return new AndConstraint((TAssertions)this); + } + + /// + /// Expects the current collection to contain all the same elements in the same order as the collection identified by + /// . Elements are compared using their . + /// + /// A params array with the expected elements. + public AndConstraint Equal(params object[] elements) + { + return Equal(elements, String.Empty); + } + + /// + /// Expects the current collection to contain all the same elements in the same order as the collection identified by + /// . Elements are compared using their . + /// + /// An with the expected elements. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Equal(IEnumerable expected, string because = "", params object[] becauseArgs) + { + AssertSubjectEquality(expected, (s, e) => s.IsSameOrEqualTo(e), because, becauseArgs); + + return new AndConstraint((TAssertions)this); + } + + protected void AssertSubjectEquality(IEnumerable expectation, Func equalityComparison, + string because = "", params object[] becauseArgs) + { + + bool subjectIsNull = ReferenceEquals(Subject, null); + bool expectationIsNull = ReferenceEquals(expectation, null); + if (subjectIsNull && expectationIsNull) + { + return; + } + + if (expectation == null) + { + throw new ArgumentNullException("expectation", "Cannot compare collection with ."); + } + + TExpected[] expectedItems = expectation.Cast().ToArray(); + + AssertionScope assertion = Execute.Assertion.BecauseOf(because, becauseArgs); + if (subjectIsNull) + { + assertion.FailWith("Expected {context:collection} to be equal to {0}{reason}, but found .", expectedItems); + } + + assertion + .WithExpectation("Expected {context:collection} to be equal to {0}{reason}, ", expectedItems) + .Given(() => Subject.Cast().ToList().AsEnumerable()) + .AssertCollectionsHaveSameCount(expectedItems.Length) + .Then + .AssertCollectionsHaveSameItems(expectedItems, (a, e) => a.IndexOfFirstDifferenceWith(e, equalityComparison)); + } + + /// + /// Expects the current collection not to contain all the same elements in the same order as the collection identified by + /// . Elements are compared using their . + /// + /// An with the elements that are not expected. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotEqual(IEnumerable unexpected, string because = "", params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected collections not to be equal{reason}, but found ."); + } + + if (unexpected == null) + { + throw new ArgumentNullException("unexpected", "Cannot compare collection with ."); + } + + List actualitems = Subject.Cast().ToList(); + + if (actualitems.SequenceEqual(unexpected.Cast())) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect collections {0} and {1} to be equal{reason}.", unexpected, actualitems); + } + + return new AndConstraint((TAssertions)this); + } + + /// + /// Expects the current collection to contain all elements of the collection identified by , + /// regardless of the order. Elements are compared using their . + /// + /// A params array with the expected elements. + public AndConstraint BeEquivalentTo(params object[] elements) + { + return BeEquivalentTo(elements, String.Empty); + } + + /// + /// Expects the current collection to contain all elements of the collection identified by , + /// regardless of the order. Elements are compared using their . + /// + /// An with the expected elements. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeEquivalentTo(IEnumerable expected, string because = "", params object[] becauseArgs) + { + if (expected == null) + { + throw new NullReferenceException("Cannot verify equivalence against a collection."); + } + + Execute.Assertion + .ForCondition(!ReferenceEquals(Subject, null)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to be equivalent to {0}{reason}, but found .", expected); + + List expectedItems = expected.Cast().ToList(); + List actualItems = Subject.Cast().ToList(); + + bool haveSameLength = Execute.Assertion + .ForCondition(actualItems.Count <= expectedItems.Count) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} {0} to be equivalent to {1}{reason}, but it contains too many items.", + actualItems, expectedItems); + + if (haveSameLength) + { + object[] missingItems = GetMissingItems(expectedItems, actualItems); + + Execute.Assertion + .ForCondition(missingItems.Length == 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} {0} to be equivalent to {1}{reason}, but it misses {2}.", + actualItems, expectedItems, missingItems); + } + return new AndConstraint((TAssertions)this); + } + + public AndConstraint BeEquivalentTo(IEnumerable expected, string because = "", params object[] becauseArgs) + { + if (expected == null) + { + throw new NullReferenceException("Cannot verify equivalence against a collection."); + } + + Execute.Assertion + .ForCondition(!ReferenceEquals(Subject, null)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to be equivalent to {0}{reason}, but found .", expected); + + List expectedItems = expected.ToList(); + List actualItems = Subject.Cast().ToList(); + + bool haveSameLength = Execute.Assertion + .ForCondition(actualItems.Count <= expectedItems.Count) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} {0} to be equivalent to {1}{reason}, but it contains too many items.", + actualItems, expectedItems); + + if (haveSameLength) + { + T[] missingItems = GetMissingItems(expectedItems, actualItems); + + Execute.Assertion + .ForCondition(missingItems.Length == 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} {0} to be equivalent to {1}{reason}, but it misses {2}.", + actualItems, expectedItems, missingItems); + } + return new AndConstraint((TAssertions)this); + } + + /// + /// Expects the current collection not to contain all elements of the collection identified by , + /// regardless of the order. Elements are compared using their . + /// + /// An with the unexpected elements. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeEquivalentTo(IEnumerable unexpected, string because = "", + params object[] becauseArgs) + { + if (unexpected == null) + { + throw new NullReferenceException("Cannot verify inequivalence against a collection."); + } + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} not to be equivalent{reason}, but found ."); + } + + IEnumerable actualItems = Subject.Cast(); + IEnumerable unexpectedItems = unexpected.Cast(); + + if (actualItems.Count() == unexpectedItems.Count()) + { + object[] missingItems = GetMissingItems(unexpectedItems, actualItems); + + Execute.Assertion + .ForCondition(missingItems.Length > 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} {0} not be equivalent with collection {1}{reason}.", Subject, + unexpected); + } + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the current collection only contains items that are assignable to the type . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint ContainItemsAssignableTo(string because = "", params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to contain element assignable to type {0}{reason}, but found .", + typeof(T)); + } + + int index = 0; + foreach (object item in Subject) + { + if (!(item is T)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected {context:collection} to contain only items of type {0}{reason}, but item {1} at index {2} is of type {3}.", + typeof(T), item, index, item.GetType()); + } + + ++index; + } + + return new AndConstraint((TAssertions)this); + } + + private static T[] GetMissingItems(IEnumerable expectedItems, IEnumerable actualItems) + { + List missingItems = new List(); + List subject = actualItems.ToList(); + + while (expectedItems.Any()) + { + T expectation = expectedItems.First(); + if (subject.Contains(expectation)) + { + subject.Remove(expectation); + } + else + { + missingItems.Add(expectation); + } + + expectedItems = expectedItems.Skip(1).ToArray(); + } + + return missingItems.ToArray(); + } + + /// + /// Expects the current collection to contain the specified elements in any order. Elements are compared + /// using their implementation. + /// + /// An with the expected elements. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Contain(IEnumerable expected, string because = "", params object[] becauseArgs) + { + if (expected == null) + { + throw new NullReferenceException("Cannot verify containment against a collection"); + } + + IEnumerable expectedObjects = expected.Cast().ToArray(); + if (!expectedObjects.Any()) + { + throw new ArgumentException("Cannot verify containment against an empty collection"); + } + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to contain {0}{reason}, but found .", expected); + } + + if (expected is string) + { + if (!Subject.Cast().Contains(expected)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} {0} to contain {1}{reason}.", Subject, expected); + } + } + else + { + IEnumerable missingItems = expectedObjects.Except(Subject.Cast()); + if (missingItems.Any()) + { + if (expectedObjects.Count() > 1) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} {0} to contain {1}{reason}, but could not find {2}.", Subject, + expected, missingItems); + } + else + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} {0} to contain {1}{reason}.", Subject, + expected.Cast().First()); + } + } + } + + return new AndConstraint((TAssertions)this); + } + + /// + /// Expects the current collection to contain the specified elements in the exact same order, not necessarily consecutive. + /// using their implementation. + /// + /// An with the expected elements. + public AndConstraint ContainInOrder(params object[] expected) + { + return ContainInOrder(expected, ""); + } + + /// + /// Expects the current collection to contain the specified elements in the exact same order, not necessarily consecutive. + /// + /// + /// Elements are compared using their implementation. + /// + /// An with the expected elements. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint ContainInOrder(IEnumerable expected, string because = "", + params object[] becauseArgs) + { + if (expected == null) + { + throw new NullReferenceException("Cannot verify ordered containment against a collection."); + } + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to contain {0} in order{reason}, but found .", expected); + } + + object[] expectedItems = expected.Cast().ToArray(); + object[] actualItems = Subject.Cast().ToArray(); + + for (int index = 0; index < expectedItems.Length; index++) + { + object expectedItem = expectedItems[index]; + actualItems = actualItems.SkipWhile(actualItem => !actualItem.IsSameOrEqualTo(expectedItem)).ToArray(); + if (actualItems.Any()) + { + actualItems = actualItems.Skip(1).ToArray(); + } + else + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected {context:collection} {0} to contain items {1} in order{reason}, but {2} (index {3}) did not appear (in the right order).", + Subject, expected, expectedItem, index); + } + } + + return new AndConstraint((TAssertions)this); + } + + /// + /// Expects the current collection to have all elements in ascending order. Elements are compared + /// using their implementation. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeInAscendingOrder(string because = "", params object[] becauseArgs) + { + return BeInAscendingOrder(Comparer.Default, because, becauseArgs); + } + + /// + /// Expects the current collection to have all elements in ascending order. Elements are compared + /// using the given implementation. + /// + /// + /// The object that should be used to determine the expected ordering. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeInAscendingOrder(IComparer comparer, string because = "", params object[] becauseArgs) + { + return BeInOrder(comparer, SortOrder.Ascending, because, becauseArgs); + } + + /// + /// Expects the current collection to have all elements in descending order. Elements are compared + /// using their implementation. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeInDescendingOrder(string because = "", params object[] becauseArgs) + { + return BeInDescendingOrder(Comparer.Default, because, becauseArgs); + } + + /// + /// Expects the current collection to have all elements in descending order. Elements are compared + /// using the given implementation. + /// + /// + /// The object that should be used to determine the expected ordering. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeInDescendingOrder(IComparer comparer, string because = "", params object[] becauseArgs) + { + return BeInOrder(comparer, SortOrder.Descending, because, becauseArgs); + } + + /// + /// Expects the current collection to have all elements in the specified . + /// Elements are compared using their implementation. + /// + private AndConstraint BeInOrder( + IComparer comparer, SortOrder expectedOrder, string because = "", params object[] becauseArgs) + { + string sortOrder = (expectedOrder == SortOrder.Ascending) ? "ascending" : "descending"; + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to contain items in " + sortOrder + " order{reason}, but found {1}.", + Subject); + } + + object[] actualItems = Subject.Cast().ToArray(); + + object[] orderedItems = (expectedOrder == SortOrder.Ascending) + ? actualItems.OrderBy(item => item, comparer).ToArray() + : actualItems.OrderByDescending(item => item, comparer).ToArray(); + + for (int index = 0; index < orderedItems.Length; index++) + { + Execute.Assertion + .ForCondition(actualItems[index].IsSameOrEqualTo(orderedItems[index])) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to contain items in " + sortOrder + + " order{reason}, but found {0} where item at index {1} is in wrong order.", + Subject, index); + } + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts the current collection does not have all elements in ascending order. Elements are compared + /// using their implementation. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeAscendingInOrder(string because = "", params object[] becauseArgs) + { + return NotBeAscendingInOrder(Comparer.Default, because, becauseArgs); + } + + /// + /// Asserts the current collection does not have all elements in ascending order. Elements are compared + /// using their implementation. + /// + /// + /// The object that should be used to determine the expected ordering. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeAscendingInOrder(IComparer comparer, string because = "", params object[] becauseArgs) + { + return NotBeInOrder(comparer, SortOrder.Ascending, because, becauseArgs); + } + + /// + /// Asserts the current collection does not have all elements in descending order. Elements are compared + /// using their implementation. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeDescendingInOrder(string because = "", params object[] becauseArgs) + { + return NotBeDescendingInOrder(Comparer.Default, because, becauseArgs); + } + + /// + /// Asserts the current collection does not have all elements in descending order. Elements are compared + /// using their implementation. + /// + /// + /// The object that should be used to determine the expected ordering. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeDescendingInOrder(IComparer comparer, string because = "", params object[] becauseArgs) + { + return NotBeInOrder(comparer, SortOrder.Descending, because, becauseArgs); + } + + /// + /// Asserts the current collection does not have all elements in ascending order. Elements are compared + /// using their implementation. + /// + private AndConstraint NotBeInOrder(IComparer comparer, SortOrder order, string because = "", params object[] becauseArgs) + { + string sortOrder = (order == SortOrder.Ascending) ? "ascending" : "descending"; + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith( + "Did not expect {context:collection} to contain items in " + sortOrder + " order{reason}, but found {1}.", + Subject); + } + + object[] orderedItems = (order == SortOrder.Ascending) + ? Subject.Cast().OrderBy(item => item, comparer).ToArray() + : Subject.Cast().OrderByDescending(item => item, comparer).ToArray(); + + object[] actualItems = Subject.Cast().ToArray(); + + bool itemsAreUnordered = actualItems + .Where((actualItem, index) => !actualItem.IsSameOrEqualTo(orderedItems[index])) + .Any(); + + if (!itemsAreUnordered) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith( + "Did not expect {context:collection} to contain items in " + sortOrder + " order{reason}, but found {0}.", + Subject); + } + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the collection is a subset of the . + /// + /// An with the expected superset. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeSubsetOf(IEnumerable expectedSuperset, string because = "", + params object[] becauseArgs) + { + if (expectedSuperset == null) + { + throw new NullReferenceException("Cannot verify a subset against a collection."); + } + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to be a subset of {0}{reason}, but found {1}.", expectedSuperset, + Subject); + } + + IEnumerable expectedItems = expectedSuperset.Cast(); + IEnumerable actualItems = Subject.Cast(); + + IEnumerable excessItems = actualItems.Except(expectedItems); + + if (excessItems.Any()) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected {context:collection} to be a subset of {0}{reason}, but items {1} are not part of the superset.", + expectedSuperset, excessItems); + } + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the collection is not a subset of the . + /// + /// An with the unexpected superset. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeSubsetOf(IEnumerable unexpectedSuperset, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!ReferenceEquals(Subject, null)) + .BecauseOf(because, becauseArgs) + .FailWith("Cannot assert a collection against a subset."); + + IEnumerable expectedItems = unexpectedSuperset.Cast(); + object[] actualItems = Subject.Cast().ToArray(); + + if (actualItems.Intersect(expectedItems).Count() == actualItems.Count()) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect {context:collection} {0} to be a subset of {1}{reason}.", actualItems, expectedItems); + } + + return new AndConstraint((TAssertions)this); + } + + /// + /// Assert that the current collection has the same number of elements as . + /// + /// The other collection with the same expected number of elements + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveSameCount(IEnumerable otherCollection, string because = "", + params object[] becauseArgs) + { + if (otherCollection == null) + { + throw new NullReferenceException("Cannot verify count against a collection."); + } + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to have the same count as {0}{reason}, but found {1}.", + otherCollection, + Subject); + } + + IEnumerable enumerable = Subject.Cast(); + + int actualCount = enumerable.Count(); + int expectedCount = otherCollection.Cast().Count(); + + Execute.Assertion + .ForCondition(actualCount == expectedCount) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to have {0} item(s){reason}, but found {1}.", expectedCount, actualCount); + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the current collection has the supplied at the + /// supplied . + /// + /// The index where the element is expected + /// The expected element + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndWhichConstraint HaveElementAt(int index, object element, string because = "", + params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to have element at index {0}{reason}, but found {1}.", index, Subject); + } + + IEnumerable enumerable = Subject.Cast(); + + object actual = null; + if (index < enumerable.Count()) + { + actual = Subject.Cast().ElementAt(index); + + Execute.Assertion + .ForCondition(actual.IsSameOrEqualTo(element)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {0} at index {1}{reason}, but found {2}.", element, index, actual); + } + else + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {0} at index {1}{reason}, but found no element.", element, index); + } + + return new AndWhichConstraint((TAssertions)this, actual); + } + + /// + /// Asserts that the current collection does not contain the supplied items. Elements are compared + /// using their implementation. + /// + /// An with the unexpected elements. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotContain(IEnumerable unexpected, string because = "", params object[] becauseArgs) + { + if (unexpected == null) + { + throw new NullReferenceException("Cannot verify non-containment against a collection"); + } + + IEnumerable unexpectedObjects = unexpected.Cast().ToArray(); + if (!unexpectedObjects.Any()) + { + throw new ArgumentException("Cannot verify non-containment against an empty collection"); + } + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to not contain {0}{reason}, but found .", unexpected); + } + + if (unexpected is string) + { + if (Subject.Cast().Contains(unexpected)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} {0} to not contain {1}{reason}.", Subject, unexpected); + } + } + else + { + IEnumerable foundItems = unexpectedObjects.Intersect(Subject.Cast()); + if (foundItems.Any()) + { + if (unexpectedObjects.Count() > 1) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} {0} to not contain {1}{reason}, but found {2}.", Subject, + unexpected, foundItems); + } + else + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} {0} to not contain element {1}{reason}.", Subject, + unexpectedObjects.First()); + } + } + } + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the collection shares one or more items with the specified . + /// + /// The with the expected shared items. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint IntersectWith(IEnumerable otherCollection, string because = "", + params object[] becauseArgs) + { + if (otherCollection == null) + { + throw new NullReferenceException("Cannot verify intersection against a collection."); + } + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to intersect with {0}{reason}, but found {1}.", otherCollection, + Subject); + } + + IEnumerable otherItems = otherCollection.Cast(); + IEnumerable sharedItems = Subject.Cast().Intersect(otherItems); + + if (!sharedItems.Any()) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected {context:collection} to intersect with {0}{reason}, but {1} does not contain any shared items.", + otherCollection, Subject); + } + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the collection does not share any items with the specified . + /// + /// The to compare to. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotIntersectWith(IEnumerable otherCollection, string because = "", + params object[] becauseArgs) + { + if (otherCollection == null) + { + throw new NullReferenceException("Cannot verify intersection against a collection."); + } + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect {context:collection} to intersect with {0}{reason}, but found {1}.", otherCollection, + Subject); + } + + IEnumerable otherItems = otherCollection.Cast(); + IEnumerable sharedItems = Subject.Cast().Intersect(otherItems); + + if (sharedItems.Any()) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith( + "Did not expect {context:collection} to intersect with {0}{reason}, but found the following shared items {1}.", + otherCollection, sharedItems); + } + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the collection starts with the specified . + /// + /// + /// The element that is expected to appear at the start of the collection. The object's + /// is used to compare the element. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint StartWith(object element, string because = "", params object[] becauseArgs) + { + AssertCollectionStartsWith(Subject?.Cast(), new[] { element }, ObjectExtensions.IsSameOrEqualTo, because, becauseArgs); + return new AndConstraint((TAssertions) this); + } + + protected void AssertCollectionStartsWith(IEnumerable actualItems, TExpected[] expected, Func equalityComparison, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .WithExpectation("Expected {context:collection} to start with {0}{reason}, ", expected) + .Given(() => actualItems) + .AssertCollectionIsNotNullOrEmpty(expected.Length) + .Then + .AssertCollectionHasEnoughItems(expected.Length) + .Then + .AssertCollectionsHaveSameItems(expected, (a, e) => a.Take(e.Length).IndexOfFirstDifferenceWith(e, equalityComparison)); + } + + /// + /// Asserts that the collection ends with the specified . + /// + /// + /// The element that is expected to appear at the end of the collection. The object's + /// is used to compare the element. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint EndWith(object element, string because = "", params object[] becauseArgs) + { + AssertCollectionEndsWith(Subject?.Cast(), new[] { element }, ObjectExtensions.IsSameOrEqualTo, because, becauseArgs); + return new AndConstraint((TAssertions) this); + } + + protected void AssertCollectionEndsWith(IEnumerable actual, TExpected[] expected, Func equalityComparison, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .WithExpectation("Expected {context:collection} to end with {0}{reason}, ", expected) + .Given(() => actual) + .AssertCollectionIsNotNullOrEmpty(expected.Length) + .Then + .AssertCollectionHasEnoughItems(expected.Length) + .Then + .AssertCollectionsHaveSameItems(expected, (a, e) => + { + int firstIndexToCompare = a.Length - e.Length; + int index = a.Skip(firstIndexToCompare).IndexOfFirstDifferenceWith(e, equalityComparison); + return index >= 0 ? index + firstIndexToCompare : index; + }); + } + + /// + /// Asserts that the element directly precedes the . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveElementPreceding(object successor, object expectation, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .WithExpectation("Expected {context:collection} to have {0} precede {1}{reason}, ", expectation, successor) + .Given(() => Subject.Cast()) + .ForCondition(subject => subject.Any()) + .FailWith("but the collection is empty.") + .Then + .ForCondition(subject => HasPredecessor(successor, subject)) + .FailWith("but found nothing.") + .Then + .Given(subject => PredecessorOf(successor, subject)) + .ForCondition(predecessor => predecessor.IsSameOrEqualTo(expectation)) + .FailWith("but found {0}.", predecessor => predecessor); + + return new AndConstraint((TAssertions)this); + } + + private bool HasPredecessor(object successor, IEnumerable subject) + { + return !ReferenceEquals(subject.First(), successor); + } + + private object PredecessorOf(object succesor, IEnumerable subject) + { + object[] collection = subject.ToArray(); + int index = Array.IndexOf(collection, succesor); + return (index > 0) ? collection[index - 1] : null; + } + + /// + /// Asserts that the element directly succeeds the . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveElementSucceeding(object predecessor, object expectation, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .WithExpectation("Expected {context:collection} to have {0} succeed {1}{reason}, ", expectation, predecessor) + .Given(() => Subject.Cast()) + .ForCondition(subject => subject.Any()) + .FailWith("but the collection is empty.") + .Then + .ForCondition(subject => HasSuccessor(predecessor, subject)) + .FailWith("but found nothing.") + .Then + .Given(subject => SuccessorOf(predecessor, subject)) + .ForCondition(successor => successor.IsSameOrEqualTo(expectation)) + .FailWith("but found {0}.", successor => successor); + + return new AndConstraint((TAssertions)this); + } + + private bool HasSuccessor(object predecessor, IEnumerable subject) + { + return !ReferenceEquals(subject.Last(), predecessor); + } + + private object SuccessorOf(object predecessor, IEnumerable subject) + { + object[] collection = subject.ToArray(); + int index = Array.IndexOf(collection, predecessor); + return (index < (collection.Length - 1)) ? collection[index + 1] : null; + } + + /// + /// Asserts that all items in the collection are of the specified type + /// + /// The expected type of the objects + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint AllBeAssignableTo(string because = "", params object[] becauseArgs) + { + return AllBeAssignableTo(typeof(T), because, becauseArgs); + } + + /// + /// Asserts that all items in the collection are of the specified type + /// + /// The expected type of the objects + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint AllBeAssignableTo(Type expectedType, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .WithExpectation("Expected type to be {0}{reason}, ", expectedType.FullName) + .Given(() => Subject.Cast()) + .ForCondition(subject => subject.All(x => x != null)) + .FailWith("but found a null element.") + .Then + .ForCondition(subject => subject.All(x => expectedType.IsAssignableFrom(x.GetType()))) + .FailWith("but found {0}.", subject => $"[{string.Join(", ", subject.Select(x => x.GetType().FullName))}]"); + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that all items in the collection are of the exact specified type + /// + /// The expected type of the objects + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint AllBeOfType(string because = "", params object[] becauseArgs) + { + return AllBeOfType(typeof(T), because, becauseArgs); + } + + /// + /// Asserts that all items in the collection are of the exact specified type + /// + /// The expected type of the objects + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint AllBeOfType(Type expectedType, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .WithExpectation("Expected type to be {0}{reason}, ", expectedType.FullName) + .Given(() => Subject.Cast()) + .ForCondition(subject => subject.All(x => x != null)) + .FailWith("but found a null element.") + .Then + .ForCondition(subject => subject.All(x => expectedType == x.GetType())) + .FailWith("but found {0}.", subject => $"[{string.Join(", ", subject.Select(x => x.GetType().FullName))}]"); + + return new AndConstraint((TAssertions)this); + } + + /// + /// Returns the type of the subject the assertion applies on. + /// + protected override string Context + { + get { return "collection"; } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Collections/CollectionAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Collections/CollectionAssertions.cs.meta new file mode 100644 index 0000000..32d4dfc --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Collections/CollectionAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7d72028d05593d846a250498229e282d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Collections/GenericCollectionAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Collections/GenericCollectionAssertions.cs new file mode 100644 index 0000000..6fb9ae9 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Collections/GenericCollectionAssertions.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Linq.Expressions; + +using FluentAssertions.Common; +using FluentAssertions.Execution; + +namespace FluentAssertions.Collections +{ + [DebuggerNonUserCode] + public class GenericCollectionAssertions : + SelfReferencingCollectionAssertions> + { + public GenericCollectionAssertions(IEnumerable actualValue) : base(actualValue) + { + } + + /// + /// Asserts that a collection is ordered in ascending order according to the value of the specified + /// . + /// + /// + /// A lambda expression that references the property that should be used to determine the expected ordering. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeInAscendingOrder( + Expression> propertyExpression, string because = "", params object[] args) + { + return BeInAscendingOrder(propertyExpression, Comparer.Default, because, args); + } + + /// + /// Asserts that a collection is ordered in ascending order according to the value of the specified + /// implementation. + /// + /// + /// The object that should be used to determine the expected ordering. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeInAscendingOrder( + IComparer comparer, string because = "", params object[] args) + { + return BeInAscendingOrder(item => item, comparer, because, args); + } + + /// + /// Asserts that a collection is ordered in ascending order according to the value of the specified + /// and implementation. + /// + /// + /// A lambda expression that references the property that should be used to determine the expected ordering. + /// + /// + /// The object that should be used to determine the expected ordering. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeInAscendingOrder( + Expression> propertyExpression, IComparer comparer, string because = "", params object[] args) + { + return BeOrderedBy(propertyExpression, comparer, SortOrder.Ascending, because, args); + } + + /// + /// Asserts that a collection is ordered in descending order according to the value of the specified + /// . + /// + /// + /// A lambda expression that references the property that should be used to determine the expected ordering. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeInDescendingOrder( + Expression> propertyExpression, string because = "", params object[] args) + { + return BeInDescendingOrder(propertyExpression, Comparer.Default, because, args); + } + + /// + /// Asserts that a collection is ordered in descending order according to the value of the specified + /// implementation. + /// + /// + /// The object that should be used to determine the expected ordering. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeInDescendingOrder( + IComparer comparer, string because = "", params object[] args) + { + return BeInDescendingOrder(item => item, comparer, because, args); + } + + /// + /// Asserts that a collection is ordered in descending order according to the value of the specified + /// and implementation. + /// + /// + /// A lambda expression that references the property that should be used to determine the expected ordering. + /// + /// + /// The object that should be used to determine the expected ordering. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeInDescendingOrder( + Expression> propertyExpression, IComparer comparer, string because = "", params object[] args) + { + return BeOrderedBy(propertyExpression, comparer, SortOrder.Descending, because, args); + } + + private AndConstraint> BeOrderedBy( + Expression> propertyExpression, IComparer comparer, SortOrder direction, string because, object[] args) + { + if (comparer == null) + { + throw new ArgumentNullException("comparer", + "Cannot assert collection ordering without specifying a comparer."); + } + + if (IsValidProperty(propertyExpression, because, args)) + { + IList unordered = (Subject as IList) ?? Subject.ToList(); + + Func keySelector = propertyExpression.Compile(); + + IOrderedEnumerable expectation = (direction == SortOrder.Ascending) + ? unordered.OrderBy(keySelector, comparer) + : unordered.OrderByDescending(keySelector, comparer); + + var orderString = propertyExpression.GetMemberPath(); + orderString = orderString == "\"\"" ? string.Empty : " by " + orderString; + + Execute.Assertion + .ForCondition(unordered.SequenceEqual(expectation)) + .BecauseOf(because, args) + .FailWith("Expected collection {0} to be ordered{1}{reason} and result in {2}.", + Subject, orderString, expectation); + } + + return new AndConstraint>(this); + } + + private bool IsValidProperty(Expression> propertyExpression, string because, object[] args) + { + if (propertyExpression == null) + { + throw new ArgumentNullException("propertyExpression", + "Cannot assert collection ordering without specifying a property."); + } + + return Execute.Assertion + .ForCondition(!ReferenceEquals(Subject, null)) + .BecauseOf(because, args) + .FailWith("Expected collection to be ordered by {0}{reason} but found .", + propertyExpression.GetMemberPath()); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Collections/GenericCollectionAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Collections/GenericCollectionAssertions.cs.meta new file mode 100644 index 0000000..1f9a4d9 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Collections/GenericCollectionAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6c74836f9ce5f05409b98f2fe139288e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Collections/GenericDictionaryAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Collections/GenericDictionaryAssertions.cs new file mode 100644 index 0000000..94d2654 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Collections/GenericDictionaryAssertions.cs @@ -0,0 +1,956 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Linq.Expressions; +using FluentAssertions.Common; +using FluentAssertions.Execution; +using FluentAssertions.Primitives; + +namespace FluentAssertions.Collections +{ + /// + /// Contains a number of methods to assert that an is in the expected state. + /// + [DebuggerNonUserCode] + public class GenericDictionaryAssertions : + ReferenceTypeAssertions, GenericDictionaryAssertions> + { + public GenericDictionaryAssertions(IDictionary dictionary) + { + if (dictionary != null) + { + Subject = dictionary; + } + } + + #region HaveCount + + /// + /// Asserts that the number of items in the dictionary matches the supplied amount. + /// + /// The expected number of items. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> HaveCount(int expected, + string because = "", params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {0} item(s){reason}, but found {1}.", expected, Subject); + } + + int actualCount = Subject.Count; + + Execute.Assertion + .ForCondition((actualCount == expected)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} {0} to have {1} item(s){reason}, but found {2}.", Subject, expected, actualCount); + + return new AndConstraint>(this); + } + + /// + /// Asserts that the number of items in the dictionary matches a condition stated by a predicate. + /// + /// The predicate which must be satisfied by the amount of items. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> HaveCount(Expression> countPredicate, + string because = "", params object[] becauseArgs) + { + if (countPredicate == null) + { + throw new NullReferenceException("Cannot compare dictionary count against a predicate."); + } + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to have {0} items{reason}, but found {1}.", countPredicate.Body, Subject); + } + + Func compiledPredicate = countPredicate.Compile(); + + int actualCount = Subject.Count; + + if (!compiledPredicate(actualCount)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} {0} to have a count {1}{reason}, but count is {2}.", + Subject, countPredicate.Body, actualCount); + } + + return new AndConstraint>(this); + } + + #endregion + + #region BeEmpty + + /// + /// Asserts that the dictionary does not contain any items. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeEmpty(string because = "", params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to be empty{reason}, but found {0}.", Subject); + } + + Execute.Assertion + .ForCondition(!Subject.Any()) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to not have any items{reason}, but found {0}.", Subject.Count); + + return new AndConstraint>(this); + } + + /// + /// Asserts that the dictionary contains at least 1 item. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> NotBeEmpty(string because = "", + params object [] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} not to be empty{reason}, but found {0}.", Subject); + } + + Execute.Assertion + .ForCondition(Subject.Any()) + .BecauseOf(because, becauseArgs) + .FailWith("Expected one or more items{reason}, but found none."); + + return new AndConstraint>(this); + } + + #endregion + + #region Equal + + /// + /// Asserts that the current dictionary contains all the same key-value pairs as the + /// specified dictionary. Keys and values are compared using + /// their implementation. + /// + /// The expected dictionary + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> Equal(IDictionary expected, + string because = "", params object [] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to be equal to {0}{reason}, but found {1}.", expected, Subject); + } + + if (expected == null) + { + throw new ArgumentNullException("expected", "Cannot compare dictionary with ."); + } + + IEnumerable missingKeys = expected.Keys.Except(Subject.Keys); + IEnumerable additionalKeys = Subject.Keys.Except(expected.Keys); + + if (missingKeys.Any()) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to be equal to {0}{reason}, but could not find keys {1}.", expected, + missingKeys); + } + + if (additionalKeys.Any()) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to be equal to {0}{reason}, but found additional keys {1}.", expected, + additionalKeys); + } + + foreach (var key in expected.Keys) + { + Execute.Assertion + .ForCondition(Subject[key].IsSameOrEqualTo(expected[key])) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to be equal to {0}{reason}, but {1} differs at key {2}.", + expected, Subject, key); + } + + return new AndConstraint>(this); + } + + /// + /// Asserts the current dictionary not to contain all the same key-value pairs as the + /// specified dictionary. Keys and values are compared using + /// their implementation. + /// + /// The unexpected dictionary + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> NotEqual(IDictionary unexpected, + string because = "", params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected dictionaries not to be equal{reason}, but found {0}.", Subject); + } + + if (unexpected == null) + { + throw new ArgumentNullException("unexpected", "Cannot compare dictionary with ."); + } + + IEnumerable missingKeys = unexpected.Keys.Except(Subject.Keys); + IEnumerable additionalKeys = Subject.Keys.Except(unexpected.Keys); + + bool foundDifference = missingKeys.Any() + || additionalKeys.Any() + || (Subject.Keys.Any(key => !Subject[key].IsSameOrEqualTo(unexpected[key]))); + + if (!foundDifference) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect dictionaries {0} and {1} to be equal{reason}.", unexpected, Subject); + } + + return new AndConstraint>(this); + } + + #endregion + + #region ContainKey + + /// + /// Asserts that the dictionary contains the specified key. Keys are compared using + /// their implementation. + /// + /// The expected key + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public WhichValueConstraint ContainKey(TKey expected, + string because = "", params object [] becauseArgs) + { + AndConstraint> andConstraint = ContainKeys(new [] { expected }, because, becauseArgs); + + return new WhichValueConstraint(andConstraint.And, Subject[expected]); + } + + /// + /// Asserts that the dictionary contains all of the specified keys. Keys are compared using + /// their implementation. + /// + /// The expected keys + public AndConstraint> ContainKeys(params TKey[] expected) + { + return ContainKeys(expected, String.Empty); + } + + /// + /// Asserts that the dictionary contains all of the specified keys. Keys are compared using + /// their implementation. + /// + /// The expected keys + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> ContainKeys(IEnumerable expected, + string because = "", params object[] becauseArgs) + { + if (expected == null) + { + throw new NullReferenceException("Cannot verify key containment against a collection of keys"); + } + + TKey [] expectedKeys = expected.ToArray(); + + if (!expectedKeys.Any()) + { + throw new ArgumentException("Cannot verify key containment against an empty sequence"); + } + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to contain keys {0}{reason}, but found {1}.", expected, Subject); + } + + var missingKeys = expectedKeys.Where(key => !Subject.ContainsKey(key)); + + if (missingKeys.Any()) + { + if (expectedKeys.Count() > 1) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} {0} to contain key {1}{reason}, but could not find {2}.", Subject, + expected, missingKeys); + } + else + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} {0} to contain key {1}{reason}.", Subject, + expected.Cast().First()); + } + } + + return new AndConstraint>(this); + } + + #endregion + + #region NotContainKey + + /// + /// Asserts that the current dictionary does not contain the specified key. + /// Keys are compared using their implementation. + /// + /// The unexpected key + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> NotContainKey(TKey unexpected, + string because = "", params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} not to contain key {0}{reason}, but found {1}.", unexpected, Subject); + } + + if (Subject.ContainsKey(unexpected)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("{context:Dictionary} {0} should not contain key {1}{reason}, but found it anyhow.", Subject, unexpected); + } + + return new AndConstraint>(this); + } + + /// + /// Asserts that the dictionary does not contain any of the specified keys. Keys are compared using + /// their implementation. + /// + /// The unexpected keys + public AndConstraint> NotContainKeys(params TKey[] unexpected) + { + return NotContainKeys(unexpected, String.Empty); + } + + /// + /// Asserts that the dictionary does not contain any of the specified keys. Keys are compared using + /// their implementation. + /// + /// The unexpected keys + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> NotContainKeys(IEnumerable unexpected, + string because = "", params object[] becauseArgs) + { + if (unexpected == null) + { + throw new NullReferenceException("Cannot verify key containment against a collection of keys"); + } + + TKey[] unexpectedKeys = unexpected.ToArray(); + + if (!unexpectedKeys.Any()) + { + throw new ArgumentException("Cannot verify key containment against an empty sequence"); + } + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to contain keys {0}{reason}, but found {1}.", unexpected, Subject); + } + + var foundKeys = unexpectedKeys.Intersect(Subject.Keys); + + if (foundKeys.Any()) + { + if (unexpectedKeys.Count() > 1) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} {0} to not contain key {1}{reason}, but found {2}.", Subject, + unexpected, foundKeys); + } + else + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} {0} to not contain key {1}{reason}.", Subject, + unexpected.Cast().First()); + } + } + + return new AndConstraint>(this); + } + + #endregion + + #region ContainValue + + /// + /// Asserts that the dictionary contains the specified value. Values are compared using + /// their implementation. + /// + /// The expected value + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndWhichConstraint, TValue> ContainValue(TValue expected, + string because = "", params object[] becauseArgs) + { + AndWhichConstraint, IEnumerable> innerConstraint = + ContainValuesAndWhich(new[] {expected}, because, becauseArgs); + + return + new AndWhichConstraint + , TValue>( + innerConstraint.And, innerConstraint.Which); + } + + /// + /// Asserts that the dictionary contains all of the specified values. Values are compared using + /// their implementation. + /// + /// The expected values + public AndConstraint> ContainValues(params TValue[] expected) + { + return ContainValues(expected, String.Empty); + } + + /// + /// Asserts that the dictionary contains all of the specified values. Values are compared using + /// their implementation. + /// + /// The expected values + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> ContainValues(IEnumerable expected, + string because = "", params object[] becauseArgs) + { + return ContainValuesAndWhich(expected, because, becauseArgs); + } + + private AndWhichConstraint, IEnumerable> ContainValuesAndWhich(IEnumerable expected, string because = "", + params object[] becauseArgs) + { + if (expected == null) + { + throw new NullReferenceException("Cannot verify value containment against a collection of values"); + } + + TValue [] expectedValues = expected.ToArray(); + + if (!expectedValues.Any()) + { + throw new ArgumentException("Cannot verify value containment with an empty sequence"); + } + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to contain value {0}{reason}, but found {1}.", expected, Subject); + } + + var missingValues = expectedValues.Except(Subject.Values); + if (missingValues.Any()) + { + if (expectedValues.Length > 1) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} {0} to contain value {1}{reason}, but could not find {2}.", Subject, + expected, missingValues); + } + else + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} {0} to contain value {1}{reason}.", Subject, + expected.Cast().First()); + } + } + + return + new AndWhichConstraint + , + IEnumerable>(this, + RepetitionPreservingIntersect(Subject.Values, expectedValues)); + } + + /// + /// Returns an enumerable consisting of all items in the first collection also appearing in the second. + /// + /// Enumerable.Intersect is not suitable because it drops any repeated elements. + private IEnumerable RepetitionPreservingIntersect( + IEnumerable first, IEnumerable second) + { + var secondSet = new HashSet(second); + return first.Where(secondSet.Contains); + } + + #endregion + + #region NotContainValue + + /// + /// Asserts that the current dictionary does not contain the specified value. + /// Values are compared using their implementation. + /// + /// The unexpected value + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> NotContainValue(TValue unexpected, + string because = "", params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} not to contain value {0}{reason}, but found {1}.", unexpected, Subject); + } + + if (Subject.Values.Contains(unexpected)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("{context:Dictionary} {0} should not contain value {1}{reason}, but found it anyhow.", Subject, unexpected); + } + + return new AndConstraint>(this); + } + + /// + /// Asserts that the dictionary does not contain any of the specified values. Values are compared using + /// their implementation. + /// + /// The unexpected values + public AndConstraint> NotContainValues(params TValue[] unexpected) + { + return NotContainValues(unexpected, String.Empty); + } + + /// + /// Asserts that the dictionary does not contain any of the specified values. Values are compared using + /// their implementation. + /// + /// The unexpected values + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> NotContainValues(IEnumerable unexpected, + string because = "", params object[] becauseArgs) + { + if (unexpected == null) + { + throw new NullReferenceException("Cannot verify value containment against a collection of values"); + } + + var unexpectedValues = unexpected.ToArray(); + + if (!unexpectedValues.Any()) + { + throw new ArgumentException("Cannot verify value containment with an empty sequence"); + } + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to not contain value {0}{reason}, but found {1}.", unexpected, Subject); + } + + var foundValues = unexpectedValues.Intersect(Subject.Values); + if (foundValues.Any()) + { + if (unexpectedValues.Length > 1) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} {0} to not contain value {1}{reason}, but found {2}.", Subject, + unexpected, foundValues); + } + else + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} {0} to not contain value {1}{reason}.", Subject, + unexpected.Cast().First()); + } + } + + return new AndConstraint>(this); + } + + #endregion + + #region Contain + + /// + /// Asserts that the current dictionary contains the specified . + /// Keys and values are compared using their implementation. + /// + /// The expected key/value pairs. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> Contain(IEnumerable> expected, + string because = "", params object[] becauseArgs) + { + if (expected == null) + { + throw new ArgumentNullException("expected", "Cannot compare dictionary with ."); + } + + KeyValuePair[] expectedKeyValuePairs = expected.ToArray(); + + if (!expectedKeyValuePairs.Any()) + { + throw new ArgumentException("Cannot verify key containment against an empty collection of key/value pairs"); + } + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to contain key/value pairs {0}{reason}, but dictionary is {1}.", expected, Subject); + } + + var expectedKeys = expectedKeyValuePairs.Select(keyValuePair => keyValuePair.Key).ToArray(); + var missingKeys = expectedKeys.Where(key => !Subject.ContainsKey(key)); + + if (missingKeys.Any()) + { + if (expectedKeyValuePairs.Count() > 1) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} {0} to contain key(s) {1}{reason}, but could not find keys {2}.", Subject, + expectedKeys, missingKeys); + } + else + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} {0} to contain key {1}{reason}.", Subject, + expectedKeys.Cast().First()); + } + } + + KeyValuePair[] keyValuePairsNotSameOrEqualInSubject = expectedKeyValuePairs.Where(keyValuePair => !Subject[keyValuePair.Key].IsSameOrEqualTo(keyValuePair.Value)).ToArray(); + + if (keyValuePairsNotSameOrEqualInSubject.Any()) + { + if (keyValuePairsNotSameOrEqualInSubject.Count() > 1) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to contain {0}{reason}, but {context:dictionary} differs at keys {1}.", + expectedKeyValuePairs, keyValuePairsNotSameOrEqualInSubject.Select(keyValuePair => keyValuePair.Key)); + } + else + { + var expectedKeyValuePair = keyValuePairsNotSameOrEqualInSubject.First(); + TValue actual = Subject[expectedKeyValuePair.Key]; + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to contain value {0} at key {1}{reason}, but found {2}.", expectedKeyValuePair.Value, expectedKeyValuePair.Key, actual); + } + } + + return new AndConstraint>(this); + } + + /// + /// Asserts that the current dictionary contains the specified . + /// Keys and values are compared using their implementation. + /// + /// The expected + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> Contain(KeyValuePair expected, + string because = "", params object[] becauseArgs) + { + return Contain(expected.Key, expected.Value, because, becauseArgs); + } + + /// + /// Asserts that the current dictionary contains the specified for the supplied . Values are compared using their implementation. + /// + /// The key for which to validate the value + /// The value to validate + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> Contain(TKey key, TValue value, + string because = "", params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to contain value {0} at key {1}{reason}, but dictionary is {2}.", value, key, + Subject); + } + + if (Subject.ContainsKey(key)) + { + TValue actual = Subject[key]; + + Execute.Assertion + .ForCondition(actual.IsSameOrEqualTo(value)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to contain value {0} at key {1}{reason}, but found {2}.", value, key, actual); + } + else + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to contain value {0} at key {1}{reason}, but the key was not found.", value, + key); + } + + return new AndConstraint>(this); + } + + #endregion + + #region NotContain + + /// + /// Asserts that the current dictionary does not contain the specified . + /// Keys and values are compared using their implementation. + /// + /// The unexpected key/value pairs + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> NotContain(IEnumerable> items, + string because = "", params object[] becauseArgs) + { + if (items == null) + { + throw new ArgumentNullException("items", "Cannot compare dictionary with ."); + } + + KeyValuePair[] keyValuePairs = items.ToArray(); + + if (!keyValuePairs.Any()) + { + throw new ArgumentException("Cannot verify key containment against an empty collection of key/value pairs"); + } + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to not contain key/value pairs {0}{reason}, but dictionary is {1}.", items, Subject); + } + + var keyValuePairsFound = keyValuePairs.Where(keyValuePair => Subject.ContainsKey(keyValuePair.Key)).ToArray(); + + if (keyValuePairsFound.Any()) + { + var keyValuePairsSameOrEqualInSubject = keyValuePairsFound.Where(keyValuePair => Subject[keyValuePair.Key].IsSameOrEqualTo(keyValuePair.Value)).ToArray(); + + if (keyValuePairsSameOrEqualInSubject.Any()) + { + if (keyValuePairsSameOrEqualInSubject.Count() > 1) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to not contain key/value pairs {0}{reason}, but found them anyhow.", keyValuePairs); + } + else + { + var keyValuePair = keyValuePairsSameOrEqualInSubject.First(); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} to not contain value {0} at key {1}{reason}, but found it anyhow.", keyValuePair.Value, keyValuePair.Key); + } + } + } + + return new AndConstraint>(this); + } + + /// + /// Asserts that the current dictionary does not contain the specified . + /// Keys and values are compared using their implementation. + /// + /// The unexpected + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> NotContain(KeyValuePair item, + string because = "", params object[] becauseArgs) + { + return NotContain(item.Key, item.Value, because, becauseArgs); + } + + /// + /// Asserts that the current dictionary does not contain the specified for the + /// supplied . Values are compared using their implementation. + /// + /// The key for which to validate the value + /// The value to validate + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> NotContain(TKey key, TValue value, + string because = "", params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} not to contain value {0} at key {1}{reason}, but dictionary is {2}.", value, + key, Subject); + } + + if (Subject.ContainsKey(key)) + { + TValue actual = Subject[key]; + + Execute.Assertion + .ForCondition(!actual.IsSameOrEqualTo(value)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:dictionary} not to contain value {0} at key {1}{reason}, but found it anyhow.", value, key); + } + + return new AndConstraint>(this); + } + + #endregion + + /// + /// Returns the type of the subject the assertion applies on. + /// + protected override string Context + { + get { return "dictionary"; } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Collections/GenericDictionaryAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Collections/GenericDictionaryAssertions.cs.meta new file mode 100644 index 0000000..81b23b8 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Collections/GenericDictionaryAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a2d83e910d6c7d94f93246e77c9aa885 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Collections/NonGenericCollectionAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Collections/NonGenericCollectionAssertions.cs new file mode 100644 index 0000000..4ecea8e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Collections/NonGenericCollectionAssertions.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections; +using System.Diagnostics; +using System.Linq; +using System.Linq.Expressions; +using FluentAssertions.Execution; + +namespace FluentAssertions.Collections +{ + /// + /// Contains a number of methods to assert that an is in the expected state. + /// + [DebuggerNonUserCode] + public class NonGenericCollectionAssertions : CollectionAssertions + { + public NonGenericCollectionAssertions(IEnumerable collection) + { + if (collection != null) + { + Subject = collection; + } + } + + /// + /// Asserts that the number of items in the collection matches the supplied amount. + /// + /// The expected number of items in the collection. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveCount(int expected, string because = "", params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to contain {0} item(s){reason}, but found .", expected); + } + + int actualCount = GetMostLocalCount(); + + Execute.Assertion + .ForCondition(actualCount == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to contain {0} item(s){reason}, but found {1}.", expected, actualCount); + + return new AndConstraint(this); + } + + /// + /// Asserts that the number of items in the collection matches a condition stated by the . + /// + /// A predicate that yields the number of items that is expected to be in the collection. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveCount(Expression> countPredicate, string because = "", + params object[] becauseArgs) + { + if (countPredicate == null) + { + throw new NullReferenceException("Cannot compare collection count against a predicate."); + } + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to contain {0} items{reason}, but found {1}.", countPredicate.Body, Subject); + } + + Func compiledPredicate = countPredicate.Compile(); + + int actualCount = GetMostLocalCount(); + + if (!compiledPredicate(actualCount)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} {0} to have a count {1}{reason}, but count is {2}.", + Subject, countPredicate.Body, actualCount); + } + + return new AndConstraint(this); + } + + private int GetMostLocalCount() + { + ICollection castSubject = Subject as ICollection; + if (castSubject != null) + { + return castSubject.Count; + } + else + { + return Subject.Cast().Count(); + } + } + + /// + /// Asserts that the current collection contains the specified object. Elements are compared + /// using their implementation. + /// + /// An object, or of objects that are expected to be in the collection. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Contain(object expected, string because = "", + params object [] becauseArgs) + { + if (expected is IEnumerable) + { + return base.Contain((IEnumerable) expected, because, becauseArgs); + } + + return base.Contain(new [] { expected }, because, becauseArgs); + } + + /// + /// Asserts that the current collection does not contain the supplied item. + /// Elements are compared using their implementation. + /// + /// The element that is not expected to be in the collection + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotContain(object unexpected, string because = "", + params object[] becauseArgs) + { + if (unexpected is IEnumerable) + { + return base.NotContain((IEnumerable)unexpected, because, becauseArgs); + } + + return base.NotContain(new[] { unexpected }, because, becauseArgs); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Collections/NonGenericCollectionAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Collections/NonGenericCollectionAssertions.cs.meta new file mode 100644 index 0000000..2a680f6 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Collections/NonGenericCollectionAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: de22e71c6e18c5943918af14af5a1e85 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Collections/SelfReferencingCollectionAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Collections/SelfReferencingCollectionAssertions.cs new file mode 100644 index 0000000..2e2cc62 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Collections/SelfReferencingCollectionAssertions.cs @@ -0,0 +1,510 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Linq.Expressions; +using FluentAssertions.Common; +using FluentAssertions.Execution; + +namespace FluentAssertions.Collections +{ + /// + /// Contains a number of methods to assert that an is in the expectation state. + /// + public class SelfReferencingCollectionAssertions : CollectionAssertions, TAssertions> + where TAssertions : SelfReferencingCollectionAssertions + { + public SelfReferencingCollectionAssertions(IEnumerable actualValue) + { + if (actualValue != null) + { + Subject = actualValue; + } + } + + /// + /// Asserts that the number of items in the collection matches the supplied amount. + /// + /// The expected number of items in the collection. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveCount(int expected, string because = "", params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to contain {0} item(s){reason}, but found .", expected); + } + + int actualCount = Subject.Count(); + + Execute.Assertion + .ForCondition(actualCount == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to contain {0} item(s){reason}, but found {1}.", expected, actualCount); + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the number of items in the collection matches a condition stated by the . + /// + /// A predicate that yields the number of items that is expected to be in the collection. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveCount(Expression> countPredicate, string because = "", + params object[] becauseArgs) + { + if (countPredicate == null) + { + throw new NullReferenceException("Cannot compare collection count against a predicate."); + } + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to contain {0} items{reason}, but found {1}.", countPredicate.Body, Subject); + } + + Func compiledPredicate = countPredicate.Compile(); + + int actualCount = Subject.Count(); + + if (!compiledPredicate(actualCount)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} {0} to have a count {1}{reason}, but count is {2}.", + Subject, countPredicate.Body, actualCount); + } + + return new AndConstraint((TAssertions)this); + } + + /// + /// Expects the current collection to contain all the same elements in the same order as the collection identified by + /// . Elements are compared using their method. + /// + /// A params array with the expected elements. + public AndConstraint Equal(params T[] elements) + { + return Equal(elements, String.Empty); + } + + /// + /// Asserts that two collections contain the same items in the same order, where equality is determined using a + /// . + /// + /// + /// The collection to compare the subject with. + /// + /// + /// A equality comparison the is used to determine whether two objects should be treated as equal. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Equal( + IEnumerable expectation, Func equalityComparison, string because = "", params object[] becauseArgs) + { + AssertSubjectEquality(expectation, equalityComparison, because, becauseArgs); + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the current collection starts with same elements in the same order as the collection identified by + /// . Elements are compared using their . + /// + /// + /// A collection of expected elements. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint StartWith(IEnumerable expectation, string because = "", params object[] becauseArgs) + { + if (expectation == null) + { + return base.StartWith(null, because, becauseArgs); + } + + AssertCollectionStartsWith(Subject, expectation.ToArray(), EqualityComparer.Default.Equals, because, becauseArgs); + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the current collection starts with same elements in the same order as the collection identified by + /// . Elements are compared using . + /// + /// + /// A collection of expected elements. + /// + /// + /// A equality comparison the is used to determine whether two objects should be treated as equal. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint StartWith( + IEnumerable expectation, Func equalityComparison, string because = "", params object[] becauseArgs) + { + if (expectation == null) + { + throw new ArgumentNullException("expectation", "Cannot compare collection with ."); + } + + AssertCollectionStartsWith(Subject, expectation.ToArray(), equalityComparison, because, becauseArgs); + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the current collection ends with same elements in the same order as the collection identified by + /// . Elements are compared using their . + /// + /// + /// A collection of expected elements. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint EndWith(IEnumerable expectation, string because = "", params object[] becauseArgs) + { + if (expectation == null) + { + return base.EndWith(null, because, becauseArgs); + } + + AssertCollectionEndsWith(Subject, expectation.ToArray(), EqualityComparer.Default.Equals, because, becauseArgs); + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the current collection ends with same elements in the same order as the collection identified by + /// . Elements are compared using . + /// + /// + /// A collection of expected elements. + /// + /// + /// A equality comparison the is used to determine whether two objects should be treated as equal. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint EndWith( + IEnumerable expectation, Func equalityComparison, string because = "", params object[] becauseArgs) + { + if (expectation == null) + { + throw new ArgumentNullException("expectation", "Cannot compare collection with ."); + } + + AssertCollectionEndsWith(Subject, expectation.ToArray(), equalityComparison, because, becauseArgs); + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the collection contains the specified item. + /// + /// The expectation item. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public AndWhichConstraint Contain(T expected, string because = "", params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to contain {0}{reason}, but found {1}.", expected, Subject); + } + + if (!Subject.Contains(expected)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} {0} to contain {1}{reason}.", Subject, expected); + } + + return new AndWhichConstraint((TAssertions) this, + Subject.Where( + item => EqualityComparer.Default.Equals(item, expected))); + } + + /// + /// Asserts that the collection contains some extra items in addition to the original items. + /// + /// An of expectation items. + /// Additional items that are expectation to be contained by the collection. + public AndConstraint Contain(IEnumerable expectedItemsList, + params T [] additionalExpectedItems) + { + var list = new List(expectedItemsList); + list.AddRange(additionalExpectedItems); + + return Contain((IEnumerable)list); + } + + /// + /// Asserts that the collection contains at least one item that matches the predicate. + /// + /// A predicate to match the items in the collection against. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public AndWhichConstraint Contain(Expression> predicate, string because = "", params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to contain {0}{reason}, but found {1}.", predicate.Body, Subject); + } + + Func func = predicate.Compile(); + + Execute.Assertion + .ForCondition(Subject.Any(func)) + .BecauseOf(because, becauseArgs) + .FailWith("{context:Collection} {0} should have an item matching {1}{reason}.", Subject, predicate.Body); + + return new AndWhichConstraint((TAssertions)this, Subject.Where(func)); + } + + /// + /// Asserts that the collection only contains items that match a predicate. + /// + /// A predicate to match the items in the collection against. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public AndConstraint OnlyContain( + Expression> predicate, string because = "", params object[] becauseArgs) + { + Func compiledPredicate = predicate.Compile(); + + Execute.Assertion + .ForCondition(Subject.Any()) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to contain only items matching {0}{reason}, but the collection is empty.", + predicate.Body); + + IEnumerable mismatchingItems = Subject.Where(item => !compiledPredicate(item)); + if (mismatchingItems.Any()) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to contain only items matching {0}{reason}, but {1} do(es) not match.", + predicate.Body, mismatchingItems); + } + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the current collection does not contain the supplied item. + /// + /// The element that is not expected to be in the collection + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public AndWhichConstraint NotContain(T unexpected, string because = "", params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to not contain {0}{reason}, but found .", unexpected); + } + + if (Subject.Contains(unexpected)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} {0} to not contain {1}{reason}.", Subject, unexpected); + } + + return new AndWhichConstraint((TAssertions)this, + Subject.Where( + item => !EqualityComparer.Default.Equals(item, unexpected))); + } + + /// + /// Asserts that the collection does not contain some extra items in addition to the original items. + /// + /// An of unexpected items. + /// Additional items that are not expected to be contained by the collection. + public AndConstraint NotContain(IEnumerable unexpectedItemsList, params T[] additionalUnexpectedItems) + { + var list = new List(unexpectedItemsList); + list.AddRange(additionalUnexpectedItems); + return NotContain((IEnumerable)list); + } + + /// + /// Asserts that the collection does not contain any items that match the predicate. + /// + /// A predicate to match the items in the collection against. + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public AndConstraint NotContain(Expression> predicate, string because = "", params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} not to contain {0}{reason}, but found {1}.", predicate.Body, Subject); + } + + if (Subject.Any(item => predicate.Compile()(item))) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:Collection} {0} to not have any items matching {1}{reason}.", Subject, predicate.Body); + } + + return new AndConstraint((TAssertions)this); + } + + /// + /// Expects the current collection to contain only a single item. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndWhichConstraint ContainSingle(string because = "", params object[] becauseArgs) + { + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:collection} to contain a single item{reason}, but found ."); + } + + switch (Subject.Count()) + { + case 0: //Fail, Collection is empty + Execute.Assertion.BecauseOf(because, becauseArgs).FailWith("Expected {context:collection} to contain a single item{reason}, but the collection is empty."); + break; + case 1: //Success Condition + break; + default: // Fail, Collection contains more than a single item + Execute.Assertion.BecauseOf(because, becauseArgs).FailWith("Expected {context:collection} to contain a single item{reason}, but found {0}.", Subject); + break; + } + + return new AndWhichConstraint((TAssertions)this, Subject.Single()); + } + + /// + /// Expects the current collection to contain only a single item matching the specified . + /// + /// The predicate that will be used to find the matching items. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndWhichConstraint ContainSingle(Expression> predicate, + string because = "", params object[] becauseArgs) + { + string expectationPrefix = + string.Format("Expected {{context:collection}} to contain a single item matching {0}{{reason}}, ", predicate.Body); + + if (ReferenceEquals(Subject, null)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith(expectationPrefix + "but found {0}.", Subject); + } + + T[] actualItems = Subject.ToArray(); + Execute.Assertion + .ForCondition(actualItems.Any()) + .BecauseOf(because, becauseArgs) + .FailWith(expectationPrefix + "but the collection is empty."); + + T[] matchingElements = actualItems.Where(predicate.Compile()).ToArray(); + int count = matchingElements.Count(); + if (count == 0) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith(expectationPrefix + "but no such item was found."); + } + else if (count > 1) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith(expectationPrefix + "but " + count + " such items were found."); + } + else + { + // Exactly 1 item was expected + } + + return new AndWhichConstraint((TAssertions) this, matchingElements); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Collections/SelfReferencingCollectionAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Collections/SelfReferencingCollectionAssertions.cs.meta new file mode 100644 index 0000000..726012d --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Collections/SelfReferencingCollectionAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e2508434680523441854da51170b5171 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Collections/SortOrder.cs b/Assets/Plugins/FluentAssertions/Core/Collections/SortOrder.cs new file mode 100644 index 0000000..bb333dd --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Collections/SortOrder.cs @@ -0,0 +1,8 @@ +namespace FluentAssertions.Collections +{ + internal enum SortOrder + { + Ascending, + Descending + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Collections/SortOrder.cs.meta b/Assets/Plugins/FluentAssertions/Core/Collections/SortOrder.cs.meta new file mode 100644 index 0000000..654b215 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Collections/SortOrder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b9573eff8891b75468bbfde5a736ebb3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Collections/StringCollectionAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Collections/StringCollectionAssertions.cs new file mode 100644 index 0000000..72f5583 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Collections/StringCollectionAssertions.cs @@ -0,0 +1,142 @@ +using System.Collections.Generic; +using System.Linq; + +namespace FluentAssertions.Collections +{ + public class StringCollectionAssertions : + SelfReferencingCollectionAssertions + { + public StringCollectionAssertions(IEnumerable actualValue) + : base(actualValue) + { + } + + /// + /// Expects the current collection to contain all the same elements in the same order as the collection identified by + /// . Elements are compared using their . + /// + /// An with the expected elements. + public new AndConstraint Equal(params string[] expected) + { + return base.Equal(expected.AsEnumerable()); + } + + /// + /// Expects the current collection to contain all the same elements in the same order as the collection identified by + /// . Elements are compared using their . + /// + /// An with the expected elements. + public AndConstraint Equal(IEnumerable expected) + { + return base.Equal(expected); + } + + /// + /// Expects the current collection to contain all elements of the collection identified by , + /// regardless of the order. Elements are compared using their . + /// + /// A params array with the expected elements. + public AndConstraint BeEquivalentTo(params string[] elements) + { + return base.BeEquivalentTo(elements.AsEnumerable()); + } + + /// + /// Expects the current collection to contain all elements of the collection identified by , + /// regardless of the order. Elements are compared using their . + /// + /// An with the expected elements. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeEquivalentTo(IEnumerable expected, string because = "", + params object[] becauseArgs) + { + return base.BeEquivalentTo(expected, because, becauseArgs); + } + + /// + /// Expects the current collection to contain the specified elements in the exact same order. Elements are compared + /// using their implementation. + /// + /// An with the expected elements. + public AndConstraint ContainInOrder(params string[] expected) + { + return base.ContainInOrder(expected.AsEnumerable()); + } + + /// + /// Expects the current collection to contain the specified elements in the exact same order. Elements are compared + /// using their implementation. + /// + /// An with the expected elements. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint ContainInOrder(IEnumerable expected, string because = "", + params object[] becauseArgs) + { + return base.ContainInOrder(expected, because, becauseArgs); + } + + /// + /// Expects the current collection to contain the specified elements in any order. Elements are compared + /// using their implementation. + /// + /// An with the expected elements. + public AndConstraint Contain(IEnumerable expected) + { + return base.Contain(expected); + } + + /// + /// Expects the current collection to contain the specified elements in any order. Elements are compared + /// using their implementation. + /// + /// An with the expected elements. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Contain(IEnumerable expected, string because = null, + object becauseArg = null, + params object[] becauseArgs) + { + var args = new List {becauseArg}; + args.AddRange(becauseArgs); + return base.Contain(expected, because, args.ToArray()); + } + + /// + /// Asserts that the current collection does not contain the supplied items. Elements are compared + /// using their implementation. + /// + /// An with the unexpected elements. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotContain(IEnumerable unexpected, string because = null, + object becauseArg = null, + params object[] becauseArgs) + { + var args = new List { becauseArg }; + args.AddRange(becauseArgs); + return base.NotContain(unexpected, because, args.ToArray()); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Collections/StringCollectionAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Collections/StringCollectionAssertions.cs.meta new file mode 100644 index 0000000..1f61c23 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Collections/StringCollectionAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fdd029d38fc6058428a32d24d7f31d95 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Collections/WhichValueConstraint.cs b/Assets/Plugins/FluentAssertions/Core/Collections/WhichValueConstraint.cs new file mode 100644 index 0000000..86d29e2 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Collections/WhichValueConstraint.cs @@ -0,0 +1,16 @@ +namespace FluentAssertions.Collections +{ + public class WhichValueConstraint : AndConstraint> + { + public WhichValueConstraint(GenericDictionaryAssertions parentConstraint, TValue value) + : base(parentConstraint) + { + WhichValue = value; + } + + /// + /// Gets the value of the object referred to by the key. + /// + public TValue WhichValue { get; private set; } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Collections/WhichValueConstraint.cs.meta b/Assets/Plugins/FluentAssertions/Core/Collections/WhichValueConstraint.cs.meta new file mode 100644 index 0000000..39f9cb4 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Collections/WhichValueConstraint.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3376827f16b8c1e4faa1ef2afb619a45 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common.meta b/Assets/Plugins/FluentAssertions/Core/Common.meta new file mode 100644 index 0000000..a519e80 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b36f4b23e0c35f544832fd6c9b9a3b07 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/CSharpAccessModifier.cs b/Assets/Plugins/FluentAssertions/Core/Common/CSharpAccessModifier.cs new file mode 100644 index 0000000..487baa0 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/CSharpAccessModifier.cs @@ -0,0 +1,12 @@ +namespace FluentAssertions.Common +{ + public enum CSharpAccessModifier + { + Public, + Private, + Protected, + Internal, + ProtectedInternal, + InvalidForCSharp + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Common/CSharpAccessModifier.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/CSharpAccessModifier.cs.meta new file mode 100644 index 0000000..4e692ce --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/CSharpAccessModifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2d04a64bd8a684e4b9f3b947eec67fd3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/CSharpAccessModifierExtensions.cs b/Assets/Plugins/FluentAssertions/Core/Common/CSharpAccessModifierExtensions.cs new file mode 100644 index 0000000..3669be7 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/CSharpAccessModifierExtensions.cs @@ -0,0 +1,98 @@ +using System; +using System.Reflection; + +namespace FluentAssertions.Common +{ + public static class CSharpAccessModifierExtensions + { + internal static CSharpAccessModifier GetCSharpAccessModifier(this MethodBase methodBase) + { + if (methodBase.IsPrivate) + { + return CSharpAccessModifier.Private; + } + + if (methodBase.IsFamily) + { + return CSharpAccessModifier.Protected; + } + + if (methodBase.IsAssembly) + { + return CSharpAccessModifier.Internal; + } + + if (methodBase.IsPublic) + { + return CSharpAccessModifier.Public; + } + + if (methodBase.IsFamilyOrAssembly) + { + return CSharpAccessModifier.ProtectedInternal; + } + + return CSharpAccessModifier.InvalidForCSharp; + } + + internal static CSharpAccessModifier GetCSharpAccessModifier(this FieldInfo fieldInfo) + { + if (fieldInfo.IsPrivate) + { + return CSharpAccessModifier.Private; + } + + if (fieldInfo.IsFamily) + { + return CSharpAccessModifier.Protected; + } + + if (fieldInfo.IsAssembly) + { + return CSharpAccessModifier.Internal; + } + + if (fieldInfo.IsPublic) + { + return CSharpAccessModifier.Public; + } + + if (fieldInfo.IsFamilyOrAssembly) + { + return CSharpAccessModifier.ProtectedInternal; + } + + return CSharpAccessModifier.InvalidForCSharp; + } + + internal static CSharpAccessModifier GetCSharpAccessModifier(this Type type) + { + if (type.GetTypeInfo().IsNestedPrivate) + { + return CSharpAccessModifier.Private; + } + + if (type.GetTypeInfo().IsNestedFamily) + { + return CSharpAccessModifier.Protected; + } + + if (type.GetTypeInfo().IsNestedAssembly || (type.GetTypeInfo().IsClass && type.GetTypeInfo().IsNotPublic)) + { + return CSharpAccessModifier.Internal; + } + + if (type.GetTypeInfo().IsPublic || type.GetTypeInfo().IsNestedPublic) + { + return CSharpAccessModifier.Public; + } + + if (type.GetTypeInfo().IsNestedFamORAssem) + { + return CSharpAccessModifier.ProtectedInternal; + } + + return CSharpAccessModifier.InvalidForCSharp; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Common/CSharpAccessModifierExtensions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/CSharpAccessModifierExtensions.cs.meta new file mode 100644 index 0000000..e306ad3 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/CSharpAccessModifierExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8abdb6349d8251345a0ac392d6dae0b3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/Configuration.cs b/Assets/Plugins/FluentAssertions/Core/Common/Configuration.cs new file mode 100644 index 0000000..57308da --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/Configuration.cs @@ -0,0 +1,99 @@ +using System; + +using FluentAssertions.Formatting; + +namespace FluentAssertions.Common +{ + public class Configuration + { + #region Private Definitions + + private readonly IConfigurationStore store; + private string valueFormatterAssembly; + private ValueFormatterDetectionMode? valueFormatterDetectionMode; + + #endregion + + /// + /// Gets the active configuration, + /// + public static Configuration Current + { + get { return Services.Configuration; } + } + + public Configuration(IConfigurationStore store) + { + this.store = store; + } + + /// + /// Gets or sets the mode on how Fluent Assertions will find custom implementations of + /// . + /// + public ValueFormatterDetectionMode ValueFormatterDetectionMode + { + get + { + if (!valueFormatterDetectionMode.HasValue) + { + valueFormatterDetectionMode = DetermineFormatterDetectionMode(); + } + + return valueFormatterDetectionMode.Value; + } + set { valueFormatterDetectionMode = value; } + } + + private ValueFormatterDetectionMode DetermineFormatterDetectionMode() + { + if (ValueFormatterAssembly != null) + { + return ValueFormatterDetectionMode.Specific; + } + + string setting = store.GetSetting("valueFormatters"); + if (!string.IsNullOrEmpty(setting)) + { + try + { + return (ValueFormatterDetectionMode)Enum.Parse(typeof(ValueFormatterDetectionMode), setting, true); + } + catch (ArgumentException) + { + throw new InvalidOperationException(string.Format( + "'{0}' is not a valid option for detecting value formatters. Valid options include Disabled, Specific and Scan.", + setting)); + } + } + + return ValueFormatterDetectionMode.Disabled; + } + + /// + /// Gets or sets the assembly name to scan for custom value formatters in case + /// is set to . + /// + public string ValueFormatterAssembly + { + get + { + if (valueFormatterAssembly == null) + { + string assemblyName = store.GetSetting("valueFormattersAssembly"); + if (!string.IsNullOrEmpty(assemblyName)) + { + valueFormatterAssembly = assemblyName; + } + } + + return valueFormatterAssembly; + } + set + { + valueFormatterAssembly = value; + valueFormatterDetectionMode = null; + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Common/Configuration.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/Configuration.cs.meta new file mode 100644 index 0000000..b3883ff --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/Configuration.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d0b5c08b75cb08c459451f31b09f2634 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/DateTimeExtensions.cs b/Assets/Plugins/FluentAssertions/Core/Common/DateTimeExtensions.cs new file mode 100644 index 0000000..4a5d236 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/DateTimeExtensions.cs @@ -0,0 +1,20 @@ +using System; + +namespace FluentAssertions.Common +{ + public static class DateTimeExtensions + { + /// + /// Converts an existing to a but normalizes the + /// so that comparisons of converted instances retain the UTC/local agnostic behavior. + /// + public static DateTimeOffset ToDateTimeOffset(this DateTime dateTime) + { + return dateTime.ToDateTimeOffset(TimeSpan.Zero); + } + public static DateTimeOffset ToDateTimeOffset(this DateTime dateTime, TimeSpan offset) + { + return new DateTimeOffset(DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified) , offset); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Common/DateTimeExtensions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/DateTimeExtensions.cs.meta new file mode 100644 index 0000000..0415be8 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/DateTimeExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8aa38bb89f1e31846b6938f4b6f5ee23 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/EnumerableExtensions.cs b/Assets/Plugins/FluentAssertions/Core/Common/EnumerableExtensions.cs new file mode 100644 index 0000000..d3a4091 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/EnumerableExtensions.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; + +namespace FluentAssertions.Common +{ + internal static class EnumerableExtensions + { + /// + /// Searches for the first different element in two sequences using specified + /// + /// The type of the elements of the sequence. + /// The type of the elements of the sequence. + /// The first sequence to compare. + /// The second sequence to compare. + /// Method that is used to compare 2 elements with the same index. + /// Index at which two sequences have elements that are not equal, or -1 if enumerables are equal + public static int IndexOfFirstDifferenceWith(this IEnumerable first, IEnumerable second, Func equalityComparison) + { + using (IEnumerator firstEnumerator = first.GetEnumerator()) + using (IEnumerator secondEnumerator = second.GetEnumerator()) + { + int index = 0; + while (true) + { + bool isFirstCompleted = !firstEnumerator.MoveNext(); + bool isSecondCompleted = !secondEnumerator.MoveNext(); + + if (isFirstCompleted && isSecondCompleted) + { + return -1; + } + + if (isFirstCompleted ^ isSecondCompleted) + { + return index; + } + + if (!equalityComparison(firstEnumerator.Current, secondEnumerator.Current)) + { + return index; + } + + index++; + } + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Common/EnumerableExtensions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/EnumerableExtensions.cs.meta new file mode 100644 index 0000000..7df6991 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/EnumerableExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5164a73abebc6bd449c050e267437015 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/ExpressionExtensions.cs b/Assets/Plugins/FluentAssertions/Core/Common/ExpressionExtensions.cs new file mode 100644 index 0000000..7178929 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/ExpressionExtensions.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; + +using FluentAssertions.Equivalency; + +namespace FluentAssertions.Common +{ + public static class ExpressionExtensions + { + public static SelectedMemberInfo GetSelectedMemberInfo(this Expression> expression) + { + if (ReferenceEquals(expression, null)) + { + throw new NullReferenceException("Expected an expression, but found ."); + } + + MemberInfo memberInfo = AttemptToGetMemberInfoFromCastExpression(expression) ?? + AttemptToGetMemberInfoFromMemberExpression(expression); + + if (memberInfo != null) + { + var propertyInfo = memberInfo as PropertyInfo; + if (propertyInfo != null) + { + return SelectedMemberInfo.Create(propertyInfo); + } + + var fieldInfo = memberInfo as FieldInfo; + if (fieldInfo != null) + { + return SelectedMemberInfo.Create(fieldInfo); + } + } + + throw new ArgumentException( + string.Format("Expression <{0}> cannot be used to select a member.", expression.Body)); + } + + public static PropertyInfo GetPropertyInfo(this Expression> expression) + { + if (ReferenceEquals(expression, null)) + { + throw new NullReferenceException("Expected a property expression, but found ."); + } + + var memberInfo = AttemptToGetMemberInfoFromCastExpression(expression) ?? + AttemptToGetMemberInfoFromMemberExpression(expression); + + var propertyInfo = memberInfo as PropertyInfo; + + if (propertyInfo == null) + { + throw new ArgumentException("Cannot use <" + expression.Body + "> when a property expression is expected."); + } + + return propertyInfo; + } + + private static MemberInfo AttemptToGetMemberInfoFromMemberExpression( + Expression> expression) + { + var memberExpression = expression.Body as MemberExpression; + if (memberExpression != null) + { + return memberExpression.Member; + } + + return null; + } + + private static MemberInfo AttemptToGetMemberInfoFromCastExpression(Expression> expression) + { + var castExpression = expression.Body as UnaryExpression; + if (castExpression != null) + { + return ((MemberExpression)castExpression.Operand).Member; + } + + return null; + } + + /// + /// Gets a dotted path of property names representing the property expression. E.g. Parent.Child.Sibling.Name. + /// + public static string GetMemberPath( + this Expression> expression) + { + var segments = new List(); + Expression node = expression; + + if (node == null) + { + throw new NullReferenceException("Expected an expression, but found ."); + } + + var unsupportedExpressionMessage = $"Expression <{expression.Body}> cannot be used to select a member."; + + while (node != null) + { + switch (node.NodeType) + { + case ExpressionType.Lambda: + node = ((LambdaExpression)node).Body; + break; + + case ExpressionType.Convert: + case ExpressionType.ConvertChecked: + var unaryExpression = (UnaryExpression)node; + node = unaryExpression.Operand; + break; + + case ExpressionType.MemberAccess: + var memberExpression = (MemberExpression)node; + node = memberExpression.Expression; + + segments.Add(memberExpression.Member.Name); + break; + + case ExpressionType.ArrayIndex: + var binaryExpression = (BinaryExpression)node; + var constantExpression = (ConstantExpression)binaryExpression.Right; + node = binaryExpression.Left; + + segments.Add("[" + constantExpression.Value + "]"); + break; + + case ExpressionType.Parameter: + node = null; + break; + + case ExpressionType.Call: + var methodCallExpression = (MethodCallExpression)node; + if (methodCallExpression.Method.Name != "get_Item" || methodCallExpression.Arguments.Count != 1 || !(methodCallExpression.Arguments[0] is ConstantExpression)) + { + throw new ArgumentException(unsupportedExpressionMessage); + } + constantExpression = (ConstantExpression)methodCallExpression.Arguments[0]; + node = methodCallExpression.Object; + segments.Add("[" + constantExpression.Value + "]"); + break; + + default: + throw new ArgumentException(unsupportedExpressionMessage); + } + } + + return string.Join(".", segments.AsEnumerable().Reverse().ToArray()).Replace(".[", "["); + } + + internal static string GetMethodName(Expression action) + { + return ((MethodCallExpression)action.Body).Method.Name; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Common/ExpressionExtensions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/ExpressionExtensions.cs.meta new file mode 100644 index 0000000..7e2eee4 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/ExpressionExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4d5365de470a3ce468c3f6a2a3252376 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/IAdapterResolver.cs b/Assets/Plugins/FluentAssertions/Core/Common/IAdapterResolver.cs new file mode 100644 index 0000000..e9e04a4 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/IAdapterResolver.cs @@ -0,0 +1,15 @@ +// ----------------------------------------------------------------------- +// Copyright (c) David Kean. All rights reserved. +// http://pclcontrib.codeplex.com/ +// ----------------------------------------------------------------------- + + +using System; + +namespace FluentAssertions.Common +{ + internal interface IAdapterResolver + { + object Resolve(Type type); + } +} diff --git a/Assets/Plugins/FluentAssertions/Core/Common/IAdapterResolver.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/IAdapterResolver.cs.meta new file mode 100644 index 0000000..d5055f5 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/IAdapterResolver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 66b3b50f0a644ed438d8ef1f0218d0bb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/IConfigurationStore.cs b/Assets/Plugins/FluentAssertions/Core/Common/IConfigurationStore.cs new file mode 100644 index 0000000..fde1f27 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/IConfigurationStore.cs @@ -0,0 +1,7 @@ +namespace FluentAssertions.Common +{ + public interface IConfigurationStore + { + string GetSetting(string name); + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Common/IConfigurationStore.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/IConfigurationStore.cs.meta new file mode 100644 index 0000000..3c30579 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/IConfigurationStore.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2737df8656173814dbff1d380882ace6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/IProvidePlatformServices.cs b/Assets/Plugins/FluentAssertions/Core/Common/IProvidePlatformServices.cs new file mode 100644 index 0000000..1163fbe --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/IProvidePlatformServices.cs @@ -0,0 +1,17 @@ +using System; + +using FluentAssertions.Formatting; + +namespace FluentAssertions.Common +{ + /// + /// Defines the contract the platform-specific assembly must implement to be able to get a chance to initialize itself. + /// + public interface IProvidePlatformServices + { + Action Throw { get; } + IValueFormatter[] Formatters { get; } + IConfigurationStore ConfigurationStore { get; } + IReflector Reflector { get; } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Common/IProvidePlatformServices.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/IProvidePlatformServices.cs.meta new file mode 100644 index 0000000..5f87dd7 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/IProvidePlatformServices.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f765b1ebab4f6e44d81d6a5c85a4e802 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/IReflector.cs b/Assets/Plugins/FluentAssertions/Core/Common/IReflector.cs new file mode 100644 index 0000000..c274f4c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/IReflector.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace FluentAssertions.Common +{ + public interface IReflector + { + IEnumerable GetAllTypesFromAppDomain(Func predicate); + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Common/IReflector.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/IReflector.cs.meta new file mode 100644 index 0000000..b338123 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/IReflector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 60d6be0ea8e6f5542b754363fe2337aa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/MethodInfoExtensions.cs b/Assets/Plugins/FluentAssertions/Core/Common/MethodInfoExtensions.cs new file mode 100644 index 0000000..c2834f8 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/MethodInfoExtensions.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; + +namespace FluentAssertions.Common +{ + public static class MethodInfoExtensions + { + internal static bool IsAsync(this MethodInfo methodInfo) + { + return methodInfo.GetMatchingAttributes(a => a.GetType().FullName.Equals("System.Runtime.CompilerServices.AsyncStateMachineAttribute")).Any(); + } + + internal static IEnumerable GetMatchingAttributes(this MemberInfo memberInfo, Expression> isMatchingAttributePredicate) where TAttribute : Attribute + { + return memberInfo.GetCustomAttributes( + typeof(TAttribute), false) + .Cast() + .Where(isMatchingAttributePredicate.Compile()); + } + + internal static bool IsNonVirtual(this MethodInfo method) + { + return !method.IsVirtual || method.IsFinal; + } + } +} diff --git a/Assets/Plugins/FluentAssertions/Core/Common/MethodInfoExtensions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/MethodInfoExtensions.cs.meta new file mode 100644 index 0000000..8088a25 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/MethodInfoExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 728b55b4e99eb5244aaa014fa39ae486 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/NullConfigurationStore.cs b/Assets/Plugins/FluentAssertions/Core/Common/NullConfigurationStore.cs new file mode 100644 index 0000000..aa85155 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/NullConfigurationStore.cs @@ -0,0 +1,10 @@ +namespace FluentAssertions.Common +{ + internal class NullConfigurationStore : IConfigurationStore + { + public string GetSetting(string name) + { + return ""; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Common/NullConfigurationStore.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/NullConfigurationStore.cs.meta new file mode 100644 index 0000000..302031e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/NullConfigurationStore.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9efaa2a61a4e28c4cbc4356a9b61270e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/NullReflector.cs b/Assets/Plugins/FluentAssertions/Core/Common/NullReflector.cs new file mode 100644 index 0000000..98a6871 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/NullReflector.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace FluentAssertions.Common +{ + internal class NullReflector : IReflector + { + public IEnumerable GetAllTypesFromAppDomain(Func predicate) + { + return new Type[0]; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Common/NullReflector.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/NullReflector.cs.meta new file mode 100644 index 0000000..f723ae4 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/NullReflector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3db7596dc321eec4e9178efe864115b9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/ObjectExtensions.cs b/Assets/Plugins/FluentAssertions/Core/Common/ObjectExtensions.cs new file mode 100644 index 0000000..60a11c6 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/ObjectExtensions.cs @@ -0,0 +1,20 @@ +namespace FluentAssertions.Common +{ + public static class ObjectExtensions + { + public static bool IsSameOrEqualTo(this object actual, object expected) + { + if (ReferenceEquals(actual, null) && ReferenceEquals(expected, null)) + { + return true; + } + + if (ReferenceEquals(actual, null)) + { + return false; + } + + return actual.Equals(expected); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Common/ObjectExtensions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/ObjectExtensions.cs.meta new file mode 100644 index 0000000..6f23f44 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/ObjectExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 881f9304fc1e6974fba1ff6645456cde +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/PlatformAdapter.cs b/Assets/Plugins/FluentAssertions/Core/Common/PlatformAdapter.cs new file mode 100644 index 0000000..542372d --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/PlatformAdapter.cs @@ -0,0 +1,29 @@ +// ----------------------------------------------------------------------- +// Copyright (c) David Kean. All rights reserved. +// http://pclcontrib.codeplex.com/ +// ----------------------------------------------------------------------- + + +using System; + +namespace FluentAssertions.Common +{ + /// + /// Facade to resolve an implementation of a particular interface using a platform-specific assembly. + /// + internal static class PlatformAdapter + { + private static readonly IAdapterResolver resolver = new ProbingAdapterResolver(); + + public static T Resolve() + { + T value = (T)resolver.Resolve(typeof(T)); + if (value == null) + { + throw new PlatformNotSupportedException("Platform doesn't support interface " + typeof(T).Name); + } + + return value; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Common/PlatformAdapter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/PlatformAdapter.cs.meta new file mode 100644 index 0000000..9271c62 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/PlatformAdapter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f15ea08350739dd42ab80b83e4e5c8a6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/ProbingAdapterResolver.cs b/Assets/Plugins/FluentAssertions/Core/Common/ProbingAdapterResolver.cs new file mode 100644 index 0000000..ec4a0b7 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/ProbingAdapterResolver.cs @@ -0,0 +1,125 @@ +// ----------------------------------------------------------------------- +// Copyright (c) David Kean. All rights reserved. +// http://pclcontrib.codeplex.com/ +// ----------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; + +namespace FluentAssertions.Common +{ + /// + /// An implementation of that probes for platforms-specific adapters by dynamically + /// looking for concrete types in platform-specific assemblies. + /// + internal class ProbingAdapterResolver : IAdapterResolver + { + #region Private Definitions + +#if NEW_REFLECTION + private readonly Func assemblyLoader; +#else + private readonly Func assemblyLoader; +#endif + private readonly object lockable = new object(); + private readonly Dictionary adapters = new Dictionary(); + private Assembly assembly; + +#endregion + + public ProbingAdapterResolver() : this(Assembly.Load) + { + } + +#if NEW_REFLECTION + public ProbingAdapterResolver(Func assemblyLoader) + { + this.assemblyLoader = assemblyLoader; + } +#else + public ProbingAdapterResolver(Func assemblyLoader) + { + this.assemblyLoader = assemblyLoader; + } +#endif + + public object Resolve(Type type) + { + lock (lockable) + { + object instance; + if (!adapters.TryGetValue(type, out instance)) + { + Assembly assembly = GetPlatformSpecificAssembly(); + instance = ResolveAdapter(assembly, type); + adapters.Add(type, instance); + } + + return instance; + } + } + + private static object ResolveAdapter(Assembly assembly, Type interfaceType) + { + string typeName = MakeAdapterTypeName(interfaceType); + +#if NEW_REFLECTION + Type type = assembly.GetType(typeName, throwOnError: false, ignoreCase: false); +#else + Type type = assembly.GetType(typeName, throwOnError: false); +#endif + if (type != null) + { + return Activator.CreateInstance(type); + } + + return type; + } + + private static string MakeAdapterTypeName(Type interfaceType) + { + // For example, if we're looking for an implementation of System.Security.Cryptography.ICryptographyFactory, + // then we'll look for System.Security.Cryptography.CryptographyFactory + return interfaceType.Namespace + "." + interfaceType.Name.Substring(1); + } + + private Assembly GetPlatformSpecificAssembly() + { + if (assembly == null) + { + assembly = ProbeForPlatformSpecificAssembly(); + if (assembly == null) + { + throw new InvalidOperationException("No platform-specific assembly detected"); + } + } + + return assembly; + } + + private Assembly ProbeForPlatformSpecificAssembly() + { +#if NEW_REFLECTION + var assemblyName = new AssemblyName(GetType().GetTypeInfo().Assembly.FullName) { Name = "FluentAssertions" }; +#else + var assemblyName = new AssemblyName(GetType().Assembly.FullName) { Name = "FluentAssertions" }; +#endif + + try + { +#if NEW_REFLECTION + return assemblyLoader(assemblyName); +#else + return assemblyLoader(assemblyName.FullName); +#endif + } + catch (FileNotFoundException) + { + } + + return null; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Common/ProbingAdapterResolver.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/ProbingAdapterResolver.cs.meta new file mode 100644 index 0000000..7ce7eda --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/ProbingAdapterResolver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3a707cadcef8b9a4f830165c8f3935e1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/PropertyInfoExtensions.cs b/Assets/Plugins/FluentAssertions/Core/Common/PropertyInfoExtensions.cs new file mode 100644 index 0000000..0521d58 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/PropertyInfoExtensions.cs @@ -0,0 +1,13 @@ +using System.Reflection; + +namespace FluentAssertions.Common +{ + public static class PropertyInfoExtensions + { + internal static bool IsVirtual(this PropertyInfo property) + { + MethodInfo methodInfo = property.GetGetMethod(true) ?? property.GetSetMethod(true); + return !methodInfo.IsNonVirtual(); + } + } +} diff --git a/Assets/Plugins/FluentAssertions/Core/Common/PropertyInfoExtensions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/PropertyInfoExtensions.cs.meta new file mode 100644 index 0000000..49de94b --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/PropertyInfoExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 15d2540c493d3a24dac470c3b8cff045 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/Services.cs b/Assets/Plugins/FluentAssertions/Core/Common/Services.cs new file mode 100644 index 0000000..9918d3b --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/Services.cs @@ -0,0 +1,97 @@ +using System; + +using FluentAssertions.Formatting; + +namespace FluentAssertions.Common +{ + /// + /// Maintains the framework-specific services. + /// + public static class Services + { + #region Private Definitions + + private static bool initialized = false; + private static readonly object lockable = new object(); + private static Configuration configuration; + private static Action throwException; + private static IReflector reflector; + private static IConfigurationStore configurationStore; + + #endregion + + public static void Initialize() + { + if (!initialized) + { + lock (lockable) + { + if (!initialized) + { + var platform = PlatformAdapter.Resolve(); + + ConfigurationStore = platform.ConfigurationStore ?? new NullConfigurationStore(); + Reflector = platform.Reflector ?? new NullReflector(); + ThrowException = platform.Throw; + + Formatter.AddPlatformFormatters(platform.Formatters); + + initialized = true; + } + } + } + } + + public static IConfigurationStore ConfigurationStore + { + get + { + Initialize(); + + return configurationStore; + } + set { configurationStore = value; } + } + + public static Configuration Configuration + { + get + { + Initialize(); + + if (configuration == null) + { + configuration = new Configuration(ConfigurationStore); + } + + return configuration; + } + } + + public static Action ThrowException + { + get + { + Initialize(); + return throwException; + } + set { throwException = value; } + } + + public static IReflector Reflector + { + get + { + Initialize(); + return reflector; + } + set { reflector = value; } + } + + public static void ResetToDefaults() + { + initialized = false; + Initialize(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Common/Services.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/Services.cs.meta new file mode 100644 index 0000000..49fc70b --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/Services.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: de44afe10f9fcad4db80c23958b123a7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/StringExtensions.cs b/Assets/Plugins/FluentAssertions/Core/Common/StringExtensions.cs new file mode 100644 index 0000000..a0b09ae --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/StringExtensions.cs @@ -0,0 +1,84 @@ +using System; +using System.Linq; +using FluentAssertions.Formatting; + +namespace FluentAssertions.Common +{ + public static class StringExtensions + { + /// + /// Finds the first index at which the does not match the + /// string anymore, including the exact casing. + /// + public static int IndexOfFirstMismatch(this string value, string expected) + { + return IndexOfFirstMismatch(value, expected, StringComparison.CurrentCulture); + } + + /// + /// Finds the first index at which the does not match the + /// string anymore, accounting for the specified . + /// + public static int IndexOfFirstMismatch(this string value, string expected, StringComparison stringComparison) + { + for (int index = 0; index < value.Length; index++) + { + if ((index >= expected.Length) || !value[index].ToString().Equals(expected[index].ToString(), stringComparison)) + { + return index; + } + } + + return -1; + } + + /// + /// Gets the quoted three characters at the specified index of a string, including the index itself. + /// + public static string IndexedSegmentAt(this string value, int index) + { + int length = Math.Min(value.Length - index, 3); + + return $"{Formatter.ToString(value.Substring(index, length))} (index {index})".Replace("{", "{{").Replace("}", "}}"); + } + + /// + /// Replaces all characters that might conflict with formatting placeholders and newlines with their escaped counterparts. + /// + public static string Escape(this string value, bool escapePlaceholders = false) + { + value = value.Replace("\"", "\\\"").Replace("\n", @"\n").Replace("\r", @"\r"); + if (escapePlaceholders) + { + value = value.Replace("{", "{{").Replace("}", "}}"); + } + + return value; + } + + /// + /// Joins a string with one or more other strings using a specified separator. + /// + /// + /// Any string that is empty (including the original string) is ignored. + /// + public static string Combine(this string @this, string other, string separator = ".") + { + var strings = new[] { @this }.Concat(new[] {other}).Where(s => s.Length > 0).ToArray(); + return string.Join(separator, strings); + } + + /// + /// Changes the first character of a string to uppercase. + /// + public static string Capitalize(this string @this) + { + return @this.Substring(0, 1).ToUpper() + @this.Substring(1); + } + + public static string RemoveNewLines(this string @this) + { + return @this.Replace("\n", "").Replace("\r", "").Replace("\\r\\n", ""); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Common/StringExtensions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/StringExtensions.cs.meta new file mode 100644 index 0000000..a187889 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/StringExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c5e2f90d79a235f4ab66251705a3df4b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/TypeExtensions.cs b/Assets/Plugins/FluentAssertions/Core/Common/TypeExtensions.cs new file mode 100644 index 0000000..ac37640 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/TypeExtensions.cs @@ -0,0 +1,350 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; + +using FluentAssertions.Equivalency; + +namespace FluentAssertions.Common +{ + public static class TypeExtensions + { + private const BindingFlags PublicMembersFlag = + BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; + + private const BindingFlags AllMembersFlag = + PublicMembersFlag | BindingFlags.NonPublic | BindingFlags.Static; + + /// + /// Determines whether the specified method has been annotated with a specific attribute. + /// + /// + /// true if the specified method has attribute; otherwise, false. + /// + public static bool HasAttribute(this MemberInfo method) where TAttribute : Attribute + { + return (method.GetCustomAttributes(typeof(TAttribute), true).Any()); + } + + public static bool HasAttribute(this Type method) where TAttribute : Attribute + { +#if NEW_REFLECTION + return (method.GetTypeInfo().GetCustomAttributes(typeof(TAttribute), true).Any()); +#else + return (method.GetCustomAttributes(typeof(TAttribute), true).Any()); +#endif + } + + + public static bool HasMatchingAttribute(this MemberInfo type, Expression> isMatchingAttributePredicate) + where TAttribute : Attribute + { + Func isMatchingAttribute = isMatchingAttributePredicate.Compile(); + + return GetCustomAttributes(type).Any(isMatchingAttribute); + } + + public static bool HasMatchingAttribute(this Type type, Expression> isMatchingAttributePredicate) + where TAttribute : Attribute + { + Func isMatchingAttribute = isMatchingAttributePredicate.Compile(); + + return GetCustomAttributes(type).Any(isMatchingAttribute); + } + + public static bool IsDecoratedWith(this MemberInfo type) + where TAttribute : Attribute + { + return GetCustomAttributes(type).Any(); + } + + public static bool IsDecoratedWith(this Type type) + where TAttribute : Attribute + { + return GetCustomAttributes(type).Any(); + } + + + private static IEnumerable GetCustomAttributes(MemberInfo type) + { + return type.GetCustomAttributes(false).OfType(); + } + + private static IEnumerable GetCustomAttributes(Type type) + { +#if NEW_REFLECTION + return type.GetTypeInfo().GetCustomAttributes(false).OfType(); +#else + return type.GetCustomAttributes(false).OfType(); +#endif + } + + /// + /// Determines whether two objects refer to the same member. + /// + public static bool IsEquivalentTo(this SelectedMemberInfo property, SelectedMemberInfo otherProperty) + { + return (property.DeclaringType.IsSameOrInherits(otherProperty.DeclaringType) || + otherProperty.DeclaringType.IsSameOrInherits(property.DeclaringType)) && + (property.Name == otherProperty.Name); + } + + public static bool IsSameOrInherits(this Type actualType, Type expectedType) + { + return (actualType == expectedType) || + (expectedType.IsAssignableFrom(actualType)); + } + + public static bool Implements(this Type type) + { + return Implements(type, typeof (TInterface)); + } + + /// + /// NOTE: This method does not give the expected results with open generics + /// + public static bool Implements(this Type type, Type expectedBaseType) + { + return + expectedBaseType.IsAssignableFrom(type) + && (type != expectedBaseType); + } + + internal static Type[] GetClosedGenericInterfaces(Type type, Type openGenericType) + { + if (type.IsGenericType() && type.GetGenericTypeDefinition() == openGenericType) + { + return new[] { type }; + } + + Type[] interfaces = type.GetInterfaces(); + return + interfaces + .Where(t => (t.IsGenericType() && (t.GetGenericTypeDefinition() == openGenericType))) + .ToArray(); + } + + public static bool IsComplexType(this Type type) + { + return HasProperties(type) && !AssertionOptions.IsValueType(type); + } + + private static bool HasProperties(Type type) + { + return type.GetProperties(PublicMembersFlag).Any(); + } + + /// + /// Finds a member by its case-sensitive name. + /// + /// + /// Returns null if no such member exists. + /// + public static SelectedMemberInfo FindMember(this Type type, string memberName, Type preferredType) + { + return SelectedMemberInfo.Create(FindProperty(type, memberName, preferredType)) ?? + SelectedMemberInfo.Create(FindField(type, memberName, preferredType)); + } + + /// + /// Finds the property by a case-sensitive name. + /// + /// + /// Returns null if no such property exists. + /// + public static PropertyInfo FindProperty(this Type type, string propertyName, Type preferredType) + { + IEnumerable properties = + type.GetProperties(PublicMembersFlag) + .Where(pi => pi.Name == propertyName) + .ToList(); + + return (properties.Count() > 1) + ? properties.SingleOrDefault(p => p.PropertyType == preferredType) + : properties.SingleOrDefault(); + } + + /// + /// Finds the field by a case-sensitive name. + /// + /// + /// Returns null if no such property exists. + /// + public static FieldInfo FindField(this Type type, string fieldName, Type preferredType) + { + IEnumerable properties = + type.GetFields(PublicMembersFlag) + .Where(pi => pi.Name == fieldName) + .ToList(); + + return (properties.Count() > 1) + ? properties.SingleOrDefault(p => p.FieldType == preferredType) + : properties.SingleOrDefault(); + } + + public static IEnumerable GetNonPrivateMembers(this Type typeToReflect) + { + return + GetNonPrivateProperties(typeToReflect) + .Select(SelectedMemberInfo.Create) + .Concat(GetNonPrivateFields(typeToReflect).Select(SelectedMemberInfo.Create)) + .ToArray(); + } + + public static IEnumerable GetNonPrivateProperties(this Type typeToReflect, IEnumerable filter = null) + { + var query = + from propertyInfo in GetPropertiesFromHierarchy(typeToReflect) + where HasNonPrivateGetter(propertyInfo) + where !propertyInfo.IsIndexer() + where (filter == null) || filter.Contains(propertyInfo.Name) + select propertyInfo; + + return query.ToArray(); + } + + public static IEnumerable GetNonPrivateFields(this Type typeToReflect) + { + var query = + from fieldInfo in GetFieldsFromHierarchy(typeToReflect) + where !fieldInfo.IsPrivate + where !fieldInfo.IsFamily + select fieldInfo; + + return query.ToArray(); + } + + private static IEnumerable GetFieldsFromHierarchy(Type typeToReflect) + { + return GetMembersFromHierarchy(typeToReflect, GetPublicFields); + } + + private static IEnumerable GetPropertiesFromHierarchy(Type typeToReflect) + { + return GetMembersFromHierarchy(typeToReflect, GetPublicProperties); + } + + private static IEnumerable GetMembersFromHierarchy( + Type typeToReflect, + Func> getMembers) where TMemberInfo : MemberInfo + { + if (IsInterface(typeToReflect)) + { + var propertyInfos = new List(); + + var considered = new List(); + var queue = new Queue(); + considered.Add(typeToReflect); + queue.Enqueue(typeToReflect); + + while (queue.Count > 0) + { + var subType = queue.Dequeue(); + foreach (var subInterface in GetInterfaces(subType)) + { + if (considered.Contains(subInterface)) + { + continue; + } + + considered.Add(subInterface); + queue.Enqueue(subInterface); + } + + IEnumerable typeProperties = getMembers(subType); + + IEnumerable newPropertyInfos = typeProperties.Where(x => !propertyInfos.Contains(x)); + + propertyInfos.InsertRange(0, newPropertyInfos); + } + + return propertyInfos.ToArray(); + } + else + { + return getMembers(typeToReflect); + } + } + + private static bool IsInterface(Type typeToReflect) + { + return typeToReflect.IsInterface(); + } + + private static IEnumerable GetInterfaces(Type type) + { + return type.GetInterfaces(); + } + + private static IEnumerable GetPublicProperties(Type type) + { + return type.GetProperties(PublicMembersFlag); + } + + private static IEnumerable GetPublicFields(Type type) + { + return type.GetFields(PublicMembersFlag); + } + + private static bool HasNonPrivateGetter(PropertyInfo propertyInfo) + { + MethodInfo getMethod = propertyInfo.GetGetMethod(true); + return (getMethod != null) && !getMethod.IsPrivate && !getMethod.IsFamily; + } + + public static MethodInfo GetMethod(this Type type, string methodName, IEnumerable parameterTypes) + { + return type.GetMethods(AllMembersFlag) + .SingleOrDefault(m => m.Name == methodName && m.GetParameters().Select(p => p.ParameterType).SequenceEqual(parameterTypes)); + } + + public static bool HasMethod(this Type type, string methodName, IEnumerable parameterTypes) + { + return type.GetMethod(methodName, parameterTypes) != null; + } + + public static MethodInfo GetParameterlessMethod(this Type type, string methodName) + { + return type.GetMethod(methodName, Enumerable.Empty()); + } + + public static bool HasParameterlessMethod(this Type type, string methodName) + { + return type.GetParameterlessMethod(methodName) != null; + } + + public static PropertyInfo GetPropertyByName(this Type type, string propertyName) + { + return type.GetProperty(propertyName, AllMembersFlag); + } + + public static bool HasExplicitlyImplementedProperty(this Type type, Type interfaceType, string propertyName) + { + var hasGetter = type.HasParameterlessMethod(string.Format("{0}.get_{1}", interfaceType.FullName, propertyName)); + var hasSetter = type.GetMethods(AllMembersFlag) + .SingleOrDefault(m => m.Name == string.Format("{0}.set_{1}", interfaceType.FullName, propertyName) && m.GetParameters().Count() == 1) != null; + + return hasGetter || hasSetter; + } + + public static PropertyInfo GetIndexerByParameterTypes(this Type type, IEnumerable parameterTypes) + { + return type.GetProperties(AllMembersFlag) + .SingleOrDefault(p => p.IsIndexer() && p.GetIndexParameters().Select(i => i.ParameterType).SequenceEqual(parameterTypes)); + } + + public static bool IsIndexer(this PropertyInfo member) + { + return (member.GetIndexParameters().Length != 0); + } + + public static ConstructorInfo GetConstructor(this Type type, IEnumerable parameterTypes) + { + return type + .GetConstructors(PublicMembersFlag) + .SingleOrDefault(m => m.GetParameters().Select(p => p.ParameterType).SequenceEqual(parameterTypes)); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Common/TypeExtensions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/TypeExtensions.cs.meta new file mode 100644 index 0000000..17dd48e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/TypeExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 23f6b65d60c2526488393d55f530e39b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Common/ValueFormatterDetectionMode.cs b/Assets/Plugins/FluentAssertions/Core/Common/ValueFormatterDetectionMode.cs new file mode 100644 index 0000000..57da018 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/ValueFormatterDetectionMode.cs @@ -0,0 +1,25 @@ +namespace FluentAssertions.Common +{ + /// + /// Defines the modes in which custom implementations of are detected as configured + /// through . + /// + public enum ValueFormatterDetectionMode + { + /// + /// Detection is disabled. + /// + Disabled, + + /// + /// Only custom value formatters exposed through the assembly set in + /// are detected. + /// + Specific, + + /// + /// All custom value formatters in any assembly loaded in the current will be detected. + /// + Scan, + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Common/ValueFormatterDetectionMode.cs.meta b/Assets/Plugins/FluentAssertions/Core/Common/ValueFormatterDetectionMode.cs.meta new file mode 100644 index 0000000..1b7b7c9 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Common/ValueFormatterDetectionMode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b43d769dfeeb1624da010403f4988732 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Disposable.cs b/Assets/Plugins/FluentAssertions/Core/Disposable.cs new file mode 100644 index 0000000..7bd0f6f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Disposable.cs @@ -0,0 +1,19 @@ +using System; + +namespace FluentAssertions +{ + internal class Disposable : IDisposable + { + private readonly Action action; + + public Disposable(Action action) + { + this.action = action; + } + + public void Dispose() + { + action(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Disposable.cs.meta b/Assets/Plugins/FluentAssertions/Core/Disposable.cs.meta new file mode 100644 index 0000000..54451df --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Disposable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 70b29c85e35026f4eb7a0dfb411bcfc6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency.meta new file mode 100644 index 0000000..20882f8 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 069fc278a7a79404daf26fa82a475f32 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionContext.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionContext.cs new file mode 100644 index 0000000..e5bdd5b --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionContext.cs @@ -0,0 +1,36 @@ +using System.Reflection; + +namespace FluentAssertions.Equivalency +{ + internal class AssertionContext : IAssertionContext + { + public AssertionContext(SelectedMemberInfo subjectProperty, TSubject subject, TSubject expectation, string because, + object[] becauseArgs) + { + SubjectProperty = subjectProperty; + Subject = subject; + Expectation = expectation; + Because = because; + BecauseArgs = becauseArgs; + } + + public SelectedMemberInfo SubjectProperty { get; private set; } + public TSubject Subject { get; private set; } + public TSubject Expectation { get; private set; } + public string Because { get; set; } + public object[] BecauseArgs { get; set; } + + internal static AssertionContext CreateFromEquivalencyValidationContext(IEquivalencyValidationContext context) + { + var expectation = (context.Expectation != null) ? (TSubject)context.Expectation : default(TSubject); + + var assertionContext = new AssertionContext( + context.SelectedMemberInfo, + (TSubject)context.Subject, + expectation, + context.Because, + context.BecauseArgs); + return assertionContext; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionContext.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionContext.cs.meta new file mode 100644 index 0000000..6e6ed31 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionContext.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 70d6c7d6cd119db4c8ed0e0b289bbf5d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionResultSet.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionResultSet.cs new file mode 100644 index 0000000..2cab8c1 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionResultSet.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; +using System.Linq; +using FluentAssertions.Execution; + +namespace FluentAssertions.Equivalency +{ + /// + /// Represents a collection of assertion results obtained through a . + /// + internal class AssertionResultSet + { + private readonly Dictionary set = new Dictionary(); + + /// + /// Adds the failures (if any) resulting from executing an assertion within a + /// identified by a key. + /// + public void AddSet(object key, string[] failures) + { + set[key] = failures; + } + + /// + /// Returns the closest match compared to the set identified by the provided or + /// an empty array if one of the results represents a successful assertion. + /// + /// + /// The closest match is the set that contains the least amount of failures, or no failures at all, and preferably + /// the set that is identified by the . + /// + public string[] SelectClosestMatchFor(object key = null) + { + if (!ContainsSuccessfulSet) + { + KeyValuePair bestMatch = BestResultSets.Any(r => r.Key.Equals(key)) + ? BestResultSets.Single(r => r.Key.Equals(key)) + : BestResultSets.First(); + + return bestMatch.Value; + } + + return new string[0]; + } + + private KeyValuePair[] BestResultSets + { + get + { + int fewestFailures = set.Values.Min(r => r.Count()); + return set.Where(r => r.Value.Count() == fewestFailures).ToArray(); + } + } + + /// + /// Gets a value indicating whether this collection contains a set without any failures at all. + /// + public bool ContainsSuccessfulSet + { + get { return set.Values.Any(v => v.Length == 0); } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionResultSet.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionResultSet.cs.meta new file mode 100644 index 0000000..b6f1d59 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionResultSet.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0676132a4d1a3694d963e8b060003ba7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionRule.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionRule.cs new file mode 100644 index 0000000..ea1f2d2 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionRule.cs @@ -0,0 +1,90 @@ +using System; +using System.Linq.Expressions; + +using FluentAssertions.Common; +using FluentAssertions.Execution; + +namespace FluentAssertions.Equivalency +{ + /// + /// General purpose implementation of that uses a predicate to determine whether + /// this rule applies to a particular property and executes an action to assert equality. + /// + /// The type of the subject. + [Obsolete("This class will be removed in a future version. Use `EquivalencyAssertionOptions.Using(Action>)` from the Fluent API instead.")] + public class AssertionRule : IAssertionRule + { + private readonly Func predicate; + private readonly Action> action; + private readonly string description; + + public AssertionRule(Expression> predicate, Action> action) + { + this.predicate = predicate.Compile(); + this.action = action; + description = "Invoke Action<" + typeof(TSubject).Name + "> when " + predicate.Body; + } + + public AssertionRule(Action> action) + { + Expression> predicate = + info => info.RuntimeType.IsSameOrInherits(typeof (string)); + + this.predicate = predicate.Compile(); + this.action = action; + description = "Invoke Action<" + typeof(TSubject).Name + "> when " + predicate.Body; + } + + /// + /// Defines how a subject's property is compared for equality with the same property of the expectation. + /// + /// + /// Provides details about the subject's property. + /// + /// + /// The value of the subject's property. + /// + /// + /// The value of a property on expectation object that was identified + /// + /// + /// Returns true if the rule was applied correctly and the assertion didn't cause any exceptions. + /// Returns false if this rule doesn't support the subject's type. + /// Throws if the rule did support the data type but assertion fails. + /// + public bool AssertEquality(IEquivalencyValidationContext context) + { + if (predicate(context)) + { + bool expectationisNull = ReferenceEquals(context.Expectation, null); + + bool succeeded = + AssertionScope.Current + .ForCondition(expectationisNull || context.Expectation.GetType().IsSameOrInherits(typeof(TSubject))) + .FailWith("Expected " + context.SelectedMemberDescription + " to be a {0}{reason}, but found a {1}", + !expectationisNull ? context.Expectation.GetType() : null, context.SelectedMemberInfo.MemberType); + + if (succeeded) + { + action(AssertionContext.CreateFromEquivalencyValidationContext(context)); + } + + return true; + } + + return false; + } + + /// + /// Returns a string that represents the current object. + /// + /// + /// A string that represents the current object. + /// + /// 2 + public override string ToString() + { + return description; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionRule.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionRule.cs.meta new file mode 100644 index 0000000..dedaa17 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionRule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: acf70fad37ca508418ced89979030587 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionRuleEquivalencyStep.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionRuleEquivalencyStep.cs new file mode 100644 index 0000000..2327abf --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionRuleEquivalencyStep.cs @@ -0,0 +1,61 @@ +using System; +using System.Linq.Expressions; + +using FluentAssertions.Common; +using FluentAssertions.Execution; + +namespace FluentAssertions.Equivalency +{ + public class AssertionRuleEquivalencyStep : IEquivalencyStep + { + private readonly Expression> canHandle; + + private readonly Action> handle; + + public AssertionRuleEquivalencyStep(Expression> predicate, Action> action) + { + canHandle = predicate; + handle = action; + } + + public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) + { + Func predicate = canHandle.Compile(); + + return ((context.SelectedMemberInfo != null) && predicate(context)); + } + + public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config) + { + bool expectationisNull = ReferenceEquals(context.Expectation, null); + + bool succeeded = + AssertionScope.Current.ForCondition( + expectationisNull || context.Expectation.GetType().IsSameOrInherits(typeof(TSubject))) + .FailWith( + "Expected " + context.SelectedMemberDescription + " to be a {0}{reason}, but found a {1}", + !expectationisNull ? context.Expectation.GetType() : null, + context.SelectedMemberInfo.MemberType); + + if (succeeded) + { + handle(AssertionContext.CreateFromEquivalencyValidationContext(context)); + return true; + } + + return false; + } + + /// + /// Returns a string that represents the current object. + /// + /// + /// A string that represents the current object. + /// + /// 2 + public override string ToString() + { + return "Invoke Action<" + typeof(TSubject).Name + "> when " + canHandle.Body; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionRuleEquivalencyStep.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionRuleEquivalencyStep.cs.meta new file mode 100644 index 0000000..f3843f3 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionRuleEquivalencyStep.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cb274c7737ff49f4d8d0bffe37774f75 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionRuleEquivalencyStepAdapter.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionRuleEquivalencyStepAdapter.cs new file mode 100644 index 0000000..02d0ab7 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionRuleEquivalencyStepAdapter.cs @@ -0,0 +1,30 @@ +namespace FluentAssertions.Equivalency +{ + /// + /// Adaptor allowing an IAssertionRule to be used where a IEquivalencyStep is required. + /// + internal class AssertionRuleEquivalencyStepAdapter : IEquivalencyStep + { + private readonly IAssertionRule assertionRule; + + public AssertionRuleEquivalencyStepAdapter(IAssertionRule assertionRule) + { + this.assertionRule = assertionRule; + } + + public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) + { + return (context.SelectedMemberInfo != null); + } + + public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config) + { + return assertionRule.AssertEquality(context); + } + + public override string ToString() + { + return assertionRule.ToString(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionRuleEquivalencyStepAdapter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionRuleEquivalencyStepAdapter.cs.meta new file mode 100644 index 0000000..06600d9 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/AssertionRuleEquivalencyStepAdapter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 62fb7fbc129abae4a916c45632b731cb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/CollectionMemberAssertionOptionsDecorator.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/CollectionMemberAssertionOptionsDecorator.cs new file mode 100644 index 0000000..d1fc863 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/CollectionMemberAssertionOptionsDecorator.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using FluentAssertions.Equivalency.Matching; +using FluentAssertions.Equivalency.Ordering; +using FluentAssertions.Equivalency.Selection; + +namespace FluentAssertions.Equivalency +{ + internal class CollectionMemberAssertionOptionsDecorator : IEquivalencyAssertionOptions + { + private readonly IEquivalencyAssertionOptions inner; + + public CollectionMemberAssertionOptionsDecorator(IEquivalencyAssertionOptions inner) + { + this.inner = inner; + } + + public IEnumerable SelectionRules + { + get + { + return inner.SelectionRules.Select(rule => new CollectionMemberSelectionRuleDecorator(rule)).ToArray(); + } + } + + public IEnumerable MatchingRules + { + get { return inner.MatchingRules.Select(rule => new CollectionMemberMatchingRuleDecorator(rule)).ToArray(); } + } + + public OrderingRuleCollection OrderingRules + { + get + { + return new OrderingRuleCollection(inner.OrderingRules.Select(rule => new CollectionMemberOrderingRuleDecorator(rule))); + } + } + + public IEnumerable UserEquivalencySteps + { + get { return inner.UserEquivalencySteps.Select(step => new CollectionMemberAssertionRuleDecorator(step)).ToArray(); } + } + + public bool IsRecursive + { + get { return inner.IsRecursive; } + } + + public bool AllowInfiniteRecursion + { + get { return inner.AllowInfiniteRecursion; } + } + + public CyclicReferenceHandling CyclicReferenceHandling + { + get { return inner.CyclicReferenceHandling; } + } + + public EnumEquivalencyHandling EnumEquivalencyHandling + { + get { return inner.EnumEquivalencyHandling; } + } + + public bool UseRuntimeTyping + { + get { return inner.UseRuntimeTyping; } + } + + public bool IncludeProperties + { + get { return inner.IncludeProperties; } + } + + public bool IncludeFields + { + get { return inner.IncludeFields; } + } + + public bool IsValueType(Type type) + { + return inner.IsValueType(type); + } + + public ITraceWriter TraceWriter => inner.TraceWriter; + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/CollectionMemberAssertionOptionsDecorator.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/CollectionMemberAssertionOptionsDecorator.cs.meta new file mode 100644 index 0000000..bdb88e4 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/CollectionMemberAssertionOptionsDecorator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 59dbe8b1dda482f4ebcd824142f2dfc9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/CollectionMemberAssertionRuleDecorator.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/CollectionMemberAssertionRuleDecorator.cs new file mode 100644 index 0000000..78c9d04 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/CollectionMemberAssertionRuleDecorator.cs @@ -0,0 +1,47 @@ +namespace FluentAssertions.Equivalency +{ + internal class CollectionMemberAssertionRuleDecorator : IEquivalencyStep + { + private readonly IEquivalencyStep eqivalencyStep; + + public CollectionMemberAssertionRuleDecorator(IEquivalencyStep equivalencyStep) + { + eqivalencyStep = equivalencyStep; + } + + public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) + { + return eqivalencyStep.CanHandle(CreateAdjustedCopy(context), config); + } + + public bool Handle( + IEquivalencyValidationContext context, + IEquivalencyValidator parent, + IEquivalencyAssertionOptions config) + { + var equivalencyValidationContext = CreateAdjustedCopy(context); + + return eqivalencyStep.Handle(equivalencyValidationContext, parent, config); + } + + private static EquivalencyValidationContext CreateAdjustedCopy(IEquivalencyValidationContext context) + { + return new EquivalencyValidationContext + { + CompileTimeType = context.CompileTimeType, + Expectation = context.Expectation, + SelectedMemberDescription = context.SelectedMemberDescription, + SelectedMemberInfo = context.SelectedMemberInfo, + SelectedMemberPath = CollectionMemberSubjectInfo.GetAdjustedPropertyPath(context.SelectedMemberPath), + Because = context.Because, + BecauseArgs = context.BecauseArgs, + Subject = context.Subject + }; + } + + public override string ToString() + { + return eqivalencyStep.ToString(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/CollectionMemberAssertionRuleDecorator.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/CollectionMemberAssertionRuleDecorator.cs.meta new file mode 100644 index 0000000..cf387b9 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/CollectionMemberAssertionRuleDecorator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8c010a519878fd042abb5e49983c455c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/CollectionMemberSubjectInfo.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/CollectionMemberSubjectInfo.cs new file mode 100644 index 0000000..8a0891e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/CollectionMemberSubjectInfo.cs @@ -0,0 +1,32 @@ +using System; +using System.Reflection; + +namespace FluentAssertions.Equivalency +{ + internal class CollectionMemberSubjectInfo : ISubjectInfo + { + public CollectionMemberSubjectInfo(ISubjectInfo subjectInfo) + { + CompileTimeType = subjectInfo.CompileTimeType; + SelectedMemberDescription = subjectInfo.SelectedMemberDescription; + SelectedMemberInfo = subjectInfo.SelectedMemberInfo; + SelectedMemberPath = GetAdjustedPropertyPath(subjectInfo.SelectedMemberPath); + RuntimeType = subjectInfo.RuntimeType; + } + + internal static string GetAdjustedPropertyPath(string propertyPath) + { + return propertyPath.Substring(propertyPath.IndexOf(".", StringComparison.Ordinal) + 1); + } + + public SelectedMemberInfo SelectedMemberInfo { get; private set; } + + public string SelectedMemberPath { get; private set; } + + public string SelectedMemberDescription { get; private set; } + + public Type CompileTimeType { get; private set; } + + public Type RuntimeType { get; private set; } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/CollectionMemberSubjectInfo.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/CollectionMemberSubjectInfo.cs.meta new file mode 100644 index 0000000..869ddfa --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/CollectionMemberSubjectInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2784d1961158805418a95efb660787b2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/CyclicReferenceHandling.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/CyclicReferenceHandling.cs new file mode 100644 index 0000000..c21eff0 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/CyclicReferenceHandling.cs @@ -0,0 +1,18 @@ +namespace FluentAssertions.Equivalency +{ + /// + /// Indication of how cyclic references should be handled when validating equality of nested properties. + /// + public enum CyclicReferenceHandling + { + /// + /// Cyclic references will be ignored. + /// + Ignore, + + /// + /// Cyclic references will result in an exception. + /// + ThrowException + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/CyclicReferenceHandling.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/CyclicReferenceHandling.cs.meta new file mode 100644 index 0000000..a4c4771 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/CyclicReferenceHandling.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 19fa0eb290f94cb448a1296449bb81ce +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/DictionaryEquivalencyStep.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/DictionaryEquivalencyStep.cs new file mode 100644 index 0000000..b4d66c0 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/DictionaryEquivalencyStep.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using FluentAssertions.Execution; + +namespace FluentAssertions.Equivalency +{ + public class DictionaryEquivalencyStep : IEquivalencyStep + { + /// + /// Gets a value indicating whether this step can handle the current subject and/or expectation. + /// + public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) + { + Type subjectType = config.GetSubjectType(context); + + return typeof(IDictionary).IsAssignableFrom(subjectType); + } + + /// + /// Applies a step as part of the task to compare two objects for structural equality. + /// + /// + /// Should return true if the subject matches the expectation or if no additional assertions + /// have to be executed. Should return false otherwise. + /// + /// + /// May throw when preconditions are not met or if it detects mismatching data. + /// + [SuppressMessage("ReSharper", "PossibleNullReferenceException")] + public virtual bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config) + { + var subject = (IDictionary)context.Subject; + var expectation = context.Expectation as IDictionary; + + if (PreconditionsAreMet(context, expectation, subject)) + { + foreach (object key in subject.Keys) + { + if (config.IsRecursive) + { + context.TraceSingle(path => $"Recursing into dictionary item {key} at {path}"); + parent.AssertEqualityUsing(context.CreateForDictionaryItem(key, subject[key], expectation[key])); + } + else + { + context.TraceSingle(path => $"Comparing dictionary item {key} at {path} between subject and expectation"); + subject[key].Should().Be(expectation[key], context.Because, context.BecauseArgs); + } + } + } + + return true; + } + + private static bool PreconditionsAreMet(IEquivalencyValidationContext context, IDictionary expectation, IDictionary subject) + { + return (AssertIsDictionary(expectation) && AssertSameLength(expectation, subject)); + } + + private static bool AssertIsDictionary(IDictionary expectation) + { + return AssertionScope.Current + .ForCondition(expectation != null) + .FailWith("{context:subject} is a dictionary and cannot be compared with a non-dictionary type."); + } + + private static bool AssertSameLength(IDictionary expectation, IDictionary subject) + { + return AssertionScope.Current + .ForCondition(subject.Keys.Count == expectation.Keys.Count) + .FailWith("Expected {context:subject} to be a dictionary with {0} item(s), but it only contains {1} item(s).", + expectation.Keys.Count, subject.Keys.Count); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/DictionaryEquivalencyStep.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/DictionaryEquivalencyStep.cs.meta new file mode 100644 index 0000000..d35c270 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/DictionaryEquivalencyStep.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a9601eb671d179b41bddac49b29c009b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumEqualityStep.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumEqualityStep.cs new file mode 100644 index 0000000..388b3e2 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumEqualityStep.cs @@ -0,0 +1,57 @@ +#region + +using System; +using System.Globalization; + +#endregion + +namespace FluentAssertions.Equivalency +{ + public class EnumEqualityStep : IEquivalencyStep + { + /// + /// Gets a value indicating whether this step can handle the current subject and/or expectation. + /// + public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) + { + Type subjectType = config.GetSubjectType(context); + + return ((subjectType != null) && subjectType.IsEnum()) || + ((context.Expectation != null) && context.Expectation.GetType().IsEnum()); + } + + /// + /// Applies a step as part of the task to compare two objects for structural equality. + /// + /// + /// Should return true if the subject matches the expectation or if no additional assertions + /// have to be executed. Should return false otherwise. + /// + /// + /// May throw when preconditions are not met or if it detects mismatching data. + /// + public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, + IEquivalencyAssertionOptions config) + { + switch (config.EnumEquivalencyHandling) + { + case EnumEquivalencyHandling.ByValue: + decimal? subjectsUnderlyingValue = (context.Subject != null) ? Convert.ToDecimal(context.Subject) : (decimal?)null; + decimal? expectationsUnderlyingValue = (context.Expectation != null) ? Convert.ToDecimal(context.Expectation) : (decimal?)null; + + subjectsUnderlyingValue.Should().Be(expectationsUnderlyingValue, context.Because, context.BecauseArgs); + break; + + case EnumEquivalencyHandling.ByName: + context.Subject.ToString().Should().Be(context.Expectation.ToString(), context.Because, context.BecauseArgs); + break; + + default: + throw new InvalidOperationException(string.Format("Don't know how to handle {0}", + config.EnumEquivalencyHandling)); + } + + return true; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumEqualityStep.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumEqualityStep.cs.meta new file mode 100644 index 0000000..f73b5db --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumEqualityStep.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1d0cb3edf9c7b6c4ea4514ee233fd653 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumEquivalencyHandling.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumEquivalencyHandling.cs new file mode 100644 index 0000000..66a4c95 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumEquivalencyHandling.cs @@ -0,0 +1,8 @@ +namespace FluentAssertions.Equivalency +{ + public enum EnumEquivalencyHandling + { + ByValue, + ByName + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumEquivalencyHandling.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumEquivalencyHandling.cs.meta new file mode 100644 index 0000000..ac87f31 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumEquivalencyHandling.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 34f368a019147d546bdb079579451ca5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumerableEquivalencyStep.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumerableEquivalencyStep.cs new file mode 100644 index 0000000..d22e86e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumerableEquivalencyStep.cs @@ -0,0 +1,74 @@ +using System; + +using System.Collections; +using System.Linq; +using System.Reflection; +using FluentAssertions.Execution; + +namespace FluentAssertions.Equivalency +{ + public class EnumerableEquivalencyStep : IEquivalencyStep + { + /// + /// Gets a value indicating whether this step can handle the verificationScope subject and/or expectation. + /// + public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) + { + Type subjectType = config.GetSubjectType(context); + + return IsCollection(subjectType); + } + + /// + /// Applies a step as part of the task to compare two objects for structural equality. + /// + /// + /// Should return true if the subject matches the expectation or if no additional assertions + /// have to be executed. Should return false otherwise. + /// + /// + /// May throw when preconditions are not met or if it detects mismatching data. + /// + public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config) + { + if (AssertExpectationIsCollection(context.Expectation)) + { + var validator = new EnumerableEquivalencyValidator(parent, context) + { + Recursive = context.IsRoot || config.IsRecursive, + OrderingRules = config.OrderingRules + }; + + validator.Execute(ToArray(context.Subject), ToArray(context.Expectation)); + } + + return true; + } + + private static bool AssertExpectationIsCollection(object expectation) + { + bool conditionMet = AssertionScope.Current + .ForCondition(!ReferenceEquals(expectation, null)) + .FailWith("{context:Subject} is a collection and cannot be compared to ."); + + if (conditionMet) + { + conditionMet = AssertionScope.Current + .ForCondition(IsCollection(expectation.GetType())) + .FailWith("{context:Subject} is a collection and cannot be compared with a non-collection type."); + } + + return conditionMet; + } + + private static bool IsCollection(Type type) + { + return !typeof(string).IsAssignableFrom(type) && typeof(IEnumerable).IsAssignableFrom(type); + } + + internal static object[] ToArray(object value) + { + return !ReferenceEquals(value, null) ? ((IEnumerable)value).Cast().ToArray() : null; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumerableEquivalencyStep.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumerableEquivalencyStep.cs.meta new file mode 100644 index 0000000..ca010ec --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumerableEquivalencyStep.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 11236c9d602f5934ab70d6ef98f44f10 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumerableEquivalencyValidator.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumerableEquivalencyValidator.cs new file mode 100644 index 0000000..7841e1d --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumerableEquivalencyValidator.cs @@ -0,0 +1,144 @@ +using System.Collections.Generic; +using System.Linq; + +using FluentAssertions.Execution; + +namespace FluentAssertions.Equivalency +{ + /// + /// Executes a single equivalency assertion on two collections, optionally recursive and with or without strict ordering. + /// + internal class EnumerableEquivalencyValidator + { + #region Private Definitions + + private readonly IEquivalencyValidator parent; + private readonly IEquivalencyValidationContext context; + + #endregion + + public EnumerableEquivalencyValidator(IEquivalencyValidator parent, IEquivalencyValidationContext context) + { + this.parent = parent; + this.context = context; + Recursive = false; + } + + public bool Recursive { get; set; } + + public OrderingRuleCollection OrderingRules { get; set; } + + public void Execute(T[] subject, object[] expectation) + { + if (AssertIsNotNull(subject) && AssertLengthEquality(subject.Length, expectation.Length)) + { + if (Recursive) + { + using (context.TraceBlock(path => $"Structurally comparing {subject} and expectation {expectation} at {path}")) + { + AssertElementGraphEquivalency(subject, expectation); + } + } + else + { + using (context.TraceBlock(path => $"Comparing subject {subject} and expectation {expectation} at {path} using simple value equality")) + { + subject.Should().BeEquivalentTo(expectation); + } + } + } + } + + private bool AssertIsNotNull(object subject) + { + return AssertionScope.Current + .ForCondition(!ReferenceEquals(subject, null)) + .FailWith("Expected {context:subject} to be a collection, but found ."); + } + + private bool AssertLengthEquality(int subjectLength, int expectationLength) + { + return AssertionScope.Current + .ForCondition(subjectLength == expectationLength) + .FailWith("Expected {context:subject} to be a collection with {0} item(s){reason}, but found {1}.", + expectationLength, subjectLength); + } + + private void AssertElementGraphEquivalency(T[] subjects, object[] expectations) + { + matchedSubjectIndexes = new HashSet(); + + foreach (int index in Enumerable.Range(0, expectations.Length)) + { + object expectation = expectations[index]; + + if (!OrderingRules.IsOrderingStrictFor(context)) + { + using (context.TraceBlock(path => $"Finding the best match of {expectation} within all items in {subjects} at {path}[{index}]")) + { + LooselyMatchAgainst(subjects, expectation, index); + } + } + else + { + using (context.TraceBlock(path => $"Strictly comparing expectation {expectation} at {path} to item with index {index} in {subjects}")) + { + StrictlyMatchAgainst(subjects, expectation, index); + } + } + } + } + + private HashSet matchedSubjectIndexes; + + private void LooselyMatchAgainst(IList subjects, object expectation, int expectationIndex) + { + var results = new AssertionResultSet(); + + foreach (int index in Enumerable.Range(0, subjects.Count)) + { + if (!matchedSubjectIndexes.Contains(index)) + { + T subject = subjects[index]; + + using (context.TraceBlock(path => $"Comparing subject at {path}[{index}] with the expectation at {path}[{expectationIndex}]")) + { + string[] failures = TryToMatch(subject, expectation, expectationIndex); + + results.AddSet(index, failures); + if (results.ContainsSuccessfulSet) + { + context.TraceSingle(_ => $"It's a match"); + matchedSubjectIndexes.Add(index); + break; + } + else + { + context.TraceSingle(_ => $"Contained {failures.Length} failures"); + } + } + } + } + + foreach (string failure in results.SelectClosestMatchFor(expectationIndex)) + { + AssertionScope.Current.AddFailure(failure); + } + } + + private string[] TryToMatch(T subject, object expectation, int expectationIndex) + { + using (var scope = new AssertionScope()) + { + parent.AssertEqualityUsing(context.CreateForCollectionItem(expectationIndex.ToString(), subject, expectation)); + + return scope.Discard(); + } + } + + private void StrictlyMatchAgainst(T[] subjects, object expectation, int expectationIndex) + { + parent.AssertEqualityUsing(context.CreateForCollectionItem(expectationIndex.ToString(), subjects[expectationIndex], expectation)); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumerableEquivalencyValidator.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumerableEquivalencyValidator.cs.meta new file mode 100644 index 0000000..f72b093 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/EnumerableEquivalencyValidator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 67c109b6b36a6a146b0af98eeb0d66a2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyAssertionOptions.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyAssertionOptions.cs new file mode 100644 index 0000000..29ac8da --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyAssertionOptions.cs @@ -0,0 +1,98 @@ +#region + +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using FluentAssertions.Common; +using FluentAssertions.Equivalency.Ordering; +using FluentAssertions.Equivalency.Selection; + +#endregion + +namespace FluentAssertions.Equivalency +{ + /// + /// Represents the run-time type-specific behavior of a structural equivalency assertion. + /// + public class EquivalencyAssertionOptions : + SelfReferenceEquivalencyAssertionOptions> + { + public EquivalencyAssertionOptions() + { + } + + internal EquivalencyAssertionOptions(IEquivalencyAssertionOptions defaults) : base(defaults) + { + } + + /// + /// Excludes the specified (nested) member from the structural equality check. + /// + public EquivalencyAssertionOptions Excluding(Expression> expression) + { + AddSelectionRule(new ExcludeMemberByPathSelectionRule(expression.GetMemberPath())); + return this; + } + + /// + /// Includes the specified member in the equality check. + /// + /// + /// This overrides the default behavior of including all declared members. + /// + public EquivalencyAssertionOptions Including(Expression> expression) + { + AddSelectionRule(new IncludeMemberByPathSelectionRule(expression.GetMemberPath())); + return this; + } + + /// + /// Includes the specified member in the equality check. + /// + /// + /// This overrides the default behavior of including all declared members. + /// + public EquivalencyAssertionOptions Including(Expression> predicate) + { + AddSelectionRule(new IncludeMemberByPredicateSelectionRule(predicate)); + return this; + } + + /// + /// Causes the collection identified by to be compared in the order + /// in which the items appear in the expectation. + /// + public EquivalencyAssertionOptions WithStrictOrderingFor( + Expression> expression) + { + orderingRules.Add(new PathBasedOrderingRule(expression.GetMemberPath())); + return this; + } + + /// + /// Creates a new set of options based on the current instance which acts on a + /// + /// + public EquivalencyAssertionOptions> AsCollection() + { + return new EquivalencyAssertionOptions>( + new CollectionMemberAssertionOptionsDecorator(this)); + } + } + + /// + /// Represents the run-time type-agnostic behavior of a structural equivalency assertion. + /// + public class EquivalencyAssertionOptions : SelfReferenceEquivalencyAssertionOptions + { + public EquivalencyAssertionOptions() + { + IncludingNestedObjects(); + + IncludingFields(); + IncludingProperties(); + + RespectingDeclaredTypes(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyAssertionOptions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyAssertionOptions.cs.meta new file mode 100644 index 0000000..31be74d --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyAssertionOptions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b685c6eac6f45b64687b8d7ff8233810 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyAssertionOptionsExtentions.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyAssertionOptionsExtentions.cs new file mode 100644 index 0000000..2c8711a --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyAssertionOptionsExtentions.cs @@ -0,0 +1,22 @@ +using System; + +namespace FluentAssertions.Equivalency +{ + public static class EquivalencyAssertionOptionsExtentions + { + /// + /// Returns either the run-time or compile-time type of the subject based on the options provided by the caller. + /// + public static Type GetSubjectType(this IEquivalencyAssertionOptions config, ISubjectInfo context) + { + bool useRuntimeType = ShouldUseRuntimeType(config); + + return useRuntimeType ? context.RuntimeType : context.CompileTimeType; + } + + private static bool ShouldUseRuntimeType(IEquivalencyAssertionOptions config) + { + return config.UseRuntimeTyping; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyAssertionOptionsExtentions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyAssertionOptionsExtentions.cs.meta new file mode 100644 index 0000000..0fc0aef --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyAssertionOptionsExtentions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a10844b59cc3a0543a4a070fd9fef032 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyValidationContext.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyValidationContext.cs new file mode 100644 index 0000000..af69494 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyValidationContext.cs @@ -0,0 +1,125 @@ +using System; + +namespace FluentAssertions.Equivalency +{ + public class EquivalencyValidationContext : IEquivalencyValidationContext + { + private Type compileTimeType; + + public EquivalencyValidationContext() + { + SelectedMemberDescription = ""; + SelectedMemberPath = ""; + } + + public SelectedMemberInfo SelectedMemberInfo { get; set; } + + public string SelectedMemberPath { get; set; } + + public string SelectedMemberDescription { get; set; } + + /// + /// Gets the value of the + /// + public object Subject { get; set; } + + /// + /// Gets the value of the . + /// + public object Expectation { get; set; } + + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + public string Because { get; set; } + + /// + /// Zero or more objects to format using the placeholders in . + /// + public object[] BecauseArgs { get; set; } + + /// + /// Gets a value indicating whether the current context represents the root of the object graph. + /// + public bool IsRoot + { + get + { + // SMELL: That prefix should be obtained from some kind of constant + return (SelectedMemberDescription.Length == 0) || + (RootIsCollection && SelectedMemberDescription.StartsWith("item[") && + !SelectedMemberDescription.Contains(".")); + } + } + + /// + /// Gets the compile-time type of the current object. If the current object is not the root object and the type is not , + /// then it returns the same as the property does. + /// + public Type CompileTimeType + { + get + { + return ((compileTimeType != typeof(object)) || ReferenceEquals(Subject, null)) ? compileTimeType : RuntimeType; + } + set { compileTimeType = value; } + } + + /// + /// Gets the run-time type of the current object. + /// + public Type RuntimeType + { + get + { + if (Subject != null) + { + return Subject.GetType(); + } + + if (SelectedMemberInfo != null) + { + return SelectedMemberInfo.MemberType; + } + + return CompileTimeType; + } + } + + /// + /// Gets or sets a value indicating that the root of the graph is a collection so all type-specific options apply on + /// the collection type and not on the root itself. + /// + public bool RootIsCollection { get; set; } + + public ITraceWriter Tracer { get; set; } + + public void TraceSingle(GetTraceMessage getTraceMessage) + { + if (Tracer != null) + { + string path = SelectedMemberDescription.Length > 0 ? SelectedMemberDescription : "root"; + Tracer.AddSingle($"{getTraceMessage(path)}"); + } + } + + public IDisposable TraceBlock(GetTraceMessage getTraceMessage) + { + if (Tracer != null) + { + string path = SelectedMemberDescription.Length > 0 ? SelectedMemberDescription : "root"; + return Tracer.AddBlock(getTraceMessage(path)); + } + else + { + return new Disposable(() => {}); + } + } + + public override string ToString() + { + return $"{{Path=\"{SelectedMemberDescription}\", Subject={Subject}, Expectation={Expectation}}}"; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyValidationContext.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyValidationContext.cs.meta new file mode 100644 index 0000000..b43b3fc --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyValidationContext.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1e21ec3d937a17340a14cb7b5f3ad895 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyValidationContextExtentions.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyValidationContextExtentions.cs new file mode 100644 index 0000000..868701c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyValidationContextExtentions.cs @@ -0,0 +1,91 @@ +using System; +using FluentAssertions.Common; + +namespace FluentAssertions.Equivalency +{ + internal static class EquivalencyValidationContextExtentions + { + internal static IEquivalencyValidationContext CreateForNestedMember(this IEquivalencyValidationContext context, + SelectedMemberInfo nestedMember, SelectedMemberInfo matchingProperty) + { + string memberDescription = nestedMember.Name; + string propertyPath = (context.SelectedMemberDescription.Length == 0) ? "member " : context.SelectedMemberDescription + "."; + + return new EquivalencyValidationContext + { + SelectedMemberInfo = nestedMember, + Subject = nestedMember.GetValue(context.Subject, null), + Expectation = matchingProperty.GetValue(context.Expectation, null), + SelectedMemberPath = context.SelectedMemberPath.Combine(memberDescription, "."), + SelectedMemberDescription = propertyPath + memberDescription, + Because = context.Because, + BecauseArgs = context.BecauseArgs, + CompileTimeType = nestedMember.MemberType, + RootIsCollection = context.RootIsCollection, + Tracer = context.Tracer + }; + } + + internal static IEquivalencyValidationContext CreateForCollectionItem(this IEquivalencyValidationContext context, + string index, T subject, object expectation) + { + string memberDescription = "[" + index + "]"; + string propertyPath = (context.SelectedMemberDescription.Length == 0) ? "item" : context.SelectedMemberDescription + String.Empty; + + return new EquivalencyValidationContext + { + SelectedMemberInfo = context.SelectedMemberInfo, + Subject = subject, + Expectation = expectation, + SelectedMemberPath = context.SelectedMemberPath.Combine(memberDescription, String.Empty), + SelectedMemberDescription = propertyPath + memberDescription, + Because = context.Because, + BecauseArgs = context.BecauseArgs, + CompileTimeType = typeof (T), + RootIsCollection = context.RootIsCollection, + Tracer = context.Tracer + }; + } + + internal static IEquivalencyValidationContext CreateForDictionaryItem( + this IEquivalencyValidationContext context, + TKey key, + TValue subject, + object expectation) + { + string memberDescription = "[" + key + "]"; + string propertyPath = (context.SelectedMemberDescription.Length == 0) ? "pair" : context.SelectedMemberDescription + String.Empty; + + return new EquivalencyValidationContext + { + SelectedMemberInfo = context.SelectedMemberInfo, + Subject = subject, + Expectation = expectation, + SelectedMemberPath = context.SelectedMemberPath.Combine(memberDescription, String.Empty), + SelectedMemberDescription = propertyPath + memberDescription, + Because = context.Because, + BecauseArgs = context.BecauseArgs, + CompileTimeType = typeof (TValue), + RootIsCollection = context.RootIsCollection, + Tracer = context.Tracer + }; + } + + internal static IEquivalencyValidationContext CreateWithDifferentSubject(this IEquivalencyValidationContext context, + object subject, Type compileTimeType) + { + return new EquivalencyValidationContext + { + CompileTimeType = compileTimeType, + Expectation = context.Expectation, + SelectedMemberDescription = context.SelectedMemberDescription, + SelectedMemberInfo = context.SelectedMemberInfo, + SelectedMemberPath = context.SelectedMemberPath, + Because = context.Because, + BecauseArgs = context.BecauseArgs, + Subject = subject, + Tracer = context.Tracer + }; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyValidationContextExtentions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyValidationContextExtentions.cs.meta new file mode 100644 index 0000000..b922afe --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyValidationContextExtentions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e57117a4e1be4e243a041ab2a578fca2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyValidator.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyValidator.cs new file mode 100644 index 0000000..97a4087 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyValidator.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using FluentAssertions.Execution; + +namespace FluentAssertions.Equivalency +{ + /// + /// Is responsible for validating the equality of one or more properties of a subject with another object. + /// + public class EquivalencyValidator : IEquivalencyValidator + { + #region Private Definitions + + private const int MaxDepth = 10; + + private readonly IEquivalencyAssertionOptions config; + + #endregion + + public EquivalencyValidator(IEquivalencyAssertionOptions config) + { + this.config = config; + } + + public void AssertEquality(EquivalencyValidationContext context) + { + using (var scope = new AssertionScope()) + { + scope.AddReportable("configuration", config.ToString()); + scope.AddNonReportable("objects", new ObjectTracker(config.CyclicReferenceHandling)); + + scope.BecauseOf(context.Because, context.BecauseArgs); + + AssertEqualityUsing(context); + + if (context.Tracer != null) + { + scope.AddReportable("trace", context.Tracer.ToString()); + } + } + } + + public void AssertEqualityUsing(IEquivalencyValidationContext context) + { + if (ContinueRecursion(context.SelectedMemberPath)) + { + AssertionScope scope = AssertionScope.Current; + scope.AddNonReportable("context", (context.SelectedMemberDescription.Length == 0) ? "subject" : context.SelectedMemberDescription); + scope.AddNonReportable("subject", context.Subject); + scope.AddNonReportable("expectation", context.Expectation); + + var objectTracker = scope.Get("objects"); + + if (!objectTracker.IsCyclicReference(new ObjectReference(context.Subject, context.SelectedMemberPath))) + { + bool wasHandled = false; + + foreach (var step in AssertionOptions.EquivalencySteps) + { + if (step.CanHandle(context, config)) + { + if (step.Handle(context, this, config)) + { + wasHandled = true; + break; + } + } + } + + if (!wasHandled) + { + Execute.Assertion.FailWith( + "No IEquivalencyStep was found to handle the context. " + + "This is likely a bug in Fluent Assertions."); + } + } + } + } + + private bool ContinueRecursion(string memberAccessPath) + { + if (config.AllowInfiniteRecursion || !HasReachedMaximumRecursionDepth(memberAccessPath)) + { + return true; + } + + AssertionScope.Current.FailWith( + "The maximum recursion depth was reached. " + + "The maximum recursion depth limitation prevents stack overflow from " + + "occuring when certain types of cycles exist in the object graph " + + "or the object graph's depth is very high or infinite. " + + "This limitation may be disabled using the config parameter." + + Environment.NewLine + Environment.NewLine + + "The member access chain when max depth was hit was: " + + memberAccessPath); + + return false; + } + + private static bool HasReachedMaximumRecursionDepth(string propertyPath) + { + int depth = propertyPath.Cast().Count(chr => chr == '.'); + + return (depth >= MaxDepth); + } + } +} diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyValidator.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyValidator.cs.meta new file mode 100644 index 0000000..74a28bb --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/EquivalencyValidator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 63b953d4f78bd754b88e2e43d6343a11 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/FieldSelectedMemberInfo.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/FieldSelectedMemberInfo.cs new file mode 100644 index 0000000..ce3324a --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/FieldSelectedMemberInfo.cs @@ -0,0 +1,45 @@ +using System; +using System.Linq; +using System.Reflection; +using FluentAssertions.Common; + +namespace FluentAssertions.Equivalency +{ + /// + /// Provides an ISelectedMemberInfo for FieldInfo objects + /// + internal class FieldSelectedMemberInfo : MemberInfoSelectedMemberInfo + { + private readonly FieldInfo fieldInfo; + + public FieldSelectedMemberInfo(FieldInfo fieldInfo) : base(fieldInfo) + { + this.fieldInfo = fieldInfo; + } + + public override object GetValue(object obj, object[] index) + { + if ((index != null) && index.Any()) + { + throw new TargetParameterCountException("Parameter count mismatch."); + } + + return fieldInfo.GetValue(obj); + } + + public override Type MemberType + { + get { return fieldInfo.FieldType; } + } + + internal override CSharpAccessModifier GetAccessModifier + { + get { return fieldInfo.GetCSharpAccessModifier(); } + } + + internal override CSharpAccessModifier SetAccessModifier + { + get { return fieldInfo.GetCSharpAccessModifier(); } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/FieldSelectedMemberInfo.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/FieldSelectedMemberInfo.cs.meta new file mode 100644 index 0000000..bff3395 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/FieldSelectedMemberInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d2b25cddd8824a245956f539ee51ed18 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/GenericDictionaryEquivalencyStep.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/GenericDictionaryEquivalencyStep.cs new file mode 100644 index 0000000..64b761c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/GenericDictionaryEquivalencyStep.cs @@ -0,0 +1,223 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using FluentAssertions.Common; +using FluentAssertions.Execution; + +namespace FluentAssertions.Equivalency +{ + /// + /// I think (but did not try) this would have been easier using 'dynamic' but that is + /// precluded by some of the PCL targets. + /// + public class GenericDictionaryEquivalencyStep : IEquivalencyStep + { + public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) + { + Type subjectType = config.GetSubjectType(context); + + return ((context.Subject != null) && GetIDictionaryInterfaces(subjectType).Any()); + } + + private static Type[] GetIDictionaryInterfaces(Type type) + { + return Common.TypeExtensions.GetClosedGenericInterfaces( + type, + typeof(IDictionary<,>)); + } + + public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config) + { + if (PreconditionsAreMet(context, config)) + { + AssertDictionaryEquivalence(context, parent, config); + } + + return true; + } + + private static bool PreconditionsAreMet(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) + { + Type subjectType = config.GetSubjectType(context); + + return (AssertImplementsOnlyOneDictionaryInterface(context.Subject) + && AssertExpectationIsNotNull(context.Subject, context.Expectation) + && AssertIsCompatiblyTypedDictionary(subjectType, context.Expectation) + && AssertSameLength(context.Subject, subjectType, context.Expectation)); + } + + private static bool AssertExpectationIsNotNull(object subject, object expectation) + { + return AssertionScope.Current + .ForCondition(!ReferenceEquals(expectation, null)) + .FailWith("Expected {context:Subject} to be {0}, but found {1}.", null, subject); + } + + private static bool AssertImplementsOnlyOneDictionaryInterface(object subject) + { + Type[] interfaces = GetIDictionaryInterfaces(subject.GetType()); + bool multipleInterfaces = (interfaces.Count() > 1); + + if (multipleInterfaces) + { + AssertionScope.Current.FailWith( + string.Format( + "{{context:Subject}} implements multiple dictionary types. " + + "It is not known which type should be use for equivalence.{0}" + + "The following IDictionary interfaces are implemented: {1}", + Environment.NewLine, + String.Join(", ", (IEnumerable)interfaces))); + return false; + } + + return true; + } + + private static bool AssertIsCompatiblyTypedDictionary(Type subjectType, object expectation) + { + Type subjectDictionaryType = GetIDictionaryInterface(subjectType); + Type subjectKeyType = GetDictionaryKeyType(subjectDictionaryType); + + Type[] expectationDictionaryInterfaces = GetIDictionaryInterfaces(expectation.GetType()); + + if (!expectationDictionaryInterfaces.Any()) + { + AssertionScope.Current.FailWith( + "{context:subject} is a dictionary and cannot be compared with a non-dictionary type."); + return false; + } + + Type[] suitableDictionaryInterfaces = expectationDictionaryInterfaces.Where( + @interface => GetDictionaryKeyType(@interface).IsAssignableFrom(subjectKeyType)).ToArray(); + + if (suitableDictionaryInterfaces.Count() > 1) + { + // Code could be written to handle this better, but is it really worth the effort? + AssertionScope.Current.FailWith( + "The expected object implements multiple IDictionary interfaces. " + + "If you need to use ShouldBeEquivalentTo in this case please file " + + "a bug with the FluentAssertions devlopment team"); + return false; + } + + if (!suitableDictionaryInterfaces.Any()) + { + AssertionScope.Current.FailWith( + string.Format( + "The {{context:subject}} dictionary has keys of type {0}; " + + "however, the expected dictionary is not keyed with any compatible types.{1}" + + "The expected dictionary implements: {2}", + subjectKeyType, + Environment.NewLine, + string.Join(",", (IEnumerable)expectationDictionaryInterfaces))); + return false; + } + + return true; + } + + private static Type GetDictionaryKeyType(Type subjectType) + { + return subjectType.GetGenericArguments()[0]; + } + + private static bool AssertSameLength(object subject, Type subjectType, object expectation) + { + string methodName = + ExpressionExtensions.GetMethodName(() => AssertSameLength(null, null)); + + MethodCallExpression assertSameLength = Expression.Call( + typeof(GenericDictionaryEquivalencyStep), + methodName, + GetDictionaryTypeArguments(subjectType) + .Concat(GetDictionaryTypeArguments(expectation.GetType())) + .ToArray(), + Expression.Constant(subject, GetIDictionaryInterface(subjectType)), + Expression.Constant(expectation, GetIDictionaryInterface(expectation.GetType()))); + + return (bool)Expression.Lambda(assertSameLength).Compile().DynamicInvoke(); + } + + private static IEnumerable GetDictionaryTypeArguments(Type subjectType) + { + var dictionaryType = GetIDictionaryInterface(subjectType); + + return dictionaryType.GetGenericArguments(); + } + + private static Type GetIDictionaryInterface(Type subjectType) + { + return GetIDictionaryInterfaces(subjectType).Single(); + } + + private static bool AssertSameLength( + IDictionary subject, + IDictionary expectation) + { + return + AssertionScope.Current.ForCondition(subject.Count == expectation.Count) + .FailWith( + "Expected {context:subject} to be a dictionary with {0} item(s), but found {1} item(s).", + expectation.Count, + subject.Count); + } + + private static void AssertDictionaryEquivalence( + IEquivalencyValidationContext context, + IEquivalencyValidator parent, + IEquivalencyAssertionOptions config) + { + Type subjectType = config.GetSubjectType(context); + + string methodName = + ExpressionExtensions.GetMethodName( + () => AssertDictionaryEquivalence(null, null, null, null, null)); + + var assertDictionaryEquivalence = Expression.Call( + typeof(GenericDictionaryEquivalencyStep), + methodName, + GetDictionaryTypeArguments(subjectType) + .Concat(GetDictionaryTypeArguments(context.Expectation.GetType())) + .ToArray(), + Expression.Constant(context), + Expression.Constant(parent), + Expression.Constant(config), + Expression.Constant(context.Subject, GetIDictionaryInterface(subjectType)), + Expression.Constant(context.Expectation, GetIDictionaryInterface(context.Expectation.GetType()))); + + Expression.Lambda(assertDictionaryEquivalence).Compile().DynamicInvoke(); + } + + private static void AssertDictionaryEquivalence( + EquivalencyValidationContext context, + IEquivalencyValidator parent, + IEquivalencyAssertionOptions config, + IDictionary subject, + IDictionary expectation) where TSubjectKey : TExpectKey + { + foreach (TSubjectKey key in subject.Keys) + { + TExpectedValue expectedValue; + + if (expectation.TryGetValue(key, out expectedValue)) + { + if (config.IsRecursive) + { + parent.AssertEqualityUsing(context.CreateForDictionaryItem(key, subject[key], expectation[key])); + + } + else + { + subject[key].Should().Be(expectation[key], context.Because, context.BecauseArgs); + } + } + else + { + AssertionScope.Current.FailWith("{context:subject} contains unexpected key {0}", key); + } + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/GenericDictionaryEquivalencyStep.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/GenericDictionaryEquivalencyStep.cs.meta new file mode 100644 index 0000000..c538b77 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/GenericDictionaryEquivalencyStep.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 21f12626cadd95a46a0bdae54c5fa0f2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/GenericEnumerableEquivalencyStep.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/GenericEnumerableEquivalencyStep.cs new file mode 100644 index 0000000..4e0afd1 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/GenericEnumerableEquivalencyStep.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using FluentAssertions.Common; +using FluentAssertions.Execution; + +namespace FluentAssertions.Equivalency +{ + public class GenericEnumerableEquivalencyStep : IEquivalencyStep + { + /// + /// Gets a value indicating whether this step can handle the verificationScope subject and/or expectation. + /// + public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) + { + var subjectType = config.GetSubjectType(context); + + return (context.Subject != null) && IsGenericCollection(subjectType); + } + + /// + /// Applies a step as part of the task to compare two objects for structural equality. + /// + /// + /// Should return true if the subject matches the expectation or if no additional assertions + /// have to be executed. Should return false otherwise. + /// + /// + /// May throw when preconditions are not met or if it detects mismatching data. + /// + public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, + IEquivalencyAssertionOptions config) + { + Type subjectType = config.GetSubjectType(context); + + var interfaceTypes = GetIEnumerableInterfaces(subjectType) + .Select(type => "IEnumerable<" + type.GetGenericArguments().Single() + ">") + .ToList(); + + AssertionScope.Current + .ForCondition(interfaceTypes.Count() == 1) + .FailWith("{context:Subject} implements {0}, so cannot determine which one " + + "to use for asserting the equivalency of the collection. ", interfaceTypes); + + if (AssertExpectationIsCollection(context.Expectation, context.Subject)) + { + var validator = new EnumerableEquivalencyValidator(parent, context) + { + Recursive = context.IsRoot || config.IsRecursive, + OrderingRules = config.OrderingRules + }; + + Type typeOfEnumeration = GetTypeOfEnumeration(subjectType); + + Expression subjectToArray = ToArray(context.Subject, typeOfEnumeration); + Expression expectationToArray = + Expression.Constant(EnumerableEquivalencyStep.ToArray(context.Expectation)); + + MethodCallExpression executeExpression = Expression.Call( + Expression.Constant(validator), + ExpressionExtensions.GetMethodName(() => validator.Execute(null, null)), + new[] {typeOfEnumeration}, + subjectToArray, + expectationToArray); + + Expression.Lambda(executeExpression).Compile().DynamicInvoke(); + } + + return true; + } + + private static bool AssertExpectationIsCollection(object expectation, object subject) + { + return AssertionScope.Current + .ForCondition(!ReferenceEquals(expectation, null)) + .FailWith("Expected {context:Subject} to be {0}, but found {1}.", null, subject) + .Then + .ForCondition(IsGenericCollection(expectation.GetType())) + .FailWith("Expected {context:Subject} to be {0}, but found {1}.", expectation, subject); + } + + private static bool IsGenericCollection(Type type) + { + var enumerableInterfaces = GetIEnumerableInterfaces(type); + + return (!typeof (string).IsAssignableFrom(type)) && enumerableInterfaces.Any(); + } + + private static Type[] GetIEnumerableInterfaces(Type type) + { + Type soughtType = typeof (IEnumerable<>); + + return Common.TypeExtensions.GetClosedGenericInterfaces(type, soughtType); + } + + private static Type GetTypeOfEnumeration(Type enumerableType) + { + Type interfaceType = GetIEnumerableInterfaces(enumerableType).Single(); + + return interfaceType.GetGenericArguments().Single(); + } + + private static MethodCallExpression ToArray(object value, Type typeOfEnumeration) + { + return Expression.Call( + typeof (Enumerable), + "ToArray", + new[] {typeOfEnumeration}, + Expression.Constant(value, typeof (IEnumerable<>).MakeGenericType(typeOfEnumeration))); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/GenericEnumerableEquivalencyStep.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/GenericEnumerableEquivalencyStep.cs.meta new file mode 100644 index 0000000..6f88eed --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/GenericEnumerableEquivalencyStep.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b1fc37046852ba549b24f5dcf273b42f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/IAssertionContext.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/IAssertionContext.cs new file mode 100644 index 0000000..d9e7416 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/IAssertionContext.cs @@ -0,0 +1,36 @@ +namespace FluentAssertions.Equivalency +{ + /// + /// Provides the required information for executing an equality assertion between a subject and an expectation. + /// + /// The type of the subject. + public interface IAssertionContext + { + /// + /// Gets the of the member that returned the current object, or null if the current + /// object represents the root object. + /// + SelectedMemberInfo SubjectProperty { get; } + + /// + /// Gets the value of the + /// + TSubject Subject { get; } + + /// + /// Gets the value of the expectation object that was matched with the subject using a . + /// + TSubject Expectation { get; } + + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + string Because { get; set; } + + /// + /// Zero or more objects to format using the placeholders in . + /// + object[] BecauseArgs { get; set; } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/IAssertionContext.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/IAssertionContext.cs.meta new file mode 100644 index 0000000..f25c87b --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/IAssertionContext.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cd3c7b0b5caccd849bead603f7307642 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/IAssertionRule.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/IAssertionRule.cs new file mode 100644 index 0000000..63e5910 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/IAssertionRule.cs @@ -0,0 +1,15 @@ +namespace FluentAssertions.Equivalency +{ + public interface IAssertionRule + { + /// + /// Defines how a subject's property is compared for equality with the same property of the expectation. + /// + /// + /// Returns true if the rule was applied correctly and the assertion didn't cause any exceptions. + /// Returns false if this rule doesn't support the subject's type. + /// Throws if the rule did support the data type but assertion fails. + /// + bool AssertEquality(IEquivalencyValidationContext context); + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/IAssertionRule.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/IAssertionRule.cs.meta new file mode 100644 index 0000000..387c58b --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/IAssertionRule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ed89c2c4472665e43b258fc0c91df8ad +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyAssertionOptions.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyAssertionOptions.cs new file mode 100644 index 0000000..5ab255d --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyAssertionOptions.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; + +namespace FluentAssertions.Equivalency +{ + /// + /// Provides the run-time details of the class. + /// + public interface IEquivalencyAssertionOptions + { + /// + /// Gets an ordered collection of selection rules that define what properties are included. + /// + IEnumerable SelectionRules { get; } + + /// + /// Gets an ordered collection of matching rules that determine which subject properties are matched with which + /// expectation properties. + /// + IEnumerable MatchingRules { get; } + + /// + /// Gets a value indicating whether or not the assertion must perform a deep comparison. + /// + bool IsRecursive { get; } + + /// + /// Gets a value indicating whether recursion is allowed to continue indefinitely. + /// + bool AllowInfiniteRecursion { get; } + + /// + /// Gets value indicating how cyclic references should be handled. By default, it will throw an exception. + /// + CyclicReferenceHandling CyclicReferenceHandling { get; } + + /// + /// Gets an ordered collection of rules that determine whether or not the order of collections is important. By default, + /// ordering is irrelevant. + /// + OrderingRuleCollection OrderingRules { get; } + + /// + /// Gets value indicating how the enums should be compared. + /// + EnumEquivalencyHandling EnumEquivalencyHandling { get; } + + /// + /// Gets an ordered collection of Equivalency steps how a subject is compared with the expectation. + /// + IEnumerable UserEquivalencySteps { get; } + + /// + /// Gets a value indicating whether the runtime type should be used rather than the declared type. + /// + bool UseRuntimeTyping { get; } + + /// + /// Gets a value indicating whether properties should be considered. + /// + bool IncludeProperties { get; } + + /// + /// Gets a value indicating whether fields should be considered. + /// + bool IncludeFields { get; } + + /// + /// Gets the currently configured tracer, or null if no tracing was configured. + /// + ITraceWriter TraceWriter { get; } + + /// + /// Gets a value indicating whether the should be treated as having value semantics. + /// + bool IsValueType(Type type); + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyAssertionOptions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyAssertionOptions.cs.meta new file mode 100644 index 0000000..d63e41f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyAssertionOptions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1f70cead0bb06dd468cc63917ac67e08 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyStep.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyStep.cs new file mode 100644 index 0000000..822d5f7 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyStep.cs @@ -0,0 +1,25 @@ +namespace FluentAssertions.Equivalency +{ + /// + /// Defines a step in the process of comparing two object graphs for structural equivalency. + /// + public interface IEquivalencyStep + { + /// + /// Gets a value indicating whether this step can handle the current subject and/or expectation. + /// + bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config); + + /// + /// Applies a step as part of the task to compare two objects for structural equality. + /// + /// + /// Should return true if the subject matches the expectation or if no additional assertions + /// have to be executed. Should return false otherwise. + /// + /// + /// May throw when preconditions are not met or if it detects mismatching data. + /// + bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config); + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyStep.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyStep.cs.meta new file mode 100644 index 0000000..39560ce --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyStep.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 768db014a3c136d439ce5ec587caf0c2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyValidationContext.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyValidationContext.cs new file mode 100644 index 0000000..1f17eed --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyValidationContext.cs @@ -0,0 +1,69 @@ +using System; + +namespace FluentAssertions.Equivalency +{ + /// + /// Provides information on a particular property during an assertion for structural equality of two object graphs. + /// + public interface IEquivalencyValidationContext : ISubjectInfo + { + /// + /// Gets the value of the . + /// + object Expectation { get; } + + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + string Because { get; } + + /// + /// Zero or more objects to format using the placeholders in . + /// + object[] BecauseArgs { get; } + + /// + /// Gets a value indicating whether the current context represents the root of the object graph. + /// + bool IsRoot { get; } + + /// + /// Gets the value of the + /// + object Subject { get; } + + /// + /// Gets or sets a value indicating that the root of the graph is a collection so all type-specific options apply on + /// the collection type and not on the root itself. + /// + bool RootIsCollection { get; set; } + + /// + /// Gets or sets the current trace writer or null if no tracing has been enabled. + /// + ITraceWriter Tracer { get; set; } + + /// + /// Starts a block that scopes an operation that will be writted to the currently configured + /// after the returned disposable is dispoed.. + /// + /// + /// If no tracer has been configured, the call will be ignored. + /// + IDisposable TraceBlock(GetTraceMessage getMessage); + + /// + /// Writes a single line to the currently configured . + /// + /// + /// If no tracer has been configured, the call will be ignored. + /// + void TraceSingle(GetTraceMessage getMessage); + } + + /// + /// Defines a function that takes the current path and returns the trace message to log. + /// + public delegate string GetTraceMessage(string path); +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyValidationContext.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyValidationContext.cs.meta new file mode 100644 index 0000000..9226521 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyValidationContext.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5d6fb52cbcca9154eb29238091d8b464 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyValidator.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyValidator.cs new file mode 100644 index 0000000..f6e3017 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyValidator.cs @@ -0,0 +1,7 @@ +namespace FluentAssertions.Equivalency +{ + public interface IEquivalencyValidator + { + void AssertEqualityUsing(IEquivalencyValidationContext context); + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyValidator.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyValidator.cs.meta new file mode 100644 index 0000000..c4f4004 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/IEquivalencyValidator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bf87b8955c14fac46a2bd46f10e95573 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/IMemberMatchingRule.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/IMemberMatchingRule.cs new file mode 100644 index 0000000..88916df --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/IMemberMatchingRule.cs @@ -0,0 +1,34 @@ +namespace FluentAssertions.Equivalency +{ + /// + /// Represents a rule that defines how to map the members from the subject-under-test with the members + /// on the expectation object. + /// + public interface IMemberMatchingRule + { + /// + /// Attempts to find a member on the expectation that should be compared with the + /// during a structural equality. + /// + /// + /// Whether or not a match is required or optional is up to the specific rule. If no match is found and this is not an issue, + /// simply return null. + /// + /// + /// The of the subject's member for which a match must be found. Can never + /// be null. + /// + /// + /// The expectation object for which a matching member must be returned. Can never be null. + /// + /// + /// The dotted path from the root object to the current member. Will never be null. + /// + /// + /// + /// Returns the of the property with which to compare the subject with, or null + /// if no match was found. + /// + SelectedMemberInfo Match(SelectedMemberInfo subjectMember, object expectation, string memberPath, IEquivalencyAssertionOptions config); + } +} diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/IMemberMatchingRule.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/IMemberMatchingRule.cs.meta new file mode 100644 index 0000000..44f4092 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/IMemberMatchingRule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f19848b8fe1c74e40930c6cae426df14 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/IMemberSelectionRule.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/IMemberSelectionRule.cs new file mode 100644 index 0000000..d140eac --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/IMemberSelectionRule.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; + +namespace FluentAssertions.Equivalency +{ + /// + /// Represents a rule that defines which members of the subject-under-test to include while comparing + /// two objects for structural equality. + /// + public interface IMemberSelectionRule + { + /// + /// Gets a value indicating whether this rule should override the default selection rules that include all members. + /// + bool IncludesMembers { get; } + + /// + /// Adds or removes properties to/from the collection of subject members that must be included while + /// comparing two objects for structural equality. + /// + /// + /// A collection of members that was prepopulated by other selection rules. Can be empty. + /// + /// + /// + /// Type info about the subject. + /// + /// + /// The collection of members after applying this rule. Can contain less or more than was passed in. + /// + IEnumerable SelectMembers(IEnumerable selectedMembers, ISubjectInfo context, IEquivalencyAssertionOptions config); + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/IMemberSelectionRule.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/IMemberSelectionRule.cs.meta new file mode 100644 index 0000000..6bc5934 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/IMemberSelectionRule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2c89b228b72818040b34fa79cddbf040 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/IOrderingRule.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/IOrderingRule.cs new file mode 100644 index 0000000..3e2094f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/IOrderingRule.cs @@ -0,0 +1,13 @@ +namespace FluentAssertions.Equivalency +{ + /// + /// Defines a rule that is used to determine whether the order of items in collections is relevant or not. + /// + public interface IOrderingRule + { + /// + /// Determines if ordering of the member referred to by the current is relevant. + /// + OrderStrictness Evaluate(ISubjectInfo subjectInfo); + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/IOrderingRule.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/IOrderingRule.cs.meta new file mode 100644 index 0000000..ffe61b2 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/IOrderingRule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5b6d7026c722f0a4888d38e4e409467e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/ISubjectInfo.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/ISubjectInfo.cs new file mode 100644 index 0000000..c874cef --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/ISubjectInfo.cs @@ -0,0 +1,38 @@ +using System; +using System.Reflection; + +namespace FluentAssertions.Equivalency +{ + /// + /// Provides details about the subject's root or nested member. + /// + public interface ISubjectInfo + { + /// + /// Gets the of the member that returned the current object, or null if the current + /// object represents the root object. + /// + SelectedMemberInfo SelectedMemberInfo { get; } + + /// + /// Gets the full path from the root object until the current object separated by dots. + /// + string SelectedMemberPath { get; } + + /// + /// Gets a display-friendly representation of the . + /// + string SelectedMemberDescription { get; } + + /// + /// Gets the compile-time type of the current object. If the current object is not the root object and the type is not , + /// then it returns the same as the property does. + /// + Type CompileTimeType { get; } + + /// + /// Gets the run-time type of the current object. + /// + Type RuntimeType { get; } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/ISubjectInfo.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/ISubjectInfo.cs.meta new file mode 100644 index 0000000..a6aed43 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/ISubjectInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6b8a4134eeffbbe44bfcd56bc48bbb2c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching.meta new file mode 100644 index 0000000..681c38a --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d53ae6a0104ea8643b408c060d689334 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching/CollectionMemberMatchingRuleDecorator.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching/CollectionMemberMatchingRuleDecorator.cs new file mode 100644 index 0000000..f43a293 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching/CollectionMemberMatchingRuleDecorator.cs @@ -0,0 +1,23 @@ +namespace FluentAssertions.Equivalency.Matching +{ + internal class CollectionMemberMatchingRuleDecorator : IMemberMatchingRule + { + private readonly IMemberMatchingRule matchingRule; + + public CollectionMemberMatchingRuleDecorator(IMemberMatchingRule matchingRule) + { + this.matchingRule = matchingRule; + } + + public SelectedMemberInfo Match(SelectedMemberInfo subjectMember, object expectation, string memberPath, + IEquivalencyAssertionOptions config) + { + return matchingRule.Match(subjectMember, expectation, memberPath, config); + } + + public override string ToString() + { + return matchingRule.ToString(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching/CollectionMemberMatchingRuleDecorator.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching/CollectionMemberMatchingRuleDecorator.cs.meta new file mode 100644 index 0000000..d8a7235 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching/CollectionMemberMatchingRuleDecorator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 056a01b4da65b5a4daedc5dd36dba5ed +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching/MustMatchByNameRule.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching/MustMatchByNameRule.cs new file mode 100644 index 0000000..559467f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching/MustMatchByNameRule.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using FluentAssertions.Common; +using FluentAssertions.Execution; + +namespace FluentAssertions.Equivalency.Matching +{ + /// + /// Requires the expectation object to have a member with the exact same name. + /// + internal class MustMatchByNameRule : IMemberMatchingRule + { + public SelectedMemberInfo Match(SelectedMemberInfo subjectMember, object expectation, string memberPath, IEquivalencyAssertionOptions config) + { + SelectedMemberInfo compareeSelectedMemberInfoInfo = null; + + if (config.IncludeProperties) + { + compareeSelectedMemberInfoInfo = SelectedMemberInfo.Create(expectation.GetType() + .FindProperty(subjectMember.Name, subjectMember.MemberType)); + } + + if ((compareeSelectedMemberInfoInfo == null) && config.IncludeFields) + { + compareeSelectedMemberInfoInfo = SelectedMemberInfo.Create(expectation.GetType() + .FindField(subjectMember.Name, subjectMember.MemberType)); + } + + if ((compareeSelectedMemberInfoInfo == null) && ExpectationImplementsMemberExplicitly(expectation, subjectMember)) + { + compareeSelectedMemberInfoInfo = subjectMember; + } + + if (compareeSelectedMemberInfoInfo == null) + { + string path = (memberPath.Length > 0) ? memberPath + "." : "member "; + + Execute.Assertion.FailWith( + "Subject has " + path + subjectMember.Name + " that the other object does not have."); + } + + return compareeSelectedMemberInfoInfo; + } + + private static bool ExpectationImplementsMemberExplicitly(object expectation, SelectedMemberInfo subjectMember) + { + return subjectMember.DeclaringType.IsInstanceOfType(expectation); + } + + /// 2 + public override string ToString() + { + return "Match member by name (or throw)"; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching/MustMatchByNameRule.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching/MustMatchByNameRule.cs.meta new file mode 100644 index 0000000..523d5a0 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching/MustMatchByNameRule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f06f25b9944dbcd42b0c21a88670b680 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching/TryMatchByNameRule.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching/TryMatchByNameRule.cs new file mode 100644 index 0000000..770a6c8 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching/TryMatchByNameRule.cs @@ -0,0 +1,21 @@ +using FluentAssertions.Common; + +namespace FluentAssertions.Equivalency.Matching +{ + /// + /// Finds a member of the expectation with the exact same name, but doesn't require it. + /// + internal class TryMatchByNameRule : IMemberMatchingRule + { + public SelectedMemberInfo Match(SelectedMemberInfo subjectMember, object expectation, string memberPath, IEquivalencyAssertionOptions config) + { + return expectation.GetType().FindMember(subjectMember.Name, subjectMember.MemberType); + } + + /// 2 + public override string ToString() + { + return "Try to match member by name"; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching/TryMatchByNameRule.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching/TryMatchByNameRule.cs.meta new file mode 100644 index 0000000..bbf3728 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Matching/TryMatchByNameRule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a8be84207e5576d4284297b3d7922deb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/MemberInfoSelectedMemberInfo.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/MemberInfoSelectedMemberInfo.cs new file mode 100644 index 0000000..7a5088c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/MemberInfoSelectedMemberInfo.cs @@ -0,0 +1,58 @@ +using System; +using System.Reflection; + +namespace FluentAssertions.Equivalency +{ + /// + /// A partial ISelectedMemberInfo implementation that delegates to a MemberInfo object + /// + internal abstract class MemberInfoSelectedMemberInfo : SelectedMemberInfo + { + private readonly MemberInfo memberInfo; + + protected MemberInfoSelectedMemberInfo(MemberInfo memberInfo) + { + this.memberInfo = memberInfo; + } + + public override string Name + { + get { return memberInfo.Name; } + } + + public override Type DeclaringType + { + get { return memberInfo.DeclaringType; } + } + + protected bool Equals(MemberInfoSelectedMemberInfo other) + { + return memberInfo.Equals(other.memberInfo); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != this.GetType()) + { + return false; + } + + return Equals((MemberInfoSelectedMemberInfo) obj); + } + + public override int GetHashCode() + { + return memberInfo.GetHashCode(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/MemberInfoSelectedMemberInfo.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/MemberInfoSelectedMemberInfo.cs.meta new file mode 100644 index 0000000..3286e5c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/MemberInfoSelectedMemberInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: afceae3dd1995b74c9f120334e34183c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/MultiDimensionalArrayEquivalencyStep.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/MultiDimensionalArrayEquivalencyStep.cs new file mode 100644 index 0000000..c360f97 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/MultiDimensionalArrayEquivalencyStep.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using FluentAssertions.Execution; + +namespace FluentAssertions.Equivalency +{ + /// + /// Supports recursively comparing two multi-dimensional arrays for equivalency using strict order for the array items + /// themselves. + /// + internal class MultiDimensionalArrayEquivalencyStep : IEquivalencyStep + { + public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) + { + Array array = context.Subject as Array; + return (array != null) && (array.Rank > 1); + } + + public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, + IEquivalencyAssertionOptions config) + { + Array subjectAsArray = (Array) context.Subject; + + if (AreComparable(context, subjectAsArray)) + { + Digit digit = BuildDigitsRepresentingAllIndices(subjectAsArray); + + do + { + var expectation = ((Array) context.Expectation).GetValue(digit.Indices); + IEquivalencyValidationContext itemContext = context.CreateForCollectionItem( + string.Join(",", digit.Indices), + subjectAsArray.GetValue(digit.Indices), + expectation); + + parent.AssertEqualityUsing(itemContext); + } + while (digit.Increment()); + } + + return true; + } + + private static Digit BuildDigitsRepresentingAllIndices(Array subjectAsArray) + { + return Enumerable + .Range(0, subjectAsArray.Rank) + .Reverse() + .Aggregate((Digit) null, (next, rank) => new Digit(subjectAsArray.GetLength(rank), next)); + } + + private static bool AreComparable(IEquivalencyValidationContext context, Array subjectAsArray) + { + return + IsArray(context.Expectation) && + HaveSameRank(context.Expectation, subjectAsArray) && + HaveSameDimensions(context.Expectation, subjectAsArray); + } + + private static bool IsArray(object expectation) + { + return AssertionScope.Current + .ForCondition(!ReferenceEquals(expectation, null)) + .FailWith("Can't compare a multi-dimensional array to {0}.", new object[] {null}) + .Then + .ForCondition(expectation is Array) + .FailWith("Can't compare a multi-dimensional array to something else."); + } + + private static bool HaveSameDimensions(object expectation, Array actual) + { + bool sameDimensions = true; + + for (int dimension = 0; dimension < actual.Rank; dimension++) + { + int expectedLength = ((Array) expectation).GetLength(dimension); + int actualLength = actual.GetLength(dimension); + + sameDimensions = sameDimensions & AssertionScope.Current + .ForCondition(expectedLength == actualLength) + .FailWith("Expected dimension {0} to contain {1} item(s), but found {2}.", dimension, expectedLength, + actualLength); + } + + return sameDimensions; + } + + private static bool HaveSameRank(object expectation, Array actual) + { + var expectationAsArray = (Array) expectation; + + return AssertionScope.Current + .ForCondition(actual.Rank == expectationAsArray.Rank) + .FailWith("Expected {context:array} to have {0} dimension(s), but it has {1}.", expectationAsArray.Rank, + actual.Rank); + } + } + + internal class Digit + { + private readonly int length; + private readonly Digit nextDigit; + private int index; + + public Digit(int length, Digit nextDigit) + { + this.length = length; + this.nextDigit = nextDigit; + } + + public int[] Indices + { + get + { + var indices = new List(); + + Digit digit = this; + while (digit != null) + { + indices.Add(digit.index); + digit = digit.nextDigit; + } + + return indices.ToArray(); + } + } + + public bool Increment() + { + bool success = (nextDigit != null) && nextDigit.Increment(); + if (!success) + { + if (index < (length - 1)) + { + index++; + success = true; + } + else + { + index = 0; + } + } + + return success; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/MultiDimensionalArrayEquivalencyStep.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/MultiDimensionalArrayEquivalencyStep.cs.meta new file mode 100644 index 0000000..eb591d5 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/MultiDimensionalArrayEquivalencyStep.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1750cac135e34bc4194263851aa0fbb1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/ObjectReference.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/ObjectReference.cs new file mode 100644 index 0000000..ff998ac --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/ObjectReference.cs @@ -0,0 +1,65 @@ +using System; +using System.Linq; +using FluentAssertions.Common; + +namespace FluentAssertions.Equivalency +{ + /// + /// Represents an object tracked by the including it's location within an object graph. + /// + internal class ObjectReference + { + private readonly object @object; + private readonly string[] path; + + public ObjectReference(object @object, string path) + { + this.@object = @object; + this.path = path.ToLower().Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries); + } + + /// + /// Determines whether the specified is equal to the current . + /// + /// + /// true if the specified is equal to the current ; otherwise, false. + /// + /// The to compare with the current . 2 + public override bool Equals(object obj) + { + var other = (ObjectReference) obj; + + return ReferenceEquals(@object, other.@object) && IsParentOf(other); + } + + private bool IsParentOf(ObjectReference other) + { + return (other.path.Length > path.Length) && other.path.Take(path.Length).SequenceEqual(path); + } + + /// + /// Serves as a hash function for a particular type. + /// + /// + /// A hash code for the current . + /// + /// 2 + public override int GetHashCode() + { + unchecked + { + return (@object.GetHashCode()*397) ^ path.GetHashCode(); + } + } + + public override string ToString() + { + return string.Format("{{\"{0}\", {1}}}", path, @object); + } + + public bool IsComplexType + { + get { return !ReferenceEquals(@object, null) && @object.GetType().IsComplexType(); } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/ObjectReference.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/ObjectReference.cs.meta new file mode 100644 index 0000000..38dcfed --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/ObjectReference.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b15e1a66168ae5240b9d9f07a4163efb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/ObjectTracker.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/ObjectTracker.cs new file mode 100644 index 0000000..7cfb136 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/ObjectTracker.cs @@ -0,0 +1,72 @@ +using System.Collections.Generic; + +using FluentAssertions.Execution; + +namespace FluentAssertions.Equivalency +{ + /// + /// Keeps track of objects and their location within an object graph so that cyclic references can be detected + /// and handled upon. + /// + internal class ObjectTracker : ICloneable2 + { + #region Private Definitions + + private readonly CyclicReferenceHandling handling; + private List orderedReferences = new List(); + + #endregion + + public ObjectTracker(CyclicReferenceHandling handling) + { + this.handling = handling; + } + + /// + /// Determines whether the specified object reference is a cyclic reference to the same object earlier in the + /// equivalency validation. + /// + /// + /// The behavior of a cyclic reference is determined by the constructor + /// parameter. + /// + public bool IsCyclicReference(ObjectReference reference) + { + bool isCyclic = false; + + if (reference.IsComplexType) + { + if (orderedReferences.Contains(reference)) + { + isCyclic = true; + if (handling == CyclicReferenceHandling.ThrowException) + { + AssertionScope.Current.FailWith( + "Expected {context:subject} to be {expectation}{reason}, but it contains a cyclic reference."); + } + } + else + { + orderedReferences.Add(reference); + } + } + + return isCyclic; + } + + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// + /// A new object that is a copy of this instance. + /// + public object Clone() + { + return new ObjectTracker(handling) + { + orderedReferences = new List(orderedReferences) + }; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/ObjectTracker.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/ObjectTracker.cs.meta new file mode 100644 index 0000000..4926a1f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/ObjectTracker.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0f9aba612a7fe0540ab3a91338e27a9e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/OrderStrictness.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/OrderStrictness.cs new file mode 100644 index 0000000..6828781 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/OrderStrictness.cs @@ -0,0 +1,9 @@ +namespace FluentAssertions.Equivalency +{ + public enum OrderStrictness + { + Strict, + NotStrict, + Irrelevant + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/OrderStrictness.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/OrderStrictness.cs.meta new file mode 100644 index 0000000..1236d50 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/OrderStrictness.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 04edf443e46439c4b9bcb92f0798de4b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering.meta new file mode 100644 index 0000000..5f22247 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: eda10ef651baab64e97b9542619ee90b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/ByteArrayOrderingRule.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/ByteArrayOrderingRule.cs new file mode 100644 index 0000000..1d14fca --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/ByteArrayOrderingRule.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using FluentAssertions.Common; + +namespace FluentAssertions.Equivalency.Ordering +{ + /// + /// Ordering rule that ensures that byte arrays are always compared in strict ordering since it would cause a + /// severe performance impact otherwise. + /// + internal class ByteArrayOrderingRule : IOrderingRule + { + public OrderStrictness Evaluate(ISubjectInfo subjectInfo) + { + return subjectInfo.CompileTimeType.Implements>() ? OrderStrictness.Strict : OrderStrictness.Irrelevant; + } + + public override string ToString() + { + return "Be strict about the order of items in byte arrays"; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/ByteArrayOrderingRule.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/ByteArrayOrderingRule.cs.meta new file mode 100644 index 0000000..4416986 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/ByteArrayOrderingRule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1990cbd8ff68a9147ab959227b9154ef +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/CollectionMemberOrderingRuleDecorator.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/CollectionMemberOrderingRuleDecorator.cs new file mode 100644 index 0000000..7bd4ec2 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/CollectionMemberOrderingRuleDecorator.cs @@ -0,0 +1,22 @@ +namespace FluentAssertions.Equivalency.Ordering +{ + internal class CollectionMemberOrderingRuleDecorator : IOrderingRule + { + private readonly IOrderingRule orderingRule; + + public CollectionMemberOrderingRuleDecorator(IOrderingRule orderingRule) + { + this.orderingRule = orderingRule; + } + + public OrderStrictness Evaluate(ISubjectInfo subjectInfo) + { + return orderingRule.Evaluate(new CollectionMemberSubjectInfo(subjectInfo)); + } + + public override string ToString() + { + return orderingRule.ToString(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/CollectionMemberOrderingRuleDecorator.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/CollectionMemberOrderingRuleDecorator.cs.meta new file mode 100644 index 0000000..436940d --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/CollectionMemberOrderingRuleDecorator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f8f28fed4bef69846925e10a526f26c4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/MatchAllOrderingRule.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/MatchAllOrderingRule.cs new file mode 100644 index 0000000..d8fa19a --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/MatchAllOrderingRule.cs @@ -0,0 +1,21 @@ +namespace FluentAssertions.Equivalency.Ordering +{ + /// + /// An ordering rule that basically states that the order of items in all collections is important. + /// + internal class MatchAllOrderingRule : IOrderingRule + { + /// + /// Determines if ordering of the member referred to by the current is relevant. + /// + public OrderStrictness Evaluate(ISubjectInfo subjectInfo) + { + return OrderStrictness.Strict; + } + + public override string ToString() + { + return "Always be strict about the collection order"; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/MatchAllOrderingRule.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/MatchAllOrderingRule.cs.meta new file mode 100644 index 0000000..22bd875 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/MatchAllOrderingRule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6b4b2ad8626b4c0498447306a13815f9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/PathBasedOrderingRule.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/PathBasedOrderingRule.cs new file mode 100644 index 0000000..e49f690 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/PathBasedOrderingRule.cs @@ -0,0 +1,66 @@ +using System; +using System.Text.RegularExpressions; + +namespace FluentAssertions.Equivalency.Ordering +{ + /// + /// Represents a rule for determining whether or not a certain collection within the object graph should be compared using + /// strict ordering. + /// + internal class PathBasedOrderingRule : IOrderingRule + { + private readonly string path; + + public PathBasedOrderingRule(string path) + { + this.path = path; + } + + /// + /// Determines if ordering of the member referred to by the current is relevant. + /// + public OrderStrictness Evaluate(ISubjectInfo subjectInfo) + { + string currentPropertyPath = subjectInfo.SelectedMemberPath; + if (!ContainsIndexingQualifiers(path)) + { + currentPropertyPath = RemoveInitialIndexQualifier(currentPropertyPath); + } + + if (currentPropertyPath.Equals(path, StringComparison.CurrentCultureIgnoreCase)) + { + return OrderStrictness.Strict; + } + else + { + return OrderStrictness.Irrelevant; + } + } + + private static bool ContainsIndexingQualifiers(string path) + { + return path.Contains("[") && path.Contains("]"); + } + + private string RemoveInitialIndexQualifier(string sourcePath) + { + var indexQualifierRegex = new Regex(@"^\[\d+]\."); + + if (!indexQualifierRegex.IsMatch(path)) + { + var match = indexQualifierRegex.Match(sourcePath); + if (match.Success) + { + sourcePath = sourcePath.Substring(match.Length); + } + } + + return sourcePath; + } + + public override string ToString() + { + return "Be strict about the order of collection items when path is " + path; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/PathBasedOrderingRule.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/PathBasedOrderingRule.cs.meta new file mode 100644 index 0000000..d01ecda --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/PathBasedOrderingRule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ae95e37d569e9144aa190410330c626f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/PredicateBasedOrderingRule.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/PredicateBasedOrderingRule.cs new file mode 100644 index 0000000..64b90fe --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/PredicateBasedOrderingRule.cs @@ -0,0 +1,39 @@ +using System; +using System.Linq.Expressions; + +namespace FluentAssertions.Equivalency.Ordering +{ + internal class PredicateBasedOrderingRule : IOrderingRule + { + private readonly Func predicate; + private readonly string description; + + public PredicateBasedOrderingRule(Expression> predicate) + { + description = predicate.Body.ToString(); + this.predicate = predicate.Compile(); + } + + public bool Invert { get; set; } + + /// + /// Determines if ordering of the member referred to by the current is relevant. + /// + public OrderStrictness Evaluate(ISubjectInfo subjectInfo) + { + if (predicate(subjectInfo)) + { + return Invert ? OrderStrictness.NotStrict : OrderStrictness.Strict; + } + else + { + return OrderStrictness.Irrelevant; + } + } + + public override string ToString() + { + return $"Be {(Invert ? "not strict" : "strict")} about the order of collections when {description}"; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/PredicateBasedOrderingRule.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/PredicateBasedOrderingRule.cs.meta new file mode 100644 index 0000000..0448490 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Ordering/PredicateBasedOrderingRule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6f3b6c6c4aba1dd4da34c22954fc40c0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/OrderingRuleCollection.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/OrderingRuleCollection.cs new file mode 100644 index 0000000..a472b9c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/OrderingRuleCollection.cs @@ -0,0 +1,69 @@ +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using FluentAssertions.Equivalency.Ordering; + +namespace FluentAssertions.Equivalency +{ + /// + /// Collection of s. + /// + public class OrderingRuleCollection : IEnumerable + { + private readonly List rules = new List(); + + /// + /// Initializes a new collection of ordering rules. + /// + public OrderingRuleCollection() + { + } + + /// + /// Initializes a new collection of ordering rules based on an existing collection of ordering rules. + /// + public OrderingRuleCollection(IEnumerable orderingRules) + { + rules.AddRange(orderingRules); + } + + /// + /// Returns an enumerator that iterates through the collection. + /// + /// + /// A that can be used to iterate through the collection. + /// + /// 1 + public IEnumerator GetEnumerator() + { + return rules.GetEnumerator(); + } + + /// + /// Returns an enumerator that iterates through a collection. + /// + /// + /// An object that can be used to iterate through the collection. + /// + /// 2 + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void Add(IOrderingRule rule) + { + rules.Add(rule); + } + + /// + /// Determines whether the rules in this collection dictate strict ordering during the equivalency assertion on + /// the collection pointed to by . + /// + public bool IsOrderingStrictFor(ISubjectInfo subjectInfo) + { + List results = rules.Select(r => r.Evaluate(subjectInfo)).ToList(); + return results.Contains(OrderStrictness.Strict) && !results.Contains(OrderStrictness.NotStrict); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/OrderingRuleCollection.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/OrderingRuleCollection.cs.meta new file mode 100644 index 0000000..2e1dfc4 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/OrderingRuleCollection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b96e8d0991a28e1469681883e39414bf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/PropertySelectedMemberInfo.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/PropertySelectedMemberInfo.cs new file mode 100644 index 0000000..8433db4 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/PropertySelectedMemberInfo.cs @@ -0,0 +1,39 @@ +using System; +using System.Reflection; +using FluentAssertions.Common; + +namespace FluentAssertions.Equivalency +{ + /// + /// Provides an ISelectedMemberInfo for PropertyInfo objects + /// + internal class PropertySelectedMemberInfo : MemberInfoSelectedMemberInfo + { + private readonly PropertyInfo propertyInfo; + + public PropertySelectedMemberInfo(PropertyInfo propertyInfo) : base(propertyInfo) + { + this.propertyInfo = propertyInfo; + } + + public override Type MemberType + { + get { return propertyInfo.PropertyType; } + } + + internal override CSharpAccessModifier GetAccessModifier + { + get { return propertyInfo.GetGetMethod(true).GetCSharpAccessModifier(); } + } + + internal override CSharpAccessModifier SetAccessModifier + { + get { return propertyInfo.GetSetMethod(true).GetCSharpAccessModifier(); } + } + + public override object GetValue(object obj, object[] index) + { + return propertyInfo.GetValue(obj, index); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/PropertySelectedMemberInfo.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/PropertySelectedMemberInfo.cs.meta new file mode 100644 index 0000000..fcdbf4d --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/PropertySelectedMemberInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bde1cbaa56a758045b973588e924c6fc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/ReferenceEqualityEquivalencyStep.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/ReferenceEqualityEquivalencyStep.cs new file mode 100644 index 0000000..5aefe63 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/ReferenceEqualityEquivalencyStep.cs @@ -0,0 +1,28 @@ +namespace FluentAssertions.Equivalency +{ + public class ReferenceEqualityEquivalencyStep : IEquivalencyStep + { + /// + /// Gets a value indicating whether this step can handle the current subject and/or expectation. + /// + public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) + { + return true; + } + + /// + /// Applies a step as part of the task to compare two objects for structural equality. + /// + /// + /// Should return true if the subject matches the expectation or if no additional assertions + /// have to be executed. Should return false otherwise. + /// + /// + /// May throw when preconditions are not met or if it detects mismatching data. + /// + public virtual bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator structuralEqualityValidator, IEquivalencyAssertionOptions config) + { + return ReferenceEquals(context.Subject, context.Expectation); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/ReferenceEqualityEquivalencyStep.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/ReferenceEqualityEquivalencyStep.cs.meta new file mode 100644 index 0000000..d8588a7 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/ReferenceEqualityEquivalencyStep.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 403790f39d183f346aa952b3e0e21486 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/RunAllUserStepsEquivalencyStep.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/RunAllUserStepsEquivalencyStep.cs new file mode 100644 index 0000000..f26bc95 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/RunAllUserStepsEquivalencyStep.cs @@ -0,0 +1,24 @@ +using System.Linq; + +namespace FluentAssertions.Equivalency +{ + /// + /// Represents a composite equivalency step that passes the execution to all user-supplied steps that can handle the + /// current context. + /// + public class RunAllUserStepsEquivalencyStep : IEquivalencyStep + { + public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) + { + return config.UserEquivalencySteps.Any(s => s.CanHandle(context, config)); + } + + public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, + IEquivalencyAssertionOptions config) + { + return config.UserEquivalencySteps + .Where(s => s.CanHandle(context, config)) + .Any(step => step.Handle(context, parent, config)); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/RunAllUserStepsEquivalencyStep.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/RunAllUserStepsEquivalencyStep.cs.meta new file mode 100644 index 0000000..9b9662c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/RunAllUserStepsEquivalencyStep.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7062ae9e4e6c5264b97d3ba2b19a9715 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/SelectedMemberInfo.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/SelectedMemberInfo.cs new file mode 100644 index 0000000..3ecccde --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/SelectedMemberInfo.cs @@ -0,0 +1,62 @@ +using System; +using System.Reflection; +using FluentAssertions.Common; + +namespace FluentAssertions.Equivalency +{ + /// + /// Exposes information about an object's member + /// + public abstract class SelectedMemberInfo + { + public static SelectedMemberInfo Create(PropertyInfo propertyInfo) + { + if (propertyInfo == null || propertyInfo.IsIndexer()) + { + return null; + } + + return new PropertySelectedMemberInfo(propertyInfo); + } + + public static SelectedMemberInfo Create(FieldInfo fieldInfo) + { + if (fieldInfo == null) + { + return null; + } + + return new FieldSelectedMemberInfo(fieldInfo); + } + + /// + /// Gets the name of the current member. + /// + public abstract string Name { get; } + + /// + /// Gets the type of this member. + /// + public abstract Type MemberType { get; } + + /// + /// Gets the class that declares this member. + /// + public abstract Type DeclaringType { get; } + + /// + /// Gets the access modifier for the getter of this member. + /// + internal abstract CSharpAccessModifier GetAccessModifier { get; } + + /// + /// Gets the access modifier for the setter of this member. + /// + internal abstract CSharpAccessModifier SetAccessModifier { get; } + + /// + /// Returns the member value of a specified object with optional index values for indexed properties or methods. + /// + public abstract object GetValue(object obj, object[] index); + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/SelectedMemberInfo.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/SelectedMemberInfo.cs.meta new file mode 100644 index 0000000..13e0269 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/SelectedMemberInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 59fda8894da834d4697884edc23cf196 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection.meta new file mode 100644 index 0000000..0e924aa --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 57eb5ed3a7832d942b1bd6013ab90896 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/AllPublicFieldsSelectionRule.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/AllPublicFieldsSelectionRule.cs new file mode 100644 index 0000000..f5234fb --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/AllPublicFieldsSelectionRule.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.Linq; +using FluentAssertions.Common; + +namespace FluentAssertions.Equivalency.Selection +{ + /// + /// Selection rule that adds all public fields of the subject. + /// + internal class AllPublicFieldsSelectionRule : IMemberSelectionRule + { + public bool IncludesMembers + { + get { return false; } + } + + public IEnumerable SelectMembers(IEnumerable selectedMembers, ISubjectInfo context, IEquivalencyAssertionOptions config) + { + return + selectedMembers.Union( + config.GetSubjectType(context).GetNonPrivateFields().Select(SelectedMemberInfo.Create)); + } + + /// + /// Returns a string that represents the current object. + /// + /// + /// A string that represents the current object. + /// + /// 2 + public override string ToString() + { + return "Include all non-private fields"; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/AllPublicFieldsSelectionRule.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/AllPublicFieldsSelectionRule.cs.meta new file mode 100644 index 0000000..7c5ac34 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/AllPublicFieldsSelectionRule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 951d5982433f4da409f79bef1f3c0f00 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/AllPublicPropertiesSelectionRule.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/AllPublicPropertiesSelectionRule.cs new file mode 100644 index 0000000..cc9e3f9 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/AllPublicPropertiesSelectionRule.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.Linq; +using FluentAssertions.Common; + +namespace FluentAssertions.Equivalency.Selection +{ + /// + /// Selection rule that adds all public properties of the subject. + /// + internal class AllPublicPropertiesSelectionRule : IMemberSelectionRule + { + public bool IncludesMembers + { + get { return false; } + } + + public IEnumerable SelectMembers(IEnumerable selectedMembers, ISubjectInfo context, IEquivalencyAssertionOptions config) + { + return + selectedMembers.Union( + config.GetSubjectType(context).GetNonPrivateProperties().Select(SelectedMemberInfo.Create)); + } + + /// + /// Returns a string that represents the current object. + /// + /// + /// A string that represents the current object. + /// + /// 2 + public override string ToString() + { + return "Include all non-private properties"; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/AllPublicPropertiesSelectionRule.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/AllPublicPropertiesSelectionRule.cs.meta new file mode 100644 index 0000000..c8bbf0c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/AllPublicPropertiesSelectionRule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f1777c25a1df07041840ec3c31880fb3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/CollectionMemberSelectionRuleDecorator.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/CollectionMemberSelectionRuleDecorator.cs new file mode 100644 index 0000000..8fe395d --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/CollectionMemberSelectionRuleDecorator.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; + +namespace FluentAssertions.Equivalency.Selection +{ + internal class CollectionMemberSelectionRuleDecorator : IMemberSelectionRule + { + private readonly IMemberSelectionRule selectionRule; + + public CollectionMemberSelectionRuleDecorator(IMemberSelectionRule selectionRule) + { + this.selectionRule = selectionRule; + } + + public bool IncludesMembers + { + get { return selectionRule.IncludesMembers; } + } + + public IEnumerable SelectMembers(IEnumerable selectedMembers, + ISubjectInfo context, IEquivalencyAssertionOptions config) + { + return selectionRule.SelectMembers(selectedMembers, new CollectionMemberSubjectInfo(context), config); + } + + public override string ToString() + { + return selectionRule.ToString(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/CollectionMemberSelectionRuleDecorator.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/CollectionMemberSelectionRuleDecorator.cs.meta new file mode 100644 index 0000000..68ad779 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/CollectionMemberSelectionRuleDecorator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3b13a7a339c3aea44b42c22d73bd547e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/ExcludeMemberByPathSelectionRule.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/ExcludeMemberByPathSelectionRule.cs new file mode 100644 index 0000000..875a68c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/ExcludeMemberByPathSelectionRule.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using System.Linq; +using FluentAssertions.Common; + +namespace FluentAssertions.Equivalency.Selection +{ + /// + /// Selection rule that removes a particular property from the structural comparison. + /// + internal class ExcludeMemberByPathSelectionRule : SelectMemberByPathSelectionRule + { + private readonly string pathToExclude; + + public ExcludeMemberByPathSelectionRule(string pathToExclude) : base(pathToExclude) + { + this.pathToExclude = pathToExclude; + } + + protected override IEnumerable OnSelectMembers(IEnumerable selectedMembers, + string currentPath, ISubjectInfo context) + { + return selectedMembers.Where(memberInfo => currentPath.Combine(memberInfo.Name) != pathToExclude).ToArray(); + } + + public override string ToString() + { + return "Exclude member root." + pathToExclude; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/ExcludeMemberByPathSelectionRule.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/ExcludeMemberByPathSelectionRule.cs.meta new file mode 100644 index 0000000..6540b5a --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/ExcludeMemberByPathSelectionRule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 210414b088c59c642b4360b17d88411b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/ExcludeMemberByPredicateSelectionRule.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/ExcludeMemberByPredicateSelectionRule.cs new file mode 100644 index 0000000..301f99f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/ExcludeMemberByPredicateSelectionRule.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; + +namespace FluentAssertions.Equivalency.Selection +{ + /// + /// Selection rule that removes a particular member from the structural comparison based on a predicate. + /// + internal class ExcludeMemberByPredicateSelectionRule : IMemberSelectionRule + { + private readonly Func predicate; + private readonly string description; + + public ExcludeMemberByPredicateSelectionRule(Expression> predicate) + { + description = predicate.Body.ToString(); + this.predicate = predicate.Compile(); + } + + public bool IncludesMembers + { + get { return false; } + } + + public IEnumerable SelectMembers(IEnumerable selectedMembers, ISubjectInfo context, IEquivalencyAssertionOptions config) + { + return selectedMembers.Where(p => !predicate(new NestedSelectionContext(context, p))).ToArray(); + } + + /// 2 + public override string ToString() + { + return "Exclude member when " + description; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/ExcludeMemberByPredicateSelectionRule.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/ExcludeMemberByPredicateSelectionRule.cs.meta new file mode 100644 index 0000000..8948049 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/ExcludeMemberByPredicateSelectionRule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a1af29bd59dc0e947a94c24c1b338511 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/IncludeMemberByPathSelectionRule.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/IncludeMemberByPathSelectionRule.cs new file mode 100644 index 0000000..694a64f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/IncludeMemberByPathSelectionRule.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; +using System.Linq; +using FluentAssertions.Common; + +namespace FluentAssertions.Equivalency.Selection +{ + /// + /// Selection rule that includes a particular property in the structural comparison. + /// + internal class IncludeMemberByPathSelectionRule : SelectMemberByPathSelectionRule + { + private readonly MemberPath pathToInclude; + + public IncludeMemberByPathSelectionRule(string pathToInclude) : base(pathToInclude) + { + this.pathToInclude = new MemberPath(pathToInclude); + } + + public override bool IncludesMembers => true; + + protected override IEnumerable OnSelectMembers(IEnumerable selectedMembers, + string currentPath, ISubjectInfo context) + { + var matchingMembers = + from member in context.RuntimeType.GetNonPrivateMembers() + where pathToInclude.IsParentOrChildOf(currentPath.Combine(member.Name)) + select member; + + return selectedMembers.Concat(matchingMembers).ToArray(); + } + + public override string ToString() + { + return "Include member root." + pathToInclude; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/IncludeMemberByPathSelectionRule.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/IncludeMemberByPathSelectionRule.cs.meta new file mode 100644 index 0000000..9862fbf --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/IncludeMemberByPathSelectionRule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 42bceb32fb8a0f84dbc698f8b30756cb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/IncludeMemberByPredicateSelectionRule.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/IncludeMemberByPredicateSelectionRule.cs new file mode 100644 index 0000000..41786a3 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/IncludeMemberByPredicateSelectionRule.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using FluentAssertions.Common; + +namespace FluentAssertions.Equivalency.Selection +{ + /// + /// Selection rule that includes a particular member in the structural comparison. + /// + internal class IncludeMemberByPredicateSelectionRule : IMemberSelectionRule + { + private readonly Func predicate; + private readonly string description; + + public IncludeMemberByPredicateSelectionRule(Expression> predicate) + { + description = predicate.Body.ToString(); + this.predicate = predicate.Compile(); + } + + public bool IncludesMembers + { + get { return true; } + } + + public IEnumerable SelectMembers(IEnumerable selectedMembers, ISubjectInfo context, IEquivalencyAssertionOptions config) + { + var members = new List(selectedMembers); + + foreach (SelectedMemberInfo selectedMemberInfo in context.RuntimeType.GetNonPrivateMembers()) + { + if (predicate(new NestedSelectionContext(context, selectedMemberInfo))) + { + if (!members.Any(p => p.IsEquivalentTo(selectedMemberInfo))) + { + members.Add(selectedMemberInfo); + } + } + } + + return members; + } + + /// 2 + public override string ToString() + { + return "Include member when " + description; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/IncludeMemberByPredicateSelectionRule.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/IncludeMemberByPredicateSelectionRule.cs.meta new file mode 100644 index 0000000..63a6701 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/IncludeMemberByPredicateSelectionRule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1076e6ef2672c5c41815b54cf094e35e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/MemberPath.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/MemberPath.cs new file mode 100644 index 0000000..39116ce --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/MemberPath.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace FluentAssertions.Equivalency.Selection +{ + /// + /// Encapsulates a dotted candidate to a (nested) member of a type. + /// + internal class MemberPath + { + private readonly List segments = new List(); + + public MemberPath(string dottedPath) + { + segments.AddRange(Segmentize(dottedPath)); + } + + public bool IsParentOrChildOf(string candidate) + { + return IsParent(candidate) || IsChild(candidate); + } + + private bool IsChild(string candidate) + { + return Segmentize(candidate).Take(segments.Count).SequenceEqual(segments); + } + + private bool IsParent(string candidate) + { + string[] candidateSegments = Segmentize(candidate); + + return candidateSegments.SequenceEqual(segments.Take(candidateSegments.Length)); + } + + private static string[] Segmentize(string dottedPath) + { + return dottedPath.Split(new[] { '.', '[', ']' }, StringSplitOptions.RemoveEmptyEntries); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/MemberPath.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/MemberPath.cs.meta new file mode 100644 index 0000000..92d7878 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/MemberPath.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f4f2b8ab1c17de847ac49b2583b9fe6b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/NestedSelectionContext.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/NestedSelectionContext.cs new file mode 100644 index 0000000..a2d084a --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/NestedSelectionContext.cs @@ -0,0 +1,38 @@ +using System; +using System.Reflection; +using FluentAssertions.Common; + +namespace FluentAssertions.Equivalency.Selection +{ + /// + /// Represents a selection context of a nested property + /// + internal class NestedSelectionContext : ISubjectInfo + { + public NestedSelectionContext(ISubjectInfo context, SelectedMemberInfo selectedMemberInfo) + { + SelectedMemberPath = context.SelectedMemberPath.Combine(selectedMemberInfo.Name); + SelectedMemberDescription = context.SelectedMemberDescription.Combine(selectedMemberInfo.Name); + CompileTimeType = selectedMemberInfo.MemberType; + RuntimeType = selectedMemberInfo.MemberType; + SelectedMemberInfo = selectedMemberInfo; + } + + public SelectedMemberInfo SelectedMemberInfo { get; private set; } + + public string SelectedMemberPath { get; private set; } + + public string SelectedMemberDescription { get; private set; } + + /// + /// Gets the compile-time type of the current object. If the current object is not the root object, then it returns the + /// same as the property does. + /// + public Type CompileTimeType { get; private set; } + + /// + /// Gets the run-time type of the current object. + /// + public Type RuntimeType { get; private set; } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/NestedSelectionContext.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/NestedSelectionContext.cs.meta new file mode 100644 index 0000000..e8e91da --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/NestedSelectionContext.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: da3cfcb3d5733c84ebf4e95b7db99dc9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/SelectMemberByPathSelectionRule.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/SelectMemberByPathSelectionRule.cs new file mode 100644 index 0000000..068ff33 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/SelectMemberByPathSelectionRule.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace FluentAssertions.Equivalency.Selection +{ + internal abstract class SelectMemberByPathSelectionRule : IMemberSelectionRule + { + private readonly string selectedPath; + + protected SelectMemberByPathSelectionRule(string selectedPath) + { + this.selectedPath = selectedPath; + } + + public virtual bool IncludesMembers + { + get { return false; } + } + + public IEnumerable SelectMembers(IEnumerable selectedMembers, ISubjectInfo context, + IEquivalencyAssertionOptions config) + { + string path = context.SelectedMemberPath; + if (!ContainsIndexingQualifiers(selectedPath)) + { + path = RemoveInitialIndexQualifier(path); + } + + return OnSelectMembers(selectedMembers, path, context); + } + + protected abstract IEnumerable OnSelectMembers(IEnumerable selectedMembers, string currentPath, ISubjectInfo context); + + private static bool ContainsIndexingQualifiers(string path) + { + return path.Contains("[") && path.Contains("]"); + } + + private string RemoveInitialIndexQualifier(string propertyPath) + { + var indexQualifierRegex = new Regex(@"^\[\d+]"); + + if (!indexQualifierRegex.IsMatch(selectedPath)) + { + var match = indexQualifierRegex.Match(propertyPath); + if (match.Success) + { + propertyPath = propertyPath.Substring(match.Length); + } + } + + return propertyPath; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/SelectMemberByPathSelectionRule.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/SelectMemberByPathSelectionRule.cs.meta new file mode 100644 index 0000000..a6b9220 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/Selection/SelectMemberByPathSelectionRule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 295f9e786d15e374b8972d99fe3e7d3d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/SelfReferenceEquivalencyAssertionOptions.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/SelfReferenceEquivalencyAssertionOptions.cs new file mode 100644 index 0000000..5a3e64e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/SelfReferenceEquivalencyAssertionOptions.cs @@ -0,0 +1,628 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using FluentAssertions.Common; +using FluentAssertions.Equivalency.Matching; +using FluentAssertions.Equivalency.Ordering; +using FluentAssertions.Equivalency.Selection; + +namespace FluentAssertions.Equivalency +{ + /// + /// Represents the run-time behavior of a structural equivalency assertion. + /// + public abstract class SelfReferenceEquivalencyAssertionOptions : IEquivalencyAssertionOptions + where TSelf : SelfReferenceEquivalencyAssertionOptions + { + #region Private Definitions + + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private readonly List selectionRules = new List(); + + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private readonly List matchingRules = new List(); + + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private readonly List userEquivalencySteps = new List(); + + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private CyclicReferenceHandling cyclicReferenceHandling = CyclicReferenceHandling.ThrowException; + + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + protected readonly OrderingRuleCollection orderingRules = new OrderingRuleCollection(); + + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private bool isRecursive; + + private bool allowInfiniteRecursion; + + private EnumEquivalencyHandling enumEquivalencyHandling; + + private bool useRuntimeTyping; + + private bool includeProperties; + + private bool includeFields; + + private readonly List valueTypes = new List(); + + private readonly Func isValueType = _ => false; + private ITraceWriter traceWriter; + + #endregion + + internal SelfReferenceEquivalencyAssertionOptions() + { + AddMatchingRule(new MustMatchByNameRule()); + + orderingRules.Add(new ByteArrayOrderingRule()); + } + + /// + /// Creates an instance of the equivalency assertions options based on defaults previously configured by the caller. + /// + protected SelfReferenceEquivalencyAssertionOptions(IEquivalencyAssertionOptions defaults) + { + allowInfiniteRecursion = defaults.AllowInfiniteRecursion; + isRecursive = defaults.IsRecursive; + cyclicReferenceHandling = defaults.CyclicReferenceHandling; + allowInfiniteRecursion = defaults.AllowInfiniteRecursion; + enumEquivalencyHandling = defaults.EnumEquivalencyHandling; + useRuntimeTyping = defaults.UseRuntimeTyping; + includeProperties = defaults.IncludeProperties; + includeFields = defaults.IncludeFields; + + selectionRules.AddRange(defaults.SelectionRules); + userEquivalencySteps.AddRange(defaults.UserEquivalencySteps); + matchingRules.AddRange(defaults.MatchingRules); + orderingRules = new OrderingRuleCollection(defaults.OrderingRules); + + isValueType = defaults.IsValueType; + traceWriter = defaults.TraceWriter; + + RemoveSelectionRule(); + RemoveSelectionRule(); + } + + /// + /// Gets an ordered collection of selection rules that define what members are included. + /// + IEnumerable IEquivalencyAssertionOptions.SelectionRules + { + get + { + bool hasConflictingRules = selectionRules.Any(rule => rule.IncludesMembers); + + if (includeProperties && !hasConflictingRules) + { + yield return new AllPublicPropertiesSelectionRule(); + } + + if (includeFields && !hasConflictingRules) + { + yield return new AllPublicFieldsSelectionRule(); + } + + foreach (IMemberSelectionRule rule in selectionRules) + { + yield return rule; + } + } + } + + /// + /// Gets an ordered collection of matching rules that determine which subject members are matched with which + /// expectation members. + /// + IEnumerable IEquivalencyAssertionOptions.MatchingRules + { + get { return matchingRules; } + } + + /// + /// Gets an ordered collection of Equivalency steps how a subject is compared with the expectation. + /// + IEnumerable IEquivalencyAssertionOptions.UserEquivalencySteps + { + get { return userEquivalencySteps; } + } + + /// + /// Gets an ordered collection of rules that determine whether or not the order of collections is important. By default, + /// ordering is irrelevant. + /// + OrderingRuleCollection IEquivalencyAssertionOptions.OrderingRules + { + get { return orderingRules; } + } + + /// + /// Gets value indicating whether the equality check will include nested collections and complex types. + /// + bool IEquivalencyAssertionOptions.IsRecursive + { + get { return isRecursive; } + } + + bool IEquivalencyAssertionOptions.AllowInfiniteRecursion + { + get { return allowInfiniteRecursion; } + } + + /// + /// Gets value indicating how cyclic references should be handled. By default, it will throw an exception. + /// + CyclicReferenceHandling IEquivalencyAssertionOptions.CyclicReferenceHandling + { + get { return cyclicReferenceHandling; } + } + + EnumEquivalencyHandling IEquivalencyAssertionOptions.EnumEquivalencyHandling + { + get { return enumEquivalencyHandling; } + } + + bool IEquivalencyAssertionOptions.UseRuntimeTyping + { + get { return useRuntimeTyping; } + } + + bool IEquivalencyAssertionOptions.IncludeProperties + { + get { return includeProperties; } + } + + bool IEquivalencyAssertionOptions.IncludeFields + { + get { return includeFields; } + } + + /// + /// Gets a value indicating whether the should be treated as having value semantics. + /// + bool IEquivalencyAssertionOptions.IsValueType(Type type) + { + return valueTypes.Contains(type) || isValueType(type) || AssertionOptions.IsValueType(type); + } + + /// + /// Causes inclusion of only public properties of the subject as far as they are defined on the declared type. + /// + /// + /// This clears all previously registered selection rules. + /// + public TSelf IncludingAllDeclaredProperties() + { + RespectingDeclaredTypes(); + + ExcludingFields(); + IncludingProperties(); + + WithoutSelectionRules(); + + return (TSelf)this; + } + + /// + /// Causes inclusion of only public properties of the subject based on its run-time type rather than its declared type. + /// + /// + /// This clears all previously registered selection rules. + /// + public TSelf IncludingAllRuntimeProperties() + { + RespectingRuntimeTypes(); + + ExcludingFields(); + IncludingProperties(); + + WithoutSelectionRules(); + + return (TSelf)this; + } + + /// + /// Instructs the comparison to include fields. + /// + /// + /// This is part of the default behavior. + /// + public TSelf IncludingFields() + { + includeFields = true; + return (TSelf)this; + } + + /// + /// Instructs the comparison to exclude fields. + /// + /// + /// This does not preclude use of `Including`. + /// + public TSelf ExcludingFields() + { + includeFields = false; + return (TSelf)this; + } + + /// + /// Instructs the comparison to include properties. + /// + /// + /// This is part of the default behavior. + /// + public TSelf IncludingProperties() + { + includeProperties = true; + return (TSelf)this; + } + + /// + /// Instructs the comparison to exclude properties. + /// + /// + /// This does not preclude use of `Including`. + /// + public TSelf ExcludingProperties() + { + includeProperties = false; + return (TSelf)this; + } + + /// + /// Instructs the comparison to respect the subject's runtime type. + /// + public TSelf RespectingRuntimeTypes() + { + useRuntimeTyping = true; + return (TSelf)this; + } + + /// + /// Instructs the comparison to respect the subject's declared type. + /// + public TSelf RespectingDeclaredTypes() + { + useRuntimeTyping = false; + return (TSelf)this; + } + + /// + /// Excludes a (nested) property based on a predicate from the structural equality check. + /// + public TSelf Excluding(Expression> predicate) + { + AddSelectionRule(new ExcludeMemberByPredicateSelectionRule(predicate)); + return (TSelf)this; + } + + /// + /// Tries to match the members of the subject with equally named members on the expectation. Ignores those + /// members that don't exist on the expectation and previously registered matching rules. + /// + public TSelf ExcludingMissingMembers() + { + ClearMatchingRules(); + matchingRules.Add(new TryMatchByNameRule()); + return (TSelf)this; + } + + /// + /// Requires the expectation to have members which are equally named to members on the subject. + /// + /// + public TSelf ThrowingOnMissingMembers() + { + ClearMatchingRules(); + matchingRules.Add(new MustMatchByNameRule()); + return (TSelf)this; + } + + /// + /// The assertion to execute when the predicate is met. + /// + public Restriction Using(Action> action) + { + return new Restriction((TSelf)this, action); + } + + /// + /// Causes the structural equality check to include nested collections and complex types. + /// + public TSelf IncludingNestedObjects() + { + isRecursive = true; + return (TSelf)this; + } + + /// + /// Causes the structural equality check to exclude nested collections and complex types. + /// + /// + /// Behaves similarly to the old property assertions API. + /// + public TSelf ExcludingNestedObjects() + { + isRecursive = false; + return (TSelf)this; + } + + /// + /// Causes the structural equality check to ignore any cyclic references. + /// + /// + /// By default, cyclic references within the object graph will cause an exception to be thrown. + /// + public TSelf IgnoringCyclicReferences() + { + cyclicReferenceHandling = CyclicReferenceHandling.Ignore; + return (TSelf)this; + } + + + /// + /// Disables limitations on recursion depth when the structural equality check is configured to include nested objects + /// + public TSelf AllowingInfiniteRecursion() + { + allowInfiniteRecursion = true; + return (TSelf)this; + } + + /// + /// Clears all selection rules, including those that were added by default. + /// + public void WithoutSelectionRules() + { + selectionRules.Clear(); + } + + /// + /// Clears all matching rules, including those that were added by default. + /// + public void WithoutMatchingRules() + { + ClearMatchingRules(); + } + + /// + /// Adds a selection rule to the ones already added by default, and which is evaluated after all existing rules. + /// + public TSelf Using(IMemberSelectionRule selectionRule) + { + return AddSelectionRule(selectionRule); + } + + /// + /// Adds a matching rule to the ones already added by default, and which is evaluated before all existing rules. + /// + public TSelf Using(IMemberMatchingRule matchingRule) + { + return AddMatchingRule(matchingRule); + } + + /// + /// Adds an assertion rule to the ones already added by default, and which is evaluated before all existing rules. + /// NOTE: These assertion rules do not apply to the root object. + /// + public TSelf Using(IAssertionRule assertionRule) + { + userEquivalencySteps.Insert(0, new AssertionRuleEquivalencyStepAdapter(assertionRule)); + return (TSelf) this; + } + + /// + /// Adds an equivalency step rule to the ones already added by default, and which is evaluated before previous user-registered steps + /// + public TSelf Using(IEquivalencyStep equivalencyStep) + { + return AddEquivalencyStep(equivalencyStep); + } + + /// + /// Causes all collections to be compared in the order in which the items appear in the expectation. + /// + public TSelf WithStrictOrdering() + { + orderingRules.Add(new MatchAllOrderingRule()); + return (TSelf)this; + } + + /// + /// Causes the collection identified by the provided to be compared in the order + /// in which the items appear in the expectation. + /// + public TSelf WithStrictOrderingFor(Expression> predicate) + { + orderingRules.Add(new PredicateBasedOrderingRule(predicate)); + return (TSelf)this; + } + + /// + /// Causes the collection identified by the provided to be compared ignoring the order + /// in which the items appear in the expectation. + /// + public TSelf WithoutStrictOrderingFor(Expression> predicate) + { + orderingRules.Add(new PredicateBasedOrderingRule(predicate) + { + Invert = true + }); + + return (TSelf)this; + } + + /// + /// Causes to compare Enum properties using the result of their ToString method. + /// + /// + /// By default, enums are compared by value. + /// + public TSelf ComparingEnumsByName() + { + enumEquivalencyHandling = EnumEquivalencyHandling.ByName; + return (TSelf) this; + } + + /// + /// Causes to compare Enum members using their underlying value only. + /// + /// + /// This is the default. + /// + public TSelf ComparingEnumsByValue() + { + enumEquivalencyHandling = EnumEquivalencyHandling.ByValue; + return (TSelf) this; + } + + /// + /// Marks the as a value type which must be compared using its + /// method. + /// + public TSelf ComparingByValue() + { + valueTypes.Add(typeof(T)); + return (TSelf) this; + } + + /// + /// Enables tracing the steps the equivalency validation followed to compare two graphs. + /// + public TSelf WithTracing(ITraceWriter writer = null) + { + traceWriter = writer ?? new StringBuilderTraceWriter(); + return (TSelf)this; + } + + #region Non-fluent API + + protected void RemoveSelectionRule() where T : IMemberSelectionRule + { + foreach (T selectionRule in selectionRules.OfType().ToArray()) + { + selectionRules.Remove(selectionRule); + } + } + + private void ClearMatchingRules() + { + matchingRules.Clear(); + } + + protected TSelf AddSelectionRule(IMemberSelectionRule selectionRule) + { + selectionRules.Add(selectionRule); + return (TSelf) this; + } + + private TSelf AddMatchingRule(IMemberMatchingRule matchingRule) + { + matchingRules.Insert(0, matchingRule); + return (TSelf) this; + } + + private TSelf AddEquivalencyStep(IEquivalencyStep equivalencyStep) + { + userEquivalencySteps.Add(equivalencyStep); + return (TSelf) this; + } + + #endregion + + /// + /// Returns a string that represents the current object. + /// + /// + /// A string that represents the current object. + /// + /// 2 + public override string ToString() + { + var builder = new StringBuilder(); + + builder.AppendLine($"- Use {(useRuntimeTyping ? "runtime" : "declared")} types and members"); + if (isRecursive) + { + if (allowInfiniteRecursion) + { + builder.AppendLine("- Recurse indefinitely"); + } + } + + builder.AppendFormat("- Compare enums by {0}" + Environment.NewLine, + (enumEquivalencyHandling == EnumEquivalencyHandling.ByName) ? "name" : "value"); + + if (cyclicReferenceHandling == CyclicReferenceHandling.Ignore) + { + builder.AppendLine("- Ignoring cyclic references"); + } + + foreach (IMemberSelectionRule rule in selectionRules) + { + builder.AppendLine("- " + rule); + } + + foreach (IMemberMatchingRule rule in matchingRules) + { + builder.AppendLine("- " + rule); + } + + foreach (IEquivalencyStep step in userEquivalencySteps) + { + builder.AppendLine("- " + step); + } + + foreach (IOrderingRule rule in orderingRules) + { + builder.AppendLine("- " + rule); + } + + return builder.ToString(); + } + + public ITraceWriter TraceWriter => traceWriter; + + /// + /// Defines additional overrides when used with + /// + public class Restriction + { + private readonly Action> action; + private readonly TSelf options; + + public Restriction(TSelf options, Action> action) + { + this.options = options; + this.action = action; + } + + /// + /// Allows overriding the way structural equality is applied to (nested) objects of type + /// + public TSelf WhenTypeIs() + { + When(info => info.RuntimeType.IsSameOrInherits(typeof(TMemberType))); + return options; + } + + /// + /// Allows overriding the way structural equality is applied to particular members. + /// + /// + /// A predicate based on the of the subject that is used to identify the property for which the + /// override applies. + /// + public TSelf When(Expression> predicate) + { +#pragma warning disable 618 + options.Using(new AssertionRule(predicate, action)); + return options; +#pragma warning restore 618 + } + } + } +} diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/SelfReferenceEquivalencyAssertionOptions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/SelfReferenceEquivalencyAssertionOptions.cs.meta new file mode 100644 index 0000000..34c591f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/SelfReferenceEquivalencyAssertionOptions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b3b713acbc6ccf74ea46c1953fe4a60f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/SimpleEqualityEquivalencyStep.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/SimpleEqualityEquivalencyStep.cs new file mode 100644 index 0000000..28a704e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/SimpleEqualityEquivalencyStep.cs @@ -0,0 +1,30 @@ +namespace FluentAssertions.Equivalency +{ + public class SimpleEqualityEquivalencyStep : IEquivalencyStep + { + /// + /// Gets a value indicating whether this step can handle the current subject and/or expectation. + /// + public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) + { + return !config.IsRecursive && !context.IsRoot; + } + + /// + /// Applies a step as part of the task to compare two objects for structural equality. + /// + /// + /// Should return true if the subject matches the expectation or if no additional assertions + /// have to be executed. Should return false otherwise. + /// + /// + /// May throw when preconditions are not met or if it detects mismatching data. + /// + public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator structuralEqualityValidator, IEquivalencyAssertionOptions config) + { + context.Subject.Should().Be(context.Expectation, context.Because, context.BecauseArgs); + + return true; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/SimpleEqualityEquivalencyStep.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/SimpleEqualityEquivalencyStep.cs.meta new file mode 100644 index 0000000..ff449ef --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/SimpleEqualityEquivalencyStep.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7765744ef886eec41a29567466b81288 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/StringEqualityEquivalencyStep.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/StringEqualityEquivalencyStep.cs new file mode 100644 index 0000000..ab48d3b --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/StringEqualityEquivalencyStep.cs @@ -0,0 +1,100 @@ +using System; + +using FluentAssertions.Common; +using FluentAssertions.Execution; + +namespace FluentAssertions.Equivalency +{ + public class StringEqualityEquivalencyStep : IEquivalencyStep + { + /// + /// Gets a value indicating whether this step can handle the current subject and/or expectation. + /// + public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) + { + Type subjectType = config.GetSubjectType(context); + + return (subjectType != null) && (subjectType == typeof (string)); + } + + /// + /// Applies a step as part of the task to compare two objects for structural equality. + /// + /// + /// Should return true if the subject matches the expectation or if no additional assertions + /// have to be executed. Should return false otherwise. + /// + /// + /// May throw when preconditions are not met or if it detects mismatching data. + /// + public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config) + { + if (!ValidateAgainstNulls(context)) + { + return true; + } + + bool expectationIsString = ValidateAgainstType(context); + + if (expectationIsString) + { + string subject = (string) context.Subject; + string expectation = (context.Expectation == null) + ? null + : (string) context.Expectation; + + subject.Should() + .Be(expectation, context.Because, context.BecauseArgs); + } + + return true; + } + + private static bool ValidateAgainstNulls(IEquivalencyValidationContext context) + { + object expected = context.Expectation; + object subject = context.Subject; + string subjectDescription = GetSubjectDescription(context); + + bool onlyOneNull = ((expected == null) && (subject != null)) || + ((expected != null) && (subject == null)); + + if (onlyOneNull) + { + AssertionScope.Current.FailWith( + "Expected " + subjectDescription + + " to be {0}{reason}, but found {1}.", expected, subject); + return false; + } + + return true; + } + + private static bool ValidateAgainstType(IEquivalencyValidationContext context) + { + bool expectationisNull = ReferenceEquals(context.Expectation, null); + + if (expectationisNull) + { + // Do not know the declared type of the expectation. + return true; + } + + return + AssertionScope.Current + .ForCondition(context.Expectation.GetType() + .IsSameOrInherits(typeof (T))) + .FailWith( + "Expected " + GetSubjectDescription(context) + + " to be {0}, but found {1}", + context.Expectation.GetType(), + context.RuntimeType); + + } + + private static string GetSubjectDescription(IEquivalencyValidationContext context) + { + return (context.SelectedMemberDescription.Length == 0) ? "subject" : context.SelectedMemberDescription; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/StringEqualityEquivalencyStep.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/StringEqualityEquivalencyStep.cs.meta new file mode 100644 index 0000000..39ac332 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/StringEqualityEquivalencyStep.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8b78ff08c4c1b1e4995770c9ffca9dcc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/StructuralEqualityEquivalencyStep.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/StructuralEqualityEquivalencyStep.cs new file mode 100644 index 0000000..899278f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/StructuralEqualityEquivalencyStep.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using FluentAssertions.Execution; + +namespace FluentAssertions.Equivalency +{ + public class StructuralEqualityEquivalencyStep : IEquivalencyStep + { + /// + /// Gets a value indicating whether this step can handle the current subject and/or expectation. + /// + public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) + { + return (context.IsRoot || config.IsRecursive); + } + + public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config) + { + bool expectationIsNotNull = AssertionScope.Current + .ForCondition(!ReferenceEquals(context.Expectation, null)) + .FailWith( + "Expected {context:subject} to be , but found {0}.", + context.Subject); + + bool subjectIsNotNull = + AssertionScope.Current.ForCondition( + !ReferenceEquals(context.Subject, null)) + .FailWith( + "Expected {context:object} to be {0}{reason}, but found {1}.", + context.Expectation, + context.Subject); + + IEnumerable selectedMembers = GetSelectedMembers(context, config).ToArray(); + if (context.IsRoot && !selectedMembers.Any()) + { + throw new InvalidOperationException( + "No members were found for comparison. " + + "Please specify some members to include in the comparison or choose a more meaningful assertion."); + } + + if (expectationIsNotNull && subjectIsNotNull) + { + foreach (var selectedMemberInfo in selectedMembers) + { + AssertMemberEquality(context, parent, selectedMemberInfo, config); + } + } + return true; + } + + private static void AssertMemberEquality(IEquivalencyValidationContext context, IEquivalencyValidator parent, SelectedMemberInfo selectedMemberInfo, IEquivalencyAssertionOptions config) + { + var matchingMember = FindMatchFor(selectedMemberInfo, context, config); + if (matchingMember != null) + { + var nestedContext = context.CreateForNestedMember(selectedMemberInfo, matchingMember); + if (nestedContext != null) + { + parent.AssertEqualityUsing(nestedContext); + } + } + } + + private static SelectedMemberInfo FindMatchFor(SelectedMemberInfo selectedMemberInfo, IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) + { + var query = + from rule in config.MatchingRules + let match = rule.Match(selectedMemberInfo, context.Expectation, context.SelectedMemberDescription, config) + where match != null + select match; + + return query.FirstOrDefault(); + } + + internal IEnumerable GetSelectedMembers(IEquivalencyValidationContext context, + IEquivalencyAssertionOptions config) + { + IEnumerable members = Enumerable.Empty(); + + foreach (var selectionRule in config.SelectionRules) + { + members = selectionRule.SelectMembers(members, context, config); + } + + return members; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/StructuralEqualityEquivalencyStep.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/StructuralEqualityEquivalencyStep.cs.meta new file mode 100644 index 0000000..4ede9ea --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/StructuralEqualityEquivalencyStep.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 97ed7a9f87af2674b8c87d34ef1360ec +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/SubjectInfoExtensions.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/SubjectInfoExtensions.cs new file mode 100644 index 0000000..df37df3 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/SubjectInfoExtensions.cs @@ -0,0 +1,51 @@ +using FluentAssertions.Common; + +namespace FluentAssertions.Equivalency +{ + public static class SubjectInfoExtensions + { + /// + /// Checks if the subject info setter has the given access modifier. + /// + /// The subject info being checked. + /// The access modifier that the subject info setter should have. + /// True if the subject info setter has the given access modifier, false otherwise. + public static bool WhichSetterHas(this ISubjectInfo subjectInfo, CSharpAccessModifier accessModifier) + { + return subjectInfo.SelectedMemberInfo.SetAccessModifier == accessModifier; + } + + /// + /// Checks if the subject info setter does not have the given access modifier. + /// + /// The subject info being checked. + /// The access modifier that the subject info setter should not have. + /// True if the subject info setter does not have the given access modifier, false otherwise. + public static bool WhichSetterDoesNotHave(this ISubjectInfo subjectInfo, CSharpAccessModifier accessModifier) + { + return subjectInfo.SelectedMemberInfo.SetAccessModifier != accessModifier; + } + + /// + /// Checks if the subject info getter has the given access modifier. + /// + /// The subject info being checked. + /// The access modifier that the subject info getter should have. + /// True if the subject info getter has the given access modifier, false otherwise. + public static bool WhichGetterHas(this ISubjectInfo subjectInfo, CSharpAccessModifier accessModifier) + { + return subjectInfo.SelectedMemberInfo.GetAccessModifier == accessModifier; + } + + /// + /// Checks if the subject info getter does not have the given access modifier. + /// + /// The subject info being checked. + /// The access modifier that the subject info getter should not have. + /// True if the subject info getter does not have the given access modifier, false otherwise. + public static bool WhichGetterDoesNotHave(this ISubjectInfo subjectInfo, CSharpAccessModifier accessModifier) + { + return subjectInfo.SelectedMemberInfo.GetAccessModifier != accessModifier; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/SubjectInfoExtensions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/SubjectInfoExtensions.cs.meta new file mode 100644 index 0000000..62d96fa --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/SubjectInfoExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ec3c43f5c32f9b947abeb090f69b17f3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/TryConversionEquivalencyStep.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/TryConversionEquivalencyStep.cs new file mode 100644 index 0000000..c5127d8 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/TryConversionEquivalencyStep.cs @@ -0,0 +1,70 @@ +using System; +using System.Globalization; + +using FluentAssertions.Common; + +namespace FluentAssertions.Equivalency +{ + public class TryConversionEquivalencyStep : IEquivalencyStep + { + /// + /// Gets a value indicating whether this step can handle the current subject and/or expectation. + /// + public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) + { + return true; + } + + /// + /// Applies a step as part of the task to compare two objects for structural equality. + /// + /// + /// Should return true if the subject matches the expectation or if no additional assertions + /// have to be executed. Should return false otherwise. + /// + /// + /// May throw when preconditions are not met or if it detects mismatching data. + /// + public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator structuralEqualityValidator, IEquivalencyAssertionOptions config) + { + if (!ReferenceEquals(context.Expectation, null) && !ReferenceEquals(context.Subject, null) + && !context.Subject.GetType().IsSameOrInherits(context.Expectation.GetType())) + { + Type expectationType = context.Expectation.GetType(); + + object convertedSubject; + if (TryChangeType(context.Subject, expectationType, out convertedSubject)) + { + context.TraceSingle(path => $"Converted subject {context.Subject} at {path} to {expectationType}"); + + var newContext = context.CreateWithDifferentSubject(convertedSubject, expectationType); + + structuralEqualityValidator.AssertEqualityUsing(newContext); + return true; + } + + context.TraceSingle(path => $"Subject {context.Subject} at {path} could not be converted to {expectationType}"); + } + + return false; + } + + private static bool TryChangeType(object subject, Type expectationType, out object conversionResult) + { + conversionResult = null; + try + { + conversionResult = Convert.ChangeType(subject, expectationType, CultureInfo.CurrentCulture); + return true; + } + catch (FormatException) + { + } + catch (InvalidCastException) + { + } + + return false; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/TryConversionEquivalencyStep.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/TryConversionEquivalencyStep.cs.meta new file mode 100644 index 0000000..745f917 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/TryConversionEquivalencyStep.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 10057de6aa5dbcb4987d81cbdbac0055 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/ValueTypeEquivalencyStep.cs b/Assets/Plugins/FluentAssertions/Core/Equivalency/ValueTypeEquivalencyStep.cs new file mode 100644 index 0000000..acf261a --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/ValueTypeEquivalencyStep.cs @@ -0,0 +1,48 @@ +using System; + +namespace FluentAssertions.Equivalency +{ + /// + /// Ensures that types that are marked as value types are treated as such. + /// + public class ValueTypeEquivalencyStep : IEquivalencyStep + { + /// + /// Gets a value indicating whether this step can handle the current subject and/or expectation. + /// + public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) + { + Type type = config.GetSubjectType(context); + + bool canHandle = + (type != null) && + (type != typeof (object)) && + config.IsValueType(type) && + !type.IsArray; + + if (canHandle) + { + context.TraceSingle(path => $"Treating {path} as a value type"); + } + + return canHandle; + } + + /// + /// Applies a step as part of the task to compare two objects for structural equality. + /// + /// + /// Should return true if the subject matches the expectation or if no additional assertions + /// have to be executed. Should return false otherwise. + /// + /// + /// May throw when preconditions are not met or if it detects mismatching data. + /// + public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator structuralEqualityValidator, IEquivalencyAssertionOptions config) + { + context.Subject.Should().Be(context.Expectation, context.Because, context.BecauseArgs); + + return true; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Equivalency/ValueTypeEquivalencyStep.cs.meta b/Assets/Plugins/FluentAssertions/Core/Equivalency/ValueTypeEquivalencyStep.cs.meta new file mode 100644 index 0000000..98d3f4c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Equivalency/ValueTypeEquivalencyStep.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 960d3dffe8f28c141a3173dce1aaefe8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/EquivalencyStepCollection.cs b/Assets/Plugins/FluentAssertions/Core/EquivalencyStepCollection.cs new file mode 100644 index 0000000..e45dca5 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/EquivalencyStepCollection.cs @@ -0,0 +1,123 @@ +#region + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using FluentAssertions.Equivalency; + +#endregion + +namespace FluentAssertions +{ + /// + /// Represents a mutable collection of equivalency steps that can be reordered and/or amended with additional + /// custom equivalency steps. + /// + public class EquivalencyStepCollection : IEnumerable + { + private List steps; + + public EquivalencyStepCollection() + { + steps = GetDefaultSteps().ToList(); + } + + public IEnumerator GetEnumerator() + { + return steps.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + /// Adds a new after any of the built-in steps, with the exception of the final + /// . + /// + public void Add() where TStep : IEquivalencyStep, new() + { + InsertBefore(); + } + + /// + /// Adds a new right after the specified . + /// + public void AddAfter() where TStep : IEquivalencyStep, new() + { + int insertIndex = Math.Max(steps.Count - 1, 0); + + IEquivalencyStep predecessor = steps.LastOrDefault(s => s is TPredecessor); + if (predecessor != null) + { + insertIndex = Math.Min(insertIndex, steps.LastIndexOf(predecessor) + 1); + } + + steps.Insert(insertIndex, new TStep()); + } + + /// + /// Inserts a new before any of the built-in steps. + /// + public void Insert() where TStep : IEquivalencyStep, new() + { + steps.Insert(0, new TStep()); + } + + /// + /// Inserts a new just before the . + /// + public void InsertBefore() where TStep : IEquivalencyStep, new() + { + int insertIndex = Math.Max(steps.Count - 1, 0); + + IEquivalencyStep equalityStep = steps.LastOrDefault(s => s is TSuccessor); + if (equalityStep != null) + { + insertIndex = steps.LastIndexOf(equalityStep); + } + + steps.Insert(insertIndex, new TStep()); + } + + /// + /// Removes all instances of the specified from the current step. + /// + public void Remove() where TStep : IEquivalencyStep + { + steps.RemoveAll(s => s is TStep); + } + + /// + /// Removes each and every built-in . + /// + public void Clear() + { + steps.Clear(); + } + + public void Reset() + { + steps = GetDefaultSteps().ToList(); + } + + private static IEnumerable GetDefaultSteps() + { + yield return new RunAllUserStepsEquivalencyStep(); + yield return new TryConversionEquivalencyStep(); + yield return new ReferenceEqualityEquivalencyStep(); + yield return new GenericDictionaryEquivalencyStep(); + yield return new DictionaryEquivalencyStep(); + yield return new MultiDimensionalArrayEquivalencyStep(); + yield return new GenericEnumerableEquivalencyStep(); + yield return new EnumerableEquivalencyStep(); + yield return new StringEqualityEquivalencyStep(); + yield return new EnumEqualityStep(); + yield return new ValueTypeEquivalencyStep(); + yield return new StructuralEqualityEquivalencyStep(); + yield return new SimpleEqualityEquivalencyStep(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/EquivalencyStepCollection.cs.meta b/Assets/Plugins/FluentAssertions/Core/EquivalencyStepCollection.cs.meta new file mode 100644 index 0000000..0a7a7b2 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/EquivalencyStepCollection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 428d1b1da3340f248a020fbc252c26d0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Events.meta b/Assets/Plugins/FluentAssertions/Core/Events.meta new file mode 100644 index 0000000..95edd00 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Events.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 57483a48005f64144b9821e9e02b4a18 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Events/EventMonitor.cs b/Assets/Plugins/FluentAssertions/Core/Events/EventMonitor.cs new file mode 100644 index 0000000..e86fb9a --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Events/EventMonitor.cs @@ -0,0 +1,28 @@ +using System; + +namespace FluentAssertions.Events +{ + /// + /// Monitors events on a given source + /// + public interface IEventMonitor + { + /// + /// Attaches event monitoring for the events defined by . + /// + /// A type implemented by the monitored object + void Attach(Type typeDefiningEventsToMonitor); + + /// + /// Gets the for the event with the given name. + /// + /// The name of the event for which the is required. + /// The for the event with the given name, if it exists; otherwise, null. + IEventRecorder GetEventRecorder(string eventName); + + /// + /// Resets monitor to clear records of events raised so far. + /// + void Reset(); + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Events/EventMonitor.cs.meta b/Assets/Plugins/FluentAssertions/Core/Events/EventMonitor.cs.meta new file mode 100644 index 0000000..0c9f850 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Events/EventMonitor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2264adc105cfadd4186527fc0bc26db7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Events/EventRecorder.cs b/Assets/Plugins/FluentAssertions/Core/Events/EventRecorder.cs new file mode 100644 index 0000000..b98217b --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Events/EventRecorder.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +namespace FluentAssertions.Events +{ + /// + /// Records activity for a single event. + /// + [DebuggerNonUserCode] + public class EventRecorder : IEventRecorder + { + private readonly IList raisedEvents = new List(); + private readonly object lockable = new object(); + private WeakReference eventObject; + + /// + /// + /// The object events are recorded from + /// The name of the event that's recorded + public EventRecorder(object eventRaiser, string eventName) + { + EventObject = eventRaiser; + EventName = eventName; + } + + /// + /// The object events are recorded from + /// + public object EventObject + { + get { return (eventObject == null) ? null : eventObject.Target; } + private set { eventObject = new WeakReference(value); } + } + + /// + /// The name of the event that's recorded + /// + public string EventName { get; private set; } + + /// + /// Enumerate raised events + /// + public IEnumerator GetEnumerator() + { + lock (lockable) + { + return raisedEvents.ToList().GetEnumerator(); + } + } + + /// + /// Enumerate raised events + /// + /// + IEnumerator IEnumerable.GetEnumerator() + { + lock (lockable) + { + return raisedEvents.ToList().GetEnumerator(); + } + } + + /// + /// Called by the auto-generated IL, to record information about a raised event. + /// + public void RecordEvent(params object [] parameters) + { + lock (lockable) + { + raisedEvents.Add(new RecordedEvent(EventObject, parameters)); + } + } + + /// + /// Resets recorder to clear records of events raised so far. + /// + public void Reset() + { + lock ( lockable ) + { + raisedEvents.Clear(); + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Events/EventRecorder.cs.meta b/Assets/Plugins/FluentAssertions/Core/Events/EventRecorder.cs.meta new file mode 100644 index 0000000..ba20a1a --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Events/EventRecorder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: abc2716a81b3d14468401b63687f1d42 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Events/EventRecordersMap.cs b/Assets/Plugins/FluentAssertions/Core/Events/EventRecordersMap.cs new file mode 100644 index 0000000..2ae2053 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Events/EventRecordersMap.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +namespace FluentAssertions.Events +{ + /// + /// Simple dictionary that uses a to the event source as the key. + /// This should ensure the Garbage Collector can still clean-up the event source object. + /// + [DebuggerNonUserCode] + public sealed class EventRecordersMap + { + private readonly Dictionary map = new Dictionary(); + + public void Add(object eventSource, IEventMonitor recorder ) + { + ForEach(eventSource, keyValuePair => map.Remove(keyValuePair.Key)); + + map.Add(new WeakReference(eventSource), recorder ); + } + + public IEventMonitor this[object eventSource] + { + get + { + IEventMonitor result = null; + TryGetMonitor( eventSource, out result ); + + if (result == null) + { + throw new InvalidOperationException(string.Format( + "Object <{0}> is not being monitored for events or has already been garbage collected. " + + "Use the MonitorEvents() extension method to start monitoring events.", eventSource)); + } + + return result; + } + } + + public bool TryGetMonitor(object eventSource, out IEventMonitor eventMonitor) + { + IEventMonitor result = null; + ForEach( eventSource, pair => result = pair.Value ); + eventMonitor = result; + return eventMonitor != null; + } + + private void ForEach(object eventSource, Action> action) + { + foreach (var keyValuePair in map.ToArray()) + { + if (IsObjectGarbageCollected(keyValuePair.Key)) + { + map.Remove(keyValuePair.Key); + } + else if (RefersToSameObject(keyValuePair.Key, eventSource)) + { + action(keyValuePair); + } + else + { + // Ignore + } + } + } + + private static bool RefersToSameObject(WeakReference weakReference, object eventSource) + { + return ReferenceEquals(weakReference.Target, eventSource); + } + + private static bool IsObjectGarbageCollected(WeakReference weakReference) + { + return ReferenceEquals(weakReference.Target, null); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Events/EventRecordersMap.cs.meta b/Assets/Plugins/FluentAssertions/Core/Events/EventRecordersMap.cs.meta new file mode 100644 index 0000000..e5e68f2 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Events/EventRecordersMap.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: acfae1768870ff04fadea588dcc41e4b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Events/IEventRecorder.cs b/Assets/Plugins/FluentAssertions/Core/Events/IEventRecorder.cs new file mode 100644 index 0000000..22e94cf --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Events/IEventRecorder.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; + +namespace FluentAssertions.Events +{ + /// + /// Records raised events for one event on one object + /// + public interface IEventRecorder : IEnumerable + { + /// + /// Store information about a raised event + /// + /// Parameters the event was raised with + void RecordEvent(params object[] parameters); + + /// + /// Resets the event recorder, removing any revents recorded thus far. + /// + void Reset(); + + /// + /// The object events are recorded from + /// + object EventObject { get; } + + /// + /// The name of the event that's recorded + /// + string EventName { get; } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Events/IEventRecorder.cs.meta b/Assets/Plugins/FluentAssertions/Core/Events/IEventRecorder.cs.meta new file mode 100644 index 0000000..3fba327 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Events/IEventRecorder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 63046a9045a62934d8e08f6a2374fd94 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Events/RecordedEvent.cs b/Assets/Plugins/FluentAssertions/Core/Events/RecordedEvent.cs new file mode 100644 index 0000000..1e4dc4a --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Events/RecordedEvent.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +namespace FluentAssertions.Events +{ + /// + /// This class is used to store data about an intercepted event + /// + [DebuggerNonUserCode] + public class RecordedEvent + { + private object[] parameters; + + /// + /// Default constructor stores the parameters the event was raised with + /// + public RecordedEvent(object monitoredObject, params object[] parameters) + { + Parameters = parameters.Select(p => (p == monitoredObject) ? new WeakReference(p) : p); + } + + /// + /// Parameters for the event + /// + public IEnumerable Parameters + { + get + { + return parameters.Select(parameter => + { + var weakReference = parameter as WeakReference; + return (weakReference != null) ? weakReference.Target : parameter; + }).ToArray(); + } + + private set { parameters = value.ToArray(); } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Events/RecordedEvent.cs.meta b/Assets/Plugins/FluentAssertions/Core/Events/RecordedEvent.cs.meta new file mode 100644 index 0000000..8107b47 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Events/RecordedEvent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 352d3238e3cfe2640a10a1f2f0168a51 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Execution.meta b/Assets/Plugins/FluentAssertions/Core/Execution.meta new file mode 100644 index 0000000..f043634 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7e36ab149adbf624c99b1c70006d0fc9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/AssertionScope.cs b/Assets/Plugins/FluentAssertions/Core/Execution/AssertionScope.cs new file mode 100644 index 0000000..df142d1 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/AssertionScope.cs @@ -0,0 +1,264 @@ +#region + +using System; +using System.Linq; +using FluentAssertions.Common; + +#endregion + +namespace FluentAssertions.Execution +{ + /// + /// Represents an implicit or explicit scope within which multiple assertions can be collected. + /// + public class AssertionScope : IDisposable + { + #region Private Definitions + + private readonly IAssertionStrategy assertionStrategy; + private readonly ContextDataItems contextData = new ContextDataItems(); + + private string reason; + private bool useLineBreaks; + + [ThreadStatic] + private static AssertionScope current; + + private AssertionScope parent; + private string expectation = ""; + private readonly bool evaluateCondition = true; + + #endregion + + private AssertionScope(IAssertionStrategy _assertionStrategy) + { + assertionStrategy = _assertionStrategy; + parent = null; + } + + /// + /// Starts an unnamed scope within which multiple assertions can be executed and which will not throw until the scope is disposed. + /// + public AssertionScope() + : this(new CollectingAssertionStrategy()) + { + parent = current; + current = this; + + if (parent != null) + { + contextData.Add(parent.contextData); + } + } + + /// + /// Starts a named scope within which multiple assertions can be executed and which will not throw until the scope is disposed. + /// + public AssertionScope(string context) : this() + { + AddNonReportable("context", context); + } + + /// + /// Creates a nested scope used during chaining. + /// + internal AssertionScope(AssertionScope sourceScope, bool sourceSucceeded) + { + assertionStrategy = sourceScope.assertionStrategy; + contextData = sourceScope.contextData; + reason = sourceScope.reason; + useLineBreaks = sourceScope.useLineBreaks; + parent = sourceScope.parent; + expectation = sourceScope.expectation; + evaluateCondition = sourceSucceeded; + } + + /// + /// Gets the current thread-specific assertion scope. + /// + public static AssertionScope Current + { + get { return current ?? new AssertionScope(new DefaultAssertionStrategy()); } + private set { current = value; } + } + + /// + /// Indicates that every argument passed into is displayed on a separate line. + /// + public AssertionScope UsingLineBreaks + { + get + { + useLineBreaks = true; + return this; + } + } + + /// + /// Gets a value indicating whether or not the last assertion executed through this scope succeeded. + /// + public bool Succeeded { get; private set; } + + /// + /// Specify the reason why you expect the condition to be true. + /// + /// + /// A formatted phrase explaining why the condition should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public AssertionScope BecauseOf(string because, params object[] becauseArgs) + { + reason = string.Format(because ?? "", becauseArgs ?? new object[0]); + return this; + } + + /// + /// Sets the expectation part of the failure message when the assertion is not met. + /// + /// + /// In addition to the numbered -style placeholders, messages may contain a few + /// specialized placeholders as well. For instance, {reason} will be replaced with the reason of the assertion as passed + /// to . Other named placeholders will be replaced with the scope data + /// passed through and . Finally, a description of the + /// current subject can be passed through the {context:description} placeholder. This is used in the message if no + /// explicit context is specified through the constructor. + /// Note that only 10 are supported in combination with a {reason}. + /// If an expectation was set through a prior call to , then the failure message is appended to that + /// expectation. + /// + /// The format string that represents the failure message. + /// Optional arguments to any numbered placeholders. + public AssertionScope WithExpectation(string expectation, params object[] args) + { + this.expectation = new MessageBuilder(useLineBreaks).Build(expectation, args, reason, contextData); + return this; + } + + /// + /// Allows to safely select the subject for successive assertions, even when the prior assertion has failed. + /// + /// + /// Selector which result is passed to successive calls to . + /// + public GivenSelector Given(Func selector) + { + return new GivenSelector(selector, evaluateCondition, this); + } + + /// + /// Specify the condition that must be satisfied. + /// + /// + /// If true the assertion will be treated as successful and no exceptions will be thrown. + /// + public AssertionScope ForCondition(bool condition) + { + if (evaluateCondition) + { + Succeeded = condition; + } + + return this; + } + + /// + /// Sets the failure message when the assertion is not met, or completes the failure message set to a + /// prior call to to . + /// + /// + /// In addition to the numbered -style placeholders, messages may contain a few + /// specialized placeholders as well. For instance, {reason} will be replaced with the reason of the assertion as passed + /// to . Other named placeholders will be replaced with the scope data + /// passed through and . Finally, a description of the + /// current subject can be passed through the {context:description} placeholder. This is used in the message if no + /// explicit context is specified through the constructor. + /// Note that only 10 are supported in combination with a {reason}. + /// If an expectation was set through a prior call to , then the failure message is appended to that + /// expectation. + /// + /// The format string that represents the failure message. + /// Optional arguments to any numbered placeholders. + public Continuation FailWith(string message, params object[] args) + { + try + { + if (evaluateCondition && !Succeeded) + { + string result = new MessageBuilder(useLineBreaks).Build(message, args, reason, contextData); + + if (!string.IsNullOrEmpty(expectation)) + { + result = expectation + result; + } + + assertionStrategy.HandleFailure(result.Capitalize()); + } + + return new Continuation(this, Succeeded); + } + finally + { + Succeeded = false; + } + } + + /// + /// Adds a pre-formatted failure message to the current scope. + /// + public void AddFailure(string formattedFailureMessage) + { + assertionStrategy.HandleFailure(formattedFailureMessage); + } + + public void AddNonReportable(string key, object value) + { + contextData.Add(key, value, Reportability.Hidden); + } + + public void AddReportable(string key, string value) + { + contextData.Add(key, value, Reportability.Reportable); + } + + /// + /// Discards and returns the failures that happened up to now. + /// + public string[] Discard() + { + return assertionStrategy.DiscardFailures().ToArray(); + } + + /// + /// Gets data associated with the current scope and identified by . + /// + public T Get(string key) + { + return contextData.Get(key); + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + Current = parent; + + if (parent != null) + { + foreach (string failureMessage in assertionStrategy.FailureMessages) + { + parent.assertionStrategy.HandleFailure(failureMessage); + } + + parent = null; + } + else + { + assertionStrategy.ThrowIfAny(contextData.Reportable); + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/AssertionScope.cs.meta b/Assets/Plugins/FluentAssertions/Core/Execution/AssertionScope.cs.meta new file mode 100644 index 0000000..1617337 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/AssertionScope.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9c58fda7efe37e442bcd2844de8e8287 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/CollectingAssertionStrategy.cs b/Assets/Plugins/FluentAssertions/Core/Execution/CollectingAssertionStrategy.cs new file mode 100644 index 0000000..3e71739 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/CollectingAssertionStrategy.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using FluentAssertions.Common; + +namespace FluentAssertions.Execution +{ + internal class CollectingAssertionStrategy : IAssertionStrategy + { + private readonly List failureMessages = new List(); + + /// + /// Returns the messages for the assertion failures that happened until now. + /// + public IEnumerable FailureMessages + { + get { return failureMessages; } + } + + /// + /// Discards and returns the failure messages that happened up to now. + /// + public IEnumerable DiscardFailures() + { + var discardedFailures = failureMessages.ToArray(); + failureMessages.Clear(); + return discardedFailures; + } + + /// + /// Will throw a combined exception for any failures have been collected since was called. + /// + public void ThrowIfAny(IDictionary context) + { + if (failureMessages.Any()) + { + var builder = new StringBuilder(); + builder.AppendLine(string.Join(Environment.NewLine, failureMessages.ToArray())); + + if (context.Any()) + { + foreach (KeyValuePair pair in context) + { + builder.AppendFormat("\nWith {0}:\n{1}", pair.Key, pair.Value); + } + } + + Services.ThrowException(builder.ToString()); + } + } + + /// + /// Instructs the strategy to handle a assertion failure. + /// + public void HandleFailure(string message) + { + failureMessages.Add(message); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/CollectingAssertionStrategy.cs.meta b/Assets/Plugins/FluentAssertions/Core/Execution/CollectingAssertionStrategy.cs.meta new file mode 100644 index 0000000..316bb8e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/CollectingAssertionStrategy.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7082eec06582f824ea48645dc7c9f654 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/ContextDataItems.cs b/Assets/Plugins/FluentAssertions/Core/Execution/ContextDataItems.cs new file mode 100644 index 0000000..05189eb --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/ContextDataItems.cs @@ -0,0 +1,93 @@ +using System.Collections.Generic; +using System.Linq; + +using FluentAssertions.Formatting; + +namespace FluentAssertions.Execution +{ + /// + /// Represents a collection of data items that are associated with an . + /// + internal class ContextDataItems + { + private readonly List items = new List(); + + public IDictionary Reportable + { + get { return items.Where(item => item.Reportable).ToDictionary(item => item.Key, item => item.Value); } + } + + public string AsStringOrDefault(string key) + { + DataItem item = items.SingleOrDefault(i => i.Key == key); + if (item != null) + { + if ((key == "subject") || (key == "expectation")) + { + return Formatter.ToString(item.Value); + } + + return item.Value.ToString(); + } + + return null; + } + + public void Add(ContextDataItems contextDataItems) + { + foreach (var item in contextDataItems.items) + { + Add(item.Clone()); + } + } + + public void Add(string key, object value, Reportability reportability) + { + Add(new DataItem(key, value, reportability)); + } + + private void Add(DataItem item) + { + var existingItem = items.SingleOrDefault(i => i.Key == item.Key); + if (existingItem != null) + { + items.Remove(existingItem); + } + + items.Add(item); + } + + public T Get(string key) + { + DataItem item = items.SingleOrDefault(i => i.Key == key); + return (T)((item != null) ? item.Value : default(T)); + } + + internal class DataItem + { + private readonly Reportability reportability; + + public DataItem(string key, object value, Reportability reportability) + { + Key = key; + Value = value; + this.reportability = reportability; + } + + public string Key { get; private set; } + + public object Value { get; private set; } + + public bool Reportable + { + get { return reportability == Reportability.Reportable; } + } + + public DataItem Clone() + { + var cloneable = Value as ICloneable2; + return new DataItem(Key, (cloneable != null) ? cloneable.Clone() : Value, reportability); + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/ContextDataItems.cs.meta b/Assets/Plugins/FluentAssertions/Core/Execution/ContextDataItems.cs.meta new file mode 100644 index 0000000..3481520 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/ContextDataItems.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ba80036ea9489964cb3a11313448f2ba +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/Continuation.cs b/Assets/Plugins/FluentAssertions/Core/Execution/Continuation.cs new file mode 100644 index 0000000..07b300c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/Continuation.cs @@ -0,0 +1,42 @@ +namespace FluentAssertions.Execution +{ + /// + /// Enables chaining multiple assertions on an . + /// + public class Continuation + { + #region Private Definition + + private readonly AssertionScope sourceScope; + private readonly bool sourceSucceeded; + + #endregion + + public Continuation(AssertionScope sourceScope, bool sourceSucceeded) + { + this.sourceScope = sourceScope; + this.sourceSucceeded = sourceSucceeded; + } + + /// + /// Continuous the assertion chain if the previous assertion was successful. + /// + public AssertionScope Then + { + get { return new AssertionScope(sourceScope, sourceSucceeded); } + } + + public bool SourceSucceeded + { + get { return sourceSucceeded; } + } + + /// + /// Provides back-wards compatibility for code that expects to return a boolean. + /// + public static implicit operator bool(Continuation continuation) + { + return continuation.sourceSucceeded; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/Continuation.cs.meta b/Assets/Plugins/FluentAssertions/Core/Execution/Continuation.cs.meta new file mode 100644 index 0000000..2aee9e1 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/Continuation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1bf5ea098f6ebc0429ba24bdddcea97c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/ContinuationOfGiven.cs b/Assets/Plugins/FluentAssertions/Core/Execution/ContinuationOfGiven.cs new file mode 100644 index 0000000..0bf3895 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/ContinuationOfGiven.cs @@ -0,0 +1,37 @@ +namespace FluentAssertions.Execution +{ + /// + /// Enables chaining multiple assertions from a call. + /// + public class ContinuationOfGiven + { + #region Private Definitions + + private readonly GivenSelector parent; + private readonly bool succeeded; + + #endregion + + public ContinuationOfGiven(GivenSelector parent, bool succeeded) + { + this.parent = parent; + this.succeeded = succeeded; + } + + /// + /// Continuous the assertion chain if the previous assertion was successful. + /// + public GivenSelector Then + { + get { return parent; } + } + + /// + /// Provides back-wards compatibility for code that expects to return a boolean. + /// + public static implicit operator bool(ContinuationOfGiven continuationOfGiven) + { + return continuationOfGiven.succeeded; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/ContinuationOfGiven.cs.meta b/Assets/Plugins/FluentAssertions/Core/Execution/ContinuationOfGiven.cs.meta new file mode 100644 index 0000000..85188a3 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/ContinuationOfGiven.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1ee1b7a9e7b3adc40bbe843a5e7cee66 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/DefaultAssertionStrategy.cs b/Assets/Plugins/FluentAssertions/Core/Execution/DefaultAssertionStrategy.cs new file mode 100644 index 0000000..05e944e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/DefaultAssertionStrategy.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; + +using FluentAssertions.Common; + +namespace FluentAssertions.Execution +{ + internal class DefaultAssertionStrategy : IAssertionStrategy + { + /// + /// Returns the messages for the assertion failures that happened until now. + /// + public IEnumerable FailureMessages + { + get + { + return new string[0]; + } + } + + /// + /// Instructs the strategy to handle a assertion failure. + /// + public void HandleFailure(string message) + { + Services.ThrowException(message); + } + + /// + /// Discards and returns the failure messages that happened up to now. + /// + public IEnumerable DiscardFailures() + { + return new string[0]; + } + + /// + /// Will throw a combined exception for any failures have been collected since was called. + /// + public void ThrowIfAny(IDictionary context) + { + + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/DefaultAssertionStrategy.cs.meta b/Assets/Plugins/FluentAssertions/Core/Execution/DefaultAssertionStrategy.cs.meta new file mode 100644 index 0000000..ffa4cc2 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/DefaultAssertionStrategy.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ded064d2fec0f204290b64dfe5f326e6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/Execute.cs b/Assets/Plugins/FluentAssertions/Core/Execution/Execute.cs new file mode 100644 index 0000000..55ce9ad --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/Execute.cs @@ -0,0 +1,23 @@ +using FluentAssertions.Common; + +namespace FluentAssertions.Execution +{ + /// + /// Helper class for verifying a condition and/or throwing a test harness specific exception representing an assertion failure. + /// + public static class Execute + { + /// + /// Gets an object that wraps and executes a conditional or unconditional assertion. + /// + public static AssertionScope Assertion + { + get + { + Services.Initialize(); + + return AssertionScope.Current; + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/Execute.cs.meta b/Assets/Plugins/FluentAssertions/Core/Execution/Execute.cs.meta new file mode 100644 index 0000000..34d7dc4 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/Execute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8438c164bb2b91944aee225047c96e25 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/GivenSelector.cs b/Assets/Plugins/FluentAssertions/Core/Execution/GivenSelector.cs new file mode 100644 index 0000000..23f1f1c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/GivenSelector.cs @@ -0,0 +1,129 @@ +using System; +using System.Linq; + +namespace FluentAssertions.Execution +{ + /// + /// Represents a chaining object returned from to continue the assertion using + /// an object returned by a selector. + /// + public class GivenSelector + { + #region Private Definitions + + private readonly T subject; + private readonly bool evaluateCondition; + private readonly AssertionScope parentScope; + + #endregion + + public GivenSelector(Func selector, bool evaluateCondition, AssertionScope parentScope) + { + this.evaluateCondition = evaluateCondition; + this.parentScope = parentScope; + + subject = evaluateCondition ? selector() : default(T); + } + + /// + /// Specify the condition that must be satisfied upon the subject selected through a prior selector. + /// + /// + /// If true the assertion will be treated as successful and no exceptions will be thrown. + /// + /// + /// The condition will not be evaluated if the prior assertion failed, nor will + /// throw any exceptions. + /// + public GivenSelector ForCondition(Func predicate) + { + if (evaluateCondition) + { + parentScope.ForCondition(predicate(subject)); + } + + return this; + } + + /// + /// Allows to safely refine the subject for successive assertions, even when the prior assertion has failed. + /// + /// + /// Selector which result is passed to successive calls to . + /// + /// + /// The selector will not be invoked if the prior assertion failed, nor will + /// throw any exceptions. + /// + public GivenSelector Given(Func selector) + { + return new GivenSelector(() => selector(subject), evaluateCondition, parentScope); + } + + /// + /// Sets the failure message when the assertion is not met, or completes the failure message set to a + /// prior call to to . + /// + /// + /// If an expectation was set through a prior call to , then the failure message is appended to that + /// expectation. + /// + /// The format string that represents the failure message. + public ContinuationOfGiven FailWith(string message) + { + return FailWith(message, new object[0]); + } + + /// + /// Sets the failure message when the assertion is not met, or completes the failure message set to a + /// prior call to to . + /// + /// + /// In addition to the numbered -style placeholders, messages may contain a few + /// specialized placeholders as well. For instance, {reason} will be replaced with the reason of the assertion as passed + /// to . Other named placeholders will be replaced with the scope data + /// passed through and . Finally, a description of the + /// current subject can be passed through the {context:description} placeholder. This is used in the message if no + /// explicit context is specified through the constructor. + /// Note that only 10 are supported in combination with a {reason}. + /// If an expectation was set through a prior call to , then the failure message is appended to that + /// expectation. + /// + /// The format string that represents the failure message. + /// Optional arguments to any numbered placeholders. + public ContinuationOfGiven FailWith(string message, params Func[] args) + { + return FailWith(message, args.Select(a => a(subject)).ToArray()); + } + + /// + /// Sets the failure message when the assertion is not met, or completes the failure message set to a + /// prior call to to . + /// + /// + /// In addition to the numbered -style placeholders, messages may contain a few + /// specialized placeholders as well. For instance, {reason} will be replaced with the reason of the assertion as passed + /// to . Other named placeholders will be replaced with the scope data + /// passed through and . Finally, a description of the + /// current subject can be passed through the {context:description} placeholder. This is used in the message if no + /// explicit context is specified through the constructor. + /// Note that only 10 are supported in combination with a {reason}. + /// If an expectation was set through a prior call to , then the failure message is appended to that + /// expectation. + /// + /// The format string that represents the failure message. + /// Optional arguments to any numbered placeholders. + public ContinuationOfGiven FailWith(string message, params object[] args) + { + bool succeeded = parentScope.Succeeded; + + if (evaluateCondition) + { + Continuation continuation = parentScope.FailWith(message, args); + succeeded = continuation.SourceSucceeded; + } + + return new ContinuationOfGiven(this, succeeded); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/GivenSelector.cs.meta b/Assets/Plugins/FluentAssertions/Core/Execution/GivenSelector.cs.meta new file mode 100644 index 0000000..5d78f77 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/GivenSelector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7af38290dfae0614abca9e72153f42a5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/GivenSelectorExtensions.cs b/Assets/Plugins/FluentAssertions/Core/Execution/GivenSelectorExtensions.cs new file mode 100644 index 0000000..325a154 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/GivenSelectorExtensions.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace FluentAssertions.Execution +{ + internal static class GivenSelectorExtensions + { + public static ContinuationOfGiven> AssertCollectionIsNotNullOrEmpty( + this GivenSelector> givenSelector, int length) + { + return givenSelector + .AssertCollectionIsNotNull() + .Then + .AssertEitherCollectionIsNotEmpty(length); + } + + public static ContinuationOfGiven> AssertCollectionIsNotNull( + this GivenSelector> givenSelector) + { + return givenSelector + .ForCondition(items => !ReferenceEquals(items, null)) + .FailWith("but found collection is ."); + } + + public static ContinuationOfGiven> AssertEitherCollectionIsNotEmpty( + this GivenSelector> givenSelector, int length) + { + return givenSelector + .ForCondition(items => !EitherIsEmpty(length, items.Count())) + .FailWith("but found empty collection."); + } + + private static bool EitherIsEmpty(int length1, int length2) + { + return ((length1 == 0) && (length2 > 0)) || ((length1 > 0) && (length2 == 0)); + } + + public static ContinuationOfGiven AssertCollectionHasEnoughItems(this GivenSelector> givenSelector, + int length) + { + return givenSelector + .Given(items => items.ToArray()) + .AssertCollectionHasEnoughItems(length); + } + + public static ContinuationOfGiven AssertCollectionHasEnoughItems(this GivenSelector givenSelector, int length) + { + return givenSelector + .Given(items => items.ToArray()) + .ForCondition(items => items.Length >= length) + .FailWith("but {0} contains {1} item(s) less.", items => items, items => length - items.Length); + } + + public static ContinuationOfGiven AssertCollectionHasNotTooManyItems(this GivenSelector givenSelector, + int length) + { + return givenSelector + .Given(items => items.ToArray()) + .ForCondition(items => items.Length <= length) + .FailWith("but {0} contains {1} item(s) too many.", items => items, items => items.Length - length); + } + + public static ContinuationOfGiven AssertCollectionsHaveSameCount(this GivenSelector> givenSelector, + int length) + { + return givenSelector + .AssertEitherCollectionIsNotEmpty(length) + .Then + .AssertCollectionHasEnoughItems(length) + .Then + .AssertCollectionHasNotTooManyItems(length); + } + + public static void AssertCollectionsHaveSameItems(this GivenSelector givenSelector, + TExpected[] expected, Func findIndex) + { + givenSelector + .Given(actual => new {Items = actual, Index = findIndex(actual, expected)}) + .ForCondition(diff => diff.Index == -1) + .FailWith("but {0} differs at index {1}.", diff => diff.Items, diff => diff.Index); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/GivenSelectorExtensions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Execution/GivenSelectorExtensions.cs.meta new file mode 100644 index 0000000..7629d14 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/GivenSelectorExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d527a77950dd59b42ab2ae145e52ee93 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/IAssertionStrategy.cs b/Assets/Plugins/FluentAssertions/Core/Execution/IAssertionStrategy.cs new file mode 100644 index 0000000..5db6668 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/IAssertionStrategy.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; + +namespace FluentAssertions.Execution +{ + /// + /// Defines a strategy for handling failures in a . + /// + public interface IAssertionStrategy + { + /// + /// Returns the messages for the assertion failures that happened until now. + /// + IEnumerable FailureMessages { get; } + + /// + /// Instructs the strategy to handle a assertion failure. + /// + void HandleFailure(string message); + + /// + /// Discards and returns the failure messages that happened up to now. + /// + IEnumerable DiscardFailures(); + + /// + /// Will throw a combined exception for any failures have been collected since was called. + /// + void ThrowIfAny(IDictionary context); + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/IAssertionStrategy.cs.meta b/Assets/Plugins/FluentAssertions/Core/Execution/IAssertionStrategy.cs.meta new file mode 100644 index 0000000..5b8fb23 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/IAssertionStrategy.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 70d4ad000cfc05d4ea3941142be82162 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/ICloneable2.cs b/Assets/Plugins/FluentAssertions/Core/Execution/ICloneable2.cs new file mode 100644 index 0000000..b4d0935 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/ICloneable2.cs @@ -0,0 +1,17 @@ +namespace FluentAssertions.Execution +{ + /// + /// Custom version of ICloneable that works on all frameworks. + /// + public interface ICloneable2 + { + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// + /// A new object that is a copy of this instance. + /// + object Clone(); + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/ICloneable2.cs.meta b/Assets/Plugins/FluentAssertions/Core/Execution/ICloneable2.cs.meta new file mode 100644 index 0000000..0abf0bd --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/ICloneable2.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 471b253b1d81a5e4487a1bee61f9f808 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/MessageBuilder.cs b/Assets/Plugins/FluentAssertions/Core/Execution/MessageBuilder.cs new file mode 100644 index 0000000..9b89616 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/MessageBuilder.cs @@ -0,0 +1,107 @@ +#region + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using FluentAssertions.Common; +using FluentAssertions.Formatting; + +#endregion + +namespace FluentAssertions.Execution +{ + /// + /// Encapsulates expanding the various placeholders supported in a failure message. + /// + internal class MessageBuilder + { + #region Private Definitions + + private readonly bool useLineBreaks; + + private readonly char[] blanks = {'\r', '\n', ' ', '\t'}; + + /// + /// Represents the phrase that can be used in as a placeholder for the reason of an assertion. + /// + private const string ReasonTag = "{reason}"; + + #endregion + + public MessageBuilder(bool useLineBreaks) + { + this.useLineBreaks = useLineBreaks; + } + + public string Build(string message, object[] messageArgs, string reason, ContextDataItems contextData) + { + string result = SubstituteReasonTag(message, SanitizeReason(reason)); + result = SubstituteContextualTags(result, contextData); + result = FormatArgumentPlaceholders(result, messageArgs); + return result; + } + + private string SubstituteReasonTag(string failureMessage, string reason) + { + return Regex.Replace(failureMessage, ReasonTag, reason); + } + + private string SubstituteContextualTags(string message, ContextDataItems contextData) + { + var regex = new Regex(@"\{(?[a-z|A-Z]+)(?:\:(?[a-z|A-Z|\s]+))?\}"); + return regex.Replace(message, match => + { + string key = match.Groups["key"].Value; + return + contextData.AsStringOrDefault(key)?.Replace("{", "{{").Replace("}", "}}") ?? + match.Groups["default"].Value; + }); + } + + private string FormatArgumentPlaceholders(string failureMessage, object[] failureArgs) + { + string[] values = failureArgs.Select(a => Formatter.ToString(a, useLineBreaks)).ToArray(); + + string formattedMessage = string.Format(failureMessage, values); + return formattedMessage.Replace("{{{{", "{{").Replace("}}}}", "}}"); + } + + private string SanitizeReason(string reason) + { + if (!string.IsNullOrEmpty(reason)) + { + reason = EnsurePrefix("because", reason); + reason = reason.Replace("{", "{{").Replace("}", "}}"); + + return StartsWithBlank(reason) ? reason : " " + reason; + } + + return ""; + } + + // SMELL: looks way too complex just to retain the leading whitepsace + private string EnsurePrefix(string prefix, string text) + { + string leadingBlanks = ExtractLeadingBlanksFrom(text); + string textWithoutLeadingBlanks = text.Substring(leadingBlanks.Length); + + return !textWithoutLeadingBlanks.StartsWith(prefix, StringComparison.CurrentCultureIgnoreCase) + ? leadingBlanks + prefix + " " + textWithoutLeadingBlanks + : text; + } + + private string ExtractLeadingBlanksFrom(string text) + { + string trimmedText = text.TrimStart(blanks); + int leadingBlanksCount = text.Length - trimmedText.Length; + + return text.Substring(0, leadingBlanksCount); + } + + private bool StartsWithBlank(string text) + { + return (text.Length > 0) && blanks.Any(blank => text[0] == blank); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/MessageBuilder.cs.meta b/Assets/Plugins/FluentAssertions/Core/Execution/MessageBuilder.cs.meta new file mode 100644 index 0000000..3fd7d6f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/MessageBuilder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c6462ce1a2203de4d9f48d985f9aa72f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/Reportability.cs b/Assets/Plugins/FluentAssertions/Core/Execution/Reportability.cs new file mode 100644 index 0000000..a835b01 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/Reportability.cs @@ -0,0 +1,11 @@ +namespace FluentAssertions.Execution +{ + /// + /// Determines whether data associated with an should be included in the assertion failure. + /// + internal enum Reportability + { + Hidden, + Reportable + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Execution/Reportability.cs.meta b/Assets/Plugins/FluentAssertions/Core/Execution/Reportability.cs.meta new file mode 100644 index 0000000..eb802e0 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Execution/Reportability.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8285f9f86a7b1d545b992268336e3b87 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/FluentDateTimeExtensions.cs b/Assets/Plugins/FluentAssertions/Core/FluentDateTimeExtensions.cs new file mode 100644 index 0000000..b0453cd --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/FluentDateTimeExtensions.cs @@ -0,0 +1,194 @@ +using System; +using System.Diagnostics; + +namespace FluentAssertions +{ + /// + /// Extension methods on to allow for a more fluent way of specifying a . + /// + /// + /// Instead of
+ ///
+ /// new DateTime(2011, 3, 10)
+ ///
+ /// you can write 3.March(2011)
+ ///
+ /// Or even
+ ///
+ /// 3.March(2011).At(09, 30) + ///
+ /// + [DebuggerNonUserCode] + public static class FluentDateTimeExtensions + { + /// + /// Returns a new value for the specified and + /// in the month January. + /// + public static DateTime January(this int day, int year) + { + return new DateTime(year, 1, day); + } + + /// + /// Returns a new value for the specified and + /// in the month February. + /// + public static DateTime February(this int day, int year) + { + return new DateTime(year, 2, day); + } + + /// + /// Returns a new value for the specified and + /// in the month March. + /// + public static DateTime March(this int day, int year) + { + return new DateTime(year, 3, day); + } + + /// + /// Returns a new value for the specified and + /// in the month April. + /// + public static DateTime April(this int day, int year) + { + return new DateTime(year, 4, day); + } + + /// + /// Returns a new value for the specified and + /// in the month May. + /// + public static DateTime May(this int day, int year) + { + return new DateTime(year, 5, day); + } + + /// + /// Returns a new value for the specified and + /// in the month June. + /// + public static DateTime June(this int day, int year) + { + return new DateTime(year, 6, day); + } + + /// + /// Returns a new value for the specified and + /// in the month July. + /// + public static DateTime July(this int day, int year) + { + return new DateTime(year, 7, day); + } + + /// + /// Returns a new value for the specified and + /// in the month August. + /// + public static DateTime August(this int day, int year) + { + return new DateTime(year, 8, day); + } + + /// + /// Returns a new value for the specified and + /// in the month September. + /// + public static DateTime September(this int day, int year) + { + return new DateTime(year, 9, day); + } + + /// + /// Returns a new value for the specified and + /// in the month October. + /// + public static DateTime October(this int day, int year) + { + return new DateTime(year, 10, day); + } + + /// + /// Returns a new value for the specified and + /// in the month November. + /// + public static DateTime November(this int day, int year) + { + return new DateTime(year, 11, day); + } + + /// + /// Returns a new value for the specified and + /// in the month December. + /// + public static DateTime December(this int day, int year) + { + return new DateTime(year, 12, day); + } + + /// + /// Returns a new value for the specified and . + /// + public static DateTime At(this DateTime date, TimeSpan time) + { + return new DateTime(date.Year, date.Month, date.Day, time.Hours, time.Minutes, time.Seconds); + } + + /// + /// Returns a new value for the specified and time with the specified + /// , and optionally . + /// + public static DateTime At(this DateTime date, int hours, int minutes, int seconds = 0, int milliseconds = 0) + { + return new DateTime(date.Year, date.Month, date.Day, hours, minutes, seconds, milliseconds); + } + + /// + /// Returns a new value for the specified and time with the specified + /// , and optionally . + /// + public static DateTimeOffset At(this DateTimeOffset date, int hours, int minutes, int seconds = 0, int milliseconds = 0) + { + return new DateTimeOffset(date.Year, date.Month, date.Day, hours, minutes, seconds, milliseconds, date.Offset); + } + + /// + /// Returns a new value for the specified and time with + /// the kind set to . + /// + public static DateTime AsUtc(this DateTime dateTime) + { + return DateTime.SpecifyKind(dateTime, DateTimeKind.Utc); + } + + /// + /// Returns a new value for the specified and time with + /// the kind set to . + /// + public static DateTime AsLocal(this DateTime dateTime) + { + return DateTime.SpecifyKind(dateTime, DateTimeKind.Local); + } + + /// + /// Returns a new value that is the current before the + /// specified . + /// + public static DateTime Before(this TimeSpan timeDifference, DateTime sourceDateTime) + { + return sourceDateTime.Subtract(timeDifference); + } + + /// + /// Returns a new value that is the current after the + /// specified . + /// + public static DateTime After(this TimeSpan timeDifference, DateTime sourceDateTime) + { + return sourceDateTime.Add(timeDifference); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/FluentDateTimeExtensions.cs.meta b/Assets/Plugins/FluentAssertions/Core/FluentDateTimeExtensions.cs.meta new file mode 100644 index 0000000..27ccff7 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/FluentDateTimeExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 29b0ff2468d8ad04289c4c48bd02f7f6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting.meta b/Assets/Plugins/FluentAssertions/Core/Formatting.meta new file mode 100644 index 0000000..c7573f8 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9043c1e5e33193d41a5f79a230cc5421 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/AggregateExceptionValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/AggregateExceptionValueFormatter.cs new file mode 100644 index 0000000..ddba4ce --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/AggregateExceptionValueFormatter.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace FluentAssertions.Formatting +{ + public class AggregateExceptionValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return value is AggregateException; + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + var exception = (AggregateException)value; + if (exception.InnerExceptions.Count == 1) + { + return "(aggregated) " + Formatter.ToString(exception.InnerException); + } + else + { + var builder = new StringBuilder(); + + builder.AppendFormat("{0} (aggregated) exceptions:\n", exception.InnerExceptions.Count); + + foreach (Exception innerException in exception.InnerExceptions) + { + builder.AppendLine(); + builder.AppendLine(Formatter.ToString(innerException)); + } + + return builder.ToString(); + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/AggregateExceptionValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/AggregateExceptionValueFormatter.cs.meta new file mode 100644 index 0000000..e7e6d06 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/AggregateExceptionValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5413070175b647f40a0fe978e40fa382 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/AttributeBasedFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/AttributeBasedFormatter.cs new file mode 100644 index 0000000..2fb500b --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/AttributeBasedFormatter.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; + +using FluentAssertions.Common; + +namespace FluentAssertions.Formatting +{ + /// + /// Specialized value formatter that looks for static methods in the caller's assembly marked with the + /// . + /// + public class AttributeBasedFormatter : IValueFormatter + { + private MethodInfo[] formatters; + private ValueFormatterDetectionMode detectionMode = ValueFormatterDetectionMode.Disabled; + + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return IsScanningEnabled && (value != null) && (GetFormatter(value) != null); + } + + private static bool IsScanningEnabled + { + get { return (Configuration.Current.ValueFormatterDetectionMode != ValueFormatterDetectionMode.Disabled); } + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + MethodInfo method = GetFormatter(value); + return (string)method.Invoke(null, new[] + { + value + }); + } + + private MethodInfo GetFormatter(object value) + { + return Formatters.FirstOrDefault(m => m.GetParameters().Single().ParameterType == value.GetType()); + } + + public MethodInfo[] Formatters + { + get + { + HandleValueFormatterDetectionModeChanges(); + + return formatters ?? (formatters = FindCustomFormatters()); + } + } + + private void HandleValueFormatterDetectionModeChanges() + { + if (detectionMode != Configuration.Current.ValueFormatterDetectionMode) + { + detectionMode = Configuration.Current.ValueFormatterDetectionMode; + formatters = null; + } + } + + private MethodInfo[] FindCustomFormatters() + { + var query = + from type in Services.Reflector.GetAllTypesFromAppDomain(Applicable) + where type != null + from method in type.GetMethods(BindingFlags.Static | BindingFlags.Public) + where method.IsStatic + where method.HasAttribute() + where method.GetParameters().Count() == 1 + select method; + + return query.ToArray(); + } + + private static bool Applicable(Assembly assembly) + { + var configuration = Configuration.Current; + ValueFormatterDetectionMode mode = configuration.ValueFormatterDetectionMode; + + return ((mode == ValueFormatterDetectionMode.Scan) || ( + (mode == ValueFormatterDetectionMode.Specific) && + assembly.FullName.Split(',')[0].Equals(configuration.ValueFormatterAssembly, StringComparison.CurrentCultureIgnoreCase))); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/AttributeBasedFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/AttributeBasedFormatter.cs.meta new file mode 100644 index 0000000..4a656db --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/AttributeBasedFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f5886b0ef24c63a4eaf21da0f4bb5e14 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/ByteValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/ByteValueFormatter.cs new file mode 100644 index 0000000..89ca8e6 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/ByteValueFormatter.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Globalization; + +namespace FluentAssertions.Formatting +{ + public class ByteValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return value is byte; + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + return "0x" + ((byte)value).ToString("X2"); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/ByteValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/ByteValueFormatter.cs.meta new file mode 100644 index 0000000..3a76c08 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/ByteValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7a7e58b05bb2a6a40a1b621c7d097720 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/DateTimeOffsetValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/DateTimeOffsetValueFormatter.cs new file mode 100644 index 0000000..226e260 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/DateTimeOffsetValueFormatter.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using FluentAssertions.Common; + +namespace FluentAssertions.Formatting +{ + public class DateTimeOffsetValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return (value is DateTime) || (value is DateTimeOffset); + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + DateTimeOffset dateTime; + + if (value is DateTime) + { + dateTime = ((DateTime)value).ToDateTimeOffset(); + } + else + { + dateTime = (DateTimeOffset) value; + } + + var fragments = new List(); + + if (HasDate(dateTime)) + { + fragments.Add(dateTime.ToString("yyyy-MM-dd")); + } + + if (HasTime(dateTime)) + { + string format = HasMilliSeconds(dateTime) ? "HH:mm:ss.fff" : "HH:mm:ss"; + fragments.Add(dateTime.ToString(format)); + } + + if (dateTime.Offset > TimeSpan.Zero) + { + fragments.Add("+" + Formatter.ToString(dateTime.Offset)); + } + + if (dateTime.Offset < TimeSpan.Zero) + { + fragments.Add(Formatter.ToString(dateTime.Offset)); + } + + if (!fragments.Any()) + { + if (HasMilliSeconds(dateTime)) + { + fragments.Add("0001-01-01 00:00:00." + dateTime.ToString("fff")); + } + else + { + fragments.Add("0001-01-01 00:00:00.000"); + } + } + + return "<" + string.Join(" ", fragments.ToArray()) + ">"; + } + + private static bool HasTime(DateTimeOffset dateTime) + { + return (dateTime.Hour != 0) || (dateTime.Minute != 0) || (dateTime.Second != 0); + } + + private static bool HasDate(DateTimeOffset dateTime) + { + return (dateTime.Day != 1) || (dateTime.Month != 1) || (dateTime.Year != 1); + } + + private static bool HasMilliSeconds(DateTimeOffset dateTime) + { + return (dateTime.Millisecond > 0); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/DateTimeOffsetValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/DateTimeOffsetValueFormatter.cs.meta new file mode 100644 index 0000000..9140f2e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/DateTimeOffsetValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7304f75776ff5ac4dbdfd62effa116be +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/DecimalValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/DecimalValueFormatter.cs new file mode 100644 index 0000000..fd93308 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/DecimalValueFormatter.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Globalization; + +namespace FluentAssertions.Formatting +{ + public class DecimalValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return value is decimal; + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + return ((decimal)value).ToString(CultureInfo.InvariantCulture) + "M"; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/DecimalValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/DecimalValueFormatter.cs.meta new file mode 100644 index 0000000..0982866 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/DecimalValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6b2aedd3093d24f429bafb86ff152101 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/DefaultValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/DefaultValueFormatter.cs new file mode 100644 index 0000000..3c6ad86 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/DefaultValueFormatter.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using FluentAssertions.Common; +using FluentAssertions.Equivalency; + +namespace FluentAssertions.Formatting +{ + public class DefaultValueFormatter : IValueFormatter + { + #region Private Definitions + + private const int RootLevel = 0; + private const int SpacesPerIndentionLevel = 3; + + #endregion + + /// + /// Determines whether this instance can handle the specified value. + /// + /// The value. + /// + /// true if this instance can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return true; + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, + int nestedPropertyLevel = 0) + { + if (value.GetType() == typeof (object)) + { + return string.Format("System.Object (HashCode={0})", value.GetHashCode()); + } + + string prefix = (useLineBreaks ? Environment.NewLine : ""); + + if (HasDefaultToStringImplementation(value)) + { + if (!processedObjects.Contains(value)) + { + processedObjects.Add(value); + return prefix + GetTypeAndPublicPropertyValues(value, nestedPropertyLevel, processedObjects); + } + else + { + return string.Format("{{Cyclic reference to type {0} detected}}", value.GetType()); + } + } + + return prefix + value; + } + + private static bool HasDefaultToStringImplementation(object value) + { + return ReferenceEquals(value.ToString(), null) || value.ToString().Equals(value.GetType().ToString()); + } + + private static string GetTypeAndPublicPropertyValues(object obj, int nestedPropertyLevel, IList processedObjects) + { + var builder = new StringBuilder(); + + if (nestedPropertyLevel == RootLevel) + { + builder.AppendLine(); + builder.AppendLine(); + } + + var type = obj.GetType(); + builder.AppendLine(type.FullName); + builder.AppendLine(CreateWhitespaceForLevel(nestedPropertyLevel) + "{"); + + IEnumerable properties = type.GetNonPrivateMembers(); + foreach (var propertyInfo in properties.OrderBy(pi => pi.Name)) + { + builder.AppendLine(GetPropertyValueTextFor(obj, propertyInfo, nestedPropertyLevel + 1, processedObjects)); + } + + builder.AppendFormat("{0}}}", CreateWhitespaceForLevel(nestedPropertyLevel)); + + return builder.ToString(); + } + + private static string GetPropertyValueTextFor(object value, SelectedMemberInfo selectedMemberInfo, int nextMemberNestingLevel, + IList processedObjects) + { + object propertyValue; + + try + { + propertyValue = selectedMemberInfo.GetValue(value, null); + } + catch (Exception ex) + { + propertyValue = string.Format("[Member '{0}' threw an exception: '{1}']", selectedMemberInfo.Name, ex.Message); + } + + return string.Format("{0}{1} = {2}", + CreateWhitespaceForLevel(nextMemberNestingLevel), + selectedMemberInfo.Name, + Formatter.ToString(propertyValue, false, processedObjects, nextMemberNestingLevel)); + } + + private static string CreateWhitespaceForLevel(int level) + { + return new string(' ', level*SpacesPerIndentionLevel); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/DefaultValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/DefaultValueFormatter.cs.meta new file mode 100644 index 0000000..55ec8b0 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/DefaultValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b75b0f9ede7fff94fae63afd33c25d48 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/DoubleValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/DoubleValueFormatter.cs new file mode 100644 index 0000000..8e87567 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/DoubleValueFormatter.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; +using System.Globalization; +using System.Text.RegularExpressions; + +namespace FluentAssertions.Formatting +{ + public class DoubleValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return value is double; + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + double doubleValue = (double)value; + + if (double.IsPositiveInfinity(doubleValue)) + { + return typeof(double).Name + "." + nameof(double.PositiveInfinity); + } + + if (double.IsNegativeInfinity(doubleValue)) + { + return typeof(double).Name + "." + nameof(double.NegativeInfinity); + } + + if (double.IsNaN(doubleValue)) + { + return doubleValue.ToString(CultureInfo.InvariantCulture); + } + + string formattedValue = doubleValue.ToString("R", CultureInfo.InvariantCulture); + + return (formattedValue.IndexOf('.') == -1) && (formattedValue.IndexOf('E') == -1) + ? formattedValue + ".0" + : formattedValue; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/DoubleValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/DoubleValueFormatter.cs.meta new file mode 100644 index 0000000..e507f2a --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/DoubleValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9ef9de836199faa4cb6ed09741c90027 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/EnumerableValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/EnumerableValueFormatter.cs new file mode 100644 index 0000000..fe9cca3 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/EnumerableValueFormatter.cs @@ -0,0 +1,58 @@ +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace FluentAssertions.Formatting +{ + public class EnumerableValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return value is IEnumerable; + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + var enumerable = ((IEnumerable)value).Cast().ToArray(); + if (enumerable.Any()) + { + string postfix = ""; + + int maxItems = 32; + if (enumerable.Length > maxItems) + { + postfix = $", ...{enumerable.Length - maxItems} more..."; + enumerable = enumerable.Take(maxItems).ToArray(); + } + + return "{" + string.Join(", ", enumerable.Select(obj => Formatter.ToString(obj, useLineBreaks, processedObjects, nestedPropertyLevel)).ToArray()) + postfix + "}"; + } + else + { + return "{empty}"; + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/EnumerableValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/EnumerableValueFormatter.cs.meta new file mode 100644 index 0000000..b540518 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/EnumerableValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fd16e91439050df479660065ddc3e136 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/ExceptionValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/ExceptionValueFormatter.cs new file mode 100644 index 0000000..277785e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/ExceptionValueFormatter.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace FluentAssertions.Formatting +{ + public class ExceptionValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return value is Exception; + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + var exception = (Exception)value; + + var builder = new StringBuilder(); + builder.AppendFormat("{0} with message \"{1}\"\n", exception.GetType().FullName, exception.Message); + + if (exception.StackTrace != null) + { + foreach (string line in exception.StackTrace.Split(new[] { Environment.NewLine }, StringSplitOptions.None)) + { + builder.AppendLine(" " + line); + } + } + + return builder.ToString(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/ExceptionValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/ExceptionValueFormatter.cs.meta new file mode 100644 index 0000000..85ba1b9 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/ExceptionValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ed27b57539d443a4da80dce2de66b0cc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/ExpressionValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/ExpressionValueFormatter.cs new file mode 100644 index 0000000..1321ea1 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/ExpressionValueFormatter.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using System.Linq.Expressions; + +namespace FluentAssertions.Formatting +{ + public class ExpressionValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return value is Expression; + } + + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, + int nestedPropertyLevel = 0) + { + return value.ToString().Replace(" = ", " == "); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/ExpressionValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/ExpressionValueFormatter.cs.meta new file mode 100644 index 0000000..03d384f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/ExpressionValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f522321d072ea564a86095c1ae701db2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/Formatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/Formatter.cs new file mode 100644 index 0000000..ded1cd0 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/Formatter.cs @@ -0,0 +1,123 @@ +using System.Collections.Generic; +using System.Linq; + +using FluentAssertions.Common; + +namespace FluentAssertions.Formatting +{ + /// + /// Provides services for formatting an object being used in an assertion in a human readable format. + /// + public static class Formatter + { + #region Private Definitions + + private static readonly List customFormatters = new List(); + + private static readonly List defaultFormatters = new List + { + new AttributeBasedFormatter(), + new PropertyInfoFormatter(), + new NullValueFormatter(), + new GuidValueFormatter(), + new DateTimeOffsetValueFormatter(), + new TimeSpanValueFormatter(), + new Int32ValueFormatter(), + new Int64ValueFormatter(), + new DoubleValueFormatter(), + new SingleValueFormatter(), + new DecimalValueFormatter(), + new ByteValueFormatter(), + new UInt32ValueFormatter(), + new UInt64ValueFormatter(), + new Int16ValueFormatter(), + new UInt16ValueFormatter(), + new SByteValueFormatter(), + new StringValueFormatter(), + new ExpressionValueFormatter(), + new ExceptionValueFormatter(), + new EnumerableValueFormatter(), + new DefaultValueFormatter(), + }; + + #endregion + + /// + /// A list of objects responsible for formatting the objects represented by placeholders. + /// + public static IEnumerable Formatters + { + get { return customFormatters.Concat(defaultFormatters); } + } + + /// + /// Returns a human-readable representation of a particular object. + /// + /// The value for which to create a . + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// Indicates whether the formatter should use line breaks when the specific supports it. + /// + /// + /// A that represents this instance. + /// + public static string ToString(object value, bool useLineBreaks = false, IList processedObjects = null, int nestedPropertyLevel = 0) + { + Services.Initialize(); + + if (processedObjects == null) + { + processedObjects = new List(); + } + + const int MaxDepth = 15; + if (nestedPropertyLevel > MaxDepth) + { + return "{Maximum recursion depth was reached...}"; + } + + IValueFormatter firstFormatterThatCanHandleValue = Formatters.First(f => f.CanHandle(value)); + return firstFormatterThatCanHandleValue.ToString(value, useLineBreaks, processedObjects, nestedPropertyLevel); + } + + /// + /// Removes a custom formatter that was previously added though . + /// + public static void RemoveFormatter(IValueFormatter formatter) + { + if (customFormatters.Contains(formatter)) + { + customFormatters.Remove(formatter); + } + } + + /// + /// Ensures a custom formatter is included in the chain, just before the default formatter is executed. + /// + public static void AddFormatter(IValueFormatter formatter) + { + if (!customFormatters.Contains(formatter)) + { + customFormatters.Insert(0, formatter); + } + } + + /// + /// Allows a platform-specific assembly to add formatters without affecting the ones added by callers of . + /// + /// + internal static void AddPlatformFormatters(IValueFormatter[] formatters) + { + foreach (var formatter in formatters) + { + if (!defaultFormatters.Contains(formatter)) + { + defaultFormatters.Insert(0, formatter); + } + } + } + } +} diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/Formatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/Formatter.cs.meta new file mode 100644 index 0000000..3a9c759 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/Formatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4f3def366d40c194e90b532daada92ce +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/GuidValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/GuidValueFormatter.cs new file mode 100644 index 0000000..ecadac5 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/GuidValueFormatter.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; + +namespace FluentAssertions.Formatting +{ + public class GuidValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return value is Guid; + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + return "{" + value + "}"; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/GuidValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/GuidValueFormatter.cs.meta new file mode 100644 index 0000000..c7d566f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/GuidValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1c93b8a89ee1c1243a4a631c7d86e5be +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/IValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/IValueFormatter.cs new file mode 100644 index 0000000..751462b --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/IValueFormatter.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; + +namespace FluentAssertions.Formatting +{ + public interface IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + bool CanHandle(object value); + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0); + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/IValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/IValueFormatter.cs.meta new file mode 100644 index 0000000..07f5e47 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/IValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0eb4295eda62f604292c6fa2276182f0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/Int16ValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/Int16ValueFormatter.cs new file mode 100644 index 0000000..0822bcd --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/Int16ValueFormatter.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Globalization; + +namespace FluentAssertions.Formatting +{ + public class Int16ValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return value is short; + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + return ((short)value).ToString(CultureInfo.InvariantCulture) + "s"; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/Int16ValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/Int16ValueFormatter.cs.meta new file mode 100644 index 0000000..16e6e87 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/Int16ValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 24a9d3d30225881499807a50ef3659ac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/Int32ValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/Int32ValueFormatter.cs new file mode 100644 index 0000000..4be93b2 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/Int32ValueFormatter.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Globalization; + +namespace FluentAssertions.Formatting +{ + public class Int32ValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return value is int; + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + return ((int)value).ToString(CultureInfo.InvariantCulture); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/Int32ValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/Int32ValueFormatter.cs.meta new file mode 100644 index 0000000..4bf7ea6 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/Int32ValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7620394ccfe1dbf4fb70d0cbea532bb3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/Int64ValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/Int64ValueFormatter.cs new file mode 100644 index 0000000..a81d268 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/Int64ValueFormatter.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Globalization; + +namespace FluentAssertions.Formatting +{ + public class Int64ValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return value is long; + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + return ((long)value).ToString(CultureInfo.InvariantCulture) + "L"; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/Int64ValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/Int64ValueFormatter.cs.meta new file mode 100644 index 0000000..c1c91a1 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/Int64ValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 450f43c52bf6f344d8bf2dd93813e23a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/NullValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/NullValueFormatter.cs new file mode 100644 index 0000000..d7f6b97 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/NullValueFormatter.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; + +namespace FluentAssertions.Formatting +{ + public class NullValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return ReferenceEquals(value, null); + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + return ""; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/NullValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/NullValueFormatter.cs.meta new file mode 100644 index 0000000..89f46ba --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/NullValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3691dd2c86b4daa40ad941bcee9b4fe4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/PropertyInfoFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/PropertyInfoFormatter.cs new file mode 100644 index 0000000..29accff --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/PropertyInfoFormatter.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Reflection; + +namespace FluentAssertions.Formatting +{ + public class PropertyInfoFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return value is PropertyInfo; + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + return ((PropertyInfo)value).Name; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/PropertyInfoFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/PropertyInfoFormatter.cs.meta new file mode 100644 index 0000000..dd4dc33 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/PropertyInfoFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fbbb8ed5fe0501e45a2135e4bb23a0ec +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/SByteValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/SByteValueFormatter.cs new file mode 100644 index 0000000..433eaa4 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/SByteValueFormatter.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Globalization; + +namespace FluentAssertions.Formatting +{ + public class SByteValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return value is sbyte; + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + return ((sbyte)value).ToString(CultureInfo.InvariantCulture) + "y"; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/SByteValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/SByteValueFormatter.cs.meta new file mode 100644 index 0000000..b1feb71 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/SByteValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 41a7969ee1d36fa49bff5f075c8bfb02 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/SingleValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/SingleValueFormatter.cs new file mode 100644 index 0000000..86bf5fb --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/SingleValueFormatter.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; +using System.Globalization; + +namespace FluentAssertions.Formatting +{ + public class SingleValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return value is float; + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + float singleValue = (float)value; + + if (float.IsPositiveInfinity(singleValue)) + { + return typeof(float).Name + "." + nameof(float.PositiveInfinity); + } + + if (float.IsNegativeInfinity(singleValue)) + { + return typeof(float).Name + "." + nameof(float.NegativeInfinity); + } + + if (float.IsNaN(singleValue)) + { + return singleValue.ToString(CultureInfo.InvariantCulture); + } + + return singleValue.ToString("R", CultureInfo.InvariantCulture) + "F"; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/SingleValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/SingleValueFormatter.cs.meta new file mode 100644 index 0000000..2abe8d4 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/SingleValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0cd8821a85da76f4494f7478af5b8ded +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/StringValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/StringValueFormatter.cs new file mode 100644 index 0000000..ef6ba50 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/StringValueFormatter.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using FluentAssertions.Common; + +namespace FluentAssertions.Formatting +{ + public class StringValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return value is string; + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + return (useLineBreaks ? Environment.NewLine : "") + "\"" + value.ToString().Escape() + "\""; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/StringValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/StringValueFormatter.cs.meta new file mode 100644 index 0000000..196a910 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/StringValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9af805497420fba4db22bb766e93383c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/TimeSpanValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/TimeSpanValueFormatter.cs new file mode 100644 index 0000000..b42af2c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/TimeSpanValueFormatter.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace FluentAssertions.Formatting +{ + public class TimeSpanValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return value is TimeSpan; + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + var timeSpan = (TimeSpan) value; + + if (timeSpan == TimeSpan.MinValue) + { + return "min time span"; + } + + if (timeSpan == TimeSpan.MaxValue) + { + return "max time span"; + } + + IEnumerable fragments = GetNonZeroFragments(timeSpan); + + if (!fragments.Any()) + { + return "default"; + } + + string sign = (timeSpan.TotalMilliseconds >= 0) ? "" : "-"; + + if (fragments.Count() == 1) + { + return sign + fragments.Single(); + } + else + { + return sign + JoinUsingWritingStyle(fragments); + } + } + + private static IEnumerable GetNonZeroFragments(TimeSpan timeSpan) + { + TimeSpan absoluteTimespan = timeSpan.Duration(); + + var fragments = new List(); + + AddDaysIfNotZero(absoluteTimespan, fragments); + AddHoursIfNotZero(absoluteTimespan, fragments); + AddMinutesIfNotZero(absoluteTimespan, fragments); + AddSecondsIfNotZero(absoluteTimespan, fragments); + AddMicrosecondsIfNotZero(absoluteTimespan, fragments); + + return fragments; + } + + private static void AddMicrosecondsIfNotZero(TimeSpan timeSpan, List fragments) + { + if (timeSpan.Ticks > 0 && timeSpan.Ticks < TimeSpan.TicksPerMillisecond) + { + var microSeconds = timeSpan.Ticks / (double)TimeSpan.TicksPerMillisecond * 1000; + fragments.Add(microSeconds.ToString("0.0") + "us"); + } + } + + private static void AddSecondsIfNotZero(TimeSpan timeSpan, List fragments) + { + if ((timeSpan.Seconds > 0) || (timeSpan.Milliseconds > 0)) + { + string result = timeSpan.Seconds.ToString(); + + if (timeSpan.Milliseconds > 0) + { + result += "." + timeSpan.Milliseconds.ToString("000"); + } + + fragments.Add(result + "s"); + } + } + + private static void AddMinutesIfNotZero(TimeSpan timeSpan, List fragments) + { + if (timeSpan.Minutes > 0) + { + fragments.Add(timeSpan.Minutes + "m"); + } + } + + private static void AddHoursIfNotZero(TimeSpan timeSpan, List fragments) + { + if (timeSpan.Hours > 0) + { + fragments.Add(timeSpan.Hours + "h"); + } + } + + private static void AddDaysIfNotZero(TimeSpan timeSpan, List fragments) + { + if (timeSpan.Days > 0) + { + fragments.Add(timeSpan.Days + "d"); + } + } + + private static string JoinUsingWritingStyle(IEnumerable fragments) + { + return string.Join(", ", AllButLastFragment(fragments)) + " and " + fragments.Last(); + } + + private static string[] AllButLastFragment(IEnumerable fragments) + { + return fragments.Take(fragments.Count() - 1).ToArray(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/TimeSpanValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/TimeSpanValueFormatter.cs.meta new file mode 100644 index 0000000..134c538 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/TimeSpanValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fe25913c031e5e444924c3fc28dfe67a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/UInt16ValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/UInt16ValueFormatter.cs new file mode 100644 index 0000000..e05b484 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/UInt16ValueFormatter.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Globalization; + +namespace FluentAssertions.Formatting +{ + public class UInt16ValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return value is ushort; + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + return ((ushort)value).ToString(CultureInfo.InvariantCulture) + "us"; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/UInt16ValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/UInt16ValueFormatter.cs.meta new file mode 100644 index 0000000..7677093 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/UInt16ValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 48832247c843f584a943a75ebd7b8a7d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/UInt32ValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/UInt32ValueFormatter.cs new file mode 100644 index 0000000..5b487d7 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/UInt32ValueFormatter.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Globalization; + +namespace FluentAssertions.Formatting +{ + public class UInt32ValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return value is uint; + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + return ((uint)value).ToString(CultureInfo.InvariantCulture) + "u"; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/UInt32ValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/UInt32ValueFormatter.cs.meta new file mode 100644 index 0000000..84c1928 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/UInt32ValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1e4727ead0b5f76498912619a3fd526a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/UInt64ValueFormatter.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/UInt64ValueFormatter.cs new file mode 100644 index 0000000..95f269e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/UInt64ValueFormatter.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Globalization; + +namespace FluentAssertions.Formatting +{ + public class UInt64ValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return value is ulong; + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + return ((ulong)value).ToString(CultureInfo.InvariantCulture) + "UL"; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/UInt64ValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/UInt64ValueFormatter.cs.meta new file mode 100644 index 0000000..b319a33 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/UInt64ValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 200a63fe75ea5cb47868d14541acf29f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/ValueFormatterAttribute.cs b/Assets/Plugins/FluentAssertions/Core/Formatting/ValueFormatterAttribute.cs new file mode 100644 index 0000000..d78b54f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/ValueFormatterAttribute.cs @@ -0,0 +1,13 @@ +using System; + +namespace FluentAssertions.Formatting +{ + /// + /// Marks a static method as a kind of for a particular type. + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] + public class ValueFormatterAttribute : Attribute + { + + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Formatting/ValueFormatterAttribute.cs.meta b/Assets/Plugins/FluentAssertions/Core/Formatting/ValueFormatterAttribute.cs.meta new file mode 100644 index 0000000..3531cc9 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Formatting/ValueFormatterAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6476cb5ca807120428a7edf057de3a4a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/InternalAssertionExtensions.cs b/Assets/Plugins/FluentAssertions/Core/InternalAssertionExtensions.cs new file mode 100644 index 0000000..d3eb222 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/InternalAssertionExtensions.cs @@ -0,0 +1,478 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; + +using FluentAssertions.Collections; +using FluentAssertions.Common; +using FluentAssertions.Equivalency; +using FluentAssertions.Numeric; +using FluentAssertions.Primitives; +using FluentAssertions.Types; + +namespace FluentAssertions +{ +#if false + /// + /// Contains extension methods for custom assertions in unit tests. + /// + [DebuggerNonUserCode] + internal static class InternalAssertionExtensions + { + /// + /// Invokes the specified action on an subject so that you can chain it with any of the ShouldThrow or ShouldNotThrow + /// overloads. + /// + public static Action Invoking(this T subject, Action action) + { + return () => action(subject); + } + + /// + /// Forces enumerating a collection. Should be used to assert that a method that uses the + /// yield keyword throws a particular exception. + /// + public static Action Enumerating(this Func enumerable) + { + return () => ForceEnumeration(enumerable); + } + + /// + /// Forces enumerating a collection. Should be used to assert that a method that uses the + /// yield keyword throws a particular exception. + /// + public static Action Enumerating(this Func> enumerable) + { + return () => ForceEnumeration(() => (IEnumerable)enumerable()); + } + + private static void ForceEnumeration(Func enumerable) + { + foreach (object item in enumerable()) + { + // Do nothing + } + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + public static ObjectAssertions Should(this object actualValue) + { + return new ObjectAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + public static BooleanAssertions Should(this bool actualValue) + { + return new BooleanAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + public static NullableBooleanAssertions Should(this bool? actualValue) + { + return new NullableBooleanAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + public static GuidAssertions Should(this Guid actualValue) + { + return new GuidAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + public static NullableGuidAssertions Should(this Guid? actualValue) + { + return new NullableGuidAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + public static NonGenericCollectionAssertions Should(this IEnumerable actualValue) + { + return new NonGenericCollectionAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + public static GenericCollectionAssertions Should(this IEnumerable actualValue) + { + return new GenericCollectionAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + public static StringCollectionAssertions Should(this IEnumerable @this) + { + return new StringCollectionAssertions(@this); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + public static GenericDictionaryAssertions Should(this IDictionary actualValue) + { + return new GenericDictionaryAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + public static DateTimeOffsetAssertions Should(this DateTime actualValue) + { + return new DateTimeOffsetAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + public static NullableDateTimeOffsetAssertions Should(this DateTime? actualValue) + { + return new NullableDateTimeOffsetAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + public static ComparableTypeAssertions Should(this IComparable comparableValue) + { + return new ComparableTypeAssertions(comparableValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + public static NumericAssertions Should(this int actualValue) + { + return new NumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + public static NullableNumericAssertions Should(this int? actualValue) + { + return new NullableNumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + public static NumericAssertions Should(this decimal actualValue) + { + return new NumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + public static NullableNumericAssertions Should(this decimal? actualValue) + { + return new NullableNumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + public static NumericAssertions Should(this byte actualValue) + { + return new NumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + public static NullableNumericAssertions Should(this byte? actualValue) + { + return new NullableNumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + public static NumericAssertions Should(this short actualValue) + { + return new NumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + public static NullableNumericAssertions Should(this short? actualValue) + { + return new NullableNumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + public static NumericAssertions Should(this long actualValue) + { + return new NumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + public static NullableNumericAssertions Should(this long? actualValue) + { + return new NullableNumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + public static NumericAssertions Should(this float actualValue) + { + return new NumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + public static NullableNumericAssertions Should(this float? actualValue) + { + return new NullableNumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + public static NumericAssertions Should(this double actualValue) + { + return new NumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + public static NullableNumericAssertions Should(this double? actualValue) + { + return new NullableNumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + public static StringAssertions Should(this string actualValue) + { + return new StringAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + public static SimpleTimeSpanAssertions Should(this TimeSpan actualValue) + { + return new SimpleTimeSpanAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + public static NullableSimpleTimeSpanAssertions Should(this TimeSpan? actualValue) + { + return new NullableSimpleTimeSpanAssertions(actualValue); + } + + /// + /// Returns a object that can be used to assert the + /// current . + /// + public static TypeAssertions Should(this Type subject) + { + return new TypeAssertions(subject); + } + + /// + /// Returns a object that can be used to assert the + /// current . + /// + public static TypeSelectorAssertions Should(this TypeSelector typeSelector) + { + return new TypeSelectorAssertions(typeSelector.ToArray()); + } + + /// + /// Returns a object that can be used to assert the current . + /// + /// + public static MethodInfoAssertions Should(this MethodInfo methodInfo) + { + return new MethodInfoAssertions(methodInfo); + } + + /// + /// Returns a object that can be used to assert the methods returned by the + /// current . + /// + /// + public static MethodInfoSelectorAssertions Should(this MethodInfoSelector methodSelector) + { + return new MethodInfoSelectorAssertions(methodSelector.ToArray()); + } + + /// + /// Returns a object that can be used to assert the + /// current . + /// + /// + public static PropertyInfoAssertions Should(this PropertyInfo propertyInfo) + { + return new PropertyInfoAssertions(propertyInfo); + } + + /// + /// Returns a object that can be used to assert the properties returned by the + /// current . + /// + /// + public static PropertyInfoSelectorAssertions Should(this PropertyInfoSelector propertyInfoSelector) + { + return new PropertyInfoSelectorAssertions(propertyInfoSelector.ToArray()); + } + + /// + /// Asserts that an object is equivalent to another object. + /// + /// + /// Objects are equivalent when both object graphs have equally named properties with the same value, + /// irrespective of the type of those objects. Two properties are also equal if one type can be converted to another and the result is equal. + /// The type of a collection property is ignored as long as the collection implements and all + /// items in the collection are structurally equal. + /// Notice that actual behavior is determined by the instance of the + /// class. + /// + /// + /// An optional formatted phrase as is supported by explaining why the + /// assertion is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public static void ShouldBeEquivalentTo(this T subject, object expectation, string because = "", + params object[] becauseArgs) + { + ShouldBeEquivalentTo(subject, expectation, config => config, because, becauseArgs); + } + + /// + /// Asserts that an object is equivalent to another object. + /// + /// + /// Objects are equivalent when both object graphs have equally named properties with the same value, + /// irrespective of the type of those objects. Two properties are also equal if one type can be converted to another and the result is equal. + /// The type of a collection property is ignored as long as the collection implements and all + /// items in the collection are structurally equal. + /// + /// + /// A reference to the configuration object that can be used + /// to influence the way the object graphs are compared. You can also provide an alternative instance of the + /// class. + /// + /// + /// An optional formatted phrase as is supported by explaining why the + /// assertion is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public static void ShouldBeEquivalentTo(this T subject, object expectation, + Func, EquivalencyAssertionOptions> config, string because = "", + params object[] becauseArgs) + { + IEquivalencyAssertionOptions options = config(AssertionOptions.CloneDefaults()); + + var context = new EquivalencyValidationContext + { + Subject = subject, + Expectation = expectation, + CompileTimeType = typeof(T), + Because = because, + BecauseArgs = becauseArgs, + Tracer = options.TraceWriter + }; + + new EquivalencyValidator(options).AssertEquality(context); + } + + public static void ShouldAllBeEquivalentTo(this IEnumerable subject, IEnumerable expectation, + string because = "", params object[] becauseArgs) + { + ShouldAllBeEquivalentTo(subject, expectation, config => config, because, becauseArgs); + } + + public static void ShouldAllBeEquivalentTo(this IEnumerable subject, IEnumerable expectation, + Func, EquivalencyAssertionOptions> config, string because = "", + params object[] becauseArgs) + { + IEquivalencyAssertionOptions options = config(AssertionOptions.CloneDefaults()); + + var context = new EquivalencyValidationContext + { + Subject = subject, + Expectation = expectation, + CompileTimeType = typeof(T), + Because = because, + BecauseArgs = becauseArgs, + Tracer = options.TraceWriter + }; + + new EquivalencyValidator(options).AssertEquality(context); + } + + /// + /// Safely casts the specified object to the type specified through . + /// + /// + /// Has been introduced to allow casting objects without breaking the fluent API. + /// + /// + public static TTo As(this object subject) + { + return subject is TTo ? (TTo)subject : default(TTo); + } + } +#endif +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/InternalAssertionExtensions.cs.meta b/Assets/Plugins/FluentAssertions/Core/InternalAssertionExtensions.cs.meta new file mode 100644 index 0000000..8a5546f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/InternalAssertionExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b95715a484edd404e82a6d062cdfef38 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Numeric.meta b/Assets/Plugins/FluentAssertions/Core/Numeric.meta new file mode 100644 index 0000000..4e3e1e9 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Numeric.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0872c304349aa0a489f3087c737d0cad +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Numeric/ComparableTypeAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Numeric/ComparableTypeAssertions.cs new file mode 100644 index 0000000..443d027 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Numeric/ComparableTypeAssertions.cs @@ -0,0 +1,198 @@ +using System; +using System.Diagnostics; +using FluentAssertions.Execution; +using FluentAssertions.Primitives; + +namespace FluentAssertions.Numeric +{ + /// + /// Contains a number of methods to assert that an is in the expected state. + /// + [DebuggerNonUserCode] + public class ComparableTypeAssertions : ReferenceTypeAssertions, ComparableTypeAssertions> + { + private const int Equal = 0; + + public ComparableTypeAssertions(IComparable value) + { + Subject = value; + } + + /// + /// Asserts that the subject is considered equal to another object according to the implementation of . + /// + /// + /// The object to pass to the subject's method. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> Be(T expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(ReferenceEquals(Subject, expected) || (Subject.CompareTo(expected) == Equal)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {0}{reason}, but found {1}.", expected, Subject); + + return new AndConstraint>(this); + } + + /// + /// Asserts that the subject is not equal to another object according to its implementation of . + /// + /// + /// The object to pass to the subject's method. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> NotBe(T expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.CompareTo(expected) != Equal) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect object to be equal to {0}{reason}.", expected); + + return new AndConstraint>(this); + } + + /// + /// Asserts that the subject is less than another object according to its implementation of . + /// + /// + /// The object to pass to the subject's method. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeLessThan(T expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.CompareTo(expected) < Equal) + .BecauseOf(because, becauseArgs) + .FailWith("Expected object {0} to be less than {1}{reason}.", Subject, expected); + + return new AndConstraint>(this); + } + + /// + /// Asserts that the subject is less than or equal to another object according to its implementation of . + /// + /// + /// The object to pass to the subject's method. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeLessOrEqualTo(T expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.CompareTo(expected) <= Equal) + .BecauseOf(because, becauseArgs) + .FailWith("Expected object {0} to be less or equal to {1}{reason}.", Subject, expected); + + return new AndConstraint>(this); + } + + /// + /// Asserts that the subject is greater than another object according to its implementation of . + /// + /// + /// The object to pass to the subject's method. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeGreaterThan(T expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.CompareTo(expected) > Equal) + .BecauseOf(because, becauseArgs) + .FailWith("Expected object {0} to be greater than {1}{reason}.", Subject, expected); + + return new AndConstraint>(this); + } + + /// + /// Asserts that the subject is greater than or equal to another object according to its implementation of . + /// + /// + /// The object to pass to the subject's method. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeGreaterOrEqualTo(T expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.CompareTo(expected) >= Equal) + .BecauseOf(because, becauseArgs) + .FailWith("Expected object {0} to be greater or equal to {1}{reason}.", Subject, expected); + + return new AndConstraint>(this); + } + + /// + /// Asserts that a value is within a range. + /// + /// + /// Where the range is continuous or incremental depends on the actual type of the value. + /// + /// + /// The minimum valid value of the range. + /// + /// + /// The maximum valid value of the range. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeInRange(T minimumValue, T maximumValue, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition((Subject.CompareTo(minimumValue) >= Equal) && (Subject.CompareTo(maximumValue) <= Equal)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected object to be between {0} and {1}{reason}, but found {2}.", + minimumValue, maximumValue, Subject); + + return new AndConstraint>(this); + } + + /// + /// Returns the type of the subject the assertion applies on. + /// + protected override string Context + { + get { return "object"; } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Numeric/ComparableTypeAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Numeric/ComparableTypeAssertions.cs.meta new file mode 100644 index 0000000..1ff2c29 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Numeric/ComparableTypeAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 62b1422ffd0d3424fbe1f02ef4058708 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Numeric/NullableNumericAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Numeric/NullableNumericAssertions.cs new file mode 100644 index 0000000..d180be6 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Numeric/NullableNumericAssertions.cs @@ -0,0 +1,83 @@ +using System.Diagnostics; +using FluentAssertions.Execution; + +namespace FluentAssertions.Numeric +{ + [DebuggerNonUserCode] + public class NullableNumericAssertions : NumericAssertions where T : struct + { + public NullableNumericAssertions(T? value) : base(value) + { + } + + /// + /// Asserts that a nullable numeric value is not null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> HaveValue(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!ReferenceEquals(Subject, null)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a value{reason}."); + + return new AndConstraint>(this); + } + + /// + /// Asserts that a nullable numeric value is not null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> NotBeNull(string because = "", params object[] becauseArgs) + { + return HaveValue(because, becauseArgs); + } + + /// + /// Asserts that a nullable numeric value is null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> NotHaveValue(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(ReferenceEquals(Subject, null)) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect a value{reason}, but found {0}.", Subject); + + return new AndConstraint>(this); + } + + /// + /// Asserts that a nullable numeric value is null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeNull(string because = "", params object[] becauseArgs) + { + return NotHaveValue(because, becauseArgs); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Numeric/NullableNumericAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Numeric/NullableNumericAssertions.cs.meta new file mode 100644 index 0000000..abbee87 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Numeric/NullableNumericAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b30ce027a6a242145b23a57ed7c9ebe6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Numeric/NumericAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Numeric/NumericAssertions.cs new file mode 100644 index 0000000..991a34c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Numeric/NumericAssertions.cs @@ -0,0 +1,356 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +using FluentAssertions.Execution; + + +namespace FluentAssertions.Numeric +{ + /// + /// Contains a number of methods to assert that an is in the expected state. + /// + [DebuggerNonUserCode] + public class NumericAssertions where T : struct + { + public NumericAssertions(object value) + { + if (!ReferenceEquals(value, null)) + { + Subject = value as IComparable; + if (Subject == null) + { + throw new InvalidOperationException("This class only supports types implementing IComparable."); + } + } + } + + public IComparable Subject { get; private set; } + + /// + /// Asserts that the integral number value is exactly the same as the value. + /// + /// The expected value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> Be(T expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(ReferenceEquals(Subject, expected) || ((!ReferenceEquals(Subject, null) && Subject.CompareTo(expected) == 0))) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:value} to be {0}{reason}, but found {1}.", expected, Subject); + + return new AndConstraint>(this); + } + + /// + /// Asserts that the integral number value is exactly the same as the value. + /// + /// The expected value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> Be(T? expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(ReferenceEquals(Subject, expected) || ((!ReferenceEquals(Subject, null) && Subject.CompareTo(expected) == 0))) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:value} to be {0}{reason}, but found {1}.", expected, Subject); + + return new AndConstraint>(this); + } + + /// + /// Asserts that the integral number value is not the same as the value. + /// + /// The unexpected value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> NotBe(T unexpected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.CompareTo(unexpected) != 0) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect {0}{reason}.", unexpected); + + return new AndConstraint>(this); + } + + /// + /// Asserts that the integral number value is not the same as the value. + /// + /// The unexpected value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> NotBe(T? unexpected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.CompareTo(unexpected) != 0) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect {0}{reason}.", unexpected); + + return new AndConstraint>(this); + } + + /// + /// Asserts that the numeric value is greater than zero. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BePositive(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.CompareTo(default(T)) > 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected positive value{reason}, but found {0}", Subject); + + return new AndConstraint>(this); + } + + /// + /// Asserts that the numeric value is less than zero. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeNegative(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.CompareTo(default(T)) < 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected negative value{reason}, but found {0}", Subject); + + return new AndConstraint>(this); + } + + /// + /// Asserts that the numeric value is less than the specified value. + /// + /// The value to compare the current numeric value with. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeLessThan(T expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.CompareTo(expected) < 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a value less than {0}{reason}, but found {1}.", expected, Subject); + + return new AndConstraint>(this); + } + + /// + /// Asserts that the numeric value is less than or equal to the specified value. + /// + /// The value to compare the current numeric value with. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeLessOrEqualTo(T expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.CompareTo(expected) <= 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a value less or equal to {0}{reason}, but found {1}.", expected, Subject); + + return new AndConstraint>(this); + } + + /// + /// Asserts that the numeric value is greater than the specified value. + /// + /// The value to compare the current numeric value with. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeGreaterThan(T expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.CompareTo(expected) > 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a value greater than {0}{reason}, but found {1}.", expected, Subject); + + return new AndConstraint>(this); + } + + /// + /// Asserts that the numeric value is greater than or equal to the specified value. + /// + /// The value to compare the current numeric value with. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeGreaterOrEqualTo(T expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.CompareTo(expected) >= 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a value greater or equal to {0}{reason}, but found {1}.", expected, Subject); + + return new AndConstraint>(this); + } + + /// + /// Asserts that a value is within a range. + /// + /// + /// Where the range is continuous or incremental depends on the actual type of the value. + /// + /// + /// The minimum valid value of the range. + /// + /// + /// The maximum valid value of the range. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeInRange(T minimumValue, T maximumValue, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition((Subject.CompareTo(minimumValue) >= 0) && (Subject.CompareTo(maximumValue) <= 0)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected value to be between {0} and {1}{reason}, but found {2}.", + minimumValue, maximumValue, Subject); + + return new AndConstraint>(this); + } + + /// + /// Asserts that a value is one of the specified . + /// + /// + /// The values that are valid. + /// + public AndConstraint> BeOneOf(params T[] validValues) + { + return BeOneOf(validValues, string.Empty); + } + + /// + /// Asserts that a value is one of the specified . + /// + /// + /// The values that are valid. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeOneOf(IEnumerable validValues, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(validValues.Contains((T)Subject)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected value to be one of {0}{reason}, but found {1}.", validValues, Subject); + + return new AndConstraint>(this); + } + + /// + /// Asserts that the object is of the specified type . + /// + /// + /// The type that the subject is supposed to be of. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> BeOfType(Type expectedType, string because = "", params object[] becauseArgs) + { + Type subjectType = Subject.GetType(); + if (expectedType.IsGenericTypeDefinition() && subjectType.IsGenericType()) + { + subjectType.GetGenericTypeDefinition().Should().Be(expectedType, because, becauseArgs); + } + else + { + subjectType.Should().Be(expectedType, because, becauseArgs); + } + + return new AndConstraint>(this); + } + + /// + /// Asserts that the object is not of the specified type . + /// + /// + /// The type that the subject is not supposed to be of. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> NotBeOfType(Type expectedType, string because = "", params object[] becauseArgs) + { + Subject.GetType().Should().NotBe(expectedType, because, becauseArgs); + + return new AndConstraint>(this); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Numeric/NumericAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Numeric/NumericAssertions.cs.meta new file mode 100644 index 0000000..83dbf1d --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Numeric/NumericAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6f09431c29a312b43a4858a62c211f30 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/NumericAssertionsExtensions.cs b/Assets/Plugins/FluentAssertions/Core/NumericAssertionsExtensions.cs new file mode 100644 index 0000000..e74854b --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/NumericAssertionsExtensions.cs @@ -0,0 +1,204 @@ +using System; +using FluentAssertions.Execution; +using FluentAssertions.Numeric; + +namespace FluentAssertions +{ + /// + /// Contains a number of extension methods for floating point . + /// + public static class NumericAssertionsExtensions + { + /// + /// Asserts a floating point value approximates another value as close as possible. + /// + /// The object that is being extended. + /// + /// The expected value to compare the actual value with. + /// + /// + /// The maximum amount of which the two values may differ. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public static AndConstraint> BeApproximately(this NullableNumericAssertions parent, + float expectedValue, float precision, string because = "", + params object [] becauseArgs) + { + Execute.Assertion + .ForCondition(parent.Subject != null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected value to approximate {0} +/- {1}{reason}, but it was .", expectedValue, precision); + + var nonNullableAssertions = new NumericAssertions((float) parent.Subject); + nonNullableAssertions.BeApproximately(expectedValue, precision, because, becauseArgs); + + return new AndConstraint>(parent); + } + + /// + /// Asserts a floating point value approximates another value as close as possible. + /// + /// The object that is being extended. + /// + /// The expected value to compare the actual value with. + /// + /// + /// The maximum amount of which the two values may differ. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public static AndConstraint> BeApproximately(this NumericAssertions parent, + float expectedValue, float precision, string because = "", + params object [] becauseArgs) + { + float actualDifference = Math.Abs(expectedValue - (float)parent.Subject); + + Execute.Assertion + .ForCondition(actualDifference <= precision) + .BecauseOf(because, becauseArgs) + .FailWith("Expected value {0} to approximate {1} +/- {2}{reason}, but it differed by {3}.", + parent.Subject, expectedValue, precision, actualDifference); + + return new AndConstraint>(parent); + } + + /// + /// Asserts a double value approximates another value as close as possible. + /// + /// The object that is being extended. + /// + /// The expected value to compare the actual value with. + /// + /// + /// The maximum amount of which the two values may differ. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public static AndConstraint> BeApproximately(this NullableNumericAssertions parent, + double expectedValue, double precision, string because = "", + params object [] becauseArgs) + { + Execute.Assertion + .ForCondition(parent.Subject != null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected value to approximate {0} +/- {1}{reason}, but it was .", expectedValue, precision); + + var nonNullableAssertions = new NumericAssertions((double) parent.Subject); + BeApproximately(nonNullableAssertions, expectedValue, precision, because, becauseArgs); + + return new AndConstraint>(parent); + } + + /// + /// Asserts a double value approximates another value as close as possible. + /// + /// The object that is being extended. + /// + /// The expected value to compare the actual value with. + /// + /// + /// The maximum amount of which the two values may differ. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public static AndConstraint> BeApproximately(this NumericAssertions parent, + double expectedValue, double precision, string because = "", + params object [] becauseArgs) + { + double actualDifference = Math.Abs(expectedValue - (double) parent.Subject); + + Execute.Assertion + .ForCondition(actualDifference <= precision) + .BecauseOf(because, becauseArgs) + .FailWith("Expected value {0} to approximate {1} +/- {2}{reason}, but it differed by {3}.", + parent.Subject, expectedValue, precision, actualDifference); + + return new AndConstraint>(parent); + } + + /// + /// Asserts a decimal value approximates another value as close as possible. + /// + /// The object that is being extended. + /// + /// The expected value to compare the actual value with. + /// + /// + /// The maximum amount of which the two values may differ. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public static AndConstraint> BeApproximately(this NullableNumericAssertions parent, + decimal expectedValue, decimal precision, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(parent.Subject != null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected value to approximate {0} +/- {1}{reason}, but it was .", expectedValue, precision); + + var nonNullableAssertions = new NumericAssertions((decimal)parent.Subject); + BeApproximately(nonNullableAssertions, expectedValue, precision, because, becauseArgs); + + return new AndConstraint>(parent); + } + + /// + /// Asserts a decimal value approximates another value as close as possible. + /// + /// The object that is being extended. + /// + /// The expected value to compare the actual value with. + /// + /// + /// The maximum amount of which the two values may differ. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public static AndConstraint> BeApproximately(this NumericAssertions parent, + decimal expectedValue, decimal precision, string because = "", + params object[] becauseArgs) + { + decimal actualDifference = Math.Abs(expectedValue - (decimal)parent.Subject); + + Execute.Assertion + .ForCondition(actualDifference <= precision) + .BecauseOf(because, becauseArgs) + .FailWith("Expected value {0} to approximate {1} +/- {2}{reason}, but it differed by {3}.", + parent.Subject, expectedValue, precision, actualDifference); + + return new AndConstraint>(parent); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/NumericAssertionsExtensions.cs.meta b/Assets/Plugins/FluentAssertions/Core/NumericAssertionsExtensions.cs.meta new file mode 100644 index 0000000..c5defc9 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/NumericAssertionsExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 065272ad542e9574a88c6e3ff44ab3f2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives.meta b/Assets/Plugins/FluentAssertions/Core/Primitives.meta new file mode 100644 index 0000000..af91abf --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9f21a6b1f84e9664b8645751bc6ba406 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/BooleanAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/BooleanAssertions.cs new file mode 100644 index 0000000..dbe4ecb --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/BooleanAssertions.cs @@ -0,0 +1,84 @@ +using System; +using System.Diagnostics; +using FluentAssertions.Execution; + +namespace FluentAssertions.Primitives +{ + /// + /// Contains a number of methods to assert that a is in the expected state. + /// + [DebuggerNonUserCode] + public class BooleanAssertions + { + public BooleanAssertions(bool? value) + { + Subject = value; + } + + /// + /// Gets the object which value is being asserted. + /// + public bool? Subject { get; private set; } + + /// + /// Asserts that the value is false. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeFalse(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue && !Subject.Value) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {0}{reason}, but found {1}.", false, Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that the value is true. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeTrue(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue && Subject.Value) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {0}{reason}, but found {1}.", true, Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that the value is equal to the specified value. + /// + /// The expected value + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Be(bool expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue && Subject.Value.Equals(expected)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:boolean} to be {0}{reason}, but found {1}.", expected, Subject); + + return new AndConstraint(this); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/BooleanAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/BooleanAssertions.cs.meta new file mode 100644 index 0000000..905b897 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/BooleanAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c086a9419900a5e4fbf79484dc91fc86 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeAssertions.cs new file mode 100644 index 0000000..6baf2ec --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeAssertions.cs @@ -0,0 +1,831 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using FluentAssertions.Execution; +using System.Linq; + +namespace FluentAssertions.Primitives +{ + /// + /// Contains a number of methods to assert that a is in the expected state. + /// + /// + /// You can use the for a more fluent way of specifying a . + /// + [DebuggerNonUserCode] + public class DateTimeAssertions + { + public DateTimeAssertions(DateTime? value) + { + Subject = value; + } + + /// + /// Gets the object which value is being asserted. + /// + public DateTime? Subject { get; private set; } + + /// + /// Asserts that the current is exactly equal to the value. + /// + /// The expected value + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Be(DateTime expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue && (Subject.Value == expected)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:date and time} to be {0}{reason}, but found {1}.", + expected, Subject.HasValue ? Subject.Value : default(DateTime?)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current or is not equal to the value. + /// + /// The unexpected value + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBe(DateTime unexpected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!Subject.HasValue || (Subject.Value != unexpected)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:date and time} not to be {0}{reason}, but it is.", unexpected); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is within the specified number of milliseconds (default = 20 ms) + /// from the specified value. + /// + /// + /// Use this assertion when, for example the database truncates datetimes to nearest 20ms. If you want to assert to the exact datetime, + /// use . + /// + /// + /// The expected time to compare the actual value with. + /// + /// + /// The maximum amount of milliseconds which the two values may differ. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeCloseTo(DateTime nearbyTime, int precision = 20, string because = "", + params object[] becauseArgs) + { + long distanceToMinInMs = (long) (nearbyTime - DateTime.MinValue).TotalMilliseconds; + DateTime minimumValue = nearbyTime.AddMilliseconds(-Math.Min(precision, distanceToMinInMs)); + + long distanceToMaxInMs = (long) (DateTime.MaxValue - nearbyTime).TotalMilliseconds; + DateTime maximumValue = nearbyTime.AddMilliseconds(Math.Min(precision, distanceToMaxInMs)); + + Execute.Assertion + .ForCondition(Subject.HasValue && (Subject.Value >= minimumValue) && (Subject.Value <= maximumValue)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:date and time} to be within {0} ms from {1}{reason}, but found {2}.", + precision, + nearbyTime, Subject.HasValue ? Subject.Value : default(DateTime?)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is not within the specified number of milliseconds (default = 20 ms) + /// from the specified value. + /// + /// + /// Use this assertion when, for example the database truncates datetimes to nearest 20ms. If you want to assert to the exact datetime, + /// use . + /// + /// + /// The time to compare the actual value with. + /// + /// + /// The maximum amount of milliseconds which the two values must differ. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeCloseTo(DateTime distantTime, int precision = 20, string because = "", + params object[] becauseArgs) + { + long distanceToMinInMs = (long)(distantTime - DateTime.MinValue).TotalMilliseconds; + DateTime minimumValue = distantTime.AddMilliseconds(-Math.Min(precision, distanceToMinInMs)); + + long distanceToMaxInMs = (long)(DateTime.MaxValue - distantTime).TotalMilliseconds; + DateTime maximumValue = distantTime.AddMilliseconds(Math.Min(precision, distanceToMaxInMs)); + + Execute.Assertion + .ForCondition(Subject.HasValue && ((Subject.Value < minimumValue) || (Subject.Value > maximumValue))) + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected {context:date and time} to not be within {0} ms from {1}{reason}, but found {2}.", + precision, + distantTime, Subject.HasValue ? Subject.Value : default(DateTime?)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is before the specified value. + /// + /// The that the current value is expected to be before. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeBefore(DateTime expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue && Subject.Value.CompareTo(expected) < 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:date and time} before {0}{reason}, but found {1}.", expected, + Subject.HasValue ? Subject.Value : default(DateTime?)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is not before the specified value. + /// + /// The that the current value is not expected to be before. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeBefore(DateTime unexpected, string because = "", + params object[] becauseArgs) + { + return BeOnOrAfter(unexpected, because, becauseArgs); + } + + /// + /// Asserts that the current is either on, or before the specified value. + /// + /// The that the current value is expected to be on or before. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeOnOrBefore(DateTime expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue && Subject.Value.CompareTo(expected) <= 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:date and time} on or before {0}{reason}, but found {1}.", expected, + Subject.HasValue ? Subject.Value : default(DateTime?)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is neither on, nor before the specified value. + /// + /// The that the current value is not expected to be on nor before. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeOnOrBefore(DateTime unexpected, string because = "", + params object[] becauseArgs) + { + return BeAfter(unexpected, because, becauseArgs); + } + + /// + /// Asserts that the current is after the specified value. + /// + /// The that the current value is expected to be after. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeAfter(DateTime expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue && Subject.Value.CompareTo(expected) > 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:date and time} after {0}{reason}, but found {1}.", expected, + Subject.HasValue ? Subject.Value : default(DateTime?)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is not after the specified value. + /// + /// The that the current value is not expected to be after. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeAfter(DateTime unexpected, string because = "", + params object[] becauseArgs) + { + return BeOnOrBefore(unexpected, because, becauseArgs); + } + + /// + /// Asserts that the current is either on, or after the specified value. + /// + /// The that the current value is expected to be on or after. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeOnOrAfter(DateTime expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue && Subject.Value.CompareTo(expected) >= 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:date and time} on or after {0}{reason}, but found {1}.", expected, + Subject.HasValue ? Subject.Value : default(DateTime?)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is neither on, nor after the specified value. + /// + /// The that the current value is expected not to be on nor after. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeOnOrAfter(DateTime unexpected, string because = "", + params object[] becauseArgs) + { + return BeBefore(unexpected, because, becauseArgs); + } + + /// + /// Asserts that the current has the year. + /// + /// The expected year of the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveYear(int expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:year} to be {0}{reason}, but found a DateTime.", expected) + .Then + .ForCondition(Subject.Value.Year == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:year} to be {0}{reason}, but found {1}.", expected, + Subject.Value.Year); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current does not have the year. + /// + /// The year that should not be in the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotHaveYear(int unexpected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:year} not to be {0}{reason}, but found a DateTime.", unexpected) + .Then + .ForCondition(Subject.Value.Year != unexpected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:year} not to be {0}{reason}, but found it is.", unexpected, + Subject.Value.Year); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current has the month. + /// + /// The expected month of the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveMonth(int expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:month} to be {0}{reason}, but found a DateTime.", expected) + .Then + .ForCondition(Subject.Value.Month == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:month} to be {0}{reason}, but found {1}.", expected, Subject.Value.Month); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current does not have the month. + /// + /// The month that should not be in the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotHaveMonth(int unexpected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:month} not to be {0}{reason}, but found a DateTime.", unexpected) + .Then + .ForCondition(Subject.Value.Month != unexpected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:month} not to be {0}{reason}, but found it is.", unexpected, + Subject.Value.Month); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current has the day. + /// + /// The expected day of the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveDay(int expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:day} to be {0}{reason}, but found a DateTime.", expected) + .Then + .ForCondition(Subject.Value.Day == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:day} to be {0}{reason}, but found {1}.", expected, Subject.Value.Day); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current does not have the day. + /// + /// The day that should not be in the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotHaveDay(int unexpected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:day} not to be {0}{reason}, but found a DateTime.", unexpected) + .Then + .ForCondition(Subject.Value.Day != unexpected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:day} not to be {0}{reason}, but found it is.", unexpected, + Subject.Value.Day); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current has the hour. + /// + /// The expected hour of the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveHour(int expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:hour} to be {0}{reason}, but found a DateTime.", expected) + .Then + .ForCondition(Subject.Value.Hour == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:hour} to be {0}{reason}, but found {1}.", expected, Subject.Value.Hour); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current does not have the hour. + /// + /// The hour that should not be in the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotHaveHour(int unexpected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:hour} not to be {0}{reason}, but found a DateTime.", unexpected) + .Then + .ForCondition(Subject.Value.Hour != unexpected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:hour} not to be {0}{reason}, but found it is.", unexpected, + Subject.Value.Hour); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current has the minute. + /// + /// The expected minutes of the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveMinute(int expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:minute} to be {0}{reason}, but found a DateTime.", expected) + .Then + .ForCondition(Subject.Value.Minute == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:minute} to be {0}{reason}, but found {1}.", expected, Subject.Value.Minute); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current does not have the minute. + /// + /// The minute that should not be in the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotHaveMinute(int unexpected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:minute} not to be {0}{reason}, but found a DateTime.", unexpected) + .Then + .ForCondition(Subject.Value.Minute != unexpected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:minute} not to be {0}{reason}, but found it is.", unexpected, + Subject.Value.Minute); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current has the second. + /// + /// The expected seconds of the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveSecond(int expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:second} to be {0}{reason}, but found a DateTime.", expected) + .Then + .ForCondition(Subject.Value.Second == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:second} to be {0}{reason}, but found {1}.", expected, Subject.Value.Second); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current does not have the second. + /// + /// The second that should not be in the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotHaveSecond(int unexpected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:second} not to be {0}{reason}, but found a DateTime.", unexpected) + .Then + .ForCondition(Subject.Value.Second != unexpected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:second} not to be {0}{reason}, but found it is.", unexpected, + Subject.Value.Second); + + return new AndConstraint(this); + } + + /// + /// Returns a object that can be used to assert that the current + /// exceeds the specified compared to another . + /// + /// + /// The amount of time that the current should exceed compared to another . + /// + public DateTimeRangeAssertions BeMoreThan(TimeSpan timeSpan) + { + return new DateTimeRangeAssertions(this, Subject, TimeSpanCondition.MoreThan, timeSpan); + } + + /// + /// Returns a object that can be used to assert that the current + /// is equal to or exceeds the specified compared to another . + /// + /// + /// The amount of time that the current should be equal or exceed compared to + /// another . + /// + public DateTimeRangeAssertions BeAtLeast(TimeSpan timeSpan) + { + return new DateTimeRangeAssertions(this, Subject, TimeSpanCondition.AtLeast, timeSpan); + } + + /// + /// Returns a object that can be used to assert that the current + /// differs exactly the specified compared to another . + /// + /// + /// The amount of time that the current should differ exactly compared to another . + /// + public DateTimeRangeAssertions BeExactly(TimeSpan timeSpan) + { + return new DateTimeRangeAssertions(this, Subject, TimeSpanCondition.Exactly, timeSpan); + } + + /// + /// Returns a object that can be used to assert that the current + /// is within the specified compared to another . + /// + /// + /// The amount of time that the current should be within another . + /// + public DateTimeRangeAssertions BeWithin(TimeSpan timeSpan) + { + return new DateTimeRangeAssertions(this, Subject, TimeSpanCondition.Within, timeSpan); + } + + /// + /// Returns a object that can be used to assert that the current + /// differs at maximum the specified compared to another . + /// + /// + /// The maximum amount of time that the current should differ compared to another . + /// + public DateTimeRangeAssertions BeLessThan(TimeSpan timeSpan) + { + return new DateTimeRangeAssertions(this, Subject, TimeSpanCondition.LessThan, timeSpan); + } + + /// + /// Asserts that the current has the date. + /// + /// The expected date portion of the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeSameDateAs(DateTime expected, string because = "", + params object[] becauseArgs) + { + var expectedDate = expected.Date; + + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:date and time} with date {0}{reason}, but found a DateTime.", expectedDate) + .Then + .ForCondition(Subject.Value.Date == expectedDate) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:date and time} with date {0}{reason}, but found {1}.", expectedDate, Subject.Value); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is not the date. + /// + /// The date that is not to match the date portion of the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeSameDateAs(DateTime unexpected, string because = "", + params object[] becauseArgs) + { + var unexpectedDate = unexpected.Date; + + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:date and time} that does not have date {0}{reason}, but found a DateTime.", unexpectedDate) + .Then + .ForCondition(Subject.Value.Date != unexpectedDate) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:date and time} that does not have date {0}{reason}, but found it does.", unexpectedDate); + + return new AndConstraint(this); + } + + /// + /// Asserts that the is one of the specified . + /// + /// + /// The values that are valid. + /// + public AndConstraint BeOneOf(params DateTime?[] validValues) + { + return BeOneOf(validValues, String.Empty); + } + + /// + /// Asserts that the is one of the specified . + /// + /// + /// The values that are valid. + /// + public AndConstraint BeOneOf(params DateTime[] validValues) + { + return BeOneOf(validValues.Cast()); + } + + /// + /// Asserts that the is one of the specified . + /// + /// + /// The values that are valid. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeOneOf(IEnumerable validValues, string because = "", params object[] becauseArgs) + { + return BeOneOf(validValues.Cast(), because, becauseArgs); + } + + /// + /// Asserts that the is one of the specified . + /// + /// + /// The values that are valid. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeOneOf(IEnumerable validValues, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(validValues.Contains(Subject)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected value to be one of {0}{reason}, but found {1}.", validValues, Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that the represents a value in the . + /// + /// + /// The expected that the current value must represent. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeIn(DateTimeKind expectedKind, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:kind} to be {0}{reason}, but found a DateTime.", expectedKind) + .Then + .ForCondition(Subject.Value.Kind == expectedKind) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:kind} to be {0}{reason}, but found {1}.", expectedKind, Subject.Value.Kind); + + return new AndConstraint(this); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeAssertions.cs.meta new file mode 100644 index 0000000..2dfe075 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ed12b3ba9357a934fb2458ee976f7425 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeOffsetAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeOffsetAssertions.cs new file mode 100644 index 0000000..d7f6793 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeOffsetAssertions.cs @@ -0,0 +1,862 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using FluentAssertions.Execution; + +namespace FluentAssertions.Primitives +{ + /// + /// Contains a number of methods to assert that a is in the expected state. + /// + /// + /// You can use the for a more fluent way of specifying a . + /// + [DebuggerNonUserCode] + public class DateTimeOffsetAssertions + { + public DateTimeOffsetAssertions(DateTimeOffset? value) + { + Subject = value; + } + + /// + /// Gets the object which value is being asserted. + /// + public DateTimeOffset? Subject { get; private set; } + + /// + /// Asserts that the current is exactly equal to the value. + /// + /// The expected value + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Be(DateTimeOffset expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue && (Subject.Value == expected)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:date and time} to be {0}{reason}, but found {1}.", + expected, Subject.HasValue ? Subject.Value : default(DateTimeOffset?)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is not equal to the value. + /// + /// The unexpected value + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBe(DateTimeOffset unexpected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!Subject.HasValue || (Subject.Value != unexpected)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:date and time} not to be {0}{reason}, but it is.", unexpected); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is within the specified number of milliseconds (default = 20 ms) + /// from the specified value. + /// + /// + /// Use this assertion when, for example the database truncates datetimes to nearest 20ms. If you want to assert to the exact datetime, + /// use . + /// + /// + /// The expected time to compare the actual value with. + /// + /// + /// The maximum amount of milliseconds which the two values may differ. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeCloseTo(DateTimeOffset nearbyTime, int precision = 20, + string because = "", + params object[] becauseArgs) + { + long distanceToMinInMs = (long)(nearbyTime - DateTimeOffset.MinValue).TotalMilliseconds; + DateTimeOffset minimumValue = nearbyTime.AddMilliseconds(-Math.Min(precision, distanceToMinInMs)); + + long distanceToMaxInMs = (long)(DateTimeOffset.MaxValue - nearbyTime).TotalMilliseconds; + DateTimeOffset maximumValue = nearbyTime.AddMilliseconds(Math.Min(precision, distanceToMaxInMs)); + + Execute.Assertion + .ForCondition(Subject.HasValue && (Subject.Value >= minimumValue) && (Subject.Value <= maximumValue)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:date and time} to be within {0} ms from {1}{reason}, but found {2}.", + precision, + nearbyTime, Subject.HasValue ? Subject.Value : default(DateTimeOffset?)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is not within the specified number of milliseconds (default = 20 ms) + /// from the specified value. + /// + /// + /// Use this assertion when, for example the database truncates datetimes to nearest 20ms. If you want to assert to the exact datetime, + /// use . + /// + /// + /// The time to compare the actual value with. + /// + /// + /// The maximum amount of milliseconds which the two values must differ. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeCloseTo(DateTimeOffset distantTime, int precision = 20, string because = "", + params object[] becauseArgs) + { + long distanceToMinInMs = (long)(distantTime - DateTimeOffset.MinValue).TotalMilliseconds; + DateTimeOffset minimumValue = distantTime.AddMilliseconds(-Math.Min(precision, distanceToMinInMs)); + + long distanceToMaxInMs = (long)(DateTimeOffset.MaxValue - distantTime).TotalMilliseconds; + DateTimeOffset maximumValue = distantTime.AddMilliseconds(Math.Min(precision, distanceToMaxInMs)); + + Execute.Assertion + .ForCondition(Subject.HasValue && ((Subject.Value < minimumValue) || (Subject.Value > maximumValue))) + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected {context:date and time} to not be within {0} ms from {1}{reason}, but found {2}.", + precision, + distantTime, Subject.HasValue ? Subject.Value : default(DateTimeOffset?)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is before the specified value. + /// + /// The that the current value is expected to be before. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeBefore(DateTimeOffset expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue && Subject.Value.CompareTo(expected) < 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:date and time} before {0}{reason}, but found {1}.", expected, + Subject.HasValue ? Subject.Value : default(DateTimeOffset?)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is not before the specified value. + /// + /// The that the current value is not expected to be before. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeBefore(DateTimeOffset unexpected, string because = "", + params object[] becauseArgs) + { + return BeOnOrAfter(unexpected, because, becauseArgs); + } + + /// + /// Asserts that the current is either on, or before the specified value. + /// + /// The that the current value is expected to be on or before. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeOnOrBefore(DateTimeOffset expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue && Subject.Value.CompareTo(expected) <= 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:date and time} on or before {0}{reason}, but found {1}.", expected, + Subject.HasValue ? Subject.Value : default(DateTimeOffset?)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is neither on, nor before the specified value. + /// + /// The that the current value is not expected to be on nor before. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeOnOrBefore(DateTimeOffset unexpected, string because = "", + params object[] becauseArgs) + { + return BeAfter(unexpected, because, becauseArgs); + } + + /// + /// Asserts that the current is after the specified value. + /// + /// The that the current value is expected to be after. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeAfter(DateTimeOffset expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue && Subject.Value.CompareTo(expected) > 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:date and time} after {0}{reason}, but found {1}.", expected, + Subject.HasValue ? Subject.Value : default(DateTimeOffset?)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is not after the specified value. + /// + /// The that the current value is not expected to be after. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeAfter(DateTimeOffset unexpected, string because = "", + params object[] becauseArgs) + { + return BeOnOrBefore(unexpected, because, becauseArgs); + } + + /// + /// Asserts that the current is either on, or after the specified value. + /// + /// The that the current value is expected to be on or after. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeOnOrAfter(DateTimeOffset expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue && Subject.Value.CompareTo(expected) >= 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:date and time} on or after {0}{reason}, but found {1}.", expected, + Subject.HasValue ? Subject.Value : default(DateTimeOffset?)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is neither on, nor after the specified value. + /// + /// The that the current value is expected not to be on nor after. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeOnOrAfter(DateTimeOffset unexpected, string because = "", + params object[] becauseArgs) + { + return BeBefore(unexpected, because, becauseArgs); + } + + /// + /// Asserts that the current has the year. + /// + /// The expected year of the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveYear(int expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:year} to be {0}{reason}, but found a DateTimeOffset.", expected) + .Then + .ForCondition(Subject.Value.Year == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:year} to be {0}{reason}, but found {1}.", expected, + Subject.Value.Year); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current does not have the year. + /// + /// The year that should not be in the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotHaveYear(int unexpected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:year} not to be {0}{reason}, but found a DateTimeOffset.", unexpected) + .Then + .ForCondition(Subject.Value.Year != unexpected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:year} not to be {0}{reason}, but found it is.", unexpected, + Subject.Value.Year); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current has the month. + /// + /// The expected month of the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveMonth(int expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:month} to be {0}{reason}, but found a DateTimeOffset.", expected) + .Then + .ForCondition(Subject.Value.Month == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:month} to be {0}{reason}, but found {1}.", expected, Subject.Value.Month); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current does not have the month. + /// + /// The month that should not be in the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotHaveMonth(int unexpected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:month} not to be {0}{reason}, but found a DateTimeOffset.", unexpected) + .Then + .ForCondition(Subject.Value.Month != unexpected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:month} not to be {0}{reason}, but found it is.", unexpected, + Subject.Value.Month); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current has the day. + /// + /// The expected day of the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveDay(int expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:day} to be {0}{reason}, but found a DateTimeOffset.", expected) + .Then + .ForCondition(Subject.Value.Day == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:day} to be {0}{reason}, but found {1}.", expected, Subject.Value.Day); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current does not have the day. + /// + /// The day that should not be in the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotHaveDay(int unexpected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:day} not to be {0}{reason}, but found a DateTimeOffset.", unexpected) + .Then + .ForCondition(Subject.Value.Day != unexpected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:day} not to be {0}{reason}, but found it is.", unexpected, + Subject.Value.Day); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current has the hour. + /// + /// The expected hour of the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveHour(int expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:hour} to be {0}{reason}, but found a DateTimeOffset.", expected) + .Then + .ForCondition(Subject.Value.Hour == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:hour} to be {0}{reason}, but found {1}.", expected, Subject.Value.Hour); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current does not have the hour. + /// + /// The hour that should not be in the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotHaveHour(int unexpected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:hour} not to be {0}{reason}, but found a DateTimeOffset.", unexpected) + .Then + .ForCondition(Subject.Value.Hour != unexpected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:hour} not to be {0}{reason}, but found it is.", unexpected, + Subject.Value.Hour); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current has the minute. + /// + /// The expected minutes of the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveMinute(int expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:minute} to be {0}{reason}, but found a DateTimeOffset.", expected) + .Then + .ForCondition(Subject.Value.Minute == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:minute} to be {0}{reason}, but found {1}.", expected, Subject.Value.Minute); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current does not have the minute. + /// + /// The minute that should not be in the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotHaveMinute(int unexpected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:minute} not to be {0}{reason}, but found a DateTimeOffset.", unexpected) + .Then + .ForCondition(Subject.Value.Minute != unexpected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:minute} not to be {0}{reason}, but found it is.", unexpected, + Subject.Value.Minute); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current has the second. + /// + /// The expected seconds of the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveSecond(int expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:second} to be {0}{reason}, but found a DateTimeOffset.", expected) + .Then + .ForCondition(Subject.Value.Second == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:second} to be {0}{reason}, but found {1}.", expected, Subject.Value.Second); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current does not have the second. + /// + /// The second that should not be in the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotHaveSecond(int unexpected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:second} not to be {0}{reason}, but found a DateTimeOffset.", unexpected) + .Then + .ForCondition(Subject.Value.Second != unexpected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:second} not to be {0}{reason}, but found it is.", unexpected, + Subject.Value.Second); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current has the offset. + /// + /// The expected offset of the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveOffset( TimeSpan expected, string because = "", + params object[] becauseArgs ) + { + Execute.Assertion + .ForCondition( Subject.HasValue ) + .BecauseOf( because, becauseArgs ) + .FailWith( "Expected {context:offset} to be {0}{reason}, but found a DateTimeOffset.", expected ) + .Then + .ForCondition( Subject.Value.Offset == expected ) + .BecauseOf( because, becauseArgs ) + .FailWith( "Expected {context:offset} to be {0}{reason}, but found {1}.", expected, Subject.Value.Second ); + + return new AndConstraint( this ); + } + + /// + /// Asserts that the current does not have the offset. + /// + /// The offset that should not be in the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotHaveOffset( TimeSpan unexpected, string because = "", + params object[] becauseArgs ) + { + Execute.Assertion + .ForCondition( Subject.HasValue ) + .BecauseOf( because, becauseArgs ) + .FailWith( "Expected {context:offset} not to be {0}{reason}, but found a DateTimeOffset.", unexpected ) + .Then + .ForCondition( Subject.Value.Offset != unexpected ) + .BecauseOf( because, becauseArgs ) + .FailWith( "Expected {context:offset} not to be {0}{reason}, but found it is.", unexpected, + Subject.Value.Second ); + + return new AndConstraint( this ); + } + + /// + /// Returns a object that can be used to assert that the current + /// exceeds the specified compared to another . + /// + /// + /// The amount of time that the current should exceed compared to another . + /// + public DateTimeOffsetRangeAssertions BeMoreThan(TimeSpan timeSpan) + { + return new DateTimeOffsetRangeAssertions(this, Subject, TimeSpanCondition.MoreThan, timeSpan); + } + + /// + /// Returns a object that can be used to assert that the current + /// is equal to or exceeds the specified compared to another . + /// + /// + /// The amount of time that the current should be equal or exceed compared to + /// another . + /// + public DateTimeOffsetRangeAssertions BeAtLeast(TimeSpan timeSpan) + { + return new DateTimeOffsetRangeAssertions(this, Subject, TimeSpanCondition.AtLeast, timeSpan); + } + + /// + /// Returns a object that can be used to assert that the current + /// differs exactly the specified compared to another . + /// + /// + /// The amount of time that the current should differ exactly compared to another . + /// + public DateTimeOffsetRangeAssertions BeExactly(TimeSpan timeSpan) + { + return new DateTimeOffsetRangeAssertions(this, Subject, TimeSpanCondition.Exactly, timeSpan); + } + + /// + /// Returns a object that can be used to assert that the current + /// is within the specified compared to another . + /// + /// + /// The amount of time that the current should be within another . + /// + public DateTimeOffsetRangeAssertions BeWithin(TimeSpan timeSpan) + { + return new DateTimeOffsetRangeAssertions(this, Subject, TimeSpanCondition.Within, timeSpan); + } + + /// + /// Returns a object that can be used to assert that the current + /// differs at maximum the specified compared to another . + /// + /// + /// The maximum amount of time that the current should differ compared to another . + /// + public DateTimeOffsetRangeAssertions BeLessThan(TimeSpan timeSpan) + { + return new DateTimeOffsetRangeAssertions(this, Subject, TimeSpanCondition.LessThan, timeSpan); + } + + /// + /// Asserts that the current has the date. + /// + /// The expected date portion of the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeSameDateAs(DateTimeOffset expected, string because = "", + params object[] becauseArgs) + { + var expectedDate = expected.Date; + + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:date and time} with date {0}{reason}, but found a DateTimeOffset.", expectedDate) + .Then + .ForCondition(Subject.Value.Date == expectedDate) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:date and time} with date {0}{reason}, but found {1}.", expectedDate, Subject.Value); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is not the date. + /// + /// The date that is not to match the date portion of the current value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeSameDateAs(DateTimeOffset unexpected, string because = "", + params object[] becauseArgs) + { + var unexpectedDate = unexpected.Date; + + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:date and time} that does not have date {0}{reason}, but found a DateTimeOffset.", unexpectedDate) + .Then + .ForCondition(Subject.Value.Date != unexpectedDate) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:date and time} that does not have date {0}{reason}, but found it does.", unexpectedDate); + + return new AndConstraint(this); + } + + /// + /// Asserts that the is one of the specified . + /// + /// + /// The values that are valid. + /// + public AndConstraint BeOneOf(params DateTimeOffset?[] validValues) + { + return BeOneOf(validValues, String.Empty); + } + + /// + /// Asserts that the is one of the specified . + /// + /// + /// The values that are valid. + /// + public AndConstraint BeOneOf(params DateTimeOffset[] validValues) + { + return BeOneOf(validValues.Cast()); + } + + /// + /// Asserts that the is one of the specified . + /// + /// + /// The values that are valid. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeOneOf(IEnumerable validValues, string because = "", params object[] becauseArgs) + { + return BeOneOf(validValues.Cast(), because, becauseArgs); + } + /// + /// Asserts that the is one of the specified . + /// + /// + /// The values that are valid. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeOneOf(IEnumerable validValues, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(validValues.Contains(Subject)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected value to be one of {0}{reason}, but found {1}.", validValues, Subject); + + return new AndConstraint(this); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeOffsetAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeOffsetAssertions.cs.meta new file mode 100644 index 0000000..69660ce --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeOffsetAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cefc21f5e2e7f7a4092a767270ef76b5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeOffsetRangeAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeOffsetRangeAssertions.cs new file mode 100644 index 0000000..2022ab1 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeOffsetRangeAssertions.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using FluentAssertions.Common; +using FluentAssertions.Execution; + +namespace FluentAssertions.Primitives +{ + /// + /// Contains a number of methods to assert that two objects differ in the expected way. + /// + /// + /// You can use the and for a more fluent + /// way of specifying a or a . + /// + [DebuggerNonUserCode] + public class DateTimeOffsetRangeAssertions + { + #region Private Definitions + + private readonly DateTimeOffsetAssertions parentAssertions; + private readonly TimeSpanPredicate predicate; + + private readonly Dictionary predicates = new Dictionary + + { + { TimeSpanCondition.MoreThan, new TimeSpanPredicate((ts1, ts2) => ts1 > ts2, "more than") }, + { TimeSpanCondition.AtLeast, new TimeSpanPredicate((ts1, ts2) => ts1 >= ts2, "at least") }, + { TimeSpanCondition.Exactly, new TimeSpanPredicate((ts1, ts2) => ts1 == ts2, "exactly") }, + { TimeSpanCondition.Within, new TimeSpanPredicate((ts1, ts2) => ts1 <= ts2, "within") }, + { TimeSpanCondition.LessThan, new TimeSpanPredicate((ts1, ts2) => ts1 < ts2, "less than") } + }; + + private readonly DateTimeOffset? subject; + private readonly TimeSpan timeSpan; + + #endregion + + protected internal DateTimeOffsetRangeAssertions(DateTimeOffsetAssertions parentAssertions, DateTimeOffset? subject, + TimeSpanCondition condition, + TimeSpan timeSpan) + { + this.parentAssertions = parentAssertions; + this.subject = subject; + this.timeSpan = timeSpan; + + predicate = predicates[condition]; + } + + /// + /// Asserts that a occurs a specified amount of time before another . + /// + /// + /// The to compare the subject with. + /// + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public AndConstraint Before(DateTimeOffset target, string because = "", + params object[] becauseArgs) + { + bool success = Execute.Assertion + .ForCondition(subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected date and/or time {0} to be " + predicate.DisplayText + + " {1} before {2}{reason}, but found a DateTime.", + subject, timeSpan, target); + + if (success) + { + var actual = target.Subtract(subject.Value); + + if (!predicate.IsMatchedBy(actual, timeSpan)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected date and/or time {0} to be " + predicate.DisplayText + + " {1} before {2}{reason}, but it differs {3}.", + subject, timeSpan, target, actual); + } + } + + return new AndConstraint(parentAssertions); + } + + /// + /// Asserts that a occurs a specified amount of time after another . + /// + /// + /// The to compare the subject with. + /// + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public AndConstraint After(DateTimeOffset target, string because = "", params object[] becauseArgs) + { + bool success = Execute.Assertion + .ForCondition(subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected date and/or time {0} to be " + predicate.DisplayText + + " {1} after {2}{reason}, but found a DateTime.", + subject, timeSpan, target); + + if (success) + { + var actual = subject.Value.Subtract(target); + + if (!predicate.IsMatchedBy(actual, timeSpan)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected date and/or time {0} to be " + predicate.DisplayText + + " {1} after {2}{reason}, but it differs {3}.", + subject, timeSpan, target, actual); + } + } + + return new AndConstraint(parentAssertions); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeOffsetRangeAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeOffsetRangeAssertions.cs.meta new file mode 100644 index 0000000..39615b5 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeOffsetRangeAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 16807cd3f8fdf1a4eb9669846ecd8d83 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeRangeAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeRangeAssertions.cs new file mode 100644 index 0000000..f03869e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeRangeAssertions.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using FluentAssertions.Execution; + +namespace FluentAssertions.Primitives +{ + /// + /// Contains a number of methods to assert that two objects differ in the expected way. + /// + /// + /// You can use the and for a more fluent + /// way of specifying a or a . + /// + [DebuggerNonUserCode] + public class DateTimeRangeAssertions + { + #region Private Definitions + + private readonly DateTimeAssertions parentAssertions; + private readonly TimeSpanPredicate predicate; + + private readonly Dictionary predicates = new Dictionary + + { + {TimeSpanCondition.MoreThan, new TimeSpanPredicate((ts1, ts2) => ts1 > ts2, "more than")}, + {TimeSpanCondition.AtLeast, new TimeSpanPredicate((ts1, ts2) => ts1 >= ts2, "at least")}, + {TimeSpanCondition.Exactly, new TimeSpanPredicate((ts1, ts2) => ts1 == ts2, "exactly")}, + {TimeSpanCondition.Within, new TimeSpanPredicate((ts1, ts2) => ts1 <= ts2, "within")}, + {TimeSpanCondition.LessThan, new TimeSpanPredicate((ts1, ts2) => ts1 < ts2, "less than")} + }; + + private readonly DateTime? subject; + private readonly TimeSpan timeSpan; + + #endregion + + protected internal DateTimeRangeAssertions(DateTimeAssertions parentAssertions, DateTime? subject, + TimeSpanCondition condition, + TimeSpan timeSpan) + { + this.parentAssertions = parentAssertions; + this.subject = subject; + this.timeSpan = timeSpan; + + predicate = predicates[condition]; + } + + /// + /// Asserts that a occurs a specified amount of time before another . + /// + /// + /// The to compare the subject with. + /// + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public AndConstraint Before(DateTime target, string because = "", + params object[] becauseArgs) + { + bool success = Execute.Assertion + .ForCondition(subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected date and/or time {0} to be " + predicate.DisplayText + + " {1} before {2}{reason}, but found a DateTime.", + subject, timeSpan, target); + + if (success) + { + var actual = target.Subtract(subject.Value); + + if (!predicate.IsMatchedBy(actual, timeSpan)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected date and/or time {0} to be " + predicate.DisplayText + + " {1} before {2}{reason}, but it differs {3}.", + subject, timeSpan, target, actual); + } + } + + return new AndConstraint(parentAssertions); + } + + /// + /// Asserts that a occurs a specified amount of time after another . + /// + /// + /// The to compare the subject with. + /// + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public AndConstraint After(DateTime target, string because = "", + params object[] becauseArgs) + { + bool success = Execute.Assertion + .ForCondition(subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected date and/or time {0} to be " + predicate.DisplayText + + " {1} after {2}{reason}, but found a DateTime.", + subject, timeSpan, target); + + if (success) + { + var actual = subject.Value.Subtract(target); + + if (!predicate.IsMatchedBy(actual, timeSpan)) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected date and/or time {0} to be " + predicate.DisplayText + + " {1} after {2}{reason}, but it differs {3}.", + subject, timeSpan, target, actual); + } + } + + return new AndConstraint(parentAssertions); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeRangeAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeRangeAssertions.cs.meta new file mode 100644 index 0000000..13dcf86 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/DateTimeRangeAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9f8ce63c2d6529b4cac24b89052421bb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/GuidAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/GuidAssertions.cs new file mode 100644 index 0000000..eba2162 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/GuidAssertions.cs @@ -0,0 +1,130 @@ +using System; +using System.Diagnostics; +using FluentAssertions.Execution; + +namespace FluentAssertions.Primitives +{ + /// + /// Contains a number of methods to assert that a is in the correct state. + /// + [DebuggerNonUserCode] + public class GuidAssertions + { + public GuidAssertions(Guid? value) + { + Subject = value; + } + + /// + /// Gets the object which value is being asserted. + /// + public Guid? Subject { get; private set; } + + #region BeEmpty / NotBeEmpty + + /// + /// Asserts that the is . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeEmpty(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition((Subject.HasValue) && (Subject.Value == Guid.Empty)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected empty Guid{reason}, but found {0}.", Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that the is not . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeEmpty(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition((Subject.HasValue) && (Subject.Value != Guid.Empty)) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect empty Guid{reason}."); + + return new AndConstraint(this); + } + + #endregion + + #region Be / NotBe + + /// + /// Asserts that the is equal to the GUID. + /// + /// The expected value to compare the actual value with. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Be(string expected, string because = "", params object[] becauseArgs) + { + var expectedGuid = new Guid(expected); + return Be(expectedGuid, because, becauseArgs); + } + + /// + /// Asserts that the is equal to the GUID. + /// + /// The expected value to compare the actual value with. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Be(Guid expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.Equals(expected)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:Guid} to be {0}{reason}, but found {1}.", expected, Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that the is not equal to the GUID. + /// + /// The unexpected value to compare the actual value with. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBe(Guid unexpected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!Subject.Equals(unexpected)) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect {context:Guid} to be {0}{reason}.", Subject); + + return new AndConstraint(this); + } + + #endregion + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/GuidAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/GuidAssertions.cs.meta new file mode 100644 index 0000000..9cd8ae2 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/GuidAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4826598e85376c440b261c2cad5ebf6c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/NegatedStringStartValidator.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/NegatedStringStartValidator.cs new file mode 100644 index 0000000..34b443f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/NegatedStringStartValidator.cs @@ -0,0 +1,44 @@ +using System; + +namespace FluentAssertions.Primitives +{ + internal class NegatedStringStartValidator : StringValidator + { + private readonly StringComparison stringComparison; + + public NegatedStringStartValidator(string subject, string expected, StringComparison stringComparison, string because, + object[] becauseArgs) : + base(subject, expected, because, becauseArgs) + { + this.stringComparison = stringComparison; + } + + protected override string ExpectationDescription + { + get + { + string predicateDescription = IgnoreCase ? "start with equivalent of" : "start with"; + return "Expected {context:string} that does not " + predicateDescription + " "; + } + } + + private bool IgnoreCase + { + get + { + return (stringComparison == StringComparison.CurrentCultureIgnoreCase) || + (stringComparison == StringComparison.OrdinalIgnoreCase); + } + } + + protected override void ValidateAgainstMismatch() + { + bool isMatch = subject.StartsWith(expected, stringComparison); + if (isMatch) + { + assertion.FailWith(ExpectationDescription + "{0}{reason}, but found {1}.", + expected, subject); + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/NegatedStringStartValidator.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/NegatedStringStartValidator.cs.meta new file mode 100644 index 0000000..1745630 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/NegatedStringStartValidator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 647b8b9225ac9d646bb0de64d29a1b18 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/NullableBooleanAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableBooleanAssertions.cs new file mode 100644 index 0000000..3d37f23 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableBooleanAssertions.cs @@ -0,0 +1,149 @@ +using System; +using System.Diagnostics; +using FluentAssertions.Execution; + +namespace FluentAssertions.Primitives +{ + /// + /// Contains a number of methods to assert that a nullable is in the expected state. + /// + [DebuggerNonUserCode] + public class NullableBooleanAssertions : BooleanAssertions + { + public NullableBooleanAssertions(bool? value) + : base(value) + { + } + + /// + /// Asserts that a nullable boolean value is not null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveValue(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a value{reason}."); + + return new AndConstraint(this); + } + + /// + /// Asserts that a nullable boolean value is not null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeNull(string because = "", params object[] becauseArgs) + { + return HaveValue(because, becauseArgs); + } + + /// + /// Asserts that a nullable boolean value is null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotHaveValue(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect a value{reason}, but found {0}.", Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a nullable boolean value is null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeNull(string because = "", params object[] becauseArgs) + { + return NotHaveValue(because, becauseArgs); + } + + /// + /// Asserts that the value is equal to the specified value. + /// + /// The expected value + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Be(bool? expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {0}{reason}, but found {1}.", expected, Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that the value is not false. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeFalse(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!Subject.HasValue || Subject.Value) + .BecauseOf(because, becauseArgs) + .FailWith("Expected nullable boolean not to be {0}{reason}, but found {1}.", false, Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that the value is not true. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeTrue(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!Subject.HasValue || !Subject.Value) + .BecauseOf(because, becauseArgs) + .FailWith("Expected nullable boolean not to be {0}{reason}, but found {1}.", true, Subject); + + return new AndConstraint(this); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/NullableBooleanAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableBooleanAssertions.cs.meta new file mode 100644 index 0000000..a556fcf --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableBooleanAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c888c669899df3843b592fc9d838b0d3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/NullableDateTimeAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableDateTimeAssertions.cs new file mode 100644 index 0000000..b19bae9 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableDateTimeAssertions.cs @@ -0,0 +1,112 @@ +using System; +using System.Diagnostics; +using FluentAssertions.Execution; + +namespace FluentAssertions.Primitives +{ + /// + /// Contains a number of methods to assert that a nullable or is in the expected state. + /// + /// + /// You can use the for a more fluent way of specifying a . + /// + [DebuggerNonUserCode] + public class NullableDateTimeAssertions : DateTimeAssertions + { + public NullableDateTimeAssertions(DateTime? expected) + : base(expected) + { + } + + /// + /// Asserts that a nullable value is not null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveValue(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected variable to have a value{reason}, but found {0}", Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a nullable value is not null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeNull(string because = "", params object[] becauseArgs) + { + return HaveValue(because, becauseArgs); + } + + /// + /// Asserts that a nullable value is null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotHaveValue(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect variable to have a value{reason}, but found {0}", Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a nullable value is null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeNull(string because = "", params object[] becauseArgs) + { + return NotHaveValue(because, becauseArgs); + } + + /// + /// Asserts that the value is equal to the specified value. + /// + /// The expected value + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Be(DateTime? expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {0}{reason}, but found {1}.", expected, Subject); + + return new AndConstraint(this); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/NullableDateTimeAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableDateTimeAssertions.cs.meta new file mode 100644 index 0000000..b6d5e6a --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableDateTimeAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fdc11fd216aad13448006c17ff39bc45 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/NullableDateTimeOffsetAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableDateTimeOffsetAssertions.cs new file mode 100644 index 0000000..14c0a70 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableDateTimeOffsetAssertions.cs @@ -0,0 +1,115 @@ +using System; +using System.Diagnostics; +using FluentAssertions.Execution; + +namespace FluentAssertions.Primitives +{ + /// + /// Contains a number of methods to assert that a nullable is in the expected state. + /// + /// + /// You can use the for a more fluent way of specifying a . + /// + [DebuggerNonUserCode] + public class NullableDateTimeOffsetAssertions : DateTimeOffsetAssertions + { + public NullableDateTimeOffsetAssertions(DateTimeOffset? expected) + : base(expected) + { + } + + /// + /// Asserts that a nullable value is not null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveValue(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected variable to have a value{reason}, but found {0}", Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a nullable value is not null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeNull(string because = "", params object[] becauseArgs) + { + return HaveValue(because, becauseArgs); + } + + /// + /// Asserts that a nullable value is null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotHaveValue(string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect variable to have a value{reason}, but found {0}", Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a nullable value is null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeNull(string because = "", + params object[] becauseArgs) + { + return NotHaveValue(because, becauseArgs); + } + + /// + /// Asserts that the value is equal to the specified value. + /// + /// The expected value + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Be(DateTimeOffset? expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {0}{reason}, but found {1}.", expected, Subject); + + return new AndConstraint(this); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/NullableDateTimeOffsetAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableDateTimeOffsetAssertions.cs.meta new file mode 100644 index 0000000..5406724 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableDateTimeOffsetAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dad515c31c6618c408cb4fd5758cccd2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/NullableGuidAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableGuidAssertions.cs new file mode 100644 index 0000000..e2a6740 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableGuidAssertions.cs @@ -0,0 +1,109 @@ +using System; +using System.Diagnostics; +using FluentAssertions.Execution; + +namespace FluentAssertions.Primitives +{ + /// + /// Contains a number of methods to assert that a nullable is in the expected state. + /// + [DebuggerNonUserCode] + public class NullableGuidAssertions : GuidAssertions + { + public NullableGuidAssertions(Guid? value) + : base(value) + { + } + + /// + /// Asserts that a nullable value is not null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveValue(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a value{reason}."); + + return new AndConstraint(this); + } + + /// + /// Asserts that a nullable value is not null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeNull(string because = "", params object[] becauseArgs) + { + return HaveValue(because, becauseArgs); + } + + /// + /// Asserts that a nullable value is null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotHaveValue(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect a value{reason}, but found {0}.", Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a nullable value is null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeNull(string because = "", params object[] becauseArgs) + { + return NotHaveValue(because, becauseArgs); + } + + /// + /// Asserts that the value is equal to the specified value. + /// + /// The expected value + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Be(Guid? expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:Guid} to be {0}{reason}, but found {1}.", expected, Subject); + + return new AndConstraint(this); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/NullableGuidAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableGuidAssertions.cs.meta new file mode 100644 index 0000000..49af594 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableGuidAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d3a656f2b92cec444ba5385a8fd029e3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/NullableSimpleTimeSpanAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableSimpleTimeSpanAssertions.cs new file mode 100644 index 0000000..e2b1d29 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableSimpleTimeSpanAssertions.cs @@ -0,0 +1,114 @@ +using System; +using System.Diagnostics; +using FluentAssertions.Common; +using FluentAssertions.Execution; + +namespace FluentAssertions.Primitives +{ + /// + /// Contains a number of methods to assert that a nullable is in the expected state. + /// + /// + /// You can use the for a more fluent way of specifying a . + /// + [DebuggerNonUserCode] + public class NullableSimpleTimeSpanAssertions : SimpleTimeSpanAssertions + { + public NullableSimpleTimeSpanAssertions(TimeSpan? value) + : base(value) + { + } + + /// + /// Asserts that a nullable value is not null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveValue(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a value{reason}."); + + return new AndConstraint(this); + } + + /// + /// Asserts that a nullable value is not null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeNull(string because = "", params object[] becauseArgs) + { + return HaveValue(because, becauseArgs); + } + + /// + /// Asserts that a nullable value is null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotHaveValue(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!Subject.HasValue) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect a value{reason}, but found {0}.", Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a nullable value is null. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeNull(string because = "", params object[] becauseArgs) + { + return NotHaveValue(because, becauseArgs); + } + + /// + /// Asserts that the value is equal to the specified value. + /// + /// The expected value + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Be(TimeSpan? expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {0}{reason}, but found {1}.", expected, Subject); + + return new AndConstraint(this); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/NullableSimpleTimeSpanAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableSimpleTimeSpanAssertions.cs.meta new file mode 100644 index 0000000..76685f9 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/NullableSimpleTimeSpanAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: abd03ad00949218448fcbee8f94efba2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/ObjectAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/ObjectAssertions.cs new file mode 100644 index 0000000..a0d3fab --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/ObjectAssertions.cs @@ -0,0 +1,131 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Xml.Serialization; +using FluentAssertions.Common; +using FluentAssertions.Equivalency; +using FluentAssertions.Execution; + +namespace FluentAssertions.Primitives +{ + /// + /// Contains a number of methods to assert that an is in the expected state. + /// + [DebuggerNonUserCode] + public class ObjectAssertions : ReferenceTypeAssertions + { + public ObjectAssertions(object value) + { + Subject = value; + } + + /// + /// Asserts that an object equals another object using its implementation. + /// + /// The expected value + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Be(object expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(Subject.IsSameOrEqualTo(expected)) + .FailWith("Expected {context:object} to be {0}{reason}, but found {1}.", expected, + Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that an object does not equal another object using its method. + /// + /// The unexpected value + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public AndConstraint NotBe(object unexpected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!Subject.IsSameOrEqualTo(unexpected)) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect {context:object} to be equal to {0}{reason}.", unexpected); + + return new AndConstraint(this); + } + + /// + /// Asserts that an object is an enum and has a specified flag + /// + /// The expected flag. + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public AndConstraint HaveFlag(Enum expectedFlag, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(!ReferenceEquals(Subject, null)) + .FailWith("Expected type to be {0}{reason}, but found .", expectedFlag.GetType()) + .Then + .ForCondition(Subject.GetType() == expectedFlag.GetType()) + .FailWith("Expected the enum to be of type {0} type but found {1}{reason}.", expectedFlag.GetType(), Subject.GetType()) + .Then + .Given(() => Subject as Enum) + .ForCondition(@enum => @enum.HasFlag(expectedFlag)) + .FailWith("The enum was expected to have flag {0} but found {1}{reason}.", _ => expectedFlag, @enum => @enum); + + return new AndConstraint(this); + } + + /// + /// Asserts that an object is an enum and does not have a specified flag + /// + /// The unexpected flag. + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public AndConstraint NotHaveFlag(Enum unexpectedFlag, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(!ReferenceEquals(Subject, null)) + .FailWith("Expected type to be {0}{reason}, but found .", unexpectedFlag.GetType()) + .Then + .ForCondition(Subject.GetType() == unexpectedFlag.GetType()) + .FailWith("Expected the enum to be of type {0} type but found {1}{reason}.", unexpectedFlag.GetType(), Subject.GetType()) + .Then + .Given(() => Subject as Enum) + .ForCondition(@enum => !@enum.HasFlag(unexpectedFlag)) + .FailWith("Did not expect the enum to have flag {0}{reason}.", unexpectedFlag); + + return new AndConstraint(this); + } + + /// + /// Returns the type of the subject the assertion applies on. + /// + protected override string Context + { + get { return "object"; } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/ObjectAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/ObjectAssertions.cs.meta new file mode 100644 index 0000000..7c601cb --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/ObjectAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8711aa516d517c24aa318a87e223da90 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/ReferenceTypeAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/ReferenceTypeAssertions.cs new file mode 100644 index 0000000..03f8fbe --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/ReferenceTypeAssertions.cs @@ -0,0 +1,286 @@ +using System; +using System.Diagnostics; +using System.Linq.Expressions; + +using FluentAssertions.Execution; + +namespace FluentAssertions.Primitives +{ + /// + /// Contains a number of methods to assert that a reference type object is in the expected state. + /// + [DebuggerNonUserCode] + public abstract class ReferenceTypeAssertions + where TAssertions : ReferenceTypeAssertions + { + /// + /// Gets the object which value is being asserted. + /// + public TSubject Subject { get; protected set; } + + /// + /// Asserts that the current object has not been initialized yet. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeNull(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(ReferenceEquals(Subject, null)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:" + Context + "} to be {reason}, but found {0}.", Subject); + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the current object has been initialized. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeNull(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!ReferenceEquals(Subject, null)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:" + Context + "} not to be {reason}."); + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that an object reference refers to the exact same object as another object reference. + /// + /// The expected object + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public AndConstraint BeSameAs(TSubject expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .UsingLineBreaks + .ForCondition(ReferenceEquals(Subject, expected)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:" + Context + "} to refer to {0}{reason}, but found {1}.", expected, Subject); + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that an object reference refers to a different object than another object reference refers to. + /// + /// The unexpected object + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public AndConstraint NotBeSameAs(TSubject unexpected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .UsingLineBreaks + .ForCondition(!ReferenceEquals(Subject, unexpected)) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect reference to object {0}{reason}.", unexpected); + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the object is of the specified type . + /// + /// The expected type of the object. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndWhichConstraint BeOfType(string because = "", params object[] becauseArgs) + { + BeOfType(typeof(T), because, becauseArgs); + + return new AndWhichConstraint((TAssertions)this, (T)(object)Subject); + } + + /// + /// Asserts that the object is of the specified type . + /// + /// + /// The type that the subject is supposed to be of. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeOfType(Type expectedType, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!ReferenceEquals(Subject, null)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:type} to be {0}{reason}, but found .", expectedType); + + Type subjectType = Subject.GetType(); + if (expectedType.IsGenericTypeDefinition() && subjectType.IsGenericType()) + { + subjectType.GetGenericTypeDefinition().Should().Be(expectedType, because, becauseArgs); + } + else + { + subjectType.Should().Be(expectedType, because, becauseArgs); + } + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the object is not of the specified type . + /// + /// The type that the subject is not supposed to be of. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeOfType(string because = "", params object[] becauseArgs) + { + NotBeOfType(typeof(T), because, becauseArgs); + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the object is not of the specified type . + /// + /// + /// The type that the subject is not supposed to be of. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeOfType(Type expectedType, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!ReferenceEquals(Subject, null)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:type} not to be {0}{reason}, but found .", expectedType); + + Subject.GetType().Should().NotBe(expectedType, because, becauseArgs); + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the object is assignable to a variable of type . + /// + /// The type to which the object should be assignable. + /// The reason why the object should be assignable to the type. + /// The parameters used when formatting the . + /// An which can be used to chain assertions. + public AndWhichConstraint BeAssignableTo(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is T) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:" + Context + "} to be assignable to {0}{reason}, but {1} is not", + typeof(T), + Subject.GetType()); + + return new AndWhichConstraint((TAssertions)this, (T)((object)Subject)); + } + + /// + /// Asserts that the object is assignable to a variable of given . + /// + /// The type to which the object should be assignable. + /// The parameters used when formatting the . + /// + /// An which can be used to chain assertions. + public AndConstraint BeAssignableTo(Type type, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!ReferenceEquals(Subject, null)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:type} not to be {0}{reason}, but found .", type); + + Execute.Assertion + .ForCondition(type.IsAssignableFrom(Subject.GetType())) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:" + Context + "} to be assignable to {0}{reason}, but {1} is not", + type, + Subject.GetType()); + + return new AndConstraint((TAssertions)this); + } + + /// + /// Asserts that the is satisfied. + /// + /// The predicate which must be satisfied by the . + /// The reason why the predicate should be satisfied. + /// The parameters used when formatting the . + /// An which can be used to chain assertions. + public AndConstraint Match(Expression> predicate, + string because = "", + params object[] becauseArgs) + { + return Match(predicate, because, becauseArgs); + } + + /// + /// Asserts that the is satisfied. + /// + /// The predicate which must be satisfied by the . + /// The reason why the predicate should be satisfied. + /// The parameters used when formatting the . + /// An which can be used to chain assertions. + public AndConstraint Match(Expression> predicate, + string because = "", + params object[] becauseArgs) + where T : TSubject + { + if (predicate == null) + { + throw new NullReferenceException("Cannot match an object against a predicate."); + } + + Execute.Assertion + .ForCondition(predicate.Compile()((T)Subject)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {0} to match {1}{reason}.", Subject, predicate.Body); + + return new AndConstraint((TAssertions)this); + } + + /// + /// Returns the type of the subject the assertion applies on. + /// + protected abstract string Context { get; } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/ReferenceTypeAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/ReferenceTypeAssertions.cs.meta new file mode 100644 index 0000000..84d07f4 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/ReferenceTypeAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: be44ec5fe5a362d4cad2882c0a9553e4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/SimpleTimeSpanAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/SimpleTimeSpanAssertions.cs new file mode 100644 index 0000000..6029e6c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/SimpleTimeSpanAssertions.cs @@ -0,0 +1,236 @@ +using System; +using System.Diagnostics; +using FluentAssertions.Execution; + +namespace FluentAssertions.Primitives +{ + /// + /// Contains a number of methods to assert that a nullable is in the expected state. + /// + [DebuggerNonUserCode] + public class SimpleTimeSpanAssertions + { + public SimpleTimeSpanAssertions(TimeSpan? value) + { + Subject = value; + } + + /// + /// Gets the object which value is being asserted. + /// + public TimeSpan? Subject + { + get; + private set; + } + + /// + /// Asserts that the time difference of the current is greater than zero. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BePositive(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.Value.CompareTo(new TimeSpan()) > 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected positive value{reason}, but found {0}", Subject.Value); + + return new AndConstraint(this); + } + + /// + /// Asserts that the time difference of the current is less than zero. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeNegative(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.Value.CompareTo(new TimeSpan()) < 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected negative value{reason}, but found {0}", Subject.Value); + + return new AndConstraint(this); + } + + /// + /// Asserts that the time difference of the current is equal to the + /// specified time. + /// + /// The expected time difference + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Be(TimeSpan expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.Value.CompareTo(expected) == 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {0}{reason}, but found {1}.", expected, Subject.Value); + + return new AndConstraint(this); + } + + /// + /// Asserts that the time difference of the current is not equal to the + /// specified time. + /// + /// The unexpected time difference + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBe(TimeSpan unexpected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.Value.CompareTo(unexpected) != 0) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect {0}{reason}.", unexpected); + + return new AndConstraint(this); + } + + /// + /// Asserts that the time difference of the current is less than the + /// specified time. + /// + /// The time difference to which the current value will be compared + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeLessThan(TimeSpan expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.Value.CompareTo(expected) < 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a value less than {0}{reason}, but found {1}.", expected, Subject.Value); + + return new AndConstraint(this); + } + + /// + /// Asserts that the time difference of the current is less than or equal to the + /// specified time. + /// + /// The time difference to which the current value will be compared + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeLessOrEqualTo(TimeSpan expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.Value.CompareTo(expected) <= 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a value less or equal to {0}{reason}, but found {1}.", expected, Subject.Value); + + return new AndConstraint(this); + } + + /// + /// Asserts that the time difference of the current is greater than the + /// specified time. + /// + /// The time difference to which the current value will be compared + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeGreaterThan(TimeSpan expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.Value.CompareTo(expected) > 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a value greater than {0}{reason}, but found {1}.", expected, Subject.Value); + + return new AndConstraint(this); + } + + /// + /// Asserts that the time difference of the current is greater than or equal to the + /// specified time. + /// + /// The time difference to which the current value will be compared + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeGreaterOrEqualTo(TimeSpan expected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.Value.CompareTo(expected) >= 0) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a value greater or equal to {0}{reason}, but found {1}.", expected, Subject.Value); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is within the specified number of milliseconds (default = 20 ms) + /// from the specified value. + /// + /// + /// Use this assertion when, for example the database truncates datetimes to nearest 20ms. If you want to assert to the exact datetime, + /// use . + /// + /// + /// The expected time to compare the actual value with. + /// + /// + /// The maximum amount of milliseconds which the two values may differ. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeCloseTo(TimeSpan nearbyTime, int precision = 20, string because = "", + params object[] becauseArgs) + { + var minimumValue = new TimeSpan(nearbyTime.Days, nearbyTime.Hours, nearbyTime.Minutes, nearbyTime.Seconds, nearbyTime.Milliseconds - precision); + var maximumValue = new TimeSpan(nearbyTime.Days, nearbyTime.Hours, nearbyTime.Minutes, nearbyTime.Seconds, nearbyTime.Milliseconds + precision); + + Execute.Assertion + .ForCondition(Subject.HasValue && (Subject.Value >= minimumValue) && (Subject.Value <= maximumValue)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:time} to be within {0} ms from {1}{reason}, but found {2}.", precision, + nearbyTime, Subject.HasValue ? Subject.Value : default(TimeSpan?)); + + return new AndConstraint(this); + } + } +} diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/SimpleTimeSpanAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/SimpleTimeSpanAssertions.cs.meta new file mode 100644 index 0000000..7e94b6d --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/SimpleTimeSpanAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d8da154ef0d01964a817115ab67da5c6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/StringAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/StringAssertions.cs new file mode 100644 index 0000000..8549ee2 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/StringAssertions.cs @@ -0,0 +1,888 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text.RegularExpressions; +using FluentAssertions.Execution; + +using System.Linq; +using JetBrains.Annotations; + +namespace FluentAssertions.Primitives +{ + /// + /// Contains a number of methods to assert that a is in the expected state. + /// + [DebuggerNonUserCode] + public class StringAssertions : ReferenceTypeAssertions + { + /// + /// Initializes a new instance of the class. + /// + public StringAssertions(string value) + { + Subject = value; + } + + /// + /// Asserts that a string is exactly the same as another string, including the casing and any leading or trailing whitespace. + /// + /// The expected string. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Be(string expected, string because = "", params object[] becauseArgs) + { + new StringEqualityValidator(Subject, expected, StringComparison.CurrentCulture, because, becauseArgs).Validate(); + + return new AndConstraint(this); + } + + /// + /// Asserts that the is one of the specified . + /// + /// + /// The values that are valid. + /// + public AndConstraint BeOneOf(params string[] validValues) + { + return BeOneOf(validValues, String.Empty); + } + + /// + /// Asserts that the is one of the specified . + /// + /// + /// The values that are valid. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeOneOf(IEnumerable validValues, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(validValues.Contains(Subject)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected value to be one of {0}{reason}, but found {1}.", validValues, Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string is exactly the same as another string, including any leading or trailing whitespace, with + /// the exception of the casing. + /// + /// + /// The string that the subject is expected to be equivalent to. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeEquivalentTo(string expected, string because = "", + params object[] becauseArgs) + { + var expectation = new StringEqualityValidator( + Subject, expected, StringComparison.CurrentCultureIgnoreCase, because, becauseArgs); + + expectation.Validate(); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string is not exactly the same as the specified , + /// including any leading or trailing whitespace, with the exception of the casing. + /// + /// The string that the subject is not expected to be equivalent to. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBe(string unexpected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject != unexpected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected string not to be {0}{reason}.", unexpected); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string matches a wildcard pattern. + /// + /// + /// The wildcard pattern with which the subject is matched, where * and ? have special meanings. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Match(string wildcardPattern, string because = "", params object[] becauseArgs) + { + new StringWildcardMatchingValidator(Subject, wildcardPattern, because, becauseArgs).Validate(); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string does not match a wildcard pattern. + /// + /// + /// The wildcard pattern with which the subject is matched, where * and ? have special meanings. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotMatch(string wildcardPattern, string because = "", params object[] becauseArgs) + { + new StringWildcardMatchingValidator(Subject, wildcardPattern, because, becauseArgs) + { + Negate = true + }.Validate(); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string matches a wildcard pattern. + /// + /// + /// The wildcard pattern with which the subject is matched, where * and ? have special meanings. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint MatchEquivalentOf(string wildcardPattern, string because = "", + params object[] becauseArgs) + { + var validator = new StringWildcardMatchingValidator(Subject, wildcardPattern, because, becauseArgs) + { + IgnoreCase = true, + IgnoreNewLineDifferences = true + }; + + validator.Validate(); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string does not match a wildcard pattern. + /// + /// + /// The wildcard pattern with which the subject is matched, where * and ? have special meanings. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotMatchEquivalentOf(string wildcardPattern, string because = "", + params object[] becauseArgs) + { + var validator = new StringWildcardMatchingValidator(Subject, wildcardPattern, because, becauseArgs) + { + IgnoreCase = true, + IgnoreNewLineDifferences = true, + Negate = true + }; + + validator.Validate(); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string matches a regular expression. + /// + /// + /// The regular expression with which the subject is matched. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint MatchRegex(string regularExpression, string because = "", params object[] becauseArgs) + { + if (regularExpression == null) + { + throw new NullReferenceException("Cannot match string against ."); + } + + Execute.Assertion + .ForCondition(!ReferenceEquals(Subject, null)) + .UsingLineBreaks + .BecauseOf(because, becauseArgs) + .FailWith("Expected string to match regex {0}{reason}, but it was .", regularExpression); + + bool isMatch; + try + { + isMatch = Regex.IsMatch(Subject, regularExpression); + } + catch (ArgumentException) + { + throw new ArgumentException( + string.Format( + "Cannot match string against \"{0}\" because it is not a valid regular expression.", + regularExpression)); + } + + Execute.Assertion + .ForCondition(isMatch) + .BecauseOf(because, becauseArgs) + .UsingLineBreaks + .FailWith("Expected string to match regex {0}{reason}, but {1} does not match.", regularExpression, Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string does not match a regular expression. + /// + /// + /// The regular expression with which the subject is matched. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotMatchRegex(string regularExpression, string because = "", params object[] becauseArgs) + { + if (regularExpression == null) + { + throw new NullReferenceException("Cannot match string against ."); + } + + Execute.Assertion + .ForCondition(!ReferenceEquals(Subject, null)) + .UsingLineBreaks + .BecauseOf(because, becauseArgs) + .FailWith("Expected string to not match regex {0}{reason}, but it was .", regularExpression); + + bool isMatch; + try + { + isMatch = Regex.IsMatch(Subject, regularExpression); + } + catch (ArgumentException) + { + throw new ArgumentException( + string.Format( + "Cannot match string against \"{0}\" because it is not a valid regular expression.", + regularExpression)); + } + + Execute.Assertion + .ForCondition(!isMatch) + .BecauseOf(because, becauseArgs) + .UsingLineBreaks + .FailWith("Did not expect string to match regex {0}{reason}, but {1} matches.", regularExpression, Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string starts exactly with the specified value, + /// including the casing and any leading or trailing whitespace. + /// + /// The string that the subject is expected to start with. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint StartWith(string expected, string because = "", params object[] becauseArgs) + { + if (expected == null) + { + throw new NullReferenceException("Cannot compare start of string with ."); + } + + if (expected.Length == 0) + { + throw new ArgumentException("Cannot compare start of string with empty string."); + } + + new StringStartValidator(Subject, expected, StringComparison.CurrentCulture, because, becauseArgs).Validate(); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string does not start with the specified value, + /// including the casing and any leading or trailing whitespace. + /// + /// The string that the subject is not expected to start with. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotStartWith(string unexpected, string because = "", params object[] becauseArgs) + { + if (unexpected == null) + { + throw new NullReferenceException("Cannot compare start of string with ."); + } + + if (unexpected.Length == 0) + { + throw new ArgumentException("Cannot compare start of string with empty string."); + } + + new NegatedStringStartValidator(Subject, unexpected, StringComparison.CurrentCulture, because, becauseArgs).Validate(); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string starts with the specified , + /// including any leading or trailing whitespace, with the exception of the casing. + /// + /// The string that the subject is expected to start with. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint StartWithEquivalent(string expected, string because = "", + params object[] becauseArgs) + { + if (expected == null) + { + throw new NullReferenceException("Cannot compare string start equivalence with ."); + } + + if (expected.Length == 0) + { + throw new ArgumentException("Cannot compare string start equivalence with empty string."); + } + + new StringStartValidator(Subject, expected, StringComparison.CurrentCultureIgnoreCase, because, becauseArgs).Validate(); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string does not start with the specified value, + /// including any leading or trailing whitespace, with the exception of the casing. + /// + /// The string that the subject is not expected to start with. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotStartWithEquivalentOf(string unexpected, string because = "", params object[] becauseArgs) + { + if (unexpected == null) + { + throw new NullReferenceException("Cannot compare start of string with ."); + } + + if (unexpected.Length == 0) + { + throw new ArgumentException("Cannot compare start of string with empty string."); + } + + new NegatedStringStartValidator(Subject, unexpected, StringComparison.CurrentCultureIgnoreCase, because, becauseArgs).Validate(); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string ends exactly with the specified , + /// including the casing and any leading or trailing whitespace. + /// + /// The string that the subject is expected to end with. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint EndWith(string expected, string because = "", params object[] becauseArgs) + { + if (expected == null) + { + throw new NullReferenceException("Cannot compare string end with ."); + } + + if (expected.Length == 0) + { + throw new ArgumentException("Cannot compare string end with empty string."); + } + + if (Subject == null) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected string {0} to end with {1}{reason}.", Subject, expected); + } + + if (Subject.Length < expected.Length) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected string to end with {0}{reason}, but {1} is too short.", expected, Subject); + } + + Execute.Assertion + .ForCondition(Subject.EndsWith(expected)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected string {0} to end with {1}{reason}.", Subject, expected); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string does not end exactly with the specified , + /// including the casing and any leading or trailing whitespace. + /// + /// The string that the subject is not expected to end with. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotEndWith(string unexpected, string because = "", params object[] becauseArgs) + { + if (unexpected == null) + { + throw new NullReferenceException("Cannot compare end of string with ."); + } + + if (unexpected.Length == 0) + { + throw new ArgumentException("Cannot compare end of string with empty string."); + } + + if (Subject == null) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected string that does not end with {1}, but found {0}.", Subject, unexpected); + } + + Execute.Assertion + .ForCondition(!Subject.EndsWith(unexpected)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected string {0} not to end with {1}{reason}.", Subject, unexpected); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string ends with the specified , + /// including any leading or trailing whitespace, with the exception of the casing. + /// + /// The string that the subject is expected to end with. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint EndWithEquivalent(string expected, string because = "", params object[] becauseArgs) + { + if (expected == null) + { + throw new NullReferenceException("Cannot compare string end equivalence with ."); + } + + if (expected.Length == 0) + { + throw new ArgumentException("Cannot compare string end equivalence with empty string."); + } + + if (Subject == null) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected string that ends with equivalent of {0}{reason}, but found {1}.", expected, Subject); + } + + if (Subject.Length < expected.Length) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected string to end with equivalent of {0}{reason}, but {1} is too short.", expected, Subject); + } + + Execute.Assertion + .ForCondition(Subject.EndsWith(expected, StringComparison.CurrentCultureIgnoreCase)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected string that ends with equivalent of {0}{reason}, but found {1}.", expected, Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string does not end with the specified , + /// including any leading or trailing whitespace, with the exception of the casing. + /// + /// The string that the subject is not expected to end with. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotEndWithEquivalentOf(string unexpected, string because = "", params object[] becauseArgs) + { + if (unexpected == null) + { + throw new NullReferenceException("Cannot compare end of string with ."); + } + + if (unexpected.Length == 0) + { + throw new ArgumentException("Cannot compare end of string with empty string."); + } + + if (Subject == null) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected string that does not end with equivalent of {0}, but found {1}.", unexpected, Subject); + } + + Execute.Assertion + .ForCondition(!Subject.EndsWith(unexpected, StringComparison.CurrentCultureIgnoreCase)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected string that does not end with equivalent of {0}{reason}, but found {1}.", unexpected, Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string contains another (fragment of a) string. + /// + /// + /// The (fragment of a) string that the current string should contain. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Contain(string expected, string because = "", params object[] becauseArgs) + { + if (expected == null) + { + throw new ArgumentException("Cannot assert string containment against ."); + } + + if (expected.Length == 0) + { + throw new ArgumentException("Cannot assert string containment against an empty string."); + } + + Execute.Assertion + .ForCondition(Contains(Subject, expected, StringComparison.Ordinal)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected string {0} to contain {1}{reason}.", Subject, expected); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string contains the specified , + /// including any leading or trailing whitespace, with the exception of the casing. + /// + /// The string that the subject is expected to contain. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint ContainEquivalentOf(string expected, string because = "", params object[] becauseArgs) + { + if (expected == null) + { + throw new ArgumentException("Cannot assert string containment against ."); + } + + if (expected.Length == 0) + { + throw new ArgumentException("Cannot assert string containment against an empty string."); + } + + Execute.Assertion + .ForCondition(Contains(Subject, expected, StringComparison.CurrentCultureIgnoreCase)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected string to contain equivalent of {0}{reason} but found {1}", expected, Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string does not contain another (fragment of a) string. + /// + /// + /// The (fragment of a) string that the current string should not contain. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotContain(string expected, string because = "", + params object[] becauseArgs) + { + if (expected == null) + { + throw new ArgumentException("Cannot assert string containment against ."); + } + + if (expected.Length == 0) + { + throw new ArgumentException("Cannot assert string containment against an empty string."); + } + + Execute.Assertion + .ForCondition(!Contains(Subject, expected, StringComparison.Ordinal)) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect string {0} to contain {1}{reason}.", Subject, expected); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string does not contain the specified string, + /// including any leading or trailing whitespace, with the exception of the casing. + /// + /// The string that the subject is not expected to contain. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotContainEquivalentOf(string unexpected, string because = "", + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!Contains(Subject, unexpected, StringComparison.CurrentCultureIgnoreCase)) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect string to contain equivalent of {0}{reason} but found {1}", unexpected, Subject); + + return new AndConstraint(this); + } + + static bool Contains(string actual, string expected, StringComparison comparison) + { + return (actual ?? "").IndexOf(expected ?? "", comparison) >= 0; + } + + /// + /// Asserts that a string is . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeEmpty(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition((Subject != null) && (Subject.Length == 0)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected empty string{reason}, but found {0}.", Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string is not . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeEmpty(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.Length > 0) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect empty string{reason}."); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string has the specified length. + /// + /// The expected length of the string + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveLength(int expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.Length == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected string with length {0}{reason}, but found string {1} with length {2}.", + expected, Subject, Subject.Length); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string is neither null nor . + /// + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public AndConstraint NotBeNullOrEmpty(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!string.IsNullOrEmpty(Subject)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected string not to be or empty{reason}, but found {0}.", Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string is either null or . + /// + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public AndConstraint BeNullOrEmpty(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(string.IsNullOrEmpty(Subject)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected string to be or empty{reason}, but found {0}.", Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string is neither null nor nor white space + /// + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public AndConstraint NotBeNullOrWhiteSpace(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!IsBlank(Subject)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected string not to be or whitespace{reason}, but found {0}.", Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a string is either null or or white space + /// + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public AndConstraint BeNullOrWhiteSpace(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(IsBlank(Subject)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected string to be or whitespace{reason}, but found {0}.", Subject); + + return new AndConstraint(this); + } + + private static bool IsBlank(string value) + { + return (value == null) || string.IsNullOrEmpty(value.Trim()); + } + + /// + /// Returns the type of the subject the assertion applies on. + /// + protected override string Context + { + get { return "string"; } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/StringAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/StringAssertions.cs.meta new file mode 100644 index 0000000..35a4682 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/StringAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 28fa804c1a05b474ab0dbf1a8e817678 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/StringEqualityValidator.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/StringEqualityValidator.cs new file mode 100644 index 0000000..3816b8e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/StringEqualityValidator.cs @@ -0,0 +1,68 @@ +using System; +using FluentAssertions.Common; + +namespace FluentAssertions.Primitives +{ + internal class StringEqualityValidator : StringValidator + { + private readonly StringComparison comparisonMode; + + public StringEqualityValidator(string subject, string expected, StringComparison comparisonMode, string because, + object[] becauseArgs) : + base(subject, expected, because, becauseArgs) + { + this.comparisonMode = comparisonMode; + } + + protected override bool ValidateAgainstSuperfluousWhitespace() + { + return assertion + .ForCondition(!((expected.Length > subject.Length) && expected.TrimEnd().Equals(subject, comparisonMode))) + .FailWith(ExpectationDescription + "{0}{reason}, but it misses some extra whitespace at the end.", expected) + .Then + .ForCondition(!((subject.Length > expected.Length) && subject.TrimEnd().Equals(expected, comparisonMode))) + .FailWith(ExpectationDescription + "{0}{reason}, but it has unexpected whitespace at the end.", expected) + .SourceSucceeded; + } + + protected override bool ValidateAgainstLengthDifferences() + { + return assertion + .ForCondition(subject.Length == expected.Length) + .FailWith( + ExpectationDescription + "{0} with a length of {1}{reason}, but {2} has a length of {3}.", + expected, expected.Length, subject, subject.Length) + .SourceSucceeded; + + } + + protected override void ValidateAgainstMismatch() + { + int indexOfMismatch = subject.IndexOfFirstMismatch(expected, comparisonMode); + if (indexOfMismatch != -1) + { + assertion.FailWith( + ExpectationDescription + "{0}{reason}, but {1} differs near " + subject.IndexedSegmentAt(indexOfMismatch) + ".", + expected, subject); + } + } + + protected override string ExpectationDescription + { + get + { + string predicateDescription = IgnoreCase ? "be equivalent to" : "be"; + return "Expected {context:string} to " + predicateDescription + " "; + } + } + + private bool IgnoreCase + { + get + { + return (comparisonMode == StringComparison.CurrentCultureIgnoreCase) || + (comparisonMode == StringComparison.OrdinalIgnoreCase); + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/StringEqualityValidator.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/StringEqualityValidator.cs.meta new file mode 100644 index 0000000..4129758 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/StringEqualityValidator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 45adad46e8ae8744982de2d4f2f2b7c5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/StringStartValidator.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/StringStartValidator.cs new file mode 100644 index 0000000..2ab724b --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/StringStartValidator.cs @@ -0,0 +1,56 @@ +using System; +using FluentAssertions.Common; + +namespace FluentAssertions.Primitives +{ + internal class StringStartValidator : StringValidator + { + private readonly StringComparison stringComparison; + + public StringStartValidator(string subject, string expected, StringComparison stringComparison, string because, + object[] becauseArgs) : + base(subject, expected, because, becauseArgs) + { + this.stringComparison = stringComparison; + } + + protected override string ExpectationDescription + { + get + { + string predicateDescription = IgnoreCase ? "start with equivalent of" : "start with"; + return "Expected {context:string} to " + predicateDescription + " "; + } + } + + private bool IgnoreCase + { + get + { + return (stringComparison == StringComparison.CurrentCultureIgnoreCase) || + (stringComparison == StringComparison.OrdinalIgnoreCase); + } + } + + protected override bool ValidateAgainstLengthDifferences() + { + return assertion + .ForCondition(subject.Length >= expected.Length) + .FailWith(ExpectationDescription + "{0}{reason}, but {1} is too short.", expected, subject) + .SourceSucceeded; + } + + protected override void ValidateAgainstMismatch() + { + bool isMismatch = !subject.StartsWith(expected, stringComparison); + if (isMismatch) + { + int indexOfMismatch = subject.IndexOfFirstMismatch(expected, stringComparison); + + assertion.FailWith( + ExpectationDescription + "{0}{reason}, but {1} differs near " + subject.IndexedSegmentAt(indexOfMismatch) + ".", + expected, subject); + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/StringStartValidator.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/StringStartValidator.cs.meta new file mode 100644 index 0000000..3c902d3 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/StringStartValidator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cc89a45aa4f105b4086624f1f3ee9c9e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/StringValidator.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/StringValidator.cs new file mode 100644 index 0000000..c932b74 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/StringValidator.cs @@ -0,0 +1,80 @@ +using System; +using FluentAssertions.Execution; + +namespace FluentAssertions.Primitives +{ + /// + /// Dedicated class for comparing two strings and generating consistent error messages. + /// + internal abstract class StringValidator + { + #region Private Definition + + protected readonly string subject; + protected readonly string expected; + protected AssertionScope assertion; + private const int HumanReadableLength = 8; + + #endregion + + protected StringValidator(string subject, string expected, string because, object[] becauseArgs) + { + assertion = Execute.Assertion.BecauseOf(because, becauseArgs); + + this.subject = subject; + this.expected = expected; + } + + public void Validate() + { + if ((expected != null) || (subject != null)) + { + if (ValidateAgainstNulls()) + { + if (IsLongOrMultiline(expected) || IsLongOrMultiline(subject)) + { + assertion = assertion.UsingLineBreaks; + } + + if (ValidateAgainstSuperfluousWhitespace()) + { + if (ValidateAgainstLengthDifferences()) + { + ValidateAgainstMismatch(); + } + } + } + } + } + + private bool ValidateAgainstNulls() + { + if (((expected == null) && (subject != null)) || ((expected != null) && (subject == null))) + { + assertion.FailWith(ExpectationDescription + "{0}{reason}, but found {1}.", expected, subject); + return false; + } + + return true; + } + + private bool IsLongOrMultiline(string value) + { + return (value.Length > HumanReadableLength) || value.Contains(Environment.NewLine); + } + + protected virtual bool ValidateAgainstSuperfluousWhitespace() + { + return true; + } + + protected virtual bool ValidateAgainstLengthDifferences() + { + return true; + } + + protected abstract void ValidateAgainstMismatch(); + + protected abstract string ExpectationDescription { get; } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/StringValidator.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/StringValidator.cs.meta new file mode 100644 index 0000000..a1dbf3b --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/StringValidator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2af5944e851c220479d91cb2b138f526 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/StringWildcardMatchingValidator.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/StringWildcardMatchingValidator.cs new file mode 100644 index 0000000..4a90185 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/StringWildcardMatchingValidator.cs @@ -0,0 +1,82 @@ +using System.Text; +using System.Text.RegularExpressions; + +using FluentAssertions.Common; + +namespace FluentAssertions.Primitives +{ + internal class StringWildcardMatchingValidator : StringValidator + { + public StringWildcardMatchingValidator(string subject, string expected, string because, object[] becauseArgs) + : base(subject, expected, because, becauseArgs) + { + } + + protected override void ValidateAgainstMismatch() + { + if (!IsMatch && !Negate) + { + assertion.FailWith(ExpectationDescription + "but {1} does not.", expected, subject); + } + + if (IsMatch && Negate) + { + assertion.FailWith(ExpectationDescription + "but {1} matches.", expected, subject); + } + } + + private bool IsMatch + { + get + { + var options = IgnoreCase ? RegexOptions.IgnoreCase : RegexOptions.None; + + return Regex.IsMatch(CleanNewLines(subject), ConvertWildcardToRegEx(CleanNewLines(expected)), options | RegexOptions.Singleline); + } + } + + private string ConvertWildcardToRegEx(string wildcardExpression) + { + return "^" + Regex.Escape(wildcardExpression).Replace("\\*", ".*").Replace("\\?", ".") + "$"; + } + + private string CleanNewLines(string input) + { + if (input == null) + { + return null; + } + + return IgnoreNewLineDifferences ? input.RemoveNewLines() : input; + } + + protected override string ExpectationDescription + { + get + { + var builder = new StringBuilder(); + builder.Append(Negate ? "Did not expect " : "Expected "); + builder.Append("{context:string}"); + builder.Append(IgnoreCase ? " to match the equivalent of" : " to match"); + builder.Append(" {0}{reason}, "); + + return builder.ToString(); + } + } + + /// + /// Gets or sets a value indicating whether the subject should not match the pattern. + /// + public bool Negate { get; set; } + + /// + /// Gets or sets a value indicating whether the matching process should ignore any casing difference. + /// + public bool IgnoreCase { get; set; } + + /// + /// Ignores the difference between environment newline differences + /// + public bool IgnoreNewLineDifferences { get; set; } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/StringWildcardMatchingValidator.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/StringWildcardMatchingValidator.cs.meta new file mode 100644 index 0000000..e466371 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/StringWildcardMatchingValidator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6a2a734d490124c4a93aea12a6d60c9e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/TimeSpanCondition.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/TimeSpanCondition.cs new file mode 100644 index 0000000..0d430eb --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/TimeSpanCondition.cs @@ -0,0 +1,11 @@ +namespace FluentAssertions.Primitives +{ + public enum TimeSpanCondition + { + MoreThan, + AtLeast, + Exactly, + Within, + LessThan + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/TimeSpanCondition.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/TimeSpanCondition.cs.meta new file mode 100644 index 0000000..91d2899 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/TimeSpanCondition.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 91697937732de104bb47768eaf1c779c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/TimeSpanPredicate.cs b/Assets/Plugins/FluentAssertions/Core/Primitives/TimeSpanPredicate.cs new file mode 100644 index 0000000..9c2dffd --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/TimeSpanPredicate.cs @@ -0,0 +1,29 @@ +using System; + +namespace FluentAssertions.Primitives +{ + /// + /// Provides the logic and the display text for a . + /// + internal class TimeSpanPredicate + { + private readonly string displayText; + private readonly Func lambda; + + public TimeSpanPredicate(Func lambda, string displayText) + { + this.lambda = lambda; + this.displayText = displayText; + } + + public string DisplayText + { + get { return displayText; } + } + + public bool IsMatchedBy(TimeSpan actual, TimeSpan expected) + { + return lambda(actual, expected); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Primitives/TimeSpanPredicate.cs.meta b/Assets/Plugins/FluentAssertions/Core/Primitives/TimeSpanPredicate.cs.meta new file mode 100644 index 0000000..2eb5879 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Primitives/TimeSpanPredicate.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: de58b29dea8496a47b5b024425d032de +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Specialized.meta b/Assets/Plugins/FluentAssertions/Core/Specialized.meta new file mode 100644 index 0000000..582ab35 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Specialized.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e94fe0d068e9f8543add6a2a40bbc246 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Specialized/ActionAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Specialized/ActionAssertions.cs new file mode 100644 index 0000000..9728bee --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Specialized/ActionAssertions.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +using FluentAssertions.Execution; +using FluentAssertions.Primitives; + +namespace FluentAssertions.Specialized +{ + /// + /// Contains a number of methods to assert that an yields the expected result. + /// + [DebuggerNonUserCode] + public class ActionAssertions : ReferenceTypeAssertions + { + private readonly IExtractExceptions extractor; + + public ActionAssertions(Action subject, IExtractExceptions extractor) + { + this.extractor = extractor; + Subject = subject; + } + + /// + /// Asserts that the current throws an exception of type . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public ExceptionAssertions ShouldThrow(string because = "", params object[] becauseArgs) + where TException : Exception + { + Exception actualException = InvokeSubjectWithInterception(); + IEnumerable expectedExceptions = extractor.OfType(actualException); + + Execute.Assertion + .ForCondition(actualException != null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a <{0}> to be thrown{reason}, but no exception was thrown.", typeof(TException)); + + Execute.Assertion + .ForCondition(expectedExceptions.Any()) + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected a <{0}> to be thrown{reason}, but found a <{1}>: {3}.", + typeof (TException), actualException.GetType(), + Environment.NewLine, + actualException); + + return new ExceptionAssertions(expectedExceptions); + } + + /// + /// Asserts that the current does not throw an exception of type . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public void ShouldNotThrow(string because = "", params object[] becauseArgs) where TException : Exception + { + Exception actualException = InvokeSubjectWithInterception(); + IEnumerable expectedExceptions = extractor.OfType(actualException); + + if (actualException != null) + { + Execute.Assertion + .ForCondition(!expectedExceptions.Any()) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect {0}{reason}, but found {1}.", typeof (TException), actualException); + } + } + + /// + /// Asserts that the current does not throw any exception. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public void ShouldNotThrow(string because = "", params object[] becauseArgs) + { + try + { + Subject(); + } + catch (Exception exception) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect any exception{reason}, but found {0}", exception); + } + } + + private Exception InvokeSubjectWithInterception() + { + Exception actualException = null; + + try + { + Subject(); + } + catch (Exception exc) + { + actualException = exc; + } + return actualException; + } + + /// + /// Returns the type of the subject the assertion applies on. + /// + protected override string Context + { + get { return "action"; } + } + } +} diff --git a/Assets/Plugins/FluentAssertions/Core/Specialized/ActionAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Specialized/ActionAssertions.cs.meta new file mode 100644 index 0000000..1c3e5bc --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Specialized/ActionAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a173ebc50ba17274199c55eba79af6e1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Specialized/AsyncFunctionAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Specialized/AsyncFunctionAssertions.cs new file mode 100644 index 0000000..97692af --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Specialized/AsyncFunctionAssertions.cs @@ -0,0 +1,158 @@ +using System; +using System.Diagnostics; +using System.Linq; +using System.Threading.Tasks; + +using FluentAssertions.Execution; + +namespace FluentAssertions.Specialized +{ + /// + /// Contains a number of methods to assert that an asynchronous method yields the expected result. + /// + [DebuggerNonUserCode] + public class AsyncFunctionAssertions + { + private readonly IExtractExceptions extractor; + + public AsyncFunctionAssertions(Func subject, IExtractExceptions extractor) + { + this.extractor = extractor; + Subject = subject; + } + + /// + /// Gets the that is being asserted. + /// + public Func Subject { get; private set; } + + /// + /// Asserts that the current throws an exception of type . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public ExceptionAssertions ShouldThrow(string because = "", params object[] becauseArgs) + where TException : Exception + { + Exception exception = InvokeSubjectWithInterception(); + var exceptions = extractor.OfType(exception); + + Execute.Assertion + .ForCondition(exception != null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {0}{reason}, but no exception was thrown.", typeof(TException)); + + Execute.Assertion + .ForCondition(exceptions.Any()) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {0}{reason}, but found {1}.", typeof(TException), exception); + + return new ExceptionAssertions(exceptions); + } + + /// + /// Asserts that the current does not throw any exception. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public void ShouldNotThrow(string because = "", params object[] becauseArgs) + { + try + { +#if NETSTANDARD1_3 + Task.Run(Subject).Wait(); +#else + Task.Factory.StartNew(() => Subject().Wait()).Wait(); +#endif + } + catch (Exception exception) + { + while (exception is AggregateException) + { + exception = exception.InnerException; + } + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect any exception{reason}, but found a {0} with message {1}.", + exception.GetType(), exception.Message); + } + } + + /// + /// Asserts that the current does not throw an exception of type . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public void ShouldNotThrow(string because = "", params object[] becauseArgs) + { + try + { +#if NETSTANDARD1_3 + Task.Run(Subject).Wait(); +#else + Task.Factory.StartNew(() => Subject().Wait()).Wait(); +#endif + } + catch (Exception exception) + { + while (exception is AggregateException) + { + exception = exception.InnerException; + } + + if (exception != null) + { + Execute.Assertion + .ForCondition(!(exception is TException)) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect {0}{reason}, but found one with message {1}.", + typeof(TException), exception.Message); + } + } + } + + private Exception InvokeSubjectWithInterception() + { + Exception actualException = null; + + try + { +#if NETSTANDARD1_3 + Task.Run(Subject).Wait(); +#else + Task.Factory.StartNew(() => Subject().Wait()).Wait(); +#endif + } + catch (Exception exception) + { + var ar = exception as AggregateException; + if (ar?.InnerException is AggregateException) + { + actualException = ar.InnerException; + } + else + { + actualException = exception; + } + } + + return actualException; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Specialized/AsyncFunctionAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Specialized/AsyncFunctionAssertions.cs.meta new file mode 100644 index 0000000..08ca98d --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Specialized/AsyncFunctionAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 65f08ea38e75a4a49a21f62c0f5743bf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Specialized/ExceptionAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Specialized/ExceptionAssertions.cs new file mode 100644 index 0000000..d1649e9 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Specialized/ExceptionAssertions.cs @@ -0,0 +1,277 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Linq.Expressions; + +using FluentAssertions.Common; +using FluentAssertions.Equivalency; +using FluentAssertions.Execution; +using FluentAssertions.Formatting; +using FluentAssertions.Primitives; + +namespace FluentAssertions.Specialized +{ + /// + /// Contains a number of methods to assert that an is in the correct state. + /// + [DebuggerNonUserCode] + public class ExceptionAssertions : + ReferenceTypeAssertions, ExceptionAssertions> + where TException : Exception + { + #region Private Definitions + + private static readonly ExceptionMessageAssertion outerMessageAssertion = new ExceptionMessageAssertion(); + + private static readonly ExceptionMessageAssertion innerMessageAssertion = new ExceptionMessageAssertion + { + Context = "inner exception message" + }; + + #endregion + + public ExceptionAssertions(IEnumerable exceptions) + { + Subject = exceptions; + } + + /// + /// Gets the exception object of the exception thrown. + /// + public TException And + { + get { return SingleSubject; } + } + + /// + /// Gets the exception object of the exception thrown. + /// + public TException Which + { + get { return And; } + } + + /// + /// Returns the type of the subject the assertion applies on. + /// + protected override string Context + { + get { return "exception"; } + } + + /// + /// Asserts that the thrown exception has a message that matches + /// depending on the specified matching mode. + /// + /// + /// The expected message of the exception. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public virtual ExceptionAssertions WithMessage(string expectedMessage, string because = "", + params object[] becauseArgs) + { + AssertionScope assertion = Execute.Assertion.BecauseOf(because, becauseArgs).UsingLineBreaks; + + assertion + .ForCondition(Subject.Any()) + .FailWith("Expected exception with message {0}{reason}, but no exception was thrown.", expectedMessage); + + outerMessageAssertion.Execute(Subject.Select(exc => exc.Message).ToArray(), expectedMessage, because, becauseArgs); + + return this; + } + + /// + /// Asserts that the thrown exception contains an inner exception of type . + /// + /// The expected type of the inner exception. + public ExceptionAssertions WithInnerException() + { + return WithInnerException(null, null); + } + + /// + /// Asserts that the thrown exception contains an inner exception of the exact type (and not a derived exception type). + /// + /// The expected type of the inner exception. + public ExceptionAssertions WithInnerExceptionExactly() + { + return WithInnerExceptionExactly(null, null); + } + + /// + /// Asserts that the thrown exception contains an inner exception of type . + /// + /// The expected type of the inner exception. + /// The reason why the inner exception should be of the supplied type. + /// The parameters used when formatting the . + public virtual ExceptionAssertions WithInnerException(string because, + params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject != null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected inner {0}{reason}, but no exception was thrown.", typeof(TInnerException)); + + Execute.Assertion + .ForCondition(Subject.Any(e => e.InnerException != null)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected inner {0}{reason}, but the thrown exception has no inner exception.", + typeof(TInnerException)); + + Execute.Assertion + .ForCondition(Subject.Any(e => e.InnerException is TInnerException)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected inner {0}{reason}, but found {1}.", typeof(TInnerException), SingleSubject.InnerException); + + return this; + } + + /// + /// Asserts that the thrown exception contains an inner exception of the exact type (and not a derived exception type). + /// + /// The expected type of the inner exception. + /// The reason why the inner exception should be of the supplied type. + /// The parameters used when formatting the . + public virtual ExceptionAssertions WithInnerExceptionExactly(string because, + params object[] becauseArgs) + { + WithInnerException(because, becauseArgs); + + Execute.Assertion + .ForCondition(Subject.Any(e => e.InnerException.GetType() == typeof(TInnerException))) + .BecauseOf(because, becauseArgs) + .FailWith("Expected inner {0}{reason}, but found {1}.", typeof(TInnerException), SingleSubject.InnerException); + + return this; + } + + /// + /// Asserts that the thrown exception contains an inner exception with the . + /// + /// The expected message of the inner exception. + /// + /// The reason why the message of the inner exception should match . + /// + /// The parameters used when formatting the . + public virtual ExceptionAssertions WithInnerMessage(string expectedInnerMessage, string because = "", + params object[] becauseArgs) + { + AssertionScope assertion = Execute.Assertion + .BecauseOf(because, becauseArgs) + .UsingLineBreaks; + + assertion + .ForCondition(Subject.Any()) + .FailWith("Expected inner exception{reason}, but no exception was thrown."); + + assertion + .ForCondition(Subject.Any(e => e.InnerException != null)) + .FailWith("Expected inner exception{reason}, but the thrown exception has no inner exception."); + + string[] subjectInnerMessage = Subject.Select(e => e.InnerException.Message).ToArray(); + + innerMessageAssertion.Execute(subjectInnerMessage, expectedInnerMessage, because, becauseArgs); + + return this; + } + + /// + /// Asserts that the exception matches a particular condition. + /// + /// + /// The condition that the exception must match. + /// + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public ExceptionAssertions Where(Expression> exceptionExpression, + string because = "", params object[] becauseArgs) + { + Func condition = exceptionExpression.Compile(); + Execute.Assertion + .ForCondition(condition(SingleSubject)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected exception where {0}{reason}, but the condition was not met by:\r\n\r\n{1}", + exceptionExpression.Body, Subject); + + return this; + } + + private TException SingleSubject + { + get + { + if (Subject.Count() > 1) + { + string thrownExceptions = BuildExceptionsString(Subject); + Services.ThrowException( + string.Format( + "More than one exception was thrown. FluentAssertions cannot determine which Exception was meant.{0}{1}", + Environment.NewLine, thrownExceptions)); + } + + return Subject.Single(); + } + } + + private static string BuildExceptionsString(IEnumerable exceptions) + { + return string.Join(Environment.NewLine, + exceptions.Select( + exception => + "\t" + Formatter.ToString(exception))); + } + + private class ExceptionMessageAssertion + { + public ExceptionMessageAssertion() + { + Context = "exception message"; + } + + public string Context { get; set; } + + public void Execute(IEnumerable messages, string expectation, string because, params object[] becauseArgs) + { + using (new AssertionScope()) + { + var results = new AssertionResultSet(); + + foreach (string message in messages) + { + using (var scope = new AssertionScope()) + { + scope.AddNonReportable("context", Context); + + message.Should().MatchEquivalentOf(expectation, because, becauseArgs); + + results.AddSet(message, scope.Discard()); + } + + if (results.ContainsSuccessfulSet) + { + break; + } + } + + foreach (string failure in results.SelectClosestMatchFor()) + { + AssertionScope.Current.FailWith(failure.Replace("{", "{{").Replace("}", "}}")); + } + } + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Specialized/ExceptionAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Specialized/ExceptionAssertions.cs.meta new file mode 100644 index 0000000..b5e3bf0 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Specialized/ExceptionAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8c4d3651b255c924bac9461db7916270 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Specialized/IExtractExceptions.cs b/Assets/Plugins/FluentAssertions/Core/Specialized/IExtractExceptions.cs new file mode 100644 index 0000000..dacb371 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Specialized/IExtractExceptions.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; + +namespace FluentAssertions.Specialized +{ + public interface IExtractExceptions + { + IEnumerable OfType(Exception actualException) where T : Exception; + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Specialized/IExtractExceptions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Specialized/IExtractExceptions.cs.meta new file mode 100644 index 0000000..02997a8 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Specialized/IExtractExceptions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5963a1713fdf019449e17eaad5e32918 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/TimeSpanConversionExtensions.cs b/Assets/Plugins/FluentAssertions/Core/TimeSpanConversionExtensions.cs new file mode 100644 index 0000000..8045503 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/TimeSpanConversionExtensions.cs @@ -0,0 +1,120 @@ +using System; +using FluentAssertions.Common; + +namespace FluentAssertions +{ + /// + /// Extension methods on to allow for a more fluent way of specifying a . + /// + /// + /// Instead of
+ ///
+ /// TimeSpan.FromHours(12)
+ ///
+ /// you can write
+ ///
+ /// 12.Hours()
+ ///
+ /// Or even
+ ///
+ /// 12.Hours().And(30.Minutes()). + ///
+ /// + public static class TimeSpanConversionExtensions + { + /// + /// Returns a based on a number of ticks. + /// + public static TimeSpan Ticks(this int ticks) + { + return TimeSpan.FromTicks(ticks); + } + + /// + /// Returns a based on a number of milliseconds. + /// + public static TimeSpan Milliseconds(this int milliseconds) + { + return TimeSpan.FromMilliseconds(milliseconds); + } + + /// + /// Returns a based on a number of seconds. + /// + public static TimeSpan Seconds(this int seconds) + { + return TimeSpan.FromSeconds(seconds); + } + + /// + /// Returns a based on a number of seconds, and add the specified + /// . + /// + public static TimeSpan Seconds(this int seconds, TimeSpan offset) + { + return TimeSpan.FromSeconds(seconds).Add(offset); + } + + /// + /// Returns a based on a number of minutes. + /// + public static TimeSpan Minutes(this int minutes) + { + return TimeSpan.FromMinutes(minutes); + } + + /// + /// Returns a based on a number of minutes, and add the specified + /// . + /// + public static TimeSpan Minutes(this int minutes, TimeSpan offset) + { + return TimeSpan.FromMinutes(minutes).Add(offset); + } + + /// + /// Returns a based on a number of hours. + /// + public static TimeSpan Hours(this int hours) + { + return TimeSpan.FromHours(hours); + } + + /// + /// Returns a based on a number of hours, and add the specified + /// . + /// + public static TimeSpan Hours(this int hours, TimeSpan offset) + { + return TimeSpan.FromHours(hours).Add(offset); + } + + /// + /// Returns a based on a number of days. + /// + public static TimeSpan Days(this int days) + { + return TimeSpan.FromDays(days); + } + + /// + /// Returns a based on a number of days, and add the specified + /// . + /// + public static TimeSpan Days(this int days, TimeSpan offset) + { + return TimeSpan.FromDays(days).Add(offset); + } + + /// + /// Convenience method for chaining multiple calls to the methods provided by this class. + /// + /// + /// 23.Hours().And(59.Minutes()) + /// + public static TimeSpan And(this TimeSpan sourceTime, TimeSpan offset) + { + return sourceTime.Add(offset); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/TimeSpanConversionExtensions.cs.meta b/Assets/Plugins/FluentAssertions/Core/TimeSpanConversionExtensions.cs.meta new file mode 100644 index 0000000..570892e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/TimeSpanConversionExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 12ca8999a2e2d6b4ab1f9050eea6317f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Tracing.meta b/Assets/Plugins/FluentAssertions/Core/Tracing.meta new file mode 100644 index 0000000..a7cfe4f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Tracing.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e526810b3acf1f546a5634599c102e6b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Tracing/ITraceWriter.cs b/Assets/Plugins/FluentAssertions/Core/Tracing/ITraceWriter.cs new file mode 100644 index 0000000..74534b0 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Tracing/ITraceWriter.cs @@ -0,0 +1,14 @@ +using System; + +namespace FluentAssertions.Equivalency +{ + /// + /// Defines the contract for an object that is used by Fluent Assertions to provide tracing in the equivalency API + /// + public interface ITraceWriter + { + void AddSingle(string trace); + IDisposable AddBlock(string trace); + string ToString(); + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Tracing/ITraceWriter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Tracing/ITraceWriter.cs.meta new file mode 100644 index 0000000..e9b04a5 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Tracing/ITraceWriter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 968f37afc0d5f084387bf4f9f6d7eb0c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Tracing/StringBuilderTraceWriter.cs b/Assets/Plugins/FluentAssertions/Core/Tracing/StringBuilderTraceWriter.cs new file mode 100644 index 0000000..15b5770 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Tracing/StringBuilderTraceWriter.cs @@ -0,0 +1,42 @@ +using System; +using System.Text; + +namespace FluentAssertions.Equivalency +{ + public class StringBuilderTraceWriter : ITraceWriter + { + private readonly StringBuilder builder = new StringBuilder(); + private int depth = 1; + + public void AddSingle(string trace) + { + WriteLine(trace); + } + + public IDisposable AddBlock(string trace) + { + WriteLine(trace); + WriteLine("{"); + depth++; + + return new Disposable(() => + { + depth--; + WriteLine("}"); + }); + } + + private void WriteLine(string trace) + { + foreach (string traceLine in trace.Split(new[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)) + { + builder.AppendLine(new string(' ', depth * 2) + traceLine); + } + } + + public override string ToString() + { + return builder.ToString(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Tracing/StringBuilderTraceWriter.cs.meta b/Assets/Plugins/FluentAssertions/Core/Tracing/StringBuilderTraceWriter.cs.meta new file mode 100644 index 0000000..41ff505 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Tracing/StringBuilderTraceWriter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 21082576ed8b84a49b8efd7d81538ae6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/TypeEnumerableExtensions.cs b/Assets/Plugins/FluentAssertions/Core/TypeEnumerableExtensions.cs new file mode 100644 index 0000000..d1a8dea --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/TypeEnumerableExtensions.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; + +using FluentAssertions.Types; + +namespace FluentAssertions +{ + /// + /// Extension methods for filtering a collection of types. + /// + public static class TypeEnumerableExtensions + { + /// + /// Filters to only include types decorated with a particular attribute. + /// + public static IEnumerable ThatAreDecoratedWith(this IEnumerable types) + { + return new TypeSelector(types).ThatAreDecoratedWith(); + } + + /// + /// Filters to only include types where the namespace of type is exactly . + /// + public static IEnumerable ThatAreInNamespace(this IEnumerable types, string @namespace) + { + return new TypeSelector(types).ThatAreInNamespace(@namespace); + } + + /// + /// Filters to only include types where the namespace of type is starts with . + /// + public static IEnumerable ThatAreUnderNamespace(this IEnumerable types, string @namespace) + { + return new TypeSelector(types).ThatAreUnderNamespace(@namespace); + } + + /// + /// Filters to only include types that subclass the specified type, but NOT the same type. + /// + public static IEnumerable ThatDeriveFrom(this IEnumerable types) + { + return new TypeSelector(types).ThatDeriveFrom(); + } + + /// + /// Determines whether a type implements an interface (but is not the interface itself). + /// + public static IEnumerable ThatImplement(this IEnumerable types) + { + return new TypeSelector(types).ThatImplement(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/TypeEnumerableExtensions.cs.meta b/Assets/Plugins/FluentAssertions/Core/TypeEnumerableExtensions.cs.meta new file mode 100644 index 0000000..289341a --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/TypeEnumerableExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 12f702f6e235ce4468afb91ba0c65563 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/TypeExtensions.cs b/Assets/Plugins/FluentAssertions/Core/TypeExtensions.cs new file mode 100644 index 0000000..558ae2d --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/TypeExtensions.cs @@ -0,0 +1,56 @@ +using System; +using System.Diagnostics; +using System.Linq; +using System.Reflection; + +using FluentAssertions.Types; + +namespace FluentAssertions +{ + /// + /// Extension methods for getting method and property selectors for a type. + /// + [DebuggerNonUserCode] + public static class TypeExtensions + { + /// + /// Returns the types that are visible outside the specified . + /// + public static TypeSelector Types(this Assembly assembly) + { + return new TypeSelector(assembly.GetTypes()); + } + + /// + /// Returns a method selector for the current . + /// + public static MethodInfoSelector Methods(this Type type) + { + return new MethodInfoSelector(type); + } + + /// + /// Returns a method selector for the current . + /// + public static MethodInfoSelector Methods(this TypeSelector typeSelector) + { + return new MethodInfoSelector(typeSelector.ToList()); + } + + /// + /// Returns a property selector for the current . + /// + public static PropertyInfoSelector Properties(this Type type) + { + return new PropertyInfoSelector(type); + } + + /// + /// Returns a property selector for the current . + /// + public static PropertyInfoSelector Properties(this TypeSelector typeSelector) + { + return new PropertyInfoSelector(typeSelector.ToList()); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/TypeExtensions.cs.meta b/Assets/Plugins/FluentAssertions/Core/TypeExtensions.cs.meta new file mode 100644 index 0000000..105e2de --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/TypeExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0262ae43a2ee20a44b04ffa7fa7f1733 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Types.meta b/Assets/Plugins/FluentAssertions/Core/Types.meta new file mode 100644 index 0000000..3c07ff6 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ed64a45f05814724e9bf8cf9309a1117 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Types/AllTypes.cs b/Assets/Plugins/FluentAssertions/Core/Types/AllTypes.cs new file mode 100644 index 0000000..8433419 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/AllTypes.cs @@ -0,0 +1,26 @@ +using System.Reflection; + +namespace FluentAssertions.Types +{ + /// + /// Static class that allows for a 'fluent' selection of the types from an . + /// + /// + /// AllTypes.From(myAssembly)
+ /// .ThatImplement<ISomeInterface>
+ /// .Should()
+ /// .BeDecoratedWith<SomeAttribute>() + ///
+ public static class AllTypes + { + /// + /// Returns a for selecting the types that are visible outside the + /// specified . + /// + /// The assembly from which to select the types. + public static TypeSelector From(Assembly assembly) + { + return assembly.Types(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Types/AllTypes.cs.meta b/Assets/Plugins/FluentAssertions/Core/Types/AllTypes.cs.meta new file mode 100644 index 0000000..683276e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/AllTypes.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9f2a272f03f06af488b713fdc425b683 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Types/ConstructorInfoAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Types/ConstructorInfoAssertions.cs new file mode 100644 index 0000000..5897607 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/ConstructorInfoAssertions.cs @@ -0,0 +1,38 @@ +using System; +using System.Diagnostics; +using System.Reflection; + +namespace FluentAssertions.Types +{ + /// + /// Contains a number of methods to assert that a is in the expected state. + /// + [DebuggerNonUserCode] + public class ConstructorInfoAssertions : MethodBaseAssertions + { + /// + /// Initializes a new instance of the class. + /// + /// The constructorInfo from which to select properties. + public ConstructorInfoAssertions(ConstructorInfo constructorInfo) + { + Subject = constructorInfo; + } + + internal static string GetDescriptionFor(ConstructorInfo constructorInfo) + { + return String.Format("{0}({1})", + constructorInfo.DeclaringType, GetParameterString(constructorInfo)); + } + + internal override string SubjectDescription + { + get { return GetDescriptionFor(Subject); } + } + + protected override string Context + { + get { return "constructor"; } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Types/ConstructorInfoAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Types/ConstructorInfoAssertions.cs.meta new file mode 100644 index 0000000..3b0d0f9 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/ConstructorInfoAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f31a2fd320a8ca34eb4f97d8a53912f3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Types/MemberInfoAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Types/MemberInfoAssertions.cs new file mode 100644 index 0000000..b2e5586 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/MemberInfoAssertions.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using FluentAssertions.Common; +using FluentAssertions.Execution; +using FluentAssertions.Primitives; + +namespace FluentAssertions.Types +{ + /// + /// Contains a number of methods to assert that a is in the expected state. + /// + [DebuggerNonUserCode] + public abstract class MemberInfoAssertions : ReferenceTypeAssertions + where TSubject : MemberInfo + where TAssertions : MemberInfoAssertions + { + /// + /// Asserts that the selected member is decorated with the specified . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndWhichConstraint, TAttribute> BeDecoratedWith( + string because = "", params object[] becauseArgs) + where TAttribute : Attribute + { + return BeDecoratedWith(attr => true, because, becauseArgs); + } + + /// + /// Asserts that the selected member is not decorated with the specified . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeDecoratedWith( + string because = "", params object[] becauseArgs) + where TAttribute : Attribute + { + return NotBeDecoratedWith(attr => true, because, becauseArgs); + } + + /// + /// Asserts that the selected member is decorated with an attribute of type + /// that matches the specified . + /// + /// + /// The predicate that the attribute must match. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndWhichConstraint, TAttribute> BeDecoratedWith( + Expression> isMatchingAttributePredicate, + string because = "", params object[] becauseArgs) + where TAttribute : Attribute + { + string failureMessage = String.Format("Expected {0} {1}" + + " to be decorated with {2}{{reason}}, but that attribute was not found.", + Context, SubjectDescription, typeof (TAttribute)); + + IEnumerable attributes = Subject.GetMatchingAttributes(isMatchingAttributePredicate); + + Execute.Assertion + .ForCondition(attributes.Any()) + .BecauseOf(because, becauseArgs) + .FailWith(failureMessage); + + return new AndWhichConstraint, TAttribute>(this, attributes); + } + + /// + /// Asserts that the selected member is not decorated with an attribute of type + /// that matches the specified . + /// + /// + /// The predicate that the attribute must match. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeDecoratedWith( + Expression> isMatchingAttributePredicate, + string because = "", params object[] becauseArgs) + where TAttribute : Attribute + { + string failureMessage = String.Format("Expected {0} {1}" + + " to not be decorated with {2}{{reason}}, but that attribute was found.", + Context, SubjectDescription, typeof(TAttribute)); + + IEnumerable attributes = Subject.GetMatchingAttributes(isMatchingAttributePredicate); + + Execute.Assertion + .ForCondition(!attributes.Any()) + .BecauseOf(because, becauseArgs) + .FailWith(failureMessage); + + return new AndConstraint((TAssertions)this); + } + + protected override string Context + { + get { return "member"; } + } + + internal virtual string SubjectDescription + { + get + { + return String.Format("{0}.{1}", Subject.DeclaringType, Subject.Name); + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Types/MemberInfoAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Types/MemberInfoAssertions.cs.meta new file mode 100644 index 0000000..63c365e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/MemberInfoAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 071d5c9bc96c46f4bb62c638e8d143e9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Types/MethodBaseAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Types/MethodBaseAssertions.cs new file mode 100644 index 0000000..a5c6002 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/MethodBaseAssertions.cs @@ -0,0 +1,54 @@ +using System; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using FluentAssertions.Common; +using FluentAssertions.Execution; + +namespace FluentAssertions.Types +{ + /// + /// Contains a number of methods to assert that a is in the expected state. + /// + [DebuggerNonUserCode] + public abstract class MethodBaseAssertions : MemberInfoAssertions + where TSubject : MethodBase + where TAssertions : MethodBaseAssertions + { + /// + /// Asserts that the selected member has the specified C# . + /// + /// The expected C# access modifier. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveAccessModifier( + CSharpAccessModifier accessModifier, string because = "", params object[] becauseArgs) + { + Execute.Assertion.ForCondition(accessModifier == Subject.GetCSharpAccessModifier()) + .BecauseOf(because, becauseArgs) + .FailWith("Expected method " + Subject.Name + " to be {0}{reason}, but it is {1}.", + accessModifier, Subject.GetCSharpAccessModifier()); + + return new AndConstraint((TAssertions)this); + } + + protected override string Context + { + get { return "methodBase"; } + } + + internal static string GetParameterString(MethodBase methodBase) + { + var parameterTypes = methodBase.GetParameters().Select(p => p.ParameterType); + + return !parameterTypes.Any() + ? String.Empty + : parameterTypes.Select(p => p.FullName).Aggregate((p, c) => p + ", " + c); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Types/MethodBaseAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Types/MethodBaseAssertions.cs.meta new file mode 100644 index 0000000..ecc07f4 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/MethodBaseAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cbb9f410b39aa7f4f91528a2147a6480 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Types/MethodInfoAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Types/MethodInfoAssertions.cs new file mode 100644 index 0000000..bfd6c6c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/MethodInfoAssertions.cs @@ -0,0 +1,142 @@ +using System; +using System.Diagnostics; +using System.Reflection; +using FluentAssertions.Common; +using FluentAssertions.Execution; + +namespace FluentAssertions.Types +{ + /// + /// Contains a number of methods to assert that a is in the expected state. + /// + [DebuggerNonUserCode] + public class MethodInfoAssertions : + MethodBaseAssertions + { + public MethodInfoAssertions(MethodInfo methodInfo) + { + Subject = methodInfo; + } + + /// + /// Asserts that the selected method is virtual. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeVirtual( + string because = "", params object[] becauseArgs) + { + string failureMessage = "Expected method " + + SubjectDescription + + " to be virtual{reason}, but it is not virtual."; + + Execute.Assertion + .ForCondition(!Subject.IsNonVirtual()) + .BecauseOf(because, becauseArgs) + .FailWith(failureMessage); + + return new AndConstraint(this); + } + + /// + /// Asserts that the selected method is async. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndConstraint BeAsync(string because = "", params object[] becauseArgs) + { + string failureMessage = "Expected subject " + + SubjectDescription + + " to be async{reason}, but it is not."; + + Execute.Assertion + .ForCondition(Subject.IsAsync()) + .BecauseOf(because, becauseArgs) + .FailWith(failureMessage); + + return new AndConstraint(this); + } + + /// + /// Asserts that the selected MethodInfo returns void. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> ReturnVoid(string because = "", params object[] becauseArgs) + { + Execute.Assertion.ForCondition(typeof(void) == Subject.ReturnType) + .BecauseOf(because, becauseArgs) + .FailWith("Expected the return type of method " + Subject.Name + " to be void {reason}, but it is {0}.", + Subject.ReturnType.FullName); + + return new AndConstraint>(this); + } + + /// + /// Asserts that the selected MethodInfo returns . + /// + /// The expected return type. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> Return(Type returnType, string because = "", params object[] becauseArgs) + { + Execute.Assertion.ForCondition(returnType == Subject.ReturnType) + .BecauseOf(because, becauseArgs) + .FailWith("Expected the return type of method " + Subject.Name + " to be {0} {reason}, but it is {1}.", + returnType, Subject.ReturnType.FullName); + + return new AndConstraint>(this); + } + + /// + /// Asserts that the selected MethodInfo returns . + /// + /// The expected return type. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint> Return(string because = "", params object[] becauseArgs) + { + return Return(typeof (TReturn), because, becauseArgs); + } + + + internal static string GetDescriptionFor(MethodInfo method) + { + string returnTypeName = method.ReturnType.Name; + + return String.Format("{0} {1}.{2}", returnTypeName, + method.DeclaringType, method.Name); + } + + internal override string SubjectDescription + { + get { return GetDescriptionFor(Subject); } + } + + protected override string Context + { + get { return "method"; } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Types/MethodInfoAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Types/MethodInfoAssertions.cs.meta new file mode 100644 index 0000000..7d3143a --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/MethodInfoAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 19949ed99ba69b0498e1335a6ffea497 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Types/MethodInfoSelector.cs b/Assets/Plugins/FluentAssertions/Core/Types/MethodInfoSelector.cs new file mode 100644 index 0000000..ad88a09 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/MethodInfoSelector.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace FluentAssertions.Types +{ + /// + /// Allows for fluent selection of methods of a type through reflection. + /// + public class MethodInfoSelector : IEnumerable + { + private IEnumerable selectedMethods = new List(); + + /// + /// Initializes a new instance of the class. + /// + /// The type from which to select methods. + public MethodInfoSelector(Type type) + : this(new[]{type}) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The types from which to select methods. + public MethodInfoSelector(IEnumerable types) + { + selectedMethods = types.SelectMany(t => t + .GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + .Where(method => !HasSpecialName(method))); + } + + /// + /// Only select the methods that are public or internal. + /// + public MethodInfoSelector ThatArePublicOrInternal + { + get + { + selectedMethods = selectedMethods.Where(method => method.IsPublic || method.IsAssembly); + return this; + } + } + + /// + /// Only select the methods without a return value + /// + public MethodInfoSelector ThatReturnVoid + { + get + { + selectedMethods = selectedMethods.Where(method => method.ReturnType == typeof (void)); + return this; + } + } + + /// + /// Only select the methods that return the specified type + /// + public MethodInfoSelector ThatReturn() + { + selectedMethods = selectedMethods.Where(method => method.ReturnType == typeof(TReturn)); + return this; + } + + /// + /// Only select the methods that are decorated with an attribute of the specified type. + /// + public MethodInfoSelector ThatAreDecoratedWith() + { + selectedMethods = selectedMethods.Where(method => method.GetCustomAttributes(false).OfType().Any()); + return this; + } + + /// + /// The resulting objects. + /// + public MethodInfo[] ToArray() + { + return selectedMethods.ToArray(); + } + + /// + /// Determines whether the specified method has a special name (like properties and events). + /// + private bool HasSpecialName(MethodInfo method) + { + return (method.Attributes & MethodAttributes.SpecialName) == MethodAttributes.SpecialName; + } + + /// + /// Returns an enumerator that iterates through the collection. + /// + /// + /// A that can be used to iterate through the collection. + /// + /// 1 + public IEnumerator GetEnumerator() + { + return selectedMethods.GetEnumerator(); + } + + /// + /// Returns an enumerator that iterates through a collection. + /// + /// + /// An object that can be used to iterate through the collection. + /// + /// 2 + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Types/MethodInfoSelector.cs.meta b/Assets/Plugins/FluentAssertions/Core/Types/MethodInfoSelector.cs.meta new file mode 100644 index 0000000..e714ec6 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/MethodInfoSelector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c34b50aa3cc647d4180cbcb64c5f4260 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Types/MethodInfoSelectorAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Types/MethodInfoSelectorAssertions.cs new file mode 100644 index 0000000..e0e1f5d --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/MethodInfoSelectorAssertions.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using FluentAssertions.Common; +using FluentAssertions.Execution; + +namespace FluentAssertions.Types +{ + /// + /// Contains assertions for the objects returned by the parent . + /// + [DebuggerNonUserCode] + public class MethodInfoSelectorAssertions + { + /// + /// Initializes a new instance of the class. + /// + /// The methods to assert. + public MethodInfoSelectorAssertions(IEnumerable methods) + { + SubjectMethods = methods; + } + + /// + /// Gets the object which value is being asserted. + /// + public IEnumerable SubjectMethods { get; private set; } + + /// + /// Asserts that the selected methods are virtual. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeVirtual(string because = "", params object[] becauseArgs) + { + IEnumerable nonVirtualMethods = GetAllNonVirtualMethodsFromSelection(); + + string failureMessage = + "Expected all selected methods to be virtual{reason}, but the following methods are not virtual:\r\n" + + GetDescriptionsFor(nonVirtualMethods); + + Execute.Assertion + .ForCondition(!nonVirtualMethods.Any()) + .BecauseOf(because, becauseArgs) + .FailWith(failureMessage); + + return new AndConstraint(this); + } + + private MethodInfo[] GetAllNonVirtualMethodsFromSelection() + { + var query = + from method in SubjectMethods + where method.IsNonVirtual() + select method; + + return query.ToArray(); + } + + /// + /// Asserts that the selected methods are decorated with the specified . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeDecoratedWith(string because = "", params object[] becauseArgs) + where TAttribute : Attribute + { + return BeDecoratedWith(attr => true, because, becauseArgs); + } + + /// + /// Asserts that the selected methods are decorated with an attribute of type + /// that matches the specified . + /// + /// + /// The predicate that the attribute must match. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeDecoratedWith( + Expression> isMatchingAttributePredicate, string because = "", params object[] becauseArgs) + where TAttribute : Attribute + { + IEnumerable methodsWithoutAttribute = GetMethodsWithout(isMatchingAttributePredicate); + + string failureMessage = + "Expected all selected methods to be decorated with {0}{reason}, but the following methods are not:\r\n" + + GetDescriptionsFor(methodsWithoutAttribute); + + Execute.Assertion + .ForCondition(!methodsWithoutAttribute.Any()) + .BecauseOf(because, becauseArgs) + .FailWith(failureMessage, typeof(TAttribute)); + + return new AndConstraint(this); + } + + private MethodInfo[] GetMethodsWithout(Expression> isMatchingPredicate) + where TAttribute : Attribute + { + return SubjectMethods.Where(method => !method.HasMatchingAttribute(isMatchingPredicate)).ToArray(); + } + + private static string GetDescriptionsFor(IEnumerable methods) + { + return string.Join(Environment.NewLine, + methods.Select(MethodInfoAssertions.GetDescriptionFor).ToArray()); + } + + /// + /// Returns the type of the subject the assertion applies on. + /// + protected string Context + { + get { return "method"; } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Types/MethodInfoSelectorAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Types/MethodInfoSelectorAssertions.cs.meta new file mode 100644 index 0000000..31777bb --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/MethodInfoSelectorAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dd43386a45ad3c146afa93d989761f01 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Types/PropertyInfoAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Types/PropertyInfoAssertions.cs new file mode 100644 index 0000000..a06b4b4 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/PropertyInfoAssertions.cs @@ -0,0 +1,232 @@ +using System; +using System.Diagnostics; +using System.Reflection; +using FluentAssertions.Common; +using FluentAssertions.Execution; + +namespace FluentAssertions.Types +{ + /// + /// Contains a number of methods to assert that a is in the expected state. + /// + [DebuggerNonUserCode] + public class PropertyInfoAssertions : + MemberInfoAssertions + { + public PropertyInfoAssertions(PropertyInfo propertyInfo) + { + Subject = propertyInfo; + } + + /// + /// Asserts that the selected property is virtual. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeVirtual( + string because = "", params object[] becauseArgs) + { + string failureMessage = "Expected property " + + GetDescriptionFor(Subject) + + " to be virtual{reason}, but it is not."; + + Execute.Assertion + .ForCondition(Subject.IsVirtual()) + .BecauseOf(because, becauseArgs) + .FailWith(failureMessage); + + return new AndConstraint(this); + } + + /// + /// Asserts that the selected property has a setter. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeWritable( + string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.CanWrite) + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected {context:property} {0} to have a setter{reason}.", + Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that the selected property has a setter with the specified C# access modifier. + /// + /// The expected C# access modifier. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeWritable(CSharpAccessModifier accessModifier, string because = "", params object[] becauseArgs) + { + Subject.Should().BeWritable(because, becauseArgs); + + Subject.GetSetMethod(true).Should().HaveAccessModifier(accessModifier, because, becauseArgs); + + return new AndConstraint(this); + } + + /// + /// Asserts that the selected property does not have a setter. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeWritable( + string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!Subject.CanWrite) + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected {context:property} {0} not to have a setter{reason}.", + Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that the selected property has a getter. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeReadable(string because = "", params object[] becauseArgs) + { + Execute.Assertion.ForCondition(Subject.CanRead) + .BecauseOf(because, becauseArgs) + .FailWith("Expected property " + Subject.Name + " to have a getter{reason}, but it does not."); + + return new AndConstraint(this); + } + + /// + /// Asserts that the selected property has a getter with the specified C# access modifier. + /// + /// The expected C# access modifier. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeReadable(CSharpAccessModifier accessModifier, string because = "", params object[] becauseArgs) + { + Subject.Should().BeReadable(because, becauseArgs); + + Subject.GetGetMethod(true).Should().HaveAccessModifier(accessModifier, because, becauseArgs); + + return new AndConstraint(this); + } + + /// + /// Asserts that the selected property does not have a getter. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeReadable( + string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!Subject.CanRead) + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected {context:property} {0} not to have a getter{reason}.", + Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that the selected property returns a specified type. + /// + /// The expected type of the property. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Return(Type propertyType, + string because = "", params object[] becauseArgs) + { + Execute.Assertion.ForCondition(Subject.PropertyType == propertyType) + .BecauseOf(because, becauseArgs) + .FailWith("Expected Type of property " + Subject.Name + " to be {0}{reason}, but it is {1}.", propertyType, Subject.PropertyType); + + + return new AndConstraint(this); + } + + /// + /// Asserts that the selected PropertyInfo returns . + /// + /// The expected return type. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Return(string because = "", params object[] becauseArgs) + { + return Return(typeof(TReturn), because, becauseArgs); + } + + internal static string GetDescriptionFor(PropertyInfo property) + { + string propTypeName = property.PropertyType.Name; + return String.Format("{0} {1}.{2}", propTypeName, + property.DeclaringType, property.Name); + } + + internal override string SubjectDescription + { + get { return GetDescriptionFor(Subject); } + } + + /// + /// Returns the type of the subject the assertion applies on. + /// + protected override string Context + { + get { return "property"; } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Types/PropertyInfoAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Types/PropertyInfoAssertions.cs.meta new file mode 100644 index 0000000..112a29d --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/PropertyInfoAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f4fbbe01ec476ff4899f875bbe920ff6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Types/PropertyInfoSelector.cs b/Assets/Plugins/FluentAssertions/Core/Types/PropertyInfoSelector.cs new file mode 100644 index 0000000..ec7c14b --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/PropertyInfoSelector.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace FluentAssertions.Types +{ + /// + /// Allows for fluent selection of properties of a type through reflection. + /// + public class PropertyInfoSelector : IEnumerable + { + private IEnumerable selectedProperties = new List(); + + /// + /// Initializes a new instance of the class. + /// + /// The type from which to select properties. + public PropertyInfoSelector(Type type) + : this(new [] {type}) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The types from which to select properties. + public PropertyInfoSelector(IEnumerable types) + { + selectedProperties = types.SelectMany(t => t + .GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)); + } + + /// + /// Only select the properties that have a public or internal getter. + /// + public PropertyInfoSelector ThatArePublicOrInternal + { + get + { + selectedProperties = selectedProperties.Where(property => + { + MethodInfo getter = property.GetGetMethod(true); + return ((getter != null) && (getter.IsPublic || getter.IsAssembly)); + }); + + return this; + } + } + + /// + /// Only select the properties that are decorated with an attribute of the specified type. + /// + public PropertyInfoSelector ThatAreDecoratedWith() + { + selectedProperties = selectedProperties.Where(property => property.GetCustomAttributes(false).OfType().Any()); + return this; + } + + /// + /// Only select the properties that return the specified type + /// + public PropertyInfoSelector OfType() + { + selectedProperties = selectedProperties.Where(property => property.PropertyType == typeof(TReturn)); + return this; + } + + /// + /// The resulting objects. + /// + public PropertyInfo[] ToArray() + { + return selectedProperties.ToArray(); + } + + /// + /// Returns an enumerator that iterates through the collection. + /// + /// + /// A that can be used to iterate through the collection. + /// + /// 1 + public IEnumerator GetEnumerator() + { + return selectedProperties.GetEnumerator(); + } + + /// + /// Returns an enumerator that iterates through a collection. + /// + /// + /// An object that can be used to iterate through the collection. + /// + /// 2 + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Types/PropertyInfoSelector.cs.meta b/Assets/Plugins/FluentAssertions/Core/Types/PropertyInfoSelector.cs.meta new file mode 100644 index 0000000..916cd25 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/PropertyInfoSelector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5b2823c5299d7a74ba24485150cc6348 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Types/PropertyInfoSelectorAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Types/PropertyInfoSelectorAssertions.cs new file mode 100644 index 0000000..7c1f282 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/PropertyInfoSelectorAssertions.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using FluentAssertions.Common; +using FluentAssertions.Execution; + +namespace FluentAssertions.Types +{ + /// + /// Contains assertions for the objects returned by the parent . + /// + [DebuggerNonUserCode] + public class PropertyInfoSelectorAssertions + { + /// + /// Gets the object which value is being asserted. + /// + public IEnumerable SubjectProperties { get; private set; } + + /// + /// Initializes a new instance of the class, for a number of objects. + /// + /// The properties to assert. + public PropertyInfoSelectorAssertions(IEnumerable properties) + { + SubjectProperties = properties; + } + + /// + /// Asserts that the selected properties are virtual. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeVirtual(string because = "", params object[] becauseArgs) + { + IEnumerable nonVirtualProperties = GetAllNonVirtualPropertiesFromSelection(); + + string failureMessage = + "Expected all selected properties to be virtual{reason}, but the following properties are not virtual:\r\n" + + GetDescriptionsFor(nonVirtualProperties); + + Execute.Assertion + .ForCondition(!nonVirtualProperties.Any()) + .BecauseOf(because, becauseArgs) + .FailWith(failureMessage); + + return new AndConstraint(this); + } + + /// + /// Asserts that the selected properties have a setter. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeWritable(string because = "", params object[] becauseArgs) + { + PropertyInfo[] readOnlyProperties = GetAllReadOnlyPropertiesFromSelection(); + + string failureMessage = + "Expected all selected properties to have a setter{reason}, but the following properties do not:\r\n" + + GetDescriptionsFor(readOnlyProperties); + + Execute.Assertion + .ForCondition(!readOnlyProperties.Any()) + .BecauseOf(because, becauseArgs) + .FailWith(failureMessage); + + return new AndConstraint(this); + } + + private PropertyInfo[] GetAllReadOnlyPropertiesFromSelection() + { + return SubjectProperties.Where(property => !property.CanWrite).ToArray(); + } + + private PropertyInfo[] GetAllNonVirtualPropertiesFromSelection() + { + var query = + from property in SubjectProperties + where !property.IsVirtual() + select property; + + return query.ToArray(); + } + + /// + /// Asserts that the selected properties are decorated with the specified . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeDecoratedWith(string because = "", params object[] becauseArgs) + where TAttribute : Attribute + { + IEnumerable propertiesWithoutAttribute = GetPropertiesWithout(); + + string failureMessage = + "Expected all selected properties to be decorated with {0}{reason}, but the following properties are not:\r\n" + + GetDescriptionsFor(propertiesWithoutAttribute); + + Execute.Assertion + .ForCondition(!propertiesWithoutAttribute.Any()) + .BecauseOf(because, becauseArgs) + .FailWith(failureMessage, typeof(TAttribute)); + + return new AndConstraint(this); + } + + private PropertyInfo[] GetPropertiesWithout() + where TAttribute : Attribute + { + return SubjectProperties.Where(property => !property.IsDecoratedWith()).ToArray(); + } + + private static string GetDescriptionsFor(IEnumerable properties) + { + return string.Join(Environment.NewLine, properties.Select(PropertyInfoAssertions.GetDescriptionFor).ToArray()); + } + + /// + /// Returns the type of the subject the assertion applies on. + /// + protected string Context + { + get { return "property info"; } + } + } +} diff --git a/Assets/Plugins/FluentAssertions/Core/Types/PropertyInfoSelectorAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Types/PropertyInfoSelectorAssertions.cs.meta new file mode 100644 index 0000000..f2f8062 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/PropertyInfoSelectorAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6b225c63504da4b4089e50ad38f7c7f0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Types/TypeAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Types/TypeAssertions.cs new file mode 100644 index 0000000..cbb79b1 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/TypeAssertions.cs @@ -0,0 +1,709 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using FluentAssertions.Common; +using FluentAssertions.Execution; +using FluentAssertions.Primitives; + +namespace FluentAssertions.Types +{ + /// + /// Contains a number of methods to assert that a meets certain expectations. + /// + [DebuggerNonUserCode] + public class TypeAssertions : ReferenceTypeAssertions + { + /// + /// Initializes a new instance of the class. + /// + public TypeAssertions(Type type) + { + Subject = type; + } + + /// + /// Asserts that the current type is equal to the specified type. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Be(string because = "", params object[] becauseArgs) + { + return Be(typeof(TExpected), because, becauseArgs); + } + + /// + /// Asserts that the current type is equal to the specified type. + /// + /// The expected type + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Be(Type expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!ReferenceEquals(Subject, null)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected type to be {0}{reason}, but found .", expected); + + Execute.Assertion + .ForCondition(Subject == expected) + .BecauseOf(because, becauseArgs) + .FailWith(GetFailureMessageIfTypesAreDifferent(Subject, expected)); + + return new AndConstraint(this); + } + + /// + /// Asserts than an instance of the subject type is assignable variable of type . + /// + /// The type to which instances of the type should be assignable. + /// The reason why instances of the type should be assignable to the type. + /// The parameters used when formatting the . + /// An which can be used to chain assertions. + public new AndConstraint BeAssignableTo(string because = "", params object[] becauseArgs) + { + return BeAssignableTo(typeof(T), because, becauseArgs); + } + + /// + /// Asserts than an instance of the subject type is assignable variable of given . + /// + /// The type to which instances of the type should be assignable. + /// The reason why instances of the type should be assignable to the type. + /// + /// An which can be used to chain assertions. + public new AndConstraint BeAssignableTo(Type type, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(type.IsAssignableFrom(Subject)) + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected {context:" + Context + "} {0} to be assignable to {1}{reason}, but it is not", + Subject, + type); + + return new AndConstraint(this); + } + + /// + /// Creates an error message in case the specified type differs from the + /// type. + /// + /// + /// An empty if the two specified types are the same, or an error message that describes that + /// the two specified types are not the same. + /// + private static string GetFailureMessageIfTypesAreDifferent(Type actual, Type expected) + { + if (actual == expected) + { + return ""; + } + + string expectedType = (expected != null) ? expected.FullName : ""; + string actualType = (actual != null) ? actual.FullName : ""; + + if (expectedType == actualType) + { + expectedType = "[" + expected.AssemblyQualifiedName + "]"; + actualType = "[" + actual.AssemblyQualifiedName + "]"; + } + + return string.Format("Expected type to be {0}{{reason}}, but found {1}.", expectedType, actualType); + } + + /// + /// Asserts that the current type is not equal to the specified type. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBe(string because = "", params object[] becauseArgs) + { + return NotBe(typeof(TUnexpected), because, becauseArgs); + } + + /// + /// Asserts that the current type is not equal to the specified type. + /// + /// The unexpected type + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBe(Type unexpected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject != unexpected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected type not to be [" + unexpected.AssemblyQualifiedName + "]{reason}, but it is."); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is decorated with the specified . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeDecoratedWith(string because = "", params object[] becauseArgs) + where TAttribute : Attribute + { + Execute.Assertion + .ForCondition(Subject.IsDecoratedWith()) + .BecauseOf(because, becauseArgs) + .FailWith("Expected type {0} to be decorated with {1}{reason}, but the attribute was not found.", + Subject, typeof (TAttribute)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is decorated with an attribute of type + /// that matches the specified . + /// + /// + /// The predicate that the attribute must match. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeDecoratedWith( + Expression> isMatchingAttributePredicate, string because = "", params object[] becauseArgs) + where TAttribute : Attribute + { + BeDecoratedWith(because, becauseArgs); + + Execute.Assertion + .ForCondition(Subject.HasMatchingAttribute(isMatchingAttributePredicate)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected type {0} to be decorated with {1} that matches {2}{reason}, but no matching attribute was found.", + Subject, typeof(TAttribute), isMatchingAttributePredicate.Body); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current implements Interface . + /// + /// The interface that should be implemented. + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndConstraint Implement(Type interfaceType, string because = "", params object[] becauseArgs) + { + if (!interfaceType.GetTypeInfo().IsInterface) + { + throw new ArgumentException("Must be an interface Type.", "interfaceType"); + } + + Execute.Assertion.ForCondition(Subject.GetInterfaces().Contains(interfaceType)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected type {0} to implement interface {1}{reason}, but it does not.", Subject, interfaceType); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current implements Interface . + /// + /// The interface that should be implemented. + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndConstraint Implement(string because = "", params object[] becauseArgs) where TInterface : class + { + return Implement(typeof (TInterface), because, becauseArgs); + } + + /// + /// Asserts that the current does not implement Interface . + /// + /// The interface that should be not implemented. + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndConstraint NotImplement(Type interfaceType, string because = "", params object[] becauseArgs) + { + if (!interfaceType.GetTypeInfo().IsInterface) + { + throw new ArgumentException("Must be an interface Type.", "interfaceType"); + } + + Execute.Assertion.ForCondition(!Subject.GetInterfaces().Contains(interfaceType)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected type {0} to not implement interface {1}{reason}, but it does.", Subject, interfaceType); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current does not implement Interface . + /// + /// The interface that should not be implemented. + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndConstraint NotImplement(string because = "", params object[] becauseArgs) where TInterface : class + { + return NotImplement(typeof(TInterface), because, becauseArgs); + } + + /// + /// Asserts that the current is derived from . + /// + /// The Type that should be derived from. + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndConstraint BeDerivedFrom(Type baseType, string because = "", params object[] becauseArgs) + { + if (baseType.GetTypeInfo().IsInterface) + { + throw new ArgumentException("Must not be an interface Type.", "baseType"); + } + + Execute.Assertion.ForCondition(Subject.IsSubclassOf(baseType)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected type {0} to be derived from {1}{reason}, but it is not.", Subject, baseType); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is derived from . + /// + /// The Type that should be derived from. + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndConstraint BeDerivedFrom(string because = "", params object[] becauseArgs) where TBaseClass : class + { + return BeDerivedFrom(typeof(TBaseClass), because, becauseArgs); + } + + /// + /// Asserts that the current type has a property of type named . + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + /// The type of the property. + /// The name of the property. + public AndWhichConstraint HaveProperty(Type propertyType, string name, string because = "", params object[] becauseArgs) + { + PropertyInfo propertyInfo = Subject.GetPropertyByName(name); + + string propertyInfoDescription = ""; + + if (propertyInfo != null) + { + propertyInfoDescription = PropertyInfoAssertions.GetDescriptionFor(propertyInfo); + } + + Execute.Assertion.ForCondition(propertyInfo != null) + .BecauseOf(because, becauseArgs) + .FailWith(String.Format("Expected {0} {1}.{2} to exist{{reason}}, but it does not.", + propertyType.Name, Subject.FullName, name)); + + Execute.Assertion.ForCondition(propertyInfo.PropertyType == propertyType) + .BecauseOf(because, becauseArgs) + .FailWith(String.Format("Expected {0} to be of type {1}{{reason}}, but it is not.", + propertyInfoDescription, propertyType)); + + return new AndWhichConstraint(this, propertyInfo); + } + + /// + /// Asserts that the current type has a property of type named . + /// + /// The type of the property. + /// The name of the property. + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndWhichConstraint HaveProperty(string name, string because = "", params object[] becauseArgs) + { + return HaveProperty(typeof(TProperty), name, because, becauseArgs); + } + + /// + /// Asserts that the current type does not have a property named . + /// + /// The name of the property. + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndConstraint NotHaveProperty(string name, string because = "", params object[] becauseArgs) + { + PropertyInfo propertyInfo = Subject.GetPropertyByName(name); + + string propertyInfoDescription = ""; + + if (propertyInfo != null) + { + propertyInfoDescription = PropertyInfoAssertions.GetDescriptionFor(propertyInfo); + } + + Execute.Assertion.ForCondition(propertyInfo == null) + .BecauseOf(because, becauseArgs) + .FailWith(string.Format("Expected {0} to not exist{{reason}}, but it does.", propertyInfoDescription)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current type explicitly implements a property named + /// from interface . + /// + /// The type of the interface. + /// The name of the property. + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndConstraint HaveExplicitProperty(Type interfaceType, string name, string because = "", params object[] becauseArgs) + { + Subject.Should().Implement(interfaceType, because, becauseArgs); + + var explicitlyImplementsProperty = Subject.HasExplicitlyImplementedProperty(interfaceType, name); + + Execute.Assertion.ForCondition(explicitlyImplementsProperty) + .BecauseOf(because, becauseArgs) + .FailWith(String.Format("Expected {0} to explicitly implement {1}.{2}{{reason}}, but it does not.", + Subject.FullName, interfaceType.FullName, name)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current type explicitly implements a property named + /// from interface . + /// + /// The interface whose member is being explicitly implemented. + /// The name of the property. + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndConstraint HaveExplicitProperty(string name, string because = "", params object[] becauseArgs) where TInterface : class + { + return HaveExplicitProperty(typeof (TInterface), name, because, becauseArgs); + } + + /// + /// Asserts that the current type does not explicitly implement a property named + /// from interface . + /// + /// The type of the interface. + /// The name of the property. + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndConstraint NotHaveExplicitProperty(Type interfaceType, string name, string because = "", params object[] becauseArgs) + { + Subject.Should().Implement(interfaceType, because, becauseArgs); + + var explicitlyImplementsProperty = Subject.HasExplicitlyImplementedProperty(interfaceType, name); + + Execute.Assertion.ForCondition(!explicitlyImplementsProperty) + .BecauseOf(because, becauseArgs) + .FailWith(String.Format("Expected {0} to not explicitly implement {1}.{2}{{reason}}, but it does.", + Subject.FullName, interfaceType.FullName, name)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current type does not explicitly implement a property named + /// from interface . + /// + /// The interface whose member is not being explicitly implemented. + /// The name of the property. + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndConstraint NotHaveExplicitProperty(string name, string because = "", params object[] becauseArgs) where TInterface : class + { + return NotHaveExplicitProperty(typeof(TInterface), name, because, becauseArgs); + } + + /// + /// Asserts that the current type explicitly implements a method named + /// from interface . + /// + /// The type of the interface. + /// The name of the method. + /// The expected types of the method parameters. + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndConstraint HaveExplicitMethod(Type interfaceType, string name, IEnumerable parameterTypes, string because = "", params object[] becauseArgs) + { + Subject.Should().Implement(interfaceType, because, becauseArgs); + + var explicitlyImplementsMethod = Subject.HasMethod(string.Format("{0}.{1}", interfaceType.FullName, name), parameterTypes); + + Execute.Assertion.ForCondition(explicitlyImplementsMethod) + .BecauseOf(because, becauseArgs) + .FailWith(String.Format("Expected {0} to explicitly implement {1}.{2}{{reason}}, but it does not.", + Subject.FullName, interfaceType.FullName, name)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current type explicitly implements a method named + /// from interface . + /// + /// The interface whose member is being explicitly implemented. + /// The name of the method. + /// The expected types of the method parameters. + /// /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndConstraint HaveExplicitMethod(string name, IEnumerable parameterTypes, string because = "", params object[] becauseArgs) where TInterface : class + { + return HaveExplicitMethod(typeof(TInterface), name, parameterTypes, because, becauseArgs); + } + + /// + /// Asserts that the current type does not explicitly implement a method named + /// from interface . + /// + /// The type of the interface. + /// The name of the method. + /// The expected types of the method parameters. + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndConstraint NotHaveExplicitMethod(Type interfaceType, string name, IEnumerable parameterTypes, string because = "", params object[] becauseArgs) + { + Subject.Should().Implement(interfaceType, because, becauseArgs); + + var explicitlyImplementsMethod = Subject.HasMethod(string.Format("{0}.{1}", interfaceType.FullName, name), parameterTypes); + + Execute.Assertion.ForCondition(!explicitlyImplementsMethod) + .BecauseOf(because, becauseArgs) + .FailWith(String.Format("Expected {0} to not explicitly implement {1}.{2}{{reason}}, but it does.", + Subject.FullName, interfaceType.FullName, name)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current type does not explicitly implement a method named + /// from interface . + /// + /// The interface whose member is not being explicitly implemented. + /// The name of the method. + /// The expected types of the method parameters. + /// /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndConstraint NotHaveExplicitMethod(string name, IEnumerable parameterTypes, string because = "", params object[] becauseArgs) where TInterface : class + { + return NotHaveExplicitMethod(typeof(TInterface), name, parameterTypes, because, becauseArgs); + } + + /// + /// Asserts that the current type has an indexer of type . + /// with parameter types . + /// + /// The type of the indexer. + /// The parameter types for the indexer. + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndWhichConstraint HaveIndexer(Type indexerType, IEnumerable parameterTypes, string because = "", params object[] becauseArgs) + { + PropertyInfo propertyInfo = Subject.GetIndexerByParameterTypes(parameterTypes); + + string propertyInfoDescription = ""; + + if (propertyInfo != null) + { + propertyInfoDescription = PropertyInfoAssertions.GetDescriptionFor(propertyInfo); + } + + Execute.Assertion.ForCondition(propertyInfo != null) + .BecauseOf(because, becauseArgs) + .FailWith(String.Format("Expected {0} {1}[{2}] to exist{{reason}}, but it does not.", + indexerType.Name, Subject.FullName, + GetParameterString(parameterTypes))); + + Execute.Assertion.ForCondition(propertyInfo.PropertyType == indexerType) + .BecauseOf(because, becauseArgs) + .FailWith(String.Format("Expected {0} to be of type {1}{{reason}}, but it is not.", + propertyInfoDescription, indexerType)); + + return new AndWhichConstraint(this, propertyInfo); + } + + /// + /// Asserts that the current type does not have an indexer that takes parameter types . + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + /// The expected indexer's parameter types. + public AndConstraint NotHaveIndexer(IEnumerable parameterTypes, string because = "", params object[] becauseArgs) + { + PropertyInfo propertyInfo = Subject.GetIndexerByParameterTypes(parameterTypes); + + Execute.Assertion.ForCondition(propertyInfo == null) + .BecauseOf(because, becauseArgs) + .FailWith(String.Format("Expected indexer {0}[{1}] to not exist{{reason}}, but it does.", + Subject.FullName, + GetParameterString(parameterTypes))); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current type has a method named with parameter types . + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + /// The name of the method. + /// The parameter types for the indexer. + public AndWhichConstraint HaveMethod(String name, IEnumerable parameterTypes, string because = "", params object[] becauseArgs) + { + MethodInfo methodInfo = Subject.GetMethod(name, parameterTypes); + + Execute.Assertion.ForCondition(methodInfo != null) + .BecauseOf(because, becauseArgs) + .FailWith(String.Format("Expected method {0}.{1}({2}) to exist{{reason}}, but it does not.", + Subject.FullName, name, + GetParameterString(parameterTypes))); + + return new AndWhichConstraint(this, methodInfo); + } + + /// + /// Asserts that the current type does not expose a method named + /// with parameter types . + /// + /// The name of the method. + /// The method parameter types. + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndConstraint NotHaveMethod(string name, IEnumerable parameterTypes, string because = "", params object[] becauseArgs) + { + MethodInfo methodInfo = Subject.GetMethod(name, parameterTypes); + + string methodInfoDescription = ""; + + if (methodInfo != null) + { + methodInfoDescription = MethodInfoAssertions.GetDescriptionFor(methodInfo); + } + + Execute.Assertion.ForCondition(methodInfo == null) + .BecauseOf(because, becauseArgs) + .FailWith(string.Format("Expected method {0}({1}) to not exist{{reason}}, but it does.", methodInfoDescription, + GetParameterString(parameterTypes))); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current type has a constructor with parameter types . + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + /// The parameter types for the indexer. + public AndWhichConstraint HaveConstructor(IEnumerable parameterTypes, string because = "", params object[] becauseArgs) + { + ConstructorInfo constructorInfo = Subject.GetConstructor(parameterTypes); + + Execute.Assertion.ForCondition(constructorInfo != null) + .BecauseOf(because, becauseArgs) + .FailWith(String.Format("Expected constructor {0}({1}) to exist{{reason}}, but it does not.", + Subject.FullName, + GetParameterString(parameterTypes))); + + return new AndWhichConstraint(this, constructorInfo); + } + + /// + /// Asserts that the current type has a default constructor. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndWhichConstraint HaveDefaultConstructor(string because = "", params object[] becauseArgs) + { + return HaveConstructor(new Type[] {}, because, becauseArgs); + } + + private string GetParameterString(IEnumerable parameterTypes) + { + if (!parameterTypes.Any()) + { + return String.Empty; + } + + return parameterTypes.Select(p => p.FullName).Aggregate((p, c) => p + ", " + c); + } + + /// + /// Asserts that the selected type has the specified C# . + /// + /// The expected C# access modifier. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveAccessModifier( + CSharpAccessModifier accessModifier, string because = "", params object[] becauseArgs) + { + Execute.Assertion.ForCondition(accessModifier == Subject.GetCSharpAccessModifier()) + .BecauseOf(because, becauseArgs) + .FailWith("Expected type " + Subject.Name + " to be {0}{reason}, but it is {1}.", + accessModifier, Subject.GetCSharpAccessModifier()); + + return new AndConstraint(Subject); + } + + /// + /// Returns the type of the subject the assertion applies on. + /// + protected override string Context + { + get { return "type"; } + } + } +} diff --git a/Assets/Plugins/FluentAssertions/Core/Types/TypeAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Types/TypeAssertions.cs.meta new file mode 100644 index 0000000..805a312 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/TypeAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 30d6d072273476d45a681c0a56a5801d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Types/TypeSelector.cs b/Assets/Plugins/FluentAssertions/Core/Types/TypeSelector.cs new file mode 100644 index 0000000..73ba30d --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/TypeSelector.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace FluentAssertions.Types +{ + /// + /// Allows for fluent filtering a list of types. + /// + public class TypeSelector : IEnumerable + { + private List types; + + public TypeSelector(IEnumerable types) + { + this.types = types.ToList(); + } + + /// + /// The resulting objects. + /// + public Type[] ToArray() + { + return types.ToArray(); + } + + /// + /// Determines whether a type is a subclass of another type, but NOT the same type. + /// + public TypeSelector ThatDeriveFrom() + { + types = types.Where(type => type.IsSubclassOf(typeof(TBase))).ToList(); + return this; + } + + /// + /// Determines whether a type implements an interface (but is not the interface itself). + /// + public TypeSelector ThatImplement() + { + types = types.Where(t => + typeof(TInterface) + .IsAssignableFrom(t) && (t != typeof(TInterface) + )).ToList(); + return this; + } + + /// + /// Determines whether a type is decorated with a particular attribute. + /// + public TypeSelector ThatAreDecoratedWith() + { + types = types +#if NEW_REFLECTION + .Where(t => t.GetTypeInfo().GetCustomAttributes(typeof(TAttribute), true).Any()) +#else + .Where(t => t.GetCustomAttributes(typeof(TAttribute), true).Length > 0) +#endif + .ToList(); + + return this; + } + + /// + /// Determines whether the namespace of type is exactly . + /// + public TypeSelector ThatAreInNamespace(string @namespace) + { + types = types.Where(t => t.Namespace == @namespace).ToList(); + return this; + } + + /// + /// Determines whether the namespace of type is starts with . + /// + public TypeSelector ThatAreUnderNamespace(string @namespace) + { + types = types.Where(t => (t.Namespace != null) && t.Namespace.StartsWith(@namespace)).ToList(); + return this; + } + + /// + /// Returns an enumerator that iterates through the collection. + /// + /// + /// A that can be used to iterate through the collection. + /// + /// 1 + public IEnumerator GetEnumerator() + { + return types.GetEnumerator(); + } + + /// + /// Returns an enumerator that iterates through a collection. + /// + /// + /// An object that can be used to iterate through the collection. + /// + /// 2 + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Types/TypeSelector.cs.meta b/Assets/Plugins/FluentAssertions/Core/Types/TypeSelector.cs.meta new file mode 100644 index 0000000..2656d51 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/TypeSelector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c0edaa39da3fb6c4a9e41773d3ac6af1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Core/Types/TypeSelectorAssertions.cs b/Assets/Plugins/FluentAssertions/Core/Types/TypeSelectorAssertions.cs new file mode 100644 index 0000000..b00d1d6 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/TypeSelectorAssertions.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Linq.Expressions; + +using FluentAssertions.Execution; +using FluentAssertions.Common; + +namespace FluentAssertions.Types +{ + /// + /// Contains a number of methods to assert that all s in a + /// meet certain expectations. + /// + [DebuggerNonUserCode] + public class TypeSelectorAssertions + { + /// + /// Initializes a new instance of the class. + /// + public TypeSelectorAssertions(IEnumerable types) + { + Subject = types; + } + + /// + /// Gets the object which value is being asserted. + /// + public IEnumerable Subject { get; private set; } + + /// + /// Asserts that the current is decorated with the specified . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeDecoratedWith(string because = "", params object[] becauseArgs) + where TAttribute : Attribute + { + IEnumerable typesWithoutAttribute = Subject + .Where(type => !type.IsDecoratedWith()) + .ToArray(); + + Execute.Assertion + .ForCondition(!typesWithoutAttribute.Any()) + .BecauseOf(because, becauseArgs) + .FailWith("Expected all types to be decorated with {0}{reason}," + + " but the attribute was not found on the following types:\r\n" + GetDescriptionsFor(typesWithoutAttribute), + typeof(TAttribute)); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is decorated with an attribute of type + /// that matches the specified . + /// + /// + /// The predicate that the attribute must match. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeDecoratedWith( + Expression> isMatchingAttributePredicate, string because = "", params object[] becauseArgs) + where TAttribute : Attribute + { + IEnumerable typesWithoutMatchingAttribute = Subject + .Where(type => !type.HasMatchingAttribute(isMatchingAttributePredicate)) + .ToArray(); + + Execute.Assertion + .ForCondition(!typesWithoutMatchingAttribute.Any()) + .BecauseOf(because, becauseArgs) + .FailWith("Expected all types to be decorated with {0} that matches {1}{reason}," + + " but no matching attribute was found on the following types:\r\n" + GetDescriptionsFor(typesWithoutMatchingAttribute), + typeof(TAttribute), isMatchingAttributePredicate.Body); + + return new AndConstraint(this); + } + + private static string GetDescriptionsFor(IEnumerable types) + { + return string.Join(Environment.NewLine, types.Select(GetDescriptionFor).ToArray()); + } + + private static string GetDescriptionFor(Type type) + { + return type.ToString(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Core/Types/TypeSelectorAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Core/Types/TypeSelectorAssertions.cs.meta new file mode 100644 index 0000000..5b8aea3 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Core/Types/TypeSelectorAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4c242700ffcc1f34c816f7d385344ddd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Core.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Core.meta new file mode 100644 index 0000000..c2c9fc2 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Core.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ca9a3fe13ca9b884ead66337d84eddf0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Core/ReflectionExtensions.cs b/Assets/Plugins/FluentAssertions/FluentAssertions.Core/ReflectionExtensions.cs new file mode 100644 index 0000000..31a3754 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Core/ReflectionExtensions.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace FluentAssertions +{ + internal static class ReflectionExtensions + { + + public static bool IsEnum(this Type type) + { + return type.IsEnum; + } + + public static bool IsPrimitive(this Type type) + { + return type.IsPrimitive; + } + + public static Type GetBaseType(this Type type) + { + return type.BaseType; + } + + public static bool IsGenericType(this Type type) + { + return type.IsGenericType; + } + + public static bool IsInterface(this Type type) + { + return type.IsInterface; + } + + public static bool IsGenericTypeDefinition(this Type type) + { + return type.IsGenericTypeDefinition; + } + + public static Type GetTypeInfo(this Type type) + { + return type; + } + + } + +} diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Core/ReflectionExtensions.cs.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Core/ReflectionExtensions.cs.meta new file mode 100644 index 0000000..0ff55a4 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Core/ReflectionExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 62a6b150444c1f44d9e3d5c7c61ec35f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40.meta new file mode 100644 index 0000000..c9ea4e5 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a87bc2c808201224e83e4d5f6eb49b9e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Common.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Common.meta new file mode 100644 index 0000000..cea89ea --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Common.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dde4f03206dc034419958016ec0f89c3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Common/DefaultReflectionProvider.cs b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Common/DefaultReflectionProvider.cs new file mode 100644 index 0000000..f476a96 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Common/DefaultReflectionProvider.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; + +namespace FluentAssertions.Common +{ + internal class DefaultReflector : IReflector + { + public IEnumerable GetAllTypesFromAppDomain(Func predicate) + { + return AppDomain.CurrentDomain + .GetAssemblies() + .Where(a => predicate(a) && !IsDynamic(a)) + .SelectMany(GetExportedTypes).ToArray(); + } + + private static bool IsDynamic(Assembly assembly) + { + return (assembly.GetType().FullName == "System.Reflection.Emit.AssemblyBuilder") || + (assembly.GetType().FullName == "System.Reflection.Emit.InternalAssemblyBuilder"); + } + + private static IEnumerable GetExportedTypes(Assembly assembly) + { + try + { + return assembly.GetExportedTypes(); + } + catch (ReflectionTypeLoadException ex) + { + return ex.Types; + } + catch (FileLoadException) + { + return new Type[0]; + } + catch (Exception) + { + return new Type[0]; + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Common/DefaultReflectionProvider.cs.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Common/DefaultReflectionProvider.cs.meta new file mode 100644 index 0000000..1585332 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Common/DefaultReflectionProvider.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c609debc2f4fa4d4ab9745afe8d36ed7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Common/ProvidePlatformServices.cs b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Common/ProvidePlatformServices.cs new file mode 100644 index 0000000..5e02ebf --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Common/ProvidePlatformServices.cs @@ -0,0 +1,41 @@ +using System; + +using FluentAssertions.Execution; +using FluentAssertions.Formatting; +using FluentAssertions.Xml; + +namespace FluentAssertions.Common +{ + public class ProvidePlatformServices : IProvidePlatformServices + { + public Action Throw + { + get { return TestFrameworkProvider.Throw; } + } + + public IConfigurationStore ConfigurationStore + { + get { return new NullConfigurationStore(); } + } + + public IReflector Reflector + { + get { return new DefaultReflector(); } + } + + public IValueFormatter[] Formatters + { + get + { + return new IValueFormatter[] + { + new AggregateExceptionValueFormatter(), + new XDocumentValueFormatter(), + new XElementValueFormatter(), + new XAttributeValueFormatter(), + new XmlNodeFormatter() + }; + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Common/ProvidePlatformServices.cs.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Common/ProvidePlatformServices.cs.meta new file mode 100644 index 0000000..f487091 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Common/ProvidePlatformServices.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 08e69e85bd3fb394382f1cb820e1a431 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution.meta new file mode 100644 index 0000000..44ca170 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5a8c697569f2cd7488ca2b76222c92e1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/GallioTestFramework.cs b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/GallioTestFramework.cs new file mode 100644 index 0000000..b1115b4 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/GallioTestFramework.cs @@ -0,0 +1,110 @@ +using System; +using System.Linq; +using System.Reflection; + +#if WINRT +using System.Reflection.RuntimeExtensions; +#endif + +namespace FluentAssertions.Execution +{ + internal class GallioTestFramework : ITestFramework + { + private Assembly assembly; + + /// + /// Throws a framework-specific exception to indicate a failing unit test. + /// + public void Throw(string message) + { + Type assertionFailureBuilderType = assembly.GetType("Gallio.Framework.Assertions.AssertionFailureBuilder"); + Type assertionHelperType = assembly.GetType("Gallio.Framework.Assertions.AssertionHelper"); + Type testContextType = assembly.GetType("Gallio.Framework.TestContext"); + + if ((assertionFailureBuilderType == null) || (assertionHelperType == null) || (testContextType == null)) + { + throw new Exception(string.Format( + "Failed to create the assertion exception for the current test framework: \"{0}\"", + assembly.FullName)); + } + + object testContext = testContextType +#if !WINRT + .GetProperty("CurrentContext") +#else + .GetRuntimeProperty("CurrentContext") +#endif + .GetValue(null, null); + + if (testContext != null) + { +#if !WINRT && !CORE_CLR + testContextType.InvokeMember("IncrementAssertCount", BindingFlags.InvokeMethod, null, testContext, null); +#else + var method = testContextType.GetRuntimeMethod("IncrementAssertCount", new Type[0]); + method.Invoke(testContext, null); +#endif + } + + object assertionFailureBuilder = Activator.CreateInstance(assertionFailureBuilderType, message); + object assertionFailure; +#if !WINRT && !CORE_CLR + assertionFailureBuilderType.InvokeMember("SetMessage", BindingFlags.InvokeMethod, null, + assertionFailureBuilder, new object[] {message}); + assertionFailure = assertionFailureBuilderType.InvokeMember("ToAssertionFailure", + BindingFlags.InvokeMethod, null, assertionFailureBuilder, null); +#else + var setMessageMethod = assertionFailureBuilderType.GetRuntimeMethod("SetMessage", new [] {typeof(string)}); + setMessageMethod.Invoke(assertionFailureBuilder, new object[] {message}); + + var toAssertionFailureMethod = assertionFailureBuilderType.GetRuntimeMethod("ToAssertionFailure", new Type[0]); + assertionFailure = toAssertionFailureMethod.Invoke(assertionFailureBuilder, null); +#endif + try + { +#if !WINRT && !CORE_CLR + assertionHelperType.InvokeMember("Fail", BindingFlags.InvokeMethod, null, null, new[] {assertionFailure}); +#else + var failMethod = assertionHelperType.GetRuntimeMethods().First(m => m.Name == "Fail"); + failMethod.Invoke(null, new[] {assertionFailure}); +#endif + } + catch (TargetInvocationException ex) + { + throw ex.InnerException; + } + } + + /// + /// Gets a value indicating whether the corresponding test framework is currently available. + /// + public bool IsAvailable + { + get + { +#if CORE_CLR + // For CoreCLR, we need to attempt to load the assembly + try + { + assembly = Assembly.Load(new AssemblyName(AssemblyName) { Version = new Version(0, 0, 0, 0) }); + return assembly != null; + } + catch + { + return false; + } +#else + assembly = AppDomain.CurrentDomain.GetAssemblies() + .FirstOrDefault(a => a.GetName().Name.Equals(AssemblyName, StringComparison.InvariantCultureIgnoreCase)); + + return (assembly != null); +#endif + } + } + + private string AssemblyName + { + get { return "Gallio"; } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/GallioTestFramework.cs.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/GallioTestFramework.cs.meta new file mode 100644 index 0000000..805c1d4 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/GallioTestFramework.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a3a51c37612d3254b89d6d7258d46e11 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MSTestFramework.cs b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MSTestFramework.cs new file mode 100644 index 0000000..ef30171 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MSTestFramework.cs @@ -0,0 +1,15 @@ +namespace FluentAssertions.Execution +{ + internal class MSTestFramework : LateBoundTestFramework + { + protected override string ExceptionFullName + { + get { return "Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException"; } + } + + protected override string AssemblyName + { + get { return "Microsoft.VisualStudio.QualityTools.UnitTestFramework"; } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MSTestFramework.cs.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MSTestFramework.cs.meta new file mode 100644 index 0000000..e91c6f1 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MSTestFramework.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 358c3c6299f66c94ea43cb1852b4016c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MSTestFrameworkV2.cs b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MSTestFrameworkV2.cs new file mode 100644 index 0000000..2651447 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MSTestFrameworkV2.cs @@ -0,0 +1,15 @@ +namespace FluentAssertions.Execution +{ + internal class MSTestFrameworkV2 : LateBoundTestFramework + { + protected override string ExceptionFullName + { + get { return "Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException"; } + } + + protected override string AssemblyName + { + get { return "Microsoft.VisualStudio.TestPlatform.TestFramework"; } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MSTestFrameworkV2.cs.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MSTestFrameworkV2.cs.meta new file mode 100644 index 0000000..97e8083 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MSTestFrameworkV2.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5a48aa4e32254594cac1eb02b21b3c1a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MSpecFramework.cs b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MSpecFramework.cs new file mode 100644 index 0000000..404121e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MSpecFramework.cs @@ -0,0 +1,15 @@ +namespace FluentAssertions.Execution +{ + internal class MSpecFramework : LateBoundTestFramework + { + protected override string AssemblyName + { + get { return "Machine.Specifications"; } + } + + protected override string ExceptionFullName + { + get { return "Machine.Specifications.SpecificationException"; } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MSpecFramework.cs.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MSpecFramework.cs.meta new file mode 100644 index 0000000..6a86ed7 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MSpecFramework.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4ec338f53f3f642448cf6a7d7aa37e3b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MbUnitTestFramework.cs b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MbUnitTestFramework.cs new file mode 100644 index 0000000..5a70015 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MbUnitTestFramework.cs @@ -0,0 +1,15 @@ +namespace FluentAssertions.Execution + { + internal class MbUnitTestFramework : LateBoundTestFramework + { + protected override string AssemblyName + { + get { return "MbUnit.Framework"; } + } + + protected override string ExceptionFullName + { + get { return "MbUnit.Core.Exceptions.AssertionException"; } + } + } + } \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MbUnitTestFramework.cs.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MbUnitTestFramework.cs.meta new file mode 100644 index 0000000..ffee4a4 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/MbUnitTestFramework.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c967f9958ab9d1d4ab9212b3d102a0e8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/NUnitTestFramework.cs b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/NUnitTestFramework.cs new file mode 100644 index 0000000..38dd756 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/NUnitTestFramework.cs @@ -0,0 +1,15 @@ +namespace FluentAssertions.Execution +{ + internal class NUnitTestFramework : LateBoundTestFramework + { + protected override string AssemblyName + { + get { return "nunit.framework"; } + } + + protected override string ExceptionFullName + { + get { return "NUnit.Framework.AssertionException"; } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/NUnitTestFramework.cs.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/NUnitTestFramework.cs.meta new file mode 100644 index 0000000..993dc6f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/NUnitTestFramework.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2a850dd67ddc2ab4baa2dbad8f770f0b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/TestFrameworkProvider.cs b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/TestFrameworkProvider.cs new file mode 100644 index 0000000..1ea9da8 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/TestFrameworkProvider.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +#if !WINRT +using System.Configuration; +#endif + +namespace FluentAssertions.Execution +{ + internal static class TestFrameworkProvider + { + #region Private Definitions + + private const string AppSettingKey = "FluentAssertions.TestFramework"; + + private static readonly Dictionary frameworks = new Dictionary + { + { "nunit", new NUnitTestFramework() }, + { "xunit", new XUnitTestFramework() }, + { "mspec", new MSpecFramework() }, + { "mbunit", new MbUnitTestFramework() }, + { "gallio", new GallioTestFramework() }, + { "mstest", new MSTestFramework() }, +#if NET45 + { "xunit2", new XUnit2TestFramework()}, + { "mstestv2", new MSTestFrameworkV2() }, +#endif + { "fallback", new FallbackTestFramework() } + }; + + private static ITestFramework testFramework; + + #endregion + + public static void Throw(string message) + { + if (testFramework == null) + { + testFramework = DetectFramework(); + } + + testFramework.Throw(message); + } + + private static ITestFramework DetectFramework() + { + ITestFramework detectedFramework = null; + + detectedFramework = AttemptToDetectUsingAppSetting(); + if (detectedFramework == null) + { + detectedFramework = AttemptToDetectUsingAssemblyScanning(); + } + + if (detectedFramework == null) + { + FailWithIncorrectConfiguration(); + } + + return detectedFramework; + } + + private static void FailWithIncorrectConfiguration() + { + string errorMessage = + "Failed to detect the test framework. Make sure that the framework assembly is copied into the test run directory" + + ", or configure it explicitly in the section using key \"" + AppSettingKey + + "\" and one of the supported " + + " frameworks: " + string.Join(", ", frameworks.Keys.ToArray()); + + throw new InvalidOperationException(errorMessage); + } + + private static ITestFramework AttemptToDetectUsingAppSetting() + { + string frameworkName = null; //ConfigurationManager.AppSettings[AppSettingKey]; + + if (!string.IsNullOrEmpty(frameworkName) && frameworks.ContainsKey(frameworkName.ToLower())) + { + ITestFramework framework = frameworks[frameworkName.ToLower()]; + if (!framework.IsAvailable) + { + throw new Exception( + "FluentAssertions was configured to use " + frameworkName + + " but the required test framework assembly could not be found"); + } + + return framework; + } + + return null; + } + + private static ITestFramework AttemptToDetectUsingAssemblyScanning() + { + return frameworks.Values.FirstOrDefault(framework => framework.IsAvailable); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/TestFrameworkProvider.cs.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/TestFrameworkProvider.cs.meta new file mode 100644 index 0000000..23a1756 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/TestFrameworkProvider.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 46776399f5ea0484eba48bdf8075bc9e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/XUnitTestFramework.cs b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/XUnitTestFramework.cs new file mode 100644 index 0000000..efc6456 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/XUnitTestFramework.cs @@ -0,0 +1,15 @@ +namespace FluentAssertions.Execution +{ + internal class XUnitTestFramework : LateBoundTestFramework + { + protected override string AssemblyName + { + get { return "xunit"; } + } + + protected override string ExceptionFullName + { + get { return "Xunit.Sdk.AssertException"; } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/XUnitTestFramework.cs.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/XUnitTestFramework.cs.meta new file mode 100644 index 0000000..33c07ae --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Execution/XUnitTestFramework.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cf3b9f2b5ad37654aa94e629233971fc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/ObjectAssertionsExtensions.cs b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/ObjectAssertionsExtensions.cs new file mode 100644 index 0000000..0f21952 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/ObjectAssertionsExtensions.cs @@ -0,0 +1,183 @@ +using System; +using System.IO; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; +using System.Text; +using System.Xml.Serialization; + +using FluentAssertions.Equivalency; +using FluentAssertions.Execution; +using FluentAssertions.Primitives; + +namespace FluentAssertions +{ + public static class ObjectAssertionsExtensions + { + /// + /// Asserts that an object can be serialized and deserialized using the binary serializer and that it stills retains + /// the values of all members. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public static AndConstraint BeBinarySerializable(this ObjectAssertions assertions, string because = "", + params object[] becauseArgs) + { + return BeBinarySerializable(assertions, options => options, because, becauseArgs); + } + + /// + /// Asserts that an object can be serialized and deserialized using the binary serializer and that it stills retains + /// the values of all members. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public static AndConstraint BeBinarySerializable(this ObjectAssertions assertions, + Func, EquivalencyAssertionOptions> options, string because = "", + params object[] becauseArgs) + { + try + { + object deserializedObject = CreateCloneUsingBinarySerializer(assertions.Subject); + + EquivalencyAssertionOptions defaultOptions = AssertionOptions.CloneDefaults() + .RespectingRuntimeTypes().IncludingFields().IncludingProperties(); + + ((T)deserializedObject).ShouldBeEquivalentTo(assertions.Subject, _ => options(defaultOptions)); + } + catch (Exception exc) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {0} to be serializable{reason}, but serialization failed with:\r\n\r\n{1}", + assertions.Subject, + exc.Message); + } + + return new AndConstraint(assertions); + } + + /// + /// Asserts that an object can be serialized and deserialized using the data contract serializer and that it stills retains + /// the values of all members. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public static AndConstraint BeDataContractSerializable(this ObjectAssertions assertions, + string because = "", params object[] becauseArgs) + { + return BeDataContractSerializable(assertions, because, becauseArgs); + } + + /// + /// Asserts that an object can be serialized and deserialized using the data contract serializer and that it stills retains + /// the values of all members. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public static AndConstraint BeDataContractSerializable(this ObjectAssertions assertions, + string because = "", params object[] becauseArgs) + { + try + { + var deserializedObject = CreateCloneUsingDataContractSerializer(assertions.Subject); + + deserializedObject.ShouldBeEquivalentTo(assertions.Subject, + options => options.RespectingRuntimeTypes().IncludingFields().IncludingProperties()); + } + catch (Exception exc) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {0} to be serializable{reason}, but serialization failed with:\r\n\r\n{1}", + assertions.Subject, + exc.Message); + } + + return new AndConstraint(assertions); + } + + private static object CreateCloneUsingBinarySerializer(object subject) + { + var stream = new MemoryStream(); + var binaryFormatter = new BinaryFormatter(); + binaryFormatter.Serialize(stream, subject); + + stream.Position = 0; + return binaryFormatter.Deserialize(stream); + } + + private static object CreateCloneUsingDataContractSerializer(object subject) + { + using (var stream = new MemoryStream()) + { + var serializer = new DataContractSerializer(subject.GetType()); + serializer.WriteObject(stream, subject); + stream.Position = 0; + return serializer.ReadObject(stream); + } + } + + /// + /// Asserts that an object can be serialized and deserialized using the XML serializer and that it stills retains + /// the values of all members. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public static AndConstraint BeXmlSerializable(this ObjectAssertions assertions, string because = "", + params object[] becauseArgs) + { + try + { + object deserializedObject = CreateCloneUsingXmlSerializer(assertions.Subject); + + deserializedObject.ShouldBeEquivalentTo(assertions.Subject, + options => options.RespectingRuntimeTypes().IncludingFields().IncludingProperties()); + } + catch (Exception exc) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Expected {0} to be serializable{reason}, but serialization failed with:\r\n\r\n{1}", + assertions.Subject, + exc.Message); + } + + return new AndConstraint(assertions); + } + + private static object CreateCloneUsingXmlSerializer(object subject) + { + var stream = new MemoryStream(); + var binaryFormatter = new XmlSerializer(subject.GetType()); + binaryFormatter.Serialize(stream, subject); + + stream.Position = 0; + return binaryFormatter.Deserialize(stream); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/ObjectAssertionsExtensions.cs.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/ObjectAssertionsExtensions.cs.meta new file mode 100644 index 0000000..5194eb9 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/ObjectAssertionsExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4cbab2505e3a904448917e84c97ce255 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Properties.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Properties.meta new file mode 100644 index 0000000..6cb9cb5 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Properties.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7350abd898b0e534eab0c39879d946db +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Properties/AssemblyInfo.cs b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..c409423 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Properties/AssemblyInfo.cs @@ -0,0 +1,14 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Fluent Assertions")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyProduct("Fluent Assertions")] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("796bb2ec-18ec-46fe-aa02-5a62902a63fa")] diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Properties/AssemblyInfo.cs.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Properties/AssemblyInfo.cs.meta new file mode 100644 index 0000000..39178ff --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Properties/AssemblyInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 769cc62351460244aa7ec3d0433afd88 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml.meta new file mode 100644 index 0000000..80a096c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 30ac0923a1e5e224d81be916bcaea529 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlAssertionExtensions.cs b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlAssertionExtensions.cs new file mode 100644 index 0000000..9110240 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlAssertionExtensions.cs @@ -0,0 +1,25 @@ +using FluentAssertions.Xml; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + +namespace FluentAssertions +{ + [DebuggerNonUserCode] + public static class XmlAssertionExtensions + { + public static XmlNodeAssertions Should(this XmlNode actualValue) + { + return new XmlNodeAssertions(actualValue); + } + + public static XmlElementAssertions Should(this XmlElement actualValue) + { + return new XmlElementAssertions(actualValue); + } + } +} diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlAssertionExtensions.cs.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlAssertionExtensions.cs.meta new file mode 100644 index 0000000..ae56b48 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlAssertionExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3165aa4f19da1ea40901cb2b89552fe4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlElementAssertions.cs b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlElementAssertions.cs new file mode 100644 index 0000000..a4d7f19 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlElementAssertions.cs @@ -0,0 +1,226 @@ +using FluentAssertions.Common; +using FluentAssertions.Execution; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Xml; + +namespace FluentAssertions.Xml +{ + /// + /// Cointains a number of methods to assert that an + /// is in the expected state./> + /// + [DebuggerNonUserCode] + public class XmlElementAssertions : XmlNodeAssertions + { + /// + /// Initialized a new instance of the + /// class. + /// + /// + public XmlElementAssertions(XmlElement xmlElement) + : base (xmlElement) + { } + + /// + /// Asserts taht the current has the specified + /// inner text. + /// + /// The expected value. + public AndConstraint HaveInnerText(string expected) + { + return HaveInnerText(expected, string.Empty); + } + + /// + /// Asserts that the current has the specified + /// inner text. + /// + /// The expected value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveInnerText(string expected, string because, params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.InnerText == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected XML element {0} to have value {1}{reason}, but found {2}.", + Subject.Name, expected, Subject.InnerText); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current has an attribute + /// with the specified + /// and . + /// + /// The name of the expected attribute + /// The value of the expected attribute + + public AndConstraint HaveAttribute(string expectedName, string expectedValue) + { + return HaveAttribute(expectedName, expectedValue, string.Empty); + } + + /// + /// Asserts that the current has an attribute + /// with the specified + /// and . + /// + /// The name of the expected attribute + /// The value of the expected attribute + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveAttribute(string expectedName, string expectedValue, string because, params object[] becauseArgs) + { + return HaveAttributeWithNamespace(expectedName, string.Empty, expectedValue, because, becauseArgs); + } + + /// + /// Asserts that the current has an attribute + /// with the specified , + /// and . + /// + /// The name of the expected attribute + /// The value of the expected attribute + public AndConstraint HaveAttributeWithNamespace(string expectedName, string expectedNamespace, string expectedValue) + { + return HaveAttributeWithNamespace(expectedName, expectedNamespace, expectedValue, string.Empty); + } + + /// + /// Asserts that the current has an attribute + /// with the specified , + /// and . + /// + /// The name of the expected attribute + /// The value of the expected attribute + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveAttributeWithNamespace( + string expectedName, + string expectedNamespace, + string expectedValue, + string because, params object[] becauseArgs) + { + XmlAttribute attribute = Subject.Attributes[expectedName, expectedNamespace]; + + string expectedFormattedName = + (string.IsNullOrEmpty(expectedNamespace) ? "" : "{" + expectedNamespace + "}") + + expectedName; + + Execute.Assertion + .ForCondition(attribute != null) + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected XML element to have attribute {0}" + + " with value {1}{reason}, but found no such attribute in {2}", + expectedFormattedName, expectedValue, Subject); + + Execute.Assertion + .ForCondition(attribute.Value == expectedValue) + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected XML attribute {0} to have value {1}{reason}, but found {2}.", + expectedFormattedName, expectedValue, attribute.Value); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current has a direct child element with the specified + /// name. + /// + /// The name of the expected child element + public AndWhichConstraint HaveElement(string expectedName) + { + return HaveElement(expectedName, string.Empty); + } + + /// + /// Asserts that the current has a direct child element with the specified + /// name. + /// + /// The name of the expected child element + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndWhichConstraint HaveElement( + string expectedName, + string because, + params object[] becauseArgs) + { + return HaveElementWithNamespace(expectedName, string.Empty, because, becauseArgs); + } + + /// + /// Asserts that the current has a direct child element with the specified + /// name and namespace. + /// + /// The name of the expected child element + /// The namespace of the expected child element + public AndWhichConstraint HaveElementWithNamespace( + string expectedName, string expectedNamespace) + { + return HaveElementWithNamespace(expectedName, expectedNamespace, string.Empty); + } + + /// + /// Asserts that the current has a direct child element with the specified + /// name and namespace. + /// + /// The name of the expected child element + /// The namespace of the expected child element + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndWhichConstraint HaveElementWithNamespace( + string expectedName, + string expectedNamespace, + string because, + params object[] becauseArgs) + { + XmlElement element = Subject[expectedName, expectedNamespace]; + + string expectedFormattedName = + (string.IsNullOrEmpty(expectedNamespace) ? "" : "{" + expectedNamespace + "}") + + expectedName; + + Execute.Assertion + .ForCondition(element != null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected XML element {0} to have child element \"" + + expectedFormattedName.ToString().Escape(escapePlaceholders: true) + "\"{reason}" + + ", but no such child element was found.", Subject); + + return new AndWhichConstraint(this, element); + } + } +} diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlElementAssertions.cs.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlElementAssertions.cs.meta new file mode 100644 index 0000000..235a1b3 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlElementAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f3b776fb3b595494a9817d3036f9ce3a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlNodeAssertions.cs b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlNodeAssertions.cs new file mode 100644 index 0000000..ae56d3b --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlNodeAssertions.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Xml; + +namespace FluentAssertions.Xml +{ + /// + /// Contains a number of methods to assert that an is in the expected state. + /// + [DebuggerNonUserCode] + public class XmlNodeAssertions : XmlNodeAssertions + { + public XmlNodeAssertions(XmlNode xmlNode) + : base(xmlNode) + { } + } +} diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlNodeAssertions.cs.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlNodeAssertions.cs.meta new file mode 100644 index 0000000..cca983c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlNodeAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 59e93ceec3fd35943be65d277bd294f1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlNodeAssertionsofTSubjectTAssertions.cs b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlNodeAssertionsofTSubjectTAssertions.cs new file mode 100644 index 0000000..2fa1d05 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlNodeAssertionsofTSubjectTAssertions.cs @@ -0,0 +1,97 @@ +using FluentAssertions.Execution; +using FluentAssertions.Primitives; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using System.Xml; + +namespace FluentAssertions.Xml +{ + /// + /// Contains a number of methods to assert that an is in the expected state. + /// + [DebuggerNonUserCode] + public class XmlNodeAssertions : ReferenceTypeAssertions + where TAssertions: XmlNodeAssertions + where TSubject : XmlNode + { + public XmlNodeAssertions(TSubject xmlNode) + { + Subject = xmlNode; + } + + /// + /// Asserts that the current is equivalent to the element. + /// + /// The expected element + public AndConstraint BeEquivalentTo(XmlNode expected) + { + return BeEquivalentTo(expected, string.Empty); + } + + /// + /// Asserts that the current is equivalent to the node. + /// + /// The expected node + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeEquivalentTo(XmlNode expected, string because, params object[] reasonArgs) + { + using (XmlNodeReader subjectReader = new XmlNodeReader(Subject)) + using (XmlNodeReader expectedReader = new XmlNodeReader(expected)) + { + new XmlReaderValidator(subjectReader, expectedReader, because, reasonArgs).Validate(true); + } + + return new AndConstraint((TAssertions)(this)); + } + + /// + /// Asserts that the current is not equivalent to + /// the node. + /// + /// The unexpected node + public AndConstraint NotBeEquivalentTo(XmlNode unexpected) + { + return NotBeEquivalentTo(unexpected, string.Empty); + } + + /// + /// Asserts that the current is not equivalent to + /// the node. + /// + /// The unexpected node + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + /// + public AndConstraint NotBeEquivalentTo(XmlNode unexpected, string because, params object[] reasonArgs) + { + using (XmlNodeReader subjectReader = new XmlNodeReader(Subject)) + using (XmlNodeReader unexpectedReader = new XmlNodeReader(unexpected)) + { + new XmlReaderValidator(subjectReader, unexpectedReader, because, reasonArgs).Validate(false); + } + + return new AndConstraint((TAssertions)this); + } + + /// + /// Returns the type of the subject the assertion applies on. + /// + protected override string Context + { + get { return "Xml Node"; } + } + } +} diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlNodeAssertionsofTSubjectTAssertions.cs.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlNodeAssertionsofTSubjectTAssertions.cs.meta new file mode 100644 index 0000000..789dfae --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlNodeAssertionsofTSubjectTAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d59018b5b2583c7469a5633533a8a9cb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlNodeFormatter.cs b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlNodeFormatter.cs new file mode 100644 index 0000000..6eb5992 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlNodeFormatter.cs @@ -0,0 +1,33 @@ +using FluentAssertions.Common; +using FluentAssertions.Formatting; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + +namespace FluentAssertions.Xml +{ + public class XmlNodeFormatter : IValueFormatter + { + public bool CanHandle(object value) + { + return value is XmlNode; + } + + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + string outerXml = ((XmlNode)value).OuterXml; + + int maxLength = 20; + + if(outerXml.Length > maxLength) + { + outerXml = outerXml.Substring(0, maxLength).TrimEnd() + "..."; + } + + return outerXml.Escape(escapePlaceholders: true); + } + } +} diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlNodeFormatter.cs.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlNodeFormatter.cs.meta new file mode 100644 index 0000000..8e3203c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.Net40/Xml/XmlNodeFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4b43049c07715a9418c41372fa616bd1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.asmdef b/Assets/Plugins/FluentAssertions/FluentAssertions.asmdef new file mode 100644 index 0000000..2ed681b --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.asmdef @@ -0,0 +1,10 @@ +{ + "name": "FluentAssertions", + "references": [], + "optionalUnityReferences": [ + "TestAssemblies" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/FluentAssertions.asmdef.meta b/Assets/Plugins/FluentAssertions/FluentAssertions.asmdef.meta new file mode 100644 index 0000000..bf1dd8e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/FluentAssertions.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 75159f8081e8d4e48b0048ffc41722d6 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/LICENSE b/Assets/Plugins/FluentAssertions/LICENSE new file mode 100644 index 0000000..37ec93a --- /dev/null +++ b/Assets/Plugins/FluentAssertions/LICENSE @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Assets/Plugins/FluentAssertions/LICENSE.meta b/Assets/Plugins/FluentAssertions/LICENSE.meta new file mode 100644 index 0000000..ef8f879 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/LICENSE.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 494e1af59799d1341912669d678ba4b2 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/README.md b/Assets/Plugins/FluentAssertions/README.md new file mode 100644 index 0000000..8c6dc22 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/README.md @@ -0,0 +1,15 @@ +[![](https://ci.appveyor.com/api/projects/status/h60mq3e5uf5tuout/branch/master?svg=true)](https://ci.appveyor.com/project/dennisdoomen/fluentassertions/branch/master) +[![](https://img.shields.io/github/release/FluentAssertions/FluentAssertions.svg?label=latest%20release)](https://github.com/FluentAssertions/FluentAssertions/releases/latest) +[![](https://img.shields.io/nuget/dt/FluentAssertions.svg?label=nuget%20downloads)](https://www.nuget.org/packages/FluentAssertions) +[![](https://img.shields.io/librariesio/dependents/nuget/FluentAssertions.svg?label=dependent%20libraries)](https://libraries.io/nuget/FluentAssertions) +![](https://img.shields.io/badge/release%20strategy-githubflow-orange.svg) + +# What is this and why do I need this? +See https://www.fluentassertions.com for background information, usage documentation, an extensibility guide, support information and more tips & tricks. + +# How do I build this? +Install Visual Studio 2017 or JetBrains Rider 2017.1 and Build Tools 2017 and run + +`build.ps1` + + diff --git a/Assets/Plugins/FluentAssertions/README.md.meta b/Assets/Plugins/FluentAssertions/README.md.meta new file mode 100644 index 0000000..66ff338 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 726c63f9b29f850489623a0a9ee60b70 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared.meta b/Assets/Plugins/FluentAssertions/Shared.meta new file mode 100644 index 0000000..4df11f7 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b781bc6f57e31db40b5376b9ba2cc22e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/AssertionExtensions.Actions.cs b/Assets/Plugins/FluentAssertions/Shared/AssertionExtensions.Actions.cs new file mode 100644 index 0000000..26c4dc0 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/AssertionExtensions.Actions.cs @@ -0,0 +1,222 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; + +using FluentAssertions.Common; +using FluentAssertions.Specialized; + +namespace FluentAssertions +{ + public static partial class AssertionExtensions + { + private static readonly AggregateExceptionExtractor extractor = new AggregateExceptionExtractor(); + + /// + /// Asserts that the throws the exact exception (and not a derived exception type). + /// + /// A reference to the method or property. + /// + /// The type of the exception it should throw. + /// + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + /// + /// Returns an object that allows asserting additional members of the thrown exception. + /// + public static ExceptionAssertions ShouldThrowExactly(this Action action, string because = "", + params object[] becauseArgs) + where TException : Exception + { + var exceptionAssertions = action.ShouldThrow(because, becauseArgs); + exceptionAssertions.Which.GetType().Should().Be(because, becauseArgs); + return exceptionAssertions; + } + + /// + /// Asserts that the throws the exact exception (and not a derived exception type). + /// + /// A reference to the method or property. + /// + /// The type of the exception it should throw. + /// + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + /// + /// Returns an object that allows asserting additional members of the thrown exception. + /// + public static ExceptionAssertions ShouldThrowExactly(this Func asyncAction, string because = "", + params object[] becauseArgs) + where TException : Exception + { + var exceptionAssertions = asyncAction.ShouldThrow(because, becauseArgs); + exceptionAssertions.Which.GetType().Should().Be(because, becauseArgs); + return exceptionAssertions; + } + + /// + /// Asserts that the throws an exception. + /// + /// A reference to the method or property. + /// + /// The type of the exception it should throw. + /// + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + /// + /// Returns an object that allows asserting additional members of the thrown exception. + /// + public static ExceptionAssertions ShouldThrow(this Action action, string because = "", + params object[] becauseArgs) + where TException : Exception + { + return new ActionAssertions(action, extractor).ShouldThrow(because, becauseArgs); + } + + /// + /// Asserts that the does not throw a particular exception. + /// + /// The current method or property. + /// + /// The type of the exception it should not throw. Any other exceptions are ignored and will satisfy the assertion. + /// + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public static void ShouldNotThrow(this Action action, string because = "", params object[] becauseArgs) + where TException : Exception + { + new ActionAssertions(action, extractor).ShouldNotThrow(because, becauseArgs); + } + + /// + /// Asserts that the does not throw any exception at all. + /// + /// The current method or property. + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public static void ShouldNotThrow(this Action action, string because = "", params object[] becauseArgs) + { + new ActionAssertions(action, extractor).ShouldNotThrow(because, becauseArgs); + } + + /// + /// Asserts that the throws an exception. + /// + /// A reference to the method or property. + /// + /// The type of the exception it should throw. + /// + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + /// + /// Returns an object that allows asserting additional members of the thrown exception. + /// + public static ExceptionAssertions ShouldThrow(this Func asyncAction, string because = "", + params object[] becauseArgs) + where TException : Exception + { + return new AsyncFunctionAssertions(asyncAction, extractor).ShouldThrow(because, becauseArgs); + } + + /// + /// Asserts that the does not throw a particular exception. + /// + /// The current method or property. + /// + /// The type of the exception it should not throw. Any other exceptions are ignored and will satisfy the assertion. + /// + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public static void ShouldNotThrow(this Func asyncAction, string because = "", params object[] becauseArgs) + { + new AsyncFunctionAssertions(asyncAction, extractor).ShouldNotThrow(because, becauseArgs); + } + + /// + /// Asserts that the does not throw any exception at all. + /// + /// The current method or property. + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public static void ShouldNotThrow(this Func asyncAction, string because = "", params object[] becauseArgs) + { + new AsyncFunctionAssertions(asyncAction, extractor).ShouldNotThrow(because, becauseArgs); + } + + private class AggregateExceptionExtractor : IExtractExceptions + { + public IEnumerable OfType(Exception actualException) where T : Exception + { + if (typeof(T).IsSameOrInherits(typeof(AggregateException))) + { + var exception = actualException as T; + + return (exception == null) ? Enumerable.Empty() : new[] { exception }; + } + + return GetExtractedExceptions(actualException); + } + + private static List GetExtractedExceptions(Exception actualException) + where T : Exception + { + var exceptions = new List(); + + var aggregateException = actualException as AggregateException; + if (aggregateException != null) + { + var flattenedExceptions = aggregateException.Flatten(); + + exceptions.AddRange(flattenedExceptions.InnerExceptions.OfType()); + } + else if (actualException is T) + { + exceptions.Add((T)actualException); + } + + return exceptions; + } + } + } +} diff --git a/Assets/Plugins/FluentAssertions/Shared/AssertionExtensions.Actions.cs.meta b/Assets/Plugins/FluentAssertions/Shared/AssertionExtensions.Actions.cs.meta new file mode 100644 index 0000000..a3e5c48 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/AssertionExtensions.Actions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 988088d8b6a099e44862fb547c431a2c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/AssertionExtensions.cs b/Assets/Plugins/FluentAssertions/Shared/AssertionExtensions.cs new file mode 100644 index 0000000..ea1fc94 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/AssertionExtensions.cs @@ -0,0 +1,762 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Xml.Linq; +using FluentAssertions.Collections; +using FluentAssertions.Equivalency; +using FluentAssertions.Events; +using FluentAssertions.Numeric; +using FluentAssertions.Primitives; +using FluentAssertions.Reflection; +using FluentAssertions.Types; +using FluentAssertions.Xml; +using JetBrains.Annotations; + +#if !SILVERLIGHT && !PORTABLE +using System.Linq.Expressions; +using FluentAssertions.Specialized; +#endif +#if SILVERLIGHT || WINRT || PORTABLE || CORE_CLR +using System.ComponentModel; +#endif +#if NET45 || WINRT || CORE_CLR +using System.Threading.Tasks; + +#endif + +namespace FluentAssertions +{ + /// + /// Contains extension methods for custom assertions in unit tests. + /// + [DebuggerNonUserCode] + public static partial class AssertionExtensions + { + /// + /// Invokes the specified action on an subject so that you can chain it with any of the ShouldThrow or ShouldNotThrow + /// overloads. + /// + [Pure] + public static Action Invoking(this T subject, Action action) + { + return () => action(subject); + } + +#if NET45 || WINRT || CORE_CLR + [Pure] + public static Func Awaiting(this T subject, Func action) + { + return () => action(subject); + } +#endif + +#if !SILVERLIGHT && !PORTABLE + + /// + /// Provides methods for asserting the execution time of a method or property. + /// + /// The object that exposes the method or property. + /// A reference to the method or property to measure the execution time of. + /// + /// Returns an object for asserting that the execution time matches certain conditions. + /// + //[MustUseReturnValue /* do not use Pure because this method executes the action before returning to the caller */] + public static MemberExecutionTimeAssertions ExecutionTimeOf(this T subject, Expression> action) + { + return new MemberExecutionTimeAssertions(subject, action); + } + + /// + /// Provides methods for asserting the execution time of a method or property. + /// + /// A reference to the method or property to measure the execution time of. + /// + /// Returns an object for asserting that the execution time matches certain conditions. + /// + //[MustUseReturnValue /* do not use Pure because this method executes the action before returning to the caller */] + public static ExecutionTimeAssertions ExecutionTime(this Action action) + { + return new ExecutionTimeAssertions(action); + } + +#endif + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static AssemblyAssertions Should(this Assembly assembly) + { + return new AssemblyAssertions(assembly); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static XDocumentAssertions Should(this XDocument actualValue) + { + return new XDocumentAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static XElementAssertions Should(this XElement actualValue) + { + return new XElementAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static XAttributeAssertions Should(this XAttribute actualValue) + { + return new XAttributeAssertions(actualValue); + } + + /// + /// Forces enumerating a collection. Should be used to assert that a method that uses the + /// yield keyword throws a particular exception. + /// + [Pure] + public static Action Enumerating(this Func enumerable) + { + return () => ForceEnumeration(enumerable); + } + + /// + /// Forces enumerating a collection. Should be used to assert that a method that uses the + /// yield keyword throws a particular exception. + /// + [Pure] + public static Action Enumerating(this Func> enumerable) + { + return () => ForceEnumeration(enumerable); + } + + private static void ForceEnumeration(Func enumerable) + { + foreach (object _ in enumerable()) + { + // Do nothing + } + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static ObjectAssertions Should(this object actualValue) + { + return new ObjectAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static BooleanAssertions Should(this bool actualValue) + { + return new BooleanAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + [Pure] + public static NullableBooleanAssertions Should(this bool? actualValue) + { + return new NullableBooleanAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static GuidAssertions Should(this Guid actualValue) + { + return new GuidAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + [Pure] + public static NullableGuidAssertions Should(this Guid? actualValue) + { + return new NullableGuidAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static NonGenericCollectionAssertions Should(this IEnumerable actualValue) + { + return new NonGenericCollectionAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static GenericCollectionAssertions Should(this IEnumerable actualValue) + { + return new GenericCollectionAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static StringCollectionAssertions Should(this IEnumerable @this) + { + return new StringCollectionAssertions(@this); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static GenericDictionaryAssertions Should(this IDictionary actualValue) + { + return new GenericDictionaryAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static DateTimeAssertions Should(this DateTime actualValue) + { + return new DateTimeAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static DateTimeOffsetAssertions Should(this DateTimeOffset actualValue) + { + return new DateTimeOffsetAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + [Pure] + public static NullableDateTimeAssertions Should(this DateTime? actualValue) + { + return new NullableDateTimeAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + [Pure] + public static NullableDateTimeOffsetAssertions Should(this DateTimeOffset? actualValue) + { + return new NullableDateTimeOffsetAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static ComparableTypeAssertions Should(this IComparable comparableValue) + { + return new ComparableTypeAssertions(comparableValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static NumericAssertions Should(this int actualValue) + { + return new NumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + [Pure] + public static NullableNumericAssertions Should(this int? actualValue) + { + return new NullableNumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static NumericAssertions Should(this decimal actualValue) + { + return new NumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + [Pure] + public static NullableNumericAssertions Should(this decimal? actualValue) + { + return new NullableNumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static NumericAssertions Should(this byte actualValue) + { + return new NumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + [Pure] + public static NullableNumericAssertions Should(this byte? actualValue) + { + return new NullableNumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static NumericAssertions Should(this short actualValue) + { + return new NumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + [Pure] + public static NullableNumericAssertions Should(this short? actualValue) + { + return new NullableNumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static NumericAssertions Should(this long actualValue) + { + return new NumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + [Pure] + public static NullableNumericAssertions Should(this long? actualValue) + { + return new NullableNumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static NumericAssertions Should(this float actualValue) + { + return new NumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + [Pure] + public static NullableNumericAssertions Should(this float? actualValue) + { + return new NullableNumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static NumericAssertions Should(this double actualValue) + { + return new NumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + [Pure] + public static NullableNumericAssertions Should(this double? actualValue) + { + return new NullableNumericAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static StringAssertions Should(this string actualValue) + { + return new StringAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current . + /// + [Pure] + public static SimpleTimeSpanAssertions Should(this TimeSpan actualValue) + { + return new SimpleTimeSpanAssertions(actualValue); + } + + /// + /// Returns an object that can be used to assert the + /// current nullable . + /// + [Pure] + public static NullableSimpleTimeSpanAssertions Should(this TimeSpan? actualValue) + { + return new NullableSimpleTimeSpanAssertions(actualValue); + } + + /// + /// Returns a object that can be used to assert the + /// current . + /// + [Pure] + public static TypeAssertions Should(this Type subject) + { + return new TypeAssertions(subject); + } + + /// + /// Returns a object that can be used to assert the + /// current . + /// + [Pure] + public static TypeSelectorAssertions Should(this TypeSelector typeSelector) + { + return new TypeSelectorAssertions(typeSelector.ToArray()); + } + + /// + /// Returns a object that can be used to assert the current . + /// + /// + [Pure] + public static ConstructorInfoAssertions Should(this ConstructorInfo constructorInfo) + { + return new ConstructorInfoAssertions(constructorInfo); + } + + /// + /// Returns a object that can be used to assert the current . + /// + /// + [Pure] + public static MethodInfoAssertions Should(this MethodInfo methodInfo) + { + return new MethodInfoAssertions(methodInfo); + } + + /// + /// Returns a object that can be used to assert the methods returned by the + /// current . + /// + /// + [Pure] + public static MethodInfoSelectorAssertions Should(this MethodInfoSelector methodSelector) + { + return new MethodInfoSelectorAssertions(methodSelector.ToArray()); + } + + /// + /// Returns a object that can be used to assert the + /// current . + /// + /// + [Pure] + public static PropertyInfoAssertions Should(this PropertyInfo propertyInfo) + { + return new PropertyInfoAssertions(propertyInfo); + } + + /// + /// Returns a object that can be used to assert the properties returned by the + /// current . + /// + /// + [Pure] + public static PropertyInfoSelectorAssertions Should(this PropertyInfoSelector propertyInfoSelector) + { + return new PropertyInfoSelectorAssertions(propertyInfoSelector.ToArray()); + } + + /// + /// Asserts that all elements in a collection of objects are equivalent to a given object. + /// + /// + /// Objects within the collection are equivalent to given object when both object graphs have equally named properties with the same + /// value, irrespective of the type of those objects. Two properties are also equal if one type can be converted to another + /// and the result is equal. + /// The type of a collection property is ignored as long as the collection implements and all + /// items in the collection are structurally equal. + /// Notice that actual behavior is determined by the global defaults managed by . + /// + /// + /// An optional formatted phrase as is supported by explaining why the + /// assertion is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public static void ShouldAllBeEquivalentTo(this IEnumerable subject, object expectation, + string because = "", params object[] becauseArgs) + { + subject.ShouldAllBeEquivalentTo(expectation, options => options, because, becauseArgs); + } + + /// + /// Asserts that all elements in a collection of objects are equivalent to a given object. + /// + /// + /// Objects within the collection are equivalent to given object when both object graphs have equally named properties with the same + /// value, irrespective of the type of those objects. Two properties are also equal if one type can be converted to another + /// and the result is equal. + /// The type of a collection property is ignored as long as the collection implements and all + /// items in the collection are structurally equal. + /// Notice that actual behavior is determined by the global defaults managed by . + /// + /// + /// A reference to the configuration object that can be used + /// to influence the way the object graphs are compared. You can also provide an alternative instance of the + /// class. The global defaults are determined by the + /// class. + /// + /// + /// An optional formatted phrase as is supported by explaining why the + /// assertion is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public static void ShouldAllBeEquivalentTo(this IEnumerable subject, object expectation, + Func, EquivalencyAssertionOptions> config, string because = "", + params object[] becauseArgs) + { + IEnumerable repeatedExpectation = RepeatAsManyAs(expectation, subject); + + subject.ShouldAllBeEquivalentTo(repeatedExpectation, config, because, becauseArgs); + } + + private static IEnumerable RepeatAsManyAs(object value, IEnumerable enumerable) + { + if (enumerable == null) + { + return Enumerable.Empty(); + } + + return RepeatAsManyAsIterator(value, enumerable); + } + + private static IEnumerable RepeatAsManyAsIterator(object value, IEnumerable enumerable) + { + using (IEnumerator enumerator = enumerable.GetEnumerator()) + { + while (enumerator.MoveNext()) + { + yield return value; + } + } + } + + /// + /// Asserts that a collection of objects is equivalent to another collection of objects. + /// + /// + /// Objects within the collections are equivalent when both object graphs have equally named properties with the same + /// value, irrespective of the type of those objects. Two properties are also equal if one type can be converted to another + /// and the result is equal. + /// The type of a collection property is ignored as long as the collection implements and all + /// items in the collection are structurally equal. + /// Notice that actual behavior is determined by the global defaults managed by . + /// + /// + /// An optional formatted phrase as is supported by explaining why the + /// assertion is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public static void ShouldAllBeEquivalentTo(this IEnumerable subject, IEnumerable expectation, + string because = "", params object[] becauseArgs) + { + subject.ShouldAllBeEquivalentTo(expectation, options => options, because, becauseArgs); + } + + /// + /// Asserts that a collection of objects is equivalent to another collection of objects. + /// + /// + /// Objects within the collections are equivalent when both object graphs have equally named properties with the same + /// value, irrespective of the type of those objects. Two properties are also equal if one type can be converted to another + /// and the result is equal. + /// The type of a collection property is ignored as long as the collection implements and all + /// items in the collection are structurally equal. + /// + /// + /// A reference to the configuration object that can be used + /// to influence the way the object graphs are compared. You can also provide an alternative instance of the + /// class. The global defaults are determined by the + /// class. + /// + /// + /// An optional formatted phrase as is supported by explaining why the + /// assertion is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public static void ShouldAllBeEquivalentTo(this IEnumerable subject, IEnumerable expectation, + Func, EquivalencyAssertionOptions> config, string because = "", + params object[] becauseArgs) + { + EquivalencyAssertionOptions> options = config(AssertionOptions.CloneDefaults()).AsCollection(); + + var context = new EquivalencyValidationContext + { + Subject = subject, + Expectation = expectation, + RootIsCollection = true, + CompileTimeType = typeof(IEnumerable), + Because = because, + BecauseArgs = becauseArgs, + Tracer = options.TraceWriter + }; + + new EquivalencyValidator(options).AssertEquality(context); + } + + /// + /// Asserts that an object is equivalent to another object. + /// + /// + /// Objects are equivalent when both object graphs have equally named properties with the same value, + /// irrespective of the type of those objects. Two properties are also equal if one type can be converted to another and the result is equal. + /// The type of a collection property is ignored as long as the collection implements and all + /// items in the collection are structurally equal. + /// Notice that actual behavior is determined by the global defaults managed by . + /// + /// + /// An optional formatted phrase as is supported by explaining why the + /// assertion is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public static void ShouldBeEquivalentTo(this T subject, object expectation, string because = "", + params object[] becauseArgs) + { + ShouldBeEquivalentTo(subject, expectation, config => config, because, becauseArgs); + } + + /// + /// Asserts that an object is equivalent to another object. + /// + /// + /// Objects are equivalent when both object graphs have equally named properties with the same value, + /// irrespective of the type of those objects. Two properties are also equal if one type can be converted to another and the result is equal. + /// The type of a collection property is ignored as long as the collection implements and all + /// items in the collection are structurally equal. + /// + /// + /// A reference to the configuration object that can be used + /// to influence the way the object graphs are compared. You can also provide an alternative instance of the + /// class. The global defaults are determined by the + /// class. + /// + /// + /// An optional formatted phrase as is supported by explaining why the + /// assertion is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public static void ShouldBeEquivalentTo(this T subject, object expectation, + Func, EquivalencyAssertionOptions> config, string because = "", + params object[] becauseArgs) + { + IEquivalencyAssertionOptions options = config(AssertionOptions.CloneDefaults()); + + var context = new EquivalencyValidationContext + { + Subject = subject, + Expectation = expectation, + CompileTimeType = typeof(T), + Because = because, + BecauseArgs = becauseArgs, + Tracer = options.TraceWriter + }; + + new EquivalencyValidator(options).AssertEquality(context); + } + + + /// + /// Safely casts the specified object to the type specified through . + /// + /// + /// Has been introduced to allow casting objects without breaking the fluent API. + /// + /// + [Pure] + public static TTo As(this object subject) + { + return subject is TTo ? (TTo)subject : default(TTo); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Shared/AssertionExtensions.cs.meta b/Assets/Plugins/FluentAssertions/Shared/AssertionExtensions.cs.meta new file mode 100644 index 0000000..f9615e7 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/AssertionExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4abfd052c7ce085449ed6c501f6368d2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/Execution.meta b/Assets/Plugins/FluentAssertions/Shared/Execution.meta new file mode 100644 index 0000000..60527a5 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Execution.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1e6f8093c4534b14b9bb0ab4e25a1ecc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/Execution/AssertionFailedException.cs b/Assets/Plugins/FluentAssertions/Shared/Execution/AssertionFailedException.cs new file mode 100644 index 0000000..f8c6044 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Execution/AssertionFailedException.cs @@ -0,0 +1,31 @@ +using System; + +#if NET40 || NET45 +using System.Runtime.Serialization; +#endif + +namespace FluentAssertions.Execution +{ + /// + /// Represents the default exception in case no test framework is configured. + /// +#if NET40 || NET45 + [Serializable] +#endif + public class AssertionFailedException : Exception + { + public AssertionFailedException(string message) : base(message) + { + + } + +#if NET40 || NET45 + protected AssertionFailedException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + + } +#endif + + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Shared/Execution/AssertionFailedException.cs.meta b/Assets/Plugins/FluentAssertions/Shared/Execution/AssertionFailedException.cs.meta new file mode 100644 index 0000000..b458483 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Execution/AssertionFailedException.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7d3154cd89c416f4985ff12f4d94d795 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/Execution/FallbackTestFramework.cs b/Assets/Plugins/FluentAssertions/Shared/Execution/FallbackTestFramework.cs new file mode 100644 index 0000000..ad9f0f8 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Execution/FallbackTestFramework.cs @@ -0,0 +1,24 @@ +namespace FluentAssertions.Execution +{ + /// + /// Throws a generic exception in case no other test harness is detected. + /// + internal class FallbackTestFramework : ITestFramework + { + /// + /// Gets a value indicating whether the corresponding test framework is currently available. + /// + public bool IsAvailable + { + get { return true; } + } + + /// + /// Throws a framework-specific exception to indicate a failing unit test. + /// + public void Throw(string message) + { + throw new AssertionFailedException(message); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Shared/Execution/FallbackTestFramework.cs.meta b/Assets/Plugins/FluentAssertions/Shared/Execution/FallbackTestFramework.cs.meta new file mode 100644 index 0000000..84d6765 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Execution/FallbackTestFramework.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fcdf55e7744fbf94392c871430a20c6d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/Execution/ITestFramework.cs b/Assets/Plugins/FluentAssertions/Shared/Execution/ITestFramework.cs new file mode 100644 index 0000000..5dacf51 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Execution/ITestFramework.cs @@ -0,0 +1,18 @@ +namespace FluentAssertions.Execution +{ + /// + /// Represents an abstraction of a particular test framework such as MSTest, nUnit, etc. + /// + internal interface ITestFramework + { + /// + /// Gets a value indicating whether the corresponding test framework is currently available. + /// + bool IsAvailable { get; } + + /// + /// Throws a framework-specific exception to indicate a failing unit test. + /// + void Throw(string message); + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Shared/Execution/ITestFramework.cs.meta b/Assets/Plugins/FluentAssertions/Shared/Execution/ITestFramework.cs.meta new file mode 100644 index 0000000..60133a0 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Execution/ITestFramework.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 89d10dfcf7962884ebc19af121141945 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/Execution/LateBoundTestFramework.cs b/Assets/Plugins/FluentAssertions/Shared/Execution/LateBoundTestFramework.cs new file mode 100644 index 0000000..769f8e7 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Execution/LateBoundTestFramework.cs @@ -0,0 +1,152 @@ +using System; +using System.IO; +using System.Linq; +using System.Reflection; + +#if WINRT + +using Windows.Storage; +using System.Threading.Tasks; +using System.Collections.Generic; + +#endif + + +namespace FluentAssertions.Execution +{ + internal abstract class LateBoundTestFramework : ITestFramework + { + private Assembly assembly = null; + + public void Throw(string message) + { + Type exceptionType = assembly.GetType(ExceptionFullName); + if (exceptionType == null) + { + throw new Exception(string.Format( + "Failed to create the assertion exception for the current test framework: \"{0}, {1}\"", + ExceptionFullName, assembly.FullName)); + } + + throw (Exception)Activator.CreateInstance(exceptionType, message); + } + + public bool IsAvailable + { + get + { +#if CORE_CLR + // For CoreCLR, we need to attempt to load the assembly + try + { + assembly = Assembly.Load(new AssemblyName(AssemblyName) { Version = new Version(0,0,0,0)}); + return assembly != null; + } + catch + { + return false; + } +#else + string prefix = AssemblyName + ","; + +#if !PORTABLE + assembly = AppDomain.CurrentDomain + .GetAssemblies() + .FirstOrDefault(a => a.FullName.StartsWith(prefix, StringComparison.CurrentCultureIgnoreCase)); +#endif + return (assembly != null); +#endif + } + } + + protected abstract string AssemblyName { get; } + protected abstract string ExceptionFullName { get; } + } + +#if WINRT + /// + /// Simulates the AppDomain class that is not available in Windows Store apps. + /// + internal sealed class AppDomain + { + public static AppDomain CurrentDomain { get; private set; } + + static AppDomain() + { + CurrentDomain = new AppDomain(); + } + + public Assembly[] GetAssemblies() + { + return GetAssemblyListAsync().Result.ToArray(); + } + + private async Task> GetAssemblyListAsync() + { + StorageFolder folder = await TryToGetFolderFromAssemblyLocation(); + if (folder == null) + { + folder = TryToGetFolderFromPackageLocation(); + } + + if (folder == null) + { + throw new Exception("Could not determine the current directory to detect the test framework"); + } + + IEnumerable assemblies = + from file in await folder.GetFilesAsync().AsTask().ConfigureAwait(false) + where (file.FileType == ".dll") || (file.FileType == ".exe") + let assm = TryLoadAssembly(new AssemblyName() + { + Name = file.DisplayName + }) + where assm != null + select assm; + + return assemblies.ToArray(); + } + + private static Assembly TryLoadAssembly(AssemblyName name) + { + try + { + return Assembly.Load(name); + } + catch (Exception) + { + return null; + } + } + + private StorageFolder TryToGetFolderFromPackageLocation() + { + try + { + return Windows.ApplicationModel.Package.Current.InstalledLocation; + } + catch + { + return null; + } + } + + private static async Task TryToGetFolderFromAssemblyLocation() + { + try + { + string assemblyPath = ((dynamic)typeof(LateBoundTestFramework).GetTypeInfo().Assembly).Location; + string folderPath = Path.GetDirectoryName(assemblyPath); + + return await StorageFolder.GetFolderFromPathAsync(folderPath); + } + catch + { + return null; + } + } + } +#endif + + +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Shared/Execution/LateBoundTestFramework.cs.meta b/Assets/Plugins/FluentAssertions/Shared/Execution/LateBoundTestFramework.cs.meta new file mode 100644 index 0000000..33d5436 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Execution/LateBoundTestFramework.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 271209e710d51164db18da8016cbe71c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/Formatting.meta b/Assets/Plugins/FluentAssertions/Shared/Formatting.meta new file mode 100644 index 0000000..479036b --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Formatting.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 68478c998d6b6bd46bf89d419a2387c4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/Formatting/XAttributeValueFormatter.cs b/Assets/Plugins/FluentAssertions/Shared/Formatting/XAttributeValueFormatter.cs new file mode 100644 index 0000000..6930e6e --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Formatting/XAttributeValueFormatter.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using System.Xml.Linq; + +namespace FluentAssertions.Formatting +{ + public class XAttributeValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return (value is XAttribute); + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + var attribute = (XAttribute) value; + return attribute.ToString(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Shared/Formatting/XAttributeValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Shared/Formatting/XAttributeValueFormatter.cs.meta new file mode 100644 index 0000000..9034e37 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Formatting/XAttributeValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4c706e99af623784aa9332d7eeb4a201 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/Formatting/XDocumentValueFormatter.cs b/Assets/Plugins/FluentAssertions/Shared/Formatting/XDocumentValueFormatter.cs new file mode 100644 index 0000000..ecb338c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Formatting/XDocumentValueFormatter.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using System.Xml.Linq; + +namespace FluentAssertions.Formatting +{ + public class XDocumentValueFormatter : IValueFormatter + { + public bool CanHandle(object value) + { + return (value is XDocument); + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, + int nestedPropertyLevel = 0) + { + var document = (XDocument)value; + + return (document.Root != null) + ? FormatDocumentWithRoot(document) + : FormatDocumentWithoutRoot(); + } + + private string FormatDocumentWithRoot(XDocument document) + { + return Formatter.ToString(document.Root); + } + + private string FormatDocumentWithoutRoot() + { + return "[XML document without root element]"; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Shared/Formatting/XDocumentValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Shared/Formatting/XDocumentValueFormatter.cs.meta new file mode 100644 index 0000000..67dae49 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Formatting/XDocumentValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a0effb8e21f280b4e99a1bd074790e9b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/Formatting/XElementValueFormatter.cs b/Assets/Plugins/FluentAssertions/Shared/Formatting/XElementValueFormatter.cs new file mode 100644 index 0000000..23cba9f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Formatting/XElementValueFormatter.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Xml.Linq; + +using FluentAssertions.Common; + +using System.Linq; + +namespace FluentAssertions.Formatting +{ + public class XElementValueFormatter : IValueFormatter + { + /// + /// Indicates whether the current can handle the specified . + /// + /// The value for which to create a . + /// + /// true if the current can handle the specified value; otherwise, false. + /// + public bool CanHandle(object value) + { + return (value is XElement); + } + + /// + /// Returns a that represents this instance. + /// + /// The value for which to create a . + /// + /// + /// A collection of objects that + /// + /// + /// The level of nesting for the supplied value. This is used for indenting the format string for objects that have + /// no override. + /// + /// + /// A that represents this instance. + /// + public string ToString(object value, bool useLineBreaks, IList processedObjects = null, int nestedPropertyLevel = 0) + { + var element = (XElement) value; + + return element.HasElements + ? FormatElementWithChildren(element) + : FormatElementWithoutChildren(element); + } + + private static string FormatElementWithoutChildren(XElement element) + { + return element.ToString().Escape(escapePlaceholders: true); + } + + private static string FormatElementWithChildren(XElement element) + { + string [] lines = SplitIntoSeparateLines(element); + + // Can't use env.newline because the input doc may have unix or windows style + // line-breaks + string firstLine = lines.First().RemoveNewLines(); + string lastLine = lines.Last().RemoveNewLines(); + + string formattedElement = firstLine + "..." + lastLine; + return formattedElement.Escape(escapePlaceholders: true); + } + + private static string [] SplitIntoSeparateLines(XElement element) + { + string formattedXml = element.ToString(); + return formattedXml.Split(new [] { Environment.NewLine }, StringSplitOptions.None); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Shared/Formatting/XElementValueFormatter.cs.meta b/Assets/Plugins/FluentAssertions/Shared/Formatting/XElementValueFormatter.cs.meta new file mode 100644 index 0000000..f60d4d8 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Formatting/XElementValueFormatter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 107369ff921c9404293b33c91a9e40a9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/SolutionInfo.cs b/Assets/Plugins/FluentAssertions/Shared/SolutionInfo.cs new file mode 100644 index 0000000..fa482fd --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/SolutionInfo.cs @@ -0,0 +1,9 @@ +using System.Reflection; + +[assembly: AssemblyCompany("www.continuousimprover.com")] +[assembly: AssemblyCopyright("Copyright Dennis Doomen 2010-2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: AssemblyVersion("4.13.1.0")] +[assembly: AssemblyFileVersion("4.13.1.0")] +[assembly: AssemblyInformationalVersion("4.13.1+Branch.master.Sha.d57a300ce206c5d1443070ec62a027e35a53b271")] diff --git a/Assets/Plugins/FluentAssertions/Shared/SolutionInfo.cs.meta b/Assets/Plugins/FluentAssertions/Shared/SolutionInfo.cs.meta new file mode 100644 index 0000000..8a567b8 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/SolutionInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dd72cce85ee367944b05517b0784d520 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/Specialized.meta b/Assets/Plugins/FluentAssertions/Shared/Specialized.meta new file mode 100644 index 0000000..24a4aaa --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Specialized.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 79b1841ea56000a4d8470691ae6b40f2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/Specialized/AssemblyAssertions.cs b/Assets/Plugins/FluentAssertions/Shared/Specialized/AssemblyAssertions.cs new file mode 100644 index 0000000..f8cdf6b --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Specialized/AssemblyAssertions.cs @@ -0,0 +1,122 @@ +using System; +using System.Linq; +using System.Reflection; +using FluentAssertions.Execution; +using FluentAssertions.Primitives; + +namespace FluentAssertions.Reflection +{ + /// + /// Contains a number of methods to assert that an is in the expected state. + /// + public class AssemblyAssertions : ReferenceTypeAssertions + { + /// + /// Initializes a new instance of the class. + /// + public AssemblyAssertions(Assembly assembly) + { + Subject = assembly; + } + +#if !PORTABLE && !SILVERLIGHT && !WINRT && !CORE_CLR + + /// + /// Asserts that an assembly does not reference the specified assembly. + /// + /// The assembly which should not be referenced. + public void NotReference(Assembly assembly) + { + NotReference(assembly, String.Empty); + } + + /// + /// Asserts that an assembly does not reference the specified assembly. + /// + /// The assembly which should not be referenced. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public void NotReference(Assembly assembly, string because, params string[] becauseArgs) + { + var subjectName = Subject.GetName().Name; + var assemblyName = assembly.GetName().Name; + + var references = Subject.GetReferencedAssemblies().Select(x => x.Name); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(references.All(x => x != assemblyName)) + .FailWith("Assembly {0} should not reference assembly {1}{reason}", subjectName, assemblyName); + } + + /// + /// Asserts that an assembly references the specified assembly. + /// + /// The assembly which should be referenced. + public void Reference(Assembly assembly) + { + Reference(assembly, String.Empty); + } + + /// + /// Asserts that an assembly references the specified assembly. + /// + /// The assembly which should be referenced. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public void Reference(Assembly assembly, string because, params string[] becauseArgs) + { + var subjectName = Subject.GetName().Name; + var assemblyName = assembly.GetName().Name; + + var references = Subject.GetReferencedAssemblies().Select(x => x.Name); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(references.Any(x => x == assemblyName)) + .FailWith("Assembly {0} should reference assembly {1}{reason}, but it does not", subjectName, assemblyName); + } +#endif + /// + /// Asserts that the Assembly defines a type called and . + /// + /// The namespace of the class. + /// The name of the class. + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// Zero or more objects to format using the placeholders in . + public AndWhichConstraint DefineType(string @namespace, string name, string because = "", params object[] becauseArgs) + { +#if !NETFX_CORE && !WINRT + var foundType = Subject.GetTypes().SingleOrDefault(t => t.Namespace == @namespace && t.Name == name); +#else + var typeInfo = Subject.DefinedTypes.SingleOrDefault(t => t.Namespace == @namespace && t.Name == name); + var foundType = typeInfo == null ? null : typeInfo.AsType(); +#endif + Execute.Assertion.ForCondition(foundType != null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected assembly {0} to define type {1}.{2}, but it does not.", Subject.FullName, + @namespace, name); + + return new AndWhichConstraint(this, foundType); + } + + /// + /// Returns the type of the subject the assertion applies on. + /// + protected override string Context + { + get { return "assembly"; } + } + } +} diff --git a/Assets/Plugins/FluentAssertions/Shared/Specialized/AssemblyAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Shared/Specialized/AssemblyAssertions.cs.meta new file mode 100644 index 0000000..8069042 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Specialized/AssemblyAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7515171981e18884a975dd66d0ce59b4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/Specialized/ExecutionTimeAssertions.cs b/Assets/Plugins/FluentAssertions/Shared/Specialized/ExecutionTimeAssertions.cs new file mode 100644 index 0000000..e86d63f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Specialized/ExecutionTimeAssertions.cs @@ -0,0 +1,77 @@ +using System; +using System.Diagnostics; +using System.Linq.Expressions; +using FluentAssertions.Execution; + + +#if !PORTABLE && !SILVERLIGHT +namespace FluentAssertions.Specialized +{ + /// + /// Provides methods for asserting that the execution time of an satisfies certain conditions. + /// + public class ExecutionTimeAssertions + { + private readonly TimeSpan executionTime; + + /// + /// Initializes a new instance of the class. + /// + /// The action of which the execution time must be asserted. + public ExecutionTimeAssertions(Action action) + { + ActionDescription = "the action"; + + var stopwatch = Stopwatch.StartNew(); + action(); + stopwatch.Stop(); + + executionTime = stopwatch.Elapsed; + } + + protected string ActionDescription { get; set; } + + /// + /// Asserts that the execution time of the operation does not exceed a specified amount of time. + /// + /// + /// The maximum allowed duration. + /// + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + public void ShouldNotExceed(TimeSpan maxDuration, string because = "", params object[] becauseArgs) + { + if (executionTime > maxDuration) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Execution of " + ActionDescription + " should not exceed {0}{reason}, but it required {1}", + maxDuration, executionTime); + } + } + } + + /// + /// Provides methods for asserting that the execution time of an object member satisfies certain conditions. + /// + /// + public class MemberExecutionTimeAssertions : ExecutionTimeAssertions + { + /// + /// Initializes a new instance of the class. + /// + /// The object that exposes the method or property. + /// A reference to the method or property to measure the execution time of. + public MemberExecutionTimeAssertions(T subject, Expression> action) : + base(() => action.Compile()(subject)) + { + ActionDescription = "(" + action.Body + ")"; + } + } +} +#endif \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Shared/Specialized/ExecutionTimeAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Shared/Specialized/ExecutionTimeAssertions.cs.meta new file mode 100644 index 0000000..ef79498 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Specialized/ExecutionTimeAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 92d84dff93dfaf74d8ac6b6b04fd2084 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/Xml.meta b/Assets/Plugins/FluentAssertions/Shared/Xml.meta new file mode 100644 index 0000000..0fe54fe --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Xml.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0d49a90c25b4d2f4f8c20fd5fa8ada9a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/Xml/XAttributeAssertions.cs b/Assets/Plugins/FluentAssertions/Shared/Xml/XAttributeAssertions.cs new file mode 100644 index 0000000..e06f1a0 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Xml/XAttributeAssertions.cs @@ -0,0 +1,124 @@ +using System.Diagnostics; +using System.Xml.Linq; +using FluentAssertions.Execution; +using FluentAssertions.Primitives; + +namespace FluentAssertions.Xml +{ + /// + /// Contains a number of methods to assert that an is in the expected state. + /// + [DebuggerNonUserCode] + public class XAttributeAssertions : ReferenceTypeAssertions + { + /// + /// Initializes a new instance of the class. + /// + public XAttributeAssertions(XAttribute attribute) + { + Subject = attribute; + } + + /// + /// Asserts that the current equals the attribute. + /// + /// The expected attribute + public AndConstraint Be(XAttribute expected) + { + return Be(expected, string.Empty); + } + + /// + /// Asserts that the current equals the attribute. + /// + /// The expected attribute + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Be(XAttribute expected, string because, params object [] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.Name.Equals(expected.Name) && Subject.Value.Equals(expected.Value)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected XML attribute to be {0}{reason}, but found {1}", expected, Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current does not equal the attribute, + /// using its implementation. + /// + /// The unexpected attribute + public AndConstraint NotBe(XAttribute unexpected) + { + return NotBe(unexpected, string.Empty); + } + + /// + /// Asserts that the current does not equal the attribute, + /// using its implementation. + /// + /// The unexpected attribute + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBe(XAttribute unexpected, string because, params object [] becauseArgs) + { + Execute.Assertion + .ForCondition(!Subject.Name.Equals(unexpected.Name) || !Subject.Value.Equals(unexpected.Value)) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect XML attribute to be {0}{reason}.", unexpected); + + return new AndConstraint(this); + } + + + /// + /// Asserts that the current has the specified value. + /// + /// The expected value + public AndConstraint HaveValue(string expected) + { + return HaveValue(expected, string.Empty); + } + + /// + /// Asserts that the current has the specified value. + /// + /// The expected value + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveValue(string expected, string because, params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.Value == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected XML attribute '{0}' to have value {1}{reason}, but found {2}.", + Subject.Name, expected, Subject.Value); + + return new AndConstraint(this); + } + + /// + /// Returns the type of the subject the assertion applies on. + /// + protected override string Context + { + get { return "XML attribute"; } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Shared/Xml/XAttributeAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Shared/Xml/XAttributeAssertions.cs.meta new file mode 100644 index 0000000..d9360b6 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Xml/XAttributeAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1b1aa6236526d454d853470c0941f199 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/Xml/XDocumentAssertions.cs b/Assets/Plugins/FluentAssertions/Shared/Xml/XDocumentAssertions.cs new file mode 100644 index 0000000..3e686cd --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Xml/XDocumentAssertions.cs @@ -0,0 +1,338 @@ +using System; +using System.Diagnostics; +using System.Xml.Linq; + +using FluentAssertions.Common; +using FluentAssertions.Execution; +using FluentAssertions.Primitives; + +namespace FluentAssertions.Xml +{ + /// + /// Contains a number of methods to assert that an is in the expected state. + /// + [DebuggerNonUserCode] + public class XDocumentAssertions : ReferenceTypeAssertions + { + /// + /// Initializes a new instance of the class. + /// + public XDocumentAssertions(XDocument document) + { + Subject = document; + } + + /// + /// Asserts that the current equals the document, + /// using its implementation. + /// + /// The expected document + public AndConstraint Be(XDocument expected) + { + return Be(expected, string.Empty); + } + + /// + /// Asserts that the current equals the document, + /// using its implementation. + /// + /// The expected document + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Be(XDocument expected, string because, params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.IsSameOrEqualTo(expected)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected XML document to be {0}{reason}, but found {1}", expected, Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current does not equal the document, + /// using its implementation. + /// + /// The unexpected document + public AndConstraint NotBe(XDocument unexpected) + { + return NotBe(unexpected, string.Empty); + } + + /// + /// Asserts that the current does not equal the document, + /// using its implementation. + /// + /// The unexpected document + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBe(XDocument unexpected, string because, params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(!ReferenceEquals(Subject, null)) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect XML document to be {0}, but found .", unexpected); + + Execute.Assertion + .ForCondition(!Subject.Equals(unexpected)) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect XML document to be {0}{reason}.", unexpected); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is equivalent to the document, + /// using its implementation. + /// + /// The expected document + public AndConstraint BeEquivalentTo(XDocument expected) + { + return BeEquivalentTo(expected, string.Empty); + } + + /// + /// Asserts that the current is equivalent to the document, + /// using its implementation. + /// + /// The expected document + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeEquivalentTo(XDocument expected, string because, params object[] becauseArgs) + { + new XmlReaderValidator(Subject.CreateReader(), expected.CreateReader(), because, becauseArgs).Validate(true); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is not equivalent to the document, + /// using its implementation. + /// + /// The unexpected document + public AndConstraint NotBeEquivalentTo(XDocument unexpected) + { + return NotBeEquivalentTo(unexpected, string.Empty); + } + + /// + /// Asserts that the current is not equivalent to the document, + /// using its implementation. + /// + /// The unexpected document + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeEquivalentTo(XDocument unexpected, string because, params object[] becauseArgs) + { + new XmlReaderValidator(Subject.CreateReader(), unexpected.CreateReader(), because, becauseArgs).Validate(false); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current has a root element with the specified + /// name. + /// + /// The name of the expected root element of the current document. + public AndWhichConstraint HaveRoot(string expected) + { + return HaveRoot(expected, string.Empty); + } + + /// + /// Asserts that the current has a root element with the specified + /// name. + /// + /// The name of the expected root element of the current document. + public AndWhichConstraint HaveRoot(XName expected) + { + return HaveRoot(expected, string.Empty); + } + + /// + /// Asserts that the current has a root element with the specified + /// name. + /// + /// The name of the expected root element of the current document. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndWhichConstraint HaveRoot(string expected, string because, + params object[] becauseArgs) + { + if (expected == null) + { + throw new ArgumentNullException("expected", + "Cannot assert the document has a root element if the element name is *"); + } + + return HaveRoot(XNamespace.None + expected, because, becauseArgs); + } + + /// + /// Asserts that the current has a root element with the specified + /// name. + /// + /// The full name of the expected root element of the current document. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndWhichConstraint HaveRoot(XName expected, string because, params object[] becauseArgs) + { + if (Subject == null) + { + throw new ArgumentNullException("subject", + "Cannot assert the document has a root element if the document itself is ."); + } + + if (expected == null) + { + throw new ArgumentNullException("expected", + "Cannot assert the document has a root element if the element name is *"); + } + + XElement root = Subject.Root; + + Execute.Assertion + .ForCondition((root != null) && (root.Name == expected)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected XML document to have root element \"" + expected.ToString().Escape(escapePlaceholders: true) + "\"{reason}" + + ", but found {0}.", Subject); + + return new AndWhichConstraint(this, root); + } + + /// + /// Asserts that the element of the current has a direct + /// child element with the specified name. + /// + /// + /// The name of the expected child element of the current document's Root element. + /// + public AndWhichConstraint HaveElement(string expected) + { + return HaveElement(expected, string.Empty); + } + + /// + /// Asserts that the element of the current has a direct + /// child element with the specified name. + /// + /// + /// The full name of the expected child element of the current document's Root element. + /// + public AndWhichConstraint HaveElement(XName expected) + { + return HaveElement(expected, string.Empty); + } + + /// + /// Asserts that the element of the current has a direct + /// child element with the specified name. + /// + /// + /// The name of the expected child element of the current document's Root element. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndWhichConstraint HaveElement(string expected, string because, + params object[] becauseArgs) + { + if (expected == null) + { + throw new ArgumentNullException("expected", + "Cannot assert the document has an element if the element name is *"); + } + + return HaveElement(XNamespace.None + expected, because, becauseArgs); + } + + /// + /// Asserts that the element of the current has a direct + /// child element with the specified name. + /// + /// + /// The full name of the expected child element of the current document's Root element. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndWhichConstraint HaveElement(XName expected, string because, + params object[] becauseArgs) + { + if (Subject == null) + { + throw new ArgumentNullException("subject", + "Cannot assert the document has an element if the document itself is ."); + } + + if (expected == null) + { + throw new ArgumentNullException("expected", + "Cannot assert the document has an element if the element name is *"); + } + + string expectedText = expected.ToString().Escape(escapePlaceholders: true); + + Execute.Assertion + .ForCondition(Subject.Root != null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected XML document {0} to have root element with child \"" + expectedText + "\"{reason}" + + ", but XML document has no Root element.", Subject); + + XElement xElement = Subject.Root.Element(expected); + Execute.Assertion + .ForCondition(xElement != null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected XML document {0} to have root element with child \"" + expectedText + "\"{reason}" + + ", but no such child element was found.", Subject); + + return new AndWhichConstraint(this, xElement); + } + + /// + /// Returns the type of the subject the assertion applies on. + /// + protected override string Context + { + get { return "XML document"; } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Shared/Xml/XDocumentAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Shared/Xml/XDocumentAssertions.cs.meta new file mode 100644 index 0000000..b69bbff --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Xml/XDocumentAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a31b7498e8b01f04ea62c5b926541731 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/Xml/XElementAssertions.cs b/Assets/Plugins/FluentAssertions/Shared/Xml/XElementAssertions.cs new file mode 100644 index 0000000..3805087 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Xml/XElementAssertions.cs @@ -0,0 +1,334 @@ +using System.Diagnostics; +using System.Xml.Linq; +using FluentAssertions.Common; +using FluentAssertions.Execution; +using FluentAssertions.Primitives; +using System.Xml; + +namespace FluentAssertions.Xml +{ + /// + /// Contains a number of methods to assert that an is in the expected state. + /// + [DebuggerNonUserCode] + public class XElementAssertions : ReferenceTypeAssertions + { + /// + /// Initializes a new instance of the class. + /// + public XElementAssertions(XElement xElement) + { + Subject = xElement; + } + + /// + /// Asserts that the current equals the + /// element, by using + /// + /// + /// The expected element + public AndConstraint Be(XElement expected) + { + return Be(expected, string.Empty); + } + + /// + /// Asserts that the current equals the + /// element, by using + /// + /// + /// The expected element + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint Be(XElement expected, string because, params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(XNode.DeepEquals(Subject, expected)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected XML element to be {0}{reason}, but found {1}.", expected, Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current does not equal the + /// element, using + /// . + /// + /// The unexpected element + public AndConstraint NotBe(XElement unexpected) + { + return NotBe(unexpected, string.Empty); + } + + /// + /// Asserts that the current does not equal the + /// element, using + /// . + /// + /// The unexpected element + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBe(XElement unexpected, string because, params object[] becauseArgs) + { + Execute.Assertion + .ForCondition((ReferenceEquals(Subject, null) && !ReferenceEquals(unexpected, null)) || !XNode.DeepEquals(Subject, unexpected)) + .BecauseOf(because, becauseArgs) + .FailWith("Expected XML element not to be {0}{reason}.", unexpected); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is equivalent to the + /// element, using a semantic equivalency + /// comparison. + /// + /// The expected element + public AndConstraint BeEquivalentTo(XElement expected) + { + return BeEquivalentTo(expected, string.Empty); + } + + /// + /// Asserts that the current is equivalent to the + /// element, using a semantic equivalency + /// comparison. + /// + /// The expected element + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint BeEquivalentTo(XElement expected, string because, params object[] becauseArgs) + { + using (XmlReader subjectReader = Subject.CreateReader()) + using (XmlReader expectedReader = expected.CreateReader()) + { + new XmlReaderValidator(subjectReader, expectedReader, because, becauseArgs).Validate(true); + } + + return new AndConstraint(this); + } + + /// + /// Asserts that the current is not equivalent to + /// the element, using a semantic + /// equivalency comparison. + /// + /// The unexpected element + public AndConstraint NotBeEquivalentTo(XElement unexpected) + { + return NotBeEquivalentTo(unexpected, string.Empty); + } + + /// + /// Asserts that the current is not equivalent to + /// the element, using a semantic + /// equivalency comparison. + /// + /// The unexpected element + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint NotBeEquivalentTo(XElement unexpected, string because, params object[] becauseArgs) + { + new XmlReaderValidator(Subject.CreateReader(), unexpected.CreateReader(), because, becauseArgs).Validate(false); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current has the specified value. + /// + /// The expected value + public AndConstraint HaveValue(string expected) + { + return HaveValue(expected, string.Empty); + } + + /// + /// Asserts that the current has the specified value. + /// + /// The expected value + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveValue(string expected, string because, params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject.Value == expected) + .BecauseOf(because, becauseArgs) + .FailWith("Expected XML element '{0}' to have value {1}{reason}, but found {2}.", + Subject.Name, expected, Subject.Value); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current has an attribute with the specified + /// and . + /// + /// The name of the expected attribute + /// The value of the expected attribute + public AndConstraint HaveAttribute(string expectedName, string expectedValue) + { + return HaveAttribute(expectedName, expectedValue, string.Empty); + } + + /// + /// Asserts that the current has an attribute with the specified + /// and . + /// + /// The name of the expected attribute + /// The value of the expected attribute + public AndConstraint HaveAttribute(XName expectedName, string expectedValue) + { + return HaveAttribute(expectedName, expectedValue, string.Empty); + } + + /// + /// Asserts that the current has an attribute with the specified + /// and . + /// + /// The name of the expected attribute + /// The value of the expected attribute + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveAttribute(string expectedName, string expectedValue, string because, + params object[] becauseArgs) + { + return HaveAttribute(XNamespace.None + expectedName, expectedValue, because, becauseArgs); + } + + /// + /// Asserts that the current has an attribute with the specified + /// and . + /// + /// The name of the expected attribute + /// The value of the expected attribute + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndConstraint HaveAttribute(XName expectedName, string expectedValue, string because, + params object[] becauseArgs) + { + XAttribute attribute = Subject.Attribute(expectedName); + string expectedText = expectedName.ToString().Escape(escapePlaceholders: true); + + Execute.Assertion + .ForCondition(attribute != null) + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected XML element to have attribute \"" + expectedText + "\" with value {0}{reason}, but found no such attribute in {1}", + expectedValue, Subject); + + Execute.Assertion + .ForCondition(attribute.Value == expectedValue) + .BecauseOf(because, becauseArgs) + .FailWith( + "Expected XML attribute \"" + expectedText + "\" to have value {0}{reason}, but found {1}.", expectedValue, attribute.Value); + + return new AndConstraint(this); + } + + /// + /// Asserts that the current has a direct child element with the specified + /// name. + /// + /// The name of the expected child element + public AndWhichConstraint HaveElement(string expected) + { + return HaveElement(expected, string.Empty); + } + + /// + /// Asserts that the current has a direct child element with the specified + /// name. + /// + /// The name of the expected child element + public AndWhichConstraint HaveElement(XName expected) + { + return HaveElement(expected, string.Empty); + } + + /// + /// Asserts that the current has a direct child element with the specified + /// name. + /// + /// The name of the expected child element + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndWhichConstraint HaveElement(string expected, string because, params object[] becauseArgs) + { + return HaveElement(XNamespace.None + expected, because, becauseArgs); + } + + /// + /// Asserts that the current has a direct child element with the specified + /// name. + /// + /// The name of the expected child element + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndWhichConstraint HaveElement(XName expected, string because, params object[] becauseArgs) + { + XElement xElement = Subject.Element(expected); + Execute.Assertion + .ForCondition(xElement != null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected XML element {0} to have child element \"" + expected.ToString().Escape(escapePlaceholders: true) + "\"{reason}" + + ", but no such child element was found.", Subject); + + return new AndWhichConstraint(this, xElement); + } + + /// + /// Returns the type of the subject the assertion applies on. + /// + protected override string Context + { + get { return "XML element"; } + } + } +} diff --git a/Assets/Plugins/FluentAssertions/Shared/Xml/XElementAssertions.cs.meta b/Assets/Plugins/FluentAssertions/Shared/Xml/XElementAssertions.cs.meta new file mode 100644 index 0000000..3905ff1 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Xml/XElementAssertions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a542b1f759a7c4442bb87838b191b870 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/Shared/Xml/XmlReaderValidator.cs b/Assets/Plugins/FluentAssertions/Shared/Xml/XmlReaderValidator.cs new file mode 100644 index 0000000..832541c --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Xml/XmlReaderValidator.cs @@ -0,0 +1,243 @@ +using FluentAssertions.Execution; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + +namespace FluentAssertions.Xml +{ + internal class XmlReaderValidator + { + AssertionScope assertion; + XmlReader subjectReader, otherReader; + + string CurrentLocation + { + get { return "/" + string.Join("/", locationStack.Reverse()); } + } + + Stack locationStack = new Stack(); + + public XmlReaderValidator(XmlReader subjectReader, XmlReader otherReader, string because, object[] reasonArgs) + { + assertion = Execute.Assertion.BecauseOf(because, reasonArgs); + + this.subjectReader = subjectReader; + this.otherReader = otherReader; + } + + class ValidationResult + { + public ValidationResult(string formatString, params object[] formatParams) + { + FormatString = formatString; + FormatParams = formatParams; + } + + public string FormatString { get; } + + public object[] FormatParams { get; } + } + + public void Validate(bool expectedEquivalence) + { + ValidationResult validationResult = Validate(); + + if(expectedEquivalence && validationResult != null) + { + assertion.FailWith(validationResult.FormatString, validationResult.FormatParams); + } + if(!expectedEquivalence && validationResult == null) + { + assertion.FailWith("Did not expect Xml to be equivalent{reason}, but it is."); + } + } + + private ValidationResult Validate() + { + subjectReader.MoveToContent(); + otherReader.MoveToContent(); + while (!subjectReader.EOF && !otherReader.EOF) + { + if (subjectReader.NodeType != otherReader.NodeType) + { + return new ValidationResult("Expected node of type {0} at {1}{reason}, but found {2}.", + otherReader.NodeType, CurrentLocation, subjectReader.NodeType); + } + + ValidationResult validationResult = null; + + switch (subjectReader.NodeType) + { + case XmlNodeType.Element: + validationResult = ValidateStartElement(); + if(validationResult != null) + { + return validationResult; + } + locationStack.Push(subjectReader.LocalName); + validationResult = ValidateAttributes(); + if(subjectReader.IsEmptyElement) + { + locationStack.Pop(); + } + break; + case XmlNodeType.EndElement: + // No need to verify end element, if it doesn't match + // the start element it isn't valid XML, so the parser + // would handle that. + locationStack.Pop(); + break; + case XmlNodeType.Text: + validationResult = ValidateText(); + break; + default: + throw new NotSupportedException($"{subjectReader.NodeType} found at {CurrentLocation} is not supported for equivalency comparison."); + } + + if(validationResult != null) + { + return validationResult; + } + + subjectReader.Read(); + otherReader.Read(); + + subjectReader.MoveToContent(); + otherReader.MoveToContent(); + } + + if (!otherReader.EOF) + { + return new ValidationResult("Expected {0}{reason}, but found end of document.", + otherReader.LocalName); + } + + if (!subjectReader.EOF) + { + return new ValidationResult("Expected end of document{reason}, but found {0}.", + subjectReader.LocalName); + } + + return null; + } + + + class AttributeData + { + public AttributeData(string namespaceUri, string localName, string value, string prefix) + { + NamespaceUri = namespaceUri; + LocalName = localName; + Value = value; + Prefix = prefix; + } + + public string NamespaceUri { get; } + public string LocalName { get; } + public string Value { get; } + public string Prefix { get; } + + public string QualifiedName + { + get + { + if(string.IsNullOrEmpty(Prefix)) + { + return LocalName; + } + + return Prefix + ":" + LocalName; + } + } + } + + private ValidationResult ValidateAttributes() + { + IList expectedAttributes = GetAttributes(otherReader); + IList subjectAttributes = GetAttributes(subjectReader); + + foreach (AttributeData subjectAttribute in subjectAttributes) + { + AttributeData expectedAttribute = expectedAttributes.SingleOrDefault( + ea => ea.NamespaceUri == subjectAttribute.NamespaceUri + && ea.LocalName == subjectAttribute.LocalName); + + if (expectedAttribute == null) + { + return new ValidationResult("Didn't expect to find attribute {0} at {1}{reason}.", + subjectAttribute.QualifiedName, CurrentLocation); + } + + if (subjectAttribute.Value != expectedAttribute.Value) + { + return new ValidationResult("Expected attribute {0} at {1} to have value {2}{reason}, but found {3}.", + subjectAttribute.LocalName, CurrentLocation, expectedAttribute.Value, subjectAttribute.Value); + } + } + + if (subjectAttributes.Count != expectedAttributes.Count) + { + AttributeData missingAttribute = expectedAttributes.First(ea => + !subjectAttributes.Any(sa => + ea.NamespaceUri == sa.NamespaceUri + && sa.LocalName == ea.LocalName)); + + return new ValidationResult("Expected attribute {0} at {1}{reason}, but found none.", + missingAttribute.LocalName, CurrentLocation); + } + return null; + } + + private IList GetAttributes(XmlReader reader) + { + IList attributes = new List(); + + if (reader.MoveToFirstAttribute()) + { + do + { + if (reader.NamespaceURI != "http://www.w3.org/2000/xmlns/") + { + attributes.Add(new AttributeData(reader.NamespaceURI, reader.LocalName, reader.Value, reader.Prefix)); + } + } while (reader.MoveToNextAttribute()); + } + + return attributes; + } + + private ValidationResult ValidateStartElement() + { + if (subjectReader.LocalName != otherReader.LocalName) + { + return new ValidationResult("Expected local name of element at {0} to be {1}{reason}, but found {2}.", + CurrentLocation, otherReader.LocalName, subjectReader.LocalName); + } + + if (subjectReader.NamespaceURI != otherReader.NamespaceURI) + { + return new ValidationResult("Expected namespace of element {0} at {1} to be {2}{reason}, but found {3}.", + subjectReader.LocalName, CurrentLocation, otherReader.NamespaceURI, subjectReader.NamespaceURI); + } + + return null; + } + + private ValidationResult ValidateText() + { + string subject = subjectReader.Value; + string expected = otherReader.Value; + + if (subject != expected) + { + return new ValidationResult("Expected content to be {0} at {1}{reason}, but found {2}.", + expected, CurrentLocation, subject); + } + + return null; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/FluentAssertions/Shared/Xml/XmlReaderValidator.cs.meta b/Assets/Plugins/FluentAssertions/Shared/Xml/XmlReaderValidator.cs.meta new file mode 100644 index 0000000..085a79f --- /dev/null +++ b/Assets/Plugins/FluentAssertions/Shared/Xml/XmlReaderValidator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d6ec02bba76ed034faf297bc5860c112 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/FluentAssertions/VERSION.md b/Assets/Plugins/FluentAssertions/VERSION.md new file mode 100644 index 0000000..4b757b4 --- /dev/null +++ b/Assets/Plugins/FluentAssertions/VERSION.md @@ -0,0 +1 @@ +This is fluent-assertions 4.19.4 diff --git a/Assets/Plugins/FluentAssertions/VERSION.md.meta b/Assets/Plugins/FluentAssertions/VERSION.md.meta new file mode 100644 index 0000000..eff96fa --- /dev/null +++ b/Assets/Plugins/FluentAssertions/VERSION.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 81d3ea551d687a14aa2dfbb9157d82a7 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes.meta b/Assets/Plugins/NaughtyAttributes.meta new file mode 100644 index 0000000..fae4246 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0b7f06eca19d1b745a832197fe686d6d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation.meta b/Assets/Plugins/NaughtyAttributes/Documentation.meta new file mode 100644 index 0000000..df80bdc --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 8dde3911cdcacad4cbe3192d388a5218 +folderAsset: yes +timeCreated: 1508669465 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/BlankSpace_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/BlankSpace_Code.PNG new file mode 100644 index 0000000..dc6b1b2 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/BlankSpace_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/BlankSpace_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/BlankSpace_Code.PNG.meta new file mode 100644 index 0000000..9e74b46 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/BlankSpace_Code.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 022c178ec9e442345958ad25512a17f4 +timeCreated: 1508669477 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/BlankSpace_Inspector.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/BlankSpace_Inspector.PNG new file mode 100644 index 0000000..bf7450f Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/BlankSpace_Inspector.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/BlankSpace_Inspector.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/BlankSpace_Inspector.PNG.meta new file mode 100644 index 0000000..972a91f --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/BlankSpace_Inspector.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 17ab0384d85cb744595133fcff8efb9d +timeCreated: 1508669477 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/BoxGroup_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/BoxGroup_Code.PNG new file mode 100644 index 0000000..33f3d86 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/BoxGroup_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/BoxGroup_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/BoxGroup_Code.PNG.meta new file mode 100644 index 0000000..7f1d43a --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/BoxGroup_Code.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: b962d99ba1e86044ea453878b9fd1ad6 +timeCreated: 1508669478 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/BoxGroup_Inspector.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/BoxGroup_Inspector.PNG new file mode 100644 index 0000000..624d4f7 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/BoxGroup_Inspector.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/BoxGroup_Inspector.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/BoxGroup_Inspector.PNG.meta new file mode 100644 index 0000000..bee4dee --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/BoxGroup_Inspector.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 9b966e4d3fd75654cbfe73a12abb0b40 +timeCreated: 1508669478 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Button_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/Button_Code.PNG new file mode 100644 index 0000000..8b4d1b0 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/Button_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Button_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/Button_Code.PNG.meta new file mode 100644 index 0000000..80a655c --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/Button_Code.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 76b0b7c29f8441540a1cf986b45f6a7c +timeCreated: 1508669478 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Button_Inspector.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/Button_Inspector.PNG new file mode 100644 index 0000000..08ee979 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/Button_Inspector.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Button_Inspector.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/Button_Inspector.PNG.meta new file mode 100644 index 0000000..c7f2391 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/Button_Inspector.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 794a606ccada1c449a6f12143f5d8ef6 +timeCreated: 1508669478 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Dropdown_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/Dropdown_Code.PNG new file mode 100644 index 0000000..fdbad05 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/Dropdown_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Dropdown_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/Dropdown_Code.PNG.meta new file mode 100644 index 0000000..39c74fc --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/Dropdown_Code.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: a8c6bf35d7527a44e93ce41d925b07f0 +timeCreated: 1508767592 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Dropdown_Inspector.gif b/Assets/Plugins/NaughtyAttributes/Documentation/Dropdown_Inspector.gif new file mode 100644 index 0000000..ffa5252 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/Dropdown_Inspector.gif differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Dropdown_Inspector.gif.meta b/Assets/Plugins/NaughtyAttributes/Documentation/Dropdown_Inspector.gif.meta new file mode 100644 index 0000000..9986230 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/Dropdown_Inspector.gif.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: c1db80a2110426d4f90e8c42467ca2c6 +timeCreated: 1508767592 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/EnableIf_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/EnableIf_Code.PNG new file mode 100644 index 0000000..b253129 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/EnableIf_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/EnableIf_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/EnableIf_Code.PNG.meta new file mode 100644 index 0000000..37e31d6 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/EnableIf_Code.PNG.meta @@ -0,0 +1,84 @@ +fileFormatVersion: 2 +guid: 020173797840d4f49905844cc0a64fcd +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 5 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + 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: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/EnableIf_Inspector.gif b/Assets/Plugins/NaughtyAttributes/Documentation/EnableIf_Inspector.gif new file mode 100644 index 0000000..3855dec Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/EnableIf_Inspector.gif differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/EnableIf_Inspector.gif.meta b/Assets/Plugins/NaughtyAttributes/Documentation/EnableIf_Inspector.gif.meta new file mode 100644 index 0000000..1ad5e46 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/EnableIf_Inspector.gif.meta @@ -0,0 +1,84 @@ +fileFormatVersion: 2 +guid: 55dace8f2296cf94ab88a1838ed4d7fe +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 5 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + 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: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/InfoBox_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/InfoBox_Code.PNG new file mode 100644 index 0000000..83103bd Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/InfoBox_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/InfoBox_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/InfoBox_Code.PNG.meta new file mode 100644 index 0000000..0a73839 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/InfoBox_Code.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 93610132c9d0ac5469afc61d66817c99 +timeCreated: 1508669478 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/InfoBox_Inspector.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/InfoBox_Inspector.PNG new file mode 100644 index 0000000..369b6b0 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/InfoBox_Inspector.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/InfoBox_Inspector.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/InfoBox_Inspector.PNG.meta new file mode 100644 index 0000000..44fd1b8 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/InfoBox_Inspector.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: edcea8333d68ae945ad1c760ae2d1562 +timeCreated: 1508669478 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/MinMaxSlider_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/MinMaxSlider_Code.PNG new file mode 100644 index 0000000..f514c2e Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/MinMaxSlider_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/MinMaxSlider_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/MinMaxSlider_Code.PNG.meta new file mode 100644 index 0000000..f270607 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/MinMaxSlider_Code.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 20085933a153a464f8a4db07e9001f42 +timeCreated: 1508669477 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/MinMaxSlider_Inspector.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/MinMaxSlider_Inspector.PNG new file mode 100644 index 0000000..6086b40 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/MinMaxSlider_Inspector.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/MinMaxSlider_Inspector.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/MinMaxSlider_Inspector.PNG.meta new file mode 100644 index 0000000..100a052 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/MinMaxSlider_Inspector.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: ca85e66652051634e815f4f8368f98d9 +timeCreated: 1508669478 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/MinValueMaxValue_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/MinValueMaxValue_Code.PNG new file mode 100644 index 0000000..0f3fd47 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/MinValueMaxValue_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/MinValueMaxValue_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/MinValueMaxValue_Code.PNG.meta new file mode 100644 index 0000000..65031fa --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/MinValueMaxValue_Code.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 50afb956ae7768b4b89d7b5ef321367f +timeCreated: 1508669477 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/MinValueMaxValue_Inspector.gif b/Assets/Plugins/NaughtyAttributes/Documentation/MinValueMaxValue_Inspector.gif new file mode 100644 index 0000000..185c9cc Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/MinValueMaxValue_Inspector.gif differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/MinValueMaxValue_Inspector.gif.meta b/Assets/Plugins/NaughtyAttributes/Documentation/MinValueMaxValue_Inspector.gif.meta new file mode 100644 index 0000000..46bb517 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/MinValueMaxValue_Inspector.gif.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 549658017be426742a56b94a5958b6f6 +timeCreated: 1508669477 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/OnValueChanged_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/OnValueChanged_Code.PNG new file mode 100644 index 0000000..969f29f Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/OnValueChanged_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/OnValueChanged_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/OnValueChanged_Code.PNG.meta new file mode 100644 index 0000000..f75ae0f --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/OnValueChanged_Code.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 1d9a471100e0c9748a60242500085501 +timeCreated: 1508669477 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ProgressBar_Code.png b/Assets/Plugins/NaughtyAttributes/Documentation/ProgressBar_Code.png new file mode 100644 index 0000000..bbc547b Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/ProgressBar_Code.png differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ProgressBar_Code.png.meta b/Assets/Plugins/NaughtyAttributes/Documentation/ProgressBar_Code.png.meta new file mode 100644 index 0000000..3281499 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/ProgressBar_Code.png.meta @@ -0,0 +1,77 @@ +fileFormatVersion: 2 +guid: 5817ff65803edc24ca258286e6d2fd33 +timeCreated: 1518636277 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ProgressBar_Inspector.gif b/Assets/Plugins/NaughtyAttributes/Documentation/ProgressBar_Inspector.gif new file mode 100644 index 0000000..7aada24 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/ProgressBar_Inspector.gif differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ProgressBar_Inspector.gif.meta b/Assets/Plugins/NaughtyAttributes/Documentation/ProgressBar_Inspector.gif.meta new file mode 100644 index 0000000..b106c8b --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/ProgressBar_Inspector.gif.meta @@ -0,0 +1,77 @@ +fileFormatVersion: 2 +guid: 631c492cc54906542851734be1231fab +timeCreated: 1518636277 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ReadOnly_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/ReadOnly_Code.PNG new file mode 100644 index 0000000..603149b Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/ReadOnly_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ReadOnly_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/ReadOnly_Code.PNG.meta new file mode 100644 index 0000000..7772c2c --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/ReadOnly_Code.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 869278751dbd45549a12050d9fea7425 +timeCreated: 1508862811 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ReadOnly_Inspector.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/ReadOnly_Inspector.PNG new file mode 100644 index 0000000..aaad6ae Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/ReadOnly_Inspector.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ReadOnly_Inspector.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/ReadOnly_Inspector.PNG.meta new file mode 100644 index 0000000..27e94d7 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/ReadOnly_Inspector.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 867cf9de018b6fd46a306be250cd7196 +timeCreated: 1508862811 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ReorderableList_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/ReorderableList_Code.PNG new file mode 100644 index 0000000..23de97e Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/ReorderableList_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ReorderableList_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/ReorderableList_Code.PNG.meta new file mode 100644 index 0000000..4a0ae92 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/ReorderableList_Code.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: d62a3181965d92a42981ed3d66adf987 +timeCreated: 1508669478 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ReorderableList_Inspector.gif b/Assets/Plugins/NaughtyAttributes/Documentation/ReorderableList_Inspector.gif new file mode 100644 index 0000000..bdf80f3 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/ReorderableList_Inspector.gif differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ReorderableList_Inspector.gif.meta b/Assets/Plugins/NaughtyAttributes/Documentation/ReorderableList_Inspector.gif.meta new file mode 100644 index 0000000..37579df --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/ReorderableList_Inspector.gif.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: a82acdae22e140148b602d98ff67b7b6 +timeCreated: 1508669478 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Required_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/Required_Code.PNG new file mode 100644 index 0000000..ac086f4 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/Required_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Required_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/Required_Code.PNG.meta new file mode 100644 index 0000000..ab0153c --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/Required_Code.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: eec3cb64c7158614781457f102d28654 +timeCreated: 1508669478 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Required_Inspector.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/Required_Inspector.PNG new file mode 100644 index 0000000..97e28b8 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/Required_Inspector.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Required_Inspector.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/Required_Inspector.PNG.meta new file mode 100644 index 0000000..2f3243e --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/Required_Inspector.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: c496c0d39ae55ec4db47a54c72510db1 +timeCreated: 1508669478 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ResizableTextArea_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/ResizableTextArea_Code.PNG new file mode 100644 index 0000000..115558e Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/ResizableTextArea_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ResizableTextArea_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/ResizableTextArea_Code.PNG.meta new file mode 100644 index 0000000..14c38fe --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/ResizableTextArea_Code.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 7a7b2846b5f13794db2650ade442c8bb +timeCreated: 1508833884 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ResizableTextArea_Inspector.gif b/Assets/Plugins/NaughtyAttributes/Documentation/ResizableTextArea_Inspector.gif new file mode 100644 index 0000000..414efa7 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/ResizableTextArea_Inspector.gif differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ResizableTextArea_Inspector.gif.meta b/Assets/Plugins/NaughtyAttributes/Documentation/ResizableTextArea_Inspector.gif.meta new file mode 100644 index 0000000..2913c61 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/ResizableTextArea_Inspector.gif.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 4d411d3022fdb9a4894b786023ff55c3 +timeCreated: 1508833884 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Section_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/Section_Code.PNG new file mode 100644 index 0000000..93d1a9e Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/Section_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Section_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/Section_Code.PNG.meta new file mode 100644 index 0000000..6af2cda --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/Section_Code.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: baeaf9f9d9ca90b4d8418fd8179195dd +timeCreated: 1508669478 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Section_Inspector.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/Section_Inspector.PNG new file mode 100644 index 0000000..4fab082 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/Section_Inspector.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Section_Inspector.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/Section_Inspector.PNG.meta new file mode 100644 index 0000000..93dea50 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/Section_Inspector.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 0cdac3f93cb6b764284bcfad3302eb59 +timeCreated: 1508669477 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ShowAssetPreview_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/ShowAssetPreview_Code.PNG new file mode 100644 index 0000000..85ff839 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/ShowAssetPreview_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ShowAssetPreview_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/ShowAssetPreview_Code.PNG.meta new file mode 100644 index 0000000..fe4e240 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/ShowAssetPreview_Code.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: bb1c59dc18499aa4d87ea7c35f80101b +timeCreated: 1509093800 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ShowAssetPreview_Inspector.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/ShowAssetPreview_Inspector.PNG new file mode 100644 index 0000000..ebf989a Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/ShowAssetPreview_Inspector.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ShowAssetPreview_Inspector.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/ShowAssetPreview_Inspector.PNG.meta new file mode 100644 index 0000000..00b5dda --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/ShowAssetPreview_Inspector.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 9fef8c6f9ed6f5b48b3f90e657bd71d5 +timeCreated: 1509093800 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ShowIf_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/ShowIf_Code.PNG new file mode 100644 index 0000000..b7d7135 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/ShowIf_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ShowIf_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/ShowIf_Code.PNG.meta new file mode 100644 index 0000000..a88ee55 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/ShowIf_Code.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 8e647f629215ab5479f1f2e9e4e10f89 +timeCreated: 1508669478 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ShowIf_Inspector.gif b/Assets/Plugins/NaughtyAttributes/Documentation/ShowIf_Inspector.gif new file mode 100644 index 0000000..0f032ca Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/ShowIf_Inspector.gif differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ShowIf_Inspector.gif.meta b/Assets/Plugins/NaughtyAttributes/Documentation/ShowIf_Inspector.gif.meta new file mode 100644 index 0000000..f9e8a8b --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/ShowIf_Inspector.gif.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 64454bc61e4706d4792d7f2d289ba722 +timeCreated: 1508669477 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ShowNativeProperty_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/ShowNativeProperty_Code.PNG new file mode 100644 index 0000000..e721b91 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/ShowNativeProperty_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ShowNativeProperty_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/ShowNativeProperty_Code.PNG.meta new file mode 100644 index 0000000..26bcbd7 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/ShowNativeProperty_Code.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 910bb6ff194fd964b952f93e9c3768cd +timeCreated: 1510927252 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ShowNativeProperty_Inspector.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/ShowNativeProperty_Inspector.PNG new file mode 100644 index 0000000..8969c64 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/ShowNativeProperty_Inspector.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ShowNativeProperty_Inspector.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/ShowNativeProperty_Inspector.PNG.meta new file mode 100644 index 0000000..c7ffb83 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/ShowNativeProperty_Inspector.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: cdd1d4dbda8666943acca44fba1b3772 +timeCreated: 1510927311 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ShowNonSerializedField_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/ShowNonSerializedField_Code.PNG new file mode 100644 index 0000000..4bac8d6 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/ShowNonSerializedField_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ShowNonSerializedField_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/ShowNonSerializedField_Code.PNG.meta new file mode 100644 index 0000000..232434b --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/ShowNonSerializedField_Code.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: c38bd18425e6caf4c96de9e9dc75d44a +timeCreated: 1508840999 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ShowNonSerializedField_Inspector.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/ShowNonSerializedField_Inspector.PNG new file mode 100644 index 0000000..a1f3795 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/ShowNonSerializedField_Inspector.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ShowNonSerializedField_Inspector.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/ShowNonSerializedField_Inspector.PNG.meta new file mode 100644 index 0000000..54c469a --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/ShowNonSerializedField_Inspector.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: fa565d87ea4765f43ab14b962d78d1d3 +timeCreated: 1508840999 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Slider_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/Slider_Code.PNG new file mode 100644 index 0000000..336bdf3 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/Slider_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Slider_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/Slider_Code.PNG.meta new file mode 100644 index 0000000..909445c --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/Slider_Code.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: c2e8583b447997d4894f6882accea083 +timeCreated: 1508669478 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Slider_Inspector.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/Slider_Inspector.PNG new file mode 100644 index 0000000..e745e41 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/Slider_Inspector.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/Slider_Inspector.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/Slider_Inspector.PNG.meta new file mode 100644 index 0000000..36d1aca --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/Slider_Inspector.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 53adc0cfbf605284a9df9e29f962da09 +timeCreated: 1508669477 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ValidateInput_Code.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/ValidateInput_Code.PNG new file mode 100644 index 0000000..9ff2ea7 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/ValidateInput_Code.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ValidateInput_Code.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/ValidateInput_Code.PNG.meta new file mode 100644 index 0000000..1524e0a --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/ValidateInput_Code.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: ea806f31fb59c894e84a667948d116fc +timeCreated: 1508669478 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ValidateInput_Inspector.PNG b/Assets/Plugins/NaughtyAttributes/Documentation/ValidateInput_Inspector.PNG new file mode 100644 index 0000000..084d203 Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/Documentation/ValidateInput_Inspector.PNG differ diff --git a/Assets/Plugins/NaughtyAttributes/Documentation/ValidateInput_Inspector.PNG.meta b/Assets/Plugins/NaughtyAttributes/Documentation/ValidateInput_Inspector.PNG.meta new file mode 100644 index 0000000..28ea083 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Documentation/ValidateInput_Inspector.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 147278501eff2104aa2bdb9c911b580f +timeCreated: 1508669477 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/LICENSE.txt b/Assets/Plugins/NaughtyAttributes/LICENSE.txt new file mode 100644 index 0000000..65b7986 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Denis Rizov + +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/Plugins/NaughtyAttributes/LICENSE.txt.meta b/Assets/Plugins/NaughtyAttributes/LICENSE.txt.meta new file mode 100644 index 0000000..05298d4 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/LICENSE.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a27c3cea5bb5d104689063a76c54ad08 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/README.md b/Assets/Plugins/NaughtyAttributes/README.md new file mode 100644 index 0000000..ba956a8 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/README.md @@ -0,0 +1,216 @@ +# NaughtyAttributes +NaughtyAttributes is an extension for the Unity Inspector. + +It expands the range of attributes that Unity provides so that you can create powerful inspectors without the need of custom editors or property drawers. It also provides attributes that can be applied to non-serialized fields or functions. + +It is implemented by replacing the default Unity Inspector. This means that if you have any custom editors, NaughtyAttributes will not work with them. All of your custom editors and property drawers are not affected in any way. + +## System Requirements +Unity 2017.1.0 or later versions. Feel free to try older version. Don't forget to include the NaughtyAttributes namespace. + +## Drawer Attributes +Provide special draw options to serialized fields. +A field can have only one DrawerAttribute. If a field has more than one, only the bottom one will be used. + +### Slider +The same as Unity's **Range** attribute. +There is no difference between the two, you can use whatever you like, I just wanted to support a custom slider attribute. + +![code](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/Slider_Code.PNG) + +![inspector](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/Slider_Inspector.PNG) + +### MinMaxSlider +A double slider. The **min value** is saved to the **X** property, and the **max value** is saved to the **Y** property of a **Vector2** field. + +![code](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/MinMaxSlider_Code.PNG) + +![inspector](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/MinMaxSlider_Inspector.PNG) + +### ReorderableList +Provides array type fields with an interface for easy reordering of elements. + +![code](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/ReorderableList_Code.PNG) + +![inspector](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/ReorderableList_Inspector.gif) + +### Button +A method can be marked as a button. A button appears in the inspector and executes the method if clicked. +Works both with instance and static methods. + +![code](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/Button_Code.PNG) + +![inspector](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/Button_Inspector.PNG) + +### Dropdown +Provides an interface for dropdown value selection. + +![code](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/Dropdown_Code.PNG) + +![inspector](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/Dropdown_Inspector.gif) + +### ResizableTextArea +A resizable text area where you can see the whole text. +Unlike Unity's **Multiline** and **TextArea** attributes where you can see only 3 rows of a given text, and in order to see it or modify it you have to manually scroll down to the desired row. + +![code](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/ResizableTextArea_Code.PNG) + +![inspector](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/ResizableTextArea_Inspector.gif) + +### ShowNonSerializedField +Shows non-serialized fields in the inspector. +All non-serialized fields are displayed at the botton of the inspector before the method buttons. +Keep in mind that if you change a non-static non-serialized field in the code - the value in the inspector will be updated after you press **Play** in the editor. +There is no such issue with static non-serialized fields because their values are updated at compile time. +It supports only certain types **(bool, int, long, float, double, string, Vector2, Vector3, Vector4, Color, Bounds, Rect, UnityEngine.Object)**. + +![code](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/ShowNonSerializedField_Code.PNG) + +![inspector](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/ShowNonSerializedField_Inspector.PNG) + +### ShowNativeProperty +Shows native C# properties in the inspector. +All native properties are displayed at the bottom of the inspector after the non-serialized fields and before the method buttons. +It supports only certain types **(bool, int, long, float, double, string, Vector2, Vector3, Vector4, Color, Bounds, Rect, UnityEngine.Object)**. + +![code](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/ShowNativeProperty_Code.PNG) + +![inspector](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/ShowNativeProperty_Inspector.PNG) + +### ReadOnly +Makes a field read only. + +![code](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/ReadOnly_Code.PNG) + +![inspector](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/ReadOnly_Inspector.PNG) + +### EnableIf / DisableIf +Thanks to [Chris Lewis](https://github.com/cmlewis89) + +![code](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/EnableIf_Code.PNG) + +![inspector](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/EnableIf_Inspector.gif) + +### ShowAssetPreview +Shows the texture preview of a given asset (Sprite, Prefab...) + +![code](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/ShowAssetPreview_Code.PNG) + +![inspector](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/ShowAssetPreview_Inspector.PNG) + +### ProgressBar +Thanks to [Shinao](https://github.com/Shinao) + +![code](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/ProgressBar_Code.png) + +![inspector](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/ProgressBar_Inspector.gif) + +## DrawCondition Attributes +Can be used to specify when a given serialized field is visible, and when not. A field can have only one DrawConditionAttribute. + +### ShowIf / HideIf +![code](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/ShowIf_Code.PNG) + +![inspector](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/ShowIf_Inspector.gif) + +## Group Attributes +Serialized fields can be grouped in different groups. +A field can have only one GroupAttribute. If a field has more than one, only the bottom one will be used. + +### BoxGroup +Surrounds grouped fields with a box. + +![code](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/BoxGroup_Code.PNG) + +![inspector](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/BoxGroup_Inspector.PNG) + +## Validator Attributes +Used for validating the fields. A field can have infinite number of validator attributes. + +### MinValue / MaxValue +Clamps integer and float fields. + +![code](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/MinValueMaxValue_Code.PNG) + +![inspector](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/MinValueMaxValue_Inspector.gif) + +### Required +Used to remind the developer that a given reference type field is required. + +![code](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/Required_Code.PNG) + +![inspector](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/Required_Inspector.PNG) + +### ValidateInput +The most powerful ValidatorAttribute. + +![code](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/ValidateInput_Code.PNG) + +![inspector](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/ValidateInput_Inspector.PNG) + +## Meta Attributes +Give the fields meta data. A field can have infinite number of meta attributes. + +### InfoBox +Used for providing additional information. + +![code](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/InfoBox_Code.PNG) + +![inspector](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/InfoBox_Inspector.PNG) + +### OnValueChanged +Detects a value change and executes a callback. +Keep in mind that the event is detected only when the value is changed from the inspector. +If you want a runtime event, you should probably use an event/delegate and subscribe to it. + +![code](https://github.com/dbrizov/NaughtyAttributes/blob/master/Assets/Plugins/NaughtyAttributes/Documentation/OnValueChanged_Code.PNG) + +## How to create your own attributes +Lets say you want to implement your own **[ReadOnly]** attribute. + +First you have to create a **ReadOnlyAttribute** class +``` +[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] +public class ReadOnlyAttribute : DrawerAttribute +{ +} +``` + +Then you need to create a drawer for that attribute +``` +[PropertyDrawer(typeof(ReadOnlyAttribute))] +public class ReadOnlyPropertyDrawer : PropertyDrawer +{ + public override void DrawProperty(SerializedProperty property) + { + GUI.enabled = false; + EditorGUILayout.PropertyField(property, true); + GUI.enabled = true; + } +} +``` + +Last, in order for the editor to recognize the drawer for this attribute, you have to press the **Tools/NaughtyAttributes/Update Attributes Database** menu item in the editor. + +## License +MIT License + +Copyright (c) 2017 Denis Rizov + +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/Plugins/NaughtyAttributes/README.md.meta b/Assets/Plugins/NaughtyAttributes/README.md.meta new file mode 100644 index 0000000..fc20fed --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a8a41fa5604699a4f88e6de0a81fb8de +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts.meta b/Assets/Plugins/NaughtyAttributes/Scripts.meta new file mode 100644 index 0000000..238d7e9 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 66686847ee1fa044bb15dfe473666178 +folderAsset: yes +timeCreated: 1507995546 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core.meta new file mode 100644 index 0000000..a055450 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 1f67e408a6d0adf4ab29d095ccd8b116 +folderAsset: yes +timeCreated: 1507998942 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes.meta new file mode 100644 index 0000000..1b422d7 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 0d8ad70d0e1e04248b1f5c5d5fb358f4 +folderAsset: yes +timeCreated: 1508414568 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes/DrawConditionAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes/DrawConditionAttribute.cs new file mode 100644 index 0000000..30b684f --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes/DrawConditionAttribute.cs @@ -0,0 +1,9 @@ +using System; + +namespace NaughtyAttributes +{ + public class DrawConditionAttribute : NaughtyAttribute + { + + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes/DrawConditionAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes/DrawConditionAttribute.cs.meta new file mode 100644 index 0000000..6d27b22 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes/DrawConditionAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 8fd9817e8bf3e054ab8e73b47bdce8c7 +timeCreated: 1508414568 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes/HideIfAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes/HideIfAttribute.cs new file mode 100644 index 0000000..0ebbe07 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes/HideIfAttribute.cs @@ -0,0 +1,15 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class HideIfAttribute : DrawConditionAttribute + { + public string ConditionName { get; private set; } + + public HideIfAttribute(string conditionName) + { + this.ConditionName = conditionName; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes/HideIfAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes/HideIfAttribute.cs.meta new file mode 100644 index 0000000..363b863 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes/HideIfAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: aafc3a255165311419b7070198e7ffaf +timeCreated: 1508414568 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes/ShowIfAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes/ShowIfAttribute.cs new file mode 100644 index 0000000..6f67e3b --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes/ShowIfAttribute.cs @@ -0,0 +1,15 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class ShowIfAttribute : DrawConditionAttribute + { + public string ConditionName { get; private set; } + + public ShowIfAttribute(string conditionName) + { + this.ConditionName = conditionName; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes/ShowIfAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes/ShowIfAttribute.cs.meta new file mode 100644 index 0000000..cff1299 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawConditionAttributes/ShowIfAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 6a9e9448e6e70094297d49ec9c82c6e1 +timeCreated: 1508414568 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes.meta new file mode 100644 index 0000000..756c714 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: c76425e719cd4424d868674bcfb233f2 +folderAsset: yes +timeCreated: 1508151410 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ButtonAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ButtonAttribute.cs new file mode 100644 index 0000000..e88e3d4 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ButtonAttribute.cs @@ -0,0 +1,24 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public class ButtonAttribute : DrawerAttribute + { + public enum ButtonInvocationTarget + { + Default, + First, + All + } + + public string Text { get; private set; } + + public ButtonInvocationTarget Target { get; set; } + + public ButtonAttribute(string text = null) + { + this.Text = text; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ButtonAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ButtonAttribute.cs.meta new file mode 100644 index 0000000..3f00112 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ButtonAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: d61d9be90aa48764096a2bea37c9bd60 +timeCreated: 1508591778 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/DisableIfAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/DisableIfAttribute.cs new file mode 100644 index 0000000..39c74d0 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/DisableIfAttribute.cs @@ -0,0 +1,15 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class DisableIfAttribute : DrawerAttribute + { + public string ConditionName { get; private set; } + + public DisableIfAttribute(string conditionName) + { + this.ConditionName = conditionName; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/DisableIfAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/DisableIfAttribute.cs.meta new file mode 100644 index 0000000..7315069 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/DisableIfAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dac53a514fd03bb48b3fae8d3d23bf78 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/DrawerAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/DrawerAttribute.cs new file mode 100644 index 0000000..b3a3a67 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/DrawerAttribute.cs @@ -0,0 +1,8 @@ +using System; + +namespace NaughtyAttributes +{ + public abstract class DrawerAttribute : NaughtyAttribute + { + } +} \ No newline at end of file diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/DrawerAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/DrawerAttribute.cs.meta new file mode 100644 index 0000000..2043b25 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/DrawerAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 57360d74732bf2749b2f8d5e0a0ea6f5 +timeCreated: 1508151410 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/DropdownAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/DropdownAttribute.cs new file mode 100644 index 0000000..0a433f4 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/DropdownAttribute.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class DropdownAttribute : DrawerAttribute + { + public string ValuesFieldName { get; private set; } + + public DropdownAttribute(string valuesFieldName) + { + this.ValuesFieldName = valuesFieldName; + } + } + + public interface IDropdownList : IEnumerable> + { + } + + public class DropdownList : IDropdownList + { + private List> values; + + public DropdownList() + { + this.values = new List>(); + } + + public void Add(string displayName, T value) + { + this.values.Add(new KeyValuePair(displayName, value)); + } + + public IEnumerator> GetEnumerator() + { + return this.values.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + + public static explicit operator DropdownList(DropdownList target) + { + DropdownList result = new DropdownList(); + foreach (var kvp in target) + { + result.Add(kvp.Key, kvp.Value); + } + + return result; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/DropdownAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/DropdownAttribute.cs.meta new file mode 100644 index 0000000..a402b5a --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/DropdownAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: cd3b8c98b0803554e9152991fe806c62 +timeCreated: 1508752474 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/EnableIfAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/EnableIfAttribute.cs new file mode 100644 index 0000000..5da4653 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/EnableIfAttribute.cs @@ -0,0 +1,15 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class EnableIfAttribute : DrawerAttribute + { + public string ConditionName { get; private set; } + + public EnableIfAttribute(string conditionName) + { + this.ConditionName = conditionName; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/EnableIfAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/EnableIfAttribute.cs.meta new file mode 100644 index 0000000..b2e4973 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/EnableIfAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a3ef98b2c0ffe1b4c91fbec23d77898e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/EnumFlagAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/EnumFlagAttribute.cs new file mode 100644 index 0000000..bc729f0 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/EnumFlagAttribute.cs @@ -0,0 +1,10 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class EnumFlagAttribute : DrawerAttribute + { + + } +} \ No newline at end of file diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/EnumFlagAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/EnumFlagAttribute.cs.meta new file mode 100644 index 0000000..e7edce6 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/EnumFlagAttribute.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cb8571c60a2443798cf9a86975107aad +timeCreated: 1555186919 \ No newline at end of file diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/MinMaxSliderAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/MinMaxSliderAttribute.cs new file mode 100644 index 0000000..aa429de --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/MinMaxSliderAttribute.cs @@ -0,0 +1,17 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class MinMaxSliderAttribute : DrawerAttribute + { + public float MinValue { get; private set; } + public float MaxValue { get; private set; } + + public MinMaxSliderAttribute(float minValue, float maxValue) + { + this.MinValue = minValue; + this.MaxValue = maxValue; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/MinMaxSliderAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/MinMaxSliderAttribute.cs.meta new file mode 100644 index 0000000..8dd63f3 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/MinMaxSliderAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 61d133a2d203a77419f35652a7f3fae0 +timeCreated: 1508427131 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ProgressBarAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ProgressBarAttribute.cs new file mode 100644 index 0000000..0649477 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ProgressBarAttribute.cs @@ -0,0 +1,32 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class ProgressBarAttribute : DrawerAttribute + { + public string Name { get; private set; } + public float MaxValue { get; private set; } + public ProgressBarColor Color { get; private set; } + + public ProgressBarAttribute(string name = "", float maxValue = 100, ProgressBarColor color = ProgressBarColor.Blue) + { + Name = name; + MaxValue = maxValue; + Color = color; + } + } + + public enum ProgressBarColor + { + Red, + Pink, + Orange, + Yellow, + Green, + Blue, + Indigo, + Violet, + White + } +} \ No newline at end of file diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ProgressBarAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ProgressBarAttribute.cs.meta new file mode 100644 index 0000000..65bfa95 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ProgressBarAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 8d8eb74e78cba7b43b3025525c5084b9 +timeCreated: 1518435237 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ReadOnlyAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ReadOnlyAttribute.cs new file mode 100644 index 0000000..d29794a --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ReadOnlyAttribute.cs @@ -0,0 +1,9 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class ReadOnlyAttribute : DrawerAttribute + { + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ReadOnlyAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ReadOnlyAttribute.cs.meta new file mode 100644 index 0000000..54b0ced --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ReadOnlyAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 4fa676ebc6d589c44817272871db148b +timeCreated: 1508862052 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ReorderableListAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ReorderableListAttribute.cs new file mode 100644 index 0000000..ff1a701 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ReorderableListAttribute.cs @@ -0,0 +1,9 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class ReorderableListAttribute : DrawerAttribute + { + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ReorderableListAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ReorderableListAttribute.cs.meta new file mode 100644 index 0000000..59e4c99 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ReorderableListAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: ff85489452472c241987e5ba4c5e512a +timeCreated: 1508402303 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ResizableTextAreaAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ResizableTextAreaAttribute.cs new file mode 100644 index 0000000..e84e664 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ResizableTextAreaAttribute.cs @@ -0,0 +1,9 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class ResizableTextAreaAttribute : DrawerAttribute + { + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ResizableTextAreaAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ResizableTextAreaAttribute.cs.meta new file mode 100644 index 0000000..43e40fd --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ResizableTextAreaAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 1793ea6e464ee6448930ecf133ed6a1d +timeCreated: 1508583166 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ShowAssetPreviewAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ShowAssetPreviewAttribute.cs new file mode 100644 index 0000000..6b35444 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ShowAssetPreviewAttribute.cs @@ -0,0 +1,17 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class ShowAssetPreviewAttribute : DrawerAttribute + { + public int Width { get; private set; } + public int Height { get; private set; } + + public ShowAssetPreviewAttribute(int width = 64, int height = 64) + { + this.Width = width; + this.Height = height; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ShowAssetPreviewAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ShowAssetPreviewAttribute.cs.meta new file mode 100644 index 0000000..bcdeb2c --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ShowAssetPreviewAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 313b856a920a987418d6437a8e20a59f +timeCreated: 1509089502 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ShowNativePropertyAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ShowNativePropertyAttribute.cs new file mode 100644 index 0000000..bb8a7c7 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ShowNativePropertyAttribute.cs @@ -0,0 +1,11 @@ +using System; +using UnityEngine; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] + public class ShowNativePropertyAttribute : DrawerAttribute + { + + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ShowNativePropertyAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ShowNativePropertyAttribute.cs.meta new file mode 100644 index 0000000..29f619d --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ShowNativePropertyAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: acc7d7e8ec9e47a4aaf4167698ae076f +timeCreated: 1510926376 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ShowNonSerializedFieldAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ShowNonSerializedFieldAttribute.cs new file mode 100644 index 0000000..8f311ef --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ShowNonSerializedFieldAttribute.cs @@ -0,0 +1,9 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class ShowNonSerializedFieldAttribute : DrawerAttribute + { + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ShowNonSerializedFieldAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ShowNonSerializedFieldAttribute.cs.meta new file mode 100644 index 0000000..d21b234 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/ShowNonSerializedFieldAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: a176aad85de73b34ba3ecd4f7baa367b +timeCreated: 1508835721 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/SliderAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/SliderAttribute.cs new file mode 100644 index 0000000..ece2b58 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/SliderAttribute.cs @@ -0,0 +1,23 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class SliderAttribute : DrawerAttribute + { + public float MinValue { get; private set; } + public float MaxValue { get; private set; } + + public SliderAttribute(float minValue, float maxValue) + { + this.MinValue = minValue; + this.MaxValue = maxValue; + } + + public SliderAttribute(int minValue, int maxValue) + { + this.MaxValue = minValue; + this.MaxValue = maxValue; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/SliderAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/SliderAttribute.cs.meta new file mode 100644 index 0000000..b121855 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/DrawerAttributes/SliderAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: f75eef8142877c345ba9b95046dd3bf6 +timeCreated: 1508422518 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/GroupAttributes.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/GroupAttributes.meta new file mode 100644 index 0000000..4455f01 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/GroupAttributes.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 86ca4f90dd05bc448959ecd8f44097a7 +folderAsset: yes +timeCreated: 1508330803 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/GroupAttributes/BoxGroupAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/GroupAttributes/BoxGroupAttribute.cs new file mode 100644 index 0000000..d66b693 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/GroupAttributes/BoxGroupAttribute.cs @@ -0,0 +1,13 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = true)] + public class BoxGroupAttribute : GroupAttribute + { + public BoxGroupAttribute(string name = "") + : base(name) + { + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/GroupAttributes/BoxGroupAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/GroupAttributes/BoxGroupAttribute.cs.meta new file mode 100644 index 0000000..fcdb278 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/GroupAttributes/BoxGroupAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 88c5a8d79f9e72a43a4cfa67fd08fdd6 +timeCreated: 1508326108 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/GroupAttributes/GroupAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/GroupAttributes/GroupAttribute.cs new file mode 100644 index 0000000..a317fe2 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/GroupAttributes/GroupAttribute.cs @@ -0,0 +1,14 @@ +using System; + +namespace NaughtyAttributes +{ + public abstract class GroupAttribute : NaughtyAttribute + { + public string Name { get; private set; } + + public GroupAttribute(string name) + { + this.Name = name; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/GroupAttributes/GroupAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/GroupAttributes/GroupAttribute.cs.meta new file mode 100644 index 0000000..db3cc39 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/GroupAttributes/GroupAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: beb48511ef6091e4ba054ad1b618933c +timeCreated: 1508326108 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes.meta new file mode 100644 index 0000000..f2ed90e --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 51ee806b39c5fb343ae7d268404d8c67 +folderAsset: yes +timeCreated: 1508497398 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes/InfoBoxAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes/InfoBoxAttribute.cs new file mode 100644 index 0000000..d09c616 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes/InfoBoxAttribute.cs @@ -0,0 +1,31 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = true, Inherited = true)] + public class InfoBoxAttribute : MetaAttribute + { + public string Text { get; private set; } + public InfoBoxType Type { get; private set; } + public string VisibleIf { get; private set; } + + public InfoBoxAttribute(string text, InfoBoxType type = InfoBoxType.Normal, string visibleIf = null) + { + this.Text = text; + this.Type = type; + this.VisibleIf = visibleIf; + } + + public InfoBoxAttribute(string text, string visibleIf) + : this(text, InfoBoxType.Normal, visibleIf) + { + } + } + + public enum InfoBoxType + { + Normal, + Warning, + Error + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes/InfoBoxAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes/InfoBoxAttribute.cs.meta new file mode 100644 index 0000000..19cb564 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes/InfoBoxAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 42c6184c84ab19d4382b06f9017f136d +timeCreated: 1508607449 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes/MetaAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes/MetaAttribute.cs new file mode 100644 index 0000000..ef2a451 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes/MetaAttribute.cs @@ -0,0 +1,9 @@ +using System; + +namespace NaughtyAttributes +{ + public abstract class MetaAttribute : NaughtyAttribute + { + public int Order { get; set; } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes/MetaAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes/MetaAttribute.cs.meta new file mode 100644 index 0000000..5f5e5d7 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes/MetaAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: fcd6d339bcd667044a48d41a78a7830c +timeCreated: 1508497398 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes/OnValueChangedAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes/OnValueChangedAttribute.cs new file mode 100644 index 0000000..ab826b8 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes/OnValueChangedAttribute.cs @@ -0,0 +1,15 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = true, Inherited = true)] + public class OnValueChangedAttribute : MetaAttribute + { + public string CallbackName { get; private set; } + + public OnValueChangedAttribute(string callbackName) + { + this.CallbackName = callbackName; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes/OnValueChangedAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes/OnValueChangedAttribute.cs.meta new file mode 100644 index 0000000..1452234 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/MetaAttributes/OnValueChangedAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: a144cdc17b6e4cf4f86692ae1dc7e4d7 +timeCreated: 1508610277 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/NaughtyAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/NaughtyAttribute.cs new file mode 100644 index 0000000..6251af9 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/NaughtyAttribute.cs @@ -0,0 +1,9 @@ +using System; + +namespace NaughtyAttributes +{ + // The base class for all naughty attributes + public class NaughtyAttribute : Attribute + { + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/NaughtyAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/NaughtyAttribute.cs.meta new file mode 100644 index 0000000..fdf1ddf --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/NaughtyAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 1accb89cb44c4a342a1857e5e3d13abb +timeCreated: 1508052914 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/NaughtyAttributes.asmdef b/Assets/Plugins/NaughtyAttributes/Scripts/Core/NaughtyAttributes.asmdef new file mode 100644 index 0000000..bfa8896 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/NaughtyAttributes.asmdef @@ -0,0 +1,3 @@ +{ + "name": "NaughtyAttributes" +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/NaughtyAttributes.asmdef.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/NaughtyAttributes.asmdef.meta new file mode 100644 index 0000000..fd8af9b --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/NaughtyAttributes.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ee89136d9a8326b458f7dad075c814e6 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes.meta new file mode 100644 index 0000000..9bee434 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 8a655727c2e629a438ad94f60080b9ea +folderAsset: yes +timeCreated: 1508151410 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/MaxValueAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/MaxValueAttribute.cs new file mode 100644 index 0000000..4c54127 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/MaxValueAttribute.cs @@ -0,0 +1,20 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class MaxValueAttribute : ValidatorAttribute + { + public float MaxValue { get; private set; } + + public MaxValueAttribute(float maxValue) + { + this.MaxValue = maxValue; + } + + public MaxValueAttribute(int maxValue) + { + this.MaxValue = maxValue; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/MaxValueAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/MaxValueAttribute.cs.meta new file mode 100644 index 0000000..4ba3b5a --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/MaxValueAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: e018059e7fe12fd42a3a1bba0dbbf9c5 +timeCreated: 1508047804 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/MinValueAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/MinValueAttribute.cs new file mode 100644 index 0000000..627e747 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/MinValueAttribute.cs @@ -0,0 +1,20 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class MinValueAttribute : ValidatorAttribute + { + public float MinValue { get; private set; } + + public MinValueAttribute(float minValue) + { + this.MinValue = minValue; + } + + public MinValueAttribute(int minValue) + { + this.MinValue = minValue; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/MinValueAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/MinValueAttribute.cs.meta new file mode 100644 index 0000000..19450e8 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/MinValueAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 337be62eb8c929f4ab8b3d495a712a56 +timeCreated: 1508048805 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/RequiredAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/RequiredAttribute.cs new file mode 100644 index 0000000..903f658 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/RequiredAttribute.cs @@ -0,0 +1,15 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class RequiredAttribute : ValidatorAttribute + { + public string Message { get; private set; } + + public RequiredAttribute(string message = null) + { + this.Message = message; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/RequiredAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/RequiredAttribute.cs.meta new file mode 100644 index 0000000..068d000 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/RequiredAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 0b70ebd0fbd89c648981f08469806779 +timeCreated: 1508655546 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/ValidateInputAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/ValidateInputAttribute.cs new file mode 100644 index 0000000..d024816 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/ValidateInputAttribute.cs @@ -0,0 +1,17 @@ +using System; + +namespace NaughtyAttributes +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class ValidateInputAttribute : ValidatorAttribute + { + public string CallbackName { get; private set; } + public string Message { get; private set; } + + public ValidateInputAttribute(string callbackName, string message = null) + { + this.CallbackName = callbackName; + this.Message = message; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/ValidateInputAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/ValidateInputAttribute.cs.meta new file mode 100644 index 0000000..ed365d1 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/ValidateInputAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: f13ea28cf56e89f4cb335e28c9ab5d9a +timeCreated: 1508657795 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/ValidatorAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/ValidatorAttribute.cs new file mode 100644 index 0000000..38222eb --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/ValidatorAttribute.cs @@ -0,0 +1,8 @@ +using System; + +namespace NaughtyAttributes +{ + public abstract class ValidatorAttribute : NaughtyAttribute + { + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/ValidatorAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/ValidatorAttribute.cs.meta new file mode 100644 index 0000000..668f7e1 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Core/ValidatorAttributes/ValidatorAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 5fac74a9575c45342be1e6dda45610ad +timeCreated: 1508151410 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor.meta new file mode 100644 index 0000000..8110aa8 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: b76068e69df25a94ab378b0b6829c4f0 +folderAsset: yes +timeCreated: 1507995613 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes.meta new file mode 100644 index 0000000..3f8ebe7 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: bfd420e5bf6a25049b8fcea8b2f48c94 +folderAsset: yes +timeCreated: 1508153828 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/BaseAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/BaseAttribute.cs new file mode 100644 index 0000000..b3fef44 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/BaseAttribute.cs @@ -0,0 +1,23 @@ +using System; + +namespace NaughtyAttributes.Editor +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public abstract class BaseAttribute : Attribute, IAttribute + { + private Type targetAttributeType; + + public BaseAttribute(Type targetAttributeType) + { + this.targetAttributeType = targetAttributeType; + } + + public Type TargetAttributeType + { + get + { + return this.targetAttributeType; + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/BaseAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/BaseAttribute.cs.meta new file mode 100644 index 0000000..d12b1ae --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/BaseAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: dd861c512b7cd804fa5f01b4d0e9f5bc +timeCreated: 1508424822 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/FieldDrawerAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/FieldDrawerAttribute.cs new file mode 100644 index 0000000..e2de8b0 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/FieldDrawerAttribute.cs @@ -0,0 +1,11 @@ +using System; + +namespace NaughtyAttributes.Editor +{ + public class FieldDrawerAttribute : BaseAttribute + { + public FieldDrawerAttribute(Type targetAttributeType) : base(targetAttributeType) + { + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/FieldDrawerAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/FieldDrawerAttribute.cs.meta new file mode 100644 index 0000000..456e222 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/FieldDrawerAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: ad0dbf00ca9ec1e4290145dc40bda96f +timeCreated: 1508835980 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/IAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/IAttribute.cs new file mode 100644 index 0000000..5d24b68 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/IAttribute.cs @@ -0,0 +1,9 @@ +using System; + +namespace NaughtyAttributes.Editor +{ + public interface IAttribute + { + Type TargetAttributeType { get; } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/IAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/IAttribute.cs.meta new file mode 100644 index 0000000..4b3a9d9 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/IAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: eec883c51d802eb49be41f384e227dad +timeCreated: 1508424822 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/MethodDrawerAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/MethodDrawerAttribute.cs new file mode 100644 index 0000000..ad78d4b --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/MethodDrawerAttribute.cs @@ -0,0 +1,11 @@ +using System; + +namespace NaughtyAttributes.Editor +{ + public class MethodDrawerAttribute : BaseAttribute + { + public MethodDrawerAttribute(Type targetAttributeType) : base(targetAttributeType) + { + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/MethodDrawerAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/MethodDrawerAttribute.cs.meta new file mode 100644 index 0000000..7b6acd3 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/MethodDrawerAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: b89ac4d9b78686548baa09fb0b103850 +timeCreated: 1508592495 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/NativePropertyDrawerAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/NativePropertyDrawerAttribute.cs new file mode 100644 index 0000000..d60e141 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/NativePropertyDrawerAttribute.cs @@ -0,0 +1,11 @@ +using System; + +namespace NaughtyAttributes.Editor +{ + public class NativePropertyDrawerAttribute : BaseAttribute + { + public NativePropertyDrawerAttribute(Type targetAttributeType) : base(targetAttributeType) + { + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/NativePropertyDrawerAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/NativePropertyDrawerAttribute.cs.meta new file mode 100644 index 0000000..9a726e7 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/NativePropertyDrawerAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 7c30e23a060c0614b876d7f14e0ee649 +timeCreated: 1510924166 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyDrawConditionAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyDrawConditionAttribute.cs new file mode 100644 index 0000000..c8fa6e9 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyDrawConditionAttribute.cs @@ -0,0 +1,11 @@ +using System; + +namespace NaughtyAttributes.Editor +{ + public class PropertyDrawConditionAttribute : BaseAttribute + { + public PropertyDrawConditionAttribute(Type targetAttributeType) : base(targetAttributeType) + { + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyDrawConditionAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyDrawConditionAttribute.cs.meta new file mode 100644 index 0000000..663b290 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyDrawConditionAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: d7962631135870e4fa748e6f81cd64d4 +timeCreated: 1508414568 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyDrawerAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyDrawerAttribute.cs new file mode 100644 index 0000000..cce3c96 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyDrawerAttribute.cs @@ -0,0 +1,11 @@ +using System; + +namespace NaughtyAttributes.Editor +{ + public class PropertyDrawerAttribute : BaseAttribute + { + public PropertyDrawerAttribute(Type targetAttributeType) : base(targetAttributeType) + { + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyDrawerAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyDrawerAttribute.cs.meta new file mode 100644 index 0000000..3b4803b --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyDrawerAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 77bb6824c4e9e054db05347dd8465f24 +timeCreated: 1508153828 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyGrouperAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyGrouperAttribute.cs new file mode 100644 index 0000000..5574cc5 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyGrouperAttribute.cs @@ -0,0 +1,11 @@ +using System; + +namespace NaughtyAttributes.Editor +{ + public class PropertyGrouperAttribute : BaseAttribute + { + public PropertyGrouperAttribute(Type targetAttributeType) : base(targetAttributeType) + { + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyGrouperAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyGrouperAttribute.cs.meta new file mode 100644 index 0000000..757cf05 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyGrouperAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 9d1b7efb592ab4a4796c70edaad2be75 +timeCreated: 1508332897 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyMetaAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyMetaAttribute.cs new file mode 100644 index 0000000..0d2e09c --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyMetaAttribute.cs @@ -0,0 +1,11 @@ +using System; + +namespace NaughtyAttributes.Editor +{ + public class PropertyMetaAttribute : BaseAttribute + { + public PropertyMetaAttribute(Type targetAttributeType) : base(targetAttributeType) + { + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyMetaAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyMetaAttribute.cs.meta new file mode 100644 index 0000000..2537218 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyMetaAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: b46e1700b41c60141b19b0a7ed25a383 +timeCreated: 1508497398 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyValidatorAttribute.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyValidatorAttribute.cs new file mode 100644 index 0000000..375bd33 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyValidatorAttribute.cs @@ -0,0 +1,11 @@ +using System; + +namespace NaughtyAttributes.Editor +{ + public class PropertyValidatorAttribute : BaseAttribute + { + public PropertyValidatorAttribute(Type targetAttributeType) : base(targetAttributeType) + { + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyValidatorAttribute.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyValidatorAttribute.cs.meta new file mode 100644 index 0000000..1e3fbfe --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Attributes/PropertyValidatorAttribute.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 38c34a83bfd0a07468f20ae50c36737f +timeCreated: 1508153828 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration.meta new file mode 100644 index 0000000..4d91c4b --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 3876cb6aacfb99f46803d5e50eacdf2c +folderAsset: yes +timeCreated: 1508230862 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/CodeGenerator.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/CodeGenerator.cs new file mode 100644 index 0000000..bafbf0b --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/CodeGenerator.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using UnityEngine; +using UnityEditor; + +namespace NaughtyAttributes.Editor +{ + public class CodeGenerator : UnityEditor.Editor + { + private static readonly string GENERATED_CODE_TARGET_FOLDER = + (Application.dataPath.Replace("Assets", string.Empty) + AssetDatabase.GUIDToAssetPath(AssetDatabase.FindAssets("CodeGenerator")[0])) + .Replace("CodeGenerator.cs", string.Empty) + .Replace("/", "\\"); + + private static readonly string CLASS_NAME_PLACEHOLDER = "__classname__"; + private static readonly string ENTRIES_PLACEHOLDER = "__entries__"; + private static readonly string META_ENTRY_FORMAT = "metasByAttributeType[typeof({0})] = new {1}();" + Environment.NewLine; + private static readonly string DRAWER_ENTRY_FORMAT = "drawersByAttributeType[typeof({0})] = new {1}();" + Environment.NewLine; + private static readonly string GROUPER_ENTRY_FORMAT = "groupersByAttributeType[typeof({0})] = new {1}();" + Environment.NewLine; + private static readonly string VALIDATOR_ENTRY_FORMAT = "validatorsByAttributeType[typeof({0})] = new {1}();" + Environment.NewLine; + private static readonly string DRAW_CONDITION_ENTRY_FORMAT = "drawConditionsByAttributeType[typeof({0})] = new {1}();" + Environment.NewLine; + + //[UnityEditor.Callbacks.DidReloadScripts] + [MenuItem("Tools/NaughtyAttributes/Update Attributes Database")] + private static void GenerateCode() + { + GenerateScript("PropertyMetaDatabase", "PropertyMetaDatabaseTemplate", META_ENTRY_FORMAT); + GenerateScript("PropertyDrawerDatabase", "PropertyDrawerDatabaseTemplate", DRAWER_ENTRY_FORMAT); + GenerateScript("PropertyGrouperDatabase", "PropertyGrouperDatabaseTemplate", GROUPER_ENTRY_FORMAT); + GenerateScript("PropertyValidatorDatabase", "PropertyValidatorDatabaseTemplate", VALIDATOR_ENTRY_FORMAT); + GenerateScript("PropertyDrawConditionDatabase", "PropertyDrawConditionDatabaseTemplate", DRAW_CONDITION_ENTRY_FORMAT); + + GenerateScript("FieldDrawerDatabase", "FieldDrawerDatabaseTemplate", DRAWER_ENTRY_FORMAT); + GenerateScript("MethodDrawerDatabase", "MethodDrawerDatabaseTemplate", DRAWER_ENTRY_FORMAT); + GenerateScript("NativePropertyDrawerDatabase", "NativePropertyDrawerDbTemplate", DRAWER_ENTRY_FORMAT); + + AssetDatabase.Refresh(); + } + + private static void GenerateScript(string scriptName, string templateName, string entryFormat) + where TAttribute : IAttribute + { + string[] templateAssets = AssetDatabase.FindAssets(templateName); + if (templateAssets.Length == 0) + { + return; + } + + string templateGUID = templateAssets[0]; + string templateRelativePath = AssetDatabase.GUIDToAssetPath(templateGUID); + string templateFormat = (AssetDatabase.LoadAssetAtPath(templateRelativePath, typeof(TextAsset)) as TextAsset).ToString(); + //string templateFullPath = (Application.dataPath.Replace("Assets", string.Empty) + templateRelativePath).Replace("/", "\\"); + //string templateFormat = IOUtility.ReadFromFile(templateFullPath); + + StringBuilder entriesBuilder = new StringBuilder(); + List subTypes = GetAllSubTypes(typeof(TClass)); + + foreach (var subType in subTypes) + { + IAttribute[] attributes = (IAttribute[])subType.GetCustomAttributes(typeof(TAttribute), true); + if (attributes.Length > 0) + { + entriesBuilder.AppendFormat(entryFormat, attributes[0].TargetAttributeType.Name, subType.Name); + } + } + + string scriptContent = templateFormat + .Replace(CLASS_NAME_PLACEHOLDER, scriptName) + .Replace(ENTRIES_PLACEHOLDER, entriesBuilder.ToString()); + + scriptContent = Regex.Replace(scriptContent, @"\r\n|\n\r|\r|\n", Environment.NewLine); // Normalize line endings + + string scriptPath = GENERATED_CODE_TARGET_FOLDER + scriptName + ".cs"; + + IOUtility.WriteToFile(scriptPath, scriptContent); + } + + private static List GetAllSubTypes(Type baseClass) + { + var result = new List(); + Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); + + foreach (var assemly in assemblies) + { + Type[] types = assemly.GetTypes(); + foreach (var type in types) + { + if (type.IsSubclassOf(baseClass)) + { + result.Add(type); + } + } + } + + return result; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/CodeGenerator.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/CodeGenerator.cs.meta new file mode 100644 index 0000000..2bbd870 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/CodeGenerator.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 990da0e1629b14049842bf2ac82cbff0 +timeCreated: 1508230160 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/FieldDrawerDatabase.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/FieldDrawerDatabase.cs new file mode 100644 index 0000000..a1e4692 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/FieldDrawerDatabase.cs @@ -0,0 +1,33 @@ +// This class is auto generated + +using System; +using System.Collections.Generic; + +namespace NaughtyAttributes.Editor +{ + public static class FieldDrawerDatabase + { + private static Dictionary drawersByAttributeType; + + static FieldDrawerDatabase() + { + drawersByAttributeType = new Dictionary(); + drawersByAttributeType[typeof(ShowNonSerializedFieldAttribute)] = new ShowNonSerializedFieldFieldDrawer(); + + } + + public static FieldDrawer GetDrawerForAttribute(Type attributeType) + { + FieldDrawer drawer; + if (drawersByAttributeType.TryGetValue(attributeType, out drawer)) + { + return drawer; + } + else + { + return null; + } + } + } +} + diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/FieldDrawerDatabase.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/FieldDrawerDatabase.cs.meta new file mode 100644 index 0000000..52c69e9 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/FieldDrawerDatabase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: b2406e32d0ab1214ab4959f1cdc8a609 +timeCreated: 1508836346 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/MethodDrawerDatabase.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/MethodDrawerDatabase.cs new file mode 100644 index 0000000..832fb60 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/MethodDrawerDatabase.cs @@ -0,0 +1,33 @@ +// This class is auto generated + +using System; +using System.Collections.Generic; + +namespace NaughtyAttributes.Editor +{ + public static class MethodDrawerDatabase + { + private static Dictionary drawersByAttributeType; + + static MethodDrawerDatabase() + { + drawersByAttributeType = new Dictionary(); + drawersByAttributeType[typeof(ButtonAttribute)] = new ButtonMethodDrawer(); + + } + + public static MethodDrawer GetDrawerForAttribute(Type attributeType) + { + MethodDrawer drawer; + if (drawersByAttributeType.TryGetValue(attributeType, out drawer)) + { + return drawer; + } + else + { + return null; + } + } + } +} + diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/MethodDrawerDatabase.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/MethodDrawerDatabase.cs.meta new file mode 100644 index 0000000..82b0f85 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/MethodDrawerDatabase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 40b81aa63ff76d34ea67277db99a6a25 +timeCreated: 1508592498 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/NativePropertyDrawerDatabase.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/NativePropertyDrawerDatabase.cs new file mode 100644 index 0000000..2844f95 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/NativePropertyDrawerDatabase.cs @@ -0,0 +1,33 @@ +// This class is auto generated + +using System; +using System.Collections.Generic; + +namespace NaughtyAttributes.Editor +{ + public static class NativePropertyDrawerDatabase + { + private static Dictionary drawersByAttributeType; + + static NativePropertyDrawerDatabase() + { + drawersByAttributeType = new Dictionary(); + drawersByAttributeType[typeof(ShowNativePropertyAttribute)] = new ShowNativePropertyNativePropertyDrawer(); + + } + + public static NativePropertyDrawer GetDrawerForAttribute(Type attributeType) + { + NativePropertyDrawer drawer; + if (drawersByAttributeType.TryGetValue(attributeType, out drawer)) + { + return drawer; + } + else + { + return null; + } + } + } +} + diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/NativePropertyDrawerDatabase.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/NativePropertyDrawerDatabase.cs.meta new file mode 100644 index 0000000..b86e8d3 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/NativePropertyDrawerDatabase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 9fd2f82e21266a94ea967208610dda1e +timeCreated: 1510925645 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyDrawConditionDatabase.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyDrawConditionDatabase.cs new file mode 100644 index 0000000..2bf40b8 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyDrawConditionDatabase.cs @@ -0,0 +1,34 @@ +// This class is auto generated + +using System; +using System.Collections.Generic; + +namespace NaughtyAttributes.Editor +{ + public static class PropertyDrawConditionDatabase + { + private static Dictionary drawConditionsByAttributeType; + + static PropertyDrawConditionDatabase() + { + drawConditionsByAttributeType = new Dictionary(); + drawConditionsByAttributeType[typeof(HideIfAttribute)] = new HideIfPropertyDrawCondition(); +drawConditionsByAttributeType[typeof(ShowIfAttribute)] = new ShowIfPropertyDrawCondition(); + + } + + public static PropertyDrawCondition GetDrawConditionForAttribute(Type attributeType) + { + PropertyDrawCondition drawCondition; + if (drawConditionsByAttributeType.TryGetValue(attributeType, out drawCondition)) + { + return drawCondition; + } + else + { + return null; + } + } + } +} + diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyDrawConditionDatabase.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyDrawConditionDatabase.cs.meta new file mode 100644 index 0000000..e4b5bff --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyDrawConditionDatabase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 0b96dc9fe878bfc49865d28d601a7468 +timeCreated: 1508414568 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyDrawerDatabase.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyDrawerDatabase.cs new file mode 100644 index 0000000..4e21af8 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyDrawerDatabase.cs @@ -0,0 +1,49 @@ +// This class is auto generated + +using System; +using System.Collections.Generic; + +namespace NaughtyAttributes.Editor +{ + public static class PropertyDrawerDatabase + { + private static readonly Dictionary drawersByAttributeType; + + static PropertyDrawerDatabase() + { + drawersByAttributeType = new Dictionary(); + drawersByAttributeType[typeof(DisableIfAttribute)] = new DisableIfPropertyDrawer(); + drawersByAttributeType[typeof(DropdownAttribute)] = new DropdownPropertyDrawer(); + drawersByAttributeType[typeof(EnableIfAttribute)] = new EnableIfPropertyDrawer(); + drawersByAttributeType[typeof(MinMaxSliderAttribute)] = new MinMaxSliderPropertyDrawer(); + drawersByAttributeType[typeof(ProgressBarAttribute)] = new ProgressBarPropertyDrawer(); + drawersByAttributeType[typeof(ReadOnlyAttribute)] = new ReadOnlyPropertyDrawer(); + drawersByAttributeType[typeof(ReorderableListAttribute)] = new ReorderableListPropertyDrawer(); + drawersByAttributeType[typeof(ResizableTextAreaAttribute)] = new ResizableTextAreaPropertyDrawer(); + drawersByAttributeType[typeof(ShowAssetPreviewAttribute)] = new ShowAssetPreviewPropertyDrawer(); + drawersByAttributeType[typeof(SliderAttribute)] = new SliderPropertyDrawer(); + drawersByAttributeType[typeof(EnumFlagAttribute)] = new EnumFlagPropertyDrawer(); + } + + public static PropertyDrawer GetDrawerForAttribute(Type attributeType) + { + PropertyDrawer drawer; + if (drawersByAttributeType.TryGetValue(attributeType, out drawer)) + { + return drawer; + } + else + { + return null; + } + } + + public static void ClearCache() + { + foreach (var kvp in drawersByAttributeType) + { + kvp.Value.ClearCache(); + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyDrawerDatabase.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyDrawerDatabase.cs.meta new file mode 100644 index 0000000..36c43db --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyDrawerDatabase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 57bb89ab38f8da84db719a3fad7934d2 +timeCreated: 1508241644 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyGrouperDatabase.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyGrouperDatabase.cs new file mode 100644 index 0000000..d2d067e --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyGrouperDatabase.cs @@ -0,0 +1,33 @@ +// This class is auto generated + +using System; +using System.Collections.Generic; + +namespace NaughtyAttributes.Editor +{ + public static class PropertyGrouperDatabase + { + private static Dictionary groupersByAttributeType; + + static PropertyGrouperDatabase() + { + groupersByAttributeType = new Dictionary(); + groupersByAttributeType[typeof(BoxGroupAttribute)] = new BoxGroupPropertyGrouper(); + + } + + public static PropertyGrouper GetGrouperForAttribute(Type attributeType) + { + PropertyGrouper grouper; + if (groupersByAttributeType.TryGetValue(attributeType, out grouper)) + { + return grouper; + } + else + { + return null; + } + } + } +} + diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyGrouperDatabase.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyGrouperDatabase.cs.meta new file mode 100644 index 0000000..bc0f34b --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyGrouperDatabase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 0e5fed99fdc5f794291677a80073b4ba +timeCreated: 1508333008 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyMetaDatabase.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyMetaDatabase.cs new file mode 100644 index 0000000..45dfc00 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyMetaDatabase.cs @@ -0,0 +1,34 @@ +// This class is auto generated + +using System; +using System.Collections.Generic; + +namespace NaughtyAttributes.Editor +{ + public static class PropertyMetaDatabase + { + private static Dictionary metasByAttributeType; + + static PropertyMetaDatabase() + { + metasByAttributeType = new Dictionary(); + metasByAttributeType[typeof(InfoBoxAttribute)] = new InfoBoxPropertyMeta(); +metasByAttributeType[typeof(OnValueChangedAttribute)] = new OnValueChangedPropertyMeta(); + + } + + public static PropertyMeta GetMetaForAttribute(Type attributeType) + { + PropertyMeta meta; + if (metasByAttributeType.TryGetValue(attributeType, out meta)) + { + return meta; + } + else + { + return null; + } + } + } +} + diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyMetaDatabase.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyMetaDatabase.cs.meta new file mode 100644 index 0000000..6a60430 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyMetaDatabase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 57233c5ec1975024aa0723241b2f8210 +timeCreated: 1508497398 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyValidatorDatabase.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyValidatorDatabase.cs new file mode 100644 index 0000000..c74ca91 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyValidatorDatabase.cs @@ -0,0 +1,36 @@ +// This class is auto generated + +using System; +using System.Collections.Generic; + +namespace NaughtyAttributes.Editor +{ + public static class PropertyValidatorDatabase + { + private static Dictionary validatorsByAttributeType; + + static PropertyValidatorDatabase() + { + validatorsByAttributeType = new Dictionary(); + validatorsByAttributeType[typeof(MaxValueAttribute)] = new MaxValuePropertyValidator(); +validatorsByAttributeType[typeof(MinValueAttribute)] = new MinValuePropertyValidator(); +validatorsByAttributeType[typeof(RequiredAttribute)] = new RequiredPropertyValidator(); +validatorsByAttributeType[typeof(ValidateInputAttribute)] = new ValidateInputPropertyValidator(); + + } + + public static PropertyValidator GetValidatorForAttribute(Type attributeType) + { + PropertyValidator validator; + if (validatorsByAttributeType.TryGetValue(attributeType, out validator)) + { + return validator; + } + else + { + return null; + } + } + } +} + diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyValidatorDatabase.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyValidatorDatabase.cs.meta new file mode 100644 index 0000000..6d882da --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/PropertyValidatorDatabase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 24e9da8a6b324374a9f655d3a867b284 +timeCreated: 1508241122 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates.meta new file mode 100644 index 0000000..5d830f1 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 7b15ea6695a69d74ab656006617d8d21 +folderAsset: yes +timeCreated: 1508230862 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/FieldDrawerDatabaseTemplate.txt b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/FieldDrawerDatabaseTemplate.txt new file mode 100644 index 0000000..926a6d7 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/FieldDrawerDatabaseTemplate.txt @@ -0,0 +1,31 @@ +// This class is auto generated + +using System; +using System.Collections.Generic; + +namespace NaughtyAttributes.Editor +{ + public static class __classname__ + { + private static Dictionary drawersByAttributeType; + + static __classname__() + { + drawersByAttributeType = new Dictionary(); + __entries__ + } + + public static FieldDrawer GetDrawerForAttribute(Type attributeType) + { + FieldDrawer drawer; + if (drawersByAttributeType.TryGetValue(attributeType, out drawer)) + { + return drawer; + } + else + { + return null; + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/FieldDrawerDatabaseTemplate.txt.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/FieldDrawerDatabaseTemplate.txt.meta new file mode 100644 index 0000000..43e8f76 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/FieldDrawerDatabaseTemplate.txt.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 943b4c41373856243996247275be2cd8 +timeCreated: 1508836344 +licenseType: Free +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/MethodDrawerDatabaseTemplate.txt b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/MethodDrawerDatabaseTemplate.txt new file mode 100644 index 0000000..d6efd8a --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/MethodDrawerDatabaseTemplate.txt @@ -0,0 +1,31 @@ +// This class is auto generated + +using System; +using System.Collections.Generic; + +namespace NaughtyAttributes.Editor +{ + public static class __classname__ + { + private static Dictionary drawersByAttributeType; + + static __classname__() + { + drawersByAttributeType = new Dictionary(); + __entries__ + } + + public static MethodDrawer GetDrawerForAttribute(Type attributeType) + { + MethodDrawer drawer; + if (drawersByAttributeType.TryGetValue(attributeType, out drawer)) + { + return drawer; + } + else + { + return null; + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/MethodDrawerDatabaseTemplate.txt.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/MethodDrawerDatabaseTemplate.txt.meta new file mode 100644 index 0000000..4531345 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/MethodDrawerDatabaseTemplate.txt.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 52d15465eb3439f4a9b95963a21d19b7 +timeCreated: 1508592495 +licenseType: Free +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/NativePropertyDrawerDbTemplate.txt b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/NativePropertyDrawerDbTemplate.txt new file mode 100644 index 0000000..fe9cca1 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/NativePropertyDrawerDbTemplate.txt @@ -0,0 +1,31 @@ +// This class is auto generated + +using System; +using System.Collections.Generic; + +namespace NaughtyAttributes.Editor +{ + public static class __classname__ + { + private static Dictionary drawersByAttributeType; + + static __classname__() + { + drawersByAttributeType = new Dictionary(); + __entries__ + } + + public static NativePropertyDrawer GetDrawerForAttribute(Type attributeType) + { + NativePropertyDrawer drawer; + if (drawersByAttributeType.TryGetValue(attributeType, out drawer)) + { + return drawer; + } + else + { + return null; + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/NativePropertyDrawerDbTemplate.txt.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/NativePropertyDrawerDbTemplate.txt.meta new file mode 100644 index 0000000..4c16e8c --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/NativePropertyDrawerDbTemplate.txt.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b82f5f6bf1fd4314c93624a8bc8835fd +timeCreated: 1510924467 +licenseType: Free +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyDrawConditionDatabaseTemplate.txt b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyDrawConditionDatabaseTemplate.txt new file mode 100644 index 0000000..adc064a --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyDrawConditionDatabaseTemplate.txt @@ -0,0 +1,31 @@ +// This class is auto generated + +using System; +using System.Collections.Generic; + +namespace NaughtyAttributes.Editor +{ + public static class __classname__ + { + private static Dictionary drawConditionsByAttributeType; + + static __classname__() + { + drawConditionsByAttributeType = new Dictionary(); + __entries__ + } + + public static PropertyDrawCondition GetDrawConditionForAttribute(Type attributeType) + { + PropertyDrawCondition drawCondition; + if (drawConditionsByAttributeType.TryGetValue(attributeType, out drawCondition)) + { + return drawCondition; + } + else + { + return null; + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyDrawConditionDatabaseTemplate.txt.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyDrawConditionDatabaseTemplate.txt.meta new file mode 100644 index 0000000..1d19d37 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyDrawConditionDatabaseTemplate.txt.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b36f5858330c2d140a697f19ba6cc36b +timeCreated: 1508414568 +licenseType: Free +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyDrawerDatabaseTemplate.txt b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyDrawerDatabaseTemplate.txt new file mode 100644 index 0000000..338dde4 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyDrawerDatabaseTemplate.txt @@ -0,0 +1,39 @@ +// This class is auto generated + +using System; +using System.Collections.Generic; + +namespace NaughtyAttributes.Editor +{ + public static class __classname__ + { + private static Dictionary drawersByAttributeType; + + static __classname__() + { + drawersByAttributeType = new Dictionary(); + __entries__ + } + + public static PropertyDrawer GetDrawerForAttribute(Type attributeType) + { + PropertyDrawer drawer; + if (drawersByAttributeType.TryGetValue(attributeType, out drawer)) + { + return drawer; + } + else + { + return null; + } + } + + public static void ClearCache() + { + foreach (var kvp in drawersByAttributeType) + { + kvp.Value.ClearCache(); + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyDrawerDatabaseTemplate.txt.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyDrawerDatabaseTemplate.txt.meta new file mode 100644 index 0000000..26014c9 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyDrawerDatabaseTemplate.txt.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 136a96a904b577244b08be5d5542a77d +timeCreated: 1508241102 +licenseType: Free +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyGrouperDatabaseTemplate.txt b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyGrouperDatabaseTemplate.txt new file mode 100644 index 0000000..5065a45 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyGrouperDatabaseTemplate.txt @@ -0,0 +1,31 @@ +// This class is auto generated + +using System; +using System.Collections.Generic; + +namespace NaughtyAttributes.Editor +{ + public static class __classname__ + { + private static Dictionary groupersByAttributeType; + + static __classname__() + { + groupersByAttributeType = new Dictionary(); + __entries__ + } + + public static PropertyGrouper GetGrouperForAttribute(Type attributeType) + { + PropertyGrouper grouper; + if (groupersByAttributeType.TryGetValue(attributeType, out grouper)) + { + return grouper; + } + else + { + return null; + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyGrouperDatabaseTemplate.txt.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyGrouperDatabaseTemplate.txt.meta new file mode 100644 index 0000000..1167151 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyGrouperDatabaseTemplate.txt.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 7fcc5bff99ecd4843b766f23cd585b55 +timeCreated: 1508332899 +licenseType: Free +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyMetaDatabaseTemplate.txt b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyMetaDatabaseTemplate.txt new file mode 100644 index 0000000..d88bea4 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyMetaDatabaseTemplate.txt @@ -0,0 +1,31 @@ +// This class is auto generated + +using System; +using System.Collections.Generic; + +namespace NaughtyAttributes.Editor +{ + public static class __classname__ + { + private static Dictionary metasByAttributeType; + + static __classname__() + { + metasByAttributeType = new Dictionary(); + __entries__ + } + + public static PropertyMeta GetMetaForAttribute(Type attributeType) + { + PropertyMeta meta; + if (metasByAttributeType.TryGetValue(attributeType, out meta)) + { + return meta; + } + else + { + return null; + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyMetaDatabaseTemplate.txt.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyMetaDatabaseTemplate.txt.meta new file mode 100644 index 0000000..849d247 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyMetaDatabaseTemplate.txt.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: fde25cf95f45b50469fcf4ee1e38993c +timeCreated: 1508497401 +licenseType: Free +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyValidatorDatabaseTemplate.txt b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyValidatorDatabaseTemplate.txt new file mode 100644 index 0000000..2a63494 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyValidatorDatabaseTemplate.txt @@ -0,0 +1,31 @@ +// This class is auto generated + +using System; +using System.Collections.Generic; + +namespace NaughtyAttributes.Editor +{ + public static class __classname__ + { + private static Dictionary validatorsByAttributeType; + + static __classname__() + { + validatorsByAttributeType = new Dictionary(); + __entries__ + } + + public static PropertyValidator GetValidatorForAttribute(Type attributeType) + { + PropertyValidator validator; + if (validatorsByAttributeType.TryGetValue(attributeType, out validator)) + { + return validator; + } + else + { + return null; + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyValidatorDatabaseTemplate.txt.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyValidatorDatabaseTemplate.txt.meta new file mode 100644 index 0000000..c0c96d4 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/CodeGeneration/Templates/PropertyValidatorDatabaseTemplate.txt.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a21c3d37c1492da4386198388150024c +timeCreated: 1508230862 +licenseType: Free +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Editors.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Editors.meta new file mode 100644 index 0000000..2c445db --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Editors.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 4db73d2276d0e8144a206c5c2cd350de +folderAsset: yes +timeCreated: 1508055750 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Editors/InspectorEditor.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Editors/InspectorEditor.cs new file mode 100644 index 0000000..3e3d542 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Editors/InspectorEditor.cs @@ -0,0 +1,367 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEditor; +using UnityEngine; + +namespace NaughtyAttributes.Editor +{ + [CanEditMultipleObjects] + [CustomEditor(typeof(UnityEngine.Object), true)] + public class InspectorEditor : UnityEditor.Editor + { + private SerializedProperty script; + + private List fields; + private readonly HashSet groupedFields; + private readonly Dictionary> groupedFieldsByGroupName; + private List nonSerializedFields; + private List nativeProperties; + private List methods; + + private readonly Dictionary serializedPropertiesByFieldName; + + private bool useDefaultInspector; + + bool FilterFields(FieldInfo f) => this.serializedObject.FindProperty(f.Name) != null; + readonly Func filterFieldsDelegate; + + // Cache non-serialized fields + bool NonSerializedFieldsFilter(FieldInfo f) + { + return f.GetCustomAttribute(true) != null && this.serializedObject.FindProperty(f.Name) == null; + } + + + public InspectorEditor() + { + groupedFieldsByGroupName = new Dictionary>(); + serializedPropertiesByFieldName = new Dictionary(); + groupedFields = new HashSet(); + fields = new List(100); + nonSerializedFields = new List(100); + nativeProperties = new List(100); + methods = new List(100); + filterFieldsDelegate = FilterFields; + } + + private void OnEnable() + { + try + { + this.script = this.serializedObject.FindProperty("m_Script"); + } + catch + { + // ignore. Unity Bug causes NPE deep inside the unity classes. + this.useDefaultInspector = true; + return; + } + + // Cache serialized fields + this.fields = ReflectionUtility.GetAllFieldsEfficiently(this.target, filterFieldsDelegate, this.fields); + // Cache serialized properties by field name + this.serializedPropertiesByFieldName.Clear(); + foreach (var field in this.fields) + { + this.serializedPropertiesByFieldName[field.Name] = this.serializedObject.FindProperty(field.Name); + } + + // If there are no NaughtyAttributes use default inspector + if (this.fields.All(f => f.GetCustomAttribute(true) == null)) + { + this.useDefaultInspector = true; + } + else + { + this.useDefaultInspector = false; + + // Cache grouped fields + this.groupedFields.Clear(); + foreach (var fi in fields) + { + if (fi.GetCustomAttribute(true) != null) + { + this.groupedFields.Add(fi); + } + } + + // Cache grouped fields by group name + groupedFieldsByGroupName.Clear(); + foreach (var groupedField in this.groupedFields) + { + string groupName = (groupedField.GetCustomAttribute(true)).Name; + + if (this.groupedFieldsByGroupName.TryGetValue(groupName, out var list)) + { + list.Add(groupedField); + } + else + { + this.groupedFieldsByGroupName[groupName] = new List() + { + groupedField + }; + } + } + + } + + this.nonSerializedFields = ReflectionUtility.GetAllFieldsEfficiently(this.target, NonSerializedFieldsFilter, nonSerializedFields); + + // Cache the native properties + this.nativeProperties = ReflectionUtility.GetAllPropertiesEfficiently( + this.target, p => p.GetCustomAttribute(true) != null, nativeProperties); + + // Cache methods with DrawerAttribute + this.methods = ReflectionUtility.GetAllMethodsEfficiently( + this.target, m => m.GetCustomAttribute(true) != null, methods); + } + + private void OnDisable() + { + PropertyDrawerDatabase.ClearCache(); + } + + public override bool RequiresConstantRepaint() + { + return useDefaultInspector == false; + } + + public override void OnInspectorGUI() + { + if (this.useDefaultInspector) + { + this.DrawDefaultInspector(); + } + else + { + this.serializedObject.Update(); + + if (this.script != null) + { + GUI.enabled = false; + EditorGUILayout.PropertyField(this.script); + GUI.enabled = true; + } + + // Draw fields + HashSet drawnGroups = new HashSet(); + foreach (var field in this.fields) + { + if (this.groupedFields.Contains(field)) + { + // Draw grouped fields + string groupName = (field.GetCustomAttributes(typeof(GroupAttribute), true)[0] as GroupAttribute).Name; + if (!drawnGroups.Contains(groupName)) + { + drawnGroups.Add(groupName); + + PropertyGrouper grouper = this.GetPropertyGrouperForField(field); + if (grouper != null) + { + grouper.BeginGroup(groupName); + + this.ValidateAndDrawFields(this.groupedFieldsByGroupName[groupName]); + + grouper.EndGroup(); + } + else + { + this.ValidateAndDrawFields(this.groupedFieldsByGroupName[groupName]); + } + } + } + else + { + // Draw non-grouped field + this.ValidateAndDrawField(field); + } + } + + this.serializedObject.ApplyModifiedProperties(); + } + + // Draw non-serialized fields + foreach (var field in this.nonSerializedFields) + { + DrawerAttribute drawerAttribute = (DrawerAttribute)field.GetCustomAttributes(typeof(DrawerAttribute), true)[0]; + FieldDrawer drawer = FieldDrawerDatabase.GetDrawerForAttribute(drawerAttribute.GetType()); + if (drawer != null) + { + drawer.DrawField(this.target, field); + } + } + + // Draw native properties + foreach (var property in this.nativeProperties) + { + DrawerAttribute drawerAttribute = (DrawerAttribute)property.GetCustomAttributes(typeof(DrawerAttribute), true)[0]; + NativePropertyDrawer drawer = NativePropertyDrawerDatabase.GetDrawerForAttribute(drawerAttribute.GetType()); + if (drawer != null) + { + drawer.DrawNativeProperty(this.target, property); + } + } + + // Draw methods + foreach (var method in this.methods) + { + DrawerAttribute drawerAttribute = (DrawerAttribute)method.GetCustomAttributes(typeof(DrawerAttribute), true)[0]; + MethodDrawer methodDrawer = MethodDrawerDatabase.GetDrawerForAttribute(drawerAttribute.GetType()); + if (methodDrawer != null) + { + + if (methodDrawer.DrawMethod(this.target, method)) + { + this.serializedObject.ApplyModifiedProperties(); + this.serializedObject.Update(); + PropertyDrawerDatabase.ClearCache(); + } + } + } + } + + private void ValidateAndDrawFields(IEnumerable fields) + { + foreach (var field in fields) + { + this.ValidateAndDrawField(field); + } + } + + private void ValidateAndDrawField(FieldInfo field) + { + this.ValidateField(field); + this.ApplyFieldMeta(field); + this.DrawField(field); + } + + private void ValidateField(FieldInfo field) + { + ValidatorAttribute[] validatorAttributes = (ValidatorAttribute[])field.GetCustomAttributes(typeof(ValidatorAttribute), true); + + foreach (var attribute in validatorAttributes) + { + PropertyValidator validator = PropertyValidatorDatabase.GetValidatorForAttribute(attribute.GetType()); + if (validator != null) + { + validator.ValidateProperty(this.serializedPropertiesByFieldName[field.Name]); + } + } + } + + private void DrawField(FieldInfo field) + { + // Check if the field has draw conditions + PropertyDrawCondition drawCondition = this.GetPropertyDrawConditionForField(field); + if (drawCondition != null) + { + bool canDrawProperty = drawCondition.CanDrawProperty(this.serializedPropertiesByFieldName[field.Name]); + if (!canDrawProperty) + { + return; + } + } + + // Check if the field has HideInInspectorAttribute + HideInInspector[] hideInInspectorAttributes = (HideInInspector[])field.GetCustomAttributes(typeof(HideInInspector), true); + if (hideInInspectorAttributes.Length > 0) + { + return; + } + + // Draw the field + EditorGUI.BeginChangeCheck(); + PropertyDrawer drawer = this.GetPropertyDrawerForField(field); + if (drawer != null) + { + drawer.DrawProperty(field, this.serializedPropertiesByFieldName[field.Name]); + } + else + { + EditorDrawUtility.DrawPropertyField(this.serializedPropertiesByFieldName[field.Name]); + } + + if (EditorGUI.EndChangeCheck()) + { + OnValueChangedAttribute[] onValueChangedAttributes = (OnValueChangedAttribute[])field.GetCustomAttributes(typeof(OnValueChangedAttribute), true); + foreach (var onValueChangedAttribute in onValueChangedAttributes) + { + PropertyMeta meta = PropertyMetaDatabase.GetMetaForAttribute(onValueChangedAttribute.GetType()); + if (meta != null) + { + meta.ApplyPropertyMeta(this.serializedPropertiesByFieldName[field.Name], onValueChangedAttribute); + } + } + } + } + + private void ApplyFieldMeta(FieldInfo field) + { + // Apply custom meta attributes + MetaAttribute[] metaAttributes = field + .GetCustomAttributes(typeof(MetaAttribute), true) + .Where(attr => attr.GetType() != typeof(OnValueChangedAttribute)) + .Select(obj => obj as MetaAttribute) + .ToArray(); + + Array.Sort(metaAttributes, (x, y) => + { + return x.Order - y.Order; + }); + + foreach (var metaAttribute in metaAttributes) + { + PropertyMeta meta = PropertyMetaDatabase.GetMetaForAttribute(metaAttribute.GetType()); + if (meta != null) + { + meta.ApplyPropertyMeta(this.serializedPropertiesByFieldName[field.Name], metaAttribute); + } + } + } + + private PropertyDrawer GetPropertyDrawerForField(FieldInfo field) + { + DrawerAttribute[] drawerAttributes = (DrawerAttribute[])field.GetCustomAttributes(typeof(DrawerAttribute), true); + if (drawerAttributes.Length > 0) + { + PropertyDrawer drawer = PropertyDrawerDatabase.GetDrawerForAttribute(drawerAttributes[0].GetType()); + return drawer; + } + else + { + return null; + } + } + + private PropertyGrouper GetPropertyGrouperForField(FieldInfo field) + { + GroupAttribute[] groupAttributes = (GroupAttribute[])field.GetCustomAttributes(typeof(GroupAttribute), true); + if (groupAttributes.Length > 0) + { + PropertyGrouper grouper = PropertyGrouperDatabase.GetGrouperForAttribute(groupAttributes[0].GetType()); + return grouper; + } + else + { + return null; + } + } + + private PropertyDrawCondition GetPropertyDrawConditionForField(FieldInfo field) + { + DrawConditionAttribute[] drawConditionAttributes = (DrawConditionAttribute[])field.GetCustomAttributes(typeof(DrawConditionAttribute), true); + if (drawConditionAttributes.Length > 0) + { + PropertyDrawCondition drawCondition = PropertyDrawConditionDatabase.GetDrawConditionForAttribute(drawConditionAttributes[0].GetType()); + return drawCondition; + } + else + { + return null; + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Editors/InspectorEditor.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Editors/InspectorEditor.cs.meta new file mode 100644 index 0000000..b623552 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Editors/InspectorEditor.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 9e82d6d6926a6c74688e2787b37630d1 +timeCreated: 1508055750 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/FieldDrawers.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/FieldDrawers.meta new file mode 100644 index 0000000..ed81436 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/FieldDrawers.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 79b05858e72c1b0498eca7954843c802 +folderAsset: yes +timeCreated: 1508835721 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/FieldDrawers/FieldDrawer.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/FieldDrawers/FieldDrawer.cs new file mode 100644 index 0000000..805a064 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/FieldDrawers/FieldDrawer.cs @@ -0,0 +1,9 @@ +using System.Reflection; + +namespace NaughtyAttributes.Editor +{ + public abstract class FieldDrawer + { + public abstract void DrawField(UnityEngine.Object target, FieldInfo field); + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/FieldDrawers/FieldDrawer.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/FieldDrawers/FieldDrawer.cs.meta new file mode 100644 index 0000000..789d479 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/FieldDrawers/FieldDrawer.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 8949267118f232a4fbebd777de8ed6fe +timeCreated: 1508835721 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/FieldDrawers/ShowNonSerializedFieldFieldDrawer.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/FieldDrawers/ShowNonSerializedFieldFieldDrawer.cs new file mode 100644 index 0000000..0c6e5be --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/FieldDrawers/ShowNonSerializedFieldFieldDrawer.cs @@ -0,0 +1,20 @@ +using System.Reflection; +using UnityEditor; + +namespace NaughtyAttributes.Editor +{ + [FieldDrawer(typeof(ShowNonSerializedFieldAttribute))] + public class ShowNonSerializedFieldFieldDrawer : FieldDrawer + { + public override void DrawField(UnityEngine.Object target, FieldInfo field) + { + object value = field.GetValue(target); + + if (!EditorDrawUtility.DrawLayoutField(value, ObjectNames.NicifyVariableName(field.Name), field.FieldType)) + { + string warning = string.Format("{0} doesn't support {1} types", typeof(ShowNonSerializedFieldFieldDrawer).Name, field.FieldType.Name); + EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: target); + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/FieldDrawers/ShowNonSerializedFieldFieldDrawer.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/FieldDrawers/ShowNonSerializedFieldFieldDrawer.cs.meta new file mode 100644 index 0000000..fa3410c --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/FieldDrawers/ShowNonSerializedFieldFieldDrawer.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 8449d5c2158e97d479caaec24c61baec +timeCreated: 1508835721 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/MethodDrawers.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/MethodDrawers.meta new file mode 100644 index 0000000..7e351e2 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/MethodDrawers.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: f95312994b1f8c746a402669cb1655eb +folderAsset: yes +timeCreated: 1508592494 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/MethodDrawers/ButtonMethodDrawer.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/MethodDrawers/ButtonMethodDrawer.cs new file mode 100644 index 0000000..9cafd9e --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/MethodDrawers/ButtonMethodDrawer.cs @@ -0,0 +1,62 @@ +using System.Reflection; +using UnityEditor; +using UnityEngine; + +namespace NaughtyAttributes.Editor +{ + [MethodDrawer(typeof(ButtonAttribute))] + public class ButtonMethodDrawer : MethodDrawer + { + public override bool DrawMethod(UnityEngine.Object target, MethodInfo methodInfo) + { + if (methodInfo.GetParameters().Length == 0) + { + ButtonAttribute buttonAttribute = (ButtonAttribute) methodInfo.GetCustomAttributes(typeof(ButtonAttribute), true)[0]; + string buttonText = string.IsNullOrEmpty(buttonAttribute.Text) ? methodInfo.Name : buttonAttribute.Text; + + if (GUILayout.Button(buttonText)) + { + EditorGUI.BeginChangeCheck(); + + var gameObjects = Selection.gameObjects; + if (gameObjects.Length <= 1 || buttonAttribute.Target == ButtonAttribute.ButtonInvocationTarget.Default) + { + methodInfo.Invoke(target, null); + } + else if (target is Component) + { + var targetType = target.GetType(); + if (buttonAttribute.Target == ButtonAttribute.ButtonInvocationTarget.First) + { + var gameObject = Selection.gameObjects[0]; + var targetComponent = gameObject.GetComponent(targetType); + methodInfo.Invoke(targetComponent, null); + } + else if (buttonAttribute.Target == ButtonAttribute.ButtonInvocationTarget.All) + { + foreach (var gameObject in Selection.gameObjects) + { + var targetComponent = gameObject.GetComponent(targetType); + methodInfo.Invoke(targetComponent, null); + } + } + } + + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObject(target, "Method Invocation: " + buttonText); + } + + return true; + } + } + else + { + string warning = typeof(ButtonAttribute).Name + " works only on methods with no parameters"; + EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: target); + } + + return false; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/MethodDrawers/ButtonMethodDrawer.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/MethodDrawers/ButtonMethodDrawer.cs.meta new file mode 100644 index 0000000..cff17a7 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/MethodDrawers/ButtonMethodDrawer.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: ad01ec1a22422c6409f913d60ce39d61 +timeCreated: 1508592494 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/MethodDrawers/MethodDrawer.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/MethodDrawers/MethodDrawer.cs new file mode 100644 index 0000000..8ff646f --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/MethodDrawers/MethodDrawer.cs @@ -0,0 +1,9 @@ +using System.Reflection; + +namespace NaughtyAttributes.Editor +{ + public abstract class MethodDrawer + { + public abstract bool DrawMethod(UnityEngine.Object target, MethodInfo methodInfo); + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/MethodDrawers/MethodDrawer.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/MethodDrawers/MethodDrawer.cs.meta new file mode 100644 index 0000000..22137e5 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/MethodDrawers/MethodDrawer.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: a65a1addcdd323249b590f7a06110869 +timeCreated: 1508592494 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NativePropertyDrawers.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NativePropertyDrawers.meta new file mode 100644 index 0000000..665bbfc --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NativePropertyDrawers.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: ae67cc6bfa799f147968e9b0371a21fc +folderAsset: yes +timeCreated: 1510924467 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NativePropertyDrawers/NativePropertyDrawer.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NativePropertyDrawers/NativePropertyDrawer.cs new file mode 100644 index 0000000..0fb0e6b --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NativePropertyDrawers/NativePropertyDrawer.cs @@ -0,0 +1,9 @@ +using System.Reflection; + +namespace NaughtyAttributes.Editor +{ + public abstract class NativePropertyDrawer + { + public abstract void DrawNativeProperty(UnityEngine.Object target, PropertyInfo property); + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NativePropertyDrawers/NativePropertyDrawer.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NativePropertyDrawers/NativePropertyDrawer.cs.meta new file mode 100644 index 0000000..897323c --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NativePropertyDrawers/NativePropertyDrawer.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 715c5ada29663a245b0b35937c892377 +timeCreated: 1510924467 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NativePropertyDrawers/ShowNativePropertyNativePropertyDrawer.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NativePropertyDrawers/ShowNativePropertyNativePropertyDrawer.cs new file mode 100644 index 0000000..f5c2943 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NativePropertyDrawers/ShowNativePropertyNativePropertyDrawer.cs @@ -0,0 +1,32 @@ +using System; +using System.Reflection; +using UnityEditor; + +namespace NaughtyAttributes.Editor +{ + [NativePropertyDrawer(typeof(ShowNativePropertyAttribute))] + public class ShowNativePropertyNativePropertyDrawer : NativePropertyDrawer + { + public override void DrawNativeProperty(UnityEngine.Object target, PropertyInfo property) + { + try + { + + object value = property.GetValue(target, null); + + if (!EditorDrawUtility.DrawLayoutField(value, ObjectNames.NicifyVariableName(property.Name), + property.PropertyType)) + { + string warning = string.Format("{0} doesn't support {1} types", + typeof(ShowNativePropertyNativePropertyDrawer).Name, + property.PropertyType.Name); + EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: target); + } + } + catch(Exception e) + { + EditorDrawUtility.DrawHelpBox("Error: " + e, MessageType.Error, logToConsole: true, context: target); + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NativePropertyDrawers/ShowNativePropertyNativePropertyDrawer.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NativePropertyDrawers/ShowNativePropertyNativePropertyDrawer.cs.meta new file mode 100644 index 0000000..9b1f424 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NativePropertyDrawers/ShowNativePropertyNativePropertyDrawer.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 518b0fde2a9d15d498bc17fd1d7062c7 +timeCreated: 1510926376 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NaughtyAttributes.Editor.asmdef b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NaughtyAttributes.Editor.asmdef new file mode 100644 index 0000000..44eaead --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NaughtyAttributes.Editor.asmdef @@ -0,0 +1,12 @@ +{ + "name": "NaughtyAttributes.Editor", + "references": [ + "NaughtyAttributes" + ], + "optionalUnityReferences": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false +} \ No newline at end of file diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NaughtyAttributes.Editor.asmdef.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NaughtyAttributes.Editor.asmdef.meta new file mode 100644 index 0000000..f53287c --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/NaughtyAttributes.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7f264d010c5f90a46beaf273bbb85ac2 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions.meta new file mode 100644 index 0000000..6742dcd --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 0ed2b7d432f0ad644b1f0752cf65aa9c +folderAsset: yes +timeCreated: 1508414568 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions/HideIfPropertyDrawCondition.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions/HideIfPropertyDrawCondition.cs new file mode 100644 index 0000000..04c359e --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions/HideIfPropertyDrawCondition.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using UnityEditor; + +namespace NaughtyAttributes.Editor +{ + [PropertyDrawCondition(typeof(HideIfAttribute))] + public class HideIfPropertyDrawCondition : PropertyDrawCondition + { + public override bool CanDrawProperty(SerializedProperty property) + { + HideIfAttribute hideIfAttribute = PropertyUtility.GetAttribute(property); + UnityEngine.Object target = PropertyUtility.GetTargetObject(property); + + FieldInfo conditionField = ReflectionUtility.GetField(target, hideIfAttribute.ConditionName); + if (conditionField != null && + conditionField.FieldType == typeof(bool)) + { + return !(bool)conditionField.GetValue(target); + } + + MethodInfo conditionMethod = ReflectionUtility.GetMethod(target, hideIfAttribute.ConditionName); + if (conditionMethod != null && + conditionMethod.ReturnType == typeof(bool) && + conditionMethod.GetParameters().Length == 0) + { + return !(bool)conditionMethod.Invoke(target, null); + } + + string warning = hideIfAttribute.GetType().Name + " needs a valid boolean condition field or method name to work"; + EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: target); + + return true; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions/HideIfPropertyDrawCondition.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions/HideIfPropertyDrawCondition.cs.meta new file mode 100644 index 0000000..2b7cd1d --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions/HideIfPropertyDrawCondition.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: f7e60d80f0231654ab13cfb1178e6eb8 +timeCreated: 1508414568 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions/PropertyDrawCondition.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions/PropertyDrawCondition.cs new file mode 100644 index 0000000..2ea9f7a --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions/PropertyDrawCondition.cs @@ -0,0 +1,9 @@ +using UnityEditor; + +namespace NaughtyAttributes.Editor +{ + public abstract class PropertyDrawCondition + { + public abstract bool CanDrawProperty(SerializedProperty property); + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions/PropertyDrawCondition.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions/PropertyDrawCondition.cs.meta new file mode 100644 index 0000000..f326b5d --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions/PropertyDrawCondition.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: ce2d1d9afa04cae43a18bd01ec9447eb +timeCreated: 1508414568 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions/ShowIfPropertyDrawCondition.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions/ShowIfPropertyDrawCondition.cs new file mode 100644 index 0000000..503ecfc --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions/ShowIfPropertyDrawCondition.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using UnityEditor; + +namespace NaughtyAttributes.Editor +{ + [PropertyDrawCondition(typeof(ShowIfAttribute))] + public class ShowIfPropertyDrawCondition : PropertyDrawCondition + { + public override bool CanDrawProperty(SerializedProperty property) + { + ShowIfAttribute showIfAttribute = PropertyUtility.GetAttribute(property); + UnityEngine.Object target = PropertyUtility.GetTargetObject(property); + + FieldInfo conditionField = ReflectionUtility.GetField(target, showIfAttribute.ConditionName); + if (conditionField != null && + conditionField.FieldType == typeof(bool)) + { + return (bool)conditionField.GetValue(target); + } + + MethodInfo conditionMethod = ReflectionUtility.GetMethod(target, showIfAttribute.ConditionName); + if (conditionMethod != null && + conditionMethod.ReturnType == typeof(bool) && + conditionMethod.GetParameters().Length == 0) + { + return (bool)conditionMethod.Invoke(target, null); + } + + string warning = showIfAttribute.GetType().Name + " needs a valid boolean condition field or method name to work"; + EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: target); + + return true; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions/ShowIfPropertyDrawCondition.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions/ShowIfPropertyDrawCondition.cs.meta new file mode 100644 index 0000000..2e7a555 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawConditions/ShowIfPropertyDrawCondition.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: fce0c8241476ad94cbbcdd6faae90700 +timeCreated: 1508414568 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers.meta new file mode 100644 index 0000000..7f3a245 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 4327d74fca5deaa4c83c483fe468d274 +folderAsset: yes +timeCreated: 1508051576 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/DisableIfPropertyDrawer.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/DisableIfPropertyDrawer.cs new file mode 100644 index 0000000..86e5bb9 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/DisableIfPropertyDrawer.cs @@ -0,0 +1,48 @@ +using System.Reflection; +using UnityEditor; +using UnityEngine; + +namespace NaughtyAttributes.Editor +{ + [PropertyDrawer(typeof(DisableIfAttribute))] + public class DisableIfPropertyDrawer : PropertyDrawer + { + public override void DrawProperty(SerializedProperty property) + { + bool drawDisabled = false; + bool validCondition = false; + + DisableIfAttribute disableIfAttribute = PropertyUtility.GetAttribute(property); + UnityEngine.Object target = PropertyUtility.GetTargetObject(property); + + FieldInfo conditionField = ReflectionUtility.GetField(target, disableIfAttribute.ConditionName); + if (conditionField != null && + conditionField.FieldType == typeof(bool)) + { + drawDisabled = (bool)conditionField.GetValue(target); + validCondition = true; + } + + MethodInfo conditionMethod = ReflectionUtility.GetMethod(target, disableIfAttribute.ConditionName); + if (conditionMethod != null && + conditionMethod.ReturnType == typeof(bool) && + conditionMethod.GetParameters().Length == 0) + { + drawDisabled = (bool)conditionMethod.Invoke(target, null); + validCondition = true; + } + + if (validCondition) + { + GUI.enabled = !drawDisabled; + EditorDrawUtility.DrawPropertyField(property); + GUI.enabled = true; + } + else + { + string warning = disableIfAttribute.GetType().Name + " needs a valid boolean condition field or method name to work"; + EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: target); + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/DisableIfPropertyDrawer.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/DisableIfPropertyDrawer.cs.meta new file mode 100644 index 0000000..579b0a4 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/DisableIfPropertyDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6093965e939dcd24687aed40741be04b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/DropdownPropertyDrawer.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/DropdownPropertyDrawer.cs new file mode 100644 index 0000000..f7ac834 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/DropdownPropertyDrawer.cs @@ -0,0 +1,130 @@ +using UnityEngine; +using UnityEditor; +using System.Reflection; +using System.Collections; +using System; +using System.Collections.Generic; + +namespace NaughtyAttributes.Editor +{ + [PropertyDrawer(typeof(DropdownAttribute))] + public class DropdownPropertyDrawer : PropertyDrawer + { + public override void DrawProperty(SerializedProperty property) + { + EditorDrawUtility.DrawHeader(property); + + DropdownAttribute dropdownAttribute = PropertyUtility.GetAttribute(property); + UnityEngine.Object target = PropertyUtility.GetTargetObject(property); + + FieldInfo fieldInfo = ReflectionUtility.GetField(target, property.name); + FieldInfo valuesFieldInfo = ReflectionUtility.GetField(target, dropdownAttribute.ValuesFieldName); + + if (valuesFieldInfo == null) + { + this.DrawWarningBox(string.Format("{0} cannot find a values field with name \"{1}\"", dropdownAttribute.GetType().Name, dropdownAttribute.ValuesFieldName)); + EditorGUILayout.PropertyField(property, true); + } + else if (valuesFieldInfo.GetValue(target) is IList && + fieldInfo.FieldType == this.GetElementType(valuesFieldInfo)) + { + // Selected value + object selectedValue = fieldInfo.GetValue(target); + + // Values and display options + IList valuesList = (IList)valuesFieldInfo.GetValue(target); + object[] values = new object[valuesList.Count]; + string[] displayOptions = new string[valuesList.Count]; + + for (int i = 0; i < values.Length; i++) + { + object value = valuesList[i]; + values[i] = value; + displayOptions[i] = value.ToString(); + } + + // Selected value index + int selectedValueIndex = Array.IndexOf(values, selectedValue); + if (selectedValueIndex < 0) + { + selectedValueIndex = 0; + } + + // Draw the dropdown + this.DrawDropdown(target, fieldInfo, property.displayName, selectedValueIndex, values, displayOptions); + } + else if (valuesFieldInfo.GetValue(target) is IDropdownList) + { + // Current value + object selectedValue = fieldInfo.GetValue(target); + + // Current value index, values and display options + IDropdownList dropdown = (IDropdownList)valuesFieldInfo.GetValue(target); + IEnumerator> dropdownEnumerator = dropdown.GetEnumerator(); + + int index = -1; + int selectedValueIndex = -1; + List values = new List(); + List displayOptions = new List(); + + while (dropdownEnumerator.MoveNext()) + { + index++; + + KeyValuePair current = dropdownEnumerator.Current; + if (current.Value.Equals(selectedValue)) + { + selectedValueIndex = index; + } + + values.Add(current.Value); + displayOptions.Add(current.Key); + } + + if (selectedValueIndex < 0) + { + selectedValueIndex = 0; + } + + // Draw the dropdown + this.DrawDropdown(target, fieldInfo, property.displayName, selectedValueIndex, values.ToArray(), displayOptions.ToArray()); + } + else + { + this.DrawWarningBox(typeof(DropdownAttribute).Name + " works only when the type of the field is equal to the element type of the array"); + EditorGUILayout.PropertyField(property, true); + } + } + + private Type GetElementType(FieldInfo listFieldInfo) + { + if (listFieldInfo.FieldType.IsGenericType) + { + return listFieldInfo.FieldType.GetGenericArguments()[0]; + } + else + { + return listFieldInfo.FieldType.GetElementType(); + } + } + + private void DrawDropdown(UnityEngine.Object target, FieldInfo fieldInfo, string label, int selectedValueIndex, object[] values, string[] displayOptions) + { + EditorGUI.BeginChangeCheck(); + + int newIndex = EditorGUILayout.Popup(label, selectedValueIndex, displayOptions); + + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObject(target, "Dropdown"); + fieldInfo.SetValue(target, values[newIndex]); + } + } + + private void DrawWarningBox(string message) + { + EditorGUILayout.HelpBox(message, MessageType.Warning); + Debug.LogWarning(message); + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/DropdownPropertyDrawer.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/DropdownPropertyDrawer.cs.meta new file mode 100644 index 0000000..eb68163 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/DropdownPropertyDrawer.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 19d935f1205a5804c80c51c3ad95a271 +timeCreated: 1508753698 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/EnableIfPropertyDrawer.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/EnableIfPropertyDrawer.cs new file mode 100644 index 0000000..ece692a --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/EnableIfPropertyDrawer.cs @@ -0,0 +1,48 @@ +using System.Reflection; +using UnityEditor; +using UnityEngine; + +namespace NaughtyAttributes.Editor +{ + [PropertyDrawer(typeof(EnableIfAttribute))] + public class EnableIfPropertyDrawer : PropertyDrawer + { + public override void DrawProperty(SerializedProperty property) + { + bool drawEnabled = false; + bool validCondition = false; + + EnableIfAttribute enableIfAttribute = PropertyUtility.GetAttribute(property); + UnityEngine.Object target = PropertyUtility.GetTargetObject(property); + + FieldInfo conditionField = ReflectionUtility.GetField(target, enableIfAttribute.ConditionName); + if (conditionField != null && + conditionField.FieldType == typeof(bool)) + { + drawEnabled = (bool)conditionField.GetValue(target); + validCondition = true; + } + + MethodInfo conditionMethod = ReflectionUtility.GetMethod(target, enableIfAttribute.ConditionName); + if (conditionMethod != null && + conditionMethod.ReturnType == typeof(bool) && + conditionMethod.GetParameters().Length == 0) + { + drawEnabled = (bool)conditionMethod.Invoke(target, null); + validCondition = true; + } + + if (validCondition) + { + GUI.enabled = drawEnabled; + EditorDrawUtility.DrawPropertyField(property); + GUI.enabled = true; + } + else + { + string warning = enableIfAttribute.GetType().Name + " needs a valid boolean condition field or method name to work"; + EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: target); + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/EnableIfPropertyDrawer.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/EnableIfPropertyDrawer.cs.meta new file mode 100644 index 0000000..9b1abe6 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/EnableIfPropertyDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 36d4c9f730abf4945814f7e205003836 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/EnumFlagPropertyDrawer.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/EnumFlagPropertyDrawer.cs new file mode 100644 index 0000000..9a1ba4e --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/EnumFlagPropertyDrawer.cs @@ -0,0 +1,20 @@ +using System; +using System.Reflection; +using UnityEditor; +using UnityEngine; + +namespace NaughtyAttributes.Editor +{ + [PropertyDrawer(typeof(EnumFlagAttribute))] + public class EnumFlagPropertyDrawer : PropertyDrawer + { + public override void DrawProperty(FieldInfo fieldInfo, SerializedProperty property) + { + EditorDrawUtility.DrawHeader(property); + Enum targetEnum = (Enum)fieldInfo.GetValue(property.serializedObject.targetObject); + Enum enumNew = EditorGUILayout.EnumFlagsField(property.displayName, targetEnum); + property.intValue = (int)Convert.ChangeType(enumNew, targetEnum.GetType()); + + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/EnumFlagPropertyDrawer.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/EnumFlagPropertyDrawer.cs.meta new file mode 100644 index 0000000..38c1ce6 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/EnumFlagPropertyDrawer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b03fc67a402f4df3a0452ad20765818b +timeCreated: 1555187285 \ No newline at end of file diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/MinMaxSliderPropertyDrawer.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/MinMaxSliderPropertyDrawer.cs new file mode 100644 index 0000000..8a9cbf2 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/MinMaxSliderPropertyDrawer.cs @@ -0,0 +1,93 @@ +using UnityEngine; +using UnityEditor; + +namespace NaughtyAttributes.Editor +{ + [PropertyDrawer(typeof(MinMaxSliderAttribute))] + public class MinMaxSliderPropertyDrawer : PropertyDrawer + { + public override void DrawProperty(SerializedProperty property) + { + EditorDrawUtility.DrawHeader(property); + + MinMaxSliderAttribute minMaxSliderAttribute = PropertyUtility.GetAttribute(property); + + if (property.propertyType == SerializedPropertyType.Vector2 || + property.propertyType == SerializedPropertyType.Vector2Int) + { + Rect controlRect = EditorGUILayout.GetControlRect(); + float labelWidth = EditorGUIUtility.labelWidth; + float floatFieldWidth = EditorGUIUtility.fieldWidth; + float sliderWidth = controlRect.width - labelWidth - 2f * floatFieldWidth; + float sliderPadding = 5f; + + Rect labelRect = new Rect( + controlRect.x, + controlRect.y, + labelWidth, + controlRect.height); + + Rect sliderRect = new Rect( + controlRect.x + labelWidth + floatFieldWidth + sliderPadding, + controlRect.y, + sliderWidth - 2f * sliderPadding, + controlRect.height); + + Rect minFloatFieldRect = new Rect( + controlRect.x + labelWidth, + controlRect.y, + floatFieldWidth, + controlRect.height); + + Rect maxFloatFieldRect = new Rect( + controlRect.x + labelWidth + floatFieldWidth + sliderWidth, + controlRect.y, + floatFieldWidth, + controlRect.height); + + // Draw the label + EditorGUI.LabelField(labelRect, property.displayName); + + // Draw the slider + EditorGUI.BeginChangeCheck(); + + Vector2 sliderValue; + if (property.propertyType == SerializedPropertyType.Vector2) + { + sliderValue = property.vector2Value; + } + else + { + sliderValue = property.vector2IntValue; + } + + EditorGUI.MinMaxSlider(sliderRect, ref sliderValue.x, ref sliderValue.y, minMaxSliderAttribute.MinValue, minMaxSliderAttribute.MaxValue); + + sliderValue.x = EditorGUI.FloatField(minFloatFieldRect, sliderValue.x); + sliderValue.x = Mathf.Clamp(sliderValue.x, minMaxSliderAttribute.MinValue, Mathf.Min(minMaxSliderAttribute.MaxValue, sliderValue.y)); + + sliderValue.y = EditorGUI.FloatField(maxFloatFieldRect, sliderValue.y); + sliderValue.y = Mathf.Clamp(sliderValue.y, Mathf.Max(minMaxSliderAttribute.MinValue, sliderValue.x), minMaxSliderAttribute.MaxValue); + + if (EditorGUI.EndChangeCheck()) + { + if (property.propertyType == SerializedPropertyType.Vector2) + { + property.vector2Value = sliderValue; + } + else + { + property.vector2IntValue = new Vector2Int((int)sliderValue.x, (int) sliderValue.y); + } + } + } + else + { + string warning = minMaxSliderAttribute.GetType().Name + " can be used only on Vector2 fields"; + EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: PropertyUtility.GetTargetObject(property)); + + EditorDrawUtility.DrawPropertyField(property); + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/MinMaxSliderPropertyDrawer.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/MinMaxSliderPropertyDrawer.cs.meta new file mode 100644 index 0000000..ca0af07 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/MinMaxSliderPropertyDrawer.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 27011af81554b5b4489b155f09275475 +timeCreated: 1508427131 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ProgressBarPropertyDrawer.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ProgressBarPropertyDrawer.cs new file mode 100644 index 0000000..582f2b1 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ProgressBarPropertyDrawer.cs @@ -0,0 +1,96 @@ +using UnityEngine; +using UnityEditor; +using System; + +namespace NaughtyAttributes.Editor +{ + [PropertyDrawer(typeof(ProgressBarAttribute))] + public class ProgressBarPropertyDrawer : PropertyDrawer + { + public override void DrawProperty(SerializedProperty property) + { + EditorDrawUtility.DrawHeader(property); + + if (property.propertyType != SerializedPropertyType.Float && property.propertyType != SerializedPropertyType.Integer) + { + EditorGUILayout.HelpBox("Field " + property.name + " is not a number", MessageType.Warning); + return; + } + + var value = property.propertyType == SerializedPropertyType.Integer ? property.intValue : property.floatValue; + var valueFormatted = property.propertyType == SerializedPropertyType.Integer ? value.ToString() : String.Format("{0:0.00}", value); + + ProgressBarAttribute progressBarAttribute = PropertyUtility.GetAttribute(property); + var position = EditorGUILayout.GetControlRect(); + var maxValue = progressBarAttribute.MaxValue; + float lineHight = EditorGUIUtility.singleLineHeight; + float padding = EditorGUIUtility.standardVerticalSpacing; + var barPosition = new Rect(position.position.x, position.position.y, position.size.x, lineHight); + + var fillPercentage = value / maxValue; + var barLabel = (!string.IsNullOrEmpty(progressBarAttribute.Name) ? "[" + progressBarAttribute.Name + "] " : "") + valueFormatted + "/" + maxValue; + + var color = GetColor(progressBarAttribute.Color); + var color2 = Color.white; + DrawBar(barPosition, Mathf.Clamp01(fillPercentage), barLabel, color, color2); + } + + private void DrawBar(Rect position, float fillPercent, string label, Color barColor, Color labelColor) + { + if (Event.current.type != EventType.Repaint) + { + return; + } + + Color savedColor = GUI.color; + + var fillRect = new Rect(position.x, position.y, position.width * fillPercent, position.height); + + EditorGUI.DrawRect(position, new Color(0.13f, 0.13f, 0.13f)); + EditorGUI.DrawRect(fillRect, barColor); + + // set alignment and cache the default + var align = GUI.skin.label.alignment; + GUI.skin.label.alignment = TextAnchor.UpperCenter; + + // set the color and cache the default + var c = GUI.contentColor; + GUI.contentColor = labelColor; + + // calculate the position + var labelRect = new Rect(position.x, position.y - 2, position.width, position.height); + + // draw~ + EditorGUI.DropShadowLabel(labelRect, label); + + // reset color and alignment + GUI.contentColor = c; + GUI.skin.label.alignment = align; + } + + private Color GetColor(ProgressBarColor color) + { + switch (color) + { + case ProgressBarColor.Red: + return new Color32(255, 0, 63, 255); + case ProgressBarColor.Pink: + return new Color32(255, 152, 203, 255); + case ProgressBarColor.Orange: + return new Color32(255, 128, 0, 255); + case ProgressBarColor.Yellow: + return new Color32(255, 211, 0, 255); + case ProgressBarColor.Green: + return new Color32(102, 255, 0, 255); + case ProgressBarColor.Blue: + return new Color32(0, 135, 189, 255); + case ProgressBarColor.Indigo: + return new Color32(75, 0, 130, 255); + case ProgressBarColor.Violet: + return new Color32(127, 0, 255, 255); + default: + return Color.white; + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ProgressBarPropertyDrawer.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ProgressBarPropertyDrawer.cs.meta new file mode 100644 index 0000000..c7403f8 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ProgressBarPropertyDrawer.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 47ba764aac86a4d488c8acd0af8f0d23 +timeCreated: 1518435237 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/PropertyDrawer.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/PropertyDrawer.cs new file mode 100644 index 0000000..1a9b898 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/PropertyDrawer.cs @@ -0,0 +1,23 @@ +using System.Reflection; +using UnityEditor; + +namespace NaughtyAttributes.Editor +{ + public abstract class PropertyDrawer + { + public virtual void DrawProperty(FieldInfo fieldInfo, SerializedProperty property) + { + DrawProperty(property); + } + + public virtual void DrawProperty(SerializedProperty property) + { + EditorDrawUtility.DrawPropertyField(property); + } + + public virtual void ClearCache() + { + + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/PropertyDrawer.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/PropertyDrawer.cs.meta new file mode 100644 index 0000000..276a963 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/PropertyDrawer.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: fd2df67a49fb7bd4d8e3914c5a2cf4a8 +timeCreated: 1508051576 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ReadOnlyPropertyDrawer.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ReadOnlyPropertyDrawer.cs new file mode 100644 index 0000000..a255642 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ReadOnlyPropertyDrawer.cs @@ -0,0 +1,16 @@ +using UnityEditor; +using UnityEngine; + +namespace NaughtyAttributes.Editor +{ + [PropertyDrawer(typeof(ReadOnlyAttribute))] + public class ReadOnlyPropertyDrawer : PropertyDrawer + { + public override void DrawProperty(SerializedProperty property) + { + GUI.enabled = false; + EditorDrawUtility.DrawPropertyField(property); + GUI.enabled = true; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ReadOnlyPropertyDrawer.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ReadOnlyPropertyDrawer.cs.meta new file mode 100644 index 0000000..aa80c05 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ReadOnlyPropertyDrawer.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: a392efb1d44b30744bb7bf76e479cfab +timeCreated: 1508862451 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ReorderableListPropertyDrawer.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ReorderableListPropertyDrawer.cs new file mode 100644 index 0000000..84ec1f9 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ReorderableListPropertyDrawer.cs @@ -0,0 +1,106 @@ +using System; +using UnityEngine; +using UnityEditor; +using UnityEditorInternal; +using System.Collections.Generic; + +namespace NaughtyAttributes.Editor +{ + [PropertyDrawer(typeof(ReorderableListAttribute))] + public class ReorderableListPropertyDrawer : PropertyDrawer + { + struct PropertyKey : IEquatable + { + readonly string fieldName; + readonly object sourceObject; + + public PropertyKey(SerializedProperty property) + { + fieldName = property.name; + sourceObject = property.serializedObject; + } + + public bool Equals(PropertyKey other) + { + return string.Equals(fieldName, other.fieldName) && + Equals(sourceObject, other.sourceObject); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + return obj is PropertyKey && Equals((PropertyKey) obj); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = (fieldName != null ? fieldName.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (sourceObject != null ? sourceObject.GetHashCode() : 0); + return hashCode; + } + } + + public static bool operator ==(PropertyKey left, PropertyKey right) + { + return left.Equals(right); + } + + public static bool operator !=(PropertyKey left, PropertyKey right) + { + return !left.Equals(right); + } + } + + Dictionary reorderableListsByPropertyName = new Dictionary(); + + public override void DrawProperty(SerializedProperty property) + { + EditorDrawUtility.DrawHeader(property); + + if (property.isArray) + { + var propertyKey = new PropertyKey(property); + if (!this.reorderableListsByPropertyName.ContainsKey(propertyKey)) + { + ReorderableList reorderableList = new ReorderableList(property.serializedObject, property, true, true, true, true) + { + drawHeaderCallback = (Rect rect) => + { + EditorGUI.LabelField(rect, string.Format("{0}: {1}", property.displayName, property.arraySize), EditorStyles.label); + }, + + drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => + { + var element = property.GetArrayElementAtIndex(index); + rect.y += 2f; + + EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), element); + } + }; + + this.reorderableListsByPropertyName[propertyKey] = reorderableList; + } + + this.reorderableListsByPropertyName[propertyKey].DoLayoutList(); + } + else + { + string warning = typeof(ReorderableListAttribute).Name + " can be used only on arrays or lists"; + EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: PropertyUtility.GetTargetObject(property)); + + EditorDrawUtility.DrawPropertyField(property); + } + } + + public override void ClearCache() + { + this.reorderableListsByPropertyName.Clear(); + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ReorderableListPropertyDrawer.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ReorderableListPropertyDrawer.cs.meta new file mode 100644 index 0000000..c06f619 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ReorderableListPropertyDrawer.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 6d5a6c66de03d1d4882f0c83b0e5f8f2 +timeCreated: 1508402303 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ResizableTextAreaPropertyDrawer.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ResizableTextAreaPropertyDrawer.cs new file mode 100644 index 0000000..cacffb1 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ResizableTextAreaPropertyDrawer.cs @@ -0,0 +1,35 @@ +using UnityEngine; +using UnityEditor; + +namespace NaughtyAttributes.Editor +{ + [PropertyDrawer(typeof(ResizableTextAreaAttribute))] + public class ResizableTextAreaPropertyDrawer : PropertyDrawer + { + public override void DrawProperty(SerializedProperty property) + { + EditorDrawUtility.DrawHeader(property); + + if (property.propertyType == SerializedPropertyType.String) + { + EditorGUILayout.LabelField(property.displayName); + + EditorGUI.BeginChangeCheck(); + + string textAreaValue = EditorGUILayout.TextArea(property.stringValue, GUILayout.MinHeight(EditorGUIUtility.singleLineHeight * 3f)); + + if (EditorGUI.EndChangeCheck()) + { + property.stringValue = textAreaValue; + } + } + else + { + string warning = PropertyUtility.GetAttribute(property).GetType().Name + " can only be used on string fields"; + EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: PropertyUtility.GetTargetObject(property)); + + EditorDrawUtility.DrawPropertyField(property); + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ResizableTextAreaPropertyDrawer.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ResizableTextAreaPropertyDrawer.cs.meta new file mode 100644 index 0000000..898f9d2 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ResizableTextAreaPropertyDrawer.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 57848d4e847a8d445a53095abdbbb274 +timeCreated: 1508583167 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ShowAssetPreviewPropertyDrawer.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ShowAssetPreviewPropertyDrawer.cs new file mode 100644 index 0000000..b548c18 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ShowAssetPreviewPropertyDrawer.cs @@ -0,0 +1,40 @@ +using UnityEngine; +using UnityEditor; + +namespace NaughtyAttributes.Editor +{ + [PropertyDrawer(typeof(ShowAssetPreviewAttribute))] + public class ShowAssetPreviewPropertyDrawer : PropertyDrawer + { + public override void DrawProperty(SerializedProperty property) + { + EditorDrawUtility.DrawPropertyField(property); + + if (property.propertyType == SerializedPropertyType.ObjectReference) + { + if (property.objectReferenceValue != null) + { + Texture2D previewTexture = AssetPreview.GetAssetPreview(property.objectReferenceValue); + if (previewTexture != null) + { + ShowAssetPreviewAttribute showAssetPreviewAttribute = PropertyUtility.GetAttribute(property); + int width = Mathf.Clamp(showAssetPreviewAttribute.Width, 0, previewTexture.width); + int height = Mathf.Clamp(showAssetPreviewAttribute.Height, 0, previewTexture.height); + + GUILayout.Label(previewTexture, GUILayout.MaxWidth(width), GUILayout.MaxHeight(height)); + } + else + { + string warning = property.name + " doesn't have an asset preview"; + EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: PropertyUtility.GetTargetObject(property)); + } + } + } + else + { + string warning = property.name + " doesn't have an asset preview"; + EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: PropertyUtility.GetTargetObject(property)); + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ShowAssetPreviewPropertyDrawer.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ShowAssetPreviewPropertyDrawer.cs.meta new file mode 100644 index 0000000..4c4b7c0 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ShowAssetPreviewPropertyDrawer.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 6c461f4d7edd955419e5e6ce2c874599 +timeCreated: 1509089502 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SliderPropertyDrawer.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SliderPropertyDrawer.cs new file mode 100644 index 0000000..c466292 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SliderPropertyDrawer.cs @@ -0,0 +1,31 @@ +using UnityEditor; + +namespace NaughtyAttributes.Editor +{ + [PropertyDrawer(typeof(SliderAttribute))] + public class SliderPropertyDrawer : PropertyDrawer + { + public override void DrawProperty(SerializedProperty property) + { + EditorDrawUtility.DrawHeader(property); + + SliderAttribute sliderAttribute = PropertyUtility.GetAttribute(property); + + if (property.propertyType == SerializedPropertyType.Integer) + { + EditorGUILayout.IntSlider(property, (int)sliderAttribute.MinValue, (int)sliderAttribute.MaxValue); + } + else if (property.propertyType == SerializedPropertyType.Float) + { + EditorGUILayout.Slider(property, sliderAttribute.MinValue, sliderAttribute.MaxValue); + } + else + { + string warning = sliderAttribute.GetType().Name + " can be used only on int or float fields"; + EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: PropertyUtility.GetTargetObject(property)); + + EditorDrawUtility.DrawPropertyField(property); + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SliderPropertyDrawer.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SliderPropertyDrawer.cs.meta new file mode 100644 index 0000000..5aae3b0 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SliderPropertyDrawer.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: ae129a284d179ae41b8ab20f506e5d99 +timeCreated: 1508422518 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyGroupers.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyGroupers.meta new file mode 100644 index 0000000..d850feb --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyGroupers.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 35fed6de66b90ad418e2ca247a303b9b +folderAsset: yes +timeCreated: 1508331735 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyGroupers/BoxGroupPropertyGrouper.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyGroupers/BoxGroupPropertyGrouper.cs new file mode 100644 index 0000000..e84eaf3 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyGroupers/BoxGroupPropertyGrouper.cs @@ -0,0 +1,24 @@ +using UnityEditor; +using UnityEngine; + +namespace NaughtyAttributes.Editor +{ + [PropertyGrouper(typeof(BoxGroupAttribute))] + public class BoxGroupPropertyGrouper : PropertyGrouper + { + public override void BeginGroup(string label) + { + EditorGUILayout.BeginVertical(GUI.skin.box); + + if (!string.IsNullOrEmpty(label)) + { + EditorGUILayout.LabelField(label, EditorStyles.boldLabel); + } + } + + public override void EndGroup() + { + EditorGUILayout.EndVertical(); + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyGroupers/BoxGroupPropertyGrouper.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyGroupers/BoxGroupPropertyGrouper.cs.meta new file mode 100644 index 0000000..b11e43f --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyGroupers/BoxGroupPropertyGrouper.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 657c1fb836d709c4b964d04f07ddd047 +timeCreated: 1508332897 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyGroupers/PropertyGrouper.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyGroupers/PropertyGrouper.cs new file mode 100644 index 0000000..2e4492a --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyGroupers/PropertyGrouper.cs @@ -0,0 +1,11 @@ +using System; + +namespace NaughtyAttributes.Editor +{ + public abstract class PropertyGrouper + { + public abstract void BeginGroup(string label); + + public abstract void EndGroup(); + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyGroupers/PropertyGrouper.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyGroupers/PropertyGrouper.cs.meta new file mode 100644 index 0000000..1e2a88a --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyGroupers/PropertyGrouper.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 207d6d654fe48184c97a1c946d0ad8a4 +timeCreated: 1508331735 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas.meta new file mode 100644 index 0000000..58792a1 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 254c9f391295da84fb392b742e7fceae +folderAsset: yes +timeCreated: 1508497398 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas/InfoBoxPropertyMeta.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas/InfoBoxPropertyMeta.cs new file mode 100644 index 0000000..83fe0b7 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas/InfoBoxPropertyMeta.cs @@ -0,0 +1,68 @@ +using System.Reflection; +using UnityEditor; + +namespace NaughtyAttributes.Editor +{ + [PropertyMeta(typeof(InfoBoxAttribute))] + public class InfoBoxPropertyMeta : PropertyMeta + { + public override void ApplyPropertyMeta(SerializedProperty property, MetaAttribute metaAttribute) + { + InfoBoxAttribute infoBoxAttribute = (InfoBoxAttribute)metaAttribute; + UnityEngine.Object target = PropertyUtility.GetTargetObject(property); + + if (!string.IsNullOrEmpty(infoBoxAttribute.VisibleIf)) + { + FieldInfo conditionField = ReflectionUtility.GetField(target, infoBoxAttribute.VisibleIf); + if (conditionField != null && + conditionField.FieldType == typeof(bool)) + { + if ((bool)conditionField.GetValue(target)) + { + this.DrawInfoBox(infoBoxAttribute.Text, infoBoxAttribute.Type); + } + + return; + } + + MethodInfo conditionMethod = ReflectionUtility.GetMethod(target, infoBoxAttribute.VisibleIf); + if (conditionMethod != null && + conditionMethod.ReturnType == typeof(bool) && + conditionMethod.GetParameters().Length == 0) + { + if ((bool)conditionMethod.Invoke(target, null)) + { + this.DrawInfoBox(infoBoxAttribute.Text, infoBoxAttribute.Type); + } + + return; + } + + string warning = infoBoxAttribute.GetType().Name + " needs a valid boolean condition field or method name to work"; + EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: PropertyUtility.GetTargetObject(property)); + } + else + { + this.DrawInfoBox(infoBoxAttribute.Text, infoBoxAttribute.Type); + } + } + + private void DrawInfoBox(string infoText, InfoBoxType infoBoxType) + { + switch (infoBoxType) + { + case InfoBoxType.Normal: + EditorGUILayout.HelpBox(infoText, MessageType.Info); + break; + + case InfoBoxType.Warning: + EditorGUILayout.HelpBox(infoText, MessageType.Warning); + break; + + case InfoBoxType.Error: + EditorGUILayout.HelpBox(infoText, MessageType.Error); + break; + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas/InfoBoxPropertyMeta.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas/InfoBoxPropertyMeta.cs.meta new file mode 100644 index 0000000..bb4c001 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas/InfoBoxPropertyMeta.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 998d996265069854eae8d1241df0c8aa +timeCreated: 1508607449 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas/OnValueChangedPropertyMeta.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas/OnValueChangedPropertyMeta.cs new file mode 100644 index 0000000..75303ce --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas/OnValueChangedPropertyMeta.cs @@ -0,0 +1,31 @@ +using System.Reflection; +using UnityEditor; +using UnityEngine; + +namespace NaughtyAttributes.Editor +{ + [PropertyMeta(typeof(OnValueChangedAttribute))] + public class OnValueChangedPropertyMeta : PropertyMeta + { + public override void ApplyPropertyMeta(SerializedProperty property, MetaAttribute metaAttribute) + { + OnValueChangedAttribute onValueChangedAttribute = (OnValueChangedAttribute)metaAttribute; + UnityEngine.Object target = PropertyUtility.GetTargetObject(property); + + MethodInfo callbackMethod = ReflectionUtility.GetMethod(target, onValueChangedAttribute.CallbackName); + if (callbackMethod != null && + callbackMethod.ReturnType == typeof(void) && + callbackMethod.GetParameters().Length == 0) + { + property.serializedObject.ApplyModifiedProperties(); // We must apply modifications so that the callback can be invoked with up-to-date data + + callbackMethod.Invoke(target, null); + } + else + { + string warning = onValueChangedAttribute.GetType().Name + " can invoke only action methods - with void return type and no parameters"; + Debug.LogWarning(warning, target); + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas/OnValueChangedPropertyMeta.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas/OnValueChangedPropertyMeta.cs.meta new file mode 100644 index 0000000..4c29909 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas/OnValueChangedPropertyMeta.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: a55050bf047356c49b1598f431d277e9 +timeCreated: 1508612140 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas/PropertyMeta.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas/PropertyMeta.cs new file mode 100644 index 0000000..3d9b499 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas/PropertyMeta.cs @@ -0,0 +1,9 @@ +using UnityEditor; + +namespace NaughtyAttributes.Editor +{ + public abstract class PropertyMeta + { + public abstract void ApplyPropertyMeta(SerializedProperty property, MetaAttribute metaAttribute); + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas/PropertyMeta.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas/PropertyMeta.cs.meta new file mode 100644 index 0000000..831ab49 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyMetas/PropertyMeta.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 87cd72b1f8ad36840a07e1128f77ec5b +timeCreated: 1508497398 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators.meta new file mode 100644 index 0000000..6713dc9 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: efd539f7816167541ba63e633f2a9a7c +folderAsset: yes +timeCreated: 1508153828 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/MaxValuePropertyValidator.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/MaxValuePropertyValidator.cs new file mode 100644 index 0000000..84f54af --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/MaxValuePropertyValidator.cs @@ -0,0 +1,33 @@ +using UnityEditor; + +namespace NaughtyAttributes.Editor +{ + [PropertyValidator(typeof(MaxValueAttribute))] + public class MaxValuePropertyValidator : PropertyValidator + { + public override void ValidateProperty(SerializedProperty property) + { + MaxValueAttribute maxValueAttribute = PropertyUtility.GetAttribute(property); + + if (property.propertyType == SerializedPropertyType.Integer) + { + if (property.intValue > maxValueAttribute.MaxValue) + { + property.intValue = (int)maxValueAttribute.MaxValue; + } + } + else if (property.propertyType == SerializedPropertyType.Float) + { + if (property.floatValue > maxValueAttribute.MaxValue) + { + property.floatValue = maxValueAttribute.MaxValue; + } + } + else + { + string warning = maxValueAttribute.GetType().Name + " can be used only on int or float fields"; + EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: PropertyUtility.GetTargetObject(property)); + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/MaxValuePropertyValidator.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/MaxValuePropertyValidator.cs.meta new file mode 100644 index 0000000..a11c91a --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/MaxValuePropertyValidator.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 84ddaea11c76b9c4f9a0b56dbab25b4c +timeCreated: 1508153828 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/MinValuePropertyValidator.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/MinValuePropertyValidator.cs new file mode 100644 index 0000000..0d20e46 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/MinValuePropertyValidator.cs @@ -0,0 +1,33 @@ +using UnityEditor; + +namespace NaughtyAttributes.Editor +{ + [PropertyValidator(typeof(MinValueAttribute))] + public class MinValuePropertyValidator : PropertyValidator + { + public override void ValidateProperty(SerializedProperty property) + { + MinValueAttribute minValueAttribute = PropertyUtility.GetAttribute(property); + + if (property.propertyType == SerializedPropertyType.Integer) + { + if (property.intValue < minValueAttribute.MinValue) + { + property.intValue = (int)minValueAttribute.MinValue; + } + } + else if (property.propertyType == SerializedPropertyType.Float) + { + if (property.floatValue < minValueAttribute.MinValue) + { + property.floatValue = minValueAttribute.MinValue; + } + } + else + { + string warning = minValueAttribute.GetType().Name + " can be used only on int or float fields"; + EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: PropertyUtility.GetTargetObject(property)); + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/MinValuePropertyValidator.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/MinValuePropertyValidator.cs.meta new file mode 100644 index 0000000..929ac89 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/MinValuePropertyValidator.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 68add38e187dd154889b1e3b13247621 +timeCreated: 1508153828 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/PropertyValidator.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/PropertyValidator.cs new file mode 100644 index 0000000..c7380ea --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/PropertyValidator.cs @@ -0,0 +1,9 @@ +using UnityEditor; + +namespace NaughtyAttributes.Editor +{ + public abstract class PropertyValidator + { + public abstract void ValidateProperty(SerializedProperty property); + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/PropertyValidator.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/PropertyValidator.cs.meta new file mode 100644 index 0000000..56aca33 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/PropertyValidator.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 73502d09058a2e344a1eb20859d29203 +timeCreated: 1508153828 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/RequiredPropertyValidator.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/RequiredPropertyValidator.cs new file mode 100644 index 0000000..8502a02 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/RequiredPropertyValidator.cs @@ -0,0 +1,41 @@ +using UnityEditor; + +namespace NaughtyAttributes.Editor +{ + [PropertyValidator(typeof(RequiredAttribute))] + public class RequiredPropertyValidator : PropertyValidator + { + bool warningNotLogged; + + public RequiredPropertyValidator() + { + warningNotLogged = true; + } + + public override void ValidateProperty(SerializedProperty property) + { + RequiredAttribute requiredAttribute = PropertyUtility.GetAttribute(property); + + if (property.propertyType == SerializedPropertyType.ObjectReference) + { + if (property.objectReferenceValue == null) + { + string errorMessage = property.name + " is required"; + if (!string.IsNullOrEmpty(requiredAttribute.Message)) + { + errorMessage = requiredAttribute.Message; + } + + EditorDrawUtility.DrawHelpBox(errorMessage, MessageType.Error, logToConsole: warningNotLogged, context: PropertyUtility.GetTargetObject(property)); + } + } + else + { + string warning = requiredAttribute.GetType().Name + " works only on reference types"; + EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: warningNotLogged, context: PropertyUtility.GetTargetObject(property)); + } + + warningNotLogged = false; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/RequiredPropertyValidator.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/RequiredPropertyValidator.cs.meta new file mode 100644 index 0000000..239c36c --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/RequiredPropertyValidator.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 0675503782f800d4081737a5e41f9bf5 +timeCreated: 1508655546 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/ValidateInputPropertyValidator.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/ValidateInputPropertyValidator.cs new file mode 100644 index 0000000..352024d --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/ValidateInputPropertyValidator.cs @@ -0,0 +1,55 @@ +using System; +using System.Reflection; +using UnityEditor; + +namespace NaughtyAttributes.Editor +{ + [PropertyValidator(typeof(ValidateInputAttribute))] + public class ValidateInputPropertyValidator : PropertyValidator + { + public override void ValidateProperty(SerializedProperty property) + { + ValidateInputAttribute validateInputAttribute = PropertyUtility.GetAttribute(property); + UnityEngine.Object target = PropertyUtility.GetTargetObject(property); + + MethodInfo validationCallback = ReflectionUtility.GetMethod(target, validateInputAttribute.CallbackName); + + if (validationCallback != null && + validationCallback.ReturnType == typeof(bool) && + validationCallback.GetParameters().Length == 1) + { + FieldInfo fieldInfo = ReflectionUtility.GetField(target, property.name); + Type fieldType = fieldInfo.FieldType; + Type parameterType = validationCallback.GetParameters()[0].ParameterType; + + if (fieldType == parameterType) + { + if (!(bool)validationCallback.Invoke(target, new object[] { fieldInfo.GetValue(target) })) + { + if (string.IsNullOrEmpty(validateInputAttribute.Message)) + { + EditorDrawUtility.DrawHelpBox(property.name + " is not valid", MessageType.Error, logToConsole: true, context: target); + } + else + { + EditorDrawUtility.DrawHelpBox(validateInputAttribute.Message, MessageType.Error, logToConsole: true, context: target); + } + } + } + else + { + string warning = "The field type is not the same as the callback's parameter type"; + EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: target); + } + } + else + { + string warning = + validateInputAttribute.GetType().Name + + " needs a callback with boolean return type and a single parameter of the same type as the field"; + + EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: target); + } + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/ValidateInputPropertyValidator.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/ValidateInputPropertyValidator.cs.meta new file mode 100644 index 0000000..fb4a666 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/PropertyValidators/ValidateInputPropertyValidator.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 9b7357cef1466544aac67a1976ad9a18 +timeCreated: 1508657795 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility.meta new file mode 100644 index 0000000..ed16edd --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: acb4475c71a3fe947a81ced84ab89c6d +folderAsset: yes +timeCreated: 1508062761 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/EditorDrawUtility.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/EditorDrawUtility.cs new file mode 100644 index 0000000..ea545e0 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/EditorDrawUtility.cs @@ -0,0 +1,149 @@ +using UnityEngine; +using UnityEditor; +using System; + +namespace NaughtyAttributes.Editor +{ + public static class EditorDrawUtility + { + public static void DrawHeader(string header) + { + EditorGUILayout.Space(); + EditorGUILayout.LabelField(header, EditorStyles.boldLabel); + } + + public static bool DrawHeader(SerializedProperty property) + { + HeaderAttribute headerAttr = PropertyUtility.GetAttribute(property); + if (headerAttr != null) + { + DrawHeader(headerAttr.header); + return true; + } + + return false; + } + + public static void DrawHelpBox(string message, MessageType type, bool logToConsole = false, UnityEngine.Object context = null) + { + EditorGUILayout.HelpBox(message, type); + + if (logToConsole) + { + switch (type) + { + case MessageType.None: + case MessageType.Info: + Debug.Log(message, context); + break; + case MessageType.Warning: + Debug.LogWarning(message, context); + break; + case MessageType.Error: + Debug.LogError(message, context); + break; + } + } + } + + public static void DrawPropertyField(SerializedProperty property, bool includeChildren = true) + { + EditorGUILayout.PropertyField(property, includeChildren); + } + + public static bool DrawLayoutField(object value, string label, Type targetType) + { + GUI.enabled = false; + + bool isDrawn = true; + Type valueType = value?.GetType() ?? targetType; + if (value != null) + { + if (valueType == typeof(bool)) + { + EditorGUILayout.Toggle(label, (bool) value); + } + else if (valueType == typeof(int)) + { + EditorGUILayout.IntField(label, (int) value); + } + else if (valueType == typeof(long)) + { + EditorGUILayout.LongField(label, (long) value); + } + else if (valueType == typeof(float)) + { + EditorGUILayout.FloatField(label, (float) value); + } + else if (valueType == typeof(double)) + { + EditorGUILayout.DoubleField(label, (double) value); + } + else if (valueType == typeof(string)) + { + EditorGUILayout.TextField(label, (string) value); + } + else if (valueType == typeof(Vector2)) + { + EditorGUILayout.Vector2Field(label, (Vector2) value); + } + else if (valueType == typeof(Vector3)) + { + EditorGUILayout.Vector3Field(label, (Vector3) value); + } + else if (valueType == typeof(Vector4)) + { + EditorGUILayout.Vector4Field(label, (Vector4) value); + } + else if (valueType == typeof(Color)) + { + EditorGUILayout.ColorField(label, (Color) value); + } + else if (valueType == typeof(Bounds)) + { + EditorGUILayout.BoundsField(label, (Bounds) value); + } + else if (valueType == typeof(Rect)) + { + EditorGUILayout.RectField(label, (Rect) value); + } + else if (valueType == typeof(Vector2)) + { + EditorGUILayout.Vector2Field(label, (Vector2) value); + } + else if (valueType == typeof(Vector3)) + { + EditorGUILayout.Vector3Field(label, (Vector3) value); + } + else if (valueType == typeof(Vector2Int)) + { + EditorGUILayout.Vector2IntField(label, (Vector2Int) value); + } + else if (valueType == typeof(Vector3Int)) + { + EditorGUILayout.Vector3IntField(label, (Vector3Int) value); + } + else if (typeof(UnityEngine.Object).IsAssignableFrom(valueType)) + { + EditorGUILayout.ObjectField(label, (UnityEngine.Object)value, valueType, true); + } + else + { + EditorGUILayout.TextField(label, $"{value}"); + } + } + else if (typeof(UnityEngine.Object).IsAssignableFrom(valueType)) + { + EditorGUILayout.ObjectField(label, (UnityEngine.Object)value, valueType, true); + } + else + { + EditorGUILayout.TextField(label, $"{value}"); + } + + GUI.enabled = true; + + return isDrawn; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/EditorDrawUtility.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/EditorDrawUtility.cs.meta new file mode 100644 index 0000000..704d3e5 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/EditorDrawUtility.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 6ff27ff7705d6064e935bb2159a1b453 +timeCreated: 1510926159 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/IOUtility.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/IOUtility.cs new file mode 100644 index 0000000..9872765 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/IOUtility.cs @@ -0,0 +1,49 @@ +using UnityEngine; +using System.IO; + +namespace NaughtyAttributes.Editor +{ + public static class IOUtility + { + public static string GetPersistentDataPath() + { + return Application.persistentDataPath + "/"; + } + + public static void WriteToFile(string filePath, string content) + { + using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write)) + { + using (StreamWriter streamWriter = new StreamWriter(fileStream, System.Text.Encoding.ASCII)) + { + streamWriter.WriteLine(content); + } + } + } + + public static string ReadFromFile(string filePath) + { + using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) + { + using (StreamReader streamReader = new StreamReader(fileStream, System.Text.Encoding.ASCII)) + { + string content = streamReader.ReadToEnd(); + return content; + } + } + } + + public static bool FileExists(string filePath) + { + return File.Exists(filePath); + } + + public static string GetPathRelativeToProjectFolder(string fullPath) + { + int indexOfAssetsWord = fullPath.IndexOf("\\Assets"); + string relativePath = fullPath.Substring(indexOfAssetsWord + 1); + + return relativePath; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/IOUtility.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/IOUtility.cs.meta new file mode 100644 index 0000000..e8ab56a --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/IOUtility.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: bf376371b2951274e823154c03f066e2 +timeCreated: 1508232215 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/PropertyUtility.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/PropertyUtility.cs new file mode 100644 index 0000000..fa8051c --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/PropertyUtility.cs @@ -0,0 +1,27 @@ +using UnityEditor; +using System; +using System.Reflection; + +namespace NaughtyAttributes.Editor +{ + public static class PropertyUtility + { + public static T GetAttribute(SerializedProperty property) where T : Attribute + { + T[] attributes = GetAttributes(property); + return attributes.Length > 0 ? attributes[0] : null; + } + + public static T[] GetAttributes(SerializedProperty property) where T : Attribute + { + FieldInfo fieldInfo = ReflectionUtility.GetField(GetTargetObject(property), property.name); + + return (T[])fieldInfo.GetCustomAttributes(typeof(T), true); + } + + public static UnityEngine.Object GetTargetObject(SerializedProperty property) + { + return property.serializedObject.targetObject; + } + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/PropertyUtility.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/PropertyUtility.cs.meta new file mode 100644 index 0000000..fad8d5b --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/PropertyUtility.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: e2d50a3c7c8a9754cb3936216494be66 +timeCreated: 1508153828 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/ReflectionUtility.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/ReflectionUtility.cs new file mode 100644 index 0000000..128d29f --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/ReflectionUtility.cs @@ -0,0 +1,192 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace NaughtyAttributes.Editor +{ + public static class ReflectionUtility + { + public static IEnumerable GetAllFields(object target, Func predicate) + { + List types = new List() + { + target.GetType() + }; + + while (types.Last().BaseType != null) + { + types.Add(types.Last().BaseType); + } + + for (int i = types.Count - 1; i >= 0; i--) + { + IEnumerable fieldInfos = types[i] + .GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public | + BindingFlags.DeclaredOnly) + .Where(predicate); + + foreach (var fieldInfo in fieldInfos) + { + yield return fieldInfo; + } + } + } + + public static List GetAllFieldsEfficiently(object target, Func predicate, List buffer) + { + if (buffer != null) + { + buffer.Clear(); + } + else + { + buffer = new List(); + } + + var types = new List() + { + target.GetType() + }; + + while (types.Last().BaseType != null) + { + types.Add(types.Last().BaseType); + } + + for (int i = types.Count - 1; i >= 0; i--) + { + var fieldInfos = types[i] + .GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly); + + foreach (var fi in fieldInfos) + { + if (!predicate(fi)) + { + continue; + } + + buffer.Add(fi); + } + } + + return buffer; + } + + public static IEnumerable GetAllProperties(object target, Func predicate) + { + List types = new List() + { + target.GetType() + }; + + while (types.Last().BaseType != null) + { + types.Add(types.Last().BaseType); + } + + for (int i = types.Count - 1; i >= 0; i--) + { + IEnumerable propertyInfos = types[i] + .GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public | + BindingFlags.DeclaredOnly) + .Where(predicate); + + foreach (var propertyInfo in propertyInfos) + { + yield return propertyInfo; + } + } + } + + public static List GetAllPropertiesEfficiently(object target, Func predicate, List buffer) + { + if (buffer != null) + { + buffer.Clear(); + } + else + { + buffer = new List(); + } + + List types = new List() + { + target.GetType() + }; + + while (types.Last().BaseType != null) + { + types.Add(types.Last().BaseType); + } + + for (int i = types.Count - 1; i >= 0; i--) + { + var propertyInfos = types[i].GetProperties(BindingFlags.Instance | + BindingFlags.Static | + BindingFlags.NonPublic | + BindingFlags.Public | + BindingFlags.DeclaredOnly); + + foreach (var propertyInfo in propertyInfos) + { + if (predicate(propertyInfo)) + { + buffer.Add(propertyInfo); + } + } + } + + return buffer; + } + + public static IEnumerable GetAllMethods(object target, Func predicate) + { + var methodInfos = target.GetType() + .GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public) + .Where(predicate); + + return methodInfos; + } + + public static List GetAllMethodsEfficiently(object target, Func predicate, List buffer) + { + + if (buffer != null) + { + buffer.Clear(); + } + else + { + buffer = new List(); + } + + var methodInfos = target.GetType() + .GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); + + foreach (var m in methodInfos) + { + if (predicate(m)) + { + buffer.Add(m); + } + } + return buffer; + } + + public static FieldInfo GetField(object target, string fieldName) + { + return GetAllFields(target, f => f.Name.Equals(fieldName, StringComparison.InvariantCulture)).FirstOrDefault(); + } + + public static PropertyInfo GetProperty(object target, string propertyName) + { + return GetAllProperties(target, p => p.Name.Equals(propertyName, StringComparison.InvariantCulture)).FirstOrDefault(); + } + + public static MethodInfo GetMethod(object target, string methodName) + { + return GetAllMethods(target, m => m.Name.Equals(methodName, StringComparison.InvariantCulture)).FirstOrDefault(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/ReflectionUtility.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/ReflectionUtility.cs.meta new file mode 100644 index 0000000..73b6ea9 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility/ReflectionUtility.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 1d86c581f02a55f458e36bf7e81e3084 +timeCreated: 1520258793 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Test.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Test.meta new file mode 100644 index 0000000..6eca4f6 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Test.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ce2bd76b5676a434bb8a84254f67f1dc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Test/NaughtyAttributes.Test.asmdef b/Assets/Plugins/NaughtyAttributes/Scripts/Test/NaughtyAttributes.Test.asmdef new file mode 100644 index 0000000..37eea20 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Test/NaughtyAttributes.Test.asmdef @@ -0,0 +1,10 @@ +{ + "name": "NaughtyAttributes.Test", + "references": [ + "NaughtyAttributes" + ], + "optionalUnityReferences": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false +} \ No newline at end of file diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Test/NaughtyAttributes.Test.asmdef.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Test/NaughtyAttributes.Test.asmdef.meta new file mode 100644 index 0000000..9f07c4c --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Test/NaughtyAttributes.Test.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 82c1e45a5287b2a4caf5433640542667 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Test/NaughtyComponent.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Test/NaughtyComponent.cs new file mode 100644 index 0000000..7c760a8 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Test/NaughtyComponent.cs @@ -0,0 +1,157 @@ +using NaughtyAttributes; +using System.Collections.Generic; +using UnityEngine; + +public class NaughtyComponent : MonoBehaviour +{ + [BoxGroup("Sliders")] + [Slider(0, 10)] + public int intSlider; + + [BoxGroup("Sliders")] + [Slider(0.0f, 10.0f)] + public float floatSlider; + + [BoxGroup("Sliders")] + [MinMaxSlider(0.0f, 100.0f)] + public Vector2 minMaxSlider; + + [BoxGroup("Reorderable Lists")] + [ReorderableList] + public int[] intArray; + + [BoxGroup("Reorderable Lists")] + [ReorderableList] + public List vectorList; + + [BoxGroup("Dropdowns")] + [Dropdown("intValues")] + public int intValue; + + [BoxGroup("Dropdowns")] + [Dropdown("stringValues")] + public string stringValue; + + [BoxGroup("Dropdowns")] + [Dropdown("vectorValues")] + public Vector3 vectorValue; + +#pragma warning disable 414 + private int[] intValues = new int[] { 1, 2, 3 }; + + private List stringValues = new List() { "A", "B", "C" }; + + private DropdownList vectorValues = new DropdownList() + { + { "Right", Vector3.right }, + { "Up", Vector3.up }, + { "Forward", Vector3.forward } + }; +#pragma warning restore 414 + + [ResizableTextArea] + public string textArea; + +#pragma warning disable 414 + [ShowNonSerializedField] + private int myInt = 10; + + [ShowNonSerializedField] + private const float PI = 3.14159f; + + [ShowNonSerializedField] + private static readonly Vector3 CONST_VECTOR = Vector3.one; +#pragma warning restore 414 + + [ShowNativeProperty] + public Transform Transform + { + get + { + return this.transform; + } + } + + [ReadOnly] + public int readOnlyInt = 5; + + public bool enableInt = true; + + [EnableIf("enableInt")] + public int enableIf; + + [DisableIf("enableInt")] + public int disabledIf; + + [EnableIf("ReturnTrue")] + public int enabledInt; + + [DisableIf("ReturnTrue")] + public int disabledInt; + + public bool showInt = true; + + [ShowIf("showInt")] + public int showIf; + + [HideIf("showInt")] + public int hideIf; + + [ShowIf("ReturnTrue")] + public int shownInt; + + [HideIf("ReturnTrue")] + public int hiddenInt; + + [ShowAssetPreview] + public Sprite sprite; + + [ShowAssetPreview(96, 96)] + public GameObject prefab; + + [ProgressBar("Health", 100, ProgressBarColor.Orange)] + public float health = 50; + + [MinValue(0.0f), MaxValue(1.0f)] + public float minMaxValidated; + + [Required] + public Transform requiredTransform; + + [Required("Must not be null")] + public GameObject requiredGameObject; + + [ValidateInput("IsNotNull", "must not be null")] + public Sprite notNullSprite; + + [InfoBox("Has onValueChanged callback")] + [OnValueChanged("OnValueChanged")] + public int onValueChanged; + + [Button] + public void MethodOne() + { + Debug.Log("MethodOne()"); + } + + [Button("Button Text")] + private void MethodTwo() + { + Debug.Log("MethodTwo()"); + } + + private bool ReturnTrue() + { + return true; + } + + private bool IsNotNull(Sprite sprite) + { + return sprite != null; + } + + private void OnValueChanged() + { + Debug.Log(this.onValueChanged); + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Test/NaughtyComponent.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Test/NaughtyComponent.cs.meta new file mode 100644 index 0000000..5702f19 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Test/NaughtyComponent.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 9c928ea15ae74a44089beb2e534c1a35 +timeCreated: 1507996629 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Test/NaughtyScriptableObject.cs b/Assets/Plugins/NaughtyAttributes/Scripts/Test/NaughtyScriptableObject.cs new file mode 100644 index 0000000..7bb6dbf --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Test/NaughtyScriptableObject.cs @@ -0,0 +1,157 @@ +using UnityEngine; +using NaughtyAttributes; +using System.Collections.Generic; + +// [CreateAssetMenu(fileName = "NaughtyScriptableObject", menuName = "NaughtyAttributes/NaughtyScriptableObject")] +public class NaughtyScriptableObject : ScriptableObject +{ + [BoxGroup("Sliders")] + [Slider(0, 10)] + public int intSlider; + + [BoxGroup("Sliders")] + [Slider(0.0f, 10.0f)] + public float floatSlider; + + [BoxGroup("Sliders")] + [MinMaxSlider(0.0f, 100.0f)] + public Vector2 minMaxSlider; + + [BoxGroup("Reorderable Lists")] + [ReorderableList] + public int[] intArray; + + [BoxGroup("Reorderable Lists")] + [ReorderableList] + public List vectorList; + + [BoxGroup("Dropdowns")] + [Dropdown("intValues")] + public int intValue; + + [BoxGroup("Dropdowns")] + [Dropdown("stringValues")] + public string stringValue; + + [BoxGroup("Dropdowns")] + [Dropdown("vectorValues")] + public Vector3 vectorValue; + +#pragma warning disable 414 + private int[] intValues = new int[] { 1, 2, 3 }; + + private List stringValues = new List() { "A", "B", "C" }; + + private DropdownList vectorValues = new DropdownList() + { + { "Right", Vector3.right }, + { "Up", Vector3.up }, + { "Forward", Vector3.forward } + }; +#pragma warning restore 414 + + [ResizableTextArea] + public string textArea; + +#pragma warning disable 414 + [ShowNonSerializedField] + private int myInt = 10; + + [ShowNonSerializedField] + private const float PI = 3.14159f; + + [ShowNonSerializedField] + private static readonly Vector3 CONST_VECTOR = Vector3.one; +#pragma warning restore 414 + + [ShowNativeProperty] + public ScriptableObject Transform + { + get + { + return this; + } + } + + [ReadOnly] + public int readOnlyInt = 5; + + public bool enableInt = true; + + [EnableIf("enableInt")] + public int enableIf; + + [DisableIf("enableInt")] + public int disabledIf; + + [EnableIf("ReturnTrue")] + public int enabledInt; + + [DisableIf("ReturnTrue")] + public int disabledInt; + + public bool showInt = true; + + [ShowIf("showInt")] + public int showIf; + + [HideIf("showInt")] + public int hideIf; + + [ShowIf("ReturnTrue")] + public int shownInt; + + [HideIf("ReturnTrue")] + public int hiddenInt; + + [ShowAssetPreview] + public Sprite sprite; + + [ShowAssetPreview(96, 96)] + public GameObject prefab; + + [ProgressBar("Health", 100, ProgressBarColor.Orange)] + public float health = 50; + + [MinValue(0.0f), MaxValue(1.0f)] + public float minMaxValidated; + + [Required] + public GameObject requiredPrefab; + + [InfoBox("Has onValueChanged callback")] + [OnValueChanged("OnValueChanged")] + public int onValueChanged; + + [Button] + public void MethodOne() + { + Debug.Log("MethodOne()"); + } + + [Button("Button Text")] + private void MethodTwo() + { + Debug.Log("MethodTwo()"); + } + + private bool ReturnTrue() + { + return true; + } + + private bool ReturnFalse() + { + return false; + } + + private bool IsNotNull(Sprite sprite) + { + return sprite != null; + } + + private void OnValueChanged() + { + Debug.Log(this.onValueChanged); + } +} diff --git a/Assets/Plugins/NaughtyAttributes/Scripts/Test/NaughtyScriptableObject.cs.meta b/Assets/Plugins/NaughtyAttributes/Scripts/Test/NaughtyScriptableObject.cs.meta new file mode 100644 index 0000000..eb5d253 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/Scripts/Test/NaughtyScriptableObject.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 753bdb918c6038142acddbd7aae6958f +timeCreated: 1518639587 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/TestAssets.meta b/Assets/Plugins/NaughtyAttributes/TestAssets.meta new file mode 100644 index 0000000..931e8f8 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/TestAssets.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 53a462744f22ca549927c5e6ea797362 +folderAsset: yes +timeCreated: 1509089305 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/TestAssets/Cube.prefab b/Assets/Plugins/NaughtyAttributes/TestAssets/Cube.prefab new file mode 100644 index 0000000..62913f8 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/TestAssets/Cube.prefab @@ -0,0 +1,97 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 1981131855061102} + m_IsPrefabParent: 1 +--- !u!1 &1981131855061102 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4344736110947706} + - component: {fileID: 33062901823624450} + - component: {fileID: 65233182844289960} + - component: {fileID: 23099360439063292} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4344736110947706 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1981131855061102} + 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} +--- !u!23 &23099360439063292 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1981131855061102} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 10303, 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_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &33062901823624450 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1981131855061102} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!65 &65233182844289960 +BoxCollider: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1981131855061102} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} diff --git a/Assets/Plugins/NaughtyAttributes/TestAssets/Cube.prefab.meta b/Assets/Plugins/NaughtyAttributes/TestAssets/Cube.prefab.meta new file mode 100644 index 0000000..f493507 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/TestAssets/Cube.prefab.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 7ec354ef3daae7641b7a3fa5e1fe0c81 +timeCreated: 1509089337 +licenseType: Free +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 100100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/TestAssets/NaughtyScriptableObject.asset b/Assets/Plugins/NaughtyAttributes/TestAssets/NaughtyScriptableObject.asset new file mode 100644 index 0000000..9fb8523 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/TestAssets/NaughtyScriptableObject.asset @@ -0,0 +1,40 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 753bdb918c6038142acddbd7aae6958f, type: 3} + m_Name: NaughtyScriptableObject + m_EditorClassIdentifier: + intSlider: 2 + floatSlider: 0 + minMaxSlider: {x: 0, y: 0} + intArray: + vectorList: [] + intValue: 0 + stringValue: + vectorValue: {x: 0, y: 0, z: 0} + textArea: + readOnlyInt: 5 + enableInt: 1 + enableIf: 0 + disabledIf: 0 + enabledInt: 0 + disabledInt: 0 + showInt: 1 + showIf: 0 + hideIf: 0 + shownInt: 0 + hiddenInt: 0 + sprite: {fileID: 0} + prefab: {fileID: 0} + health: 50 + minMaxValidated: 0 + requiredPrefab: {fileID: 1981131855061102, guid: 7ec354ef3daae7641b7a3fa5e1fe0c81, + type: 2} + onValueChanged: 1 diff --git a/Assets/Plugins/NaughtyAttributes/TestAssets/NaughtyScriptableObject.asset.meta b/Assets/Plugins/NaughtyAttributes/TestAssets/NaughtyScriptableObject.asset.meta new file mode 100644 index 0000000..dbcb741 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/TestAssets/NaughtyScriptableObject.asset.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 9cf80899b80517945a2d2390fb48877f +timeCreated: 1518639643 +licenseType: Free +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/TestAssets/icon-github.png b/Assets/Plugins/NaughtyAttributes/TestAssets/icon-github.png new file mode 100644 index 0000000..228b09a Binary files /dev/null and b/Assets/Plugins/NaughtyAttributes/TestAssets/icon-github.png differ diff --git a/Assets/Plugins/NaughtyAttributes/TestAssets/icon-github.png.meta b/Assets/Plugins/NaughtyAttributes/TestAssets/icon-github.png.meta new file mode 100644 index 0000000..14874c3 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/TestAssets/icon-github.png.meta @@ -0,0 +1,103 @@ +fileFormatVersion: 2 +guid: 005888ede18a58e4db8d069cfa3007cb +timeCreated: 1509089310 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + 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} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: WebGL + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/_Scenes.meta b/Assets/Plugins/NaughtyAttributes/_Scenes.meta new file mode 100644 index 0000000..91002d8 --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/_Scenes.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: afb4c815411c28b449e61fbaa1a8bfa3 +folderAsset: yes +timeCreated: 1507995550 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/NaughtyAttributes/_Scenes/DemoScene.unity b/Assets/Plugins/NaughtyAttributes/_Scenes/DemoScene.unity new file mode 100644 index 0000000..1d29eeb --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/_Scenes/DemoScene.unity @@ -0,0 +1,334 @@ +%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: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 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.44657874, g: 0.49641258, b: 0.5748172, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 0 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_TemporalCoherenceThreshold: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 1 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + 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: 1 + 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: 1 +--- !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 &1444377589 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1444377591} + - component: {fileID: 1444377590} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &1444377590 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1444377589} + m_Enabled: 1 + serializedVersion: 8 + m_Type: 1 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_Lightmapping: 4 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &1444377591 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1444377589} + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!1 &1591883662 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1591883666} + - component: {fileID: 1591883665} + - component: {fileID: 1591883664} + - component: {fileID: 1591883663} + 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 &1591883663 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1591883662} + m_Enabled: 1 +--- !u!124 &1591883664 +Behaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1591883662} + m_Enabled: 1 +--- !u!20 &1591883665 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1591883662} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + 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: 0 + 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: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &1591883666 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1591883662} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + 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} +--- !u!1 &2033251972 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2033251974} + - component: {fileID: 2033251973} + m_Layer: 0 + m_Name: TestObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &2033251973 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2033251972} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9c928ea15ae74a44089beb2e534c1a35, type: 3} + m_Name: + m_EditorClassIdentifier: + intSlider: 0 + floatSlider: 0 + minMaxSlider: {x: 0, y: 0} + intArray: + vectorList: [] + intValue: 0 + stringValue: + vectorValue: {x: 0, y: 0, z: 0} + textArea: + readOnlyInt: 5 + enableInt: 1 + enableIf: 0 + disabledIf: 0 + enabledInt: 0 + disabledInt: 0 + showInt: 1 + showIf: 0 + hideIf: 0 + shownInt: 0 + hiddenInt: 0 + sprite: {fileID: 21300000, guid: 005888ede18a58e4db8d069cfa3007cb, type: 3} + prefab: {fileID: 1981131855061102, guid: 7ec354ef3daae7641b7a3fa5e1fe0c81, type: 2} + health: 50 + minMaxValidated: 0 + requiredTransform: {fileID: 2033251974} + requiredGameObject: {fileID: 2033251972} + notNullSprite: {fileID: 21300000, guid: 005888ede18a58e4db8d069cfa3007cb, type: 3} + onValueChanged: 0 +--- !u!4 &2033251974 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2033251972} + 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: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/Plugins/NaughtyAttributes/_Scenes/DemoScene.unity.meta b/Assets/Plugins/NaughtyAttributes/_Scenes/DemoScene.unity.meta new file mode 100644 index 0000000..819f1ec --- /dev/null +++ b/Assets/Plugins/NaughtyAttributes/_Scenes/DemoScene.unity.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 07845a5477be2b149a6f1cb32b5a3a5b +timeCreated: 1507998788 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem.meta b/Assets/Plugins/UnityTutorialSystem.meta new file mode 100644 index 0000000..ee63de2 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 74f7829a3941fc646ad1cfa4efa7fe52 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/LICENSE.txt b/Assets/Plugins/UnityTutorialSystem/LICENSE.txt new file mode 100644 index 0000000..4031813 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018-2019 Thomas Morgner + +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/Plugins/UnityTutorialSystem/LICENSE.txt.meta b/Assets/Plugins/UnityTutorialSystem/LICENSE.txt.meta new file mode 100644 index 0000000..b02d5ea --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/LICENSE.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f8e734814ea2e0d41a0a79bd7f8b0486 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes.meta b/Assets/Plugins/UnityTutorialSystem/Scenes.meta new file mode 100644 index 0000000..8cfcdbd --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 41671983d3817d84d82d3559c411e23a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/ContentList.prefab b/Assets/Plugins/UnityTutorialSystem/Scenes/ContentList.prefab new file mode 100644 index 0000000..b814a7b --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/ContentList.prefab @@ -0,0 +1,537 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1119027821575648 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 224930166395689530} + - component: {fileID: 222869044883501650} + - component: {fileID: 114312059845659162} + - component: {fileID: 8556782208736572212} + m_Layer: 5 + m_Name: Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &224930166395689530 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1119027821575648} + 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: + - {fileID: 224554747877605170} + m_Father: {fileID: 224160305383547462} + 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: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &222869044883501650 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1119027821575648} + m_CullTransparentMesh: 0 +--- !u!114 &114312059845659162 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1119027821575648} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, 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_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 + m_UseSpriteMesh: 0 +--- !u!114 &8556782208736572212 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1119027821575648} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: 20 + m_PreferredHeight: 20 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!1 &1415598103615636 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 224528275417451060} + - component: {fileID: 114821739908165324} + - component: {fileID: 114400973501864318} + m_Layer: 5 + m_Name: ContentList + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &224528275417451060 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1415598103615636} + 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: + - {fileID: 224160305383547462} + m_Father: {fileID: 0} + m_RootOrder: 0 + 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, y: 1} +--- !u!114 &114821739908165324 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1415598103615636} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f70555f144d8491a825f0804e09c671c, 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: 5 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 1 + m_ChildControlHeight: 0 +--- !u!114 &114400973501864318 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1415598103615636} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5dabfd477c564c518af7ad4e2362742a, type: 3} + m_Name: + m_EditorClassIdentifier: + showRootNode: 0 + template: {fileID: 1223395836} + showAllNodes: 0 + hideCompletedSubTrees: 0 +--- !u!1 &1472719709801288 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 224554747877605170} + - component: {fileID: 222743336091278658} + - component: {fileID: 114741211279708708} + m_Layer: 5 + m_Name: Checkmark + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &224554747877605170 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1472719709801288} + 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: 224930166395689530} + 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: 20, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &222743336091278658 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1472719709801288} + m_CullTransparentMesh: 0 +--- !u!114 &114741211279708708 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1472719709801288} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, 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_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10901, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!1 &1574653218349702 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 224432365767571276} + - component: {fileID: 222190762113586452} + - component: {fileID: 114720927400143124} + m_Layer: 5 + m_Name: Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &224432365767571276 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1574653218349702} + 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: 224160305383547462} + 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.5, y: 0.5} +--- !u!222 &222190762113586452 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1574653218349702} + m_CullTransparentMesh: 0 +--- !u!114 &114720927400143124 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1574653218349702} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, 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_text: 'Test + +' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 14 + m_fontSizeBase: 14 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 257 + m_isAlignmentEnumConverted: 1 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 5, y: 3, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 114720927400143124} + characterCount: 5 + spriteCount: 0 + spaceCount: 1 + wordCount: 1 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_havePropertiesChanged: 0 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_isInputParsingRequired: 0 + m_inputSource: 0 + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!1 &1843578962797072 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 224160305383547462} + - component: {fileID: 3591000738502833973} + - component: {fileID: 1223395836} + - component: {fileID: 256921282078287685} + m_Layer: 5 + m_Name: _Template + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &224160305383547462 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1843578962797072} + 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: + - {fileID: 224930166395689530} + - {fileID: 224432365767571276} + m_Father: {fileID: 224528275417451060} + 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: 0, y: 0} + m_SizeDelta: {x: 0, y: 30} + m_Pivot: {x: 0, y: 0} +--- !u!114 &3591000738502833973 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1843578962797072} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 2109663825, guid: f70555f144d8491a825f0804e09c671c, 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: 114312059845659162} + toggleTransition: 1 + graphic: {fileID: 114741211279708708} + m_Group: {fileID: 0} + onValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Toggle+ToggleEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null + m_IsOn: 1 +--- !u!114 &1223395836 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1843578962797072} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: bcf2b234f7c645128d79667d27a38161, type: 3} + m_Name: + m_EditorClassIdentifier: + whenNextEventColor: {r: 0.740566, g: 0.79368824, b: 1, a: 1} + whenCompletedColor: {r: 0.7028302, g: 1, b: 0.72236216, a: 1} + defaultColor: {r: 1, g: 1, b: 1, a: 1} + whenNextEventFontStyle: 0 + whenCompletedFontStyle: 0 + defaultFontStyle: 0 + toggle: {fileID: 3591000738502833973} + label: {fileID: 114720927400143124} + indentPerLevel: 20 + ignoreLeadingIndent: 0 +--- !u!114 &256921282078287685 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1843578962797072} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ea16d7c66e8746679b5a105ab2458c21, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 0 diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/ContentList.prefab.meta b/Assets/Plugins/UnityTutorialSystem/Scenes/ContentList.prefab.meta new file mode 100644 index 0000000..d9fe8b4 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/ContentList.prefab.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 154207b2fe8edf6469479d563d3e8e59 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 100100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/DemonstrationEventLogger.asset b/Assets/Plugins/UnityTutorialSystem/Scenes/DemonstrationEventLogger.asset new file mode 100644 index 0000000..ce7ce73 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/DemonstrationEventLogger.asset @@ -0,0 +1,16 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !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: eb241ac2c5a447599a51649ca12e622f, type: 3} + m_Name: DemonstrationEventLogger + m_EditorClassIdentifier: + stream: {fileID: 11400000, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} + enabled: 1 diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/DemonstrationEventLogger.asset.meta b/Assets/Plugins/UnityTutorialSystem/Scenes/DemonstrationEventLogger.asset.meta new file mode 100644 index 0000000..77c1122 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/DemonstrationEventLogger.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c633d558de1a6ab4b97eabaf09b08b31 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/DemonstrationEventStream.asset b/Assets/Plugins/UnityTutorialSystem/Scenes/DemonstrationEventStream.asset new file mode 100644 index 0000000..c7e5342 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/DemonstrationEventStream.asset @@ -0,0 +1,141 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !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: 0efa5601f9e59ab4990baf4ac245a6dc, type: 3} + m_Name: DemonstrationEventStream + m_EditorClassIdentifier: + messageTypes: + - Button A + - Button B + - Button C + - Button D + - Button E + - Melody Complete + - Button Pressed + - Button Pressed Complete + - Tasks Complete +--- !u!114 &114087278996602626 +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: 83707740ea9a4854b2b1651e53c42c0b, type: 3} + m_Name: Button A + m_EditorClassIdentifier: + stream: {fileID: 11400000} +--- !u!114 &114237395628351686 +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: 83707740ea9a4854b2b1651e53c42c0b, type: 3} + m_Name: Button D + m_EditorClassIdentifier: + stream: {fileID: 11400000} +--- !u!114 &114295595302332938 +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: 83707740ea9a4854b2b1651e53c42c0b, type: 3} + m_Name: Melody Complete + m_EditorClassIdentifier: + stream: {fileID: 11400000} +--- !u!114 &114453565588672230 +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: 83707740ea9a4854b2b1651e53c42c0b, type: 3} + m_Name: Tasks Complete + m_EditorClassIdentifier: + stream: {fileID: 11400000} +--- !u!114 &114505920661840866 +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: 83707740ea9a4854b2b1651e53c42c0b, type: 3} + m_Name: Button C + m_EditorClassIdentifier: + stream: {fileID: 11400000} +--- !u!114 &114531965955044376 +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: 83707740ea9a4854b2b1651e53c42c0b, type: 3} + m_Name: Button B + m_EditorClassIdentifier: + stream: {fileID: 11400000} +--- !u!114 &114683655999235588 +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: 83707740ea9a4854b2b1651e53c42c0b, type: 3} + m_Name: Button Pressed + m_EditorClassIdentifier: + stream: {fileID: 11400000} +--- !u!114 &114969602861105628 +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: 83707740ea9a4854b2b1651e53c42c0b, type: 3} + m_Name: Button Pressed Complete + m_EditorClassIdentifier: + stream: {fileID: 11400000} +--- !u!114 &114979598298759166 +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: 83707740ea9a4854b2b1651e53c42c0b, type: 3} + m_Name: Button E + m_EditorClassIdentifier: + stream: {fileID: 11400000} diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/DemonstrationEventStream.asset.meta b/Assets/Plugins/UnityTutorialSystem/Scenes/DemonstrationEventStream.asset.meta new file mode 100644 index 0000000..c1fe6b5 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/DemonstrationEventStream.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c01cc92f4088c6e4abcd3830c0002c24 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/Material A.mat b/Assets/Plugins/UnityTutorialSystem/Scenes/Material A.mat new file mode 100644 index 0000000..95fce92 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/Material A.mat @@ -0,0 +1,77 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Material A + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + 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: 0} + 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_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: 0.6925462, b: 0.48584908, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/Material A.mat.meta b/Assets/Plugins/UnityTutorialSystem/Scenes/Material A.mat.meta new file mode 100644 index 0000000..1a68cab --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/Material A.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2d0f2f374d40b044cad99564f6499b66 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/Material B.mat b/Assets/Plugins/UnityTutorialSystem/Scenes/Material B.mat new file mode 100644 index 0000000..830b863 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/Material B.mat @@ -0,0 +1,77 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Material B + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + 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: 0} + 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_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: 0.90372217, b: 0.48627448, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/Material B.mat.meta b/Assets/Plugins/UnityTutorialSystem/Scenes/Material B.mat.meta new file mode 100644 index 0000000..4128aca --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/Material B.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 613e8da578a66c94f8d7dd6e9c35cfef +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/Material C.mat b/Assets/Plugins/UnityTutorialSystem/Scenes/Material C.mat new file mode 100644 index 0000000..2ec952c --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/Material C.mat @@ -0,0 +1,77 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Material C + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + 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: 0} + 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_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: 0.69889736, g: 1, b: 0.48627448, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/Material C.mat.meta b/Assets/Plugins/UnityTutorialSystem/Scenes/Material C.mat.meta new file mode 100644 index 0000000..c527e98 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/Material C.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cdcd9310224fa424bb696b3a16069566 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/Material D.mat b/Assets/Plugins/UnityTutorialSystem/Scenes/Material D.mat new file mode 100644 index 0000000..a5b465f --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/Material D.mat @@ -0,0 +1,77 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Material D + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + 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: 0} + 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_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: 0.48627448, b: 0.62796795, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/Material D.mat.meta b/Assets/Plugins/UnityTutorialSystem/Scenes/Material D.mat.meta new file mode 100644 index 0000000..11c92c1 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/Material D.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 254da5f51648fba4c9a58e4aa28b91de +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/Material E.mat b/Assets/Plugins/UnityTutorialSystem/Scenes/Material E.mat new file mode 100644 index 0000000..af25c09 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/Material E.mat @@ -0,0 +1,77 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Material E + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + 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: 0} + 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_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: 0.48627448, g: 0.9159756, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/Material E.mat.meta b/Assets/Plugins/UnityTutorialSystem/Scenes/Material E.mat.meta new file mode 100644 index 0000000..86409c8 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/Material E.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 156bb662bf805ff4293c7bedc3c3082d +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/Player.prefab b/Assets/Plugins/UnityTutorialSystem/Scenes/Player.prefab new file mode 100644 index 0000000..5dc0765 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/Player.prefab @@ -0,0 +1,342 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 0} + m_RootGameObject: {fileID: 1244723767573728} + m_IsPrefabAsset: 1 +--- !u!1 &1070021465145296 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 4628888185422042} + - component: {fileID: 33440364477968484} + - component: {fileID: 23621741914110926} + - component: {fileID: 135733888523515464} + m_Layer: 0 + m_Name: Head + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1244723767573728 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 4100914089427470} + - component: {fileID: 143371818348401776} + - component: {fileID: 114571473726663984} + m_Layer: 0 + m_Name: Player + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1631203309818378 +GameObject: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 4348443926274028} + - component: {fileID: 20170485882131438} + - component: {fileID: 81224396187494474} + m_Layer: 0 + m_Name: Camera + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1687002603152750 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 4114957474629024} + - component: {fileID: 33539184950781672} + - component: {fileID: 23016541972173176} + - component: {fileID: 136889383682470836} + m_Layer: 0 + m_Name: Body + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4100914089427470 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1244723767573728} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 7.8787584, y: 1.1831524, z: -1.7996497} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4628888185422042} + - {fileID: 4114957474629024} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4114957474629024 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1687002603152750} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0.75, z: 0} + m_LocalScale: {x: 0.75, y: 0.75, z: 0.75} + m_Children: [] + m_Father: {fileID: 4100914089427470} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4348443926274028 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1631203309818378} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0.262, z: -0.044} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4628888185422042} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4628888185422042 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1070021465145296} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1.7, z: 0} + m_LocalScale: {x: 0.6, y: 0.6, z: 0.6} + m_Children: + - {fileID: 4348443926274028} + m_Father: {fileID: 4100914089427470} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!20 &20170485882131438 +Camera: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1631203309818378} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + 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: 0 + orthographic size: 5 + m_Depth: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!23 &23016541972173176 +MeshRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1687002603152750} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_Materials: + - {fileID: 10303, 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_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &23621741914110926 +MeshRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1070021465145296} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_Materials: + - {fileID: 10303, 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_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &33440364477968484 +MeshFilter: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1070021465145296} + m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} +--- !u!33 &33539184950781672 +MeshFilter: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1687002603152750} + m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0} +--- !u!81 &81224396187494474 +AudioListener: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1631203309818378} + m_Enabled: 1 +--- !u!114 &114571473726663984 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1244723767573728} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 874752e98bdb4ccd8f8377e539e3529e, type: 3} + m_Name: + m_EditorClassIdentifier: + strafeKey: 306 + strafeKey2: 305 + forwardMovementSpeed: 2 + reverseMovementSpeed: 1 + strafeSpeed: 1 + movementThreshold: 0.1 + rotationSpeed: 180 + independentHeadMovement: 0 + invertHeadLook: 0 + head: {fileID: 0} + MovementBlocked: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + Moving: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!135 &135733888523515464 +SphereCollider: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1070021465145296} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Radius: 0.5 + m_Center: {x: 0, y: 0, z: 0} +--- !u!136 &136889383682470836 +CapsuleCollider: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1687002603152750} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + m_Radius: 0.5 + m_Height: 2 + m_Direction: 1 + m_Center: {x: 0, y: 0, z: 0} +--- !u!143 &143371818348401776 +CharacterController: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1244723767573728} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Height: 2 + m_Radius: 0.5 + m_SlopeLimit: 45 + m_StepOffset: 0.3 + m_SkinWidth: 0.08 + m_MinMoveDistance: 0.001 + m_Center: {x: 0, y: 0, z: 0} diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/Player.prefab.meta b/Assets/Plugins/UnityTutorialSystem/Scenes/Player.prefab.meta new file mode 100644 index 0000000..d642bc3 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/Player.prefab.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f124838f11137ef4fade04d0ac972bc6 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 100100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/Scripts.meta b/Assets/Plugins/UnityTutorialSystem/Scenes/Scripts.meta new file mode 100644 index 0000000..680a7ec --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2e105fa76f47ed64cbf37dcb36f6ae42 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/Scripts/CharacterBehaviour.cs b/Assets/Plugins/UnityTutorialSystem/Scenes/Scripts/CharacterBehaviour.cs new file mode 100644 index 0000000..7a49dac --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/Scripts/CharacterBehaviour.cs @@ -0,0 +1,130 @@ +using NaughtyAttributes; +using UnityEngine; +using UnityEngine.Events; + +namespace UnityTutorialSystem.Scenes.Scripts +{ + /// + /// A basic character controller that allows WASD movement and mouse look in a single script. + /// + [RequireComponent(typeof(CharacterController))] + public class CharacterBehaviour : MonoBehaviour + { + [BoxGroup("Movement")] + [Tooltip("Modifier Key to enable strafing movement")] + [SerializeField] KeyCode strafeKey; + + [BoxGroup("Movement")] + [Tooltip("Alternative modifier Key to enable strafing movement")] + [SerializeField] KeyCode strafeKey2; + + [BoxGroup("Movement")] + [SerializeField] bool independentHeadMovement; + + [BoxGroup("Movement")] + [SerializeField] bool invertHeadLook; + [BoxGroup("Movement")] + [SerializeField] bool mouseMovement; + + [BoxGroup("Movement Speed")] + [SerializeField] float forwardMovementSpeed; + [BoxGroup("Movement Speed")] + [SerializeField] float reverseMovementSpeed; + [BoxGroup("Movement Speed")] + [SerializeField] float strafeSpeed; + [BoxGroup("Movement Speed")] + [SerializeField] float rotationSpeed; + [BoxGroup("Movement Speed")] + [Tooltip("At which velocity does the animation system show an movement animation?")] + [SerializeField] float movementThreshold; + + [BoxGroup("Internal")] + [SerializeField] Transform head; + + CharacterController characterController; + [SerializeField] UnityEvent movementBlocked; + [SerializeField] UnityEvent moving; + + public UnityEvent MovementBlocked => movementBlocked; + + public UnityEvent Moving => moving; + + public CollisionFlags MovementResult { get; private set; } + + void Reset() + { + strafeKey = KeyCode.LeftControl; + strafeKey2 = KeyCode.RightControl; + forwardMovementSpeed = 2; + reverseMovementSpeed = 1; + strafeSpeed = 1; + movementThreshold = 0.1f; + rotationSpeed = 5f; + } + + void Awake() + { + characterController = GetComponent(); + } + + void FixedUpdate() + { + var h = Input.GetAxis("Horizontal"); + if (mouseMovement && !independentHeadMovement) + { + h += Input.GetAxis("Mouse X"); + } + + var v = Input.GetAxis("Vertical"); + var velocity = Vector3.zero; + if (v < 0) + { + velocity += transform.forward * v * reverseMovementSpeed * Time.fixedDeltaTime; + } + else + { + velocity += transform.forward * v * forwardMovementSpeed * Time.fixedDeltaTime; + } + + if (Input.GetKey(strafeKey) || Input.GetKey(strafeKey2)) + { + velocity += transform.right * h * strafeSpeed * Time.fixedDeltaTime; + } + else + { + transform.Rotate(Vector3.up, h * rotationSpeed * Time.fixedDeltaTime); + } + + if (mouseMovement) + { + head.localRotation = HandleMouseLook(); + } + + MovementResult = characterController.Move(velocity); + + if (MovementResult != 0) + { + movementBlocked?.Invoke(); + } + + if (characterController.velocity.magnitude > movementThreshold) + { + moving?.Invoke(); + } + } + + Quaternion HandleMouseLook() + { + var mouseLookAxisX = independentHeadMovement ? Input.GetAxis("Mouse X") : 0; + var mouseLookAxisY = Input.GetAxis("Mouse Y") * (invertHeadLook ? 1 : -1); + var angleY = mouseLookAxisX * Time.fixedDeltaTime * rotationSpeed; + var angleX = mouseLookAxisY * Time.fixedDeltaTime * rotationSpeed; + + var eulers = head.localRotation.eulerAngles; + eulers.y += angleY; + eulers.x = Mathf.Clamp(Mathf.DeltaAngle(0, eulers.x + angleX), -45, 45); + eulers.z = 0; + return Quaternion.Euler(eulers); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/Scripts/CharacterBehaviour.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scenes/Scripts/CharacterBehaviour.cs.meta new file mode 100644 index 0000000..7ec4bf7 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/Scripts/CharacterBehaviour.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 874752e98bdb4ccd8f8377e539e3529e +timeCreated: 1546096240 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/TutorialAssembly.unity b/Assets/Plugins/UnityTutorialSystem/Scenes/TutorialAssembly.unity new file mode 100644 index 0000000..b04ec12 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/TutorialAssembly.unity @@ -0,0 +1,4887 @@ +%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: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 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.44657898, g: 0.4964133, b: 0.5748178, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 0 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 1 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 1 + 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: 1 +--- !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 &121474007 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 121474008} + - component: {fileID: 121474009} + - component: {fileID: 121474010} + m_Layer: 0 + m_Name: CombinedStateHandler + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &121474008 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 121474007} + 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: 2005220181} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &121474009 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 121474007} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8f0a408106974c8d87c1327fb3471f9b, type: 3} + m_Name: + m_EditorClassIdentifier: + Messages: + - {fileID: 114969602861105628, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} + - {fileID: 114295595302332938, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} + matchStarting: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + matchComplete: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + debug: 0 + matchFailed: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + matchMode: 0 +--- !u!114 &121474010 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 121474007} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7fb333aa63754b08a8a3c8327964d16b, type: 3} + m_Name: + m_EditorClassIdentifier: + stateChain: {fileID: 121474009} + successMessage: {fileID: 0} +--- !u!1 &136464903 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 136464907} + - component: {fileID: 136464906} + - component: {fileID: 136464905} + - component: {fileID: 136464904} + - component: {fileID: 136464908} + - component: {fileID: 136464909} + - component: {fileID: 136464910} + m_Layer: 0 + m_Name: Cube D + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!65 &136464904 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 136464903} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &136464905 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 136464903} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 254da5f51648fba4c9a58e4aa28b91de, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &136464906 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 136464903} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &136464907 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 136464903} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 2.705, y: 1, z: -4.827} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 638795628} + m_Father: {fileID: 1569524829} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!82 &136464908 +AudioSource: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 136464903} + m_Enabled: 1 + serializedVersion: 4 + OutputAudioMixerGroup: {fileID: 0} + m_audioClip: {fileID: 8300000, guid: b0fec8744b503ce47b10824d221e0727, type: 3} + m_PlayOnAwake: 0 + m_Volume: 1 + m_Pitch: 1.2 + Loop: 0 + Mute: 0 + Spatialize: 0 + SpatializePostEffects: 0 + Priority: 128 + DopplerLevel: 1 + MinDistance: 1 + MaxDistance: 500 + Pan2D: 0 + rolloffMode: 0 + BypassEffects: 0 + BypassListenerEffects: 0 + BypassReverbZones: 0 + rolloffCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + panLevelCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + spreadCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + reverbZoneMixCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 +--- !u!114 &136464909 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 136464903} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 707a12fe3b5f46afa91e26f91d81b0ef, type: 3} + m_Name: + m_EditorClassIdentifier: + message: {fileID: 114237395628351686, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} +--- !u!114 &136464910 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 136464903} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3c2f7fb44e844d968edd605a04aa2f80, type: 3} + m_Name: + m_EditorClassIdentifier: + Clicked: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 136464909} + m_MethodName: TriggerEvent + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 136464908} + m_MethodName: Play + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + MouseEntered: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + MouseExited: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!1 &141102406 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 141102407} + - component: {fileID: 141102410} + - component: {fileID: 141102409} + - component: {fileID: 141102408} + m_Layer: 0 + m_Name: Sphere + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &141102407 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 141102406} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: 0} + m_LocalScale: {x: 0.19999999, y: 0.19999999, z: 0.19999999} + m_Children: [] + m_Father: {fileID: 159285980} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!135 &141102408 +SphereCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 141102406} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Radius: 0.5 + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &141102409 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 141102406} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10303, 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_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &141102410 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 141102406} + m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &146596266 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 146596267} + - component: {fileID: 146596270} + - component: {fileID: 146596269} + - component: {fileID: 146596268} + m_Layer: 5 + m_Name: Scrollbar Horizontal + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &146596267 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 146596266} + 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: + - {fileID: 1087091968} + m_Father: {fileID: 165394804} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -17, y: 20} + m_Pivot: {x: 0, y: 0} +--- !u!114 &146596268 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 146596266} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -2061169968, guid: f70555f144d8491a825f0804e09c671c, 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: 1871891756} + m_HandleRect: {fileID: 1871891755} + m_Direction: 0 + m_Value: 0 + m_Size: 0.99999994 + m_NumberOfSteps: 0 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Scrollbar+ScrollEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &146596269 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 146596266} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, 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_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + 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 +--- !u!222 &146596270 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 146596266} + m_CullTransparentMesh: 0 +--- !u!1 &159285979 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 159285980} + - component: {fileID: 159285981} + m_Layer: 0 + m_Name: GameObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &159285980 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 159285979} + 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: + - {fileID: 141102407} + m_Father: {fileID: 1471210924} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &159285981 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 159285979} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3a5e67e2cca44e86b9b488f72160885e, type: 3} + m_Name: + m_EditorClassIdentifier: + sources: + - {fileID: 168782044} + detailedDebugging: 0 + nextMessageSource: {fileID: 1471210926} + autoPopulate: 0 + enableForNextMessage: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 141102406} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + disableForNextMessage: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 141102406} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!1 &165394803 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 165394804} + - component: {fileID: 165394807} + - component: {fileID: 165394806} + - component: {fileID: 165394805} + m_Layer: 5 + m_Name: Scroll View + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &165394804 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 165394803} + 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: + - {fileID: 491854709} + - {fileID: 146596267} + - {fileID: 385256436} + m_Father: {fileID: 375966259} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: -400, y: 0} + m_SizeDelta: {x: 400, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &165394805 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 165394803} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 0.392} + 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: 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 +--- !u!222 &165394806 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 165394803} + m_CullTransparentMesh: 0 +--- !u!114 &165394807 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 165394803} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1367256648, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Content: {fileID: 2004723107} + m_Horizontal: 0 + m_Vertical: 1 + m_MovementType: 1 + m_Elasticity: 0.1 + m_Inertia: 1 + m_DecelerationRate: 0.135 + m_ScrollSensitivity: 1 + m_Viewport: {fileID: 491854709} + m_HorizontalScrollbar: {fileID: 146596268} + m_VerticalScrollbar: {fileID: 385256437} + m_HorizontalScrollbarVisibility: 2 + m_VerticalScrollbarVisibility: 0 + m_HorizontalScrollbarSpacing: -3 + m_VerticalScrollbarSpacing: -3 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.ScrollRect+ScrollRectEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!1 &168782041 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 168782043} + - component: {fileID: 168782044} + - component: {fileID: 168782042} + m_Layer: 0 + m_Name: MelodyStateHandler + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &168782042 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 168782041} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7fb333aa63754b08a8a3c8327964d16b, type: 3} + m_Name: + m_EditorClassIdentifier: + stateChain: {fileID: 168782044} + successMessage: {fileID: 114295595302332938, guid: c01cc92f4088c6e4abcd3830c0002c24, + type: 2} +--- !u!4 &168782043 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 168782041} + 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: + - {fileID: 1088321519} + - {fileID: 1079922267} + - {fileID: 536738628} + m_Father: {fileID: 2005220181} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &168782044 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 168782041} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dfb04f096c9c4ca387330c23be4262f1, type: 3} + m_Name: + m_EditorClassIdentifier: + Messages: + - {fileID: 114505920661840866, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} + - {fileID: 114505920661840866, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} + - {fileID: 114237395628351686, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} + - {fileID: 114979598298759166, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} + - {fileID: 114979598298759166, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} + - {fileID: 114237395628351686, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} + - {fileID: 114505920661840866, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} + - {fileID: 114531965955044376, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} + - {fileID: 114087278996602626, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} + - {fileID: 114087278996602626, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} + - {fileID: 114531965955044376, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} + - {fileID: 114505920661840866, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} + matchStarting: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + matchComplete: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1088321520} + m_MethodName: Play + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + debug: 0 + matchFailed: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 168782044} + m_MethodName: ResetMatch + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 1079922268} + m_MethodName: Play + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + mode: 0 +--- !u!1 &364011009 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 364011010} + - component: {fileID: 364011012} + - component: {fileID: 364011011} + m_Layer: 5 + m_Name: Handle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &364011010 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 364011009} + 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: 1824248533} + 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: 0, y: 0} + m_SizeDelta: {x: 20, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &364011011 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 364011009} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, 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_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 + m_UseSpriteMesh: 0 +--- !u!222 &364011012 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 364011009} + m_CullTransparentMesh: 0 +--- !u!1 &375966258 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 375966259} + - component: {fileID: 375966261} + - component: {fileID: 375966260} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &375966259 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 375966258} + 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: + - {fileID: 165394804} + m_Father: {fileID: 787784673} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 400, y: 0} + m_Pivot: {x: 1, y: 0} +--- !u!114 &375966260 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 375966258} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.118999995, g: 0.118999995, b: 0.118999995, a: 0.7607843} + 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: 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 +--- !u!222 &375966261 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 375966258} + m_CullTransparentMesh: 0 +--- !u!1 &385256435 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 385256436} + - component: {fileID: 385256439} + - component: {fileID: 385256438} + - component: {fileID: 385256437} + m_Layer: 5 + m_Name: Scrollbar Vertical + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &385256436 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 385256435} + 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: + - {fileID: 1824248533} + m_Father: {fileID: 165394804} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0} + m_AnchorMax: {x: 1, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 20, y: 0} + m_Pivot: {x: 1, y: 1} +--- !u!114 &385256437 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 385256435} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -2061169968, guid: f70555f144d8491a825f0804e09c671c, 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: 364011011} + m_HandleRect: {fileID: 364011010} + m_Direction: 2 + m_Value: 0 + m_Size: 0.99999994 + m_NumberOfSteps: 0 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Scrollbar+ScrollEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &385256438 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 385256435} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, 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_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + 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 +--- !u!222 &385256439 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 385256435} + m_CullTransparentMesh: 0 +--- !u!1 &491854708 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 491854709} + - component: {fileID: 491854712} + - component: {fileID: 491854711} + - component: {fileID: 491854710} + m_Layer: 5 + m_Name: Viewport + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &491854709 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 491854708} + 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: + - {fileID: 2004723107} + m_Father: {fileID: 165394804} + 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: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 1} +--- !u!114 &491854710 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 491854708} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, 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_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10917, 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 +--- !u!222 &491854711 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 491854708} + m_CullTransparentMesh: 0 +--- !u!114 &491854712 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 491854708} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1200242548, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ShowMaskGraphic: 0 +--- !u!1 &492172209 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 492172210} + - component: {fileID: 492172213} + - component: {fileID: 492172212} + - component: {fileID: 492172211} + m_Layer: 0 + m_Name: Sphere + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &492172210 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 492172209} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: 0} + m_LocalScale: {x: 0.19999999, y: 0.19999999, z: 0.19999999} + m_Children: [] + m_Father: {fileID: 638795628} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!135 &492172211 +SphereCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 492172209} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Radius: 0.5 + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &492172212 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 492172209} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10303, 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_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &492172213 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 492172209} + m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &536738627 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 536738628} + m_Layer: 0 + m_Name: Progress + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &536738628 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 536738627} + 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: 168782043} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &540661107 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 540661111} + - component: {fileID: 540661110} + - component: {fileID: 540661109} + - component: {fileID: 540661108} + - component: {fileID: 540661112} + - component: {fileID: 540661113} + - component: {fileID: 540661114} + m_Layer: 0 + m_Name: Cube A + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!65 &540661108 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 540661107} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &540661109 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 540661107} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 2d0f2f374d40b044cad99564f6499b66, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &540661110 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 540661107} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &540661111 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 540661107} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 5, y: 1, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1770791380} + m_Father: {fileID: 1569524829} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!82 &540661112 +AudioSource: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 540661107} + m_Enabled: 1 + serializedVersion: 4 + OutputAudioMixerGroup: {fileID: 0} + m_audioClip: {fileID: 8300000, guid: b0fec8744b503ce47b10824d221e0727, type: 3} + m_PlayOnAwake: 0 + m_Volume: 1 + m_Pitch: 0.8 + Loop: 0 + Mute: 0 + Spatialize: 0 + SpatializePostEffects: 0 + Priority: 128 + DopplerLevel: 1 + MinDistance: 1 + MaxDistance: 500 + Pan2D: 0 + rolloffMode: 0 + BypassEffects: 0 + BypassListenerEffects: 0 + BypassReverbZones: 0 + rolloffCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + panLevelCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + spreadCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + reverbZoneMixCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 +--- !u!114 &540661113 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 540661107} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 707a12fe3b5f46afa91e26f91d81b0ef, type: 3} + m_Name: + m_EditorClassIdentifier: + message: {fileID: 114087278996602626, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} +--- !u!114 &540661114 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 540661107} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3c2f7fb44e844d968edd605a04aa2f80, type: 3} + m_Name: + m_EditorClassIdentifier: + Clicked: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 540661113} + m_MethodName: TriggerEvent + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 540661112} + m_MethodName: Play + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + MouseEntered: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + MouseExited: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!4 &606059359 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 4628888185422042, guid: f124838f11137ef4fade04d0ac972bc6, + type: 3} + m_PrefabInstance: {fileID: 1838933567} + m_PrefabAsset: {fileID: 0} +--- !u!1 &636989485 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 636989486} + - component: {fileID: 636989487} + m_Layer: 0 + m_Name: GameObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &636989486 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 636989485} + 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: + - {fileID: 1634999306} + m_Father: {fileID: 796071486} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &636989487 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 636989485} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3a5e67e2cca44e86b9b488f72160885e, type: 3} + m_Name: + m_EditorClassIdentifier: + sources: + - {fileID: 168782044} + detailedDebugging: 0 + nextMessageSource: {fileID: 796071488} + autoPopulate: 0 + enableForNextMessage: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1634999305} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + disableForNextMessage: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1634999305} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!1 &638795627 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 638795628} + - component: {fileID: 638795629} + m_Layer: 0 + m_Name: GameObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &638795628 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 638795627} + 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: + - {fileID: 492172210} + m_Father: {fileID: 136464907} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &638795629 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 638795627} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3a5e67e2cca44e86b9b488f72160885e, type: 3} + m_Name: + m_EditorClassIdentifier: + sources: + - {fileID: 168782044} + detailedDebugging: 0 + nextMessageSource: {fileID: 136464909} + autoPopulate: 0 + enableForNextMessage: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 492172209} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + disableForNextMessage: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 492172209} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!1 &787784669 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 787784673} + - component: {fileID: 787784672} + - component: {fileID: 787784671} + - component: {fileID: 787784670} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &787784670 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 787784669} + 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!114 &787784671 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 787784669} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 1 + m_ReferencePixelsPerUnit: 1 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 1000, y: 700} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!223 &787784672 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 787784669} + 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_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &787784673 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 787784669} + 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: 375966259} + - {fileID: 1771506620} + m_Father: {fileID: 0} + m_RootOrder: 3 + 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!1 &796071482 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 796071486} + - component: {fileID: 796071485} + - component: {fileID: 796071484} + - component: {fileID: 796071483} + - component: {fileID: 796071487} + - component: {fileID: 796071488} + - component: {fileID: 796071489} + m_Layer: 0 + m_Name: Cube E + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!65 &796071483 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 796071482} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &796071484 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 796071482} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 156bb662bf805ff4293c7bedc3c3082d, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &796071485 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 796071482} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &796071486 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 796071482} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.844, y: 1, z: -4.806} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 636989486} + m_Father: {fileID: 1569524829} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!82 &796071487 +AudioSource: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 796071482} + m_Enabled: 1 + serializedVersion: 4 + OutputAudioMixerGroup: {fileID: 0} + m_audioClip: {fileID: 8300000, guid: b0fec8744b503ce47b10824d221e0727, type: 3} + m_PlayOnAwake: 0 + m_Volume: 1 + m_Pitch: 1.4 + Loop: 0 + Mute: 0 + Spatialize: 0 + SpatializePostEffects: 0 + Priority: 128 + DopplerLevel: 1 + MinDistance: 1 + MaxDistance: 500 + Pan2D: 0 + rolloffMode: 0 + BypassEffects: 0 + BypassListenerEffects: 0 + BypassReverbZones: 0 + rolloffCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + panLevelCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + spreadCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + reverbZoneMixCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 +--- !u!114 &796071488 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 796071482} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 707a12fe3b5f46afa91e26f91d81b0ef, type: 3} + m_Name: + m_EditorClassIdentifier: + message: {fileID: 114979598298759166, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} +--- !u!114 &796071489 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 796071482} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3c2f7fb44e844d968edd605a04aa2f80, type: 3} + m_Name: + m_EditorClassIdentifier: + Clicked: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 796071488} + m_MethodName: TriggerEvent + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 796071487} + m_MethodName: Play + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + MouseEntered: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + MouseExited: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!1 &945075559 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 945075561} + - component: {fileID: 945075560} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &945075560 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 945075559} + m_Enabled: 1 + serializedVersion: 8 + m_Type: 1 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_Lightmapping: 4 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &945075561 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 945075559} + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!1 &1079922266 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1079922267} + - component: {fileID: 1079922268} + m_Layer: 0 + m_Name: Failure + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1079922267 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079922266} + 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: 168782043} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!82 &1079922268 +AudioSource: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079922266} + m_Enabled: 1 + serializedVersion: 4 + OutputAudioMixerGroup: {fileID: 0} + m_audioClip: {fileID: 8300000, guid: 1ad39a45585989f4bb1a2e1be5b5a46d, type: 3} + m_PlayOnAwake: 0 + m_Volume: 1 + m_Pitch: 1 + Loop: 0 + Mute: 0 + Spatialize: 0 + SpatializePostEffects: 0 + Priority: 128 + DopplerLevel: 1 + MinDistance: 1 + MaxDistance: 500 + Pan2D: 0 + rolloffMode: 0 + BypassEffects: 0 + BypassListenerEffects: 0 + BypassReverbZones: 0 + rolloffCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + panLevelCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + spreadCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + reverbZoneMixCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 +--- !u!1 &1087091967 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1087091968} + m_Layer: 5 + m_Name: Sliding Area + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1087091968 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1087091967} + 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: + - {fileID: 1871891755} + m_Father: {fileID: 146596267} + m_RootOrder: 0 + 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: -20, y: -20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1088321518 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1088321519} + - component: {fileID: 1088321520} + m_Layer: 0 + m_Name: Success + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1088321519 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1088321518} + 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: 168782043} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!82 &1088321520 +AudioSource: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1088321518} + m_Enabled: 1 + serializedVersion: 4 + OutputAudioMixerGroup: {fileID: 0} + m_audioClip: {fileID: 8300000, guid: eea9c093ac8487942b9278ef0c512c40, type: 3} + m_PlayOnAwake: 0 + m_Volume: 1 + m_Pitch: 1 + Loop: 0 + Mute: 0 + Spatialize: 0 + SpatializePostEffects: 0 + Priority: 128 + DopplerLevel: 1 + MinDistance: 1 + MaxDistance: 500 + Pan2D: 0 + rolloffMode: 0 + BypassEffects: 0 + BypassListenerEffects: 0 + BypassReverbZones: 0 + rolloffCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + panLevelCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + spreadCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + reverbZoneMixCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 +--- !u!1 &1163547442 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1163547443} + - component: {fileID: 1163547444} + m_Layer: 0 + m_Name: GameObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1163547443 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1163547442} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: 0} + m_LocalScale: {x: 0.19999999, y: 0.19999999, z: 0.19999999} + m_Children: + - {fileID: 1982592445} + m_Father: {fileID: 1299307874} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1163547444 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1163547442} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3a5e67e2cca44e86b9b488f72160885e, type: 3} + m_Name: + m_EditorClassIdentifier: + sources: + - {fileID: 168782044} + detailedDebugging: 0 + nextMessageSource: {fileID: 1299307876} + autoPopulate: 0 + enableForNextMessage: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1982592444} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + disableForNextMessage: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1982592444} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!1 &1202807401 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1202807407} + - component: {fileID: 1202807406} + - component: {fileID: 1202807405} + - component: {fileID: 1202807404} + - component: {fileID: 1202807403} + - component: {fileID: 1202807402} + m_Layer: 0 + m_Name: ButtonCube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1202807402 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1202807401} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 707a12fe3b5f46afa91e26f91d81b0ef, type: 3} + m_Name: + m_EditorClassIdentifier: + message: {fileID: 114683655999235588, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} +--- !u!114 &1202807403 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1202807401} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3c2f7fb44e844d968edd605a04aa2f80, type: 3} + m_Name: + m_EditorClassIdentifier: + Clicked: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1202807402} + m_MethodName: TriggerEvent + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + MouseEntered: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + MouseExited: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!65 &1202807404 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1202807401} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1202807405 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1202807401} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10303, 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_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &1202807406 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1202807401} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1202807407 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1202807401} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 3.3839302, y: -0.35, z: -1.9372907} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1569524829} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1001 &1223395833 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 491854709} + m_Modifications: + - target: {fileID: 1415598103615636, guid: 154207b2fe8edf6469479d563d3e8e59, type: 3} + propertyPath: m_Name + value: ContentList + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_RootOrder + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_SizeDelta.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_AnchorMax.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_Pivot.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_Pivot.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 114720927400143124, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_havePropertiesChanged + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 114720927400143124, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_isInputParsingRequired + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224160305383547462, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224160305383547462, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224160305383547462, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224160305383547462, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224160305383547462, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224160305383547462, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_SizeDelta.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 114821739908165324, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_ChildControlHeight + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 114821739908165324, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_ChildForceExpandWidth + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224930166395689530, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224930166395689530, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224930166395689530, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224930166395689530, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224930166395689530, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224930166395689530, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_SizeDelta.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224432365767571276, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224432365767571276, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224432365767571276, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224432365767571276, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224432365767571276, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224432365767571276, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_SizeDelta.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3591000738502833973, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_Interactable + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3591000738502833973, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_Colors.m_DisabledColor.r + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 3591000738502833973, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_Colors.m_DisabledColor.g + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 3591000738502833973, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_Colors.m_DisabledColor.b + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 3591000738502833973, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + propertyPath: m_Colors.m_DisabledColor.a + value: 1 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 154207b2fe8edf6469479d563d3e8e59, type: 3} +--- !u!1 &1299307870 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1299307874} + - component: {fileID: 1299307873} + - component: {fileID: 1299307872} + - component: {fileID: 1299307871} + - component: {fileID: 1299307875} + - component: {fileID: 1299307876} + - component: {fileID: 1299307877} + m_Layer: 0 + m_Name: Cube C + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!65 &1299307871 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1299307870} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1299307872 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1299307870} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: cdcd9310224fa424bb696b3a16069566, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &1299307873 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1299307870} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1299307874 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1299307870} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 5, y: 1, z: -4.734} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1163547443} + m_Father: {fileID: 1569524829} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!82 &1299307875 +AudioSource: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1299307870} + m_Enabled: 1 + serializedVersion: 4 + OutputAudioMixerGroup: {fileID: 0} + m_audioClip: {fileID: 8300000, guid: b0fec8744b503ce47b10824d221e0727, type: 3} + m_PlayOnAwake: 0 + m_Volume: 1 + m_Pitch: 1 + Loop: 0 + Mute: 0 + Spatialize: 0 + SpatializePostEffects: 0 + Priority: 128 + DopplerLevel: 1 + MinDistance: 1 + MaxDistance: 500 + Pan2D: 0 + rolloffMode: 0 + BypassEffects: 0 + BypassListenerEffects: 0 + BypassReverbZones: 0 + rolloffCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + panLevelCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + spreadCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + reverbZoneMixCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 +--- !u!114 &1299307876 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1299307870} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 707a12fe3b5f46afa91e26f91d81b0ef, type: 3} + m_Name: + m_EditorClassIdentifier: + message: {fileID: 114505920661840866, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} +--- !u!114 &1299307877 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1299307870} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3c2f7fb44e844d968edd605a04aa2f80, type: 3} + m_Name: + m_EditorClassIdentifier: + Clicked: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1299307876} + m_MethodName: TriggerEvent + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 1299307875} + m_MethodName: Play + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + MouseEntered: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + MouseExited: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!1 &1471210920 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1471210924} + - component: {fileID: 1471210923} + - component: {fileID: 1471210922} + - component: {fileID: 1471210921} + - component: {fileID: 1471210925} + - component: {fileID: 1471210926} + - component: {fileID: 1471210927} + m_Layer: 0 + m_Name: Cube B + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!65 &1471210921 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1471210920} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1471210922 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1471210920} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 613e8da578a66c94f8d7dd6e9c35cfef, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &1471210923 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1471210920} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1471210924 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1471210920} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 5, y: 1, z: -2.097} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 159285980} + m_Father: {fileID: 1569524829} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!82 &1471210925 +AudioSource: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1471210920} + m_Enabled: 1 + serializedVersion: 4 + OutputAudioMixerGroup: {fileID: 0} + m_audioClip: {fileID: 8300000, guid: b0fec8744b503ce47b10824d221e0727, type: 3} + m_PlayOnAwake: 0 + m_Volume: 1 + m_Pitch: 0.9 + Loop: 0 + Mute: 0 + Spatialize: 0 + SpatializePostEffects: 0 + Priority: 128 + DopplerLevel: 1 + MinDistance: 1 + MaxDistance: 500 + Pan2D: 0 + rolloffMode: 0 + BypassEffects: 0 + BypassListenerEffects: 0 + BypassReverbZones: 0 + rolloffCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + panLevelCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + spreadCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + reverbZoneMixCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 +--- !u!114 &1471210926 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1471210920} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 707a12fe3b5f46afa91e26f91d81b0ef, type: 3} + m_Name: + m_EditorClassIdentifier: + message: {fileID: 114531965955044376, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} +--- !u!114 &1471210927 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1471210920} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3c2f7fb44e844d968edd605a04aa2f80, type: 3} + m_Name: + m_EditorClassIdentifier: + Clicked: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1471210926} + m_MethodName: TriggerEvent + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 1471210925} + m_MethodName: Play + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + MouseEntered: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + MouseExited: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!1 &1569524828 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1569524829} + m_Layer: 0 + m_Name: Scenery + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1569524829 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1569524828} + 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: + - {fileID: 1202807407} + - {fileID: 540661111} + - {fileID: 1471210924} + - {fileID: 1299307874} + - {fileID: 136464907} + - {fileID: 796071486} + - {fileID: 1672648496} + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1634999305 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1634999306} + - component: {fileID: 1634999309} + - component: {fileID: 1634999308} + - component: {fileID: 1634999307} + m_Layer: 0 + m_Name: Sphere + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1634999306 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1634999305} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: 0} + m_LocalScale: {x: 0.19999999, y: 0.19999999, z: 0.19999999} + m_Children: [] + m_Father: {fileID: 636989486} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!135 &1634999307 +SphereCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1634999305} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Radius: 0.5 + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1634999308 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1634999305} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10303, 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_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &1634999309 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1634999305} + m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1672648492 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1672648496} + - component: {fileID: 1672648495} + - component: {fileID: 1672648494} + - component: {fileID: 1672648493} + m_Layer: 0 + m_Name: Floor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!64 &1672648493 +MeshCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1672648492} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Convex: 0 + m_CookingOptions: 14 + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &1672648494 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1672648492} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10303, 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_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &1672648495 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1672648492} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1672648496 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1672648492} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 100, y: 1, z: 100} + m_Children: [] + m_Father: {fileID: 1569524829} + m_RootOrder: 6 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1743168502 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1743168503} + - component: {fileID: 1743168506} + - component: {fileID: 1743168505} + - component: {fileID: 1743168504} + m_Layer: 0 + m_Name: Sphere + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1743168503 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1743168502} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: 0} + m_LocalScale: {x: 0.2, y: 0.2, z: 0.2} + m_Children: [] + m_Father: {fileID: 1770791380} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!135 &1743168504 +SphereCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1743168502} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Radius: 0.5 + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1743168505 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1743168502} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10303, 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_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &1743168506 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1743168502} + m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1770791379 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1770791380} + - component: {fileID: 1770791381} + m_Layer: 0 + m_Name: GameObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1770791380 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1770791379} + 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: + - {fileID: 1743168503} + m_Father: {fileID: 540661111} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1770791381 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1770791379} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3a5e67e2cca44e86b9b488f72160885e, type: 3} + m_Name: + m_EditorClassIdentifier: + sources: + - {fileID: 168782044} + detailedDebugging: 0 + nextMessageSource: {fileID: 540661113} + autoPopulate: 0 + enableForNextMessage: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1743168502} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + disableForNextMessage: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1743168502} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!1 &1771014849 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1771014850} + - component: {fileID: 1771014851} + - component: {fileID: 1771014852} + m_Layer: 0 + m_Name: ButtonStateHandler + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1771014850 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1771014849} + 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: + - {fileID: 1816184698} + - {fileID: 2089696630} + m_Father: {fileID: 2005220181} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1771014851 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1771014849} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8f0a408106974c8d87c1327fb3471f9b, type: 3} + m_Name: + m_EditorClassIdentifier: + Messages: + - {fileID: 114683655999235588, guid: c01cc92f4088c6e4abcd3830c0002c24, type: 2} + matchStarting: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + matchComplete: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1816184699} + m_MethodName: Play + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + debug: 0 + matchFailed: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 2089696631} + m_MethodName: Play + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + matchMode: 1 +--- !u!114 &1771014852 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1771014849} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7fb333aa63754b08a8a3c8327964d16b, type: 3} + m_Name: + m_EditorClassIdentifier: + stateChain: {fileID: 1771014851} + successMessage: {fileID: 114969602861105628, guid: c01cc92f4088c6e4abcd3830c0002c24, + type: 2} +--- !u!1 &1771506619 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1771506620} + - component: {fileID: 1771506622} + - component: {fileID: 1771506621} + m_Layer: 5 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1771506620 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1771506619} + 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: 787784673} + 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: -289, y: 155} + m_SizeDelta: {x: 400, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1771506621 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1771506619} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, 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_text: "Click on the indicated elements to play. \nUse WASD to move around if needed." + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 20 + m_fontSizeBase: 20 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 257 + m_isAlignmentEnumConverted: 1 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 1771506621} + characterCount: 76 + spriteCount: 0 + spaceCount: 14 + wordCount: 14 + linkCount: 0 + lineCount: 2 + pageCount: 1 + materialCount: 1 + m_havePropertiesChanged: 0 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_isInputParsingRequired: 0 + m_inputSource: 0 + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1771506622 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1771506619} + m_CullTransparentMesh: 0 +--- !u!1 &1816184697 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1816184698} + - component: {fileID: 1816184699} + m_Layer: 0 + m_Name: Success + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1816184698 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1816184697} + 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: 1771014850} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!82 &1816184699 +AudioSource: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1816184697} + m_Enabled: 1 + serializedVersion: 4 + OutputAudioMixerGroup: {fileID: 0} + m_audioClip: {fileID: 8300000, guid: eea9c093ac8487942b9278ef0c512c40, type: 3} + m_PlayOnAwake: 0 + m_Volume: 1 + m_Pitch: 1 + Loop: 0 + Mute: 0 + Spatialize: 0 + SpatializePostEffects: 0 + Priority: 128 + DopplerLevel: 1 + MinDistance: 1 + MaxDistance: 500 + Pan2D: 0 + rolloffMode: 0 + BypassEffects: 0 + BypassListenerEffects: 0 + BypassReverbZones: 0 + rolloffCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + panLevelCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + spreadCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + reverbZoneMixCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 +--- !u!1 &1824248532 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1824248533} + m_Layer: 5 + m_Name: Sliding Area + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1824248533 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1824248532} + 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: + - {fileID: 364011010} + m_Father: {fileID: 385256436} + m_RootOrder: 0 + 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: -20, y: -20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1001 &1838933567 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 1244723767573728, guid: f124838f11137ef4fade04d0ac972bc6, type: 3} + propertyPath: m_Name + value: Player + objectReference: {fileID: 0} + - target: {fileID: 4100914089427470, guid: f124838f11137ef4fade04d0ac972bc6, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4100914089427470, guid: f124838f11137ef4fade04d0ac972bc6, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4100914089427470, guid: f124838f11137ef4fade04d0ac972bc6, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4100914089427470, guid: f124838f11137ef4fade04d0ac972bc6, type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4100914089427470, guid: f124838f11137ef4fade04d0ac972bc6, type: 3} + propertyPath: m_LocalRotation.y + value: 0.9174745 + objectReference: {fileID: 0} + - target: {fileID: 4100914089427470, guid: f124838f11137ef4fade04d0ac972bc6, type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4100914089427470, guid: f124838f11137ef4fade04d0ac972bc6, type: 3} + propertyPath: m_LocalRotation.w + value: 0.3977945 + objectReference: {fileID: 0} + - target: {fileID: 4100914089427470, guid: f124838f11137ef4fade04d0ac972bc6, type: 3} + propertyPath: m_RootOrder + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 4100914089427470, guid: f124838f11137ef4fade04d0ac972bc6, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 133.119 + objectReference: {fileID: 0} + - target: {fileID: 114571473726663984, guid: f124838f11137ef4fade04d0ac972bc6, + type: 3} + propertyPath: head + value: + objectReference: {fileID: 606059359} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: f124838f11137ef4fade04d0ac972bc6, type: 3} +--- !u!1 &1871891754 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1871891755} + - component: {fileID: 1871891757} + - component: {fileID: 1871891756} + m_Layer: 5 + m_Name: Handle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1871891755 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1871891754} + 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: 1087091968} + 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: 0, y: 0} + m_SizeDelta: {x: 20, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1871891756 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1871891754} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, 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_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 + m_UseSpriteMesh: 0 +--- !u!222 &1871891757 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1871891754} + m_CullTransparentMesh: 0 +--- !u!1 &1909489377 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1909489380} + - component: {fileID: 1909489379} + - component: {fileID: 1909489378} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1909489378 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1909489377} + 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 &1909489379 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1909489377} + 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 &1909489380 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1909489377} + 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: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1982592444 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1982592445} + - component: {fileID: 1982592448} + - component: {fileID: 1982592447} + - component: {fileID: 1982592446} + m_Layer: 0 + m_Name: Sphere + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1982592445 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1982592444} + 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: 1163547443} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!135 &1982592446 +SphereCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1982592444} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Radius: 0.5 + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1982592447 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1982592444} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10303, 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_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &1982592448 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1982592444} + m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} +--- !u!224 &2004723107 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 224528275417451060, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + m_PrefabInstance: {fileID: 1223395833} + m_PrefabAsset: {fileID: 0} +--- !u!114 &2004723108 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 114400973501864318, guid: 154207b2fe8edf6469479d563d3e8e59, + type: 3} + m_PrefabInstance: {fileID: 1223395833} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5dabfd477c564c518af7ad4e2362742a, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &2005220180 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2005220181} + - component: {fileID: 2005220182} + - component: {fileID: 2005220183} + m_Layer: 0 + m_Name: StateHandlers + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2005220181 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2005220180} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 3.3839302, y: -0.5588294, z: -1.9372907} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 168782043} + - {fileID: 1771014850} + - {fileID: 121474008} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2005220182 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2005220180} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 731ae49d9a7e44078b9e9300c6c829c2, type: 3} + m_Name: + m_EditorClassIdentifier: + tutorialStateTrackers: + - {fileID: 168782042} + - {fileID: 1771014852} + - {fileID: 121474010} + debug: 0 +--- !u!114 &2005220183 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2005220180} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: bba432f912c64ce291ce3be12de22190, type: 3} + m_Name: + m_EditorClassIdentifier: + modelSource: {fileID: 2005220182} + treeView: {fileID: 2004723108} +--- !u!1 &2089696629 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2089696630} + - component: {fileID: 2089696631} + m_Layer: 0 + m_Name: Failure + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2089696630 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2089696629} + 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: 1771014850} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!82 &2089696631 +AudioSource: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2089696629} + m_Enabled: 1 + serializedVersion: 4 + OutputAudioMixerGroup: {fileID: 0} + m_audioClip: {fileID: 8300000, guid: 1ad39a45585989f4bb1a2e1be5b5a46d, type: 3} + m_PlayOnAwake: 0 + m_Volume: 1 + m_Pitch: 1 + Loop: 0 + Mute: 0 + Spatialize: 0 + SpatializePostEffects: 0 + Priority: 128 + DopplerLevel: 1 + MinDistance: 1 + MaxDistance: 500 + Pan2D: 0 + rolloffMode: 0 + BypassEffects: 0 + BypassListenerEffects: 0 + BypassReverbZones: 0 + rolloffCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + panLevelCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + spreadCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + reverbZoneMixCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/TutorialAssembly.unity.meta b/Assets/Plugins/UnityTutorialSystem/Scenes/TutorialAssembly.unity.meta new file mode 100644 index 0000000..8f1a12c --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/TutorialAssembly.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d8f8698187927e7458c0c8eb98a938eb +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/piano.wav b/Assets/Plugins/UnityTutorialSystem/Scenes/piano.wav new file mode 100644 index 0000000..27a9fb7 Binary files /dev/null and b/Assets/Plugins/UnityTutorialSystem/Scenes/piano.wav differ diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/piano.wav.meta b/Assets/Plugins/UnityTutorialSystem/Scenes/piano.wav.meta new file mode 100644 index 0000000..2e0606d --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/piano.wav.meta @@ -0,0 +1,22 @@ +fileFormatVersion: 2 +guid: b0fec8744b503ce47b10824d221e0727 +AudioImporter: + externalObjects: {} + serializedVersion: 6 + defaultSettings: + loadType: 0 + sampleRateSetting: 0 + sampleRateOverride: 44100 + compressionFormat: 1 + quality: 1 + conversionMode: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + preloadAudioData: 1 + loadInBackground: 0 + ambisonic: 0 + 3D: 1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/slam.wav b/Assets/Plugins/UnityTutorialSystem/Scenes/slam.wav new file mode 100644 index 0000000..61a68e1 Binary files /dev/null and b/Assets/Plugins/UnityTutorialSystem/Scenes/slam.wav differ diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/slam.wav.meta b/Assets/Plugins/UnityTutorialSystem/Scenes/slam.wav.meta new file mode 100644 index 0000000..8efc450 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/slam.wav.meta @@ -0,0 +1,22 @@ +fileFormatVersion: 2 +guid: 1ad39a45585989f4bb1a2e1be5b5a46d +AudioImporter: + externalObjects: {} + serializedVersion: 6 + defaultSettings: + loadType: 0 + sampleRateSetting: 0 + sampleRateOverride: 44100 + compressionFormat: 1 + quality: 1 + conversionMode: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + preloadAudioData: 1 + loadInBackground: 0 + ambisonic: 0 + 3D: 1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/tada3.mp3 b/Assets/Plugins/UnityTutorialSystem/Scenes/tada3.mp3 new file mode 100644 index 0000000..04152c3 Binary files /dev/null and b/Assets/Plugins/UnityTutorialSystem/Scenes/tada3.mp3 differ diff --git a/Assets/Plugins/UnityTutorialSystem/Scenes/tada3.mp3.meta b/Assets/Plugins/UnityTutorialSystem/Scenes/tada3.mp3.meta new file mode 100644 index 0000000..4e37e32 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scenes/tada3.mp3.meta @@ -0,0 +1,22 @@ +fileFormatVersion: 2 +guid: eea9c093ac8487942b9278ef0c512c40 +AudioImporter: + externalObjects: {} + serializedVersion: 6 + defaultSettings: + loadType: 0 + sampleRateSetting: 0 + sampleRateOverride: 44100 + compressionFormat: 1 + quality: 1 + conversionMode: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + preloadAudioData: 1 + loadInBackground: 0 + ambisonic: 0 + 3D: 1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts.meta b/Assets/Plugins/UnityTutorialSystem/Scripts.meta new file mode 100644 index 0000000..018c631 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3f390c25df9708145a55a5aa983cbbf3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators.meta new file mode 100644 index 0000000..0769487 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e4be03bec2444b3383709e9267f01a38 +timeCreated: 1546191377 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageAggregator.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageAggregator.cs new file mode 100644 index 0000000..9f99f80 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageAggregator.cs @@ -0,0 +1,252 @@ +using System.Collections.Generic; +using JetBrains.Annotations; +using NaughtyAttributes; +using UnityEngine; +using UnityEngine.Events; +using UnityTutorialSystem.Events; + +namespace UnityTutorialSystem.Aggregators +{ + /// + /// Aggregates low-level event stream messages into higher level aggregate events. + /// An typical EventMessageAggregator monitors one or more event streams to detect + /// predefined sequences of events in the stream. When an event sequence is fully + /// matched, the built-in events of this class can be used to fire a new event stream + /// message via an associated . + /// + /// + /// + /// An EventMessageAggregator follows a defined lifecycle. + /// + /// + /// During the event the aggregator will collect data from the + /// given configuration (usually a set of objects + /// injected into the property) and will build up any + /// matcher-specific internal data structures during repeated calls to + /// . As part of the initialization, the aggregator + /// will subscribe to the associated event streams of all monitored messages. + /// + /// + /// While the aggregation is active and not in a terminal state (success or failure) + /// this class will react to incoming s. Any + /// internal state change will trigger the event. + /// + /// + /// This implementation assumes that the set of receivable messages does not change + /// during the lifetime of the instance. + /// + /// + public abstract class EventMessageAggregator : MonoBehaviour, IEventMessageAggregator + { + readonly HashSet streams; + [SerializeField] [ReorderableList] protected List Messages; + [SerializeField] UnityEvent matchStarting; + [SerializeField] UnityEvent matchComplete; + [SerializeField] MatchProgressEvent matchProgress; + [SerializeField] bool debug; + + protected EventMessageAggregator() + { + streams = new HashSet(); + matchComplete = new UnityEvent(); + matchProgress = new MatchProgressEvent(); + } + + /// + /// This event is fired when the aggregator is ready to receive messages after this MonoBehaviour became active. + /// + public UnityEvent MatchStarting => matchStarting; + + /// + /// This event is fired when the aggregator has successfully finished matching events. Be aware that this event + /// is NOT fired when the matching fails with an error. To receive error information subscribe to the MatchProgress + /// event and check the sender's MatchResult property for failures. + /// + public UnityEvent MatchComplete => matchComplete; + + /// + /// This event is fired whenever any progress has been made. Any internal state change will always result in a + /// MatchProgress event. + /// + public MatchProgressEvent MatchProgress => matchProgress; + + /// + /// Resets the aggregator to the initial state as if no message has been received yet. + /// + public abstract void ResetMatch(); + + /// + /// Queries the internal state of the message aggregator. The given buffer will be filled with + /// structs containing the expected event in the order they are expected to be seen as well as flags indicating whether + /// the event has been seen or is expected to be seen next. + /// + /// A receive buffer. If null, a new list will be created. If the list is non-empty, the list will be cleared. + /// The buffer provided or a new list if the buffer given is null. + public abstract List ListEvents(List buffer = null); + + /// + /// Returns the current state of the matching process. + /// + public virtual EventMessageMatcherState MatchResult { get; protected set; } + + void Awake() + { + RegisterValidMessages(); + } + + /// + /// Registers all event messages. This method filters out any messages injected that are + /// either null or that have no associated. + /// + /// + /// This default processing of the injected event messages can be disabled by overriding + /// and returning false in that method. + /// + void RegisterValidMessages() + { + if (OnBeforeRegisterMessages()) + { + DebugLog("Registering .. " + name); + foreach (var m in Messages) + { + if (m == null) + { + continue; + } + + RegisterValidMessage(m); + if (m.Stream != null) + { + streams.Add(m.Stream); + } + else + { + Debug.LogError("Unable to process message that has no publishing stream. " + m); + } + } + } + + OnAfterRegisterMessages(); + } + + /// + /// An extension point to allow to skip the default message registration. + /// + /// true if the default message processing should commence, false otherwise. + protected virtual bool OnBeforeRegisterMessages() + { + return true; + } + + /// + /// An extension point to allow post-processing of the registered messages and the matcher state. + /// + protected virtual void OnAfterRegisterMessages() + { + } + + /// + /// A service callback to register the given message. The message is guaranteed to be non-null and + /// to have an associated event stream. + /// + /// The message + protected abstract void RegisterValidMessage([NotNull] BasicEventStreamMessage m); + + /// + /// Registers as listener to all known event streams and fires the MatchStarting event. + /// + protected virtual void OnEnable() + { + foreach (var stream in streams) + { + stream.ReceivedEvent.AddListener(OnEventReceivedWrapper); + } + + MatchStarting?.Invoke(); + } + + /// + /// Unregisters as listener from all known event streams. + /// + protected virtual void OnDisable() + { + foreach (var stream in streams) + { + stream.ReceivedEvent.RemoveListener(OnEventReceivedWrapper); + } + } + + /// + /// Callback that is invoked whenever one of the event streams generated a new message. If the message + /// received is not one of the defined messages for this aggregator or if the aggregator is in a terminal + /// state, the message will be ignored. + /// + /// The message received from the event streams + void OnEventReceivedWrapper(BasicEventStreamMessage message) + { + if (MatchResult != EventMessageMatcherState.Waiting) + { + DebugLog("Not Handling event " + message + " in " + gameObject.name + " -> " + MatchResult); + return; + } + + if (!Messages.Contains(message)) + { + return; + } + + if (OnEventReceived(message)) + { + DebugLog("Handling event " + message + " in " + gameObject.name); + MatchProgress?.Invoke(this, message); + } + else + { + DebugLog("Rejected event " + message + " in " + gameObject.name); + } + } + + /// + /// A callback used when event messages have been received from one of the underlying s. + /// + /// The message received from the event stream. + /// + protected abstract bool OnEventReceived(BasicEventStreamMessage received); + + /// + /// Filters the log messages by the debug flag. + /// + /// + void DebugLog(string message) + { +#if DEBUG + if (debug) + { + Debug.Log(name + ": " + message, this); + } +#endif + } + + /// + /// Simple helper function that ensures that the buffer used in ListEvents is correctly + /// initialised. If a list is + /// + /// a list buffer, or null to create a new buffer + /// The buffer or a new list. + [NotNull] protected static List EnsureBufferValid([CanBeNull] List buffer, int capacity = 0) + { + if (buffer == null) + { + buffer = new List(capacity); + } + else + { + buffer.Clear(); + buffer.Capacity = Mathf.Max(buffer.Capacity, capacity); + } + + return buffer; + } + + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageAggregator.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageAggregator.cs.meta new file mode 100644 index 0000000..fe8d605 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageAggregator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 16bf0b72df264fceb6d2a759afef5e0c +timeCreated: 1546273811 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageAggregatorStatePublisher.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageAggregatorStatePublisher.cs new file mode 100644 index 0000000..0d92cdf --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageAggregatorStatePublisher.cs @@ -0,0 +1,127 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Events; +using UnityTutorialSystem.Events; +using UnityTutorialSystem.UI; + +namespace UnityTutorialSystem.Aggregators +{ + /// + /// A companion for instances that monitors the + /// EventMessageAggregator and republishes the events as UnityEvents. The + /// is also used by the to detect parent-child relationships between + /// EventMessageAggregator instances. + /// If no is injected into the field, this + /// class will try to locate a EventMessageAggregator on the same GameObject. + /// + /// + public class EventMessageAggregatorStatePublisher : StreamEventSource + { + /// + /// Materialization of a generic UnityEvent. + /// + public class ProgressEvent : UnityEvent + { + } + + [SerializeField] EventMessageAggregator stateChain; + [SerializeField] BasicEventStreamMessage successMessage; + [SerializeField] ProgressEvent stateChanged; + + public EventMessageAggregatorStatePublisher() + { + stateChanged = new ProgressEvent(); + } + + /// + /// Republishes the EventMessageAggregator's matchProgress event. + /// + /// + public ProgressEvent StateChanged => stateChanged; + + /// + /// A BasicEventStreamMessage that is fired when the associated EventMessageAggregator successfully + /// finished its matching. The EventStream associated with this message will be considered a parent + /// stream by the EventStreamTreeModelBuilder. + /// + public BasicEventStreamMessage SuccessMessage => successMessage; + + /// + /// Republishes the associated EventMessageAggregator's current match result state. + /// + public EventMessageMatcherState MatchResult => stateChain.MatchResult; + + /// + /// Queries the internal state of the associated message aggregator. The given buffer will be filled + /// with structs containing the expected event in the order they are + /// expected to be seen as well as flags indicating whether the event has been seen or is expected to + /// be seen next. + /// + /// + /// A receive buffer. If null, a new list will be created. If the list is non-empty, + /// the list will be cleared. + /// + /// The buffer provided or a new list if the buffer given is null. + public List FetchEvents(List buffer) + { + return stateChain.ListEvents(buffer); + } + + void Awake() + { + if (stateChain == null) + { + stateChain = GetComponent(); + } + } + + void OnEnable() + { + if (stateChain != null) + { + stateChain.MatchStarting.AddListener(OnMatchStarting); + stateChain.MatchComplete.AddListener(OnMatchComplete); + stateChain.MatchProgress.AddListener(OnMatchProgress); + } + } + + void OnDisable() + { + if (stateChain != null) + { + stateChain.MatchStarting.RemoveListener(OnMatchStarting); + stateChain.MatchComplete.RemoveListener(OnMatchComplete); + stateChain.MatchProgress.RemoveListener(OnMatchProgress); + } + } + + /// + /// Checks whether the message given matches the success message that is fired when the + /// EventMessageAggregator successfully matches its events received. + /// + /// + /// + public override bool WillGenerateMessage(BasicEventStreamMessage msg) + { + return Equals(SuccessMessage, msg); + } + + void OnMatchStarting() + { + StateChanged.Invoke(this, null); + } + + void OnMatchProgress(EventMessageAggregator source, BasicEventStreamMessage message) + { + StateChanged.Invoke(this, message); + } + + void OnMatchComplete() + { + if (successMessage != null) + { + successMessage.Publish(); + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageAggregatorStatePublisher.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageAggregatorStatePublisher.cs.meta new file mode 100644 index 0000000..d1ef9dd --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageAggregatorStatePublisher.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7fb333aa63754b08a8a3c8327964d16b +timeCreated: 1546536562 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageCounter.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageCounter.cs new file mode 100644 index 0000000..b5fb2c6 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageCounter.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityTutorialSystem.Events; +using UnityTutorialSystem.Helpers; + +namespace UnityTutorialSystem.Aggregators +{ + /// + /// A simple example of a message aggregator. This class counts the incoming events that match the given message. + /// + public class EventMessageCounter : EventMessageAggregator + { + readonly HashSet> messagePool; + [SerializeField] int targetCount; + + public EventMessageCounter() + { + messagePool = new HashSet>(); + } + + public int Count { get; private set; } + + /// + protected override void RegisterValidMessage(BasicEventStreamMessage m) + { + messagePool.Add(new UnityObjectWrapper(m)); + } + + /// + public override void ResetMatch() + { + MatchResult = EventMessageMatcherState.Waiting; + Count = 0; + } + + /// + public override List ListEvents(List buffer = null) + { + buffer = EnsureBufferValid(buffer, Messages.Count); + + var completed = MatchResult == EventMessageMatcherState.Success; + var expected = MatchResult == EventMessageMatcherState.Waiting; + foreach (var m in Messages) + { + buffer.Add(new EventMessageState(m, completed, expected)); + } + + return buffer; + } + + /// + protected override bool OnEventReceived(BasicEventStreamMessage received) + { + if (!messagePool.Contains(new UnityObjectWrapper(received))) + { + return false; + } + + Count += 1; + if (targetCount == Count) + { + MatchResult = EventMessageMatcherState.Success; + MatchComplete?.Invoke(); + } + + return true; + + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageCounter.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageCounter.cs.meta new file mode 100644 index 0000000..4c73b81 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageCounter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 681f3afe2d0a4d42ac2722dbbb129213 +timeCreated: 1546191297 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageMatcherState.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageMatcherState.cs new file mode 100644 index 0000000..dc7ce17 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageMatcherState.cs @@ -0,0 +1,22 @@ +namespace UnityTutorialSystem.Aggregators +{ + /// + /// Indicates the current state of the matching process for a . + /// + /// + public enum EventMessageMatcherState + { + /// + /// Indicates that matching has not yet finished. + /// + Waiting, + /// + /// Indicates that matching has finished successfully. + /// + Success, + /// + /// Signals that matching failed at some point in the process. + /// + Failure + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageMatcherState.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageMatcherState.cs.meta new file mode 100644 index 0000000..45c45d4 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageMatcherState.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: eadd0d878bf0412fbd212abfc7686cbf +timeCreated: 1554221904 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageState.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageState.cs new file mode 100644 index 0000000..593f1d5 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageState.cs @@ -0,0 +1,36 @@ +using System; +using UnityTutorialSystem.Events; + +namespace UnityTutorialSystem.Aggregators +{ + /// + /// A struct representing the matching state of an EventMessageAggregator. + /// + public struct EventMessageState + { + /// + /// The event stream message represented by this state. + /// + public readonly BasicEventStreamMessage Message; + /// + /// Has this message been seen by the aggregator? + /// + public readonly bool Completed; + /// + /// Is this one of the messages the aggregator expects to receive next? + /// + public readonly bool ExpectedNext; + + public EventMessageState(BasicEventStreamMessage message, bool completed, bool expectedNext) + { + if (message == null) + { + throw new ArgumentNullException(nameof(message)); + } + + Message = message; + Completed = completed; + ExpectedNext = expectedNext; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageState.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageState.cs.meta new file mode 100644 index 0000000..b3c8f5b --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventMessageState.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fd79870684344d349dddc68c6b84268c +timeCreated: 1555687075 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventSequenceAggregator.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventSequenceAggregator.cs new file mode 100644 index 0000000..2dbdaef --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventSequenceAggregator.cs @@ -0,0 +1,162 @@ +using System.Collections.Generic; +using JetBrains.Annotations; +using NaughtyAttributes; +using UnityEngine; +using UnityEngine.Events; +using UnityTutorialSystem.Events; + +namespace UnityTutorialSystem.Aggregators +{ + /// + /// A event sequence matcher. The matcher checks incoming events against a + /// predefined sequence of events. If the matching is strict, any incoming event + /// that does not match the expected event will mark the sequence as failed. + /// A non-strict matcher will simply ignore events that do not match and will + /// patiently wait until it sees a suitable next event. Therefore non-strict matchers will + /// never fire a match-failed event. + /// + /// + /// Acceptable events are stored in the 'validMessages' list. + /// This class tracks each received message in a list of flags, one entry for each + /// accepted message. The success message is fired when all events have been seen at + /// least once. + /// + public class EventSequenceAggregator : EventMessageAggregator + { + /// + /// Defines the validation mode for this aggregator. + /// + public enum ValidationMode + { + /// + /// Requests lenient matching. A lenient matcher will ignore out of order events. + /// + [UsedImplicitly] Lenient = 0, + /// + /// Requests that the matcher accepts events in a relaxed order. Events that form a + /// series of events that all are marked as out-of-order executable will be treated + /// as an event set instead of an event list. Out of order processing will not skip + /// events that are not marked for out of order execution. + /// + AllowOutOfOrderEvents = 1, + /// + /// Requires strict matching. Any event not seen in the correct order will mark the + /// aggregator as failed. + /// + Strict = 2 + } + + readonly List validMessages; + readonly List matchState; + + [SerializeField] UnityEvent matchFailed; + [SerializeField] ValidationMode mode; + [ShowNonSerializedField] int nextEvent; + + public EventSequenceAggregator() + { + validMessages = new List(); + matchState = new List(); + } + + /// + protected override void RegisterValidMessage(BasicEventStreamMessage m) + { + validMessages.Add(m); + matchState.Add(false); + } + + /// + public override void ResetMatch() + { + nextEvent = 0; + MatchResult = EventMessageMatcherState.Waiting; + + for (var i = 0; i < matchState.Count; i++) + { + matchState[i] = false; + } + } + + /// + public override List ListEvents(List buffer = null) + { + buffer = EnsureBufferValid(buffer, Messages.Count); + + for (var index = 0; index < validMessages.Count; index++) + { + var m = validMessages[index]; + buffer.Add(new EventMessageState(m, matchState[index], enabled && (index == nextEvent))); + } + + return buffer; + } + + /// + protected override bool OnEventReceived(BasicEventStreamMessage messageReceived) + { + if (nextEvent >= validMessages.Count) + { + return false; + } + + var nextEventMessage = validMessages[nextEvent]; + if (messageReceived == nextEventMessage) + { + matchState[nextEvent] = true; + nextEvent = FindNextOpenEvent(); + if (nextEvent == validMessages.Count) + { + MatchResult = EventMessageMatcherState.Success; + MatchComplete?.Invoke(); + } + + return true; + } + + switch (mode) + { + case ValidationMode.AllowOutOfOrderEvents: + { + for (var idx = nextEvent + 1; idx < validMessages.Count; idx += 1) + { + var msg = validMessages[idx]; + if (!msg.AllowOutOfOrderExecution) + { + break; + } + + if (msg == messageReceived && !matchState[idx]) + { + matchState[idx] = true; + return true; + } + } + + break; + } + case ValidationMode.Strict: + { + MatchResult = EventMessageMatcherState.Failure; + matchFailed?.Invoke(); + return true; + } + } + + return false; + } + + int FindNextOpenEvent() + { + for (var idx = nextEvent + 1; idx < validMessages.Count; idx += 1) + { + if (matchState[idx] == false) + { + return idx; + } + } + + return validMessages.Count; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventSequenceAggregator.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventSequenceAggregator.cs.meta new file mode 100644 index 0000000..2eb5db7 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventSequenceAggregator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: dfb04f096c9c4ca387330c23be4262f1 +timeCreated: 1546192635 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventSetAggregator.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventSetAggregator.cs new file mode 100644 index 0000000..aec45e7 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventSetAggregator.cs @@ -0,0 +1,130 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Events; +using UnityTutorialSystem.Events; + +namespace UnityTutorialSystem.Aggregators +{ + /// + /// + /// An aggregator that waits for all events to occur. The events can + /// occur in any order. If strict mode is enabled, a non-matching + /// event will fail this aggregator. + /// + /// + /// Duplicate declared messages will be collated into a single expected message. + /// To match multiple messages of the same type, use a + /// as a child matcher. + /// + /// + public class EventSetAggregator : EventMessageAggregator + { + /// + /// Defines how strict incoming messages are matched against the set of + /// received messages. + /// + public enum MatchMode + { + /// + /// Requests an lenient matching mode. Duplicate messages will be ignored. + /// + Lenient = 0, + /// + /// Requires strict matching. Any duplicate event received will fail the + /// aggregator. + /// + Strict = 2 + } + + readonly Dictionary matchState; + readonly List messages; + + [SerializeField] UnityEvent matchFailed; + [SerializeField] MatchMode matchMode; + int matchCount; + + public EventSetAggregator() + { + matchState = new Dictionary(); + messages = new List(); + } + + /// + protected override void RegisterValidMessage(BasicEventStreamMessage m) + { + if (matchState.ContainsKey(m)) + { + return; + } + + messages.Add(m); + matchState[m] = false; + } + + /// + public override void ResetMatch() + { + foreach (var k in matchState) + { + matchState[k.Key] = false; + } + + MatchResult = EventMessageMatcherState.Waiting; + matchCount = 0; + } + + /// + protected override bool OnEventReceived(BasicEventStreamMessage messageReceived) + { + if (matchCount == matchState.Count) + { + return false; + } + + bool matching; + if (!matchState.TryGetValue(messageReceived, out matching)) + { + // no such element in the list of possible matches. + return false; + } + + if (matching) + { + if (matchMode == MatchMode.Strict) + { + MatchResult = EventMessageMatcherState.Failure; + matchFailed?.Invoke(); + return true; + } + + // repeated invocations of the same event should not trigger the alarm. + return false; + } + + matchState[messageReceived] = true; + matchCount += 1; + if (matchCount == matchState.Count) + { + MatchResult = EventMessageMatcherState.Success; + MatchComplete?.Invoke(); + } + + return true; + } + + /// + public override List ListEvents(List buffer = null) + { + buffer = EnsureBufferValid(buffer, messages.Count); + + foreach (var m in messages) + { + bool matchCompleted; + matchState.TryGetValue(m, out matchCompleted); + buffer.Add(new EventMessageState(m, matchCompleted, enabled && !matchCompleted)); + } + + return buffer; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventSetAggregator.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventSetAggregator.cs.meta new file mode 100644 index 0000000..73a3f7d --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/EventSetAggregator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8f0a408106974c8d87c1327fb3471f9b +timeCreated: 1546194648 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/IEventMessageAggregator.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/IEventMessageAggregator.cs new file mode 100644 index 0000000..db6e34a --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/IEventMessageAggregator.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; +using UnityEngine.Events; +using UnityTutorialSystem.Events; + +namespace UnityTutorialSystem.Aggregators +{ + /// + /// Aggregates low-level event stream messages into higher level aggregate events. + /// An typical EventMessageAggregator monitors one or more event streams to detect + /// predefined sequences of events in the stream. When an event sequence is fully + /// matched, the built-in events of this class can be used to fire a new event stream + /// message via an associated . + /// + /// + /// This interface primarily exists for unit testing purposes. + /// + public interface IEventMessageAggregator + { + /// + /// This event is fired when the aggregator is ready to receive messages after this MonoBehaviour became active. + /// + UnityEvent MatchStarting { get; } + + /// + /// This event is fired when the aggregator has successfully finished matching events. Be aware that this event + /// is NOT fired when the matching fails with an error. To receive error information subscribe to the MatchProgress + /// event and check the sender's MatchResult property for failures. + /// + UnityEvent MatchComplete { get; } + + /// + /// This event is fired whenever any progress has been made. Any internal state change will always result in a + /// MatchProgress event. + /// + MatchProgressEvent MatchProgress { get; } + + /// + /// Resets the aggregator to the initial state as if no message has been received yet. + /// + void ResetMatch(); + + /// + /// Queries the internal state of the message aggregator. The given buffer will be filled with + /// structs containing the expected event in the order they are expected to be seen as well as flags indicating whether + /// the event has been seen or is expected to be seen next. + /// + /// A receive buffer. If null, a new list will be created. If the list is non-empty, the list will be cleared. + /// The buffer provided or a new list if the buffer given is null. + List ListEvents(List buffer = null); + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/IEventMessageAggregator.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/IEventMessageAggregator.cs.meta new file mode 100644 index 0000000..6f39f45 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/IEventMessageAggregator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5d52b262cfc940eaa2cc2b224d9e9be2 +timeCreated: 1546273478 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/MatchProgressEvent.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/MatchProgressEvent.cs new file mode 100644 index 0000000..6ba2e4f --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/MatchProgressEvent.cs @@ -0,0 +1,15 @@ +using UnityEngine.Events; +using UnityTutorialSystem.Events; + +namespace UnityTutorialSystem.Aggregators +{ + /// + /// MatchProgressEvents are fired every time the state of an changes. + /// + /// + /// This is an empty materialization of a generic UnityEvent as Unity cannot handle generics well. + /// + public class MatchProgressEvent : UnityEvent + { + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/MatchProgressEvent.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/MatchProgressEvent.cs.meta new file mode 100644 index 0000000..69c454e --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/MatchProgressEvent.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 446436bec03f4270a10deca2357c50ad +timeCreated: 1554219269 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/OneOfEventSetAggregator.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/OneOfEventSetAggregator.cs new file mode 100644 index 0000000..fc6b66e --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/OneOfEventSetAggregator.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using UnityTutorialSystem.Events; + +namespace UnityTutorialSystem.Aggregators +{ + /// + /// An aggregator component that waits for any of the given messages and fires a + /// success message if at least one of the listed messages has been encountered. + /// + public class OneOfEventSetAggregator : EventMessageAggregator + { + readonly List messages; + readonly HashSet matchState; + int matchCount; + + public OneOfEventSetAggregator() + { + matchState = new HashSet(); + messages = new List(); + } + + /// + protected override void RegisterValidMessage(BasicEventStreamMessage m) + { + if (matchState.Add(m)) + { + messages.Add(m); + } + } + + /// + public override void ResetMatch() + { + MatchResult = EventMessageMatcherState.Waiting; + matchCount = 0; + } + + /// + protected override bool OnEventReceived(BasicEventStreamMessage messageReceived) + { + if (matchCount > 0) + { + return false; + } + + if (matchState.Contains(messageReceived)) + { + MatchResult = EventMessageMatcherState.Success; + MatchComplete?.Invoke(); + + matchCount += 1; + return true; + } + + return false; + } + + /// + public override List ListEvents(List buffer = null) + { + if (buffer == null) + { + buffer = new List(messages.Count); + } + else + { + buffer.Clear(); + buffer.Capacity = Math.Max(buffer.Capacity, messages.Count); + } + + var next = MatchResult == EventMessageMatcherState.Waiting; + var completed = MatchResult == EventMessageMatcherState.Success; + foreach (var m in messages) + { + buffer.Add(new EventMessageState(m, completed, enabled && next)); + } + + return buffer; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/OneOfEventSetAggregator.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/OneOfEventSetAggregator.cs.meta new file mode 100644 index 0000000..93f63c5 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Aggregators/OneOfEventSetAggregator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4b936e148a754716a66b12da9c791232 +timeCreated: 1546272706 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Events.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Events.meta new file mode 100644 index 0000000..dc941ff --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Events.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2d6107e4f8a94ce689a8e8c4b0f73e71 +timeCreated: 1546191053 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Events/BasicEventStream.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/BasicEventStream.cs new file mode 100644 index 0000000..ca6917a --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/BasicEventStream.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; +using JetBrains.Annotations; +using NaughtyAttributes; +using UnityEngine; +using UnityEngine.Events; + +namespace UnityTutorialSystem.Events +{ + /// + /// A event stream publishes preconfigured messages. Both the event stream and the + /// messages are s defined as assets in the Unity editor. + /// Each message defined for an event stream object contains a reference to the event + /// stream that declared it. You can publish the message via its + /// method. + /// + /// + /// Publishing messages on an EventStreams is a reentrant operation. Messages are guaranteed + /// to be sent in the order received. If - as an result of an published message - a listener + /// of this stream publishes new messages these messages will be processed after all other pending + /// messages have been finished. This class enforces a hard limit of 250 processed message per + /// message cascade. Any excess message will be dropped. + /// + [CreateAssetMenu(menuName = "Event Stream/Event Stream")] + public class BasicEventStream : ScriptableObject + { + [SerializeField] bool ignoreForNextEventIndicatorHint; + [SerializeField] [ReorderableList] List messageTypes; + [SerializeField] bool debug; + + [NonSerialized] readonly Queue queuedMessages; + [NonSerialized] bool processingMessage; + + public BasicEventStream() + { + messageTypes = new List(); + receivedEvent = new EventStreamReceivedEvent(); + queuedMessages = new Queue(); + processingMessage = false; + } + + /// + /// A flag defining that messages defined by this event stream should not be used to + /// display visual indicators for actions that generate the next events. Use this + /// for events that represent internal state. Remember that aggregator implementations + /// can track events from multiple sources. + /// + public bool IgnoreForNextEventIndicatorHint => ignoreForNextEventIndicatorHint; + + /// + /// Checks whether the message given is a valid message that belongs to this event stream. + /// + /// the message being tested + /// + public virtual bool IsValidMessage([CanBeNull] BasicEventStreamMessage msg) + { + return msg != null && messageTypes.Contains(msg.name); + } + + void Awake() + { + processingMessage = false; + } + +#if UNITY_EDITOR + /// + /// An editor function to generate message objects from the list of messages defined in . + /// + [Button("Generate Message Handles")] + [UsedImplicitly] + internal void Regenerate() + { + var retainedNodes = BasicEventStreamEditorSupport.CleanGraph(this); + var generatedNodes = new List(); + + foreach (var node in messageTypes) + { + if (node == null) + { + continue; + } + + BasicEventStreamMessage streamNode; + if (retainedNodes.TryGetValue(node, out streamNode)) + { + streamNode.SetUpStream(this); + continue; + } + + var msg = CreateNode(); + msg.name = node; + msg.SetUpStream(this); + generatedNodes.Add(msg); + } + + BasicEventStreamEditorSupport.GenerateNodes(this, generatedNodes); + } + + /// + /// A factory function to create new message event sub-objects. + /// + /// the newly created message object + protected virtual BasicEventStreamMessage CreateNode() + { + return CreateInstance(); + } +#endif + + /// + /// Publishes the message if the message given is defined by this event stream. + /// Publishing is a reentrant operation and newly generated messages will be + /// processed in the order they are received. This method will not process more than + /// 250 messages in a single cascade. + /// + /// the message being published + public void Publish(BasicEventStreamMessage msg) + { + if (msg.Stream != this) + { + return; + } + + if (processingMessage) + { + if (queuedMessages.Count > 250) + { + Debug.LogError("More than 250 messages in a single cascade. Aborting."); + return; + } + + DebugLog("=== Queue message " + msg); + queuedMessages.Enqueue(msg); + } + else + { + processingMessage = true; + try + { + DebugLog("=== Begin Publish message " + msg); + ReceivedEvent?.Invoke(msg); + DebugLog("=== End Publish message " + msg); + + var cascadeCount = 0; + while (cascadeCount < 250 && queuedMessages.Count > 0) + { + var message = queuedMessages.Dequeue(); + DebugLog("=== Begin Publish queued message " + message); + ReceivedEvent?.Invoke(message); + DebugLog("=== End Publish queued message " + message); + cascadeCount += 1; + } + + queuedMessages.Clear(); + } + finally + { + processingMessage = false; + } + } + } + + void DebugLog(string message) + { +#if DEBUG + if (debug) + { + Debug.Log(message, this); + } +#endif + } + + #region ReceivedEvent + + /// + /// Unity cannot serialize or deserialize generic classes. So to use a generic class, + /// we have to derive a concrete (aka non-generic) subclass for it. Oh, well .. + /// + [UsedImplicitly] + class EventStreamReceivedEvent : UnityEvent + { + } + + [SerializeField] EventStreamReceivedEvent receivedEvent; + + /// + /// Subscribe to the ReceivedEvent event to get notified when a new message has been + /// published. + /// + public UnityEvent ReceivedEvent => receivedEvent; + + #endregion + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Events/BasicEventStream.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/BasicEventStream.cs.meta new file mode 100644 index 0000000..794e97f --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/BasicEventStream.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0efa5601f9e59ab4990baf4ac245a6dc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Events/BasicEventStreamEditorSupport.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/BasicEventStreamEditorSupport.cs new file mode 100644 index 0000000..0ad5796 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/BasicEventStreamEditorSupport.cs @@ -0,0 +1,92 @@ +#if UNITY_EDITOR +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace UnityTutorialSystem.Events +{ + /// + /// Support code for creating event message sub-objects on BasicEventStream assets. + /// This is an editor-only class containing helper methods used by the BasicEventStream + /// editor callbacks. + /// + public static class BasicEventStreamEditorSupport + { + /// + /// Removes all nodes that are no longer part of the stream's set of defined event types. + /// The list returned contains all retained nodes that continue to be valid. + /// + /// The event stream being processed + /// A buffer of retained message nodes keyed by their name + /// + public static Dictionary CleanGraph(BasicEventStream eventStream, + Dictionary retainedNodes = null) + { + if (retainedNodes == null) + { + retainedNodes = new Dictionary(); + } + + if (eventStream == null) + { + Debug.Log("Not a graph"); + return retainedNodes; + } + + var assetPath = AssetDatabase.GetAssetPath(eventStream); + foreach (var asset in AssetDatabase.LoadAllAssetsAtPath(assetPath)) + { + if (asset == null) + { + continue; + } + + if (asset == eventStream) + { + continue; + } + + + var node = asset as BasicEventStreamMessage; + if (node != null) + { + if (eventStream.IsValidMessage(node)) + { + Debug.Log("Retained asset " + asset + " of type " + asset.GetType()); + retainedNodes.Add(node.name, node); + } + else + { + Debug.LogWarning("Destroyed asset " + node); + Object.DestroyImmediate(node, true); + } + } + else + { + Debug.LogWarning("Destroyed foreign asset " + asset); + Object.DestroyImmediate(asset, true); + } + } + + return retainedNodes; + } + + /// + /// Adds the given list of generated nodes as sub-objects to the event stream asset. + /// + /// The event stream + /// The nodes that should be added to the stream asset + public static void GenerateNodes(BasicEventStream basicEventStream, + List generatedNodes) + { + foreach (var n in generatedNodes) + { + EditorUtility.SetDirty(n); + AssetDatabase.AddObjectToAsset(n, basicEventStream); + } + + EditorUtility.SetDirty(basicEventStream); + } + } +} +#endif diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Events/BasicEventStreamEditorSupport.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/BasicEventStreamEditorSupport.cs.meta new file mode 100644 index 0000000..7059a03 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/BasicEventStreamEditorSupport.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d58ffcfc50c1437dabc7fb649e22d7e2 +timeCreated: 1546104978 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Events/BasicEventStreamMessage.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/BasicEventStreamMessage.cs new file mode 100644 index 0000000..7c1ca7f --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/BasicEventStreamMessage.cs @@ -0,0 +1,53 @@ +using NaughtyAttributes; +using UnityEngine; + +namespace UnityTutorialSystem.Events +{ + /// + /// The BasicEventStreamMessage is a generic message emitted by a BasicEventStream. + /// Messages are identified by their asset name. Each message holds a reference to the + /// message stream that can publish it. Use the method to send + /// this event to all subscribers of the message stream. + /// + public class BasicEventStreamMessage : ScriptableObject + { + [SerializeField] [ReadOnly] BasicEventStream stream; + [SerializeField] bool allowOutOfOrderExecution; + + /// + /// Defines whether this message accepts out-of-order processing of sibling events in the + /// same event message aggregator. + /// + public bool AllowOutOfOrderExecution => allowOutOfOrderExecution; + + /// + /// The message stream associated with this message. + /// + public BasicEventStream Stream + { + get => stream; + protected set => stream = value; + } + + /// + /// A simple non-public entry point so that BasicEventStreams can + /// pass itself to instances of this class at design time. + /// + /// + internal void SetUpStream(BasicEventStream eventStream) + { + stream = eventStream; + } + + /// + /// Publishes the message to the associated stream. + /// + public void Publish() + { + if (stream != null) + { + stream.Publish(this); + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Events/BasicEventStreamMessage.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/BasicEventStreamMessage.cs.meta new file mode 100644 index 0000000..b4c404c --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/BasicEventStreamMessage.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 83707740ea9a4854b2b1651e53c42c0b +timeCreated: 1546010922 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Events/PublishStreamEvent.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/PublishStreamEvent.cs new file mode 100644 index 0000000..fcc1bfa --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/PublishStreamEvent.cs @@ -0,0 +1,44 @@ +using JetBrains.Annotations; +using UnityEngine; + +namespace UnityTutorialSystem.Events +{ + /// + /// This class exists as an trigger to fire events from UnityEvent bindings. + /// Attach this class to your game object and in your custom scripts, fire + /// an event that calls the TriggerEvent method. + /// The message defined in the inspector will be published to the message's + /// associated event stream. From there aggregators and reactors can pick up + /// the state change that has been signaled here. + /// Architectural note: Messages do not carry source object information. At + /// the moment they also do not carry any parameter information. This is a + /// deliberate act, as event stream messages are not intended to replace + /// normal event processing. The messages defined in this package are used + /// to provide analytics, achievement and tutorial state triggers only. + /// + public class PublishStreamEvent : StreamEventSource + { + [SerializeField] BasicEventStreamMessage message; + + /// + public override bool WillGenerateMessage(BasicEventStreamMessage msg) + { + return Equals(message, msg); + } + + /// + /// Fires the associated message to it's stream. This method is indented to be + /// called as part of some form of event handling in your target objects. + /// Trigger it when the success conditions for the task represented by the + /// given message is met. + /// + [UsedImplicitly] + public void TriggerEvent() + { + if (message != null) + { + message.Publish(); + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Events/PublishStreamEvent.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/PublishStreamEvent.cs.meta new file mode 100644 index 0000000..ddc6a5e --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/PublishStreamEvent.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 707a12fe3b5f46afa91e26f91d81b0ef +timeCreated: 1546107365 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Events/StaticStreamEventSource.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/StaticStreamEventSource.cs new file mode 100644 index 0000000..e901e60 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/StaticStreamEventSource.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace UnityTutorialSystem.Events +{ + /// + /// A stream event source that checks against a set of messages. Use this + /// if you need to indicate state or trigger common behaviour for more than one + /// message source. + /// + public class StaticStreamEventSource : StreamEventSource + { + [SerializeField] List messages; + + public override bool WillGenerateMessage(BasicEventStreamMessage msg) + { + return (messages != null) && messages.Contains(msg); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Events/StaticStreamEventSource.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/StaticStreamEventSource.cs.meta new file mode 100644 index 0000000..f823f8f --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/StaticStreamEventSource.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1609f2334944417ca2505b738c497f96 +timeCreated: 1547575735 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Events/StreamEventSource.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/StreamEventSource.cs new file mode 100644 index 0000000..27489b0 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/StreamEventSource.cs @@ -0,0 +1,21 @@ +using UnityEngine; + +namespace UnityTutorialSystem.Events +{ + /// + /// A base type for all MonoBehaviours that can activate EventStream messages. + /// StreamEventSources are referenced by the NextEvent-predictor system to + /// simplify the wiring up of event cascades. + /// + public abstract class StreamEventSource : MonoBehaviour + { + /// + /// Checks whether the message given will be generated by is source. The + /// NextEventSelector implementations will use this method to locate components + /// that could trigger the event in question. + /// + /// The message object to be evaluated + /// true if the source will generate this message, false otherwise. + public abstract bool WillGenerateMessage(BasicEventStreamMessage msg); + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Events/StreamEventSource.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/StreamEventSource.cs.meta new file mode 100644 index 0000000..37d9b4d --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Events/StreamEventSource.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 20861c5f9f5e433783fa0cead6cc2341 +timeCreated: 1547574890 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers.meta new file mode 100644 index 0000000..9d95c4b --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 73edf1b61f9a45549bfbd64643c828a8 +timeCreated: 1546273434 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/DictionaryUtility.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/DictionaryUtility.cs new file mode 100644 index 0000000..e315e5e --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/DictionaryUtility.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; + +namespace UnityTutorialSystem.Helpers +{ + /// + /// Dictionary helper methods. + /// + public static class DictionaryUtility + { + /// + /// Implements the missing AddRange method found in other collection classes. + /// This implementation preserves the actual type of the dictionary implementation + /// so that we dont end up with boxed or up-casted instances. + /// + /// + /// + /// + /// + /// + public static Dictionary AddRange(this Dictionary target, Dictionary source) + { + return AddRange, Dictionary, TKey, TValue>(target, source); + } + /// + /// Implements the missing AddRange method found in other collection classes. + /// This implementation preserves the actual type of the dictionary implementation + /// so that we dont end up with boxed or up-casted instances. + /// + /// + /// + /// + /// + /// + /// + /// + public static TDictionary AddRange(this TDictionary target, TEnumerable source) + where TDictionary: IDictionary + where TEnumerable: IEnumerable> + { + foreach (var s in source) + { + target.Add(s.Key, s.Value); + } + + return target; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/DictionaryUtility.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/DictionaryUtility.cs.meta new file mode 100644 index 0000000..f4ac21a --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/DictionaryUtility.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 53b979b9c1384ca3aa02da3ac040d6d1 +timeCreated: 1555351610 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/MouseEventPublisher.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/MouseEventPublisher.cs new file mode 100644 index 0000000..372fd17 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/MouseEventPublisher.cs @@ -0,0 +1,40 @@ +using UnityEngine; +using UnityEngine.Events; + +namespace UnityTutorialSystem.Helpers +{ + /// + /// A basic helper object that republishes incoming Unity event messages as + /// proper s. + /// + public class MouseEventPublisher : MonoBehaviour + { + /// + /// Republishes framework events received from clicks. + /// + public UnityEvent Clicked; + /// + /// Republishes framework events received from MouseEntered events. + /// + public UnityEvent MouseEntered; + /// + /// Republishes framework events received from MouseExited events. + /// + public UnityEvent MouseExited; + + void OnMouseUp() + { + Clicked?.Invoke(); + } + + void OnMouseEnter() + { + MouseEntered?.Invoke(); + } + + void OnMouseExit() + { + MouseExited?.Invoke(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/MouseEventPublisher.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/MouseEventPublisher.cs.meta new file mode 100644 index 0000000..7595fee --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/MouseEventPublisher.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3c2f7fb44e844d968edd605a04aa2f80 +timeCreated: 1546189089 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/SharedMethods.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/SharedMethods.cs new file mode 100644 index 0000000..f16df51 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/SharedMethods.cs @@ -0,0 +1,96 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.SceneManagement; + +namespace UnityTutorialSystem.Helpers +{ + /// + /// Copied from VRTK_SharedMethods class (MIT License). + /// + public static class SharedMethods + { + /// + /// Finds all components of a given type. + /// + /// + /// This method returns components from active as well as inactive GameObjects in all scenes. It doesn't return assets. + /// For performance reasons it is recommended to not use this function every frame. Cache the result in a member + /// variable at startup instead. + /// + /// The component type to search for. Must be a subclass of `Component`. + /// + /// If this is true, all loaded scenes will be searched. If this is false, only the active + /// scene will be searched. + /// + /// All the found components. If no component is found an empty array is returned. + public static T[] FindEvenInactiveComponents(bool searchAllScenes = false) where T : Component + { + var results = FindEvenInactiveComponentsInValidScenes(searchAllScenes); + return results.ToArray(); + } + + /// + /// The FindEvenInactiveComponentsInLoadedScenes method searches active and inactive game objects in all + /// loaded scenes for components matching the type supplied. + /// + /// If true, will search all loaded scenes, otherwise just the active scene. + /// If true, will stop searching objects as soon as a match is found. + /// + static IEnumerable FindEvenInactiveComponentsInValidScenes(bool searchAllScenes, bool stopOnMatch = false) where T : Component + { + IEnumerable results; + if (searchAllScenes) + { + var allSceneResults = new List(); + for (var sceneIndex = 0; sceneIndex < SceneManager.sceneCount; sceneIndex++) + { + allSceneResults.AddRange(FindEvenInactiveComponentsInScene(SceneManager.GetSceneAt(sceneIndex), stopOnMatch)); + } + + results = allSceneResults; + } + else + { + results = FindEvenInactiveComponentsInScene(SceneManager.GetActiveScene(), stopOnMatch); + } + + return results; + } + + /// + /// The FIndEvenInactiveComponentsInScene method searches the specified scene for components matching the type + /// supplied. + /// + /// The scene to search. This scene must be valid, either loaded or loading. + /// If true, will stop searching objects as soon as a match is found. + /// + static IEnumerable FindEvenInactiveComponentsInScene(Scene scene, bool stopOnMatch = false) + { + var results = new List(); + if (!scene.isLoaded) + { + return results; + } + + foreach (var rootObject in scene.GetRootGameObjects()) + { + if (stopOnMatch) + { + var foundComponent = rootObject.GetComponentInChildren(true); + if (foundComponent != null) + { + results.Add(foundComponent); + return results; + } + } + else + { + results.AddRange(rootObject.GetComponentsInChildren(true)); + } + } + + return results; + } + } +} diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/SharedMethods.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/SharedMethods.cs.meta new file mode 100644 index 0000000..9f3cdf0 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/SharedMethods.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a1ff3d1bca2f4a429d42124df87e4716 +timeCreated: 1547576788 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/UnityObjectWrapper.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/UnityObjectWrapper.cs new file mode 100644 index 0000000..a7092ef --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/UnityObjectWrapper.cs @@ -0,0 +1,67 @@ +using System; +using JetBrains.Annotations; + +namespace UnityTutorialSystem.Helpers +{ + /// + /// An object wrapper for UnityObjects that compares objects based on + /// instance-id instead of low level Equals calls. The + /// implementation calls into the native code for no sane reason, which + /// can be performance critical. + /// + /// + public struct UnityObjectWrapper where T: UnityEngine.Object + { + [NotNull] public readonly T Value; + + public UnityObjectWrapper(T value) + { + // ReSharper disable once JoinNullCheckWithUsage + if (ReferenceEquals(value, null)) + { + throw new ArgumentNullException(); + } + Value = value; + } + + public bool Equals(UnityObjectWrapper other) + { + return Equals(Value.GetInstanceID(), other.Value.GetInstanceID()); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + return obj is UnityObjectWrapper other && Equals(other); + } + + public override int GetHashCode() + { + return Value.GetHashCode(); + } + + /// + /// Implicitly wraps the given UnityObject into an ObjectWrapper. + /// + /// the object to wrap + /// The UnityObjectWrapper for the given Unity-Object. + public static implicit operator UnityObjectWrapper(T w) + { + return new UnityObjectWrapper(w); + } + + /// + /// Implicitly unwraps the wrapper into the contained Unity object. + /// + /// An object wrapper containing a non-null Unity object + /// the unwrapped object + public static implicit operator T (UnityObjectWrapper w) + { + return w.Value; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/UnityObjectWrapper.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/UnityObjectWrapper.cs.meta new file mode 100644 index 0000000..1a055b6 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Helpers/UnityObjectWrapper.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a56c930883ad40f690e5eafe4535d08f +timeCreated: 1554223107 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors.meta new file mode 100644 index 0000000..ce44e7e --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e91d42edb55347d883dcf906f55b7478 +timeCreated: 1555688144 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors/NextEventAggregationActivator.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors/NextEventAggregationActivator.cs new file mode 100644 index 0000000..3f15e3b --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors/NextEventAggregationActivator.cs @@ -0,0 +1,49 @@ +using UnityEngine; +using UnityTutorialSystem.Aggregators; +using UnityTutorialSystem.Events; + +namespace UnityTutorialSystem.Predictors +{ + /// + /// An low-maintenance event aggregation activator for activating dependent + /// EventMessageAggregator instances. Add this to a child-level aggregator + /// that is paired with a , usually a + /// . This will selectively enable the + /// aggregator while the parent stream expects the aggregator's result event message + /// as one of its next messages. + /// + [RequireComponent(typeof(StreamEventSource))] + [RequireComponent(typeof(EventMessageAggregator))] + public class NextEventAggregationActivator : NextEventSelectorBase + { + EventMessageAggregator target; + StreamEventSource nextMessageSource; + + protected override bool AutoPopulate => true; + + protected override StreamEventSource NextMessageSource => nextMessageSource; + + void Awake() + { + nextMessageSource = GetComponent(); + target = GetComponent(); + target.enabled = false; + } + + protected override void OnEnableForNextMessage() + { + if (target != null) + { + target.enabled = true; + } + } + + protected override void OnDisableForNextMessage() + { + if (target != null) + { + target.enabled = false; + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors/NextEventAggregationActivator.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors/NextEventAggregationActivator.cs.meta new file mode 100644 index 0000000..36ca119 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors/NextEventAggregationActivator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 639079f633a24c1cba6733ee5e559bc2 +timeCreated: 1547587926 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors/NextEventSelector.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors/NextEventSelector.cs new file mode 100644 index 0000000..0750aa3 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors/NextEventSelector.cs @@ -0,0 +1,45 @@ +using UnityEngine; +using UnityEngine.Events; +using UnityTutorialSystem.Aggregators; +using UnityTutorialSystem.Events; + +namespace UnityTutorialSystem.Predictors +{ + /// + /// + /// A general purpose next-event selector. Use this to fire events when the event produced + /// by the given StreamEventSource is one of the next + /// expected messages of the collaborating s. + /// + /// + /// One usual use for this class is to activate and deactivate visual indicators that guide + /// the player to the location of the next task that should be done. + /// + /// + public class NextEventSelector : NextEventSelectorBase + { + [SerializeField] StreamEventSource nextMessageSource; + [SerializeField] bool autoPopulate; + [SerializeField] UnityEvent enableForNextMessage; + [SerializeField] UnityEvent disableForNextMessage; + + + protected override StreamEventSource NextMessageSource => nextMessageSource; + + protected override bool AutoPopulate => autoPopulate; + + public UnityEvent EnableForNextMessage => enableForNextMessage; + + public UnityEvent DisableForNextMessage => disableForNextMessage; + + protected override void OnEnableForNextMessage() + { + enableForNextMessage?.Invoke(); + } + + protected override void OnDisableForNextMessage() + { + disableForNextMessage?.Invoke(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors/NextEventSelector.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors/NextEventSelector.cs.meta new file mode 100644 index 0000000..2a4903b --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors/NextEventSelector.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3a5e67e2cca44e86b9b488f72160885e +timeCreated: 1546273454 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors/NextEventSelectorBase.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors/NextEventSelectorBase.cs new file mode 100644 index 0000000..2c88ba4 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors/NextEventSelectorBase.cs @@ -0,0 +1,321 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityTutorialSystem.Aggregators; +using UnityTutorialSystem.Events; +using UnityTutorialSystem.Helpers; + +namespace UnityTutorialSystem.Predictors +{ + /// + /// + /// A base class for components that react to 'next event' changes. + /// Due to the structured nature of the s + /// we can ask them to tell when a given message would be expected next. + /// + /// + /// This class handles all common initialization and maintenance of the + /// event listeners. + /// + /// + public abstract class NextEventSelectorBase : MonoBehaviour + { + readonly HashSet effectiveSources; + [SerializeField] List sources; + [SerializeField] bool detailedDebugging; + List messageBuffer; + bool started; + + /// + protected NextEventSelectorBase() + { + effectiveSources = new HashSet(); + messageBuffer = new List(); + sources = new List(); + } + + /// + /// Returns the (modifiable) set of effective message aggregator sources. + /// Normally you should not need to modify the collection, but if you do + /// while this behaviour is already enabled, make sure you call + /// to ensure that this behaviour gets notified of state changes. + /// + protected ICollection EffectiveSources => effectiveSources; + + /// + /// Returns the event producer that defines the 'next message' this selector is looking for. This + /// is usually the event source that would fire that message if certain success conditions are met. + /// + protected abstract StreamEventSource NextMessageSource { get; } + + /// + /// Defines whether this source will auto-populate the event message aggregator objects from instances + /// defined in the scene. If set to false, it will only look at the sources defined in the injected + /// collection. + /// + protected abstract bool AutoPopulate { get; } + + /// + /// An internal method called during the initialization that collects the + /// instances referenced in the sources list and scene (if auto-populate is enabled). + /// + protected virtual void PopulateSources() + { + foreach (var s in sources) + { + if (s != null) + { + effectiveSources.Add(s); + } + } + + if (AutoPopulate) + { + DebugLog("Start auto-populating " + name); + var aggregator = SharedMethods.FindEvenInactiveComponents(true); + if (aggregator.Length == 0) + { + DebugLog("No aggregators found."); + } + + foreach (var s in aggregator) + { + if (s == null) + { + continue; + } + + if (IsValidMessageSource(s)) + { + effectiveSources.Add(s); + } + } + } + + DebugLog("After populate " + name + " contains " + effectiveSources.Count + " active sources."); + } + + void DebugLog(string message) + { + if (detailedDebugging) + { + Debug.Log(message); + } + } + + /// + /// Validates that the given message aggregator is able to generate the + /// produced by the NextMessageSource. If an aggregator cannot generate that message, there is no point + /// in actually subscribing for update events. + /// + /// the potential message source + /// true if the source can generate the NextMessage, false otherwise + protected virtual bool IsValidMessageSource(EventMessageAggregator source) + { + if (NextMessageSource == null) + { + Debug.LogWarning("No such message source"); + return false; + } + + messageBuffer = source.ListEvents(messageBuffer); + foreach (var b in messageBuffer) + { + if (FilterMessage(b.Message)) + { + DebugLog("Filtered " + b.Message); + continue; + } + + if (NextMessageSource.WillGenerateMessage(b.Message)) + { + return true; + } + + DebugLog("No match for " + b.Message); + } + + DebugLog("Filtered " + source + " because " + messageBuffer.Count + " " + source.enabled); + return false; + } + + /// + /// Tests whether this message should be ignored. This default implementation simply checks the + /// property of the + /// . + /// + /// The message. + /// true if the message should be ignored, false otherwise. + protected virtual bool FilterMessage(BasicEventStreamMessage msg) + { + var stream = msg.Stream; + if (stream != null) + { + return stream.IgnoreForNextEventIndicatorHint; + } + + return false; + } + + void Start() + { + if (!started) + { + started = true; + PopulateSources(); + OnEnable(); + } + + OnMatchRestart(); + } + + /// + /// An override point that is called when the next-message is expected next. Use this to enable + /// your dependent behaviours. + /// + protected virtual void OnEnableForNextMessage() + { + } + + /// + /// An override point that is called when the next-message is expected next. Use this to disable + /// your dependent behaviours. + /// + protected virtual void OnDisableForNextMessage() + { + } + + + void OnMatchProgress(EventMessageAggregator source, BasicEventStreamMessage message) + { + if (!source.enabled) + { + return; + } + + if (FilterMessage(message)) + { + return; + } + + // Find a message source that can generate this message. + // If none is found, then this is not one of the handled messages. + messageBuffer = source.ListEvents(messageBuffer); + var isMatch = false; + foreach (var m in messageBuffer) + { + if (m.ExpectedNext && NextMessageSource.WillGenerateMessage(m.Message)) + { + isMatch = true; + DebugLog("OnMatchProgress: " + transform.name + " (match) via " + m.Message); + break; + } + } + + + if (isMatch) + { + OnEnableForNextMessage(); + } + else + { + OnDisableForNextMessage(); + } + } + + /// + /// Unity callback when the behaviour is enabled. If you override this, make sure + /// you call this base method. + /// + protected virtual void OnEnable() + { + if (!started) + { + return; + } + + foreach (var s in effectiveSources) + { + SubscribeTo(s); + } + } + + /// + /// Unity callback when the behaviour is disabled. If you override this, make sure + /// you call this base method. + /// + protected virtual void OnDisable() + { + foreach (var s in effectiveSources) + { + UnsubscribeFrom(s); + } + } + + /// + /// Subscribes to all relevant events on the given . + /// Use this if your own instances in a override. + /// + /// The message aggregator to subscribe to + protected void SubscribeTo(EventMessageAggregator s) + { + s.MatchProgress.AddListener(OnMatchProgress); + s.MatchStarting.AddListener(OnMatchRestart); + s.MatchComplete.AddListener(OnMatchRestart); + } + + /// + /// Unsubscribes from all relevant events on the given . + /// Use this if your own instances in a override. + /// + /// The message aggregator to subscribe to + protected void UnsubscribeFrom(EventMessageAggregator s) + { + s.MatchProgress.RemoveListener(OnMatchProgress); + s.MatchStarting.RemoveListener(OnMatchRestart); + s.MatchComplete.RemoveListener(OnMatchRestart); + } + + void OnMatchRestart() + { + var isMatch = false; + foreach (var source in effectiveSources) + { + if (!source.enabled) + { + continue; + } + + messageBuffer = source.ListEvents(messageBuffer); + foreach (var m in messageBuffer) + { + if (FilterMessage(m.Message)) + { + continue; + } + + if (m.ExpectedNext && NextMessageSource.WillGenerateMessage(m.Message)) + { + isMatch = true; + DebugLog("OnStart: " + transform.name + " " + (isMatch ? "(match)" : "(no match)") + " via " + m.Message); + break; + } + } + } + + if (!isMatch) + { + DebugLog("OnStart: " + transform.name + " (no match) -> " + messageBuffer.Count + " => " + effectiveSources.Count); + } + + + if (isMatch) + { + OnEnableForNextMessage(); + } + else + { + OnDisableForNextMessage(); + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors/NextEventSelectorBase.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors/NextEventSelectorBase.cs.meta new file mode 100644 index 0000000..9526d02 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Predictors/NextEventSelectorBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7af7813867fe4e5e97d0a05282d46cc8 +timeCreated: 1547588299 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial.meta new file mode 100644 index 0000000..8c3b056 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c8b30dd5732040d89851b010738b6251 +timeCreated: 1552498685 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventMessage.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventMessage.cs new file mode 100644 index 0000000..64d3e69 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventMessage.cs @@ -0,0 +1,24 @@ +using NaughtyAttributes; +using UnityEngine; +using UnityTutorialSystem.Aggregators; +using UnityTutorialSystem.Events; + +namespace UnityTutorialSystem.Tutorial +{ + /// + /// An extended stream message type that contains separate texts for each + /// state the message can assume in an . + /// + public class TutorialEventMessage : BasicEventStreamMessage + { + [SerializeField] [ResizableTextArea] string taskOpenMessage; + [SerializeField] [ResizableTextArea] string taskSuccessMessage; + [SerializeField] [ResizableTextArea] string taskFailureMessage; + + public string TaskOpenMessage => taskOpenMessage; + + public string TaskSuccessMessage => taskSuccessMessage; + + public string TaskFailureMessage => taskFailureMessage; + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventMessage.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventMessage.cs.meta new file mode 100644 index 0000000..0623ebe --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventMessage.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8cb599dd07c2401fb31ef8ce61dd8b2a +timeCreated: 1547029384 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventStream.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventStream.cs new file mode 100644 index 0000000..1323395 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventStream.cs @@ -0,0 +1,32 @@ +using UnityEngine; +using UnityTutorialSystem.Events; + +namespace UnityTutorialSystem.Tutorial +{ + /// + /// An event stream type that contains instances + /// instead of plain instances. + /// + [CreateAssetMenu(menuName = "Event Stream/Tutorial Event Stream")] + public class TutorialEventStream : BasicEventStream + { +#if UNITY_EDITOR + /// + protected override BasicEventStreamMessage CreateNode() + { + return CreateInstance(); + } +#endif + /// + /// Validates that the message given is valid for this stream. + /// A message is valid if it is both an TutorialEventMessage + /// instance and a registered child of the stream. + /// + /// message to test + /// true, if the message is owned by this stream, false otherwise. + public override bool IsValidMessage(BasicEventStreamMessage msg) + { + return base.IsValidMessage(msg) && msg is TutorialEventMessage; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventStream.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventStream.cs.meta new file mode 100644 index 0000000..ce250ed --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventStream.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 177a928ab1d64b8aab0e860dcea415f8 +timeCreated: 1547030401 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventTreeBinding.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventTreeBinding.cs new file mode 100644 index 0000000..eea907c --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventTreeBinding.cs @@ -0,0 +1,21 @@ +using UnityEngine; +using UnityTutorialSystem.UI; + +namespace UnityTutorialSystem.Tutorial +{ + /// + /// A basic binding component to decouple presentation (TreeView) from + /// data source (EventStreamTreeModelBuilder). This class simply connects the + /// model created by the EventStreamTreeModelBuilder to the TreeView. + /// + public class TutorialEventTreeBinding : MonoBehaviour + { + [SerializeField] EventStreamTreeModelBuilder modelSource; + [SerializeField] TutorialEventTreeView treeView; + + void Start() + { + treeView.Model = modelSource.Model; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventTreeBinding.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventTreeBinding.cs.meta new file mode 100644 index 0000000..439d101 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventTreeBinding.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: bba432f912c64ce291ce3be12de22190 +timeCreated: 1552574979 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventTreeItemRenderer.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventTreeItemRenderer.cs new file mode 100644 index 0000000..2d3ae5e --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventTreeItemRenderer.cs @@ -0,0 +1,224 @@ +using System; +using TMPro; +using UnityEngine; +using UnityEngine.UI; +using UnityTutorialSystem.Events; +using UnityTutorialSystem.UI; +using UnityTutorialSystem.UI.Trees; + +namespace UnityTutorialSystem.Tutorial +{ + /// + /// + /// A TreeItemRenderer for TutorialEventMessage instances. This behaviour must + /// be added on the root object of the tree-item prefab or template object. + /// This class receives a TutorialEventMessage from the TreeView and configures + /// the assigned TextMeshProUGUI instance based on the formatting parameters + /// set in the inspector. + /// + /// + /// This class is lenient in which BasicEventStream messages it consumes + /// (basically to work around Unity's built-in limitations centred around generics + /// and instantiating generic serialized objects in a scene). If the + /// message given is a TutorialEventMessage, this renderer will use the extended + /// texts provided by the message, otherwise it will fall back to use the message + /// object's name as text. + /// + /// + public class TutorialEventTreeItemRenderer : TreeItemRenderer + { + [SerializeField] Color whenNextEventColor; + [SerializeField] Color whenCompletedColor; + [SerializeField] Color defaultColor; + [SerializeField] FontStyles whenNextEventFontStyle; + [SerializeField] FontStyles whenCompletedFontStyle; + [SerializeField] FontStyles defaultFontStyle; + + [SerializeField] Toggle toggle; + [SerializeField] TextMeshProUGUI label; + [SerializeField] float indentPerLevel; + [SerializeField] int ignoreLeadingIndent; + + LayoutGroup layout; + bool anchorStored; + int indentCorrection; + Vector2 anchor; + + void Reset() + { + whenNextEventColor = Color.yellow; + whenCompletedColor = Color.green; + defaultColor = Color.white; + toggle = GetComponentInChildren(); + label = GetComponentInChildren(); + } + + bool IsNextEvent(EventStreamTreeModelData data) + { + if (data.ExpectedNext == false) + { + return false; + } + + var message = data.SourceMessage; + if ((message != null) && (message.Stream != null) && message.Stream.IgnoreForNextEventIndicatorHint) + { + return false; + } + + return true; + } + + string GetNextMessage(BasicEventStreamMessage msg) + { + var tutorialEventMessage = msg as TutorialEventMessage; + if (tutorialEventMessage != null) + { + var txt = tutorialEventMessage.TaskOpenMessage; + if (!string.IsNullOrWhiteSpace(txt)) + { + return txt; + } + } + + return msg.name; + } + + string GetFailureMessage(BasicEventStreamMessage msg) + { + var tutorialEventMessage = msg as TutorialEventMessage; + if (tutorialEventMessage != null) + { + var txt = tutorialEventMessage.TaskFailureMessage; + if (!string.IsNullOrWhiteSpace(txt)) + { + return txt; + } + } + + return msg.name; + } + + protected override void Awake() + { + ignoreLeadingIndent = Math.Max(ignoreLeadingIndent, 0); + layout = GetComponent(); + base.Awake(); + } + + string GetSuccessMessage(BasicEventStreamMessage msg) + { + var tutorialEventMessage = msg as TutorialEventMessage; + if (tutorialEventMessage != null) + { + var txt = tutorialEventMessage.TaskSuccessMessage; + if (!string.IsNullOrWhiteSpace(txt)) + { + return txt; + } + } + + return msg.name; + } + + void MarkLayoutDirty() + { + var rectTransform = GetComponent(); + if (rectTransform != null) + { + LayoutRebuilder.MarkLayoutForRebuild(rectTransform); + } + } + + protected override void OnUpdateValue(TreePath treePath) + { + if (treePath == null) + { + ResetContents(); + MarkLayoutDirty(); + return; + } + + EventStreamTreeModelData data; + if (treePath.TryGetLastComponent(out data) && (data.SourceMessage != null)) + { + if (label != null) + { + if (IsNextEvent(data)) + { + label.text = GetNextMessage(data.SourceMessage); + label.fontStyle = whenNextEventFontStyle; + label.color = whenNextEventColor; + } + else if (data.Completed) + { + label.text = GetSuccessMessage(data.SourceMessage); + label.fontStyle = whenCompletedFontStyle; + label.color = whenCompletedColor; + } + else + { + label.text = GetFailureMessage(data.SourceMessage); + label.fontStyle = defaultFontStyle; + label.color = defaultColor; + } + } + + if (toggle != null) + { + toggle.isOn = data.Completed; + var rt = toggle.transform as RectTransform; + ApplyIndent(rt); + } + + MarkLayoutDirty(); + } + else + { + ResetContents(); + MarkLayoutDirty(); + } + } + + void ApplyIndent(RectTransform rt) + { + if (rt != null) + { + if (!anchorStored) + { + var tree = gameObject.GetComponentInParent>(); + if (tree != null) + { + indentCorrection = tree.ShowRootNode ? 0 : -1; + } + + anchorStored = true; + anchor = rt.anchoredPosition; + } + + var effectiveIndent = Math.Max(0, indentCorrection + IndentLevel - 1 - ignoreLeadingIndent); + var indentSpacing = indentPerLevel * effectiveIndent; + if (layout != null) + { + var padding = layout.padding; + layout.padding = new RectOffset((int)indentSpacing, padding.top, padding.right, padding.bottom); + } + rt.anchoredPosition = new Vector2(anchor.x + indentSpacing, anchor.y); + } + } + + void ResetContents() + { + if (label != null) + { + label.text = ""; + label.fontStyle = FontStyles.Normal; + } + + if (toggle != null) + { + toggle.isOn = false; + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventTreeItemRenderer.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventTreeItemRenderer.cs.meta new file mode 100644 index 0000000..cdfabe7 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventTreeItemRenderer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: bcf2b234f7c645128d79667d27a38161 +timeCreated: 1546540331 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventTreeView.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventTreeView.cs new file mode 100644 index 0000000..c4907ac --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventTreeView.cs @@ -0,0 +1,63 @@ +using UnityEngine; +using UnityTutorialSystem.UI; +using UnityTutorialSystem.UI.Trees; + +namespace UnityTutorialSystem.Tutorial +{ + /// + /// A TreeView for EventStreamTreeModelData as produced by the + /// EventStreamTreeModelBuilder. This class only works well if it + /// is used in conjunction with a LayoutElement that can auto-arrange + /// the child nodes generated by the view. + /// + /// + public class TutorialEventTreeView : TreeView + { + [SerializeField] TutorialEventTreeItemRenderer template; + [SerializeField] bool showAllNodes; + [SerializeField] bool hideCompletedSubTrees; + + + /// + protected override TreeItemRenderer ItemRenderer => template; + + /// + /// Controls the visibility of nodes. This method is depends on the showAllNodes and + /// hideCompletedSubTrees injected variables. + /// If hideCompletedSubTrees is true, it will collapse branches where all nodes have + /// been completed. If this test would make the node visible, a second test based on + /// showAllNodes will selectively only show nodes that are either completed or expected + /// next. + /// + /// The tree path to check + /// true to show the corresponding node, false otherwise. + protected override bool IsPathVisible(TreePath path) + { + if (hideCompletedSubTrees) + { + if (path.Count > 1) + { + var parentNode = path[path.Count - 2]; + if (parentNode.Completed) + { + return false; + } + } + } + + if (!showAllNodes) + { + if (path.TryGetLastComponent(out var stateData) && (stateData != null)) + { + // Debug.Log("Maybe Hiding node " + path); + return stateData.Completed || stateData.ExpectedNext; + } + + // Debug.Log("Hiding node " + path); + return false; + } + + return true; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventTreeView.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventTreeView.cs.meta new file mode 100644 index 0000000..241f83a --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/Tutorial/TutorialEventTreeView.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5dabfd477c564c518af7ad4e2362742a +timeCreated: 1546540039 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/UI.meta new file mode 100644 index 0000000..e566447 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a5c1c335c534444385afae4c4e73602c +timeCreated: 1546447346 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/EventStreamTreeModelBuilder.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/EventStreamTreeModelBuilder.cs new file mode 100644 index 0000000..cb21a2a --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/EventStreamTreeModelBuilder.cs @@ -0,0 +1,429 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NaughtyAttributes; +using UnityEngine; +using UnityTutorialSystem.Aggregators; +using UnityTutorialSystem.Events; +using UnityTutorialSystem.Helpers; +using UnityTutorialSystem.UI.Trees; + +namespace UnityTutorialSystem.UI +{ + /// + /// A tree model builder that creates a tree of + /// objects based on the + /// instances given. + /// Each is assumed + /// to be associated with a single + /// . + /// + /// + /// + /// This class attempts to detect hierarchical relationships between + /// the + /// given by + /// trying to match the success message of each + /// with a + /// produced message of any of the associated + /// instances. + /// + /// + /// This TreeModelBuilder manages a single tree model that can be + /// shared between multiple tree view instances. The model will be + /// kept up to date for as long as the associated + /// instances are valid. The + /// class will delay all work until + /// has been called. + /// + /// + public class EventStreamTreeModelBuilder : MonoBehaviour + { + readonly List buffer; + readonly ListTreeModel model; + + [SerializeField] [ReorderableList] List tutorialStateTrackers; + [SerializeField] bool debug; + + Dictionary nodeMapper; + EventStreamTreeModelData rootNode; + bool started; + + /// + /// Default constructor. + /// + public EventStreamTreeModelBuilder() + { + buffer = new List(); + model = new ListTreeModel(); + } + + /// + /// The model produced by this builder. + /// + public ITreeModel Model => model; + + /// + /// Diagnostic method that conditionally logs messages to the debug log. + /// + /// + void DebugLog(string message) + { +#if DEBUG + if (debug) + { + Debug.Log(name + ": " + message); + } +#endif + } + + void Start() + { + started = true; + + RebuildModel(); + } + + /// + /// Rebuilds the complete tree model. Use this only as last resort after + /// you removed or added EventMessageAggregator instances in the scene. + /// But try to keep all EventMessageAggregator definitions static if + /// humanly possible, its better for performance and every one involved. + /// + public void RebuildModel() + { + var data = CollectTreeData(); + PrintTree(data); + (rootNode, nodeMapper) = CreateTreeNodes(data); + DebugLog("Generated tree:\n" + rootNode.AsTextTree()); + model.Root = rootNode; + + foreach (var d in tutorialStateTrackers) + { + OnTrackerStateChanged(d); + } + } + + void OnEnable() + { + foreach (var d in tutorialStateTrackers) + { + d.StateChanged.AddListener(OnTrackerStateChanged); + } + + if (started) + { + foreach (var d in tutorialStateTrackers) + { + OnTrackerStateChanged(d); + } + } + } + + void OnDisable() + { + foreach (var d in tutorialStateTrackers) + { + d.StateChanged.RemoveListener(OnTrackerStateChanged); + } + } + + /// + /// Called when the state of the associated EventMessageAggregator has changed. This + /// updates the + /// + /// + /// + void OnTrackerStateChanged(EventMessageAggregatorStatePublisher source, BasicEventStreamMessage message = null) + { + if (!started) + { + return; + } + + // Attempt to find the parent EventMessageAggregator that handles the + // success message of that source. The messages tracked by the source + // are represented by child nodes within that parent. + EventStreamTreeModelData data; + if (!nodeMapper.TryGetValue(source, out data)) + { + // only the root itself can be without parent. + data = rootNode; + } + + source.FetchEvents(buffer); + + for (var index = 0; index < buffer.Count; index++) + { + var b = buffer[index]; + var c = data[index]; + if (b.Message == c.SourceMessage) + { + c.Completed = b.Completed; + c.ExpectedNext = b.ExpectedNext; + } + else + { + Debug.LogWarning("Inconsistent data model from source " + source); + } + } + + // Special case handling: child-nodes of root won't ever receive completion events as + // there is no aggregator listening for the completed notification. Therefore we + // have to manually poll that state. + foreach (var rootChild in rootNode) + { + if (rootChild == data) + { + rootChild.Completed = source.MatchResult == EventMessageMatcherState.Success; + } + } + + // Nuke the treeview. Right now that is cheaper to write than proper + // targeted event handling. + model.FireStructureChanged(); + } + + /// + /// Creates an list of expected states for the tree. This method blindly + /// gathers all events produced by each + /// and - in a second step - + /// attempts to build a hierarchy by checking the success message of the + /// EventMessageAggratorStatePublisher with all collected messages. + /// + /// + /// This method has O(N^2) complexity, but hopefully you won't ever have + /// so many activities that this actually matters. + /// + /// + /// The list of aggregator message states that have no parent. All other + /// states can be reached from there. + /// + List CollectTreeData() + { + var data = new List(); + foreach (var n in tutorialStateTrackers) + { + var messages = n.FetchEvents(buffer); + data.Add(new ExpectedStates(n, n.SuccessMessage, messages, debug)); + } + + foreach (var self in data) + { + foreach (var n in data) + { + if (self.MessageSource == n.MessageSource) + { + continue; + } + + if (self.ExpectsMessage(n.SuccessMessage)) + { + self.AddChild(n); + } + } + } + + return data.Where(d => !d.IsDependency).ToList(); + } + + /// + /// Creates an artificial root node not backed by any success message. Any actual event aggregators + /// that would act as root nodes (because they have no success message on their own) will be flattened + /// into this root node. + /// + /// The list of potential root nodes + /// The created tree node and a mapping of the created node and all its child nodes and their respective sources. + static ValueTuple> CreateTreeNodes(List data) + { + var roots = data.Where(s => !s.IsDependency).ToList(); + var nodes = new Dictionary(); + var childStates = new List(); + foreach (var s in roots) + { + var (item, subNodes) = AddTree(s); + nodes.AddRange(subNodes); + item.ExpectedNext = false; + AddGeneratedChildItems(childStates, item); + } + + var treeModelData = new EventStreamTreeModelData(null, false, true, childStates); + return ValueTuple.Create(treeModelData, nodes); + } + + /// + /// Adds all nodes represented by the EventStreamTreeModelData given as item to the list of child states. + /// This method flattens all event message aggregators that generate no success message. + /// + /// The collected child nodes + /// The item to process + static void AddGeneratedChildItems(List childStates, EventStreamTreeModelData item) + { + if (item.SourceMessage != null) + { + item.ExpectedNext = false; + childStates.Add(item); + return; + } + + foreach (var child in item) + { + AddGeneratedChildItems(childStates, child); + } + } + + /// + /// Generates a sub-tree for the given ExpectedStates instance that + /// replicates the structure of all known dependencies for that state. + /// + /// The state that is processed. + /// + /// The created tree node and a mapping of the created node and all its + /// child nodes and their respective sources. + /// + static ValueTuple> AddTree(ExpectedStates state) + { + var childStates = new List(); + var nodeMapper = new Dictionary(); + foreach (var s in state.RequiredMessages) + { + ExpectedStates dependency; + if (state.IsProvidedByDependency(s.Message, out dependency)) + { + var (item, subNodes) = AddTree(dependency); + nodeMapper.AddRange(subNodes); + item.ExpectedNext = s.ExpectedNext; + childStates.Add(item); + } + else + { + var message = s.Message; + childStates.Add(new EventStreamTreeModelData(message, s.Completed, s.ExpectedNext)); + } + } + + var stateData = new EventStreamTreeModelData(state.SuccessMessage, state.Completed, false, childStates); + nodeMapper[state.MessageSource] = stateData; + return (stateData, nodeMapper); + } + + /// + /// A debug helper function that prints the resulting tree into the log. + /// + /// + void PrintTree(List states) + { + if (!debug) + { + return; + } + + DebugLog("---- START TREE DUMP ---"); + foreach (var state in states) + { + PrintTree(state, 0); + } + + DebugLog("---- END TREE DUMP ---"); + } + + void PrintTree(ExpectedStates state, int indent) + { + DebugLog($"{$"{indent}".PadLeft(2).PadRight(indent * 4)}:{state.MessageSource}"); + foreach (var s in state.Dependencies) + { + PrintTree(s, indent + 1); + } + } + + /// + /// An internal helper data structure used during the initial tree construction during the Start event. + /// + class ExpectedStates + { + public readonly List RequiredMessages; + public readonly EventMessageAggregatorStatePublisher MessageSource; + public readonly BasicEventStreamMessage SuccessMessage; + public readonly HashSet Dependencies; + readonly bool debug; + + public ExpectedStates(EventMessageAggregatorStatePublisher message, + BasicEventStreamMessage successMessage, + List requiredMessages, + bool debug) + { + MessageSource = message; + SuccessMessage = successMessage; + RequiredMessages = new List(requiredMessages); + Dependencies = new HashSet(); + this.debug = debug; + if (debug) + { + Debug.Log("Expected state: " + SuccessMessage + " -> " + string.Join(",", RequiredMessages)); + } + } + + public bool IsDependency { get; private set; } + + public bool Completed => MessageSource.MatchResult == EventMessageMatcherState.Success; + + public void AddChild(ExpectedStates nKey) + { + if (nKey.IsDependentOn(this)) + { + Debug.LogWarning($"Circular dependency in tutorial states between {SuccessMessage} and {nKey.SuccessMessage}."); + return; + } + + nKey.IsDependency = true; + Dependencies.Add(nKey); + } + + bool IsDependentOn(ExpectedStates expectedStates) + { + foreach (var d in Dependencies) + { + if (d == expectedStates) + { + return true; + } + + if (d.IsDependentOn(expectedStates)) + { + return true; + } + } + + return false; + } + + public bool IsProvidedByDependency(BasicEventStreamMessage msg, out ExpectedStates dependency) + { + foreach (var d in Dependencies) + { + if (d.SuccessMessage == msg) + { + dependency = d; + return true; + } + } + + dependency = default; + return false; + } + + public bool ExpectsMessage(BasicEventStreamMessage msg) + { + foreach (var r in RequiredMessages) + { + if (r.Message == msg) + { + return true; + } + } + + return false; + } + } + } +} diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/EventStreamTreeModelBuilder.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/EventStreamTreeModelBuilder.cs.meta new file mode 100644 index 0000000..17e6e1a --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/EventStreamTreeModelBuilder.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 731ae49d9a7e44078b9e9300c6c829c2 +timeCreated: 1546535346 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/EventStreamTreeModelData.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/EventStreamTreeModelData.cs new file mode 100644 index 0000000..dde228c --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/EventStreamTreeModelData.cs @@ -0,0 +1,245 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using JetBrains.Annotations; +using UnityTutorialSystem.Events; + +namespace UnityTutorialSystem.UI +{ + /// + /// A TreeModel data node that represents a + /// and all messages that contribute + /// to state changes of that message. + /// + public class EventStreamTreeModelData : IReadOnlyList, + IEquatable + { + readonly List subTasks; + + /// + /// Creates a new EventStreamTreeModelData representing the given source + /// message and all its contributing sub messages. + /// + /// + /// The source message represented by this tree node. + /// + /// + /// A flag indicating whether the message has been seen. + /// + /// + /// A flag indicating whether this message will be seen soon. + /// + /// + /// The messages contributing to the state of the source message. + /// + public EventStreamTreeModelData(BasicEventStreamMessage sourceMessage, + bool completed, + bool expectedNext, + IReadOnlyList data) + { + SourceMessage = sourceMessage; + Completed = completed; + ExpectedNext = expectedNext; + subTasks = new List(data); + } + + /// + /// A lazy constructor implementation to automatically wrap single + /// argument calls of the collection into a + /// . + /// + /// + /// The source message represented by this tree node. + /// + /// + /// A flag indicating whether the message has been seen. + /// + /// + /// A flag indicating whether this message will be seen soon. + /// + /// + /// The messages contributing to the state of the source message. + /// + public EventStreamTreeModelData(BasicEventStreamMessage sourceMessage, + bool completed, + bool expectedNext, + params EventStreamTreeModelData[] data) : + this(sourceMessage, completed, expectedNext, (IReadOnlyList) data) + { + } + + /// + /// The source message represented by this node. + /// + public BasicEventStreamMessage SourceMessage { get; } + + /// + /// A flag indicating that the message has been received by the EventMessageAggregator. + /// + public bool Completed { get; set; } + + /// + /// A flag indicating that the system expects this message to be fired next. + /// + public bool ExpectedNext { get; set; } + + /// + /// Compares this tree node for structural equality. Required by the ListTreeModel implementation + /// and its GetIndexOf method. + /// + /// the other node to compare + /// true if both nodes represent the same message and submessage set. + public bool Equals(EventStreamTreeModelData other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (!Equals(SourceMessage, other.SourceMessage)) + { + return false; + } + + if (Completed != other.Completed) + { + return false; + } + + return subTasks.SequenceEqual(other.subTasks); + } + + /// + /// Indexer access, part of the IList interface. + /// + /// the index. + /// the element at the index given + /// If the index is invalid. + public EventStreamTreeModelData this[int idx] => subTasks[idx]; + + /// + /// Return the number of sub-elements in this node. + /// + public int Count => subTasks.Count; + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + /// Returns an non-allocating memory efficient list enumerator. + /// + /// An efficient enumerator. + public List.Enumerator GetEnumerator() + { + return subTasks.GetEnumerator(); + } + + /// + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != GetType()) + { + return false; + } + + return Equals((EventStreamTreeModelData) obj); + } + + /// + public override int GetHashCode() + { + unchecked + { + var hashCode = 19; + foreach (var s in subTasks) + { + hashCode = (hashCode * 397) ^ (s != null ? s.GetHashCode() : 0); + } + + hashCode = (hashCode * 397) ^ (SourceMessage != null ? SourceMessage.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ Completed.GetHashCode(); + return hashCode; + } + } + + /// + [NotNull] + public override string ToString() + { + if (SourceMessage == null) + { + return $"({nameof(SourceMessage)}: , {nameof(Completed)}: {Completed})"; + } + + return $"({nameof(SourceMessage)}: {SourceMessage.name}, {nameof(Completed)}: {Completed})"; + } + + /// + /// A standard equality operator implementation. + /// + /// + /// + /// true if both objects are structurally equal, false otherwise. + public static bool operator ==(EventStreamTreeModelData left, EventStreamTreeModelData right) + { + return Equals(left, right); + } + + /// + /// A standard inequality operator implementation. + /// + /// + /// + /// true if both objects are structurally non-equal, false otherwise. + public static bool operator !=(EventStreamTreeModelData left, EventStreamTreeModelData right) + { + return !Equals(left, right); + } + + /// + /// Prints the tree as indented string, one element per line. Useful for debugging. + /// + /// + public string AsTextTree() + { + var b = new StringBuilder(); + AsTreeText(b, this, 0); + return b.ToString(); + } + + static void AsTreeText(StringBuilder b, EventStreamTreeModelData data, int indent) + { + b.Append("".PadLeft(indent * 4)); + b.Append(data); + b.Append("\n"); + foreach (var c in data) + { + AsTreeText(b, c, indent + 1); + } + } + } +} diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/EventStreamTreeModelData.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/EventStreamTreeModelData.cs.meta new file mode 100644 index 0000000..7928009 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/EventStreamTreeModelData.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e3bd3996dc9b44ada890cec6bddc77cb +timeCreated: 1546541854 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/SaneHBoxLayout.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/SaneHBoxLayout.cs new file mode 100644 index 0000000..5eb3dfc --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/SaneHBoxLayout.cs @@ -0,0 +1,79 @@ +using UnityEngine; +using UnityEngine.UI; + +namespace UnityTutorialSystem.UI +{ + /// + /// Unity's built in layout components behave rather erratically when asked to deal with + /// flexible layouts. Instead of trying to fix what is not fixable, lets quickly implement + /// a simple and working layout manager. + /// + /// + public class SaneHBoxLayout : LayoutGroup + { + const int AXIS_HORIZONTAL = 0; + const int AXIS_VERTICAL = 1; + + /// + public override void CalculateLayoutInputHorizontal() + { + // Mandatory.. + base.CalculateLayoutInputHorizontal(); + var minSize = (float)padding.horizontal; + var prefSize = (float)padding.horizontal; + var flexSize = (float) padding.horizontal; + foreach (var c in rectChildren) + { + minSize += LayoutUtility.GetMinWidth(c); + prefSize += LayoutUtility.GetPreferredWidth(c); + flexSize += LayoutUtility.GetFlexibleWidth(c); + } + + SetLayoutInputForAxis(minSize, prefSize, flexSize, AXIS_HORIZONTAL); + } + + /// + public override void CalculateLayoutInputVertical() + { + var paddingVertical = (float) padding.vertical; + var minSize = 0f; + var prefSize = 0f; + var flexSize = 0f; + foreach (var c in rectChildren) + { + minSize = Mathf.Max(LayoutUtility.GetMinHeight(c), minSize); + prefSize = Mathf.Max(LayoutUtility.GetPreferredHeight(c), prefSize); + flexSize = Mathf.Max(LayoutUtility.GetFlexibleHeight(c), flexSize); + } + + SetLayoutInputForAxis(minSize + paddingVertical, prefSize + paddingVertical, flexSize + paddingVertical, AXIS_VERTICAL); + } + + /// + public override void SetLayoutHorizontal() + { + var prefSize = 0f; + var space = Mathf.Max(0, rectTransform.rect.size[AXIS_HORIZONTAL] - padding.horizontal); + foreach (var c in rectChildren) + { + var pref = LayoutUtility.GetPreferredWidth(c); + var min = LayoutUtility.GetMinWidth(c); + var availSpace = Mathf.Max(0, space - prefSize); + var allocatedSpace = Mathf.Max(min, Mathf.Min(availSpace, pref)); + + SetChildAlongAxis(c, AXIS_HORIZONTAL, prefSize + padding.left, allocatedSpace); + prefSize += allocatedSpace; + } + } + + /// + public override void SetLayoutVertical() + { + foreach (var c in rectChildren) + { + var min = LayoutUtility.GetPreferredHeight(c); + SetChildAlongAxis(c, AXIS_VERTICAL, padding.top, min); + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/SaneHBoxLayout.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/SaneHBoxLayout.cs.meta new file mode 100644 index 0000000..df5a6a7 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/SaneHBoxLayout.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ea16d7c66e8746679b5a105ab2458c21 +timeCreated: 1548098687 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees.meta new file mode 100644 index 0000000..4f6e1fa --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6fb2d7aa1bce45cebf89ff79fab50c0b +timeCreated: 1546536457 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/ITreeModel.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/ITreeModel.cs new file mode 100644 index 0000000..2b91456 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/ITreeModel.cs @@ -0,0 +1,111 @@ +using System; + +namespace UnityTutorialSystem.UI.Trees +{ + /// + /// A Tree model . This model abstracts away the + /// underlying data structure by forming a facade with all required + /// operations over the data nodes. This is + /// roughly modelled after the excellent design found in Java Swing. + /// + /// The underlying node data type + public interface ITreeModel + { + /// + /// Checks whether the model has a tree node. + /// + bool HasRoot { get; } + + /// + /// If the model has a root tree node, return it. + /// + /// + TNode Root { get; } + + /// + /// + /// Tests whether the given is a leaf node. A + /// leaf is any that + /// cannot possibly have children. For example, a file is a leaf + /// in a file system tree, but an empty + /// directory is not. Even though an empty directory currently has no + /// child nodes, there are circumstances that directory can have child + /// nodes in the future. + /// + /// + /// Implementation note: This test is currently only used for + /// presentation purposes. + /// + /// + /// The node to test + /// + /// if the cannot have + /// children, otherwise. + /// + bool IsLeaf(TNode node); + + /// + /// Return the child node at the given index. + /// + /// the parent node + /// the index of the child node in the parent node + /// The node at the given index, never null. + /// if the node given does not have a child at that position. + /// + /// + TNode GetChildAt(TNode parent, int index); + + /// + /// Returns the number of child nodes this + /// node contains. + /// + /// The parent node + /// + /// a positive integer + /// + int ChildCount(TNode parent); + + /// + /// Returns the index of the given node in the + /// node or -1 if this potential + /// node is not a of + /// the parent. + /// + /// The parent node + /// The child node + /// + /// the positive index of the node in the + /// parent, or -1 if the node given as is not a + /// of that parent. + /// + /// + /// + int GetIndexOfChild(TNode parent, TNode child); + + /// + /// Informs all listeners that the structure of the tree at the given tree path has + /// changed. A structural change indicates that nodes have been added or removed from + /// the tree. If an empty tree path is given it indicates that the root node itself has changed. + /// + event EventHandler> StructureChanged; + + /// + /// Informs all listeners that the data inside a tree node has changed. Firing this event + /// does not indicate that nodes have been added or removed, it merely means that one or + /// more properties of the TNode object representing the node have changed in some way. + /// + event EventHandler> NodesChanged; + + /// + /// A specialised structural change event that indicates that new nodes have been added + /// at the given location. + /// + event EventHandler> NodesInserted; + + /// + /// A specialised structural change event that indicates that old nodes have been removed + /// at the given location. + /// + event EventHandler> NodesRemoved; + } +} diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/ITreeModel.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/ITreeModel.cs.meta new file mode 100644 index 0000000..8284151 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/ITreeModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 482a7e46e128817498c1767b6defa33c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/ListTreeModel.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/ListTreeModel.cs new file mode 100644 index 0000000..ed122b8 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/ListTreeModel.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; + +namespace UnityTutorialSystem.UI.Trees +{ + /// + /// A standard implementation of a tree model for list based tree nodes that maps tree + /// operations to their corresponding list operations on the nodes themselves. + /// + /// A list based data type is required for this class. + public class ListTreeModel : TreeModel where TList : class, IReadOnlyList + { + /// + /// Creates an empty tree model. + /// + public ListTreeModel() + { + } + + /// + /// Initializes the tree model with the given root node. + /// + /// + public ListTreeModel(TList root) + { + Root = root; + } + + /// + public sealed override bool HasRoot => Root != null; + + /// + public sealed override TList Root { get; set; } + + /// + public override bool IsLeaf(TList node) + { + return node.Count == 0; + } + + /// + public override TList GetChildAt(TList parent, int index) + { + return parent[index]; + } + + /// + public override int ChildCount(TList parent) + { + return parent.Count; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/ListTreeModel.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/ListTreeModel.cs.meta new file mode 100644 index 0000000..c7d57ea --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/ListTreeModel.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1212d068e3c04f29aeb3ff3ff813a527 +timeCreated: 1546611822 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeItemRenderer.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeItemRenderer.cs new file mode 100644 index 0000000..d9bce09 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeItemRenderer.cs @@ -0,0 +1,60 @@ +using UnityEngine; + +namespace UnityTutorialSystem.UI.Trees +{ + /// + /// Abstract because its unity + /// + /// + public abstract class TreeItemRenderer : MonoBehaviour + { + TreePath path; + bool awake; + + public int IndentLevel + { + get + { + if (Path == null) + { + return 0; + } + + return Path.Count; + } + } + + public TreePath Path + { + get { return path; } + set + { + path = value; + if (value != null) + { + name = path.ToString(); + } + else + { + name = "[]"; + } + + if (awake) + { + OnUpdateValue(path); + } + } + } + + protected virtual void Awake() + { + awake = true; + if (path != null) + { + OnUpdateValue(path); + } + } + + protected abstract void OnUpdateValue(TreePath treePath); + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeItemRenderer.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeItemRenderer.cs.meta new file mode 100644 index 0000000..fb992df --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeItemRenderer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f79abfd702d54a69acd02006d33bde2f +timeCreated: 1546538066 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeModel.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeModel.cs new file mode 100644 index 0000000..50eb806 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeModel.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; + +namespace UnityTutorialSystem.UI.Trees +{ + /// + /// An abstract base class for tree model implementations. This class + /// provides default implementations for all events. + /// + /// + public abstract class TreeModel : ITreeModel + { + /// + public abstract bool HasRoot { get; } + + /// + public abstract TNode Root { get; set; } + + /// + public abstract bool IsLeaf(TNode node); + + /// + public abstract TNode GetChildAt(TNode parent, int index); + + /// + public abstract int ChildCount(TNode parent); + + /// + public virtual int GetIndexOfChild(TNode parent, TNode child) + { + if (IsLeaf(parent)) + { + return -1; + } + + var cmp = Comparer.Default; + var count = ChildCount(parent); + for (var c = 0; c < count; c += 1) + { + if (cmp.Compare(child ,GetChildAt(parent, c)) == 0) + { + return c; + } + } + + return -1; + } + + /// + public event EventHandler> StructureChanged; + /// + public event EventHandler> NodesChanged; + /// + public event EventHandler> NodesInserted; + /// + public event EventHandler> NodesRemoved; + + /// + /// Triggers the StructureChanged event for the root node to indicate that something somewhere inside the + /// tree has changed. This usually results in a full rebuild of any UI element or dependent data structure, + /// and thus this is the most expensive event that can be used to inform others of changes. + /// + public void FireStructureChanged() + { + StructureChanged?.Invoke(this, new TreeModelEventArgs(new TreePath(), new[] {0}, new[] {Root})); + } + + /// + /// Indicates that the child node at the given tree path has changed. + /// + /// + /// The path to the parent node + /// The index of the child node within the parent node + /// The child node that has changed + public void FireNodesChanged(TreePath parent, int index, TNode child) + { + NodesChanged?.Invoke(this, new TreeModelEventArgs(parent, index, child)); + } + + /// + /// Indicates that the structure at the given tree path has changed. + /// + /// + /// The path to the parent node + /// The index of the child node within the parent node + /// The child node that has changed + public void FireStructureChanged(TreePath parent, int index, TNode child) + { + StructureChanged?.Invoke(this, new TreeModelEventArgs(parent, index, child)); + } + + /// + /// Indicates that a new node has been inserted into the parent at the given + /// index positions. + /// + /// + /// The parent node + /// The index of the child node within the parent node + /// The child node that has changed + public void FireNodeInserted(TreePath parent, int index, TNode child) + { + if (parent == null) + { + throw new ArgumentNullException(nameof(parent)); + } + + NodesInserted?.Invoke(this, new TreeModelEventArgs(parent, index, child)); + } + + /// + /// Indicates that an existing node has been removed from the parent at the given + /// index positions. + /// + /// + /// The parent node + /// The index of the child node within the parent node + /// The child node that has changed + public void FireNodeRemoved(TreePath parent, int index, TNode child) + { + if (parent == null) + { + throw new ArgumentNullException(nameof(parent)); + } + + NodesRemoved?.Invoke(this, new TreeModelEventArgs(parent, index, child)); + } + + /// + /// Indicates that the given node has changed. + /// + /// The path to the parent node + /// The child node that has changed + public void FireNodeChanged(TreePath parentPath, TNode child) + { + TNode parent; + parentPath.TryGetLastComponent(out parent); + var pos = GetIndexOfChild(parent, child); + FireNodesChanged(parentPath, pos, child); + } + + /// + /// Indicates that the structure at the given tree path has changed. + /// + /// + /// + /// + public void FireStructureChanged(TreePath parentPath, TNode child) + { + TNode parent; + parentPath.TryGetLastComponent(out parent); + var pos = GetIndexOfChild(parent, child); + FireStructureChanged(parentPath, pos, child); + } + } +} diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeModel.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeModel.cs.meta new file mode 100644 index 0000000..08d3d98 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeModel.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4da3430a8d7344a08ca72a8e0434083d +timeCreated: 1546538796 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeModelEventArgs.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeModelEventArgs.cs new file mode 100644 index 0000000..c5c68a5 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeModelEventArgs.cs @@ -0,0 +1,93 @@ +using System; +using JetBrains.Annotations; + +namespace UnityTutorialSystem.UI.Trees +{ + /// + /// An event argument class for tree modification events. + /// + /// + public class TreeModelEventArgs : EventArgs + { + /// + /// Constructs an event argument with the given path as context path and + /// no information about changed child nodes. + /// + /// The context path + /// If the given path is null + public TreeModelEventArgs([NotNull] TreePath path) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Path = path; + Children = new TNode[0]; + ChildIndices = new int[0]; + } + + /// + /// Constructs an event argument for tree modification events caused by a + /// single tree node. Use this constructor for insertion and deletion events. + /// + /// The context path. + /// The index of the child within the parent. + /// The child node. + /// if any of the parameters is null + public TreeModelEventArgs([NotNull] TreePath path, int childIndex, [NotNull] TNode child) : this(path, new[] {childIndex}, new[] {child}) + { + } + + /// + /// Constructs an event argument for tree modification events caused by a + /// multiple tree nodes within the same parent. + /// + /// The context path. + /// The indices of the child within the parent. + /// The child nodes. + /// if any of the parameters is null + public TreeModelEventArgs([NotNull] TreePath path, [NotNull] int[] childIndices, [NotNull] TNode[] children) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + if (childIndices == null) + { + throw new ArgumentNullException(nameof(childIndices)); + } + + if (children == null) + { + throw new ArgumentNullException(nameof(children)); + } + + ChildIndices = childIndices; + Children = children; + Path = path; + } + + /// + /// The indices of the position of the child nodes in the node described by the context path. + /// + [NotNull] public int[] ChildIndices { get; } + + /// + /// The children. + /// + [NotNull] public TNode[] Children { get; } + + /// + /// The context path. + /// + [NotNull] public TreePath Path { get; } + + /// + public override string ToString() + { + return $"{nameof(Path)}: {Path}, {nameof(ChildIndices)}: {ChildIndices}, {nameof(Children)}: {Children}"; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeModelEventArgs.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeModelEventArgs.cs.meta new file mode 100644 index 0000000..0aaa17d --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeModelEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 61eec6fa4b033c442a5bcec141fe189c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreePath.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreePath.cs new file mode 100644 index 0000000..5523f8c --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreePath.cs @@ -0,0 +1,311 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using JetBrains.Annotations; + +namespace UnityTutorialSystem.UI.Trees +{ + /// + /// Factory methods for the TreePath data type. + /// + public static class TreePath + { + public static TreePath Empty() + { + return new TreePath(); + } + + /// + /// Creates a new, single level tree path from the given node. + /// + /// the node data + /// The TreeNode type + /// A treepath containing the given node as only element. + public static TreePath From(TNode n) + { + return new TreePath(n); + } + + /// + /// Creates a TreePath from the ordered set ot nodes. + /// + /// The set of nodes making up the path. + /// The TreeNode type + /// the created TreePath + public static TreePath From(params TNode[] n) + { + var a = (TNode[]) n.Clone(); + return new TreePath(a, n.Length); + } + } + + /// + /// A TreePath represents a hierarchical address in a tree data structure. + /// Each element represents a node in the tree at the given level so that + /// the element at N+1 is a child of the tree node found at level N. + /// + /// The TreeNode content type + public sealed class TreePath : IReadOnlyList, IEquatable> + { + readonly TNode[] backend; + + internal TreePath() + { + backend = new TNode[0]; + Count = 0; + } + + internal TreePath(TNode component) + { + backend = new[] {component}; + Count = backend.Length; + } + + internal TreePath(TNode[] component, int count) + { + // not need for defensive cloning, as we trust the implementation. + backend = component; + Count = count; + } + + /// + /// Appends the given component to this tree-path creating a new path from it. + /// + /// The new child component. + /// The new tree path + public TreePath Append(TNode component) + { + var tmpArray = new TNode[Count + 1]; + for (var index = 0; index < Count; index++) + { + tmpArray[index] = this[index]; + } + + tmpArray[Count] = component; + return new TreePath(tmpArray, Count + 1); + } + + /// + /// Returns the parent path of this path, which is the path with + /// the last element removed. This method will fail with an + /// ArgumentException if the path is already empty. + /// + /// if the Path is empty + public TreePath Parent + { + get + { + if (Count == 0) + { + throw new ArgumentException(); + } + + return new TreePath(backend, Count - 1); + } + } + + /// + public bool Equals(TreePath other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (Count != other.Count) + { + return false; + } + + if (ReferenceEquals(backend, other.backend)) + { + return true; + } + + return this.SequenceEqual(other); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + /// Returns the number of segments in this path. Returns zero for the empty path. + /// + public int Count { get; } + + /// + /// Accesses the path segment at the given index. + /// + /// a zero based index. + public TNode this[int index] => backend[index]; + + /// + /// Attempts to retrieve the last component of the path. + /// + /// The last component + /// true if the path is non empty, false otherwise. + public bool TryGetLastComponent(out TNode c) + { + if (Count == 0) + { + c = default(TNode); + return false; + } + + c = backend[Count - 1]; + return true; + } + + /// + /// Returns an struct-based enumerator to support more efficient + /// foreach loops. + /// + /// + public Enumerator GetEnumerator() + { + return new Enumerator(this); + } + + /// + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != GetType()) + { + return false; + } + + return Equals((TreePath) obj); + } + + /// + public override int GetHashCode() + { + unchecked + { + // this isn't overly quick but will do for now. + var hashCode = Count; + for (var i = 0; i < Count; i++) + { + object n = backend[i]; + hashCode = (hashCode * 397) ^ (n?.GetHashCode() ?? 0); + } + + return hashCode; + } + } + + /// + [NotNull] + public override string ToString() + { + var payload = string.Join("', '", backend); + return $"['{payload}']"; + } + + /// + /// Compares the two tree paths for structural equality using the Equals operator. + /// + /// The left path + /// The right path + /// true if both paths are structurally equal, false otherwise. + public static bool operator ==(TreePath left, TreePath right) + { + return Equals(left, right); + } + + /// + /// Compares the two tree paths for structural inequality using the Equals operator. + /// + /// The left path + /// The right path + /// true if both paths are structurally unequal, false otherwise. + public static bool operator !=(TreePath left, TreePath right) + { + return !Equals(left, right); + } + + /// + /// A enumerator that does not cause heap allocations when used correctly. + /// + public struct Enumerator : IEnumerator + { + readonly TreePath contents; + + int index; + TNode current; + + /// + internal Enumerator(TreePath widget) : this() + { + contents = widget; + index = -1; + current = default(TNode); + } + + /// + public void Dispose() + { + } + + /// + public bool MoveNext() + { + if (index + 1 < contents.Count) + { + index += 1; + current = contents[index]; + return true; + } + + current = default(TNode); + return false; + } + + /// + public void Reset() + { + index = -1; + current = default(TNode); + } + + object IEnumerator.Current => Current; + + /// + public TNode Current + { + get + { + if ((index < 0) || (index >= contents.Count)) + { + throw new InvalidOperationException(); + } + + return current; + } + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreePath.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreePath.cs.meta new file mode 100644 index 0000000..2eddfef --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreePath.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 751ae8498fde4ca4ab6662906f5e037f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeView.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeView.cs new file mode 100644 index 0000000..5b2f2ab --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeView.cs @@ -0,0 +1,239 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace UnityTutorialSystem.UI.Trees +{ + /// + /// + /// A TreeView component. This class takes a Tree structure represented by the + /// and unrolls it into a rendered structure. + /// This base class does not track the expanded state of nodes, if you want to + /// support this use the method to influence whether + /// collapsed nodes are shown. + /// + /// + /// This class will generate a (pooled) copy of the a template TreeItemRenderer + /// game-object and behaviour and expects that the child nodes of the RectTransform + /// are laid out correctly by an independent LayoutElement behaviour attached to the + /// same GameObject. + /// + /// This class is abstract because it uses generics and unity does not like that. + /// + /// + public abstract class TreeView : MonoBehaviour + { + readonly List> pool; + [SerializeField] bool showRootNode; + ITreeModel model; + + /// + protected TreeView() + { + pool = new List>(); + } + + /// + /// Defines whether the root node of the model will be visible. + /// If set to false, this tree will look as if it is a list of + /// independent sub trees and nodes. + /// + public bool ShowRootNode + { + get { return showRootNode; } + set + { + showRootNode = value; + OnModelUpdated(); + } + } + + /// + /// The TreeModel that provides the data for this component. The + /// tree will update in response to the events fired by the model. + /// + public ITreeModel Model + { + get { return model; } + set + { + if (model != null) + { + model.NodesChanged -= OnNodesChanged; + model.NodesInserted -= OnNodesInserted; + model.NodesRemoved -= OnNodesRemoved; + model.StructureChanged -= OnStructureChanged; + } + + model = value; + if (model != null) + { + model.NodesChanged += OnNodesChanged; + model.NodesInserted += OnNodesInserted; + model.NodesRemoved += OnNodesRemoved; + model.StructureChanged += OnStructureChanged; + } + + OnModelUpdated(); + } + } + + /// + /// A TreeItemRenderer. The renderer will be cloned via + /// + /// for each node in the tree. This TreeView implementation here + /// expects that all calls to this property return the same instance + /// for the lifetime of this object. + /// + /// This property is abstract to work around Unity's Generics limitations. + /// + protected abstract TreeItemRenderer ItemRenderer { get; } + + /// + /// Called when the script instance is loaded. This simply disables the + /// template item renderer game object. + /// + protected virtual void Awake() + { + if (ItemRenderer != null) + { + ItemRenderer.gameObject.SetActive(false); + } + } + + /// + /// Called when the tree model has changed. + /// + /// The tree model that caused this event. + /// The tree model change event arguments. + protected virtual void OnStructureChanged(object sender, TreeModelEventArgs e) + { + OnModelUpdated(); + } + + /// + /// Called when the tree model has changed. + /// + /// The tree model that caused this event. + /// The tree model change event arguments. + protected virtual void OnNodesRemoved(object sender, TreeModelEventArgs e) + { + OnModelUpdated(); + } + + /// + /// Called when the tree model has changed. + /// + /// The tree model that caused this event. + /// The tree model change event arguments. + protected virtual void OnNodesInserted(object sender, TreeModelEventArgs e) + { + OnModelUpdated(); + } + + /// + /// Called when the tree model has changed. + /// + /// The tree model that caused this event. + /// The tree model change event arguments. + protected virtual void OnNodesChanged(object sender, TreeModelEventArgs e) + { + OnModelUpdated(); + } + + /// + /// Callback handler that is invoked in response to data changes. + /// + protected virtual void OnModelUpdated() + { + if ((model == null) || (model.HasRoot == false)) + { + foreach (var p in pool) + { + p.Path = null; + p.gameObject.SetActive(false); + //p.transform.SetParent(null, false); + } + + return; + } + + var r = model.Root; + var usedNodes = RefreshNodes(TreePath.From(r), 0, ShowRootNode); + for (var i = usedNodes; i < pool.Count; i += 1) + { + var p = pool[i]; + p.Path = null; + p.gameObject.SetActive(false); + //p.transform.SetParent(null, false); + } + } + + /// + /// Internal method that is called as part of the rebuilding of render nodes after + /// data in the model has changed. Refreshes the tree. + /// + /// The node to refresh + /// The index of the next free node in the ItemRenderer pool + /// a flag indicating whether the current node is visible. + /// Normally we would not process invisible nodes, but the root node can be + /// invisible and still contain visible child nodes if is set to false. + /// + /// A pointer to the next free node in the TreeItemRenderer pool. + protected virtual int RefreshNodes(TreePath node, int nextNodeIndexInPool, bool visible) + { + while (pool.Count <= nextNodeIndexInPool) + { + pool.Add(InstantiateRenderer()); + } + + if (!IsPathVisible(node)) + { + return nextNodeIndexInPool; + } + + if (visible) + { + var r = pool[nextNodeIndexInPool]; + //r.transform.SetParent(transform, false); + r.Path = node; + r.gameObject.SetActive(true); + nextNodeIndexInPool += 1; + } + + T t; + if (node.TryGetLastComponent(out t)) + { + var count = model.ChildCount(t); + for (var i = 0; i < count; i += 1) + { + var child = model.GetChildAt(t, i); + nextNodeIndexInPool = RefreshNodes(node.Append(child), nextNodeIndexInPool, true); + } + } + + return nextNodeIndexInPool; + } + + /// + /// Checks whether this tree-path should be visible in the rendered tree. + /// + /// The TreePath to check + /// true, if the node should show, false otherwise. + protected virtual bool IsPathVisible(TreePath path) + { + return true; + } + + /// + /// A helper method that instantiates a new ItemRenderer. + /// + /// + protected virtual TreeItemRenderer InstantiateRenderer() + { + var itemRenderer = Instantiate(ItemRenderer); + var rtransform = itemRenderer.transform; + rtransform.SetParent(transform, false); + return itemRenderer; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeView.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeView.cs.meta new file mode 100644 index 0000000..aeaba77 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/Trees/TreeView.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 12b7756f8361458788b8fcdcce01dc2d +timeCreated: 1546536320 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/VisibleDuringEdit.cs b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/VisibleDuringEdit.cs new file mode 100644 index 0000000..b5f4c1b --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/VisibleDuringEdit.cs @@ -0,0 +1,21 @@ +using UnityEngine; + +namespace UnityTutorialSystem.UI +{ + /// + /// A small helper that deactivates template elements when not in the editor. + /// Template elements are instantiated via a script, which also takes care of + /// setting the newly instantiated game object active. + /// + public class VisibleDuringEdit : MonoBehaviour + { + void Awake() + { + if (Application.isPlaying) + { + Debug.Log("Hiding " + name); + gameObject.SetActive(false); + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UI/VisibleDuringEdit.cs.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/VisibleDuringEdit.cs.meta new file mode 100644 index 0000000..a33b545 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UI/VisibleDuringEdit.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 626299593e724090a1512265b83f574f +timeCreated: 1546534943 \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UnityTutorialSystem.asmdef b/Assets/Plugins/UnityTutorialSystem/Scripts/UnityTutorialSystem.asmdef new file mode 100644 index 0000000..5f8e42b --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UnityTutorialSystem.asmdef @@ -0,0 +1,15 @@ +{ + "name": "UnityTutorialSystem", + "references": [ + "NaughtyAttributes", + "Unity.TextMeshPro" + ], + "optionalUnityReferences": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [] +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Scripts/UnityTutorialSystem.asmdef.meta b/Assets/Plugins/UnityTutorialSystem/Scripts/UnityTutorialSystem.asmdef.meta new file mode 100644 index 0000000..0a9fe5f --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Scripts/UnityTutorialSystem.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 21d86dcf9d039d74ebea76df0aed66ab +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Sound-License.txt b/Assets/Plugins/UnityTutorialSystem/Sound-License.txt new file mode 100644 index 0000000..049a702 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Sound-License.txt @@ -0,0 +1,17 @@ + + +piano.wav: + + Created by lomographicmusic, licensed under CC-BY 3.0 license. + https://freesound.org/people/lomographicmusic/sounds/382482/ + +slam.wav: + + Created by Goup_1, licensed under CC-BY 3.0 license. + https://freesound.org/people/Goup_1/sounds/176532/ + +tada3.mp3: + + Created by usinggarageband, licensed under CC-BY 3.0 license. + https://freesound.org/people/usinggarageband/sounds/152574/ + \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Sound-License.txt.meta b/Assets/Plugins/UnityTutorialSystem/Sound-License.txt.meta new file mode 100644 index 0000000..df83e4c --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Sound-License.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 6a52952a0b50c7e4b9926e5066727828 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Tests.meta b/Assets/Plugins/UnityTutorialSystem/Tests.meta new file mode 100644 index 0000000..db14904 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Tests.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b0b5c162315037143a7fcf9dc919f141 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Tests/TreePathTest.cs b/Assets/Plugins/UnityTutorialSystem/Tests/TreePathTest.cs new file mode 100644 index 0000000..e013ed6 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Tests/TreePathTest.cs @@ -0,0 +1,29 @@ +using FluentAssertions; +using NUnit.Framework; +using UnityTutorialSystem.UI.Trees; + +namespace Tests +{ + public class TreePathTest + { + // A Test behaves as an ordinary method + [Test] + public void Append_On_Empty_Creates_Valid_Path() + { + var root = TreePath.Empty(); + var result= root.Append("One"); + result.Count.Should().Be(1); + result[0].Should().Be("One"); + } + + // A Test behaves as an ordinary method + [Test] + public void Append_On_Path_Creates_Valid_Path() + { + var root = TreePath.From("One", "Two"); + var result= root.Append("Three"); + result.Count.Should().Be(3); + result[2].Should().Be("Three"); + } + } +} diff --git a/Assets/Plugins/UnityTutorialSystem/Tests/TreePathTest.cs.meta b/Assets/Plugins/UnityTutorialSystem/Tests/TreePathTest.cs.meta new file mode 100644 index 0000000..617f6ee --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Tests/TreePathTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 95e0de82a0c5a484fbecdf563d88ce8e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/Tests/UnityTutorialSystem.Tests.asmdef b/Assets/Plugins/UnityTutorialSystem/Tests/UnityTutorialSystem.Tests.asmdef new file mode 100644 index 0000000..8d53d34 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Tests/UnityTutorialSystem.Tests.asmdef @@ -0,0 +1,19 @@ +{ + "name": "UnityTutorialSystem.Tests", + "references": [ + "UnityTutorialSystem", + "FluentAssertions" + ], + "optionalUnityReferences": [ + "TestAssemblies" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [] +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/Tests/UnityTutorialSystem.Tests.asmdef.meta b/Assets/Plugins/UnityTutorialSystem/Tests/UnityTutorialSystem.Tests.asmdef.meta new file mode 100644 index 0000000..8065c7d --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/Tests/UnityTutorialSystem.Tests.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 30607f09b7a3b0346ab7ea530e2656b7 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/UnityTutorialSystem/package.json b/Assets/Plugins/UnityTutorialSystem/package.json new file mode 100644 index 0000000..0f91130 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/package.json @@ -0,0 +1,12 @@ +{ + "name": "com.rabbitstewdio.unitytutorialsystem", + "displayName": "Unity Tutorial System", + "version": "0.0.1", + "unity": "2018.3", + "description": "A event driven system to implement in-game tutorials and success and failure trackers.", + "keywords": [ + "in-game tutorials", + "unity" + ], + "category": "Unity" +} \ No newline at end of file diff --git a/Assets/Plugins/UnityTutorialSystem/package.json.meta b/Assets/Plugins/UnityTutorialSystem/package.json.meta new file mode 100644 index 0000000..726e0b7 --- /dev/null +++ b/Assets/Plugins/UnityTutorialSystem/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 760276944df581247a57cc0cac21f035 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro.meta b/Assets/TextMesh Pro.meta new file mode 100644 index 0000000..f9da8b5 --- /dev/null +++ b/Assets/TextMesh Pro.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f54d1bd14bd3ca042bd867b519fee8cc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources.meta b/Assets/TextMesh Pro/Resources.meta new file mode 100644 index 0000000..cfc142f --- /dev/null +++ b/Assets/TextMesh Pro/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 243e06394e614e5d99fab26083b707fa +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials.meta b/Assets/TextMesh Pro/Resources/Fonts & Materials.meta new file mode 100644 index 0000000..8a01112 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 731f1baa9d144a9897cb1d341c2092b8 +folderAsset: yes +timeCreated: 1442040525 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Drop Shadow.mat b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Drop Shadow.mat new file mode 100644 index 0000000..403fbaf --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Drop Shadow.mat @@ -0,0 +1,103 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: LiberationSans SDF - Drop Shadow + m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3} + m_ShaderKeywords: OUTLINE_ON UNDERLAY_ON + m_LightmapFlags: 5 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + 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: 2846298, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + 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_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _Diffuse: 0.5 + - _DiffusePower: 1 + - _FaceDilate: 0.1 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 10 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0.1 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 0.73125 + - _ScaleRatioC: 0.64125 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0.5 + - _UnderlayOffsetY: -0.5 + - _UnderlaySoftness: 0.05 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _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} diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Drop Shadow.mat.meta b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Drop Shadow.mat.meta new file mode 100644 index 0000000..fbd2cdb --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Drop Shadow.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e73a58f6e2794ae7b1b7e50b7fb811b0 +timeCreated: 1484172806 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Outline.mat b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Outline.mat new file mode 100644 index 0000000..0d3303a --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Outline.mat @@ -0,0 +1,101 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: LiberationSans SDF - Outline + m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3} + m_ShaderKeywords: OUTLINE_ON + m_LightmapFlags: 5 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: 3000 + stringTagMap: {} + disabledShaderPasses: [] + 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: 2846298, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + 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_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _Diffuse: 0.5 + - _FaceDilate: 0.1 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 10 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0.1 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 0.73125 + - _ScaleRatioC: 0.64125 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _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} diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Outline.mat.meta b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Outline.mat.meta new file mode 100644 index 0000000..88d6334 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Outline.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 79459efec17a4d00a321bdcc27bbc385 +timeCreated: 1484172856 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF.asset b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF.asset new file mode 100644 index 0000000..dcf2d70 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF.asset @@ -0,0 +1,3886 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2180264 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: LiberationSans SDF Material + m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3} + m_ShaderKeywords: _EMISSION + m_LightmapFlags: 1 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + 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} + - _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} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2846298} + 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} + - _OutlineTex: + 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_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _BumpScale: 1 + - _ColorMask: 15 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _Diffuse: 0.5 + - _DstBlend: 0 + - _FaceDilate: 0 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 10 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0 + - _Parallax: 0.02 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 0.73125 + - _ScaleRatioC: 0.73125 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SpecularPower: 2 + - _SrcBlend: 1 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UVSec: 0 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + - _ZWrite: 1 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _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} +--- !u!28 &2846298 +Texture2D: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: LiberationSans SDF Atlas + m_ImageContentsHash: + serializedVersion: 2 + Hash: 00000000000000000000000000000000 + m_ForcedFallbackFormat: 4 + m_DownscaleFallback: 0 + serializedVersion: 2 + m_Width: 1024 + m_Height: 1024 + m_CompleteImageSize: 1048576 + m_TextureFormat: 1 + m_MipCount: 1 + m_IsReadable: 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 + image data: 1048576 + _typelessdata: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000204050607080909090908080706050402010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020202020202020201000000000000000000000000000000000000000000000000020406070808070706040100000000000000000000000000000000010305070708080706050300000000000000000000000000000000000000000000000004070808080808080808080807050200000000000000000000000000000000000000000000000001050708080808080808080808080808080808080808080808080808080808080808080808080808080808080808070501000000000000000000000000000000000000000000000000000000000000020608080808080808080808080807040000000000000000000000000000000000000000020507080808080808080808080807040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000102020202020202020000000000000000000000000000000000000000000000000000000000000001040607080808080705030100000000000000000000000000000000000000000000000000000000000000000000000004060808080808080808070502000000000000000000000000000000000003060707070707070707070707070707070707070707070707070707070503000000000000000000000000000000000000000000000000000004060808080808080808070502000000000000000000000000000000000000000000000000000000000000020507070707070707070502000000000000000000000000000000000000000000000000000000000005090c0e0f0f0f0f0f0f0f0e0c080300000000000000000000000000000000000000000000000000000002070a0d0d0d0d0d0d0d0d0c090500000000000000000000000000000002070b0e101010101010101010100e0c07020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010407090b0c0e0f1010111110100f0e0d0c0a0806030000000000000000000000000000000000000000000000000000000000000000000005090c0e0e0e0e0e0e0e0e0e0e0d0a07020000000000000000000000000000000000000000000000000000000000000001060a0c0e0e0e0e0e0e0e0e0e0e0c090500000000000000000000000000000000000000000000000000000000000000030507080808080808080808060300000000000000000000000000000000000000000000000000000000000000000000000000000205080a0d0f1012131415151515151515141312100f0d0b09070402000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001060a0d0e0f0f0f0f0f0f0f0e0c080300000000000000000000000000000000000005090c0f1113141415141312100e0b07030000000000000000000003070a0d1012131415141413110f0d090601000000000000000000000000000000000000060c10131515151515151515151514110e0902000000000000000000000000000000000000000002080d11141515151515151515151515151515151515151515151515151515151515151515151515151515151515151514110d08020000000000000000000000000000000000000000000000000000040a0e1214151515151515151515151513100c060000000000000000000000000000000003090e1214151515151515151515151513110c070000000000000000000000000000000000000000000000000000000000000000000000000000000003080b0e0f0f0f0f0f0f0f0e0d0a060100000000000000000000000000000000000000000000000002070a0e101214151515141312100d0a060200000000000000000000000000000000000000000000000000000000000000060b1013151515151515151514110e080200000000000000000000000000060c1012141414141414141414141414141414141414141414141414141414120f0b0500000000000000000000000000000000000000000000060b1013151515151515151514110e08020000000000000000000000000000000000000000000000000000040a0e111314141414141413110e090400000000000000000000000000000000000000000000000000030a1015191b1b1b1b1b1b1b1b1a18140f0801000000000000000000000000000000000000000000000000070e1317191a1a1a1a1a1a1a1815110b04000000000000000000000000060d13181b1d1d1d1d1d1d1d1d1d1d1b18130d060000000000000001040607090a0a0b0b0b0b0b0a090807050301000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003070b0e11131517191a1c1c1d1d1d1d1d1c1b1a181714120f0c09050100000000000000000000000000000000000000000000000000000000040b1115191a1a1a1a1a1a1a1a1a1a1917130d070000000000000000000000000000000000000000000000000000000000060c1216191a1a1a1a1a1a1a1a1a1a1916110b05000000000000000000000000000000000000000000000000000105090d101213141515151515151515130f0b0500000000000000000000000000000000000000000000000000000000000000000004080b0f121417191b1d1e20212122222222222121201e1d1c1a181613110e0b080501000000000000000000000000000000000000000000000000000000000000000000000000000000050c12161a1b1b1b1b1b1b1b1b1a18140f08010000000000000000000000000001070c1115181b1e1f21212121201f1d1a17140f0b05000000000000040a0f13171a1c1f2021212121201e1c1916120d08020000000000000000000000000000020a11181c2021222222222222222222211e19140d05000000000000000000000000000000000000050d13191e2022222222222222222222222222222222222222222222222222222222222222222222222222222222222222201e19130d05000000000000000000000000000000000000000000000000070e151a1e212222222222222222222221201c18110a0200000000000000000000000000060e151a1e212222222222222222222222201d18120b0300000000000000000000000000000000000000000000000000000000000000000000000001080f14181a1b1b1b1b1b1b1b1b1a17120c0600000000000000000000000000000000000000000004090e13171a1d1f2021222221201e1c1916120d0803000000000000000000000000000000000000000000000000000000010911171c1f2122222222222222201e19140d0500000000000000000000030a11171c1f2020202020202020202020202020202020202020202020202020201f1b17110a02000000000000000000000000000000000000010911171c1f2122222222222222201e19140d05000000000000000000000000000000000000000000000000080f151a1e20202020202020201e1a150e070000000000000000000000000000000000000000000000050d151c212527282828282828282724201a130b02000000000000000000000000000000000000000000010a12191f23262727272727272725211c160f06000000000000000000000810181e2427292a2a2a2a2a2a2a2a2927241f18110800000205080b0e10121415161718181818181716151312100d0b0804010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002070b0f13171a1d202224262728292a2a2a2a2a2928272523211f1c1915120d090500000000000000000000000000000000000000000000000000060e161c21252727272727272727272726231e1811090000000000000000000000000000000000000000000000000000000810171d22262727272727272727272725221d160f070000000000000000000000000000000000000000000001070d1115191c1e202122222222222222211f1b161009000000000000000000000000000000000000000000000000000000000002070c1014171b1e212326282a2b2c2d2e2f2f2f2f2e2e2d2c2b2a28262422201d1b1814110e0a060200000000000000000000000000000000000000000000000000000000000000000000000710171d222628282828282828282724201a130b020000000000000000000000060d13181d2125282a2c2d2e2e2e2d2b292724201b16110a040000030910151a1f2326292b2d2e2e2e2d2c2b2825221e19130e07000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2d2a251f170f0600000000000000000000000000000000050e171e252a2d2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2d2a251e170e050000000000000000000000000000000000000000000007101920262b2e2e2e2e2e2e2e2e2e2e2e2e2c28231c140b02000000000000000000000007101820262a2d2e2e2e2e2e2e2e2e2e2e2e2c29231d150c0300000000000000000000000000000000000000000000000000000000000000000000020b131a202427282828282828282826231e17100700000000000000000000000000000000000002090f151a1f2326292b2d2e2e2e2e2d2b2926221e19140e0801000000000000000000000000000000000000000000000000010a131b22282c2e2e2e2e2e2e2e2e2d2a251f170f050000000000000000030c151c23282b2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2b27221b140b0200000000000000000000000000000000010a131b22282c2e2e2e2e2e2e2e2e2d2a251f170f050000000000000000000000000000000000000000000009111920262a2d2d2d2d2d2d2d2d2a2620191108000000000000000000000000000000000000000000030d171f272d31343535353535353534302b251d140b0100000000000000000000000000000000000000000a131c242a2f3234343434343433312d2820180f06000000000000000007111a222a2f343636363636363636363634302a221a11070a0e1215181a1d1f202223242425252524242322201e1c1a1714110d090500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e13171c1f2326292c2f3132343536363737373636353332302e2b2825211e1a15100b0600000000000000000000000000000000000000000000050f1820272d3134343434343434343434332f2a231b12090000000000000000000000000000000000000000000000000007111a22292e3234343434343434343434322e28211910060000000000000000000000000000000000000000060c13181d2225282b2d2e2e2e2e2e2e2e2e2e2b27211a1209000000000000000000000000000000000000000000000000000004090e13181c2024272a2d3032343638393a3b3b3c3c3c3b3b3a3938363533312f2c2a2724211d1a16120e0a05010000000000000000000000000000000000000000000000000000000000000006101921292e32353535353535353534302b251d140b010000000000000000020a11181e24292d313437393a3b3b3a3a383633302c27221c150e07060d141b21262b2f333538393a3b3b3a393735322e29241f19120b03000000000000000000000a141d262e34383b3b3b3b3b3b3b3b3b3b3a36302921180e030000000000000000000000000000030d1720293036393b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3936302920170d030000000000000000000000000000000000000000051019222b31373a3b3b3b3b3b3b3b3b3b3b3b38342e261d140a00000000000000000000050f19222a31363a3b3b3b3b3b3b3b3b3b3b3b39352e271e150b000000000000000000000000000000000000000000000000000000000000000000000a141d242b30343535353535353535332f292219100700000000000000000000000000000000050d141a20262b2f3336383a3b3b3b3b393835322e2a251f19120b04000000000000000000000000000000000000000000000009131c252d33383b3b3b3b3b3b3b3b3a36302921170d03000000000000000b151e262e34383a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a37332d251d13090000000000000000000000000000000009131c252d33383b3b3b3b3b3b3b3b3a36302921170d03000000000000000000000000000000000000000007111b232b3237393a3a3a3a3a3a3936312b231a100600000000000000000000000000000000000000000b151f2931383e4142424242424242403c362f261d12080000000000000000000000000000000000000007121c252e353b3f404040404040403e39322a21170d02000000000000030e18232c343b4043434343434343434343403b342c231912161a1e212427292b2d2f30313132323231302f2e2d2b292623201d1915110c07020000000000000000000000000000000000000000000000000000000000000000000000000000000002090e14191f23282c2f3336393b3d3f40424343444443434241403e3c3a3734312e2a26211c17110c0600000000000000000000000000000000000000020d17212a32393e404141414141414141413f3b352d241b11060000000000000000000000000000000000000000000000040f19232c343a3e414141414141414141403e39332b22180d020000000000000000000000000000000000010910171e24292e323537393b3b3b3b3b3b3b3b3b38332c241b1208000000000000000000000000000000000000000000000003090f151a1f23282c3033373a3c3f4143444647484848484848484746454341403e3b393633302d2a26221e1a16110c080200000000000000000000000000000000000000000000000000000000030e18222b333a3f4142424242424242403c362f261d120800000000000000030c141b23292f34393d41434547474847464542403c38332d2720191110181f262c32373b3f424446474847474644413e3a35302a241d150d05000000000000000006111c262f383f454848484848484848484846423b332a1f150a000000000000000000000000000009141f29323b41464848484848484848484848484848484848484848484848484848484848484848484848484848484848484846413b32291f140900000000000000000000000000000000000000010c17222b343c43474848484848484848484848453f382f261c11060000000000000000000b16212b343c4246484848484848484848484845403930271d1207000000000000000000000000000000000000000000000000000000000000000007121c262f363c4042424242424242413f3a332b22190e040000000000000000000000000000070f171e252c31373b3f424546484848474644423e3a36302a241d160e05000000000000000000000000000000000000000000040f1a252e373f44474848484848484846413b33291f150a00000000000007121d2730383f44474747474747474747474747474747474747474747474747474746443e372f251b10050000000000000000000000000000040f1a252e373f44474848484848484846413b33291f150a00000000000000000000000000000000000000020e19232d353d434647474747474746423c352c22180d0200000000000000000000000000000000000005111c27313b43494d4e4e4e4e4e4e4e4d4841382f24190f040000000000000000000000000000000000020d18232e3740474b4d4d4d4d4d4d4d4a443c33291f140800000000000009141f2a343e464c4f50505050505050504f4c463e352b211e22262a2e313336383a3b3c3d3e3e3e3e3e3d3c3b39373533302d2925211d18130d070200000000000000000000000000000000000000000000000000000000000000000000000000070d141a20252a2f34383c3f4245484a4c4d4e4f50505050504f4e4d4b494744413e3a36312d28221d17110a03000000000000000000000000000000000008131e29333c444a4d4d4d4d4d4d4d4d4d4d4b463f362d22170c00000000000000000000000000000000000000000000000a15202b353e454b4d4d4d4d4d4d4d4d4d4d4a443d342a1f140800000000000000000000000000000000020a131b22292f353a3e414446474848484848484847443e362d24190e03000000000000000000000000000000000000000001080e141a20252b2f34383c404346494b4e5051535454555555555554535251504e4c4a484543403d3936322e2a26221d18130e0903000000000000000000000000000000000000000000000000000009141f2a343d454b4e4e4e4e4e4e4e4e4d4841382e24190f040000000000030d151e262d343a4045494d50525354545453514f4c48433e38322b231b1a222931373d43474b4e51535454545352504d4a46413b352e271f170e05000000000000000b17222d38424a5154555555555555555555524d453c31261b1004000000000000000000000000030e1a26313b444c5255555555555555555555555555555555555555555555555555555555555555555555555555555555555555524c443b31261a0e0300000000000000000000000000000000000006121d28333d464e535555555555555555555554514a42382d22170b000000000000000005111c28333d464e535555555555555555555554514b42392e23180c00000000000000000000000000000000000000000000000000000000000000020d19242e3841484c4e4e4e4e4e4e4e4e4b453d342b20150b00000000000000000000000000071019212930373d42474b4f51535455555453514e4a46413c352f2720170f0600000000000000000000000000000000000000000915212c364049505455555555555555524c453b31261b110600000000000c18232e39424a50535353535353535353535353535353535353535353535353535353504941372d22160b00000000000000000000000000000915212c364049505455555555555555524c453b31261b110600000000000000000000000000000000000008141f2a353f474e52535353535353524e473e34291e13070000000000000000000000000000000000000a16222d39434d555a5b5b5b5b5b5b5b59534a40362b20150b000000000000000000000000000000000006121e2a35404952585a5a5a5a5a5a59554e453b3025190d0100000000000d1925313c4650575c5d5d5d5d5d5d5d5d5c5850473d332a2a2e33363a3d4042454648494a4b4b4b4b4b4a49484644423f3c3935312d28241e19130d0600000000000000000000000000000000000000000000000000000000000000000000030b12181f252b31363b4044484b4f525456585a5b5c5d5d5d5d5c5c5b59575553504d4a46423d39332e28221c150e07000000000000000000000000000000000c1824303b454e555a5a5a5a5a5a5a5a5a5a5751493f34281d1105000000000000000000000000000000000000000000030f1b26323d4750565a5a5a5a5a5a5a5a5a5a564f463b3025190d010000000000000000000000000000010b141c252c343a40454a4e51535455555555555555544f483f352b20140800000000000000000000000000000000000000050c131920262b31363b4044484c4f5355585a5c5e5f6061626262626161605f5e5c5b595754524f4c4946423e3a36322e29241f1a140f09030000000000000000000000000000000000000000000000010d1925313c464f565b5b5b5b5b5b5b5b59534a40362b20160b00000000020c151f2730383f454c5155595c5f60616161605e5b58544f4a433c352d24232c343b42494e53575b5d5f616161605f5d5a56524c474039312920170e040000000000000f1b27333f4a545c616161616161616161615e574d43372c20150a00000000000000000000000006131f2b37424d565e616161616161616161616161616161616161616161616161616161616161616161616161616161616161615e564d42372b1f13060000000000000000000000000000000000000a16222e3a454f585f61616161616161616161615c544a3f33271b0f03000000000000000915212d39444f585f61616161616161616161615c544b4034281c100400000000000000000000000000000000000000000000000000000000000006121e2a35404a52595b5b5b5b5b5b5b5b574f463c32271c12070000000000000000000000071019222b333a42484e53575b5e60616161615f5d5a57524d474039312921180f05000000000000000000000000000000000000000d1a26323d48525b60616161616161615e574d43382d22170d0200000004101d2934404a545c6060606060606060606060606060606060606060606060606060605b53493e33271b0f03000000000000000000000000000d1a26323d48525b60616161616161615e574d43382d22170d0200000000000000000101010101010101010c1824303c4751595f6060606060605f5950463b2f23170b0000000000000000000000000000000000000d1a26323e4a555f6668686868686868645c52473d32271c1106000000000001050707070707070707070916222e3b46515b636767676767676660574d4135291d10040000000000101d2935414d58626869696969696969696862594f453b32363a3f4346494c4f5153555657575858585757565453514e4c4845413d39342f2a241e18110a0300000000000000000000000000000000000000000000000000000000000000060e151c232a30363c42474b5054585b5e616365676869696a6a6a696867666462605d5956524e49443f39332d272019110a020000000000000000000000000000101c2935414c576066676767676767676767635b5045392d21160a00000000000000000000000000000000000000000008141f2b37434e59616767676767676767676661574d4135291d110400000000000000000000000000000a131d262e373e454c51565a5d5f6161616161616161605a51473c3025180c0000000000000000000000000000000000010810171e242b31373d42474c5054585c5f626467696a6c6d6e6e6f6f6f6e6e6d6c6b69676563615e5c5955524e4b47423e3935302b25201a140e080200000000000000000000000000000000000000000004111d2936424d58616768686868686868645c52473d32271d12070000000a141e273139424950575d6166696b6d6d6e6d6c6a6864605b554e473f372e2c353d454d545a5f64676a6c6d6e6e6d6b6966625d58524b433b322920160c020000000000121e2b37434f5b666d6e6e6e6e6e6e6e6e6e695f54493d32261b0f0400000000000000000000000915222f3b47535e686e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e685e53473b2f2215090000000000000000000000000000000000010d1a26323e4a56616a6e6e6e6e6e6e6e6e6e6e6d665b5044372b1f1306000000000000000c1925313d4a55616a6e6e6e6e6e6e6e6e6e6e6d665c5145382c2014070000000000000000000000000000000000000000000000000000000000000916222e3b46525c64686868686868686761584e43392e23190e03000000000000000000050f18222b343d454c53595f63676a6c6e6e6e6d6c6a67635e58524b433b332a21170d03000000000000000000000000000000000000101d2936424e5a646c6e6e6e6e6e6e6e695f54493f34291e13080000000713202c3945515c666c6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6c655b4f43372b1e120500000000000000000000000000101d2936424e5a646c6e6e6e6e6e6e6e695f54493f34291e1308000000000004090c0d0e0e0e0e0e0e0e0e0f1b2834404c58636b6d6d6d6d6d6d6a62574c4033271a0e0100000000000000000000000000000000000f1c2935424e5b6671757575757575756e64594e43382e23180d02000003090d11131414141414141414141825313e4a57636d73737373737372695e5145392c1f13060000000000121f2c3845515e6a747676767676767676746b61574d443c42464b4f5256595b5e6061636364656565646362615f5d5b5855514d4945403b352f29231c150e0600000000000000000000000000000000000000000000000000000000000810181f272e353b42474d52575c6064676a6d70727375757677777676757473716f6c6966625e5a55504a453f38312a231c140c0400000000000000000000000000121f2b3844515d69727474747474747474746c61564a3e32261a0e0300000000000000000000000000000000000000000c1824303c48545f6b73747474747474747472695e5245392c1f13060000000000000000000000000007111c252f38404850575d6266696c6d6e6e6e6e6e6e6e6c63594d4134281b0f00000000000000000000000000000000030b131a21282f363c42484e53585c6064686b6e71737577797a7b7b7b7b7b7b7a7a7977767472706d6b6865625e5b57534e4a45403b36312b251f19130c05000000000000000000000000000000000000000006131f2c3945525e6a73757575757575756e64594e44392e24190e040007121c263039434b545b62686d727578797a7b7a797774706c66605951494036353e474f575f656b707476797a7b7a7a7876726e69635c554d443b32281e1409000000000013202c3946525f6c777b7b7b7b7b7b7b7b7b7065594e42372c20150900000000000000000000000a1724303d4a56636f7a7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7a6f63564a3d3024170a000000000000000000000000000000000005111d2936424e5a67737b7b7b7b7b7b7b7b7b7b786c6053473b2e22160a00000000000003101c2834414d5966727b7b7b7b7b7b7b7b7b7b786d6154483c3023170b0000000000000000000000000000000000000000000000000000000000000b1825313e4a57636e74757575757575736a60554a40352a20150a0000000000000000010c16212a343d464f575e656a6f7377797a7b7b7a7976736e69635d554d453c33291f150b000000000000000000000000000000000000111e2b3744515e6a767b7b7b7b7b7b7a71665b50453a30251a0f0400000815212e3b4854616d787a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a776c5f5346392d20130600000000000000000000000000111e2b3744515e6a767b7b7b7b7b7b7a71665b50453a30251a0f040000030a1015181a1a1a1a1a1a1a1a1a1a1d293643505c69747a7a7a7a7a7a74685b4f4235291c0f070000000000000000000000000000000000101c2936434f5c697681828282828280756b60554a3f342a1f140900060d14191d202121212121212121212126323f4c5965727f8181818181796d6053463a2d20150f0700000000121f2c3945525f6b7882838383838383837d73695f564c484d52575b5f6265686a6c6e6f707171717171706f6e6c6a6764615e5a55514c46413b342e272018110900000000000000000000000000000000000000000000000000000009111a222a313840464d53595e63686c7074777a7c7e808182838484838382817f7d7b7875726e6a66615b56504a433c352d261e160d05000000000000000000000000131f2c3946525f6c7981818181818181817e72665a4e42372b1f13070000000000000000000000000000000000000005111d2935404c5864707c8181818181818181796d6053463a2d201307000000000000000000000000030e19232d37414a525a62686e7276787a7b7b7b7b7b7b7b75695c5043362a1d10000000000000000000000000000000040c151d242c333a41474e53595e63686c7174787b7d80828485868788888888888786858482817e7c7a7774716e6a67635f5a56514c47423c37312b241e170f07000000000000000000000000000000000000000713202d3a4653606d7982828282828280756b60554b40352b20150b030e19232e38424b555d656d73797e8284868788878684817c77716a635b52483f3d475059616970767b8083858787878685827e7a746e675f564d443a30251b100500000000131f2c3945525e6b76828888888888888882766b5f54483d31261a0f03000000000000000000000a1724303d4a5763707d88888888888888888888888888888888888888888888888888888888888888888888888888888888887d7063574a3d3024170a00000000000000000000000000000000000815212d3946525e6a76838888888888888888887c6f63574a3e3226190d01000000000007131f2c3844505d6975828888888888888888887d7064584c3f33271b0f0200000000000000000000000000000000000000000000000000000000000c1825323f4b5865727e8282828282827c71675c51473c31271c11070000000000000008131e28323c464f58616870767b8083868788888785837f7a756e675f574e453b31271c12070000000000000000000000000000000000111e2a3744505d69747f888888888882776c62574c41362c21160b00000915222f3c4855626f7b87878787878787878787878787878787878787878787878786796d6053463a2d20130700000000000000000000000000111e2a3744505d69747f888888888882776c62574c41362c21160b00050d151b212527272727272727272727272a3643505d697683878787878275695c4f4236291f19120a010000000000000000000000000000000f1b2835414d5965707a858e8e8e8e877c71665c51463b30261b10060f181f252a2d2e2e2e2e2e2e2e2e2e2e2e323f4c5965727f8c8d8d8d86796d6053463a2d2620191108000000111e2a37434f5b66707a848d909090908f857b71675e5454595e63676b6e727477797b7c7d7e7e7e7e7d7d7c7a787674716d6a66615c57524c463f38312a221b120a0200000000000000000000000000000000000000000000000009121b232c343b434a51585e646a6f74787c808386898b8d8e8f90909090908f8d8c8a8885827e7a76716c67615b554e473f3830281f170e050000000000000000000000121e2b3844505d6874808c8e8e8e8e8e8e83776b5f53473b2f24180c000000000000000000000000000000000000000a16212d3945515d6975818c8e8e8e8e8e8d8175695d5145382c1f13060000000000000000000000000a15202b353f49535c646c73797e8285878888888888888376695d5043362a1d100000000000000000000000000000050e161e272e363e454c52595f656a6f74787d8184878a8d8f909293949595959595949392918f8d8b898684817e7a77736f6b66625d58534d48423c362f292119100600000000000000000000000000000000000006121f2c3845515d68737d888e8e8e8e877c72675c52473c32271c1209141f2a35404a545d676f777e858a8e919394949492908d88837c756d645a5147454f59626b737b82878c909294949493918e8b86807871685f564c42372c21160b00000000111d2a36424e5965707c87939595959593877b7065594e42372b201409000000000000000000000a1724303d4a5763707d8a9595959595959595959595959595959595959595959595959595959595959595959595959595958a7d7063574a3d3024170a00000000000000000000000000000000000c1824313d4955626e7a8693959595959595958b7f73665a4e4235291d100400000000000a16232f3b4754606c798591959595959595958d8174685c4f43372b1e120600000000000000000000000000000000000000000000000000000000000b1724313d4a56616c77828c8e8e8e8e83786e63584e43382e23180e030000000000030f1a252f3a444e58616a737a81878c909294959594928f8b868079716960574d43382e23180d02000000000000000000000000000000000f1c2835414d58636e78838e959594897e73685e53483d32281d1207000916222f3c4855626f7b88949494949494949494949494949494949494949494949386796d6053463a2d201307000000000000000000000000000f1c2835414d58636e78838e959594897e73685e53483d32281d12070d171f262d313334343434343434343434343643505d6976839094948f8275695c4f42362f2a241c130a0000000000000000000000000000000c1925313d48535e69747e89949b998e83786d62584d42372c21170e1821293036393a3a3a3a3a3a3a3a3a3a3a3a3f4c5965727f8c999a9386796d6053463a37322b231a110600000f1b27333f4a545e68727b858f999d9d978d837970665c5f656a6f73777b7e81848687898a8a8b8b8b8a8a88878583807d7a76726d68635d57514a433c342c241c140b020000000000000000000000000000000000000000000008121b242d353d464d555c63696f757b8084898c90939597999b9c9c9d9d9d9c9b9a989794918e8b87827d78726c665f58514a423a312920170d0400000000000000000000101c2834404c58646f7b87939a9a9a9a93877b6f64584c4034281c11050000000000000000000000000000000000020e1a26323e4a56616d7985919a9a9a9a94887c7064584d4135291d1004000000000000000000000004101b26313c47515b656e767e858a8e92949595959595908376695d5043362a1d1000000000000000000000000000050e172028303940484f565d646a70767b8085898d909496999b9d9fa0a1a2a2a2a2a1a1a09f9d9c9a989593908d8a87837f7b77726e69645e59534d47413a332b22180d02000000000000000000000000000000000004101c2935404c56616c76818c969b998e83796e63594e43392e23190e1a25313c47515c666f79818990969a9d9d9b9b9b9e9c99948e877e766c63594e4c56616b747d858d93989c9f9c9b9b9c9e9b96918a837a71685e53493e33281c11050000000e1a26323d48545f6b76828d99a2a2a2988d81766a5f53483c31251a0e030000000000000000000a1724303d4a5763707d8a97a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2978a7d7063574a3d3024170a0000000000000000000000000000000003101c2834414d5965717e8a96a2a2a2a2a2a29b8f82766a5d5145392c20140700000000010d1a26323f4b5763707c8895a1a2a2a2a2a29c9084786b5f53473a2e22160a00000000000000000000000000000000000000000000000000000000000915212d3945505a65707a85909b9b958a80756a5f554a3f352a1f150a00000000000914202b36414c56606a737c858c92989c9d9a99999a9d9b97918b837b72695f554a40352a1f1308000000000000000000000000000000000c1824303b46515c67727c87929d9b90857a6f645a4f44392e23190e030916222f3c4955626f7c8996a0a0a09e9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9386796d6053463a2d201307000000000000000000000000000c1824303b46515c67727c87929d9b90857a6f645a4f44392e23190e151f2931383d4041414141414141414141414143505d697683909d9c8f8275695c4f423f3b352e251b110700000000000000000000000000000915202c37424c57626d78838d989f948a7f74695e53493e33281d16202a333b4246474747474747474747474747474c5965727f8c99a09386796d60534746433d352c23180d02000b17222d38424c566069737d87919ba49f958b82786e646a70757a7f83878a8d90929495969798989897969594928f8d8986827e79746e68625c554e463e362e261d140b02000000000000000000000000000000000000000007111a242d363f474f575f666e747b81868b9095989c9fa2a4a6a7a8a9a9a8a9a9a8a7a5a3a19e9a97938e89847e77716a635b544b433b32291f160d030000000000000000000c18242f3b47535f6b76828e9aa6a7a4988c8074685c5145392d211509000000000000000000000000000000000007131f2b37424e5a66727e8a96a2a7a79b8f83776b5f54483c3024180d0000000000000000000000000915212c38434e59636d77808890969b9ea0a1a2a2a29d908376695d5043362a1d10000000000000000000000000040e172029323a424a525a61686f757b81878c9195999da0a29f9c9a99979696959595969697989a9c9da0a29f9d9a96938f8b87837e79746f6a645e58524c453d34291f13080000000000000000000000000000000000000c18242f3a454f5a656f7a858f9aa0958b80756a60554a40352a20151f2b36424d58636d78828b939ba19a94918f8e8f91969c9f9891887e756a6055535d68737d868f979e9d97928f8e8e9093989f9c958c837a70655a4f44392d22160a0000000915202c37434e5a65717c88939faaa99e92877b7064594d42362b1f14080000000000000000000a1724303d4a5763707d8a97a4aeaeaea8a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a4978a7d7063574a3d3024170a0000000000000000000000000000000007131f2c3844505d6975818e9aa6aeaeacaeab9e9286796d6155483c3023170b0000000004111d2936424e5b6773808c98a4aeacacaeaca094887b6f63574a3e3226190d010000000000000000000000000000000000000000000000000000000005111d28333e49535e69747e89949e9c91867c71665c51463c31261c1106000000030e1a26313c48535d68727c868e969e9b95918d8c8c8e91969c9c958d847a71665c51463b3024190d0200000000000000000000000000000008141f2a35404a55606b76818b96a1968c81766b60554b40352a1f150a091623303c4956636f7c8996a2a89d938e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e86796d6053463a2d2013070000000000000000000000000008141f2a35404a55606b76818b96a1968c81766b60554b40352a1f151c27313b43494d4d4d4d4d4d4d4d4d4d4d4d4d4d505d697683909d9c8f8275695c4f4d4c4740372d23180d0100000000000000000000000000040f1a25303b46505b66717c87919c9b90867b70655a4f453a2f241c27323c454d5254545454545454545454545454545965727f8c99a09386796d605454534e473e342a1e13070006111c26303a444e58616b757f89929ca69d948a80766f757b81868b8f93979a9c9fa1a2a3a4a4a5a4a4a3a2a09e9c9996928e8a85807a746d665f58504840382f261d140a00000000000000000000000000000000000000050f19232c363f485159616971787f868c92979ca1a5a8a9a6a3a19f9d9c9c9c9c9c9e9fa1a3a6a9a7a39e9a958f89837c756d655d554d443b31281e150b01000000000000000007131f2b37424e5a66727d8995a1ada89c9185796d6155493d32261a0e02000000000000000000000000000000000c18232f3b47535f6b77838e9aa6aea2968a7e72675b4f43372b2014080000000000000000000000020e1a26313d49545f6a757f89929aa1a7a8a29d99979696908376695d5043362a1d100000000000000000000000030d162029323b444c545c646c737a80878d92979ca1a09c989592908e8c8a8a89888888898a8a8c8d8f919395989b9ea19f9b97938f8a85807b75706a645d574f463b3024190c00000000000000000000000000000000000007131e28333e48535e68737e89939e9c91877c71675c51473c31271c24303c47535e6974808a949d9f978f8984828182858a9199a29a91877c71665b59646f7a858f98a19b938c8683818283878d959e9e958c81776c61554a3e33271b0f030000040f1b26323d4954606b76828e99a4afa3988c81756a5e53473c3025190e0200000000000000000a1724303d4a5763707d8a97a4b0afa59d9898989898989898989898989898989898989898989898989898989898989898978a7d7063574a3d3024170a000000000000000000000000000000000b17232f3b4854606c7985919daaa8a19fa2a8a295897d7164584c3f33271b0e020000000814202d3945525e6a76838f9ba8a5a09fa3aba4978b7f73665a4e4235291d110500000000000000000000000000000000000000000000000000000000000c17222c37424c57626c77828d97a2988d83786d63584d43382d23180d03000007131f2b37424e59646f7a848e98a099918a84817f7f81858b929b9f968d83786e63584c41352a1e1206000000000000000000000000000000020e18232e39444e59646f7a858f9a9d92887d72675c51473c31261b10091623303c4956626f7b87929da5988c82828282828282828282828282828282828282796d6053463a2d20130700000000000000000000000000020e18232e39444e59646f7a858f9a9d92887d72675c51473c31261b222e39434d54595a5a5a5a5a5a5a5a5a5a5a5a5a5a5d697683909d9c8f8275695c5a5a5852493f34291d1206000000000000000000000000000009141e29343f4a555f6a75808b95a0978c82766c61564b40362b212d38444e575e61616161616161616161616161616165727f8c99a09386796d6161615f5950463b2f24170b00000a141e28323c464f59636d77818a949ea69c92887e7a81878d92979ba0a3a6a9a8a6a4a2a2a1a1a1a2a3a4a6a8a8a5a29e9a95908b857e78716a625a524a41382f261c12080000000000000000000000000000000000020d17212b353e48515a636b737b838a91979da3a8aba6a19d9996949291908f8f8f90919294979a9da1a6aaa5a09a948d867f776f675f564d433a30271d13080000000000000000020e1a26323d4955616d7884909ca8ada195897d72665a4e42362a1f130700000000000000000000000000000004101c2834404c58636f7b87939faba99d9185796e62564a3e32271b0f03000000000000000000000006121e2a36424e5a65717c87919ba4aca59d96918d8b8a89898376695d5043362a1d1000000000000000000000010b151e28323b444d565e666e767d858b92989ea39e9994908c898683817f7e7d7c7b7b7b7c7d7e7f81828487898c8f9295999da19f9b96918c86817b756f6861574c4135291c10030000000000000000000000000000000000010c17212c37414c57616c77828c97a1988e83786e63584e43382e232834404c58646f7b86919ca1978d857d78757475797f87909aa2988e83776c605e6a75818b96a19c9289817a767575777c838c959f9e93887d72665b4f43372b1f13070000000a15212c38434f5a66717c88949faaa99d92867b6f64584d41362a1f130800000000000000000a1724303d4a5763707d8a97a4b0aa9e938c8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8a7d7063574a3d3024170a000000000000000000000000000000020e1a27333f4b5864707c8995a1aa9f9692969fa5998d8174685b4f43362a1e12050000000b1724303c4955616d7a86929fa69b949399a3a79b8f83766a5e5145392d211408000000000000000000000000000000000000000000000000000000000006101b25303b46505b65707b86909b9f948a7f746a5f544a3f342a1f140a00000c1824303c47535f6a75818b96a09a90877f7974727275798089929c9f958a7f74695d52463b2f23170b0000000000000000000000000000000007121c27323d48525d68737e89939e998e84796e63584d42382d22170c15222e3b47535f6a75818c97a19a8f84787575757575757575757575757575757575736a5e5245392c1f1306000000000000000000000000000007121c27323d48525d68737e89939e998e84796e63584d42382d2227333f4a555f65676767676767676767676767676767697683909d9c8f827569676767635b51463a2e2215090000000000000000000000000000020d18232d38434e59636e79848f9a9e93887d73685d52473c3227313d495560696d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d727f8c99a09386796d6d6d6d6b62574c4033271a0e0000030c16202a343d47515b656e78828c96a0a49a9086858c92989ea3a7aba6a29f9c99979695949494959697999c9ea2a6aaa6a19c96908a837b746c645c534a41382e241a1006000000000000000000000000000000000a141f29333d47505a636c757d858d959ca2a8aba59f9a95918d8a87858483828282838486888a8d91959a9fa5aba59f989189817971685f564c42392f241a100500000000000000000915212d3944505c6874808b97a3afa69a8e82766a5f53473b2f23170b0000000000000000000000000000000915212d3944505c6874808c98a4afa4988c8175695d51453a2e22160a0000000000000000000000000915222e3a46525e6a76828d98a3ada59c938b85817e7d7c7c7c76695c5043362a1d100000000000000000000008131d27303a444d565f68707880888f969da39e98928d8884807c7977747371706f6f6f6f6f7071727476787a7c7f8285898d9195999ea29d97928c86807a73695d5144382b1e120500000000000000000000000000000000000005101a25303a45505a65707a85909b9f958a80756a5f554a3f352a2c3845515d6975818c97a29b90857b736c6967696e757e89939f9f94897d7165636f7a86929da1958b80776f6a68686b7179838e99a49a8f83776b5f53473b2f23160a00000004101b27323d4954606b77828e99a5aea3978c8075695e52473b3024190d02000000000000000a1724303d4a5763707d8a97a4b0a99c8f827e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7d7063574a3d3024170a00000000000000000000000000000006121e2a36434f5b6774808c98a5a6998d868e9aa69c9084776b5f52463a2e2115090000020e1b2733404c5865717d8a96a2a1958987929eab9f92867a6e6155493d3024180c00000000000000000000000000000000000000000000000000000000000009141f29343f49545f69747e89949f9b91867b71665b51463b31261b110604101c2834404c5864707b87929d9f93897e756d686666686e76808a95a09c91857a6e63574b3f33271b0f03000000000000000000000000000000000b16202b36414c57616c77828d97a0958a80746a5f54493e34291e13121f2b37424e59646f7a858f9aa0958a80766c6868686868686868686868686868686761584d4236291d11040000000000000000000000000000000b16202b36414c57616c77828d97a0958a80746a5f54493e34292936424f5b6771747474747474747474747474747474747683909d9c8f8275747474746d62564a3d3124170b00000000000000000000000000000006111c27313c47525d67727d88939e9a8f84796e64594e43382d333f4c5965717a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7f8c99a093867a7a7a7a7a74685b4f4235291c0f000000040e18222c353f49535d66707a848e97a1a2989190979da3a9aaa49f9a96938f8d8b898888878888898b8d8f92969a9ea3a9a7a19b948d867e766e655c534a40362c22180e03000000000000000000000000000006101b26303b454f59626c757e878f979fa6ada7a09a948e8985817d7b7977767575757677797b7e8185898e949aa0a7aaa39b938b837a71685e544b41362c21170c010000000000000005101c2834404b57636f7b87929eaaaa9f93877b6f63574b4034281c100400000000000000000000000000020e1a25313d4955616d7985919ca8ab9f94887c7064584c4135291d11050000000000000000000000000c1825313e4a56636f7b87939eaaa99e948a817a7571706f6f6f6d64594d4135281c0f00000000000000000005101a242f39424c565f68717a828a929aa1a099928c87817c7874706d6a68666463626262626363646667696b6d707376797c8184898d92979ca19d97918b83786b5f5245382c1f12050000000000000000000000000000000000000009131e29333e49535e69737e89949e9c91867c71665c51463c31303c4855616d7985919da1968a7e7369615c5b5d636c77828e99a59a8e82766967737f8b97a39c9084796e655e5b5b5f67717c88939f9f94887c7064574b3f32261a0d010000000a16212d38434f5a66717d88949faba89d91867a6f63584c41352a1e1307040404040404040a1724303d4a5763707d8a97a4b0a99c8f82757171717171717171717171717171717171717171717171717171717171717171716b6054483c2f2316090000000000000000000000000000000915222e3a46535f6b7784909ca8a3968a7e8b97a4a093877b6e62564a3d3125180c000006121e2a37434f5c6874818d99a69f9286828f9ba7a2968a7d7165594c4034281c0f030000000000000000000000000000000000000000000000000000000000020d18222d38424d58626d78828d98a2988d82786d62584d42382d22180d0713202c3844505c6874818c98a3998d82776c635c59595d646e78838f9aa2978b8073685c4f43372b1f130600000000000000000000000000000000040f1a252f3a45505b65707b86919c9c91867b70665b50453a30251a0f1a26313d48535e69737d88929b9c92887e756c645c5b5b5b5b5b5b5b5b5b5b5b5b5b564f463c3125190d01000000000000000000000000000000040f1a252f3a45505b65707b86919c9c91867b70665b50453a302a3744505d6a77818181818181818181818181818181818184909d9c8f83818181817e7165584b3e3225180b000000000000000000000000000000000a15202b35404b56616b76818c97a1968b80756a60554a3f3433404c5966738087878787878787878787878787878787878e9aa1958a878787878275695c4f4236291c0f0000000006101a232d37414b545e68727c868f99a3a29d9ca1a8aca59f99948e8a8683817e7c7b7b7a7b7b7c7e8083868a8e93989ea4aba69f98908880776e655c52483e342a20150a00000000000000000000000000010c17222d38424c57616b747e879099a1a9ada59d968f88837d7975716e6c6a69696969696b6c6f7175797d83898f969da5ada59d958c837a70665c52483e33281e130800000000000000000c17232f3b47525e6a76828e99a5afa3978c8074685c5044382d21150a0a0a0a0a0a0a0a0a0a0a0a0a0a0a121e2a36424e5a65717d8995a1ada69b8f83776b5f54483c3024180d010000000000000000000000000e1b2734404d5966727e8b97a3afa3988d82786f696563636363615b52483d3125190c0000000000000000010c17212c36404a545e68717a838c949ca49c958e87817b76716c6864615e5b59585756555555565758595b5c5f616366696d7074787d81868b90959ba095897e72675b4f43372a1e110400000000000000000000000000000000000000020c17222c37424c57626c77828d97a2988d83786d63584d4338333f4b5864717d8995a29d9185796d6257504e515b65717d8995a19e9286796d6a77838f9ba4978b7f73685d534e4f55606b77838f9ba4988c8073675b4e4235291c100300000004101b27323e4955606c77838e9aa5aea2978b8074695d52463b2f24181111111111111111111724303d4a5763707d8a97a4b0a99c8f827569656565656565656565656565656565656565656565656565656565656565656461594f44382c2014070000000000000000000000000000000d1925313e4a56626f7b8793a0aca094877b8894a1a3978a7e7266594d4134281c0f03000915212e3a46535f6b7884909da89c8f837f8c98a4a69a8d8175695c5044382b1f130700000000000000000000000000000000000000000000000000000000000006111b26313b46515b66717b86919b9f94897e74695f54493f34291f140a16232f3c4854606d7985919da194887c71655b514c4d525c67727e8a96a29c9084786c6053473b2f22160a000000000000000000000000000000000008131e29333e49545f69747f8a95a0988d82776c61574c41362b211615202b36414c57616c768089939c9a90877e766e665e564e4e4e4e4e4e4e4e4e4e4e4b453d342a1f1409000000000000000000000000000000000008131e29333e49545f69747f8a95a0988d82776c61574c41362b3744505d6a77848e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e95a09f958e8e8e8e8b7e7165584b3e3225180b00000000000000000000000000000000030e19242f39444f5a65707a85909b9c92877c71665b51463b33404c596673808c9494949494949494949494949494949498a0a69c959494948f8275695c4f4236291c0f000000000008111b252f39424c56606a737d87919ca9a9a9adaaa29b948e88837e7a777471706f6e6e6e6f70717476797d82878d9399a0a8aaa29a928980776d645a50463c31271c110600000000000000000000000007121e29343e49545e69737d879099a2abaca39b938b847d77726d6865625f5e5d5c5c5c5d5e606265696d72777d848b939ba3aca79e958c82786e645a4f453a2f24190e030000000000000007131e2a36424e5965717d8995a0aca89c9084786d6155493d31251917171717171717171717171717171717232f3b47525e6a76828e9aa6ada2968a7e72665b4f43372b1f140800000000000000000000000000101d2936434f5c6875828e9aa7ab9e93877b70665d585656565655504940362b201409000000000000000008131e28333e48525c66707a838c959ea29a928b837c76706a65605c5854514f4d4b4a49484849494a4b4c4e505254575a5d6064686c71757a7f848a8f958f84786d61564a3f33271b0f02000000000000000000000000000000000000000005101b25303b45505b65707b86909b9f948a7f746a5f544a3f35424e5b6774808c99a59a8e8275695d5145414955616d7985929ea295897c706d7a86939fa194887b6f63574b42434f5a66737f8b98a49c8f83766a5d5144382b1f1205000000000a16212d38444f5b66727d8994a0aba89c91857a6e63574c4035291e1e1e1e1e1e1e1e1e1e1e24303d4a5763707d8a97a4b0a99c8f8275695c58585858585858585858585858585858585858585858585858585858585858554f473d32271b1004000000000000000000000000000004101d2935414d5a66727e8b97a3aa9d91857985929ea69a8e8275695d5044382b1f1307000c1925313d4a56626f7b8794a0a5998c807c8995a1a99d9185786c6054473b2f23170a000000000000000000000000000000000000000000000000000000000000000a141f2a343f4a545f6a747f8a949f9b90867b70665b50463b30261b101926323f4b5764707c8995a19d9184786c60544940404a56616d7985929ea094887c6f63574a3e3225190c0000000000000000000000000000000000010c17222d37424d58636e78838e999e94897e73685d53483d32271d121a25303b45505a646e77818a939b99918880776f686058504842424242424242413f3a332b22180e030000000000000000000000000000000000010c17222d37424d58636e78838e999e94897e73685d53483d323744505d6a7784909a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9b9fa7a79f9b9a9a988b7e7165584b3e3225180b000000000000000000000000000000000007121d28333e48535e69747e89949f988e83786d62574d4237404c596673808c99a1a09c9b9b9b9b9b9b9b9b9b9b9b9b9ea5aaa19c9b9b9b8f8275695c4f4236291c0f00000000000009131d27313b45505a646e78828e9aa7b4b6ada2989089827c77726e6a67656362616161626365676a6d71767b81888f969ea6aca49b928980766c62584d43382e23180d0200000000000000000000020d18242f3a45505b65707a858f98a2abaca39a91898179726c66615c59555351504f4f4f50515356595d61666c72798189919aa3aca79e948a80766c61564c41362b1f140900000000000000020e1a25313d4955606c7884909ca7ada195897d7165594e42362a232323232323232323232323232323232328333f4b57636f7b87929eaaa99d9185796d62564a3e32271b0f0300000000000000000000000000111e2b3744515e6a7784909da9a79b8e82766a5f544c4a49494948453f372e241a0f0400000000000000030e19242f3a454f5a646e78828c959ea29990888079726b655e5954504b484542403e3d3c3c3c3c3c3d3e40414345484b4d5154585c6065696e73797e848a897e72675b5045392e22170b0000000000000000000000000000000000000000000009141f29343e49545f69747e89949f9b91867b71665b51463b43505d6976838f9ca4988b7e7266594d413844515d6976828f9ca5988c7f72707c8995a29e9285786c5f53473b3e4a5763707c8995a29e9285796c5f53463a2d2014070000000005101c27333e4a55616c77838f9aa5ada2968b8074685d51463a2f2a2a2a2a2a2a2a2a2a2a2a2a303d4a5763707d8a97a4b0a99c8f8275695c4f4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b49443d352b21160b0000000000000000000000000000000814202c3945515d6a76828e9ba7a79b8e8276828f9ba89e9185796c6054473b2f23160a03101c2834414d5966727e8b97a3a3968a7d7986929faba195887c7064574b3f33261a0e02000000000000000000000000000000000000000000000000000000000000030d18232d38434d58636d78838d98a2978d82776d62574d42372d22171c2835414e5a6773808c98a59a8d8175685c5044383945515d6975828e9ba4988c7f73665a4d4134281b0f02000000000000000000000000000000000005101b26313c46515c67727c87929d9a90857a6f64594f44392e2318131e29333e48525c656f788189929a9a928a8179726a625a534b443c3535353535322e29211910060000000000000000000000000000000000000005101b26313c46515c67727c87929d9a90857a6f64594f44393744505d6a7784909da199959595959595959595959595959aa4a39a959595958b7e7165584b3e3225180b0000000000000000000000000000000000010c16212c37424c57626d78838d989f948a7e74695e53483e404c596673808c99a1968f8e8e8e8e8e8e8e8e8e8e8e8e939da398908e8e8e8e8275695c4f4236291c0f0000000000000a16212c37424c57626c76818a949eaab6b6a99d91867e77716b66625e5b5856555454545556585b5e61656a70767d848c949da6ada49b92887e746a5f554a3f34291e13070000000000000000000007131e2a35404b57616c77828c96a1aaaea49a91887f776f67615b55504c49464443424243434547494d51555b61676f777f88919aa4aea69c92887d73685d52473c31251a0e03000000000000000915212c3844505c67737f8b97a3aea59a8e82766a5e52463b303030303030303030303030303030303030303844505c6873808b97a3afa4988c8175695d5145392e22160a0000000000000000000000000000121f2c3845525f6b7885929eaba4988b7f72665a4e423d3c3c3c3c39342d251c130800000000000000000914202b36414c56616c76808a949ea29990877e766e676059534e48443f4042444545454543413f3c3834333537393b3e4144484c5054595e63686d73787e84786d61564a3f34281d110600000000000000000000000000000000000000000000020d17222d38424d58626d77828d98a2988d82786d62584d4245525e6b7884919ea396897d7063574a3e35414e5b6774818d9aa69a8e8174717e8b97a49c9083766a5d5144373b4854616d7a8793a0a194877b6e6155483b2f22150800000000000b16222d39444f5b66727d8994a0aba79c9085796e62574b4037373737373737373737373737373d4a5763707d8a97a4b0a99c8f8275695c4f423e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3d39332b23190f040000000000000000000000000000000b1824303c4855616d7986929eaaa4988b7f73808c98a5a195887c7063574b3f32261a0d07131f2c3844505d6975828e9aa7a093877a76838f9ca8a4988c8073675b4f42362a1e12050000000000000000000000000000000000000000000000000000000000000006111c26313c46515c66717c86919c9e94897e74695e54493e34291e1e2a3744505d6976828f9ba4978b7e7265594c403435414d5a66737f8c98a59b8e8275695c5043372a1e11040000000000000000000000000000000000000a141f2a35404a55606b76818b96a1968b81766b60554b40352a1f1417222c36404a535d666f77808890989b938b847c746c655d554e463e362d282826221d1710070000000000000000000000000000000000000000000a141f2a35404a55606b76818b96a1968b81766b60554b403744505d6a7784909c9b8f88888888888888888888888889929e9d9189888888887e7165584b3e3225180b00000000000000000000000000000000000005101a25303b46505b66717c87919c9b90857a70655a4f44404c596673808b959e91858282828282828282828282828c99a09387828282828275695c4f4236291c0f000000000004101b27323d48535e69737e88929ca6b0b3b2aa9d91877d7369605a56524e4c4a48484748484a4c4e51555a5f656b727a828b949da6ada49a90867b71665c51463b2f24190d020000000000000000010c18242f3b46515d68737e89949ea8b0a69c92887f766d655d564f4944403d3a383636363637383a3d40454a4f565d656d767f88929ca6aea49a8f857a6f64584d42362b1f14080000000000000004101c28333f4b57636e7a86929ea9aa9e92867a6f63574b3f3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d4954606c7884909ca8ab9f93887c7064584c4035291d11050000000000000000000000000000131f2c3946525f6c7986929faca296897c7063574a3e323030302f2d28231b130a0100000000000000030f1a26313c47525d68737d88929ca39a90877e756c645d554e484242464a4d4f5152525251504e4b4844403b36302c2f3235383c41464a4d52575c61676d737873675c5045392e241d160e060000000000000000000000000000000000000000000006101b26313b46505b66717b86919b9f94897f74695f54494653606c7986939fa195887b6f6255493c33404c5966727f8c98a59c8f827573808c99a69b8e8275685c4f42363946525f6c7985929fa295897c6f6256493c3023160a000000000005111c28333e4a55616c78838f9aa6ada1968a7f73685c51454444444444444444444444444444444a5763707d8a97a4b0a99c8f8275695c4f423632323232323232323232323232323232323232323232323232323232302d2821191007000000000000000000000000000000030f1b2734404c5865717d8996a2aea195887c707d8995a2a4988c8073675a4e4236291d110a16232f3b4754606c7985919ea99d90847773808c99a5a89c9083776b5e52463a2e21150900000000000000000000000000000000000000000000000000000000000000000a151f2a353f4a555f6a75808a959f9b90857b70655b50453b30251f2c3945525f6b7885919ea295897c6f63564a3d31323e4b5764707d8996a39d9184786b5e5245392c1f1306000000000000000000000000000000000000030e18232e39444e59646f7a858f9a9d92877c72675c51463c31261b101a242e38414b545d656e767e878e969d958e867e766f67605850483f372e241b16120c0500000000000000000000000000000000000000000000030e18232e39444e59646f7a858f9a9d92877c72675c51463c43505d6975808a959a8d827b7b7b7b7b7b7b7b7b7b7b83909d9c8f827b7b7b7b7b7164584b3e3125180b0000000000000000000000000000000000000009141e29343f4a545f6a75808b95a0978c81766c61564b404b57636e79838e9894897f757575757575757575757f8c99a09386797575757571665a4e4135281b0f00000000000a15212c38434e5a65707a85909aa4aeada7a5a7a2988f857b71675e544a423f3d3c3b3b3b3c3d3f4245494e535a61687078828b949ea8aca2988d83786d62574c41352a1e1307000000000000000005111d2934404c57636e79848f9aa5b0a99e948a80766d645b534b443e3934302d2b2a2929292a2c2e3134393e444b535b646d76808a949faaaba1968b80756a5e53473c3025190d01000000000000000b17232f3a46525e6a75818d99a5afa3978b7f73675c504a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4d5965717d8995a0aca69a8f83776b5f53483c3024180c010000000000000000000000000000131f2c3946525f6c7986929faca194887b6e6255483c2f23232322201d1711090100000000000000000914202b37424d59646f7a858f9aa49c92887e756b635a524b4442484e5256595c5d5e5f5f5e5d5a5854504c47413b352e303840474d52565a5c5e5f5f5e62686c6961564b433d362f2720180f07000000000000000000000000000000000000000000000a141f2a343f4a545f6a747f8a949f9b90867b70665b504754616d7a8794a0a194877a6e6154473b323e4b5865717e8b98a49d90837673818d9aa79a8e8174675b4e41343845515e6b7784919ea3968a7d7063574a3d3024170a0000000000000b16222d3944505b67727e8995a0aca79b9085796d625651515151515151515151515151515151515763707d8a97a4b0a99c8f8275695c4f42362925252525252525252525252525252525252525252525252525252524211c160f070000000000000000000000000000000006131f2b3743505c6874818d99a5ab9e9286796d7a86939fa89b8f83766a5e5245392d20140d1a26323f4b5763707c8895a1a69a8d8174717d8996a2ac9f93877a6e62564a3d3125190c00000000000000000000000000000000000000000000000000000000000306090b0e18232e38434e58636e78838e98a2978c82776c62574c42372c222e3a4754606d7a8693a0a194877a6e6154483b2f2f3c4855626e7b8894a19f9386796d6054473a2e2114080000000000000000000000000000000000000007121c27323d48525d68737e89939e998e83786e63584d42382d2217121c262f38424b535c646c757c848c949b9890888179716a625a514940372d241a100600000000000000000000000000000000000000000000000007121c27323d48525d68737e89939e998e83786e63584d42414d59636e78838d98948a7f746e6e6e6e6e6e6e6e7683909d9c8f82756e6e6e6e696054483c3023170a000000000000000000000000000000010407090a0d18222d38434e59636e79848f999e93887d72685d524747525c67717c87919b90867b7168686868686868727f8c99a09386796d686868665f554a3e3226190d00000000030f1b26323d4954606b76818c97a1acada39b989ba3a1978d83796f665c52483e352f2e2e2e2f303335393d42484f565e666f79828c96a1aba99f948a7e73685d52463b2f24180c00000000000000000a16222e3945515d68747f8b96a1acada2978d82786e645b5249413a332d2824211f1d1c1c1c1d1f2124282d33394149525b646e78838d98a3aea89d92867b6f64584d41352a1e12060000000000000006121e2a36414d5965717c8894a0aca79c9084786c6056565656565656565656565656565656565656565656565e6a75828d99a5ada2968a7e72665a4f43372b1f1408000000000000000000000000000000131f2c3946525f6c7986929faca194877a6d6154473a2e2116161614100c06000000000000000000020e1a25313c48535f6a75808b96a19e948a80766c6259514840474e54595e6266686a6b6b6b6b696764615c58524d46403839424a52585e6366696b6b6b6b6a6865625e59544e474139322a21191007000000000000000000000000000000000000000000030d18232d38434d58636d78838d98a2978d82776d62574d54616d7a8794a1a094877a6d6053473a313e4b5764717d8a97a49d90847774818e9aa79a8d8173675a4d41343744515d6a7784919ea4978a7d7164574a3e3124170b00000000000005111c28333f4a56616d78848f9ba6aca1968a7e73675d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d63707d8a97a4b0a99c8f8275695c4f4236291c18181818181818181818181818181818181818181818181818181714100b0500000000000000000000000000000000000a16222f3b47535f6c7884919da9a89b8f83766a7783909ca89f92867a6d6155493c302417111d2936424e5b6773808c98a4a3978a7e716e7a87939faca3978a7e7266594d4135291c10040000000000000000000000000000000000000000000000000001060b0f121518191b1c27313c47515c67717c87919c9e93897e73695e53493e33292f3b4855626e7b8894a19f9386796c6053463a2d2e3a4754606d7a8693a0a194887b6e6255483b2f22150900000000000004080b0c0d0d0d0d0d0d0d0d0d0d0d16202b36414c57616c77828d97a0958a7f746a5f54493e33291e13141d262f38414a525a636b727a828991989a938b837c746b635b52493f362c22180e030000000000000000000004080b0c0d0d0d0d0d0d0d0d0d0d0d16202b36414c57616c77828d97a0958a7f746a5f54493e47525c67717c86919b91867c71676161616161697683909d9c8f8275696161615e574e43382c20140800000000000000000000000001060a0e1113151718191c27313c47525d67727d88939e9a8f84796e63594e434b55606a757f8a94988d83786e635b5b5b5b65727f8c99a09386796d605b5b5a544d43382d21160a0000000008141f2b37434e5a65717c88939ea8b1a69b918c919ba59f958b82786e645a50473d33292122222426292d31373d444c555d67707a858f9aa5b0a69b90857a6e63574c4034291d1105000000000000020e1a26323e4a56626d7985909ca7b2a79c91867b70665c524940372f28221c181412100f0f10111215181c22282f374049525c66717b87929da8aea3978c8175695e52463a2e22160a00000000000000020d1925313d4854606c78848f9ba7aca094897d71656363636363636363636363636363636363636363636363636e7a86929eaaa99d9185796d62564a3e32261b0f03000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d201409090704000000000000000000000007131e2a36424d5964707b87929da2988d82786e645a5047414951585f656a6e727577787878777673706d68635e58514a43424b545c63696e7275777878787775726e6a655f59524b443c332b2219100600000000000000000000000000000000000000000006111c26313c46515c66717c86919c9e94897e74695e5454616e7b8894a1a094877a6d6053473a313e4a5764717d8a97a49d90847774818e9aa79a8d8173675a4d40343744515d6a7784919ea4978a7d7164574a3e3124170b000000000000000b17222e3945505c67727e8a95a1aca69b9084786d6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a707d8a97a4b0a99c8f8275695c4f4236291c0f0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0a0804000000000000000000000000000000000000010e1a26323e4b57636f7c8894a0ada5988c80736774808d99a5a2968a7d7165584c4033271b14202d3945525e6a76838f9ba8a094877b6e6b7784909ca9a69a8e8275695d5145382c201407000000000000000000000000000000000000000000000000070d12171b1f2224262728282a35404a55606a75808b95a09a90857a70655a50453a30303c4956636f7c8996a29e9285786b5f5245392c2c3946535f6c7986929fa296897c6f6356493c3023160a00000000030a101417191919191919191919191919191a242f3a45505b65707b86919c9c91867b70655b50453a2f251a0f141d262f3840495159616870777f868e959d958d867d756d645b51483e342a1f150a0000000000000000030a101417191919191919191919191919191a242f3a45505b65707b86919c9c91867b70655b5045404a555f6a747f8994988e83796e645955555d697683909d9c8f8275695c5555524d453c32271b10040000000000000000000002080d12161a1d202224252626262b35404b56616b76818c97a0968b80756a5f554a434e58636d78828d97958a80756b60564e5965727f8c99a09386796d60534e4d49433a31271c1105000000000c1824303c48535f6b76828d99a4afaa9f948a7f89939ca69d948a80766c62594f453b31281e16171a1d21262c333a434b555e69737d88939ea9aca1968b8074685d5145392d21160a00000000000006121e2a36424e5a66727e8a96a1adaca1968a7f74695f544a40372e251d16110c0805030000000406080c11161d252e37404a555f6a75808c97a3aea99d91867a6e62564a3e32261a0e02000000000000000814202c38444f5b67737e8a96a2aea5998d817570707070707070707070707070707070707070707070707070737f8b97a2aea4988c8175695d5145392d22160a00000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d20140700000000000000000000000000000b17232f3b47525e6a75818c98a39c91867b70665c5248414a535b636a70767a7e81838585858482807d79746f69635c554d4a545d666e757a7e828485858583817e7a76706a645d554e453d342b22180f050000000000000000000000000000000000000000000a151f2a353f4a555f6a75808a959f9b90857b70655b54616d7a8794a1a094877a6d6154473a313e4b5764717e8b97a49d90847774818e9aa79a8e8174675a4d41343844515e6b7784919ea4978a7d7063574a3d3024170a0000000000000006111d28343f4a56616d78848f9ba6aca1958a7e777777777777777777777777777777777777777777777d8a97a4b0a99c8f8275695c4f4236291c0f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005111d2a36424e5a67737f8b98a4aea295897c7064717d8a96a2a6998d8174685c4f43372b1e1724303c4955616d7a86929fa99d9184786b6874818d99a6aa9e9285796d6154483c3024170b00000000000000000000000000000000000000000000040b12181e23272b2e3133343535343439434e59636e79848e99a1978c81766c61574c4137303d4a5663707d8a96a39e9184776b5e5145382b2c3845525f6b7885929ea3968a7d7063574a3d3024170a000000050e151b202426262626262626262626262626262629333e49545f69747f8a95a0988d82776c61574c41362b20160b141d262e373f474f565e666d747c838b939b9890877e766d635a50463c31261c1106000000000000050e151b202426262626262626262626262626262629333e49545f69747f8a95a0988d82776c61574c41434e58636d77828d97958a80756b6056505d697683909d9c8f8275695c4f4846423b332a20150a00000000000000000000070d13191e2226292c2f3032333333333239444f5a65707a85909b9c91877c71665b504647515c66717b86909b91877c72675d525965727f8c99a09386796d605346413d3831281f150a0000000004101c2834404c5864707c87939faab0a4998e8378818a949ea59c92887e746b61574d433a30261c120d10151a21283139434d57616c76828d98a4afa79c9085796d62564a3e32261a0e0200000000000916222e3a47535f6b77838f9ba6b2a79c9085796e63584d42382e251c130c050000000000000000000000050c131b252e38434e59646f7a86929da9aea2968b7f73675b4f43362a1e120600000000000000040f1b27333f4a56626e7a86919da9aa9e92867d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d848f9ba7ab9f93877b7064584c4035291d110500000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d20140700000000000000000000000000030f1b28343f4b57636f7b86929ea1968b80746a5f544a404a535c656d757b82878b8e90919292918f8c8985807a746e665f57515c666f7880868b8e91929291908e8a86817c756f675f574f463d342a20170c020000000000000000000000000000000000000000030e18232e38434e58636e78838e98a2978c82776c6257606d7a8693a0a194887b6e6155483b323f4b5865717e8b98a59c90837673808d99a69b8e8174685b4e42353845525e6b7885919ea396897c7063564a3d3023170a00000000000000000c17232e3945505c67737e8a95a1aca69b8f8584848484848484848484848484848484848484848484848b97a4b1a99c8f8275695c4f4236291c0f060606060606060606060606060606060606060606050200000000000000000000000000000000000000000000000815212d3946525e6a77838f9ba8ab9e9286796d616e7a87939fa99d9084786b5f53463a2e221b2733404c5865717d8a96a2a69a8d81756865717d8a96a3aea295897d7164584c4033271b0f020000000000000000000000000000000000000000070e161d23292f33373b3d3f41414241403f3c47525c67727c87929d9e93887d73685e53483e333d4a5763707d8a97a49e9184776b5e5144382b2b3845515e6b7784919ea4978a7d7164574a3e3124170b0000050e1720272c30333333333333333333333333333333333337424d58636d78838e999e93897e73685d52483d32271c1212141c252d353d454c545b626a71798189929a9991887f756c62584d43382d22170b0000000000050e1720272c30333333333333333333333333333333333337424d58636d78838e999e93897e73685d52483d46515b66707b85909a92877d72685d535d697683909d9c8f8275695c4f423a36312921180e040000000000000000020a11181f242a2e3236393b3d3e3f4040403f3e3d48535e69747e89949f988d83786d62574c424a545f69747e8993998e84796f645a5965727f8c99a09386796d6053463a312d261f160d03000000000714202c3844515d6975818c98a4b0ab9f94887d7178828c96a0a49a90867c73695f554b42382e241a1107090f161f27313b454f5a65707b87939eaaada1968a7e72665a4e42362a1e120500000000000d1925323e4a56636f7b87939fabaea2978b7f73685c51463b31261c130a01000000000000000000000000000109131c27313c47525e6975818d99a5b1a79b8f83776b5f53463a2e22150900000000000000000b16222e3a46525d6975818d98a4aea2978d8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8b94a0aca69a8f83776b5f53473c3024180c0000000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d2014070000000000000000000000000007131f2c3844505c6874808b97a39c9085796e63584d4348525c656e777f868d92979a9d9e9f9f9d9c9995918c867f7871696058626d78818a91979b9d9e9f9e9d9a97928d878079716961584f463c32281e140900000000000000000000000000000000000000000007111c27313c47515c67717c87919c9e93897e73695e5f6c7985929fa295897c6f6256493c33404d596673808c99a59b8e8275727f8c98a59c8f8275695c4f43363a46535f6c7986929fa195887b6f6255493c2f231609000000000000000006111d28343f4b56626d7984909ba7aca097919191919191919191919191919191919191919191919191949da8b3a99c8f8275695c4f4236291c13131313131313131313131313131313131313131313110f0a050000000000000000000000000000000000000000000c1825313d4955626e7a86939faba89b8f83766a5e6b7783909ca8a094877b6f62564a3e31251e2a37434f5c6874818d99a5a3978a7e7265616e7a87939faba5998d8174685c4f43372b1e12060000000000000000000000000000000000000008101820272e353a3f43474a4c4d4e4e4e4d4b49464b55606b75808b96a09a8f857a6f645a4f453a3d4a5763707d8a97a49e9184776a5d5144372a2b3844515e6b7784919ea4978a7d7164574a3e3124170b00010c17202931383d3f40404040404040404040404040404040404046515c67727c87929d9a8f857a6f64594e44392e231b1e202122232b333a4249515860676f778088919a9a91877e746a5f544a3f33281d1105000000010c17202931383d3f40404040404040404040404040404040404046515c67727c87929d9a8f857a6f64594e443f4a545f69737e8993998e84796f645a5d697683909d9c8f8275695c4f42362a251f170f060000000000000000040c141c232a30353a3e4245484a4b4c4c4d4c4c4a49464c57626d78838d989f94897e74695e5348434d58626d77828c97958b81766b615965727f8c99a09386796d6053463a2d211c150d0400000000000b1724303c4854616d7985919da9b1a69a8e82776b707a848e98a1a2988f857b71675d544a40362c23190f05050d151f29333e49545f6a76828e99a5b1a69a8e83766a5e52463a2e2115090000000003101c2935414e5a66737f8b97a3afaa9e92867a6e63574b40352a1f140a01000000000000000000000000000000010b15202b36414d5964707c8894a1adab9f93877b6f62564a3e3125180c000000000000000006121d2935414d5864707c88949faba89f98969696969696969696969696969696969696969696969696969696979da6ada1968a7e72665a4f43372b1f13080000000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d201407000000000000000000000000000b17232f3c4854606c7884909ca3978b8074685d5247444f5a646e77818991989ea3a5a09d9b9a9a9b9c9f9c97918a837b736a6168737f8a949ca3a29c97959596999d9e98928b837b736a61584e443a30261b10060000000000000000000000000000000000000000000a15202a35404a55606a75808a95a09a90857a70655e6a7784909da3978a7d7164584b3f35424e5b6874818d9aa6998d8073717d8a97a39d9084776a5e5145383c4855616e7a8794a0a093867a6d6154473b2e2115080000000000000000000c17232e3a45515c68737e8a96a1aca9a19e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9fa6aeb5a99c8f8275695c4f42362920202020202020202020202020202020202020202020201e1b1610090100000000000000000000000000000000000003101c2834414d5965727e8a96a3afa4988c8073675b6774808c99a5a3978b7e72665a4d413528212e3a46535f6b7884909da9a093877b6e625e6b7783909ca8a99c9084786b5f53473b2e22160a00000000000000000000000000000000000008111a222a323940464b4f5356595a5b5b5b5a5855524e4e59646e79848f99a1968c81766c61564c413d4a5763707d8a97a49e9184776a5e5144372b2b3844515e6b7784919ea4978a7d7164574a3e3124170b0007131e29323b43494c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c55606b76818b96a1968b81766b60554a3f352a272b2d2e2f30303132383f464e555d656d767f88929b9990867b71665b5044392d22160a00000007131e29323b43494c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c55606b76818b96a1968b81766b60554a3f424d57626c77818c96968b81766c615d697683909d9c8f8275695c4f4236291c140d060000000000000000040d161e262e353b41464a4e52545658595959595857555350505b66717c87919c9b90857a70655a4f4446505b65707a858f9a92887d73685e65727f8c99a09386796d6053463a2d20130a030000000000010e1a27333f4c5864717d8995a1adada195897d726668727c869099a3a1978d83796f665c52483e352b21170d04030d17212c37424e5a65717d8995a1adab9f93877a6e62564a3d3125180c0000000006131f2b3844515d6a76828f9ba7b3a69a8e82766a5e52463a2f23180d030000000000000000000000000000000000030e1925303c4854606c7884919da9afa3978b7e7266594d4134281b0f0200000000000000010d1924303c48545f6b77838f9ba6b1a9a4a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a4a8afa99d9185796d61564a3e32261a0f030000000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d201407000000000000000000000000010e1a27333f4b5864707c8895a19e92867a6f63574c404b56616b76808a939ba3a69f9994918e8d8d8e9093969b9c948d857c736a6c7884909ba6a198908b89888a8c91969d9d958d857c736a60564c42372d22170c010000000000000000000000000000000000000000030e19232e39434e59636e79838e99a1978c81776c616875828e9ba5998c8073675a4e423b45515e6a7683909ca3978b7e716f7b8894a19f9286796d6154483c3f4b5764707d8996a29d9184786b5f5245392c20130600000000000000000006121d2934404b57626d7985909ca7b2adaaaaa7a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a6abb3b5a99c8f8275695c4f42362c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a27211b130b0100000000000000000000000000000000000713202c3844505d6975818e9aa6aea195897c70635864717d8996a2a79a8e8275695d5144382c25313d4a56626f7b8794a0a99d9084786b5f5b6774808c98a5aca094887b6f63574a3e3226190d010000000000000000000000000000000006101a232c343c444b51575b5f6365676868676664625e5a54525d67727d88929d9d93887d73685d53483d4a5763707d8a96a39e9184776b5e5144382b2b3845515e6b7885929ea3968a7d7063574a3d3024170a000c18242f3a444d545859595959595959595959595959595959595959595959646f7a858f9a9d92877c72675c51463b3132373a3b3c3c3d3e3e3e3b3c434b535b646d768089949e988d83776c61564a3e32261a0e0200000c18242f3a444d545859595959595959595959595959595959595959595959646f7a858f9a9d92877c72675c51463b46505a656f7a858f9993887d73695e697683909d9c8f8275695c4f4236291c0f030000000000000000020c161f2830383f464c52575b5e616364656666666564625f5c58545f6a75808b95a0978c81766b61564b4049545e69737d8893998f857a6f6565727f8c99a09386796d6053463a2d20130700000000000004111d2a36434f5b6874818d99a5b1a99d9185796d61606a747d87919ba59f958b81776e645a50463d33291f150c0205101b26323d4955616c7885919da9afa3978a7e7266594d4134281b0f020000000915222e3b4754606d7985929eabafa3978a7e7266594d41352a1e1207000000000000000000000000000000000000000814202c3844505c6874818d99a6b2a79a8e8275695c5043372a1e110500000000000000000814202b37434f5b66727e8a96a2adb4b1a9a29f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa1a7afb3b0a4988c8074695d5145392d22160a000000000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d20140700000000000000000000000004111d2a36424f5b6774808c98a59a8e82766a5e524645515c67727d88929ca5a59c948e88848281818183868a8f959b978e857c726f7b8894a1a59a8f867f7c7b7d81858b929a9f978e857c72685e54493e34291e130700000000000000000000000000000000000005090d11131c27323c47525c67727c87929d9e93887e736866737f8b98a49b8f83766a5e5349484a55616d7986929fa094887b6f6c7985919ea295897c7064594d4848505b6773808c98a59a8e8275695c5043372a1e1105000000000000000000010c18232f3a45515c68737f8a96a1adb8aea49c9898989898989898989898989898989898989898989aa1abb5a99c8f8275695c4f423939393939393939393939393939393939393939393939393937332d251d130900000000000000000000000000000000000b17232f3c4854606c7985919daaaa9e9285796d6055616d7a86929faa9e9285796d6054483b2f2834414d5966727e8b97a3a6998d8174685c5864707c8995a1aea4978b7f73665a4e4236291d1105000000000000000000000000000000040e18222c353e464e555c62676c6f727374757473716e6a65605a56616b76818b96a19a8f84796f645a4f444956636f7c8996a29e9285786b5f5245382c2c3945525f6c7885929fa396897c6f6356493d3023160a00101c2935404c565f65666666666666666666666666666666666666666666666668737e89939e998e83786d63584d42373d43464848494a4b4b4a4640394149525b646d77828d989f94897d72665a4e42362a1e12050000101c2935404c565f65666666666666666666666666666666666666666666666668737e89939e998e83786d63584d423e49535e68737d88929a8f857a7065697683909d9c8f8275695c4f4236291c0f0300000000000000000a141e28313a424a51585d62676a6d6f717273737372706e6c68645f59636e79848f999e93887d72675d5247424c57616c76818b96968c81776c65727f8c99a09386796d6053463a2d2013070000000000000713202c3945525e6b7784909ca9b2a6998d8175685c58626b757f89939da79d938a80766c62584f453b31271e140a000a15212c3844505c6875818d9aa6b2a69a8e8275695c5043372b1e12050000000b1724303d4a56636f7c8895a1aeaca093877b6e6256493d3125190d0100000000000000000000000000000000000000030f1b2734404c5865717d8a97a3afaa9d9185786b5f5246392d2014070000000000000000030f1b27323e4a56626d7985919da9b4aba0979292929292929292929292929292929292929292929292959ea8b4ab9f93877b7064584c4035291d1105000000000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d2014070000000000000000000000000714202d3945525e6b7783909ca2968a7e7165594d414a56626d79848f9aa4a79c938a837c7875737375777a7e848a9097978e847a707d8a96a3a094897d746f6f71747a80889099a0978e847a70655b50453a2f24190d02000000000000000000000000000000050b1015191d2022242b35404b55606b75808b96a09a8f857a6f656f7c8894a09f93877b6f645b5654565c67727e8a96a29c9084786c6975828e9aa5998d81756a5f58555558616c7884909ca2968a7e7266594d4134281b0f020000000000000000000007121e2935404b57626e7985909ca7b3a99d928b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8f9aa5b2a99c8f8275695c4f4646464646464646464646464646464646464646464646464646433e372f251b1005000000000000000000000000000000020e1a27333f4b5864707c8995a1ada79a8e8275695d515e6a76838f9ba7a195897c7064574b3f322c3844505d6975828e9aa7a2968a7d71655954616d7986929eaaa79b8f83766a5e5245392d2114080000000000000000000000000000000b16202a343e47505860676e73787b7e81818281807d7a76716b645d5a646f79848f9aa1968b81766b61564b4855626f7b8895a29f9286796c5f5346392d2d3a4653606c7986939fa295887b6f6255493c2f22160900121f2b3844515d68717373737373737373737373737373737373737373737373726c77828d97a0958a7f74695f54493f484f5354555657575857524a41384049525c66707b87929e9a8f83776b5f52463a2d2114080000121f2b3844515d68717373737373737373737373737373737373737373737373726c77828d97a0958a7f74695f54493e414c56616b76818b95978c82776d697683909d9c8f8275695c4f4236291c0f030000000000000007111c26303a434c545c63696e73777a7c7e7f8080807e7d7b7874706a645d67727d88939e998f84796e63584e43454f5a646f79848e9993897e7469727f8c99a09386796d6053463a2d2013070000000000000916222f3b4854616d7a86939facafa2968a7d716558505a636d77818b959ea59b92887e746a61574d433930261c120804101c2834404c5965717e8a96a3afaa9d9185786c5f53463a2d2014070000000d1926323f4c5865717e8b97a4b0aa9d9184786b5f52463a2d2115090000000000000000000000000000000000000000000b1824303d4955626e7b8794a1adada093877a6e6155483b2f2216090000000000000000000a16222e3945515d6974808c98a4afa79b8f86868686868686868686868686868686868686868686868c98a4b1a69a8e83776b5f53473c3024180c00000000000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d2014070000000000000000000000000916222f3c4855616d7a86939f9f93867a6e615549434f5b67737e8a95a0aa9f958b8178716c686767686a6e73787e868d95968c82777d8a97a49d9184786c636264696f767e879099a0968c82776c62574c40352a1e130700000000000000000000000000020a10161c2125292c2f31323339444e59646e79848e99a1968c81766c6b78848f9ba3978c81766d66626162676e78838f9aa3978c80746865717d8995a19d92867b7169646161646a737e8994a09d92867a6e62564a3d3125180c0000000000000000000000010c18232f3a46515d68747f8b96a2ada89b8e827e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e8a97a4b0a99c8f8275695c5353535353535353535353535353535353535353535353535353524f4941372d22160b00000000000000000000000000000006121e2a37434f5b6774808c98a5afa3978b7e7266594e5a67737f8c98a4a5988c8073675b4e42362f3b4754606c7985919eaa9f93867a6e6155515d6976828e9ba7ab9f92867a6e6155493d3024180c000000000000000000000000000007121d27323c465059626a72797f84888b8d8e8e8e8c8a86827c766f675e5d68737d88939d9d92887d72675d524854616d7a8794a0a093877a6d6154473b2e2e3b4854616e7a8794a0a094877a6d6154473b2e2115080013202c3946535f6c7980808080808080808080808080808080808080808080807e71707b86919b9b91867b70655a5047515a5f616262636465635c53483d37404a545f6a76828e9a9f93877b6e6255493c3023170a000013202c3946535f6c7980808080808080808080808080808080808080808080807e71707b86919b9b91867b70655a50453a454f5a646f79848e9993897e74697683909d9c8f8275695c4f4236291c0f03000000000000020d18232e38424c555e666d747a7f8386898b8c8c8c8c8b8a8784817b766f67616b76818c97a0958b80756a5f544a3f48535d68727d87929a90857b70727f8c99a09386796d6053463a2d2013070000000000000b1824313d4a5763707c8995a2aeaca093877a6e615549515b656f79838c96a0a49a90867c73695f554b42382e241a11070c1824303d4955626e7b8794a0adada094877b6e6155483c2f2316090000000e1b2834414e5a6773808d99a6b2a89b8e8275695c5043372a1e11050000000000000000000000000000000000000000000814212d3a46535f6c7985929eabafa296897c7063574a3d3124170b00000000000000000005111d2935404c5864707b87939faba79b8f83797979797979797979797979797979797979797979808c98a4ada1968a7e72665a4e43372b1f130700000000000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d2014070000000000000000000000000b1825313e4a5763707d8996a29c9083776a5e524547535f6b77838f9ba6a5998e83786f66605c5a5a5b5e62676d747b838c9494897e7d8a96a39c8f8276695c55585d646c747e87919b9e93897e73685d52463b2f24180d010000000000000000000000050d141b22282d3135393b3d3f40404047525d67727d88929d9d93887d7368737e8a95a09d92887f77726f6e6f7278818a95a09d92877b6f63616d78848f9aa3988d837b74706e6e70757c858f9aa2978c8175695e52463a2d21150900000000000000000000000007121e2935404c57636e7a85919ca8aa9e92877b7171717171717171717171717171717171717d8a97a4b0a99c8f8275695f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5a53493e33271b0f0300000000000000000000000000000915222e3a46535f6b7784909ca8aca093877b6e62564b57636f7c8895a1a89c8f83776a5e524539323f4b5763707c8895a1a89b8f83776a5e524d5a66727e8b97a4aea2968a7d7165594d4034281c0f03000000000000000000000000010d18232e39434e58626b747c848a9094979a9b9b9a9996938e88817970675e616c76818c96a1998f84796f64594e535f6c7985929fa195887b6f6256493c30303d4956626f7c8895a29f9285796c5f5346392d2013070013202c3946535f6c79868c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8b7e7169747f8a959f978d82776c61564d59636b6e6e6f7071716e655a4e413538424d5965727e8b97a3978a7d7164584b3e3225180c000013202c3946535f6c79868c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8b7e7169747f8a959f978d82776c61564c413d48525d67727c87919b90867b707683909d9c8f8275695c4f4236291c0f0300000000000008131e2a353f4a545e6770787f858b8f93959798999999989694918c8781797169656f7a85909b9c91877c71665b5045414b56606b75808a95978c8277727f8c99a09386796d6053463a2d2013070000000000000d1926333f4c5865727e8b98a4b1aa9d9184776b5e524649535d67717a848e98a2a2988e857b71675d534a40362c22190f0814212d3a46535f6c7885919eabafa396897d7064574a3e3124180b000000101c2936424f5c6875828e9ba8b2a6998c8073675a4d4134281b0f0200000000000000000000000000000000000000000005121f2b3844515d6a7784909da9b1a4978b7e7165584b3f3225190c000000000000000000010c1824303c47535f6b77838e9aa6ab9f93877b706c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6d7884909ca8a89d9185796d61564a3e32261a0f0300000000000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d2014070000000000000000000000000d1a2733404c5966727f8b98a59a8d8174675b4f424a56636f7b8794a0aba094887c71675d55504d4d4f52565c6269717a828b9590857c8996a39c8f8275695c4f4c525a626b75808a949f9b9085796e63574c4035291d110600000000000000000000060f171f262d33383d4245484a4c4c4c4c4b4b56606b76818b96a19a8f847a6f6d78838e98a29a9189837e7b7b7b7e838a939c9f958b80756a5e5c68737e89939d9f958d86807c7b7b7d81868e97a19a90867b7064594d4135291d1105000000000000000000000000010d18242f3b46525d6974808b97a2ada3988c817569656565656565656565656565656565707d8a97a4b0a99c8f82756c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b655b4f44372b1f120500000000000000000000000000010d1925323e4a56626f7b8793a0aca89c9084776b5f524754606c7885919daa9f93867a6e6155493d36424e5a6773808c98a4a4988c8073675b4e4a56636f7b8894a0ada69a8d8175695c5044382b1f130700000000000000000000000007131e2935404b55606a747d868e959b9f9a96949495979b9e99928b837970665c656f7a858f9aa0968b80756b6055515e6a7783909ca3978a7d7164584b3f32333f4b5864717d8a97a39c9083776a5d5144382b1e12050013202c3946535f6c79869399999999999999999999999999999999999999988b7e71646d78838e999e93897e73685d525d69757a7b7c7d7d7e76695d504437333d4a5663707d8a96a3988c7f7265594c3f3326190c000013202c3946535f6c79869399999999999999999999999999999999999999988b7e71646d78838e999e93897e73685d52483d414b56606b75808a95978c82777683909d9c8f8275695c4f4236291c0f030000000000010d1824303b46515c667079828a91969b9c97949291919193959a9d98928b837b716769747e89949f988d82776d62574c41444f59646e79838e9893897e737f8c99a09386796d6053463a2d2013070000000000000e1b2734414d5a6773808d99a6b3a89b8e8275695c4f43414b555f68727c86909aa3a0978d83796f655c52483e342b21170d121e2b3744515d6a7683909ca9b1a5988b7e7265594c3f3326190d000000111d2a3744505d6a7683909da9b1a4988b7e7165584b3f3226190c0000000000000000000000000000000000000000000003101d2936434f5c6975828f9ba8b2a6998c807366594d4033271a0d0000000000000000000008131f2b37434e5a66727e8995a1ada4988c8074685f5f5f5f5f5f5f5f5f5f5f5f5f5f5f65717d8995a1ada4988c8074685d5145392d21160a0000000000000000000000000000000000000003131f2c3946525f6c7986929faca094877a6d6053473a2d2014070000000000000000000000000f1c2835424e5b6774818d9aa4978b7e7265584c404d5965727e8b97a3a89b8f83776b60554b43414142464b51585f687079838c968c818996a29c908376695c504348505a636d78838d98a1968b8074685d51453a2e22160a000000000000000000060f18212930383e44494e5154575859595958575459646f79848f9aa1968b81766b727c8690989f9b948e8a8888888b8f959c9e968d83796f645956616c77818b949c9f97918c898888898c9198a09a92887e74695e53483c3125190d010000000000000000000000000007131e2a35414c57636e7a85919ca8a99d92867a6f635858585858585858585858585863707d8a97a4b0a99c8f827979797979797979797979797979797979797979797979797979797979776c6053463a2d2014070000000000000000000000000004101d2935414e5a66727e8b97a3b0a5998c8074685b4f44505c6975818e9aa6a2968a7d7165594c403945525e6a76838f9ba8a195887c7063574b47535f6c7884919da9a99d9185786c6054483b2f23170a0000000000000000000000000c18232f3a46515c67717c868f98a09a938e8a8887888b90969d9d958b82786d635e68737e88939e9d92877c72675d525b6874818d9aa5998c8073675b4e423636424e5b6773808d99a69a8d8174685b4f4236291c10030013202c3946535f6c79869292929292929292949ca69e9592929292929292928b7e716467717c87929d9a8f84796f64595d69768388898a8a85786c6054494240414a5764707d8a96a3998c7f7266594c403326190d000013202c3946535f6c79869292929292929292949ca69e9592929292929292928b7e716467717c87929d9a8f84796f64594e4339444e59636e78838d9893897e7683909d9c8f8275695c4f4236291c0f03000000000005111d2935414c57636d78828b949b9d96908b888584848586898e949b9d958d83796f646d78828d989f94897e73695e53483d47525c67717c86919a8f857a7f8c99a09386796d6053463a2d2013070000000000000f1c2935424f5b6875828e9ba8b3a6998d8073675a4d4139434d57606a747e88919ba59f958b81776e645a50463d33291f15101c2935424f5b6875818e9ba7b3a69a8d8173675a4d4134271b0e010000121e2b3845515e6b7784919eaab0a3968a7d7063574a3d3124170b00000000000000000000000000000000000000000000000e1b2835414e5b6774818e9aa7b4a79a8d8174675a4e4134281b0e00000000000000000000030f1a26323e4a55616d7985919ca8a89d9185796d61555252525252525252525252525e6a76828e99a5ab9f93877b7064584c4034291d11050000000000000000000000000000000000000005131f2c3946525f6c7986929faca094877a6d6053473a2d201407000000000000000000000000101d2a3643505c6976828f9ca296897c7063564a424f5b6874818e9aa7a4988c7f73675b4f44393434363a3f464d565e67717a848e938e919aa59d9084776a5e51443e48515c66717c87929e9c9185796e62564a3e32261a0e0200000000000000040e18212a333b42494f555a5e6163656666666563615d5d68737d88939d9d92887d726a747d868e949a9e9a97959495979b9d99938c847b71675d52505b656f79828a91979c9c9896949496999d9b96908880766c62584d42372b2014080000000000000000000000000000020d1924303b46525d6974808b97a2aea3978c8074695d524b4b4b4b4b4b4b4b4b4b5763707d8a97a4b0a99d918786868686868686868686868686868686868686868686868686868686867a6d6053473a2d201407000000000000000000000000000814202d3945515d6a76828e9ba7aea195897d7064584c414d5965727e8a97a3a6998d8174685c50433c4955616d7a86929faa9e9185796c60544743505c6875818d99a6ada195887c7064574b3f33261a0e020000000000000000000005111d2834404c57626d78838e98a1999089827d7b7a7b7f848b949d9d948a7f74695e616c77818c97a1998e84796e63595965727e8a97a39c8f83776a5e52473c3c47525e6a77838f9ca3968a7e7165594c4033271a0e010013202c3946535f6c798686868686868686868a96a2988c8686868686868686867e7164606b75818b96a1968b80756b605b6773808c969694887c70655b534e4c4d515b67737f8c98a4988b7e7265584c3f3225190c000013202c3946535f6c798686868686868686868a96a2988c8686868686868686867e7164606b75818b96a1968b80756b60554a3f3d47525c66717b86909a8f847983909c9c8f8275695c4f4236291c0f0300000000000915222e3a46515d69747f8a949d9d948b857f7b797777787a7d8289929b9f958b80756966717c87919c9b90857a6f645a4f44404b55606a747f8a94968b807e8c98a09386796d6053463a2d201307000000000000101d2a3643505d697683909ca9b1a5988b7e7265594c3f323b454e58626c768089939da79d938980766c62584f453b31271e141a2734414d5a6773808d99a6b3a89b8e8275685b4f4235281c0f020000121f2c3945525f6b7885929eabafa296897c6f6256493c3023160900000000000000000000000000000000000000000000000d1a2734404d5a6673808d9aa6b3a89b8e8275685b4e4235281c0f00000000000000000000000a16212d3945515c6874808c97a3ada195897d72665a4e4646464646464646464b57636e7a86929eaaa69a8e83776b5f53473b3024180c00000000000000000000000000000000000000010613202c3946535f6c7986929faca094877a6d6053473a2d201407000000000000000000000000111e2b3744515d6a7784909da194877b6e61554844515d6a7683909ca9a295897c7063574b3e3327272a2e343c444c555f68727c87919b9ca3ab9e9285786c5f5246393f4a555f6b76818d98a1968a7e73675b4f43372b1e1206000000000000020c16202a333c454d545b60666a6d707273737371706d6965616c76818c96a1998f84796f6b747c83898e9295969898989694918d88817a72695f554b49535d67707880868c9093969798989796938f8b857e766d645a50463b30251a0f0300000000000000000000000000000007131e2a35414c58636f7a86919da8a89c91857a6e63574c403e3e3e3e3e3e3e4a5763707d8a97a4b0ada2989393939393939393939393939393939393939393939393939393939393877a6d6053473a2d201407000000000000000000000000000b1824303c4955616d7986929eaaaa9e9286796d6154483d4956626e7b8793a0a99d9184786c5f5347404c5865717d8a96a2a69a8e8275695d5044404c5965717d8a96a2afa4988c8073675b4f42362a1e1205000000000000000000000915212d3945515c68737f8a959f9c91877e77716e6d6f7379828b95a09b91867a6f635a65707a85909aa0958b80756a6056626e7b87939f9f93877b6f63584e49484e58636f7b87939f9f93877a6e6256493d3024180b0000131f2c3946525f6b7679797979797979797b8895a2978a7d7979797979797979786f6359646f7a858f9a9d92877c71675c64707c8894a0998d82776d645e5a595a5d636d77838f9ba295897c7063574a3e3124180b0000131f2c3946525f6b7679797979797979797b8895a2978a7d7979797979797979786f6359646f7a858f9a9d92877c71675c51463b404a555f6a747f8994968b80828f9c9c8f8275695c4f4236291c0f0300000000000c1925313e4a56626e7a85919b9f958b8179736f6c6b6a6b6d71778089949f9d92867a6e626a75808b95a0978c81766b60564b40434e58636d78828d9792877e8b98a09386796d6053463a2d201307000000000000111e2a3744515d6a7784909daab0a4978a7d7164574b3e31333c46505a646d77818b959fa59b92887e746a60574d43392f261c1926333f4c5966727f8c99a5b2a99c8f8275695c4f4336291c10030000131f2c3946525f6c7986929facaea295887b6f6255483c2f22150900000000000000000000000000000000000000000000000d192633404c596673808c99a6b3a89c8f8275685c4f4235291c0f000000000000000000000005111d2834404c58636f7b87939eaaa69a8e82766a5e53473b393939393939444f5b67737f8b97a3ada1958a7e72665a4e43372b1f13070000000000000000000000000000000002070b0e1014202d3a4653606d798693a0aca094877a6d6053473a2d201407000000000000000000000000121f2c3845525e6b7885919ea09386796d60534745525f6b7885919eaba093877a6d6154483b2f221a1d232a323a434d56606a75808a95a0abada093877a6d6154483b38434e5965707c88939f9b8f83776b5f53473b2e22160a00000000000009131e28323c454e575e666c71767a7c7e8080807e7c7976716b656f7a858f9aa0968b80766b6a71787d8285888a8b8b8b8a8885817c76706860574d44414b555e666e757b808487898a8b8b8a8987837f7a736c645b52493f342a1f140900000000000000000000000000000000020d1924303b47525e6975808c97a3ada2968b7f74685c51453a32323232323d4a5763707d8a97a4b0b4aaa3a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a094877a6d6053473a2d201407000000000000000000000000030f1b2734404c5865717d8996a2aea79b8e8276695d51453a46525f6b7784909ca8a094887b6f63564a434f5c6874818d99a5a3978a7e7265594d413d4955616e7a86939faba89c9083776b5f52463a2e211509000000000000000000000d1925313d4955616d7985909ba0958a7f756c65626163687079848f9aa2978c8074685d5e69737e89939e9c92877c71675c5f6b77838f9ba3978c80756a6059555558606974808b97a39a8e82766a5e52463a2d2115080000111e2a36434f5a646b6c6c6c6c6c6c6c6e7b8895a2978a7d716c6c6c6c6c6c6c6c675e535d68737e89939e998e83786d62606c78838e999e93897f766f6a676667696d757e8994a09d9286796d6154483b2f2216090000111e2a36434f5a646b6c6c6c6c6c6c6c6e7b8895a2978a7d716c6c6c6c6c6c6c6c675e535d68737e89939e998e83786d62584d4239434d58626d77828c979186828f9c9c8f8275695c4f4236291c0f0300000000000f1c2835414d5a66727e8a96a2998e83786f6863605e5d5e61666d77828d99a3978b7e7266636e79848f999d93887d72675c52473c47515c66717b8690988d828b98a09386796d6053463a2d201307000000000000111e2b3844515e6b7784919eaab0a3968a7d7063574a3d302a343e48525c656f79838d96a0a49a90867c72695f554b41382e241a25323f4b5865727e8b98a5b2a99d908376695d5043362a1d1003000013202c3946535f6c798693a0acaea295887b6e6155483b2e22150800000000000000000000000000000000000000000000000c1926323f4c5965727f8c99a6b2a99c8f8275695c4f4236291c0f0000000000000000000000000c18232f3b47535f6a76828e9aa5aa9e93877b6f63574b3f332c2c2c303c4854606c7884909ba7a89c9185796d61554a3e32261a0e03000000000000000000000000000000060d13171b1c1e232f3c4855616e7b8794a1ada094877a6d6053473a2d201407000000000000000000000000131f2c3946525f6c7985929f9f9286796c5f534646535f6c7986929fac9f9286796c5f5346392d201312182028313b444e59636e79848f9aa6aea295897c6f63564a3d323d48545f6b77838f9b9f93877b6f63574b3e32261a0d0100000000040f1a25303a444e57606970777d8286898b8c8c8c8b8986827c766f68737e88939e9d92877d7267666c7276797b7d7e7e7e7d7b7975716b655e564e453b39434c545c63696f74777a7c7d7e7e7d7c7a77736e68625a524940372d22180d02000000000000000000000000000000000008131f2a36414d58646f7a86929da8a79c9085796d62564b3f34282525303d4a5763707d8a97a4b0b8afa9a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a094877a6d6053473a2d20140700000000000000000000000006131f2b3744505c6874818d99a5b0a3978b7e72665a4d4136434f5b6774808c99a5a3978b7e72665a4d46535f6b7884909da9a093877b6e6256493d3946525e6a77838f9ca8ac9f93877b6e62564a3d3125190d00000000000000000004101c2935414d5a66727e8a95a19b9084786d635a5554565e67727d8994a09c9185796d6157626c77828c97a2998e83786e635b66727e8a95a19c91867c726a656262646a727b86919ca095897d72665a4e42362a1e110500000e1a26323d48525a5e5f5f5f5f5f5f616e7b8895a2978a7d71645f5f5f5f5f5f5f5c554c56616c77828d979f958a7f74695e66727d88929c9b9188817b7674737375797f87909ba1978c8175695d5145392c20130700000e1a26323d48525a5e5f5f5f5f5f5f616e7b8895a2978a7d71645f5f5f5f5f5f5f5c554c56616c77828d979f958a7f74695e54493e3c46515b66707b8590988d88919d9c8f8275695c4f4236291c0f030000000000111e2b3744505d6975828e969795897d71675d5753515152555b66717d8995a29a8e8175685d67727d88939e998e84796e63584d433f4a545f69747e8993948f929ca09386796d6053463a2d201307000000000000121e2b3845515e6b7884919eabb0a396897c6f6356493d30232c36404a535d67717b858e98a2a2988e857a71675d534a40362c2225323e4b5864717e8b98a4b1aa9d9084776a5d5044372a1d1104000013202c3946535f6c7986939facaea295887b6e6155483b2e22150800000000000000000000000000000000000000000000000c1926333f4c5965727f8c99a6b2a99c8f8275695c4f4236291c0f00000000000000000000000007131f2a36424e5a65717d8995a1aca3978b8074685c5044382c202935414d5965717c8894a0aca4988c8074685d5145392d21160a0000000000000000000000000000000810181e2327292a2d343f4b5764707d8996a2aca09386796d6053473a2d20140700000000000000000000000013202c3946535f6c7986929f9f9285786b5f52454653606d798693a0ab9e9285786b5e5245382c1f12060e161f29323c47515c67727e8995a0aca4978b7e7265584c3f3337434f5b66727e8b97a3988b7f73675a4e4235291d1004000000000a15202c36414c566069727a82898e9296989999999895928d888179716c77818c97a1998e84796e646166696d6f70717171706f6c6965605a534c443c33313a424a52585e63686b6e7071717171706e6b67625d57504840372e251b1106000000000000000000000000000000000000020e1925303c47535e6975818c97a3ada1968a7e73675c5045392e2224303d4a5763707d8a97a4b0b0a69d9999999999999999999999999999999999999999999999999999999994877a6d6053473a2d2014070000000000000000000000000a16222f3b4753606c7884919da9aca094877b6f62564a3e333f4c5864707d8995a2a79b8e8276695d514a56626f7b8794a0a89c9084776b5f52463a36424e5b6773808c98a4afa3978b7e72665a4d4135291c100400000000000000000713202c3845515d6a76828e9aa3978b7f73675c5149474c56616c7884909ca195897d7165595b65707b85909b9f958a80756a60626d79848f9aa3988e857c75716f6f70757b848d98a29a8f84786d61554a3e32261a0e0100000a16212c3640484e52525252525255616e7b8895a2978a7d716457525252525252504b45505b65707b86919b9b90867b7065616b76808a939b9a938c878381808082858a9199a1998f857b6f64594d4135291d100400000a16212c3640484e52525252525255616e7b8895a2978a7d716457525252525252504b45505b65707b86919b9b90867b70655a4f453a3f49545e69737e889397959aa39c8f8275695c4f4236291c0f030000000000131f2c3946525f6b788588898a8c85786c60554c474544454955616d7a8693a09c9083766a5d616b76818c97a0958a80756a5f54493f434d58626c77828c969b9da4a09386796d6053463a2d201307000000000000121e2b3845515e6b7885929eabb0a396897c6f6356493c3023242e38414b555f69737c86909aa4a0968d83796f655c52483e342a24313e4b5764717e8b98a4b1aa9d9084776a5d5044372a1d11040000131f2c3946525f6c7986929facafa295887b6f6255483c2f22160900000000000000000000000000000000000000000000000d1a2633404d596673808c99a6b3a89c8f8275685b4f4235291c0f000000000000000000000000020e1a26313d4955616c7884909ca8a89c9084786c6054493d31252e3a46515d6975818d99a5ab9f93877b6f64584c4034281d1105000000000000000000000000000007111a22292f333637393d45505b6773808c98a5aa9e9184786b5f5245392c1f130600000000000000000000000013202c3946535f6c798693a09f9285786b5f52454653606d798693a0ab9e9285786b5e5145382b1e1205040d17202b35404b56616d78848f9ba7a69a8d8174675b4e4235323e4a56626e7a87939f9b8f83766a5e5145382c201307000000040f1b26323d48535e68727b848c949a9e9c98969696989c9e99938b837a71707a85909aa0958b80756b60595d6062646565656462605d59544f49423a322a28303840474d53575b5f61636465656463615e5b57524c453e362e251c1309000000000000000000000000000000000000000008141f2b36414d58646f7b86929da9a79b9084786d61564a3f332824303d4a5763707d8a97a4b0ab9f948c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c877a6d6053473a2d2014070000000000000000000000010e1a26323f4b57636f7c8894a0ada99c9084786b5f53463a303c4854616d7986929eaa9e9285796d60544d5966727e8b97a3a5998c8074675b4f4336323f4b5764707c8995a1ada79a8e8276695d5145382c20140800000000000000000916222f3b4854616d7986929ea094877b6f63574b403b44505c6874808c99a5998d8174685c545e69747e89949e9c91877c71665c68737e88939ca0978e87817d7b7b7d81868d969f9c92887d72675c5045392d21150900000004101a242e363d4245464646464855616e7b8895a2978a7d7164574a4646464645443f3e49545f69747f8a959f978c82776c61646e78818a91989d97938f8d8c8d8e91969b9d978f877d73695e53483c3025190c00000004101a242e363d4245464646464855616e7b8895a2978a7d7164574a4646464645443f3e49545f69747f8a959f978c82776c61564b4138424d57626c77818c96a1a5a59c8f8275695c4f4236291c0f030000000000131f2c3946525f6b767a7b7c7d7e8076695d50443a38373945525f6b7885929f9d9184776a5d5a656f7a85909b9c91867b71665b50453b46505b65707a858f9a9f9f9f9386796d6053463a2d201307000000000000121e2b3844515e6b7784919eabb0a396897d7063564a3d30231c262f39434d57616a747e88929ca59f958b81776d645a50463c3329323e4b5865717e8b98a5b1aa9d9083766a5d5044372a1d11040000121f2c3845525f6b7885929eabafa296897c6f6356493d3023160a00000000000000000000000000000000000000000000000e1a2734414d5a6773818d9aa6b3a89b8e8275685b4e4235281b0f000000000000000000000000000915212d3844505c6873808b97a3aca095897d7165594d41352a323e4a56626e7a86929da9a69a8e82766b5f53473b3024180c0000000000000000000000000000030e19232c343b40424345494f57616d7884909ca8a69a8e8275695c5043372a1e110400000000000000000000000013202c3946525f6c7986929f9f9285786b5f52454653606c798693a0ab9e9285786b5f5245382c1f120500050f19242e3945505b67737e8a96a2a89c8f83766a5d5144382e3a46525e6b7783909c9f9286796d6154483b2f2216090000000814202c37434e59646f7a848d969e9d96908c8a898a8c91979e9d958c83796e737e89939e9c92877c72675c52545657585858575553504d48433d373028201e262e353c42474b4f525556575858575654524f4b46413a342c241c130a010000000000000000000000000000000000000000030e1925303c47535e6a75818c98a3aca095897e72675b5044382d24303d4a5763707d8a97a4b0a99c8f827f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7a6d6053473a2d201407000000000000000000000005111d2a36424e5b6773808c98a4b0a5998d8174685c4f43372c3845515d6a76828e9ba7a195897c706457505d6975828e9aa7a195897d7064584b3f332f3b4854606c7985919eaaaa9e9286796d6155483c3024170b00000000000000000c1825313e4a5763707c8995a29d9184786b5f53463a333f4b5864707d8996a29d9084776b5f5257626d77828d98a2988e83786d63616c76818a939ba098928d8a8888898c91989f9b938a80766b61564a3f34281c11050000000008121c242c3236383939393b4855616e7b8895a2978a7d7164574a3e39393939373437424d58636d78838e999e93887d73685d666f7780878d92979a9c9a99999b9c9a96918c857d746b61574d42372b2014080000000008121c242c3236383939393b4855616e7b8895a2978a7d7164574a3e39393939373437424d58636d78838e999e93887d73685d52473d3b45505a656f7a848f989898988f8275695c4f4236291c0f030000000000111e2a37434f5a646b6d6e7071727370665a4e413c3c3d3f45525f6b7885929f9d9084776a5d535e69747e89949f988d82776c62574c413f49535e68737d88929292929286796d6053463a2d201307000000000000111e2b3744515e6a7784919eaab0a3978a7d7063574a3d3124171e27313b454f58626c76808a939da79d938980766c62584e453b31323f4c5965727e8c98a5b2a99c908376695d5043362a1d10030000121e2b3844515e6b7784919eaab0a3978a7d7064574a3e3124180b00000000000000000000000000000000000000000000010f1c2835424e5b6874818e9ba7b3a79a8d8174675a4e4134271b0e0000000000000000000000000004101c28343f4b57636f7a86929eaaa5998d82756a5e52463a2e37434f5b67727e8a96a2ada1958a7e72665a4e42372b1f130700000000000000000000000000000914202a353e464c4f5052555a6169737e8995a0aca1968a7e7266594d4134281b0f02000000000000000000000000121f2c3945525f6c7885929f9f9286796c5f534646525f6c7985929fac9f9286796c5f5346392d201306000007121d28343f4b56626e7a86929eaa9f9286796d6054473b2e36424f5b6774808d99a295897c7063574a3e3125180b0000000c1925313c48545f6b76818b969f9d948b85807d7c7d80858c959e9e958b80756c77828c97a2998e83796e63594e494a4b4b4b4a494744413d38322c251e16141c242a30363b3f4346484a4b4b4b4b4a4846423f3a352f29221a120a010000000000000000000000000000000000000000000008141f2b36424d5964707b87929ea9a69a8f83786c6155493e3227303d4a5763707d8a97a4b0a99c8f82757272727272727272727272727272727272727272727272727272727271695d5145392c20130600000000000000000000000915212d3946525e6a77838f9ba8aea295897d7164584c40332935414e5a66727e8b97a4a5988c8073675b54606c7985919eaa9e9286796d6154483c2f2c3844505d6975828e9aa7aea295897d7164584c4033271b0f03000000000000000d1a2733404d5966727e8b98a49b8e8275695c5043372f3c4855616e7a8793a0a093877a6d6154505b66707b86919b9f958a7f746a5f656f78818991979c9d9996959596999d9c97918981786e645a4f44392e23170c0000000000000a121a21262a2c2c2c2e3b4855616e7b8895a2978a7d7164574a3e312c2c2c2b28313b46515c67717c87929d9a8f84796f645d656e757c82878b8e9091929291908d8a86817a736b625950453b30251a0f0300000000000a121a21262a2c2c2c2e3b4855616e7b8895a2978a7d7164574a3e312c2c2c2b28313b46515c67717c87929d9a8f84796f64594e43383e49535e68737d888c8c8c8c8c8275695c4f4236291c0f0300000000000e1a26323e48525a5f616263646567655e5449484848494b4f56626e7a8793a09b8f8275695c4f57626d78828d989f94897e73685e53483d424c57616c7681858585858585796d6053463a2d201307000000000000111d2a3744505d6a7683909da9b1a4978b7e7164584b3e322518151f29333d46505a646e78818b959fa59b91887e746a60574d433933404d596673808c99a6b2a89c8f8275695c4f4236291c10030000111d2a3743505d697683909ca9b1a4988b7e7265584c3f3326190d0000000000000000000000000000000000000000000004111d2a3743505d6976838f9ca9b2a5998c807366594d4033261a0d00000000000000000000000000000b17232f3b46525e6a76828d99a5aa9e92867a6e62564b3f333c48535f6b77838f9ba7a89c9185796d61554a3e32261a0e0200000000000000000000000000000d1925313c4650575c5d5e61656b737b85909aa6a59a9085796d6156493d3125190c00000000000000000000000000121f2b3845515e6b7885919ea09386796d60534745515e6b7784919eaaa093877a6d6154473b2e2115080000000c17232e3a46525e6a76828e9ba7a195887c6f63564a3e31333f4c5864717d8a96a3988b7e7266594c4033271a0d010004101d2935414d5965707c87929da0958b827a74706f70747a838c96a19c92877b6f707b85909ba0958a80756a60554a403e3e3e3e3c3a3834302c27211b140c0a12191f252a2f3336393b3d3e3e3e3e3d3b3936332e29241e171008000000000000000000000000000000000000000000000000030e1a25313c48535f6a75818d98a3aba094897d71665a4f43382c303d4a5763707d8a97a4b0a99c8f827569656565656565656565656565656565656565656565656565656565655f574c4135291d110400000000000000000000000c1825313d4956626e7a87939fabab9e9286796d6155483c3025323e4a56636f7b8894a0a89c8f83776a5e5763707c8895a1a79b8e8276695d5145382c2835414d5966727e8b97a3afa5998d8174685c4f43372b1f1206000000000000000f1c2835424e5b6874818d9aa6998c8073665a4d41342d3946525f6b7885919ea295897c6f63564a545f69747f8a949f9c91867b71665d666f777f868c909497989999989794918c867f776f665c52483d33281d110600000000000000080f151a1d1f1f222e3b4855616e7b8895a2978a7d7164574a3e31241f1f1e1f2a353f4a55606b75818b96a1968b80756a605c636a70767b7e81838585858483817e7a756f68615950473e34291f140900000000000000080f151a1d1f1f222e3b4855616e7b8895a2978a7d7164574a3e31241f1f1e1f2a353f4a55606b75818b96a1968b80756a60554a3f37414c56616b767e7e7e7e7e7e7e75695c4f4236291c0f0300000000000a16212c3740484f5354555657595a5953535555555556585b6068737e8a96a2978b7f73665a4d505b66717c87919c9b90857a6f645a4f443a454f5a646f78787878787878766b5f5246392c201306000000000000101d2936434f5c6975828f9ca8b2a5988c7f7266594c4033261a0d17212b353e48525c666f79838d97a1a39a90867c72695f554b4137424e5b6774818e9aa7b4a79a8e8174685b4e4135281b0f0200000f1c2935424f5b6875828e9ba7b3a6998d8073675a4e4135281c0f030000000000000000000000000000000000000000000713202c3945525e6b7884919daab0a4978b7e7164584b3e3225180c000000000000000000000000000007121e2a36424d5965717d8994a0aca2978b7f73675b4f4337404c5864707c88949faba3988c8074685c5145392d21150a000000000000000000000000000000111d2936424d5862686a6b6e71767d858e97a1a59c93897e73685c5145392d21150900000000000000000000000000111e2b3744515d6a7784909da194877b6e61554843505d6976838f9ca9a195887b6f6256493d3023170b00000006121d2935414e5a66727e8b97a4a4988b7e7266594d4034303c4955626e7b8894a19a8d8174685b4e4235281c0f02000714202c3945515d6975818d98a49a8f8479706864636469707a85909ba3988c807469747e89949e9c91877c71675c51473c323231302e2b2824201b1610090200070e141a1f23272a2d2f3031323231302f2d2a26221e19130c0600000000000000000000000000000000000000000000000000000914202b37424e5965707b87929ea9a59a8e83776b6054493d32303d4a5763707d8a97a4b0a99c8f8275695c595959595959595959595959595959595959595959595959595958544e453b3025190d010000000000000000000004101c2834414d5965727e8a96a3afa79b8f82766a5d5145392c222e3a47535f6c7884909da99f93867a6e615a6773808c98a4a3978b7e72665a4d41352925313d4a56626f7b8793a0aca99d9084786c5f53473b2e22160a00000000000000101d2a3643505d6976838f9ca4988b7e7165584b3f322a3744505d6a7683909ca4978a7e7164584b4d58626d78838d98a2988d83786d625d666d747b8084888a8c8c8c8c8a8884807b746d655d544a40362c21160b000000000000000000040a0e111215222e3b4855616e7b8895a2978a7d7164574a3e312417131218232e39444e59646f7a858f9a9d92877c71665c595f656a6e727577787878787674716e69645e574f473e352c22180d020000000000000000040a0e111215222e3b4855616e7b8895a2978a7d7164574a3e312417131218232e39444e59646f7a858f9a9d92877c71665c51463b3a454f5a646e727272727272726e65594d4134281b0f02000000000005101a252e373e434647484a4b4c4d4e575f626262626364676b727a858f9b9c91867b6f63574a4a545f6a75808b95a0968c81766b60554b403e48535d666b6b6b6b6b6b6b6a645a4f43372a1e11050000000000000f1b2835424e5b6874818e9aa7b3a79a8d8174675b4e4235281c0f0f19232c36404a545d67717b858f98a2a2988e847a71675d53494043505d6976828f9ca8b2a6998c8073665a4d4034271a0e0100000e1b2734414d5a6673808c99a6b2a89b8f8276695d5044372b1e12060000000000000000000000000000000000000000000a16232f3b4854616d7a8693a0acaea295897c6f63564a3d3024170a0000000000000000000000000000020e1925313d4954606c78848f9ba7a79b8f83776c6054483c45515d6974818c98a4ab9f93877b6f63584c4034281d1105000000000000000000000000000000121f2c3945525e6a7476787a7d82888f97a0a29b938a81776c62574b4034291d110500000000000000000000000000101d293643505c6976828f9ca295897c6f635649424e5b6874818e9aa7a3978a7d7164584c3f33261a0e010000010d1925313e4a56636f7b8894a1a79a8e8275695c5043372d3a4753606c7986929f9c8f8376695d5043372a1d1104000a17232f3c4855616d7986929ea195897d72675e5756585e68737e8a96a29d9185786c6d77828d97a2988e83786e63584e43382e2423211f1c1814100a050000000003090e13171b1e202224242525252422201d1a16120d0701000000000000000000000000000000000000000000000000000000030f1a26313c48535f6a76818d98a4ab9f94887c71655a4e4337303d4a5763707d8a97a4b0a99c8f8275695c4f4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c49433c33291e130800000000000000000000000713202c3844515d6975828e9aa6b0a4978b7f72665a4e4135291e2b3743505c6874818d99a6a2968a7d71655e6a76838f9ba8a094877b6f63564a3e3125212e3a46535f6b7784909ca9aca094887b6f63574a3e32261a0d01000000000000111e2b3844515e6a7784919da3978a7d7064574a3d312936424f5c6875828f9ba5988c7f7266594c46515b66717b86919c9f948a7f74695f5c63696f74787b7d7e80807f7d7b78746f69635b534b42382e241a1005000000000000000000000000000815222e3b4855616e7b8895a2978a7d7164574a3e3124170b07121c27323d48525d68737e89939e998e83786d625754595e6266686a6b6b6b6b6a6865625d58534c453d352c231a1006000000000000000000000000000815222e3b4855616e7b8895a2978a7d7164574a3e3124170b07121c27323d48525d68737e89939e998e83786d62574d42373d48525c6365656565656565635c53483d3125190c0000000000000009131c252c3237393a3c3d3e3f485460696f6f6f6f6f7173777d848d969c948a80756a5e5247434e58636e79848f999d92887d72675c51473c414b545b5f5f5f5f5f5f5f5e5a52483e32271b0e020000000000000d1a2733404d596673808c99a5b2a89c8f8276695d5044372b1e1207111a242e38424c555f69737d87909aa4a0968c83796f655b524846525f6b7884919eaab1a4978b7e7165584c3f3226190c0000000c1926323f4b5865717e8a97a3b0aa9e9185786c5f53473a2e22160a0000000000000000000000000000000000000000020e1a26323f4b5764707c8995a2aeaca093877a6d6154483b2e2215090000000000000000000000000000000915202c3844505b67737f8b96a2aca094887c7064584d414a55616d7985919da9a69a8e82766b5f53473b2f24180c0000000000000000000000000000000013202c3946535f6c798384878a8e93999f9b96908981786f655b50453a2f23180c00000000000000000000000000000f1c2835424e5b6874818e9aa3978a7d7164584b404c5966727e8b98a4a6998d8074675b4e42362a1d11050000000915222e3a4753606c7885919eaa9d9184786b5f53463a2d3845515e6b7784919d9e9184776b5e5145382b1f1205000d1926323f4b5864707d8995a29d9185796d61564c494c57626e7a86929fa195887c7066707b86909b9f958a80746a5f554a3f352a1f15120f0c0804000000000000000002070b0e1114161718181818171514110e0a06010000000000000000000000000000000000000000000000000000000000000914202b37424e5965707c87939eaaa4998d82766b5f54483c313d4a5763707d8a97a4b0a99c8f8275695c4f423f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3d38322a21170d0200000000000000000000000b17232f3c4854606d7985919eaaaca094887b6f63564a3e32251b2734404c5865717d8a96a2a6998d817468616d7a86929fa99d9084786b5f53473a2e221e2a37434f5b6874818d99a5b0a4988b7f73675a4e4236291d1105000000000000121f2c3845525f6b7885929ea296897c6f6356493d302835414e5b6774818e9ba69a8d8073675a4d404a545f6a747f8a959f9b90867b70665b585e63686c6f7172737372716f6c68635e58514941392f261d130800000000000000000000000000010815222e3b4855616e7b8895a2978a7d7164574a3e3124170b000b16202b36414c56616c77828d979f948a7f74695e534e5256595c5d5e5f5f5e5d5b5955514d47413a332b231a110800000000000000000000000000010815222e3b4855616e7b8895a2978a7d7164574a3e3124170b000b16202b36414c56616c77828d979f948a7f74695e53493e36404a51575858585858585857524a41372c20150900000000000000010a131b21272b2d2e2f30313e4b5864717b7b7b7b7c7d8083888e9698928a82786e63594d423c47525d67727d88939d998e84796e63584d4239424a4f52525252525252514e4840362c21160a000000000000000c1825323e4b5864717d8a97a3b0aa9e9185786c5f53473a2e22150909121c26303a434d57616b747e88929ca69e958b81776d645a504955616e7a8793a0acaea295897c7063564a3d3124170b0000000a1724303d4956626f7b8894a1adada094887b6f63564a3e32261a0e030000000000000000000000000000000000000007121e2a36424e5b6773808c98a5b1a99d9084776b5e5245392c20130700000000000000000000000000000004101c27333f4b57626e7a86929da9a4998d8175695d51454e5a66727e8a96a1ada195897d72665a4e42372b1f13070000000000000000000000000000000013202c3946535f6c79869193969a9f9a938f8b857f776f665d53493e34291e120700000000000000000000000000000d1a2733404d5966727f8c98a5998c8073665a4d414a57636f7c8895a1a89c9083776a5e52463a2e22160a00000006121f2b3744505d6976828f9ca8a094877b6e6255493d303743505d697683909c9f9285796c5f5246392c201306000f1b2834414e5a6773808c99a59b8e8275695d50443c46525e6a76838f9ca4988b7f726669747f8a949f9c91867b71665c51463c31261c11060000000000000000000000000000020507090a0b0b0b0b0a09070501000000000000000000000000000000000000000000000000000000000000000000030f1a26313d48545f6b76828d99a4aa9e93877b7065594d42363d4a5763707d8a97a4b0a99c8f8275695c4f4236323232323232323232323232323232323232323232323232302c2720180f050000000000000000000000020e1b27333f4b5864707c8995a1ada99d9084786c5f53473a2e221824303c4955616d7a86929fa99c9084776b64717d8996a2a5998d8174685c4f43372b1e1b27333f4c5864717d8996a2aea79b8f83766a5e5245392d211508000000000000131f2c3946525f6c7986929fa295887c6f6255493c2f2734414d5a6774818d9aa79a8e8174675a4d41434d58636e78838e98a2988d82776d625753585c5f62646566666564625f5c58534d463f372f261d140b010000000000000000000000050a0d0f15222e3b4855616e7b8895a2978a7d7164574a3e3124170b00040f1a242f3a45505b65707b86919b9b90867b70655a4f464a4d4f5152525251504f4c4945413c36302921191108000000000000000000000000050a0d0f15222e3b4855616e7b8895a2978a7d7164574a3e3124170b00040f1a242f3a45505b65707b86919b9b90867b70655a4f453a3840464a4c4c4c4c4c4c4c4b4740382f251a0f040000000000000000010910161b1e20212225323e4b5865717e888888898a8c8f9493908c8780786f665c52473c35404b56616b76818c97a0958a80746a5f54493e383f434545454545454545423d362e241a1005000000000000000a1723303c4955626f7b8894a1adada094887b6f62564a3e3125190d020a141e28313b454f59626c76808a949da79d938980756c62584e5865717d8a96a2afac9f93867a6d6154483b2f2215090000000815212e3a4753606c7885919eaab0a3978b7e73665a4e42372b1f1409000000000000000000000000000000000000020d18232f3b47525e6b77838f9ba8b2a69a8d8175685c4f43362a1d1104000000000000000000000000000000000b17232e3a46525e6975818d99a4a99d9185796e62564a535f6b76828e9aa6a89c9185796d6155493e32261a0e020000000000000000000000000000000013202c3946535f6c798693a0a2a69f9388837f7a746d655d544b41372d22170c0100000000000000000000000000000c1825323e4b5764707d8a96a39b8e8275695c50434754606d7985929eaa9f93877a6e62564a3e32271b10040000030f1c2835414e5a6774818d99a6a3968a7d7165584c3f3335424f5c6875828f9ba09386796d6053473a2d20140700101d2936434f5c6975828f9ba5988c7f73665a4d4135424e5b6774808d99a69a8e817468626d78838d98a3988d83786d62584d43382d23180d03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000915202c37434e5a65707c88939eaaa4988d81756a5e53473c3d4a5763707d8a97a4b0a99c8f8275695c4f423629262626262626262626262626262626262626262626262524201b150e0600000000000000000000000006121e2a37434f5b6874808c99a5b1a5998d8174685c5043372b1e14202d3945525e6a76838f9ba8a093877b6e6774808c99a5a296897d7165584c4033271b1723303c4855616d7986929eabab9f93867a6e6255493d3124180c00000000000013202c3946535f6c798693a0a295887b6f6255483c2f2734404d5a6773818d9aa79b8e8174675b4e413c47515c67717c87919c9e94897e74695e544c5053565759595959585653504c47423b352d261d140b0200000000000000000000030a11161a1c1c222e3b4855616e7b8895a2978a7d7164574a3e3124170b000008131e29333e49545f69747f8a959f978c81766c61564b40404244454545454442403d3935302b251e170f070000000000000000000000030a11161a1c1c222e3b4855616e7b8895a2978a7d7164574a3e3124170b000008131e29333e49545f69747f8a959f978c81766c61564b4036353a3e3f3f3f3f3f3f3f3e3b362f261d13090000000000000000000000050a0f1213141825323e4b5865717e8b959596979990898784817b756e665d544a40362f39444f5a656f7a85909b9c91867b70665b50453a3337383838383838383836322c241c120800000000000000000814212e3a4753606c7885919eaab0a3978b7e72665a4e42362a1e1307020c161f29333d47515a646e78828c959fa59b91887e746a60565c6874818d99a5b2a99c9084776b5e5245392c20130700000006121f2b3844505d6975828e9aa6b3a79b8f83776b5f53473c30251a0f05000000000000000000000000000000000009131e2934404b57636f7b87939fabafa3968a7e7265594c4034271b0e020000000000000000000000000000000006121e2935414d5965707c8894a0aba2968a7e72665a4f57636f7b87939faba3988c8074685c5045392d21150a000000000000000000000000000000000013202c3946535f6c7986939da0a49f938884807a746d655d544b41372d22170c0100000000000000000000000000000a1623303c4955626e7b8794a09d9184786b5f524644515d6975828e9aa6a3978a7e72665a4f43372c21160b0100000d1926333f4c5965727e8b98a5a6998d8174685b4f423635414e5b6774818e9ba094877a6d6154473a2e21140700111e2b3744515e6a7784909da4978a7d7164574b3e333f4c5865727e8b98a49c908376695d66717b86919c9f948a7f746a5f544a3f342a1f140a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040f1b26323d4954606b76828d99a4a99e92877b6f64584d413d4a5763707d8a97a4b0a99c8f8275695c4f4236291c191919191919191919191919191919191919191919191714100a04000000000000000000000000000916222e3a46535f6b7784909ca8aea2968a7d7165584c4033271b111d2936424e5a67737f8c98a4a3978a7e716a7783909ca89f92867a6d6155493c30241714202c3945515d6a76828f9ba7afa2968a7d7165594d4034281c0f03000000000013202c3946535f6c798693a0a295887b6f6255483c2f2734404d5a6773818d9aa79b8e8174675b4e4135404a55606a75808a95a09b90867b70655b504547494b4c4c4c4c4b494744403b36302a231c140b0200000000000000000000040d151c22262829282e3b4855616e7b8895a2978a7d7164574a3e3124170b0000010c17222d37424d58636d78838e999e93887d72685d52473c363738383838373533312d29251f1a130d050000000000000000000000040d151c22262829282e3b4855616e7b8895a2978a7d7164574a3e3124170b0000010c17222d37424d58636d78838e999e93887d72685d52473c322e3132323232323232312f2a241d140b010000000000000000000000060c1216191b1c25323e4b5865717e8b9898999a9a8d827f7b76706a645c544b42382e28333d48535e69737e89949f988d82776c61574c41362b2c2c2c2c2c2c2c2b2a26211a120a00000000000000000006121f2b3744505d6975828e9ba7b3a79a8e82766a5e52463b2f24180e03040e17212b353f48525c667079838d97a1a39990867c72685f606c7884919da9b2a5998d8174685b4f43362a1d1104000000030f1c2834414d5966727e8a96a3afab9f93877b6f64584d42372c21170d0400000000000000000000000000000008111b25303b46515c6874808b97a3afab9f93867a6e6256493d3124180b0000000000000000000000000000000000010d1925313c4854606b77838f9ba7a69b8f83776b5f535c6874808c98a3aa9f93877b6f63584c4034281c1105000000000000000000000000000000000013202c3946535f6c79868f9194989c9a93908b857f776f665d53493e34291e120700000000000000000000000000000814212d3a46535f6c7885919ea093877a6e625549414d5965727e8a96a2a79b8f83776b5f54493d32271d130a02000b1824313e4b5764717d8a97a4a99c9083776a5e52453934414e5a6774818e9aa194877b6e6154483b2e21150800121f2c3845525f6b7885929ea296897c6f6356493d313e4a5764707d8a97a39e9184776b5e5f6a747f8a959f9b91867b71665b50463b31261b1106000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a15212c37434e5a65717c88939faaa3978c8175695e52473d4a5763707d8a97a4b0a99c8f8275695c4f4236291c0f0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0b08040000000000000000000000000000010d1925323e4a56636f7b8794a0acab9f92867a6d6155493c3024180d1a26323e4b57636f7c8894a1a69a8d81746d7986929fa79b8f83766a5e5145392d2014101d2935424e5a66737f8b98a4b0a69a8d8175695c5044382c1f1307000000000013202c3946535f6c7986929fa295887b6f6255483c2f2734404d5a6773818d9aa79a8e8174675b4e413439434e59636e79838e99a2978c82776c62574c423c3e3f40403f3e3d3a37342f2b251f18110a0200000000000000000000030d161f272d32353635313b4855616e7b8895a2978a7d7164574a3e3124170b00000005101b26313b46515c67717c87929d9a8f84796e64594e43382d2c2c2c2b2a292724211d19140e08020000000000000000000000030d161f272d32353635313b4855616e7b8895a2978a7d7164574a3e3124170b00000005101b26313b46515c67717c87929d9a8f84796e64594e43382d252525252525252525221e19120b0200000000000000000000000810171e222627292a323e4b5865717e8b8b8b8c8e91948f8b87827b746b62594e44392e232c37414c57626d77828d989e94897e73685d53483d32271f1f1f1f1f1f1f1d1a150f0800000000000000000000030f1c2835414d5a66727e8b97a3afaa9e92867a6e63574c40352a1f150b02050f19232d36404a545e68717b858f99a3a2988e847a716765717d8995a1adaea296897d7165584c4033271a0e02000000000c1925313d4a56626e7a86929eaaafa3988c8075695e53483d33291f160e070100000000000000000000000309111a232d37414c57626d7985909ca8b2a69a8e82766a5e5246392d2115080000000000000000000000000000000000000814202c37434f5b67737e8a96a2ab9f93877b6f6458616d7884909ca8a69a8e82766a5f53473b2f23180c00000000000000000000000000000000000013202c3946535f6c79818284878c91979f9c97908981786f655b50453a2f23180c000000000000000000000000000005121e2b3744505d6975828e9ba3968a7e7165594d404955616d7985919da89f93887c70655a4f44392f251c140e0c0d1824313e4a5764717d8a97a4ab9f93867a6d6154483c34414d5a6774818e9aa194887b6e6154483b2e2115080013202c3946535f6c7986929fa295887b6f6255493c303d495663707c8996a39e9285786b5e58636d78838e98a2988d82776d62584d42382d22180d0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101b26323d4954606b77828e99a5a89d91867a6e63574c404a5763707d8a97a4b0a99c8f8275695c4f4236291c0f0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0c0a0703000000000000000000000004111d2935414e5a66727e8b97a3b0a79b8f83766a5e5145392d20140a16222f3b4753606c7885919da99c908477707c8995a2a4988b7f73675a4e4235291d110d1926323e4a57636f7b8894a0adaa9d9185796c6054483b2f23170a0000000000131f2c3946525f6c7885929fa296897c6f6255493c2f2734414d5a6774818e9aa79a8d8174675a4d4134323c47525c67727c87929c9e93897e73695e53493e333233333232302e2b28241f1a140e070000000000000000000000000a151f2831383e4243413d3b4855616e7b8895a2978a7d7164574a3e3124170b0000000009141f2a353f4a55606b75818b96a0968b80756a60554a3f34291f1f1f1e1c1a1815110d0803000000000000000000000000000a151f2831383e4243413d3b4855616e7b8895a2978a7d7164574a3e3124170b0000000009141f2a353f4a55606b75818b96a0968b80756a60554a3f34291f1919191919191816130e0801000000000000000000000007111a22292e32343536383e4b5865717e7e7e7e7f81858a9097938d867d746a60554a3f342825303b46505b66717c87919c9a90857a6f64594f44392e23181212121212110e09040000000000000000000000000c1925313e4a56626e7b87939fabafa3978b8074685d51463c31271d140b0307111b252e38424c565f69737d87919aa4a0968c83796f6b76828d99a5b1a99d9285796d6155493c3024170b00000000000915212d3a46525e6a76828e99a5b1a89d91867a6f645a4f453b31282019120d08050201000000010306090e141b232c353f49535e68737e8a96a1adada1968a7e72665a4e42362a1d1105000000000000000000000000000000000000030f1b27333f4a56626e7985919da9a4988c8074685c65717d8995a1ada195897d72665a4e42362b1f1307000000000000000000000000000000000000121f2c3845515d69727475787b80868d959ea29b938a81776c61574b4034291d110500000000000000000000000000030f1c2834414d5a66727e8b97a49a8d8175695c504445515d6974808c97a3a4998d82766b60554b41372e251e1a18191e2733404c5865727e8b98a4aea295897d7064574b3e34414e5b6774818e9aa194877a6e6154473b2e2114080013202c3946535f6c798693a0a295887b6f6255483c303c4956636f7c8996a29f9285786b5f525c66717c87919c9f94897e74695f54493f34291f1409000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a15212c38434f5a66717d88949faba2978b8074685d51464a5763707d8a97a4b0a99c8f8275695c4f4236291c1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1917130e08010000000000000000000814202d3945515d6a76828e9ba7b0a4988b7f73665a4e4235291d1106131f2b3844505c6975818d9aa69f93877a737f8c98a5a194887c6f63574b3e3226190d0a16222e3b4753606c7885919da9ada195887c7064574b3f33271a0e0200000000121f2b3845525e6b7885919ea396897c7063564a3d302835424e5b6874818e9ba6998c807366594d40332b35404b55606b75808b95a09b90857a70655a50453a302626262523211f1b17130e090300000000000000000000000004101b26313a434a4e4f4e49424855616e7b8895a2978a7d7164574a3e3124170b00000000030d18232e39444e59646f7a848f9a9c92877c71665b51463b30251a1211100e0b080501000000000000000000000000000004101b26313a434a4e4f4e49424855616e7b8895a2978a7d7164574a3e3124170b00000000030d18232e39444e59646f7a848f9a9c92877c71665b51463b30251a100c0c0c0c0b0a0602000000000000000000000000040f19232c343a3f41424344454955616b717171717375797e858e979890867c72675c5045392d2129343f4a545f6a75808b95a0968b81766b60554a40352a1f140a000000000000000000000000000000000000000915222e3a46525e6a76838e9aa6b2a79c9085796e63584d43392f261d150e0809131c26303a444d57616b757e89929ca69e958b8177707c87939eaab0a5998d8175695d5145392d201408000000000005111d2936424e5965717d8994a0abaea3978c81766b61574d433a322a231d1814110f0d0d0c0d0e0f12151a1f262d353e47515b656f7a85909ba7b2a79c9085796d61564a3e3226190d01000000000000000000000000000000000000000a16222e3a45515d6975818c98a4a89c9084786c606a76828e9aa6a89c9085796d6155493d32261a0e02000000000000000000000000000000000000101d2935414c57606667696b6f747b838c96a0a59c93897e73685c5145392d21150900000000000000000000000000000c1925313e4a56636f7b8894a09d9185796d615549404c58646f7b87929da89e93887c72675d53494037302a26252629303944505c6874818d9aa6b1a5988c8073675a4e4135424f5b6875828e9ba094877a6d6054473a2e2114070013202c3946535f6c798693a0a295887b6f6255483c303c4956636f7c8996a39f9285786b5f5255606a75808a95a09b90867b70655b50463b30261b100600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101b27323e4955606b77838e9aa5a89c9185796e62574b4a5763707d8a97a4b0a99c8f8275695c4f4236292626262626262626262626262626262626262626262626262626231f19130b0200000000000000000b1824303c4955616d7a86929eabada094887b6f63574a3e3226190d030f1c2834404d5965717e8a96a3a296897d75828f9ba79d9185786c6053473b2f22160a06121f2b3744505c6875818d9aa6b1a5988c8074675b4f43362a1e120500000000111e2b3744515d6a7784909da4978a7d7164574b3e312936434f5c6975828f9ca5988c7e7265594c3f32262e39444e59646e79848e99a1978c81776c61574c41372c2119181715120f0b070200000000000000000000000000000915212d38434c555a5c5a534c4855616e7b8895a2978a7d7164574a3e3124170b000000000007111c27323d48525d68737e89939e988e83786d62574c42372c21160c01000000000000000000000000000000000000000915212d38434c555a5c5a534c4855616e7b8895a2978a7d7164574a3e3124170b000000000007111c27323d48525d68737e89939e988e83786d62574c42372c21160c010000000000000000000000000000000000000a16212b353e454b4e4f505152535459616565656566696d747c85909b988e84786d6155493d3125222d38434e58636e79848f999d92877c72675c51463c31261b100600000000000000000000000000000000000006121e2a36424e5a66727e8a95a1acada1968a8074695f554b41382f27201914100c141e28323c454f59636d76808a949ea69d93897f77828d98a4afab9f94887c7165594d4135291c10040000000000010d1925313d4955606c78838f9aa5b0a89d92887d73695f564d443c352f2924211e1c1a1919191a1c1e22262b31373f475059636c77818c96a1acaca1968b8074685c5145392d211509000000000000000000000000000000000000000006111d2935414c5864707c88939faba195897d71656e7a86929eaaa3978c8074685c5045392d211509000000000000000000000000000000000000000d1924303b454e565a5b5c5f6369717a848e99a5a59a9084796d6156493d3125190c00000000000000000000000000000916222e3a47535f6b7784909ca195897d7165594d4247535e6a75818c97a2a4998e83796e655b5249423b36333233353a424b55606c7884909ca9b4a89b8f8276695d50443843505d6976838f9c9f9386796c6053463a2d20130700131f2c3946525f6c7986929fa295887c6f6255493c303d4a5663707d8996a39e9185786b5e514e59636e79838e99a2978d82776c62574c42372d22170d020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a16212d38444f5b66717d89949faba2968a7f73685c514a5763707d8a97a4b0a99c8f8275695c4f42363333333333333333333333333333333333333333333333333333322f2b241d140b01000000000000030f1b2834404c5965717d8996a2aea99d9184786c5f53473b2e22160a000c1824313d4955626e7a87939fa5998c807885919ea69a8d8175695c5044372b1f1306030f1b2834404c5965717d8a96a2afa89c9083776b5f52463a2e22150900000000101d2936434f5c6975828f9ba5988b7e7265594c3f332b3744515d6a7783909da3978a7d7164574b3e312527323d47525d67727d87929d9e93897e73685e53483e33281e130a08060300000000000000000000000000000000000c1825313d49545f6669655e575055616e7b8895a2978a7d7164574a3e3124170b0000000000000b16202b36414c56616c77828d979f94897e74695e53483e33281d1208000000000000000000000000000000000000000c1825313d49545f6669655e575055616e7b8895a2978a7d7164574a3e3124170b0000000000000b16202b36414c56616c77828d979f94897e74695e53483e33281d12080000000000000000000000000000000000030f1b27323d4750575a5b5d5e5f60615e5758585858595c626a737e8a96a095897d7265594d4034281c26313c47525d67727d88939d998e83786e63584d42382d22170c010000000000000000000000000000000000020e1a26323e4a56616d7984909ba6b2a79c91867b71665d534a4139312b25201c191716202a333d47515b646e78828c969fa59b91877e89939ea9b0a59a8e83776c6054483c3025180c000000000000000915212c3844505b66727d89949fa9afa4998f857b71685f564e47403a35302d2a282726262627292b2e32363c42495159626b757e89939da8b1a69b90857a6e63574c4034291d11050000000000000000000000000000000000000000010d1824303c48535f6b77838f9aa6a5998d817569727e8a97a3aa9f93877b6f63574c4034281c10050000000000000000000000000000000000000008131f29333c444a4d4e5053585f68727d88949faba1968a7e7266594d4134281b0f020000000000000000000000000006121e2b37434f5b6773808c98a4998d82766a5e5247424d59646f7a85909ba5a0958b81766d645b534c46423f3e3f41454c545d67727d8994a0a4a8aa9e9285796c6053473a45525e6b7784919d9e9185786b5f5245392c1f120600121f2c3845525e6b7885919ea396897c7063564a3d313e4a5764717d8a97a49d9084776a5e5147525c67727c87929c9e94897e74695e53493e34291e140900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005101c27333e4955606c77838e9aa5a79b9084796d62564a5763707d8a97a4b0a99c8f8275695c4f424040404040404040404040404040404040404040404040404040403f3b362f261d130800000000000006131f2b3744505c6875818d99a6b2a6998d8175685c5044372b1f1206000815212d3946525e6b77838f9ca89b8f837b8794a0a3968a7e7165594d4034281b0f03000c1824303d4955626e7a87939fabaca093877b6e62564a3e3125190d000000000f1b2835414e5a6774818d9aa6998d8174675a4e41352d3946525f6c7885919ea195887b6f6256493c3023202b36404b56606b76818b96a09a8f857a6f655a4f453a2f251a0f05000000000000000000000000000000000000000e1a2734404d596571767069615a55616e7b8895a2978a7d7164574a3e3124170b000000000000040f1a242f3a45505a65707b86919b9b90857a70655a4f443a2f24190e030000000000000000000000000000000000000e1a2734404d596571767069615a55616e7b8895a2978a7d7164574a3e3124170b000000000000040f1a242f3a45505a65707b86919b9b90857a70655a4f443a2f24190e030000000000000000000000000000000006131f2b37434e59626768696a6b6d6d6960554b4b4b4d5158626d7986929f9a8e8275695c5043362a1d202a35404b56616b76818c97a0958a7f746a5f54493e33291e13080000000000000000000000000000000000000a16212d3945515c68737e8a95a0abada2988d83786e655c534b433c36302c2825232221212b353f49535c66707a848d97a1a399908a909aa5b0aa9f94897d72665b4f43382c2014080000000000000004101c27333f4a55616c77828d98a2acaba1978d837a71686058514b45413d393735343332333435373a3e42474d545b636b747d87909aa5afa99f948a7e73685d52463b2f24180c0000000000000000000000000000000000000000000008141f2b37434f5a66727e8a96a1a99d9185796d76838f9ba7a69a8e82766a5f53473b2f23180c0000000000000000000000000000000000000000020d17212a32393e404143474d56606b77838f9ba7a69a8e8275695c5043372a1e110500000000000000000000000000020f1b27333f4b57636f7b87939f9e92867a6f63584c4148535e69747e89949ea79c92897f766d655e57524e4c4b4c4e51575d666f79838e9a97989ea8a194887b6f63564a3d4754606d7986939f9d9083776a5d5144372b1e110500111e2b3744515d6a7783909da4978a7e7164584b3f333f4c5865727e8b98a59c8f8276695c50434b55606b75808b95a09b90857a70655b50453a30251b10050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b16222d38444f5b66727d8994a0aba1958a7e73675b505763707d8a97a4b0a99c8f8275695c4f4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4b4741382f241a0e0300000000000a16232f3b4753606c7885919da9afa2968a7d7165594c4034281b0f030005111d2a36424f5b6773808c98a59e92857e8a97a39f93877a6e6255493d3124180c00000814212d3946525e6a77838f9ca8afa3978b7e72665a4d4135291c10040000000d1a26333f4c5865727e8b97a49b8f8276695d504438303c4855616e7a8793a09f9286796d6054473b2e2119242f39444f59646f79848f99a1968c81766c61564c41362c21160c010000000000000000000000000000000000000e1b2834414e5b6774817a736c655e616e7b8895a2978a7d7164574a3e3124170b0000000000000008131e28333e49545f69747f8a959f978c81766c61564b40352b20150a0000000000000000000000000000000000000e1b2834414e5b6774817a736c655e616e7b8895a2978a7d7164574a3e3124170b0000000000000008131e28333e49545f69747f8a959f978c81766c61564b40352b20150a000000000000000000000000000000000815212e3b4753606b7375767778797a7165594c3f3f4046515e6a7784909d9d9184776b5e5145382b1f19242f39444f5a656f7a85909b9c91867b70655b50453a2f251a0f04000000000000000000000000000000000005111d2834404b57626d79848f9aa4afa99f948a81776e655d554e47413c383432302e2e2d2e2f37414a545e68727b858f99a3a29a969aa2acada3988d82776c61554a3e33271b0f0400000000000000000b17222d39444f5b66717b86909ba5afa89f958c837a726a635c56514d4946434140403f40404244464a4e53585e656d757d868f99a2acaca2978d83786d62574c41352a1e130700000000000000000000000000000000000000000000030f1b26323e4a56616d7985919ca8a295897d717a87939faba195897d71665a4e42362a1f1307000000000000000000000000000000000000000000060f1821282d323435373b444f5b67737f8b98a4aa9e9185786b5f5245392c1f130600000000000000000000000000000b17232f3b47535f6b77828e9aa3978b8074695d5247414d57626d77828c96a0a49b918880777069635e5b5958595a5d62686f78818b95928a8c96a2a4978b7e7265594d404a56636f7c8895a19b8e8175685b4f4236291c100300101d2936424f5c6875828e9ba5998c8073665a4d4135424e5b6774818d99a69a8d8174675b4e42444e59646e79848e99a2978c82776c61574c42372c22170c02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005101c27333e4a55616c78838f9aa6a69b8f84786c61555763707d8a97a4b0a99c8f8275695c595959595959595959595959595959595959595959595959595959595958524a41362b1f140800000000010e1a26323f4b57636f7c8894a1adab9f93867a6e6155493d3024180b0000010e1a26333f4b5764707c8995a1a19588818d99a69c8f83776a5e5246392d211508000005111d2a36424e5b6773808c98a4b1a79a8e8276695d5145392c2014080000000b1824313d4a56636f7b8894a19e9185786c6054473c34404c5864707d8996a29c9083776a5e5145382c1f131d28323d48525d68727d88929d9d93887d73685d53483d33281d13080000000000000000000000000000000000000e1b2834414e5b677481857e766f68616e7b8895a2978a7d7164574a3e3124170b00000000000000010c17222d37424d58636d78838e999e93887d72675d52473c31271c110600000000000000000000000000000000000e1b2834414e5b677481857e766f68616e7b8895a2978a7d7164574a3e3124170b00000000000000010c17222d37424d58636d78838e999e93887d72675d52473c31271c11060000000000000000000000000000000915222f3c4855626f7b82838485868074675b4f443f3f44515d6a7784909d9f9285786b5f5245382c1f121d28333d48535e69737e89949f988d82776c61574c41362b20160b0000000000000000000000000000000000000c18232f3a45515c67727d88929da7b0a69c938980776f675f58524d4844413e3c3b3a3a3a3b3d3f424c566069737d87919ba5a5a3a5abafa59b91867b71665b4f44392d22160a00000000000000000006111c28333e49545f6a747e89939da6afa79e958c847c746e68625d595552504e4d4c4c4c4d4e5053565a5e646970777e878f98a1abada39a90867b71665b51463a2f24190d0200000000000000000000000000000000000000000000000a16222d3945515d6874808c98a3a69a8d81757e8b97a3a89c9084786d6155493d32261a0e0200000000000000000000000000000000000000000000060f161d222527282b323e4a5763707c8995a2aca09386796d6053473a2d201407000000000000000000000000000007131f2b37424e5a66727d8995a09c91857a6e63584d4246515b66707a848e97a0a39a9189817a746f6a67656565676a6e737a818a93978c8186929fa79a8e8175685c50434d5a66727e8b97a4988c7f7366594d4034271b0e01000e1b2734414d5a6673808c98a59b8f8276695d51454045515e6a76838f9ca4978b7e7265594c403d47525d67727d87929d9e93897e73685e53493e33281e13090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b16222d3944505b66727d8995a0aba095897d7266616163707d8a97a4b0a99c8f827569666666666666666666666666666666666666666666666666666666666666645c52473c3024170b0000000005111e2a36424e5b6773808c98a4b0a89b8f83766a5e5245392d2114080000000a17232f3b4854606c7985919ea4978c86909ca5988c8073675b4f42362a1d11050000010e1a26323f4b5764707c8995a1adaa9e9286796d6155483c3024170b0000000915222e3b4753606c7885919da194887c7064584d424045505c6874808c99a5998c8074675b4f4236291d1016212b36414b56616b76818b96a19a8f847a6f645a4f443a2f241a0f0400000000000000000000000000000000000e1b2834414e5b6774818e88817a736b6e7b8895a2978a7d7164574a3e3124170b000000000000000005101b26313b46515c67717c87929d9a8f84796e63594e43382d22180d02000000000000000000000000000000000e1b2834414e5b6774818e88817a736b6e7b8895a2978a7d7164574a3e3124170b000000000000000005101b26313b46515c67717c87929d9a8f84796e63594e43382d22180d0200000000000000000000000000000815212e3b4754606d79868f91928f83776b60564f4c4c4e55606c7885919e9e9285786b5f5245382c1f1216212c37414c57626d77828d989e93897e73685d52483d32271c1207000000000000000000000000000000000007121e2934404b56616b76818b959fa9aea49b92898178716a635e5954504d4b494847474748494b4e51555a616b757f89939fabb0b2b1a79d94897f746a5f54493e33281c1105000000000000000000000b17222d38434d58626d77818b949da6afa79e968e868079736e6965615f5c5b5a5959595a5b5d5f62666a6f757b82899199a1aaaca49b91887e74695f554a3f34291e130700000000000000000000000000000000000000000000000005111d2934404c58646f7b87939faa9d918579828e9ba7a3978c8074685c5044392d211509000000000000000000000000000000000000000000000000040b1116191a1b222f3b4854616e7a8794a0ada094877a6d6053473a2d2014070000000000000000000000000000020e1a26323e4a55616d78848f9ba2968b8074695e53483f49545e68727b858e979fa39b938c85807a777472717273767a7e858b939b91867b838f9ca89d9184786b5f5246515d6976828e9ba295897c7064574b3e3225180c00000c1925323e4b5764707c8995a19e9285796d62574f4d4e57626e7a86929ea094887b6f63564a3d36404b56606b76818b96a09a90857a6f655a4f453a30251a1005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005111c28333f4a56616c78848f9aa6a59a8e83776e6e6e6e707d8a97a4b0a99c8f8275737373737373737373737373737373737373737373737373737373737373736e64584c4033261a0d000000000915212d3a46525e6a77838f9ba8b0a4988c8073675a4e4236291d110500000007131f2c3844505d6975828e9aa69d959398a1a195897c7064574b3f33261a0e010000000a16232f3b4854606c7985919eaaaea295897d7164584c4034271b0f03000006121f2b3844505c6975818d99a4988c8075695e544e4d4f57616d7884909ca094897c7064584c3f33271a0e0f1a242f3a444f5a646f7a858f9aa1968b81766b61564b41362b21160b01000000000000000000000000000000000e1b2834414e5b6774818e938b847d766f7b8895a2978a7d7164574a3e3124170b00000000000000000009141f2a353f4a55606b75818b96a0968b80756a5f554a3f34291e1409000000000000000000000000000000000e1b2834414e5b6774818e938b847d766f7b8895a2978a7d7164574a3e3124170b00000000000000000009141f2a353f4a55606b75818b96a0968b80756a5f554a3f34291e1409000000000000000000000000000006131f2c3845515e6a76838f9b9e93887c7168605b59595a5e67717c8894a19d9084776a5e5144382b1e120f1a25303b46505b66717c87919c9a8f857a6f64594e44392e23180d0300000000000000000000000000000000010c18232e39444f5a646f79838d97a0a9ada49b938a837b756f6964605d5a5756555453545556585a5e61666b70777d85919daab7b7ab9f958c82776d63584e43382d22160b000000000000000000000005101b26313c46515b656f78828b949da5ada8a098918a847e7975716e6b69676666656667686a6c6f72767b80868c939ba3ababa39a92897f766c62584d43382d23180d02000000000000000000000000000000000000000000000000000c1824303b47535f6b76828e9aa6a195897d86929faa9e93877b6f63574c4034281c1005000000000000000000000000000000000000000000000000000005090c0e13202d3a4653606c798693a0aca094877a6d6053473a2d2014070000000000000000000000000000000a16212d3944505c67737e8a95a09c91867b70655a4f45424c566069737c858d959da49e97918b8783817f7e7e8082868a90969d948a7f74808c99a5a093877a6e62554a56616d7986929e9f92867a6d6154483b2f23160a00000a16232f3b4854606d7985919da2968a7e7368605b595a5f68737e8a96a29c9084786c5f53473a2f39444f59646f79848f99a1978c81766c61564c41372c21170c0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17222e3944505b67727e8995a0ab9f93887c7b7b7b7b7b7d8a97a4b0a99c8f83808080808080808080808080808080808080808080808080808080808080808074675a4d4134271a0e010000000c1825313d4956626e7a87939fabada194887c6f63574b3e32261a0d0100000003101c2834414d5966727e8a97a3a7a1a0a3aa9e9185796d6054483b2f23170a0000000007131f2c3844505d6975828e9aa6b2a5998d8174685c5043372b1f12060000030f1c2834404d5965717d8994a09d91867a70665f5b595b6069737e8995a19b9084786c6054483c3023170b08131d28333d48535d68737d88939e9d92887d72685d52483d32281d1208000000000000000000000000000000000e1b2834414e5b6774818e97968f8881797b8895a2978a7d7164574a3e3124170b000000000000000000030d18232e39444e59646f7a848f9a9c91877c71665b50463b30251a10050000000000000000000000000000000e1b2834414e5b6774818e97968f8881797b8895a2978a7d7164574a3e3124170b000000000000000000030d18232e39444e59646f7a848f9a9c91877c71665b50463b30251a10050000000000000000000000000004101d2936424e5a67737e8a96a1998e837a726b676565676a7078838e99a4998d8174685c4f4336291d1009141e29343f4a545f6a75808b95a0968b81766b60554a3f352a1f1409000000000000000000000000000000000007121d28333d48535d67717b858e97a0a8ada59c958d86807a75706c6966646261616061616364676a6d72767c82888f97a1adb8b4a79b8e837970665b51473c31261c12080000000000000000000000000a151f2a343f49535d667079828b939ba3abaaa39c958f8a85817d7a78767473737273737476787b7e82878c91979ea5ada8a199918980766d645a50463c31271c1106000000000000000000000000000000000000000000000000000007131f2b37424e5a66727d8995a1a5998d818a96a3a59a8e82766a5e53473b2f23170c0000000000000000000000000000000000000000000000000000000000000613202c3946525f6c7986929faca094877a6d6053473a2d20140700000000000000000000000000000005111c28343f4b56616d78848f9aa2978c81766c61574c42444e57616a737b838b9299a0a29c97938f8d8c8b8c8d8f92969b9c948b8278707d8996a2a3968a7d7164584f5b66727e8a96a29b8f83766a5e5145392c201307000007131f2c3844505c6874808c97a39b8f857a726b6766676b717a85909ba2978b8073685b4f43372b323d48525d68727d88929d9e93887d73685e53483d33281e1308000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111d28333f4a56616d78848f9ba6a4998d888888888888888d98a5b1ab9f948d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8174675a4d4134271a0e01000004101c2835414d5965727e8a96a3afa99d9185786c6054473b2f22160a00000000000c1825313d4a56626e7b8793a0acadacafa79a8e8275695d5044382c1f13070000000003101c2834414d5966727e8a97a3afa99d9084786c5f53473b2e22160a0000000c1824303c4854606c78838f9aa2978c8278706a6766676b727b858f9aa0958a7f73675c5044382c201307010c16212c36414c56616c76818c97a1998f84796f64594f44392f24190f040000000000000000000000000000000e1b2834414e5b67747e858c9399928b847c8895a2978a7d7164574a3e3124170b0000000000000000000007111c27323d48525d68737e89939e988d83786d62574c42372c21160b0100000000000000000000000000000e1b2834414e5b67747e858c9399928b847c8895a2978a7d7164574a3e3124170b0000000000000000000007111c27323d48525d68737e89939e988d83786d62574c42372c21160b01000000000000000000000000010d1a26323e4a56626e79848f9a9f958c847c7774727273767b828b959f9e93887c7064584c4033271b0e020d18222d38434e58636e79848f999d92877c72675c51463b31261b100500000000000000000000000000000000000b16212c36414b555f69737c858e979fa7aea69f98918b86817c797573716f6e6d6d6d6e6f7173767a7d82878d939aa1a9aeababa89c90867c72685e554b41372d241a10060000000000000000000000030e18232d37414b555e677079818a9199a0a7ada7a19b96918d8a87848281807f7f8080818385888b8e93979da3a9aba49e968f877f766d645b52483e342a1f150a000000000000000000000000000000000000000000000000000000020e1a26323e4955616d7884909ca89d928c909ba6a195897d71655a4e42362a1f130700000000000000000000000000000000000000000000000000000000000005131f2c3946525f6c7986929faca094877a6d6053473a2d201407000000000000000000000000000000000b17232e3a45505c67727d88939e9e93887d73685e544a41454f586169717981888e949a9fa39f9c9a989898999b9e9e99928a82796f6d7a86929fa0998d8074675b54606b77838e9aa3978b7e72665a4e4235291d1004000004101c2834404c58646f7b86919ca1968c847c77747374767c838c96a19b90857a6e63574b3f33272b36414b56616b76818b96a19a8f857a6f645a4f443a2f241a0f0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17222e3945505c67737e8a95a1aa9f9795959595959595979fa9b5b0a69e9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a8e8174675a4d4134271a0e0100000713202c3844515d6975828e9aa6b2a69a8d8175695c5044382b1f130600000000000915212e3a46525f6b7784909ca8b5b9afa3978b7e7266594d4135281c100300000000000c1825313d4a56626e7b8793a0acaca094887b6f63574b3e32261a0d0100000814202c3844505b67727d88939d9e948b827b77747374777d848d97a1998f84796e62574b3f33271b0f030005101a252f3a454f5a65707a85909aa0968b81766b60564b40362b20160b0000000000000000000000000000000d1a26333f4b57636c737a81888f96968e878a96a2978a7d7164574a3e3124170b00000000000000000000000b16202b36414c56616c77828c979f94897e74695e53483d33281d120700000000000000000000000000000d1a26333f4b57636c737a81888f96968e878a96a2978a7d7164574a3e3124170b00000000000000000000000b16202b36414c56616c77828c979f94897e74695e53483d33281d1207000000000000000000000000000a16222e3a46515d68737d88919a9e958e8883817f7e8082878c949d9e958c82766b6054483c3024180b0006111c26313c47525d67727d88939d998e83786d63584d42372d22170b000000000000000000000000000000000005101a252f39434d57616a737c858d959ca4aaaaa39d97928d898582807d7c7b7a7a7a7b7c7e8083868a8e93989ea5aba9a39e9fa4a2988e847a70675d53493f362c22180e05000000000000000000000006111b252f39434c555e676f7880878e959ba1a7aca7a29d999693918f8e8d8c8c8c8d8e8f9194979b9fa3a8aaa59f99938c857d756d645b524940362c22180e03000000000000000000000000000000000000000000000000000000000915212d3944505c6874808b97a3a49c999ba2a89c9084786d6155493d31261a0e0200000000000000000000000000000000000000000000000000000000000003131f2c3946525f6c7986929faca094877a6d6053473a2d2014070000000000000000000000000000000006121d28343f4a56616c77828d97a29a8f857a70665c524940464e575f676f767d83898e93979a9c9e9e9e9e9c9a97928d87807870676a7783909393939083776a5e5b66717c88949f9e92867a6e62564a3e3226190d010000000c1824303c47535e6a75808a949d9e968e888381808183878d959e9d93897e74695d52463b2f23242f3a444f5a646f7a858f9aa1968c81766b61564c41362b21160b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111d28343f4b56626d7884909ba6a9a3a2a2a2a2a2a2a2a3a9acacacaca9a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a69a8e8174675a4d4134271a0e0100000b1723303c4854606d7985919eaaaca3968a7e7165594d4034281b0f03000000000005121e2a36434f5b6774808c99a5acacaca093877b6e62564a3d3125190c0000000000000915212e3a46525f6b7784909ca9aca4988b7f73675a4e4236291d1105000004101c27333f4a56616c76818b959d9d948d878381808183888e969f9a91877d72675c51463a2f23170b00000009131e28333e49535e68737e89939e9d92877d72675d52473d32271d110600000000000000000000000000000b17232f3b46515a61686f767d848b929993959ca4978a7d7164574a3e3124170b0000000000000000000000040f1a242f3a45505a65707b86919b9b90857a6f655a4f44392f24180d01000000000000000000000000000b17232f3b46515a61686f767d848b929993959ca4978a7d7164574a3e3124170b0000000000000000000000040f1a242f3a45505a65707b86919b9b90857a6f655a4f44392f24180d0100000000000000000000000006121d2935404b56616c767f8890979e9994908d8c8c8d8f92989e9b948c837a70655a4f43382c20140800000a15202a35404b56616b76818c97a0958a7f74695f54493e33281c1004000000000000000000000000000000000008131d27313b454e58616a727b838b92999fa6aba8a29d9995918e8c8a898887878788898a8c8f92969a9fa4a9aaa59e9892939ba4a0968c83786f655b51483e342a20170d03000000000000000000000009131d27313a434c555d666e757c848a90969ba0a5a9a9a6a2a09d9c9a999999999a9b9c9ea0a3a7aba7a39e99948e88817a736b635b524940372e241a1006000000000000000000000000000000000000000000000000000000000005101c2834404b57636f7b87929ea7a7a6a7a7a3978b8074685c5044392d2115090000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d20140700000000000000000000000000000000010c17232e39444f5a65707b86909ba1968c82786e645b524940454d555d646b72787d82878a8d8f91929291908d8a87827c756e665e677480868686868686796d61616c77828e99a4998d82766a5e52463a2e22160a0000000008131f2b36424d58636e78828b939aa09993908d8d8d8f93989f9a938a81776d62574c41352a1e1d28333d48535d68737d88939e9d93887d72685d52483d32271b0f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c17232e3a45515c67737e8a96a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09a8e8174675a4d4134271a0e0100000e1b27333f4c5864707c8995a0a0a09f93877a6e6255493d3124180c000000000000020e1a27333f4b5864707c8995a0a0a0a09c9084776b5f53463a2e21150900000000000005121e2a36434f5b6874808c99a0a0a09b8f83766a5e5246392d2115080000000b17222e39444f5a656f79838b949b9e98938f8d8d8d9094999f9891887f756b61564b4035291e1206000000020c17222c37424c57616c77828c97a2998e84796e64594e44392e22170b000000000000000000000000000007131e2a353f4850575e656c737a81888f969da0a0978a7d7164574a3e3124170b00000000000000000000000008131e28333e49545e69747f8a959f978c81766b61564b4035291d11050000000000000000000000000007131e2a353f4850575e656c737a81888f969da0a0978a7d7164574a3e3124170b00000000000000000000000008131e28333e49545e69747f8a959f978c81766b61564b4035291d1105000000000000000000000000010d18242f3a454f5a646d767e868c92979a9c9a9898999b9c9995908a827a71685e53493e32271b0f040000030e19242f39444f5a656f7a8590999991867b70655a5044392d2014080000000000000000000000000000000000010b162029333d464f586069717980878e949aa0a5a9a9a5a19e9b99979594949494949597999b9ea2a6aaa9a49f99938d8689929ca69e948b81776d635a50463c32281f150b0100000000000000000000010b151f28313a434b545c636b72797f858a9094999ca0a3a5a8a9a8a7a6a6a6a6a6a7a9a9a7a5a29f9b97938e89837d7670686159514940372e251c1208000000000000000000000000000000000000000000000000000000000000000c17232f3b47525e6a76828e999a9a9a9a9a9a92877b6f63574b4034281c10040000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d201407000000000000000000000000000000000006121d28333e49545f69747e89939e9e948a80766d645b524941434b535a60676c72767a7e81838485858483817e7a76716b645c58647079797979797979776d6068737e89949f9f94887c7165594e42362a1e120600000000030e1a25313c47515c66707981898f95999c9c9a9a9a9c9c99958f8981786f655b51463b30241916212c36414c56616c76818c9799998f84796f64594f44382c1f1307000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121d29343f4b56626d7984909393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393938e8174675a4d4134271a0e010000111e2a37434f5b6874808c93939393938f83776a5e5246392d211508000000000000000b17232f3c4854606d79859293939393938d8074685b4f43372a1e1205000000000000020e1a27333f4c5864707d89939393939393867a6e6255493d3124180b00000006111d28333e49535d67717982898f95999c9c9a9a9a9c9b98938d877f766d63594f443a2f23180d010000000005101b25303b45505b65707b85909999958b80756b60554a3f33271b0e0200000000000000000000000000020d18232d363e454c535a61686f767d848b929393938a7d7164574a3e3124170b000000000000000000000000010c17222c37424d58636d78838e939393887d72675d5145392d20140700000000000000000000000000020d18232d363e454c535a61686f767d848b929393938a7d7164574a3e3124170b000000000000000000000000010c17222c37424d58636d78838e939393887d72675d5145392d2014070000000000000000000000000007121e29333e48525b646c747b81868a8e9092939392918f8d89847e7870685f564c42372c21160a0000000007121d28333d48535e69737e898c8c8c8c82776c6155493c2f23160a000000000000000000000000000000000000040e17212b343d464e575f676e757c83898f94999da1a5a8aaa7a5a3a2a1a0a0a0a1a2a4a5a8aaa7a4a19c98938e88827b818a949ea69d93897f756b62584e443a31271d13090000000000000000000000030c161f283139424a525960676e74797f84888c909496999b9d9e9fa0a0a0a0a09f9e9c9a9895928f8b87827d77726b655e574f473f372e251c130a000000000000000000000000000000000000000000000000000000000000000007131e2a36424e5965717d898d8d8d8d8d8d8d8d82766a5e52473b2f23170c000000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d2014070000000000000000000000000000000000000b17222d37424d58626d77818c96a09c92897f766d645b534b4341484f555b61666a6e717476777878777674726e6a655f5952545f686c6c6c6c6c6c6c6c6566707a858f9aa4998e82776b6054493d3125190d01000000000009141f2a35404a545e676f777e84898d8f9192939392908d89847e776f665d53493f34291e130f1a252f3a454f5a656f7a858c8c8c8c8b81766b6054483b2f2215090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c18232e3a45515c68737f86868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868174675a4d4134271a0e010000131f2c3946525f6b7784868686868686868073675b4e42362a1d1105000000000000000713202c3844515d697682868686868686867d7064584c3f33271b0e02000000000000000b1723303c4854616d7986868686868686867e7165594c3f3326190c000000000b16212c37414b555f6770777e84898d9091929392918f8c88827c756d645b51473d33281d120700000000000009141e29343e49545e69747e898c8c8c8c877c72675b4f43362a1d1004000000000000000000000000000007111b242c343a41484f565d646b72798086868686867d7164574a3e3124170b0000000000000000000000000005101b26313b46515c67717c868686868684796e6155483b2f221508000000000000000000000000000007111b242c343a41484f565d646b72798086868686867d7164574a3e3124170b0000000000000000000000000005101b26313b46515c67717c868686868684796e6155483b2f22150800000000000000000000000000010c17222c364049525a626970757a7e8184858686868583817d78736d665e564d443a30251b100500000000010b16212c37414c57626d778080808080807d7063574a3d3024170a00000000000000000000000000000000000000050f19222b343c454d555d646b71787d83888d9195989b9ea0a2a3a4a5a6a6a6a5a4a3a2a09e9b9894918c87827d777078828c96a0a59b91877d746a60564c43392f251b10050000000000000000000000040d161f27303840474e555c62686e73787c8184878a8c8e90919293949494939291908e8c8986837f7b76716c66605a534c453d352d251c130a010000000000000000000000000000000000000000000000000000000000000000020e1a25313d4955606c788181818181818181817d71655a4e42362a20170c020000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d20140700000000000000000000000000000000000005101b26313b46515b65707a848e97a19b91887f766d655d554e4740444a50555a5e626567696b6b6b6b6a6865625e5a544e484d565d5f5f5f5f5f5f5f5f646e78828c96a19d93887c71665a4f43382c201509000000000000030e19242e38424c555d656c73787d8083858686868583817d78736c655d544b41382d23180d08131e28333e48535e68737e8080808080807c6f6356493c3023160900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121d2934404b57626e7879797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797972665a4d4034271a0e010000131f2c3946525f6b767979797979797979797064574b3f32261a0e010000000000000004101c2935414d5a66727979797979797979776d6155483c3023170b00000000000000000714202c3845515d6a757979797979797979797165584c3f3326190c0000000005101b252f39434c555e656d73787d8183858686868583807c77716a635b52493f362b21160c01000000000000020d17222d37424d57626d7780808080808080776a5d5144372a1e110400000000000000000000000000000009121a222930373e454c535a61686f757979797979796f63574a3d3124170a000000000000000000000000000009141f2a353f4a55606b75797979797979786d6155483b2f22150800000000000000000000000000000009121a222930373e454c535a61686f757979797979796f63574a3d3124170a000000000000000000000000000009141f2a353f4a55606b75797979797979786d6155483b2f221508000000000000000000000000000005101a242e37404850585e656a6e72757778797979787674716d68625c544d443b32281e1409000000000000050f1a25303b45505b6670737373737373726b6155483c2f2316090000000000000000000000000000000000000000071019222a333b434b525960666c72777c8185898c8f9193959698989999999898969593918e8c8884807b77716b66707a848e97a1a3998f867c72685e554b41372d22160b000000000000000000000000040d151e262e353d444b51575d62676c7074787b7d80828485868687878786868483817f7c7a76736f6a65605b554f48423a332b231b130a01000000000000000000000000000000000000000000000000000000000000000000000915212c3844505c6771737373737373737373736c615549423b32291e13080000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d2014070000000000000000000000000000000000000009141f2a343f49535e68727c858f98a29a918880776f675f58514b443f44494e5256595b5d5e5e5e5e5d5b5956524e49433d444b515353535353545c646d76808a949ea1968c81766b6055493e32271b10040000000000000007121c26303a434b535b61676c70747678797979787674716d67615b534b42392f261b1106010c17222c37414c57616c72737373737373726b6054483b2f221509000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c18232f3a46515c666c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6960564a3e3225190c000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c675e53473b2f23160a0000000000000000000c1925313d4a5560696c6c6c6c6c6c6c6c6c665c5145382c201407000000000000000004101c2935414d59636b6c6c6c6c6c6c6c6c6c685f54493d3024170b000000000009131e27313a434c545b62676c71747678797979787673706b665f59514940372d241a0f05000000000000000006101b26303b46505b666f7373737373737370675b4f4336291d1004000000000000000000000000000000000910171e252c333a41484f565d646b6c6c6c6c6c6c675e53473b2e2216090000000000000000000000000000030d18232e39434e59636b6c6c6c6c6c6c6c665c5145392d201407000000000000000000000000000000000910171e252c333a41484f565d646b6c6c6c6c6c6c675e53473b2e2216090000000000000000000000000000030d18232e39434e59636b6c6c6c6c6c6c6c665c5145392d20140700000000000000000000000000000008121c252e363f464d53595e6266686a6c6c6c6c6b6a6764615c57514a433b322920160c020000000000000009131e29343f4a545e646666666666666662594f44382c2014070000000000000000000000000000000000000000000710182129313940484e555b61676c7075797c80828587888a8b8c8c8c8c8c8b8a888784827f7c7874706b66605e68727c868f99a0a0988e847a70665d53493e33271b0f02000000000000000000000000030c141c242b323940464c51575c6064686b6e717375777879797a7a7a797978767472706d6a66635e5a554f4a443d3730292119110901000000000000000000000000000000000000000000000000000000000000000000000004101c28333f4b555f6567676767676767676766625a57534d443a3025190d0100000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d20140700000000000000000000000000000000000000030d18232d37424c56606a737d869099a19a92898179716a635c564f4a443f4246494c4e5051515151504f4c4a46423d38323a404446464950575e666e768089929ca3998f857a6f645a4e43382d21160a0000000000000000000a141e283139414950565c6064676a6b6c6c6c6b6a6864615c565049413930271e140a000005101b25303a45505a62666666666666666661594f43382c1f13070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121e2935404a545b5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5d574e44392d2216090000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5c554c42372b1f13070000000000000000000915212d39444e575d5f5f5f5f5f5f5f5f5f5b544a3f34281c10040000000000000000000d1925313c4751595e5f5f5f5f5f5f5f5f5f5d564d43382c2014080000000000010c161f28313a424950565c6064676a6b6c6c6c6b6967635f5a544e473f372e251b12080000000000000000000009141f29343f49545d6466666666666666645e554a3f33271a0e020000000000000000000000000000000000060d131a21282f363d444b52595e5f5f5f5f5f5f5c554c41362b1f120600000000000000000000000000000007111c27323d4751595e5f5f5f5f5f5f5f5b544a4034291d11040000000000000000000000000000000000060d131a21282f363d444b52595e5f5f5f5f5f5f5c554c41362b1f120600000000000000000000000000000007111c27323d4751595e5f5f5f5f5f5f5f5b544a4034291d1104000000000000000000000000000000000a131c252d343b42484d5256595c5e5f5f5f5f5e5d5b5855504b453f38312920170e040000000000000000020d18222d38424c5358595959595959595650473e33281c100400000000000000000000000000000000000000000000060f171f272f363d444a50565b6064696c707376787a7c7d7e7e7f807f7e7e7d7c7a7875736f6c68645f5a5556606a737d8791939393938c82786f655b4f43372b1e120500000000000000000000000000020a121921282e353b40464b53595c5c5f626467686a6b6c6d6d6d6d6d6c6b6a686663615e5c5b575049443e38322c251e170f0800000000000000000000000000000000000000000000000000000000000000000000000000000b17232e39434d54595a5a5a5a5a5c626464646464635f564c4135291d110500000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d201407000000000000000000000000000000000000000006111b26303a444e58616b747d878f98a09b938b837c746e67615b55504b47433f404243444545454442403d3a3635373a3d41454a4f555b616870788089929ba49b91877d73685e53483d32271c1005000000000000000000020c161f2730373e454b5054585b5d5f5f5f5f5f5d5b5855504b453e372f271e150c0200000009141e29343e4850565959595959595959564f473d32271b0f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010d18232e38424a5052535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353514c453c32281d11050000000a16212c3740484f52535353535353535353504b433a30251a0e0300000000000000000005111c27323c454c515353535353535353524f4a42382e23180c000000000000000000000914202b353f474e52535353535353535353514c443b31271b1004000000000000040d161f2830383f454b5054585b5d5f5f5f5f5e5d5a57534f49433c352d251c13090000000000000000000000020d18222d38424b53585959595959595958544c43392e22160a00000000000000000000000000000000000000020910171e252c333a41484e52535353535353504b433a30251a0e02000000000000000000000000000000000b16202b363f484e5253535353535352504a42382e23180c00000000000000000000000000000000000000020910171e252c333a41484e52535353535353504b433a30251a0e02000000000000000000000000000000000b16202b363f484e5253535353535352504a42382e23180c0000000000000000000000000000000000010a131b222a31373c42464a4d4f515253535352504e4c4844403a342e261f170e050000000000000000000006111c26303a42484b4c4c4c4c4c4c4c4a453e352c21160b000000000000000000000000000000000000000000000000050d151d242b32393f444a4f54585c606467696b6d6f7071727273727271706f6d6b696663605c58534e494e58626b757f8686868686868681776c5f5346392d201306000000000000000000000000000000080f161d23292f3a46525c656969696969696969655f60606160606067696969696969696862584d42362d27211a140c0500000000000000000000000000000000000000000000000000000000000000000000000000000006121d27323b43494c4d4d50575f666d717171717170685e5246392d20130700000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d20140700000000000000000000000000000000000000000009141e28323c464f59626b747d868e979f9d958d867f78726c66615c57534f4c48464341403f3e3d3d3d3e3f40424446494d51565b60666c737a828a929ba49c92897f756b61574c41372c21160a0000000000000000000000040d151e252d343a3f44484c4e505253535352514f4c48443f3a332d251d150c0300000000020d17222c363e454a4c4c4c4c4c4c4c4c4a453e352b21160a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121c2630383f434646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464645413b332a21160b0000000005101a252e373e434646464646464646464644403931281e140900000000000000000000000b16202a333b4145464646464646464646433f382f261c110600000000000000000000030e19232d363d424546464646464646464644403a322920150a0000000000000000040d161e262d343a3f44484c4e515253535352504e4b47433e38322b231b130a0100000000000000000000000006111b26303941484b4c4c4c4c4c4c4c4c48423a31271c1106000000000000000000000000000000000000000000050c131a21282f363d424546464646464644403931281e13080000000000000000000000000000000000040f19242d363d424546464646464646433f3830261c1207000000000000000000000000000000000000000000050c131a21282f363d424546464646464644403931281e13080000000000000000000000000000000000040f19242d363d424546464646464646433f3830261c1207000000000000000000000000000000000000010911181f262b31363a3d404344454646464544423f3c38342f29231c150d050000000000000000000000000a141e2830373c3f4040404040403f3e3a342c231a100500000000000000000000000000000000000000000000000000030b121a20272d33393e43484c5054575a5d5f616264656565666565656462615f5c5a5754504c47433e465059636d767979797979797979766b5f5346392d20130600000000000000000000000000000000040b121824313e4a57636e75757575757575756f64585354535c687275757575757575736a5e5245382c1f16100902000000000000000000000000000000000000000000000000000000000000000000000000000000030a1119202931383d454c535a626970787d7d7d7d7d7a6e6154473b2e21140800000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d201407000000000000000000000000000000000000000000020c16202a343d475059626b747c858d959c9f98918a847d77726d68635f5b585552504e4c4b4a4a4a4a4a4b4c4e505356595d61666b71777e858c949ca49b938a80776d63594f453a30251a0f04000000000000000000000000030c141b22282e33383c3f4244454646464544423f3c38342e28221b130b0300000000000006101a242c343a3e404040404040403f3e39332c23190f04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b151e262d3337393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393835302921180f04000000000009131c252c32373939393939393939393938342f281f160c020000000000000000000000040e18212930353839393939393939393937332d261d140a00000000000000000000000007111b242b32363939393939393939393938352f2920170e03000000000000000000040c141b22292e34383c3f4244454646464544413f3b37322d27201911090100000000000000000000000000000a141e2730363c3f404040404040403f3c3730281f150b000000000000000000000000000000000000000000000001080f161d242b32363939393939393938342e271f160c0200000000000000000000000000000000000008121b242b3236393939393939393937332d261e140b000000000000000000000000000000000000000000000001080f161d242b32363939393939393938342e271f160c0200000000000000000000000000000000000008121b242b3236393939393939393937332d261e140b000000000000000000000000000000000000000000060d141a20252a2e313436383939393938373533302c28231e18110a0300000000000000000000000000030c161e252b303233333333333333312e29221a110800000000000000000000000000000000000000000000000000000001080f161c22282e33383c4044484b4e50525456575859595959585857565452504d4a4744403c37343e47515b646b6c6c6c6c6c6c6c6c6b645a4f43372b1e12050000000000000000000000000000000000000b1825323e4b5865717e828282828282807366594d47515d6a7782828282828282796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000000000000060d141c232a323940484f565e656c747b828a8a8a8a857b6e6154483b2e21150800000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d20140700000000000000000000000000000000000000000000040e18222b353e475059626a737b838b9299a09c958f89837d78746f6b6764615f5c5b5958575756575758595b5d5f6265696d72777c82898f969ea29a928981776e655b51473d33291e13090000000000000000000000000000020910171d23282c303335373839393939373633302c28231d17100901000000000000000008121a22292e313333333333333333312e28211a11070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c141c22272b2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c29241f170f06000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2b28231d160d0400000000000000000000000000060f171e24292c2c2c2c2c2c2c2c2c2c2b27221c140b020000000000000000000000000009121a20262a2c2c2c2c2c2c2c2c2c2c2b29241e170e050000000000000000000000020a11171d23282c3033353739393939383735322f2b26211b150e0700000000000000000000000000000000020c151e252b30323333333333333332302c261e160d0300000000000000000000000000000000000000000000000000050c131a20262a2c2c2c2c2c2c2c2b28231d150d04000000000000000000000000000000000000000009121a21262a2c2c2c2c2c2c2c2c2b27221c140c0200000000000000000000000000000000000000000000000000050c131a20262a2c2c2c2c2c2c2c2b28231d150d04000000000000000000000000000000000000000009121a21262a2c2c2c2c2c2c2c2c2b27221c140c020000000000000000000000000000000000000000000003090f14191e212527292b2c2c2c2c2c2a292623201c17120d0600000000000000000000000000000000040c141a1f23262626262626262625221d171008000000000000000000000000000000000000000000000000000000000000040b11171d22272c3034383b3e41444648494a4b4c4c4c4c4c4b4a49474643413e3b38342f2b2c353f49525a5f5f5f5f5f5f5f5f5f5f5a52493e33271b0f020000000000000000000000000000000000000b1825323e4b5865717e8b8f8f8f8f8d807366594d44515d6a77848f8f8f8f8f86796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000000000000910181f262e353c434b525961686f777e858d94978f867c736a5f52463a2d20140700000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca094877a6d6053473a2d21140b0b09060200000000000000000000000000000000000000061019232c353e4750586169717880888f959ca09a948e8984807b7774716e6b696766656463636364656667696c6e7275797e83888e949aa19f97908880776e655c53493f362b21170c0200000000000000000000000000000000060c12171c202326292a2c2c2c2c2c2b292724201c17120c0600000000000000000000000810171d2225262626262626262625221d17100800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a11171b1e202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201f1d19130d060000000000000000010910161a1e1f2020202020202020201f1c18120b04000000000000000000000000000000050d13191c1f2020202020202020201e1b17110a02000000000000000000000000000000080f151a1d1f2020202020202020201f1c18130c050000000000000000000000000000060c12171c202326292b2c2c2c2c2c2a2826231f1b16100a04000000000000000000000000000000000000030c131a1f2326262626262626262624201b140c0400000000000000000000000000000000000000000000000000000001080f151a1d1f2020202020201f1c17120b0400000000000000000000000000000000000000000000080f151a1e1f202020202020201e1b17110a0200000000000000000000000000000000000000000000000000000001080f151a1d1f2020202020201f1c17120b0400000000000000000000000000000000000000000000080f151a1e1f202020202020201e1b17110a020000000000000000000000000000000000000000000000000004090d1215181b1d1e1f2020201f1e1c1a1714100c070100000000000000000000000000000000000002090f141719191919191919191816110c06000000000000000000000000000000000000000000000000000000000000000000060b11161b2024282c2f323537393b3c3d3e3f3f403f3f3e3d3c3b393734322f2b28241f242d3740494f525353535353535353524f4940372c21160a000000000000000000000000000000000000000b1825323e4b5865717e8b989c9c9a8d807366594d44515d6a7784919c9c9c9386796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000009121b222931383f474e555d646b727a81899097998f867d736a61584d42362a1e120500000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca194877a6d6154473b2e2118181816120e080100000000000000000000000000000000000007111a232c353e464f575f676e767d848b91979d9f9a95908c8784807d7a7876747371717070707171737476787b7e82858a8e94999fa19b948d867e766e655c534a41372e241a0f0500000000000000000000000000000000000001060b1014171a1c1e1f2020201f1e1c1a1714100b060100000000000000000000000000060c12161819191919191919191815110c0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060b0f121313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131312100d08020000000000000000000000050a0e111313131313131313131312100c0701000000000000000000000000000000000002080d1012131313131313131313120f0b0600000000000000000000000000000000000004090e111313131313131313131312100c07010000000000000000000000000000000001060b1014171a1c1e1f2020201f1e1c1916130f0a0500000000000000000000000000000000000000000002090f131719191919191919191917140f090200000000000000000000000000000000000000000000000000000000000004090e1113131313131313120f0c0700000000000000000000000000000000000000000000000000040a0e111313131313131313120f0b060000000000000000000000000000000000000000000000000000000000000004090e1113131313131313120f0c0700000000000000000000000000000000000000000000000000040a0e111313131313131313120f0b0600000000000000000000000000000000000000000000000000000000000105090c0e10121313131312110f0d0b0804000000000000000000000000000000000000000000000003070a0c0d0d0d0d0d0d0d0c090601000000000000000000000000000000000000000000000000000000000000000000000000050b0f14181c1f2326282b2c2e30313232323332323231302e2c2a2825221f1b17131b252e373e4346464646464646464646433e372e251b1005000000000000000000000000000000000000000b1825323e4b5865717e8b98a5a69a8d807366594d44515d6a7784919ea9a09386796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000000007121b242c343b424a515860676e767d848c939a9990877d746b61584f463c31261a0e0200000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca195887b6e6255483c2f25252524221e19130b0300000000000000000000000000000000000008111a232c343d454d555c646b727980868c92979da19c9894908c8a878482817f7e7d7d7d7d7d7e7f818385878a8e92969a9fa19c969089827b746c645c534a41382f251c12080000000000000000000000000000000000000000000004070b0d0f11121313131211100e0b080400000000000000000000000000000000000106090c0d0d0d0d0d0d0d0d0b0905000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004070b0d10111213131312110f0d0a07030000000000000000000000000000000000000000000000000003070a0c0d0d0d0d0d0d0d0c0b08030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003080c101316191c1e2022232425262626262625242321201e1b1916130f0b09131c252c32373939393939393939393937322c251c130900000000000000000000000000000000000000000b1825323e4b5865717e8b98a5a69a8d807366594d44515d6a7784919eaaa09386796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000020e19232d363e464d545c636a717980878f969d9990877d746b62594f463d342a1f14090000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca396897d7064574b3e32323232312f2a241d150c0200000000000000000000000000000000000008111a222b333b434b525961676e747b81868c91969a9fa09c999693918f8d8c8b8a8a8a8a8a8b8c8d8f9194979a9ea29f9a95908a857e777169625a524a41382f261d130a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001040608090a0b0b0c0c0c0b0a09080604020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306080b0d0f101112131313131212100f0d0b0907040000000000000000000000000000000000000000000000000000000000000000000000000000000104070808080808080808080806040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002070b0e101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100e0b0702000000000000000000000000000000000000000000000005080b0c0c0c0c0c0c0c0c0c0c0b090501000000000000000000000005080b0c0c0c0c0c0c0c0c0c0c0b09050100000000000000000000000000000000000000000000000000040708080808080808080808070400000000000000000000000000000000000000000000000000030608080808080808080808080807050100000000000000000000000000000000000000000000000000000000000000000003070a0d0f11131516171819191919191817161513110f0c0a060300010a131b21272a2c2c2c2c2c2c2c2c2c2c2a27211b130a0100000000000000000000000000000000000000000b1825323e4b5865717e8b98a0a09a8d807366594d44515d6a7784919ea0a09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000007131f2a353f4850575f666d747c838b9299a09a90877e756b625950473d342b22180e030000000000000000000000000000000000000000000000000000000000000000121f2c3845525f6b7885929eaba5988c7f73665a4e433f3e3e3e3e3b362f271e1409000000000000000000000000000000000000000810192129313940484f565d63696f757b80858a8e93969a9da0a09e9c9a9998979796969798999a9c9ea0a19e9a97938e8a857f79736d665f58504840382f261d140b0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001040608090a0b0b0c0c0c0b0a0908060402000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000105080b0e101214161718181919181817161513110f0c090602000000000000000000000000000000000000000000000000000000000000000000000000000000000004080c0f1215171a1b1d1e1f1f20201f1f1e1d1c1a181613100d09050100000000000000000000000000000000000000000000000000000000000000000001070c11131515151515151515151513100b060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306080a0c0d0e0f0f0f0f0f0e0d0c0a080502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060d13171b1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1b17130d060000000000000000000000000000000000000000050b111517181919191919191919191815110c060000000000000000050c111517181919191919191919181815110c0600000000000000000000000000000000000000000000060c10131515151515151515151513100c06000000000000000000000000000000000000000000040a0f1214151515151515151515151514110d08020000000000000000000000000000000000000000000000000000000000000000000000020507080a0b0c0c0c0d0c0c0b0b0a08060502000000000000010910161b1e1f20202020202020201f1e1b161009010000000000000000000000000000000000000000000b1825323e4b5865717e8b939393938d807366594d44515d6a7784919393939386796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000000b1824303c47515a626970787f868e959ca39a91887e756c625950473e352b22191006000000000000000000000000000000000000000000000000000000000000000000111e2b3744515d6a7783909da9a79b8f83776b5f554e4c4b4b4b4a47413930261b100400000000000000000000000000000000000000070f171f272e363d444b52585e646a6f74797e82868a8e919496989a9c9d9e9fa0a0a09f9e9d9c9b999794918e8b87827e79736e68625b544d463e362e261d140b020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000105080b0e101214161718181919181817161513110f0c0906020000000000000000000000000000000000000000000000000000000000000000000000000000000004090d1114181a1d1f212224242525252525242321201d1b1815120e0a0601000000000000000000000000000000000000000000000000000000000000000000000001060b1014181b1f212426282a2b2c2c2c2c2c2c2b2a282725221f1c1915110d0803000000000000000000000000000000000000000000000000000000000000030b12181d20222222222222222222211f1c17110a010000000000000000000000000000000000000000000000000000000000000000000000000000000206090d10121517191a1b1c1c1c1c1c1b1a181614120f0c080501000000000000000000000000000000000000000000000000000000000000000000000000000000000000000810181e23272929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292927231e181008000000000000000000000000000000000000070f161c21242525252525252525252524221d1811090000000000000810171d21242525252525252525252524211d17100900000000000000000000000000000000000000020a11181c2021222222222222222221201c18110a02000000000000000000000000000000000000070f151b1f212222222222222222222222201e19130d0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0e1113131313131313131313110e0a0500000000000000000000000000000000000000000000000b1825323e4b5865717e868686868686807366594d44515d6a7784868686868686796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000000e1a2733404c58636c747b828a91989fa09a91887e756c635a50473e352c2319100700000000000000000000000000000000000000000000000000000000000000000000101d2936424f5c6875818e9aa7ab9f93877c71675f5a5858585857524b42372c2115090000000000000000000000000000000000000000050d151d242b333940474d53595e64696d72767a7e8184878a8c8e8f909292939393929291908e8c8a8885827e7a76726d68625d57504a433b342c241c140b02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004090d1114181a1d1f212224242525252525242321201d1b1815120e0a06010000000000000000000000000000000000000000000000000000000000000000000000060b1015191d212427292c2e2f30313232323231312f2e2c2a2825221e1a16120d08020000000000000000000000000000000000000000000000000000000000000001070c12171c2024282b2e313335363738393939393838363533312f2c2925211d18140e0903000000000000000000000000000000000000000000000000000000030d151d24292d2e2e2e2e2e2e2e2e2e2e2c28221b130b0100000000000000000000000000000000000000000000000000000000000000000000000005090e1216191c1f2123252728292929292828262523211e1b1815110d08040000000000000000000000000000000000000000000000000000000000000000000000000000000007111a22292f3336363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636332f29221a11070000000000000000000000000000000007101921282d3032323232323232323232312e29221b12090000000008111a22282d3132323232323232323232312e29221b12090000000000000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2c28231c140b020000000000000000000000000000000008111920262b2e2e2e2e2e2e2e2e2e2e2e2e2d2a251e170e0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b57647079797979797979797165594c44505d697579797979797979766b5f5246392c1f13060000000000000000000000000000000000000000000000000000000000000000000000000f1c2835424f5b68747e858d939393939392887f766c635a51483e352c231a100700000000000000000000000000000000000000000000000000000000000000000000000e1b2734404d5966727e8b97a3afa4998d8379706a6765656565635d53493d3226190d000000000000000000000000000000000000000000030b121a21282f353c42484d53585d62666a6e7275787b7d7f81828485868686868685848381807d7b7875726e6a66615c57514b453f38312a221a120a0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060b1015191d212427292c2e2f30313232323231312f2e2c2a2825221e1a16120d080200000000000000000000000000000000000000000000000000000000000000050c11171c2125292d303336383a3c3d3e3e3f3f3e3e3d3c3b393734312e2a27221e19130e080200000000000000000000000000000000000000000000000000000000050c12181d23272c3034373a3d3f414344454646464645444342403e3b3835312d29241f1a140e0801000000000000000000000000000000000000000000000000010b151f272f35393b3b3b3b3b3b3b3b3b3b38332d251d130900000000000000000000000000000000000000000000000000000000000000000001060c11151a1e2225282b2e3032333535363636353433312f2d2b2824211d19140f0a0500000000000000000000000000000000000000000000000000000000000000000000000000030e19232c343b4042434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434342403b342c23190e030000000000000000000000000000040f19232b33393d3f3f3f3f3f3f3f3f3f3f3d3a342d241b1106000005101a232c33393d3f3f3f3f3f3f3f3f3f3f3d3a342c241b1006000000000000000000000000000000000a141d262e34383b3b3b3b3b3b3b3b3b3b38342e261d140a00000000000000000000000000000007101a232b32373a3b3b3b3b3b3b3b3b3b3b3b3936302920170d03000000000000000004070808080808080808080807050200000000000000000000000000000000000000000000000000000000000000000001040708080808080808080808070400000000000000000000000000000000000000000000000000000000000a16232f3c48535e686c6c6c6c6c6c6c6c68605549414d58636a6c6c6c6c6c6c6c6b645a4f43372a1e11050000000000000000000000000000000000000000000000000000000000000000000000000f1c2835424f5b687582868686868686868680766d645b51483f362c231a11080000000000000000000000000000000000000000000000000000000000000000000000000c1825313d4a56626e7b87939eaaaa9f958b827b7673727171716f655a4e4235281c0f0000000000000000000000000000000000000000000001080f161d242a30363c42474c51565a5e6265696b6e70727476777879797979797877767573716f6c6966625e5a56514b46403a342d261f18100800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050c11171c2125292d303336383a3c3d3e3e3f3f3e3e3d3c3b393734312e2a27221e19130e0802000000000000000000000000000000000000000000000000000000030a11171d22282d3135393d40424547484a4b4b4c4c4b4b4a49474543413e3a37332e29241f19130c0600000000000000000000000000000000000000000000000000020910171d23292e33383c404447494c4e505152525353525251504e4c4a4845413d3935302b251f19130c05000000000000000000000000000000000000000000000007121d273139404548484848484848484847443f372f251b100400000000000000000000000000000000000000000000000000000000000000060c12171c21262a2e3235383a3d3f4041424242424241403e3c3a3734312d2925201b16100b0500000000000000000000000000000000000000000000000000000000000000000000000914202a353e464c4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4c463e352a20140900000000000000000000000000000a16212b353d44494b4c4c4c4c4c4c4c4c4c4a453f362d23180c01000b16212c353e45494b4c4c4c4c4c4c4c4c4b4a453e362c22170c01000000000000000000000000000006111c262f383f4548484848484848484848453f382f261c110600000000000000000000000000050f19222c353d4347484848484848484848484846413b32291f1409000000000000060c10131515151515151515151514110e0802000000000000000000000000000000000000000000000000000000000001070d11141515151515151515151513100c0700000000000000000000000000000000000000000000000000000007131f2b37424d565c5f5f5f5f5f5f5f5f5d574e433c4751595e5f5f5f5f5f5f5f5f5a52483e32261a0e020000000000000000000000000000000000000000000000000000000000000000000000000f1b2835424e5b6773797979797979797979766d645b52493f362d241a1108000000000000000000000000000000000000000000000000000000000000000000000000000915222e3a46525e6a76828d98a3ada79d948d8783807e7e7e7e76695d5043362a1d10000000000000000000000000000000000000000000000000050b12191f252b31363c40454a4e5256595c5f62646668696a6b6c6c6c6c6c6b6b6968666462605d5956524e4a45403a352f29221c150d06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a11171d22282d3135393d40424547484a4b4b4c4c4b4b4a49474543413e3a37332e29241f19130c0600000000000000000000000000000000000000000000000000060d151b22282e33383d4145494c4f5153555657585858585757555452504d4a47433f3a35302a241e1710090200000000000000000000000000000000000000000000040c131b22282e343a3f44484c505356585a5c5e5f5f5f5f5f5f5e5d5b595754514d4a45413c36312b241d160f07000000000000000000000000000000000000000000000c18232f39434b5154555555555555555554504941372c21150a0000000000000000000000000000000000000000000000000000000000040b11171d23282d32363a3e414447494b4d4e4f4f4f4f4f4e4c4b494643403d3935302c27211c161009030000000000000000000000000000000000000000000000000000000000000000000d1925313c4650575c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5750463c3125190d0000000000000000000000000004101b27323d474f55585858585858585858585650483f34291d120604101c28333d474f56585858585858585858585650483e34291d110500000000000000000000000000000b17222d38424a5154555555555555555554514a42382d22170b000000000000000000000000030d17212b343e474e535555555555555555555555524c443b31261a0e03000000020a11171c2021222222222222222222201e19140d05000000000000000000000000000000000000000000000000000000030b12181d2022222222222222222221201c18120a0200000000000000000000000000000000000000000000000000030f1a26303b444b505353535353535353514c453c353f474e5253535353535353524f4840372c21160a000000000000000000000000000000000000000000000000000000000000000000000000000d1a26333f4b5761696c6c6c6c6c6c6c6c6c6b645b524940362d241b1208000000000000000000000000000000000000000000000000000000000000000000000000000006121e2a36424e5a65707c87919ba4aba69e98938f8d8b8b8b8376695d5043362a1d100000000000000000000000000000000000000000000000000001070e141a20252b3035393e4246494d50535557595b5c5e5e5f5f5f5f5f5f5e5d5b5a585653504d4a46423e39342f29241e17110a03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060d151b22282e33383d4145494c4f5153555657585858585757555452504d4a47433f3a35302a241e17100902000000000000000000000000000000000000000000000810181f262d33393f44494d5255595b5e6062636465656565646362605e5c5956534f4b46413b362f29221b140c040000000000000000000000000000000000000000060e161e252c333a40454b5054585c5f626567696a6b6c6c6c6c6b6a69686663605d5a56514c47423c362f2821191109010000000000000000000000000000000000000004101d2934404b555d616161616161616161605b53493d32261a0e01000000000000000000000000000000000000000000000000000001080f161c23282e34393e42464a4e51535658595b5b5c5c5c5b5a59575553504d4945413c37322d27211b140e070000000000000000000000000000000000000000000000000000000000000000111d2936424d58626869696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696862584d4236291d11000000000000000000000000000713202c38434e596165656565656565656565625a50453a2e2216090814212d39444f596165656565656565656565625a50453a2e21150900000000000000000000000000000f1b27333f4a545c616161616161616161615c544a3f33271b0f0300000000000000000000020b151f29333c4650595f61616161616161616161615e564d42372b1f13060000020b141c23282c2e2e2e2e2e2e2e2e2e2e2d2a251f170f0500000000000000000000000000000000000000000000000000030d151d24292d2e2e2e2e2e2e2e2e2e2e2c28231c140c020000000000000000000000000000000000000000000000000009141f29323a4044464646464646464645413a332d353d42454646464646464646433e372e251a1005000000000000000000000000000000000000000000000000000000000000000000000000000a17232f3a454f585e5f5f5f5f5f5f5f5f5f5f5a524940372e241b1209000000000000000000000000000000000000000000000000000000000000000000000000000000020e1a26313d49545f6a757f89929aa0a5a9a39f9b999898908376695d5043362a1d1000000000000000000000000000000000000000000000000000000003090f141a1f24292d32363a3d404346494b4d4e50515252535353525251504f4d4b494744413e3a36322d28231e18120c06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000810181f262d33393f44494d5255595b5e6062636465656565646362605e5c5956534f4b46413b362f29221b140c0400000000000000000000000000000000000000010a121a222a31383e454a5055595e6265686a6d6e70717172727171706f6d6b6966635f5b56524c47413a342d251e160e05000000000000000000000000000000000000060f18202830373e454b51565c6064686c6f7274757778797979797877767472706d6a66625d58534d47413a332b231b130a010000000000000000000000000000000000000713202c3945515c676d6e6e6e6e6e6e6e6e6d655a4e4236291d100400000000000000000000000000000000000000000000000000040c131a21272e343a3f44494e52565a5d60626466676869696968676664625f5c5955514d48433e38322c261f18110a03000000000000000000000000000000000000000000000000000000000000121f2c3945525e6a747676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676746a5e5245392c1f12000000000000000000000000000b17232f3c4854606b717272727272727272726c62564a3e3125190c0b1724303c4955616b727272727272727272726c62564a3e3125190c0000000000000000000000000000121e2b37434f5b666d6e6e6e6e6e6e6e6e6d665b4f43372b1e1205000000000000000000000a141d27313b454e58626b6e6e6e6e6e6e6e6e6e6e6e685e53473b2f221509000009141d262e34383b3b3b3b3b3b3b3b3b3b3a36302921170d030000000000000000000000000000000000000000000000010b151f272f35393b3b3b3b3b3b3b3b3b3b39342e261e140a00000000000000000000000000000000000000000000000000020d1720282f3438393939393939393938353029232b313639393939393939393937322c251c1309000000000000000000000000000000000000000000000000000000000000000000000000000006121e29333d464d51535353535353535353524f4940372e251c120900000000000000000000000000000000000000000000000000000000000000000000000000000000000915212c37434e58636d7680888f95999c9e9fa0a0a09d908376695d5043362a1d10000000000000000000000000000000000000000000000000000000000003090e13181d21262a2d3134373a3c3e4042434445464646464645444342403f3c3a3734312e2a26211d18120d0701000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a121a222a31383e454a5055595e6265686a6d6e70717172727171706f6d6b6966635f5b56524c47413a342d251e160e050000000000000000000000000000000000010a131c242c343b434950565b61656a6e717477797b7c7d7e7e7e7e7e7d7b7a7875726f6b67625d58524c453e37302820170e0500000000000000000000000000000000060f18212a323a41494f565c62676c7175787b7e8182848586868686858483817e7c7976726e69645e58524b443d352d251c130a0100000000000000000000000000000000000814212e3b4754616d797b7b7b7b7b7b7b7b766a5e5145382b1e1205000000000000000000000000000000000000000000000000070e161d252c32393f454b50555a5e6266696c6f71737475757575757472706e6c6965615d59544f49443e37312a231c140d05000000000000000000000000000000000000000000000000000000000013202c3946535f6c798383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383796c5f5346392c2013000000000000000000000000020e1a27333f4b5864707c7e7e7e7e7e7e7e7e7e72665a4d4135281c100e1a2733404c5865717d7e7e7e7e7e7e7e7e7e72665a4d4135291c10040000000000000000000000000013202c3946525f6c777b7b7b7b7b7b7b7b776c5f5246392c20130600000000000000000008121c252f39434d57606a747b7b7b7b7b7b7b7b7b7b7a6f63564a3d3024170a0005101b262f383f454748484848484848484846413b33291f1409000000000000000000000000000000000000000000000007121d27313940454848484848484848484845403830261c110600000000000000000000000000000000000000000000000000050e161d23282b2c2c2c2c2c2c2c2c2b29241e1920262a2c2c2c2c2c2c2c2c2c2a26211a130a010000000000000000000000000000000000000000000000000000000000000000000000000000010c17212b343c414546464646464646464646433e372e251c130a00000000000000000000000000000000000000000000000000000000000000000000000000000000000004101b26313c47515b646d767d84898d90929393939393908376695d5043362a1d100000000000000000000000000000000000000000000000000000000000000003080c1115191d2124282a2d2f3233353637383939393939383837353432302e2b2825211e1a15110c070100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c242c343b434950565b61656a6e717477797b7c7d7e7e7e7e7e7d7b7a7875726f6b67625d58524c453e37302820170e05000000000000000000000000000000000a131c252e363e464d545b61676c71767a7d81848688898a8b8c8c8b8a8a888684827e7b77736e69635d575049413a322920170e050000000000000000000000000000050f18212a333c444c535a61676d73787c8185888b8d8f90929293939292918f8d8b8986827e7a756f6a635d564f473f372e251c130a00000000000000000000000000000000000815212e3b4854616e7b8888888888888885786b5e5145382b1e1205000000000000000000000000000000000000000000000008111820282f363d444a50565c61666a6e7276797b7e80818282828282817f7d7b7875716d6965605a554f49423c352e261f170f060000000000000000000000000000000000000000000000000000000013202c3946535f6c798690909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909086796c5f5346392c201300000000000000000000000005111e2a36434f5b6774808c8c8c8c8c8c8c8c8276695d5044382b1f13111d2a36434f5b6874818c8c8c8c8c8c8c8c8276695d5145382c2014070000000000000000000000000013202c3946535f6c798688888888888886796c5f5346392c201306000000000000000006101a242e37414b555f69727c86888888888888888882786e6256493d3023170a000a16222d37414a5054555555555555555555524c453b31261b0f03000000000000000000000000000000000000000000010d18242f39434b5154555555555555555554514a42382d22170b0000000000000000000000000000000000000000000000000000040c12181c1f20202020202020201f1c18130f151a1d1f202020202020201f1e1a1610090100000000000000000000000000000000000000000000000000000000000000000000000000000000051019222a3035383939393939393939393937322c251c130a01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a15202a353f49525b646c72787d8183858686868686868376695d5043362a1d100000000000000000000000000000000000000000000000000000000000000000000105090d1115181b1e21232527282a2b2c2c2c2c2c2c2c2b2a29272523211f1c1915120e0905000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a131c252e363e464d545b61676c71767a7d81848688898a8b8c8c8b8a8a888684827e7b77736e69635d575049413a322920170e05000000000000000000000000000008121c252e37404850585f666c72787d82868a8d90929496979898989897969593918e8b87837f7a746f68625b534c433b322920170d04000000000000000000000000030d17212a333c454e565d656c72797e84898d919497999b9d9e9fa0a09f9e9d9c9a9895928e8a85817b756e686159514940372e251c1208000000000000000000000000000000000815212e3b4854616e7b8894959595959285786b5e5145382b1e12050000000000000000000000000000000000000000000109121a222a323a41484f555c61676d72767b7e8285888a8c8e8f8f8f8f8e8d8c8a8785817d7975706b66605a544d463f3830292118100700000000000000000000000000000000000000000000000000000013202c3946535f6c7986939c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9386796c5f5346392c20130000000000000000000000000915212d3a46525f6b7784909898989898989285796c6054473b2f221614212d3946525e6b7784909898989898989285796d6154483c3023170b0000000000000000000000000013202c3946535f6c798693959595959386796c5f5346392c20130600000000000000050e18222c364049535d67717a848e9595959595958d847a70665d52463a2e211508000e1b27333e49535c616161616161616161615e574d42372b1f140800000000000000000000000000000000000000000006111d2935404b555d616161616161616161615c544a3f33281b0f03000000000000000000000000000000000000000000000000000001070c1012131313131313131312100c0804090e11131313131313131313110e0a05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000710181f25292c2c2c2c2c2c2c2c2c2c2c2a27211b130a010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030e19232d374049525a61676c717477787979797979797974685c4f4336291d100000000000000000000000000000000000000000000000000000000000000000000000000105080c0f121416181a1c1d1e1f1f2020201f1f1e1d1c1b191715120f0c090502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008121c252e37404850585f666c72787d82868a8d90929496979898989897969593918e8b87837f7a746f68625b534c433b322920170d0400000000000000000000000006101a242e374049525a626971777d84898e92969a9c9fa1a3a4a5a5a5a5a4a3a1a09d9a97948f8b85807a736c655d554d443b32291f160c0100000000000000000000000a151f29333c454e575f676f767d848a8f94999da1a3a6a8a9a7a6a6a6a6a7a9a9a7a4a19e9a96918c868079726b635b524940372e241a10060000000000000000000000000000000815212e3b4854616e7b8894a1a2a29e9285786b5e5145382b1e12050000000000000000000000000000000000000000010a131b242c343c444b535a60676d73787d82878b8e9295979997969696969698989694918d8a86817c77716b655f58514a423b332a22191108000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09386796c5f5346392c20130000000000000000000000000c1825313d4956626e7a87939fa5a5a5a5a195887c6f63574a3e3225191724303c4955616e7a87939fa5a5a5a5a195897d7064584c3f33271b0e0200000000000000000000000013202c3946535f6c798693a0a2a2a09386796c5f5346392c201306000000000000030d17202a343e48515b656f79838c96a0a2a2a2988f857b72685e544b40352a1e120500111e2a37434f5b656d6e6e6e6e6e6e6e6e6e695f54483c3024180c0000000000000000000000000000000000000000000a16222e3a46515d676e6e6e6e6e6e6e6e6e6d665b5044372b1f12050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060e14191d1f2020202020202020201f1e1b161009010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007111b252e3740484f565c6165686a6b6c6c6c6c6c6c6c6a62584c4034271b0e000000000000000000000000000000000000000000000000000000000000000000000000000000000205080a0c0e0f10111213131313131211110f0e0c0a080603000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006101a242e374049525a626971777d84898e92969a9c9fa1a3a4a5a5a5a5a4a3a1a09d9a97948f8b85807a736c655d554d443b32291f160c0100000000000000000000030e18222c364049525b646c747b82898f949a9ea2a6a9a7a5a3a2a1a0a0a1a2a3a5a7aaa7a3a09b96918b857e776f675f564d443b31271d13090000000000000000000007121c27313b454e576069717981888f959ba0a5a9a7a4a09e9c9b9a99999a9a9c9ea0a3a7aaa6a29d97918b847d756d645b524940362c22170d0200000000000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000000000000000000000000a131c252d363e464e565d646b72787e84898e93979793908e8c8a898989898a8b8c8f91949896928d88827d76706a635c544c453c342c231a11070000000000000000000000000000000000000000000000000013202c3946535f6c798693939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939386796c5f5346392c20130000000000000000000000030f1c2834414d5965727e8a97a3a39f9fa4a4988c7f73665a4e4135291c1a27333f4c5865717d8a96a3a49e9ea2a5998c8074685b4f43372a1e120600000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000010b151f29323c46505a636d77818b959ea8ada49a90877d736960564c42392f24190d0100121f2c3945525f6b777b7b7b7b7b7b7b7b7a7064584c4035291d110500000000000000000000000000000000000000030f1b27323e4a56626e797b7b7b7b7b7b7b7b786c5f5346392d20130600000000000000040708080808080808080807040100000000000000000000000004060808080808080808060300000000000000000000000003060808080808080808080806020000000000000000000000000000000000000000000000000000000000000000000003080d101213131313131313131313110e0a050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131c252e363e444a5055585b5d5f5f5f5f5f5f5f5f5e5950463b3024180c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030e18222c364049525b646c747b82898f949a9ea2a6a9a7a5a3a2a1a0a0a1a2a3a5a7aaa7a3a09b96918b857e776f675f564d443b31271d1309000000000000000000000a151f2a343e48525b646d767e868d949aa0a5aaa6a29e9b999795949494949596989b9ea1a5aaa7a29c969089817971685f564d43392f251b10050000000000000000030e19232e38434d576069727b838b939aa0a6aba5a09b9794918f8e8d8d8d8d8e8f9194979a9fa4a9a8a39c968f877f766d645b52483e34291f140900000000000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e12050000000000000000000000000000000000000009121c252e374048505860686f767d83898f9597938e8a8784817f7e7d7c7c7c7d7e808285888b8f9499938e88827b746d665e564e463e352c2319100600000000000000000000000000000000000000000000000013202c3946535f6c798686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686796c5f5346392c2013000000000000000000000007131f2c3844505d6975828e9aa39992939aa49b8f82766a5d5145382c1f1d2a36424f5b6874818d99a59a929198a29c9084776b5f53463a2e22150900000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000009131d27313a444e58626c758089939da7afa59b92887e746b61574e443a31271d12070000121f2c3845525e6a7682888888888888888175695d5145392d22160a0000000000000000000000000000000000000008141f2b37434f5b67737e8888888888888883776b5f5246392c2013060000000000060c101315151515151515151513110c07010000000000000000060c10131515151515151514120f0a040000000000000000040a0f1214151515151515151514120e090300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c242c33393f44484c4f515253535353535353524e473e342a1f13070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002040608090a0a0a0a09080705030100000000000000000000000000000000000000000000000000000002040607080808080806050300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a151f2a343e48525b646d767e868d949aa0a5aaa6a29e9b999795949494949596989b9ea1a5aaa7a29c969089817971685f564d43392f251b1005000000000000000006111c26313c46505a646d76808890979fa5aba6a09b96928f8c8a8888878787888a8c8e91959a9fa4aaa8a19a938b837a71685f554b41372c22170c010000000000000009141f2a35404a555f68727b858d959da5aba6a099948f8b8885838181808081818385878a8e93989ea4aba7a099918980766d645a50453b30261b1005000000000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000000000000000000007111b242e374049525a626a727981888e9597918c87827e7a77757371706f6f6f70717375787b7f83888d9298938d867f787068605850473e352b22180f050000000000000000000000000000000000000000000000131f2c3946525f6b767979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979766b5f5246392c1f1300000000000000000000000a16232f3b4754606c7985919e9f93878894a09e9285796d6054483b2f23202d3946525e6b7784909ca1958986919ea093877b6f62564a3e3125190d00000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000008111b252f39434c56606a747e87919ba5afa69d938980766c62594f453c32281f150b010000111d2a36424e5a66717d8995959595959185796d62564a3e32261a0e030000000000000000000000000000000000000c1824303c48545f6b77838f95959595958a7e72665a4f43372a1e1105000000020a11181c20212222222222222222201d18120b030000000000020a11171c2021222222222222211f1b160f08000000000000080f161b1f212222222222222222211e1a150e0700000000000000000000000000000000020608080808080808080808080808080808080808080808080808080706050402000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a121a21282e34383c404244454646464646464645423c352c22180d020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003070b0e111315161717171716151312100d0b080400000000000000000000000000000000000000000004080c0f111214141515151413110f0c09050000000000000000000000000000000000000000000000000000000000000000000000000000000006111c26313c46505a646d76808890979fa5aba6a09b96928f8c8a8888878787888a8c8e91959a9fa4aaa8a19a938b837a71685f554b41372c22170c01000000000000000c17222d38434d58626c768089919aa2a9a9a29b958f8a8682807d7c7b7a7a7b7b7d7f8285898e93999fa7aca59d958d847a71675d53493e33281d1207000000000000040f1a26313c47515c66707a848e979fa7aca39c958e89837f7b787674737373737476787b7e82878d939aa1a9aba39b928980766c61574d42372c21160b000000000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e12050000000000000000000000000000000000050f19232d364049525b646c747c848b9298918b85807b76726e6b68666463626263636567696c6f73777c81878d9398918a827a726a625950473e342a21170d0200000000000000000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b645a4f43372a1e1100000000000000000000010e1a26323f4b5764707c8895a19d908484919da195897c7064574b3e322623303c4955616e7a87939f9e9285828f9ba3978b7e72665a4d4135291c1004000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000006101a232d37414b555e68727c869099a3ada89e948b81776e645a50473d332a20160d030000000e1a26323d4955616d7884909ca2a2a2968a7e72665a4e43372b1f1307000000000000000000000000000000000005111d2935404c5864707c8894a0a2a29d9185796d61564a3e32261a0e020000020b141c23282c2e2e2e2e2e2e2e2e2e2d29241d150d03000000010b141c22282c2e2e2e2e2e2e2e2e2b27211a12090000000009121a21272b2e2e2e2e2e2e2e2e2e2d2b26201810070000000000000000000000000003090e121415151515151515151515151515151515151515151515151515141312100e0c0a0704010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000810171d23282c3033363839393939393939393936312b231a1106000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0f13171a1d202123232424232322201e1c1a1714100b05000000000000000000000000000000000001080f14181b1d1f202122222221201e1c1915110c0701000000000000000000000000000000000000000000000000000000000000000000000000000c17222d38434d58626c768089919aa2a9a9a29b958f8a8682807d7c7b7a7a7b7b7d7f8285898e93999fa7aca59d958d847a71675d53493e33281d120700000000000006111d28343f4a545f6a747e88919ba3aca89f979089837e7a7673716f6e6d6d6e6f707375797d82888e959ca4ada79f968d83796f655a50453a2f24180d0200000000000915202b37424d58636e78828c96a0a9aba29a928a837d77736f6c69686766666768696b6e72767b81888f979fa8ada49b91887e73695e53493d32271c10050000000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000000000000000020d17212b353f48525b646d757e868e96948d87807a746f6a66625f5c59585656555657585a5c5f63676b70767b82888f96948c847c736b625950463c33291e140a000000000000000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5a52483e32261a0e0000000000000000000005111d2a36424e5b6773808c98a49a8d81818e9aa5988c8073675a4e42352927333f4c5864717d8a96a29b8f82808c98a59a8e8276695d5145382c201407000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000040e18222c353f49535d67707a848e98a2aba9a0968c83796f655c52483e352b21180e04000000000915212d3944505c6874808b97a3aea69a8f83776b5f53473b3024180c00000000000000000000000000000000000a16212d3945515d6975818c98a4aea4988c8174695d5145392d22160a0000000a141d262e34383b3b3b3b3b3b3b3b3b39352f271f150b01000009131d262d34383b3b3b3b3b3b3b3a37322c241b1107000007111b242c32373a3b3b3b3b3b3b3b3b3a37312a22190f050000000000000000000000070e151a1e212222222222222222222222222222222222222222222222222121201e1d1b191614110d09050100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050c11171c202427292b2c2c2c2c2c2c2c2c2c2a25201911080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040b10161b1f23272a2c2e2f303030302f2e2d2b292624211c160f07000000000000000000000000000000020b131a2025282a2c2d2e2e2e2e2e2c2b2825211d18130d06000000000000000000000000000000000000000000000000000000000000000000000006111d28343f4a545f6a747e88919ba3aca89f979089837e7a7673716f6e6d6d6e6f707375797d82888e959ca4ada79f968d83796f655a50453a2f24180d0200000000000b17232e3945505b66717b86909aa3ada89e968d867e78726e6a66646261616161626466696d71767c838b929ba4ada89f958b81766c61564b40352a1e130700000000020e1a26313d48535f6a75808a949ea8ada39990888078726c67635f5d5b5a59595a5b5d5f62666b70767d858d959ea8ada39a8f857b70655a4f44382d21150a0000000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e1205000000000000000000000000000000000a141f29333d47515a646d767f889098918a837b756f69635e5a56524f4d4b4a4a4a4a4a4b4d5053575b60656a70767d848b93968e867d746b61584e443b30261c11070000000000000000000000000000000000000000000a16212c3740484f525353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353524f4840372c21160a000000000000000000000814212d3946525e6a77838f9ca4978b7e7e8b97a49b8f83766a5e5145382c2a36424f5b6774818d99a5988c807c8995a29e9286796d6154483c3023170b000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600030c16202a343e47515b656f78828c96a0aaaba1978e847a70675d534a40362d23190f06000000000005101c2834404b57636f7b87929eaaab9f93877b7064584c4034281c1105000000000000000000000000000000020e1a26323e4a56616d7985919da9ab9f93877b7064584c4035291d1105000006111c262f383f4548484848484848484845403931271d12070005101b252f383f444748484848484847433d362d23180d02020d18232d363d4347484848484848484847423c342b21170c0000000000000000000007101820262b2d2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2d2c2b2a282523201d1915110d080300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060b1014171a1c1e1f202020202020201f1d1a140e070000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080f161c22272b2f3336393b3c3d3d3d3d3c3b39383533302d282119100700000000000000000000000000000a141d252b313437383a3b3b3b3b3b393734312d29241e18110a030000000000000000000000000000000000000000000000000000000000000000000b17232e3945505b66717b86909aa3ada89e968d867e78726e6a66646261616161626466696d71767c838b929ba4ada89f958b81766c61564b40352a1e13070000000004101c28333f4a56616c77828d98a2aca99f968c847b746d67625d5a57565454545455575a5d61656b71788089929ba4aea79d93887e73685d51463a2f23180c0000000007131f2b36424e5965707b86919ca6b0a59b91877e766e67605b5753504e4d4d4d4d4e5053565a5f656b737b838c96a0aaaba1978c82766b6055493e32261a0e0300000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000000000000006111b26303b454f59636c767f8891988f878078716a635d58534e4a4d50535556575757575554514e4b4f54595f656b7279818991988f867d736a60564c42382e23180e03000000000000000000000000000000000000000005101a252e373e4346464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646433e372e251a1005000000000000000000000c1824303d4955626e7a86939fa195887c7b8894a19e9286796d6154483c2f2d3945525e6a7783909ca295897c7a86939fa295897d7064584c3f33271b0e020000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306010b151e28323c464f59636d77818a949ea8aca2998f857c72685e554b41382e241b1107000000000000000c17232f3b47525e6a76828d99a5b0a4988c8074685c5145392d21150900000000000000000000000000000007131f2b37424e5a66727e8a96a2ada69a8e83776b5f53473c3024180c0000000b17222d38424a51545555555555555554514b43392f23180c000a16212c37414a5054555555555555534f483f352a1f130707131e2a353f484f535555555555555555534e463d33281d11050000000000000000050f19222a31373a3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3a39383634322f2c2926221d19140f09040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004080b0e1011121313131313131313110d090300000000000000000000000000000000000000000000000000000000000000000000000000000000000000030b131a21272d32373c3f434547494a4a4a4a49484644423f3d39332b23190f0400000000000000000000000007121c262f363d4143454647484848474644413d39342f29231c150d050000000000000000000000000000000000000000000000000000000000000004101c28333f4a56616c77828d98a2aca99f968c847b746d67625d5a57565454545455575a5d61656b71788089929ba4aea79d93887e73685d51463a2f23180c000000000915212d3844505c67727e89949fa9ada2978d847a7169625b56514e4b4948474748494b4d51555a60676e768089929ca7afa59a8f84796e63574b4034281c10040000000b17232f3b47535e6a76818d98a3ada99e93897f756c645c554f4a474442414040404244464a4e545a6169717a848e98a3ada99e93887c71665a4e43372b1f130700000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e12050000000000000000000000000000010c17222d38424d57616b757e8891978e867d756e665f58524c4d52565a5d5f61636364646362605e5b57524d4e545a61686f777f8790988f867c72685e544a3f352a1f140900000000000000000000000000000000000000000009131c252c32373939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393937322c251c130900000000000000000000030f1b2834404c5965717d8a96a29e9286797885919da295897d7064574b3f32303c4855616e7a86939f9f9286797784909ca5998c8074685b4f43372a1e12060000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130609131d26303a444e58616b757f89939ca6aea49a90877d736a60564c43392f261c1209000000000000000007131e2a36424e5965717d8994a0aca89d9185796d6155493e32261a0e0200000000000000000000000000000c18232f3b47535f6b77838e9aa6ada1968a7e72665a4f43372b1f13080000000f1b27333f4a545c6161616161616161615d554b4034291d10040f1b27323e49535b61616161616161605951463b3024180c0b17232f3b4651596061616161616161615f584f44392d22150900000000000000000c17212b343c42474848484848484848484848484848484848484848484848484847464443413e3c3935322e2925201a150f0902000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d151d242c32383e43484c4f52545556575756555453514e4c49443d352b21160b0000000000000000000000020d19242e3841484d505253545555555452504d4945403a342d261f170f060000000000000000000000000000000000000000000000000000000000000915212d3844505c67727e89949fa9ada2978d847a7169625b56514e4b4948474748494b4d51555a60676e768089929ca7afa59a8f84796e63574b4034281c10040000000d1925313d4955616c78848f9aa5b0a69b90867b71685f57504a45413e3c3b3a3a3b3c3e4144494f555c656d76808b95a0abaca1968a7f73685c5045392d2115090000020f1b27333f4b57636f7b87929ea9aea3978c82776d635a524a443f3a37353433333435373a3e42484f575f68727c86919ca7afa4998e82766b5f53473b2f23170b00000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e1205000000000000000000000000000008131e29343f49545e69737d8791988e857c746b635c544e4c53585e6266696c6e6f707171706f6d6a67635e59534c4f565d656d757e8790988e847a70665b51463c31261b10040000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a26211a130a010000000000000000000006121f2b3744505c6875818d9aa69c8f837675818e9aa5988c8073675b4e4236333f4b5864717d8a96a29c8f837674818d99a69c9084776b5f53463a2e2215090000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201307111b252f38424c56606a737d87919ba5aea59c92887e756b61584e443b31271d140a000000000000000000020e1a25313d4955606c7884909ba7ada195897d72665a4e42362a1f13070404040404040404040404040404101c2834404c58636f7b87939faba89d9185796d61564a3e32261a0f03000000121e2b37434f5b666d6e6e6e6e6e6e6e6d675c5145392c201307131f2b37434f5a656d6e6e6e6e6e6e6b63584c4034281c100e1a2733404c57626b6e6e6e6e6e6e6e6e6a61564a3e3125180c0000000000000005111d28333d464e53555555555555555555555555555555555555555555555555545353514f4d4b4845423e3a35302b26201a140d06000000000000000000000000000000000000000000000000000000000205090b0e0f101010100f0d0b0905020000000105080a0c0d0d0d0c0a08050200000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d161f272f363d44494f54585b5e60626363636362615f5d5b58554f473d32271b10040000000000000000000006121e2a35404a53595c5e6061616161615f5d5956514c463f38312921180f0600000000000000000000000000000000000000000000000000000000000d1925313d4955616c78848f9aa5b0a69b90867b71685f57504a45413e3c3b3a3a3b3c3e4144494f555c656d76808b95a0abaca1968a7f73685c5045392d211509000004101d2935414d5965717d8995a0acaca0958a7e746960564d463f393532302e2e2e2e2f3234383d444b535b656e79838e99a4b0a79c9085796d6155493d3125190c000006121e2b37434f5c6874808c97a3afa99d92867b70655b51484039332e2b2927262627282a2e32373d454d56606a74808b96a1adaa9f93877b6f64574b3f33271b0e02000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000000000020e19242f3a45505b66707a858f998f867c736a6259524a50575e64696e7276787b7c7d7d7d7d7b7976736f6a645e57504b535b636c757e8791968c82786d63584d42372c21160a000000000000000000000000000000000000000000010910161a1e1f20202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201f1e1a1610090100000000000000000000000a16222e3b4753606c7885919da5998d8074727e8a97a39c8f83766a5e51453936424f5b6774808c99a5998c8073717d8a96a3a094877b6f62564a3e3125190d0000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130f19232d37414a545e68727c858f99a3ada79d938a80766c63594f463c32291f150b02000000000000000000000915212c3844505c67737f8b97a2aea69a8e82766a5f53473b2f231711111111111111111111111111111115212d3944505c6874808c98a4afa4988c8074695d5145392d21160a0000000013202c3946525f6c777b7b7b7b7b7b7b796d6154473b2e21140c1824303c48535f6b777b7b7b7b7b7b74685c5145392d21150f1c2835424e5b68747b7b7b7b7b7b7b7b7266594c4033261a0d000000000000000915222d39444f585f61616161616161616161616161616161616161616161616161605f5e5c5a5755514e4a46413c37312b251f18110a0200000000000000000000000000000000000000000000000004090e1215181a1c1d1d1d1c1b1a1815120e0a05080d111417191a1a1a181714120e0a0500000000000000000000000000000000000000000000000000000000000000000000000000000000030d161f28313941484f555b6064686b6d6f707070706f6e6c6a676561594f44382c201407000000000000000000000916222e3a46525c64696b6c6d6e6e6e6d6c6966615c57514a423b332a21180f0500000000000000000000000000000000000000000000000000000004101d2935414d5965717d8995a0acaca0958a7e746960564d463f393532302e2e2e2e2f3234383d444b535b656e79838e99a4b0a79c9085796d6155493d3125190c00000713202c3845515d6976828e9aa5b1a79b8f84786d62584e443c342e292523222121212325282d32394149535c67727d88939fabada195897d7165594d4135281c1003000915222e3a47535f6c7884909ca8b0a4988c8175695e54493f362e27221e1c1a1a1a1a1c1e21262c333b444e58636e7985909ca8b0a4988c8074685b4f43372a1e1105000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e12050000000000000000000000000008131f2a35414c57626d77828c9791877d736a6158504a525a62696f757a7e828587898a8a8a8a8886837f7b756f69615a5149515a626b757e8993948a7f74695f54493d32271c100500000000000000000000000000000000000000000000050a0e1113131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313110e0a05000000000000000000000000010d1926323e4a57636f7b8894a0a2968a7d716e7b8794a09f92867a6d6155483c3945525e6a7783909ca296897d706e7a87939fa3978b7e72665a4d4135291c100400000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201318212b353f49535c66707a848e97a1aba89e958b81776e645a51473d342a20170d03000000000000000000000004101c27333f4b57636e7a86929ea9ab9f93877b6f63574c4034281e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e25313d4955616d7985919ca8ab9f93877b7064584c4034291d11050000000013202c3946535f6c79868888888888887b6e6154483b2e2115111c2834404c5864707c888888888885796d6155493d3125190f1c2835424f5b687582888888888888807366594d4033261a0d000000000000000c1825313e4a56616a6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6d6c6a696664615e5a56524d48423d373029231b140c0400000000000000000000000000000000000000000002090f151a1e21242728292a2a29282624211e1a151014191d2123252626262523211e1b1610090100000000000000000000000000000000000000000000000000000000000000000000000000010b151f28313a434b525a60666b7074777a7b7d7d7d7d7b7a787674716b6054483c2f231609000000000000000000000b1824313e4a56636e7577797a7b7b7b7a7875726d68625b544d453c332a21170e0400000000000000000000000000000000000000000000000000000713202c3845515d6976828e9aa5b1a79b8f84786d62584e443c342e292523222121212325282d32394149535c67727d88939fabada195897d7165594d4135281c1003000a16232f3c4854616d7986929eaaaea2968a7e73675c51463c322a221d19161514141516191c21272f37414b55606b77828e9aa6b2a69a8e8275695d5144382c1f1306000b1824313d4a56626f7b8894a0acaca094887c7064584d42372d241c16120f0e0d0d0e0f12151b2129323c47525d6874808b97a4b0a89c9084776b5f52463a2d211408000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e1205000000000000000000000000020d1925303b47525d68737e899494897f756b62584f4a535c646c747a81868b8e9294969797979695928f8b86817a736c635b5248505a636d76818b9591867b70655a4f43382d21160a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101d2935424e5a66737f8b98a49f93877a6e6b7884909da296897d7064584b3f3c4855616d7a86939f9f92867a6d6b7784909ca79b8e8276695d5145382c20140700000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2016202a333d47515b646e78828c969fa9aaa0968c83796f665c52483f352b22180e05000000000000000000000000000b17232f3a46525e6975818d99a5afa3978c8074685c5044382d2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a36424e5a66717d8995a1ada69a8e83776b5f53473c3024180c000000000013202c3946535f6c79869395959594887b6e6154483b2e211515212d3945515d6874818c95959595897d71665a4e42362a1e121c2835424f5b6875828f959595958d807366594d4033261a0d000000000000000d1a2633404c5966727b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7a79777573706d6a66625d59534e48423b342d261e160e0600000000000000000000000000000000000000060d141a20252a2e313335363636363533312e2a26211c1f25292d303233333332302d2a27211b130a0100000000000000000000000000000000000000000000000000000000000000000000000009131d27313a434c555d646b71777c80848688898a8a8988878583817d7063574a3d3024170a000000000000000000000b1825323e4b5865717e8486878888888785827e79736d665e574e453c332920160c01000000000000000000000000000000000000000000000000000a16232f3c4854616d7986929eaaaea2968a7e73675c51463c322a221d19161514141516191c21272f37414b55606b77828e9aa6b2a69a8e8275695d5144382c1f1306000c1925323e4b5764707d8995a2aeab9f92867a6e62564b3f342a2018110d0a080707080a0c10161d252f39444f5a66727d8a96a2aeaa9e9285796d6054473b2e221509000d1a2733404c5965727e8b97a3b0a99d9084786c5f54483c31261b120b06030000000002050a1017202a35404c57636f7b8794a0acaca093877b6e6255493c3023170a000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000000007131e2a35414c58636e7a8590978c82776d63595048525c656e767e858c92979b9b98959493939496999b97928c857d756d645a5148515b656f79848e988d82766b6055493e32271b0f0300000000000000000000000000000000000001060a0c0d0d0d0d0d0d0d0c0a06010000000000000002070a0c0d0d0d0d0d0d0d0b0804000004080b0d0d0d0d0d0d0c0a0703000004080b0d0d0d0d0d0d0d0c0a060200000000000000000000000004070809090909090807050100000000000000000000000000000000000000000814202d3945515e6a76838f9ba79c9084776b6874818d99a5998c8074675b4f423f4b5864707d8996a29c8f83766a6874818d99a59e9286796d6154483c3023170b00000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201e28323c454f59636d76808a949ea8aba1988e847a71675d544a40362d23191006000000000000000000000000000006121e2a35414d5965717c8894a0aca89c9084786d6155493d373737373737373737373737373737373737373b47525e6a76828e9aa6ada1968a7e72665a4e43372b1f1307000000000013202c3946535f6c798693a0a2a194887b6e6154483b2e21151a26323d4955616d7985919da2a29a8e82766a5e52463a2e23171c2835424f5b6875828f9ca2a29a8d807366594d4033261a0d000000000000000d1a2633404d5966738088888888888888888888888888888888888888888888888786858482807d7a76726e69645f59534d463f38302820180f0600000000000000000000000000000000000710171f252c31363a3d40424343434341403d3a36322d272a3035393c3e4040403e3c3a37322c251c1309000000000000000000000000000000000000000000000000000000000000000000000006101b252f39434c565e676e767d83888c90939596979796959492908a7d7063574a3d3024170a000000000000000000000b1825323e4b5865717e8b939494959493918e8a857e78706860574e453b32281d1309000000000000000000000000000000000000000000000000000c1925323e4b5764707d8995a2aeab9f92867a6e62564b3f342a2018110d0a080707080a0c10161d252f39444f5a66727d8a96a2aeaa9e9285796d6054473b2e221509000e1b2734414d5a6673808c98a5b1a89b8f83766a5e52463a2e23180e060100000000000000040b131d27323e4955616d7986929eabada195887c6f63564a3d3124180b000f1c2835424e5b6774818d9aa6b3a69a8d8174685c4f43372b20140900000000000000000000050e19242f3b47535f6b7784909da9afa3968a7d7164584b3f3225190c000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e12050000000000000000000000000b17232f3b46525e6974808b9691867b70665b5147505a646e77808890979d99938f8b89878686888a8d91979d978f877f766c63594e49535d67727c879293887c71665a4f43372c2014080000000000000000000000000000000000060c1216191a1a1a1a1a1a1a1916120c060000000000070d1316191a1a1a1a1a1a191814100a0a101518191a1a1a1a1a1917130e080a101418191a1a1a1a1a1a1916120d07000000000000000000070c10141515151515151514110d08010000000000000000000000000000000000000b1724303c4855616d7a86929ea6998d81746865717d8a96a29c9083776a5e5245424e5b6774808c99a5988c80736764717d8a96a2a295897d7064584c3f33271b0e02000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2026303a444d57616b757e89929ca6aca3998f867c72685f554b42382e251b1107000000000000000000000000000000010d1925313c4854606c77838f9ba7ada195897d71655a4e4444444444444444444444444444444444444444444b57636f7b87929eaaa89d9185796d61564a3e32261a0e03000000000013202c3946535f6c798693a0aca194887b6e6154483b2e21151e2a36424e5a66727d8995a1adaa9e92877a6f63574b3f33271b1c2835424f5b6875828f9ca8a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d95959595959595959595959595959595959595959595949392908e8c8986827e7a75706a645e575049423a322a21180f06000000000000000000000000000000081119222930373d42464a4c4e4f50504f4e4c4a46423e3832353c4145494b4c4d4c4b4946433e372e251b1005000000000000000000000000000000000000000000000000000000000000000000010c17222c37414b555e68707981888e94989c9fa1a3a4a3a3a2a09e978a7d7063574a3d3024170a000000000000000000000b1825323e4b5865717e8b98a0a1a2a1a09e9a96908a827a726960574d44392f251a10050000000000000000000000000000000000000000000000000e1b2734414d5a6673808c98a5b1a89b8f83766a5e52463a2e23180e060100000000000000040b131d27323e4955616d7986929eabada195887c6f63564a3d3124180b00101c2936424f5c6875828e9ba7b2a5998c8073675a4e4235291d120600000000000000000000010b16212d3945515d6a76828f9ba8b0a4978b7e7265594c3f33261a0d00111d2a3743505d6976838f9ca8b1a4978b7e7265594c4033271b0f03000000000000000000000007131e2a37434f5c6874818d9aa7b2a5998c8073665a4d4034271a0e000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e1205000000000000000000000004101c2834404b57636e7a8691968a7f74695e54494d57626c768089929a9c958e88837e7c7a79797b7d81868c929a9991887e746a60564b4b55606b76818c978e82776b5f54483c3024180c000000000000000000000000000000000810181e22252626262626262625221e1810080000010a12191e23252626262626262624201b15151b212426262626262626231f1a13151b20242626262626262625221e181109000000000000020a12181d2022222222222222211d19130c0400000000000000000000000000000000020f1b2733404c5864717d8996a2a2968a7d7164616e7a87939f9f93867a6e61554845515e6a77838f9ca295897d7064616e7a86939fa5998d8174685b4f43372a1e1206000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c252e38424c565f69737d87919aa4aea49a91877d746a60564d433930261c130900000000000000000000000000000000000814202c38434f5b67737e8a96a2aea59a8e82766a5e52515151515151515151515151515151515151515151515c6873808b97a3afa4988c8074685d5145392d21160a00000000000013202c3946535f6c798693a0aca194887b6e6154483b2e2117232f3b47525e6a76828e9aa6b2afa3978b7f73675b4f43372c201c2835424f5b6875828f9ca8a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a1a1a09f9d9b9896928e8a86817b756f69625b544c443c332a21180f050000000000000000000000000007101a232b333b42484e5256595b5c5d5d5c5b5956524e49443d40474d5155585959595855534f4940372c21160a00000000000000000000000000000000000000000000000000000000000000000008131e29343e49535d67707a828b92999fa4a9aaa6a29f9d9c9c9c9d978a7d7063574a3d3024170a000000000000000000000b1825323e4b5865717e8b989c9c9d9fa2a6a6a19b948c847b72695f554b41372c22170c010000000000000000000000000000000000000000000000101c2936424f5c6875828e9ba7b2a5998c8073675a4e4235291d120600000000000000000000010b16212d3945515d6a76828f9ba8b0a4978b7e7265594c3f33261a0d00111e2b3744515d6a7783909da9b0a3978a7d7164584b3f3226190d01000000000000000000000005111d2935414e5a6773808c99a6b2a69a8d8174675a4e4134281b0e00121e2b3845515e6b7784919daaafa296897c7063564a3d3124180b000000000000000000000000020e1b2733404c5965727e8b98a5b1a79b8e8175685b4f4235281c0f000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000000814202c3844505c6874808b979084796e63584d48535e69747e88929b9c938b837c77726f6d6d6d6e71757a818890999a90877c72675d52474e5964707b869293887c7064594d4135291d1004000000000000000000000000000008121a22292e3233333333333333322e29221a1208000a131c232a2f3233333333333333302c261f1f272c31333333333333322f2b241d1f262c3033333333333333322f2a231b120900000000020b141c23292c2f2f2f2f2f2f2f2d2a241e160d0400000000000000000000000000000006121e2b37434f5c6874818d99a59f93877a6e615e6b7783909ca2968a7d7164584c4855616d7a86929f9f9286796d615e6a7783909ca89c9084776b5f53463a2e221509000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2d36404a545e68717b858f99a3aca69c92897f756b62584e443b31271e140a010000000000000000000000000000000000040f1b27333f4a56626e7a86919da9aa9e92877b6f635d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d606c7884909ca8ab9f93877b6f64584c4034291d110500000000000013202c3946535f6c798693a0aca194887b6e6154483b2e211c27333f4b57636f7b87939faaa8a8a79b9084786c6054483c30241c2835424f5b6875828f9ca8a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6aeaeaba5a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a4a4a6a8aaa8a5a29e9b96928c87817a746d655e564e453c332a21170e040000000000000000000000040e18222c353d454d53595e626568696969696765625e5a554f484a52585d616466666664625f5a52493e33271b0f0200000000000000000000000000000000000000000000000000000000000000030e19242f3a45505a656f79838c949ca4aaaba49e9a9692908f8f8f90918a7d7063574a3d3024170a000000000000000000000b1825323e4b5865717e8b908f8f9092969ba0a7a69e968e857b71675d53483e33281d12070000000000000000000000000000000000000000000000111e2b3744515d6a7783909da9b0a3978a7d7164584b3f3226190d01000000000000000000000005111d2935414e5a6773808c99a6b2a69a8d8174675a4e4134281b0e00121f2c3845525e6b7885919eabaea295887b6f6256493c3023170a000000000000000000000000000d1926323f4b5865717e8b97a4b0a89b8f8275685c4f4236291c1000121f2c3945525f6b7885929fabaea194887b6e6155483b2f221509000000000000000000000000000b1824313e4a5764707d8a96a3b0a99c8f8376695c5043362a1d10000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000000c1824303c4855616c788490968a7e73685c51464e5964707b86909a9d938a8178716b66636160606265696f767e87909a988e84796e63584d48535e6975818c988d8175695d5145392d2114080000000000000000000000000005101a242c343a3e404040404040403e3a342c241a1007111c252e353b3f4040404040403f3d3831292931383d4040404040403f3c362f262931383d3f4040404040403e3a352d241b11060000000a141d262e34393b3c3c3c3c3c3b39352f281f160c0100000000000000000000000000000915222e3a46535f6b7884909da99c9084776b5e5b6774808c99a5998d8174675b4f4b5864707d8996a29b8f83766a5e5b6774808c99a5a094877b6f63564a3e3125190d000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392f353f48525c667079838d97a1aba79d948a80766d635950463c32291f150c02000000000000000000000000000000000000000b16222e3a46515d6975818c98a4afa3978b80736a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a717d8995a0aca69a8e83776b5f53473b3024180c0000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e21202c3844505c6873808b97a3a09b9ba1a094887c7064584c4035291d2835424f5b6875828f9ca8a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b3aca29a9696969696969696969696969696969798999b9ea1a4a8aba7a29d98928c857e77706860574e453c332920160c02000000000000000000000b16202a343e474f575e656a6e72747676767574726f6b66605a52545c63696e71737373716e6b645a4f43372b1e12050000000000000000000000000000000000000000000000000000000000000008141f2a36414c57626c77818b959ea6aea8a099938e8986848282828385877d7063574a3d3024170a000000000000000000000b1825323e4b5865717e8483828284868a8f959ca4a8a0978d83796f655a4f453a2f24180d0200000000000000000000000000000000000000000000121f2c3845525e6b7885919eabaea295887b6f6256493c3023170a000000000000000000000000000d1926323f4b5865717e8b97a4b0a89b8f8275685c4f4236291c1000131f2c3946525f6c7986929facada194877a6e6154483b2e211508000000000000000000000000000a1724303d4a5663707c8996a2afa99c908376695d5043372a1d100013202c3946535f6c7986929facada094877a6d6054473a2e211407000000000000000000000000000916232f3c4956626f7c8895a2afaa9d9084776a5d5044372a1d11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000030f1b2834404c5965717d89959185796e62574b47535e6a76818c97a0968b81786f67605a5654535355595e646c757e88929d968b80756a5f53484d5864707b87939185796d6155493d3024180b000000000000000000000000000b17222c363e454a4d4d4d4d4d4d4d4a453e362c22170d18232e3740464b4d4d4d4d4d4d4c49433b32323b43494c4d4d4d4d4d4b4741382f323b43494c4d4d4d4d4d4d4b463f372d23180c010005111b262f383f454848484848484846413a31281e130800000000000000000000000000000d1925313e4a56636f7b8794a0a6998d8174685b5864707d8995a29c9083776b5e524e5b6773808c99a5988c8073675a5864707d8995a2a3978b7e72665a4d4135291c10040000000000000013202c3946535f6c798693a0acaca09386796c5f534841393d47515a646e78828c959fa9a89f958b82786e645b51473e342a21170d03000000000000000000000000000000000000000006121d2935414d5864707c88949faba89c9084787777777777777777777777777777777777777777777777777777828d99a5ada1958a7e72665a4e42372b1f13070000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e2125313d4854606c7884909ca1968f8f98a3998d8175695d5145392d212835424f5b6875828f9ca8a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b3a79b908a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8b8d8f9194989ca0a5aba9a39d979089827a726960574e453b32281e130900000000000000000006111c27323c465059616970767a7e8182838382817e7b76716b645d5d666e757a7d8080807d7b766b5f5346392d201306000000000000000000000000000000000000000000000000000000000002050e1925303c47525d68737e89939da7b0a89e968f88827d797776757576787a7b7063564a3d3024170a000000000000000000000b1825313e4b5764707877767575777a7e848a929aa2a89f958b81766c61564b40352a1e130800000000000000000000000000000000000000000000131f2c3946525f6c7986929facada194877a6e6154483b2e211508000000000000000000000000000a1724303d4a5663707c8996a2afa99c908376695d5043372a1d100013202c3946535f6c7986939facada093877a6d6053473a2d201407000000000000000000000000000916222f3c4855626f7b8895a2aeaa9d9084776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201407000000000000000000000000000815222f3b4855616e7b8895a2aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e12050000000000000000000006121f2b3744505c6975818d998d8175695d51464b57636f7b87929e9a8f84796f665d554f4a474647494d535a636c76818b95928e867b7064574b48535f6b77838f968a7d7165594c4034271b0f02000000000000000000000004101c28333e485056595959595959595650483e33281c121e2a353f49515759595959595959544d44393a444d5459595959595958524b413639444d54595959595959595751493f34291d1105000b16222d38414a5154555555555555524c433a2f251a0e0300000000000000000000000004101c2935414d5a66727e8b97a3a3968a7d71645855616d7986929f9f93877a6e6155515e6a76838f9ca295897c70645754616d7986929fa79b8e82766a5d5145382c2014070000000000000013202c3946535f6c798693a0acaca09386796c625a524b43454f59626c76808a949da7aaa0968d83796f665c52493f352c22180f05000000000000000000000000000000000000000000010d1924303c48545f6b77838f9aa6aca0958984848484848484848484848484848484848484848484848484848487929eaaa89c9185796d61554a3e32261a0e030000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e212935414d5965717d8994a09e92858793a09d9185796d61564a3e32262835424f5b6875828f9ca8a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7e808285888b90949a9fa5aca8a29b938c847b726a60574d443a2f251b100600000000000000000c17232e39444e58626b737b81878b8d8f90908f8d8b87827c766e66656f7880868a8c8d8c8a86796d6053463a2d201307000000000000000000000000000000000000000000000000000004080b0f11141f2a36414d58636f7a85909aa5afa89f958c847d76716d6a6968696a6b6e6f695f53473b2f221609000000000000000000000a16232f3b48535e676c6b6969696a6e727980889099a3a79d93887d73685d51463b3024190d0200000000000000000000000000000000000000000013202c3946535f6c7986939facada093877a6d6053473a2d201407000000000000000000000000000916222f3c4855626f7b8895a2aeaa9d9084776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815222e3b4855616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e1205000000000000000000000915222e3a4753606c78859195897c7064584c434f5b6874808c98a094897d72685d544b433e3b3a3a3c4148515a646f7a858986827e7a7164584b424e5a66727e8b978d8175685c5043372a1e110500000000000000000000000714202c38444f5a6266666666666666625a4f44382c2016222e3a46515b63666666666666655f564b40404b565f656666666666645d53483c404b565f65666666666666635b50453a2e211509000f1b27333e49545c616262626262625d564c41362b2014090000000000000000000000000713202c3845515d6976828e9ba79f93877a6e6155515e6a76838f9ba2968a7d71655854616d7986929f9e9286796d6154515e6a76838f9ba89e9286796d6155483c3023170b0000000000000013202c3946535f6c798693a0acaca093867b746c645d554d4d57616b747e88929ca6aba2988e857b71675e544a40372d231a100600000000000000000000000000000000000000000000000814202b37434f5b66727e8a96a2ada59b939191919191919191919191919191919191919191919191919191919299a3aea4988c8074685c5145392d21160a000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e222e3a46525d6975818d99a59b8f8284909da2968a7e72665a4e42362a2835424f5b6875828f9ca8a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f727070707070707070707070707071727375787b8084898e949aa1a8ada59e968d857c72695f554b41372c22170c0100000000000004101c28343f4a55606a747d858c92979a9c9d9d9c9a97938e8881786f6c77818a9196999a999386796d6053463a2d201307000000000000000000000000000000000000000000000003080c1014181b1e20242f3b47525e6975808b96a1acaba1978d837a726b65615e5c5b5c5d5f61625e574d42372b1f13070000000000000000000007131f2b37424c555c5f5e5d5c5c5e62676e767e87919ba5a49a8f84796e63574c41352a1e130700000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815222e3b4855616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e1205000000000000000000000b1824313d4a56636f7b88949185796c60544846535f6b7884909c9b9084786c61564b4239322e2d2d30363f48535d68737f7d7976726e695f54483e4a56626e7b87939184786b5f5246392d20140700000000000000000000000916232f3c4855616c737373737373736c6155483c2f231825313e4a57636d73737373737371675c504345515c687173737373736f64594d4143505c67717373737373736d62564a3d3124170b00111e2a37434f5b666d6f6f6f6f6f6e685d52473c31251a0f0300000000000000000000000b17232f3c4854616d7985929ea99c9084776b5e524e5a6773808c98a4998d8174685b5764707d8995a29b8f83766a5d514e5a6773808c98a5a295897d7164584c4033271b0f0200000000000013202c3946535f6c798693a0acaea2978d867e766e675f57555f69737c87909aa4ada39990867c72695f554c42382e251b1108000000000000000000000000000000000000000000000000030f1b27323e4a56626d7985919da8ada49f9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9ea3abab9f93877b6f64584c4034281d1105000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e27323e4a56626e7a86929ea4988c7f818d99a69a8e82766a5f53473b2f2835424f5b6875828f9ca8a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f7265636363636363636363636363646567696c6f73787d838990979ea6aea89f978e857b71675d53493e34291e13080000000000000815212d3944505c67727c868f979ea29c9793929192939699928a8278727d89939ca29d97949386796d6053463a2d201307000000000000000000000000000000000000000000040a0f14181d2124272a2d2f34404c58636f7a86919da8afa49a8f857b7168615a55514f4f4f50525555534d453b31261a0f0300000000000000000000030f1a25303a434b505251504f4f51565c646c757f89939da8a1968a8074695d52463b2f24180d01000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e1205000000000000000000000d1a2633404c5965727e8b978e8275695d50444956626e7b8794a0988b7f73675b50443a3027222021252d36414c57626d73716d6966625e574d433a46525f6b77849094877a6e6155483c2f23160900000000000000000000000a1724303d4a5763707d80808080807d7063574a3d30241926323f4c5965727f8080808080786b5e51454955616d79808080808075695d524645515e6b7880808080807e7165584b3e3225180b00121f2c3945525f6b777b7b7b7b7b7a6f64594d42372b1f140800000000000000000000020e1a27333f4b5864707c8995a1a6998d8174685b4f4b5763707c8995a19c9084776b5e5a6773808c98a4988c8073675a4e4b5764707c8995a1a5998d8174685c4f43372b1e120600000000000013202c3946535f6c798693a0acb3a89f98908881797169615d67717b858f98a2aca49b91877d746a60574d433a30261d130900000000000000000000000000000000000000000000000000000a16222e3945515d6974808c98a4afafabaaa7a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a6aaabaeb2a69a8e82766b5f53473b2f24180c00000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e2b37434f5b67737e8a96a2a195887c7d8a96a29f93877b6f63574b3f332835424f5b6875828f9ca8a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f726559565656565656565656565657585a5c5f63676c72777e858c949ca5aea9a0978d83796f655a50453a2f24190e0300000000000c1825313d4955616d78838e98a1a198918b87858485878a8e93948a8176838f9aa59c938c878786796d6053463a2d20130700000000000000000000000000000000000000040a10151b2024292d303437393c3e45515c6874808b97a2aea99e93887d73695f564f49454342434446484947423b33291f150900000000000000000000000009141e28313940444645434343454b525a636d77818c96a1a79c91857a6e63574c4035291d1206000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e1205000000000000000000000f1c2835424e5b6774818d988c7f73665a4d414b5865717d8a97a194887c6f63574b3f33281e1613141b252f3a46515b636765615d5956524d453c36434f5c6875818e96897d7064574a3e3125180b00000000000000000000000a1724303d4a5763707d8a8d8d8d8a7d7063574a3d30241926323f4c5965727f8c8d8d8d85786b5e51454e5a66727d898d8d8d867a6e62564b45515e6b78858d8d8d8b7e7165584b3e3225180b00121f2c3845525e6a75808888888881756a5e53483c3024180d0100000000000000000005111e2a36434f5b6774808c99a5a3968a7d7165584c4754606d7985929e9f93877a6e625e6a76838f9ca195897c7063574b4854606d7986929ea99c9084786b5f53473a2e22160900000000000013202c3946535f6c798693a0acb9b1a9a29a928b837b736c666f79838d97a1aaa69c92897f756b62584e453b31281e140b01000000000000000000000000000000000000000000000000000005111d2935404c5864707b87939fabb6aea49c98989898989898989898989898989898989898989898989aa1abb6ada195897d72665a4e42372b1f130700000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e303c47535f6b77838f9ba79e9185797a86929ea3978b8073685c5044382c35424f5b6875828f9ca8a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f7265594c4a4a4a4a4a4a4a4a4a4a4a4c4e5053575b61666c737a828a939ca5aea89f958b81776c61574c41362b1f140900000000000f1b2834404d5965717d8995a0a4998f86807a7877787a7d82888f92887d86929fa2968b817b7a7c796c6053463a2d201307000000000000000000000000000000000001080f151b21262c3035393d404346484a4c55616d7985919ca8afa4988d82766c61574d443d3936353637393b3c3a36312921170e03000000000000000000000000020d161f272e34373938373636394048515b656f7a85909ba6a2968b8074685d51463a2e23170b000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000111d2a3743505d6976838f968a7d7064574b414d5a6673808c999e9285796c6053473b2f23170c0709131e29343f4951575a5855514d4a46413b3334404d5966727f8c988b7e7265594c3f3326190d00000000000000000000000a1724303d4a5763707d8a979a978a7d7063574a3d30241926323f4c5965727f8c999a9285786b5e5147535f6b76828e9a9a968b7e73675b4f45515e6b7885929a988b7e7165584b3e3225180b00111d2936424e59636e79848f9592877b7064584d4135291d11050000000000000000000915212d3a46525f6b7784909ca89f93877a6e61554944515d6976828e9ba3968a7d7165616d7986929f9e9285796d60544845515d6a76828f9ba7a094877b6f63564a3e3225190d00000000000013202c3946535f6c798693a0acb9b0a9a5a49c958d857d766e77818b959fa9a79d948a81776d635a50463c33291f160c02000000000000000000000000000000000000000000000000000000000c1824303c47535f6b76828e9aa6b2a89c928b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8f9aa5b2a89c9185796d6155493e32261a0e0200000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e34404c5864707c88949fa69a8e827576828e9ba79c9084786c6054483c3035424f5b6875828f9ca8a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f7265594c3f3d3d3d3d3d3d3d3d3d3e3f4144474b50555b61697078818a939ca6b0a79d93897e73685d52473c30251a0e0200000000111d2a3643505c6975818e9aa69e93887d746e6b6b6b6e71767d848d8e838794a19e9285796f6d7070685d5145382c1f120600000000000000000000000000000000050c131a20262c32373c4145494c50525557595a66727d8a95a1adaa9e93877b70655a4f46423e39342f292a2d2f2f2e2a251f170f060000000000000000000000000000040d161d23282b2c2b2a29292e363f49535e68737e8a95a0a89c9185796e62564b3f33271c10040000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000121e2b3845515e6b77849194887b6e625549424f5b6875828e9b9d9083776a5d5144382b1f130600010d18232d373f464b4d4c4845413d3a363029323e4b5764717d8a978d8173675a4d4134271b0e00000000000000000000000a1724303d4a5763707d8a97a4978a7d7063574a3d30241926323f4c5965727f8c999e9285786b5e514c57636f7b87939fa69b8f84786c605448515e6b7885929e988b7e7165584b3e3225180b000d1a25313c47525d68737e8994988c8175695d5145392d2115080000000000000000000c1825313d4956626e7a87939fa99c9084776b5e5246414d5a66727e8b97a4998d81746864707c8995a29b8f82766a5d5144414e5a66737f8c98a4a3978b7e72665a4e4135291d1004000000000013202c3946535f6c798693a0acb2a89e98989e9f978f888078808a939da7a99f958c82786e655b51483e342a21170d04000000000000000000000000000000000000000000000000000000000007131f2b37424e5a66727d8995a1ada79a8d817e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e8a97a4afa3988c8074685c5145392d21150a0000000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e3945515d6874808c98a4a3968a7e72727e8b97a3a094897c7165594d413535424f5b6875828f9ca8a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f7265594c3f323030303030303030313234373b3f444a50575e666f77818a949ea8afa59a90857a6f64584d42362b1f130800000000121f2b3845525e6b7784919da79a8e82766b635f5e5f61666b727a838d8e9099a49c8f8276696064645e564b4034281c1004000000000000000000000000000000070f161e252b32383d43484d5155595c5f616465676a76828e9aa6b2a69a8e82766b5f5956524e49453f3a342e272222211e1a140d0500000000000000000000000000000000040b12171c1e1f1f1d1c1d242d37414c57626d78848f9ba6a1968a7e73675b5044382c2015090000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000121f2c3945525f6c78859293877a6d60544743505c6976838f9c9b8f8275695c4f4236291d1003000006111b252d353b3f403f3c3935312d2a2523303d4956636f7c89968e8175685b4e4235281b0f00000000000000000000000a1724303d4a5763707d8a97a4978a7d7063574a3d30241926323f4c5965727f8c999e9285786b5e51505c6874808c98a3a8a094887c7165594d515e6b7885929e988b7e7165584b3e3225180b000915202b36404b56616c78848f9b9185796d6155493d3124180c0000000000000000030f1c2834414d5965727e8a97a3a6998d8174685b4f433e4a56636f7b8894a19c9084776b6773808c98a4988c7f73665a4e413e4a57636f7c8895a1a79b8e82766a5d5145392c201408000000000013202c3946535f6c798693a0acaea2968d8c959ea19a928a8288929ba5aaa0978d837970665c53493f362c22180f05000000000000000000000000000000000000000000000000000000000000030e1a26323e4955616d7985909ca8a99d9185797171717171717171717171717171717171717176828e9aa6ab9f93877b6f63584c4034281c11050000000000000000000013202c3946535f6c798693a0aca194887b6e6154483b313d4955616d7985919da99f93877a6e6e7a87939fa5998d8175695d51453a35424f5b6875828f9ca8a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f7265594c3f3226232323232323232426282b2f33383f454c545d656f78828c97a1acaca1968b8075695e53473b3024180c0000000013202c3946535f6c7986929fa4988b7e72665a525152555a6169717b85909ba2a79a8e8174675b5757534c443a2f24180c00000000000000000000000000000109111921282f363d43494e54595d6165686b6e707273757a86929eaaada195897d716b6865625e5a55504b453f39322b241d150e090300000000000000000000000000000000000001070c0f1213121010121b25303a45505c67737e8a96a1a79b8f84786c6055493d3125190d0200000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e12050000000000000000000013202c3946535f6c7986939386796c5f534644505d6a7783909d9b8e8174675b4e4135281b0e0200000009131b232a2f323433302c2925211e19222f3c4855626f7b88958f8275685b4f4235291c0f00000000000000000000000a1724303d4a5763707d8a97a4978a7d7063574a3d30241926323f4c5965727f8c999e9285786b5e5155616d7985909c9e9b9e998d81756a5e52515e6b7885929e988b7e7165584b3e3225180b00040f19242f3a45505b67727e8a96968a7e7165594d4034281b0f020000000000000007131f2c3844505d6975828e9aa6a3968a7d7165584c3f3b4753606c7885919da093877a6e6a76838f9ba195887c7063574a3e3b4754606c7985919eaa9e9286796d6155483c3024170b000000000013202c3946535f6c798693a0acaca09386838c959ea49c948e919aa4aba2988e857b71685e544a41372d241a100700000000000000000000000000000000000000000000000000000000000000000a15212d3945505c6874808c97a3aea2968a7e7266656565656565656565656565656565656f7b87939faba69a8e82766b5f53473b2f24180c000000000000000000000013202c3946535f6c798693a0aca194887b6e6154483b36424e5a66727d8995a1a79b8f83776a6a77838f9ba79d92867a6e62564a3e35424f5b6875828f9ca8a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f7265594c3f32261917171717171718191c1f23282d343b424b535d66707a858f9aa5b0a89d91867b6f63584c4035291d110500000013202c3946535f6c798693a0a4978a7d7063574a4446494f575f69737e8995a1a79a8e8174675a4d4a47423b32281d120700000000000000000000000000010a131b232b333a41484e545a5f64696d7175787a7d7e8182828a96a2aeab9e92857c7a7875726e6a66615c56514a443d362e271f160e0500000000000000000000000000000000000000000000000000000109131e29343f4a56626d7985919ca8a094897d7165594d42362a1e120600000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e12050000000000000000000013202c3946535f6c7986939286796c5f524644505d6a7784909d9a8e8174675a4d4134271b0e01000000010911191e2326272624201c19151115222e3b4855616e7b88958f8275695c4f4236291c0f00000000000000000000000a1724303d4a5763707d8a97a4978a7d7063574a3d30241926323f4c5965727f8c999e9285786b5e515a65717d89959d938e939d92867a6e6357515e6b7885929e988b7e7165584b3e3225180b000008121d28333f4a56626e7986929a8e8175695c5043372a1e1105000000000000000a16232f3b4754606c7985919eaaa093877a6e6255493c3744505c6975818e9aa3968a7d716d7986929e9e9285796c6054473b3844505d6975828e9ba7a295897d7164584c4033271b0f020000000013202c3946535f6c798693a0acaca093867a838c969fa69f9b9ca3aca39990867c73695f564c42382f251b120800000000000000000000000000000000000000000000000000000000000000000005111c2834404c57636f7b87939eaaa69a8f83776b5f585858585858585858585858585c6874808c97a3ada195897d72665a4e42362b1f1307000000000000000000000013202c3946535f6c798693a0aca194887b6e6154483b3b47525e6a76828e9aa6a3978b7f736666727e8a96a2a2968a7e72665a4e4337424f5b6875828f9ca8a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f7265594c3f3226190c0a0a0a0a0a0b0d0f12171c22293039414b545e69737e89949faaaea3978c8074695d5145392d21150900000013202c3946525f6c7985929fa4978a7d7064574a43403f454d57626d7884909da79a8e8174675a4d413b37302920160c01000000000000000000000000010a131c252d353d444c52595f656b7075797d818487898b8d8e8f929ba6b2aca0948b898784817e7a76726d68625c554f484039312820170f050000000000000000000000000000000000000000000000000000020c17232e3a45515d6874808c98a4a5998d82766a5e52463a2e23170b00000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e12050000000000000000000013202c3946535f6c7986939386796c5f534644505d6a7784909d9a8e8174675b4e4134281b0e01000000070f171d2226282826231f1c18151115222f3c4855626e7b88958f8275685c4f4236291c0f00000000000000000000000a1724303d4a5763707d8a97a4978a7d7063574a3d30241926323f4c5965727f8c999e9285786b5e525e6a76828e9a988c818c98978b7f73675c515e6b7885929e988b7e7165584b3e3225180b00030e19242d363e45515d6975828e9a9184786b5f5246392c201307000000000000010e1a26323f4b5764707c8895a1a99c9084776b5e52463934404d5965727e8a97a3998d8174707c8995a19b8e8276695d51443835414d5a66727e8b97a4a5998d8174685c4f43372b1e12060000000013202c3946535f6c798693a0acaca09386797a848d969fa8a7a8ada59b91887e746a61574d443a30261d130900000000000000000000000000000000000000000000000000000000000000000000000c18232f3b47535e6a76828e9aa5ab9f93877b6f64584c4b4b4b4b4b4b4b4b4b4b55616c7884909ca8a89c9085796d6155493e32261a0e02000000000000000000000013202c3946535f6c798693a0aca194887b6e6154483b3f4b57636f7b87939eaa9e92867a6f63626e7a86929ea79b8f83776b5f53473b424f5b6875828f9ca8a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f7265594c3f3226190c0000000000000003060b11171f272f39424c57616c77828e99a5b0a89d9185796d6155493d3125190d010000121f2b3845515e6a7784909da5988c7f73675b534f4d4b4a4a505c6874818d9aa69a8e8174675a4d41342b251f170e04000000000000000000000000000a131c252e363f474f565d646b71767c81858a8d919396989a9b9c9ea4adb4b1a69d979593918e8a87827d78736d676059524a433a322921170e05000000000000000000000000000000000000000000000000000006121d2934404c58646f7b8793a0aa9e92867a6e63574b3f33271b0f03000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000131f2c3946525f6c79859293867a6d60534743505d697683909c9b8e8275685b4f4235281c0f02000006101921282e323535322f2b2824211d1823303c4956626f7c89958e8275685b4f4235281c0f00000000000000000000000a1724303d4a5763707d8a97a4978a7d7063574a3d30241926323f4c5965727f8c999e9285786b5e57636f7b87939e94887c87939c9084786c60555e6b7885929e988b7e7165584b3e3225180b0008141f2b353f484f545966727e8b9893877a6d6154483b2e22150800000000000005111d2a36424e5b6773808c98a4a6998d8174685b4f4336313d4956626e7b8794a09c908477737f8c98a4988b7f73665a4d4135313e4a56636f7b8894a1a99c9084786b5f53473a2e2216090000000013202c3946535f6c798693a0acaca0938679717a848d96a0a9b2ab9e93897f756c62584f453b32281e150b01000000000000000000000000000000000000000000000000000000000000000000000007131f2a36424e5a65717d8995a1aca4988c8074685c50453e3e3e3e3e3e3e424d5965717d8995a1ada3988c8074685c5045392d21150900000000000000000000000013202c3946535f6c798693a0aca194887b6e6154483b44505c6773808b97a3a69a8e82766a5e5d6975818d99a59f93877b6f63584c40424f5b6875828f9ca8a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f7265594c3f3226190c06060606060606060604060d151d27303b45505b66717c88949fabada2968a7e72665a4d4135291d10040000101d2a36434f5c6875818d99a59b8f83786d645f5c59585756565965727f8c98a59a8e8174675a4d4134271a140d050000000000000000000000000008121c252e374048515960686f767c82888d91969a9da0a2a5a6a8a9a8a8a7a8a8a9a8a4a2a09d9a97938e89847e78726b645c554c443b332920170d030000000000000000000000000000000000000000000000000006121e2935414d5965707c8894a0ada3978b7f73675b4f43382c201408000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000121f2b3845515e6b78849194887b6e615548424f5c6975828f9b9c8f8376695d5043372a1d110400020d18222b333a3f41413f3b3834312d292324313e4a5764707d8a968d8174675a4e4134281b0e00000000000000000000000a1724303d4a5763707d8a97a4978a7d7063574a3d30241926323f4c5965727f8c999e9285786b5e5c6874808b979b8f8377838f9a95897d7165595e6b7885929e988b7e7165584b3e3225180b000c1824303c47515a6062636f7c899595887c6f6256493c3023160a0000000000000814212d3946525e6a77838f9ca8a3968a7d7165584c40332e3a46535f6b7884909d9f93877a75828e9ba195887c6f63574a3e322e3b4753606c7885919daaa094877b6f63564a3e3225190d0100000013202c3946535f6c798693a0acaca09386796c727b848e97a0a9aa9d90847a71685f564d443b32291f160d040000000000000000000000000000000000000000000000000000000000000000000000020e1a26313d4955616c7884909ca7a89c9185796d6155493d32323232323a46525e6a76828e99a5aa9f93877b6f63584c4034281c110500000000000000000000000013202c3946535f6c798693a0aca194887b6e6154483d4854606c7884909ca8a195897d71655a5965717d8995a1a4988c8074685c5044424f5b6875828f9ca8a69a8d807366594d4033261a0d0000000000050a0e1a2633404d596673808d9aa6b2a6998c7f7265594c3f32261913131313131313131312100c080b151f29333e4955606b77838f9ba7b2a69a8e82766a5d5145392c20140700000e1b2734404c5965717d89949fa094897f76706b6866656363636265727e8c98a59a8e8174675a4d4134271a0e020000000000000000000000000006101a242e374049525a636b727981878d93989da2a6a9a8a5a29f9d9c9b9b9a9b9b9c9ea0a2a5a8a6a39f9a95908a837d766e665e564d453b32291f150b010000000000000000000000000000000000000000000000000b16222e3a46525d6975818d99a5b1a79b9084786c6054483c3024180d010000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000111e2a3744505d6a76839096897c7063574a414e5b6774818d9a9d9184786b5e5245392d2014080508141f2a343d454b4e4e4b4744403d39342e2733404c5965727e8b988c7f7266594c4033261a0d00000000000000000000000a1724303d4a5763707d8a97a4978a7d7063574a3d30241926323f4c5965727f8c999e9285786b5e616c7884909c968b7e737e8a96998e82766a5e5e6b7885929e988b7e7165584b3e3225180b000e1b2834404d58636c6f6f6f7a8794968a7d7064574a3d3124170b0000000000000c1824303d4955626e7a86939faba093877a6e6255493c302a37434f5c6874818d99a296897d7884919d9e9185796c6053473b2e2b3744505c6975828e9aa7a3978b7e72665a4e4135291d100400000013202c3946535f6c798693a0acaca09386796c69727b858e97a0a9a0968d847a71685f564d443b31281f160d0400000000000000000000000000000000000000000000000000000000000000000000000915212d3844505c68737f8b97a3ada195897d71665a4e42362a2527333f4b57636e7a86929eaaa69a8e82766a5f53473b2f23180c0000000000000000000000000013202c3946535f6c798693a0aca194887b6e615448414d5965717d8994a0a89c9185796d615554606c7884909ca89c9084786c615549424f5b6875828f9ca8a69a8d807366594d4033261a0d000000010910161a1e2633404d596673808d9aa6b2a6998c7f7265594c3f3226202020202020202020201f1c18130d0d17222d38434f5b66727e8a96a2aeaa9e9286796d6154483c2f23170a00000b1824303c4854606c77838d97a19b9188817b7875737170706f6f6f727e8c98a59a8e8174675a4d4134271a0e01000000000000000000000000030e18222c364049525b646c757c848b92999fa4a9aaa4a09c989593918f8e8e8e8e8f90919396999ca0a5aaa6a19b958e87807870685f574d443b31271d13090000000000000000000000000000000000000000000000030f1b27333f4b56626e7a86929ea9b5aca094887c7064594d4135291d11050000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e1205000000000000000000000f1c2935424f5b6874818e988b7e7265594d404c5966727e8b989f93867a6d6155483c3025191312131a25303b464f565a5b5754504d49453f382f36424f5b6874818d978a7d7164584b3e3225180c00000000000000000000000a1724303d4a5763707d8a97a4978a7d7063574a3d30241926323f4c5965727f8c999e9285786b5e65717d89959e92867a6e7985919d92877b6f635e6b7885929e988b7e7165584b3e3225180b00101c2936434f5c69757b7b7b7b8793988b7e7164584b3e3225180b0000000000030f1b2834404c5965717d8a96a2a99c9084776b5e5246392d2733404c5865717d8a96a2988c807a8794a09b8e8275695d5044382b2834414d5966727e8b97a3a79b8e82766a5d5145392c20140800000013202c3946535f6c798693a0acaca09386796c6069727c858e97a0a89f968d837a71685f564d433a31281f160d040000000000000000000000000000000000000000000000000000000000000000000004101c28343f4b57636f7a86929eaaa69a8e82766a5e52473b2f232c38444f5b67737f8b97a3ada195897d71665a4e42362b1f13070000000000000000000000000013202c3946535f6c798693a0aca194887b6e61544846525d6975818d99a5a4988c8074685c50505c6874808c98a4a195897d7165594d424f5b6875828f9ca8a69a8d807366594d4033261a0d0000010a131a21262a2c33404d596673808d9aa6b2a6998c7f7265594c3f322c2c2c2c2c2c2c2c2c2c2c2b29241e170f101c27333e4a56626e7a86929fabaea295897d7064584b3f3226190d00000814202c38444f5b66717b858f979e9a938c888481807e7d7d7c7c7b7b7e8c98a59a8e8174675a4d4134271a0e010000000000000000000000000b15202a343e48525b646d767e878e969da4aaaaa49e9994908c898684838281818182838587898c9094999ea4aaa6a099928a827a71695f564d43392f251b1006000000000000000000000000000000000000000000000814202c38434f5b67737e8b96a2aeb8b0a5998d8175695d5145392d22160a0000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e1205000000000000000000000e1a2734404d5966727f8b988e8175685c50434a5763707c8995a296897d7165594d41362b23201e1f242c36414d5861676764605c5955514941363945525e6a77839094887b6f6256493c3023170a00000000000000000000000a1724303d4a5763707d8a97a4978a7d7063574a3d30241926323f4c5965727f8c999e9285786b5e6a76828e99998d81756975818d99978b8074685e6b7885929e988b7e7165584b3e3225180b00101c2936434f5c6976838888888b95988b7e7265584c3f3225190c000000000006121f2b3744505c6875818d9aa6a6998d8174685b4f43362a24303c4955616e7a87939f9b8f827d8a96a3978b7e72665a4d41342825313d4a56626f7b8794a0aa9e9286796d6155483c3024170b00000013202c3946535f6c798693a0acaca09386796c5f606a737c858e98a1a89f958c837a71685f564d433a31281f160d04000000000000000000000000000000000000000000000000000000000000000000000b17232f3b46525e6a76828d99a5aa9e93877b6f63574b3f3328303c4854606c7884909ba7a89c9085796d6155493d32261a0e020000000000000000000000000013202c3946535f6c798693a0aca194887b6e6154484a56626e7a86929ea99f93877b7064584c4b57636f7b87939fa5998d82766a5e52464f5b6875828f9ca8a69a8d807366594d4033261a0d000009131c252c32373939404d596673808d9aa6b2a6998c7f7265594c3f3939393939393939393939393835302921180e16222e3a46525e6a76838f9ba8b1a5998c8073675a4e4135281c0f020004101c27333e4a555f6a737c858c93989d9894908e8c8b8a8a89898888888e9aa69a8e8174675a4d4134271a0e01000000000000000000000007121c27313c46505a646d7680889099a0a8aea69f99938d8884807c7a7776757474747576787a7d8084888d93999fa6aba49c948c847b71685f554b41372d22170d020000000000000000000000000000000000000000010d1925303c4854606c77838f9ba7aeacada99d9185796e62564a3e32261a0e0200000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e1205000000000000000000000c1825313e4a5763707c89959184786c5f53474854616d7986929e998d8175695e52473d352f2c2b2c2f353e48535e697373706c6965625b52483d3d4955616e7a86939185796c6053473a2e21150800000000000000000000000a1724303d4a5763707d8a97a4978a7d7063574a3d30241926323f4c5965727f8c999e9285786b636e7a86929e94887c7165707c88949c9084786d616b7885929e988b7e7165584b3e3225180b00101c2936434f5c697683909595969d988c7e7265584c3f3225190c00000000000a16222e3b4753606c7885919da9a3968a7d7165584c403327212d3946525e6b7783909c9e9185808c99a194887b6f63564a3e3125212e3a47535f6c7884919da9a296897d7164584c4033271b0f02000013202c3946535f6c798693a0acaca09386796c5f57616a737c868f98a1a89e958c837a71685f554c433a31281f160d0400000000000000000000000000000000000000000000000000000000000000000006121e2a36424d5965717d8894a0aca3978b8073685c5044382c35414d5965707c8894a0aca3978c8074685c5044392d211509000000000000000000000000000013202c3946535f6c798693a0aca194887b6e6154484f5b67727e8a96a2a79b8f83776b5f534747535f6b77838f9ba79e92867a6e62564a4f5b6875828f9ca8a69a8d807366594d4033261a0d0005101a252e373e434646464d596673808d9aa6b2a6998c7f7265594c4646464646464646464646464645413a332a2015111d2935424e5a6773808c98a5b1a89b8f8276695d5043372a1e110400000b16222d38434d58616a737b82888c919496989999989796969695959498a0a79a8e8174675a4d4134271a0e0100000000000000000000020d18232e39434e58626c767f89929aa2aaaca49c958e87827c7773706d6b6968676767686a6b6e7074787c82878e959ca4aca69e968d847a71675d53493e34291e1309000000000000000000000000000000000000000006121d2935414d5965707c8894a0aaa39fa0a6a2968a7e72665a4e43372b1f130700000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e1205000000000000000000000916222f3b4854606d79869294887b6f63574b45515d6976828e9a9d91867a6f64594f47403b3938393b4047505a646f7a807c7875716d64594d41414d5965717d8a968e8276695d5044382b1f120600000000000000000000000a1724303d4a5763707d8a97a4978a7d7063574a3d30241926323f4c5965727f8c999e9285786b67737f8b979b8f84786c606c78848f9b95897d71666b7885929e988b7e7165584b3e3225180b00101c2936434f5c697683909ca2a3a5988c7e7265584c3f3225190c00000000010d1926323e4a57636f7b8894a0aca093877a6e6255493d30241d2a36424f5b6774808c99a19488838f9b9e9185786c6053473b2e221e2b3743505c6875818d9aa6a5998d8174685c4f43372b1e1206000013202c3946535f6c798693a0acaca09386796c5f5358616a737d868f98a2a79e958c837a71675e554c433a31281f160c030000000000000000000000000000000000000000000000000000000000000000020e1925313d4854606c78848f9ba7a89c9084786c6054493d313a46515d6975818d99a5aa9e93877b6f63574c4034281c1005000000000000000000000000000013202c3946535f6c798693a0aca194887b6e615448535f6b77838f9ba7a2968a7e72665a4f43424e5a66727e8a96a2a2968b7e73675b4f4f5b6875828f9ca8a69a8d807366594d4033261a0d000a16212c3740484f52535353596673808d9aa6b2a6998c7f7265595353535353535353535353535353514c453c32271c101926323e4b5764707d8996a2afaa9e9185786b5f5245392c201306000005111c27313c464f58616970767c8184878a8b8c8d8d8e8e8e8e8f8f8f949da79a8e8174675a4d4134271a0e010000000000000000000008131f2a353f4a555f6a747e88919ba4acaba29a928a837c76706c6764615e5d5b5b5b5b5c5d5f6164686c71767c838a929aa2aba89f968c83796f655a50453b30251a0f04000000000000000000000000000000000000000a16222e3a46525d6975818d99a5a19892949da69a8f83776b5f53473b2f23180c00000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e12050000000000000000000007131f2c3845515d6976828e988c8074685c50454d5966717d8995a0978b80756b6159514b48454545474c5159626b76818c8885817e76695d504346525e6a76828e978b7e72665a4d4135281c0f0300000000000000000000000a1724303d4a5763707d8a97a4978a7d7063574a3d30241926323f4c5965727f8c999e9285786b6c7884909c978b7f73675b67737f8b979a8e82766b6b7885929e988b7e7165584b3e3225180b00101c2936434f5c697683909ca9afa5988c7e7265584c3f3225190c0000000004101d2935424e5a66737f8b98a4a99d9084776b5f5246392d211a26333f4b5864707d8995a2978d8a939e9a8e8275695c5044372b1f1b2734404c5965727e8a97a3a99d9084786b5f53473a2e221609000013202c3946535f6c798693a0acaca09386796c5f534f58616b747d879099a2a79e958c837970675e554c433a31281e150c0300000000000000000000000000000000000000000000000000000000000000000914202c3844505b67737f8b96a2aca095897d7165594d41353e4a56626e7a86929da9a69a8e82766a5f53473b2f23180c00000000000000000000000000000013202c3946535f6c798693a0aca194887b6e61544c5864707c88949fa99d92867a6e62564a3e3e4a56626e7a86929ea79b8f83776b5f534f5b6875828f9ca8a69a8d807366594d4033261a0d000e1a26323e48525a5f5f5f5f5f6673808d9aa6b2a6998c7f72655f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5d574e43382d211516232f3c4855616e7a8794a0adaca093867a6d6054473a2e2114080000030e1a242f3840474f575e656b7074787b7d7e808181818182828282838c99a59a8e8174675a4d4134271a0e01000000000000000000030e1925303b46515c67717b86909aa3adaba29990888078716b65605b575452504f4e4e4e4f505255585b60656b717880889099a2aba89e958b81776c62574c41362b201509000000000000000000000000000000000000030f1b27333f4a56626e7a86929da99c90868b96a29f93877b6f63584c4034281c1004000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e12050000000000000000000004101c2935414d5a66727e8a969084786d61564a4955616d78848f9a9d92877d736b635c575452515254575c636b747d889295918a7e73685c4f424c57636e7a869293877a6e62564a3e3125190c0000000000000000000000000a1724303d4a5763707d8a97a4978a7d7063574a3d30241926323f4c5965727f8c999e9285786b717d89949e92867a6e6257636e7a86929e93877b6f6b7885929e988b7e7165584b3e3225180b00101c2936434f5c697683909ca9b2a5988c7e7265584c3f3225190c000000000814202d3945515e6a76838f9ba7a6998d8174685c4f43362a1e1723303c4855616d7986929f9f98969ba4978b7e7266594d4134281c1824313d4956626e7b8793a0aca094887b6f63564a3e3225190d010013202c3946535f6c798693a0acaca09386796c5f53464f59626b747d879099a2a79e958c837970675e554c433a30271e150c030000000000000000000000000000000000000000000000000000000000000004101c27333f4b56626e7a86929da9a5998d81756a5e52463a434f5b67727e8a96a2ada195897d71665a4e42362a1f130700000000000000000000000000000013202c3946535f6c798693a0aca194887b6e6154515c6874808c98a4a5998d8175695d51453a3a45515d6975818d99a5a094887c7064584f5b6875828f9ca8a69a8d807366594d4033261a0d00111e2a37434f5a646b6c6c6c6c6c73808d9aa6b2a6998c7f726c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c686055493d31241814202d3946535f6c7885929eabaea195887b6f6255483c2f221609000008141f2b36404a5257595a5b5f64686b6e70727373747474757575757e8c98a59a8e8174675a4d4134271a0e0100000000000000000008141f2a36414c58636d78838d98a2acada39990877e766e666059544f4b48454342414141424446484b4f545a60666e767e879099a3ada79d93897e73695e53483d31261b0f0400000000000000000000000000000000000814202c37434f5b67737e8a96a2a5998d8186929ea4988c8074685c5044382d211509000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000000d1925313d4956626e79859195897d72665b5045505c67737e89949e998f867c746e6863605f5e5f6064686e757d868f99998e84786d62574b47525d6874808b978e82766a5e52463a2e2215090000000000000000000000000a1724303d4a5763707d8a97a4978a7d7063574a3d30241926323f4c5965727f8c999e9285786b75818d99998d81756a5e525e6a75818d99988c80746b7885929e988b7e7165584b3e3225180b00101c2936434f5c697683909ca9aca5988c7e7265584c3f3225190c000000000b1724303c4855616d7a86929eaba3968a7d7165584c4033271b14202c3945515e6a76838f9ba8a4a3a6a094887b6f63564a3e31251815212d3a46525f6b7784909da9a4978b7e73665a4e4135291d10040013202c3946535f6c798693a0acaca09386796c5f5346475059626b757e879099a3a79e958c827970675e554c423930271e150c03000000000000000000000000000000000000000000000000000000000000000b17222e3a46525d6975818d99a4aa9e92867a6e62564b3f48535f6b77838f9ba7a89c9084786d6155493d31261a0e0200000000000000000000000000000013202c3946535f6c798693a0aca194887b6e615455616d7985919da9a094887c7165594d413535414d5965717d8995a0a4988c8074685c515b6875828f9ca8a69a8d807366594d4033261a0d00131f2c3946525f6b76797979797979808d9aa6b2a6998c7f79797979797979797979797979797979797165594c40332619121e2b3844515e6a7784909daaafa396897c706356493d3023170a00000b1824303c47525c6366676868696a6b6864656667676767686868727e8c98a59a8e8174675a4d4134271a0e010000000000000000010d1924303c47525e69747f8a959faaafa59b91877e756c645c554e48433f3b3937353434353537393c3f44494e555c646c757e87919ba5afa59a90857a6f64594e42372c20150900000000000000000000000000000000010d1924303c4854606c77838f9ba7a195897c828e9aa69c9085786d6155493d3125190d020000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000000915212d3945515d6975818c988f83786c61564b4b56616c77828c969f988f877f7974706d6b6b6b6d70747980878f989b91877c72675c51454d58636e7a859195897d72665a4e42362a1e12060000000000000000000002020a1724303d4a5763707d8a97a4978a7d7063574a3d30241926323f4c5965727f8c999e9285786e7a86929e94897d7165594d5965717c88949c9185796d7885929e988b7e7165584b3e3225180b00101c2936434f5c697683909ca0a0a0988c7e7265584c3f3225190c000000000f1b2733404c5864717d8996a0a0a093877a6e6255493d302417101d2935424e5a6773808c98a0a0a0a09d9185786c5f53473a2e2215121e2a37434f5c6874818d99a0a09b8f82766a5d5145392c2014080013202c3946535f6c798693a0acaca09386796c5f53463e475059626c757e87919aa3a79e948b827970675e544b423930271e150c0300000000000000000000000000000000000000000000000000000000000006121e2935414d5964707c8894a0aba2978b7f73675b4f434c5864707c88949faba3978b8074685c5044392d2115090000000000000000000000000000000013202c3946535f6c798693a0aca194887b6e61545a66727d8995a1a79c9084786c6054483c30313c4854606c7884909ca89d9185796d61555b6875828f9ca8a69a8d807366594d4033261a0d0013202c3946535f6c79868686868686868e9aa7b3a69a8e8686868686868686868686868686868686807366594d4033261a101d2a3643505d697683909ca9b0a4978a7d7164574a3e3124170b00000d1a2733404c58646e7373747576777872675a595a5a5a5b5b5b65727e8c98a59a8d8174675a4d4134271a0e01000000000000000006121e2935414c58636f7a85919ba6b1a89e93897f756c635a524a433d38332f2c2a29282828292a2d2f33383d434a525a636c758089949ea9aca1978c81766a5f54483d31251a0e0200000000000000000000000000000006121d2935414d5964707c8894a0a99d9185787d8a96a2a195897d7165594e42362a1e12060000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e1205000000000000000000000005111d2935414d5864707b879294897e73685d5248505b65707a848d969e98918a84807c7a7878787a7c80858a91999a92897f756b60564b4a545f6a75808b968f84786d6155493d32261a0e0200000000000001060a0d0e0f0f1724303d4a5763707d8a97a4978a7d7063574a3d30241926323f4c5965727f8c999e928578727e8a969c9084786c60544854606c78848f9b958a7e727885929e988b7e7165584b3e3225180b00101c2936434f5c6976839093939393938c7e7265584c3f3225190c00000000111e2a37434f5c6874818d939393939084776b5f5246392d21140d1926323e4b5763707c899393939393938e8275695c5044372b1f120e1b2733404c5865717d8a939393939286796d6155483c3023170a0013202c3946535f6c798693a0acaca09386796c5f5346393e47505a636c757e88919aa3a69d948b827970665d544b423930271e150b020000000000000000000000000000000000000000000000000000000000010d1925303c4854606b77838f9ba7a79b8f83776c605448515d6974818c98a4aa9e93877b6f63574c4034281c10040000000000000000000000000000000013202c3946535f6c798693a0aca194887b6e61545e6a76828e9aa6a3978b7f73675b5044382c2c3844505c6874808c97a3a195897d71655a5b6875828f9ca8a69a8d807366594d4033261a0d0013202c3946535f6c798693939393939397a0abb6aa9f97939393939393939393939393939393938d807366594d4033261a0f1c2936424f5c6875828f9ca8b1a4988b7e7164574b3e3124180b00000e1b2834414e5b67748081818283848275695c504d4d4e4e4e5966737f8c99a59a8d8073675a4d4034271a0d0100000000000000000b17222e3a46525d6975808c97a2adaca1978c82776d635a51484039322c2723201d1c1b1b1b1c1e2023272c32384048515a636d77828d97a2ada89d92877b7065594d42362a1e12070000000000000000000000000000000a16222e3a46515d6975818d99a4a5998c81747985919da59a8e82766a5e52463a2e22170b0000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e12050000000000000000000000010d1824303c48535f6a76818c988f84796f645a5049545e68727b848c949b9c95908c898685858586898c90969c98918980766d63594f47515c66717b8691958a7e73675c5044392d211509000000000000050c1216191b1b1b1b24303d4a5763707d8a97a4978a7d7063574a3d30241b26323f4c5965727f8c999e92857877838f9b978b7f73675c50444f5b67737e8a969a8e83777885929e988b7e7165584b3e3225180b00101c2936434f5c697683868686868686867e7265584c3f3225190c0000000013202c3946525f6b78848686868686868174685c4f43362a1e110a16232f3b4754606d7985868686868686867e7265594d4034281b0f0b1724303d4955626e7a868686868686867d7164584b3e3225180c0013202c3946535f6c798693a0acaca09386796c5f534639353e48515a636c767f88919ba4a69d948b82786f665d544b423930271d140b0200000000000000000000000000000000000000000000000000000000000814202c37434f5b67727e8a96a2aca094887c7064584c55616d7985919da9a59a8e82766a5e53473b2f23170c000000000000000000000000000000000013202c3946535f6c798693a0aca194887b6e6157636f7b87939eaa9e92877b6f63574b3f332728333f4b57636f7b87939fa69a8e82766a5e5b6875828f9ca8a69a8d807366594d4033261a0d0013202c3946535f6c798693a0a0a0a0a0a2a9b2bcb1a8a2a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09a8d807366594d4033261a0f1c2835424f5b6875828e9ba8b1a4988b7e7165584b3e3225180b00000d1a2733404d5966727e8b8e8f909084786c60544c4a494a505c6875818e9aa5988c7f7266594c403326190d0000000000000000030f1b27333f4b57626e7a86919da8b2a69b90857a70655b51483f362e27201b1713110f0e0e0e0f1114171b21272e363f48515b66707b86919ca8afa3988d81766a5e52473b2f23170b0000000000000000000000000000030f1b27333f4a56626e7a86919da9a194887c7075818d99a59e92867a6e63574b3f33271b0f0300000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000000008141f2b37424e5965707b8691968b81766c61584e4c566069727a828990959a9c9895939292929395989c99938d867e766e645b51475059636d78828d988e83786d61564b3f34281c10050000000000070f171d22262828282828303d4a5763707d8a97a4978a7d7063574a3d30282828323f4c5965727f8c999e9285787b87939e92867a6e63574b3f4a56626e7a86919d93877b7885929e988b7e7165584b3e3225180b00101c2936424f5c68747979797979797979797064584b3e3225180c00000000131f2c3946525f6b7679797979797979797165594c4033271b0e07131f2c3844515d69757979797979797979786e62564a3d3125180c0814212d3946525e6b7679797979797979797064584b3e3225180c0013202c3946535f6c798693a0acaca09386796c5f5346392c363f48515a646d768089929ba4a69d948b82786f665d544b42392f261d140b0200000000000000000000000000000000000000000000000000000000030f1b27333e4a56626e7985919da9a4988d8175695d515a66727e8a96a1ada195897d71655a4e42362a1e1307000000000000000000000000000000000013202c3946535f6c798693a0aca194887b6e615c6773808b97a3a69a8e82766a5e52463b2f23232f3b47535f6b77838e9aa69e92867a6e635b6875828f9ca8a69a8d807366594d4033261a0d0013202c3946535f6c798693a0a6a6a6a6a8aeb6bfb5ada8a6a6a6a6a6a6a6a6a6a6a6a6a6a6a69a8d807366594d4033261a0f1c2835424f5b6875828e9ba8b1a5988b7e7165584b3e3225180b00000c1825313e4a56636f7b87939b9c94887c71665d585656575a626d7884909da296897d7064574b3e3125180b000000000000000006131f2b37434f5b67737f8b96a2aeaca1958a7e73695e53493f362d241c150f0b0704010000000205070b10151c242d36404a545f6974808b96a2aea99e92877b6f63574b3f33271b0f03000000000000000000000000000814202b37434f5b67737e8a96a2a89c9084786c717d8995a1a3978b7f73675b4f43382c20140800000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e1205000000000000000000000000030f1a26313d48535f6a75808b9592887d736960564d4e57606870787e848a8e92959798999999989694918d88827b746d645c52494f58626b75808a9492887d72675c50453a2e23170b000000000006101921282e323535353535353d4a5763707d8a97a4978a7d7063574a3d35353535353f4c5965727f8c999e928578808c98998d82766a5e52463a46525d6975818d98988c817885929e988b7e7165584b3e3225180b000e1b2733404c57626a6c6c6c6c6c6c6c6c6c685f54483c3023170a00000000111e2a37434f5a646b6c6c6c6c6c6c6c6c685f54493d3024180b03101c2835414d58636a6c6c6c6c6c6c6c6c6c675d52463a2e21150905111d2a36424e5a646b6c6c6c6c6c6c6c6c685f54483c3023170a0013202c3946535f6c798693a0acaca09386796c5f5346392c2d363f48525b646d768089929ba4a69d948b81786f665d544b42392f261d140b02000000000000000000000000000000000000000000000000000000000a16222e3a45515d6975818c98a4a99d9185796d62565f6b76828e9aa6a89c9084786d6155493d31261a0e02000000000000000000000000000000000013202c3946535f6c798693a0aca194887b6e61606c7884909ca8a195897d71665a4e42362a1e1f2a36424e5a66727e8a96a2a3978b7f73675b6875828f9ca8a69a8d807366594d4033261a0d0013202c3946535f6c79869399999999999ca4aeb8ada39c999999999999999999999999999999998d807366594d4033261a0f1c2936424f5c6875828f9ca8b1a4988b7e7164574b3e3124180b00000915222e3b47535f6b77838e99a4998d82786f6965636364666b747e8995a19d9286796d6155483c2f23160a00000000000000000a16222f3b47535f6b77848f9ba7b3a79b8f84786d62574c42372d241b120b040000000000000000000000040b121b242e38424d58636e7a85919da9afa3978b8073675b4f43372b1f1206000000000000000000000000010d1924303c4854606b77838f9ba7a4988c8074686c7885919da79b9084786c6054483c3024180d01000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e1205000000000000000000000000000915202b37424d58636e79848e988f857b72685f564e4e565e666d73797e8285888a8b8c8c8c8b8a8785817c77716a635b524a5058616a747d8791968b81766b60554a3f34281d120600000000020d18222b333a3f414242424242424a5763707d8a97a4978a7d7063574a424242424242414c5965727f8c999e92857884909c95897d7165594d4236414d5964707c88949d91857985929e988b7e7165584b3e3225180b000b17232f3b4650585e5f5f5f5f5f5f5f5f5f5d564d42372c201407000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5d564d43382c201408000c1925303c4751595e5f5f5f5f5f5f5f5f5f5c554b41352a1e1206020e1a26323d48525a5f5f5f5f5f5f5f5f5f5d564d42372c2014070013202c3946535f6c798693a0acaca09386796c5f5346392c242d364049525b646d768089929ca5a69d948a81786f665d544b41382f261d140b0200000000000000000000000000000000000000000000000000000006111d2935414c5864707c87939faba2968a7e72665a636f7b87939faba3978b8074685c5044392d21150900000000000000000000000000000000000013202c3946535f6c798693a0aca194887b6e6165717c8994a0a89d9185796d6155493d31251a1a26323e4a56626e7986919da79b9084786c606875828f9ca8a69a8d807366594d4033261a0d0013202c3946535f6c79868c8c8c8c8c8c929ca8b4a89c918c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c807366594d4033261a101d2a3643505c6976838f9ca9b0a4978a7d7164574a3e3124170b000006121e2b37434f5b66727d88939c9f948a817a7571706f7072777d86909aa2978c8175695d5145392c20140700000000000000010d1a26323f4b57636f7b8894a0acaea2968a7e73675c51463b30261b120900000000000000000000000000000009121c26313b47525d6975818c98a4b0a89c9084786b5f53473b2e22160900000000000000000000000006111d2935414d5864707c8894a0aba094887c70646874808c98a4a094887c7064584d4135291d1105000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000000000040f1a26313c47525c67727c8791978e847a71686058504d545b62686d7276797b7d7e8080807e7d7b7875706b655f58514a5159626a737c868f988e84796f645a4f44392e23170c010000000008141f2a343d454b4e4e4e4e4e4e4e4e5763707d8a97a4978a7d7063574e4e4e4e4e4e4e4e4c5965727f8c999e92857d89959c9084786c6055493d313c48545f6b77838f9b968a7e85929e988b7e7165584b3e3225180b0007131e29343e464d52535353535353535353514b443b31261b0f03000000000a16212c3740484f525353535353535353514c443b31261b10040008141f2a353f474e52535353535353535353504a43392f24190d02000a15212c3640484f525353535353535353514b443b31261b0f030013202c3946535f6c798693a0acaca09386796c5f5346392c20242e374049525b656e77808a939ca5a69d948a81786f665d534a41382f261d140b020000000000000000000000000000000000000000000000000000010d1824303c48535f6b77838e9aa6a69a8e82766a5e6874808c98a3aa9e92877b6f63574b4034281c100400000000000000000000000000000000000013202c3946535f6c798693a0aca194887b6e616975818d99a5a4988c8074685c5145392d211516212d3945515d6975818d99a5a094887c70646875828f9ca8a69a8d807366594d4033261a0d0013202c3946535f6c797f7f7f7f7f7f808d9aa6b2a6998c7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7366594d4033261a121e2b3844515e6a7784909daaafa396897c7063564a3d3023170a0000020e1a26323e4a55606b76818a949c9c938b85817e7c7c7d7f83888f98a19990867b7064594d4135291d10040000000000000004101d2935424e5a6773808c98a4b0aa9e92867a6e62564b3f34291e140a00000000000000000000000000000000000a141f2a35414c5864707c8894a0acaca094887b6f63574a3e3225190d0000000000000000000000000a16222e3a46515d6975818d98a4a89c9084786c6064707c8894a0a5998d8175695d5145392d22160a000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e1205000000000000000000000000000009141f2a35404b55606a757f8993968d837a726a615a524c50575c6166696c6f717273737372706e6c6864605a544e4d545c636b747c858e9890867c72685d53483d32271c110600000000000d1925303b464f565a5b5b5b5b5b5b5b5b63707d8a97a4978a7d70635b5b5b5b5b5b5b5b5b585965727f8c999f9285818d99978b8073685c5044382c37434f5b67727e8a969a8e8285929e988b7e7165584b3e3225180b00020d18222c353c424546464646464646464644403a32291f140a000000000005101a252e373e4346464646464646464644403a32291f150a0000030e19232d353d4245464646464646464646443f3931271d13080000040f1a242e363d4346464646464646464644403a32291f140a000013202c3946535f6c798693a0acaca09386796c5f5346392c201b252e374049535c656e77818a939ca6a59c938a81786f655c534a41382f261d140a01000000000000000000000000000000000000000000000000000008141f2b37434f5a66727e8a95a1ab9f93877b6f636c7884909ca8a59a8e82766a5e52473b2f23170b0000000000000000000000000000000000000013202c3946535f6c798693a0aca194887b6e626e7a86929ea99f93887b7064584c4034281c10111d2935414d5965717c8894a0a4998d8175696875828f9ca8a69a8d807366594d4033261a0d00121f2b3844515d6871727272727273808d9aa6b2a6998c7f72727272727272727272727272727272726d63574b3f32251914202d3946535f6c7885929eabaea195887b6f6255493c2f2216090000000a16222d39444f5a646f78828a92999d96918d8b89898a8b8e93999d9790877e74695e53483c3025190d000000000000000006131f2c3845515e6a76838f9ba8b2a69a8e8275695d51463a2e23180d020000000000000000000000000000000000030e1924303c48535f6c7884909ca9b0a4988b7f73665a4d4135281c0f0300000000000000000000030f1b27333e4a56626e7a86919da9a4988c8074685b606c7884909ca89d9185796e62564a3e32261a0e020000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e12050000000000000000000000000000030e19242f39444e59636d77818a94958d847b736c645d56504b5155595d606264656666666564625f5c58544f4c52585f666d757d868e9791887e746a60564c41362c21160b000000000000101d2935414d586167686868686868686868707d8a97a4978a7d7068686868686868686868635a65727f8c999f938686929e92877b6f63574b3f3328333e4a56626e7985919d938785929e988b7e7165584b3e3225180b000006101a232a31363939393939393939393938342f2820170d0300000000000009131c252c323739393939393939393938342f2820170d0300000007111b232b31363939393939393939393937342e271f150c0100000008121c242c323639393939393939393938342f2820170d03000013202c3946535f6c798693a0acaca09386796c5f5346392c20131c252e37414a535c656f78818a949da6a59c938a81776e655c534a41382f261c130a0100000000000000000000000000000000000000000000000000030f1b26323e4a56616d7985919ca8a3978b7f7367717c8995a1aca195897d71655a4e42362a1e13070000000000000000000000000000000000000013202c3946535f6c798693a0aca194887b6e67727e8a96a2a79b8f83776b5f53473b3024180c0d1924303c4854606c7884909ca89d9185796d6875828f9ca8a69a8d807366594d4033261a0d00101c2834404c565f65656565656673808d9aa6b2a6998c7f7265656565656565656565656565656565635b51463b2f231616232f3c4855616e7a8794a0adaca093867a6d6054473a2e21140800000005111c27333e48535d666f7880878e93979b9997969696989b9a96928c857e756c62584d42372b20140800000000000000000915222e3b4754606d7986929fabafa3968a7e7165594d4135291d12060000000000000000000000000000000000000008131f2b37434f5c6874818d99a6b2a79b8f8276695d5044372b1e1205000000000000000000000814202b37434f5b67737e8a96a2aca094887b6f63575c6874808c98a4a2968a7e72665a4e43372b1f13070000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000000000000007121d27323c47515b656e78818a94968e857d766f68615b56504c4d515356575959595958575553504c4d52575d6369707880878f9891887f756c62584e443a2f251a0f05000000000000121f2c3845515e6973757575757575757575757d8a97a4978a7d75757575757575757575746c6165727f8c99a3978f8f979a8e82766a5e52463b2f232e3945515d6975818c98988f8f96a1988b7e7165584b3e3225180b0000000811192025292c2c2c2c2c2c2c2c2c2c2b28241d160e0500000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2b28241e160e05000000000009111920262a2c2c2c2c2c2c2c2c2c2c2b28231c150d0300000000000a121a21262a2c2c2c2c2c2c2c2c2c2b28241d160e0500000013202c3946535f6c798693a0acaca09386796c5f5346392c2013131c252f38414a535d666f78818b949da6a59c938a81776e655c534a41382e251c130a01000000000000000000000000000000000000000000000000000a16212d3945515d6874808c98a3a79b8f83776b75818d99a5a89c9084786c6155493d31251a0e020000000000000000000000000000000000000013202c3946535f6c798693a0aca194887b6e6b77838f9ba7a2968a7e72675b4f43372b1f13070814202c3844505c6773808b97a3a2968a7e726875828f9ca8a69a8d807366594d4033261a0d000c18242f3a444d5458595959596673808d9aa6b2a6998c7f726559595959595959595959595959595957514940352a1e131a26323f4b5764707d8996a2afaa9e9185786b5f5246392c201306000000000b16212c37414b545d666e767c82878b8e909293939291908d8a86817a736c635a50463b30251a0f0300000000000000000b1824313d4a56636f7c8995a1aeaca093877a6e6255493d3125190d0100000000000000000000000000000000000000030f1b27333f4c5864717d8a96a3afaa9e9185786c5f53463a2d211407000000000000000000010d1824303c48545f6b77838f9ba7a79b8f83776b5f5357636f7c8894a0a69a8f83776b5f53473b2f23170c0000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e1205000000000000000000000000000000010b16202b353f49535c666f78818a92978f888179736d67615c5853504d4a4b4c4c4c4c4c4a4b4d5154595d62686e747b828a919890887f766d635a50463c32281e13080000000000000013202c3946535f6c7982828282828282828282828a97a4978a82828282828282828282827d706365727f8c99a6a19b9ba095897d71655a4e42362a1e2935404c5864707b87939f9b9ba0a5988b7e7165584b3e3225180b00000000070e14191d1f2020202020202020201f1c18120c04000000000000000000010910161a1e1f20202020202020201f1c18130c0500000000000000070f151a1d1f2020202020202020201e1c17120b03000000000000000810161a1e1f20202020202020201f1c18120c040000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130a131d262f38414b545d666f78828b949da7a59c938a80776e655c534a40372e251c130a0000000000000000000000000000000000000000000000000005111d2834404c58636f7b87939faaa094887b6f7985919da9a3978b8074685c5044382d211509000000000000000000000000000000000000000013202c3946535f6c798693a0aca194887b6e707c88939fa99e92867a6e62564a3e32261b0f0304101b27333f4b57636f7b87939fa69a8e82766a75828f9ca8a69a8d807366594d4033261a0d0007131e28323b43484b4c4c4d596673808d9aa6b2a6998c7f7265594c4c4c4c4c4c4c4c4c4c4c4c4c4c4a463f372e2319121e2a36424e5b6773808c98a5b1a89b8f8276695d5044372a1e11050000000005101a252f39424b545c646b71767b7f8284858686868583817e7a756f69625a51483e342a1f14090000000000000000000d1926333f4c5865727e8b97a4b1aa9d9084776b5f5246392d2115080000000000000000000000000000000000000000000b1724303c4955626e7b8794a0adada094877b6e6255483c2f23160900000000000000000005111d2935414d5864707c8894a0aba3978b7f73675b4f535f6b7784909ca89f93877b6f63584c4034281c100400000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e120500000000000000000000000000000000040e19232d37414a545d666f7881899198928b847e78726d6864605c595755545353535456575a5d6165696e737980868d94968f877e766d645b51483e342b20160c010000000000000013202c3946535f6c79868e8e8e8e8e8e8e8e8e8e929ba79b928e8e8e8e8e8e8e8e8e8e8a7d706365727f8c99a6aca8a89c9084786d6155493d31251a24303c48535f6b77838e9aa6a8aba5988b7e7165584b3e3225180b000000000003090d111213131313131313131312100c0701000000000000000000000000050a0e1113131313131313131312100c070100000000000000000004090e1113131313131313131313120f0b0600000000000000000000040a0e1113131313131313131312100c0701000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060b141d262f39424b545d666f79828b959ea7a59c928980776e655c524940372e251c1208000000000000000000000000000000000000000000000000000c18242f3b47535f6b76828e9aa6a4988c80737d8995a1aa9e92877b6f63574b3f34281c1004000000000000000000000000000000000000000013202c3946535f6c798693a0aca194877a6e74808c98a4a5998d8175695d51463a2e22160a00000b17232f3b47535f6a76828e9aa69f93877b6f75828f9ca8a69a8d807366594d4033261a0d00010c16202931383c3f3f404d596673808d9aa6b2a6998c7f7265594c3f3f3f3f3f3f3f3f3f3f3f3f3f3e3a352e251c1218232f3a46525e6a77838f9ba8b1a5988c8073675a4e4135281c0f03000000000009131d273039424b525960666b6f72757778797979787674716e69645e5750483f362c22180d030000000000000000000e1b2834414e5a6774818d9aa6b3a79b8e8275685c4f43362a1e11050000000000000000000000000000000000000000000814212d3a46535f6c7885929eabafa396897d7063574a3d3124180b0000000000000000000a16222e3a45515d6975818d98a4aa9e92867a6e62564b4f5b6773808b98a4a4988c8074685c5044382d21150900000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000103050815212e3b4854616e7b8894a1aeab9e9285786b5e5145382b1e1205050300000000000000000000000000000007111b252f38424b545d666e777f878e95968f89837e78746f6c6866636261605f6061626466696d71757a7f858b9198938c847c746c645b52493f362c23190f04000000000000000013202c3946535f6c7986939b9b9b9b9b9b9b9b9b9da0a0a09d9b9b9b9b9b9b9b9b9b968a7d706365727f8c99a0a0a0a0978b8074685c5044382d21151f2b37434e5a66727e8a95a0a0a0a0988b7e7165584b3e3225180b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306020b141d263039424b545d677079838c959ea7a49b928980776e645b524940372e241a0f0400000000000000000000000000000000000000000000000007131f2b36424e5a66717d8995a1a89c908477818d99a5a5998e82766a5e52473b2f23170b00000000000000000000000000000000000000000013202c3946535f6c798693a0aca194877a6d7884909ca8a094897c7165594d4135291d1106000007121e2a36424e5a66727e8a96a2a3978b807375828f9ca8a69a8d807366594d4033261a0d0000050e171f262c303233404d596673808d9aa6b2a6998c7f7265594c3f323232323232323232323232312e2a231c13141e2934404b57636f7b87939fabaea295897d7064574b3f3226190d000000000000010b151e27303940484e555a5f6366696a6c6c6c6c6b6a6865625d59534d463e362d241a100600000000000000000000101c2936434f5c6975828f9ba8b2a6998c8073665a4d4134271b0e0200000000000000000000000000000000000000000005121e2b3744515d6a7783909da9b1a4988b7e7265584c3f3226190c0000000000000000030f1b27323e4a56626e7a85919da9a59a8e82766a5e52464b57636f7b8793a0a89c9085786d6155493d3125190d02000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acada09386796d6053463a2d20130b0b0b0b0b0a09060200000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0acaca09386796d6053463a2d20130d0803000000000000000000040a0e15212e3b4854616e7b8894a1acaa9e9184776a5d5144372a1e11000000000004090d10121215212e3b4854616e7b8894a1acab9e9285786b5e5145382b1e121211100c08020000000000000000000000000009131d263039424b545c656d747c838a9197948f8984807c787572706e6d6d6c6d6d6f717376797d81868b9096968f89817a726b625a524940372d241a110700000000000000000013202c3946535f6c7986939393939393939393939393939393939393939393939393938a7d706365727f8c939393939393877b6f63574b4034281c101a26323e4a56616d79859193939393938b7e7165584b3e3225180b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010407090b0d0e1011111212121111100f0e0d0b09070402000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600020b141e273039424b555e677079838c959ea8a49b928980766d645b524940362c211509000000000000000000000000000000000000000000000000020e1a26323d4955616d7884909ca8a094877b85919da9a195897d7165594e42362a1e120700000000000000000000000000000000000000000013202c3946535f6c798693a0aca094877a707c8894a0a89c9084786c6054483c3125190d010000020e1a26323e4a56616d7985919da89c90847775828f9ca8a69a8d807366594d4033261a0d000000050d151b20242633404d596673808d9aa6b2a6998c7f7265594c3f32262626262626262626262625221e1811121c25303a45515c68737f8b97a3afaa9e9285796d6154483c2f23160a00000000000000030c151e272f363d43494e53575a5c5e5f5f5f5f5e5d5b5955524d47423b342c241b12080000000000000000000000111e2a3744505d6a7783909da9b1a4978b7e7165584b3f3225190c0000000000000000000000000000000000000000000003101c2936424f5c6875828f9ba8b3a6998c8073665a4d4033271a0d000000000000000008141f2b37434f5b67727e8a96a2ada195897d7165594d4147535f6b77838f9ba7a195897d7165594d42362a1e1206000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d20130700000000000005080a0b0b0b0b0b15212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c798693a0a7a7a09386796d6053463a2d201717171717171715120e08010000000815212e3b4854616e7b8894a1a7a79e9184776a5d5144372a1e110013202c3946535f6c798693a0a0a0a09386796d6053463a2d201c19140e08010000000000020910151a1d212e3b4854616e7b8894a0a0a09e9184776a5d5144372a1e1100000000080f15191d1e1e1e212e3b4854616e7b8894a0a0a09e9285786b5e5145382b1e1e1e1e1c19140d06000000000000000000000000010b141e273039424a535b636a727980868c929895908c8885817e7d7b7a7979797a7b7d808285898d919696918b847e7770686159514840372e251b12080000000000000000000013202c3946535f6c798686868686868686868686868686868686868686868686868686867d706365727f8686868686868682766a5e53473b2f23170b16212d3945515d687480868686868686867e7165584b3e3225180b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003070b0e111316181a1b1c1d1e1e1e1e1e1e1d1c1b19181613110e0b0804010000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0a0a0a09386796c5f5346392c2013060000020c151e27303a434c555e67717a838c959fa0a09b928980766d645b52483d32261a0e010000000000000000000000000000000000000000000000000915212d3944505c6874808b97a3a3978b7f8995a1a89c9084786c6155493d31251a0e0200000000000000000000000000000000000000000013202c3946535f6c798693a0aca093867974808c98a4a3978b8073675c5044382c201408000000000915212d3945515d6975818d99a5a094887b75828e9ba8a69a8d807366594d4033261a0d00000000030a10141a2633404d596673808d9aa6b2a6998c7f7265594c3f3226191919191919191919191816120d141c242d37424c57626d7984909ca7b1a5998d8275695d5145382c2013070000000000000000030c151d242b32383e42474a4d4f515253535352504f4c4945413c363029221a1209000000000000000000000000121e2b3845515e6b7784919eaab0a3968a7d7063574a3d3124170b00000000000000000000000000000000000000000000000e1b2834414e5b6774818e9aa7b4a79a8e8174675b4e4134281b0e00000000000000010c1824303c48545f6b77838f9ba7a89c9085786d6155493d434f5b67737f8b97a3a59a8e82766a5e52463a2e22170b000000000000000013202c3946535f6c798693a0a7a7a09386796d6053463a2d20130700000000050c111417171717171717212e3b4854616e7b8894a1a7a79e9184776a5d5144372a1e110013202c3946535f6c7986939a9a9a9a9386796d6053463a2d2224242424242424221e19130c0400000815212e3b4854616e7b88949a9a9a9a9184776a5d5144372a1e110013202c3946535f6c798693939393939386796d6053463a2d2b29251f19120c05000000060d141b2126292b2e3b4854616e7b8893939393939184776a5d5144372a1e110000000912192025292b2b2b2b2e3b4854616e7b8893939393939285786b5e5145382b2b2b2b2b28241f181007000000000000000000000000020c151e2730384149515860676e757b81878c91969894918e8b89888786868687888a8c8f92959994908b858079736c655e564f473f362e251c13090000000000000000000000131f2c3946525f6b76797979797979797979797979797979797979797979797979797979786e62657179797979797979797971665a4e42362a1e1307111d2834404c58636f7979797979797979797064574b3e3125180b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002070b0f13171a1d2022242628292a2b2b2b2b2b2a2a2927262422201d1b1814110d0905000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693939393939386796c5f5346392c201306000000030c151e27313a434c555f68717a838d9393939393928980766d645a4e42362a1d110400000000000000000000000000000000000000000000000005101c2834404b57636f7b87929ea79b8f878d99a5a3978b8073685c5044382c2115090000000000000000000000000000000000000000000013202c3946535f6c798693a0aca09386797884909ca89e93877b6f63574b3f33271c10040000000005111d2935414d5864707c8894a0a4988c8075828e9ba8a69a8d807366594d4033261a0d000000000000040d1a2633404d596673808d9aa6b2a6998c7f7265594c3f3226190c0c0c0c0c0c0c0c0c0b0d12181e252d364049535e68737e8a95a1acaca095897d7165594d4135291c1004000000000000000000030b131a21272d32363b3e41434445464646454442403d3935302b251f18100800000000000000000000000000121f2c3945525f6b7885929fabafa296897c6f6256493c3023160900000000000000000000000000000000000000000000000d1a2733404d5a6673808d9aa6b3a89b8e8275685b4f4235281c0f0000000000000005111d2935414c5864707c88949faba4988c8074685c5044383f4b57636f7b87939faa9e92867a6e63574b3f33271b0f030000000000000013202c3946535f6c7986939a9a9a9a9386796d6053463a2d2013070000020910171c2123242424242424232e3b4854616e7b88949a9a9a9a9184776a5d5144372a1e110013202c3946535f6c79868d8d8d8d8d8d86796d6053463a2d2e303131313131302e2a241d160f07000815212e3b4854616e7b888d8d8d8d8d8d84776a5d5144372a1e110013202c3946535f6c798686868686868686796d6053463a383835312a241d17100a030a11181e252c323638383b4854616e7b8686868686868684776a5d5144372a1e11000008121b242b313538383838383b4854616e7b8686868686868685786b5e514538383838383735302a221a1006000000000000000000000000030c151e262f373f474e555c636970757b81858a8e92959898969494939393949596999794918d89847f7a746e68615a534c453d352d241c130a010000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c675d5f686c6c6c6c6c6c6c6c6c686055493d31261a0e020c18242f3b47535e676c6c6c6c6c6c6c6c6c685e53483c2f23160a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003080e12171b1f23272a2c2f313334363737383838383736353433312f2c2a2724211d1915100c0702000000000000000000000000000000000000000000000000000000000013202c3946535f6c798686868686868686796c5f5346392c20130600000000030c151f28313a434d565f68717a84868686868686868680766a5e5145382b1f1205000000000000000000000000000000000000000000000000000c17232f3b47525e6a76828e99a5a19893969fa99e92867a6f63574b3f34281c10040000000000000000000000000000000000000000000013202c3946535f6c798693a0aca09386797c8894a0a69a8e82766a5e52473b2f23170b0000000000000c1824303c4854606c7884909ca89c908377818e9ba7a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f7265594c3f3226190c0b0b0c0c0d0e101316191e232930374048525b656f7a85909ba6b2a79b9084786c6155493d3125190c000000000000000000000001080f161c21262a2e313436383939393938373533302d2925201a140d060000000000000000000000000000131f2c3946525f6c7986929facaea295887b6f6255483c2f22150900000000000000000000000000000000000000000000000d192633404c596673808c99a6b2a89c8f8275685c4f4236291c0f000000000000000a16222e3945515d6975818c98a4ab9f93877b6f64584c40343a46535f6b77838f9ba7a3978b7f73675b4f43382c2014080000000000000013202c3946535f6c79868d8d8d8d8d8d86796d6053463a2d20130700050c131b22282d303131313131312f2e3b4854616e7b888d8d8d8d8d8d84776a5d5144372a1e110013202c3946535f6c798181818181818181796d6053463a363a3d3e3e3e3e3e3d3a362f282019120b0815212e3b4854616e7b8181818181818181776a5d5144372a1e1100131f2c3946525f6b767979797979797979766b5f5346454544413c352f28221b150e151c222930373d424545454754606d77797979797979797975695d5044372a1d1100040f1a242d363d424445454545454754606d777979797979797979756a5e5144454545454544413b342c22180d02000000000000000000000000030c141d252d353c444b52585e646a7075797e8285888b8d8f919292929292908f8d8a8884817c78736e69635d565049423a332b231b120a010000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5c55565d5f5f5f5f5f5f5f5f5f5d574e43382d2115090007131f2b36414c555c5f5f5f5f5f5f5f5f5f5c564d42372b1f130700000000000000000000000000000000000000000000000000000000000000000000000000000000000002080e14191e23272c2f3336393b3e3f4142434445454544444342413f3d3b393633302d2925211c18130e0802000000000000000000000000000000000000000000000000000000131f2c3946525f6b767979797979797979766b5f5246392c1f13060000000000030d161f28313a444d565f687279797979797979797979766a5e5145382b1f12050000000000000000000000000000000000000000000000000007131e2a36424e5965717d8994a0aaa3a0a2a8a5998e82766a5e52463b2f23170b000000000000000000000000000000000000000000000013202c3946535f6c798693a0ac9f928679808c98a4a195897d72665a4e42362a1e12060000000000000814202c38444f5b6773808b97a3a093877b818d9aa7a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f7265594c3f32261918181818191a1b1d1f22252a2e343a4249525a646d77818c96a1acaca0958a7e73675c5044382c20140800000000000000000000000000040a10151a1e2225282a2b2c2c2c2c2c2a292724211d19140e090200000000000000000000000000000013202c3946535f6c798693a0acaea295887b6e6155483b2e22150800000000000000000000000000000000000000000000000c1926323f4c5965727f8c99a6b2a99c8f8275695c4f4236291c0f000000000000030f1b27323e4a56626e7985919da9a79b8f83776b5f53473b2f36424e5a66737e8b97a3a79b8f84786c6054483c3024180c0100000000000013202c3946535f6c798181818181818181796d6053463a2d201307080f161e252c33393c3e3e3e3e3e3d3c383b4854616e7b8181818181818181776a5d5144372a1e1100121f2c3845515d6972737373737373737372695e51453941464a4a4a4a4a4a4a46413a322b241c150e14202d3a46535f6a72737373737373737371675b4f43362a1d1000111e2a37434f5a646b6c6c6c6c6c6c6c6c6b645a51515151514d47403a332d2620191f262d343b42484e51515151515b656c6c6c6c6c6c6c6c6c6a63584d4135281c0f000a15212b363f474e5151515151514f505b656c6c6c6c6c6c6c6c6c6b63594e505151515151514d463e34291e130700000000000000000000000000020b131b232b323940474d53595f64696d7275797c7e81838485868686858482817e7b7874706c67625d57524b453e3730292119110900000000000000000000000000000a16212c3740484f5253535353535353535353535353535353535353535353535353535353504a4c51535353535353535353514c453c32271c100400020e1a25303a434b50535353535353535353504b443b30261a0f030000000000000000000000000000000000000000000000000000000000000000000000000000000000060d13191f252a2f33383c3f4245484a4c4e4f50515151515151504f4e4c4a484543403d3935312d28231e19130e080100000000000000000000000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6b645a4f43372a1e1105000000000000040d161f28323b444d5660686c6c6c6c6c6c6c6c6c6c6b64594e4236291d100400000000000000000000000000000000000000000000000000020e1a25313d4955606c7884909ca0a0a0a0a0a095897d7165594e42362a1e1207000000000000000000000000000000000000000000000013202c3946535f6c798693a0ac9f92857984909ca89d9185796d6155493d31261a0e02000000000000030f1b27333f4b57636f7b87939fa3978b7e808d9aa6a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f7265594c3f32262525252525262628292b2e32363a3f454c535b646c757f89939ea8afa59a8f84796d62564b3f34281c1004000000000000000000000000000000050a0e1216191b1d1e1f2020201f1e1c1a1815110d0803000000000000000000000000000000000013202c3946535f6c7986929facaea295887b6e6155483b2f22150800000000000000000000000000000000000000000000000d1926333f4c5966727f8c99a6b2a99c8f8275695c4f4236291c0f00000000000008141f2b37434f5b66727e8a96a2aea2968a7e72665a4f43372b323e4a56626e7a87939faba094887c7064584d4135291d1105000000000000121f2c3845515d6972737373737373737372695e5145392c1f130b121a212830373e45494a4a4a4a4a4a48433c46535f6a72737373737373737371675b4f43362a1d1000101c2935414c57606667676767676767676660574d41424b5256575757575756524b443d352e271f18121e2a36424e5861666767676767676767655f554a3f33271b0e000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5c5e5e5e5e5e5d58524b453e38312b242a31383f464c535a5e5e5e5e5e5e5b5f5f5f5f5f5f5f5f5f5e5951473c3025190c000e1a26323d4851595e5e5e5e5e5e5b55535b5f5f5f5f5f5f5f5f5f5e5951575c5e5e5e5e5e5d5850463b3024180c00000000000000000000000000000109111920272e353c42484e53585d6165696d6f727476777879797978777574716f6c6864605c57524c46403a332c251e170f0700000000000000000000000000000005101a252e373e434646464646464646464646464646464646464646464646464646464646443f404446464646464646464645413a332a20150b00000008131e283139404446464646464646464644403a32291f140900000000000000000000000000000000000000000000000000000000000000000000000000000000030a11181e252b30363b3f44484b4f525457595a5c5d5e5e5e5e5e5d5d5c5a595754524f4c4945413d39342f2a251f19130c060000000000000000000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5a52483e32261a0e0200000000000000040d162029323b444e565d5f5f5f5f5f5f5f5f5f5f5f5a52483d31261a0e0100000000000000000000000000000000000000000000000000000915212c3844505c67737f8b939393939393939084786c6055493d3125190e02000000000000000000000000000000000000000000000013202c3946535f6c798693a0ab9f92857b8794a0a4988c8174685d5145392d21150900000000000000000b17232f3b47525e6a76828e9aa69b8e82808c99a6a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f7265594c3f3232323232323232333436383b3e42464b51575e656d757e88919ba5afa89e93887d73675c51453a2e23170b0000000000000000000000000000000000000206090c0e1012131313131211100e0b08050100000000000000000000000000000000000000131f2c3946525f6c7986929facafa295887b6f6255493c2f22160900000000000000000000000000000000000000000000000d1a2633404d596673808c99a6b3a89c8f8275685b4f4235281c0f0000000000010c1824303c48535f6b77838f9ba6a99d92867a6e62564a3e32262e3a46525e6a76828e9ba7a5998d8175695d5145392d22160a000000000000101c2935414c57606667676767676767676660574d4135291d10151d242b333a41495055575757575757544e46424e5861666767676767676767655f554a3f33271b0e000d1924303b454e55595a5a5a5a5a5a5a5a59554e453f4a545d636464646464635d564e474038312a231b1a26313c464f565a5a5a5a5a5a5a5a5a59544d43392e22170b000a16212c3740484f5253535353535353545f676b6b6b6b6b6a635d565049433c352f353c434a50575e656a6b6b6b6b6b665d5353535353535353524e473f352a1f140800111e2a36424e59636a6b6b6b6b6b67605a5352535353535353535352545b61686b6b6b6b6b6962574c4034281b0f00000000000000000000000000000000070e161d242a31373c42474c5155595d60636668696b6b6c6c6c6b6a696765625f5c5854504b46413b352f28221b140c05000000000000000000000000000000000009131c252c32373939393939393939393939393939393939393939393939393939393939373434383939393939393939393835302921180e04000000020c161f272e343839393939393939393938342f2820170d02000000000000000000000000000000000000000000000000000000000000000000000000000000050d151c232930363c41464b5054585b5e61636567686a6a6b6b6b6b6a6968676563615e5c5855514d4945403b36302a241e17110a03000000000000000000000000000000000000000000000a16212c3740484f525353535353535353524f4840372c21160a000000000000000000040e172029323c444c5153535353535353535353524e4840362b20150900000000000000000000000000000000000000000000000000000004101c28333f4b57636e7a8686868686868686867f73675c5044382c21150900000000000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e92857e8b97a3a094887c7064584c4034281c1105000000000000000006121e2a36424e5a66727e8a96a29e92867f8c98a5a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f7265594c3f3e3e3e3e3e3e3f3f40414345474a4e52575c626870777f88919aa3adaaa0968c81776c61564b4034291e12060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000121f2c3845525f6b7885929eabafa296897c6f6356493d3023160a00000000000000000000000000000000000000000000000e1b2734414d5a6773818d9aa6b3a89b8e8175685b4e4235281b0f000000000005111d2935404c5864707c88949faba5998d8175695d51453a2e222a36424e5a66727e8a96a2a99d9185796d62564a3e32261a0e0200000000000d1924303b454e55595a5a5a5a5a5a5a5a59554e453b3025191920272e363d444c535a6164646464646460584e43464f565a5a5a5a5a5a5a5a5a59544d43392e22170b0008131e29333c444a4d4d4d4d4d4d4d4d4d4d4a443c434f5b666f71717171716f676059524a433c342d261e202a343d454a4d4d4d4d4d4d4d4d4d4c49433b31271d11060005101a252e373e43464646464646464c5865707878787878756e68615b544e47403a40474d545b6269707678787878776e62564946464646464645423d352d23190e0300131f2c3945525e6b757878787878726b645e57514a464646464a51585f656c73787878787874685c5043362a1d100000000000000000000000000000000000040b12191f252b31373c4145494d515457595b5d5e5f5f5f5f5f5e5c5a585653504c48443f3a35302a241d17100902000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b28282b2c2c2c2c2c2c2c2c2c2b29241e170f060000000000040d151d23282b2c2c2c2c2c2c2c2c2c2b28231d160e05000000000000000000000000000000000000000000000000000000000000000000000000000000070f171f262d343b41474d52575c6064676b6d707274757677777878777776757372706d6b6865615d5955504c47413b352f29221b140d0500000000000000000000000000000000000000000005101a252e373e4346464646464646464646433e372e251a100500000000000000000000050e17202a323a40444646464646464646464645433d362e241a0f04000000000000000000000000000000000000000000000000000000000b17232f3a46525e6a75797979797979797979786e63574b3f33281c100400000000000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9184828f9ba79b8f83776b5f53483c3024180c000000000000000000020e1a26323e4955616d7985919da295897e8b98a5a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f7265594c4b4b4b4b4b4b4b4b4c4d4e4f5154565a5e62676d737a8189919aa3acaaa1988e847a70655a50453a2e23180c010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111e2b3844515e6b7784919daab0a3978a7d7064574a3e3124180b00000000000000000000000000000000000000000000020f1c2835424f5b6875818e9ba7b3a69a8d8174675a4d4134271b0e00000000000a16222e3945515d6975818c98a4aca094887c7165594d4135291d26323e4a56626e7a86929eaaa2968a7e72665a4e42372b1f1307000000000008131e29333c444a4d4d4d4d4d4d4d4d4d4d4a443c33291f1c232a323940484f565e656c7171717171706a5f54473d454a4d4d4d4d4d4d4d4d4d4c49433b31271d110600020d17212a32393d404040404040404040403e393845515e6b777d7d7d7d7d79726b635c554d463f37302922222b33393e404040404040404040403d3831291f160b00000009131c252c3237393939393939404c59667380858585858079736c665f58524b454b51585f666d747a81858585857d7063574a3d39393939393936312b231b1107000013202c3946535f6c7985858585837c766f69625c554f48474e555c626970777e8585858584776a5d5044372a1d1100000000000000000000000000000000000000070e141a20262b3035393d4144474a4c4e5051525253525251504e4c494743403c38332f29241e19120c05000000000000000000000000000000000000000000010910161a1e1f202020202020202020202020202020202020202020202020202020201e1c1c1f2020202020202020201f1c18130d0500000000000000040b12171c1f2020202020202020201f1c18120c04000000000000000000000000000000000000000000000000000000000000000000000000000000081119212931383f464c53585e63686c7074777a7c7e8182838484858584848382817e7c7a7774716d6a65615c57524c47413a342d261f17100800000000000000000000000000000000000000000009131c252c32373939393939393939393937322c251c1309000000000000000000000000050e1820292f3538393939393939393939393936322c241b1208000000000000000000000000000000000000000000000000000000000006121e2a36414d58636a6c6c6c6c6c6c6c6c6c6c675d52463b2f23170b0000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aa9e918486929fa2968a7e73675b4f43372b1f1307000000000000000000000915212d3945515d6975818d99a4998d818a97a4a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f72655958585858585858585859595a5c5e6063666a6e73787e858c939ba3aca9a1988f867c72685e53493e33281d1207000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111d2a3743505d697683909ca9b1a5988b7e7265594c3f33261a0d0000000000000000000000000000000000000000000005111e2a3743505d6976838f9ca9b2a5998c7f7266594c4033261a0d00000000030f1b26323e4a56626d7985919da9a89c9084786c6054483c302519222e3a46525e6a76828e9aa6a69a8f83776b5f53473b2f23170c0000000000020d17212a32393d404040404040404040403e39322a211f262d353c434b525961686f767d7d7d7d7d7c706356493d393e404040404040404040403d3831291f160b000000050f1820272d3133343434343434343433312d3845515e6b78838a8a8a8a847c756e665f585149423b332c2521282e3233343434343434343433312c261f170d04000000010a131a21262a2c2c2c2c2c323f4c5865717a848d92918b847e77716a635d5650555c636a71777e858c92928b82786e6256493d302c2c2c2c2c2a2620191109000000131f2c3945525f6b767f8891928e88817a746d67605a53525960666d747b82898f9290877d74695c5043362a1d10000000000000000000000000000000000000000003090f141a1f24292d3135383b3e4042434445464646454443413f3d3a3734302c27231e19130d0701000000000000000000000000000000000000000000000000050a0e111313131313131313131313131313131313131313131313131313131313120f101213131313131313131312100c080200000000000000000000070c0f1213131313131313131312100c070100000000000000000000000000000000000000000000000000000000000000000000000000000008111a232b333b424a51575e64696f74787c808386898b8d8f90919192929190908e8d8b898784817d7a76716d68635e58524c453f383029211a11090100000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2a26211a130a0100000000000000000000000000060e171e24292b2c2c2c2c2c2c2c2c2c2c2c2a26211a1209000000000000000000000000000000000000000000000000000000000000010d1925313c4751595e5f5f5f5f5f5f5f5f5f5f5c554b41352a1e12060000000000000000000000000000000000000000000000000013202c3946535f6c798693a0ab9f93898b96a29e92867a6e62564a3e32271b0f030000000000000000000005111d2935404c5864707c8894a09c90888d98a4a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f726565656565656565656565656667686a6d6f72767a7f848a90969ea5ada8a0978f867d736a60564c42372c22170c010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2935424f5b6875818e9ba7b3a69a8d8174675a4e4135281c0f030000000000000000000000000000000000000000000714202c3946525f6b7884919eaab0a4978a7e7164584b3e3225180c0000000008131f2b37434f5a66727e8a96a2ada3978b8073675c5044382c20141d2935424e5a66727e8a96a2ab9f93877b6f63584c4034281c10040000000000050f1820272d3133343434343434343433312d2820222931383f474e555c646b727a81888a8a8a877d7063564a3d303233343434343434343433312c261f170d0400000000060e161c212527272727272727272727252a3743505c67717a848d96968e878078716a625b544c453e362f282022252727272727272727272624211b150d050000000000010910161a1e1f20202024303c48545f68717a848d96968f89827b756e68615b60676e757b82899097958c837970675d52463a2e212020201f1d1a150f0700000000111e2a36434e5a646d7680899299928c857f78726b645e5d636a71787f868d939a91877e756b62584c4034281b0f0000000000000000000000000000000000000000000003090e14181d2125282c2e3133353738393939393837363533302e2b2724201c17120d0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008111a232c353d454d545b62696f757a8084888c909395989a9b9c9d9e9e9e9e9d9c9b99989593908d8a86827d79746e69635d575049423b332b231b130a0100000000000000000000000000000000000000010910161a1e1f20202020202020201f1e1a16100901000000000000000000000000000000050c13181c1f202020202020202020201f1e1a150f0800000000000000000000000000000000000000000000000000000000000000000814202b353f474e5253535353535353535353504a43392f24190d020000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca49b95969da5998d8175695d52463a2e22160a0000000000000000000000000c1824303c4854606c7884909ba29994979fa9a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f7271717171717171717171727273747577797c7e82868b90959ba1a8aba59d968e867d746b62584e443a30251b1005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1b2734404d5a6673808c99a5b2a89c8f8276695d5044372b1f12060000000000000000000000000000000000000000000a17232f3c4855616d7a8793a0acaea295897c6f6356493d3023170a000000000c1824303c48535f6b77838f9ba6aa9f93877b6f63574b3f33271b101925313d4956626e7a86929eaaa4988c8074685c5044382d211509000000000000060e161c21252727272727272727272725211e252c343b424a515860676e757d848b939790877e756b6054483c2f252727272727272727272624211b150d05000000000000040b1115181a1a1a1a1a1a1a1a1a1a1b2834404b565f68717b848d9799918a837b746d655e574f48413a322b241c1a1a1a1a1a1a1a1a1a1a1815100a030000000000000000050a0e1113131314202c38434d565f68727b848d969a948d878079736c666b727880868d949b968d837a71675e554b41352a1e13131313110e090400000000000e1a26323d48525b646d768089929b97908a837d766f69676e757c838a90979b91887e756c625950463b3024180c00000000000000000000000000000000000000000000000003080c1115191c1f222527282a2b2c2c2c2c2c2b2a282624211e1b1814100b0601000000000000000000000000000000000000000000000000000000000000000000000000000000040a0e1112131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131312100c080200000000000000000000000002040607070808080807060401000000000000000000000000000000000000000000000007111a232c353e474f575f666d747a80868b9094989c9fa2a4a6a8a9a8a8a7a7a8a8a9a8a6a4a29f9d9996928e8985807a746e68625b544d453d352d251c130a010000000000000000000000000000000000000000050a0e1113131313131313131313110e0a0500000000000000000000000000000000000001070c10121313131313131313131313110e0a04000000000000000000000000000000000000000000000000000000000000000000030e19232d353d424546464646464646464646443f3931271d1308000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada6a2a3a7a095897d7165594d4135291d12060000000000000000000000000814202c37434f5b67737f8b97a3a4a1a2a8b1a69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b2a6998c7f7e7e7e7e7e7e7e7e7e7e7e7e7e8081828486888b8e92979ba1a6aca6a09a938b847c736b625950463c32281e140900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1925323f4b5864717d8a97a3b0aa9e9185786c6053473b2e22160a0000000000000000000000000000000000000000020e1a26333f4b5764707d8996a2afac9f93867a6d6154473b2e22150800000005111d2935404c5864707c88939faba69a8e82766a5e52473b2f23170b15212d3945515d6976828e9aa6a89c9085786d6155493d3125190d01000000000000040b1115181a1a1a1a1a1a1a1a1a1a19212830373e454d545b636a717980878f969a91887e756c62594f44382c201a1a1a1a1a1a1a1a1a1a1815100a0300000000000000000005090c0d0d0d0d0d0d0d0d0d0d17232e39444d565f69727b858e979c958d867e777069615a534b443d352e261d140d0d0d0d0d0d0d0d0b08040000000000000000000000000205060606101b26313b444d576069727b848e979f98918b847e7771767c838a91989f978d847a71685f554c43392f24190d0606060401000000000000000a15212c364049525b646d768089929b9b958e88817a74727980878e949b9b92897f766c635a50473e342a1f130800000000000000000000000000000000000000000000000000000005090c101316181a1c1d1e1f1f201f1f1e1d1b191715120f0b08040000000000000000000000000000000000000000000000000000000000000000000000000000000000080f151a1d1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1c18130d05000000000000000002070c0f11121314151515151412100e0b070200000000000000000000000000000000000000050f19232c353e475059616970787f858c91979ca0a5a8a9a6a3a09e9d9c9b9a9b9b9c9d9ea0a2a4a7a9a6a29e9a95908b86807a736d665e574f473f372e251c1309000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007111b232b3136393939393939393939393937342e271f150c01000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acacacacaca89c9084786c6054483d3125190d01000000000000000000000000030f1b27333f4b57636f7b87939eaaacacacaca69a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b3a79b918b8b8b8b8b8b8b8b8b8b8b8b8b8c8c8d8e909295979b9ea3a7aba6a19b958f88817a726a615950473e342a20160c0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1723303c4955626f7b8894a0adada194887b6f63574b3e32261b0f030000000000000000000000000000000000000007131f2b37434f5b6773808c98a5b1a99d9084776b5e5245392c2013060000000a16222d3945515d6975818c98a4ada1958a7e72665a4e42362a1e1206111d2935414d5965717d8a96a2ada195897d7165594d42362a1e1206000000000000000005090c0d0d0d0d0d0d0d0d101a232b333a414950575f666d747c838b92999a91887e756c635a50473d33271c100d0d0d0d0d0d0d0d0d0b0804000000000000000000000000000000000000000000000007121d28323b444d576069727b858e979f989089827a736c645d564e4740382f251b100500000000000000000000000000000000000000000000000000000a151f29323b454e576069727b858e97a09c968f89827b81878e959ca0978e857b72685f564d433a31271d1308000000000000000000000000040f1a242e374049525b646d778089929ba099938c857f7d848b92989f9c938980766d645b51483f352c22180d020000000000000000000000000000000000000000000000000000000000000306090b0d0f1112121313131211100f0d0b080603000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a121a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b29241e170f06000000000000060d13181b1d1f202121222222211f1d1a17130e090300000000000000000000000000000000020c17212b343e475059626b737b828a90979da2a8aba6a19d99969492908f8e8e8e8e8f90919395989b9ea2a6aaa6a19c97918b857e7770696159514940372e251b110600000000000000000508090a0a0a0a0a0a0a0a0908050000000000000000000000000407090a0a0a0a0a0a0a0a0a08050200000000000000000000000206090a0a0a0a0a0a0a0a0a090603000000000000000000000000000000000000000000000000000000000000000000000009111920262a2c2c2c2c2c2c2c2c2c2c2c2b28231c150d0300000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0a0a0a0a0a0a0978b8074685c5044382c20140800000000000000000000000000000b17232e3a46525e6a76828e9aa0a0a0a0a0a09a8d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6b3ada39b9898989898989898989898989898999a9b9d9fa1a4a7aaa6a39f9a95908a847d766f6860584f473e352c22180e040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000814212e3a46535f6c7885919daab0a4988b7f73675b4f43372b201409000000000000000000000000000000000000020d18242f3b47535f6b7783909ca8b2a69a8d8174685c4f43362a1d11040000030f1a26323e4a56616d7985919da9a99d9185796d6155493d32261a0e020d1925313d4955616d7985929eaaa59a8e82766a5e52463a2e22170b0000000000000000000000000000000000010c17222c353d444c535a626970787f868e959c9b92887f766c635a51483e352c21160b0000000000000000000000000000000000000000000000000000000000000000000000010c162029323b454e576069737c858e98a19b938c857d766f676059524a41372d21160a0000000000000000000000000000000000000000000000000000030d172029333c454e576069727c858e97a0a19a948d878b9299a0a1988e857c726960564d443a31281f150b010000000000000000000000000008121c252e374049525b656e778089939ca49d97908a888f959ca39d938a81776e645b52493f362d231a10060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008121c242c32363839393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393835302921180e04000000000811181f24282a2c2d2e2e2e2e2e2d2c2927231f1a140e0700000000000000000000000000000009141e29333d465059626b747d858d949ba2a8aca59f9a95918d8a878583828181818282838587898b8e92969a9ea3a8a8a29c969089827b736b635b524940372d22170b000000000000060c11141617171717171717171614110c060000000000000000040b10131617171717171717171615120d08010000000000000003090e131516171717171717171615130f090300000000000000000000000000000000000000000000000000000000000000000000070f151a1d1f202020202020202020201e1c17120b030000000000000000000000000000000000000000000000000000000013202c3946535f6c7986939393939393939393877b6f63574b3f33281c1004000000000000000000000000000006121e2a36424e5a66727d8a93939393939393938d807366594d4033261a0d000000000000000d1a2633404d596673808d9aa6acacaca7a5a5a5a5a5a5a5a5a5a5a5a5a5a5a6a7a8a9a7a5a3a09d9a97938e89847e79726c655e564e463d352c231910060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005121e2b3744505c6975828e9aa6b2a79b8f83776b5f53483c31261b100600000000000000000000000000000000000a141f2a35404c58636f7b8793a0acaea2968a7d7165594c4033271b0e02000007131f2b37434f5a66727e8a96a2ada4988c8175695d5145392d211509000915212d3945515d6975818d99a5aa9e92867a6e63574b3f33271b0f030000000000000000000000000000000006121d29343e474f565e656c737b828991989f9b928980766d645a51483f362c231a0f05000000000000000000000000000000000000000000000000000000000000000000000000040e172029333c454e57616a737c868f98a19e978f888179726b635c53493e32261a0e020000000000000000000000000000000000000000000000000000050e17202a333c454e57606a737c858e97a0a59f9894969da4a2988f867c736a60574e443b32281f160d030000000000000000000000000000000a131c252e374049535c656e77818a939ca5a29b959499a0a69d948a81786e655c524940362d241b11080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000407080808080808080808080808080808080808080704000000000000000004101a242e363d4245464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464644413b332a20160b00000007111a222a30343738393a3b3b3b3b3a3836332f2b251f19120a0200000000000000000000000006101b26303a454f58626b757e868f979ea6ada8a19a948f8985817d7b787775747474757576787a7c7f8286898e92979da2a8a8a19b948c857d756d645b52493f33281c1004000000010a11181d2123232323232323232323211d18110a010000000000070f161b2022232323232323232323211e19130c030000000000050d141a1f22232323232323232323221f1a140d050000000000000000000000000000000000000000000000000000000000000000000004090e111313131313131313131313120f0b0600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798686868686868686868682766a5e53473b2f23170b000000000000000000000000000000020e1a26313d4955616d7985868686868686868686807366594d4033261a0d000000000000000d1a2633404d596673808d9aa0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09f9f9e9d9c9a999694918e8a87827d78736d67615a534c443c342b231a11070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030f1b2834414d5965727e8a96a2aeab9f93887c7064594d42372c22180e0500000000000000000000000000000009121c26303b46515d6874808c98a4b0aa9e92867a6e6155493d3024180b0000000c1824303c47535f6b77838f9aa6aca094887c7064584c4034281d11050005101d2935414d5965717d8995a1ada3978b7f73675b4f43372c201408000000000000000000000000000000000916222e3a45505961686f767e858d949ba29b928980766d645b52483f362d241a11080000000000000000000000000000000000000000000000000000000000000000000000000000050e17212a333c454e58616a737c868f98a0a09a928b847c756e655a4f42362a1d1004000000000000000000000000000000000000000000000000000000050e18212a333c454e57616a737c858e97a0a0a0a0a0a0a09990877d746a61584e453c322920160d0400000000000000000000000000000000010a131c252e37414a535c656e77818a939ca0a0a0a0a0a09e948b82786f665c534a40372e241b12090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c10131515151515151515151515151515151515151513100c070000000000000a16212c3640484e525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252514c453c32271c110500030e19232c343b4043454647484848484745423f3b36312a241c140c0300000000000000000000010c17222d37424c57616a747e879098a1a9ada59d968f89837d7975716e6c6a6968676768696a6b6d707376797d82878c91979ea4aba59e978f877f766d645b5044382c1f13060000010a131b23292d2f30303030303030302f2d29231b130a0100000008111921272c2f3030303030303030302e2a241d150d03000000050f171f262b2e3030303030303030302e2b261f170f0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6b76797979797979797979797971665a4e42362a1e1207000000000000000000000000000000000915212d3945515d697479797979797979797979797165594c403326190d000000000000000d1a2633404d596673808d93939393939393939393939393939393939393939291908f8e8c8a8785827e7a76726d68625c564f49413a322a22191108000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1825313d4955626e7a86929eaab0a4988c81756a5f54493e342a20170f08020000000000000000000000040a121b242d38424d58636e7985919ca8b1a69a8e82766a5e5245392d211408000005111d2934404c5864707b87939faba79b8f83776b5f54483c3024180c0200000c1825313d4955616d7985919da9a79b8f84786c6054483c3024180c010000000000000000000000000000000c1825323e4a56616b727a818890979ea09c938980776d645b524940362d241b120800000000000000000000000000000000000000000000000000000000000000000000000000000000050f18212a333c464f58616a747d869093939393938e8780776b5e5145382b1e120500000000000000000000000000000000000000000000000000000000060f18212a333c454e58616a737c858f9393939393939390877e746b62584f463c332a20170e04000000000000000000000000000000000000010a131c252f38414a535c656e78818a93939393939393938c827970665d544a41382e251c120900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a11181c2021222222222222222222222222222222222221201d18120b03000000000e1a26323d48525a5e5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5d574e44392d211509000914202b353e464c505253545455555453514f4b47423c352e261e150c0200000000000000000007121e29343e49545e68727c869099a2aaaca49b938c847e77726d6965625f5d5c5b5b5b5b5c5d5f616366696d71767b80868c939aa1a9a9a199918980766c6054473b2e211508000008121c252d34393c3d3d3d3d3d3d3d3d3c39342d251c1208000005101a232b32383b3d3d3d3d3d3d3d3d3c3a352f271f150b0000020d17212931373b3d3d3d3d3d3d3d3d3d3b37312921170d03000000000000000000000000000000000000000000000000000000000000000003060808080808080808080807050200000000000000000000000000000000000000000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c686055493e32261a0e020000000000000000000000000000000005111d2834404c58626a6c6c6c6c6c6c6c6c6c6c6c686055493d3124180b000000000000000d1a2633404d596673808686868686868686868686868686868686868686868585848381807d7b7875726e6a66615c57514b443e3730282018100700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000915212d3945515d6975818d99a5b0a99d92877b70655a50463c3229211a130e090603020101010204070a0f151c242d363f49545e6974808b96a1adaca195897d71665a4d4135291d110500000a16212d3945515d6974818c98a4aea3978b7e73675b4f43372b1f13110f0b070814202c3845515d6975818d99a5aca094887c7064584d4135291d11050000000000000000000000000000000d1a2633404d5966737d848b9393939393938a81776e655b524940372e241b1209000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f18212a343d464f58626b747d868686868686868685786b5e5145382b1e12050000000000000000000000000000000000000000000000000000000000060f18212a333c464f58616a737c8686868686868686867e756b625950463d342a21180e050000000000000000000000000000000000000000010a131d262f38414a535d666f78818686868686868686837a70675e544b42382f261c130a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2c29231d150c03000000111e2a36434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6960554a3e3125190c000d1a25313c4750585c5e606161616161605e5b57534d47403830271e140a0000000000000000020d18242f3a45505b65707a848e98a2abada39a9289817a736c66615c595553514f4e4e4e4e4f505254575a5d61656a6f757b81888f979fa7aba39a92887b6e6155483b2e22150800030f1a242e373f45494a4a4a4a4a4a4a4a49453f372e241a0f03000c17212c353d44484a4a4a4a4a4a4a4a4946413931271c12060009141f29333b4247494a4a4a4a4a4a4a4947423b33291f1409000000000000000000000000000000000000000000000000000000000000050b10131515151515151515151514120e090300000000000000000000000000000000000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5d574e44382d2115090000000000000000000000000000000000000c1824303b4650595e5f5f5f5f5f5f5f5f5f5f5f5d574e43382d211509000000000000000d192633404c59657179797979797979797979797979797979797979797979797877767473716e6c6966625e5a55504b454039332c251e160e0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005111d2935414d5965717c88949fabaea3988d82776c62584e443b332b241e191512100f0e0d0e0f1113161b20272e363f48515b65707b86919ca7b2a79b9084786d6155493d3125190d0100000e1a26323e4a56616d7985919da1a19e92867a6e62564a3f33271e1e1d1b17120c101c2834404c5865717d8995a1a1a1998d8175695d5145392d2115090000000000000000000000000000000d1a2633404d59667380868686868686868681776e655c534940372e251b12090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f18222b343d475059626b75797979797979797979756a5e5144382b1e1205000000000000000000000000000000000000000000000000000000000000060f18212a343d464f58616a73797979797979797979756c635950473e342b22180f0600000000000000000000000000000000000000000000010b141d262f38414a545d666f7879797979797979797971685e554c423930261d140a01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a141d262e34383b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b39342e271e150a000000131f2c3946525f6b76797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797972665a4d4034271a0e00111d2a36424e5962686b6c6d6e6e6e6e6d6a67635e58524a423930261c11070000000000000007131e2a35404b57616c77828c96a0aaaea49b918880776f68615b55514c4946444242414142434446484a4d5155595e646970767d858d959ea8aca295887b6e6155483b2e221508000814202b3640495155565656565656565655514940362b20140805111d28333d474f54565656565656565656524b43392e23170b020e1a25303b454d53565656565656565656534d453b31261a0e02000000000000000000000000000000000000000000000000000000010910171c1f21222222222222222222211e1a140e06000000000000000000000000000000000000000000000000000000000000000a16212c3740484f525353535353535353535353514c453c32271c110500000000000000000000000000000000000008131f2a343e474e525353535353535353535353514c453c32271c1004000000000000000b1824313d495560686c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6a69686664625f5c5956524e4945403a342e28211b130c0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010d1925313d4854606b77838e99a4afa99e93887e746960564d453d36302a25221f1d1b1a1a1b1c1d2023272c32384048515a636d77828c97a2adaca1968a7f73685c5045392d211509000000111e2a36434e5a66727e8a94949494948e82766a5e52463a2e2b2b2b2a28231e170f1824303c4854606c788591949494949185796d62564a3e3125190c0000000000000000000000000000000d192633404c596571797979797979797979786f665c534a41372e251c130900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061019222b343e475059626a6c6c6c6c6c6c6c6c6c6b63594e4235291d100300000000000000000000000000000000000000000000000000000000000000060f18222b343d464f5861696c6c6c6c6c6c6c6c6c6b635a51483e352c22191006000000000000000000000000000000000000000000000000020b141d262f38424b545d666c6c6c6c6c6c6c6c6c6c685f564c433a30271e140b020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c262f383f454848484848484848484848484848484848484845403930261c1106000013202c3946535f6c79868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868174675a4d4134271a0e00131f2c3945525e6a7477797a7b7b7b7b7977746f6a635c544b42382e23180d020000000000010c18242f3b46515d68737e89939ea8b0a69c92897f766d655e56504a45403d3a3736353434353637393b3e4145494e53585e656c737b838c97a4aea295887b6e6155483b2e221508000c1825313c48525b616363636363636363615b52483c3125180c0915212d39454f59606363636363636363625d554a3f34281c0f06121e2a36424d575f6363636363636363635f574d42372b1f12060000000000000000000000000000000000000000000000000000000a131b22282c2e2e2e2e2e2e2e2e2e2e2d2a261f18100600000000000000000000000000000000000000000000000000000000000005101a252e373e4346464646464646464646464645413a332a20160b00000000000000000000000000000000000000020d18222c353c4245464646464646464646464645413a332a20150b00000000000000000915212d38434e575d5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5e5d5c5b59575553504d4a46423e39342f29231d171009020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000814202c38434f5b66717d88939ea9afa59a90857b72685f574f48413b36322e2b2928272727282a2c2f33373d434a525a626c757f89949ea9b0a59a8f84796e62574b4034281c1005000000131f2c3945525f6b7783888888888888887d7165594d41383838383837342f28211814202c3844505c687481888888888888887e72665a4d4034271a0e0000000000000000000000000000000b1824313d495560686c6c6c6c6c6c6c6c6c6c665d544a41382f251c130a010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071019222c353e4750595e5f5f5f5f5f5f5f5f5f5e5951473d3125190d010000000000000000000000000000000000000000000000000000000000000000061019222b343d464f585e5f5f5f5f5f5f5f5f5f5e5951483f362c231a10070000000000000000000000000000000000000000000000000000020b141d262f39424b545b5f5f5f5f5f5f5f5f5f5f5c564d433a31281e150c0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17222d38424a5154555555555555555555555555555555555554514a42382e23170c000013202c3946535f6c798692929292929292929292929292929292929292929292929292929292929292929292929292929292929292928e8174675a4d4134271a0e0013202c3946535f6c79848687888888878684807b756e665d544a3f352a1f1308000000000005111d2935404c57636e79848f9aa5b0a99e948a80766d645b534c453e3934302d2b2928282828292b2c2f3235393d42474d535a6169717c8996a3aea295887b6e6155483b2e221508000f1b2834414d59646d70707070707070706d64594d4134281b0f0b1824313d4a56616b70707070707070706e675c5044372b1e120815212e3a46535e696f707070707070706f695f53473b2e221508000000000000000000000000000000000000000000000000000008121c252d33383b3b3b3b3b3b3b3b3b3b3a36312a22180f0400000000000000000000000000000000000000000000000000000000000009131c252c32373939393939393939393939393835302921180e04000000000000000000000000000000000000000006111a232b31363939393939393939393939393835302921180e04000000000000000004101c27323c454c5153535353535353535353535353535353535353535353525251504e4d4b494644413d3a36322d28231e18120c05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101b27333e4955606b76828c97a1acaca1978d847a71696159524c47423e3a3836353434343536383b3f43484e555c646c757e87919ba5b0a99e94897e73685c51463a2f23170c0000000013202c3946525f6c777b7b7b7b7b7b7b7b786d61554942444444444443403a332a221a1c2834404c5864707a7b7b7b7b7b7b7b7b73665a4d4134271a0e0000000000000000000000000000000915212d38434e575d5f5f5f5f5f5f5f5f5f5f5b544b42382f261d130a010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007101a232c353e474e52535353535353535353524e483f362b20150900000000000000000000000000000000000000000000000000000000000000000000071019222b343d464d51535353535353535353524e483f362d241a110800000000000000000000000000000000000000000000000000000000020b141d273039424a5052535353535353535353504b443b31281f160c030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1b27333f4a545c616161616161616161616161616161616161615c544a3f34281c10030013202c3946535f6c7986939f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9a8e8174675a4d4134271a0e0013202c3946535f6c798692949495959493908c8680786f665c51463b3025190d02000000000a16222e3a45515d68747f8b96a1acada2978d82786e645b5249413a332d2824211e1c1b1b1b1b1c1e202225292d31363c42484f57636f7c8996a3aea295887b6e6155483b2e22150800101c2936434f5c69757d7d7d7d7d7d7d7d75695c4f4336291c100c1926323f4c5965727c7d7d7d7d7d7d7d786c5f5346392c20130916222f3c4955626f7b7d7d7d7d7d7d7d7b6f6256493c3023160900000000000000000000000000000000000000000000000000040f1a242e373e444748484848484848484846423c342a20160b000000000000000000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2b29241e170f060000000000000000000000000000000000000000000008111920252a2c2c2c2c2c2c2c2c2c2c2c2c2b29241e170f06000000000000000000000b15202a333a4145464646464646464646464646464646464646464646464645444342403e3c3a3734312d2a26211c17120c0701000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a16222d38444f5a65707b85909aa4aea99f968d847b736b645d57524e4a47444341414041424345484b4f545960666e767e879099a3adaba1978c82776c61564b4035291e120700000000111e2b37434f5b656d6e6e6e6e6e6e6e6e6d665c50494f5151515151504b443c342c241c24303c48545f696e6e6e6e6e6e6e6e6e6a61564a3e3225190c00000000000000000000000000000004101c27323c454c5153535353535353535352504a42392f261d140b0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008111a232c353c424546464646464646464645423d362d24190f040000000000000000000000000000000000000000000000000000000000000000000000071019222b343c414546464646464646464645423d362d241b1208000000000000000000000000000000000000000000000000000000000000020b151e2730383f434646464646464646464644403a32291f160d0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000121e2b37434f5b666d6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6d665c5044382b1f12060013202c3946535f6c798693a0acacacaca8a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a79a8e8174675a4d4134271a0e0013202c3946535f6c798693a0a1a2a2a19f9c97918a81776d63584c41352a1e1206000000020e1a26323e4a56626d7985909ca7b2a79c91867b70665c524940383028221c181412101013151515151516191d21252b30373e4956636f7c8996a3aea295887b6e6155483b2e22150800101c2936434f5c6976838a8a8a8a8a8a8376695c4f4336291c100c1926323f4c5965727f8a8a8a8a8a8a86796c5f5346392c20130916222f3c4955626f7c898a8a8a8a8a897c6f6356493c30231609000000000000000000000000000000000000000000000000000915202c3640495054555555555555555555534d463c32271c1005000000000000000000000000000000000000000000000000000000000000010910161a1e1f20202020202020202020201f1c18130d05000000000000000000000000000000000000000000000000070e141a1d1f20202020202020202020201f1c18130d050000000000000000000000040e1821293035383939393939393939393939393939393939393939393939383736353432302d2b2825211e1a15110c070100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005101c27323e49535e69737e88929ca5afa89f968d857d756f69635e5a5653514f4e4d4d4d4e505254575b60656b717880889099a2abaca2998f857b70665b50453a2f23180d01000000000f1b27333e49535b606161616161616161605c544b545b5e5e5e5e5e5c564e463e362d25202c37434d575e6161616161616161615f584f453a2e22160a000000000000000000000000000000000b15202a333a414546464646464646464646433f3830271d140b02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008111a232b3136393939393939393939393936322b241b120800000000000000000000000000000000000000000000000000000000000000000000000000071019222a3035383939393939393939393936322b241b12090000000000000000000000000000000000000000000000000000000000000000030c151e262d33373939393939393939393938342f2820170d04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946525f6c777b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b786c6053473a2d2014070013202c3946535f6c798693a0acb4a9a19b9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a8e8174675a4d4134271a0e0013202c3946535f6c7986939d9d9fa2a6aca8a39c938a7f74695e52463a2e22160a00000006121e2a37434f5b67727e8a96a1adaca1968a7f74695f544a40372e261e17110c0a11171c20222222222222222222222225303c4956636f7c8996a3aea295887b6e6155483b2e22150800101c2936434f5c6976839096969696908376695c4f4336291c100c1926323f4c5965727f8c969696969386796c5f5346392c20130916222f3c4955626f7c899696969696897c6f6356493c30231609000000000000000000000000000000000000000000000000020e1a26313d48525b606161616161616161615f584e44382d21150a0000000000000000000000000000000000000000000000000000000000000000050a0e1113131313131313131313131312100c0802000000000000000000000000000000000000000000000000000003090d1113131313131313131313131312100c080200000000000000000000000000060f171e24292b2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b2a28272523211e1b1815110d0905000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b16212c37424d57626c76808a939da6aea89f978f87807a746f6a6663605e5c5b5a5a5a5b5c5e6164676b70767c838a929aa2ababa39a90877d73695e54493e34291d120700000000000b16222d38414a5054545454545454545454504a525c666a6b6b6b6b68605850483f372f2726313b454c52545454545454545454534e463d33281d120600000000000000000000000000000000040e1821293035383939393939393939393937332d261e150b020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008111920262a2c2c2c2c2c2c2c2c2c2c2c2a26211a12090000000000000000000000000000000000000000000000000000000000000000000000000000000710181f25292c2c2c2c2c2c2c2c2c2c2c2a26211a120900000000000000000000000000000000000000000000000000000000000000000000030c141c22272b2c2c2c2c2c2c2c2c2c2c2b28231d160e0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986888888888888888888888888888888877a6d6053473a2d2014070013202c3946535f6c798693a0acafa3978f8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8174675a4d4134271a0e0013202c3946535f6c798691909192969ba1a9aea59b91867a6e63574b3e32261a0d0100000a16222e3b47535f6b77838f9ba6b2a79c9085796e63584d43382e251c140c050b141c23282c2e2f2f2f2f2f2f2f2f2f2f2f303c4956636f7c8996a3aea295887b6e6155483b2e22150800101c2936434f5c697683909ca3a39c908376695c4f4336291c100c1926323f4c5965727f8c99a3a3a09386796c5f5346392c20130916222f3c4955626f7c8996a2a3a396897c6f6356493c3023160900000000000000000000000000000000000000000000000007131f2b36424e59646c6e6e6e6e6e6e6e6e6e6a6055493e32261a0e020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050d13181c1f202020202020202020202020202020202020202020201f1f1e1d1c1a181714120f0c09050100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005101b26303b46505a646e78818a949ca4aca9a199928b85807a76726f6c6a696767676768696b6d7073777c81878e949ca3acaaa29991887e756b61574d42382d22170c01000000000005111b262f383f4447484848484848484847454956626e7777777777726a625a51494139312829333b414647484848484848484846423c342b22170c010000000000000000000000000000000000060f171e24292b2c2c2c2c2c2c2c2c2c2c2b27221c140c03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070e151a1d1f2020202020202020201f1e1a150f080000000000000000000000000000000000000000000000000000000000000000000000000000000000060e14191d1f2020202020202020201f1e1a150f08000000000000000000000000000000000000000000000000000000000000000000000000020a11171b1e202020202020202020201f1c18120c040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986939595959595959595959595959594877a6d6053473a2d2014070013202c3946535f6c798693a0acaca0938681818181818181818181818181818181818181818181818181818181818181818181818181818174675a4d4134271a0e0013202c3946535f6c7986858484868a8f97a0aaada2978b7f73675b4e4236291d100400000d1926323e4a57636f7b87939fabaea2978b7f73685c51463b31261c130a0209131d262d34393b3c3c3c3c3c3c3c3c3c3c3c3c3c4956636f7c8996a3aea295887b6e6155483b2e22150800101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c302316090000000000000000000000000000000000000000000000000c18242f3b47535f6a767b7b7b7b7b7b7b7b7b72665a4e42372b1f13070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306090b0d0e0f10111212121111100f0d0c09070401000000000000000000000000000000000000000000000000000000000000000000000000000000000002080c101213131313131313131313131313131313131313131313131211100f0e0c0a080503000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009141f29343e48525c666f78818a929ba2aaaba49d96918b86827e7b79777574747374747677797c8083888d92999fa6aea7a09890887f766c63594f453b30261b1006000000000000000a141d262d34383a3b3b3b3b3b3b3b3b3b3d4a5763707d848484847c746c635b534b423a322a293036393b3b3b3b3b3b3b3b3b3a37312b2219100500000000000000000000000000000000000000050d13181c1f202020202020202020201e1b17110a02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e111313131313131313131313110e0a040000000000000000000000000000000000000000000000000000000000000000000000000000000000000003080d101213131313131313131313110e0a04000000000000000000000000000000000000000000000000000000000000000000000000000000060b0f121313131313131313131312100c0701000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0a2a2a2a2a2a2a2a2a2a2a2a094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca093867974747474747474747474747474747474747474747474747474747474747474747474747474746f64584c4033261a0d0013202c3946525f6b7779787777797e858e99a4afa79b8f83766a5e5145382c1f13060004101c2935424e5a66737f8b97a4b0aa9e92867a6e63574b40352a1f150b0105101b252f383f4548484848484848484848484848484956636f7c8996a3aea295887b6e6155483b2e22150800101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c30231609000000000000000000000000000000000000000000000005111d2834404c58636f7b878888888888888882766b5f53473b3024180c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000206090d10131517191b1c1d1e1e1e1e1e1e1d1b1a181613110e0a0602000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020d18222c36404a545d666f78818990989fa5aca8a29c97928e8b888684828181818181828486898c9094999ea4aaa9a39d958e867e756d645a51473d33291f140a0000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e303d4a56636f79848e918e867e756d655d544c443c342b252a2d2e2e2e2e2e2e2e2e2e2d2a262019100700000000000000000000000000000000000000000002080c101213131313131313131313120f0b060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986939696969696969696989fa9ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c67676767676767676767676767676767676767676767676767676767676767676767676767645d53483c3024180b00111e2a37434f5a656c6d6b6a6a6d737c87939fabab9f9286796d6054473a2e2115080006131f2c3845515d6a76838f9ba7b2a69a8e82766a5e52463a2f23180d03000a16212c37414a5054555555555555555555555555555556636f7c8996a3aea295887b6e6155483b2e22150800101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c3023160900000000000000000000000000000000000000000000000a16212d3945515c6874808c95959595959593877b6f64584c4034291d1105000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004090e1216191c1f22242627292a2b2b2b2b2b2a2928272522201d1a16120e0a0500000000000000000000000000000000000000000000000000000407080808080808080808080806040000000000000000000000000000000000000000000000000000000000010507080808080808080808080806020000000000000000000000000205080a0a0a0a0a0a0a0a0a09070400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006101a242e38424b545d666e777e868d949aa0a6aba8a39e9b979492908f8e8d8d8d8e8f919395989ca0a4a9a9a49e98928b847c746c635b52483f352b21170d02000000000000000000020a11171c1f2121212121212121222e3a47525d68727c86909890877f776f665e564e463d352d2520212121212121212121211e1a150e07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306080a0c0d0e0f0f0f0f0f0e0d0c0a080502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000305080a0c0e0f1011111212121111100e0d0b0907040100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002040608090a0a0b0b0a0a080705030000000000000000000000000000000002040506060606050403010000000000000000000013202c3946535f6c79868989898989898989898d98a4ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a58534b41372b201408000f1b27333e49535b60605f5d5e616b76828e9ba7aea195887b6f6255493c2f231609000915222e3b4754606d7986929eabafa3968a7e7265594d41352a1e120700000e1a26323e49535b61626262626262626262626262626262636f7c8996a3aea295887b6e6155483b2e22150800101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c3023160900000000000000000000000000000000000000000000030f1a26323e4a55616d7985919ca2a2a2a2a2988c8074685d5145392d22160a000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b10151a1e2225292c2e3032343637373838383837363533312f2c2926231e1a16110c0600000000000000000000000000000000000000000000060c1013151515151515151515151513100b060000000000000000000000000000000000000000000000000002080d11141515151515151515151514120f0a04000000000000000001080d12151617171717171717171614100b05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008131c263039424b545c656d747b83898f959a9fa4a7aba7a4a19f9d9c9b9a9a9a9b9c9d9fa2a4a8aaa6a29d98938d878079726a625a514940362d23190f05000000000000000000000000060c101314151515151515151e2a36414c56606a747e89939991898178706860584f473f372e261e161515151515151514120e0903000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000407080808080808080808080808080808080808080704000000000000000000000000000000000000000000000000000000000000000000000206090d10121517191a1b1c1c1c1c1c1b1a181614120f0c08050100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005080c0f121417191a1c1d1e1e1e1e1e1e1d1c1b1a181613100d0a070300000000000000000000000000000000000000000000000000000000000000000000000000000000000206090c0f111314161717171717161514120f0d0a060300000000000000000206090c0e10121313131312110f0d0a07040000000000000013202c3946535f6c787c7c7c7c7c7c7c7c7c7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f534d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4c4841392f251a0f03000a16212d3741494f53535251515a66727f8c98a5b0a3968a7d7063574a3d3124170a000b1724313d4a56636f7c8895a1aeaca093877a6e6256493d3125190d010000101d2a36424e5a656d6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f7c8996a3aea295887b6e6155483b2e22150800101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c302316090000000000000000000000000000000000000000000008131f2b37434e5a66727e8a95a1adadacaea89d9185796d61564a3e32261b0f03000000000000000000000000000000000000000000000000000000000000000000000000000000050b11161c21252a2e3235383b3d3f4142434444454544444341403e3c3936322f2b26211c17110b05000000000000000000000000000000000000020a11181c2021222222222222222222211f1c1711090100000000000000000000000000000000000000000000040c13191d2022222222222222222222211f1b150f07000000000000030c13191e2123232323232323232322201c16100800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a141e273039424a535b626a71787e84898f93979b9fa2a4a6a8a9a8a7a7a7a7a8a8a9a8a6a3a19d9a96918d87827c756e67605850483f372e241b11070000000000000000000000000000000406080808080808080e19252f3a444e58626d77818b959b938a827a726a615951494038302820170f080808080807050200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c10131515151515151515151515151515151515151513110c0700000000000000000000000000000000000000000000000000000000000005090e1216191c1f2123252728292929292828262523211e1b1815110d08040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003080c1114181b1e2123252728292a2b2b2b2b2b2a2928262422201d1a16130f0a0601000000000000000000000000000000000000000000000000000000000000000000000000050a0e1215191b1e20212223242424242322201e1c1916120f0a0601000000050a0e1216191b1d1e1f2020201f1e1c1a1714100b060000000000121e2b3744505c666e6f6f6f6f6f6f6f6f6f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f534641414141414141414141414141414141414141414141414141414141414141414141403c372f271d1309000005101b252f373e44464645444a5764707d8a96a3b0a4978b7e7164574b3e3124180b000d1926333f4c5865727e8b97a4b0aa9d9184786b5f52463a2d211509000000121e2b3845515e6b777b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7c8996a3aea295887b6e6155483b2e22150800101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c30231609000000000000000000000000000000000000000000010c1824303c47535f6b77838e9aa6a7a19fa2a9a1968a7e72665a4f43372b1f140800000000000000000000000000000000000000000000000000000000000000000000000000020910161c22272d31363a3e4144474a4c4d4f505151515151504f4e4c4a4845423f3b37322d28221d17100a03000000000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2e2c28221b130a010000000000000000000000000000000000000000040e161e24292d2e2e2e2e2e2e2e2e2e2e2e2b262019110800000000030d151d242a2e3030303030303030302f2c28211a120800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020c151e273038414951585f666d73787e83878b8f9295989a9c9d9e9f9f9f9f9f9e9d9b999794918e8a86817c76706a645d564e463e362d241b12090000000000000000000000000000000000000000000000000008131e28323c46515b656f79848e989c948c847b736b635b524a423a3229211910070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a11181c2021222222222222222222222222222222222222201d18120b030000000000000000000000000000000000000000000000000001060c11151a1e2225282b2e3032333535363636353433312f2d2b2824211d19140f0a05000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f14181d2124282b2d303234353637383838383837363433312f2c2926231f1b16110c07010000000000000000000000000000000000000000000000000000000000000000060b11161a1e2225282a2c2e2f3031313130302e2d2b2825221f1b16120d07060c11161a1e2225282a2b2c2c2c2c2b2a282623201c17110a020000000f1b28333f4a545d6263636363636363636f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f53463934343434343434343434343434343434343434343434343434343434343434343433302b251d150b0100000009131d252d33373a3a393c4956626f7c8895a2afa5988b7e7165584b3e3225180b000e1b2834414e5a6773808d99a6b3a79b8e8275695c5043372a1e1105000000121e2b3845515e6b788588888888888888888888888888888888888d98a4aea295887b6e6155483b2e22150800101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c3023160900000000000000000000000000000000000000000005111d2935404c5864707b87939fa89e959297a0a69a8f83776b5f53483c3024180d010000000000000000000000000000000000000000000000000000000000000000000000050d141b21272d33383d42464a4e515456585a5c5d5d5e5e5e5e5d5c5b595754524e4b47433e39342e28221b140d0600000000000000000000000000000a141d262e34383b3b3b3b3b3b3b3b3b3b3b38332d251c130900000000000000000000000000000000000000020c1620282f35393b3b3b3b3b3b3b3b3b3b3a37322b231a10060000000b151f272f353a3c3d3d3d3d3d3d3d3d3c38332c241a110600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c151e262f373f464d545b61676d72777b7f8386898b8d8f9091929292929291908e8d8a8885827e7975706b655f59524b443c342c241b12090000000000000000000000000000000000000000000000000000010c16202a353f49535d67727c86909a9e968e857d756d645c544c443b332b22190f05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2c29231d150c030000000000000000000000000000000000000000000000060c12171c21262a2e3235383a3d3f4041424242424241403e3c3a3734312d2925201b16100b050000000000000000000000000000000000000000000000000000000000000000000000000000030a10151b2024292d3134373a3c3e4042434444454545444342413f3e3b3936322f2b27221d18120d070000000000000000000000000000000000000000000000000000000000040b11171c21262a2e313437393a3c3d3d3e3e3d3c3b393735322f2b27221d181311171d22262b2e313436383939393938373533302c28221b140b0100000b17232e38424b525556565656565656626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5346392c27272727272727272727272727272727272727272727272727272727272727272624201a130b0300000000010b131b22272b2d2d2f3b4855626e7b8895a2aea5988b7e7165584b3e3225180b00101c2936424f5c6875828f9ba8b2a6998c8073665a4d4134281b0f02000000121e2b3845515e6b78859295959595959595959595959595959595979fa9aea295887b6e6155483b2e22150800101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c302316090000000000000000000000000000000000000000000a16222e3945515d6974818c98a4a4988c868f9ba79f93887c7064584c4135291d1106000000000000000000000000000000000000000000000000000000000000000000000810171e252c33393e44494e52565a5d6063656768696a6b6b6b6b6a69676663615e5b57534e4a453f39332d261f18100800000000000000000000000006111c262f383f454848484848484848484847443f372e251a100500000000000000000000000000000000000009141e28323a41464848484848484848484847433d352c22170c010006121c2731394146494a4a4a4a4a4a4a4a48443e362c22180d0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c151d252d343c434a50565c61666b6f7376797c7e818284858586868685848382807e7b7875726d69645f5a544e474139322a231a120900000000000000000000000000000000000000000000000000000000040e19232d37414b56606a747e89939d9f978f877e766e665e554d453d352b21170c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a141d262e34383b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b39352e271e150b000000000000000000000000000000000000000000040b11171d23282d32363a3e414447494b4d4e4f4f4f4f4f4e4c4b494643403d3935302c27211c161009030000000000000000000000000000000000000000000000000000000000000000000001080e151b21262b3035393d404346494b4d4e50515151515151504f4e4c4a4845423f3b37332e29231e18120b040000000000000000000000000000000000000000000000000000070f151c22282d32363a3e4143454749494a4a4a4a49484644413e3b37332e29241e1c22282e32373b3e414344454646464543423f3c38332d261d1309000006111c27303940464949494949494955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5346392c201a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a18140f0901000000000000010910161b1f20222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00111e2a3744505d6a7683909da9b1a4978b7e7165584b3f3226190c00000000121e2b3845515e6b7885929ea2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a3a9b1aea295887b6e6155483b2e22150800101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c302316090000000000000000000000000000000000000000030f1b27323e4a56626d7985919da9a093877f8b97a3a4988c8175695d51453a2e22160a0000000000000000000000000000000000000000000000000000000000000000010a121a222930373e444a4f555a5e62666a6d6f71737576777778787777757472706d6a67635f5a55504a443e383129221a120a02000000000000000000000b17222d38424a515455555555555555555554504940362c22170d020000000000000000000000000000000006111b26303a444c5255555555555555555555534e473e34291d1206000b17232e39434b52565656565656565656554f483e34291e12060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030b131b232a31383f454b50565a5f63676a6d707274757778787979797877767573716f6c6965615d59544e49433c362f282019110800000000000000000000000000000000000000000000000000000000000007111b252f39444e58626c76818b959fa1999188807870675f574f473d33281d11050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c262f383f454848484848484848484848484848484848484845403930271d120700000000000000000000000000000000000001080f161c23282e34393e42464a4e51535658595b5b5c5c5c5b5a59575553504d4945413c37322d27211b140e070000000000000000000000000000000000000000000000000000000000000000040c131920262c32373c4145494d50535558595b5c5d5e5e5e5e5e5d5c5a595754514e4b47433e3a342f29231d160f080100000000000000000000000000000000000000000000010a111920272d33393e42464a4d505254555657575757565453504e4a47433f3a352f2a272e34393e43474a4d4f515253535252504e4b48443f372f251b100500000a151e272f353a3c3c3c3c3c3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5346392c20130e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0d0b080300000000000000000000050b0f1215222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00121e2b3845515e6b7784919eaab0a3968a7d7063574a3d3124170b00000000121e2b3845515e6b7885929ea6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a295887b6e6155483b2e22150800101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c3023160900000000000000000000000000000000000000000814202b37434f5b66727e8a96a2a89b8f837b87939fa99d91857a6e62564a3f33271b0f03000000000000000000000000000000000000000000000000000000000000020b131c242c333b42494f555b60656a6e7276797c7e80828384848585848482817f7d7a77736f6b66615b565049423b342c241c140b020000000000000000000f1b27333f4a545c61616161616161616161605b52483e33291f140a000000000000000000000000000000030d18222d37424c565d616161616161616161615f5950453a2e22160a000f1c28343f4a555d626363636363636363615a50463a2e22160a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000109111820272d343a3f454a4e53575a5e61636567696a6b6c6c6c6c6b6b6a68676562605c5955514d48433d37312b241d160e07000000000000000000000000000000000000000000000000000000000000000009131d28323c46505a656f79838d98a2a39a928a8279716961594f45392d211509000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17222d38424a5154555555555555555555555555555555555554514b42392e23180c0000000000000000000000000000000000040c131a21272e343a3f44494e52565a5d60626466676869696968676664625f5c5955514d48433e38322c261f18110a030000000000000000000000000000000000000000000000000000000000070e161d242b31373d43484d5155595c5f62646668696a6b6b6b6b6a6a69676563615e5b57534f4a45403a342e28211a120b030000000000000000000000000000000000000000020b131b232b32383f444a4e5356595c5f6062636364646362615f5d5a57534f4b46403b3532393f454a4f53575a5c5e5f5f5f5f5e5d5b5854504941372d22160a0000030c151d24292d2f303030303c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00121f2c3945525f6b7885929fabafa296897c6f6256493c3023160900000000121e2b3845515e6b7885929a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a95887b6e6155483b2e22150800101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c3023160900000000000000000000000000000000000000010d1924303c48545f6b77838f9ba6a3978b7f77838f9ba7a2968a7e73675b4f43382c2014080000000000000000000000000000000000000000000000000000000000020b141d252e363e454c535a60666c71767a7e8285888b8d8e909191929191908f8d8b898683807b77726d67615b544d463e362e261d140b020000000000000000121e2b37434f5b666d6e6e6e6e6e6e6e6e6e6c645a50453b30261b110700000000000000000000000000000a141f29343e49545e686e6e6e6e6e6e6e6e6e6e6b61564b3e3226190c00121e2b3744505c676e70707070707070706c62574b3e3225190c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070e151c22282e34393e43474b4e515457595b5c5d5e5f5f5f5f5f5e5d5c5a585653504d4945413c37322c262019130b04000000000000000000000000000000000000000000000000000000000000000000010c16202a343e49535d67717b86909aa0a09c948b837b736a61564a3d3125180b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1b27333f4a545c616161616161616161616161616161616161615c544b4034281c1004000000000000000000000000000000070e161d252c32393f454b50555a5e6266696c6f71737475757575757472706e6c6965615d59544f49443e37312a231c140d0500000000000000000000000000000000000000000000000000000009111920282f363c43494e54585d6165696c6e7173747677777878777776757472706d6a67635f5b56514b464039322b241d150d04000000000000000000000000000000000000020b141d252d353c434a50555a5f6366696b6d6f70707171706f6e6c6966635f5b56514c46403c434a50565b5f6366696a6c6c6c6c6b696764605b53493e33271b0f000000030b12191d21232323232f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5346392c201306040404040404040404040404040404040404040404040404040301000000000000000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00131f2c3946525f6c7986929facaea295887b6f6255483c2f22150900000000121e2b3845515e6b78858d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d887b6e6155483b2e22150800101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c302316090000000000000000000000000000000000000006121d2935414d5964707c88949fab9f93877b737f8b97a3a79b8f83776c6054483c3125190d01000000000000000000000000000000000000000000000000000000010a141d262f3740484f575e656b72777d82878b8e929597999b9c9d9e9e9e9e9d9c9a9896938f8b87837d78726c655f57504840382f261d140b020000000000000013202c3946525f6c777b7b7b7b7b7b7b7b7b766c61574c42382d23180e0300000000000000000000000007111c26313b46505b65707a7b7b7b7b7b7b7b7b7b73675a4d4134271a0e0013202c3946535f6c787d7d7d7d7d7d7d7d73665a4d4034271a0d010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a11171d23282d32373b3e4245484a4c4e4f5151525253525251504f4d4c494744413d3935302b26211b150e08010000000000000000000000000000000000000000000000000000000000000000000000040e18222d37414b555f6a747e889293939393938d857c7266594c3f3326190c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000121e2b37434f5b666d6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6d665c5145382c1f1306000000000000000000000000000008111820282f363d444a50565c61666a6e7276797b7e80818282828282817f7d7b7875716d6965605a554f49423c352e261f170f060000000000000000000000000000000000000000000000000109121a232b323941474e545a5f64696d7175787b7d8081828484858584848382817e7c7a77736f6b67625c57514b443d362e271f160e0500000000000000000000000000000000000a141d262f373f474e555b61666b6f7275787a7b7c7d7d7d7d7c7a7876736f6b67625d57514b474e555b61666b6f72757778797979787674706c655b4f43372a1e110000000001070d1114161616222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5346392c20131111111111111111111111111111111111111111111111111111100d0a0500000000000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0013202c3946535f6c7986939facaea295887b6e6155483b2e22150800000000121e2b3845515e6b78808080808080808080808080808080808080808080808080807b6e6155483b2e22150800101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c30231609000000000000000000000000000000000000000b16222e3a46525d6975818d98a4a79b8f83776e7b87939faba094887c7065594d41352a1e120600000000000000000000000000000000000000000000000000000009131c262f384149525a616970767d83898e92979b9ea1a4a6a8a9aaa9a8a8a9a9a8a7a5a29f9b98938e89847d777069625a524a41392f261d140a00000000000000131f2c3945525e6b758088888888888888887e73695e54493f342a20150b0000000000000000000000030e18232d38424d57626c778288888888888888867c7166594d4034271a0d0013202c3946535f6c79868a8a8a8a8a8a8173675a4d4034271a0d0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c12171d22262a2e3236393b3e40414344454546464645454442413f3d3a3734312d2924201b15100a03000000000000000000000000000000000000000000000000000000000000000000000000000006111b252f39434e58626c76818686868686868686807366594c403326190d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946525f6c777b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b786d6054473a2d2114070000000000000000000000000109121a222a323a41484f555c61676d72767b7e8285888a8c8e8f8f8f8f8e8d8c8a8785817d7975706b66605a544d463f3830292118100700000000000000000000000000000000000000000000000a131b242c353c444b52595f656b7075797d8185878a8c8e8f909191929191908f8d8b898683807b77736d68625c564f484039312820170f0600000000000000000000000000000008121c262f384149515960666c72777b7e82848688898a8a8a8a898785827f7b77736e68635c56515960666d72777b7f8284858686868483807c776b5f5246392c2013000000000000010508090916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5346392c201d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1c1a151009020000000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0013202c3946535f6c7986929facaea295887b6e6155483b2f22150800000000111e2a3743505c677173737373737373737373737373737373737373737373737373726a5f53473a2d21140800101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c3023160900000000000000000000000000000000000004101b27333f4b56626e7a86919da9a3978b7f736a77838f9ba7a4998d8175695e52463a2e23170b000000000000000000000000000000000000000000000000000007111b252e38414a535b646b737a81888e94999ea3a7aaa9a6a3a09f9d9c9c9c9c9d9ea0a2a5a9a8a49f9a958f89827b746c645c534b42382f261c1208000000000000111d2a36424e59646e78838d95959595958f857a70665b51463c31271c1208000000000000000000000b15202a353f4a545f69747e89939595959594897f746a6055493d3125180c0013202c3946535f6c798693969696968d8173675a4d4034271a0d01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001060c11161a1e2226292c2f31333536373839393939393837363432302e2b2825211d19140f0a04000000000000000000000000000000000000000000000000000000000000000000000000000000000009131d27323c46505a646f787979797979797979797165584c3f3326190c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986888888888888888888888888888888877a6d6154473a2e2114070000000000000000000000010a131b242c343c444b535a60676d73787d82878b8e9295979997969696969698989694918d8a86817c77716b655f58514a423b332a2219110800000000000000000000000000000000000000000009121c252e363e464e565d646a70767c81858a8d919496999a9c9d9e9e9e9e9e9d9b9a9895928f8c88837e79736d676059524a433a322921180e050000000000000000000000000005101a242e38414a535b636a71787d83878b8e91939596979797969594918f8b88837e79746e67615b636a71787e83878b8e9092939392918f8c86796c5f5346392c2013000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5346392c2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2926211b140c0300000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00131f2c3946525f6c7986929facafa295887b6f6255493c2f221609000000000f1b2834404b565f65666666666666666666666666666666666666666666666666666661584e42372b1e120600101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c302316090000000000000000000000000000000000000914202c38444f5b67737e8a96a2ab9f93877b6f66737e8b97a3a99e92867a6e62574b3f33271c1004000000000000000000000000000000000000000000000000040f19232d37404a535c656d757d858c93999fa5aaaba6a19d9a969492908f8f8f8f90919396999da1a6aba6a09a948d857e766e655d544b41382e241a100500000000000e1a26323d48525c66717b85909aa2a2a1978c82776d62584e43392e24190f04000000000000000007121c27313c46515b66707b86909ba2a2a1978c82776d63584e43382d2115090013202c3946535f6c798693a0a3a39a8d8173675a4d4034271a0d010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0e12161a1d2022242628292b2b2c2c2c2c2c2b2a29282624211f1c1815110d080300000000000000000000000000000000000000000000000000000000000000000000000000000000000000010b16202a343e48535d666c6c6c6c6c6c6c6c6c6c685f54493d3024170b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986939595959595959595959595959594877a6d6154473a2e21140700000000000000000000000a131c252d363e464e565d646b72787e84898e93979793908e8c8a898989898a8b8c8f91949896928d88827d76706a635c544c453c342c231a11070000000000000000000000000000000000000008121b242e374048505860676f757c82878d91969a9da0a3a5a7a9a9a8a8a7a8a8a9a8a6a4a29f9c98948f8a857f78726b645c554c443b332a20170d040000000000000000000000010c17212c36404a535c656d757c83898e93979b9da0a1a3a2a2a2a2a2a09e9b98948f8a857f79726b656d757c83898f93979b9d9fa0a09f9e9c9386796c5f5346392c2013000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f534639373737373737373737373737373737373737373737373737373737373735322c261e150b01000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00121f2c3845525f6b7885929eabafa296897c6f6356493d3023160a000000000b17232e39444d54595959595959595959595959595959595959595959595959595959564f463c31261a0e0200101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c302316090000000000000000000000000000000000020d1925313d4854606c78848f9ba7a79b8f83776b626e7a87939faba2968b7f73675b5044382c2015090000000000000000000000000000000000000000000000010b16202b353f49525c656e7780878f979ea4abaca6a09a95918d8a878584838282828385878a8d91959aa0a6aba59e97908880776f665d534a40362c22170d02000000000915202b36404a555f69737e88929da7a89e94897e746a5f554a40362b21160c01000000000000040f19242e39434e58636d78828d97a2aca49a8f857b70665b51473c32271c11050013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002060a0d101316181a1b1d1e1f1f1f201f1f1e1e1c1b191715120f0c09050100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040e18222c37414b545b5f5f5f5f5f5f5f5f5f5f5d564d43382c2014080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0a2a2a2a2a2a2a2a2a2a2a2a194877a6d6154473a2e2114070000000000000000000009121c252e374048505860686f767d83898f9597938e8a8784817f7e7d7c7c7c7d7e808285888b8f9499938e88827b746d665e564e463e352c23191006000000000000000000000000000000000006101a242d374049525a626a727980878d93989da2a6a9a8a5a29f9d9c9b9b9a9b9b9c9ea0a2a5a8a8a4a09b96908a847d766e665e564d453c32291f150c010000000000000000000007121e28333e48525c656e777f878e949a9fa3a39f9c99979695959597999b9fa3a09b96918a847d756e777f878e949a9fa4a7a5a2a09f9e9fa09386796c5f5346392c2013000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5346444444444444444444444444444444444444444444444444444444444444423e3730271d1208000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00111e2b3844515e6b7784919daab0a3978a7d7064574a3e3124180b0000000007121d28323b43494c4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4c4a443d342a2015090000101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c30231609000000000000000000000000000000000006121e2a36414d5965717c8894a0aca3978b7f73675e6a76838f9ba7a79b9084786c6054493d3125190e020000000000000000000000000000000000000000000008121d28323d47515b646e7780899199a1a8afa8a19b948f8a85817d7b79777675757577787a7d8185898f949ba1a9a9a29a928981786f655c52483e33291f140900000000040f1a242e38434d57626c76818b959faaa59b90867b71675c52473d32281e13090000000000010b16202b35404a555f6a747f89949ea9a79d93887e73695e544a3f352a20150b000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010407090b0d0f10111213131313121211100e0d0b08060300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006101a252f39424a5053535353535353535353514c443b31271b10040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaaa098969696969696969694877a6d6154473a2e21140700000000000000000007111b242e374049525a626a727981888e9597918c87827e7a77757371706f6f6f70717375787b7f83888d9298938d867f787068605850473e352b22180f05000000000000000000000000000000030d18222c363f49525b646c747c848b92989ea4a9aaa4a09c989593918f8e8e8e8e8f90919396999ca0a5aaa6a19b958e87807870685f574e443b31271d1309000000000000000000010d18242f3a454f5a646e77808991989fa5a39d98938f8c8a898888898a8c8f93979ca1a29c958f878078818991989fa6a7a19c989593929292939386796c5f5346392c2013000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f53505050505050505050505050505050505050505050505050505050505050504e4942392f24190d020000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00111d2a3743505d697683909ca9b1a5988b7e7265594c3f3326190d00000000010c16202931383d3f40404040404040404040404040404040404040404040404040403e39332b22180e030000101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c3023160900000000000000000000000000000000000b17232f3a46525e6a75818d99a5ab9f93877b6f635a66727e8b97a3aca094897d7165594d42362a1e1207000000000000000000000000000000000000000000030e19242f39444e59636d768089929ba3abaea69e979089837e7975716e6c6a696968696a6c6e7174797e838990979ea6aca49b938a81776d645a4f453b30261b10050000000008121c27313b46505a646f79838e98a2aca2988d83786e63594f443a2f251a10060000000008121d27323c47515c66717c86919ba6aaa0968b81766c61574d42382d23190e04000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131d2730383f444646464646464646464644403a322920150a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca5998e898989898989898989877a6d6154473a2e2114070000000000000000050f19232d364049525b646c747c848b9298918b85807b76726e6b68666463626263636567696c6f73777c81878d9398918a827a726a625950473e342a21170d0200000000000000000000000000000a151f29343e48515b646d767e868e959da3a9aaa49e9994908c898684838281818182838587898c9094999ea4aaa6a099928a827a716960564d43392f251b1006000000000000000007121e2a35404b56616c768089929ba3a8a099928c8783807d7c7b7b7c7d8083878b90959ba2a099928a828a939ba3aaa39c96918c8986858585868886796c5f5346392c2013000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5a544b40352a1e12060000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000f1c2935424f5b6875828e9ba7b3a6998d8074675a4e4135281c0f0300000000040e171f262c30333333333333333333333333333333333333333333333333333333312d2821191007000000101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c302316090000000000000000000000000000000004101c28333f4b57636e7a86929eaaa69a8f83776b5e56626e7a86929eaaa5998d82766a5e52463b2f23170b00000000000000000000000000000000000000000009141f2a35404b56606a757f89929ba4adada49c948c857e78726d6965625f5e5c5c5b5c5d5f6165686d72787e858d949ca5ada59c938980766c61574c42372c21160b00000000000b151f29343e48535d67717c86909ba5aa9f958a80756b60564c41372c22170d020000050f1a242f39444e59636e78838d98a2ada3998e84796f645a50453b30261c110700000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000103050608090a0a0b0b0b0a09080706040200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010b151e262e33373939393939393939393938352f2920170e03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7c7c7c7c7c7c7c7c7c796d6054473a2e21140700000000000000020d17212b353f48525b646d757e868e96948d87807a746f6a66625f5c59585656555657585a5c5f63676b70767b82888f96948c847c736b625950463c33291e140a0000000000000000000000000006111c26313b465059636d767f889098a0a7aea69f99938d8884807c7a7776757474747576787a7d8084888d93999fa6aba49c948c847b72685f554b41372d22170d02000000000000000b17232f3a46515d68737d88929ba4a79e968e87817b7773716f6f6e6f7173767a7f848a91979fa49c948f939ca5a8a098918b85807c7a7878797a7c7e796c5f5346392c2013000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a655d52463a2e2215090000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000e1b2734414d5a6673808c99a6b2a89b8f8276695d5044372b1e12060000000000050d151b202426262626262626262626262626262626262626262626262626262625221d170f0700000000101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c30231609000000000000000000000000000000000915212c3844505c67737f8b97a3ada2968a7e72665a525e6a76828e99a5aa9e92867a6f63574b3f34281c100400000000000000000000000000000000000000030f1a25313c47525d67727c87919aa4adada49b928a827a736d67615d59555351504f4f4f515255585c61676d737b828a939ca5aea59b92887d73695e53493e33281d110600000000030d18222c36414b55606a747e89939da8a69c92877d72685d53483e34291f140a00010c16212b36404b55606a75808a959faaa69c91877c72685d53483e33291f140a0000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d090907050300000000000000000001040608090a0a090806040100000000000000000000000000000000000000000000000000000000000000000000000105080b0d101113151616171717171716151412110f0c09060300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c141c22272b2c2c2c2c2c2c2c2c2c2c2b29241e170e0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca4978a7d706f6f6f6f6f6f6f6f6e675d5145392c201306000000000000000a141f29333d47515a646d767f889098918a837b756f69635e5a56524f4d4b4a4949494a4b4d5053575b60656a70767d848b93968e867d746b61584e443b30261c11070000000000000000000000020d18232d38434d57626b757f88919aa2aaaca49c958e87827c7773706d6b6968676767686a6b6e7074787c82878e959ca4aca69e968d847a71675d53493e34291e1308000000000000030f1c28343f4b57636e79848f9aa4a99f958c847c756f6b67646362626264676a6e73797f868d959da69e9c9ea5a79e968e86807974706d6b6b6c6d6f7272695d5145382c1f12000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca0938679777777777777777777777777777777777777777777777777777777777777777777766e63564a3d3124170b0000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000c1926323f4b5865717e8a97a3b0aa9e9185786c5f53473a2e221609000000000000030a101418191a1a1a1a1a1a1a1a1a1a1a1b22282c2f2f2e2a2723201c1a1a1a1815110c050000000000101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c30231609000000000000000000000000000000020e1a25313d4955606c7884909ca7a99d9185796d61564d5965717d8995a1aca3978b8073685c5044382d211509000000000000000000000000000000000000000914202b37424d58636e79848e98a3acafa59b928980787068625b56514c494644434242434446494c50565b62697078818a939ca5ada3998f857a70655a4f44392e23170c000000000006101a252f39434e58626d77818c96a0aaa3998e84796f655a50453b30261c110709131e28333d48525d67727c87919ca6a99f948a80756b60564b41372c22170d020000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a17161514120f0c080400000000050a0d111315161717161413100d0a0702000000000000000000000000000000000000000000000000000000000001060a0e1114171a1c1e2021222324242424242322211f1d1b1916130f0c08040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a11171b1e202020202020202020201f1c18130c050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca4978a7d706363636363636363625d554b4035291d100400000000000006111b26303b454f59636c767f8891988f878078716a635d58535252514c453e3d3c3c3c3d3f4144494f5254595f656b7279818991988f867d736a60564c42382e23180e030000000000000000000008131e29343f4a545f69737d87919aa3acaba29a928a837c76706c6764615e5d5b5b5b5b5c5d5f6164686c71767c838a929aa2aba89f968c83796f655b50453b30251a0f04000000000007131f2c3844505c68737f8b96a1aba1978d837a726a645f5b5856555556585a5e63686e747b838b949faaa8aaa99e958c847c756e6864605f5f5f6063666660574c4135291d10000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acada09387848484848484848484848484848484848484848484848484848484848484848484847e7164574b3e3124180b0000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000a1724303d4956626f7b8894a1adada094887b6f63564a3e32261a0e020000000000000004080b0d0d0d0d0d0d0d0d0d0d131c252d34393b3c3a37332f2c2825211d19140e07000000000000101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c3023160900000000000000000000000000000007131e2a36424e5965717d8995a0aca4988c8175695d514955616c7884909ca8a89c9084786d6155493d31261a0e020000000000000000000000000000000000020e1a25313c48535e6a75808b95a0aab1a79d938980776e665e57504a45403d3a383636353637393c40454a50575f666f77818a949da7aba1978c82776c61564a3f34281d1105000000000009131d27323c46515b656f7a848e99a3aba0968b81766c61574d42382d23180e101a252f3a444f59646e79838e98a3aca2978d83786e63594e443a2f251a1006000000000013202c3946535f6c798693a0aca79a8d8173675a4d40342723232322201e1c1814100b05050b11161a1d202223232323211f1d1a16130e08010000000000000000000000000000000000000000000000000003080d12161a1d212426292b2c2e2f303031313130302f2d2c2a2825221f1c1814100b060100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060b0f121313131313131313131312100c0701000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca4978a7d70635756565656565656524c43392f24180c000000000000010c17222d38424d57616b757e8891978e867d756e665f5f5f5f5f5f5f5d574f453a302f303135404a535b5e5f5f5f5f61686f777f8790988f867c72685e544a3f352a1f1409000000000000000000020e1924303b46515b66717b858f99a3acaba29990888078716b65605b575452504f4e4e4e4f505255585b60656b717880889099a2aba89f958b81776c62574c41362b20150900000000000a16232f3b4854606c7884909ca7a69b90857b71686059534e4b494848494b4e52575c62697179828f9ba8b5b1a5988c837a726a635d585452525254565a5a564e453b3024190d000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acafa499929090909090909090909090909090909090909090909090909090909090909090908b7e7164574b3e3124180b0000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000815212e3a4753606c7985919eaab0a3978b7e72665a4e42362b1f1308000000000000000000000000000000000000040f1a242e373f45484946433f3c3834312d2925201911080000000000101c2936434f5c697683909ca9a99c908376695c4f4336291c100c1926323f4c5965727f8c99a6aca09386796c5f5346392c20130916222f3c4955626f7c8996a2afa396897c6f6356493c302316090000000000000000000000000000000c17232f3b47525e6a76828e99a5ab9f94887c7064584c44505c6874808b97a3aca195897d71655a4e42362a1f1307000000000000000000000000000000000007131f2a36424d5964707b86919ca7b2aa9f958b81776e655c544c453f3934302d2b2a2929292b2d3034393f454d545d656e78828b95a0aaa89e93887d72675b5045392d2115080000000000010b16202a343f49535e68727c87919ba6a79d93887e73695e54493f352a201517222c37414c56616b76808b95a0aaa59a90867b71665c51473d32281d130900000000000013202c3946535f6c798693a0aca79a8d8173675a4d40342f3030302f2d2b2824201c161110171c2126292c2e2f30302f2e2c2926231f19120b020000000000000000000000000000000000000000000003090f14191e22262a2d30333537393b3c3d3d3e3e3d3d3c3b3a383634322f2b2824201b17110c0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a49494949494946413a31281d120700000000000008131e29343f49545e69737d8791988e857c746b6360696b6b6b6b6b6b6961564b3f332625303b46515c656b6b6b6b6b6b6b6a6d757e8790988e847a70665b51463c31261b1004000000000000000008131f2a35414c57626d78838d97a1abada39990877e766e666059544f4b48454342414141424446484b4f545a60666e767e879099a3ada79d93897e73695e53483d31261a0f03000000000d1926323f4b5764707c8895a1aca1958a7e73695f564e47423f3d3c3c3d3f42464d57616b757e88929daab1b1a4988c81766c6158524c48454546474a4d4d4a443c33291f1308000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acb5aba39e9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d988b7e7164574b3e3124180b0000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0006121f2b3844505d6975828e9aa7b3a79b8f83766a5f53473b30251a0f0500000000000000000000000000000000000a15202c364049505555534f4b4844413d3936312b231a110700000000101c2936434f5c697683909ca9a99c908376695d5043362a1d100c1926323f4c5965727f8c99a6aca09386796c5f5346392d20130916222f3c4955626f7c8996a2afa396897c6f6356493c30231609000000000000000000000000000005101c2834404b57636f7b87929eaaa79b8f83776b5f54483f4b57636f7b87939faaa59a8e82766a5f53473b2f23180c00000000000000000000000000000000000b17232f3b47525e6a75818c98a3aeaea3988e83796f655c534a423a342e2824211e1d1c1c1d1e2024282e343b434b535c666f79848e98a3aaa49a8f83786d6156493d3124170b000000000000040e18232d37414c56606b757f8a949ea8a49a8f857b70665b51463c32271d1e29333e48535d68727d87929ca7a89d93897e74695f544a40352b20160c0100000000000013202c3946535f6c798693a0aca79a8d8173675a4d403b3c3d3d3c3b3a3734302c27221c1b22282d3236393b3c3d3d3c3a3836322f2a241d140b010000000000000000000000000000000000000002080f141a20252a2e3236393c3f4244464748494a4a4a4a4a4948474543413e3b3834302c27221d17120b050000000000000000000000000000000000000000000000000407080808080808080808080602000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002050708080808080808080706030000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3c3c3c3c3c3a362f281f160b010000000000020e19242f3a45505b66707a858f998f867c736a625a677278787878787873675b4e4235282c37424d58636e7778787878787874696c757e8791968c82786d63584d42372c21160a00000000000000010d1824303b47525d68747e8a949fa9afa59b91877e756c645c554e48433f3b3937353434353537393c3f44494e555c646c757e87919ba5afa59a90857a6f64594e42372b201409000000000f1b2835414e5a6773808c98a5a89c9084786d62574d443c3732302f2f3037414b555f69737d87909aa4a8a4a5a89e93887d73685d52473c3938393b3e40403e39322a21170d02000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acb9b3aca8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a4988b7e7164574b3e3124180b0000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00030f1c2835414d5a66727e8b97a3afab9f93877b6f63584c41362b21170d0400000000000000000000000000000007111c26313d48525b61625f5b5854504d4946423c352c23190e03000000101c2936434f5c697683909ca9aa9d9083766a5d5044372a1d110c1926323f4c5965727f8c99a6ada09386796d6053473a2d20140916222f3c4955626f7c8996a2afa396897c6f6356493c3023160900000000000000000000000000000915212d3944505c6874808b97a3aea2968a7e72675b4f433b47535e6a76828e9aa6aa9e93877b6f63584c4034281d1105000000000000000000000000000000030f1b2834404b57636f7b86929da9b3a89d92877c71675d534a41383029221d181412100f0f101114181d22293139414a545e67727c87919c9e99938d887e7265584b3f3225180c0000000000000006111b25303a444e59636d78828c97a1aba1978c82776d63584e43392e2425303a454f5a646f79848f99a4aba0968c81776c62584d43382e23190f040000000000000013202c3946535f6c798693a0aca79a8d8173675a4d454749494a49484644403d38332d27252c33393e424547494a4a494745423f3b362e261d1309000000000000000000000000000000000000060d131a20262b31353a3e4246494c4e5152545556575757575756555352504d4a4744403c38332e28231d171009020000000000000000000000000000000000000000060c101315151515151515151514120e0a040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e1214151515151515151514120f0a05000000000013202c3946535f6c798693a0aca4978a7d7063574a3d303030302f2e2a241e160d0400000000000008131f2a35414c57626d77828c9791877d736a61585b687582858585858275685b4f423528323d48535e69747f858585858581766a626b757e8993948a7f74695f54493d32271c100500000000000006121d2935414c58636e7a85909ba6b0a89e93897f756c635a524a433d38332f2c2a29282828292a2d2f33383d434a525a636c758089949ea9aca1978c81756a5f53483c3125190e02000000111d2a3743505c6976828f9ba8a5998c8074685c51453b322b2623222a343e49535d67717b858f99a2a69e98989ea49a8f84796e63584d42372c2c2e323434322d2821180f0600000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acb4aaa19c9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b988b7e7164574b3e3124180b0000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000c1925313e4a56626e7a87939eaaafa3978c8074695e53483d33281f160e0701000000000000000000000002081019232d38434e59646d6f6b6864605d5955524e473e352a1f1408000000101c2936434f5c697683909ca9aa9e9184776b5e5145382b1f120c1926323f4c5965727f8c99a6ada194877a6e6154483b2e22150916222f3c4955626f7c8996a2afa396897c6f6356493c3023160900000000000000000000000000020e1a26323e4955616d7884909ca8a99d91867a6e62564a3e36424e5a66727d8995a1ada3978c8074685c5145392d21160a00000000000000000000000000000007131f2c3844505c6874808b97a3aeada2968b80756a60554b41382f261e17110c08050300000205080c11171f272f38424c56606a75808a95938d88827c766f63574b3e3125180b000000000000000009141e28323d47515c66707a858f99a4a99e94897f746a5f554b40362b2d37424c57616c76818b96a0aba3998f847a6f655b50463b31271c1207000000000000000013202c3946535f6c798693a0aca79a8d8173675a4f5254555656565553504d49443e39322f373e444a4e52545656565554514e4b4740382f251a0f04000000000000000000000000000000010910171e252b31373c41464a4e5255585b5d5f61626363646464636261605e5c5a5754504c48443f3a342e28211b140c050000000000000000000000000000000000020a11181c20212222222222222222211e1a150e070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060e141a1e202121212121212121211f1b1610080000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024232323211e19130c04000000000000020d1925303b47525d68737e899494897f756b62584f5b6875828e92928f8275685b4f42352e39444f5a65707b869192928f857a6f645a636d76818b9591867b70655a4f43382d21160a0000000000000a16222e3a46515d6974808b96a1adaca1978c82776d635a51484039322c2723201d1c1b1b1b1c1e2023272c32384048515a636d77828d97a2ada89d92877b7065594d42362a1e1206000000121f2b3845515e6b7784919daaa3968a7d7064584c403429201a1d27323c46505a656f79838d97a1a89e958c8c96a0a1968b80756a5f54483d32262225272725221d160f060000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acafa398908e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8b7e7164574b3e3124180b0000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000915222e3a46525e6a76828e9aa5b1a89d91867a6f64594f443a31282018120d08050302010101020406090e131a222b353f4a545f6a767b7774706d6965625e5950473c3024180c000000101c2936434f5c697683909ca9ab9f9286796c6053463a2d21140d1926333f4c5966727f8c99a6afa295897c6f6356493d3024170b1623303c4956636f7c8996a2afa396897c6f6356493c302316090000000000000000000000000007131f2b37424e5a66727d8995a1ada5998d8175695d51463a323d4955616d7985919ca8a89c9185796d61554a3e32261a0f0300000000000000000000000000000b17232f3c4854606c7884909ca8b4a89c91857a6f64594e44392f261d140d0600000000000000000000060d151d26303a444e59636e79848d88827c76716b655d52473b2f22160a0000000000000000020c16212b353f4a545e69737d88929ca6a59b91867c71675c52473d33343e49535e68737d88939da8a79c92877d72685e53493e342a1f150a00000000000000000013202c3946535f6c798693a0aca79a8d8173675a5b5e6162636363615f5c59554f4a443d39414950555a5e6162636362605e5b57524a41362b2014080000000000000000000000000000030b131b222930363c42484d52565a5e6265676a6c6d6f6f70717170706f6e6d6b696663605c58544f4a453f39332c251e170f07000000000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2b26201910070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000710181f262a2d2e2e2e2e2e2e2e2e2d2b27211a120900000013202c3946535f6c798693a0aca4978a7d7063574a3d302417161615120d08010000000000000007131e2a35414c58636e7a8590978c82776d6359504e5b6875828e9b9c8f8275685b4f4235343f4a55606b76818c979e93897e73685d535b656f79848e988d82766b6055493e32271b0f0300000000020e1b27333f4a56626e7a85919ca8b2a69b90857a70655b51483f362e27201b1713110f0e0e0e0f1114171b21272e363f48515b66707b86919ca8afa3988d81756a5e52463b2f23170b000000131f2c3946525f6c7985929faba194887b6e6255483c3023181a242f39434e58626c76818b959fa9a0968c83848e99a49c91867b70655a4e43382c21191a1a1916110b04000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386828282828282828282828282828282828282828282828282828282828282828282827e7164574b3e3124180b0000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000005121e2a36424e5a66717d8995a0acaea2978c81766b60564c433a322a231d191512100e0e0d0e0f101216191e252c343d47515b66717c8784807c7975726e6a62584d4135281c0f030000101c2936434f5c697683909ca9ada194877b6e6255493c3024180d1a2733404d596673808c99a6b0a4978a7e7165584c3f33271a0e1723303d4a5663707d8996a3b0a396897c6f6356493c30231609000000000000000000000000000c1824303b47535f6b76828e9aa6aca094887c7064594d41352d3945515c6874808c98a4ada195897e72665a4e43372b1f130800000000000000000000000000010e1a27333f4b5864707c8895a1adafa3978b8074695d52473c32271d140b02000000000000000000000000030b141e28323c47525c68737e827c76716b65605a534b41362a1f1307000000000000000000040f19232e38424c57616b76808a959fa9a2988d83786e64594f443a3b46505b65707a858f9aa4aa9f958a80756b61564c41372d22180d0300000000000000000013202c3946535f6c798693a0aca79a8d81736764686b6d6f70706f6e6c6965605b554e47424b535a61666a6d6f70706f6d6a67635c53483c3124180c00000000000000000000000000040d151d252c343a41484e53595e62676a6e717476787a7b7c7d7d7d7d7d7c7b79777573706c6965605b56504b443e3730292119110900000000000000000000000000000a141d262e34383b3b3b3b3b3b3b3b3b3a37312b2219100500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f19222a31363a3b3b3b3b3b3b3b3b3a37322c241b1207000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a090805020000000000000000000b17232f3b46525e6974808b9691867b70665b51474e5b6875828e9b9c8f8275685b4f42353b46515c67727d88939e978d82776c61574c535d67727c879293887c71665a4f43372c2014080000000006121f2b37434f5b67737e8a96a2adaca1958a7e73695e53493f362d241c150f0b0704010000000205070b10151c242d36404a545f6974808b96a2aea99e92867a6f63574b3f33271b0e02000013202c3946535f6c798693a0aca094877a6d6054473a2d2117212c36414b555f6a747e88939da7a1978e847a7d88939ea3988d81766b6054493d32261b0f0e0c09050000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca0938679757575757575757575757575757575757575757575757575757575757575757575746d62564a3d3024170a0000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000010d1a26313d4955616c78848f9aa5b1a89d92877d72685e554c443c352e2925211e1c1b1a1a1b1c1d1f22252a30363e464f59636d77828d908c8985817e7a74695d5044372a1d11040000101c2936434f5c697683909ca9afa3968a7d7165584c4034291d131b2834414e5a6774818d9aa7b2a6998d8174675b4f43372b1f151824313e4b5764717d8a97a4afa296897c6f6256493c2f23160900000000000000000000000005111d2934404c58646f7b87939faaa79b8f84786c6054483c302834404c58646f7b87939faba69a8e83776b5f53473c3024180c0100000000000000000000000004111d2a36424f5b6774808c98a5b1ab9e93877b6f63584c41362b20160c020000000000000000000000000000020c16202b35404b56616d7776716b65605a544e4941392f24190e020000000000000000000007111c26303b454f5a646e78838d97a2aa9f958a80756b61564c41424d57626c77818c96a1aba2988d83786e64594f443a30251b10060000000000000000000013202c3946535f6c798693a0aca79a8d81736a7074777a7b7c7d7c7b7875716c666059514a545d656c72767a7c7d7c7b7976736e64594d4034271b0e000000000000000000000000050d161f272f373e454c53595f64696e73777a7d8183858788898a8a8a8a8a89888684827f7c7975716c67615c564f49423a332b231b120900000000000000000000000006111c262f383f4548484848484848484847433c342b21170c010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050e18212b343c4246484848484848484847433e362d23190e030013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a00000000000000000000000004101c2834404b57636e7a8691968a7f74695e5449424e5b6875828e9b9c8f8275685b4f4236414c57626d78838e999b91867b70655b50454b55606b76818c978e82776b5f54483c3024180c000000000a16222f3b47535f6b77838f9ba7b3a79b8f84786d62574c42372d241b120b040000000000000000000000040b121b242e38424d58636e7a85919da9aea3978b7f73675b4f43372b1e1206000013202c3946535f6c798693a0aca094877a6d6053473a2d211e28333d48525d67717c86909aa4a3998f857b7276818c97a39e93877c71655a4e43372c2015090000000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c686868686868686868686868686868686868686868686868686868686868686868645b51463a2e2115090000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000915212d3944505c67727e89949faaaea4998e847a70675e554d46403a35312d2b2928272727282a2c2e32363b41485058616b757f89949c9995918e8a81766a5d5044372a1e11040000101c2936434f5c697683909ca9b2a6998d8175685d51453a2f251f1e2936424f5c6875828e9ba8b4a89c9084776b5f53473c31271f1e26333f4c5965727e8b98a5aea295887b6f6255483c2f2216090000000000000000000000000a16222d3945515d6874808c98a3aea2978b7f73675b4f43382c242f3b47535f6b77838f9aa6ab9f93877b7064584c4035291d11050000000000000000000000000713202c3945525e6b7783909ca8b3a79a8e82766a5e52473b3024190e0400000000000000000000000000000000040e19242f3a45505b656b6b65605a544e49433d3730271d13080000000000000000000000000a141f29333d48525c67717b86909aa4a79c92877d72685d53494a545f69747e89939ea8a59b90867c71675c52483d33281e1309000000000000000000000013202c3946535f6c798693a0aca79a8d8173767b80848688898a898785817d77716b635b535c666f777d83868889898886838075685b4f4235281c0f0000000000000000000000040e171f283139414850575e646a70757a7e83878a8d8f929395969697979796959493918e8c8885817c78736d67615a534c453d352d241b120900000000000000000000000b17222d38424a51545555555555555555534e463d33281d110600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d17202a333d464d525454545454545454534f483f352b1f14080013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000000814202c3844505c6874808b979084796e63584d42424e5b6875828e9b9c8f8275685b4f423d48535e69747e8a959f958a7f74695f54493e444e5964707b869293887c7064594d4135291d10040000000d1926323e4b57636f7b8894a0abaea2968a7e73675c51463b30261b120900000000000000000000000000000009121c26313b47525d6975818c98a4b0a79c9084776b5f53473b2e2216090000131f2c3946525f6c7985929faba194877b6e6155483b2f2225303a454f5a646e79838d98a2a59b91877d736a707b86919da4998d82766b5f54483d31251a0e0200000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5852493f35291d11050000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000005101c28333f4a56616c78838e98a3adaba0968c837970675f58514b45413d3a3736353434343536383b3e42474c535a626a737d87919ba6a5a19d92877b7065594d4135291c0f030000101c2936434f5c697683909ca9b5a99d9185796d61564b41372f2b2b2c3845515e6a7784909da9b6aca094877b7064584d4239302c2a2b35424e5b6774818d9aa6ada194877a6e6154483b2e2115080000000000000000000000030f1b26323e4a56616d7985919ca8aa9e92867a6e62564b3f33271f2b37434e5a66727e8a96a2aea4988c8074695d5145392e22160a0000000000000000000000000916222f3b4854616d7a86939facafa3978a7e72665a4e42362a1f130800000000000000000000000000000000000007121d28343f49535b5f5f5a544e49433d38322c251e150b01000000000000000000000000020d17212c36404a555f69747e88939da7a3998f847a6f655a50515b66707b85909aa5a89e93897e746a5f554b40362b21160c02000000000000000000000013202c3946535f6c798693a0aca79a8d817a81878c90939596969694918d89837c756d655c646e7881898e9395969695928f8275685b4f4235281c0f00000000000000000000030d162029313a434b535a61686f757b81868b8f9396999c9ea0a1a2a3a4a4a4a3a2a19f9d9b9895918d88847e78726c655e574f473f362e241b1209000000000000000000000f1b27333f4a545c6161616161616161615f584f453a2e221609000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010b151f29323c454f585f6161616161616161605a51473c3024180c0013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000000c1824303c4855616c788490968a7e73685c51463b424e5b6875828e9b9c8f8275685b4f42434e59646f7a85909b998e83786d63584d42373d48535e6975818c988d8175695d5145392d211408000004101c2935424e5a67737f8b98a4b0aa9e92867a6e62564b3f34291e140a00000000000000000000000000000000000a141f2a35414c5864707c8894a0acaca094887b6f63564a3e3125190c0000121f2b3845515e6b7784919daaa296897c7063574b3e33272c37414c56616b76808b959fa79d93897f756b616975808b97a29e93887c7065594e42362a1f130700000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f534e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4c4740372e23180d010000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000b17232e3945505b66717c87919ba5afa89e948b8279716a635c56514d4946444241414041424345474a4e52575d646c747c858f99a3adaca1968c81756a5f54483d3125190d000000101c2936434f5c697683909ca9b4aca1958a7e73685d5349413b3837383d4854616d7986929fabb2aaa4988c81756a5f544b423c3837383b45515e6a76838f9ca8ac9f9286796c6053463a2d201407000000000000000000000008141f2b37434f5a66727e8a96a1ada5998d81756a5e52463a2e221a26323e4a56626d7985919da9a99d9185796d62564a3e32271b0f0300000000000000000000000b1825313e4a5763707c8996a2aeaca094877b6e62564a3e32261a0e02000000000000000000000000000000000000010c17222d3841494f52524e49433d38322c26211b140c030000000000000000000000000000050f1a242e39434d57626c76818b95a0aaa0968b81766c625758626d77828d97a2aba1978c82776d62584e43392e241a0f0500000000000000000000000013202c3946535f6c798693a0aca79a8d81838b92989c9fa2a3a3a2a09d99948e8780776e656a75808a939a9fa2a3a3a19c8f8275685b4f4235281c0f000000000000000000010b151f28323b434c555d656c737a81878c92979b9fa3a6a8a9a6a5a3a2a2a2a2a2a3a5a7a9a7a4a19d99948f8a847d7770686159514840372d241b1107000000000000000000121e2b37434f5b666d6e6e6e6e6e6e6e6e6a61564a3e3225190c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131d27313b444e57616a6e6e6e6e6e6e6e6e6b63584d4134281b0f0013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000030f1b2834404c5965717d89959185796e62574b4035424e5b6875828e9b9c8f8275685b4f424a55606b76818c979d92877c71675c51463b3137424d5864707b87939185796d6155493d3024180b000006131f2c3845515d6a76838f9ba7b2a69a8e8275695d51463a2e23180d020000000000000000000000000000000000030e1924303c48535f6c7884909ca9b0a4978b7f72665a4d4134281c0f0300101d2a3643505c6975828e9ba7a4988c7f73675b4f43382e333e48535e68737d88929da7a0958b81776d6359636f7a86919da4998d81766a5e53473b2f23180c00000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5346424242424242424242424242424242424242424242424242424242424242403c362e251c1107000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000006111d28333f4a55606a757f89939da7b0a69d948c837b746d67625d595653514f4e4d4d4d4e505154565a5e63696f767e868e97a1aaaea49a8f857a6f64594e42372c201409000000101c2936434f5c697683909ca9ada29b988f84796f655b534c47454445484e5965717d8995a2aeaaa0999892867b70665d544d48454445474c56626e7a86929fabaa9d9084776b5e5145382c1f120600000000000000000000010d1824303c48535f6b77838f9aa6aca094897d7165594d41352a1e16222d3945515d6975818c98a4ada2968a7e72665b4f43372b20140800000000000000000000000d1a2633404c5966727e8b98a4b1aa9d9184786b5f53463a2e211509000000000000000000000000000000000000000006111c262f373e434645433d38322c26211b151009020000000000000000000000000000000008121d27313b46505a656f79838e98a2a89d93887e73695f5f6a747f89949ea9a49a8f857a70655b51463c31271d12080000000000000000000000000013202c3946535f6c798693a0aca79b8f868c959da4a29f9c9b9a9a9b9c9e9f99918981776e6f7b87929ca5ababa49f9c9b8f8275685b4f4235281c0f00000000000000000009131d27313a444d565e676f767e858c92989da2a7aba7a39f9c9a9896969595959697989a9da0a3a7a9a5a09b958f88817a736b635a52493f362d23190f05000000000000000013202c3946525f6c777b7b7b7b7b7b7b7b73665a4d4033271a0d010000000000000000000000000000000000000000000000000000000000000000000000000000000000000007111b252f39434d56606a737b7b7b7b7b7b7b7b75695c504336291d100013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a000000000000000000000006121f2b3744505c6975818d998d8175695d51463a35424e5b6875828e9b9c8f8275685b4f45505b66717c87929d968b80756b60554a3f352a303c48535f6b77838f968a7d7165594c4034271b0f02000915222e3b4754606d7986929eabafa3968a7e7165594d4135291d12060000000000000000000000000000000000000008131f2b37434f5c6874818d99a6b2a79b8e8275695d5044372b1e1205000f1b2834414d5a66727f8b97a4a89b8f83776b60554a40363a454f5a656f7a858f99a4a2988e84796f655b525e6975808c98a39e92877b6f63584c4034281c1004000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f534639353535353535353535353535353535353535353535353535353535353533302b241c130a00000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000c17222d38434e58636d77818b959ea7afa69e958d867f78736e6965625f5d5c5b5a5a5a5b5c5e6063666a6f747a81889098a0a9afa69c92887d73685e53483c31261b0f04000000101c2936434f5c697683909ca9a79b908b908b81766d655d57535151525459606a75818d99a5b0a4988e8b928d82786f665e585452515153575e68737e8a96a2aea79a8e8275685c4f43362a1d10040000000000000000000006111d2935414c5864707c88939faba79c9084786c6054483d312519111d2935414c5864707c8894a0aba69b8f83776b5f54483c3024190d01000000000000000000000f1b2835414e5b6774818d9aa7b3a79b8e8275695c5043372a1e12050000000000000000000000000000000000000000000a141d252d3337393936322c26211b15100a04000000000000000000000000000000000000000b151f2a343e48535d67727c86919ba5a59a90857b706666717b86909ba6a79d92887d73685e54493f342a20150b000000000000000000000000000013202c3946535f6c798693a0acaba09792969ea19b9692908e8d8d8e8f92959a9b9389807673808c97a3aeaba29a938f8e8f8275685b4f4235281c0f000000000000000006111b252f39434c565f687078818890969da3a9aaa49f9b9793908d8b8a89888888898a8c8e9093979ba0a5aaa6a09a938c857d756c645b51483f352b21170c020000000000000013202c3946535f6c79868888888888888173675a4d4034271a0d01000000000000000000000000000000000000000000000000000000000000000000000000000000000000040f19232d37414b555f68727c858888888888877d73685c4f4336291d100013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a00000000000000000000000915222e3a4753606c78859195897c7064584c403535424e5b6875828e9b9c8f8275685b4f4c57626d78838e999a8f84796e64594e43392e232b37424e5a66727e8b978d8175685c5043372a1e1105000b1824313d4a56636f7c8895a1aeaca093877a6e6255493d3125190d0100000000000000000000000000000000000000030f1b27333f4c5864717d8a96a3afaa9e9185786c5f53463a2d201407000c1925313e4a56636f7b87939faba094887c71665c52483f414b56616c76818c96a1a59b91867c72675d534d58646f7b87939ea3978c8074685c5044382d211509000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5346392c2828282828282828282828282828282828282828282828282828282827241f19120a0100000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000006111c27323c47515b656f79838c959da6aea79f98918a847e7975726e6c6a686767676768696a6d6f72767a80858b929aa2aaaea69d948a80766c61574c41362b20150900000000101c2936434f5c697683909ca9a5998c7f89928980766f6863605e5d5e60646a727c87929ea9aca09488818c948a8178706964605e5d5e606368707a848f9ba7afa3978b7e7266594d4034271b0e02000000000000000000000a16222e3a45515d6975818c98a4afa3978b7f73675c5044382c20140c1824303c48545f6b77838f9ba7ab9f94887c7064584d4135291d120600000000000000000000101d293643505c6975828f9ca8b2a6998c8073665a4d4134281b0f02000000000000000000000000000000000000000000020b131b22272a2c2c2a26211b15100a04000000000000000000000000000000000000000000030d18222c37414b55606a747e89939ea8a1978d82786d6e78838d98a2aaa0958b81766c61574c42382d23180e03000000000000000000000000000013202c3946535f6c798693a0acb2a9a29fa19e96908a8683818181818386898e949a92887e76838f9ca8b0a49a90888382828275685b4f4235281c0f00000000000000030d18222d37414b555e68717a828b939aa1a8aca59f99948f8a8783817e7d7c7b7b7b7c7d7f8184878b8f94999fa5aba59e968f877e766d635a51473d33281e13090000000000000013202c3946535f6c798693959595958d8173675a4d4034271a0d010000000000000000000000000000000000000000000000000000000000000000000000000000000000010c16202b353f49535d67717a848e94949492887e756b61574c4034271b0e0013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a00000000000000000000000b1824313d4a56636f7b88949185796c6054483c3035424e5b6875828e9b9c8f8275685b50525d68737e89949e93887d72685d52473d32271c26323e4a56626e7b87939184786b5f5246392d201407000d1926333f4c5865727e8b97a4b0aa9d9084776b5f5246392d2115080000000000000000000000000000000000000000000b1724303c4955626e7b8794a0adada094877a6e6155483c2f221609000916222e3a47535f6b77838e9aa5a4998e83786e645a514947525d68737d88939da89e93897f746a60564c47535f6a76828e9aa59c9085796d6155493d3125190d000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5346392c201b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1a18140e08000000000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000000a15202a353f4a545d67707a838b949ca3aba9a29b958f8a86817e7b78777574737374747577797c7e82878b91969da4abaca49c948b81786e645a4f453a30251a0f0300000000101d2a3643505d697683909da9a5988c7e838e9289817a746f6c6b6a6b6d70757c858e98a3afa89c90847b8691938a827b75706d6b6a6b6c6f747a828c96a1acab9f93877b6f63564a3e3125180c00000000000000000000030f1b27333f4a56626e7985919da9aa9e92867a6f63574b3f33271c1008141f2b37434f5b67737e8a96a2aea4988d8175695d52463a2e22160b00000000000000000000111e2b3744515d6a7784909daab1a4978b7e7165584b3f3225190c0000000000000000000000000000000000000000000000010910161b1e201f1e1a15100a0400000000000000000000000000000000000000000000000006101a252f39444e58626d77818c96a0a99e94897f7475808a949fa9a3988e83796f645a4f453b30261b110700000000000000000000000000000013202c3946535f6c798693a0acb9b3aea79d948c847e7a777573737476797d838990988f857a85929eabab9f93887e7775767873675b4e4235281b0f0000000000000009141f2a343f49535d67707a838c949da4aca9a29b948e88837e7a777472706f6f6e6f6f717275777b7e83888e949ba2a9a8a19990887f756c62594f453a30251b100500000000000013202c3946535f6c798693a0a2a29a8d8173675a4d4034271a0d01000000000000000000000000000000000000000000000000000000000000000000000000000000000008131d28323d47515b656f79838c96a09e948a80766c63594f453b2f23170b0013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a00000000000000000000000d1a2633404c5965727e8b978e8275695d5044382c35424e5b6875828e9b9c8f8275685d5d5d646f7a85909b978c81766c61564b41362b2016222e3a46525f6b77849094877a6e6155483c2f231609000e1b2834414e5a6774818d99a6b3a79b8e8275685c4f43362a1e11050000000000000000000000000000000000000000000814212d3a46535f6c7885929eabafa296897d7063574a3d3124170b0006121e2a37434e5a66727d89949fa99f948a80756c635b534e59646f79848f9aa4a1978c82776d63584e44424e5a65717d8995a1a195897d7165594d4135291d11040000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5346392c20130f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0e0b080300000000000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000040e19232d38424b555e687179828a9299a0a6aca6a19b96928e8a878583828181818181828486888b8e92979ca2a8afa8a29a928a82786f665c52483e33291e13080000000000101d2a3643505d697683909daaa5988b7e7c8792938b85807b79777778797c81878e97a0aaada2978b80747f8994948c86817c79787777797b80858c949ea8b0a59a8e83776b5f53463a2e221509000000000000000000000814202c37434f5b67737e8a96a2aea59a8e82766a5e52463b2f23170b030f1b27333f4a56626e7a86929ea9a99d91867a6e62564a3f33271b1004000000000000000000121f2c3845525e6b7885919eabb0a396897d7063574a3d3124170a00000000000000000000000000000000000000000000000000050a0f111313110e0a0400000000000000000000000000000000000000000000000000000009131d28323c46515b65707a848e99a3a69b91867c7c87919ca6a69b91877c72675d52483e33291e140a0000000000000000000000000000000013202c3946535f6c798693a0acb9b5aa9f958b827a736e6a686767686a6d71777e868e978c818693a0ada79b8e82766c68696c6961564b3f33261a0d00000000000004101b26303b46505b656f79838c959ea6aea89f979089827c77726e6b68656463626262636466686b6e73777d838990979fa8aba29a91887e746b61564c41372c21160b00000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0100000000000000000000000000000000000000000000000000000000000000000000000000000000050f1a252f3a444e59636d77818b959ea1968c82786e645a51473d34291e13070013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a00000000000000000000000f1c2835424e5b6774818d988c7f73665a4d41342835424e5b6875828e9b9c8f82756a6a6a6a6a75808b969b90857a70655a4f453a30281e151e2a36434f5c6875818e96897d7064574a3e3125180b00101c2936434f5c6975828f9ba8b2a6998c8073665a4d4134271b0e0200000000000000000000000000000000000000000005121e2b3744515d6a7783909da9b1a4988b7e7265584c3f3226190c00020e1a26323e4a55616c77828d98a2a69c91887e756d655e575f6a75808b96a1a59a90857a70655b51463c3d4955616d7985919da59a8e8275695d5145392d2114080000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5346392c20130b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0a0906020000000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000000007111c263039434c565f67707880878e959ba1a7aba7a29e9a979492908f8e8d8d8e8e8f909295979b9ea3a8ada9a39d97908881786f665d544a40362c22170c020000000000101d2a3743505d6a7683909daaa4988b7e75808a9496908c888684848586898c9298a0a9aea59b90857a6e78828c9597918c888684848486888b90979ea6b0a79e93887d72665a4e42362a1e1206000000000000000000010d1925313c4854606b77838f9ba7ada195897d7165594e42362a1e1206000a16222e3a46525d6975818d99a5aea2968a7e73675b4f44382c201408000000000000000000131f2c3946525f6c7985929facafa295887c6f6255493c2f2316090000000000000000000000000000000000000000000000000000000205060605020000000000000000000000000000000000000000000000000000000000010b16202a353f49535e68727d87919ca6a2988e83838e98a3a99e948a7f756a60554b41362c21170d020000000000000000000000000000000013202c3946535f6c798693a0acb9afa4988e83797068625e5b5a5a5b5d61666c747c858f92898b95a1aea4988b7e72665b5d5f5d584f453a2e23170a0000000000000a16212c37424d58626d77818b959ea7b0a79e968d867e77716b66625e5b5957565555555657595c5f62676c71777e868d959ea7aca39a90877c72685e53493e33281d1106000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000000000000000000000000000000000000000000000000000000000000000000000000000000010c16212c36414b56606a757f89939da4998f857a70665c52483f352b22170d020013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000111d2a3743505d6976838f968a7d7064574b3e322835424e5b6875828e9b9c8f827777777777777c87929d94897e74695f59524a423a30271d1b2734404d5966727f8c988b7e7265594c3f3326190d00111e2a3744505d6a7783909da9b1a4978b7e7165584b3f3225190c0000000000000000000000000000000000000000000003101c2936424f5c6875828f9ba8b2a6998c8073665a4d4033271a0d00000a16212d39444f5b66717b86909aa3a39a90877f776f686266717c87929da79e93897e73695e54493f353844505c6874818d99a59e9286796d6155493d3024180c0000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5346392c2017171717171717171717171717171717171717171717171717171717171715120d0801000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000a141e27313a434d555e666e757c848a90969ba0a4a8aaa6a3a09e9d9b9a9a9a9a9b9c9d9fa1a4a7aba9a6a29d98928c857e766e665d544b42382e241a1005000000000000111d2a3744505d6a7784909daaa4978a7d7178828c959c9894929191919395999da3aaaba49c93897f7469707a838d959d9895929191919294989ca1a8aca69e958c82776c6055493e32261a0e0200000000000000000006121e2935414d5965707c8894a0aba89c9084786c6155493d3125190e020006121d2935414d5965717c8894a0aca79b8f84786c6054483d3125190d02000000000000000013202c3946535f6c7986939facaea295887b6e6155483b2f221508000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040e18232d37424c56606b75808a949ea99f958c8c95a0aaa1978d82786d63584e44392f241a1005000000000000000000000000000000000013202c3946535f6c798693a0acb6aa9e93877c71675e56524f4d4d4e51555b626a737d879295969da6afa396897d7063575052514d463d33291d1206000000000005101b27323d48535e69747e89939da6b0a89e958c847b746d66605b56524f4c4a49484849494b4d4f52565b60666c747b848c959ea8aca2988f847a6f655a4f44392e23170c000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0100000000000000000000000000000000000000000000000000000000000000000000000000000007121d28333d48535d68727c87919ba59c92877d73685e544a40362d23191006000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000121e2b3845515e6b77849194887b6e6255493c2f2835424e5b6875828e9b9c8f84848484848484848d989b8e827975706a645c544c42392f251a25323e4b5764717d8a978d8173675a4d4134271b0e00121e2b3845515e6b7784919eaab0a3968a7d7063574a3d3124170b00000000000000000000000000000000000000000000000e1b2834414e5b6774818e9aa7b4a79a8e8174675b4e4134281b0e000005111c28333e49545f69747e88919ba3a2999189817a736d6c77828d98a3a2978c82776c61574c42382d34404c5864707c8995a1a2968a7d7165594d4034281b0f0300000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5346392c24242424242424242424242424242424242424242424242424242424242424221e19130b030000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000000000020c151f28313a434c545c636b72787f858a8f94989c9fa2a4a7a8a9a8a7a7a7a7a8a8aaa9a7a5a3a09d9a96918c87817a746c655c544b423930261c120800000000000000111e2b3744515d6a7784919ea2a2968a7d70707a838b939a9f9f9e9e9e9fa1a5a9a7a49f99928a81776d6268717a838b93999f9f9e9e9e9fa1a4a8a8a5a09b948c837a70655a4f44382d21160a000000000000000000000b17232e3a46525e6975818d99a4afa3978b8074685c5044382d2115090000010d1925313c4854606c7884909ca7aca094887c7165594d41362a1e1206000000000000000013202c3946535f6c798693a0acaea194887b6e6155483b2e2215080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007111b25303a444f59636e78828c97a1a79e98989ea7a49a90857b70665c51473c32271d130800000000000000000000000000000000000013202c3946535f6c798693a0acb2a69a8e82766b60554c454241414245495058616b75808b96a2a7afafa295887b6f6255494645413b342b21170c0100000000000a16212d38434f5a65707b86909ba5afa99f968c837a7269625b554f4a4642403e3c3c3c3c3d3e4043464a4f555b6269717a838c96a0aaaaa0968c81766c61564a3f34281d11060000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d010000000000000000000000000000000000000000000000000000000000000000000000000000030e19242f39444f5a646f79848e98a3a0958b80756b61574c42382e251b110800000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000121f2c3945525f6c78859293877a6d6054473a2e2835424e5b6875828e9ba0969190909090909090959f9c908986817c756e665e544b41372c2123303d4956636f7c89968e8175685b4e4235281b0f00121f2c3945525f6b7885929fabafa296897c6f6256493c3023160900000000000000000000000000000000000000000000000d1a2733404d5a6673808d9aa6b3a89b8e8275685b4f4235281c0f0000000b16222d38434d58626c768089919aa2a39b938c857e78737d89949fa69b91867b70655b50453b3026303c4854606c7985919da69a8d8175695c5044372b1f120600000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f53463931313131313131313131313131313131313131313131313131313131313131302e2a241d150c0200000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000000030d161f28313a424a525960676d73797e83888c8f9395989a9c9d9e9f9f9f9f9f9e9d9c9a999694918d8a85817b756f69625a534b423930271e140a0100000000000000121e2b3845515e6b77849195959595897c6f68717981888e94989b9d9f9f9f9f9d9b98948e8881786f655b5f68717981888e93979b9d9e9f9f9f9e9b99959089827a71685e53493e33271c110500000000000000000004101c27333f4b57626e7a86929da9aa9f93877b6f63574b4034281c10040000000814202c3844505b67737f8b97a3afa5998d81756a5e52463a2f23170b000000000000000013202c3946535f6c798693a0acaea195887b6e6155483b2e221508000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009141e28333d47515c66707b858f9aa4a8a4a4a8a79d93887e73695f544a3f352b20160b0100000000000000000000000000000000000013202c3946535f6c798693a0acafa2968a7d71655a4e433a36343435393e464f59636e7a85919da9b5aea295887b6e6155483b3835302a22190f050000000000030f1b26323e4954606b76828c97a2acaca2988e847a716860585049433e3a363331302f2f2f303134363a3e444950585f68717a848e98a2ada89e93887d72675c5045392e22170b0000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d05060708080808070504010000000000000000000000000000000000000000000000000000000009141f2a35404b56616b76818b96a0a4998e84796e64594f453b30261c13090000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a000000000000000000000013202c3946535f6c7986939386796c5f5346392d2835424e5b6875828e9ba39a96969696969696969696989a95928d87807870665d53483e3327222f3c4855626f7b88958f8275685b4f4235291c0f00131f2c3946525f6c7986929facaea295887b6f6255483c2f22150900000000000000000000000000000000000000000000000d192633404c596673808c99a6b2a89c8f8275685c4f4236291c0f00000005101b26313c46505a646d7680889098a0a59d96908a847e848f9aa5a0958a7f74695e54493e3429212c3844505c6975818e9a9c989185786c6053473b2e22150800000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f53463e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3d3a352f271e140a00000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000000040d161f28303840474e555c62686d73777c808386898b8d8f9091929293929291908f8e8c8a8785817d7975706a645e575049413930271e150c020000000000000000131f2c3946525f6c78858888888888887b6f62676f777d83888c8f9192939292918e8c88837d766e665d53565f676f767d82878b8e9092929392918f8c89847e7870685f564c42372c21160b000000000000000000000915202c3844505b67737f8b96a2aea69a8e82766a5e53473b2f23170b0000000004101b27333f4b57636e7a86929eaaa99e92867a6e63574b3f33281c10040000000000000013202c3946535f6c7986929facaea295887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020c16212b35404a545e69737d88929da8b1b1aba0968b81766c62574d42382e23190e040000000000000000000000000000000000000013202c3946535f6c798693a0acaca093877a6e6155493d32292727292d343d47525d6974808c98a4b1aea295887b6e6155483b2e29251f18100700000000000008141f2b37434e5a66717c88939ea9b0a59b90867c72685f564e463f38322e2a2724232222222325272a2e33383f464e565f68727c86919ba6afa49a8f84786d61564a3f33271c100400000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a10121314151515141312100e0b0804000000000000000000000000000000000000000000000000040f1a25313c47525d67727d88929da79d92877c72675d52483d33291f140a010000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a000000000000000000000013202c3946535f6c7986939286796c5f5246392c2835424e5b6875828e9b9d91898989898989898989898b8e939998928a82786f655a4f44382d222e3b4855616e7b88958f8275695c4f4236291c0f0013202c3946535f6c798693a0acaea295887b6e6155483b2e22150800000000000000000000000000000000000000000000000c1926323f4c5965727f8c99a6b2a99c8f8275695c4f4236291c0f000000000a151f2a343e48525b646d767e868e959ca3a19b958f8a8b95a0a59a8f84786d63584d443e38332d2834404d5965717e8a94908c89857c6f6256493c3023160900000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f534a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a46413930261c1105000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000000000000000040d161e262e363d444b51575c62676b6f73777a7c7e81828485858686868585848381807d7b7875716d69645f59534c463e372f271e150c0300000000000000000013202c3946525f6c777b7b7b7b7b7b7b796d615d656c72777c7f82848586868584827f7c77726b645c544b4d565d656b71767b7e8284858686858482807c78736d665e564d443a30251b1005000000000000000000020e1925313d4954606c7884909ba7ada195897d72665a4e42362a1e130700000000000b17232f3a46525e6a76828e99a5aea3978b7f73675c5044382c21150900000000000000121f2c3945525f6b7885929fabafa296897c6f6356493c3023160a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050f19232e38424d57616b76808c99a6b3b5a89c8f84796f655a50453b31261c1107000000000000000000000000000000000000000013202c3946535f6c798693a0acaa9d9184786b5f5246392d211b1a1c222b36414c5864707c8895a1adaea295887b6e6155483b2e2219140d06000000000000000c1824303c48545f6b76828e99a4afaa9f94897e746a60564d443c342d27221d1a181615151617181b1e22272d343c444d56606a747f8a94a0ababa095897e72675b4f44382c20140800000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a1c1e202121222221201f1d1a1714100c07010000000000000000000000000000000000000000000915202b37424d58636e79848f99a4a2978c81766b60554b40362b21170d03000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a000000000000000000000013202c3946535f6c7986939386796c5f5346392c2835424e5b6875828e9b9c8f827c7c7c7c7c7c7c7c7d7e82888f979c948b81766c60554a3e32262f3c4855626e7b88958f8275685c4f4236291c0f0013202c3946535f6c7986929facaea295887b6e6155483b2f22150800000000000000000000000000000000000000000000000d1926333f4c5966727f8c99a6b2a99c8f8275695c4f4236291c0f00000000030e18222c364049525b646c747c838b91989ea4a09b96969da79f93887d7267605a554f4a443e3831313d4956626e7a878784807c79756c6155483c2f22160900000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c5f5757575757575757575757575757575757575757575757575757575757575757575756524b42382d22160a000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000000000000040c141c242b323940464c51565b5f63676a6d70727475777878797979787877767473716e6c6865615d58534e48423b342c251d150c0300000000000000000000121e2b37434f5b666d6e6e6e6e6e6e6e6d675c535a61666b6f737577787979787775736f6b66605a534a42444c535a60666b6f72757778797979777673706c67625b544c443b32281e14090000000000000000000007121e2a36424d5965717d8994a0aca89c9185796d6155493d32261a0e02000000000006121e2a36424d5965717d8995a1ada79c9084786c6055493d31251a0e02000000000000121e2b3845515e6b7784919eaab0a3968a7d7064574a3e3124180b0000000000000000000000000000000000000000000000000003060809080502000000000000000000000000000000000000000000000000000000000000000000010b151f2a343e49535d67727c86919ca8b4b5a99c90867b71675c52483d33291e140a000000000000000000000000000000000000000013202c3946535f6c798693a0aca99c8f8376695d5043372a1e110e101924303c4854606c7985929eaaaea295887b6e6155483b2e221508020000000000000004101c2834404c5864707c88939faaafa4988d82776c62584e443b322a221c16110e0b0a0909090a0c0e12161c222a323b444e58626d78838e9aa5b1a69a8f83786c6054483c3024180c00000013202c3946535f6c798693a0aca79a8d8173675a4d40342726292b2c2e2e2e2e2e2d2b292724201c17120d0700000000000000000000000000000000000000040f1b26313d48535e6975808b95a0a79b90857a6f64594f44392f241a0f0500000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000131f2c3946525f6c79859293867a6d6053473a2d2835424e5b6875828e9b9c8f82756f6f6f6f6f6f6f7072767d858e989d93887d72665a4e42362a303c4956626f7c89958e8275685b4f4235281c0f00131f2c3946525f6c7986929facafa295887b6f6255493c2f22160900000000000000000000000000000000000000000000000d1a2633404d596673808c99a6b3a89c8f8275685b4f4235281c0f000000000006101a242e374049525a626a727980878d93999ea3a2a3a7a89b8f827a75706b66605b554f49433c353a46525f6b777e7b7774706c69645b5044392c20140700000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386796c6464646464646464646464646464646464646464646464646464646464646464646464635d54493e32261a0e020000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000000000000020a121921272e343a40454a4f53575b5e61636567696a6b6c6c6c6c6c6b6a69686664625f5c5955514c48423c363029221b130b0300000000000000000000000f1b27333f4a545c6161616161616161615d554b4f555b5f6366696b6c6c6c6b6a6966635f5b554f4841383a41484f555a5f6366686a6b6c6c6c6b696764605c56504a423b322920160c02000000000000000000000b17232f3b46525e6a76828d99a5afa4988c8074685c5045392d211509000000000000020d1925313d4955616c7884909ca8aca095897d7165594e42362a1e1307000000000000111d2a3744505d6a7683909ca9b1a4988b7e7265584c3f3326190d0000000000000000000000000000000000000000000000050b0f13151514120e0a060200000000000000000000000000000000000000000000000000000000000008121d27313c46505a656f79848e98a3adaaaaada2988d83786e64594f453a30261b11070000000000000000000000000000000000000013202c3946535f6c798693a0aca89b8e8275685b4f4235281c0f0208131f2b3844505d6976838f9ca8aea295887b6e6155483b2e22150800000000000000000814202c3945515d6975818c98a4b0aa9e93877c71665b50463c32292018110a05010000000000000002060b11182029323c46515c67727d8994a0ababa094887d7165594d4135281c1004000013202c3946535f6c798693a0aca79a8d8173675a4d403430333538393a3b3b3b3b39383633302c28231e18120b0400000000000000000000000000000000000915202c37424e5964707b86919ca7a1968a7f74695e53483d32271d12080000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000121f2b3845515e6b78849194887b6e6155483b2f2835424e5b6875828e9b9c8f82756862626262626263666b737c86919c9a8e83776b5e5246392d313e4a5764707d8a968d8174675a4e4134281b0e00121f2c3845525f6b7885929eabafa296897c6f6356493d3023160a00000000000000000000000000000000000000000000000e1b2734414d5a6773818d9aa6b3a89b8e8175685b4e4235281b0f00000000000008121c252e374048505860676e757b82888d9398a1acb3aa9d928b86817c77716c66605a544e474039434f5b6770726f6b6764605d5952493e33281c100400000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca09386797171717171717171717171717171717171717171717171717171717171717171717171716e665b4f42362a1d10040000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000000000000000000080f161d23292f353a3f43474b4e525457595b5c5d5e5f5f5f5f5f5e5d5c5b59575553504d4945403c37312b251e181009010000000000000000000000000b17222d38424a51545555555555555554514b43444a4f53575a5c5e5f5f5f5f5e5c5a57534f4a443d362f2f373d44494e5356595c5e5f5f5f5f5e5d5a5854504b453f38312920170e040000000000000000000004101c28343f4b57636f7a86929eaaab9f93877b6f64584c4034281c1005000000000000000915212c3844505c6874808c97a3afa5998e82766a5e52473b2f23170c000000000000101c2936424f5c6875828e9ba8b3a6998d8074675a4e4135281c0f030000000000000000000000000000000000000000000810161b1f2122211e1a16120e0a0602000000000000000000000000000000000000000000000000000005101a242e39434d58626c76818b95a0aaa39e9ea2a99f958a80766b61574c42372d23180e0400000000000000000000000000000000000013202c3946535f6c798693a0aca79a8e8174675b4e4134281b0e01030f1c2835424e5b6774818d9aa7aea295887b6e6155483b2e22150800000000000000000b1824303c4955616d7985919da9b1a5998d82766b5f54493f342a20170e0600000000000000000000000000060e17202a353f4a55606c77838f9ba7b1a5998d8175695d5145382c201407000013202c3946535f6c798693a0aca79a8d8173675a4d40383c3f4244464748484847464542403c38342f29231d160e06000000000000000000000000000000030e1a26313d48545f6a76818c97a2a69b9084796e62574c41362b21160b010000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000111e2a3744505d6a76839096897c7063574a3e312835424e5b6875828e9b9c8f8275685b5555555555575a616a74808b979f93877a6e6255493c3033404c5965727e8b988c7f7266594c4033261a0d00111e2b3844515e6b7784919daab0a3978a7d7064574a3e3124180b00000000000000000000000000000000000000000000020f1c2835424f5b6875818e9ba7b3a69a8d8174675a4d4134271b0e000000000000000a131c252e363e464e555d636a70767c8287909ca8aca7a49c97928d88827d77726c655f58524b433f4a555e6566635f5b5854504d4740372d22170c0000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaca093867d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d776a5e5144382b1e11050000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000000000000000000040b12181e24292e33373b3f4245484a4c4e4f515152525352525251504e4d4b494643403d3935302b26201a140d06000000000000000000000000000006111c262f383f45484848484848484848454039393e43474b4d50515253535251504d4b47433e39332c25252c32383e42474a4d4f515253535251504e4b48443f3a342d261f170e0500000000000000000000000915212d3844505c6873808b97a3afa69a8e83776b5f53473b2f24180c000000000000000004101c2834404b57636f7b87939faaaa9e92877b6f63574b4034281c100500000000000e1b2734414d5a6773808d99a6b2a89b8f8276695d5044372b1f1206000000000000000000000000000000000000000009121a21272c2e2f2e2a26221e1a16120e0a060100000000000000000000000000000000000000000000030d17212c36404b555f69747e88939da7a399929199a3a79c92877d73685e54493f352a20160b01000000000000000000000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000d1a2633404c596673808c99a6aea295887b6e6155483b2e22150800000000000000020e1b2733404c5865717d8995a1adaca094887c7165594e43382d22180e05000000000000000000000000000000050e18232e39444f5b67727e8a96a2aea99d9185796d6155483c3023170b000013202c3946535f6c798693a0aca79a8d8173675a4d4044484c4f5152545455555453514f4c4844403a352e2720181008000000000000000000000000000008131f2b36424e5965707b87929ea9a1958a7e73685c51463b30251a0f04000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a00000000000000000000000f1c2935424f5b6874818e988b7e7265594d40342835424e5b6875828e9b9c8f8275685b4f494949494a4f58636f7b8794a0968a7d7164574b3e3236424f5b6874818d978a7d7164584b3e3225180c00111d2a3743505d697683909ca9b1a5988b7e7265594c3f33261a0d0000000000000000000000000000000000000000000005111e2a3743505d6976838f9ca9b2a5998c7f7266594c4033261a0d00000000000000010a131c242d343c444b52585f656b7178838f9ba8a19b9a9ea29e99938e89837d77716a635c554d45434c54585956534f4b4844413c362e251b10060000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acaea1968c8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a84776b5e5144382b1e11050000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000000000000000000000000070d13181d22272b2f3236393b3e4041434445454646464545444342403e3c3a3734302d29241f1a150f0902000000000000000000000000000000000a141d262e34383b3b3b3b3b3b3b3b3b39352f2d32373b3e414345464646454443413e3b37322d28211a1a21272d32363a3e414344454646464543413f3c38332e29231c150d050000000000000000000000020e1a26313d4955616c7884909ca8ada2968a7e72665a4e42372b1f13070000000000000000000b17232f3b47535f6a76828e9aa6afa3978b8074685c5044392d21150900000000000c1926323f4b5865717e8a97a3b0aa9e9185786c6053473b2e22160a0000000000000000000000000000000000000007111b242c33383b3c3a36322e2a26221e1a16120c050000000000000000000000000000000000000000000a141f29333e48525c67717b86909aa5a69c928787919ca6a4998f857a70655b51463c32271d1308000000000000000000000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000c1925323f4c5865727e8b98a5aea295887b6e6155483b2e2215080000000000000005111e2a37434f5c6874818d99a5b2a89c9084786c6054493d32261b1106000000000000000000000000000000000007111c27333f4a56626e7a86929eabaea295897d7164584c3f33261a0e010013202c3946535f6c798693a0aca79a8d8173675a4d4c5054585b5d5f60616161615f5e5b5855504b464039322a221a1108000000000000000000000000010c1824303c47535f6a76818d98a4a79c9084796d62564b4035291e130800000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a00000000000000000000000e1a2734404d5966727f8b988e8175685c5043372b35424e5b6875828e9b9c8f8275685b4f423c3c3c3e46535f6b7885919e988c7f7266594c3f333945525e6a77839094887b6f6256493c3023170a000f1c2935424f5b6875818e9ba7b3a69a8d8174675a4e4135281c0f030000000000000000000000000000000000000000000714202c3946525f6b7884919eaab0a4978a7e7164584b3e3225180c0000000000000000010a121b232a323940474d545a66717d8994a0a4988f8d92979ca19f9a948e88827b756e675f574f4742484c4d4a46433f3c3834302b241c1309000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acb2a79e9897979797979797979797979797979797979797979797979797979797979797979797979184776b5e5144382b1e11050000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000000000000000000000000000000001070c12161b1f2326292c2f3133353637383939393939383736353432302d2b2824211d18140f0904000000000000000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2d292422272b2f3234363839393939383634322f2b27221c161010161c21262a2e3134363839393939383735322f2c28231d18110a0300000000000000000000000007131f2a36424e5a65717d8995a1aca99d9185796d61564a3e32261a0e0200000000000000000007131f2a36424e5a66727d8995a1ada89c9084786d6155493d32261a0e02000000000a1724303d4956626f7b8894a1adada194887b6f63574b3e32261b0f030000000000000000000000000000000000020e19232d363e44474846433e3a36322e2a26221d160f060000000000000000000000000000000000000007121c26303b454f5a646e78838d97a2a99f958a807f8a949fa9a1968c82776d62584e43392f241a10050000000000000000000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e221508000000000000000714202d3946525f6b7884909da9b1a4988c8074675b4f44382c20150a000000000000000000000000000000000000000b16222e3a46525e6a76828f9ba7b1a5998d8074675b4f4236291d10040013202c3946535f6c798693a0aca79a8d8173675a51575c6164676a6c6d6e6e6e6d6c6a6865615c57514b443c342c231a1107000000000000000000000005111d2935404c58646f7b87929ea9a2968b7f73685c51453a2f23180d0200000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a00000000000000000000000c1825313e4a5763707c89959184786c5f53473b2f35424e5b6875828e9b9c8f8275685b4f42352f2f3744505d6a7784909d998d807366594d40333d4955616e7a86939185796c6053473a2e211508000e1b2734404d5a6673808c99a5b2a89c8f8276695d5044372b1f12060000000000000000000000000000000000000000000a17232f3c4855616d7a8793a0acaea295897c6f6356493d3023170a0000000000000000000009111920272f353c46525e6a76828e9aa59e938782868b91969ba19f99938d8780787169615950473e3f403e3a37332f2c28242019120a01000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0acafafa9a5a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a49e9184776b5e5144382b1e11050000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000000000000000000000000000001060a0f13161a1d2022242628292b2b2c2c2c2c2c2b2b2a28272523211e1b1814100c0803000000000000000000000000000000000000000000020a11181c20212222222222222222201d18161b1f2225282a2b2c2c2c2c2b2a2825221f1b16110b05050b10151a1e222527292b2c2c2c2c2b2a282623201c17120c0600000000000000000000000000000c18232f3b47535f6a76828e9aa5b0a4988c8175695d5145392d21160a00000000000000000000020e1a26323d4955616d7985919da8ada195897d72665a4e42372b1f1307000000000815212e3a4753606c7985919eaab0a4988b7f73675b4f43372b201409000000000000000000000000000000000008131f2a353f484f5455534f4b47433e3b37332e2821180f050000000000000000000000000000000000050f19232e38424d57616b76808a959fa9a2988d837878838d98a2a89e93897f746a60554b41362c22170d0200000000000000000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e221508000000000000000a16232f3c4855616e7a8793a0acaea195897c7064574b3f33271b10040000000000000000000000000000000000000006111d2935424e5a66737f8b98a4b1a89c9083776a5e5145382c1f13060013202c3946535f6c798693a0aca79a8d8173675a5d63686d717476787a7b7b7b7a797774716d68625c554e463e352c23191006000000000000000000000916212d3945515d6975808c98a3a99d91867a6e62574b4034291d12070000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a00000000000000000000000916222f3b4854606d79869294887b6f63574b403435424e5b6875828e9b9c8f8275685b4f423b3b3c3e44515d6a7784909d998d807366594d4036414d5965717d8a968e8276695d5044382b1f1206000c1925323f4b5864717d8a97a3b0aa9e9185786c6053473b2e22160a0000000000000000000000000000000000000000020e1a26333f4b5764707d8996a2afac9f93867a6d6154473b2e2215080000000000000000000000070e161d26323e4a57636f7b87939fa5998d82767b80858a8f959ba19e98918a837b736b625950463c33312e2a2723201c18140e080000000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c798693a0a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a29e9184776b5e5144382b1e11050000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000000000000000000000000000000000003070a0e111316181a1b1d1e1f1f1f201f1f1f1e1d1c1a191714120f0c08040000000000000000000000000000000000000000000000000000060c101315151515151515151513110c0a0f1316191b1d1e1f20201f1e1d1b1916130f0a0500000000050a0e1216181b1d1e1f20201f1f1d1c191713100b0601000000000000000000000000000005111d2834404c58636f7b87939eaaab9f94887c7064584c4035291d110500000000000000000000000915212d3945515c6874808c98a4b0a69a8e82766b5f53473b3024180c0000000006121f2b3844505d6975828e9aa7b3a79b8f83776b5f54483c31261b1006000000000000000000000000000000020d1824303b47515a60625f5b57534f4b47433f3a332a21170d02000000000000000000000000000000020c16212b35404a545e69737d88929ca7a59b90867b71717b86909ba5a59b91867c71675d52483e33291f140a00000000000000000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e221508000000000000000c1825323e4b5764707d8a96a3afab9e9286796d6054483b2f23170b0000000000000000000000000000000000000000010d1925323e4a5763707c8995a2aeab9f9286796d6054473a2e2115080013202c3946535f6c798693a0aca79a8d81736761686e74797d81838587888888878683817d78736d67605850473e352b22170d030000000000000000020e1a26323e4a56626d7985919da8a5998d8175695d52463a2f23180c010000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a000000000000000000000007131f2c3845515d6976828e988c8074685c50453935424e5b6875828e9b9c8f8275685b4f484848484a4e56616d7985929e988c7e7265594c3f3b46525e6a76828e978b7e72665a4d4135281c0f03000a1723303c4955626f7b8894a0adada194887b6f63574b3e32261b0f030000000000000000000000000000000000000007131f2b37434f5b6773808c98a5b1a99d9084776b5e5245392c20130600000000000000000000000005111d2a36424e5a67737f8b97a3a094887c716f74797e848a90969da39c958d857d746b62584e43392e231e1b1713100c0803000000000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c79869395959595959595959595959595959595959595959595959595959595959595959595959595959595959184776b5e5144382b1e11050000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000000000000000000000000000000000000000000010407090b0d0f10111212131313131211100f0e0c0a0805020000000000000000000000000000000000000000000000000000000000000004070808080808080808080704010003060a0c0f11121313131212100f0c0a060300000000000000000206090c0e10121213131312110f0d0a070400000000000000000000000000000000000a16212d3945515c6874808c97a3afa79b8f83776b5f53483c3024180c00000000000000000000000005111c2834404c5864707b87939fabaa9f93877b6f64584c4034291d1105000000030f1c2835414d5a66727e8a97a3afab9f93887c7064594d42372c22180e0500000000000000000000000000010a141f2a35404c58636c6e6b67635f5b57534f4b443c33291e130700000000000000000000000000000009141e28323d47515c66707a858f99a4a89e93897e746a69747e89949ea9a2988e83796e645a4f453b30261c1107000000000000000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e221508000000000000000e1a2733404d5966727f8c98a5b1a99c8f83766a5d5144382c1f13070000000000000000000000000000000000000000000916222f3b4854616d7a86939facaea195887b6f6256493c3023170a0013202c3946535f6c798693a0aca79a8d8173676b72797f85898d9092939495949492908d89847f78726a625950473d33291f140a000000000000000005121e2a36424e5a66727e8a96a2aca094887c7064594d41352a1e1207000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a000000000000000000000004101c2935414d5a66727e8a969084786d61564a3f35424e5b6875828e9b9c8f8275685b5555555555575a6068727d8995a196897d7064574b3e414c57636e7a869293877a6e62564a3e3125190c00000814212e3a46535f6c7885919daab0a4988b7f73675b4f43372b201409000000000000000000000000000000000000020d18242f3b47535f6b7783909ca8b2a69a8d8174685c4f43362a1d11040000000000000000000000000814202d3946525e6a77838f9ba79c9084786c63686d73787e858b9299a19f978f867d746a60554b4035291e130b0703000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946535f6c79868888888888888888888888888888888888888888888888888888888888888888888888888888888888888884776b5e5144382b1e11050000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030f1a26323e4a55616d7985919ca8aea2968a7e72675b4f43372b1f1308000000000000000000000000000c1824303b47535f6b77838f9aa6afa3988c8074685d5145392d22160a000000000c1925313d4a56626e7a86929eaab0a4988d81756a5f54493e342a20170f070100000000000000000000040b131c26303b46515d69747b77736f6b67635f5b564e453b2f24180c000000000000000000000000000007111b25303a444f59636d78828c97a1aba1968c82776d62626d77828c97a1aa9f958b80766c61574d42382e23190e040000000000000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e221508000000000000000f1c2835424e5b6874818e9aa7b3a79a8d8174675b4e4235291c10030000000000000000000000000000000000000000000713202c3945525e6b7884919daab0a3978a7d7164574b3e3125180b0013202c3946535f6c798693a0aca79a8d81736c757d848b9095999c9ea0a1a2a1a09f9c9995908a837c746b62594f453b31261b1005000000000000000915222e3a46525e6a76838e9aa6a89c9084786c6054483c3025190d01000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000000d1925313d4956626e79859195897d72665b50453a424e5b6875828e9b9c8f82756861616161616263666b717a848f9a9d9186796d6155483c47525d6874808b978e82766a5e52463a2e221509000005121e2b3744505c6975828e9aa6b2a79b8f83776b5f53483c31261b100600000000000000000000000000000000000a141f2a35404c58636f7b8793a0acaea2968a7d7165594c4033271b0e020000000000000000000000000a1723303c4955616e7a87939fa4988c8073675b5d62676d737980878f97a0a1988f867c71675c51463a2f23180c0000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070013202c3946525f6c787b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b766a5e5144372b1e11050000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000000000000000000000000000000000000000000000001050708080808080808080808060300000000000000000000000000000000000000000000000000000000000000000000000004070808080808080808080807040000000000000000000000000000000000000000000000000000000105070808080808080808080808070400000000000000000000000000000000000000000008131f2b37434e5a66727e8995a1ada99d91867a6e62564a3e32271b0f030000000000000000000000000007131f2b37434f5a66727e8a96a2aea89c9185796d61564a3e32261b0f030000000915212e3a46525e6a76828e9aa5b1a99d92877b70655a50463c32292119120d0805030101010203060a0f151c252e38424c57636e7985837f7b77736f6b6760574c4034281c0f03000000000000000000000000040e18232d37424c56606b75808a949ea8a4998f857a70655b5b65707a85909aa5a79d92887d73695e544a3f352b20160c0100000000000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e22150800000000000000101d2a3643505c6976838f9ca9b2a5988c7f7266594c4033271a0d0100000000000000000000000000000000000000000004111d2a3743505d6976838f9ca9b2a5988c7f7266594c3f3326190d0013202c3946535f6c798693a0aca79a8d8173757e878f969c9e9c9a999898999b9ea2a7a5a19b958e867d746b61574d42382d22170b000000000000000d1925313e4a56626e7a87939faba4988c8074685c5044382c20140800000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000000915212d3945515d6975818c988f83786c61564b41424e5b6875828e9b9c8f82756e6e6e6e6e6e6e7072767c838c96a0978c8175695d5145434d58636e7a859195897d72665a4e42362a1e12060000030f1b2834414d5965727e8a96a2aeab9f93887c7064594d42372c22180e0500000000000000000000000000000009121c26303b46515d6874808c98a4b0aa9e92867a6e6155493d3024180b000000000000000000000000000d1926333f4b5864717d8a96a2a194887c6f635751565c62686f767d858e97a0a1988e83786e62574b4034281c100400000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d20140700121e2b3743505b666d6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6d655a4e4236291d10030000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000000000000000000000000000000000000000001080d111415151515151515151514130f0b050000000000000000000000000000000000000000000000000000000000000000060c10131515151515151515151513100c06000000000000000000000000000000000000000000000001070d1114151515151515151515151513100c07000000000000000000000000000000000000010c1824303c47535f6b77838e9aa6b0a4998d8175695d51453a2e22160a0000000000000000000000000000030f1a26323e4a56626d7985919da9ada1968a7e72665a4f43372b1f140800000005111d2a36424e5a65717d8994a0abaea3988d82776c62584e443b332b241e1915110f0e0e0e0e1013161b20272e374049545e69747f8b8f8b87837f7b7772685d5044372b1e11050000000000000000000000010b16202a343f49535e68727c87919ba6a79c92887d73685e54545e69737e88939da8a49a8f857a70665b51473c32281d130900000000000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e22150800000000000000111e2b3744515e6a7784909daab0a4978a7d7164574b3e3125180b00000000000000000000000000000000000000000000010f1c2835424e5b6875818e9ba7b3a69a8d8173675a4d4134271a0e0013202c3946535f6c798693a0aca79a8d81747e8890999a96928f8d8c8c8c8d8f92969ba1a8a6a09890877d73695f54493e33281c1105000000000004101c2935414e5a66727e8b97a3ada194887c7064584b3f33271b0f0300000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a00000000000000000000000005111d2935414d5864707b879294897e73685d5248424e5b6875828e9b9c8f827b7b7b7b7b7b7b7b7c7e82878e959e988f857a6f64584d414a545f6a75808b968f84786d6155493d32261a0e020000000c1825313d4955626e7a86929eaab0a4988c81756a5f54493e342a20170f08020000000000000000000000040a121b242d38424d58636e7985919ca8b1a69a8e82766a5e5245392d211408000000000000000000000000000f1c2835414e5a6774808d99a59e9185786c6053474b51575d646b737c858e98a39f958a7f73685c5045382c20140800000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d201407000f1b27333f4a545c61626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262615b53483d32261a0d010000000000000000000815222e3b4855616e7b8895a1a1a1988b7e7165584b3e3225180b0000000000000000000000000000000000000000000000000000040c13191d20222222222222222222211f1b1610080000000000000000000000000000000000000000000000000000000000020a11181c2021222222222222222221201c18110a020000000000000000000000000000000000000000040c13191d202222222222222222222221201c18120a020000000000000000000000000000000005111d2935404c5864707b87939fabaca094887c7064584d4135291d11050000000000000000000000000000000a16222d3945515d6975818d98a4b0a69a8e83776b5f53483c3024180d010000010d1925313d4955616c78838f9aa5b0a99e93897e746960564d453d352f2925211e1c1b1a1a1b1d1f22262b32394049525b65707a85909b97938f8b8783786b5e5145382b1e1205000000000000000000000009131d27323c46515b656f7a848e99a3aa9f958b80766b61574c4d57616c76818c96a1aba1978c82786d63594e44392f251a1006000000000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e22150800000000000000121f2c3845525e6b7885929eabafa396897c706356493d3023170a00000000000000000000000000000000000000000000000e1b2734414d5a6773818d9aa6b3a79b8e8174685b4e4135281b0f0013202c3946535f6c798693a0aca69a8d807b869099958f8a8683817f7e7f8082868a90979ea7aaa2998f857b70665b5044392d22160b00000000000713202c3845515d6a76828e9ba7aa9d9185786c6054483b2f23170b0000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a000000000000000000000000010d1824303c48535f6a76818c988f84796f645a50464e5b6875828e9b9d91888888888888888888898b8e93999c968f867d73695e534747515c66717b8691958a7e73675c5044392d211509000000000915212d3945515d6975818d99a5b0a99d92877b70655a50463c3229211a130e090603020101010204070a0f151c242d363f49545e6974808b96a1adaca195897d71665a4d4135291d110500000000000000000000000002111d2a3743505c6976828f9ca89b8f8276695d50443f454c5259616a737c86919ca69b9085796d6155493c3024170b00000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d201407000b17222d38424a515555555555555555555c646869696969696969665e5555555556606769696969696969686259555555555555555554504941372c211509000000000000000000000815222e3b4855616e7b8894949494948b7e7165584b3e3225180b00000000000000000000000000000000000000000000000000040d161e24292d2e2e2e2e2e2e2e2e2e2e2b27211a1209000000000000000000000000000000000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2c28231c140b02000000000000000000000000000000000000040d161d24292d2e2e2e2e2e2e2e2e2e2e2e2c28231c140c020000000000000000000000000000000a16222e3945515d6974808c98a4aca79b8f83776c6054483c3024190d0100000000000000000000000000000005111d2935414c5864707c8894a0acab9f93887c7064584c4135291d11060000000915212d3844505b67727d89949faab0a59a90857b72685f574e47403a35312d2b2928272728292b2e32373d434a525b646d77828c97a2a39f9b958a7e73675b4f43372a1d11040000000000000000000006101a252f39444e58626d77818c96a0aaa2988e83796e645a4f4545505a656f7a848f99a4a89e94897f756a60564b41372c22180d030000000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e22150800000000000000131f2c3946525f6c7985929facafa295887b6f6255493c2f22160900000000000000000000000000000000000000000000000d1a2633404d596673808c99a6b3a89b8f8275685b4f4235281c0f0013202c3946535f6c798693a0aca6998c80828d98918a837e79767472727273767a7e858c959ea7aba1978d82776c61554a3e33271b0f04000000000a16232f3b4854616d7986929eaaa69a8e8175695c5044382b1f13070000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000000008141f2b37424e5965707b8691968b81766c61584e4e5b6875828e9b9f9a95959595959595959596989b9996918b847d746b61574c465059636d78828d988e83786d61564b3f34281c10050000000005111d2935414d5965717c88949fabaea3988d82776c62584e443b332b241e191512100f0e0d0e0f1113161b20272e363f48515b65707b86919ca7b2a79b9084786d6155493d3125190d0100000000000000000000000005121f2b3845515e6b7784919da69a8d8174675a4e41353a41484f58616a75808b96a2a195897d7164584c3f33261a0d01000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070006111c2630384045484848484848484956626d75757575757575757065594c484f5b677275757575757575746a5f524848484848484848443f372f251a1004000000000000000000000815222e3b4855616e7b888888888888887e7165584b3e3225180b000000000000000000000000000000000000000000000000020c161f282f35393b3b3b3b3b3b3b3b3b3a38332c241b110700000000000000000000000000000000000000000000000000000a141d262e34383b3b3b3b3b3b3b3b3b3b38342e261d140a0000000000000000000000000000000000010c161f282f35393b3b3b3b3b3b3b3b3b3b3b39342e261e140a0000000000000000000000000000000e1b27323e4a56626d7985919da0a0a0968b7e73675b4f43372c20140800000000000000000000000000000000010c1824303c4854606b77838f9ba0a0a0988c8175695d51453a2e22160a00000004101c28333f4a56616c77828d98a2adaca1978d847a71696059524b46413d3a37353434343536383b3e43484e555c646d768089939ea8b0a59a8f84796d62564b3f33271b0e02000000000000000000030d18222c36414b55606a747e89939da8a69b91867c71675d52483d3e49535e68737d88929da7a69b91877c72675d53483e34291f150a0000000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e2215080000000000000013202c3946535f6c7986929facaea295887b6e6255483b2f22150800000000000000000000000000000000000000000000000d192633404c5966727f8c99a6b2a89c8f8275695c4f4236291c0f0013202c3946535f6c798693a0aca5988c7f899490878078726d6a67666565676a6e737a838c959faaa99e94897d72665b4f44382c201408000000000c1925323e4b5764707c8995a2aea3978a7e7265594d4034281c0f030000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a00000000000000000000000000030f1a26313d48535f6a75808b9592887d736960564e5b6875828e92929292929292929292929292918f8d8985807a736b62594f464f58626b75808a9492887d72675c50453a2e23170b0000000000010d1925313d4854606b77838e99a4afa99e93887e746960564d453d36302a25221f1d1b1a1a1b1c1d2023272c32384048515a636d77828c97a2adaca1968a7f73685c5045392d211509000000000000000000000000000613202c3946525f6c7986929fa5998c7f7266594c40332f363d464f58636e7a86929ea5998d8174675b4e4235281c0f02000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d20140700000a141e262e34393b3c3c3c3c3c3e4a5764717d8282828282828174675a4d43505d6976828282828282827a6d6053473c3c3c3c3c3c3b38342d251d130900000000000000000000000815222e3b4854616d797b7b7b7b7b7b7b7a7164584b3e3125180b00000000000000000000000000000000000000000000000008131e28313a414648484848484848484847443e362d23190e0300000000000000000000000000000000000000000000000006111c262f383f4548484848484848484848453f382f261c11060000000000000000000000000000000008131e28313a4045484848484848484848484845403830261c11060000000000000000000000000000111e2a37434f5b66727e8a939393939392867a6e62564a3f33271b0f0300000000000000000000000000000000000814202b37434f5b67737e8a93939393939185796e62564a3e3225190c000000000b17222e3944505b66717b86919ba5afa99f968c837a726a635d57514d49464442414041414345474b4f545960666e767f88919ba5b0a99e94897e73685c51453a2e22170b000000000000000000000b151f29343e48535d67717c86909ba5a99e94897f746a60554b403637414c56616b76818b95a0aaa3988e84796f655a50453b31261c120700000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e2215080000000000000013202c3946535f6c798693a0acaea295887b6e6155483b2e22150800000000000000000000000000000000000000000000000c1926323f4c5965727f8c99a6b2a99c8f8275695c4f4236291c0f0013202c3946535f6c798693a0aca69a8f898e92887e756d67615d5b5958595a5d62697079838d98a3aea59a8f83776c6054483c3024180c000000020f1b2834414d5a6673808c98a5ada094887b6f6256493d3124180c000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a00000000000000000000000000000915202b37424d58636e79848e988f857b72685f565b68758286868686868686868686868686858483807d79746f68615950475058616a747d8791968b81766b60554a3f34281d12060000000000000814202c38434f5b66717d88939ea9afa59a90857b72685f574f48413b36322e2b2928272727282a2c2f33373d434a525a626c757f89949ea9b0a59a8f84796e62574b4034281c1005000000000000000000000000000613202c3946535f6c798693a0a5988b7e7265584b3f32252c343d47525d6976828f9ba89c8f8376695d5043362a1d1004000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070000020c141c23292d2f2f2f2f2f313e4a5764717d8a8f8f8f8f8e8174675a4d43505d6976838f8f8f8f8f877a6d6053473a2f2f2f2f2f2e2c28221b130b0100000000000000000000000713202d3945515d676d6e6e6e6e6e6e6e6e695f54483c3023170a0000000000000000000000000000000000000000000000010d1925303a434c52555555555555555555544f483f352a1f14080000000000000000000000000000000000000000000000000b17222d38424a5154555555555555555554514a42382d22170b000000000000000000000000000000040f1a252f3a434b515455555555555555555554514a42382d22170b0000000000000000000000000000131f2c3946525f6b7783868686868686868175695e52463a2e22160b000000000000000000000000000000000000030f1b27333f4a56626e7a86868686868686867e73665a4d4034271a0e0000000006111d28333e49545f6a747f89939da6b0a89e958d847c756e68625d595552504f4e4d4d4e4f5154575b5f656b71788088919aa3adaba1978d82776c61564b4034291d120600000000000000000008121c27313b46505a646f79838e98a2aca1978c82776d63584e44392f303a454f5a646f79848e99a3aaa0958b81766c62574d43382e23190f04000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e2215080000000000000013202c3946525f6c7986929facaea295887b6f6255483c2f22150900000000000000000000000000000000000000000000000d192633404c596673808c99a6b2a89c8f8275695c4f4236291c0f0013202c3946535f6c798693a0acaba19996968b80766c635c56514e4c4c4c4e51575e67717b86919da8aba094887c7065584c4034281c0f03000005111e2a3743505c6975828f9ba7aa9e9185786c5f53473a2e211508000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000000000040f1a26313c47525c67727c8791978e847a7168605a6773797979797979797979797979797978777674716d69635d564f4a5159626a737c868f988e84796f645a4f44392e23170c0100000000000004101b27333e4955606b76828c97a1acaca1978d847a71696159524c47423e3a3836353434343536383b3f43484e555c646c757e87919ba5b0a99e94897e73685c51463a2f23170c00000000000000000000000000000613202c3946535f6c7986939fa5988c7e7265594c3f3226222b35414e5a6774818d9aa79d9084776a5d5144372a1e1104000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d201407000000020b12181d202222222224313e4a5764717d8a979c9c9a8e8174675a4d43505d697683909c9c9c94877a6d6053473a2d2222222222201c17110a0100000000000000000000000004111d2935404b555c6161616161616161615e574d43382c201407000000000000000000000000000000000000000000000005121e2a36414c565d616161616161616161605a51473c3024180c0000000000000000000000000000000000000000000000000f1b27333f4a545c616161616161616161615c544a3f33271b0f0300000000000000000000000000000b16212b36414c555d61616161616161616161615c544a3f33281b0f0300000000000000000000000000131f2c3946525f6b767979797979797979797165594d4135291e1206000000000000000000000000000000000000000a16222e3a46525d697579797979797979797972665a4d4034271a0e00000000000b17222d38434d58636d77818b949ea7afa89f968e878079736e6965625f5d5b5b5a5a5b5c5e6063676b70767c838a929aa3acaca2998f857b70665b50453a2f23180c010000000000000000050f1a242e38434d57626c76818b959faaa49a8f857a70665b51473c322728333d48525d67727c87919ca6a79d93887e73695f544a40352b21160c020000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e22150800000000000000121f2c3945525f6c7885929facafa295897c6f6255493c2f23160900000000000000000000000000000000000000000000000d1a2733404d5a6673808d99a6b3a89b8e8275685b4f4235281c0f0013202c3946535f6c798693a0acb3aaa59b9084796e645a514a4541403f3f41464d555f6a75808c98a3afa5998d8175695c5044382b1f130600000714202d3946525f6b7885919eaaa89b8f8276695d5044372b1e1206000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a00000000000000000000000000000009141f2a35404b55606a757f8993968d837a726a6161696c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6b696764615d58524c4d545c636b747c858e9890867c72685d53483d32271c110600000000000000000a16222d38444f5a65707b85909aa4aea99f968d847b736b645d57524e4a47444341414041424345484b4f545960666e767e879099a3adaba1978c82776c61564b4035291e1207000000000000000000000000000006121f2c3945525f6b7885929ea6998d8073675a4e42362f2e2e34414d5a6773818d9aa69d9184776a5d5144372a1e1104000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d2014070000000000070c11141515151724313e4a5764717d8a97a4a79a8e8174675a4d43505d697683909da9a094877a6d6053473a2d201515151513100c060000000000000000000000000000010c18242f39434b51545454545454545454524d453c31261b0f0400000000000000000000000000000000000000000000000814212d3a46525d686e6e6e6e6e6e6e6e6e6c63584c4034281b0e020000000000000000000000000000000000000000000000121e2b37434f5b666d6e6e6e6e6e6e6e6e6d665b4f43372b1e12050000000000000000000000000007121c27323d48535d676e6e6e6e6e6e6e6e6e6e6d665b5044372b1f120500000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c685f54483d3125190d010000000000000000000000000000000000000006121d2935414d58636a6c6c6c6c6c6c6c6c6c6960564a3e3225190c000000000005101b26313c46515b656f79828c959da6aea8a098918b847e7a75716e6c6a6867676767696a6c6f73777c81878e959ca4acaba29a90877d73695f54493e33281d12070000000000000000020d17212b36404a555f69737e88929da7a79d92887e73695e544a3f352a20212c36414b56606b75808a959faaa49a90857b71665c51473d32281e13090000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e22150800000000000000121f2b3845515e6b7884919eabb0a396897d7063564a3d3024170a00000000000000000000000000000000000000000000000e1b2834414e5b6774818d9aa7b4a79a8e8174675b4e4135281b0e0013202c3946535f6c798693a0acb9aea2968a7e73685d5248403935333233353b434d58646f7b87939faba99d9185786c6054473b2f22160900000916222f3b4854616e7a8793a0ada6998d8073675a4e4135281c0f03000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a000000000000000000000000000000030e19242f39444e59636d77818a94958d847b736c645d5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5e5d5b5855514c4c52585f666d757d868e9791887e746a60564c41362c21160b00000000000000000005101c27323e49535e69737e88929ca5afa89f968d857d756f69635e5a5653514f4e4d4d4d4e505254575b60656b717880889099a2abaca2998f857b70665b50453a2f23180d01000000000000000000000000000004111e2b3844515d6a7783909da89b8f82766a5e52473f3b3a3b3e46515c6975828e9ba79c908376695d5043372a1d1004000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d20140700000000000000040708090b1724313e4a5764717d8a97a4a79a8e8174675a4d43505d697683909daaa094877a6d6053473a2d20140909080704000000000000000000000000000000000007121d273139404547484848484848484846413b332a20150a0000000000000000000000000000000000000000000000000916222f3c4955626e7a7b7b7b7b7b7b7b7b75695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946525f6c777b7b7b7b7b7b7b7b776c5f5246392c201306000000000000000000000000030e18232e39444e59646f797b7b7b7b7b7b7b7b7b786c5f5346392d201306000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5d564d43382c2014080000000000000000000000000000000000000000010d1925303c4751595e5f5f5f5f5f5f5f5f5f5d574e44392d2216090000000000000a15202a353f49535d677079838b949ca4abaaa39c96908a86817e7b787675747373747577797c7f83888d92989fa6aea9a19990887e756b61574d42382d22170c0100000000000000000a141e29333d48525c66717b85909aa4aaa0958b81766c61574d42382d23191a242f39444e59636e78838d98a2aca1978d82786e63594f443a30251b100600000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e22150800000000000000111e2b3744515d6a7784909daab1a4978a7e7164584b3e3225180c0000000000000000000000000000000000000000000003101d2936424f5c6875828f9ba8b3a6998d8073665a4d4034271a0e0013202c3946535f6c798693a0acb6aa9e92867a6e62564b40362e2926252629313c47535f6b77838f9ba8ada195887c7063574a3e3125190c00000b1724313d4a5663707c8996a2afa4978b7e7165584c3f3226190d00000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000000000000007121d27323c47515b656e78818a94968e857d766f68615b5652525252525252525252525251504e4c494d52575d6369707880878f9891887f756c62584e443a2f251a0f05000000000000000000000b16212c37424d57626c76808a939da6aea89f978f87807a746f6a6663605e5c5b5a5a5a5b5c5e6164676b70767c838a929aa2ababa39a90877d73695e54493e34291d120700000000000000000000000000000001101d2936424f5b6874818d9aa69e92867a6f6459514b4847484a5058626d7985919da79a8e8175685b4f4235291c1003000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2ada094877a6d6053473a2d20140700000000000000000000000b1724313e4a5764717d8a97a0a09a8e8174675a4d43505d697683909da0a094877a6d6053473a2d20140700000000000000000000000000000000000000000008131e28313a414649494949494949494947423c342a20160a0000000000000000000000000000000000000000000000000916222f3c4955626f7c888888888888888376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798688888888888886796c5f5346392c2013060000000000000000000000000a141f2a35404a55606b7681888888888888888881766b5f5246392c201306000000000000000000000000000a16212c3740484f52535353535353535353514c443b31261b100400000000000000000000000000000000000000000008141f2a353f474e52535353535353535353514c453c32281d1105000000000000030e18232d37414b555e677079828a9299a0a7ada7a19b96928d8a8785838281818181828486888b8f93989ea4aaaca59e978f877e756c63594f453b31261b1106000000000000000007111c26303a454f59646e78838d97a1aca3998e84796f645a50453b30261c11131d28323d47525c67717c86919ba6a99f948a80756b60564c41372d22180e03000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e22150800000000000000101d2936434f5c6975828f9ca8b2a5998c7f7366594d4034271a0e0100000000000000000000000000000000000000000006121f2b3844515e6a7783909da9b1a5988b7e7265594c3f3226190c0013202c3946535f6c798693a0acb3a79a8e8276695d51463a2f241d1a1919202b36424e5b6773808c98a5b1a4988b7f72665a4d4134271b0e02000c1926323f4c5865717e8b97a4afa295897c6f63564a3d3024170b00000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a00000000000000000000000000000000010b16202b353f49535c666f78818a92978f888179736d67615c5853504d4a484746464647494b4d5154595d62686e747b828a919890887f766d635a50463c32281e1308000000000000000000000005101b26303b46505a646e78818a949ca4aca9a199928b85807a76726f6c6a696767676768696b6d7073777c81878e949ca3acaaa29991887e756b61574d42382d22170c01000000000000000000000000000000000e1a2733404c5965717e8a96a2a3978b80756b635c57555454565b616a747e8a95a1a3978b7e7266594d4034271a0e0100000000000000000000000000000000000003070a0b0b16222f3c4955626f7c8996a2ada094877a6d6053473a2d20140700000000000000000000000b1724313e4a5764717d8a939393938e8174675a4d43505d6976839093939393877a6d6053473a2d2014070000000000000000000000000000000000000000010d19242f3a434c52555555555555555555534e463c32271c100400000000000000000000000000000000000000000000000916222f3c4955626f7c899595959595908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693959595959386796c5f5346392c201306000000000000000000000006101b26313c46515c67727c879295959595958f857a6f645a4f43372a1e11050000000000000000000000000005101a252e373e434646464646464646464644403a32291f150a00000000000000000000000000000000000000000000030e19232d353d424546464646464646464645413b332a21160b000000000000000007111b252f39434c555e67707880888f959ca2a7aca7a29e9a969491908e8e8d8d8e8f909295989b9fa4a9aba6a09a948d857d756c635a51473d33291f140a0000000000000000040e19232d38424c57616b75808a949fa9a69c91877c72675d53483e33291f140a0b16202b35404a555f6a747f8a949ea9a69c91877c72685d53493e342a1f150b000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e221508000000000000000f1b2835414e5b6774818d9aa7b3a79a8e8175685b4f4236291d11040000000000000000000000000000000000000000000815212e3a4753606c7985929fabafa3968a7d7064574a3e3124180b0013202c3946535f6c798693a0acb0a4978b7e72665a4d4135291e120d0c0e1a26323f4b5764707d8996a2afa79b8e8275685c4f43362a1d1004000e1a2734404d5a6673808c99a6ada094877a6e6154483b2f22150900000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000000000000000040e19232d37414a545d666f7881899198928b847e78726d6864605c595755545353535456575a5d6165696e737980868d94968f877e766d645b51483e342b20160c0100000000000000000000000009141f29343e48525c666f78818a929ba2aaaba49d96918b86827e7b79777574747374747677797c8083888d92999fa6aea7a09890887f766c63594f453b30261b100600000000000000000000000000000000000b1824313d4955616d7985919ca79d92877d746d676361616163676c737c86909ba69e92877b6e62564a3d3125180c000000000000000000000000000000000002090f1316181818222f3c4955626f7c8996a2ada094877a6d6053473a2d20140700000000000000000000000b1724313e4a5764717d8686868686868174675a4d43505d6976838686868686867a6d6053473a2d201407000000000000000000000000000000000000000005111d2935414c565d6262626262626262625f584e43382c20140800000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2a2a29c908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693a0a2a2a09386796c5f5346392c20130600000000000000000000010c17222d38424d58636e78838e99a2a2a29d93887d73685d53483d32261a0e02000000000000000000000000000009131c252c32373939393939393939393938342f2820170d03000000000000000000000000000000000000000000000007111b232b3136393939393939393939393835302921180f0400000000000000000009141d27313a434c555e666e767d848b91969ca1a5a9aaa6a3a09e9c9b9a9a9a9a9b9d9fa1a4a7aba8a49f9a958f89827b736b635a51483f352b21170d0300000000000000010c16202b353f49545e68737d87929ca6a99f948a80756a60564b41362c22170d02040f19242e39434e58636d78828d97a2aca3998e847a6f655b50463b31271c12080000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e221508000000000000000d1a2633404c5965727e8b98a4b1a99d9084776a5e5245392c2014080000000000000000000000000000000000000000000c1824313d4956626f7b8894a1adada194887b6e6255493c2f23160a0013202c3946535f6c798693a0acaea195887c6f63564a3e3125190d01000a16232f3c4855616e7a8793a0adaa9d9084776b5e5145382c1f1206000f1c2835424e5b6875818e9ba7ac9f9286796c6053463a2d20140700000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a00000000000000000000000000000000000007111b252f38424b545d666e777f878e95968f89837e78746f6c6866636261605f6061626466696d71757a7f858b9198938c847c746c645b52493f362c23190f0400000000000000000000000000020d18222c36404a545d666f78818990989fa5aca8a29c97928e8b888684828181818181828486898c9094999ea4aaa9a39d958e867e756d645a51473d33291f140a0000000000000000000000000000000000000815212d3945515d6974808b96a0a39990877e7873706e6d6e6f73777e858e98a2a2978c81766a5e52463a2e22150900000000000000000000000000000000050d141a1f23252525252f3c4955626f7c8996a2ada094877a6d6053473a2d20140700000000000000000000000a1724313d4a57636f797979797979797972665a4d434f5c687479797979797979776c6053463a2d20140700000000000000000000000000000000000000000714202d3946525d686e6f6f6f6f6f6f6f6f6a6055493c3023170a00000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2aea99c908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000008131e29333e49545f6a747f8a95a0aaaca1968c81766c61564c41372c21160a000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2b28241e160e050000000000000000000000000000000000000000000000000009111920262a2c2c2c2c2c2c2c2c2c2c2c29241f170f0600000000000000000000020c151f28313a434c545c646b727980858b9095999da0a3a5a7a9a9a8a7a7a7a7a8a9a9a7a5a29f9c98948f8a847e777069615951483f362d23191005000000000000000008131e28323c47515b66707a858f99a3aca2978d82786e63594e44392f251a1005000007121c27323c46515b66707b86909ba5aaa0968b81776c62584d43392e24190f0300000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e221508000000000000000b1825313e4a5763707c8996a2aeac9f93867a6d6155483c3024180c000000000000000000000000000000000000000004101c2834404d5965727e8a97a3b0ab9e9285796c6053463a2d2114080013202c3946535f6c798693a0acac9f9386796d6054473b2e22150900000714202d3946525f6c7885919eabac9f9286796c6053463a2d20140700101d293643505c6976828f9ca9aa9e9184786b5e5245382b1f120500000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000000000000000000009131d263039424b545c656d747c838a9197948f8984807c787572706e6d6d6c6d6d6f717376797d81868b9096968f89817a726b625a524940372d241a110700000000000000000000000000000006101a242e38424b545d666e777e868d949aa0a6aba8a39e9b979492908f8e8d8d8d8e8f919395989ca0a4a9a9a49e98928b847c746c635b52483f352b21170d0200000000000000000000000000000000000005111d2935414c58636e79848e98a1a299908a84807c7b7a7a7c7e83898f97a0a29990857b7065594e42362a1e1206000000000000000000000000000000040e171f262b2f31323232323c4955626f7c8996a2ada094877a6d6053473a2d20140700000000000000000000000916222e3b47535e676c6c6c6c6c6c6c6c6960564a404c58626a6c6c6c6c6c6c6c6b655b4f44372b1f120500000000000000000000000000000000000000000815222e3b4855616e7a7c7c7c7c7c7c7c7b7164584b3e3225180b00000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000040f1a252f3a45505b65707b86919ca6afa59a8f857a6f655a4f453a2f251a0f0400000000000000000000000000000000010910161a1e1f2020202020202020201f1c18130c05000000000000000000000000000000000000000000000000000000070f151a1d1f2020202020202020201f1d19130d06000000000000000000000000030d161f28313a424a525961676e747a7f84898d909496999b9c9e9e9f9f9f9f9e9d9c9a989693908c88837e78736c665f574f473f362d241b11080000000000000000010d19242f3a444e59636d77828c96a1aba59a90857b71665c51473d32281d1309000000000b15202a353f4a545f69747e89939ea8a89d93897e74695f554a40362b20140900000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e221508000000000000000916222f3b4854616d7a86939facaea296897d7165584c4034281d1106000000000000000000000000000000000000000a15212d3844515d6975818e9aa6b3a89b8f83766a5d5144382b1f12050013202c3946535f6c798693a0acaa9e9184786b5e5245382c1f1306000005111e2b3744515d6a7783909da9ada194877b6e6155483b2f22150800111e2a3744515d6a7784909daaa99d9083776a5d5044372a1e110400000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a00000000000000000000000000000000000000010b141e273039424a535b636a727980868c929895908c8885817e7d7b7a7979797a7b7d808285898d919696918b847e7770686159514840372e251b1208000000000000000000000000000000000008131c263039424b545c656d747b83898f959a9fa4a7aba7a4a19f9d9c9b9a9a9a9b9c9d9fa2a4a8aaa6a29d98938d878079726a625a514940362d23190f0500000000000000000000000000000000000000010d1824303b47525d68727c868f979fa29b95908c89888787898b8f949aa1a09890877e74695e53483d31251a0e020000000000000000000000000000010c16202930373c3e3e3e3e3e3e4955626f7c8996a2ada094877a6d6053473a2d201407000000000000000000000006121f2b36414c555c5f5f5f5f5f5f5f5f5d574e443b4650595e5f5f5f5f5f5f5f5f5a53493e33271b0f0300000000000000000000000000000000000000000815222e3b4855616e7b888989898989897e7165584b3e3225180b00000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000b16212b36414c57616c77828d98a2ada89e93887e73685e53483e33281e130900000000000000000000000000000000000000050a0e111313131313131313131312100c0701000000000000000000000000000000000000000000000000000000000004090e111313131313131313131312100d08020000000000000000000000000000040d161f28303840484f565d63696e73787c8184878a8c8e9091929292929292908f8e8c898683807c77726d67615b544d453d352d241b120900000000000000000005121e2a35414b56606a757f89949ea0a09d93897e74695f544a40352b20160c0100000000040e19232e38424d58626c77828c97a0a0a09a90867b71675c52473c3125190d01000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e221508000000000000000713202c3945525e6a7783909ca8b2a5998d8175695d5145392e22170c02000000000000000000000000000000000005101b26323d4955616d7985919daab1a4988c8073675a4e4135291c10030013202c3946535f6c798693a0aca99c908376695d5043372a1d1104000002101c2936434f5c6975828f9ca8afa295897c6f6256493c3023160a00121e2b3845515e6b7884919eaba99c8f8275695c4f4336291d100300000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000000000000000000000020c151e2730384149515860676e757b81878c91969894918e8b89888786868687888a8c8f92959994908b858079736c655e564f473f362e251c1309000000000000000000000000000000000000010a141e273039424a535b626a71787e84898f93979b9fa2a4a6a8a9a8a7a7a7a7a8a8a9a8a6a3a19d9a96918d87827c756e67605850483f372e241b110700000000000000000000000000000000000000000008131f2a36414b56606a747d858d949a9fa09c989694949495989b9fa09b958e867e756c62574d42372b20150900000000000000000000000000000007121d28323b42484b4b4b4b4b4b4b55626f7c8996a2ada094877a6d6053473a2d2014070000000000000000000000020e1a25303a434b505353535353535353514c453c343e474e5253535353535353524f4941372d22160b0000000000000000000000000000000000000000000815222e3b4855616e7b8895969696968b7e7165584b3e3225180b00000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000007121d27323d48535d68737e89949ea9aca1978c81776c61574c41372c21170c010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d161e262e363d444b51575d63686c7074787b7d808283848586868685858483817f7d7a77736f6b67615c565049423b332b231b1209000000000000000000000814212d3a46525d68727c879193939393938b81776c62574d43382e23190f0400000000000007111c26313b46505b65707a858f93939393938d83786e64594d4135291c1003000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e2215080000000000000004111d2a36424f5b6774808c98a4b1a99d9185796d61564a3f34291e130900000000000000000000000000000000040d17222d38434e5a65717d8995a1adada194887c7063574b3e3226190d000013202c3946535f6c798693a0aca89b8f8275685c4f4235291c0f030000000f1b2835414e5b6774818e9ba7b0a3968a7d7063574a3d3124170a00121f2c3945525f6b7885929faba89b8e8275685b4f4235281c0f0200000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a000000000000000000000000000000000000000000030c151e262f373f474e555c636970757b81858a8e92959898969494939393949596999794918d89847f7a746e68615a534c453d352d241c130a0100000000000000000000000000000000000000020c151e273038414951585f666d73787e83878b8f9295989a9c9d9e9f9f9f9f9f9e9d9b999794918e8a86817c76706a645d564e463e362d241b120900000000000000000000000000000000000000000000020e19242f3a444e58626b737b83898f93979a9d9e9fa09f9e9d9b98948f8a837c746c635a50463b30261a0f040000000000000000000000000000000c18232f3a444d535758585858585858626f7c8996a2ada094877a6d6053473a2d20140700000000000000000000000008131e2831394044464646464646464645413b332c353c42454646464646464646433e372f251b10050000000000000000000000000000000000000000000815222e3b4855616e7b8895a2a2a2988b7e7165584b3e3225180b00000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000030e19232e39444f59646f7a858f9aa5b0a59a90857a70655a50453a30251a100500000000000000000003070a0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0b09050100000000000000000000000000000000000000000000000000000000000000000000040c141c242b333a40464c52575c6064686b6e717375767778797979797877767472706d6a67635f5b56514b453e383129211a110900000000000000000000000916232f3c4955626e798486868686868686847a6f655a50463b31261c120700000000000000000a151f2a343f49545e69737e868686868686868680756a5d5144372b1e1104000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aea295887b6e6155483b2e22150800000000000000010e1a26333f4b5864707c8894a0acada1958a7e72675b50453a30251b120a0200000000000000000000000000050d161f29333e49545f6b76828e9aa5b1a89c9084786c6054473b2f23160a000013202c3946535f6c798693a0aca79b8e8174675b4e4135281b0e020000000e1a2734414d5a6773818d9aa7b1a4978a7e7164574b3e3124180b0013202c3946525f6c7986929faca89b8e8174675b4e4135281b0e0200000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a00000000000000000000000000000000000000000000030c141d252d353c444b52585e646a7075797e8285888b8d8f919292929292908f8d8a8884817c78736e69635d565049423a332b231b120a01000000000000000000000000000000000000000000030c151e262f373f464d545b61676d72777b7f8386898b8d8f9091929292929291908e8d8a8885827e7975706b655f59524b443c342c241b120900000000000000000000000000000000000000000000000008131d28323d465059616971787e83878b8e909192939392908e8c88847e78726a625a51483e34291f140900000000000000000000000000000000101c2834404b565e6465656565656565656f7c8996a2ada094877a6d6053473a2d201407000000000000000000000000020c161f272e3438393939393939393938353029232b313639393939393939393937332d251d1309000000000000000000000000000000000000000000000815222e3b4855616e7b8895a2aca5988b7e7165584b3e3225180b00000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000a141f2a35404b55606b76818b96a1aca99e93897e73695e53493e33291e13090000000000000000030a0f141718191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919181815110c0600000000000000000000000000000000000000000000000000000000000000000000020a121a21282f353b41464b5054585c5f62646668696b6b6c6c6c6c6b6a69686664615e5b57534f4a453f3a332d261f1710080000000000000000000000000916232f3c4955626e7879797979797979797972685d53493e34291f150a000000000000000000030d18222d37424c57616c76797979797979797979756a5d5144372b1e1104000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a5aca295887b6e6155483b2e22150800000000000000000b17232f3b4854606c7884909ca7b2a69a8f83786c61564c41372d241c140d070200000000000000000004090f161f28313b45505a65717c87939faaafa4988c8074685c5044382b1f1307000013202c3946535f6c798693a0aca79a8e8174675a4d4134271b0e010000000d1a2733404d596673808d9aa6b1a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8e8174675a4e4134281b0e0100000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000000000000000000000000000020b131b232b323940474d53595f64696d7275797c7e81838485868686858482817e7b7874706c67625d57524b453e37302921191109000000000000000000000000000000000000000000000000030c151d252d343c434a50565c61666b6f7376797c7e818284858586868685848382807e7b7875726d69645f5a544e474139322a231a120900000000000000000000000000000000000000000000000000010c16212b343e474f585f666c72777b7e8183858686868584827f7c78736d67605850483f362c22180d0300000000000000000000000000000000121f2b3844505c68707171717171717171717c8996a2ada094877a6d6053473a2d20140700000000000000000000000000040d151d23282b2c2c2c2c2c2c2c2c2c29241f1920252a2c2c2c2c2c2c2c2c2c2a27211b130b01000000000000000000000000000000000000000000000815222e3b4855616e7b8895a0a0a0988b7e7165584b3e3225180b00000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000006101b26313c46515c67727c87929da8aca1978c82776c62574c42372c22170c0200000000000000050d141b2023252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252524211d1710090000000000000000000000000000000000000000000000000000000000000000000000080f161d242a30353a3f44484c4f5255585a5b5d5e5f5f5f5f5f5e5e5c5b595755524f4b47433e39342e28221b140d05000000000000000000000000000814212d3a46525d666c6c6c6c6c6c6c6c6c6c6960564c41372c22180d030000000000000000000006111b26303b45505a646b6c6c6c6c6c6c6c6c6c6b63594d4135291c1003000013202c3946535f6c798693a0a0a09a8e8174675a4d4134271a0e01000b1825323e4b5865717e8b98a0a0a095887b6e6155483b2e221508000000000000000007131f2b3744505c67737f8b97a2aeaba094897e73685d53493f362e251e18130f0b090707060708090c10141a2128313a434d57616c77828d99a4afaa9e93877b6f64584c4034271b0f03000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0e010000000d1a2633404c596673808c99a6b2a5988c7e7265584c3f3225190c0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e0100000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000000000000000000000000000000109111920272e353c42484e53585d6165696d6f727476777879797978777574716f6c6864605c57524c46403a332c251e170f070000000000000000000000000000000000000000000000000000030b131b232a31383f454b50565a5f63676a6d707274757778787979797877767573716f6c6965615d59544e49433c362f2820191108000000000000000000000000000000000000000000000000000000050f19222c353d464d555b61666b6f72757778797979787775736f6c67625c554e463e362d241a1006000000000000000000000000000000000013202c3946535f6c797e7e7e7e7e7e7e7e7e7e8996a2ada094877a6d6053473a2d2014070000000000000000000000000000040b12171c1f20202020202020201f1d19130e141a1d1f20202020202020201e1b1610090100000000000000000000000000000000000000000000000815222e3b4855616e7b8893939393938b7e7165584b3e3225180b00000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000020c17222d38424d58636e78838e99a4afa59b90857a70655b50453b30251b100500000000000000040e171f262c303232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232312e29221b12090000000000000000000000000000000000000000000000000000000000000000000000050c12191e242a2f34383c404346494b4d4f505152525352525251504e4d4b4845423f3b37322e28231d17100a03000000000000000000000000000005111d2935404b545c5f5f5f5f5f5f5f5f5f5f5d574e443a30251b100600000000000000000000000009141e29333e48525a5f5f5f5f5f5f5f5f5f5f5e5951473c3125190d00000013202c3946535f6c798693939393938e8174675a4d4134271a0e01000b1825323e4b5865717e8b9393939393887b6e6155483b2e2215080000000000000000030f1b27333f4b57636e7a86919da8b1a69a8f857a6f655b514840373029231f1b1816141313131416191c20252b323a434c555f69737e89939eaaafa4998d82766b5f53473b2f23170b00000013202c3946535f6c798693a0aca79a8d8173675a4d4134271a0e010000000d192633404c596673808c99a6b2a5988c7e7265584c3f3225190c0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e0100000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000000000000000000000000000000000070e161d242a31373c42474c5155595d60636668696b6b6c6c6c6b6a696765625f5c5854504b46413b352f28221b140c05000000000000000000000000000000000000000000000000000000000109111820272d343a3f454a4e53575a5e61636567696a6b6c6c6c6c6b6b6a68676562605c5955514d48433d37312b241d160e07000000000000000000000000000000000000000000000000000000000007101a232b343c434a50565b5f6366686a6b6c6c6c6c6a6966635f5b56514a443c352c241b120800000000000000000000000000000000000013202c3946535f6c79868b8b8b8b8b8b8b8b8b8f99a4ada094877a6d6053473a2d20140700000000000000000000000000000000070c0f12131313131313131312100d0803090d11131313131313131313110f0a05000000000000000000000000000000000000000000000000000815222e3b4855616e7b868686868686867e7165584b3e3225180b00000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000008131e29343e49545f6a74808a95a0aba99e93897e73695e54493e34291e140900000000000000010c16202931373c3e3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3d3a342c241b1006000000000000000000000000000000000000000000000000000000000000000000000001070d13191e23282c3033373a3c3e40424344454646464645444342403e3c3936332f2b27221d18120c0600000000000000000000000000000000010d19242f39424a5053535353535353535353514c453c32281e130900000000000000000000000000020d17222c3640484f52535353535353535353524e473f352b20140900000013202c3946535f6c79868686868686868174675a4d4134271a0e01000b1825323e4b5865717e868686868686867b6e6155483b2e2215080000000000000000000b17232f3b46525e6975808b97a2adaca1968b81776d635a5249423b352f2b27242221202020212325282c31363d444c555e67717b858f9aa5b0a99e93887c71655a4e42372b1f130700000013202c3946535f6c798693a0aca79a8e8174675a4e4134271b0e010000000d1a2633404c596673808c99a6b2a5988c7e7265584c3f3225190c0013202c3946535f6c798693a0aca79a8e8174675b4e4134281b0e0100000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a000000000000000000000000000000000000000000000000000000040b12191f252b31373c4145494d515457595b5d5e5f5f5f5f5f5e5c5a585653504c48443f3a35302a241d1710090200000000000000000000000000000000000000000000000000000000000000070e151c22282e34393e43474b4e515457595b5c5d5e5f5f5f5f5f5e5d5c5a585653504d4945413c37322c262019130b0400000000000000000000000000000000000000000000000000000000000000081119222a31383f454a4f5356595b5d5f5f5f5f5f5e5c5a57534f4b453f39322b231a12090000000000000000000000000000000000000013202c3946535f6c79869398989898989898989aa1aaaca094877a6d6053473a2d20140700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000815212e3b4854616d7779797979797979797064574b3e3125180b00000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000040f1a25303a45505b66707b86919ca6aca2978c82776c62574c42372d22170d020000000000000007121d28323b42484b4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4b4a453e362c22170c0100000000000000000000000000000000000000000000000000000000000000000000000002080d12171c2024272a2d30323435373838393939393837363533312f2d2a26231f1b16110c060100000000000000000000000000000000000007121d2730383f444646464646464646464645413b332a21160c02000000000000000000000000000005101a242e363d434646464646464646464645423d362d23190e03000000131f2c3946525f6b76797979797979797972665a4d4034271a0e01000b1825313e4b5764707979797979797979776d6154483b2e21150800000000000000000006121e2a36414d58636f7a85909ba6b0a89d93897f756c645b534c46403b3733312f2e2d2c2d2e2f3134383c42484f565e677079838d97a1acada2978d82766b6054493d32261a0e0300000013202c3946535f6c798693a0aca89b8e8174685b4e4135281b0f020000000d1a2733404d5a6673808d9aa6b2a5988b7e7165584b3e3225180c0013202c3946525f6c7986929faca89b8e8174685b4e4135281b0f0200000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a0000000000000000000000000000000000000000000000000000000000070e141a20262b3035393d4144474a4c4e5051525253525251504e4c494743403c38332f29241e19120c0500000000000000000000000000000000000000000000000000000000000000000000030a11171d23282d32373b3e4245484a4c4e4f5151525253525251504f4d4c494744413d3935302b26211b150e08010000000000000000000000000000000000000000000000000000000000000000000710181f272d33393e43474a4d4f515253535352514f4d4a47433f3a342e2720191108000000000000000000000000000000000000000013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a094877a6d6053473a2d20140700000000000000040708080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808060200000000000000000000000000000713202c3845515c666c6c6c6c6c6c6c6c6c685e53483c2f23160a00000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000b16212b36414c57616c77828d98a2ada59b90857b70655b50463b30261b100600000000000000000c18242f3a444d5458585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585650483e34291d1105000000000000000000000000000000000000000000000000000000000000000000000000000002070b1014171b1e21232527292a2b2c2c2c2c2c2c2b2a28272523201d1a17130f0a05000000000000000000000000000000000000000000010b151e272e3337393939393939393939393835302921180f050000000000000000000000000000000009121c242c3236393939393939393939393936322b241b110700000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6960564a3e3225190c00000a16232f3c48535e686c6c6c6c6c6c6c6c6c665c5145382c201307000000000000000000020d1925303c47525e69747e89949ea8afa59b91887e756d655e57514c4743403d3c3a3a393a3b3c3e4144484d535960687079828b959fa9afa59b91867b70655a4f43382c2115090000000013202c3946535f6c798693a0aca89b8f8275685c4f4236291c0f030000000e1b2734414d5a6774818d9aa7b1a4978b7e7164574b3e3125180b00121f2c3845525f6b7885929faba89b8f8275685b4f4235291c0f0200000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a00000000000000000000000000000000000000000000000000000000000003090f141a1f24292d3135383b3e4042434445464646454443413f3d3a3734302c27231e19130d070100000000000000000000000000000000000000000000000000000000000000000000000000060c12171d22262a2e3236393b3e40414344454546464645454442413f3d3a3734312d2924201b15100a03000000000000000000000000000000000000000000000000000000000000000000000000060e151c22282d32373a3e40424445464646454443413e3b37332e29231c160e0700000000000000000000000000000000000000000013202c3946535f6c7986939393939393939393939393939393877a6d6053473a2d2014070000000000060c101315151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151514120f0a0400000000000000000000000004101c28343f4a545b5f5f5f5f5f5f5f5f5f5c564d42372b1f130700000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130601010107121d27323d48535d68737e89949ea9a99e94897e74695e54493e34291f1409000000000000000000101c2834404b565f6465656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565625a50453a2e211509000000000000000000000000000000000000000000000000000000000000000000000000000000000004070b0e111417191b1c1d1e1f1f201f1f1f1e1d1c1a181614110e0a0703000000000000000000000000000000000000000000000000030c151c23282b2c2c2c2c2c2c2c2c2c2c2c29241f170f060000000000000000000000000000000000000a121a21262a2c2c2c2c2c2c2c2c2c2c2c2a26201a120900000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5d574e44392d221609000007131f2b37424d565c5f5f5f5f5f5f5f5f5f5b544a3f34281c10040000000000000000000008141f2a36414c57626d77828c96a0aaada39a91887f777069625c57534f4c4a484746464647494a4d5054595e646b727a828b949da7b0a79d93897f74695f54493d32271b10040000000013202c3946535f6c798693a0aca99c9083766a5d5043372a1e11040000000f1b2835424e5b6874818e9ba7b0a3978a7d7064574a3e3124170b00121e2b3845515e6b7784919eaaa99c8f8276695c4f4336291d100300000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170a000000000000000000000000000000000000000000000000000000000000000003090e14181d2125282c2e3133353738393939393837363533302e2b2724201c17120d08020000000000000000000000000000000000000000000000000000000000000000000000000000000001060c11161a1e2226292c2f31333536373839393939393837363432302e2b2825211d19140f0a04000000000000000000000000000000000000000000000000000000000000000000000000000000030a11171d22262a2e313436373839393939383634322f2b27221d18110b040000000000000000000000000000000000000000000013202c3946535f6c7986868686868686868686868686868686867a6d6053473a2d201407000000020a11181c20212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211f1b150f070000000000000000000000000c18232e38424a4f525353535353535353504b443b30261a0f0300000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130e0e0e0e0e19232e39444f59646f7a858f9aa5ada2978d82776d62574d42382d22180d02000000000000000000121f2b3844515d6870727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272726c62564a3d3124180b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000205080a0c0e0f111212131313131211100f0d0c0a07040100000000000000000000000000000000000000000000000000000000030a11171b1e202020202020202020201f1d19130d0600000000000000000000000000000000000000000810161a1e1f2020202020202020201f1d1a150f080000000000000a16212c3740484f525353535353535353514c453c32281d11050000030f1a26303b444b505353535353535353524f4a42382e23180c0000000000000000000000030e1925303b46515b66707a858e98a2abaca39a9189817a746d68635f5c595755545353535455575a5d60656a6f767d848c949da6afa89f958b82776d62584d42372c21160a000000000013202c3946535f6c798693a0acaa9e9184786b5e5245382c1f1306000003101d2936434f5c6975828f9ca8afa296897c6f6356493d3023160a00111e2a3744515d6a7784909daaaa9d9084776a5d5144372a1e110400000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3024170b0b0a070300000000000000000000000000000000000000000000000000000000000003080c1115191c1f222527282a2b2c2c2c2c2c2b2a282624211e1b1814100b0601000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0e12161a1d2022242628292b2b2c2c2c2c2c2b2a29282624211f1c1815110d080300000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c11161a1e222527292b2c2c2c2c2c2b2a2825221f1b17120c06000000000000000000000000000000000000000000000000131f2c3946525f6b767979797979797979797979797979797979776c6053463a2d2014070000020b141c23282c2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2b2620191108000000000000000000000006111c262f383f4346464646464646464644403a32291f14090000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201a1a1a1a1a1a1f2a35404b55606b76818b96a1aca69b90867b70665b50463b30261b10060000000000000000000013202c3946535f6c797e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7265584b3f3225180c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060b0f121313131313131313131312100d080200000000000000000000000000000000000000000000040a0e111313131313131313131313110e09040000000000000005101a252e373e4346464646464646464645413b332a21160b0000000009141f29323a4044464646464646464646433f382f261c110600000000000000000000000008131e29343f4a545e69737c869099a1aaaca39b938c857f79746f6b6865636260605f6061626466696c71757b81878e969ea6afa79f968d837970655b51463b31261b1004000000000013202c3946535f6c798693a0acac9f9386796d6054473b2e221509000005121f2b3844515e6a7784909daaaea194887b6e6255483c2f22150900101d2936434f5c6976828f9ca8ab9e9185786b5e5245382c1f120600000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d302418181817140f0a030000000000000000000000000000000000000000000000000000000000000005090c101316181a1c1d1e1f1f201f1f1e1d1b191715120f0b0804000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002060a0d101316181a1b1d1e1f1f1f201f1f1e1e1c1b191715120f0c0905010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0e1215181b1c1e1f2020201f1e1d1b1916130f0b060100000000000000000000000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b655b4f44372b1f120500000a141d262e34383b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3a37322b231a100600000000000000000000000a141d262d333739393939393939393938342f2820170d020000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2727272727272727313c47515c67727d87929da8a99f94897e74695f54493f34291f140a000000000000000000000013202c3946535f6c79868c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c7e7265584c3f3225190c0000000000000004070808080808080808080808080808080808080808080808080808070604030100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131c252c32373939393939393939393835302921180f0400000000020d1720282f343839393939393939393937332d261d140a00000000000000000000000000020d18232d38424d57616a747d878f98a0a8ada59e97908a85807b787472706e6d6d6c6d6d6f707275797d81868c9299a0a8ada69e958d847a71675e54493f352a1f140900000000000013202c3946535f6c798693a0acaea195887b6f63564a3d3125180c00000814212d3a46535f6c7985929fabaca09386796d6054473a2e211408000f1c2835424e5b6874818e9aa7ac9f9286796c6053463a2d20140700000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d302525252523201b150e050000000000000000000000000000000000000000000000000000000000000000000306090b0d0f1112121313131211100f0d0b0806030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010407090b0d0f10111213131313121211100e0d0b08060300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000206090c0e1011121313131212100e0c0a0603000000000000000000000000000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5a53493e33271b0f030006111c262f383f4548484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484847433d352c22170c0100000000000000000000020b141c22272b2c2c2c2c2c2c2c2c2c2b28231d160e05000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f53463934343434343434343438424d58636e78838e99a4ada2988d82786d62584d42382d22180d02000000000000000000000013202c3946535f6c7986939290909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090968c7e7265584c3f3225190c0000000000060c101315151515151515151515151515151515151515151515151515141412110f0d0b090603000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010406080a0c0e0f101111121212121111100f0e0c0a08060401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c29241f170f06000000000000050e161d23282b2c2c2c2c2c2c2c2c2c2b27221c140b02000000000000000000000000000006111c26303b454f58626b747d868e969ea5aca8a29b96908c8884817e7c7b7a7979797a7b7d7f8285898d92979da4aba9a39b948c837a72685f564c42382d23180e0300000000000013202c3946535f6c798693a0acb0a4978b7e7265594d4134281c1106050b1724303c4955626e7b8794a0adaa9e9184786b5f5245392c1f1306000e1a2734404d5a6673808c99a6ada194877b6e6155483b2f22160900000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3d3232323231302c261f170e0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a16212c3740484f525353535353535353535353535353535353524f4941372d22160b00000b17222d38424a51545555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555534e473e34291d12060000000000000000000000020a11171b1e2020202020202020201f1c18120c0400000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346414141414141414141414149545f6a74808a95a0aba69b91867b71665b51463b31261b110600000000000000000000000013202c3946535f6c7986938983838383838383838383838383838383838383838383838383838383838383838383838383838383838383838384908c7e7265584c3f3225190c000000020a11181c202122222222222222222222222222222222222222222222222221201f1e1c1a1815120f0b070300000000000000000000000000000000000000000000000000000000000000000000000000000000000003060a0d10131517191a1c1d1d1e1e1e1e1e1e1d1d1c1a19171513100d0a060300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010910161a1e1f20202020202020201f1d19130d060000000000000000040c12181c1f2020202020202020201e1b17110a02000000000000000000000000000000000a141f29333d465059626b747c848c939aa1a7aca7a19c9894908d8b89888786868687888a8c8e9195999ea3a9aaa59e98918a827a716960574d443a30261b11070000000000000013202c3946535f6c798693a0acb3a69a8e8175695d5145392d22171312131c2834404c5865717d8a96a3afa89b8f8276695d5043372a1e1104000c1925323f4b5865717e8b97a4afa296897c7063564a3d3124170b00000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574a3e3e3e3e3e3e3c37312921170d0200000000000002070b0e101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100e0b07020000000000000000000000040708090909090909090908070501000000000000000000000000030608090909090909090909080502000000000000000000000000030608090909090909090909080603000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005101a252e373e4346464646464646464646464646464646464646433e372f251b100500000f1b27333f4a545c6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161615f5950453a2e22160a00000000000000000000000000060b0f1213131313131313131312100c07010000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f534d4d4d4d4d4d4d4d4d4d4d4d505b66707b86919ca7aa9f948a7f746a5f544a3f342a1f140a0000000000000000000000000013202c3946535f6c798693887b767676767676767676767676767676767676767676767676767676767676767676767676767676767676767683908c7e7265584c3f3225190c0000020b141c23282c2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2d2c2a292724221f1b18140f0b060100000000000000000000000000000000000000000000000000000000000000000000000001060a0f13161a1c1f2124252728292a2b2b2b2b2b2b2a2928272524211f1c1916130f0a0601000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0e1113131313131313131312100d08020000000000000000000001070c1012131313131313131313120f0b06000000000000000000000000000000000000030d17212b343e475059626a727a82898f969ba1a6aaa8a4a09d9a98969493939393949596989b9ea1a5a9a9a49f99938d867f7870685f574e453b32281e140a000000000000000013202c3946535f6c798693a0acb6aa9d9185796d61554a3e342922201f1f232d3844505c6874818d99a6b2a5998c8073675a4e4135281c0f02000b1724303d4a5663707c8995a2afa4978b7e7265584c3f33261a0d01000000000000000000000000000013202c3946535f6c798693a0aca4978a7d7063574b4b4b4b4b4b4b48433b33291e13080000000000060d13171b1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1b17130d060000000000000000070c11141515151515151515151514110d08010000000000000000050b0f131515151515151515151514120e09030000000000000000040a0f121515151515151515151515130f0a040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131c252c32373939393939393939393939393939393939393937332d251d1309000000121e2b37434f5b666d6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6b61564b3e3226190c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1004000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5a5a5a5a5a5a5a5a5a5a5a5a5a5a626c77828d98a2ada2988d83786d62584d43382d23180f070000000000000000000000000013202c3946535f6c798693887b6f6969696969696969696969696969696969696969696969696969696969696969696969696969696969697683908c7e7265584c3f3225190c00000a141d262e34383b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3a3a39373533312e2b2724201b17120c0701000000000000000000000000000000000000000000000000000000000000000002070d12161b1f2226292c2e3032343536373738383838383736353432302e2c2926221f1b16120d0701000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050f19222c353e475058606870777e848a90959a9ea2a6a9a9a6a4a2a1a0a0a0a0a0a1a3a5a7aaa8a4a19d98938e88827b746d665e564d453c332920160c02000000000000000013202c3946535f6c798693a0acb9ada195897d72665b50453b332f2c2c2c2e353f4955606c7884909da9aea296897d7064584b3f3226190d00000915222f3b4854616e7a8793a0aca69a8d8174675b4e4235291c1003000000000000000000000000000013202c3946535f6c798693a0aca4978a7d70635858585858585857544d453b3025190d010000000810181e23272929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292927231e1810080000000000020b12181d2022222222222222222222211d19130c040000000000000810161b1f21222222222222222222211e1a140d06000000000000070e151a1f21222222222222222222211f1b160f08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a27211b130b0100000013202c3946525f6c777b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b73675a4d4134271a0e00000000000000030507080909090909080706040100000000000000000000000000000000000000000000000000000000000000000000000005101a25303c4955626f7c8996a2afa99c908376695c4f43362b20150b000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c67676767676767676767676767676768737e89949ea9a69c91867b71665c51463c362f282119110900000000000000000000000013202c3946535f6c798693887b6f625c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c697683908c7e7265584c3f3225190c0006111c262f383f45484848484848484848484848484848484848484848484848484746454442403d3a3734302c27221d18120c06000000000000000000000000000000000000000000000000000000000000070d13181d22272b2f3235383b3d3f40424344444445454544444342403f3d3b3835322f2b27221d18130d0600000000000000000000000000000000000000040708080808080808080808070400000000000000000000000000000000000000000000000000000407080808080808080808080704000000000000000000000000000000000000000000000000000000000000000000000007101a232c353e464e565e656c73797f84898e9296999c9fa1a3a4a5a6a6a6a6a6a5a4a2a09e9b9895918c87827d77706a635b544c443b332a20170e0400000000000000000013202c3946535f6c798693a0acb8b1a69a8e83776c61574d453f3b3938393b3f47505b66717d8995a1adaa9e92867a6d6155483c3023170a00000713202d3946525f6b7884919daaa89c8f83766a5d5144382b1f1206000000000000000000000000000013202c3946535f6c798693a0aca4978a7d706565656565656565645f574c4135291d1104000007111a22292f3336363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636332f29221a1107000000020c141c23292d2f2f2f2f2f2f2f2f2f2f2d2a241e160d040000000009121a21272c2e2f2f2f2f2f2f2f2f2f2e2a251f180f060000000007101920262b2e2f2f2f2f2f2f2f2f2f2e2b27211a1108000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010910161a1e1f2020202020202020202020202020202020201e1b161009010000000013202c3946535f6c79868888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888174675a4d4134271a0e0000000000050b0f1214151516161615151412100e0b08040000000000000000000000000000000000000000000000000000000000000000010c17212c37414c56626f7c8996a2afa99c908376695c51473c32271c12070000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca093867974747474747474747474747474747474747a85909aa5aa9f948a7f746a5f57524d47413a332b231b1209000000000000000000000013202c3946535f6c798693887b6f62554f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f5c697683908c7e7265584c3f3225190c000b17222d38424a5154555555555555555555555555555555555555555555555555545352504e4c4a4743403c38332e29231d17110a030000000000000000000000000000000000000000000000000000040b12181e24292e33373b3e424547494b4d4e4f50515151515151504f4e4d4b494745423e3b37332e29241e18110b04000000000000000000000000000000060c10131515151515151515151513100c0600000000000000000000000000000000000000000000060c10131515151515151515151513100c070000000000000000000000000000000000000000000000000000000000000000000008111a232c343c444c535b61686e73797d82868a8d909294969798999a9a9a9998979694918f8c8885817c77716b655f58514a423a322921180e050000000000000000000013202c3946535f6c798693a0acafa69f9d94897e73695f57504b47464545474b5159626d77838e99a5b1a69a8e82766a5d5145392c201407000005111e2a3743505c6975828e9ba7ab9e9285796c6053473a2e221509000000000000000000000000000013202c3946535f6c798693a0aca4978a7d71717171717171717170695e5245392c20130700030e19232c343b4042434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434342403b342c23190e0300000a141e262e34393b3c3c3c3c3c3c3c3c3b39352f281f160c01000007111b242c33383b3c3c3c3c3c3c3c3c3c3a36312921180e030000050f19222a31373a3c3c3c3c3c3c3c3c3c3b37322b231a100600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0e1113131313131313131313131313131313131313110f0a0500000000000013202c3946535f6c798693959595959595959595959595959595959595959595959595959595959595959595959595959595959595958e8174675a4d4134271a0e000000010910161b1f2022222222222221201f1d1a1714100b0600000000000000000000000000000000000000000000000000000000000008131e28333e48535e68737d8996a2afa99c9083786e63594e43392e23190e0300000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386818181818181818181818181818181818181818c96a1aca4988d83786f6b67635e58524c453d352d241b12090000000000000000000013202c3946535f6c798693887b6f6255484343434343434343434343434343434343434343434343434343434343434343434343434f5c697683908c7e7265584c3f3225190c000f1b27333f4a545c6161616161616161616161616161616161616161616161616161605f5d5b595653504c48443f3a342f28221c150d06000000000000000000000000000000000000000000000000070e151c23292f353a3f43474b4e515456585a5b5c5d5e5e5e5e5e5e5d5c5b5a585654514e4b47433f3a352f29231c150e06000000000000000000000000020a11181c2021222222222222222221201c18110a02000000000000000000000000000000000000020a11181c2021222222222222222221201c18120a0200000000000000000000000000000000000000000000000000000000000000000008111a222b333a424950565c62686d72767a7d81838688898b8c8c8d8d8d8c8c8a89878582807c7874706b66605a544d473f38302820170f06000000000000000000000013202c3946535f6c798693a0aca89d94909490857b7169615b575452525254575c636b747e89949faaaca195897d72665a4d4135291d10040000020f1b2834414d5a66737f8c98a4ada194887b6f63564a3e3125190c000000000000000000000000000013202c3946535f6c798693a0aca4978a7e7e7e7e7e7e7e7e7e7e7a6d6154473a2e211407000914202a353e464c4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4c463e352a2014090006111c26303840454848484848484848484846413a31281e130800020d18232d363e444748484848484848484846423b332a20150a00000b16212b343c434748484848484848484847433d352c22180d0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a29a8e8174675a4d4134271a0e0000010b131b22272b2d2e2f2f2f2f2f2e2d2b292724201c17110b05000000000000000000000000000000000000000000000000000000050f1a252f3a454f5a646f7a858f9aa5b1aca0958a80756a60554a40352a20150a00000000000000000000000000000000000000000013202c3946535f6c798693a0acafa3978f8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e939da8b0a3968a817e7b78736f69635d564f473f372e241b120800000000000000000013202c3946535f6c798693887b6f6255483c36363636363636363636363636363636363636363636363636363636363636363636434f5c697683908c7e7265584c3f3225190c00121e2b37434f5b666d6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6d6d6b6a6865635f5c58544f4a45403a342d261f1810080000000000000000000000000000000000000000000009111920272e353b40464b4f53575a5d6062646668696a6a6b6b6b6b6a6a6968666563605d5a57534f4a45403a342e272018100800000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2c28231c140b0200000000000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2c28231c140c02000000000000000000000000000000000000000000000000000000000000000000081019212830373e454b51575c61666a6e717477797b7d7e7f80808180807e7d7c7a787673706c68645f5a554f49433c352e261e160e0500000000000000000000000013202c3946535f6c798693a0aca5988c848b968d847b736c6763615f5f5f6063676d757d87909ba5b0a69b9084796d6155493d3125190d010000000c1925323e4a5763707c8995a1aea4978b7e7266594d4135281c10040000000000000000000000000013202c3946535f6c798693a0aca59a8f8b8b8b8b8b8b8b8b8b877a6d6154473a2e211407000d1925313c4650575c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5750463c3125190d000b17222d38424a5155555555555555555555524c433a2f24190d0107131f2a353f484f54555555555555555555534d453c31261b0f0305111c28333d464e53555555555555555555544f473e34291e120600000000000000000000000000000000000000000000000000000000000000010305060708080808070604020000000000000000000000000000000102030303020100000000000000000000000000000013202c3946535f6c798693a0acaeaea9a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a59a8e8174675a4d4134271a0e000009131d252d33373a3b3c3c3c3c3c3b3a383633302c27221d160f0800000000000000000000000000000000000000000000000000010c16212c36414c56616b76818c96a1acb6b1a69c91877c71675c51473c31271c1107000000000000000000000000000000000000000013202c3946535f6c798693a0acb4a9a19b9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9ea5afb2a69b918e8b8884807a756f686159514940372d231a0f05000000000000000013202c3946535f6c798693887b6f6255483c2f292929292929292929292929292929292929292929292929292929292929292936434f5c697683908c7e7265584c3f3225190c0013202c3946525f6c777b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7a79787674726f6c6864605b56514b453f38312a221a120a020000000000000000000000000000000000000009121a232a323940464c51565b5f63676a6d6f717374757677777878777777767473716f6d6a67635f5b56514c463f39312a221a12090000000000000000000a141d262e34383b3b3b3b3b3b3b3b3b3b38342e261d140a000000000000000000000000000000000a141d262e34383b3b3b3b3b3b3b3b3b3b39342e261e140a00000000000000000000000000000000000000000000000000000000000000000000070f171e25303a444c535656565a5e6165686a6c6e707172737373737372716f6e6c696763605c58534e49443e38312a231c140c040000000000000000000000000013202c3946535f6c798693a0aca5988c7e8590968d857d78736f6d6c6b6b6d6f73787f878f98a2acaa9f958a7e73685c5045392d211509000000000a16222f3b4754606d7985929eaaa79a8e8275695d5144382c2014070000000000000000000000000013202c3946535f6c798693a0acaba19a989898989898989894877a6d6154473a2e21140700111d2936424d58626869696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696862584d4236291d11000f1b27333f4a545c616262626262626262625d564c41352a1d11050b17242f3b46515a606262626262626262625e574e43382c2014070915212d39444f585f626262626262626262605950463a2f23170a0000000000000000000000000000000000000000000000000000000003070a0d0f111314151515141412110f0c090602000000000000000206090c0d0f0f0f0f0f0e0d0b0906030000000000000000000013202c3946535f6c798693a0acb3a89f99989898989898989898989898989898989898989898989898989898989898989898989898988e8174675a4d4134271a0e0005101b252f373e444648484949494848464542403c38332e28211a120900000000000000000000000000000000000000000000000008131d28333d48535d68737d88939da8aeababaea3988e83786e63584e43382e23180e030000000000000000000000000000000000000013202c3946535f6c798693a0acb9b2aca8a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a9a9aaabaca39d9a9794908b868079736b635b52493f352c21170d020000000000000013202c3946535f6c798693887b6f6255483c2f221c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c7986888888888888888888888888888888888888888888888887868583817e7b7874706c67625c565049433b342c241c140b02000000000000000000000000000000000009121b242c343c434a51575d62676b6f7376797b7e80818283848485858484838281807e7c7976736f6b67625d57514a433c342c241b12090000000000000006111c262f383f4548484848484848484848453f382f261c1106000000000000000000000000000006111c262f383f454848484848484848484845403830261c11060000000000000000000000000000000000000000000000000000000000000000000005111e2a36414c565e6263636363605a5b5e606263656566666766666564636362605e5954504c48433e38322c261f19110a02000000000000000000000000000013202c3946535f6c798693a0aca6998c7f7f8a94968f89837f7c7a797878797c7f848a9199a1aaaba1988d83786d62574b4034281c11050000000007131f2c3844515d6975828e9aa6aa9e9185796d6054483c3024180c0000000000000000000000000013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a094877a6d6154473a2e21140700121f2c3945525e6a747676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676746a5e5245392c1f1200121e2b3743505b666d6f6f6f6f6f6f6f6f6e685d5246392d2114070e1a2733404c58636c6f6f6f6f6f6f6f6f6e695f54483c2f23160a0b1824313d4a55616a6f6f6f6f6f6f6f6f6f6b62574b3f3326190d0000000000000000000000000000000000000000000000000000050a0f1316191c1e202121222221201f1d1b1916120e0a0500000003090e1215181a1b1c1c1c1c1b19171513100c06000000000000000013202c3946535f6c798693a0acaea2968d8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8174675a4d4134271a0e000a16212d3741494f535455555555555453514f4c48443f39332c241b120900000000000000000000000000000000000000000000040f1a242f3a444f5a646f79848f9aa4aaa29e9fa4aa9f958a80756a5f554a3f352a1f150a0000000000000000000000000000000000000013202c3946535f6c798693a0acb5aba29d9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9d9d9fa0a3a6a7a4a09c97918b847d756d645b51473d33291e13080000000000000013202c3946535f6c798693887b6f6255483c2f2215101010101010101010101010101010101010101010101010101010101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c79869395959595959595959595959595959595959595959594949391908d8b8884817c78736d68615b544d463e362e261d140b0200000000000000000000000000000008121b242d363e464e555c62686e73777b808386888a8c8e8f90919192929191908f8e8c8a888683807b77736e68625c554e463e362d241b11080000000000000b17222d38424a5154555555555555555554514a42382d22170b00000000000000000000000000000b17222d38424a5154555555555555555554514a42382d22170b000000000000000000000000000000000000000000000000000000000000000000000714212d3a46525e686f6f6f6f6f6c635751535557585959595b61666a6d6f6f6f6d6a655f5851483f362d27211b150e070000000000000000000000000000000013202c3946535f6c798693a0aca6998c8078828c969a948f8b898785858586888b90959ba3aba9a19990867c71675c51453a2f23170c000000000003101c2835414d5966727e8a96a3ada195897c7064584c4034281c100400000000000000000000000013202c3946535f6c7986939393939393939393939393939393877a6d6154473a2e2114070013202c3946535f6c798383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383796c5f5346392c20130013202c3946525f6c787b7b7b7b7b7b7b7b7a6e6255483b2f2215080f1c2835424f5b68747b7b7b7b7b7b7b7b7b7064574b3e3124180b0c1926333f4c5965727b7b7b7b7b7b7b7b7b73675a4e4134281b0e000000000000000000000000000000000000000000000000040a10161a1f2326292b2c2d2e2e2e2e2d2c2a2825221e1a16110b05080f141a1e2225272829292928272624221f1c17120b0300000000000013202c3946535f6c798693a0acaca093867e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e74675a4d4134271a0e000f1b27333e49535b6061626262626261605e5b5854504a443d362d241b12080000000000000000000000000000000000000000010b16212b36414b56616b76818b96a1aba29891939ba5a69c91867c71665c51463c31261c110700000000000000000000000000000000000013202c3946535f6c798693a0acafa39991909090909090909090909090909090909090909090919294969a9ea2a8a8a39d968f877e766d63594f453a30251a0f0300000000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a1a09f9e9c9a9794918d88847e79736c665f58504840382f261d140a010000000000000000000000000006101a242d374048505860676d74797e83888c8f929597999a9c9d9e9e9e9e9e9e9d9c9b999795928f8c88837e79736d665f5850483f362d231a100500000000000f1b27333f4a545c616161616161616161615c544a3f33271b0f03000000000000000000000000030f1b27333f4a545c616161616161616161615c544a3f33281b0f030000000000000000000000000000000000000000000000000000000000000000000915222f3b4855626e7a7c7c7c7c74675b4e47484a4e545b61666c7176797c7c7b7976716a635a51483e33291e120a03000000000000000000000000000000000013202c3946535f6c798693a0aca69a8d80737a848d969e9b9895939292929395989ba0a6aba59f978f877d746a5f554a3f34291e12070000000000000c1925313d4a56626e7a86929eaaa5998d8174685c5044382c20150900000000000000000000000013202c3946535f6c7986868686868686868686868686868686867a6d6154473a2e2114070013202c3946535f6c798690909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909086796c5f5346392c20130013202c3946535f6c7986888888888888887b6f6255483c2f2215090f1c2835424f5b687582888888888888887e7164574b3e3124180b0d192633404c59667380888888888888888174675b4e4134281b0e0000000000000000000000000000000000000000000000080f151c21262b2f323537393a3b3b3b3b3a383734312e2a26211c1610131a20252a2e313335363636353432312e2c28231c150c03000000000013202c3946535f6c798693a0acaca093867971717171717171717171717171717171717171717171717171717171717171717171717171716d63584c3f33261a0d00111e2a37434f5a656c6e6f6f6f6f6f6e6c6a6864605b564f483f372d241a0f040000000000000000000000000000000000000008121d28323d48525d68727d88929da8a69b908689949ea9a3988d83786d63584d43382d23180e03000000000000000000000000000000000013202c3946535f6c798693a0acaca093878383838383838383838383838383838383838383838485878a8d92979ca3aaa8a19991887f756b61574c41362b20140900000000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaeaea8a4a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a4a5a7a9a9a6a4a09d99948f8a847e777169625a524a41382f261c1309000000000000000000000000030e18222c363f49525a626a71787f858a8f94989b9ea1a4a5a7a7a6a5a4a4a4a4a5a5a6a7a6a4a19e9b98948f8a857e78716a625a51483f352c22170d0200000000121e2b37434f5b666d6e6e6e6e6e6e6e6e6d665b4f43372b1e120500000000000000000000000005121e2b37434f5b666d6e6e6e6e6e6e6e6e6d665b5044372b1f12050000000000000000000000000000000000000000000000000000000000000000000815222e3b4854616e7a87898983766a5e52494d53595f666c72787d828688898886827c756c635a4f453a2f23180d01000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173727b848c93999ea2a09f9e9f9fa1a4a8a6a39f9a948d867d756b62584e43392e23180c010000000000000915212d3a46525e6a76828e9aa6a99d9185786c6155493d3125190e020000000000000000000000131f2c3946525f6b767979797979797979797979797979797979776c6053473a2d2114070013202c3946535f6c7986939c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9386796c5f5346392c20130013202c3946535f6c7986939595959595887b6f6255483c2f2215090f1c2835424f5b6875828f95959595958b7e7164574b3e3124180b0d192633404c596673808c95959595958e8174675b4e4134281b0e000000000000000000000000000000000000000000020a121920272d32373b3f4244464748484847464543413e3a36322d28221b1d252b31363a3e404242424242413f3d3b38342e271e150b010000000013202c3946535f6c798693a0acaca09386796c65656565656565656565656565656565656565656565656565656565656565656565656565625b52473b2f23170b0013202c3946525f6b777b7b7c7c7c7b7a797774716c67615951493f362b21160b000000000000000000000000000000000000040f19242f39444f59646f79848f99a4aa9f948a7e828d98a2aa9f948a7f746a5f544a3f352a1f150a000000000000000000000000000000000013202c3946535f6c798693a0acaca0938679767676767676767676767676767676767676767677797b7e81868b9198a0a8aba39a91877d73685e53483c31261a0e03000000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acb2a79d9796969696969696969696969696969697989a9c9fa2a6aaa9a5a09b958f89827b746c645c534a41382e251b110700000000000000000000000a151f2a343e48515b646c747c838a90969ba0a4a8a8a5a19f9d9b99989898979898999a9b9da0a3a6a8a4a09b96908a837c746c635a51473e33291e14090000000013202c3946525f6c777b7b7b7b7b7b7b7b776c5f5246392c2013060000000000000000000000000613202c3946525f6c777b7b7b7b7b7b7b7b786c5f5346392d2013060000000000000000000000000000000000000000000000000000000000000000000714202d3a46535f6c79859293867a6e635956595e646b71777d83898e92959695928d877e756c61564b4035291d1206000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d817369727a81888e9396999c9d9e9e9e9d9c9a97938e89827b746b625950463c32271c11060000000000000005111d2936424e5a66727d8995a1ada195897d7165594d42362a1f13070000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b655b5044382b1f12060013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09386796c5f5346392c20130013202c3946535f6c798693a0a2a2a295887b6f6255483c2f2215090f1c2835424f5b6875828f9ca2a2a2988b7e7164574b3e3124180b0d192633404c596673808c99a2a2a29b8e8174675b4e4134281b0e0000000000000000000000000000000000000000020b141c242b32383e43474b4e505254545555545352504d4a47423e39332d26272f363c42464a4d4e4f4f4f4e4d4c4a47443f3930271d12070000000013202c3946535f6c798693a0acaca09386796c5f58585858585858585858585858585858585858585858585858585858585858585858585856514940352a1f13070013202c3946535f6c79868889898988878684817d78726b635b51483d32271c110500000000000000000000000000000000000b16202b36404b56606b75808b96a0aba3988d83787b86919ba6a69b91867b71665b51463b31261c11060000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c696969696969696969696969696969696969696a6c6e71757a80878e969fa8aca3998f857a6f64594e42372b1f1307000000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acada1958c8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8c8d909296999ea2a8aca6a19a948d867e766e655c534a40372d23190f0400000000000000000006111c26313c46505a636d757e868e959ba1a7aba6a19c989592908e8d8c8b8b8a8b8b8c8d8f9193969a9ea2a8a7a19b958d867e756c63594f453b30251a0f0400000013202c3946535f6c798688888888888886796c5f5346392c2013060000000000000000000000000613202c3946535f6c798688888888888886796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000000005121f2b3844515d6a778390978b80746b6563656a70767c82898f949a9ea2a3a29e9890877d73685c51463a2e22160a000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d817367686f767d82878a8d8f90919292918f8d8a87837d777169625950473e342a20150b0000000000000000010d1925313d4955616d7985919ca8a5998d82766a5e52473b3024180d02000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5b53493f33281c0f030013202c3946535f6c798693939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939386796c5f5346392c20130013202c3946535f6c798693a0acafa295887b6f6255483c2f2215090f1c2835424f5b6875828f9ca8afa4988b7e7164574b3e3124180b0d192633404c596673808c99a6afa89b8e8174675b4e4134281b0e00000000000000000000000000000000000000010b141d262e363d43494f53575a5d5f6061616161605e5c5a56534e4a443e3831313941484e5256595b5c5c5c5b5a585654504a42392f24180d0100000013202c3946535f6c798693a0acaca09386796c5f534b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4a463f372e24190e020013202c3946535f6c798693969696959492908d89847d756d63594f44382d22160a0000000000000000000000000000000007121d27323d47525d67727d87929da7a79c91877c71747f8a959faaa2988d83786d62584d43382d23180d0300000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5d5e5f6265696f757c848d96a0aaaba1978c81756a5f53473b2f24170b000000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca093867d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7e7f818386898d92979ca2a8aca59f97908880776e655c52493f352b20160b0100000000000000000b17222d38434d58626c757f8890989fa6ada6a09a95908c89868482807f7e7e7d7e7e7f818284878a8e92979ca3a9a69f9890877e756b61574c42372c20150900000013202c3946535f6c798693959595959386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693959595959386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000000003101c2936424f5b6874818d9991867d75716f71757b81878d949aa0a5a2a0a0a1a4a2998f84796e62564a3e32261a0e020000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675e656b71767a7e8182848585858483817e7b77726c665f5850473e352c22180e040000000000000000000915212d3945515c6874808b97a3aa9e92867b6f63584c41352a1e1308000000000000000000000a16212c3740484f525353535353535353535353535353535353524f4941372d22170b000013202c3946535f6c798686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686796c5f5346392c20130013202c3946535f6c798693a0acafa295887b6f6255483c2f2215090f1c2835424f5b6875828f9ca8b1a4988b7e7164574b3e3124180b0d192633404c596673808c99a6b3a89b8e8174675b4e4134281b0e0000000000000000000000000000000000000009131d262f3840474e555a5f63676a6c6d6e6e6e6d6d6b6966635f5a554f49423b3a434b53595e63666869696968676563605c544b4035291d110500000013202c3946535f6c798693a0acaca09386796c5f53463e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3d3a342d251c1207000013202c3946535f6c7986919190909193969a99948f877f756b60554a3e32261a0e020000000000000000000000000000040e19242e39444e59646e79848e99a4aba0958a80756a6d78838e99a3a99f948a7f74695f544a3f342a1f140a00000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f534f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f50515355595e636a727b848e99a3aea89d92877b6f64584c4034281b0f030000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386797070707070707070707070707070717274777a7d81868b91979ea5aca9a29a928981776e645b51473c32281d12070000000000000005111d28333e4a545f6a747e88919aa2aaaba39c958f8984807c79777573727171717171727475787a7d82868b91989fa7aaa29990877d73695e53483d31261a0e03000013202c3946535f6c798693a0a2a2a09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0a2a2a09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000000000000000e1a2733404c5865717d8a96988f87817d7c7d81868c92989fa59f9a96939394979ca1968a7e73675b4f42362a1e11050000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a5a60656a6e71747677787878777674726e6b66615b544d463e352c231a10060000000000000000000005111c2834404c57636f7a86929da9a3978b8074685d51463b2f24190e0300000000000000000005101a252e373e4346464646464646464646464646464646464646433e372f261b11060000131f2c3946525f6b767979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979766b5f5246392c1f130013202c3946535f6c798693a0acaca295887b6f6255483c2f2215090f1c2835424f5b6875828f9ca8aca4988b7e7164574b3e3124180b0d192633404c596673808c99a6aca89b8e8174675b4e4134281b0e00000000000000000000000000000000000007111b252f38414a525960666b6f7376787a7b7b7b7a797775726f6b66615b544d45434c555d646a6f72747575757573726f6d665d5145392d20140700000013202c3946535f6c798693a0acaca09386796c5f534639323232323232323232323232323232323232323232323232323232323232323232312e29231b130a00000013202c3946535f6c79868584848485868a8e959d9991877d72665a4e42362a1e110500000000000000000000000000000b15202b35404b55606b75808b95a0aba4998e84796e6367717c87929ca7a69b91867b71665b51463b31261b1106000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346434343434343434343434343434343434446494d52596069727c87929da8afa3988c8074685c5044372b1f12060000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c636363636363636363636363636466686a6d71757a80868c939aa2aaaca49b938980766d63594e44392f24190e030000000000000b16222e3944505b66717b86909aa3acaaa199918a837d7874706d6a68676565646464656667696b6e71757a80868d959ea7aba2998f857a7065594e42372b1f1307000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000000000000000b1724303d4955616e7a86929d99928d8a898a8d92979ea4a09a948e898786888b91999b8f83776b5e52463a2d2114080000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4f555a5e626567696a6b6b6b6b696865625e5a555049433b342c231a11080000000000000000000000000c18242f3b47525e6975818c97a3a89c9185796e63574c41352a1f14090000000000000000000009131c252c32373939393939393939393939393939393939393937332d251d140a000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b645a4f43372a1e110013202c3946535f6c798693a0a0a0a095887b6f6255483c2f2215090f1c2835424f5b6875828f9ca0a0a0988b7e7164574b3e3124180b0d192633404c596673808c99a0a0a09b8e8174675b4e4134281b0e0000000000000000000000000000000000030e18232d37414a535c636b71777b80838586888888878684827e7b77726c665f574f4b555e676f757b7e8182828281807e7c786e6155483b2f22150800000013202c3946535f6c798693a0acaca09386796c5f5346392c252525252525252525252525252525252525252525252525252525252525252524221d18110a0100000013202c3946525f6b777978777777787a7d838b949f998e83776b5e5246392d2014070000000000000000000000000007121c27323c47525c67727c87929ca7a89d92877c72675c606a75808b96a0aba2988d82776d62584d42382d22180d020000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f534639363636363636363636363636363637383a3d41474e57606a75818c98a3afa89c9184786c6053473a2e2215090000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f56565656565656565656565758595b5e6165696f747a81889098a0a9ada49b92897e756a60564b40352a1f14090000000000030f1b27333e4a56616c77828d98a2acaba2988f877f78726d6864605e5c5a595857575758595a5c5f6265696f757b838c959ea8aba1978c81766a5f53473b2f23170b000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000000000000000814212d3945515d6975818c97a19d99979697999ea3a19b958f88827d7a797b8087909a93877a6e6255493d3024170b0000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d494e5255585b5c5d5e5e5e5e5d5b5956524e4a443e38312a221a11080000000000000000000000000007131f2a36424d59646f7b86929da8a2968b7f74685d52473c31261b1005000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a27221b130b020000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5a52483e32261a0e0013202c3946535f6c7986939393939393887b6f6255483c2f2215090f1c2835424f5b6875828f93939393938b7e7164574b3e3124180b0d192633404c596673808c93939393938e8174675b4e4134281b0e000000000000000000000000000000000009141f2a353f49535c656e757c82878c8f91939495949493918e8b87837d7770696159525c67707981878b8e8f8f8f8e8d8b887b6f6255483c2f22150900000013202c3946535f6c798693a0acaca09386796c5f5346392c20181818181818181818181818181818181818181818181818181818181818181715120d070000000000111e2a37434f5a656c6c6b6a6a6a6b6d7278828d999f93877a6e6155483b2f221509000000000000000000000000030e19232e39434e59636e79838e99a3aba1968b81766b605559646e79848f99a4a99f94897e74695f54493f34291f14090000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c292929292929292929292929292a2b2d31363c454e59646f7b87939facada194887b6f63564a3d3124170b0000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f534a4a4a4a4a4a4a4a4a4a4a4b4c4f5155595e636970767e868e97a0a9ada49a91877c72675d52473c31251a0f030000000007131f2b37434f5b67727d89949fa9aea49990867d756d67615c5854514f4d4c4b4b4b4b4b4c4e505255595e636a7179838c96a1aca89e92877b7064584c4033271b0f020013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000000000005111d2935414d58646f7a858f99a2a6a3a3a3a6a29c96908a837d77716d6d6f757e8893968a7d7165584c3f3326190d0000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d404246494c4e505151515151504e4c4946423e39332d261f1810080000000000000000000000000000020e1925313c47535e6a75808c97a2a79c90857a6e63584d42372c21170c01000000000000000000010910161a1e1f2020202020202020202020202020202020201e1b16100901000000000a16212c3740484f525353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353524f4840372c21160a0013202c3946535f6c7986868686868686867b6f6255483c2f2215090f1c2835424f5b687582868686868686867e7164574b3e3124180b0d192633404c59667380868686868686868174675b4e4134281b0e00000000000000000000000000000000040f1a26313c46515b656e7780878e93989b9ea0a1a2a1a19f9d9b97938e89827b736b6259636e78838b92979a9c9c9c9b9995887b6f6255483c2f22150900000013202c3946535f6c798693a0acaca09386796c5f5346392c20130b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0906010000000000000f1b27333e49535b60605e5d5d5d5f6167717d8a96a296897c6f6356493d3023160a0000000000000000000000000a15202a35404a55606a75808a95a0aaa59a8f84796f64594f525d68727d88939da8a69b90867b70665b50463b30261b100600000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201c1c1c1c1c1c1c1c1c1c1c1c1d1e21252b333d47535f6b7783909ca8b0a4978b7e7265584c3f3326190d0000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f53463d3d3d3d3d3d3d3d3d3d3e404245494d52585e656c747c858e97a1abaca3988e84796e63584d42372b201409000000000b1723303c4854606c77838f9aa5b0a79d92887e746b635c56504b484542413f3e3e3e3e3f40414346494d52585f67707a85909ba6afa3988c8074685c5043372b1e12050013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000000000010d1925303c47535e69737d8790979c9fa09e9b96918b857e78726c666160636c76818d998d8074675a4e4135281c0f0200000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d40363a3d3f414344454545444342403d3a36322d28221c150e06000000000000000000000000000000000914202b36424d59646f7a85909ba6a1968b8075695e53493e33281e13090000000000000000000000050a0e1113131313131313131313131313131313131313110f0a0500000000000005101a252e373e4346464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646433e372e251a100500131f2c3946525f6b767979797979797979786d6155483b2f2215080f1b2835424e5b67737979797979797979797063574a3e3124170b0c1926333f4c58657179797979797979797972675a4d4134271b0e000000000000000000000000000000000914202b37424d58636d77818991999fa4a8a5a19d9b9a9a9a9b9c9f9f9a948d857d746b626974808a949da3a7a6a09b989795887b6f6255483c2f22150900000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000000000000a16212d3741494f53575a5a5a5a5b5d636f7c8996a2968a7d7063564a3d3023170a000000000000000000000007111c27313c47515c67717c87919ca7a89e93887d73685d52484b56616b76818c97a1aca2978d82776d62574d42372d22170d02000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013101010101010101010101010121519212b36424f5b6774818d9aa6b3a6998d8073675a4d4134271b0e0100000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f534639303030303030303030323336393d41474d535a626a737c858f99a3adaaa0958b8075695e53483c3125190e020000000e1b27333f4c5864707c8894a0abada1968b80766c6259514a443f3b383634333231313132333437393d41474d555e68737e8a96a1ada89c9084786b5f53463a2d2114080013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000000000000814202b36424c57626b757e868c909293918f8a85807a736d67615b55535a65717d89938f8276695c5043372a1d110400000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d40342d303335363738383838373533312e2a26211c17110a030000000000000000000000000000000000030e1a25313c47525e69747f8a959fa79c91867b70655a4f453a2f251a1006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131c252c32373939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393937322c251c13090000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c665c5145392d2014070d1a26333f4b5761696c6c6c6c6c6c6c6c6c675e53473b2f2216090b1724303d49545f686c6c6c6c6c6c6c6c6c6961564a3e3226190d000000000000000000000000000000010d1925313d48535f6a747f89939ba3aaa7a09a95918e8d8d8d8e9092969a9e978f877d746a6d7985919ca6afa59c958f8c8a8b887b6f6255483c2f22150900000013202c3946535f6c798693a0acaca09386796c5f5346392c20130606060606060606060606060606060606060606060606060606050300000000000000000000000005101b252f37434f59626767676767696d75808b98a195887c6f6256493c3023160900000000000000000000030e18232e38434e58636e78838e98a3aca2978c81766c61564c41444f5a656f7a85909aa5a99e94897e74695e54493e34291f1409000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000305080f1a26333f4c5965727e8b98a5b2a89b8e8275685b4e4235281c0f0200000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c23232323232323242527292d31363b42495058616a737d87919ba6b1a79c91867b7064594d42362a1e1307000000111e2a36434f5c6874818c989d9fa29c9085796e645a50473f39342f2c292726252424242526282a2d31363c434c57626d7985919eaaaca094877b6e6255493c2f23160a0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000000000000030e1a25303b45505a636c747b8084868685827e79746e68625c564f494854616d7986868684776b5e5145382b1f120500000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034272426282a2b2b2b2b2b2a282724211e1a16110b0500000000000000000000000000000000000000000914202b36414c57626d78838e99a3a2978c82766c61564c41372c22180e0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a26211a130a0100000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5b544a4034291d11040a17232f3a454f585e5f5f5f5f5f5f5f5f5f5c554c42372b1f13070814202c38434d565d5f5f5f5f5f5f5f5f5f5d574f44392e22160a00000000000000000000000000000005111d2a36414d5965707b86919ba5ada69d958f8985828180808183868a8e93999990867c72717d8a96a2ada99e938a837f7d7e807b6f6255483c2f22150900000013202c3946535f6c798693a0acaca09386796c5f5346392c2013131313131313131313131313131313131313131313131313131312100c0701000000000000000000000915212e3b4754606b737473737476797f87919c9c9185796d6054473b2e221508000000000000000000000a151f2a353f4a555f6a75808a959faaa59b90857a70655a4f453a3d48535e68737e89949ea9a59b90857b70655b50453b30251b10060000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000b1825313e4b5764717e8b98a4b1a89c8f8275685b4f4235291c0f0200000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c2017171717171717181a1d20252a30373e464f58616b757f8a949faaaea3978c81756a5e52473b2f23170b000000131f2c3945525f6b77848b8e909395978b8074685d52483e352e2823201d1b1918181818181a1b1e21252a313a45515d6975828e9ba7afa3968a7d7064574a3e3124180b0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000000000000009141f29343e48515a62696f747779797876726e68635d57514a443e45525e6a7679797979766a5e5145382b1f120500000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a1a1b1d1e1e1e1e1e1d1c1a1815120e0a0500000000000000000000000000000000000000000000030e1925303b46515c67717c87919ca69e93887d73685d53483e342a1f150b0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000010910161a1e1f20202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201f1e1a161009010000000a16212c3740484f52535353535353535352504a42382e23180c0006121e29333d464d51535353535353535353504b433a30251a0e0304101b27313b444c51535353535353535353514d453d33281d11060000000000000000000000000000000915212d3a46525e6a75818d98a2ada89e948b847d787573737375777a7d82888e95988e847a74818d99a6afa3988c827873717173746b6054473b2e21150800000013202c3946535f6c798693a0acaca09386796c5f5346392c202020202020202020202020202020202020202020202020202020201f1c18120b040000000000000000000915222f3c4855626f7b8181818182858a91999d948b8074695d5144382c1f130600000000000000000006111c26313c46515c66717c86919ca6a99f94897e74695e53493e3337414c57626c77828d98a2aca2978c82776c62574c42372d22170d0200000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000001040b1825313e4b5764717e8b98a4b1a89c8f8275685b4f4235291c0f0200000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c20130a0a0a0a0a0a0c0e1114191f252c343d464f59636d78838e99a4b0a99d92867a6f63574b3f34271b0f03000013202c3946525f6c777c7e818486898b877b6f63574c41362c231d1713100e0d0c0b0b0b0c0d0f1115191f2934414d5a6673808c99a6b1a5988b7e7265584c3f3226190c0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000000000000000000020d17222c363f4850585e64686a6c6c6b6966625d57524c463f3936424e59646b6c6c6c6c6b64594e4236291d100400000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0f101112121211110f0d0b0805020000000000000000000000000000000000000000000000000008131e29343f4a55606a75808a959fa59a8f847a6f655a50463b31271d130a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0e1113131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313110e0a05000000000005101a252e373e4346464646464646464646433f3830261c120700010c17212b343c414546464646464646464644403931281e140900000a152029323a404446464646464646464645413b342b21160c000000000000000000000000000000000c1824313d4956626e7a86929ea9aca1968c8279726c69676667686a6d71767c838a92968c8177838f9ca9ac9f93877b706764656767625a4f43382b1f130600000013202c3946535f6c798693a0acaca09386796c5f5346392c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b28231d160d0400000000000000000814212e3a47535f6b77838d8d8e8f92969a96928b82796e63584c4034281c10040000000000000000030d18232d38434d58636d78838d98a3ada2988d82776d62574c42372c303b45505b66707b86919ba6a99e93897e73695e53493e34291e140900000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130b0b0b0b0b0b0b0b0b0b0c0c0e10141b2733404c5965727e8b98a5b2a89b8e8275685b4f4235281c0f0200000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000104080e141b222b343d47515c66717c88939eaaaea3978b8074685c5044382c1f13070000111e2b37434f5b656d707275777a7c7e81776b5f53473b2f241a110b070401000000000000000205080e1926323f4c5865727e8c98a5b2a6998c807366594c403326190d0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000000000000000006101a242d363e464d53585b5e5f5f5f5d5a56514c46413b342e313d48525a5f5f5f5f5f5f5a52483d31261a0e0100000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d010000000000000000000000000000000000000000000000000000000000000000000000000000020d18232e39434e59636e78838d98a2a1968b81766c62574d43392f251c1208000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131c252c32373939393939393939393937332d261e140b000000051019222a30353839393939393939393938342f281f160c020000030e1720292f35383939393939393939393835302922190f05000000000000000000000000000000000e1b2734404d5965727e8a97a3aea79b90857a7067615c5a595a5b5e61666b717880889193887d84919eaaa99c9083776b5f57585a5b5750483d32271b0f0300000013202c3946535f6c798693a0acaca09386796c5f534639393939393939393939393939393939393939393939393939393939393938342f281f160c020000000000000006121e2b37434f5b67737e8b979a94908f8d8a86807970675d52473b3024180c0000000000000000000a141f2a343f4a545f6a747f8a949faaa69c91867b71665b50463b302529343e49545f69747f8a959faaa59b90857a70655b50453b30251b1005000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20181818181818181818181818191a1d20252d38434f5b6874818d9aa6b3a69a8d8174675a4e4134271b0e0100000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000002091019222b353f4a55606b76828d99a5b1a89c9084786c6054483c2f23170b00000f1b27333e49535b616366686b6d70727571675b4f42362a1e130800000000000000000306090c1014181e26333f4c5965727e8c98a5b2a6998c807366594c403326190d0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000000000000000000000008121b242c343b42474c4f51535352504e4a46403b352f29232b3640484e5253535353524e4840362b2015090000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0100000000000000000000000000000000000000000000000000000000000000000000000000000006111c27323d47525c67717b86909aa49d93887e74695f554b41372e241a110700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001030506070808080807060402000000000000000000000000000000010203030302010000000000000000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2b27221c140c02000000000710181f25292c2c2c2c2c2c2c2c2c2c2b28231d160d0400000000050e171e24292b2c2c2c2c2c2c2c2c2c2c29251f1810070000000000000000000000000000000000101d2936424f5b6875818e9aa6afa3978b7f73685e56504d4d4d4f51555a60666e767f88928f8486929faba79a8e8174685b4f4b4e4e4b463f362c21160a0000000013202c3946535f6c798693a0acaca09386796c5f534646464646464646464646464646464646464646464646464646464646464644403931281e140900000000000000020e1a26323e4a56626e7a8692988c8382817e7a756e675e554b40352a1f1308000000000000000006111b26313b46515b66717b86919ba6aa9f958a7f746a5f54493f34291f222d38424d58636d78838e99a3aca1978c82776c61574c42372c22170c020000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c252525252525252525252525252627292c31373f4954606b7784909ca9b1a4988b7e7265594c3f33261a0d0000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000071019232e38434f5a65717d8894a0acaca194887c7064584b3f33261a0e01000b16222d38414a505457595c5e61636668665f564a3f33271a0e020000000104070a0c0f1215181c2024293038424e5b6774808d99a6b2a5998c7f7266594c3f3326190d0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000000000000000000009121a222a30363b3f424546464544413e3a352f2a241e1a242e363d43454646464645433d362e241a0f040000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000000000000000000000000000000000000000000000000000000000000000000000000000000000b16202b36404b555f6a747e88929ca49a90857b71675d534940362c23180e02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003070a0d0f111314151515141412110f0c090602000000000000000206090c0d0f0f0f0f0f0e0d0b09060300000000000000000000000000000000000000000000000000010910161a1e1f2020202020202020201e1b17110a02000000000000060e14191d1f2020202020202020201f1c18120b04000000000000050c13181c1f2020202020202020201f1d19140d06000000000000000000000000000000000000111e2b3744515d6a7783909da9aca093877a6e62574c444140404245494e555c646d76808a948f8f97a2aea6998c807366594d4041413f3b342d241a0f050000000013202c3946535f6c798693a0acaca09386796c5f5353535353535353535353535353535353535353535353535353535353535353504b433a30251a0e03000000000000000a16222e3a46525e6a76828e998d827674726e69645d554c43392f24190e0200000000000000020d18222d38424d58626d78828d98a2ada3998e83786e63584d43382d22181b26313c46515c67717c87929ca7a99e93897e73695e53493e33291e13090000000000000013202c3946535f6c798693a0acaca09386796c5f5346393232323232323232323232323232323436383c4249515b66717c8894a0acada195897c7063574a3e3124180b0000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000007111c27323d4954606c7884909ca8b1a5988c8074675b4f42362a1d11040005111b262f383f44484a4d4f525457595b5a554d44392e22170a0205080b0d101316191c1f2225282c30353b414a545f6a76838f9ca8b1a4978b7e7165584b3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000000000000000000000000000810181f252b2f3336383939393735322e29241e1913121b242c323639393939393936322c241b1208000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0100000000000000000000000000000000000000000000000000000000000000000000000000000000040f19242e39434d58626c76808a949da1978d83796f655b52483e352a1f1308000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0f1316191c1e202121222221201f1d1b1916120e0a0500000003090e1215181a1b1c1c1c1c1b19171513100c0600000000000000000000000000000000000000000000000000050a0e1113131313131313131313120f0b0600000000000000000003080d101213131313131313131312100c0701000000000000000001070c101213131313131313131312100d080200000000000000000000000000000000000000121f2c3945525f6b7885929eabaa9e9184786b5f52463a34333436393d434a525b646d78828d989ba0a9b2a6998c7f7265594c3f3435332f2a231b1208000000000013202c3946535f6c798693a0acaca09386796c5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5c554c42372b1f13070000000000000006121e2a36424e5a66727e8a9692867a6e65625e58524b433a31271d1208000000000000000009141f29343f49545f69747f89949fa9a79c92877c71675c51463c31261c11141f2a353f4a55606a75808b96a0aba59a90857a70655a50453a30251a100500000000000013202c3946535f6c798693a0acaca09386796c5f53463e3e3e3e3e3e3e3e3e3e3e3e3e3e3f3f404245484d535b636d77828d99a4b0a99d9185796d6054473b2f2216090000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000b16212c3844505b6774808c98a4b1a89c9083776a5e5245392c20130700000a141d262d34383b3e404345484a4d4f4e4a443b32281d110b0e1114171a1d1f2225282b2e3134383c41464c535c66707b87939fabaea295897c7063564a3d3124170b0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000000000000000000000000060d141a1f2327292b2c2c2c2b2825221d18130d0809121a21262a2c2c2c2c2c2c2a26211a120900000000000000000000000000000000000013202c3946535f6c798693a0a0a09a8d8173675a4d4034271a0d01000000000000000000000000000000000000000000000000000000000000000000000000000000000008121d27313c46505a646e78828b959f9f958b81776d645a50463b3024180c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a10161a1f2326292b2c2d2e2e2e2e2d2c2a2825221e1a16110b05080f141a1e2225272829292928272624221f1c17120b030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929facaa9d9083766a5d5044372a2627292d32394049525c66707b86929da9b2b2a6998c7f7265594c3f322826231e18110900000000000013202c3946535f6c798693a0acaca09386796c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c675e53473b2f22160900000000000000010d1925313d4956626d798692938b7f73675b524d47403931281f150b010000000000000006101b26303b46505b66707b86909ba6aba0968b80756b60554a40352a1f150a0e18232e39434e59646e79848f99a4aca1978c81776c61574c41372c21170c01000000000013202c3946535f6c798693a0acaca09386796c5f534b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4c4d4f5154595e656d757f89949faaafa4998d8175695d5144382c1f13070000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000004101c27333f4b5763707c8895a1adac9f93867a6d6154483b2f2216090000020b141c23282c2f313436393b3e4042413e393229201614171a1d202326292c2f3235383a3d4144484c51575e656e77828d98a3afab9f92867a6d6154483b2f2216090013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000000000000000000000000002090e13171a1d1f20201f1e1c1916110d07020000080f151a1e1f202020201f1e1a150f080000000000000000000000000000000000000013202c3946535f6c798693939393938d8173675a4d4034271a0d010000000000000000000000000000000000000000000000000000000000000000000000000000000000000b15202a343e48525c667079838d939393938980766c62584c4034281b0f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f151c21262b2f323537393a3b3b3b3b3a383734312e2a26211c1610131a20252a2e313335363636353432312e2c28231c150c0300000000000000000004070808080808080808080704010000000000000000000000000000000000000000000000000306080808080808080808080808070400000000000000000000000000000407080808080808080808060300000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaa9d908376695d5043362a1d1a1d21272e37404a545f6a75818c98a3afb2a6998c7f7265594c3f32261a17130d060000000000000013202c3946535f6c798693a0acaca0938679797979797979797979797979797979797979797979797979797979797979797979797063574a3e3124170b00000000000000000915212d3945515d69758186868684786c5f53463c362f271f160d0300000000000000020d17222d37424d57626d77828d97a2ada4998f84796e64594e43392e23190e0307111c27323c47525d68727d88939da8a89e93887e73685e53483e33281e1309000000000013202c3946535f6c798693a0acaca09386796c5f5858585858585858585858585858585858595a5b5e61656a70777f88919ba5b0a99e93887c7065594d4034281c10030000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000b17232f3b4754606c7985929eabaea295897c7063574a3e3124180b000000020a11171c202225272a2c2f31343535322d2720181c2023272a2d303335383b3e4144474a4d5054585d62686f77808a949ea9b2a69a8e83766a5e5245392c2013070013202c3946535f6c798693a0acaca09386796c5f5346392c2013060303030303030303030303030613202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002070b0e1012131313110f0d0906010000000000040a0e11131313131313110e0a04000000000000000000000000000000000000000013202c3946535f6c79868686868686868173675a4d4034271a0d01000000000000000000000000000000000000000000000000000000000000000000000000000000000000030e18222c36404a545e67717a848686868686867e74695c4f4336291d1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a121920272d32373b3f4244464748484847464543413e3a36322d28221b1d252b31363a3e404242424242413f3d3b38342e271e150b01000000000000060c101315151515151515151513110c07010000000000000000000000000000000000000000040a0f1214151515151515151515151513100c0700000000000000000000060c1013151515151515151515130f0b050000000000000000000000000000000000000000000013202c3946535f6c7986929facaa9d9084776a5d5144382b1f1a18161c252e38424d58646f7b87939fabb2a6998c7f7265594c3f3226190c0702000000000000000013202c3946535f6c798693a0acada09489868686868686868686868686868686868686868686868686868686868686868686867e7164574b3e3124180b000000000000000005111d2935414d5965717979797979766b5f5346392d241d150d04000000000000000009141e29343e49545e69747e89949ea9a89d93887d72685d52473d32271c120700000b15202b36404b56616b76818c97a1aca59a8f857a6f655a4f453a2f251a10050000000013202c3946535f6c798693a0acaca09386796c6565656565656565656565656565656565656566686a6d71757b8189919aa3adaba1978d82766b6054483c3024180c000000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000007131f2b3844515d6976838f9ca8b1a4988b7e7265594c3f33261a0d0000000000060c101316181b1d20222527282826221c2125282c303336393c3f4245484a4d505356595c6064696e737a8189929ba5b0aba0958a7e72665a4e4236291d11040013202c3946535f6c798693a0acaca09386796c5f5346392c2013101010101010101010101010101013202c3946535f6c798693a0acada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6b7679797979797979797266594d4033271a0d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006101a242e38424c555f6872797979797979797974685c4f4336291d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141c242b32383e43474b4e505254545555545352504d4a47423e39332d26272f363c42464a4d4e4f4f4f4e4d4c4a47443f3930271d120700000000020a11181c20212222222222222222201d18120b03000000000000000000000000000000000000070f151b1f212222222222222222222221201c18120a02000000000000020a11181c202122222222222222211f1c161009010000000000000000000000000000000000000000121f2c3845525e6b7884919eaaab9e9285796c6053473b312b272423222126313c47535f6b77838f9ca8b2a6998c7f7265594c3f3226190c0000000000000000000013202c3946535f6c798693a0acb0a59b949393939393939393939393939393939393939393939393939393939393939393938b7e7164574b3e3124180b0000000000000000010d1925313d49545f686c6c6c6c6c6b645a4f43372b1e120b03000000000000000005101b25303b45505b65707b85909ba5aca1968c81766b61564b40362b20160b000000040f19242f3a444f5a656f7a85909aa5aca1968c81766c61564c41372c21170c0100000013202c3946535f6c798693a0acaca09386797171717171717171717171717171717171717272737476797d81868c939ba3acaca39990857b70655a4e43372c201408000000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000003101c2835414e5a6774818d99a6b3a69a8d8174675a4e4135281b0f000000000000000407090c0e111316181a1c1b1f24282d3135383c3f4246494c4e5154575a5d606366696c70757a7f858c939ba4adaea49a8f84786d61564a3e32261a0d010013202c3946535f6c798693a0acaca09386796c5f5346392c201c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c202c3946535f6c798693a0acada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002040608090a0b0b0c0c0c0b0b0a0807050301000000000000000000000000000000000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6960554a3d3125180c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008121c26303a434d5760686c6c6c6c6c6c6c6c6a62584c4034271b0e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010b141d262e363d43494f53575a5d5f6061616161605e5c5a56534e4a443e3831313941484e5256595b5c5c5c5b5a585654504a42392f24180d010000020b141c23282c2e2e2e2e2e2e2e2e2e2d29241d150d030000000000000000000000000000000008111920262b2e2e2e2e2e2e2e2e2e2e2e2e2c28231c140c0200000000020b141c23282c2e2e2e2e2e2e2e2e2e2c27221b130a0000000000000000000000000000000000000000111e2a3744505d6976838f9ca8ada194887c6f63584d433c3633312f2e2e2d2d37424e5b6773808c99a5b2a6998c7f7265594c3f3226190c0000000000000000000013202c3946535f6c798693a0acb7ada5a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0988b7e7164574b3e3124180b0000000000000000000814202c38434d565d5f5f5f5f5f5f5a52493e33271b0f020000000000000000020c17222c37424c57626c77828c97a2aca59a90857a6f655a4f443a2f24190f040000000008121d28333d48535e68737e89949ea9a89d93887d73685d53483d33281e130800000013202c3946535f6c798693a0acaca093867e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e80818386898d92979ea5acaaa29a91877e74695f54493d32261b0f03000000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000d1926333f4c5865727e8b98a4b1a89b8f8275695c4f4336291c1000000000000000000000000104070c13191f252a2f34393d4145484c4f5255585b5e606366696c6f7275797c81858a90969da5adaea59c92887d72675c5145392d211609000013202c3946535f6c798693a0acaca09386796c5f5346392c2929292929292929292929292929292929292c3946535f6c798693a0acada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306090c0e11131416171818191918181716151412100d0b08040100000000000000000000000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5d574e44392d211509000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a141e28313b454e575d5f5f5f5f5f5f5f5f5e5950463b3024180c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131d262f3840474e555a5f63676a6c6d6e6e6e6d6d6b6966635f5a554f49423b3a434b53595e63666869696968676563605c544b4035291d110500000a141d262e34383b3b3b3b3b3b3b3b3b39352f271f150b01000000000000000000000000000006101a232b32373a3b3b3b3b3b3b3b3b3b3b3b39342e261e140a000000000a141d262e34383b3b3b3b3b3b3b3b3b38332c251c1208000000000000000000000000000000000000000f1c2835424e5b6774808c99a5b0a4988c8074695f554d4743403e3c3b3a3a3a3a3f4b5864717d8a97a3b0a6998c7f7265594c3f3226190c0000000000000000000013202c3946535f6c798693a0acb9b1aaa6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a4988b7e7164574b3e3124180b00000000000000000004101b26313b444c515353535353524f4940372c21160a00000000000000000009131e29333e49535e69737e89939ea9a99e93897e73685e53483d33281d13080000000000010c16212c37414c57626c77828d98a2ada49a8f857a6f645a4f453a2f251a0f05000013202c3946535f6c798693a0acaea2968d8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8c8c8e909295999ea3a9aca69f9890887e756c62574d42372c21150a00000000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000b1824313e4a5764707d8a96a3b0a99d9083766a5d5044372a1d110000000000000000000000010810171e242a30363b4045494d5154585b5e6164676a6d707376787b7e8285898d91969ca1a8afaca49c938a80766c61564b3f34281d1105000013202c3946535f6c798693a0acaca09386796c5f53463936363636363636363636363636363636363636363946535f6c798693a0acada09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000000000000000000000000002070b0f1215181b1d1f212224242525252525242322201e1c1a1714110d09050000000000000000000000000000000000000000000000000a16212c3740484f525353535353535353514c453c32271c110500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020c161f29333c454c515353535353535353524e473e342a1f13070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007111b252f38414a525960666b6f7376787a7b7b7b7a797775726f6b66615b544d45434c555d646a6f72747575757573726f6d665d5145392d2014070006111c262f383f4548484848484848484845403931271d120700000000000000000000000000020d18222c353d4347484848484848484848484845403830261c1106000006111c262f383f45484848484848484847443e372e241a0f030000000000000000000000000000000000000d1a26333f4b5864707c8995a1aca89c91867b71675f58534f4c4a494847474646464956626f7c8996a2afa6998c7f7265594c3f3226190c0000000000000000000013202c3946535f6c798693a0acb3a89f9a9999999999999999999999999999999999999999999999999999999999999999988b7e7164574b3e3124180b000000000000000000000a151f29323a4044464646464646433e372e251b1005000000000000000004101a25303a45505a65707a85909aa5ada2978d82776c62574c41372c21160c0100000000000005101a25303b45505b66707b86919ba6aba1968b81766b61564c41362c21160b000013202c3946535f6c798693a0acb3a89f99989898989898989898989898989898989898989898999a9c9fa2a5a9aaa5a09b948d867e756d635a50463b31261b100400000000000013202c3946535f6c798693887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000000091623303c4956626f7c8995a2afaa9e9184776b5e5144382b1e1100000000000000000000020a131a22292f363c41474c5155595d6164676b6e717476797c7f8285888b8e9195999da2a7adada7a19a928a81786e645a4f45392e23180c00000013202c3946535f6c798693a0acaca09386796c5f53464343434343434343434343434343434343434343434346535f6c798693a0acada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000000000000000000000004090e13171b1f2225272a2c2e2f3031323232323231302e2d2b292623201d1915110c070200000000000000000000000000000000000000000005101a252e373e4346464646464646464645413b332a20160b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d17202a333a4145464646464646464645423c352c22180d02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030e18232d37414a535c636b71777b80838586888888878684827e7b77726c665f574f4b555e676f757b7e8182828281807e7c786e6155483b2f221508000b17222d38424a51545555555555555554514b43392f23180c0000000000000000000000000009141f29343e474e535555555555555555555554514a42382d22170b00000b17222d38424a515455555555555555544f4940362b2014090000000000000000000000000000000000000a1723303c4854606c7884909ba6aea2978d8379716a635f5b5957555554535353535255626f7b8895a2afa6998c7f7265594c3f3226190c0000000000000000000013202c3946535f6c798693a0acaea2978e8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8b7e7164574b3e3124180b00000000000000000000030d1720282f343839393939393937322c251c13090000000000000000000a16212c37414c57616c77818c97a1aca69b90867b70655b50453a30251a1005000000000000000009131e29343e49545f69747f8a959faaa89d93887d73685d53483d33281d11050013202c3946535f6c798693a0acacaca9a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a6a7a9a8a6a4a19d99958f89837c746c635b51483e34291f14090000000000000013202c3946535f6c798693887b6f6255483c2f2215090909090909090909090909090909090909090909090909090909101c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000915222f3c4855626e7b8895a2aeab9e9285786b5e5145382b1e12000000000000000000020b141c242c333a41474d52585c6165696d7074777a7d808386898c8e9194979a9da1a5a9aeaca7a29c968f8880786f665c52483e33281d120600000013202c3946535f6c798693a0acaca09386796c5f534f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f535f6c798693a0acada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000000000000000000040a10151a1f23272b2e313436393a3c3d3e3e3f3f3f3e3e3d3b3a383533302d2925211d18130d0701000000000000000000000000000000000000000009131c252c32373939393939393939393835302921180e0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050e18212930353839393939393939393936312b231a11060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009141f2a353f49535c656e757c82878c8f91939495949493918e8b87837d7770696159525c67707981878b8e8f8f8f8e8d8b887b6f6255483c2f221509000f1b27333f4a545c6161616161616161615d554b4034291d1004000000000000000000000005101b25303b4650595f61616161616161616161615c544a3f33281b0f03000f1b27333f4a545c6161616161616161605a52483c3125190d0000000000000000000000000000000000000714202c3844505c68737e8a959fa9a99f958c837b756f6b6865636261616060605f5f5f626f7b8895a2afa6998c7f7265594c3f3226190c0000000000000000000013202c3946535f6c798693a0acaca093867f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7e7164574b3e3124180b0000000000000000000000050e161e24282b2c2c2c2c2c2c2a27211b130a010000000000000000000e1a26323d48535e68737e89939ea0a09f948a7f74695f54493e34291e1309000000000000000000020d17222d38424d58636d78838e99a0a0a09a8f84796f645a4f44392e2216090013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09f9e9d9c9a9895918d89847e78716a625a51493f362c22180d030000000000000013202c3946535f6c798693887b6f6255483c2f2215151515151515151515151515151515151515151515151515151515151c2936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000815222e3b4855616e7b8894a1aeab9e9285786b5f5245382c1f120000000000000000020b141d262e363e454c52585e63686d7175797d8084878a8d8f9295989b9ea1a4a7aaadada9a5a09b96918b857e766e665d544a40362c21170c0100000013202c3946535f6c798693a0acaca09386796c5f5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000000000000000000030910161b21262b2f33373b3e40434547484a4b4b4c4c4b4b4a49484644423f3c3935312d28231e18130d0600000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c29241e170f06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f171e24292b2c2c2c2c2c2c2c2c2c2a252019110800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040f1a26313c46515b656e7780878e93989b9ea0a1a2a1a19f9d9b97938e89827b736b6259636e78838b92979a9c9c9c9b9995887b6f6255483c2f22150900121e2b37434f5b666d6e6e6e6e6e6e6e6d675c5145392c20130700000000000000000000010c17212c37424d57626b6e6e6e6e6e6e6e6e6e6e6d665b5044372b1f120500121e2b37434f5b666d6e6e6e6e6e6e6e6c64594d4135291c1004000000000000000000000000000000000004101c28343f4b57626d78838d97a1a9a79e958d86807b777472706f6e6d6d6d6d6c6c6c6b6f7b8895a2afa6998c7f7265594c3f3226190c0000000000000000000013202c3946535f6c798693a0acaca0938679727272727272727272727272727272727272727272727272727272727272727272726c6155493d3023170a000000000000000000000000050c13181c1f20202020201f1e1b1610090100000000000000000000111d2a36434e5a656f7a858f93939393938d83786d62584d42382d22170d020000000000000000000006101b26313c46515c67717c879293939393938b81766b61564a3e3225190c0013202c3946535f6c7986939393939393939393939393939393939393939393939393939393939292918f8d8b8885817d78736d665f5850483f372d241a1006000000000000000013202c3946535f6c798693887b6f6255483c2f222222222222222222222222222222222222222222222222222222222222222936434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000815222e3b4855616e7b8894a1aeab9f9285786b5f5245382c1f1200000000000000000a141d262f38404850575d63696f74797d8285898c909396999c9fa1a4a7aaadadaaa7a4a19d9994908b858079736c645c544b42382f251a10050000000013202c3946535f6c798693a0acaca09386796c696969696969696969696969696969696969696969696969696969696c798693a0acada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000000000000070e141b21272c32373b3f43474a4d4f5254555657585858585857565453514e4c4945413d39342f2a241e18110a03000000000000000000000000000000000000010910161a1e1f20202020202020201f1c19130d050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050d13181c1f20202020202020201f1d1a140e0700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000914202b37424d58636d77818991999fa4a8a5a19d9b9a9a9a9b9c9f9f9a948d857d746b626974808a949da3a7a6a09b989795887b6f6255483c2f2215090013202c3946525f6c777b7b7b7b7b7b7b796d6154473b2e2114080000000000000000000008131d28333e49535e69747b7b7b7b7b7b7b7b7b7b786c5f5346392d2013060013202c3946525f6c777b7b7b7b7b7b7b75695d5145382c2013070000000000000000000000000000000000000b17232f3a45515c67717b858f979fa6a79f98918c8784817e7d7c7b7a7a797979797978787b8895a2afa6998c7f7265594c3f3226190c0000000000000000000013202c3946535f6c798693a0acaca09386796c656565656565656565656565656565656565656565656565656565656565656565625a5045392d2114080000000000000000000000000001070c1012131313131313110e0a05000000000000000000000000121f2c3945525e6b768186868686868686867c71665c51463b31261b10060000000000000000000000000a141f2a353f4a55606a758086868686868686867d72665a4d4034271a0e0013202c3946535f6c79868686868686868686868686868686868686868686868686868686868686858482817e7c7975716c67615b554e463e362d241b120800000000000000000013202c3946535f6c798693887b6f6255483c2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f36434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000915222f3c4855626e7b8895a2aeab9e9285786b5e5145382b1e120000000000000007121c262f38414a525a61686f757a8085898e9295999c9fa2a5a8abaeadaaa7a4a19e9b9894918d88847f7a746e68615a524a423930261d1308000000000013202c3946535f6c798693a0acaca0938679767676767676767676767676767676767676767676767676767676767676798693a0acada09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000000000000020a11181f262c32383d42474b4f5356595c5e6062636465656565646463615f5d5b5855514d4945403b352f29231c150d0600000000000000000000000000000000000000050a0e1113131313131313131312100d08020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080c1012131313131313131313110d09030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010d1925313d48535f6a747f89939ba3aaa7a09a95918e8d8d8d8e9092969a9e978f877d746a6d7985919ca6afa59c958f8c8a8b887b6f6255483c2f2215090013202c3946535f6c79868888888888887b6e6154483b2e211508000000000000000000040f19242f3a454f5a65707a85888888888888888886796d6053463a2d20130700131f2c3945525e6b7784888888888885796d6054483c2f23170a00000000000000000000000000000000000006121e29343f4a555f69737c858d959ca1a6a39d9893908d8b8a8888878786868686868585858a96a2afa6998c7f7265594c3f3226190c0000000000000000000013202c3946535f6c798693a0acaca09386796c5f59595959595959595959595959595959595959595959595959595959595959595650483e33281d110500000000000000000000000000000000000000000000000000000000000000000000000000000000121f2c3845525e6b76797979797979797979756a5f554a3f352a1f140a00000000000000000000000000030e18232e39434e59646e7879797979797979797972665a4d4034271a0e00131f2c3946525f6b7679797979797979797979797979797979797979797979797979797979797978777674726f6c6965605c56504a433c342c241b12090000000000000000000013202c3946535f6c798693887b6f6255483c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c434f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000000091623303c4956626f7c8995a2afaa9e9184776b5e5144382b1e11000000000000040e19232e38414a535c646c737a80868b91959a9ea1a5a8acafaca9a6a3a09d9a9895928f8b8884817c78736e69635d575048403830271e140b01000000000013202c3946535f6c798693a0acaca0938783838383838383838383838383838383838383838383838383838383838383838793a0acada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000000040c141c232a31373d43494e53575c5f6366686b6d6e70717172727171706f6e6c6a6764615e5a55514c46403a342d261f18100800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005111d2a36414d5965707b86919ba5ada69d958f8985828180808183868a8e93999990867c72717d8a96a2ada99e938a837f7d7e807b6f6255483c2f2215090013202c3946535f6c79869395959594887b6e6154483b2e2115080000000000000000000b15202b36404b56616c76818c959595959595959386796d6053463a2d20130700111e2a36434f5b6774808c95959595897c7064574b3f33261a0e010000000000000000000000000000000000010c18232e39434d57616a737b838a90969b9fa2a3a09c9a9896959494949393939292929291939ca6b2a6998c7f7265594c3f3226190c0000000000000000000013202c3946535f6c798693a0acaca09386796c5f534c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4a453e362c22170c0000000000000000000000000407080909090909090909080705010000000000000000000000000000111d2a36424e5a646b6c6c6c6c6c6c6c6c6c6a63594e43382e23180d03000000000000000000000000000007111c27323c47525d666c6c6c6c6c6c6c6c6c6c6960564a3e3225190c00111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6a69676563605d5955504b453f38312a221a1209000000000000000000000013202c3946535f6c798693887b6f6255484848484848484848484848484848484848484848484848484848484848484848484848484f5c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000b1824313d4a5763707d8a96a3b0a99d9083766a5d5044372a1d110000000000000a15202b353f49535c656e767e858b91979ca1a6aaaeaca9a6a29f9c999794918e8b8885827f7c7874706c67625d57524c453e362f261e150c0200000000000013202c3946535f6c798693a0acafa3999190909090909090909090909090909090909090909090909090909090909090909199a3afada09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000050e161e262d353c42494f545a5f63686c6f727577797b7c7d7e7e7e7e7e7d7c7a797674716d6a66615c57514c453f38312a221a120a01000000000000000000000000000000000000000004070a0c0d0e0f1010100f0e0c0a0704000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002070b0d0e0e0e0e0e0e0e0e0e0d0b08030000000000000000000000000000000000000000000000000103050708080909080706050300000000000000000000000000000001020303030202000000000000000000000000000915212d3a46525e6a75818d98a2ada89e948b847d787573737375777a7d82888e95988e847a74818d99a6afa3988c827873717173746b6054473b2e2115080013202c3946535f6c798693a0a2a194887b6e6154483b2e211508000000000000000007111c27323c47525d68727d88939ea2a2a2a2a2a09386796d6053463a2d201307000e1a27333f4c5864707d8995a2a2988c8073675b4e42362a1d110500000000000000000000000000000000000006111c27313c464f58616971787f858a8f9296999b9d9fa0a1a2a1a0a0a0a0a09f9f9f9e9e9fa5aeb2a6998c7f7265594c3f3226190c0000000000000000000013202c3946535f6c798693a0acaca09386796c5f53463f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3e3a342c241a100500000000000000000000070c11141515151515151515151514110d08010000000000000000000000000e1a26323d48525a5f5f5f5f5f5f5f5f5f5f5e5951473c32271c1107000000000000000000000000000000000b15202b36404b545c5f5f5f5f5f5f5f5f5f5f5d574e44392d221609000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5e5c5b595654504d49443f3a342d272018100800000000000000000000000013202c3946535f6c798693887b6f625555555555555555555555555555555555555555555555555555555555555555555555555555555c697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000d1a26333f4c5865727e8b98a4b1a89b8f8275695c4f4336291c10000000000005101c27323c47515b656e7780888f969da3a8adada8a4a09d999693908d8a8785827e7c7976736f6c6864605b57524c46403a332c251d140c030000000000000013202c3946535f6c798693a0acb5aba29d9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9da2abb5ada09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000000060e17202830383f464d545a60656b6f74787b7e82848688898a8b8b8c8b8b8a89878583817d7a76726d68635d57504a433b342c241c130a010000000000000000000000000000000000040a101316181a1b1c1c1c1c1c1b191714100c070200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080e13171a1a1a1a1a1a1a1a1a1a1a18140f09010000000000000000000000000000000000000003070a0d10121314151515151413110f0d0a0602000000000000000206090c0e0f1010100f0e0d0b09070400000000000000000c1824313d4956626e7a86929ea9aca1968c8279726c69676667686a6d71767c838a92968c8177838f9ca9ac9f93877b706764656767625a4f43382b1f13060013202c3946535f6c798693a0aca194887b6e6154483b2e21150800000000000000030d18232e38434e59646e79848f9aa4aeaeaeaeada09386796d6053463a2d201307000b1723303c4854616d7986929ea89c8f83776a5e5246392d211408000000000000000000000000000000000000000b15202a343d464f585f676e74797e83868a8c8f919293949596969696969797979898989aa0aab2a6998c7f7265594c3f3226190c0000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346393232323232323232323232323232323232323232323232323232323232312e29221a1208000000000000000000020b12181d2022222222222222222222211d19130c0400000000000000000000000a15212c3640484f52535353535353535353524e473f352b20150a0000000000000000000000000000000000040f19242f39424a5053535353535353535353514c453c32281d1105000a16212c3740484f525353535353535353535353535353535353535353535353535353535353535251504e4c4a4744413d38332e28221c150e060000000000000000000000000013202c3946535f6c798693887b6f6262626262626262626262626262626262626262626262626262626262626262626262626262626262697683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000003101c2935424e5b6774818d99a6b3a69a8d8174675b4e4135281b0f00000000000a16212d38434e59636d77818a929aa1a8aeaca6a19c9894908d8a8784817e7b7875726f6c696663605c5854504b46413b352f29221a130b02000000000000000013202c3946535f6c798693a0acb9b4adaaa9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9aaadb4b9ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000050e182029323a424951585f656b71767b8084888b8e91939496979898989898979594928f8d8a86827d79746e68625b544d463e362e251c130a01000000000000000000000000000000070f161b20232527282929292929272523201c18130e0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a12191f23262727272727272727272624201a130b0300000000000000000000000000000000050a0f13171a1c1e202122222222211f1e1c1916130e0a0500000004090e1216181b1c1c1c1c1c1b1a181613100c070000000000000e1b2734404d5965727e8a97a3aea79b90857a7067615c5a595a5b5e61666b717880889193887d84919eaaa99c9083776b5f57585a5b5750483d32271b0f030013202c3946535f6c798693a0aca194887b6e6154483b2e2115080000000000000009141f2a343f4a55606a75808b96a0abb1b0b3b8ada09386796d6053463a2d201307000714202c3845515d6a76828f9ba79f93877a6e6155493d3024180b00000000000000000000000000000000000000030e18222b343d464e555c62686d72767a7d808284868788888989898a8a8a8a8a8b8b8b8e98a4b0a6998c7f7265594c3f3226190c0000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2626262626262626262626262626262626262626262626262626262624221d171008000000000000000000020c141c23292d2f2f2f2f2f2f2f2f2f2f2d2a241e160d0400000000000000000000040f1a242e363d434646464646464646464645423d352d23190e0400000000000000000000000000000000000008121d2730383f444646464646464646464645413b332a21160b000005101a252e373e434646464646464646464646464646464646464646464646464646464646464645444342403d3b3834302c28231d17110a03000000000000000000000000000013202c3946535f6c798693887b6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f7683908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000007131f2c3844515d6a76838f9ca8b1a4988b7e7265594c4033261a0d00000000030f1b27323e4955606a758089939ca4acafa8a19b95908c8884817d7a7774716e6c696663605d5a5753504c48443f3a35302a241e1710090100000000000000000013202c3946535f6c798693a0acb6ada5a09f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa0a5adb6ada09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000040e17202a323b444c545b626970767c82878c9094979a9d9fa1a3a4a4a5a5a5a4a3a2a09e9c9996928e8a857f79736d665f58504840372e251c1309000000000000000000000000000007101920272c2f313335353636363534322f2c28241f19130d0600000000000000000000000000000000000000000000000000000000000000000000000000000000000a131c242a2f3334343434343434343433302b251d150b0100000000000000000000000000040b11161b1f2326292b2d2e2f2f2f2e2d2c2a2825221f1b16110b06090f151a1e222527292929292928262422201c18120b0300000000101d2936424f5b6875818e9aa6afa3978b7f73685e56504d4d4d4f51555a60666e767f88928f8486929faba79a8e8174685b4f4b4e4e4b463f362c21160a000013202c3946535f6c798693a0aca194887b6e6154483b2e21150800000000000005101b26303b46515c66717c87929ca7aaa5a4a7adada09386796d6053463a2d2013070004101d2935414e5a66737f8b98a4a2968a7d7165594c4034271b0f02000000000000000000000000000000000000030d161e252b343c434b51575d62666a6e71737577797a7b7b7c7c7d7d7d7d7d7d7e7e7e8895a2afa6998c7f7265594c3f3226190c0000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201919191919191919191919191919191919191919191919191919191815110c06000000000000000000000a141e262e34393b3c3c3c3c3c3c3c3c3b39352f281f160c010000000000000000000008121c242c3236393939393939393939393936312b231b110700000000000000000000000000000000000000010b151e272e3337393939393939393939393835302921180f0400000009131c252c3237393939393939393939393939393939393939393939393939393939393939393938363533312e2b2824201c17120c060000000000000000000000000000000013202c3946535f6c798693887b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b83908c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000010c1824303c4854606d7985929eabaea295897c7063574a3e3124180b000000000714202c37434f5a66717c87919ba5aeada59d968f8a84807c7874716e6b6865625f5c595653514e4a4744403c38332e29241e19130c05000000000000000000000013202c3946535f6c798693a0acb0a59b949292929292929292929292929292929292929292929292929292929292929292949ba5b0ada09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000020c162029323c444d565e656d747b82888d93989ca0a4a7aaa8a5a3a2a1a1a0a1a1a2a4a6a8a8a5a29e9a95908b857e787169625a524940372e251b1208000000000000000000000000040f19222b32383c3e40414243434342413f3c3834302a251e17100901000000000000000000000000000000000000000000000000000000000000000000000000000007121c252e353b3f414141414141414141403c372f271d1309000000000000000000000000080f161c22272b2f333538393b3b3c3c3b3a393735322f2b26221d1711131a20262b2e313435363636353433312f2c28231d150d03000000111e2b3744515d6a7783909da9aca093877a6e62574c444140404245494e555c646d76808a948f8f97a2aea6998c807366594d4041413f3b342d241a0f05000013202c3946535f6c798693a0aca194887b6e6154483b2e2115080000000000010c17222c37424d58626d78838e98a3aaa099979ba4ada09386796d6053463a2d20130700000d1925323e4a57636f7c8894a1a6998d8174685c5043372b1e12060000000000000000000000000000000000000b151f282f363a3d3e40464c51565a5e616467696b6c6d6e6f6f6f70707070717171717b8895a2afa6998c7f7265594c3f3226190c0000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0b0905010000000000000000000006111c26303840454848484848484848484846413a31281e130800000000000000000000000a121a21262a2c2c2c2c2c2c2c2c2c2c2c2a2620191109000000000000000000000000000000000000000000030c151c23282b2c2c2c2c2c2c2c2c2c2c2c29241f170f0600000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b2a282724221f1c1814100b0601000000000000000000000000000000000013202c3946535f6c7986938c88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888889928c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000007121d2834404c5864707c8995a1aeab9f93867a6d6154483b2f221609000000000b1724303c4854606b77828e98a3adada49b938b847e78746f6c6865615e5b585553504d4a4744413e3b3734302c27231e1a181614110f0d0a06010000000000000013202c3946535f6c798693a0acada0948986868686868686868686868686868686868686868686868686868686868686868994a0adada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000a141e28323b444e565f6770777f868d93999ea3a8aaa6a29e9b99979594949494949697999b9ea2a6aaa6a19c969089827b746c645b524940372d241a100600000000000000000000000b16212b343d43484b4d4e4f4f4f4f4f4d4b4845403b363029221b130b02000000000000000000000000000000000000000000000000000000000000000000000000010d18232e3740474c4d4d4d4d4d4d4d4d4d4c4841392f251a0f03000000000000000000020a121a21272d32373b3f4244464748484848474544413e3b37322d28221c1e252c31363b3e404243434342413f3e3b38342e271f150b010000121f2c3945525f6b7885929eabaa9e9184786b5f52463a34333436393d434a525b646d78828d989ba0a9b2a6998c7f7265594c3f3435332f2a231b120800000013202c3946535f6c798693a0aca194887b6e6154483b2e211508000000000008131e28333e49545e69747f8a949faaa3988e8a929eaaa09386796d6053463a2d20130700000a16222e3b4753606c7885919da99d9084786b5f53473a2e221509000000000000000000000000000000000006121d27313a41474a4b4c4d4e4f50525355585a5c5e5f6161626363636363636464646f7b8895a2afa6998c7f7265594c3f3226190c0000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0b080400000000000000000b17222d38424a5155555555555555555555524c433a2f24190d0100000000000000000000000810161a1e1f2020202020202020201f1d1a150f070000000000000000000000000000000000000000000000030a11171b1e202020202020202020201f1d19130d06000000000000010910161a1e1f2020202020202020202020202020202020202020202020202020202020201f1e1d1c1a181513100c0804000000000000000000000000000000000000000013202c3946535f6c7986939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393938c7e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000040e18232e3945515c6874808c98a5b1a89c9083776a5e5245392c201307000000010e1b2733404c5864707c88949faab0a59b92898179736d68635f5c5855524f4c494643413e3b3835322f2b282a2c2c2b29272422201e1c1916120c0600000000000013202c3946535f6c798693a0acaca0938679797979797979797979797979797979797979797979797979797979797979798693a0acada09386796d6053463a2d201307000000000000000000000000000000000000000000000000000007111c26303a444d5660687179828991979ea4aaa9a39e9a95928f8c8a898887878788898a8d8f92969a9ea4a9a7a19b948d867e756d645b52493f362c22170d0200000000000000000004101c27323d464e5457595b5c5c5c5c5b5a5854514c47413b342c251d140b02000000000000000000000000000000000000000000000000000000000000000000000006121e2a35404952585a5a5a5a5a5a5a5a5a58534b41372b2014080000000000000000020b141c242b32383e43474b4e515354555555555452504e4b47433e39332d262830373d42474a4d4f4f4f4f4f4e4c4a4845403931271d1207000013202c3946535f6c7986929facaa9d9083766a5d5044372a2627292d32394049525c66707b86929da9b2b2a6998c7f7265594c3f322826231e1811090000000013202c3946535f6c798693a0aca194887b6e6154483b2e21150800000000040f1a242f3a45505a65707b86909ba6a79c9287828f9ca8a09386796d6053463a2d201307000006121f2b3744505c6975818d9aa6a094877b6f62564a3e3125190c00000000000000000000000000000000000b17232e39434c525657595a5b5c5d5e5f5e59515051535455555656565657575757626f7b8895a2afa5998c7f7265594c3f3226190c0000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a191814100a030000000000000f1b27333f4a545c616262626262626262625d564c41352a1d1105000000000000000000000000040a0e111313131313131313131313110e09040000000000000000000000000000000000000000000000000000060b0f121313131313131313131312100d0802000000000000000000050a0e11131313131313131313131313131313131313131313131313131313131313131212100f0d0b090603000000000000000000000000000000000000000000000013202c3946535f6c798686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686867e7265584c3f3225190c0013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000050d16202a35404b56616d7985919da9b0a4988c8073675b4f4236291d110400000004111d2a36434f5c6874818d99a4b0a99e938980776f68615c5753504c494642403d3a3734312e2b2825232b31363939383533312f2d2a2826231e171008000000000013202c3946535f6c798693a0acaca09386796c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c798693a0acada09386796d6053463a2d20130700000000000000000000000000000000000000000000000000030e19232e38424c565f68727a838b939ba2a9aba49e98928e898582807d7c7b7a7a7a7b7c7e8083868a8e93989ea4aba69f9790887f766d645b51483e33291f140a0000000000000000000814202d38444f586064666768696969686664615d58524c453e372f261d140b02000000000000000000000000000000000000000000000000000000000000000000000916222e3a46515b63676767676767676767645d53483c3024180b00000000000000020b141d262e363d444a4f54585b5d5f6161626261605f5d5a57534f4a443f3831313a41484e5357595b5c5c5c5b5a595754514b43392f24180d010013202c3946535f6c798693a0acaa9d908376695d5043362a1d1a1d21272e37404a545f6a75818c98a3afb2a6998c7f7265594c3f32261a17130d06000000000013202c3946535f6c798693a0aca194887b6e6154483b2e211508000000000b16202b36414c56616c77828c97a2aba0968b8083909ca9a09386796d6053463a2d2013070000030f1b2834404d5965717e8a96a3a3978b7e7266594d4135281c1003000000000000000000000000000000030f1c28343f4b555d6364656667696a6b6c6b63594e454647484949494a4a4a4a4a56636f7c8996a2afa5988c7e7265584c3f3225190c0000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2626262626262626262626262626262626262626262626262626262626262624201b150d050000000000121e2b3743505b666d6f6f6f6f6f6f6f6f6e685d5246392d2114070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6b76797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797064584b3e3225180c0013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000040910171f28323c46515c67727e8a95a1adaca094887c7064574b3f33261a0e0100000006131f2c3945525e6b7784909ca9b0a4988d82776e655d56504b4743403c393633302d2b2825221f1c222c353c4245464442403e3b393735322e29221a11070000000013202c3946535f6c798693a0acaca09386796c5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000000000000000000000000000a15202a353f4a545e68717a848d959da5ada8a19a938d87827d797673716f6e6d6d6d6e6f717376797d82878d939aa1a8a9a299918980766d63594f453b30261b100500000000000000000a1723303c4955606a707274757676767573706d69635e57504941382f261d140a010000000000000000000000000000000000000000000000000000000000000000000b1824313e4a57636d7474747474747474746f64584c4033261a0d000000000000000a141d262f3840484f555b5f64676a6c6d6e6f6f6e6d6b6966635f5b56504a433b3a434c53595f63666869696968676563615c554b4035291d11050013202c3946535f6c7986929facaa9d9084776a5d5144382b1f1a18161c252e38424d58646f7b87939fabb2a6998c7f7265594c3f3226190c070200000000000013202c3946535f6c798693a0aca194887b6e6154483b2e21150800000007121c27323d48525d68737e88939ea9a49a8f847984909daaa09386796d6053463a2d2013070000000c1824313d4956626e7a87939fa79a8e8275695d5044382c1f130700000000000000000000000000000005121e2b3844505c676f7172737475777879756a5e5145393a3b3c3c3c3d3d3d3e4b5864717d8a97a4b0a4988b7e7165584b3e3225180b0000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346393333333333333333333333333333333333333333333333333333333333333333302c261f170e040000000013202c3946525f6c787b7b7b7b7b7b7b7b7a6e6255483b2f2215080000000000000000000000000000000000000000000000000000000000000000000000000000000000030608080808080808080808070501000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306080b0d0f101112131313131212100f0d0b09070400000000000000000000000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c685f54483c3023170a0013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000010205070b0f141b2129313a444e58636e78848f9ba6b2a79b8f83776b5f53473b2f23170a000000000814212e3a4754606d7a86939facaca093877b70655c534c45403b3734302d2a2724211e1b1815131f2a343e474e5253514f4c4a484644413f3a342c23190f0400000013202c3946535f6c798693a0acaca09386796c5f53525252525252525252525252525252525252525252525252535f6c798693a0acada09386796d6053463a2d20130700000000000000000000000000000000000000000000000005101b26313c47515b66707a838d969fa7afa79e968f88817b76716d6966646261616161626365676a6d71767b82888f969ea7aba39b92897f756b61574d42382d22170c01000000000000000b1825323e4b5864717c7f818282838382807d79746f69625a534a42392f261c13080000000000000000000000000000000000000000000000000000000000000000000c1925323f4c5865727e818181818181818174675a4d4134271a0e01000000000007111c262f39424a525960666b707376797a7b7b7b7b7a7876736f6b66615b544d46434d555e656a6f7275767676757472706d675d5145392d20140700121f2c3845525e6b7884919eaaab9e9285796c6053473b312b272423222126313c47535f6b77838f9ca8b2a6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e2115080000030e18232e39444e59646f7a848f9aa5a89e93887d7784919eaba09386796d6053463a2d2013070000000815212d3a46525e6b7783909ca89e9285796c6054483b2f23160a0000000000000000000000000000000613202c3946535f6c787d7e808182838486796c6053473b302f2f3030303036424e5a6773808c99a5afa396897d7063574a3d3124170b0000000000000000000013202c3946535f6c798693a0acaca09386796c5f534640404040404040404040404040404040404040404040404040404040404040403f3d38312920160b0000000013202c3946535f6c7986888888888888887b6f6255483c2f221509000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f121415151515151515151514110d0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004080c0f1215171a1b1d1e1f1f20201f1f1e1d1c1a181613100d0905010000000000000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5d564d42372c2014070013202c3946535f6c798693a0acaca09386796c5f5346392c20130b0b0b0c0c0e0f1114171b20262c333b434d56606a747f8a95a0acada1968a7e73675b4f43372b1f1307000000000915222f3c4855626e7b8895a1aea99c9084776b5f544a413a342f2b2724211d1a1714120f0c0c1824303b4650595e5f5d5b59575452504e4b453e352b20150a00000013202c3946535f6c798693a0acaca09386796c5f53464646464646464646464646464646464646464646464646535f6c798693a0acada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000b16212d38434d58636d77828c959fa8afa69d958c857d76706a65615d5a5856555454545556585a5d61656a70767d858c959da6ada49b91877d73695e54493e33281d1207000000000000000b1825323e4b5865717e8b8d8f8f908f8e8c8985807a736c645c544b41382e241a100600000000000000000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c8e8e8e8e8e8e8174675a4d4134271a0e0100000000030e19232d38414b545c646b71777c80838587888888888685827f7b77726c665f58504b555f676f767b7f8183838382817e7c796e6155483b2f22150800111e2a3744505d6976838f9ca8ada194887c6f63584d433c3633312f2e2e2d2d37424e5b6773808c99a5b2a6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e21150800000a141f2a35404a55606b75818b96a1aca2978c81767885929eaba09386796d6053463a2d20130700000005111e2a36424f5b6774808c99a5a195897c7064574b3f32261a0d01000000000000000000000000000006121f2c3845525e6b77848b8d8e8f9091887c6f63574c413c39373737383a3f47525e6a76828f9ba8ada094877b6e6255483c2f2316090000000000000000000013202c3946535f6c798693a0acaca09386796c5f534d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4c49433b32271d120600000013202c3946535f6c7986939595959595887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000000000000000000000000000080f161b1f21222222222222222222201e19130d050000000000000000000000000000000000000000000000000000000000000000000000000000000001060b1014181b1f212426282a2b2c2c2c2c2c2c2b2a282725221f1c1915110d0803000000000000000000000000000000000000000a16212c3740484f5253535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353514b443b31261b0f030013202c3946535f6c798693a0acaca09386796c5f5346392c201818181819191a1c1e2023272c31373e454d565f68727c86919ca6b1a69b9085796e62564a3f33271b0f03000000000916222f3c4955626f7c8996a2afa79b8e8175685b4f43382f29231f1b1814110e0b08050205101c2834404c58626a6c6a686563615f5d5a5750473c32261a0e02000013202c3946535f6c798693a0acaca09386796c5f53463939393939393939393939393939393939393939393946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000000000000000000000005111c27333e49545f6a747f89949ea7b1a79d948b837a736c655f5a55514e4b4948474747484a4b4e51555a5f656b737a838b949da7ada3998f857b70655b50453a2e23180c010000000000000b1825323e4b5865717e8b989b9c9c9c9b9995918b857e766e665d534a40362c22180d02000000000000000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c989a9a9a9a8e8174675a4d4134271a0e01000000000915202a353f49535d666e767d83888c8f92949595959493918f8b88837d7771696259525d67717981878b8e8f908f8e8d8b887b6f6255483c2f221509000f1c2835424e5b6774808c99a5b0a4988c8074695f554d4743403e3c3b3a3a3a3a3f4b5864717d8a97a3b0a6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e2115080006101b26313c46515c67727c87929da8a59b90857a707986929faca09386796d6053463a2d201307000000020e1a27333f4b5864707d8995a2a4988c8073675b4e4236291d1104000000000000000000000000000004111d2a36434f5c6874818d999a9c9d988c8074685d534c484644444444464a5059646f7a86929faba99d9185786c5f53463a2d2114080000000000000000000013202c3946535f6c798693a0acaca09386796c5f5959595959595959595959595959595959595959595959595959595959595959595959544d43392e23170b00000013202c3946535f6c798693a0a2a2a295887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000000000000000000000000009121a21272b2e2e2e2e2e2e2e2e2e2e2d2a251e170e050000000000000000000000000000000000000000000000000000000000000000000000000001070c12171c2024282b2e313335363738393939393838363533312f2c2925211d18140e0903000000000000000000000000000000000005101a252e373e43464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464644403a32291f140a000013202c3946535f6c798693a0acaca09386796c5f5346392c2525252525252627282a2d3033383d42484f575f68717a848e98a2adaaa0958a7f73685d51453a2e22160b00000000000916222f3c4955626f7c8996a2afa79a8e8174675a4d4134271e17130f0b08070708080a0d1117212d3844505c697479767472706e6b696762594e43372b1e1205000013202c3946535f6c798693a0acaca09386796c5f5346392c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c3946535f6c798693a0acada09386796d6053463a2d20130700000000000000000000000000000000000000000000000a16222d38444f5a66717b86919ba5b0a99f958b82797169615a544e4945413e3d3b3a3a3b3b3d3f4245494e545a61687179828b959fa9aba1978c82776c61564b4034291d12060000000000000b1825323e4b5865717e8b98a1a1a2a4a7a5a19c97908880786f655c52483e34291f1409000000000000000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5a7a79a8e8174675a4d4134271a0e01000000040f1b26313c47515b656f7880878e94989c9ea0a1a2a2a1a09e9b98948f89827b746b6259636e79838b92979b9c9c9c9b9a95887b6f6255483c2f221509000d1a26333f4b5864707c8995a1aca89c91867b71675f58534f4c4a494847474646464956626f7c8996a2afa6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e211508020c17222d38424d58636e78838e99a4aa9f94897e746d798693a0aca09386796d6053463a2d201307000000000b17232f3c4854616d7986929ea89b8f83766a5e5245392d2014080000000000000000000000000000010e1b2733404c5965717d8995a1a8a89c90857a6f655d5854525150505153565b626b75808c97a3afa5998d8175695c5044372b1e12050000000000000000000013202c3946535f6c798693a0acaca09386796c6666666666666666666666666666666666666666666666666666666666666666666666655f554b3f33271b0e02000013202c3946535f6c798693a0acafa295887b6f6255483c2f22150900000000000000000000000000000000000000000000000000000000000000000000000007111b242c32373a3b3b3b3b3b3b3b3b3b3936302920170d030000000000000000000000000000000000000000000000000000000000000000000000050c12181d23272c3034373a3d3f414344454646464645444342403e3b3835312d29241f1a140e08010000000000000000000000000000000009131c252c3237393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393938342f2820170d03000013202c3946535f6c798693a0acaca09386796c5f5346393232323232323233343537393c3f44484e535a6169717a838c96a0aaada3998e83786d62574c4035291d120600000000000916222f3c4955626f7b8895a2aea79a8e8174685b4e423529221d191715141414141517191d2229333e4955606c788583817e7c7a7876736a5f53463a2d211407000013202c3946535f6c798693a0acaca09386796c5f5346392c201f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f202c3946535f6c798693a0acada09386796d6053463a2d20130700000000000000000000000000000000000000000000040f1b27323e4a55606c77828d98a3adaca1978d837970675f574f48423d393532302f2e2e2e2f303235393d42484f575f677079838d97a2aca99e94897e73675c51453a2e23170b0000000000000b1825323e4b5865717e8b95949495989b9fa5a8a19a928a81776e645a50463b30261b10050000000000000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000000915202c37424d58636d77818a92999fa4a8a5a09d9b9999999a9c9e9f9a948d867d756b626974808b959da3a7a69f9b989795887b6f6255483c2f221509000a1723303c4854606c7884909ba6aea2978d8379716a635f5b5957555554535353535255626f7b8895a2afa6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e21150808131e29343e49545f69747f8a95a0aaa3988d82776d6d7a8794a0ada09386796d6053463a2d201307000000000714202c3845515d6a76828f9ba79f92867a6d6155493c3024170b0000000000000000000000000000000b1824303d4955616d7985909ba7ada1968b81776f6964615f5e5d5d5e5f62676d747d87929da8aba094897d7165594d4034281b0f030000000000000000000013202c3946535f6c798693a0acaca093867973737373737373737373737373737373737373737373737373737373737373737373737371675c4f43362a1d1104000013202c3946535f6c798693a0acafa295887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000000000000000000000020d18232d363d434748484848484848484846413b32291f1409000000000000000000000000000000000000000000000000000000000000000000020910171d23292e33383c404447494c4e505152525353525251504e4c4a4845413d3935302b251f19130c05000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b28241d160e0500000013202c3946535f6c798693a0acaca09386796c5f53463e3e3e3e3e3e3e3f3f40424346484c4f54595f656c737b838c959ea8afa59b91877c72675c51463a2f24180d0100000000000815212e3b4854616e7a8794a0ada99c8f83766a5d51463b332d2926242221212021222326292d333b454f5a65717d89908d8b898785827a6e6154483b2e211508000013202c3946535f6c798693a0acaca09386796c5f5346392c2013131313131313131313131313131313202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000000000000000000000814202c38434f5b66727d88939fa9afa59a8f857b71675e554d453e37312d29252322212121222426292d32373e454d555e67717b85909ba5b0a59a8f84796d62564b3f33281c100400000000000b1825323e4b5865717e89888888898b8f949aa0a8a49c938a80766c62574d42372c21160b0000000000000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000010d1925313d48545f6a757f89939ca4aaa7a09994918e8c8c8c8e8f9295999e978f877e746b6d7985919ca7afa59c948f8b8a8a887b6f6255483c2f221509000714202c3844505c68737e8a959fa9a99f958c837b756f6b6865636261616060605f5f5f626f7b8895a2afa6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e2115080f1a25303a45505b65707b86919ca6a79c91867b71666e7b8794a1ada09386796d6053463a2d2013070000000004101c2935414e5a66737f8b98a4a2968a7d7164584c4033271b0e0200000000000000000000000000000814202c3945505c68737f8a959fa9a89d938a817a74706d6b6a6a6a6a6c6f72787e868f99a3aea4998e83786c6054483c3024180c000000000000000000000013202c3946535f6c798693a0acaca0938680808080808080808080808080808080808080808080808080808080808080808080808080776b5e5144382b1e1105000013202c3946535f6c798693a0acaca295887b6f6255483c2f221509000000000000000000000000000000000000000000000000000000000000000000000007131e2a353f484f53555555555555555555524c443b31261a0e0300000000000000000000000000000000000000000000000000000000000000040c131b22282e343a3f44484c505356585a5c5e5f5f5f5f5f5f5e5d5b595754514d4a45413c36312b241d160f07000000000000000000000000000000010910161a1e1f202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201f1c18120c040000000013202c3946535f6c798693a0acaca09386796c5f534b4b4b4b4b4b4b4b4c4c4d4e505255585c60656a70767d858d959ea7afa69d938980756b60554a3f34291e13070000000000000713202d3946525f6c7885919eaaab9e92867a6e62574d453e393532302f2e2d2d2e2f303235393e454d57616c77828e999a9896938f83776a5e5246392d201407000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000000000000000000000d1925303c4854606b77838e9aa5b0a99e93887e73695f554c433b332c26211c1917151414141517191d21262c333b434c555f69747e89949faaaca1958a7e73675c5044382c21150900000000000b1825323e4b5865717d7c7b7b7b7c7f83888f969ea6a59c92887e73695e53493e32271c110500000000000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e01000005111e2a36424d5965707b86919ba5aea69d958e898481808080818386898e93999990867c73717d8a96a2aea99e938a837e7d7d807b6f6255483c2f2215090004101c28343f4b57626d78838d97a1a9a79e958d86807b777472706f6e6d6d6d6d6c6c6c6b6f7b8895a2afa6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e21150b16212c36414c57616c77828d98a2aba0958a80756a616e7b8895a1ada09386796d6053463a2d20130700000000000d1925323e4a57636f7b8894a0a5998d8174685c4f43372a1e1205000000000000000000000000000004101c2834404b57626e78838e98a1aaa59c938b85817d7a7877767777797b7e83899098a1aba59c92887d72665b5044382c201408000000000000000000000013202c3946535f6c798693a0acaea2978e8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d84776b5e5144382b1e1105000013202c3946535f6c798693a0a0a0a095887b6f6255483c2f22150900000000000000000000000000000000000000000000000000000000000000000000000b17232f3b465159606161616161616161615e564d42372b1f1306000000000000000000000000000000000000000000000000000000000000060e161e252c333a40454b5054585c5f626567696a6b6c6c6c6c6b6a69686663605d5a56514c47423c362f282119110901000000000000000000000000000000050a0e11131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131312100c0701000000000013202c3946535f6c798693a0acaca09386796c5f58585858585858585858595a5b5d5f6164686c70757b81888f979fa7aea69d948b81776d63594e44392e23180d0100000000000005111e2b3744505d6975828e9aa6aea2968a7f74695f574f4a45423f3d3b3b3a3a3a3b3d3f41454a50575f69737d88939fa7a4a2968a7e72665a4e42362a1e1105000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d20130700000000000000000000000000000000000000000004111d2935414d5965707c88949fabafa3988d82766c61574d433a3129211b15100d0a08080708090a0d10151b2129313a434d57626c77838e99a4b0a69b8f84786c6155493d3125190d00000000000a1724303d4955616b71706f6e6e6f73777d848c949da6a49a90857b70655a4f44392d22160b00000000000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e0100000915212e3a46525e6a76818d98a3ada89e948b837d78757373737476797d82878d94988f857a74818d9aa6afa3978c817872707173736b6054473b2e21150800000b17232f3a45515c67717b858f979fa6a79f98918c8784817e7d7c7b7a7a797979797978787b8895a2afa6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e2115121d27323d48535d68737e89949ea9a4998e84796e63626f7b8895a2ada09386796d6053463a2d20130700000000000916222e3b4753606c7885919da99c9084776b5f53463a2e2115090000000000000000000000000000000c18232f3a46515c67717c868f98a0a7a59d96918c8987858483838485878b8f949ba2aaa49c938a80766b60554a3f33271c1004000000000000000000000013202c3946535f6c798693a0acb3a9a09a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9184776b5e5144382b1e1105000013202c3946535f6c7986939393939393887b6f6255483c2f22150900000000000000000000000000000000000000000000000000000000000000000000000e1a2733404c57626b6e6e6e6e6e6e6e6e6e685e53473b2f2215090000000000000000000000000000000000000000000000000000000000060f18202830373e454b51565c6064686c6f7274757778797979797877767472706d6a66625d58534d47413a332b231b130a0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c6565656565656565656565656668696b6e7174787c81878d939aa1a9aca49c948b82786f655b51473d32271d120700000000000000020f1c2834414d5966727e8a96a1ada79b90857b7169615b55514e4b4a484747474748494b4e51555b6169717b858f9aa5b0a89c91857a6e62564a3e32261a0e02000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d2013070000000000000000000000000000000000000000000814212d3945515d6975818d99a4b0a99e92877b70655a50453b31281f17100904000000000000000001040910171f28313b46505b66717c88949fabaca095897d7165594d4135291d1004000000000815212d39444f5961646362616163666c727a828b949ea8a1978c82766b60554a3e33281c1105000000000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e0100000c1825313d4a56626e7a86929ea9aca1968c8279726c68666666686a6d71767c838a92968c8277838f9ca9ac9f93877b70666464666762594f43372b1f1306000006121e29343f4a555f69737c858d959ca1a6a39d9893908d8b8a8888878786868686868585858a96a2afa6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e211519232e39444f59646f7a858f9aa5a89d92887d72675c626f7b8895a2ada09386796d6053463a2d201307000000000006121f2b3744505c6875818d9aa6a094877b6e62564a3d3125180c00000000000000000000000000000007121e2935404b55606a737d868e959ca2a7a29d99959392919090919294979ba0a5a6a09a928a81786e645a4f44392d22170b00000000000000000000000013202c3946535f6c798693a0acacacaba7a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a69e9184776b5e5144382b1e1105000013202c3946535f6c7986868686868686867b6f6255483c2f22150900000000000000000000000000000000000000000000000000000000000000000000000f1c2835424e5b68747b7b7b7b7b7b7b7b7a6f63564a3d3024170a00000000000000000000000000000000000000000000000000000000060f18212a323a41494f565c62676c7175787b7e8182848586868686858483817e7c7976726e69645e58524b443d352d251c130a01000000000000000000000000000000000000000000000000000000000000000000000306080808080808080808080603000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca093867971717171717171717171717272737476787a7d8184888d92989ea4aba8a19a928a827970665d534a3f352b20160b0000000000000000000c1925313d4956626d7985909ba6ada2978d837a736c66615d5a585655545353545556585a5d61666c737b838d96a1abaca1968b8074695d51463a2e22160a00000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d2013070000000000000000000000000000000000000000000c1824303d4955616d7986929da9b0a4988d81756a5f54493e33291f160d0500000000000000000000000000050d161f29343f4a55606b77838e9aa6b1a5998e8275695d5145392d2014080000000005111c28333e474f555756555555565b61687079828c96a0a99e93887d72665b4f44392d22160a000000000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e0100000e1b2734404d5965727e8a97a3afa79b90857a7067605c5a59595b5d61656b717880889193897d84919eaaa99c9083776b5e57585a5a5750473d32271b0f030000010c18232e39434d57616a737b838a90969b9fa2a3a09c9a9896959494949393939292929291939ca6b2a6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e21151f2a35404b55606b76818b96a1aca1968b81766b6055626f7b8895a2ada09386796d6053463a2d2013070000000000030f1b2834404d5965717e8a96a3a3978b7e7266594d4134281c0f030000000000000000000000000000010d18232e39434e58616b737c838a91969b9fa3a5a2a09e9d9d9d9d9fa0a3a5a29f9a958f8880786f665c52483d32271c110600000000000000000000000013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09e9184776b5e5144382b1e11050000131f2c3946525f6b767979797979797979786d6155483b2f22150800000000000000000000000000000000000000000000000000000000000000000000000f1c2835424f5b687582888888888888887d7063574a3d3024170a000000000000000000000000000000000000000000000000000000050f18212a333c444c535a61676d73787c8185888b8d8f90929293939292918f8d8b8986827e7a756f6a635d564f473f372e251c130a0000000000000000000000000000000000000000000000000000000000000000050b0f1314151515151515151514120f0a0500000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca093867e7e7e7e7e7e7e7e7e7e7e7e7e7f8081838487898d9094999ea3a9aaa49d978f8880786f675e544b41382e23190f040000000000000000000915212d3945515d68747f8a959fa9a99f958c857d77726d6a6765636261606061616364676a6d72777d858d959fa8aea49a90857a6e63584c4135291d110600000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d2013070000000000000000000000000000000000000000020f1b2734404c5965717d8a96a2aeaca094887c7065594e42372c22170d04000000000000000000000000000000040e18222d38434f5b66727e8a96a2aeaa9e9286796d6155493c3024170b00000000000b17212c353d44494b4a4848484a4f565e67707a848f99a4a4998e83776c61554a3e33271b10040000000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000101d2936424f5c6875818e9aa6afa3978b7e73685e55504d4c4d4e51555a5f666e767e88918f8486929faba79a8e8174685b4f4b4d4e4b463e352b21160a0000000006111c27313c464f58616971787f858a8f9296999b9d9fa0a1a2a1a0a0a0a0a09f9f9f9e9e9fa5aeb2a6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e211b26313c47515c67727d88929da8a59a8f857a6f645955626f7b8895a2ada09386796d6053463a2d2013070000000000000c1824313d4955626e7a87939fa69a8e8275695d5044382b1f130600000000000000000000000000000007121d27323c464f59616a727980858a8f9396999b9c9e9e9f9f9f9e9d9b9996938e89847d766e665d544a40362c21160b0000000000000000000000000013202c3946535f6c79869393939393939393939393939393939393939393939393939393939393939393939393939393939393939184776b5e5144382b1e11050000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c665c5145392d20140700000000000000000000000000000000000000000000000000000000000000000000000f1c2835424f5b6875828f95959595958a7d7063574a3d3024170a0000000000000000000000000000000000000000000000000000030d17212a333c454e565d656c72797e84898d919497999b9d9e9fa0a09f9e9d9c9a9895928e8a85817b756e686159514940372e251c12080000000000000000000000000000000000000000000000000000000000000810161b1f212222222222222222211f1b160f08000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaea2968d8b8b8b8b8b8b8b8b8b8b8b8b8c8c8d8e8f919396999ca0a5a9a8a39e98928c857e766e665d554c42392f261c12070000000000000000000005111d2935404c57626d78838d97a0a9a89f968f88837e797673716f6e6d6d6d6d6e6f717376797e83898f979fa8aea69c92887e73685d52473b3024180d0100000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000000000000000005121e2a3743505c6875818d9aa6b2a89c9083776b5f54483c31261b1005000000000000000000000000000000000006111c27323e4a56616d7986929eaaaea296897d7165584c3f33271a0e010000000005101a232c33393c3e3d3c3b3b3e444c555e68727d88929da89f94897d72665b4f43382c2015090000000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000111e2b3844515d6a7784909da9aca093877a6e62574c444040404245494e555c646c758089948f9097a2aea6998c807366594d4041413f3a342c231a0f0400000000000b15202a343d464f585f676e74797e83868a8c8f919293949596969696969797979898989aa0aab2a6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e21222d38434d58636e79848e99a4a99e93897e73685d5355626f7b8895a2ada09386796d6053463a2d2013070000000000000815212d3946525e6b7783909ca89e9185786c6054473b2f22160a000000000000000000000000000000000b16202a343d474f5860676e747a7e83878a8c8e90919292929291908f8c8a86827d78726b645c544b42382e241a0f040000000000000000000000000013202c3946535f6c79868686868686868686868686868686868686868686868686868686868686868686868686868686868686868684776b5e5144382b1e110500000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5b544a4034291d110400000000000000000000000000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca2a2a2978a7d7063574a3d3024170a00000000000000000000000000000000000000000000000000000a151f29333c454e575f676f767d848a8f94999da1a3a6a8a9a7a6a6a6a6a7a9a9a7a4a19e9a96918c868079726b635b524940372e241a10060000000000000000000000000000000000000000000000000000000009121a21272b2e2e2e2e2e2e2e2e2e2e2b27211a12090000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acb3a89f999898989898989898989898989899999a9c9ea0a2a5a9a8a5a19c98938d87817a736c645c544b433a30271e140a0000000000000000000000000c18242f3b46515c67717b858e979fa6a8a19a948e8a8683807e7c7b7a7a7a7a7b7c7d8082868a8e949aa1a9aca59c948a81766c61574c41352a1f13080000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d20130700000000000000000000000000000000000000000814212d3a46535f6b7884919da9b0a4988c8073675b4f43372c201409000000000000000000000000000000000000000a16222d3945515d6976828e9ba7b2a5998d8174685b4f4236291d1004000000000008111a21282d3031312f2e2f333a434c56616b76818c97a3a59a8e83776c6054493d31251a0e0200000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000121f2c3945525f6b7885929eabaa9e9184786b5f52463a34333335383d434a525a646d77828d979ca1a9b2a6998c7f7265594c3f3434332f29221a1108000000000000030e18222b343d464e555c62686d72767a7d808284868788888989898a8a8a8a8a8b8b8b8e98a4b0a6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e2129343f49545f6a75808a95a0aba2978d82776c61574c55626f7b8895a2ada09386796d6053463a2d20130700000000000005111e2a36424f5b6774808c99a5a195887c6f63574b3e3226190d01000000000000000000000000000000040e18222b353d464e555c63696e73777a7d8082838485858685848382807d7a76726d67615a524a423930261c12080000000000000000000000000000131f2c3946525f6b76797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979756a5d5144372b1e110400000a16212c3740484f52535353535353535352504a42382e23180c0000000000000000000000000000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8aea4978a7d7063574a3d3024170a0000000000000000000000000000000000000000000000000007121c27313b454e576069717981888f959ba0a5a9a7a4a09e9c9b9a99999a9a9c9ea0a3a7aaa6a29d97918b847d756d645b524940362c22170d02000000000000000000000000000000000000000000000000000007111b242c33383a3b3b3b3b3b3b3b3b3a37322c241b110700000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acacaca9a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a6a7a9a8a6a4a29f9c9995918c87827c766f69615a524a423931281e150c0200000000000000000000000007131e2935404a555f69737c858d959ca2a8a59f9a96928f8c8a89888787878788898a8c8f92969a9fa5aca8a19a938a81786e655a50453a2f24190e020000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d20130700000000000000000000000000000000000000000a1623303c4955626e7b8794a0acada195887c6f63574b3f33271b0f030000000000000000000000000000000000000005111d2935414d5a66727e8b98a4b0a99c9084776a5e5145382c1f13060000000000000810161c2123242422222228313a444f5a646f7b86919da89f94887c7165594e42362a1f130700000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e01000013202c3946535f6c7986929facaa9d9083766a5d5043372a2627292c32384048525b66707b86919da8b3b2a6998c7f7265594c3f322826231e18100800000000000000030d161e252b343c434b51575d62666a6e71737577797a7b7b7c7c7d7d7d7d7d7d7e7e7e8895a2afa6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e25303b45505b66717b86919ca7a69b91867b70655b504855626f7b8895a2ada09386796d6053463a2d201307000000000000020e1a26333f4b5864707d8995a2a4988c7f73675a4e4235291d100400000000000000000000000000000000061019232b343c444b52575d62676a6e71737576777879797878777573716e6a66615c564f48403830271e140a010000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b63594d4135291c1003000005101a252e373e4346464646464646464646433f3830261c12070000000000000000000000000000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a000000000000000000000000000000000000000000000000030e19232e38434d576069727b838b939aa0a6aba5a09b9794918f8e8d8d8d8d8e8f9194979a9fa4a9a8a39c968f877f766d645b52483e34291f140900000000000000000000000000000000000000000000000000030e19232d363e4447484848484848484847433d362d23190e02000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09f9f9e9d9b9a989593908c8985807b76706b645e575048403830271f160c0300000000000000000000000000020d18232e39434d57616a737b838a91979ca1a6a6a29e9b9997969594949494949597999b9ea2a6a9a6a19c96908981786f665d53483e34291e1308000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d20130700000000000000000000000000000000000000000c1925323e4b5764717d8a96a3afab9e9285796c6054473b2f23160a0000000000000000000000000000000000000000010d1925313e4a56636f7c8895a1aeac9f9386796d6054473b2e22150800000000000000050b10141718171615161f28333d48535e6975818c98a3a5998d82766a5e53473b2f23170c00000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e01000013202c3946535f6c798693a0acaa9d908376695d5043362a1d1a1c21272e364049545f6a75808c98a3afb2a6998c7f7265594c3f32261917120d0600000000000000000b151f282f363a3d3e40464c51565a5e616467696b6c6d6e6f6f6f70707070717171717b8895a2afa6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e2c37414c57626d77828d98a3aa9f958a7f74695f54494855626f7b8895a2ada09386796d6053463a2d201307000000000000000b17232f3c4854616d7986929ea79b8f83766a5e5145392c2014070000000000000000000000000000000000071019222a323940464c52565a5e616466686a6b6b6c6c6b6b6a686764615e5a55504a443d362f261e150c020000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5e5951473c3125190d0000000009131c252c32373939393939393939393937332d261e140b000000000000000000000000000000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000000000009141f2a35404a555f68727b858d959da5aba6a099948f8b8885838181808081818385878a8e93989ea4aba7a099918980766d645a50453b30261b100500000000000000000000000000000000000000000000000008141f2a353f484f545555555555555555534f483f352a1f1307000000000000000000000000000000000000000000000000000013202c3946535f6c79869393939393939393939393939393939393939393929291908f8d8b898683807c78746f6a655f59534c453e362e261e150d0400000000000000000000000000000007121c27313b454e58616971787f868c91959a9da1a3a6a6a4a2a1a1a0a0a1a1a2a3a5a7a5a3a09d9a95918b857e776f665d544b41372c22170c01000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d20130700000000000000000000000000000000000000000e1a2734404d596673808c99a5b2a89c8f83766a5d5144382b1f13060000000000000000000000000000000000000000000916222e3b4754606d7986939facaea195887c6f6256493d3023170a00000000000000000004080a0b0b09080d16212c37424d58646f7b87939eaa9e92877b6f63574c4034281c1004000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e01000013202c3946535f6c7986929facaa9d9084776a5e5144382b201b18161c242e38424d58646f7b87939fabb2a6998c7f7265594c3f3226190c0601000000000000000006121d27313a41474a4b4c4d4e4f50525355585a5c5e5f6161626363636363636464646f7b8895a2afa6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e333d48535e69737e89949fa9a3998e83786d63584d424855626f7b8895a2ada09386796d6053463a2d201307000000000000000713202c3845515d6a76828f9ba79f9286796d6155483c3023170b00000000000000000000000000000000000007101820272e353b41464a525d666a6b6b6b6b68605f5f5e5d5c5a5855524e4a453f39332c241d140c03000000000000000000000000000000000a16212c3740484f52535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353524e473f352b20140900000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2b27221c140c02000000000000000000000000000000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a0000000000000000000000000000000000000000000000040f1a26313c47515c66707a848e979fa7aca39c958e89837f7b787674737373737476787b7e82878d939aa1a9aba39b928980766c61574d42372c21160b0000000000000000000000000000000000000000000000000c1824303c47515a606161616161616161605a51473b3024180b000000000000000000000000000000000000000000000000000013202c3946535f6c798686868686868686868686868686868686868686868685848382817e7c7a7774706c68645f5a544e48413b332c241c140c0300000000000000000000000000000000000b151f29333c464e575f666e747a8085898d919497999b9c9d9e9f9f9f9f9f9e9d9c9b999794918d8985807a736c655d544b42392f251b100600000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d20130700000000000000000000000000000000000000000f1c2835424e5b6874818e9aa7b3a69a8d8174675b4e4235291c100300000000000000000000000000000000000000000006131f2c3845525e6b7784919daab0a3978a7d7164584b3e3225180c00000000000000000000000000000000050f1a25303c47535f6a76828e9aa6a3978c8074685c5044382d211509000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000121f2c3845525e6b7884919eaaab9e9285796c6053473c322b272523222126313c47535f6b77838f9ba8b2a6998c7f7265594c3f3226190c000000000000000000000b17232e39434c525657595a5b5c5d5e5f5e59515051535455555656565657575757626f7b8895a2afa5998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2f39444f5a646f7a85909ba5a79d92877c71675c51463c4855626f7b8895a2ada09386796d6053463a2d2013070000000000000004101c2935414e5a66737f8b97a4a296897d7164584c3f33271a0e02000000000000000000000000000000000000060e161d242a30353d4a56636e7777777777726a625951514f4d4b4945423e39342e28211a130b02000000000000000000000000000000000005101a252e373e434646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464645423d362d23190e030000000000010910161a1e1f2020202020202020201e1b17110a0200000000000000000000000000000000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000000000915202b37424d58636e78828c96a0a9aba29a928a837d77736f6c69686766666768696b6e72767b81888f979fa8ada49b91887e73695e53493d32271c100500000000000000000000000000000000000000000000000e1b2834404c58636c6e6e6e6e6e6e6e6e6b63584c4034271b0e0100000000000000000000000000000000000000000000000000131f2c3946525f6b7679797979797979797979797979797979797979797979787776757472706d6a6764605c58534e49433d363029221a130b02000000000000000000000000000000000000030d17212b343c454d555c63696f74797d8185888a8c8e909192929292929291908f8e8c8a8785817d79746e68625b534b423930271d13090000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acada09386796d6053463a2d2013070000000000000000000000000000000000000000101d2a3643505d6976838f9ca9b1a5988b7e7265594c4033261a0d0100000000000000000000000000000000000000000004111d2a3643505c6976828f9ca8b2a5988c7f7266594c4033261a0d000000000000000000000000000000000009141f2b36424e5a65717d8995a1a89c9084786d6155493d3125190d020000000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000111e2a3744505d6976838f9ca8ada194887c7064584d443c373431302f2e2e2d36424e5b6773808c99a5b2a6998c7f7265594c3f3226190c000000000000000000030f1c28343f4b555d6364656667696a6b6c6b63594e454647484949494a4a4a4a4a56636f7c8996a2afa5988c7e7265584c3f3225190c000000000000000013202c3946535f6c798693a0aca194887b6e6154483b35404b56616b76818c97a1aba1968b80756b60554a3f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000d1925323e4a57636f7b8894a0a5998d8074685b4f43362a1e110500000000000000000000000000000000000000040b12191e24313e4a5764717d848484847c746b635b534a423f3c3936322d28231d161008010000000000000000000000000000000000000009131c252c3237393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393936322b241b11070000000000000000050a0e1113131313131313131313120f0b06000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000000020e1a26313d48535f6a75808a949ea8ada39990888078726c67635f5d5b5a59595a5b5d5f62666b70767d858d959ea8ada39a8f857b70655a4f44382d21150a0000000000000000000000000000000000000000000000101c2936434f5c69757b7b7b7b7b7b7b7b74685c4f4235291c0f0300000000000000000000000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6b6a68676563615e5b5854504c47423d37322b251e171008010000000000000000000000000000000000000000050f19222a333b434a51585e63686d7175787b7d8082838485868686868585848381807d7b7875716d68635d575049413930271e150b010000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0acaca09386796d6053463a2d2013070000000000000000000000000000000000000000111e2b3844515e6a7784919daab0a3978a7d7164574b3e3125180b00000000000000000000000000000000000000000000010f1c2835424e5b6874818e9ba7b3a69a8d8173675a4d4134271b0e000000000000000000000000000000000004101c27333f4b57636e7a8693a0aca195897d7165594e42362a1e12060000000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e0100000f1c2835424e5b6773808c99a5b0a4988c8075695f564e4743403e3d3c3b3a3a3a3f4b5764717d8a97a3b0a6998c7f7265594c3f3226190c00000000000000000005121e2b3844505c676f7172737475777879756a5e5145393a3b3c3c3c3d3d3d3e4b5864717d8a97a4b0a4988b7e7165584b3e3225180b000000000000000013202c3946535f6c798693a0aca194887b6e6154483b3c47525d67727d88939da8a59a8f84796f64594e43393c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000916222e3b47535f6c7884919da99c9084776b5f52463a2d211508000000000000000000000000000000000000000001070d1724313d4a57636f7a848e918e867d756d655c544c443c332b26211c17110b05000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a26201a1209000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a0000000000000000000000000000000000000000000007131f2b36424e5965707b86919ca6b0a59b91877e766e67605b5753504e4d4d4d4d4e5053565a5f656b737b838c96a0aaaba1978c82766b6055493e32261a0e0300000000000000000000000000000000000000000000101c2936434f5c6976838888888888888275695c4f4236291c0f03000000000000000000000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5e5d5c5a595654524f4b4844403b37312c26201a130d0500000000000000000000000000000000000000000000000710182129313940464d52585d6165696c6f71737576777879797979787877767473716e6c6965615c57524c453e372f271e150c03000000000000000013202c3946535f6c798693a0a0a0a09386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693a0a0a0a09386796d6053463a2d2013070000000000000000000000000000000000000000121f2c3845525f6b7885929eabafa296897c6f6356493d3023170a00000000000000000000000000000000000000000000000e1a2734414d5a6773818d9aa6b3a79b8e8174685b4e4235281b0f00000000000000000000000000000000000915202c3844505c67737f8b97a3afa59a8e82766a5e52463a2e22170b0000000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e0100000d1a26333f4b5864707c8995a0aca89d91867b71685f59534f4d4b494848474747464956626f7c8995a2afa6998c7f7265594c3f3226190c0000000000000000000613202c3946535f6c787d7e808182838486796c6053473b302f2f3030303036424e5a6773808c99a5afa396897d7063574a3d3124170b000000000000000013202c3946535f6c798693a0aca194887b6e6154483b434e58636e79848f99a4a89e93887d73685d52473d323c4855626f7b8895a2ada09386796d6053463a2d201307000000000000000006121f2b3743505c6875818d9aa6a093877a6e6256493d3124180c000000000000000000000000000000000000000000000916222e3b47535e68727c8791988f877f766e665e564e453d352d241c140c040000000000000000000000000000000000000000000000010910161a1e1f2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201f1d1a150f0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a000000000000000000000000000000000000000000000b17232f3b47535e6a76818d98a3ada99e93897f756c645c554f4a474442414040404244464a4e545a6169717a848e98a3ada99e93887c71665a4e43372b1f130700000000000000000000000000000000000000000000101c2936434f5c69768390959595958f8275695c4f4236291c0f03000000000000000000000000000000000000000000000000000a16212c3740484f52535353535353535353535353535353535353535353535251504f4e4c4a4845423f3c38342f2b26211b150f090200000000000000000000000000000000000000000000000000060f171f272e353b41474c5155595c5f62646668696b6b6c6c6c6c6b6b6a69686664625f5c5955514c46413a342d251d150c0300000000000000000013202c3946535f6c798693939393939386796c5f5346392c2013060000000000000000000000000613202c3946535f6c798693939393939386796d6053463a2d2013070000000000000000000000000000000000000000131f2c3946525f6c7986929facafa295887b6f6255493c2f22160900000000000000000000000000000000000000000000000d1a2633404d596673808c99a6b3a89b8f8275685b4f4235281c0f00000000000000000000000000000000020d1925313d4954606c7884909ca7b3aa9e92867a6e63574b3f33271b0f0300000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e0100000a17232f3c4854606c7884909ba6aea2988d837a716a645f5c5957565554545353535355626f7b8895a2afa6998c7f7265594c3f3226190c00000000000000000006121f2c3845525e6b77848b8d8e8f9091887c6f63574c413c39373737383a3f47525e6a76828f9ba8ada094877b6e6255483c2f231609000000000000000013202c3946535f6c798693a0aca194887b6e6154483f4a545f6a75808b95a0aba2978c81766c61564b41362f3c4855626f7b8895a2ada09386796d6053463a2d2013070000000000000000030f1b2834404c5965717e8a96a3a3978a7e7265594d4034281b0f0300000000000000000000000000000000000000000006121f2b36414c56606a757f8993999189817870685f574f473f362e261e160d05000000000000000000000000000000000000000000000000050a0e111313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313110e09040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a000000000000000000000000000000000000000000020f1b27333f4b57636f7b87929ea9aea3978c82776d635a524a443f3a37353433333435373a3e42484f575f68727c86919ca7afa4998e82766b5f53473b2f23170b00000000000000000000000000000000000000000000101c2936434f5c697683909ca2a29c8f8275695c4f4236291c0f030000000000000000000000000000000000000000000000000005101a252e373e43464646464646464646464646464646464646464646464645454442413f3d3b3936332f2c28241f1a15100a0400000000000000000000000000000000000000000000000000000000050d151c232a30363b4045494d505356585a5b5d5e5f5f5f5f5f5f5e5d5d5b5a585553504d4945403b352f29221b130b030000000000000000000013202c3946535f6c798686868686868686796c5f5346392c2013060000000000000000000000000613202c3946535f6c798686868686868686796d6053463a2d201307000000000000000000000000000000000000000013202c3946535f6c7986929facaea295887b6e6155483b2f22150800000000000000000000000000000000000000000000000d1926333f4c5966727f8c99a6b2a99c8f8275695c4f4236291c0f0000000000000000000000000000000006121e2a36414d5965717d8994a0acb8afa3978b7f73675b4f43382c20140800000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e0100000713202c3844505c67737e8a949fa9a99f958c837c75706b686664636261616060605f5f626f7b8895a2afa6998c7f7265594c3f3226190c00000000000000000004111d2a36434f5c6874818d999a9c9d988c8074685d534c484644444444464a5059646f7a86929faba99d9185786c5f53463a2d211408000000000000000013202c3946535f6c798693a0aca194887b6e61544846505b66717c87919ca7a69b90857a70655a4f453a2f2f3c4855626f7b8895a2ada09386796d6053463a2d2013070000000000000000000c1824303d4955626e7a87939fa69a8e8175695c5044372b1f1206000000000000000000000000000000000000000000020e1a25303a444e59636d77818b969b928a827a716961595148403830281f170f070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000006121e2b37434f5c6874808c97a3afa99d92867b70655b51484039332e2b2927262627282a2e32373d454d56606a74808b96a1adaa9f93877b6f64574b3f33271b0e020000000000000000000002070a0b0c0c0c0c0c0c0c101c2936434f5c697683909ca9a99c8f8275695c4f4236291c0f0c0c0c0c0c0c0c0b0a07020000000000000000000000000000000009131c252c32373939393939393939393939393939393939393939393939393837363433312f2c292623201c18130e090400000000000000000000000000000000000000000000000000000000000000030b12181f252a3034393d404447494b4d4f50515252525352525151504f4d4b494644403d39342f2a241e171009010000000000000000000000131f2c3946525f6b767979797979797979766b5f5246392c1f130600000000000000000000000006131f2c3946525f6b767979797979797979766b5f5346392d201306000000000000000000000000000000000000000013202c3946535f6c798693a0acaea295887b6e6155483b2e22150800000000000000000000000000000000000000000000000c1926323f4c5965727f8c99a6b2a99c8f8275695c4f4236291c0f000000000000000000000000000000000b17232f3a46525e6a76828d99a5b1b1b2a79b9084786c6054483c3024180c01000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000030f1c28333f4b56626d78838d97a0a9a79e958d87817b787572716f6e6e6d6d6d6d6c6c6c6f7b8895a2afa6998c7f7265594c3f3226190c000000000000000000010e1b2733404c5965717d8995a1a8a89c90857a6f655d5854525150505153565b626b75808c97a3afa5998d8175695c5044372b1e1205000000000000000013202c3946535f6c798693a0aca194887b6e6154484c57626d78838d98a3aa9f94897e74695e53493e33282f3c4855626f7b8895a2ada09386796d6053463a2d2013070000000000000000000815212d3946525e6b7783909ca89d9185786c6053473b2e2216090000000000000000000000000000000000000000000008131e28323d47515b656f7a848e989c948c847b736b635a524a423a31292119100700000000000000000000000000000000000000000000000000000000000000000000010407090a0b0c0c0c0c0b0a080604010000000000000000000000000305060707070605040200000000000000000000000000000000000000000000000000000000000000000000040608080808080808080806040000000000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a0000000000000000000000000000000000000000000915222e3a47535f6c7884909ca8b0a4988c8175695e54493f362e27221e1c1a1a1a1a1c1e21262c333b444e58636e7985909ca8b0a4988c8074685b4f43372a1e1105000000000000000001080e13161819191919191919191c2936434f5c697683909ca9a99c8f8275695c4f4236291c19191919191919191816130e08010000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b2a2928262422201d1a1713100b07030000000000000000000000000000000000000000000000000000000000000000000000070d14191f24282d3134373a3d3f4142434445464646464545444342403e3c3a3734302d28241e19130d0600000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6b645a4f43372a1e110500000000000000000000000005111e2a37434f5a646b6c6c6c6c6c6c6c6c6b645a4f43372b1e12050000000000000000000000000000000000000000131f2c3946525f6c7986929facaea295887b6f6255483c2f22150900000000000000000000000000000000000000000000000d192633404c596673808c99a6b2a89c8f8275685c4f4236291c0f00000000000000000000000000000004101c27333f4b57636e7a86929eaaa7a4a5aaa094887c7064584d4135291d1105000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000000b17232e3a45515c66717b858e979fa6a79f98928c8884817f7d7c7b7b7a7a7a79797979787b8895a2afa6998c7f7265594c3f3226190c000000000000000000000b1824303d4955616d7985909ba7ada1968b81776f6964615f5e5d5d5e5f62676d747d87929da8aba094897d7165594d4034281b0f03000000000000000013202c3946535f6c798693a0aca194887b6e615448535e69747e89949faaa3988d83786d62574d42372c222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000005111d2a36424f5b6774808c98a5a194887b6f63574a3e3225190d00000000000000000000000000000000000000000000020c16212b353f49535e68727c86909b9e958d857d756c645c544b433b332b22190f0500000000000000000000000000000000000000000000000000000000000002060a0e11131517181919191818161513100d0a0602000000000001060a0d0f11131313131312100f0d0a070300000000000000000000000000000000000000000000000000000000060b101315151515151515151513100b06000000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a0000000000000000000000000000000000000000000b1824313d4a56626f7b8894a0acaca094887c7064584d42372d241c16120f0e0d0d0e0f12151b2129323c47525d6874808b97a4b0a89c9084776b5f52463a2d21140800000000000000030b13191f22252525252525252525252936434f5c697683909ca9a99c8f8275695c4f42362925252525252525252525231f1a130c030000000000000000000000000000010910161a1e1f202020202020202020202020202020202020202020201f1e1e1c1b19181513110e0b070300000000000000000000000000000000000000000000000000000000000000000000000000000002080e13181c2124282b2e303234353738383939393939383736353432302d2b2824201c18130d080200000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5a52483e32261a0e02000000000000000000000000020e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5a52493e33271b0f020000000000000000000000000000000000000000121f2c3945525f6b7885929fabafa295897c6f6256493c2f23160900000000000000000000000000000000000000000000000d1a2734404d5a6673808d9aa6b3a89b8e8275685b4f4235281c0f0000000000000000000000000000000914202c3844505c67737f8b97a3a59c9799a0a5998d8175695d5145392d22160a000000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e0100000006121d29343f4a555f69737c858d959ba1a6a39d9894908e8c8a8988888787878686868685858a96a2afa6998c7f7265594c3f3226190c000000000000000000000814202c3945505c68737f8a959fa9a89d938a817a74706d6b6a6a6a6a6c6f72787e868f99a3aea4998e83786c6054483c3024180c00000000000000000013202c3946535f6c798693a0aca194887b6e61544f5a65707a85909ba6a79c91877c71665b50463b3025222f3c4855626f7b8895a2ada09386796d6053463a2d201307000000000000000000010e1a26333f4b5864707c8995a1a4988b7f73665a4e4135291c100400000000000000000000000000000000000000000000050f19232d37414c56606a747e89939d9f978f877e766e665d554d453d342b21160b0000000000000000000000000000000000000000000000000000000003080e12161a1d20222425252626252423211f1c1916120d09030001070d1216191c1e1f202020201f1d1b1917140f0a03000000000000000000000000000000000000000000000000010a11171c1f2122222222222222211f1c1711090100000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a0000000000000000000000000000000000000000000d1a2733404c5965727e8b97a3b0a99d9084786c5f54483c31261b120b06030000000002050a1017202a35404c57636f7b8794a0acaca093877b6e6255493c3023170a000000000000020c151d242a2f313232323232323232323236434f5c697683909ca9a99c8f8275695c4f423632323232323232323232312f2b251e150c02000000000000000000000000000000050a0e111313131313131313131313131313131313131313131313121211100e0d0b09070401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002070c1015181c1e21232627292a2b2c2c2c2c2c2c2b2b2a28272523211e1b1814100c0702000000000000000000000000000000000a16212c3740484f525353535353535353524f4840372c21160a00000000000000000000000000000a16212c3740484f525353535353535353524f4940372c21160a000000000000000000000000000000000000000000121f2b3845515e6b7884919eabb0a3968a7d7063574a3d3024170a00000000000000000000000000000000000000000000000f1b2835414e5b6774818e9aa7b4a79a8e8174675b4e4134281b0e0000000000000000000000000000010d1925313d4854606c7884909ca79e938b8e98a49d9185796d62564a3e32261a0e020000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e01000000010c18232e38434d57616a737b838a90959a9ea2a4a09d9a9897969594949493939393929292949ca6b2a6998c7f7265594c3f3226190c0000000000000000000004101c2834404b57626e78838e98a1aaa59c938b85817d7a7877767777797b7e83899098a1aba59c92887d72665b5044382c20140800000000000000000013202c3946535f6c798693a0aca194887b6e615456616c76818c97a2aba0958b80756a5f544a3f34291f222f3c4855626f7b8895a2ada09386796d6053463a2d201307000000000000000000000a17232f3c4854616d7986929ea79b8f82766a5d5145382c201307000000000000000000000000000000000000000000000007111b25303a444e58626d77818b95a0a199908880786f675f574f463d33281c11050000000000000000000000000000000000000000000000000000070e14191e23262a2c2f30313232323231302e2c2926221e19140f090c12181d2226282b2c2d2d2d2c2b2a282623201b150e0600000000000000000000000000000000000000000000010b131b22282c2e2e2e2e2e2e2e2e2e2c28221b130a01000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a0000000000000000000000000000000000000000000f1c2835424e5b6774818d9aa6b3a69a8d8174685c4f43372b20140900000000000000000000050e19242f3b47535f6b7784909da9afa3968a7d7164584b3f3225190c00000000000009141e272f363b3e3f3f3f3f3f3f3f3f3f3f3f434f5c697683909ca9a99c8f8275695c4f423f3f3f3f3f3f3f3f3f3f3f3e3b362f271e140a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004080c0f121517191b1c1d1e1f1f20201f1f1f1e1d1c1a191714120f0c08040000000000000000000000000000000000000005101a252e373e4346464646464646464646433e372e251a1005000000000000000000000000000005101a252e373e4346464646464646464646433e372e251b1005000000000000000000000000000000000000000000111e2a3744515d6a7784909daab1a4978b7e7165584b3f3225190c0000000000000000000000000000000000000000000003101d2936434f5c6975828f9ba8b3a6998c8073665a4d4034271a0d000000000000000000000000000006121e2a36414d5965717d8994a0a69a8e828894a0a2968a7e72665a4e42372b1f13070000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000000006111c27313b454f58616971787e858a8e9295989b9d9ea0a1a2a2a1a1a0a0a0a09f9f9f9fa0a5aeb2a6998c7f7265594c3f3226190c00000000000000000000000c18232f3a46515c67717c868f98a0a7a59d96918c8987858483838485878b8f949ba2aaa49c938a80766b60554a3f33271c100400000000000000000013202c3946535f6c798693a0aca194887b6e61545d68727d88939ea8a4998e84796e63584e43382d2318222f3c4855626f7b8895a2ada09386796d6053463a2d201307000000000000000000000713202c3845515d6976828e9ba79e9286796d6154483c2f23170a00000000000000000000000000000000000000000000000009141e28323c46515b656f79848e98a2a29a928a8179716960584f44392d211508000000000000000000000000000000000000000000000000030b12191f252a2f3336393b3d3e3f3f3f3f3e3c3a3835322e2a25201a14161d23292e323537393a3a3a3938363532302c2620180f0600000000000000000000000000000000000000000009131d252d33383b3b3b3b3b3b3b3b3b38332d251c1309000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a000000000000000000000000000000000000000000111d2a3743505d6976838f9ca8b1a4978b7e7265594c4033271b0f03000000000000000000000007131e2a37434f5c6874818d9aa7b2a5998c8073665a4d4034271a0e000000000004101b25303941474b4c4c4c4c4c4c4c4c4c4c4c4c4f5c697683909ca9a99c8f8275695c4f4c4c4c4c4c4c4c4c4c4c4c4c4b47413930261b1005000000000000000000000004080a0c0c0c0c0c0c0c0c0c0b0804000000000000000000000102030303020100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306080a0c0e0f11111213131313121211100f0e0c0a080503000000000000000000000000000000000000000000000009131c252c32373939393939393939393937322c251c13090000000000000000000000000000000009131c252c32373939393939393939393937322c251c130900000000000000000000000000000000000000000000101d2936434f5c6975828f9ba8b2a5998c8073665a4d4034271b0e0200000000000000000000000000000000000000000006121f2b3845515e6a7784909da9b1a4988b7e7265584c3f3226190c00000000000000000000000000000b17232e3a46525e6a75818d99a5a2968a7e84909ca69a8f83776b5f53473b2f23170c0000000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e0100000000000a151f29333d464f575f666d73797e8286898c8e9092939495959696969696979797979899a0aab2a6998c7f7265594c3f3226190c000000000000000000000007121e2935404b55606a737d868e959ca2a7a29d99959392919090919294979ba0a5a6a09a928a81786e645a4f44392d22170b0000000000000000000013202c3946535f6c798693a0aca194887b6e6159646e79848f9aa4a89d92887d72675c52473c31271c15222f3c4855626f7b8895a2ada09386796d6053463a2d2013070000000000000000000004101c2935414d5a66727e8b97a4a295897d7064584b3f33261a0e010000000000000000000000000000000000000000000000020c16202a353f49535d67727c86909aa0a09c938b837b726a6155493d3124180b0000000000000000000000000000000000000000000000050d151d242a30363b3f4245484a4b4c4c4c4b4a494745423e3a36312b251f21282f353a3e414446464646464543413f3c38312a21180d030000000000000000000000000000000000000004101b252f373f44474848484848484847443f372e251a0f040000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a000000000000000000000000000000000000000000121e2b3845515e6b7784919daaafa296897c7063564a3d3124180b000000000000000000000000020e1b2733404c5965727e8b98a5b1a79b8e8175685b4f4235281c0f00000000000915212c37414b5257585858585858585858585858585c697683909ca9a99c8f8275695c5858585858585858585858585857534b42382d21160a000000000000000000030a0f14171919191919191919191714100a0300000205080a0c0d0e0f0f0f0f0f0e0d0b090705020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2a26211a130a0100000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2a27211b130a01000000000000000000000000000000000000000000000f1b2835414e5a6774818d9aa6b3a79b8e8175685c4f43362a1d11050000000000000000000000000000000000000000000915212e3a4753606c7986929fabafa396897d7063574a3e3124180b0000000000000000000000000004101b27333f4b57636e7a86929eaa9e92867a808b97a39f93877b6f63584c4034281c100400000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000000000030e18212b343d454d555c62686d7276797d8082848586878888898989898a8a8a8a8a8b8e98a4b0a6998c7f7265594c3f3226190c0000000000000000000000010d18232e39434e58616b737c838a91969b9fa3a5a2a09e9d9d9d9d9fa0a3a5a29f9a958f8880786f665c52483d32271c11060000000000000000000013202c3946535f6c798693a0aca194887b6e61606a75808b96a0aba1968c81766b60564b40352a201515222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000000000d1925323e4a56636f7b8894a0a5998c8074675b4f42362a1d1105000000000000000000000000000000000000000000000000040e19232d37414b56606a747e899393939393938d857c7265584c3f3226190c00000000000000000000000000000000000000000000050e171f272e353c41464b4f5254565858595958575654514e4a46423c3730292b323a40464a4e50525353535251504e4b48433c33291f1409000000000000000000000000000000000000000a15212c37414950545555555555555554504940362c2115090000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a000000000000000000000000000000000000000000121f2c3945525f6b7885929fabaea194887b6e6155483b2f221509000000000000000000000000000b1824313e4a5764707d8a96a3b0a99c8f8376695c5043362a1d1000000000000d1925313d49535d636565656565656565656565656565697683909ca9a99c8f8275696565656565656565656565656565645d54493e32261a0d0100000000000000050d151b202425262626262626262524201b150e070b0e111416181a1b1c1c1c1c1c1b19181614110e0a0602000000000000000000000000000000000000000000000000000000000407080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080704010000000000000000000000000000000000010910161a1e1f20202020202020201f1e1a16100901000000000000000000000000000000000000010910161a1e1f20202020202020201f1e1b1610090100000000000000000000000000000000000000000000000d1a26333f4c5965727e8b98a4b1a99d9084776b5e5245392d2014080000000000000000000000000000000000000000000c1825313d4a56626f7b8894a1adada094877b6e6255483c2f231609000000000000000000000000000814202c3844505b67737f8b97a3a69a8e82767b87939fa4988c8074685c5044382d21150900000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000000000040d161e252b333b434a51575c61666a6d7073757778797b7b7b7c7c7c7d7d7d7d7d7d7e8895a2afa6998c7f7265594c3f3226190c00000000000000000000000007121d27323c464f59616a727980858a8f9396999b9c9e9e9f9f9f9e9d9b9996938e89847d766e665d544a40362c21160b000000000000000000000013202c3946535f6c798693a0aca194877a6d6166717c87929ca7a59a90857a6f645a4f44392f24190e15222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000000000916222e3b47535f6c7884919da89c9083776b5e5246392d2114080000000000000000000000000000000000000000000000000007111b252f3a444e58626c778186868686868686867f7265594c3f3226190c000000000000000000000000000000000000000000040e172029313940474d52575b5e616364656565656462605e5a56524d48423b34343c444b51565a5d5f6060605f5e5c5a58544e453b31251a0e020000000000000000000000000000000000020e1a26323d49535b6061616161616161605b52483d32261a0d0000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c7986929facada094877a6d6054473a2e211407000000000000000000000000000916232f3c4956626f7c8895a2afaa9d9084776a5d5044372a1d1100000000000f1c2835414e5a656f7272727272727272727272727272727683909ca9a99c8f82757272727272727272727272727272726f665a4e4235291c1003000000000000040e171f262c30323232323232323232302c27201713171b1e2123252628282929292827262423201d1a17130e0904000000000000000000000000000000000000000000000000060c10131515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151513110c07010000000000000000000000000000000000050a0e1113131313131313131313110e0a0500000000000000000000000000000000000000000000050a0e1113131313131313131313110e0a05000000000000000000000000000000000000000000000000000b1824313e4a5763707c8995a2aeac9f93877a6e6155493d3024180c010000000000000000000000000000000000000005111d2935414d5966727e8b97a3b0aa9e9185786c5f53463a2d211407000000000000000000000000010d1925313d4854606c7884909ba7a2968a7e7277838f9ba79c9085786d6155493d3125190d02000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e0100000000000b151f2830363b3d3e40464b51555a5d616466686a6c6d6e6e6f6f6f6f7070707071717b8895a2afa6998c7f7265594c3f3226190c000000000000000000000000000b16202a343d474f5860676e747a7e83878a8c8e90919292929291908f8c8a86827d78726b645c544b42382e241a0f04000000000000000000000013202c3946535f6c798693a0aca094877a6d626d78838e98a3a99e94897e73685e53483d32281d120915222f3c4855626f7b8895a2ada09386796d6053463a2d201307000000000000000000000006121f2b3743505c6875818d9aa69f93877a6e6255493d3024180b000000000000000000000000000000000000000000000000000009131e28323c46505b656f787979797979797979797165584b3f3225190c0000000000000000000000000000000000000000020c162029323b434b52585e63676b6d707172727271706f6d6a67635e59534d463e3d464e565c6266696c6d6d6d6c6b6967645f574d42362a1e1205000000000000000000000000000000000005111e2a36424e5a656d6e6e6e6e6e6e6e6c645a4e4236291d100000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201407000000000000000000000000000815222f3b4855616e7b8895a2aeaa9e9184776a5d5144372a1e110000000000101c2936434f5c69767e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e83909ca9a99c8f827e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e766a5d5044372a1d11040000000000010c16202931373c3f3f3f3f3f3f3f3f3f3c383129211f23272a2d2f31333435363636353433312f2d2a26231f1a15100a040000000000000000000000000000000000000000020a11181c2021222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222201d18120b030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000916222f3b4854616d7a86929fabafa2968a7d7165594d4135291d1206000000000000000000000000000000000000000a16212d3945515d6975828e9aa6b3a79b8f8276695d5044372b1e120500000000000000000000000006121e2a35414d5965717c8894a0aa9e92867a6e727e8b97a3a195897d7165594d42362a1e1206000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000000007121d27313a41474a4b4c4d4f5051525354575a5c5e5f6061626262636363636363646f7b8895a2afa6998c7f7265594c3f3226190c00000000000000000000000000040e18222b353d464e555c63696e73777a7d8082838485858685848382807d7a76726d67615a524a423930261c120800000000000000000000000013202c3946535f6c798693a0aca09386796d69747f8a949faaa2988d82776c62574c41362c21160b0915222f3c4855626f7b8895a2ada09386796d6053463a2d2013070000000000000000000000030f1b2734404c5965717d8a96a3a3968a7d7165594c4034271b0f0200000000000000000000000000000000000000000000000000010c16202a343f49535d666c6c6c6c6c6c6c6c6c6c685f54483c3024170b000000000000000000000000000000000000000009141e28323b444d555c63696f73777a7c7e7e7f7f7e7d7b7976736e6a645e575049454f5860686e7376787979797977757370695e53463a2e21140800000000000000000000000000000000000815212d3946525e6b767b7b7b7b7b7b7b766a5e5144372b1e110000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110000000000101c2936434f5c6976838c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c949fabaa9e938c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c84776a5d5044372a1d1104000000000007121d28323b43484b4c4c4c4c4c4c4c4c49433b33292b2f3336393c3e40414242424242413f3e3c3936332f2b26211b150f08010000000000000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2d29241d150d0300000000000000000004070808080808080808080808080808080808080808080808080808080807060503010000000000000000000000000000000000000000000000000000000000000407080808080808080808080704010000000000000000000713202c3945515e6a77838f9ca8b2a6998d8175695d51453a2e23180d02000000000000000000000000000000000006111c27323e4a55616d7985929eaab0a4988b7f73665a4e4135281c0f030000000000000000000000000b17222e3a46525e6a75818d99a5a69a8e82766a6e7a86929ea59a8e82766a5e52463a2e22170b000000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e01000000000c17232e39434c535758595a5b5c5d5f605f5a524f51525354555555565656565757626f7b8895a2afa5998c7f7265594c3f3226190c0000000000000000000000000000061019232b343c444b52575d62676a6e71737576777879797878777573716e6a66615c564f48403830271e140a0100000000000000000000000013202c3946535f6c798693a0aca09386796c707b86909ba6a69c91867b70665b50453a30251a0f050915222f3c4855626f7b8895a2ada09386796d6053463a2d2013070000000000000000000000000b1824303d4955626e7a87939fa69a8d8175685c5043372b1e12060000000000000000000000000000000000000000000000000000040e18222d37414b545c5f5f5f5f5f5f5f5f5f5f5d564d43382c2014080000000000000000000000000000000000000005101b25303a444d565f676e757a7f8386898a8c8c8c8b8a8886837f7a756f69625a524d57616a72797e8285868686858482807b6e6255483c2f22150900000000000000000000000000000000000c1824313d4955626e7a87888888888882766a5d5144372b1e110000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110000000000101c2936434f5c697683909898989898989898989898989898999da6b0b0a59d9998989898989898989898989898989084776a5d5044372a1d110400000000000c18232f3a444d54585959595959595958544d453b32373b3f4346494b4c4e4f4f4f4f4e4d4c4a4846423f3b36312c262019120b03000000000000000000000000000000000a141d262e34383b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b39352f271f150b01000000000000060c101315151515151515151515151515151515151515151515151515151514141311100e0c090703000000000000000000000000000000000000000000000000060c10131515151515151515151513110c07010000000000000004101d2936424e5b6773808c98a4b0a99d9185796e62564b3f34291e140a01000000000000000000000000000000040e18222d38434f5a66727d8a96a2aeaca094887c6f63574a3e3225190d00000000000000000000000004101b27333f4b57626e7a86929eaaa2968a7e72656a76828e9aa69e92867a6e63574b3f33271b0f030000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e01000000030f1c2834404b555e6364666768696a6b6d6b64594e4446474848494949494a4a4a56636f7c8996a2afa5988c7e7265584c3f3225190c000000000000000000000000000000071019222a323940464c52565a5e616466686a6b6b6c6c6b6b6a686764615e5a55504a443d362f261e150c020000000000000000000000000013202c3946535f6c798693a0ac9f9286796c77828c97a2aaa0958a7f746a5f54493e34291e1309000915222f3c4855626f7b8895a2ada09386796d6053463a2d2013070000000000000000000000000814212d3946525e6b7783909ca89d9184786c5f53473a2e22150900000000000000000000000000000000000000000000000000000006111b252f39424a5053535353535353535353514c443b31261b1004000000000000000000000000000000000000000b16212c37414c565f68717880868b90939597989998989795928f8b86817b746c645c545e69737c848a8f9193939392918f887b6f6255483c2f22150900000000000000000000000000000000030f1b2834404c5965717e8a959595958b7f72665a4e4135291c100000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110000000000101c2936434f5c697683909c9e9e9e9e9e9e9e9e9e9e9e9e9e9fa2aab3b3aaa29f9e9e9e9e9e9e9e9e9e9e9e9e9e9d9084776a5d5044372a1d110400000000000f1c2834404b565f6465656565656565655f574d433d43474b4f525557595a5b5c5c5c5b5a595755524f4b47423d37312b241d150d05000000000000000000000000000006111c262f383f454848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484845403931271d120700000000020a11181c2021222222222222222222222222222222222222222222222222222221201f1e1c1b181613100c080400000000000000000000000000000000000000020a11181c2021222222222222222222201d18120b03000000000000010d1a26323f4b57636f7c8894a0acaea2968a7e73675c51463b30261c130a0300000000000000000000000000050d16202a343f4a55606b77838e9aa6b2a89c9084786c5f53473b2f22160a0000000000000000000000000814202c38444f5b67737f8b97a2aa9e9286796d6166727e8a96a2a3978b7f73675b4f43382c2014080000000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e0100000005121f2b3844505c676f7172737576777879766a5e5145393a3b3c3c3c3c3c3d3f4b5864717d8a97a4b0a4978b7e7165584b3e3225180b0000000000000000000000000000000007101820272e353b41464a4e5255585a5c5d5e5f5f5f676b6b6b6b6b675e544a453f39332c241d140c03000000000000000000000000000013202c3946535f6c798693a0ac9f928578737d88939ea9a4998e83786e63584d42382d22170d02000915222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000000000005111d2a36424f5b6773808c98a5a094887b6f63564a3e3125190c0000000000000000000000000000000000000000000000000000000009131d2730383f444646464646464646464644403a32291f150a0000000000000000000000000000000000000005111c28333e49535e68717a838a91979c9fa2a4a5a4a2a2a2a19f9b97928c867e766e655c65707b858e969b9ea0a0a09f9d95887b6f6255483c2f2215090000000000000000000000000000000006121f2b3743505c6875818d9aa2a094887b6f63564a3e3225190d0000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110000000000101c2936434f5c6976839092929292929292929292929292929298a2adada1989292929292929292929292929292929084776a5d5044372a1d11040000000000121e2b3844505c68707272727272727271695f554c494e53575b5f626466676869696868676563615e5b57534e49433c362f271f170f06000000000000000000000000000b17222d38424a5154555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555554514b43392f23180c000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2d2c2b292725221f1c1814100b0601000000000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2d29241d150d030000000000000a16232f3b47535f6b77848f9ba7b2a69b8f84786d62574c42382e251c150e0804000000000000000001050a10171f28323c46505b66717c88939fabafa3978c8074685b4f43372b1f13060000000000000000000000010d1925313d4854606c78848f9ba7a69a8d8275695d616d7986929ea79b8f84786c6054483c3024180c0100000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000000613202c3946535f6c797e7f818283848586796c6053473b302e2f2f2f303036424e5a6773808c99a5afa396897d7063574a3d3124170b0000000000000000000000000000000000060e161d242a30353a3e4246494b4d4f50515860697177777777777065584c3f342e28211a130b0200000000000000000000000000000013202c3946535f6c798693a0ab9e92857879848f9aa5a79d92877c72675c51463c31261b100600000915222f3c4855626f7b8895a2ada09386796d6053463a2d201307000000000000000000000000010e1a26333f4b5864707c8995a1a4978b7e72665a4d4135281c1004000000000000000000000000000000000000000000000000000000010b151e272e33373939393939393939393938342f2820170d03000000000000000000000000000000000000000a16222d39444f5a656f79838c959ca2a8a8a29d999796969697989b9e9d97908880776e656a76828c97a0a7aba39c97949394887b6f6255483c2f221509000000000000000000000000000000000916222e3b47535f6c7884919da99d9184786c5f53473b2e2216090000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110000000000101c2936434f5c69768385858585858585858585858585858586919da9a99c908685858585858585858585858585858584776a5d5044372a1d11040000000000131f2c3946525f6c797f7f7f7f7f7f7f7a71675e54545a5f64686b6e70727475757575757372706e6b67635f5a544e474039312921180f060000000000000000000000000f1b27333f4a545c616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161615d554b4034291d100400000a141d262e34383b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3a39373634312f2c2824201c17120c0600000000000000000000000000000a141d262e34383b3b3b3b3b3b3b3b3b3b39352f271f150b01000000000007131f2b37434f5b67737f8b96a2adaca0958a7e73695e544a40372e261f1914100c0a09080708090b0d11151b2229313a444e58626d77838e99a4b0a99e92877b6f63574b3f33271b0f03000000000000000000000006121e2935414d5965717c8894a0aca195897d7165595d6975828e9aa6a094887c7064584d4135291d110500000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e0100000006121f2c3845525e6b77848c8d8e8f9092887c6f63574c423c39383737383a3f48535e6a76838f9ba8ada094877b6e6255483c2f231609000000000000000000000000000000000000040b12191e24292e3236393c3f4149515a626a727a83848484807366594c4033261d161008010000000000000000000000000000000013202c3946535f6c798693a0aa9e918477808b96a1aca1968b80756b60554a40352a1f140a0000000915222f3c4855626f7b8895a2ada09386796d6053463a2d201307000000000000000000000000000a17232f3c4854606d7985929ea79b8e8276695d5144382c1f130700000000000000000000000000000000000000000000000000000000030c151c23282b2c2c2c2c2c2c2c2c2c2c2b28241e160e0500000000000000000000000000000000000000030f1b27323e4a55616c77818b959ea7ada49d96918d8a8989898a8c8e92969b9a928980766d6f7b87929ea9ada399918b888687887b6f6255483c2f221509000000000000000000000000000000000d1925323e4a56636f7b8894a0a69a8d8175685c5043372b1f12060000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000f1c2936424f5b68737878787878787878787878787878787883909ca9a99c8f827878787878787878787878787878787874685c5043362a1d10040000000000121f2b3844515d69737c868c8c8c8c8c837970665c5f656b6f74777a7d7f818282828282817e7d7a77736f6a655f59524b433b332a21180e040000000000000000000000121e2b37434f5b666d6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6d675c5145392c2013070006111c262f383f454848484848484848484848484848484848484848484848484848484747454442403e3b3834302c28231d17110a03000000000000000000000006111c262f383f454848484848484848484845403931271d12070000000000030f1b27333f4b57626e7a85919ca7b1a69b90857a70665c52494038312a25201c19171515141516171a1d21262c333b434c565f6a747e89949faaafa4988d82766a5e53473b2f23170b0000000000000000000000000b17222e3a46525e6975818d99a5a99d9185796d61555965717d8996a2a5998d8175695d5145392d22160a00000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e0100000004111d2a36434f5c6874818d999b9c9d988c8074685d544c484645444445474a5159646f7b87939faba99d9185786c5f53463a2d2114070000000000000000000000000000000000000001070d13191d22262a323a424b535b636c747c848c9190867b7165584c3f3326190c0500000000000000000000000000000000000013202c3946535f6c798693a0aa9d90837c87929da7a59a8f84796f64594e44392e23180e030000000915222f3c4855626f7b8895a2ada09386796d6053463a2d201307000000000000000000000000000713202c3845515d6976828e9ba79e9285796d6054483b2f23160a0000000000000000000000000000000000000000000000000000000000030a11171b1e202020202020202020201f1c18130c05000000000000000000000000000000000000000006131f2b37434f5b66727d88939da7ada49b928b85817e7c7c7c7d7f82868a8f959b92897f75727e8b97a3afa79c9187807b797a7c7b6e6255483c2f22150900000000000000000000000000000004101c2935414d5a66727e8b97a4a3968a7e7165594c4034281b0f030000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000e1a27333f4b5761696b6b6b6b6b6b6b6b6b6b6b6b6b6b6b75828f9ca9a99c8f82756b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6962574c4034281b0f020000000000101c2935414c57616a747e87919999958b82786e656b71767b8084878a8c8d8e8f8f8f8e8d8b898783807b76706a645d554d453c332a20160c020000000000000000000013202c3946525f6c777b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b796d6154473b2e211408000b17222d38424a51545555555555555555555555555555555555555555555555555554545352514f4d4a4744413d38332e28221c150e07000000000000000000000b17222d38424a5154555555555555555554514b43392f23180c0000000000000b17222e3a46525d6974808b96a1acaca1978c82786e645b524a433c36302c28252322212121222426292d32383e454d565e68717b86909ba5b0a89d92877c7065594e42362a1f13070000000000000000000000040f1b27333f4b56626e7a86929ea9a4998d8175695d5155616d7985919da99d9185796d62564a3e32261a0e02000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e01000000010e1b2733404c5865717d8995a1a9a89c90857a6f665e5855535151515153565b626b75818c97a3afa5998d8175685c5044372b1e1205000000000000000000000000000000000000000000020b131b232b343c444c545d656d757e868e9692887e74695f54493d3024170b0000000000000000000000000000000000000013202c3946535f6c798693a0a99c9083838e99a3a99e93887d73685d52483d32271c1207000000000915222f3c4855626f7b8895a2ada09386796d6053463a2d2013070000000000000000000000000004101c2935414d5a66727e8b97a4a195897c7064574b3f32261a0e01000000000000000000000000000000000000000000000000000000000000060b0f121313131313131313131312100c07010000000000000000000000000000000000000000000a16222f3b47535f6b77838e9aa5afa69b9289817a75716f6f6f7173767a7e848a919991877c75818e9aa7aea2968a7f756f6d6d6f70695e53463a2d2114080000000000000000000000000000000713202c3845515d6976828e9ba79f93877a6e6255493d3024180c000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000b17232f3a454f575d5e5e5e5e5e5e5e5e5e5e5e5e5e5e6975828f9ca9a99c8f8275695e5e5e5e5e5e5e5e5e5e5e5e5e5e5d5850463b3024180c0000000000000c1824303b454f58626c757f89929c9d948a80766e757c82878c909396989a9b9c9c9c9b9a989693908c87827c756e675f574e453c32281e140a0000000000000000000013202c3946535f6c7986888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888887b6e6154483b2e211508000f1b27333f4a545c61616161616161616161616161616161616161616161616161616161605f5d5b595754504d49443f3a342d27201811090000000000000000000f1b27333f4a545c616161616161616161615d554b4034291d1004000000000006121e2935414c57636e79858f9aa5afa89e948a80766d645c544d47413c383532302f2e2e2e2f303336393e434950575f68707a838d98a2acaca2978c81766b5f54483d31251a0e0200000000000000000000000814202c38444f5b67737f8b96a2aca094887c7064584c515d6975818d99a5a2968a7e72665a4e42372b1f1307000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e01000000000b1824303c4955616d7884909ba6ada1968b81786f6964615f5e5d5d5e6063676d747d87929da8ab9f94887d7165594c4034281b0f030000000000000000000000000000000000000000040c141d252d353d464e565e666f777f879098958b81766c62584d43382c2014080000000000000000000000000000000000000013202c3946535f6c798693a0a99c90858a959faaa2978c82776c61564c41362b20160b00000000000915222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000000000000000d1925313e4a56636f7b8894a0a5988c8073675b4e4236291d1105000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1925323e4a57636f7b88949fabab9f948a80766f69656362636466696e737980878f978e847983909da9ab9e92867a6e63606163635f574d42362a1e12050000000000000000000000000000000a17232f3c4854606d7985929ea89c9083776b5e5246392d211408000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000a16222d38434c54595b5b5b5b5b5b5b5b5b5b5b5b5b5c6975828f9ca8a99c8f8275695c5b5b5b5b5b5b5b5b5b5b5b5b5b5a554d44392e22170b00000000000008131e29333d46505a636d76808a949d9c92897f7980878d93989ca0a3a3a09f9e9e9e9fa1a3a29f9c98938d878079716960574e443a30261b110600000000000000000013202c3946535f6c7986939595959595959595959595959595959595959595959595959595959595959595959595959595959595959594887b6e6154483b2e21150800121e2b37434f5b666d6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6d6d6b6a686663605d5955504a453f38312a231b120a0100000000000000121e2b37434f5b666d6e6e6e6e6e6e6e6e6d675c5145392c2013070000000000010d1924303b46525d68737e89939ea8b0a69c928980766e665f58524d4844413f3d3b3b3a3b3c3d3f4245494e545a6169717a838c959fa9afa59a90857a6f64594e43372c2015090000000000000000000000010d1925313c4854606c78848f9ba7a79b8f84786c6054484d5965717d8995a1a69a8f83776b5f53473b2f23170c000000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e01000000000814202c3844505c68737e8a959fa9a89d938a817a75716e6c6b6a6a6b6c6f73787e879099a3aea3998e83776c6054483c3024180c0000000000000000000000000000000000000000050e161e262e373f474f586068707881899199978d83796e645a50463c31271b10040000000000000000000000000000000000000013202c3946535f6c798693a0aca19791939ca6a69b90867b70655a4f453a2f241a0f0400000000000915222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000000000000000916222e3a47535f6c7884919da89c8f83776a5e5245392d20140800000000000000000000000003090d0f111111111111100e0b06000000000000050a0d10111111111111100d0a050000000000000000000000000000000000000000000000000f1b2834414d5a66737f8b98a4b0a69a8e83786d645d58565556575a5d62676e757d858e958a8085919eaba89c8f83766a5d53545657544d453b30251a0e020000000000000000000000000000010e1a26333f4b5764707c8995a1a5988c8074675b4f42362a1d1105000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000d1a26323e4a555f6567676767676767676767676767676875828f9ca8a99c8f8275696767676767676767676767676767665f554a3f33271a0e010000000000020d17212b343e48515b656e78828b959f9b9187838b92999ea4a39e9a9694929191929394979a9ea4a39e98928b837b726960564c42382d22170c01000000000000000013202c3946535f6c798693a0a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a194887b6e6154483b2e2115080013202c3946525f6c777b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7a7978777572706d6965605b56504a433c342d241c130a0100000000000013202c3946525f6c777b7b7b7b7b7b7b7b796d6154473b2e21140800000000000008131e2a35404c57616c77818c96a0a9aea49b92898078716a635e5854504d4b4948484748484a4c4e51555a5f656c737b838c959ea7b0a69d93897e74695e53483d32261b0f04000000000000000000000006121e2935414d5965707c8894a0aca3978b7f73675b4f434955616d7985919da99f93877b6f63584c4034281c10040000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000000004101c2834404b57626d78838d97a1a9a59c938c86817d7a7977777777797b7f84899099a2aba59c92877d72665b4f44382c20140800000000000000000000000000000000000000060f172028303840495159616a727a828a939b9a90857b71675d52483e342a20150a000000000000000000000000000000000000000013202c3946535f6c798693a0aca9a19d9fa5aa9f948a7e74695e53493e33281e13080000000000000915222f3c4855626f7b8895a2ada09386796d6053463a2d201307000000000000000000000000000006121e2b3743505c6875818d9aa69f93867a6e6155493c3024170b0000000000000000000000080f14191c1e1e1e1e1e1e1d1a17110b030000020910161a1c1e1e1e1e1e1e1c1a1610090200000000000000000000000000000000000000000000101d2a3643505c6975828e9ba7aea296897d72665c524c4949494b4d51565c636b737c858f918788939faca79a8d8174675b4e474a4a48433b33291f140900000000000000000000000000000005111d2a36424e5b6773808c98a5a195897c7064584b3f33261a0e01000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000f1c2835424e5a667174747474747474747474747474747475828f9ca8a99c8f827574747474747474747474747474747471675b4f4236291d1003000000000000050f19222c363f49535c667079838d96a099918e959ca3a69f98928e8a878584848586888a8e93989ea5a39c958d847b72685e54493f34291e1207000000000000000013202c3946535f6c798693a0acaeaeaeaaa6a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a194887b6e6154483b2e2115080013202c3946535f6c79868888888888888888888888888888888888888888888888888887868583817f7c7975716c67615b554e463f362e251c130900000000000013202c3946535f6c7986888888888888887b6e6154483b2e211508000000000000020d19242f3a45505b65707a848e97a1aaada49b928a827b756e6964605d5a5856555454545556585b5e61666b70777e858d959ea7b0a79e948b81776c62574c42372b20150a0000000000000000000000000b16222e3a46525d6975818d99a5aa9e92867a6e63574b3f44505c6975818d99a5a4988c8074685c5044382d2115090000000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e0100000000000c17232f3a46515c67717b858f979fa6a59e97918d8987858484848486888b8f959ba2aba49c938a80756b60554a3e33271c1004000000000000000000000000000000000000030e172129323a424a525b636b737b848c949c9c92887e73695f554b41362c22180e03000000000000000000000000000000000000000013202c3946535f6c798693a0acb3adaaabaea3988d83786d62574d42372c22170c010000000000000915222f3c4855626f7b8895a2ada09386796d6053463a2d2013070000000000000000000000000000020f1b2734404c5965717d8a96a2a2968a7d7165584c4033271b0f020000000000000000000912192025292a2a2a2a2a2a2a27221c150d04020b141b2126292a2a2a2a2a2a2926211b140b02000000000000000000000000000000000000000000121e2b3845515e6b7784919daaac9f9286796d61554a413d3c3d3e41454b5259616a737d879292939aa4afa6998c807366594c403d3d3b37312a21170d030000000000000000000000000000000814212d3946525e6a77838f9ca89e9285796d6154483c2f23170a00000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110000000000101c2936434f5c697681818181818181818181818181818181828f9ba8a99c8f8381818181818181818181818181818181776a5d5044372a1d11040000000000000007101a242d37414a545e67717b858e98a19c9b9fa7a59c948d87827e7b79787778797b7e82878d949ba4a79f968d847a70655b50453a2f24180d010000000000000013202c3946535f6c798693a0acb7b4a9a09998989898989898989898989898989898989898989898989898989898989898989898989894887b6e6154483b2e2115080013202c3946535f6c798693959595959595959595959595959595959595959595959594949392908e8b8985817d78736d665f58504840372e251b1107000000000013202c3946535f6c7986939595959594887b6e6154483b2e2115080000000000000007131e29343e49535e68727c858f98a0a9ada49c948d86807a75706c6966646362616161626365676a6e72767c82888f979fa7afa69e958c83796f655a50463b30251a0f040000000000000000000000030f1b27333f4b56626e7a86929ea9a69a8e82766a5e52463a404c5864707c8995a1a89c9084786d6155493d3125190d0100000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e01000000000007121e29343f4a555f69737c858d959ca1a7a29d99969492919090919294979ba0a6a5a099928a81786e64594f44392d22160b0000000000000000000000000000000000000009151f29333b444c545c646d757d858e969e9f958a80766c62574d43392f251a100600000000000000000000000000000000000000000013202c3946535f6c798693a0acb9b9b7b2a79c91877c71665b51463b30261b1005000000000000000915222f3c4855626f7b8895a2ada09386796d6053463a2d2013070000000000000000000000000000000b1824303d4955626e7a87939fa6998d8174685c4f43372a1e1206000000000000000008121b242b313537373737373736332e271f160d0b141d252c323637373737373736322c251d140b000000000000000000000000000000000000000000131f2c3946525f6c7885929fabaa9d9184776b5e514539302f3032353a40474f58616b75808b969fa4acb2a6998c7f7265594c3f32312f2b261f180f05000000000000000000000000000000000b1824303d4955616e7a87939fa79b8e8276695d5145382c20130700000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110000000000101c2936434f5c6976838e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e949faaab9f958e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e84776a5d5044372a1d1104000000000000000008121b252f38424c555f69727c868f9aa5a8aba69c938a827b76716e6c6b6b6b6c6f72767b8289929ba4a89f968c82776c62574b4035291e12060000000000000013202c3946535f6c7986919ba5b0b0a4988e8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b887b6e6154483b2e2115080013202c3946535f6c798693a0a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a1a0a09e9d9a9895918d89847e78716a625a524940372d23190e040000000013202c3946535f6c798693a0a2a2a194887b6e6154483b2e21150800000000000000010c17222d37424c56606a737c868e979fa7aea69f98918b86817c797673716f6e6e6d6e6f707174767a7e82878d939aa1a9aca59d948c837a70675d53493e34291e14090000000000000000000000000814202c38434f5b67737e8b96a2ada195897d7165594e42363c4854606c7885919da9a195897d7165594d42362a1e120600000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000000000010d18232e39434e58616a737b838a90969b9fa2a5a2a09f9e9d9d9e9fa1a4a5a29e9a948e8880786f665c52483d32271c1105000000000000000000000000000000000000030f1a26313b454d555e666e767e878f979fa1978d83786e645a50463b31271d13080000000000000000000000000000000000000000000013202c3946535f6c798693a0acacacacaba0958b80756a5f554a3f342a1f140900000000000000000915222f3c4855626f7b8895a2aca09386796d6053463a2d2013070000000000000000000000000000000814212d3946525e6a77838f9ca89d9084786b5f53463a2e2115090000000000000005101a242d363c41444444444444433f3931281f14121c262f373e42444444444444423e372f261c1207000000000000000000000000000000000000000013202c3946535f6c798693a0acaa9d908376695d5043372a222325292e353d464f59636e7984909ba7b3b2a6998c7f7265594c3f3226231f1b150e0600000000000000000000000000000000020f1b2734404c5965717d8a96a2a4978b7e72665a4d4135291c100400000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110000000000101c2936434f5c697683909b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9fa6b0b1a79f9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9084776a5d5044372a1d110400000000000000000009131d26303a434d57606a747d8a96a3b0aa9f948a8178716a65625f5e5e5e6062666a70778089929ca6a89e93897e73685d51463a2e23170b00000000000000131f2c3945525e6a75808a949ea8aea295887e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7a6e6154483b2e2115080013202c3946535f6c798693a0acaeaea8a4a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a4a4a5a7a9a7a4a19d99948f89837c746c645b52493f352b20150b0000000013202c3946535f6c798693a0acaea194887b6e6154483b2e211508000000000000000006101b25303a444e58616a737c858d959da4aba9a39c97918d898582807d7c7b7a7a7b7b7c7e8083868a8e93999ea5aca8a29a938b837a71685e554b41372d22180d020000000000000000000000010d1925303c4854606c77838f9ba7a89c9185796d6155493d313844505c6874818c98a5a59a8e82766a5e52463a2e22170b00000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e0100000000000007121c27323c464f58616971787f858a8f9296989a9c9d9e9e9f9e9e9c9b9896928e89837d766e665d544a40362b21160b0000000000000000000000000000000000000007131f2b37424d575f67707880889199a1a4998f857b71675c52483e34291f150b010000000000000000000000000000000000000000000013202c3946535f6c798693a0a0a0a0a0a0998f84796e63594e43382d23180d0200000000000000000915222f3c4855626f7b8895a0a0a09386796d6053463a2d20130700000000000000000000000000000005111d2a36424e5b6773808c98a5a094877b6f62564a3d3125190c000000000000000a16212c3640474d5051515151514f4a433a31261b18242e3841494e5151515151514e4941382e24180d010000000000000000000000000000000000000013202c3946535f6c798693a0acaa9d908376695d5043372a1d16191d242b343d47525d68737f8a96a2aeb2a6998c7f7265594c3f322619130f0a03000000000000000000000000000000000006121e2b3743505c6874818d99a6a094887b6f63564a3e3225190d0000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110000000000101c2936434f5c697683909b9b9b9b9b9b9b9b9b9b9b9b9da3a8aab0b7b8b1aba8a49d9b9b9b9b9b9b9b9b9b9b9b9b9084776a5d5044372a1d1104000000000000000000010b141e28323e4955616c78838e99a5b1a89c8f82786f665f59555351515253565a5f666d76808a95a0aba59b9085796e62574b3f33271b0f03000000000000111d2a36424e59636d77828c96a0aaa4998e847a71717171717171717171717171717171717171717171717171717171717171717171717171695e5246392d2014070013202c3946535f6c798693a0acb2a79d9796969696969696969696969696969696969798999b9da0a3a7aaa5a09a948d867e766d645b51473c32271c110600000013202c3946535f6c798693a0acaea194887b6e6154483b2e21150800000000000000000009141e28323c464f58616a737b838b9299a0a6aba8a29d9995918f8c8a898887878888898b8d8f92969a9fa4aaa9a49d979089817970685f564c43392f251b100600000000000000000000000006121d2935414d5965707c8894a0aca4988c8074685c5044392d34404c5864707c8894a0aa9e92867a6e63574b3f33271b0f03000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e01000000000000000b15202a343d464f585f676e74797e8386898c8e8f919192929291908e8c8986827d78726b645c544b42382e241a0f04000000000000000000000000000000000000000916222f3b47535f697179828a929aa0a09c92887d73695f554a40362c22180e03000000000000000000000000000000000000000000000013202c3946535f6c79869393939393939393887d72675d52473c31271c11060000000000000000000915222f3c4855626f7b88939393939386796d6053463a2d201307000000000000000000000000000000010e1a26333f4b5764707c8995a1a3978b7e7266594d4134281c10030000000000030f1b27323e4852595d5d5d5d5d5d5b554c42372c201e2935404a535a5d5d5d5d5d5d5a534a4035291e120500000000000000000000000000000000000000131f2c3946525f6c7985929fabaa9d9184776b5e5145382c231e1c1a19222b36404b57626e7a86929eaab2a6998c7f7265594c3f3226190c03000000000000000000000000000000000000000915222e3a47535f6b7884909da99d9184786c5f53473a2e2216090000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110000000000101c2936434f5c6976838e8e8e8e8e8e8e8e8e8e8e8e8e919ba6b2aeababafb3a79b928e8e8e8e8e8e8e8e8e8e8e8e8e84776a5d5044372a1d11040000000000000000000006121e2a36424e5a66727d8994a0abb6aa9e93897f756c62584f46454445474a4e545c646e78838e99a5aca1968a7f73675b5044382b1f13070000000000000e1a26313d47515c66707a848e98a2aaa0968c82786e65656565656565656565656565656565656565656565656565656565656565656565645f574d41362a1e11050013202c3946535f6c798693a0acada1958c8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8b8c8e9093979ba0a6aca69f98908880766d63594e43392d22170b00000013202c3946535f6c798693a0a3a3a194887b6e6154483b2e211508000000000000000000020c16202a343d464f586169717981888e949aa0a5a9a9a5a19e9b99979695949494959697999c9fa2a6aba7a39e98928c857e776f675e564d443a31271d1309000000000000000000000000000a16222e3a46525d6975818d99a5ab9f93877b7064584c403428303c4854606c7884909ca8a3978b7f73675b4f43372c201408000000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e0100000000000000040e18222b343d464e555c63686e72767a7d7f81838485858585848382807d7a76716c676059524a42392f261c120800000000000000000000000000000000000000000a1724303d4a5663707b838b9393939393938a80766b61574d43392e241a100600000000000000000000000000000000000000000000000013202c3946535f6c7986868686868686868681766b61564b40352b20150a000000000000000000000915222f3c4855626f7b86868686868686796d6053463a2d201307000000000000000000000000000000000a17232f3b4854606d7985929ea79a8e8275695d5044382b1f1307000000000005121e2b37434f5a646a6a6a6a6a6a675e54483d3024212e3a46515c656a6a6a6a6a6a655c51463a2e21150900000000000000000000000000000000000000121f2b3845515e6b7784919daaac9f9286796d6154493d342e2b28272625242f3a46515d6976828e9ba7b2a6998c7f7265594c3f3226190c00000000000000000000000000000000000000000c1925313e4a56626f7b8794a0a69a8d8175685c5043372b1f12060000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110000000000101c2936434f5c697681818181818181818181818181818a97a4aba39e9ea3aca4978b8181818181818181818181818181776a5d5044372a1d1104000000000000000000000916222e3a46525e6a76828e9aa5b1b0aca59b91887e746a61574d443a383a3d424a525c67727d8994a0aca79b9084786c6054483c2f23170b0000000000000915202b36404a545e68727c86909aa5a89e948a80756b61585858585858585858585858585858585858585858585858585858585858585858544d453b3025190d010013202c3946535f6c798693a0acaca093867d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7e808184878b8f959ba2aaaaa29a92887e756a60554a3f33281c1105000013202c3946535f6c7986939696969694887b6e6154483b2e21150800000000000000000000040e18222b343d464f575f676f767d83898f94999da1a4a8aaa8a5a4a2a1a1a1a1a2a2a4a6a8a9a6a3a09c97928d87817a746c655d554c443b32281f150b01000000000000000000000000030f1b27333f4a56626e7a86929da9a79b8f83776b5f53473b2f242b3844505c6874808c98a4a79b8f84786c6054483c3024180c010000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000000000000000061019222b343c434b51575d62666a6d70737476777878787877767573706d6a66615b554f4840382f261d140a0000000000000000000000000000000000000000000a1724303d4a5763707d868686868686868682786e645a4f453b31271d120800000000000000000000000000000000000000000000000000131f2c3946525f6b76797979797979797979796f655a4f44392f24190e04000000000000000000000815222f3b4855616d7879797979797979766b5f5346392d201306000000000000000000000000000000000713202c3844515d6976828e9ba79e9185796c6054473b2f22160a00000000000714202d3a46535f6b7577777777777065594c40332723303d4956626e7777777777776e62564a3d3124180b00000000000000000000000000000000000000111d2a3643505c6975828e9ba7aea295897d71655a4f463f3a3735333232313135414d5a66727f8b98a4b1a6998c7f7265594c3f3226190c0000000000000000000000000000000000000003101c2835414d5966727e8b97a3a3968a7d7165594c4034271b0f030000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000f1c2835424e5a667174747474747474747474747478838e99a5a39992929aa4a69a8e847874747474747474747474747471675b4f4236291d1003000000000000000000000c1925313e4a56626f7b87939fabada59f9ea29a90867c73695f564c42392f3138404a55606c77838f9ba7aca094887c7064584b3f33271a0e020000000000040f19242e38424c56606a747e89939da7a69c92887d73695f554b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b48433c33291f1408000013202c3946535f6c798693a0acaca09386797070707070707070707070707070707070717375777b7f848a9098a0a9aca49a91877c71665b5044392d21150a000013202c3946535f6c79868a8a8a8a8a8a887b6e6154483b2e2115080000000000000000000000061019222b343d454d555d646b72787e83888d9195989b9ea0a1a3a4a5a5a5a5a5a4a2a19f9d9a9793908b86817b766f69625a534b433a322920160d03000000000000000000000000000814202c37434f5b67737e8a96a2aea2968a7e72665b4f43372b1f27333f4b5864707c8894a0aca094887c7064584d4135291d11050000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e01000000000000000000071019222a323940464c51565a5e616466686b6e6f70706f6c6a686664615e5a55504a443d362e261d140b020000000000000000000000000000000000000000000a1723303d4a56636f7879797979797979797970665c52483e33291f150b0100000000000000000000000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c675e53483d33281d120800000000000000000000000714202d3945515c666c6c6c6c6c6c6c6c6b645a4f43372b1e12050000000000000000000000000000000004101c2835414d5a66727e8b97a0a095887c7063574b3e32261a0d00000000000714212e3a4754606d79848484848174685b4f42362924303d4a5663707c848484847e7265594c4033271a0e010000000000000000000000000000000000000f1b2834414d5a66737f8b98a4b0a5998d82766b6158514b464442403f3e3e3e3e3e4a5763707d8a96a3b0a6998c7f7265594c3f3226190c0000000000000000000000000000000000000007131f2c3844505d6975828e9aa79f93877a6e6255493d3024180b000000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000d1a26323e4a555f656767676767676767676769747f8a95a0a89d928788939ea9a0958a7f746967676767676767676767665f554a3f33271a0e01000000000000000000030f1c2835414d5a66727e8b97a3afa69b939298a1988f857b71685e544b41372e2e39444f5b67737f8b97a3b0a5988c8074675b4f42362a1d110400000000000008121c26303a444e58626c77818b959fa9a3998f857b71675d53483e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3c38312a21170d02000013202c3946535f6c798693a0acaca09386796c636363636363636363636363636363646566686b6e73787e868e97a1abaca3988e83786c61554a3e32261a0e010013202c3946535f6c787d7d7d7d7d7d7d7d7a6e6154473b2e211408000000000000000000000000071019222b333c434b525a60676d72777c8185898c8f9193959697989898989897969492908e8b87837f7a76706a645e5750494139312820170e0400000000000000000000000000010d1924303c4854606c77838f9ba7a99e92867a6e62564a3e32261a232f3b47535f6b7884909ca8a4998d8175695d5145392d21160a0000000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000000000000000000007101820272e353b40454a505860676d73777a7c7d7d7b7975706a635c544d49443f39322b241c140b02000000000000000000000000000000000000000000000915222e3a47525d676c6c6c6c6c6c6c6c6c6c685f544a40362c22170d0300000000000000000000000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5c554c41372c21160b01000000000000000000000004111d2934404a545b5f5f5f5f5f5f5f5f5f5a52493e33271b0f0200000000000000000000000000000000000d1925313e4a56636f7b88939393938c8073675a4e4235291c10000000000006131f2c3845515e6a778390919083776a5e5145382c222f3b4854616d798691918d8174685b4f42362a1d11040000000000000000000000000000000000000c1925323e4a57636f7b87939fabaa9e93887d736a625c5753504e4d4c4b4b4a4a4a4a55626f7c8895a2afa6998c7f7265594c3f3226190c000000000000000000000000000000000000000a16232f3b4854606c7985919ea89c9083776a5e5246392d211408000000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000a16222d38434c54595b5b5b5b5b5b5b5b5b65707a86909ba6a1968b80828c97a3a69c91867b70655b5b5b5b5b5b5b5b5b5a554d44392e22170b0000000000000000000005121f2b3744505d6976828e9ba7aea2958a868f99a1978d837a70665d534940362c333f4a57636f7b8794a0ada89c9084776b5e5245392c201307000000000000000a141e28323c46515b656f79838d97a1aba1978d83796f645a50463c323232323232323232323232323232323232323232323232323231302c2620180f0500000013202c3946535f6c798693a0acaca09386796c5f565656565656565656565656565657585a5c5f62676d747c858f99a4afaa9f94897d72665a4e42362a1e110500121e2b3744505c676e70707070707070706f685d5145392d20130700000000000000000000000000071019212a323941484f555b61676c7075797c80828586888a8b8b8c8c8c8b8a89888684817e7b77736f6a655f59534c463e372f271f160e05000000000000000000000000000006121d2935414d5964707c8894a0aca5998d8175695d51463a2e22161f2b37434f5b6773808c98a4a99d9185796d62564a3e32261a0e0200000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000000000000000000000060e151d232a323d465059626a72787e8387898a898885817b756e665d544b41372e27211a120a02000000000000000000000000000000000000000000000006121e2a36414c555c5f5f5f5f5f5f5f5f5f5f5c564d43382e241a10060000000000000000000000000000000000000000000000000000000a16212c3740484f5253535353535353535353504b433a30251a0f05000000000000000000000000000c18232e38424a505253535353535353524f4940372c21160a0000000000000000000000000000000000000915222e3a47535f6c7884868686868683766a5d5144372b1e11000000000004101d2936424f5b6874818d9a9286796d6054473b2f222c3945515e6a7783909c9084776a5e5245392c2013070000000000000000000000000000000000000916222e3b47535f6b77828e99a4afa49a8f857c746d67635f5d5b595958575757575656626f7b8895a2afa6998c7f7265594c3f3226190c000000000000000000000000000000000000010d1a26323f4b5764707c8995a1a5988c8073675b4f42362a1d1105000000000000000000000000000000000000000000000000000f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170a00000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000005111c27313a43494d4e4e4e4e4e4e4e55606b76818c97a2a69b90857a7b86919ca7a2978c81766b61564e4e4e4e4e4e4e4d49433b32271d1106000000000000000000000814212d3a4653606c7885919eaaab9f92867d87919a9f958c82786f655b52483e352e3a47535f6b7884919daaac9f93867a6d6154483b2f22160900000000000000020c16202b353f49535d67717b858f9aa4a99f958b81766c62584e443a302625252525252525252525252525252525252525252525252523201b150e060000000013202c3946535f6c798693a0acaca09386796c5f534a4a4a4a4a4a4a4a4a4a4a4a4a4a4b4d4f52565c626a737d87929da9b1a69a8e83766a5e5246392d211408000f1c28343f4a555d626363636363636363635e564c4135291d11040000000000000000000000000000070f1820272f363d444a50565b6065696c707376787a7b7d7e7e7e7f7e7e7d7c7b797775726f6b67635e59544e48423b342d251d150d040000000000000000000000000000000a16222e3a46515d6975818d99a4aca094897d7165594d4135291d111b27333f4b57636f7b8894a0aca2968a7e72665a4e42372b1f130700000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e01000000000000000000000000040d18242f3a444e58626b747c848a8f9395969694918d8780786f665d53493f34291e130800000000000000000000000000000000000000000000000000020e19252f3a434b5053535353535353535353504b443b31271c12080000000000000000000000000000000000000000000000000000000005101a252e373e43464646464646464646464644403931281e1309000000000000000000000000000007121c2630383f43464646464646464646433e372e251b100500000000000000000000000000000000000006121e2b3743505c687479797979797979756a5d5144372b1e110000000000010e1a2733404c5965727e8b9795897c7063574a3e31252936424f5b6874818d9a93867a6d6154483b2f22160a00000000000000000000000000000000000006121e2b37434e5a66717d88929da7aba1978e867e78736f6c6967666565646464636363636f7b8895a2afa6998c7f7265594c3f3226190c00000000000000000000000000000000000004111d2936424e5b6773808c98a4a195897c7064584b3f33261a0e010000000000000000000004090b0d0d0d0d0d0d0d0d0d0d0d0d0f1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d3024170d0d0d0d0d0d0d0d0d0d0d0d0c0a070300000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110000000000000a151f2831383d40414141414146515c67727d88939ea8a0958a7e7475808b96a1a99e93887d72675c51464141414141413d38312920160b00000000000000000000000a16232f3c4955626e7b8894a1ada99c9083777e88929c9e948a81776d645a50473d333743505c6975828e9ba8aea295897c7063574a3d3124180b0000000000000000040f19232d37414b555f69737d88929ca6a79c92887e746a60564c42372d23191818181818181818181818181818181818181818181817140f0a03000000000013202c3946535f6c798693a0acaca09386796c5f53463d3d3d3d3d3d3d3d3d3d3d3d3e3f4043464b5158616b76818c98a4afab9f93877a6e6255493d3024170a000b17232e39434b5256565656565656565656534c443a2f24190d01000000000000000000000000000000060e161d242c32393f454a4f54585c606466696b6d6f7071727272727171706e6d6b6865625f5b57524d48423d373029221b130b03000000000000000000000000000000030f1b27333f4a56626e7a86919da9a89c9084786c6054483d3125190d17232f3b47535f6b77838f9ba8a69a8e83776b5f53473b2f23170c00000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e0100000000000000000000000007121e2a35404b56606a747d868e959b98959495979a98918a82786f655b50453a2f24180c000000000000000000000000000000000000000000000000000008131e2831393f444646464646464646464644403a32291f150a00000000000000000000000000000000000000000000000000000000000009131c252c3237393939393939393939393938342e271f160c020000000000000000000000000000000b141e262d333739393939393939393937322c251c130900000000000000000000000000000000000000020f1b2734404c57626a6c6c6c6c6c6c6c6b63594d4135291c100000000000000b1824313d4a56636f7c8895988b7e7266594d4034272733404c5965727e8b9795897c7063574b3e3225190c000000000000000000000000000000000000020e1a26323e4955606b76818b959ea6a9a098908a847f7b7876747372717171717070706f6f7b8895a2afa6998c7f7265594c3f3226190c0000000000000000000000000000000000000814202d3945525e6a76838f9ba89e9285796d6054483c2f23170a000000000000000000040b101518191a1a1a1a1a1a1a1a1a1a1a1a1c2835424f5b6875828f9ca8b0a4978a7d7063574a3d30241a1a1a1a1a1a1a1a1a1a1a1a1a1917130e08010000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000030d161f262d313434343437424d58636d78838e99a4a5998e83786d6e79848f9aa5a4998f84796e63584d423734343434312d271f170e0400000000000000000000000b1825313e4b5764707d8a96a3afa79a8e817476808a939d9c938980766c62594f453c34414d5a6673808c99a6b1a4988b7e7265584c3f3326190d00000000000000000007111b252f39434d57616c76808a949ea8a49a90867c72685d53493f352b21170d0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0a07040000000000000013202c3946535f6c798693a0acaca09386796c5f5346393030303030303030303030313234363a3f464f5964707b87939facafa3968a7d7165584b3f3226190d0006121c2731394146494c4c4c4c4c4c4c4c4a47423a32281e13080000000000000000000000000000000000040b131a21272e34393f44484c5054575a5c5f6162636465656565656464646464615b56534f4b46423d37312b251e18100901000000000000000000000000000000000814202b37434f5b67737e8a96a2aea3978b8074685c5044382c201408131f2b37434f5b67737f8b97a3ab9f93877b6f63584c4034281c1004000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000000000000000000000000b17232f3b46515d68727c86909898918c8988888a8e949c948b81776d62574c4034291d110500000000000000000000000000000000000000000000000000010c161f272e34383939393939393939393938342f2820170d03000000000000000000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2b28231d150d0400000000000000000000000000000000020c141c22272b2c2c2c2c2c2c2c2c2c2a27211b130a0100000000000000000000000000000000000000000b17232f3b4650585e5f5f5f5f5f5f5f5e5951473c3125190d0000000000000915222e3b4754606d7986929a8e8175685c4f43362a24313d4a56636f7b8895988c7f73665a4d4134281b0f020000000000000000000000000000000000000a16212d38444f5a646f79838c949ca3a9a29b958f8b87858281807e7e7e7d7d7d7d7d7c7c7c8895a2afa6998c7f7265594c3f3226190c0000000000000000000000000000000000000b1724303c4955616d7a86929fa79b8e8276695d5144382c2013070000000000000000060e151c212426262626262626262626262626262835424f5b6875828f9ca8b0a4978a7d7063574a3d30262626262626262626262626262626231f1a130b0200000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000040d151b2125272828323d48535e69747f8a95a0a99e93887d726768737e89949faaa0958a8074695e54493e3328282725211c150d050000000000000000000000000d1926333f4c5965727e8c98a5b1a5998c7f736e78818b959e9b91887e746b61574e443a3f4b5865717e8b97a4b1a6998d8073675a4d4134271b0e0100000000000000000009131d27313b46505a646e78828c96a0aaa2988e84796f655b51473d33291f140a000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c232323232323232323232425272a2e343d48535f6b7783909ca8b2a6998d8073675a4d4134271b0e00000b17232e39444d5458595959595959595650473d32271c100400000000000000000000000000000000000001080f161c22282e33383c4044484b4d505254555757585b626a7071717171716c63574b433f3b36312c26201a140d060000000000000000000000000000000000010d1924303c4854606b77838f9ba7ab9f93877b6f63574b3f33271c10040e1b27333f4b57636f7b87939faba4988c8074685c5044382c211509000000000000000000000c1925323f4c5865727e8c98a5b2a79a8e8174675a4d4134271a0e010000000000000000000000030f1b27333f4b57636e79848e98968d86807c7b7b7e838a929b93897e73685d5145392d2115090000000000000000000000000000000000000000000000000000040d151d23282b2c2c2c2c2c2c2c2c2c2c2b28231d160e050000000000000000000000000000000000000000000000000000000000000000010910161a1e1f202020202020202020201f1c17120b04000000000000000000000000000000000000020a11171b1e20202020202020201f1e1b1610090100000000000000000000000000000000000000000007131e29343e464d5253535353535353524e473f352b20140900000000000006131f2b3845515e6a7683909c9084776b5e5245392c212e3a4753606c7985929b8e8275695c5043372b1e120500000000000000000000000000000000000005101c27323d48535d67707a828a92989ea3a6a09b9794918f8e8c8c8b8b8a8a8a8a898989898c97a3b0a6998c7f7265594c3f3226190c0000000000000000000000000000000000020e1b2733404c5864717d8a96a2a4978b7e72665a4d4135291c100400000000000000050f1820272d3133333333333333333333333333333335424f5b6875828f9ca8b0a4978a7d7063574a3d333333333333333333333333333333322f2b241d140b01000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110000000000000000030a1015181a232e39444f5a65707b86919ba6a3988d82776c61616c77838e99a4a79c91867b70655a4f44392e241a1915100a03000000000000000000000000000e1b2734414d5a6773818d9aa6b1a4978b7e71666f79838c96a09a90867d736960564c433d4a5763707d8996a3b0a89b8e8275685b4f4235291c0f02000000000000000000010b151f2a343e48525c66707a848f99a3aaa0968b81776d63594f453b30261c12080000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2017171717171717171717191b1e232b37424f5b6774818d9aa6b3a89b8e8275685b4f4235291c0f00000f1b28343f4b555f656666666666666661594f44382c2013070000000000000000000000000000000000000000040b11171d22272c3034383b3e414346474950575e666d747c7d7d7d7d7d74675a4d41342f2a25201b150f090200000000000000000000000000000000000006111d2935414d5864707c8894a0aba69a8e82766a5e53473b2f23170b000a16222e3b47535f6b77838f9ba7a89c9084786d6155493d3125190d010000000000000000000c1925323f4c5865727e8c98a5a7a79a8e8174675a4d4134271a0e01000000000000000000000006121f2b3743505c68737f8b96988e847b74706e6e72788089939b9085796d6155493d3125180c000000000000000000000000000000000000000000000000000000030b12171c1e202020202020202020201f1c18120c040000000000000000000000000000000000000000000000000000000000000000000000050a0e111313131313131313131313120f0c0700000000000000000000000000000000000000000000060b0f12131313131313131313110e0a050000000000000000000000000000000000000000000000020d18222c353c42454646464646464645423d362d23190e0300000000000003101c2935424e5b6774818d9993867a6d6154483b2f222b3844515d6a76838f9c9185786b5f53463a2d211408030303030201000000000000000000000000000b16212c36414b555e68707880878d92979b9ea1a3a09e9c9a999898989797979696969695979ea8b2a6998c7f7265594c3f3226190c000000000000000000000000000000000005121e2a37434f5c6874818d99a5a094887b6f63564a3e3125190d00000000000000020d17212a32383d40404040404040404040404040404040424f5b6875828f9ca8b0a4978a7d7063574a404040404040404040404040404040403f3c362f261d1309000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000409141f2a35404b55606b76818c97a2a89d92877b70655a5b66717c87929da8a2978c82766c61564b40352a1f1409050000000000000000000000000000000f1b2835424e5b6875818e9ba8b0a3968a7d706367717a848e97a1988f857b72685e554b414955626f7b8895a2afa99c8f8376695c504336291d100300000000000000000000040e18222c36404a545e68727c87919ba5a79d93897f756b61574c42382e241a100600000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130a0a0a0a0a0a0a0a0b0c0e121a26333f4c5965727e8b98a5b1a99c8f8376695c4f4336291c100000111e2b3744505c6770737373737373726b6054483c2f23160900000000000000000000000000000000000000000000060c11161b2024282c2f32363d444c535a616970777f868a8a8a8a8174675a4d4134271e19140f090400000000000000000000000000000000000000000a16222e3a46515d6975818d98a4ada2968a7e72665a4e42362a1e12070006121e2a36424e5b67737f8b97a3ada195897d7165594d42362a1e12060000000000000000000c1925323f4c5865727e8c989a9a9a9a8e8174675a4d4134271a0e0100000000000000000000000815212e3a47535f6c7884909c91867c7269636162666e77818c97968a7e7265594d4034271b0e0200000000000000000000000000000000000000000000000000000000060b0f121313131313131313131312100c07010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006101a232a313639393939393939393936322b241b110700000000000001070d1a26333f4c5865717e8a9795897c7063574a3e31252935424e5b6774808d9994877b6e6255493c3023170f0f0f0f0f0f0d0b060100000000000000000000040f1a252f39434c565e666e757b81868b8f929597999b9c9d9e9e9f9f9f9fa0a0a0a0a0a1a2a7afb2a6998c7f7265594c3f3226190c00000000000000000000000000000000000915212e3a46535f6b7784909ca99d9184786c5f53473a2e2216090000000000000008131e29333c43494c4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4f5b6875828f9ca8b0a4978a7d7063574d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4b4741382f251a0f030013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110000000000000000000005101a25303b46515c67727d88939ea9a1968b80756a5f5455606b76818c97a2a99e93887d72675c51473c31261b10050000000000000000000000000000000f1c2936424f5c6975828f9ca8afa296897c6f635f68727c858f99a1978d847a70675d534a4855616e7b8894a1aeaa9d9083776a5d5044372a1d1104000000000000000000000006101a242e38424c57616b757f89939da7a59b91877d73685e544a40362c22180e03000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000020b1824313e4b5764717d8a97a4b1a99c908376695c4f4336291c100001121f2c3845525f6b788080808080807d7063574a3d3024170a000000000000000000000000000000000000000000000000060b0f141c232a313940474f565d656c737a82899197938a81776e64584c4033261a0e0904000000000000000000000000000000000000000000030f1b27333e4a56626e7a86919da9a99d9185796d61554a3e32261a0e0200020e1a26323e4a56626e7b87939faba5998e82766a5e52463a2e22170b0000000000000000000c1925323f4c5865727e8c8d8d8d8d8d8d8174675a4d4134271a0e0200000000000000000000000a1723303d4956626f7b8894988c80756a605854565c65707b87939a8e8175685c4f4336291d1003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002070c0e1010101010100f0d090400060a0e101010101010100e0a06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000811192025292c2c2c2c2c2c2c2c2c2a26201a1209000000000000060d12171a24303d4956626f7b8894988c7f72665a4d41342826333f4c5864717d8a96968a7d7164584b3f33261c1c1c1c1c1c1c1a17120c050000000000000000000008131d27313a434c545c636a70767a7e8286888b8d8e9090919292929292939393949494969da8b2a6998c7f7265594c3f3226190c00000000000000000000000000000000000c1825313d4a56626e7b8794a0a6998d8175685c5043372b1e1206000000000000000c1824303a454e555959595959595959595959595959595959595b6875828f9ca8b0a4978a7d706359595959595959595959595959595959595958524b41362b2014080013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000000000b16212c37424d58636e78848e99a4a69b90857a6f64594d4e59646f7a85919ca7a59a8f84796e63584d42372c21170c010000000000000000000000000000101c2936434f5c6976838f9ca9afa295887b6f6256606a737d87909a9f968c82786f655c524854616e7a8794a1aeaa9d9184776a5d5144372a1e110400000000000000000000000008121c26303b454f59636d77818b959faaa3998f857a70665c52483e34291f150b010000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000002050b1824313e4b5764717d8a97a4b1a99c8f8376695c4f4336291c100004121f2c3945525f6b78858c8c8c8c8a7d7063574a3d3124170a000000000000000000000000000000000000000000000000050e171f262d353c434b525960686f767e858c949b948a81786f655c52473c3024170b00000000000000000000000000000000000000000000000814202b37434f5b67737e8a96a2aea4988c8175695d5145392d2115090000000a16222e3a46525e6a76838f9ba7aa9e92867a6e62574b3f33271b0f0300000000000000000c1925323f4c5865727e818181818181818174675a4d4134271d140900000000000000000000000b1825313e4b5764717d8a9795897c7064584e484a535e6a7783909c9084776a5d5144372b1e110500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060d13181b1d1d1d1d1d1d1c19150f0b11161a1c1d1d1d1d1d1c1a16110b04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070e14191d1f202020202020201f1d1a150f080000000000000710171e2327292e3a4753606c7985929b8e8275695c5043372a29303c4955626e7b8794998d8074675b4e4235292929292929292826231d170f07000000000000000000010b151f28313a424a52595f656a6e7276797c7e808283848485858586868686868787878b97a3afa6998c7f7265594c3f3226190c00000000000000000000000000000000030f1c2834414d5966727e8b97a3a2968a7d7165594c4034271b0f0200000000000000101c2935414c5760656666666666666666666666666666666666666875828f9ca8b0a4978a7d7066666666666666666666666666666666666666645d53483c3024180b0013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000007121d28333d48535e69747f8a95a0aba0958a7e73685d524748535e69747f8a95a0aba0958a80746a5f54493e33281d12070000000000000000000000000000101c2936434f5c697683909ca9afa295887b6f625558616b757e88929b9e948b81776d645a5054616d7a8794a1aeaa9e9184776a5d5144372a1e1104000000000000000000000000000a141f29333d47515b656f79848e98a2aba0968c82786e645a50453b31271d13090000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130b0b0b0b0b0b0b0c0d0f11151b26333f4c5865727e8b98a4b1a79b8e8275685b4f4235291c0f0006131f2c3946525f6c7986929999978a7d7164574a3e3124170b0000000000000000000000000000000000000000000000020d17202930383f464e555c646b727981888f979d948b81786f665d534a41362b1f140800000000000000000000000000000000000000000000000c1824303c48545f6b77838f9ba6a6a094887c7064584c4035291d11090401060b121e2a36424e5a66727e8a97a3a6a3978b7f73675b4f43372c20140800000000000000000b1824313e4a56626d7373737373737373736f64584c40382f251b1004000000000000000000000b1825323e4b5865717e8b9894877a6d6154473c424e5b6875818e9b9185786b5e5145382b1e12050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000811181f2427292a2a2a2a2a2825201a151c2226292a2a2a2a2a2926221d160e0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090d11121313131313131313110e090400000000000006101922292f3335363844515d6a76838f9c9184786b5f5246393636363a46535f6c7885919c8f83766a5d5144383636363636363635332e2821190f06000000000000000006101921282e323940474e54595e62666a6d6f71737576777778787979797979797a7a7b8895a2afa6998c7f7265594c3f3226190c0000000000000000000000000000000006131f2b3844505d6975828e9aa69f93877a6e6155493d3024180b0000000000000000121f2b3845515d68717373737373737373737373737373737373737375828f9ca8b0a4978a7d73737373737373737373737373737373737373736f64594c4033271a0d0013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110000000000000000020d18232e39444f5a65707b86919ca6a4998e83786d62574c41414c58636e79848f9aa5a79c91867b70655a4f443a2f24190e0300000000000000000000000000101c2936434f5c697683909ca9afa295887b6f62554f59636c768089939d9d938980766c625954616d7a8794a1aeaa9e9184776a5d5144372a1e110400000000000000000000000000030d17212b353f49535d67727c86909aa4a89e948a80766c61574d43392f251b110700000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201818181818181818191a1b1e21262d37434f5b6774808d99a6b1a5988c8073665a4d4134271b0e000613202c3946535f6c7986939fa4978b7e7164574b3e3124180b000000000000000000000000000000000000000000000009141f29323b424951585f676e757d848b939a9e948b82786f665d544b41382f241a0e030000000000000000000000000000000000000000000000101c2935414d5864707c88949a9a9a9a8f84776c6054483c30241b19150f0c12171a1c26323e4a56626e7a86929a9a9a9a8f84786c6054483c3024170b00000000000000000916222e3a46515b63676767676767676767645d56524a41372c211509000000000000000000000b1825323e4b5865717e8b9894877a6e61554940444f5c6875828e9b9184786b5e5145382b1e1205000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007111a222a303436363636363635312c251f272e3336363636363636332e2720170e04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030e18222c343a3f424242424e5b6774808d9993877a6e615548424242424244505d6975828f9b9285796d6054474242424242424242423f3a332b21170d02000000000000020d18222b33393e41424344484d52565a5d6063656768696a6b6b6b6c6c6c6c6d6d6d6f7b8895a2afa6998c7f7265594c3f3226190c000000000000000000000000000000000a16222f3b4754606c7885919ea89c8f83776a5e5246392d211408000000000000000013202c3946535f6c798080808080808080808080808080808080808080828f9ca8b0a4978a80808080808080808080808080808080808080808074675b4e4134281b0e0013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000009141f2a35404b56606b76818c97a2a99e93887d72675c51453a3b46515c67727d88939ea9a2988d82776c61564b40352a1f140a00000000000000000000000000101c2936434f5c6976828f9ca9afa295887c6f625549515a646e77818b959e9b92887e746b6157616e7a8794a1aeaa9d9084776a5d5144372a1e11040000000000000000000000000000050f19232d37414c56606a747e88929ca6a69c92887d73695f554b41372d23180e04000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2525252525252525252526282a2d31373f49545f6b7783909ca8ada195897d7064574b3e3225190c000713202d3a4653606d798693a0a4988b7e7165584b3e3225180b00000000000000000000000000000000000000000000020e1a25303b444d545b626a717880878e969d9e958c827970665d544b42392f261d1308000000000000000000000000000000000000000000000000121f2b3845515d6975818d8d8d8d8d8d8b7f73675b4f43372b292825201a171e232729292e3a46525e6a76828d8d8d8d8d8d887c7064584c4033261a0d000000000000000006121e29353f4951575a5a5a5a5e636464646464625c53493d3226190d000000000000000000000b1824313e4a5764707d8a9696897d71655a514d4e56606c7884909c9083766a5d5044372a1e110400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030e19232c343b40434343434343413d362f2931393f424343434343423f39322920150b00000000000000000000000000000004070809090909090909090807050507080909090909090909080705010000000000000000000000000000000000000000000000000000000000000009141f2a343e454b4f4f4f4f4f5864717d8a9696897d7064574f4f4f4f4f4f4f4f5a6673808c9895887c6f63564f4f4f4f4f4f4f4f4f4e4b453d33291e130800000000000008141f29343d444a4d4f50515253545657565456585a5b5d5d5e5f5f5f5f5f5f6060626f7b8895a2afa6998c7f7265594c3f3226190c000000000000000000000000000000010d1926323e4b57636f7c8895a1a5988c8073675b4e42362a1d1105000000000000000013202c3946535f6c79868d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d949faab2a69a918d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8174675b4e4134281b0e0013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110000000000000005101b25303b46515c67727d88939ea9a3988d82766b60554a3f3435404b56616c77828d98a3a99e93887d72675d52473c31261b10050000000000000000000000000f1c2935424f5c6875828f9ca8afa296897c6f63564948525c656f79838c96a09a90877d736960616e7b8894a1aeaa9d9083766a5d5043372a1d110400000000000000000000000000000007111b25303a444e58626c76808a949fa9a4998f857b71675d53493f342a20160c020000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346393232323232323232323232333437393d4249515b65707b87939faba89d9185796d6154483c2f23160a000714202d3a4753606d798693a0a5988b7e7165584b3f3225180c0000000000000000000000000000000000000000000005121e2a36424c565e666d747c838a9299a09e958c837970675e544b423930261d140b0100000000000000000000000000000000000000000000000013202c3946535f6c7980808080808080807a6e62574b3f36363634312c2521292f3335363636424e5a66727e808080808080808074675a4d4134271a0e0000000000000002091018232d3740474b4d525a61686f71717171716e655a4e4235291c10000000000000000000000a16232f3c4955626e7a8793998d82776c635c595a6068727d8894998d8174685b4f4235291c1003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000914202b353e464c4f50505050504d484138313b434a4f50505050504f4a443b31271c1105000000000000000000000000070c111415151515151515151515141111141515151515151515151514110d070100000000000000000000000000000000000000000000000000000000000d1925313c4650575b5c5c5c5c5c626e7b8794988c8073665c5c5c5c5c5c5c5c5c5c64707d8996978b7e72655c5c5c5c5c5c5c5c5c5c5b564f453b3024180c0000000000010d1925303b454f565a5b5d5e5f60616263625d544c4d4f5051515252525253535355626f7c8995a2afa5988c7f7265594c3f3226190c00000000000000000000000000000004101d2935424e5a67737f8c98a4a195897c7064574b3f33261a0e01000000000000000013202c3946535f6c7986939a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9ea6b0b7aca29c9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a8e8174675b4e4134281b0e0013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000000b16212c37424d58636e78848e99a4a89c91867b70655a4f44392e2e39444f5a65707b87929da8a59a8f84796e63584d42372d22170c0100000000000000000000000f1b2835414e5b6874818e9ba7b0a3978a7d7064574a404a535d67707a848e97a1998f857b7268626f7c8895a2afa99c8f8276695c4f4336291d10030000000000000000000000000000000009141e28323c46505a646e78838d97a1aba1978d83796f655a50463c32281e140a0000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f53463e3e3e3e3e3e3e3e3e3e3e3f40414346494e545b636c77828d98a4ada2978c8075695d5145382c201407000714202d3a4753606d7a8794a0a5988c7e7265584c3f3225190c000000000000000000000000000000000000000000000814212e3a46525e6870777f868d959ca09f958c837a70675e554c423930271e140b0200000000000000000000000000000000000000000000000000121f2b3845515d6871737373737373737372695e524642424242413d372f2b333a3f42424242424a56616c7373737373737373736e64584c4033261a0d000000000000050c141b222a31383f474e555d646b737a7d7d7d7d7d766a5d5043372a1d11000000000000000000000814212d3a46525f6b77838f9a93887e756e6866676b727a848e9994897c7164584c3f33271a0e01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1a25313c4750585c5d5d5d5d5d59524a3f38434d555b5d5d5d5d5d5b554d43392d22160a00000000000000000000020b12181d2022222222222222222222211d1d2022222222222222222222201d18120b0300000000000000000000000000000000000000000000000000000000111d2936424d5862686969696969696c7885919b8e82756969696969696969696969696e7a87939a8e817569696969696969696969696761574c4034281c0f030000000004101d2935414d57616768696a6b6d6e6f706e665b4f43424344454545464646464a5663707d8996a3b0a5988b7e7265584c3f3225190c0000000000000000000000000000000714202c3945515e6a76838f9ba79e9285796d6054483b2f23170a00000000000000000013202c3946535f6c798693a0a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a9acacacacaca8a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a69b8e8174675b4e4134281b0e0013202c3946535f6c798693a0acaca09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1acaa9e9184776a5d5144372a1e1100000000000007121d28333e48535e69747f8a95a0aba1968b80756a5f54493e322728333e49545f6a75808b96a1aba0958b80756a5f54493e33281d120700000000000000000000000e1a2734404d5a6773808d99a6b1a4988b7e7165584b3f414b555e68727b858f99a1978d847a7067707d8a96a3b0a89b8e8275685b4f4235281c0f0200000000000000000000000000000000020c16202a343e48525c67717b858f99a3a99f958b81766c62584e443a30261c110700000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f534b4b4b4b4b4b4b4b4b4b4b4b4c4c4e5052555a5f656d757e89939ea9a59b91867b6f64584c4034281c1004000714212e3a4754616d7a8794a1a5998c7f7265594c3f3226190c000000000000000000000000000000000000000000000916222f3c4955626f7a82899193939393938d837a71685e554c433a30271e150c020000000000000000000000000000000000000000000000000000101c2935414c57606566666666666666666660574f4f4f4f4f4f4d484138343d454b4f4f4f4f4f4f505a62666666666666666666645c52473c3024170b0000000001080f171e252d343b434a515960676e767d858a8a8a8a83776a5d5044372a1d110000000000000000000005111e2a36434f5b66727e89949a90878079757373777c848c96988e83776c6054483c3024170b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111d2a36424e5962686969696969645c51453d49555f676969696969675f554a3e32261a0d010000000000000000020c141c23292d2f2f2f2f2f2f2f2f2f2f2d2a292d2f2f2f2f2f2f2f2f2f2f2d29241d150d03000000000000000000000000000000000000000000000000000000121f2c3845525e6a737575757575757576828f9b918578757575757575757575757575757884919d908477757575757575757575757573695d5044372b1e11050000000006121f2c3845515d697275767778797a7c7d776b5e52453936373838383939393f4c5865717e8b97a4b0a4978a7e7164574b3e3125180b0000000000000000000000000000000b1723303c4855616d7986929fa79b8e8276695d5144382c1f130700000000000000000013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09b8e8174675b4e4134281b0e0013202c3946535f6c798693a0a0a0a09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a0a0a09e9184776a5d5144372a1e110000000000030d18232e39444f5a65707b86919ca7a69b90857a6e63584d42372c21212c38434e59646f7a85909ba6a79c91867b70655a50453a2f24190e03000000000000000000000c1926333f4c5965727e8b98a5b1a6998c8073665a4d4039434d56606a737d87909a9f968c83796f717e8b98a4b1a6998d8073675a4d4134271b0e010000000000000000000000000000000000040e18222c36404b555f69737d87919ba5a79d93887e746a60564c42382d23190f05000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5858585858585858585858585858595a5c5f62666a70777e87919aa5a69d93897f74695e53473c3024180c00000815212e3b4854616e7b8794a1a6998c7f7366594c403326190d000000000000000000000000000000000000000000000916222f3c4955626f7c8686868686868686847a71685f564c433a31281e150c030000000000000000000000000000000000000000000000000000000c1824303a454e555959595959595959595a5c5c5c5c5c5c5c5c59534a403b464f575b5c5c5c5c5c5c5c5b59595959595959595958524a41362b1f1408000000030b131a212930373e464d545c636a727980888f96958c837970665b4f4236291c1000000000000000000000020e1a26323e4a56616c77828c9699918a8581808183888e969a91877c71665b4f44382c2014080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000131f2c3945525e6a7476767676766d625649404d596671767676767671665a4e4236291d110500000000000000000a141e262e34393b3c3c3c3c3c3c3c3c3b393535393b3c3c3c3c3c3c3c3c3b39352f271f150b00000000000000000000000000000000000000000000000000000013202c3946535f6c798282828282828282838e9a9487828282828282828282828282828282838f9c9387828282828282828282828282786b5e5145382b1e1205000000000613202c3946535f6c7982838485868788867a6d6154483c33302f2e2e2f3238434f5b6774818d99a6afa295897c7063564a3d3024170a0000000000000000000000000000020e1a27333f4c5864717d8996a2a3978b7e72665a4d4135281c100400000000000000000013202c3946535f6c7986939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393938e8174675b4e4134281b0e0013202c3946535f6c798693939393939386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8893939393939184776a5d5144372a1e11000000000009141f2a35404b56616b76818c97a2aba094897e73685d52473c31261b1b26313c47525d68737e8a94a0aba3988d82776c61564b40352a1f150a000000000000000000000b1824313e4a5764707d8996a3afa79b8e8275685c4f43363b444e58616b757e88929b9e948b817773808d99a6b1a4988b7e7265594c3f3326190d0000000000000000000000000000000000000006101a242f39434d57616b758089949ea8a49a90867c72685e54493f352b21170d030000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c6565656565656565656565656565656667696b6e72767b82899199a2a49c948b81776d63584d42362b1f130800000815222e3b4855616e7b8894a1a6998c807366594c4033261a0d000000000000000000000000000000000000000000000916222f3c4855616e7879797979797979797971685f564d433a31281f160c030000000000000000000000000000000000000000000000000000000008131e29333c43494c4d4d4d4d4d4d535d656969696969696969655c5247414c576167696969696969696761574d4d4d4d4d4d4d4b4741382f241a0e030000030c151d242c333a424950585f666d757c838b9299968c837a71675e554a3e33261a0e00000000000000000000000a16222e3945505b66707a848d959c96918e8c8d8f93999991887e756a60554a3e33271c1004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c79838383837e7266594d414e5b67748183838383766a5e5246392d2115090000000000000006111c263038404548484848484848484848464140454848484848484848484845403931271d1207000000000000000000000000000000000000000000000000000013202c3946535f6c79868f8f8f8f8f8f8f8f949e99918f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f95a098918f8f8f8f8f8f8f8f8f8f8f85786b5e5145382b1e12050000000005121f2b3844515e6a76838f9092939495897d7165594e44403d3b3b3b3c3e424a54606b7784909ca9ac9f93877a6e6154483b2f221509000000000000000000000000000005111e2a36434f5b6874808d99a5a094887b6f63564a3e3125190c0000000000000000000013202c3946535f6c798686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868174675b4e4134281b0e0013202c3946535f6c798686868686868686796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8686868686868684776a5d5144372a1e110000000005101b26303b46515c67727d88939ea9a4998e83786d62574c41362b1f1415202b36414c57626d78838e99a4a99e93897d73685d52473c31261b10050000000000000000000916232f3c4855626e7b8794a0ada99d9084776b5e524539323c464f59636c768089939d9d93898076828f9ba8afa296897c7063574a3e3124180b000000000000000000000000000000000000000008131d27313b454f59636d77828c96a0aaa2988e847a70655b51473d33291f150a0000000000000000000000000000000000000013202c3946535f6c798693a0acaca093867971717171717171717171717171717172737475787a7e82878d939ba3a09a928a82796f655b51463b30251a0e0300000815222e3b4855616e7b8895a2a69a8d807366594d4033261a0d000000000000000000000000000000000000000000000714202d3945515c666c6c6c6c6c6c6c6c6c6c685f564d443b31281f160d040000000000000000000000000000000000000000000000000000000000020d17212a32383d4040404040404b58646f75757575757575756e63574b44515d69737575757575757573695d504440404040403f3b362f261d13080000000a151e272f363d454c535b6269717880878e959d968d847a71685f554c43382d22160a000000000000000000000005111d28333f49545e68727b838b92979b9a999a9b99948e877e766c63594e44392d22160b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000121f2b3844515e6a778490908e8275695d51454c5966727f8c9090867a6e6255493d3125180c000000000000000b17222d38424a5155555555555555555555524c4b5155555555555555555555514b43392e23180c000000000000000000000000000000000000000000000000000013202c3946535f6c7986939c9c9c9c9c9c9c9da0a29d9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9da1a29d9c9c9c9c9c9c9c9c9c9c9285786b5e5145382b1e12050000000003101c2935424e5b6773808c989ea0a1998d81756a5f56504c49484848484a4e545c66717c8894a0aca89c9084776b5e5246392d20130700000000000000000000000000000815212d3a46525f6b7784909ca99d9084786b5f53473a2e22150900000000000000000000131f2c3946525f6b767979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797972675a4d4134271b0e00131f2c3946525f6b767979797979797979766b5f5346392d201306000000000000000000000000000814212e3a4754606d77797979797979797975695d5044372a1d11000000000b16212c37424d58636e79848f99a4a99e93887d72675b50453a2f24190e0e19242f3a45505b67727d88939ea9a59a8f84796e63584d43382d22170c0100000000000000000714212d3a46535f6c7885919eaaac9f93877a6e6155493d31343d47515a646e77818b949e9b92887e85919daaaca093877a6e6155483b2f2216090000000000000000000000000000000000000000010b151f29333d47515c66707a848e98a2aaa0968c81776d63594f453b31261c120800000000000000000000000000000000000013202c3946535f6c798693a0acaca093867e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e80818284878a8e92989e9f9a958f88817870675d544a3f352a1f14090000000915222f3c4855626f7b8895a2a79a8d8173675a4d4034271a0d0100000000000000000000000000000000000000000005111d2935404b545b5f5f5f5f5f5f5f5f5f5f5d564e443b32291f160d0400000000000000000000000000000000000000000000000000000000000000050f1820272d313333333333404c596673808282828282827e7265584c45525f6b7882828282828282786b5e51453833333333322f2b241d140b01000006111c27303941484f565e656c747b828a9198a0968d847a71685f564d433a31271c11050000000000000000000000000c17222d38424c566069717980878b8f919292908d89837c756c645b51473c32271c1105000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101d2a3643505c6975828f9c9285796d6155484b5764717d8a97968a7e7265594d4135281c10040000000000000f1b27333f4a545c616262626262626262625d56545d616262626262626262615d554b4034281c10040000000000000000000000000000000000000000000000000013202c3946535f6c7986909090909090909090959f9a929090909090909090909090909090909196a099929090909090909090909085786b5e5145382b1e120500000000000d1a26333f4b5764707c88949faba99e92877c7168615c585655545455575a5f656e78828d99a4afa3988c8074675b4f43362a1d110500000000000000000000000000000c1824313d4956626e7a8793a0a6998d8174685c5043372b1e120600000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6961564a3e3226190d00111e2a37434f5a646b6c6c6c6c6c6c6c6c6b645a4f43372b1e12050000000000000000000000000006131f2c3844505b656c6c6c6c6c6c6c6c6c6a63584d4135281c0f00000007121d28333e49535e69747f8a95a0aba3988d82766b60554a3f34291e130808131e29343f4a55606b76818c97a2aba1968b80756a5f54493e33281d1308000000000000000005121e2b3744505c6975828e9aa6afa2968a7d7165594d41362b353f48525c656f79828c969f9a90878894a0ada99d9084776b5f5246392d201407000000000000000000000000000000000000000000030d17212b35404a545e68727c86909aa5a89d93897f756b61574d42382e241a1006000000000000000000000000000000000013202c3946535f6c798693a0acaea2968d8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8c8c8d8f9193969a9d9a97938f8a847d766e665e554b42382d23180d020000000916222f3c4955626f7c8995a2a79a8d8174675a4d4134271a0e01000000000000000000000000000000000000000000010d18242e39424a5053535353535353535353514c443c322920170d04000000000000000000000000000000000000000000000000000000000000000000060e151c21242626262633404c596673808c8f8f8f8f8c7e7265584c45525f6b78858f8f8f8f8f85786b5e5145382b26262626231f19130b020000000b17232e38424b525a616870777e868d949ca0978e847b72685f564d443a31281f150b0000000000000000000000000006111b26303b444e575f676f757b808385868584817d78726b635b52493f352b20160b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1b2835414e5b6774818d9a95897d7165584c4956636f7c89959a8e8275695d5145382c201408000000000000121e2b3743505b666d6f6f6f6f6f6f6f6f6e685d5c666e6f6f6f6f6f6f6f6f6e675c5145382c1f13060000000000000000000000000000000000000000000000000013202c3946535f6c79848484848484848484848e9a9589848484848484848484848484848484848f9c93878484848484848484848484786b5e5145382b1e120500000000000a17232f3b47545f6b77838e99a4aea3988d837a726c6865636161616263666a7077808a949faaa99e92877b6f63574b3f33271a0e0200000000000000000000000000030f1b2834404d5965727e8a97a3a2968a7d7165594c4034271b0f02000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5d574f44392e22160a000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5a52493e33271b0f020000000000000000000000000004101c28343f4a535b5f5f5f5f5f5f5f5f5f5e5951473c3025190c0000030e18232e39444f5a65707b86919ca7a79c91867b70655a4f44392e23170c01010d18232e39444f5a65707b86919ca7a79c91867b70665b50453a2f24190e0300000000000000030f1b2834414d5966727e8a96a3afa69a8d82756a5e52473c322d36404a535d67707a848d97a19992929aa4b0a5998d8174685c4f43362a1e110500000000000000000000000000000000000000000000050f19242e38424c56606a747e89939da7a59b91877d73695e544a40362c22180e040000000000000000000000000000000013202c3946535f6c798693a0acb3a89f999898989898989898989898989898989898999a9b9d9c9592908e8b87837e78726c645d544c433930261c110700000000091623303c4956626f7c8996a2a79a8e8174675a4e4134281b0e010000000000000000000000000000000000000000000007121d2730383f444646464646464646464644403a322a20170e050000000000000000000000000000000000000000000000000000000000000000000000040b101518191a1a2633404c596673808c999c9c988c7e7265584c45525f6b7885929c9c9c9285786b5e5145382b1e1a1a1917130e0801000000000f1b28333f4a545d646b737a818990979fa0978e857b726960574d443b32281f160d0300000000000000000000000000000a141f29323c454d555d646a6f73767879797775716c676059514940362d23190f04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1a2633404c5966727f8c98998d8174685c504854616e7a87949e9285796d6154483c3024170b00000000000013202c3946525f6c787b7b7b7b7b7b7b7b7a6e62606d787b7b7b7b7b7b7b7b796d6054473a2e21140700000000000000000000000000000000000000000000000000131f2c3945525e6a747777777777777777777e8b9795897c7777777777777777777777777777808d9994877b7777777777777777777774695d5144372b1e1105000000000007131f2b37434f5b66727d88939da7aa9f958c847d7874716f6e6e6e6e7072767b8289929ba6aba1978c81766a5f53473b2f23170b000000000000000000000000000006121f2b3744505c6975818e9aa69f93867a6e6155493d3024180b00000000000000000000000a16212c3740484f5253535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353514d453d33281d1106000a16212c3740484f525353535353535353524f4940372c21160a0000000000000000000000000000000c17232d3841494f525353535353535353524e473f352a1f1408000009141f2a35404b56616c76828c97a2aca1968b80756a5f54483d32271c1106000006111c27323d48535e6974808b96a1aca3988d82776c61564b40352b20150a00000000000000000c1825313d4a56626e7a86929eaaaa9e92867a6f64594e443c363238414b555e68727b858f98a29e9ea3acada195897d7164584c4033271b0e02000000000000000000000000000000000000000000000008121c26303a444e58626c76818b959fa9a3998f857a70665c52483e342a20150b0100000000000000000000000000000013202c3946535f6c798693a0acb9b1a9a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a6a6a8a1958a8684817e7b77726d67615a524b423a31271e140a00000000000a1623303c4956636f7c8996a3a89b8e8174675b4e4134281b0e0200000000000000000000000000000000000000000000000b151e262e33373939393939393939393938352f2920170e05000000000000000000000000000000000000000000000000000000000000000000000000000004090b0d0d192633404c596673808c99a6a5988c7e7265584c45525f6b7885929fa99e9285786b5e5145382b1e120d0c0a0703000000000000121e2b3744505c666e767d858c939aa0a0978e857c736960574e453b322920160d04000000000000000000000000000000030d17202a333b434b52595e63676a6b6c6c6b6865615b554e473f362e241b110700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1825323e4b5764717d8a979d9184786c605447535f6c7986929f95897d7164584c4034271b0f03000000000013202c3946535f6c7986888888888888887b6f62606d7a87888888888888877a6d6154473a2e21140700000000000000000000000000000000000000000000000000111d2a36424e5962696a6a6a6a6a6a6a6a6f7c8895988c7f736a6a6a6a6a6a6a6a6a6a6a6a717d8a96968a7d716a6a6a6a6a6a6a6a6a6862584d4135281c10030000000000030f1b27323e4a55606c76818b959ea7a89e968f8984817e7c7b7a7b7b7d7f82878c939ba4aba2998f857b7065594e42372b1f130700000000000000000000000000000916222e3b4753606c7885919da89c8f83776a5e5245392d211408000000000000000000000005101a252e373e43464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464645413b342b21160c000005101a252e373e4346464646464646464646433e372e251b100500000000000000000000000000000006111c262f383e4346464646464646464645423d352d23190e030005101b26313b46515c67727d88939ea9a69b9085796e63584d42372c21160b000000000b16212c37424d58636e79848f9aa5a99e94897e73685d52473c31261b1005000000000000000915212d3a46525e6a76828d99a5aea3978c80756a60564e47423e3c3c434c566069737d87909aa3abafb3a89c9185796d6154483c3024170b000000000000000000000000000000000000000000000000000a141e28323c46505b656f79838d97a1aba1968c82786e645a50463b31271d130900000000000000000000000000000013202c3946535f6c798693a0acb5aba39e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9fa1a3a5a1958984817c78726c66615c564f48413930281f150c0200000000000a1723303d4a5663707d8a96a3a89b8e8275685b4e4235281b0f020000000000000000000000000000000000000000000000030c141c22272b2c2c2c2c2c2c2c2c2c2c2b29241e170e05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d192633404c596673808c99a6a5988c7e7265584c45525f6b7885929fab9e9285786b5e5145382b1e12050000000000000000000013202c3946535f6c7880888f93939393938f857c736a61574e453c332920170e040000000000000000000000000000000000050e182129323941474d53575b5d5f5f5f5e5c5955504a443d352d241b12090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1723303d4956636f7c8995a194887c7063574b515e6b7784919d998d8174685c5043372b1f1306000000000013202c3946535f6c7986939595959595887b6f62606d7a87949595959594877a6d6154473a2e211407000000000000000000000000000000000000000000000000000e1a26313c4750585c5d5d5d5d5d5d5d606d7986929b8e8275695d5d5d5d5d5d5d5d5d5d626e7b8794998d8073675d5d5d5d5d5d5d5d5c5750463b3024190c000000000000000a16222d39444f5a656f79838c959ca3a8a09a94908d8b8988878788898b8e93989ea5a8a19990877d73695e53483d31261a0e0200000000000000000000000000000d1925323e4a57636f7b8894a1a5988c8073675b4e42362a1d110500000000000000000000000009131c252c323739393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393835302922190f0500000009131c252c32373939393939393939393937322c251c130900000000000000000000000000000000000a141d262d33373939393939393939393936312b231b110700000a16212c37424d58636e79848f9aa4aa9f94897e73685d52473c31261b100400000000040f1a25313c47525d68737e89949faaa59a8f84796e63584e43382d22160b0000000000000005111d2a36424e5965717c88949faaa89d91877c72686058524e4b4948494a4e57616b747e88929ca8b5ada2978b8074685c5044382c20140800000000000000000000000000000000000000000000000000020c16202a353f49535d67717b858f99a4a89e948a80766c62574d43392f251b1107000000000000000000000000000013202c3946535f6c798693a0acb0a4999291919191919191919191919191919192939496999c9b94908d88837e77706961584f463c32281e160d030000000000000a1724303d4a5763707d8a96a3a89b8e8275685b4f4235281c0f02000000000000000000000000000000000000000000000000020a11171b1e202020202020202020201f1c18130c0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d192633404c596673808c99a0a0988c7e7265584c45525f6b7885929fa09e9285786b5e5145382b1e12050000000000000000000013202c3946535f6c798686868686868686867c736a61574e453c332a20170e0500000000000000000000000000000000000000060f1720272f363c42474b4e51525352514f4c49443f39322b231b1209000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000815222e3b4854616e7a8794a0988c8073675b4f505c6976828f9c9d9084786c5f53473b2f23160a000000000013202c3946535f6c798693a0a2a2a295887b6f62606d7a8794a0a2a2a194877a6d6154473a2e211407000000000000000000000000000000000000000000000000000915202b353e464c50505050505050515d6a76838f9c9185786c5f5350505050505050535f6c7885919c8f83766a5d51505050505050504c463e342a1f14080000000000000005111c27333e48535d67717a838b92989ea3a5a09c9997969494949596989b9ea3a7a29d968f877e756b62574d42372c201509000000000000000000000000000004101c2935414e5a66737f8b98a4a195897c7064574b3f32261a0e01000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c29251f18100700000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2a27211b130a010000000000000000000000000000000000020b141b22272b2c2c2c2c2c2c2c2c2c2c2a26201911090000000e1a26323e49545e6974808a95a0a0a0998e83786d62574c40352a1f140900000000000009141f2a35404b56616c77828d99a0a0a0968b80756a5f54493e33271b0f02000000000000010d1925313d4954606b77828d98a3ada3988e847a726a635e5a5756555557595c61676f77818d9aa7b4a79c91867a6f63574c4034291f160c0200000000000000000000000000000000000000000000000000040e19232d37414b555f69737d88929ca6a69c92887e73695f554b41372d23190e040000000000000000000000000013202c3946535f6c798693a0acada093888484848484848484848484848484848586888a8d90959a9d99948f89827b736a61584e44392f24190e030000000000000b1724313e4a5764707d8a97a4a89c8f8275685c4f4236291c0f030000000000000000000000000000000000000000000000000000060b0f121313131313131313131312100c07010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d192633404c596673808c939393938c7e7265584c45525f6b7885929393939285786b5e5145382b1e120500000000000000000000131f2c3946525f6b76797979797979797979746a61584f463c332a21180e05000000000000000000000000000000000000000000050e161d242b31363b3f42444546464543403d38332e272019110900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000714202d3a46535f6c7986929f9c9083776b5f534e5b6774818d9aa094887c6f63574b3f33261a0e020000000013202c3946535f6c798693a0acafa295887b6f62606d7a8794a0adaea194877a6d6154473a2e21140700000000000000000000000000000000000000000000000000030e19232c353b40434444444444444e5b6774818d9994877b6e625549444444444444505c6975828f9b9285796c605347444444444443403b342c22180d0200000000000000000b16212c37414b555f68717980878d93979b9fa1a4a4a2a1a1a1a1a2a4a4a19e9b96918b857d756c635a50453b30251a0f0400000000000000000000000000000713202c3845515d6a76828f9ba79e9285796d6054483b2f23160a0000000000000000000000000000010910161a1e1f202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201f1d19140d06000000000000010910161a1e1f20202020202020201f1e1b1610090100000000000000000000000000000000000000020a11161b1e2020202020202020201f1d1a150f0700000000111e2a36434f5a65707b86919393939393887c71665b50453a2f24190e03000000000000030e19242f3a45505b66717c87929393939391877b71665b4f43372b1e1205000000000000000915212c38444f5a66717c87919ba5aaa0968c847c756f6a66646362626365686d7279818a939da9b2a5988c80756b62584e453b31281e140b010000000000000000000000000000000000000000000000000007111b252f39434d57616c76808a949ea8a49a8f857b71675d53493f352a20160c0200000000000000000000000013202c3946535f6c798693a0acaca0938679777777777777777777777777777778797b7d8184898f959ca09a948d857c736a60564b40362b1f14080000000000000b1724313e4a5764717d8a97a4a99c8f8275695c4f4236291c0f030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d192633404c596673808686868686867e7265584c45525f6b7885868686868685786b5e5145382b1e120500000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6a62584f463d342a21180f060000000000000000000000000000000000000000000000040b131920252a2f323537393939383634302c28221c160f0700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005121f2b3845515e6b7784919d9f93877b6f62564d5966727f8c98a4988c8073675b4f42362a1e12050000000013202c3946535f6c798693a0acaca295887b6f62606d7a8794a0adaca194877a6d6154473a2e211407000000000000000000000000000000000000000000000000000007111a232a30343637373737373f4c5865717d8a97968a7d7165584c3f37373737414d5a6673808c9894887b6f6256493d3737373736343029221a100600000000000000000005101a252f39434d565f676e757c82878b8f929597989a9a9b9b9b9a999795928f8b86807a736b635a51483e34291f14090000000000000000000000000000000a17232f3c4854616d7986929ea79b8e8275695d5144382c1f130700000000000000000000000000000000050a0e11131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131312100d0802000000000000000000050a0e1113131313131313131313110e0a050000000000000000000000000000000000000000000000050b0f1113131313131313131313110e09040000000000121f2c3945525f6b76828686868686868681766b60554a3f34291e1308000000000000000007121d28333e4954606b76818686868686868682776c5f5346392d2013060000000000000004101b27323e49545f6a758089939da6a89e968e86807a7673716f6f6f707274787d848b939ca5aba7a79b91877d746a60574d433a30261d1309000000000000000000000000000000000000000000000000000009131d27313b45505a646e78828c96a0aaa1978d83796f655b51463c32281e140a00000000000000000000000013202c3946535f6c798693a0acaca09386796c6a6a6a6a6a6a6a6a6a6a6a6a6b6b6d6e7174787d848b939ba59e978e857c72675d52473c3025190e0200000000000b1824313e4b5764717e8b98a4a99c908376695c4f4336291c1003000000000000000000000000000000000000000000000000000000000000000002040608090a0b0b0c0c0c0b0b0a08070503010000000000000000000000000000000000000000000000000000000000000000000000000000000c1926333f4c58657179797979797979797064584b45515e6a7679797979797979756a5e5144382b1e1205000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5e5850463d342b22180f060000000000000000000000000000000000000000000000000001080e141a1e2326292b2c2c2c2b2a2724201c17110b040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003101d2a3643505c6976828f9ca3978b7e72665a4e5864717d8a97a49c8f83776b5e52463a2e2215090000000013202c3946535f6c798693a0a2a0a095887b6f62606d7a8794a0a2a0a094877a6d6154473a2e2114070000000000000000000000000000000000000000000000000000000811181f24282a2a2a2a2a303d4956626e7b8794998d8174675b4e42352a2a323e4b5764707d8996978b7e7265594c40332a2a2a2a28241e181007000000000000000000000009131e28313b444c555d646b70767b7f8386888a8c8d8e8e8e8e8d8c8b8886837e7a756f68615951483f362c22180d020000000000000000000000000000010e1a26333f4b5864707d8995a2a3978b7e72665a4d4135281c100300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000121f2c3845525e6b7679797979797979797970655a4f44392d22170c010000000000000000010c17222d38434e59646f787979797979797979766b5f5346392d20130600000000000000000b16212d38434e59636d77818b949ca4a89f98918b8682807d7c7b7c7d7e8184898f959da5a79f9b9ba1998f867c72695f554c42382f251b120800000000000000000000000000000000000000000000000000010b151f29343e48525c66707a848e99a3a99f958b81776c62584e443a30261c1207000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5d5d5d5d5d5d5d5d5d5d5e5e5f606264686c72798189939da7a0978e84796e63584d41362a1e120600000000000b1825323e4b5865717e8b98a4a99c908376695d5043362a1d1003000000000000000000000000000000000000000000000000000000000306090c0e11131416171818191918181716151412100d0b08040100000000000000000000000000000000000000000000000000000000000000000000000b1724303d49545f686c6c6c6c6c6c6c6c685f5448424e59646b6c6c6c6c6c6c6c6b63594e4235291d1003000000000000000000000a16212c3740484f52535353535353535353524d463e342b221910060000000000000000000000000000000000000000000000000000000003090e12161a1c1e1f201f1f1d1b1814100b06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2835424e5b6774818d9aa79b8e82766a5e5156636f7c8995a29f93877b6e62564a3e3125190d0100000013202c3946535f6c7986939f96939393887b6f62606d7a87949e96939393877a6d6154473a2e21140700000000000000000000000000000000000000000000000000000000070e14181b1d1d1d1d212d3a46535f6c7885919c8f83766a5e5145382c232f3c4855616e7a87939a8d8174685b4f4236291d1d1d1c1c1a17120c0600000000000000000000010c16212b343c434b52595f656a6f7376797c7d7f818182828181807e7c7976726e69635d564f473f362d241a100600000000000000000000000000000005111d2a36424f5b6774808c99a5a094877b6f63564a3e3125190c00000000000000000000000000000000000005090c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0c090500000000000000000000000000040708080808080808080808070400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111d2a36424e5a646b6c6c6c6c6c6c6c6c6c675e53483d32271c11060000000000000000000006111c27323d48535e676c6c6c6c6c6c6c6c6c6b645a4f43372b1e1205000000000000000005101b26313c47515c666f78828a929aa0a7a39c97928f8c8a898888898b8d91959aa0a7a39c958e9098a1988e847a71675e544a41372d241a100600000000000000000000000000000000000000000000000000030e18222c36404a545e68727c87919ba5a79d93897e746a60564c42382e23190f050000000000000000000013202c3946535f6c798693a0acaca09386796c5f535151515151515151515151525355585c61676f77818b96a1a9a0958b8075695e52463b2e22160a00000000000c1825323f4b5865727e8b98a5aa9d9083766a5d5043372a1d11040000000000000000000000000000000000000000000000000002070b0f1215181b1d1f212224242525252525242322201e1c1a1714110d09050000000000000000000000000000000000000000000000000000000000000000000814202c38434d565d5f5f5f5f5f5f5f5f5d564d423d48525a5f5f5f5f5f5f5f5f5e5951473d3125190d010000000000000000000005101a252e373e434646464646464646464645423c342c221910070000000000000000000000000000000000000000000000000000000000000002060a0d101112131312100e0b08040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1a2733404d5966737f8c99a59e92867a6d615555616e7a8794a1a3978b7e72665a4d4135291d110400000013202c3946535f6c798692998d868686867b6f62606d798693988d868686867a6d6154473a2e2114070000000000000000000000000000000000000000000000000000000000060e161d22262828282b3744505d6976828f9b9286796d6054473b2e282d3946525e6b7784909c9083776a5e5145382c282828282826231e17100700000000000000000005111c28333d464e535555555a5e63676a6d6f717273747575747473716f6d6a66625d585555524d453b31261a0f030000000000000000000000000000000814212d3946525e6b7783909ca89d9084786b5f53473a2e22150900000000000000000000000000000000040b1115181a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1816110b05000000000000000000060c10131515151515151515151513100c0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1a26323d48525a5f5f5f5f5f5f5f5f5f5f5c554c42372c21160b0000000000000000000000000a15202b36414c555c5f5f5f5f5f5f5f5f5f5f5a52493e33271b0f020000000000000000000a15202b353f4a545d666f7880888f959ba0a4a39e9b989796959596979a9da1a6a29d98928b83869099a0968d83796f665c53493f362c22180d020000000000000000000000000000000000000000000000000006101a242e38424c56616b757f89939da7a59a90867c72685e544a3f352b21170d0300000000000000000013202c3946535f6c798693a0acaca09386796c5f5346444444444444444444444547494c50565d656f7985909ca7a79c91867a6f63574b3f32261a0e01000000000c1925323f4c5865727e8c98a5aa9d9084776a5d5044372a1d1104000000000000000000000000000000000000000000000004090e13171b1f2225272a2c2e2f3031323232323231302e2d2b292623201d1915110c070200000000000000000000000000000000000000000000000000000000000004101b27313b444c515353535353535353514b443b3640484e5253535353535353524e483f362b20150900000000000000000000000009131c252c3237393939393939393939393836312a221a100700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1825323e4b5864717e8a97a4a2968a7d71655953606c7986929fa79a8e82766a5d5145392d201408000000121f2c3945525f6b788592988c7f797979786d615f6c798692988b7e797979776c6053473a2d21140700000000000000000000000000000000000000000000000000000000050f1820282e323535353535414e5a6773808c9995887c6f63564a3e35353536434f5c6875818e9a9286796d6154483b353535353535332f292219100700000000000000000915212d39444f585f6262626262615b5e60626466676768686767666563605d6162626262625e574d42372b1f13060000000000000000000000000000000b1824303d4955626e7a87939fa6998d8174685c4f43372b1e1206000000000000000000000000000000060e161c21252727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272725221d160f07000000000000020a11181c2021222222222222222221201c18110a020000000000000000000000000000000000000000000000000000000000000000000000000000000000000a15212c3640484f52535353535353535353504b433a30251a0f04000000000000000000000000040f1a25303a434b50535353535353535353524f4940372c21160a00000000000000000000030e19232e38424b545d666e767d848a8f94989c9fa1a2a3a2a2a2a3a3a19f9d9a96918c8780797e87919b9f958b82786e655b51483e34291e1307000000000000000000000000000000000000000000000000000008121c26303a454f59636d77818b959fa9a2988e847a70665b51473d33291f150b01000000000000000013202c3946535f6c798693a0acaca09386796c5f534639373737373737373838393a3c40444b535d68737f8b97a3aea3978b7f73675b4e4236291d1104000000000c1926323f4c5965727f8c99a6aa9e9184776a5d5144372a1e1104000000000000000000000000000000000000000000040a10151a1f23272b2e313436393a3c3d3e3e3f3f3f3e3e3d3b3a383533302d2925211d18130d070100000000000000000000000000000000000000000000000000000000000a152029323a4044464646464646464644403a322e363d43454646464646464645423d362d24190f04000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c29251f1810070000000000000000000000000000000000000000000000000000000000000000000001040608090b0c0c0d0d0d0d0d0c0b0a080604020000000000000000000000000000000000000000000000000000000000000000000000000000000003060809090909090909090907040000000000000000000000000000000000000000000000000000000000000000000a1723303d4956636f7c8995a2a69a8d8175695d515e6b7784919daa9e92867a6d6155493d3024180c000000121e2b3844515e6a778491998d80736c6c6c665c5e6b788591988c7f726c6c6b655b5044382b1f1206000000000000000000000000000000000000000000000000000000010c16212a32393e4142424242424b5764707d8996988b7e7266594d4242424242424d5966727e8b9895897c7063574a424242424242423f3a342b22180e03000000000000000b1824313d4a55616a6f6f6f6f6f6d665e575658595a5b5b5b5b5a59585860676e6f6f6f6f6e695f53473b2f2216090000000000000000000000000000020f1b2734404c5965717d8a96a3a2968a7d7165584c4033271b0f020000000000000000000000000000050f1820272d3133343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343433312e282119100600000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2c28231c140b020000000000000000000000000000000000000000000000000000000000000000000000000000000000040f1a242e363d434646464646464646464644403931281e1409000000000000000000000000000008131e2831393f4446464646464646464646433e372e251b1005000000000000000000000007121c263039424b545c646c73797e84888c8f9294969798989897969593908d8a86817b756e757f89929c9d948a80766d635a50463b2f23170b00000000000000000004080b0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d141e29333d47515b656f79838e98a2aaa0968c82776d63594f453b31271c1208000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2a2a2a2a2a2a2b2b2c2d303439414c57636f7b8794a0ada79b8f83776a5e5245392c1f1306000000000d192633404c596673808c99a6aa9e9184776b5e5144382b1e110500000000000000000000000000000000000000030910161b21262b2f33373b3e40434547484a4b4b4c4c4b4b4a49484644423f3c3935312d28231e18130d0600000000000000000000000000000000000000000000000000000000030e1720292f3538393939393939393938342f28242c323639393939393939393936322b241b12080000000000000000000000000000010910161a1e1f2020202020202020201f1d19140e06000000000000000000000000000000000000000000000000000000000000000004080b0e101214161718191a1a1a1a191918161513110e0b07040000000000000000000000000000000000000000000000000000000000000000000000040a0f131516161616161616161514100c06000000000000000000000000000000000000000000000000000000000000000915222f3b4855616e7b8794a1aa9d9185796c60545c6976828f9ca8a2968a7d7165594c4034281c0f030000101d2a3643505c6976828f9b8e8275685f5f5b545d6a7683909a8d8174685f5f5b53493f33281c0f0300000000000000000000000000000000000000000000000000000007121d28323c444a4e4f4f4f4f4f4f55616e7a87939a8e8175685c4f4f4f4f4f4f4f4f57636f7c8995988b7e7266594f4f4f4f4f4f4f4e4b453e342a1f1409000000000000000c1926333f4c5965727b7b7b7b7b787069615a524c4d4e4e4e4e4d525a626a72797b7b7b7b7b7063564a3d3024170a000000000000000000000000000006121e2b3743505c6875818d9aa69f93867a6e6155493c3024180b0000000000000000000000000000020d17212a32393d404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040403e39332b22180e030000000a141d262e34383b3b3b3b3b3b3b3b3b3b38342e261d140a00000000000000000000000000000000000000000000000000000000000000000000000000000000000008121c242c32363939393939393939393938342f281f160d020000000000000000000000000000020c161f272e34383939393939393939393937322c251c1309000000000000000000000000000a141e273039424a525a61676d73787c80838688898a8b8b8b8a8a888684817d7975706a646d77818a93939392897f756b62574c3f33271a0e00000000000000030a101518191a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a212b353f49535d67717c86909aa4a89e93897f756b61574d43382e241a10060000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201e1e1e1e1e1e1e1f2123282f3a46535f6c7885919eabab9f93867a6d6054473b2e211508000000000d1a2633404d596673808c99a6ab9e9184776b5e5145382b1e1205000000000000000000000000000000000000070e141b21272c32373b3f43474a4d4f5254555657585858585857565453514e4c4945413d39342f2a241e18110a03000000000000000000000000000000000000000000000000000000050e171e24292b2c2c2c2c2c2c2c2c2b28241d1a21262a2c2c2c2c2c2c2c2c2c2a26211a12090000000000000000000000000000000000050a0e111313131313131313131312110d090300000000000000000000000000000000000000000000000000000000000002070c1014171a1d1f21232425262626262626252423211f1d1a1714100c070200000000000000000000000000000000000000000000000000000000000000070f151b1f22222222222222222222201c1711090100000000000000000000000000000000000000000000000000000000000714202d3a4653606c7986929faca195897c7064585b6874818e9aa7a6998d8175695c5044382c1f130700000f1c2835414e5b6774818d9a9184786b5f53504f5b6875818e9a9083776a5e524f4941372d22170b000000000000000000000000000000000000000000000000000000000b17232f3a444e565a5b5b5b5b5b5b5b5f6b7884919d9084786b5f5b5b5b5b5b5b5b5b5b606d7986929a8e8275685c5b5b5b5b5b5b5b5b5750463c3125190d010000000000000d192633404c5966738088888888827a736b645c554d4642454d555c646c747c84888888887d7063574a3d3024170a00000000000000000000000000000915222e3a47535f6c7884919da89c8f83776a5e5245392d211408000000000000000000000000000008131e29333c444a4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4a443d342a1f1409000006111c262f383f4548484848484848484848453f382f261c11060000000000000000000000000000000000000000000000000000000000000000000000000000000000000a121a21262a2c2c2c2c2c2c2c2c2c2c2b28231d160d0400000000000000000000000000000000040d151d23282b2c2c2c2c2c2c2c2c2c2c2a27211b130a0100000000000000000000000000020c151e27303941484f565c62676c707376797b7c7d7e7e7e7d7d7b7a7775716d69645f5b656e78828686868686867d74685b4f4235291c0f000000000000050e151b212426262626262626262626262626262626262626262d37414b56606a747e88929ca6a59b91877d73695f544a40362c22180e0400000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20131111111111121214171e2b3744505d6a7683909da9aea195887b6f6256493c2f231609000000000d1a2733404d596673808d9aa6ab9e9285786b5e5145382b1f120500000000000000000000000000000000020a11181f262c32383d42474b4f5356595c5e6062636465656565646463615f5d5b5855514d4945403b352f29231c150d06000000000000000000000000000000000000000000000000000000050c13181c1f20202020202020201f1c18120f151a1e1f202020202020201f1e1a150f08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080e13181c202427292c2e2f31323233333333333231302e2c2a2724201c17130d08010000000000000000000000000000000000000000000000000000000008111920272b2e2f2f2f2f2f2f2f2f2f2c28221b130a010000000000000000000000000000000000000000000000000000000006121f2c3845515e6b7784919daaa5998c8074685c596673808c99a5a99d9185786c6054483b2f23170b00000d1a26333f4c5865717e8a9794877b6f63574b4d5966727e8b9893877a6e62564a3e372f261b1106000000000000000000000000000000000000000000000000000000000f1b2734404b56606768686868686868686875828e9a93877a6e68686868686868686868686a7783909c9184786b68686868686868686761584d42362a1d11040000000000000c1925323f4b58646f78828c95948c857d766e675f5850494f575f676e767e868e95948a81766d6155493c3023160a00000000000000000000000000000c1925313e4a56636f7b8894a0a4988c8073675b4e4236291d110500000000000000000000000000000d1924303b454e55595a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a59564f463c31251a0e02000b17222d38424a5154555555555555555554514a42382d22170b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000810161a1e1f2020202020202020201f1c18120b04000000000000000000000000000000000000030b12171c1e2020202020202020201f1e1b16100901000000000000000000000000000000030c151e272f363e454b51565b6064676a6c6e707171717171706f6d6b6865615d5853535c6670787979797979797973685b4f4235291c0f0000000000040e171f272c31333333333333333333333333333333333333333333333a444e58626c76808a949ea9a3998f857a70665c52483e342a20160b01000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130b0b0b0b0b0c0d0e111d2936434f5c697683909ca9b0a3968a7d7063574a3d3024170a000000000d1a2734404d5a6773818d9aa7ac9f9285786b5f5245382c1f1205000000000000000000000000000000040c141c232a31373d43494e53575c5f6366686b6d6e70717172727171706f6e6c6a6764615e5a55514c46403a342d261f18100800000000000000000000000000000000000000000000000000000001070c1012131313131313131312100c07040a0e11131313131313131313110e0a04000000000000000000000000000000000000000000000000000005090c0e0e0e0e0e0e0e0e0e0e0c09050000000000000000000000000000000000000000000000060d13191f24282c303336383a3c3d3e3f40404040403f3e3c3b393633302c28231e19130d06000000000000000000000000000000000000000000000000000005101a232b32373b3c3c3c3c3c3c3c3c3b39342d251c13080000000000000000000000000000000000000000000000000000000003111d2a3743505d6976838f9ca9a89c9084786b5f5864717e8a97a4aca195887c7064584b3f33271b0e02000b1724303d4956626f7b8794978b8073685c504a57636f7c8894978a7e72675b4f44382d22170c0200000000000000000000000000000000000000000000000000000000101d2a3643505c6872757575757575757575757f8b9896897d7575757575757575757575757575818d9a93877a757575757575757575736a5e5245392c1f13060000000000000a17232f3b47525d66707a838d97978f8880787169625a53596169717880889098968c82786e655b5045392d2114080000000000000000000000000004101c2835414d5a66727e8b97a4a195897c7064574b3f32261a0e010000000000000000000000000000101c2935414c57606667676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676661584d42362a1e1105000f1b27333f4a545c616161616161616161615c544a3f33271b0f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0e111313131313131313131312100c0701000000000000000000000000000000000000000000060b0f1213131313131313131313110e0a05000000000000000000000000000000000000030c151d242c333a40454b4f54575b5d60626364646564646362605e5c5955514d484a545e676c6c6c6c6c6c6c6c6a62574b3f33271a0e00000000010c16202931383d40404040404040404040404040404040404040404040404046505a646e78838d97a1aba1978c82786e645a50463c32271d1309000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2018181818181819191b1d212a3743505d697683909ca9b0a4978a7d7063574a3d3024170a000000000e1a2734414d5a6774818e9aa7ac9f9286796c5f5246392c1f13060000000000000000000000000000050e161e262d353c42494f545a5f63686c6f727577797b7c7d7e7e7e7e7e7d7c7a797674716d6a66615c57514c453f38312a221a120a010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b1116191a1a1a1a1a1a1a1a1a1a1916110b0400000000000000000000000000000000000000020a11181f252a2f34383c3f424547494a4b4c4c4d4d4d4c4b4a494745423f3c38342f2a241e171009010000000000000000000000000000000000000000000000010c17222c353d4347494949494949494948453f372e241a0f04000000000000000000000000000000000000000000000000000000000f1c2835424e5b6874818e9aa0a0a094887b6f635763707c8996a0a0a0988c8074675b4f43372b1e1206000815212e3a46535f6b7784909b9084786d61564b54606c7885919b8f83776c60554a3e34291e130800000000000000000000000000000000000000000000000000000000111e2a3744515d6a7782828282828282828282828a97998c828282828282828282828282828282828c98968982828282828282828282796d6053463a2d20130700000000000007131f2b36414b545e68717b858e9899928a837b746c655d636b737b838a929a978e847a70665c53493f34281d11050000000000000000000000000007131f2c3844515d6976828e9ba79e9285796d6054483b2f23160a000000000000000000000000000000121f2c3845515d69727373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373726a5e5246392d20130700121e2b37434f5b666d6e6e6e6e6e6e6e6e6d665b4f43372b1e1205000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030b131a21282e343a3f44484b4e515355565758585857575554524f4c4945413c424c555c5f5f5f5f5f5f5f5f5e5850453a2f23170b0000000007121d28323b43494c4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d525c66717b858f99a3a89e948a80766c62584d43392f251b10050000000013202c3946535f6c798693a0acaca09386796c5f5346392c252525252525252526272a2d323a46525f6b7884919eaab0a3968a7d7063574a3d3024170a000000000e1b2834414e5b6774818e9aa7ac9f9286796c5f5346392c20130600000000000000000000000000060e17202830383f464d545a60656b6f74787b7e82848688898a8b8b8c8b8b8a89878583817d7a76726d68635d57504a433b342c241c130a01000000000000000000000000000000000004070808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080806020000000000000000000000070f161d22252727272727272727272725221d160f060000000000000000000000000000000000030c141b232930363b4044484c4f515355575859595959595958575654524f4c4844403b352f29221b130b030000000000000000000000000000000000000000000005111d28333e474e54555555555555555555504940362c201509000000000000000000000000000000000000000000000000000000000e1a2733404d596673808c93939393938b7f73675a616e7b8793939393939084776b5f53473a2e2115080005121e2a37434f5b67737f8b9795897e72675c51505c6874808c9894887d71665b50453a3025190e02000000000000000000000000000000000000000000000000000000111e2a3744515d6a77848f8f8f8f8f8f8f8f8f8f929b9d938f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f939c9b928f8f8f8f8f8f8f8f8f86796d6053463a2d201307000000000000020e19242f39424c565f69737c8690999c958d867e766f676d757d858d959c998f857c72685e544b41372d22170c00000000000000000000000000000a16232f3b4854606d7985929ea79a8e8275695d5144382c1f130700000000000000000000000000000013202c3946535f6c7981818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181817a6d6154473a2e2114070013202c3946525f6c777b7b7b7b7b7b7b7b776c5f5246392c20130600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000407080808080808080808080704000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010810171d23292e33373b3f424447484a4a4b4b4b4b4a49474543403d3935303a434b505353535353535353524d463e34291e1207000000000c18232f3a444d54595959595959595959595959595959595959595959595959595959595f69737d87919ba5a69c92887e74695f554b41372d22170b0000000013202c3946535f6c798693a0acaca09386796c5f534639323232323232323232333436393d434c57626e7a8793a0acafa295897c6f6356493d3023160a000000000e1b2835414e5b6774818e9ba8aca09386796c5f5346392d201306000000000000000000000000050e182029323a424951585f656b71767b8084888b8e91939496979898989898979594928f8d8a86827d79746e68625b544d463e362e251c130a010000000000000000000000000000060c101315151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151514120f0a04000000000000000006101921282e3234343434343434343434322d2821180f06000000000000000000000000000000040d151e262d343b41474c5055585b5e60626365656666666666656462605e5b5854504b46413a342d251d150d040000000000000000000000000000000000000000000916222e3a454f59606262626262626262615b52483d3125190d000000000000000000000000000000000000000000000000000000000c1925323f4b5864717e8686868686868683776a5e606c7986868686868686867b6f6356493d3023160a00020e1a27333f4b57636e7a86919a8f84786d63584d58646f7b8792998e83776c61574c41362a1e1206000000000000000000000000000000000000000000000000000000111e2a3744515d6a7784919c9c9c9c9c9c9c9c9c9da0a59e9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9ea0a39d9c9c9c9c9c9c9c9c9386796d6053463a2d2013070000000000000008131d27303a444d57616a747d87919a9f9790888179727880878f979f9b91877d736a60564c42392f251b110600000000000000000000000000010e1a26323f4b5764707c8995a1a3978b7e7266594d4135281c100300000000000000000000000000000013202c3946535f6c79868d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d877a6d6154473a2e2114070013202c3946535f6c798688888888888886796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c10131515151515151515151513100c06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050c12181d23272b2f3335383a3c3d3e3e3e3e3e3d3c3a393634302d292831393f44464646464646464645423c342c22170d01000000000f1c2834404b565f6566666666666666666666666666666666666666666666666666666666666b758089939ea8a49a90867b71675d53493e33281c100300000013202c3946535f6c798693a0acaca09386796c5f53463e3e3e3e3e3e3e3e3e3f3f414345494e555e68737e8b97a3afaca094877a6e6154483b2f221509000000000f1b2835424e5b6875828e9ba8ada09386796d6053463a2d2013070000000000000000000000040e17202a323b444c545b626970767c82878c9094979a9d9fa1a3a4a4a5a5a5a4a3a2a09e9c9996928e8a857f79736d665f58504840372e251c1309000000000000000000000000020a11181c20212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211f1b150f07000000000000020d18222b33393e404141414141414141403e39322a21170d0200000000000000000000000000030c161f2730373f464c52585c6164686a6d6f707172737373737372706f6d6b6864615c57524c453e372f271f160d0300000000000000000000000000000000000000000c1825313e4a56616b6f6f6f6f6f6f6f6f6d64594d4135281c0f030000000000000000000000000000000000000000000000000000000a1724303d4a56636f787979797979797979756a5e5e6a767979797979797979786e6256493c3023160a00000a17232e3a46525e6975808b93938a7f74695f54535f6a76818d9393897e73685e52473b2e221509000000000000000000000000000000000000000000000000000000111e2a3744515d6a77849191919191919191919191949d9d9491919191919191919191919191919191959e9b93919191919191919186796d6053463a2d20130700000000000000010b151e28323b454f58626b757f89929ca29a938b847c828a9199a19c93897f756b61584e443a30271d1309000000000000000000000000000005111d2936424e5b6773808c98a5a094877b6f62564a3e3125190c0000000000000000000000000000000013202c3946535f6c7986939a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a94877a6d6154473a2e2114070013202c3946535f6c798693959595959386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000000000000020a11181c2021222222222222222221201c18110a02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001070c12171b1f2326292b2d2f303131323231302f2e2c2a2724211d1f272e343839393939393939393836312a221910060000000000111e2b3744505c68717373737373737373737373737373737373737373737373737373737373737377828c96a1aca2978d83796f655b5044382c1f130600000013202c3946535f6c798693a0acaca09386796c5f534b4b4b4b4b4b4b4b4b4b4c4c4d4f52555a6067707a85909ba7b3a99d9184786b5f5246392d201407000000000f1c2835424f5b6875828f9ca8ada094877a6d6053473a2d20140700000000000000000000020c162029323c444d565e656d747b82888d93989ca0a4a7aaa8a5a3a2a1a1a0a1a1a2a4a6a8a8a5a29e9a95908b857e787169625a524940372e251b120800000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2b2620191108000000000008141f2a343d444a4d4d4d4d4d4d4d4d4d4d4a443c33291f1308000000000000000000000000010b151e283139414951575e63686d717477797b7d7e7f808080807f7e7d7b797774716c68635d575049413931281f150b01000000000000000000000000000000000000000d1a2633404d5966727c7c7c7c7c7c7c7c76695d5043372a1d10040000000000000000000000000000000000000000000000000000000915222e3a47525d676c6c6c6c6c6c6c6c6c6b635959646b6c6c6c6c6c6c6c6c6c675d52463a2e211508000006121e2a35414d58636e7a85868686867b7064574e5965707b86868686857a6f63564a3d3023170a000000000000000000000000000000000000000000000000000000111e2a3744515d6a778484848484848484848484848b98978b848484848484848484848484848484848c99968a848484848484848484796d6053463a2d2013070000000000000000030c162029333d46505a636d76808a939da59d968e878c949ba39e948a81776d635950463c32281e150b0100000000000000000000000000000814202d3945525e6a77838f9ca89d9084786b5f53463a2e2215090000000000000000000000000000000013202c3946535f6c7986939e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e94877a6d6154473a2e2114070013202c3946535f6c798693a0a2a2a09386796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2c28231c140b0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001060b0f13171a1c1f21222324252525242423211f1d1b181411151d23282b2c2c2c2c2c2c2c2c2c29251f181007000000000000121f2c3845525f6b7880808080808080808080808080808080808080808080808080808080808080808086929faca99f958b81776c6054473b2e21150800000013202c3946535f6c798693a0acaca09386796c5f585858585858585858585858595a5c5e61656b7179828c96a1acb0a4998d8174685c5043372a1e1105000000000f1c2936424f5c6975828f9ca8ada094877a6d6154473a2e211407000000000000000000000a141e28323b444e565f6770777f868d93999ea3a8aaa6a29e9b99979594949494949697999b9ea2a6aaa6a19c969089827b746c645b524940372d241a10060000000000000000000a141d262e34383b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3a37322b231a1006000000010d1925303b464f565a5a5a5a5a5a5a5a5a5a564e453b3024190d01000000000000000000000008131d27303a434b535b62696f74797d818386888a8b8c8c8d8d8d8c8b8a888684817d78746e68625b534b433a31271d1309000000000000000000000000000000000000000d192633404c5966738089898989898983776a5d5044372a1d110400000000000000000000000000000000000000000000000000000006121e2a36414c555c5f5f5f5f5f5f5f5f5f5e5951525a5f5f5f5f5f5f5f5f5f5f5c554b41352a1e12050000010d1925303c47525d68737979797979797064574b535f6a747979797979786f63564a3d3023170a000000000000000000000000000000000000000000000000000000111d2a3743505c697377777777777777777777777c8895988b7f77777777777777777777777777777d8a96968a7d7777777777777777756b5f5246392c201306000000000000000000040e17212b343e48515b646e78818b959ea7a09894969ea5a0968c82786f655b51473e342a20160d030000000000000000000000000000000b1724303c4955616e7a86939fa6998d8174685c4f43372b1e12060000000000000000000000000000000013202c3946535f6c7986929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292877a6d6154473a2e2114070013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000000000000a141d262e34383b3b3b3b3b3b3b3b3b3b38342e261d140a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003070a0d1012141617181818181817161513110e0b08050b12171c1e20202020202020201f1d19140e0600000000000000121f2c3845525f6b78858d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8e97a2aeb1a79d93887b6e6155483b2e22150800000013202c3946535f6c798693a0acaca09386796c656565656565656565656565656667686b6e71767c838b949ea8b2a99e93887c7064584c4034271b0f0200000000101c2936434f5c6975828f9ca9aea194877a6d6154473b2e21140800000000000000000007111c26303a444d5660687179828991979ea4aaa9a39e9a95928f8c8a898887878788898a8d8f92969a9ea4a9a7a19b948d867e756d645b52493f362c22170d020000000000000006111c262f383f4548484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484847433d352c22170c01000004111d2935414d57616667676767676767676660574c4135291d100400000000000000000000040f1a242f39424c555d656d747a8085898d909294969798999a9a999998979593908d8984807a736c655d554c43392f251a10050000000000000000000000000000000000000c1926323f4c5965727e8c96969696908376695c5043362a1d1003000000000000000000000000000000000000000000000000000000020e19252f3a434b50535353535353535353524e48484e52535353535353535353504a43392f24190d0200000008141f2a36414c5761696c6c6c6c6c6c685e53484d58626a6c6c6c6c6c6c675d52473a2e2215090000000000000000000000000000000000000000000000000000000f1b2834404c5761696a6a6a6a6a6a6a6a6a6a6d7986929b8e82756a6a6a6a6a6a6a6a6a6a6a6a6e7a8793998c80736a6a6a6a6a6a6a6963594e42362a1e110500000000000000000000050f19222c363f49525c666f79838c96a0a0a0a0a0a0a0988e847a70665d53493f352c22180e04000000000000000000000000000000000f1b2733404c5865717d8a96a0a0968a7d7165584c4033271b0f020000000000000000000000000000000013202c3946535f6c7985858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585857a6d6154473a2e2114070013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000006111c262f383f4548484848484848484848453f382f261c1106000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030607090a0b0b0b0b0b0a090806040100000000060b0f12131313131313131312110d09030000000000000000121f2c3845525f6b7885929a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9aa0a9b3b9aea295887b6e6155483b2e22150800000013202c3946535f6c798693a0acaca09386797171717171717171717171717172727375777a7d82878e959da6afaba2988d82776b6054483c3024180b0000000000101d2936434f5c697683909ca9aea194887b6e6154483b2e2115080000000000000000030e19232e38424c565f68727a838b939ba2a9aba49e98928e898582807d7c7b7a7a7a7b7c7e8083868a8e93989ea4aba69f9790887f766d645b51483e33291f140a000000000000000b17222d38424a51545555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555534e473e34291d1206000006131f2c3945525e6972747474747474747472695d5145382c1f1206000000000000000000000b16212c36404b545e676f777e858b9195999c9fa1a3a1a0a09f9f9fa0a1a2a19f9c9995908b857e776f675e554b41372c21160b0000000000000000000000000000000000000c1825323f4b5865717e8b98a2a29c8f8275695c4f4236291c10030000000000000000000000000000000000000000000000000000000008131e2831393f4446464646464646464645423d3d4345464646464646464646443f3931271d130800000000030e19242f3a454f585e5f5f5f5f5f5f5c564d424650595e5f5f5f5f5f5f5c554c41362a1e12060000000000000000000000000000000000000000000000000000000c1824303b464f575c5d5d5d5d5d5d5d5d5d5e6a76838f9c9184786b5f5d5d5d5d5d5d5d5d5d5f6b7884919b8f83766a5d5d5d5d5d5d5d5951483d32261a0e02000000000000000000000007101a242d37404a545d67717a848e9393939393939390867c72685e554b41372d231a10060000000000000000000000000000000000111e2a37434f5c6874818d93939393867a6e6155493c3024170b0000000000000000000000000000000000131f2c3945525e6b757878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878766c6053473a2d2114070013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000000000b17222d38424a5154555555555555555554514a42382d22170b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000121f2c3845525f6b7885929fa6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a7abacacacaca295887b6e6155483b2e22150800000013202c3946535f6c798693a0acaca093867e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7f808284868a8e93999fa7afaaa29990867b70655a4f43372c2014080000000000101d2a3643505d697683909da9aea195887b6e6155483b2e22150800000000000000000a15202a353f4a545e68717a848d959da5ada8a19a938d87827d797673716f6e6d6d6d6e6f717376797d82878d939aa1a8a9a299918980766d63594f453b30261b10050000000000000f1b27333f4a545c6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161615f5950453a2e22160a00000713202d3a4653606d798181818181818181796c5f5346392c20130600000000000000000005111c27323d48525c667079818990979ca1a49f9c9996959493929292939496989b9ea2a19c969089817970675d53483e33281d110600000000000000000000000000000000000b1824313e4b5764717e8b97a4a89b8e8275685b4f4235281c0f0200000000000000000000000000000000000000000000000000000000010c161f272e343839393939393939393939363232363939393939393939393937342e271f150c01000000000008131e29333d464d51535353535353504b443b3e474e52535353535353504b433a2f25190e0200000000000000000000000000000000000000000000000000000007131e29343d464c505151515151515151515b6774808d9993877a6e615551515151515151515c6975828e9a9285796c605351515151504d473f362b20150a0000000000000000000000000008121b252e38424b555f68727c8586868686868686867d746a60564c43392f251b120800000000000000000000000000000000000013202c3946525f6b7884868686868683766a5e5245392d2014080000000000000000000000000000000000111e2a36424e59636a6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6a645a4f44372b1f12060013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000000000f1b27333f4a545c616161616161616161615c544a3f33271b0f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104070a0c0e10111112121111100f0d0b08050200000000000000000000000000000000000000000000000000000000121f2c3845525f6b7885929fa0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a095887b6e6155483b2e22150800000013202c3946535f6c798693a0acaea2968d8b8b8b8b8b8b8b8b8b8b8b8b8b8b8c8c8d8e9093969a9ea4aaaca69f9890877e74695f54493e32271b0f030000000000111d2a3744505d6a7783909daaaea295887b6f6255483c2f2215090000000000000005101b26313c47515b66707a838d969fa7afa79e968f88817b76716d6966646261616161626365676a6d71767b82888f969ea7aba39b92897f756b61574d42382d22170c010000000000121e2b37434f5b666d6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6b61564b3e3226190c00000713202d3a4653606d79868e8e8e8e8e8e86796c5f5346392c2013060000000000000000000b16222d39444f5a646e78828b939ba2a49e98938f8c8a8887868686868687898b8e92969ca2a19a938b82786f655a4f44392e22160b00000000000000000000000202010000000b1724313d4a5764707d8a97a4a89b8e8174675b4e4135281b0e020000010202010000000000000000000000000000000000000000000000040d151d23282b2c2c2c2c2c2c2c2c2c2c2a26262a2c2c2c2c2c2c2c2c2c2c2b28231c150d03000000000000010c17212b343b414546464646464644403a32353c4245464646464646443f3931281e130800000000000000000000000000000000000000000000000000000000020d18222b343b404344444444444444444c5865717d8a96968a7d7164584b4444444444444d5966727f8b9894887b6f63564a44444444413c352d241a0f04000000000000000000000000000009131d263039434d56606a73797979797979797979756b62584e443a31271d130900000000000000000000000000000000000000131f2c3946525f6b767979797979797973675b4e4236291d11040000000000000000000000000000000000121f2b3844515d6871727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727271695e5246392d2013070013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000000000121e2b37434f5b666d6e6e6e6e6e6e6e6e6d665b4f43372b1e120500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005090d111416191b1c1d1e1e1e1e1e1d1b191715110e0a060100000000000000000000000000000000000000000000000000121f2c3845525f6b788592939393939393939393939393939393939393939393939393939393939393939393939393939393887b6e6155483b2e22150800000013202c3946535f6c798693a0acb3a89f99989898989898989898989898989898999a9b9d9fa2a6aaa9a5a09b958e867e756b62584d43382c21160a000000000000111e2a3744515d6a7784909daaafa295887b6f6255493c2f221609000000000000000b16212d38434d58636d77828c959fa8afa69d958c857d76706a65615d5a5856555454545556585a5d61656a70767d858c959da6ada49b91877d73695e54493e33281d1207000000000013202c3946525f6c777b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b73675a4d4134271a0e00000713202d3a4653606d7986939a9a9a9a9386796c5f5346392c201306000000000000000004101b27333e4a55606b76808a949da5a29a938c8783807d7b7a79797979797b7c7e82868b90979fa59d948b81766c61564a3f33271b0f0300000000000001060a0d0e0e0e0d0c0b0a1723303d4a5663707d8a96a3a79a8d8174675a4d4134271b0e0a0b0c0d0e0f0d0b0702000000000000000000000000000000000000000000030b12171c1e2020202020202020201f1e1a1a1e1f2020202020202020201e1c17120b030000000000000000050f19222a30353839393939393938342f282b31363939393939393938342e271f160c0100000000000000000000000000000000000000000000000000000000000610192229303437373737373737373c4955626e7b8794998c8073675a4e42373737373e4a5763707c8995978b7e7265594c4037373735312b231b1208000000000000000000000000000000010b141e27313b444e5861696c6c6c6c6c6c6c6c6c6b635a50463c32281f150b0100000000000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6961564a3e32261a0d01000000000000000000000000000000000013202c3946535f6c797f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7a6d6154473a2e2114070013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946525f6c777b7b7b7b7b7b7b7b776c5f5246392c20130600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001060c1115191d20232527292a2b2b2b2b2a29282624211e1a16120d07020000000000000000000000000000000000000000000000121f2c3845525f6b788586868686868686868686868686868686868686868686868686868686868686868686868686868686867b6e6155483b2e22150800000013202c3946535f6c798693a0acacaca9a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a6a8a9a7a5a3a09d99948f8a837c746c635a50463b31261b1005000000000000111e2a3744515d6a7784919eaaaca296897c6f6255493c2f22160900000000000005111c27333e49545f6a747f89949ea7b1a79d948b837a736c655f5a55514e4b4948474747484a4b4e51555a5f656b737a838b949da7ada3998f857b70655b50453a2e23180c010000000013202c3946535f6c79868888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888174675a4d4134271a0e00000713202d3a4653606d798693a0a7a7a09386796c5f5346392c20130600000000000000000814202c38444f5b66727d88929ca6a2999088817b7773716f6d6c6c6c6c6d6e7072767a7f858d959ea69d93887d72675b4f44382b1f13070000000000050c1216191b1b1a191817161623303c4956636f7c8996a2a69a8d8073675a4d4034271a161718191a1b1b1a17130e0700000000000000000000000000000000000000000000060b0f1213131313131313131313110e0e1113131313131313131313120f0b0600000000000000000000000710181f25292c2c2c2c2c2c2c2b28231d20262a2c2c2c2c2c2c2c2b28231d150d04000000000000000000000000000000000000000000000000000000000000000710181e24282a2a2a2a2a2a2a2d3a46535f6c7885919c8f83766a5d5144382b2a2f3b4854606d7986929a8d8174685b4f42362a2a2825201911090000000000000000000000000000000000020c151f29323c464f585e5f5f5f5f5f5f5f5f5f5e5951483e342a20170d0300000000000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5d574f453a2e22160a00000000000000000000000000000000000013202c3946535f6c79868c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c877a6d6154473a2e2114070013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798688888888888886796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c12171c2125292c2f323436373838383837363533302d2a26221d18130d0600000000000000000000000000000000000000000000121f2b3845515e6a76797979797979797979797979797979797979797979797979797979797979797979797979797979797979776d6154483b2e21150800000013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09f9e9e9c9b999794918d89847e78716a625a51483e342a1f150a00000000000000111e2b3844515e6b7784919ea0a0a096897c6f6356493c302316090000000000000a16222d38444f5a66717b86919ba5b0a99f958b82797169615a544e4945413e3d3b3a3a3b3b3d3f4245494e545a61687179828b959fa9aba1978c82776c61564b4034291d12060000000013202c3946535f6c798693959595959595959595959595959595959595959595959595959595959595959595959595959595959595958e8174675a4d4134271a0e00000713202d3a4653606d798693a0adaca09386796c5f5346392c20130600000000000000000c1824303c4854606c77838e99a4a59b90877e76706b67646261605f5f5f60616366696e747b838c96a0a49a8f83786c6054483c2f23170a00000000070f171d22262828272625242322222f3c4955626f7b8895a2a6998c807366594c403326222324252627282827241f1911090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060d14191d1f2020202020201f1c1812151a1d1f2020202020201e1c17120b03000000000000000000000000000000000000000000000000000000000000000000060d13181b1d1e1e1e1e1e1e2b3743505c6975828e9b9285796c6053473a2e222c3845515e6a7783909c9084776b5e5245392c201c19140e0700000000000000000000000000000000000000030d17202a343d464d51535353535353535353524e483f362c22180e050000000000000000000000000000000000000000000a16212c3740484f5253535353535353514d453d33281d120600000000000000000000000000000000000013202c3946535f6c7986939999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999994877a6d6154473a2e2114070013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693959595959386796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a10171d23282d3135393c3e414243444545444443413f3d3a36322e29241e18110a030000000000000000000000000000000000000000101d2936424e59646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c665c5145382c20130700000013202c3946535f6c798693939393939393939393939393939393939393939393929291908e8c8a8784817d78736d67605850483f362c22180e0300000000000000121e2b3845515e6b7885919393939393897d7063564a3d3023170a0000000000040f1b27323e4a55606c77828d98a3adaca1978d837970675f574f48423d393532302f2e2e2e2f303235393d42484f575f677079838d97a2aca99e94897e73675c51453a2e23170b0000000013202c3946535f6c798693a0a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a29a8e8174675a4d4134271a0e00000713202d3a4653606d798693a0adaca09386796c5f5346392c20130600000000000000000f1b2834404c5965717c88949fa89f94897e756c655f5b585554535252535355575a5d6269717a848f9aa6a094887c7064584b3f3226190d00000006101921282e32353534333231302f2e2f3b4855616e7b8895a1a5988c7f7265594c3f322d2e2f30313233353533302a231b1209000000000000000000000000000000000000030608090a0a0a0908060300000000000000000000000000000000000000000000000000000000000000000000000002080d101213131313131312100c07090e1113131313131313120f0b0600000000000000000000000000000000000000000000000000000000000000000000000002070c0f1111111111111b2834414d5a66737f8c9894887b6f63564a3d31242936424f5b6874818d9993867a6d6154483b2f22160c0803000000000000000000000000000000000000000000050e18222b343c414546464646464646464645423d362d241a10060000000000000000000000000000000000000000000005101a252e373e43464646464646464645413b342b21170c0100000000000000000000000000000000000013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a094877a6d6154473a2e2114070013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0a2a2a09386796c5f5346392c2013060202020202020202020201000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050d141b22282e34393d4245484b4d4f5051515151514f4e4c4946423e3a352f29231c150d05000000000000000000000000000000000000000e1a26313d48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5b544a3f34281c100400000013202c3946535f6c7986868686868686868686868686868686868686868686868685848382807d7b7874716c67625c554e463e362d241a10060000000000000000121f2c3845525e6b7885868686868686867d7063564a3d3024170a00000000000814202c38434f5b66727d88939fa9afa59a8f857b71675e554d453e37312d29252322212121222426292d32373e454d555e67717b85909ba5b0a59a8f84796d62564b3f33281c100400000013202c3946535f6c798693a0acaeaea9a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a59a8e8174675a4d4134271a0e00000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000121e2b3744505c6975818d97999c998e82776c635a534e4b49474646464647484a4d52575f68727e8a96a2a5988c8073675a4e4135281c0f0200020d18222b333a3f4141403f3e3d3c3b3a393b4854616e7a8794a1a5988b7e7265584b3f393a3b3c3d3e3f404141403b352d241b1006000000000000000000000000000003080c0f121416171717161412100c080400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1925323e4a5763707c8995978b7e7265594c40332727333f4c5865717e8a9795897c7063574b3e3225190c000000000000000000000000000000000000000000000000061019222a3035383939393939393939393936322b241b120800000000000000000000000000000000000000000000000009131c252c323739393939393939393835302922190f050000000000000000000000000000000000000013202c3946535f6c7986939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393877a6d6154473a2e2114070013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130f0f0f0f0f0f0f0f0f0f0e0e0c0b090704010000000000000000000000000000000000000000000000000000000000000000000000000000070f171f262d333a3f45494e5155575a5c5d5e5e5e5e5d5c5a5856524f4a46403b342e271f170f070000000000000000000000000000000000000915202b3640484e52535353535353535353535353535353535353535353535353535353535353535353535353535353535353524f4a42382e23180c00000000131f2c3946525f6b767979797979797979797979797979797979797979797979797877767573716e6c6864605b56504a433c342c241b1208000000000000000000121f2b3845515e6a767979797979797979786f63564a3d3023170a00000000000d1925303c4854606b77838e9aa5b0a99e93887e73695f554c433b332c26211c1917151414141517191d21262c333b434c555f69747e89949faaaca1958a7e73675c5044382c21150900000013202c3946535f6c798693a0acb3a89f99989898989898989898989898989898989898989898989898989898989898989898989898988e8174675a4d4134271a0e00000713202d3a4653606d798693a0adaca09386796c5f5346392c201306000000000000000013202c3946535f6c7885888a8d8f92897d71665b5148433f3c3b3a3939393a3b3e41464d56616d7986929fa89b8f8276695c5043372a1d11040008141f2a343d454b4e4e4d4c4b4a49484746454754606d7a8794a0a4988b7e7164574b45464748494a4b4c4d4e4e4c473f362d22170c000000000000000000000000040a0f14181c1f212324242423211f1c1914100b050000000000000000000000000000000000000407080909090909080705010001050708090909090908070401000000000000000000000000000000000407080909090909080705010000000000000000000000000000000000000000000000000000000000000000000916222f3b4854616d7a86939a8d8174685b4f42362a24303d4956626f7b8894988c7f73665a4d4134281b0f020000000000000000000000000000000000000000000000000710181f25292c2c2c2c2c2c2c2c2c2c2c2a26211a120900000000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c29251f181007000000000000000000000000000000000000000013202c3946535f6c7986868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686867a6d6154473a2e2114070013202c3946535f6c798693a0acaca09386796c5f5346392c201307070707070707070707070605040200000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201c1c1c1c1c1c1c1c1c1c1c1b1a19181613110e0a070200000000000000000000000000000000000000000000000000000000000000000000071019212930383e454b50555a5e616466686a6b6b6b6b6a696765625f5b56514c463f383129211910070000000000000000000000000000000000040f1a242e363d434546464646464646464646464646464646464646464646464646464646464646464646464646464646464646433f382f261c110600000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6b6a686664625f5c5854504b453f39322a221a120900000000000000000000101d2936424e59646b6c6c6c6c6c6c6c6c6c675d52473a2e2215090000000004111d2935414d5965707c88949fabafa3988d82766c61574d433a3129211b15100d0a08080708090a0d10151b2129313a434d57626c77838e99a4b0a69b8f84786c6155493d3125190d00000013202c3946535f6c798693a0acaea2968d8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8174675a4d4134271a0e00000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000131f2c3945525e6b75797b7e81838585786c6054493f3732302e2d2c2c2c2d2f31353b45515e6a7784919daa9d9184776b5e5144382b1e1105000d1925303b464f565a5b5a59585756555453525153606d798693a0a4978a7d7164575051525354555757595a5b5b5851483e33281c100400000000000000000001080f151b2024282b2e2f3030302f2e2b2825201b161009020000000000000000000000000000070c11141515151515151514110d080d11141515151515151514110c0700000000000000000000000000070c11141515151515151514110d0801000000000000000000000000000000000000000000000000000000000000000713202c3945515e6a7783909c9084776b5e5245392c212e3a47535f6c7885919b8e8275695c5043372b1e120500000000000000000000000000000000000000000000000000060e14191d1f2020202020202020201f1e1a150f08000000000000000000000000000000000000000000000000000000010910161a1e1f202020202020201f1d19140d06000000000000000000000000000000000000000000131f2c3946525f6b767979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979776c6053473a2d2114070013202c3946535f6c798693a0acaca09386796c5f5346392c201414141414141414141414141312100f0c0a0704000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2828282828282828282828282827262422201d1a17130e0a0500000000000000000000000000000000000000000000000000000000000000071019222b333b424950565c61666a6d7073757677787877777574716e6b67625d57514a433b332b22191006000000000000000000000000000000000008121b242c3236393939393939393939393939393939393939393939393939393939393939393939393939393939393939393937332d261d140a00000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5e5d5b5a585653504c48443f3a342e272018100800000000000000000000000e1a26313d48525a5f5f5f5f5f5f5f5f5f5f5c554c41362a1e1206000000000814212d3945515d6975818d99a4b0a99e92877b70655a50453b31281f17100904000000000000000001040910171f28313b46505b66717c88949fabaca095897d7165594d4135291d1004000013202c3946535f6c798693a0acaca093867e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e74675a4d4134271a0e00000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000111e2a36424e59636a6d6f717476797b75695c5044382d26232120201f202123292f3844515d6a7784909daa9e9285786b5e5145382b1e120500101d2935414d58616768676665636261605f5e5d5c5f6c7986929fa3968a7d70635c5d5e5f606162636465666768635a5045392d2014070000000000000000040b131a20262b3034383a3c3d3d3d3c3a3835312c27211b140d050000000000000000000000020b12181d2022222222222222201d1913181d2022222222222222201d18120b03000000000000000000020b12181d2022222222222222201d19130c0400000000000000000000000000000000000000000000000000000000000004101d2936424f5b6874818d9a93867a6d6154483b2f232b3744505d6976828f9b9185786c5f53463a2d211408000000000000000000000000000000000000000000000000000003080d101213131313131313131313110e0a04000000000000000000000000000000000000000000000000000000000000050a0e11131313131313131312100d080200000000000000000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b655b5044382b1f12060013202c3946535f6c798693a0acaca09386796c5f5346392c21212121212121212121212120201f1d1b191613100c0804000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f53463935353535353535353535353535353432312f2c2a26231f1a15100b0500000000000000000000000000000000000000000000000000000000061019222b343d454c545b61676d72767a7d808283848585848482807e7b77736e68625c554d453d342b22180e04000000000000000000000000000000000009121a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b27221c140b0200000000000a16212c3740484f525353535353535353535353535353535353535353535353535251504f4d4b494643403c38332e29231c150e060000000000000000000000000915202b3640484e52535353535353535353504b433a2f25190e02000000000c1824303d4955616d7986929da9b0a4988d81756a5f54493e33291f160d0500000000000000000000000000050d161f29343f4a55606b77838e9aa6b1a5998e8275695d5145392d201408000013202c3946535f6c798693a0acaca093867971717171717171717171717171717171717171717171717171717171717171717171717171716d63584c3f33261a0d00000713202d3a4653606d798693a0adaca09386796c5f5346392c20130600000000000000000e1a26323d4851595e606265676a6c6e6c63584d4034281c17191c1f23262a2f343a414a54606c7985929eab9e9184786b5e5145382b1e120500121f2c3845515e697374737271706f6e6d6c6b6a69686b7885929fa296897c6f68696a6b6c6d6e6f7071727374746c6155483c2f23160900000000000000050e161d242b32373c404447494a4a4a494744413d38322c261f170f07000000000000000000020c141c23292d2f2f2f2f2f2f2f2d29241e24292d2f2f2f2f2f2f2f2d29231d150c0300000000000000020c141c23292d2f2f2f2f2f2f2f2d29241e160d040000000000000000000000000000000000000000000000000000000000010e1a2733404c5965717e8a9795897c7064574b3e32252835414e5a6773808c9994877b6e6255493c3023170b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5b53493f33281c0f030013202c3946535f6c798693a0acaca09386796c5f5346392e2e2e2e2e2e2e2e2e2e2e2e2e2d2c2b2a282523201c18140f0a0500000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346424242424242424242424242424241403f3d3b3936332f2b26211c1610090200000000000000000000000000000000000000000000000000040e18222b343d464f575e656c73787d8286898c8e9091919291908f8d8a87837e79746d665f574f463d342a20160c010000000000000000000000000000000000080f151a1e1f202020202020202020202020202020202020202020202020202020202020202020202020202020202020201e1b17110a0200000000000005101a252e373e434646464646464646464646464646464646464646464646464645454342413f3c3a3734302c27231d17110b0400000000000000000000000000040f1a242e363d4345464646464646464646443f3931281e130800000000020f1b2734404c5965717d8a96a2aeaca094887c7065594e42372c22170d04000000000000000000000000000000040e18222d38434f5b66727e8a96a2aeaa9e9286796d6155493c3024170b000013202c3946535f6c798693a0acaca09386796c65656565656565656565656565656565656565656565656565656565656565656565656565625b52473b2f23170b00000713202d3a4653606d798693a0adaca09386796c5f5346392c20130600000000000000000a15212b363f474e515356585b5d6062605a51473c30241f2225282b2f33373b40454c535c66717c8895a1a99c9083766a5d5044372a1e11040013202c3946535f6c7981807f7e7d7c7b7a7978777675747885919ea295887c737475777779797b7c7d7e7e80817d7063564a3d3023170a000000000000050e171f272f363d43484c5053555657575553514d49443e3730292119100700000000000000000a141e262e34393b3c3c3c3c3c3b39352f282f35393b3c3c3c3c3c3b39352e271e140a000000000000000a141e262e34393b3c3c3c3c3c3b39352f281f160c0100000000000000000000000000000000000000000000000000000000000b1824303d4956626f7b8894988c7f73665a4d41342826323e4b5764707d8996968a7d7164584c3f33261a0d01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000206090a0a0a0a0a0a0a0a0a0a080400000000000000000000000000000407090a0a0a0a0a0a0a0a0a0a090703000000000000000a16212c3740484f525353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353524f4941372d22170b000013202c3946535f6c798693a0acaca09386796c5f53463a3a3a3a3a3a3a3a3a3a3a3a3a3a3a39383634322f2c2824201b16100a040000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f534f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4e4d4c4a4845423f3b37322d27211b140d060000000000000000000000000000000000000000000000010b16202a343d464f58606970777e84898e9296999b9c9e9e9e9e9d9b9997938f8a857f78716961584f463c32281d1308000000000000000000000000000000000000040a0e111313131313131313131313131313131313131313131313131313131313131313131313131313131313131313120f0b0600000000000000000009131c252c323739393939393939393939393939393939393939393939393939393837363432302d2b2724201c17120c060000000000000000000000000000000008121b242c32363939393939393939393938342e271f160c010000000005121e2a3743505c6875818d9aa6b2a89c9083776b5f54483c31261b1005000000000000000000000000000000000006111c27323e4a56616d7986929eaaaea296897d7165584c3f33271a0e010013202c3946535f6c798693a0acaca09386796c5f58585858585858585858585858585858585858585858585858585858585858585858585856514940352a1f130700000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000040f1a242d363d424547494c4e515355544f483f352b282b2e3134383b3f43474b50575d656e78828d99a5a6998d8174685b4f4236291c10030013202c3946535f6c79868d8c8b8a8988878685848382818084919ea295887f8181828384858687888a8a8c8c8a7d7063564a3d3023170a0000000000050e172029313941484e54585c606263636362605d59544f49423b332b2219100700000000000006111c26303840454848484848484846413a313940454848484848484845403930261c1106000000000006111c26303840454848484848484846413a31281e130800000000000000000000000000000000000000000000000000000000000815212e3a4753606c788591938e8275695c5043372b232f3c4855616e7a8793938d8074675b4e4235291c1003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080e12151717171717171717171614100b0500000000000000000000050b1014161717171717171717171716130f0a04000000000005101a252e373e4346464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646433e372f261b1106000013202c3946535f6c798693a0acaca09386796c5f5347474747474747474747474747474747464543413e3c3835302c27211c150f0801000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5a585754524f4b47423e38322c261f1710080000000000000000000000000000000000000000000008121d27323c454f58616a727a82898f959a9ea2a5a7a5a3a3a2a3a4a6a6a39f9b96908a837b736a61584e443a2f241a0f04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b2a29272623211e1b1814100b060100000000000000000000000000000000000009121a21262a2c2c2c2c2c2c2c2c2c2c2b28231d150d0400000000000814212d3a46535f6b7884919da9b0a4988c8073675b4f43372c201409000000000000000000000000000000000000000a16222d3945515d6976828e9ba7b2a5998d8174685b4f4236291d10040013202c3946535f6c798693a0acaca09386796c5f534b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4a463f372e24190e0200000713202d3a4653606d798693a0adaca09386796c5f5346392c20130600000000000000000008121b242b3135383a3d3f4244464847443e362d3134383b3e4144474b4f53575c62686f77808a949faaa195897d7165594c4033271a0e010013202c3946535f6c7986939897969594939291908f8e8d8c8c95a0a4988e8c8d8e8f909192939495969798968a7d7063564a3d3023170a00000000030d172029323b434b52595f64696c6e7070706f6c6965605a544d453d342b22190f0500000000000b17222d38424a5155555555555555524b433a424b5155555555555555514b42382e23180d01000000000b17222d38424a5155555555555555524b433a2f24190e030000000000000000000000000000000000000000000000000000000006121f2b3744505d69768286868685786c5f5246392c202d3946525f6b778486868683766a5d5144372b1e110400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040c13191e2223242424242424242423201c17100800000000000000000810171c20232424242424242424242422201b150e07000000000009131c252c32373939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393937332d251d140a00000013202c3946535f6c798693a0acaca09386796c5f54545454545454545454545454545454535351504d4b4845413c38322d27201a120b030000000000000000000013202c3946535f6c798693a0acaca09386796c686868686868686868686868686868686867676563615e5b57534e49443e373029221a12090000000000000000000000000000000000000000030e19242f39434e57616a737c858c949aa0a6a7a29e9b989796969697999ca0a5a7a19b948d857c736a60564b41362b20150a0000000000000000000000000000000000000205080a0b0c0d0d0d0d0c0a09070402000000000000000000000001040607070707070605030100000000000000000000000000000000000000000000010910161a1e1f2020202020202020202020202020202020202020202020201f1e1d1c1b191715120f0b080400000000000000000000000000000000000000000000080f151a1e1f2020202020202020201e1c17120b030000000000000a1623303c4955626e7b8794a0acada195887c6f63574b3f33271b0f030000000000000000000000000000000000000005111d2935414d5a66727e8b98a4b0a99c9084776a5e5145382c1f13060013202c3946535f6c798693a0acaca09386796c5f53463e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3d3a342d251c12070000000713202d3a4653606d798693a0adaca09386796c5f5346392c201306000000000000000000000912192025292b2e303335383a3c3b383335393d4144474a4d5054575b5f63686d737a8189929ba6a59a8f84786d6155493d3024180b000013202c3946535f6c798693a0a4a3a2a1a09f9e9d9c9b9a99999ea7aaa09a999a9b9c9d9e9fa0a1a2a3a4a3968a7d7063564a3d3023170a000000000a141f28323b444d555d646b7075787b7d7d7d7b7975716b655e574f463d342b21170c02000000000f1b27333f4a545c616262626262615d554b414a545d616262626262615c544a3f34291e1307000000000f1b27333f4a545c616262626262615d554b41362b20140900000000000000000000000000000000000000000000000000000000030f1c2835414e5a67727979797979766b5f5246392c1f2a36434f5c68747979797979756a5d5144372b1e1104000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d161e252a2e3030303030303030302f2d28221a120900000000000008121a22282c2f303030303030303030302f2c272019100700000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a27221b130b0200000013202c3946535f6c798693a0acaca09386796c6161616161616161616161616161616161605f5e5c5a5754514d48433e38322b241d150d0500000000000000000013202c3946535f6c798693a0acaca0938679757575757575757575757575757575757575747372706d6b67635f5a554f49423b342c241b1209000000000000000000000000000000000000000a15202b36404b555f69737c868e969ea5a8a29c96928f8c8a8989898b8d90959aa0a7a69f978e857c72685d52483d31261b0f04000000000000000000000000000002070b0f1214161819191a1a1918171513110e0b0702000000000002060a0e101214141414141311100d0b0804000000000000000000000000000000000000000000050a0e11131313131313131313131313131313131313131313131313131212110f0e0c0a0805020000000000000000000000000000000000000000000000000000040a0e1113131313131313131313120f0b0600000000000000000c1925323e4b5764717d8a96a3afab9e9285796c6054473b2f23160a0000000000000000000000000000000000000000010d1925313e4a56636f7c8895a1aeac9f9386796d6054473b2e2215080013202c3946535f6c798693a0acaca09386796c5f534639323232323232323232323232323232323232323232323232323232323232323232312e29231b130a000000000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000000000080f15191d1f212426292b2d2f33383d4146494d505356595d6064676b6f74787e858b939ba4a59c93897e73685c5045392d201408000013202c3946535f6c798693a09f9e9d9c9b9a999897969594959aa4a79d969495969798999a9b9c9d9e9fa0968a7d7063564a3d3023170a00000006111c26303a444d565f676f767c818588898a8a8885827c77706961584f463d33291e140900000000121e2b3743505b666d6f6f6f6f6f6e675d5247505c666e6f6f6f6f6f6d665c51463a2f24180d01000000121e2b3743505b666d6f6f6f6f6f6e675d52473c31251a0e03000000000000000000000000000000000000000000000000000000000d1926323e4a5661696c6c6c6c6c6b645a4f43372a1e2734404c57626a6c6c6c6c6c6b63594d4135291c10030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b151f282f363a3d3d3d3d3d3d3d3d3d3c39332c241b11060000000006111a242c33383c3d3d3d3d3d3d3d3d3d3d3b38322a22190f0400000000010910161a1e1f2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201e1b161009010000000013202c3946535f6c798693a0acaca09386796d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6c6b696664615d59544f49433d362f271f170e05000000000000000013202c3946535f6c798693a0acaca093878282828282828282828282828282828282828281807e7c7a77736f6b66605a544d453e362d241b1209000000000000000000000000000000000004101b26313c47525d67717b858f98a0a8a69e97908b86827f7d7c7c7d7e8184898f969da6a9a0978e84796f64594e43372c20140900000000000000000000000003090e13171b1e2123242626262626252422201d1a17130e09040002080d12161a1d1f20212121201f1e1c1a1714100b0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1a2734404d596673808c99a5b2a89c8f83766a5d5144382b1f13060000000000000000000000000000000000000000000916222e3b4754606d7986939facaea195887c6f6256493d3023170a0013202c3946535f6c798693a0acaca09386796c5f5346392c252525252525252525252525252525252525252525252525252525252525252524221d18110a01000000000713202d3a4653606d798693a0adaca09386796c5f5346392c20130600000000000000000000000004090d1012151920272e343a3f44494d5256595d606366696c7073777b80848a90969da5a39b938a81776c61564b4034281c1004000013202c3946535f6c798693939291908f8e8d8c8c8b8a898889929fa2968b8788898a8b8c8d8e8f90919293948a7d7063564a3d3023170a0000010d18232d38424c565f68717981878d919496979694928d88827b736a61584f453a30251b0f0400000013202c3946525f6c787b7b7b7b7b796f64594d53606d787b7b7b7b7b786d62574c4035291e120600000013202c3946525f6c787b7b7b7b7b796f64594d42362b1f1408000000000000000000000000000000000000000000000000000000000a16222e39444f575d5f5f5f5f5f5f5a52483e32261a232f3b4650585e5f5f5f5f5f5e5951473c3125190d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121d27313a41474a4a4a4a4a4a4a4a4a49443e362d23180d010000040e18222c363e44484a4a4a4a4a4a4a4a4a4a48433c342b20160a000000000000050a0e1113131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313110f0a0500000000000013202c3946535f6c798693a0acaca093867a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7979777573706d6965605a554e484039312920170e050000000000000013202c3946535f6c798693a0acafa398908f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8e8e8d8b898683807b76716b655e5750483f372e241b1107000000000000000000000000000000000a15212c37434e59646e79838d97a1aaa59c948c857f7a7673716f6f707174787d848b949da6a9a0968b81756a5f54483d3125190d0100000000000000000001080e141a1f23272a2d2f31323333333332302f2c2a27231f1a150f090c13191e2326292b2d2e2e2e2d2c2b292624201c160f060000000000000000000000000000000000000205080a0c0e0f1010100f0e0d0c0a070401000000000000000000010406080a0a0a0a0a090706040100000000000000000000000000000000000000000003080d10121313131313110e09030000000000000000000000000000000f1c2835424e5b6874818e9aa7b3a69a8d8174675b4e4235291c100300000000000000000000000000000000000000000006131f2c3845525e6b7784919daab0a3978a7d7164584b3e3225180c0013202c3946535f6c798693a0acaca09386796c5f5346392c20181818181818181818181818181818181818181818181818181818181818181715120d070000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000000000000000010a131b232b32393f454b5055595e6265696c6f7275797c8083878b90959ba1a59f99918a81786f655b50453a2f23170c00000013202c3946535f6c79868786868484838281807e7e7d7c7b84909da194887b7b7d7d7e808181828384858687887d7063564a3d3023170a000007131e29343f4a545e68717a838b92989da1a3a4a3a19e99938c857c736a60574c42372c21150a000000131f2c3945525e6a75808888888880756a5e53535f6b7681888888887e73685d51463a2e23170b000000131f2c3945525e6a75808888888880756a5e53473c3024180c0000000000000000000000000000000000000000000000000000000006111d28333d454d515353535353524f4840372c21161e29343e464d525353535353524e473f352b2014090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17232e39434c525657575757575757575550483f34291e120600010b15202a343e484f5557575757575757575757544e463c32271b1004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada1948a8787878787878787878787878787878787878786858482807c7975706b666059524b433b322920170e0400000000000013202c3946535f6c798693a0acb4aaa29c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9b9a99989693908c87827d767069615a514940362d23190f050000000000000000000000000000030f1a26323d49545f6a75808b959fa9a69c938a827a746e6a666463626365686c7279828b949fa9a79d92877c7065594d4135291d11050000000000000000040c131a20262b2f33373a3c3e3f4040403f3f3d3b3936332f2b26201b14171e242a2f3336383a3a3a3a3a39373533302d2720181006000000000000000000000000000000050a0e111417191b1c1c1c1c1c1b1a181614110d0905000000000004090d1013151617171716151412100e0b07020000000000000000000000000000000000060e14191d1f202020201f1d1a150e070000000000000000000000000000101d2a3643505d6976838f9ca9b1a5988b7e7265594c4033261a0d0100000000000000000000000000000000000000000004111d2a3643505c6976828f9ca8b2a5988c7f7266594c4033261a0d0013202c3946535f6c798693a0acaca09386796c5f5346392c20130b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b090601000000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c20130600000000000000000000000000000a131c252d353c434a50565c61656a6e7275787b7e8285888c9093979ca1a59f9a948e8780776f665d53493e34291d120700000013202c3946535f6c787b7b79797877767574737271706f76838f9ca093867a6f70717273747575767778797a7b7b6f6356493d3023160a00000c18242f3a46515b66707a848d959da4a9adafb0b0adaaa59e978e867c72685e53483d32261b0f040000111d2a36424e59646e79848f9592867b6f64584f5a646f7a8590959085796e62574b3f33271b0f030000111d2a36424e59646e79848f9592867b6f64584c4135291d1105000000000000000000000000000000000000000000000000000000000c16212b343b4145464646464646433e372e251a1018222c353c4245464646464645423d362d23190e030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c28343f4b555d636363636363636363615a51463a2f23160a0009131d27323c46505a616363636363636363636360584e43382c201407000000000000000104060707070707070707070707070707070707070707070707070707070707070706060402000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acb1a69c95949494949494949494949494949494949494949392918f8c8985817c77716b645d554d443b322920160c02000000000013202c3946535f6c798693a0acb9afa8a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a4a5a6a4a29f9c98938e88827b736c635b52483f352b21160c010000000000000000000000000008141f2b37434e5a65707c87929ca7a89e948a81787069635d5a57565656585c61687079838d98a3aea3988d81756a5e52463a2d21150900000000000000050e161d242b31363b3f4346494a4c4c4d4d4c4b4a4845423f3b36312c261f21292f353b3f42454647474747454442403d38322a22180e03000000000000000000000000060c11161a1e21232627282929292928272523201d1915110c0601040a1015191d1f22232424242322211f1d1a17130d060000000000000000000000000000000710181f25292c2c2c2c2c2c2a262019110800000000000000000000000000111e2b3844515e6a7784919daab0a3978a7d7164574b3e3125180b00000000000000000000000000000000000000000000010f1c2835424e5b6874818e9ba7b3a69a8d8173675a4d4134271b0e0013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000000000000008121c252e373f474e555b61676c71767a7e8285888b8e9195989ca0a4a8a59b948f89837c756e665d544b41372d22170c01000000121e2b3744505b666e6f6e6d6c6b6a696867666564636875828e9b9f9286796c636465666768696a6b6c6d6d6f6f695f53473b2e2215090005111d2934404c57626d78828c969fa7afb5b9bcbdbcbab6b0a9a0988e857a70655a4e43372c20140800000e1a26313d47525d68737e8995988c8175695d51535d68737e8a95968a7f73675b5044372b1f130700000e1a26313d47525d68737e8995988c8175695d5145392d21140800000000000000000000000000000000000000000000000000000000050f19222930353839393939393937322c251c1309101a232a31363939393939393936322b241b110700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000121e2b3844505c676f70707070707070706c62574b3f3226190c06101a252f39434e58626c707070707070707070706a6054483c2f23160a000000000002080d1113141414141414141414141414141414141414141414141414141414141414141312110f0c0906020000000000000000000000000000000000000000000013202c3946535f6c798693a0acb7aea6a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a0a09f9d9b9895918d88827c756e675f564d443b32281e1309000000000013202c3946535f6c798693a0acb2a79d9796969696969696969696969696969696969697989a9da1a5a8a49f99938c857d756d645a51473d33281d1308000000000000000000000000000c1824303c48535f6b76828d98a3aca1978c82786f665e57524d4b49494a4c50565e67717b86929da9a99e92867a6e62564a3d3125180c000000000000060f1720282f363c42474c4f5355575859595959585654524f4b47423d37312a2b333a41464b4f51535454545352504e4c49443c342a20150900000000000000000000030a11171c21262a2d30323435363636363533312f2c2925211d17120c0f151b2125292c2e30303030302f2d2b2927231e18110900000000000000000000000000051019222a303538393939393936312b231a1107000000000000000000000000121f2c3845525f6b7885929eabafa296897c6f6356493d3023170a00000000000000000000000000000000000000000000000e1a2734414d5a6773818d9aa6b3a79b8e8174685b4e4235281b0f0013202c3946535f6c798693a0acaca09386796c5f5346392c201306060606060606060606060606060606060606060606060606060503000000000000000000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c20130600000000000000000000000006101a242e374049515860666d73787d82868a8e9194979b9ea1a4a8aaacada09489837d77716a635c544b42392f251b1006000000000f1b27333f4a545c616261605f5e5d5c5b5a5959585a6774818d9a9e9184786b5e5758595a5b5c5d5e5f606162625e574d42372b1f1306000915212d3945515d68737e8a949ea8b1b9c0c5c9cac9c6c1bab2aaa0968c81766b6054483c3024180c00000915202b36404b56616d78848f9b9185796d61554c57626d7984909b9084786c6054483b2f23160a00000915202b36404b56616d78848f9b9185796d6155493d3124180c00000000000000000000000000000000000000000000000000000000000710181f25292c2c2c2c2c2c2c2a26211a130a010811192025292c2c2c2c2c2c2c2a26201a1209000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c787d7d7d7d7d7d7d7d73665a4d4034271a0d0e18222c36414b555f6a747d7d7d7d7d7d7d7d7d7c7064574a3e3124170b00000000060d14191d2020202020202020202020202020202020202020202020202020202020202020201f1d1b1916120e0904000000000000000000000000000000000000000013202c3946535f6c798693a0acb9afa8a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a4a5a6a9a8a5a19d99948e87807971685f564d433a2f251b10050000000013202c3946535f6c798693a0acada1958b8989898989898989898989898989898989898a8c8e9195999ea4aaa49e978f877f766c63594f443a2f24190e02000000000000000000000004101c2834404c5864707b87939ea9a69b90857a70665d544c46413e3d3c3d40444c555f6a75818d99a09f9e968a7e7266594d4134281b0f0000000000040e182129323941474e53585c5f626465666666666563615e5b57534e48423c35353d454c52575b5e60616161605f5d5b58554e463c31261a0e020000000000000000060e151c22282d3236393c3f41424243434241403e3c3935322d28231d171920272c3135383b3c3d3d3d3d3b3a3836332f2a231b12080000000000000000000000010c17212b343c41454646464645423c352c23180e020000000000000000000000131f2c3946525f6c7986929facafa295887b6f6255493c2f22160900000000000000000000000000000000000000000000000d1a2633404d596673808c99a6b3a89b8f8275685b4f4235281c0f0013202c3946535f6c798693a0acaca09386796c5f5346392c2013131313131313131313131313131313131313131313131313131312100c0701000000000000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000000000020d17222c364049525b636a71787e84898e92969a9ea1a4a19e9b9b9c9d9fa2a0948984807b756f6860574e453c32281d1308000000000b17222e38424b5155555453535151504f4e4d4c4d596673808c999d9084776a5d514b4d4d4e4f50515253545555534d453b31261a0e02000c1825313d4955616d7985909ba6b0bac3cbd1d5d7d5d2ccc4bcb2a89e93887c7065594d4034281c0f0300040f19242f3a45505c67737e8a96968a7d7165594d515c68737f8b9794887c7064574b3f3226190d0000040f19242f3a45505c67737e8a96968a7d7165594d4034271b0f020000000000000000000000000000000000000000000000000000000000060d14191d1f20202020201f1e1a161009010000070e14191d1f20202020201f1d1a150f0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c79868a8a8a8a8a8a8173675a4d4034271a0d151f2a343e48535d67717c868a8a8a8a8a8a8a82786d6256493d3023170a000000060f181f25292c2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2c2a2825221e1a15100a0400000000000000000000000000000000000013202c3946535f6c798693a0acb2a79d9796969696969696969696969696969696969697989a9c9fa3a7a9a49f99928b837a71685f554c41372c21170b0000000013202c3946535f6c798693a0acaca093867c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7d7d7f8285888d9399a0a7a9a19991887e756b61564b40352a1f140800000000000000000002040814202c3845515d6975818c98a4ada1968a7e73695e544b423b3532303030333a434d5964707c8994949392918e8275695c5043372a1e1100000000020c16202a333b444b52595e64686b6e70727373737271706d6b67635f59544d463f3e474f575d63676a6c6d6d6d6d6b6a676560584d42372b1e12060000000000000007101820272d34393e4246494b4d4e4f4f4f4f4e4d4b4845423e39342e2822232b32383d414547494a4a4a49484745423f3b342d241a0f050000000000000000000006121e29333d464d5153535353524e473e352a1f1408000000000000000000000013202c3946535f6c7986929facaea295887b6e6155483b2f22150800000000000000000000000000000000000000000000000d1926333f4c5966727f8c99a6b2a99c8f8275695c4f4236291c0f0013202c3946535f6c798693a0acaca09386796c5f5346392c202020202020202020202020202020202020202020202020202020201f1c18120b040000000000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c201306000000000000000000000008131e29343e48525b646d747c83898f959a9ea2a4a09c9995928f8e8f909395999b93908c868079726961574e44392f24190e0300000006111c263039404548494847464544434241403f4c5865727e8b989c8f8276695c4f43404142434445454647484946423b33291f140900000f1b2834404d5965727e8a96a1adb7c2ccd5dce2e3e2ded6cec4baafa4998d8175695d5044372b1f1206000008121d28343f4a56626e7a86929a8d8175685c504b57636e7a8793988c8073675a4e4135281c0f03000008131d28343f4a56626e7a86929a8d8175685c5043372a1e110400000000000000000000000000000000000000000000000000000000000002080d1012131313131313110e0a05000000000003090d1112131313131313110e09040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693979797978d8173675a4d4034271a121d27313b46505a646f79838d97979797978f857a70665c51463a2e2115080000040f1821293036393a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a39383734322e2a26211b150e08000000000000000000000000000000000013202c3946535f6c798693a0acada1958b8989898989898989898989898989898989898a8b8d9093979ca1a7aaa49c958c847a71675d53493e33281d110600000013202c3946535f6c798693a0acaca09386796f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f70717275787c82878e959ea6aba39a91877d72685d52473b3025190d02000000000000040a0e11121724303c4855616d7985919da9a89c9085796d62574c4239302a2523232428313c4854606d798688878685848382786b5e5145382b1e120000000009141e28323c454d555d646a6f74787b7d7e8080807f7e7c7a77736f6a655f58514946505961686e7377797a7a7a79787674716a5f53473a2e211408000000000000071019222a31383f454a4e5255585a5b5c5c5c5c5b595755514e4a453f3a332c2d353d43494e515456575757565553514f4b463f362c21160a000000000000000000000a17232f3a454f585e5f5f5f5f5e5950463b3024180c000000000000000000000013202c3946535f6c798693a0acaea295887b6e6155483b2e22150800000000000000000000000000000000000000000000000c1926323f4c5965727f8c99a6b2a99c8f8275695c4f4236291c0f0013202c3946535f6c798693a0acaca09386796c5f5346392c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b28231d160d0400000000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c20130600000000000000000000020e1924303a45505a646d767e878e949ba0a5a19d9894908c89868282828486898d92979c97928b847b736960564b41362b201409000000000a141e272e35393c3c3b3a393837363534333e4b5764717d8a979b8e8275685b4f42353435363738393a3b3c3c3a36302921170d030000111d2a3643505c6975828e9aa6b2bec9d4dee7eef0eee8e0d6ccc1b5a99d9185786c6053473a2d21140800030e19242d363e46515d6976828e9b9184786b5f5246525e6a76838f9b8f8376695d5044372b1e110500030f1a242e373f45515d6976828e9b9184786b5f5245392c20130600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0a4a49a8d8173675a4d4034271a1a242e39434d58626c76818b959fa4a49c91877d73685e544a3f35291d110500000b16202a333b414547474747474747474747474747474747474747474747474747474747474747464543413e3a36322c262019120a0200000000000000000000000000000013202c3946535f6c798693a0acaca093867c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7d7e8183878b90969ca4aca79e968d83796f655a4f44392e23170c00000013202c3946535f6c798693a0acaca09386796c636363636363636363636363636363636466696c71767c848c949da7aca3998f84796e63584d41352a1e12060000000000080f151a1d1f1f2733404c5865717d8995a1ada4988c8074685c51463b30261f1f1f1f1f202c3845515e6a767c7b7a797877767572685c5044372b1e1100000005101b26303a444e575f676f757b8084878a8b8c8d8c8c8b898783807b76706a635b534d58626b737a808386878787868583817b6f6255483c2f2215090000000000061019232b343c434a50555a5e6264666869696968676664615e5a55504b453e37373f474e545a5e60626363636361605e5b5750483d32271b0f030000000000000000000d1a26333f4b5761696c6c6c6c6a62584c4034281b0f0200000000000000000000131f2c3946525f6c7986929facaea295887b6f6255483c2f22150900000000000000000000000000000000000000000000000d192633404c596673808c99a6b2a89c8f8275685c4f4236291c0f0013202c3946535f6c798693a0acaca09386796c5f534639393939393939393939393939393939393939393939393939393939393938342f281f160c02000000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000000007131f2a36414c57616c767f8891989fa6a29c96918c8884807d79767576777a7d81868c939b9d968e857b72675d52473c31251a0e02000000020c151d24292d2f2f2e2d2c2b2a292928303d4a5663707c89969a8d8174675a4d41342728292a2b2c2d2e2f2f2e2a251f170f05000000121f2b3845515e6b7784919daab6c2cedae5f0f9fefaf2e8ddd2c6b9ada194887b6e6255483c2f2216090008141f2b353f484f545a66727e8b9893867a6d615450545a6773808c999185786c5f5246392d201307000814202b36404950555a66727e8b9893867a6d6154473b2e21150800000000000000000000000000000000000000000000000000000000000000000000010305060708080808080706050301000000000000000000000000000000000000000000000000000000000000000000000000000001030506070808080807060402000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a222c36404b555f69747e88929da7a89e948a80756b61574c42382e23180d010005111c27323c454d52535353535353535353535353535353535353535353535353535353535353535352504d4a47423d38322b241c140c03000000000000000000000000000013202c3946535f6c798693a0acaca09386796f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f70717274777a7f858b929aa2aba89f958b81766c61564a3f34281c1005000013202c3946535f6c798693a0acaca09386796c5f56565656565656565656565656565657595c60656b7279828b959faaaba0968b8074695e52463a2f23170a000000000a121a21262a2c2c2c37434f5c6874818d99a5aca094877b6f63574b40342c2c2c2c2c2c2c2c2c36424e5a656d6f6e6d6c6b6a69696760574c4034281c0f0000000b17222d37424c566069717980878c90949698999a9999979593908c87827b746d655d545f69737d858b9092949494939190887b6f6255483c2f22150900000000040e18222b353d464d555b61666a6e717375757676757472706d6a66615c565049413f49515960656a6d6f7070706f6e6c6a68625a4f43382b1f13060000000000000000000f1b2835424e5b67737979797974695c5043362a1d100400000000000000000000121f2c3945525f6b7885929fabafa295897c6f6256493c2f23160900000000000000000000000000000000000000000000000d1a2734404d5a6673808d9aa6b3a89b8e8275685b4f4235281c0f0013202c3946535f6c798693a0acaca09386796c5f534646464646464646464646464646464646464646464646464646464646464644403931281e1409000000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c201306000000000000000000000b17232f3b47525d68737e88919aa3a79f97918a85807c7874706d6a68696b6d71757b8289929ba0978d84796f64594d42362a1f130700000000030b12181d2022222221201f1e1d1c222f3c4955626f7b8895998c807366594c4033261c1d1d1e1f20212222211e1a140d050000000013202c3946535f6c7986929facb8c5d2deebf7fffffffaeee2d5c9bcafa396897c7063564a3d3023170a000c1824303c47515a606263707c899695887b6f62565b606264707d8a9693877a6d6154473b2e211508000c1825313c47525b616363707c899695887b6f6256493c2f231609000000000000000000000206090a0a0a0a0a0a0a0a0a0a080400000000000307090c0e1011131414151515151413110f0d0a0703000000000000000000000000000000000000000000000000000000000000000003070a0d10121314151515141412110f0c0905010004080a0a0a0a0a0a0a0a0a0a08050000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271f29333e48525c67717b86909aa4aba1968c82786e63594f453a30261c110700000915212d39444e575e606060606060606060606060606060606060606060606060606060606060605f5e5c5a57534e49433c352e261e150c030000000000000000000000000013202c3946535f6c798693a0acaca09386796c636363636363636363636363636363636465686b6e737980889099a3ada79d93887d72675c5044392d211509000013202c3946535f6c798693a0acaca09386796c5f53494949494949494949494949494a4b4d50545960687079838d98a3aea79c91867a6e63574b3f33271a0e02000008121c242c32363839393946525f6b7884909da9a99c9084776b5f53473b39393939393939393939383d48535c61636261605f5e5d5c5a564e453a2f24180c000005111d28333e49545e68727b838b92989ca0a3a5a5a3a2a2a2a29f9c98938d867f776e665d65707b868f969c9fa0a1a0a09e95887b6f6255483c2f221509000000000b16202a343e474f585f666d72777a7d808182838382817f7d7a76726d67615a534b47515b636b7176797c7d7d7d7c7b7977746b6054473b2e2115080000000000000000000f1c2835424f5b687582868684776a5d5044372a1d110400000000000000000000121f2b3845515e6b7884919eabb0a3968a7d7063574a3d3024170a00000000000000000000000000000000000000000000000f1b2835414e5b6774818e9aa7b4a79a8e8174675b4e4134281b0e0013202c3946535f6c798693a0acaca09386796c5f5353535353535353535353535353535353535353535353535353535353535353504b433a30251a0e030000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c201306000000000000000000030f1b2834404c57636f7a858f9aa3a69d958d867f7974706c6864615d5b5c5e61656a70778089939e9f958b80756a5e53473b2f23170a000000000000070d1114161615141312111015212e3b4854616e7a8794988b7e7265584b3f322519101112131415161615120e0902000000000013202c3946535f6c798693a0acb9c6d3dfecf9fffffffdf0e3d6cabdb0a3978a7d7063574a3d3024170a000e1b2834404d58636c6f6f6f7b8894968a7d706359646c6f6f6f7b889595887b6f6255493c2f231609000f1b2834414d59646d6f6f6f7b8794968a7d7063574a3d3124170a000000000000000001080e12151717171717171717171614100b0504080c101316181b1d1e1f20212122222121201e1c1a17130f0b0601000000000000000000000000000000000000000000000000000000060b0f13171a1c1e202121222221201f1d1b1815120d0b10141617171717171717171614110c06000000000013202c3946535f6c798693a0aca79a8d8173675a4d40342727313b45505a646e78838d97a2aca3998f857a70665c51473d33291e140a0000000b1825313d495560696d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6c6b6966635f5a544e47403830271e150b0100000000000000000000000013202c3946535f6c798693a0acaca09386796c5f56565656565656565656565656565657595b5e63686e767e87919ba6afa59a8f84786d6155493d3125190d010013202c3946535f6c798693a0acaca09386796c5f53463c3c3c3c3c3c3c3c3c3c3c3c3d3e4044484e565e67717b86919da8aea2978b7f73675b4f43372a1e12050004101a242e363d42454646464855616e7a8793a0aca6998d8174685b4f4646464646464646464646464541414a5155565554535251504f4e4a443c33291e130700000a16222e3944505b65707a848d959da3a8a7a19c999695959596989a9d9e98918981786f656b76828d97a1a7aba39c97939293887b6f6255483c2f22150900000007121d27323c465059616a71787d83878a8c8e8f908f8f8d8c8986827e78736c655d554f59636d757c8286888a8a8a898886837b6f6255483c2f2215090000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000111e2a3744515d6a7784909daab1a4978b7e7165584b3f3225190c0000000000000000000000000000000000000000000003101d2936434f5c6975828f9ba8b3a6998c8073665a4d4034271a0d0013202c3946535f6c798693a0acaca09386796c5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5c554c42372b1f13070000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c20130600000000000000000006121f2b3744505c6874808b96a1a99e958b837b746e68645f5c5854514e505155595e656e77818c97a39d92867b6f63574b3f33261a0e01000000000000010507090908070605030714202d3a4753606d798693978a7d7164574a3e3124180b020506070809090806020000000000000013202c3946535f6c7986929facb8c5d1deeaf6fffffff8ede1d5c8bcafa396897c706356493d3023170a00101c2936434f5c69757b7b7b7b8794978b7e71645d69767b7b7b7b889496897c706356493d3023160a00101c2936434f5c69757c7c7c7c8794978b7e7164574b3e3125180b00000000000000040c13191e2223242424242424242423201c17101014181c1f222527292b2c2d2e2e2e2e2e2d2c2b2926231f1b17120c07000000000000000000000000000000000000000000000000060c11161b1f2326292b2c2e2e2e2e2e2d2c2a2825211e19171c2023242424242424242423211d1711090100000013202c3946535f6c798693a0aca79a8d8173675a4d4034272e38434d57616c76808b959fa9a69c91877d73685e544a40352b21170d020000000d1a2633404c5966727a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a797875736f6a655f59524a423930271d130900000000000000000000000013202c3946535f6c798693a0acaca09386796c5f53494949494949494949494949494a4b4c4f52575d646c757f8a949fababa095897d72665a4e4135291d11040013202c3946535f6c798693a0acaca09386796c5f5346393030303030303030303030303234383d444c555f6a75808c98a3afa79c9084776b5f53463a2d211508000a16212c3640484e52525252525764707d8a96a3afa3978a7e71655852525252525252525252525252514d463f45484948474645444342413e39322a21170c0100030f1b27333e4a56616c77828c969fa7aca39c96908c8a888888898b8e91959a9b938a81776d6f7b87939ea9ada299918b878686887b6f6255483c2f2215090000010d18232e39444e58616b737b83898e9396999b9c9c9c9b9a9896928e8a847e776f675f56606b757f878d9295969796969492887b6f6255483c2f2215090000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000101d2936434f5c6975828f9ba8b2a5998c8073665a4d4034271b0e0200000000000000000000000000000000000000000006121f2b3845515e6a7784909da9b1a4988b7e7265584c3f3226190c0013202c3946535f6c798693a0acaca09386796c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c675e53473b2f2216090000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000000815212e3a4753606c7884909ca8a2978d83797169635d58534f4c4845424345484d545c65707b87929fa3978c8073675b4f4236291d10040000000000000000000000000000000006131f2c3946525f6c78859296897c6f6356493d3023170a0000000000000000000000000000000000121f2b3845515e6b7784909da9b6c2cedae4eef6f8f6f0e7dcd1c5b9ada094877b6e6255483c2f22160900101c2936434f5c6976838888888b96988b7e71655d6a77848888888c96978a7d7063574a3d3024170a00101c2936434f5c6976838989898c96988b7e7165584b3e3225180b000000000000030d161e252a2e3030303030303030302f2d28221a1c2024282c2f31343637393a3a3b3b3b3b3a393735322f2c27231e18120b040000000000000000000000000000000000000000030a11171d22272b2f323537393a3b3b3b3b3a383634312e2a2522282d2f3030303030303030302d28221b130a00000013202c3946535f6c798693a0aca79a8d8173675a4d40342b36404a555f69737d88929ca7a89e948a80756b61574c42382e24190f05000000000d1a2633404d596673808787878787878787878787878787878787878787878787878787878787878684827f7b76716a635c544b42392f251b1106000000000000000000000013202c3946535f6c798693a0acaca09386796c5f53463c3c3c3c3c3c3c3c3c3c3c3c3d3e4042464b525a636d78838e9aa5b1a69a8e82766a5e5145392c2014070013202c3946535f6c798693a0acaca09386796c5f5346392c232323232323232323232325282c323a434d58646f7b87939facaca093877b6e6256493d3024170a000e1a26323d48525a5e5f5f5f5f5f66737f8c98a5aea195887b6f625f5f5f5f5f5f5f5f5f5f5f5f5f5f5e5850463b3c3c3b3a393938373635322e2820180f05000007131f2b37434f5b67727d89939ea8ada39a928a85807d7b7b7b7c7e8185898f959b93898075727e8b97a3afa79b91877f7a79797b7a6e6255483c2f221509000007121e2935404b55606a737d858d949a9fa3a5a6a2a09f9f9fa0a19e9a958f89817971685f66727d8791999ea2a3a4a09d9c95887b6f6255483c2f2215090000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000f1b2835414e5a6774818d9aa6b3a79b8e8175685c4f43362a1d11050000000000000000000000000000000000000000000915212e3a4753606c7986929fabafa396897d7063574a3e3124180b0013202c3946535f6c798693a0acaca0938679797979797979797979797979797979797979797979797979797979797979797979797063574a3e3124170b0000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000000a1723303d4956626f7b8894a1a99d91867b70675f58514c47433f3c383536393c424a535e6a76838f9ba89c9083776a5e5145382c1f12060000000000000000000000000000000005121e2b3845515e6b77849195887b6f6255483c2f2216090000000000000000000000000000000000101d2a36434f5c6875818e9aa6b2bdc8d3dce4eaeceae5ded5cbc0b5a99d9185786c5f53463a2d21140700101c2936434f5c697683909595969d988c7e72655d6a7784909595979e978a7d7164574a3e3124170b00101c2936434f5c697683909696979e988c7e7265584c3f3225190c0000000000000b151f282f363a3d3d3d3d3d3d3d3d3d3c39332c24272c3034383b3e40424445474748484848474644423f3c38332e29231d160e07000000000000000000000000000000000000050d141c22282e33373b3f4244464748484847464543403d3a36312c33393c3d3d3d3d3d3d3d3d3c39342d251c1207000013202c3946535f6c798693a0aca79a8d8173675a4d4034333d48525c66717b858f9aa4aba1968c82786e63594f453b30261c120800000000000d1a2633404d596673808d949494949494949494949494949494949494949494949494949494949392918e8b87827c756e665d544b41372d22180d020000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346393030303030303030303030303133363a4048515c66727d8995a1adaa9e92867a6d6155483c2f23160a0013202c3946535f6c798693a0acaca09386796c5f5346392c2016161616161616161617181b2028313c47535f6b7783909ca9afa3978a7e7165584b3f3226190c00111e2a36434f5a646b6c6c6c6c6c6c75818e9ba7ac9f9386796d6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6a62574c4034302f2e2d2c2b2a292826221d160f060000000a16222f3b47535f6b77838f9aa5b0a59b9188807974706f6e6f707275797e838a919891877d75828e9aa7aea2968a7f756e6c6d6e6f685e52463a2d21140800000b17232f3a46515c67727c868f979fa6aba49e9a96939292929395979b9f9a938b837a71676c77838e99a3aaa9a09994919090887b6f6255483c2f2215090000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000d1a26333f4c5965727e8b98a4b1a99d9084776b5e5245392d2014080000000000000000000000000000000000000000000c1825313d4a56626f7b8894a1adada094877b6e6255483c2f2316090013202c3946535f6c798693a0acada09489868686868686868686868686868686868686868686868686868686868686868686867e7164574b3e3124180b0000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000000b1825313e4b5764717d8a97a3a6998d8175695f554d46403b3733302c292a2c3138424e5a6773808d99a69f9286796d6053473a2d2114070000000000000000000000000000000002111d2a3743505d6a76839094877a6d6154473b2e21150800000000000000000000000000000000000e1b2734404d5965717d8995a1acb6c1cad2d9dedfdedad4ccc3b9aea3988c8175685c5044372b1e120500101c2936434f5c697683909ca2a3a5988c7e72655d6a7784909da2a3a4978a7d7164574a3e3124170b00101c2936434f5c697683909ca3a4a5988c7e7265584c3f3225190c000000000006121d27313a41474a4a4a4a4a4a4a4a4a49443e362d33383c4144484a4d4f51525354545555545352504e4b48443f3a342e272019110800000000000000000000000000000000070f171f262d33393f43484b4e515254545555545352504d4a46423d373e44494a4a4a4a4a4a4a4a49453f372e24190e020013202c3946535f6c798693a0aca79a8d8173675a4d40343b454f59646e78838d97a1aba3998f857a70665c51473d33291e140a0000000000000d1a2633404d596673808d9aa0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09f9d9b97938d8780786f665d53493f34291e13080000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c232323232323232323232324272a2f363f4a55616d7985919daaaea296897d7064574b3e3225180c0013202c3946535f6c798693a0acaca09386796c5f5346392c201309090909090909090a0c0f16202b36424f5b6774818d9aa6b2a6998d8073675a4d4134271b0e00131f2c3946525f6b767979797979797983909ca9aa9e9184797979797979797979797979797979797974685c5044382c2221201f1e1d1c1b1916110b04000000000c1925323e4b57636f7c8894a0abaa9f94897f766e68646261626365696d72787f868e978f847984909da9aa9e9286796d635f6062635e564c41362a1e12050004101c2834404b57626d78838e98a1a9aaa19a938e8a8785858586888b8e93989d958c83796f707c8894a0ababa1978e88848383857b6f6255483c2f2215090000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000b1824313e4a5763707c8995a2aeac9f93877a6e6155493d3024180c010000000000000000000000000000000000000005111d2935414d5966727e8b97a3b0aa9e9185786c5f53463a2d2114070013202c3946535f6c798693a0acb0a59b949393939393939393939393939393939393939393939393939393939393939393938b7e7164574b3e3124180b0000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000000b1825323e4b5865717e8b98a5a4978a7e7165584d433b35302b2723201c1f242b333f4c5966727f8c99a6a194877b6e6154483b2e2215080000000000000000000000000000000003111e2a3744515d6a77849094877b6e6155483b2e22150800000000000000000000000000000000000c1824313d4955616d79848f9aa5afb8c0c8ced1d2d1cec9c2bab1a79d92877b7064584c4034281b0f0300101c2936434f5c697683909ca9afa5988c7e72655d6a7784909daaafa4978a7d7164574a3e3124170b00101c2936434f5c697683909ca9b0a5988c7e7265584c3f3225190c00000000000b17232e39434c525657575757575757575550483f373e44484d515457595c5d5f606161616161605f5d5b5854504b454039322b231a11080000000000000000000000000000071019212931383f454a4f54575b5d5f6061616161605e5c5956524d4842485055575757575757575755504940352a1f13070013202c3946535f6c798693a0aca79a8d8173675a4d4038424d57616b75808a949fa9a69c91877d73695e544a40352b21170d020000000000000d1a2633404d596673808d9aa6adadaba6a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a6a8aaa7a39e98918a81786f655b50463b3024190d0200000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2016161616161616161617181a1e242e3944505d6975828e9ba7b1a5988c7f7266594d4033271a0d0013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000040e1a26333f4c5965727e8b98a5b1a89b8e8275685b4f4235291c0f0013202c3946525f6c788486868686868687929eabaa9e92878686868686868686868686868686868685786c6054483c2f231713121110100f0d0a060000000000000f1b2834414d5a6673808c98a4b0a59a8e82776d645c5855555557595d61676d747c858e968b8085919eaba89b8f8276695d53535556534d443b3025190e02000714202c3844505c68737f8a95a0aaaba1988f88827d7a7978797a7c7e82878c9299958b817773808c98a4b0a59a8f857d78767678786e6155483b2f2215080000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000916222f3b4854616d7a86929fabafa2968a7d7165594d4135291d1206000000000000000000000000000000000000000a16212d3945515d6975828e9aa6b3a79b8f8276695d5044372b1e12050013202c3946535f6c798693a0acb7ada5a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0988b7e7164574b3e3124180b0000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000000b1825323e4b5865717e8b98a4a4978a7d7063574a3d312a241f1b1f23272b30363d454f5b6774818d9aa6a295887b6e6155483b2e2215080000000000000000000000000000000005121f2b3845525e6b78849195887c6f6255493c2f23160900000000000000000000000000000000000815212d3945505c68737e89939da6aeb6bdc2c5c5c5c2beb7b0a89e958b80756a5f53483c3024180c0000101c2936434f5c697683909ca9aca5988c7e72655d6a7784909daaaca4978a7d7164574a3e3124170b00101c2936434f5c697683909ca9aca5988c7e7265584c3f3225190c00000000000f1c28343f4b555d636363636363636363615a514640484f54595d606366686a6b6d6d6e6e6e6e6d6b6a6764605c57514b443c352c231a1108000000000000000000000000060f19222b333b424950565b6064676a6c6d6e6e6e6d6c6b6966625e59544e515a616363636363636363615b51473b3024170b0013202c3946535f6c798693a0aca79a8d8173675a4d40404a545e69737d87929ca6a89e948a80756b61574c42382e24190f05000000000000000d1a2633404d596673808d9aa6afaba19a98989898989898989898989898989898989898989898999b9ea3a8aaa39c938a81776d62574c41352a1e130700000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201309090909090909090a0b0e121c2834414d5a6673808c99a5b2a79a8e8174675b4e4135281b0f0013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000b1824313e4a5764717d8a97a4b0a99c8f8276695c4f4336291c1000111e2b37434f5c6874808c92929292929399a3aeaea3999392929292929292929292929292929292887c7064584b3f33271b0f0604010000000000000000000000111d2a3643505c6975828f9ba8aea295897d71665b524c4948484a4d51565c636a727b858e918788939faca69a8d8174675a4e47494947423b32291e140800000a1723303c4854606c7884909ba7afa4998f867d76716e6c6b6c6d6f72767b81878e9693897e75828f9ba8ada195897d736b696a6c6d665d5145392d2014070000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000713202c3945515e6a77838f9ca8b2a6998d8175695d51453a2e23180d02000000000000000000000000000000000006111c27323e4a55616d7985929eaab0a4988b7f73665a4e4135281c0f030013202c3946535f6c798693a0acb9b1aaa6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a4988b7e7164574b3e3124180b0000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000000b1824313e4a5764707d8a96a3a4978b7e7165584c40352e2926282b2f33373c41474e57616c7783909ca8a194877b6e6154483b2e221508000000000000000000000000000000000613202c3946535f6c79869296897d7063574a3d3024170a000000000000000000000000000000000004101c2834404b56616c77818b949da4acb1b5b8b9b8b6b2aca69e958c83796f64594e42372b1f14080000101c2936434f5c697683909ca0a0a0988c7e72655d6a7784909da0a0a0978a7d7164574a3e3124170b00101c2936434f5c697683909ca0a0a0988c7e7265584c3f3225190c0000000000121e2b3844505c676f70707070707070706c62574b48525a6065696d7072757778797a7b7b7b7b7a787673706c67625c554e463e352c2319100500000000000000000000040e18212b343d454d545b61676c707376787a7b7b7b7a797775726e6a655f5957626c70707070707070706d63584c4033271a0e0013202c3946535f6c798693a0aca79a8d8173675a4d4047515c66707a858f99a3aba1968c82786e63594f453b30261c120800000000000000000d1a2633404d596673808d969da5a5998f8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8c8f92979da4aca59d93897e74695d52463b2f23170b00000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000020c1925323e4b5864717e8b97a4b1a89c8f8275695c4f4236291c100013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000a1724303d4a5763707d8a97a4b0a99c908376695c4f4336291c10000f1b27333f4c5864707c89959f9f9f9fa0a4abb5b4aba39f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f988c8074685b4f43372b1f120600000000000000000000000000121f2b3845515e6b7784919daaab9f9286796d615549403c3b3c3d40454a51586069737c879193949aa4b0a6998c807366594c403c3d3b36302920170d0200000d1a26333f4b5864707c8995a1aca99e92887d746c65615f5f5f6063666a70767c848c9590867b84909daaaa9d9185786c615d5d5f605c544b4035291d11050000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000004101d2936424e5b6773808c98a4b0a99d9185796e62564b3f34291e140a01000000000000000000000000000000040e18222d38434f5a66727d8a96a2aeaca094887c6f63574a3e3225190d000013202c3946535f6c798693a0acb3a89f9a9999999999999999999999999999999999999999999999999999999999999999988b7e7164574b3e3124180b0000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000000916232f3c4855616e7a87939fa6998d8174685c51473f39353334373b3f43474c52596069737d8994a0ab9f9286796c6053473a2d21140700000000000004080a0c0c0b0a0908070714212d3a4754606d7a8693978a7d7164574b3e3125180b0708090a0b0c0c0b080500000000000000000c17232f3a45505b656f78828b939aa0a5a9abacaba9a6a19b948c847a71675d52473d31261a0f030000101c2936434f5c6976839093939393938c7e72655d6a77849093939393938a7d7164574a3e3124170b00101c2936434f5c6976839093939393938c7e7265584c3f3225190c000000000013202c3946535f6c787d7d7d7d7d7d7d7d73665a4d4e59646c7175797c7f818385868788888887868583807c78736d67605850473e352b21170d020000000000000000010b16202a333d464f575f666c72787c80838587888888878684827e7a76706a635c67737d7d7d7d7d7d7d7d74685b4e4135281b0f0013202c3946535f6c798693a0aca79a8d8173675a4d454f59636e78828c97a1aba3998f857a70665c52473d33291f140a0000000000000000000d1a2633404d5966737e858c939ba4978a807e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e8082868c929aa2aba59b90857a6e63574b4034281c0f03000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000a1724313d4a5763707d8a97a4b0a99c908376695c4f4336291c100013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000b1824313e4a5764717d8a97a4b0a99c908376695c4f4336291c10000b1723303c4854606c798591989898989ba2abb6ada39b98989898989898989898989898989898989084786b5f53473b2e22160900000000000000000000000000131f2c3946525f6c7985929fabaa9d9084776a5e5145382f2e2f3134393f464e57616a75808a95a0a5acb2a6998c7f7265594c3f32302e2b251f170e050000000f1c2835424e5b6773808c99a5b1a5988d81766b625a5553525254565a5f646b727a838c958c8185929eaba89b8e8275695c50505353504a42392f24180d010000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000010d1a26323f4b57636f7c8894a0acaea2968a7e73675c51463b30261c130a0300000000000000000000000000050d16202a343f4a55606b77838e9aa6b2a89c9084786c5f53473b2f22160a000013202c3946535f6c798693a0acaea2978e8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8b7e7164574b3e3124180b0000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000000714202d3946525e6a76838e9aa59c9085796e6359514a45413f4044474b4f53585d646a727b858f9aa5a79b8f83766a5e5145382b1f120600000000030a0f1417191918171615141315222e3b4855616e7b8894988b7e7265594c3f32261913141516161718181715110b0500000000000007121d28333e49535d66707881888f95999d9f9f9f9d9a959089827a71685f554b41362b201509000000101c2936434f5c697683868686868686867e72655d6a7784868686868686867d7164574a3e3124170b00101c2936434f5c697683868686868686867e7265584c3f3225190c000000000013202c3946535f6c79868a8a8a8a8a8a8173675a4d515d6a767d8185898c8e909293949495959493918f8c88847e78726a625950473d33291e1308000000000000000007121d27323c454f58616970777e83888c8f92939495949493918e8b86817b756e666875828a8a8a8a8a8a8174675a4e4134281b0e0013202c3946535f6c798693a0aca79a8d8173675a524c56616b75808a949ea8a69c91877d73695e544a40362b21170d020000000000000000000c1925323e4b57636d737a8189929b9b918b837b7371717171717171717171717171717171717173767a81889099a3aca2968b8074685c5044382c1f1307000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000a1724303d4a5763707d8a97a4b0a99c908376695c4f4336291c100013202c3946535f6c798693a0acaca09386796c5f5346392c201306010101010101010204070f1a26333f4c5865727e8b98a4b1a89c8f8275695c4f4236291c0f000713202c3844505c6975818c8c8c8c8c909aa6b2a79c918c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c887b6f63574a3e3125180b0000000000000000000000000013202c3946535f6c798693a0acaa9d908376695d5043362a222225282e353c454f59636e79848f9ba7b2b2a6998c7f7265594c3f3226221f1a140d0500000000111e2a3743505d6976838f9ca8ada195887c7065595049464546474a4e535960687079838d938a8b94a0ada69a8d8073675a4d444647443f3930271d1207000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000000a16232f3b47535f6b77848f9ba7b2a69b8f84786d62574c42382e251c150e0804000000000000000001050a10171f28323c46505b66717c88939fabafa3978c8074685b4f43372b1f1306000013202c3946535f6c798693a0acaca093867f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7e7164574b3e3124180b0000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c20130600000000000000000005111d2a36424e5a66727d89949ea1968a80756b635c56514e4c4d5053575b5f64696f757c858d97a1aba0968a7e72665a4e4235291c1003000000050d151b202425252424232221201f232f3c4956626f7c8895998c807366594d4033271e1f2021222324252524211c170f080000000000010c17222d37414b545e666f767d84898d90929392908e8a857e7870685f564d43392f241a0f04000000101c2936424f5c687479797979797979797970645c69747979797979797979796f63574a3d3124170a00101c2936424f5c68747979797979797979797064584b3e3225180c000000000013202c3946535f6c798693979797978d8173675a4d515e6b77848d9195989b9d9ea0a0a1a2a1a1a09e9c9894908a847c746b62594f453b30251a0e03000000000000030e19242f39434e57616a737b82898f94989c9ea0a1a2a1a09f9d9a97928d8780786f6976838f979797978d8073665a4d4033271a0d0013202c3946535f6c798693a0aca79a8d81746c645c545e68727d87919ca6a89e948a80756b61574c42382e24190f05000000000000000000000a16222f3a46515b62686f778089929b9c958d857b726864646464646464646464646464646465666a6f767e87919ca7a89c9084786c6054483b2f23160a000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000001040c1825323e4b5764717d8a97a4b1a99c8f8276695c4f4336291c100013202c3946535f6c798693a0acaca09386796c5f5346392c20130d0d0d0d0d0d0e0e0f101318202b37434f5b6774818d99a6b3a79a8d8174675b4e4135281b0f0003101c2834404c5965717d7e7e7e7e7e8a97a4b0a5988c7f7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7265584b3f3225180c0000000000000000000000000013202c3946535f6c798693a0acaa9d908376695d5043372a1d16181d232b333d47515c67737e8a96a2aeb2a6998c7f7265594c3f322619120e09020000000000121f2b3845525e6b7884919eaaab9e9285796c6054483e3938393b3e42484f565e67717b859096969ca6b1a6998c7f7266594c3f393a38342e271e150b01000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000007131f2b37434f5b67737f8b96a2adaca0958a7e73695e544a40372e261f1914100c0a09080708090b0d11151b2229313a444e58626d77838e99a4b0a99e92877b6f63574b3f33271b0f03000013202c3946535f6c798693a0acaca0938679727272727272727272727272727272727272727272727272727272727272727272726c6155493d3023170a0000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c201306000000000000000000010e1a26323e4a55616c77828c96a09c91877e756d67615d5a58595c6063676b70757a80878e969fa9a3998f84796d62564a3e3226190d010000040e171f262c30323231302f2e2d2c2b2b303d4a5763707d8a969a8d8174675b4e41342a2b2c2d2e2f30313232312d2821191107000000000006101b252f39424c545d656c72787d818485868584817d79736d665e564d443b31271d1308000000000e1b2733404c57626a6c6c6c6c6c6c6c6c6c685f58626a6c6c6c6c6c6c6c6c6c675e53473b2e221609000e1b2733404c57626a6c6c6c6c6c6c6c6c6c685f54483c3023170a000000000013202c3946535f6c798693a0a4a49a8d8173675a4d515e6b7885929da1a4a7a5a3a1a09f9e9e9fa1a3a7a5a09b958e867e756b61574c41362b20140800000000000009141f2a35404b555f69737c858d949aa0a4a8a6a29f9d9c9c9c9d9ea19e98918a81786f7784909da4a4998c807366594c403326190d0013202c3946535f6c798693a0aca89b90877e766e665e66707a848f99a3aba1978c82786e63594f453b30261c1208000000000000000000000006121e2a353f4951575e656d76808a949e9f978d84796f645957575757575757575757575757585a5e646c75808a96a1ada195887c7064574b3e3225190c000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130b0b0b0b0b0b0b0c0c0e10141c2834404d5966727f8c98a5b2a89b8e8275685b4f4235291c0f0013202c3946535f6c798693a0acaca09386796c5f5346392c201a1a1a1a1a1a1a1a1a1b1d1f232a323c47535f6b7783909ca8b1a5988c7f7266594d4033271a0d00000c1824303d4955616b72727272727d8a97a4b0a4988b7e727272727272727272727272727272727272726c62564a3d3124180b00000000000000000000000000131f2c3946525f6c7885929fabaa9d9184776b5e5245392c231f1c1b1a212b35404b56626e7986929eaab2a6998c7f7265594c3f3226190c020000000000000013202c3946525f6c7986929facaa9d9084776a5d5144382d2c2c2e32373d444c555f69737e89949fa7aeb2a6998c7f7265594c3f322d2b28231c150c0300000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000000030f1b27333f4b57626e7a85919ca7b1a69b90857a70665c52494038312a25201c19171515141516171a1d21262c333b434c565f6a747e89949faaafa4988d82766a5e53473b2f23170b00000013202c3946535f6c798693a0acaca09386796c656565656565656565656565656565656565656565656565656565656565656565625a5045392d2114080000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c201306000000000000000000000a16212d3944505b66707a858e979f9990877f78726d6a676566696c6f73777b81868b9299a0a8a29a91877d72685c51453a2e22160a0000010c16202931373c3f3f3e3d3c3b3a393837363e4b5864717e8a979b8e8275685b4f42363738393a3b3c3d3e3f3f3d39332b23190f04000000000009131d27303a424b535a61676d7175777879797775716d68625b544c443b32291f150b01000000000b17232f3b4650585e5f5f5f5f5f5f5f5f5f5d5650595e5f5f5f5f5f5f5f5f5f5c554c41362b1f1206000b17232f3b4650585e5f5f5f5f5f5f5f5f5f5d564d42372c201407000000000013202c3946535f6c798693a0aca79a8d8173675a4d515e6b7885929ea29f9b999694939292929294979ba0a6a6a09890877d73695e53473c3125190d0100000000030e1a25303c47525d67717b858e979ea5aba6a09b9693918f8f8f909294989c9c938a81777784919eaba6998c7f7265594c3f3226190c0013202c3946535f6c798693a0acaca2989088807870686d77828c96a0aba3998f857a70665c52473d33291f140a000000000000000000000000020d18232d373f464c535b646e78828d98a39f968b81766b5f544b4b4b4b4b4b4b4b4b4b4b4b4b4e535a636e7984909ca5a4988c8073665a4d4134281b0f000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20181818181818181819191a1d20262e3944505c6975828e9aa7b2a6998d8073675a4d4134271b0e0013202c3946535f6c798693a0acaca09386796c5f5346392c2727272727272727272728292c2f343c444e5964707b87939facaea295897c7063574a3e3125180c00030e18222d39444f596165656565717e8b98a4b0a4978a7d71656565656565656565656565656565656565625a50453a2e21150900000000000000000000000000121e2b3845515e6b7784919daaac9f93867a6d6155493e352f2b29272626252e3a45515d6975828e9aa7b2a6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0acaa9d908376695d5043362a1f2022262b323a434d57616c77838e9aa5b1b2a6998c7f7265594c3f32261f1c17120b030000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000000000b17222e3a46525d6974808b96a1acaca1978c82786e645b524a433c36302c28252322212121222426292d32383e454d565e68717b86909ba5b0a89d92877c7065594e42362a1f130700000013202c3946535f6c798693a0acaca09386796c5f59595959595959595959595959595959595959595959595959595959595959595650483e33281d11050000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000000005111c28333e49545e69737c858e959c99918a837e797673727275787c8083888c91979da3a7a09890887f756b61564b4034291d1106000007121d28323b43484b4c4b4a49484746454443424c5965727e8c989c8f8376695d504343444546474748494a4b4b49443d352b21160b0000000000010b151e283039414950565c6165686a6c6c6c6a6865615c57514a423a322920170d04000000000007131e29343e464d52535353535353535353514b474e52535353535353535353504b433a30251a0e020007131e29343e464d52535353535353535353514b443b31261b0f03000000000013202c3946535f6c798693a0aca79a8d8173675a4d525f6b7885929a96928f8c8a888685858586888b8f959ca3aaa2998f857a6f64594d41362a1e12050000000008131f2b36424d58636e79838d97a0a9aca39c958f8a86848282828385888c90969c93897e7885929eaba5988c7e7265584c3f3225190c0013202c3946535f6c798693a0acb3aaa29a928a827a71757f89949ea8a69c91877d73695e544a40362b21170d030000000000000000000000000007111b242d343a4149525c66707b86929da79d92877c7065594e423e3e3e3e3e3e3e3e3e3e3f4248525c6874808c989997968f8275695c5043362a1d11000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c252525252525252525252627292c3138404a55616d7985919daab0a3978a7e7165584c3f3226190d0013202c3946535f6c798693a0acaca09386796c5f53463934343434343434343434343536383b40464e56606a75818c98a4b0aa9e9286796d6154483b2f2216090008141f2a343d454b4f5658585865727e8b98a5b0a4978a7d706358585858585858585858585858585858585650483e34291d110500000000000000000000000000101d2a3643505c6975828e9ba7aea295897d71655a5047403b3836343332323235414d5966727e8b98a4b1a6998c7f7265594c3f3226190c000000000000000013202c3946535f6c7986939facaa9d9083766a5d5044372a1e15151a2128313b45505b66727d8995a1adb2a6998c7f7265594c3f322619100c0600000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000000006121e2935414c57636e79858f9aa5afa89e948a80766d645c544d47413c383532302f2e2e2e2f303336393e434950575f68707a838d98a2acaca2978c81766b5f54483d31251a0e0200000013202c3946535f6c798693a0acaca09386796c5f534c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4a453e362c22170c000000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c20130600000000000000000000000b17222d38424d57606a737b848b91979b958f8a8682807e7e8185888c9094989da2a7a29c958e877e766d63594f443a2f23180c0100000c18232f3a444d5458585756555553535251504f4e5a6673808c999d9084776a5d514e4f50515253545556575858554f473d32271c10040000000000030c161e272f373e454b5055595c5e5f5f5f5e5c5955514b453f38302820170e05000000000000020d18222c353c424546464646464646464644403c424546464646464646464644403931281e13080000020d18222c353c424546464646464646464644403a32291f140a00000000000013202c3946535f6c798693a0aca79a8d8173675a4d525f6b7885928e8a8683807d7b79787878797b7e848a919aa3aba1978c8175695e52463a2e221509000000000c1824303c47535e6975808b959fa9aca39a918a847e7a7776757576787b80858b929a90867a86929faca5988c7e7265584c3f3225190c0013202c3946535f6c798693a0acb9b4aca49c948c847b7c87919ba5a89e948a80756b61574d42382e24190f0500000000000000000000000000000009121b23293037404a545f6a75818c98a4a4998d82766a5e52463a3131313131313131313236404b57636f7c888d8c8b898884776b5e5145382b1e12000000000000000013202c3946535f6c798693a0acaca09386796c5f5346393232323232323232323232333436393d4249525c67727d8995a1adaca094877b6f6256493d3024170b0013202c3946535f6c798693a0acaca09386796c5f5346404040404040404040404041414345484c51585f68727c87929da9b0a5998d8275695d5145382c201307000d1925303c464f575b5b5b5b5b65717e8b98a4b0a4978a7d70635b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5a554d453e362c22170c01000000000000000000000000000f1b2834414d5a66727f8b97a3afa5998e82776c6259514b47444241403f3f3e3e3e4a5763707d8996a3afa6998c7f7265594c3f3226190c0000000000000000121f2c3945525f6b7885929eabaa9e9184786b5f5246392e26221f1e1c1f29343e4a55616d7885919da9b2a6998c7f7265594c3f3226190c000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000010d1924303b46525d68737e89939ea8b0a69c928980766e665f58524d4844413f3d3b3b3a3b3c3d3f4245494e545a6169717a838c959fa9afa59a90857a6f64594e43372c2015090000000013202c3946535f6c798693a0acaca09386796c5f53463f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3e3a342c241a1005000000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c201306000000000000000000000005101b26303b454e58616a727980868b90949a96928f8d8b8b8e9194989ca0a4a4a09b96918a847c756c645b51473d33281d12070000000f1c2834404b565f646564636261605f5e5d5c5b5b5b6774818e9a9e9185786b5f5a5b5c5d5e5f6061626364656561594f44382c201407000000000000040c151d252c333a3f44494c4f51525352514f4d4945403a342d261e160e05000000000000000006101a232a313639393939393939393939383431363939393939393939393938342e271f160c0200000006101a232a31363939393939393939393938342f2820170d0300000000000013202c3946535f6c798693a0aca79a8d8173675a4d525f6b788586827d7a7673716e6d6c6b6b6c6f73788088919ca6a89d92867a6e62564a3e3125180c00000004101d2935404c58646f7b86919ca7afa49a91888078726e6b6968696a6c6f7479808891978c8186929faca5988b7e7165584b3f3225180c0013202c3946535f6c798693a0acb3aaa3a1a39e958d85848e98a3aba1978c82786e63594f453b30261c120800000000000000000000000000000000000911181e252e38424d5964707c8894a0aa9e92877b6f63564a3e322524242424242424252f3b4753606c798281807e7d7b7a756a5e5144382b1e12000000000000000013202c3946535f6c798693a0acaca09386796c5f53463e3e3e3e3e3e3e3e3e3e3e3f3f404245494e545b646e78838f9aa6b1a89c9084786b5f53463a2e2115080013202c3946535f6c798693a0acaca09386796c5f534d4d4d4d4d4d4d4d4d4d4d4d4d4e4f5154585c6269717a848e99a3aeaa9f94897d7165594d4135291c100400101d2935414d5861676868686868717e8a97a4b0a4978a7d7068686868686868686868686868686868665f564a3f33271b100600000000000000000000000000000c1925313e4a57636f7b87939faaaa9f93887e746b635c5754514f4e4d4c4c4b4b4b4a55626f7b8895a2afa6998c7f7265594c3f3226190c0000000000000000111e2b3844515e6a7784909da9aca093877a6e62564a4037322e2c2a2928282d3944505c6875818d9aa6b2a6998c7f7265594c3f3226190c000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000000000008131e2a35404c57616c77818c96a0a9aea49b92898078716a635e5854504d4b4948484748484a4c4e51555a5f656c737b838c959ea7b0a69d93897e74695e53483d32261b0f040000000013202c3946535f6c798693a0acaca09386796c5f5346393232323232323232323232323232323232323232323232323232323232312e29221a120800000000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000000000000a141f29333d464f5760676e757a808488929e9e9b9998989a9da1a4a3a09c98948f8a857f79726a635a52493f352b21160c01000000121e2b3844505c68707271706f6e6d6c6b6a696867666875828e9b9f9286796c666768696a6b6c6d6e6f6f7071726b6054483c2f23160900000000000000030b131b22282e34383d4043444646464543403d39342f29231c140d04000000000000000000000811192025292c2c2c2c2c2c2c2c2c2c2b28262a2c2c2c2c2c2c2c2c2c2c2b28231d150d0400000000000811192025292c2c2c2c2c2c2c2c2c2c2b28241d160e050000000000000013202c3946535f6c798693a0aca79a8d8173675a4d525f6c79807a76716d6a676462605f5e5e6062676d76808a95a0aca3978b7e7266594d4134281b0f0200000814212d3945515d6974808c97a3aea89d93887e766e67625e5c5b5c5d6063686f767e889192888994a0aca5988b7e7165584b3e3225180b0013202c3946535f6c798693a0acaca19894979f9f978f8e96a0aaa3998f857a70665c52473d33291f140a00000000000000000000000000000000000000060d141c26313c4854606c7884919da9a3978b7f73665a4e4135291c1818181818181f2b3844515d697375747371706e6d6b63594e4235291d10000000000000000013202c3946535f6c798693a0acaca09386796c5f534b4b4b4b4b4b4b4b4b4b4b4b4c4c4d4f5155595f656d76808a95a0abaea2978b8073675b4f43372b1e12050013202c3946535f6c798693a0acaca09386796c5f5a5a5a5a5a5a5a5a5a5a5a5a5a5a5b5c5e6064686d747b848c96a0aaada3998e83776c6055493d3125190d0000121f2c3845515e69737575757575757d8a97a4b0a4978a7e757575757575757575757575757575757571675b4f43372b1e120600000000000000000000000000000916222e3a47535f6b76828e99a4aea59a90867d756e6863605d5c5a5959585858575757626f7b8895a2afa6998c7f7265594c3f3226190c0000000000000000101d2936424f5c6875818e9aa6afa3968a7e72675c5249423e3b38373635353534404c5965727e8b97a4b1a6998c7f7265594c3f3226190c000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000000000020d19242f3a45505b65707a848e97a1aaada49b928a827b756e6964605d5a5856555454545556585b5e61666b70777e858d959ea7b0a79e948b81776c62574c42372b20150a000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2626262626262626262626262626262626262626262626262626262624221d1710080000000000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c201306000000000000000000000000030e18232d37414a535b636a71777d8287929eaba8a6a5a4a3a09d9a9793908c88837e79746e676059514840372d23190f0500000000131f2c3946525f6c797e7d7d7b7b7a79787776757473727683909ca093877a7273747575777778797a7b7c7d7e7d7063574a3d3024170a0000000000000000010910171d23282c30343638393939383634312d28231e18110a02000000000000000000000000070e14191d1f2020202020202020201f1c1a1d1f2020202020202020201f1c17120b0400000000000000070e14191d1f2020202020202020201f1c18120c04000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d515e6a74756f6a65615e5a58555352515253565c646e7884909ca8a79a8e8275695c5043362a1d110400000c1824313d4955616d7985919da8aea2978c81766d645c5652504f4f5153575d646c76808a9593949ba5b0a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca89b8f878d97a0a19b9a9fa8a69c92877d73695e544a40362b21170d030000000000000000000000000000000000000000020a14202b3743505c6875818e9aa7a79b8f82766a5d5144382b1f120b0b0b0b101c2935414d586168696766656362605e5951473d3125190d000000000000000013202c3946535f6c798693a0acaca09386796c5f5858585858585858585858585858595a5b5e61656a70778089929ca6b1a79c91867a6f63574b3f33271b0f020013202c3946535f6c798693a0acaca09386796c67676767676767676767676767676767696a6d7074797f868d969ea8aea59b91877c71665b4f44382c201509000013202c3946535f6c79828282828282828a97a4b0a5988c828282828282828282828282828282828282776b5f53473a2e22160a000000000000000000000000000006121e2a36424e5a66717c87929ca6aca2988f878079746f6c6a68676665656565646464636f7b8895a2afa6998c7f7265594c3f3226190c00000000000000000e1b2734404d5965727e8a96a2aea69a8f83786e645b544e4a4745444342424141414a5663707c8996a2afa6998c7f7265594c3f3226190c000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000007131e29343e49535e68727c858f98a0a9ada49c948d86807a75706c6966646362616161626365676a6e72767c82888f979fa7afa69e958c83796f655a50463b30251a0f04000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201919191919191919191919191919191919191919191919191919191815110c06000000000000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c20130600000000000000000000000009141f2a353f49535c656d757c83898e9299a3a9a5a19d9a9794918e8a8784807c77736e68635c564e473f362e241b12080000000000131f2c3946525f6c79868a89888786868584838281807e7e84909da194887d7e80818282838485868788898a8a7d7063574a3d3024170a00000000000000000000050c12171c202427292b2c2c2c2b2a2724211d18120d0600000000000000000000000000000003090d111213131313131313131312100e1113131313131313131313120f0c070000000000000000000003090d111213131313131313131312100c070100000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4d58626869635e5955514e4b4947454545474a525c6773808c98a5aa9d9184776b5e5145382b1f120500030f1b2834404d5965717d8a96a2ada99d91867a6f655b524a4543424244474c525a646e78838e9aa0a5adb2a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d81858e98a1a8a7aba89e948a80756b61574d42382e241a0f0500000000000000000000000000000000000000000000030f1b2734404d5966727f8c98a5ab9e9285796c6053463a2d2114070404040d1925303b464f575b5c5b5958565554524e483f362b201509000000000000000013202c3946535f6c798693a0acaca09386796c6565656565656565656565656565656566686a6d71767b8289929ba4aeaaa0958b8075695e52473b2f23170b000013202c3946535f6c798693a0acaca093867973737373737373737373737373737374747577797c80858a90979fa8ada59c938980756b60554a3e33271c10040000121f2b3844515d6975818d8f8f8f8f8f929ba7b3a89d938f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f877b6f63574a3e32261a0e0200000000000000000000000000020e1a26323d4954606b76808a949da6aaa199918a84807c79777574737272717171717170707b8895a2afa6998c7f7265594c3f3226190c00000000000000000c1824313d4a56626e7a86929ea9aba0958a80766d655f5a565452504f4f4e4e4e4d4d55626f7b8895a2afa6998c7f7265594c3f3226190c000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000000000000010c17222d37424c56606a737c868e979fa7aea69f98918b86817c797673716f6e6e6d6e6f707174767a7e82878d939aa1a9aca59d948c837a70675d53493e34291e140900000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0b09050100000000000000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000000000040f1b26313c46515b656e777f878e94999ea3a29d9995918e8a8784817e7b7774706b67625d57514b443d352d241b1209000000000000131f2c3946525f6c798692969594939291908f8e8e8c8c8b8b949fa3978d8a8b8c8d8e8f90919293949596978a7d7063574a3d3024170a000000000000000000000001060b1014181b1d1e1f201f1e1d1b1815110c0701000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4650575c5c58524d4945423f3c3a3938383a404b5764707d8996a3ac9f9286796c5f5346392c2013060005121e2b3743505c6975818d9aa6b1a5998d8175695e53494039363536373b4148525c67727d8994a0acb6b2a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d817c868f99a2abaea2978c82786e64594f453b30261c120800000000000000000000000000000000000000000002080c0f1825313e4b5764717d8a97a3ada194877b6e6155483c2f22161111111111141f2a343d454b4f4f4e4d4b4a484745423d362d24190f04000000000000000013202c3946535f6c798693a0acaca09386797171717171717171717171717171717272737577797d81878d949ba4adaaa1988e84796e63584d41362a1e1207000013202c3946535f6c798693a0acaca09386818181818181818181818181818181818181828486898c90969ba2a9aaa39b938a81776d63594e43382d22160b000000101c2834414d5965717d8a969c9c9c9c9ea4adb8aea59e9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c978b7f73675a4e42362a1e120500000000000000000000000000000a15212d38434e59646e78828b949ba2a9a39c96908c8885838281807f7e7e7e7e7d7d7d7d7d8895a2afa6998c7f7265594c3f3226190c00000000000000000915212d3a46525e6a75818c97a2aca69c91887f77706a6663605e5d5c5b5b5b5b5a5a5a626f7b8895a2afa6998c7f7265594c3f3226190c000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000000000000006101b25303a444e58616a737c858d959da4aba9a39c97918d898582807d7c7b7a7a7b7b7c7e8083868a8e93999ea5aca8a29a938b837a71685e554b41372d22180d0200000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0b08040000000000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c20130600000000000000000000000914202c37424d58636d76808991989fa5a29c96918d8985827e7b7875726e6b67645f5b56514c464039322b231b120900000000000000131f2c3946525f6c7986929fa2a1a09f9e9d9c9b9a999897979da6a99f989798999a9b9c9d9e9fa0a1a2a2978a7d7063574a3d3024170a000000000000000000000000000004080b0e101213131312100e0c0805000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d40464c4f504d47423d393532302e2c2b2c2f3c4955626f7b8895a2ada09386796d6053463a2d201307000814212d3a46535f6c7885919da9ada195897c7064584d41372e2a28292b2f36404a55606c7884909ca8b4b2a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d81737d879099a3ac9f92867a70675e544b42392f261d140a0100000000000000000000000000000000000000070e14181b1d23303d4956636f7c8996a2afa296897c706356493d30231d1d1d1d1d1d1d1d222b343a3f424341403e3d3c3a3936322b241b120800000000000000000013202c3946535f6c798693a0acaca093867e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7f80818386898d92989ea5ada8a0988f867c72675d52473c3025190e02000013202c3946535f6c798693a0acaea2978f8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8e8e8f909295989ca1a7aaa49f98918981786f655c51473d32271c11050000000c1824313d4955616d7a86929b9b9b9b9ca1a9b3b1a79f9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b8f83776a5e52463a2e211509040302010000000000000000000004101b27323d48525c667079828a91979da2a6a19c989592908e8d8c8c8c8b8b8b8a8a8a8a8a8d97a3b0a6998c7f7265594c3f3226190c000000000000000005111d2935414d5964707b86909ba4ada39a9189827b76726f6d6b6a6968686767676767666f7b8895a2afa6998c7f7265594c3f3226190c000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000000000000000009141e28323c464f58616a737b838b9299a0a6aba8a29d9995918f8c8a898887878888898b8d8f92969a9fa4aaa9a49d979089817970685f564c43392f251b10060000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a191814100a03000000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c20130600000000000000000000010d1925313d48545f6a747f89929ba3a69e97908a85817c7975726f6b6865625f5b57534f4b46403b352e28201d1a161009010000000000131f2c3946525f6c7986929fa1a09f9e9d9c9b9a99989796969ca5a89e97969798999a9b9c9d9e9fa0a1a2978a7d7063574a3d3024170a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d403b404343403c36312d292623211f1f28313d4956636f7c8995a2ada09386796d6053463a2d201307000a1723303c4955626e7b8794a0adaa9e9185796c6054483c30251d1c1c1f242e3944505b6773808c98a4b0b2a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173747e87919aa4a1968c827970665d544b41382f261c130a0000000000000000000000000000000000000811181f24282a2a2f3c4955626f7b8895a2afa4978a7d7164574a3e312a2a2a2a2a2a2a2a2a2a2a292f333636353332302f2e2c2a26211a12090000000000000000000013202c3946535f6c798693a0acaea2968d8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8c8d8e909295999ea3a9aba59e968e867d746a60564b40352a1f140800000013202c3946535f6c798693a0acb4a9a09b9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9b9b9d9fa1a4a8a6a29e99938d867f776f665d534a40352b20150a000000000814212d3945515d6a76828e8e8e8e8e8f97a2aeaba0958f8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e877a6e62564a3d31241811100f0e0d0c090400000000000000000a15212b36404b545e6770787f868c91969a9ea1a3a19f9d9b9a9998989898989797979696989fa9b2a6998c7f7265594c3f3226190c0000000000000000010d1925313c48535e69747e89929ba3aba39b938d87827e7c797876757575747474737373737b8895a2afa6998c7f7265594c3f3226190c000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000000000000000020c16202a343d464f586169717981888e949aa0a5a9a9a5a19e9b99979695949494959697999c9fa2a6aba7a39e98928c857e776f675e564d443a31271d1309000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2626262626262626262626262626262626262626262626262626262626262624201b150d050000000000000713202d3a4653606d798693a0adaca09386796c5f5346392c2013060000000000000000000005111d2935414d5965707b86919ba4a59c948c857f7975706c6965625f5c5956524f4b47433f3a3532302f2d2c2a26211b130b0200000000131f2c3946525f6c7986929695949292908f8e8d8c8b8a898a939fa3978c898a8b8c8d8e8f909192939495968a7d7063574a3d3024170a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d403434363634302a25211d1a171a2129313a434e5965727e8a97a4ac9f9286796c5f5346392c201306000c1925323e4b5864717d8a96a3afa89b8f8276695d5044382c20140f10131c27333f4b57636f7c8894a1adb2a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d81736c757f88929ba59e948b82786f665d534a41382e251c12090000000000000000000000000000000007111a232a30343637373c4855626f7b8895a2afa4978b7e7164574b3e37373737373737373737373736322d2929282725242221201e1a150f08000000000000000000000013202c3946535f6c798693a0acb3a89f99989898989898989898989898989898989898999b9c9fa2a5aaa9a49f9a938c857c746b62584e44392f24190e0300000013202c3946535f6c798693a0acb9b1aaa6a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a4a4a3a19f9d9a96928d88827b746d655d544b41382e24190f040000000004111d2935414d5a66727e828282828285929eaba99c8f838282828282828282828282828282828282827e7265584b3f32251f1e1d1c1b1a1815100a03000000000000040f1a242f39424c555e666d747b81868a8e919496989a9b9c9d9e9e9e9e9e9f9f9f9fa0a0a1a7afb2a6998c7f7265594c3f3226190c0000000000000000000814202b37424d58626d7680899199a0a6a59e98938e8b8886848382828281818181818080808895a2afa6998c7f7265594c3f3226190c000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000000000000000000040e18222b343d464f575f676f767d83898f94999da1a4a8aaa8a5a4a2a1a1a1a1a2a2a4a6a8a9a6a3a09c97928d87817a746c655d554c443b32281f150b01000000000000000013202c3946535f6c798693a0acaca09386796c5f5346393333333333333333333333333333333333333333333333333333333333333333302c261f170e0400000000000713202d3a4653606d798693a0adaca09386796c5f5346392c201306000000000000000000000814202d3945525e6a76818d98a2a79d938a827a746e6964605d595653504d4a46433f3e424342403f3d3b3a3836322c251d140a00000000131f2c3946525f6c79868a898887868584838281807e7d7d84919ea295887c7d7e808181828484868688888a8a7d7063574a3d3024170a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d403427292928241f191511171e252c333b434c555f6a76828e9aa6a99d9084776b5e5145382b1f1205000e1a2734404d596673808c99a5b2a5998c8073665a4d4135281c1003030b17232f3b4753606c7985929eabb2a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173676d768089939ca69d948b81786f655c534a40372e241b12090000000000000000000000000000030e19232c353b40434444444855626f7b8895a2afa4988b7e7164574b44444444444444444444444444423e3831281e1a1817161413110e0a0400000000000000000000000013202c3946535f6c798693a0acacaca9a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a6a7a9a8a6a4a19d99948e88827a736a625950463c32281d12080000000013202c3946535f6c798693a0acb3a89f999898989898989898989898989898989898989897969492908d8a86827c77716a635b534b42392f261c12070000000000010d1925313d4a56626d74757575757783909da9aa9d9084777575757575757575757575757575757575746e63574a3e312d2c2b2a29282725211b150d0400000000000008121d27303a434c545c63696f757a7e8285888a8c8d8f90909191919292929292939393959da7b2a6998c7f7265594c3f3226190c000000000000000000030f1a25313b46515b656e7780878e959a9fa4a39f9b97959391908f8f8e8e8e8e8d8d8d8c8c8f99a4b0a6998c7f7265594c3f3226190c000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000061019222b343d454d555d646b72787e83888d9195989b9ea0a1a3a4a5a5a5a5a5a4a2a19f9d9a9793908b86817b766f69625a534b433a322920160d0300000000000000000013202c3946535f6c798693a0acaca09386796c5f534640404040404040404040404040404040404040404040404040404040404040403f3d38312920160b00000000000713202d3a4653606d798693a0adaca09386796c5f5346392c201306000000000000000000000a1723303c4955616e7a86929ea9a1968b81787069635d5854504d4a4643403d3a3a42494e4f4e4d4b4a484745423e372f261c1106000000131f2c3946525f6c787e7d7c7b7a7978777675747372717885929ea295897c7171737375767778797a7b7c7d7e7d7063574a3d3024170a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271d1d1b18140e141b22292f363d454d555e67717c87929eaaa69a8e8175685c4f43362a1d1004000f1c2835424e5b6874818e9aa7b0a4978a7d7164584b3f3226190c000006131f2b3844505d6976838f9ca8b2a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d817367646e77818a949da69d938a81776e655c524940372d241b1108000000000000000000000000000915202b353e464c505050505055626f7b8895a2afa4988b7e71645750505050505050505050505050504f4a433a30251a0f0a0908060402000000000000000000000000000013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09f9e9d9c9a9794918d88837d777068615850473e342a20160b010000000013202c3946535f6c798693a0acaea2968d8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8b8b8a89888684817d7a75716b655f585149413930271d140a000000000000000915212d3a45515b63686868686875828e9ba7ab9f9285796c6868686868686868686868686868686868645c52463b3a39383736353433312c261f160d030000000000010b151e28313a424a51585e64696e7275787b7d7f8182838484848485858586868686868b96a3afa6998c7f7265594c3f3226190c0000000000000000000009141f2a343f49535c656d757d848a8f93979b9ea0a2a19f9e9d9c9b9b9b9a9a9a9a9a99999aa1aab2a6998c7f7265594c3f3226190c000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000000000000000000000071019222b333c434b525a60676d72777c8185898c8f9193959697989898989897969492908e8b87837f7a76706a645e5750494139312820170e040000000000000000000013202c3946535f6c798693a0acaca09386796c5f534d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4c49433b32271d1206000000000713202d3a4653606d798693a0adaca09386796c5f5346392c201306000000000000000000000c1825323e4b5764717d8a96a2a79b8f84796f665e57514c4844413d3a37343137424c545a5c5b5958565553524f4941382d23170c000000121e2b3744505c677071706f6e6d6c6b6a69686766656c7885929fa396897c6f65666768696a6b6c6d6e6f7071726b6054483c2f2316090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a100f0c0f171e262d343a41484f575f677079838d98a4ada2968a7e7165594d4034271b0e0200101d2a3643505d6976838f9ca9afa295897c6f6356493d3023170a0000030f1c2835424e5b6774818d9aa6b2a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675c656f78828b949ea59c938a80776d645b52493f362d231a11080000000000000000000000000e1a26313c4750585c5d5d5d5d5d626f7b8895a2afa4988b7e71645d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5b554c42372b2014070000000000000000000000000000000000000013202c3946535f6c7986939393939393939393939393939393939393939393939393939292918f8d8b8885817c77726c655e574f463e352c22180e04000000000013202c3946535f6c798693a0acaca093867e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7d7c7b797774716e6a65605a544e473f372f271e150b020000000000000005111d29343f4952585b5b5b5b66737f8c98a5ada194887b6e625b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b59524a474847464544434241403d3831281f150b000000000006101921292f33383f464d53585d6266696c6e717274757677777778787878797979797b8895a2afa6998c7f7265594c3f3226190c00000000000000000000030d18232d37414a535b646b72787e83878b8f91949697999a9a9b9b9b9c9c9c9c9c9d9d9d9fa4adb2a6998c7f7265594c3f3226190c000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000000000000000000000000071019212a323941484f555b61676c7075797c80828586888a8b8b8c8c8c8b8a89888684817e7b77736f6a655f59534c463e372f271f160e05000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5959595959595959595959595959595959595959595959595959595959595959595959544d43392e23170b000000000713202d3a4653606d798693a0adaca09386796c5f5346392c201306000000000000000000000d1a2633404c5966727f8c99a5a4988b7f73685d544c46413c3834312e2a27313d48545e66696866656361605e5a534a3f34281c100400000f1c2834404b565e646564636261605f5e5d5b5a595f6c7986929fa3968a7d7063595a5b5c5d5e5f60616263646561594f44382c2014070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d071018212830373e454c535a61697179828b959faaa79c9185796d6155493d3124180c0000111e2b3744515e6a7784909daaaea194887b6e6155483b2f2215090000000d1a2633404c5965727e8c98a5b1a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a5d666f79838c959fa59c928980766d645b51483f352c231a10070000000000000000000000111d2a36424e5962696a6a6a6a6a6a6f7b8895a2afa4988b7e716a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a665e53483c3023170b0000000000000000000000000000000000000013202c3946535f6c79868686868686868686868686868686868686868686868686868686858482817e7b7875706b66605a534c453d342c231a100600000000000013202c3946535f6c798693a0acaca093867972727272727272727272727272727272727171706e6d6a6865625d59544f49433c352d251d150c030000000000000000010c18232d3740474c4e4e4e5764707d8996a2afa3968a7d7165584e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4c4a50545554535251504f4e4d49433a31271c1105000000030e18222b333a3f42434445474d5156595d5f6264666769696a6b6b6b6b6b6b6c6c6c6f7b8895a2afa6998c7f7265594c3f3226190c000000000000000000000006111b252f384149525960676d72777b7f828587898b8c8d8e8e8e8e8f8f8f8f90909090939ba6b2a6998c7f7265594c3f3226190c000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000070f1820272f363d444a50565b6065696c707376787a7b7d7e7e7e7f7e7e7d7c7b797775726f6b67635e59544e48423b342d251d150d0400000000000000000000000013202c3946535f6c798693a0acaca09386796c6666666666666666666666666666666666666666666666666666666666666666666666655f554b3f33271b0e020000000713202d3a4653606d798693a0adaca09386796c5f5346392c201306000000000000000000000d1a2633404d596673808d9aa6a295897c6f63574b423b35302c282627282c34404c59657076747371706e6c6b655b5045392c20130700000c18232f39444d54585857565554535251504f4e53606d798693a0a4978a7d7164574d4e4f515153545556575858554f473d32271c10040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d1019222a323a424950575d646b737a838b949da7aba1968b8074695d5145392d2115080000121f2c3845525e6b7885929eabada093867a6d6053473a2d2114070000000b1825313e4b5764717d8a97a4b0a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a545d67707a838d96a0a49b92897f766d635a51473e352c2219100700000000000000000000131f2c3945525e6a74777777777777777b8895a2afa4988b7e77777777777777777777777777777777777064584c3f3226190c00000000000000000000000000000000000000131f2c3946525f6b7679797979797979797979797979797979797979797979797979797978777674726f6c6864605b554f49423a332b221a11070000000000000013202c3946535f6c798693a0acaca09386796c6565656565656565656565656565656565646362605e5c5955514d48433e38312a231b130b030000000000000000000006111b252e363c4042424855616e7a86939faca6998d8174685c4f434242424242424242424242424249535c6161605f5e5d5d5b5b59544c43392d22160a00000008141f2a343d454b4e4f5152535455565757535557595b5c5d5d5e5e5e5e5f5f5f5f626f7b8895a2afa6998c7f7265594c3f3226190c00000000000000000000000009131d262f3840484f565c61666b6f7376787a7c7e7f808181828282828283838383848996a2afa6998c7f7265594c3f3226190c000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000000000000000000000000000060e161d242c32393f454a4f54585c606466696b6d6f7071727272727171706e6d6b6865625f5b57524d48423d373029221b130b030000000000000000000000000013202c3946535f6c798693a0acaca093867973737373737373737373737373737373737373737373737373737373737373737373737371675c4f43362a1d11040000000713202d3a4653606d798693a0adaca09386796c5f5346392c201306000000000000000000000d1a2633404d596673808c99a6a295887b6f6255493e3936343332323335383d45505c68758181807e7c7b79776d6154483b2e221508000007121d28323b42484b4b4a49484746454443424754616d7a8794a0a4988b7e7164584b42434445464748494a4b4b49443d352b21160b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0f19222b343c444c545b62686f767d858c959da6ada3998f84796e63584c4035291d11050000131f2c3946525f6c7986929facac9f9286796c5f5346392d2013060000000a1723303d4a5663707c8996a3afa5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d555e68717b848e97a1a49b91887e756c635950473e342b22190f0600000000000000000013202c3946535f6c7984848484848484848996a2afa5988c8484848484848484848484848484848484807366594c403326190d00000000000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6a69676563605c58544f4a443e37302921191008000000000000000013202c3946535f6c798693a0acaca09386796c5f5858585858585858585858585858585857565553514f4c4945413d38322d262019110a0200000000000000000000000009131c242b3033353945525e6a7783909ca8a99c9084786b5f53473c3535353535353535353537434f5b656d6e6d6c6b6a696867655e554a3e32261a0d0000010d1925303c464f575b5c5d5e6061626364635d544b4d4e4f50515151515152525255626f7c8995a2afa5988c7e7265594c3f3226190c000000000000000000000008121b242b3135383d444a50565b5f6366696c6e7071727374747575757575767676767b8895a2afa6998c7f7265594c3f3226190c000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000000000000000000000000000000040b131a21272e34393f44484c5054575e6364646464646565656565646362605e5c5956534f4b46423d37312b251e18100901000000000000000000000000000013202c3946535f6c798693a0acaca0938680808080808080808080808080808080808080808080808080808080808080808080808080776b5e5144382b1e11050000000713202d3a4653606d798693a0adaca09386796c5f5346392c201306000000000000000000000c1926323f4c5865727e8b98a4a3968a7d716559504a454241403f3f404244484e57616d78848e8c8b8987867a6e6155483b2f2215080000010c16202931373c3e3f3e3d3c3a393837363b4854616e7b8894a1a5988b7e7265584c3f363738393a3b3c3d3e3f3d39332b23190f04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a17212b343d464e565e656c737a81888f969ea7aca49b91877d73685d52473b3024180c00000013202c3946535f6c7986939facac9f9285786c5f5246392c1f13060000000916232f3c4955626f7c8895a2afa5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d4c565f69727c858f98a2a39a91877e756b625950463d342b21180f06000000000000000013202c3946535f6c798690909090909090939ba6b2a89d94909090909090909090909090909090908c807366594c403326190d000000000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5e5c5b595653504c48433e39332c251e170f0700000000000000000013202c3946535f6c798693a0acaca09386796c5f534c4c4c4c4c4c4c4c4c4c4c4c4c4c4b4b4a48474543403d3935312c27211b150e070000000000000000000000000000010a12191f24272a36424f5b6773808c98a4aca094887c7064584c41362b282828282828282d3946525f6b777b7a79787776757470665b4e4235291c10000004101d2935414d586167696a6b6c6d6f70716f665b4f43414243444444454545454a5763707d8996a3b0a5988b7e7265584c3f3225190c00000000000000000000040f1a242d363d4244464748494a4f53575a5d5f6163656667676868686869696969696f7b8895a2afa6998c7f7265594c3f3226190c000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000000000000000000000000000000001080f161c22282e33383c4044505c676f71717171716e6760585857565553514f4d4a46433f3b36312c26201a140d060000000000000000000000000000000013202c3946535f6c798693a0acaea2978e8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d84776b5e5144382b1e11050000000713202d3a4653606d798693a0a7a7a09386796c5f5346392c201306000000000000000000000b1824313e4a5763707c8995a1a5998d81766b625b55524f4d4c4c4c4d4e5054596069737e89959997968f83776b5f5246392d201407000000040e171f262b30323231302f2e2d2c2b2f3b4855626e7b8895a2a5998c7f7265594c3f332a2b2c2d2e2f313232312d282119110700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a1f29333d464f58606870777e858b9299a1a8aba39a92897f756b61564b40352a1f130700000013202c3946535f6c798693a0acac9f9285786b5f5245382c1f12050000000915222f3c4855626f7b8895a2aea5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d444d57606a737c869099a2a39990877e746b62584f463d332a21180e050000000000000013202c3946535f6c7986939d9d9d9d9d9d9fa4adb7afa69f9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d998c807366594c403326190d000000000000000000000000000000000000000a16212c3740484f525353535353535353535353535353535353535353535353535353535251504e4c4a4744403c37332d27211b140d050000000000000000000013202c3946535f6c798693a0acaca09386796c5f53463f3f3f3f3f3f3f3f3f3f3f3f3f3e3e3d3c3a383633302d2925201b16100a030000000000000000000000000000000000080e13181a26333f4b5764707c8894a0aca4988c8074695d52473d332b262322222428323d4955626e7a878786858483828176695d5043362a1d10000006121f2c3845515e6973757778797a7b7c7d786b5e52453936363738383838383f4c5865727e8b97a4b0a4978a7d7164574b3e3125180b000000000000000000000a15212b363f474e51525355565758595a595553555658595a5b5b5b5b5b5c5c5c5c626f7b8895a2afa6998c7f7265594c3f3226190c000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000000000000000000000000000000000000040b11171d22272c303945525f6c787d7d7d7d7d79726a635c544d48474543403d3a37332f2a25201b150f0902000000000000000000000000000000000013202c3946535f6c798693a0acb3a9a09a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9184776b5e5144382b1e11050000000713202d3a4653606d7986939a9a9a9a9386796c5f5346392c201306000000000000000000000916222f3b4854616d7985919da99e92887d746c66615e5c5a595959595b5d60656b727b858f9aa5a2968b7f73675b4f43362a1e110500000000050d141b2023252524232221201f222f3c4955626f7c8895a2a6998c807366594d4033261f2021222324252524211c170f080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271c26313b454f58616a727a828990969da4aba8a199918980766d63594f453a2f24190e0200000013202c3946535f6c798693a0acac9f9285786b5f5245382c1f12050000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d40454e58616a747d87909aa3a29990877d746a61584f453c332a20170e0500000000000013202c3946535f6c7986939a9a9a9a9a9a9ca2abb6ada49d9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a998c807366594c403326190d0000000000000000000000000000000000000005101a252e373e434646464646464646464646464646464646464646464646464646464645444342403d3a3734302c27221c16100902000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346393232323232323232323232323231302f2e2c2a2724211d1914100a05000000000000000000000000000000000000000003080b17232f3b47535f6c78848f9ba7a99d91857a6f64594f453d3632302e2f30333a444e5a65717e8a93929190908d8174675b4f4235291c1000000613202c3946535f6c7982848586878889867a6d6155483d34312f2f2f303238434f5b6874818d9aa6aea295897c6f63564a3d3023170a000000000000000000020e1a26323d4851595e5f606162636566676660564b4a4b4c4d4e4e4e4f4f4f4f4f56626f7c8996a2afa5988c7e7265584c3f3226190c000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000000000000000000000000000000000000000060c11161b202c3946525f6c79848a8a8a8a837c756d665f575049413a34312e2a27231e19140f09040000000000000000000000000000000000000013202c3946535f6c798693a0acacacaba7a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a69e9184776b5e5144382b1e11050000000713202d3a4653606d79868d8d8d8d8d8d86796c5f5346392c201306000000000000000000000713202c3845515d6975818c97a2a4998f867e77726e6a68676665656667696c70767c848d97a1a59b90857a6e62574b3f33271a0e02000000000003090f1417181817161514131623303c4956636f7c8996a2a69a8d8173675a4d4034271a131415161718181715110b05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d403427222d38434d57616a737c848c939aa1a8aca49d968f877f766d645b51473d33281e13080000000013202c3946535f6c798693a0acac9f9285786b5f5245382c1f12050000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d403c464f58626b757e88919ba4a2998f867c736a61574e453c322920170d04000000000013202c3946535f6c79868e8e8e8e8e8e8e9099a5b1a79b928e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8c807366594c403326190d000000000000000000000000000000000000000009131c252c3237393939393939393939393939393939393939393939393939393939393938363533312e2b2824201b16110b050000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c252525252525252525252525242422211f1d1b1814110d090400000000000000000000000000000000000000000000000007131f2b37434f5b67737e8a96a1ada2978b80756b61574f48423e3c3b3b3d3f444c55606b76828e9a9f9e9d95897d7164584c3f33261a0d000005121f2b3844515d6a76838f9192949596897d7165594e45403e3c3c3c3c3f434a55606c7884909ca9ac9f93867a6d6154483b2f22150900000000000000000004111e2a36424e59636a6c6d6e6f7071737471685c50443e4040414242424242424a5764707d8a96a3b0a5988b7e7265584b3f3225180c000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000000000000000060b121e2b3844515d68727b848e97958e877f787069625b534c453d362f272019120e090400000000000000000000000000000000000000000013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09e9184776b5e5144382b1e11050000000b15202d3a4653606d798181818181818181796c5f5346392c2013060000000000000000000004101c2835414d5864707b86919ba4a1989089837e7a777573737272737476797c81878e969fa69d93897e74685d52463a2e22160a000000000000000003070a0c0c0b0a09080a1724303d4a5763707d8a96a3a79a8e8174675a4e4134281b0e0708090a0b0c0b08050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d40342728333f4a545f69737c858e969ea5aca8a19a938c847d756d645b52493f362b21170c010000000013202c3946525f6c7986929facac9f9285796c5f5246392c1f13060000000915222f3c4855626f7b8895a2aea5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d40343d475059636c768089929ca5a1988f857c736960574e443b32291f160d030000000013202c3946535f6c7981818181818181818995a2afa4988b8181818181818181818181818181818181807366594c403326190d0000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b2a282624221f1b18140f0a0500000000000000000000000000000013202c3946535f6c798693a0a0a0a09386796c5f5346392c2019191919191919191919181817161413100e0b0805010000000000000000000000000000000000000000000000000000030f1b27333f4b56626e7985909ca7a89d92877d73696159534e4b494848494c50565e67717c87939eaaa89d9185796d6155483c3024170b000003101c2935424e5b6773808c989fa0a1998d81766b6057514d4a494848494b4f545c66717c8894a0aca89c9083776b5e5245392c20130700000000000000000006131f2c3945525e6b7578797b7c7d7e7f81786b5f5246393334343535353536404d5965727e8b98a4b0a3978a7d7164574b3e3124180b000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000000000000000000000000000000000000000000000000101c2834404c566069727b858e9798918a827b746c655e564f484039322a231c140b0100000000000000000000000000000000000000000013202c3946535f6c79869393939393939393939393939393939393939393939393939393939393939393939393939393939393939184776b5e5144382b1e1105000007121d27313a45515e6972737373737373737372695d5145382c1f120600000000000000000000000c1824303c48535e69747e89929ba3a29a948e8a86848280807f7f80818385898d9299a0a49c948b81776d62574c41352a1e120600000000000000000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174685b4e4235281b0f0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034272e3945505b66707b858e97a0a8ada59e968f88817a736b635b524940372d241a0f050000000000121f2c3845525f6b7885929eabac9f9386796c5f5346392d2013060000000916232f3c4956626f7c8995a2afa5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d4034343e47515a646d77808a939da6a1978e857b726960564d443b31281f150c01000000121f2c3845515d6972747474747474747b8895a2afa4988b7e74747474747474747474747474747474746e63574b3e3225190c000000000000000000000000000000000000000000010910161a1e1f2020202020202020202020202020202020202020202020202020201f1e1d1c1a1815120f0c0803000000000000000000000000000000000013202c3946535f6c798693939393939386796c5f5346392c20130c0c0c0c0c0c0c0c0c0b0b0a0908060401000000000000000000000000000000000000000000000000000000000000000b17222e3a46515d68747f8a95a0aba3998f857b736b645f5a5756555556585c61687079838e99a4aea3978c8175695d5145392c2014080000000d1a26323f4b57636f7b88939faaaa9e92877c7269625c595756555556585b5f666e78838e99a5afa3978c8073675b4f42362a1d11040000000000000000000613202c3946525f6c78858687898a8b8c877a6e6255493e373432323233353a45505c6875818e9aa7aea195887c6f6256493d3023170a000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000000000000000000000000000000000000000000000000c18242f3a444e576069737c858e979b948d857e776f686159524b443c352e261d130900000000000000000000000000000000000000000013202c3946535f6c79868686868686868686868686868686868686868686868686868686868686868686868686868686868686868684776b5e5144382b1e110500000c17232e39434c5357606667676767676767676660574c4135291c1004000000000000000000000008141f2b37424d58626d76808991989fa59f9a9693908e8d8c8c8c8c8d8f9295999ea4a099928a82796f655b50463b2f24190d0100000000000000000000000000000000000b1825313e4b5764717e8b98a4a89b8f8275685b4f4235291c0f0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d403427323e4a56616c77828d97a0a9aba39b938c857d766f686159514940372e251b1208000000000000121e2b3845515e6b7784919eaaada093877a6d6054473a2e2114070000000a1724303d4a5763707d8a96a3b0a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d40342c353f48525b656e78818b949da7a0978e847b72685f564d433a31271e1308000000101d2935414c5760666767676767676f7b8895a2afa4988b7e7167676767676767676767676767676767645c52473b2f23160a0000000000000000000000000000000000000000000000050a0e11131313131313131313131313131313131313131313131313131313131212100f0d0b090603000000000000000000000000000000000000000013202c3946535f6c798686868686868686796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121e2935404c57636e79848e99a3aba0978e857d756f6a67646261616365686c727a828b959faaa79c91867b6f64584c4034281c10040000000a16232f3b47535f6b77838e99a4aea4998e847b736d6966646262626264676b7178818a949faaa89d92877b6f63574b3f33261a0e0200000000000000000005111e2b3744505d6976828f94959698968a7e72665b504843403f3e3e3f41454c56616d7985919da9ab9f9286796d6054473b2e221508000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000000000000000000007131e28323c454e57616a737c858f989e979089817a736b645d554e473f382f251a0f040000000000000000000000000000000000000000131f2c3946525f6b76797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979756a5d5144372b1e110400000f1c2834404b555e636464646464625c5a5a5a59554e453b3024190d000000000000000000000000030f1a25313c46515b656e777f878d94999da1a29f9d9b9a999999999a9c9ea1a29e9a948e88817870675d53493f34291e13070000000000000000000000000000000000000c1825323f4b5865727e8b98a0a09c8f8275695c4f4336291c100300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d40342a36434f5b66727e89949ea9aba2999189817a736c655e564f473f372e251c130900000000000000111d2a3744505d6a7683909ca9aea194887b6e6155483b2f2215090000000c1825323e4b5864717e8b97a4b1a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d4034272d364049535c666f78828b959ea8a0968d847a71685f554c43392f25190e0200000d1924303b454e565a5a5a5a5a5a626f7b8895a2afa4988b7e71645a5a5a5a5a5a5a5a5a5a5a5a5a5a5a58524a40352a1f1307000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6b767979797979797979766b5f5246392c1f13060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010d18242f3b46515c67727c87919ba4a9a0978f87817b7673706f6e6e6f7174787d848c949da7a99f958b80756a5e53473c3024180c0000000007131f2b37434f5a66717d88929da6aaa0968d857e797572706f6f6f6f7173777c828a939ca6aba1978c81756a5e53473b2f23170a00000000000000000000020f1c2835414d5a66737f8b97a2a3a49a8e82776c6259534f4d4c4b4b4c4e51575e68727e8995a1ada79b8f83766a5e5145382c1f1306000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000000000000000000000000000000000000000000000000010c17202a333c454e57616a737c868f98a19a938c847d766e676058514a41372c2115090000000000000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b63594d4135291c10030000121f2b3844505c676f71717171716e676058514d4a443c33291e160f0800000000000000000000000009141f2a353f49535c656d757c82888d9195989a9c9e9f9fa0a09f9e9d9b9996928e89837d766e665e554b42382d23180d020000000000000000000000000000000000000c1926323f4c5965727f8c93939393908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d40342d3a46525f6b77838f9aa5aca29990877f777068615a534c453d352d251c130a0100000000000000101c2936424f5c6875828e9ba8afa296897c6f63564a3d3024170a0000010e1a2734404d5966737f8c99a5b2a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d403427242e37414a545d667079838c969fa19f968d837a71675e554b41362a1f1306000008131f29333c444a4d4d4d4d4d55626f7b8895a2afa4988b7e7164574d4d4d4d4d4d4d4d4d4d4d4d4d4d4c4740382e24190e020000000000000000000000000000000000000000000104060708090a0a0a090806040100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6b645a4f43372a1e110500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007131e2a35404b56606b757f89929ba4a9a099928c8783807d7c7b7b7c7d8184898f969ea6a8a0978d83796e63584d42362b1f130800000000030f1b26323e4955606b76818b949da6a89f978f8a85817e7d7c7b7b7c7d8083888d949ca5aaa2998f857a6f64594e42362a1f130700000000000000000000000d1925323e4a56636f7b87929ea9ab9f94897e746b645f5c5a585858595a5d6268707a848f9aa6ada2968b7e73665a4e4235291d1004000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000000000000000000000050e18212a333c464f58616a747d868f99a29d968f888079726a635c53483d3126190d01000000000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5e5951473c3125190d00000013202c3946535f6c797d7d7d7d7d79716a635b544d453e372f28211a120b0400000000000000000000030e18232d37414a535b636a71777c8185898b8e9091929293939291908e8c8986827d78726b645d544c433930261b1106000000000000000000000000000000000000000d1a2633404c5966738086868686868684776a5d5044372a1d110400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034303c4955626e7b87939faba59a90877d756d655e574f48413a332b231b130a0100000000000000000e1b2834414e5a6773808d99a6b0a4978b7e7165584b3f3226190d000004111d2a36424f5b6874818e9aa7b2a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d4034271c252f38424b545e67717a848d94949494948c837970675d53473b2f2216090000020d17212a32393e404141414855626f7b8895a2afa4988b7e7164574b414141414141414141414141413f3c362f261c12080000000000000000000000000000000000000000050a0e1012141516161717161513110e0a0602000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5a52483e32261a0e02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020d18232e39444f59636d778089929aa1a8a49d98938f8c8a888888898a8d90959aa0a8a69f978e857b71675d52473c31251a0e0300000000000a16212d38444f5a646f79828c949ca3a9a19b95918e8b8a898888898a8c8f93999fa6a7a09890877d73695e53483c31251a0e0200000000000000000000000916222e3a46525e6a76818d98a2ada59a90867d75706b686665656565676a6e737a838c96a0aba79c91857a6e62564a3e3226190d01000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000000000000000000000000000000000000000000000000000060f18212a343d464f58626b747d879099a0a099928b837c756d655a4e4235291c1003000000000000000000000000000000000000000a16212c3740484f525353535353535d666b6b6b6b6b6a655e575353535353535353535353565d646a6b6b6b6b6b675f545353535353524e473f352b20140900000013202c3946535f6c79848a8a8a8a837c746d665e575049413a332b241d150e070000000000000000000007111b252f384149515960666b7175797c7f8183848586868686858482807d7a76716c67605a524b423a31271e140a00000000000000000000000000000000000000000d192633404c596571797979797979797974695c5043362a1d100400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034323e4b5864717d8a96a3ab9f94887e746b635b534c453e37302821191109010000000000000000000d1926333f4c5865727e8b97a4b0a6998d8073675a4e4135291c1004020915212d3945525e6a7784909ca9b2a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a1d263039424c555f68727b858888888888888882796f63574a3d3124170b000000060f1821282d323434343c4855626f7b8895a2afa4988b7e7164574b3e34343434343434343434343433302b241d140a00000000000000000000000000000000000000020a10161a1d1f2122232323232321201d1a17120e090300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a16212c3740484f525353535353535353524f4840372c21160a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121d28323d47515b656e77808890979da3a8a39f9b98969595959597999ca0a5a7a29b948d857c73695f554b40352a1f140900000000000005101c27323d48525d677079828a91989ea2a6a19d9a98969595959597999b9fa4a6a19c968e867e756b61574c41362b20140900000000000000000000000006121e2a36424e5965707b86919ba4aca2988f87817b787573727171727376797e858c959ea8a99f958a8074695d52463a2e22160a00000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000000000000000000000000000000000000000000000000000000060f18222b343d465059626b747e879093939393938e877f766a5d5144372a1e11040000000000000000000000000000000000000005101a252e373e4346464646464956626e7778787878767069625c554f48464646464c535a61676e7578787878787065584c4646464645423d362d23190e03000000121f2b3845515d68727b858e97958e867f777069625a534c443d362e272018110a0100000000000000000009131d262f373f474e545a6065696d7072747677787979797978777573706d6a65615b554f48413930281f150c0200000000000000000000000000000000000000000b1824313d495560686c6c6c6c6c6c6c6c6a62584c4034281b0f0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034333f4c5966727f8c98a5a89c8f83776c62595149423a332c251e170f0700000000000000000000000b1724313d4a56636f7c8895a1aea89b8f82766a5d5145382c20140e0f111a25313d4955616e7a86939facb2a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a141e27303a434d566069737b7b7b7b7b7b7b7b7b7a7064574a3e3124180b00000000060f161d222527272f3c4855626f7b8895a2afa4988b7e7164574b3e31272727272727272727272726241f19130b02000000000000000000000000000000000000030c141b2126292c2d2f2f3030302f2e2c2a26231e19140e080100000000000000000000000000000000000000000000000000000000000000000000000000000000000005101a252e373e4346464646464646464646433e372e251a10050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b16212b353f49535c656e767e858c92989ca1a4a7a5a3a2a2a2a2a3a6a7a4a09b96908a837b726a61574d43392f24190e03000000000000000b16212c36414b555e67707880868c92979a9ea1a3a4a3a2a2a2a2a3a5a3a19e9a96918b847c746b62594f453b30251a0f03000000000000000000000000020e1a25313d48545f6a747f89929ba4aaa199928c888482807e7e7e7e8082868a90969ea7a8a0978d83796e63584c4135291e120600000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000000000000000000000000000061019222b343e475059626b757e868686868686868684776a5d5144372a1e1104000000000000000000000000000000000000000009131c252c3237393939393d4a5763707d85858585817a746d67605a534d464950575e656b72798085858585807366594c403939393936322b241b110700000000101c2935414c576069727c858e97989189827b736c655d564f484039322a231c130a010000000000000000010b141d252d353c43494f54595d60636668696b6b6c6c6c6c6b6a686664615d5955504a443d362f271e160d030000000000000000000000000000000000000000000915212d38434e575d5f5f5f5f5f5f5f5f5e5950463b3024180c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d403433404c596673808c99a6a69a8d8174675b50473f373029221a130c050000000000000000000000000915222e3b4754606d7986929eabab9e9285796d6154483d31251d1b1b1d222c36424d5965717d8a96a2afb2a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d151e28313b444e57616a6e6e6e6e6e6e6e6e6e6e695f54483c2f23160a0000000000040b1116191a222f3c4855626f7b8895a2afa4988b7e7164574b3e31241a1a1a1a1a1a1a1a1a1a1a17130e0905010000000000000000000000000000000000010b151e262d3236383a3b3c3d3d3d3c3b3936332f2a251f19120b0400000000000000000000000000000000000000000000000000000000000000000000000000000000000009131c252c32373939393939393939393937322c251c130900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040f19232d37414a535c646c737a81878c9094989a9c9e9f9f9f9f9e9c9a9794908b857f78716960574e453b31271d12070000000000000000040f1a252f39434c555e666e757b81868a8e91949698999a9a9a9a99989694918e8a858079726a625950473d33291e140900000000000000000000000000000915202c37424d58636d7781899299a0a6a39d9894908e8c8b8b8b8c8d8f92969ba1a8a59e968e857b71675c52463b3024190d0100000000000000000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000000000000000000000000000000000000000000000000000000000071019222c353e475059636c7579797979797979797975695d5044372a1d11040000000000000000000000000000000000000000010a131a21262a2c2c2c303d4956626e79828b92928c857f78726b655e5851545b62696f767d848b92928d847a7165584c3f322c2c2c2a26201a120900000000000c1824303a454e57606a737c858e989b948c857e766f686159524b433c352d251c1308000000000000000000020b131b232b32383e43484d515457595b5d5e5f5f5f5f5f5e5d5c5a5755514d49443f39332c241d150c040000000000000000000000000000000000000000000004101c27323c454c515353535353535353524e473e352a1f14080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d403433404c5966737f8c99a5a79a8d8174685c524940372e261d140b020000000000000000000000000006131f2c3845515d6a76838f9ba7aea195897d7165594d42372e2928282a2e343e48535e6a76828e9aa6b2b2a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0c161f29323c454f585e616161616161616161615e574d43372b1f13070000000000000005090c15222f3c4855626f7b8895a2afa4988b7e7164574b3e3124180e0e0e0e0e141a1d20201f1d1915110d090501000000000000000000000000000008131d2730383e4245474849494a4a494745423f3b36302b241d160e060000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2a26211a130a01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121b252f38414a525a62696f757b8084888b8e90919292929291908d8b88847f7a746d665f574e453c332a20150b0100000000000000000008131d27313a434c545c636a70757a7e8285878a8b8c8d8d8e8d8c8b8a8885827e79746e67605950473e352b21170d020000000000000000000000000000040f1b26313c46515b656e7780888f959ba0a4a4a09d9b9998989898999b9ea2a7a39f99938c847c73695f554b40352a1f130800000000000000000000000000000004080b0f1c2835424f5b6875828f9084776a5d5044372a1d110b0905000000000000000000000000000000000000000000000000000000000000000000000000071019232c353e47515a636b6c6c6c6c6c6c6c6c6c6a63584d4135281c0f03000000000000000000000000000000000000000000010910161a1e1f20212e3a46525d677079828b9497908a837d767069625c5f666c737a81888f96978e857b72685f54483c3024201f1d1a150f0800000000000008131e29333c454e57616a737c868f989e979088817a726b645c554e463f372e241a0f040000000000000000000109111920272d32383c4044474a4d4f5051525353535252514f4d4b4845413d38332e28211a130b030000000000000000000000000000000000000000000000000b15202a333a4145464646464646464645423c352c23180e020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034323e4b5864717d8a97a3a99c9084786e645b524940382f261d140b0100000000000000000000000004101c2935424e5a66737f8b97a3afa5998d81756a5e53494039363435363a3f464f5a646f7b87929eaab6b2a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d040d17202a333d464d5254545454545454545454524c453b31261b0f030000000000000000000915222f3c4855626f7b8895a2afa4988b7e7164574b3e3124180b000710181f252a2c2d2c2925211d1915110d09050000000000000000000000020e19242f3942494e515355565656565554524f4b47423c362f28201810070000000000000000000000000000000000000000000000000000000000000000000000000000000000010910161a1e1f20202020202020201f1e1a16100901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a131d262f38404850575e646a6f74787c7e818384858686858483817e7b77736e69625c554d453c332a21180e0400000000000000000000010b15202a333c424a51585f646a6e7276787b7d7e8081818181807e7d7b7875726d68635d564e473e352c23190f050000000000000000000000000000000009141f2a353f49535c656e767d848a8f94989b9ea0a2a3a4a4a4a4a3a2a09e9b97938e88827a726a61574d43392e24190d0200000000000000000000000000030a101417191c2835424f5b6875828f9084776a5d5044372a1d191815110b04000000000000000000000000000000000000000000000000000000000000000000000007111a232c353f4851595e5f5f5f5f5f5f5f5f5f5e5951473c3025190c000000000000000000000000000000000000000000000000050a0e1113131e2a35414b555e677079828c959b958e88817a746d676a70777e858c9399988e857c726960564d43382c201413110e090400000000000000020d17212a333c454f58616a737d868f98a19a938b847d756e676058514940362c2015090000000000000000000000070e151c21272c3034383b3e404243454546464646454443413e3c3935312d28221c160f080100000000000000000000000000000000000000000000000000040e18212930353839393939393939393936312b231a1107000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034303d4956626e7b87939faaa1958a80766d645b524a41382f261d1309000000000000000000000000000d1926323e4a57636f7b87939faba99e92867b70655b524a4542414243464a5058616b76818c97a1a6aeb2a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01050e18212b343c42464848484848484848484746413b33291f150a000000000000000000000915222f3c4855626f7b8895a2afa4988b7e7164574b3e3124180b050f19222a3136393a3935312d2925211d1915100a0300000000000000000006131f2a36414b545a5e60616263636362615e5b57524d474039322a22191007000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0e1113131313131313131313110e0a05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010b141d262e363e454c53595f64686c6f7274767878797978787674726f6b67625d57514a433b332a21180f060000000000000000000000030f1b26323c454d53565656595e6266696c6e707273737474737372706e6c6966615d57524b443d352c231a11070000000000000000000000000000000000030e18232d37414a535c646b72797e84888c8f9193959697979897969594918f8b87827d77706860574e453c32271d120700000000000000000000000000050e151b202426262835424f5b6875828f9084776a5d5044372a262624211c160f07000000000000000000000000000000000000000000000000000000000000000000000008111a232d363f474e52535353535353535353524e473f352a1f140800000000000000000000000000000000000000000000000000000205060d19242f39434c555e677079838c959e99938c867f7872747b828990979d988f867c736a60574e443b31261b1006040200000000000000000000050f18212a333d464f58616b747d879099a29d968f878079716a635b52483d3125190d000000000000000000000000040a10161b2024282c2f3133353738393939393938373634322f2c2925211c17110b0500000000000000000000000000000000000000000000000000000000060f171e24292b2c2c2c2c2c2c2c2c2c2a262019110800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d40342d3a46525e6a76828e99a4a69c92887f766d645c534a41382f251b11060000000000000000000000000a16222e3a47535f6b76828e9aa5aea3978c81776d645c56514f4e4e5052565b626a737d889294959ca6b1a5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0100060f19222a31363a3b3b3b3b3b3b3b3b3b3b3936302921170d03000000000000000000000915222f3c4855626f7b8895a2afa4988b7e7164574b3e3124180b0c17212b343c42464745413d3935312d2926211c150d0400000000000000000916222f3b47525d666a6c6e6f7070706f6d6b67635e58524b443c342b22191006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141c242c343b42484e53585c606366686a6b6c6c6c6c6b6a6865635f5b57524c463f38312921180f060000000000000000000000000713202c38434e575f6363636363605a5d5f626365666767676766656462626362605d59534d463e352c22180e0400000000000000000000000000000000000007111b252f38414a525a61676d73777c7f82858788898a8b8b8a8a898785827f7b77716c655e564e453c332a20150b00000000000000000000000000050e1720272c3033333335424f5b6875828f9084776a5d504437333333312d2721191006000000000000000000000000000000000000000000000000000000000000000000000008111b242d363d424546464646464646464645423d352d23190e03000000000000000000000000000000000000000000000000000000000008131d27313a434c555e67707a838c959e9e97908a837d7f868d949ba19990867d736a61574e453c32291f150a0000000000000000000000000000060f18212b343d464f59626b747d879099a0a099928a837c746d64594d4135281c0f0000000000000000000000000000050a0f14181c1f222527292a2b2c2c2c2c2c2c2b29282523201d1915100b0600000000000000000000000000000000000000000000000000000000000000050d13181c1f20202020202020201f1d1a150e070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d40342a36424e5a66717c87929ca6a49a91887f766e655c534a41372d22180d02000000000000000000000006121e2a36424e5a66727d89949faaa99e93897f766e67615e5c5b5b5c5e62676d747c868f92888a95a1aea5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0100000710181f252a2d2e2e2e2e2e2e2e2e2e2e2d2a251e170f0500000000000000000000000915222f3c4855626f7b8895a2aea4988b7e7164584b3e3225180b121d28333d464d5253514d4946423e3a36322d271f160d03000000000000000b1824313e4a57636f77797b7c7c7d7d7b7a77736f69635d564e463d342b22180f05000000000000000000000000000000000000000000000000000000000000000004070808080808080808080807040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a131a222930373c42474c505357595b5d5e5f5f5f5f5e5d5b5956534f4b46413b352e271f170f06000000000000000000000000000916232f3c48545f6a6f6f6f6f6f6b615653555758595a5a5a5c61666a6d6f6f6f6d69645e5750473e342a20150a0000000000000000000000000000000000000009131d262f3840484f565c62676b6f7376787a7b7d7d7e7e7d7d7c7a7876736f6b66605a534c443c332a21180e04000000000000000000000000010c17202931383d3f404040424f5b6875828f9084776a5d50444040403f3d39322b22180e03000000000000000000000000000000000000000000000000000000000000000000000009121b242b3236393939393939393939393936312b231b1107000000000000000000000000000000000000000000000000000000000000010b151f28313a434c555e68717a838c959ea29b958e888a91989ea39a90877e746b62584f463c332a20170d03000000000000000000000000000000060f19222b343d475059626b757e879093939393938e867f76695d5043372a1d100000000000000000000000000000000004080c101316181a1c1d1e1f2020201f1f1e1d1b191614100d09040000000000000000000000000000000000000000000000000000000000000000000002080c1012131313131313131313110e0903000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d403427323e4954606b75808a949da6a39a918980776e655c53493f342a1f14090000000000000000000000020e1a26323e4955616c77838e99a3ada59b91888078726d6a686768696b6e72787e868e978c818794a0ada5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000000060e141a1e2021212121212121212121201d19130d050000000000000000000000000815222e3b4854616e7b8794a1ada5988c7e7265594c3f33261a1618222e3a454f585e605d5a56524e4a46423e3831281f150a000000000000000b1825323e4b5865717e868889898a89888683807a756e6760584f463d342a21170d020000000000000000000000000000000000000000000000000000000000060c10131515151515151515151513100c0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010910171f252b31363b4044474a4d4f50515252525251504f4c4a47433f3a353029231c150d0500000000000000000000000000000b1724313d4a5764707b7c7c7c7c7266594c494a4b4f555c62686d72777a7c7c7b79757069615950463c32271c1105000000000000000000000000000000000000010b141d262e363d454b51565b5f6366696c6d6f7071717171706f6e6c6966635f5a554f49423a332a21180f060000000000000000000000000007131e29323b43494c4c4c4c4c4f5b6875828f9084776a5d504c4c4c4c4c49443c342a1f140900000000000000000000000000000000000000000000000000000000000000000000000009121a20262a2c2c2c2c2c2c2c2c2c2c2c2a26201911090000000000000000000000000000000000000000000000000000000000000000030d161f28313a434c565f68717a838c969fa6a09994959ca2a49a91887e756b625950463d342a21180e050000000000000000000000000000000000071019222b353e475059626c757e868686868686868684776a5d5044372a1d11000000000000000000000000000000000000000307090c0e0f111212131313131211100e0c0a070401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034272d38434e59646e78828b949ca4a39b928981776e645b50463b30251a0f0300000000000000000000000a15212d39444f5b66717c87919ba5ada39a928a837e7a7775747575777a7e8389909890857a8794a1aea5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d010000000003090e11141515151515151515151514110d0802000000000000000000000000000714212d3a4753606d7986939faca69a8d8174675b4e42352924232429333f4b56616a6d6a66625e5a56524e49433a31271c10050000000000000b1825323e4b5865717e8b94959696969593908b868079726a61584f463c33291e140a000000000000000000000000000000000000000000000000000000020a11181c2021222222222222222221201c18110a0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060d141a20262b2f34373b3e4042444545464646454442403d3a37332e2a241e18110a030000000000000000000000000000000a1724303d4a5663707c8989898175685c50494e545a60676d73787e838689898885817b736b62584e43382d22160b00000000000000000000000000000000000000020c1824303b454f565b5c5c5c5c5c5d5f616263646464646362615f5d5c5c5c5c5c5a544b41362b1f130700000000000000000000000000000c18242f3a444d545859595959595b6875828f9084776a5d595959595959554e463c31251a0e02000000000000000000000000000000000000000000000000000000000000000000000000080f151a1d1f2020202020202020201f1d1a150f0700000000000000000000000000000000000000000000000000000000000000000000040d161f28313a434d565f68717a848d969fa0a0a0a0a0a09b92887f756c635950473e342b22180f0600000000000000000000000000000000000000071019232c353e47505a636c7579797979797979797974695c5043362a1d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002050707070707070707070705020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d40342727323d48525c667079828a929ba4a49b938a80766c62584d42372b201409000000000000000000000005101c28333e4a55606a758089939ca5aca39c958f8a86838281818284878a8f949b92887e7a8794a1aea5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d010000000000000205070808080808080808080807050100000000000000000000000000000006131f2c3945525e6b7884919daaa89c8f83766a5e52463b34313030343b45505b67737a76726e6a66625e5a554d43382d2115090000000000000b1825323e4b5865717e8b98a2a3a3a3a29f9c97918b847c736a61584e453a30261b110600000000000000000000000000000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2c28231c140b020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090f141a1f23282b2e31333537383939393938373533312e2b27231e19130d0700000000000000000000000000000000000916222f3c4855616e7b87949185786d6158565a5f656c72787e848a8f93959695928c857d746a60554a3e33271c1004000000000000000000000000000000000000000f1c2834404c57616769696969696969686258575757575c646869696969696969655d53473c2f23170a0000000000000000000000000000101c2935404c565f656666666666666875828f9084776a6666666666666560584d42362a1e11050000000000000000000000000000000000000000000000000000000000000000000000000004090e111313131313131313131313110e0904000000000000000000000000000000000000000000000000000000000000000000000000040d161f28313a444d565f68717a848d93939393939393928980766d635a51473e352c2219100600000000000000000000000000000000000000000007101a232c353e48515a636b6c6c6c6c6c6c6c6c6c6a62584c4034281b0f0000000000000000000000000000000000000000000000000000000000000000000000000000000406070707070707070502000000000000000000000000000000000000000000000000000000040a0e1113141414141414141413120e0a04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d403427202b36404a545e6770788189929ba4a59c92897e74695e53483c3125190e0200000000000000000000000b16222d38434e59636d77818a939aa2a8a6a09a9692908e8e8e8f9193969b9a928980767b8894a1aea5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d010000000000000000000000000000000000000000000000000000000000000000000000000004111d2a3743505c6975828e9ba7ab9f92867a6e62574d45403d3c3d40454d57616c7883827e7a76726e6a665f55493e3225190d0000000000000b1825323e4b5865717e8b989a9a9b9da1a5a8a39c958e857c736a60564c42382d22180d020000000000000000000000000000000000000000000000000a141d262e34383b3b3b3b3b3b3b3b3b3b38342e261d140a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e13171b1f222527292a2b2c2c2c2c2b2a292724221e1b17120d08020000000000000000000000000000000000000714202d3a46535f6c79859295897e73696463656b71777d838a8f959a9fa2a3a19d978f867c71665b4f44382c20140800000000000000000000000000000000000000111e2b3744505d697375757575757575746a5e524b4b56626d75757575757575756f64584b3f3225190c0000000000000000000000000000121f2b3844515d68717373737373737375828f90847773737373737373726a5e52463a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d161f28323b444d565f68717b84868686868686868680766d645b51483f352c23191007000000000000000000000000000000000000000000000008111a232c363f4851595e5f5f5f5f5f5f5f5f5f5e5950463b3024180c00000000000000000000000000000000000000000000000000000000000000000000000001070c101314141414141413110e0903000000000000000000000000000000000000000000000000070f151a1e202020202020202020201e1a150f080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a242e38424c555e666e778089929ba5a49a90867b7064594d42362a1e1206000000000000000000000005111c27323c47515c656f78818990979ca1a5a6a29f9d9b9b9b9c9d9f9c968f8880776e7b8894a1aea5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0100000000000000000000000000000000000000000000000000000000000000000000000000010f1b2834414d5a66727e8b97a3aea2968a7f73695f56504c4a49494c51575f68737d898e8a86827e7a7671665a4e4134281b0e0200000000000b1825323e4b5865717e8b8e8e8e8f9195999fa5a7a0978f867c72685e54493f34291e1308000000000000000000000000000000000000000000000006111c262f383f4548484848484848484848453f382f261c11060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002070b0f1316181a1c1e1f1f20201f1f1e1c1a1815120f0b0601000000000000000000000000000000000000000005121e2b3844515d6a76838f9a8f857b74717072767c82888e959ba1a5a1a0a0a1a4a1988e83776c6054493d3024180c00000000000000000000000000000000000000121e2b3845515e6b7882828282828282796d6053464a5764717d828282828282807366594c403326190d000000000000000000000000000013202c3946535f6c798080808080808080828f908480808080808080807b6e6154483b2e21150800000000000000000000000000000000000000000000000000000000010406090b0d0f10111213131313121211100e0c0a080502000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d162029323b444d565f6972797979797979797979776e655b52493f362d231a11070000000000000000000000000000000000000000000000000008111a242d363f484e52535353535353535353524e473e352a1f14080000000000000000000000000000000000000000000000000000000000000000000000040c13181d20212121212121201e1a140e060000000000000000000000000000000000000000000008111920262a2d2d2d2d2d2d2d2d2d2d2a26211a120900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4134271a1c26303a434c545d656d768089939ea9a2978c81756a5e52463a2e2216090000000000000000000000000a15202b35404a535d666f777e858b9195999b9d9e9f9f9e9d9b9895908b857e766e6e7b8895a2aea5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0100000000000000000000000000000000000000000000000000000000000000000000000000000c1925313e4a56636f7b87939faba79b90857a7168615c59575656585c6269717a858f9a96928e8a868175685b4f4235281c0f0200000000000b1825323e4b5865717e828181818285898e949ba2a9a1988e847a70665b50453b3024190e03000000000000000000000000000000000000000000000b17222d38424a5154555555555555555554514a42382d22170b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306090c0e0f11121313131312110f0e0b090602000000000000000000000000000000000000000000000003101c2935424e5a6773808c98978e86807d7c7e82878d9399a0a49e9995939395989d9f94897d7165594d4134281c0f03000000000000000000000000000000000000121e2b3845515e6b78858f8f8f8f8f86796d6053464a5764717d8a8f8f8f8f8c807366594c403326190d0000000000000000000000000000121f2c3845515d69747f8a8c8c8c8c8c8c8d94958d8c8c8c8c8c8c8c81756a5f53463a2d201407000000000000000000000000000000000000000000000000000206090d101315181a1b1d1e1f1f2020201f1e1e1c1b191714120f0b080400000000000000000000000000000000000000000000000000000000000000000000000000000000040e172029323b444e5760686c6c6c6c6c6c6c6c6c6b655c534940372d241b110800000000000000000000000000000000000000000000000000000008121b242d363d424546464646464646464645423c352c23180e0200000000000000000000000000000000000000000000000000000000000000000000040d161d24292c2e2e2e2e2e2e2d2a251f181007000000000000000000000000000000000000000007111a232b3236393a3a3a3a3a3a3a3a3937322b241b1107000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946525f6c7986929faca79a8e8174675b4e4135281b141e28313a424b535b646e77828c97a2a99e92867a6f63564a3e3225190c000000000000000000000000040f19232e38414b545d656c747a8085898c8f9192929291908e8c8884807a736c646e7b8895a2aea5988b7e7165584b3e3225180b0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0100000000000000000000000000000000000000000000000000000000000000000000000000000916222e3a47535f6b77828e9aa5ada1978c837a736d686563636365686d737b838c96a1a29e9a94897d7165594d4034271b0e0100000000000b1824313e4a57636f777675747475787d82899099a1aaa0968c82776d62574c41362a1f1408000000000000000000000000000000000000000000000f1b27333f4a545c616161616161616161615c544a3f33271b0f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1926323f4b57636f7b88939f97918c8a898b8e93989ea59f99938d898686888c929a998d8175695d5044382b1f1306000000000000000000000000000000000000121e2b3845515e6b7885929c9c9c9386796d6053464a5764717d8a979c9c998c807366594c403326190d0000000000000000000000000000101c2935414c57636e79848f9999999999999d9e9a999999999991867a6f64594e42362a1e1205000000000000000000000000000000000000000000000004090e1216191c1f222426282a2b2c2c2c2c2c2c2b2a29272623211e1b1814100b07020000000000000000000000000000000000000000000000000000000000000000000000000000050e172029323c454e565d5f5f5f5f5f5f5f5f5f5f5b534a41372e251b1209000000000000000000000000000000000000000000000000000000000009121b242b3236393939393939393939393936312b231a110700000000000000000000000000000000000000000000000000000000000000000000020c161f282f35393a3a3a3a3a3a3936312a22190f05000000000000000000000000000000000000020d18232c353d4246474747474747474746433d362d23190e03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0d0f0f0f0f0f0f0d0a05000000000000000000000000000000000000000000000000000000050a0d0f0f0f0f0f0f0d0a050000000000000000000000000000000000000004080b0c0d0d0d0d0c0a0602000000000000121f2c3845525e6b7885919eaba89c8f8275695c4f43362a1d11161f2830394149525c66707b86919da9a3978b7e73665a4d4135281c0f0200000000000000000000000007121c262f39424b535b62696f74797d8082848586858584827f7c78746e6861616e7b8895a2aea5988b7e7165584b3e3225180b0013202c3946535f6c798693a0a0a09a8d8173675a4d4034271a0d01000000000000000000000000000000000000000000000000000000000000000000000000000006121e2a36424e5a66727d88939ea8a89e958c847d787472706f6f7174787e858d959ea8ada3998e83776c6054483c3024180c0000000000000916222f3b47525d666a69686767696c71777e878f98a2a89e94897e73685d52473c3025190e03000000000000000000000000000000000000000000121e2b37434f5b666d6e6e6e6e6e6e6e6e6d665b4f43372b1e1205000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000205080b0d0f101112121211100f0d0b0805020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a16232f3b47535f6b77828e99a29d999796979a9ea4a09a948e87827c79797c8188919b9185796c6053473b2e221509000000000000000000000000000000000000121e2b3845515e6b7885929ea9a09386796d6053464a5764717d8a97a4a6998c807366594c403326190d00000000000000000000000000000d1924303b46515c68737e8995a0a6a6a6a6a9aaa6a6a6a6a1968b8074695e53483c31261a0e02000000000000000000000000000000000000000000050b10151a1e2225292c2e31333536373839393939393837363432302d2a2724201c17130d080200000000000000000000000000000000000000000000000000000000000000000000000000050e17202a333c444c51535353535353535353524f4941382f251c13090000000000000000000000000000000000000000000000000000000000000009121a21262a2c2c2c2c2c2c2c2c2c2c2c2a2620191108000000000000000000000000000000000000000000000000000000000000000000000008131e28313a404547474747474746423c342b21160b00000000000000000000000000000000000007131f2a343e474e525353535353535353534e483f352a1f140800000000000000000000000000000000000000000000000000000000000000000000000000000000000000040b11161a1c1c1c1c1c1c1a16110b040000000000000000000000000000000000000000000000040b11161a1c1c1c1c1c1c1a16110b04000000000000000000000000000000030a10141719191919191816120d070000000000111e2b3744515d6a7783909da9aa9d9084776b5e5245392c20140d161e272f37404a545e6975818d99a6a79b8f8276695d5043372a1e1104000000000000000000000000000a141d273038414950575e63686d7073767778797878777573706c68635d57616e7b8895a2aea5988b7e7165584b3e3225180b0013202c3946535f6c798693939393938d8173675a4d4034271a0d010000000000000000000000000000000000000000000000000000000000000000000000000000020e1a26323e4955606c77828c96a0a9a79e968f8984817e7d7c7c7e81848a90979fa8ada49b91877c71665b4f44382c20140800000000000006131f2a36414b545b5d5c5b5a5b5c60666d757d86909aa4a59b90857a6f63584d41362b1f140800000000000000000000000000000000000000000013202c3946525f6c777b7b7b7b7b7b7b7b776c5f5246392c2013060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001060a0e1215181a1c1d1e1e1e1e1e1d1b1a1714110e0a050000000000000000000000000000000000000000000000000000000000000000000000000000000000000007131f2b37434f5a66717c87919ba3a5a3a3a4a6a19b958f89827c76716d6d70767f899495887c6f63564a3d3124180b000000000000000000000000000000000000121e2b3845515e6b7885929eaba09386796d6053464a5764717d8a97a4a6998c807366594c403326190d000000000000000000000000000008131e2a35404b56626d78838f9aa5b0b3b3b5b5b3b3b1a69b9085796e63584d41362b2015090000000000000000000000000000000000000000050b11161c21252a2e3235383b3d40414344454646464645454442413f3c3a3734302c28231e19130e0801000000000000000000000000000000000000000000000000000000000000000000000000050e17212a323a404446464646464646464646433e372f261d130a010000000000000000000000000000000000000000000000000000000000000000080f151a1e1f2020202020202020201f1d1a150e070000000000000000000000000000000000000000000000000000000000000000000000020e1925303a434b51545454545454524d463d33281d110500000000000000000000000000000000000b1824303b4650595f60606060606060605f5951473c3024180c000000000000000000000000000000000000000000000000000000000000000000000000000000000000050e161c222628292929292826221c160e05000000000000000000000000000000000000000000050e161c222628292929292826221c160e0500000000000000000000000000050e151b2024262626262625221e18120a01000000101d2936424f5c6875828e9ba7ac9f93867a6d6155483c30251a1513151d252e38424d5865717d8a97a3aa9e9184786b5e5245382c1f120600000000000000000000000000020b151e262f373f464c52585c616467696b6b6c6c6b6a686663605c575255616e7b8895a2aea5988b7e7165584b3e3225180b0013202c3946535f6c79868686868686868173675a4d4034271a0d010000000000000000000000000000000000000000000000000000000000000000000000000000000a16212d38444f5a65707a858e97a0a7a8a19a95908d8b8a89898a8d90959ba1a9aaa39b928980756b60554a3e33271c1004000000000000020e19252f39424a4f51504e4e4e50545b636b747e88929da7a1968b8075695e53473c3025190d02000000000000000000000000000000000000000013202c3946535f6c798688888888888886796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001070d12161a1e212426282a2b2b2b2b2b29282624211e1a16110c060100000000000000000000000000000000000000000000000000000000000000000000000000000000030f1b26323e4955606a757f8991989d9f9f9e9a95908a847d77716b656060646d78838f978b7e7265584c3f33261a0d000000000000000000000000000000000000121e2b3845515e6b7885929ea0a09386796d6053464a5764717d8a97a0a0998c807366594c403326190d0000000000000000000000000000020d18242f3a45505c67727d89949faab5c0c1c2c0b7aba0958a7e73685d52473b30251a0f03000000000000000000000000000000000000020910161c22272c31363a3e4145474a4c4e505152525353535251504f4d4b494643403c38342f2a251f19130c05000000000000000000000000000000000000000000000000000000000000000000000000050f1820292f35383939393939393939393937332d251d140b0100000000000000000000000000000000000000000000000000000000000000000000040a0e111313131313131313131313110e090300000000000000000000000000000000000000000000000000000000000000000000000006121e2a36414c555d6061616161615e584f44392e22160900000000000000000000000000000000000e1b2734404c58626b6d6d6d6d6d6d6d6d6b63584d4134281c0f0200000000000000000000000000000000000000000000000000000000000000000000000000000000040e1720272e32353636363635322e2720170e0400000000000000000000000000000000000000040e1720272e32353636363635322e2720170e040000000000000000000000050e1720272c303333333333322f2a231c130a0000000e1b2734414d5a6673808c98a5aea295897d7164584d41362c25211f1f1f2126303c4956626f7c8895a2ac9f9386796c5f5346392d2013060000000000000000000000000000030c141d252d343b41474c5154585a5c5e5f5f5f5e5d5c5a5754504b4855616e7b8895a2aea5988b7e7165584b3e3225180b00131f2c3946525f6b7679797979797979797266594d4033271a0d0000000000000000000000000000000000000000000000000000000000000000000000000000000005101c27333e49545e69727c858e969da3a9a6a19d9a9896969697999ca1a6aaa59f98918980776d63594e44382d22160b000000000000000008131d2730383e42444342414144495159626c76808b96a0a89d91867a6f64584d41352a1e1207000000000000000000000000000000000000000013202c3946535f6c798693959595959386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060d13181d22272a2e313335363738383837363533302d2a26221d18120c05000000000000000000000000000000000000000000000000000000000000000000000000000000000a16212d38434e59636d767f878d909293918e89847e79726c66605a54535b67727e8b938d8174675a4e4135281b0f020000000000000000000000000000000000121e2b3845515e6b7885929393939386796d6053464a5764717d8a939393938c807366594c403326190d00000000000000000000000000000007121d29343f4a55616c77828e99a4afbac5c7bcb1a59a8f84786d62574c40352a1f1408000000000000000000000000000000000000050d141a21272d33383d42464a4e515456595b5c5d5e5f5f5f5f5f5e5d5c5a585553504c4844403b36302a241e171009010000000000000000000000000000000000000000000000000000000000000000000000060e171e24292b2c2c2c2c2c2c2c2c2c2c2a27221b130b020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000815212e3a47525e676d6d6d6d6d6d6a61564a3e3125180c0000000000000000000000000000000000101c2936424f5c68747a7a7a7a7a7a7a7a75695d5043372a1d1004000000000000000000000000000000000000000000000000000000000000000000000000000000000b16202932393e4242424242423e39322920160b000000000000000000000000000000000000000b16202932393e4242424242423e39322920160b00000000000000000000010c17202931383d3f404040403e3b352e251c120700000c1925323e4b5764707d8995a2aea5998d8175695e52483e36312e2c2c2c2d30363e4956626f7c8995a2ada09386796d6053463a2d201307000000000000000000000000000000020b131b222930363b4044484b4e505152525252514f4d4b47443f4855616e7b8895a2aea5988b7e7165584b3e3225180b00111e2a37434f5a646b6c6c6c6c6c6c6c6c6960554a3d3125180c00000000000000000000000000000000000000000000000000000000000000000000000000000000000b16212c37424c57606a737c848b92989da1a5a7a6a4a3a2a3a4a6a8a5a29e99948e877f776e655b51473d32271c11050000000000000000010c151e262d32363736353434383f47505a646e79848f9aa5a3978c8075695d52463b2f23170c000000000000000000000000000000000000000013202c3946535f6c798693a0a2a2a09386796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a11181e24292e33373a3d404243444545454443413f3d3a36322d29231d17100902000000000000000000000000000000000000000000000000000000000000000000000000000005101c27323c47515b646d757b8184868685827e78736d67615b544e484a56636f7b8686868275695c4f4336291d10030000000000000000000000000000000000121e2b3845515e6b7885868686868686796d6053464a5764717d868686868686807366594c403326190d000000000000000000000000000000010c17232e39444f5b66717c87939ea9b4bfc1b6aa9f94897d72675c51463a2f24190e020000000000000000000000000000000000080f171e252c32383e44494e52565a5d60636567696a6b6c6c6c6c6b6b6a686664625f5c5854504b46413b352f29221b130c040000000000000000000000000000000000000000000000000000000000000000000000050c13181c1f202020202020202020201e1b16100901000000000000000000000000000000000000000000000000000000000000000000000000000000000406080808080808080808070501000000000000000000000000000000000000000000000000000000000000000000000000000a1623303d4956636f797a7a7a7a7a7266594d4033271a0d0000000000000000000000000000000000101c2936434f5c69768387878787878784776a5d5044372a1d110400000000000000000000000000000000000000000000000000000000000000000000000000000006111d27323b444a4e4f4f4f4f4e4a443b32271d1106000000000000000000000000000000000006111d27323b444a4e4f4f4f4f4e4a443b32271d110600000000000000000007131e29323b43494c4c4c4c4c4b463f372e23180d02000a16232f3c4854616d7986929eaaa99d91867a6f64595048413d3a3938393a3d4147505a66727e8a97a4ac9f9386796c5f5346392d20130600000000000000000000000000000000010911181e252a3034383c3f414344454646454443413e3b383b4855616e7b8895a2aea5988b7e7165584b3e3225180b000e1a26323e48525a5f5f5f5f5f5f5f5f5f5d574e44392d211509000000000000000000000000000000000000000000000000000000000000000000000000000000000005101b26303b454f58616a727981878c9195989b9d9e9f9f9f9e9d9b9996928e89837c756d655c534940352b20160b00000000000000000000030c141c2226292a2a2828282d353e48525d67727d89949fa89d91867a6e63574b4034281c10050000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050d141c23292f353a3f4346494c4e505151515151504e4c4946423e39342e28221b140c0400000000000000000000000000000000000000000000000000000000000000000000000000000a15202b353f49525b636a70747779797875726d68625c565049433d4754606c777979797974685c4f4336291d10030000000000000000000000000000000000121e2b3844515e6a7579797979797979766b5f53464a57636f79797979797979797165584c3f3326190c0000000000000000000000000000000006111c28333e4954606b76818d98a3aeb9bbb0a4998e83776c61564b3f34291e1307000000000000000000000000000000000109121a212930373d444a4f555a5e62666a6d6f7274757778797979797877767573716e6b6864605c57524c47413a332c251e160e05000000000000000000000000000000000000000000000000000000000000000000000001070c101213131313131313131313110f0a0500000000000000000000000000000000000000000000000000000000000000000000000000000000060c101314151515151515151413110d080200000000000000000000000000000000000000000000000000000000000000000000000a1724303d4a5763707d878787878173675a4d4034271a0d0100000000000000000000000000000000101c2936434f5c69768390949494949084776a5d5044372a1d11040000000000000000000000000000000000000000000000000000000000000000000000000000000a16222e39444d555b5c5c5c5c5b554d44392e22160a00000000000000000000000000000000000a16222e39444d555b5c5c5c5c5b554d44392e22160a0000000000000000000c18242f3a444d5458595959595751493f352a1e1206000713202c3845515d6975818d99a5aea2978b80766b6259524d494745454547494d5259626c76828e9aa6aa9d9184786b5e5245382c1f1206000000000000000000000000000000000000060d13191f24282c303235363838393938373634322f2e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000a16212c3740484f525353535353535353514c453c32271c110500000000000000000000000000000000000000000000000000000000000000000000000000000000000009141f29333d464f5860686f757b8185898c8e909192929292918f8d8a86827d77716a635b534a41372e24190f040000000000000000000000020a11161a1d1e1d1c1b1c232c36404b56616c77838f9aa6a2978b7f73685c5044392d2115090000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f171f262d343a40464b4f5356595b5c5d5e5e5e5d5c5a5855524e4a453f3a332d251e160e0500000000000000000000000000000000000000000000000000000000000000000000000000040f19232d37404951595f64686b6c6c6b6966615c57514b453e383844505b656b6c6c6c6c6a62584c4034271b0e020000000000000000000000000000000000101d2935424e59636b6c6c6c6c6c6c6c6b645a4f4347535e676c6c6c6c6c6c6c6c685f54493d3024170b00000000000000000000000000000000000b16222d38434e5a65707b87929da8b3b5a99e93887d71665b5045392e23180d01000000000000000000000000000000020a131b242b333a42484f555b60656a6e7276797c7e818284858686868685848382807d7b7874716c68635e58524c453e372f2820170f0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a11171c1f212121212121212121201d19130c04000000000000000000000000000000000000000000000000000000000000000000000a1724303d4a5763707d8a94948d8174675a4d4134271a0e0100000000000000000000000000000000101c2936434f5c697683909ca0a09d9084776a5d5044372a1d11040000000000000000000000000000000000000000000000000000000000000000000000000000000d1a26333f4a555f6769696969675f554a3f33261a0d01000000000000000000000000000000000d1a26333f4a555f6769696969675f554a3f33261a0d010000000000000000101c2935404c565f6566666666635b51463b2f22160a0004101c2935414d5965717d88949faaa89d92877d746b645e5956535252525355595d646b747d88939faaa69a8e8275695c5043372a1e11040000000000000000000000000000000000000002080e13181c202326282a2b2c2c2c2c2b292725222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0005101a252e373e4346464646464646464645413b332a20160b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000020d17212b343d464e565d646a7075797c80828485868686858482807d7a76716c666059514941382f251c12080000000000000000000000000000050a0e1011100f0e111a242f3a45505b66727d8995a1a79c9084786d6155493d32261a0e0200000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f18212931383f464c51565b5f626567696a6b6b6b6a696765625e5a56514b453e37302820170f060000000000000000000000000000000000000000000000000000000000000000000000000007111b252e373f474e54585c5e5f5f5f5d5955504b45403a332d333f49535b5f5f5f5f5f5e5950463b3024180c0000000000000000000000000000000000000d1925313d4751595e5f5f5f5f5f5f5f5f5a52493e414c555c5f5f5f5f5f5f5f5f5d564d43382c201408000000000000000000000000000000000005101b27323d48535f6a75808c97a2adafa3988d82766b60554a3e33281d1206000000000000000000000000000000010b141c252d353d454c535a60666c71767a7e8286898b8d8f9091929393929291908e8c8a8784817d78746e69635d575049413a322921180f060000000000000000000000000000000005090c0e0e0e0e0e0e0e0e0e0e0d0a07020000000000000000000000000000000000000000000000000000000000000001060a0c0e0e0e0e0e0e0e0e0e0e0c09050000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2d29241e160e050000000000000000000000000000000000000000000000000000000000000000000b1724313e4a5764717d8a979a8e8174675a4d4134271b0e0100000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d11040000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2935424e5b67717575757571675b4e4235291c0f03000000000000000000000000000000000f1c2935424e5b67717575757571675b4e4235291c0f030000000000000000121f2b3844515d6871737373736d63574b3e3225180c00000c1925313d4954606c77838e99a3aea4998f867d756f696562605f5f5f606265696f757d868f9aa4aca1968a7e7266594d4134281b0f0200000000000000000000000000000000000000000002070c101417191b1d1e1f1f1f1f1e1d1b19222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000009131c252c32373939393939393939393835302921180e040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050f19222b343c444c52595f64696d707375777879797978777673716e6a65605b554e473f372f261d130a000000000000000000000000000000000000000000000008121d28333e4a55616d7884909ca8a195897d72665a4e42362a1f130700000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f18212a333b424a51575d62676b6f72747677777877777574716e6a66615c565049423a322921180e050000000000000000000000000000000000000000000000000000000000000000000000000009131c252d353c42484c4f52535352504d4945403a342e28222d3741494f5253535353524e473e342a1f13070000000000000000000000000000000000000915202b363f484e5253535353535353524f4940373a434b505353535353535353514c443b31271b10040000000000000000000000000000000000000a15212c37424d59646f7a85919ca7a89d92877b70655a4f44382d22170c000000000000000000000000000000000a131d262e373f474f575e656b71777d82878b8f9295989a9c9d9e9f9fa09f9f9e9c9b999694908d8984807a746e68615a534b443b332a21180f0600000000000000000000000000040b1115191a1a1a1a1a1a1a1a1a1a1917130d070000000000000000000000000000000000000000000000000000000000060c1216191a1a1a1a1a1a1a1a1a1a1916110b050000000000000a141d262d34383a3b3b3b3b3b3b3b3b3935302820170e0400000000000000000000000000000000000000000000000000000000000000000b1824313e4a5764717d8a979b8e8174675b4e4134281b0e0100000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c69768282828276695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768282828276695c4f4336291c1003000000000000000013202c3946535f6c79808080807366594c403326190d00000814202c38444f5b66717c87929ca6aba1988f87817a75716f6d6c6b6b6d6e71757a80878f98a1aba59a9084796d6156493d3125180c0000000000000000000000000000000000000000000000000004070a0d0f10121213131211100e15222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000010a131a21262a2c2c2c2c2c2c2c2c2c2c29241e170f0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071019222a323a41484e53585d606466686a6b6c6c6c6b6a696764615e59554f49433c352d251d140b010000000000000000000000000000000000000000000000010c17222d3945505c6874808b97a3a69a8e82766a5f53473b2f23170b00000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000000000000040e18212a333c454d545b62686e73777b7e8182848485848482817e7a77726d67615b534c443b332a20170d03000000000000000000000000000000000000000000000000000000000000000000000000010a131b232b31373c40434546464543413d39342f29231d1b262f373e43464646464645423c352c22180d02000000000000000000000000000000000000040f19242d363d42454646464646464646433e372e31394044464646464646464644403a322920150a00000000000000000000000000000000000000040f1a26313c47525e6974808b96a1a2978c81756a5f54493d32271c110500000000000000000000000000000009121c252f3840495159616870767d83888e92979b9ea1a4a6a8a9a8a7a6a6a6a7a8a9a7a5a3a09d9995908b86807a736c655d554d453c332a21180e040000000000000000000000060e161c21252727272727272727272726231e1811090000000000000000000000000000000000000000000000000000000810171d22262727272727272727272725221d160f070000000005111b262f383f4447484848484848484745413a322920160c03000000000000000000000000000000000000000000000000000000000000000b1824313e4b5764717e8b989b8e8174685b4e4135281b0f0200000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c6976838f8f8376695c4f4336291c100300000000000000000000000000000000101c2936434f5c6976838f8f8376695c4f4336291c1003000000000000000013202c3946535f6c79868c8c807366594c403326190d000004101c27333e4a55606b75808a949da5aaa199928c86817e7b79787878797b7d81868b9299a1aaa59c93897e73685c5145392d21150900000000000000000000000000000000000000000000000000000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000010910161a1e1f20202020202020201f1c19130d0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007101820282f363c42484c5154575a5c5d5e5f5f5f5f5e5c5a5855514d49443e38322b231b130b020000000000000000000000000000000000000000000000000005111c2834404b57636f7b8793a0aa9f93877b6f63574b3f34281c1004000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000000000000000020c16202a333c454e575e666d73797e83878b8d8f90919291908f8d8a87837e78736c655e564d453c32291f150b010000000000000000000000000000000000000000000000000000000000000000000000000109111920262b303436383939393734312d28231e1812141d252d333739393939393936312b231a1106000000000000000000000000000000000000000008121b242b323639393939393939393937322c25272e3438393939393939393938352f2920170e0300000000000000000000000000000000000000000914202b36414c58636e7984909b9c91867b6f64594e43372c21160b00000000000000000000000000000006111b242e37414a525b636b737a81888e94999ea3a7aba7a3a19e9c9b9a9a999a9a9b9d9fa1a4a7a9a5a19c97918b857e776f675f574e453c332a20160c02000000000000000000050f1820272d3134343434343434343434332f2a231b12090000000000000000000000000000000000000000000000000007111a22292e3234343434343434343434322e28211910060000000b16222d38414a50545454545454545454524c443b32281e150b010000000000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b989b8e8275685b4e4235281b0f0200000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d0000000b16222d38434e59646e78828b949ca3aaa49d97928e8a888685858586888a8d92979da3aaa39b938a81776c62574b4034291d110500000000000000000000000000000000000000000000000000000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000050a0e1113131313131313131312100d08020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060e161e252b31373c4044484b4d4f51525253525251504e4b4945413d38332d272019110901000000000000000000000000000000000000000000000000000006121e2a36424e5965717d8995a1ada3978c8074685c5044382c201409000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000000000009131e28323c454e57606870787e858a8f93979a9c9d9e9e9e9d9c9996938f8a847e776f685f574e443b31271d13080000000000000000000000000000000000000000000000000000000000000000000000000000070e151b2024272a2c2c2c2c2a2825211d17120c070b131b22272a2c2c2c2c2c2c2a25201911080000000000000000000000000000000000000000000009121a21262a2c2c2c2c2c2c2c2c2c2a27211b1d23282b2c2c2c2c2c2c2c2c2b29241e170e05000000000000000000000000000000000000000000030e1925303b46515d68737e8a95968b8074695e53483d31261b10050000000000000000000000000000040e18232d364049535c646d757d858c93999fa5aaa8a39f9b979492908e8d8d8c8d8d8e909295989b9fa4a9a8a29c968f888179716960574e453c32281e140a0000000000000000020d17212a32393e404141414141414141413f3b352d241b11060000000000000000000000000000000000000000000000040f19232c343a3e414141414141414141403e39332b22180d0200000f1b27333e49535b6061616161616161615d564d433a30271d13090000000000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b989b8f8275685b4f4235281c0f0200000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104050607070707060503010000000000000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d00000005111c27323d47525c666f78818a91989fa4a8a29e9a9794939292929394969a9da2a8a49f98918981786f655b50453a2f23180c0000000000000000000000000000000000000000000000000000000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040c131a20262b3034383b3e41434445464646454443413f3c3935312c27221c150e07000000000000000000000000000000000000000000000000000000000b17232f3b46525e6a76828e99a5b1a89c9084786c6055493d3125190d010000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000000000000005101a25303a444e57616a727a828990969ba0a3a6a6a4a3a3a3a4a6a6a39f9a958f898179716960564d43392f241a0f04000000000000000000000000000000000000000000000000000000000000000000000000000003090f14181b1d1f20201f1e1c1915110c070100010910161b1e20202020201f1d1a140e07000000000000000000000000000000000000000000000000080f151a1e1f202020202020201f1e1b161012171c1f20202020202020201f1c18130c05000000000000000000000000000000000000000000000008131f2a35404b57626d78848f90857a6e63584d42362b20150a0000000000000000000000000000000b15202a343e48525b656e767f878f969ea4aba9a39d98938e8b888583828180808081828385888b8f93989da3a9a7a19a938b837b726a61574e443a30261c11060000000000000008131e29333c444a4d4d4d4d4d4d4d4d4d4d4b463f362d22170c00000000000000000000000000000000000000000000000a15202b353e454b4d4d4d4d4d4d4d4d4d4d4a443d342a1f14080000111e2b37434f5b656d6e6e6e6e6e6e6e6e685f564c42392f251b110700000000000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c989c8f8275685b4f4235291c0f0200000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d11101213131414131311100d0b07040000000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d000000000b16202b36404a545d666f7880878d93999da1a4a6a3a1a09f9e9f9fa1a3a6a4a19d99938d8780776f665d53493e34291e12070000000000000000000000000000000000000000000000000000000000000000000000000000000815222e3b4855616e7b8895a2aca5988b7e7165584b3e3225180b00000000000000000508090a0a0a0a0a0a0a0a09080501000000000000000000000000000206080a0a0a0a0a0a0a0a0a09070400000000000000000000000000000000000000000000000001080f151a1f24282c2f32343637383939393938363532302d2925211c16110a040000000000000000000000000000000000000000000000000000000004101c28333f4b57636f7a86929eaab6aca195897d7165594d4135291e12060000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000000000b16212c37414c566069737c848c949ba1a7a5a19d9a98969696989a9da1a6a6a19a938b837b72685f554b41362c21160b0000000000000000000000000000000000000000000000000000000000000000000000000000000003080b0e1112131312110f0c0905000000000000050a0f11131313131313110d09030000000000000000000000000000000000000000000000000000040a0e11131313131313131313110e0a05070c0f12131313131313131312100c0701000000000000000000000000000000000000000000000000020d19242f3a45515c67727d898a7f73685d52473c30251a0f04000000000000000000000000000007121d27323c46505a646d7780899199a1a8ada59e98928c87837e7b78767574737373747577797c7f83878c92989ea5aca59d958d857c736960564c42382d23180d030000000000000c1824303b454e555a5a5a5a5a5a5a5a5a5a5751493f34281d1105000000000000000000000000000000000000000000030f1b26323d4750565a5a5a5a5a5a5a5a5a5a564f463b3025190d010013202c3946525f6c777b7b7b7b7b7b7b7a71685e544b41372d23190f05000000000000000000000000000000000000000000000000000000000c1926323f4c5865727e8c989c8f8275695c4f4236291c0f0300000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1b1d1e1f202020201f1e1c1a1714100c07020000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d00000000040f19242e38424b545d666e757c82888d9195989a9c9e9f9fa09f9f9e9c9a9895918d88827c756d655d544b41372d22170c010000000000000000000000000000000000000000000000000000000000000000000000000000000815222e3b4855616e7b8895a0a0a0988b7e7165584b3e3225180b000000000000060c11141617171717171717171614110c070000000000000000000002080e12151617171717171717171614100b0500000000000000000000000000000000000000000000000003090f14181c20232527292b2c2c2c2c2c2b2a282623201d1915100b050000000000000000000000000000000000000000000000000000000000000915202c3844505c6773808b97a3afb7b1a5998d82756a5e52463a2e22160a0000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000000000006121d28333e48535d68727b858e969ea6a7a09a95918d8b8a8a8a8b8d91959aa0a7a59d958d847a71675d52483d32271c1106000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121e29343f4a56616c778284796d62574c41352a1f14090000000000000000000000000000020d18232e39434e58626c768089929ba3ababa39b948d86817b76726f6c6a686766666667686a6c6f73777b81868d949ba3aba79f978e857b72685e54493f342a1f1409000000000000101c2935414c576066676767676767676767635b5045392d21160a00000000000000000000000000000000000000000008141f2b37434e59616767676767676767676661574d4135291d110400131f2c3945525e6b757f888888888888837a70665d53493f352b21170c020000000000000000000000000000000000000000000000000000000c1926323f4c5965727f8c999c8f8276695c4f4336291c100300000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a2527292b2c2d2d2d2d2c2b292623201c18130d0701000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d000000000008121c263039424b545c636a71777c8185888b8e9091929293939291908e8b8985817c77716a635c534b42392f251b1006000000000000000000000000000000000000000000000000000000000000000000000000000000000815222e3b4855616e7b8893939393938b7e7165584b3e3225180b00000000010a11181d2123232323232323232323211d18110a0200000000000000040c13191e2123232323232323232322201c160f080000000000000000000000000000000000000000000000000003080c101316191b1d1e1f1f201f1f1e1d1b191714110d090400000000000000000000000000000000000000000000000000000000000000020e1925313d4955606c7884909ca8adaaabaa9e92867a6e62564a3f33271b0f0300000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000000000010c18232e39444f5a656f79848d97a0a8a49c958f8984817e7d7d7d7e8184898f959da5a79f968c83796f645a4f44392e23170c0000000000000000000000000000000000000000000000000000000306070707070707070707070603000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010304050607070707060504030100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c18232e39444f5b66717c7e72675c51463a2f24190e02000000000000000000000000000008141f2a35404a55606a747e88929ba4adaaa1999189827b756f6a66625f5d5b5a59595a5a5c5d6063666b70757b82899199a1aaa9a0978d847a70665b51463b31261a0f040000000000121f2b3844515d69727474747474747474746c61564a3e32261a0e0300000000000000000000000000000000000000000c1824303c48545f6b73747474747474747472695e5245392c1f130600111e2a36424e59636d77818a949494948c82786f655b51473d33291e14090000000000000000000000000000000000000000000000000000000d192633404c596673808c999c908376695c4f4336291d100300000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372e31343638393a3a3a3a39373533302c28231e18120c050000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d0000000000000a141e273039424a52595f666b7075797c7e81838485868686858483817f7c7975706b665f59514a413930271d130900000000000000000000000000000000000000000000000000000000000000000000000000000000000815222e3b4855616e7b868686868686867e7165584b3e3225180b000000010a131b23292d2f3030303030303030302d29231c140b010000000000040d161e252a2e3030303030303030302f2c27211a110800000000000000000000000000000000000000000000000000000004070a0c0e1011121313131212100f0d0a08040100000000000000000000000000000000000000000000000000000000000000000006121e2a36424d5965717d8995a0a9a19d9fa5a2968b7e73675b4f43372b1f140800000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201309090909090909090909090909090909090909090909090908070401000000000000000000000006121d29343f4b56616c76818b969fa9a49b928b837d7874727070707274787d848b939ba4a89f958b81766b60554a3f34281d1106000000000000000000000000000000000000000000000000060b0f1214141414141414141414120f0b060000000000000000000000000000000000000000000000000000000000000000000000000000000000000206090b0d0f111213131414131312110f0d0b0906020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111d28333e4955606b76776c61564b4034291e13080000000000000000000000000000030e1925303b46515c67717c86909aa4adaba1988f877f77706a645f5a5653514f4d4d4d4d4e4f5153575a5f646a70777f878f98a1aba99f968c82776d62584d42372c21150a0000000000131f2c3946525f6c7981818181818181817e72665a4e42372b1f13070000000000000000000000000000000000000005111d2935404c5864707c8181818181818181796d6053463a2d201307000e1a26323d48515b656e78828c96a09e948a81776d63594f453a30261b110600000000000000000000000000000000000000000000000000000d192633404c596673808c999d908376695d5043362a1d100300000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044373a3d40424446464747464544423f3c38342f2a241d160f0700000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d000000000000020c151e27303840474e545a6064696c6f72747677787979797978767572706c6964605a544e47403830271e150b0100000000000000000000000000000000000000000000000000000000000000000000000000000000000815212e3b4854616d7779797979797979797064574b3e3125180b00000008121c252d34393c3d3d3d3d3d3d3d3d3c39342e261d130900000000010b161f2830363a3d3d3d3d3d3d3d3d3d3c38332c231a1006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17232f3a46525e6a76828d99a5a19791939ca69b8f83776b5f54483c3024180c00000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20151515151515151515151515151515151515151515151515151514110c07000000000000000000000b17222e3a45515c67727d88939da7a59b92898079726c686564636365686d72798189929ca6a79d92887d72675c5045392e22170b00000000000000000000000000000000000000000000020a11171c1f202020202020202020201f1b17110a020000000000000000000000000000000000000000000000000000000000000000000000000002070b0f1215181a1c1d1f2020202020201f1e1c1a1815120f0b070200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17222d38434f5a646b6b655b50453a2e23180d02000000000000000000000000000008141f2b36414d58636e78838e98a2acaca2998f867d756d655f58534e4a47444241404040414244474a4e53595f656d757d868f99a2aca89e94897f74695e53483d32261b100400000000121e2b3844505d6874808c8e8e8e8e8e8e83776b5f53473b2f24180c000000000000000000000000000000000000000a16212d3945515d6975818c8e8e8e8e8e8d8175695d5145382c1f1306000a15212b363f49535c66707a848e99a39c93897f756b61564c42372d22180d02000000000000000000000000000000000000000000000000000d1a2633404d596673808d9a9d9083766a5d5043372a1d100400000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d504442464a4d4f51525353535352504e4c4844403b352f2821191109000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d00000000000000030c151e262e353c43494f54585c60636668696b6c6c6c6c6c6b6a686663605d58544f49433c352e261e150c030000000000000000000000000000000000000000000000000000000000000000000000000000000000000713202c3845515c666c6c6c6c6c6c6c6c6c685e53483c2f23160a0000030f1a242e373f45494a4a4a4a4a4a4a4a49453f382f251a0f0400000007121d27313a4146494a4a4a4a4a4a4a4a48443d352c22170c01000000000000000407080808080808080807050100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101c27333f4b57636e7a86929ea89c90858a96a2a094887c7064584c4034291d1105000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c222222222222222222222222222222222222222222222222222222201d18120b030000000000000004101c27333f4b56626d78848f9aa4a99e948980766e67615c59575657595c61676f77808a949ea9a4998e83786d61564a3f33271c10040000000000000000000000000000000000000000020c141c23282b2d2d2d2d2d2d2d2d2d2d2b27221c140b020000000000000000000000000000000000000000000000000000000000000000000004090e13171b1e222427282a2b2c2d2d2d2d2c2b2a292724211e1b17130e090300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005101c27323d48525a5f5f5b53493f33281d12070000000000000000000000000000010d1925303c47535e69747f8a959faaafa49a90877d746b635b544d47423e3a3735343333333436383b3e42474d545b636b747d87909ba5afa59b90867b70655a4e43372c20150900000000101c2834404c58646f7b87939a9a9a9a93877b6f64584c4034281c11050000000000000000000000000000000000020e1a26323e4a56616d7985919a9a9a9a94887c7064584d4135291d100400040f1a242d37414a545e68727c87919ba59b91877d72685e54493f34291f1409000000000000000000000000000000000000000000000000000d1a2734404d5a6773808d9a9d9084776a5d5044372a1d110400000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d50494e5256595c5e5f606060605f5d5b5854504b46403a332b231b12090000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d0000000000000000030c141c242b32383e43484c505457595b5d5e5f5f5f5f5f5e5d5b595754504c48433e38312b231c140c030000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101c28343f4a545b5f5f5f5f5f5f5f5f5f5c564d42372b1f130700000814202b3640495155565656565656565655514a41372c2115090000000c18232f39434c52565656565656565656544f473e34291d12060000000000060c1013151515151515151514110d0801000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000914202c3844505c67737f8b97a3a4988c8086929ea4988c8175695d5145392d211509000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2d29231d150c030000000000000814202c3844505b67737e8a95a0aba2978c82776e655c55504c4a4a4a4c50565d656e78828d98a3aba095897e72675b5044382c20140800000000000000000000000000000000000000000a141e262e34383a3a3a3a3a3a3a3a3a3a38332d261d140a000000000000000000000000000000000000000000000000000000000000000003090f151a1f23272b2e3133353738393a3a3a3a3938373533312e2b27231e1a140f090200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a16212c3640484f52524f4941372d22170c01000000000000000000000000000006121e2a35414d58646f7a86919ca6b1a89d93887e756b62595149423c36322e2b292727262728292b2e32373c42495159626b757e89939ea8ada2978c81766b5f54493d31261a0e020000000c18242f3b47535f6b76828e9aa6a7a4988c8074685c5145392d211509000000000000000000000000000000000007131f2b37424e5a66727e8a96a2a7a79b8f83776b5f54483c3024180d00000008121b252f39424c56606b757f8a949ea3998f847a70655b50463b30261b10050000000000000000000000000000000000000000000000000d1a2734404d5a6773818d9a9d9184776a5d5144372a1e110400000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d50555a5e6266686a6c6d6d6d6c6b6a6764615c57514b443d352d241b120900000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d000000000000000000020a121920272d32373c4044474a4d4f5051525353535251504f4d4a4744403c37322d262019120a020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c18232e38424a4f525353535353535353504b443b30261a0f0300000c1825313c48525b616363636363636363625c53483d3125190d010004101c2834404b555e626363636363636363605950453a2e221609000000020a11181c202122222222222222201d19130c040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020d1925313d4954606c7884909ca7a094887c818d99a59d9185796d61554a3e32261a0e020000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f53463c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3b39352e271e140a0000000000000c1824303c4854606c78848f9ba6a89c91867b70665c534b44403d3d3d40444b535c66707b86919da8a69a8f84786c6054483c3024180c0000000000000000000000000000000000000006111c2630383f4447474747474747474746443f382f261c1106000000000000000000000000000000000000000000000000000000000000070e141b20262b2f33373a3d40424345464647474646454442403d3a37332f2a25201a140d0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040f1a242e363d434646433e372f261b11060000000000000000000000000000000b17232e3a46525e6975808c97a2adaca1968b81766c635950473f38312b26221e1c1b1a1a1a1b1d1f22262b31383f475059636d77818c97a2ada99e93877c7065594e42362a1f130700000007131f2b37424e5a66727d8995a1ada89c9185796d6155493d32261a0e02000000000000000000000000000000000c18232f3b47535f6b77838e9aa6aea2968a7e72675b4f43372b2014080000000009131d27303a444f59636d78828d97a2a0968c82776d62574d42372c21160b0000000000000000000000000000000000000000000000000e1a2734414d5a6774818e9a9e9184776a5d5144372b1e110400000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5a60666a6e72757778797a7a79787674716d68635d564f473f372e241b1107000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d0000000000000000000000070e151b21272c3034383b3e404243454546464646454442403e3b3834302c27211b150e07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c262f383f4346464646464646464644403a32291f14090000000f1b2834414d59646d70707070707070706d655a4e4235291c0f030006131f2c3845515c676f70707070707070706b62564a3e3225180c0000020b141c23282c2e2e2e2e2e2e2e2e2d29241e160d040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121e2a36414d5965717d8994a0a89c9084787d8995a1a1968a7e72665a4e42362a1e13070000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5348484848484848484848484848484848484848484848484848484848484845403930261c11060000000004101c2834404d5965717d8994a0aca3978b8074695e544a4139343130313439414a545f6a75808c97a3aba094897d7165594d4135281c10040000000000000000000000000000000000000c17232e38424a5053535353535353535353504941382d22170b00000000000000000000000000000000000000000000000000000000020a11191f262c31363b3f43474a4c4e505152535353535352504e4c4a47433f3b36312b251f1811090200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008121c242c3236393937332d251d140a000000000000000000000000000000030f1b27333f4b57636e7a86919da8b1a69a8f847a6f655a51473e352d261f1a1612100e0d0d0d0e1012161a20262d353e47515b65707a85909ca7afa4998d82766a5e53473b2f23170b000000020e1a26323d4955616d7884909ca8ada195897d72665a4e42362a1f130700000000000000000000000000000004101c2834404c58636f7b87939faba99d9185796e62564a3e32271b0f0300000000010b151f29333d47515c66707b86909ba69e93897e74695e54493e33281d120700000000000000000000000000000000000000000000000e1b2834414e5a6774818e9a9e9184776b5e5144382b1e110500000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5e656b71767b7e818485868787868583807d78746e686159514940372d23190f050000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d000000000000000000000000040a10161b2024282b2f3133353738393939393938373534312f2c2824201b16100a03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a141d262d333739393939393939393938342f2820170d02000000101c2936434f5c69757d7d7d7d7d7d7d7d766a5d5043372a1d1004000714202d3a4753606d797d7d7d7d7d7d7d7d7366594d4033261a0d00000a141d262e34383b3b3b3b3b3b3b3b39352f281f160c020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17232f3a46525e6a76828d99a5a4988c80747985919da69a8e82766a5f53473b2f23170b0000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f55555555555555555555555555555555555555555555555555555555555555514b42382e23170b000000000713202c3844515d6975818d99a5aa9e92867a6f63584d42382f28242324282f38434d58646f7b87929eaaa5998d8175695d5145382c201407000000000000000000000000000000000004101c28343f4a545c606060606060606060605b53493f33271b0f030000000000000000000000000000000000000000000000000000040c141c232a31373d42474b4f5356595b5d5e5f606060605f5e5d5b5956534f4b47423c363029231b130b030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a121a21262a2c2c2a27221b130b0200000000000000000000000000000007131f2b37434f5b67737f8b97a2aeaba095897e73685d53493f352c231b140e090603000000000003060a0e141b232c353f49535e69747f8a96a1adaa9e92877b6f63574b3f33271b0f030000000915212d3944505c6874808b97a3afa69a8e82766a5f53473b2f23170b0000000000000000000000000000000915212d3944505c6874808c98a4afa4988c8175695d51453a2e22160a000000000000030d17212b353f4a545f69747f8a949fa59b90867b70655a4f44392e23180d01000000000000000000000000000000000000000000000e1b2834414e5b6774818e9b9e9184786b5e5145382b1e120500000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a6870767d82878b8e909293949393918f8d89857f79726b635b52493f352b21160c0100000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d0000000000000000000000000000050a0f14181c1f222527292a2b2c2c2c2c2c2b2a292725221f1c18140f0a05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141c22272b2c2c2c2c2c2c2c2c2c2b28231d160e0500000000101c2936434f5c6976838a8a8a8a8a8a84776a5d5044372a1d1104000714202d3a4753606d7a878a8a8a8a8a8a807366594d4033261a0d0006111c262f383f45484848484848484846413a31281e1309000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101c27333f4b57636e7a86929eaaa094887c7074818d99a59f93877b6f63574b3f34281c100400000000000000000000000013202c3946535f6c798693a0acaca09386796c62626262626262626262626262626262626262626262626262626262626262615c544a3f34281c0f030000000a17232f3c4854606d7985919da9a69a8e82766a5e52473b30261d1817181d26313c47535e6a76828e9aa6a99d9185796d6154483c3023170b000000000000000000000000000000000006131f2c3845505c666c6d6d6d6d6d6d6d6d6c655b5044382b1f120600000000000000000000000000000000000000000000000000040d161e262e353c42484e53585c5f626567696b6c6d6d6d6d6c6b696865625f5b57524d48423b342d251d150d040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000810161a1e1f201e1b16100901000000000000000000000000000000000a16232f3b47535f6c7884909ba7b2a69b8f84786d61564c41372d231a110a030000000000000000000000030a111a232d37424c57636e7985919ca8afa3978c8074685c4f43372b1f130600000005101c2834404b57636f7b87929eaaaa9f93877b6f63574b4034281c100400000000000000000000000000020e1a25313d4955616d7985919ca8ab9f94887c7064584c4135291d110500000000000000050f19232e38434d58626d78838e99a4a2978c82776c61564b4034291e1307000000000000000000000000000000000000000000000f1b2835424e5b6875818e9b9e9285786b5e5145382b1e120500000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a727a81888e93979a9d9ea0a0a09f9e9c9995908b847d756d645b51473d33281d120700000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d0000000000000000000000000000000003080c0f1316181a1c1d1e1f2020201f1f1e1c1a181613100c0803000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a11171b1e2020202020202020201f1c18120c040000000000101c2936434f5c69768390969696969084776a5d5044372a1d1104000714202d3a4753606d7a8794969696968d807366594d4033261a0d000b17222d38424a515455555555555555524c433a30251a0f04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000914202c3844505c67737f8b97a3a89c9084786c707c8894a0a3978b8074685c5044382c20140900000000000000000000000013202c3946535f6c798693a0acaca09386796f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6d665c5044382b1f12050000000d1a26323f4b5764707c8995a1ada2968a7e7165594d41362a1f140b0a0b151f2b36424e5a66727e8a96a3aea195897d7064584b3f33261a0e01000000000000000000000000000000000814212e3b4754606d787a7a7a7a7a7a7a7a776c6053463a2d201407000000000000000000000000000000000000000000000000040d161f2830383f474d54595f63686c6f7274767779797a7a7979787674726f6b67635e59534d463f372f271f160d03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0e111313110f0a050000000000000000000000000000000000010d1a26323f4b57636f7c8894a0acaea2968a7e72675b50453a2f251b110800000000000000000000000000000008111b25303b46515d6874808c98a4b0a89c9084786c5f53473b2f22160a000000000c17232f3b47525e6a76828e99a5afa3978c8074685c5044382d21150a0a0a0a0a0a0a0a0a0a0a0a0a0a0a121e2a36424e5a65717d8995a1ada69b8f83776b5f54483c3024180d01000000000000000007111c26313b46515c66717c88939ea99e93887d72675c51463a2f24180d010000000000000000000000000000000000000000000f1b2835424e5b6875828e9b9f9285786b5f5245382c1f120500000000000000000000000000000000101c2936434f5c697683909ca9aa9d908477727b848c93999f9d9b9a9a9a9a9c9fa2a7a5a19c968f877f766d63594f443a2f24190e02000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d000000000000000000000000000000000000000306090c0e0f111212131313131211100e0c0907030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060b0f1213131313131313131312100c0701000000000000101c2936434f5c697683909ca3a39d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0a3a39a8d807366594d4033261a0d000f1b27333f4a545c61616161616161615d564c41362c21160b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010d1925313d4854606c7884909ca7a4988c8073676c7884909ca89c9084786c6054493d3125190d01000000000000000000000013202c3946535f6c798693a0acaca093867b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b786c605346392d201307000003101c2935424e5b6773808c98a5ac9f93877a6e6255493d3125190e0200030e1a25313d4956626e7a87939faca5998c8074675b4f4236291d1004000000000000000000000000000000000815212e3b4854616e7b87878787878787877a6d6053473a2d2014070000000000000000000000000000000000000000000000020c161f28313a424a51585f656a6f74787b7e8183848586868786868483817e7b78736f6a645e575049413931281f160c02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101d2936424e5b6773808c98a4b0a99d9185796d62564a3f34291e1309000000000000000000000000000000000009141e2a35404c58636f7b8794a0acaca094887c6f63574a3e3225190d0000000007131e2a36424e5965717d8995a0aca89c9084786d6155493d31251917171717171717171717171717171717232f3b47525e6a76828e9aa6ada2968a7e72665b4f43372b1f1408000000000000000000000a151f2a343f4a55606b76818d98a3a59a8f84786d62574c4035291e12070000000000000000000000000000000000000000000f1c2835424f5b6875828f9c9f9285786b5f5245392c1f120600000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084777b848d969d9894918f8d8d8d8e8f92969ba1a8a7a09991887e756b61564b40352a1f1308000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00121e2b37434f5b666d6e6e6e6e6e6e6e685e53483d32281d1207000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121e2a36414d5965717d8994a0aca094887b6f636874808c98a4a195897d7165594d4135291e1206000000000000000000000013202c3946535f6c798693a0acada1958b888888888888888888888888888888888888888888888888888888888888888886796d6053463a2d201307000006121f2b3844515d6a76838f9ca8a99c9084776b5e5246392d2115090000000915212d3a46525e6b7784909ca9a89c9083776a5e5145382c1f1306000000000000000000000000000000000815212e3b4854616e7b88949494949494877a6d6053473a2d20140700000000000000000000000000000000000000000000000a141e28313a434c545c636a70767b8084888b8d8f91929393939392918f8d8b8784807b756f69625b534b433a31281e140a00000000000000000000000000040708090909090909090909090909090909090909090909090909090909090909090909090909090909090909080704000000000000000000000713202c3845515e6a76838f9ca8b2a6998d8175695d5145392e22170c010000000000000000000000000000000000020d18242f3b47535f6b7784909ca8b0a4988b7f73665a4e4135281c0f03000000020e1a25313d4955606c7884909ca7ada195897d7165594e42362a232323232323232323232323232323232328333f4b57636f7b87929eaaa99d9185796d62564a3e32271b0f0300000000000000000000030d18232e39444f5a65707b87929da9a0958a7e73685d51463a2f23180c0000000000000000000000000000000000000000000f1c2936424f5c6875828f9c9f9286796c5f5246392c1f130600000000000000000000000000000000101c2936434f5c697683909ca9aa9d908378838d9697918c8884828180808183868a8f969da5aba39a91877d72685d52473b3024190d010000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002070b0d0f0e0c09050000000000000000000001060a0d0e0e0d0a06010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d0013202c3946525f6c777b7b7b7b7b7b7a6f645a4f44392e23190e03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17232e3a46525e6a75818d99a5a89b9083776b5f636f7b8894a0a5998d81756a5e52463a2e22160a000000000000000000000013202c3946535f6c798693a0acb1a69d96959595959595959595959595959595959595959595959595959595959595959386796d6053463a2d20130700000814212e3a4753606c7985929eaba69a8d8174685b4f42362a1d110500000005111e2a36434f5b6874818d9aa6ab9f9286796d6054473b2e221509000000000000000000000000000000000815212e3b4854616e7b8894a0a0a0a094877a6d6053473a2d2014070000000000000000000000000000000000000000000007111c26303a434d555e666d747b81878c9094979a9c9e9fa0a0a0a09f9e9c9a9794908b86817a746d655d554c433a30261c120700000000000000000000070c1114151515151515151515151515151515151515151515151515151515151515151515151515151515151515151513100b0500000000000000000916222f3b4854616d7986929fabafa2968a7d7165594d4135291d11060000000000000000000000000000000000000007131f2b37434f5b6774808c99a5b2a79b8f8276695d5044372b1e1205000000000915212c3844505c67737f8b97a3aea59a8e82766a5e52463b303030303030303030303030303030303030303844505c6873808b97a3afa4988c8175695d5145392e22160a00000000000000000000000007111c27323d48535f6a75818c98a3a69b9085796e62574b4034281d110500000000000000000000000000000000000000000f1c2936424f5c6975828f9c9f9286796c5f5346392c20130600000000000000000000000000000000101c2936434f5c697683909ca9a99c90837f8a94948d86807b787574737374767a7e848b939ca5aca3998f84796e63584c41352a1e12060000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004090e13171a1b1b1915110b0300000000000000050c1216191b1b1a16120d0803000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00131f2c3945525e6b7681888888888881766b60564b40352a1f150a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101b27333f4b57636e7a86929eaaa3978b7f73675b5f6b7784909ca89e92867a6e62564a3f33271b0f030000000000000000000013202c3946535f6c798693a0acb8afa7a3a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a09386796d6053463a2d20130700000a1623303c4955626f7b8894a1ada4988b7e7265594c4033271a0e01000000020e1a2733404c5965727e8b98a4aea195887c6f6356493d3024170b000000000000000000000000000000000815212e3b4854616e7b8894a1adada094877a6d6053473a2d201407000000000000000000000000000000000000000000030e19232e38424c555f6770787f868d92989ca0a3a6a9aaa9a8a8a8a8a9aaa9a6a3a09c97928c867e776f675e554c42382e24190f0400000000000000020b12181d2022222222222222222222222222222222222222222222222222222222222222222222222222222222222222221f1c171009010000000000000b1824313d4a5763707c8995a2aeac9f93877a6e6155493d3024180c0100000000000000000000000000000000000000020e1b27333f4b5864717d8a96a3afaa9e9185786c5f53463a2d2114070000000004101c28333f4b57636e7a86929ea9aa9e92867a6f63574b3f3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d4954606c7884909ca8ab9f93887c7064584c4035291d1105000000000000000000000000000b16212c37424e5964707b87929eaaa1968a7f73685c5145392d22160a0000000000000000000000000000000000000000101c2936434f5c6976838f9ca09386796c5f5346392c20130600000000000000000000000000000000101c2936434f5c697683909ca9a89b8f828590948a827b756f6c69676666686a6e7379818a939da8aba0968b8074695d52463a2e22170a0000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d00000000000000000000000000000000000000000000000000000000000000000000000000000000000001060b10151a1f2427282825211c150e050000000000070f171d2226282826221e19140f0a0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00111d2a36424e59646f7a858f959592887d72675c51473c31261b110600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000814202c3844505b67737f8b97a3ab9f93877b6f63575b6773808b97a4a2968b7e73675b4f43372b1f14080000000000000000000013202c3946535f6c798693a0acb9b1aaa6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a09386796d6053463a2d20130700000c1825313e4b5764717d8a96a3afa296897c7063574a3e3124180b00000000000b1824313d4a5763707c8996a2afa4978b7e7165584b3f3226190c000000000000000000000000000000000815212e3b4854616e7b8894a1aeada094877a6d6053473a2d20140700000000000000000000000000000000000000000009141f2a353f4a545e677179828a91989ea3a8aca7a4a19e9d9c9b9b9c9d9ea1a4a7aca8a39d979089817970675e544a40352b20150a000000000000020c141c23292d2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2e2c28221b130a0000000000000d1a26333f4c5965727e8b98a4b1a99d9084776b5e5245392d2014080000000000000000000000000000000000000000000b1723303c4855616e7a8794a0adada094877b6e6255483c2f23160900000000000b17232f3a46525e6a75818d99a5afa3978b7f73675c504a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4d5965717d8995a0aca69a8f83776b5f53483c3024180c0100000000000000000000000000040f1b26313c48535f6a76828d99a5a79b9084796d61564a3e32261b0f0300000000000000000000000000000000000000101d293643505c697683909ca09386796d6053463a2d20130700000000000000000000000000000000101c2936434f5c697683909ca9a99c91888b958b81787069645f5c5a595a5b5e62686f78818b96a1aca79c91857a6e62574b3f33271b0e0200000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d0000000000000000000000000000000000000000000000000000000000000000000000000000000003080d12171c21262b30333534322d271f170e0400000006101921282e323535322e2925201b16110c070200000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d000e1a26323d48525d68737e89939e998e84796e63584d43382d22170c02000000000000000000000000000000000000000000000000000000000000000000000000000000000000010d1925313d4854606c7884909ba7a79b8f83776b5f5357636f7b87939fa79b8f83776b5f54483c3024180c0000000000000000000013202c3946535f6c798693a0acb3a89f9a999999999999999999999999999999999999999999999999999999999999999386796d6053463a2d20130700000d1a2633404c5966727f8c98a5ada194877b6e6155483c2f22160900000000000916222f3b4855616e7b8794a1ada6998c8073665a4d4134271b0e010000000000000000000000000000000815212e3b4854616e7b8894a1a4a4a094877a6d6053473a2d2014070000000000000000000000000000000000000000030e1a25313c47515c667079838b949ba3a9aca5a09b979492908f8f8f8f909294989ba0a6aca8a29b938b82796f665c52473c32271c100500000000000a141e262e34393b3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3b38332d251c120800000000000f1b2835414e5a6774818d9aa6b3a79b8e8275685c4f43362a1d11050000000000000000000000000000000000000000000814202d3946535f6c7885919eabafa396897d7063574a3e3124180b000000000006121e2a36414d5965717c8894a0aca79c9084786c6056565656565656565656565656565656565656565656565e6a75828d99a5ada2968a7e72665a4f43372b1f14080000000000000000000000000000000914202b37424e5965717c8894a0aca1958a7e72665b4f43372b1f130700000000000000000000000000000000000000101d2a3643505d697683909da09386796d6053473a2d20140700000000000000000000000000000000101c2936434f5c697683909ca9ada29a95968e83796f665f5853504e4d4d4e51565d666f79848f9aa6ada2968b7f73675b4f43372b1e120600000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d0000000000000000000000000000000000000000000000000000000000000000000000000000050a0f14191e23282d31363b4041413e38312920160b0000020d18222b333a3f41413f3a35302b26221d18130e09040000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d000915202b36414c57616c77828d97a0958a80756a5f54493e34291e130800000000000000000000000000000000000000000000000000000000000000000000000000000000000006121e2a35414d5965717c8894a0aca2968a7e72665a4e535f6b77838f9ba7a094887c7064584c4034291d110500000000000000000013202c3946535f6c798693a0acaea2978e8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c86796d6053463a2d20130700000e1b2835414e5b6774818d9aa7ac9f9386796d6053473a2d21140700000000000714202d3a4653606c7986929faca79b8e8275685b4f4235291c0f030000000000000000000000000000000815212e3b4854616e7b88949898989894877a6d6053473a2d201407000000000000000000000000000000000000000008141f2b36424d58636d78828c959da6ada8a19a948f8b888584828282828485888b8f949aa1a8aca59d948b82786e63594e43382d22160b0000000006111c26303840454848484848484848484848484848484848484848484848484848484848484848484848484848484848484848443e372e24190e0300000000101d2936434f5c6975828f9ba8b2a5998c8073665a4d4034271b0e0200000000000000000000000000000000000000000005121e2b3744515d6a7683909ca9b1a4988b7e7265584c3f3226190c0000000000020d1925313d4854606c78848f9ba7aca094897d71656363636363636363636363636363636363636363636363636e7a86929eaaa99d9185796d62564a3e32261b0f03000000000000000000000000000000030f1a26313d4854606c77838f9ba7a69a8f83776b5f53473b2f23170b00000000000000000000000000000000000000111d2a3744505d6a7683909da094877a6d6053473a2d20140700000000000000000000000000000000101c2936434f5c697683909ca9b4aba59f93887c72675d544d474341404042454c545d68737e8a95a1ada79b8f84776b5f53473b2e22160900000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d000000000000000000000000000000000000000000000000000000000000000000000002070c11161b20252a2e33383d42474c4e4d4a433b32271d11060008141f2a343d454b4e4e4b46413c37322d28231f1a15100b06010000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00040f1a252f3a45505b65707b86919c9c91867b71665b50453a30251a0f0400000000000000000000000000000000000000000000000000000000000000000000000000000000000b17222e3a46525e6a75818d99a5a99d92867a6e62564a4f5b67737f8b97a3a4988c8175695d5145392d21150900000000000000000013202c3946535f6c798693a0acaca093867f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f796d6053463a2d2013070000101c2936424f5c6975828f9ba8ab9e9285786b5f5245392c1f1206000000000006121f2c3845525e6b7884919eaba99c908376695d5043372a1d11040000000000000000000000000000000815212e3b4854616e7b888b8b8b8b8b8b877a6d6053473a2d20140700000000000000000000000000000000000000000c1824303c47535e69747f8a949ea7afa69e968f89847f7b79777575757577797b7f84898f969ea6afa69d948a80756a6055493e33271c10040000000b17222d38424a515555555555555555555555555555555555555555555555555555555555555555555555555555555555555554504940362b20140800000000111e2a3744515d6a7783909da9b1a4978b7e7165584b3f3225190c0000000000000000000000000000000000000000000002101c2936424f5c6875828e9ba8b3a6998c8073665a4d4034271a0d0000000000000814202c38444f5b67737e8a96a2aea5998d817570707070707070707070707070707070707070707070707070737f8b97a2aea4988c8175695d5145392d22160a00000000000000000000000000000000000915202c38434f5b67737f8b97a3ab9f93887b7064584c4034271b0f03000000000000000000000000000000000000111d2a3744505d6a7784909da094877a6d6154473a2e21140700000000000000000000000000000000101c2936434f5c697683909ca9b6b2a59a8e82766b60554b423c37343334353a424c56616d7985919da9aca094887b6f63564a3e3125190c00000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d00000000000000000000000000000000000000000000000000000000000000000004090e13181d22272b30353a3f44494e53585b5a554d44392e22160a000d1925303b464f565a5b57524d48433e39342f2a25201c17120d0803000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d000008131e29333e49545f69747f8a95a0988d82776c62574c41362c21160b0000000000000000000000000000000000000000000000000000000000000000000000000000000004101b27333f4b57626e7a86929eaaa5998d8175695d51454a57636f7b87939fa99d9185796d6155493e32261a0e02000000000000000013202c3946535f6c798693a0acaca0938679727272727272727272727272727272727272727272727272727272727272727271685d5145382c1f13060000111d2a3743505d6a7683909da9aa9d9084776a5d5144372b1e1105000000000004111e2a3744515d6a7784909daaaa9d9184776b5e5144382b1e12050000000000000000000000000000000815212e3b4754616e7a7e7e7e7e7e7e7e7e796d6053473a2d2014070000000000000000000000000000000000000004101d2935414d58646f7b86919ca6afa79d948c847d78736f6c6a696868696a6c6f73787e848c949da6afa69c91877c71665b4f44382c2115090000000f1b27333f4a545c61626262626262626262626262626262626262626262626262626262626262626262626262626262626262605a52473c3125190c00000000121f2b3845515e6b7884919eabb0a3968a7d7063574a3d3024170a00000000000000000000000000000000000000000000000e1b2834414e5a6774818d9aa7b4a79a8e8174675b4e4134281b0e000000000000040f1b27333f4a56626e7a86919da9aa9e92867d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d848f9ba7ab9f93877b7064584c4035291d11050000000000000000000000000000000000040f1b27333f4a56626e7a86939faba4988c8074685c5044382b1f1307000000000000000000000000000000000000111e2a3744515d6a7784919da194877a6d6154473b2e21140800000000000000000000000000000000101c2936434f5c697683909ca9b6aea195897d71655a4f4439312b28272729303a45505c6874818c99a5b0a4978b7e72665a4d4134281b0f02000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d00000000000000000000000000000000000000000000000000000000000001060b10151a1f23282d32373c41464b50555a5f6468665f554a3f33261a0e00101d2935414d58616767625d59544f4a45403b36312c27221d18140f0a0500000000000000000000000000000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d0000010c17222d37424d58636e78838e999f94897e73685e53483d32271d12070000000000000000000000000000000000000000000000000000000000000000000000000000000814202c38444f5b67737f8b97a2aca094897c7165594d4146525e6a77838f9ba7a1968a7e72665a4e42362a1e1307000000000000000013202c3946535f6c798693a0acaca09386796c65656565656565656565656565656565656565656565656565656565656565655f564c4135291d10040000121e2b3844515e6b7784919eaaa99c908376695d5043362a1d1004000000000000101d293643505c6976838f9ca9ab9e9285786b5f5245392c1f12060000000000000000000000000000000714202d3946525e6970717171717171717170685d5145382c1f1306000000000000000000000000000000000000000814202d3945515d6975818c97a2ada99f958b827a736c6763605d5c5b5b5c5d6063676c737a828a949da7aea3988e82776c6055493d3125190d010000121e2b3743505b666d6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6c64594d4134281b0f00000000121f2c3945525f6b7885929fabafa295897c6f6256493c2f23160900000000000000000000000000000000000000000000000d1a2733404d596673808d99a6b3a89b8e8275685b4f4235281c0f000000000000000b16222e3a46525d6975818d98a4aea2978d8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8b94a0aca69a8f83776b5f53473c3024180c000000000000000000000000000000000000000b16222e3a46525e6a76828e9ba7a89c9084786c6054473b2f23170a000000000000000000000000000000000000111e2b3744515e6a7784919ea194887b6e6154483b2e21150800000000000000000000000000000000101c2936434f5c697683909ca9b6aa9e9285796d6155493d32271f1b1a1a1e2834404c5864707d8995a2aea79b8e8275695c5043372a1e1105000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d0000000000000000000000000000000000000000000000000000000003080d12171c20252a2f34393e43484d52575c61656a6f7471675b4f4236291c1000121f2c3845515e6973736e69645f5a55514c47423d38332e29241f1a15100c070200000000000000000000000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00000005101b26313c46515c67727c87929d9a90857a6f64594f44392e23190e0300000000000000000000000000000000000000000000000000000000000000000000000000010d1925313d4854606c78848f9ba7a89c9084786c6054483c424e5a66727e8b97a3a69a8e82766a5f53473b2f23170b000000000000000013202c3946535f6c798693a0acaca09386796c5f59595959595959595959595959595959595959595959595959595959595958544d443a3024180d000000121f2c3845525f6b7885929eaba89c8f8275695c4f4236291c10030000000000000f1c2935424f5b6875828f9ba8ac9f9286796c5f5346392d20130600000000000000000000000000000005111d2a36414c575f646464646464646464645f564c4135291d1004000000000000000000000000000000000000000b1724303c4955616d7985919da9aea2988d83797068615b5753514f4f4f4f5153575b61687078828b95a0abaa9f94887d7165594e4236291d1105000013202c3946525f6c787b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b75695c5043362a1d100000000013202c3946525f6c7986929facaea295887b6f6255483c2f22150900000000000000000000000000000000000000000000000d192633404c596673808c99a6b2a89c8f8275685c4f4236291c0f0000000000000006121d2935414d5864707c88949faba89f98969696969696969696969696969696969696969696969696969696979da6ada1968a7e72665a4f43372b1f13080000000000000000000000000000000000000006121e2a36424e5a66727e8b97a3ada194887c7064574b3f33261a0e010000000000000000000000000000000000111e2b3844515e6b7784919ea194887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c697683909ca9b4a79b8e8275695d5145382d21160f0d0d1824303c4854616d7a86939facaa9e9185786b5f5246392d201307000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d0000000000000000000000000000000000000000000000000000050a0f14181d22272c31363b40454a4f54595d62676c71767b8076695d5043362a1d100013202c3946535f6c797f7a75706b66615c57524e49443f3a35302b26211c17120d09040000000000000000000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d000000000a141f2a35404a55606b76818b96a1968c81766b60554b40352a1f140a0000000000000000000000000000000000000000000000000000000000000000000000000006121e2935414d5965717c8894a0aca3978b8073675c5044383e4a56626e7a86939fab9f93877b6f63574b3f34281c10040000000000000013202c3946535f6c798693a0acaca09386796c5f534c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c49433b32291e1308000000131f2c3946525f6c7986929faca89b8e8275685b4f4235281c0f020000000000000f1b2835424e5b6875818e9ba8ada09386796d6053473a2d201407000000000000000000000000000000010d1925303b454d5457575757575757575757534d443a2f24180d00000000000000000000000000000000000000000d1a26333f4c5865717d8a96a2aea89d91867b71675e56504b47444342424344474b50565e666f79848e99a4b0a5998e82766a5e5246392d211508000013202c3946535f6c7986888888888888888888888888888888888888888888888888888888888888888888888888888888888376695d5043362a1d100000000013202c3946535f6c798693a0acaea295887b6e6155483b2e22150800000000000000000000000000000000000000000000000c1926323f4c5965727f8c99a6b2a99c8f8275695c4f4236291c0f00000000000000010d1924303c48545f6b77838f9ba6b1a9a4a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a4a8afa99d9185796d61564a3e32261a0f0300000000000000000000000000000000000000010d1926323e4a56626f7b8793a0aca4988c8073675b4e4236291d11040000000000000000000000000000000000121e2b3845515e6b7885919ea295887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c697683909ca9b1a5988c7f73665a4d4135281c1004000714202c3945525e6b7784909daaaca093877a6e6154483b2f221509000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d000000000000000000000000000000000000000000000002070c11151a1f24292e33383d42474c51565a5f64696e73787d82878376695d5043362a1d100013202c3946535f6c798686817c77726d68635e59544f4a46413c37322d28231e19140f0a06010000000000000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00000000030e18232e39444e59646f7a858f9a9d92887d72675c51463c31261b10060000000000000000000000000000000000000000000000000000000000000000000000000b17222e3a46525e6975818d99a5aa9f93877b6f63574b3f333a46525e6a76828e9aa6a3978b8074685c5044382c2014080000000000000013202c3946535f6c798693a0acaca09386796c5f53463f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3c38312920170c0200000013202c3946535f6c7986939faca89b8e8275685b4e4235281b0f020000000000000e1b2834414e5b6774818e9ba7ada094877a6d6053473a2d211407000000000000000000000000000000000915202c36404950555555555555555555544e473e33281e130700000000000000000000000000000000000000000f1c2935424e5b6774818d99a6b0a4988c8075695f554c453f3b3836353536383b3f454c545d67727d88939faaaa9e92867a6e6256493d3124180b000013202c3946535f6c7986939595959595959595959595959595959595959595959595959595959595959595959595959595908376695d5043362a1d100000000013202c3946535f6c7986929facaea295887b6e6155483b2f22150800000000000000000000000000000000000000000000000d192633404c5966727f8c99a6b2a89c8f8275695c4f4236291c0f00000000000000000814202b37434f5b66727e8a96a2adb4b1a9a29f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa1a7afb3b0a4988c8074695d5145392d22160a0000000000000000000000000000000000000000000916222e3a46535f6b7784909ca9a89c8f83776a5e5245392d2014070000000000000000000000000000000000121f2b3845515e6b7885929ea295887b6f6255483c2f22150900000000000000000000000000000000101c2936434f5c697683909ca9afa396897d7064574b3e3225190c000004111d2a36434f5c6975828f9ba8afa295897c6f63564a3d3024170a000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d00000000000000000000000000000000000000000004090e12171c21262b30353a3f44494e52575c61666b70757a7f84898e908376695d5043362a1d100013202c3946535f6c7986928d88837e79746f6a65605b56514c48433e39342f2a25201b16110c0703000000000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d000000000007121c27323d48525d68737e89939e998e83786e63584d42382d22170c0100000000000000000000000000000000000000000000000000000000000000000000040f1b27333f4b56626e7a86929ea9a69a8e82766a5e53473b2f36424e5a66727e8a96a2a89c9084786c6054493d3125190d0100000000000013202c3946535f6c798693a0acaca09386796c5f53463932323232323232323232323232323232323232323232323232323232302c2720170e050000000013202c3946535f6c798693a0aca89b8e8174675b4e4134281b0e020000000000000e1a2734414d5a6774818e9aa7aea194877a6d6154473a2e211407000000000000000000000000000000000d1925313d48525b61626262626262626260594f453a2e2216090000000000000000000000000000000000000000111e2a3744505d6a76838f9ca8ada094887b6f64584d433a332e2b292828292b2e333a424b56606b76828e9aa6afa3968a7e7265594c4034271b0e020013202c3946535f6c798693a0a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a29d908376695d5043362a1d1000000000131f2c3946525f6c7986929facafa295887b6f6255493c2f22160900000000000000000000000000000000000000000000000d1a2633404d596673808c99a6b3a89b8f8275685b4f4235281c0f0000000000000000030f1b27323e4a56626d7985919da9b4aba0979292929292929292929292929292929292929292929292959ea8b4ab9f93877b7064584c4035291d110500000000000000000000000000000000000000000006121e2a37434f5b6874818d99a6ab9f93867a6d6155483c2f23160a0000000000000000000000000000000001121f2c3845525f6b7885929fa295887b6f6255493c2f22160900000000000000000000000000000000101c2936434f5c697683909ca9aea194887b6e6255483c2f23160a0000010e1b2834414e5a6773818d9aa6b0a4978a7e7164584b3e3225180c000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d00000000000000000000000000000000000001060a0f14191e23282d32373c41464b4f54595e63686d72777c81868b909599908376695d5043362a1d100013202c3946535f6c79869398938e8a85807b76716c67625d58534e4944403b36312c27221d18130e090400000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d0000000000000b16202b36414c57616c77828d97a0958a80746a5f54493e33291e1308000000000000000000000000000000000000000000000000000000000000000000000814202c38434f5b67737f8b96a2ada1968a7e72665a4e42362a323e4a56626e7a86929eaaa195897d7165594d4135291e120600000000000013202c3946535f6c798693a0acaca09386796c5f5346392c26262626262626262626262626262626262626262626262626262524201b150e05000000000013202c3946535f6c798693a0aca89b8e8174675b4e4134281b0e010000000000000e1a2734414d5a6774818e9aa7aea194877a6d6154473a2e211407000000000000000000000000000000000f1c2835414d59646d6f6f6f6f6f6f6f6f6b61564a3e3225190c0000000000000000000000000000000000000000121f2c3845525e6b7884919eaaaa9d9184786b5f53473c3128221f1d1c1c1d1f2228303a444f5a66717d8a96a2a5a49a8d8175685c4f43362a1d11040013202c3946535f6c7986939e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9d908376695d5043362a1d1000000000121f2c3845525f6b7885929eabafa296897c6f6356493d3023170a00000000000000000000000000000000000000000000000e1b2734414d5a6774818d9aa7b3a79b8e8174685b4e4235281b0f0000000000000000000a16222e3945515d6974808c98a4afa79b8f86868686868686868686868686868686868686868686868c98a4b1a69a8e83776b5f53473c3024180c00000000000000000000000000000000000000000000020e1b2733404c5865717e8a97a3afa296897d7064574b3e3225190c0000000000000000000000000000000004131f2c3945525f6c7885929fa296897c6f6255493c2f22160900000000000000000000000000000000101c2936434f5c697683909ca9aca09386796d6053473a2d2114070000000d1926333f4c5965727f8c98a5b2a5988c7f7266594c3f3326190d000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d0000000000000000000000000000000003070c11161b20252a2f34393e43484c51565b60656a6f74797e83888d92969ba09d908376695d5043362a1d100013202c3946535f6c798693a09f9a95908b87827d78736e69645f5a55504b46413d38332e29241f1a15100b060100000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d000000000000040f1a252f3a45505b65707b86919c9c91867b70665b50453a2f251a0f040000000000000000000000000000000000000000000000000000000000000000010d1925313c4854606c78848f9ba7a99d9185796d6155493d32262d3946525e6a76828e9aa6a5998d8175695e52463a2e22160a00000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2019191919191919191919191919191919191919191919191919191714100a0300000000000013202c3946535f6c798693a0aca89b8e8174675b4e4134281b0e010000000000000e1a2734414d5a6774818e9aa7aea194877a6d6154473a2e21140700000000000000000000000000000000101d2a3743505d69767c7c7c7c7c7c7c7c73665a4d4033271a0d010000000000000000000000000000000000000013202c3946525f6c7986929faca89c8f8276695c5043372b1f1712100f0f1012171e28323d4955616d7a8692999998979084776b5e5245382c1f13060013202c3946535f6c7986929292929292929292929292929292929292929292929292929292929292929292929292929292908376695d5043362a1d1000000000111e2b3844515e6a7784919daab0a3978a7d7164574b3e3125180b00000000000000000000000000000000000000000000020f1c2935424f5b6875828e9ba8b3a69a8d8173675a4d4134271b0e00000000000000000005111d2935404c5864707b87939faba79b8f83797979797979797979797979797979797979797979808c98a4ada1968a7e72665a4e43372b1f130700000000000000000000000000000000000000000000000b1724303d4955626e7b8794a0ada5998c8073665a4d4134281b0f0200000000000000000000000000000006131f2c3946525f6c7986929fa296897c6f6356493c3023160900000000000000000000000000000000101c2936434f5c697683909ca9ab9f9285786c5f5245392c1f13060000000b1825323e4b5864717e8b98a4b1a69a8d8073675a4d4034271a0e000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d000000000000000000000000000004090e13181d22272c31363b4044494e53585d62676c71767b80858a8e93989da2a49f9a908376695d5043362a1d100013202c3946535f6c7986939ba0a5a19c97928d88847e7a75706b66615c57524d48433e3935302b26211c17120d08030000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d0000000000000008131e29333e49545f69747f8a95a0988d82776c61574c41362b21160b000000000000000000000000000000000000000000000000000000000000000006121e2935414d5965707c8894a0aca4988c8175695d5145392d212935414d5966727e8a96a2aa9e92867a6e62564a3f33271b0f03000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0b0804000000000000000013202c3946535f6c798693a0aca89b8e8275685b4e4235281b0f020000000000000e1b2834414e5b6774818e9aa7ada094877a6d6054473a2e21140700000000000000000000000000000000101d2a3643505d6976838989898989898174675a4e4135281c10060000000000000000000000000000000000000013202c3946535f6c798693a0aca89b8e8275685b4e4235281c0f0603000003060c16212d3945515e6a77838e8d8c8b8a8986796d6053473a2d2114070013202c3946535f6c7985858585858585858585858585858585858585858585858585858585858585858585858585858585858376695d5043362a1d1000000000101d2a3743505d6976838f9ca9b1a5988b7e7265594c4033261a0d0100000000000000000000000000000000000000000005111e2a3744505d697683909ca9b2a5988c7f7266594c4033261a0d000000000000000000010c1824303c47535f6b77838e9aa6ab9f93877b706c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6d7884909ca8a89d9185796d61564a3e32261a0f0300000000000000000000000000000000000000000000000814212d3a46535f6c7885919eaba89b8f8275695c5043372a1e11040000000000000000000000000000000613202c3946535f6c7986939fa396897c6f6356493c3023160a00000000000000000000000000000000101c2936434f5c697683909ca9ab9e9184776b5e5145382b1e12050000000b1724313e4a5764707d8a97a4b0a79a8e8174675b4e4134281b0e000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d000000000000000000000001060b10151a1f24292e33383d41464b50555a5f64696e73787d82878b90959a9fa4a29d98938e898376695d5043362a1d100013202c3946535f6c79858a8f94999ea3a39e99948f8a85817b76726d68635e59544f4a45403b36322d28231e19140f0a05000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00000000000000010c17222d37424d58636d78838e999e94897e73685d53483d32271c1207000000000000000000000000000000000000000000000000000000000000000b16222e3a46525d6975818d99a5aca094887c7064584c4034291d25313d4955616d7a86929eaaa2968b7e73675b4f43372b1f1308000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca89b8e8275685b4f4235281c0f020000000000000e1b2835414e5b6874818e9ba8ada093867a6d6053473a2d20140700000000000000000000000000000000101c2936424f5c6875828e969696968f8276695d5044382d22180f0700000000000000000000000000000000000013202c3946535f6c7986929faca89b8e8275685b4e4235281c0f02000000000005101d2936424f5b68758181807f7e7d7d7c786d6054473a2d21140700131f2c3945525e6b7578787878787878787878787878787878787878787878787878787878787878787878787878787878787873685c4f4336291d10000000000f1c2935424f5b6874818e9ba7b3a69a8d8174675b4e4235291c10030000000000000000000000000000000000000000000714202d3946525f6b7885919eaab0a3978a7d7164584b3e3225180c0000000000000000000008131f2b37434e5a66727e8995a1ada4988c8074685f5f5f5f5f5f5f5f5f5f5f5f5f5f5f65717d8995a1ada4988c8074685d5145392d21160a00000000000000000000000000000000000000000000000005121e2b3744505d6976838f9ca8aa9d9184786b5f5245392c20130600000000000004080b0c0c0b0a09080713202d3946535f6c798693a0a3968a7d7063564a3d3023170a08090a0b0c0c0b080500000000000000101c2936434f5c697683909ca9aa9e9184776a5d5144372b1e11040000000a1723303d4a5663707d8a96a3b0a89b8e8275685b4e4235281b0f000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d00000000000000000003080d12171c21262b30353a3e43484d52575c61666b70757a7e84898d92979ca1a5a09b96918c87827d7872675b4f4236291c1000131f2c3945525e6a74797e84898e93989da2a5a09b96918c87827d78736f6a65605b56514c47423d38332f2a25201b16110c0702000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d000000000000000005101b26313b46515c67727c87929d9a8f857a6f64594e44392e23180e030000000000000000000000000000000000000000000000000000000000030f1b27333f4a56626e7a86929ea9a79b8f83776b5f54483c302418212d3945515d6975828e9aa6a79b8f83776b5f54483c3024180c000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000121f2c3845525f6b7885929eaba89c8f8275695c4f4236291c0f030000000000000f1c2835424f5b6875828e9ba8aca09386796c605346392d201307000000000000000000000000000000000e1b2834414e5a6773808c99a2a29e9185796c6155493e342a211911090200000000000000000000000000000000121f2c3945525f6b7885929eaba89c8f8276695c5043372a1e13080000000000010e1a2734404d596570757473727171706f6d665c5145382c1f130600111e2a36424e59636a6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6961574c4034271b0e000000000e1a2734404d5a6673808c99a5b2a89c8f83766a5d5144382b1f13060000000000000000000000000000000000000000000b1723303c4855616e7a8793a0acaea195887c6f6256493d3023170a00000000000000000000030f1a26323e4a55616d7985919ca8a89d9185796d61555252525252525252525252525e6a76828e99a5ab9f93877b7064584c4034291d1105000000000000000000000000000000000000000000000000030f1c2835424e5b6774818d9aa6aca093867a6d6054473b2e21150800000000030a1014171919181716151413202d3a4653606d798693a0a3968a7d7063574a3d302417141516161718181715110b050000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1e11040000000a1623303d4956636f7c8996a3b0a89b8f8275685b4f4235281c0f000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d00000000000000050a0f14191e23282d32373b40454a4f54595e63686d72767b81858a8f94999ea3a49f9a95908b86817b76726d6760564b3f33271a0e00111d2a36424e5962696e73787d82878c91969ba0a5a29d98938e8984807a75706c67625d58534e49443f3a35302b27221d18130e090400000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00000000000000000009141f2a35404a55606b76818b96a1968b81766b60554a40352a1f140900000000000000000000000000000000000000000000000000000000000814202c38434f5b67737e8b96a2aea3978b7f73675b4f43372b1f141d2935414d5965717d8996a2aba094887c7064584c4034291d11050000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000121e2b3845515e6b7784919eaaa99c908376695c5043362a1d1003000000000000101c2936434f5c6975828f9ca8ab9f9285786c5f5246392c1f1306000000000000000000000000000000000d1926323f4b5864717d8a96a2ada195897d71665b50463c332b231b130c04000000000000000000000000000000111e2b3744515d6a7783909ca9aa9d9184786b5f53473b2f241a110801000000000c1825313d49545e656867666665646362615c544b4034281c1004000e1a26323d4851595e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5d584f453b2f23170b000000000c1925323e4b5864717d8a96a3afab9e9285796c6054473b2f23160a0000000000000000000000000000000000000000030f1b27333f4b5864707d8996a2afac9f9386796d6054473b2e22150800000000000000000000000a16212d3945515c6874808c97a3ada195897d72665a4e4646464646464646464b57636e7a86929eaaa69a8e83776b5f53473b3024180c00000000000000000000000000000000000000000000000000000d1a2633404c5965727e8b98a5aea195887b6f6256493c3023160a000000050d151b20242525242323222120202d3a4753606d7a8693a0a4978a7d7063574a3d30241f2021222324252524211c160f0700000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1e1104000000091623303c4956636f7c8996a3b0a89c8f8275685b4f4235281c0f000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d0000000000060c11161b20252a2f33383d42474c51565b60656a6f74787d82878c91969ba0a5a29d98938e89847f7a75706b66615c564e443a2e23170b000d1a25313c4750585d62676c71767b80858a8f94999ea3a49f9a95908b86817c77726d69645f5a55504b46413c37322d28241f1a15100b050000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d000000000000000000030e18232e39444e59646f7a858f9a9d92877c72675c51463b31261b1005000000000000000000000000000000000000000000000000000000010d1925303c4854606c77838f9ba7aa9e92867a6e62564b3f33271b0f1925313d4955616d7985919da9a4988c8175695d5145392d2115090000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0b090500000000000000111e2a3744505d6a7784909daaaa9d9084776a5d5144372a1e1104000000000002111d2a3743505d697683909ca9aa9e9184776b5e5145382b1f1205000000000000000000000000000000000a1723303c4955616e7a86929ea9a5998e82776c62584e453d342d251e160f070000000000000000000000000000101c2936424f5b6874818d9aa6aca093877b6f63574c41362c231a130b030000000814202c37424c54595b5b5a595857565555514b42392e23180c00000a15212b363f474e51515151515151515151515151515151565e62626262626262615c54515151515151515151515151515151514c463d34291e1307000000000a1723303c4955626e7b8794a0adada195887c6f63574b3f33271b0f040000000000000000000000000000000000000008131f2b37434f5b6774808c99a5b2a99c9084776a5e5145382c1f1306000000000000000000000005111d2834404c58636f7b87939eaaa69a8e82766a5e53473b393939393939444f5b67737f8b97a3ada1958a7e72665a4e43372b1f130700000000000000000000000000000000000000000000000000000b1824313e4a5764707d8a96a3b0a3978a7d7064574b3e3124180b0000050e171f262c30323231302f2e2d2c2b2d3a4753606d7a8794a0a4978a7d7164574a3e312b2c2d2e2f30313232302d2821191007000000101c2936434f5c697683909ca9aa9e9184776a5d5144372b1e11040000000a1623303d4956636f7c8996a3b0a89c8f8275685b4f4235281c0f000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d000000020a11181d22272c30353a3f44494e53585d62676c71757a8084898e93989da2a5a09b96918c87827d78736e69645f5a55504b443c33281d1206000914202b353e464c51565b60656a6f74797e84898d92989da2a6a19c97928d88837e79746f6a65615c57524d48433e39342f2a25211c16100900000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d0000000000000000000007121c27323d48525d68737e89939e998e83786e63584d42372d22170c01000000000000000000000000000000000000000000000000000006121d2935414d5965707c8894a0aca5998e82766a5e52463a2e22160a15212d3945515d6975818d99a5a99d9185796d6155493e32261a0e0200000013202c3946535f6c798693a0acaca09386796c5f5346392c201a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1815100b040000000000101d2936434f5c6976828f9ca8ab9e9184786b5e5245382b1f1205000000000005121e2b3844515e6b7784919daaa99d9083776a5d5044372a1e1104000000000000000000000000000000000814202d3945515d6975818d98a4aa9f94897e746a60574e463f3730282019110a020000000000000000000000000e1a2733404c5965717d8a96a2aea3978b8074685d52483e352c241d150e06000004101b26303a42494d4e4e4d4c4b4b4a494845403930271d12070000040f1a242d363d42444545454545454545454545454546525e686e6f6f6f6f6f6f6e665b50454545454545454545454545454544413b342b22170d02000000000814212d3a46535f6c7884919da9b0a4988c8073675b4f43372c20150a000000000000000000000000000000000000030e1924303c47535f6b7784909ca8b2a6998d8174685b4f4236291d10040000000000000000000000000c18232f3b47535f6a76828e9aa5aa9e93877b6f63574b3f332c2c2c303c4854606c7884909ba7a89c9185796d61554a3e32261a0e0300000000000000000000000000000000000000000000000000000a1623303c4955626f7b8895a2aea5988b7e7265594c3f3226190c00010c16202931383c3f3f3e3d3c3b3a3938373a4754616d7a8794a1a4978a7d7164574b3e3738393a3b3c3d3e3f3f3d39332b23190f040000101c2936434f5c697683909ca9ab9e9184776b5e5145382b1e12050000000a1723303d4a5663707d8a96a3b0a89b8e8275685b4e4235281c0f000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d0000020b141c23282d32373c41464b50555a5f64696d72777c81868b90959a9fa4a49f9a95908b86817b76716c67625d58534e49443f3a332a21170c0100030e19232c343b40464b50555a5f64696e73787d82878c91969ba0a5a39e99948f8a85807b76716c67625e59544f4a45403b36312c27211a1209000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00000000000000000000000b16202b36414c57616c77828d97a0958a7f74695f54493e33291e130800000000000000000000000000000000000000000000000000000a16222e3a46525d6975818d99a5ada195897d7165594d41362a1e1206101c2935414d5965717d8995a1ada1968a7e72665a4e42362a1e130700000013202c3946535f6c798693a0acaca09386796c5f5346392c2626262626262626262626262626262626262626262626262626262624211c160e06000000000f1c2835424e5b6874818e9aa7ac9f9286796c5f5346392d20130700000000000613202c3946525f6c7885929eaba89b8f8275695c4f4336291c10030000000000000000000000000000000004111d2935414d5965707c87929da8a59a90867c726960585149413a322b231c140c0400000000000000000000000b1824303d4955616d7985919da8a89c91857a6f645a50473e362f2720181109020009141e2830373d414241403f3f3e3d3c3b39352e271e150b0000000008121b242b3135383838383838383838383838383b4855626e7a7c7c7c7c7c7c786c5f5346393838383838383838383838383735302a22191006000000000005121e2b3743505c6875818d9aa6b2a89c9084776b6054483d31261b110700000000000000000000000000000000010a151f2a35414c5864707c8894a0acaea296897d7165584c3f33271a0e0100000000000000000000000007131f2a36424e5a65717d8995a1aca3978b8074685c5044382c202935414d5965717c8894a0aca4988c8074685d5145392d21160a0000000000000000000000000000000000000000000000000000000815212e3b4754616d7a8794a0ada6998d8073665a4d4034271a0e0007131e28323b43484b4c4b4a494847464544434754616e7a8794a1a4988b7e7164574b43434445464748494a4b4b49443d352b21160a0000101c2936434f5c697683909ca9ab9e9285786b5f5245392c1f13060000000b1724313e4a5764707d8a97a4b0a79b8e8174675b4e4135281b0e000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d00000a141d262e34393e43484d52575c61666a6f74797e83888d92979ca1a6a29d98938e89847f7a75706b66615c57524d48433e39342e2821180f0500000007111a222a30353a3f44494e53585d62676c71767b80858a8f94999ea3a4a09b96918c87827d78736e69645f5b56514c47423d38332c241b12080000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d0000000000000000000000040f1a242f3a45505b65707b86919c9c91867b70655b50453a2f241a0f04000000000000000000000000000000000000000000000000030f1b27333f4a56626e7a86929da9a89c9084786d6155493d3125190d010c1824303c4955616d7985919da9a69a8e82766a5e53473b2f23170b00000013202c3946535f6c798693a0acaca09386796c5f5346393333333333333333333333333333333333333333333333333333333333312d2720180f050000000e1a2734404d5a6673808c99a6ada094877a6e6154483b2e22150800000000000815212e3a4754606d7a8693a0aca69a8d8174675a4e4134281b0e0200000000000000000000000000000000010d1925313c48545f6b76818b96a0aaa2988e847b736a625b534c443d352d261e160e05000000000000000000000814212d3945515d6975808c97a2ada2968b81766c625950484039312a221b140c04020c161e262c3134353434333231302f2f2d29231d150c0300000000000912192025292b2b2b2b2b2b2b2b2b2b2b2b2f3c4855626f7b888989898986796c5f5346392c2b2b2b2b2b2b2b2b2b2b2b2b28241f181007000000000000020f1b2834404d5965717d8a96a2aeaca094887c7065594e43382d23190f0600000000000000000000000000000109131c26313c47525d6975818c98a4b0aa9e9286796d6155493c3024170b00000000000000000000000000020e1a26313d4955616c7884909ca8a89c9084786c6054493d31252e3a46515d6975818d99a5ab9f93877b6f64584c4034281d11050000000000000000000000000000000000000000000000000000000713202d3a4653606c7986939faca79a8e8174675b4e4135281b0e000c18242f3a444d54585857565554535251504f4f54616e7b8894a1a4988b7e7165584e4f50515253545556575858554f473d32271b0f0300101c2936434f5c697683909ca9aca09386796d6053473a2d2114070000000c1825323e4b5864717e8b98a4b1a79a8d8174675a4d4134271b0e000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d0006111c262f383f454a4f54595e63676c71767b80858a8f94999ea3a5a09b96918c87827d78736e69645f5a55504b46413c37322d28231d170f0600000000000811181f24292e33383d42474c51565b60656a6f74797e83888d92979ca1a6a29d98938e89847f7a75706b66615c58534e49443e362d24190e0300101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00000000000000000000000008131e29333e49545f69747f8a95a0978d82776c61564c41362b20160b0000000000000000000000000000000000000000000000000814202c37434f5b67737e8a96a2aea4988c8074685c5044382c211509000814202c3844505c6975818d99a5ab9f93877b6f63574b3f33281c1004000013202c3946535f6c798693a0acaca09386796c5f53464040404040404040404040404040404040404040404040404040404040403d38322a21170d0200000c1925323f4b5865717e8b97a4aea295887c6f6356493d3023170a00000000000a1623303c4955626f7b8895a1aea5988b7e7265594c4033261a0d0000000000000000000000000000000000000814202c37434e59646f7a848e98a1a9a0968d857c746d655e564e473f38302820170f0600000000000000000005111d2935414c58646f7a86919ba6a89d92887e746b625a524b433c342d251e160e06040c141b212527282827262524242322201d18120b0300000000000000080f15191d1e1e1e1e1e1e1e1e1e1e1e222f3c4855626f7b889596969386796c5f5346392c201e1e1e1e1e1e1e1e1e1e1e1c18130d0600000000000000000c1824303d4955616d7985919da9b0a4998d81766a5f54493f342b21181009030000000000000000000000050b131b252e38434d58636e7a85919da9b1a5998d8275695d5145392d20140800000000000000000000000000000915212d3844505c6873808b97a3aca095897d7165594d41352a323e4a56626e7a86929da9a69a8e82766b5f53473b3024180c0000000000000000000000000000000000000000000000000000000006121f2c3945525f6b7885929eaba89b8f8275685b4f4235291c0f00101c2834404c565f656564636261605f5e5d5c5b5a616e7b8895a1a5988b7e71655a5b5c5d5e5f6061626364656561594e43382c20130700101c2936434f5c697683909ca9ada194877b6e6155483b2f2216090000000d1a26333f4c5966727f8c98a5b2a6998c807366594d4033261a0d000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d000b17222d38424a51565b5f64696e73787d82878c91969ba0a5a49f9a95908b86817b76716c67625d58534e49443f3a35302b26211c17120c0500000000000000060d13181d22272c31363b40454a4f545a5f64696e73787d82878c91969ba0a5a39e9a95908b86817c77726d68635e59544f483f352b20140800101c2936434f5c697683909ca9aa9d9184776a5e5144372b1e1105000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d000000000000000000000000010c17222d37424d58636d78838e999e93897e73685d52483d32271c110700000000000000000000000000000000000000000000010d1924303c4854606c77838f9ba7ab9f93877b6f63584c4034281c10040004101c2834404c5864717c8995a1ada3978b8074685c5044382c201408000013202c3946535f6c798693a0acaca09386796c5f534d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4c49443c33291e130800000b1724303d4a56636f7c8995a2aea4978a7e7164584b3f3226190d00000000000c1925323e4b5764717d8a96a3afa396897d7064574a3e3125180b000000000000000000000000000000000000040f1b26323d48535d68727c868f98a0a89f978e867e776f6860595149423a322921180f060000000000000000010d1824303c47535e69747f89949ea7a49a90877d746c645d554d463f3730282018100802091015181b1b1b1a19181817161514110c070000000000000000000004090d101212121212121212121215222f3c4855626f7b8895a2a09386796c5f5346392c201312121212121212121211100c08020000000000000000000814212d3945515d6975818d98a4b0a99e92877c71665b51463d332a221b140f0a0705030202020305080c10161d252d37404a545f6a75808b97a2aeaca095897d7165594d4135291d1004000000000000000000000000000004101c28343f4b57636f7a86929eaaa5998d82756a5e52463a2e37434f5b67727e8a96a2ada1958a7e72665a4e42372b1f13070000000000000000000000000000000000000000000000000000000004121e2b3845515e6b7784919eaba99c8f8276695c4f4336291c1000121f2b3844515d68717271706f6e6d6c6b6a696867666e7b8895a2a5988c7e72666768696a6b6b6d6d6f6f7071716b6054483b2f22160900101c2936434f5c697683909ca9afa296897c7063574a3d3124180b0000010f1b2834414e5a6774818d9aa6b1a4988b7e7265584c3f3225190c000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938c807366594c403326190d000f1b27333f4a545c61666b70757a7f84898e93989da2a6a29d98938e89847f7a75706b66615c57524d48433e39342f29251f1a15100b060100000000000000000002080d12171c21262b30353a3f44494e53585d62676c71767b80858a8f94999ea3a5a09b96928d88837e79746f6a65605a51473c3025180c00101c2936434f5c697683909ca9ab9e9285786b5f5245392c201306000714212d3a4753606d7a8794a0ada69a8d807366594d4033261a0d0000000000000000000000000005101b26313b46515c67727c87929d9a8f857a6f64594e44392e23180d0300000000000000000000000000000000000000000006121d2935414d5964707c8894a0aca69b8f83776b5f53473b2f23170c0000000c1824303c4854606c7885919da9a89c9084786c6054493d3125190d010013202c3946535f6c798693a0acaca09386796c5f5959595959595959595959595959595959595959595959595959595959595959554e453b3024190d01000915222e3b4854616d7a86939faca6998c8073675a4e4135281c1003000000030f1b2834414d5a6673808c99a5ada094877b6e6155483c2f231609000000000000000000000000000000000000000a15202b36414c56606a737d868e969ea6a0989089817a726a635b534c443b332a21180f06000000000000000008141f2b36414d58626d78828c959ea7a2998f877e766e675f585049413a322a221a12090004090c0e0f0e0d0d0c0b0a09080704010000000000000000000000000000000000000000000000000915222f3c4855626f7b8895a2a09386796c5f5346392c2013060000000000000000000000000000000000000000000004111d2935414d5964707c88939faaafa4988d82776d62584f453c342c25201b171311100f0f0f101214181c21282f373f49525c66717b86919ca8b1a69b8f84786c6155493d3125190d000000000000000000000000000000000b17232f3b46525e6a76828d99a5aa9e92867a6e62564b3f333c48535f6b77838f9ba7a89c9185796d61554a3e32261a0e020000000000000000000000000000000000000000000000000000000001111e2a3744515d6a7784919daaa99c908376695d5043362a1d100013202c3946535f6c797e7d7c7b7b7979787776757473727b8895a2a5988c7e7272737475767778797a7b7c7d7e7c7063564a3d3023170a00101c2936434f5c697683909ca9b1a4988b7e7265594c4034271b0f030004111d2a3643505c6975828f9ba8afa3968a7d7064574a3e3124180b000000000000010507101c2936434f5c69768390908376695c4f4336291c100705010000000000000000000000010507101c2936434f5c69768390908376695c4f4336291c1007050100000000000013202c3946535f6c7986938c807366594c403326190d00121e2b37434f5b666d72777c81868b90959a9ea3a5a09b96918c87827d78736e69645f5a55504b46413c37322d28231e19140f0a05000000000000000000000000000001060b10151a1f24292e33383d42474c51565b60656a6f74797e83888d92979ca1a6a29d98948f8a85807b76716c63594d4134281b0f00101c2936434f5c697683909ca9aca093867a6d6154473b2f22160a000714212e3a4754616d7a8794a1aea69a8d807366594d4033261a0d000000000000000000000000000009141f2a35404a55606b75818b96a1968b81756b60554a3f352a1f14090000000000000000000000000000000000000000000a16222e3a46515d6975818d99a4aca2968a7e72665a4e43372b1f13070000000814202c3844505c6874818c98a5aca095897d7165594d4135291d12060013202c3946535f6c798693a0acaca09386796c66666666666666666666666666666666666666666666666666666666666666666560574c4135291d1004000713202c3945525e6b7784909da9a89b8f8276695d5144382c1f130700000006121f2b3744505c6975828e9ba7aa9e9185786c5f53463a2d20140700000000000000000000000000000000000000040f1a252f3a444e58616b747c848c949ca3a29b938b847c756d655d554d453c332a21180e0400000000000000030e1a25303b46515b66707a838c959da6a19990888079716a625b534c443c342c241b1209000000000000000000000000000000000000000000000000000000000000000000000000000000000915222f3c4855626f7b8895a2a09386796c5f5346392c20130600000000000000000000000000000000000000000000000c1824303c48545f6b76828d99a4afaa9f94897e746a61574e463e37312b2723201e1c1c1b1c1d1e2124282d33394149515b646e78828d98a3aeaba0958a7e73675c5044382c2015090000000000000000000000000000000007121e2a36424d5965717d8994a0aca2978b7f73675b4f4337404c5864707c88949faba3988c8074685c5145392d21150a000000000000000000000000000000000000000000000000000000000000111d2a3744505d6a7784909daaaa9d9083766a5d5043372a1d100013202c3946535f6c79868a89888786858484828281807e7d8895a2a6998c7f7e7f818182838485868788898a8a7d7063564a3d3023170a00101c2936434f5c697683909ca9b3a79a8e8175685c5043372b1f1308040814202d3945525e6b7784919daaaea194887b6e6255493c2f2316090000000000070d1114161c2936434f5c69768390908376695c4f4336291c1614110d07000000000000000000070d1114161c2936434f5c69768390908376695c4f4336291c1614110d07000000000013202c3946535f6c7986938c807366594c403326190d0013202c3946525f6c777e83888d92979ba0a5a49f9a948f8a85817b76716c67625d58534e49443f3a35302b26211c17120d08030000000000000000000000000000000000000004090e13181d22272c31363b40454a4f54595e63686d73787d82878c91969ba0a5a49f9a95918c87827d75695c5043362a1d1000101c2936434f5c697683909ca9aea295897c6f63574a3e32261a0f060815222e3b4854616e7b8894a1aea69a8d807366594d4033261a0d0000000000000000000000000000030e18232e39444e59646f7a858f9a9d92877c71675c51463b31261b100500000000000000000000000000000000000000000f1b27333f4a56626e7a86919da0a09d92867a6e62564a3e32261a0e0200000004101c2834404c5864707c8894a0a0a0998d8175695e52463a2e22160a0013202c3946535f6c798693a0acaca093867973737373737373737373737373737373737373737373737373737373737373737372695d5145382c1f13060004111d2a36434f5c6875818e9aa6aa9e9285796c6054483b2f23170b0000000b17232f3b47535f6c7885919eaaa79b8e8275695c5044372b1e1205000000000000000000000000000000000000000008131e28323c464f59626a727a828a9299a1a59d968e877f776f675f574e453c332a20160b010000000000000008141f2a353f4a545e68717a838b949ca4a29a928b837b746d655e564e463e362d241b12080000000000000000000000000000000000000000000000000000000000000000000000000000000915222f3c4855626f7b8895a2a09386796c5f5346392c20130600000000000000000000000000000000000000000000000814202c37434f5a65717c87929da8b0a59b90867c736960585049423c37332f2d2b29282829292b2d3034383e444b535b636d76808a949fa9afa59a8f84786d62564b3f33281c100400000000000000000000000000000000020e1925313d4954606c78848f9ba7a79b8f83776c6054483c45515d6974818c98a4ab9f93877b6f63584c4034281d1105000000000000000000000000000000000000000000000000000000000000111d2a3744505d6a7783909daaaa9d9084776a5d5044372a1d110013202c3946535f6c798693969594939291908f8e8d8c8b8a8e98a4a79b908a8b8c8d8e8f90919293949596968a7d7063564a3d3023170a00101c2936434f5c697683909ca9b6a99d9084786c5f53473b3024191211111824303c4955616e7a87939facab9f9286796c6053473a2e211408000000030b12181d2022222936434f5c69768390908376695c4f4336292222201d18120b030000000000030b12181d2022222936434f5c69768390908376695c4f4336292222201d18120b0300000013202c3946535f6c7986938c807366594c403326190d0013202c3946535f6c79868f94989da2a7a29d98938e89847e7a75706b66615c57524d48423d39332e29241f1a15100b0601000000000000000000000000000000000000000000000003080d12171c21262b30353a3f44494e53585d62676c71767b80858a8f94999ea3a6a19c97928d8376695d5043362a1d1000101c2936434f5c697683909ca9b1a4988b7f73665a4e42372c2118121116232f3c4955626f7b8895a2aea6998c807366594c403326190d00000000000000000000000000000007121c27323d48525d68737e89939e998e83786d63584d42372c22170c0100000000000000000000000000000000000000111e2a37434f5b67737e8a93939393938d8175695d5145392e22160a00000000000b1824303c4854606c7884909393939392867a6e62564a3e3225190c0013202c3946535f6c798693a0acaca0938680808080808080808080808080808080808080808080808080808080808080808080796d6053463a2d20130700010e1b2734404d5965727e8a97a3ada195887c7064584b3f34281d120a0809111c27333f4b57636f7b8894a1ada4978b7e72665a4d4134281b0f030000000000000000000000000000000000000000010c16202a343d4750586068707880878f969ea5a09891898179716960574e453c32281d130800000000000000020d18232d38424c565f687179828a929aa1a49c958d867e776f68605850483f362d241a100600000000000000000000000000000000000000000000000000000000000101010101010101010915222f3c4855626f7b8895a2a09386796c5f5346392c2013060101010101010101010000000000000000000000000000030f1b26323d4954606b76818c96a1abaca2988e857b726a625a534d48433f3c39373635353536383a3c4044494f565d656d757f88929ca6b0a89e93887d72675c51453a2e23170b0000000000000000000000000000000000000915202c3844505b67737f8b96a2aca094887c7064584d414a55616d7985919da9a69a8e82766b5f53473b2f24180c00000000000000000000000000000000000000000000000000000000000000111d2a3744505d6a7784909daaaa9d9084776a5d5044372a1d110013202c3946535f6c798693a0a2a1a09f9e9d9c9b9a99989799a0a9aca29a9798999a9b9c9d9e9ea0a0a1a2968a7d7063564a3d3023170a00101c2936434f5c697683909ca9b6aca094887c7064584c41362b221f1e1e202a35414c5865717d8a96a2afa99c9083776a5e5145382b1f12060000020c151d24292d2f2f2f36434f5c69768390908376695c4f43362f2f2f2d29241d150c02000000020c151d24292d2f2f2f36434f5c69768390908376695c4f43362f2f2f2d29241d150c02000013202c3946535f6c7986938c807366594c403326190d0013202c3946535f6c7986939fa4a5a09b96918c87827d78736e69645f5a55504b46413c37322d28231e19140f0a050000000000000000000000000000000000000000000000000000000001060b10151a1f24292e33383d42474c51565b60656a6f74797e83888d92979ca1a7a39d908376695d5043362a1d1000101c2936434f5c697683909ca9b4a79b8f83776b5f53483d332a231f1e1e25313e4a5764707d8a96a3b0a5988c7e7265594c3f3226190c000000000000000000000000000000000b16202b36414c56616c77828d979f958a7f74695e54493e33281e13080000000000000000000000000000000000000013202c3946525f6b7783868686868686867c7165594d4135291d1105000000000007131f2b3844505c687480868686868686867e73665a4d4134271a0e0013202c3946535f6c798693a0acaea2978e8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d86796d6053463a2d20130700000c1824313d4956626e7b87939faba4988c8074685c5044392e231b16151619222d38444f5b6773808b98a4aca094877b6f63564a3e3125190c00000000000000000000000000000000000000000000040f18222b353e464e575e666e757d848c939ba2a39b938b837b726a60574d44392f241a0f040000000000000007111c26303a444d565f67707880888f979ea69f989089817a726a625a51483f362c22180e0300000000000000000000000000000000000000000000000000060a0d0e0e0e0e0e0e0e0e0e0e15222f3c4855626f7b8895a2a09386796c5f5346392c20130e0e0e0e0e0e0e0e0e0e0c09050000000000000000000000000a16212c38434e59646f7a858f99a3adaaa0978e857c746c655e59534f4b48464443424242434446494c50555a61676f767f88919aa4aeaaa0968c81766c61564b3f34291d120600000000000000000000000000000000000004101c27333f4b57626e7a86929da9a4998d8175695d51454e5a66727e8a96a1ada195897d72665a4e42372b1f130700000000000000000000000000000000000000000000000000000000000000111d2a3744505d6a7784909daaaa9d908376695d5043372a1d100013202c3946535f6c798693a0a1a09f9e9d9c9b9a99989796989fa9aca199969698989a9b9c9d9e9fa0a1a2968a7d7063564a3d3023170a00101c2936434f5c697683909ca9b6b0a4988c8074695d52473d342e2c2a2b2c323b46515d6975818d99a5b2a5998d8174675b4f4236291d100400000a141e272e35393c3c3c3c434f5c69768390908376695c4f433c3c3c3c39352e271e140a0000000a141e272e35393c3c3c3c434f5c69768390908376695c4f433c3c3c3c39352e271e140a000013202c3946535f6c7986938c807366594c403326190d0013202c3946535f6c798693a0a39a948f8a85817b76716c67625d58534e49443f3a35302b26211c17120d080300000000000000000000000000000000000000000000000000000000000000000004090e13181d22272c31363b40454a4f54595e63686d72777c82878c91969ca69d908376695d5043362a1d1000101c2936434f5c697683909ca9b6ab9f93877b70655a4f453c342e2b2a2b2c34414d5966727f8b98a5b0a4978a7e7164584b3e3125180b00000000000000000000000000000000040f1a242f3a45505b65707b86919b9b91867b70655a50453a2f24190f04000000000000000000000000000000000000131f2c3946525f6b767979797979797979776c6054483c3024190d010000000000030f1b27333f4c58647079797979797979797972665a4d4034271a0e0013202c3946535f6c798693a0acb3a9a09a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9386796d6053463a2d20130700000915212e3a46525f6b77838f9ba7a89c9084786d61564a40352d26232222252b343f4955606c7884909ca8a89c9084776b5f53473a2e2215090000000000000000000000000000000000000000000000061019232c343d454d545c646b737a82899198a0a59d958d857c72695f554b41362b20150a00000000000000000a141e28323b444d555e666e767d858d949ca3a29b938b847c746c635a51483e342a1f150a0000000000000000000000000000000000000000000000050c1116191b1b1b1b1b1b1b1b1b1b1b222f3c4855626f7b8895a2a09386796c5f5346392c201b1b1b1b1b1b1b1b1b1b1a1815100a030000000000000000000004101b27323d48535e68737d87919ba4aea9a0978e867e76706a645f5b575452504f4f4e4f50515355585c61666c72798189919aa3acaba2988e847a6f655a4f44392e23180c01000000000000000000000000000000000000000b17232e3a46525e6975818d99a4a99d9185796e62564a535f6b76828e9aa6a89c9185796d6155493e32261a0e0200000000000000000000000000000000000000000000000000000000000002111e2b3744515d6a7784919eaaa99c908376695d5043362a1d100013202c3946535f6c7986939694939291908f8e8d8c8b8a898d98a4a79a8f898a8b8c8d8e8f909192939495968a7d7063564a3d3023170a00101c2936434f5c697683909ca9b6b4a89d91857a6e63594f463f3b383737393d444d58636e7985919da9aea295897d7164584c3f33261a0e010006111c263039404548494949494f5c69768390908376695c4f494949494845403930261c11060006111c263039404548494949494f5c69768390908376695c4f494949494845403930261c11060013202c3946535f6c7986938c807366594c403326190d0013202c3946535f6c798693a09e9289847e7a75706b66615c56514c47423d38332e29241f1a15100b06010000000000000000000000000000000000000000000000000000000000000000000000000002070c11161c21262b30353a3f44494e53585d62676c71767b80858a95a19d908376695d5043362a1d1000101c2936434f5c697683909ca9b4aca4988d81766b61574e463f3b383738393c45515d6975828e9aa7afa295897c7063564a3d3024170a000000000000000000000000000000000008131e29333e49545f69747f8a959f978c82776c61564b41362b20150b000000000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6b655b4f44382c201408000000000000000b17232f3b47535e676c6c6c6c6c6c6c6c6c6960564a3e3225190c0013202c3946535f6c798693a0acacacaba7a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a09386796d6053463a2d201307000005121e2a36424f5b67737f8b97a3aca195897d72675c51473e37322f2e2f31363d46505b66717d8894a0aca3978b8073675b4f43372b1e120600000000000000000000000000000000010102030201000007101a222b333b424a5259616870777f878e97a0a79f968e857b71675d52483d32261b100400000000000000020c162029323b434c545c646c737b828a9199a0a59d968e867e756c635a50463c31261c1105000000000000000000000000000000000000000000070f161d22262728282828282828282828282f3c4855626f7b8895a2a09386796c5f5346392c28282828282828282828282725211c150d05000000000000000000000a15202c36414c57616b758089929ca5ada9a0989088817b75706b6764615f5d5c5b5b5b5c5e5f6265686d71777d848b929ba3acaba29990867c72685e53493e33281d1206000000000000000000000000000000000000000006121e2935414d5965707c8894a0aba2968a7e72665a4f57636f7b87939faba3988c8074685c5045392d21150a0000000000000000000000000000000000000000000000000000000000000004121e2b3845515e6b7784919eaba99c8f8275695c4f4336291c100013202c3946535f6c79868a898887868584828281807e7d7c8996a2a6998c807d7e7f8081828384858687888a8a7d7063564a3d3023170a00101c2936434f5c697683909ca9b3aaa29f968b80756b6158504b4745444445494e565f69747f8a96a2aea99d9185796d6155483c3023170b00000b17222e38424b515555555555555c69768390908376695c555555555555514b42382e22170b000b17222e38424b515555555555555c69768390908376695c555555555555514b42382e22170b0013202c3946535f6c7986938c807366594c403326190d0013202c3946535f6c798693a09d9085807a75706b66615c57524d48433e39342f2a25201b16110c070200000000000000000000000000000000000000000000000000000000000000000000000000000004090e13181d22272c31363b40454a4f54595e63686d72777c818793a09d908376695d5043362a1d1000101c2936434f5c697683909ca9ada29b9893887d73696057504b4745444446484d57626d7985919daaaca093877a6e6154483b2f2215090000000000000000000000000000000000010c17222d37424d58636d78838e999e93887d73685d52473d32271c110600000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5a53493e33271b10040000000000000007131f2b37424c555c5f5f5f5f5f5f5f5f5f5d574e44392d2216090013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09386796d6053463a2d2013070000020e1a26323e4b57636e7a86929ea9a69a8f83786e63595049423e3c3b3c3e41474f58626d77838e99a5a99e92877b6f63574b3f33271b0e020000000000000000010508090a0b0c0c0d0e0f0f0f0d0a05000710192129313840484f565e656d747c858e97a0a8a0978d83796f64594e43382c2115090000000000000000040e172029313a424a525a6169707880878f969fa7a09890877e756b62584d43382d22170b000000000000000000000000000000000000000006101921282e32343434343434343434343434343c4855626f7b8895a2a09386796c5f53463934343434343434343434343434312d271f170d04000000000000000000040f1a25303a454f59636d77818a939ba3abaaa29a938c86817b7773706e6b6a69686868696a6c6e7174787d82888f959da4aca9a19990877e746a60564c41372c21160b000000000000000000000000000000000000000000010d1925313c4854606b77838f9ba7a69b8f83776b5f535c6874808c98a3aa9f93877b6f63584c4034281c11050000000000000000000000000000000000000000000000000000000000000006131f2c3945525f6c7885929faba89b8e8275685b4f4235281c0f0013202c3946535f6c797e7d7c7b7a7978777675747371707d8a96a3a79a8d817471727374757677797a7b7c7d7e7c7063564a3d3023170a00101c2936434f5c697683909ca9ada298929392877d736a625b57535251515255596068717b86919ca7b0a4998d8175695d5145392c20140800000f1b27333f4a545c616262626262626976839090837669626262626262615c544a3f33271b0f000f1b27333f4a545c616262626262626976839090837669626262626262615c544a3f33271b0f0013202c3946535f6c7986938c807366594c403326190d0013202c3946535f6c798693a0a197908b86817c77726d68635e59544f4a45403b36312c27221d18130e09040000000000000000000000000000000000000000000000000000000000000000000000050a0f14191e23282d32373c41464b50555a5f64696e73787d82878c9199a49d908376695d5043362a1d1000101c2936434f5c697683909ca9a79b908b908f857b7269625c57535151515254585f69737e8a95a1ada99d9184786b5f5246392d20140700000000000000000000000000000000000005101b26313b46515c67717c87929d9a8f84796f64594e43392e23180d02000000000000000000000000000000000a16212c3740484f525353535353535353524f4941372d22160b0000000000000000030e1a25303a434b50535353535353535353514c453c32281d11050013202c3946535f6c79869393939393939393939393939393939393939393939393939393939393939393939393939393939386796d6053463a2d2013070000000a16222e3a46525e6a75818d98a3aba0958a80756b625a544e4b4948484a4d5259616a747e89949faaa4988d81766a5e52473b2f23170b0000000000000000070d111416171818191a1b1c1c1c1916110b04070f171f262e363d454c535b636a737c858e98a2a99f958b81766b6054493d32261a0e020000000000000000050e171f283038404850575f666e757d858c959ea7a29990877d74695f544a3e33281c1105000000000000000000000000000000000000020d18222b33393e41414141414141414141414141414855626f7b8895a2a09386796c5f534641414141414141414141414141403d3831291f150b0000000000000000000009131e29333d48515b656e778189929aa1a9aca59e97928c8883807d7a7877757575757677797b7d8185898e949aa0a7ada69f978f877e756b62584e443a30251b1005000000000000000000000000000000000000000000000814202c37434f5b67737e8a96a2ab9f93877b6f6458616d7884909ca8a69a8e82766a5f53473b2f23180c00000000000000000000000000000000000000000000000000000000000000000714202d3a4653606d798693a0aca79a8e8174675b4e4134281b0e00121f2b3844515d687071706f6e6d6c6b6a6968676665717e8b97a4a89b8e817568666768696a6b6c6d6e6f7071716b6054483b2f22160900101c2936434f5c697683909ca9a99d918689948f857c746d6763605e5d5d5f61656b727a838d97a2ada99e93887c7065594d4135291c10040000121e2b3744505b666e6f6f6f6f6f6f6f7683909083766f6f6f6f6f6f6f6e665b5044372b1e1200121e2b3744505b666e6f6f6f6f6f6f6f7683909083766f6f6f6f6f6f6f6e665b5044372b1e120013202c3946535f6c7986938c807366594c403326190d0013202c3946535f6c798693a0a8a19c97928d88837e79746f6a65605b56514c47423d38332e29241f1a15100b0601000000000000000000000000000000000000000000000000000000000002070c11161b20252a2f34393e43484d52575c61666b70757a7f84898e93989da3a79d908376695d5043362a1d1000101c2936434f5c697683909ca9a5998c7f89948d847b746d6763605e5d5e5f61646a717a85909ba6b1a5998d8175685c5043372a1e11050000000000000000000000000000000000000009141f2a353f4a55606b75818b96a1968b80756b60554a3f342a1f14090000000000000000000000000000000005101a252e373e4346464646464646464646433e372f251b100500000000000000000009141e283139404446464646464646464645413b332a21160b000013202c3946535f6c79868686868686868686868686868686868686868686868686868686868686868686868686868686868686796d6053463a2d20130700000006121e2a36414d5964707b87929da8a69c91877d746c655f5a5755555557595e646b737c86909ba5a89d92877c7065594d42362a1e1206000000000000030b12181d212323242526272828292826221c150e05050d151c242b333a42495159616a737c86919ba6a79d92877c71655a4e42362a1e1206000000000000000000050d161e262e363e454d545c636b727a838c959ea8a29990867b71665b5044392d22160a00000000000000000000000000000000000008141f29343d444a4d4e4e4e4e4e4e4e4e4e4e4e4e4e4e55626f7b8895a2a09386796c5f534e4e4e4e4e4e4e4e4e4e4e4e4e4e4d49433b31271c1106000000000000000000020c17212b364049535c656e7780888f979ea4aba9a39d9894908c8987858382828282828485878a8d91959a9fa5aba8a29c948d857d756c635950463d32281e14090000000000000000000000000000000000000000000000030f1b27333f4a56626e7985919da9a4988c8074685c65717d8995a1ada195897d72665a4e42362b1f130700000000000000000000000000000000000000000000000000000000000000000815222e3b4854616e7a8794a1ada6998c8073665a4d4033271a0d00101c2834404b565f6465646362615f5e5d5c5b5a5965727f8c98a5a89c8f8275695c5a5b5c5d5e5f60616263646561594e43382c20130700101c2936434f5c697683909ca9a99c8f82838e978e867e78736f6d6b6a6a6b6d71767c848c959fa9ada3988d82766b6054483c3024180c00000013202c3946535f6c787c7c7c7c7c7c7c7c839090837c7c7c7c7c7c7c7c786c5f5346392c20130013202c3946535f6c787c7c7c7c7c7c7c7c839090837c7c7c7c7c7c7c7c786c5f5346392c20130013202c3946535f6c7986938c807366594c403326190d0013202c3946535f6c798692979ca1a6a39e99948f8a85807b76716c67625d58534e49443f3a35302b26211c17120d08030000000000000000000000000000000000000000000000000004090e13181d22272c31363b40454a4f54595e63686d72777c81868b90959a9fa4a5a09b96908376695d5043362a1d1000101d2a3643505d697683909da9a5988c7e828d968d857e78736f6c6b6a6b6b6d70757b838d97a1acaca095897d7165594c4034271b0f0200000000000000000000000000000000000000030d18232e39444e59646f7a858f9a9d92877c71665c51463b30261b10050000000000000000000000000000000009131c252c32373939393939393939393937332d251d130900000000000000000000020c161f282f34383939393939393939393835302921180f040000131f2c3946525f6b76797979797979797979797979797979797979797979797979797979797979797979797979797979797979766b5f5346392d201306000000010d1925313c48535f6a75818b96a1aba39990877e77706b676462616263666a6f757d858e98a2aba1968c81766a5f54483d31251a0e020000000000020c151d24292d2f303132333334353635322d2720170e04030a121a212830373f474f57616a747f8a95a0aba4998d82766a5f53473b2e22160a00000000000000000000040c141c242c333b424a525961697179838c96a0aaa2978d82776c61554a3e32261a0e0200000000000000000000000000000000000d1925303b454f565a5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b626f7b8895a2a09386796c5f5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b59554d43392e22160a00000000000000000000050f1a242e37414a535c656d767e858c93999fa5aaa9a4a09c98969391908f8e8e8f8f90929496999da1a5aaa8a39d97918a837b736b625a51473e342b21170c020000000000000000000000000000000000000000000000000a16222e3a45515d6975818c98a4a89c9084786c606a76828e9aa6a89c9085796d6155493d32261a0e0200000000000000000000000000000000000000000000000000000000000000000a1623303c4956626f7c8895a2aea5988b7e7265584c3f3226190c000c18242f3a444d54585857565554535251504f4d5a6673808d99a6a99d9083766a5d504e4f505152535556575858554f473d32271b0f0300101d2936434f5c697683909ca9a89c8f827d8892989089847f7b79787777787a7d82878e969ea7aea59b91867b70655a4f43372c20140800000013202c3946535f6c798689898989898989899292898989898989898986796c5f5346392c20130013202c3946535f6c798689898989898989899292898989898989898986796c5f5346392c20130013202c3946535f6c7986938c807366594c403326190d0013202c3946535f6c7982878b90959a9fa4a49f9a95908b86827c77726d68635e59544f4a45403b36312c27221d18130e0904000000000000000000000000000000000000000000050a0f14191f23282d32383c42474b51555b6064696e73787d83888d92979ca1a6a39e99948f8a858176695d5043362a1d1000101d2a3643505d697683909daaa5988b7e7b8690979089847f7b79777777787a7d81868d959fa8afa59a8f84786c6155493c3024180b00000000000000000000000000000000000000000007121c27323d48525d68737e89939e998e83786d62584d42372c21170c01000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2a27211b130b010000000000000000000000040d161d23282b2c2c2c2c2c2c2c2c2c2c29241f170f06000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b645a4f43372b1e1205000000000914202b37424e59646f7a858f99a3aba2999088827b7773706f6e6f7072767a80878f97a0aaa3998f857a6f64594e43372c2015090000000000000a141e272e35393c3d3e3e3f40414242423e39312920150b0000080f171e262d353d454f58636d78848f9aa6aa9e93877b6f63574b3e3225190d0000000000000000000000020a121a2229313840474f575f67717a848e99a4a99f94897d72665a4f43372b1e12060000000000000000000000000000000000101d2935414d576167676767676767676767676767676767676f7b8895a2a09386796c67676767676767676767676767676767665f554a3f33261a0e000000000000000000000008121c252f38414a535c646c737a82888e94999ea2a6aaa8a5a2a09e9d9c9b9b9b9c9d9ea0a3a6a9a9a5a19c97928c867f787169615950483f352c22190f050000000000000000000000000000000000000000000000000006111d2935414c5864707c88939faba195897d71656e7a86929eaaa3978c8074685c5045392d2115090000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5764717d8a97a3b0a3968a7d7064574a3e3124180b0007121d28323b42484b4b4a49484746454443424e5b6774818e9aa7aa9e9184776b5e5145434445464748494a4b4b49443d352b21160a0000101d2a3643505d697683909da9a89b8e8276808b949b948f8b88868484848586898d9299a0a8aca49c93897f746a5f54493d32271b0f0300000013202c3946535f6c798693969494949494949494949494949494969386796c5f5346392c20130013202c3946535f6c798693949494949494949999949494949494949386796c5f5346392c20130013202c3946535f6c7986938c807366594c403326190d00121f2b3844515d6871767b80858a8f93989da2a6a19c97928d88837e79746f6a65605b56514c47423d38332e29241f1a15100b060100000000000000000000000000000002070c11161b20252a2f34393e43484d52575c61666b70757a8084898e93989da2a6a19c97928d88847e7a756f665a4e4235291c0f00101d2a3743505d6a7683909daaa4988b7e747e88929b958f8b88868484848587898d91989fa8afa79d93897e73675c5044382c201408000000000000000000000000000000000000000000000b16202b36414c56616c77828d979f948a7f74695e53493e33281d130800000000000000000000000000000000010910161a1e1f2020202020202020201e1b1610090100000000000000000000000000040b12181c1f2020202020202020201f1d19130d06000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5a52493e33271b0f0200000000030f1a26313c48535d68737d87919aa3aba29a938d8783807d7b7b7b7c7e82868c9299a1a9a39a91877d73685e53483d31261b0f04000000000006111c2630394046494a4a4b4c4d4e4f4f4e4a433b31271c11050000050c141b232b333d46515c67727e8a96a2aea3978b7f73665a4e4135281c0f030000000000000000000000000810171f262e353d454d555f68727c87929da9a59a8e83776b5f53473b2e2216090000000000000000000000000000000000121f2c3845515d697274747474747474747474747474747474747b8895a2a0938679747474747474747474747474747474747471675b4f4236291c100000000000000000000000000a131d262f38414a525a616970767d83888d92969a9ea1a3a5a7a8a9a8a8a8a8a9a9a8a7a5a29f9c9995908c86817b746d665f574f473e362d231a10070000000000000000000000000000000000000000000000000000010d1824303c48535f6b77838f9aa6a5998d817569727e8a97a3aa9f93877b6f63574c4034281c10050000000000000000000000000000000000000000000000000000000000000000000d1a2733404c5966727f8c98a5aea195887b6f6255493c2f23160a00010c16202931373c3e3f3d3c3b3a39383736424f5b6875828e9ba8ab9f9285786c5f5245393738393a3b3c3d3e3f3d39332b23190f040000111d2a3744505d6a7683909daaa79a8e817478828c959d9b979592919190919396999ea4aaa8a19a928a81776d63584e43382c21160a0000000013202c3946535f6c7986938d87878787878787878787878787878d9386796c5f5346392c20130013202c3946535f6c798687878787878787889191888787878787878786796c5f5346392c20130013202c3946535f6c7986938c807366594c403326190d00101c2834404c565f656a6f74797e83888d92979ba0a5a39e99948f8a85807b76716c67625d58534e49443f3a35302b26211c17120d0803000000000000000000000004090e13181d22272c31363b40454a4f54595e63686d72777c81868b90959a9fa4a49f9a95908c87827d78736e69645d54493e3226190d00111d2a3744505d6a7784909daaa4978a7d71768089929a9b979492919191929395999da3a9aaa49d958c82776c61564b3f34281c100400000000000000000000000000000000000000000000040f1a242f3a45505b65707b86919b9b90867b70655a4f453a2f24190e040000000000000000000000000000000000050a0e1113131313131313131313110f0a050000000000000000000000000000000001070c101213131313131313131312100d080200000000000a16212c3740484f52535353535353535353535353535353535353535353535353535353535353535353535353535353535353524f4940372c21160a0000000000000915202b36414c56616b757f889199a1a8a59e98938f8c8a888888898b8e92979da3a9a29a91897f756b61574c41362b20150a0000000000000b17222e38424b5155565758595a5a5b5c5a554d43392d22160a00000002091119212b353f4a56616d7986929eaba79b8f8276695d5044372a1e110500000000000000000000000000060d151c242b333b434d56606b75818c98a4ab9f93877b6f63574a3e3125180c000000000000000000000000000000000013202c3946535f6c798181818181818181818181818181818181818995a2a0938681818181818181818181818181818181818176695d5043362a1d10000000000000000000000000010b141d262f38404850575e656b72777d82868a8e919497999a9c9d9e9e9e9e9d9d9b9a989693908d8984807b756f69635c554d453d352c241b11080000000000000000000000000000000000000000000000000000000008141f2b37434f5a66727e8a96a1a99d9185796d76838f9ba7a69a8e82766a5f53473b2f23180c00000000000000000000000000000000000000000000000000000000000000000003101c2935424e5b6874818d9aa7ac9f9386796d6054473a2e2115080000040e171f262c30323231302f2e2d2c2b3643505c6976838f9ca9aca09386796d6053463a2d2b2c2d2e2f313232302d2821191007000000111e2a3744515d6a7784909da2a29a8d8073707a838b92999ea19f9e9d9d9ea0a2a5a8a5a19c96908980786e655b51473c31261b10040000000013202c3946535f6c7986938b7e7a7a7a7a7a7a7a7a7a7a7a7a7e8b9386796c5f5346392c20130013202c3946525f6b777a7a7a7a7a7a7a7a839090837a7a7a7a7a7a7a7a776b5f5246392c20130013202c3946535f6c7986938c807366594c403326190d000c18242f3a444d54595e63686d72777c81868b90959a9fa3a5a09b96918c87827c77736d69635e5a54504a45403b36312c27221d18130e080200000000000000030a10151a1f24292e33383d42474c51565b60656a6f74797e83888d92979ca1a6a29d98948f8a85807b76716c67625d58534b42382d21160a00111e2b3744515d6a7784919ea2a2968a7d706d7680888f969ca19f9e9e9e9ea0a2a5a9a6a39f99938b837970655b50453a2e23170b00000000000000000000000000000000000000000000000008131e29333e49545f69747f8a959f978c82776c61564b40362b20150a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005101a252e373e434646464646464646464646464646464646464646464646464646464646464646464646464646464646464646433e372e251b1005000000000000030f1a252f3a454f59636d767f878f979da3a9a49f9b989695959596989a9ea3a8a49e9790887f766d63594f453a30251a0f040000000000000f1b27333f4a545c626364656566676869665f554a3e32261a0d0100000000070f19232e3945515d6a76838f9ca8aa9e9185786b5f5245392c1f13060000000000000000000000000000030a12192129313a444e5964707b8793a0aca4978b7e7266594d4034271b0e010000000000000000000000000000000013202c3946535f6c79868e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e919aa5a3988f8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8376695d5043362a1d1000000000000000000000000000020b141d262e363e454c535a60666c71767a7e8285888a8c8e8f909191919191908f8d8b898784817c78746f6a645e58514a433b332b231a12090000000000000000000000000000000000000000000000000000000000030f1b26323e4a56616d7985919ca8a295897d717a87939faba195897d71665a4e42362a1f130700000000000000000000000000000000000000000000000000000000000000000006121f2b3844515d6a7683909ca9aa9d9184776b5e5245392c1f1306000000050d141b2023252524232221201f2b3744515d6a7784909daaada094877a6d6154473b2e212021222324252524211c160f0700000000121e2b3844515e6b778491969696968c7f7368707981878d93979a9c9e9fa0a09f9e9c9995918b857e766e665d53493f352a20150a000000000013202c3946535f6c7986938b7e716d6d6d6d6d6d6d6d6d6d717e8b9386796c5f5346392c201300111e2a37434f5a656c6d6d6d6d6d6d6d7683909083766d6d6d6d6d6d6d6c655a4f43372a1e110013202c3946535f6c7986938c807366594c403326190d0007131e28323b43494e52575c61666b70757a7f84898e93989da2a6a19c97928d88837e79746f6a65605b56514c47423d38332e29241f1a130c030000000000050d151b20252a2f34393e43484d52575c61666b70757a80858a8e94999ea3a5a09c97928d88837e79746f6a65605b56514c47413930261b100500121e2b3845515e6b77849195959595897c6f646d767e858b9095989b9d9f9f9f9f9e9c9a97938e88817970675e54493f34281d1206000000000000000000000000000000000000000000000000010c17222d37424d58636d78838e999e93887d73685d52473c32271c11060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306090b0d0e0e0f0f0e0d0c0a080603000000000000000000000000000009131c252c3237393939393939393939393939393939393939393939393939393939393939393939393939393939393939393937322c251c1309000000000000000008131e28333d47515b646d757d858c92989da1a4a7a5a3a2a2a2a2a4a7a5a29d99938c857e766d645b51473d33291e130800000000000000121e2b3744505b666e707171727374757571665a4e4235281c0f03000000000007111d2935424e5b6774818e9aa7aca09386796d6053473a2d20140700000000000000000000000000000000070f171f28323d48535f6b7783909ca2a29a8e8275685c4f4236291c10030000000000000000000000000000000013202c3946535f6c7986939b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9ca2abaaa19c9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b908376695d5043362a1d100000000000000000000000000000020b141c242c343b42494f555b60656a6e7275787b7d8081828384848584848382817e7d7a7774706c68635e59534d464038312922191108000000000000000000000000000000000000000000000000000000000000000a16222d3945515d6874808c98a3a69a8d81757e8b97a3a89c9084786d6155493d32261a0e020000000000000000000000000000000000000000000000000000000000000000000815212e3a4753606c7985929eaba79b8e8275695c5043362a1d110400000000030a0f1417181817161514131f2c3845525e6b7885919eabaea195887b6e6255483c2f22151415161718181715110b050000000000131f2c3945525f6b78858989898989897e7165676f767c82878a8d909192939392918f8c8985807a736c655c544a41372d23190e03000000000013202c3946535f6c7986938b7e7165606060606060606065717e8b9386796c5f5346392c2013000f1b27333e49535b606060606060606976839090837669606060606060605b53493e33271b0f0013202c3946535f6c7986938c807366594c403326190d00010c16202931383d42474c51565b5f64696e73787d82878c91969ba0a5a39e99948f8a85807b76716c67625d58534e49443f3a35302b251e150c02000000050e171f262c31363b40454a4f54595e63686d72777c81868b90959a9fa4a39f9a95908b86817c77726d68635e59544f4b46413c362f271e140a0000131f2c3946525f6c78858888888888887b6f62646c737a8085898c8f919292939291908d8a87827c766f675e554c42382d22170c010000000000000000000000000000000000000000000000000005101b26313b46515c67717c87929d9a8f84796e64594e43382e23180d020000000000000000000000000000000004080b0c0c0b0804000000000000000000000000000000000105090d10131517191a1b1b1b1b1a191715120f0b07020000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a27211b130a010000000000000000010c17212b353f49525b636b737a81878c9195989b9d9e9f9f9f9e9d9b9995928d88827b746c645b52493f362c21170c020000000000000013202c3946535f6c787c7d7e7f8081828276695d5044372b1e12060000000000000d1a2734404d5a6773808d9aa6ada194877a6d6154473a2e2114070000000000000000000000000000000000050d16202b37434f5b6874818d959595959083776a5d5044372a1e11040000000000000000000000000000000013202c3946535f6c798693a0a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a7abb3b1aaa6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a69d908376695d5043362a1d10000000000000000000000000000000020a121a222930373e444a4f54595e6266696c6f7173747677777778777776757472706e6b6864605c57524d47423b352e271f181007000000000000000000000000000000000000000000000000000000000000000005111d2934404c58646f7b87939faa9d918579828e9ba7a3978c8074685c5044392d211509000000000000000000000000000000000000000000000000000000000000000000000b1824313d4956626f7b8894a1ada5988c7f73665a4d4134281b0f0200000000000003070a0c0c0b0a090813202c3946535f6c7986929facafa296897c6f6356493d3023160a08090a0b0c0b08050000000000000013202c3946535f6c787c7c7c7c7c7c7c7b70635d646b71767a7e818385868686868482807d79746f69625a534a42382f251b110700000000000013202c3946535f6c7986938b7e7165585353535353535865717e8b9386796c5f5346392c2013000a16212d3741494f5353535353535c69768390908376695c5353535353534f4941372d21160a0013202c3946535f6c7986938c807366594c403326190d0000050e171f262c31363b40454a4f54595e63676c71767b80858a8f94999ea3a5a09b96918c87827d78736e69645f5a55504b46413c362f271e140a0000010c16202931383d42474c51565b60656a6f74797e83888d92979ca1a6a29d98938e89847f7a75706b66615c57524e49443f3a35302b251e150c02000013202c3946525f6c777b7b7b7b7b7b7b796d615a61686e74787c808284858686868483817e7b76716b645d554c433a30261b110600000000000000000000000000000000000000000000000000000009141f2a353f4a55606b75818b96a1968b80756a60554a3f34291f14090000000000000000000000000000030a10141719191815100a0400000000000000000000000105090d1115191c1f2224262728282828272524211f1b17130e090300000000000000000000010910161a1e1f2020202020202020202020202020202020202020202020202020202020202020202020202020202020201f1e1b1610090100000000000000000000050f19232d374049515a61696f767b8185898c8e909192929292908f8c8986817c767069625a524940372d241a0f050000000000000000131f2c3945525f6b78858a8b8c8d8d8e85786c5f53473a2e23170e0704030304060e1a2734404d5a6773818d9aa6aea194877a6d6154473a2e211407000000000000000000000000000000000000040f1a2733404c5966727f88888888888884776b5e5145382b1e12050000000000000000000000000000000013202c3946535f6c798693999999999999999999999999999999999aa1aaa89f9a99999999999999999999999999999999908376695d5043362a1d1000000000000000000000000000000000000810171f262c36414b545b5e5e5e5e5e5f62646668696a6a6b6b6b6a6a69676663615e5e5e5e5e5e5c554c42372b231c150d06000000000000000000000000000000000000000000000000000000000000000000000c1824303b47535f6b76828e9aa6a195897d86929faa9e93877b6f63574c4034281c1005000000000000000000000000000000000000000000000000000000000000000000020f1b2734404c5965727e8b97a3aea295897c7064574b3e3225190c0000000000000000000000000000000714212d3a4753606d7a8693a0adb0a3978a7d7064574a3d3124170b000000000000000000000000000000121e2b3744505b666e6f6f6f6f6f6f6f6f695f545960656a6e7274767879797979787673706d68635d57504941382f261d13090000000000000013202c3946535f6c7986938b7e7165584b474747474b5865717e8b9386796c5f5346392c20130005101b252f373e4446474747474f5c69768390908376695c4f4747474746443e372f251b10050013202c3946535f6c7986938c807366594c403326190d000000050d151b20252a2f34393e43484d52575c61666b6f74797e83888d92979ca1a6a29c97928d89847e79746f6a65605b56514c47413930261b10050007131e28323b43494e53585d62676c71767b80858a8f94999ea3a5a09b96918c87827d78736e69645f5b56514c47423d38332e29241f1a130c03000000121e2b37434f5b666d6e6e6e6e6e6e6e6d675c51575d63686c7073767778797979787674726e6a66605a534b433a31281e140a00000000000000000000000000000000000000000000000000000000030d18232e39444e59646f7a848f9a9c92877c71665b51463b30251b1005000000000000000000000000050e151b2024262624211c150e07010000000000000105090d1116191d2125292c2e313234353535343332302e2b27231f1a140e080100000000000000000000050a0e111313131313131313131313131313131313131313131313131313131313131313131313131313131313131313110e0a050000000000000000000000000007111b242e373f484f575e646a7074797c7f828385868686858482807d7975706b655e57504840372e251b1208000000000000000000111e2a3744505d6976828f9898999a94877b6f63574b3f34292018141110101113171f2a36424f5b6874818e9ba7ada094877a6d6154473a2e211407000000000000000000000000000000000000000c1825323f4b5865717b7b7b7b7b7b7b7b766a5e5145382b1e12050000000000000000000000000000000013202c3946535f6c79868c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8f99a4a2978e8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8376695d5043362a1d10000000000000000000000000000000000000060d16222f3b47535d666b6b6b6b6b6a645e595b5c5d5e5e5e5e5d5d5c5b595d646a6b6b6b6b6b675e53483c2f23160a03000000000000000000000000000000000000000000000000000000000000000000000007131f2b37424e5a66727d8995a1a5998d818a96a3a59a8e82766a5e53473b2f23170c0000000000000000000000000000000000000000000000000000000000000000000006121f2b3743505c6875818d9aa6ab9f9286796d6154483b2f23160a0000000000000000000000000000000815222e3b4855616e7b8894a1acaca4988b7e7165584b3e3225180c0000000000000000000000000000000f1b27333f4a545c6162626262626262625e574d4e545a5e6265686a6b6c6c6c6c6b696764615c58524c453e372f261d140b010000000000000013202c3946535f6c7986938b7e7165584b3e3a3a3e4b5865717e8b9386796c5f5346392c2013000009131d252d33373a3a3a3a434f5c69768390908376695c4f433a3a3a3a37332d251d1309000013202c3946535f6c7986938c807366594c403326190d00000000030a10151a1f23282d32373c41464b50555a5f64696e73777c81868b90959a9fa4a39e99948f8a85807b76716c67625d58534b42382d21160a000c18242f3a444d54595e63686d72777c81868b90959a9fa4a39e99948f8a85807b76716c67635e59544f4a45403b36312c27221d18140e0802000000000f1b27333f4a545c6161616161616161615d554b4c52575c606467696b6c6c6c6c6b6a6865625e5a554f48413931281f160c02000000000000000000000000000000000000000000000000000000000007121c27323d48525d68737e89939e988e83786d62574d42372c21160c0100000000000000000000050e1720272c303333312d272019120c07050405070a0d1115191d22262a2d3135383b3d3f4141424241403f3d3a37342f2a252019130c0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121c252d363e454c53595f64686c707375777879797978777573706d69655f5a544d463e362e251c1309000000000000000000000f1c2835414e5a6773808c98a5a6a3978b7f73675c50453b322a24201e1d1c1d1f2328313b46525e6a7783909ca9ac9f9286796c605346392d201307000000000000000000000000000000000000000a1724303c495560696e6e6e6e6e6e6e6e6d655a4e4236291d10040000000000000000000000000000000013202c3946535f6c797f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f8895a2a093867f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f76695d5043362a1d10000000000000000000000000000000000000000b1724313d4a57636f7878787878766f69625b5550515151515150535a61686f7678787878787064574b3e3225180b000000000000000000000000000000000000000000000000000000000000000000000000020e1a26323e4955616d7884909ca89d928c909ba6a195897d71655a4e42362a1f1307000000000000000000000000000000000000000000000000000000000000000000000a16222e3b47535f6c7884919da9a79b8f83766a5e5145382c2013070000000000000000000000000000000916232f3c4955626f7b8895a0a0a0a0988c7f7265594c3f3326190d0000000000000000000000000000000b17222e38424b51555555555555555555534d4543494e5256595b5d5e5f5f5f5f5e5d5b5854504c47413b342d251d140b02000000000000000013202c3946535f6c7986938b7e7165584b3e3d3d3e4b5865717e8b9386796c5f5346392c201300000b151f282f363a3d3d3d3d434f5c69768390908376695c4f43362d2d2d2b27221b130b01000013202c3946535f6c7986938c807366594c403326190d00000000000004090e13181d22272b30353a3f44494e53585d62676c71767a8084898e93989da2a5a09b96918c87827d78736e69645d54493e3226190d00101c2834404c565f656a6f74797e83888d92979ca1a6a19c97928d88837e79746f6b66615c57524d48433e39342f2a25201c17120d08030000000000000b17222d38424a51545555555555555554514b4341464c5054575a5c5e5f5f5f5f5e5d5b5956524e49443d372f271f160d04000000000000000000000000000000000000000000000000000000000000000b16202b36414c56616c77828d979f948a7e74695e53483e33281d1208000000000000000000010c17202931383d3f3f3d38322a241d181411111214171a1d21252a2e32363a3d4144474a4c4d4e4e4e4e4d4b494743403b36312b241e1710080000000000000000000000000000000000000000000000000000000003060707070707070707050300000000000000000000000000000000000000000000000000000000000000000000000a131b242c333b42484e53585c606366686a6b6c6c6c6b6a696764615d59544e48423b342c241c130a01000000000000000000000d1926323f4b5764707c8995a1ada79b8f84786d62574d443b35302c2a29292a2c2f333a434d57636e7a87939fabaa9d9184776b5e5245382c1f1206000000000000000000000000000000000000000814202c38434e575e6161616161616161605b53493d32261a0e0100000000000000000000000000000000121f2b3844515d687172727272727272727272727272727272727b8895a2a093867972727272727272727272727272727272726f665a4e4235291c0f000000000000000000000000000000000000000b1824313e4b5764717e85858585817a736d666059534c464a50575e656c737981858585857e7265584c3f3225190c000000000000000000000000000000000000000000000000000000000000000000000000000915212d3944505c6874808b97a3a49c999ba2a89c9084786d6155493d31261a0e02000000000000000000000000000000000000000000000000000000000000000000020e1a26323e4b57636f7b8894a0aca4988b7f73675a4e4235291d10040000000000000000000000000000000a1724303d4a5663707d899393939393938d8073675a4d4034271a0e01000000000000000000000000000006111c263039404548494949494949494947423b383d4246494c4f50525353535252504e4b4844403b363029221b130b0200000000000000000013202c3946535f6c7986938b7e7165584b4a4a4a4a4b5865717e8b9386796c5f5346392c20130006121d27313a41474a4a4a4a4a4f5c69768390908376695c4f43362920201f1b1610090100000013202c3946535f6c7986938c807366594c403326190d000000000000000002070c11161b20252a2f33383d42474c51565b60656a6f74797d83888c91969ba0a5a29d98938e89847e7a756f665a4e4235291c0f00121f2b3844515d6871767b80858a8f94999ea3a49f9a95908b86817c77736e69645f5a55504b46413c37322d28241f1a15100b0601000000000000000006111c262f383f45484848484848484848454039353b4044484b4e50515253535252504f4c4a46423d38322c251d150d040000000000000000000000000000000000000000000000000000000000000000040f1a242f3a45505a65707b86919b9b90857a70655a4f443a2f24190e03000000000000000007131e29323b43494c4c49433c352f2924201e1e1f202326292d31363a3e42464a4d515456585a5b5b5b5a59585653504c47423c362f28211a110800000000000000000000000000000000000000000000000000060c10121414141414141414120f0b050000000000000000000000000000000000000000000000000000000000000000000109121a222930373d42484c5054575a5c5d5e5f5f5f5f5e5c5a5855514d48433d373129221a120a0100000000000000000000000a16232f3b4854606c7985919da8aca095897e73695f564d46403c3937363637383b3f454c555e6974808b97a3afa79a8e8275695c5043362a1d11040000000000000000000000000000000000000006121d27323c454d53555555555555555554504941372c21150a0000000000000000000000000000000000101c2834404c565f65656565656565656565656565656565656f7b8895a2a09386796c65656565656565656565656565656565645d54493e3226190d000000000000000000000000000000000000000b1724313e4a57636f79838c92928c857e78716b645e5751545b626970777d848b92928d837a7064584b3e3225180c0000000000000000000000000000000000000000000000000000000000000000000000000005101c2834404b57636f7b87929ea7a7a6a7a7a3978b8074685c5044392d2115090000000000000000000000000000000000000000000000000000000000000000000007121e2a36424e5b67737f8b97a4aca094887b6f63574b3e3226190d010000000000000000000000000000000b1824313e4b5764717d86868686868686868174675b4e4135281b0e020000000000000000000000000000000a141e272e35393c3c3c3c3c3c3c3c3c3a36312c31363a3d40424445464646464543413f3c38342f2a241e171009010000000000000000000013202c3946535f6c7986938b7e7165585757575757575865717e8b9386796c5f5346392c2013000b17232e39434c525657575757575c69768390908376695c4f4336291c14120f0b05000000000013202c3946535f6c7986938c807366594c403326190d0000000000000000000000050a0f14191e23282d32373b40454a4f54595e63686d72777c81868b9094999ea3a39e99948f8a858176695d5043362a1d100013202c3946535f6c7982878c91969ba0a5a29d98938e8985807a76716c67625d58534e49443f3a35302b27221d18130e09040000000000000000000000000a141d262e34383b3b3b3b3b3b3b3b3b39352f2a2f34383c3f41434545464646454442403d3a36322d27211a130b030000000000000000000000000000000000000000000000000000000000000000000008131e28333e49545f69747f8a959f978c81766c61564b40362b20150a00000000000000000c18242f3a444d545859554e47403a34302d2b2a2b2d2f3236393d42464a4e5256595d60636567676868676664625f5c58534d47413a332c231a100500000000000000000000000000000000000000000000030b12171c1f20202020202020201f1b161009010000000000000000000000000000000000000000000000000000000000000000000810171e252b31373c4044484b4d4f51525253525251504e4b4845413c37322c261f1810080000000000000000000000000007131f2c3844505c6874808c98a3afa69b90857b71685f58514c48454443434345474b50565e67707a85909ca7afa3978b7e7266594d4134281b0f02000000000000000000000000000000000000000b17232e39434c5358585858585858585858554f463c32261b0f03000000000000000000000000000000000c18242f3a444d5458595959595959595959595959595959626f7b8895a2a09386796c5f59595959595959595959595959595958534b42382d21160a000000000000000000000000000000000000000916222f3b47535e677079838c9597908a837c766f69625b5f666d747a81888f96978d847a71685e53483c2f23170a00000000000000000000000000000000000000000000000000000000000000000000000000000c17232f3b47525e6a76828e999a9a9a9a9a9a92877b6f63574b4034281c1004000000000000000000000000000000000000000000000000000000000000000000000b17232f3b47535f6b77838f9ba7a89c9084786b5f53473b2f22160a000000000000000000000000000000000b1724313e4a5763707979797979797979797973675a4e4135281b0e02000000000000000000000000000000020c151d24292d2f2f2f2f2f2f2f2f2f2e2a2521262a2e31333637383939393938373532302c28241f19130d0600000000000000000000000013202c3946535f6c7986938b7e7165636363636363636365717e8b9386796c5f5346392c2013000f1c28343f4b555d6363636363636369768390908376695c4f4336291c1005030000000000000013202c3946535f6c79868686807366594c403326190d0000000000000000000000000003080d12171c21262b30353a3f43484d52575c61666b70757a7f84898e93989ca1a5a09b96908376695d5043362a1d100013202c3946535f6c798692979ca1a5a09b96918c88837d79746f6a65605b56514c47423d38332f2a25201b16110c07020000000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2d29241e23282c2f323536383939393938373533312e2a26211c160f09010000000000000000000000000000000000000000000000000000000000000000000000010c17222d37424d58636d78838e999e93887d72685d52473c31271c110600000000000000101c2935404c565f65656058524b45403c393837383a3c3f4246494e52565a5e6266696d6f72737475747473716f6c68635e59524c453d352c22170c010000000000000000000000000000000000000000030c151c23282b2d2d2d2d2d2d2d2d2b27221b130b01000000000000000000000000000000000000000000000000000000000000000000050d141a20262b3034383b3e41424445464646454443413f3c3935302c26211b140d06000000000000000000000000000003101c2834404c58646f7b87929da8aca1978d837a7169635d585452504f4f505154575c61687079828c97a2ada99e92867a6e62564a3d3125180c00000000000000000000000000000000000000000f1b28343f4b555e6465656565656565656560584e43372b1f13060000000000000000000000000000000007131e28323b43484b4c4c4c4c4c4c4c4c4c4c4c4c4c4c55626f7b8895a2a09386796c5f534c4c4c4c4c4c4c4c4c4c4c4c4c4c4b47413930261b10050000000000000000000000000000000000000006131f2b36414c555e67717a838c959b948e87817a746d666a71787e858c939a978e857b72685f564c42372b1f1307000000000000000000000000000000000000000000000000000000000000000000000000000007131e2a36424e5965717d898d8d8d8d8d8d8d8d82766a5e52473b2f23170c0000000000000000000000000000000000000000000000000000000000000000000005101c28333f4b57636f7b87939faba3978b8073675b4f43372b1f1206000000000000000000000000000000000916222f3b47535e676c6c6c6c6c6c6c6c6c6c6961564b3f3226190d0000000000000000000000000000000000030b12181d20222222222222222222211e1a151a1e212427292a2c2c2c2c2c2b2a282623201c18130e08020000000000000000000000000013202c3946535f6c7986938b7e7170707070707070707070717e8b9386796c5f5346392c201300121e2b3844505c676f70707070707070768390908376695c4f4336291c10030000000000000000131f2c3946525f6b76797979797165584c3f3326190c00000000000000000000000000000001060b10151a1f24292e33383d42474b50555a5f64696e73787d82878c91969ba0a49d908376695d5043362a1d100013202c3946535f6c798693a0a39e9994908b86817c77726d68635e59544f4a45403b37322d28231e19140f0a05000000000000000000000000000000000000020a11181c20212222222222222222201d1813181c202326282a2b2c2c2c2c2b2a292724211e1a15100b04000000000000000000000000000000000000000000000000000000000000000000000000000005101b26313b46515c67717c87929d9a8f84796e63594e43382d23180d02000000000000121f2b3844515d6871716a635c56514c484644444546484b4e52565a5e62666a6e7276797c7e8081828181807e7b78746f6a645d564f473e33281d110500000000000000000000000000000000000000010b151e272e34383a3a3a3a3a3a3a3a37332d251d13090000000000000000000000000000000000000000000000000000000000000000000002090f151a1f24282c2f323436373839393939383634322f2c2925201b150f0903000000000000000000000000000000000c1824303b47535f6a75818c97a1aca99f958c837b746e6864615e5d5c5c5d5e6063676c737a828b949ea9aea3988d81766a5e52463a2e2115090000000000000000000000000000000000000000111e2b3744505c67707272727272727272716a6054473b2e22150900000000000000000000000000000000010c16202931383c3f3f3f3f3f3f3f3f3f3f3f3f3f3f4855626f7b8895a2a09386796c5f53463f3f3f3f3f3f3f3f3f3f3f3f3f3e3b362f271e140a0000000000000000000000000000000000000000020e1a25303a434c555f68717a838c959f99928c857e7871757c838990979e988e857c726960564d443a30261a0f030000000000000000000000000000000000000000000000000000000000000000000000000000020e1a25313d4955606c788181818181818181817d71655a4e42362a1e1307000000000000000000000000000000000000000000000000000000000000000000000a16212d3844505c6873808b97a3aa9f93877b6f63574b3f33271b0f030000000000000000000000000000000007131f2b37424c555c5f5f5f5f5f5f5f5f5f5f5e584f453a2e22160a00000000000000000000000000000000000000070d111416161616161616161615120e090e1115181a1c1e1f202020201f1d1c1a1714100c070200000000000000000000000000000013202c3946535f6c7986938b7e7d7d7d7d7d7d7d7d7d7d7d7d7e8b9386796c5f5346392c20130013202c3946535f6c787d7d7d7d7d7d7d7d8390908376695c4f4336291c10030000000000000000111e2a37434f5a646b6c6c6c6c685f54493d3024170b00000000000000000000000000000000000004090e13181d22272c31363b40454a4f54585d62676c71767b80858a8f94999d908376695d5043362a1d100013202c3946535f6c7986939c98938e89847f7a75706b66615c57524d48433f3a35302b26211c17120d080300000000000000000000000000000000000000000000060c101315151515151515151513110c070c101317191b1d1e1f20201f1f1e1c1a1815120e0904000000000000000000000000000000000000000000000000000000000000000000000000000000000009141f2a353f4a55606b75818b96a0968b80756a5f554a3f34291e140900000000000013202c3946535f6c797c756e68625c5855525151515355585b5e62666a6e72767a7e8285888b8d8e8e8e8d8c8a8884807b756f6861595045392e2215090000000000000000000000000000000000000007121d2730393f444747474747474746443e372f251b1005000000000000000000000000000000000000000000000000000000000000000000000004090f13181c1f222527292b2c2c2c2c2c2b2a282623201c19140f0a0400000000000000000000000000000000000007131f2b37424e59646f7a85909aa4aea79e958d867f7974706d6b6a6969696b6d6f73787e848c949da6b0a69c92877b7065594d42362a1e12050000000000000000000000000000000000000000121f2c3845525f6b787e7e7e7e7e7e7e7e7c6f6356493c302316090000000000000000000000000000000000050e171f262c30323232323232323232323232323c4855626f7b8895a2a09386796c5f534639323232323232323232323232322f2b251e150c0200000000000000000000000000000000000000000008131e28313a434d565f68717a838d969f9d97908a837c80868d949ba2988f867c736a60574e443b32281e1409000000000000000000000000000000000000000000000000000000000000000000000000000000000915212c3844505c6771737373737373737373736c6155493d31251a0e0200000000000000000000000000000000000000000000000000000000000000000004101b26323e4955616c7884909ca8a59a8e82766b5f53473b2f23170b0000000000000000000000000000000000030e1a25303a434b5053535353535353535353514d463d33281d12060000000000000000000000000000000000000000010507090909090909090909080602000205080b0e1011121313131312110f0d0a070400000000000000000000000000000000000013202c3946535f6c7986938f8a8a8a8a8a8a8a8a8a8a8a8a8a8a8f9386796c5f5346392c20130013202c3946535f6c79868a8a8a8a8a8a8a8b93908376695c4f4336291c100300000000000000000e1a26323e48525a5f5f5f5f5f5d564d43382c201408000000000000000000000000000000000000000003080c11161b20252a2f34393e43484d52575c60656a6f74797e83888d92908376695d5043362a1d100013202c3946535f6c798693918c87827d78736e69645f5a55504b47423d38332e29241f1a15100b060100000000000000000000000000000000000000000000000000000407080808080808080808070401000004070a0d0f1012121313131211100e0b09050200000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d18232e39444e59646f7a848f9a9c91877c71665b50463b30251a1005000000000013202c3946535f6c79868079736d6864615f5e5d5e5f6164676a6e72767a7e82868a8e929597999b9b9b9a999794908c86807a736b61564a3e3125180b000000000000000000000000000000000000010d18242f39424a5053535353535353534f4941372d21160a0000000000000000000000000000000000000000000000000000000000000000000000000003080c101316191b1d1e1f1f201f1f1e1d1b191714100c08040000000000000000000000000000000000000000030e1a26313c48535e69747e88929ca5ada79f97918a85817d7a787676767677797c8084898f969ea6afa79e948a80756a5f54483d3125190d010000000000000000000000000000000000000000121f2c3845525f6b78858c8c8c8c8c8c897c6f6356493c30231609000000000000000000000000000000000000050d151b20242526262626262626262626262f3c4855626f7b8895a2a09386796c5f5346392c262626262626262626262625231f1a130c0300000000000000000000000000000000000000000000020c161f28313a434d565f68717a848d969fa29b948e878a91989fa29990867d746a61584e453c322920160d02000000000000000000000000000000000000000000000000000000000000000000000000000000020e1a25303b454d555f6567676767676767676766625a4f44382d211509000000000000000000000000000000000000000000000000000000000000000000000a15212c37434e5a66717d8995a0aca095897d71665a4e42362a1e130700000000000000000000000000000000000009141e28313940444646464646464646464645413b342b21170c010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693939393939393939393939393939393939386796c5f5346392c20130013202c3946535f6c7986939393939393939393908376695c4f4336291c100300000000000000000a16212c3740484f5253535353514c443b31271b10040000000000000000000000000000000000000000000001060b1014191e23282d32373c41464b50555a5f63686d72777c81868b8376695d5043362a1d100013202c3946535f6c79868a85807b76716c67625d58544f4a45403b36312c27221d18130e090400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007111c27323d48525d68737e89939e988d83786d62574c42372c21160b010000000013202c3946535f6c79868a847e7974706e6c6a6a6b6c6e7073777a7e82868a8f93969a9ea1a4a4a2a1a1a1a3a3a09c97928b857d7266594c3f3326190d00000000000000000000000000000000000005111d2935404b545c60606060606060605b53493e33271b0f0200000000000000000000000000000000000000000000000000000000000000000000000000000003070a0c0e1011121313131211100f0d0a07040000000000000000000000000000000000000000000000000914202b37424c57626c76808a939ba3aba9a29c96918c898684838383838486888c90959aa1a8ada69e958c82786e63594e43372c201509000000000000000000000000000000000000000000121f2c3845525f6b7885929898989896897c6f6356493c3023160900000000000000000000000000000000000000030a1014171919191919191919191919222f3c4855626f7b8895a2a09386796c5f5346392c20191919191919191919191817130e0802000000000000000000000000000000000000000000000000040d161f28313b444d565f68717a848d969fa69f9994959ca3a39a90877e746b62584f463c332a20170e040000000000000000000000000000000000000000000000000000000000000000000000000000000005121e2a36424d575f636464646464625b5a5a5a5a5750483e33281c100400000000000000000000000000000000000000000000000000000000000000000005101b27323d49545f6b76828e9aa5a69b8f84786c6155493d32261a0e02000000000000000000000000000000000000020c161f282f3438393939393939393939393835302a22190f050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0d0f0f0f0f0f0f0d0a0600000000000000000000000000000013202c3946535f6c798686868686868686868686868686868686868686796c5f5346392c20130013202c3946535f6c7986868686868686868686868376695c4f4336291c1003000000000000000005101a252e373e43464646464644403a322920150a000000000000000000000000000000000000000000000000000004090e13181c21262b30353a3f44494e53585d62676b70757a808376695d5043362a1d100013202c3946535f6c79837e79746f6a65605c57524d48433e39342f2a25201b16110c0803000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000206090a0a0a0a0a0a0a0a0a08060407090a0a0a0a0a0a0a0a090704000000000000000000000000000000000000000000000000000000000000000000000000000b16202b36414c56616c77828d979f94897e74695e53483d33281d12070000000013202c3946535f6c7986938f8a85817d7a78777777797a7d8083868a8e92979b9fa3a4a09d9a979594949496989b9ea39d968c807366594c403326190d0000000000000000000000000000000000000714202d3945515d666d6d6d6d6d6d6d6c655a4f43372a1e110500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030f1a25303b46505a646e7781899199a0a7ada7a19d9995939190909090919295989ca0a6aca9a39c948c837a70665c52473c31261b0f04000000000000000000000000000000000000000000121f2c3845525f6b7885929fa5a5a396897c6f6356493c3023160900000000000000000000000000000000000000000004080b0c0c0c0c0c0c0c0c0c0c15222f3c4855626f7b8895a2a09386796c5f5346392c20130c0c0c0c0c0c0c0c0c0c0a0703000000000000000000000000000000000000000000000000000000040d161f29323b444d565f68727b848d96a0a0a0a0a0a0a09a91887e756b625950463d342a21180e0500000000000000000000000000000000000000000000000000000000000000000000000000000000000814212d3a46535e697071717171716d655e574f4d4b463e362c21160e060000000000000000000000000000000000000000000000000000000000000000010c17222d38434e5a65707c88939faaa1958a7e73675c5044392d2115090000000000000000000000000000000000000000040d161d23282b2c2c2c2c2c2c2c2c2c2c2c29251f18100700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030b1116191c1c1c1c1c1c1a16110b0400000000000000000000000000131f2c3946525f6b767979797979797979797979797979797979797979766b5f5246392c1f1300131f2c3946525f6b7679797979797979797979797974685c4f4236291c100300000000000000000009131c252c3237393939393938352f2920170e030000000000000000000000000000000000000000000000000000000002070c11161b1f24292e33383d42474c51565b60656a6e737874685c4f4336291d1000131f2c3946525f6b7677726d68635f5a55504b46413c37322d28231e1914100b06010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080e1215171717171717171717151210141617171717171717171614100b050000000000000000000000000000000000000000000000000000000000000000000000040f1a242f3a45505a65707b86919b9b90857a70655a4f44392f24190e0300000013202c3946535f6c7986939b95918d8987858484848587898c8f93969a9ea3a4a09b9894918d8b89888788898b8e92979c998c807366594c403326190d0000000000000000000000000000000000000815222f3b4855616e787a7a7a7a7a7a776b5f5246392c2013060000000000000000000000000000000000000000000000000000000000000000000000000000000003070b0c0d0d0d0d0d0d0d0d0c0a060200000000000000000000000000000000000000000000000000000009141f29343e48525c656e7780878f969ca2a7aba9a5a2a09e9d9c9c9d9e9fa1a4a8aca8a39e98918a827a71685e554a40362b20150a00000000000000000000000000000000000000000000121f2c3845525f6b7885929facb0a396897c6f6356493c302316090000000000000000000000000000000000000000000000000000000000000000000915222f3c4855626f7b8895a2a09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000000000000040d172029323b444d576069727b848e9393939393939392887f756c635950473e342b22180f060000000000000000000000000000000000000000000000000000000000000000000000000000000000000915222f3c4855626e7b7d7d7d7d7d777069615a534b443d352e271f18110a0200000000000000000000000000000000000000000000000000000000000007121d28333e4954606b76828d99a4a69a8f84786d62564b3f33281c1005000000000000000000000000000000000000000000040b12181c1f202020202020202020201f1d19140d0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050d151c222628292929292826221d160e06000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b645a4f43372a1e1100111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6a62574c4033271b0e01000000000000000000010a131a21262a2c2c2c2c2c2b29241e170e050000000000000000000000000000000000000000000000000000000000000000050a0f14191e23272c31363b40454a4f54595e63686c6a62584c4034271b0e00111e2a37434f5a646b6b67625d58534e49443f3a35302b26211c18130e0904000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040c13191e22232424242424242423211e1c2023242424242424242423201c160f08000000000000000000000000000000000000000000000000000000000000000000000008131e28333e49545f69747f8a959f978c81766b61564b40352b20150a00000013202c3946535f6c7986939ca19d99969392919091929496999c9fa3a4a09c98948f8b8884817e7c7b7a7b7d7f82868b90968c807366594c403326190d0000000000000000000000000000000000000915222f3c4855626f7b878787878786796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000001080e1317191a1a1a1a1a1a1a1a1916120d070000000000000000000000000000000000000000000000000000020d18222c36404a535c656d757d848b91969b9fa2a5a8a9aaa9a9a9a9aaaaa8a6a3a09c97928c86807870685f564c43392e24190e0300000000000000000000000000000000000000000000121f2c3845525f6b7885929facaca396897c6f6356493c302316090000000000000000000000000000000000000000000000000000000000000000000915222f3c4855626f7b8895a2a09386796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000000000000000050e172029323b454e576069727b85868686868686868680766d635a51473e352c22191006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000915222f3c4855626f7b868a8a8a89827a736c645d564e474039312a231b140d0500000000000000000000000000000000000000000000000000000000040e19242f39444f5b66717c87939eaa9f94897e73675c51453a2e23170b000000000000000000000000000000000000000000000001070c10121313131313131313131312100d080200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d171f272d32353636363635322e2820180f0500000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5a52483e32261a0e000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5e5850463b2f23170b0000000000000000000000010910161a1e1f202020201f1c18130c05000000000000000000000000000000000000000000000000000000000000000000000003080d12171c21262b2f34393e43484d52575c5f5e5950463b3024180c000e1a26323e48525a5f5f5b56514c47423d38332e2924201b16110c070200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d161e252a2e3030303030303030302e2a272c2f30303030303030302f2c27211a110800000000000000000000000000000000000000000000000000000000000000000000010c17222d37424d58636d78838e999e93887d72675d52473c31261c1106000013202c3946535f6c79838b91979ca1a2a09e9e9d9e9fa0a2a5a39f9c9894908c88837f7b7875726f6e6e6e7073767a7f858b8c807366594c403326190d0000000000000000000000000000000000000915222f3c4855626f7b889494949386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000000030b131a1f2326262626262626262625221e181109000000000000000000000000000000000000000000000000000006101a242e38414a535c646b727980858a8f9396999b9d9e9f9f9f9f9e9d9b999793908b87817b746d665e564d443a31271d12080000000000000000000000000000000000000000000000121f2c3845525f6b7885929fa0a0a096897c6f6356493c302316090000000000000000000000000000000000000000000000000000000000000000000915222f3c4855626f7b8895a2a09386796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000000000000050e172029333c454e57606972797979797979797979766d645b51483f352c231a100700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000815212e3a47535f6a747d869097938c857d766f686059524a433c342d261e1710080000000000000000000000000000000000000000000000000000010b15202b35404b56616c77828d99a4a4998e83786d61564b3f34291d120600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a151f2931393e4142424242423f39322a20160c01000000000000000000000a16212c3740484f525353535353535353535353535353535353535353524f4840372c21160a000a16212c3740484f52535353535353535353535353524d463e34291e130700000000000000000000000000050a0e11131313131312100c0701000000000000000000000000000000000000000000000000000000000000000000000000000001060b10151a1f24292e33383c41464b5053524e473e342a1f1307000a16212c3740484f52524f4a45403b36312c28231e19140f0a05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b151f282f363a3d3d3d3d3d3d3d3d3d3a3532383c3d3d3d3d3d3d3d3d3c38332b231a10050000000000000000000000000000000000000000000000000000000000000000000005101b26313b46515c67717c87929d998f84796e63584e43382d22170b0000121f2b3844515d68717980868c9195999b9d9fa0a09f9d9b9996938f8c8884807b77736f6c68656361616263666a6e73798087807366594c403326190d0000000000000000000000000000000000000915222f3c4855626f7b8895a0a09386796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000020b151d252b30323333333333333333322f2a231b1209000000000000000000000000000000000000000000000000000009131c262f38414a525961686e74797e83868a8c8e90919292929291908f8d8a8784807b76706a635c544c443b32281f150b000000000000000000000000000000000000000000000000121f2c3845525f6b7885929393939393897c6f6356493c302316090000000000000000000000000000000000000000000000000000000000000000000915222f3c4855626f7b8895a2a09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000000000000000000050e17202a333c454e5760696c6c6c6c6c6c6c6c6c6b645b52493f362d231a110700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121f2b37434e58626b747d879099978f888179726b635c554d463f383029221a12080000000000000000000000000000000000000000000000000008121d27323c47525d67727d89949fa89d92887c71665b50453a2e23180c0100000000000000000000000000000000000000000000000000000000000000000004090b0d0d0d0d0d0d0d0d0d0b0804000000000000000000000004090b0d0d0d0d0d0d0d0d0d0b0804000000000000000000000000000005111c27313b434a4e4f4f4f4f4e4a443c32281d12060000000000000000000005101a252e373e4346464646464646464646464646464646464646464646433e372e251a10050005101a252e373e434646464646464646464646464645423c352c22180d02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004090e13181d22272c31363b40444645423c352c22180d020005101a252e373e434646433e3934302b26211c17120d0803000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121d27313a41474a4a4a4a4a4a4a4a4946403d44484a4a4a4a4a4a4a4a48443d352c22170c000000000000000000000000000000000000000000000000000000000000000000000009141f2a353f4a55606b75808b96a0958b80756a5f544a3f33271b0f0300101c2935404c565f676e757a8085898c8f9192939392918f8d8a8783807c78746f6b67635f5c5956555455575a5e63686e757c807366594c403326190d0000000000000000000000000000000000000915222f3c4855626f7b8895a2a09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000009131d272f363c3f40404040404040403e3a352d241b110600000000000000000000000000000000000000000000000000010a141d262f3840484f565d63686e72767a7d8082838585868685858482807e7b77736f6a655f58514a423a322920160d03000000000000000000000000000000000000000000000000121f2c3845525f6b7885868686868686867c6f6356493c302316090000000000000000000000000000000000000000000000000000000000000000000915222f3c4855626f7b8895a0a09386796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050e18212a333c454e575d5f5f5f5f5f5f5f5f5f5f5a524940372d241b110800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030f1b26323c475059626b757e8790999a928b847c756e665f585149423b332c241a1106000000000000000000000000000000000000000000000006101a242f39434e59636e79848f9aa5a1968c81766b60554a3f34281d12060000000000000000000000000000000000000000000000000000000000000000040b101518191a1a1a1a1a1a1a191815100a0400000000000000040b101518191a1a1a1a1a1a1a191815100a040000000000000000000000000916212d38434d555a5c5c5c5c5b564e443a2f23170b000000000000000000000009131c252c32373939393939393939393939393939393939393939393937322c251c130900000009131c252c3237393939393939393939393939393936312a231a1006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002070c11161b20252a2f3438393936312b231a110600000009131c252c3237393937332e29241f1a15100b0601000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17232e39434c52565757575757575756524b474f545757575757575757554f473e33281d110500000000000000000000000000000000000000000000000000000000000000000000030d18232e39434e59646f79848f939391877c71665b5044382b1f1206000c18242f3a444e555c63696f74797c808284858686858482807d7a77736f6b67635f5b5753504c4a4847484a4e52575d646b72797165584c3f3226190c0000000000000000000000000000000000000915222f3c4855626f7b8895a2a09386796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000040f1a252f3941474c4d4d4d4d4d4d4d4d4b463f372d23180c0100000000000000000000000000000000000000000000000000020b141d262e363d444b52575d62666a6e71737577787979797978777573716e6b67635e59534d474038302820170e0400000000000000000000000000000000000000000000000000121f2b3845515e6a767979797979797979786e6255493c2f2316090000000000000000000000000000000000000000000000000000000000000000000915222f3c4855626f7b889393939386796c5f5346392c201306000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f18212a333c454c51535353535353535353524f4940372e251b12090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a15202b343e475059626c757e87919a9d968e878078716a625b544c453e362c23180d02000000000000000000000000000000000000000000040e18222c36404b55606a75808b95a0a49a8f857a6f645a4f44392d22170c0100000000000000000000000000000000000000000000000000000000000000060e151c212426262626262626262624211c150e050000000000060e151c212426262626262626262624211c150e0500000000000000000000000d1925323e4a555f66696969696760564b3f33271b0e0200000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a26211a130a01000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c292520191108000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0f14191e23282b2c2c2a252019110800000000010a131a21262a2c2c2a27221d18130e0904000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c28343f4b555d6363636363636363625d544f5960636363636363636360595045392d211509000000000000000000000000000000000000000000000000000000000000000000000007111c27323d48525d68737e868686868682776c6053463a2d2014070007131e29323c434b52585e63686d7073767779797979777673716e6b67635f5b57534f4b4743403d3b3b3c3e42464c525960686c685f54493d3024170b0000000000000000000000000000000000000915222f3c4855626f7b8895a2a09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000814202c37414b535859595959595959595751493f34291d11050000000000000000000000000000000000000000000000000000020b141c242b333a40464c51565a5e616466686a6b6c6c6c6c6b6a696765625f5b57534e48423c352e261e160e050000000000000000000000000000000000000000000000000000101d2936424e59646b6c6c6c6c6c6c6c6c6c665d52463a2d2114080000000000000000000000000000000000000000000000000000000000000000000915222f3c4855626f7b868686868686796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f18212a333b414546464646464646464646433e372e251c130900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040f19222c353e47505a636c757e88919aa099918a837b746d655e574f483e34291e12070000000000000000000000000000000000000000020c161f29333e48525c67717c87919ca79d93887e73685e53483d32271c110600000000000000000000000000000000000000000000000000000000000000050f1820272d31333333333333333333312d2720170e05000000050f1820272d31333333333333333333312d2720170e05000000000000000000000e1b2835414e5a66717575757572685c4f4336291d10030000000000000000000000010910161a1e1f20202020202020202020202020202020202020201f1e1a161009010000000000010910161a1e1f2020202020202020202020201f1d19140e0700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004080d12171c1e201f1d1a140e07000000000000010910161a1e1f201e1b16110c0702000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000121e2b3844505c676f707070707070706e665b55616b70707070707070706b61564a3d3124180b0000000000000000000000000000000000000000000000000000000000000000000000000b16202b36414c56616c76797979797979776c6053463a2d20140700010c17202a323940474d53585c606467696b6c6c6c6c6b696764625e5b57534f4b47433f3b3734312f2e2f32363b41474f565d5f5d564d43382c2014080000000000000000000000000000000000000915222f3c4855626f7b8895a2a09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000c1824313d48535d646666666666666666635b50453a2e211509000000000000000000000000000000000000000000000000000000020a121a21282f353b40454a4e5255585a5c5d5e5f5f5f5f5e5d5c5a5856534f4b47423d37312a231c140c040000000000000000000000000000000000000000000000000000000e1a26313d48525a5f5f5f5f5f5f5f5f5f5f5c544b4035291d11050000000000000000000000000000000000000000000000000000000000000000000815222f3b4855616d78797979797979766b5f5246392c1f13060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f1821293035383939393939393939393937322c251c130a01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007101a232c353e48515a636c767f88919ba39c958d867e777069615a50463b2f23170a00000000000000000000000000000000000000010a141e28313b454f5a646e79838e98a3a0958b81766c61574c41362c21160b00000000000000000000000000000000000000000000000000000000000000020d17212a32383d4040404040404040403d38322920170c0100020d17212a32383d4040404040404040403d38322920170c010000000000000000000f1c2835424f5b687582828282776a5d5044372a1d110400000000000000000000000000050a0e1113131313131313131313131313131313131313131313110e0a05000000000000000000050a0e111313131313131313131313131312110d090300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002070b0f121313110d0903000000000000000000050a0e111313110f0a0501000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c787d7d7d7d7d7d7d776b5e5865727d7d7d7d7d7d7d7d7265594c3f3226190c000000000000000000000000000000000000000000000000000000000000000000000000040f1a242f3a45505a646b6c6c6c6c6c6c6b655b4f44372b1f12050000050e1720272e353c41474c5054585a5c5e5f5f5f5f5e5c5a5855524f4b47433f3b37332e2b2724222122252a2f363d444c5152504b443b31261b10040000000000000000000000000000000000000915222f3c4855626f7b8895a2a09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000e1b2734404d59656f73737373737373736d62564a3d3124170b0000000000000000000000000000000000000000000000000000000000080f161d242a2f353a3e4245484b4d4f51525253535252514f4e4c4946433f3b36312b261f19120a02000000000000000000000000000000000000000000000000000000000915202b3640484e52535353535353535353504a42392f24190d010000000000000000000000000000000000000000000000000000000000000000000714202d3945515c666c6c6c6c6c6c6c6b645a4f43372a1e1105000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f171e24292c2c2c2c2c2c2c2c2c2c2c2a27211b130a010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008111a232c363f48515a646d767f89929ba09f989089827a736c62574b3f33261a0d0000000000000000000000000000000000000009131c263039434d57616c76808b959fa2988e84796f655a50453a30251a0f040000000000000000000000000000000000000000000000000000000000000008131e29333c43494c4d4d4d4d4d4d4d4c49433b32281e13070008131e29333c43494c4d4d4d4d4d4d4d4c49433b32281e13070000000000000000000f1c2835424f5b6875828f8f84776a5d5044372a1d1104000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c79868a8a8a8a8a85786b5e5865727e8a8a8a8a8a8a7f7265594c3f3226190c0000000000000000000000000000000000000000000000000000000000000000000000000008131e28333e49525a5f5f5f5f5f5f5f5f5a53493e33271b0f03000000050e161d242a30363b4044484b4e50515253535251504e4b4946423f3b37332f2b27221f1b18151416191e242b333a40444644403a32291f150a000000000000000003060707070707070707070915222f3c4855626f7b8895a2a09386796c5f5346392c20130707070707070707070705020000000000000000000000000000000000000000000000000f1b2835424e5b6875808080808080807e7165584b3e3225180b000000000000000000000000000000000000000000000000000000000000050c12191e24292e3236393c3f4143444546464646454443413f3d3a37332f2a25201a140e07000000000000000000000000000000000000000000000000000000000000040f1a242e363d4345464646464646464646443f3830271d12070000000000000000000000000000000000000000000000000000000000000000000004111d2934404a545b5f5f5f5f5f5f5f5f5a52483e32261a0e0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050d13191c1f2020202020202020201f1e1b1610090100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008111a242d363f48525b646d7680899293939393938c857d74675a4e4134281b0e01000000000000000000000000000000000004101a252e38424b555f69737d88929ca49a90867c72675d53483e33291e130900000000000000000000000000000000000000000000000000000000000000000c1824303a454e55595959595959595959554d443a2f24180c000c1824303a454e55595959595959595959554d443a2f24180c0000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000000000000000407080808080808080808080808080808080808080808080808080808080808080808080808080808070400000000000000000000000000000000000000000000000000000000000000000000000000000000000104070808080808080808080704000000000000000000000000000000000000000000000000000000000000000000000206080b0d0f101212131313131211100e0c0a0704000000000000000000000000000000000000000000000000000000000000000000000000000004070808080808080808080806030000000000000000000000000000000000000000000000000000000013202c3946535f6c7986939797979285786b5e5865727e8c979797978c7f7265594c3f3226190c00000000000000000000000000000000000000000000000000000000000000000000000000010c17222c3740494f52535353535353524f4941372d22160b0000000000040b12191f252a2f34383c3f414345464646464543413f3c3936332f2b27231f1b16120f0b0908090d131921282f34383938342f2820170d03000000000000060b0f121414141414141414141415222f3c4855626f7b8895a2a09386796c5f5346392c201414141414141414141414120f0a04000000000000000000000000000000000000000000000f1b2835424e5b6875828d8d8d8d8d8b7e7165584b3e3225180b0000000000000000000000000000000000000000000000000000000000000001070d13181d2226292d303234363738393939393837363433302d2a27231e1a150f0903000000000000000000000000000000000000000000000000000000000000000008121b242c32363939393939393939393937332e271e150b0100000000000000000000000000000000000000000000000000000000000000000000000c18232e38424a5052535353535353524f4840372c21160a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080d101213131313131313131313110e0a0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008121b242d364049525b646d778086868686868686868174675b4e4134281b0e0100000000000000000000000000000000000a16212c37404a545d67717b858f9aa49b92887e746a60564b41372c22170c020000000000000000000000000000000000000000000000000000000000000000101c2935414c57606566666666666666655f564c4034281c1000101c2935414c57606566666666666666655f564c4034281c100000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000000000060c101315151515151515151515151515151515151515151515151515151515151515151515151515151513100c070000000000000000000000000000000000000000000000000000000000000000000000000001070c111315151515151515151513100c07000000000000000000000000000000000000000000000000000000000002070b0f1215171a1c1d1e1f2020201f1f1e1c1b191613100d0904000000000000000000000000000000000000000000000000000000000000000000070c111315151515151515151515130f0b05000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0a49e9285786b5e5865727e8c98a4a4998c7f7265594c3f3226190c000000000000000000000000000000000000000000000000000000000000000000000000000005101b252e373e434646464646464646433e372f251b100500000000000000070e14191f24282c2f323537383939393938363532302d2a26231f1b17130f0a06030000000002080f171e24282b2c2b28241e160e050000000000020a11171c1f2121212121212121212121222f3c4855626f7b8895a2a09386796c5f5346392c2121212121212121212121201e1b160f080000000000000000000000000000000000000000000f1b2835424e5b6875828e9a9a9a988b7e7165584b3e3225180b00000000000000000000000000000000000000000000000000000000000000000002070d11161a1d20232628292b2b2c2c2c2c2c2b29282624211e1b17130e0904000000000000000000000000000000000000000000000000000000000000000000000009121a21262a2c2c2c2c2c2c2c2c2c2c2b28231c150c0300000000000000000000000000000000000000000000000000000000000000000000000007121c2630383f434646464646464646433e372e251a1005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b242e374049525b656e7779797979797979797972675a4d4134271b0e0100000000000000000000000000000000000e1a26323d48525c666f79838d97a09d938980766c62584e44392f251a1005000000000000000000000000000000000000000000000000000000000000000000121f2b3845515d68717373737373737371685d5144382b1e1200121f2b3845515d68717373737373737371685d5144382b1e120000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000000020a11181c20212222222222222222222222222222222222222222222222222222222222222222222222222221201d18120b0300000000000000000000000000000000000000000000000000000000000000000000030b12181d20222222222222222221201c18120a020000000000000000000000000000000000000000000000000004090e13171b1e212426282a2b2c2c2c2c2c2b2a29272523201c1915100b060100000000000000000000000000000000000000000000000000000000030b12181d20222222222222222222211f1c1610090100000000000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00000000000000000000000000000000000000000000000000000000000000000000000000000009131c252c3237393939393939393937332d251d130900000000000000000003080e13181c202326282a2b2c2c2c2c2b2a282623211d1a16130f0b0703000000000000000000050c13181c1e1f1e1c18130c040000000000010b141b22282b2d2e2e2e2e2e2e2e2e2e2e2e2f3c4855626f7b8895a2a09386796c5f5346392e2e2e2e2e2e2e2e2e2e2e2e2d2b27211a120900000000000000000000000000000000000000000f1b2835424e5b6875828e9ba6a5988b7e7165584b3e3225180b00000000000000000000000000000000000000000000000000000000000000000000000105090d111417191b1d1e1f1f20201f1f1e1d1b191715120e0b07020000000000000000000000000000000000000000000000000000000000000000000000000000080f151a1e1f2020202020202020201e1b17110a0300000000000000000000000000000000000000000000000000000000000000000000000000000b141e262d3337393939393939393937322c251c13090000000000000000000000000000000000000000000000000000000000040708080808080808080808070502000000000000000000000000000000000000000000000000000000000000000000010407080808080808080808080704000000000000000000000000000000000000000000000000000000000000000000000000000009121b252e374049535c656b6c6c6c6c6c6c6c6c6c6961564a3e3226190d000000000000000000000000000000000000111d2a36434e5a646e78818b939393938b81776e645a50463c32281d13090000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7980808080808080796c5f5246392c1f130013202c3946535f6c7980808080808080796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2c29231d150c030000000000000000000000000000000000000000000000000000000000000000030d151d24292d2e2e2e2e2e2e2e2e2e2c28231c140c020000000000000000000000000000000000000000000003090f151a1f23272b2e3133353638383939393938373634322f2c2925211c17120c060000000000000000000000000000000000000000000000000000030c151d23292c2e2e2e2e2e2e2e2e2e2e2c27221b130a00000000000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c000000000000000000000000000000000000000000000000000000000000000000000000000000010a131b21272a2c2c2c2c2c2c2c2c2a27211b130b01000000000000000000000002070c101317191c1d1f2020201f1f1d1b191714110e0a07030000000000000000000000000001070c10121312100c070100000000000009131d262d33383a3a3a3a3a3a3a3a3a3a3a3a3a3c4855626f7b8895a2a09386796c5f53463a3a3a3a3a3a3a3a3a3a3a3a3a3a37322c241b1107000000000000000000000000000000000000000f1b2835424e5b6875828e9ba8a5988b7e7165584b3e3225180b00000000000000000000000000000000000000000000000000000000000000000000000000000105080a0c0e101112131313131211100f0d0b080502000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0e1113131313131313131313120f0b0600000000000000000000000000000000000000000000000000000000000000000000000000000000020c141c22272b2c2c2c2c2c2c2c2c2a26211a130a01000000000000000000000000000000000000000000000000000000060c10131515151515151515151514110e0802000000000000000000000000000000000000000000000000000000000001070d11141515151515151515151513100c070000000000000000000000000000000000000000000000000000000000000000000000000009131c252e37414a535b5f5f5f5f5f5f5f5f5f5f5d574f44392e22160a000000000000000000000000000000000000121f2c3945525e6b768086868686868682786f655c52483e342a20160c010000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c79868d8d8d8d8d86796c5f5246392c1f130013202c3946535f6c79868d8d8d8d8d86796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000a141d262e34383b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b39342e271e150a00000000000000000000000000000000000000000000000000000000000000010b151f272f35393b3b3b3b3b3b3b3b3b39342e261e140a000000000000000000000000000000000000000000070e141a20262b2f33373a3d3f4143444546464646454442403e3c3835312d28231d17110a030000000000000000000000000000000000000000000000000b151e272e35393b3b3b3b3b3b3b3b3b3b38332c251c1208000000000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00000000000000000000000000000000000000000000000000000000000000000000000000000000010910161b1e1f202020202020201e1b1610090100000000000000000000000000000004070a0d0f11121313131312110f0d0a080501000000000000000000000000000000000000000000000000000000000000000005101b252f373f4447474747474747474747474747474855626f7b8895a2a09386796c5f53474747474747474747474747474746433d362d23190e030000000000000000000000000000000000000f1b2835424e5b6875828e9ba2a2988b7e7165584b3e3225180b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a11171b1e202020202020201f1e1a161009010000000000000000000000000000000000000000000000000000020a11171c2021222222222222222222201e19140d05000000000000000000000000000000000000000000000000000000030b12181d2022222222222222222221201c18120a020000000000000000000000000000000000000000000000000000000000000000000000010a131c252f3841494f52535353535353535353514d453d33281d1106000000000000000000000000000000000000121f2c3845525e6b76797979797979797870675d534a40362c22180e04000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986939a9a9a9286796c5f5246392c1f130013202c3946535f6c7986939a9a9a9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000006111c262f383f4548484848484848484848484848484848484848484848484848484848484848484848484848484845403930261c110600000000000000000000000000000000000000000000000000000000000007121d273139404548484848484848484845403830261c1106000000000000000000000000000000000000020a11181f262b31363b3f4347494c4e5051525253535252504f4d4b4845413d39342e28221c150d060000000000000000000000000000000000000000000007121d273039404548484848484848484847443e372e241a0f030000000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0e111313131313131313110f0a0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a16222d3741495053545454545454545454545454545455626f7b8895a2a09386796c5f545454545454545454545454545454534f483f352a1f14080000000000000000000000000000000000000f1b2835424e5b6875828e959595958b7e7165584b3e3225180b0000000000000000000000000000000000000000000001070b0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0d0a06000000000000000000000000000000000000000000000000000205080a0c0e0f10111212121111100f0d0b0907040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060b0f121313131313131313110e0a05000000000000000000000000000000000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2d2a251f170f0500000000000000000000000000000000000000000000000000030d151d24292d2e2e2e2e2e2e2e2e2e2e2c28231c140c020000000000000000000000000000000000000000000000000000000000000000000000010a131d262f373e434646464646464646464645413b342b21160c00000000000000000000000000000000000000111d2a36424e5a646b6c6c6c6c6c6c6c6c675e554b41382e241a100600000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0a69f9286796c5f5246392c1f130013202c3946535f6c798693a0a69f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000b17222d38424a51545555555555555555555555555555555555555555555555555555555555555555555555555554514a42382e23170c0000000000000000000000000000000000000000000000000000000000000c18232f39434b51545555555555555554514a42382d22170b0000000000000000000000000000000000030c141b232a31373d42474b4f5356585b5c5e5f5f5f5f5f5e5d5c5a5754514d49443f3a342d261f1810080000000000000000000000000000000000000000000c18232e39424b51545555555555555555544f4940362b2014090000000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1b27333e49535b60616161616161616161616161616161626f7b8895a2a09386796c616161616161616161616161616161615f5a51473c3024180c0000000000000307090b0b0b0b0b0b0b0b0b0f1b2835424e5b6875828888888888887e7165584b3e3225180b0b0b0b0b0b0b0b0b0b090602000000000000000000060d12171a1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1a16110b04000000000000000000000000000000000000000003070b0e121417191b1c1d1e1e1e1e1e1e1d1b1a181613100d090500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009141d262e34383b3b3b3b3b3b3b3b3b3b3a36302921170d030000000000000000000000000000000000000000000000010b151f272f35393b3b3b3b3b3b3b3b3b3b39342e261e140a000000000000000000000000000000000000000000000000000000000000000000000000010b141d252d3337393939393939393939393835302922190f05000000000000000000000000000000000000000e1a26323d48525a5f5f5f5f5f5f5f5f5f5c554c43392f261c12080000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000f1b27333f4a545c6161616161616161616161616161616161616161616161616161616161616161616161616161615c544a3f34281c10030000000000000000000000000000000000000000000000000000000004101d2934404b555d6161616161616161615c544a3f33281b0f03000000000000000000000000000000040d151e262d353c42484e53575b5f626567696a6b6c6c6c6c6b6a686664615d5955504b453f38312a221a11090000000000000000000000000000000000000004101c2834404b545c616161616161616161605a52483c3125190d0000000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c000000000000000000000000000000000000000000000106090b0c0c0c0c0c0c0c0c0c0c0b0905010000000000000000000000000000000000000000000000000000000003070a0c0c0c0c0c0c0c0c0c0c0a0804000000000000000000000000000000000005080b0c0c0c0c0c0c0c0c0c0c0a0804000000000000000000111e2a37434f5b656c6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6f7b8895a2a09386796d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6b63584d4034281b0f0000000002090e1316171818181818181818181b2835414e5b67747b7b7b7b7b7b7b7b7164584b3e3125181818181818181818181715120d07010000000000000710171e2327292929292929292929292929292929292929292929292929292929292929292929292929292929292929292826221d160e060000000000000000000000000000000000050a0f13171b1e21232627292a2b2b2b2b2b2a29282624221f1c1915110c07020000000000000000000000000000000000000000000000000000000000000000010407090b0d0f10111112121211100f0e0c0a080502000000000000000000000000000000000000000000000000000005101b262f383f454748484848484848484846413b33291f1409000000000000000000000000000000000000000000000007121d27313940454848484848484848484845403830261c1106000000000000000000000000000000000000000000000000000000000000000000000000020b131b22272a2c2c2c2c2c2c2c2c2c2c2c29251f18100700000000000000000000000000000000000000000a15212c3640484f525353535353535353504b433a31271d140a000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000121e2b37434f5b666d6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6d665c5044382b1f1206000000000000000000000000000000000000000000000000000000000713202c3945515c676d6e6e6e6e6e6e6e6d665b5044372b1f12050000000000000000000000000000030d161f2730383f464d53595e63686b6f72747677787979797978767573706d6965615c56504a433b342c231b120900000000000000000000000000000000000006131f2c3845515c666d6e6e6e6e6e6e6e6e6c64594d4135281c0f0300000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c000000000000000000000000000000000000000000060c121518191919191919191919191815110c0600000000000000000000000000000000000000000000000000030a0f1417181919191919191919181714100a0400000000000000000000000000050c111517181919191919191919181714100a030000000000000013202c3946525f6b777a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7b8895a2a093867a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a75695c504336291d10000000040c141a1f22242424242424242424242426333f4b57626b6e6e6e6e6e6e6e6e696054483c30242424242424242424242424221e19120b020000000006101922292f333536363636363636363636363636363636363636363636363636363636363636363636363636363636363635322e2820180e040000000000000000000000000000040b10161b1f23272a2d3032343537373838383837363533312f2c2925211d18130d07010000000000000000000000000000000000000000000000000000000005090d101316181a1b1d1e1e1e1e1e1e1d1c1b191714110e0b070300000000000000000000000000000000000000000000000a16222d37414a5054555555555555555555524c453b31261b0f03000000000000000000000000000000000000000000010d18242f39434b5154555555555555555554514a42382d22170b00000000000000000000000000000000000000000000000000000000000000000000000000010910161b1e202020202020202020201f1d19140d06000000000000000000000000000000000000000000040f1a242e363d43464646464646464646443f3931281f150b02000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000013202c3946525f6c777b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b786c6053473a2d201407000000000000000000000000000000000000000000000000000000000814212e3b4754616d797b7b7b7b7b7b7b786c5f5346392d20130600000000000000000000000000010b151f283139414951585e656a6f74787b7e81828485868686858483827f7c7976716d67615b544d463e352d241b110800000000000000000000000000000000000714212d3a4754606d787b7b7b7b7b7b7b7b75695d5043372a1d100400000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00000000000000000000000000000000000000000911181d22242525252525252525252524221d1811090000000000000000000000000000000000000000000000050d141b20232525252525252525252524201c160e0600000000000000000000000810171d21242525252525252525252523201b150e0600000000000013202c3946535f6c798687878787878787878787878787878787878b97a3a1948a87878787878787878787878787878787878376695d5043362a1d100000040d161e252b2f313131313131313131313131313b4650595f61616161616161615e574e4338313131313131313131313131312e2a241d140b020000030e18222c343a3f42424242424242424242424242424242424242424242424242424242424242424242424242424242424242423e39322a20160b00000000000000000000000002090f161c21262b2f33373a3c3f4142434445454544444341403e3b3835312d29241e18120c0500000000000000000000000000000000000000000000000002070c1115191c2022252728292a2b2b2b2b2b2a29272523211e1b17130e0a040000000000000000000000000000000000000000000e1b27333e49535c616161616161616161615e574d42372b1f140800000000000000000000000000000000000000000006111d2935404b555d616161616161616161615c544a3f33281b0f030000000000000000000000000000000000000000000000000000000000000000000000000000050a0f111313131313131313131312100d0802000000000000000000000000000000000000000000000008121c242c323639393939393939393938342e271f160d0300000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000013202c3946535f6c79868888888888888888888888888888888888888888888888888888888888888888888888877a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b88888888888886796d6053463a2d2013070000000000000000000000000009131d27313a434b535b626970767b8084878b8d8f91929293939291908e8c8986827d78736d665f5750473f362d231a1006000000000000000000000000000000000714212e3a4754616d7a8788888888888884776a5d5044372a1d110400000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c0000000000000000000000000000000000000009121b23292e3132323232323232323232312e29221b1209000000000000000000000000000000000000000000040e171f262c3032323232323232323232302c2720180f0600000000000000000008111a22282d3132323232323232323232302c2720180f05000000000013202c3946535f6c79869394949494949494949494949494949494969da8a69c9594949494949494949494949494949494908376695d5043362a1d1000010b161f2830373b3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e474f535555555555555555524d453e3e3e3e3e3e3e3e3e3e3e3e3e3e3d3a352e261d1309000009141f2a343e454b4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4e4a443c32281d120600000000000000000000050c131a21272d32373b3f4346494b4d4f505151515151504f4e4c4a4845413d39342f2a241d160f0800000000000000000000000000000000000000000001070d13181d2125292c2f3133353637383838383737353432302d2a27231f1a15100a0400000000000000000000000000000000000000111e2a37434f5b656d6e6e6e6e6e6e6e6e6e695f54483c3024180c0000000000000000000000000000000000000000000a16222e3a46515d676e6e6e6e6e6e6e6e6e6d665b5044372b1f12050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a121a21262a2c2c2c2c2c2c2c2c2c2b28231d150d040000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000013202c3946535f6c79869395959595959595959595959595959595959595959595959595959595959595959594877a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b88949595959386796d6053463a2d20130700000000000000000000000006101b252f39434c555d656d747b81878c9094979a9c9d9e9fa09f9f9e9d9b9895928e89847e777169625951483f352c22180d030000000000000000000000000000000714202d3a4753606d7a8794959595959184776a5d5144372a1e110400000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00000000000000000000000000000000000007111b242d343a3d3f3f3f3f3f3f3f3f3f3f3d3a342d241b110600000000000000000000000000000000000000010c16202931373c3e3f3f3f3f3f3f3f3f3f3c38322a21180e030000000000000005101a232c33393d3f3f3f3f3f3f3f3f3f3f3c38312a21170d020000000013202c3946535f6c798693a0a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a2a7afaea6a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a19d908376695d5043362a1d100007121d28313a42474a4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4a4640382f251b1004000d1925313c4650575b5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5b564e44392e23170b000000000000000000070f171e252c32383e43474c4f5355585a5b5d5d5e5e5e5e5d5c5b595754514d4945403b352f282119120a01000000000000000000000000000000000000050c13191e24292d3135383b3e4041434444454545444342413f3c3a37332f2b26211b150f08010000000000000000000000000000000000121f2c3945525f6b777b7b7b7b7b7b7b7b7a7064584c4035291d110500000000000000000000000000000000000000030f1b27323e4a56626e797b7b7b7b7b7b7b7b786c5f5346392d2013060000000000040a0e1112131313131313131313120f0b0600000000000000000000000000000000000000000000000000000000000000050a0e1112131313131313131312110e0a04000000000000000000000810161a1e1f20202020202020201e1c17120b03000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000013202c3946535f6c798693a0a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a094877a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b8894a1a2a09386796d6053463a2d2013070000000000000000000000020d17222d37414b555e676f777f868c92979ca0a3a6a7a5a3a2a2a2a2a4a5a7a5a29e9a958f89827b736b635a51473e342a1f150a0000000000000000000000000000000713202d3a4653606d798693a0a2a29e9184776b5e5144382b1e110500000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c0000000000000000000000000000000000010d18232d373f454a4c4c4c4c4c4c4c4c4c4c4a453f362d23180c0100000000000000000000000000000000000007121d28323b42484b4c4c4c4c4c4c4c4c4b49433c332a1f150a000000000000010c17212c353e45494b4c4c4c4c4c4c4c4c4b48433c33291f14080000000013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a1a7afada5a1a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09d908376695d5043362a1d10000c18232f39434c535757575757575757575757575757575757575757575757575757575757575757575757575757575757575756524a41372c21150900111d2936424d5862686969696969696969696969696969696969696969696969696969696969696969696969696969696969696760564b3f33271a0e0000000000000000071019212830373d44494e53585c5f62646668696a6b6b6b6b6a69676563605d5a55514c46403a332b241c130a01000000000000000000000000000000000810171e242a2f35393d4145484a4c4e4f505151515151504f4d4b4946433f3b37322c26201a130b0400000000000000000000000000000000121f2c3845525e6a7682888888888888888175695d5145392d22160a0000000000000000000000000000000000000008141f2b37434f5b67737e8888888888888883776b5f5246392c20130600000000080f151a1d1f1f1f1f1f1f1f1f1f1f1e1b17120b03000000000000000000000000000000000000000000000000000000020910161b1e1f1f1f1f1f1f1f1f1f1f1d1a16100901000000000000000000040a0e11131313131313131313120f0b060000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000013202c3946535f6c798693a0a3a3a3a3a3a3a3a3a3a3a3a3a4a8aeaeaeada6a3a3a3a3a3a3a3a3a3a3a3a3a094877a6d6053473a2d201407000000000000000001030303030303030303030303030303030303030815212e3b4854616e7b8894a1ada09386796d6053463a2d201307000000000000000000000008131e29343e49535d677079818991979ea3a8a7a29e9b98979695959697999c9fa4a9a5a09a948d857d756c635950463b31261c110600000000000000000000000000000613202c3946525f6c7985929facab9e9285786b5e5245382c1f120500000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c000000000000000000000000000000000006121e29343f495156585858585858585858585650483f34291d12060000000000000000000000000000000000000c18242f3a444d5458585858585858585858554e453c31261c1106000000000008131e28333d474f5658585858585858585858544e453b3025190d0100000013202c3946535f6c79869393939393939393939393939393939393959da7a59b9493939393939393939393939393939393908376695d5043362a1d1000101c2834404b555e63646464646464646464646464646464646464646464646464646464646464646464646464646464646464635c53493d3125190d00121f2c3845525e6a7375757575757575757575757575757575757575757575757575757575757575757575757575757575757572675b4f4236291c100000000000000007101a222b333a41484f555a5f64686b6e71737576777778787777757472706d6a66615d57514b443d352d251c130a0100000000000000000000000000020a121a21282f353b40454a4d515457595b5c5d5e5e5e5e5d5d5b5a5855524f4b47423d38322b241d150d05000000000000000000000000000000111d2a36424e5a66717d8995959595959185796d62564a3e32261a0e030000000000000000000000000000000000000c1824303c48545f6b77838f95959595958a7e72665a4f43372a1e110500000009121a21262a2c2c2c2c2c2c2c2c2c2c2b28231d150d0400000000000000000000000000000000000000000000000000020b141b22272a2c2c2c2c2c2c2c2c2c2c2a26211a130a01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000013202c3946535f6c79869396969696969696969696969696979da6b1aea39b9796969696969696969696969694877a6d6053473a2d201407000000000002070b0e101010101010101010101010101010101010101015212e3b4854616e7b8894a1ada09386796d6053463a2d20130f0c090400000000000000020e1924303b45505b656f78828b939ba2a9a8a19b96928f8c8a898888898a8c8f93989da3aaa59f978f877e756b62574d43382d22170c010000000000000000000000000005121f2b3845515e6b7884919eaaac9f9286796c5f5346392c20130600000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00000000000000000000000000000000000a16222e3a46515b6265656565656565656565625a50453a2e22160a000000000000000000000000000000000000101c2834404b565f6465656565656565656560574d43382d23180d03000000050f1a252f3a454f5961656565656565656565645f574c4135291d110400000013202c3946535f6c798686868686868686868686868686868686868b96a3a0948986868686868686868686868686868686868376695d5043362a1d1000121f2b3844505c67707171717171717171717171717171717171717171717171717171717171717171717171717171717171716e655a4e4135281c0f0013202c3946535f6c7982828282828282828282828282828282828282828282828282828282828282828282828282828282828276695d5043362a1d10000000000000061019232c343c444c535a60666b7074787b7d80828384848585848382817e7c7976726d68635d564f473f372e251c1309000000000000000000000000020b141c242c333a40464c51565a5d61636667696a6b6b6b6b6a69686664625f5b57534e49433d362f271f170f0600000000000000000000000000000e1a26323d4955616d7884909ca2a2a2968a7e72665a4e43372b1f1307000000000000000000000000000000000005111d2935404c5864707c8894a0a2a29d9185796d61564a3e32261a0e02000008121b242c32363839393939393939393937342e271f160c020000000000000000000000000000000000000000000000000a141d262d33373939393939393939393936322c251c13090000000000000000000000000000000000000000000000000000000001060a0d0e0e0e0e0e0e0e0d0a06010000000000000000000000000000000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000013202c3946535f6c79868a8a8a8a8a8a8a8a8a8a8a8a8a8a8b95a0ada99d928a8a8a8a8a8a8a8a8a8a8a8a8a8a877a6d6053473a2d20140700000000060d13171b1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c212e3b4854616e7b8894a1ada09386796d6053463a2d201c1b19150f0901000000000007131f2a35414c57626c77818b949da5ada59e96908a8682807d7c7b7b7c7e8083878c9298a0a8a9a19990877d73695f544a3f34281d12060000000000000000000000000002111e2a3744505d6a7683909da9ada093867a6d6054473a2d21140700000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00000000000000000000000000000000030f1b27333f4b57626d727272727272727272726c62564a3f33271b0f030000000000000000000000000000000000121f2b3844515d6870727272727272727271695f544a3f342a1f140a0000010c16212c36414c56616b72727272727272727271695e5245392c201307000000131f2c3946525f6b7679797979797979797979797979797979797b8895a2a0938679797979797979797979797979797979797974695c4f4336291d100013202c3946535f6c797e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e76695d5043362a1d100013202c3946535f6c79868f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8376695d5043362a1d100000000000040e18222b353e464e565e656b71777c8084878a8c8e909191929191908f8d8b8986827e79746e686159514940372e251b110700000000000000000000020b141d262e363e454b52575d62666a6d70727475777778787777767573716e6b68645f5a544e484139312921180f05000000000000000000000000000915212d3944505c6874808b97a3aea69a8f83776b5f53473b3024180c00000000000000000000000000000000000a16212d3945515d6975818c98a4aea4988c8174695d5145392d22160a0000040f1a242e363d4245464646464646464645443f3931281e1308000000000000000000000000000000000000000000000006111c262f373e4345464646464646464645433d362e251b10050000000000000000000000000000000000000000000000000000060d1217191b1b1b1b1b1b1b1916120c0500000000000000000000000000000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000013202c3946535f6c787d7d7d7d7d7d7d7d7d7d7d7d7d7d7d85929faca89b8e827d7d7d7d7d7d7d7d7d7d7d7d7d7d796d6053473a2d2014070000000810181e2327292929292929292929292929292929292929292929292e3b4854616e7b8894a1ada09386796d6053463a2d29292825201a130b02000000000c18242f3b47525d68737e89939da6aea59c938c857f7a7673716f6f6f6f7173777b81878e969ea7aba2998f857b71665b50453a2e23170b0000000000000000000000000000101c2936424f5c6875828e9ba8aea194887b6e6155483b2f22150900000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c0000000000000000000000000000000007131f2b37434f5b67737e7e7e7e7e7e7e7e7e7e73675b4f43372b1f1307000000000000000000000000000000000013202c3946535f6c797e7e7e7e7e7e7e7e7b71665b51463b31261b11060008131d28333d48535d68737d7e7e7e7e7e7e7e7e7a6d6154473a2e211407000000111e2a37434f5a646b6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6f7b8895a2a09386796d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6a62584c4034281b0f0013202c3946535f6c79868b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8376695d5043362a1d100013202c3946535f6c7986939c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c908376695d5043362a1d1000000000010b16202a343d47505860686f767c82878c909497999b9c9d9e9e9e9e9d9c9a9895928e8a857f79726b635b524940372d23190e030000000000000000010a141d262f3840484f565d63686d7276797c7e81828484858584848382807d7b77746f6b656059524b433b332a21170e0400000000000000000000000005101c2834404b57636f7b87929eaaab9f93877b7064584c4034281c1105000000000000000000000000000000020e1a26323e4a56616d7985919da9ab9f93877b7064584c4035291d110500000a15212c3640484e52525252525252525252504a433a3025190e02000000000000000000000000000000000000000000000c17232e3841494f525252525252525252524e4840372c21160a000000000000000000000000000000000000000000000000000810181e23262828282828282726221d170f07000000000000000000000000000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000121e2b3744505c676e70707070707070707070707070707885929faca89b8e8275707070707070707070707070706f675c5145382c1f1306000007111a22292f3336363636363636363636363636363636363636363636363b4854616e7b8894a1ada09386796d6053463a36363634312c251d140a00000004101c2834404c58636e7a85909aa5afa69c938a817a736e6a66646362626364676b70757c848c959ea8aba1978d82786d61564b3f33281c1004000000000000000000000000000e1b2834414e5a6773808d99a6afa296897c6f6356493d3023170a00000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c000000000000000000000000000000000c18242f3b47535f6b77838c8c8c8c8c8c8c8c83776b5f53473c3024180c0000000000000000000000000000000000121f2c3845515d69737e898c8c8c8c8c8c82786d62584d42382d23180d040f1a242f3a444f5a646f7a848c8c8c8c8c8c8a7f746a5e5246392d2013070000000e1b27323e49525a5f606060606060606060606060606060626f7b8895a2a09386796c606060606060606060606060606060605e5950463b3024180c0013202c3946535f6c7986939898989898989898989898989898989898989898989898989898989898989898989898989898908376695d5043362a1d100013202c3946535f6c798693a0a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a69d908376695d5043362a1d100000000008121d28323c464f59626a727a81888e93989ca0a3a5a7a7a5a4a4a4a5a6a8a7a4a19e9a96908a847d756d645b52493f352a20150a000000000000000008131c262f39424a525a61686e74797e8286898b8d8f909192929190908e8c8a8784807b76716b645d554d453c332920160c010000000000000000000000000c17232f3b47525e6a76828d99a5b0a4988c8074685c5145392d21150900000000000000000000000000000007131f2b37424e5a66727e8a96a2ada69a8e83776b5f53473c3024180c0000000e1a26323d48525a5e5f5f5f5f5f5f5f5f5f5c554c41362a1f130700000000000000000000000000000000000000000005111c28343f4a535b5f5f5f5f5f5f5f5f5f5e5a52483e32271b0f02000000000000000000000000000000000000000000000008111a22292f3334343434343434322e28211910060000000000000000000000000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000f1c28343f4a555d62636363636363636363636363636b7885929faca89b8e827568636363636363636363636363625e554b4034281c100400030e19232c343b404243434343434343434343434343434343434343434343434854616e7b8894a1ada09386796d60534643434343413d372f261c120700000814202d3945515d6874808b96a1aca99e948a81776f68625d5a5756555556585b5f646a727a838c96a0aba99f94897e73675c5044382c201408000000000000000000000000000d1926333f4c5865727e8b98a4b0a4978a7e7164584b3e3225190c00000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00000000000000000000000000000004101c2834404c5864707c889498989898989894887c7064584c4034281c100400000000000000000000000000000000101d2935414c57626c77818c9698989894897f74695f54493f34291f140b16212b36414b56616b76818b96989898978d82786d63584d42362a1e11050000000a16212c3740494f53535353535353535353535353535355626f7b8895a2a09386796c5f535353535353535353535353535353524e473e352a1f13080013202c3946535f6c798693a0a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a49d908376695d5043362a1d100013202c3946535f6c7986939999999999999999999999999999999999999999999999999999999999999999999999999999908376695d5043362a1d10000000030e19242f39444e58616b747c848c93999fa4a8a7a29f9c9a9898979898999b9ea1a5aaa6a19c968f877f766d645b51463c31261b100500000000000005101a242e38424b545c646c737980858a8e9295989a9c9d9e9e9e9e9d9c9b999693908c87827c756f675f574e453b32281e130900000000000000000000000007131e2a36424e5965717d8994a0aca89d9185796d6155493e32261a0e0200000000000000000000000000000c18232f3b47535f6b77838e9aa6ada1968a7e72665a4f43372b1f1308000000111d2a36424e5a646b6c6c6c6c6c6c6c6c6c675e53473b2f23170b0000000000000000000000000000000000000000000915212d3945505c656b6c6c6c6c6c6c6c6c6b645a4f43372b1e120500000000000000000000000000000000000000000000040f1a232c343a3f414141414141413e3a332b22180e0300000000000000000000000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000b17232e39434b52565656565656565656565656565f6b7885929faca89b8e8275685b565656565656565656565656524c43392f23180c00000914202a353e464c4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f54616e7b8894a1ada09386796d60534f4f4f4f4f4d4841382e23180d01000c1824303d4955616d7985919ca8aea2978c82786e665e57524e4b494848494b4f53596068717a848e99a4afa69a8f84786c6155493d3125180c000000000000000000000000000b1824313d4a5763707c8995a2afa5998c8073665a4d4034271b0e01000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c0000000000000000000000000000000814202c3844505c6874808c98a4a5a5a5a5a4988c8074685c5044382d211509000000000000000000000000000000000d1924303b46505a656f7a858f99a4a59b90867b70665b50463b31261b121d28323d48525d68727d88929da5a59a90857b70665b51473c31261a0e0200000005101b252e373e4346464646464646464646464646464855626f7b8895a2a09386796c5f53464646464646464646464646464646423d352c23180e020013202c3946535f6c7986939c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c908376695d5043362a1d100013202c3946535f6c79868c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8376695d5043362a1d1000000009141f2b35404b56606a737d868e969da4aaa6a09b9692908d8c8b8a8b8b8d8f92959a9fa5aba7a099918980766d63584e43382d21160b0000000000010c17212c36404a545d666e767d848b91969a9ea2a4a3a09e9d9d9d9d9e9fa1a4a3a09c98938d878079716960574d443a2f251a0f040000000000000000000000020e1a25313d4955606c7884909ba7ada195897d72665a4e42362a1f13070404040404040404040404040404101c2834404c58636f7b87939faba89d9185796d61564a3e32261a0f03000000121f2c3845525e6b767979797979797979786f63574b4034281c100400000000000000000000000000000000000000020e1a26323d4955616d777979797979797979766b5f5346392d201306000000000000000000000000000000000000000000000a16212b353e464b4e4e4e4e4e4e4e4a453d342a1f140800000000000000000000000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000006121c2731394146494a4a4a4a4a4a4a4a4a4a4a525f6b7885929faca89b8e8275685b4e4a4a4a4a4a4a4a4a4a4a4946413a31271d120700000d1925313c4650575c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c616e7b8894a1ada09386796d605c5c5c5c5c5c59534a4035291d1205000f1b2734404c5965717d8995a1a7a89d91867b70665c544c46413e3c3c3c3d3f42484e565f68727d88939ea9aca095897d7165594d4134281c10030000000000000000000000000916222f3b4854616e7a8793a0aca79b8e8175685b4f4236291d1004000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c0000000000000000000000000000010d1925313d4955616c7885919ca8a09a9aa0a99d9185796d6155493d3125190d0100000000000000000000000000000008131f29343e49535e68737d88929da7a2978d82776d62574d42382d2219242f39444f59646f79848f99a4a89d93897e74695f544a3f352a201409000000000009131c252c3337393a3a3a3a3a3a3a3a3a3a3a3a3c4855626f7b8895a2a09386796c5f53463a3a3a3a3a3a3a3a3a3a3a3a3a3936312b231a1107000013202c3946535f6c7986909090909090909090909090909090909090909090909090909090909090909090909090909090908376695d5043362a1d100013202c3946535f6c7980808080808080808080808080808080808080808080808080808080808080808080808080808080808076695d5043362a1d100000020e1a25303c47525d67727c868f98a0a8aaa39b958f8a8683817f7e7d7e7e808285898e939aa1a9aba39b92897e746a5f54493e33271b10040000000007121d28333e48525c666f7880888f969ca1a6a29e9996949290909090919295989ba0a5a49e99928b837b72695f564b41372c21160b0000000000000000000000000915212c3844505c67737f8b97a2aea69a8e82766a5f53473b2f231711111111111111111111111111111115212d3944505c6874808c98a4afa4988c8074695d5145392d21160a00000000121f2c3945525f6b7783868686868686868074685c5044382d2115090000000000000000000000000000000000000007131f2a36424e5a66727d8686868686868684786c5f5346392d201306000000000000000000000000000000000000000000030f1b27323d4750575a5b5b5b5b5b5a564f463b3025190d01000000000000000000000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000b151f272f353a3c3d3d3d3d3d3d3d3d3d3d45525f6b7885929faca89b8e8275685b4e423d3d3d3d3d3d3d3d3d3d3a3630281f160b010000111d2936424d58626869696969696969696969696969696969696969696969696969696e7b8894a1ada09386796d69696969696969645c51463a2e21150800111e2a3743505c6875818d97999a9b978c8075695e544a423a3532302f2f3033373c444d56606b76818d98a4b0a5998d8175695d5044382b1f13060000000000000000000000000713202d3946525f6b7884919daaa99d9083776a5e5145382c1f1306000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c000000000000000000000000000005111d2935414d5965717d8995a1a2968e8e97a2a195897d7165594d41352a1e1206000000000000000000000000000000020d18222c37414c56616b76818b95a0a99e94897e74695f54493f3429202b36404b56606b75808b96a0aba1968c81776c62574d42382e23190e030000000000010a131b21272b2d2d2d2d2d2d2d2d2d2d2d2d2f3c4855626f7b8895a2a09386796c5f5346392d2d2d2d2d2d2d2d2d2d2d2d2c2a262019110800000013202c3946535f6c7983838383838383838383838383838383838383838383838383838383838383838383838383838383838376695d5043362a1d1000121f2b3844515d687173737373737373737373737373737373737373737373737373737373737373737373737373737373737370665a4e4235291c0f000007131f2b36424d58636e79848e98a1aaaaa198918a847e7a777472717171727376797d82888f979fa8ada49a91867c71665a4f44382c201408000000010d18242f3a454f5a646e78818a929aa1a7a49d97928d8a8785848383838486888b8f949aa0a7a49d958d847b71675d53483d32271c1005000000000000000000000004101c27333f4b57636e7a86929ea9ab9f93877b6f63574c4034281e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e25313d4955616d7985919ca8ab9f93877b7064584c4034291d110500000000111e2a37434f5b67727e8a92929292929084786d6155493d3125190e020000000000000000000000000000000000000b17232f3b47535f6a76828e92929292928b7f73675b5044372b1e120500000000000000000000000000000000000000000006131f2b37434f59626767676767676761584d4136291d1104000000000000000000000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000030d151d242a2e303030303030303030303845525f6b7885929faca89b8e8275685b4e42353030303030303030302e2a251e160d04000000121f2c3945525e6a747676767676767676767676767676767676767676767676767676767b8894a1ada093867976767676767676756e6256493d3024170a00131f2c3946525f6b7884898a8c8d8f90877b6f63584d423830292523222223262b323b444f5a65707c8894a0acaa9e9185796c6054473b2e22150900000000000000000000000005111e2a3743505c6975828e9ba7ab9f9286796d6054473b2e221509000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00000000000000000000000000000915212d3945515d6975818d99a59e918586929ea59a8e82766a5e52463a2e22160a0000000000000000000000000000000006101b25303a454f5a646f79848e99a3a59b90867b70655b50463b3027323d47525d67727c87929da7a4998f847a6f655a50463b31261c110700000000000000010910161b1e2020202020202020202020222f3c4855626f7b8895a2a09386796c5f5346392c2020202020202020202020201e1a150f0700000000121f2c3945525e6a7476767676767676767676767676767676767676767676767676767676767676767676767676767676767672675b4f4236291c1000101c2935404c565f65666666666666666666666666666666666666666666666666666666666666666666666666666666666666645e54493e32261a0d00000c1824303b47535e6975808b95a0aaaba1988f877f78736e6a67666564646567696d71777d858d969fa9aca2988d82776c6054493d3125190d00000006121e2935404b56616c76808a939ca4aaa299928c86817d7a787776767777797c7f83898f969da6a79f968d83796f645a4f44382d21160a0000000000000000000000000b17232f3a46525e6975818d99a5afa3978c8074685c5044382d2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a36424e5a66717d8995a1ada69a8e83776b5f53473c3024180c00000000000e1b27333e4a56626e7985919d9f9f9f95897d7165594e42362a1e1206000000000000000000000000000000000004101c2834404b57636f7b87939f9f9f9e92867a6e62574b3f33271b0f0300000000000000000000000000000000000003070a0e15212e3b4754606b73747474747473695e5245392c1f130c090500000000000000000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000000030c13191e212323232323232323232c3845525f6b7885929faca89b8e8275685b4e4235282323232323232323211e19130c040000000013202c3946535f6c79838383838383838383838383838383838383838383838383838383838895a1ada0948783838383838383837d7164574a3e3124170b0013202c3946525f6b777b7c7e7f81828483776b5f53473c31261e19161516171a2029323d48545f6b7784909ca9ada195887c6f63564a3d3124180b000000000000000000000000020f1b2834414d5966727e8b98a4aea195887c6f63564a3d3125180c000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00000000000000000000000000020e1a26323e4a56626d7a86929ea69a8e82828f9ba79e92867a6e62564a3e32261b0f030000000000000000000000000000000009131e28333d48525d67727c87919ca6a2978d82776d62574d42372e39444e59636e79848e99a4a79c92887d73685e53493e34291f140a00000000000000000000050a0f121313131313131313131315222f3c4855626f7b8895a2a09386796c5f5346392c201313131313131313131313110e09040000000000111d2936424d5862686969696969696969696969696969696969696969696969696969696969696969696969696969696969696760564b3f33271a0e000c18242f3a444d545859595959595959595959595959595959595959595959595959595959595959595959595959595959595958534c42382d21160a0004101c2834404c58636f7b86919ca7afa4998f867d756d67625e5b59585757595a5d61666c737b848d97a2adaa9f94887c7165594d4135291c100400000b17232f3a46515d68737d88929ca5aba2989088817a75716e6c6a69696a6b6d6f73777d848b949da7a89f958b81766b6055493e32261b0f03000000000000000000000006121e2a35414d5965717c8894a0aca89c9084786d6155493d373737373737373737373737373737373737373b47525e6a76828e9aa6ada1968a7e72665a4e43372b1f130700000000000a16222e3945515d6975818c98a4aca59a8e82766a5e52463b2f23170b00000000000000000000000000000000000915212c3844505c6874808c97a3aca5998d8175695e52463a2e23170b0000000000000000000000000000000000050a0f13161a1d222f3c4855626f7b8181818181796d6053463a2d201c1815110c080300000000000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000000001080d121516171717171717171f2c3845525f6b7885929faca89b8e8275685b4e4235281b1717171717171615120e0802000000000013202c3946535f6c7986909090909090909090909090909090909090909090909090909090929aa5b0a49991909090909090908a7d7164574a3e3124170b00111e2a37434f5a656c6e7071727475777872675b4e42362a1f140d0a09090a0f17212c37434f5b6874818d99a6b0a4978b7e7265584c3f3326190d000000000000000000000000000c1825313e4a57636f7c8895a1ada4978b7e7265594d4034281b0f030000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c0000000000000000000000000006121e2a36424e5a66727e8a96a2a3978a7e7e8b97a3a2978b7e73675b4f43372b1f130700000000000000000000000000000000020c17212c36414b56606b75808a959fa99e94897e74695e54493e35404b55606a75808b95a0aaa0958b80766b61564c41372c22180d0300000000000000000000000002050607070707070707070915222f3c4855626f7b8895a2a09386796c5f5346392c2013070707070707070707060502000000000000000d1925313c4650575c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5b564e443a2e23170b0007131e29323b43494c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4b48423a30261c1005000713202c3844505c6874808c97a3aea89d92887d746b635c56524e4c4b4b4b4c4e51555a6169727b86909ba7b0a5998d8275695d5145382c20130700030f1b27333f4b57626e79848f9aa4aea49990867d766f6965615f5e5d5d5d5e6063676c7279828b959faaa79d93887d71665a4f43372b1f13070000000000000000000000010d1925313c4854606c77838f9ba7ada195897d71655a4e4444444444444444444444444444444444444444444b57636f7b87929eaaa89d9185796d61564a3e32261a0e03000000000005111d2935404c5864707b87939fabaa9e92877a6f63574b3f33271c1004000000000000000000000000000000020d1925313d4955616c7884909ca8aca094887c7165594d41352a1e1206000000000000000000000000000000060c11161b1f2326292c2f3c4855626f7b888e8e8e86796d6053463a2e2b2825211d18140e09030000000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000000000000205080a0a0a0a0a0a0a121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f0a0a0a0a0a0a0806020000000000000013202c3946535f6c7986939c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9ea3acb5aba29d9c9c9c9c9c9c978a7d7164574a3e3124170b000f1b27333e49535b606163646667696a6b6960564a3e32261a0e0300000000050f1b27333f4c5865717e8a97a3b0a6998d8073675a4e4134271b0e000000000000000000000000000916222e3b4753606c7985919eaaa79a8e8175685c5043372b1e12060000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c000000000000000000000000000a16222e3a46525e6a76828e9aa69f93877b7b8793a0a79b8f83776b5f53473b2f23180c0000000000000000000000000000000000050f1a242f39444e59636e78838d98a2a59b90857b70655b50453c47515c67727c87929ca7a3988e83796e64594f453a30251b10060000000000000000000000000000000000000000000000000915222f3c4855626f7b8895a2a09386796c5f5346392c2013060000000000000000000000000000000000000914202a353e464c4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4b443c32281d120600010c17202931383d3f4040404040404040404040404040404040404040404040404040404040404040404040404040404040403f3c3730281e140a00000a17232f3c4854606c7985919ca8aea3978c81766b6259514a4642403e3e3e3f4145494f576069747f8a96a1adaa9e9286796d6154483b2f23160a0007131f2b3744505c67737f8a96a1aba89d92887d746b645e595553515050505254575b61687079838d98a4afa4998e83776b5f53473b2f23170a0000000000000000000000000814202c38434f5b67737e8a96a2aea59a8e82766a5e52515151515151515151515151515151515151515151515c6873808b97a3afa4988c8074685d5145392d21160a000000000000010c1824303c47535f6b77838e9aa6afa3978b7f73675c5044382c20140900000000000000000000000000000006121e2a36424d5965717d8995a1ada79b8f84786c6054483d3125190d0100000000000000000000000000040b11171d22262b2f3236393b3d4855626f7b88959b9386796d6053463c3a3734312d29241f1a140e0701000000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f0200000000000000000000000000000013202c3946535f6c798693a0a9a9a7a3a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a3a8b0b8afa7a3a2a2a2a2a2a2978a7d7164574a3e3124170b000a16212d3741494f53555658595b5c5e5f5d574e44392e22160a0000000000000b1724303d4956626f7c8995a2afa89b8e8275685b4f4235291c0f0000000000000000000000000006131f2b3844505d6975828e9aa6a99d9184786c5f53473a2e2216090000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c000000000000000000000000030f1b27333f4b57636f7b87939fa89c9083777784909ca89f94887b7064584c4034281c1004000000000000000000000000000000000008131d28323d47525c67717b86919ba5a2978c82776c62574c434e58636e78838e99a3a69b91877c72675d52483d33281e1309000000000000000000000000000000000000000000000000000915222f3c4855626f7b8895a2a09386796c5f5346392c201306000000000000000000000000000000000000030e19232c343b4042434343434343434343434343434343494d4f4f4f4f4f4f4f4f4d48434343434343434343434343434343423f39322a20160c010000050e1720272c303333333333333333333333333333333333333333333333333333333333333333333333333333333333333332302b251e160c0300000d1926323f4b5864707c8995a1ada99e92867a6f645a50473f3a36333231313335383e454e58626e7985919da9aea295897c7064574b3e3125180c000a16222f3b4754606c7884909ba7aea2978b80766b625a524d49464443434445474a4f565e67717c87929eaaaa9f93887c7064574b3f33261a0e010000000000000000000000040f1b27333f4a56626e7a86919da9aa9e92877b6f635d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d606c7884909ca8ab9f93877b6f64584c4034291d11050000000000000008131f2b37434e5a66727e8a95a1ada79c9084786c6054493d3125190d0100000000000000000000000000000b17232e3a46525e6a76828e99a5aea2968b7f73675b4f44382c20140800000000000000000000000001080f161c22282d32373b3f4245484a4c55626f7b8895a09386796d60534b494744413d3935302b251f19120b040000000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f0200000000000000000000000000000013202c3946535f6c798693a0aca69c96959595959595959595959595959595959595959595979ea8b2a79d96959595959595958a7d7164574a3e3124170b0005101b252f373e4447484a4b4c4e4f5152514c453c33281d11060000000000000815222e3b4855616e7b8894a1aea99c8f8376695c4f4336291c1000000000000000000000000000030f1c2834414d5966727e8a97a3ada094887b6f63564a3e3225190d0100000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00000000000000000000000007131f2b37434f5b67737f8b97a3a5988c807474808c98a4a4988c8074685c5044382c2014090000000000000000000000000000000000010b16202b35404a555f6a747f89949ea99e93897e73695e534a55606a75808a95a0a99e948a7f756a60554b40362b21170c02000000000000000000000000000000000000000000000000000915222f3c4855626f7b8895a2a09386796c5f5346392c2013060000000000000000000000000000000000000007111a22292f333636363636363636363636363638424c545a5b5b5b5b5b5b5b5b59534a403636363636363636363636363635332e2820180e0500000000050e151b20242626262626262626262626262626262626262626262626262626262626262626262626262626262626262626231f1a140c040000000f1c2835424e5a6773808c99a5a6a5998d8175695e53483e352e292625242526282d333c46515d6975818d9aa6b1a5988c7f7266594d4033271a0d000c1925323e4b5763707c8894a0aca99d91867a6f645a5048413d3938373637383b3f444c555f6a76828d99a5b0a4988c8073675b4e4236291d10040000000000000000000000000b16222e3a46515d6975818c98a4afa3978b80736a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a717d8995a0aca69a8e83776b5f53473b3024180c0000000000000000030f1a26323e4a55616d7985919ca8aca094897d7165594d41352a1e12060202020202020202020202020204101b27333f4b57636e7a86929eaaa99e92867a6e62564b3f33271b10040000000000000000000000030b121a21272e34393e43474b4e515456585a626f7b8895a09386796d605a585653504d4945413c36312a241d160e0600000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f0200000000000000000000000000000013202c3946535f6c7986939ea9a0948a8888888888888888888888888888888888888888888c96a2aea1958b88888888888888887d7164574a3e3124170b000009131d252d33383a3b3d3e404143444544403b332a21160c000000000000000714212e3a4754616d7a8794a0ada99d908376695d5043362a1d1000000000000000000000000000000c1825313d4a56626e7a87939faba4978b7e72665a4e4235291d110500000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c0000000000000000000000000b17232f3b47535f6b77838f9ba7a195897c70707c8894a0a89c9185786d6155493d3125190d010000000000000000000000000000000000040f19242e39434d58626d77828c97a1a59a90857a70655a515c66717c87919ca7a2978d82786d63584e44392f241a0f0500000000000000000000000000000000000000000000000000000915222f3c4855626f7b8895a2a09386796c5f5346392c20130600000000000000000000000000000000000000000810181e2327292929292929292929292929313d49545e666868686868686868645c52463a2e29292929292929292929292926221d160e060000000000030b12181d202222222222222222222222222222222222222222222222222222222222222222222222222222222222222222201c17110901000000111e2b3744505d6976838f97989a9b96897d7165594d41362c231d1a181818191c212a35404c5965717e8a97a4b0a79a8e8174675b4e4135281b0f000f1b2834414d5a66737f8c98a4b0a6998d8175695e52483e36312d2b2a2a2a2c2e333a434e5965717d8995a2aea89c9083776a5e5145382c1f130600000000000000000000000006121d2935414d5864707c88949faba89c9084787777777777777777777777777777777777777777777777777777828d99a5ada1958a7e72665a4e42372b1f13070000000000000000000a16212d3945515c6874808c98a3afa5998d81756a5e52463a2e22170f0f0f0f0f0f0f0f0f0f0f0f0f0f0f14202c3844505b67737f8b97a3afa5998d8175695e52463a2e22170b0000000000000000000000040c151d242b32393f454a4f53575b5e61636567686f7b8895a09386796d686664625f5c5955514c47423c352f2720181007000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f0200000000000000000000000000000013202c3946525f6c77828d97a29f93877d7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b8894a1ada093867b7b7b7b7b7b7b7b7b7063574a3d3124170a0000010b131b22272b2d2f303233353638383835302921180f05000000000000000814212e3a4754616d7a8794a0adaa9d908376695d5043362a1d1000000000000000000000000000000915212d3a46525e6a77838f9ba7a79b8f82766a5e5245392d21150900000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c000000000000000000000004101c2834404c5864707c8894a0aa9e9185796c6c7884909ca8a195897d7165594d4135291d110600000000000000000000000000000000000007121c27313c46515b66707b85909aa5a1978c82776c6158636d78838e98a3a59a90857b70665c51473c32271d12080000000000000000000000000000000000000000000000000000000915222f3c4855626f7b8895a2a09386796c5f5346392c201306000000000000000000000000000000000000000000060d13171b1c1c1c1c1c1c1c1c1c1c1c2734414d5a667075757575757575756e63564a3e31241c1c1c1c1c1c1c1c1c1c1c1a17120c040000000000020c151d24292d2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2c28221b130a000000131f2c3946525f6b7885898b8c8d8e8f867a6d6155493c31251a110d0c0b0b0d101824303d4956626f7c8895a2aea89c8f8275695c4f4236291c1000101d2a36434f5c6975828e9ba7afa3968a7d7165594d41362c25211e1d1d1d1f2228323d4955616d7986929fabab9f9286796d6053473a2e211408000000000000000000000000010d1924303c48545f6b77838f9aa6aca0958984848484848484848484848484848484848484848484848484848487929eaaa89c9185796d61554a3e32261a0e0300000000000000000005111d2834404c58636f7b87939faaaa9e92867a6e62574b3f33271b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b25313c4854606c7884909ba7aca094887c7065594d4135291e120600000000000000000000040d161e262e363d444a50565b5f63676a6d70727375767b8895a0938679757473716f6c6965615d58534d474039322a221910070000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f02000000000000000000000000000000111e2b37434f5b66707b85909ba3998f857a706f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f7b8894a1ada09386796f6f6f6f6f6f6f6e695f54483b2f231609000000010910161b2125292a2a2a2a2a2b2c2b2a2825201a120a020000000000000a16232f3c4855626e7b8894a1aea99c8f8376695c4f4336291d10000000000000000000000000000005111e2a36424e5a66737e8b97a3ab9e92867a6e6256493d3125190d01000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00000000000000000000000814202c3844505c6874808c98a4a69a8e8275696874808c98a4a5998d82756a5e52463a2e22160a000000000000000000000000000000000000000b15202a353f4a545e69737e89939da89e93897e73685f6a747f8a959fa89e93897e74695f544a3f352a20160b010000000000000000000000000000000000000000000000000000000915222f3c4855626f7b8895a0a09386796c5f5346392c2013060000000000000000000000000000000000000000000002070b0e101010101010101010101b2835424e5b6875828282828282827e7165584b3e3225181010101010101010100f0e0a06000000000000000a141e272e35393c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3b38332d251c1208000013202c3946525f6c777b7d7e7f80818284776b5e5245392d20140801000000000815222e3b4854616e7b8794a1aea99c908376695c504336291d1000121e2b3844515e6a7784909daaada094877a6e6155493c30251a14121010111316202c3845515e6a7783909ca9aea194887b6f6255483c2f221609000000000000000000000000000814202b37434f5b66727e8a96a2ada59b939191919191919191919191919191919191919191919191919191919299a3aea4988c8074685c5145392d21160a00000000000000000000000c18242f3b47535f6a76828e9aa5aea2978b7f73675b4f43382c28282828282828282828282828282828282935414d5965717c8894a0aca79b8f84786c6054483c3125190d01000000000000000000030d161f28303840484f555b61666b6f73777a7c7e808283848996a09488838281807d7b7875726d69645e58524b433c342b2219100600000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f020000000000000000000000000000000f1b27333e49545f69747e89939ea1968c82776d6362626262626262626262626262626e7b8894a1ada09386796d626262626262625e574d43372b1f1307000000000a141d252c313537373737373737373735312b241c140d070301010207101a26323e4b5764707d8996a3afa89b8e8275685b4f4235291c0f0000000000000000000000000000010e1a26323e4a56626e7a87939faba2968a7e72665a4e42362a1e1206000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00000000000000000000010d1925303c4854606c7884909ca8a2968a7e726564707c8894a0aa9e92867a6e62564a3e32261a0e02000000000000000000000000000000000000030e18232d38424d57626c77818c96a1a59a90857a7066717b86919ca6a1968c81776c62574d43382e23190e04000000000000000000000000000000000000000000000000000000000915222f3c4855626f7b889393939386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000f1b2835424e5b6875828e8f8f8f8f8b7e7165584b3e3225180b00000000000000000000000000000000000006111c26303940454849494949494949494949494949494949494949494949494949494949494949494949494949494949494948443f372e241a0f0300121e2b37434f5b666d6f7071727375767773685c5043362a1d110400000000020714212e3a4754616d7a8794a1aea99c908376695d5043362a1d1000131f2c3945525f6c7885929fabab9e9285786c5f5346392d2014080503010406101d2936424f5b6875828e9ba8afa396897c7063564a3d3023170a00000000000000000000000000030f1b27323e4a56626d7985919da8ada49f9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9ea3abab9f93877b6f64584c4034281d1105000000000000000000000007131f2b36424e5a66717d8995a1ada79b8f84786c6054483c353535353535353535353535353535353535353a46525d6975818d99a5aea2968b7e73675b4f43382c201408000000000000000000010b151f28313a424a525960676d72777b808386898b8d8e8f90939ba49992908f8e8c8a8885827e79756f69635d554e463d342b22180f04000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f020000000000000000000000000000000b16222d38424d57626c77828c97a19e94897f746a60555555555555555555555555616e7b8894a1ada09386796d60555555555555534d453b31261b0f0300000007111c262f373d42434444444444444443413c362e261e1813100e0e0f1219222c37424e5a67737f8c98a5b1a6998d8073675a4d4134271b0e0000000000000000000000000000000a16222e3a46525e6a76828e9aa6a69a8e82766a5e52463a2e22160b000000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c0000000000000000000005111d2935414d5965717d8995a1aa9e92867a6e62606c7884909ca8a2968a7e72675b4f43372b1f13070000000000000000000000000000000000000007111c26313b45505a656f7a848f99a4a1978c81766d78838d98a2a4998f847a6f655b50463b31261c110700000000000000000000000000000000000000000000000000000000000915222f3c4855626f7b868686868686796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000f1b2835424e5b6875828e9b9c9c988b7e7165584b3e3225180b0000000000000000000000000000000000000b17222e38424b515555555555555555555555555555555555555555555555555555555555555555555555555555555555555554504940362b201408000f1b27333f4a545c61626364666768696a6861574c4034271b0f09090a0a0c0f1219232f3b4855616e7b8894a1aea89c8f8275695c4f4336291c100013202c3946535f6c798693a0acaa9d9184776a5e5144382b1e120500000000010e1b2734414d5a6773818d9aa7b0a4978a7d7064574a3e3124170b00000000000000000000000000000a16222e3945515d6974808c98a4afafabaaa7a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a6aaabaeb2a69a8e82766b5f53473b2f24180c000000000000000000000000020e1a26323d4955616d7884909ca8aca094887c7065594d4242424242424242424242424242424242424242424a56626e7a86929ea9a99d92867a6e62564b3f33271b0f0400000000000000000009131d27313a434c545c646b72787e83888c8f929598999b9c9d9fa4aba39e9d9c9a999794918e8a85817b756e675f584f463d342a20160c010000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0a29f9286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f0200000000000000000000000000000005111b26313b46505b65707a85909aa59b91867c71675c5248484848484848484854616e7b8894a1ada09386796d6053484848484846423b332a1f150a000000010c18232e3841484e5050505050505050504d4840383029231f1c1b1a1c1e232b343d48535f6b77838f9ba7b0a3978a7e7165584c3f3226190d00000000000000000000000000000006121e2a36424e5a66727e8a96a2aa9e92867a6e62564b3f33271b0f040000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c000000000000000000000915212d3945515d6975818d99a5a69a8e82766a5e5c6874808c98a4a79b8f83776b5f53473b2f23170b00000000000000000000000000000000000000000a141f29343e49535e68737d88929da79e93887e747f8a949fa79d92887d73685e53493e34291f150a0000000000000000000000000000000000000000000000000000000000000815222f3b4855616d78797979797979766b5f5246392c1f130600000000000000000000000000000000000000000000000000000000000000000000000f1b2835424e5b6875828e9ba8a5988b7e7165584b3e3225180b0000000000000000000000000000000000000f1b27333f4a545c61626262626262626262626262626262626262626262626262626262626262626262626262626262626262615b52483c3125190c000b17222d38424a5154555758595a5b5c5d5c574f453b2f23181616161617191b1e232b343f4b5763707c8996a2afa79a8e8174685b4e4235281c0f0013202c3946535f6c798693a0acaa9d9084776a5d5044372a1d110400000000000d1a2633404d596673808d99a6b1a4978a7d7164574a3e3124170b000000000000000000000000000005111d2935404c5864707b87939fabb6aea49c98989898989898989898989898989898989898989898989aa1abb6ada195897d72665a4e42372b1f1307000000000000000000000000000915212d3944505c6874808b97a3afa5998d8175695d514e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4f5b67737e8a96a2aea5998d8175695d52463a2e22160b00000000000000000005101b252f39434c555e666e767d83898f94989c9fa2a4a6a7a6a5a6abb0a9a5a4a5a7a5a3a19e9a96918c868079716a61584f463c32281e13080000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c7986939595959286796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f02000000000000000000000000000000000a141f29343e49545e69737e88939ea3988e83786e63594e443c3c3c3c3c3c4854616e7b8894a1ada09386796d6053463c3c3c3c3a36302921180e0300000005111d29343f4a535a5d5d5d5d5d5d5d5d5d59524a423b342f2b292727282b2f353d454f5a65707b87939fabaca094877b6f6256493d3024170b000000000000000000000000000000020e1a26323e4a55616d7985919da9a3978b7f73675b4f43382c2014090000000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c000000000000000000020e1a26323e4a56626d7986929da9a2968a7e72665a57646f7c8894a0ab9f93877b6f63584c4034281c100400000000000000000000000000000000000000030d18222c37414c56616b76818b95a0a59a8f857b86909ba6a0958b80766b61564c42372d22180d030000000000000000000000000000000000000000000000000000000000000714202d3945515c666c6c6c6c6c6c6c6b645a4f43372a1e110500000000000000000000000000000000000000000000000000000000000000000000000f1b2835424e5b6875828e9ba8a5988b7e7165584b3e3225180b000000000000000000000000000000000000121e2b3744505b666e6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6c64594d4135281c0f0006111c262f383f4548494a4b4c4d4f5051504c453d33292222222223232425272b2f353d46505c6773808c98a5b0a4988b7e7266594d4033271a0e0013202c3946535f6c7986929facaa9d9084776a5d5044372a1d110400000000000d1a2633404d596673808c99a6b0a3978a7d7063574a3d3124170a0000000000000000000000000000000c1824303c47535f6b76828e9aa6b2a89c928b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8f9aa5b2a89c9185796d6155493e32261a0e020000000000000000000000000004101c2834404b57636f7b86929eaaa99d92867a6e625b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5f6b77838f9ba7aca094887c7065594d4135291e12060000000000000000010c17222c37414b555e67707880878e959a9fa4a8a6a29f9c9b99989aa0a89e9898999a9c9fa2a6a6a29d97918b837b736a61584e443a2f251a0f0300000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c7986888888888886796c5f5246392c1f130000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f0200000000000000000000000000000000030d18222d37424c57616c77818c96a19f958a80756a60554b40362f2f2f3b4854616e7b8894a1ada09386796d6053463a2f2f2f2d2a251f170f06000000000814212d3945515c656a6a6a6a6a6a6a6a69645c544c46403b3835343435373b40474f57616b76818c98a4afa89c9084786b5f53463a2e211508000000000000000000000000000000000915212d3945515d6974808c98a4a79b8f83776c6054483c3125190e0200000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00000000000000000006121e2a36424e5a66727e8a96a2aa9e92867a6e6256535f6b7784909ca8a4988c8074685c5044382c201408000000000000000000000000000000000000000006101b25303a454f5a646f79848e99a3a1968c848d97a2a3988e83796e645a4f453a30251b10060000000000000000000000000000000000000000000000000000000000000004111d2934404a545b5f5f5f5f5f5f5f5f5a52483e32261a0e0200000000000000000000000000000000000000000000000000000000000000000000000f1b2835424e5b6875828e9ba0a0988b7e7165584b3e3225180b00000000000000000000000000000000000013202c3946535f6c787c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c75695c5043362a1d1000000a141d262e34383b3c3d3e3f4142434443403b332c2f2f2f2f2f2f30313234373b40474e58626d7884909ca8aca094887b6f63564a3e3125180c00121f2c3845525e6b7885919eaaaa9e9184776b5e5145382c1f130905030304070f1b2834414e5a6774818d9aa6afa296897c6f6356493d3023160a00000000000000000000000000000007131f2b37424e5a66727d8995a1ada79a8d817e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e8a97a4afa3988c8074685c5145392d21150a0000000000000000000000000000000c17232f3b47525e6a76828d99a5aea2968a7e7368686868686868686868686868686868686868686868686868707c8894a0aba79b8f83776c6054483c3025190d01000000000000000007121e29333e49535d677079828a9299a0a6a9a39e999693908e8c8b8e98a2968c8b8c8e9092969a9ea4a8a39c958d857c736a60564c41362b20140900000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946525f6c787b7b7b7b7b7b7b776b5f5245392c1f120000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f02000000000000000000000000000000000006101b26303b45505a656f7a858f9aa49c91877c72675d52473d32282e3b4854616e7b8894a1ada09386796d6053463a2d2222211e1a140d050000000000091623303c4955626d7677777777777777756d665e57514b47444241414243474b5158616a737d88939ea9aea3978c8074685b4f43372b1e12050000000000000000000000000000000005111d2934404c5864707b87939eaaa094887c7065594d42362a1f130700000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c0000000000000000000a16222e3a46525e6a76828e9aa6a69a8e82766a5e524f5b6773808b97a3a89c9084786c6055493d3125190d01000000000000000000000000000000000000000009131e28333d48525d67727c87919ca69d9490959ea69c91877c72675d52483d33281e14090000000000000000000000000000000000000000000000000000000000000000000c18232e38424a5052535353535353524f4840372c21160a0000000000000000000000000000000000000000000000000000000000000000000000000f1b2835424e5b6875828e939393938b7e7165584b3e3225180b00000000000000000000000000000000000013202c3946535f6c7986898989898989898989898989898989898989898989898989898989898989898989898989898989898376695d5043362a1d100000020b141c23282c2e2f3032333435363737342f34393b3c3c3c3c3c3c3d3e4043474b5158616a747e8995a0aca69b8f83776b5f53473b2e22160900111e2a3744505d6976838f9ca8ac9f9286796d6054473b2f241a141110101113171f2b3743505c6975828e9ba8ada094877a6e6155483b2f221509000000000000000000000000000000030e1a26323e4955616d7985909ca8a99d9185797171717171717171717171717171717171717176828e9aa6ab9f93877b6f63584c4034281c110500000000000000000000000000000007121e2a36424e5965717d8994a0aca79b8f83777575757575757575757575757575757575757575757575757575818c98a4aea2968a7e73675b4f43382c2014080000000000000000010d18242f3a45505a656f78828b949ca4aba49d97928d89868381807e8895a093867e808183868a8e93989ea5a79f978f867c72685d53483c31261a0e03000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f1300121e2b3743505b666d6f6f6f6f6f6f6f6d665b4f43372a1e110000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f0200000000000000000000000000000000000009141e29343e49535e68737d88939da3998e83796e64594f44392f2e3b4854616e7b8894a1ada09386796d6053463a2d201514120e09030000000000000a1623303d495663707c8484848484848480777069625c5753514f4e4d4e5053575c636a737c858f99a4afa89d92867b6f63574b3f33271b0f0200000000000000000000000000000000000c1824303c47535f6b76828e99a5a5998d81756a5e52473b2f24180d01000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c0000000000000000030f1b27333f4b57636e7a87939faba2968a7e7266594d4b57636f7b87939faba195897d7165594d4135291d11050000000000000000000000000000000000000000020c17212c36414b56606b75808a959fa6a09da0a79f948a80756a60554b41362c21170c0200000000000000000000000000000000000000000000000000000000000000000007121c2630383f434646464646464646433e372e251a10050000000000000000000000000000000000000000000000000000000000000000000000000f1b2835424e5b6875828686868686867e7165584b3e3225180b00000000000000000000000000000000000013202c3946535f6c7986939696969696969696969696969696969696969696969696969696969696969696969696969696908376695d5043362a1d10000000020a11181c20212324252627282a2a2a2e373f45484949494949494a4b4d4f53575c636a737c86909ba6a99f94897e73675b4f43372b1f1206000f1c2835424e5b6773808c99a5aea195887c7064584c41362c25211e1d1d1e202329313c47535f6b7884919daaaa9d9185786c5f53463a2d201407000000000000000000000000000000000a15212d3945505c6874808c97a3aea2968a7e7266656565656565656565656565656565656f7b87939faba69a8e82766b5f53473b2f24180c00000000000000000000000000000000020e1925313d4954606c7884909ba7aba0948882828282828282828282828282828282828282828282828282828285919da9a99d92867a6e62564a3f33271b0f03000000000000000007121e2935404b56616c76818b949da6aaa19a938c86827d7a7775737b8895a09386797374777a7d82878d949ba3a9a1988e847a6f64594e42372b1f1307000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f13000f1b27333f4a545c6162626262626262615c54493e33271b0f0000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f02000000000000000000000000000000000000020d17222c37414c57616c76818b96a0a0958b80756b60564b41362e3b4854616e7b8894a1ada09386796d6053463a2d201308050200000000000000000916222f3c4955626f7b8890909090909089827a736d6863605d5b5a5a5b5d5f63686e747c858e97a1abaca1978c81756a5e53473b2f23170b00000000000000000000000000000000000008131f2b37424e5a65717d8994a0a99e92867a6f63584c4035291e1207000000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c000000000000000007131f2b37434f5b67737f8b97a3aa9e92867a6e62554947535f6b77838f9ba7a5998d8175695d51463a2e22160a000000000000000000000000000000000000000000050f1a242f39444e59636e78838d98a2acaaaca2978d82786d63594e44392f241a0f0500000000000000000000000000000000000000000000000000000000000000000000000b141e262d3337393939393939393937322c251c1309000000000000000000000000000000000000000000000000000000000000000000000000000e1b2835414e5a677379797979797979797064574b3e3125180b00000000000000000000000000000000000013202c3946535f6c798693a0a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a29d908376695d5043362a1d100000000000060c101315161718191b1c1d202c364049505555555555565657585a5c5f63686e747c858e98a2aaa1988d83786d61564a3f33271b0f03000d1a26333f4b5864707c8995a0aca4988c8074685d52483e37312d2b2a2a2a2c2f343b434d58646f7b8894a0aca59a8d8175695c5044372b1e12050000000000000000000000000000000005111c2834404c57636f7b87939eaaa69a8f83776b5f585858585858585858585858585c6874808c97a3ada195897d72665a4e42362b1f130700000000000000000000000000000000000915202c3844505c67737f8b97a2aea499918e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8f97a2ada4998d8175695d52463a2e22160b0000000000000000000b17232f3a46515d68737e88939da6aaa1988f88817b76716d6a686f7b8895a09386796d686a6d71767b8289919aa4aaa0968b81756a5f53473c3024170b000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f13000b17222d38424a51555555555555555554514a41382d22160b0000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f020000000000000000000000000000000000000006101b25303a454f5a646f7a848f99a49c92877d72675d52483d333b4854616e7b8894a1ada09386796d6053463a2d201307000000000000000000000815222e3b4855616e7b88949d9d9d9d9b938c857e79746f6c6a68676768696c6f73797f868e97a0a9ada49a8f857a6f64594d42362a1f1307000000000000000000000000000000000000030e1a26323d4955606c77838f9aa6a3978b8074685d51463a2f23180d020000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00000000000000000b17232f3b47535f6b77838f9ba7a69a8e8276695d5145434e5b67737e8b97a3aa9e92867a6e62564a3e32261a0e0200000000000000000000000000000000000000000008131d28323d47525c67717b86929eabb6aa9d91867b71665c51473c32271d1308000000000000000000000000000000000000000000000000000000000000000000000000020c141c22272b2c2c2c2c2c2c2c2c2a26211a130a01000000000000000000000000000000000000000000000000000000000000000000000000000d1926323f4b5661696c6c6c6c6c6c6c6c685e53483c2f23160a00000000000000000000000000000000000013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09d908376695d5043362a1d1000000000000000040708090a0c0d0e0f1925313d48525b61626262626263636466686b6f73797f868e97a0a9a1988f867b71665b50453a2e22160b00000a17232f3c4854606c7884909ba6a89c91857a6e645a5048423d3937363637393b40454c555f6a75808c98a4aca095897d7165594d4034281b0f0300000000000000000000000000000000000c18232f3b47535e6a76828e9aa5ab9f93877b6f64584c4b4b4b4b4b4b4b4b4b4b55616c7884909ca8a89c9085796d6155493e32261a0e02000000000000000000000000000000000004101c27333f4b57626e7a86929ea9aba29c9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9ca1a9aba094887c7064594d4135291d1206000000000000000004101c28343f4b57626e79848f9aa4aca2988f867d76706a65615e626f7b8895a09386796d605e61656a70778088929ca6a89d92877b7064584c4034281b0f030013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130006111c2630384045484848484848484848453f382f261b11050000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f02000000000000000000000000000000000000000009141e29333e48535d68727d88929da3998e84796f645a4f443a3b4854616e7b8894a1ada09386796d6053463a2d201307000000000000000000000714212e3a4754616d7a8794a0aaaaaaa59e97908a84807c79767574747476787b80848a9198a0a9ada49b92887e73685e53473c31251a0e02000000000000000000000000000000000000000915212d38444f5b66727d8995a0a89c9185796e62574b4035291e13070000000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c0000000000000004101c2834404c5864707c8894a0aca2968a7d7265594d413e4a56626e7a87939faba2968a7e72665a4e43372b1f13070000000000000000000000000000000000000000000a141f29343e49535d68727d87929eabb1aa9d91867b71665c51473c32281d130800000000000000000000000000000000000000000000000000000000000000000000000000020a11171b1e202020202020201f1e1a1610090100000000000000000000000000000000000000000000000000000000000000000000000000000a16222e3a454f585e5f5f5f5f5f5f5f5f5c564d42372b1f130700000000000000000000000000000000000013202c3946535f6c7986939393939393939393939393939393939393939393939393939393939393939393939393939393908376695d5043362a1d100000000000000000000000000000000f1c2835414d59646d6f6f6f6f6f6f70717375787b80848a9198a0a59e978f867d746a5f554a3f34281d110600000713202c3844505c67737e8a95a0aaa1968b80766c625a534d49464443434445484b50575e67717b86919da8a59a8f84786d6155493d3124180c00000000000000000000000000000000000007131f2a36424e5a65717d8995a1aca4988c8074685c50453e3e3e3e3e3e3e424d5965717d8995a1ada3988c8074685c5045392d211509000000000000000000000000000000000000000b17232e3a46525e6975818d99a5b0ada9a8a8a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a8a8a8acb2a79b8f83776c6054483c3025190d0100000000000000000814202c3844505c68737f8a96a1aca59a90867c746c645e595555626f7b8895a09386796d6053555a5f666d76808a949faba3988c8074685c5044372b1e12060013202c3946535f6c798693a0ac9f9286796c5f5246392c1f1300000a141e262e34393b3c3c3c3c3c3c3c3b39342e261d140a000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f020000000000000000000000000000000000000000020c17212c37414c56616b76818b96a0a0968b81766b61564c413b4854616e7b8894a1ada09386796d6053463a2d201307000000000000000000000713202d3a4653606c798693a0acb0a7a09ea09b95908c888583828181818285878b90959ca2aaaba39b928980766c61574c41362b201409000000000000000000000000000000000000000004101c27333e4a56616d78848f9aa6a2968a7f73685c51463b2f24190e0200000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c000000000000000814202c3844505c6874808c98a4aa9e9286796d6155493d3a46525e6a76828e9aa7a79b8f83776b5f53473b2f23170b000000000000000000000000000000000000000007111c26303b45505a656f7a848f99a4a6a4a6a2978d83786e63594e44392f241a10050000000000000000000000000000000000000000000000000000000000000000000000000000060b0f121313131313131313110e0a050000000000000000000000000000000000000000000000000000000000000000000000000000000006121d28333d464d515353535353535353504b443b30261a0f0300000000000000000000000000000000000013202c3946535f6c7986868686868686868686868686868686868686868686868686868686868686868686868686868686868376695d5043362a1d10000000000000000000000000000000101d2a3743505d69767c7c7c7c7c7c7d7e808284878b90969ca29f99938c857d746b62584e43382e23170c010000030f1c28333f4b57626d78838e98a2a79c92887e756c655e595552515050515254575c62697079838d98a3a79e93897e73675c5044382d201408000000000000000000000000000000000000020e1a26313d4955616c7884909ca7a89c9185796d6155493d32323232323a46525e6a76828e99a5aa9f93877b6f63584c4034281c11050000000000000000000000000000000000000006121e2a35414d5965707c8894a0acb7afa59e9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9ca3acb7aea2968a7e73675b4f43372c2014080000000000000000000b1724303c4854606c7884909ca7aa9e93897e746a625a534d4955626f7b8895a09386796d6053494e545b646e78838e9aa6a99d9184786c5f53473a2e2115080013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000020c141c23292d2f2f2f2f2f2f2f2f2f2c29231c140b02000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000000000000000020302010000121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f0200000000000000000000000000000000000000000005101a252f3a444f5a646f79848e99a39d92887d72685d53483e4854616e7b8894a1ada09386796d6053463a2d2013070000000000000000000006131f2c3945525f6c7885929faba99e9591959ca19c989492908e8e8e8e8f9194979ca1a7aca7a099918980776d645a50453b30251a0e030000000000000000000000000000000000000000000b16222d3944505b67727e8995a0a79c9085796e62574c41352a1f140900000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c000000000000000c1824303c4854606c7884909ca8a69a8e8275695d51453936424e5a66727e8a96a2ab9f93877b6f63574b3f34281c1004000000000000000000000000000000000000040e18232d38424d57626c76818b96a0a29a979ba39f948a80756a60564b41362c21170c02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c17212b343b4145464646464646464644403a32291f140900000000000000000000000000000000000000131f2c3946525f6b7679797979797979797979797979797979797979797979797979797979797979797979797979797979797974685c4f4336291d10000000000000000000000000000000111d2a3744505d6a778489898989898a8b8c8e9194979c9d9a97938e88827b736b625950463c31271c1106000000000b17232f3a45515c67727c869099a2a49990877e766f6a65615f5d5d5d5d5f6164686d737a838b959fa79f958c82776c61564b3f34281c1004000000000000000000000000000000000000000915212d3844505c6873808b97a3ada195897d71665a4e42362a2527333f4b57636e7a86929eaaa69a8e82766a5f53473b2f23180c0000000000000000000000000000000000000000010d1925313c4854606c77838f9ba7b3a99e938e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e919ba6b2a99d91867a6e62564a3f33271b0f030000000000000000000e1b2733404c5864717d8995a1aca4998d82776c62585048424855626f7b8895a09386796d605346434a525c66727d8995a2ada094887b6f6256493c3023170a0013202c3946535f6c798693a0ac9f9286796c5f5246392c1f13000000020b12181d20222222222222222222201d18120a0200000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000000000000003080c0e0f0f0d0a06121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f020000000000000000000000000000000000000000000009131e28333d48525d67727d87929ca4998f84796f645a4f454854616e7b8894a1ada09386796d6053463a2d2013070000000000000000000004121e2b3845515e6b7784919eaba6998d848b92989ea3a19e9c9b9a9a9b9c9ea0a4a8aaa6a19b958e877f776e655c52483e33291e13080000000000000000000000000000000000000000000005111d28343f4a56616d78838f9aa5a1968a7f73685d52473b30251a0f04000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00000000000005111d2935414d5965717d8995a1ada2968a7d7165594d4135323e4a56626e7a86929eaaa4988c8074685c5044382c2014080000000000000000000000000000000000000b15202a353f4a545e69737e88939da59a908a919ba69c91877c72675d52483e33291e140900000000000000000000000000000000000000000000000000000000000000000000000000000000050a0c0e0e0e0e0e0e0e0e0e0e0c08040000000000000000000000000000000000000000000000000000000000000000000000000000050f19222a303538393939393939393938342f2820170d0200000000000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6a62584c4034271b0e000000000000000000000000000000111d2a3744505d6a778490969696969697999b9d9a9593918e8b87827d777069615950473e342a20150b000000000006121e2934404b55606a747e879099a0a2999088817b75716e6b6a69696a6b6d7074787e858c959da49d958d837a70655b50453a2e23170b000000000000000000000000000000000000000004101c28343f4b57636f7a86929eaaa69a8e82766a5e52473b2f232c38444f5b67737f8b97a3ada195897d71665a4e42362b1f13070000000000000000000000000000000000000000000814202c38434f5b67737e8a96a2aea79a8d81818181818181818181818181818181818181818181818a97a4b0a4988d8175695d51463a2e22160a00000000000000000000111d2a36434f5c6874818d999fa29f93887c70655a50463e3c4855626f7b8895a09386796d6053463a404a55616d7986929faba3978a7d7164574b3e3125180b0013202c3946535f6c798693a0ac9f9286796c5f5246392c1f13000000070f171d222628282828282828282826221d170f0700000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000000000000080e14181b1c1c1a1611121f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f0200000000000000000000000000000000000000000000010c17212c36414b56606b75808b95a0a0968b81766c61564c4854616e7b8894a1ada09386796d6053463a2d2013070000000000000000000001111e2a3744515d6a7784909daaa6998c8080878d93989c9fa2a4a6a7a7a7a6a5a3a19d9a95908a847d756d655c534a40362c22170d0200000000000000000000000000000000000000000000000b17222e3945505b67727d89949fa79c90857a6e63584d42362b20150a000000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c0000000000000915212d3945515d6975818d99a5aa9e9285796d6155493d312d3a46525e6a76828e9aa6a89c9084786c6054483d3125190d010000000000000000000000000000000008121d27313c46515b66707b85909aa59e93897f8a949fa3988e84796f645a4f453a30251b110600000000000000000000000000000000000000000000000000000000000000000000000000050b1116191b1b1b1b1b1b1b1b1b1a18140f0902000000000000000000000000000000000000000000000000000000000000000000000000000710181f25292c2c2c2c2c2c2c2c2c2b28231d160e0500000000000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5e5950463b3024180c000000000000000000000000000000111d2a3744505d6a7784909da2a2a3a3a4a5a79e92888684827e7b76716b655e574f473e352c22180e030000000000010c18232e39444e58626c757e878f969ca19a938c86817d7a7877767677787a7c80848a90979e9f99938b837a71685e54493e33281d12060000000000000000000000000000000000000000000b17232f3b46525e6a76828d99a5aa9e93877b6f63574b3f3328303c4854606c7884909ba7a89c9085796d6155493d32261a0e02000000000000000000000000000000000000000000040f1b27333f4a56626e7a85919da9a89c9085797474747474747474747474747474747474747475828d99a5aba094887c7064594d4135291d120600000000000000000000131f2c3945525e6b77848d909295988f83776b5f54493e343c4855626f7b8895a09386796d6053463a3945515e6a7784909da9a5988c7e7265594c3f3226190c0013202c3946535f6c798693a0ac9f9286796c5f5246392c1f13000006101921282e32353535353535353534322e2821190f06000000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000000010a1219202427292826221d161f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f020000000000000000000000000000000000000000000000050f1a242f3a444f59646e79848e99a39d92887d73685e534954616e7b8894a1ada09386796d6053463a2d2013070000000000000000000000101d2a3643505d697683909ca9a69a8d81757c82878c90939698999a9a9a99989794918e89847f79726b635b534a41382e241a100500000000000000000000000000000000000000000000000006111d28343f4a56616c77838e99a4a1968b8074695e53483d32271c11060000000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c0000000000020e1a26323d4955616d7985919da9a69a8d8175695d5145392d2935414d5966727e8a96a2aca195897d7165594d4135291d1105000000000000000000000000000000040f19242e39434e58636d77828c97a1a2978c8278838e98a3a0958b81766b61574c42372d22180d030000000000000000000000000000000000000000000000000000000000000000000000060f161d22252728282828282828282724201a140c0300000000000000000000000000000000000000000000000000000000000000000000000000060d14191d1f20202020202020201f1c18120c040000000000000000000000000000000000000000000a16212c3740484f52535353535353535353535353535353535353535353535353535353535353535353535353535353535353524e473e342a1f1307000000000000000000000000000000111d2a3744505d6a7784909da4a4a4a5a6a8a99d9084807d7975706a66605a544d453d352c231a10060000000000000007121d27323c47505a636c757d848b91969a9d97928d8a8785848383848586898c90959b9b98938e88817971685f564c42372d22170c0100000000000000000000000000000000000000000006121e2a36424d5965717d8894a0aca3978b8073685c5044382c35414d5965707c8894a0aca3978c8074685c5044392d21150900000000000000000000000000000000000000000000000b16222e3a46515d6975818c98a4ada195897d7167676767676767676767676767676767676e7a86929eaaa79b8f83776b6054483c3024190d010000000000000000000013202c3946535f6c787e818386898b8b7f73675b4f43372f3c4855626f7b8895a09386796d6053463a36434f5c6975828f9ca9a6998c807366594c403326190d0013202c3946535f6c798693a0ac9f9286796c5f5246392c1f1300020d18222b333a3f4142424242424242413e3a332b21180d020000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000000009131c242b30343635322e28201f2c3845525f6b7885929faca89b8e8275685b4e4235281b0f0200000000000000000000000000000000000000000000000008131d28323d48525d67727c87919ca49a8f857a6f655a5054616e7b8894a1ada09386796d6053463a2d20130700000000000000000000000f1c2936424f5c6975828f9ca8a79a8e817470767b808386898b8c8d8e8d8d8c8a8885827d79736e676059514941382f261c120800000000000000000000000000000000000000000000000000000c17222e3944505b66717d88939ea79c91867a6f64594e43382d22170c0100000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c000000000006121e2a36424e5a66727e8a96a2aea295897d7165594d41352925313d4955616d7986929eaaa5998d8175695d5145392e22160a0000000000000000000000000000010c16212b36404b555f6a747f89949ea69b90857b717c87919ca79d92887d73685e53493f342a1f150a00000000000000000000000000000000000000000000000000000000000000000000050f1821282e3234343434343434343433302c251e150c020000000000000000000000000000000000000000000000000000000000000000000000000002080d1012131313131313131312100c07010000000000000000000000000000000000000000000005101a252e373e434646464646464646464646464646464646464646464646464646464646464646464646464646464646464645423c352c22180d02000000000000000000000000000000111d2a3744505d6a7784909797979798999b9da0968f8c8985817b767069615951483f362c22170d0200000000000000000b16202b353e48515a636b727980858a8d90949c9996939190909090919395989c96928f8c87837d766f675f564d443a30261b100500000000000000000000000000000000000000000000020e1925313d4854606c78848f9ba7a89c9084786c6054493d313a46515d6975818d99a5aa9e93877b6f63574c4034281c1005000000000000000000000000000000000000000000000006121d2935414d5864707c88939faba59a8e82766a5e5a5a5a5a5a5a5a5a5a5a5a5a5a5b67737f8b97a2aea2968a7e73675b4f43372b2014080000000000000000000000121e2b3744505c666e7174777a7c7f827c6f63574a3e322f3c4855626f7b8895a09386796d6053463a36434f5c6976828f9ca9a6998c807366594c403326190d0013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130008141f2a343d454b4e4e4e4e4e4e4e4e4e4a453d33291f13080000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000006111b252e363c4042423e39322b232c3845525f6b7885929faca89b8e8275685b4e4235281b0f02000000000000000000000000000000000000000000000000010c16212b36404b55606b75808a959fa1968c81766c615754616e7b8894a1ada09386796d6053463a2d20130700000000000000000000000f1b2835424e5b6874818e9ba7a89b8f8275686a6f73777a7c7e80818181807f7d7b7875716d68625c564f473f372f261d140a00000000000000000000000000000000000000000000000000000006111d28333e4a55606b76828d98a3a2978c81766b5f54493e33281e130800000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00000000000a16222e3a46525e6a76828e9aa6aa9d9185796d6155493d3125212d3945515d6975818d99a5a99e92867a6e62564a3e32261a0e020000000000000000000000000009131e28323d47525c67717c86919ba59f94897e746a75808b95a0a49a8f857a70655b50463b31271c12070000000000000000000000000000000000000000000000000000000000000000020d17212a32393e414141414141414141403d3730271e130900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131c252c3237393939393939393939393939393939393939393939393939393939393939393939393939393939393939393936312b231a110600000000000000000000000000000000111d2a3744505d6a77848a8a8a8a8a8b8c8e9194989c9995918c87817a736b635a51483e34291f14090000000000000000040e19232c363f48515961686e74797d81848a96a3a2a09e9d9d9c9d9ea0a2a5988c8583807b77716b655d564d443b32281e14090000000000000000000000000000000000000000000000000914202c3844505b67737f8b96a2aca095897d7165594d41353e4a56626e7a86929da9a69a8e82766a5f53473b2f23180c000000000000000000000000000000000000000000000000010d1924303c48545f6b77838f9aa6aa9e92877a6f63574d4d4d4d4d4d4d4d4d4d4d54606c77848f9ba7a99d91857a6e62564a3e33271b0f0300000000000000000000000f1b28333f4a545d6265686a6d707375756c6054473b2e2f3c4855626f7b8895a09386796d6053463a3945515e6a7784909daaa5988c7f7265594c3f3226190c0013202c3946535f6c798693a0ac9f9286796c5f5246392c1f13000d1925303b464f565a5b5b5b5b5b5b5b5a564f453b3024190d0000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d110400000000000000000000000c17222d3740474d4f4e4a443c352e2c3845525f6b7885929faca89b8e8275685b4e4235281b0f0200000000000000000000000000000000000000000000000000040f1a242f39444e59636e78838e98a39d93887e73695e54616e7b8894a1ada09386796d6053463a2d20130700000000000000000000000e1b2734414d5a6774818d9aa7a99c8f8376695f63676b6d7072737374747372716f6c6965615c57514b443d352d251d140b02000000000000000000000000000000000000000000000000000000000b17222d38444f5a65707b86919ca89d92877c71665b50453a2f24190e03000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00000000030f1b27333f4b57636e7a87939eaaa5998d8175695d5145392d201d2935414d5965717d8995a1ada2968a7e72665a4e42362b1f130700000000000000000000000005101a252f3a444f59636e78838d98a2a3988d82786d636e79848e99a4a1968c82776d62584d43382e23190f040000000000000000000000000000000000000000000000000000000000000008131e29333c444a4d4e4e4e4e4e4e4e4e4d48413930251a0f03000000000000000000000000000000000000000000000000000000000000000205080a0c0d0e0f1010100f0f0e0c0b090604010000000000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a25201911080000000000000000000000000000000000111d2a3743505d6a767d7d7d7d7d7d7e808285888c91979e9d98928c857d756c635a50453b30251a0f03000000000000000007111a242e37414a535b636a71777c81848b96a3a5a2a09f9e9e9fa0a2a4a5988c84817d78726c655d554d443b322920160c0200000000000000000000000000000000000000000000000004101c27333f4b56626e7a86929da9a5998d81756a5e52463a434f5b67727e8a96a2ada195897d71665a4e42362a1f13070000000000000000000000000000000000000000000000000008141f2b37434f5b66727e8a96a1ada3978b7f73675c504441414141414141414d5864707c8894a0aca4988d8175695d51463a2e22160a0000000000000000000000000b17232e38424b5256585b5e6163666969635a4f44382b2f3c4855626f7b8895a09386796d6053463a424b56616d7a86929faba4978a7e7164584b3e3225180b0013202c3946535f6c798693a0ac9f9286796c5f5246392c1f1300101d2935414d586167686868686868686761574c4135291c100000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d11040000000000000000000004111d28343f4952595c5b564e473f38313845525f6b7885929faca89b8e8275685b4e4235281b0f02000000000000000000000000000000000000000000000000000008121d27323d47525c67717c87919ca59a8f857a70655b616e7b8894a1ada09386796d6053463a2d20130700000000000000000000000d1a2733404d596673808c99a6aa9d9083776a5d575b5e6163656667676766656462605d5955504b464039322b231b130b02000000000000000000000000000000000000000000000000000000000005111c27323d49545f6a75808b96a1a4998d82776c61564b40362b20150a000000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c0000000007131f2b37434f5b67737f8b97a3ada195897d7165594d4135281c1925313d4955616d7985919da9a69b8f83776b5f53473b2f23170b0000000000000000000000020d17222c37414b56606b75808a959fa69c91867b71665d67727d88929da89e93897e74695f554a40352b20160b010000000000000000000000000000000000000000000000000000000000000c1824303b454e565a5b5b5b5b5b5b5b5b59534b41372b2014080000000000000000000000000000000000000000000000000000000003070b0e111416181a1b1c1c1c1c1c1b1a19171513100d090501000000000000000000000000000000000000000000000000010910161a1e1f2020202020202020202020202020202020202020202020202020202020202020202020202020202020201f1d1a140e070000000000000000000000000000000102030f1c2935424e5a656e707070707071727375787c81868c939ba49e978f877e756b61574c42372b20140900000000000000000b16202b353f49535c656d757c82888d91949c9c999694929292929395989b9d94908d89847e776f675f564c42382e23190e03000000000000000000000000000000000000000000000000000b17222e3a46525d6975818d99a4aa9e92867a6e62564b3f48535f6b77838f9ba7a89c9084786d6155493d31261a0e0200000000000000000000000000000000000000000000000000030f1b27323e4a56616d7985919da8a79c9084786c6054483d34343434343945515d6975818d99a4aba094887c7064584d4135291d110600000000000000000000000006111c2730394046494c4f5154575a5c5d5951483e33272f3c4855626f7b8895a09386796d605346464c545d67727e8a96a2aea195887c6f6356493d3023170a0013202c3946535f6c798693a0ac9f9286796c5f5246392c1f1300121f2c3845515e69737575757575757573695d5145382b1f120000000000000000000f1c2835424f5b6875828f9084776a5d5044372a1d1104000000000000000000000814202d3945505b6468676059514a423b3845525f6b7885929faca89b8e8275685b4e4235281b0f020000000000000000000000000000000000000000000000000000010b16202b35404b55606a75808a949fa1978c82776c62616e7b8894a1ada09386796d6053463a2d20130700000000000000000000000c1926323f4c5965727e8c98a5aa9e9184776b5e514f52545758595a5a5a5a59575553504d4945403a352e282119120a01000000000000000000000000000000000000000000000000000000000000000b16212c37424d58636f7a85909ba59f94897e73685d52473c31261c11060000000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c000000000b17232f3b47535f6b77838f9ba7a99d9185796d6155493d30241814202c3845515d6975818d99a5ab9f93877b6f63574b3f33271c1004000000000000000000000a141f29333e48535d68727d87929ca6a0958a80746a5f56606b76818c96a1a59b90867b71665c51473d32281d1308000000000000000000000000000000000000000000000000000000000000101c2935414c5760666767676767676767655d53483c3024180b0000000000000000000000000000000000000000000000000000040a0e13171b1e2123252728292929292928272624221f1c1916120d0803000000000000000000000000000000000000000000000000050a0e111313131313131313131313131313131313131313131313131313131313131313131313131313131313131313110d0903000000000000000000000003070a0c0d0e0f10111926323d49535c626363636363646567696c70757b8289929ba4a19991877d73695e53483c3125190e0200000000000006111c27323d47515b656e777f878e94999d9b96918c89878685858586888b8f93999d99958f89817971685e544a40352a1f14090000000000000000000000000000000000000000000000000006121e2935414d5964707c8894a0aba2978b7f73675b4f434c5864707c88949faba3978b8074685c5044392d2115090000000000000000000000000000000000000000000000000000000a16222d3945515d6974808c98a4aca094897c7165594d4135292727323e4a56626e7985919da9a79b8f83776b5f54483c3024180d01000000000000000000000000000a151e272f353a3d404245484a4d50504d473f362c222f3c4855626f7b8895a09386796d60534d51575e666f79848f9aa6aa9e9286796d6054473b2e2215080013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c7982828282828282796c5f5246392c1f13000000000000000005101c2835424f5b6875828f9084776a5d5044372a1d1106000000000000000000000916232f3c4955616d75726a635c544d453e45525f6b7885929faca89b8e8275685b4e4235281b0f02000000000000000000000000000000000000000000000000000000040f19242e39434e58636e78838d98a29e93897e7469616e7b8894a1ada09386796d6053463a2d20130700000000000000000000000b1825323e4b5865717e8b98a4ab9e9285786b5f524545484a4c4d4d4d4d4d4c4b494744413d39342f29231d160f0700000000000000000000000000000000000000000000000000000000000000000004101b26313c47525d68737e89949fa59a8f84796e63594e43382d22170d0200000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00000004101c2834404c5864707b8894a0aca5998d8175695d5145382c2014101c2834404c5864707c8995a1ada3988c8074685c5044382c20140800000000000000000006111b26303b45505a646f79848e99a3a3998e83786e63584f5a646f7a858f9aa5a2978d83786e63594e44392f241a10050000000000000000000000000000000000000000000000000000000000121f2b3844515d697274747474747474746f64594c4033271a0d000000000000000000000000000000000000000000000000040a10151a1f23272a2d2f3233343536363636353432312e2c2926221d19140e08020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a0f141718191a1b1c1d1e212c37414a5156575757575757585a5c60646970778089929ca7a3998f857a6f64594d42362a1e12060000000000000c17222e39444e59636d77808991989fa098908a85807d7a797878797a7c7e83888e949ca09a938b837a70665c51473c31251a0f03000000000000000000000000000000000000000000000000010d1925303c4854606b77838f9ba7a79b8f83776c605448515d6974818c98a4aa9e93877b6f63574c4034281c100400000000000000000000000000000000000000000000000000000005111d2934404c58646f7b87939faba5998d8175695d52463a2e222b37434f5a66727e8a96a2aea2968a7e72675b4f43372b2014080000000000000000000000000000030c151d242a2e303336393b3e414343413c362d24222f3c4855626f7b8895a09386796d6054595d62686f78818b95a0aba59a8e8276695d5145382c1f13060013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c79868e8e8e8e8e86796c5f5246392c1f1300000000000000000b16212c38434f5b6875828f9084776a5d5044392e23170c010000000000000000000a1723303d4a5663707d7c756d665f57504845525f6b7885929faca89b8e8275685b4e4235281b0f020000000000000000000000000000000000000000000000000000000007121d27323c47515c66717b86919ba59a90857b70666e7b8894a1ada09386796d6053463a2d20130700000000000000000000000b1724313e4a5764707d8a97a4ac9f9286796c5f5346393b3d3f40414141403f3e3c3a3734312d28231e18120b0400000000000000000000000000000000000000000000000000000000000000000000000914202b36414c57626c77828d98a3a1968b80756a5f544a3f34291e130900000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c0000000814202c3844505c6874808c98a4ada195897d7165594d4034281c100c1824303c4854606c7884919ca9a89c9084786c6054483c3024190d0100000000000000030e18232d38424c57616c76818b96a0a79d92877c72675c5148535e68737e89939ea99f948a80756a60564b41362c21170c0200000000000000000000000000000000000000000000000000000000131f2c3946525f6c79818181818181818174675a4d4134271a0e0100000000000000000000000000000000000000000001080f151b21262b2f3336393c3e4041424343434242403f3d3b3835322e29251f1a140d0600000000000000000000000000000000000000000000000000000000000000000306090b0c0e0f0f1010100f0e0d0b09070401000000000000000000000000000000000000000000000000000000000000050d141b202325262728292a2b2c2c2f384046494a4a4a4a4a4b4c4d5054585e656d76808b95a0aba1978c81756a5e52463a2e221609000000000005111c28343f4a55606b758089929ba3a0978e867f7974706e6c6b6b6c6d6f72777c838a939ca59d958c82786e63584d42372b201408000000000000000000000000000000000000000000000000000814202c37434f5b67727e8a96a2aca094887c7064584c55616d7985919da9a59a8e82766a5e53473b2f23170c00000000000000000000000000000000000000000000000000000000000c1824303b47535f6b76828e9aa6a99e92867a6e62564a3e3327303b47535f6b77838f9ba6a99d9185796e62564a3e33271b0f03000000000000000000000000000000030b13191e212427292c2f3234363735312b25292d303c4855626f7b8895a09386796d606165696e737a818a939da7aa9f94897d7165594d4135291c10040013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c7986939b9b9b9286796c5f5246392c1f130000000000000006111c27323e49545f6a76828f9084776c61554a3f34291d12070000000000000000000a1723303d4a5663707d877f787069615a534b525f6b7885929faca89b8e8275685b4e4235281b0f0200000000000000000000000000000000000000000000000000000000000b15202a35404a555f6a747f8a949fa2978c82776d6e7b8894a1ada09386796d6053463a2d20130700000000000000000000000a1723303d4a5663707c8996a3ada09386796d6053473a2f313233343434343331302e2b2825211c18120d0b0b0a080500000000000000000000000000000003070a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0e19242f3a45505b66717c87919ca79c91877c71665b50453b30251a0f05000000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c0000000c1824303c4854606c7884909ca8a99d9185796d6155483c3024180c0814202c3844505c6874808c98a4aca094897c7165594d4135291d1105000000000000000b151f2a343f49545e69737e88939da7a0968b80756b60554a414c57616c77828d97a2a69c91877c72675d52483e33291e140900000000000000000000000000000000000000000000000000000000131f2c3946525f6c79868e8e8e8e8e8e8174675a4d4134271a0e010000000000000000000000000000000000000000040b131a20262c32373b3f4346494b4d4e4f4f4f4f4f4e4d4c4a4745423e3a35302b251f1811090200000000000000000000000000000000000000000000000000000004080c0f121517191a1c1c1c1c1c1c1b19181613110d0a06010000000000000000000000000000000000000000000000000000040e171f262c303233343536373839393835353a3d3d3d3d3d3d3e3f4144484d545c646e79848f9ba6a89d92867a6f63564a3e3225190d00000000000915212d3944505b67727c87919ba4a2988e857c746d6864615f5f5e5f6063666b7178818a949ea79e948a80756a5e53483c3024190d00000000000000000000000000000000000000000000000000030f1b27333e4a56626e7985919da9a4988d8175695d515a66727e8a96a1ada195897d71655a4e42362a1e1307000000000000000000000000000000000000000000000000000000000007131f2b37424e5a66727d8995a1ada2968a7e73675b4f43372b34404c5864707b87939faba4988c8175695d51453a2e22160a000000000000000000000000000000000001080d1215171a1d202225282a2a28282d3135393d404855626f7b8895a09386796d696d7175797e858c939ca5aca3988e83786c6155493d3125190d000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0a89f9286796c5f5246392c1f13000000000000000c17222d38444f5a65717c879294897d72675c50453a2f23180d0200000000000000000a1723303d4a5663707d8a8a827b736c645d56525f6b7885929faca89b8e8275685b4e4235281b0f020000000000000000000000000000000000000000000000000000000000040e19232e38434d58636d78828d97a29e94897e746e7b8894a1ada09386796d6053463a2d20130700000000000000000000000916232f3c4955626f7c8895a2ada194877a6e6154473b2e24262727272727262523211f1c18181818181818181714100b05000000000000000000000002090f13161818181818181818181818181818181818181e29343f4a545f6a75808b95a0a3988d82776d62574c41372c21160c010000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c000005111d2935414d5965717d8995a1ada5998d8175695d5144382c20140804101c2834404c5864707c8894a0aca5998d8175695d5145392d21150a00000000000007121c27313c46515b65707a858f9aa4a49a8f84796e64594e443a45505b65707b86909ba6a3998e84796f645a4f453a30261b1106000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929b9b9b9a8e8174675a4d4134271a0e0100000000000000000000000000000000000000050e151d242b32383d42474b4f525557595b5b5c5c5c5c5b5a585654514e4a46413c36302a231b130b03000000000000000000000000000000000000000000000000060b1014181c1f2224262728292929292827262422201d1a16120d08030000000000000000000000000000000000000000000000010c16202931373c3e3f4041424344454645413b33303030303031313234373c424a525d67737e8a96a2aea3978b7f73665a4e4135281c0f03000000010d1a26323e4a55616d78838e99a3a79b90867c726a625c58555352525254565a60666f78828d98a3a69c91867b7064584d4135291d1104000000000000000000000000000000000000000000000000000a16222e3a45515d6975818c98a4a99d9185796d62565f6b76828e9aa6a89c9084786d6155493d31261a0e020000000000000000000000000000000000000000000000000000000000030e1a26323e4955616d7985909ca8a79b8f83776b5f54483c303945515c6874808c98a4ab9f94887c7064584c4135291d1106000000000000000000000000000000000000000105080b0e101316191d23292f34393d4145494c5055626f7b8895a09386797275797d81858a90969da5aca39a91877c71665b5044382d211509000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f1300000000000006121d28333f4a55606b77828d989a8f83786d62564b40352a1e130800000000000000000a1723303d4a5663707d8a948d857e766f6760595f6b7885929faca89b8e8275685b4e4235281b0f0200000000000000000000000000000000000000000000000000000000000007121c27313c46515b66717b86909ba59b90867b707b8894a1ada09386796d6053463a2d20130700000000000000000000000815222e3b4855616e7b8894a1aea195887b6e6255483c2f25252525252525252525252525252525252525252524211c160f07000000000000000000050d141a1f2325252525252525252525252525252525252525252d38434e59636e79848f99a49f94897e73695e53483d33281d12080000000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00000915212d3945515d6975818d99a5ada195897d7165584c4034281c1004000b17242f3c4854606c7884909ca8a99d9186796e62564a3e32261a0e0200000000040f19242e38434d58626d77828c97a1a89d93887d72685d52473d333e49545f69747f8a949faaa0958b81766c61574c42372d22180e030000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929fa8a79a8e8174675a4d4134271a0e01000000000000000000000000000000000000060f171f272f363d43494e53575b5f62646667686969696968676563605d5a56524d47413b342d251d150c03000000000000000000000000000000000000000000060c11171c2024282b2e3032343536363636353433312f2c2926221e19140e090200000000000000000000000000000000000000000007121d28323b42484b4c4d4e4f50515253514c453c3228242424242426282b3038414b56626e7a86929faba79b8f8276695d5044372b1e110500000005111d2936424e5a66727d8994a0aaa1968a7f746a6058514c4846454546474a4f555d66707b87939eaaa3988c8175695d5145392d2014080000000000000000000000000000000000000000000000000006111d2935414c5864707c87939faba2968a7e72665a636f7b87939faba3978b8074685c5044392d211509000000000000000000000000000000000000000000000000000000000000000a15212d3945505c6874808c97a3aba094887c7064584c40353d4955616d7985919da8a69b8f83776b5f54483c3024180d010000000000000000000000000000000000000000000000020a121a21282e343a4044494d5155595c60636f7b8895a093867b7e8285898d91969ba1a8a9a19a91897f756a60554a3f33281c1004000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000010d18232e3945505b66717d88939ea095897e73685c51463b3024190e03000000000000000a1723303d4a5663707d8a96978f888179726a635f6b7885929faca89b8e8275685b4e4235281b0f02000000000000000000000000000000000000000000000000000000000000000a15202a353f4a545f69747e89949ea2978d82777b8894a1ada09386796d6053463a2d20130700000000000000000000000814212e3a4754616d7a8794a0ada296897c6f6256493c32323232323232323232323232323232323232323232302d282119110700000000000000040e171f262b2f313232323232323232323232323232323232323232323c47525d67727d88929da59b90857a6f655a4f443a2f24190f0400000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c00020e1925313d4955616d7985919da9a99d9185796c6054483c3024180c000007131f2b37434f5b6874808c98a4aea2968a7e72665a4e42362a1e1207000000010c16202b35404a555f6a747e89949ea8a1968c81766b61564b41362d37424d58626d78838e98a3a79d92887d73685e53493f342a1f150a0000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e010000000000000000000000000000000000060f182129313941484e545a5f63686b6e70727475757676757473726f6d6a66625d58534d463f372f271e150c03000000000000000000000000000000000000030a11171d23282c3034383b3d3f41424243434242413f3e3b3936322e2a25201a140d0600000000000000000000000000000000000000000c18242f3a444d5458595a5b5c5d5e5f5f5d574e44392e2217171718191b1f262f3a45525e6a7783909da9aa9e9185786b5f5246392c2013060000000714202d3945525e6a76828e9aa6a99d9185796e62584e46403c393838393b3e434b545f6a76828e9aa7a99d9186796d6155493c3024170b00000000000000000000000000000000000000000000000000010d1824303c48535f6b77838e9aa6a69a8e82766a5e6874808c98a3aa9e92877b6f63574b4034281c10040000000000000000000000000000000000000000000000000000000000000005111c2834404c57636f7b87929eaaa4988c8175695d514539424e5a66727d8995a1ada2968a7e72665b4f43372b1f14080000000000000000000000000000000000000000000000020b141c242b323940464b5055595d6165686c6f727b8895a19489878a8e9195999da2a7aaa49e97908880766d63594e43382d22170b00000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f13000000000007131e29343f4b56616c78838e99a4a69b8f84796e63574c41362a1f1409000000000000000a1723303d4a5663707d8a96a19a928b847c756d666b7885929faca89b8e8275685b4e4235281b0f0200000000000000000000000000000000000000000000000000000000000000030e18232d38434d58626d77828c97a29e93887d7b8894a1ada09386796d6053463a2d20130700000000000000000000000713202d3a4653606d798693a0aca3968a7d7063574a3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3d39332b23190f050000000000010c16202930373c3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e404b56616b76818b96a1a1978c81766b61564b40362b20160b00000013202c3946535f6c798693a0ab9e9285786b5e5865727e8c98a5a6998c7f7265594c3f3226190c0006121e2a36424e5a66727e8a96a2aea5998d8175685c5044382c2014080000030f1b27333f4b57636f7b8894a0aca69a8e83766b5f53473b2f23170b00000008131d28323d47525c66717b86909ba5a59a90857a6f655a4f443a2f26313b46515c66717c87919ca7a49a8f857a70655b50463b31271c110600000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e0100000000000000000000000000000000040e18212a333b434b52595f656b6f74777a7d7f81828283838281807e7c7976726e69645e575049413930271e150b0100000000000000000000000000000000050d141b22282e33383d414447494c4d4e4f4f4f4f4f4e4c4a4845423e3a35302b251f18110902000000000000000000000000000000000003101c2834404b565f6466676769696b6b6c6960564a3e3225190c0a0b0c0f141d2936424f5c6875828f9ba8aca093867a6d6054473a2d2114070000000a16232f3c4855616e7a86939faba6998d8175685d51463c35302d2c2c2c2e3239424e5a66727e8b97a4aea2968a7d7165584c3f33261a0d000000000000000000000000000000000000000000000000000008141f2b37434f5a66727e8a95a1ab9f93877b6f636c7884909ca8a59a8e82766a5e52473b2f23170b0000000000000000000000000000000000000000000000000000000000000000000c18232f3b47535e6a76828e9aa5a99d9185796d61564a3e47535e6a76828e9aa6a99d9185796e62564a3e32271b0f0300000000000000000000000000000000000000000000020b141d262e363d444b51575c6165696d7175787b7f828996a29b9493979a9ea1a5a9a7a39e99938c857e766d645b51473c32271c110600000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f1300000000020d19242f3a45515c67727e89949fabaca1968a7f74695d52473c31251a0f040000000000000a1723303d4a5663707d8a969da49d958e877f78706b7885929faca89b8e8275685b4e4235281b0f02000000000000000000000000000000000000000000000000000000000000000007111c26313b46505b66707b85909aa59a8f837b8894a1ada09386796d6053463a2d201307000000000000000000000006131f2c3946525f6c7985929faca4978a7d7164574b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b49443d352b21160b000000000007121d28323b42484b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4f5a646f7a858f9aa49d93887d72675d52473d32271d1207000013202c3946535f6c798693a0a09e9285786b5e5865727e8c98a0a0998c7f7265594c3f3226190c000a16222e3a46525e6a76828e9aa6aca195897c7064584c4034281c10040000000b17232f3b47535f6b77838f9ba7ab9f93877b6f63574b3f33271b0f0300010d19242f39444e59636e78838d98a2a99e93897e73685e53483d33281f2a343f4a55606a75808b95a0aba1968c82776d62584d43382e23170c00000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e01000000000000000000000000000000020c16202a333c454d555d646b71767b8084878a8c8d8e8f908f8f8e8d8b8986827e7a756f69625b534b423930271d1309000000000000000000000000000000070f171f262d33393f44494d505356585a5b5c5c5c5c5b5a595754524e4a46413c36302a231b140c030000000000000000000000000000000005121f2b3844515d6870727374757677787972665a4d4134271b0e020000030f1b2835414e5b6874818e9ba8aea194877b6e6154483b2e2115080000000c1825323e4b5764707d8a96a2afa3978a7e7165584c40352a23201f1f202227313d4a56636f7c8895a2aea6998d8174675b4e4135281c0f0200000000000000000000000000000000000000000000000000030f1b26323e4a56616d7985919ca8a3978b7f7367717c8995a1aca195897d71655a4e42362a1e130700000000000000000000000000000000000000000000000000000000000000000007131f2a36424e5a65717d8995a0aca2968a7e72665a4e424b57636f7b87939faaa4988c8175695d5145392e22160a00000000000000000000000000000000000000000000000a141d262f3840484f565c62686d7176797d8185888b8e929ba6a5a0a0a3a6aaa7a39f9b97928d87817b746c645b52493f352b20150b0000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000008141f2a35404c57626d78848f9aa5b1b2a79c90857a6f63584d42372b20150a0000000000000a1723303d495663707c848b939aa1a098918a827b737885929faca89b8e8275685b4e4235281b0f020000000000000000000000000000000000000000000000000000000000000000000a151f2a343f49545e69747e89939ea0958a7e8894a1ada09386796d6053463a2d201307000000000000000000000005121f2b3845515e6b7884919eaba4988b7e716558585858585858585858585858585858585858585858585858554f473d33271c1004000000000c18232f3a444d535758585858585858585858585858585858585858585858585858585d68737d88939da4998f84796e64594e44392e23180c000013202c3946535f6c7986939393939285786b5e5865727e8c939393938c7f7265594c3f3226190c000e1a27333f4a56626e7a87929ea0a09d9185786c6054483c3024180c0000000007131f2b37434f5b67737f8b97a0a0a0978b8073675c5044382c2014070005111e2a35414b56606b75808a959fa0a0978d82776c61574c41372c2118232e38434e59636e79848e99a0a09e93897e74695f554a3f34281c1004000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e010000000000000000000000000000000a141e28323c454e575f676f757c82878c909396989a9b9c9c9c9c9b999795928f8a86817a746d655d544b42392f251b100600000000000000000000000000071019212931383e454a5055595d60636567686969696968676563615e5a56524d47423b342d251e150d040000000000000000000000000000000613202c3946535f6c797f8081828384858275685c4f43362a1e130c0a090a101c2935424f5b6875828e9ba8aea194887b6e6154483b2e2115080000000d1a2633404c5966727f8c98a5aea295887c6f6256493d3024181412121316222e3b4754616d7a8793a0ada89c8f8276695c5043362a1d100400000000000000000000000000000000000000000000000000000a16212d3945515d6874808c98a3a79b8f83776b75818d99a5a89c9084786c6155493d31251a0e02000000000000000000000000000000000000000000000000000000000000000000020e1a26313d4955616c7884909ca7a69a8e83776b5f5347505c6874808b97a3ab9f93887c7064584c4135291d11050000000000000000000000000000000000000000000008121c262f38414a525960676d73787d82868a8d9194989b9ea4adaeaaa7a4a19e9a97938f8b87827c767069625a524940372d23190f040000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f13000000030e1a25303b46525d68737e8a95a0abb7b8ada2968b8075695e53483d31261b100500000000000916222f3b4854606a727a81888f979ea39b948d857e7885929faca89b8e8275685b4e4235281b0f02000000000000000000000000000000000000000000000000000000000000000000030d18232d38424d57626c77828c97a19b90848894a1ada09386796d6053463a2d201307000000000000000000000002111e2b3744515d6a7784909daaa5988c7f72656565656565656565656565656565656565656565656565656561594f44382c20140800000000101c2834404b565e64656565656565656565656565656565656565656565656565656565656c76818b96a1a0968b80756b60554b4034281c10040013202c3946535f6c7986868686868685786b5e5865727e8686868686867f7265594c3f3226190c00111e2a36434f5b67737f8b93939393938d8174685c5044382c20140800000000020e1b27333f4b57636f7b8793939393939084786c6054483c3023170a000814212d3a46525d67727c87919393939390867b70655b50453a30251a111c27323c47525d67727d88929393939390867b71665c5045382c1f1306000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e01000000000000000000000000000006111b26303a444e576069717980878d93989ca0a3a4a2a09f9f9f9fa1a3a4a19e9b96918c857e776f665d544b41372c22170c01000000000000000000000007101a222b333b424950565b6065696c6f71737475767675757472706d6a67625e59534d463f372f271f160d03000000000000000000000000000006121f2c3845525e6b78848d8e8f90919084776b5f52463a2f251d1816161719202c3844515d6a7683909ca9ada194877a6d6154473b2e2114080000000e1b2734414d5a6774818d9aa7aea194887b6e6154483b2e22150805050713202d3946535f6c798693a0acaa9d9084776a5d5144372a1e1104000000000000000000000000000000000000000000000000000005111d2834404c58636f7b87939faaa094887b6f7985919da9a3978b8074685c5044382d21150900000000000000000000000000000000000000000000000000000000000000000000000915212d3844505c68737f8b97a3ab9f93877b6f63584c55606c7884909ca8a69b8f83776b5f53483c3024180c01000000000000000000000000000000000000000000050f1a242e38414b535c646b72797f84898e9296999da1a4a7aaafaba39e9b9895918e8b87837f7b76706b655e57504840372e251b1107000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000914202b36414d58636e7985909ba6b2bdbeb3a89c91867b7064594e43382c21160b000000000007131f2c38434e5861686f767d858c939ba29e9790888185929faca89b8e8275685b4e4235281b0f020000000000000000000000000000000000000000000000000000000000000000000006111b26303b46505b65707a858f9aa1968e9099a4ada09386796d6053463a2d201307000000000000000000000000101d2a3643505d697683909ca9a6998d807371717171717171717171717171717171717171717171717171716b6055483c3023160a00000000121f2b3844505c68707171717171717171717171717171717171717171717171717171717171717a848f99a59c92877c72675c5145382c1f130600131f2c3946525f6b7679797979797979756a5e58647079797979797979797165584b3f3225190c00121f2c3945525f6b7783868686868686867c7064584c4034281c100400000000000a16222e3a47535f6b7783868686868686867c7064574b3e3125180b000916232f3c4955626e7984868686868686867f74695f54493e34291e130a15202b35404b56606b76818686868686868683786d6054473b2e211408000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e0100000000000000000000000000020d18222d38424c566069727b838b92999ea4a5a09b989593929292939496999ca0a5a29d97908981786f665d53493e34291e130700000000000000000000061019232c343d454d545b61676c7175797c7e80818283838282817e7c7a76736e69645e585149413931281f150c020000000000000000000000000004111d2a3743505c6975828e9a9c9c9d93877b6f63574c41372e2825232324262a323d4854606c7985929eabac9f9386796d6053473a2d2014070000000e1b2834414e5b6774818e9ba8aea194877a6d6154473b2e21140802020613202c3946535f6c7986929facab9e9184776b5e5144382b1e11050000000000000000000000000000000000000000000000000000000c18242f3b47535f6b76828e9aa6a4988c80737d8995a1aa9e92877b6f63574b3f34281c1004000000000000000000000000000000000000000000000000000000000000000000000004101c28343f4b57636e7a86929eaaa3988c8074685c505965717d8995a1aca2968a7e72665b4f43372b1f1408000000000000000000000000000000000000000000000b16212c36404a535d656e757d848a90959a9ea2a6a8a5a19fa0a5a499928e8b8885827e7b77736f6a655f5a534d463e362e251c130900000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000040f1b26313c47535e6974808b96a1acb8c3c4b9aea3978c81766a5f54493e32271c110600000000030f1b27323d464f565d656c737a828990979ea19a938b8b94a0ada89b8e8275685b4e4235281b0f0200000000000000000000000000000000000000000000000000000000000000000000000a141f29343e49535e69737e88939d9f9b9ca2abada09386796d6053463a2d201307000000000000000000000000101c2936424f5c6975828f9ca8a79a8d817e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7d7064574a3e3124170b0000000013202c3946535f6c797e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e8996a2a3998e83786d6054473a2d21140700111e2a37434f5a646b6c6c6c6c6c6c6c6b6359545f686c6c6c6c6c6c6c6c685f54483c3024170b00121f2c3845525e6b767979797979797979776c6054483c3024180c00000000000006121e2a36424e5a66727979797979797979797064574b3e3125180b000916232f3c4955626e787979797979797979776d62584d42372d22170d040e19242f39444f5a646f787979797979797979776d6054473a2e211408000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e010000000000000000000000000007131e29343f49545e68727b848d959da4a7a09a948f8c89878585858687898c90959aa0a7a29b938b82786f655a50453a2f24190d020000000000000000040e18222b353e464f575f666c72787d8185888b8d8e8f90908f8e8d8b8986837f7a756f69625b534b433a31271e140a00000000000000000000000000010f1b2834414d5a66737f8b97a4a9a3978b7f73685d52494039343130303032363c444e5965707c8995a1adaa9d9184786b5e5245392c1f13060000000e1b2834414e5b6774818e9aa7aea194887b6e6155483b2f2216100f0f1014212d3a4753606d798693a0acaa9e9184776b5e5144382b1e110500000000000000000000000000000000000000000000000000000007131f2b36424e5a66717d8995a1a89c908477818d99a5a5998e82766a5e52473b2f23170b000000000000000000000000000000000000000000000000000000000000000000000000000b17232f3b46525e6a76818d99a5a89c9085786d61555e6a76828d99a5a99d9185796d62564a3e32261b0f0300000000000000000000000000000000000000000006121d28333d48525c656f7780878e959ba1a6a9a4a09c989592949ca09488827f7c7975726e6b67635e59544e48423b342c241c130a0100000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f1300000a15212c37424d59646f7a86919ca7b2bec6c6bfb4a99d92877c70655a4f44382d22170c00000000000a15202b343d444c535a616870777e868d949ba29d97969ca6b1a89b8e8275685b4e4235281b0f020000000000000000000000000000000000000000000000000000000000000000000000020d18222d37424c57616c76818c96a1a7a8acb4ada09386796d6053463a2d2013070000000000000000000000000f1b2835424e5b6875818e9ba8a99d928b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8a7d7164574a3e3124170b0000000013202c3946535f6c79868b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8f99a4aaa094877a6d6154473a2e211407000e1a26323e48525a5f5f5f5f5f5f5f5f5e59514d565d5f5f5f5f5f5f5f5f5d564d43382c20140800111d2a36424e5a646b6c6c6c6c6c6c6c6c6b655b5044382c201407000000000000020e1a26323e4a5660696c6c6c6c6c6c6c6c6c685e53483c2f23160a000814212d3a46525d666c6c6c6c6c6c6c6c6c6c655b51463b31261b10060007121d28333d48535e676c6c6c6c6c6c6c6c6c6c655b5044382c1f1306000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e01000000000000000000000000020d19242f3a45505b66707a848d969fa7a69d968f89847f7c7a797878797b7d8084898f969da5a59d948a81766c61574c41352a1e130700000000000000000b15202a343d475058616970777e84898d919597999b9c9c9c9c9b9a9895938f8b86817a746d655d554c433930261c1107000000000000000000000000000c1925323e4a57636f7b87939faba79c9085796f645b524b45413e3d3c3d3f42464d56606b76818d99a5b1a79a8e8275695c5043372a1d11040000000e1a2734414d5a6773808d99a6afa296897c7063574a3e32261f1c1b1b1c1f24303c4955626e7b8794a1ada99d9083766a5d5044372a1d1104000000000000000000000000000000000000000000000000000000020e1a26323d4955616d7884909ca8a094877b85919da9a195897d7165594e42362a1e12070000000000000000000000000000000000000000000000000000000000000000000000000006121e2a36414d5965717c8894a0aca195897d716559636e7a86929eaaa4988c8175695d5145392e22160a000000000000000000000000000000000000000000000c17232e39444f5a646e7781899299a0a7a8a29d9894908c89868a96a0938679736f6c6966625e5b57524e48433d373029221a120a010000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130005101b27323d48545f6a75818c97a2adb9b9b9b9b9b9afa4988d82766b60554a3f33281d120600000000040f19222b333a414850575e656c747b828991989fa3a3a7aeb5a89b8e8275685b4e4235281b0f0200000000000000000000000000000000000000000000000000000000000000000000000006101b25303b45505a656f7a858f9aa4afb8b9ada09386796d6053463a2d2013070000000000000000000000000e1b2734414d5a6774818d9aa7aea49c98989898989898989898989898989898989898989898989898978a7d7164574a3e3124170b0000000013202c3946535f6c7986939898989898989898989898989898989898989898989898989898989898989aa1aaaea194877a6d6154473a2e211407000a16212c3740484f5253535353535353524e48444b515353535353535353514c443b31261b1004000e1a26323d48525a5f5f5f5f5f5f5f5f5f5f5b53493f33281c0f03000000000000000a16222e39444e575d5f5f5f5f5f5f5f5f5f5c564d42372b1f13070005111d2935404b545c5f5f5f5f5f5f5f5f5f5f5b534a3f342a1f14090000010b16212c36414c555c5f5f5f5f5f5f5f5f5f5f5b534a3f34281c1004000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e0100000000000000000000000007121e2a35414c57626d77828c969fa8a69d948b847d7873706d6c6b6b6c6e7074787d848b939ba4a69c93887e73685d52463b2f23180c0000000000000007121d27313c464f59626a737b82898f95999da1a4a2a09e9e9e9e9fa1a4a29f9b97928c867e776f675e554b42382e23190e030000000000000000000000000916222e3b47535f6b77838f9aa6aca1968b81766d645c56514d4a49494a4b4e52585f68727c87929ea9aea3978b7e7266594d4134281b0f020000000d1926333f4c5965727e8b98a4b0a4988b7e72665a4e4238302b292828292b2f36414c5864717d8a96a3afa79b8e8275685c4f4236291c1003000000000000000000000000000000000000000000000000000000000915212d3944505c6874808b97a3a3978b7f8995a1a89c9084786c6155493d31251a0e0200000000000000000000000000000000000000000000000000000000000000000000000000020d1925313d4854606c78848f9ba7a59a8e82766a5e67737f8b97a3ab9f93887c7064584c4035291d110500000000000000000000000000000000000000000005111d28343f4b56616b76808a939ba3aba49d97918c8884807c7b8895a09386796d63605d5956524e4b46423d37322c251f18100800000000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f13000a16222d38434e5a65707b87929da8acacacacacacacacaa9e93887d71665b5045392e23170c000000000007101921282f373e454c535b626970787f868d959ca3aaacaca89b8e8275685b4e4235281b0f020000000000000000000000000000000000000000000000000000000000000000000000000009141e29333e49535e68737d88929da8acacaca09386796d6053463a2d2013070000000000000000000000000d1a2733404d596673808c99a6acaca7a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a4978a7d7164574a3e3124170b0000000013202c3946535f6c798693a0a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a6abacaca194877a6d6154473a2e2114070005101a252e373e43464646464646464645423d3a4044464646464646464644403a32291f150a00000a15212c3640484f525353535353535353524f4941372d22170b000000000000000005111d28323c454c51535353535353535353504b443b30261a0f0300010d19242f39424a50535353535353535353524f4941382d23180d03000000050f1a25303a434b50535353535353535353524f4941382d23170c00000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e010000000000000000000000000c17232f3b46525d68737e89949ea8a79d948a8179726c6763615f5f5f606164686c72798189929ca6a49a8f85796e63574c4034281c10040000000000020e19232e39434d57616b747c858d949aa0a5a29d999593919191919395979b9fa5a29d979089817970675d544a3f352a20150a00000000000000000000000006121e2b37434f5b66727e89949faaa79d92887f766e67615d5957565656585a5e6369717a848e99a4afa99e92867a6e62564a3e3125190c000000000b1824313d4a56636f7c8895a1ada79b8e82766a5f544a413c3836353536373b4048525d6975818d99a5b0a4988b7f73665a4d4034271b0e010000000000000000000000000000000000000000000000000000000005101c2834404b57636f7b87929ea79b8f878d99a5a3978b8073685c5044382c2115090000000000000000000000000000000000000000000000000000000000000000000000000000000914202c38444f5b67737e8b96a2aa9e92867a6e626b77848f9ba7a69a8f83776b5f53483c3024180c010000000000000000000000000000000000000000000915212d3945505c67727d88929ba5aba29a928c86817c7774707b8895a09386796d6054504d4a46423e3a36312c26211a1614110e0a050000000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f13000f1b27333e4954606b76818d98a0a0a0a0a0a0a0a0a0a0a0a0998e83776c61564b3f34281c10040000000000070f161e252c333b424950575f666d747c838a9199a0a0a0a09b8e8275685b4e4235281b0f0200000000000000000000000000000000000000000000000000000000000000000000000000020d17222c37414c56616c76818b96a0a0a0a0a09386796d6053463a2d2013070000000000000000000000000c1926333f4c5965727f8c98a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0978a7d7164574a3e3124170b0000000013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a094877a6d6154473a2e211407000009131c252c323739393939393939393936322f3438393939393939393938342f2820170d030000040f1a242e363d4346464646464646464646433e372f261b11060000000000000000000b16212a333b414546464646464646464644403a32291f140900000007121d2730383f4446464646464646464646433e382f261c1106000000000008131e2831393f4446464646464646464646433e382f261c110600000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e01000000000000000000000004101c2834404b57636e7a85909ba5aba0968b82786f68615b57545252525355585c61676f77808a949ea29f968b8074685c5145382c1f1306000000000008141f2a35404b555f69737d868f979ea5a49d97918c89868584848586888b8f9499a0a7a29b938b82796f665c51473c31261b10040000000000000000000000020e1a26323e4a56616d78838e99a3ada49a91888079726d69666463636364676a6e747b838c96a0aaada2978c81756a5e52463a2e221509000000000915222e3b4754606c7885919da8ab9f93877b70665c534c48444242424244474b525a646f7a85919da9aca094887c6f63574a3e3225190c0000000000000000000000000000000000000000000000000000000000000c17232f3b47525e6a76828e99a5a19893969fa99e92867a6f63574b3f34281c100400000000000000000000000000000000000000000000000000000000000000000000000000000004101b27333f4b56626e7a86929da9a2968a7e7266707c8894a0aca2968a7e72665a4f43372b1f1308000000000000000000000000000000000000000000000d1925313d4a55616d78848f99a4aca2999088817a75706b676f7b8895a09386796d605346413d3a363230302e2c2a272522201e1a16100902000000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f1300111e2a37434f5b66717c8793939393939393939393939393939393897d72675c5045382c1f1306000000000000050c131a222930373e464d545b636a717880878e93939393938e8275685b4e4235281b0f02000000000000000000000000000000000000000000000000000000000000000000000000000005101b25303a454f5a646f79848f93939393939386796d6053463a2d2013070000000000000000000000000c1825323e4b5865717e8b939393939393939393939393939393939393939393939393939393939393938a7d7164574a3e3124170b0000000013202c3946535f6c798693939393939393939393939393939393939393939393939393939393939393939393939393877a6d6154473a2e2114070000010a131a21262a2c2c2c2c2c2c2c2c2c2a2624282b2c2c2c2c2c2c2c2c2b28241e160e050000000008121c242c32363939393939393939393937332d251d140a00000000000000000000050f18212930353839393939393939393938342f2820170d02000000010b151e272e33373939393939393939393937332d261d140a000000000000020c161f272e34383939393939393939393937332d261d140a0000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e0100000000000000000000000814202c3844505c68747f8b96a1aca59a8f84796f665d564f4b4846454546484b50565d656e78828d9896928f8b85796d6054473b2e21140800000000020e1925303b47515c67717b858f98a1a9a29a928b85817c7a78777778797b7e83888e959da6a59d948b81786d63584e43372c21150a0000000000000000000000000a16222e3945505b66717c87919ba4aca39a928a847e797572706f6f707173767a80868d959ea8aea49b90867b7064594d41362a1e12050000000006131f2b3844505c6874808c97a3aea3988d82776e655e5854514f4e4e4f5153575d646c76808b96a2ada69b8f84786c5f53473b2f22160900000000000000000000000000000000000000000000000000000000060b0e131e2a36424e5965717d8994a0aaa3a0a2a8a5998e82766a5e52463b2f23170f0b060000000000000000000000000000000000000000000000000000000000000000000000000000000b17222e3a46525d6975818d99a4a79b8f83766a74808c98a4a99d9185796d61564a3e32261b0f0300000000000000000000000000000000000000000003101c2935414d5a66727e8a95a0aba59b90877e766f69645f626f7b8895a09386796d6053463a3130363b3d3d3b383634312f2d2a27221b140b020000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946525f6b778286868686868686868686868686868686868684786d6054473b2e21140800000000000000010910171e252d343b424a51585f676e757c848686868686868275685b4e4235281b0f0200000000000000000000000000000000000000000000000000000000000000000000000000000009131e28333e48535d68727d8686868686868686796d6053463a2d2013070000000000000000000000000b1824313e4a5764717d8686868686868686868686868686868686868686868686868686868686868686867d7164574a3e3124170b0000000013202c3946535f6c798686868686868686868686868686868686868686868686868686868686868686868686868686867a6d6154473a2e211407000000010910161a1e1f202020202020201f1e1a181c1f20202020202020201f1c18130c050000000000000a121a21262a2c2c2c2c2c2c2c2c2c2c2a27221b130b020000000000000000000000060f171f24292c2c2c2c2c2c2c2c2c2c2b28231d160e050000000000030c151c23282b2c2c2c2c2c2c2c2c2c2c2b27221b140b0200000000000000040d151d23282b2c2c2c2c2c2c2c2c2c2c2b27221b140b020000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e0100000000000000000000000c1824303c4955616d7884909ca7ab9f94887d72685e544c443f3b3938393a3c3f444b535c66707b878d8a86837f7c776d6054473a2e2114080000000008131f2b36414d58636e78838d97a1aaa3999088817a75706d6b6a6a6b6d6f72777d848b949da6a69d938a7f756a5f54493d32261b0f03000000000000000000000005111d28343f4a55606a757f89929ba3aba49c958f8985827f7d7c7c7d7e8082868b91989fa8aca49c92897e74695e53483c3125190d0100000000030f1c2834404c58646f7b86919ca6a99e948980776f6964605d5c5b5b5c5d6063686e767e88929da8aa9f958a7e73675b4f43372b1f13060000000000000000000000000000000000000000000000000000030a11171b1d1e25313d4955606c7884909ca0a0a0a0a0a095897d7165594e42362a1e1e1b17110b030000000000000000000000000000000000000000000000000000000000000000000000000006121e2935414d5964707c8894a0ab9f93877b6f7884909ca8a4988c8174695d5145392d22160a0000000000000000000000000000000000000000000006121f2b3844515d6a76828e9aa6aa9f94897e756c645e5855626f7b8895a09386796d6053463a323a42474a4a474543403e3b3936322d251d140a0000000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f1300131f2c3946525f6b767979797979797979797979797979797979797979776d6054473a2e211408000000000000000000050d141b222931383f464e555c636a72797979797979797973675a4e4135281b0e02000000000000000000000000000000000000000000000000000000000000000000000000000000020c17212c36414c56616b767979797979797979766b5f5346392d2013060000000000000000000000000a1723303d4a56636f78797979797979797979797979797979797979797979797979797979797979797979796f63574a3d3124170a00000000131f2c3946525f6b76797979797979797979797979797979797979797979797979797979797979797979797979797979776c6053473a2d2114070000000000050a0e11131313131313131313110e0c1012131313131313131312100c070100000000000000000810161a1e1f2020202020202020201e1b1610090100000000000000000000000000060d13191d1f2020202020202020201f1c18120c0400000000000000030a11171b1e202020202020202020201e1b16110a02000000000000000000030b12171c1e202020202020202020201e1b16110a02000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e0100000000000000000000030f1b2834404c5965717d8995a1ada69a8e82776c61564c423a332f2c2c2c2d2f3339414a545f6a7581817d7a76736f6c655b5044382c1f1306000000000c1824303b47535e6974808a959fa9a59b91877e766f6964615f5e5d5e6063666b7279828b949ea9a59b91867b70655a4e43372c2014080000000000000000000000000c17222e39444e59636d7680899199a1a7a7a09a95918e8c8a8989898a8c8f92979ca2a9a9a29a928a81776d62584d42372b2014090000000000000c1824303c47535e6a75808a959ea8a59b9289817a74706c6a696868686a6c6f74798088909aa4aba2988e83786d61564a3f33271b0f0300000000000000000000000000000000000000000000000000030c151c22272a2b2b2c3844505c67737f8b939393939393939084786c6055493d312b2b2a27231c150d04000000000000000000000000000000000000000000000000000000000000000000000000010d1925303c4854606b77838f9ba7a3978b7f737c8894a0ab9f93877b7064584c4035291d1105000000000000000000000000000000000000000000000814212d3a4753606c7985929eaaa69a8e82776c635a534c55626f7b8895a09386796d6053463a3a444c53565654514f4d4a4846433e372f261c110600000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f1300111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c655b5044382c1f130600000000000000000000020910181f262d353c434a515960676c6c6c6c6c6c6c6c6961564b3f3226190d000000000000000000000000000000000000000000000000000000000000000000000000000000000005101a252f3a444f59646b6c6c6c6c6c6c6c6c6b645a4f43372b1e12050000000000000000000000000915222e3a47525d676c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c675e53473b2e22160900000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b655b5044382b1f1206000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0e1113131313131313131313110f0a050000000000000000000000000000000002080d101213131313131313131312100c070100000000000000000000060b0f1213131313131313131313110f0b0500000000000000000000000000060b0f1213131313131313131313110f0b050000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e010000000000000000000006121e2b3744505c6875818d99a5aea295897d72665a4f443a302822201f1f2023282f38424d5965707775716e6a6763605b534a3f34281c100400000005111d2935404c58646f7a86919ca7aa9f94897f756c645d58545251515253565b60676f78828d97a2ada3988d82766b5f54483c3024180c00000000000000000000000006111c27323c47515b656e7780878f969ca2a7a6a19d9a989796969697999b9ea3a8a8a39e97908980776e655b51463b31251a0f0300000000000007131f2b36424d58636e78838c969ea7a49b938c86807c79777575757576787b80858b929aa2aaa19990867c71665c50453a2e22160b00000000000000000000000000000000000000000000000000010c151e272e3337383838383f4b57636e7a8686868686868686867f73675c50443838383837332e271f160c020000000000000000000000000000000000000000000000000000000000000000000000000814202c37434f5b67727e8a96a2a79b8f8377808c98a4a69a8e83776b5f53473c3024180c00000000000000000000000000000000000000000000000916222f3c4855626e7b8894a1ada2968a7d71665b51484855626f7b8895a09386796d6053463a414c565e6363605e5c595754524f4941382e23180c00000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f13000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5b534a3f34281c1004000000000000000000000000060d141c232a313940474e555c5f5f5f5f5f5f5f5f5e584f453a2e22160a00000000000000000000000000000000000000000000000000000000000000000000000000000000000008131e28333d48525a5f5f5f5f5f5f5f5f5f5f5a52493e33271b0f0200000000000000000000000006121e2a36414c555c5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5c554c41362b1f1206000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5b53493f33281c0f03000000000000010508090909090909070300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e01000000000000000000000815212e3a47535f6c7885919da9aa9e9285796d6155493e33281e1d1d1d1d1d1d1d26313d48545e676b6865615e5a5753504941382d23170c000000000915212d3945515d6974808c97a2ada4998d82776d635a534c4845444445474a4f555d66707b86919ca8a99e93887c7064594d4135291c10040000000000000000000000000b16202b353f49535c656d757d848b91979ba0a3a6a7a5a3a3a2a3a4a5a8a6a4a09c98928c867e776e655c53493f342a1f140900000000000000030e1a25313c47525c67717a848c959da4a59e97918c888583828282828385888b90969ca4a69f988f877d746a60554a3f34281d12060000000000000000000000000000000000000000000000000008131e2731383f43454545454546525e6a75797979797979797979786e63574b4545454545433f3931281e1409000000000000000000000000000000000000000000000000000000000000000000000000030f1b27333e4a56626e7985919da99f93877a84909ca8a1968a7e72665a4e43372b1f130800000000000000000000000000000000000000000000000a1723303d495663707c8996a3aca093877a6e6155493f4855626f7b8895a09386796d6053463a45515d686f6f6d6a686663615f5b534a3f34281c1004000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f13000a16212c3740484f525353535353535353535353535353535353535353524f4941382d23170c0000000000000000000000000000030a111820272e353d444b505353535353535353514d463d33281d1206000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c16212c3640484e525353535353535353524f4940372c21160a00000000000000000000000000020e19252f3a434b505353535353535353535353535353535353535353535353535353535353535353535353504b433a30251a0e02000000000a16212c3740484f52535353535353535353535353535353535353535353535353535353535353535353535353535353524f4941372d22170b000000000001070d1114161616161615130f0a04000000000000000000000000000000000000000000000000000000000000000000000000000000000000010406080a0b0c0c0c0c0c0b0a090705030000000000000000000000000000000000000000000000000000000000000407090a0a0a0a0a0a0a0a0a090602000000000000000000000000000000000000000000000000000000000000000000000000030709090909090908050100000000000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e01000000000000000000000a1724303d4956626f7b8894a0ada79b8e8275695d5145392d2a2a2a2a2a2a2a2a2a2a2c37424c555b5e5c5955524e4b47443f382f261c1106000000000c1925313d4955616d7985919da8aa9f93877c71665b5148413c393737383a3e444b555f6974808b97a3aea4988d8175695d5145392c201408000000000000000000000000040f19232d37414a535b646b737980868b9093979a9c9d9e9f9f9f9e9d9c9a9794908c87817b746d655c534a41372d23180d03000000000000000009141f2a35404a555f68717a838b92999fa5a29d989592908f8e8e8f909294989ca1a6a19b958d867d756b62584e43392e23170c01000000000000000000000000000000000000000000000000020e19252f39424a4f5151515151514e58636a6c6c6c6c6c6c6c6c6c6c675d525151515151514f4a433a30251a0f030000000000000000000000000000000000000000000000000000000000000000000000000a16222e3a45515d6975818c98a4a3978a7e8894a0a89d9185796d61564a3e32261a0f0300000000000000000000000000000000000000000000000a1724303d4a5763707d8a97a4ab9e9285786b5f52463c4855626f7b8895a09386796d6053463c4855616e7a7c79777572706e6b655c5145392c201307000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130005101a252e373e4346464646464646464646464646464646464646464646433e382f261c110600000000000000000000000000000000070e151c242b32394044464646464646464645413b342b21170c0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000050f1a242e363d4345464646464646464646433e372e251b1005000000000000000000000000000008131e2831393f44464646464646464646464646464646464646464646464646464646464646464646464644403931281e1308000000000005101a252e373e434646464646464646464646464646464646464646464646464646464646464646464646464646464646433e372f261b110600000000030b12191d212323232323221f1b150f07000000000000000000000000000000000000000000000000000000000000000000000000000003070b0e1113151617181919191818171614120f0d0a0602000000000000000000000000000000000000000000000000050b10141617171717171717171715120e08020000000000000000000000000000000000000000000000000000000000000000040a0f1315161616161614110d07010000000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e01000000000000000000000c1926323f4b5865717e8a97a3b0a5988c7f72665a4d4136363636363636363636363636363a434a4f51504c4945423e3b3735312c251d140a00000003101c2835414d5965727e8a96a2ada69a8e82766b5f54493f36302c2b2b2c2e3239434d58636f7a86929eaaa99d9185796d6155483c3024170b0000000000000000000000000007111b252f384149525961686e757a7f84878a8d8f919292929292918f8d8b8884807b767069625b534a41382f251b1106000000000000000000030e19242e39434d565f68717981888e94999ea1a4a19e9d9c9b9b9c9d9ea1a4a29f9a96908a837c746b625950463c32271c11060000000000000000000000000000000000000000000000000006131f2a36414b545b5e5e5e5e5e5e5953595e5f5f5f5f5f5f5f5f5f5f5c55595e5e5e5e5e5e5c554c42372b1f130700000000000000000000000000000000000000000000000000000000000000000000000006111d2935404c5864707b87939fa79a8e848c98a4a4988c8074695d5145392d21160a0000000000000000000000000000000000000000000000000a1724303d4a5763707d8a97a4ab9e9285786b5e51453c4855626f7b8895a09386796d605346414d5965717d888684817f7c7a776d6154483b2e221508000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f13000009131c252c32373939393939393939393939393939393939393939393937332d261d140a000000000000000000000000000000000000030b121920272e343839393939393939393835302a22190f0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008121b242c32363939393939393939393937322c251c1309000000000000000000000000000000010c161f272e3438393939393939393939393939393939393939393939393939393939393939393939393938342e271f160c0200000000000009131c252c3237393939393939393939393939393939393939393939393939393939393939393939393939393939393937332d251d140a00000000030c151d24292d2f303030302f2b27201910070000000000000000000000000000000000000000000000000000000000000000000001060b0f14171a1d1f2123242526262625252422201e1c1916120e0a050000000000000000000000000000000000000000000810171c2023242424242424242423221e19130c04000000000000000000000000000000000000000000000000000000000000070f151b1f222323232323211d19120b0300000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e01000000000000000000000e1b2734414d5a6773808c99a6afa396897d7063574a43434343434343434343434343434343434343444343434343434343413d372f261c1207000006131f2b3844505d6975828e9aa6aea2968a7d72665a4e43382d25201e1e1f2227313b47525e6a76828e9aa6aea295897d7164584c3f33271a0e010000000000000000000000000009131d262f3740484f565d63696e73777b7e81828485868686858482817e7b78746f6a655e58504941382f261d1309000000000000000000000007121d27313b444d565f676f767d83888d9295989b9d9e9f9f9f9f9e9d9b9996938e8a857f78716a625950473e342a20150b00000000000000000000000000000000000000000000000000000916222f3b47535d666b6b6b6b6b6a645e575253535353535353535353565d646a6b6b6b6b6b675e53483c2f23160a000000000000000000000000000000000000000000000000000000000000000000000000010c1824303c48535f6b77838e9aa69f9691949da89f93877b7064584c4034291d11050000000000000000000000000000000000000000000000000a1724303d4a5763707d8a96a3ac9f9285796c5f53473c4855626f7b8895a09386796d60534647525d6975818d93908e8b89877a6e6255483b2f221508000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b27221b140b020000000000000000000000000000000000000000070f161d23282b2c2c2c2c2c2c2c2c2c29251f181007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121a21262a2c2c2c2c2c2c2c2c2c2c2a27211b130a0100000000000000000000000000000000040d151d23282b2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b28231d150d0400000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a27221b130b02000000000a151e272f353a3c3c3c3c3c3b37322b23190f050000000000000000000000000000000000000000000000000000000000000001070c12171b2023272a2c2e3031323232323231302f2d2b2825221e1a16110b0500000000000000000000000000000000000008121a22282c2f3030303030303030302e2a251e160d040000000000000000000000000000000000000000000000000000000007101920272b2f303030302f2d29241d150c03000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e0100000000000000000000101c2936424f5c6875828e9ba8aea194887b6e625550505050505050505050505050505050505050505050505050505050504e4841382e24180d01000915222e3b4754606c7985919eaaab9f92867a6d6155493d32261c13111112161f2a36414d5966727e8b97a3b0a5998d8174675b4f4236291d100400000000000000000000000000010b141d252e363d454c52585e63676b6f717476777879797978777674726f6c68645f59534d463f372f261d140b010000000000000000000000000b151f29323b444d555d646b72777d8185898c8e90919292929291908e8c8a86837e79736d675f5850473e352c22180e0400000000000000000000000000000000000000000000000000000b1724313d4a57636f7878787878766f69625b554e48464646464d535a61686f7678787878787064574b3e3225180b0000000000000000000000000000000000000000000000000000000000000000000000000008141f2b37434e5a66727e8a95a1a8a19ea0a6a69a8e83776b5f53473b3024180c000000000000000000000000000000000000000000000000000916232f3c4955626f7b8895a1ada094887b6f63574c434855626f7b8895a09386796d6053464f59646f7a86919d9d9a988f83776b5e5246392d211407000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f13000000010910161a1e1f2020202020202020202020202020202020202020201e1b16110a0200000000000000000000000000000000000000000000040b12171c1f20202020202020201f1d19140d0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f151a1e1f20202020202020201f1e1b16100901000000000000000000000000000000000000030b12171c1e20202020202020202020202020202020202020202020202020202020202020202020201f1c17120b04000000000000000000010910161a1e1f202020202020202020202020202020202020202020202020202020202020202020202020202020201e1b161009010000000006111c2730394046494949494947433d352b21160b000000000000000000000000000000000000000000000000000000000000050c12181e23272c303336383b3c3e3e3f3f3f3f3e3d3b3a3735322e2a26211c16100a0300000000000000000000000000000006101a242c33383c3d3d3d3d3d3d3d3d3d3b3630281f150b010000000000000000000000000000000000000000000000000000050f19232b32373b3c3c3c3c3c3a352f271e150a000000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e0100000000000000000000111d2a3744505d6a7683909da9ada093867a6d605d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5a534a4035291e1205000b1824313d4a56636f7c8895a1ada89c8f83766a5e5145392d21150a0404060e1925313d4a56626f7b8894a0ada99c9083776a5e5145382c1f12060000000000000000000000000000020b131c242c333a41474d52575b5f626567696b6b6c6c6c6b6a696765635f5c58534e48423b342d251d140b0200000000000000000000000000030d172029323b434b535a60666c7175797c7f82838485868685858482807d7a76726d68625c554e463e352c231a10060000000000000000000000000000000000000000000000000000000b1824313e4b5764717e85858585817a736d666059534c464a50575e656c737981858585857e7265584c3f3225190c000000000000000000000000000000000000000000000000000000000000000000000000060d121a26323e4a56616d7985919ca2a2a2a2a2a1958a7e72665a4e43372b1f140f090100000000000000000000000000000000000000000000000815212e3a4754606d7986929faba3978b7f74685e554e4955626f7b8895a09386796d60535158616b75808b97a2a9a2978b7f73675b4e42362a1e1105000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000050a0e1113131313131313131313131313131313131313131313110f0b050000000000000000000000000000000000000000000000000001070c0f12131313131313131312100d0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0e1113131313131313131313110e0a0500000000000000000000000000000000000000000000060b0f121313131313131313131313131313131313131313131313131313131313131313131313120f0c0700000000000000000000000000050a0e111313131313131313131313131313131313131313131313131313131313131313131313131313131313110f0a050000000000000b17232e38424b525556565656544e473d33281c1105000000000000000000000000000000000000000000000000000000010810171d23292e33383c3f424547494a4b4c4c4c4b4b4a484644413e3a36322d28221c150e0600000000000000000000000000010c18222c363e44484a4a4a4a4a4a4a4a4a47413a31271d120700000000000000000000000000000000000000000000000000000b16212b353d4347494949494946403930271c11060000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e0100000000000000000000121e2b3845515e6b7784919eaaac9f9286796c69696969696969696969696969696969696969696969696969696969696969655c51463a2e211508000d1a26333f4c5865727e8b97a4b0a6998d8074675b4e4235291d11050000000915212e3a46535f6c7885929eabab9f9286796d6053473a2e211408000000000000000000000000000000010a121a21282f363c41464b4f5356585b5d5e5f5f5f5f5f5e5c5b595653504c47423d37312a231b130b02000000000000000000000000000000050e172029313941484f555b6065696d70737576787879797978777573716e6a66625c57514a433c342c231a1108000000000000000000000000000000000000000000000000000000000b1724313e4a57636f79838c92928c857e78716b645e5751545b626970777d848b92928d837a7064584b3e3225180c00000000000000000000000000000000000000000000000000000000000000000000000710171e23272d3945515c6874808c959595959595959185796d61564a3e322825201a130b020000000000000000000000000000000000000000000006131f2c3845515e6a76838f9ba6a79c90857a7067605a5555626f7b8895a09386796d60575c626a737d87929da8a89d91867a6e62564a3e32261a0e02000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f13000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1b28333f4a545d626363636360594f44392d2115090000000000000000000000000000000000000000000000000000030b131a21282f343a3f44484c4f52545657585959595857565553504e4a47423e39332d262018110900000000000000000000000006121e29343e484f55575757575757575756524c43392f23180c0000000000000000000000000000000000000000000000000005111c28333d474e545656565655524b42382e23170b0000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e0100000000000000000000121f2c3945525f6b7885929fabac9f92857876767676767676767676767676767676767676767676767676767676767676766e6256493d3024170a000f1b2835414e5a6774818d9aa6b0a4978b7e7165584c3f33261a0d0100000005121e2b3744515d6a7683909ca9aea194887b6f6255493c2f2316090000000000000000000000000000000000080f171e242a30353a3f4346494c4e5051525253525251504e4c4a47433f3b37312c261f181109010000000000000000000000000000000000050e171f272f363d444a4f54595d616466686a6b6c6c6c6c6b6a686764615e5a56514c463f39322a221a110800000000000000000000000000000000000000000000000000000000000916222f3b47535e677079838c9597908a837c766f69625b5f666d747a81888f96978d847a71685e53483c2f23170a0000000000000000000000000000000000000000000000000000000000000000000006101922292f333536404c58636f7b8788888888888888888074685d5145393634312c251d140b0000000000000000000000000000000000000000000004101d2935424e5a66727e8a96a1aca1978c8279716b65615e626f7b8895a09386796d6063676d747c858f99a3ada2978c8175695e52463a2e22160a00000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130000000000000000000000000000000000000000000000000000000000000000000000000000050a0d0f0f0f0f0f0f0d0a05000000000000000000000000000000000000000000000000000001070b0f1011111111110f0c070200000000000000000000000000000000000000000000000000000000000000000000000000020406070808080808070605030100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001030506070808080807070504020000000000000000000000000000000000000000000000000000000000000000000000000000000000020406070808080807070503010000000000000000000000000000000000000000000000000000121e2b3744505c666e6f6f6f6f6b6155493d3124180b00000000000000000000000000000000000000000000000000030c151d242c333a40454b5054585b5e60626465656565656463615f5d5a57534e49443e38312a221b120a01000000000000000000000a16222e3a45505a616363636363636363635e554b4034281c10030000000000000000000000000000000000000000000000000915212d39444f596063636363625d544a3f33281b0f0000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e010000000000000000000013202c3946535f6c7986929facac9f928683838383838383838383838383838383838383838383838383838383838383837d7164574a3e3124170b00101d2936434f5c6975828f9ba8afa295897c6f6356493d3024170b0000000003101c2935424f5b6874818e9ba7b0a3968a7d7063574a3d3124170b000000000000000000000000000000000000050c13191f252a2e33373a3d3f4243444546464645444342403d3a37332f2b26201a140d060000000000000000000000000000000000000000050d151d252c32383e44494d5154575a5c5d5e5f5f5f5f5e5d5c5a5855524e4a45403a342e272018100800000000000000000000000000000000000000000000000000000000000006131f2b36414c555e67717a838c959b948e87817a746d666a71787e858c939a978e857b72685f564c42372b1f1307000000000000000000000000000000000000000000000000000000000000000000030e18222c343a3f42424247535f6a767b7b7b7b7b7b7b7b7b7a6f64584c424242413d372f261c1207000000000000000000000000000000000000000000000d1926323e4a56626d79848f9aa5a89e948b837c76716d6a686f7b8895a09386796d6b6f73787f868e97a1aba59b90867a6f64584d41352a1e120600000013202c3946535f6c798693a0ac9f9286796c5f5246392c1f130013202c3946535f6c798693a0ac9f9286796c5f5246392c1f13000000000000000000000000000000000000000000000000000000000000000000000000040b11161a1c1c1c1c1c1c1a16110b040000000000000000000000000000000000000000000000050c12171b1d1e1e1e1e1d1b18130d05000000000000000000000000000000000000000000000000000000000000000003070a0d0f1112131415151515141312100e0c090602000000000000000000000000000000000000000000000000000000000000000000000000000105080b0e1012131415151515141312100e0c0906030000000000000000000000000000000000000000000000000000000000000000000105090c0f11121414151515141312100d0b0704000005080a0a0a0a0a0a0a0a0a0907040000000000000013202c3946535f6c787c7c7c7c7265594c3f3226190c000000000000000000000000000000000000000000000000030c151e262f363e454b51575c6064686a6d6f70717272727271706e6c6966635f5a554f49433c342d241c130a000000000000000000000c1925323e4a56626c70707070707070706f675c5144382b1f12060000000000000000000000000000000000000000000000000b1824313d4955616b6f6f6f6f6e665c5044372b1e120000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e010000000000000000000013202c3946535f6c798693a0acafa39891909090909090909090909090909090909090909090909090909090909090908a7d7164574a3e3124170b00111e2b3744515d6a7784909daaada194877b6e6155483b2f22150900000000000e1a2734404d5a6673808d99a6b1a4988b7e7165584b3f3225190c0000000000000000000000000000000000000001080e14191e22272a2e3033353638393939393838363533312e2b27231f1a150f090300000000000000000000000000000000000000000000030b131a21272d33383d4145484b4d4f50515253535252514f4d4b4945423e39342f29231c150e0600000000000000000000000000000000000000000000000000000000000000020e1a25303a434c555f68717a838c959f99928c857e7871757c838990979e988e857c726960564d443a30261a0f0300000000000000000000000000000000000000000000000000000000000000000009141f2a343e454b4f4f4f4f4f5a646d6f6f6f6f6f6f6f6f6f6e685e534f4f4f4f4d4841382e24190d020000000000000000000000000000000000000000000916222e3a45515c68737e89939ca5a69d958e87827d7a7775737b8895a093867975787b7f848a9198a0a9a69d93897e74695e53473c3025190d0100000013202c3946535f6c798693a0a09f9286796c5f5246392c1f130013202c3946535f6c798693a0a09f9286796c5f5246392c1f130000000000000000000000000000000000000000000000000000000000000000000000050e161c222628292929292826221c160e05000000000000000000000000000000000000000000060f171e23272a2a2a2a2a2a28241e170f070000000000000000000000000000000000000000000000000000000003070c101316191b1d1f20212222222121201e1c1a1815120e0a0601000000000000000000000000000000000000000000000000000000000000000004090d1114181a1c1e20212122222121201f1d1b1816120f0b06010000000000000000000000000000000000000000000000000000000004090d1215181b1d1f202122222221201e1c1a1714100b0c11141617171717171717171614100b05000000000013202c3946535f6c798689897f7265594c3f3226190c0000000000000000000000000000000000000000000000020c151e27303840484f565c62676c707477797b7d7e7e7f7f7e7d7c7b7876736f6b66615b544d463e362e251c12090000000000000000000d1a2633404d5966737d7d7d7d7d7d7d7d796c6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727c7c7c7c786c5f5346392c20130000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e010000000000000000000013202c3946535f6c798693a0acb4aaa29d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d978a7d7164574a3e3124170b00121f2c3845525e6b7885919eabaca09386796d6053473a2d21140700000000000c1926333f4c5965727f8c98a5b2a5998c7f7366594c403326190d00000000000000000000000000000000000000000003080d12161a1e212426282a2b2c2c2c2c2c2b2a282624221f1b17130e09040000000000000000000000000000000000000000000000000001080f161c22272c3135383b3e4042444546464646454443413f3c3936322d29231e18110b0400000000000000000000000000000000000000000000000000000000000000000008131e28313a434d565f68717a838d969f9d97908a837c80868d949ba2988f867c736a60574e443b32281e1409000000000000000000000000000000000000000000000000000000000000000000010d1925313c4650575b5c5c5c5c5c5c61626262626262626262625e5c5c5c5c5c5c59534a40352a1e120600000000000000000000000000000000000000000005111d2935404b57616c77818a939ca3a79f99938e89868381807e8895a09386818284878b90959ba2aaa59d948b81776d62584d41362b1f14080000000013202c3946535f6c7986939393939286796c5f5246392c1f130013202c3946535f6c7986939393939286796c5f5246392c1f1300000000000000000000000000000000000000000000000000000000000000000000040e1720272e32353636363635322e2720170e0400000000000000000000000000000000000000050f1821282f34363737373737342f2921190f050000000000000000000000000000000000000000000000000003090e13181c202326282a2c2d2e2e2e2e2e2d2c2b292724221e1b16120d070200000000000000000000000000000000000000000000000000000000050b1015191d212427292b2c2d2e2e2e2e2e2d2b2a2725221f1b17120d080200000000000000000000000000000000000000000000000003090f15191e2125282a2c2d2e2e2e2e2e2d2b292623201c17171d2123242424242424242423201c1710080000000013202c3946535f6c7986938c7f7265594c3f3226190c00000000000000000000000000000000000000000000000a141e273039424a525a61686d73787c808386888a8b8c8c8c8b8a898785827f7b77726c665f58504840372e241b110700000000000000000d1a2633404d596673808a8a8a8a8a8a86796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f898986796c5f5346392c20130000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e010000000000000000000013202c3946535f6c7986929facb7ada5a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a2a8aaaaa3978a7d7063574a3d3024170a00131f2c3946525f6c7985929facac9f9286796c5f5346392c20130600000000000c1825323e4b5865717e8b98a4b1a69a8d8073665a4d4034271a0d000000000000000000000000000000000000000000000002060a0e1215171a1c1d1e1f1f201f1f1e1d1c1a1815120f0b07020000000000000000000000000000000000000000000000000000000000040b11161c2025292c2f3234363738393939393837363432302d2926221d18130d070000000000000000000000000000000000000000000000000000000000000000000000020c161f28313a434d565f68717a848d969fa29b948e878a91989fa29990867d746a61584e453c322920160d0200000000000000000000000000000000000000000000000000000000000000000004111d2936424d58626869696969696969676157555555555c656969696969696969655c52463a2e221609000000000000000000000000000000000000000000010c18232f3a45505a656f78818a9299a0a6a49e9a9692908e8c8c8e98a2978e8d8f9194979ba0a6a8a29b938b83796f655b51463b30251a0e030000000013202c3946535f6c7986868686868686796c5f5246392c1f130013202c3946535f6c7986868686868686796c5f5246392c1f13000000000000000000000000000000000000000000000000000000000000000000000b16202932393e4242424242423e39322920160b000000000000000000000000000000000000010c16212a333a40434444444443403a332b21170c010000000000000000000000000000000000000000000002080f141a1f24282c2f323537383a3b3b3b3b3b3a39383634312e2a27221e19130d0700000000000000000000000000000000000000000000000000030a10161c2125292d30333637393a3b3b3b3b3a39383634312e2b27231e19130d0700000000000000000000000000000000000000000000070e141a20252a2e313436383a3b3b3b3b3a39383533302c282322282d3030303030303030302f2c28221a120800000013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000000000000008121c263039424b545c646c72797e84898c909395969898999898979694928f8b87837d77716a625a524940362d23190e04000000000000000d1a2633404d596673808d979797979386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e0100000000000000000000121f2c3945525f6c7885929fabb1a59b9493939393939393939393939393939393939393939393939393979faaafa396897c6f6356493d3023160a0013202c3946535f6c798693a0acac9f9285786b5f5245392c1f120600000000000b1824313e4b5764717e8b97a4b1a79a8d8174675a4d4134271a0e00000000000000000000000000000000000000000000000000000205080b0d0f1012121313131212100f0d0b09060300000000000000000000000000000000000000000000000000000000000000000000050b1014181c20232527292a2b2c2c2c2c2c2b29282623201d1a16110c070100000000000000000000000000000000000000000000000000000000000000000000000000040d161f28313b444d565f68717a848d969fa69f9994959ca3a39a90877e746b62584f463c332a20170e040000000000000000000000000000000000000000000000000000000000000000000006121f2c3845525e6a737575757575757573695d51484b57636e75757575757575756e63574a3e3124180b0000000000000000000000000000000000000000000007121e29343e49535d666f7880878e949a9fa3a6a29f9c9b99989aa0a9a09a9a9b9da0a3a7a5a19c969089817970675d54493f342a1f14080000000000131f2c3946525f6b7679797979797979766b5e5245382c1f1200131f2c3946525f6b7679797979797979766b5e5245382c1f1200000000000000000000000000000000000000000000000000000000000000000006111d27323b444a4e4f4f4f4f4e4a443b32271d1106000000000000000000000000000000000006121d28323c454b5051515151504c453d33291e1207000000000000000000000000000000000000000000050c131a20252b3034383b3f41434546474848484847464442403d3a37332e29241e18120b0300000000000000000000000000000000000000000000070e151b22272c3135393d40424446474848484847464543403e3b37332e2a241e18120b03000000000000000000000000000000000000010911181f262c31363a3e4143454647484848474644423f3c38342f2d34393c3d3d3d3d3d3d3d3d3c38332c241a1006000013202c3946535f6c7986938c7f7265594c3f3226190c000000000000000000000000000000000000000000040f19242e38424b545d666e767d848a9094999c9fa1a3a3a2a2a2a3a4a2a09e9b97938e89827b746c645b52483f352a20150a000000000000000d1a2633404d596673808d9aa4a4a09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e0100000000000000000000121e2b3845515e6b7784919eaaada19489868686868686868686868686868686868686868686868686868e9aa6aea295887b6f6255493c2f2216090013202c3946535f6c798693a0acac9f9285786b5f5245382c1f120500000000000b1724313e4a5764717d8a97a4b1a79a8e8174675a4d4134271a0e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004080c101316191b1c1e1f1f20201f1f1e1d1b191714110d09050000000000000000000000000000000000000000000000000000000000000000000000000000000000040d161f29323b444d565f68727b848d96a0a0a0a0a0a0a09a91887e756b625950463d342a21180e0500000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7982828282828282786b5f52454c5865727e8282828282827e7165584b3e3225180b00000000000000000000000000000000000000000000010c17222d37414b545d666e757d83898e93979a9da0a2a4a5a5a6abb2aba7a5a4a3a19f9c9995908b857e776f675e554b42382d23180d020000000000111e2a37434f5a646b6c6c6c6c6c6c6c6b645a4e42362a1d1100111e2a37434f5a646b6c6c6c6c6c6c6c6b645a4e42362a1d110000000000000000000000000000000000000000000000000000000000000000000a16222e39444d555b5c5c5c5c5b554d44392e22160a00000000000000000000000000000000000a16222e39444e565c5d5d5d5d5c574f453a2f23170b0000000000000000000000000000000000000000080f171e252b31363b4044484b4e50525354555555545352514f4d4a47433f3a352f29231c150d06000000000000000000000000000000000000000109111920262d33383d4246494c4f515253545555545453514f4d4a47433f3a35302a231c150e0600000000000000000000000000000000010a131b232a31373d42464a4d505253545555545453514f4c48443f3a363e45494a4a4a4a4a4a4a4a48443e362c22180c010013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000000000000b16202b36404a545d666f7880888f959ba0a5a39f9b99979696969698999ca0a4a39f9a948d867e766d645a51463c32271c11060000000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e0100000000000000000000111e2a3744505d6a7683909ca9ada093867a7979797979797979797979797979797979797979797979808c99a6ada094877a6d6154473b2e2115080013202c3946535f6c798693a0acac9f9285786b5f5245382c1f120500000000000b1724313e4a5764717d8a97a4b1a79a8e8174675a4d4134271a0e000000000000000000000000000000000000000000000001030406070708080807060503010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004070a0c0e101112131313131211100e0c0a0805010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d172029323b444d576069727b848e9393939393939392887f756c635950473e342b22180f060000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c79868f8f8f8f8f85786b5f52454c5865727e8c8f8f8f8f8b7e7165584b3e3225180b000000000000000000000000000000000000000000000006101b252f39424b545c646b72787d82878b8e9193959798999ba1a9a09a9998969592908d8985807a746d655d554c433a30261b11060000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5a52483d32261a0e000e1a26323e48525a5f5f5f5f5f5f5f5f5f5a52483d32261a0e0000000000000000000000000000000000000000000000000000000000000000000d1a26333f4a555f6769696969675f554a3f33261a0d01000000000000000000000000000000000d1a26333f4b5660686a6a6a6a6861574b3f33271b0e0200000000000000000000000000000000000009111a212930363c42474c5054575a5c5e606161616161605f5d5b5956534f4b46413b352e271f170f070000000000000000000000000000000000020b131b232a31383e44494e5255595b5d5f6061616161615f5e5c5957534f4b46413b352e271f180f070000000000000000000000000000000a131c252d353c42484d5256595c5e6061616161615f5d5b5854504b453f4850555757575757575757554f483e34291e12060013202c3946535f6c7986938c7f7265594c3f3226190c000000000000000000000000000000000000000006111c27323d47525c666f78828a929aa0a7a39d97938f8c8a8989898a8b8d9093989da3a59f9890887f766c62584e43382d22170c0000000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e0100000000000000000000101c2936424f5c6875828e9ba7aea194877b6e6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c74818e9aa7ab9f9285796c5f5346392d2013070013202c3946535f6c7986939facac9f9285786c5f5245392c1f120600000000000b1824313e4b5764717e8b98a4b1a79a8d8173675a4d4134271a0e000000000000000000000000000000000000000104080b0d0f11131414151514141312100e0c090602000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050e172029323b454e576069727b85868686868686868680766d635a51473e352c22191006000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986939c9c9c9285786b5f52454c5865727e8c989c9c988b7e7165584b3e3225180b00000000000000000000000000000000000000000000000009131d273039424a525960666c72767b7e828487898a8b8c8f99a2978e8c8b8a888683817d78746e69625b544b433a31271e140a000000000000000a16212c3740484f5253535353535353524f4840362c21150a000a16212c3740484f5253535353535353524f4840362c21150a0000000000000000000000000000000000000000000000000000000000000000000f1c2935424e5b67717575757571675b4e4235291c0f03000000000000000000000000000000000f1c2835424e5b67727777777773685c4f4336291d1003000000000000000000000000000000000009121b232b333a41484d53585c606467696b6c6d6e6e6e6e6d6c6a6865625f5b56514c463f38312921191007000000000000000000000000000000020b141d252d353c43494f55595e6265686a6c6d6e6e6e6e6d6c6a6866635f5b57524c464039312a211910070000000000000000000000000008121c252e373f464d53595e6266696b6c6d6e6e6e6d6c6a6764605c57514a515a616363636363636363615a50453a2e22160a0013202c3946535f6c7986938c7f7265594c3f3226190c00000000000000000000000000000000000000000c17222e39444e59646e78818b949ca4a8a099928c8783807d7c7c7c7d7e8184878c9299a0a8a29a91887e746a60554a3f34281d110600000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e01000000000000000000000e1b2734414d5a6673808c99a5afa296897c70635f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f6a7683909ca9a99d9084776a5e5144382b1e120500131f2c3945525f6c7885929facac9f9286796c5f5346392d20130600000000000c1825323f4b5865717e8b98a5b1a6998d807366594d4033271a0d000000000000000000000000000000000004090d1114171a1c1e1f202121212120201e1d1b1815120e0a060100000000000000000000000000000000000000000000000305070707070707070707070707070707070707070707070707070707070707070707070707070707070706030000000000000000000000000000000000000000000000000000000000000000000000000000000000050e172029333c454e57606972797979797979797979766d645b51483f352c231a100700000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c798693a0a99f9285786b5f52454c5865727e8c98a5a5988b7e7165584b3e3225180b000000000000000000000000000000000000000000000000010b151e27303840484f555b61666a6e7275787a7c7d7e808895a093867f7e7d7b797774706c68635d575049423a31281f160c020000000000000005101a252e373e43464646464646464646433d362e241a0f040005101a252e373e43464646464646464646433d362e241a0f04000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c69768282828276695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c69758284848376695d5043362a1d10030000000000000000000000000000000009121b242d353d454c53595e64686c70737678797a7b7b7b7a79787774726f6b67625d57514a433b332b2219100600000000000000000000000000010b141d262f373f474e545b60656a6e717476787a7b7b7b7b7a797775726f6b67635d57514a433b332b221a1007000000000000000000000005101a242e37404951585f656a6e727577797a7b7b7b7a797674706c68625c5558636c70707070707070706c62564a3e3225190c0013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000000005111d28343f4a55606b75808a949da6a89f968e87817b7673716f6f6f707274777b81878e969ea7a39a90867c71665b5045392e22160b00000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e01000000000000000000000c1925323f4b5864717d8a96a3afa4988b7e7265595353535353535353535353535353535353606c7985929eaba79a8e8175685b4f4236291d100300121f2b3845515e6b7884919eaaada093877a6d6054473a2e21140700000000000d1926333f4c5966727f8c98a5b2a5998c7f7266594c3f3326190d000000000000000000000000000000050a1014191d202426292a2c2d2e2e2e2e2d2c2b292725221e1a16120d070200000000000000000000000000000000000000050b0f12141414141414141414141414141414141414141414141414141414141414141414141414141414141412100c0600000000000000000000000000000000000000000000000000000000000000000000000000000000050e17202a333c454e5760696c6c6c6c6c6c6c6c6c6b645b52493f362d231a11070000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c798693a0ac9f9285786b5f52454c5865727e8c98a5a5988b7e7165584b3e3225180b00000000000000000000000000000000000000000000000000030c151e262e363d444a50555a5e6266696b6e6f71727b8895a093867971706f6d6a6764605c57524c463f3830281f160d0400000000000000000009131c252c323739393939393939393936322c241c120800000009131c252c323739393939393939393936322c241c120800000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c6976838f8f8376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d100300000000000000000000000000000008121b242e373f474f575e646a6f74797c808284868788888887868583817e7b77736e68625c554d453d342b22180e0400000000000000000000000009131d262f38414951585f666c71767a7e8183858687888888878684827e7b78736e69635c554d453d342c22190f05000000000000000000010c17222c364049525b626a70767a7e82848687888888878583807d78736d675f5b67747d7d7d7d7d7d7d7d7366594d4033261a0d0013202c3946535f6c7986938c7f7265594c3f3226190c000000000000000000000000000000000000000a16222e3945505b67727c87929ca5aaa0968d847c756f6a67646362626365676b70757c848c959ea8a2988e83786d61564a3f33271b0f03000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e01000000000000000000000a1723303c4955626e7b8793a0aca69a8e8175695c5046464646464646464646464646464a57636f7b8894a1ada4978b7e7266594d4034271b0e0100111e2a3744505d6a7783909da9aea194887b6e6255483c2f22160900000000000e1b2734414d5a6773808d9aa6b1a4988b7e7165584b3f3225180c00000000000000000000000000030a10161b2025292d30333537393a3a3b3b3a3a39383634312e2a27221d18130d0600000000000000000000000000000000010910161b1f20202020202020202020202020202020202020202020202020202020202020202020202020202020201f1c17120b03000000000000000000000000000000000000000000000000000000000000000000000000000000050e18212a333c454e575d5f5f5f5f5f5f5f5f5f5f5a524940372d241b1108000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c798693a0a09f9285786b5f52454c5865727e8c98a0a0988b7e7165584b3e3225180b0000000000000000000000000000000000000000000000000000030c141c242b32393f444a4e5256595c5f6163646f7b8895a09386796d6462605e5b5854504c46413b342d261e160d0400000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2a26211a120a00000000010a131a21262a2c2c2c2c2c2c2c2c2c2a26211a120a0000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d1003000000000000000000000000000005101a242d374049515961686f757b8085898c8f919394949594949392908e8b87837f7a746d665f574f463d342a20160c010000000000000000000007111b252f38414a535b636a71777d82868a8d909293949595949392908e8b88847f7a746d675f574f473e342b21170d03000000000000000007121e29333e48525b646d747b81868b8e9192949495949392908d89847e78716a616875828a8a8a8a8a8a7e7265594c3f3326190d0013202c3946535f6c7986938c7f7265594c3f3226190c000000000000000000000000000000000000030f1b27333e4a56616d78838e99a3ada2988e847b726a645e5a5856555657585b5f646a727a838c96a0a69f94897e72675b4f43372b1f1206000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e01000000000000000000000814212d3a46525f6b7784909ca8a99d9185786c6155493e3939393939393939393939434f5b67737f8b98a4ada094887b6f63564a3e3125180c0000101c2936424f5c6875828e9ba8afa296897c7063564a3d3124180b0000000003101c2936424f5b6875828e9ba7afa3968a7d7063574a3d3124170b000000000000000000000000070e151b21272c3135393c3f424445464748484747464442403d3a37332e29241e18110a0300000000000000000000000000010b131b22272b2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2b28231c150c03000000000000000000000000000000000000000000000000000000000000000000000000000000060f18212a333c454c51535353535353535353524f4940372e251b120900000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986939393939285786b5f52454c5865727e8c939393938b7e7165584b3e3225180b000000000000000000000000000000000000000000000000000000020a121a21272e33393e42464a4d50525456626f7b8895a09386796d605554514f4c4844403b353029231b140c04000000000000000000000000010910161a1e1f202020202020201f1e1a161008000000000000010910161a1e1f202020202020201f1e1a161008000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d100300000000000000000000000000020d17212c353f49525b636b737a81878c9195989b9d9fa0a1a2a1a1a09e9c9a97948f8a857f78716961584f463c32281e1308000000000000000000030e18232d37414a535c656d747c82888e92969a9c9ea0a1a1a2a1a09f9d9b9894908b857f787169615850463d33291f140a00000000000000010d18242f3a454f5a646d767e868d92979a9d9fa0a1a2a1a09e9c9995908a837b736b6976828f979797978b7e7165584b3e3225180b0013202c3946535f6c7986938c7f7265594c3f3226190c00000000000000000000000000000000000007131f2b37434f5b66727e8994a0aaa69b91867c72696059534e4b4949494a4c4f53596068717a848f9a9996928f83776c6053473a2d211407000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e010000000000000000000005111e2a37434f5b6874808c98a4ada195897d71665a4f453b312c2c2c2c2c2c2c343e49545f6b77838f9ba7a99d9184786c6053473b2e22150900000e1b2834414e5a6773808d99a6b1a4988b7e7265594c4033271a0e0100000006121f2b3844515d6a7683909ca9aea194887b6e6255493c2f23160900000000000000000000010911181f262c32383d4145494c4e505253545454545352514f4d4a47433f3a352f29231c150d0500000000000000000000000009131d252d33373a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a38342e271e150b01000000000000000000000000000000000000000000000000000000000000000000000000000000060f18212a333b414546464646464646464646433e372e251c13090000000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986868686868685786b5f52454c5865727e8686868686867e7165584b3e3225180b0000000000000000000000000000000000000000000000000000000000080f161c22282d32363a3e4143464855626f7b8893939386796d60534745423f3c38342f2a241e18110a02000000000000000000000000000000050a0e11131313131313131313110e0a04000000000000000000050a0e11131313131313131313110e0a0400000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000000000009141e29333d47515b646d757d858c92989da1a5a39f9d9b9a9a9a9a9b9da0a3a3a09b96908a837b736a61584e443a2f251a0f0400000000000000000a151f2a343f49535c656e777f868d94999ea2a4a09d9a999898999a9c9fa2a4a09b96908a837b736a62584f453b31261c110600000000000006121e2935404b56616c76808890989ea3a7a9a5a19f9d9c9c9c9c9ea09b958d857d746a7683909da4a4978a7d7164574b3e3124180b0013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000000b17232f3b47535f6b77838f9aa6aca1958a7f746a60574e47423f3d3c3c3d3f43484e565f68727d88918d8a86837f7a6e6154473b2e211408000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000000000000000000000131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e0100000000000000000000020e1b27333f4c5864707c88949faba59a8e82776c61574d433b3532302f3033373d46505a65707c88939faba4988c8074685c5044372b1f120600000d1926323f4c5865717e8a97a3b0a69a8d8174685b4f42362a1e12060000000915222e3a4753606c7985929eabab9f9286796d6053473a2e211408000000000000000000020a131b232a31383e43484d5155585b5d5f6061616161605f5d5b5956534f4a46403a342e271f170f070000000000000000000005101b252f373e444647474747474747474747474747474747474747474747474747474747474747474747474747474747443f3930271d120700000000000000000000000000000000000000000000000000000000000000000000000000000000060f1821293035383939393939393939393937322c251c130a0100000000000000000000000000000000000000000000000000000000000000000000000000000000000006131f2c3946525f6b7679797979797979766a5e51454b58647079797979797979797064574b3e3125180b000000000000000000000000000000000000000000000000000000000000040b11171c21262a2e3134373c4855626f7b8686868686796d6053463a3633302c28231e19130d0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d1003000000000000000000000000040f1a25303b454f59636d767f878f969da3a7a19b9793908e8d8d8d8e8f9194979ca1a7a29b958d857c736a60564c41362b20150a0000000000000005101b26313c46515b656e77808991989fa5a39d9894908e8c8c8c8c8d8f92969ba0a6a29b958d857c746a61574d42382d22170c0100000000000a17222e3a46515d68737d88929aa2a9aba49e999592908f8f8f909194979c978f867c737784909daaa4978a7d7064574a3d3124170b0013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000020e1a27333f4b5864707c88949faba79b9084786d62584e453d3632302f303133373c444d56616c778384817d7a76736f685d5145392d201307000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000000000000004070809131f2c3946525f6c7986929faca79a8e8174675a4d4134271a0e0908070400000000000000000b17232f3b47545f6b77838f9aa5aa9f94887d73685f564d46413e3c3c3d3f43484f58626c77828d99a4aa9f93887c7064584c4034271b0f0300000b1724303d4956626f7b8894a1ada99c9083776b5e52463a2e22170d0a090a0e1a25313e4a56626f7b8894a1ada99c9083776a5e5145382c1f12060000000000000000020b141d252d343c43494f54595d6164676a6b6d6d6e6e6d6d6c6a6866635f5b56514c463f383129211910070000000000000000000a16212d3741494f5353535353535353535353535353535353535353535353535353535353535353535353535353535353504a42392f24180d0100000000000000000000000000000000000000000000000000000000000000000000000000000000060f171e24292c2c2c2c2c2c2c2c2c2c2c2a27211b130a010000000000000000000000000000000000000000000000000000000000000000000000000000000000000005111e2a37434f5a646b6c6c6c6c6c6c6c6b64594e4248545f686c6c6c6c6c6c6c6c685e53483c2f23160a0000000000000000000000000000000000000000000000000000000000000000060b11151a1e2225282f3b4855616d787979797979766b5f5346392d2723201c18130e080200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0d0f0f0f0f0f0f0d0a0500000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000000000a15202c37424c57616b757f889199a1a8a39c958f8a878482818080818284878b90959ca3a69f978e857c72685d53483d32261b10040000000000000b16212d38434d58626d76808a929ba3a8a099928c888481807e7e808183868a8f959ca3a69f978f867c73695f544a3f34291d120700000000020e1b27333f4b57626e79848f9aa3acaba29a938d8986848282828385878b9096988e857a7784919eaaa4978a7d7063574a3d3024170a0013202c3946535f6c7986938c7f7265594c3f3226190c000000000000000000000000000000000005111e2a36434f5b6774808c98a4afa3978b7f73675c51463c332b2623222324272b323b444f5a66727b7874716d6a67635e564c4135291d1104000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000000000070c11141515151f2c3946525f6c7986929faaa79a8e8174675a4d4134271a15151513100b0600000000000007131f2b37434f5b66727d89949faaa59a8f857a71685f58524d4b49494a4b4f535a616a747e88939eaaa4998e82776b5f53483c3024170b0000000815212e3a4753606c7885919daaac9f93877a6e62564a3f33281e1916161719202a36424e5a66727e8b97a3b0a6998d8174685b4f4236291d100400000000000000010a141d262f373f464d545a6065696d71747678797a7b7b7a79787775726f6b67625d57514a433b332b2219100700000000000000000f1b27333e49535b60606060606060606060606060606060606060606060606060606060606060606060606060606060605c544b4035291d11050000000000000000000000000000000000000000000000000000000000000000000000000000000000050d13191c1f2020202020202020201f1e1b161009010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020e1a26323e48525a5f5f5f5f5f5f5f5f5f5a52483d424d565d5f5f5f5f5f5f5f5f5c564d42372b1f130700000000000000000000000000000000000000000000000000000000000000000000050a0e121518202d3945515c666c6c6c6c6c6c6b645a4f43372b1e1714100c070200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040b11161a1c1c1c1c1c1c1a16110b040000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000000040f1b26323d48535e69737d87919aa3aba299918a847e7a77757373737475787b7f848a9199a1a9a0978e84796f64594e43372c201509000000000005101c27333e49545f6a747e89929ca4a89f968e87817b78757372727374767a7e848a9199a2a9a1988e857b70665b50453a2f23180c0000000006121e2b37434f5b67737f8a96a1acada2999088817c797776757576787b80858b92968c827885929eaba3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c00000000000000000000000000000000000714202d3946525e6b7784909ca8ab9f93867a6e62574b40352a211a191919191a2029333e4a56616a6e6c6865615e5a57534c443a2f24190d01000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c2013000000020b12181d20222222222c3946525f6c7986929d9d9d9a8e8174675a4d41342722222222201c1710090100000000030f1b27323e4a55616c77838e98a3aba1968c83797169635e5a57565556585b5f656b737c868f9aa5a89e93887d71665a4f43372b1f130700000006121f2b3744505c6975818d99a6afa3978b7e73675b50443a302925232223252a323c47525e6a76828e9aa7aea2968a7d7165584c3f33271a0e010000000000000009131c262f38414951585f656b71757a7d8183858687888887868583817e7b77736e68625c544d453d342b22190f0500000000000000111e2a37434f5a656c6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d665d5145392d20140700000000000000000000000000000000000000000000000000000000000000000000000000000000000002080d101213131313131313131313110e0a0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a16212c3740484f5253535353535353524e4840363b444b515353535353535353504b443b30261a0f03000000000000000000000000000000000000000000000000000000000000000000000000020609111d2934404a545b5f5f5f5f5f5f5f5a52493e33271b0f0704000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050e161c222628292929292826221c160e0500000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d100300000000000000000000000915202c37434e5965707a858f99a3aca29990878079736e6b6867666667696b6f737980878f98a1a9a0968b81766b5f54493d31251a0e02000000000a15212d38444f5a66717b86909aa4aaa0968d847c75706b6866656566676a6e72787f879099a3aaa0978d82776d62564b4034291d11050000000915222e3a47535f6b77848f9ba7b1a69b90877e76716d6a696868696c6f737980889094897e85929eaba3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c00000000000000000000000000000000000a16232f3c4855616e7a8793a0aca89b8f83766a5e52463a2e262626262626262626262d39444f585f615f5c5955514e4a47423a32281e130800000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000020c141c23292d2f2f2f2f2f3946525f6c798690909090908e8174675a4d41342f2f2f2f2e2c28221b130a00000000000a16222d3944505b66717c87919ba5a89e958c837b746e6a666463626365676b70767d858e97a1aaa1968c81766b6055493e32261b0f03000000030f1c2834404d5965717d8995a1ada79b8f83786c61564c423a3532302f3032353b434d58636f7b87929eaaaa9e9286796d6155493c3024170b0000000000000006111b252e38414a525b626a70777c81868a8d8f9193949494949392908e8b87837e79736d665f574f463d342b21170d0200000000000013202c3946525f6b777a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a786e6155483b2f22150800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005101a252e373e43464646464646464645433d362e323a4044464646464646464644403a32291f1409000000000000000000000000000000000000000000000000000000000000000000000000000000000c18232e38424a50525353535353524f4940372c21160a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040e1720272e32353636363635322e2720170e04000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d100300000000000000000000010d1925313d48545f6b76818c97a1aba49a90877e756e67625e5b5a595a5b5c5f63686e757d868f99a3a89d92877c7065594e42362a1e1105000000020e1a26323e4955606c77828d98a2aca3988e847a726b645f5c595858595b5e62676d757e87919ba6a99e94897e73685c5145392d22160a0000000b1824313d4a56626f7b8794a0acaba094897e746c65605e5c5b5c5d5f63686e767e8790908585929faca3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c00000000000000000000000000000000000c1825323e4b5764707d8a96a2afa5998c8073675a4e4236333333333333333333333333333d464e535553504c4945423e3b363029221a120800000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c201300000a141e262e34393b3c3c3c3c3c46525f6c79848484848484848174675a4d413c3c3c3c3c3b38332d251c12080000000005111c28333e4a55606a757f89939ca5a79e958d86807a7673706f6f707174777b81888f97a0a9a2988f857a70655a4f44382d21160a00000000000c1824303d4955616d7985909ca8aba094897d72685e544c46413e3d3c3d3e41464d565f6a75808c97a3afa5998d8175695d5145392d201408000000000000030e18222d37404a535c646d747b82888d9296999c9e9fa0a1a1a1a09e9d9a97948f8a857e78716961584f463d33291f140a00000000000013202c3946535f6c798687878787878787878787878787878787878787878787878787878787878787878787878787877b6f6255483c2f2215090000000000000000000000000000000000000004080b0c0d0d0d0d0d0d0d0d0d0c090601000000000000000000000000000000000000000000000000000000000000000005090b0c0d0d0d0d0d0d0d0d0c0b08040000000000000000000000000000000000000000000000000009131c252c323739393939393939393936322c24282f3438393939393939393938342f2820170d020000000000000000000000000000000000000000000000000000000000000000000000000000000007121c2630383f4346464646464646433e372e251b1005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b16202932393e4242424242423e39322920160b000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000006121e2a36424d5965707c87939ea8a89d93887e756b635c56524f4d4d4d4e5053575c636b737d87919c9d9a968d82766a5e5246392d20140700000006121e2b36424e5a66717d88939fa9a79c91867c72696059534f4d4c4c4d4e51565c636c757f8a95a0aba59b8f84796d61564a3e32261a0e0200000d1a2733404c5965727e8b97a3b0a79b8f83786d625a54514f4f4f5053575d646c757e88938e8e96a2aea3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c00000000000000000000000000000000000e1a2734404d5966737f8c98a5b0a3968a7d7164584b404040404040404040404040404040404042464847434040404040403e3a342c241a1005000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130006111c263038404548484848484847515e6a7477777777777777777165594d47484848484848443e372e241a0f04000000000b17222d38434e58636d77818a939ba3a79f98918b86827f7d7c7c7c7e8083878c9399a1a8a19890867c73685e53483d32271c100500000000000814202c3945505c6874808b96a1aca59a8f847970665e57514d4b4949494b4d52575f68717b86919da8aa9f94887c7165594d4135291d11040000000000000a141f2a343f49525c656e767e868d93999ea2a4a09d9b999999999a9c9fa2a3a09b96908a837b736a61584f453b30261b1106000000000013202c3946535f6c798693949494949494949494949494949494949494949494949494949494949494949494949494887b6f6255483c2f2215090000000000000000000000000000000000030a101417191919191919191919191816120c060000000000000000000000000000000000000000000000000000000000050b111518191919191919191919191815100a040000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2a26211a1d24282b2c2c2c2c2c2c2c2c2b28231d160e050000000000000000000000000000000000000000000000000000000000000000000000000000000000000b141e262d33373939393939393937322c251c13090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111d27323b444a4e4f4f4f4f4e4a443b32271d11060000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d1003000000000000000000000a16222e3a46525e6a76818d99a4aea2978c81766c625a524b46424140404143464b5159616b757f8a94918d8a86837a6e6154483b2e2115080000000a16232f3b47535f6b76828e99a5ada2968b80756a60574e4843403f3f4042454a515a636d78838f9aa6aca1958a7e72665a4e42362a1e120600000f1c2835424e5b6874818d9aa6b0a3978b7e73675b51484543424244474b525a636c76818c979aa0a8b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c00000000000000000000000000000000000f1c2935424f5b6874818e9aa7aea195887b6f62554c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4a453e362c22170b000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c2013000b17222d38424a51555555555555534d5862696a6a6a6a6a6a6a6a675f544f54555555555554504940362b2015090000000005111c27323c47515b656f7881899199a0a6a29c97928e8c8a8989898b8d9093989ea4a49e968f867d746b61574c42372c21160b00000000000004101c2834404c57636e7a85909ba5aba0968b82787068625d5a57565556575a5d6369717a838d98a3aea4998e83776c6054483d3125190d00000000000005101b26313b46505a646e77808990989ea4a49e9894918e8d8c8c8c8e9093969ba0a7a19b948d857c736a61574d42382d22170c010000000013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a095887b6f6255483c2f22150900000000000000000000000000000000050d151b20242626262626262626262625221d171008000000000000000000000000000000000000000000000000000000070f161c21242626262626262626262624211c150e060000000000000000000000000000000000000000000000010910161a1e1f202020202020201f1e1a150f12181c1f20202020202020201f1c18120c0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000020c141c22272b2c2c2c2c2c2c2c2a27211b130a01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a16222e39444d555b5c5c5c5c5b554d44392e22160a0000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d1003000000000000000000010d1926323e4a56626e7a86929ea9a99d91867a6f655a5048403a3634333335373a40474f59636e79848885817e7a77736a5f53463a2d2114070000010e1a26323f4b57636f7b87939faaa89d91857a6e63584e453d373432323335393f48515c67727d8995a1ada69a8f83776b5f52463a2e2215090000111d2a3743505d6976838f9ca9ada094877b6f62564a3f38363536373b4048515a656f7a86919da9b1b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000111d2a3743505d6976838f9ca9ada093877a6d615959595959595959595959595959595959595959595959595959595959595650483e33281c10040000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c2013000f1b27333f4a545c6162626262625f5850585c5d5d5d5d5d5d5d5d5b555259606262626262605b52483d3125190d00000000000a15202a353f49535d666f7780878e959aa0a4a29e9b989696969697999c9fa4a39e99938c857d746b62594f453a30251a1004000000000000000c18232f3b46525d68737e89949ea8a89d948a827a736e6966646362636466696e747b838c959faaa69c92877c71665b4f43382c2014080000000000000b16212c37424d58626c768089929aa2a8a099928d888482807f7f808183868a8f959ca3a69f978e867c73695e54493f34281d12060000000013202c3946535f6c798693a0acadadaba6a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a295887b6f6255483c2f221509000000000000000000000000000000040e171f262c3032333333333333333333312e29221a12080000000000000000000000000000000000000000000000000006101921282d3133333333333333333333312d2720180f05000000000000000000000000000000000000000000000000050a0e11131313131313131313110e0a04070c1012131313131313131312100c0701000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a11171b1e2020202020201f1e1b1610090100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1a26333f4a555f6769696969675f554a3f33261a0d0100000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d100300000000000000000004101d2935424e5a66737e8b97a3afa4988c8175695e53483f362e2a272627282a2f353d47515c68737f7c7875716e6a6761584e42372a1e1205000004111d2a36424f5b6773808b98a3afa4988c8074695d52473c332b27262527292e363f4a55616d7884909ca9ab9f93877b6f62564a3d3125180c0000121e2b3845515e6b7784919eaaab9e9285786c5f53463a2e2929292b2f363f48535e6975818c98a4b0b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000121e2b3844515e6b7784919daaac9f9286796c66666666666666666666666666666666666666666666666666666666666666625a5044392d2114080000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c201300121e2b3743505b666d6f6f6f6f6f69625a535050505050505050504f545c646b6f6f6f6f6f6c64594d4135281c0f0000000000040e19232d37414b545d656d757c83898f94989b9ea1a2a3a2a2a3a3a2a09e9a97928d88817a736b625950473d33291e1409000000000000000007131e2a35414c57626d77828c959fa8a69d948c857e7a7573716f6f6f7173767a7f868d959ea7a79e948b80756b6055493e33271b1004000000000004101c27323e49545f69747e88929ba4a89f968e87817c78757372727374777a7e848a9199a2a9a0988e857a70665b50453a2e23170c0000000013202c3946535f6c798693a0acb6aba19a989898989898989898989898989898989898989898989898989898989895887b6f6255483c2f2215090000000000000000000000000000010c16202931383d3f4040404040404040403e3a342c241a10050000000000000000000000000000000000000000000000030e18222b33393d3f40404040404040403f3d38322a21170d020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060b0f1213131313131313110e0a05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2935424e5b67717575757571675b4e4235291c0f0300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000713202c3845515e6a76838f9ba7aca094887b7064584d42372d241d1b1a1a1b1e242b35404b57636d726f6c6965625e5b564f463c31261a0e0200000714202d3945525e6a77838f9ca8ada194887c7064584c41352a211b19191a1d242e3944505c6874818d99a5afa3978b7e7266594d4134281b0f0200121f2c3945525f6c7885929faba99d9083766a5d5144372b1e1c1c1e242d37414d5864707c8894a0adb0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000121f2c3845525f6b7885929eabac9f92857873737373737373737373737373737373737373737373737373737373737373726c6155493c3023170a0000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130013202c3946525f6c787b7b7b7b7b746c655d564e4744444444474e565e666e757b7b7b7b7b76695d5043372a1d1000000000000007111b252f38424b535b636b72787e83888c8f92949697979897969593918e8b87827c767068615950473e352b21170c020000000000000000020d19242f3b46505b66707a848d969ea6a69e96908a86827f7d7c7c7c7d7f82868b90979fa7a59d958c82786e64594e43382d22160a0000000000000915212d38444f5a65707b86909aa4aaa0968d857d76706c6967656566686a6e737880879099a3aaa0968c82776c61564b3f34281d110500000013202c3946535f6c7884909ba7b2a69a8f8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b887b6f6255483c2f221509000000000000000000000000000007131e28323b43494c4c4c4c4c4c4c4c4c4c4a453e362c22170b00000000000000000000000000000000000000000000000915202a343d44494c4c4c4c4c4c4c4c4c4c49433c33291e1308000000000000000000000000000000000000000000000000000000000001060a0d0e0e0e0e0e0e0e0e0e0d0c08040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c69768282828276695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000916222f3b4854616d7986929eaba99c9084786b5f53473c30252222222222222222232f3b46515b626563605c5955524e4b453d342b2015090000000a16232f3c4855616e7a86939fabaa9d9185786c6054473b3024190f0c0c0d121c2834404c5864707d8996a2afa79a8e8275695c5043372a1e11050013202c3946535f6c7986929faca89b8f8275685c4f4236291c100f121b25303c4854606c7885919daab0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000131f2c3946525f6c7986929facac9f928580808080808080808080808080808080808080808080808080808080808080807d7164574a3e3124170b0000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130013202c3946535f6c7986888888867e776f686059514a424149515960687078808788888884776a5d5044372a1d110000000000000009131d262f394149515960676d72777c80838587898a8a8b8a8a888785827e7a76716b655e574f473e352c23190f050000000000000000000008131e29343f49545e68717b848c949ba2a8a19b96928e8c8a8989898a8c8e92969ca2a7a19b938b837a70675c52483d32271c10050000000000020e1a26323d4955606b77828d98a2aca3988e847b726b65605c5a59595a5b5e62676e757e87919ca6a89e94897e73675c5045392d21160a000000121e2b3744505c67737e8a96a1aca4978b7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7b6e6255483c2f22150900000000000000000000000000000c18242f3a444d54585959595959595959595650483e33281c1005000000000000000000000000000000000000000000030e1a26313c464f5559595959595959595959554e453b3024190d01000000000000000000000000000000000000000000000000000000060d1216191a1a1a1a1a1a1a1a1a1a1815100a0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306090b0c0e0f1010111110100f0e0d0b09070401000000000000000000000000000000000000000000000000000000000000000000000000050a0e101111111111100d0904000000000000000000000000000000000000000000101c2936434f5c6976838f8f8376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000b1824313e4a5763707c8995a2aea69a8d8174685c4f43372f2f2f2f2f2f2f2f2f2f2f2f353f495157595754504d4946423f3a332b22190f060000000c1825323e4b5764707d8996a2afa79b8e8275695c5044372b1f13070000010c1723303c4855616d7a86939facaa9d9184786b5f5246392c2013070013202c3946535f6c798693a0aca89b8e8174685b4e4135281b0f0209141f2b3744505c6975828e9ba7b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c000000000000000000000000000000000013202c3946535f6c798693a0acada1968e8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8a7d7164574a3e3124170b0000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c201300121f2c3845515e69747d87919590898179726a635b544c4b535b636a727a828a91958f857b72675b4f4336291d1000000000000000010b141d262f3840474e555b61676b6f7376797b7c7d7d7e7d7d7c7a7875726e6a65605a534c453d352c231a11070000000000000000000000020d18222d38424c565f69717a828a90979ca1a5a29e9b989796969697989b9ea2a5a19c969089827971685e554b40362b20160a00000000000006121e2a36424e5a66717d88939ea9a89c91877c7269605954504d4c4c4d4f52565c636c75808a95a0aba59a8f84786d61564a3e32261a0e0200000f1c28343f4b57626e7985909ba6a69b8f8478717171717171717171717171717171717171717171717171717171717170695e53463a2e2114080000000000000000000000000000101c2834404b565f65666666666666666666625a5044392d21150900000000000000000000000000000000000000000007131f2b37424e58616566666666666666666560574c4135291d100400000000000000000000000000000000000000000000000000000810181e23262727272727272727272724201b140d040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000106090d10131517191a1c1c1d1d1d1d1d1c1b19181613110e0a070300000000000000000000000000000000000000000000000000000000000000020a10161a1d1e1e1e1e1e1c19150f080000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000d1a2633404c5965727e8b98a4b0a4978b7e7165584c403c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3f464a4c4b4744403d3c3c3c3a36302921180e0300000e1a2733404d5966727f8c98a5b1a5988c7f73665a4d4134281b0f030000000714202c3945525e6b7784919daaaca093877a6d6154483b2e2215080013202c3946535f6c798693a0aca79a8e8174675a4e4134271b0e01030f1b2834414d5a6673808c99a6b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c000000000000000000000000000000000013202c3946535f6c798693a0acb2a89f9a999999999999999999999999999999999999999999999999999999999999978a7d7164574a3e3124170b0000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c201300101d2935414d58626b757e88929a938b847c756d665e57555d656d747c848c949b91877d736960564b3f33271a0e0000000000000000020b141d262e3841484d50565b5f63676a6c6e6f70717171706f6d6b6966625e59544f4c463e352b231a11080000000000000000000000000006111b26303a444d575f6870787f858b9095999c9fa1a2a3a2a2a2a3a2a19e9c9895908b857e7770675f564c43392f241a0f040000000000000a16222e3b47535f6b76828e99a5ada2968b80756a60574f4843413f3f4042464b525a636e78848f9aa6aca1958a7e72665a4e42362a1e120500000b17232f3a46515c68737e8a95a0aba0958a7f7469646464646464646464646464646464646464646464646464646464645f574d42362a1e12050000000000000000000000000000121e2b3844505d68717373737373737373726c6155493d32261a0e0200000000000000000000000000000000000000000c18242f3b47535f6a72737373737373737371695d5145382c1f13060000000000000000000000000000000000000000000000000008111a22292f3234343434343434343433312c261f160d0300000000000000000000000000000000000000000000000000000000000000000000000000000000000004090d1216191c1f2224262728292a2a2a2a292927262422201d1a17130f0a0601000000000000000000000000000000000000000000000000000000030c141b2126292a2a2a2a2a2925201a120a01000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000f1b2835414e5b6774818d9aa6aea295897c6f6356494848484848484848484848484848484848484848484848484848484846423b332a1f150a00000f1c2935424e5b6874818e9aa7b0a3968a7d7064574b3e3225190c0000000004111d2a3643505c6975828f9ba8aea295897c6f6356493d3023170a0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000c1925323f4b5865717e8b98a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c000000000000000000000000000000000013202c3946535f6c7986939facb9b0a8a4a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a5a6a6a6a4978a7d7063574a3d3124170a0000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c2013000d1925303b465059636c768089939d968e877f777068615f676f777f878e969c93897f756b61584e44392e23170b00000000000000000006121e2935404a53595c5c5c5c5c5c5d5f6163646464646362615f5c5c5c5c5c5c5b5750473c31251a0e0100000000000000000000000000000a141e28323b454d565e666d747a8085898d9092949697979897969594928f8c89847f7a736d655e554d433a31271d1208000000000000010e1a26323f4b57636f7b87939faaa99d91857a6e63584e453d3734333334363a4048515c67727d8995a1ada69a8e83776a5e52463a2e211509000006121e2935404b57626d78838e99a4a69b90867b71675d5757575757575757575757575757575757575757575757575757544e453b31251a0e020000000000000000000000000000131f2c3946525f6c7980808080808080807d72665a4e42362a1e13070000000000000000000000000000000000000005101c2834404c58646f7b8080808080808080796d6053463a2d201307000000000000000000000000000000000000000000000000050f1a232c343a3f414141414141414141403d3830281f150a00000000000000000000000000000000000000000000000000000000000000000000000000000000040a1015191e2225292c2e30323435363637373736353433312f2c2926231f1b16110c0701000000000000000000000000000000000000000000000000010b151e262d3236373737373735312b241c1309000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d1003000000000000000000101d2a3643505c6976828f9ca8ada094877a6e61555555555555555555555555555555555555555555555555555555555555534d453b31261b0f0300111d2a3743505d6976838f9ca9aea195887b6f6255493c3023160a00000000010f1b2835414e5b6774818d9aa7b0a4978a7d7164574b3e3125180b0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1724313e4a5764707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000131f2c3946525f6c7985929facb2a79e97969696969696969696969696969696969696969696969696969aa2acb0a396897d7063564a3d3023170a0000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130008141f2a343e47515a646e77818b949e989189827a736b6a7179818991989e948a81776d63594f463c32281d12060000000000000000000915222e3a46515c646969696969696969665e57575757576067696969696969696862584e42362a1d11040000000000000000000000000000020c162029333b444c545b62696e74797d81838688898a8a8b8a8a89878583807c78736e68625b544c433a31281f150b0100000000000004111d2936424e5b67737f8b97a3afa4988c8174695d52473c332b28262627292e36404a56616d7885919da9ab9f93877b6e62564a3d3125180c0000010d18232f3a45515c67727d88929da7a2978d83786e655b524b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b48433c33291f1409000000000000000000000000000000121f2b3844515d6975818c8c8c8c8c8c8c82766a5e53473b2f23170b000000000000000000000000000000000000000915212d3945505c6874808c8c8c8c8c8c8c8175695e5145392c1f13060000000000000000000000000000000000000000000000000a16212b353e464b4d4d4d4d4d4d4d4d4d4d49423a31271c110500000000000000000000000000000000000000000000000000000000000000000000000000030a10161b20252a2e3235383b3d3f404243434444434342413f3d3b3936332f2b27221d18120c06000000000000000000000000000000000000000000000007121d2730383e424444444444413d362e251b10050000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d1003000000000000000000111e2b3744515d6a7784909daaaca09386796d626262626262626262626262626262626262626262626262626262626262625e574d43372b1f130700121e2b3844515e6b7784919daaada094877a6d6154473b2e21150800000000000d1a2733404d596673808c99a6b2a5988b7e7265594c3f3226190c0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000121f2b3845525e6b7885919eabaea2968c8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a909ba7afa295887c6f6255493c2f2316090000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c201300020d18222c353f48525c656f79828c969f9b948c857d76747b838b939ba0968c82786f655b51473d342a20160b000000000000000000000b1724313d4a56626e75757575757575757065594c4b4f5c687275757575757575746a5e5245392c201306000000000000000000000000000000040e172129323a424a51575d63686d707477797b7c7d7d7e7d7d7c7b797673706c68635d575049423a31281f160d03000000000000000714202c3945525e6a77838f9ba8ada194887c7064584c41352b211b19191a1d242e3945505c6874818d99a5afa3978b7e7266594d4034281b0f02000007121e29343f4a55606b76818b959fa99f958a81776d645a5148403e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3c38312a21180d03000000000000000000000000000000101c2935414c5864707c87939999999993877b6f63574b4034281c10040000000000000000000000000000000000020e1a26313d4955616d7985919999999994887c7065594d4135291d10040000000000000000000000000000000000000000000000030f1b27323d4750575a5a5a5a5a5a5a5a5a59544c43382d22160a000000000000000000000000000000000000000000000000000000000000000000000000070e151b21272c31363a3e414447494b4d4e4f505050504f4f4d4c4a4845423f3b37332e29231d17110a030000000000000000000000000000000000000000020d19242f3942494e51515151504e4840372d22170b0000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d1003000000000000000000121f2c3845525e6b7885919eabac9f9285796f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6e695f54483b2f23160900121f2c3845525f6b7885929eabaca09386796c6053463a2d20130700000000000c1925323f4c5865727e8b98a5b2a6998c807366594d4033261a0d0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000111e2b3744515d6a7784909daaada093867d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7f8c99a6ada194877b6e6154483b2e2215080000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c2013000006101a232d37404a535d67707a848d97a19e968f87807e868d959da1988e847a70665d53493f352c22180e04000000000000000000000b1824313e4b5764717e8282828282828173675a4d44505d6a7782828282828282796d6053463a2d20130700000000000000000000000000000000050f172028303840474c52575c6164676a6c6e6f70717171706f6e6c6a6764605c57524c473f3730281f160d0400000000000000000a16232f3c4855616d7a86939fabaa9d9185786c6054483c3024190f0c0c0e121d2834404c5864717d8996a2afa79a8e8275695c5043372a1e11050000010c18232e39444f59646f79838e98a1a69c92897f766c635a52494038313131313131313131313131313131313131312f2c2620180f06000000000000000000000000000000000c1824303c48535f6b77838e9aa6a6a3978b8074685c5044382c211509000000000000000000000000000000000007121e2a36424e5a66717d8995a1a6a69b8f84786c6054483c3125190d01000000000000000000000000000000000000000000000006131f2c38434f5962676767676767676767655e554a3e32261a0d01000000000000000000000000000000000000000000000000000000000000000000020a11191f262c32383d42464a4e515456585a5b5c5d5d5d5d5c5b5a595754524f4b47433f3a342f28221b140d060000000000000000000000000000000000000006121e2a35404b545a5d5d5d5d5d5952493e33281c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d1003000000000000000000131f2c3946525f6c7985929facac9f92857b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7063574a3d3124170a0013202c3946535f6c7986929facac9f9286796c5f5246392c1f130600000000000b1825313e4b5864717e8b98a4b1a69a8d8173675a4d4034271a0d0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000101d2936434f5c6975828f9ba8ada094877a7070707070707070707070707070707070707070707074818d9aa7ac9f9286796c6053463a2d2014070000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c201300000008111b252e38414b555e68727b858f98a2a199928a8890989fa3998f867c72685e544b41372d231a100600000000000000000000000b1824313e4b5764717e8b8f8f8f8f8d8173675a4d44505d6a77848f8f8f8f8f86796d6053463a2d201307000000000000000000000000000000000005101c28333e4952585c5c5c5c5c5c5e60626364646464636361605d5c5c5c5c5c5c5851483d32271b0f040000000000000000000c1825313e4b5764707d8996a2afa79b8e8275695c5044382b1f13080000010c1824303c4855616e7a8793a0acaa9d9184786b5f5246392c20130700000006111c27323d48525d67727c869099a3a49b91887e756c645b524a413930282424242424242424242424242424242423201b150e06000000000000000000000000000000000008141f2b37434f5a66727e8a95a1ada89c9084786c6155493d3125190e02000000000000000000000000000000000b17232f3b47535e6a76828e9aa6aea2968b7e73675b4f43382c2014080000000000000000000000000000000000000000000000000815222e3b4754606b73747474747474747470665a4e4235281c0f020000000000000000000000000000000000000000000000000000000000000000040c141c232a31373d43494d52565a5d606365666869696a6a696968676563615e5b57534f4a45403a342d261f1710070000000000000000000000000000000000000915222e3a46525d656a6a6a6a6a645b5044382c1f130600000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d100300000000000000000013202c3946535f6c7986939facaca0948a88888888888888888888888888888888888888888888888888888888888888887d7164574a3e3124170b0013202c3946535f6c798693a0acac9f9285786b5f5245382c1f120500000000000b1824313e4b5764717d8a97a4b1a79a8e8174675a4d4134271a0e0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c00000000000000000000000000000000000f1b2835414e5a6774818d99a6aea295887c6f63636363636363636363636363636363636363636976828f9ca8aa9d9184776b5e5145382c1f12060000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000000009131c262f39434c566069737c869099a3a49c95949aa2a59b91877d746a60564c42392f251b11080000000000000000000000000b1824313e4b5764717e8b989c9c9a8d8173675a4d44505d6a7784909c9c9c9386796d6053463a2d20130700000000000000000000000000000000000714202c3944505b636869696969696969665f57575757575f666969696969696968635a4f43372b1f12060000000000000000000e1a2733404d5966727f8c98a5b1a5988c7f73665a4d4134281c0f030000000714202d3945525e6b7884919daaaca093877a6d6154483b2e221508000000000b16212b36414b55606a747d87919ba4a39a91887e766d645c534b423a322a221a1818181818181818181818181816140f0a03000000000000000000000000000000000000030f1b26323e4a56616d7985919ca8ada195897d7165594e42362a1e120600000000000000000000000000000004101c28343f4b57636f7b87939eaaa99d92867a6e62564b3f33271b0f040000000000000000000000000000000000000000000000000916222f3c4955626f7c818181818181818176695c4f4336291c100300000000000000000000000000000000000000000000000000000000000000040d161e262e353c43494f54595e62666a6d6f717375757677777676757372706d6a67645f5b56514b453f3831292119110900000000000000000000000000000000000a1724303d4a56636e77777777766c6054473b2e21150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d100300000000000000000013202c3946535f6c798693a0acb1a69c96959595959595959595959595959595959595959595959595959595959595958a7d7164574a3e3124170b0013202c3946535f6c798693a0acac9f9285786b5f5245382c1f120500000000000b1724313e4a5764717d8a97a4b1a79a8e8174675a4d4134271a0e0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c00000000000000000000000000000000000d1926333f4c5865717e8b97a4b0a3978a7e71655856565656565656565656565656565656565f6b7885919eaaa79b8e8275695c5043362a1d11040000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c201300000000010a141d27313a444e57616b747e88919ba0a0a0a0a0a09d93897f756b62584e443a31271d1309000000000000000000000000000b1824313e4b5764717e8b98a4a79a8d8173675a4d44505d6a7784909da9a09386796d6053463a2d20130700000000000000000000000000000000000916222f3c4855616c757575757575757571665a4e4b4e5a667175757575757575746b6053473a2e2114080000000000000000000f1c2835424e5b6874818e9aa7b0a3968a7d7064574b3e3225190c0000000004111d2a3743505c6975828f9ca8aea295897c6f6356493d3023170a00000000040f1a242f39444e58626b757f89929ba5a39a91887f766e655d544c443c342c241c130b0b0b0b0b0b0b0b0b0b0b0a07030000000000000000000000000000000000000000000a16212d3945515d6874808c98a3afa5998e82766a5e52463b2f23170b0000000000000000000000000000000915202c3844505c6874808b97a3afa5998d8175695d52463a2e22160b000000000000000000000000000000000000000000000000000916222f3c4955626f7c898e8e8e8e8e8e8376695c4f4336291c1003000000000000000000000000000000000000000000000000000000000000040d161f2830383f474d545a60656a6e7276797c7e808182838484838282807e7c7a7773706b67625c565049423b332b231b1209000000000000000000000000000000000b1724313e4a5764717d8484847b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d100300000000000000000013202c3946535f6c798693a0acb7aea7a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2978a7d7064574a3e3124170b0013202c3946535f6c798693a0acac9f9285786b5f5245382c1f120500000000000b1824313e4b5764717d8a97a4b1a79a8e8174675a4d4134271a0e0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c00000000000000000000000000000000000b1724303d4956626f7b8894a1ada6998d8174685b4f4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a56626e7b8794a0ada5988c8073665a4d4134281b0f020000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000000000020b151f28323c454f59626c757f8992939393939393938b81776d635950463c32281f150b01000000000000000000000000000b1824313e4b5764717e8b98a4a79a8d8173675a4d44505d6a7784909daaa09386796d6053463a2d2013070000000000000000000000000000000000091623303c4956636f7c8282828282828275685b4f424f5b6875828282828282827b6e6155483b2e221508000000000000000000101d2a3743505d6976838f9ca9aea295887b6f6255493c3023160a00000000020f1b2835414e5b6774818d9aa7b0a3978a7d7164574b3e3125180b000000000008131d27323c46505a636d768089939ca5a39a918880776f665e564e463e362d251d150d04000000000000000000000000000000000000000000000000000000000000000005111d2834404c58636f7b87939faaaa9e92867a6f63574b3f33271c100400000000000000000000000000010d1925313d4955606c7884909ca8aca094887c7065594d4135291e1206000000000000000000000000000000000000000000000000000916222f3c4955626f7c89969a9a9a9a908376695c4f4336291c10030000000000000000000000000000000000000000000000000000000000030d161f28313a424a51585f656b71767a7e8285888b8c8e8f909090908f8e8d8b898683807c77726d68615b544d453d352d241b12080000000000000000000000000000000b1724313e4a5764717d8a91887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d1003000000000000000000131f2c3946525f6c7986929facb4aaa19b9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9da4aeafa3968a7d7063574a3d3024170a0013202c3946535f6c7986929facac9f9286796c5f5246392c1f130600000000000b1825323e4b5864717e8b98a4b1a69a8d8173675a4d4034271a0d0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c00000000000000000000000000000000000815212e3a4753606c7885919da9a99c9084776b5f53483d3d3d3d3d3d3d3d3d3d3d3d424d5966727e8a97a3aea195897c7064574b3e3225190c000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c2013000000000000030d16202a333d47505a636d7781868686868686868683786f655b51483e342a20160d0300000000000000000000000000000b1824313e4b5764717e8b98a0a09a8d8173675a4d44505d6a7784909da0a09386796d6053463a2d2013070000000000000000000000000000000000091623303c4956636f7c898f8f8f8f8f8275685b4f424f5b6875828f8f8f8f8f887b6e6155483b2e221508000000000000000000121e2b3844515e6b7784919daaada094877a6d6154473b2e21150800000000000d1a2733404d596673808c99a6b1a5988b7e7265594c3f3226190c0000000000010b16202a343e48515b646e77818a939ca5a39a928981787068605850483f372f271f160e0600000000000000000000000000000000000000000000000000000000000000000c18242f3b47535f6b76828e9aa6afa3978b7f73675c5044382c2014090909090909090909090909090909121e2a36414d5965717d8995a1aca79b8f83776c6054483c3025190d01000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2a7a79c908376695c4f4336291c100300000000000000000000000000000000000000000000000000000000010b151f28313a434c545c636a70767c82868b8e929597999b9c9d9d9d9d9c9b99989593908c88837e79736c665f574f473f362d241a100700000000000000000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d1003000000000000000000121f2c3845525f6b7885929eabafa3988f8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e929ca8afa296897c6f6356493c3023160900121f2c3845525f6b7885929eabaca09386796d6053463a2d20130700000000000c1925323f4c5865727e8b98a5b2a6998c807366594d4033261a0d0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c000000000000000000000000000000000006121f2b3744505c6975818d99a5aca094887c7064594d43383030303030303030323c47525e6a76828e9aa6aa9e9285796d6054483b2f23160a000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c201300000000000000040e18212b353e48515b656e7879797979797979797970675d53493f362c22180e040000000000000000000000000000000b1824313e4b5764717e8b939393938d8173675a4d44505d6a7784909393939386796d6053463a2d2013070000000000000000000000000000000000091623303c4956636f7c89969c9c9c8f8275685b4f424f5b6875828f9c9c9c95887b6e6155483b2e221508000000000000000000121f2c3845525f6b7885929eabaca09386796d6053463a2d20130700000000000c1925323f4c5865727e8b98a5b2a6998c807366594d4033261a0d000000000000040e18222c363f49525c656e78818a939ba4a49b938a827a726a625a51494139312820180f070000000000000000000000000000000000000000000000000000000000000007131f2b36424e5a66717d8995a1ada79c9084786c6054483d31251915151515151515151515151515151517222e3a46525e6a76828d99a5aea2968a7e73675b4f43382c20140800000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c10030000000000000000000000000000000000000000000000000000000009131d27313a434d555e666d747b82888d92979b9ea1a4a6a7a9a9a8a8a9a9a8a6a4a29f9c98948f8a847e777069615951483f362c22190e04000000000000000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d1003000000000000000000111e2b3844515e6a7784919daaada09387818181818181818181818181818181818181818181818181818c99a6aea194887b6e6155483b2f22150900121e2b3844515e6b7784919daaada094877a6d6154473b2e21150800000000000d1a2633404d596673808c99a6b2a5988c7e7265594c3f3226190c0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000030f1c2834404d5965717d8995a1aca4988c81756a5f544a4139322e2c2c2d2f343b434e58636f7a86929eaaa5998d8275695d5145382c201307000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000000000000000060f19232c363f49535c666c6c6c6c6c6c6c6c6c6c685e554b41372d241a1006000000000000000000000000000000000b1824313e4b5764717e8686868686868173675a4d44505d6a7784868686868686796d6053463a2d2013070000000000000000000000000000000000091623303c4956636f7c8996a3a89c8f8275685b4f424f5b6875828f9ca8a295887b6e6155483b2e22150800000000000000000013202c3946535f6c7986929facac9f9286796c5f5246392c1f130600000000000b1825323e4b5864717e8b98a4b1a69a8d8173675a4d4034271a0d0000000000000006101a242d37404a535c666f788189929aa3a59c948c847c746b635b534b433a322a21191108000000000000000000000000000000000000000000000000000000000000020e1a26323d4955616d7884909ca8aca094897d7165594d41352a222222222222222222222222222222222227333f4b57626e7a86929eaaa99d92867a6e62564a3f33271b0f0300000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c100300000000000000000000000000000000000000000000000000000006101b252f39434c565f6770777f868d93999ea3a7aaa6a3a09e9d9c9c9c9c9d9ea0a2a5a9a8a4a09b958f89827b736b635a51483e342a20160c010000000000000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d1003000000000000000000101d2a3643505c6976838f9ca9ada094877a7474747474747474747474747474747474747474747474808d9aa6aca093867a6d6054473a2e21140700111d2a3743505d6976838f9ca9aea295887b6f6255493c3023160a00000000010f1b2835414e5a6774818d9aa7b0a4978a7d7164574b3e3125180b0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000000c1824303d4955616d7884909ca7a99d92877b71665c534a433e3a3938393c3f454d565f6a75808c97a3aca095897d7165594d4135281c1004000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c201300000000000000000007111a242e37414a545b5f5f5f5f5f5f5f5f5f5f5c564d43392f251b120800000000000000000000000000000000000b1724313e4a57637079797979797979797266594d43505c697479797979797979766b5f5346392d2013060000000000000000000000000000000000091623303c4956636f7c8996a3a89c8f8275685b4f424f5b6875828f9ca8a295887b6e6155483b2e22150800000000000000000013202c3946535f6c798693a0acac9f9285786b5f5245382c1f120500000000000b1824313e4b5764717d8a97a4b1a79a8e8174675a4d4134271a0e000000000000000008121b252e38414a545d666e7780899199a2a69e968e867d756d655d554c443c332b231a11090000000000000000000000000000000000000000000000000000000000000915212d3944505c6874808b97a3afa5998d81756a5e52463a2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f38444f5b67737f8b97a3aea4998d8175695d52463a2e22160b0000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c10030000000000000000000000000000000000000000000000000000020d17222d37414b555e687179828a91989ea4aaa7a29d9a969492908f8f8f8f90929496999da1a6aba6a19a948d857d756c635a50463c32281d13080000000000000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000f1c2835424e5b6874818d9aa7aea195887b6f67676767676767676767676767676767676767676875828e9ba8aa9e9185786b5f5245392c1f1306000f1c2935424e5b6874818e9aa7b0a3968a7d7064574b3e3225190c0000000004111d2a36434f5c6975828f9ba8afa295897c6f6356493d3023170a0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000000814202c3844505c68737f8a96a1aca3988d82786e655c554f4a47464546484b50575f68717c86919da8a69b8f84786c6155493d3125190c00000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000000000000000000008121c252f38424a5052535353535353535353504b443b31271d13090000000000000000000000000000000000000916222f3b47535e676c6c6c6c6c6c6c6c6960554a404c58626a6c6c6c6c6c6c6c6b645a4f43372b1e12050000000000000000000000000000000000091623303c4956636f7c8996a0a09c8f8275685b4f424f5b6875828f9ca0a095887b6e6155483b2e22150800000000000000000013202c3946535f6c798693a0acac9f9285786b5f5245382c1f120500000000000b1724313e4a5764717d8a97a4b1a79a8e8174675a4d4134271a0e00000000000000000009131c262f38424b545c656e767f879098a0a8a0978f877f776f675e564e453d352c231b1209000000000000000000000000000000000000000000000000000000000005101c2834404b57636f7b87929eaaaa9e92867a6e62564b3f3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c4854606c78848f9ba7aba094887c7064594d4135291d12060000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000000000008131e29343e49535d67707a838b949ba3a9a8a29c96918d8a878584838282838485878a8d91959aa0a6aca59e978f877e756c62584e443a2f24190e0300000000000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000d1a2733404c5966727e8b98a4afa3968a7d70645a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5e6b7784909daaa89c8f8376695d5044372a1e1104000e1a2734404d5966737f8c98a5b1a5988c7f73665a4d4134281b0f030000000713202c3945525e6b7784919daaada094877a6e6154483b2f2215090013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c00000000000000000000000000000000000004101c2834404b57626e79848f9aa5a99f948a80776e67605a565452525354575c61687179838d98a3aaa0958a7e73675c5044382c20140800000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c201300000000000000000000000a131d2630383f434646464646464646464644403a32291f150b0100000000000000000000000000000000000007131f2b37424c555c5f5f5f5f5f5f5f5f5d574e443b4650595e5f5f5f5f5f5f5f5f5a52493e33271b0f020000000000000000000000000000000000091623303c4956636f7c89939393938f8275685b4f424f5b6875828f93939393887b6e6155483b2e22150800000000000000000013202c3946535f6c798693a0acac9f9285786b5f5245382c1f120500000000000b1824313e4b5764717d8a97a4b1a79a8e8174675a4d4134271a0e000000000000000000010a141d262f39424a535c646d757e868e969fa7a19991898178706860574f473e352d241b120900000000000000000000000000000000000000000000000000000000000c17232f3b47525e6a76828e99a5aea2978b7f73675b4f4848484848484848484848484848484848484848484d5965707c8894a0aca79b8f83776c6054483c3025190d010000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c100300000000000000000000000000000000000000000000000000030e1925303b45505b656f79838c959da5ada59e97908b86817d7b78777675757677787a7d8185898f959ca3aaa9a19990877e746a60564b41362b20150900000000000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000b1825313e4a5763707c8995a2aea5988c8073675a4e4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d55616d7a86939faca6998d8074675b4e4235281c0f03000c1825323e4b5764707d8996a2afa79b8e8275695c5044372b1f13080201020b17232f3b4854616d7a86939facaa9e9185786c5f5346392d2014070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c000000000000000000000000000000000000000c17232f3a46515d68737e89939da7a69c92898078716b6663605f5f5f6164686d737a838c959faaa3988e83786d62564b3f34281c100400000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000000000000000000000010b141e262d33373939393939393939393938342f2820170d0300000000000000000000000000000000000000030e1a25303a434b505353535353535353514c453c353e474e5253535353535353524f4940372c21160a000000000000000000000000000000000000091623303c4956636f7c8686868686868275685b4f424f5b6875828686868686867b6e6155483b2e22150800000000000000000013202c3946535f6c7986929facac9f9286796c5f5246392c1f130600000000000b1825323e4b5864717e8b98a4b1a69a8d8173675a4d4034271a0d00000000000000000000020b141d262f38414a525b636c747c858d959da5a39b938b827a7269615950473f362d241b12090000000000000000000000000000000000000000000000000000000007131e2a36424e5965717d8994a0aca79b8f84786c6055555555555555555555555555555555555555555555555d6975818d99a5aea2968a7e73675b4f43372c201408000000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c10030000000000000000000000000000000000000000000000000008141f2a36414c57626c77818b959ea7ada49b938c857f7a75716e6c6a696969696a6c6e7174797e848a9198a1a9aba29990867c72675d52473c31261b0f04000000000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000916222f3b4854616d7986929eaba89b8f83766a5e5246414141414141414141414141414c5864717d8996a2aea2968a7d7164584c3f33261a0d01000a16232f3c4855616e7a87939facaa9d9185786c6054483c302419110f0e0f121c27333f4b5764707c8995a2aea79b8f8276695d5044372b1e12050013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000000007121e2935404b56616c77818b959ea8a49b928a837c77726f6d6c6b6c6e7074787e858c959ea7a49b91877c72675c51453a2e23170b0000000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c2013000000000000000000000000020c141c22272b2c2c2c2c2c2c2c2c2c2c2b28231d160e0500000000000000000000000000000000000000000009141e2831394044464646464646464645413b332c353c42454646464646464646433e372e251b10050000000000000000000000000000000000000916232f3c4955626e787979797979797973675b4e424e5b677379797979797979776d6154483b2e211508000000000000000000121f2c3845525f6b7885929eabaca09386796c6053463a2d20130700000000000c1925323f4c5865727e8b98a5b2a6998c807366594d4033261a0d0000000000000000000000020b141d262f384049515a626a727a838b939ba3a59d948c847b736b6259514840372e241b1208000000000000000000000000000000000000000000000000000000020e1a25313d4955606c7884909ca7aca094887c70646262626262626262626262626262626262626262626262626e7a86929da9a99d91867a6e62564a3f33271b0f03000000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000000010d1925303c47525d68737e89939da7aea49b928a827a746e6965625f5d5c5c5c5c5d5f6164686d72787f878f97a0a9aba2988e84796f64594e42372c201409000000000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000713202c3845515d6a76828e9ba7ab9f92867a6e63574c40363434343434343434343a45515c6874818d99a5ab9f93877a6e6155493c3024170b00000714202d3946525e6b7783909ca8ada194887c7064584c41362b221e1c1b1c1e232d3844505b6774808c98a5b0a4988c7f73665a4e4135281c0f030013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c00000000000000000000000000000000000000010d18242f3a45505a656f79838c959ea6a49c958e88837e7b797878797a7c8084898f969ea7a39b92897f756a60554a3f34291d12060000000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c201300000000000000000000000000020a11171b1e202020202020202020201f1c18120c0400000000000000000000000000000000000000000000020c161f282f3438393939393939393938353029232b313639393939393939393937322c251c1309000000000000000000000000000000000000000814212d3a46525d666c6c6c6c6c6c6c6c6961574b3f4b5761696c6c6c6c6c6c6c6c665c5145382c201307000000000000000000121e2b3844515e6b7784919daaada094877a6d6154473b2e21150800000000000d1a2633404d596673808c99a6b2a5988c7e7265594c3f3226190c000000000000000000000000020b141d262e373f4850586069717981899199a1a69e968d857c746b635a524940372d241a11070000000000000000000000000000000000000000000000000000000915212c3844505c67737f8b97a2aea5998d81756f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f727e8a96a2aea4988d8175695d51463a2e22160a00000000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c100300000000000000000000000000000000000000000000000006121e2a35414d58636f7a85909aa5afa69c928980777069635d59555351504f4f50515255585c61676d757d858e97a1abaaa0968b80756a5f54483d3125190e020000000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d100300000000000000000004101d2935424e5a66727e8a96a2aea3978b7f73685d52483e352f2a2828292b3038414b56626d7985919da9a79b8f83766a5e5246392d211408000005111d2a36424f5b6773808c98a4b0a4988c8174695d52473d342e2a2828282a2e353f4955606c7884909ca8aca094887c6f63574b3e3225190d000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c000000000000000000000000000000000000000007121e29333e49535d67717a838c949ca3a69f99938f8b888685858687898c90959aa1a7a199918980766d63594e44392e23180c010000000000000d1a2633404d596673808d9aa6ada09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c2013000000000000000000000000000000060b0f121313131313131313131312100c0701000000000000000000000000000000000000000000000000040d161d23282b2c2c2c2c2c2c2c2c2c29241e1920262a2c2c2c2c2c2c2c2c2c2a27211b130a010000000000000000000000000000000000000005111d2935404b545c5f5f5f5f5f5f5f5f5e584f453a454f585e5f5f5f5f5f5f5f5f5b544a3f34281c1004000000000000000000111d2a3743505d6976838f9ca9aea195887b6f6255493c2f23160a00000000010f1b2834414e5a6774818d9aa7b0a4978a7d7164574b3e3125180b00000000000000000000000000020b141c252d363e464e575f676f777f878f979fa79f978f867e756c645b52493f362c23190f05000000000000000000000000000000000000000000000000000004101c28333f4b57636e7a86929ea9a99d91867b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b838f9ba7aba094887c7064594d4135291d120600000000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c10030000000000000000000000000000000000000000000000000a16222e3a46525e6975808b96a1acaa9f958a81776e665e57524d494644434242434446484c50565c636b737c858f99a4afa79d92877b7065594d42362a1e12060000000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d1003000000000000000000010d1925323e4a56626e7a86929da9a79c9085796e645a5047403a37353435383c424a535d68737e8a95a1ada2968a7e72665a4e42362a1d11050000010e1a26333f4b57636f7b87939faba99d91857a6e64594f463f3a37353435373a3f47515b66717d8994a0aca89c9084786c6053473b2f22160a000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000000000010c17222c37414b555f68717a828a91989ea3a49f9b9795939292929496989ca0a6a19c968f8780776e645b51473c32271c1106000000000000000d1a2633404d596673808d9aa1a1a09386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040b12181c1f20202020202020201f1c19130e151a1d1f202020202020201f1e1b161009010000000000000000000000000000000000000000010d19242f39424a505353535353535353514d463d333d464d5153535353535353524f4a42382e23180c000000000000000000000f1c2935424f5b6874818e9aa7b0a3968a7d7064574b3e3225180c0000000004111d2a36434f5c6975828f9ba8afa295897c6f63564a3d3023170a0000000000000000000000000000020a131b242c343d454d555d656d757d858d959da6a19890877e756d645b51483e352b21170d0200000000000000000000000000000000000000000000000000000b17232f3a46525e6a75818d99a5aea2968c8888888888888888888888888888888888888888888888888888888a949faba79b8f83776b6054483c3024190d0100000000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c10030000000000000000000000000000000000000000000000020e1a26333f4b57626e7a86919da8afa4998e83786e655c544c46413d3a383636363637393c40454a5159616a737d88929da8aea3988d81766a5e52463a2e22160a0000000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d1003000000000000000000000916222e3a46525d6975818c98a3aca1968b80766c6259514b464342414244474d535c656f79848f9ba6a89d91867a6e62564a3e32261a0e010000000a17232f3b47535f6b77838e9aa5ada2968b80756b6158504a464342414243464b5159636d77838e99a5aea3978b8074685c4f43372b1f1306000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c00000000000000000000000000000000000000000006101b252f3a434d565f68707880868c92979b9fa2a4a1a09f9f9fa0a2a4a19e9a96918b847d756d655c53493f352b20160b00000000000000000d1a2633404d596673808d949494949386796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c2013000000000001070b0e0f0f0f0f0f0f0f0f0f0e0b060104090c0f0f0f0f0f0f0f0f0f0e0c09040000000000000000000000000000000000000000000001070c1012131313131313131312100d0803090e11131313131313131313110e0a05000000000000000000000000000000000000000000000007121d2730383f44464646464646464645413c342b343c41454646464646464646433f382f261c1106000000000000000000000e1a2734404d5966737f8c98a5b1a5988c7f7266594d4134281b0f030000000713202c3845525e6b7784909daaada094877a6e6154483b2f2215090000000000000000000000000000000109121a222b333b434b535b636b737b838b949da5a29990887f766d635a50473d33291e140a000000000000000000000000000000000000000000000000000006121e2a36414d5965717c8894a0aca89e97959595959595959595959595959595959595959595959595959595969ca5aea2968a7e73675b4f43372b2014080000000000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c1003000000000000000000000000000000000000000000000005111e2a36434f5b67737f8b97a2aeaa9e93877c71675c534a423b35302d2b2a2929292b2d3034393f474f58616b76818c97a2aea99e92867a6f63574b3e32261a0e0100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000005111d2935414d5964707b86919ca7a79d92887e746b635c5752504e4e4f5154585e656e77818b96a1aca2978c8075695d52463a2e22160a0000000007131f2b37434f5a66727d89949faaa89c92877d736a625b5652504e4e4e5052565c636b747e89949faaa89d91867a6f63574b3f33271b0f03000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000000000000009131e28313b444d565e666e757b81868b8f929598999a9b9b9b9a999795928e8a858079736b645b534a41372d23190f040000000000000008121b2633404d5966738088888888888886796d6053463a2d2013070000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c201300000000060d12171a1c1c1c1c1c1c1c1c1c1a17120c0f15191b1c1c1c1c1c1c1c1c1b19140f09010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010b151e272e333739393939393939393835302a222a303538393939393939393937332d261d140a00000000000000000000000c1825323e4b5764707d8996a2afa79b8e8275695c5044372b1f13080201020b17232f3b4854616d7986939facaa9e9185786c5f5346392d2014070000000000000000000000000000000000081019212931394149515961697179828a939ca5a29a91887f756c62594f453b30261b110600000000000000000000000000000000000000000000000000010d1925313d4854606c78838f9ba7b0a8a3a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a6aea99d91857a6e62564a3e33271b0f030000000000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c100300000000000000000000000000000000000000000000000815212d3a46525f6b77838f9ba7b1a5998d82766b60554b4138302a24211e1d1c1c1d1e2024282e353d464f5a646f7a86919da9afa3978b7f73675b4e42362a1d110500000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d100300000000000000000000010d1925303c48535e6a75808b95a0aaa49990867d756e68625f5c5b5b5b5d60646970778089939da7a59b90857a6f63584c4135291d120600000000030e1a26323e4a55616c77828d98a2aca3998f857c746d67625f5c5b5b5b5c5f62676d757d87909ba5aba1968b8075695e52463b2f23170b00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c00000000000000000000000000000000000000000000020c161f29323b444c545c636a70757a7f8386898b8c8e8e8e8e8d8c8a8885827e79746e686159524941382f251b110700000000000000040f1a242d35404c5966727b7b7b7b7b7b7b7b786c5f5346392d2013060000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130000000710171e232729292929292929292927231e171a20252829292929292929292825201a130b020000000000000000000000000000000000000000000000000000000508090a0a0a0a0a0a0a0a090805010000000000000000000000000000000000000000000000000000000000000000000000030c151c23282b2c2c2c2c2c2c2c2c2c29251f181f25292c2c2c2c2c2c2c2c2c2b27221c140b0200000000000000000000000a16232f3c4855616e7a87939facaa9d9185786c6054473b302419110f0e0f111b27333f4b5764707c8995a2aea89b8f8276695d5044372b1e1205000000000000000000000000000000000000070f171f272f373f474f575f677078818a939ca5a39a91887e746b61574c42382d22170c01000000000000000000000000000000000000000000000000000814202c38434f5b67737e8a96a2aeb3afaaa3a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a2a8afb2b0a4988d8175695d51463a2e22160a000000000000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c100300000000000000000000000000000000000000000000000b1724303d4956626e7b87939facada195897d7165594e43392f261e191412100f0f101114181d232b343e48535e6975818c98a4b0a79b8f83776a5e5245392d20140700000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d100300000000000000000000000814202b37424d58636e79848e98a1aaa29890878079736e6b696867686a6c70757a8189929ba5a79d93897e74695e52473c3024190d0100000000000a16212d39444f5b66717c86909aa4aba1978e867e78736e6b69686768696b6e73787f879099a2aca3998f847a6f63584d41362a1e120700000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000000000000000040d17202a333b424a51585f656a6f73777a7c7e808181828181807e7b7976726d68635d564f48423c342a20160b00000000000000000915202b363f474d56616a6e6e6e6e6e6e6e6e6d665b5044372b1e12050000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c2013000006101922292f33353636363636363635332f2921252c3134363636363636363634312c251d140b00000000000000000000000000000000000000000000000000060c11141617171717171717171614110c070000000000000000000000000000000000000000000000000000000000000000000000030a11171b1e20202020202020201f1d19140e14191d1f20202020202020201e1b17110a020000000000000000000000000714202d3946525e6b7783909ca8ada194887c7064584c41352b221d1b1a1b1d232d38444f5b6773808c98a5b0a4988c8073675a4e4135281c0f0300000000000000000000000000000000000000050d151d252d353d454d555e666f78818a939ca6a39a90877c73685e54493f34291e130700000000000000000000000000000000000000000000000000040f1b27333f4a56626e7a86919da9b5aca1989494949494949494949494949494949494949494949494969ea9b4aba094887c7064584d4135291d1106000000000000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c100300000000000000000000000000000000000000000000000d1a26333f4c5865717e8a97a3afaa9d9185786c6054493d32271d140d08050300000205080c1219222c36414d5864707c8894a0adab9f93877a6e6155483c2f23160a00000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000000030f1a25313c47525d67727c868f98a1a9a199918a847f7b787574747576797c80868c939ba4a69e958b81776d62574c41362a1f140800000000000005111c28333e49545f6a747e89929ba4a9a0989089837e7a787675747576787b7e848a9199a2aba39a91877d73685d52473c3025190e0200000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c0000000000000000000000000000000000000000000000030f1b26313c454d53555555595e63676a6d707273747475747473716f6c6966615d57555555534d463c32271c1004000000000000000e1a26323d4751595d5e5f6161616161616161605c544a3f33271b0f030000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c201300030e18222c343a3f4242424242424242423f3a332b2f373d414242424242424242413d372f261c120700000000000000000000000000000000000000000000010a11181d2123232323232323232323211d18110a020000000000000000000000000000000000000000000000000000000000000000000000060b0f12131313131313131312100d0803080d10121313131313131313120f0b06000000000000000000000000000005111d2a36424f5b6774808c98a4b0a4988c8074695d52473d342d2a2827282a2e353f4954606c7884909ca8aca094887c7063574b3e3226190d000000000000000000000000000000000000000000030b131b232b333b434c545d666e77818a949da7a2988f857a70655b50453a2f24190d02000000000000000000000000000000000000000000000000000b16222e3a46515d6975818d98a4b0a79b8f87878787878787878787878787878787878787878787878c98a4b1a79b8f83776b5f54483c3024190d01000000000000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c100300000000000000000000000000000000000000000000000f1b2835414e5b6774818d99a6b2a79a8e8175695c5044382c20150b0200000000000000000007101a25303c4854606c7884919daaafa296897d7064574b3e3225180c00000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000000000914202b36404b55606a747d868f979fa6a39c95908b8784828181828385888c91979ea5a49c948c83796f655b50463b3025190e03000000000000000b16222d38434e58626d768089929aa1a8a29b948f8a8784828281828284878b8f959ba3a8a19991887f756b61564c41362b1f14080000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c00000000000000000000000000000000000000000000000714202c38434e575e6262626262615c5e616365666768686767666462605d5c6162626262625f584e44382d20140800000000000000111d2a36424e59636a6b6b6b6b69635b54545454504a42382d22170b000000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c20130009141f2a343e454b4f4f4f4f4f4f4f4f4f4b453d343841484d4f4f4f4f4f4f4f4f4d4841382e24190d020000000000000000000000000000000000000000010a131b23292d2f3030303030303030302d29231c140b01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020e1a27333f4b57636f7b88939faba89d91857a6e63594f463f3936353435363a3f47505b66717c8894a0aca89c9084786c6054473b2f22160a00000000000000000000000000000000000000000000010911192129313a424b545c656e78828b95a0aaa0968c82776c62574c40352a1e13070000000000000000000000000000000000000000000000000006121d2935414d5864707c88949faba79b8e827a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7f8b97a4aea2968a7e72675b4f43372b20140800000000000000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c10030000000000000000000000000000000000000000000000101d2a3643505c6976828f9ca8b1a4988b7e7266594d4034281c1004000000000000000000000008141f2b3744505c6875828e9aa7b1a5988c7f7366594d4033271a0e00000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000010507101c2936434f5c69768390908376695c4f4336291c1007050100000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d1003000000000000000000000000030e19242f39444e58626b747d858d949ba1a6a19b9793918f8e8e8e909295989da2a59f99928b837a71675d53493f34291e1308000000000000000005101b26313c46515b646e77808890979da3a6a09b9793918f8e8e8e8f9193979ba0a6a39d968f877f766d63594f453a2f24190e030000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01070b1723303d4a5663707d8a96a3aea3968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3226190c0a0a0a0a0a0a0a0a0906020000000000000000000000000a16232f3c48545f696e6f6f6f6f6d675f5856585a5a5b5b5b5a595856575f666d6f6f6f6f6f6a6055493d3024170b00000000000000131f2c3945525e6b7577777777756d645c544c47443f382f261c1106000000000000000000000000000000000000000000000000000c1926323f4c5965727f8c9386796c5f5346392c2013000d1925313c4650575b5c5c5c5c5c5c5c5b574f463b404a53595c5c5c5c5c5c5c5c59534a40352a1e1206000000000000000000000000000000000000000008121c252d34393c3d3d3d3d3d3d3d3d3c39342e261d130900000000000000000000000000000000000000000000000000000000000000000104070a0c0e0f111212131313131212100f0d0b0906030000000000000000000000000000000000000000000000000000000b17232f3b47535f6b77838e9aa5ada2968b80756b6158504a464341414143464a5159626c77828e99a5aea3978b8074685c5044372b1f1307000000000000000000000001020304050708090908050100070f171f283039424a535c666f79848e98a3a89e94897e73685d52463b2f24180c00000000000000000000000000000000000000000000000000010d1924303c48545f6b77838f9ba6ab9f93877b6f6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d7884909ca8a99d9185796e62564a3e33271b0f0300000000000000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c10030000000000000000000000000000000000000000000000121e2b3844515e6a7784919daaafa396897d7063574a3e3125180c000000000000000000000000030f1b2834404d5966727f8c98a5b1a79a8e8174685b4e4235281c0f00000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000070d1114161c2936434f5c69768390908376695c4f4336291c1614110d07000000000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000000000008121d28323c465059626b737b838a90969b9fa3a3a09d9c9b9b9b9c9ea1a4a29e99948e88817970685f554c42372d22180d020000000000000000000a15202a353f49525c656e767e858c92979ca0a3a3a09d9c9b9b9b9c9da0a3a3a09c97928c857d756d645b51473d33281e1308000000000013202c3946535f6c798693a0a1a19a8e8174675a4d4134271a0e0c12171b23303d4a5663707d8a96a1a1a1968a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f32261917171717171717171715120e0801000000000000000000000b1824313e4b5764707b7b7b7b7b787169625a534d4e4e4e4e4d4d5159616971787b7b7b7b7b7165584b3f3225180c0000000000000013202c3946535f6c79848484847e766e665e554d453d352c241c140c03000000000000000000000000000206090a0a0a0a0a0a0a0a0c1926323f4c5965727f8c9386796c5f5346392c201300111d2936424d586268696969696969696761574c4147525c656969696969696969655c52463a2e22160900000000000000000000000000000000000000030f1a242e373f45494a4a4a4a4a4a4a4a49453f382f251a0f040000000000000000000000000000000000000000000000000000000001060a0d111416191a1c1d1e1f1f20201f1f1e1d1c1a1815130f0c080400000000000000000000000000000000000000000000000007131f2b37434f5a66727d89949faaa79c91877c736a625b56524f4e4d4e4f52565c636b747e89949faaa89d92867a6f63574b3f33271b0f030000000000000002070a0c0d0f1011121315161614110d0701050e161e272f38414a545e67727c86919ca7a59b9085796e63574c4034281d1105000000000000000000000000000000000000000000000000000814202b37434f5b66727e8a96a2ada3978c80746860606060606060606060606060606065717d8994a0aca4988c8175695d51453a2e22160a0000000000000000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8996a2afa99c908376695c4f4336291c10030000000000000000000000000000000000000000000000121f2c3945525f6b7885929eabaea195887b6e6255483c2f221609000000000000000000000000000c1825313e4b5764717d8a97a3b0a89c8f8276695c4f4336291d1000000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000030b12181d2022222936434f5c69768390908376695c4f4336292222201d18120b0300000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d100300000000000000000000000000010b16202a343e475059616971787e858a8f9396999b9d9e9f9f9f9e9d9b9895928e89837d766e675e564d433a30261b110600000000000000000000030e18232d37404a535c646c737a81878c9094979a9c9d9e9f9f9f9e9d9b999794908b86817a736b635b52493f362b21170c01000000000013202c3946535f6c798693949494948e8174675a4d4134271a0f171e23282a303d4a5663707d8a94949494948a7d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f322624242424242424242423221e19130c040000000000000000000b1824313e4b5764717e88888888837b746c655d564e4742444c545c636b737b83888888887e7265584c3f3225190c00000000000000131f2c3946525f6b76818b919189807870675f574f473e362e261e150d050000000000000000000001080e12151717171717171717171926323f4c5965727f8c9386796c5f5346392c201300121f2c3845525e6a737575757575757573695d51444b57636e75757575757575756e63574a3e3124180b000000000000000000000000000000000000000814202b3640495155565656565656565655514a41372c211509000000000000000000000000000000000000000000000000000002080d12161a1d20232527292a2b2c2c2c2c2c2c2b2a282724221f1c18140f0b0500000000000000000000000000000000000000000000030f1b26323e4a55616c77838d98a3ada3998e857c746c66625e5c5b5a5b5c5e62676d747d86909ba5aba1968b8075695e52473b2f23170b00000000000001080e1317191a1b1d1e1f20212222211d19130b03040c151d262f38424c56606a75808a96a1aca1968b8074685c5145392d21150800000000000000000000000000000000000000000000000000030f1b27323e4a56626d7985919da9a89c9084786c61555353535353535353535353535e6975818d99a5ab9f94887c7064584c4135291d11060000000000000000000000000000000000000000000000000000000000000000010c16222f3c4955626f7c8996a2afa99c908376695c4f4336291c1107000000000000000000000000000000000000000000000013202c3946525f6c7986929facada094877a6d6154473a2e211408000000000000000000000000000a1623303c4956626f7c8995a2afaa9d9083776a5d5044372a1d1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000020c151d24292d2f2f2f36434f5c69768390908376695c4f43362f2f2f2d29241d150c02000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000000000000040e18222c353e474f575f666d73797e83878a8d8f909292929291908e8c8986827d78726b645d554c433a31281e140900000000000000000000000007111b252e38414a525a62696f757b8084888b8d8f909292929291908f8d8a8784807a756f68615a514940372d241a0f0500000000000013202c3946535f6c79868888888888888174675a4d4134271a1821282f3437383d4a5663707d888888888888887d7063564a3d3023170a0013202c3946535f6c7986938c7f7265594c3f3230303030303030303030302e2a251e160d0300000000000000000a1724303d4a56626d77818a94958d867e776f686059514a4e565e666d757d858d94958b82786e63574a3e3125180b00000000000000111e2a37434f5a646f79838d97928a8279716961595048403830271f170f060000000000000000040c13191e222324242424242424242426323f4c5965727f8c9386796c5f5346392c20130013202c3946535f6c7982828282828282786b5f52454c5865727e8282828282827e7165584b3e3225180b000000000000000000000000000000000000000c1825313c48525b616363636363636363625c53483d3125190d01000000000000000000000000000000000000000000000001070e13191d2226292d2f323435373838393939393838363533312e2b2824201b16110b040000000000000000000000000000000000000000000a16222d3944505b66717c86919ba4aaa0978e867e77726e6b69676767696b6e72787f878f98a2aca3998f857a6f64584d42362a1e13070000000000020b13191f23262728292a2c2d2e2f2f2d29241d150d03030b141d26303a444e58636e7984909ba7a79c9085796d6155493d3125180c00000000000000000000000000000000000000000000000000000a16222e3945515d6974808c98a4ada195897d7165594d4747474747474747474a56626e7a86929eaaa69b8f83776b5f54483c3024180d01000000000000000000000000000000000000000000000000000000000000000008131d28333d4955626f7c8996a2afa99c908376695c4f43382e23180e030000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053473a2d201407000000000000000000000000000915222f3b4855626e7b8895a2aeaa9d9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000000a141e272e35393c3c3c3c434f5c69768390908376695c4f433c3c3c3c39352e271e140a000000000000000000000f1c2936424f5c6975828f908376695d5043362a1d100300000000000000000000000000000006101a232c353d454d555c62686d72777a7d80828485858685848382807d7976716c66605a524b433a31281f160c020000000000000000000000000009131c262f38404850575e646a6f74787b7e81828485858685858482817e7b77736f69645e574f483f372e251b12080000000000000013202c3946525f6c777b7b7b7b7b7b7b7b73665a4d4134271a222a333a404344444956636f7a7b7b7b7b7b7b7b7a6f6356493d3023160a0013202c3946535f6c7986938c7f7265594c3f3d3d3d3d3d3d3d3d3d3d3d3d3a362f281f150b00000000000000000915212e3a46515c656f78828c959790898179726a635b54586068707780878f97978d837970665c52463b2e221609000000000000000e1a26323e48535d67717b86909a948b837b736b625a524a4139312921181008000000000000030d161e252a2e3030303030303030303030323f4c5965727f8c9386796c5f5346392c20130013202c3946535f6c79868f8f8f8f8f85786b5f52454c5865727e8c8f8f8f8f8b7e7165584b3e3225180b000000000000000000000000000000000000000f1b2834414d59646d70707070707070706d655a4e4235291c0f0300000000000000000000000000000000000000000000040c12191f24292e3236393c3e40424345454646464645444342403d3b3834302c27221c160f08010000000000000000000000000000000000000005111c28333e4a555f6a747f89929ba4a9a0989089837e7a777574747475777a7e848a9199a1aaa39b91887d73685d52473c3025190e0200000000010b141d242b2f323435363738393b3c3c39352f271f150b00020b141e28323c47515c68737f8b97a3ada1958a7d7165594d4134281b0f030000000000000000000000000000000000000000000000000005111d2935404c5864707b87939faba5998e82766a5e52463a3a3a3a3a3a3a434f5b67737e8a96a2aea2968a7e72665b4f43372b1f14080000000000000000000000000000000000000000000000000000000000000000040f1a242f3a444f5a646f7c8996a2afa99c9083766a5f554a3f352a1f150a0000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000006111c263039404548494949494f5c69768390908376695c4f494949494845403930261c11060000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000000000000000008111a232b343b434a51575d62666a6e717475777878797878777573706d6965605b554f48413931281f160d040000000000000000000000000000010a141d262e363e454c53595e63686b6f727476777878797878777574716e6b67635e58524c453e362d251c13090000000000000000111e2b37434f5b656d6e6e6e6e6e6e6e6e6a61564a3e3225242c343c444b50515151535e686e6e6e6e6e6e6e6e6e685e53473a2e2215080013202c3946535f6c7986938c7f7265594c4a4a4a4a4a4a4a4a4a4a4a4a4a47413a31271d12060000000000000005111d29353f4a535d66707a838d979a938b847c756d665e626a727a82899199998f857b71675e544a40352a1e1206000000000000000a16212c37414b555f69747e88929c958d857c746c645c534b433b332a221a120a01000000000b151f282f363a3d3d3d3d3d3d3d3d3d3d3d3d3f4c5965727f8c9386796c5f5346392c20130013202c3946535f6c7986939c9c9c9285786b5f52454c5865727e8c989c9c988b7e7165584b3e3225180b00000000000000000000000000000000000000101c2936434f5c69757d7d7d7d7d7d7d7d766a5d5043372a1d1004000000000000000000000000000000000000000000070f161d242a30353a3e4245484b4d4f505152525353525251504e4c4a4744403c38332d27211a130b03000000000000000000000000000000000000000b17222d38434e58636d778089929aa2a9a29a948f8a8784828181818284878a8f959ba2a8a19a91897f756b61574c41362b1f1409000000000009131d262f363b3f40414344454647484846403931271d120700020c16202a35404b57626e7a87939faca69a8e8275695c5044372b1e120500000000000000000000000000000000000000000000000000000c1824303c47535f6b77828e9aa6aa9e92867a6e63574b3f332d2d2d303c4854606b77838f9ba7a99d9185796e62564a3e32271b0f0300000000000000000000000000000000000000000000000000000000000000010b16212b36414b56616b76818b97a3b0aa9d91867b71665c51463c31261c110600000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000b17222e38424b515555555555555c69768390908376695c555555555555514b42382e22170b0000000000000000000f1c2936424f5c6975828f908376695d5043362a1d10030000000000000000000000000000000000081119222a31383f464c51565a5e626567696a6b6c6c6b6b6a686664615d59554f4a443d362f271f160d0400000000000000000000000000000000020b141c242c343b41484d53575c5f626567696a6b6c6c6b6b6a696765625f5b57524d47413a332c241c130a0100000000000000000f1b27333e49535b6061616161616161615f584f453a2e252d363e464e565c5e5e5e5e5e5d6161616161616161615d564c42362a1e12060013202c3946535f6c7986938c7f7265595757575757575757575757575756524c43392e23170b00000000000000010d18232e38414b545e68717b858e989d968e877f7770686c747c848c949b9a90877d73695f564c42382e24190d020000000000000005101a252f39434d58626c76808b959f978f867e766e655d554d453c342c241b130a01000006121d27313a41474a4a4a4a4a4a4a4a4a4a4a4a4a4c5965727f8c9386796c5f5346392c20130013202c3946535f6c798693a0a99f9285786b5f52454c5865727e8c98a5a5988b7e7165584b3e3225180b00000000000000000000000000000000000000101c2936434f5c6976838a8a8a8a8a8a84776a5d5044372a1d1104000000000000000000000000000000000000000008101920282f353b41464a4e5255575a5b5d5e5f5f5f5f5f5f5e5d5b595654504c48433e38322c251d150d0500000000000000000000000000000000000005111c27313c47515b656e77808890979ea3a59f9a9693908f8e8e8e8f9193969ba0a6a39d97908880766d645a4f453a2f25190e0300000000030f1a252f3841474b4d4e4f505253545555524b43392e23180c0000040e19242f3a46525e6b7784909da9aa9d9185786c5f5346392d201407000000000000000000000000000000000000000000000000000008131f2b37434e5a66727d8995a1ada3978b7f73675b4f44382c202935404c5864707c8894a0aba4988c8175695d5145392e22160a000000000000000000000000000000000000000000000000000000000000000008121d28323d48525d68727d88929da8b3aea3988d83786d63584d43382d23180d03000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000f1b27333f4a545c616262626262626976839090837669626262626262615c544a3f33271b0f000000000000000109121c2936424f5c6975828f908376695d5043362a1d120a0100000000000000000000000000000000000710181f272e343a40454a4e5255585a5c5e5e5f5f5f646a6b6b6b6b6962584d4139322c241d150d04000000000000000000000000000000000000020a121a222930363c42474b4f5356595b5c5e5e5f5f5f63696b6b6b6b6a63594e423c363029211a120a010000000000000000000b16222d38414a50545454545454545454534e463d33282f373f48505860686b6b6b6b6a665c5454545454545454514c443a30251a0e020013202c3946535f6c7986938c7f72656363636363636363636363636363635d554b3f34281c0f000000000000000007111c262f39424c565f69737c869099a0989189827a73777e868e969e9c92887e756b61574d443a30261c120700000000000000000009131d27313c46505a646e78838d97a198908880776f675f574e463e362d251c130800000b17232e39434c5256575757575757575757575757575965727f8c9386796c5f5346392c20130013202c3946535f6c798693a0ac9f9285786b5f52454c5865727e8c98a5a5988b7e7165584b3e3225180b00000000000000000000000000000000000000101c2936434f5c69768390969696969084776a5d5044372a1d11040000000000000000000000000000000000000008111a222b323940474c52565a5e61646668696b6b6c6c6c6c6b6b69686563605c59544f4a443d362f271f170e050000000000000000000000000000000000000a15202a353f49535c656e767e868c92989ca1a4a29f9d9b9a9a9b9b9d9fa3a3a09c97928c857e766d645b52483e33291e130800000000000814202b37414b52585a5b5c5d5e5f6162625d554b4034281c1004000007121e2a36424f5b6875818e9ba7ada094877a6e6154483b2e2215080000000000000000000000000000000000000000000000000000030e1a26323e4a55616d7985909ca8a79b9084786c6054483c30252d3945515d6975818c98a4ab9f93887c7064584c4135291d110500000000000000000000000000000000000000000000000000000000000000040f19242f39444f59646f79848f99a4afb2b2aa9f948a7f746a5f544a3f342a1f140a000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000121e2b3744505b666e6f6f6f6f6f6f6f7683909083766f6f6f6f6f6f6f6e665b5044372b1e12000000000000010a131b242c36424f5c6975828f908376695d5043362d241c130b020000000000000000000000000000000000060e151c23292f353a3e4246494c4e505152555d656e767777777774695d5044372a211a130b030000000000000000000000000000000000000000000810171e252b31363b3f43474a4c4e505152545c646d7577777777756b5e5245392c251e171008000000000000000000000005111b262f383f4447484848484848484846423c342b31394149515a626a7277777777776e62564948484848484745413a32281e1409000013202c3946535f6c7986938c7f727070707070707070707070707070706f675c5044382b1e120000000000000000000a141d27313a444d57616a747e87919ba39b948c857d81899098a09e948a80766c63594f453b32281e140a00000000000000000000010b15202a343e48525c67717b858f9aa29a928981797168605850483f372e241a0f04000f1c28343f4b555d63636363636363636363636363636365727f8c9386796c5f5346392c20130013202c3946535f6c798693a0a09f9285786b5f52454c5865727e8c98a0a0988b7e7165584b3e3225180b00000000000000000000000000000000000000101c2936434f5c697683909ca3a39d9084776a5d5044372a1d110400000000000000000000000000000000000007101a232c343c444b52585d62666a6e7073757677787979797978777674726f6c6965605b554f484139312920170d030000000000000000000000000000000000040e19232d37414a535c646c747b81878c9194989a9c9e9f9fa09f9e9d9c9a9794908c87817a736c645b524940362c21170c0200000000000c1824303c48535d646667696a6b6c6d6f6e675c5145382c1f13060000020e1a2734404d5a6773808d9aa6afa295897c6f6256493c302316090000000000000000000000000000000000000000000000000000000a16212d3945505c6874808c97a3aca094887c7065594d413529323e4a56626d7985919da9a69b8f83776b5f53483c3024180c01000000000000000000000000000000000000000000000000000000000000000b16202b36404b56606b75808b96a0aba9a5a6aaa69b91867b71665b51463b31261b11060000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c787c7c7c7c7c7c7c7c839090837c7c7c7c7c7c7c7c786c5f5346392c20130000000000020b131c252d363e47505c6975828f908376695d50483f362e251d140b030000000000000000000000000000000000030a11181e24292e3236393d3f41464e575f676f778084848484776b5e5144382b1e1108010000000000000000000000000000000000000000000000060d141a20252a2f33373a3d4042454d555e666e767e84848484796c5f5346392c20130c05000000000000000000000000000a141d262d34383a3b3b3b3b3b3b3b3b3a37312b323a424b535b636c747c848484847d7063574a3d3b3b3b3b3b39352f2820160c02000013202c3946535f6c7986938c7f7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d786c5f5346392c2013000000000000000000020b151e28323b454f58626c757f89929ca59e968f888b939aa29f968c82786e645b51473d332a20160c020000000000000000000000030e18222c36414b555f69737d88929ca49b938b837a726a625a514940362c20150900121e2b3844505c676f707070707070707070707070707070727f8c9386796c5f5346392c20130013202c3946535f6c7986939393939285786b5f52454c5865727e8c939393938b7e7165584b3e3225180b00000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d11040000000000000000000000000000000000040f19222c353e464e565d63696e73777a7d808183848586868686858483817e7c7975716c66605a534b433b32291f150b01000000000000000000000000000000000007111b252f38414a525a626970767b8084888b8e8f919292939292918f8d8b8884807b756f69615a524940372e241a10050000000000000e1a2734404d59646f7374757778797a7b796d6054473a2e2115080000000d192633404c596673808c99a6b0a396897c7063564a3d3023170a00000000000000000000000000000000000000000000000000000005111c2834404c58636f7b87939eaaa5998d8175695d51463a2e37434e5a66727e8a96a2ada2968a7e72665b4f43372b1f14080000000000000000000000000000000000000000000000000000000000000007121d27323d47525d67727d87929da7a69e9899a0a9a2988d82786d62584d42382d23180d0300000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c798689898989898989899292898989898989898986796c5f5346392c201300000000030c141d252e373f485059626a75828f9083766b625a514840372f261d150c03000000000000000000000000000000000000060d13181d22262a2f373f4850586069717981899191897f756a5d5144372b1e11040000000000000000000000000000000000000000000000000002090f141a1f23272b2e363e474f575f677078808991918b81766b5f5246392c1f13060000000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2d2a2b343c444c545d656d757e868e918e84796f63564a3d302e2e2e2e2d29241e160e0400000013202c3946535f6c798693908a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a86796c5f5346392c201300000000000000000000030d162029333d46505a636d76808a949da7a19994969da5a1978d847a70665c52493f352b21180e040000000000000000000000000006101a242f39434d57616c76808a949fa59d958c847c746b635b52483d3125190d0013202c3946535f6c787d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7f8c9386796c5f5346392c20130013202c3946535f6c7986868686868685786b5f52454c5865727e8686868686867e7165584b3e3225180b00000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000000000000000000010c16202b343e47505860676e747a7e8386898c8e9091929293939292918f8d8b8885817c77726b645d554d443b31271d130800000000000000000000000000000000000009131d262f38404950575e656a6f74787c7e81838485868686858483817e7b78746f6a645e57504840372e251c1208000000000000000f1b2835424e5b687580818283858687887b6f6256493d312519100b090a0e1a2734404d5a6673808d9aa6b0a396897c6f6356493c3023160a000000000000000000000000000000000000000000000000000000000c18232f3b47535e6a76828e9aa5a99d92867a6e62564a3e323b47535f6b77838e9aa6a99d9185796d62564a3e32261b0f03000000000000000000000000000000000000000000000000000000000000040e19242e39444e59646e79848e99a4aa9f948c8e97a2a99f94897f74695f54493f34291f140a00000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c798693969494949494949494949494949494949386796c5f5346392c2013000000040c151e262f374049515a626b747c859091867d746c635a524941382f271e150d0400000000000000000000000000000000000001071018202831394149515a626a727a838b93968c82776d63594d4135291c100300000000000000000000000000000000000000000000000000000003090f171f2730384048505961697179828a92978d83796f645a4f43372a1e1105000000000000000000000000000000020a11171c1f212121212121212121252d353d464e565e666f777f87909890867c72685d52473a2e22212121201d19130c040000000013202c3946535f6c798693939393939393939393939393939393939386796c5f5346392c20130000000000000000000000040e17212b343e48515b646e78818b959ea0a0a0a0a0a0998f857b72685e544a40372d23190f0600000000000000000000000000000008131d27313b45505a646e78838d97a0a09e968e867e756d64594d4135281c0f0013202c3946535f6c79868a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a909386796c5f5346392c201300131f2c3946525f6b7679797979797979766a5e51454b58647079797979797979797064574b3e3125180b00000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d11040000000000000000000000000000000008131d28323d465059626a727980858a8f9396989b9c9e9e9fa0a09f9e9d9c9a9895918d88837d766f675f564d43392f241a0f040000000000000000000000000000000000010b141d262e373e464d53595f64686c6f727476777879797978777674726f6c68635e59534c453e362e251c130a00000000000000000e1b2734414d5a6673808c8f909192948a7e7265594d41362b211b171616191f2a36424f5b6874818e9aa7afa295887c6f6255493c2f2316090000000000000000000000000000000000000000000000000000000007131f2a36424e5a65717d8995a1aca2968a7e72675b4f4337404c58646f7b87939faba4988c8175695d5145392e22160a000000000000000000000000000000000000000000000000000000000000000b15202b35404b55606b75808b95a0aba3988d8386919ba6a69b90867b70665b50463b31261b1106000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938d8787878787878787878787878787878786796c5f5346392c20130000030d161e272f384149525b636c757d868e94948f877e756c645b534a413930271f160d040000000000000000000000000000000001091119222a323a424b535b636c747c848c95998e847a70665b51473c3125190d0000000000000000000000000000000000000000000000000000000008101821293139414a525a626b737b838b949a90867b71675d53483e32261a0e020000000000000000000000000000000000060c1013141515151515161e262e373f474f58606870788189919993897e746a60564c41362a1e15151413110d0801000000000013202c3946535f6c798686868686868686868686868686868686868686796c5f5346392c2013000000000000000000000000050f19222c363f49535c666f79838c9393939393939391877d736960564c42382f251b110700000000000000000000000000000000010b151f29343e48525c66717b858f939393939390877f76695d5043372a1d100013202c3946535f6c798693939393939393939393939393939393939386796c5f5346392c201300111e2a37434f5a646b6c6c6c6c6c6c6c6b64594e4248545f686c6c6c6c6c6c6c6c685e53483c2f23160a00000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000000000000000000000000000000020e19242f3a444e58626b747c848b91969b9fa2a5a3a19f9e9d9c9c9d9d9fa0a2a4a19d99948e88817971685f554b41362b20150a000000000000000000000000000000000000020b141c252d343b42484e53585c60636568696b6c6c6c6c6b6b696765625f5c57534d48413b342c241c130a0100000000000000000c1925323f4b5864717d8a969d9e9f9a8e8275695e52473d332c272423232529313b46525e6b7783909ca9ada094877a6e6154483b2e22150800000000000000000000000000000000000000000000000000000000020e1a26313d4955616c7884909ca8a79b8f83776b5f53483c44505c6874808c98a4ab9f93887c7064584c4035291d110500000000000000000000000000000000000000000000000000000000000007121c27323c47525c67727c87929ca7a79c91867c7f8a959faaa2978d82776d62574d42382d22180d020000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938b7e7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a776b5f5246392c201300000b151f283039424a535b646d757e878f9289899190877e766d655c534b423931281f160c010000000000000000000000000000020b131b232b343c444c545d656d757e868e969b91877c72685e544a3f352b2014090000000000000000000000000000000000000000000000000000010a121a222a333b434b535c646c747c858d959c92887e74695f554b41372c21160a00000000000000000000000000000000000000000406080808080f172028303840495159616a727a828a939b958b81776d62584e443a2f25190e080807040100000000000000131f2c3946525f6b767979797979797979797979797979797979797979766b5f5246392c1f130000000000000000000000000007101a242d37414a545d67717a8486868686868686867f756b61574e443a30261d1309000000000000000000000000000000000000030d18222c36404a555f69737d868686868686868684776a5d5044372a1d110013202c3946535f6c798686868686868686868686868686868686868686796c5f5346392c2013000e1a26323e48525a5f5f5f5f5f5f5f5f5f5a52483d424d565d5f5f5f5f5f5f5f5f5c564d42372b1f130700000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000000000000000008131f2a35404b56606a747d868e969ca2a7a29e9a979492919090909091929496999da2a59f99928b837a71675d52483d32261b0f03000000000000000000000000000000000000020a131b222930373d42474c505356595b5d5e5f5f5f5f5f5e5d5b5956534f4b47423c363029221a120a010000000000000000000a1723303c4955616e7a87939fabaa9e92867a6f63594f453d373330303031353b434d57636f7a87939facab9e9285796c5f53463a2d20140700000000000000000000000000000000000000000000000000000000000915212d3844505c6873808b97a3ab9f94887c7064584c404955616d7985919ca8a69a8f83776b5f53483c3024180c010000000000000000000000000000000000000000000000000000000000030e19232e39434e59636e79838e99a3aba0958a807578838e98a3a99e94897e74695f54493f34291f14090000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986938b7e716d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6c655a4f43372a1e110006121d27313a424b545c656d767f87909088807f8790918880766e655d544b433a31281d120700000000000000000000000000020b141d252d353d464e565e666f777f8790989e93897f756b60564c42382e23190e0300000000000000000000000000000000000000000000000000010a131b242c343c454d555d656e767e868f979f958b80766c62584d43392f251a10050000000000000000000000000000000000000000000000000710192129323a424a525b636b737b848c949c988e83796f655b51463c32281e1308000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b645a4f43372a1e11000000000000000000000000000008121b252f38424b555f6872797979797979797979766d63594f453c32281e140b010000000000000000000000000000000000000006101a242e39434d57616b7579797979797979797974695c5043362a1d1000131f2c3946525f6b767979797979797979797979797979797979797979766b5f5246392c1f13000a16212c3740484f5253535353535353524e4840363b444b515353535353535353504b443b30261a0f0300000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d11040000000000000000000000000000010d1924303b47525d68727c868f98a0a7a39c97928d8a878684838383838485878a8d91969ca4a49d958c83796f64594e43372c20140800000000000000000000000000000000000000010910181f252b31373b4044474a4c4f5051525353525251504e4c4a47433f3b36312b251e17100800000000000000000000000814202d3946525e6a76838f9aa6aea2978b80756a61574f48433f3d3c3d3e41464c555e6974808b97a3afa89b8f83766a5d5144382b1f1205000000000000000000000000000000000000000000000000000000000004101c28343f4b57636f7a86929eaaa4988c8174695d51454e5a65717d8995a1ada2968a7e72665a4f43372b1f13080000000000000000000000000000000000000000000000000000000000000a15202a35404a55606a75808a95a0aaa4998e83796e717c87929ca7a59b90867b70655b50463b30261b100600000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000000000010507101c2936434f5c69768390908376695c4f4336291c1007050100000000000013202c3946535f6c7986938b7e71656060606060606060606060606060605b53493e33271b0f000b17232e39434c545d666e778088918f877e76757e868f918980776f665d554c433a2f24180c000000000000000000000000000a141d262e373f474f586068707881899199a0968c81776d63594f443a30261c1207000000000000000000000000000000000000000000000000000008131c252d363e464e575f676f7780889098a1978d83786e645a50463b31271d1309000000000000000000000000000000000000000000000000050f19222b333b444c545c646d757d858e969e9a90867c72675d53493f342a20160c010000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5a52483e32261a0e00000000000000000000000000000009131d26303a434d5660696c6c6c6c6c6c6c6c6c6b645b51473d342a20160c0200000000000000000000000000000000000000000008121c27313b454f5a636b6c6c6c6c6c6c6c6c6c6a62584c4034281b0f00111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b645a4f43372a1e110005101a252e373e43464646464646464645433d362e323a4044464646464646464644403a32291f14090000000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000000000000000000000000000006121d2935414c58636e79848e98a1aaa199928b86817e7b79777676767677787a7d81858b929aa2a79e958b81756a5f54483c3024180c000000000000000000000000000000000000000000060d141a20262b2f34373b3d404243454546464645444342403d3a37332f2a25201a140d0600000000000000000000000005111d2a36424e5a66727e8a95a1aca89c91877c7369615a544f4c4a49494b4d51575e67707b85919ca8afa3978b7f73675a4e4235291c10030000000000000000000000000000000000000000000000000000000000000b17232f3b46525e6a76828d99a5a99d9185796d615549525e6a76828e9aa6a99d9185796d61564a3e32261b0f03000000000000000000000000000000000000000000000000000000000007111c27313c47515c67717c87919ca7a89d92877c72676a75808b96a0aba2978d82776d62574d42372d22170d02000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e221508000000000000000000000000070d1114161c2936434f5c69768390908376695c4f4336291c1614110d07000000000013202c3946535f6c7986938b7e71655853535353535353535353535353534f4941372d21160a000f1c28343f4b555e666f788089928e867d756c6c747d858e928a81786f675e554b4035291c1004000000000000000000000005101b262f3840495159616a727a828a939ba2988e847a70655b51473d33281e140a0000000000000000000000000000000000000000000000000000040f1a242e373f485058606871798189929aa29a8f857b71675c52483e342a1f150b010000000000000000000000000000000000000000000000000c17212b353d454d555e666e767e878f979f9d93887e746a60554b41372d23190e04000000000000000000000000000a16212c3740484f525353535353535353535353535353535353535353524f4840372c21160a000000000000000000000000000000010b141e27313b444e575d5f5f5f5f5f5f5f5f5f5f5a52493f352b22180e0400000000000000000000000000000000000000000000010b151f29333d4851595e5f5f5f5f5f5f5f5f5f5e5950463b3024180c000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5a52483e32261a0e000009131c252c323739393939393939393936322c24282f3438393939393939393938342f2820170d020000000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000000000000000a16222e3a46525d6974808b96a0aaa1988f87807a75716e6c6b6a69696a6a6c6e71757a8088909aa4a79d92877c7064594d4135281c100300000000000000000000000000000000000000000002090f151a1f23272b2e3133353738393939393938373533312e2b27231f1a140f090200000000000000000000000000010e1a26323e4a56616d79848f9ba5aea3988e857b736b655f5b5856565657595d62697079828c97a2adaa9e93877b6f63574b3e3226190d0100000000000000000000000000000000000000000000000000000000000007121e2a36424d5965717d8994a0aca1958a7e72665a4e57636f7b87929eaaa4988c8174695d5145392d22160a0000000000000000000000000000000000000000000000000000000000030e18232e38434e58636e78838e98a3aba1968b81766b60646e79848f99a4a99e94897e74695e54493e34291e1409000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000000030b12181d2022222936434f5c69768390908376695c4f4336292222201d18120b0300000013202c3946535f6c7986938b7e7165584b47474747474747474747474746443e372f251b100500121e2b3844505c677078818a928d857c746b63626b737c848d938a827970675d5145382c1f130600000000000000000000000a16222d38414a525b636b737b848c949ca59b91877c72685e54493f352b21170c0200000000000000000000000000000000000000000000000000000915202c364049515a626a727a838b939ba49c92887d73695f554b40362c22180e0300000000000000000000000000000000000000000000000005111d28333d474f575f67707880889199a19f958b81766c62584e44392f251b1107000000000000000000000000000005101a252e373e4346464646464646464646464646464646464646464646433e372e251a100500000000000000000000000000000000020c161f29323c454c51535353535353535353524f4940372d23191006000000000000000000000000000000000000000000000000030d17222c363f484e52535353535353535353524e473e352a1f1408000a16212c3740484f525353535353535353535353535353535353535353524f4840372c21160a0000010a131a21262a2c2c2c2c2c2c2c2c2c2a26211a1d24282b2c2c2c2c2c2c2c2c2b28231d160e05000000000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000000000000000d1926323e4a56626e7a86919ca7a4998f867d756f696562605e5d5d5c5d5e5f6164696e767e88939ea9a4988d8175695d5144382c1f1306000000000000000000000000000000000000000000000004090e13171b1f222427292a2b2c2c2c2c2c2b2a282624221e1b17130e0903000000000000000000000000000000000a16222d3945515c68737e89949ea8aaa0978e857d76706b67656363636466696e737a828b949ea9aea3988d82766a5f53473b2e22160a00000000000000000000000000000000000000000000000000000000000000020e1925313d4954606c78848f9ba7a69a8e82766a5f535c6773808b97a3ab9f93877b7064584c4035291d110500000000000000000000000000000000000000000000000000000000000a151f2a353f4a555f6a75808a959faaa59a8f84796f64595d67727d88939da8a59b90857b70655b50453b30251b10050000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e221508000000000000000000020c151d24292d2f2f2f36434f5c69768390908376695c4f43362f2f2f2d29241d150c02000013202c3946535f6c7986938b7e7165584b3e3a3a3a3a3a3a3a3a3a3a3a3a37332d251d1309000013202c3946535f6c78828a9390847b736a625959616a727a838f948b82796d6053473a2d20140700000000000000000000000e1b27333e49535c646d757d858e969ea69d93897f746a60564c42382d23190f050000000000000000000000000000000000000000000000000000000d1925313d48525b636c747c848c959da59f948a80766c61574d43392f241a1006000000000000000000000000000000000000000000000000000915212d39454f5961697179828a929aa3a2988d83796f655a50463c32281d13090000000000000000000000000000000009131c252c32373939393939393939393939393939393939393939393937322c251c1309000000000000000000000000000000000000040d17202a333b414546464646464646464646433e372e251b1107000000000000000000000000000000000000000000000000000005101a242d363d424546464646464646464645423c352c23180e020005101a252e373e4346464646464646464646464646464646464646464646433e372e251a1005000000010910161a1e1f202020202020201f1e1a150f12181c1f20202020202020201f1c18120c0400000000000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d11040000000000000000000000000000101d2935424e5a66727e8a96a1a49d92877d736b635e5956535150505050515355585d646c76818d98a4a99d9185796d6054473b2e2215090000000000000000000000000000000000000000000000000003070b0f1215181a1c1d1e1f2020201f1e1d1c1a1815120f0b070200000000000000000000000000000000000005111d2934404b56626c77828c969fa9a9a0978f88817c777471706f6f717275797e858c949da6afa69c91877c70655a4e42362a1e120600000000000000000000000000000000000000000000000000000000000000000915202c3844505b67737f8b96a2ab9f93877b6f6357606c7884909ca8a69a8e83776b5f53473c3024180c000000000000000000000000000000000000000000000000000000000006111c26313c46515c66717c86919ca6a89e93887d73685d5256616b76818c96a1aca2978c82776c62574c42372c22170d0200000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e2215080000000000000000000a141e272e35393c3c3c3c434f5c69768390908376695c4f433c3c3c3c39352e271e140a000013202c3946535f6c7986938b7e7165584b3e3d3d3d3d3d3d3d3d3d3d3d3d3a362f281f150b0000121f2c3945525e6a747c858e928981786f675e5e666f778089928e867d746b5f5246392d2013070000000000000000000000111d2a36434f5b656e767e878f979fa0a0968b81776d63584e443a30261b1107000000000000000000000000000000000000000000000000000000000f1c2835414d59646d757e868e969ea0a0978d83786e645a50453b31271d130800000000000000000000000000000000000000000000000000000b1825313d4a56616a737b838b949ca0a09a90867b71675d53493e342a20160c0100000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a26211a130a0100000000000000000000000000000000000000050e1821293035383939393939393939393937322c251c13090000000000000000000000000000000000000000000000000000000008121b242b3236393939393939393939393936312b231a110700000009131c252c32373939393939393939393939393939393939393939393937322c251c1309000000000000050a0e11131313131313131313110e0a04070c1012131313131313131312100c07010000000000000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d11040000000000000000000000000000121f2c3845515e6a76838f929597978c81756b6159524d494645444343434446484c525a65707c8895a1ada195887c6f63564a3d3024170a000000000000000000000000000000000000000000000000000000000306090b0e0f1112121313131212100f0d0b090602000000000000000000000000000000000000000000000c18232f3a45505b66707a848d979fa7a9a199938d8884817e7d7c7c7d7f82868a90979ea6aea69d948a80756a5f54493d32261a0e02000000000000000000000000000000000000000000000000000000000000000004101c27333f4b57626e7a86929da9a3978b8073685c65717d8995a0aca1968a7e72665a4e43372b1f130800000000000000000000000000000000000000000000000000000000030d18232d38434d58636d78838d98a3aca2978c81766c61564c4f5a646f7a85909aa5a99e93897e73695e53493e33291e140900000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e221508000000000000000006111c263039404548494949494f5c69768390908376695c4f494949494845403930261c11060013202c3946535f6c7986938b7e7165584b4a4a4a4a4a4a4a4a4a4a4a4a4a47413a31271d120600111d2936424d58626a737c858d928a817970686770788189928e857c746b62594e42362a1e11050000000000000000000000121f2c3845525e6b7780889193939393938e84796f655b51473c32281e140a0000000000000000000000000000000000000000000000000000000000101d2a3743505d69767f879093939393938f857b71665c52483e34291f150b0100000000000000000000000000000000000000000000000000000c1926333f4c5966727c858d939393939392887e746a5f554b41372d22180e04000000000000000000000000000000000000010910161a1e1f20202020202020202020202020202020202020201f1e1a16100901000000000000000000000000000000000000000000060f171e24292c2c2c2c2c2c2c2c2c2c2c2a27211b130a01000000000000000000000000000000000000000000000000000000000009121a21262a2c2c2c2c2c2c2c2c2c2c2c2a262019110800000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a26211a130a01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000000000000000000000000000013202c3946535f6c79818386888b8d877b6f64594f47413d3a383736363738393c414854606c7985929faba4978b7e7165584b3e3225180c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121d29343f49545e68727b858d959da4aba49e9894908d8b8989898a8c8e92969ba1a8aaa39c948b82786e63594e43382c211509000000000000000000000000000000000000000000000000000000000000000000000b17232e3a46525d6975818d99a4a89c9084786c606975818d99a5a89d9185796d61564a3e32261a0f03000000000000000000000000000000000000000000000000000000000a141f2a343f4a545f6a747f8a949faaa59b90857a70655a4f4548535e68737e89949ea9a59a90857a70655a50453a30251b1005000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000b17222e38424b515555555555555c69768390908376695c555555555555514b42382e22170b0013202c3946535f6c7986938b7e7165585757575757575757575757575756524c43392e23170b000d1925313c465059616a737b848d948b837a717179828a938d857c736a625950473d32261a0e020000000000000000000000121f2c3845525f6b788586868686868686867c72685d53493f352b20160c020000000000000000000000000000000000000000000000000000000000111d2a3744505d6a778486868686868686867d73695f554a40362c22180d030000000000000000000000000000000000000000000000000000000d192633404c59667380868686868686868681766c62584e43392f251b1106000000000000000000000000000000000000000000050a0e1113131313131313131313131313131313131313131313110e0a05000000000000000000000000000000000000000000000000050d13191c1f2020202020202020201f1e1b1610090100000000000000000000000000000000000000000000000000000000000000080f151a1e1f2020202020202020201f1d1a150e07000000000000010910161a1e1f20202020202020202020202020202020202020201f1e1a1610090100000000000000000000000000000000000000000000000407080808080808080808080704010000000003060808080808080808080807050100000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d11040000000000000000000000000000121f2b3844515d68717477797c7e8183766a5e53483d36312d2b2a2a2a2a2b2d303845515e6b7784919eaba5988c7f7265594c3f3226190c000000000004090e10121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212100d090400000000000000010c17222d38424c566069727b838b93999fa5a9a4a09c999796969697989b9ea2a7a9a59f99928a82796f665c52473c31261b10040000000000000000000000000000000000000000000000000000000000000000000006121e2935414d5965707c8894a0aba094887c70646e7a86929eaaa4988c8074695d5145392d21160a0000000000000000000000000000000000000000000000000000000006111b26313b46515b66717b86919ba6a99f94897e74695e53493e414c57626c77828d97a2aca1978c81776c61574c41372c22170c020000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e22150800000000000000000f1b27333f4a545c616262626262626976839090837669626262626262615c544a3f33271b0f0013202c3946535f6c7986938b7e71656363636363636363636363636363635d554b3f34281c0f000914202a353e474f586069727a838c948c837b7a838b948c847b726a615850473e352b20150a000000000000000000000000121f2b3845515e6a76797979797979797979746a60564c41372d23190f04000000000000000000000000000000000000000000000000000000000000101d2a3643505c6974797979797979797979756b61574d43392e241a1006000000000000000000000000000000000000000000000000000000000c1926333f4c586571797979797979797979786f645a50463c32271d1309000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080d101213131313131313131313110e0a0500000000000000000000000000000000000000000000000000000000000000000000040a0e111313131313131313131313110e0903000000000000000000050a0e1113131313131313131313131313131313131313131313110e0a050000000000000000000000000000000000000000000000060c10131515151515151515151513110c0701050b10131515151515151515151514110d08020000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d11040000000000000000000000000000101c2935404c565f65686a6d6f72747671665a4e42362b25211f2024272a2d32363d46525f6b7885919eaba6998c807366594c403326190d00000000080f151a1d1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1d19150f080000000000000006111b26303a444e576069717981888e94999ea2a5a8a6a4a3a2a3a3a5a7a7a4a19d99948e87807870675e544a40352b20150a0000000000000000000000000000000000000000000000000000000000000000000000010d1925313c4854606b77838f9ba7a5998d817568727e8a96a2ab9f93877b7064584c4034291d1105000000000000000000000000000000000000000000000000000000020d18222d38424d58626d78828d98a2ada2988d82776d62574c42373a45505b65707b86919ba6a89e93897e73685e53493e33291e13090000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e2215080000000000000000121e2b3744505b666e6f6f6f6f6f6f6f7683909083766f6f6f6f6f6f6f6e665b5044372b1e120013202c3946535f6c7986938b7e717070707070707070707070707070706f675c5044382b1e1200030e19232c353d464e576068717a838b948d84848c948c837a726960584f463e352c23190f04000000000000000000000000101d2936424e59646b6c6c6c6c6c6c6c6c6c6a62584e443a30251b1107000000000000000000000000000000000000000000000000000000000000000f1b2834404c58626a6c6c6c6c6c6c6c6c6c6b635a4f453b31271c120800000000000000000000000000000000000000000000000000000000000b1724303d49545f686c6c6c6c6c6c6c6c6c6c665d53483e342a20150b010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a11181c2021222222222222222222201d18120b10171c1f21222222222222222222201d19130c0500000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000000000000000c18242f3a444d55595b5e606365676a675f554a3e32262326292d3033363a3e42484e57626e7a8793a0aca5988c7e7265594c3f3226190c00000009121a2026292b2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b292520191209000000000000000a141e28323c454e575f676f767d83898d9295989b9d9e9f9f9f9f9e9c9a9895918d88837c756e665e554c42382e24190e040000000000000000000000000000000000000000000000000000000000000000000000000814202c37434f5b67737e8a96a2a99d9185796d76828e9aa6a69a8e83776b5f53473b3024180c0000000000000000000000000000000000000000000000000000000009141f29343f49545f69747f89949fa9a69c91867b71665b50463b30343e49545f69747f8a959faaa59a8f857a6f655a50453a30251a100500000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e221508000000000000000013202c3946535f6c787c7c7c7c7c7c7c7c839090837c7c7c7c7c7c7c7c786c5f5346392c20130013202c3946535f6c7986938b7e7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d786c5f5346392c2013000007111a222b343c454e565f687079828a938f8e948b827a716860574e463d342c231a1107000000000000000000000000000e1a26313d48525a5f5f5f5f5f5f5f5f5f5f5e5950463c32281e140900000000000000000000000000000000000000000000000000000000000000000c1824303b4650595e5f5f5f5f5f5f5f5f5f5e5951483d33291f150b0000000000000000000000000000000000000000000000000000000000000814202c38434d565d5f5f5f5f5f5f5f5f5f5f5b544b41362c22180e0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030507090a0b0c0c0c0c0b0b090806030100000000000000000000000000000000000000000000000000000000000000000000000307090a0a0a0a0a0a0a0a0a090703000000000000000000000000000000000000000000000000000306080a0b0c0c0c0c0b0a090705020000000000000101010101010101010100000000000000000000000000000206090a0a0a0a0a0a0a0a0a0a08040000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2d29241d151b22282c2e2e2e2e2e2e2e2e2e2e2d2a251e160e05000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000000000000000000000000000007131e29323b43494c4f515456585b5d5b564d44392d2c2f3236393c3f43464a4e53596069747f8a96a3afa3978a7d7164574b3e3125180b000008121b242b313638383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383836312b231b1208000000000000020c16202a333c454d565d646b72777d8286898c8e90919292929291908e8c8985817c77716b645c544c433a30261c120700000000000000000000000000000000000000000000000000000000000000000000000000030f1b27333e4a56626e7985919da9a195897d717a86929eaaa1958a7e72665a4e43372b1f130700000000000000000000000000000000000000000000000000000006101b26303b46505b66707b86909ba6aa9f958a7f746a5f54493f34292d38424d58636d78838e98a3aca1978c81766c61574c41372c21170c01000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000000000000b1724313e4a5764717d8a95887b6e6155483b2e221508000000000000000013202c3946535f6c798689898989898989899292898989898989898986796c5f5346392c20130013202c3946535f6c7986938f8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a86796c5f5346392c2013000000081019222a333c444d565e677078818a92938a827970685f564e453c342b221a110800000000000000000000000000000915202b3640484e52535353535353535353524e473e352a20160c02000000000000000000000000000000000000000000000000000000000000000008141f2a353e474e52535353535353535353524e483f362c21170d0300000000000000000000000000000000000000000000000000000000000004101b27313b444c5153535353535353535353504a42392f251a1006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000105090c0f1214151718191919191817161412100d0a0602000000000000000000000000000000000000000000000000000000000000030a0f131617171717171717171716130f0a04000000000000000000000000000000000000000105090d10121516181819191918171614110e0b070304080c0e0e0e0e0e0e0e0e0e0d0b080300000000000000000001080e12151717171717171717171614100b050000000000000a141d262e34383b3b3b3b3b3b3b3b3b3b39352f271f252d33383b3b3b3b3b3b3b3b3b3b3935302820170d020000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d11040000000000000000000000000000010c17202932383d404245474a4c4e504f4b443b3235383c3f4245484c4f52565a5f646b727b85909ba7aca094877b6f6256493c3023170a00040f1a242e363d42454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545423d352d23190f04000000000000050e18212a333b444b535a60666c7175797d80828485868686858483817f7c7975716c666059524a423a31281e140a0000000000000000000000000000000000000000000000000000000000000000000000000000000a16222e3a45515d6975818c98a4a5998d81757e8a96a2a89d9185796d61564a3e32261a0e030000000000000000000000000000000000000000000000000000020d17222d37424d57626d77828d97a2ada3998e83786e63584d43382d2226313b46515c66717c87929ca7a89e93887d73685e53483e33281e1308000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000000000040b111724313e4a5764717d8a95887b6e6155483b2e2215100a0200000000000013202c3946535f6c798693969696969696969b9b969696969696969386796c5f5346392c20130013202c3946535f6c798693939393939393939393939393939393939386796c5f5346392c201300000000071018212a323b444c555e666f7880898a81786f675e564d443c332a22191008000000000000000000000000000000040f1a242e363d434546464646464646464645423c352c23190e04000000000000000000000000000000000000000000000000000000000000000000020e18232c353c424546464646464646464645423d362d241a100500000000000000000000000000000000000000000000000000000000000000000a152029323a404446464646464646464646443f3830271d130900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003080d1115181b1e2022242525262625252423211f1c1a16130e0a05000000000000000000000000000000000000000000000000000000060e151b1f22242424242424242424221f1b150e060000000000000000000000000000000001070c1115191c1f21232425262626252422201e1b17140f0f14181a1b1b1b1b1b1b1b1b1a18140f0901000000000000040c13191e2223242424242424242423201c1710080000000006111c262f383f454848484848484848484845403931272e373e444748484848484848484846413a32291f14090000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000000000000000000000000000000050e1720272d313336383b3d404244433f39393d4144484b4e5255585b5f62666a6f757c858d97a2ada79b9084786b5f53463a2e211508000a15212c3640484e5152525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252514e473f352b20150900000000000000060f182129323a41484f555b6065696d70737577787979797877767572706d6965605b554e47403830281f160c0200000000000000000000000000000000000000000000000000000000000000000000000000000006111d2935414c5864707c88939fa99d918579828e9aa6a4988c8074685d5145392d21160a00000000000000000000000000000000000000000000000000000009141e29343e49545e69747e89949ea9a79c92877c71675c51463c31261b1f2a353f4a55606a75808b96a0aba59a8f857a6f655a4f453a2f251a0f050000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110000000000050e151c2226313e4a5764717d8a95887b6e6155483b2e25211b140c03000000000013202c3946535f6c798693a0a2a2a2a2a2a3a6a6a3a2a2a2a2a2a09386796c5f5346392c20130013202c3946535f6c798686868686868686868686868686868686868686796c5f5346392c20130000000000060f182029323a434c545d666e778080776f665d554c433b322a21181007000000000000000000000000000000000008121b242c3236393939393939393939393936312b231a1107000000000000000000000000000000000000000000000000000000000000000000000007111a232b3136393939393939393939393936322b241b1208000000000000000000000000000000000000000000000000000000000000000000030e1720292f35383939393939393939393937332e261e150b010000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090e14181d2125282b2d2f30313232323232312f2e2b2926221f1a16110b05000000000000000000000000000000000000000000000000060f1820262b2f3030303030303030302f2c26201810060000000000000000000000000000060d13181d2125292b2e30313232323232312f2d2a27241f1b1b20242728282828282828282724201a130b0200000000030d161e252a2e3030303030303030302f2d28221a12090000000b17222d38424a5154555555555555555554514b43392f3640495054555555555555555555524c443b30251a0e0200101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000000000000000000050e151c212427292c2e31333537383d4145494d5154575b5e6164686b6e72767b81878e969fa9aba0968a7f73675b4f43372b1e1205000e1a26323d4852595e5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5e5951473d3125190d0000000000000000060f1720282f373d444a4f55595d616466686a6b6c6c6c6b6b6a686663605d59544f49433d362e261e160d0300000000000000000000000000000000000000000000000000000000000000000000000000000000010d1824303c48535f6b77838e9aa6a195897c86929eaa9f93877b6f64584c4034281d1105000000000000000000000000000000000000000000000000000005101b25303b45505b65707b85909ba5aba0968b80756b60554a40352a1f1518232e39434e59646e79848f99a4aca1968c81766c61564c41362c21160c0100000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100000000050e1720272d32353e4a5764717d8a95887b6e6155483b35312c261e150c030000000013202c3946535f6c798693a0acafafafafafb2b2afafafafafaca09386796c5f5346392c201300131f2c3946525f6b767979797979797979797979797979797979797979766b5f5246392c1f13000000000000060e172028313a424b545c656d76776e655d544b433a312920180f060000000000000000000000000000000000000009121a21262a2c2c2c2c2c2c2c2c2c2c2c2a25201911080000000000000000000000000000000000000000000000000000000000000000000000000008111920262a2c2c2c2c2c2c2c2c2c2c2c2a26211a12090000000000000000000000000000000000000000000000000000000000000000000000050e171e24292b2c2c2c2c2c2c2c2c2c2c2b27221c140c0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000070d141a1f24292d313437393b3d3e3f3f3f3f3e3d3c3a3835322f2b26221c17110a03000000000000000000000000000000000000000000030e18212a31373b3d3d3d3d3d3d3d3d3d3b37322a22180e040000000000000000000000020a11181e24292d3235383a3c3e3f3f3f3f3e3d3c393733302b27252c3134343434343434343433302b251d140b010000000b151f282f363a3d3d3d3d3d3d3d3d3d3c39332c241b110600000f1b27333f4a545c616161616161616161615d554b40343d48525b606161616161616161615e564c42362b1e120600101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d11040000000000000000000000000000000000040a1015181a1d1f242c32383e44484d5155595d6064676a6d7174777a7e82878c9299a0a8aca3998f84796e62574b3f33271b0f0200111e2a36434e5a646a6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6a63594e4236291d10000000000000000000060e161d252c32393e44494d5154575a5c5d5e5f5f5f5f5e5d5b595754514d48433e38322b241c140c0400000000000000000000000000000000000000000000000000000000000000000000000000000000000008141f2b37434f5a66727e8a96a1a5998d818a96a2a69a8e82776b5f53473b3024180c0000000000000000000000000000000000000000000000000000020d17222c37424c57626c77828c97a2aca4998f84796e64594e43392e23180e111c27323c47525d67727d88939da8a89d93887d73685d53483d33281d130800000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000000050e17202931393e42424a5764717d8a95887b6e61554842413d3730271e150c0300000013202c3946535f6c798693a0acb9bcbcbcbcbebebcbcbcbcb9aca09386796c5f5346392c201300111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b645a4f43372a1e1100000000000000050e161f283039424a535b646b6b655c534b423931281f170e05000000000000000000000000000000000000000000080f151a1e1f2020202020202020201f1d1a140e07000000000000000000000000000000000000000000000000000000000000000000000000000000070e151a1d1f2020202020202020201f1e1a150f0800000000000000000000000000000000000000000000000000000000000000000000000000050c13181c1f202020202020202020201e1b17110a02000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a11181f252b3035393d414446484a4b4c4c4c4c4b4a494744423f3b37322d28221c150e07000000000000000000000000000000000000000009141f2a333c43484a4a4a4a4a4a4a4a4a48433c342a20150a00000000000000000000040c141c23292f35393e414447494a4b4c4c4c4b4a484643403c373230373d404141414141414141403c362f261d1308000006121d27313a41474a4a4a4a4a4a4a4a4a49443e362d23180d0100121e2b37434f5b666d6e6e6e6e6e6e6e6e6d675c514539414e59646c6e6e6e6e6e6e6e6e6e685e53473b2e22150800101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d11040000000000000000000000000000000000000004080d161f272f363d444a4f54595d6265696d7073777a7d8184878a8e93989da3aaa9a29a91877d72685c51463a2f23170b0000131f2c3945525f6b7678787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878756a5e5145382b1f1200000000000000000000040c131a21272d33383d4145484b4d4f51525253525251504f4d4a4844413c38332d272019120a0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000030f1b26323e4a56616d7985919ca89d928b909aa6a1958a7e72665a4e42372b1f1307000000000000000000000000000000000000000000000000000009131e29333e49535e69737e89939ea9a89d93887d72685d52473d32271c12070b15202b36404b56616b76818c96a1aca49a8f847a6f645a4f443a2f241a0f05000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110000040e172029323b434a4e4f4d5764717d8a95887b6e61554d4f4d49423930271e150c02000013202c3946535f6c798693a0acb9c6c9c9c9cacac9c9c9c6b9aca09386796c5f5346392c2013000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5a52483e32261a0e0000000000000000040d161e272f384149525a5f5f5a534a413930271f160d050000000000000000000000000000000000000000000000040a0e111313131313131313131313110d0903000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e111313131313131313131313110e0a0400000000000000000000000000000000000000000000000000000000000000000000000000000001070c101213131313131313131313120f0b0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000040c141c232a30363c4145494d50535556575859595858575553514e4b47433e39332d2720181109010000000000000000000000000000000000030e1a26313b454d54575757575757575757544e463c32261b0f030000000000000000040d161e262d343a40454a4e5153565758595958585755524f4c48433e3942484d4e4e4e4e4e4e4e4e4c4841382f241a0e03000b17232e39434c525657575757575757575550483f34291e12060013202c3946525f6c777b7b7b7b7b7b7b7b796d6154473b44505d6a767b7b7b7b7b7b7b7b7a6f6356493d3023160a00101c2936434f5c697683909ca9aa9d9084776a5d5044372a1e110400000000000000000000000000000000000000030d161f28313941484f555b6065696e7275797c8083868a8d9093979a9fa3a9aaa59e9790887e756b61564b4035291e1206000013202c3946535f6c7985858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585786b5f5245382c1f12000000000000000000000001090f161c22272c3135393c3e4143444546464645454442403e3b3835302c27221c150f08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003060a16222d3945515d6874808c98a3a49b989aa2a89c9185796d61554a3e32261a0e030000000000000000000000000000000000000000000000000005101a25303a45505a65707a85909aa5aca1968c81766b61564b40362b20150b00040e19242f39444f5a646f7a85909aa5aba1968b81766b61564b41362c21160c010000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100010c162029323b444d555a5c595764717d8a95887b6e61555a5c5a544b423930271e140a000013202c3946535f6c798693a0acb9c6d3d5d5d7d7d5d5d3c6b9aca09386796c5f5346392c2013000a16212c3740484f525353535353535353535353535353535353535353524f4840372c21160a000000000000000000040c151e262f3740484f52524f4941382f271e150d040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050e161e262e353b42474d5155595c5f61636465656565646362605d5a57534f4a443e38312a231b130a010000000000000000000000000000000006121f2b37424d575f6363636363636363635f584e43372c1f130700000000000000030d161f2830383f464c51565a5d606264656565656463615f5c58544f49434b53595b5b5b5b5b5b5b5b59534b41362b1f1307000f1c28343f4b555d636363636363636363615a51463a2f23160a0013202c3946535f6c7986888888888888887b6e6154483b44515d6a7784888888888888887d7063564a3d3023170a00101c2936434f5c697683909ca9aa9e9184776b5e5144382b1e1105000000000000000000000000000000000000010b151f28313a434b525a60666c71757a7e8285898c8f9396999ca0a3a7aba8a49f99938d867e756c63594f443a2f24180d01000013202c3946535f6c7986929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929285786b5f5245382c1f1200000000000000000000000000050b11161c2025292c2f32343637383939393938373534312f2c2824201b16100a0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f1315161d2934404c58646f7b87939fa8a7a4a6a8a3988c8074685c5145392d21160a00000000000000000000000000000000000000000000000000020c17222c37414c57616c77828c97a1aca59a90857a6f655a4f443a2f24190f04000008121d28333d48535e68737e89949ea9a89d92887d72685d52483d33281d13080000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110007121d28323b444d565f6668645c64717d8a95887b6e615d6569655d544b423930261b10050013202c3946535f6c798693a0acb9c6d3dfe2e3e3e2dfd3c6b9aca09386796c5f5346392c20130005101a252e373e4346464646464646464646464646464646464646464646433e372e251a100500000000000000000000030c141d252e373e434646433e372f261d150c030000000000000000000000000000000000000000000000000000000000000000000000000000000000000002040607080808080807060503010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000103050607080808080707050402000000000000000000000000000000000000000000000000000000000000000000000000000000000002040607080808080707050301000000000000000000000000000000000000000000000000000000000000000000050e17202830383f464d53585d6265696c6e70717272727271706e6c6a67635f5a55504a433c342d251c130a010000000000000000000000000000000815222e3b47535f697070707070707070706a5f54483b2f221609000000000000000b151e28313a424a51575d62666a6d6f707172727271706e6b68645f5a544e535d656767676767676767645d52473c2f23170a00121e2b3844505c676f70707070707070706c62574b3f3226190c0013202c3946535f6c7986939595959594887b6e6154483b44515d6a77849195959595958a7d7063564a3d3023170a00101c2936434f5c697683909ca9ab9e9285786b5f5245392c1f130600000000000000000000000000000000000008131d27313a434c555d646b71777c81868a8e9295989c9fa2a5a9aaa7a4a09c98938e88827b746c635a51473d33281d120700000013202c3946535f6c7986939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939285786b5f5245382c1f12000000000000000000000000000000050b1015191d20232528292b2c2c2c2c2c2b2a292725221f1c1814100b050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070e151b1f22232324303b47535f6b76828e9a9b9b9b9b9b9b93877b6f64584c4034281d11050000000000000000000000000000000000000000000000000009131e28333e48535e68737e89939ea8a99e93897e73685e53483d33281d1208000000010c16212c37414c57626c77828d97a2ada4998f84796f64594f443a2f241a0f0400000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e11000c18242f3a444d565f6871756e6564717d8a95887b6e61666f756f665d544b42382d21160a0013202c3946535f6c798693a0acb9c6d3dfecf0f0ecdfd3c6b9aca09386796c5f5346392c2013000009131c252c32373939393939393939393939393939393939393939393937322c251c1309000000000000000000000000020b131c252c3237393937332d251d140b030000000000000000000000000000000000000000000000000000000000000000000000000000000003070a0d0f1112131415151515141312100e0c090602000000000000000000000000000000000000000000000000000000000000000000000000000105080b0e1012131415151515141312100e0c0906030000000000000000000000000000000000000000000000000000000000000000000105090c0f11121414151515141312100d0b0704000005080a0a0a0a0a0a0a0a0a09070400000000000000000000000000040d172029323a424a51585e64696e7275787a7c7d7e7f7f7e7e7d7b7976736f6b66615b544e463f362e251c130a000000000000000000000000000000091623303c4956626f7b7d7d7d7d7d7d7d7c7063574a3d3024170a00000000000007121c27303a434c545b62686e7276797b7d7e7e7f7e7e7c7a7874706b665f5859656f74747474747474746f64584b3f3226190c0013202c3946535f6c787d7d7d7d7d7d7d7d73665a4d4034271a0d0013202c3946535f6c798693a0a2a2a194887b6e6154483b44515d6a7784919ea2a2a2968a7d7063564a3d3023170a00101c2936434f5c697683909ca9ac9f9386796d6053473a2d2114080000000000000000000000000000000000040f1a242f39434c565e676e767d83888d92969a9ea1a5a8aba8a5a19e9b9794908c87827d777069625a51483f352b21160c0100000013202c3946535f6c7986868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868685786b5f5245382c1f12000000000000000000000000000000000004090d101416191b1d1e1f1f201f1f1e1e1c1a181613100c080400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007101920262b2e3030303037424e5a66727d898e8e8e8e8e8e8e8e82766b5f53473b2f241a130d05000000000000000000000000000000000000000000000005101a252f3a454f5a656f7a858f9aa5ada2978d82776c62574c41372c21160c0100000000050f1a25303a45505b65707b86919ba6aba0968b81766b61564b41362b21160b01000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100101c2834404b565f68717a80776d64717d8a95887b6e666f7882786f665d54493e32261a0d0013202c3946535f6c798693a0acb9c6d3dfececececdfd3c6b9aca09386796c5f5346392c20130000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a26211a130a0100000000000000000000000000010a131a21262a2c2c2a27211b130b02000000000000000000000000000000000000000000000000000000000000000000000000000003070c101316191b1d1f20212222222121201e1c1a1815120e0a0601000000000000000000000000000000000000000000000000000000000000000004090d1114181a1c1e20212122222121201f1d1b1816120f0b06010000000000000000000000000000000000000000000000000000000004090d1215181b1d1f202122222221201e1c1a1714100b0c11141617171717171717171614100b0500000000000000000000010c151f29323b444c545c63696f757a7e828587898a8b8c8c8c8b89888583807b77726c665f58504840372e251c12080000000000000000000000000000091623303c4956636f7c898a8a8a8a8a8a7d7063574a3d3024170a0000000000030e19242e39424c555e666d73797e8285888a8b8c8c8c8b898784817c77716a635b687481818181818181807366594d4033261a0d0013202c3946535f6c79868a8a8a8a8a8a8173675a4d4034271a0d0013202c3946535f6c798693a0acaea194887b6e6154483b44515d6a7784919eaaaea3968a7d7063564a3d3023170a00101c2936434f5c697683909ca9ada194887b6e6255493c2f23170a00000000000000000000000000000000000a15202b36414b555e68707981888e94999ea2a6aaa8a5a29e9b9895928f8b8784807b76716c655f5850483f362d23190f0500000000131f2c3946525f6b7679797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979766a5e5145382b1f12000000000000000000000000000000000000000004070a0c0e1011121313131212110f0e0c0907040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050f19222b32373b3c3c3c3c3c3d4955616d788282828282828282827d72665a4e4237302b251e170f07000000000000000000000000000000000000000000010c17212c37414c56616c76818c96a1aca69b90867b70655b50453a30251a100500000000000009131e29343e49545f69747f8a959faaa79d92887d72685d52483d32281d1208000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100121f2b3844515d68717a838980766d717d8a95887b6e6f78818b82786f665a4e4235291c100013202c3946535f6c798693a0acb9c6d3dfdfdfdfdfdfd3c6b9aca09386796c5f5346392c2013000000010910161a1e1f20202020202020202020202020202020202020201f1e1a16100901000000000000000000000000000000010910161a1e1f201e1b161009010000000000000000000000000000000000000000000000000000000000000000000000000003090e13181c202326282a2c2d2e2e2e2e2e2d2c2b292724221e1b16120d070200000000000000000000000000000000000000000000000000000000050b1015191d212427292b2c2d2e2e2e2e2e2d2b2a2725221f1b17120d080200000000000000000000000000000000000000000000000003090f15191e2125282a2c2d2e2e2e2e2e2d2b292623201c17171d2123242424242424242423201c17100800000000000000000009131d27313b444d565e666d747b81858a8e9194969798999998979694928f8c87837d77716a625a524940372d241a0f0500000000000000000000000000091623303c4956636f7c8996979797978a7d7063574a3d3024170a00000000000914202b35404a545e6770777e858a8e92959698989998979694908c88827c746d646975828e8e8e8e8e8b7e7265584c3f3225190c0013202c3946535f6c798693979797978d8173675a4d4034271a0d0013202c3946535f6c798693a0acaea194887b6e6154483b44515d6a7784919eaab0a3968a7d7063564a3d3023170a00101c2936434f5c697683909ca9afa3968a7d7064584b3f32261a0e06080a0b0a0804000000000000000000030f1b26323d48525d67707a838b92999fa5aaa8a4a09c9995928f8c8986827f7b77736f6b66605a544d463e362d241b11080000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b64594e4236291d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b16212b343c434749494949494744505c6872757575757575757575746c61554944403c36302921191007000000000000000000000000000000000000000007121d28333d48535d68737d88939ea8aa9f948a7f74695f54493e34291e130b0b0b0b0a080400020d17222d38424d58636d78838e98a3aea4998f84796f64594f44392f24190e030013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000000000000000815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e110013202c3946535f6c79838c92898076717d8a95887b6f78818a948b82766a5d5044372a1d110013202c3946535f6c798693a0acb9c6d3d3d3d3d3d3d3d3c6b9aca09386796c5f5346392c20130000000000050a0e1113131313131313131313131313131313131313131313110e0a0500000000000000000000000000000000000000050a0e111313110f0a050000000000000000000000000000000000000000000000000000000000000000000000000002080f141a1f24282c2f323537383a3b3b3b3b3b3a39383634312e2a27221e19130d0700000000000000000000000000000000000000000000000000030a10161c2125292d30333637393a3b3b3b3b3a39383634312e2b27231e19130d0700000000000000000000000000000000000000000000070e141a20252a2e313436383a3b3b3b3b3a39383533302c282322282d3030303030303030302f2c28221a12080000000000000005101b252f39434d565f6870787f868c91969a9da0a2a3a2a1a1a2a3a3a19e9b98938e89827c746c645b52493f362b21170c01000000000000000000000000091623303c4956636f7c8996a3a4a4978a7d7063574a3d3024170a00000000030e1a25313c47525c667079828990969a9ea1a3a4a5a6a5a4a2a09d98938d867e766d697683909b9b9b988b7e7164574b3e3125180b0013202c3946535f6c798693a0a4a49a8d8173675a4d4034271a0d0013202c3946535f6c798693a0a3a3a194887b6e6154483b44515d6a7784919ea3a3a3968a7d7063564a3d3023170a00101c2936434f5c697683909ca9b2a5998c8073675b4e42362a1e13131417171714100b05000000000000000814202c37434e59646f79838c949ca4aba8a29c9894908c898683807c7976736f6b67635f5a554f49423b342c241b12090000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5a52483d31261a0e0000000000000003090d10121212121212121211100c080200000000000000000000000000000000060b0e111212121212121212110f0b0701000000000000000000000000000000000000000000000000000000000004101c28333d464e545656565656534e4b56606668686868686868686868635a5553504c47413a332b22190f06000000000000000000000000000000000000000c18232f3a444f5a646f7a858f9aa4a7a3988d83786d62584d42382d221717171717171614100b0506101b26313b46515c66717c87929ca7a7a0968b80756b60564b40362b1f13070013202c3946535f6c798693a0acada09386796d6053463a2d201307030302000000000000010203030815212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100121f2c3845515d69737c858e928980767d8a95887b78818a948c837a71675b4f4236291d100013202c3946535f6c798693a0acb9c6c6c6c6c6c6c6c6c6c6b9aca09386796c5f5346392c201300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050c131a20252b3034383b3f41434546474848484847464442403d3a37332e29241e18120b0300000000000000000000000000000000000000000000070e151b22272c3135393d40424446474848484847464543403e3b37332e2a241e18120b03000000000000000000000000000000000000010911181f262c31363a3e4143454647484848474644423f3c38342f2d34393c3d3d3d3d3d3d3d3d3c38332c241a10060000000000010c17222c37414b555f68717a828a91979da2a5a09c99979594949596989b9ea3a49f9a948d867e766d645b51483d33281e1308000000000000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a0000000008131f2b37424d58636e78828b949ba1a6aaa6a19e9b99989898989a9c9f98918980766d7783909da8a4978a7d7164574a3e3124170b0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0013202c3946535f6c7986939696969694887b6e6154483b44515d6a77849196969696968a7d7063564a3d3023170a00101c2936434f5c697683909ca9b4a89c8f83776a5e52463b2f251f1f21232423211c1710080000000000000c1824303c48545f6b76818b959ea6aca49d96918c8884807d797673706d6a66635f5b57534e49443e38312a221f1b160f0800000000000a16212c3740484f5253535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353524e4840362b201509000000000000070e14191c1e1e1e1e1e1e1e1e1e1c19140d0600000000000000000000000000030a11171b1d1e1e1e1e1e1e1e1e1e1b17120c04000000000000000000000000000000000000000000000000000000000815212d39444f586063636363635f584e4e555a5b5b5b5b5b5b5b5b5e61636362605d58534c453d342b21170d030000000000000000000000000000000000000f1c2834404b56616b76818b969a9a9a9a91877c71665c51463b31262324242424242423201c1710080a141f2a353f4a55606a75808b969a9a9a9a92877d72675d52473c3023170b0013202c3946535f6c798693a0acada09386796d6053463a2d20130f0f0f0f0d090500060a0d0f0f0f0f15212e3b4854616e7b8894a1aeaa9e9184776a5d5144372a1e1100101d2935414c57616a737c858e9289807d8a95887b818a948c837a71685f554a3f33271a0e0013202c3946535f6c798693a0acb9b9b9b9b9b9b9b9b9b9b9b9aca09386796c5f5346392c2013000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004070808080808080808080705010000000000000000000000000000000000080f171e252b31363b4044484b4e50525354555555545352514f4d4a47433f3a352f29231c150d06000000000000000000000000000000000000000109111920262d33383d4246494c4f515253545555545453514f4d4a47433f3a35302a231c150e0600000000000000000000000000000000010a131b232a31373d42464a4d505253545555545453514f4c48443f3a363e45494a4a4a4a4a4a4a4a48443e362c22180c010000000007121d28333e49535d67717a838c949ba2a7a09a94908c8a88888888898c8e92979ca3a59f98908880766d63594f453a2f24190e030000000000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a000000000c1824303c47535e6a75808a949da5ada8a19a95918e8c8b8b8b8c8d9094989a92897f757784919eaaa4978a7d7063574a3d3024170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0013202c3946535f6c79868a8a8a8a8a8a887b6e6154483b44515d6a77848a8a8a8a8a8a8a7d7063564a3d3023170a00101c2936434f5c697683909ca9b6ab9f93877b6f63574c41362e2c2c2d3031302d28221a120800000000020f1b2834404c5864707c87929da7ada39a928b85807b7874706d6a6764605d5a56534f4b47423e383432312f2e2b27211911080000000005101a252e373e43464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464645433d362e241a0f0400000000000911192025292b2b2b2b2b2b2b2b2b28241f1810070000000000000000000000030c151c22272a2b2b2b2b2b2b2b2b2a28231d160e050000000000000000000000000000000000000000000000000000000b1724303d4955606a6f6f6f6f6f6a6055494a4e4e4e4e51575c62676b6e6f6f6f6c69645e574f463d33291f1409000000000000000000000000000000000000121e2b3844505c68727d888d8d8d8d8d8d8b80756a5f554a3f352a2c2f313131313131302d28211a130c0e18232e39434e59646e79848d8d8d8d8d8d8d84796e64584c3f33261a0d0013202c3946535f6c798693a0a2a2a09386796d6053463a2d201c1c1c1c1b1915100b11161a1c1c1c1c1c212e3b4854616e7b8894a1a2a29e9184776a5d5144372a1e11000d1924303b454e57616a737c858e9289808a9588818a948c837a71685f564d43392e22160a0013202c3946535f6c798693a0acacacacacacacacacacacacacaca09386796c5f5346392c2013000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001070c101314151515151515151514110d0802000000000000000000000000000009111a212930363c42474c5054575a5c5e606161616161605f5d5b5956534f4b46413b352e271f170f070000000000000000000000000000000000020b131b232a31383e44494e5255595b5d5f6061616161615f5e5c5957534f4b46413b352e271f180f070000000000000000000000000000000a131c252d353c42484d5256595c5e6061616161615f5d5b5854504b453f4850555757575757575757554f483e34291e1206000000010c18232f3a45505a656f79838c959ea6a59d958f8984807d7b7b7b7b7d7f82868b9198a0a8a29a92897f756b61564c41362b1f14080000000000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000003101c2834404c58646f7b86919ca6afa89f968f898582807e7e7e7f8184878c929991877d7784919eaba3978a7d7063574a3d3024170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0013202c3946535f6c787d7d7d7d7d7d7d7d7a6e6154473b44515d6a767d7d7d7d7d7d7d7d7b6f6356493d3023160a00101c2936434f5c697683909ca9b0a7a0978b8074685d5348403a38393a3d3e3c39332c241a100600000005121e2b3743505c6975818d98a4aea59b9188817a746f6b6864615d5a5754514e4a47434345454442413f3d3c3a37322b231a11060000000009131c252c323739393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393936322c241b1208000000000008121b232b313538383838383838383735302a221a1006000000000000000000010c151e272e3337383838383838383837342e2820170d0300000000000000000000000000000000000000000000000000000c1825323f4b5865717c7c7c7c7c7164584b3f434950565c62686d73777a7c7c7b79756f6861584f453b31261b10040000000000000000000000000000000000131f2c3946525f6c79818181818181818181796e63594e43382e32383c3e3e3e3e3e3e3c39332c251d160f111c27323c47525d67727d81818181818181818074675a4d4134271a0e0013202c3946535f6c798693959595959386796d6053463a2d29292929292825211b161d22262829292929292e3b4854616e7b8894959595959184776a5d5144372a1e110008131f29333c454e57616a737b858e928b8f978d8b938c837a71685f564d443b31271c11060013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09386796c5f5346392c201300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030b12181d20212121212121212121201e19140d0500000000000000000000000009121b232b333a41484d53585c606467696b6c6d6e6e6e6e6d6c6a6865625f5b56514c463f38312921191007000000000000000000000000000000020b141d252d353c43494f55595e6265686a6c6d6e6e6e6e6d6c6a6866635f5b57524c464039312a211910070000000000000000000000000008121c252e373f464d53595e6266696b6c6d6e6e6e6d6c6a6764605c57514a515a616363636363636363615a50453a2e22160a00000006121d2934404b56616c76818b959ea7a59c938b847d7874716f6e6e6f7073767a80878e969fa8a49b91877d73685d52473c3025190e0200000000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000007131f2c3844505c6874818c98a3aeaaa0968d857e7975737271717274777b81878f968f847985929eaba3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00121e2b3744505c676e70707070707070706f685d514539424e5a656e70707070707070706f695f53473b2e22150900101c2936434f5c697683909ca9a99e959190857a6f645a514a46454647494a49443e362c22170c0100000713202d3946535f6c7885919da9aa9e93897f766f69635f5b5854514e4b4845413e41494f5252504f4d4c4a4947433d352c22180d02000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a26211a12090000000000040f19242d353c42444545454545454544413b342c22180d02000000000000000008131e2731383f43454545454545454543403932291f150a00000000000000000000000000000000000000000000000000000b1825323e4b5864717d8989898073675b4f4a4f555b61676d73797e838789898885817a736a61574d42372c21150a0000000000000000000000000000000000121f2b3844515d687173737373737373737371675c52473c32343d44484a4a4a4a4a4a49443e362f2820191215202b36404b56616b737373737373737373736f64584c4033261a0d0013202c3946535f6c798688888888888886796d6053463a36363636363635322d2620282e32353636363636363b4854616e7b8888888888888884776a5d5144372a1e1100020d17212a333c454e576169727b858e979a9f99958c837a71685f564d443b32291f150b000013202c3946535f6c798693939393939393939393939393939393939386796c5f5346392c2013000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d151d23292c2e2e2e2e2e2e2e2e2e2d2a251f170f060000000000000000000009121b242d353d454c53595e64686c70737678797a7b7b7b7a79787774726f6b67625d57514a433b332b2219100600000000000000000000000000010b141d262f373f474e545b60656a6e717476787a7b7b7b7b7a797775726f6b67635d57514a433b332b221a1007000000000000000000000005101a242e37404951585f656a6e727577797a7b7b7b7a797674706c68625c5558636c70707070707070706c62564a3e3225190c0000000b17232e3a45515c68737d88939da7a79d938a8179726c67646261616263666a6f757c848d97a1aba3998f847a6f63584d41362a1e130700000000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a0000000a16222f3b4854606c7985919da9afa4998e847b736d696665646466686b70767d858d968b8085929faca3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000f1c28343f4a555d626363636363636363635e564c41353d49535c626363636363636363635f574d42372b1f130600101c2936434f5c697683909ca9a6998d848c8b81766c635c565352525355575550483e34291d120600000815222e3b4854616e7a8794a0ada6998e82776d645d58534f4c4845423e3b38353f49535b5f5f5d5b5a585755534f473e342a1e130700000000010910161a1e1f202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201f1e1a150f080000000000000915202b353f474d5151515151515151514d463e342a1f130800000000000000030e19252f39424a4f5151515151515151504b443b31261b1004000000000000000000000000000000000000000000000000000a1723303d4956636f7c89959083776b6057565a60666c72797f858a8f93959694918c857c73695f54493d32261a0f0300000000000000000000000000000000101c2835404c576066676767676767676767655f554b4035323d464e54575757575757554f484139322b241c1519242f39444f596266676767676767676767645d53483c3024170b0013202c3946525f6c787b7b7b7b7b7b7b7b786c60534642424242424242413d38302a32393f42424242424242424754616d797b7b7b7b7b7b7b7b766a5d5044372a1e110000060f18212a333c454e576069727b858e979f958c837a71685f564d443b322920170d04000013202c3946535f6c798686868686868686868686868686868686868686796c5f5346392c20130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010b151f272f34393b3b3b3b3b3b3b3b3b3936302921180e03000000000000000008121b242e373f474f575e646a6f74797c808284868788888887868583817e7b77736e68625c554d453d342b22180e0400000000000000000000000009131d262f38414951585f666c71767a7e8183858687888888878684827e7b78736e69635c554d453d342c22190f05000000000000000000010c17222c364049525b626a70767a7e82848687888888878583807d78736d675f5b67747d7d7d7d7d7d7d7d7366594d4033261a0d000004101c27333f4b56626d79848f9aa5aba0968b81786f67615b5856545455575a5e636a727b858f99a4aba1968b8075695e52473b2f23170b00000000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a0000000c1825323e4b5763707c8995a1adaa9e93877c7269615c5a585758595b5f646b727b848e928787939faca3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000b17232e39434b5256565656565656565656534c443a2f37414a5155565656565656565656534d453c31261a0f0300101d2a3643505d697683909ca9a5998c7f8892887e756d6762605f5f606264615a50453a2e22160900000916222f3c4855626f7b8895a2aea3968a7d71655b534c47433f3c3835322f2c3844505b656b6b6a68676563625f5950463b2f23170b000000000000050a0e11131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313110e0a04000000000000000e1a26313d4751595e5e5e5e5e5e5e5e5d5850463b3024190d0200000000000008141f2a36414b545b5e5e5e5e5e5e5e5e5c564d43382c201408000000000000000000000000000000000000000000000000000815222e3b4754616d7a869394887d72696463666b71777d848a90969b9fa2a3a19d968e857b70655a4e43372b1f1307000000000000000000000000000000000c18242f3a454e55595a5a5a5a5a5a5a5a5a59544d43392f38444e5860646464646464615a534b443d352e271f181d28333d4750575a5a5a5a5a5a5a5a5a5a58534b41362b20140800121e2b3743505b666d6f6f6f6f6f6f6f6f6d665c504f4f4f4f4f4f4f4f4e49423a323c444a4e4f4f4f4f4f4f4f4f515d676e6f6f6f6f6f6f6f6f6d64594e4235291c10000000060f18212a333c454e576069727b85929c8f837a71685f564d443b322920170e05000000131f2c3946525f6b767979797979797979797979797979797979797979766b5f5246392c1f13000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121d273139404547484848484848484846413b332a20150a0000000000000005101a242d374049515961686f757b8085898c8f919394949594949392908e8b87837f7a746d665f574f463d342a20160c010000000000000000000007111b252f38414a535b636a71777d82868a8d909293949595949392908e8b88847f7a746d675f574f473e342b21170d03000000000000000007121e29333e48525b646d747b81868b8e9192949495949392908d89847e78716a616875828a8a8a8a8a8a7e7265594c3f3326190d00000814202c3844505c67737e8a95a1aca69a8f84796f665d56504b494848494a4e52586069737d88939ea9a89d91867a6f63574b3f33271b0f03000000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a0000000e1b2734404d5966737f8c98a4b1a69a8e82766b6057504d4c4b4b4c4f53596169727c8690929299a3afa3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0006121c2731394146494c4c4c4c4c4c4c4c4a47423a32282f384045494b4c4c4c4c4c4c4c4a47423c332a1f15090000101d2a3643505d697683909daaa5988c7e848f91888078736e6c6b6c6d6e716c62564a3e3125180c00000916222f3c4955626f7c8995a2aea295887b6e625549413b3733302c2a2b2e333c4854606c777876757372706e6b62574c3f33271a0e010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111d2a36424e59636a6b6b6b6b6b6b6b6962584c41352a1e13070000000000020e1925303c47535d666b6b6b6b6b6b6b6b675f54493d3024180b000000000000000000000000000000000000000000000000000613202c3945525e6b778490998e847a74707072767c83898f959ba1a5a1a0a0a1a5a0978d82766b5f53473b2f23170b0000000000000000000000000000000007131e29333c44494d4d4d4d4d4d4d4d4d4d4c49433b322f3c4854606a7071717171716c645d564e474038312a231b212c353e454b4d4d4d4d4d4d4d4d4d4d4c4741392f251a0f03000f1b27333f4a545c616262626262626262615c54595c5c5c5c5c5c5c5c5a544c423a444e565b5c5c5c5c5c5c5c5b57555d616262626262626262615b52483d3125190d0000040d161f28313a434c555e677079828b9591938980776e655c534b42392f261e150c020000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b645a4f43372a1e1100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c18242f39434b51545454545454545454524d453c31261b0f040000000000020d17212c353f49525b636b737a81878c9195989b9d9fa0a1a2a1a1a09e9c9a97948f8a857f78716961584f463c32281e1308000000000000000000030e18232d37414a535c656d747c82888e92969a9c9ea0a1a1a2a1a09f9d9b9894908b857f787169615850463d33291f140a00000000000000010d18242f3a454f5a646d767e868d92979a9d9fa0a1a2a1a09e9c9995908a837b736b6976828f979797978b7e7165584b3e3225180b00000b1824303c4854606c7884909ba7aca094897d72685d544b443f3c3b3b3c3e42474e57616b76818d98a4aea3978b8074685c5044372b1f1307000000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a000000101c2936424f5b6875828e9ba7afa2968a7d7165594e45413f3e3e4043484f57606a747f8a959ea3abb0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000b17232e39444d5458595959595959595650473d32272d38424b5358595959595959595751493f34291d12060000111d2a3744505d6a7783909daaa4988b7e7f8b97918a847e7b797879797b7d7266594c403326190d00000915222f3c4855626e7b8895a1aea295887b6e6255483e3a3836363636383a3f454e5864707c858382807e7d7b74685b4e4235281c0f0200000000000004080b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0b080400000000000000121f2c3845525e6a757878787878787874695d52463b2f24180d010000000008131f2a36414d58636f78787878787878787165594c3f3326190d0000000000000000000000000000000000000000000000000004111d2a36434f5c6874818d99968d85807d7c7e82888e949aa0a39e9895939395989e9e93877b7064584c3f33271b0e02000000000000000000000000000000020c17212a32383d40404040404040404040403d383129313e4a5764707c7d7d7d7d7d766f676059514a433c342d261e232c343a3e404040404040404040403f3c362f261d130800000b17222d38424a5155555555555555555555515c646969696969696969665e53483f4b566067696969696969696862585255555555555555555554504940362c20150900010b161f28313a434c555e677079828b948b858d928981776e655d544b423930271e140900000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5a52483e32261a0e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004111d2935404b555c6161616161616161615e574d43382c201407000000000009141e29333d47515b646d757d858c92989da1a5a39f9d9b9a9a9a9a9b9da0a3a3a09b96908a837b736a61584e443a2f251a0f0400000000000000000a151f2a343f49535c656e777f868d94999ea2a4a09d9a999898999a9c9fa2a4a09b96908a837b736a62584f453b31261c110600000000000006121e2935404b56616c76808890989ea3a7a9a5a19f9d9c9c9c9c9ea09b958d857d746a7683909da4a4978a7d7164574b3e3124180b00020f1b2734404c5864707c8994a0aca79b8f84786c61564c423933302e2e2f32363c454f5a65707c88939faba89c9084786c6054473b2f23160a000000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a000000111e2a3744505d6a7683909ca9aca093877a6e6155493d3432313233373d454e58626d7884909ba7b3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000f1b28343f4b555f656666666666666661594f44382c323e49545d6466666666666666625b51453a2e2215090000111e2a3744505d6a7784909daaa4978b7e7a86919c958f8b878685858688807366594c403326190d00000814212e3b4754616d7a8693a0aca396897d716459504a47444343424344474a5057606a75818c908e8d8b898074675b4e4235281b0f0200000000030a101417191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191714100a040000000000121f2c3945525f6b77838585858585857a6e63574c4035291e1307000000020d1924303b47525e6975808585858585857d7266594c4033261a0d00000000000000000000000000000000000000000000000000010e1b2733404c5864717d89949f97908c8a898b8e93999fa59e98928d888686888d939b988c8074685b4f43362a1e110500000000000000000000000000000000050f1820272d313334343434343434343433312c2624313e4a5764717d878a8a8a888179726b635c554d463f3730292122292e323434343434343434343433302b251d140b01000006111c26303840454848484848484848484a56626e75757575757575757065594c434f5c687275757575757575746a5e5248484848484848484848443f372e251a0f040007121d28313a434c555e677079828b948b827a848d938a81776f665d544b423930261b1005000a16212c3740484f525353535353535353535353535353535353535353524f4840372c21160a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713202d3945515d676d6e6e6e6e6e6e6e6e695f54483c3023170a00000000040f1a25303b454f59636d767f878f969da3a7a19b9793908e8d8d8d8e8f9194979ca1a7a29b958d857c736a60564c41362b20150a0000000000000005101b26313c46515b656e77808991989fa5a39d9894908e8c8c8c8c8d8f92969ba0a6a29b958d857c746a61574d42382d22170c0100000000000a17222e3a46515d68737d88929aa2a9aba49e999592908f8f8f909194979c978f867c737784909daaa4978a7d7064574a3d3124170b0005121e2b3743505c6874818d99a5afa3978b7f73675b50453a302823222123252a333d48545f6b77838f9ba7aca094887c7063574b3f3226190d000000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a000000121f2b3845525e6b7884919eabaa9e9184786b5f5246392d262525272b333c46515c67737f8b97a3afb0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0000111e2b3744505c6770737373737373726b6054483c2f35424e5a666f737373737373736d62564a3e3124180b0000111e2b3744515d6a7784919eaaa4978a7d75808c97a09b9794929292938c807366594c403326190d00000613202c3945525f6b7884909da9a5998d81756b625b565351504f4f505153575b6169727c86929c9b9995897d7064584b3f33261a0d01000000050d151b20242526262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262524201c150e0600000000111e2a37434f5b66727d89929292928b8074685d51463a2f23180d01000008131e2a35414c58636f7a86919292928f83786c61564a3e3125180c00000000000000000000000000000000000000000000000000000b1724303c4854606c78848f9aa19c989696979a9fa4a099938d87817c79797c8189929c9084776b5f5246392d2014070000000000000000000000000000000000060e161c2125272727272727272727272624211b23303c4955616c757e889197928b847c756e665f585049423b332c251e22252727272727272727272726241f1a130b02000000000a141e262e34393b3c3c3c3c3c3c3c3e4b5764717e8282828282828173675a4d44505d6a7782828282828282796d6053463c3c3c3c3c3c3c3c3b38342d251c130800000c18232f39434d555e677079828b948b8279717a848d938a81786f665d544b42372c21150a0005101a252e373e4346464646464646464646464646464646464646464646433e372e251a1005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000815222e3b4854616d797b7b7b7b7b7b7b7a7164584b3e3125180b000000000a15202c37424c57616b757f889199a1a8a39c958f8a878482818080818284878b90959ca3a69f978e857c72685d53483d32261b10040000000000000b16212d38434d58626d76808a929ba3a8a099928c888481807e7e808183868a8f959ca3a69f978f867c73695f544a3f34291d120700000000020e1b27333f4b57626e79848f9aa3acaba29a938d8986848282828385878b9096988e857a7784919eaaa4978a7d7063574a3d3024170a000814212d3a46535f6b7884919da9aca093877b6e62564b3f33281e1715151619212c37434f5b67737f8b98a4b0a4988c8073675a4e4135291c10030000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a000000131f2c3946525f6c7985929faca99c8f8376695d5043372a1e18181a212a343f4b57626e7b87939facb0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0001121f2c3845525f6b788080808080807d7063574a3d303643505d69768080808080807e7265594c3f3226190c0000111e2b3844515e6b7784919eaba3968a7d707a85909aa4a3a19f9f9f998c807366594c403326190d000004111e2a37434f5c6874818d99a4a99d92877d736c6662605e5d5c5c5d5e6063676c737b848e98a3a79c9085796d6154483c3023170b000000050e171f262c3032323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232302c2720180f050000000e1b27333e4a55606c77838e9a9e9c9185796e62574c4035291e120700020d1924303b46525d6974808b979e9e94897d72675b5044392d21150900000000000000000000000000000000000000000000000000000814202c3844505b67727d88929ba4a5a3a3a4a5a09b958e88827b75706d6d7077808a9593877a6e6155483c2f23160a000000000000000000000000000000000000040b1015181a1a1a1a1a1a1a1a1a1a1a181514212d3945505a636c767f88919b958e878078716a625b544c453e362f2820191a1a1a1a1a1a1a1a1a1a1917130e08010000000000020c141c23292d2f2f2f2f2f2f2f313e4b5764717e8b8f8f8f8f8d8173675a4d44505d6a77848f8f8f8f8f86796d6053463a2f2f2f2f2f2f2f2e2c28221b130a010000101c2834404b555f677079838c948b82797068727b848d938a81786f665d54493e32261a0d000009131c252c32373939393939393939393939393939393939393939393937322c251c130900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000815222e3b4855616e7b888888888888887e7165584b3e3225180b000000040f1b26323d48535e69737d87919aa3aba299918a847e7a77757373737475787b7f848a9199a1a9a0978e84796f64594e43372c201509000000000005101c27333e49545f6a747e89929ca4a89f968e87817b78757372727374767a7e848a9199a2a9a1988e857b70665b50453a2f23180c0000000006121e2b37434f5b67737f8a96a1acada2999088817c797776757576787b80858b92968c827885929eaba3968a7d7063564a3d3023170a000a1723303c4955626e7b8794a0aca99c9084776b5f52463a2e22170c0808090f1b26323e4b57636f7c8895a1aea89b8f82766a5d5144372b1e12050000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca89b8e8275685b4f4235291c0f0b0f18232e3a46525e6b7784909ca9b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0004121f2c3945525f6b78858c8c8c8c8a7d7063574a3d313743505d6976838c8c8c8c8c7f7265594c3f3326190c0000121f2b3845515e6b7885929ea2a296897c6f747e89929ba2a7aaaca6998c807366594c403326190d0000020e1b2734404c5864707c88939ea9a3998f867e77726f6c6a696969696a6c6f73787e858d96a0aaa1968b8074685c5044382c2014070000010c16202931383c3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3d38322a21170d0200000a16222d38444f5b66727d89949fa1968b7f73685c51453a2f23180c0107131e2a35414c57636e7a85919ca59a8f83786c61564a3f33281d1105000000000000000000000000000000000000000000000000000004101c27333f4a56616b76808992999d9f9f9d9a958f89837d77706a646060656e798490968a7d7064574b3e3225180c000000000000000000000000000000000000000005090c0d0d0d0d0d0d0d0d0d0d0d0b08111c28333e48515a646d767f89929b99918a837b746d655e574f484139322b22190f0d0d0d0d0d0d0d0d0d0b07030000000000000000020b12181d2022222222222224313e4b5764717e8b989c9c9a8d8173675a4d44505d6a7784909c9c9c9386796d6053463a2d22222222222222201c17110901000000121f2b3844505c677179838c948b827970676069727b848d938a81786f655a4e4235291c100000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a26211a130a0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000815222e3b4855616e7b8894949494948b7e7165584b3e3225180b0000000915202c37434e5965707a858f99a3aca29990878079736e6b6867666667696b6f737980878f98a1a9a0968b81766b5f54493d31251a0e02000000000a15212d38444f5a66717b86909aa4aaa0968d847c75706b6866656566676a6e72787f879099a3aaa0978d82776d62564b4034291d11050000000915222e3a47535f6b77848f9ba7b1a69b90877e76716d6a696868696c6f737980889094897e85929eaba3968a7d7063564a3d3023170a000c1926323f4b5864717d8a97a3afa69a8d8174685b4f43362a1e12060000000a16222f3b4754606d7986929fabab9e9285786c5f53463a2d2014070000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79b8e8174675b4e4134281b0e0206121e2a36424f5b6874818e9aa7b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0006131f2c3946525f6c7986929999978a7d7164574a3e313744505d6a7784909999998c807366594c403326190d0000121f2c3945525f6b78859295959595887c6f6c76808990969b9d9fa0998c807366594c403326190d0000000b1824303c4854606b76828d97a1aaa1988f89837e7b79777675757677797b7f83898f979fa8a3998f84796e63574c4034281c1004000007131e28323b43484b4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c49433c33291f1408000005111c27333e4a55606c77838e9aa59c9085796e62574b4034291d12060d18242f3b46525d6974808b97a2a094897d72675b5044392e22170b000000000000000000000000000000000000000000000000000000000b17222e39444f5a646e7780878d919293918e89847e78726c655f5954545c6874808c938c7f7266594d4033271a0d0100000000000000000000000000000000000000000000000000000000000000000000000c17222c363f48525b646d768089929b9c948d867e777068615a534b443d342b21160b000000000000000000000000000000000000000000070c111415151515151824313e4b5764717e8b98a4a79a8d8173675a4d44505d6a7784909da9a09386796d6053463a2d2015151515151513100b06000000000013202c3946535f6c79838c948b827970675e576069727b848d938a81766a5d5044372a1d11000000010910161a1e1f20202020202020202020202020202020202020201f1e1a161009010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000815222e3b4855616e7b8895a1a1a1988b7e7165584b3e3225180b0000010d1925313d48545f6b76818c97a1aba49a90877e756e67625e5b5a595a5b5c5f63686e757d868f99a3a89d92877c7065594e42362a1e1105000000020e1a26323e4955606c77828d98a2aca3988e847a726b645f5c595858595b5e62676d757e87919ba6a99e94897e73685c5145392d22160a0000000b1824313d4a56626f7b8794a0acaba094897e746c65605e5c5b5c5d5f63686e767e8790908585929faca3968a7d7063564a3d3023170a000e1b2734414d5a6773808c99a5b1a4988b7e7265594c4033271a0e0200000006131f2c3845515e6a7784909da9ada094877b6e6155483c2f2216090000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01020e1a2733404d5966727f8c98a5b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000613202c3946535f6c7986939fa4978b7e7164574b3e313744515d6a7784919da6998d807366594d4033261a0d000013202c3946535f6c79868888888888887b6e656e777e858b8e919293928c807366594c403326190d0000000814202c37434f5a65707b858f98a0a8a19a948f8b888584838282838486888b8f949aa1a9a29a91877d73685d52463b2f23180c0000000c18242f3a444d5458595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595958554e453b3025190d0100000b16222d38444f5b66727d89949fa1968a7e73685c51453a2e23170c131e2935404c57636e7a85919ca59a8f83786c61554a3f33281d11060000000000000000000000000000000000000000000000000000000006111d28333d48525c656e767c8184868684827d78736d67615a544e484b5764707d8686868174685b4e4235281c0f02000000000000000000000000000000000000000000000000000000000000000000000005101a242d364049525b646d768089929c9f989089827a736c645d564e463d33281c1105000000000000000000000000000000000000000000000407080909090b1824313e4b5764717e8b98a4a79a8d8173675a4d44505d6a7784909daaa09386796d6053463a2d20130909090908070400000000000000121f2c3845515e69737c868b827970675e554e576069727b848d847b71675b4f4336291d100000000000050a0e1113131313131313131313131313131313131313131313110e0a0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000006121e2a36424d5965707c87939ea8a89d93887e756b635c56524f4d4d4d4e5053575c636b737d87919c9d9a968d82766a5e5246392d20140700000006121e2b36424e5a66717d88939fa9a79c91867c72696059534f4d4c4c4d4e51565c636c757f8a95a0aba59b8f84796d61564a3e32261a0e0200000d1a2733404c5965727e8b97a3b0a79b8f83786d625a54514f4f4f5053575d646c757e88938e8e96a2aea3968a7d7063564a3d3023170a00101c2936424f5c6875828e9ba8afa296897d7063574a3d3124180b0000000004101d2936424f5c6875828e9ba8afa296897c7063564a3d3024170a0000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000c1825323e4b5864717e8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000713202d3a4653606d798693a0a4988b7e7165584b3e323844515e6b7784919ea69a8d8073675a4d4034271a0d010013202c3946525f6c777b7b7b7b7b7b7b796d61656d747a7e828486868583807366594c403326190d000000030f1b27323e49545f69737d868e969da3a59f9b97949290908f8f90909294979ba0a5a49e9790887f756b61564c40352a1e1307000000101c2834404c565f6565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656560574d41362a1d1105000005111c27333e4a55606c77838e9aa59b9084796d62564b3f34281d1118242f3a46515d6874808b96a2a094897d72665b5044392e22170b0000000000000000000000000000000000000000000000000000000000000b16212c36404a535c646b71757879797875716c67615c554f49433d4855616d787979797973675b4e4235281b0f0200000000000000000000000000000000000000000000000000000000000000000000000008121b242e374049525b656e77808a939ca29b938c857d766f6760584f44392d211508000000000000000000000000000000000000000000000000000000000b1824313e4b5764717e8b98a0a09a8d8173675a4d44505d6a7784909da0a09386796d6053463a2d20130700000000000000000000000000101d2935414d58616a737c827970675e554c454e576069727b847b72695f564b3f33271a0e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000a16222e3a46525e6a76818d99a4aea2978c81766c625a524b46424140404143464b5159616b757f8a94918d8a86837a6e6154483b2e2115080000000a16232f3b47535f6b76828e99a5ada2968b80756a60574e4843403f3f4042454a515a636d78838f9aa6aca1958a7e72665a4e42362a1e120600000f1c2835424e5b6874818d9aa6b0a3978b7e73675b51484543424244474b525a636c76818c979aa0a8b0a3968a7d7063564a3d3023170a00111e2a3744505d6a7683909da9aea194887b6e6255483c2f22160900000000000e1b2734414d5a6773818d9aa6b1a4978b7e7164584b3e3225180c0000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1724313d4a5763707d8a97a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000714202d3a4753606d798693a0a5988b7e7165584b3f323845515e6b7784919ea79a8d8173675a4d4134271a0e0100121e2b37434f5b666d6e6e6e6e6e6e6e6d675c5b62696e72757779797877746e63574b3e3225190c000000000a16212c37424d57616b747c848b92979ca0a3a3a19f9d9c9c9c9c9d9fa1a4a4a19d98938d867e766d63594f453a2f24190d02000000121f2b3844515d6871727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727271695e5246392d2013070000000b16222d38444f5b66727d89949fa1958a7e73675c5045392e22171e2935404c57626e7985909ca59a8f83786c61554a3f33281c110600000000000000000000000000000000000000000000000000000000000005101a242e38414a52596065686b6c6c6b6965615c56504a443e373945515c666c6c6c6c6c6961574b3f33261a0d010000000000000000000000000000000000000000000000000000000000000000000000000009121b252e374049535c656e77818a939ca09e978f888179726a6155493d3124180b000000000000000000000000000000000000000000000000000000000b1824313e4b5764717e8b939393938d8173675a4d44505d6a7784909393939386796d6053463a2d201307000000000000000000000000000d1925303b464f58616a747870675e554c433c454e5760697279726960574d44392e23170b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0d0f0f0f0f0f0f0d0a0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00010d1926323e4a56626e7a86929ea9a99d91867a6f655a5048403a3634333335373a40474f59636e79848885817e7a77736a5f53463a2d2114070000010e1a26323f4b57636f7b87939faaa89d91857a6e63584e453d373432323335393f48515c67727d8995a1ada69a8f83776b5f52463a2e2215090000111d2a3743505d6976838f9ca9ada094877b6f62564a3f38363536373b4048515a656f7a86919da9b1b0a3968a7d7063564a3d3023170a00121f2b3845515e6b7784919eaaada093877a6d6054473a2e21140800000000000d192633404c5966727f8c99a5b2a5988c7f7265594c3f3326190c0000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000714202d3a4753606d7a8794a0a5988c7e7265584c3f323845515e6b7885929ea79a8e8174675a4d4134271a0e01000f1b27333f4a545c6161616161616161615d5551575d6266696b6c6c6c6a68645c52473b2f23160a0000000005101b26313b454f59626a727980868b909497999b9d9e9f9fa09f9e9d9c9a9794918c87827b746c645b51483d33281e13070000000013202c3946535f6c797f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7a6d6154473a2e21140700000005111c27333e4a55606c77838e9aa59b8f84786d61564a3f33281c232f3a46515c68737f8a96a19f94897d72665b5044392d22170b000000000000000000000000000000000000000000000000000000000000000008121c262f3840484e54595c5e5f5f5e5c5955504b453f39332c34404a545b5f5f5f5f5f5e584f453a2f23170a00000000000000000000000000000000000000000000000000000000000000000000000000000009131c252e37414a535c656f78818a9393939393928b847c7265584c3f3226190c000000000000000000000000000000000000000000000000000000000b1824313e4b5764717e8686868686868173675a4d44505d6a7784868686868686796d6053463a2d2013070000000000000000000000000008141f2a343d464f58626a6c675e554c433a333c454e5760686c6860574e453b32281d1206000000000000000000000000000000000000000000000000000000000000000000000000000000000000040b11161a1c1c1c1c1c1c1a16110b040000000000000000000000000000000000000000000000000000000000000000000000000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0004101d2935424e5a66737e8b97a3afa4988c8175695e53483f362e2a272627282a2f353d47515c68737f7c7875716e6a6761584e42372a1e1205000004111d2a36424f5b6773808b98a3afa4988c8074695d52473c332b27262527292e363f4a55616d7884909ca9ab9f93877b6f62564a3d3125180c0000121e2b3845515e6b7784919eaaab9e9285786c5f53463a2e2929292b2f363f48535e6975818c98a4b0b0a3968a7d7063564a3d3023170a00121f2c3945525f6c7885929fabac9f9286796c5f5346392d20130600000000000c1825323f4b5865717e8b98a5b1a6998d807366594d4033271a0d0000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000714212e3a4754616d7a8794a1a5998c7f7265594c3f323845525f6b7885929fa79b8e8174675b4e4134281b0e01000b17222d38424a51545555555555555554514b464c52565a5c5e5f5f5f5e5b58524a40352a1e1307000000000009141f29333d47505860686f757a8084878a8d8f90929292939292918f8d8b8885817b767069625a52493f362c21170c010000000013202c3946535f6c79868c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c877a6d6154473a2e211407000000000b16222d38444f5b66727d89949fa095897e72675b5044392d222934404b57626e7985909ca59a8e83786c61554a3f33281c11060000000000000000000000000000000000000000000000000000000000000000010a141d262e363d43484d5052535352504d49443f3a342e28232e38424a505253535353514d463d33291e1206000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c252f38414a535d666f788186868686868686867f7265594c3f3226190c000000000000000000000000000000000000000000000000000000000b1724313e4a57637079797979797979797266594d43505c697479797979797979766b5f5346392d20130600000000000000000000000000020d18222b343d4650585e5f5c554c433a312a333c454e565d5f5d574e453c332920160b000000000000000000000000000000000000000000000000000000000000000000000000000000000000050e161c222628292929292826221c160e0500000000000000000000000000000000000000000000000000000000000000030406070808080707050815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000713202c3845515e6a76838f9ba7aca094887b7064584d42372d241d1b1a1a1b1e242b35404b57636d726f6c6965625e5b564f463c31261a0e0200000714202d3945525e6a77838f9ca8ada194887c7064584c41352a211b19191a1d242e3944505c6874818d99a5afa3978b7e7266594d4134281b0f0200121f2c3945525f6c7885929faba99d9083766a5d5144372b1e1c1c1e242d37414d5864707c8894a0adb0a3968a7d7063564a3d3023170a0013202c3946535f6c7986929facac9f9285786c5f5245392c1f120600000000000b1824313e4b5764717e8b98a4b1a79a8d8173675a4d4034271a0e0000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000815212e3b4854616e7b8794a1a6998c7f7366594c40333946525f6c7985929fa89b8e8175685b4e4235281b0f020006111c262f383f4548484848484848484845403b41464a4d5052525352514f4c4740382e24190e020000000000030d17212b353e464e565d64696f73787b7e8182848586868686858483817e7c7874706b655f58504840372d241a0f05000000000013202c3946535f6c7986939999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999994877a6d6154473a2e2114070000000005111c27333e4a55606c77838e9aa59a8f84786c61554a3f33282f3a45515c68737f8a96a19f94897d72665b5044392d22170b00000000000000000000000000000000000000000000000000000000000000000000020b141c242b32383c40434546464543413d39332e28231c1c2630383f43464646464645413c342b21170c0100000000000000000000000000000000000000000000000000000000000000000000000000000000010a131d262f38414b545d666f787979797979797979797165584b3f3225190c000000000000000000000000000000000000000000000000000000000916222f3b47535e676c6c6c6c6c6c6c6c6960554a404c58626a6c6c6c6c6c6c6c6b645a4f43372b1e12050000000000000000000000000000061019222b343e464d5253504b433a3128212a333c444c5153514c453c332a21170e040000000000000000000000000000000000000000000000000000000000000000000000000000000000040e1720272e32353636363635322e2720170e04000000000000000000000000000000000000000000000000000003070a0d0f1113141415151413121015222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000916222f3b4854616d7986929eaba99c9084786b5f53473c30252222222222222222232f3b46515b626563605c5955524e4b453d342b2015090000000a16232f3c4855616e7a86939fabaa9d9185786c6054473b3024190f0c0c0d121c2834404c5864707d8996a2afa79a8e8275695c5043372a1e11050013202c3946535f6c7986929faca89b8f8275685c4f4236291c100f121b25303c4854606c7885919daab0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0acac9f9285786b5f5245382c1f120500000000000b1724313e4a5764717d8a97a4b1a79a8e8174675a4d4134271a0e0000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000815222e3b4855616e7b8894a1a6998c807366594c40333946535f6c7986929fa89b8e8275685b4e4235281c0f0200000a141d262e34383b3b3b3b3b3b3b3b3b393530353a3e41434546464544423f3c362e261c120700000000000000060f19232c343d444c52585e63676b6f71747577787979797978777674726f6c68645f5a544d463e362e241b120800000000000013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a094877a6d6154473a2e21140700000000000b16222d38444f5b66727d89949fa095897d72665b4f44392d343f4b56626d7984909ba59a8e83776c61554a3f33281c11060000000000000000000000000000000000000000000000000000000000000000000000020a121a20262c303437383939383734312d28231d1711141e262d333739393939393835302a22191005000000000000000000000000000000000000000000000000000000000000000000000000000000000000010b141d262f39424b545d666c6c6c6c6c6c6c6c6c6c685f54483c3024170b0000000000000000000000000000000000000000000000000000000007131f2b37424c555c5f5f5f5f5f5f5f5f5d574e443b4650595e5f5f5f5f5f5f5f5f5a52493e33271b0f02000000000000000000000000000000071019222c343c424546443f3931281f18212a323a40444645413a332a21180f050000000000000000000000000000000000000000000000000000000000000000000000000000000000000b16202932393e4242424242423e39322920160b000000000000000000000000000000000000000000000000050a0f1316191c1e1f2021212121201f1d1b222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000b1824313e4a5763707c8995a2aea69a8d8174685c4f43372f2f2f2f2f2f2f2f2f2f2f2f353f495157595754504d4946423f3a332b22190f060000000c1825323e4b5764707d8996a2afa79b8e8275695c5044372b1f13070000010c1723303c4855616d7a86939facaa9d9184786b5f5246392c2013070013202c3946535f6c798693a0aca89b8e8174685b4e4135281b0f0209141f2b3744505c6975828e9ba7b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0acac9f9285786b5f5245382c1f120500000000000b1724313e4a5764717d8a97a4b1a79a8e8174675a4d4134271a0e0000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000815222e3b4855616e7b8895a2a69a8d807366594d40333946535f6c798693a0a89c8f8275685b4f4235281c0f020000020b141c23282c2e2e2e2e2e2e2e2e2e2d2924292e31343738393939383633302b241c140a00000000000000000007101a222b323a41474d52575b5f626567696a6b6c6c6c6c6b6a69676563605c58534e48423b342c241b12090000000000000013202c3946535f6c7986939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393877a6d6154473a2e211407000000000005111c27333e4a55606c77838e9aa59a8f83786c61554a3e333a45515c68737e8a96a19f94897d72665b4f44392d22170b0000000000000000000000000000000000000000000000000000000000000000000000000000080f151b2024282a2c2c2c2c2a2825211c17120c060c141c22272b2c2c2c2c2c2c29251f1810070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141d263039424b545c5f5f5f5f5f5f5f5f5f5f5d564d43382c20140800000000000000000000000000000000000000000000000000000000030e1a25303a434b505353535353535353514c453c353e474e5253535353535353524f4940372c21160a000000000000000000000000000000000007101a222a3136383938342e271f160f1820292f3538393835302921180f0600000000000000000000000000000000000000000000000000000000000000000000000000000000000006111d27323b444a4e4f4f4f4f4e4a443b32271d1106000000000000000000000000000000000000000000050b11161b1f2326282a2c2d2e2e2e2e2d2b2a27252e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000d1a2633404c5965727e8b98a4b0a4978b7e7165584c403c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3f464a4c4b4744403d3c3c3c3a36302921180e0300000e1a2733404d5966727f8c98a5b1a5988c7f73665a4d4134281b0f030000000714202c3945525e6b7784919daaaca093877a6d6154483b2e2215080013202c3946535f6c798693a0aca79a8e8174675a4e4134271b0e01030f1b2834414d5a6673808c99a6b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0acac9f9285786b5f5245382c1f120600000000000b1824313e4b5764717e8b97a4b1a79a8d8174675a4d4134271a0e0000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000915222f3c4855626f7b8895a2a79a8d8173675a4d40343a4653606d798693a0a99c8f8275695c4f4236291c0f03000000020a11181c20212222222222222222201d191e2225282a2b2c2c2c2b2927231f19120a020000000000000000000007101921282f363c42474b4f5356585a5c5d5e5f5f5f5f5f5e5d5b595653504c48433d37312a221a1209000000000000000013202c3946535f6c7986868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686867a6d6154473a2e2114070000000000000b16222d38444f5b66727d89949fa094897d72665b4f44383f4b56626d7884909ba59a8e83776c61554a3e33281c1106000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f14181b1d1f20201f1e1b1815100b060100020a11171b1e20202020201f1d19140e0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141e273039424a5053535353535353535353514c443b31261b1004000000000000000000000000000000000000000000000000000000000009141e2831394044464646464646464645413b332c353c42454646464646464646433e372e251b10050000000000000000000000000000000000000710181f25292c2c2b28231d150d060e171e24292b2c2b29241e170f06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a16222e39444d555b5c5c5c5c5b554d44392e22160a00000000000000000000000000000000000000020a10171c22272b2f323537393a3b3b3b3a39383634312e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000f1b2835414e5b6774818d9aa6aea295897c6f6356494848484848484848484848484848484848484848484848484848484846423b332a1f150a00000f1c2935424e5b6874818e9aa7b0a3968a7d7064574b3e3225190c0000000004111d2a3643505c6975828f9ba8aea295897c6f6356493d3023170a0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000c1925323f4b5865717e8b98a4b0a3968a7d7063564a3d3023170a00131f2c3946525f6c7986929facac9f9286796c5f5346392c20130600000000000b1825323e4b5865717e8b98a4b1a69a8d8073675a4d4034271a0d0000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000916222f3c4955626f7c8995a2a79a8d8174675a4d41343a4753606d7a8793a0a99c8f8276695c4f4336291c10030000000000060c101315151515151515151513110d1216191b1d1f20201f1e1d1a17130e0800000000000000000000000000070f161e242b30363b3f4346494c4e505152525353525251504e4c4a4744403c37322c261f181008000000000000000000131f2c3946525f6b767979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979776c6053473a2d21140700000000000005111c27333e4a55606c77838e9aa59a8e83776c6055493e45505c67737e8a95a19f94897d72665b4f44392d22160b00000000000000000000000000000000000000000000000000000000000000000000000000000000000004080c0f1112131312110f0c0904000000000000060b0f12131313131312100d0803000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020c151e2730383f444646464646464646464644403a32291f150a000000000000000000000000000000000000000000000000000000000000020c161f282f3438393939393939393938353029232b313639393939393939393937322c251c13090000000000000000000000000000000000000000060e14191d1f201e1c17120b0300050c13181c1f201f1c18130d0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1a26333f4a555f6769696969675f554a3f33261a0d010000000000000000000000000000000000050d141b22282d33373b3e4144454747484847464543403d3a3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00101d2a3643505c6976828f9ca8ada094877a6e61555555555555555555555555555555555555555555555555555555555555534d453b31261b0f0300111d2a3743505d6976838f9ca9aea195887b6f6255493c3023160a00000000010f1b2835414e5b6774818d9aa7b0a4978a7d7164574b3e3125180b0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1724313e4a5764707d8a97a4b0a3968a7d7063564a3d3023170a00121f2c3845525e6b7885919eabaca09386796d6053473a2d21140700000000000c1926323f4c5965727e8c98a5b2a6998c807366594c4033261a0d0000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00091623303c4956626f7c8996a2a79a8e8174675a4e41343a4754606d7a8794a0a99c908376695c5043362a1d100300000000000000040708080808080808080807040105090c0f111213131312100e0b0703000000000000000000000000000000050c13191f252a2f33373a3d3f414344454646464645444342403d3b3734302b26211b140d0600000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b655b5044382b1f1206000000000000000b16222d38444f5b66727d89949f9f94887d71665a4f434a56616d78848f9ba59a8e83776c61554a3e33281c11050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c151e272e33373939393939393939393938342f2820170d0300000000000000000000000000000000000000000000000000000000000000040d161d23282b2c2c2c2c2c2c2c2c2c29241e1920262a2c2c2c2c2c2c2c2c2c2a27211b130a0100000000000000000000000000000000000000000003090d111213120f0b060000000001070c10121312100c08020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2935424e5b67717575757571675b4e4235291c0f0300000000000000000000000000000000060f171f262d33393e43474b4e5052535454545453514f4d4a46424855616e7b8895a2aea5988b7e7165584b3e3225180b00111e2b3744515d6a7784909daaaca09386796d626262626262626262626262626262626262626262626262626262626262625e574d43372b1f130700121e2b3844515e6b7784919daaada094877a6d6154473b2e21150800000000000d1a2733404d596673808c99a6b2a5988b7e7265594c3f3226190c0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a00111e2b3744515d6a7784909daaada194877b6e6154483b2e22150800000000000d1a2734404d5a6673808c99a6b1a5988b7e7265584b3f3225190c0000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000a1623303c4956636f7c8996a3a89b8e8174675b4e41343a4754616d7a8794a1aa9d908376695d5043362a1d10040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080e14191e23272b2e303335363738393939393838363533312e2b28241f1a150f090300000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5b53493f33281c0f030000000000000005111c27333e4a55606c77838e9aa5998e82776b605449505b67727e8995a09f94897d72665b4f44392d22160b00000000000000000000000000000000000000000000000000030507070707070707070707060400000000000000000000000000000000000000000000000000000000000000000000000306070707070707070707070503000000000000000000000000000000000000000000000000000000000000000000000000000000030c151c23282b2c2c2c2c2c2c2c2c2c2c2b28241e160e05000000000000000000000000000000000000000000000000000000000000000000040b12181c1f20202020202020201f1c19130e151a1d1f202020202020201f1e1b161009010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c69768282828276695c4f4336291c1003000000000000000000000000000000060f18212930383e444a4f53575a5d5f60616161605f5e5c5956524d4855616e7b8895a2aea5988b7e7165584b3e3225180b00121f2c3845525e6b7885919eabac9f9285796f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6e695f54483b2f23160900121f2c3845525f6b7885929eabaca09386796c6053463a2d20130700000000000c1925323f4c5865727e8b98a5b2a6998c807366594d4033261a0d0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a00101d293643505c6975828f9ca8afa295897c6f6356493d3024170a00000000020f1c2835424e5b6874818e9aa7b0a3978a7d7064574a3e3124180b0000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000a1723303d4a5663707d8a96a3a89b8e8275685b4e42353b4854616e7b8894a1aa9d9084776a5d5044372a1d110400000000000001060a0c0e0e0e0e0e0e0e0d0c090400000000000000000000000000000000000000000000000000000000000000000003090e13171b1e212426282a2b2c2c2c2c2c2c2b2a282724221f1b18130f0a04000000000000000000000000000a16212c3740484f525353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353524f4941372d22170b0000000000000000000b16222d38444f5b66727d89949f9f93887c71655a4e56616d78848f9aa59a8e83776c60554a3e33281c11050000000000000000000000000000000000000000000000050b0f121314141414141414141413100c0701000000000000000000000000000000000000000000000000000000000000060c101214141414141414141414120f0b050000000000000000000000000000000000000000000000000000000000000000000000000000030a11171b1e202020202020202020201f1c18130c05000000000000000000000000000000000000000000000000000000000000000000000001070c1012131313131313131312100d0803090e11131313131313131313110e0a0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003080c0f1111111111100e0a05000000000000000000000000000000000000000000000000000000000000101c2936434f5c6976838f8f8376695c4f4336291c10030000000000000000000000000000050f18212a333b424950555b5f6367696b6d6d6e6e6d6c6b6866625e595455616e7b8895a2aea5988b7e7165584b3e3225180b00131f2c3946525f6c7985929facac9f92857b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7063574a3d3124170a0013202c3946535f6c7986929facac9f9286796c5f5246392c1f130600000000000b1825313e4b5864717e8b98a4b1a69a8d8173675a4d4034271a0d0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000f1b2835414e5b6774818d9aa6b0a4978a7e7164584b3f3226190d0100000005111e2a3744505d6976838f9ca9aea195887b6f6256493c3023160a0000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000a1724303d4a5763707d8a96a3a89b8e8275685b4f42353b4855616e7b8894a1aa9d9084776a5d5144372a1e11040000000000050c1216191a1a1a1a1a1a1a1a1815100a0300000000000000000000000000000000000000000000000000000000000000000002070b0f1215171a1b1d1e1f1f20201f1f1e1d1c1a1815120f0b070300000000000000000000000000000005101a252e373e4346464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646433e372f261b110600000000000000000005111c27333e4a55606c77838e9aa4998d82766b5f545b67727e8995a09f94897d72665b4f44382d22160b00000000000000000000000000000000000000000000010910161b1e202020202020202020201f1d18130c04000000000000000000000000000000000000000000000000000000030a11171c1f202020202020202020201f1b17110a020000000000000000000000000000000000000000000000000000000000000000000000000000060b0f121313131313131313131312100c0701000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070e14191c1d1e1e1e1e1d1a16110a0300000000000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000000030e17212a333c454c545b61666b6f737678797a7b7b7a797775726e6a655f58616e7b8895a2aea5988b7e7165584b3e3225180b0013202c3946535f6c7986939facaca0948a88888888888888888888888888888888888888888888888888888888888888887d7164574a3e3124170b0013202c3946535f6c798693a0acac9f9285786b5f5245382c1f120500000000000b1824313e4b5764717d8a97a4b1a79a8e8174675a4d4134271a0e0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000d1a2633404c5965727e8b98a4b1a6998c8073675a4e4235291d10040000000814212d3946525f6b7885919eaaac9f93867a6d6054473b2e2115080000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000b1724313e4a5764707d8a97a4a89c8f8275685c4f42363c4855626e7b8895a2aa9e9184776a5e5144382b1e1105000000000710171d2225272727272727272725211b150d0400000000000000000000000000000000000000000000000000000000000000000000000205080b0d0f101112131313131212100f0d0b0906030000000000000000000000000000000000000009131c252c32373939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393937332d251d140a00000000000000000000000b16222d38444f5b66727d89949f9e93887c706559616c78838f9aa59a8e83776c60554a3e33271c1105000000000000000000000000000000000000000000010a131b22272b2d2d2d2d2d2d2d2d2d2d2c29241e160e0400000000000000000000000000000000000000000000000000030c151c23282b2d2d2d2d2d2d2d2d2d2d2b27221b140b02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040709090909090909080501000105080909090909090907040000000000000000000000000000000911191f25282a2a2a2a2a2926221c150c03000000000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000000b151f29333c454e575e656c72777c80828586878887878684817e7a76706a63616e7b8895a2aea5988b7e7165584b3e3225180b0013202c3946535f6c798693a0acb1a69c96959595959595959595959595959595959595959595959595959595959595958a7d7164574a3e3124170b0013202c3946535f6c798693a0acac9f9285786b5f5245382c1f120500000000000b1724313e4a5764717d8a97a4b1a79a8e8174675a4d4134271a0e0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000b1824313d4a56636f7c8995a1aea89b8f83766a5d5145392d21150a0605060c1824303d4955626e7a8793a0aca99d9184776b5e5245392c2013060000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000b1724313e4a5764717d8a97a4a99c8f8275695c4f42363c4855626f7b8895a2ab9e9184776b5e5144382b1e110500000007101922282e323434343434343433312c261f160d03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a27221b130b02000000000000000000000005111c27333e4a55606c77838e9aa4998d82766b5f66727d8994a09f94897d72665b4f44382d22160b0000000000000000000000000000000000000000000009131c252d33373a3a3a3a3a3a3a3a3a3a38352f2820160d020000000000000000000000000000000000000000000000000b151e262e34383a3a3a3a3a3a3a3a3a3a37332d251d1309000000000000000004080b0c0d0d0d0d0d0d0d0c0b0905000000000000000000000000000000000000000000000002070a0c0d0d0d0d0d0d0d0d0d0d0c0b080400000000000000000000000000000000000000060b0f1213131313131313131312100d08020000000000000000000000000000000000000000000000000000000000000000060c11141616161616161614110d070d11141616161616161614100c0600000000000000000000000007111b232a3035373737373736322d261e160c020000000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000007121d27313b454e57606870777d83888c8f91939494949392908e8b86817b746d656e7b8895a1aea5988b7e7165584b3e3225180b0013202c3946535f6c798693a0acb7aea7a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2978a7d7064574a3e3124170b0013202c3946535f6c798693a0acac9f9285786b5f5245382c1f120500000000000b1824313e4b5764717d8a97a4b1a79a8e8174675a4d4134271a0e0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000915222e3b4754606d7986929eaaab9e9286796d6155493d31261c15131213151e2935404c5965717d8a96a3afa69a8e8175685c4f43362a1d11040000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000b1824313e4b5764717e8b98a4a99c908376695c4f43363c4955626f7c8996a2ab9e9285786b5e5145382b1e12050000030e19222b333a3e41414141414141403d3831281f150b0000000000000002070b0e101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100f0e0a06000000000000000000000000010910161a1e1f2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201e1b16100901000000000000000000000000000b16222d38444f5b66727d89949f9e93877b70656c77838f9aa5998e83776c60554a3e33271c110500000000000000000000000000000000000000000005101b252e373e434647474747474747474745403a32281e1409000000000000000000000000000000000000000000000007121d2730383f4447474747474747474746443e372f251b10050000000000030a1014171919191919191919191815110b040000000000000000000000000000000000000001080e13161919191919191919191919191815100a04000000000000000000000000000000030b12171b1e1f1f1f1f1f1f1f1f1f1f1c19140d060000000000000000000000000000000000000000000000000000000000010a11181d2022232323232323211d1812181d2123232323232322201c17110901000000000000000000040f19232d353c414444444444423e3830281e13090000000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000000000020e19232e39434d57616a727a82898f94989b9ea0a1a1a1a09f9d9a97928d867f776e6e7b8894a1aea5988b7e7165584b3e3225180b00131f2c3946525f6c7986929facb4aaa19b9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9da4aeafa3968a7d7063574a3d3024170a0013202c3946535f6c7986929facac9f9286796c5f5246392c1f130600000000000b1825323e4b5864717e8b98a4b1a69a8d8173675a4d4034271a0d0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0006131f2c3845515d6a76828e9ba7aea296897d71655a4e43382e2622201f2022262f3a45515d6975818d99a6afa3978a7e7265594d4034271b0e020000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000b1825323e4b5865717e8b98a4a99c908376695d5043363c4956636f7c8996a2ab9e9285786b5f5245382c1f120500000915202b343d454a4d4d4d4d4d4d4d4d49433a31271c11060000000000060d13171b1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1a17120c04000000000000000000000000050a0e1113131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313110f0a0500000000000000000000000000000005111c27333e4a55606c77838e9aa4988d81766a727d89949f9f94887d71665b4f44382d22160b000000000000000000000000000000000000000000000a16212c3740494f53535353535353535353514b443a30251a0e03000000000000000000000000000000000000000000000c18232e39424a5053535353535353535353504941372d22160b00000000050e151b202426262626262626262624211c160f070000000000000000000000000000000000020b12191f2325262626262626262626262624211c150e0600000000000000000000000000040d151d23282b2c2c2c2c2c2c2c2c2c2b29251f181007000000000000000000000000000000000000000000000000000000010b131c23282d2f30303030302f2d29241d24292d2f30303030302f2d28221b130a0000000000000000000915202b353f474d50515151514f4a423a30251a0e0300000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000008141f2a35404b555f69737c848c949a9fa4a8a7a3a09e9c9c9c9d9fa19e98918981776e7a8794a1aea5988b7e7165584b3e3225180b00121f2c3845525f6b7885929eabafa3988f8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e929ca8afa296897c6f6356493c3023160900121f2c3845525f6b7885929eabaca09386796d6053463a2d20130700000000000c1925323f4c5865727e8b98a5b2a6998c807366594d4033261a0d0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0004101c2935414e5a66727e8a96a2aea69a8e82766a5f54494037322e2c2c2c2e3238414c57626d7985919da9ab9f93877b6e62564a3d3125180c000000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000c1825323f4b5865727e8b98a5aa9d9083766a5d5043373d495663707c8996a3ac9f9285786c5f5245392c1f120600020e1a26313c464f565a5a5a5a5a5a5a59544c43392e22160a000000000810181e2327292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292926221d160e060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b16222d38444f5b66727d89949f9e92877b7077838e9aa5998e83776c6055493e33271c1105000000000000000000000000000000000000000000000e1a26323e49525b5f6060606060606060605d564c42372b1f130700000000000000000000000000000000000000000005111d2934404a545c606060606060606060605b53493e33271b0f030000050e1720272c30333333333333333333312d2721191006000000000000000000000000000000010b141d242a2f323333333333333333333333312d2720180f050000000000000000000000020c161f272e34373939393939393939393835302a22190f05000000000000000000000000000000000000000000000000000009131d252d34393c3c3c3c3c3c3c39352e272f353a3c3c3c3c3c3c3c39342d251c120800000000000000000e1a26313d4751585d5d5d5d5d5b544c41362b1f130700000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000020e1925303b46515c67717b858e969ea5aba7a09b979391908f8f909295989d9b938980767a8794a0ada5988b7e7165584b3e3225180b00111e2b3844515e6a7784919daaada09387818181818181818181818181818181818181818181818181818c99a6aea194887b6e6155483b2f22150900121e2b3844515e6b7784919daaada094877a6d6154473b2e21150800000000000d1a2633404d596673808c99a6b2a5988c7e7265594c3f3226190c0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a00000d1925323e4a56626e7a86929da9aa9e93877c70665b5249423e3b3938393b3e434a535d68737e8a96a2ada69a8f83776a5e52463a2e211509000000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000c1925323f4c5865727e8c98a5aa9d9084776a5d5044373d4a5663707d8a96a3ac9f9286796c5f5246392c1f13060005121e2a37424e586166676767676767655e554a3f33261a0e01000007111a22292f333636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363635332e2820180e0500000000000002070b0e101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100f0e0a06000000000000000000000000000000000000000000000005111c27333e4a55606c77838e9aa3988c81757d88949f9f94887d71665b4f44382d22160b0000000000000000000000000000000000000000000000111e2a36434f5a646c6d6d6d6d6d6d6d6d6d685e53473b2f24180c0000000000000000000000000000000000000000000a16222d3945515c666c6d6d6d6d6d6d6d6d6c655b4f43372b1e120500010c17202931383d3f404040404040403f3d39322b22180e03000000000000000000000000000009131d262f363b3f404040404040404040403f3d38322a21170d020000000000000000000008131e2831393f4445464646464646464645413b342b21170c01000000000000000000000000000000000000000000000000040f1a252f373f45484949494949494640393039404649494949494948453f372e241a0f0300000000000000111d2a36424e5963696a6a6a6a665d53473b2f23160a00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000000007131f2a36414d58636e78838d97a0a8aca49c958f8b87848382838486888c91979b92887e7a8693a0ada5988b7e7165584b3e3225180b00101d2a3643505c6976838f9ca9ada094877a7474747474747474747474747474747474747474747474808d9aa6aca093867a6d6054473a2e21140700111d2a3743505d6976838f9ca9aea295887b6f6255493c3023160a00000000010f1b2835414e5a6774818d9aa7b0a4978a7d7164574b3e3125180b0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a00000915222e3a46525e6975818c98a3aea4988d82776d645b544e4a47464546474a4e545c656f7984909ba6aca1958a7e72665a4e42362a1e1205000000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000c1926323f4c5965727f8c99a6aa9e9184776a5d5144373d4a5763707d8a97a4aca09386796c5f5346392c201306000714212d3a46535f6a7374747474747470675b4f4236291d100300030e19232c343b4042434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343423f39322a20160c0100000000060d13171b1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1a17120c04000000000000000000000000000000000000000000000b16222d38444f5b66727d89949f9d92867b828e99a5998e83776c6055493e33271c10050000000000000000000000000000000000000000000000121f2c3945525f6b767a7a7a7a7a7a7a7a796f64584c4034281c110500000000000000000000000000000000000000030e1a26323e4a56626d787a7a7a7a7a7a7a7a776c5f5346392d2013060007131e29323b43494c4c4c4c4c4c4c4c4c49443c342a1f140900000000000000000000000000050f1a252f3840474b4c4c4c4c4c4c4c4c4c4c4c49433c33291e1308000000000000000000020e1925303a434a50525252525252525252514d463d33291d12060000000000000000000000000000000000000000000000000915202c3641495155565656565655514a4238424b5155565656565655504940362b20140800000000000000131f2c3945525e6a75777777776f64574b3e3225180b00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000c18242f3b47525e6974808a959fa9ada39a928a847e7a7876757677797c80858c939a8f857a8693a0ada5988b7e7165584b3e3225180b000f1c2835424e5b6874818d9aa7aea195887b6f67676767676767676767676767676767676767676875828e9ba8aa9e9185786b5f5245392c1f1306000f1c2935424e5b6874818e9aa7b0a3968a7d7064574b3e3225190c0000000004111d2a36434f5c6975828f9ba8afa295897c6f6356493d3023170a0013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000005111d2935414d5964707b87929da7a99e948980766d655f5a565452525254565a5f666e77818b96a1aca59b8f84796d61564a3e32261a0e02000000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000d192633404c596673808c99a6aa9e9184776b5e5144383e4a5764717d8a97a4aca09386796d6053463a2d201307000815222e3b4855616e7b818181818181776a5d5044372a1d1104000914202a353e464c4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4b443c32281d12060000000810181e2327292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292926221d160e0600000000000000000000000000000000000000000005111c27333e4a55606c77838e9aa3978c8188949f9f94887d71665b4f44382d22160b000000000000000000000000000000000000000000000000121f2c3945525e6b7783878787878787878074685c5145392d2115090000000000000000000000000000000000000007131f2b37434e5a66727e8787878787878783776b5f5346392d201306000c18242f3a444d54585959595959595959554e463c31251a0e020000000000000000000000010b16212c37414a52575959595959595959595959554e453b3024190d01000000000000000006121e2a36414c555c5f5f5f5f5f5f5f5f5f5d584f453a2e23170a0000000000000000000000000000000000000000000000000d1925313d48535b616363636363625c544a3f4a545d626363636363615b52473c3125180c0000000000000013202c3946535f6c798484847e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000004101c2834404c58636f7a86919ca7afa59b91888079736e6b6969696a6c70747a818992968b808693a0aca5988b7e7165584b3e3225180b000d1a2733404c5966727e8b98a4afa3968a7d70645a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5e6b7784909daaa89c8f8376695d5044372a1e1104000e1a2734404d5966737f8c98a5b1a5988c7f73665a4d4134281b0f030000000713202c3945525e6b7784919daaada094877a6e6154483b2f2215090013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0000010d1925313c48535f6a75808b96a0aaa59b91887f77706a6663605f5f5f6063666b71788089939da8a99e94897e73685c5145392d22160a00000000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000d1a2633404d596673808c99a6ab9e9184776b5e5145383e4b5764717d8a97a4ada09386796d6053473a2d201407000915222f3c4855626f7b888e8e8e8e84776a5e5144382b1e1105000d1925313c4650575c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5b564e443a2e23170b000007111a22292f333636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363635332e2820180e050000000000000000000000000000000000000000000b16222d38444f5b66727d89949f9d928a8e99a5998e82776c6055493e33271c1005000000000000000000000000000000000000000000000000111d2a36434e5a66727e8a94949494949185796d6155493e32261a0e020000000000000000000000000000000000000c18242f3b47535f6b77838f94949494948a7e73675b4f43372b1e120500101c2935404c565f65666666666666666560584d42362a1e1105000000000000000000000007121d28333d48535c63666666666666666666666560574c4135291d100400000000000000000915222e3b47535e676c6c6c6c6c6c6c6c6c6961564b3f33261a0d0100000000000000000000000000000000000000000000000f1c2935414e59646d6f6f6f6f6f6e665b4f434f5b666e6f6f6f6f6f6d64594d4134281b0f0200000000000013202c3946535f6c7986918c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000000814202c3945515d6874808c97a2ada99e93897f766e67625f5d5c5c5e6064696f77808992928787939faca5988b7e7165584b3e3225180b000b1825313e4a5763707c8995a2aea5988c8073675a4e4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d55616d7a86939faca6998d8074675b4e4235281c0f03000c1825323e4b5764707d8996a2afa79b8e8275695c5044372b1f13080201020b17232f3b4854616d7a86939facaa9e9185786c5f5346392d2014070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0000000814202b37424e59646f79848e98a1aaa39a9189827b76726f6d6c6b6c6d6f72767c828a929ba5a9a0978d82776d62564b4034281d110500000000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000d1a2733404d596673808d9aa6ab9e9285786b5e5145383e4b5764717e8b98a4ada094877a6d6053473a2d21140700091623303c4956626f7c89969a9a9185786b5e5145382b1f120500111d2936424d5862686969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696760564b3f33271a0e00030e19232c343b4042434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343423f39322a20160c01000000000000000000000000000000000000000005111c27333e4a55606c77838e9aa09b9799a09f94887d71665a4f44382d22160b000000000000000000000000000000000000000000000000000e1a26323e4a55616d7985919ca0a0a095897d72665a4e42362a1f1307000000000000000000000000000000000005101c2834404c58646f7b87939fa0a09d91867a6e62564a3f33271b0f0200121f2b3844515d687173737373737373726a5e52463a2d20140700000000000000000000030e19242f39444f5a646e7373737373737373737371695d5145382c1f130600000000000000000a1724313d4a56636f78797979797979797973675b4e4235281b0f020000000000000000000000000000000000000000000000101d2a3743505d6a767c7c7c7c7c776b5e5245525f6b787c7c7c7c7c75695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000000b1824303c4955616d7985919ca8aea3978c81776d645c5652504f505154585e656d76818b96919299a3afa5988b7e7165584b3e3225180b000916222f3b4854616d7986929eaba89b8f83766a5e5246414141414141414141414141414c5864717d8996a2aea2968a7d7164584c3f33261a0d01000a16232f3c4855616e7a87939facaa9d9185786c6054483c302419110f0e0f121c27333f4b5764707c8995a2aea79b8f8276695d5044372b1e12050013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000030f1a26313c47525d68727c868f98a1a9a39b938d87827e7b7a7978797a7c7e83878d949ca4a8a0978e857b70665b50453a2f23180c0000000000000000000000091623303c4956636f7c8996a3b0a4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000d1a2734404d5a6773818d9aa7ac9f9285786b5f5245383e4b5865717e8b98a5aea194877a6d6154473a2e211407000a1723303d4a5663707d8a96a39f9285786c5f5246392c1f130600121f2c3945525e6a7476767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767672675b4f4236291c10000914202a353e464c4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4b443c32281d12060000000000000000000000000000000000000000000b16222d38444f5b66727d89939393939393938e82776b6055493e33271c1005000000000000000000000000000000000000000000000000000a16212d3945515c6874808c98a3ada69a8e82766a5f53473b2f23170c00000000000000000000000000000000000915212d3945505c6874808c98a4ada4988d8175695d51463a2e22160a000013202c3946535f6c79808080808080807b6e6154483b2e211508000000000000000000000a15202a35404b56606b7680808080808080808080796d6053463a2d20130700000000000000000b1724313e4a5764717d868686868686868275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a778489898985786b5f5246525f6c79868989898376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000020f1b2734404c5965717d8995a1ada99d92867b70655b524b4643424344484c535b656f79848f9b9ea3abb2a5988b7e7165584b3e3225180b000713202c3845515d6a76828e9ba7ab9f92867a6e63574c40363434343434343434343a45515c6874818d99a5ab9f93877a6e6155493c3024170b00000714202d3946525e6b7783909ca8ada194887c7064584c41362b221e1c1b1c1e232d3844505b6774808c98a5b0a4988c7f73665a4e4135281c0f030013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000915202b36414b56606a747d868f979ea5a59e98938e8b888686858686888b8e93999fa6a49e968e857c73695f544a3f34291d12070000000000000000000000091623303c4956636f7c8996a3aea4978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000e1a2734414d5a6774818e9aa7ac9f9286796c5f5246393f4c5865727e8c98a5aea194887b6e6154483b2e211508000b1724313e4a5764707d8a97a49f9386796c5f5346392d2013060013202c3946535f6c7983838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838376695d5043362a1d10000d1925313c4650575c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5b564e443a2e23170b00000000000000000000000000000000000000000005111c27333e4a55606c778386868686868686867d71665a4f44382d21160b000000000000000000000000000000000000000000000000000005111d2834404c58636f7b87939faaab9f93877b6f63574c4034281c1004000000000000000000000000000000020e1a26313d4955616d7985919ca8aba094887c7064584d4135291d1206000013202c3946535f6c79868c8c8c8c8c887b6e6154483b2e21150800000000000000000006111c26313c47525c67727d888c8c8c8c8c8c8c8c86796d6053463a2d20130700000000000000000b1724313e4a5764717d8a92929292928f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a778490969285786b5f5246525f6c79869296908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000005121e2a3743505c6875818d99a6b1a5998d81756a5e5349403a373636383c4149535d68737e8a95a1adb4b2a5988b7e7165584b3e3225180b0004101d2935424e5a66727e8a96a2aea3978b7f73685d52483e352f2a2828292b3038414b56626d7985919da9a79b8f83766a5e5246392d211408000005111d2a36424f5b6773808c98a4b0a4988c8174695d52473d342e2a2828282a2e353f4955606c7884909ca8aca094887c6f63574b3e3225190d000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a00000000030e19242f3a444e58626b747d858c939a9fa4a39f9a9795939292929395979b9fa4a49f99938c847c736a61574d42382d22170c010000000000000000000000091623303c4956636f7c8996a1a1a1978a7d7063574a3d3024170a00000013202c3946535f6c798693a0aaa79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3aaa3968a7d7063564a3d3023170a0013202c3946535f6c798693a0a1a19a8d8173675a4d4034271a0d000e1b2834414e5b6774818e9aa7ac9f9286796c5f5346393f4c5965727f8c98a5aea194887b6e6155483b2e221508000b1825313e4b5764717e8b97a4a093867a6d6053473a2d2114070013202c3946535f6c7986909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090908376695d5043362a1d1000111d2936424d5862686969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696760564b3f33271a0e000000000000000000000000000000000000000000000b16222d38444f5b6671797979797979797979766b6055493e32271c10050000000000000000000000000000000000000000000000000000000c18242f3b47535f6a76828e9aa6afa3978c8074685c5044382d21150900000000000000000000000000000007131e2a36424e5a66727d8995a1ada79b8f83776b6054483c3024190d01000013202c3946535f6c79869399999994887b6e6154483b2e2115080000000000000000020d18222d38434e58636e79848e999999999999999386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a979f9f9f9c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000814212d3a46535f6b7884919da9ada195897c7165594d42372e2a29292b3037414b56616d7985919ca9b5b2a5988b7e7165584b3e3225180b00010d1925323e4a56626e7a86929da9a79c9085796e645a5047403a37353435383c424a535d68737e8a95a1ada2968a7e72665a4e42362a1d11050000010e1a26333f4b57636f7b87939faba99d91857a6e64594f463f3a37353435373a3f47515b66717d8994a0aca89c9084786c6053473b2f22160a000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000008131d28323c465059626b737b82898e94989ca0a2a4a1a09f9f9fa0a1a4a29f9c98938e88817a726a61584f453b31261c1106000000000000000000000000091623303c4956636f7c8994949494948a7d7063574a3d3024170a00000013202c3946535f6c7986939d9d9d9a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a969d9d9d968a7d7063564a3d3023170a0013202c3946535f6c798693949494948d8173675a4d4034271a0d000e1b2835414e5b6774818e9ba8aca09386796c5f5346393f4c5965727f8c99a6aea295887b6e6155483b2f221508000c1825323f4b5865727e8b98a5a194877a6e6154473b2e2114080013202c3946535f6c7986939c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c908376695d5043362a1d1000121f2c3945525e6a7476767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767672675b4f4236291c100000000000000000000000000000000000000000000005111c27333e4a5560686c6c6c6c6c6c6c6c6c6b645a4f44382d21160b0000000000000000000000000000000000000000000000000000000007131f2b36424e5a66717d8995a1ada89c9084786d6155493d31251a0e0200000000000000000000000000000b17232f3b47535e6a76828e9aa6aea2968a7e72675b4f43372b20140800000013202c3946535f6c798693a0a6a194887b6e6154483b2e211508000000000000000009141e29343f4a545f6a75808b95a0a6a6a6a6a6a09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4aca89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000a1623303c4955626e7b8794a0acaa9e9285796d6054483c31251e1c1d1f252f3a45515c6874808c98a5b1b2a5988b7e7165584b3e3225180b00000916222e3a46525d6975818c98a3aca1968b80766c6259514b464342414244474d535c656f79848f9ba6a89d91867a6e62564a3e32261a0e010000000a17232f3b47535f6b77838e9aa5ada2968b80756b6158504a464342414243464b5159636d77838e99a5aea3978b8074685c4f43372b1f1306000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0000000000010c16202a343e475059616970777d83888c90939698999a9b9b9b9a99979593908c88837d76706860584f463d33291f140a00000000000000000000000000091623303c4956636f7c888888888888887d7063574a3d3024191006000013202c3946535f6c798690909090908e8174675a4d4134271a0e01000a1723303d4a5663707d8a90909090908a7d7063564a3d3023170a0013202c3946535f6c79868888888888888173675a4d4034271a0d000f1b2835424e5b6875828e9ba8ada09386796d6053463a404c596673808c99a6afa295887b6f6255483c2f221509000c1926333f4c5965727f8c99a5a194887b6e6155483b2f2215080013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09d908376695d5043362a1d100013202c3946535f6c7983838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838376695d5043362a1d1000000000000000000000000000000000000000000000000b16222d38444e575d5f5f5f5f5f5f5f5f5f5f5a52483e32271c100500000000000000000000000000000000000000000000000000000000020e1a26323d4955616d7884909ca8ada195897d71655a4e42362a1e12060303030303030303030303030304101c28343f4b57636f7b87939eaaa99d91857a6e62564a3e33271b0f0300000013202c3946535f6c798693a0aca194887b6e6154483b2e2115080000000000000005101a25303b46505b66717c87919ca7b2b3b3b3ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000c1825323e4b5764717d8a96a3afa89b8f8276695d5144382c20140f10131d2834404c5864707c8995a1aeb2a5988b7e7165584b3e3225180b000005111d2935414d5964707b86919ca7a79d92887e746b635c5752504e4e4f5154585e656e77818b96a1aca2978c8075695d52463a2e22160a0000000007131f2b37434f5a66727d89949faaa89c92877d736a625b5652504e4e4e5052565c636b747e89949faaa89d91867a6f63574b3f33271b0f03000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000040e18222c353e474f575e656c72777c808487898b8d8e8e8e8e8d8c8b898683807c77716b655e564e463d342b21170d03000000000000000000000000000916232f3c4956626f797b7b7b7b7b7b7b7a6f63564a3d342b22180d020013202c3946535f6c79848484848484848174675a4d4134271a0e06030b1723303d4a5663707d848484848484847d7063564a3d3023170a0013202c3946525f6c777b7b7b7b7b7b7b7b72665a4d4033271a0d000f1c2835424f5b6875828f9ca8ada094877a6d6053473a404d596673808d9aa6afa295897c6f6255493c2f221609000d1a2633404d596673808c99a6a295887b6f6255493c2f2216090013202c3946535f6c7986939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393908376695d5043362a1d100013202c3946535f6c7986909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090908376695d5043362a1d10000000000000000000000000000000000000000000000005111c27323c454c51535353535353535353524f4840372c21160b0000000000000000000000000000000000000000000000000000000000000915212d3944505c6874808b97a3afa59a8e82766a5e52463b2f231710101010101010101010101010101015202c3844505c6874808b97a3afa4988c8175695d51453a2e22160a0000000013202c3946535f6c798693a0aca194887b6e6154483b2e211508000000000000010c16212c37424c57626d78828d98a3aeadacaeb4ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000e1a2733404d5966737f8c99a5b2a6998c8073675a4e4135281c1004030c18232f3c4854606d7986929fabb2a5988b7e7165584b3e3225180b0000010d1925303c48535e6a75808b95a0aaa49990867d756e68625f5c5b5b5b5d60646970778089939da7a59b90857a6f63584c4135291d120600000000030e1a26323e4a55616c77828d98a2aca3998f857c746d67625f5c5b5b5b5c5f62676d757d87909ba5aba1968b8075695e52463b2f23170b00000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0000000000000007101a232c353d454d545a61666b7074777a7d7e808181828181807e7c7a7774706b66605a534c453c342b22190f0500000000000000000000000000000815212e3a46525e686d6e6e6e6e6e6e6e6e685e534c463d34291e130700131f2c3945525e6a7477777777777777777165594d4033271f17100d151d25303c4955626d7677777777777777766d6255493c3023160900111e2b37434f5b656d6e6e6e6e6e6e6e6e6a61564a3e3225190c000f1c2936424f5c6975828f9ca8ada094877a6d6154473a404d5a6773808d9aa6afa296897c6f6356493c30231609000e1a2734404d5a6773818d9aa6a396897c6f6356493d3023160a0013202c3946535f6c7986868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868376695d5043362a1d100013202c3946535f6c7986939c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c908376695d5043362a1d100000000000000000000000000000000000000000000000000b16202a333a414546464646464646464646433e372e251b100500000000000000000000000000000000000000000000000000000000000005101c2834404b57636f7b87929eaaaa9e92877b6f63574b3f33271c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c25313d4955606c7884909ca8ab9f94887c7064584d4135291d11060000000013202c3946535f6c798693a0aca194887b6e6154483b2e21150800000000000008121d28333e48535e69747e89949faaa7a19fa3aaada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000f1c2835424e5b6874818e9aa7b0a4978a7e7164584b3f3226190d00000713202c3845515d6a7683909ca9b2a5988b7e7165584b3e3225180b0000000814202b37424d58636e79848e98a1aaa29890878079736e6b696867686a6c70757a8189929ba5a79d93897e74695e52473c3024190d0100000000000a16212d39444f5b66717c86909aa4aba1978e867e78736e6b69686768696b6e73787f879099a2aca3998f847a6f63584d41362a1e120700000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0000000000000005111d28333d474e535555555b6064686b6e70727374747574747371706d6b67645f5a555555524c443b30251a0e02000000000000000000000000000005121e2a36414c565d6161616161616161615e5e5d574f463b2f24180c00111d2a36424e5962696a6a6a6a6a6a6a6a675f544940383129221a171f272f373e46515c656a6a6a6a6a6a6a6a6a655c5145392d211408000f1b27333e49535b6061616161616161615f584f45392e22160900101c2936434f5c6975828f9ca9aea194877a6d6154473b414d5a6773818d9aa7b0a396897c6f6356493d3023160a000e1b2834414e5b6774818e9aa7a3968a7d7063574a3d3024170a00131f2c3946525f6b7679797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797974685c4f4336291d100013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09d908376695d5043362a1d10000000000000000000000000000000000000000000000000040e1821293035383939393939393939393937322c251c130900000000000000000000000000000000000000000000000000000000000000000c17232f3b47525e6a76828d99a5afa3978b8073675c5044382c29292929292929292929292929292929292a36414d5965717d8995a1aca79b8f83776b5f54483c3024180d010000000013202c3946535f6c798693a0aca194887b6e6154483b2e2115080000000000040e19242f3a444f5a65707a85909ba6a89d959398a1ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000101d2a3643505c6976838f9ca9afa295897c6f6356493d3024170a000004101c2935424e5b6874818d9aa7b2a5988b7e7165584b3e3225180b000000030f1a25313c47525d67727c868f98a1a9a199918a847f7b787574747576797c80868c939ba4a69e958b81776d62574c41362a1f140800000000000005111c28333e49545f6a747e89929ba4a9a0989089837e7a787675747576787b7e848a9199a2aba39a91877d73685d52473c3025190e0200000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000915222e39454f585f6262626262615b5f616365666768686767666563615e5d6162626262625e564d42362b1f12060000000000000000000000000000020e1925303a434c51545454545c646a6b6b6b6b6961574c4034281b0f000e1a26313c4750585c5d5d5d6062626262626059524a433b342c2521293139414850585f6262626262615d5d5d5d5a534a3f34291d1105000b16222d38414a50545454545454545454534e463d33281d110500101d2936434f5c697683909ca9aea194887b6e6154483b414d5a6774818e9aa7b0a3968a7d7063564a3d3023170a000f1c2835424e5b6875828e9ba8a4978a7d7164574b3e3124180b00111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6a62584c4034271b0e0013202c3946535f6c7986939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393908376695d5043362a1d1000000000000000000000000000000000000000000000000000060f171e24292b2c2c2c2c2c2c2c2c2c2c2a26211a130a01000000000000000000000000000000000000000000000000000000000000000007131e2a36424e5965717d8994a0aca89c9084786c6054493d363636363636363636363636363636363636363a46525e6a76828d99a5aea2968a7e72675b4f43372b201408000000000013202c3946535f6c798693a0aca194887b6e6154483b2e21150800000000000a15202b36404b56616c76818c97a2aca1968b86909ca9a09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000111e2b3744515d6a7784909daaaea194887b6e6155483b2f2215090000000d1a2733404c5966727f8c98a5b2a5988b7e7165584b3e3225180b000000000914202b36404b55606a747d868f979fa6a39c95908b8784828181828385888c91979ea5a49c948c83796f655b50463b3025190e03000000000000000b16222d38434e58626d768089929aa1a8a29b948f8a8784828281828284878b8f959ba3a8a19991887f756b61564c41362b1f14080000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e02000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000c1825313e4a56616a6f6f6f6f6f6d655e5757585a5b5b5b5b5a5958565860686e6f6f6f6f6e685e53473b2e22150900000000000000000000000000000008131e28313a4145474d565e666e767777777773685c5043362a1d10000915202b353e464c505059646c6f6f6f6f6f6b635c544d453e362f2c333b434b535a626a6f6f6f6f6f6d665b50504e4841382e23180c010005111b262f383f4447484848484848484846423c342b21170c0000101d2a3643505d697683909da9aea195887b6e6155483b414e5b6774818e9ba7b0a3978a7d7063574a3d3024170a000f1c2936424f5c6975828f9ca8a4988b7e7165584b3e3225180c000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5e5950463b3024180c0013202c3946535f6c7986868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868376695d5043362a1d100000000000000000000000000000000000000000000000000000050d13181c1f2020202020202020201f1e1a16100901000000000000000000000000000000000000000000000000000000000000000000020e1a25313d4955606c7884909ba7aca094897d7165594d4343434343434343434343434343434343434343434b57636e7a86929eaaa99d9185796e62564a3e32271b0f03000000000013202c3946535f6c798693a0aca194887b6e6154483b2e2115080000000006111c27323c47525d68727d88939ea8a59a8f85828f9ca9a09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000121f2c3845525e6b7885919eabada093867a6d6054473a2d2114070000000c1825323e4b5864717d8a97a4b0a5988b7e7165584b3e3225180b00000000030e19242f39444e58626b747d858d949ba1a6a19b9793918f8e8e8e909295989da2a59f99928b837a71675d53493f34291e1308000000000000000005101b26313c46515b646e77808890979da3a6a09b9793918f8e8e8e8f9193979ba0a6a39d968f877f766d63594f453a2f24190e030000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a110f0b0a1723303d4a5663707d8a96a3aea3968a7d7063564a3d3023170a000000000000000d1a2633404d5966727b7b7b7b7b7770686159524d4e4e4e4e4e4d535a626a727a7b7b7b7b7a6f6356493d3023160a0000000000000000000000000000050d151e262e363e474f575f6770788084848484776a5d5044372a1d1100030e19232c353b4043505d69767b7b7b7b7b756e665f5750484139363d454d555d646c747b7b7b7b7b786c5f5246423d372f261c1107000006111c263039404548494949494949494947433d352c22170c0100111d2a3744505d6a7783909daaaea295887b6f6255483c424e5b6875828e9ba8b0a4978a7d7164574a3e3124170b00101d293643505c697683909ca9a5988c7e7265594c3f3226190c000a16212c3740484f52535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353524e473e342a1f130700131f2c3946525f6b7679797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797974685c4f4336291d1000000000000000000000000000000000000000000000000000000002080c101213131313131313131313110e0a050000000000000000000000000000000000000000000000000000000000000000000000000915202c3844505c67737f8b97a2aea5998d82756a5e524f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f5b67737f8b97a3aea4988c8175695d51453a2e22160a00000000000013202c3946535f6c798693a0aca194887b6e6154483b2e211508000000020d18232e38434e59636e79848f9aa4a99e93897e83909da9a09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000131f2c3946525f6c7985929facac9f9386796c5f5346392d2013060000000a1724303d4a5663707d8996a3b0a5988b7e7165584b3e3225180b000000000008121d28323c465059626b737b838a90969b9fa3a3a09d9c9b9b9b9c9ea1a4a29e99948e88817970685f554c42372d22180d020000000000000000000a15202a353f49525c656e767e858c92979ca0a3a3a09d9c9b9b9b9c9da0a3a3a09c97928c857d756d645b51473d33281e1308000000000013202c3946535f6c798693a0a1a19a8e8174675a4d4134271e1d1b17121723303d4a5663707d8a96a1a1a1968a7d7063564a3d3023170a000000000000000d1a2633404d5966738088888888827a736b645c554d4642454d555d656c747c84888888887d7063564a3d3023170a00000000000000000000000000060f171f2730384048505961697179828a9191897e74695c5043362a1d10000007111a232a303744505d6a77848888888780787069615a524b4340484f575f676e767e8688888886796c5f534639312c251d140a0000000b17222e38424b51555555555555555555544f473e34291d120600111e2a3744515d6a7784909daaafa295887b6f6255493c424f5b6875828e9ba8b1a4978a7d7164574b3e3124180b00111d2a3744505d6a7683909daaa6998c807366594c4033261a0d0005101a252e373e434646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464645423c352c22180d0200111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6a62584c4034271b0e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101c27333f4b57636e7a86929ea9aa9e92867a6e625c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c606c7884909ba7ab9f94887c7064584c4135291d110500000000000013202c3946535f6c798693a0aca194887b6e6154483b2e21150800000009141f2a343f4a55606a75808b96a0aba2978c827784919daaa09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986939facac9f9285786c5f5246392c1f13060000000916232f3c4955626f7c8995a2afa5988b7e7165584b3e3225180b0000000000010b16202a343e475059616971787e858a8f9396999b9d9e9f9f9f9e9d9b9895928e89837d766e675e564d433a30261b110600000000000000000000030e18232d37404a535c646c737a81878c9094979a9c9d9e9f9f9f9e9d9b999794908b86817a736b635b52493f362b21170c01000000000013202c3946535f6c798693949494948e8174675a4d41342b2b2a27231d1723303d4a5663707d8a94949494948a7d7063564a3d3023170a000000000000000c1926323f4c58646f79828c95948c857d756e665f5750484f575f676f767e868e95948a80766c6155483c2f23160900000000000000000000000008101821293139414a525a626b737b838b94958b81776d63584c4034281b0f0000000811181f2936434f5b67727b858f95918a827b736c645d554e4a5259616971788188909591877d73695e5145382c211a130b020000000f1b27333f4a545c616262626262626262605950453a2e22160a00111e2a3744515d6a7784919eaaaca296897c6f6255493c424f5b6875828f9ca8aca4988b7e7164574b3e3124180b00111e2b3744515d6a7784919daaa69a8d8073675a4d4034271a0d000009131c252c3237393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393936312b231a110600000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5e5950463b3024180c000000000000000000000000000000000000000000000106090b0b0a0804000000000000000000000000000000000000000000000206090a0a09060200000000000000000000000000000000000000000000000b17232e3a46525e6975818d99a5aea2978b7f7369696969696969696969696969696969696969696969696969707c8894a0aca69b8f83776b5f54483c3024180d0100000000000013202c3946535f6c798693a0aca194887b6e6154483b2e211508000005101b26303b46515b66717c87929ca7a69b90867b7885919eaba09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c798693a0acac9f9285786b5f5245382c1f12050000000915222f3c4855626f7b8895a2aea5988b7e7165584b3e3225180b000000000000040e18222c353e474f575f666d73797e83878a8d8f909292929291908e8c8986827d78726b645d554c433a31281e140900000000000000000000000007111b252e38414a525a62696f757b8084888b8d8f909292929291908f8d8a8784807a756f68615a514940372d241a0f0500000000000013202c3946535f6c79868888888888888174675a4d4138383837332e282023303d4a5663707d888888888888887d7063564a3d3023170a000000000000000b1723303c47535d67707a848d97968f8780787169625a535a6169717981889098958c82786e645a5045392d20140700000000000000000000010a121a222a333b434b535c646c747c858d95988e84796f655b51463b3024180c00000000070e1a27333f4b566069737d86909a948d857e766f676058545c636b737b838b929a93897f756b62584d4135291d10090100000000121e2b3744505b666e6f6f6f6f6f6f6f6f6b62564a3e3225190c00111e2b3844515e6b7784919ea0a0a096897c6f6356493c424f5c6975828f9ca0a0a0988b7e7165584b3e3225180b00121e2b3845515e6b7884919ea0a09a8e8174675a4e4134281b0e0000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a25201911080000000a16212c3740484f52535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353524e473e342a1f1307000000000000000000000000000000000000000000070d121517181714100b0400000000000000000000000000000000000001080e1215171715120e080200000000000000000000000000000000000000000006121e2a35414d5965707c8894a0aca79b8f84787676767676767676767676767676767676767676767676767676818d99a5ada2968a7e72665b4f43372b1f14080000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e21150800010c17222c37424d57626d78838e98a3aa9f948a7f747885929faca09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c798693a0acac9f9285786b5f5245382c1f12050000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000000006101a232c353d454d555c62686d72777a7d80828485858685848382807d7976716c66605a524b433a31281f160c020000000000000000000000000009131c262f38404850575e646a6f74787b7e81828485858685858482817e7b77736f69645e574f483f372e251b12080000000000000013202c3946525f6c777b7b7b7b7b7b7b7b73665a4d44444444433f39322a23303d4956636f7a7b7b7b7b7b7b7b7a6f6356493d3023160a0000000000000007131f2b36414b555e68727b858f9899928a837b746c645d646b737b838b929a978d837a70665c52493e33281c1004000000000000000000030b131b242c343c454d555d656e767e868f979a90867c72675d53493f352a1f140800000000000b17232e39444e57616b747e88919b978f888179716a625e666e757d858d959c948b81776d635950463b3025190d01000000000013202c3946535f6c787c7c7c7c7c7c7c7c73665a4d4034271a0d00121e2b3845515e6b7885919393939393897d7063564a3d434f5c6976838f93939393938b7e7265584c3f3225190c00121f2c3945525f6b788592939393938e8275685b4e4235281b0f000000010910161a1e1f2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201f1d1a140e070000000005101a252e373e434646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464645423c352c22180d0200000000000000000000000000000000000000020a12191e22242423201c160f0700000000000000000000000000000000030c13191e222323221e1a140c040000000000000000000000000000000000000000010d1925313c4854606c77838f9ba7aca0948883838383838383838383838383838383838383838383838383838386929da9a99d9185796d62564a3e32271b0f030000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e2115080008131d28333e49535e69747e8a949faaa3988e83786d7986939faca09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c798693a0acac9f9285786b5f5245382c1f12050000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000008111a232b343b434a51575d62666a6e717475777878797878777573706d6965605b554f48413931281f160d040000000000000000000000000000010a141d262e363e454c53595e63686b6f727476777878797878777574716e6b67635e58524c453e362d251c13090000000000000000111e2b37434f5b656d6e6e6e6e6e6e6e6e6a61565151515151504b443c332b2e3a47535e686e6e6e6e6e6e6e6e6e685e53473a2e22150800000000000000030e1a252f39434c566069737c8690999c948d857e766f676e757d858d959d998f857b71685e544a40372d22170c000000000000000000020c151d252d363e464e575f676f77808890989d93897e746a60564b41372d23180e02000000000006121d28323c454f59626c768089939c9a928b837c746d68707880878f979f968c82786f655b51473e342a1f140800000000000013202c3946535f6c79868989898989898173675a4d4034271a0d00121f2c3845525e6b7885868686868686867d7063564a3d43505d697683868686868686867e7265584c3f3226190c0013202c3946535f6c79868686868686868275685c4f4236291c0f0000000000050a0e111313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313110d090300000000000009131c252c3237393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393936312b231a110600000000000000000000000000000000000000020b141c242a2e3131302c27211910070000000000000000000000000000040d151d242a2e30302e2a251e160d0400000000000000000000000000000000000000000814202c38434f5b67737e8a96a2aea59a929090909090909090909090909090909090909090909090909090909198a2aea4988c8175695d5145392e22160a000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e211508040f19242f3a454f5a65707b86909ba6a79c92877c716d7a8693a0ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c7986929facac9f9285796c5f5246392c1f13060000000915222f3c4855626f7b8895a2aea5988b7e7165584b3e3225180b000000000000000000081119222a31383f464c51565a5e626567696a6b6c6c6b6b6a686664615d59554f4a443d362f271f160d0400000000000000000000000000000000020b141c242c343b41484d53575c5f626567696a6b6c6c6b6b6a696765625f5b57524d47413a332c241c130a0100000000000000000f1b27333e49535b6061616161616161615f585b5e5e5e5e5e5c564e453d352d36424c565d6161616161616161615d564c42362a1e1206000000000000000008131d27313a444e57616a747e88919b9f9790888179727880878f979f9a91877d73695f564c42382e251b10060000000000000000000a141e272f373f485058606871798189929a9f958b81776c62584e443a2f251b1107000000000000000b16202a333d47505a646d77818a949d9d958e867e77727a828a9199a1988e847a70675d53493f352c22180d0200000000000013202c3946535f6c798693969696968d8173675a4d4034271a0d00121f2b3845515e6a767979797979797979786f63564a3d434f5c68747979797979797979797165584b3f3225190c00131f2c3946525f6b76797979797979797973685b4f4235291c0f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a252019110800000000000000000000000000000000000000020b141d262e353a3d3e3c38322b22191007000000000000000000000000040d161f272f363a3d3d3b3630281f160d0400000000000000000000000000000000000000040f1b27333f4a56626e7a86919da9aca39e9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9da2aaab9f93887c7064584c4035291d1105000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e2115080b15202b36414b56616c77828c97a2aba0968b80756a6d7a8794a0ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000121f2c3945525f6b7885929eabac9f9386796c5f5346392d2013060000000916232f3c4956626f7c8995a2afa5988b7e7165584b3e3225180b000000000000000000000710181f272e343a40454a505b646a6b6b6b6b69625f5e5d5c5a5754514d49443f39322c241d150d04000000000000000000000000000000000000020a121a222930363c42474b545f676b6b6b6b6b665f5f5e5d5c5a5856534f4b46423c363029211a120a010000000000000000000b16222d38414a50545454545454545454535d666b6b6b6b6b6760574f473f36303a444c51545454545454545454514c443a30251a0e020000000000000000010b151f28323c454f59626c757f89929ca19a938b837c828a9299a19c92897e756b61574e443a30261d130900000000000000000006111c2630394149515a626a727a838b939ba2988d83796f655b50463c32281e13090000000000000000040e18212b353e48525b656f78828c959f9f989089817c848c949ca39990867c72685e554b41372d241a10060000000000000013202c3946535f6c798693a0a2a29a8d8173675a4d4034271a0d00101d2936424e59646b6c6c6c6c6c6c6c6c6c675d52473a404c58626a6c6c6c6c6c6c6c6c6c685f54483c3024170b00111e2a37434f5a646b6c6c6c6c6c6c6c6c6a62574b3f33271a0e000000000000000000000003070a0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0b080400000000000000000000000000000000010910161a1e1f2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201f1d1a140e0700000000000000000000000000000000000000020b141d262f3840464a4b49443d342b2219100700000000000000000000040d161f2831394146494a47413a31281f160d04000000000000000000000000000000000000000b16222e3a46515d6975818c98a4b0aeaaa9a8a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a7a9a9adb2a69a8f83776b5f53483c3024180c01000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e211508111c27323d47525d68737d88939ea9a49a8f84796e646e7b8894a1ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000121e2b3845515e6b7784919eaaada093877a6d6054473a2e2114070000000a1724303d4a5763707d8a96a3b0a5988b7e7165584b3e3225180b0000000000000000000000060e151c23292f353b4754606c7677777777746b635b534f4d4b4845413d38332d27211a130b030000000000000000000000000000000000000000000810171e252b31363f4c596571777777777770686058514f4e4c4946433f3b36302b251e171008000000000000000000000005111b262f383f4447484848484848484a57636f77777777777169615951484038323a414547484848484848484745413a32281e140900000000000000000000030d16202a333d47505a636d77818a949da49d958e878c949ca39e948a80766d63594f453c32281e140b010000000000000000000b17222e38424b535b636c747c848c959da49a90867c71675d53493f342a20160c02000000000000000000060f19232c364049535d667079838d96a0a29b938c878e969ea59b91877e746a60564c43392f251b1208000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000e1a26313d48525a5f5f5f5f5f5f5f5f5f5f5c554c41363b4650595e5f5f5f5f5f5f5f5f5f5d564d43382c201408000e1a26323e48525a5f5f5f5f5f5f5f5f5f5e5850453a2f23170b000000000000000000030a0f1417181919191919191919191919191919191919191919191919191919191919191919191919181714100b0400000000000000000000000000000000050a0e111313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313110d090300000000000000000000000000000000000000010a141d262f38414a525657554f463d342b221910070000000000000000040d161f28313a434b525656534c433a31281f160d0400000000000000000000000000000000000006121d2935414d5864707c88949fabb7aea49d99999999999999999999999999999999999999999999999ba2acb7ada2968a7e72665a4f43372b1f140800000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e21150d18232e39434e59646f79848f9aa5a89e93887d7268616e7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000111d2a3744505d6a7683909da9aea194887b6e6155483b2f2215090000000c1925323e4b5864717e8b97a4b1a5988b7e7165584b3e3225180b000000000000000000000000030a11181e242e3b4855616e7b848484847d756d655c544c443c3935312c27221c160f08010000000000000000000000000000000000000000000000060d141a202633404d59667380848484837a726a62595149413d3a37332f2a251f1a130c05000000000000000000000000000a141d262d34383a3b3b3b3b3b3b3e4b5865717e848484847b736b635a524a423a3135393b3b3b3b3b3b3b3b3b39352f2820160c020000000000000000000000040e18212b353e48515b656e78828b959fa7a09894979ea69f968c82786e655b51473d332a20160c02000000000000000000000f1b27333f4a545d656d757e868e969ea79d92887e746a5f554b41372d23180e04000000000000000000000007111a242e37414b545e67717b858e98a1a59e969498a0a79d938980756c62584e443b31271d130900000000000000000013202c3946535f6c798693a0a0a09a8d8173675a4d4034271a0d000915202b3640484e52535353535353535353504b433a2f343e474e52535353535353535353514c443b31261b1004000a16212c3740484f525353535353535353524d463e34291e12070000000000000000050d141b20232525252525252525252525252525252525252525252525252525252525252525252525252524211c160f0700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c262f38414a535c636460584f463d342b22191007000000000000040d161f28313a434c555d63635e564d433a31281f160c030000000000000000000000000000000000010d1924303c48545f6b77838f9aa6b2a99d928c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c909aa6b2a99d9185796d62564a3e32261b0f0300000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e2115141f2a353f4a55606b75808b96a1aba2978c81766c61626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000101c2936424f5c6875828e9ba8afa296897c7063564a3d3024170b0000010e1b2734404d596673808c99a5b2a5988b7e7165584b3e3225180b0000000000000000000000000000060d15212e3b4854616d78828c918f877f766e665e564e453d352d241c17110b04000000000000000000000000000000000000000000000000000002090f192633404c5965717c8690918c847c746b635b534a423a322a231e19140e08020000000000000000000000000000020b141c23282c2e2e2e2e2e2e313e4b5764707a858f918d857d756c645c544b433b332d2e2e2e2e2e2e2e2e2e2d29241e160e0400000000000000000000000000060f19232c363f49535c667079838d96a0a0a0a0a0a0a0978e847a70665c53493f352b22180e040000000000000000000000121e2b3744505b666f777f879098a0a09f958b81766c62584e44392f251b11060000000000000000000000000008121c252f39424c555f69727c868f99a0a0a0a0a0a09e958b81776d635a50463c32291f150b0100000000000000000013202c3946535f6c798693939393938d8173675a4d4034271a0d00040f1a242e363d4345464646464646464646443f3931282c353c424546464646464646464644403a32291f150a000005101a252e373e4346464646464646464645423c342c22170d0100000000000000040e171f262c3032323232323232323232323232323232323232323232323232323232323232323232323232302d27211910060000000000000000000000000106090b0b0a0804000000000000000000000000000000000000000000000206090a0a0906020000000000000000000000000000000003070a0c0c0c0c0c0c0c0c0c0c0b0804000000000000000009131c252e38414a535c656e716a61584f463d342b2219100700000000040d161f28313a434c555e676f6f685f554c433a31281e150b01000000000000000000000000000000000008141f2b37434f5b66727e8a96a1ada79a8d81808080808080808080808080808080808080808080808a97a4b0a4988c8175695d5145392d22160a0000000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e21151b26313b46515c67717c87929da7a59b90857a70655a626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000e1b2834414e5a6773808d99a6b0a4978b7e7165584c3f3226190d000005111d2a36434f5c6875818e9aa7b2a5988b7e7165584b3e3225180b0000000000000000000000000000000713202c3845515c66707a858f999189817870685f574f473f362e261e160d05000000000000000000000000000000000000000000000000000000000b1824313d4955606a747e8993968e867d756d655c544c443c332b231b130a0200000000000000000000000000000000020a11171c1f2121212121232f3c48535e69737d8791978f877e766e665d554d453d342c2421212121212121201d19130c0400000000000000000000000000000007111a242d37414a545e67717a848e939393939393938f857b72685e544a41372d2319100600000000000000000000000013202c3946535f6c7881899193939393938d83796f655a50463c32271d13090000000000000000000000000000000a131d27303a434d57606a747d8791939393939393938c83796f655b51483e342a20170d030000000000000000000013202c3946535f6c79868686868686868173675a4d4034271a0d000008121b242c32363939393939393939393938342e271f232b31363939393939393939393938342f2820170d0300000009131c252c32373939393939393939393836312a2219100600000000000000010c16202931373c3e3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3d38322b22180e0300000000000000000000070d121517181714100b04000001040608090a0b0b0a0a08070502000001080e1215171715120e0802000000000000000000000000030a0f1417181919191919191919181714100b04000000000005101a252e37404a535c656e777c736a61584f463d342b231a10070000040d161f28313a434c555e6770797a71675e554c433a30271d13080000000000000000000000000000000000030f1b27323e4a56626d7985919da8a99d9185797373737373737373737373737373737373737376828e9aa6ab9f93877b7064584c4035291d11050000000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e2117222d37424d58636d78838e99a3a99f94897e74695e55626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000d1926333f4c5865727e8b97a4b0a6998d8073675a4e4135291c1004020915212d3946525e6b7784909da9b2a5988b7e7165584b3e3225180b00000000000000000000000000000004101c28343f4a545e69737d87919b928a827a716961595148403830281f170f070000000000000000000000000000000000000000000000000000000915212d38434e58626c76818b95988f877f766e665e564e453d352d241c140c040000000000000000000000000000000000060c101314151515151f2b37424d57616b75808a9499908880786f675f574f463e362e251d151515151413110d0801000000000000000000000000000000000008121c252f38424c555f69727c8686868686868686867d736a60564c42382f251b11070000000000000000000000000013202c3946535f6c798686868686868686867b71675d53483e342a20160b01000000000000000000000000000000010b151e28323b454e58626b757e8686868686868686847a71675d53493f362c22180e050000000000000000000000131f2c3946525f6b7679797979797979797266594d4033271a0d00000009121a21262a2c2c2c2c2c2c2c2c2c2c2b28231d151920252a2c2c2c2c2c2c2c2c2c2c2b28241e160e0500000000010a131a21262a2c2c2c2c2c2c2c2c2c2c29251f181007000000000000000007121d28323b42484b4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4b49443d342a20150a0000000000000000020a12191e22242423201c160f070a0d1012141617171717161513110f0b080c13191e222323221e1a140c0400000000000000000000050d141b20232525252525252525252524201c160f06000000000a16212c374049525c656e7781867c736a61584f463d352c231a1007040d161f28313a434c555e67707982837970675e554c42392f24190d0200000000000000000000000000000000000a16222d3945515d6974808c98a4ada1958a7e7266666666666666666666666666666666666f7b87929eaaa69a8f83776b5f53473c3024180c000000000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e211e29333e49545f69747f8a959faaa3988d82776d625755626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000b1724313d4a56636f7c8895a1aea89b8f83766a5d5145382c20140e0e111a26313d4955626e7a87939facb2a5988b7e7165584b3e3225180b000000000000000000000000000000000c18232e38424c57616b75808a949c948c847b736b635a524a423a312921191008000000000000000000000000000000000000000000000000000004101c27323c46505a656f79838d98999189817870685f574f473f362e261e160d050000000000000000000000000000000000000406080808080f1a26303b454f59636e78828c969a928a817971696058504840372f271f170e080807040100000000000000000000000000000000000000000a131d26303a434d57606a73797979797979797979756b61584e443a30261d13090000000000000000000000000000131f2c3946525f6b7679797979797979797974695f554b41372c22180e040000000000000000000000000000000000030c162029333c465059636d7679797979797979797972685f554b41372e241a1006000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6960554a3d3125180c00000000080f151a1e1f2020202020202020201e1c17120b0e141a1d1f2020202020202020201f1c18130c05000000000000010910161a1e1f20202020202020201f1d19140e060000000000000000000c18242f3a444d5458585858585858585858585858585858585858585858585858585858585858585858585858554f463c31261b0f03000000000000020b141c242a2e3131302c27211912161a1c1f2123242424242322201e1b1814151d242a2e30302e2a251e160d040000000000000000040e171f262c3032323232323232323232302d27201810060000000e1a26323e48525b646e7780898f867c736a61584f473e352c231a100d161f28313a434c555e677079828b8c837970675e544b41352a1e1206000000000000000000000000000000000005111d2935404c58646f7b87939faba69a8e82766a5f595959595959595959595959595c67737f8b97a3ada1968a7e72665a4f43372b1f1308000000000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e21252f3a45505b65707b86919ba6a79c91867b71665b5055626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000915222e3b4754606d7986929fabab9e9286796d6155483d31251c1b1b1d232c37424e5a66727e8a96a2afb2a5988b7e7165584b3e3225180b0000000000000000000000000000000006111c26303b454f59636d78828c969e958d857d756c645c544b433b332b221a120900000000000000000000000000000000000000000000000000000b15202a343e49535d67717b86909a9b928a827a716961595148403830281f170f05000000000000000000000000000000000000000000000009141f29333d47515c66707a858f999c938b837b736a625a524941393129201810060000000000000000000000000000000000000000000000010b141e28313b454e58626a6c6c6c6c6c6c6c6c6c6b63594f463c32281e150b010000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6a62584d43392f251b100600000000000000000000000000000000000000040e17212a343e47515b646b6c6c6c6c6c6c6c6c6c6960574d43392f251c1208000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5d574e44392d2115090000000000040a0e1113131313131313131313120f0b060003090d111313131313131313131312100c0701000000000000000000050a0e1113131313131313131312110d090300000000000000000000101c2834404b565f6465656565656565656565656565656565656565656565656565656565656565656565656560584e43372b1f12060000000000020b141d262e353a3d3e3c38322b221e2226292b2e2f30313131302e2d2a2724201f272f363a3d3d3b3630281f160d04000000000000010c16202931373c3e3f3f3f3f3f3f3f3f3f3d38322a22180e030000111e2a37434f5a646d76808992988f867c736a615950473e352c231a161f28313a434c555e677079828b94948b827970665d52463a2e2115080000000000000000000000000000000000000c1824303b47535f6b76828e9aa6ab9f93877b6f63574c4c4c4c4c4c4c4c4c4c4c54606c7884909ca7a99d9185796d61564a3e32261a0f03000000000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e212b36414c57616c77828d97a2aba0958a80756a5f544a55626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000006131f2c3845515e6a76838f9ba7aea195897d7165594d42372e2927282a2e343e48535f6a76828e9aa6b2b2a5988b7e7165584b3e3225180b00000000000000000000000000000000000a141f29333d47515c66707a848f999f978f877e766e665d554d453d342c241b110700000000000000000000000000000000000000000000000000040e18222d37414b555f6a747e88929d9c948c847b736b635a524a423a312921170d0300000000000000000000000000000000000000000000020d17212b36404a545e68727d87919b9d958d857c746c645b534b433b322a22180e040000000000000000000000000000000000000000000000020c161f29333c4650585e5f5f5f5f5f5f5f5f5f5e5951473e342a20160c030000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5e5850463c31271d1309000000000000000000000000000000000000000000050f18222c353f49525a5f5f5f5f5f5f5f5f5f5f5d574e453b31271d130a00000000000000000000000000000a16212c3740484f525353535353535353514c453c32271c11050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000121f2b3844515d68707272727272727272727272727272727272727272727272727272727272727272727272716a5f53473b2e21150800000000020b141d262f3840464a4b49443d342b2a2e3235383a3c3d3e3e3d3d3b393734302c2831394146494a47413a31281f160d04000000000007121d28323b42484b4c4c4c4c4c4c4c4c4b49443c342a2015090000131f2c3946525f6b768089929ba1988f867c736b625950473e352c231f28313a434c555e677079828b949d9d948b82786e6256493d3023170a00000000000000000000000000000000000007131f2b37424e5a66727d8995a1ada3978c8074685c504440404040404040414d5965717c8994a0aca4988c8074695d5145392d22160a00000000000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e27323d48525d68737e89939ea9a4998e84796e63584d4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000004101d2935424e5a67737f8b97a3afa5998d81756a5e5349403935343436393f47505a65707b87929eaab6b2a5988b7e7165584b3e3225180b0000000000000000000000000000000000030d17212b35404a545e68727d87919ba199908880786f675f574f463e362d23180d020000000000000000000000000000000000000000000000000006111b252f39434e58626c76818b959f9e958d857d756c645c544b433b33291f14090000000000000000000000000000000000000000000000050f19242e38424c57616b757f89949e9f968e867e766d655d554d443c342a20160a000000000000000000000000000000000000000000000000040d17212a343e464d52535353535353535353524e473f352c22180e04000000000000000000000000000000000a16212c3740484f52535353535353535353524d463e342a20150b010000000000000000000000000000000000000000000006101a232d3740484f52535353535353535353514c453c33291f150b02000000000000000000000000000005101a252e373e4346464646464646464645413b332a20160b00000000000000000000000000000000000000000000040a0e10121212121212121212110e0b060000000000000000000000000000000000000003070a0c0c0c0c0c0c0c0b08040000000000000000000013202c3946535f6c797e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7c6f6255493c2f221609000000010a141d262f38414a525657554f463d34363a3e424547494a4a4a4a49484643403c38343a434b525656534c433a31281f160d04000000000c18242f3a444d5458585858585858585858554e463c31261a0e0200131f2c3946525f6b768089929ba4a1988f867d746b625950473e352c28313a434c555e677079828b949da69e958c837a6f63564a3d3024170a000000000000000000000000000000000000030e1a26323e4955616d7985909ca8a89c9084786c6155493d33333333333a46525d6975818d99a5ab9f93877b7064584c4034291d110500000000000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e2e39444e59646f7a858f9aa5a89d92887d72675c51474855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000000d1926323e4b57636f7b87939fabaa9e92877b70655b524a4542414143454a5058626c76818c98a2a6aeb2a5988b7e7165584b3e3225180b000000000000000000000000000000000000050f19242e38424c56616b757f89949ea29a928a81797169605850483f352a1e1307000000000000000000000000000000000000000000000000000009131d27323c46505a646f79838d97a19f978f877e766e665d554d453b31261a0e02000000000000000000000000000000000000000000000008121c26303a454f59636d77828c96a0a098908880776f675e564e463c32271c1004000000000000000000000000000000000000000000000000050f18222c343c424546464646464646464645423d362d231a1006000000000000000000000000000000000005101a252e373e434646464646464646464645423c342c22180e0400000000000000000000000000000000000000000000000008111b252e373e434646464646464646464645413b332a21170d030000000000000000000000000000000009131c252c32373939393939393939393835302921180e040000000000000000000000000000000000000000010910151a1d1e1e1e1e1e1e1e1e1e1d1b17110b0300000000000000000000000000000003090f1417181919191919181714100b04000000000000000013202c3946535f6c79868c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c897c6f6255493c2f2216090000010a131c262f38414a535c636460584f463d42474b4e51535556575757565452504c48443f434c555d63635e564d433a31281f160c03000000101c2834404b565f6465656565656565656560584d42372b1e120600111e2a37434f5a646d768089929ba4a1988f867d746b625950473e35313a434c555e677079828b949da69e958c837a71685e53473b2e221509000000000000000000000000000000000000000a15212d3945505c6874808c97a3ada195897d7165594d42362a2627333f4a56626e7a86929ea9a69a8e83776b5f53473c3024180c0000000000000000000000000013202c3946535f6c798693a0aca194887b6e6154483b2e35404b55606b76818b96a1aca1968b81766b60554b404855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000000a16222e3b47535f6b77838e9aa5aea3988c81776d645c55514f4d4e4f52565b626a747e889395959ca6b2a5988b7e7165584b3e3225180b0000000000000000000000000000000000000008121c26303a454f59636d77828c96a0a49c938b837b726a625a51463b2f23170b0000000000000000000000000000000000000000000000000000010b16202a343e48535d67717b85909aa4a199908880786f675f574d42372b1f13060000000000000000000000000000000000000000000000000a141e29333d47515b66707a848e99a3a29a91898179706860584e43382c20140800000000000000000000000000000000000000000000000000061019222a3136383939393939393939393936322b241b11080000000000000000000000000000000000000009131c252c3237393939393939393939393836312a221a1006000000000000000000000000000000000000000000000000000009131c252c3237393939393939393939393835302921180f050000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c29241e170f060000000000000000000000000000000000000000010b131b2126292b2b2b2b2b2b2b2b2b2a27221c150d0400000000000000000000000000050d141b20232525252525252524201c160f060000000000000013202c3946535f6c7986939898989898989898989898989898989898989898989898989898989898989896897c6f6255493c2f221609000009131c252e38414a535c656e716a61584f484e53575a5e60626364646363615f5c5955504b4c555e676f6f685f554c433a31281e150b010000121f2b3844515d68707272727272727272716a5f53473a2e211408000e1b27323e49525b646d768089929ba4a1988f867d746b625950473e3a434c555e677079828b949da69e958c837a71685f564d42362b1f13060000000000000000000000000000000000000005111c2834404c57636f7b87939eaaa5998e82766a5e52463a2e232b37434f5b67737e8a96a2ada1968a7e72665a4e43372b1f13070000000000000000000000000013202c3946535f6c798693a0aca194887b6e6154483b313c46515c67727c87929da8a59a8f857a6f64594f443c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000006121e2a36424e5a66727d89949faaa99e93897f766d66615d5b5a5b5c5e62666d747c869092898a95a1aea5988c7e7265584c3f3225190c00000000000000000000000000000000000000000a141e29333d47515b66707a848e98a0a09d958d857c746c63574c3f33261a0d010000000000000000000000000000000000000000000000000000040e18222c37414b555f69747e88929ca0a09a928a817971695f53473b2e221509000000000000000000000000000000000000000000000000020d17212b353f4a545e68727c87919ba0a09b938b837a726a6055493c3023170a00000000000000000000000000000000000000000000000000000710181f25292c2c2c2c2c2c2c2c2c2c2c2a26201a12090000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c29251f181007000000000000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c29241f170f0600000000000000000000000000000000000000010910161a1e1f20202020202020201f1c19130d050000000000000000000000000000000000000000000a131d252c323638383838383838383837332e271f160c020000000000000000000000040e171f262b3032323232323232302d272018100600000000000013202c3946535f6c798693a0a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a296897c6f6255493c2f2216090005101a252e37404a535c656e777c736a615854595e63676a6d6f707171706f6e6b6865615c57555e6770797a71675e554c433a30271d1308000013202c3946535f6c797e7e7e7e7e7e7e7e7b6f6255483c2f221509000a16212c374049525b646d768089929ba4a1988f867d746b62595047434c555e677079828b949da69e958c837a71685f564d443b30251a0e0200000000000000000000000000000000000000000c18232f3b47535e6a76828e9aa5aa9e92867a6e63574b3f3327303c48545f6b77838f9ba7a89d9185796d61564a3e32261a0f030000000000000000000000000013202c3946535f6c798693a0aca194887b6e6154483b38424d58636e78838e99a4a99e93897e73685d53483d3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000020e1a26323e4a55616c78838e99a3ada59b91888078726d6a686767686b6e72787e868f978c818794a0ada5988c7e7265584c3f3225190c0000000000000000000000000000000000000000020c17212b353f4a545e68727c879193939393938e867e74675b4e4135281b0e0200000000000000000000000000000000000000000000000000000006101a252f39434d58626c76808b9393939393938b837b6f6356493d3023160a00000000000000000000000000000000000000000000000000050f19232e38424c56606b757f899393939393938c847c7164584b3e3225180b000000000000000000000000000000000000000000000000000000060e14191d1f2020202020202020201f1d1a150f0800000000000000000000000000000000000000000000010910161a1e1f2020202020202020201f1d19140e060000000000000000000000000000000000000000000000000000000000010910161a1e1f2020202020202020201f1d19130d0600000000000000000000000000000000000000000000050a0e1113131313131313131312100d080200000000000000000000000000000000000000000006111b252f373d42454545454545454545433f3931281e130900000000000000000000010c16202931373c3e3f3f3f3f3f3f3d38322a22180e03000000000013202c3946535f6c798693a0acb2b2a79e9998989898989898989898989898989898989898989898989896897c6f6255493c2f221609000a16212c374049525c656e7780867c736a615f656a6f7376797b7d7d7d7d7c7a7875716d68625e67707982837970675e554c42392f24190d020013202c3946535f6c79868c8c8c8c8c8c887b6f6255483c2f2215090005101b252e374049525b646d768089929ba4a1988f867d746b6259504c555e677079828b949da69e958c837a71685f564d443b32291f140900000000000000000000000000000000000000000007131f2a36424e5a65717d8995a0aca3978b7f73675b4f44382c35404c5864707c8894a0aba4988c8074685d5145392d21160a000000000000000000000000000013202c3946535f6c798693a0aca194887b6e6154483b3e49545f6a74808a95a0aaa2978d82776c61574c41363c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000000000010507101c2936434f5c69768390908376695c4f4336291c1007050100000000000000000a16212d3944505b66717c87919ca5ada39a918a837d797675747475777a7e8389909890857a8693a0ada5988c7e7265584c3f3225190c000000000000000000000000000000000000000000050f19232d38424c56606a757f86868686868686868275685b4e4235281b0f020000000000000000000000000000000000000000000000000000000009131d27313b46505a646e788386868686868686867d7063564a3d3023170a000000000000000000000000000000000000000000000000000007111c26303a444f59636d778186868686868686867e7165584b3e3225180b0000000000000000000000000000000000000000000000000000000003090d111213131313131313131313110e090400000000000000000000000000000000000000000000000000050a0e111313131313131313131312110d09030000000000000000000000000000000000000000000000000000000000000000050a0e111313131313131313131312100d080200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17222d3741494e5151515151515151514f4a433a30251a0e0300000000000000000007121d28323b42484b4c4c4c4c4c4b49443c342a20150a000000000013202c3946535f6c7986939faab4ada1958c8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b897c6f6255493c2f221609000e1a26323e48525b646e7780898f867c736a6a70767b7f838688898a8a8a898784817d78736e677079828b8c837970675e544b41352a1e12060013202c3946535f6c7986939898989895887b6f6255483c2f221509000009131c252e374049525b646d768089929ba4a1988f867d746b6259555e677079828b949da69e958c837a71685f564d443b322920170d02000000000000000000000000000000000000000000020e1a26313d4955616c7884909ca7a79b9084786c6054483c303945515d6975818c98a4ab9f93877b7064584c4034291d1105000000000000000000000000000013202c3946535f6c798693a0aca194887b6e6154483b45505b66707b86919ca6a69b91867b70655b50453a2f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000000000000000111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c000000000000000000000000000000000000000000070d1114161c2936434f5c69768390908376695c4f4336291c1614110d070000000000000005111c28333f4a55606b75808a939ca5aca39b948e8986838181818284868a8f949b92887e7986939faca6998c7f7265594c3f3226190c0000000000000000000000000000000000000000000007111c26303a444e59636d7779797979797979797973675a4e4135281b0e0200000000000000000000000000000000000000000000000000000000010b151f2a343e48525c6771797979797979797979786e6256493c3023160a0000000000000000000000000000000000000000000000000000000a141e28323d47515b6570787979797979797979797064574b3e3125180b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000206090a0a0a0a0a0a0a0a0a0a0804000000000000000000000000000004101c28333f49535a5e5e5e5e5e5e5e5e5e5b554c41362b1f13070000000000000000000c18232f39444d5458585858585858554e463c31261b10050000000013202c3946535f6c79838e98a2acab9e92857e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7b6f6255493c2f22160900111e2a37434f5a646d76808992988f867c73757c82878b8f9294969797979593918d89847f797279828b94948b827970665d52463a2e2115080013202c3946535f6c798693a0a5a5a295887b6f6255483c2f2215090000010a131c252e374049525b646d768089929ba4a1988f867d746b625e677079828b949da69e958c837a71685f564d443b322920170e0500000000000000000000000000000000000000000000000915212d3844505c68737f8b97a3aca094887c7065594d41353e4a56616d7985919da9a69a8e83776b5f53473b3024180c00000000000000000000000000000013202c3946535f6c798693a0aca194887b6e615448414c57626c77828d98a2aa9f958a7f74695f54493e332f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f02000000000000000000000000000000000000000002070b111d2a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000000030b12181d2022222936434f5c69768390908376695c4f4336292222201d18120b030000000000000b17222d39444e59636e78818a939ba2a8a69f9a9592908e8e8e8f9093969a9a928980767885929faca6998c807366594c403326190d00000000000000000000000000000000000000000000000a141e28323d47515b656b6c6c6c6c6c6c6c6c6c6961564b3f3226190d000000000000000000000000000000000000000000000000000000000000030e18222c36404b555f686c6c6c6c6c6c6c6c6c6c675d52463a2e211508000000000000000000000000000000000000000000000000000000020c17212b353f49535e676c6c6c6c6c6c6c6c6c6c685e53483c2f23160a00000000000000000000000000000000000000000000000000000000000000000306080a0b0c0d0d0d0d0c0b0a080604010000000000000000000000000000000000000000000000000000000000000000000003070809090909090909090907040000000000000000000000000000000000000000000206090a0a0a0a0a0a0a0a0a0a080400000000000000000000000000000307090a0a0a0a0a0a0a0a0a0907030000000000000000000001080e12151717171717171717171614100b0500000000000000000000000006131f2c3844505b656a6b6b6b6b6b6b6b6b675e53473b2f23160a0000000000000000000f1c2834404b565e6465656565656560584d43382c21160a00000000121f2b3844505c67717c86909aa5ada1968c8277717171717171717171717171717171717171717171717171716a5f53473a2e21150800131f2c3946525f6b768089929ba1988f867c80878d92979b9fa1a3a4a4a3a2a09d9995908a847d828b949d9d948b82786e6256493d3023170a0013202c3946535f6c798693a0acafa295887b6f6255483c2f221509000000010a131c252e374049525b646d768089929ba4a1988f867d746b677079828b949da69e958c837a71685f564d443b322920170e0500000000000000000000000000000000000000000000000004101c28343f4b57636e7a86929eaaa5998d8175695d51463a424e5a66727e8a96a2ada1958a7e72665a4e42372b1f130700000000000000000000000000000013202c3946535f6c798693a0aca194887b6e61544848535e68737e89949ea9a3998e83786d63584d42372d2f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f0200000000000000000000000000000000000001070d13171c202a3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c000000000000000000000000000000000000020c151d24292d2f2f2f36434f5c69768390908376695c4f43362f2f2f2d29241d150c02000000000006111c27323d47525c666f78818990979da2a5a6a29e9c9b9a9a9b9d9f9c97908880776e7885919ea9a6998c807366594d4033261a0d0000000000000000000000000000000000000000000000020c16212b353f49535a5f5f5f5f5f5f5f5f5f5f5e584f453a2e22160a0000000000000000000000000000000000000000000000000000000000000006101a242f39434d565d5f5f5f5f5f5f5f5f5f5f5c554b41352a1e120500000000000000000000000000000000000000000000000000000000050f19232d38424c555c5f5f5f5f5f5f5f5f5f5f5c564d42372b1f1307000000000000000000000000000000000000000000000000000000000106090d101214161819191a1a191918171513110e0b07030000000000000000000000000000000000000000000000000000000000050b0f131516161616161616161514110c07000000000000000000000000000000000001080e12151717171717171717171614100b0500000000000000000000040a0f131617171717171717171716130f0a0300000000000000040c13191e2223242424242424242423201c17100800000000000000000000000815212e3b4754606d7678787878787878786f64574b3e3125180b000000000000000000121e2b3744505c67707272727272716a5f54493e32271b10040000000f1c2834404b55606a747e89939da7a89e94897f756b656565656565656565656565656565656565656565656460584e42372b1f120600131f2c3946525f6b768089929ba4a1988f868b92989ea3a7a8a5a3a2a2a3a4a6a9a5a19b958f888b949da69e958c837a6f63564a3d3024170a0013202c3946535f6c798693a0acafa295887b6f6255483c2f22150900000000010a131c252e374049525b646d768089929ba4a1988f867d747079828b949da69e958c837a71685f564d443b322920170e0500000000000000000000000000000000000000000000000000000b17232f3b46525e6a76828d99a5a99d91867a6e62564a3e47535f6b77838e9aa6a89c9185796d61554a3e32261a0e0300000000000000000000000000000013202c3946535f6c798693a0aca194887b6e6154484f5a646f7a85909aa5a79d92877c71675c51463b31262f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000000000050c13191e23282c2f3744505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c0000000000000000000000000000000000000a141e272e35393c3c3c3c434f5c69768390908376695c4f433c3c3c3c39352e271e140a0000000000000b16202b36404a545d666f777e868c9196999c9e9fa09f9e9d9b9995918b857e766e6a7784919c9c9c9a8d8073675a4d4034271a0d000000000000000000000000000000000000000000000000050f19232d3741494f52535353535353535353514d463d33281d1206000000000000000000000000000000000000000000000000000000000000000008131d27313b444b5153535353535353535353504a43392f24190d02000000000000000000000000000000000000000000000000000000000007111b26303a434b5053535353535353535353504b443b30261a0f03000000000000000000000000000000000000000000000000000003090d1216191c1f212324252626262626252322201d1a17130f0b0601000000000000000000000000000000000000000000000000000810161b1f22222222222222222222201d18120a020000000000000000000000000000040c13191e2223242424242424242423201c1710080000000000000000060e151b1f22242424242424242424221f1b150e060000000000030d161e252a2e3030303030303030302f2d28221a1209000000000000000000000815222e3b4855616e7b858585858585857e7165584b3e3225180b000000000000000000131f2c3946525f6c787e7e7e7e7e7b71655a4f43382c2115090000000c17232e39444e58626c76818b959faaa59b91877d72685e585858585858585858585858585858585858585858554e463c31261a0f0300111e2a37434f5a646d768089929ba4a19893959ca3a9a49f9b9997969696979a9da1a6a7a09a94969da69e958c837a71685e53473b2e2215090013202c3946535f6c798693a0a3a3a295887b6f6255483c2f2215090000000000010a131c252e374049525b646d768089929ba4a1988f867d79828b949da69e958c837a71685f564d443b322920170e0500000000000000000000000000000000000000000000000000000006121e2a36424d5965717c8894a0aca2968a7e72675b4f434c58636f7b87939faba4988c8074685d5145392d21160a0000000000000000000000000000000013202c3946535f6c798693a0aca194887b6e61544b56606b76818c96a1aba1968b80756b60554a3f352a222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f02000000000000000000000000000000000810171e242a2f34383c3f44505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c000000000000000000000000000000000006111c263039404548494949494f5c69768390908376695c4f494949494845403930261c11060000000000040f19242e38424b545d656d747a8085898d8f9192939292918f8c8985807a736c6469768390909090908e8174675b4e4134281b0e0000000000000000000000000000000000000000000000000007111b252f373e434646464646464646464645413b342b21170c010000000000000000000000000000000000000000000000000000000000000000010b151f29323a404446464646464646464646443f3931271d1308000000000000000000000000000000000000000000000000000000000000000a141e2831393f444646464646464646464644403a32291f14090000000000000000000000000000000000000000000000000003090f14191e2225292b2e303132333333333231302e2c2a27231f1b16110c06000000000000000000000000000000000000000000000008121a21272c2e2f2f2f2f2f2f2f2f2f2d29231c140b02000000000000000000000000030d161e252a2e3030303030303030302f2d28221a120900000000000006101820262c2f3030303030303030302f2b2620180f06000000000b151f282f363a3d3d3d3d3d3d3d3d3d3c39332c241b11060000000000000000000815222e3b4855616e7b8892929292928b7e7165584b3e3225180b000000000000000000121f2b3844515d69737e898c8c8c82776b6054493d31251a0e02000007121d27323c46505a656f79838e98a2aca3998f847a70665c514b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b49433c342a20150900000e1b27323e49525b646d768089929ba4a3a0a1a7a59e98938f8c8a8989898b8d91969ba1a8a4a1a2a79e958c837a71685f564d42362b1f13060013202c3946535f6c7986939696969695887b6f6255483c2f221509000000000000010a131c252e374049525b646d768089929ba4a1988f86828b949da69e958c837a71685f564d443b322920170e0500000000000000000000000000000000000000000000000000000000020d1925313d4854606c78848f9ba7a79b8f83776b5f5347505c6874808c98a4ab9f93877b6f64584c4034281d11050000000000000000000000000000000013202c3946535f6c798693a0aca194887b6e6154525c67727d88929da8a49a8f84796f64594e43392e23222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000000000000020a121a22292f353b4044484b4e505d6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000b17222e38424b515555555555555c69768390908376695c555555555555514b42382e22170b00000000000008121c263039424b535b62696f75797d818384868686858482807d79746f69625b6875818383838383838275685b4f4235281c0f00000000000000000000000000000000000000000000000000000a131d252d3337393939393939393939393835302a22190f0500000000000000000000000000000000000000000000000000000000000000000000030d1720282f34383939393939393939393937342e271f150c0100000000000000000000000000000000000000000000000000000000000000020c161f272e34383939393939393939393938342f2820170d02000000000000000000000000000000000000000000000000070e141a20252a2e3235383a3c3e3f404040403f3e3d3b3936332f2b27221d17110b04000000000000000000000000000000000000000006111a242c33383b3c3c3c3c3c3c3c3c3c39342e261d140a0000000000000000000000000b151f282f363a3d3d3d3d3d3d3d3d3d3c39332c241b110600000000040e18222a32373b3d3d3d3d3d3d3d3d3d3b37312a21180e03000006121d27313a41474a4a4a4a4a4a4a4a4a49443e362d23180d0100000000000000000815222e3b4855616e7b88959e9e9e988b7e7165584b3e3225180b000000000000000000101c2935414c57626c77828e9893887c71655a4e42362a1e12060000010b16202a343e49535d67717c86909aa5aba0968c82786d63594f453e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3c38322a22180e0300000a16212c374049525b646d768089929eaaaca9a19a938d8783807d7c7c7c7e81858a90969ea5aeaea3978c837a71685f564d443b30251a0e020013202c3946535f6c7986898989898989887b6f6255483c2f22150900000000000000010a131c252e374049525b646d768089929ba4a1988f8d949da69e958c837a71685f564d443b322920170e050000000000000000000000000000000000000000000000000000000000000914202c3844505b67737f8b96a2ab9f93887c7064584c55616d7985919ca8a69a8e82766b5f53473b3024180c000000000000000000000000000000000013202c3946535f6c798693a0aca194887b6e615458636e79848e99a4a89e93887d73685d52473d32271c222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f0200000000000000000000000000020b141c242c333a41464b5054575a5c5e6a7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c00000000000000000000000000000000000f1b27333f4a545c616262626262626976839090837669626262626262615c544a3f33271b0f000000000000000a141e273039414951585e64696d7174767879797978777573706d68635e57596570767676767676767671665a4e4135281b0f0000000000000000000000000000000000000000000000000000010b131b21272a2c2c2c2c2c2c2c2c2c2c2c29251f181007000000000000000000000000000000000000000000000000000000000000000000000000050e161d24282b2c2c2c2c2c2c2c2c2c2c2b28231c150d03000000000000000000000000000000000000000000000000000000000000000000040d151d23282b2c2c2c2c2c2c2c2c2c2c2b28231d160e050000000000000000000000000000000000000000000000030b121920262b31363a3e414447494a4c4c4d4d4c4c4b494745423f3c38332e28231c160f07000000000000000000000000000000000000020d18232c363d44484949494949494949484540382f261b10050000000000000000000006121d27313a41474a4a4a4a4a4a4a4a4a49443e362d23180d010000000a15202a343c43484a4a4a4a4a4a4a4a4a48433c332a20150a00000b17232e39434c525657575757575757575550483f34291e120600000000000000000815222e3b4855616e7b8895a2aba5988b7e7165584b3e3225180b0000000000000000000c1824303b45505b66717c8893998d82766a5e52463a2e221609000000040e18222d37414b55606a747e89939da7a89e948a80756b61564c4238323232323232323232323232323232302c272018100600000005101b252e374049525b646e79838f9ca9a9a0989088827c7773716f6f707275797e858c939ca4ada195887d73685f564d443b32291f1409000013202c3946535f6c787c7c7c7c7c7c7c7c7a6e6255483b2f2215090000000000000000010a131c252e374049525b646d768089929ba4a19b999ea69e958c837a71685f564d443b322920170e050000000000000000000000000000000000000000000000000000000000000004101b27333f4b56626e7a86929da9a4988c8074685d515a65717d8995a1ada1958a7e72665a4e42372b1f1307000000000000000000000000000000000013202c3946535f6c798693a0aca194887b6e61545f6a75808a95a0aba2978c81766c61564b41362b2015222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f02000000000000000000000000010a141d262e363e454c52575c606467696b6c7784909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c0000000000000000000000000000000000121e2b3744505b666e6f6f6f6f6f6f6f7683909083766f6f6f6f6f6f6f6e665b5044372b1e1200000000000000020c151e272f373f464d53585d616467696b6c6c6c6b6b696764615c58524c545e666969696969696969675f554a3e3226190d000000000000000000000000000000000000000000000000000000010910161b1e202020202020202020201f1d19140d060000000000000000000000000000000000000000000000000000000000000000000000000000040c12181c1f202020202020202020201e1c17120b030000000000000000000000000000000000000000000000000000000000000000000000030b12171c1e202020202020202020201f1c18120c040000000000000000000000000000000000000000000000050d151d242b31373c41464a4e51535557585959595959575654524f4c48433f39342e2720191109010000000000000000000000000000000007121e29343e484f54555555555555555555514a41382d22160a000000000000000000000b17232e39434c525657575757575757575550483f34291e12060000030f1b26323c464e54575757575757575757544e453c31261b0f03000f1c28343f4b555d636363636363636363615a51463a2f23160a00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000008131e29343f4954606b76828e9992877b6e62564a3e3225190d0000000006111b252f39444e58626c76818b959faaa69b91877d72685e544a40352b2525252525252525252525252523201c160e06000000000009131c252f3b47525e6974808a95a0aaa0978e867e76706b676463626365696d737a818a929ba5a4998f84796e63584c41352920170d020000121e2b3744505c666e6f6f6f6f6f6f6f6f6f685e52463a2d211407000000000000000000010a131c252e374049525b646d768089929ba6a7a6a99f958c837a71685f564d443b322920170e050000000000000000000000000000000000000000000000000000000000000000000b17222e3a46525d6975818d99a4a99d9185796d61555e6a76828e9aa6a89c9185796d61554a3e32261a0e02000000000000000000000000000000000013202c3946535f6c798693a0aca194887b6e615b66717b86919ca7a69b90857a70655a4f453a2f241915222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f0200000000000000000000000009131d262f38404850575d63686c70737677797984909d9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c000000000000000000000000000000000013202c3946535f6c787c7c7c7c7c7c7c7c839090837c7c7c7c7c7c7c7c786c5f5346392c20130000000000000000030c151d252d343b41474c5155585b5d5e5f5f5f5f5e5c5a5854504c47424c545a5c5c5c5c5c5c5c5c5b554d43392d22160a0000000000000000000000000000000000000000000000000000000000050a0f111313131313131313131312100d08020000000000000000000000000000000000000000000000000000000000000000000000000000000001070c101213131313131313131313120f0b06000000000000000000000000000000000000000000000000000000000000000000000000000000060b0f121313131313131313131312100c07010000000000000000000000000000000000000000000000060e171f272e353c42484d52565a5d6062646566666666656463615e5b58544f4a453f39322b231b130b020000000000000000000000000000000a17232f3b46505a606262626262626262615c53493e33271b0e020000000000000000000f1c28343f4b555d636363636363636363615a51463a2f23160a000007131f2c37434e585f6363636363636363635f574e43372b1f130600121e2b3844505c676f70707070707070706c62574b3f3226190c00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000000020d17222d38434e5a65717d8995978b7e72665a4d4135281c0f030000000009131d27323c46505a656f79838d98a2aca3998f847a70665c51473d33291e18181818181818181818181714100a04000000000000030f1b2834404b57636f7a86919ca7a2988e857c746c655f5b58565556595d626870778089939da7a1968b8074695d52463a2e22160a0000000f1b28333f4a545d626363636363636363625e564c41362a1e110500000000000000000000010a131c252e374049525b646d76808995a2afb3a79a8e837a71685f564d443b322920170e050000000000000000000000000000000000000000000000000000000000000000000006121e2935414d5964707c8894a0aba195897d72665a636f7b87929eaaa3988c8074685c5145392d21150a00000000000000000000000000000000000013202c3946535f6c798693a0aca194877b6e61626d77828d98a3aa9f94897e74695e53493e33281d1315222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f02000000000000000000000006101b252f38414a525a61686e74787c808284858687929e9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3225190c070200000000000000000000000000000013202c3946535f6c798689898989898989899292898989898989898986796c5f5346392c2013000000000000000000030b131b232a30363c4045494c4e50525253535251504e4b4844403b3a42494e4f4f4f4f4f4f4f4f4e4a433b31271c110500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050f182029313940474d53595e62666a6c6f70727373737372716f6d6b6764605b56504a443d352d251d140b0200000000000000000000000000000d1a26333f4b57626b6f6f6f6f6f6f6f6f6d655b4f43362a1d1104000000000000000000121e2b3844505c676f70707070707070706c62574b3f3226190c00000916222f3b48545f6a7070707070707070706a5f54473b2f2215090013202c3946535f6c787d7d7d7d7d7d7d7d73665a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000000000000009141e27323d4955616c7885919b8e8276695d5044372b1e120500000000010b16202a343e49535d67717c86909aa4aba0968c82786d63594f453a30261c120b0b0b0b0b0b0b0b0b0a0804000000000000000007131f2c3844505c6874808b97a2a59b90867c736a625a544f4b49494a4d51575e666e77818b95a0a79c91857a6e62564a3e32261a0e0100000b17232e38424b5255565656565656565656534c443a3025190d0100000000000000000000040d161f28313a434c555e677079828b96a2afafa89b8f867c736a615950473e352c231a100700000000000000000000000000000000000000000000000000000000000000000000010d1925303c4854606b77838f9ba7a69a8e82766a5e6773808b97a3ab9f93877b6f63584c4034281d110500000000000000000000000000000000000013202c3946535f6c798693a0aca094877a6d6169737e89949faaa3988d83786d62574c42372c21170c15222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f0200000000000000000000020d18222d37414a535c646c73798084898c8f91929393999f9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f32251916130e08010000000000000000000000000013202c3946535f6c798693949494949494949494949494949494969386796c5f5346392c201300000000000000000000020911181f252b3035393c3f424445464646454443413f3c38342f31383e424343434343434343423e39322920150b000000000000000000000000000000000000000000000000000002050708090a0b0b0b0b0b0a090706030100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000305060708080808070604020000000000000000000000000000000000000000000000000000000000000000000000000000000306090c0e101112131313131212110f0d0b09060300000000000000000000000000000000000000000000000000040e17212a323b434a52585f656a6e7276797b7d7e808080807e7d7c7a7774706c67615c554e473f372f261d140a00000000000000000000000000000e1b2834414e5a67747c7c7c7c7c7c7c7c776b5e5245382c1f120500000000000000000013202c3946535f6c787d7d7d7d7d7d7d7d73665a4d4034271a0d01000a1724303d4a5763707c7d7d7d7d7d7d7d7c706356493d3023160a0013202c3946535f6c79868a8a8a8a8a8a8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000004101b2530394147505c6875818d9a9185786c5f53463a2d2014070000000000040e18222d37414b55606a747e88939da7a89e948a80756b61574c42382e24190f050000000000000000000000000000000000000a16232f3b4854606c7884909ca89f94897e746a61585049433f3c3c3d40454c545c656f79848e99a5a2968a7e73675a4e4236291d1104000006111c27303940464949494949494949494947423b32281e130800000000000000000000040d161f28313a434c555e677079828b949da7a3a2a6a1988f867c736b625950473e352c231a1108000000000000000000000000000000000000000000000000000000000000000000000814202c37434f5b67727e8a96a2aa9e92867a6e626c7884909ca8a69a8e82766b5f53473b2f24180c0000000000000000000000000000000000000013202c3946535f6c798693a0aca093877a6d656f7a85909ba5a79c91877c71665b50463b30251b100915222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000008131e29343e49525c656e767e858b9095989b9d9fa0a0a49f9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f322625231f19120b0200000000000000000000000013202c3946535f6c7986878787878787878787878787878787878d9386796c5f5346392c2013000000000000000000000000060d14191f24292d303335373839393939383635322f2c2824262d3235363636363636363635322e2720170e04000000000000000000000000000000000000000000000105090c0f1113151617181818181717151412100d0a07030000000000000000000000000000000000000000000000000206090a0a0a0a0a0a0a0a0a0907030003070a0d0f111314151515151412110e0c090501000000000000000000000000000000000000000000000000000000000000000003080c101316181a1c1e1f1f2020201f1e1d1c1a1815120f0b0702000000000000000000000000000000000000000000020c162029333c444d555c636a70757a7e8285888a8b8c8d8d8c8c8a898684807c78726d676059514941382f261c1208000000000000000000000000000e1b2834414e5b67748189898989898985786b5f5245382c1f120500000000000000000013202c3946535f6c79868a8a8a8a8a8a8173675a4d4034271a0d01000a1724303d4a5763707d8a8a8a8a8a8a8a7d7063564a3d3023170a0013202c3946535f6c798693979797978d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000000000000915212c37414b52575965717e8a9794877a6e6155483b2f22150900000000000006111b252f39444e58626c76818b959faaa69b91877d73685e544a40352b21170d0200000000000000000000000000000000000d1926323e4b5764707c8895a1a59a8e83776d62584e463e3732302f31343a424a535d67727d8894a0a79b8f83776a5e5245392d2014070000000a151e272f353a3c3c3c3c3c3c3c3c3c3c3a36302920170c02000000000000000000040d161f28313a434c555e677079828b949da69d96959ba4a1988f867d746b625950473e352c231a1108000000000000000000000000000000000000000000000000000000000000000000030f1b27333e4a56626e7985919da9a3978b7e7367707c8894a0aca195897d72665a4e42372b1f13070000000000000000000000000000000000000013202c3946535f6c798693a0aca09386796d6b76818c97a1aba0958b80756a5f544a3f34291f14090915222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f02000000000000000000020e1925303b46505a646e7780888f969ca1a5a8aaabacadac9f9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3232322f2a241d140b02000000000000000000000013202c3946525f6b777a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7e8b9386796c5f5346392c20130000000000000000000000000002080e13181c202426282a2b2c2c2c2c2b2a282623201c181c21262829292929292929292926221c160e0500000000000000000000000000000000000000000004080d1115181b1e2021232424252525242322211f1c1a1713100b07020000000000000000000000000000000000000001080e121517171717171717171716130f0b0f1316191c1e202121222221201f1d1b1815110d080300000000000000000000000000000000000000000000000000000000040a0f14181c1f222527292a2b2c2c2c2c2c2b2a282724221f1b17130e09030000000000000000000000000000000000000009141e28323b454e565f676e757b81868b8f9294969899999a9998979593908c88847e78726a635b534a41382e241a10050000000000000000000000000e1b2834414e5b6774818e969696969285786b5f5245382c1f120500000000000000000013202c3946535f6c798693979797978d8173675a4d4034271a0d01000a1724303d4a5763707d8a97979797968a7d7063564a3d3023170a0013202c3946535f6c798693a0a4a49a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000000000000d1925313d49535d6365656f7c889596897c6f6356493d3023170a0000000000000009131d27323c46505a656f79838d98a2aca3998f857a70665c51473d33291e140a00000000000000000000000000000000000f1b2834414e5a6773808c98a5a195897d72665b50463c342c26232224293038414b55606c77838f9ba79f93867a6d6155483c2f221609000000030c151d24292d2f3030303030303030302e2a251e170e05000000000000000000040d161f28313a434c555e677079828b949da69d948b89929ba4a1988f867d746b625950473e352c231a11080000000000000000000000000000000000000000000000000000000000000000000a16222e3a45515d6975818c98a4a79b8f83776b74818c98a5a89c9185796d6155493e32261a0e020000000000000000000000000000000000000013202c3946535f6c798693a0ac9f9386796c727d88939ea8a4998e84796e63584e43382d23180d020915222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f0200000000000000000008131f2b36414c57626c768089929aa1a7adb1b4b7b8b9b8ac9f9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c3f3e3f3e3b362e261d140b0200000000000000000000111e2a37434f5a656c6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d717e8b9386796c5f5346392c201300000000000000000000000000000003080c1014171a1c1e1f1f20201f1e1d1b191713100c1016191c1c1c1c1c1c1c1c1c1c1a16110b040000000000000000000000000000000000000000040a0f14191d2125282a2c2e30313132323131302f2d2b292623201c17130d080200000000000000000000000000000000040c13191e22232424242424242424221f1b161b1f2326282b2c2d2e2e2e2e2d2c2a2725211d19140e080200000000000000000000000000000000000000000000000002090f151b1f24282c2f3134363738393939393938373533312e2b27231f1a140e08020000000000000000000000000000000006101b25303a444d576068717880878d92979b9ea1a3a2a1a0a0a1a2a4a29f9c98948f89837c756d655c534a40362c22170d0200000000000000000000000e1b2834414e5b6774818e9ba2a29f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0a4a49a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4a4a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000000000000f1c2835414e5a656f7272727a8794978a7d7164574a3e3124180b00000000000000010b16202a343e49535d67717c86909aa4aba1968c82786e63594f453b30261c120800000000000000000000000000000002111d2a3643505c6975828f9ba89e9185796d61554a3f342b221b1716181e262f39444f5b67737f8b98a4a296897d7063574a3e3124180b00000000030b12191d2123232323232323232323211e1a140d05000000000000000000040d161f28313a434c555e677079828b949da69e958b828089929ba4a1988f867d746b625950473e352c231a1108000000000000000000000000000000000000000000000000000000000000000006111d2935414c5864707b87939fab9f93877b6f7885919da9a3988c8074685c5045392d21150a000000000000000000000000000000000000000013202c3946535f6c798693a0ac9f9286796e79848f99a4a89d92887d72675c52473c31271c1106000915222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000000c1824303c47535e69747e88929ba4acb2b8bdc1c3c5c5b8ac9f9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c454a4c4b4740382f261d140b020000000000000000000f1b27333e49535b60606060606060606060606060606065717e8b9386796c5f5346392c201300000000000000000000000000000000000004080b0d0f11121313131212100f0d0a070400050a0d0f10101010101010100f0d0a06000000000000000000000000000000000000000002080f151b2025292d313437393b3c3d3e3e3e3e3e3d3b3a3835332f2c28231e19130d070000000000000000000000000000030d161e252a2e3030303030303030302f2c2622272b2f323537393a3b3b3b3b3a383634312d29241f19130d0600000000000000000000000000000000000000000000060d141b20262b3034383b3e404244454646464645454342403d3a37332f2a25201a130c050000000000000000000000000000010c17222d37424c565f69727a838a91989ea3a49f9b98969494949495979a9da2a5a09b958e877f776e655c52483e33291e130800000000000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000000101c2936434f5c69767e7e7e7e8693988b7e7165584b3e3225180b0000000000000000040e18222d37414b555f6a747e88939da7a89e948a80756b61574c42382e24190f05000000000000000000000000000004121f2b3845515e6b7784919da89b8f8276695d5144392d2219100a090c141d27333e4a57636f7c8895a2a4988b7e7265594c3f3326190c000000000001070d11141616161616161616161615120e0902000000000000000000040d161f28313a434c555e677079828b949da69e958c8379768089929ba4a1988f867d746b625950473e352c231a110800000000000000000000000000000000000000000000000000000000000000010d1824303c48535f6b77838e9aa6a3978b7f737c8895a1aa9f93877b6f63584c4034281c1105000000000000000000000000000000000000000013202c3946535f6c798693a0ab9f92857875808b95a0aba1968c81766b60564b40352a20150a00000915222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f02000000000000000004101c2935404c58636f7a85909aa4adb6bdc4c9cdd0d2c5b8ac9f9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265584c50565957524a41382f261d140c0300000000000000000a16212d3741494f53535353535353535353535353535865717e8b9386796c5f5346392c2013000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050c131a20262c3135393d40434547494a4b4b4b4b4a49484644423f3c38342f2a241e18110a030000000000000000000000000b151f282f363a3d3d3d3d3d3d3d3d3d3b37322e33373b3f4144464748484847474543403d3935302b251e17100800000000000000000000000000000000000000000810181f262c32373c4044474a4d4f5051525353535251504e4c4a47433f3b36312b251e170f070000000000000000000000000007121e29343e49535e68717b848c959ca3a69f99948f8c8988878787898b8e91969ca2a6a099918980776e645a50453a30251a0e03000000000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000000101c2936434f5c6976838c8c8c8e97988c7e7265584c3f3225190c00000000000000000006101b252f39434e58626c76818b959faaa69c91877d73685e544a40362b21170d030000000000000000000000000006131f2c3946525f6c7985929fa69a8d8073675a4e4135281c11070000020b16222e3b4754616d7a8793a0a6998d8073665a4d4034271a0d010000000000000105080909090909090909090908060200000000000000000000040d161f28313a434c555e677079828b949da69e958c8379706d768089929ba4a1988f867d746b625950473e352c231a11080000000000000000000000000000000000000000000000000000000000000008141f2b37434f5a66727e8a95a1a89b8f8377808c99a5a69a8e82766a5f53473b2f23180c00000000000000000000000000000000000000000013202c3946535f6c798693a0ab9e9184787c87919ca7a59a90857a6f645a4f44392e24190e0300000915222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f0200000000000000000814202d3945515d6974808c97a2acb6bfc8cfd5d9dcd2c5b8ac9f9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e726558515a6265635c534a41392f261e150c030000000000000005101b252f373e44464747474747474747474747474b5865717e8b9386796c5f5346392c2013000000000000000000000000000000000000000000000004080a0b0c0c0d0d0d0c0b0a080604010000000000000000000000000000000000000000000000000000000000000000070f171e252b32373c4146494d50525456575758585757565553514e4b4844403b35302a231c150d050000000000000000000006121d27313a41474a4a4a4a4a4a4a4a4a48433c393f43474b4e5052535455555453524f4d4945413c363029221a120a01000000000000000000000000000000000109121a222930373d43484c505457595b5d5e5f5f5f5f5f5e5d5b595653504b47423c363029211911090000000000000000000000010d18242f3a45505b65707a838d969ea6a59c958e88837f7c7b7a7a7b7c7e81858b91989fa8a39b928980766c61574c41362b201409000000000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000000101c2936434f5c697683909898999f988c7e7265584c3f3225190c0000000000000000000009131d27323c46505a656f79838d98a2aca3998f857a70665c52473d33291f140a000000000000000000000000000613202c3946535f6c798693a0a6998c7f7266594c3f3326190d000000000613202c3946535f6c7986929fa79a8d8173675a4d4034271a0d0100000000000000000000000000000000000000000000000000000000000000040d161f28313a434c555e677079828b949da69e958c83797067646d768089929ba4a1988f867d746b625950473e352c231a1108000000000000000000000000000000000000000000000000000000000000030f1a26323e4a56616d7985919ca89f93877b84909ca9a195897d72665a4e42362b1f130700000000000000000000000000000000000000000013202c3946535f6c798693a0aa9d918478838d98a3a99e94897e73685e53483d32281d12070000000915222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f0200000000000000000b1724303c4955616d7985919da8b3bec8d1dae0e5dfd2c5b8ac9f9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265585a636c726e655c534b423930271e150c030000000000000009131d252d33373a3a3a3a3a3a3a3a3a3a3a3a3e4b5865717e8b9386796c5f5346392c2013000000000000000000000000000000000000000000050b1014161819191919191918171513100d09050100000000000000000000000000000000000000000000000000000000081119212830363d43484d5256595c5f61626364656564646361605d5b5854504b46413b352e261f170f060000000000000000000b17232e39434c52565757575757575757544e46454a4f54575a5d5f6061616161605e5c5956514d47413b342c241c130a010000000000000000000000000000000a131b242c343b42484e54585c606366686a6b6c6c6c6c6c6b696865635f5c57534d47413a332b231b12090000000000000000000007121e2935404b57616c77818c959fa8a59b938a837c7773706e6d6d6e6f72757a7f868d969fa8a49b92887e73685e53473c31251a0e020000000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000000101c2936434f5c697683909ca5a6a5988c7e7265584c3f3225190c00000000000000000000010b16202a343e49535d67717c86909aa4aba1968c82786e63594f453b30261c12080000000000000000000000000613202c3946535f6c7986939fa6998c7f7266594c403326190d000000000713202d3946535f6c7986929fa79a8d8173675a4d4034271a0d01000000000000000000000000000000000000000000000000000000000000030c161f28313a434c555e677079828b949da69e958c837970675e5b646d768089929ba4a1988f867d746b625950473e352c231a11070000000000000000000000000000000000000000000000000000000000000a16212d3945515d6874808c98a3a3978b7e8894a0a89c9085796d6155493d32261a0e0200000000000000000000000000000000000000000013202c3946535f6c798693a0a99d90837e89949faaa2988d82776c62574c41362c21160b010000000915222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f0200000000000000000d1a26333f4c5864717d8996a2adb9c5d0dae3ebebdfd2c5b8ac9f9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e72655a636c757e776e655d544b423930271e150c030000000000000b151f282f363a3d3d3d3d3d3d3d3d3d3d3d3d3e4b5865717e8b9386796c5f5346392c20130000000000000000000000000000000000000000070f161c2023252526262626262523221f1d1916110c07010000000000000000000000000000000000000000000000000008111a232b333a41484e54595e6265696b6d6f7071717171716f6e6c6a6764605c57524c463f38312921180f0600000000000000000f1c28343f4b555d6363636363636363635f584e50565b606467696b6d6e6e6e6e6d6b6865625d58534c453e362e251c130a000000000000000000000000000009121c252d363e464d53595f64696c70727576787979797978777674726f6c68635e59534c453d352d241b12080000000000000000000b17232f3a46515d68737e89939da7a79d93898178716b6763616060616365696e747b848c96a0aaa49a8f857a6f64594d42362a1f13070000000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000000101c2936434f5c697683909ca9b2a5988c7e7265584c3f3225190c0000000000000000000000040e18222d37414b555f6a747e88939da7a89e948a80756b61574c42382e241a0f05000000000000000000000006121f2c3945525f6b7885929ea69a8d8174675a4e4135281c11070000030c17232f3b4854616d7a8793a0a6998c807366594d4033271a0d000000000000000000000000000000000000000000000000000000000000000a151e28313a434c555e677079828b949da69e958c837a70675e55525b656e778089929ba4a1988f867d746b625950473e352c23190f04000000000000000000000000000000000000000000000000000000000005111d2834404c58636f7b87939fa79b8f858c98a4a3978c8074685c5045392d2115090000000000000000000000000000000000000000000013202c3946535f6c798693a0a99c8f8285909ba6a69c91867b70665b50453a30251a0f04000000000915222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f0200000000000000000f1c2935424e5b6774818d99a5b2becad6e1ecf5ebdfd2c5b8ac9f9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e7265636c757e8781776f665d544b423930271e150c030000000006121d27313a41474a4a4a4a4a4a4a4a4a4a4a4a4a4b5865717e8b9386796c5f5346392c20130000000000000000000000000000000000000007111921272c303132333333333231302e2c2926221d18120c05000000000000000000000000000000000000000000000008111a232c353d454c53595f65696e7275787a7c7d7e7e7e7e7d7c7b797674706c68635d57514a433b332a21180f0500000000000000121e2b3844505c676f70707070707070706a5f545b61676c70737678797b7b7b7a797775726e69645e57504840372e251c120800000000000000000000000006111b242e37404850575e656b7075797c7f81838485868686858483817e7b78746f6a645e574f473f362d241a10060000000000000004101c28343f4b57626e79848f9aa5aba0958b81776e67605b575554535456595d6369717a848e99a4aca1968c81756a5e53473b2f23170b0000000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000000101c2936434f5c697683909ca9b0a5988c7e7265584c3f3225190c00000000000000000000000006101b252f39434e58626c76818b959faaa69c91877d73695e544a40362b21170d030000000000000000000004121e2b3844515e6a7784909da89b8f8276695d5145392e2319110b0a0d151e28333f4b5763707c8995a2a4978b7e7165584c3f3225190c00000000000000000000000000000000000000000000000000000000000006111c27313a434c555e677079828b949da69e958c837a71685e554c49535c656e778089929ba4a1988f867d746b625950473e352b21160b0000000000000000000000000000000000000000000000000000000000020d18242f3b47535f6a76828e9aa6a09792959ea99f93877b6f63574c4034281c10050000000000000000000000000000000000000000000013202c3946535f6c798693a0aa9d91898c97a2aa9f958a7f746a5f54493e34291e130900000000000915222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000111e2a3744505d6a76838f9ca8b5c1cedae6f2f8ebdfd2c5b8ac9f9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e726568747e87908a81786f665d544b423930271e150d040000000b17232e39434c5256575757575757575757575757575865717e8b9386796c5f5346392c2013000000000000000000000000000000000000050f19232b33383c3e3f3f4040403f3e3d3b3835322e29231d160f0700000000000000000000000000000000000000000006101a232c353e474f565e646b70757a7e818487888a8b8b8b8b8a89878683807c78746e69625c544d453c332a21170d0300000000000013202c3946535f6c787d7d7d7d7d7d7d7c70645f666c72777c80838586878888878684817e7a756f69625a524940372e241a100500000000000000000000030e18222d364049525a626970767c8185888b8e90919293939292918f8d8b8884807b756f68615951483f362c22180e030000000000000814202c3844505c68737f8a96a1aca59a8f84796f655c554f4b484747484a4d51585f68727c87929ea9a89d92867b6f63584c4034281c0f0300000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000000101c2936434f5c697683909ca3a3a3988c7e7265584c3f3225190c0000000000000000000000000009131d27323c46505a656f79838d98a2aca3998f857a70665c52473d33291f140a0000000000000000000001101d2936434f5c6875828e9ba79e9285796d61554a3f352b231b1716191f27303a45505b6773808c98a4a195897c6f63564a3d3124170b0000000000000000000000000000000000000000000000000000000000000b17222e38424c555e677079828b949da69e958c837a71685f564c43414a535c656e778089929ba4a1988f867d746b625950473d32271b0f030000000000000000000000000000000000000000000000000000000008131e29333e47515a66717d8995a1a9a29fa1a7a69a8e82766a5f544a40362c21170b0000000000000000000000000000000000000000000013202c3946535f6c798693a0aca39a95979ea9a3998e83786e63584d42382d22170c0200000000000915222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f020000000000000000121f2c3845525e6b7885919eaab7c4d0dde9f6f8ebdfd2c5b8ac9f9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e726567727b848d938a81786f665d544b423930271f160d0300000f1c28343f4b555d63636363636363636363636363636365717e8b9386796c5f5346392c20130000000000000000000000000000000000000b16212b353d44484b4c4c4c4c4c4c4b494745423e39342f282119110800000000000000000000000000000000000000030d18222c353e47505961686f767c81868a8e9193959697989898979694928f8c8984807a746d665f574e453c33291f150b000000000000121f2c3945525f6b78858a8a8a8a8a8a7e72656970777e83888c8f91939495959493918e8a86807a736c645b524940362c22170c020000000000000000000a151f2a343e48525b646c747b81878c9195989a9c9e9f9fa09f9f9e9c9a9794908c86817a736b635a51483e342a1f150a0000000000000c1824303c4854606c7884909ba7aba094897d72675d534b433e3b3a3a3b3d41464e56606b76818c98a4aea3978c8074685c5044382c1f130700000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000000101c2936434f5c6976839096969696968c7e7265584c3f3225190c00000000000000000000000000010b16202a343e49535d67717c86909aa4aba1968c82786e63594f453b30261c1208000000000000000000000e1b2734404d5966727e8b97a4a295897d72665b51473d352d272423252a3139424c56616c7884909ca89e9286796d6054473b2e2215090000000000000000000000000000000000000000000000000000000000000e1b27333f4a545e677079828b949da69e958c837a71685f564d433a38414a535c656e778089929ba4a1988f867d746b62594f44382c1f1307000000000000000000000000000000000000000000000000000000030e1925303b454f59636c757d86929fa4a2a1a1a3a4978b7f776f665c52483e33281d110600000000000000000000000000000000000000000013202c3946535f6c798693a0acaca5a2a3a8a79d92877c71675c51463c31261b10060000000000000915222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f02000000000000000013202c3946535f6c7986929facb8c5d2dfebf8f8ebdfd2c5b8ac9f9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e72656069727a838c938a81786f665d544b423931281f150b0000121e2b3844505c676f707070707070707070707070707070717e8b9386796c5f5346392c2013000000000000000000000000000000000005101c28333d474f5557585959595958575654514e4a45403a332b231a11080000000000000000000000000000000000000a151f29343e475059626b727a81878d92969a9da0a2a3a2a2a2a2a3a2a19f9c9995908b857f78706960574e453b31271d12080000000000111e2b3844515e6b778491979797978c80736a727a82898f94989b9ea0a1a1a1a19f9d9a96918c857e766d645b52483e33291e1308000000000000000005101b26313c46505a646d757e858c93989da1a4a5a29f9e9d9c9c9d9fa1a5a4a09c97928c857d756c635a50463c31261b100500000000030f1b2834404c5865717d8995a1aca79b8f83776c61564b4139322f2e2d2e31353c444e5964707b87939faba89c9084786c6054483b2f23160a00000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000000101c2936434f5c697683898989898989897e7265584c3f3225190c0000000000000000000000000000040e18222d37414b555f6a747e88939da7a89e948a80756b61574d42382e241a0f050000000000000000000c1825313e4a56636f7b8894a0a69a8f83786d63594f473f3833303031353b424b545e68737d8994a0a69a8e8276695d5145382c1f1306000000000000000000000000000000000000000000000000000000000000111d2a37434f5b667079828b949da69e958c837a71685f564d433a312f38414a535c656e778089929ba4a1988f867d746b6054483b2f22150900000000000000000000000000000000000000000000000000000008131f2b36414c57616b757e878f979c98959495979b9b918981786e645a4f44392e23170b00000000000000000000000000000000000000000013202c3946535f6c798693a0acb6b1aeafaba1968b80756b60554a40352a1f140a000000000000000915222f3c4855626f7b8895a2ada09386796d6053463a2d20130700000000000000000b1724313e4a5764717d8a97a4b1a89c8f8275685b4f4235281c0f02000000000000000013202c3946535f6c798693a0acb9c6d3dfecf9f8ebdfd2c5b8ac9f9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e72655e6068717a838c938a81786f665d544b433a31271c11060013202c3946535f6c787d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7e8b9386796c5f5346392c201300000000000000000000000000000000000814212d39444f5960646566666666656463605e5a56514b443d352c231a10060000000000000000000000000000000006111c26313b464f59626b747c848c92989ea2a4a09c99979695959697989b9ea1a5a19c97908a827a726960574d43392e24190e0300000000111e2a3744515d6a7784909da4a49a8d8173727c858d949a9f9c9a999898999b9da1a5a6a29d97908880766d645a4f453a2f24190e03000000000000000a16212d38434d58626c767f8890979ea4a8a29d99959391909090919295989da2a8a39d968f877e756c62584d43382d22160b0000000005121e2b3743505c6875818d99a5afa3978b7e73675b4f44392f2722212122242a323d48535f6b77838f9ba7ada195887c7064574b3f3226190d01000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000000101c2936434f5c69757c7c7c7c7c7c7c7c7c7165584b3f3225180c00000000000000000000000000000006101b252f39434e58626c76818b959fa9a69c91877d73695e544a40362b21170d0300000000000000000916222e3b47535f6b77838f9ba6a0948a7f746b61595049433f3d3c3e41464d545d66707a848f9aa6a195897d7266594d4135291c1004000000000000000000000000000000000000000000000000000000000000121e2b3845515e6b78828b949da69e958c837a71685f564d433a3128262f38414a535c656e778089929ba4a1988f867c6f6356493c302316090000000000000000000000000000000000000000000000000000000c1824303c47535e69737d87909997908b8988888a8f959b938a80766c61564a3f33281c1004000000000000000000000000000000000000000013202c3946535f6c798693a0acb5b5b5afa59a8f84796f64594e44392e23180e03000002050709090915222f3c4855626f7b8895a2ada09386796d6053463a2d201307000000000001070b0e1724313e4a5764717d8a97a4afa89c8f8275685b4f4235281c0f0c090400000000000013202c3946535f6c798693a0acb9c6d3dfecf9f8ebdfd2c5b8ac9f9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e726b6b6b6b6b7179828b938a81786f665d554c43392e23170b0013202c3946535f6c79868a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8f9386796c5f5346392c201300000000000000000000000000000000000a1724303d4955616b70727273737372716f6d6a66625c564f473e352c22170d020000000000000000000000000000010c17222d38434d57616b757e868f969da4a59e9994908d8b898888898a8c8e91959aa0a6a29b948c847b72695f554b40352b20150900000000111d2a3743505d6a7683909daaa79a8e81747b858e969c9793908d8c8c8c8c8e91959aa0a7a8a19a928980766c61574c41362b1f1408000000000000040f1b27323e49545f6a747e88919aa2a9a59e97918d8986848383838486898c91979da4a8a19990877e74695f54493e33281c11050000000815212e3a46535f6c7884919da9ac9f93877a6e62564a3f33281d1614141518202b37434e5a66737f8b98a4b0a5988c8073675a4e4235291c1003000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000000000000f1b2834414d59646d6f6f6f6f6f6f6f6f6f6a6055493d3024170b0000000000000000000204040404040409131d27323c46505a656f79838d98a2aca3998f857a70665c52483d33291f150a000000000000000006121e2b37434f5b67737e8a95a1a69b91877d736b625b544f4c4a494a4d52575e666f78828c96a1a69b9084786d6155493d3125190d00000000000000000000010202020202020202020201000000000000000000111e2b3744505d68737c858e979e958c837a71685f564d443a31281f1d262f38414a535c656e778089929b988f867d746b6054483b2f221509000000000000000000000000000000000000000000000000000004101c2835404c58646f7a858f99958d85807c7b7b7e848b939c92887d72675b5044382c201407000000000000000000000000000000000000000013202c3946535f6c798693a0a8a8a8a8a89e93887d73685d52483d32271c120701060a0e111415161616222f3c4855626f7b8895a2a8a09386796d6053463a2d20130700000000060d12171a1c24313e4a5764717d8a97a2a2a29c8f8275685b4f4235281c1b19140f09010000000013202c3946525f6c7985929facb8c5d2deebf8f8ebdfd2c5b8ac9f9285786b5f5246525f6c7986929c908376695c4f4336291c100300000000000013202c3946535f6c7986938c7e787878787878787879828b948a82786f675e554a3f33271b0f0013202c3946535f6c798693939393939393939393939393939393939386796c5f5346392c201300000000000000000000000000000000000b1825323e4b5865717d7e7f8080807e7d7c7976726d68615950473e34291e1308000000000000000000000000000006121d28343f4a545f69737d879098a0a8a29b938d8884817e7c7b7b7c7d7f8285898f959ca3a69e968e857b71675c52473c31261a0f04000000101d2a3643505d697683909da9a89b8e8278838d9796908b878381807e7e808285898e959ca4aca49b92887d73685d52473c3025190e0200000000000814202c38434f5a65717b86909aa3aca49b938c86817c797776767677797c80858c939ba3aba29990867b71665b4f44392d21160a0000000a1724303d4956626f7b8894a0ada99c9083776b5e52463a2e22160b0707090f1a26323e4a57636f7c8895a1aea89b8f83766a5d5144382b1f1205000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000000000000c1825313c47525b6163636363636363636360584f44392d21150800000000000000060b0e101111111111111116202a343e48535d67717b86909aa4aba1978c82786e64594f453b31261c120800000000000000030e1b27333e4a56626d79848f9aa5a2988f857c746d66605b58565657595d63697078818a949da8a0958a7e73685c5045392d2115090000000000000001060a0d0f0f0f0f0f0f0f0f0f0f0e0b07020000000000000f1c2834404c57616a737c858e958c837a71685f564d443b32281f16141d262f38414a535c656e778089928f867d746b62594f43382c1f130700000000000000000000000000000000000000000000000000000713202c3845515d6975808c97978d837b746f6e6f7278818a949a8f84786c6054483c3023170b000000000000000000000000000000000000000013202c3946535f6c7986939b9b9b9b9b9b978c82776c61564c41362b20160b070d12171b1e2022232322222f3c4855626f7b88959b9b9b9386796d6053463a2d2013070000000710171e23272929313e4a5764717d8a95959595958f8275685b4f423529292825201a130b02000000121f2b3845515e6b7784919daab7c3d0dce9f5f8ebdfd2c5b8ac9f9285786b5f5246525f6c7986929c908376695c4f4336291c100902000000000013202c3946535f6c7986938d85858585858585858585858a95948b827870675c5044372b1e110013202c3946535f6c798686868686868686868686868686868686868686796c5f5346392c201300000000000000000000000000000000000b1825323e4b5865717e8b8c8c8c8c8b8a8886837e79726b625950453b3024190d02000000000000000000000000000b17232e3a45505b66717b858f99a2aaa2999089827c777471706f6f6f707275797d838a919aa2a8a0968d83796e63594d42372b201409000000101d2936434f5c697683909ca9a89c8f82808a95938c857f7a77747372727375787d838a929ba5ada39a8f857a6f64584d41362a1e120700000000000c1824303c4854606b77828d98a2aca59b9289817a75706d6b6a69696b6d70747a8189919aa4aba2988d82776c6155493e32261a0e0200000c1926323f4b5865717e8a97a3b0a69a8d8174685b4f42362a1e12060000000a16222e3b4754606c7986929fabab9e9285796c6053463a2d211407000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000000000000814202b3640495055565656565656565656544e463d33281c10040000000000040b12171b1d1e1e1e1e1e1e1e1e1e222c37414b555f6a747e88939da7a89e948a80756b61574d42382e241a0f050000000000000a151e28313a45515c68737e89939eaaa1978f867e77716c676563636466696e747b828a939ca6a4998e83786d62574b40352c23190f040000000000050c12171a1b1c1c1c1c1c1c1c1c1c1a17130d0700000000000c18242f3b454e57616a727b858c837a71685f564d443b322920160d0b141d262f38414a535c656e778089867d746b625950473d32271b0f0300000000000000000000000000000000000000000000000000000916222f3b4854616d7985919c90857b7169636162676f78828d9995897d7164584c3f33261a0d000000000000000000000000000000000000000013202c3946535f6c79868e8e8e8e8e8e8e8e867b70655a4f453a2f241a0f0d13181e23272a2d2f30302f2d2f3c4855626f7b888e8e8e8e8e86796d6053463a2d201307000006101922292f333536363e4a5764717d888888888888888275685b4f4236363634312c251d140b000000111d2a3743505c6976828f9ba8b4c1cdd9e5f1f8ebdfd2c5b8ac9f9285786b5f5246525f6c7986929c908376695c4f4336291e1a140d050000000013202c3946535f6c798693959292929292929292929292949b9d948b82786c5f5245392c1f1200131f2c3946525f6b767979797979797979797979797979797979797979766b5f5246392c1f1300000000000000000000000000000000000b1825323e4b5865717e8b98999999989795928f8a847d756b62574c41352a1e120600000000000000000000000004101c28343f4b56616d77828d97a1aba39990877e77716b6765636262636466696d72788088909aa4a89f958b80756a5f53483d3125190e020000101c2936434f5c697683909ca9a99c8f838691938a817a736e6a6866656566696d72788089939da7aba1968b8075695e52463b2f23170b00000000030f1c2834404d5965707c88939fa9a99e938980776f6964615e5d5c5d5e6064696f767f89929da7a99f94897d72665a4e42362a1e120600000e1b2834414d5a6773808d99a6b1a4988b7e7265594c4033271a0e0200000006131f2b3844515e6a7783909da9ada194877b6e6255483c2f221609000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000000030f1a242e373f454849494949494949494947433c342b21160b0000000000050e161d23272a2a2a2a2a2a2a2a2a2a2a2a2f39434e58626c76818b959fa9a69c92877d73695e544a40362c21170d030000000006111c27313a434c555e677079838f9ca9a9a1989089827c787471706f7072757a7f858c949ca5aea296897d746b625950473e352b21160b000000000710171e23262828282828282828282827241f1811090000000007131e29333c454e576069727b837a71685f564d443b322920170e04020b141d262f38414a535c656e77807d746b625950473e352b21160a0000000000000000000000000000000000000000000000000000000b1824313e4a5763707c8995978b7f74695f5754565d66717c8894998d8074675b4e4135281c0f020000000000000000000000000000000000000013202c3946535f6c798282828282828282827e74695e53493e3329211712191e24292e3336393b3c3c3c3a373c4855626f7b82828282828282796d6053463a2d20130700030e18222c343a3f424242424a5763707b7b7b7b7b7b7b7b7b74685b4f42424242413d372f261c120700000f1c2835414e5a6773808c98a5b1bdc9d4e0eaf4ebdfd2c5b8ac9f9285786b5f5246525f6c7986929c908376695c4f43362e2b251f170e0500000013202c3946535f6c79868b8b8b8b8b8b8b8b8b8b8b8b8b8e98988f867d74695e5145382b1f1200111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b645a4f43372a1e1100000000000000000000000000000000000b1825323e4b5865717e8b8d8d8d8d8e9194999b958f877d73695d52463a2e22160a0000000000000000000000000915212d3844505c67737e89949fa9a79c91877e756d65605b585655555657595d61676e757e88929ca7a79c91877b7065594d42362a1e12060000101c2936434f5c697683909ca9aa9e928a8d958a81786f68635e5b5958595a5c61676e77818b95a0aba89d91867a6f63574b3f33271b0f0300000006121f2b3844505d6975818d999c9d9f988c82776e655e585452504f505154585e656d76808b96a1aca59a8e82776b5f53473a2e2216090000101c2936424f5c6875828e9ba8afa296897c7063574a3d3124180b0000000003101d2936424f5c6875828e9ba8afa396897d7063574a3d3124170a000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000000000000008121c252d34393c3c3c3c3c3c3c3c3c3c3b37322b22190f0500000000030d1720282e3336373737373737373737373737373c46505a656f79838d98a2aca3998f857a70665c52483d33291f150a000000000b17222e38424c555e677079828b949faba9aaa29b948e8884807e7c7c7d7e82868b91979ea6aaaba59990877d746b625950473d32271b0f03000006101921292f3335353535353535353535332f2a231b1208000000020d17212a333c454e576069727971685f564d443b322920170e050000020b141d262f38414a535c656e76746b625950473e352c23190f040000000000000000000000000000000000000000000000000000000c1926333f4c5965727e8b9894877b6f63574d484b545f6b7884919c8f8276695c504336291d100300000000000000000000000000000000000000121f2c3845515e6973757575757575757575746d62574d47423b33291f1e242a2f353a3f4346484949484744404754606b7475757575757575736a5e5245392c1f13060009141f2a343e454b4f4f4f4f4f545f696e6f6f6f6f6f6f6f6f6c63584f4f4f4f4f4d4841382e24190d02000d1926323f4b5764707c8894a0acb8c3ced8e2eaebdfd2c5b8ac9f9285786b5f5246525f6c7986929c908376695c4f433d3b36302920160c02000013202c3946535f6c797e7e7e7e7e7e7e7e7e7e7e7e7e7e88958f867d746b62584d4135291d10000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5a52483e32261a0e00000000000000000000000000000000000b1825323e4b5865717e82818080818284888d959e998f857a6e63574b3e3226190d0000000000000000000000000c1925313d4955616c78848f9aa5aca1958a80756c635b544f4c4a4948494b4d51565c646c76808b96a1aca3988d81756a5e52463a2e22160a0000101c2936434f5c697683909ca9afa49b96988e83786f665e57524f4d4c4c4d50555c656f79848f9aa6aea3978b8073675b4f43372b1f13060000000714212e3a4753606c79858b8d8f919392877b70655c534d484543434345484c535b646e7984909ba7ab9f93877b6f63574a3e3225190d0000111e2a3744505d6a7683909da9aea194887b6e6255483c2f22160900000000000e1b2734414d5a6773808d9aa6b1a4978b7e7165584b3e3225180c000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000000000a131b22282d2f3030303030303030302e2b262019100700000000000a151f2932393f4344444444444444444444444444444448535d67717b86909aa4aba1978c82786e64594f453b31261c12070000000e1b27333f4a545e677079828b949da6a09c9fa5a59f9994908d8a89898a8b8e92969ca2a9a29e9fa4a29990877d746b62594f44382c1f130700030e18222b333a3f42424242424242424242403b352d241a1005000000050f18212a333c454e5760696c685f564d443b322920170e0500000000020b141d262f38414a535c656a69625950473e352c231a1107000000000000000000000000000000000000000000000000000000000d192633404c596673808c999286796c5f53463b43505c6976838f9c9084776a5d5044372a1d110400000000000000000000000000000000000000101d2935414d58616768686868686868686868635b5656534d453b3126292f353b41464b4f525556565553504c474f5a6267686868686868686761584d4236291d1104000d1925313c4650575b5c5c5c5c5c5c5e626262626262626262605c5c5c5c5c5c5c59534a40352a1e1206000a16232f3b4854606c7884909ba7b2bcc6d0d8dfe4dfd2c5b8ac9f9285786b5f524a525f6c7986929c908376695c4f4a4947423b32281e13080000121f2b3844505c68707171717171717171717171757e878f8f867c746b625950463c3025190d000a16212c3740484f525353535353535353535353535353535353535353524f4840372c21160a00000000000000000000000000000000000b1824313e4a57636f76757473737475787c838c96a1978b7f73675a4e4135281c0f020000000000000000000004101c2935414d5965717d8995a0aca79b9084796e635a5149433f3d3c3c3c3e41454a525a646e7984909ba7a99e92867a6f63574b3e32261a0e0100101c2936434f5c697683909ca9b6ada69e93877c71675d544c4642403f3f41444b535d67727d8995a1ada89c9084786c5f53473b2f22160a0000000814212e3b4754616d797d7e818284868882766a5e544a423c38373637383c4149525d68737e8a96a2aea3978b7f73665a4d4135281c0f0300121f2b3845515e6b7884919eaaada093867a6d6054473a2e21140700000000000d1926333f4c5966727f8c99a5b2a5988c7f7266594c3f3326190c000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000000000000000010911171c2022232323232323232323221f1b150e07000000000004101c27313b444b4f5151515151515151515151515151515151555f6a747e88939da7a89e948a80756b61574d42382e23180d010000111d2a37434f5b667079828b949da69e9590939aa1a7a5a09c9997969696989a9ea2a7a49e9791939ba4a29990877d746b6054483b2f2215090008141f2a343d454b4e4f4f4f4f4f4f4f4f4f4c463f362c21160b00000000060f18212a333c454e575d5f5c564d443b322920170e05000000000000020b141d262f38414a535a5e5d5850473e352c231a110800000000000000000000000000000000000000000000000000000000000d192633404c596673808c999386796d6054484045505d697683909c9083766a5d5044372a1d1104000000000000000000000000000000000000000d1925303b464f565a5b5b5b5b5b5b5b5b6063636363625f574d42372e343a40464c51575b5f61636362605c58524c50575b5b5b5b5b5b5b5b5b564f463c3125190d0100111d2936424d58626869696969696969676157555555555c656969696969696969655c52463a2e2216090007131f2c3844505c67737e8a95a0aab4bec6cdd4d8dcd2c5b8ac9f9285786b5f5656565f6c7986929c908376695c565656534c443a3025190d0100101c2834404b565e646565656565656565656d757e87908f867c736a625950473e342a1f14080005101a252e373e4346464646464646464646464646464646464646464646433e372e251a100500000000000000000000000000000000000916222f3b47525d65696867666667686b717a85919d9b8f8276695d5043372a1d1104000000000000000000000713202c3845515d6975828e9aa5aea2968a7e73685c52483f3833302f2f303134394048525d68737f8b96a3afa3978b7f73675b4e42362a1d110500101c2936434f5c697683909ca9b6b1a5998d82766b60554b423b363332323439414b56616d7884909ca8aca094887c6f63574a3e3225190c0000000713202c3945515d676e7072747678797b7d72665a4e4240403f3e3d3b393637414b56626e7a86929eaba79b8f8276695d5044372b1e120500131f2c3945525f6c7885929facac9f9286796c5f5346392d20130600000000000c1825323f4b5865717e8b98a5b1a6998d807366594d4033271a0d000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000000000000060c10141616161616161616161615130f0a040000000000000915212d38434d565b5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d626c76818b959fa9a69c92877d73695f544a4035291d12050000121e2b3845515e6b78828b949da69e958c83898f969ca1a5a8a6a4a3a3a3a5a7a7a39e99938c8589929ba4a2998f867c6f6356493c30231609000d1925303c464f575b5b5b5b5b5b5b5b5b5b5851483e33271b0f0300000000060f18212a333c454c5152504b443b322920170e050000000000000000020b141d262f3841484e51504d463e352c231a11080000000000000000000000000000000000000000000000000000000000000c1925323f4c5865727e8b9795887c706459514d4f57616d7985919b8f8275695c4f4336291d10030000000000000000000000000000000000000008141f2a343d454b4e4e4e4e4e4e4e56616b6f6f6f6f6f695f53473b393f454b52575d62676b6e6f6f6e6c68635d564e4b4e4e4e4e4e4e4e4e4e4b453d342a1f14090000121f2c3845525e6a737575757575757573695d51484b57636e75757575757575756e63574a3e3124180b00030f1b27333f4b57626d79848e98a2acb4bcc2c8cccfd1c5b8ac9f9285786b63636363636c7986929c90837669636363635e564c41352a1d1105000c18232f3a444d53575858585858585c646d767f88908e867c736a615850473e352c22180e03000009131c252c32373939393939393939393939393939393939393939393937322c251c130900000000000000000000000000000000000006121e2a36414b535a5d5c5a5a595a5c606875828e9b9e9184776b5e5144382b1e1105000000000000000000000a16222f3b4854616d7985929eaaab9e92867a6e62564b40362d272422222325282e36404b57626e7a86929faba79b8f83776b5e5246392d20140700101c2936434f5c697683909ca9b6ada195897d71655a4e4339302a272526282f3944505c6874808c99a5b0a4988b7f73665a4d4135281c0f03000004111d2935404b555d62646667696b6d6f706b61564b4c4c4c4c4b4a4845423e3a46525e6a76828f9ba8aa9e9185786c5f5346392d2013070013202c3946535f6c7986939facac9f9285786b5f5245392c1f120600000000000b1824313e4b5764717e8b98a4b1a79a8d8173675a4d4134271a0e000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000000000000000004070909090909090909090909060300000000000000000c1825313d49555f676a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6f79838d98a2ada3998f857b70665c51463a2e2115080000111e2b3744505d68737c858e979e958c837a7e858b9095999c9fa1a2a2a1a09e9b97938d88817b8089929b9990877d746b6054483b2f22150900101d2935414d586167686868686868686868635a4f44382c1f13060000000000060f18212a333b41444644403a322920170e0500000000000000000000020b141d262f373d424444413b342c231a1108000000000000000000000000000000000000000000000000000000000000000b1724313d4a56636f7c8894988c81766b635c595b6169737e8995988c8073665a4d4134281b0e0200000000000000000000000000000000000000020d18222b333a3f4142424242424d5966737c7c7c7c7b7063574a3e444a50575d63686e73777a7c7c7b78746f6860574e4442424242424242413f3a332b22180e03000013202c3946535f6c7982828282828282786b5f52454c5865727e8282828282827e7165584b3e3225180b00000b17232f3a46515c67727c87909aa2aab1b7bcc0c3c4c5b8ac9f928578707070707070707986929c908376707070706f685e5246392d2014070007121d28323b42484b4b4b4b4b4d59646e768088918e857c736a61584f463e352c231a1006000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a26211a130a01000000000000000000000000000000000000020e19242f3942494e565c5e5e5d5e5f626975828e9b9e9184776b5e5144382b1e1105000000000000000000000c1825323e4b5763707c8995a1aea89b8f82766a5e52463a2f241b17161516181d242f3a46525e6a76838f9ba8ab9f93877a6e6155483c2f23160a00101c2936434f5c697683909ca9b6aa9e9185796d6155493d32271e1a19191d2834404c5864707c8995a2aea79b8f8276695d5044372b1e11050000010d18242f39434c525557595b5c5e6062636059565758595959585654524e4a46414e5a6773808c99a5ada094877a6e6154483b2e2215080013202c3946535f6c798693a0acac9f9285786b5f5245382c1f120500000000000b1724313e4a5764717d8a97a4b1a79a8e8174675a4d4134271a0e000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000000000000000000000000000000000000000000000000000000000000000d1a2734404d59667177777777777777777777777777777777777777777777777b86909ca8aba1978d82786e6256493d3024170a00000f1c2834404c57616a737c858e958c837a7173797f84898d90929495959493918e8b87827c76707680899290877d746b62594f43382c1f130700121f2c3845515e69737575757575757575746c6054473b2e211508000000000000060f1821293035383938342f2820170e05000000000000000000000000020b141d252c3236373735302a221a110800000000000000000000000000000000000000000000000000000000000000000915222e3b4753606c7884909b92877d746d6866676b727b858f9a93877b6f63574b3e3225190c00000000000000000000000000000000000000000006101921282e3235353535353f4c5965727e8989897e72665a4e4a4f555b62686e747a7f8487898988858079726960564c4136353535353535322e292119100600000013202c3946535f6c79868f8f8f8f8f85786b5f52454c5865727e8c8f8f8f8f8b7e7165584b3e3225180b000006121e2935404b56606b757e8890989fa6abb0b3b6b8b9b8ac9f92857d7d7d7d7d7d7d7d7d86929c90837d7d7d7d7d7a6e6155483b2e22150800010c16202930373c3e3e3e3e424f5b68758089918e857c736a61584f463d342c231a10070000000000010910161a1e1f20202020202020202020202020202020202020201f1e1a16100901000000000000000000000000000000000000000008131d27313d495560686b6a6a6b6c6e737b86919e9b8f8376695d5044372a1d1104000000000000000000000e1a2734404d5966727f8c98a5b1a5988c8073675a4e4235291d120b09090a0c121e2936424e5a6773808c99a5afa2968a7d7064574b3e3225190c00101c2936434f5c697683909ca9b4a79b8e8275695d5044382c21150e0c0c17232f3c4854616d7a86939facaa9e9185786c5f5246392d20140700000007131d28313a4146494a4c4e505253555a5d606264656666656463615e5a56524d4b5864717d8a97a3afa295897c6f6356493c3023160a0013202c3946535f6c798693a0acac9f9285786b5f5245382c1f120500000000000b1724313e4a5764717d8a97a4b1a79a8e8174675a4d4134271a0e000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000000000000000000000000000000000000000000000000000000000000000e1a2734414d5a6774818484848484848484848484848484848484848484848484848f9ba8b3a99e948a7d7164574a3e3124170b00000c18242f3b454e57616a727b858c837a7168686e73787d818386878888888785827e7b76716b656d768089877d746b625950473d32271b0f030013202c3946535f6c7982828282828282827b6f6255483c2f22150900000000000000060f171e24292b2c2b28231d160e050000000000000000000000000000020b131a2126292b2a28241f18100800000000000000000000000000000000000000000000000000000000000000000006131f2b3844505c68737f8a959990877e78747374777d858d97988d82766b5f53473b2f22160a00000000000000000000000000000000000000000000070f171d222628282828313e4b5764707d8a968e82766a5f57565b60666d737980858b9093969694918b847b72685e53473c31282828282826221d1710070000000013202c3946535f6c7986939c9c9c9285786b5f52454c5865727e8c989c9c988b7e7165584b3e3225180b0000010d18232e39444e59636c757e868e959aa0a4a7a9abacacaca0958b8a8a8a8a8a8a8a8a8a8b959e938a8a8a8a8a887b6e6155483b2e2215080000040e171f262b2f31323234414d5a66707a838c857c736a61584f463d342b221a10070000000000000000050a0e1113131313131313131313131313131313131313131313110e0a0500000000000000000000000000000000000000000000010d1a2734404d59667178777777787a7e858d97a0968b7f73675a4e4235281c0f0300000000000000000000101c2935424f5b6875818e9aa7afa3968a7d7064574b3e3226190d01000000010d1926323e4b5764707d8a96a3b0a5998c8073665a4d4134271b0e00101c2936434f5c697683909ca9b1a5988c7f72665a4d4134281c1004000713202c3945515e6a7784909da9ada094877a6e6155483b2f221509000000010c161f282f353a3c3e414950565c6166696d6f7172727372716f6d6a67625e585256636f7c8995a2afa3978a7d7064574a3d3124170b0013202c3946535f6c798693a0acac9f9285786b5f5245392c1f120600000000000b1824313e4b5764717e8b97a4b1a79a8d8174675a4d4134271a0e000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000000000000000000000000000000000000000000000000000000000000000e1a2734414d5a6774818e919191919191919191919191919191919191919191919196a0abb7b0a4978a7d7164574a3e3124170b000007131e29333c454e576069727b837a71685f5d63686c717477797a7b7b7b7a7876726f6a65605b646d76807d746b625950473e352b21160a000013202c3946535f6c79868f8f8f8f8f8f887b6f6255483c2f2215090000000000000000050d13181c1f1f1e1c18120c0400000000000000000000000000000000010910151a1d1e1e1c18140e0600000000000000000000000000000000000000000000000000000000000000000000030f1b27333f4b57626d78838d9799908a8481808183888f969990867b70655a4e43372b1f13060000000000000000000000000000000000000000000000050c1216191b1b1b232f3c4955626e7b889493877c71686463666c72787e848b91969ba0a2a2a19c968e847a6f64594d42362a1e1b1b1b1a16120c05000000000013202c3946535f6c798693a0a99f9285786b5f52454c5865727e8c98a5a5988b7e7165584b3e3225180b00000007121d28323d47515a636c747c83898f94989b9d9e9fa0a0a09d97969696969696969696979da09c9796969695887b6e6155483b2e221508000000050d141a1f23252525323e49545e68717a837c736a61584f463d342b2219100700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1a2734414d5a67737f84848485878a90979d978e84796e63574b3e3226190d0100000000000000000000111e2a3744505d6a7683909ca9aea195887b6f6255493c2f23160a00000000000a16232f3c4955626f7b8895a1aea79b8e8275685c4f4236291c1000101c2936434f5c697683909ca9afa396897d7064574a3e3125190c000004101d2a36434f5c6875828e9ba8afa296897c7063564a3d3024170a00000000040d161e242a313a434b535b61676d7276797b7d7e7f807f7e7c7a77736e69635d56616e7b8894a1aea4978b7e7164574b3e3125180b00131f2c3946525f6c7985929facac9f9286796c5f5346392c20130600000000000c1825323e4b5865717e8b98a4b1a69a8d8073665a4d4034271a0d000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000000000000000000000000000000000000000000000000000000000000000e1a2734414d5a6774818e9a9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9ea1a8acacaca4978a7d7164574a3e3124170b0000020d17212a333c454e576069727971685f5651575c6164686a6c6e6f6f6e6d6b6966635e5a54525b646d76756b625950473e352c23190f04000013202c3946535f6c7986939c9c9c9c95887b6f6255483c2f22150900000000000000000002080c101213120f0c07010000000000000000000000000000000000000004090d1011110f0c08020000000000000000000000000000000000000000000000000000000000000000000000000b17232f3a46515c67717b858e969b95908d8c8d8f94999890877e74695f54493d32261a0e0300000000000000000000000000000000000000000000000001060a0d0e0f14212d3a46535f6c788591988d837a73707072777d83898f969ca2a4a1a0a0a2a5a0968c81756a5e52463a2e22160f0e0d0a060100000000000013202c3946535f6c798693a0ac9f9285786b5f52454c5865727e8c98a5a5988b7e7165584b3e3225180b000000000b16212b353f48515a626a71787e83888b8e9092939393939393939393939393939393939393939393939393887b6e6155483b2e2215080000000002090f13161818212d38434c565f687179736a61584f463d342b221910070000000000000000000000000000000000000000000000050a0d0f0f0f0f0f0f0d0a050000000000000000000000000000000000000000000000000000040b111926323e4b57636f7b8791919294979895918c857c72685d52463a2e22160a0000000000000000000000121f2b3845515e6b7884919eaaada093877a6d6054473a2e21140800000000000814212e3a4754606d7a8793a0ada99c9083766a5d5044372a1e1100101c2936434f5c697683909ca9aea194887b6e6255483c2f2316090000010e1b2734414d5a6773808d9aa6b1a4978b7e7164584b3e3225180c000000000006111b253039434c555d656c73787e8285888a8b8c8c8c8b8986837f7a756e6861616e7b8894a1aea5988b7e7165584b3e3225180b00121f2c3845525e6b7885919eabaca09386796d6053473a2d21140700000000000c1926333f4c5965727e8c98a5b2a6998c807366594c403326190d000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000000000000000000000000000000000000000000000000000000000000000e1a2734414d5a6774818e9aa0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0978a7d7164574a3e3124170b000000050f18212a333c454e5760696c685f564d464b5054585b5e6061626261615f5d5a56524e4949525b646a6a625950473e352c231a110700000013202c3946535f6c798693a0a8a8a295887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121e2935404a555f69737c848c92989c9a999a9c99948d867e756c62584d42372c21150a00000000000000000000000000000000000000000000000000000000000005121e2b3744505d6975828e9a958c84807d7c7e83888e949ba1a39d9895939395999e9d92867a6f63574a3e3226190d010000000000000000000013202c3946535f6c798693a0a09f9285786b5f52454c5865727e8c98a0a0988b7e7165584b3e3225180b00000000040f19232d363f48505860676d72777b7f828485868686868686868686868686868686868686868686868686867b6e6155483b2e22150800000000000003070a0b101b26313a434d565f686c6961584f463d342b2219100700000000000000000000000000000000000000000000040b11161a1c1c1c1c1c1c1a16110b040000000000000000000000000000000000000000000000080f161c22282e3a46525e6a76828e9a978e8c8b8985817a736a60564c41352a1e12060000000000000000000000131f2c3946525f6c7985929facac9f9286796c5f5346392d20130600000000000613202d3946535f6c7986929facaa9e9184776b5e5145382b1f1200101c2936434f5c697683909ca9aca09386796d6053473a2d2114070000000d1926333f4c5965727e8c98a5b2a5988c7f7266594c403326190d00000000020d18222d37414b555e676f777e84898e929597989999989795938f8b868079726b626d7a8794a1aea5988b7e7165584b3e3225180b00111e2b3744515d6a7784909daaada194877b6e6155483b2f22150900000000000e1a2734404d5a6673808d99a6b1a4988b7e7265584b3f3225190c000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79a8d8174675a4d4134271b0e01000a1724303d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000000000000000000000000000000000000000000000000000000000000000e1a2734414d5a6774818e9393939393939393939393939393939393939393939393939393939393938a7d7164574a3e3124170b00000000060f18212a333c454e575d5f5c564d443b4044484c4f5153545555555452504d4a46423d4049525a5e5d5850473e352c231a11080000000013202c3946535f6c798693a0acafa295887b6f6255483c2f221509000000000004090d10121212121212121212121212121212121212121212121212121212121212121212121212100d0904000000000000000000000000000000000000000000000000000000000000000000000000010d18232e39434d57616a727a81878c8f929292908d88837c746c635a50463b31261b1004000000000000000000000000000000000000000000000000000000000000030f1c2834414d5966727e8a969e96908c8a898b8f949aa0a49e98928c888686898d949c978b7f73675a4e4235291d10040000000000000000000013202c3946535f6c7986939393939285786b5f52454c5865727e8c939393938b7e7165584b3e3225180b000000000007111b242d363e464e555c61676b6f7275777879797979797979797979797979797979797979797979797979776d6154483b2e211508000000000000000000000a151f28313a434d565c5f5d574f463d342b2219100700000000000000000000000000000000000000000000050e161c222628292929292826221c160e050000000000000000000000000000000000000000020a121920272e33393e424e5a66727e8a969386807e7c79756f6961584e443a2f251e170f070000000000000000000013202c3946535f6c798693a0acac9f9285786b5f5245392c1f1206000000000005121f2c3945525f6b7885929facac9f9285786c5f5246392c1f1300101c2936434f5c697683909ca9ab9f9285786c5f5245392c1f13060000000b1825323e4b5864717e8b97a4b1a69a8d8073675a4d4034271a0e0000000008131e29343f49535d67707981898f959a9ea1a3a5a4a2a1a1a19f9b97918b847d746c6d7a8794a1aea5988b7e7165584b3e3225180b00101d2936434f5c6975828f9ba8afa295897c6f6356493d3024170b00000000020f1c2835424e5b6874818e9aa7b0a3968a7d7064574a3e3124180b000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca79b8e8175685b4f4235291c0f03000a1724313d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000000000000000000000000000000000000000000000000000000000000000e1a2734414d5a67748186868686868686868686868686868686868686868686868686868686868686867d7164574a3e3124170b0000000000060f18212a333c454c5152504b443b3234383c3f42454648484848474644413e3a36313740484e51514d473e352c231a1108000000000013202c3946535f6c798693a0acaca295887b6f6255483c2f22150900000000080f15191d1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1d1a150f0800000000000000000000000000000000000000000000000000000000000000000000000007121c27313b454e5760686f767b808385868584817c77716a625a51483e342a1f150a00000000000000000000000000000000000000000000000000000000000000000c1925313d4955616d7985909ba19c989696989b9fa59f99938c86817c797a7c828a939b8f83766a5e5145382c1f13060000000000000000000013202c3946535f6c7986868686868685786b5f52454c5865727e8686868686867e7165584b3e3225180b00000000000009121b242c353c434a50565b5f6366686a6b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c665c5145382c20130700000000000000000000030d161f28313b444b5053514d453d342b2219100700000000000000000000000000000000000000000000040e1720272e32353636363635322e2720170e04000000000000000000000000000000000000030b141c242b32393f444a4e5256626e7a8692968a7e72706d69645e574f48433d3730292119110800000000000000000013202c3946535f6c798693a0acac9f9285786b5f5245382c1f1205000000000003121f2c3845525f6b7885929facac9f9386796c5f5346392c201300101c2936434f5c697683909ca9ab9e9184776b5e5145382b1e12050000000a1724313d4a5764707d8a97a4b0a79a8e8174675b4e4134281b0e000000020d19242f3b46505b656f79828b939aa1a6aaa49f9b989694949495989b9c968f877e756d7a8794a1aea5988b7e7165584b3e3225180b000f1b2835414e5b6774818d9aa6b0a4978b7e7165584c3f32261a0d0100000005111e2b3744505d6976838f9ca9aea195887b6f6256493c3023160a000000000000000e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120500000000000000000013202c3946535f6c798693a0aca99c8f83766a5d5044372b1f1307000b1724313e4a5764717d8a97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000000000000000000000000000000000000000000000000000000000000000e1a2734404d5a6672797979797979797979797979797979797979797979797979797979797979797979796f63574a3d3124170a000000000000060f18212a333b41444644403a3229282c303336383a3b3c3c3b3a393735322e2a262e373d424544413c352c231a110800000000000013202c3946535f6c798693a0a0a0a095887b6f6255483c2f2215090000000912192025292b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2926201a120a0000000000000000000000000000000000000000000000000000000000000000000000000b15202a333c454e565e646a6f73767879797774716c665f5850483f362c22180e0300000000000000000000000000000000000000000000000000000000000000000915212d3945515c68737e89939ca4a5a3a3a4a5a09a948e88817b75706d6d7178818b969286796d6054473b2e22150900000000000000000000131f2c3946525f6b7679797979797979766a5e51454b58647079797979797979797064574b3e3125180b0000000000000009121b232a32393f454a4f5357595c5e5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5b544a3f34281c10040000000000000000000000040d161f29323a40444645413b342b2219100700000000000000000000000000000000000000000000000b16202932393e4242424242423e39322920160b0000000000000000000000000000000000030c151d262e363d444a50555a5e62656975828e9a8e83776c6a6865625d59544e48413a332b231a1108000000000000000013202c3946535f6c798693a0acac9f9285786b5f5245382c1f1205000000000005121f2c3845525f6b7885929facaca09386796c5f5346392c201300101c2936434f5c697683909ca9aa9e9184776a5d5144372a1e11040000000a1723303d4a5663707d8a96a3b0a89b8e8275685b4e4235281b0f00000007131e2a35414c57626d77818b949da5aca69f98938f8b89888787898b8f93999990877e747a8794a1aea5988b7e7165584b3e3225180b000d1a26333f4c5965727e8b97a4b0a6998d8073675b4e4235291d11050000000814212d3a46525f6c7885919eaaac9f93867a6d6054473b2e211508000000000000020e1b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f120908050100000000000013202c3946535f6c798693a0acab9e9185786c6053473b2f23180d060b1825313e4b5764717e8b97a4b0a3968a7d7063564a3d3023170a0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b00000000000000000000000000000000000202020202020202020201000000000000000000000c1925323e4a5660696c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c675e53473b2e22160900000000000000060f1821293035383938342f28201c202427292b2d2e2f2f2f2e2c2b2825221e1c252c3236383835312a231a11080000000000000013202c3946535f6c7986939393939393887b6f6255483c2f221509000008121b242b313538383838383838383838383838383838383838383838383838383838383838383838383836312c241c12090000000000000000000000000000000000000000000000000000000000000000000000030e18212a333c444c53595f63676a6b6c6c6a6865605b554e463e362d241a100600000000000000000000000000000000000000000000000000000000000000000005111d2934404b57626c77818a93999d9f9f9d99948f89837c76706a646060666f7a859195887c6f63564a3d3024170b00000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6b64594e4248545f686c6c6c6c6c6c6c6c685e53483c2f23160a000000000000000009111920272e34393e43474a4d4f515253535353535353535353535353535353535353535353535353524f4a42382e23180c00000000000000000000000000040d1720282f3438393835302922191007000000000000000000000000000000000000000000000006111d27323b444a4e4f4f4f4f4e4a443b32271d1106000000000000000000000000000000020b151e272f3840474e555b61666b6e7275777d899593877b797774716e69655f59534c453d352c231a11080000000000000013202c3946525f6c7986929facac9f9286796c5f5246392c20130600000000000613202c3946525f6c7986929facaca09386796c5f5346392c201300101c2936434f5c697683909ca9aa9d9084776a5d5044372a1e11040000000a1623303c4956636f7c8996a3b0a89b8f8275685b4f4235281c0f0000000c18232f3b46525d68737e89939da6aea59c948d87837f7c7b7a7b7c7e83878d949990867c7a8794a1aea5988b7e7165584b3e3225180b000b1824313d4a56636f7c8895a1aea89c8f83766a5e5145392d21150a0706070d1824313d4955626e7b8794a0ada99d9084776b5e5245392c1f13060000000001080d121b2834414e5b6774818e9ba8ac9f9285786b5f5245382c1f171614110c07000000000013202c3946535f6c798693a0acada194887b6f63574b3f34291f1712111926323f4c5865727e8b98a5afa396897c6f6356493c302316090013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000000000000000000000050a0d0f0f0f0f0f0f0f0f0f0f0e0c0804000000000000000916222d39444e575d5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5c554c41362b1f12060000000000000000060f171e24292b2c2b28231d161014171a1d1f202122222221201e1c191612131a2126292b2b29251f191108000000000000000013202c3946535f6c7986868686868686867b6f6255483c2f22150900040f1a242d363d42444545454545454545454545454545454545454545454545454545454545454545454544423d362e241a10050000000000000000000000000000000000000000000000000000000000000000000000060f18212a323a41484e53575b5d5f5f5f5e5c58544f4a433c342c241b120800000000000000000000000000000000000000000000000000000000000000000000000c18232f3a45505b656f7881888d919292918d89837d77716b655e5853545d6975818d938b7e7165584b3f3226190c000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5a52483d424d565d5f5f5f5f5f5f5f5f5c564d42372b1f1307000000000000000000070e151c23282e33373b3e404344454646464646464646464646464646464646464646464646464646433f382f261c11060000000000000000000000000000050e161d23282b2c2c29251f1810070000000000000000000000000000000000000000000000000a16222e39444d555b5c5c5c5c5b554d44392e22160a0000000000000000000000000000000a141d273039414a525960666c72777b7e8184858a95988c868583817e7a75706b645e564f473e352c231a1006000000000000121f2c3845525f6b7885919eabaca09386796d6053473a2d21140700000000000714212d3a4753606d798693a0acac9f9386796c5f5346392c201300101c2936434f5c697683909ca9aa9d9084776a5d5144372a1e1104000000091623303c4956636f7c8996a3b0a89c8f8275685b4f4235281c0f000004101c2834404c57636e7a85909ba5afa69c938a827c7673706e6d6e6f72777c828a92988d837a8794a1aea5988b7e7165584b3e3225180b000915222e3b4754606d7985929eaaab9f92867a6d6155493d32271c16141314161e2935414d5965717e8a96a3afa69a8e8175685c4f43362a1d1104000000030c13191e212834414e5b6774818e9ba8ac9f9285786b5f5245382c232323211d18110a0200000013202c3946535f6c798693a0acb0a4988c8073685c51463b3128221f1e1f2734414d5a6673808d99a6aea295887b6f6255493c2f2216090013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b000000000000000000000000040b1116191b1c1c1c1c1c1c1c1c1c1b18140f0901000000000005111d28323c454c5153535353535353535353535353535353535353535353535353535353535353535353504b433a30251a0e02000000000000000000050d13181c1f1f1e1c18120c04080b0e101214151515151413110f0c0906090f151a1d1e1e1c19140e07000000000000000000131f2c3946525f6b767979797979797979786d6155483b2f221508000a15212b363f474e5151515151515151515151515151515151515151515151515151515151515151515151514e4840362c21160a000000000000000000000000000000000000000000000000000000000000000000000000060f18202830373d42474b4e51525352514f4c48443e38312a221a120900000000000000000000000000000000000000000000000000000000000000000000000007121e29343e49535d666f767d8284868684817d78726c66605a534d474c5965717e8686868073665a4d4034271a0e010000000000000000000a16212c3740484f5253535353535353524e4840363b444b515353535353535353504b443b30261a0f0300000000000000000000040b11171d22272b2e3134363839393939393939393939393939393939393939393939393939393937332d261d140a00000000000000000000000000000000040c12181c1f201f1d19140d06000000000000000000000000000000000000000000000000000d1a26333f4a555f6769696969675f554a3f33261a0d010000000000000000000000000007111c252f39424b535c636b72787d83878b8e9092949c9e969392908d8a86817c766f68615950473e352c22180d030000000000111e2b3744515d6a7784909da9aea194887b6e6155483c2f22160900000000000916222f3b4855616e7b8794a1adac9f9285796c5f5246392c1f1300101c2936434f5c697683909ca9aa9e9184776a5d5144372b1e11040000000a1623303d4956636f7c8996a3b0a89c8f8275685b4f4235281c0f00000814202c3844505c6874808b96a1aca99e948a8178716b666361616163666b7178808891948a7e8794a1aea5988b7e7165584b3e3225180b0006131f2c3844515d6976828e9aa6aea2968a7d71665a4e43382e27222020202227303a46515d6975818d9aa6afa3978a7e7265594d4034271b0e020000030d151d242a2e3034414e5b6774818e9ba8ac9f9285786b5f524538303030302d29231c140b01000013202c3946535f6c798693a0acb4a89c9084786d62574d433a332e2c2b2c2e3743505c6875828e9ba7ada194877b6e6154483b2e2215080013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000000000000815222e3b4855616e7b8895a2aea5988b7e7165584b3e3225180b0000000000000000000000050e151c2226282828282828282828282724201a130b0200000000000b16212a333b41454646464646464646464646464646464646464646464646464646464646464646464644403931281e1308000000000000000000000002080c101213120f0c070100000000040607080909080806050200000000040a0e101211100d080300000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c665c5145392d201407000e1a26323d4851595e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5952483e32271b0f02000000000000000000000000000000000000000000000000000000000000000000000000060e161e252b31373b3f42444546464543403c38332d272018100800000000000000000000000000000000000000000000000000000000000000000000000000010c17222d37414b545d646b71757879797875716c67615b554e48423d4956626e787979797972665a4d4034271a0e0100000000000000000005101a252e373e43464646464646464645433d362e323a4044464646464646464644403a32291f140900000000000000000000000000060c11161b1f222527292b2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b27221c140b02000000000000000000000000000000000001070c10121312100d080200000000000000000000000000000000000000000000000000000f1c2935424e5b67717575757571675b4e4235291c0f03000000000000000000000000040e19232d37414b545d656e757c83898e93979a9d9fa1a6a8a2a09f9c9a96928d87817a736b625950473e34291f150a0000000000101d2936434f5c6875828e9ba8afa296897c7063574a3e3125180c00000000000c1825313d4a5763707c8996a2afab9e9185786b5e5245382b1f1200101c2936434f5c697683909ca9ab9e9184776b5e5145382b1e12050000000a1724303d4a5663707d8a96a3b0a89b8e8275685b4e4235281b0f00000b1824303c4855616d7985909ca8aea3978c82786e665f5a57555454565a5f666e767f899390858894a1aea5988b7e7165584b3e3225180b0003101c2935414d5a66727e8a96a2aea69a8e82766b60554a4038322f2d2c2d2f3339424c57626e7a85919daaab9f93877a6e6256493d3124180c0000000b151f272f353a3c3d414e5b6774818e9ba8ac9f9285786b5f52453d3d3d3d3c39342e261d1309000013202c3946535f6c798693a0acb2aaa1958a7e73695f554c443e3a3838383a3e48535f6b7884919daaab9f9286796c6053463a2d2014070013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000000000001070b0e15222e3b4855616e7b8895a2a6a5988b7e7165584b3e3225180e0c090400000000000000040e1720272d323535353535353535353534312b251d140b0000000000040f1821293035383939393939393939393939393939393939393939393939393939393939393939393938342e271f160c02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5b544a4034291d110400111e2a36424e59636a6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6a645a4f43372b1e120500000000000000000000000000000000000000000000000000000000000000000000000000040c131a20262b2f333537393939383633302c27221c150e0600000000000000000000000000000000000000000000000000000000000000000000000000000006101b252f39424b535a6065696b6c6c6b6865605b56504a433d373a46525d676c6c6c6c6c6960564a3e3225190c000000000000000000000009131c252c323739393939393939393936322c24282f3438393939393939393938342f2820170d02000000000000000000000000000000060a0e1216181b1d1e1f20202020202020202020202020202020202020202020202020201e1b17110a0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c69768282828276695c4f4336291c10030000000000000000000000000a15202b353f49535d666f7780878e949a9fa3a6a3a19f9e9e9e9fa1a4a6a29e98928c857d746b62594f463b31261b1005000000000e1b2834414d5a6773808c99a5b1a4988b7e7266594d4134281c110a07070709101c2834404d5966727e8b98a4b1aa9d9084776a5d5144372b1e1100101c2936434f5c697683909ca9ab9f9285786c5f5245392c1f13060000000b1724313e4a5764717d8a97a4b0a79b8e8174675b4e4135281b0e00020f1b2734404c5865717d8995a1ada99d91867b70665c544e4a4847484a4e545c646d77818b96909199a4b0a5988b7e7165584b3e3225180b00000d1925313d4a56626e7a86919da9aa9f93877c71665c524a433e3b3a393a3b3f444b545e68737f8a96a2aea69a8e82766a5e52463a2d211508000006121c2731394146494a4a4e5b6774818e9ba8ac9f9285786b5f524a4a4a4a4a49453f382f251a0f040013202c3946535f6c798693a0acaaa0999790857b71675e564f4a47454445474a505964707b8894a0aca99d9084776a5e5145382b1f12060013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00000000060d12171a1c222e3b4855616e7b88959a9a9a988b7e7165584b3e32251c1b19140f090100000000000b16202931393e41424242424242424242403c362f261d12080000000000060f171f24292c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b28231d150d0400000000000000000000000000000000000000000000000000000000000000000002070c0e1010101010100f0d09040000000000000000000000000000000a16212c3740484f52535353535353535352504a42382e23180c0000131f2c3945525e6b7578787878787878787878787878787878787878787878787878787878787878787878766b5f53463a2d201307000000000000000000000000000000000000000000000000000000000000000000000000000002090f151a1f2326292b2c2c2c2b292724201b16110a03000000000000000000000000000000000000000000000000000000000000000000000000000000000009131d27303941484f55595c5e5f5f5e5c59554f4a443f38322c35414b555c5f5f5f5f5f5d574e44392d2216090000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2a26211a1d24282b2c2c2c2c2c2c2c2c2b28231d160e050000000000000000000000000000000000000206090c0e1011121313131313131313131313131313131313131313131313131313120f0b0600000000000000000000000000000000000000000000000000000000000000050a0e1011111111110f0c080300000000000000000000000000101c2936434f5c6976838f8f8376695c4f4336291c1003000000000000000000000005111c27323c47515b656f78818a9199a0a6a6a09b9794929191919395989ca2a8a49d968f877e756b61574d43382d22170b000000000c1926323f4b5864717d8a96a2afa79a8e8275695d5145392d221a161414141519212c3844505c6975818e9aa7b3a89c8f8276695c504336291d1000101c2936434f5c697683909ca9aca09386796d6053473a2d2114070000000c1825323e4b5865717e8b98a4b1a69a8d8173675a4d4134271a0e0005111e2a3743505c6874818d99a5b0a4988c8175695e544a433e3b3a3b3e434a525b656f79848f9b9da3abb2a5988b7e7165584b3e3225180b00000915212d3946515d6975818c98a3aea4998d83786e645c544f4b48474647484b4f555d66707a85909ba7aca095897d72665a4e42362a1e110500000b17232e39434b52565656565b6774818e9ba8ac9f9285786b5f56565656565655514a41372c2115090013202c3946535f6c798693a0aca4988e8b928d83797068615b565352515253565b626b76818c98a4b0a69a8d8175685c4f4336291d10040013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0000000710171e232729292e3b4855616e7b888d8d8d8d8d8b7e7165584b3e3229292825201a130b0200000006111c27323b434a4e4f4f4f4f4f4f4f4f4f4d4841382e24190e020000000000060d13191d1f202020202020202020202020202020202020202020202020202020202020202020201f1c17120b04000000000000000000000000000000000000000000000000000000000000000000060d13181b1d1d1d1d1d1d1c19150f08010000000000000000000000000005101a252e373e4346464646464646464646433f3830261c1207000013202c3946535f6c79858585858585858585858585858585858585858585858585858585858585858585857a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000000000000000000000004090e13171a1c1e1f201f1e1d1b1814100b0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000010b151e272f373d44494d5052535352504d49443f39332d27242f39434a505353535353514c453c32281d1105000000000000000000000000010910161a1e1f202020202020201f1e1a150f12181c1f20202020202020201f1c18120c040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a11161a1d1e1e1e1e1d1c19140e07000000000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000b16222d38434e59636d77818a939ba3aaa29b958f8b888584848486898c91969da4a8a19890877d73695f54493e33281c11050000000a1723303c4955616e7a86939fabaa9e9185796d61554a3e342b262221202122252a333e4955606c7885919da9b3a79a8d8174675b4e4235281b0f00101c2936434f5c697683909ca9ada194887b6e6155483c2f2216090000000d1a2633404c5966727f8c99a5b2a6998c807366594c4033261a0d000814212d3946525f6b7884909da9ada094887c7064584d4238322f2e2e32384049535d68737e8a95a1adb4b2a5988b7e7165584b3e3225180b000005111d2935414d5864707b86919ca7aa9f948a80766e66605b575453535355575b60676f78818c96a1aca59a8f84786d61554a3e32261a0d0100000f1c28343f4a555d62636363636774818e9ba8ac9f9285786b63636363636363625c53483d3125190d0013202c3946535f6c798693a0aca29689818b958b827a726c6763605e5e5e6062666c747d87929da9aea2968a7e7165594c4034271b0e020013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000006101922292f333536363b4855616e7b808080808080807e7165584b3e36363634312c251d140b0000000a16222e39434d555a5b5b5b5b5b5b5b5b5b59534a40352a1e120600000000000002080d101213131313131313131313131313131313131313131313131313131313131313131313120f0c07000000000000000000000000000000000000000000000000000000000000000000000811181f2427292a2a2a2a2a2825201a130a020000000000000000000000000009131c252c32373939393939393939393937332d261e140b00000013202c3946535f6c79869292929292929292929292929292929292929292929292929292929292929292877a6d6053473a2d20140700000000000000000000000000000000000000000000000000000000000000000000000000000000000003070a0d101112131312100e0b080400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c151d252c32383d41434546464543403d38332e28221c1d2731393f44464646464645413b332a21160b000000000000000000000000000000050a0e11131313131313131313110e0a04070c1012131313131313131312100c07010000000000000000000000000000000000000000000000000000000000040708080808080808080706040200000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c151c2226292a2a2a2a2a28251f1911090000000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000000005111c28333e4a55606a757f89939ca5a9a0989089847f7b79777778797c80858b929aa2aaa2998f857b71665b5044392d22160a0000000814202d3946525e6a77838f9ba7ada195897d72665b50463d36322f2e2d2d2f31353c454f5a65717d8995a1adb1a5988c7f7266594d4033271a0d00101c2936434f5c697683909ca9afa296897c7063574a3e3125180c0000020f1b2835414e5a6774818d9aa6b1a4988b7e7165584b3f3225190c000a16232f3c4955626e7a8794a0aca99d9184786c6054483c3126222122262e37414c57626d7984909ca8b4b2a5988b7e7165584b3e3225180b0000010d1925303c47535e6a75808b959fa9a69c92898078716b676361605f606163676b7179818a939ea8a89e93897e73675c5045392d211509000000121e2b3744505c676e707070707074818e9ba8ac9f92857870707070707070706d655a4e4235291c0f0013202c3946535f6c798693a0aca3968a7d858f948c847d77736f6c6b6b6b6c6f72777e868f99a4afa99d92867a6e6255493d3124180b000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00030e18222c343a3f4242424247535f6a7273737373737373736d62564a42424242413d372f261c120700000d1a26323e4a555f66686868686868686868645c52473b2f2216090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007111a222a303436363636363635312c251d140a00000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2b27221c140c0200000013202c3946535f6c7986939e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e94877a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030b131a21272c313437383939383734302c27221d1711151f272e343739393939393835302921180f0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c101315151515151515151413110f0b0804000000000000000000000000000000000000000000000000000000000000000000000000000000020c161e262d3236373737373735302a231b110700000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000a16212d39444f5b66717c87919ba5aba1978e867e78736f6c6b6a6b6d70747a8188909aa3aba1978d82776c61554a3e33271b0f03000005111d2a36424e5a66727e8a96a2ada69a8e83776c62584f48423e3c3a3a3a3b3e41474e57616c77828e99a5b1afa3968a7d7064574b3e3125180c00101c2936434f5c697683909ca9b1a4988b7e7266594d4034271b0f030005111e2a3743505c6975828f9ba8afa396897d7063574a3d3124170b000c1825323e4b5764707d8a96a3afa79a8e8175685c5043372b1f1614161c252f3a45515c6874808c98a4b0b2a5988b7e7165584b3e3225180b00000008141f2b37424d58636e79838e97a1aaa49b928a827c7773706e6d6c6d6e7073777d838b939ca5a9a0968c82776c61564b3f34281c110500000013202c3946535f6c787d7d7d7d7d7d818e9ba8ac9f92857d7d7d7d7d7d7d7d7d766a5d5043372a1d100013202c3946535f6c798693a0aca4978a7d7e8892968f89837e7b79787778797b7e83899098a1abada2988c8175695d5245392d211508000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0009141f2a343e454b4f4f4f4f4f4f5861666666666666666666635b504f4f4f4f4f4d4841382e24190d02000f1c2935424e5b67717575757575757575756e63574a3e3125180b00000000000000000000000000000000000000000000000000000000000000000000000000000000040a0e11131313131313131313131313131313131313131313131313131313120f0b06000000000000030e19232c343b40434343434343413d362f261c110700000000000000000000000000010910161a1e1f2020202020202020201e1b17110a020000000013202c3946535f6c79869393939393939393939393939393939393939393939393939393939393939393877a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000000000000000000000003060809090a0a0a0a0908060502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010910161c2025282a2c2c2c2c2a2824201c16110b060d151c23282b2c2c2c2c2c2c29241f170f06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a11181c202122222222222222211f1e1b1814100b050000000000000000000000000000000000000000000000000000000000000000000000000009131e2830383e424444444444413c352d23190f04000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000020e1a26323e4a55616c77838e98a3ada3998f857c746d6763605e5d5e6064686f767e88919ca6a99f94897d72665b4f43372b1f13070000010e1a26323e4a56626e7a85919ca7ab9f94897e746a6159534e4b48474647484a4d52586069737d88939faab6ada094877b6e6155483c2f23160a00101c2936434f5c697683909ca9b3a79a8e8175685c5043372b1f1308050814212d3946525f6b7884919daaada194877b6e6255483c2f221609000d1a2733404d5966727f8c98a5b1a4988b7e7265594d4034271b0f080a131e2934404b57636f7c8894a0adb2a5988b7e7165584b3e3225180b000000030f1a25313c47525d67727c858f98a0a8a49c948d88837f7c7a7979797b7c8083888e959ca5a79f978e847a70655b50453a2e23170c0000000013202c3946535f6c79868a8a8a8a8a8a919da9ada0958b8a8a8a8a8a8a8a8a84776a5d5044372a1d110013202c3946535f6c798693a0aca5988b7e76808a949a948f8b888685848586888b8e949aa2aaaca49b91867b7064594d4135291d1105000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000d1925313c4650575b5c5c5c5c5c5c5c5b59595959595959595c5c5c5c5c5c5c5c59534a40352a1e120600101c2936434f5c697682828282828282827e7265584c3f3225190c000000000000000000000000000000000000000000000000000000000000000000000000000000080f151a1e1f20202020202020202020202020202020202020202020202020201e1c17120b03000000000914202b353e464c4f50505050504d4841382e23180c010000000000000000000000000000050a0e1113131313131313131313120f0b0600000000000013202c3946535f6c79868686868686868686868686868686868686868686868686868686868686868686867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000000000000000000060b101315161617171716161513110f0c09050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b1014181b1e1f20201f1d1b1814100b060000030b12171c1e20202020201f1d19130d06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2c2a2724201b16100a0300000000000000000000000000000000000000000000000000000000000000000000030e1a25303a424a4f51515151504d473f352b201509000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000007131f2b37434f5a66727d89949faaa89d92877d736a625b565351515254585d646c75808a95a0aca59a8f83776b5f53473b2f23160a0000000a16222e3a46515d6974808b96a0aba59a90867c736b645e5a57555453535556595e636a727b858f9aa4b0b6aa9d9185786b5f53463a2d20140700101c2936434f5c697683909ca9b6a99d9184786c5f53473c30241a1412121924303d4955616e7a8793a0acab9e9285796c6053463a2d211407000f1c2835424e5b6874818e9aa7afa296897c7063574a3e3124180c00010c18232f3b47535f6c7885919daab2a5988b7e7165584b3e3225180b0000000009141f2b35404b55606a737c868e969ea4a69f99938f8c898786868687898c8f94999fa7a49d968e857c72685e54493e33281d12060000000013202c3946535f6c79869396969696969ba3aeb1a69d97969696969696969084776a5d5044372a1d110013202c3946535f6c798693a0aca5988c7f7278818a939b9b9794929191929294979a9fa5aca8a29b92897f746a5f53483c3125190d01000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00111d2936424d586268696969696969696761574d4d4d525c656969696969696969655c52463a2e22160900101c2936434f5c6976838f8f8f8f8f8f8c7e7265584c3f3225190c000000000000000000000000000000000000000000000000000000000000000000000000000009121a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b28231c150d030000000d1a25313c4750585c5d5d5d5d5d59524a3f34291d11050000000000000000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6b7679797979797979797979797979797979797979797979797979797979797979797979776c6053463a2d201407000000000000000000000000000000000000000000000000000000000000000000000000020a11171c1f212223232323232221201e1b1815110c07010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004080c0f1112131312110f0c0804000000000000060b0f12131313131312100d0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a141d262e34383b3b3b3b3b3b3b3b3a393734302c27221b150d0600000000000000000000000000000000000000000000000000000000000000000007131f2b36414c545b5d5d5d5d5d5851473d31261a0e000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000000a17232f3b47535f6b77838e9aa5aea2978b80756b6158504a47454445484c525a646e78848f9ba7ab9f94887c7063574b3f32261a0d01000006111d2935414c57636e79848f99a3aca2988e857d766f6a666362606060616366696e757c848d97a1abb6b3a79a8e8275695c5043372a1e120500101c2936434f5c697683909ca9b6ada094887c7064584c41362c24201e1e212a35414d5965717d8a96a2afa89c8f83766a5d5144382b1f120500101d2a3643505c6976828f9ca8ada194877b6e6155483b2f221609000007131f2b3743505c6975828e9ba7b2a5988b7e7165584b3e3225180b00000000030e19242f39444e58616b737c848c93999fa4a49f9b9896949393939496989ba0a5a39e99928b847b736a60564c42372d22170c010000000013202c3946535f6c798693a0a2a2a2a2a5acb5b8aea7a3a2a2a2a2a2a29d9084776a5d5044372a1d110013202c3946535f6c798693a0aca6998c80736f78818990979da19f9e9e9e9fa1a3a7a8a5a29d97908980776d63584d42372b20140800000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00121f2c3845525e6a737575757575757573695d51444b57636e75757575757575756e63574a3e3124180b00101c2936434f5c697683909c9c9c9c988c7e7265584c3f3225190c0000000000000000000000000000000000000000000000000000000000000000000000000008121b242b323639393939393939393939393939393939393939393939393939393937342e271f150c010000111d2a36424e5962686969696969645c5145392d2115090000000000000000000000000000000000000000000000000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b655b4f44372b1f12050000000000000000000000000000000000000000000000000000000000000000000000010b141c22282c2e2f30303030302f2e2c2a2825211d18120c060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c262f383f454848484848484848474543403c38332d261f18100700000000000000000000000000000000000000000000000000000000000000000a16232f3b47535d666a6a6a6a6963594e42362a1d11000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000010e1a26333f4b57636f7b87939faba99d91857a6f64594f463f3a3837383b4148525c67737e8a96a2a6a4988c8073675b4e4235291c10030000010d1824303b46525d68727d87919ba4aaa0978f87817b7673706e6d6d6d6e7072767a80868e969fa9b3bcafa3978b7e7266594d4134281b0f0200101c2936434f5c697683909ca9b6b0a4988c8074695d52483e35302d2b2b2d323b46525d6975818d99a6b1a5988c8073675b4e4235291c100300111e2b3744515d6a7784909daaac9f9386796d6053473a2d2114070000030f1b2834414d5a6673808c99a5b2a5988b7e7165584b3e3225180b000000000008121d27323c464f59616a727a81888e93989b9fa1a4a2a1a0a0a0a1a2a3a19e9b97938d878179726961574e443a30261b1005000000000013202c3946535f6c79869396969696969aa3adb1a69c96969696969696969084776a5d5044372a1d110013202c3946535f6c798693a0aca69a8d8073666f777f868c9195999b9d9e9f9f9e9d9b9995918c867e766e655b51463c31261a0f0300000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0013202c3946535f6c7982828282828282786b5f52454c5865727e8282828282827e7165584b3e3225180b00101c2936434f5c697683909ca8a8a5988c7e7265584c3f3225190c000000000000000000000000000000000000000000000000000000000000000000000000040f19242d363d42454646464646464646464646464646464646464646464646464646443f3931271d13080000131f2c3945525e6a7476767676766d6256493d3125190c00000000000000000000000000000000000000000000000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5a53493e33271b0f03000000000000000000000000000000000000000000000000000000000000000000000009131d262d33383b3c3c3d3d3d3c3c3b393734312d28231e171009010000000000000000000000000000000000000000000000000000000005090c0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0d0b0803000000000000000000000005090c0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0d0b08030000000000000b17222d38424a5154555555555555555452504c48443e38312922191007000000000000000000000000000000000000000000000000000000000000000b1825323e4b57646f77777777756a5e5245392c1f13000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000004111d2a36424f5b6773808c98a4b0a4988c8175695d52473d342e2b2b2c3036404b56626e7a86939a9a99988f83766a5d5144382b1f120500000008131e2a35404b56616b757f89929aa2a9a199928c87837f7d7b7a797a7b7c7e82868b9198a0a8b1bbb8aca093877b6f62564a3d3125180c0000101c2936434f5c697683909ca9b6b2a99d91857a6f645a5047403c393838393d444d58636e7a86919da9ada195897c7064584b3f32261a0d0100121f2b3845515e6b7885919eabab9e9285786b5f5245392c1f13060000000c1925323e4b5864717d8a97a4b0a5988b7e7165584b3e3225180b0000000000010b16202a343d474f5860686f767c82878c8f929597989a9a9a9a99989795928f8b87827c766f6860574e453c32291e140900000000000013202c3946535f6c7986898989898989919ca9ada0948b898989898989898984776a5d5044372a1d110013202c3946535f6c798693a0aca69a8d807366656d747b8185898c8f9192929292908f8c8985817a746d655c53493f352a1f14090000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0013202c3946535f6c79868f8f8f8f8f85786b5f52454c5865727e8c8f8f8f8f8b7e7165584b3e3225180b00101c2936434f5c697683909ca9b2a5988c7e7265584c3f3225190c0000000000000000000000000000000000000000000000000000000000000000000000000915202b363f484e525353535353535353535353535353535353535353535353535353504a43392f24190d020013202c3946535f6c79838383837e7266594d4135291c1004000000000000000000000000000000000000000000000000000000000000000000000000000a16212c3740484f5253535353535353535353535353535353535353535353535353535353535353535353524f4941372d22160b000000000000000000000000000000000000000000000000000000000000000000000005101b252f383f444748494a4a4a4948474543403d39342f29221b130a0100000000000000000000000000000000000000000000000000040b1116191a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a18140f090100000000000000040b1116191a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a18140f0901000000000f1b27333f4a545c6161616161616161605f5c58544f49433b342b221910060000000000000000000000000000000000000000000000000000000000000c1925323f4c5865727e848484796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000714202d3945525e6b7783909ca8ada194887c7064584c41362b231f1e1f242e3a46525e6a77838e8e8d8c8b8a85796c6053463a2d201307000000020d19242f3a444f59636d76808991989fa5a49d97938f8c898887868787898b8e92979ca2a1a5adb6b4a89b8f83776b5f53463a2e2115090000101c2936434f5c697683909ca9b2a8a19d978b80766b6259524c4846454546494e565f6974808b96a2aea99d9185796c6054483c2f23170a0000131f2c3945525f6c7885929facaa9e9184776b5e5145382b1e12050000000a1723303d4956636f7c8996a2afa5988b7e7165584b3e3225180b000000000000040e18222b353d464e565e656b71767b808386888a8c8d8d8e8d8d8c8a8886837f7b76716b645d564e453c332a21170d0200000000000013202c3946535f6c787c7c7c7c7c7c818e9ba8ac9f92857c7c7c7c7c7c7c7c7c76695d5043372a1d100013202c3946535f6c798693a0aca79a8d8173675b62696f75797d808284858685858482807d79756f69625b534a41372d23180e030000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0013202c3946535f6c7986939c9c9c9285786b5f52454c5865727e8c989c9c988b7e7165584b3e3225180b00101c2936434f5c697683909ca9aca5988c7e7265584c3f3225190c0000000000000000000000000000000000000000000000000000000000000000000000000d1925313d4751595e5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5c554b41352a1e120500121f2b3844515e6a778490908e8275695d5145382c2014080000000000000000000000000000000000000000000000000000000000000000000000000005101a252e373e43464646464646464646464646464646464646464646464646464646464646464646464646433e372f251b100500000000000000000000000000000000000000000000000000000000000000000000000a16212d3741495054555656565656555452504d4945403a342c251c130a010000000000000000000000000000000000000000000000060f161d22252727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272624201a130b030000000000060f161d22252727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272624201a130b03000000121e2b37434f5b666d6e6e6e6e6e6e6e6d6b6865605b544d453d342b22180e0300000000000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9186796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000a16232f3c4855616e7a87939facaa9d9185786c6054483c3024191211131d2936424f5b6874818281807f7e7d7d796d6053473a2d2014070000000007121d28333d47515b646d767e868e949a9fa4a39f9b9896949493949496989a9ea19b95959ba4afafa3978b7f73675b4f43362a1e12050000101c2936434f5c697683909ca9aba096919392887d746b635d585552515153555a6068717b86919ca7afa3988c8174685c5044382c201307000013202c3946535f6c7986929facaa9d9084776a5d5144372a1e11040000000915222f3c4855626f7b8895a2aea5988b7e7165584b3e3225180b0000000000000009141f29323b42474c535a60666b6f7377797c7e7f80818181807e7d7b7976736f6a656059534c443c332a21180f0500000000000000121e2b3744505b666e6f6f6f6f6f74818e9ba8ac9f9285786f6f6f6f6f6f6f6f6d64594d4135281c0f0013202c3946535f6c798693a0aca79a8d8173675a585e64696d7173767778797978777573706d69645e58514941382f251b1107000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0013202c3946535f6c798693a0a99f9285786b5f52454c5865727e8c98a5a5988b7e7165584b3e3225180b00101c2936434f5c697683909ca0a0a0988c7e7265584c3f3225190c000000000000000000000000000000000000000000000000000000000000000000000000101d2935424e59636b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c675d52463a2e21150800101d2a3643505c6975828f9c9285796d6155483c3024180b000000000000000000000000000000000000000000000000000000000000000000000000000009131c252c323739393939393939393939393939393939393939393939393939393939393939393939393937332d251d13090000000000000000000000000000000000000000000000000000000000000000000000000e1b27323e49535b6062636363636362615f5c5955514b453e372e251c130900000000000000000000000000000000000000000000060f1821282d3234343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343433302b251d150b01000000060f1821282d3234343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343433302b251d150b01000013202c3946525f6c777b7b7b7b7b7b7b7a7875716c665f574f463d342a1f150a00000000000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000c1825313e4b5764707d8996a2afa79a8e8275695c5044372b1f1308040e1a2733404c59657076757473727271706e675c5144382c1f130600000000010c16212b363f49525b646d747c83898f94989c9fa1a3a3a1a0a0a0a1a2a19e9a96908a89939fabaa9f93877b6f63574b3f33261a0e020000101c2936434f5c697683909ca9a89c8f8489958f867d756e6964615f5e5e5f61656b727a838d98a2ada99e92877b7064584c4034281c1004000013202c3946535f6c798693a0acaa9d9084776a5d5044372a1d11040000000815212e3b4854616e7b8894a1aea5988b7e7165584b3e3225180b000000000000020e1a25303b444d53565656565a5f63676a6d6f7172737474737372716f6d6a67635e5a544e48413a322a21180f0600000000000000000f1b27333f4a545c61626262626774818e9ba8ac9f9285786b62626262626262615b52483d3125190d0013202c3946535f6c798693a0aca79a8d8173675a4d53585d616467696b6b6c6c6b6a696764615d58534d463f372f261d130900000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0013202c3946535f6c798693a0ac9f9285786b5f52454c5865727e8c98a5a5988b7e7165584b3e3225180b00101c2936434f5c6976839093939393938c7e7265584c3f3225190c000000000000000000000000000000000000000000000000000000000000000000000000121e2b3844515e6a7579797979797979797979797979797979797979797979797979786e6256493c3023160a000f1b2835414e5b6774818d9a95897d7165584c4034281b0f0300000000000000000000000000000000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a27211b130b01000000000000000000000000000000000000000000000000000000000000000000000000111e2a37434f5b656c6f6f7070706f6f6d6b6965615c56504840372e241a10050000000000000000000000000000000000000000020d17212a32393e404141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141403c372f271d13090000020d17212a32393e404141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141403c372f271d1309000013202c3946535f6c79868888888888888684817c77716961584f463b31271c1106000000000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000e1a2733404d5966727f8c98a5b1a5988c7f7266594d4034281b0f03000b1824303c48545e666968676766656463625d554b4034281c10040000000000050f1a242d374049525b636a71787d83888c8f92959798999a9a99989795928e8a857f86929eaba59a8e82766a5e53473b2e22160a000000101c2936434f5c697683909ca9a89b8f82838e988f87807974706e6c6b6b6c6e71767c848c959fa9aca2978c81766a5f53473c3024180c00000013202c3946535f6c798693a0acaa9d9084776a5d5044372a1d11040000000814212e3b4754616e7a8794a1aea5988b7e7165584b3e3225180b00000000000005121e2a36424c565e6263636363605a5b5e606364666667676766656462626362605d59544e463f362d231a0f060000000000000000000b17222e38424b51555555555b6774818e9ba8ac9f9285786b5f55555555555555504940362c2015090013202c3946535f6c798693a0aca79a8d8173675a4d474c5155585a5c5e5f5f5f5f5e5c5a5855514c47423b342d251d140b0100000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0013202c3946535f6c798693a0a09f9285786b5f52454c5865727e8c98a0a0988b7e7165584b3e3225180b00101c2936434f5c697683868686868686867e7265584c3f3225190c000000000000000000000000000000000000000000000000000000000000000000000000121f2c3845525f6b78858686868686868686868686868686868686868686868686867d7063564a3d3023170a000d1a2633404c5966727f8c98998d8174685c5044372b1f13070000000000000000000000000000000000000000000000000000000000000000000000000000010910161a1e1f20202020202020202020202020202020202020202020202020202020202020202020201e1b1610090100000000000000000000000000000000000000000000000000000000000000000000000000121f2c3945525f6b777b7c7d7d7d7c7b7a7875716d68615a524940362c22170c000000000000000000000000000000000000000008131f29333c444a4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4c4841392f251a0f030008131f29333c444a4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4c4841392f251a0f030013202c3946535f6c798693959595959493918d88827b736a61574d43382d22170b000000000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000f1c2835424e5b6874818e9aa7afa3968a7d7064574a3e3125180c00000814202c37424c545a5c5b5b5a5958575655524b43392e23180c0000000000000008121c252e374049515860666c72777c808386888a8b8c8d8d8d8c8a8886827e79818c97a3aca095897d71665a4e42362a1e1206000000101c2936434f5c697683909ca9a99c8f827d889299918b85817d7a787777797a7d82888e969ea8ada49a90867b7065594e42372b1f130700000013202c3946535f6c798693a0acaa9d9084776a5d5044372a1d11040000000815212e3b4854616e7b8894a1aea5988b7e7165584b3e3225180b0000000000000814212e3a46525e686f6f6f6f6f6c625751545658595a5a5a5b61666a6d6f6f6f6d6a655f5851483f352b21170c01000000000000000006111c26303940454849494e5b6774818e9ba8ac9f9285786b5f52494949494948453f372e241a0f040013202c3946535f6c798693a0aca79a8d8173675a4d404045484b4e50515252525251504e4b4845403c36302a231b130b020000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0013202c3946535f6c7986939393939285786b5f52454c5865727e8c939393938b7e7165584b3e3225180b00101c2936424f5c68747979797979797979797064584b3e3225180c000000000000000000000000000000000000000000000000000000000000000000000000121f2c3845525f6b788592939393939393939393939393939393939393939393938a7d7063564a3d3023170a000c1825323e4b5764717d8a979d9184786c6054473b2f23170a00000000000000000000000000000000000000000000000000000000000000000000000000000000050a0e11131313131313131313131313131313131313131313131313131313131313131313131313110f0a05000000000000000000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986898a8a8a89888684817d79736c645b52483e33281d1106000000000000000000000000000000000000000d1924303b454e565a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a58534b41372b201408000d1924303b454e565a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a58534b41372b2014080013202c3946535f6c798693a0a2a2a2a1a09d99948d857c73695f554a3f33281c11050000000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000101d2a3643505d6976838f9ca9aea195887b6f6255493c2f23160a0000040f1b26303a42494e4f4f4e4d4c4b4b4a4946413a31271d120700000000000000000a131c252e373f474e555b61666b6f7376797b7d7e808080807f7e7c7976727b87929da9a69b8f84786c6155493d32261a0e02000000101c2936434f5c697683909ca9a99c908376818b949c96918c898785848485878a8e9399a0a8aca49b92897e74695e53483d31261a0f0300000013202c3946535f6c7986929facaa9d9084776a5d5144372a1e11040000000915222f3b4855626e7b8895a2aea5988b7e7165584b3e3225180b0000000000000916222f3c4955626f7a7c7c7c7c74675b4e47494b4e555b61676c72767a7c7c7b7976706a625a51473d33281d12070000000000000000000a141e272e35393c3c414e5b6774818e9ba8ac9f9286796c5f53463c3c3c3c3c39342d251d1309000013202c3946535f6c798693a0aca79a8d8173675a4d4035393c3f414344454646454443413f3c3835302b251f18110901000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0013202c3946535f6c7986868686868685786b5f52454c5865727e8686868686867e7165584b3e3225180b000e1b2733404c57626a6c6c6c6c6c6c6c6c6c685f54483c3023170a000000000000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929fa0a0a09c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c968a7d7063564a3d3023170a000a1723303d4956636f7c8995a194887c7063574b3f33261a0e020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c798692969696969593918e8a847e766d645a5045392e22160a00000000000000000000000000000000000000101d2935414c5760666767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767645d53483c3024180b00101d2935414c5760666767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767645d53483c3024180b0013202c3946535f6c7986939696989b9ea4a9a59f978f857b71665b5044392d2115090000000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000111e2b3844515e6a7784919daaada093877a6d6154473a2e21140800000009141e2831383e4243424140403f3e3d3c3a352f281f150b010000000000000000010a131c252d353c434a50565b5f63676a6d6f71727373737372716f6d6c77828d98a3aba0958a7e73675c5044392d21150900000000101c2936434f5c697683909ca9aa9d90837679828c949c9d9996939291919294969a9ea4aba7a19a928980766c62584d42372c20150900000000121f2c3945525f6c7885929fabaa9e9184776b5e5144382b1e12050000000a1623303c4956636f7c8995a2afa5988b7e7165584b3e3225180b0000000000000915222f3b4855616e7b88898983766a5e52494d535960666c72787d828688898886827c746c63594f453a2f23180c010000000000000000020c151d24292d2f34414e5a6774818e9aa7ada093877a6d6154484546474948453f372f251a0f040013202c3946535f6c798693a0aca79a8d8173675a4d40342c30323536383839393838363532302c28241f1a140d060000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00131f2c3946525f6b7679797979797979766a5e51454b58647079797979797979797064574b3e3125180b000b17232f3b4650585e5f5f5f5f5f5f5f5f5f5d564d42372c20140700000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929faba0958f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8a7d7063564a3d3023170a000815222e3b4854616e7a8794a0988c8073675b4f43362a1e12060000000000000000000000000000000000000000000000000000000000000000000000000000000004080b0d0d0d0d0d0d0d0d0d0c0a0601000000000000000000000000040708090909090909090908070501000000000000000000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c798691909090909295999a958f8880766c61564a3f33271b0e02000000000000000000000000000000000000121f2c3845515d697274747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474746f64584c4033261a0d00121f2c3845515d697274747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474746f64584c4033261a0d0013202c3946535f6c798689898a8b8e9399a0a8a9a1978d83786c61554a3e3226190d0100000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000121f2c3845525f6b7885929eabac9f9286796c5f5346392d201306000000020c161f262d323536353534333231302f2d2a241d160d0300000000000000000000010c17222d373f474c4e4d4f53575b5e606264656666676666646367727d88939ea9a59a8f84786d61564a3f33281c100500000000101c2936434f5c697683909ca9aa9d9084777079828a92989da2a09f9e9e9fa0a3a6a8a5a19c96908880776e655b50463b31251a0f0400000000121f2b3845515e6b7884919eabab9e9285786b5f5245392c1f13060000000c1825313e4b5764717d8a97a3b0a5988b7e7165584b3e3225180b0000000000000714212d3a4753606c79869292867a6e635956595f656b71777d83898e92959695928d867e756b61564b4034291d1105000000000000000000030b12181d202734404d5a6673808d99a6aea295897c706458535152545655514941362c2015090013202c3946535f6c798693a0aca79a8d8173675a4d4034272326282a2b2c2c2c2c2b2a282623201c18130e0902000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d00111e2a37434f5a646b6c6c6c6c6c6c6c6b64594e4248545f686c6c6c6c6c6c6c6c685e53483c2f23160a0007131e29343e464d52535353535353535353514b443b31261b0f0300000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7984909ba69c8f838282828282828282828282828282828282827d7063564a3d3023170a000714202d3a46535f6c7986929f9c9083776b5f53463a2e2216090000000000000000000000000000000000000000000000000000000000000000000000000000030a1015181a1a1a1a1a1a1a1a1a1916120c06000000000000000000070c11141515151515151515151514110d080100000000000000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7985848383838486898d949c9a92887d72675b4f43372a1e120500000000000000000000000000000000000013202c3946535f6c79818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818174675a4d4134271a0e0013202c3946535f6c79818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818174675a4d4134271a0e0013202c3946535f6c787c7c7c7d7e82878e969fa9a99f94897d72665a4e4236291d110400000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000131f2c3946525f6c7986929facab9f9285786b5f5245392c1f120600000000040d151c212628292928272625242423211e19130c04000000000000000000000005111d29343f4951585b59544f4b4e515456575859595a595959636e79848f9aa5a99e94897d72675c50453a2e23170b0000000000101c2936434f5c697683909ca9aa9d9084776a707880878c9296999b9d9e9f9f9e9d9b9895908b857e766e655c53493f342a1f14090000000000111e2a3744515d6a7784909daaac9f9386796d6053473a2d2114070000020e1a2733404d5966727f8c98a5b1a5988b7e7165584b3e3225180b00000000000006121f2c3845515e6a778490968b7f746a6463656a70767c83898f949a9fa2a3a19e9890877d73685c5145392e22160a0000000000000000000000070d111926323f4c5865727e8b98a4b1a5988c81756a625f5e5f6062615b53483d3125190d0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a191b1d1e1f1f1f1f1e1d1b191714100c08030000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000e1a26323e48525a5f5f5f5f5f5f5f5f5f5a52483d424d565d5f5f5f5f5f5f5f5f5c564d42372b1f130700020d18222c353c424546464646464646464644403a32291f140a00000000000000000000000000000000000000000000000000000000000000000000000000121f2b3844505c68737e8a949f9d91867b7575757575757575757575757575757575756d6155493c2f2316090005121f2b3845515e6b7784919d9f93877b6f62564a3e3225190d01000000000000000000000000000000000000000000000000000000000000000000000000050d151b212426272727272727272725221d171008000000000000020b12181d2022222222222222222222211d19130c04000000000000000000000000000000000000000000000000000000000000000000000000121f2c3845525e6b76787776767677797c828a939e9a8f83776b5f53463a2d21140800000000000000000000000000000000000013202c3946535f6c79868e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8174675a4d4134271a0e0013202c3946535f6c79868e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8174675a4d4134271a0e00121e2b3744505c666e6f6f6f7072767c848d97a2ada59a8e82766a5e5245392d20140700000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c798693a0acab9e9285786b5e5145382b1e12050000000000030a1016191c1c1c1b1a191918171614120d08010000000000000000000000000815212d3945505b636765605b56514b47494b4c4c4d4d4d56606a75808b95a0aba2988d82776c61564a3f34281d12060000000000101c2936434f5c697683909ca9aa9d9084776a666e757b8186898c8f9192929292908f8c8984807a736c645c534a41372d22180d030000000000101d2936434f5c6975828f9ca8ada194877b6e6155483b2f221609000005111e2a36434f5b6874818e9aa7b2a5988b7e7165584b3e3225180b00000000000004101d2936434f5c6875818d9a91867c75716f71757b81878e949aa0a5a2a0a0a1a4a2998f84796d62564a3e32261a0e010000000000000000000000010b1824313d4a5763707c8995a2aea99d91867c746e6c6b6c6d6f6d64594e4135291c0f0013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0f10121213131211100f0d0a07040000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000a16212c3740484f5253535353535353524e4840363b444b515353535353535353504b443b30261a0f03000006101a232a31363939393939393939393938342f2820170d03000000000000000000000000000000000000000000000000000000000000000000000000000f1c2834404b57626d78838d98a2978c82786e69696969696969696969696969696968645b5045392d2014080003101d2a3643505c6976828f9ca3978b7e72665a4e4235291d11050000000000000000000000000000000000000000000000000000000000000000000000050e171f272c31333434343434343434322e29221a110700000000020c141c23292d2f2f2f2f2f2f2f2f2f2f2d2a241e160d040000000000000000000000000000000000000000000000000000000000000000000000111d2a36424e5a646b6c6a6969696a6d7178818d98a094877b6e6255493c2f23160900000000000000000000000000000000000013202c3946535f6c7986939a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a8e8174675a4d4134271a0e0013202c3946535f6c7986939a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a8e8174675a4d4134271a0e000f1b28333f4a545d6263636364666b727b85909ba7ab9f93867a6e6155483c2f23160a00000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c798693a0acab9e9285786b5e5145382b1e120500000000000000050a0d0f100f0e0e0d0c0b0a0908050100000000000000000000000000000a1723303d4955626d74716c67615c57524d4842404049535d67727c87919ca7a69b91867b70665b5044392e23170c010000000000101c2936434f5c697683909ca9aa9d9084776a5d636a7075797d808284858686858482807c78746e68615a524a41382f251b11060000000000000f1b2835414e5b6774818d9aa7afa296897c7063574a3e3125180c00000a16222e3a46525e6b7784909da9b2a5988b7e7165584b3e3225180b000000000000000e1b2734404c5965727e8a96988f87817d7c7e81878c92999fa59f9995939394979da1958a7e72665a4e42362a1d11050000000000000000000000000916222f3b4854616d7986929eaaaea3988e867f7b7978787a7c766a5d5043372a1d100013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0005101a252e373e43464646464646464645433d362e323a4044464646464646464644403a32291f1409000000000811192025292c2c2c2c2c2c2c2c2c2c2b28241d160e0500000000000000000000000000000000000000000000000000000000000000000000000000000c17232f3a45515b66717b8690999e948a80776e665d5c5c5c5c5c5c5c5c5c5c5c5c5c5952493f34281d110400000f1c2835424e5b6774818d9aa79b8e82766a5e5145392d21140800000000000000000000000000000000000000000000000000000000000000000000040d17202931383d4040404040404040403e3a342c23190f040000000a141e262e34393b3c3c3c3c3c3c3c3c3b39352f281f160c01000000000000000000000000000000000000000000000000000000000000000000000e1a26323d48525a5f5f5e5d5c5d5e6066707c8996a296897d7063574a3d3024170a00000000000000000000000000000000000013202c3946535f6c798693a0a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a79a8e8174675a4d4134271a0e0013202c3946535f6c798693a0a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a79a8e8174675a4d4134271a0e000b17232e38424b5255565656575a6069747f8a96a2aea296897d7064574b3e3125180b00000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000013202c3946535f6c798693a0acab9e9285786b5e5145382b1e1205000000000000060c1013151514131211100f0e0d0b080400000000000000000000000000000b1724313e4a5764717d7d77726d68635e58534e4947515b656f79848e99a3a89e948a7f746a5f54493e33281d1206000000000000101c2936434f5c697683909ca9aa9d9084776a5d595f64696d7173767778797978777573706c68635d57504840382f261d1309000000000000000d1a2633404c5966727e8b98a5b1a4988b7e7265594d4034271b0f0306101b27323e4a56626e7a87939facb2a5988b7e7165584b3e3225180b000000000000000b1824313d4956626e7a86929e98928d8a898a8d92989ea4a099938e898686888c91999b8f83776a5e5246392d2014080000000000000000000000000713202c3845515d6975818d99a4aeaaa098908b878585858684776a5d5044372a1d110013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d000009131c252c323739393939393939393936322c24282f3438393939393939393938342f2820170d020000000000070e14191d1f2020202020202020201f1c18120c0400000000000000000000000000000000000000000000000000000000000000000000000000000007121e29343f4a555f6a747e87919a9c928980776f675f574f4f4f4f4f4f4f4f4f4f4f4d4740372d22170c0000000d1a2733404d5966737f8c99a59e92867a6d6155493d3124180c000000000000000000000000000000000000000000000000000000000000000000030d161f29323b43494c4d4d4d4d4d4d4d4d4a453e352b21160a000006111c26303840454848484848484848484846413a31281e1308000000000000000000000000000000000000000000000000000000000000000000000a15212c3640484f52575b5b5b5b5c5e636f7c8895a2978a7d7063574a3d3024170a00000000000000000000000000000000000013202c3946535f6c798693a0acb4ada5a09f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9a8e8174675a4d4134271a0e0013202c3946535f6c798693a0acb4ada5a09f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9a8e8174675a4d4134271a0e0006111c2730394046494949494a4e57626e7a86929eaba5988c7f7266594c403326190d00000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000131f2c3946525f6c7986929facab9e9285786b5f5245382c1f120500000000020a11171c20212221201f1e1d1c1b1a1814100a030000000000000000000000000b1724313e4a5764717d88837e79746e69645f5a555059636d77818b95a0aaa1978c82786d63584d43382d22170c00000000000000101c2936434f5c697683909ca9aa9d9084776a5d5053595d616467696a6b6c6c6b6a696664605c57524c453e362e261d140b01000000000000000b1825313e4a5763707d8996a2afa79a8e8175685c5043372b1f140f1018222d38434f5a66727e8a97a3afb2a5988b7e7165584b3e3225180b000000000000000815212d3946525e6a75818c97a29d999796979a9ea3a19b958e88827d7a797b8087909a93877a6e6155493c3023170a00000000000000000000000004101c2935414d5965717c87929ca5aca9a29c97949292929084776a5d5044372a1d110013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d0000010a131a21262a2c2c2c2c2c2c2c2c2c2a26211a1d24282b2c2c2c2c2c2c2c2c2b28231d160e050000000000000003090d111213131313131313131312100c070100000000000000000000000000000000000000000000000000000000000000000000000000000000010c18232e38434d58626c757f88919a9b928a817971696159514a4242424242424242403c362e251b11060000000c1825323e4b5864717e8a97a4a2968a7d7165594d4034281c100300000000000000000000000000000000000000000000000000000000000000020c151f28313b444d54595a5a5a5a5a5a5a5a5650473d32271b0f03000b17222d38424a5155555555555555555555524c433a2f24190d01000000000000000000000000000000000000000000000000000000000000000000040f1a242e37434f596268686767686a6e75808b97a195897c6f6356493d3023170a00000000000000000000000000000000000013202c3946535f6c798693a0acb0a59b94929292929292929292929292929292929292929292929292929292929292929292929292928e8174675a4d4134271a0e0013202c3946535f6c798693a0acb0a59b94929292929292929292929292929292929292929292929292929292929292929292929292928e8174675a4d4134271a0e00000a151e272f353a3c3c3c3d3e46515d6a76838f9ba8a69a8d8173675a4d4134271a0e01000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000121f2c3845525f6b7885929eabac9f9285796c5f5246392c1f1306000000010b141c22282c2e2e2d2c2c2b2a29282724201b140d0400000000000000000000000b1724313e4a5764717d8a8f8a85807a75706b65605b626b757f89939da7a2998f857a70665c51463c31261b100500000000000000101c2936434f5c697683909ca9aa9d9084776a5d50484d5155585a5c5e5f5f5f5f5e5c5a5754504b46413a342c241c140b0200000000000000000916232f3c4855616e7a87939faca99d9184786c6054483c30251d1b1c222a343e4954606b77838f9ba7b3b2a5988b7e7165584b3e3225180b0000000000000005111d2935414d5964707b869099a2a5a3a3a3a6a19c96908a837d77716d6d6f757e8893968a7d7164584b3f3226190d000000000000000000000000000d1925313d4854606b76808a939ba1a6a9a7a3a09f9e9d9084776a5d5044372a1d110013202c3946535f6c798693a0aca79a8d8173675a4d4034271a0d01000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0a0a09a8d8173675a4d4034271a0d000000010910161a1e1f202020202020201f1e1a150f12181c1f20202020202020201f1c18120c04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c27313c46505a636d767f8890999c938b837b736b635c544c453d363636363634302b241c1309000000000a1723303d4956636f7c8995a2a69a8d8175695d5044382c201307000000000000000000000000000000000000000000000000000000000000020b141e27313a434d565f65676767676767676662594f43382b1f1306000f1b27333f4a545c616262626262626262625d564c41352a1d1105000000000000000000000000000000000000000000000000000000000000000000000814212e3a4753606b7475747475777a8087919c9c9185796d6054483b2e22150900000000000000000000000000000000000013202c3946535f6c798693a0acada0948986868686868686868686868686868686868686868686868686868686868686868686868686868174675a4d4134271a0e0013202c3946535f6c798693a0acada0948986868686868686868686868686868686868686868686868686868686868686868686868686868174675a4d4134271a0e0000030c151d24292d2f30303035414e5a6773808d99a6a79a8e8174675b4e4134281b0e01000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000111e2b3744515e6a7784909daaaca09386796d6053473a2d20140700000009131d262d34383b3b3a39383736353433312c261f160d03000000000000000000000b1724313e4a5764717d8a9795908b86817b76716c676b747d87919ba5a39a90877d73695e544a3f352a1f150a0000000000000000101c2936434f5c697683909ca9aa9d9084776a5d50444145484b4e505152525252514f4d4b4844403b352f29221a130a020000000000000000000714202d3945525e6b7784909ca8ada094887c7064584d42372e2a28292d333c46505a65717c88939fabb7b2a5988b7e7165584b3e3225180b00000000000000010d1925313c48535e69747e8790979c9f9f9e9b96908b857e78726c666160636c76828d998c8073675a4d4134281b0f020000000000000000000000000814202c38434e59646e7881899095999c9e9fa0a09f9d9084776a5d5044372a1d110013202c3946535f6c798693a0a0a09a8d8173675a4d4034271a0d01000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693939393938d8173675a4d4034271a0d0000000000050a0e11131313131313131313110e0a04070c1012131313131313131312100c0701000000000000000000000000000000000000000000000000000000000104060708090a0a0a0908070503000000000000000000000000000000000000000000000000000000000a15202a343e48515b646d767e878f979d958d857d756d665e574f473f372f292927242019120a01000000000915222f3b4855616e7b8794a1aa9d9185796c6054483c2f23170b0000000000000000000000000000000000000000000000000000000000010a141d263039434c555f687173737373737373736b6054473b2e22150800121e2b3743505b666d6f6f6f6f6f6f6f6f6e685d5246392d211407000000000000000000000000000000000000000000000000000000000000000004090e15222e3b4855616e7b8281818283868b91999c948a8074695d5145382c1f130700000000000000000000000000000000000013202c3946535f6c798693a0acaca0938679797979797979797979797979797979797979797979797979797979797979797979797979797972665a4d4034271a0e0013202c3946535f6c798693a0acaca0938679797979797979797979797979797979797979797979797979797979797979797979797979797972665a4d4034271a0e000000030b12191d2123232326333f4c5865727e8b98a5a89b8e8174675b4e4134281b0e01000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000101d2a3643505c6976828f9ca8ada194877a6e6154483b2e221508000005101b252f383f44474847464544434241403d3831281f150b000000000000000000000b1724313e4a5764717d8a91969b97928c87827d7873737d868f99a3a49b92887e756b61574d42382e23180e030000000000000000101c2936434f5c697683909ca9aa9d9084776a5d504437393c3f414344454646454443413e3b38342f2a241e171009010000000000000000000004111d2a36434f5b6774808c98a5b0a4988c8175695e5349403a363535383e454e58626c77828d99a4abb2b2a5988b7e7165584b3e3225180b00000000000000000814202b37424d57626c757e868c909293918e8a858079736d67605a55535a65717d89938f8275695c4f43362a1d1004000000000000000000000000040f1b26323d48525c666f777e84898d909293939392918f84776a5d5044372a1d110013202c3946535f6c798693939393938d8173675a4d4034271a0d01000000000000000000000000000000000000000000000000000000000013202c3946535f6c79868686868686868173675a4d4034271a0d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003070b0e1012141516161716161513110f0c0905010206090b0c0c0c0c0c0c0c0c0b0906010000000000000000030e18222c363f49525b646c757d858d959d978f87807870686159514941382f261d18140e080000000000000714202d3a4653606c7986929faca195897c7064584c3f33271b0f02000000000000000000000000000000000000000000000000000000000a131c262f38424b555e67717a818181818181817c6f6255493c2f2216090013202c3946525f6c787b7b7b7b7b7b7b7b7a6e6255483b2f221508000000000000000000000000000000000000000000000000000000000000050b10151a1e222d3a46525e6a76828e8e8e9092969996918a82786e63584c4135281c100600000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6960554a3e3125190c0013202c3946535f6c798693a0acaca09386796c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6960554a3e3125190c0000000001070d111416161825313e4b5764717e8b97a4a89b8e8174675b4e4134281b0e01000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000f1c2835424e5b6874818d9aa7afa295897c6f6256493d3023170a00000a16212c37414a50545554535251504f4e4c49423a31271c11060000000000000000000a1724313d4a5763707b80858a8f949998938e89837e7d868f98a1a49b928980766c63594f453b30261c130a020000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372d303235363838393938373634322f2c28231e19130c06000000000000000000000000010e1a27333f4c5864707c8894a0aca99d91867a70655b524b4643424244494f576069737e89939a9aa0a9b2a5988b7e7165584b3e3225180b0000000000000000030f1a25303b46505a636c747b8084868685827e79746e68625c554f494955616d7a86868684776a5e5144382b1e1205000000000000000000000000000a15202b36404a545d656d73797d81838586868685848381776a5d5044372a1d110013202c3946535f6c79868686868686868173675a4d4034271a0d010000000000000000000000000000000000000000000000000000000000131f2c3946525f6b7679797979797979797266594d4033271a0d0000000000000000000000000000000000000000000000000000000003060809090909090807050301000000000000000000000000000000000000000000050a0f13171a1d1f2122232323232321201e1c1915110d0d12161819191919191919191815120d06000000000000000006101a242d374049525a636b737b838b929a99918a827a736b635b534a41382f261c12080000000000000006121f2c3845515e6b7784919daaa5998c8074685c4f43372b1f120600000000000000000000000000000000000000000000000000000009121c252e38414a545d677079838c8d8d8d8d8d887c6f6255493c2f2216090013202c3946535f6c7986888888888888887b6f6255483c2f22150900000000000000000000000000000000000000000000000000000000050b11161c21252a2e3236424e5a66727e8a969b948f8e8d8a85807870675c52473b30241c17110b050000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5d574e44392d2115090013202c3946535f6c798693a0acaca09386796c5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5d574e44392d211509000000000000010508090b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000d1a2733404d5966727f8b98a4b0a3978a7d7164584b3f3226190d00020e1a26323e49535b6161605f5e5d5c5b5b59544c43392e22160a0000000000000000000916232f3b48545f696f74797e83888d929899948f8a878f98a1a49b928980766d645a51473d36312b241c140a0000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a2326282a2b2c2c2c2c2b292825231f1c17130d080100000000000000000000000000000b17232f3c4854606c78848f9ba7aea2978c81776d645c56524f4e4f51555a6169727b8590958d8e97a2afa5988b7e7165584b3e3225180b00000000000000000009141f29343e48515a62696f747779797876726e68635d57504a443e45525e6b7679797979756a5e5144382b1e120500000000000000000000000000040f1a242e38424b535b62686d717477787979797977767470665b4f4236291c1000131f2c3946525f6b7679797979797979797266594d4033271a0d000000000000000000000000000000000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6960554a3d3125180c0000000000000000000000000000000000000000000000000004090d1012141616161616151412100e0b080501000000000000000000000000000000040b11161b1f2326292b2d2f303030302f2e2d2b2825211d19191e2225252525252525252524221e181109010000000000000008121b252e37404851596169717981888f979b948c857d756d655c534a41382e241a100500000000000003111d2a3743505d6976838f9ca9a89c9084786b5f53473b2e22160a000000000000000000000000000000000000000000000000000008111b242e37404a535c666f78828b959a9a9a92897f766c6054483b2f2215080013202c3946535f6c7986939595959595887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000020910161c22272d31363a3e41444a56626e7a8692998c8282807d79746e665e554b4037322d28221d17100a03000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f535252525252525252525252525252525252525252525252525252525252525252525252514c453c32271c11050013202c3946535f6c798693a0acaca09386796c5f535252525252525252525252525252525252525252525252525252525252525252525252514c453c32271c1105000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000c1825313e4a5763707c8995a2aea5998c8073675a4e4135291c100605111e2a36434f5a656d6e6d6c6b6a696867655e554a3f33261a0e01000000000000000007131f2b37434d575e63686d73787d82878c91969b969398a1a89c928980776e645b56514c47423c362e261c120700000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d191b1d1e1f1f1f1f1e1d1b1916130f0b07020000000000000000000000000000000007131f2b38444f5b67737e8a96a1aca89e93897f766e67625e5c5b5b5d61656c737b848e978f848693a0ada5988b7e7165584b3e3225180b000000000000000000020d18222c363f4850585e64686a6c6c6b6966625d57524c453f3936424e5a646b6c6c6c6c6b63594e4235291d1003000000000000000000000000000008121d263039414950575c6165686a6b6c6c6c6c6b6967655e554a3e32261a0e00111e2a37434f5a646b6c6c6c6c6c6c6c6c6960554a3d3125180c0000000000000000000000000000000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5d574e44392d2115090000000000000000000000000000000000000000000000050b1015191c1f21222323232221201f1d1a1815110d0701000000000000000000000000080f161c22272b2f3336383a3b3c3d3d3d3c3b393734312d2924232a2e313232323232323232312e29231b1309000000000000000009131c252e363f474f575f676f767e858c949c968f877f776e655c534a40362c22170c020000000000000f1c2835424e5b6874818e9aa0a0a094887b6f63574b3e32261a0e0000000000000000000000000000000000000000000000000007111a232d364049525c656e78818b949da59c938980766d645a4f44382c2013070013202c3946535f6c798693a0a2a2a295887b6f6255483c2f22150900000000000000000000000000000000000000000000000000050d141b21272d33383d42464a4e5154565d6975828e9a8e827673716d69635c544e4b47433e39342e28221b140d060000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f53464646464646464646464646464646464646464646464646464646464646464646464644413b332a20160b000013202c3946535f6c798693a0acaca09386796c5f53464646464646464646464646464646464646464646464646464646464646464646464644413b332a20160b00000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000916222f3b4854616d7a86929faba89b8f82766a5d5145392d2116131214202d3946525f6b777b7a79787776757470675b4f4236291d10030000000000000000030f1b26313b454d53585d62676c71767b80858b97a2a0a3a6a69a8d807b76716c67625d57524d4840382e23180d01000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110f10121213131211100f0c0a070300000000000000000000000000000000000000030f1b27333f4b56626d79848f9aa4afa59b91888079736e6b6968686a6d71777d858d9694897e8693a0aca5988b7e7165584b3f3225180c0000000000000000000006101a242d363e464d53585b5e5f5f5f5d5a56514c46403a342e323d48525a5f5f5f5f5f5e5951473d3125190d010000000000000000000000000000010b141e272f373f454b5055585b5d5f5f5f5f5f5e5d5b58534c43382d22160a000e1a26323e48525a5f5f5f5f5f5f5f5f5f5d574e44392d2115090000000000000000000000000000000000000000000000000000000000000a16212c3740484f525353535353535353514c453c32271c1105000000000000000000000000000000000000000000010910161c2125292b2e2f3030302f2e2d2b292724211e19120b03000000000000000000020a121a21272d32373b3f4245464849494a4949474644413d3a35302e353a3e3f3f3f3f3f3f3f3f3e3a342d251b110700000000000000010a131b242d353d454d555d646c737a828a929a99918980776e655c52483e33291e13080000000000000e1a2733404d596673808c93939393938b7f73675a4e4236291d10000000000000000000000000000000000000000000000000071019232c353f48525b646e77818a939da69d948a81776e645b52483e33271c10040013202c3946535f6c798693a0acafa295887b6f6255483c2f2215090000000000000000000000000000000000000000000000000810171e252c33393e44494e52565a5d60636567717d899593877b6f69676663615e5b57534e4a453f39332d261f18100800000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346393939393939393939393939393939393939393939393939393939393939393939393835302921180e04000013202c3946535f6c798693a0acaca09386796c5f5346393939393939393939393939393939393939393939393939393939393939393939393835302921180e0400000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000713202c3945515e6a76838f9ba7ab9e9286796d6155493d3228221f1f2026313d4955616e7a8786868584838281776a5d5044372a1d11040000000000000000000a151f2a333b42474c51565b60656a7179818a96a2a39c999b9d928c87827d78726d68635e59524a4035291e1206000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d11040000000000000000000000000000000000000000000000000000000000000000000b17232e3a45515c68737d88939da6ada39a928a847e7a7775757576797d82888f97978d837986929faca5988c7e7265584c3f3225190c000000000000000000000008121b242c343b42474c4f51535352504e4a45403b352f29232c3640484f5253535353524e483f362b20150900000000000000000000000000000000020c151d252d343a4045494c4f51525353535251504e4c48423a31271c1105000a16212c3740484f525353535353535353514c453c32271c110500000000000000000000000000000000000000000000000000000000000005101a252e373e4346464646464646464645413b332a20160b000000000000000000000000000000000000000000030b131a21272c3135383a3c3c3c3c3c3b3a383633312e29241d150c0200000000000000020b141c242b32383e43484b4f51535556565656555452504d4a46413c3840464a4c4c4c4c4c4c4c4c4a463f372d23180d02000000000002080d10131b232b333b434b535a61697078808890999b928a81776e645a50453a2f24190e0300000000000c1925323f4b5864717e8686868686868683776a5e5144382b1e120000000000000000000000000000000000000000000000060f19222b353e47515a646d768089939ca59e948b81786f655c524940362c22160b000013202c3946535f6c798693a0acaca295887b6f6255483c2f22150900000000000000000000000000000000000000000000010a121a222930373e444a4f555a5e62666a6d6f717375798591978b8077757472706d6a67635f5a55504a443e383129221a120a020000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b29241e170f0600000013202c3946535f6c798693a0acaca09386796c5f5346392c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b29241e170f060000000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000004111d2936424e5a67737f8b97a3aea295897d71655a4e443a322e2c2c2d3038424e5965717d8a939291908f8d8174685b4f4236291d10030000000000000000030e18212a31373e444a51585f666d747b838b939ba099928c90959a98938d88837e79746f6a645c51463a2e221509000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000000000000000000000000000000000000000000000000000006121d2934404b56616c76818b949da5aca49c958f8a87848281828385898e939a988f857b7885929eaba5988c7e7265584c3f3225190c00000000000000000000000009121a222a30363b3f434546464544413e3a352f2a241e1a242e363d43464646464645423d362d24190f040000000000000000000000000000000000030b141b22292f34393c40424445464646464543423f3c3730281f150a000005101a252e373e4346464646464646464645413b332a20160b000000000000000000000000000000000000000000000000000000000000000009131c252c32373939393939393939393835302921180e040000000000000000000000000000000000000000030c151d252c32383d414447484949494948464442403d3a352f271e140a000000000000010b141d262e363d444a4f54585b5e60616263636362615f5d5956514c47414a515758585858585858585651493f352a1e120600000000060d14191d1f202122293139414850575e666e767e878f989c938980766c61574c41362a1f140800000000000a1724303d4a56636f787979797979797979756a5e5144382b1e1200000000000000000000000000000000000000000000050e18212b343d475059636c767f89929ba59e958c82796f665d534a40372e241a1005000013202c3946535f6c798693a0a2a0a095887b6f6255483c2f221509000000000000000000000000000000000000000000020b131c242c333b42494f555b60656a6e7276797c7e80828385909c90858482817f7d7a77736f6b66615b565049423b342c241c140b0200000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1c18130d050000000013202c3946535f6c798693a0acaca09386796c5f5346392c201f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1c18130d05000000000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000010d1a26323e4b57636f7b87939eaaa69a8e82766b60554c443e3a3938393c424a545f6a76818d999f9e9d968a7d7165584c4033271a0e0100000000000000000a15202a333c43494f555c636970777e868d959d9d968f878084898e939899948f8a85807a756e62564a3d3024170a000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000000000000000000000000000000000000000000000000000000000000000000010c18232f3a45505a656f78828b939ba2a8a7a09b9693908f8e8e8f9295999e978f867d737784919eaba6998c7f7265594c3f3226190c000000000000000000000000000810181f252b2f3336383939393735322e29241e1913121c242c323639393939393936322b241b120800000000000000000000000000000000000000020911171e23282c30333637393939393938373533302c261e160d0300000009131c252c32373939393939393939393835302921180e040000000000000000000000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c29241e170f060000000000000000000000000000000000000000020b151e272f373d44494d515355565656555453514f4c4946403930261c1106000000000009131d262f3840484f555b5f64676a6c6e6f70706f6f6d6b6966625d58524c525c636565656565656565625b51463b2f23160a000000060f171f25292c2d2e2f2f3031363e454d545c646c747d8690999b92887d73685d52473c3024180d01000000000915222e3a47525d676c6c6c6c6c6c6c6c6c6b63594e4235291d10000000000000000000000000000000000000000000040e17202a333d464f59626b757e88919ba49f968c837970675d544b41382e251c120800000013202c3946535f6c7986939f96939393887b6f6255483c2f2215090000000000000000000000000000000000000000020b141d252e363e454c535a60666c71767a7e8285888b8d8e909197a19791908f8d8b898683807b77726d67615b544d463e362e261d140b02000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201313131313131313131313131313131313131313131313131313131313131312100c0802000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201313131313131313131313131313131313131313131313131313131313131312100c080200000000000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000000a16222e3a46525e6a76828d99a4aa9e93887c72675e554f4a47454546484d535c66707b87929eaaa99d9185796d6155493d3024170b0000000000000000030f1b26313c454e545a60676d747b828990989f98928b847d75787d82878c91969b96918b867e7164584b3e3125180b000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d11040000000000000000000000000000000000000000000000000000000000000000000007121d28333e48535d677079818991979da1a5a7a39f9d9c9b9b9c9e9f9a948d857d746b7784909da3a3998c807366594c403326190d0000000000000000000000000000060d141a1f23272a2b2c2c2c2b2825221d18130d070a121a21262a2c2c2c2c2c2c2a26211a120900000000000000000000000000000000000000000000060c12181c202427292b2c2c2c2c2c2b2a282624201b140c0400000000010a131a21262a2c2c2c2c2c2c2c2c2c2c29241e170f0600000000000000000000000000000000000000000000000000000000000000000000010910161a1e1f20202020202020201f1c19130d0500000000000000000000000000000000000000000009141d27303941484f55595d606263636362615f5e5b5956524b42382d22160b0000000006111b252f38414a525960666b707477797b7c7c7d7c7b7a7875726e69635d5658646e72727272727272726d63574b3e3225190c0000040f1821293035393a3b3b3c3d3e3d3b3b424a525a626b747e87919c9a8f857a6f63584c4135291d11050000000006121e2a36414c555c5f5f5f5f5f5f5f5f5f5e5951473d3125190d0000000000000000000000000000000000000000040d162029323c454f58616b747e87909aa3a0978d847a71675e554b42382f261c130a0000000013202c3946535f6c798692998d868686867b6f6255483c2f22150900000000000000000000000000000000000000010a141d262f3740484f575e656b72777d82878b8e929597999b9c9da1a9a29e9d9c9a9896938f8b87837d78726c655f57504840382f261d140b020000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000006121e2a36424e5a65717c88939ea9a4998e83797067605a565352525355585e656e78828d98a3aea3988c8175695d5145392d211408000000000000000007131f2b37434e575f656b72787f868d949b99938d878079726b6c71767b81868b90959a978b7e7165584b3e3225180b000000000000101c2936434f5c697683909ca0a09d9084776a5d5044372a1d110400000000000000000000000000000000000000000000000000000000000000000000010c17222c37414b555e676f777f868c9195999b9d9f9f9f9f9d9b98938e89827b736b69768390969696968d8073665a4d4034271a0d00000000000000000000000000000003090e13171a1d1f20201f1e1c1915110c070200000810161a1e1f202020201f1e1a150f0800000000000000000000000000000000000000000000000001070c1014171a1c1e1f2020201f1f1d1c1a17140f0902000000000000010910161a1e1f20202020202020201f1c19130d0500000000000000000000000000000000000000000000000000000000000000000000000000050a0e1113131313131313131312100d080200000000000000000000000000000000000000000006101b252f39424b535a6065696c6e6f6f6f6f6e6c6a6865625d544a3f33271b0e000000020d18222d37414a535c646b71777c8083868789898a89888785827e7a756f68615b68747e7e7e7e7e7e7e7e7366594d4033261a0d00000b16202a333b4145474748494a4a4a47413a40485059626b75808a95a1968b8075695d5145392d21140800000000020e19252f3a434b50535353535353535353524e483f362b20150900000000000000000000000000000000000000030c161f28323b444e57616a737d869099a2a1978e857b72685f554c433930261d140a0100000000121f2c3945525f6b788592988c7e797979786d6155483b2f2215080000000000000000000000000000000000000009131c262f384149525a616970767d83898e92979b9ea1a4a6a8a9aaa9a8a8a9a9a8a7a5a29f9b98938e89847d777069625a524a41392f261d140a0000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000020e1a26313d4954606b76828c97a2aaa0958b8279726b6662605f5f5f6164697077808a949ea9a79c92877b7064584d4135291d110400000000000000000916222f3b48545f6a70767d838a909090908e88827c756f686161666b70757a7f84898e938b7e7165584b3e3225180b000000000000101c2936434f5c69768390939393939084776a5d5044372a1d1104000000000000000000000000000000000000000000000000000000000000000000000005101a252f39434c555d666d747a8085898c8f9192929392908e8b87837d777069616875828a8a8a8a8a8a8174675a4e4134281b0e000000000000000000000000000000000003070b0e1012131313110f0d0905010000000000040a0e11131313131313110e0a040000000000000000000000000000000000000000000000000000000004080b0e1011121313131312110f0d0b080300000000000000000000050a0e1113131313131313131312100d080200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c17222d37414b545d656b7176797b7c7c7c7b7a797774726e665b4f43372a1e1100000008131e29343f49535c656e757c83888c909294959696969593918e8a86807a736b626875828c8c8c8c8c8c7e7265584c3f3226190c0005111c28323c454d5153545555565757534c43393e47505a636e79848f9b9d91857a6d6155493d3024170b000000000008131e2831393f4446464646464646464645423d362d24190f04000000000000000000000000000000000000000a151e28313a444d566069737c858f98a2a1988f857c726960564d433a31271e140b020000000000121e2b3844515e6b778491998c80736c6c6c665c5145392d20140700000000000000000000000000000000000007111b252e38414a535b646b737a81888e94999ea3a7aaa9a6a3a09f9d9c9c9c9c9d9ea0a2a5a9a8a49f9a958f89827b746c645c534b42382f261c120800000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0b0905000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0b090500000000000000000000000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000915212c38434f5a65707b86909aa4a79d948b837c77726f6d6c6b6c6e71757a8189929ca6a99f958b80756a5f53483c3024180c0000000000000000000a1724303d4a5763707c8283838383838383827d77716a645d56555a5f64696e73787d83888b7e7165584b3e3225180b000000000000101c2936434f5c69768386868686868684776a5d5044372a1d110400000000000000000000000000000000000000000000000000000000000000000000000009131d27313a434b545b62696f74797d8082848586868584827f7b77726c665f5a66737d7d7d7d7d7d7d7d74685b4e4135281b0f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000206090a0a0a0a0a0a0a0a0a0a0906030000000000000000000000000006111d28333e49535d666f767d82858889898988878583817e786b5e5245382c1f120000020d1924303b46505b656e7780878e94989c9fa1a2a3a3a3a2a09e9a96918b847d756c6976838f989898988b7e7164584b3e3225180b000915212d39444e575e606161626364635e554b40353e48525c67737f8b97a2968a7d7165584c3f33261a0d0100000000010c161f272e34383939393939393939393936322b241b12080000000000000000000000000000000000000006111c26303a434c565f68727b858e97a1a2998f867c736a60574e443b31281f150c02000000000000101d2a3643505c6976828f9b8e8275685f5f5b544a4034291d11040000000000000000000000000000000000040f19232d37404a535c656d757d858c93999fa5aaaba6a19d9a969492908f8f8f8f90919396999da1a6aba6a09a948d857e766e655d544b41382e241a1005000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201919191919191919191919191919191919191919191919191919181715110c0500000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201919191919191919191919191919191919191919191919191919181715110c050000000000000000000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000000004101b27323d49545e69747e88929ba4a69d958e88837e7b797878797a7d81868c939ba4a8a0978d83796e64594d42372b1f14080000000000000000000a1623303c4956626d75767676767676767676716b665f59524b494e53585d63686d72777c817e7265584c3f3225190c000000000000101c2936424f5c6874797979797979797974695c5043362a1d1004000000000000000000000000000000000000000000000000000000000000000000000000010b151f283139424a51585e64696d70737677787979787775736f6b66615b5456626b70707070707070706c63584c4033271a0d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000407090c0d0e0f1010100f0e0d0b08060200000000030405050505050505050402000000000000000000000000000000000000000000000000000206090c0e1011121313131312110f0d0a0704000000000000000000000000000000000000000000000000000407080808080808080808080705010000000000000000000001080e12151717171717171717171716130f090300000000000000000000000b17222e3945505b656f7881888e9294969696959492908d85786b5f5245382c1f12000007121e2a35414c57626d77818a92999fa4a8a8a3a09d9b9a9a9a9b9c9f9d968f877e756b7683909da5a4978a7d7164574a3e3124180b000c1825313e4a5560696d6d6e6f70716f675c50443836404b56636f7b8894a19a8d8174675b4e4135281b0f020000000000040d151d23282b2c2c2c2c2c2c2c2c2c2c2a26211a120900000000000000000000000000000000000000000b17222e38424c555e68717a848d97a0a39a90877d746a61584e453c32291f160d03000000000000000f1c2835414e5b6774818d9a9184786b5f53504a42382e23180c0000000000000000000000000000000000010b16202b353f49525c656e7780878f979ea4abaca6a09a95918d8a878584838282828385878a8d91959aa0a6aba59e97908880776f665d534a40362c22170d020000000013202c3946535f6c798693a0acaca09386796c5f5346392c2525252525252525252525252525252525252525252525252525252524211d171008000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2525252525252525252525252525252525252525252525252525252524211d17100800000000000000000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000a16212c37424d57626c768089929aa2a7a099938e8b888685858687898d91979ea5a69f978e857b71675d52473c31261a0f030000000000000000000815212d3945515c646969696969696969696966605a544e47413e43484d52575c61666b7075797064584b3e3225180c0000000000000e1b2733404c57626a6c6c6c6c6c6c6c6c6a62584c4034281b0f0200000000000000000000000000000000000000000000000000000000000000000000000000030d161f2730383f464d53585d616467696b6c6c6c6c6a6966635f5b554f495059606363636363636363615a51473b3024170b0000000000000000000000000000000000000000000000000000000000000000000000000000000004090d101316181a1b1c1c1c1c1c1b191715120f0b06070c0f111212121212121212110f0b07010000000000000000000000000000000000000001060a0e1215181a1c1e1f1f20201f1e1d1b191714100c08030000000000000000000000000000000000000000060c10131515151515151515151514110d080200000000000000040c13191e2223242424242424242424221f1a140d05000000000000000000030f1b27333f4a56616c77818a93999ea1a2a3a2a2a09f9c9285786b5f5245382c1f1200000b17232f3b46525d69747e89939ca4aaaaa39c9793918f8e8d8d8e9092969a9990877d747784919daaa4978a7d7063574a3d3124170a000d1a2733404d596672797a7b7c7d7d796c6053473a323a4753606d798693a09c8f8275695c4f4236291c1003000000000000030b12171c1e2020202020202020201f1e1a150f080000000000000000000000000000000000000000000f1b27333f4a545e67707a838d969fa49a91887e756b62584f463c332a20170d0400000000000000000d1a26333f4c5865727e8a9794877b6f63574b3f3830261c1207000000000000000000000000000000000008121d28323d47515b646e7780899199a1a8afa8a19b948f8a85817d7b79777675757577787a7d8185898f949ba1a9a9a29a928981786f655c52483e33291f14090000000013202c3946535f6c798693a0acaca09386796c5f5346393232323232323232323232323232323232323232323232323232323232312d28221a11080000000000000013202c3946535f6c798693a0acaca09386796c5f5346393232323232323232323232323232323232323232323232323232323232312d28221a1108000000000000000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000004101b26313b46505a646d76808890979ea4a49f9b9795939292929496999da2a8a29b948d857c73695f554b40362b2014090000000000000000000005111d29343f4a52595c5c5c5c5c5c5c5c5c5c5a554f49433c3632373c41464b50555a5f64696c685f54483c3023170a0000000000000b17232f3b4650585e5f5f5f5f5f5f5f5f5e5950463b3024180c000000000000000000000000000000000000000000000000000000000000000000000000000000040d151e262d353b41474c5154585a5c5e5f5f5f5f5e5c5a57534f4a443e474f5456565656565656565550483f352a1f13070000000000000000000000000000000000000000000000000000000000000000000000000000050a1015191d20232526282929292928272624211e1b171213181c1e1e1e1e1e1e1e1e1e1e1b17120c040000000000000000000000000000000001070d12161b1e222527292a2c2c2c2c2c2b2a282623201c18140f090300000000000000000000000000000000020a11181c2021222222222222222222201d19130c040000000000030d161e252a2e303030303030303030302f2b261f170f05000000000000000006131f2b37434f5b67727e89939da4aaada7a29f9d9c9d9e9285786b5f5245382c1f1200030f1b27333f4b57636e7a85909ba5aea9a098918c8784828181818183868a8f94998f867b7784919eaba4978a7d7063574a3d3024170a000d1a2734404d5a66738087888989887b6f62564b423f3f4754606d7a8693a09c8f8276695c4f4336291c10030000000000000000060b0f1213131313131313131313110e0a0400000000000000000000000000000000000000000000121e2b3744505b667079838c959fa49b92887f756c635950473d342a21180e050000000000000000000b1724313d4956626f7b8794978b8073675c5045392e23180d0300000000000000000000000000000000030e19242f39444e59636d768089929ba3abaea69e979089837e7975716e6c6a696968696a6c6e7174797e838990979ea6aca49b938a81776d645a4f453b30261b100500000013202c3946535f6c798693a0acaca09386796c5f53463f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3d39332c231a100500000000000013202c3946535f6c798693a0acaca09386796c5f53463f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3d39332c231a10050000000000000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e03010000000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c100300000000000000000000000009141f29343e48525b646d767e868d93989da2a5a3a1a09f9f9fa0a2a5a4a09c97918a837b726a61574d43392f24190e0300000000000000000000010c18232e3840484d4f4f4f4f4f4f4f4f4f4f4e49443e38312b262b30353a3f44494f54595d5f5d564d42372c20140700000000000007131e29343e464d525353535353535353524e473e352a1f140800000000000000000000000000000000000000000000000000000000000000000000000000000000030c141c232a30363b4045484b4e505152535352514f4d4a47433e39353d44484a4a4a4a4a4a4a4a48453e362d23190e02000000000000000000000000000000000000000000000000000000000000000000000000020910161b2025292c2f31333535363636353432302e2b27231e1e24282a2b2b2b2b2b2b2b2b2a28231d160e050000000000000000000000000000050c12181d22272b2e31343637383939393938363532302c2924201a150f080100000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2d29241e160e04000000000b151f282f363a3d3d3d3d3d3d3d3d3d3d3b37312921170d02000000000000000916222e3b47535f6c78848f9aa5aeaca39c9692909090919285786b5f5245382c1f120006121f2b37434f5c6874808b97a2acaca1978e87807b787574737375767a7e838990978d837885929eaba3968a7d7063564a3d3023170a000c1925323f4b5864717d899495968b7e73675d544e4c4c4f58636f7c8895a19b8e8275685c4f4235291c0f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c78828b959ea69c928980766d635a51473e342b22180f05000000000000000000000815212e3a46535f6b7784909c9084786d61564b3f352a1f150a0000000000000000000000000000000009141f2a35404b56606a757f89929ba4adada49c948c857e78726d6965625f5e5c5c5b5c5d5f6165686d72787e858d949ca5ada59c938980766c61574c42372c21160b00000013202c3946535f6c798693a0acaca09386796c5f534c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4b4a453e352c22170b00000000000013202c3946535f6c798693a0acaca09386796c5f534c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4b4a453e352c22170b0000000000000000000000000000000b1724313e4a5764717d8a97a4a89b8e8275685b4f4235281c100f0d0a06000000000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c1003000000000000000000000000030d18222c364049525b646c747b82888d9195999b9d9e9fa09f9e9d9b9894908b857f78716960574e453c32271d120800000000000000000000000007111c262e363d4143434343434343434343413d38322d26201a1f252a2f34393e43484d5153514b443b31261b0f03000000000000020d18222c353c4245464646464646464645423c352c23180e020000000000000000000000000000000000000000000000000000000000000000000000000000000000020a11181f252b3034383c3f414345454646454443413e3b37322d2c33383c3d3d3d3d3d3d3d3d3c39332d241b1107000000000000000000000000000000000000000000000000000000000000000000000000050d141b21272c3135393b3e40414243434342413f3d3a37332f2a282f3437383838383838383837342e2820170d030000000000000000000000010910171d23292e33373a3d40424445464646454543413f3c3935302b26201a130c040000000000000000000000000a141d262e34383b3b3b3b3b3b3b3b3b3b39352f2820160c02000006121d27313a41474a4a4a4a4a4a4a4a4a4a47423b33291f1409000000000000000c1825313e4a57636f7c8894a0acaea49a918a86838383858685786b5f5245382c1f12000915222e3b4753606c7884909ca8b0a59a8f867c756f6b69676767686a6d72787e868f958a7f85929faba3968a7d7063564a3d3023170a000a1723303c4855616d7986919d9b8f84796f665f5a59595b606a74808c98a4998c8073675a4d4134281b0e020000000000000000000004080b0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0c09060100000000000013202c3946535f6c7986939da7a1958a81776d645b51483f352c22191006000000000000000000000005121e2a37434f5b67737f8b9795897e72675c51463b31261b0f030000000000000000000000000000030f1a25313c47525d67727c87919aa4adada49b928a827a736d67615d59555351504f4f4f515255585c61676d737b828a939ca5aea59b92887d73695e53493e33281d1106000013202c3946535f6c798693a0acaca09386796c5f58585858585858585858585858585858585858585858585858585858585858585650473e33281c1105000000000013202c3946535f6c798693a0acaca09386796c5f58585858585858585858585858585858585858585858585858585858585858585650473e33281c110500000000000000000000000000000b1724313e4a5764717d8a97a4a99c8f8376695d5043372b1f1d1c1a16110b0400000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000000000101c2936434f5c69768390908376695c4f4336291c10030000000000000000000000000006101a242e374049525a626970767c8185898c8f909292939292908e8b8884807a746d665f574e453c332a20150b01000000000000000000000000000a141c252b31343636363636363636363635322d27211b150f14191e23282d32373c41454644403a32291f140a000000000000000006101a232a31363939393939393939393936312b231a11070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070d14191f24282c303235373839393939383634322e2b262221272c2f30303030303030302f2d28221b1209000000000000000000000000000000000000000000000000000000000000000000000000060f171f262c32383d4145484a4c4e4f4f4f4f4f4d4c4947433f3b35333a4044454545454545454543403932291f150a00000000000000000000030b131b22292f353a3f43474a4d4f50525253535251504e4b4845413c37312b241d160e060000000000000000000006111c262f383f454848484848484848484846413a32281e130800000b17232e39434c5256575757575757575756534d453b30251a0e020000000000000d1a2733404d5966727e8b98a4b0a89d9288807a777676787a7c786b5f5245382c1f12000c1825313e4a56636f7b8894a0acab9f94887e736a635f5c5b5a5a5b5e61666d747d868f908586929faca3968a7d7063564a3d3023170a000714202d3945515d6975818c97a1958b8178706a676565676b727b86919ca095897d7064584b3f3226190d000000000000000000030a101417191919191919191919191919191919191919191919191919191816120c06000000000013202c3946535f6c7986939fa8a194897f756c625950463d332a20170d040000000000000000000000020e1b27333f4b57636e7a86919a8f84786d62584d42372c20130700000000000000000000000000000914202b37424d58636e79848e98a3acafa59b928980787068625b56514c494644434242434446494c50565b62697078818a939ca5ada3998f857a70655a4f44392e23170c000013202c3946535f6c798693a0acaca09386796c65656565656565656565656565656565656565656565656565656565656565656561594f44392d211408000000000013202c3946535f6c798693a0acaca09386796c65656565656565656565656565656565656565656565656565656565656565656561594f44392d21140800000000000000000000000000000a1724313d4a5763707d8a96a3aa9e9185786b5f53473b302b2a2926221d160e05000000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000000000010507101c2936434f5c69768390908376695c4f4336291c1007050100000000000000000000000008121c252e37404850585f656b7075797d808284858686868584827f7c78736e69635c554d453c332a21180e040000000000000000000000000000020a131a202528292929292929292929292825211c16100a04080d12171c21262b3035383938342f2820170d030000000000000000000811192025292c2c2c2c2c2c2c2c2c2c2a26201911080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080e13181c202326282a2b2c2c2c2c2b2a2825221e1a16161c2022232323232323232323201c171009000000000000000000000000000000000000000000000000000000000000000000000000060f18212930373e43494d515457595b5c5c5c5c5b5a5856534f4b46413c454c505151515151515151504b443b31261b10040000000000000000040d151d252c333a40454b4f5356595b5d5e5f5f5f5f5e5c5a5855514d48423c362f28201810070000000000000000000b17222d38424a5154555555555555555555524c443a3025190e02000f1c28343f4b555d636363636363636363635f574d42362a1e12050000000000000f1b2835424e5b6774818e9aa7b0a4988c80766e6a696a6b6d706e665b4f43372a1e11000e1a2733404d5966727e8b98a4b0a69a8e83776c615853504e4d4d4f51565b626b747d8792909097a2aea3968a7d7063564a3d3023170a0004101d2935414d58646f7b86909a9d938a827b7673727274777d848d98a29a8f84786c6054483c2f23170a0000000000000000050e151b20242626262626262626262626262626262626262626262626262625221d1811090000000013202c3946535f6c79848d96a0a59b91887e746b62584f453c32291f160c0300000000000000000000000a17232f3a46525e6975808b93938a7f74695f54483c2f23160a00000000000000000000000000020e1a25313c48535e6a75808b95a0aab1a79d938980776e665e57504a45403d3a383636353637393c40454a50575f666f77818a949da7aba1978c82776c61564a3f34281d11050013202c3946535f6c798693a0acaca0938679727272727272727272727272727272727272727272727272727272727272727272726b6155493d3023170a000000000013202c3946535f6c798693a0acaca0938679727272727272727272727272727272727272727272727272727272727272727272726b6155493d3023170a00000000000000000000000000000a1623303c4956626f7b8895a1ada094877b6f63574c423b383635332e2720170e040000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c20130000000000070d1114161c2936434f5c69768390908376695c4f4336291c1614110d070000000000000000000000000a131c252e363e464d545a5f64696d7073757778797979787775726f6c68635d57514a433b332a21180f060000000000000000000000000000000001080f14191b1c1c1c1c1c1c1c1c1c1c1c1915100b0500000001060c11161b2025292c2c2b28241d160e050000000000000000000000070e14191d1f20202020202020201f1d1a150e070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002070c101417191c1d1e1f20201f1e1d1b1916120e0a0b10141617171717171717171614100c06000000000000000000000000000000000000000000000000000000000000000000000000050f18212a333b42494f54595d6164666768696969686765625f5b57524c464e565c5e5e5e5e5e5e5e5e5c564d43382c20140800000000000000040d161f272f373e454b51565b5f6366686a6b6c6c6c6c6b696764615d58534e48413a322a2219100700000000000000000f1b27333f4a545c616161616161616161615d564c41362a1e120600121e2b3844505c676f707070707070707070695e52463a2d211408000000000000101c2936434f5c6975828f9ca8ada094887b6f645e5c5d5f6163625d544a3f33271b0f000f1c2935424f5b6874818e9aa7afa3978a7e72665b50474341404142454a5159626b75808b969ca1a9b0a3968a7d7063564a3d3023170a00000d1924303c47535e69747e88929a9c948d8783807e7f8183888e969f9b92887e73675c5044382c20140700000000000000050e1720272c3033333333333333333333333333333333333333333333333333312e29221b1208000000121f2b3844515d68717b858e97a1a39990877d736a61574e443b31281e150b020000000000000000000006121e2a35414d58636f7a85868686867b7064574b3e3125180b0000000000000000000000000007131f2a36424d5964707b86919ca7b2aa9f958b81776e655c544c453f3934302d2b2a2929292b2d3034393f454d545d656e78828b95a0aaa89e93887d72675b5045392d2115080013202c3946535f6c798693a0acaca093867e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7d7164574b3e3124180b000000000013202c3946535f6c798693a0acaca093867e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7d7164574b3e3124180b00000000000000000000000000000815212e3a4754606d7985929eaaa3978b8074685e544c474443423f39322920160b0000000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000000030b12181d2022222936434f5c69768390908376695c4f4336292222201d18120b0300000000000000000000010a131c242c343b42494e54595d616467696a6b6c6c6c6b6a686663605c57524c463f38312921180f060000000000000000000000000000000000000004090c0f101010101010101010100f0d09050000000000000000050a0f14191d1f201f1c18120c040000000000000000000000000003090d1112131313131313131313110e0903000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004070a0d0f11121313131212100e0c09060200000407090a0a0a0a0a0a0a0a09070400000000000000000000000000000000000000000000000000000000000000000000000000020d17212a333c454c545a6065696d707274757676757573716f6b67635d57515560686b6b6b6b6b6b6b6b675f54493d3024180b000000000000020c161f283139414950565c62676b6f7274767879797978777673706d69645f59524b443c342b2219100600000000000000121e2b37434f5b666d6e6e6e6e6e6e6e6e6e685e52463a2e2115080013202c3946535f6c787d7d7d7d7d7d7d7d7b6e6255483c2f221509000000000000101c2936434f5c697683909ca9ab9e9285786c5f534f5052545656524b42382d22170b00111d2a3744505d697683909ca9ada094877a6e62564a3e3735343435393f475059646e7a85919ca8b3b0a3968a7d7063564a3d3023170a00000814202b36424d58626c76808890979e98938f8d8c8c8d8f94999f99928980766c61564b3f34281c1004000000000000010c17202931383d3f4040404040404040404040404040404040404040404040403e3a342d241a10060000101c2834404b565f69727c858f98a2a2998f867c736960564d433a30271d140a01000000000000000000020d1925303c47525d68737979797979797064574b3e3125180b000000000000000000000000000b17232f3b47525e6a75818c98a3aeaea3988e83796f655c534a423a342e2824211e1d1c1c1d1e2024282e343b434b535c666f79848e98a3aaa49a8f83786d6156493d3124170b0013202c3946535f6c798693a0acaea2968d8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8b7e7164574b3e3124180b000000000013202c3946535f6c798693a0acaea2968d8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8b7e7164574b3e3124180b000000000000000000000000000006121f2b3844515d6975828d99a4a89c90857a6f665e585451504e4a443b32271c110500000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c20130000020c151d24292d2f2f2f36434f5c69768390908376695c4f43362f2f2f2d29241d150c0200000000000000000000010a121a222a31373d43484d5154575a5c5e5f5f5f5f5f5d5c5a5753504b46413b352e271f170f0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003080d10121312100c070100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009141f29333c454e575e656b7175797c7f818282838282807e7b78736e69625b5a667278787878787878787165594c3f3326190d0000000000000a141e28313a434b535a61686e73777b7e818385868686858482807d7975706a645d564e463d342b22180e0400000000000013202c3946525f6c777b7b7b7b7b7b7b7b7a6f6256493c2f2316090013202c3946535f6c79868a8a8a8a8a8a887b6f6255483c2f221509000000000000101c2936434f5c697683909ca9aa9d9084776a5e51444445484a4946413930261c110600121f2b3845515e6b7784919eaaab9e9185786b5f52463a2d282727292d353e48525d6874808c98a4b0b0a3968a7d7063564a3d3023170a0000030e1a25303b46505a646d767e868c92979a9b9998989a9c9b98938e8780776e645a50453a2e23170b0000000000000007131e29323b43494c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4a453f362c22170c00000c18242f3a444d57606a737d869099a3a1988e857b72685f554c42392f261c13090000000000000000000008141f2a36414c5761696c6c6c6c6c6c685e53483c2f23160a000000000000000000000000030f1b2834404b57636f7b86929da9b3a89d92877c71675d534a41383029221d181412100f0f101114181d22293139414a545e67727c87919c9e99938d887e7265584b3f3225180c0013202c3946535f6c798693a0acb3a89f999898989898989898989898989898989898989898989898989898989898989898988b7e7164574b3e3124180b000000000013202c3946535f6c798693a0acb3a89f999898989898989898989898989898989898989898989898989898989898989898988b7e7164574b3e3124180b000000000000000000000000000003101c2835414d5965717c88939ea8a1968c8178706964605e5d5b554d44392e22160a00000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c201300000a141e272e35393c3c3c3c434f5c69768390908376695c4f433c3c3c3c39352e271e140a0000000000000000000000000910181f262c32373c4145484b4d4f515253535252514f4d4a47443f3b35302a231c150d0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004080b0c0c0c0c0c0c0c0b08040000000000000000000000000000000000000000000000000000000004070808080808080808080808080808080808080808080808080808080808080808080808080808080806040000000000000000000000000004070808080808080808080807040000000000000000000005101b26303b454e57606970777c8286898c8d8f8f908f8e8d8b8884807a746d655d6875828585858585857f7266594c4033261a0d000000000007121c26303a434c555d656c73797e83888b8e909192939292918f8c8985817b756f6860584f463d342a20160c01000000000013202c3946535f6c7986888888888888887c6f6255493c2f2316090013202c3946535f6c7986939797979795887b6f6255483c2f221509000000000000101c2936434f5c697683909ca9aa9d9084776a5d504437393b3d3d3a352f271e150a0000131f2c3946525f6c7885929faba99c9083766a5d5044372b1e1a1a1d232c36414c58636f7b8894a0acb0a3968a7d7063564a3d3023170a00000009141f2a343e48525b646c747b81868b8e9092939392918f8c88837c756e655c53483e33281d1206000000000000000c18242f3a444d54585959595959595959595959595959595959595959595959595650483e34281d11050007121d28323b454e58616b747e87919aa3a0978d847a71675e544b41382e251b1209000000000000000000030e19242f3a454f585e5f5f5f5f5f5f5c564d42372b1f130700000000000000000000000007131f2c3844505c6874808b97a3aeada2968b80756a60554b41382f261e17110c08050300000205080c11171f272f38424c56606a75808a95938d88827c766f63574b3e3125180b0013202c3946535f6c798693a0acb9b1aaa6a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a4988b7e7164574b3e3124180b000000000013202c3946535f6c798693a0acb9b1aaa6a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a4988b7e7164574b3e3124180b0000000000000000000000000000000c1925313d4954606b77828c96a0a89d938a827a74706c6a69675f554a3e32261a0d00000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c20130006111c263039404548494949494f5c69768390908376695c4f494949494845403930261c1106000000000000000000000000060d141b21262c3035383c3f41434445464646454443403e3b37332f2a241f18110a030000000000000000000000000000000000000000000000000000000000000104070a0c0e0f111112121211100e0d0a080401000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a101417191919191919191715100b04000000000000000000000000000000000000000000000000060c10131515151515151515151515151515151515151515151515151515151515151515151515151515151513100b06000000000000000000060c10131515151515151515151513100c0700000000000000000b16212c37424d57606a727a82888d9295989a9b9c9c9c9b999794908b857f776f676975828f929292928b7e7165584b3f3225180c00000000030e19232e38424c555e676f777e848a8f94979a9c9e9fa09f9f9d9b9995918c878179726a61584f463c32281d13080000000000131f2c3946525f6c7985929595959595887b6f6255493c2f2216090013202c3946535f6c798693a0a4a4a295887b6f6255483c2f221509000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372c2f30302e2a241d150c03000013202c3946535f6c7986939faca89b8f8275685c4f4236291c100e111a242f3b47535f6b7884919da9b0a3968a7d7063564a3d3023170a000000020d18222d364049525a626970757a7e8284858686868482807c77716b645c534a41372c22170c0100000000000000101c2935404c565f65666666666666666666666666666666666666666666666666625a5045392d21150800010c162029333c464f59626b757e88929ba49f968c837970665d534a40372d241b110800000000000000000008131e29333d464d51535353535353504b443b30261a0f030000000000000000000000000b17232f3c4854606c7884909ca8b4a89c91857a6f64594e44392f261d140d0600000000000000000000060d151d26303a444e59636e79848d88827c76716b655d52473b2f22160a0013202c3946535f6c798693a0acb7ada5a1a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0988b7e7164574b3e3124180b000000000013202c3946535f6c798693a0acb7ada5a1a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0988b7e7164574b3e3124180b0000000000000000000000000000000914202c38444f5a65707a848e969ea49c948c85807c79777671675b4e4235281c0f00000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000b17222e38424b515555555555555c69768390908376695c555555555555514b42382e22170b0000000000000000000000000003090f151b2024292c2f323436383939393938373634312f2b27231e19130d0700000000000000000000000000000000000000000000000000000000000004090d101416191b1c1d1e1e1e1e1e1d1b191714110d0904000000000000000000000000000000000000000000000000000000000000000000000000000000060e151b20242526262626262624211c160f06000000000000000000000000000000000000000000020a11181c20212222222222222222222222222222222222222222222222222222222222222222222222222222211f1c17110a010000000000020a11181c2021222222222222222221201c18120a02000000000004101c27323e49545e69727c858c93999ea2a5a7a6a4a2a1a1a1a1a09c979089817970697683909c9e9e978b7e7164574b3e3124180b000000000a15202b35404a545e67707981888f969ba0a4a7a9a9a7a6a6a7a9a8a5a29d98928b847c736a61584e443a2f24190e0300000000121f2c3845525f6b7885929fa2a2a295887b6f6255483c2f2215090013202c3946535f6c798693a0acafa295887b6f6255483c2f221509000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a222423211e19130b0300000013202c3946535f6c798693a0aca89b8e8174675b4e4135281b0e0208131f2b37434f5c6875828e9ba7b0a3968a7d7063564a3d3023170a0000000006101b242e37404850585e646a6e727577787979797876736f6b666059524a41382f251b10050000000000000000121f2b3844515d68717373737373737373737373737373737373737373737373726c6155493d3024170a0000040e17212a343d47505a636c768089929ca59e958b82786f655c52493f362d231a10070000000000000000010c17212b343b414546464646464644403a32291f1409000000000000000000000000010e1a27333f4b5864707c8895a1adafa3978b8074695d52473c32271d140b02000000000000000000000000030b141e28323c47525c68737e827c76716b65605a534b41362a1f13070013202c3946535f6c798693a0acb0a59b949393939393939393939393939393939393939393939393939393939393939393938b7e7164574b3e3124180b000000000013202c3946535f6c798693a0acb0a59b949393939393939393939393939393939393939393939393939393939393939393938b7e7164574b3e3124180b00000000000000000000000000000004101b27323e49545e68727b848c93989d9e97918c8886848275695c4f4236291c0f00000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c2013000f1b27333f4a545c616262626262626976839090837669626262626262615c544a3f33271b0f000000000000000000000000000000040a0f14181c202326282a2b2c2c2c2c2c2b292725221f1b17120d08020000000000000000000000000000000000000000000000000000000000050b1015191d20232527292a2b2b2b2b2a29282623201d1915100b06000000000000000000000000000000000000000000000000000000000000000000000000050f1820272c3032323232323232302d272018100600000000000000000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2c28221b130b01000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2c28231c140c02000000000915212c38444f5a65707a858e969ea4aaa9a39e9a97959494949596999c9b938b82796f7784909daaa4978a7d7164574a3e3124170b00000004101b26313c47515c667079828b939aa1a7aca8a39f9c9a999a9a9c9fa4a9a9a39d968e867c736a60564b41362b20150900000000121f2b3845515e6b7885929eabaea195887b6e6155483b2e2215080013202c3946535f6c798693a0acafa295887b6f6255483c2f221509000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d171715120d08010000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271b0e01020f1b2734404d596673808c99a5b0a3968a7d7063564a3d3023170a000000000009121c252e363e464d53595e6266686a6c6c6c6c6b6967635f5a554e4840382f261d130900000000000000000013202c3946535f6c7980808080808080808080808080808080808080808080807e7164574b3e3124180b000000050f18222b353e48515a646d77808a939da69d948a81776e645b51483f352c22190f060000000000000000050f19222a30353839393939393938342f2820170d0200000000000000000000000004111d2a36424f5b6774808c98a5b1ab9e93877b6f63584c41362b20160c020000000000000000000000000000020c16202b35404b56616d7776716b65605a544e4941392f24190e020013202c3946535f6c798693a0acada09489868686868686868686868686868686868686868686868686868686868686868686867e7164574b3e3124180b000000000013202c3946535f6c798693a0acada09489868686868686868686868686868686868686868686868686868686868686868686867e7164574b3e3124180b000000000000000000000000000000000b16212c37424c566069727a81888d91949d9c9895928f8275695c4f4236291c0f00000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c201300121e2b3744505b666e6f6f6f6f6f6f6f7683909083766f6f6f6f6f6f6f6e665b5044372b1e12000000000000000000000000000000000003080c101416191b1d1e1f2020201f1e1d1b1916130f0b07020000000000000000000000000000000000000000000000000000000000040a11161c2125292c2f323436373838383837363432302d2925211c17110b04000000000000000000000000000000000000000000000000000000000000000000020d17212a32383d3f3f3f3f3f3f3f3d38322a22180e030000000000000000000000000000000000000a141d262e34383b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b38332d251d13090000000a141d262e34383b3b3b3b3b3b3b3b3b3b39342e261e140a000000010d1925313d4954606b77828c96a0a8aea69e97928e8b89888787888a8c90959a948b81777784919eaaa4978a7d7063574a3d3024170a0000000a15212c38434e58636e78828b949da5acaaa39c9793908d8d8d8e9093989da4aba7a0988f857c72675d52473c31261a0f03000000121e2b3845515e6b7784919eabaea194887b6e6154483b2e2115080013202c3946535f6c798693a0ababa295887b6f6255483c2f221509000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110a08060200000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000c1925323e4b5865717e8b97a4b0a3968a7d7063564a3d3023170a0000000000000a131c242c343b42484d5256595c5e5f5f5f5f5e5d5a57534f49443d362e261d140b0100000000000000000013202c3946535f6c79868c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8b7e7164574b3e3124180b00000000061019232c363f48525b656e78818b949ea69c938980766d635a50473e342b21180e0500000000000000000710181f25292c2c2c2c2c2c2c2b28231d160e05000000000000000000000000000713202c3945525e6b7783909ca8b3a79a8e82766a5e52473b3024190e0400000000000000000000000000000000040e19242f3a45505b656b6b65605a544e49433d3730271d1308000013202c3946535f6c798693a0acaca0938679797979797979797979797979797979797979797979797979797979797979797979797064574a3e3124180b000000000013202c3946535f6c798693a0acaca0938679797979797979797979797979797979797979797979797979797979797979797979797064574a3e3124180b0000000000000000000000000000000005101b26303a444e57606870767c81848b97a3a4a19c8f8275695c4f4236291c0f00000000000000000000000000000000000c1925323f4c5865727e8c9386796c5f5346392c20130013202c3946535f6c787c7c7c7c7c7c7c7c839090837c7c7c7c7c7c7c7c786c5f5346392c2013000000000000000000000000000000000000000004070a0d0f1011121313131211100e0c09060300000000000000000000000000000000000000000000000000000000000000070f151c22272d3135393c3e414243444545444443413f3c3935312d28221c160f08010000000000000000000000000000000000000000000000000000000000000008131e29333c43494c4c4c4c4c4c4c49443c342a1f1409000000000000000000000000000000000006111c262f383f4548484848484848484848484848484848484848484848484848484848484848484848484848484847443f372f251b10040006111c262f383f454848484848484848484845403830261c1106000004111d2935414d5965717d88939ea8b0a69c948c86827e7c7b7a7a7b7d8084898f9693897f7784919eaba3968a7d7063574a3d3024170a0000030f1b26323d49545f6a75808a949da6afa8a098918b87838180808184878c9299a1aaaaa1978e84796f64594e42372b201408000000111e2b3844515e6b7784919eaaaea194877a6d6154473b2e2114080013202c3946535f6c7986939e9e9e9e95887b6f6255483c2f221509000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1724313d4a5763707d8a97a4b0a3968a7d7063564a3d3023170a000000000000010a121b222a30373c41464a4d4f515253535352504e4b47433e38322b241c140b020000000000000000000013202c3946535f6c79869399999999999999999999999999999999999999988b7e7164574b3e3124180b000000000007111a242d364049535c666f78828c959ea59b92897f756c625950463d332a20160c020000000000000000060d14191d1f2020202020201f1c18120c0400000000000000000000000000000916222f3b4854616d7a86939facafa3978a7e72665a4e42362a1f130800000000000000000000000000000000000007121d28343f49535b5f5f5a544e49433d38322c251e150b01000013202c3946535f6c798693a0acaca09386796d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6c685e53473b2f231609000000000013202c3946535f6c798693a0acaca09386796d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6c685e53473b2f2316090000000000000000000000000000000005101b25303a444e5760686f767c81858b97a3a29f9c8f8275695c4f4236291c0f00000000000000000000000000000002070c1925323f4c5865727e8c9386796c5f5346392c20130013202c3946535f6c798689898989898989899292898989898989898986796c5f5346392c20130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a111920272d33383d4145484b4d4f5051515151514f4e4b4945423d38332d27211a130b030000000000000000000000000000000000000000000000000000000000010d1925303b454e5458595959595958554e463c31261a0e02000000000000000000000000000000000b17222d38424a5154555555555555555555555555555555555555555555555555555555555555555555555555555554504941372c21150a000b17222d38424a5154555555555555555554514a42382d22170b00000814202d3945515d6a76828d99a5b0a89e948a827b75726f6e6d6e6f7174787e848c9491867b85929eaba3968a7d7063564a3d3023170a00000814202c37434e5a65707b87919ca6afa89f968e87807b7774737374777b81888f98a1aba9a0968b80756a5f53483c3024190d010000111e2a3744515d6a7784919eaaada094877a6d6154473a2e2114070013202c3946535f6c7986919191919191887b6f6255483c2f221509000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a00000000000000000910181f252b31363a3d404344464646464543413e3b37322d27211a120a02000000000000000000000013202c3946535f6c79869292929292929292949ca69e9592929292929292928b7e7164574b3e3124180b00000000000008121b242e37414a545d677079838c969fa49b91887e756b62584f453c32281e130800000000000000000002080d101213131313131312100c07010000000000000000000000000000000b1825313e4a5763707c8996a2aeaca094877b6e62564a3e32261a0e02000000000000000000000000000000000000010c17222d3841494f52524e49433d38322c26211b140c0300000013202c3946535f6c798693a0acaca09386796c6060606060606060606060606060606060606060606060606060606060606060605d564c42372b1f1307000000000013202c3946535f6c798693a0acaca09386796c6060606060606060606060606060606060606060606060606060606060606060605d564c42372b1f1307000000000000000000000000000000000b16212c37424c566069727a81888d91959d9b9693908e8275695c4f4236291c0f0000000000000000000000000001080e13161925323f4c5865727e8c9386796c5f5346392c20130013202c3946535f6c798693949494949494949999949494949494949386796c5f5346392c20130000000000000000000000000000000000000000000205080b0d0f101112121211100f0e0c090603000000000000000000000000000000000000000000000000000000020b131b232b32383e44494d5155575a5b5d5e5e5e5e5d5c5a5855524e49443f39322c241d150d040000000000000000000000000000000000000000000000000000000004111d2935414c575f6565656565656560584d42362a1e1205000000000000000000000000000000000f1b27333f4a545c616161616161616161616161616161616161616161616161616161616161616161616161616161605b53493d32261a0e000f1b27333f4a545c616161616161616161615c544a3f33281b0f03000a1723303c4855616d7a86929eaaaea2978c8278706965636161616264686d737a828a948d8285929faca3968a7d7063564a3d3023170a00000c1824303c48545f6b76828d98a3adaaa0968d847c756f6a676666686b70767d868f99a3aea79d92877b7064594d4135291d11050000111d2a3744505d6a7784909daaada094877a6d6053473a2d2014070013202c3946535f6c7984848484848484847b6f6255483c2f221509000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000060d141a20252a2e3134363839393939383735322f2b27211c160f080000000000000000000000000013202c3946535f6c798686868686868686868a96a2988c8686868686868686867e7164574b3e3124180b0000000000000009121c252f38424b555e67717a848d97a0a39a90877d746a61574e443a3024190d010000000000000000000000000000000000000000000000000000000000000000000000000000000d1a2633404c5966727e8b98a4b1aa9d9184786b5f53463a2e211509000000000000000000000000000000000000000006111c262f373e434645433d38322c26211b151009020000000013202c3946535f6c798693a0acaca09386796c5f5353535353535353535353535353535353535353535353535353535353535353514b443b30251a0f03000000000013202c3946535f6c798693a0acaca09386796c5f5353535353535353535353535353535353535353535353535353535353535353514b443b30251a0f0300000000000000000000000000000004101c27323e49535e68727b848c93999d9c958f8a8684828175695c4f4236291c0f000000000000000000000000020b12191f232526323f4c5865727e8c9386796c5f5346392c20130013202c3946535f6c798687878787878787889191888787878787878786796c5f5346392c201300000000000000000000000000000000000001050a0e1115171a1b1d1e1e1e1e1e1d1c1a1816130f0c07030000000000000000000000000000000000000000000000010b141d252d353c434a4f55595d616466686a6a6b6b6b6a696764615e5a55504a443d362f271f160e050000000000000000000000000000000000000000000000000000000613202c3945515d69717272727272716a5f53463a2d21140700000000000000000000000000000000121e2b37434f5b666d6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6d655a4e4236291d1000121e2b37434f5b666d6e6e6e6e6e6e6e6e6d665b5044372b1f1205000d1926323f4b5864717d8a96a2aea99d91867a70665e595655545455585c61687078828b938a8a94a0aca3968a7d7063564a3d3023170a0004101c2835414d5964707c88939eaaaea3998e857b726a635e5b595a5b5f646b747d87919ca7aea3988c8175695d5145392d2114080000101d2a3743505d697683909daaada09386796d6053463a2d20130700131f2c3945525e6b757777777777777777766d6154483b2e221508000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0000000000000000000003090f14191e2125272a2b2c2c2c2c2b2a2826231f1b16100b040000000000000000000000000000131f2c3946525f6b7679797979797979797b8895a2978a7d7979797979797979786f63574a3e3124170b00000000000000000a131d263039434c555f68727b858e98a1a2998f867c736960564c4135291d11050000000000000000000003060809090909090908060200000000000000000000000000000000000f1b2835414e5b6774818d9aa7b3a79b8e8275695c5043372a1e12050000000000000000000000000000000000000000000a141d252d3337393936322c26211b15100a0400000000000013202c3946535f6c798693a0acaca09386796c5f534646464646464646464646464646464646464646464646464646464646464645403a32291f140900000000000013202c3946535f6c798693a0acaca09386796c5f534646464646464646464646464646464646464646464646464646464646464645403a32291f1409000000000000000000000000000000000915202c38444f5a65707a848d969da49b928a847e7a77757470665a4e4135281b0f0000000000000000000000020b141d242a2f3232323f4c5865727e8c9386796c5f5346392c20130013202c3946525f6b777a7a7a7a7a7a7a7a839090837a7a7a7a7a7a7a7a776b5f5246392c20130000000000000000000000000000000001070c11161a1e21242628292b2b2b2b2b2a282725221f1c18130f090400000000000000000000000000000000000000000009131d262f373f474e555b60656a6d7073757677787877777573716e6a65615b554f484139312820170e0400000000000000000000000000000000000000000000000000050a14202d3a4753606d7a7f7f7f7f7f7b6e6155483b2e2215090400000000000000000000000000000013202c3946525f6c777b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b766a5e5145382b1e120013202c3946525f6c777b7b7b7b7b7b7b7b786c5f5346392d201306000e1b2834414e5a6773808c99a5b1a5988c8174695e544d4a484747494c50565e667079848e95959ba5b0a3968a7d7063564a3d3023170a000814202c3945515d6975818d98a4b0a89d92877c72696058524e4d4d4f535a626b75808b96a1ada99d9186796d6155493d3024180b0000101d2a3643505d697683909ca9aca09386796c5f5346392d20130600111d2a36424e59636a6b6b6b6b6b6b6b6b6a655b5044382c201307000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a00000000000000000000000003090d1215181b1d1e1f2020201f1d1c1916130f0a0500000000000000000000000000000000111e2a36434f5a646b6c6c6c6c6c6c6c6e7b8895a2978a7d716c6c6c6c6c6c6c6c675e53473b2f2216090000000000000000010b141e27313a434d566069737c868f99a0a0988e857b72685d5245392d2013070000000000000000050b0f131515151515151514120e0903000000000000000000000000000000101d293643505c6975828f9ca8b2a6998c8073665a4d4134281b0f02000000000000000000000000000000000000000000020b131b22272a2c2c2a26211b15100a04000000000000000013202c3946535f6c798693a0acaca09386796c5f53463a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a38342f2820170d0200000000000013202c3946535f6c798693a0acaca09386796c5f53463a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a38342f2820170d02000000000000000000000000000000000d1925313d4954606b76818c969fa79c92898079726e6a6867655e54493e3225190d00000000000000000000020b141d262e363b3e3f3e3f4c5865727e8c9386796c5f5346392c201300111e2a37434f5a656c6d6d6d6d6d6d6d7683909083766d6d6d6d6d6d6d6c655a4f43372a1e11000000000000000000000000000000060c12181d22262a2d303335363738383837363533312e2b28241f1a150f090200000000000000000000000000000000000007111b252f384149515960666c71767a7d808283848585848482807d7a76716c66605a524b433a322920160d0300000000000000000000000000000000000000000000050b11161b202d3a4753606d7a878c8c8c887b6e6155483b2e221a150f09030000000000000000000000000013202c3946535f6c798688888888888888888888888888888888888888888888888888888888888888888888888885786b5e5145382b1e120013202c3946535f6c798688888888888886796d6053463a2d20130700101d2936434f5c6975828f9ba8aea195897c7064584c423d3b3a3b3c3f454c545e68727d88949fa6adb0a3968a7d7063564a3d3023170a000b1723303c4855616d7985919da9afa3978c81756b60574e4742404043485059636e7985919da9aea2968a7d7165594c4033271a0e0200101c2936434f5c697683909ca9ac9f9286796c5f5346392c201306000e1a26323d4751595d5e5e5e5e5e5e5e5e5e5a53493f34281c1004000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a00000000000000000000000000000105090c0e10121313131312110f0d0a07030000000000000000000000000000000000000e1a26323d48525a5e5f5f5f5f5f5f616e7b8895a2978a7d71645f5f5f5f5f5f5f5c554c42362b1f1307000000000000000000020c151f28313b444e57616a747d8790939393938d847a6e6154473b2e211408000000000000000810161b1f22222222222222211e1a150e060000000000000000000000000000111e2b3744515d6a7784909daab1a4978b7e7165584b3f3225190c0000000000000000000000000000000000000000000000010910161b1e201f1e1a15100a040000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2c28241d160e050000000000000013202c3946535f6c798693a0acaca09386796c5f5346392d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2c28241d160e050000000000000000000000000000000003101c2935414d5965717d88939ea8a1958b80766e67625e5c5b59544c42382d211509000000000000000000030c141d262f3840474b4c4a454c5865727e8c9386796c5f5346392c2013000f1b27333e49535b606060606060606976839090837669606060606060605b53493e33271b0f00000000000000000000000000020a11171e23292e32363a3d3f414344454545444342403e3b3834302b26201a140d0600000000000000000000000000000000040e19232d37414a535b636a71777d8286898c8e9091919291908f8c8a86827d78726b645d554c443b32281f150b0100000000000000000000000000000000000000020910161c22272b2f3a4753606d7a87949995887b6e6155483b2f2a26201b150e0700000000000000000000000013202c3946535f6c798693959595959595959595959595959595959595959595959595959595959595959595959285786b5e5145382b1e120013202c3946535f6c798693959595959386796d6053463a2d20130700111e2b3744515d6a7784909daaac9f9286796d6054483c312f2e2e30343a424c56606b77828e9aa6b2b0a3968a7d7063564a3d3023170a000e1a26333f4c5864717d8995a2aeaa9e92867b6f64594f453c363334373e47525d6874818c99a5b1a69a8d8174685b4f4336291d1004000f1c2936424f5c6975828f9ca9ac9f9286796c5f5246392c1f1306000915202b363f474d515151515151515151514e4841372d22170c00000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a16212c3640484e52525252525255616e7b8895a2978a7d716457525252525252504b433a30251a0e0200000000000000000000030d161f29323c454f58626b757e868686868686867b6e6154483b2e21150800000000000009121a21272c2e2f2f2f2f2f2f2e2b262018100600000000000000000000000000121f2c3845525e6b7885919eabb0a396897d7063574a3d3124170a00000000000000000000000000000000000000000000000000050a0f111313110e0a0400000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c202020202020202020202020202020202020202020202020202020201f1c18120c04000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c202020202020202020202020202020202020202020202020202020201f1c18120c04000000000000000000000000000000000006131f2c3844515d6975828d99a4a79b8f84796e655c56524f4e4c48423a31261b10050000000000000000030c151e262f38414a52575956504c5865727e8c9386796c5f5346392c2013000a16212d3741494f5353535353535c69768390908376695c5353535353534f4941372d21160a000000000000000000000000050c141b22292f34393e4246494c4e505151515151504e4d4a4744403c37312c251f1810090100000000000000000000000000000a15202b353f49535c656d757c83898e9296999b9c9e9e9e9e9d9b9996928e89837d766e675e564d443a31271d1309000000000000000000000000000000000000050d141b21282d33373c3f4753606d7a8794a095887b6e6155483f3b36312c262019120a020000000000000000000013202c3946535f6c798693a0a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a29e9285786b5e5145382b1e120013202c3946535f6c798693a0a2a2a09386796d6053463a2d20130700121f2c3845525f6b7885929eabaa9d9084776b5e5145382c2221212328303a444f5a66727d8a96a2aeb0a3968a7d7063564a3d3023170a00101d2936424f5b6774818d99a0a3a59a8e82766a5e53473d332a27272c35404c5864707c8995a2aea99d9084776a5e5145382c1f1206000f1c2935424f5b6875828f9ca8ac9f9285786b5f5245382c1f12050008141f29343d444a4d4e4e4e4e4e4e4e4e4e4b463e352b21160a00000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000000000000000000206090b0d0f10101010100f0d0b090603000000000000000000000000000000000004101a242e363d4245464646464855616e7b8895a2978a7d7164574a4646464645443f3931281e1409000000000000000000000000040d17202a333d465059626c7579797979797979776d6054473a2e211408000000000007111b242c33383b3c3c3c3c3c3c3a37312a22180f04000000000000000000000000131f2c3946525f6c7985929facafa295887c6f6255493c2f231609000000000000000000000000000000000000000000000000000000020506060502000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013131313131313131313131313131313131313131313131313131312100c070100000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013131313131313131313131313131313131313131313131313131312100c07010000000000000000000000000000000000000815212e3b4754606d7985929eaaa3978b7e73685d534b464341403d3730281f150a0000000000000000030c151e273039424a535c6365625a515865727e8c9386796c5f5346392c20130005101b252f373e4446474747474f5c69768390908376695c4f4747474746443e372f251b10050000000000000000000000060e171e262d343a40454a4e5256585b5c5d5e5e5e5d5d5b595754504c47423d373029221b130a0200000000000000000000000006111c27323c47515b656e777f878e94999ea2a5a7a5a3a2a2a2a3a6a5a29e9a948e88807970685f564c43392f251a100500000000000000000000000000000000070f171e262c33393e43484c4f53606d7a8794a095887b6e61554f4b47423d37312a231c140c0400000000000000000013202c3946535f6c798693a0acaeaea9a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a59e9285786b5e5145382b1e120013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946525f6c7986929faca89c8f8276695c5043362a1d1415171e28333e4955616d7986929eabb0a3968a7d7063564a3d3023170a00121f2b3845515e6a77839092949698968a7e7265594d42362b211a1a24303c4854616d7a86939facac9f9286796c6053473a2d211407000f1c2835424f5b6875828e9ba8ab9e9285786b5e5245382b1f1205000d1925303b454f565a5b5b5b5b5b5b5b5b5a5750473d32271b0f03000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0000000000000000000000000001060a0e1215181a1b1c1d1d1d1c1b1a1815120f0b070200000000000000000000000000000008121c242c3236383939393b4855616e7b8895a2978a7d7164574a3e3939393937342e271f160c0200000000000000000000000000050e18212b343e47505a636b6c6c6c6c6c6c6c6c655b5044382c1f130600000000030e19232d363e444748484848484847423c342a20160b00000000000000000000000013202c3946535f6c7986939facaea295887b6e6155483b2f221508000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130707070707070707070707070707070707070707070707070707060606040100000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2013070707070707070707070707070707070707070707070707070706060604010000000000000000000000000000000000000a1623303c4956626f7b8895a1aca093877a6e62564b413a363433312c261e160d0300000000000000030c151e273039424b545d656e726c635a5865727e8c9386796c5f5346392c2013000009131d252d33373a3a3a3a434f5c69768390908376695c4f433a3a3a3a37332d251d13090000000000000000000000060f18202830383f454b51565a5e626567696a6b6b6b6a69686663605c58534e48423b342d251c140b0200000000000000000000000b17222d38434e59636d76808991999fa5aaa49f9b989695959697999ca0a5a5a099928b837a71685e554b41362c21170c010000000000000000000000000000071019212930373e444a4f54585b5e616d7a8794a095887b6e615e5b57534e48423c352e261e160d04000000000000000013202c3946535f6c798693a0acb3a89f99989898989898989898989898989898989898989898989898989898989285786b5e5145382b1e120013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca89b8e8275685b4f4235281c0f080c16212d3945515e6a76838f9ca8b0a3968a7d7063564a3d3023170a0013202c3946535f6c7981838587898c8e877a6e6255493d31251a0f13202c3945525e6b7884919eaaada194877b6e6155483b2f221508000f1b2835424e5b6875828e9ba8ab9e9184786b5e5145382b1e120500101d2935414d57616767676767676767676762594f43372b1f1306000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000000000070c12161b1e22242628292a2a2a29282624221f1b17120d080200000000000000000000000000000a121a21262a2c2c2c2e3b4855616e7b8895a2978a7d7164574a3e312c2c2c2b28231d150d04000000000000000000000000000000060f19222c353e4851595e5f5f5f5f5f5f5f5f5b534a3f34281c1004000000000915202a353f484f54555555555555534d463c32271c1004000000000000000000000013202c3946535f6c798693a0acaea194887b6e6155483b2e221508000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20131313131313131313131313131313131313131313131313131313131312110d09040000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20131313131313131313131313131313131313131313131313131313131312110d0904000000000000000000000000000000000a1724313d4a5764707d8a97a3aa9d9184786b5f52463a2f2a282724201b140c0400000000000000030c151e273039424b545d666e777e756c635a65727e8c9386796c5f5346392c201300000b151f282f363a3d3d3d3d434f5c69768390908376695c4f433d3d3d3d3a362f281f150b00000000000000000000060f18212a323a424950565c62666b6e71747577777878777674726f6c68645f59534d463e372e261d140b0100000000000000000005111c28333f4a55606a757f89929ba3aaa59f98938f8c8a8988898a8d90959aa0a7a49c958c837a70675d53483e33281d120700000000000000000000000000071019222b333b42494f555b6064686b6d6f7a8794a095887b6f6d6a67635f59544d47403830281f160d030000000000000013202c3946535f6c798693a0acaea2968d8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b85786b5e5145382b1e120013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675b4e4134281b0e0105111d2935424e5b6774818d9aa6b0a3968a7d7063564a3d3023170a00121f2b3845515d68717477797b7d7f8183786b5f52463a2d211509111d2a3743505d697683909ca9afa295897c6f6255493c2f231609000e1b2834414e5b6774818e9ba8aa9e9184776b5e5144382b1e110500121f2c3845515d69727474747474747474736b6054473b2e211508000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a00000000000000000000040b12181d22272b2e31333536363636363533312e2b27231e19130d060000000000000000000000000000080f151a1d1f1f222e3b4855616e7b8895a2978a7d7164574a3e31241f1f1e1b17120b03000000000000000000000000000000000007101a232c363f484e5253535353535353524f4941382d23170c00000000040f1b26313c47515a606262626262625f584e44382d201408000000000000000000000013202c3946535f6c798693a0acaea195887b6e6155483b2e221508000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1d1a150f0700000000000013202c3946535f6c798693a0acaca09386796c5f5346392c201f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1d1a150f070000000000000000000000000000000b1724313e4a5764717d8a97a4a89c8f8276695c5043372a1e1b1a18140f090200000000000000040c151e273039424b545d666f7881877e756c6265727e8c9386796c5f5346392c20130006121d27313a41474a4a4a4a4a4f5c69768390908376695c4f4a4a4a4a4a47413a31271d12060000000000000000040e18212a333c444c545b62686d72777a7e8182848485848483817e7c7874706a655e57504840382f261d13090000000000000000000a16222d3944505b66717c87919ba4ada49b948d8783807d7c7b7c7d8184898f959da5a69e958c83796f645a4f453a2f24190d020000000000000000000000060f19222b343d454c545a61666b7074777a7c7e8794a095887e7c7a77736f6a655f58514a423a31281f150c0200000000000013202c3946535f6c798693a0acaca093867e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e786b5e5145382b1e120013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01010d1a26333f4c5965727e8b98a5b0a3968a7d7063564a3d3023170a00101c2935414c576066686a6c6e7072747673695d5044372a1e1105101c2936434f5c6975828f9ca9b0a396897c6f6356493d3023160a000e1b2734414e5a6774818e9aa7aa9e9184776a5d5144372a1e11040013202c3946535f6c7981818181818181817b6f6255483c2f221509000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000070f161d23292e33373a3d3f41424343434341403d3b37332f2a241e1710090100000000000000000000000000040a0e111215222e3b4855616e7b8895a2978a7d7164574a3e31241713120f0b06000000000000000000000000000000000000000008111a242d363d42454646464646464646433e382f261c1106000000000915202c37424d58636c6f6f6f6f6f6f6a6055493d3024170b000000000000000000000013202c3946535f6c7986929facaea295887b6f6255483c2f221509000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c292520191109000000000013202c3946535f6c798693a0acaca09386796c5f5346392c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c29252019110900000000000000000000000000000b1724313e4a5764717d8a97a4a89b8e8275685b4e4235281c0f0d0b08040000000000000000040d161e273039424b545d666f78818a90877e746765727e8c9386796c5f5346392c2013000b17232e39434c525657575757575c69768390908376695c575757575756524c43392e23170b00000000000000020c16202a333c454e565e666d73797e83878a8d8f90919291918f8e8b8885817b767069625a524a41382f251b110700000000000000030e1a26323e4a55616c77838e98a3ada49b9289827c7773706f6f6f7174787d848b939ba4a79e958b81766c61564b40352a1e130800000000000000000000030e18212b343d464f575e656c72777c808486898a8d97a2988e8b898683807b76706a635c544c433a31271e140a00000000000013202c3946535f6c798693a0acaca093867971717171717171717171717171717171717171717171717171717171716f675b4f43372a1d110013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000b1825313e4b5764717d8a97a4b0a3968a7d7063564a3d3023170a000c1824303a454e55595b5d5f626466686a6961574c4034281c0f030f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000e1a2734414d5a6774818d9aa7aa9d9084776a5d5044372a1d11040013202c3946535f6c79868e8e8e8e8e8e887b6f6255483c2f221509000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000009111921282e343a3f43474a4c4e4f5050504f4e4c4a47443f3b353029221b130b02000000000000000000000000000000000815222e3b4855616e7b8895a2978a7d7164574a3e3124170b0000000000000000000000000000000000000000000000000008121b242b323639393939393939393937332d261d140a00000000020e1a26313d48545f6a757b7b7b7b7b7b7165584b3f3225180c0000000000000000000000121f2c3945525f6b7885929fabafa296897c6f6356493c3023160a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f534639393939393939393939393939393939393939393939393939393939393939393836312b231b11070000000013202c3946535f6c798693a0acaca09386796c5f534639393939393939393939393939393939393939393939393939393939393939393836312b231b1107000000000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e0100000000000000000000030d161f283039424b545d666f78818a938c847b726665727e8c9386796c5f5346392c2013000f1c28343f4b555d636363636363636976839090837669636363636363635d554b3f34281c0f0000000000000009141e28323c454e57606870777e848a8f9397999c9d9e9e9e9d9c9a9895918c87817b746c645c534a41372d23190f0400000000000007131f2b37434f5a66727d89949faaa69c92898077716b676462626365686c72798189929ba5a79d92887d73685d52463b3024190d010000000000000000000b151f2a333d464f58616970777d83888c90939597999fa8a099979593908c87827b756d665e554c433930261b1106000000000013202c3946535f6c798693a0acaca09386796c65656565656565656565656565656565656565656565656565656565645e554a3f33271b0e0013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1724303d4a5763707d8a96a3b0a3968a7d7063564a3d3023170a0008131e29333c44494d4f51535557595b5d5c574f463b3024180c000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000d1a2734404d5a6773818d9aa6aa9d9083766a5d5043372a1d11040013202c3946535f6c7986939b9b9b9b95887b6f6255483c2f221509000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0000000000000009121b232b323940454a4f5356595b5c5d5d5d5c5b595653504b46413b342d251d140b020000000000000000000000000000010815222e3b4855616e7b8895a2978a7d7164574a3e3124170b000000000000000000000000000000000000000000000000000009121a21262a2c2c2c2c2c2c2c2c2c2b27221b140b020000000007131f2b37424e5965707b86888888857a7064574b3e3225180b0000000000000000000000121e2b3845515e6b7784919eaab0a3968a7d7064574a3e3124180b000000000000000000000000000000000000000000000000000306080908050200000000000000000000000000000013202c3946535f6c798693a0acaca09386796c5f5346464646464646464646464646464646464646464646464646464646464646464645423c352d23190e0300000013202c3946535f6c798693a0acaca09386796c5f5346464646464646464646464646464646464646464646464646464646464646464645423c352d23190e030000000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000000b151f28313a424b545d666f78818a938c837a72696065727e8c9386796c5f5346392c201300121e2b3844505c676f70707070707070768390908376707070707070706f675c5044382b1e1200000000000006101b26303a444e576169727a828990969b9fa3a6a5a3a2a2a2a3a5a7a4a19d98928c867e766e655c53493f352b20160b0000000000000a17232f3b47535f6b77838e9aa5aa9f958a80766d665f5a57565556585c61676f778089939da8a49a8f84796e63574c41352a1e1206000000000000000007121c27313b454f58616a737a82888e94989c9fa2a4a5a6a6a6a6a4a29f9c97928d86807870675e554b41372d23180d020000000013202c3946535f6c798693a0acaca09386796c5f58585858585858585858585858585858585858585858585858585857534c43392e22170b0013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a00020d17212a32383d40424446484a4d4f51504c463d34291e1307000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000d1a2633404d596673808d9aa6a99c908376695d5043362a1d10030013202c3946535f6c798693a0a8a8a295887b6f6255483c2f221509000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110400000000000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a00000000000008121b242d353d444b51565b5f6265676969696969676563605c57524c453e372f261d140b010000000000000000000000050a0d0f15222e3b4855616e7b8895a2978a7d7164574a3e3124170b000000000000000000000000000000000000000000000000000000080f151a1e1f20202020202020201e1b16110a0200000000000b17232f3b47535f6a76818d9594897e73685e53473b2f23160a0000000000000000000000111d2a3744505d6a7683909ca9b1a4988b7e7265584c3f3326190d0000000000000000000000000000000000000000000000050b0f13151514120e0a060200000000000000000000000013202c3946535f6c798693a0acaca09386796c5f53525252525252525252525252525252525252525252525252525252525252525252524e473f352b20140800000013202c3946535f6c798693a0acaca09386796c5f53525252525252525252525252525252525252525252525252525252525252525252524e473f352b2014080000000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e0100000000000000000006111c27313a434c545d666f78818a938c837a7168605e65727e8c9386796c5f5346392c20130013202c3946535f6c787d7d7d7d7d7d7d7d839090837d7d7d7d7d7d7d7d786c5f5346392c20130000000000010c17222d37424c566069737b848c949ba1a6a5a09c999795959697999ca0a5a9a49e97908880776e655b51473d32271c110600000000000e1a26333f4b57636f7b87939fa0a2998e83786e645b544e4b4948494c50565d656e77818b96a1aba1968b8074695d52463a2f23170b00000000000000020d18232e39434d57616a737c858c939a9fa4a7a39f9c9a9999999b9da0a4a8a39e98918a827970675d53493f34291f13080000000013202c3946535f6c798693a0acaca09386796c5f534b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b47413a31271c11060013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0000050f1820272d313336383a3c3e40424443403b342b22180d02000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000d1a2633404c596673808c99a6a99c908376695c4f4336291c10030013202c3946535f6c798693a0acafa295887b6f6255483c2f221509000000000001101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d110d0b070200000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000006101a242d363f474e565c62676b6f7274757676767574726f6c68635d57504941382f261d1309000000000000000000030a11161a1c1c222e3b4855616e7b8895a2978a7d7164574a3e3124170b00000000000000000000000000000000000000000000000000000000040a0e11131313131313131313110f0b05000000000000030f1b2734404c58646f7b87929a8e83786d62574c42372b1f13070000000000000000000000101c2936424f5c6875828e9ba8b3a6998d8074675a4e4135281c0f030000000000000000000000000000000000000000000810161b1f2122211e1a16120e0a060200000000000000000013202c3946535f6c798693a0acaca09386796c5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5e5951473c3125190d00000013202c3946535f6c798693a0acaca09386796c5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5e5951473c3125190d0000000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e010000000000000000000b17232e39434c555e666f78818a948b8279716b6b6b6b6b727e8c9386796c5f5346392c20130013202c3946535f6c79868a8a8a8a8a8a8a8b93938b8a8a8a8a8a8a8a86796c5f5346392c2013000000000007131e29343e49545e68727b858e969ea5a7a09a94908c8a8988898a8c9094999fa6a9a29a928980776d63594e44392e23170c0100000000101c2936424f5b6773808c9092949694887d71665c524a433e3c3c3d3f444b535c656f7a848f9aa5a79c91857a6e63574b3f33271b0f0300000000000008131f2a35404a555f69737c868e969ea5a9a29c9793908d8c8c8c8e9094989da4a9a39c948b82796f655b51463b3025190e0200000013202c3946535f6c798693a0acaca09386796c5f53463e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3b3630281f150b000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000060e161c212527292b2d2f31333637373430292219100600000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000d192633404c5966727f8c99a6a99c8f8275695c4f4236291c10030013202c3946535f6c798693a0acafa295887b6f6255483c2f22150900000000050c121c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1b1a17130d06000000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a00000000030e18222c363f48515960676d73777b7e818283838382817e7c78746e68625a534a41382e251a100600000000000000040d151c22262829282e3b4855616e7b8895a2978a7d7164574a3e3124170b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121f2b3744505c6874808c9894897d72665b50453a30251a0f0300000000000000000000000e1b2734414d5a6773808d99a6b2a89b8f8276695d5044372b1f1206000000000000000000000000000000000000000009121a21272c2e2f2e2a26221e1a16120e0a060100000000000013202c3946535f6c798693a0acaca09386796c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6a63584d4135291c1003000013202c3946535f6c798693a0acaca09386796c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6a63584d4135291c100300000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e010000000000000000000f1b27333f4a555e677078828b948b827978787878787878787e8c9386796c5f5346392c20130013202c3946535f6c798693939393939393939393939393939393939386796c5f5346392c201300000000020d19242f3a45505b65707a848d97a0a8a49c958e8984807d7c7b7c7d8084888e949ca3aca49b92897f756b60554a3f34291d120600000000101d2a3643505d69768081838587898b83776c60554a403832302f303339414a535d68737e8994a0aba2968b7f73675c5044382c2014070000000000020e1925303b46515c67717b858f98a0a8a79e97918b878381807f808184888c9299a0a8a69d948b81776d62574c41362b1f130800000013202c3946535f6c798693a0acaca09386796c5f534639323232323232323232323232323232323232323232323232312f2b251e160d03000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a00000000040b1015181a1c1e21232527292a2a28241e1810070000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000c1926323f4c5965727f8c99a5a89c8f8275685c4f4236291c0f030013202c3946535f6c798693a0a7a7a295887b6f6255483c2f221509000000070f171d222936434f5c697683909ca9aa9d9084776a5d5044372a282826231e1811090000000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000a151f2a343e48515a636b72787e83878b8d8f9090908f8d8b8884807a736c655c534a40362c22170c010000000000030d161f272d32353635313b4855616e7b8895a2978a7d7164574a3e3124170b000000000000000000000000000001070b0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0e0b07010000000000000915222e3b4753606c7884909b8f84786c61554a3f34291e14090000000000000000000000000c1926323f4b5865717e8a97a3b0aa9e9185786c6053473b2e22160a0000000000000000000000000000000000000007111b242c33383b3c3a36322e2a26221e1a16120c05000000000013202c3946535f6c798693a0acaca093867979797979797979797979797979797979797979797979797979797979797979797979797975695d5144372b1e1104000013202c3946535f6c798693a0acaca093867979797979797979797979797979797979797979797979797979797979797979797979797975695d5144372b1e110400000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000111e2b3744505c677079828b94958a85858585858585858585858d9386796c5f5346392c20130013202c3946535f6c798686868686868686868686868686868686868686796c5f5346392c20130000000007131e2a35404c57626c77828c969fa9a49b938b837d7874716f6f6f7174787d838a929aa3aca49b91877c72675c50453a2e23170b000000000f1c2935424e5a656f737577797b7d7e7f73675b4f44392e26232224282f38414c56616c78838f9aa6a79c9084786c6054483c3024170b000000000007131f2a36414c58636e78838d97a1aaa69d958d86807a777473727375787b81878e969fa8a69d93897e74695e53473c3024180c00000013202c3946535f6c798693a0acaca09386796c5f5346392c252525252525252525252525252525252525252525252525231f1a130c0400000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a00000000000005090c0e10121416181a1c1e1d1b18130d06000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000c1925323f4c5865727e8c98a5a89b8f8275685b4f4235281c0f020013202c3946535f6c7986939a9a9a9a95887b6f6255483c2f221509000006101921282e3236434f5c697683909ca9aa9d9084776a5d504437353535332f2a231b120800000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a00000005101b26313c46505a636c757c848a8f94979a9b9b9b9b9c9a9894908b857e766e655c52483e34291e130800000000000a151f2831383e4243413d3b4855616e7b8895a2978a7d7164574a3e3124170b00000000000000000000000000060d12171a1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1a17120d0600000000000b1824313d4a56636f7b8894978b7f73675b5044392d22170c020000000000000000000000000a1724303d4956626f7b8894a1adada194887b6f63574b3e32261b0f030000000000000000000000000000000000020e19232d363e44474846433e3a36322e2a26221d160f060000000013202c3946535f6c798693a0acada0948986868686868686868686868686868686868686868686868686868686868686868686868684776b5e5144382b1e1105000013202c3946535f6c798693a0acada0948986868686868686868686868686868686868686868686868686868686868686868686868684776b5e5144382b1e110500000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000121f2c3945525f6c78828b949d9b949292929292929292929292959386796c5f5346392c201300131f2c3946525f6b767979797979797979797979797979797979797979766b5f5246392c1f13000000010c18242f3b46525d68737e89939ea8a59b92898179726c676462626364676c71788088919ba4ada3998e83786d62564b3f33271c10040000000d1926323e49545d6366686a6c6e7072736d63574b3f332a2b2b2a2a2927303a45505b66727e8a95a1aca094887c7064584c4034271b0f02000000000c18242f3b47525e69747f8a959fa9a89e948b837b746e6a68666566686b70757c848d96a0aba59b90857a6f64584c4135291d1105000013202c3946535f6c798693a0acaca09386796c5f5346392c20181818181818181818181818181818181818181818181816130e09020000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a00000000000000000000030507090c0e1011110f0c070200000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000c1825323e4b5865717e8b98a5a89b8e8275685b4e4235281b0f020013202c3946535f6c79868d8d8d8d8d8d887b6f6255483c2f22150900020d18222b333a3f41434f5c697683909ca9aa9d9084776a5d5044424242413f3b342d241a0f05000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0000000b16222d38434d58626c757e878e959b9c9793908e8e8e9092969b9c96908980776e645a50453a2f24190d0200000004101b26313a434a4e4f4e49424855616e7b8895a2978a7d7164574a3e3124170b0000000000000000000000000710171e2327292929292929292929292929292929292929292929292927231e171007000000000d1a2733404c5965727e8b9794877b6f63574b423b32281e13080000000000000000000000000815212e3a4753606c7985919eaab0a4988b7f73675b4f43372b201409000000000000000000000000000000000008131f2a353f484f5455534f4b47433e3b37332e2821180f0500000013202c3946535f6c798693a0acb0a59b9492929292929292929292929292929292929292929292929292929292929292929292929184776b5e5144382b1e1105000013202c3946535f6c798693a0acb0a59b9492929292929292929292929292929292929292929292929292929292929292929292929184776b5e5144382b1e110500000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000121f2b3845515e69747d868f98988e8b8b8b8b8b8b8b8b8b8b8b8b8b86796c5f5346392c201300111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b645a4f43372a1e1100000005111d2935404c57636e7985909ba5a89d938980776f67605b58565556585b60666e767f89939da8aaa0958a7e73675b5044382c2014080000000915212d38424b52575a5b5d5f61636567635b51463a353737383737353432333f4a56616d7985919da9a5998d8174685c5043372b1e120600000004101c2834404c58636f7a86919ca6aca1968c82797169635e5b59595a5c5f646b727b848e99a4ada2978c8074695d5145392d211508000013202c3946535f6c798693a0acaca09386796c5f5346392c20130b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0a070300000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000000000000000000000000000000000000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000b1825323e4b5864717e8b98a4a89b8e8174675b4e4134281b0e020013202c3946535f6c7981818181818181817b6f6255483c2f2215090008141f2a343d454b4e4e4f5c697683909ca9aa9d9084776a5d504e4e4e4e4e4b463f362c21160a000013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000004101c27333e49545f6a747e879099a098918b868382818283868a8f969e9a928a80766c61574c41352a1e13070000000915212d38434c555a5c5a534c4855616e7b8895a2978a7d7164574a3e3124170b000000000000000000000006101922292f333536363636363636363636363636363636363636363635332f29221910060000000f1c2835424e5b6874818d9a9184786b5f56534c443a3025190d01000000000000000000000006121f2b3844505d6975828e9aa7b3a79b8f83776b5f54483c31261b1006000000000000000000000000000000020d1824303b47515a60625f5b57534f4b47433f3a332a21170d02000013202c3946535f6c798693a0acb3ada5a09f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9e9184776b5e5144382b1e1105000013202c3946535f6c798693a0acb3ada5a09f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9e9184776b5e5144382b1e110500000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000101d2935414d58626b747d868f95887e7e7e7e7e7e7e7e7e7e7e7e7e7e796c5f5346392c2013000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5a52483e32261a0e0000000a16222d3945515d6874808b96a1aca1968c81776e655d554f4b4948494b4f555c646d76818b96a1aca69b8f84786c6054483c3024180b00000005101b26303941474b4d4f51535557595a5751493f4042434444444342403e3b3945515c6875818d99a5a99d9084786c5f53473a2e2115090000000814202d3945515c6874808b97a2ada69a8f857a70675f58524f4d4c4d4f53596069727d88939eaaa89d9185796d6155493d3124180c000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000000000000000000000000000000000000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000b1824313e4b5764717e8b97a4a79a8e8174675a4e4134281b0e0100121f2c3845515d69727373737373737373736b5f53473a2e211508000d1925303b464f565a5b5b5c697683909ca9aa9d9084776a5d5b5b5b5b5b5b5750483d32271b0f030013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a00000915212c38444f5b66717b869099a2988f87807a7775747576797e848c949e9c92887e73685d52463b2f23180c0000000c1825313d49545f6669655e575055616e7b8895a2978a7d7164574a3e3124170b00000000000000000000030e18222c343a3f42424242424242424242424242424242424242424242423f3a342c22180e030000101d2a3743505d6976838f9b8e82756963625e564c41362a1e11050000000000000000000000030f1c2835414d5a66727e8a97a3afab9f93887c7064594d42372c22180e0500000000000000000000000000010a141f2a35404c58636c6e6b67635f5b57534f4b443c33291e1307000013202c3946535f6c798693a0a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a79e9184776b5e5144382b1e1105000013202c3946535f6c798693a0a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a79e9184776b5e5144382b1e110500000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e010000000000000000000d1925303c465059626b747d868f8f877e75717171717171717171717170685c5044382b1f12000a16212c3740484f525353535353535353535353535353535353535353524f4840372c21160a0000020e1a26323e4a56626d7985919ca7a69b8f857a6f655c534b443f3c3c3d3f444a525b656f7a85909ba7aca094897c7164584c4034271b0f020000000a141e272f363b3e40424446484a4c4d4b47484b4d4f50515151504f4d4a4744404c5864717d8995a2aca094887b6f62564a3d3124180b0000000c1824303d4955616d7985919ca8aca095897e73685e554d4642403f4043484e57606b76828d99a5ada2968a7d7165594d4034271b0e020013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000000000000000000000000000000000000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000b1724313e4a5764717d8a97a4a79a8d8174675a4d4134271a0e0100101c2935414c57606667676767676767676661594e43372b1f120600101d2935414d586167686868697683909ca9aa9d9084776a68686868686867625a4f43382b1f13060013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a00010d1925313d4955606c77828d98a29a90867c756e6a6867686a6d737a828c96a19a90857a6e63574c4034281c100400000e1a2734404d596571767069615a55616e7b8895a2978a7d7164574a3e3124170b0000000000000000000009141f2a343e454b4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4b453e342a1f14090000121e2b3844515e6b7784919a8d81736f6f6f685e52463a2d2114070000000000000000000000000c1925313d4a56626e7a86929eaab0a4988d81756a5f54493e342a20170f070100000000000000000000040b131c26303b46515d69747b77736f6b67635f5b564e453b2f24180c000013202c3946535f6c7986939a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9184776b5e5144382b1e1105000013202c3946535f6c7986939a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9184776b5e5144382b1e110500000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e0100000000000000000008141f2a343e475059626b747c868f90877e756d656565656565656565645e564b4034281c100005101a252e373e4346464646464646464646464646464646464646464646433e372e251a1005000005111e2a36424e5a66727e8a96a1aca095897e73685e534a413933302f3033384049535d68737f8b96a2aea5998d8174685c5043372a1e1205000000020c151d252b2f323436383a3c3e42474c5054575a5b5d5d5e5d5d5b595754504c4855616d7a86929faba3978b7e7265594c4033271a0e0100030f1b2834404d5965717d8995a1ada79b8f84786d61574c433b36333334373d454f5a65717c8995a1a2a19a8d8175685c4f43362a1d11040013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000000000000000000000000000000000000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000a1724303d4a5763707d8a97a4a79a8d8173675a4d4034271a0d01000d1924303b454e55595a5a5a5a5a5a5a5a5a5650473d32261b0f0300121f2c3845515e6973757575757683909ca9aa9d90847775757575757575746b6054473b2e2115080013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a0004111d2935414d5965717d88949f9f94897e746b635e5b5b5b5e6168707a85909ba1968b8074685c5044382c20140700000e1b2834414e5b6774817a736c655e616e7b8895a2978a7d7164574a3e3124170b000000000000000000000d1925313c4650575b5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5b5750463c3125190d0000121f2c3845525f6b788592998c807c7c7c7a6e6255483b2f2215090000000000000000000000000915212e3a46525e6a76828e9aa5b1a99d92877b70655a50463c32292119120d0805030101010203060a0f151c252e38424c57636e7985837f7b77736f6b6760574c4034281c0f030013202c3946535f6c79868d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d84776b5e5144382b1e1105000013202c3946535f6c79868d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d84776b5e5144382b1e110500000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000030e18222c353e475059626a737c868f90887f766d645b58585858585857534d443a2f23180c000009131c252c32373939393939393939393939393939393939393939393937322c251c13090000000915212d3a46525e6a76838f9aa6a79b9084786d61574c42382f27232223272e37414c57626e7a86929eaaa99d9184786b5f53463a2d21140800000000030b13191f2325272a323940474d53585c60636668696a6b6a69686663605c5853515e6a7783909ca9a69a8d8174685b4f4236291d10040006121e2b3744505c6975818d9aa6afa3978b7f73675c50453b312a2726272b333d4854606c788591969594939184776b5e5245392c1f13060013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000000000000000000000000000000000000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000a1724303d4a5763707d8a96a3a69a8d807366594d4033271a0d000008131e29333c444a4d4d4d4d4d4d4d4d4d4d4a453e352b20150a000013202c3946535f6c79828282828284909ca9aa9d918482828282828282827b6f6255483c2f2215090013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3aca3968a7d7063564a3d3023170a000814202d3945515e6a76828e99a59a8f83776c6259524f4e4f51565e68737e8a96a29c9085786c6054483c3023170b00000e1b2834414e5b677481857e766f68616e7b8895a2978a7d7164574a3e3124170b00000000000000000000111d2936424d5862686969696969696969696969696969696969696969696862584d4236291d110000131f2c3946525f6c7986929b90898989887b6f6255483c2f22150900000000000000000000000005111d2a36424e5a65717d8994a0abaea3988d82776c62584e443b332b241e1915110f0e0e0e0e1013161b20272e374049545e69747f8b8f8b87837f7b7772685d5044372b1e11050013202c3946535f6c79818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181776b5e5144382b1e1105000013202c3946535f6c79818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181776b5e5144382b1e110500000000000000000000000b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e010000000000000000000006101a232c353e475058616a737c868f91887f766d64584c4b4b4b4b4b48423b32281d12070000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a26211a130a010000000c1825313d4a56626e7a87939faba3978b7f73675c50453a30261d1715171c252f3a46525d6a76828e9ba7aca094877b6e6255493c2f23160a000000000001080e1319222b343c444b52585e64686c70737576777777767573706c68635e595b6774818d9aa6a99c9083776a5e5145382b1f1206000815212e3a47535f6c7885919da9ac9f93877b6e62574b3f34291f1a191b212c3844505d6975828a8988878686857a6d6054473a2e2114070013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000000000000000000000000000000000000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000a1723303d4a5663707d8996a3a6998c807366594d4033261a0d00000915202b363f474d515151515151515151514e4841372d22170c000013202c3946535f6c79868e8e8e8e8f95a0acaca1968f8e8e8e8e8e8e8e887b6f6255483c2f2215090013202c3946535f6c798693a0a0a09a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a0a0a0968a7d7063564a3d3023170a000a1723303c4955616e7a86929ea2968a7e72665b5047424142454c57626d7985929ea195897d7064584b3f33261a0d01000e1b2834414e5b6774818e88817a736b6e7b8895a2978a7d7164574a3e3124170b00000000000000000000121f2c3845525e6a73757575757575757575757575757575757575757575736a5e5245382c1f12000013202c3946535f6c798693a099969695887b6f6255483c2f221509000000000000000000000000010d1925313d4955616c78838f9aa5b0a99e93897e746960564d453d352f2925211e1c1b1a1a1b1d1f22262b32394049525b65707a85909b97938f8b8783786b5e5145382b1e120500121f2c3845515d697273737373737373737373737373737373737373737373737373737373737373737373737373737373737373737371675c5043372a1d11040000121f2c3845515d697273737373737373737373737373737373737373737373737373737373737373737373737373737373737373737371675c5043372a1d11040000000000000003070a0b0b1724313e4a5764717d8a97a4a89b8e8174675b4e4134281b0e01000000000000000000000007101a232c353e464f58616a737c858e91898074685b4e423e3e3e3e3c37302920160c01000000010910161a1e1f20202020202020202020202020202020202020201f1e1a16100901000000020f1b2834404d5965727e8a97a3aca093877b6f63574b3f34291e140b090b131e2935414d5a66727f8b98a4afa3968a7d7064574b3e3125180b000000000000050f18222b343d464e555d636a6f74797c7f828384848483817f7c78746f6a645d65727e8b98a4ab9f9286796c6053463a2d211407000a1723303d4956626f7b8894a0ada99c9084776b5f52463a2e23170e0c0f1c2834414d5a67737e7d7c7b7b7a7978766c6053473a2d2114070013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000000000000000000000000000000000000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a00091623303c4956636f7c8996a3a6998c807366594c403326190d00000e1a26323d4751595d5e5e5e5e5e5e5e5e5e5a53493f34281c10040013202c3946535f6c7986939b9b9b9ba0a8b2b2a8a09c9b9b9b9b9b9b95887b6f6255483c2f2215090013202c3946535f6c798693939393938e8174675a4d4134271a0e01000a1723303d4a5663707d8a93939393938a7d7063564a3d3023170a000d1926323f4b5864717d8a96a29f93877a6e62564a3e3634353a45515d6975828e9ba5998c8074675b4e4235291c1003000e1b2834414e5b6774818e938b847d766f7b8895a2978a7d7164574a3e3124170b0000000000000000000013202c3946535f6c79828282828282828282828282828282828282828282796c5f5346392c2013000013202c3946535f6c798693a0a5a3a295887b6f6255483c2f221509000000000000000000000000000915212d3844505b67727d89949faab0a59a90857b72685f574e47403a35312d2b2928272728292b2e32373d434a525b646d77828c97a2a39f9b958a7e73675b4f43372a1d110400101c2935414c576066676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767655f564b3f33271b0f020000101c2935414c576066676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767655f564b3f33271b0f02000000000002090f131618181825313e4b5864717e8b98a4a89b8e8174675b4e4134281b0e0100000000000000000000000007101a232c343d464f58616a737c858c837970665a4d41343232312f2b261f170e04000000000000050a0e1113131313131313131313131313131313131313131313110e0a05000000000005111e2a3743505c6975818e9aa6a99d9084776b5f53463a2e23170c0200010d1925313e4a5763707d8996a2afa5988c7e7265594c3f3326190d0000000000020c17212a343d464f5860676e757b8085898c8e90919191908e8c8885807b756f6863707c8996a2ada194877b6e6255483c2f221609000c1926323f4b5864717e8a97a3b0a69a8d8174685b4f43362a1e1206000d1926323f4b57636d71706f6f6e6d6c6b6a645a4f43372b1f12060013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000000000000000000000000000000000000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000916232f3c4955626f7c8996a2a5998c7f7265594c3f3226190c0000111d2a36424e59636a6b6b6b6b6b6b6b6b6a655b5044382c2013070013202c3946535f6c7986939e9e9e9ea0a7b0b4aaa29e9e9e9e9e9e9e95887b6f6255483c2f2215090013202c3946535f6c79868686868686868174675a4d4134271a0e01000a1723303d4a5663707d868686868686867d7063564a3d3023170a000f1b2835414e5a6773808c99a59d9084776b5e5246392d282935414d5966727f8b98a59c8f83766a5d5144382b1e1205000e1b2834414e5b6774818e97968f8881797b8895a2978a7d7164574a3e3124170b0000000000000000000013202c3946535f6c79868f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f86796c5f5346392c2013000013202c3946535f6c798693a0acafa295887b6f6255483c2f2215090000000000000000000000000004101c28333f4a56616c77828d98a2adaca1978d847a71696059524b46413d3a37353434343536383b3e43484e555c646d768089939ea8b0a59a8f84796d62564b3f33271b0e02000d1924303b454e55595a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5f646464646464615b5a5a5a5a5a5a5a5a5a5a5a5a5a5a59544d44392e23170b0000000d1924303b454e55595a5a5a5a5a5a5a5a5a5a5a5a5a5a5d636464646464635d5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a59544d44392e23170b0000000000050d141a1f2325252526333f4c5965727e8c98a5a89b8e8174675b4e4134281b0e010000000000000000000000000007101a222b343d464f58616a737c837a71675e54493d31252525231f1a140d050000000000000000000000000000000000000000000000000000000000000000000000000000000000000714202d3946525f6b7884919daaa79a8e8175685c4f43362a1e12060000000916222f3c4855626e7b8894a1aea69a8d8173675a4d4134271a0e000000000009141e28323c464f58616a727980868c9195989b9c9d9e9d9c9b9895918c86817a736b6e7b8894a1ada296897c7063564a3d3024170a000e1b2734414d5a6673808c99a6b1a4988b7e7265594c4033271a0e02000a16232f3b46515b626464636261605f5f5d5952483e33271b0f030013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000000000000000000000000000000000000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000916222f3c4955626f7b8895a2a5988c7e7265584c3f3225190c0000131f2c3945525e6b757777777777777777766d6154483b2e2215080013202c3946535f6c79869191919191959ea9ada2989191919191919191887b6f6255483c2f22150900131f2c3946525f6b76797979797979797972665a4d4034271a0e01000a1623303c4956626e7879797979797979786e6256493c3023160a00101d2a3643505c6975828f9ba79b8e8275685c4f43362a1d25313e4a5764707d8a96a39e9285796c5f5346392d201307000e1b2834414e5b67747e858c9399928b847c8895a2978a7d7164574a3e3124170b0000000000000000000013202c3946535f6c7986939c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9386796c5f5346392c2013000013202c3946535f6c798693a0acaca295887b6f6255483c2f22150900000000000000000000000000000b17222e3944505b66717b86919ba5afa99f968c837a726a635d57514d49464442414041414345474b4f545960666e767f88919ba5b0a99e94897e73685c51453a2e22170b000008131e29333c444a4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d545b626a7071717171716c63574d4d4d4d4d4d4d4d4d4d4d4d4d4c49433b32281d120600000008131e29333c444a4d4d4d4d4d4d4d4d4d4d4d4d4d4f5b666f71717171716f676059524d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4c49433b32281d120600000000040e171f262b2f3132323236424e5b6774818d9aa6a79a8e8174675b4e4134281b0e010000000000000000000000000000071019222b343d464f58616a737971685f554c42382d21181816130f0902000000000000000000000000000000000000000000000000000000000000000000000000000000000000000916222f3c4855616e7a8793a0aca5988c7f7366594d4034271b0e020000000714212d3a4754606d7a8793a0ada79b8e8174675b4e4135281b0e0000000005101b25303a444e58616a737c838b91979da1a4a7a6a4a2a1a1a1a2a19c97928b857d756d798693a0aca4978b7e7164584b3e3225180c000f1c2935424f5b6875828e9ba7afa296897c7063574a3d3124180b000007121e2a353f4950565757565554535352514e4840362c21160b000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000000000000000000000000000000000000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000915222f3c4855626f7b8895a2a5988b7e7165584b3f3225180c000013202c3946535f6c7984848484848484847b6f6255483c2f2215090013202c3946535f6c798484848484848d99a5aa9e918684848484848484847b6f6255483c2f22150900111e2a37434f5a646b6c6c6c6c6c6c6c6c6960564a3e3225190c00000815212e3a46525d676c6c6c6c6c6c6c6c6c675d52463a2e21150800111e2b3844515e6a7784909da6998d8073675a4d4134271b232f3c4955626f7b8895a1a094877a6d6154473b2e211508000d1a26333f4b57636c737a81888f96968e878a96a2978a7d7164574a3e3124170b0000000000000000000013202c3946535f6c798693a0a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a09386796c5f5346392c2013000013202c3946535f6c798693a0a0a0a095887b6f6255483c2f221509000000000000000000000000000006111d28333e49545f6a747f89939da6b0a89e958d847c756e68625d595552504f4e4d4d4e4f5154575b5f656b71788088919aa3adaba1978d82776c61564b4034291d12060000020d17212a32393d40404040404040404040404040404040414850575e666d747c7d7d7d7d7d74675a4d414040404040404040404040403d38312920160b01000000020d17212a32393d40404040404040404040404045515e6b777d7d7d7d7d79726b635c554d4640404040404040404040404040404040403d38312920160b01000000010c16202930373c3e3e3e3e4046525e6a76838f9ca8a69a8d8073675a4d4034271a0e01000000000000000000000000000000071019222b343d464f5861696c675f564d433a31261b100b0a07030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1824313e4a5763707d8996a2afa4978a7e7164584b3e3225180c000000000713202d3a4653606d798693a0aca89b8e8275685b4e4235281c0f000000000b16212c37424c56606a737c858e959ca3a8a8a39e9a979594949496989b9f9d968f877e757885929eaba5988c7f7266594c3f3326190d00111d2a3743505d6a7683909ca9aea194887b6e6255483c2f2216090000020d18232d373f45494b4a49484847464544423d362e251a1005000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000000000000000000000000000000000000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000815222e3b4855616e7b8895a1a4988b7e7165584b3e3225180b000013202c3946535f6c7986919191919191887b6f6255483c2f22150900131f2c3945525e6a7577777777777d8a96a3aa9d90847777777777777777766d6154483b2e221508000e1a26323e48525a5f5f5f5f5f5f5f5f5f5d574e44392d221609000005121e2a35414b555c5f5f5f5f5f5f5f5f5f5c554b41352a1e120500121f2c3845525f6b7885929ea5988c7f7265594c3f332619212e3b4754616d7a8794a0a195887b6e6255483c2f221509000b17232f3b46515a61686f767d848b929993959ca4978a7d7164574a3e3124170b0000000000000000000013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09386796c5f5346392c2013000013202c3946535f6c7986939393939393887b6f6255483c2f2215090000000000000000000000000000000b17222d38434d58636d77818b949ea7afa89f968e878079736e6965625f5d5b5b5a5a5b5c5e6063676b70767c838a929aa3acaca2998f857b70665b50453a2f23180c01000000050f1820272d3133343434343434343434343434363d444c535a616970777f868a8a8a8a8174675a4d41343434343434343434343433312c271f170e040000000000050f1820272d3133343434343434343434343845515e6b78838a8a8a8a847c756e665f585149423b3434343434343434343434343433312c271f170e040000000007121d28323b42484b4b4b4b4c5058636e7a86929faba5988b7e7265594c3f3326190d0000000000000000000000000000000000071019222b343d464f585e5f5c554d433a31281f150a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1a26333f4c5965727e8b98a4b0a3968a7d7063574a3d3024170a000000000713202d3a4653606d798693a0aca89b8f8275685b4f4235281c0f00000006111c28333e49535e68727c868f97a0a7aba39d97928e8b89888788898c8f93989d9991887e7784919eaaa69a8d8073675a4d4034271a0e00121e2b3844515e6b7784919eaaada093867a6d6054473a2d21140700000007111b242d34393d3e3d3d3c3b3a39383735312b241c130900000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000000000000000000000000000000000000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000815212e3b4854616e7b8894a1a4988b7e7164574b3e3124180b000013202c3946535f6c7986939e9e9e9e95887b6f6255483c2f22150900111d2a36424e5963696a6a6a6a6e7a8794a0aa9d9084776a6a6a6a6a6a6a6a645b5044382c201307000a16212c3740484f525353535353535353514c453c32281d11050000020d19242f39434a50535353535353535353504a43392f24190d020013202c3946525f6c7986929fa5988b7e7165584b3f322518202d3a4753606d798693a0a296897c6f6255493c2f2216090007131e2a353f4850575e656c737a81888f969da0a0978a7d7164574a3e3124170b0000000000000000000013202c3946535f6c79869393939393939393939393939393939393939386796c5f5346392c2013000013202c3946535f6c7986868686868686867b6f6255483c2f22150900000000000000000000000000000005101b26313c46515b656f79828c959da6aea8a098918b847e7a75716e6c6a6867676767696a6c6f73777c81878e959ca4acaba29a90877d73695f54493e33281d12070000000000060e161c2125272727272727272727272a313940474f565d656c737a82899197938a81776e64584c4033272727272727272727272624211b150d0500000000000000060e161c2125272727272727272727272a3743505c67717a848d96968e878078716a625b544c453e362f282727272727272727272624211b150d0500000000000c18232f3a444d5357585858595c616a74808b97a3afa296897d7064574a3e3125180b000000000000000000000000000000000000071019222b343d464d5153504b433a31281f160d03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1b2834414e5a6774818d9aa6b0a396897c7063564a3d3023170a000000000814212e3a4754606d7a8793a0ada89b8e8275685b4e4235281b0f0000000b16222d39444f5a65707a848e97a1a9a9a199928c86827e7c7b7a7b7d7f83878c92999a90867c84909daaa79a8e8174675b4e4134281b0e00121f2c3845525f6b7885929eabac9f9286796c5f5346392c2013060000000009121b22292d303131302f2e2d2c2c2b2925201a120a0100000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000000000000000000000000000000000000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000814212e3b4754616d7a8794a1a4978a7d7164574a3e3124170b000013202c3946535f6c798693a0ababa295887b6f6255483c2f221509000e1a26313d4751585d5d5d5d5f6b7884919daa9d9084776a5d5d5d5d5d5d5d5952493f34281c10040005101a252e373e4346464646464646464645413b332a21160b0000000008131d2731393f44464646464646464646443f3931271d1308000013202c3946535f6c798693a0a5988b7e7165584b3e322518202d3a4653606d798693a0a296897c6f6356493c3023160900020d18232d363e454c535a61686f767d848b929393938a7d7164574a3e3124170b0000000000000000000013202c3946535f6c79868686868686868686868686868686868686868686796c5f5346392c20130000131f2c3946525f6b767979797979797979786d6155483b2f221508000000000000000000000000000000000a15202a353f49535d677079838b949ca4abaaa39c96908a86817e7b787675747373747577797c7f83888d92989fa6aea9a19990887e756b61574d42382d22170c01000000000000040b1115181a1a1a1a1a1a1a1f262d353c434b525960686f767e858c949b948a81786f655c52473c30241a1a1a1a1a1a1a1a1a1a1815100a03000000000000000000040b1115181a1a1a1a1a1a1a1a1a1b2834404b565f68717b848d9799918a837b746d655e574f48413a322b241c1a1a1a1a1a1a1a1815100a03000000000000101c2834404b565e6465656566686c737c86919ca7ab9f93867a6d6155483c2f23160900000000000000000000000000000000000000071019222b343b41454644403931281f160d040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936424f5c6875828e9ba8b0a3968a7d7063564a3d3024170a000000000a16232f3c4855626e7b8894a1aea79a8d8174675a4e4134281b0e000004101c27333f4a55616c76818c96a0a9aaa0978f87807a75726f6e6d6e7073767b81878e96988d8283909da9a89b8e8275685b4e4235281c0f00131f2c3946525f6c7986929facac9f9285786b5f5245392c1f120600000000000911171d2124242423222121201f1e1c19150f08000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000000000000000000000000000000000000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000714212e3a4754616d7a8794a0a4978a7d7063574a3d3124170a000013202c3946535f6c798693a0acafa295887b6f6255483c2f221509000915202b353f474d505151515c6975828e9ba79d9084776a5d5151515151504e4840372d22170b00000009131c252c32373939393939393939393835302921180f0400000000010c151f272e343739393939393939393937342e271f150c01000013202c3946535f6c7986929fa5988b7e7165584b3e322518202d3a4653606d798693a0a296897c6f6255493c2f231609000007111b242c343a41484f565d646b72798086868686867d7164574a3e3124170b00000000000000000000131f2c3946525f6b76797979797979797979797979797979797979797979766b5f5246392c1f130000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c665c5145392d20140700000000000000000000000000000000030e18232d37414b555e677079828a9299a0a7ada7a19b96928d8a8785838281818181828486888b8f93989ea4aaaca59e978f877e756c63594f453b31261b110600000000000000000005090c0d0d0d0d0d17202930383f464e555c646b727981888f979d948b81786f665d534a41362b1f140d0d0d0d0d0d0d0d0d0b08040000000000000000000000000005090c0d0d0d0d0d0d0d0d0d17232e39444d565f69727b858e979c958d867e777069615a534b443d352e261d140d0d0d0d0d0b08040000000000000000121f2b3844505c68707171717274787e858e98a2ada69a8e82766a5e5245392d2014070000000000000000000000000000000000000000071019222a3035383938342f281f160d04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111d2a3743505d6a7683909ca9b0a4978a7d7164584b3e3225190d050202040e1a26323e4b5764707d8996a3afa5998c807366594d4033271a0d00000814202c38444f5b66727d88939ea8aca2988e857d756f69656361616263666b70767c848c95948883909ca9a89c8f8275685b4f4235291c0f0013202c3946535f6c7986929facab9e9285786b5e5145382b1f1205000000000000060c111517181716161514131211100d090400000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000000000000000000000000000000000000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000714202d3a4753606d7a8794a0a3968a7d7063574a3d3024170a000013202c3946535f6c798693a0acafa295887b6f6255483c2f22150900040f19232d353c414444444d5966727f8b98a49d9084776a5d504444444444423d362e251b1106000000010a131a21262a2c2c2c2c2c2c2c2c2c2c29241f170f06000000000000030d151c23282b2c2c2c2c2c2c2c2c2c2b28231c150d03000000121f2c3945525f6b7885929fa5988c7e7265584c3f322619212e3a4754606d7a8794a0a295887b6f6255483c2f22160900000009121a222930373e454c535a61686f757979797979796f63574a3d3124170a00000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b645a4f43372a1e1100000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5b544a4034291d1104000000000000000000000000000000000007111b252f39434c555e67707880888f959ca2a7aca7a29e9a969491908e8e8d8d8e8f909295989b9fa4a9aba6a09a948d857d756c635a51473d33291f140a0000000000000000000000000000000009141f29323b424951585f676e757d848b939a9e948b82786f665d544b41382f241a0e03000000000000000000000000000000000000000000000000000000000000000000000007121d28323b444d576069727b858e979f989089827a736c645d564e4740382f251b1005000000000000000000000000000013202c3946535f6c797e7e7e7f8184898f97a0aaa99f94897d72665a4e4236291d11040000000000000000000000000000000000000000000710181f25292c2c2b28231d160d0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111e2b3844515e6b7784919eaab2a5998c8073665a4e41352a1f16110f0f10161f2a36424e5a6773808c98a5b0a3978a7e7164584b3f3225190c00000c1825313d4954606c78838e9aa5afa59a90867c736b645e5956555455575a5f646b727a838d97908d949faba99c8f8275695c4f4236291c0f0013202c3946535f6c7986939facab9e9285786b5e5145382b1e12050000000000000004080b0d0d0c0b0a09080706050401000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000000000000000000000000000000000000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000713202d3a4653606d7986939797968a7d7063564a3d3023170a000013202c3946535f6c798693a0a4a4a295887b6f6255483c2f221509000007111b232a303537373e4a5763707c8995a19d9084776a5d50443737373735312c251c13090000000000010910161a1e1f20202020202020201f1d19130d060000000000000000030b12171c1e2020202020202020201e1c17120b0300000000121e2b3845515e6b7784919da6998c807366594d4033271a222f3b4855616e7b8894a1a194877b6e6154483b2e221508000000000910171e252c333a41484f565d646b6c6c6c6c6c6c675e53473b2e221609000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5a52483e32261a0e00000a16212c3740484f52535353535353535352504a42382e23180c0000000000000000000000000000000000000009141d27313a434c555e666e767d848b91969ca1a5a9aaa6a3a09e9c9b9a9a9a9a9b9d9fa1a4a7aba8a49f9a958f89827b736b635a51483f352b21170d03000000000000000000000000000000020e1a25303b444d545b626a717880878e969d9e958c827970665d544b42392f261d1308000000000000000000000000000000000000000000000000000000000000000000000000010c162029323b454e576069737c858e98a19b938c857d766f676059524a41372d21160a000000000000000000000000000013202c3946535f6c79868b8b8c8d90949aa1a9a9a1978d83786c61554a3e3226190d0100000000000000000000000000000000000000000000060d14191d1f201f1c18120b040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000121f2c3845525f6b7885929eabb4a89b8f82766a5e52463b3128211d1c1b1d2128313c47535e6a76838f9ba8ada194887b6f6256493d3024170a0004101c2935414d5965717d8994a0aba99e93887e746a6159524d4a4847484a4e53596068717b858f9a9a9ea6b1a99c8f8275695c4f4236291c0f00131f2c3946525f6c7986929facab9e9285786b5f5245382c1f12050000000000030a101518191a1918171615141312100d090300000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0aca79a8e8174675a4d4134271a0e01000a1723303d4a5663707d8a96a3b0a3968a7d7063564a3d3023170a000000000000000000000000000000000000000000000000000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000613202d3946535f6c79868a8a8a8a897c6f6356493c30231609000013202c3946535f6c7986939797979795887b6f6255483c2f2215090000000911191f25282a2f3b4854606d7986929f9d9084776a5d5044372a2a2a2925201a130a0100000000000000050a0e1113131313131313131312100d08020000000000000000000000060b0f12131313131313131313120f0b06000000000000111d2a3743505d6976838f9ca79a8e8174685b4e4235291c24303d4a56636f7c8995a29f9386796d6053473a2d2014070000000000060d131a21282f363d444b52595e5f5f5f5f5f5f5c554c41362b1f1206000000000000000000000a16212c3740484f52535353535353535353535353535353535353535353524f4840372c21160a000005101a252e373e4346464646464646464646433f3830261c120700000000000000000000000000000000000000020c151f28313a434c545c646b727980858b9095999da0a3a5a7a9a9a8a7a7a7a7a8a9a9a7a5a29f9c98948f8a847e777069615951483f362d231910050000000000000000000000000000000005121e2a36424c565e666d747c838a9299a09e958c837970675e544b423930261d140b0100000000000000000000000000000000000000000000000000000000000000000000000000040e172029333c454e57616a737c868f98a19e978f888179726b635c53493e32261a0e020000000000000000000000000013202c3946535f6c79869398989a9ca0a5a8a49e978f857b71665b5044392d21150900000000000000000000000000000000000000000000000002080d10121312100c0701000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7986929facb7aa9e92867a6e63574d433a322d2a2828292d323a434d58636f7b87939fabaa9e9185796c6053473a2e211508000713202c3845515d6975818d99a5afa4988d82766c62584f47413d3b3b3c3e42484f565f69737d88949faab0b5a99c8f8275695c4f4236291c0f00121f2c3945525f6b7885929eabac9f9285786c5f5245392c1f130600000000050e151b21242626252423232221201f1d19140e07000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c798693a0a6a69a8e8174675a4d4134271a0e01040a1723303d4a5663707d8a96a3a6a3968a7d7063564a3d3023170a000000000000000000000000000000000000000000000000000000000f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000613202c3946535f6c787d7d7d7d7d7d7b6f6255493c2f231609000013202c3946535f6c79868a8a8a8a8a8a887b6f6255483c2f22150900000000070e14191c1f2c3845515e6a7783909c9d9084776a5d5044372a1e1e1c19150f08010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2835424e5b6774818d9aa69c8f83766a5d5144382c2527333f4c5865717e8b97a49d9184776b5e5245382c1f1206000000000000020910171e252c333a41484e52535353535353504b433a30251a0e020000000000000000000005101a252e373e434646464646464646464646464646464646464646464646433e372e251a100500000009131c252c32373939393939393939393937332d261e140b000000000000000000000000000000000000000000030d161f28313a424a525961676e747a7f84898d909496999b9c9e9e9f9f9f9f9e9d9c9a989693908c88837e78736c665f574f473f362d241b110800000000000000000000000000000000000814212e3a46525e6870777f868d959ca09f958c837a70675e554c423930271e140b02000000000000000000000000000000000000000000000000000000000000000000000000000000050e17212a333c454e58616a737c868f98a0a09a928b847c756e655a4f42362a1d10040000000000000000000000000013202c3946535f6c798693a0a0a0a09f9e9b98938c857c73695f554a3f33281c1105000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986939facb9aea2968b7f74695e554c443e3936353536393d444c555f6a75808c97a3afa69a8e8275695d5044382b1f1206000a16232f3b4854616d7985929eaaab9f93877b70655a50463d36312e2e2f32373d444d57616c77828e9aa5b2b5a89c8f8275695c4f4236291c0f00121e2b3845515e6b7784919eaaac9f9386796c5f5346392d201307000000040e171f272c3133333231302f2e2d2c2b29251f1911080000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c7986939a9a9a9a8e8174675a4d4134271a120c0f151923303d4a5663707d8a969a9a9a968a7d7063564a3d3023170a0000000000000000000000000000000000000000000005090c0d0d0d0f1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a0005121e2b3844505c676f70707070707070695e53473a2e211508000013202c3946535f6c787d7d7d7d7d7d7d7d7b6e6255483c2f221509000000000003080c101d2936424f5b6774818d93939084776a5d5044372a1d11100d090400000000000000000000000000000000000000000004060707050300000000000002050708080603000000000000000000000000000000000000000000000d1a26333f4c5865717e8a97a39e9285796d6054483c33323237434f5b6874818d99a69a8e8275685c4f43362a1d11040000000000000000050c131a21282f363d424546464646464644403931281e130800000000000000000000000009131c252c3237393939393939393939393939393939393939393939393937322c251c130900000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2b27221c140c0200000000000000000000000000000000000000000000040d161f28303840484f565d63696e73787c8184878a8c8e9091929292929292908f8e8c898683807c77726d67615b544d453d352d241b12090000000000000000000000000000000000000916222f3c4955626f7a82899193939393938d837a71685e554c433a30271e150c020000000000000000000000000000000000000000000000000000000000000000000000000000000000050f18212a333c464f58616a747d869093939393938e8780776b5e5145382b1e12050000000000000000000000000013202c3946535f6c7986939393939392918f8c87827b736a61584d43382d22170b000000000000000000000000000000000000000000000000000000000000000000000000050a0d0f0f0f0f0f0f0f0f0f0f0d0a0500000000000000000000000001070b0d0f0f0f0f0f0f0f0f0f0e0c090400000000000000000013202c3946535f6c798693a0acb5ada79c90857b70675e564f49454342424345494e565e67717b86919da8aca195897d7165594d4134281c0f03000c1925323e4b5764707c8995a1aea79b8e82766b5f54493e342b25222122262b323b454f5a66717d8995a1aeb5a89b8f8275685b4f4235281c0f00111e2a3744505d6a7683909da9ada093877a6d6054473a2e2114080000010c16202931383d40403f3e3d3c3b3a393835312a231a110700000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c79868d8d8d8d8d8d8174675a4d413427231d171b212528303d4a5663707d8a8d8d8d8d8d8a7d7063564a3d3023170a0000000000000000000000000000000000000000040b1115181a1a1a1a1c2936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a00030f1c28343f4b555d63636363636363635f574d42362a1e12060000121e2b3844505c676f707070707070707070695e52463a2d21140800000000000000010e1a26333f4c5865717e8686868684776a5d5044372a1d110400000000000000000000000000000000000000000001070c10131414120f0a05000002080e11141514130f0b0500000000000000000000000000000000000000000b1724303d4956626e7b87939fa195897c7065594e44403e3f424954606b7784909ca3978b7e7266594d4034271b0e0200000000000000000001080f161d242b32363939393939393938342e271f160c02000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a26211a130a010000000000010910161a1e1f2020202020202020201e1b17110a02000000000000000000000000000000000000000000000000040d161e262e363d444b51575d63686c7074787b7d808283848586868685858483817f7d7a77736f6b67615c565049423b332b231b1209000000000000000000000000000000000000000916222f3c4955626f7c8686868686868686847a71685f564c433a31281e150c0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f18212a343d464f58626b747d868686868686868685786b5e5145382b1e12050000000000000000000000000013202c3946535f6c79868686868686868482807b76706961584f463c31271c110600000000000000000000000000000000000000000000000000000000000000000000040b1116191b1c1c1c1c1c1c1c1c1b1916110b04000000000000000000060d12171a1c1c1c1c1c1c1c1c1c1b19151009020000000000000013202c3946535f6c798693a0acada39b98978c82797068605a5552504e4e4f51555a60677079838d98a3aea69b9084786d6155493d3125180c00000e1b2734414d5a66737f8c98a5b0a3978b7e72665a4e42372c22191514161a2129333e4955616d7985929eabb4a89b8e8174685b4e4235281b0f00101c2936424f5c6875828e9ba8aea194887b6e6255483c2f221609000007121d28323b43494c4d4b4b4a4948474645413c352c23180e02000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070013202c3946535f6c79808080808080808074675a4d4135332e2821252c3134363d4a5663707d808080808080807d7063564a3d3023170a00000000000000000000000000000000000000070f161c212526262626262936424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a00000b17232e39434c525657575757575756534d453b31251a0f0400000f1c28343f4b555d636363636363636363635f574d42362a1e120500000000000000000b1724303d4956626e78797979797974695c5043362a1d10040000000000000000000000000000000000000000050c12181c1f21201e1b161008050d14191e2022211f1b161009030000000000000000000000000000000000000815212d3a46525e6b77838f9aa5998d81756a5f56504c4b4c4e535b65707c8894a09e93877b6e62564a3d3125180c000000000000000000000000050c131a20262a2c2c2c2c2c2c2c2b28231d150d040000000000000000000000000000010910161a1e1f2020202020202020202020202020202020202020201f1e1a161009010000000000000000050a0e1113131313131313131313120f0b06000000000000000000000000000000000000000000000000000000040c141c242b333a40464c52575c6064686b6e717375767778797979797877767472706d6a67635f5b56514b453e383129211a110900000000000000000000000000000000000000000916222f3c4855616e7879797979797979797971685f564d433a31281f160c03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f18222b343d475059626b75797979797979797979756a5e5144382b1e120500000000000000000000000000131f2c3946525f6b76797979797979797876736f6b655e574f463d342a1f150a00000000000000000000000000000000000000000000000000000000000000000000050e151c22262828282828282828282826221c160e06000000000000000810181e23262828282828282828282825201b140c0300000000000013202c3946535f6c798693a0aca89c918b91948b8279726b66615e5c5b5b5c5e61656b7279828b959fa9aa9f958a7e73685c5044392d2115080000101c2936424f5c6875828e9ba7ada194887b6f62564a3e32261b1009080a0f17222d3945515d6976828f9ca8b3a79a8d8174675a4d4134271b0e000e1b2834414e5a6773808d99a6afa396897d7063574a3e3124180b00000c18232f3a444d54595958575655545352514d473e342a1f1408000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d20130700121f2b3845515d687173737373737373736e64584c42423f3a332b2f373d4142424854606b7373737373737373736b6054483c2f22160900000000000000000000000000000000000006101921282d3133333333333336424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a0005101b26303941474b4c4c4c4c4c4c4c4c4b49443d352b21160b00000b17232e39434c5256575757575757575756534d453b30251a0e0200000000000000000815212d3a46525d666c6c6c6c6c6c6a62584c4034281b0f02000000000000000000000000000000000000030910161d23292c2e2d2b27211a120f171f252a2d2e2e2b27211b140e07000000000000000000000000000000000005121e2a36424e5a66727e8a95a09e92877c7168615c5958585a5e646d77828d99a4998e82766a5e52463a2e2215090000000000000000000000000001080f151a1d1f2020202020201f1c17120b040000000000000000000000000000000000050a0e111313131313131313131313131313131313131313131313110e0a050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a121a21282f353b41464b5054585c5f62646668696b6b6c6c6c6c6b6a69686664615e5b57534f4a453f3a332d261f1710080000000000000000000000000000000000000000000714202d3945515c666c6c6c6c6c6c6c6c6c6c685f564d443b31281f160d040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061019222b343e475059626a6c6c6c6c6c6c6c6c6c6b63594e4235291d100300000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6b6967635f5a544d453d342b22180e03000000000000000000000000000000000000000000000000000000000000000000040e1720272d3235353535353535353535322e2720180e04000000000007111a22292f3335353535353535353534312c251e150c01000000000013202c3946525f6c7986929faca6998c808a95948b847d76726e6b696868696a6d71767c848b949da7aca2988e83786d62574b4034281c10040000111e2b3744515d6a7783909da9ab9f9285796c6053473a2e22150a00000005101c2835414e5b6774818d9aa7b2a6998c807366594d4033271a0d000d1926323f4c5865717e8b97a4b0a4988b7e7265594c4033271a0e02030f1c2834404b565f65666564636261605f5e5850463b3024180c000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d20130700101c2935414c5760656666666666666666645c524f4f4e4b453d333941494d4f4f4f4f596266666666666666666662594f44382c2014070000000000000000000000000000000000030e18222b32393d40404040404040424f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000a16212d38424b5357585858585858585858554f473d32271c10040006121d27313a41474a4a4a4a4a4a4a4a4a4a47423b33291f140900000000000000000005111d2935404b545c5f5f5f5f5f5f5e5950463b3024180c000000000000000000000000000000000000070e141b21282f34383a3a37322c241b17212930363a3b3a38332c261f18120b05000000000000000000000000000000020e1a26323e4a56616d78848e99a3988d837a726c68666565676a6f767f89939e9e93887d71655a4e42362a1e120600000000000000000000000000000004090e1113131313131313120f0c07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f161d242a30353a3f44484c4f5255585a5b5d5e5f5f5f5f5f5e5e5c5b595755524f4b47433e39342e28221b140d050000000000000000000000000000000000000000000005111d2935404b545b5f5f5f5f5f5f5f5f5f5f5d564e443b32291f160d0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071019222c353e4750595e5f5f5f5f5f5f5f5f5f5e5951473d3125190d01000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5e5d5a57534e48423b332b22191006000000000000000000000000000000000000000000000000000000000000000000000b16202931393e414242424242424242413e39322a20160c01000000030e19232c343a3f424242424242424242413d3730271d13090000000000121f2c3945525f6b7885929faba6998c80838d98968e88827d7a7775757575777a7d82878e959da6aca39a90867c71675c51453a2f23170c000000121f2c3845525e6b7885919eabaa9d9084776a5e5144382b1f1206000000000d1a2733404d596673808c99a6b1a5988b7e7265584c3f3225190c000b1724303d4956626f7b8894a1ada69a8d8174685b4f43362a1e120b0a121e2b3744505c6871737271706f6e6d6c6a62584d4134281c0f030013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000c1824303a454e555959595959595b5c5c5c5c5c5c5c5b564f453b414b53595c5c5c5c5c5c5c5c595959595959595650473d33271c1004000000000000000000000000000000000009141f2a343d444a4c4d4d4d4d4d4d4d4f5c6975828f9ca9b0a3968a7d7063564a3d3023170a000d1a26323e49545d6465656565656565656561594f44382c201407000b17222d38424a5155555555555555555555524c433a2f24190d010000000000000000010d19242f39424a50535353535353524e473e352a1f140800000000000000000000000000000000030b12181f262c333940454746433e362d241f29333b41464847443e37312a231d160f080000000000000000000000000000000a16222d3945505c67727d87929b9f958c847d787472717273767a8188919b9f968c81766b6055493d32261a0e0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005090c0d0d0d0d0d0d0d0d0d0c090500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050c12191e242a2f34383c404346494b4d4f505152525352525251504e4d4b4845423f3b37322e28231d17100a030000000000000000000000000000000000000000000000010d18242e39424a5053535353535353535353514c443c322920170d0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007101a232c353e474e52535353535353535353524e483f362b20150900000000000000000000000000000a16212c3740484f525353535353535352504e4b47423d373029211910070000000000000000000000000000000000000000000000000000000000000000000006111c27323b434a4e4f4f4f4f4f4f4f4f4e4a443c32281d12060000000915202b353e464b4e4f4f4f4f4f4f4f4f4d4942392f251a0f0300000000121f2b3845515e6b7885919eaba69a8d807c868f9999938e8a8684828282828486898e9399a0a7aaa29a91887e746a60554a3f34291e1207000000131f2c3946525f6c7986929faca99c8f8276695c504336291d1003000000000d1a2633404d596673808c99a6b0a3968a7d7064574a3e3124180b000815212e3a4753606c7885919eaaa99c9084776b5f53463a2f231a171718222e3a46535f6c78807e7d7c7b7b797974695d5043372a1d11040013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070008131e29333c43494c4d4d4e586268696969696969696761574c4047525d656969696969696969645c514d4d4d4d4a453e352c21160b0000000000000000000000000000000000010e1a25313b464e555959595959595959595c6975828f9ca9b0a3968a7d7063564a3d3023170a00101c2935424e5a666f7272727272727272726b6054483c2f231609000f1b27333f4a545c616262626262626262625d564c41352a1d110500000000000000000007121d2730383f4446464646464645423c352c23180e02000000000000000000000000000000030c151d232a31373e444b5154534f4840362b26313b454c5255544f49423b352e28211a1209000000000000000000000000000005111d28343f4a56606b758089929a9e968f8984817f7e7e8082868c929a9e968d847a70655a4f44382d211509000000000000000000000000000000000206090c0f1112121212110f0d0a0602000000000000000000000000000000000000040b1115181a1a1a1a1a1a1a1a1a1815110b0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001070d13191e23282c3033373a3c3e40424344454646464645444342403e3c3936332f2b27221d18120c06000000000000000000000000000000000000000000000000000007121d2730383f444646464646464646464644403a322a20170e05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008111a232c353c424546464646464646464645423d362d24190f04000000000000000000000000000005101a252e373e4346464646464646464544413f3b37322c261f170f0700000000000000000000000000000000000000000000000000000000000000000000000a16222e39434d555a5b5b5b5b5b5b5b5b5a554e443a2e23170b0000020e1a26313c4750575b5b5b5b5b5b5b5b5b59534b41362b1f140700000000111e2b3744515d6a7784909daaa79a8d81747d878f979e9a9693918f8e8e8f9092969a9ea4aaa69f9890887f766c62584e43392e23180c0100000013202c3946535f6c798693a0aca89c8f8275685b4f4235291c0f02000000000e1a2734404d5a6773808d9aa6aea195887b6f6256493c3023160a0006121f2b3844505d6975828e9aa6aca093877b6f63574b40352b2624242529333e4a56626f7b878b8a8988878683766a5d5044372a1e11040013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d20130700020d17212a32383d404045525e6a747575757575757573695d50444b57636f75757575757575756e62564a4040403e3a342c231a0f05000000000000000000000000000000000005111e2a36424d5860666666666666666666666975828f9ca9b0a3968a7d7063564a3d3023170a00111d2a3744505d6a767e7e7e7e7e7e7e7e7d7063574a3d3024170a00121e2b3743505b666d6f6f6f6f6f6f6f6f6e685d5246392d211407000000000000000000010b151e272e33373939393939393936312b231a1107000000000000000000000000000000000b151e272e353c42494f565c605f5a52483d322c38434d575e61605a544d464039332c241b110600000000000000000000000000000c17232e39444f59646d77808990979d9a94908d8c8b8b8c8f92979d9a948c847b72685e53483d32271c1004000000000000000000000000000003090e1216191b1d1e1f1f1f1d1c1916130e0904000000000000000000000000000000060e161c212527272727272727272725211c160f060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080d12171c2024272a2d30323435373838393939393837363533312f2d2a26231f1b16110c0601000000000000000000000000000000000000000000000000000000000b151e262e33373939393939393939393938352f2920170e050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008111a232b3136393939393939393939393936322b241b12080000000000000000000000000000000009131c252c32373939393939393939383735322f2b26211b140d050000000000000000000000000000000000000000000000000000000000000000000000000d1a26323e4a555f6668686868686868686760564b3f33271b0e020005111e2a36424e5862676868686868686868655d53483c3023170b00000000101d2a3643505d6976838f9ca9a89b8e8174747d858d949a9f9f9d9c9b9b9c9d9fa2a6a8a49f9a948d867e766d645a51463c32271c11060000000013202c3946535f6c798693a0aca89c8f8275685b4f4235291c0f02000000020f1b2835414e5b6774818e9aa7ac9f93867a6d6054473b2e21150800030f1c2834414d5965727e8a96a2ada3978b7f73685c51473d3632313031343b45505b66727e8b97979695948c8073675a4e4235291c10030013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070000050f1820272d31333a4653606d7982828282828282786b5e51454c5965727f8282828282827e7164574b3e3333322e29221a11080000000000000000000000000000000000000713202d3946525e69727373737373737373737375828f9ca9b0a3968a7d7063564a3d3023170a00111d2a3744505d6a77848c8c8c8c8c8c8a7d7063574a3d3024170a0013202c3946525f6c787b7b7b7b7b7b7b7b7a6e6255483b2f22150800000000000000000000030c151c23282b2c2c2c2c2c2c2c2a26201911080000000000000000000000000000000007121d27303940464d545a61676d6b64594e4338333e49545f696e6c655e58514b443d362d23180d020000000000000000000000000006121d28333d48525c656e767e868c91969a9c9a989898999b9b98948f89827a726960564c42372c21160b0000000000000000000000000002090f141a1e2225282a2b2c2c2b2a2826221f1a15100a03000000000000000000000000050f1820272d31333434343434343433312d2820180f06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002070b1014171b1e21232527292a2b2c2c2c2c2c2c2b2a28272523201d1a17130f0a0500000000000000000000000000000000000000000000000000000000000000030c141c22272b2c2c2c2c2c2c2c2c2c2c2b29241e170e0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008111920262a2c2c2c2c2c2c2c2c2c2c2c2a26211a12090000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2a2826231f1a150f0902000000000000000000000000000000000000000000000000000000000000000000000000000f1c2935424e5b6771757575757575757572675b4f4336291d1003000713202d3946525e6a7375757575757575756f64584c3f3226190c000000000f1c2935424f5b6875828e9ba8a89c8f82756b737b82898e93989b9ea0a1a2a2a1a09e9b98948f89837c746c645b52483f352a20150b000000000013202c3946525f6c7986929faca99c8f8275695c4f4336291d100300000005111e2a3743505c6976828f9ca8aa9d9184786b5e5245392c1f130600000c1825313d4955616d7985919da8a79c9084796d63584f48423f3d3d3e40454d57616c77838f9ba4a3a094887c7064574b3f3226190d010013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000060e151c21242d3a4653606d79868f8f8f8f8f85786b5e51454c5965727f8c8f8f8f8f8b7e7164574b3e312625221d171008000000000000000000000000000000000000000714212e3a4754616d7a8080808080808080808080838f9ca9b0a3968a7d7063564a3d3023170a00111d2a3744505d6a77849098989898978a7d7063574a3d3024170a0013202c3946535f6c7986888888888888887b6f6255483c2f2215090000000000000000000000030a11171b1e2020202020201f1d1a150e0700000000000000000000000000000000000c18232e39424b51585e656c7279756b60554a3f39444f5a65707a767069635c564f483f342a1e130700000000000000000000000000000b16212b36404a535c656d747b81868a8d909192939392908e8b88837d77706860574e443a30251b1005000000000000000000000000060d141a20252a2e323437383838383735322f2b26211b150e0700000000000000000000020d17212a32393d4040404040404040403e39322a21180f050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004070b0e111417191b1c1d1e1f1f201f1f1f1e1d1c1a181614110e0a070300000000000000000000000000000000000000000000000000000000000000000000020a11171b1e202020202020202020201f1c18130c050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070e151a1d1f2020202020202020201f1e1a150f0800000000000000000000000000000000000000010910161a1e1f202020202020201f1e1c1916130e0a04000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c69768282828282828282776a5d5044372a1d1104000714202d3a4753606d7a82828282828282807366594d4033261a0d000000000e1b2734414d5a6773808d99a6a99d9083776a6970777d83888c8f91939595959493918f8c88837e78716a625a524940362d23190e040000000000121f2c3845525f6b7885919eabaa9d9084776a5d5144372b1e12050000000814212d3946525f6b7884919daaa79b8e8275695c5043372a1d110400000915212d3945515d6975808c97a3aca1958a7f746a6159534e4c4a4a4b4d51575f69737d89949faba79b9084786c6054483b2f23160a000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d20130700000000040b1015202d3a4653606d7986939c9c9c9285786b5e51454c5965727f8c999c9c988b7e7164574b3e31241816120c0600000000000000000000000000000000000000000714212e3a4754616d7a878d8d8d8d8d8d8d8d8d8d8d949fabb0a3968a7d7063564a3d3023170a00111d2a3744505d6a7784909da5a5a4978a7d7063574a3d3024170a0013202c3946535f6c7986939595959595887b6f6255483c2f22150900000000000000000000000000060b0f1213131313131313110e0903000000000000000000000000000000000004111d2935404b545c636970777d847c71665b5146404b56616c7782827b746e67605a50463b2f23170b0000000000000000000000000000050f1a242e38414a535b62696f757a7d8183858686868584827f7b77726c665e564e453c32281e14090000000000000000000000000810171f252b31363a3e41434545454543413e3b37322c261f18110901000000000000000008131e29333c444a4d4d4d4d4d4d4d4d4d4a443c332a21170e050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000205080a0c0e0f111212131313131211100f0d0c0a070401000000000000000000000000000000000000000000000000000000000000000000000000000000060b0f121313131313131313131312100c07010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e111313131313131313131313110e0a0400000000000000000000000000000000000000000000050a0e11131313131313131312110f0d0a06020000000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c6976838f8f8f8f8f8f84776a5d5044372a1d1104000714202d3a4753606d7a878f8f8f8f8f8d807366594d4033261a0d000000000d1926333f4c5865727e8b98a4ab9e9185786b5f666c72777b8082858788888888868582807b77726c665f58504840372e241b1107000000000000111e2b3744515d6a7784909da9ab9e9285786c5f53463a2e2115090000030e1925313d4955616e7a8793a0aca4988b7f73665a4d4134281b0f02000005111d2935404c58646f7b86919ca7a69b91867c736b645f5b58575757595d6269717a858f9aa5aca1968a7f73675c5044382b1f1307000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070000000000000713202d3a4653606d798693a0a99e9285786b5e51454c5965727f8c99a6a4988b7e7164574b3e3124180b06010000000000000000000000000000000000000000000714212e3a4754616d7a87949a9a9a9a9a9a9a9a9a9a9ea6b0b0a3968a7d7063564a3d3023170a00111d2a3744505d6a7784909daab0a4978a7d7063574a3d3024170a0013202c3946535f6c798693a0a2a2a295887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713202c3945515c666e747b82888e83786d62574c46515c67727d888c868079726b62574b3f33261a0d01000000000000000000000000000008121c262f38414950585e64696d71747678797979787775736f6b66615b544c443c332a20160c02000000000000000000000009121a222930373c42464a4d5051525251504e4b47423d37312a231b130a01000000000000000d1924303b454e55595a5a5a5a5a5a5a59554e453c332920170d04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c697683909c9c9c9c9084776a5d5044372a1d1104000714202d3a4753606d7a87949c9c9c9a8d807366594d4033261a0d000000000b1824313d4a5763707d8996a2aca093867a6d615b61666b6f7376787a7b7b7b7b7a7876736f6b66615b554e463e362e251c120900000000000000101d2936434f5c6875828e9ba7ada094877b6f62564a3d32261b1009080b151f2a36414d5965717d8a96a3ada195887c7063574a3e3225190c000000000c1824303c47535e6975808b95a0aaa2988f857d766f6b676563636466696d737b838d96a1aba59a8f85796e62574b3f33271b0f03000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070000000000000713202d3a4653606d798693a0ab9e9285786b5e51454c5965727f8c99a6a4988b7e7164574b3e3124180b00000000000000000000000000000000000000000000000714212e3a4754616d7a8794a1a6a6a6a6a6a6a6a6a6a9acacaca3968a7d7063564a3d3023170a00111d2a3744505d6a7784909daaaca4978a7d7063574a3d3024170a0013202c3946535f6c798693a0acafa295887b6f6255483c2f2215090000000000000000000003060809090909090908060200030608090909090909080602000000000000000000000815222e3b4854616d7880868c93948a7e74695e534d58636e79848f97918a847d74675b4e4135281b0e020000000000000000000000000000000a141d262f373f464d53585d6165686a6b6c6c6c6c6a6966635f5b565049423b322a21180e04000000000000000000000009121b242c343b42484d52565a5c5e5f5f5e5d5a57534e49423c352d251c130a01000000000000101c2935414c576066676767676767676660574e453b32291f160d030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002040507070808080706050301000000000000000000000000000000000000000000000103050607070808080706050402000000000000000000000000000000000000000000000000000000000000000000000000000000000204060708080807070504020000000000000000000000000000000002020202020100000000000000000000000000000000000000000000000000000000000000000000000203050607080808070605030100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002040506070808080707060403010000000000000000000000000000000000000000000000101c2936434f5c697683909ca8a89d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0a8a69a8d807366594d4033261a0d000000000916222f3c4855616e7a8794a0ada295897c6f6356555a5f6367696c6d6e6f6f6e6d6b6967635f5b56504a433c342d241c130b05000000000000000e1b2734414d5a6673808c98a5b0a3978a7e72665a4e42372c221a1615171d27313c47525e6975818d9aa6a99d9185796c6054473b2f2216090000000008131f2b36424d58636e79848e98a2aaa1978f87817b7773717070717275797e858d959fa8a69d93897e73685d51463a2f23170b00000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070000000000000713202d3a4653606d798693a0a09e9285786b5e51454c5965727f8c99a0a0988b7e7164574b3e3124180b00000000000000000000000000000000000000000000000714212e3a4754616d7a8794a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0968a7d7063564a3d3023170a00111d2a3744505d6a7784909da0a0a0978a7d7063574a3d3024170a0013202c3946535f6c798693a0acafa295887b6f6255483c2f2215090000000000000000050b0f131515151515151514120e0b0f131515151515151514120e090300000000000000000815212e3b4754616d78828c969e9b90857a6f645a535e69747f8a95a09b91877c72665a4e4134281b0e02000000000000000000000000000000020b141d252d343b42474d5155585b5d5f5f5f5f5f5e5c5a57534f4a443e38302921180f06000000000000000000000008121b242d363e454c53595e6366696b6b6b6b6967635f5a544d463f372e251c1309000000000000121f2c3845515d697273737373737373726a60574d443b31281f150c0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000105090c0e10121314151514141311100d0b08050100000000000000000000000000000105080b0d0f11131414151514141312100f0c0a0704000000000000000000000000000000000000000000000000000000000000000002060a0d0f111314141515141312100e0c090602000000000000000105090b0d0e0f0f0f0e0d0c0a08060300000000000000000000000000000000000000000000000000000205090c0e10121314141514141312100e0b0805010000000000000000000000000000000000000000000000000000000000000000000000000003070a0c0e10121314141515141312110f0d0b08050200000000000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d000000000714202d3946525f6b7885919eaaa4978b7e7265594c4f53575a5d5f6161626261605f5d5a57534f4a453f38312a23211f1b17110a0200000000000c1925323e4b5764707d8995a2aea69a8e82766a5f54493e342c25222223282f39434d58636e7a86929eaaa5998d8175695d5044382b1f130600000000030e1a25303c47525d67727c869099a1a9a199928c8783807e7d7d7d7f82858a90979fa8a69e958b81776c61574b4035291e120600000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070000000000000713202d3a4653606d7986939393939285786b5e51454c5965727f8c939393938b7e7164574b3e3124180b00000000000000000000000000000000000000000000000714212e3a4754616d7a8793939393939393939393939393939393938a7d7063564a3d3023170a00111d2a3744505d6a77849093939393938a7d7063574a3d3024170a0013202c3946535f6c798693a0acaca295887b6f6255483c2f221509000000000000000810161b1f22222222222222211e1a161b1f22222222222222211e1a150e06000000000000000713202c3845505c66707a848e99a2978c81766b6059646f7a86919c9e94897f756a60564a3e3226190d0000000000000000000000000000000000020b131b232a30363c4145494c4f505253535352514f4d4a47433e39332d261f170f06000000000000000000000006101a242d363f4850575e646a6f73757778787776736f6b655f58514940372e251b1107000000000013202c3946535f6c79818181818181817c72695f564d433a31271e150b02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090d1115181b1d1f2021212121201f1e1c1a1714110d09040000000000000000000004090d1114171a1c1e1f202121212121201f1d1b191613100c0803000000000000000000000000000000000000000000000000000000040a0e1216191c1e1f2021212121201f1d1b1815120e090500000003090d1215181a1b1c1c1c1b1a191715120f0b0600000000000000000000000000000000000000000000050a0e1215181b1d1e202121212121201e1d1a1814110d0804000000000000000000000000000000000000000000000000000000000000000002070b0f1316191b1d1f202121212121201f1e1c1a1815120e0a060100000000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d0000000005111e2a3743505c6975828e9ba7a69a8d8175685c5043474b4e505254555555555452504e4b47433e3b39373432302e2b27221b140b02000000000a16232f3c4854616d7986929eaaaa9f93877b70655a50463e36322f2e303339414a545f6974808b97a2aca195897d7165594d4034281c1003000000000009141f2a35404b56606a747d878f989fa6a49d98938f8d8b8a8a8a8c8e91969ba1a9a39c948c83796f655b50453a2f24180d0100000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070000000000000713202d3a4653606d7986868686868685786b5e51454c5965727f8686868686867e7164574b3e3124180b00000000000000000000000000000000000000000000000714212e3a4754616d7a868686868686868686868686868686868686867d7063564a3d3023170a00111d2a3744505d6a7784868686868686867d7063574a3d3024170a0013202c3946535f6c798693a0a0a0a095887b6f6255483c2f22150900000000000009121a21272c2e2f2f2f2f2f2f2e2b2621272c2e2f2f2f2f2f2f2e2b262018100600000000000004101c28343f4a545e68727c87919b9d93887d7267606b76818c97a0968c82776d63594e44392e22160a000000000000000000000000000000000000010911181f252b3035393d40424445464646454443413e3b37332e28221b140d050000000000000000000000020d18222c363f485159616970757b7f8284858584827f7b76706a625b524940372d23190f040000000013202c3946535f6c79868d8d8d8d8d8d847b71685f554c433930271d140a01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090f14191d2125272a2c2d2e2e2e2e2d2c2b292624211d1915100b05000000000000050b1015191d212426292a2c2d2e2e2e2e2d2c2b2a282523201c18140f0a040000000000000000000000000000000000000000000000040a10151a1e2225282a2c2d2e2e2e2e2d2b2a2725221e1a15100b05080e14191e2124262828282828272524211f1c17110a03000000000000000000000000000000000000060b11161a1e212527292b2c2d2e2e2e2d2c2b292724211d19140f0a040000000000000000000000000000000000000000000000000000000003090e13171b1f2225282a2b2d2d2e2e2e2e2d2c2a292724211e1a16110d07010000000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00000000020f1b2834414d5a66737f8b98a4a99d9184786c5f53473b3e41444647484848484746444143484b4a484643413f3d3a38332d251d1309000000000713202c3845515d6975818d99a5afa3988d81766c62584f48423e3c3b3c3f444b535d66707b86919ca8a79c9084786c6155493c3024180c000000000000030e19242f39444e58626b757d868d959ba1a6a39f9c9998979697989a9da1a6a49f99928a827970675d53493e34291e12070000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070000000000000613202d3946535f6b7679797979797979756a5e51444b58657179797979797979797063574a3e3124170b00000000000000000000000000000000000000000000000714212d3a4753606c7779797979797979797979797979797979797979786e6256493c3023160a00101d2a3643505c69747979797979797979786f63564a3d3023170a0013202c3946535f6c7986939393939393887b6f6255483c2f221509000000000007111b242c33383b3c3c3c3c3c3c3a37312c33383b3c3c3c3c3c3c3a37312a22180f040000000000000c17232e38424c56606b757f89939d998e83786e66717c87929d998f847a70655b51473d32281d11050000000000000000000000000000000000000000060d141a1f24292d303335373839393939383634322f2b27221d17100a0200000000000000000000000009141f29343e48515a636b737a81878b8e919292918f8b87827b746d645b52493f352b20160b00000000121f2c3845515e69747d8790999a9a968d847a71675e554b42392f261d130a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060d141a20252a2e31343638393a3b3b3a3a39373533302d2925201b16100a030000030a10161c2125292d30333537393a3a3b3b3b3a39383634322f2c2824201b15100a030000000000000000000000000000000000000000070e151b21262a2e323537393a3a3b3b3a39383634312e2a26211c1610131a20252a2e313335353535353432302e2b28231c140c03000000000000000000000000000000040b11171c21262a2e31343638393a3b3b3b3a39383633302d2925201b150f090200000000000000000000000000000000000000000000000001080e141a1f23282b2f32343638393a3b3b3b3a3a39373533312e2a26221d18130d0600000000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00000000000c1925323e4a57636f7c8894a0aca094887b6f63574b40343537393b3b3c3c3b3a393b454e5457575452504e4b4947443e372f251b100500000004101c2935414d5965717d88949faba99e93887e746a615a534e4a4848494b50565d656e78828d97a2aca1968b7f73685c5044382c2014080000000000000008121d28323c465059626b747b838a90959a9ea1a3a5a4a4a3a4a5a5a3a09d98938e87807870675e554b41372d22170c010000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d20130700000000000005121e2b37434f5a646b6c6c6c6c6c6c6c6b63594e4248545f686c6c6c6c6c6c6c6c675e53473b2f221609000000000000000000000000000000000000000000000006121f2b3844505b656b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c675d52463a2e211508000f1b2834404c58626a6c6c6c6c6c6c6c6c6c675d52473a2e2215090013202c3946535f6c7986868686868686867b6f6255483c2f22150900000000030e19232d363e444748484848484847423c363e444748484848484847423c342a20160b00000000000006111c26303a444f59636d77818b96a0958a7f746d78838e999c91877d72685e54493f352b20160b0000000000000000000000000000000000000000000002090e14191d212427292a2c2c2c2c2c2b2a2825221f1b16110b0500000000000000000000000000040f1a26303b46505a636c757d858c92979b9a99999a9b98938d867e766d645b51473c32271c1105000000101d2935414d58626b747e87919aa39f968c837970675d544b41382f251c120900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000911181f252b31363a3d4043454647484847474544423f3c3935312c27211b150e07070e151b21272c3135393c3f424445464748484747464543413e3c3834302c26211b150e070000000000000000000000000000000000010a121920262c32363b3e4143454747484847464543403d3a36322d27211b1d242b31363a3d404142424241403f3d3a38342e261e150b0000000000000000000000000000080f161c22282d32363a3d404244464747484747464442403d3935312c26201a130c0500000000000000000000000000000000000000000000050c13191f252a2f34383b3e41434546474748484746454442403d3a36322e29241e18110a030000000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00000000000916222e3b4753606c7884909ca9a4988c8074685c5045392e2b2c2e2f2f2f2e2e36424d575f6463615f5c5a585653504941372d22160b000000000c1925313d4954606c77838e99a4aea49a90867c736b645e5a57555555585b61676f77818a949ea9a69b9085796e62574b3f34281c100400000000000000010b16202a343e475059626a71787e84898e919497989aa0a9a19b989694908c88827c756e665e554c43392f251b1006000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000020f1b27333e49525a5f5f5f5f5f5f5f5f5e5951473d434d565d5f5f5f5f5f5f5f5f5c554c42372b1f13070000000000000000000000000000000000000000000000030f1c28333f49535b5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5c554b41352a1e1205000c1824303b4650595e5f5f5f5f5f5f5f5f5f5c554c41362a1e120600131f2c3946525f6b767979797979797979786d6155483b2f221508000000000915202a353f484f54555555555555534d463f484f54555555555555534d463c32271c100400000000040b11161e28333d47515b656f7a848e989c91867b737e89949e948a80756b61564c42382d231915100a030000000000000000000000000000000000000000000003080d1114171a1c1e1f2020201f1e1d1b1916130f0a050000000000000000000000000000000915202c37424d57626c757e878f979a95908d8c8c8d90949a98908880766d63594e43382d22160b0000000d1925303c465059626c757e88929ba49e958c82796f665d534a41372e241b12080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a121b222a30373c41464a4d4f5153545454545352514e4c4945413d38322d26201911111920262d33383d4145494c4e50525354545454535351504d4b4844403c37322c261f181109010000000000000000000000000000020b131c232b32383d42474a4e5052535454545453514f4d4a46423d38332c26272f363c42464a4c4e4f4f4f4e4d4b4947443f3830271d12070000000000000000000000020a121920272e33393e42464a4d4f5153535454545352514f4c4945413d37322c251e170f070000000000000000000000000000000000000000070f171e242b30363b4044474b4d4f515353545454545352504e4c4946423e3a352f29231c150d0500000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d000000000006121f2b3743505c6874808c98a4a89c9084786d61564b40352b2121222222232f3b47535e6970706d6b69676462605b53493e33271b0f030000000814202c38444f5b66717d88929da7aca2988e867d766f6a666362616264676c7279818a939ca6a99e94897e73685d51463a2f23170b000000000000000000040e18222c353e4750585f666d73787d8285888a8c8e97a3988f8c8a8784817c77716b645c544c433a31271d130900000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000a16212c3740494f5253535353535353524e483f363b444c515353535353535353504b433a30251a0e030000000000000000000000000000000000000000000000000b17222d3741494f525353535353535353535353535353535353535353504a43392f24190d020008141f2a353e474e52535353535353535353504b433a2f25190e0200111e2a37434f5a646b6c6c6c6c6c6c6c6c6c665c5145392d201407000000040f1b26313c47515a606262626262625f584e47515a606262626262625f584e44382d201408000000060e161d2225292c353f49535e68727c86909a978c8279858f9b978c82786e63594f443a302b2825211b140d0400000000000000000000000000000000000000000000000105080b0e1011121313131212100e0c09060300000000000000000000000000000000020e1a26313d48535e69747e879199978f8984817f7f8184898f969a92897f756a60554a3e33271c1004000008141f2a343e47505a636d768089929ca59e948b81786f655c524940362d241a1108000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a131c242d343b42484d5256595c5e6061616161605f5d5b5855524d49443e38312a231b1b232a31383e44494d5255585b5d5f6061616161605f5e5c5a5754514d48433d37312a231b130b02000000000000000000000000010b141d252e353c43494e53575a5d5f60616161605f5e5c5956524e49443e3730313941474d5256595b5b5b5b5b5a585653504a42392e23180c01000000000000000000030b141c242b32393f444a4e5256595c5e5f60616161605f5e5b5955514d48433d3730292119110800000000000000000000000000000000000009111921282f363c42474c5054575a5c5e5f6061616161605f5d5b5956524f4a45403a342e261f170f07000000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d0000000000030f1b2734404c5864707c88949faba195897e72675c51473d332b252222242a35404b57636f7b7c7a787573716f6c655b4f43372b1e120500000004101c27333e4a55606b76818b959fa8aaa0978f88817b7672706f6e6f7073787d848b939ca5aaa1978d82786d62574c4035291e12070000000000000000000007101a232c353e464e555c62686d7175787b7d7f8794a095887f7d7b7874706b666059524a423a31281f150b0100000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d2013070000000000000005101b252e373e43464646464646464645423d362d323a4044464646464646464644403931281e14090000000000000000000000000000000000000000000000000006111b262f373e43464646464646464646464646464646464646464646443f3931271d13080000020e18232c353c4245464646464646464646443f3931281e130800000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5b544a4034291d11040000000915202c37424d58636c6f6f6f6f6f6f6a60554d58636c6f6f6f6f6f6f6a6055493d3024170b0000050f1820282e3235383b3f424c56606a747e89939d9388808b96998f857a70665c5147413e3b3734312c261f160d0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006131f2b37424e5965707b859099968d857e7874727274787d848c959b91877c71665b4f44382c2014080000030e18222c353e48515b646d77808a939ca69d948a81776e645b52483f362c231a1007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008121c252e363e464d53595e6266686b6c6d6e6e6d6d6b6a6765615e59544f49433c352d25252d353c43494f54595e6165676a6b6d6d6e6e6d6d6c6b696664605d59544e49423c352d251d140b02000000000000000000000009131d262f373f474e545a5f6366696b6d6d6e6e6d6c6a6866625e5a554f49423b3a434b52595e62656768686867666562605c544b4035291d11040000000000000000030c151d262e363d444a50555a5e6265686a6c6d6d6e6d6d6c6a6865625d59544e48413a332b231a11080000000000000000000000000000000009121b232b333a41474d53585c606366696b6c6d6d6e6e6d6c6b6a6865625f5b56514c463f383129211910070000000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d0000000000000b17232f3c48545f6b77838f9aa6a69a8f84786e63594f453d36312f2f30353c46515c68738089878482807d7b776c5f5346392d201306000000000b16222d38444f5a646f79838d969fa7a9a199928c87827f7d7b7b7b7d8084898e959da5aaa1988f857b70665b50453a2f24180d01000000000000000000000008111a232c343c434a51575c6165696c6f717a8794a095887b716e6b68645f5a544e47403930281f160d030000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acada09386796d6053463a2d201307000000000000000009131c252c323739393939393939393936322b24282f3438393939393939393938342f281f160c0200000000000000000000000000000000000000000000000000000a141d252d333739393939393939393939393939393939393939393937342e271f150c0100000007111a232b31363939393939393939393938342e271f160c0100000a16212c3740484f52535353535353535352504a42382e23180c000000020e1a26313d48545f6a757b7b7b7b7b7b716558545f6a757b7b7b7b7b7b7165584b3f3225180c00020d17212a32393e4145484b4e515558626d77818b959a8f8b929c92877d73695e5754504d4a4744413d3830281f150a0000000000000001050809090909090909090909080602000000000000000000000000000000000000000000000000000000000000000000000a16232f3b47535f6a76818c97978d847b736d686666686c727a838c96998e83776c6054483c3024180b00000006101a232c363f49525b656e77818a949da69c938980766d645a51483e352c2219100600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006101a242e37404850585e646a6e727577797a7b7b7a79787674716e6a65605a544e473f372f2f373f474e545b60656a6e71747678797a7b7b7a7a79777573706d69645f5a544d463f372f261d140b0100000000000000000007111b252f38414951595f656b6f737678797a7b7b7a797775726e6a66605a544d45424c555d646a6e72747575757473716f6c665c5145392d20140700000000000000020b151e272f3840474e555b61666b6e727577797a7a7b7a7a797774716e69655f59534c453d352c231a1108000000000000000000000000000009121b242d353d444c52585e63686c70737577797a7a7b7b7a79787674726e6b67625d57514a433b332b22190f0600000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00000000000007131f2b37434f5b66727e8995a0aba0958a7f756a61574f47413d3b3b3d40464e58626d79849093918f8c8a84786c5f5346392d2013060000000005111c27323d48525d67717a848d959da4aba49d97928e8b898888888a8c90949aa0a7a7a0988f867d73695f544a3f34291e13070000000000000000000000000008111a222a31383f454b5055595d60626d7a8794a095887b6e625f5c58544f49433d362e271e160d04000000000000000013202c3946535f6c798693a0acaca09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0acaca09386796d6053463a2d2013070000000000000000010a131b21272a2c2c2c2c2c2c2c2c2c2a26211a1e24282b2c2c2c2c2c2c2c2c2b28231d160d04000000000000000000000000000000000000000000000000000000020b131b22272a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2b28231c150d03000000000008111920262a2c2c2c2c2c2c2c2c2c2c2b28231d150d0400000005101a252e373e4346464646464646464646433f3830261c120700000007131f2b37424e5965707b86888888857a7064575965707b86888888857a7064574b3e3225180b0008131e29333c444a4e5154575b5e6164676b6f79838d989a989b948a80756d6a6663605d5a5653504d49423a31271c11050000000001070d11141616161616161616161615120e090200000000000000000000000000000000000000000000000000000000000000000d1a26323f4b57636f7b87939b90857b7269615c59595b6168707a848f9a94887d7165584c4034271b0e0200000008111a242d374049535c656f78828b949ea59b928980766c635a50473e342b22180f0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000020d18222c364049525a626970757a7e82848687888887868583817d7a76716b665f585149413838414951585f666c71767a7d818385868788888786858482807c7975706b655f58514941382f261d13090000000000000000030e18232d37414a535b636a71767b7f828486878887878684827e7b76716c655e574f4a545e676f757a7e8182828281807e7b786d6155483b2f221508000000000000000a141d273039414a525960666c72777b7e81848586878887868583817e7a75706b645e564f473e352c231a100600000000000000000000000007111b242d363f474f565d64696f74787c7f8284868787888787868583817e7b77736e68625c544d453d342b21180e04000000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d000000000000030f1b27323e4a56616d78848f9aa5a69c91877c73696159524d4a4848494c5158606a747f8a95a09d9b988c8074685c4f43372b1e120500000000000b16212c36414b555f68717a838b9399a0a5a9a39e9b989695959596999ca0a5a8a39c958e867d746b61574d43382d23180d01000000000000000000000000000008101820272e343a4045494d5053606d7a8794a095887b6e6155504c48433e38322b241c150c0400000000000000000013202c3946535f6c798693a0a0a0a09386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0a0a0a09386796d6053463a2d201307000000000000000000010910161b1e1f202020202020201f1e1a150f13181c1f20202020202020201f1c18120b040000000000000000000000000000000000000000000000000000000000010910161b1e2020202020202020202020202020202020202020201e1c17120b0300000000000000070e151a1d1f2020202020202020201e1c17120b03000000000009131c252c32373939393939393939393937332d261e140b000000000b17232f3b47535f6a76818d9594897e73685e535f6a76818d9594897e73685e53473b2f23160a000c1824303b454e565a5d6064676a6d7074777a7d818a96a3a49e9285807c797673706c696663605c59544c43382d22160a000000030b12191d2123232323232323232323211e1a140d05000000000000000000000000000000000000000000000000000000000000000f1c2935424e5a6773808c98968a7e74696057504c4c4f565e68727d8994998d8175685c4f43362a1d11040000000008121b242e37414a535d666f79828c959ea49b91887e756c625950463d342a21170e0500000000000000000000000000000000000000000000000000000000000000000000000000000000000009141f29343e48525b646c747b81868a8e91929494949493918f8d8a86827c77716a635b534a42414a535b636a71777d82868a8d8f9193949494949392918f8c8985817c76706a635b534a42382f251b11070000000000000009141f2a353f49535c656d757c82878b8f91939494949392908e8b87827d7770696159515c66707980868b8d8f8f8f8e8c8a887b6f6255483c2f22150900000000000007111c252f39424b535c636b72787d83878b8e9092939494949392908d8a86817c766f68615950473e352c22180d0300000000000000000000050f19232d363f48515961686f757b8084888c8e909293949494949391908d8a87837e79736d665f574e463d332a20160c010000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d000000000000000a16222d3945505b67727d88939ea8a3988e857b736b645e5956555556585d626a727c86919ba6a99e92877b6f63574b3f33271b0f020000000000040f1a242f39434d565f68717981888e949a9ea2a5a7a4a3a2a2a2a3a5a8a5a19d97918b847c746b62594f453b31261c110600000000000000000000000000000000060e151c23292f34393d414753606d7a8794a095887b6e615548403c37322d272019120b030000000000000000000013202c3946535f6c798693939393939386796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693939393939386796d6053463a2d2013070000000000000000000000050a0e11131313131313131313110e0a04070c1012131313131313131312100c07010000000000000000000000000000000000000000000000000000000000000000050a0f11131313131313131313131313131313131313131313120f0b060000000000000000000003090e1113131313131313131313120f0b0600000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2b27221c140c02000000030f1b2734404c58646f7b87929a8e83786d625758646f7b87929a8e83786d62574c42372b1f130700101c2935414c5760666a6d7073767a7d8083878a8d919ba6aea2978f8c8986827f7c7975726f6c69655e554a3e32261a0d0000030c151d24292d2f3030303030303030302e2a251e170e05000000000000000000000000000000000000000000000000000000000000111e2b3744505d6a76838f9b9285796d62574e454040444c56616c7884909d9084776b5e5245392c1f1306000000000009121c252f38414b545d67707a838c969fa39a91877e746b62584f463c332920170c0200000000000000000000000000000000000000000000000000000000000000000000000000000000030e1a25303b46505a646d767e868c92979a9d9fa0a1a1a0a09e9c9996928d88827c746d655d544b4a535c656d747c82888d9296999c9e9fa0a1a1a1a09f9d9b9895918d88827b746d655c544a41372d23180e030000000000030f1a26313c46515b656e7780878d93979b9e9fa1a1a1a09f9d9a97938e88827b736b6259636e78828b92979a9b9c9b9a9995887b6f6255483c2f2215090000000000040e19232d37414b545d656e757c83898e93979a9d9fa0a1a1a1a09f9c9a96928d87817a736b625950473e34291f150a000000000000000000020c17212b353f48515a636b727a80868c9095989b9d9fa0a1a1a1a09f9e9c9a97938f8a857e78716961584f453c32281d13080000000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d0000000000000005111d28343f4a56616c77818c96a1aaa0978e857c756f69666362616265686e747c858e98a2ada3988d81766a5f53473b2f23170b0000000000000008131d27313b444d565f676f767d83898e9296999b9d9e9f9f9f9e9d9b9895918c868079726a625950473d33291f150a000000000000000000000000000000000000030b11181e23282d313a4753606d7a87939393887b6e6155483b302b27211b150f0800000000000000000000000013202c3946535f6c798686868686868686796c5f5346392c20130600000000000000000000000000000000000000000000000000000000000013202c3946535f6c798686868686868686796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010910161a1e1f2020202020202020201e1b17110a020000000006121f2b3744505c6874808c9894897d72665b505c6874808c9894897d72665b50453a30251a0f0300121f2b3844515d697276797c808386898c909396999b9a9fa89f9b9b9895928f8c8885827e7b787570665a4e4235281c0f00000a151e272f353a3c3c3c3c3c3c3c3c3c3c3a36302920170c020000000000000000000000000000000000000000000000000000000000121f2c3945525f6b7885919b8f8276695d51463c34333a44505c6874818e9a9386796d6053473a2d2014070000000000000a131d262f39424b555e68717a848d97a0a39990877d746a61574e453b32281e13080000000000000000000000000000000000000000000000000000000000000000000000000000000008141f2b36424d57626c76808890979ea3a6a7a29f9c9a9a9a9a9c9ea19e99948d867f776e665d53525c656e777f868d94999ea2a6a29e9c9b9a9a9a9b9d9fa2a5a19d98938d867f776e665c53493f352a1f140900000000000814202b37424d58626d77808991989ea3a7a6a19e9b9a9a9a9b9d9f9f99938c857d746b626974808a949da3a6a7a09b999895887b6f6255483c2f22150900000000000a15202b353f49535d666f7780878e949a9fa3a6a3a19f9e9e9e9fa1a4a6a29e98928c857d746b62594f463b31261b1005000000000000000009131e29333d47515a636c757d848b92979ca1a4a3a09d9b9a9a9a9b9c9ea0a4a39f9b96908a827b736a61574e443a2f241a0f0400000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00000000000000000c17222e39444f5a65707a858f98a2a9a0978e87807a7572706e6e6f7174797f868e97a0aaa69b91867b7065594e42362b1f130700000000000000010b151f29323b444d555d646b72787d8286898c8f909192929292908e8c8985807b756e67605850473e352b21170d030000000000000000000000000000000000000000060c12171c212d3a4753606d7a86868686867b6e6155483b2e221b16100a0400000000000000000000000000131f2c3946525f6b767979797979797979766b5f5246392c1f1306000000000000000000000000000000000000000000000000000000000000131f2c3946525f6b767979797979797979766b5f5346392d201306000000000000000000000000000000010407090a0c0c0d0d0d0c0b0a0805030000000000000000000000000000000000000000000000000000000000000000000004090c0d0d0d0d0d0d0d0d0d0c0a060100000001060a0c0d0d0d0d0d0d0d0d0d0b08040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0e1113131313131313131313120f0b060000000000000915222e3b4753606c7884909b8f84786c615553606c7884909b8f84786c61554a3f34291e14090000131f2c3946525f6c798286898c8f9296999c9d98948f8e96a0968f90959a9e9b9895928e8b88858276695c4f4336291c100006111c27303940464949494949494949494947423b32281e1308000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986939a8e8174675a4e41352a2833404d596673808c9994877a6d6154473a2e211407000000000000010b141d27303a434c565f68727b858e97a1a2998f867c736a60574d443a3025190d010000000000000000000000000000000000000000000000000000000000000000000000000000010d1925303c47535e69747e88919aa2a9a9a19b96928f8e8d8d8e8f9194989c9f98918981786f655c5a646e77808991989fa5a59f9a9592908e8d8d8d8e9092969a9ea4a49e98918981786e655b51463c31261b1004000000010d1925313c48535e69747e89929ba3aaa8a09a95918f8d8d8d8e9093969a9e978f867d746a6d7985919ca6aea69d958f8c8b8b887b6f6255483c2f2215090000000005111c27323c47515b656f78818a9199a0a6a6a09b9794929191919395989ca2a8a49d968f877e756b61574d43382d22170b00000000000000040f1a25303a454f59636c757e878f969da3a7a19b9793908e8d8d8d8e8f9194989ca1a7a19b948d857c736960564b41362b20150a00000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d000000000000000006111d28333e49535e68737d879099a2a9a099928b86827e7c7b7b7c7e81858a9098a0a9a69d948a80756a5f54483d31261a0e020000000000000000030d172029323b434b535a60666c7176797d80828485868686858482807c79746f6a645d564e463e352c23190f050000000000000000000000000000000000000000000001070c14202d3a4653606c777979797979776d6154483b2e21150a05000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6b645a4f43372a1e1105000000000000000000000000000000000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6b645a4f43372b1e120500000000000000000000000001060a0e111315171819191a1919181614120f0b07030000000000000000000000000000000000000000000000000000000000030a1015181a1a1a1a1a1a1a1a1a1916120c0500060d1216191a1a1a1a1a1a1a1a1a1815100a030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1824313d4a56636f7b8894978b7f73675b5056636f7b8894978b7f73675b5044392d22170c020000121e2b3844505d6975818d95989b9f9f9b96918c888385919d908484898e92979ca09e9b97948a7e72665a4e4135281c0f000b17232e38424b5255565656565656565656534c443a3025190d010000000000000000000000000000000000000000000000000000000013202c3946535f6c7986939a8e8174675a4e4135292833404c596673808c9994877a6d6154473a2e21140700000000000000020b151e27313a444d566069737c858f98a2a1988e857c72695f564c41362a1e1105000000000000000000000000000000000000000000000000000000000000000000000000000005111d2935414d58646f7a85909aa3aca89f97908a8683818181818385888c91969c9b938a81776e64626c768089929ba3a9a19a948e89868381818181828486898e9399a0a7a29b938a81776d62584d42372c21150a00000005111d2935414d5964707b86919ba4ada79e968f8985828181818284868a8e9399988f867c72717d8a96a2ada99e948b84807e7e807b6f6255483c2f221509000000000b16222d38434e59636d77818a939ba3aaa29b958f8b888584848486898c91969da4a8a19890877d73695f54493e33281c11050000000000000a15202b36414c57616b757e889099a0a8a49c96908b878482818181818385888b90969ca3a69f978e857b72675d52483d32261b0f04000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d0000000000000000000b16212c37424c57616b747e879098a0a7a39d97928e8b898888898a8d91969ba2aaa59d948b82786d63584d42372c20150900000000000000000000050e172029313941484f555b61656a6d707375777879797978777573706c68645e58524b443c342c231a11070000000000000000000000000000000000000000000000000005121f2b37444f5b656b6c6c6c6c6c6c665c5145382c201307000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5a52483e32261a0e020000000000000000000000000000000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5a52493e33271b0f020000000000000000000002080d12161a1d2022242526262626262423211e1b18130f09040000000000000000000000000000000000000000000000000000050e151c212527272727272727272725221d17100811181e222527272727272727272624211b150d05000000000000000005090c0d0d0d0d0d0d0d0d0d0c09050000000002070a0c0d0d0d0d0d0d0d0d0d0b0803000000000000000000000000000000000000000000000d1a2733404c5965727e8b9794877b6f63574c5965727e8b9794877b6f63574b423b32281e13080000101c2834404c5965717d8995a19d98948f8a85817c7885929d9084787d82868b9094999e9e92867a6e62564a3d3125190d000f1b28333f4a545d626363636363636363625e564c41362a1e110500000000000000000000000000000000000000000000000000000000121f2c3945525f6b7885919b8f8275695d51453b33333a444f5b6874818d9a9386796d6053473a2d2014070000000000000000030c151f28323b444e57606a737d869099a2a0978e847b71685e52463a2d21140700000000000000000000000000000000000000000000000000000000000000000000000000000815212d3945515d6975818c97a2aca99f968d857f7a767473737476787c80858b91989c938a80766c69747e88929ba4a9a0978f89827d79767473737475777a7d82878e959da6a49c92897e746a5f54493d32261b0f0300000815212d3a46525e6a75818c97a2ada89e958c847d797574737475777a7e83888e95988e847a74818d99a6b0a3988c827973717273746c6054473b2e21150800000005111c28333e4a55606a757f89939ca5a9a0989089847f7b79777778797c80858b929aa2aaa2998f857b71665b5044392d22160a0000000000040f1b26323d48535e68737d87919aa2aba29a928b847f7b77757473737476787b80858b9299a1a9a0978e84796f64594e43372c201509000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00000000000000000005101b25303a454f59626c757e868e969da3a8a29e9a979695959597999da1a7a7a19a938b827970665c51473c31261b0f040000000000000000000000050e171f272f373d444a5055595d616466696a6b6c6c6c6b6a696664605c58534d474039322a221a11080000000000000000000000000000000000000000000000000000030f1b27333e49535a5f5f5f5f5f5f5f5b544a3f34281c1004000000000000000000000000000000000a16212c3740484f525353535353535353524f4840372c21160a000000000000000000000000000000000000000000000000000000000000000a16212c3740484f525353535353535353524f4940372c21160a00000000000000000000070d13191e2226292c2f30323333333332312f2d2b27241f1a150f08010000000000000000000000000000000000000000000000050e1720272d31333434343434343433322e29221a121a22292e32343434343434343433312c261f170d040000000000040b1115181a1a1a1a1a1a1a1a1a1916110c0500070d1317191a1a1a1a1a1a1a1a1a17140f090200000000000000000000000000000000000000000f1c2835424e5b6874818d9a9184786b5f56535b6874818d9a9184786b5f56534c443a3025190d01000c1824303c4855616d79859196918c88837e7975707986929e91847771767a7f84888d92968e82766a5e5245392d21150900121e2b3744505c666e6f6f6f6f6f6f6f6f6f685e52463a2d21140700000000000000000000000000000000000000000000000000000000111e2b3744515d6a76838f9c9185796d62574d443f3f434c55606c7884909c9184786b5e5245392c1f1306000000000000000000030d162029323c454e58616b747d87909aa3a0968d847a6e6255483b2f22150900000000000000000000000000000000000000000000000000000000000000000000000000000b1824313d4955626e7a86929da8ada2978d847b736e6a68676768696c6f747980868e969b92887e736f7a85909aa4aaa0978e857e77716d6a68676767686a6d71767c838b949da6a49b90867b70655a4e43372b20140800000b1824313d4956626e7a86929ea9ada1978c837a726d69676767686b6e72777d838a92968c8176838f9ca8ac9f93877b706764656768635a4f44382c1f13060000000a16212d39444f5b66717c87919ba5aba1978e867e78736f6c6b6a6b6d70747a8188909aa3aba1978d82776c61554a3e33271b0f03000000000914202c37434e59646f7a858f99a2aca29990888079736e6b6867676768696c6f747980878f98a1a99f958b81756a5f54483d3125190e020000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d0000000000000000000009141e29333d47505a636c747c848b92979da1a5a7a4a2a2a2a2a4a6a7a4a09b969089817970675e544a3f352a1f140900000000000000000000000000050d161d252c33393f44494d5155585a5c5d5e5f5f5f5f5e5c5a5754504c47423c362f2820181008000000000000000000000000000000000000000000000000000000000b16222d3741494f525353535353524f4a42382e23180c000000000000000000000000000000000005101a252e373e4346464646464646464646433e372e251a10050000000000000000000000000000000000000000000000000000000000000005101a252e373e4346464646464646464646433e372e251b10050000000000000000020a11181f242a2e3236393b3d3e3f4040403f3e3c3a3734302b26201a130c04000000000000000000000000000000000000000000040d17202931383d4040404040404040403e3a332c231b242c343a3e4040404040404040403d3831291f160b00000000060e161c212527272727272727272725221d170f0911191e232627272727272727272624201a130c0300000000000000000000000000000000000000101d2a3743505d6976838f9b8e82756963625e5d6976838f9b8e82756963625e564c41362a1e1105000814202c3844515d6975818d8a85817c77726e696c7986939e9185786b6a6f73787c81868a8a7e7266594d4135291d11050013202c3946535f6c787c7c7c7c7c7c7c7c7a6e6255483b2f22150900000000000000000000000000000000000000000000000000000000101c2935424e5b6773808c98968a7e73695f564f4c4c4f555e67727d8894998d8175685c5043372a1d110400000000000000000000040e17202a333c464f59626b757e88929ea89f95887b6f6255483c2f22150900000000000000000000000000000000000000000000000000000000000000000000000000000e1a2733404c5965727e8a96a2aea89c91867b7169625e5b5a5a5b5d6063686e757c848c959a8f857a76818c97a1aca2988e857b736c66615d5b5a5a5a5c5e61656b7279818a949ea8a2988d82766b5f54483c3024180b00000e1a2733404c5965727e8a96a2aea79c90857a7068615d5a5a5a5c5e62666b727980899193887d84919eaaa99c9084776b5f58585a5b5851483e33271b0f030000020e1a26323e4a55616c77838e98a3ada3998f857c746d6763605e5d5e6064686f767e88919ca6a99f94897d72665b4f43372b1f1307000000010d1925313d48545f6b76818c96a1aba59a90877e766e68635f5c5a5a5a5b5d5f63686e757d868f99a3a79d92877c7065594e42362a1e11050000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00000000000000000000020c17212b353e48515a626a727980868c9195989b9d9e9f9f9f9e9c9a97948f8a857e776f675e554c42382e23190e030000000000000000000000000000040c131a21282d33383d4145484b4d4f515252535252514f4d4b4844403b36312b241d160e06000000000000000000000000000000000000000000000000000000000005101b252f373e4346464646464646433f382f261c110600000000000000000000000000000000000009131c252c32373939393939393939393937322c251c130900000000000000000000000000000000000000000000000000000000000000000009131c252c32373939393939393939393937322c251c13090000000000000000040c141c232a30353a3e4245484a4b4c4c4d4c4c4a494643403c37312b251e160e0500000000000000000000000000000000000000030d161f29323b43494d4d4d4d4d4d4d4d4d4a453e352b232d363e464b4d4d4d4d4d4d4d4d4c49433b31271d11060000050f1820272d31333434343434343433322e282119131b232a2f32343434343434343433302b251e150c02000000000000000000000000000000000000121e2b3844515e6b7784919a8d81736f6f6f685e6b7784919a8d81736f6f6f685e52463a2d2114070004101c2834404c5965717d837e7975706b6662606d7a86939f9285786c5f63676c71757a7e837a6d6155493d3125190d010013202c3946535f6c7986898989898989887b6f6255483c2f221509000000000000000000000000000000000000000000000000000000000d1a26323f4b57636f7b87939b90857a7168615b59585b60677079838e9994897d7165594c4034271b0f0200000000000000000000020b151e27313a444d57606a737c86919eaaa195887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000000000000000000000000000101c2936424f5b6874818d9aa6afa3978b8074695f57514e4d4d4e5053585d636a727a838d96978c817b87929da8a69b90867c7269615b55514e4d4d4e4f51555a60676f78828c969f9c9893877c7064584c4033271a0d0100101c2936424f5b6874818d9aa6afa3978b7f73685e56504e4d4e4f52555a60676e767f88928f8485929faba79a8e8174685b4f4c4e4f4c463f362c21160b00000007131f2b37434f5a66727d89949faaa89d92877d736a625b565351515254585d646c75808a95a0aca59a8f83776b5f53473b2f23160a00000006121e2a36414d5965707c87929da8a99e93897e756c645d57524f4e4d4d4e5053575d636b747d87919c9e9a978d82766a5e5246392d2014070000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d0000000000000000000000050f19232c363f48505860686f757b8085898c8f909292929291908e8b88847e79736c655d554c433a30261c120700000000000000000000000000000000010910161c22282d3135393c3f41434445464646454443413e3b3834302b251f19130c040000000000000000000000000000000000000000000000000000000000000009131d252d33373939393939393937332d261d140a00000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2a26211a130a01000000000000000000000000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2a27211b130a0100000000000000040d161e262e353b41464a4e525456585959595958575553504c48423d362f2820170f050000000000000000000000000000000000030c151f28313b444d55595a5a5a5a5a5a5a5a5650473d322c353f4850575a5a5a5a5a5a5a5a59544d43392e22170b00020d17212a32393d4040404040404040403e39332b221b252d353b3f40404040404040403f3c372f271e140b020000000000000000000000000000000000121f2c3845525f6b788592998c807c7c7c7a6e626b788592998c807c7c7c7a6e6255483b2f22150900000c1824303c4854616d7777726e69645f5b56616d7a87949f9286796c5f575b6065696e737774695d5145392d211509000013202c3946535f6c7986939696969695887b6f6255483c2f221509000000000000000000000000000000000000000000000000000000000a17232f3b47535f6b76828d98978d837a726c676565676b7179828b95998e83786c6055493c3024180c00000000000000000000010a141d273039434c565f69727c858f98a2a2988f857b6f6255483c2f2215090000000000000000000000000000000000000000000000000000000000000000000000000000111e2b3744515d6a7783909ca9aca094877b6f63584d464240404244474c52586068717a858f999388818c98a3aba0958a7e746a6057504945424140414245494e555d66707a859093908c89858174675b4e4134281b0e0100111e2b3744515d6a7783909ca9aca093877b6e63574c4541404143454a4f555c646d76808a948e8f97a2aea6998c8073665a4d404142403b352d241a10050000000a17232f3b47535f6b77838e9aa5aea2978b80756b6158504a47454445484c525a646e78848f9ba7ab9f94887c7063574b3f32261a0d0100000916222e3a46525e6a75818d98a4aea3978c81776c635a524b46434140414244474c5259626b75808a95918e8a87837a6e6154483b2e2115080000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00000000000000000000000007111a242d363e474e565d646a6f74797c808284858686858483817e7b77736e68625b534b433a31281e140a00000000000000000000000000000000000000050b11171c2125292c2f323436373839393938383634322f2c28241f1a140e08010000000000000000000000000000000000000000000000000000000000000000010b131b21272a2c2c2c2c2c2c2c2b27221c140b020000000000000000000000000000000000000000010910161a1e1f20202020202020201f1e1a161009010000000000000000000000000000000000000000000000000000000000000000000000010910161a1e1f20202020202020201f1e1b1610090100000000000000020c161f2830383f464c52575b5e616364656666666564625f5c58534e48413a322921170e04000000000000000000000000000000020b151e27313a434d565f65676767676767676661594e4337353e47515a626667676767676767655f554a3f33271b0e0008131e29333c444a4d4d4d4d4d4d4d4d4d4a453d342b232d373f464b4d4d4d4d4d4d4d4d4c48413930261d140a0100000000000000000000000000000000131f2c3946525f6c7986929b90898989887b6f626c7986929b90898989887b6f6255483c2f22150900000814202c3844505b656c6b67625d58544f55616e7b8894a09386796d60535054595d62676b6a62584d4135291d1105000013202c3946535f6c798693a0a3a3a295887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000000007131f2b37434e5a65707b86909a958c847d7874727274777c838b949b91877d72675b5044382c2014080000000000000000000009131c262f39424b555e68717b848e97a1a39990867d736a5f53473a2e2114080000000000000000000000000000000000000000000000000000000000000000000000000000121f2c3945525f6b7885929eabaa9e9185786b5f53473b35343435373b40474e565f69727d8892998f8b929da9a69b8f84786d62584e453e393534343436393d444b545e68737e8a8783807c79756f65594d4034271a0e0100121f2c3945525f6b7885929eabaa9e9185786b5f52463a35343436393e444b525b646e78828d989ba0a9b2a6998c7f7265594c3f3535332f2a231b1208000000010e1a26333f4b57636f7b87939faba99d91857a6f64594f463f3a3837383b4148525c67737e8a96a2a6a4988c8073675b4e4235291c100300000d1925323e4a56626e7a86929ea9a99d91867b70655b5148403a3634343435373b40475059636e79848985827e7a77736a5f53463a2d2114070000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d0000000000000000000000000008121b242c353d444b52595e64686d7073757778797979787674726f6b67625d575049413931281f160c02000000000000000000000000000000000000000000060b1015191d20232628292b2c2c2c2c2c2b292825231f1c18130e09030000000000000000000000000000000000000000000000000000000000000000000000010910161b1e202020202020201e1b17110a020000000000000000000000000000000000000000000000050a0e1113131313131313131313110e0a05000000000000000000000000000000000000000000000000000000000000000000000000000000050a0e1113131313131313131313110e0a050000000000000000000a141e28313a424a51585d62676a6d6f717273737372706e6c68645f59534b443b332920160c0100000000000000000000000000010a141d273039434c565f687173737373737373736b5f53473a3d475059626c737373737373737371675b4f43362a1d10000d1924303b454e55595a5a5a5a5a5a5a5a564f463d342a343f4951575a5a5a5a5a5a5a5a58534b42392f261c130a0000000000000000000000000000000013202c3946535f6c798693a099969695887b6f626c798693a099969695887b6f6255483c2f221509000004101c28343f4a535b5f5f5b56514c484855626f7b8895a094877a6d615447484d52565b5e5e5950473c3025190d01000013202c3946535f6c798693a0acafa295887b6f6255483c2f22150900000000000000000000000000000000000000000000000000000000030f1a26323d49545f6a747e88919a968f8984817e7e8083888e959b928980756b60554a3f33281c100400000000000000000008121b252e38414b545d67707a838d96a0a49a91877e746b61584d42372b1e1206000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986939faca99d9083766a5d5044372a2727282b2f353c444d57616b76818c989a979ba4aea2968a7e72675c51463c332d29272728292d3239424c57626e797e7a7774706d69655d53483d3124180c000013202c3946535f6c7986929facaa9d9083766a5d5044372a27272a2d32394049525c66717b87929da9b2b2a6998c7f7265594c3f322827241f1811090000000004111d2a36424f5b6773808c98a4b0a4988c8175695d52473d342e2b2b2c3036404b56626e7a86939a9a99988f83766a5d5144382b1f12050004101c2935424e5a66727e8b97a3aea4988c8175695e53493f362f2a282727282b2f363e47515c6874807c7975726e6b6762594e43372b1e12050000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d000000000000000000000000000009121a232b323a41474d53585c606466696a6b6c6c6c6b6a6866635f5b56514b453e372f271f160d0400000000000000000000000000000000000000000000000004090d101417191b1d1e1f1f201f1f1e1d1b191613100c0703000000000000000000000000000000000000000000000000000000000000000000000000000000050a0f1113131313131313120f0b0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007111c26303a434c545c63696e73777a7c7e7f8080807e7d7b7874706a645d564d453b32281d1308000000000000000000000000000a131d262f39424b555e68717a818181818181817b6f6255483c464f59626b757e81818181818181776a5d5144372a1e1100101c2935414c576066676767676767676661584f453c333a45515b636767676767676767645d544b41382e251c120900000000000000000000000000000013202c3946535f6c798693a0a5a3a295887b6f626c798693a0a5a3a295887b6f6255483c2f2215090000000c17232d3841495053524f4a45413c4955626f7c8995a194887b6e6154483c41464a4f52514d473e352a1f140800000013202c3946535f6c798693a0acafa295887b6f6255483c2f22150900000000000000000000000000000000000000000000000000000000000a15212c37424d58626c767f8890989a94908d8c8c8d8f949999918981776d64594f44392e22170b00000000000000000007111a242d37404a535d666f79838c959fa49b92887e756c62594f463c31261a0e02000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798693a0aca99c908376695d5043362a1d1a1c1f242a323b454f5964707b87929ea4a7adaa9e9286796d62564a3f342a221c1a1a1b1d2127303a45515d6871726e6b6764605d59544b42372c201408000013202c3946535f6c798693a0acaa9d908376695d5043362a1d1b1d21272f37404a545f6a75818c98a4b0b2a6998c7f7265594c3f32261a17130d0700000000000714202d3945525e6b7783909ca8ada194887c7064584c41362b231f1e1f242e3a46525e6a77838e8e8d8c8b8a85796c6053463a2d2013070007131f2c3845515d6a76828f9ba7aca094887c7064584d42372d241e1b1a1a1c1f242c35404b57636d73706c6965625e5b5750473c32261a0e020000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1d1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00000000000000000000000000000008111921282f363c42474c5054575a5c5e5f5f5f5f5e5d5b5956534f4b46403a342d251d150d040000000000000000000000000000000000000000000000000000000104070a0c0e1011121313131211100e0c0a07030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000407080909090909080705010001050708090909090908070401000000000000000000000000000000000407080909090909080705010000000000000000000000000000000000000000000000000000020d18232e38424c555e666d747a7f8386898b8c8c8c8c8b8a8784817b766f675f574d44392f24190e03000000000000000000000009121c252f38414b545d67707a838c8d8d8d8d8d887b6f625548454e58616b747d878d8d8d8d8d8d84776a5d5144372a1e1100121f2c3845515d697273737373737373726a61574e453b3d4a56626d73737373737373736f665d534a40372e241b1208000000000000000000000000000013202c3946535f6c798693a0acafa295887b6f626c798693a0acafa295887b6f6255483c2f22150900000006111c262f383f444646433e3a353d4956636f7c8996a295887b6e6255483c353a3e434545413c352c23190e0300000013202c3946535f6c798693a0acaca295887b6f6255483c2f221509000000000000000000000000000000000000000000000000000000000004101b26313c46505a646d767e868d93989b9a9898999c98948e8780776e655c52483d32271c11060000000000000000071019232c363f49525c656f78828b959ea59c928980766c635a50473d342a20150900000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929facaa9d9084776a5d5144382b211c1917192029333d48535e6a76828e9aa6b2b3a79b8e8276695d5145392e2322222222222222222935414c57606565625e5b5854504d49423930251b0f04000013202c3946535f6c7986929facaa9d9084776a5d5144382b1f1a17161d252e38434d5964707b87939fabb2a6998c7f7265594c3f3226190c07020000000000000a16232f3c4855616e7a87939facaa9d9185786c6054483c3024191211131d2936424f5b6874818281807f7e7d7d796d6053473a2d201407000916222f3b4854606d7986929eaba99d9084786b5f53483c30252222222222222222232f3b46515b636664605d5956524f4b453e352b20150a000000101c2936434f5c697683909ca9aa9d9084776a5d5044372a1e1104000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d00000000000000000000000000000000070f161d242b31363b4044484b4d4f515252535252504f4d4a47433f3a352f29221b130c0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002070c0e1010101010100f0d09090d0f1010101010100e0b070a0e101010101010100d0a05000000000000000000000000000000000000070c11141515151515151514110d080d11141515151515151514110c0700000000000000000000000000070c11141515151515151514110d080100000000000000000000000000000000000000000000000008131e2a353f4a545e6770787f858b8f93959798999999989694918c87817971695f564b41362b1f14080000000000000000000008121b242e37414a535d666f79828c959a9a9a92887f756c6054474e57616a737c868f999a9a988e857b72685c5043362a1d100013202c3946535f6c79818181818181817c736a60574d443e4b5865717e81818181818181786f655c524940362d241a11080000000000000000000000000013202c3946535f6c798693a0acaca295887b6f626c798693a0acaca295887b6f6255483c2f221509000000000a141d262d3337393937322e303d4a5763707d8a96a095897c6f6255493c2f2e3336383835312b231a11070000000013202c3946535f6c798693a0a0a0a095887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000000000000a141f2a343e48525b646c747b82878c8f919292918f8c88827c756d655c534a40362b21160b0000000000000000060f19222b353e48515b646e77818a949da69d938a80776d645b51483e352b22180e03000000000000000000000000000000000000000000000000000000000000000000000000000000121f2c3845525e6b7885919eabab9e9285796c6054483c322c2825232221212c37424e5965717d8a96a3afb1a4988b7f72665a4d41352e2e2e2e2e2e2e2e2e2e2e303a454e55595956524f4b4844413d3730271e140a010000121f2c3845525e6b7885919eabab9e9285796c6053473b312a262422212126313c48535f6b77838f9ca8b2a6998c7f7265594c3f3226190c00000000000000000c1825313e4b5764707d8996a2afa79a8e8275695c5044372b1f1308040e1a2733404c59657076757473727271706e675c5144382c1f1306000b1824313e4a5763707c8995a1aea69a8d8174685c4f43372e2e2e2e2e2e2e2e2e2e2e2e3540495157595754504d4946423f3a342c23190f05000000101c2936434f5c697683909ca9aa9e9184776b5e5145382b1f1205000714202d3a4753606d7a8794a0ada69a8d807366594d4033261a0d0000000000000000000000000000000000040c131920252b3034383c3e41434445464646454442403d3a37332e29241e17100902000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004060707070707070707050200000000000000000000060d13181b1d1d1d1d1d1d1c191515191c1d1d1d1d1d1d1b1713171a1c1d1d1d1d1d1c1a16110b030000000000000000000000000000020b12181d2022222222222222201d1913181d2022222222222222201d18120b03000000000000000000020b12181d2022222222222222201d19130c0400000000000000000000000000000000000000000000010d1824303b46515c667079828a91969b9c97949291919193959a9d98928b837b71675d52473c3025190d01000000000000000007111a242d364049525c656f78828b949ea59c928980766d635a4f4d566069737c858f98a1a2988f867c736960564b4034271b0f0013202c3946535f6c79868d8d8d8d8d8d857c72695f564d434b5865717e8a8d8d8d8d8d8a81776e645b52483f362c231a100700000000000000000000000013202c3946535f6c798693a0a0a0a095887b6f626c798693a0a0a0a095887b6f6255483c2f22150900000000020b141b22272b2d2c2a2724313e4a5764717d8a939393897c6f6356493d3023272a2c2b292520191108000000000013202c3946535f6c7986939393939393887b6f6255483c2f221509000000000000000000000000000000000000000000000000000000000000030e18222c364049525a626a70767b80838586868583807c77716a635b534a41382e241a0f0400000000000000050e18212b343d47505a636d768089939ca69e948b81786e655b52493f362c2319100600000000000000000000000000000000000000000000000000000000000000000000000000000000111e2a3744505d6a76838f9ca8ada195887c7064594e443d383432302f2e2d2d313d4955616e7a8793a0acafa296897c7063574a3e3b3b3b3b3b3b3b3b3b3b3b3b3b3b3c43494c4c4946423f3b3b3b3b38332d251c13090000111e2a3744505d6a76838f9ca8ada194887b6f63584d433b3633312f2e2d2d2d37434f5b6773808c99a5b2a6998c7f7265594c3f3226190c00000000000000000e1a2733404d5966727f8c98a5b1a5988c7f7266594d4034281b0f03000b1824303c48545e666968676766656463625d554b4034281c1004000d1a2633404c5965727e8b98a4b0a4978b7e7265594c403b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3f464b4c4b4844413d3b3b3b3a36302921170d030000101c2936434f5c697683909ca9ab9f9285796c5f53463a2d201408000714212e3a4754616d7a8794a0ada69a8d807366594d4033261a0d00000000000000000000000000000000000001080e141a1f24282c2f323436383939393938373533312e2b27221e18120c060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001070c10131414141414141414120f0a04000000000000000811181f2427292a2a2a2a2a2825202125282a2a2a2a2a2927231e2227292a2a2a2a2a2926221c150d04000000000000000000000000020c141c23292d2f2f2f2f2f2f2f2d29241e24292d2f2f2f2f2f2f2f2d29231d150c0300000000000000020c141c23292d2f2f2f2f2f2f2f2d29241e160d0400000000000000000000000000000000000000000005111d2935414c57636d78828b949b9d96908b888584848586898e949b9d958d83796f64584d41362a1e12060000000000000007101a232c363f48525b646e77818a949da69d938a81776d645b514c565f68727b858e97a1a29990867d736a61574e443a2f23170b00121f2c3845525e6a747d8790999a9a978e847b71685f554c4a56636e77818a949a9a9a938980766d645a51483e352c22191006000000000000000000000013202c3946535f6c7986939393939393887b6f626c7986939393939393887b6f6255483c2f2215090000000000020a11171b1e20201e1b25313e4b5764717e86868686867d7063574a3d30241b1d1f1f1d19140e0700000000000013202c3946535f6c7986868686868686867b6f6255483c2f2215090000000000000000000000000000000000000000000000000000000000000006111b242e37404850585f656b6f7376787979787673706b666059514941382f261c120800000000000000040d17202a333c464f59626c757f88929ba59e958c82786f665c534940362d241a110700000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2935424e5b6774808c99a5b1a4988c81756a60564f4944413e3d3b3a3a3a393946525f6b7885919eabada194877a6e61554848484848484848484848484848484848484848484848484848484847443f372e251a0f04000f1c2935424e5b6774808c99a5b0a4988c8074695f554d47423f3d3c3b3a3a39393f4b5864717d8a97a3b0a6998c7f7265594c3f3226190c00000000000000000f1c2835424e5b6874818e9aa7afa3968a7d7064574a3e3125180c00000814202c37424c545a5c5b5b5a5958575655524b43392e23180c00000f1b2835414e5b6774818d9aa6afa295897c6f63564a4848484848484848484848484848484848484848484848484848484846413b33291f14090000101c2936434f5c697683909ca9ada094877b6e6155493c3024170c000814212e3b4754616d7a8794a1aea69a8d807366594d4033261a0d000000000000000000000000000000000000000003090e13181c202325282a2b2c2c2c2c2b2a292725221e1b17120d070100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040c13181d2021212121212121201e1b160f08000000000007111a222a303436363636363635312c2c3135363636363636342f292e3336363636363635322d271f160d0300000000000000000000000a141e262e34393b3c3c3c3c3c3b39352f282f35393b3c3c3c3c3c3b39352e271e140a000000000000000a141e262e34393b3c3c3c3c3c3b39352f281f160c0100000000000000000000000000000000000000000915222e3a46515d69747f8a949d9d948b857f7b797777787a7d8289929b9f958b8075695e52463a2e221509000000000000060f19222c353e48515a646d768089939ca69d948b81786e655b524c555e68717a848d97a0a39a90877e746b61584f453c32281d120700111d2936424d58626b757e87919aa4a0968d847a71675e544b525c656f78828b949ea59b928980766c635a50473e342b22180f060000000000000000000013202c3946535f6c7986868686868686867b6f626c7986868686868686867b6f6255483c2f22150900000000000000060b0f121313111825313e4b576470797979797979786f63564a3d302317111212100d090300000000000000131f2c3946525f6b767979797979797979786d6155483b2f221508000000000000000000000000000000000000000000000000000000000000000009121c252e363e464d545a5f6367696b6c6c6b6a67645f5a554e473f372f261d140a00000000000000030c161f29323c454e58616b747e87919aa49f968c837970665d544a41372e241b12080000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1a26333f4c5864707d8995a1aca99d92877c7268605a54504d4b4948474746464646505d6a7784909daaac9f9386796c60555555555555555555555555555555555555555555555555555555555554504940362c211509000d1a26333f4b5864707d8995a1aca89c91867b70675f58524f4c4a484747464646464956626f7c8996a2afa6998c7f7265594c3f3226190c0000000000000000101d2a3643505d6976838f9ca9aea195887b6f6255493c2f23160a0000040f1b26303a42494e4f4f4e4d4c4b4b4a4946413a31271d12070000101d293643505c6975828f9ca8ada094877a6e61555555555555555555555555555555555555555555555555555555555555524c453b31261b0f0300101c2936434f5c697683909ca9afa3968a7d7164584c4034281d120b0915222f3b4855616e7b8894a1aea6998c807366594d4033261a0d0000000000000000000000000000000000000000000003070c101316191b1d1e1f1f201f1f1e1c1a1815120f0a06010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d161d24292c2e2e2e2e2e2e2e2d2b27211a1209000000030e19232c343b40434343434343413d36373d41434343434343403b34393f424343434343423e3931281f150a0000000000000000000006111c26303840454848484848484846413a313940454848484848484845403930261c1106000000000006111c26303840454848484848484846413a31281e130800000000000000000000000000000000000000000c1925313e4a56626e7a85919b9f958b8179736f6c6b6a6b6d71778089949f9d92867a6e62564a3d3125180c0000000000050f18212b343e47505a636c768089929ba59e958b82786f665c534b545e67707a838d969fa49a91887e756b62594f463d332a21160c01000d1925313c465059626c757e88929ba49f958c837970665d544a535d666f79828c959ea49b91887e756c625950463d342a21180e05000000000000000000131f2c3946525f6b767979797979797979786d616b767979797979797979786d6155483b2f221508000000000000000000030506060a16232f3c48535e686c6c6c6c6c6c6c675d52473a2e22150900000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c665c5145392d2014070000000000000000000000000000000000000000000000000000000000000000000a131c242c343c42494e53575a5d5e5f5f5f5d5b58544f49433c352e251d140b02000000000000000a151e28313b444e57616a737d879099a3a0978d847a71675e554b42382f251c1209000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1723303c4854606c7884909ba6aea3988e847a726b65605d5a585655545353535252525d697683909daaab9e9285786b616161616161616161616161616161616161616161616161616161616161605b52483d32261a0d000b1723303c4854606c7884909ba6ada2978d83797169635e5b5856555453535353525255626f7b8895a2afa6998c7f7265594c3f3226190c0000000000000000111e2b3844515e6a7784919daaada093877a6d6154473a2e21140800000009141e2831383e4243424140403f3e3d3c3a352f281f150b010000111e2b3744515d6a7784909daaaca09386796d616161616161616161616161616161616161616161616161616161616161615e574d42372b1f130700101c2936434f5c697683909ca9b2a5998d8174685c5045392e241c17161723303d4956636f7c8995a2afa6998c7f7266594c403326190d0000000000000000000000000000000000000000000000000004070a0c0f1012121313131211100e0c09060200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020c161f282f35393a3a3a3a3a3a3a3a37322c241b110700000914202b353e464c4f50505050504d484141494e50505050504f4c453d444a4f50505050504e4a433a31261b10040000000000000000000b17222d38424a5155555555555555524b433a424b5155555555555555514b42382e23180d02000000000b17222d38424a5155555555555555524b433a2f24190e03000000000000000000000000000000000000000f1c2835414d5a66727e8a96a2998e83786f6863605e5d5e61666d77828d99a3978b7e7266594d4034271b0e00000000050e17212a333d465059626c757e88919ba49f958c837970665d544a545d667079838c959fa49b92897f766c635950473d342b21180f05000009141f2a343e47505a636d768089929ca59e958b82786f665c534b545d67707a838c969fa39a91877e746b62584f463c332a20170e040000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c665c646b6c6c6c6c6c6c6c6c6c665c5145392d2014070000000000000000000000000007131f2b37424d565c5f5f5f5f5f5f5f5c554c41362a1e1206000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5b544a4034291d1104000000000000000000000000000000000000000000000000000000000000000000010a121b222a31373d42474b4e5052525252504e4b47433e38322b231c130b020000000000000006111c26303a434d566069737c868f98a2a1988e857b72685f554c433930261d130a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000714202c3844505c68737e8a959fa9aa9f968c847d76716c69666463616160605f5f5f5f5e697683909daaab9e9184776e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6c645a4e4236291d10000714202c3844505c68737f8a959fa9a99e958b837b746f6a676563626160605f5f5f5f5f626f7b8895a2afa6998c7f7265594c3f3226190c0000000000000000121f2c3845525f6b7885929eabac9f9286796c5f5346392d201306000000020c161f262d323536353534333231302f2d2a241d160d03000000121f2b3845525e6b7885919eabac9f9286796e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e695f54483b2f22160900101c2936434f5c697683909ca9b5a99d9185786d61564b40362e2724232326323f4b5864717d8a97a4b0a5988b7e7265584b3f3225190c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008131e28313a40454747474747474746433d362d23190e03000d1a25313c4750585c5d5d5d5d5d59524a4a535a5d5d5d5d5d5c574f464d565b5d5d5d5d5d5b554c43382d2115090000000000000000000f1b27333f4a545c616262626262615d554c414a545d616262626262615c544a3f34291e1307000000000f1b27333f4a545c616262626262615d554c41362b20140900000000000000000000000000000000000000111e2b3744505d6975828e969795897d71675d5753515152555b66717d8995a29a8e8175685b4f4236291c10000000040d172029333c454f58626b747e87919aa3a0968d837a71675e544b535c666f78828b959ea59c928980766d645a51473e352b22190f06000000030e18222c353e48515b646d77808a939ca69d948b81786e655b524b555e68717a848d97a0a39990877d746a61584e453c322920160d04000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5b545a5f5f5f5f5f5f5f5f5f5f5b544a4034291d110400000000000000000000000000030f1a26303b444b5053535353535353504b433a2f25190e02000000000000000000000000000a16212c3740484f52535353535353535352504a42382e23180c0000000000000000000000000000000000000000000000000000000000000000000000000911181f262c32373b3f41444546464544423f3b37322d272019120a0100000000000000000b17222d38424c555f68727b858e98a1a2988f867c736960564d433a31271e140b01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101c28343f4b57626d78838d97a0a9a89f968e88827d797573716f6e6d6d6d6c6c6c6b6b6b7683909daaab9e91847b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b766a5e5144372b1e110004101c2834404b57626d78838e97a1aaa69d958d86807b777472706f6e6d6d6c6c6c6b6b6b6f7b8895a2afa6998c7f7265594c3f3226190c0000000000000000131f2c3946525f6c7986929facab9f9285786b5f5245392c1f120600000000040d151c212628292928272625242423211e19130c0400000000131f2c3946525f6c7985929facac9f92857b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7a7063574a3d3124170a00101c2936434f5c697683909ca9b6ada195897e72675c52484038333130303136424e5b6773808c99a5b0a3978a7d7064574a3e3124180b00000000000001060a0c0e0e0e0e0e0e0e0d0c09040004080b0d0e0e0e0e0e0e0e0d0a070200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020e1925303a434b5154545454545454534f483f352a1f140800111d2a36424e5962686969696969645c51525c6569696969696861584d555f676969696969665f54493d3125190d000000000000000000121e2b3743505b666d6f6f6f6f6f6e675d5247505c666e6f6f6f6f6f6d665c51463b2f24180d01000000121e2b3743505b666d6f6f6f6f6f6e675d52473c31251a0e03000000000000000000000000000000000000131f2c3946525f6b788588898a8c85786c60554c474544454955616d7a8693a09c9083766a5d5043372a1d100000030c161f29323b454e57616a747d879099a3a0978e847b71685f554c525c656e78818a949da69d938a80776d645b52483f352c23191007000000000006101a232c363f49525b656e77818a949da69d938a81776d645b514c565f68727b858e97a1a2998f867c736a60574e443b32281f160c030000000000000a16212c3740484f52535353535353535352504a4f52535353535353535352504a42382e23180c00000000000000000000000000000009141f29323a404446464646464646443f3931281e1308000000000000000000000000000005101a252e373e4346464646464646464646433f3830261c120700000000000000000000000000000000000000000000000000000000000000000000000000060e141b21262b2f323537383939383735332f2b27211c150f07000000000000000000000f1b27333f4a545e67717a848d97a0a39990877d736a61574e443b31281f150c02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17232f3a45515c66717b858e979ea6a8a099938d898582807d7c7b7a79797979797878787783909daaac9f93898888888888888888888888888888888888888888888888888888888888888884776b5e5144382b1e1100000b17232f3a46515c67717c858f98a0a7a79f97918b8783817e7c7b7a7a79797979787878777b8895a2afa6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0acab9e9285786b5e5145382b1e12050000000000030a1016191c1c1c1b1a191918171614120d0801000000000013202c3946535f6c7986939facaca0948a88888888888888888888888888888888888888888888888888888888888888887d7164574a3e3124170b00101c2936434f5c697683909ca9b1a8a29a8f84796e645a524a44403d3c3d3e4148535e6a77838f9ca8aea195887b6f6256493c3023160a0000000000050c1216191a1a1a1a1a1a1a1a1815100a0f14181a1a1a1a1a1a1a1a1917120d0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121e2a36414c555d606161616161615f5a51473c3024180c00131f2c3945525e6a7476767676766d625656636e767676767673695d515a667176767676767165594d4135291c1004000000000000000013202c3946525f6c787b7b7b7b7b796f64594d53606d787b7b7b7b7b786d62574c4035291e120600000013202c3946525f6c787b7b7b7b7b796f64594d42362b1f1308000000000000000000000000000000000000131f2c3946525f6b767a7b7c7d7e8076695d50443a38373945525f6b7885929f9d9184776a5d5144372a1e1100000a151e28313b444d576069737c868f99a2a1988e857c72695f564d525b646e77818a939da69d948a81786e655c524940362d231a11070000000000000008111a242d374049535c656f78828b949ea59c928980766d635a514d566069727c858f98a1a1988f857c726960564d443a31281e150b02000000000005101a252e373e4346464646464646464646433f4346464646464646464646433f3830261c1207000000000000000000000000000000020d1720282f34383939393939393938342e271f160c0100000000000000000000000000000009131c252c32373939393939393939393937332d261e140b000000000000000000000000000000000000000000000000000000000000000000000000000000030910151a1f2326282a2c2c2c2c2b2926231f1b16100a040000000000000000000000111e2a37434f5b667079838c969fa09a91877e746b61584e453c32291f160c03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121e29343f4a555f69737c858d949ba1a6a49e9995918e8c8a89888786868686858585858485919daab0a59b959595959595959595959595959595959595959595959595959595959595959184776b5e5144382b1e11000007121e2934404a55606a737d868e959ca2a7a29c9793908d8b898887878686868685858584848a96a2afa6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0acab9e9285786b5e5145382b1e120500000000000000050a0d0f100f0e0e0d0c0b0a090805010000000000000013202c3946535f6c798693a0acb0a59c96959595959595959595959595959595959595959595959595959595959595958a7d7164574a3e3124170b00101c2936434f5c697683909ca9aa9f9692958a80766c645c55504c4a494a4b4d525a646f7b87939fabab9f9286796d6054473a2e211508000000000710171d2225272727272727272725211b151a2024272727272727272726231e18110900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000815212e3a47525e676d6d6d6d6d6d6d6b63584d4034281b0f0013202c3946535f6c79838383837e7266595764717d83838383796d61555b6875828383838276695d5145392c2014080000000000000000131f2c3945525e6a75808888888880756a5e53535f6b7681888888887f73685d51463a2f23170b000000131f2c3945525e6a75808888888880756a5e53473c3024180c000000000000000000000000000000000000111e2a37434f5a646b6d6e7071727370665a4e413c3c3d3f45525f6b7885929f9d9084776a5d5044372a1e110006111c27303a434d565f69727b858e98a1a2998f867c736a60574d515a646d768089939ca59e958b82786f665c534a40372e241b110800000000000000000008121b242e37414a535d666f79828c959fa49b92887f756c6359504e57606a737c869099a2a1978e857b72685f564c433a30271d140b01000000000009131c252c3237393939393939393939393733373939393939393939393937332d261e140b0000000000000000000000000000000000050e161d23282b2c2c2c2c2c2c2c2b28231d150d0400000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2b27221c140c020000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0e1316191c1e1f1f201f1e1c1a17130f0a0500000000000000000000000000121f2c3845525f6b78828b9393939392887e756c62594f463d332a20170d04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c18232e38434d57616a737b82898f959a9ea2a5a19e9b99979694949393939292929291919197a2adb7ada6a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a29e9184776a5d5144372a1e110000010d18232e39434e58616b737c838a91969b9fa3a39f9c999796959493939392929292929191939ba6b2a6998c7f7265594c3f3226190c000000000000000013202c3946535f6c798693a0acab9e9285786b5e5145382b1e1205000000000000060c1013151514131211100f0e0d0b08040000000000000013202c3946535f6c798693a0acb7aea6a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2978a7d7164574a3e3124170b00101c2936434f5c697683909ca9a69a8d868d92887e756d66605c5857565657595d636c76818c97a3afa89c8f83766a5e5145382c1f130600000007101922282e323434343434343433312d261f252c303334343434343434322f29231b1208000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1623303d4956636f797a7a7a7a7a7a75695c504336291d1000121f2b3844515e6a778490908e8275695d56626f7c899090897d7165595a6673808c909086796d6155493c3024180c0000000000000000111d2a36424e59646e79848f9592867b6f64584f5a646f7a8590959085796e62574b3f33271b0f030000111d2a36424e59646e79848f9592867b6f64584c4035291d100400000000000000000000000000000000000e1a26323e48525a5f616263646567655e5449484848494b4f56626e7a8793a09b8f8275695c4f4336291d10000b17232e38424c555f68717b848e97a0a39990877d746a61574e505a636c767f89929ba59e958c837970665d544a41382e251b1209000000000000000000000009121c252f38414b545d67707a838c969fa49a91887e756b62584f4e58616b747d87909aa3a0978d847a71685e554c42392f261d13090000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2b272a2c2c2c2c2c2c2c2c2c2c2b27221c140c02000000000000000000000000000000000000040c12181c1f202020202020201e1c17120b03000000000000000000000000000000000000010910161a1e1f2020202020202020201e1b17110a02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002060a0d0f111213131211100d0a0703000000000000000000000000000000121f2c3845525f6b788586868686868680766d635a50473d342b21180e05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c27313b454f58616970787e84898e9295989b9d9fa0a1a2a1a0a0a0a09f9f9f9e9e9e9ea2a9b3b3a9a09b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9ba0a9aeaa9d9083776a5d5044372a1d1100000007121d27323c464f59616a727980858a8f9396999c9e9fa1a2a1a1a0a0a09f9f9f9e9e9e9e9fa5adb2a6998c7f7265594c3f3226190c0000000000000000131f2c3946525f6c7986929facab9e9285786b5f5245382c1f120500000000020a11171c20212221201f1e1d1c1b1a1814100a03000000000013202c3946525f6c7986929facb4aaa19c9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9ea5aeaea3968a7d7063574a3d3024170a00101d2a3643505c697683909ca9a5988c7f869191888078716c68656363636466696e757e88929da9afa3988c8073675b4e4236291d10040000030e19222b333a3e41414141414141403d38312930373c40414141414141413f3b342d241a10050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1723303d4a5663707d87878787878376695d5043362a1d1000101d2a3643505c6975828f9c9285796d6155616e7a8794998d8175685c5865727e8b9895897d7165584c4034281b0f03000000000000000e1a26313d47525d68737e8995978c8175695d51535d68737e8a95968a7f73675c5044372b1f130700000e1a26313d47525d68737e8995978c8175695d5145392d21140800000000000000000000000000000000000a16212c3740484f5354555657595a5953535555555556585b6068737e8a96a2978b7f73665a4d4134281b0f000f1b28333f4a545e67717a838d96a0a49a91877e746b62584f4f59626b757e88919ba49f968c837a70675e544b42382f261c1309000000000000000000000000000a131d262f39424c555e68717a848d97a0a39990877d746a61584e4f59626b757e88919aa49f968c837a70675e544b42382f251b10040000000000010910161a1e1f2020202020202020201e1b1e1f2020202020202020201e1b17110a02000000000000000000000000000000000000000001070c101213131313131313120f0b0600000000000000000000000000000000000000000000050a0e1113131313131313131313120f0b060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000121f2b3845515e6a7679797979797979776d645b51483e352b22190f06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b151f29333d464f575f666d73787d8286898c8e91929495959696969797979798989898999da6b0aea2978f8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8f97a2aea99c8f8376695c504336291d10000000000b15202a343d474f5860676e747a7e83878a8d8f919394959696969697979797989898989aa1aab2a6998c7f7265594c3f3226190c0000000000000000121f2c3845525f6b7885929eabac9f9285796c5f5246392c1f1306000000010b141c22282c2e2e2d2c2c2b2a29282724201b140d0400000000121f2c3845525f6b7885929eabafa398908e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e939da8afa296897c6f6356493c3023160900101d2a3643505d697683909daaa5988b7e808a95918a837d787472706f707172757a8087909aa4afa99e93877b6f63574b3f32261a0d0100000915202b343d454a4d4d4d4d4d4d4d4d49433b313942484c4d4d4d4d4d4d4d4b463f362c22170b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1723303d4a5663707d8a949494908376695d5043362a1d10000f1b2835414e5b6774818d9a95897d7165585f6c7985929d9185786c605763707d8996998d8175685c5044382b1f1307000000000000000915202b36404b56616d78848f9b9185796d61554c57626d7984909b9084786c6054473b2f23160a00000915202b36404b56616d78848f9b9185796d6155493d3024180b000000000000000000000000000000000005101a252e373e434647484a4b4c4d4e575f626262626364676b727a858f9b9c91867b6f63574a3e3225190c00121e2b3744505c667079838c959fa49b92887f756c6259504a56616b747e87909aa3a0978d847a71685e554c423930261d140a0100000000000000000000000000010b141d27303a434c565f68727b858e97a1a2998f867c736a60574e5059636c757f88929ba49e958c837970665d544a41372c21150900000000000000050a0e1113131313131313131313120f1113131313131313131313120f0b060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101d2936424e59646b6c6c6c6c6c6c6c6b655b52493f362c231910070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030e18212b343d454d545b62676d7176797d80828486878889898a8a8a8a8a8a8b8b8b8b8c949fabac9f928681818181818181818181818181818181818181818181818186929faca89b8e8275685b4f4235291c0f00000000040e18222b353d464e555c63696e73777a7d80828486878889898a8a8a8a8a8b8b8b8b8c8f98a4b0a6998c7f7265594c3f3226190c0000000000000000111e2b3744515e6a7784909daaaca09386796d6053473a2d20140700000009131d262d34383b3b3a39383736353433312c261f160d03000000111e2b3844515e6a7784919daaada09387818181818181818181818181818181818181818181818181818c99a6aea194887b6e6255483b2f22150900101d2a3643505d697683909daaa4988b7e78838d97948e8984817e7d7c7d7d7f82858b9199a2acaca2988d82766a5f53473b2f23160a0000020e1a26313c464f565a5a5a5a5a5a5a59544d4339424b53595a5a5a5a5a5a5a5751483e33281c100400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1723303d4a5663707d8a96a19d908376695d5043362a1d10000d1a2633404c5966727f8c98998d8174685c5e6a7784909d95887c706457626e7b88949d9185786c6054473b2f23170a00000000000000040f19242f3a45505b67737e8a96968a7d7165594d515c68737f8b9794887c7064574b3f3226190d0000040f19242f3a45505b67737e8a96968a7d7165594c4034271b0e02000000000000000000000000000000000009131c252c3237393a3c3d3e3f485460696f6f6f6f6f7173777d848d969c948a80756a5e52473a2e22160a0013202c3946535f6c78828b959ea69c928980766d635a50474c5966727d879099a2a1978e857b72685f564c433a30271e140b02000000000000000000000000000000020b151e28313a444d566069737c858f98a2a1988f857c72695f564c515a636d768089929ca59e948b82786f665c53483d32261a0d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004090d101111111111110f0c080200000000000000000003090d10111111111111100d0803000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1a26313d48525a5f5f5f5f5f5f5f5f5f5a534940372d241a1107000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d151d242b333b434a50565c61656a6d70737577797a7b7c7c7d7d7d7d7d7d7e7e7e7e83909daaac9f93867974747474747474747474747474747474747474747474798693a0aca69a8d8073675a4d4134271b0e00000000030d151d242b343c444b51575d62676a6e71747678797a7b7c7c7d7d7d7d7d7e7e7e7e7e8895a2afa6998c7f7265594c3f3226190c0000000000000000101d2a3643505c6976828f9ca8ada194877a6e6154483b2e221508000005101b252f383f44474847464544434241403d3831281f150b000000101d2a3643505d6976838f9ca9ada094877a7474747474747474747474747474747474747474747474808d99a6aca093867a6d6054473a2e21140800111d2a3744505d6a7784909daaa4978b7e717b858e979994908d8b8a89898a8c8e92969ca3ababa39a90867b70655a4e42362b1f1306000005121e2a37424e586166676767676767655f554a3f49545d6567676767676767625a5044392d20140800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1723303d4a5663707d8a96a39d908376695d5043362a1d10000c1825323e4b5764717d8a979d9184786c605c6976828f9c988c8074675b606d798693a094887c7064574b3f33271a0e020000000000000008121d28343f4a56626e7a86929a8d8175685c504b57636e7a8793988c8073675a4e4135281c0f03000008121d28343f4a56626e7a86929a8d8175685c4f43372a1d11040000000000000000000000000000000000010a131b21272b2d2e2f30313e4b5864717b7b7b7b7c7d8083888e9698928a82786e63594d42362a1e12060013202c3946535f6c7986939da7a1958a80776d645b5148404c596673808c98a2a79b8f857c726960564d443a31281e150c020000000000000000000000000000000000030c161f28323b444e57616a737d869099a2a1978e857b71685e5248515b646d77808a939da69d948a81786e655a4e4235291c10000000000001070b0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0e0b070100000000000000000000000000000000000000000000000001090f151a1d1e1e1e1e1e1e1c18130d0600000000000000070e14191c1e1e1e1e1e1e1c19140e070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000915202b3640484e5253535353535353524f4941372e251b1208000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b151f272f353a3c3e3f454b5055595d616466696b6c6d6e6f6f7070707071717171717683909daaada094877a6e67676767676767676767676767676767676767676f7b8894a1aea4988b7e7265594c3f3326190d000000000b151f272f353a3c3e40464c51565a5e626567696b6c6e6f6f707070707171717171717b8895a2afa6998c7f7265594c3f3226190c00000000000000000f1c2835424e5b6874818d9aa7afa295897c6f6256493d3023170a00000a16212c37414a50545554535251504f4e4c49423a31271c110600000f1c2835424e5b6874818e9aa7aea195887b6e67676767676767676767676767676767676767676875828e9ba8aa9e9185786b5f5245392c1f130600111e2a3744515d6a7784909da9a4978a7d70737c858e969d9c9a9796969697989a9ea2a7aaa5a09991887e746a5f54493d32261a0e0200000714212d3a46535f6a7374747474747471675b4f424d59656f747474747474736c6155493c2f23160a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1723303d4a5663707d8a96a39d908376695d5043362a1d10000a1723303d4956636f7c8995a194887c70635b6774818d9a9c9084776b5f5f6b7885919e988c8073675b4f43362a1e1206000000000000030e19242d363e45515d6976828e9b9184786b5f5246525e6a76838f9b8f8276695d5044372b1e110500030e19242d363e46515d6976828e9b9184786b5e5245392c201306000000000000000000000000000000000000010910161b1e20212225323e4b5865717e888888898a8c8f9493908c8780786f665c52473c31251a0e020013202c3946535f6c7986939fa9a094887f756c62594f46404c596673808c99a4a79b8e847a71675e544b42382f251c120900000000000000000000000000000000000000030d162029323c454e58616b747d87909aa3a0968d847a6e62554849525b656e78818a949da69d938a80766a5d5144372a1e1100000000060d12171a1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1a17120d0600000000000000000000000000000000000000000000020b131a2126292b2b2b2b2b2a28241f18100700000000000911192025292b2b2b2b2b2b2925201911090100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040f1a242e363d43454646464646464646433e372f251c13090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121c2731394146494a4b4d4e4f50515254575a5c5e5f616262636363636364646465697683909daaaea295897c6f635b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b64717d8a96a3afa296897c7063574a3e3124180b00000006121c2731394146494a4b4d4e4f50515255585a5d5e606162626363636364646464656f7b8895a2afa6998c7f7265594c3f3226190c00000000000000000d1a2733404d5966727f8b98a4b0a3978a7d7164584b3f3226190d00020e1a26323e49535b6161605f5e5d5c5b5b59544c43392e22160a00000d1a2733404d5966727f8b98a4afa3968a7d70645b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5e6b7784909da9a89c8f8376695d5044372a1e110500111e2b3844515e6a7784919c9c9c96897d706a737c848b92979ca0a3a3a3a4a5a6a5a4a19e9a958e877f766c62584d42372c2115090000000815222e3b4854616e7b818181818181776a5d50444f5b68758181818181817d7063574a3d3024170a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1723303d4a5663707d8a96a39d908376695d5043362a1d10000815222e3b4854616e7a8794a0988c8073675b66727f8c98a093877b6f635d6a7683909c9c9083776b5f53463a2e22160900000000000008141f2b353f484f545a66727e8b9893867a6d615450545a6773808c989185786c5f5246392c2013070008141f2b353f484f545a66727e8b9893867a6d6154473b2e2115080000000000000000000000000000000000000000050a0f1213141825323e4b5865717e8b959596979990898784817b756e665d544a40362b201409000013202c3946535f6c79848d97a0a59a91877e746b61584e454c5966737f88929ba4a0968c837970665d544a41372e241b120800000000000000000000000000000000000000040e17202a333c464f59626b757e88929ea89f95887b6f6255484049535c666f78828b97a3a59c9184776a5d5144372a1e110000000710171e2327292929292929292929292929292929292929292929292927231e1710070000000000000000000000000000000000000000040c141d252c32363738383838373430292219100600000008121b232b313537383838383735312b231b130b020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008121b242c323639393939393939393937332d251d130a01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17232e39434b52565758595a5c5d5e5f5e59514f515354555556565657575757575d697683909daab0a4978b7e7265594e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e5a6773808c99a5aca093877a6e6155483b2f2216090000000b17232e39434b52565758595a5c5d5e5f5e59515052535455565656575757575757626f7b8895a2afa5998c7f7265594c3f3226190c00000000000000000c1825313e4a5763707c8995a2aea5998c8073675a4e4135291c100605111e2a36434f5a656d6e6d6c6b6a696867655e554a3f33261a0e01000c1825313e4a5763707c8995a2aea5988c8073675a4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e54616d7a86939faca6998d8174675b4e4235281c0f0300121f2c3845525e6b78859090909090897c6f626a727980868c90949698999a9a9a999795928e89837c756d645a51463c31261b10040000000915222f3c4855626f7b888e8e8e8e84776b5e51444f5c6975828e8e8e8e8a7d7164574b3e3124180b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1723303d4a5663707d8a96a39d908376695d5043362a1d10000714202d3a46535f6c7986929f9c9083776b5f64717d8a97a3978b7e73665c6875828e9ba093877b6f63564a3e3226190d0100000000000c1824303c47515a606263707c899695887b6f62565b606264707d8a9693877a6d6154473b2e211508000c1824303c47515a606263707c899695887b6f6256493c2f2316090000000000000000000000000000000000000000060c1216191b1c25323e4b5865717e8b9898999a9a8d827f7b76706a645c544b42382e24190e030000121f2b3844515d68727b858e98a1a39990867d736a60574d4a57626d768089939ca59e958c82786f665c534940362d241a1107000000000000000000000000000000000000020b151e27313a444d57606a737d86919eaaa195887b6f6255483e48515a646d77818a96a3a79e9184776a5d5144372a1e11000006101922292f333536363636363636363636363636363636363636363635332f2922191006000000000000000000000000000000000000050e161e262f363d42444444444444403b342b22180d0200040f1a242d353c41444444444444413c352d251d140c040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121a21262a2c2c2c2c2c2c2c2c2c2a27211b130b0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030f1c28343f4a555d626465666768696b6c6a63594d4546474849494a4a4a4a4a4b515d6a7784909daab3a69a8d8175685c504441414141414141414141414146525e6a76838f9ba8a99d9084776b5e5246392d2014070000030f1c28343f4a555d626465666768696b6c6a63594d4546474849494a4a4a4a4a4b56636f7c8996a2afa5988c7e7265584c3f3225190c00000000000000000916222f3b4854616d7a86929faba89b8f82766a5d5145392d2116131214202d3946525f6b777b7a79787776757470675b4f4236291d1003000916222f3b4854616d7986929faba89b8f82766a5e5246414141414141414141414141414c5864707d8995a2aea3968a7d7165584c3f33261a0d010013202c3946535f6c79838383838383837b6e6260686f757b8084878a8c8d8d8e8d8c8b8886827d78726b635b52483f342a1f150a00000000091623303c4956626f7c89969a9a9285786b5e5245505d697683909a9a988b7e7165584b3e3225180c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1723303d4a5663707d8a96a39d908376695d5043362a1d100005121f2b3845515e6b7784919d9f93877b6f62636f7c8995a29b8f83766a5e6773808d99a3978b7e72665a4e4235291d110500000000000e1b2834404d58636c6f6f6f7b8794968a7d706359646c6f6f6f7b889595887b6f6255493c2f221609000e1b2834404d58636c6f6f6f7b8894968a7d7063574a3d3124170a000000000000000000000000000000000000000810171e222627292a323e4b5865717e8b8b8b8c8e91948f8b87827b746b62594e44392e23170c000000101c2834404c566069737c868f98a2a2988f857c72695f564c515b646d77818a939da69d948b81786e655b52493f362c2319100600000000000000000000000000000000010a141d27303a434c565f69727c858f98a2a2988f857b6f62554847505a636c768089929ca79e958c82776a5d5144372a1e1100030e18222c343a3f42424242424242424242424242424242424242424242423f3a342c22180e0300000000000000000000000000000000070f172028303840484e5151515151504c463d34291e1307000915202b363f474d5151515151514d473f372f261e160e0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f151a1e1f20202020202020201e1b16100901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005121e2b3744505c676e7071737475767778756a5e5145393b3b3c3c3d3d3d3d3e46525f6b7885929eabb6a99d9185786c6155493e343434343434343434343f4b56626e7a86939faba5998d8174685c4f43362a1e1105000005121e2b3744505c676e7071737475767778756a5e51453a3b3c3c3d3d3d3d3e3e4b5864717d8a97a4b0a4988b7e7165584b3e3225180c00000000000000000713202c3945515e6a76838f9ba7ab9e9286796d6155493d3228221f1f2026313d4955616e7a8786868584838281776a5d5044372a1d1104000713202c3945515e6a76828f9ba7ab9e92867a6e62574b40363434343434343434343a45515c6874818d99a5ab9f93877a6e6255493c3024170b0000121f2c3945525e6a7476767676767676756b60565d646a6f74777b7d7e80818181807e7c7976716c676059514940362d23180e03000000000a1723303d4a5663707d8996a39f9285796c5f5246505d6a7784909da5988c7e7265594c3f3226190c00000000000000000000000000000000000000000000000000000004060808080808080808080808080808080808080808080808080808080a1723303d4a5663707d8a96a39d908376695d5043362a1d100003101d2a3643505c6976828f9ca3978b7e7266616e7a8794a09f92867a6e6265727e8b98a49b8f82766a5e5245392d2115080000000000101c2936434f5c69757b7b7b7b8794978b7e71645d69767b7b7b7b889496897c706356493d3023160a00101c2936434f5c69757b7b7b7b8794978a7e7164574b3e3125180b00000000000000000000000000000000000007111a22292e32343536383e4b5865717e7e7e7e7f81858a9097938d867d746a60554a3f34281c110500000c18242f3a444e57616a737d879099a3a1978e857b71685f554c525b656e78818b949ea69d938a80776d645b51483e352b22180f0600000000000000000000000000000009131c262f39424b555e68717b848e97a1a39990867d736a5f53474f59626b757e88929ba49f968c837970665b4f4236291d100009141f2a343e454b4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4b453e342a1f14090000000000000000000000000000000911192129323a424a525a5e5e5e5e5e5d574f463b2f24180c000e1a26323d4751595d5e5e5e5e5d5851494038302820170f0700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0e11131313131313131313110f0a05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c787d7e808182838485796c6053473b302f2f30303030313c4855616e7a8793a0acb9ada195897d71665b50453b332c292828292d333c46505c67737e8a96a3ada195897d7164584c4033271b0e0200000613202c3946535f6c787d7e808182838485796c6053473b2f2f303030303036424e5a6673808c99a5afa3968a7d7063574a3d3124170b000000000000000004111d2936424e5a67737f8b97a3aea295897d71655a4e443a322e2c2c2d3038424e5965717d8a939291908f8d8174685b4f4236291d10030004101d2935424e5a66727e8b97a2aea3978b7f73685d52483e352e2a2828282b3037414b56616d7985919da9a79b8f83776a5e5246392d2114080000111d2936424d5862686969696969696968635a4f52595e63686b6e70727374747373716f6d6965615b554e473f372e241b110700000000000a1724313d4a5764707d8a97a4a09386796c605346515e6a7784919ea6998c807366594c4033261a0d00000000000000000000000000000000000000000000000000060c1013141515151515151515151515151515151515151515151515151515151723303d4a5663707d8a96a39d908376695d5043362a1d1000000f1c2835424e5b6774818d9aa79b8e82766a606c7986929fa2968a7e716563707d8a96a39e92867a6e6155493d3124180c0000000000101c2936434f5c6976838888888b96988b7e71655d6a77848888888c96978a7d7063574a3d3024170a00101c2936434f5c6976838888888b96988b7e7165584b3e3225180b0000000000000000000000000000000000040f19232c343a3f41424344454955616b717171717375797e858e979890867c72675c5045392d211509000007131e28323c454e58616b747e87919aa4a0968d847a71675e544b535c666f78828c959ea59c928980766c635a50473d342a21180e050000000000000000000000000008121b252e38414b545d67707a838d96a0a49a91877e746b61584d4e58616b747e87919aa4a0978d847a71675e544a3e32261a0e000d1925313c4650575b5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5b5750463c3125190d00000000000000000000000000020a121a232b333b444c545c646a6b6b6b6b6961574c4034281b0f00111d2a36424e59636a6b6b6b6b69635b524a423a32292119110900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006131f2c3945525e6b77848b8c8d8e9091887c6f63584c423c3937363637383c424d5964717d8996a2afbbb1a59a8e82776c61574d453d3835343436393e454e58626d78848f9ba7a89c9185796d6155483c3024170b00000006121f2c3945525e6b77848b8c8d8e9091887b6f63574b413b39373636373a3e47525e6a76828f9ba8ada094877b6e6255493c2f2316090000000000000000010d1a26323e4b57636f7b87939eaaa69a8e82766b60554c443e3a3938393c424a545f6a76818d999f9e9d968a7d7165584c4033271a0e0100010d1926323e4a56626e7a86929da9a79b9085796e64595047403a36343435373b4149535d68737e8a95a1ada2968b7e73675a4e42362a1d110500000d1925313c4650575c5c5c6063636363625e574d474d53575b5f62646566676767666563605d5955504a443d352d251c12090000000000000b1825313e4b5764717e8b97a4a093877a6d605347515e6b7885919ea69a8d8073675a4d4034271a0d0100000000000000000000000000000000000000000000020a11171c1f212121212121212121212121212121212121212121212121212121212123303d4a5663707d8a96a39d908376695d5043362a1d1000000d1a2733404d5966737f8c99a59e92867a6d616b7784919da69a8e827569626f7b8895a1a2968a7d7165594d4134281c100400000000101c2936434f5c697683909595969d988c7e72655d6a7784909595979e978a7d7164574a3e3124170b00101c2936434f5c697683909595969d988c7e7265584c3f3225190c00000000000000000000000000000000000a16212b353e454b4e4f505152535459616565656566696d747c85909b988e84786d6155493d3125180c0000010c16202a333d464f59626c757f88929ba59f968c83796f665d534a545d677079838c969fa49b92887e756c62594f463c332a20170d04000000000000000000000007111a242d37404a535d666f79838c959fa59b92887f756c62594f4d57606a737d869099a3a1978e857b72685f554c42382d22160a00111d2936424d5862686969696969696969696969696969696969696969696862584d4236291d11000000000000000000000000030c141c242c353d454d565e666e767777777773685c5043362a1d1000131f2c3945525e6b7577777777756d645c544c443b332b231a120a020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004111d2a36434f5c6875818d999a9b9c988c8074685e544c48464443434345484d545e6975818d99a5b2bcb6aa9f94887d73695f574f49444241414245494f576069747e8a95a0aca3978c8074685c5044382c20140800000004111d2a36434f5c6875818d999a9b9c988b8073685d534c484544434344464a5059636f7a86929eabaa9d9185786c5f53463a2d2114080000000000000000000a16222e3a46525e6a76828d99a4aa9e93887c72675e554f4a47454546484d535c66707b87929eaaa99d9185796d6155493d3024170b0000000916222e3a46525e6975818c98a3aca1968b80756b6259514b464341414244474c535b656f79848f9ba6a89d91867a6e62564a3e32261a0e0100000914202a353e464c4f57626b6f6f6f6f6f695f534742474b4f5255585d63676b6e6f6f6e6c68635d564e453c32281e130a000000000000000c1825323f4b5865717e8b98a5a194877a6e615447525f6c7885929fa79a8e8174675b4e4134281b0e01000000000000000000000000000000000000000000020b141c23282c2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e303d4a5663707d8a96a39d908376695d5043362a1d1000000c1825323e4b5864717e8a97a4a2968a7d71656976828f9ca89e9185796d606d7a8693a0a69a8e8175695d5044382c20140700000000101c2936434f5c697683909ca2a3a5988c7e72655d6a7784909da2a3a4978a7d7164574a3e3124170b00101c2936434f5c697683909ca2a3a5988c7e7265584c3f3225190c00000000000000000000000000000000030f1b27323d4750575a5b5d5e5f60615e5758585858595c626a737e8a96a095897d7265594d4034281b0f020000050e18212b343d47505a636d768089939ca69e958b82786f655c524b555e67717a848d97a0a49a91877e746b61584e453c32291f160c03000000000000000000071019232c363f49525c656f78828b959ea69c938980766d635a504c565f69727c858f98a2a2988f867c736960564d433a31261c110500121f2c3845525e6a73757575757575757575757575757575757575757575736a5e5245382c1f120000000000000000000000050d151e262e363e474f575f6770788084848484776a5d5044372a1d110013202c3946535f6c79848484847e766e665e554d453d352c241c140c03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010e1b2734404c5965717d8995a1a8a89c91857a6f665e585552515050505154585e66707b86929da9b4afaeb0a59a8f857b7168615a54514e4d4e4f51555a6169727b86909ba6a79c91867b6f63584c4034281c1004000000010e1b2734404c5965717d8995a1a8a89c9085796f655d5854525050505152565b626b75808b97a3afa5998d8175695c5044372b1e120500000000000000000006121e2a36424e5a65717c88939ea9a4998e83797067605a565352525355585e656e78828d98a3aea3988c8175695d5145392d21140800000006121e2a35414d5964707b87929da7a79c92877d746b635c56524f4e4d4e5053585e656d76818b96a1aca2978c8075695d52463a2e22160a000000030e19232c343b404d5a66737c7c7c7c7b6f63564a3e444a50575d63696e73777a7c7c7b78746e6860574e443a2f24190e030000000000000c1926323f4c5965727f8c98a5a195887b6e615548535f6c7986929fa89b8e8275685b4e4235281b0f020000000000000000000000000000000000000000000a141d262d34383a3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3d4a5663707d8a96a39d908376695d5043362a1d1000000a1723303d4956636f7c8995a2a69a8d8175696774818e9aa7a195897d70646b7885929eaa9d9185796d6054483c3023170b00000000101c2936434f5c697683909ca9afa5988c7e72655d6a7784909daaafa4978a7d7164574a3e3124170b00101c2936434f5c697683909ca9afa5988c7e7265584c3f3225190c0000000000000000000000000000000006131f2b37434e59626768696a6b6d6d6960554b4b4b4d5158626d7986929f9a8e8275695c5043362a1d1104000000060f19222b353e48515b646d77818a949da69d948a81776e645b514c555f68727b858e97a1a39990867d736a60574e443b31281e150c0200000000000000060f19222b353e48515b646e77818a949da69d948a81776d645b514c555e68717b848e97a1a39990867d736a61574e443b31281f150a000013202c3946535f6c79828282828282828282828282828282828282828282796c5f5346392c201300000000000000000000060f171f2730384048505961697179828a9191897e74695c5043362a1d1000131f2c3946525f6b76818b919189807870675f574f473e362e261e150d050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1824303d4955616d7985909ba7ada2968c81786f6964615f5d5d5c5d5e6064697078828c97a3aea9a3a2a5aca1978d837a726b65605d5b5a5b5c5e61666c737b848d97a2aba0968b8075695e53473b2f24180c00000000000b1824303d4955616d7985909ca7ada1968b81776f6864605e5d5d5d5d5f62666c747d87919ca8aba094897d7165594d4034281c0f03000000000000000000020e1a26313d4954606b76828c97a2aaa0958b8279726b6662605f5f5f6164697077808a949ea9a79c92877b7064584d4135291d1104000000010d1925313c48535f6a75808b96a0aaa3998f867d756d67625e5c5b5a5b5d5f63696f778089929da7a59b90857a6f64584d4135291e12060000000007111a222933404c5966727f8989897e7266594e4a4f555c62686e747a7f8487898988858079726960564c41362b1f14080000000000000d1a2633404d596673808c99a6a295887c6f62554953606d798693a0a89c8f8275695c4f4236291c0f03000000000000000000000000000000000000000005111b262f383f4447484848484848484848484848484848484848484848484848484848484848484a5663707d8a96a39d908376695d5043362a1d1000000915222f3b4855616e7b8794a1aa9d9185796c6673808c99a5a5998d8174686a7783909da9a195897c7064584c3f33271b0f03000000101c2936434f5c697683909ca9aca5988c7e72655d6a7784909daaaca4978a7d7164574a3e3124170b00101c2936434f5c697683909ca9aca5988c7e7265584c3f3225190c000000000000000000000000000000000815212e3b4753606b7375767778797a7165594c3f3f4046515e6a7784909d9d9184776b5e5145382b1f120500000000071019232c363f49525c656e78818b949ea69c938980766d635a504d566069737c868f98a2a2988f857c736960564d433a30271e140b010000000000050e18212b343d47505a636d768089939ca69e948b81786e655c524b545d67707a838d96a0a39a91877e746b61584e453c32291f160d03000013202c3946535f6c79868f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f86796c5f5346392c201300000000000000000008101821293139414a525a626b737b838b94958b81776d63584c4034281b0f00111e2a37434f5a646f79838d97928a8279716961595048403830271f170f0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000814202d3945515c68737f8a959fa9a89d938a817a75706d6b6a69696a6b6d70747a828a949ea9a99f97959aa3a99f958d847d76716d6a686767686a6d72777d858d969fa9a2998f84796f63584d42362a1f130700000000000814202d3945515c68747f8a95a0aaa79d9389817a74706d6b6a69696a6c6e72777e868f99a3aea4998e83786c6055493d3024180c00000000000000000000000915212c38434f5a65707b86909aa4a79d948b837c77726f6d6c6b6c6e71757a8189929ca6a99f958b80756a5f53483c3024180c00000000000814202b37424d59646f79848e98a1aba1988f877f78736e6b68676768696c6f747a8189929ba4a79d94897e74695e53473c3025190d01000000000008101825323e4b5864717d8a968e82766a5f57575b61676d737980858b9094969694918b847b72685d52473c3025190d0100000000000e1a2734404d5a6773818d9aa6a396897c6f63564954616d7a8794a0a99c908376695c504336291d100300000000000000000000000000000000000000000b16222d38414a505454545454545454545454545454545454545454545454545454545454545454545663707d8a96a39d908376695d5043362a1d1000000714202d3a4653606c7986929faca195897c7064717e8a97a4a99c9084786c6875828e9ba8a5998c8074685c4f43372b1f1206000000101c2936434f5c697683909ca0a0a0988c7e72655d6a7784909da0a0a0978a7d7164574a3e3124170b00101c2936434f5c697683909ca0a0a0988c7e7265584c3f3225190c000000000000000000000000000000000915222f3c4855626f7b82838485868074675b4f443f3f44515d6a7784909d9f9285786b5f5245382c1f1205000000000007111a242d37404a535c666f79828c959fa59b92887f756c62594f4e57616a737d869099a3a1978e857b72685f554c423930261d130800000000040d17202a333d464f59626c757f88929ba59f958c83796f665d534a535d666f79838c959fa49b92887e756c62594f463c332a20170d0400000013202c3946535f6c7986939c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9386796c5f5346392c201300000000000000010a121a222a333b434b535c646c747c858d95988e84796f655b51463b3024180c000e1a26323e48535d67717b86909a948b837b736b625a524a41393129211810080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101c2834404c57626e78838d97a1a9a59c938c85817d7a787776767677797c80868c949da6aaa1978d88919aa3a89f968f88827d797675747475777a7d82888f979fa8a39a90877d72685d52473c30251a0e02000000000004101c2834404c57636e79848e98a1aaa59b938b85807c797877767677787a7e83899098a1aba69c92887d72675b5044382c201408000000000000000000000004101b27323d49545e69747e88929ba4a69d958e88837e7b797878797a7d81868c939ba4a8a0978d83796e64594d42372b1f14080000000000030f1a26313c47525d67727c868f99a1a9a199918a847e7a777574747576787b80858c939ba4a79e958c82776d62574c41362b1f1408000000000000000a1723303c4956626f7b889492877b71686463666c72787e858b91969ca0a2a2a19c968d84796f64584d41352a1e120600000000000e1b2834414e5b6774818e9aa7a3968a7d7063574a54616e7b8894a1aa9d9083776a5d5044372a1d110400000000000000000000000000000000000000000f1b27333e49535b6061616161616161616161616161616161616161616161616161616161616161616163707d8a96a39d908376695d5043362a1d10000006121f2b3845515e6b7784919daaa5998c8074686f7c8996a2aca094887b6f6773808d99a6a99c9084786b5f53473b2f22160a000000101c2936434f5c6976839093939393938c7e72655d6a77849093939393938a7d7164574a3e3124170b00101c2936434f5c6976839093939393938c7e7265584c3f3225190c000000000000000000000000000000000815212e3b4754606d79868f91928f83776b60564f4c4c4e55606c7885919e9e9285786b5f5245382c1f120500000000000008121b252e38414a545d67707a838d96a0a49a91877e746b61584e4e58616b747e87919aa3a0978d847a71675e544b42382f251a0f040000030c161f29323c454e58616b747e87919aa4a0968d837a70675d544a525c656f78828b959ea59c928980766c635a50473d342b21180e050000000013202c3946535f6c798693a0a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a09386796c5f5346392c2013000000000000030b131b242c343c454d555d656e767e868f979a90867c72675d53493f352a1f1408000a16212c37414b555f69747e88929c958d857c746c645c534b433b332a221a120a010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c18232f3a46515c67717c858f979fa6a59d97918d898785848383838486898c91979ea6a8a0988f857e889199a1a8a099938d8985838181818284868a8e949aa1a8a19991887e756b61564b41362b1f1409000000000000000c18232f3b46515c67727c868f98a0a7a59d96918c8986848483838485878a8e949aa2aaa49c948a80766b61554a3f33281c10040000000000000000000000000a16212c37424d57626c768089929aa2a7a099938e8b888685858687898d91979ea5a69f978e857b71675d52473c31261a0f030000000000000914202b36414b56606a747d878f989fa6a39c958f8a8784828181818385888c91979da5a49d958c837970665b51463b3025190e03000000000000000815212e3a4753606c798592988d837a73707072777d838a90969ca2a4a1a0a0a2a59f968b8075695e52463a2e22160900000000000f1b2835424e5b6875828e9ba8a4978a7d7164574b55626f7b8895a2aa9e9184776a5e5144372b1e11050000000000000000000000000000000000000000111e2b37434f5b656d6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e707d8a96a39d908376695d5043362a1d10000003111d2a3743505d6976838f9ca9a89c9084786b6e7b8794a1aca4988c807367727e8b98a5aca094887b6f63574b3e32261a0e010000101c2936434f5c697683868686868686867e72655d6a7784868686868686867d7164574a3e3124170b00101c2936434f5c697683868686868686867e7265584c3f3225190c0000000000000000000000000000000006131f2c3845515e6a76838f9b9e93887c7168605b59595a5e67717c8894a19d9084776a5e5144382b1e12050000000000000009131c262f38424b555e68717a848e97a0a39990877d736a60574d4f59626c757e88929ba49f968c837970665d544a41362b20140900000a151e28313b444e57616a737d879099a3a1978e847b71685e554b515b646e77818a949da69d938a80776d645a51483e352b22190f06000000000013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09386796c5f5346392c20130000000000020c151d252d363e464e575f676f77808890989d93897e746a60564b41372d23180e020005101a252f39434d58626c76808b959f978f867e766e655d554d453c342c241b130a01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007131e2935404b555f6a737c858d959ca1a7a29d9996939290909090919295989da2a8a39d968e867c767f878f979da3a49e9995928f8e8e8e8f9092969a9fa5a39d968f877e766c63594f443a2f24190e030000000000000007131e2a35404b55606a747d868e969ca2a7a19c98959391909090909194969a9fa5a6a09a928a81786e645a4f44392e22170b0000000000000000000000000004101b26313b46505a646d76808890979ea4a49f9b9795939292929496999da2a8a29b948d857c73695f554b40362b20140900000000000000030e19242f39444e58626b747d868d959ba2a6a09b9793908f8e8e8e8f9194989ca2a5a09a938b837a71675e54493f342a1f1308000000000000000006121f2b3844515d6976828e9a958c84807d7d7e83898f959ba1a39d9894939395999f9d91867a6e62564a3e3225190d00000000000f1c2936424f5c6875828f9ca8a4988b7e7165584b55626f7c8995a2ab9e9185786b5e5145382b1f1205000000000000000000000000000000000000000013202c3946525f6c777b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7d8a96a39d908376695d5043362a1d100000000f1c2835424e5b6874818e9aa0a0a094887b6f6c7986929fa0a09b8f83776b707d8a96a0a0a0988b7f73675b4e42362a1e11050000101c2936424f5c687479797979797979797970645c69747979797979797979796f63574a3d3124170a00101c2936424f5c68747979797979797979797064584b3e3225180c0000000000000000000000000000000004101d2936424e5a67737e8a96a1998e837a726b676565676a7078838e99a4998d8174685c4f4336291d100400000000000000010a141d263039434c565f69727b858e98a1a2988f857c72695f564c505a636c768089929ca59e958b82786f665c53483d3125190c0006111c26303a434d566069737c868f99a2a2988f857c72695f564c505a636d768089939ca69d948a81786e655b52483f362c2319100700000000000013202c3946535f6c79869393939393939393939393939393939393939386796c5f5346392c201300000000000a141e272f373f485058606871798189929a9f958b81776c62584e443a2f251b110700000009131d27313c46505a646e78838d97a198908880776f675f574e463e362d251c13080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010d18232e39434e58616a737b838a90969b9fa2a5a2a09e9d9d9c9d9e9fa1a5a4a19d98928b847c746d757d858c92989da1a4a19e9c9b9a9a9b9d9fa2a4a09c97928b857d756c645a51473d33281d13080000000000000000020d18232e39444e58626b747c848b91979b9fa3a4a29f9e9d9c9c9d9ea0a3a6a39f9a958f8881786f665c52483d33281c1106000000000000000000000000000009141f29343e48525b646d767e868d93989da2a5a3a1a09f9f9fa0a2a5a4a09c97918a837b726a61574d43392f24190e03000000000000000008131d28323c465059626b747b838a90969b9fa3a39f9d9b9a9a9b9c9ea1a4a29e9a958f88817971685f554c42382d23180d02000000000000000003101c2835414d5a66727e8a969e96908c8a898b8f949aa0a49e97918c888686898d949c978b7e72665a4e4135291c100300000000101d2936434f5c6976838f9ca9a5988c7e7265594c5663707c8996a3ac9f9285786c5f5245392c1f1306000000000000000000000000000000000000000013202c3946535f6c798688888888888888888888888888888888888888888888888888888888888888888888888d98a49d908376695d5043362a1d100000000e1a2733404d596673808c93939393938b7f736b7784919393939393877a6e6f7b8893939393938f83776a5e52463a2d21140800000e1b2733404c57626a6c6c6c6c6c6c6c6c6c685f58626a6c6c6c6c6c6c6c6c6c675e53473b2e221609000e1b2733404c57626a6c6c6c6c6c6c6c6c6c685f54483c3023170a00000000000000000000000000000000010d1a26323e4a56626e79848f9a9f958c847c7774727273767b828b959f9e93887c7064584c4033271b0e020000000000000000020b141e27313a444d57606a737c868f99a0a0978e857b71685d5148515a646d77808a939da09d948b81786e64594d4134281b0f000b17222d38424c555f68727b858e98a1a29990867c736a60574d5059626c757f88929ba59e958b82786f665c534940362d241a11070000000000000013202c3946535f6c79868686868686868686868686868686868686868686796c5f5346392c20130000000006111c2630394149515a626a727a838b939ba2988d83796f655b50463c32281e130900000000010b15202a343e48525c67717b858f9aa29a928981797168605850483f372e241a0f04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121d27323c464f58616971787f858a8f9396999b9c9e9f9fa09f9f9e9c9a9895918c87817a726a636b737a81878c9195989b9d9e9fa09f9f9e9c9a9894908c86817a736b635a52483f352b21160c0100000000000000000007121d27323c465059626a727980868b8f9396999b9d9e9f9fa09f9e9d9b9996938f8a847d766f665d544a40362c21160b000000000000000000000000000000030d18222c364049525b646c747b82888d9195999b9d9e9fa09f9e9d9b9894908b857f78716960574e453c32271d1208000000000000000000010c16202a343e475059626a71787f858a8f93979a9c9d9f9fa09f9e9d9b9996928e89837d766f675f564d433a30261c1106000000000000000000000d1925313e4a56626e7985909ba19c989696989b9fa59f99928c86807c797a7d828a939b8f82766a5d5144382b1f120600000000111d2a3743505d6a7683909daaa6998c807366594d5763707d8a97a3ac9f9386796c5f5346392d201306000000000000000000000000000000000000000013202c3946535f6c79869394949494949494949494949494949494949494949494949494949494949494949494979fa99d908376695d5043362a1d100000000c1925323f4b5864717e8686868686868683776a7683868686868686867e726d7a86868686868686867a6e6255483c2f22160900000b17232f3b4650585e5f5f5f5f5f5f5f5f5f5d5650595e5f5f5f5f5f5f5f5f5f5c554c41362b1f1206000b17232f3b4650585e5f5f5f5f5f5f5f5f5f5d564d42372c20140700000000000000000000000000000000000a16222e3a46515d68737d88919a9e958e8883817f7e8082878c949d9e958c82766b6054483c3024180b00000000000000000000020c151f28323b454e57616a747d8790939393938d847a6d61544748525b656e78818b93939393938a8075695c4f4336291c10000f1b27333f4a545e67717a848d97a0a39a90877d746a61584e4e58616b747e87919aa49f968c837970665d544a41372e241b12080000000000000000131f2c3946525f6b76797979797979797979797979797979797979797979766b5f5246392c1f13000000000b17222e38424b535b636c747c848c959da49a90867c71675d53493f342a20160c020000000000030e18222c36414b555f69737d88929ca49b938b837a726a625a514940362c2015090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b15202a343d464f585f676e74797e8386898c8e9091929293929291908e8b8885807b756f68605961696f767b8185888c8e90919293929291908e8b8884807b756f686159514840362d23190f0500000000000000000000000b16202a343e47505860676e747a7f83878a8d8f90919292939292908f8d8a87837e78736c645d544b42382f241a0f050000000000000000000000000000000006101a242e374049525a626970767c8185898c8f909292939292908e8b8884807a746d665f574e453c332a20150b0100000000000000000000040e18222c353e4750585f676e74797e83878a8d8f919292939292908f8c8a86827d78726c645d554d443b31281e140a00000000000000000000000915212d3a45515d68737e89939da4a5a3a3a4a59f9a948e87817b756f6d6d7178818c979285796c6053473a2e21150800000000111e2b3744515d6a7784919daaa69a8d8173675a4d5764717d8a97a4aca093867a6d6053473a2d201407000000000000000000000000000000000000000013202c3946535f6c798693a0a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a3a8aa9d908376695d5043362a1d100000000a1724303d4a56636f787979797979797979756a73797979797979797979716b767979797979797979786e6155483c2f221609000007131e29343e464d52535353535353535353514b474e52535353535353535353504b433a30251a0e020007131e29343e464d52535353535353535353514b443b31261b0f03000000000000000000000000000000000006121d2935404b56616c767f8890979e9994908d8c8c8d8f92989e9b948c837a70655a4f43382c2014080000000000000000000000030d162029333c454f58626b757e868686868686867a6d6154474049535c666f78828686868686868376695c4f4336291c1000111e2a37434f5b667079838c969fa09b91887e756b62594f48545f6a737d879099a0a0968d847a71675e544b42382f251c1209000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b645a4f43372a1e11000000000f1b27333f4a545d656d757e868e969ea79d92887e746a5f554b41372d23180e040000000000000006101a242f39434d57616c76808a949fa59d958c847c746b635b52483d3125190d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040e18222b343d464e555c62686e72767a7d8082838485868686858483817e7c78746f6a645d564f575e646a7074797c7f828385868686858483817e7c78746f6a645d564f473f362e241b1107000000000000000000000000040e18222c353e464e565d63696e73777a7d8082848585868686858482807d7a77726d67615a534b423930261d130800000000000000000000000000000000000008121c252e37404850585f656b7075797d808284858686868584827f7c78736e69635c554d453c332a21180e0400000000000000000000000006101a232c353e464e555c62686e73777b7e81838485868686858482807d7a76716c67615a534b433b32291f160c02000000000000000000000005111d2935404c57626d77818a93999e9f9f9d99948f89837c767069646061666f7a869195887b6f6256493d3023170a00000000121e2b3845515e6b7784919ea0a09a8e8174675b4e5865717e8b98a0a0a094877a6d6154473b2e211408000000000000000000000000000000000000000013202c3946535f6c798693a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a09d908376695d5043362a1d100000000915222e3a47525d676c6c6c6c6c6c6c6c6c6b63696c6c6c6c6c6c6c6c6c68646b6c6c6c6c6c6c6c6c6c665c5145392d2014070000020d18222c353c424546464646464646464644403c424546464646464646464644403931281e13080000020d18222c353c424546464646464646464644403a32291f140a000000000000000000000000000000000000010d18242f3a454f5a646d767e868c92979a9c9a9898999b9c9995908a827a71685e53493e32271b0f04000000000000000000000000040e17212a333d465059636c7679797979797979776c6053473a414a545d6670787979797979797974685c4f4236291c1000121f2c3845525f6b78828b93939393928980766c635950474a5763707c868f939393938e857b71685f554c423930261d130a000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5a52483e32261a0e00000000121e2b3744505b666f777f879098a0a09f958b81766c62584e44392f251b110600000000000000000008131d27313b45505a646e78838d97a0a09e968e867e756d64594d4135281c0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061019222b343c434a51575d62666a6d70737576777879797978777674726f6c68645f59534c454c53595f64686c707375777879797978787674726f6c68635e59524c453d352d241b1209000000000000000000000000000006101a232c343c444b52585e63676b6e71737577787979797978777574716e6a66615c564f48413930271e150b01000000000000000000000000000000000000000a131c252e363e464d545a5f64696d7073757778797979787775726f6c68635d57514a433b332a21180f06000000000000000000000000000008111a232c343c434a51575d62676b6e717476777879797978777573716d6a66615b564f484139312920170d04000000000000000000000000010d18242f3a46505b656f7881888e919292918d88837d77716b645e5853545e6975818e938a7d7164584b3e3225190c00000000121f2c3945525f6b788592939393938e8275685b4e5865727e8c9393939393887b6e6155483b2e221508000000000000000000000000000000000000000013202c3946535f6c7986939393939393939393939393939393939393939393939393939393939393939393939393939393908376695d5043362a1d1000000006121e2a36414c555c5f5f5f5f5f5f5f5f5f5e595e5f5f5f5f5f5f5f5f5f5d5a5f5f5f5f5f5f5f5f5f5f5b544b4035291d110500000006101a232a313639393939393939393939383431363939393939393939393938342e271f160c0200000006101a232a31363939393939393939393938342f2820170d030000000000000000000000000000000000000007121e29333e48525b646c747b81868a8e9092939392918f8d89847e7870685f564c42372c21160a0000000000000000000000000000050f18212b343e47515a646b6c6c6c6c6c6c6c6b655b50443838424b545e676c6c6c6c6c6c6c6c6a62574c4033271b0e00121f2c3845525f6b788586868686868680776d645a51473e4a5763707d868686868686857c72695f564d433a30271e140b01000000000000000000000a16212c3740484f52535353535353535353535353535353535353535353524f4840372c21160a0000000013202c3946535f6c7881899193939393938d83796f655a50463c32271d130900000000000000000000010b151f29343e48525c66717b858f939393939390877f76695d5043372a1d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071019222a323940464c51565a5e616466686a6b6b6c6c6c6c6b6a686663605c58534e48413b41484e53585c606366686a6b6c6c6c6c6b6a686663605c57534d47413a332b231b12090000000000000000000000000000000008111a222a323940474c52575b5f626567696a6b6c6c6c6c6b6a696765625e5a56514b453e372f271e150c030000000000000000000000000000000000000000010a131c242c343b42494e54595d616467696a6b6c6c6c6b6a686663605c57524c463f38312921180f060000000000000000000000000000000008111a222a323940464c51565b5f626567696b6b6c6c6c6b6a696764615e5a55504a443e372f271f170e05000000000000000000000000000007131e29343f49535d666f767d8284868684817d77726c666059534d474d5965727e868686807366594d4033271a0d0000000013202c3946535f6c79868686868686868275695c4f59667380868686868686867b6f6255493c2f221609000000000000000000000000000000000000000013202c3946535f6c7986868686868686868686868686868686868686868686868686868686868686868686868686868686868376695d5043362a1d10000000020e19252f3a434b50535353535353535353524e51535353535353535353514f52535353535353535353504a42392e24180d01000000000811192025292c2c2c2c2c2c2c2c2c2c2b28262a2c2c2c2c2c2c2c2c2c2c2b28231d150d0400000000000811192025292c2c2c2c2c2c2c2c2c2c2b28241d160e050000000000000000000000000000000000000000010c17222c364049525a626970757a7e8184858686868583817d78736d665e564d443a30251b1005000000000000000000000000000000060f19222c353f48525a5f5f5f5f5f5f5f5f5f5b53493f333039424c555c5f5f5f5f5f5f5f5f5e5850463b2f23170b00121f2b3845515e6a7679797979797979776e655b52483f3d4a56636f7879797979797979736a60574e443b31281e150c02000000000000000000000005101a252e373e434646464646464646464646464646464646464646464646433e372e251a10050000000013202c3946535f6c798686868686868686867b71675d53483e342a20160b010000000000000000000000030d18222c36404a555f69737d868686868686868684776a5d5044372a1d1100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007101820272e353b40454a4e5255575a5c5d5e5f5f5f5f5f5e5d5b595754504c47423c3630363d42474c5054575a5c5d5e5f5f5f5f5e5d5b595653504c47423c362f282119110900000000000000000000000000000000000008101820282f353b41464b4f5255585a5c5d5e5f5f5f5f5f5e5c5a5855524e4a453f3a332c251d150c0300000000000000000000000000000000000000000000010a121a222a31373d43484d5154575a5c5e5f5f5f5f5f5d5c5a5753504b46413b352e271f170f0600000000000000000000000000000000000008101820272e353b40464a4f5256585b5d5e5f5f5f5f5f5e5c5a5855514e49443f39332c251d150d05000000000000000000000000000000020d18232d37414b545d656c71757879797775716c66615b554e48423d4a56636f78797979797266594d4033271a0d00000000131f2c3946525f6b76797979797979797973685b4f5865717979797979797979786e6155483c2f2216090000000000000000000000000000000000000000131f2c3946525f6b7679797979797979797979797979797979797979797979797979797979797979797979797979797979797974685c4f4336291d100000000008131e2831393f44464646464646464646454245464646464646464646454346464646464646464646443f3830271d1207000000000000070e14191d1f2020202020202020201f1c1a1d1f2020202020202020201f1c17120b0400000000000000070e14191d1f2020202020202020201f1c18120c040000000000000000000000000000000000000000000005101a242e37404850585e656a6e72757778797979787674716d68625c544d443b32281e1409000000000000000000000000000000000007101a232d3640484e5253535353535353524f4941372d27303a434b505353535353535353524d463e34291e130700101d2936424e59646b6c6c6c6c6c6c6c6c665c534940363a47525d676c6c6c6c6c6c6c6c6961584e453c32291f160c030000000000000000000000000009131c252c3237393939393939393939393939393939393939393939393937322c251c13090000000000131f2c3946525f6b7679797979797979797974695f554b41372c22180e040000000000000000000000000006101a242e39434d57616b7579797979797979797974695c5043362a1d1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060e151d23292f353a3e4245484b4d4f5051525253535251504f4d4a4744403b37312b252b31373c4044474b4d4f51525253535251504f4d4a47443f3b36312b251e170f070000000000000000000000000000000000000000070e161d242a30353a3f4346494c4e4f5152525353525251504e4c4946423e39342e28221a130b03000000000000000000000000000000000000000000000000000910181f262c32373c4145484b4d4f515253535252514f4d4a47443f3b35302a231c150d050000000000000000000000000000000000000000060e151c23292f353a3e4346494c4e50515253535252514f4e4b4845423d39332e28211a130b03000000000000000000000000000000000006111b263039424b535a6065696b6c6c6b6865605b554f4a433d373a47525d676c6c6c6c6c6960554a3d3125180c00000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6a62574b545f686c6c6c6c6c6c6c6c6c665c5145392d2014070000000000000000000000000000000000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6a62584c4034271b0e00000000010c161f272e343839393939393939393939363839393939393939393938373939393939393939393937332e261e150b000000000000000003090d111213131313131313131312100e1113131313131313131313120f0c070000000000000000000003090d111213131313131313131312100c070100000000000000000000000000000000000000000000000008121c252e363f464d53595e6266686a6c6c6c6c6b6a6764615c57514a433b322920160c0200000000000000000000000000000000000008111b242e363d43454646464646464646433e372f261e2831393f44464646464646464645423c352c22180d02000e1a26313d48525a5f5f5f5f5f5f5f5f5f5b544a41372e36414c555c5f5f5f5f5f5f5f5f5e584f463c332a20170d040000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a26211a130a010000000000111e2a37434f5a646b6c6c6c6c6c6c6c6c6c6a62584d43392f251b100600000000000000000000000000000008121c27313b454f5a636b6c6c6c6c6c6c6c6c6c6a62584c4034281b0f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040b12181e24292e3236393c3e414244454546464645454442403e3b3834302b26201a20262b3034383b3e4042444546464646454442403e3b37332f2a25201a130c0500000000000000000000000000000000000000000000040c12191f252a2e33363a3d3f4143444546464646454443413f3d3936322d28231d17100901000000000000000000000000000000000000000000000000000000060d141b21262c3035383c3f41434445464646454443403e3b37332f2a241f18110a0300000000000000000000000000000000000000000000040b12181e24292e32363a3d3f42434545464646454443413f3c3935312d28221d16100901000000000000000000000000000000000000000a141e27303941484f55595c5e5f5f5e5c59544f4a443e38322c36414c555c5f5f5f5f5f5d574e44392d211509000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5e5850454d565d5f5f5f5f5f5f5f5f5f5b544b4035291d110500000000000000000000000000000000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5e5950463b3024180c0000000000040d151d23282b2c2c2c2c2c2c2c2c2c2c2a2c2c2c2c2c2c2c2c2c2c2b2a2c2c2c2c2c2c2c2c2c2c2b27221c140c03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a131c252d343b42484d5256595c5e5f5f5f5f5e5d5b5855504b453f38312920170e04000000000000000000000000000000000000000009121b242c323639393939393939393937332d251d161f272e343839393939393939393936312a231a100600000915202b3640484e5253535353535353524f4a42382f252f3a434b505353535353535353514d463d342a21170e0500000000000000000000000000000000010910161a1e1f2020202020202020202020202020202020202020201f1e1a161009010000000000000e1a26323e48525a5f5f5f5f5f5f5f5f5f5f5e5850463c31271d130900000000000000000000000000000000010b151f29333d4851595e5f5f5f5f5f5f5f5f5f5e5950463b3024180c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070d13181d2226292d2f3234363738393939393938373534312f2b28241f1a140f151a1f24282c2f32343637383939393938373533312e2b27231f1a140e080200000000000000000000000000000000000000000000000001080e13191e22262a2d303234363738393939393838363533302d2a26221d18120c0500000000000000000000000000000000000000000000000000000000000003090f151b2024292c2f323436383939393938373634312f2b27231e19130d070000000000000000000000000000000000000000000000000000070d13181d22262a2e3033353738393939393837363432302d2925211c17110b05000000000000000000000000000000000000000000020c151e272f373e44494d5052535352504c48443e39332d27252f3a434b505353535353514c453c32271c1105000000000a16212c3740484f525353535353535353524d463e444c51535353535353535353504a42392e24180d0100000000000000000000000000000000000000000a16212c3740484f52535353535353535353535353535353535353535353535353535353535353535353535353535353535353524e473e342a1f1307000000000000030b12171c1e2020202020202020201f1e1f2020202020202020201f1e1f2020202020202020201e1b17110a020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131b222a31373c42464a4d4f515253535352504e4c4844403a342e261f170e050000000000000000000000000000000000000000000009121a21262a2c2c2c2c2c2c2c2c2c2a27221b130d151d23282b2c2c2c2c2c2c2c2c2c292520191108000000040f1a242e363d43454646464646464646433f382f261e2831393f44464646464646464645413b342b22180f0500000000000000000000000000000000000000050a0e111313131313131313131313131313131313131313131313110e0a0500000000000000000a16212c3740484f52535353535353535353524d463e342a20150b010000000000000000000000000000000000030d17222c363f484e52535353535353535353524e473e352a1f1408000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002070c11161a1d20232527292a2b2c2c2c2c2c2b2a292725221f1c18130e0904090e13181c1f222527292b2c2c2c2c2c2b2a292725221f1b17130e09030000000000000000000000000000000000000000000000000000000002080d12161a1e21242628292b2c2c2c2c2c2c2b2a282624211e1a16110c0601000000000000000000000000000000000000000000000000000000000000000000040a0f14181c202326282a2b2c2c2c2c2c2b292725221f1b17120d08020000000000000000000000000000000000000000000000000000000002070d12161a1e212426282a2b2c2c2c2c2c2b2a282623201d1915100b06000000000000000000000000000000000000000000000000030c151d252c33383d41434546464543403c38332d28221c1e2831393f44464646464645413b332a20160b000000000005101a252e373e4346464646464646464645423c343a4044464646464646464646443f3830271d120700000000000000000000000000000000000000000005101a252e373e434646464646464646464646464646464646464646464646464646464646464646464646464646464646464645423c352c22180d020000000000000000060b0f12131313131313131313131112131313131313131313121113131313131313131313120f0b060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010911181f262b31363a3d404344454646464544423f3c38342f29231c150d05000000000000000000000000000000000000000000000000080f151a1e1f20202020202020201e1b161009030b12171c1e20202020202020201f1d19140e07000000000008121b242c323639393939393939393937332d261d161f272e343839393939393939393835302a22191006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005101a252e373e434646464646464646464645423c342c22180e040000000000000000000000000000000000000005101a242d363d424546464646464646464645423c352c23180e02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000105090d111416191b1c1e1e1f2020201f1f1e1c1a1816130f0b070300000003070c101316191b1c1e1f1f20201f1f1e1c1a1815120f0b0702000000000000000000000000000000000000000000000000000000000000000001060a0e111417191b1d1e1f1f20201f1f1e1d1b191714110e0a05000000000000000000000000000000000000000000000000000000000000000000000000000003080c101416191b1d1e1f2020201f1e1d1b1916130f0b0702000000000000000000000000000000000000000000000000000000000000000001060a0e1215171a1c1d1e1f2020201f1e1d1b191714110d0905000000000000000000000000000000000000000000000000000000030b131a21272c313437383939383634302c27221c1611161f272e343839393939393835302921180e0400000000000009131c252c32373939393939393939393836312a2f353839393939393939393937332e261e150b000000000000000000000000000000000000000000000009131c252c3237393939393939393939393939393939393939393939393939393939393939393939393939393939393939393936312b231a1106000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060d141a20252a2e313436383939393938373533302c28231e18110a030000000000000000000000000000000000000000000000000000040a0e11131313131313131313110f0a05000000060b0f12131313131313131312110d09030000000000000009121a21262a2c2c2c2c2c2c2c2c2c2b27221c140d151d23282b2c2c2c2c2c2c2c2c2c29251f1810070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131c252c3237393939393939393939393836312a221a100600000000000000000000000000000000000000000008121b242b3236393939393939393939393936312b231a110700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104070a0c0e101112121313131312110f0e0c09060300000000000000000003070a0c0e1011121313131312110f0e0c09060300000000000000000000000000000000000000000000000000000000000000000000000000000205080b0d0f101112131313131211100f0d0b0805010000000000000000000000000000000000000000000000000000000000000000000000000000000000000004070a0d0f1011121313131211100e0c09060300000000000000000000000000000000000000000000000000000000000000000000000000000205080b0d0f1112121313131211100f0d0a080401000000000000000000000000000000000000000000000000000000000000010910161c2125282a2c2c2c2c2a2724201b16110b050d151d23282b2c2c2c2c2c2c29241e170f0600000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c29251f24292b2c2c2c2c2c2c2c2c2c2b27221c140c030000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2a2520191108000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090f14191e212527292b2c2c2c2c2c2a292623201c17120d0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f151a1e1f20202020202020201e1b17110a030b12171c1e20202020202020201f1d19140d060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131a21262a2c2c2c2c2c2c2c2c2c2c2c29251f181007000000000000000000000000000000000000000000000009121a21262a2c2c2c2c2c2c2c2c2c2c2c2a2620191108000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b1015181b1e1f20201f1d1b1814100b050000030b12171c1e20202020201f1c19130d05000000000000000000010910161a1e1f20202020202020201f1d1914181c1f2020202020202020201e1b17110a0200000000000000000000000000000000000000000000000000010910161a1e1f2020202020202020202020202020202020202020202020202020202020202020202020202020202020201f1d1a140e07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004090d1215181b1d1e1f2020201f1e1c1a1714100c0701000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0e11131313131313131313120f0b06000000060b0f12131313131313131312100d080200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010910161a1e1f2020202020202020201f1d19140e0600000000000000000000000000000000000000000000000000080f151a1e1f2020202020202020201f1d1a150e0700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004080c0f1112131312110f0c0804000000000000060b0f12131313131312100d0802000000000000000000000000050a0e1113131313131313131312110d090c1012131313131313131313120f0b060000000000000000000000000000000000000000000000000000000000050a0e111313131313131313131313131313131313131313131313131313131313131313131313131313131313131313110d090300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000105090c0e10121313131312110f0d0b080400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0e111313131313131313131312110d0903000000000000000000000000000000000000000000000000000000040a0e111313131313131313131313110e09030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + m_StreamData: + offset: 0 + size: 0 + path: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 71c1514a6bd24e1e882cebbe1904ce04, type: 3} + m_Name: LiberationSans SDF + m_EditorClassIdentifier: + hashCode: 231247347 + material: {fileID: 2180264} + materialHashCode: -1183942120 + fontAssetType: 1 + m_fontInfo: + Name: Liberation Sans + PointSize: 86 + Scale: 1 + CharacterCount: 250 + LineHeight: 98.90625 + Baseline: 0 + Ascender: 77.84375 + CapHeight: 59.1875 + Descender: -18.21875 + CenterLine: 0 + SuperscriptOffset: 77.84375 + SubscriptOffset: -12.261719 + SubSize: 0.5 + Underline: -12.261719 + UnderlineThickness: 6.298828 + strikethrough: 23.675 + strikethroughThickness: 0 + TabWidth: 239.0625 + Padding: 9 + AtlasWidth: 1024 + AtlasHeight: 1024 + atlas: {fileID: 2846298} + m_glyphInfoList: + - id: 32 + x: 10 + y: 1033 + width: 23.90625 + height: 96.0625 + xOffset: 0 + yOffset: 77.84375 + xAdvance: 23.90625 + scale: 1 + - id: 33 + x: 1004 + y: 619 + width: 8.3125 + height: 59.15625 + xOffset: 7.75 + yOffset: 59.1875 + xAdvance: 23.90625 + scale: 1 + - id: 34 + x: 336 + y: 10 + width: 23.21875 + height: 18.59375 + xOffset: 3.625 + yOffset: 59.1875 + xAdvance: 30.53125 + scale: 1 + - id: 35 + x: 426 + y: 611 + width: 47.03125 + height: 58.84375 + xOffset: 0.375 + yOffset: 58.84375 + xAdvance: 47.84375 + scale: 1 + - id: 36 + x: 164 + y: 361 + width: 45.5 + height: 69.625 + xOffset: 0.90625 + yOffset: 63.6875 + xAdvance: 47.84375 + scale: 1 + - id: 37 + x: 405 + y: 953 + width: 70.34375 + height: 60.15625 + xOffset: 3.0625 + yOffset: 59.6875 + xAdvance: 76.46875 + scale: 1 + - id: 38 + x: 383 + y: 779 + width: 53 + height: 60.34375 + xOffset: 3 + yOffset: 59.53125 + xAdvance: 57.375 + scale: 1 + - id: 39 + x: 796 + y: 234 + width: 7.71875 + height: 18.59375 + xOffset: 4.34375 + yOffset: 59.1875 + xAdvance: 16.40625 + scale: 1 + - id: 40 + x: 146 + y: 738 + width: 22.78125 + height: 80.125 + xOffset: 5.3125 + yOffset: 62.34375 + xAdvance: 28.625 + scale: 1 + - id: 41 + x: 165 + y: 450 + width: 22.8125 + height: 80.125 + xOffset: 0.5 + yOffset: 62.34375 + xAdvance: 28.625 + scale: 1 + - id: 42 + x: 807 + y: 42 + width: 30.75 + height: 30.1875 + xOffset: 1.375 + yOffset: 59.1875 + xAdvance: 33.46875 + scale: 1 + - id: 43 + x: 725 + y: 422 + width: 41.78125 + height: 42.0625 + xOffset: 4.1875 + yOffset: 49.65625 + xAdvance: 50.21875 + scale: 1 + - id: 44 + x: 569 + y: 889 + width: 8.4375 + height: 20.1875 + xOffset: 7.71875 + yOffset: 9.21875 + xAdvance: 23.90625 + scale: 1 + - id: 45 + x: 764 + y: 15 + width: 21 + height: 6.71875 + xOffset: 3.8125 + yOffset: 26.21875 + xAdvance: 28.625 + scale: 1 + - id: 46 + x: 558 + y: 710 + width: 8.1875 + height: 9.1875 + xOffset: 7.84375 + yOffset: 9.21875 + xAdvance: 23.90625 + scale: 1 + - id: 47 + x: 383 + y: 667 + width: 23.90625 + height: 63.15625 + xOffset: 0 + yOffset: 62.34375 + xAdvance: 23.90625 + scale: 1 + - id: 48 + x: 787 + y: 475 + width: 41.09375 + height: 60.90625 + xOffset: 3.34375 + yOffset: 60.0625 + xAdvance: 47.84375 + scale: 1 + - id: 49 + x: 321 + y: 386 + width: 37.0625 + height: 59.15625 + xOffset: 6.53125 + yOffset: 59.1875 + xAdvance: 47.84375 + scale: 1 + - id: 50 + x: 962 + y: 298 + width: 39.1875 + height: 60.0625 + xOffset: 4.3125 + yOffset: 60.0625 + xAdvance: 47.84375 + scale: 1 + - id: 51 + x: 908 + y: 380 + width: 40.78125 + height: 60.90625 + xOffset: 3.25 + yOffset: 60.0625 + xAdvance: 47.84375 + scale: 1 + - id: 52 + x: 378 + y: 386 + width: 43.34375 + height: 59.15625 + xOffset: 1.96875 + yOffset: 59.1875 + xAdvance: 47.84375 + scale: 1 + - id: 53 + x: 441 + y: 386 + width: 40.78125 + height: 60 + xOffset: 3.4375 + yOffset: 59.1875 + xAdvance: 47.84375 + scale: 1 + - id: 54 + x: 339 + y: 48 + width: 39.6875 + height: 60.90625 + xOffset: 4.34375 + yOffset: 60.0625 + xAdvance: 47.84375 + scale: 1 + - id: 55 + x: 501 + y: 386 + width: 39.09375 + height: 59.15625 + xOffset: 4.40625 + yOffset: 59.1875 + xAdvance: 47.84375 + scale: 1 + - id: 56 + x: 968 + y: 378 + width: 40.34375 + height: 60.90625 + xOffset: 3.71875 + yOffset: 60.0625 + xAdvance: 47.84375 + scale: 1 + - id: 57 + x: 398 + y: 54 + width: 39.71875 + height: 60.90625 + xOffset: 4.03125 + yOffset: 60.0625 + xAdvance: 47.84375 + scale: 1 + - id: 58 + x: 941 + y: 175 + width: 8.1875 + height: 45.4375 + xOffset: 7.84375 + yOffset: 45.4375 + xAdvance: 23.90625 + scale: 1 + - id: 59 + x: 800 + y: 158 + width: 8.4375 + height: 56.4375 + xOffset: 7.71875 + yOffset: 45.4375 + xAdvance: 23.90625 + scale: 1 + - id: 60 + x: 422 + y: 465 + width: 41.78125 + height: 43.65625 + xOffset: 4.21875 + yOffset: 50.15625 + xAdvance: 50.21875 + scale: 1 + - id: 61 + x: 847 + y: 413 + width: 41.78125 + height: 27.71875 + xOffset: 4.1875 + yOffset: 42.1875 + xAdvance: 50.21875 + scale: 1 + - id: 62 + x: 483 + y: 465 + width: 41.78125 + height: 43.65625 + xOffset: 4.21875 + yOffset: 50.15625 + xAdvance: 50.21875 + scale: 1 + - id: 63 + x: 848 + y: 460 + width: 41.09375 + height: 60.0625 + xOffset: 3.5 + yOffset: 60.0625 + xAdvance: 47.84375 + scale: 1 + - id: 64 + x: 10 + y: 939 + width: 73.125 + height: 74.1875 + xOffset: 6.75 + yOffset: 62.34375 + xAdvance: 87.3125 + scale: 1 + - id: 65 + x: 751 + y: 871 + width: 57.03125 + height: 59.15625 + xOffset: 0.15625 + yOffset: 59.1875 + xAdvance: 57.375 + scale: 1 + - id: 66 + x: 939 + y: 619 + width: 45.75 + height: 59.15625 + xOffset: 7.03125 + yOffset: 59.1875 + xAdvance: 57.375 + scale: 1 + - id: 67 + x: 825 + y: 782 + width: 54.46875 + height: 60.90625 + xOffset: 4.34375 + yOffset: 60.0625 + xAdvance: 62.09375 + scale: 1 + - id: 68 + x: 808 + y: 703 + width: 50.9375 + height: 59.15625 + xOffset: 7.03125 + yOffset: 59.1875 + xAdvance: 62.09375 + scale: 1 + - id: 69 + x: 492 + y: 707 + width: 46.59375 + height: 59.15625 + xOffset: 7.03125 + yOffset: 59.1875 + xAdvance: 57.375 + scale: 1 + - id: 70 + x: 725 + y: 484 + width: 42.03125 + height: 59.15625 + xOffset: 7.03125 + yOffset: 59.1875 + xAdvance: 52.53125 + scale: 1 + - id: 71 + x: 593 + y: 809 + width: 56.15625 + height: 60.90625 + xOffset: 4.3125 + yOffset: 60.0625 + xAdvance: 66.90625 + scale: 1 + - id: 72 + x: 947 + y: 698 + width: 48.03125 + height: 59.15625 + xOffset: 7.03125 + yOffset: 59.1875 + xAdvance: 62.09375 + scale: 1 + - id: 73 + x: 571 + y: 56 + width: 8.03125 + height: 59.15625 + xOffset: 7.90625 + yOffset: 59.1875 + xAdvance: 23.90625 + scale: 1 + - id: 74 + x: 655 + y: 66 + width: 35.28125 + height: 60 + xOffset: 1.34375 + yOffset: 59.1875 + xAdvance: 43 + scale: 1 + - id: 75 + x: 682 + y: 875 + width: 49.34375 + height: 59.15625 + xOffset: 7.03125 + yOffset: 59.1875 + xAdvance: 57.375 + scale: 1 + - id: 76 + x: 514 + y: 56 + width: 37.90625 + height: 59.15625 + xOffset: 7.03125 + yOffset: 59.1875 + xAdvance: 47.84375 + scale: 1 + - id: 77 + x: 828 + y: 862 + width: 57.53125 + height: 59.15625 + xOffset: 7.03125 + yOffset: 59.1875 + xAdvance: 71.625 + scale: 1 + - id: 78 + x: 315 + y: 671 + width: 48.03125 + height: 59.15625 + xOffset: 7.03125 + yOffset: 59.1875 + xAdvance: 62.09375 + scale: 1 + - id: 79 + x: 305 + y: 779 + width: 58.71875 + height: 60.90625 + xOffset: 4.0625 + yOffset: 60.0625 + xAdvance: 66.90625 + scale: 1 + - id: 80 + x: 670 + y: 572 + width: 45.75 + height: 59.15625 + xOffset: 7.03125 + yOffset: 59.1875 + xAdvance: 57.375 + scale: 1 + - id: 81 + x: 10 + y: 843 + width: 58.71875 + height: 76.3125 + xOffset: 4.0625 + yOffset: 60.0625 + xAdvance: 66.90625 + scale: 1 + - id: 82 + x: 666 + y: 730 + width: 51.0625 + height: 59.15625 + xOffset: 7.03125 + yOffset: 59.1875 + xAdvance: 62.09375 + scale: 1 + - id: 83 + x: 878 + y: 701 + width: 49.5 + height: 60.90625 + xOffset: 3.875 + yOffset: 60.0625 + xAdvance: 57.375 + scale: 1 + - id: 84 + x: 600 + y: 651 + width: 48.625 + height: 59.15625 + xOffset: 1.90625 + yOffset: 59.1875 + xAdvance: 52.53125 + scale: 1 + - id: 85 + x: 668 + y: 651 + width: 48.84375 + height: 60 + xOffset: 6.625 + yOffset: 59.1875 + xAdvance: 62.09375 + scale: 1 + - id: 86 + x: 749 + y: 792 + width: 56.59375 + height: 59.15625 + xOffset: 0.375 + yOffset: 59.1875 + xAdvance: 57.375 + scale: 1 + - id: 87 + x: 305 + y: 954 + width: 80.5 + height: 59.15625 + xOffset: 0.375 + yOffset: 59.1875 + xAdvance: 81.15625 + scale: 1 + - id: 88 + x: 899 + y: 781 + width: 53.625 + height: 59.15625 + xOffset: 1.90625 + yOffset: 59.1875 + xAdvance: 57.375 + scale: 1 + - id: 89 + x: 593 + y: 730 + width: 53.59375 + height: 59.15625 + xOffset: 1.875 + yOffset: 59.1875 + xAdvance: 57.375 + scale: 1 + - id: 90 + x: 872 + y: 622 + width: 47.125 + height: 59.15625 + xOffset: 2.71875 + yOffset: 59.1875 + xAdvance: 52.53125 + scale: 1 + - id: 91 + x: 188 + y: 758 + width: 17.09375 + height: 80.15625 + xOffset: 6.125 + yOffset: 62.34375 + xAdvance: 23.90625 + scale: 1 + - id: 92 + x: 557 + y: 624 + width: 23.90625 + height: 63.15625 + xOffset: 0 + yOffset: 62.34375 + xAdvance: 23.90625 + scale: 1 + - id: 93 + x: 455 + y: 773 + width: 17.0625 + height: 80.15625 + xOffset: 0.65625 + yOffset: 62.34375 + xAdvance: 23.90625 + scale: 1 + - id: 94 + x: 964 + y: 248 + width: 39.53125 + height: 30.90625 + xOffset: 0.40625 + yOffset: 59.1875 + xAdvance: 40.34375 + scale: 1 + - id: 95 + x: 894 + y: 265 + width: 50.09375 + height: 5.46875 + xOffset: -1.3125 + yOffset: -11.625 + xAdvance: 47.84375 + scale: 1 + - id: 96 + x: 807 + y: 10 + width: 17.8125 + height: 12.875 + xOffset: 4.4375 + yOffset: 63.34375 + xAdvance: 28.625 + scale: 1 + - id: 97 + x: 99 + y: 12 + width: 44.1875 + height: 47.125 + xOffset: 3.625 + yOffset: 46.28125 + xAdvance: 47.84375 + scale: 1 + - id: 98 + x: 456 + y: 135 + width: 38.6875 + height: 63.15625 + xOffset: 5.53125 + yOffset: 62.34375 + xAdvance: 47.84375 + scale: 1 + - id: 99 + x: 163 + y: 12 + width: 37.0625 + height: 47.125 + xOffset: 3.625 + yOffset: 46.28125 + xAdvance: 43 + scale: 1 + - id: 100 + x: 485 + y: 528 + width: 38.65625 + height: 63.15625 + xOffset: 3.59375 + yOffset: 62.34375 + xAdvance: 47.84375 + scale: 1 + - id: 101 + x: 220 + y: 12 + width: 40.34375 + height: 47.125 + xOffset: 3.625 + yOffset: 46.28125 + xAdvance: 47.84375 + scale: 1 + - id: 102 + x: 632 + y: 145 + width: 22.8125 + height: 62.21875 + xOffset: 1.1875 + yOffset: 62.25 + xAdvance: 23.90625 + scale: 1 + - id: 103 + x: 514 + y: 135 + width: 38.65625 + height: 64 + xOffset: 3.59375 + yOffset: 46.15625 + xAdvance: 47.84375 + scale: 1 + - id: 104 + x: 674 + y: 145 + width: 36.28125 + height: 62.3125 + xOffset: 5.9375 + yOffset: 62.34375 + xAdvance: 47.84375 + scale: 1 + - id: 105 + x: 722 + y: 228 + width: 7.5625 + height: 62.3125 + xOffset: 5.75 + yOffset: 62.34375 + xAdvance: 19.09375 + scale: 1 + - id: 106 + x: 558 + y: 777 + width: 15.40625 + height: 80.15625 + xOffset: -2.125 + yOffset: 62.34375 + xAdvance: 19.09375 + scale: 1 + - id: 107 + x: 543 + y: 542 + width: 37.34375 + height: 62.3125 + xOffset: 5.78125 + yOffset: 62.34375 + xAdvance: 43 + scale: 1 + - id: 108 + x: 730 + y: 146 + width: 7.5625 + height: 62.3125 + xOffset: 5.78125 + yOffset: 62.34375 + xAdvance: 19.09375 + scale: 1 + - id: 109 + x: 669 + y: 809 + width: 60.25 + height: 46.28125 + xOffset: 5.6875 + yOffset: 46.28125 + xAdvance: 71.625 + scale: 1 + - id: 110 + x: 544 + y: 476 + width: 36.53125 + height: 46.28125 + xOffset: 5.6875 + yOffset: 46.28125 + xAdvance: 47.84375 + scale: 1 + - id: 111 + x: 902 + y: 313 + width: 40.59375 + height: 47.125 + xOffset: 3.59375 + yOffset: 46.28125 + xAdvance: 47.84375 + scale: 1 + - id: 112 + x: 263 + y: 476 + width: 38.6875 + height: 64.0625 + xOffset: 5.53125 + yOffset: 46.25 + xAdvance: 47.84375 + scale: 1 + - id: 113 + x: 335 + y: 212 + width: 38.71875 + height: 64.125 + xOffset: 3.59375 + yOffset: 46.28125 + xAdvance: 47.84375 + scale: 1 + - id: 114 + x: 796 + y: 272 + width: 21.5 + height: 46.28125 + xOffset: 5.6875 + yOffset: 46.28125 + xAdvance: 28.625 + scale: 1 + - id: 115 + x: 837 + y: 268 + width: 37.5 + height: 47 + xOffset: 2.375 + yOffset: 46.15625 + xAdvance: 43 + scale: 1 + - id: 116 + x: 766 + y: 80 + width: 21.9375 + height: 56.25 + xOffset: 1.28125 + yOffset: 55.625 + xAdvance: 23.90625 + scale: 1 + - id: 117 + x: 807 + y: 92 + width: 36.53125 + height: 46.28125 + xOffset: 5.5625 + yOffset: 45.4375 + xAdvance: 47.84375 + scale: 1 + - id: 118 + x: 600 + y: 393 + width: 42.4375 + height: 45.4375 + xOffset: 0.28125 + yOffset: 45.4375 + xAdvance: 43 + scale: 1 + - id: 119 + x: 600 + y: 889 + width: 62.4375 + height: 45.4375 + xOffset: -0.15625 + yOffset: 45.4375 + xAdvance: 62.09375 + scale: 1 + - id: 120 + x: 662 + y: 393 + width: 41.09375 + height: 45.4375 + xOffset: 0.9375 + yOffset: 45.4375 + xAdvance: 43 + scale: 1 + - id: 121 + x: 663 + y: 489 + width: 42.625 + height: 63.28125 + xOffset: 0.1875 + yOffset: 45.4375 + xAdvance: 43 + scale: 1 + - id: 122 + x: 828 + y: 178 + width: 35.21875 + height: 45.4375 + xOffset: 3.46875 + yOffset: 45.4375 + xAdvance: 43 + scale: 1 + - id: 123 + x: 987 + y: 933 + width: 25.78125 + height: 80.15625 + xOffset: 1.40625 + yOffset: 62.34375 + xAdvance: 28.71875 + scale: 1 + - id: 124 + x: 229 + y: 371 + width: 6.96875 + height: 80.53125 + xOffset: 7.65625 + yOffset: 62.34375 + xAdvance: 22.34375 + scale: 1 + - id: 125 + x: 216 + y: 79 + width: 25.71875 + height: 80.15625 + xOffset: 1.40625 + yOffset: 62.34375 + xAdvance: 28.71875 + scale: 1 + - id: 126 + x: 663 + y: 459 + width: 42.5 + height: 10.65625 + xOffset: 3.84375 + yOffset: 33.90625 + xAdvance: 50.21875 + scale: 1 + - id: 160 + x: 10 + y: 1033 + width: 23.90625 + height: 96.0625 + xOffset: 0 + yOffset: 77.84375 + xAdvance: 23.90625 + scale: 1 + - id: 161 + x: 710 + y: 66 + width: 8.3125 + height: 59.15625 + xOffset: 10.15625 + yOffset: 45.4375 + xAdvance: 28.625 + scale: 1 + - id: 162 + x: 457 + y: 55 + width: 37.09375 + height: 60.46875 + xOffset: 5.65625 + yOffset: 59.1875 + xAdvance: 47.84375 + scale: 1 + - id: 163 + x: 600 + y: 537 + width: 43.9375 + height: 60.0625 + xOffset: 2.40625 + yOffset: 60.0625 + xAdvance: 47.84375 + scale: 1 + - id: 164 + x: 883 + y: 182 + width: 38.34375 + height: 38.40625 + xOffset: 4.71875 + yOffset: 47.84375 + xAdvance: 47.84375 + scale: 1 + - id: 165 + x: 736 + y: 642 + width: 48.0625 + height: 59.15625 + xOffset: -0.09375 + yOffset: 59.1875 + xAdvance: 47.84375 + scale: 1 + - id: 166 + x: 255 + y: 371 + width: 6.96875 + height: 80.53125 + xOffset: 7.65625 + yOffset: 62.34375 + xAdvance: 22.34375 + scale: 1 + - id: 167 + x: 191 + y: 559 + width: 38.15625 + height: 69.53125 + xOffset: 4.8125 + yOffset: 62.34375 + xAdvance: 47.84375 + scale: 1 + - id: 168 + x: 735 + y: 313 + width: 23.40625 + height: 7.71875 + xOffset: 1.875 + yOffset: 58.9375 + xAdvance: 28.625 + scale: 1 + - id: 169 + x: 401 + y: 873 + width: 60.71875 + height: 60.71875 + xOffset: 1.28125 + yOffset: 60.0625 + xAdvance: 63.375 + scale: 1 + - id: 170 + x: 982 + y: 881 + width: 31.03125 + height: 32.78125 + xOffset: 1.0625 + yOffset: 60.15625 + xAdvance: 31.84375 + scale: 1 + - id: 171 + x: 644 + y: 13 + width: 40.84375 + height: 33.5625 + xOffset: 3.46875 + yOffset: 39.5 + xAdvance: 47.84375 + scale: 1 + - id: 172 + x: 398 + y: 10 + width: 41.78125 + height: 24.09375 + xOffset: 4.1875 + yOffset: 31.6875 + xAdvance: 50.21875 + scale: 1 + - id: 173 + x: 955 + y: 87 + width: 21 + height: 6.71875 + xOffset: 3.8125 + yOffset: 26.21875 + xAdvance: 28.625 + scale: 1 + - id: 174 + x: 225 + y: 779 + width: 60.71875 + height: 60.71875 + xOffset: 1.28125 + yOffset: 60.0625 + xAdvance: 63.375 + scale: 1 + - id: 175 + x: 894 + y: 290 + width: 48.9375 + height: 3.9375 + xOffset: -0.71875 + yOffset: 64.9375 + xAdvance: 47.5 + scale: 1 + - id: 176 + x: 912 + y: 43 + width: 24.09375 + height: 23.9375 + xOffset: 5.09375 + yOffset: 60.0625 + xAdvance: 34.40625 + scale: 1 + - id: 177 + x: 970 + y: 458 + width: 41.78125 + height: 51.1875 + xOffset: 2.71875 + yOffset: 51.21875 + xAdvance: 47.1875 + scale: 1 + - id: 178 + x: 863 + y: 123 + width: 25.28125 + height: 36 + xOffset: 1.71875 + yOffset: 59.6875 + xAdvance: 28.625 + scale: 1 + - id: 179 + x: 599 + y: 10 + width: 25.84375 + height: 36.53125 + xOffset: 1.125 + yOffset: 59.6875 + xAdvance: 28.625 + scale: 1 + - id: 180 + x: 844 + y: 10 + width: 17.8125 + height: 12.875 + xOffset: 3 + yOffset: 63.34375 + xAdvance: 28.625 + scale: 1 + - id: 181 + x: 972 + y: 777 + width: 41.6875 + height: 63.28125 + xOffset: 5.875 + yOffset: 45.4375 + xAdvance: 49.5625 + scale: 1 + - id: 182 + x: 198 + y: 179 + width: 39.15625 + height: 70.25 + xOffset: 3.34375 + yOffset: 59.1875 + xAdvance: 46.1875 + scale: 1 + - id: 183 + x: 857 + y: 42 + width: 8.1875 + height: 9.25 + xOffset: 10.1875 + yOffset: 27.96875 + xAdvance: 28.625 + scale: 1 + - id: 184 + x: 558 + y: 739 + width: 15.28125 + height: 18.21875 + xOffset: 4.96875 + yOffset: 0 + xAdvance: 28.625 + scale: 1 + - id: 185 + x: 912 + y: 86 + width: 23.375 + height: 35.5 + xOffset: 3.34375 + yOffset: 59.1875 + xAdvance: 28.625 + scale: 1 + - id: 186 + x: 863 + y: 71 + width: 29.25 + height: 32.78125 + xOffset: 1.125 + yOffset: 60.15625 + xAdvance: 31.40625 + scale: 1 + - id: 187 + x: 704 + y: 11 + width: 40.84375 + height: 33.5625 + xOffset: 3.46875 + yOffset: 39.5 + xAdvance: 47.84375 + scale: 1 + - id: 188 + x: 582 + y: 954 + width: 65.40625 + height: 59.15625 + xOffset: 2.34375 + yOffset: 59.1875 + xAdvance: 71.71875 + scale: 1 + - id: 189 + x: 495 + y: 954 + width: 67.03125 + height: 59.15625 + xOffset: 2.34375 + yOffset: 59.1875 + xAdvance: 71.71875 + scale: 1 + - id: 190 + x: 667 + y: 954 + width: 64.71875 + height: 59.65625 + xOffset: 3.0625 + yOffset: 59.6875 + xAdvance: 71.71875 + scale: 1 + - id: 191 + x: 909 + y: 460 + width: 41.125 + height: 60.0625 + xOffset: 5.5 + yOffset: 45.4375 + xAdvance: 52.53125 + scale: 1 + - id: 192 + x: 910 + y: 939 + width: 57.03125 + height: 74.59375 + xOffset: 0.15625 + yOffset: 74.59375 + xAdvance: 57.375 + scale: 1 + - id: 193 + x: 88 + y: 453 + width: 57.03125 + height: 74.59375 + xOffset: 0.15625 + yOffset: 74.59375 + xAdvance: 57.375 + scale: 1 + - id: 194 + x: 10 + y: 367 + width: 57.03125 + height: 75.15625 + xOffset: 0.15625 + yOffset: 75.1875 + xAdvance: 57.375 + scale: 1 + - id: 195 + x: 10 + y: 272 + width: 57.03125 + height: 75.5 + xOffset: 0.15625 + yOffset: 75.53125 + xAdvance: 57.375 + scale: 1 + - id: 196 + x: 87 + y: 362 + width: 57.03125 + height: 71.96875 + xOffset: 0.15625 + yOffset: 72 + xAdvance: 57.375 + scale: 1 + - id: 197 + x: 10 + y: 177 + width: 57.03125 + height: 75.0625 + xOffset: 0.15625 + yOffset: 75.0625 + xAdvance: 57.375 + scale: 1 + - id: 198 + x: 204 + y: 954 + width: 81.3125 + height: 59.15625 + xOffset: 1 + yOffset: 59.1875 + xAdvance: 86 + scale: 1 + - id: 199 + x: 10 + y: 79 + width: 54.46875 + height: 78.28125 + xOffset: 4.34375 + yOffset: 60.0625 + xAdvance: 62.09375 + scale: 1 + - id: 200 + x: 84 + y: 79 + width: 46.59375 + height: 74.59375 + xOffset: 7.03125 + yOffset: 74.59375 + xAdvance: 57.375 + scale: 1 + - id: 201 + x: 150 + y: 79 + width: 46.59375 + height: 74.59375 + xOffset: 7.03125 + yOffset: 74.59375 + xAdvance: 57.375 + scale: 1 + - id: 202 + x: 88 + y: 547 + width: 46.59375 + height: 75.15625 + xOffset: 7.03125 + yOffset: 75.1875 + xAdvance: 57.375 + scale: 1 + - id: 203 + x: 492 + y: 786 + width: 46.59375 + height: 71.96875 + xOffset: 7.03125 + yOffset: 72 + xAdvance: 57.375 + scale: 1 + - id: 204 + x: 150 + y: 644 + width: 17.8125 + height: 74.59375 + xOffset: 0.375 + yOffset: 74.59375 + xAdvance: 23.90625 + scale: 1 + - id: 205 + x: 154 + y: 550 + width: 17.8125 + height: 74.59375 + xOffset: 5.9375 + yOffset: 74.59375 + xAdvance: 23.90625 + scale: 1 + - id: 206 + x: 354 + y: 859 + width: 27.8125 + height: 75.15625 + xOffset: -1.9375 + yOffset: 75.1875 + xAdvance: 23.90625 + scale: 1 + - id: 207 + x: 155 + y: 177 + width: 23.40625 + height: 71.96875 + xOffset: 0.28125 + yOffset: 72 + xAdvance: 23.90625 + scale: 1 + - id: 208 + x: 905 + y: 860 + width: 57.40625 + height: 59.15625 + xOffset: 0.5625 + yOffset: 59.1875 + xAdvance: 62.09375 + scale: 1 + - id: 209 + x: 87 + y: 173 + width: 48.03125 + height: 75.5 + xOffset: 7.03125 + yOffset: 75.53125 + xAdvance: 62.09375 + scale: 1 + - id: 210 + x: 10 + y: 652 + width: 58.71875 + height: 75.4375 + xOffset: 4.0625 + yOffset: 74.59375 + xAdvance: 66.90625 + scale: 1 + - id: 211 + x: 10 + y: 557 + width: 58.71875 + height: 75.4375 + xOffset: 4.0625 + yOffset: 74.59375 + xAdvance: 66.90625 + scale: 1 + - id: 212 + x: 10 + y: 462 + width: 58.71875 + height: 76 + xOffset: 4.0625 + yOffset: 75.1875 + xAdvance: 66.90625 + scale: 1 + - id: 213 + x: 10 + y: 747 + width: 58.71875 + height: 76.34375 + xOffset: 4.0625 + yOffset: 75.53125 + xAdvance: 66.90625 + scale: 1 + - id: 214 + x: 832 + y: 941 + width: 58.71875 + height: 72.8125 + xOffset: 4.0625 + yOffset: 72 + xAdvance: 66.90625 + scale: 1 + - id: 215 + x: 969 + y: 190 + width: 38.34375 + height: 38.40625 + xOffset: 5.9375 + yOffset: 47.84375 + xAdvance: 50.21875 + scale: 1 + - id: 216 + x: 751 + y: 950 + width: 61.03125 + height: 63.78125 + xOffset: 2.96875 + yOffset: 61.5625 + xAdvance: 66.90625 + scale: 1 + - id: 217 + x: 150 + y: 858 + width: 48.84375 + height: 75.4375 + xOffset: 6.625 + yOffset: 74.59375 + xAdvance: 62.09375 + scale: 1 + - id: 218 + x: 218 + y: 859 + width: 48.84375 + height: 75.4375 + xOffset: 6.625 + yOffset: 74.59375 + xAdvance: 62.09375 + scale: 1 + - id: 219 + x: 286 + y: 859 + width: 48.84375 + height: 76 + xOffset: 6.625 + yOffset: 75.1875 + xAdvance: 62.09375 + scale: 1 + - id: 220 + x: 160 + y: 269 + width: 48.84375 + height: 72.8125 + xOffset: 6.625 + yOffset: 72 + xAdvance: 62.09375 + scale: 1 + - id: 221 + x: 87 + y: 268 + width: 53.59375 + height: 74.59375 + xOffset: 1.875 + yOffset: 74.59375 + xAdvance: 57.375 + scale: 1 + - id: 222 + x: 735 + y: 563 + width: 45.75 + height: 59.15625 + xOffset: 7.03125 + yOffset: 59.1875 + xAdvance: 57.375 + scale: 1 + - id: 223 + x: 422 + y: 528 + width: 43.03125 + height: 63.15625 + xOffset: 5.9375 + yOffset: 62.34375 + xAdvance: 52.53125 + scale: 1 + - id: 224 + x: 251 + y: 670 + width: 44.1875 + height: 64.15625 + xOffset: 3.625 + yOffset: 63.34375 + xAdvance: 47.84375 + scale: 1 + - id: 225 + x: 426 + y: 689 + width: 44.1875 + height: 64.15625 + xOffset: 3.625 + yOffset: 63.34375 + xAdvance: 47.84375 + scale: 1 + - id: 226 + x: 493 + y: 624 + width: 44.1875 + height: 63.46875 + xOffset: 3.625 + yOffset: 62.625 + xAdvance: 47.84375 + scale: 1 + - id: 227 + x: 865 + y: 540 + width: 44.1875 + height: 62.53125 + xOffset: 3.625 + yOffset: 61.6875 + xAdvance: 47.84375 + scale: 1 + - id: 228 + x: 929 + y: 540 + width: 44.1875 + height: 59.75 + xOffset: 3.625 + yOffset: 58.9375 + xAdvance: 47.84375 + scale: 1 + - id: 229 + x: 187 + y: 648 + width: 44.1875 + height: 70.1875 + xOffset: 3.625 + yOffset: 69.34375 + xAdvance: 47.84375 + scale: 1 + - id: 230 + x: 10 + y: 12 + width: 69.875 + height: 47.125 + xOffset: 2.75 + yOffset: 46.28125 + xAdvance: 76.46875 + scale: 1 + - id: 231 + x: 339 + y: 128 + width: 37.0625 + height: 64.5 + xOffset: 3.625 + yOffset: 46.28125 + xAdvance: 43 + scale: 1 + - id: 232 + x: 384 + y: 302 + width: 40.34375 + height: 64.15625 + xOffset: 3.625 + yOffset: 63.34375 + xAdvance: 47.84375 + scale: 1 + - id: 233 + x: 393 + y: 218 + width: 40.34375 + height: 64.15625 + xOffset: 3.625 + yOffset: 63.34375 + xAdvance: 47.84375 + scale: 1 + - id: 234 + x: 599 + y: 310 + width: 40.34375 + height: 63.46875 + xOffset: 3.625 + yOffset: 62.625 + xAdvance: 47.84375 + scale: 1 + - id: 235 + x: 782 + y: 338 + width: 40.34375 + height: 59.75 + xOffset: 3.625 + yOffset: 58.9375 + xAdvance: 47.84375 + scale: 1 + - id: 236 + x: 629 + y: 227 + width: 17.8125 + height: 63.3125 + xOffset: 0.40625 + yOffset: 63.34375 + xAdvance: 23.90625 + scale: 1 + - id: 237 + x: 659 + y: 310 + width: 17.8125 + height: 63.3125 + xOffset: 5.65625 + yOffset: 63.34375 + xAdvance: 23.90625 + scale: 1 + - id: 238 + x: 735 + y: 340 + width: 27.8125 + height: 62.625 + xOffset: -1.875 + yOffset: 62.625 + xAdvance: 23.90625 + scale: 1 + - id: 239 + x: 757 + y: 156 + width: 23.40625 + height: 58.90625 + xOffset: 0.3125 + yOffset: 58.9375 + xAdvance: 23.90625 + scale: 1 + - id: 240 + x: 396 + y: 134 + width: 41 + height: 64.40625 + xOffset: 3.59375 + yOffset: 63.59375 + xAdvance: 47.84375 + scale: 1 + - id: 241 + x: 280 + y: 10 + width: 36.53125 + height: 61.6875 + xOffset: 5.84375 + yOffset: 61.6875 + xAdvance: 47.84375 + scale: 1 + - id: 242 + x: 444 + y: 302 + width: 40.59375 + height: 64.15625 + xOffset: 3.59375 + yOffset: 63.34375 + xAdvance: 47.84375 + scale: 1 + - id: 243 + x: 453 + y: 218 + width: 40.59375 + height: 64.15625 + xOffset: 3.59375 + yOffset: 63.34375 + xAdvance: 47.84375 + scale: 1 + - id: 244 + x: 569 + y: 227 + width: 40.59375 + height: 63.46875 + xOffset: 3.59375 + yOffset: 62.625 + xAdvance: 47.84375 + scale: 1 + - id: 245 + x: 572 + y: 145 + width: 40.59375 + height: 62.53125 + xOffset: 3.59375 + yOffset: 61.6875 + xAdvance: 47.84375 + scale: 1 + - id: 246 + x: 842 + y: 334 + width: 40.59375 + height: 59.75 + xOffset: 3.59375 + yOffset: 58.9375 + xAdvance: 47.84375 + scale: 1 + - id: 247 + x: 786 + y: 417 + width: 41.78125 + height: 38.53125 + xOffset: 2.71875 + yOffset: 47.9375 + xAdvance: 47.1875 + scale: 1 + - id: 248 + x: 804 + y: 635 + width: 48.71875 + height: 48.46875 + xOffset: 1.84375 + yOffset: 46.875 + xAdvance: 52.53125 + scale: 1 + - id: 249 + x: 504 + y: 302 + width: 36.53125 + height: 64.15625 + xOffset: 5.8125 + yOffset: 63.34375 + xAdvance: 47.84375 + scale: 1 + - id: 250 + x: 513 + y: 218 + width: 36.53125 + height: 64.15625 + xOffset: 5.8125 + yOffset: 63.34375 + xAdvance: 47.84375 + scale: 1 + - id: 251 + x: 666 + y: 227 + width: 36.53125 + height: 63.46875 + xOffset: 5.8125 + yOffset: 62.625 + xAdvance: 47.84375 + scale: 1 + - id: 252 + x: 599 + y: 66 + width: 36.53125 + height: 59.75 + xOffset: 5.8125 + yOffset: 58.9375 + xAdvance: 47.84375 + scale: 1 + - id: 253 + x: 88 + y: 838 + width: 42.625 + height: 81.15625 + xOffset: 0.1875 + yOffset: 63.34375 + xAdvance: 43 + scale: 1 + - id: 254 + x: 88 + y: 738 + width: 38.4375 + height: 80.15625 + xOffset: 5.78125 + yOffset: 62.34375 + xAdvance: 47.84375 + scale: 1 + - id: 255 + x: 88 + y: 642 + width: 42.625 + height: 76.75 + xOffset: 0.1875 + yOffset: 58.9375 + xAdvance: 43 + scale: 1 + - id: 8192 + x: 10 + y: 1033 + width: 0 + height: 0 + xOffset: 0 + yOffset: 0 + xAdvance: 43 + scale: 1 + - id: 8193 + x: 10 + y: 1033 + width: 0 + height: 0 + xOffset: 0 + yOffset: 0 + xAdvance: 86 + scale: 1 + - id: 8194 + x: 10 + y: 1033 + width: 0 + height: 0 + xOffset: 0 + yOffset: 0 + xAdvance: 43 + scale: 1 + - id: 8195 + x: 10 + y: 1033 + width: 0 + height: 0 + xOffset: 0 + yOffset: 0 + xAdvance: 86 + scale: 1 + - id: 8196 + x: 10 + y: 1033 + width: 0 + height: 0 + xOffset: 0 + yOffset: 0 + xAdvance: 28.6875 + scale: 1 + - id: 8197 + x: 10 + y: 1033 + width: 0 + height: 0 + xOffset: 0 + yOffset: 0 + xAdvance: 21.5 + scale: 1 + - id: 8198 + x: 10 + y: 1033 + width: 0 + height: 0 + xOffset: 0 + yOffset: 0 + xAdvance: 14.3125 + scale: 1 + - id: 8199 + x: 10 + y: 1033 + width: 0 + height: 0 + xOffset: 0 + yOffset: 0 + xAdvance: 47.84375 + scale: 1 + - id: 8200 + x: 10 + y: 1033 + width: 0 + height: 0 + xOffset: 0 + yOffset: 0 + xAdvance: 23.90625 + scale: 1 + - id: 8201 + x: 10 + y: 1033 + width: 0 + height: 0 + xOffset: 0 + yOffset: 0 + xAdvance: 17.21875 + scale: 1 + - id: 8202 + x: 10 + y: 1033 + width: 0 + height: 0 + xOffset: 0 + yOffset: 0 + xAdvance: 7.1875 + scale: 1 + - id: 8203 + x: 10 + y: 1033 + width: 0 + height: 0 + xOffset: 0 + yOffset: 0 + xAdvance: 0 + scale: 1 + - id: 8204 + x: 399 + y: 470 + width: 3.5 + height: 65.5 + xOffset: -1.78125 + yOffset: 54.0625 + xAdvance: 0 + scale: 1 + - id: 8205 + x: 228 + y: 271 + width: 18.8125 + height: 70.84375 + xOffset: -9.40625 + yOffset: 59.40625 + xAdvance: 0 + scale: 1 + - id: 8206 + x: 257 + y: 181 + width: 20 + height: 70.84375 + xOffset: -1.75 + yOffset: 59.40625 + xAdvance: 0 + scale: 1 + - id: 8207 + x: 261 + y: 91 + width: 20 + height: 70.84375 + xOffset: -18.3125 + yOffset: 59.40625 + xAdvance: 0 + scale: 1 + - id: 8210 + x: 823 + y: 243 + width: 47.78125 + height: 5.75 + xOffset: 0 + yOffset: 24.71875 + xAdvance: 47.84375 + scale: 1 + - id: 8211 + x: 890 + y: 240 + width: 47.78125 + height: 5.75 + xOffset: 0 + yOffset: 24.71875 + xAdvance: 47.84375 + scale: 1 + - id: 8212 + x: 225 + y: 754 + width: 86 + height: 5.75 + xOffset: 0 + yOffset: 24.71875 + xAdvance: 86 + scale: 1 + - id: 8213 + x: 495 + y: 929 + width: 86 + height: 5.75 + xOffset: 0 + yOffset: 24.71875 + xAdvance: 86 + scale: 1 + - id: 8214 + x: 560 + y: 394 + width: 20.46875 + height: 62.3125 + xOffset: 7.5 + yOffset: 62.34375 + xAdvance: 35.53125 + scale: 1 + - id: 8215 + x: 600 + y: 617 + width: 50.09375 + height: 14.5625 + xOffset: -1.3125 + yOffset: -3.65625 + xAdvance: 47.5 + scale: 1 + - id: 8216 + x: 996 + y: 127 + width: 8.4375 + height: 19.1875 + xOffset: 5.3125 + yOffset: 59.1875 + xAdvance: 19.09375 + scale: 1 + - id: 8217 + x: 390 + y: 589 + width: 8.4375 + height: 19.1875 + xOffset: 5.3125 + yOffset: 59.1875 + xAdvance: 19.09375 + scale: 1 + - id: 8218 + x: 556 + y: 17 + width: 8.4375 + height: 19.1875 + xOffset: 5.3125 + yOffset: 8.21875 + xAdvance: 19.09375 + scale: 1 + - id: 8219 + x: 996 + y: 88 + width: 8.4375 + height: 19.1875 + xOffset: 5.28125 + yOffset: 59.1875 + xAdvance: 19.09375 + scale: 1 + - id: 8220 + x: 360 + y: 628 + width: 22.34375 + height: 19.1875 + xOffset: 3.125 + yOffset: 59.1875 + xAdvance: 28.625 + scale: 1 + - id: 8221 + x: 348 + y: 589 + width: 22.34375 + height: 19.1875 + xOffset: 3.125 + yOffset: 59.1875 + xAdvance: 28.625 + scale: 1 + - id: 8222 + x: 514 + y: 17 + width: 22.34375 + height: 19.1875 + xOffset: 3.125 + yOffset: 8.21875 + xAdvance: 28.625 + scale: 1 + - id: 8223 + x: 766 + y: 41 + width: 21.4375 + height: 19.1875 + xOffset: 3 + yOffset: 59.1875 + xAdvance: 28.625 + scale: 1 + - id: 8224 + x: 207 + y: 471 + width: 36.28125 + height: 68.09375 + xOffset: 5.78125 + yOffset: 62.34375 + xAdvance: 47.84375 + scale: 1 + - id: 8225 + x: 249 + y: 560 + width: 36.3125 + height: 68.21875 + xOffset: 5.6875 + yOffset: 62.34375 + xAdvance: 47.84375 + scale: 1 + - id: 8226 + x: 305 + y: 587 + width: 23.3125 + height: 23.3125 + xOffset: 3.375 + yOffset: 40.15625 + xAdvance: 30.09375 + scale: 1 + - id: 8230 + x: 330 + y: 750 + width: 62.625 + height: 9.1875 + xOffset: 11.65625 + yOffset: 9.21875 + xAdvance: 86 + scale: 1 + - id: 8234 + x: 560 + y: 311 + width: 20 + height: 63.25 + xOffset: -1.75 + yOffset: 51.78125 + xAdvance: 0 + scale: 1 + - id: 8235 + x: 696 + y: 310 + width: 20 + height: 63.25 + xOffset: -18.28125 + yOffset: 51.78125 + xAdvance: 0 + scale: 1 + - id: 8236 + x: 266 + y: 281 + width: 20 + height: 70.71875 + xOffset: -10 + yOffset: 59.28125 + xAdvance: 0 + scale: 1 + - id: 8237 + x: 305 + y: 296 + width: 20 + height: 70.71875 + xOffset: -10 + yOffset: 59.28125 + xAdvance: 0 + scale: 1 + - id: 8238 + x: 296 + y: 191 + width: 20 + height: 70.71875 + xOffset: -10 + yOffset: 59.28125 + xAdvance: 0 + scale: 1 + - id: 8239 + x: 10 + y: 1033 + width: 0 + height: 0 + xOffset: 0 + yOffset: 0 + xAdvance: 17.21875 + scale: 1 + - id: 8240 + x: 103 + y: 953 + width: 81.34375 + height: 60.125 + xOffset: 2.28125 + yOffset: 59.6875 + xAdvance: 86 + scale: 1 + - id: 8242 + x: 908 + y: 141 + width: 10.9375 + height: 21.78125 + xOffset: 3.5625 + yOffset: 59.1875 + xAdvance: 16.125 + scale: 1 + - id: 8243 + x: 315 + y: 630 + width: 25.3125 + height: 21.78125 + xOffset: 3.5625 + yOffset: 59.1875 + xAdvance: 30.4375 + scale: 1 + - id: 8244 + x: 459 + y: 14 + width: 34.25 + height: 21.78125 + xOffset: -3.875 + yOffset: 59.1875 + xAdvance: 30.4375 + scale: 1 + - id: 8249 + x: 955 + y: 113 + width: 21.21875 + height: 33.5625 + xOffset: 3.6875 + yOffset: 39.5 + xAdvance: 28.625 + scale: 1 + - id: 8250 + x: 956 + y: 34 + width: 21.1875 + height: 33.5625 + xOffset: 3.71875 + yOffset: 39.5 + xAdvance: 28.625 + scale: 1 + - id: 8252 + x: 749 + y: 234 + width: 27.46875 + height: 59.15625 + xOffset: 7.75 + yOffset: 59.1875 + xAdvance: 43 + scale: 1 + - id: 8254 + x: 969 + y: 166 + width: 34.0625 + height: 4.90625 + xOffset: -2.6875 + yOffset: 68.03125 + xAdvance: 28.625 + scale: 1 + - id: 8260 + x: 600 + y: 458 + width: 43.09375 + height: 59.15625 + xOffset: -17.46875 + yOffset: 59.1875 + xAdvance: 14.375 + scale: 1 + - id: 8286 + x: 738 + y: 64 + width: 8.1875 + height: 62.3125 + xOffset: 7.84375 + yOffset: 62.34375 + xAdvance: 23.90625 + scale: 1 + - id: 8298 + x: 300 + y: 101 + width: 20 + height: 70.71875 + xOffset: -10 + yOffset: 59.28125 + xAdvance: 0 + scale: 1 + - id: 8299 + x: 321 + y: 465 + width: 20 + height: 70.71875 + xOffset: -10 + yOffset: 59.28125 + xAdvance: 0 + scale: 1 + - id: 8300 + x: 281 + y: 386 + width: 20.15625 + height: 70.71875 + xOffset: -10.09375 + yOffset: 59.28125 + xAdvance: 0 + scale: 1 + - id: 8301 + x: 993 + y: 529 + width: 20.15625 + height: 71 + xOffset: -10.09375 + yOffset: 59.5625 + xAdvance: 0 + scale: 1 + - id: 8302 + x: 344 + y: 296 + width: 20.0625 + height: 70.84375 + xOffset: -10.0625 + yOffset: 59.40625 + xAdvance: 0 + scale: 1 + - id: 8303 + x: 360 + y: 465 + width: 20 + height: 70.71875 + xOffset: -10 + yOffset: 59.28125 + xAdvance: 0 + scale: 1 + - id: 8364 + x: 800 + y: 555 + width: 45.9375 + height: 60.90625 + xOffset: 0.65625 + yOffset: 60.0625 + xAdvance: 47.84375 + scale: 1 + - id: 8482 + x: 481 + y: 877 + width: 68.40625 + height: 32.53125 + xOffset: 7.875 + yOffset: 59.1875 + xAdvance: 86 + scale: 1 + - id: 9633 + x: 737 + y: 721 + width: 51.4375 + height: 51.4375 + xOffset: 0.25 + yOffset: 51.46875 + xAdvance: 51.9375 + scale: 1 + m_kerningInfo: + kerningPairs: + - m_FirstGlyph: 32 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -4.745117 + yAdvance: 0 + m_SecondGlyph: 65 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -4.745117 + - m_FirstGlyph: 32 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 89 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 32 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 84 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 87 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -3.1914062 + yAdvance: 0 + m_SecondGlyph: 97 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -3.1914062 + - m_FirstGlyph: 87 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -3.1914062 + yAdvance: 0 + m_SecondGlyph: 65 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -3.1914062 + - m_FirstGlyph: 87 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 101 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 87 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -0.7558594 + yAdvance: 0 + m_SecondGlyph: 121 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -0.7558594 + - m_FirstGlyph: 87 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 111 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 87 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 114 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 87 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -4.745117 + yAdvance: 0 + m_SecondGlyph: 44 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -4.745117 + - m_FirstGlyph: 87 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 59 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 87 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 117 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 87 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 58 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 87 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 45 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 87 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -4.745117 + yAdvance: 0 + m_SecondGlyph: 46 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -4.745117 + - m_FirstGlyph: 119 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -4.745117 + yAdvance: 0 + m_SecondGlyph: 44 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -4.745117 + - m_FirstGlyph: 119 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -4.745117 + yAdvance: 0 + m_SecondGlyph: 46 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -4.745117 + - m_FirstGlyph: 65 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -4.745117 + yAdvance: 0 + m_SecondGlyph: 32 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -4.745117 + - m_FirstGlyph: 65 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -3.1914062 + yAdvance: 0 + m_SecondGlyph: 87 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -3.1914062 + - m_FirstGlyph: 65 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 119 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 65 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 86 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 65 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 89 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 65 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 84 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 65 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 121 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 65 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 118 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 65 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 8217 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 86 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 97 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 86 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 65 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 86 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -4.745117 + yAdvance: 0 + m_SecondGlyph: 101 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -4.745117 + - m_FirstGlyph: 86 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -3.1914062 + yAdvance: 0 + m_SecondGlyph: 121 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -3.1914062 + - m_FirstGlyph: 86 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 105 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 86 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -4.745117 + yAdvance: 0 + m_SecondGlyph: 111 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -4.745117 + - m_FirstGlyph: 86 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -3.1914062 + yAdvance: 0 + m_SecondGlyph: 114 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -3.1914062 + - m_FirstGlyph: 86 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -7.8945312 + yAdvance: 0 + m_SecondGlyph: 44 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -7.8945312 + - m_FirstGlyph: 86 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -3.1914062 + yAdvance: 0 + m_SecondGlyph: 59 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -3.1914062 + - m_FirstGlyph: 86 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -3.1914062 + yAdvance: 0 + m_SecondGlyph: 117 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -3.1914062 + - m_FirstGlyph: 86 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -3.1914062 + yAdvance: 0 + m_SecondGlyph: 58 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -3.1914062 + - m_FirstGlyph: 86 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -4.745117 + yAdvance: 0 + m_SecondGlyph: 45 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -4.745117 + - m_FirstGlyph: 86 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -7.8945312 + yAdvance: 0 + m_SecondGlyph: 46 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -7.8945312 + - m_FirstGlyph: 89 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 32 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 89 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 97 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 89 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 65 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 89 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -7.8945312 + yAdvance: 0 + m_SecondGlyph: 101 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -7.8945312 + - m_FirstGlyph: 89 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 112 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 89 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -7.8945312 + yAdvance: 0 + m_SecondGlyph: 113 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -7.8945312 + - m_FirstGlyph: 89 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -4.745117 + yAdvance: 0 + m_SecondGlyph: 118 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -4.745117 + - m_FirstGlyph: 89 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -3.1914062 + yAdvance: 0 + m_SecondGlyph: 105 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -3.1914062 + - m_FirstGlyph: 89 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -7.8945312 + yAdvance: 0 + m_SecondGlyph: 111 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -7.8945312 + - m_FirstGlyph: 89 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -11.0859375 + yAdvance: 0 + m_SecondGlyph: 44 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -11.0859375 + - m_FirstGlyph: 89 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -5.584961 + yAdvance: 0 + m_SecondGlyph: 59 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -5.584961 + - m_FirstGlyph: 89 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -4.745117 + yAdvance: 0 + m_SecondGlyph: 117 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -4.745117 + - m_FirstGlyph: 89 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -4.745117 + yAdvance: 0 + m_SecondGlyph: 58 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -4.745117 + - m_FirstGlyph: 89 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -7.8945312 + yAdvance: 0 + m_SecondGlyph: 45 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -7.8945312 + - m_FirstGlyph: 89 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -11.0859375 + yAdvance: 0 + m_SecondGlyph: 46 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -11.0859375 + - m_FirstGlyph: 82 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 87 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 82 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 86 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 82 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 89 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 82 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 84 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 84 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 32 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 84 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -9.532227 + yAdvance: 0 + m_SecondGlyph: 97 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -9.532227 + - m_FirstGlyph: 84 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -9.532227 + yAdvance: 0 + m_SecondGlyph: 99 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -9.532227 + - m_FirstGlyph: 84 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 79 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 84 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -4.745117 + yAdvance: 0 + m_SecondGlyph: 119 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -4.745117 + - m_FirstGlyph: 84 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 65 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 84 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -9.532227 + yAdvance: 0 + m_SecondGlyph: 101 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -9.532227 + - m_FirstGlyph: 84 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -4.745117 + yAdvance: 0 + m_SecondGlyph: 121 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -4.745117 + - m_FirstGlyph: 84 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -3.1914062 + yAdvance: 0 + m_SecondGlyph: 105 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -3.1914062 + - m_FirstGlyph: 84 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -9.532227 + yAdvance: 0 + m_SecondGlyph: 111 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -9.532227 + - m_FirstGlyph: 84 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -3.1914062 + yAdvance: 0 + m_SecondGlyph: 114 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -3.1914062 + - m_FirstGlyph: 84 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -9.532227 + yAdvance: 0 + m_SecondGlyph: 115 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -9.532227 + - m_FirstGlyph: 84 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -9.532227 + yAdvance: 0 + m_SecondGlyph: 44 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -9.532227 + - m_FirstGlyph: 84 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -9.532227 + yAdvance: 0 + m_SecondGlyph: 59 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -9.532227 + - m_FirstGlyph: 84 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -3.1914062 + yAdvance: 0 + m_SecondGlyph: 117 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -3.1914062 + - m_FirstGlyph: 84 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -9.532227 + yAdvance: 0 + m_SecondGlyph: 58 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -9.532227 + - m_FirstGlyph: 84 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -4.745117 + yAdvance: 0 + m_SecondGlyph: 45 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -4.745117 + - m_FirstGlyph: 84 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -9.532227 + yAdvance: 0 + m_SecondGlyph: 46 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -9.532227 + - m_FirstGlyph: 80 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 32 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 80 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 65 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 80 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -11.0859375 + yAdvance: 0 + m_SecondGlyph: 44 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -11.0859375 + - m_FirstGlyph: 80 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -11.0859375 + yAdvance: 0 + m_SecondGlyph: 46 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -11.0859375 + - m_FirstGlyph: 49 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 49 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 121 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 44 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 121 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 46 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 70 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -4.745117 + yAdvance: 0 + m_SecondGlyph: 65 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -4.745117 + - m_FirstGlyph: 70 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -9.532227 + yAdvance: 0 + m_SecondGlyph: 44 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -9.532227 + - m_FirstGlyph: 70 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -9.532227 + yAdvance: 0 + m_SecondGlyph: 46 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -9.532227 + - m_FirstGlyph: 118 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 44 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 118 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 46 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 102 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 102 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 102 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 1.5537109 + yAdvance: 0 + m_SecondGlyph: 8217 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: 1.5537109 + - m_FirstGlyph: 76 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -3.1914062 + yAdvance: 0 + m_SecondGlyph: 32 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -3.1914062 + - m_FirstGlyph: 76 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 87 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 76 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 86 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 76 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 89 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 76 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -6.3828125 + yAdvance: 0 + m_SecondGlyph: 84 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -6.3828125 + - m_FirstGlyph: 76 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -3.1914062 + yAdvance: 0 + m_SecondGlyph: 121 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -3.1914062 + - m_FirstGlyph: 76 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -4.745117 + yAdvance: 0 + m_SecondGlyph: 8217 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -4.745117 + - m_FirstGlyph: 114 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -4.745117 + yAdvance: 0 + m_SecondGlyph: 44 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -4.745117 + - m_FirstGlyph: 114 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -4.745117 + yAdvance: 0 + m_SecondGlyph: 46 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -4.745117 + - m_FirstGlyph: 114 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 3.1914062 + yAdvance: 0 + m_SecondGlyph: 8217 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: 3.1914062 + - m_FirstGlyph: 8216 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 8216 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 8217 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -3.1914062 + yAdvance: 0 + m_SecondGlyph: 32 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -3.1914062 + - m_FirstGlyph: 8217 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 115 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + - m_FirstGlyph: 8217 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: -1.5537109 + yAdvance: 0 + m_SecondGlyph: 8217 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: -1.5537109 + m_kerningPair: + m_FirstGlyph: 0 + m_FirstGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + m_SecondGlyph: 0 + m_SecondGlyphAdjustments: + xPlacement: 0 + yPlacement: 0 + xAdvance: 0 + yAdvance: 0 + xOffset: 0 + fallbackFontAssets: [] + m_CreationSettings: + sourceFontFileName: + sourceFontFileGUID: e3265ab4bf004d28a9537516768c1c75 + pointSizeSamplingMode: 1 + pointSize: 86 + padding: 9 + packingMode: 4 + atlasWidth: 1024 + atlasHeight: 1024 + characterSetSelectionMode: 1 + characterSequence: 32 - 126, 160 - 255, 8192 - 8303, 8364, 8482, 9633 + referencedFontAssetGUID: + referencedTextAssetGUID: + fontStyle: 0 + fontStyleModifier: 2 + renderMode: 7 + includeFontFeatures: 0 + fontWeights: + - 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} + normalStyle: 0 + normalSpacingOffset: 0 + boldStyle: 0.75 + boldSpacing: 7 + italicStyle: 35 + tabSize: 10 diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF.asset.meta b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF.asset.meta new file mode 100644 index 0000000..66e69d1 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8f586378b4e144a9851e7b34d9b748ee +timeCreated: 1484171803 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/LineBreaking Following Characters.txt b/Assets/TextMesh Pro/Resources/LineBreaking Following Characters.txt new file mode 100644 index 0000000..a52cc38 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/LineBreaking Following Characters.txt @@ -0,0 +1 @@ +)]}〕〉》」』】〙〗〟’”⦆»ヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎゕゖㇰㇱㇲㇳㇴㇵㇶㇷㇸㇹㇺㇻㇼㇽㇾㇿ々〻‐゠–〜?!‼⁇⁈⁉・、%,.:;。!?]):;=}¢°"†‡℃〆%,. \ No newline at end of file diff --git a/Assets/TextMesh Pro/Resources/LineBreaking Following Characters.txt.meta b/Assets/TextMesh Pro/Resources/LineBreaking Following Characters.txt.meta new file mode 100644 index 0000000..73ed660 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/LineBreaking Following Characters.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fade42e8bc714b018fac513c043d323b +timeCreated: 1425440388 +licenseType: Store +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/LineBreaking Leading Characters.txt b/Assets/TextMesh Pro/Resources/LineBreaking Leading Characters.txt new file mode 100644 index 0000000..285696e --- /dev/null +++ b/Assets/TextMesh Pro/Resources/LineBreaking Leading Characters.txt @@ -0,0 +1 @@ +([{〔〈《「『【〘〖〝‘“⦅«$—…‥〳〴〵\[({£¥"々〇〉》」$⦆¥₩ # \ No newline at end of file diff --git a/Assets/TextMesh Pro/Resources/LineBreaking Leading Characters.txt.meta b/Assets/TextMesh Pro/Resources/LineBreaking Leading Characters.txt.meta new file mode 100644 index 0000000..cc684b3 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/LineBreaking Leading Characters.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d82c1b31c7e74239bff1220585707d2b +timeCreated: 1425440388 +licenseType: Store +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Shaders.meta b/Assets/TextMesh Pro/Resources/Shaders.meta new file mode 100644 index 0000000..622b295 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 99f836c9cb9345dba2e72c4a1f2d0695 +folderAsset: yes +timeCreated: 1436068007 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_Bitmap-Custom-Atlas.shader b/Assets/TextMesh Pro/Resources/Shaders/TMP_Bitmap-Custom-Atlas.shader new file mode 100644 index 0000000..c130a16 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_Bitmap-Custom-Atlas.shader @@ -0,0 +1,142 @@ +Shader "TextMeshPro/Bitmap Custom Atlas" { + +Properties { + _MainTex ("Font Atlas", 2D) = "white" {} + _FaceTex ("Font Texture", 2D) = "white" {} + _FaceColor ("Text Color", Color) = (1,1,1,1) + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _ClipRect("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _Padding ("Padding", float) = 0 + + _StencilComp("Stencil Comparison", Float) = 8 + _Stencil("Stencil ID", Float) = 0 + _StencilOp("Stencil Operation", Float) = 0 + _StencilWriteMask("Stencil Write Mask", Float) = 255 + _StencilReadMask("Stencil Read Mask", Float) = 255 + + _ColorMask("Color Mask", Float) = 15 +} + +SubShader{ + + Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } + + Stencil + { + Ref[_Stencil] + Comp[_StencilComp] + Pass[_StencilOp] + ReadMask[_StencilReadMask] + WriteMask[_StencilWriteMask] + } + + + Lighting Off + Cull [_CullMode] + ZTest [unity_GUIZTestMode] + ZWrite Off + Fog { Mode Off } + Blend SrcAlpha OneMinusSrcAlpha + ColorMask[_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + + #include "UnityCG.cginc" + + struct appdata_t { + float4 vertex : POSITION; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct v2f { + float4 vertex : SV_POSITION; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + float4 mask : TEXCOORD2; + }; + + uniform sampler2D _MainTex; + uniform sampler2D _FaceTex; + uniform float4 _FaceTex_ST; + uniform fixed4 _FaceColor; + + uniform float _VertexOffsetX; + uniform float _VertexOffsetY; + uniform float4 _ClipRect; + uniform float _MaskSoftnessX; + uniform float _MaskSoftnessY; + + float2 UnpackUV(float uv) + { + float2 output; + output.x = floor(uv / 4096); + output.y = uv - 4096 * output.x; + + return output * 0.001953125; + } + + v2f vert (appdata_t v) + { + float4 vert = v.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + + vert.xy += (vert.w * 0.5) / _ScreenParams.xy; + + float4 vPosition = UnityPixelSnap(UnityObjectToClipPos(vert)); + + fixed4 faceColor = v.color; + faceColor *= _FaceColor; + + v2f OUT; + OUT.vertex = vPosition; + OUT.color = faceColor; + OUT.texcoord0 = v.texcoord0; + OUT.texcoord1 = TRANSFORM_TEX(UnpackUV(v.texcoord1), _FaceTex); + float2 pixelSize = vPosition.w; + pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1])); + + // Clamp _ClipRect to 16bit. + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)); + + return OUT; + } + + fixed4 frag (v2f IN) : SV_Target + { + fixed4 color = tex2D(_MainTex, IN.texcoord0) * tex2D(_FaceTex, IN.texcoord1) * IN.color; + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw); + color *= m.x * m.y; + #endif + + #if UNITY_UI_ALPHACLIP + clip(color.a - 0.001); + #endif + + return color; + } + ENDCG + } +} + + CustomEditor "TMPro.EditorUtilities.TMP_BitmapShaderGUI" +} diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_Bitmap-Custom-Atlas.shader.meta b/Assets/TextMesh Pro/Resources/Shaders/TMP_Bitmap-Custom-Atlas.shader.meta new file mode 100644 index 0000000..ffea03c --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_Bitmap-Custom-Atlas.shader.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 48bb5f55d8670e349b6e614913f9d910 +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_Bitmap-Mobile.shader b/Assets/TextMesh Pro/Resources/Shaders/TMP_Bitmap-Mobile.shader new file mode 100644 index 0000000..1517a12 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_Bitmap-Mobile.shader @@ -0,0 +1,144 @@ +Shader "TextMeshPro/Mobile/Bitmap" { + +Properties { + _MainTex ("Font Atlas", 2D) = "white" {} + _Color ("Text Color", Color) = (1,1,1,1) + _DiffusePower ("Diffuse Power", Range(1.0,4.0)) = 1.0 + + _VertexOffsetX("Vertex OffsetX", float) = 0 + _VertexOffsetY("Vertex OffsetY", float) = 0 + _MaskSoftnessX("Mask SoftnessX", float) = 0 + _MaskSoftnessY("Mask SoftnessY", float) = 0 + + _ClipRect("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + + _StencilComp("Stencil Comparison", Float) = 8 + _Stencil("Stencil ID", Float) = 0 + _StencilOp("Stencil Operation", Float) = 0 + _StencilWriteMask("Stencil Write Mask", Float) = 255 + _StencilReadMask("Stencil Read Mask", Float) = 255 + + _ColorMask("Color Mask", Float) = 15 +} + +SubShader { + + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + + Stencil + { + Ref[_Stencil] + Comp[_StencilComp] + Pass[_StencilOp] + ReadMask[_StencilReadMask] + WriteMask[_StencilWriteMask] + } + + + Lighting Off + Cull Off + ZTest [unity_GUIZTestMode] + ZWrite Off + Fog { Mode Off } + Blend SrcAlpha OneMinusSrcAlpha + ColorMask[_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma fragmentoption ARB_precision_hint_fastest + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + + #include "UnityCG.cginc" + + struct appdata_t { + float4 vertex : POSITION; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct v2f { + float4 vertex : POSITION; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float4 mask : TEXCOORD2; + }; + + sampler2D _MainTex; + fixed4 _Color; + float _DiffusePower; + + uniform float _VertexOffsetX; + uniform float _VertexOffsetY; + uniform float4 _ClipRect; + uniform float _MaskSoftnessX; + uniform float _MaskSoftnessY; + + v2f vert (appdata_t v) + { + v2f OUT; + float4 vert = v.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + + vert.xy += (vert.w * 0.5) / _ScreenParams.xy; + + OUT.vertex = UnityPixelSnap(UnityObjectToClipPos(vert)); + OUT.color = v.color; + OUT.color *= _Color; + OUT.color.rgb *= _DiffusePower; + OUT.texcoord0 = v.texcoord0; + + float2 pixelSize = OUT.vertex.w; + //pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1])); + + // Clamp _ClipRect to 16bit. + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)); + + return OUT; + } + + fixed4 frag (v2f IN) : COLOR + { + fixed4 color = fixed4(IN.color.rgb, IN.color.a * tex2D(_MainTex, IN.texcoord0).a); + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw); + color *= m.x * m.y; + #endif + + #if UNITY_UI_ALPHACLIP + clip(color.a - 0.001); + #endif + + return color; + } + ENDCG + } +} + +SubShader { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + Lighting Off Cull Off ZTest Always ZWrite Off Fog { Mode Off } + Blend SrcAlpha OneMinusSrcAlpha + BindChannels { + Bind "Color", color + Bind "Vertex", vertex + Bind "TexCoord", texcoord0 + } + Pass { + SetTexture [_MainTex] { + constantColor [_Color] combine constant * primary, constant * texture + } + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_BitmapShaderGUI" +} diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_Bitmap-Mobile.shader.meta b/Assets/TextMesh Pro/Resources/Shaders/TMP_Bitmap-Mobile.shader.meta new file mode 100644 index 0000000..8d516c0 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_Bitmap-Mobile.shader.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1e3b057af24249748ff873be7fafee47 +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_Bitmap.shader b/Assets/TextMesh Pro/Resources/Shaders/TMP_Bitmap.shader new file mode 100644 index 0000000..f4e324a --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_Bitmap.shader @@ -0,0 +1,142 @@ +Shader "TextMeshPro/Bitmap" { + +Properties { + _MainTex ("Font Atlas", 2D) = "white" {} + _FaceTex ("Font Texture", 2D) = "white" {} + _FaceColor ("Text Color", Color) = (1,1,1,1) + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _ClipRect("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + + _StencilComp("Stencil Comparison", Float) = 8 + _Stencil("Stencil ID", Float) = 0 + _StencilOp("Stencil Operation", Float) = 0 + _StencilWriteMask("Stencil Write Mask", Float) = 255 + _StencilReadMask("Stencil Read Mask", Float) = 255 + + _ColorMask("Color Mask", Float) = 15 +} + +SubShader{ + + Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } + + Stencil + { + Ref[_Stencil] + Comp[_StencilComp] + Pass[_StencilOp] + ReadMask[_StencilReadMask] + WriteMask[_StencilWriteMask] + } + + + Lighting Off + Cull [_CullMode] + ZTest [unity_GUIZTestMode] + ZWrite Off + Fog { Mode Off } + Blend SrcAlpha OneMinusSrcAlpha + ColorMask[_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + + #include "UnityCG.cginc" + + struct appdata_t { + float4 vertex : POSITION; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct v2f { + float4 vertex : SV_POSITION; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + float4 mask : TEXCOORD2; + }; + + uniform sampler2D _MainTex; + uniform sampler2D _FaceTex; + uniform float4 _FaceTex_ST; + uniform fixed4 _FaceColor; + + uniform float _VertexOffsetX; + uniform float _VertexOffsetY; + uniform float4 _ClipRect; + uniform float _MaskSoftnessX; + uniform float _MaskSoftnessY; + + float2 UnpackUV(float uv) + { + float2 output; + output.x = floor(uv / 4096); + output.y = uv - 4096 * output.x; + + return output * 0.001953125; + } + + v2f vert (appdata_t v) + { + float4 vert = v.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + + vert.xy += (vert.w * 0.5) / _ScreenParams.xy; + + float4 vPosition = UnityPixelSnap(UnityObjectToClipPos(vert)); + + fixed4 faceColor = v.color; + faceColor *= _FaceColor; + + v2f OUT; + OUT.vertex = vPosition; + OUT.color = faceColor; + OUT.texcoord0 = v.texcoord0; + OUT.texcoord1 = TRANSFORM_TEX(UnpackUV(v.texcoord1), _FaceTex); + float2 pixelSize = vPosition.w; + pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1])); + + // Clamp _ClipRect to 16bit. + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)); + + return OUT; + } + + fixed4 frag (v2f IN) : SV_Target + { + fixed4 color = tex2D(_MainTex, IN.texcoord0); + color = fixed4 (tex2D(_FaceTex, IN.texcoord1).rgb * IN.color.rgb, IN.color.a * color.a); + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw); + color *= m.x * m.y; + #endif + + #if UNITY_UI_ALPHACLIP + clip(color.a - 0.001); + #endif + + return color; + } + ENDCG + } +} + + CustomEditor "TMPro.EditorUtilities.TMP_BitmapShaderGUI" +} diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_Bitmap.shader.meta b/Assets/TextMesh Pro/Resources/Shaders/TMP_Bitmap.shader.meta new file mode 100644 index 0000000..2d5438f --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_Bitmap.shader.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 128e987d567d4e2c824d754223b3f3b0 +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF Overlay.shader b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF Overlay.shader new file mode 100644 index 0000000..8c461cf --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF Overlay.shader @@ -0,0 +1,304 @@ +Shader "TextMeshPro/Distance Field Overlay" { + +Properties { + _FaceTex ("Face Texture", 2D) = "white" {} + _FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0 + _FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0 + _FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + _OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineTex ("Outline Texture", 2D) = "white" {} + _OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0 + _OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0 + _OutlineWidth ("Outline Thickness", Range(0, 1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _Bevel ("Bevel", Range(0,1)) = 0.5 + _BevelOffset ("Bevel Offset", Range(-0.5,0.5)) = 0 + _BevelWidth ("Bevel Width", Range(-.5,0.5)) = 0 + _BevelClamp ("Bevel Clamp", Range(0,1)) = 0 + _BevelRoundness ("Bevel Roundness", Range(0,1)) = 0 + + _LightAngle ("Light Angle", Range(0.0, 6.2831853)) = 3.1416 + _SpecularColor ("Specular", Color) = (1,1,1,1) + _SpecularPower ("Specular", Range(0,4)) = 2.0 + _Reflectivity ("Reflectivity", Range(5.0,15.0)) = 10 + _Diffuse ("Diffuse", Range(0,1)) = 0.5 + _Ambient ("Ambient", Range(1,0)) = 0.5 + + _BumpMap ("Normal map", 2D) = "bump" {} + _BumpOutline ("Bump Outline", Range(0,1)) = 0 + _BumpFace ("Bump Face", Range(0,1)) = 0 + + _ReflectFaceColor ("Reflection Color", Color) = (0,0,0,1) + _ReflectOutlineColor("Reflection Color", Color) = (0,0,0,1) + _Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ } + _EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0) + + + _UnderlayColor ("Border Color", Color) = (0,0,0, 0.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + _GlowColor ("Color", Color) = (0, 1, 0, 0.5) + _GlowOffset ("Offset", Range(-1,1)) = 0 + _GlowInner ("Inner", Range(0,1)) = 0.05 + _GlowOuter ("Outer", Range(0,1)) = 0.05 + _GlowPower ("Falloff", Range(1, 0)) = 0.75 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = 0.5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5.0 + _ScaleX ("Scale X", float) = 1.0 + _ScaleY ("Scale Y", float) = 1.0 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _MaskCoord ("Mask Coordinates", vector) = (0, 0, 32767, 32767) + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + + Tags + { + "Queue"="Overlay" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest Always + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma target 3.0 + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ BEVEL_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + #pragma shader_feature __ GLOW_ON + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + #include "TMPro.cginc" + + struct vertex_t { + float4 position : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + + struct pixel_t { + float4 position : SV_POSITION; + fixed4 color : COLOR; + float2 atlas : TEXCOORD0; // Atlas + float4 param : TEXCOORD1; // alphaClip, scale, bias, weight + float4 mask : TEXCOORD2; // Position in object space(xy), pixel Size(zw) + float3 viewDir : TEXCOORD3; + + #if (UNDERLAY_ON || UNDERLAY_INNER) + float4 texcoord2 : TEXCOORD4; // u,v, scale, bias + fixed4 underlayColor : COLOR1; + #endif + float4 textures : TEXCOORD5; + }; + + // Used by Unity internally to handle Texture Tiling and Offset. + float4 _FaceTex_ST; + float4 _OutlineTex_ST; + + pixel_t VertShader(vertex_t input) + { + float bold = step(input.texcoord1.y, 0); + + float4 vert = input.position; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + float4 vPosition = UnityObjectToClipPos(vert); + + float2 pixelSize = vPosition.w; + pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(input.texcoord1.y) * _GradientScale * 1.5; + if (UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + float bias =(.5 - weight) + (.5 / scale); + + float alphaClip = (1.0 - _OutlineWidth*_ScaleRatioA - _OutlineSoftness*_ScaleRatioA); + + #if GLOW_ON + alphaClip = min(alphaClip, 1.0 - _GlowOffset * _ScaleRatioB - _GlowOuter * _ScaleRatioB); + #endif + + alphaClip = alphaClip / 2.0 - ( .5 / scale) - weight; + + #if (UNDERLAY_ON || UNDERLAY_INNER) + float4 underlayColor = _UnderlayColor; + underlayColor.rgb *= underlayColor.a; + + float bScale = scale; + bScale /= 1 + ((_UnderlaySoftness*_ScaleRatioC) * bScale); + float bBias = (0.5 - weight) * bScale - 0.5 - ((_UnderlayDilate * _ScaleRatioC) * 0.5 * bScale); + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + float2 bOffset = float2(x, y); + #endif + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + + // Support for texture tiling and offset + float2 textureUV = UnpackUV(input.texcoord1.x); + float2 faceUV = TRANSFORM_TEX(textureUV, _FaceTex); + float2 outlineUV = TRANSFORM_TEX(textureUV, _OutlineTex); + + pixel_t output = { + vPosition, + input.color, + input.texcoord0, + float4(alphaClip, scale, bias, weight), + half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)), + mul((float3x3)_EnvMatrix, _WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, vert).xyz), + #if (UNDERLAY_ON || UNDERLAY_INNER) + float4(input.texcoord0 + bOffset, bScale, bBias), + underlayColor, + #endif + float4(faceUV, outlineUV), + }; + + return output; + } + + + fixed4 PixShader(pixel_t input) : SV_Target + { + float c = tex2D(_MainTex, input.atlas).a; + + #ifndef UNDERLAY_ON + clip(c - input.param.x); + #endif + + float scale = input.param.y; + float bias = input.param.z; + float weight = input.param.w; + float sd = (bias - c) * scale; + + float outline = (_OutlineWidth * _ScaleRatioA) * scale; + float softness = (_OutlineSoftness * _ScaleRatioA) * scale; + + half4 faceColor = _FaceColor; + half4 outlineColor = _OutlineColor; + + faceColor.rgb *= input.color.rgb; + + faceColor *= tex2D(_FaceTex, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y); + outlineColor *= tex2D(_OutlineTex, input.textures.zw + float2(_OutlineUVSpeedX, _OutlineUVSpeedY) * _Time.y); + + faceColor = GetColor(sd, faceColor, outlineColor, outline, softness); + + #if BEVEL_ON + float3 dxy = float3(0.5 / _TextureWidth, 0.5 / _TextureHeight, 0); + float3 n = GetSurfaceNormal(input.atlas, weight, dxy); + + float3 bump = UnpackNormal(tex2D(_BumpMap, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y)).xyz; + bump *= lerp(_BumpFace, _BumpOutline, saturate(sd + outline * 0.5)); + n = normalize(n- bump); + + float3 light = normalize(float3(sin(_LightAngle), cos(_LightAngle), -1.0)); + + float3 col = GetSpecular(n, light); + faceColor.rgb += col*faceColor.a; + faceColor.rgb *= 1-(dot(n, light)*_Diffuse); + faceColor.rgb *= lerp(_Ambient, 1, n.z*n.z); + + fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDir, -n)); + faceColor.rgb += reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a; + #endif + + #if UNDERLAY_ON + float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z; + faceColor += input.underlayColor * saturate(d - input.texcoord2.w) * (1 - faceColor.a); + #endif + + #if UNDERLAY_INNER + float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z; + faceColor += input.underlayColor * (1 - saturate(d - input.texcoord2.w)) * saturate(1 - sd) * (1 - faceColor.a); + #endif + + #if GLOW_ON + float4 glowColor = GetGlowColor(sd, scale); + faceColor.rgb += glowColor.rgb * glowColor.a; + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); + faceColor *= m.x * m.y; + #endif + + #if UNITY_UI_ALPHACLIP + clip(faceColor.a - 0.001); + #endif + + return faceColor * input.color.a; + } + + ENDCG + } +} + +Fallback "TextMeshPro/Mobile/Distance Field" +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF Overlay.shader.meta b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF Overlay.shader.meta new file mode 100644 index 0000000..6c8679f --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF Overlay.shader.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: dd89cf5b9246416f84610a006f916af7 +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Mobile Masking.shader b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Mobile Masking.shader new file mode 100644 index 0000000..8dd81a3 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Mobile Masking.shader @@ -0,0 +1,245 @@ +// Simplified SDF shader: +// - No Shading Option (bevel / bump / env map) +// - No Glow Option +// - Softness is applied on both side of the outline + +Shader "TextMeshPro/Mobile/Distance Field - Masking" { + +Properties { + _FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + _OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _UnderlayColor ("Border Color", Color) = (0,0,0,.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = .5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5 + _ScaleX ("Scale X", float) = 1 + _ScaleY ("Scale Y", float) = 1 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + _MaskTex ("Mask Texture", 2D) = "white" {} + _MaskInverse ("Inverse", float) = 0 + _MaskEdgeColor ("Edge Color", Color) = (1,1,1,1) + _MaskEdgeSoftness ("Edge Softness", Range(0, 1)) = 0.01 + _MaskWipeControl ("Wipe Position", Range(0, 1)) = 0.5 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest [unity_GUIZTestMode] + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ OUTLINE_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + + struct vertex_t { + float4 vertex : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct pixel_t { + float4 vertex : SV_POSITION; + fixed4 faceColor : COLOR; + fixed4 outlineColor : COLOR1; + float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV + half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w) + half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw) + #if (UNDERLAY_ON | UNDERLAY_INNER) + float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved + half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y) + #endif + }; + + float _MaskWipeControl; + float _MaskEdgeSoftness; + fixed4 _MaskEdgeColor; + bool _MaskInverse; + + pixel_t VertShader(vertex_t input) + { + float bold = step(input.texcoord1.y, 0); + + float4 vert = input.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + float4 vPosition = UnityObjectToClipPos(vert); + + float2 pixelSize = vPosition.w; + pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(input.texcoord1.y) * _GradientScale * 1.5; + if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + float layerScale = scale; + + scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale); + float bias = (0.5 - weight) * scale - 0.5; + float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale; + + float opacity = input.color.a; + #if (UNDERLAY_ON | UNDERLAY_INNER) + opacity = 1.0; + #endif + + fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor; + faceColor.rgb *= faceColor.a; + + fixed4 outlineColor = _OutlineColor; + outlineColor.a *= opacity; + outlineColor.rgb *= outlineColor.a; + outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, (outline * 2)))); + + #if (UNDERLAY_ON | UNDERLAY_INNER) + + layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale); + float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale); + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + float2 layerOffset = float2(x, y); + #endif + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + + // Structure for pixel shader + pixel_t output = { + vPosition, + faceColor, + outlineColor, + float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y), + half4(scale, bias - outline, bias + outline, bias), + half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)), + #if (UNDERLAY_ON | UNDERLAY_INNER) + float4(input.texcoord0 + layerOffset, input.color.a, 0), + half2(layerScale, layerBias), + #endif + }; + + return output; + } + + + // PIXEL SHADER + fixed4 PixShader(pixel_t input) : SV_Target + { + half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x; + half4 c = input.faceColor * saturate(d - input.param.w); + + #ifdef OUTLINE_ON + c = lerp(input.outlineColor, input.faceColor, saturate(d - input.param.z)); + c *= saturate(d - input.param.y); + #endif + + #if UNDERLAY_ON + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a); + #endif + + #if UNDERLAY_INNER + half sd = saturate(d - input.param.z); + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a); + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); + c *= m.x * m.y; + #endif + + float a = abs(_MaskInverse - tex2D(_MaskTex, input.texcoord0.zw).a); + float t = a + (1 - _MaskWipeControl) * _MaskEdgeSoftness - _MaskWipeControl; + a = saturate(t / _MaskEdgeSoftness); + c.rgb = lerp(_MaskEdgeColor.rgb*c.a, c.rgb, a); + c *= a; + + #if (UNDERLAY_ON | UNDERLAY_INNER) + c *= input.texcoord1.z; + #endif + + #if UNITY_UI_ALPHACLIP + clip(c.a - 0.001); + #endif + + return c; + } + ENDCG + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Mobile Masking.shader.meta b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Mobile Masking.shader.meta new file mode 100644 index 0000000..dbfc71a --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Mobile Masking.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: bc1ede39bf3643ee8e493720e4259791 +timeCreated: 1463704911 +licenseType: Pro +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Mobile Overlay.shader b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Mobile Overlay.shader new file mode 100644 index 0000000..adcdc05 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Mobile Overlay.shader @@ -0,0 +1,229 @@ +// Simplified SDF shader: +// - No Shading Option (bevel / bump / env map) +// - No Glow Option +// - Softness is applied on both side of the outline + +Shader "TextMeshPro/Mobile/Distance Field Overlay" { + +Properties { + _FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + _OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _UnderlayColor ("Border Color", Color) = (0,0,0,.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = .5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5 + _ScaleX ("Scale X", float) = 1 + _ScaleY ("Scale Y", float) = 1 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + Tags + { + "Queue"="Overlay" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest Always + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ OUTLINE_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + + struct vertex_t { + float4 vertex : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct pixel_t { + float4 vertex : SV_POSITION; + fixed4 faceColor : COLOR; + fixed4 outlineColor : COLOR1; + float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV + half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w) + half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw) + #if (UNDERLAY_ON | UNDERLAY_INNER) + float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved + half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y) + #endif + }; + + + pixel_t VertShader(vertex_t input) + { + float bold = step(input.texcoord1.y, 0); + + float4 vert = input.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + float4 vPosition = UnityObjectToClipPos(vert); + + float2 pixelSize = vPosition.w; + pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(input.texcoord1.y) * _GradientScale * 1.5; + if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + float layerScale = scale; + + scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale); + float bias = (0.5 - weight) * scale - 0.5; + float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale; + + float opacity = input.color.a; + #if (UNDERLAY_ON | UNDERLAY_INNER) + opacity = 1.0; + #endif + + fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor; + faceColor.rgb *= faceColor.a; + + fixed4 outlineColor = _OutlineColor; + outlineColor.a *= opacity; + outlineColor.rgb *= outlineColor.a; + outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, (outline * 2)))); + + #if (UNDERLAY_ON | UNDERLAY_INNER) + + layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale); + float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale); + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + float2 layerOffset = float2(x, y); + #endif + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + + // Structure for pixel shader + pixel_t output = { + vPosition, + faceColor, + outlineColor, + float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y), + half4(scale, bias - outline, bias + outline, bias), + half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)), + #if (UNDERLAY_ON | UNDERLAY_INNER) + float4(input.texcoord0 + layerOffset, input.color.a, 0), + half2(layerScale, layerBias), + #endif + }; + + return output; + } + + + // PIXEL SHADER + fixed4 PixShader(pixel_t input) : SV_Target + { + half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x; + half4 c = input.faceColor * saturate(d - input.param.w); + + #ifdef OUTLINE_ON + c = lerp(input.outlineColor, input.faceColor, saturate(d - input.param.z)); + c *= saturate(d - input.param.y); + #endif + + #if UNDERLAY_ON + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a); + #endif + + #if UNDERLAY_INNER + half sd = saturate(d - input.param.z); + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a); + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); + c *= m.x * m.y; + #endif + + #if (UNDERLAY_ON | UNDERLAY_INNER) + c *= input.texcoord1.z; + #endif + + #if UNITY_UI_ALPHACLIP + clip(c.a - 0.001); + #endif + + return c; + } + ENDCG + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Mobile Overlay.shader.meta b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Mobile Overlay.shader.meta new file mode 100644 index 0000000..29cbfcc --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Mobile Overlay.shader.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a02a7d8c237544f1962732b55a9aebf1 +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Mobile.shader b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Mobile.shader new file mode 100644 index 0000000..5c655d7 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Mobile.shader @@ -0,0 +1,229 @@ +// Simplified SDF shader: +// - No Shading Option (bevel / bump / env map) +// - No Glow Option +// - Softness is applied on both side of the outline + +Shader "TextMeshPro/Mobile/Distance Field" { + +Properties { + _FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + _OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _UnderlayColor ("Border Color", Color) = (0,0,0,.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = .5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5 + _ScaleX ("Scale X", float) = 1 + _ScaleY ("Scale Y", float) = 1 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest [unity_GUIZTestMode] + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ OUTLINE_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + + struct vertex_t { + float4 vertex : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct pixel_t { + float4 vertex : SV_POSITION; + fixed4 faceColor : COLOR; + fixed4 outlineColor : COLOR1; + float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV + half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w) + half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw) + #if (UNDERLAY_ON | UNDERLAY_INNER) + float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved + half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y) + #endif + }; + + + pixel_t VertShader(vertex_t input) + { + float bold = step(input.texcoord1.y, 0); + + float4 vert = input.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + float4 vPosition = UnityObjectToClipPos(vert); + + float2 pixelSize = vPosition.w; + pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(input.texcoord1.y) * _GradientScale * 1.5; + if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + float layerScale = scale; + + scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale); + float bias = (0.5 - weight) * scale - 0.5; + float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale; + + float opacity = input.color.a; + #if (UNDERLAY_ON | UNDERLAY_INNER) + opacity = 1.0; + #endif + + fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor; + faceColor.rgb *= faceColor.a; + + fixed4 outlineColor = _OutlineColor; + outlineColor.a *= opacity; + outlineColor.rgb *= outlineColor.a; + outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, (outline * 2)))); + + #if (UNDERLAY_ON | UNDERLAY_INNER) + + layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale); + float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale); + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + float2 layerOffset = float2(x, y); + #endif + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + + // Structure for pixel shader + pixel_t output = { + vPosition, + faceColor, + outlineColor, + float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y), + half4(scale, bias - outline, bias + outline, bias), + half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)), + #if (UNDERLAY_ON | UNDERLAY_INNER) + float4(input.texcoord0 + layerOffset, input.color.a, 0), + half2(layerScale, layerBias), + #endif + }; + + return output; + } + + + // PIXEL SHADER + fixed4 PixShader(pixel_t input) : SV_Target + { + half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x; + half4 c = input.faceColor * saturate(d - input.param.w); + + #ifdef OUTLINE_ON + c = lerp(input.outlineColor, input.faceColor, saturate(d - input.param.z)); + c *= saturate(d - input.param.y); + #endif + + #if UNDERLAY_ON + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a); + #endif + + #if UNDERLAY_INNER + half sd = saturate(d - input.param.z); + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a); + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); + c *= m.x * m.y; + #endif + + #if (UNDERLAY_ON | UNDERLAY_INNER) + c *= input.texcoord1.z; + #endif + + #if UNITY_UI_ALPHACLIP + clip(c.a - 0.001); + #endif + + return c; + } + ENDCG + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Mobile.shader.meta b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Mobile.shader.meta new file mode 100644 index 0000000..3db6338 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Mobile.shader.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: fe393ace9b354375a9cb14cdbbc28be4 +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Surface-Mobile.shader b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Surface-Mobile.shader new file mode 100644 index 0000000..ae78bc6 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Surface-Mobile.shader @@ -0,0 +1,136 @@ +// Simplified version of the SDF Surface shader : +// - No support for Bevel, Bump or envmap +// - Diffuse only lighting +// - Fully supports only 1 directional light. Other lights can affect it, but it will be per-vertex/SH. + +Shader "TextMeshPro/Mobile/Distance Field (Surface)" { + +Properties { + _FaceTex ("Fill Texture", 2D) = "white" {} + _FaceColor ("Fill Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + _OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineTex ("Outline Texture", 2D) = "white" {} + _OutlineWidth ("Outline Thickness", Range(0, 1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _GlowColor ("Color", Color) = (0, 1, 0, 0.5) + _GlowOffset ("Offset", Range(-1,1)) = 0 + _GlowInner ("Inner", Range(0,1)) = 0.05 + _GlowOuter ("Outer", Range(0,1)) = 0.05 + _GlowPower ("Falloff", Range(1, 0)) = 0.75 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = 0.5 + + // Should not be directly exposed to the user + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5.0 + _ScaleX ("Scale X", float) = 1.0 + _ScaleY ("Scale Y", float) = 1.0 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + //_MaskCoord ("Mask Coords", vector) = (0,0,0,0) + //_MaskSoftness ("Mask Softness", float) = 0 +} + +SubShader { + + Tags { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + LOD 300 + Cull [_CullMode] + + CGPROGRAM + #pragma surface PixShader Lambert alpha:blend vertex:VertShader noforwardadd nolightmap nodirlightmap + #pragma target 3.0 + #pragma shader_feature __ GLOW_ON + + #include "TMPro_Properties.cginc" + #include "TMPro.cginc" + + half _FaceShininess; + half _OutlineShininess; + + struct Input + { + fixed4 color : COLOR; + float2 uv_MainTex; + float2 uv2_FaceTex; + float2 uv2_OutlineTex; + float2 param; // Weight, Scale + float3 viewDirEnv; + }; + + #include "TMPro_Surface.cginc" + + ENDCG + + // Pass to render object as a shadow caster + Pass + { + Name "Caster" + Tags { "LightMode" = "ShadowCaster" } + Offset 1, 1 + + Fog {Mode Off} + ZWrite On ZTest LEqual Cull Off + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_shadowcaster + #include "UnityCG.cginc" + + struct v2f { + V2F_SHADOW_CASTER; + float2 uv : TEXCOORD1; + float2 uv2 : TEXCOORD3; + float alphaClip : TEXCOORD2; + }; + + uniform float4 _MainTex_ST; + uniform float4 _OutlineTex_ST; + float _OutlineWidth; + float _FaceDilate; + float _ScaleRatioA; + + v2f vert( appdata_base v ) + { + v2f o; + TRANSFER_SHADOW_CASTER(o) + o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); + o.uv2 = TRANSFORM_TEX(v.texcoord, _OutlineTex); + o.alphaClip = o.alphaClip = (1.0 - _OutlineWidth * _ScaleRatioA - _FaceDilate * _ScaleRatioA) / 2; + return o; + } + + uniform sampler2D _MainTex; + + float4 frag(v2f i) : COLOR + { + fixed4 texcol = tex2D(_MainTex, i.uv).a; + clip(texcol.a - i.alphaClip); + SHADOW_CASTER_FRAGMENT(i) + } + ENDCG + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Surface-Mobile.shader.meta b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Surface-Mobile.shader.meta new file mode 100644 index 0000000..d559598 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Surface-Mobile.shader.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 85187c2149c549c5b33f0cdb02836b17 +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Surface.shader b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Surface.shader new file mode 100644 index 0000000..08cee8d --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Surface.shader @@ -0,0 +1,155 @@ +Shader "TextMeshPro/Distance Field (Surface)" { + +Properties { + _FaceTex ("Fill Texture", 2D) = "white" {} + _FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0 + _FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0 + _FaceColor ("Fill Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + _OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineTex ("Outline Texture", 2D) = "white" {} + _OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0 + _OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0 + _OutlineWidth ("Outline Thickness", Range(0, 1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _Bevel ("Bevel", Range(0,1)) = 0.5 + _BevelOffset ("Bevel Offset", Range(-0.5,0.5)) = 0 + _BevelWidth ("Bevel Width", Range(-.5,0.5)) = 0 + _BevelClamp ("Bevel Clamp", Range(0,1)) = 0 + _BevelRoundness ("Bevel Roundness", Range(0,1)) = 0 + + _BumpMap ("Normalmap", 2D) = "bump" {} + _BumpOutline ("Bump Outline", Range(0,1)) = 0.5 + _BumpFace ("Bump Face", Range(0,1)) = 0.5 + + _ReflectFaceColor ("Face Color", Color) = (0,0,0,1) + _ReflectOutlineColor ("Outline Color", Color) = (0,0,0,1) + _Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ } + _EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0) + _SpecColor ("Specular Color", Color) = (0,0,0,1) + + _FaceShininess ("Face Shininess", Range(0,1)) = 0 + _OutlineShininess ("Outline Shininess", Range(0,1)) = 0 + + _GlowColor ("Color", Color) = (0, 1, 0, 0.5) + _GlowOffset ("Offset", Range(-1,1)) = 0 + _GlowInner ("Inner", Range(0,1)) = 0.05 + _GlowOuter ("Outer", Range(0,1)) = 0.05 + _GlowPower ("Falloff", Range(1, 0)) = 0.75 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = 0.5 + + // Should not be directly exposed to the user + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5.0 + _ScaleX ("Scale X", float) = 1.0 + _ScaleY ("Scale Y", float) = 1.0 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + //_MaskCoord ("Mask Coords", vector) = (0,0,0,0) + //_MaskSoftness ("Mask Softness", float) = 0 +} + +SubShader { + + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + + LOD 300 + Cull [_CullMode] + + CGPROGRAM + #pragma surface PixShader BlinnPhong alpha:blend vertex:VertShader nolightmap nodirlightmap + #pragma target 3.0 + #pragma shader_feature __ GLOW_ON + #pragma glsl + + #include "TMPro_Properties.cginc" + #include "TMPro.cginc" + + half _FaceShininess; + half _OutlineShininess; + + struct Input + { + fixed4 color : COLOR; + float2 uv_MainTex; + float2 uv2_FaceTex; + float2 uv2_OutlineTex; + float2 param; // Weight, Scale + float3 viewDirEnv; + }; + + + #define BEVEL_ON 1 + #include "TMPro_Surface.cginc" + + ENDCG + + // Pass to render object as a shadow caster + Pass + { + Name "Caster" + Tags { "LightMode" = "ShadowCaster" } + Offset 1, 1 + + Fog {Mode Off} + ZWrite On + ZTest LEqual + Cull Off + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_shadowcaster + #include "UnityCG.cginc" + + struct v2f { + V2F_SHADOW_CASTER; + float2 uv : TEXCOORD1; + float2 uv2 : TEXCOORD3; + float alphaClip : TEXCOORD2; + }; + + uniform float4 _MainTex_ST; + uniform float4 _OutlineTex_ST; + float _OutlineWidth; + float _FaceDilate; + float _ScaleRatioA; + + v2f vert( appdata_base v ) + { + v2f o; + TRANSFER_SHADOW_CASTER(o) + o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); + o.uv2 = TRANSFORM_TEX(v.texcoord, _OutlineTex); + o.alphaClip = (1.0 - _OutlineWidth * _ScaleRatioA - _FaceDilate * _ScaleRatioA) / 2; + return o; + } + + uniform sampler2D _MainTex; + + float4 frag(v2f i) : COLOR + { + fixed4 texcol = tex2D(_MainTex, i.uv).a; + clip(texcol.a - i.alphaClip); + SHADOW_CASTER_FRAGMENT(i) + } + ENDCG + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} + diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Surface.shader.meta b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Surface.shader.meta new file mode 100644 index 0000000..bc7933f --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF-Surface.shader.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f7ada0af4f174f0694ca6a487b8f543d +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF.shader b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF.shader new file mode 100644 index 0000000..7a2a63b --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF.shader @@ -0,0 +1,305 @@ +Shader "TextMeshPro/Distance Field" { + +Properties { + _FaceTex ("Face Texture", 2D) = "white" {} + _FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0 + _FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0 + _FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + _OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineTex ("Outline Texture", 2D) = "white" {} + _OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0 + _OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0 + _OutlineWidth ("Outline Thickness", Range(0, 1)) = 0 + _OutlineSoftness ("Outline Softness", Range(-1,1)) = 0 + + _Bevel ("Bevel", Range(0,1)) = 0.5 + _BevelOffset ("Bevel Offset", Range(-0.5,0.5)) = 0 + _BevelWidth ("Bevel Width", Range(-.5,0.5)) = 0 + _BevelClamp ("Bevel Clamp", Range(0,1)) = 0 + _BevelRoundness ("Bevel Roundness", Range(0,1)) = 0 + + _LightAngle ("Light Angle", Range(0.0, 6.2831853)) = 3.1416 + _SpecularColor ("Specular", Color) = (1,1,1,1) + _SpecularPower ("Specular", Range(0,4)) = 2.0 + _Reflectivity ("Reflectivity", Range(5.0,15.0)) = 10 + _Diffuse ("Diffuse", Range(0,1)) = 0.5 + _Ambient ("Ambient", Range(1,0)) = 0.5 + + _BumpMap ("Normal map", 2D) = "bump" {} + _BumpOutline ("Bump Outline", Range(0,1)) = 0 + _BumpFace ("Bump Face", Range(0,1)) = 0 + + _ReflectFaceColor ("Reflection Color", Color) = (0,0,0,1) + _ReflectOutlineColor("Reflection Color", Color) = (0,0,0,1) + _Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ } + _EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0) + + + _UnderlayColor ("Border Color", Color) = (0,0,0, 0.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + _GlowColor ("Color", Color) = (0, 1, 0, 0.5) + _GlowOffset ("Offset", Range(-1,1)) = 0 + _GlowInner ("Inner", Range(0,1)) = 0.05 + _GlowOuter ("Outer", Range(0,1)) = 0.05 + _GlowPower ("Falloff", Range(1, 0)) = 0.75 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = 0.5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5.0 + _ScaleX ("Scale X", float) = 1.0 + _ScaleY ("Scale Y", float) = 1.0 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _MaskCoord ("Mask Coordinates", vector) = (0, 0, 32767, 32767) + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest [unity_GUIZTestMode] + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma target 3.0 + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ BEVEL_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + #pragma shader_feature __ GLOW_ON + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + #include "TMPro.cginc" + + struct vertex_t { + float4 position : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + + struct pixel_t { + float4 position : SV_POSITION; + fixed4 color : COLOR; + float2 atlas : TEXCOORD0; // Atlas + float4 param : TEXCOORD1; // alphaClip, scale, bias, weight + float4 mask : TEXCOORD2; // Position in object space(xy), pixel Size(zw) + float3 viewDir : TEXCOORD3; + + #if (UNDERLAY_ON || UNDERLAY_INNER) + float4 texcoord2 : TEXCOORD4; // u,v, scale, bias + fixed4 underlayColor : COLOR1; + #endif + float4 textures : TEXCOORD5; + }; + + // Used by Unity internally to handle Texture Tiling and Offset. + float4 _FaceTex_ST; + float4 _OutlineTex_ST; + + pixel_t VertShader(vertex_t input) + { + float bold = step(input.texcoord1.y, 0); + + float4 vert = input.position; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + + float4 vPosition = UnityObjectToClipPos(vert); + + float2 pixelSize = vPosition.w; + pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(input.texcoord1.y) * _GradientScale * 1.5; + if (UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + float bias =(.5 - weight) + (.5 / scale); + + float alphaClip = (1.0 - _OutlineWidth*_ScaleRatioA - _OutlineSoftness*_ScaleRatioA); + + #if GLOW_ON + alphaClip = min(alphaClip, 1.0 - _GlowOffset * _ScaleRatioB - _GlowOuter * _ScaleRatioB); + #endif + + alphaClip = alphaClip / 2.0 - ( .5 / scale) - weight; + + #if (UNDERLAY_ON || UNDERLAY_INNER) + float4 underlayColor = _UnderlayColor; + underlayColor.rgb *= underlayColor.a; + + float bScale = scale; + bScale /= 1 + ((_UnderlaySoftness*_ScaleRatioC) * bScale); + float bBias = (0.5 - weight) * bScale - 0.5 - ((_UnderlayDilate * _ScaleRatioC) * 0.5 * bScale); + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + float2 bOffset = float2(x, y); + #endif + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + + // Support for texture tiling and offset + float2 textureUV = UnpackUV(input.texcoord1.x); + float2 faceUV = TRANSFORM_TEX(textureUV, _FaceTex); + float2 outlineUV = TRANSFORM_TEX(textureUV, _OutlineTex); + + pixel_t output = { + vPosition, + input.color, + input.texcoord0, + float4(alphaClip, scale, bias, weight), + half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)), + mul((float3x3)_EnvMatrix, _WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, vert).xyz), + #if (UNDERLAY_ON || UNDERLAY_INNER) + float4(input.texcoord0 + bOffset, bScale, bBias), + underlayColor, + #endif + float4(faceUV, outlineUV), + }; + + return output; + } + + + fixed4 PixShader(pixel_t input) : SV_Target + { + float c = tex2D(_MainTex, input.atlas).a; + + #ifndef UNDERLAY_ON + clip(c - input.param.x); + #endif + + float scale = input.param.y; + float bias = input.param.z; + float weight = input.param.w; + float sd = (bias - c) * scale; + + float outline = (_OutlineWidth * _ScaleRatioA) * scale; + float softness = (_OutlineSoftness * _ScaleRatioA) * scale; + + half4 faceColor = _FaceColor; + half4 outlineColor = _OutlineColor; + + faceColor.rgb *= input.color.rgb; + + faceColor *= tex2D(_FaceTex, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y); + outlineColor *= tex2D(_OutlineTex, input.textures.zw + float2(_OutlineUVSpeedX, _OutlineUVSpeedY) * _Time.y); + + faceColor = GetColor(sd, faceColor, outlineColor, outline, softness); + + #if BEVEL_ON + float3 dxy = float3(0.5 / _TextureWidth, 0.5 / _TextureHeight, 0); + float3 n = GetSurfaceNormal(input.atlas, weight, dxy); + + float3 bump = UnpackNormal(tex2D(_BumpMap, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y)).xyz; + bump *= lerp(_BumpFace, _BumpOutline, saturate(sd + outline * 0.5)); + n = normalize(n- bump); + + float3 light = normalize(float3(sin(_LightAngle), cos(_LightAngle), -1.0)); + + float3 col = GetSpecular(n, light); + faceColor.rgb += col*faceColor.a; + faceColor.rgb *= 1-(dot(n, light)*_Diffuse); + faceColor.rgb *= lerp(_Ambient, 1, n.z*n.z); + + fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDir, -n)); + faceColor.rgb += reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a; + #endif + + #if UNDERLAY_ON + float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z; + faceColor += input.underlayColor * saturate(d - input.texcoord2.w) * (1 - faceColor.a); + #endif + + #if UNDERLAY_INNER + float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z; + faceColor += input.underlayColor * (1 - saturate(d - input.texcoord2.w)) * saturate(1 - sd) * (1 - faceColor.a); + #endif + + #if GLOW_ON + float4 glowColor = GetGlowColor(sd, scale); + faceColor.rgb += glowColor.rgb * glowColor.a; + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); + faceColor *= m.x * m.y; + #endif + + #if UNITY_UI_ALPHACLIP + clip(faceColor.a - 0.001); + #endif + + return faceColor * input.color.a; + } + + ENDCG + } +} + +Fallback "TextMeshPro/Mobile/Distance Field" +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF.shader.meta b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF.shader.meta new file mode 100644 index 0000000..e343136 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_SDF.shader.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 68e6db2ebdc24f95958faec2be5558d6 +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_Sprite.shader b/Assets/TextMesh Pro/Resources/Shaders/TMP_Sprite.shader new file mode 100644 index 0000000..f90467d --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_Sprite.shader @@ -0,0 +1,113 @@ +Shader "TextMeshPro/Sprite" +{ + Properties + { + _MainTex ("Sprite Texture", 2D) = "white" {} + _Color ("Tint", Color) = (1,1,1,1) + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _ColorMask ("Color Mask", Float) = 15 + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + + [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0 + } + + SubShader + { + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + "PreviewType"="Plane" + "CanUseSpriteAtlas"="True" + } + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull Off + Lighting Off + ZWrite Off + ZTest [unity_GUIZTestMode] + Blend SrcAlpha OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass + { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + struct appdata_t + { + float4 vertex : POSITION; + float4 color : COLOR; + float2 texcoord : TEXCOORD0; + }; + + struct v2f + { + float4 vertex : SV_POSITION; + fixed4 color : COLOR; + half2 texcoord : TEXCOORD0; + float4 worldPosition : TEXCOORD1; + }; + + fixed4 _Color; + fixed4 _TextureSampleAdd; + float4 _ClipRect; + + v2f vert(appdata_t IN) + { + v2f OUT; + OUT.worldPosition = IN.vertex; + OUT.vertex = UnityObjectToClipPos(OUT.worldPosition); + + OUT.texcoord = IN.texcoord; + + #ifdef UNITY_HALF_TEXEL_OFFSET + OUT.vertex.xy += (_ScreenParams.zw-1.0)*float2(-1,1); + #endif + + OUT.color = IN.color * _Color; + return OUT; + } + + sampler2D _MainTex; + + fixed4 frag(v2f IN) : SV_Target + { + half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color; + + #if UNITY_UI_CLIP_RECT + color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect); + #endif + + #ifdef UNITY_UI_ALPHACLIP + clip (color.a - 0.001); + #endif + + return color; + } + ENDCG + } + } +} diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMP_Sprite.shader.meta b/Assets/TextMesh Pro/Resources/Shaders/TMP_Sprite.shader.meta new file mode 100644 index 0000000..f3e9cc9 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMP_Sprite.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: cf81c85f95fe47e1a27f6ae460cf182c +timeCreated: 1450517184 +licenseType: Pro +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMPro.cginc b/Assets/TextMesh Pro/Resources/Shaders/TMPro.cginc new file mode 100644 index 0000000..5898130 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMPro.cginc @@ -0,0 +1,84 @@ +float2 UnpackUV(float uv) +{ + float2 output; + output.x = floor(uv / 4096); + output.y = uv - 4096 * output.x; + + return output * 0.001953125; +} + +fixed4 GetColor(half d, fixed4 faceColor, fixed4 outlineColor, half outline, half softness) +{ + half faceAlpha = 1-saturate((d - outline * 0.5 + softness * 0.5) / (1.0 + softness)); + half outlineAlpha = saturate((d + outline * 0.5)) * sqrt(min(1.0, outline)); + + faceColor.rgb *= faceColor.a; + outlineColor.rgb *= outlineColor.a; + + faceColor = lerp(faceColor, outlineColor, outlineAlpha); + + faceColor *= faceAlpha; + + return faceColor; +} + +float3 GetSurfaceNormal(float4 h, float bias) +{ + bool raisedBevel = step(1, fmod(_ShaderFlags, 2)); + + h += bias+_BevelOffset; + + float bevelWidth = max(.01, _OutlineWidth+_BevelWidth); + + // Track outline + h -= .5; + h /= bevelWidth; + h = saturate(h+.5); + + if(raisedBevel) h = 1 - abs(h*2.0 - 1.0); + h = lerp(h, sin(h*3.141592/2.0), _BevelRoundness); + h = min(h, 1.0-_BevelClamp); + h *= _Bevel * bevelWidth * _GradientScale * -2.0; + + float3 va = normalize(float3(1.0, 0.0, h.y - h.x)); + float3 vb = normalize(float3(0.0, -1.0, h.w - h.z)); + + return cross(va, vb); +} + +float3 GetSurfaceNormal(float2 uv, float bias, float3 delta) +{ + // Read "height field" + float4 h = {tex2D(_MainTex, uv - delta.xz).a, + tex2D(_MainTex, uv + delta.xz).a, + tex2D(_MainTex, uv - delta.zy).a, + tex2D(_MainTex, uv + delta.zy).a}; + + return GetSurfaceNormal(h, bias); +} + +float3 GetSpecular(float3 n, float3 l) +{ + float spec = pow(max(0.0, dot(n, l)), _Reflectivity); + return _SpecularColor.rgb * spec * _SpecularPower; +} + +float4 GetGlowColor(float d, float scale) +{ + float glow = d - (_GlowOffset*_ScaleRatioB) * 0.5 * scale; + float t = lerp(_GlowInner, (_GlowOuter * _ScaleRatioB), step(0.0, glow)) * 0.5 * scale; + glow = saturate(abs(glow/(1.0 + t))); + glow = 1.0-pow(glow, _GlowPower); + glow *= sqrt(min(1.0, t)); // Fade off glow thinner than 1 screen pixel + return float4(_GlowColor.rgb, saturate(_GlowColor.a * glow * 2)); +} + +float4 BlendARGB(float4 overlying, float4 underlying) +{ + overlying.rgb *= overlying.a; + underlying.rgb *= underlying.a; + float3 blended = overlying.rgb + ((1-overlying.a)*underlying.rgb); + float alpha = underlying.a + (1-underlying.a)*overlying.a; + return float4(blended, alpha); +} + diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMPro.cginc.meta b/Assets/TextMesh Pro/Resources/Shaders/TMPro.cginc.meta new file mode 100644 index 0000000..f633f58 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMPro.cginc.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 407bc68d299748449bbf7f48ee690f8d +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMPro_Properties.cginc b/Assets/TextMesh Pro/Resources/Shaders/TMPro_Properties.cginc new file mode 100644 index 0000000..df1b6d9 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMPro_Properties.cginc @@ -0,0 +1,84 @@ +// UI Editable properties +uniform sampler2D _FaceTex; // Alpha : Signed Distance +uniform float _FaceUVSpeedX; +uniform float _FaceUVSpeedY; +uniform fixed4 _FaceColor; // RGBA : Color + Opacity +uniform float _FaceDilate; // v[ 0, 1] +uniform float _OutlineSoftness; // v[ 0, 1] + +uniform sampler2D _OutlineTex; // RGBA : Color + Opacity +uniform float _OutlineUVSpeedX; +uniform float _OutlineUVSpeedY; +uniform fixed4 _OutlineColor; // RGBA : Color + Opacity +uniform float _OutlineWidth; // v[ 0, 1] + +uniform float _Bevel; // v[ 0, 1] +uniform float _BevelOffset; // v[-1, 1] +uniform float _BevelWidth; // v[-1, 1] +uniform float _BevelClamp; // v[ 0, 1] +uniform float _BevelRoundness; // v[ 0, 1] + +uniform sampler2D _BumpMap; // Normal map +uniform float _BumpOutline; // v[ 0, 1] +uniform float _BumpFace; // v[ 0, 1] + +uniform samplerCUBE _Cube; // Cube / sphere map +uniform fixed4 _ReflectFaceColor; // RGB intensity +uniform fixed4 _ReflectOutlineColor; +//uniform float _EnvTiltX; // v[-1, 1] +//uniform float _EnvTiltY; // v[-1, 1] +uniform float3 _EnvMatrixRotation; +uniform float4x4 _EnvMatrix; + +uniform fixed4 _SpecularColor; // RGB intensity +uniform float _LightAngle; // v[ 0,Tau] +uniform float _SpecularPower; // v[ 0, 1] +uniform float _Reflectivity; // v[ 5, 15] +uniform float _Diffuse; // v[ 0, 1] +uniform float _Ambient; // v[ 0, 1] + +uniform fixed4 _UnderlayColor; // RGBA : Color + Opacity +uniform float _UnderlayOffsetX; // v[-1, 1] +uniform float _UnderlayOffsetY; // v[-1, 1] +uniform float _UnderlayDilate; // v[-1, 1] +uniform float _UnderlaySoftness; // v[ 0, 1] + +uniform fixed4 _GlowColor; // RGBA : Color + Intesity +uniform float _GlowOffset; // v[-1, 1] +uniform float _GlowOuter; // v[ 0, 1] +uniform float _GlowInner; // v[ 0, 1] +uniform float _GlowPower; // v[ 1, 1/(1+4*4)] + +// API Editable properties +uniform float _ShaderFlags; +uniform float _WeightNormal; +uniform float _WeightBold; + +uniform float _ScaleRatioA; +uniform float _ScaleRatioB; +uniform float _ScaleRatioC; + +uniform float _VertexOffsetX; +uniform float _VertexOffsetY; + +//uniform float _UseClipRect; +uniform float _MaskID; +uniform sampler2D _MaskTex; +uniform float4 _MaskCoord; +uniform float4 _ClipRect; // bottom left(x,y) : top right(z,w) +//uniform float _MaskWipeControl; +//uniform float _MaskEdgeSoftness; +//uniform fixed4 _MaskEdgeColor; +//uniform bool _MaskInverse; + +uniform float _MaskSoftnessX; +uniform float _MaskSoftnessY; + +// Font Atlas properties +uniform sampler2D _MainTex; +uniform float _TextureWidth; +uniform float _TextureHeight; +uniform float _GradientScale; +uniform float _ScaleX; +uniform float _ScaleY; +uniform float _PerspectiveFilter; diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMPro_Properties.cginc.meta b/Assets/TextMesh Pro/Resources/Shaders/TMPro_Properties.cginc.meta new file mode 100644 index 0000000..24f0f8f --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMPro_Properties.cginc.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3997e2241185407d80309a82f9148466 +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMPro_Surface.cginc b/Assets/TextMesh Pro/Resources/Shaders/TMPro_Surface.cginc new file mode 100644 index 0000000..3659e87 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMPro_Surface.cginc @@ -0,0 +1,115 @@ +void VertShader(inout appdata_full v, out Input data) +{ + v.vertex.x += _VertexOffsetX; + v.vertex.y += _VertexOffsetY; + + UNITY_INITIALIZE_OUTPUT(Input, data); + + float bold = step(v.texcoord1.y, 0); + + // Generate normal for backface + float3 view = ObjSpaceViewDir(v.vertex); + v.normal *= sign(dot(v.normal, view)); + +#if USE_DERIVATIVE + data.param.y = 1; +#else + float4 vert = v.vertex; + float4 vPosition = UnityObjectToClipPos(vert); + float2 pixelSize = vPosition.w; + + pixelSize /= float2(_ScaleX, _ScaleY) * mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy); + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(v.texcoord1.y) * _GradientScale * 1.5; + scale = lerp(scale * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(v.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + data.param.y = scale; +#endif + + //float opacity = v.color.a; + + data.param.x = (lerp(_WeightNormal, _WeightBold, bold) / 4.0 + _FaceDilate) * _ScaleRatioA * 0.5; // + + v.texcoord1.xy = UnpackUV(v.texcoord1.x); + data.viewDirEnv = mul((float3x3)_EnvMatrix, WorldSpaceViewDir(v.vertex)); +} + +void PixShader(Input input, inout SurfaceOutput o) +{ + +#if USE_DERIVATIVE | BEVEL_ON + float3 delta = float3(1.0 / _TextureWidth, 1.0 / _TextureHeight, 0.0); + + float4 smp4x = { tex2D(_MainTex, input.uv_MainTex - delta.xz).a, + tex2D(_MainTex, input.uv_MainTex + delta.xz).a, + tex2D(_MainTex, input.uv_MainTex - delta.zy).a, + tex2D(_MainTex, input.uv_MainTex + delta.zy).a }; +#endif + +#if USE_DERIVATIVE + // Screen space scaling reciprocal with anisotropic correction + float2 edgeNormal = Normalize(float2(smp4x.x - smp4x.y, smp4x.z - smp4x.w)); + float2 res = float2(_TextureWidth * input.param.y, _TextureHeight); + float2 tdx = ddx(input.uv_MainTex)*res; + float2 tdy = ddy(input.uv_MainTex)*res; + float lx = length(tdx); + float ly = length(tdy); + float s = sqrt(min(lx, ly) / max(lx, ly)); + s = lerp(1, s, abs(dot(normalize(tdx + tdy), edgeNormal))); + float scale = rsqrt(abs(tdx.x * tdy.y - tdx.y * tdy.x)) * (_GradientScale * 2) * s; +#else + float scale = input.param.y; +#endif + + // Signed distance + float c = tex2D(_MainTex, input.uv_MainTex).a; + float sd = (.5 - c - input.param.x) * scale + .5; + float outline = _OutlineWidth*_ScaleRatioA * scale; + float softness = _OutlineSoftness*_ScaleRatioA * scale; + + // Color & Alpha + float4 faceColor = _FaceColor; + float4 outlineColor = _OutlineColor; + faceColor *= input.color; + outlineColor.a *= input.color.a; + faceColor *= tex2D(_FaceTex, float2(input.uv2_FaceTex.x + _FaceUVSpeedX * _Time.y, input.uv2_FaceTex.y + _FaceUVSpeedY * _Time.y)); + outlineColor *= tex2D(_OutlineTex, float2(input.uv2_OutlineTex.x + _OutlineUVSpeedX * _Time.y, input.uv2_OutlineTex.y + _OutlineUVSpeedY * _Time.y)); + faceColor = GetColor(sd, faceColor, outlineColor, outline, softness); + faceColor.rgb /= max(faceColor.a, 0.0001); + + +#if BEVEL_ON + // Face Normal + float3 n = GetSurfaceNormal(smp4x, input.param.x); + + // Bumpmap + float3 bump = UnpackNormal(tex2D(_BumpMap, input.uv2_FaceTex.xy)).xyz; + bump *= lerp(_BumpFace, _BumpOutline, saturate(sd + outline * 0.5)); + bump = lerp(float3(0, 0, 1), bump, faceColor.a); + n = normalize(n - bump); + + // Cubemap reflection + fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDirEnv, mul((float3x3)unity_ObjectToWorld, n))); + float3 emission = reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a; +#else + float3 n = float3(0, 0, -1); + float3 emission = float3(0, 0, 0); +#endif + + + +#if GLOW_ON + float4 glowColor = GetGlowColor(sd, scale); + glowColor.a *= input.color.a; + emission += glowColor.rgb*glowColor.a; + faceColor = BlendARGB(glowColor, faceColor); + faceColor.rgb /= max(faceColor.a, 0.0001); +#endif + + // Set Standard output structure + o.Albedo = faceColor.rgb; + o.Normal = -n; + o.Emission = emission; + o.Specular = lerp(_FaceShininess, _OutlineShininess, saturate(sd + outline * 0.5)); + o.Gloss = 1; + o.Alpha = faceColor.a; +} diff --git a/Assets/TextMesh Pro/Resources/Shaders/TMPro_Surface.cginc.meta b/Assets/TextMesh Pro/Resources/Shaders/TMPro_Surface.cginc.meta new file mode 100644 index 0000000..8e75022 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Shaders/TMPro_Surface.cginc.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d930090c0cd643c7b55f19a38538c162 +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Sprite Assets.meta b/Assets/TextMesh Pro/Resources/Sprite Assets.meta new file mode 100644 index 0000000..5171f1b --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Sprite Assets.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 512a49d95c0c4332bdd98131869c23c9 +folderAsset: yes +timeCreated: 1441876896 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Sprite Assets/EmojiOne.asset b/Assets/TextMesh Pro/Resources/Sprite Assets/EmojiOne.asset new file mode 100644 index 0000000..5b12b95 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Sprite Assets/EmojiOne.asset @@ -0,0 +1,296 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2103686 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: TextMeshPro/Sprite + m_Shader: {fileID: 4800000, guid: cf81c85f95fe47e1a27f6ae460cf182c, type: 3} + m_ShaderKeywords: UNITY_UI_CLIP_RECT + m_LightmapFlags: 5 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _MainTex: + m_Texture: {fileID: 2800000, guid: dffef66376be4fa480fb02b19edbe903, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _ColorMask: 15 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _UseUIAlphaClip: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _Color: {r: 1, g: 1, b: 1, a: 1} +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 84a92b25f83d49b9bc132d206b370281, type: 3} + m_Name: EmojiOne + m_EditorClassIdentifier: + hashCode: -1836805472 + material: {fileID: 2103686} + materialHashCode: 0 + spriteSheet: {fileID: 2800000, guid: dffef66376be4fa480fb02b19edbe903, type: 3} + spriteInfoList: + - id: 0 + x: 0 + y: 384 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: Smiling face with smiling eyes + hashCode: -1318250903 + unicode: 128522 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 1 + x: 128 + y: 384 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f60b + hashCode: 57188339 + unicode: 128523 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 2 + x: 256 + y: 384 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f60d + hashCode: 57188341 + unicode: 128525 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 3 + x: 384 + y: 384 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f60e + hashCode: 57188340 + unicode: 128526 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 4 + x: 0 + y: 256 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: Grinning face + hashCode: -95541379 + unicode: 128512 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 5 + x: 128 + y: 256 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f601 + hashCode: 57188256 + unicode: 128513 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 6 + x: 256 + y: 256 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: Face with tears of joy + hashCode: 239522663 + unicode: 128514 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 7 + x: 384 + y: 256 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f603 + hashCode: 57188258 + unicode: 128515 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 8 + x: 0 + y: 128 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f604 + hashCode: 57188261 + unicode: 128516 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 9 + x: 128 + y: 128 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f605 + hashCode: 57188260 + unicode: 128517 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 10 + x: 256 + y: 128 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f606 + hashCode: 57188263 + unicode: 128518 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 11 + x: 384 + y: 128 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f609 + hashCode: 57188264 + unicode: 128521 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 12 + x: 0 + y: 0 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f618 + hashCode: 57188168 + unicode: 128536 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 13 + x: 128 + y: 0 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f923 + hashCode: 57200239 + unicode: 129315 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 14 + x: 256 + y: 0 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 263a + hashCode: 1748406 + unicode: 9786 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 15 + x: 384 + y: 0 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 2639 + hashCode: 1748462 + unicode: 9785 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + fallbackSpriteAssets: [] +--- !u!21 &1369835458 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: TextMeshPro/Sprite + m_Shader: {fileID: 4800000, guid: cf81c85f95fe47e1a27f6ae460cf182c, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 5 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: [] + m_Floats: [] + m_Colors: [] diff --git a/Assets/TextMesh Pro/Resources/Sprite Assets/EmojiOne.asset.meta b/Assets/TextMesh Pro/Resources/Sprite Assets/EmojiOne.asset.meta new file mode 100644 index 0000000..c7ac83f --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Sprite Assets/EmojiOne.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c41005c129ba4d66911b75229fd70b45 +timeCreated: 1480316912 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Style Sheets.meta b/Assets/TextMesh Pro/Resources/Style Sheets.meta new file mode 100644 index 0000000..4958550 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Style Sheets.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 4aecb92fff08436c8303b10eab8da368 +folderAsset: yes +timeCreated: 1441876950 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Style Sheets/Default Style Sheet.asset b/Assets/TextMesh Pro/Resources/Style Sheets/Default Style Sheet.asset new file mode 100644 index 0000000..ceb609b --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Style Sheets/Default Style Sheet.asset @@ -0,0 +1,68 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ab2114bdc8544297b417dfefe9f1e410, type: 3} + m_Name: Default Style Sheet + m_EditorClassIdentifier: + m_StyleList: + - m_Name: H1 + m_HashCode: 2425 + m_OpeningDefinition: <#40ff80>* + m_ClosingDefinition: '*' + m_OpeningTagArray: 3c00000073000000690000007a000000650000003d00000032000000650000006d0000003e0000003c000000620000003e0000003c000000230000003400000030000000660000006600000038000000300000003e0000002a000000 + m_ClosingTagArray: 2a0000003c0000002f00000073000000690000007a000000650000003e0000003c0000002f000000620000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e000000 + - m_Name: Quote + m_HashCode: 92254330 + m_OpeningDefinition: + m_ClosingDefinition: + m_OpeningTagArray: 3c000000690000003e0000003c00000073000000690000007a000000650000003d0000003700000035000000250000003e0000003c0000006d000000610000007200000067000000690000006e0000003d0000003100000030000000250000003e000000 + m_ClosingTagArray: 3c0000002f000000690000003e0000003c0000002f00000073000000690000007a000000650000003e0000003c0000002f00000077000000690000006400000074000000680000003e0000003c0000002f0000006d000000610000007200000067000000690000006e0000003e000000 + - m_Name: Link + m_HashCode: 2687968 + m_OpeningDefinition: <#40a0ff> + m_ClosingDefinition: + m_OpeningTagArray: 3c000000750000003e0000003c000000230000003400000030000000610000003000000066000000660000003e0000003c0000006c000000690000006e0000006b0000003d0000002200000049000000440000005f0000003000000031000000220000003e000000 + m_ClosingTagArray: 3c0000002f000000750000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e0000003c0000002f0000006c000000690000006e0000006b0000003e000000 + - m_Name: Title + m_HashCode: 98732960 + m_OpeningDefinition: + m_ClosingDefinition: + m_OpeningTagArray: 3c00000073000000690000007a000000650000003d000000310000003200000035000000250000003e0000003c000000620000003e0000003c000000610000006c00000069000000670000006e0000003d00000063000000650000006e0000007400000065000000720000003e000000 + m_ClosingTagArray: 3c0000002f00000073000000690000007a000000650000003e0000003c0000002f000000620000003e0000003c0000002f000000610000006c00000069000000670000006e0000003e000000 + - m_Name: H2 + m_HashCode: 2426 + m_OpeningDefinition: <#4080FF> + m_ClosingDefinition: + m_OpeningTagArray: 3c00000073000000690000007a000000650000003d000000310000002e00000035000000650000006d0000003e0000003c000000620000003e0000003c000000230000003400000030000000380000003000000046000000460000003e000000 + m_ClosingTagArray: 3c0000002f00000073000000690000007a000000650000003e0000003c0000002f000000620000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e000000 + - m_Name: H3 + m_HashCode: 2427 + m_OpeningDefinition: <#FF8040> + m_ClosingDefinition: + m_OpeningTagArray: 3c00000073000000690000007a000000650000003d000000310000002e0000003100000037000000650000006d0000003e0000003c000000620000003e0000003c000000230000004600000046000000380000003000000034000000300000003e000000 + m_ClosingTagArray: 3c0000002f00000073000000690000007a000000650000003e0000003c0000002f000000620000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e000000 + - m_Name: C1 + m_HashCode: 2194 + m_OpeningDefinition: + m_ClosingDefinition: + m_OpeningTagArray: 3c000000630000006f0000006c0000006f000000720000003d000000230000006600000066000000660000006600000034000000300000003e000000 + m_ClosingTagArray: 3c0000002f000000630000006f0000006c0000006f000000720000003e000000 + - m_Name: C2 + m_HashCode: 2193 + m_OpeningDefinition: + m_ClosingDefinition: + m_OpeningTagArray: 3c000000630000006f0000006c0000006f000000720000003d000000230000006600000066000000340000003000000046000000460000003e0000003c00000073000000690000007a000000650000003d000000310000003200000035000000250000003e000000 + m_ClosingTagArray: 3c0000002f000000630000006f0000006c0000006f000000720000003e0000003c0000002f00000073000000690000007a000000650000003e000000 + - m_Name: C3 + m_HashCode: 2192 + m_OpeningDefinition: + m_ClosingDefinition: + m_OpeningTagArray: 3c000000630000006f0000006c0000006f000000720000003d000000230000003800000030000000410000003000000046000000460000003e0000003c000000620000003e000000 + m_ClosingTagArray: 3c0000002f000000630000006f0000006c0000006f000000720000003e0000003c0000002f000000620000003e000000 diff --git a/Assets/TextMesh Pro/Resources/Style Sheets/Default Style Sheet.asset.meta b/Assets/TextMesh Pro/Resources/Style Sheets/Default Style Sheet.asset.meta new file mode 100644 index 0000000..95fd96e --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Style Sheets/Default Style Sheet.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f952c082cb03451daed3ee968ac6c63e +timeCreated: 1432805430 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/TMP Settings.asset b/Assets/TextMesh Pro/Resources/TMP Settings.asset new file mode 100644 index 0000000..f34d7c9 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/TMP Settings.asset @@ -0,0 +1,103 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2705215ac5b84b70bacc50632be6e391, type: 3} + m_Name: TMP Settings + m_EditorClassIdentifier: + m_enableWordWrapping: 1 + m_enableKerning: 1 + m_enableExtraPadding: 0 + m_enableTintAllSprites: 0 + m_enableParseEscapeCharacters: 1 + m_missingGlyphCharacter: 0 + m_warningsDisabled: 0 + m_defaultFontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_defaultFontAssetPath: Fonts & Materials/ + m_defaultFontSize: 36 + m_defaultAutoSizeMinRatio: 0.5 + m_defaultAutoSizeMaxRatio: 2 + m_defaultTextMeshProTextContainerSize: {x: 20, y: 5} + m_defaultTextMeshProUITextContainerSize: {x: 200, y: 50} + m_autoSizeTextContainer: 0 + m_fallbackFontAssets: [] + m_matchMaterialPreset: 1 + m_defaultSpriteAsset: {fileID: 11400000, guid: c41005c129ba4d66911b75229fd70b45, + type: 2} + m_defaultSpriteAssetPath: Sprite Assets/ + m_defaultColorGradientPresetsPath: Color Gradient Presets/ + m_enableEmojiSupport: 1 + m_defaultStyleSheet: {fileID: 11400000, guid: f952c082cb03451daed3ee968ac6c63e, + type: 2} + m_leadingCharacters: {fileID: 4900000, guid: d82c1b31c7e74239bff1220585707d2b, type: 3} + m_followingCharacters: {fileID: 4900000, guid: fade42e8bc714b018fac513c043d323b, + type: 3} + m_FontCreatorRecentSettings: + - sourceFontFileName: + sourceFontFileGUID: edcaa01543603ae4cb6b2edf25967e21 + pointSizeSamplingMode: 1 + pointSize: 109 + padding: 12 + packingMode: 0 + atlasWidth: 128 + atlasHeight: 128 + characterSetSelectionMode: 5 + characterSequence: 64 + fontStyle: 0 + fontStyleModifier: 2 + renderMode: 281 + includeFontFeatures: 0 + referenceFontAssetGUID: 903613a9fe4b65946aa20dfcce07abec + - sourceFontFileName: + sourceFontFileGUID: edcaa01543603ae4cb6b2edf25967e21 + pointSizeSamplingMode: 0 + pointSize: 108 + padding: 12 + packingMode: 0 + atlasWidth: 128 + atlasHeight: 128 + characterSetSelectionMode: 5 + characterSequence: 64 + fontStyle: 0 + fontStyleModifier: 2 + renderMode: 2090 + includeFontFeatures: 0 + referenceFontAssetGUID: 70cf10c1d306ada42aa6cd7268db990d + - sourceFontFileName: + sourceFontFileGUID: edcaa01543603ae4cb6b2edf25967e21 + pointSizeSamplingMode: 1 + pointSize: 109 + padding: 12 + packingMode: 0 + atlasWidth: 128 + atlasHeight: 128 + characterSetSelectionMode: 5 + characterSequence: 64 + fontStyle: 0 + fontStyleModifier: 2 + renderMode: 329 + includeFontFeatures: 0 + referenceFontAssetGUID: 396d465a5821ead47b589b228da7e980 + - sourceFontFileName: + sourceFontFileGUID: edcaa01543603ae4cb6b2edf25967e21 + pointSizeSamplingMode: 1 + pointSize: 338 + padding: 36 + packingMode: 0 + atlasWidth: 4096 + atlasHeight: 4096 + characterSetSelectionMode: 1 + characterSequence: 32 - 126, 160 - 255, 8192 - 8303, 8364, 8482, 9633 + fontStyle: 0 + fontStyleModifier: 2 + renderMode: 329 + includeFontFeatures: 0 + referenceFontAssetGUID: 3a4171c252e1112499af739474d9f48e + m_CreationSettingsSelectionIndex: 0 + m_CreationSettingsIndex: 0 diff --git a/Assets/TextMesh Pro/Resources/TMP Settings.asset.meta b/Assets/TextMesh Pro/Resources/TMP Settings.asset.meta new file mode 100644 index 0000000..32db384 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/TMP Settings.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3f5b5dff67a942289a9defa416b206f3 +timeCreated: 1436653997 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Sprites.meta b/Assets/TextMesh Pro/Sprites.meta new file mode 100644 index 0000000..8b699e5 --- /dev/null +++ b/Assets/TextMesh Pro/Sprites.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d0603b6d5186471b96c778c3949c7ce2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Sprites/EmojiOne Attribution.txt b/Assets/TextMesh Pro/Sprites/EmojiOne Attribution.txt new file mode 100644 index 0000000..384180a --- /dev/null +++ b/Assets/TextMesh Pro/Sprites/EmojiOne Attribution.txt @@ -0,0 +1,3 @@ +This sample of beautiful emojis are provided by EmojiOne https://www.emojione.com/ + +Please visit their website to view the complete set of their emojis and review their licensing terms. \ No newline at end of file diff --git a/Assets/TextMesh Pro/Sprites/EmojiOne Attribution.txt.meta b/Assets/TextMesh Pro/Sprites/EmojiOne Attribution.txt.meta new file mode 100644 index 0000000..0d30e65 --- /dev/null +++ b/Assets/TextMesh Pro/Sprites/EmojiOne Attribution.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 381dcb09d5029d14897e55f98031fca5 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Sprites/EmojiOne.json b/Assets/TextMesh Pro/Sprites/EmojiOne.json new file mode 100644 index 0000000..6c4e50b --- /dev/null +++ b/Assets/TextMesh Pro/Sprites/EmojiOne.json @@ -0,0 +1,156 @@ +{"frames": [ + +{ + "filename": "1f60a.png", + "frame": {"x":0,"y":0,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f60b.png", + "frame": {"x":128,"y":0,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f60d.png", + "frame": {"x":256,"y":0,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f60e.png", + "frame": {"x":384,"y":0,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f600.png", + "frame": {"x":0,"y":128,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f601.png", + "frame": {"x":128,"y":128,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f602.png", + "frame": {"x":256,"y":128,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f603.png", + "frame": {"x":384,"y":128,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f604.png", + "frame": {"x":0,"y":256,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f605.png", + "frame": {"x":128,"y":256,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f606.png", + "frame": {"x":256,"y":256,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f609.png", + "frame": {"x":384,"y":256,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f618.png", + "frame": {"x":0,"y":384,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f923.png", + "frame": {"x":128,"y":384,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "263a.png", + "frame": {"x":256,"y":384,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "2639.png", + "frame": {"x":384,"y":384,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}], +"meta": { + "app": "http://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "EmojiOne.png", + "format": "RGBA8888", + "size": {"w":512,"h":512}, + "scale": "1", + "smartupdate": "$TexturePacker:SmartUpdate:196a26a2e149d875b91ffc8fa3581e76:fc928c7e275404b7e0649307410475cb:424723c3774975ddb2053fd5c4b85f6e$" +} +} diff --git a/Assets/TextMesh Pro/Sprites/EmojiOne.json.meta b/Assets/TextMesh Pro/Sprites/EmojiOne.json.meta new file mode 100644 index 0000000..762cf15 --- /dev/null +++ b/Assets/TextMesh Pro/Sprites/EmojiOne.json.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8f05276190cf498a8153f6cbe761d4e6 +timeCreated: 1480316860 +licenseType: Pro +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Sprites/EmojiOne.png b/Assets/TextMesh Pro/Sprites/EmojiOne.png new file mode 100644 index 0000000..4adb015 Binary files /dev/null and b/Assets/TextMesh Pro/Sprites/EmojiOne.png differ diff --git a/Assets/TextMesh Pro/Sprites/EmojiOne.png.meta b/Assets/TextMesh Pro/Sprites/EmojiOne.png.meta new file mode 100644 index 0000000..c9fa1a7 --- /dev/null +++ b/Assets/TextMesh Pro/Sprites/EmojiOne.png.meta @@ -0,0 +1,431 @@ +fileFormatVersion: 2 +guid: dffef66376be4fa480fb02b19edbe903 +TextureImporter: + fileIDToRecycleName: + 21300000: EmojiOne_0 + 21300002: EmojiOne_1 + 21300004: EmojiOne_2 + 21300006: EmojiOne_3 + 21300008: EmojiOne_4 + 21300010: EmojiOne_6 + 21300012: EmojiOne_7 + 21300014: EmojiOne_8 + 21300016: EmojiOne_9 + 21300018: EmojiOne_10 + 21300020: EmojiOne_11 + 21300022: EmojiOne_12 + 21300024: EmojiOne_13 + 21300026: EmojiOne_5 + 21300028: EmojiOne_14 + externalObjects: {} + serializedVersion: 5 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 2 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: iPhone + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: + - serializedVersion: 2 + name: EmojiOne_0 + rect: + serializedVersion: 2 + x: 0 + y: 384 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 4bcc36da2108f2c4ba3de5c921d25c3c + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_1 + rect: + serializedVersion: 2 + x: 128 + y: 384 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: e9eea8093eaeaee4d901c4553f572c22 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_2 + rect: + serializedVersion: 2 + x: 256 + y: 384 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 49451da35411dcc42a3692e39b0fde70 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_3 + rect: + serializedVersion: 2 + x: 384 + y: 384 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: f65709664b924904790c850a50ca82bc + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_4 + rect: + serializedVersion: 2 + x: 0 + y: 256 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 5b92c568a5ec9ad4b9ed90e271f1c9a8 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_6 + rect: + serializedVersion: 2 + x: 256 + y: 256 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: b10f2b48b7281594bb8a24a6511a35af + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_7 + rect: + serializedVersion: 2 + x: 384 + y: 256 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 10a600f9329dc2246a897e89f4d283cd + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_8 + rect: + serializedVersion: 2 + x: 0 + y: 128 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 66cffa363b90ab14787d8a5b90cf4502 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_9 + rect: + serializedVersion: 2 + x: 128 + y: 128 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 55cf3d409c9b89349b1e1bdc1cc224ad + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_10 + rect: + serializedVersion: 2 + x: 256 + y: 128 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 2a9e58eaf96feef42bcefa1cf257193f + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_11 + rect: + serializedVersion: 2 + x: 384 + y: 128 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 2489120affc155840ae6a7be2e93ce19 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_12 + rect: + serializedVersion: 2 + x: 0 + y: 0 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 412349a150598d14da4d7140df5c0286 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_13 + rect: + serializedVersion: 2 + x: 128 + y: 0 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: a937464b42bb3634782dea34c6becb6c + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_5 + rect: + serializedVersion: 2 + x: 256 + y: 0 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: b0f933b217682124dbfc5e6b89abe3d0 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_14 + rect: + serializedVersion: 2 + x: 128 + y: 256 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: f7235c763afe4434e8bb666750a41096 + vertices: [] + indices: + edges: [] + weights: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 3e32d8f5477abfc43b19066e8ad5032e + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Implementation.md b/Implementation.md new file mode 100644 index 0000000..ae477ef --- /dev/null +++ b/Implementation.md @@ -0,0 +1,213 @@ +# Implementation notes + +## Prerequisites + +This project assumes that the target project (the project +that will be using the ``UnityTutorialSystem`` library) exposes +relevant ``UnityEvent``s or can be modified to invoke the event +triggers on the UnityTutorialSystem when the relevant +program state has changed. + +The ``UnityTutorialSystem`` works best if your project has a +clear set of states or conditions that can act as triggers +for tutorial event transitions. Natural examples of these +states or conditions are tasks the player has completed or +events that have been triggered in the game world (ie +an enemy attacks, or supplies run low, etc). + +## Defining Events + +The ``UnityTutorialSystem`` is driven by a set of event streams. +The ``BasicEventStream`` class is a ``ScriptableObject`` that +manages a predefined set of ``BasicEventStreamMessages``. +You can sub-class the ``BasicEventStream`` to generate more +specialised ``BasicEventStreamMessage`` types. As every +``BasicEventStreamMessage`` is an ``ScriptableObject`` itself you +can define additional properties and methods on these +objects if necessary. (By using a scriptable object as +basis of this implementation you can also reference those +events in prefabs and other scriptable object assets; and +it completely avoids the use of Singletons or other scene +based crutches to manage the flow of events.) + +Each ``BasicEventStreamMessage`` carries a reference to its +declaring BasicEventStream. This means you can trigger a +message by simply calling '``BasicEventStreamMessage#Publish``' +at any time. + +``BasicEventStream`` accepts event listeners that will be +called whenever a message managed by this stream has been +published. As such the ``BasicEventStream`` acts as a simple +event bus for its defined messages. You can have multiple +event streams in your project and I recommend that you +create one ``BasicEventStream`` instance for each distinct +sequence of tasks you want to track. + +The stream can handle a limited amount of reentrant events. +This means that a message that is published via the stream +can generate new events that are published via the same +stream, and all of those messages will be sent out to all +listeners. + +To avoid infinite loops from configuration errors where +a message sends out new messages in an infinite loop, the +stream will stop processing after 250 messages have been +processed in the current frame. + +The ``UnityTutorialSystem`` provides a ``PublishStreamEvent`` +mono-behaviour that can be used to publish messages +in response to other ``UnityEvent`` invokations. + +``BasicEventStreamMessage`` objects are defined in the Unity-Editor +by editing the ``BasicEventStream`` itself. Each message entry +will generate a new ``BasicEventStreamMessage`` object as +sub-asset of the ``BasicEventStream``. Each stream will only +process messages that it defined itself. However +``EventStreamMessageAggregator``s can combine messages from many +``BasicEventStream`` instances into higher level tracking events. + +## Event Message Aggregators + +An event message aggregator is a component that analyses +the events it has received to match predefined sequences +of events. + +Each aggregator maintains a list of ``BasicEventStreamMessage`` +objects it expects to see. During start up, the stream +will attempt to register itself with the ``BasicEventStream`` +that publishes those messages. + +The ``EventMessageAggregators`` implemented here are stateful +trackers that attempt to maintain only minimal state during +the matching process. Each time a new event is received, +the ``EventMessageAggregator`` will update its internal state +and will fire events to notify any listener of its eventual +state change. + +Due to the structure of the matching done the ``EventMessageAggregator`` +can tell which ``BasicEventStreamMessage`` would need to be +received next to move the state closer to a succesful +match. (This is very similar to a stream based pattern matcher +or regular expression matching.) Internally the ``EventMessageAggregator`` +implementations use a state machine that can be in one of +three states: Waiting for data, success, or failure. + +The ``EventMessageAggregator`` can provide detailed information +about its internal state, including which of the messages +have been seen, which will be (hopefully) seen next, and which +are not yet matched. + +All of this is implemented via the ``EventMessageAggregator#ListEvents`` +method. This method accepts a buffer of ``EventMessageState`` +data objects so that all calls can be completely non-allocating. + +This information will be used by both the predictor components +and the ``TreeModelBuilder``. + +When an ``EventMessageAggregator`` successfully matched all +expected events, it will fire an internal ``success`` event. +You can use an additional ``EventMessageAggregatorStatePublisher`` +to publish a ``BasicEventStreamMessage`` when that happens. +The ``EventStreamTreeModelBuilder`` will interpret the fact that +a success of an aggregator caused an message to be published +as a hint that this ``EventMessageAggregator`` is a dependent +aggregator of any ``EventMessageAggregator``that waits for +that message. + + +## Predictors + +The whole point of this library is to point players towards the +next goal in tutorial and other guided sequences. This is +achieved with the help of the ``predictor`` components. + +This library ships with two predictor components: + +* NextEventSelector + + This is simple class monitors an set of ``EventMessageAggregator`` + instances to wait for a notification that the aggregator expects + the given ``BasicEventStreamMessage`` as its next received message. + + When that happens this NextEventSelector fires a UnityEvent + that you can use to enable or disable visual indicators or + to trigger any other action to guide the player to the next goal + (or maybe to spawn enemies to prevent the player to get there). + +* NextEventAggregationActivator + + This is specialized version of the NextEventSelector that + simplifies the wiring up of ``EventMessageAggregator`` + hierarchies. It is placed next to an + ``EventMessageAggregatorStatePublisher`` and will activate + or deactivate the associated ``EventMessageAggregator`` when + its ``success`` message is expected to be received next. + +## User Interface + +The ``UnityTutorialSystem`` library comes with a TreeView component +that can render all ``BasicEventStreamMessage``s known to the +aggregators, their hierarchy and relationship between each other +and their current tracking state. + +The UI package contains the necessary code to render a TreeView +(or a list if you set the 'Indent' property to zero) of all +events using Unity's inbuilt UI system. + +The ``EventStreamTreeModelBuilder`` is responsible for monitoring +all ``EventMessageAggregator`` instances in a scene and produces +a TreeModel of ``EventStreamTreeModelData`` objects that reflects +the current state of the tracking. The model is updated as soon +as any of the aggregators reports a new state change. + +Unity does not like generics in serialized objects in a scene, +so to use the TreeView with your own data, you have to create +a non-generic sub-class of the ``TreeView`` class. +The ``TutorialEventTreeView`` is such an example. + +The ``EventStreamTreeModelBuilder`` requires a list of +``EventMessageAggregator`` instances to work. If you allow it, +it can fetch all ``EventMessageAggregator`` instances from the +active scene, which is usually what you'd want anyway. + +The Builder then builds up a static model of the events +processed by each of the aggregators and the relationships between +the aggregators. (Note: This happens only once, so any change +you might make to the set of aggregators afterwards, either +by adding more events or new aggregators, will NOT be reflected +in the tree model. Always define your event messages and +aggregations so that all events are available when the +scene starts. (And if you really MUST make changes, call +``EventStreamTreeModelBuilder#RebuildModel`` afterwards.) + +## Tutorial Events + +So far, all messages were pretty much generic. This library's +primary purpose is to make it easier to write tutorial levels +for games. However, no player wants to see 'Kill the Orc' after +they already slain the green humanoid. + +The ``Tutorial`` package contains a specialised ``TutorialEventStream`` +that contains ``TutorialEventMessage`` objects. It also nicely +demonstrates how to use customized messages in this library. +A ``TutorialEventMessage`` has three description texts for the +event - one for when the task is not done yey ("Go kill that orc"), +one for when the task was a success ("You've slain the orc!") +and one for when the task failed ("The orc has slain you!"). + +A specialised TreeView (because Unity really does not like generics +and refuses to save references of such fields) offers some +additional logic to possibly hide completed tasks. + +The ``TutorialTreeItemRenderer`` is responsible for updating the +various UI components with the data from the ``EventStreamTreeModelData`` +and its contained ``TutorialEventMessage`` with its three different +messages depending on what state the message is in. + +To connect the ``TutorialEventTreeView`` with the +``EventStreamTreeModelBuilder`` that supplies the data that is +displayed, we have to utilize a ``TutorialEventTreeBinding`` +MonoBehaviour. This class simply takes the model produced by +the ``EventStreamTreeModelBuilder`` and registers it in +the TreeView. Multiple TreeViews can share the same model. + diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..15bc72f --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 + +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/Packages/manifest.json b/Packages/manifest.json new file mode 100644 index 0000000..a095c8e --- /dev/null +++ b/Packages/manifest.json @@ -0,0 +1,36 @@ +{ + "dependencies": { + "com.unity.package-manager-ui": "2.0.7", + "com.unity.textmeshpro": "1.3.0", + "com.unity.modules.ai": "1.0.0", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.cloth": "1.0.0", + "com.unity.modules.director": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.particlesystem": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.physics2d": "1.0.0", + "com.unity.modules.screencapture": "1.0.0", + "com.unity.modules.terrain": "1.0.0", + "com.unity.modules.terrainphysics": "1.0.0", + "com.unity.modules.tilemap": "1.0.0", + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.uielements": "1.0.0", + "com.unity.modules.umbra": "1.0.0", + "com.unity.modules.unityanalytics": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.unitywebrequestassetbundle": "1.0.0", + "com.unity.modules.unitywebrequestaudio": "1.0.0", + "com.unity.modules.unitywebrequesttexture": "1.0.0", + "com.unity.modules.unitywebrequestwww": "1.0.0", + "com.unity.modules.vehicles": "1.0.0", + "com.unity.modules.video": "1.0.0", + "com.unity.modules.vr": "1.0.0", + "com.unity.modules.wind": "1.0.0", + "com.unity.modules.xr": "1.0.0" + } +} diff --git a/ProjectSettings/AudioManager.asset b/ProjectSettings/AudioManager.asset new file mode 100644 index 0000000..4f31e74 --- /dev/null +++ b/ProjectSettings/AudioManager.asset @@ -0,0 +1,17 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!11 &1 +AudioManager: + m_ObjectHideFlags: 0 + m_Volume: 1 + Rolloff Scale: 1 + Doppler Factor: 1 + Default Speaker Mode: 2 + m_SampleRate: 0 + m_DSPBufferSize: 1024 + m_VirtualVoiceCount: 512 + m_RealVoiceCount: 32 + m_SpatializerPlugin: + m_AmbisonicDecoderPlugin: + m_DisableAudio: 0 + m_VirtualizeEffects: 1 diff --git a/ProjectSettings/ClusterInputManager.asset b/ProjectSettings/ClusterInputManager.asset new file mode 100644 index 0000000..e7886b2 --- /dev/null +++ b/ProjectSettings/ClusterInputManager.asset @@ -0,0 +1,6 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!236 &1 +ClusterInputManager: + m_ObjectHideFlags: 0 + m_Inputs: [] diff --git a/ProjectSettings/DynamicsManager.asset b/ProjectSettings/DynamicsManager.asset new file mode 100644 index 0000000..b3c263d --- /dev/null +++ b/ProjectSettings/DynamicsManager.asset @@ -0,0 +1,30 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!55 &1 +PhysicsManager: + m_ObjectHideFlags: 0 + serializedVersion: 8 + m_Gravity: {x: 0, y: -9.81, z: 0} + m_DefaultMaterial: {fileID: 0} + m_BounceThreshold: 2 + m_SleepThreshold: 0.005 + m_DefaultContactOffset: 0.01 + m_DefaultSolverIterations: 6 + m_DefaultSolverVelocityIterations: 1 + m_QueriesHitBackfaces: 0 + m_QueriesHitTriggers: 1 + m_EnableAdaptiveForce: 0 + m_ClothInterCollisionDistance: 0 + m_ClothInterCollisionStiffness: 0 + m_ContactsGeneration: 1 + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + m_AutoSimulation: 1 + m_AutoSyncTransforms: 0 + m_ReuseCollisionCallbacks: 1 + m_ClothInterCollisionSettingsToggle: 0 + m_ContactPairsMode: 0 + m_BroadphaseType: 0 + m_WorldBounds: + m_Center: {x: 0, y: 0, z: 0} + m_Extent: {x: 250, y: 250, z: 250} + m_WorldSubdivisions: 8 diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset new file mode 100644 index 0000000..8f21bf9 --- /dev/null +++ b/ProjectSettings/EditorBuildSettings.asset @@ -0,0 +1,11 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1045 &1 +EditorBuildSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Scenes: + - enabled: 1 + path: Assets/Plugins/UnityTutorialSystem/Scenes/TutorialAssembly.unity + guid: d8f8698187927e7458c0c8eb98a938eb + m_configObjects: {} diff --git a/ProjectSettings/EditorSettings.asset b/ProjectSettings/EditorSettings.asset new file mode 100644 index 0000000..29dea52 --- /dev/null +++ b/ProjectSettings/EditorSettings.asset @@ -0,0 +1,21 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!159 &1 +EditorSettings: + m_ObjectHideFlags: 0 + serializedVersion: 7 + m_ExternalVersionControlSupport: Visible Meta Files + m_SerializationMode: 2 + m_LineEndingsForNewScripts: 2 + m_DefaultBehaviorMode: 0 + m_SpritePackerMode: 0 + m_SpritePackerPaddingPower: 1 + m_EtcTextureCompressorBehavior: 1 + m_EtcTextureFastCompressor: 1 + m_EtcTextureNormalCompressor: 2 + m_EtcTextureBestCompressor: 4 + m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd + m_ProjectGenerationRootNamespace: + m_UserGeneratedProjectSuffix: + m_CollabEditorSettings: + inProgressEnabled: 1 diff --git a/ProjectSettings/GraphicsSettings.asset b/ProjectSettings/GraphicsSettings.asset new file mode 100644 index 0000000..1a6b7d1 --- /dev/null +++ b/ProjectSettings/GraphicsSettings.asset @@ -0,0 +1,64 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!30 &1 +GraphicsSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_Deferred: + m_Mode: 1 + m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} + m_DeferredReflections: + m_Mode: 1 + m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} + m_ScreenSpaceShadows: + m_Mode: 1 + m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} + m_LegacyDeferred: + m_Mode: 1 + m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} + m_DepthNormals: + m_Mode: 1 + m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} + m_MotionVectors: + m_Mode: 1 + m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} + m_LightHalo: + m_Mode: 1 + m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} + m_LensFlare: + m_Mode: 1 + m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} + m_AlwaysIncludedShaders: + - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 17000, guid: 0000000000000000f000000000000000, type: 0} + m_PreloadedShaders: [] + m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, + type: 0} + m_CustomRenderPipeline: {fileID: 0} + m_TransparencySortMode: 0 + m_TransparencySortAxis: {x: 0, y: 0, z: 1} + m_DefaultRenderingPath: 1 + m_DefaultMobileRenderingPath: 1 + m_TierSettings: [] + m_LightmapStripping: 0 + m_FogStripping: 0 + m_InstancingStripping: 0 + m_LightmapKeepPlain: 1 + m_LightmapKeepDirCombined: 1 + m_LightmapKeepDynamicPlain: 1 + m_LightmapKeepDynamicDirCombined: 1 + m_LightmapKeepShadowMask: 1 + m_LightmapKeepSubtractive: 1 + m_FogKeepLinear: 1 + m_FogKeepExp: 1 + m_FogKeepExp2: 1 + m_AlbedoSwatchInfos: [] + m_LightsUseLinearIntensity: 0 + m_LightsUseColorTemperature: 0 diff --git a/ProjectSettings/InputManager.asset b/ProjectSettings/InputManager.asset new file mode 100644 index 0000000..17c8f53 --- /dev/null +++ b/ProjectSettings/InputManager.asset @@ -0,0 +1,295 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!13 &1 +InputManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Axes: + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: left + positiveButton: right + altNegativeButton: a + altPositiveButton: d + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: down + positiveButton: up + altNegativeButton: s + altPositiveButton: w + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left ctrl + altNegativeButton: + altPositiveButton: mouse 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left alt + altNegativeButton: + altPositiveButton: mouse 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left shift + altNegativeButton: + altPositiveButton: mouse 2 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: space + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse X + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse Y + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse ScrollWheel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 2 + joyNum: 0 + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 0 + type: 2 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 1 + type: 2 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 0 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 1 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 2 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 3 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: return + altNegativeButton: + altPositiveButton: joystick button 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: enter + altNegativeButton: + altPositiveButton: space + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Cancel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: escape + altNegativeButton: + altPositiveButton: joystick button 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 diff --git a/ProjectSettings/NavMeshAreas.asset b/ProjectSettings/NavMeshAreas.asset new file mode 100644 index 0000000..3b0b7c3 --- /dev/null +++ b/ProjectSettings/NavMeshAreas.asset @@ -0,0 +1,91 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!126 &1 +NavMeshProjectSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + areas: + - name: Walkable + cost: 1 + - name: Not Walkable + cost: 1 + - name: Jump + cost: 2 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + m_LastAgentTypeID: -887442657 + m_Settings: + - serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.75 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_SettingNames: + - Humanoid diff --git a/ProjectSettings/NetworkManager.asset b/ProjectSettings/NetworkManager.asset new file mode 100644 index 0000000..5dc6a83 --- /dev/null +++ b/ProjectSettings/NetworkManager.asset @@ -0,0 +1,8 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!149 &1 +NetworkManager: + m_ObjectHideFlags: 0 + m_DebugLevel: 0 + m_Sendrate: 15 + m_AssetToPrefab: {} diff --git a/ProjectSettings/Physics2DSettings.asset b/ProjectSettings/Physics2DSettings.asset new file mode 100644 index 0000000..57760e2 --- /dev/null +++ b/ProjectSettings/Physics2DSettings.asset @@ -0,0 +1,38 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!19 &1 +Physics2DSettings: + m_ObjectHideFlags: 0 + serializedVersion: 4 + m_Gravity: {x: 0, y: -9.81} + m_DefaultMaterial: {fileID: 0} + m_VelocityIterations: 8 + m_PositionIterations: 3 + m_VelocityThreshold: 1 + m_MaxLinearCorrection: 0.2 + m_MaxAngularCorrection: 8 + m_MaxTranslationSpeed: 100 + m_MaxRotationSpeed: 360 + m_BaumgarteScale: 0.2 + m_BaumgarteTimeOfImpactScale: 0.75 + m_TimeToSleep: 0.5 + m_LinearSleepTolerance: 0.01 + m_AngularSleepTolerance: 2 + m_DefaultContactOffset: 0.01 + m_AutoSimulation: 1 + m_QueriesHitTriggers: 1 + m_QueriesStartInColliders: 1 + m_ChangeStopsCallbacks: 0 + m_CallbacksOnDisable: 1 + m_ReuseCollisionCallbacks: 1 + m_AutoSyncTransforms: 0 + m_AlwaysShowColliders: 0 + m_ShowColliderSleep: 1 + m_ShowColliderContacts: 0 + m_ShowColliderAABB: 0 + m_ContactArrowScale: 0.2 + m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} + m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} + m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} + m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff diff --git a/ProjectSettings/PresetManager.asset b/ProjectSettings/PresetManager.asset new file mode 100644 index 0000000..820e662 --- /dev/null +++ b/ProjectSettings/PresetManager.asset @@ -0,0 +1,27 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1386491679 &1 +PresetManager: + m_ObjectHideFlags: 0 + m_DefaultList: + - type: + m_NativeTypeID: 108 + m_ManagedTypePPtr: {fileID: 0} + m_ManagedTypeFallback: + defaultPresets: + - m_Preset: {fileID: 2655988077585873504, guid: c1cf8506f04ef2c4a88b64b6c4202eea, + type: 2} + - type: + m_NativeTypeID: 1020 + m_ManagedTypePPtr: {fileID: 0} + m_ManagedTypeFallback: + defaultPresets: + - m_Preset: {fileID: 2655988077585873504, guid: 0cd792cc87e492d43b4e95b205fc5cc6, + type: 2} + - type: + m_NativeTypeID: 1006 + m_ManagedTypePPtr: {fileID: 0} + m_ManagedTypeFallback: + defaultPresets: + - m_Preset: {fileID: 2655988077585873504, guid: 7a99f8aa944efe94cb9bd74562b7d5f9, + type: 2} diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset new file mode 100644 index 0000000..609604b --- /dev/null +++ b/ProjectSettings/ProjectSettings.asset @@ -0,0 +1,627 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!129 &1 +PlayerSettings: + m_ObjectHideFlags: 0 + serializedVersion: 15 + productGUID: d039e26a85babdc4d9e67da1fb311400 + AndroidProfiler: 0 + AndroidFilterTouchesWhenObscured: 0 + AndroidEnableSustainedPerformanceMode: 0 + defaultScreenOrientation: 4 + targetDevice: 2 + useOnDemandResources: 0 + accelerometerFrequency: 60 + companyName: DefaultCompany + productName: Empty + defaultCursor: {fileID: 0} + cursorHotspot: {x: 0, y: 0} + m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} + m_ShowUnitySplashScreen: 1 + m_ShowUnitySplashLogo: 1 + m_SplashScreenOverlayOpacity: 1 + m_SplashScreenAnimation: 1 + m_SplashScreenLogoStyle: 1 + m_SplashScreenDrawMode: 0 + m_SplashScreenBackgroundAnimationZoom: 1 + m_SplashScreenLogoAnimationZoom: 1 + m_SplashScreenBackgroundLandscapeAspect: 1 + m_SplashScreenBackgroundPortraitAspect: 1 + m_SplashScreenBackgroundLandscapeUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenBackgroundPortraitUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenLogos: [] + m_VirtualRealitySplashScreen: {fileID: 0} + m_HolographicTrackingLossScreen: {fileID: 0} + defaultScreenWidth: 1024 + defaultScreenHeight: 768 + defaultScreenWidthWeb: 960 + defaultScreenHeightWeb: 600 + m_StereoRenderingPath: 0 + m_ActiveColorSpace: 0 + m_MTRendering: 1 + m_StackTraceTypes: 010000000100000001000000010000000100000001000000 + iosShowActivityIndicatorOnLoading: -1 + androidShowActivityIndicatorOnLoading: -1 + iosAppInBackgroundBehavior: 0 + displayResolutionDialog: 1 + iosAllowHTTPDownload: 1 + allowedAutorotateToPortrait: 1 + allowedAutorotateToPortraitUpsideDown: 1 + allowedAutorotateToLandscapeRight: 1 + allowedAutorotateToLandscapeLeft: 1 + useOSAutorotation: 1 + use32BitDisplayBuffer: 1 + preserveFramebufferAlpha: 0 + disableDepthAndStencilBuffers: 0 + androidStartInFullscreen: 1 + androidRenderOutsideSafeArea: 0 + androidBlitType: 0 + defaultIsNativeResolution: 1 + macRetinaSupport: 1 + runInBackground: 1 + captureSingleScreen: 0 + muteOtherAudioSources: 0 + Prepare IOS For Recording: 0 + Force IOS Speakers When Recording: 0 + deferSystemGesturesMode: 0 + hideHomeButton: 0 + submitAnalytics: 1 + usePlayerLog: 1 + bakeCollisionMeshes: 0 + forceSingleInstance: 0 + resizableWindow: 0 + useMacAppStoreValidation: 0 + macAppStoreCategory: public.app-category.games + gpuSkinning: 1 + graphicsJobs: 0 + xboxPIXTextureCapture: 0 + xboxEnableAvatar: 0 + xboxEnableKinect: 0 + xboxEnableKinectAutoTracking: 0 + xboxEnableFitness: 0 + visibleInBackground: 1 + allowFullscreenSwitch: 1 + graphicsJobMode: 0 + fullscreenMode: 1 + xboxSpeechDB: 0 + xboxEnableHeadOrientation: 0 + xboxEnableGuest: 0 + xboxEnablePIXSampling: 0 + metalFramebufferOnly: 0 + xboxOneResolution: 0 + xboxOneSResolution: 0 + xboxOneXResolution: 3 + xboxOneMonoLoggingLevel: 0 + xboxOneLoggingLevel: 1 + xboxOneDisableEsram: 0 + xboxOnePresentImmediateThreshold: 0 + switchQueueCommandMemory: 0 + switchQueueControlMemory: 16384 + switchQueueComputeMemory: 262144 + switchNVNShaderPoolsGranularity: 33554432 + switchNVNDefaultPoolsGranularity: 16777216 + switchNVNOtherPoolsGranularity: 16777216 + vulkanEnableSetSRGBWrite: 0 + m_SupportedAspectRatios: + 4:3: 1 + 5:4: 1 + 16:10: 1 + 16:9: 1 + Others: 1 + bundleVersion: 0.1 + preloadedAssets: [] + metroInputSource: 0 + wsaTransparentSwapchain: 0 + m_HolographicPauseOnTrackingLoss: 1 + xboxOneDisableKinectGpuReservation: 0 + xboxOneEnable7thCore: 0 + isWsaHolographicRemotingEnabled: 0 + vrSettings: + cardboard: + depthFormat: 0 + enableTransitionView: 0 + daydream: + depthFormat: 0 + useSustainedPerformanceMode: 0 + enableVideoLayer: 0 + useProtectedVideoMemory: 0 + minimumSupportedHeadTracking: 0 + maximumSupportedHeadTracking: 1 + hololens: + depthFormat: 1 + depthBufferSharingEnabled: 0 + oculus: + sharedDepthBuffer: 1 + dashSupport: 1 + enable360StereoCapture: 0 + protectGraphicsMemory: 0 + enableFrameTimingStats: 0 + useHDRDisplay: 0 + m_ColorGamuts: 00000000 + targetPixelDensity: 30 + resolutionScalingMode: 0 + androidSupportedAspectRatio: 1 + androidMaxAspectRatio: 2.1 + applicationIdentifier: {} + buildNumber: {} + AndroidBundleVersionCode: 1 + AndroidMinSdkVersion: 16 + AndroidTargetSdkVersion: 0 + AndroidPreferredInstallLocation: 1 + aotOptions: + stripEngineCode: 1 + iPhoneStrippingLevel: 0 + iPhoneScriptCallOptimization: 0 + ForceInternetPermission: 0 + ForceSDCardPermission: 0 + CreateWallpaper: 0 + APKExpansionFiles: 0 + keepLoadedShadersAlive: 0 + StripUnusedMeshComponents: 1 + VertexChannelCompressionMask: 4054 + iPhoneSdkVersion: 988 + iOSTargetOSVersionString: 9.0 + tvOSSdkVersion: 0 + tvOSRequireExtendedGameController: 0 + tvOSTargetOSVersionString: 9.0 + uIPrerenderedIcon: 0 + uIRequiresPersistentWiFi: 0 + uIRequiresFullScreen: 1 + uIStatusBarHidden: 1 + uIExitOnSuspend: 0 + uIStatusBarStyle: 0 + iPhoneSplashScreen: {fileID: 0} + iPhoneHighResSplashScreen: {fileID: 0} + iPhoneTallHighResSplashScreen: {fileID: 0} + iPhone47inSplashScreen: {fileID: 0} + iPhone55inPortraitSplashScreen: {fileID: 0} + iPhone55inLandscapeSplashScreen: {fileID: 0} + iPhone58inPortraitSplashScreen: {fileID: 0} + iPhone58inLandscapeSplashScreen: {fileID: 0} + iPadPortraitSplashScreen: {fileID: 0} + iPadHighResPortraitSplashScreen: {fileID: 0} + iPadLandscapeSplashScreen: {fileID: 0} + iPadHighResLandscapeSplashScreen: {fileID: 0} + appleTVSplashScreen: {fileID: 0} + appleTVSplashScreen2x: {fileID: 0} + tvOSSmallIconLayers: [] + tvOSSmallIconLayers2x: [] + tvOSLargeIconLayers: [] + tvOSLargeIconLayers2x: [] + tvOSTopShelfImageLayers: [] + tvOSTopShelfImageLayers2x: [] + tvOSTopShelfImageWideLayers: [] + tvOSTopShelfImageWideLayers2x: [] + iOSLaunchScreenType: 0 + iOSLaunchScreenPortrait: {fileID: 0} + iOSLaunchScreenLandscape: {fileID: 0} + iOSLaunchScreenBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreenFillPct: 100 + iOSLaunchScreenSize: 100 + iOSLaunchScreenCustomXibPath: + iOSLaunchScreeniPadType: 0 + iOSLaunchScreeniPadImage: {fileID: 0} + iOSLaunchScreeniPadBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreeniPadFillPct: 100 + iOSLaunchScreeniPadSize: 100 + iOSLaunchScreeniPadCustomXibPath: + iOSUseLaunchScreenStoryboard: 0 + iOSLaunchScreenCustomStoryboardPath: + iOSDeviceRequirements: [] + iOSURLSchemes: [] + iOSBackgroundModes: 0 + iOSMetalForceHardShadows: 0 + metalEditorSupport: 1 + metalAPIValidation: 1 + iOSRenderExtraFrameOnPause: 0 + appleDeveloperTeamID: + iOSManualSigningProvisioningProfileID: + tvOSManualSigningProvisioningProfileID: + iOSManualSigningProvisioningProfileType: 0 + tvOSManualSigningProvisioningProfileType: 0 + appleEnableAutomaticSigning: 0 + iOSRequireARKit: 0 + appleEnableProMotion: 0 + clonedFromGUID: c0afd0d1d80e3634a9dac47e8a0426ea + templatePackageId: com.unity.template.3d@1.0.4 + templateDefaultScene: Assets/Scenes/SampleScene.unity + AndroidTargetArchitectures: 5 + AndroidSplashScreenScale: 0 + androidSplashScreen: {fileID: 0} + AndroidKeystoreName: + AndroidKeyaliasName: + AndroidBuildApkPerCpuArchitecture: 0 + AndroidTVCompatibility: 1 + AndroidIsGame: 1 + AndroidEnableTango: 0 + androidEnableBanner: 1 + androidUseLowAccuracyLocation: 0 + m_AndroidBanners: + - width: 320 + height: 180 + banner: {fileID: 0} + androidGamepadSupportLevel: 0 + resolutionDialogBanner: {fileID: 0} + m_BuildTargetIcons: [] + m_BuildTargetPlatformIcons: [] + m_BuildTargetBatching: + - m_BuildTarget: Standalone + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: tvOS + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: Android + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: iPhone + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: WebGL + m_StaticBatching: 0 + m_DynamicBatching: 0 + m_BuildTargetGraphicsAPIs: + - m_BuildTarget: AndroidPlayer + m_APIs: 0b00000008000000 + m_Automatic: 1 + - m_BuildTarget: iOSSupport + m_APIs: 10000000 + m_Automatic: 1 + - m_BuildTarget: AppleTVSupport + m_APIs: 10000000 + m_Automatic: 0 + - m_BuildTarget: WebGLSupport + m_APIs: 0b000000 + m_Automatic: 1 + m_BuildTargetVRSettings: + - m_BuildTarget: Standalone + m_Enabled: 0 + m_Devices: + - Oculus + - OpenVR + m_BuildTargetEnableVuforiaSettings: [] + openGLRequireES31: 0 + openGLRequireES31AEP: 0 + m_TemplateCustomTags: {} + mobileMTRendering: + Android: 1 + iPhone: 1 + tvOS: 1 + m_BuildTargetGroupLightmapEncodingQuality: [] + m_BuildTargetGroupLightmapSettings: [] + playModeTestRunnerEnabled: 0 + runPlayModeTestAsEditModeTest: 0 + actionOnDotNetUnhandledException: 1 + enableInternalProfiler: 0 + logObjCUncaughtExceptions: 1 + enableCrashReportAPI: 0 + cameraUsageDescription: + locationUsageDescription: + microphoneUsageDescription: + switchNetLibKey: + switchSocketMemoryPoolSize: 6144 + switchSocketAllocatorPoolSize: 128 + switchSocketConcurrencyLimit: 14 + switchScreenResolutionBehavior: 2 + switchUseCPUProfiler: 0 + switchApplicationID: 0x01004b9000490000 + switchNSODependencies: + switchTitleNames_0: + switchTitleNames_1: + switchTitleNames_2: + switchTitleNames_3: + switchTitleNames_4: + switchTitleNames_5: + switchTitleNames_6: + switchTitleNames_7: + switchTitleNames_8: + switchTitleNames_9: + switchTitleNames_10: + switchTitleNames_11: + switchTitleNames_12: + switchTitleNames_13: + switchTitleNames_14: + switchPublisherNames_0: + switchPublisherNames_1: + switchPublisherNames_2: + switchPublisherNames_3: + switchPublisherNames_4: + switchPublisherNames_5: + switchPublisherNames_6: + switchPublisherNames_7: + switchPublisherNames_8: + switchPublisherNames_9: + switchPublisherNames_10: + switchPublisherNames_11: + switchPublisherNames_12: + switchPublisherNames_13: + switchPublisherNames_14: + switchIcons_0: {fileID: 0} + switchIcons_1: {fileID: 0} + switchIcons_2: {fileID: 0} + switchIcons_3: {fileID: 0} + switchIcons_4: {fileID: 0} + switchIcons_5: {fileID: 0} + switchIcons_6: {fileID: 0} + switchIcons_7: {fileID: 0} + switchIcons_8: {fileID: 0} + switchIcons_9: {fileID: 0} + switchIcons_10: {fileID: 0} + switchIcons_11: {fileID: 0} + switchIcons_12: {fileID: 0} + switchIcons_13: {fileID: 0} + switchIcons_14: {fileID: 0} + switchSmallIcons_0: {fileID: 0} + switchSmallIcons_1: {fileID: 0} + switchSmallIcons_2: {fileID: 0} + switchSmallIcons_3: {fileID: 0} + switchSmallIcons_4: {fileID: 0} + switchSmallIcons_5: {fileID: 0} + switchSmallIcons_6: {fileID: 0} + switchSmallIcons_7: {fileID: 0} + switchSmallIcons_8: {fileID: 0} + switchSmallIcons_9: {fileID: 0} + switchSmallIcons_10: {fileID: 0} + switchSmallIcons_11: {fileID: 0} + switchSmallIcons_12: {fileID: 0} + switchSmallIcons_13: {fileID: 0} + switchSmallIcons_14: {fileID: 0} + switchManualHTML: + switchAccessibleURLs: + switchLegalInformation: + switchMainThreadStackSize: 1048576 + switchPresenceGroupId: + switchLogoHandling: 0 + switchReleaseVersion: 0 + switchDisplayVersion: 1.0.0 + switchStartupUserAccount: 0 + switchTouchScreenUsage: 0 + switchSupportedLanguagesMask: 0 + switchLogoType: 0 + switchApplicationErrorCodeCategory: + switchUserAccountSaveDataSize: 0 + switchUserAccountSaveDataJournalSize: 0 + switchApplicationAttribute: 0 + switchCardSpecSize: -1 + switchCardSpecClock: -1 + switchRatingsMask: 0 + switchRatingsInt_0: 0 + switchRatingsInt_1: 0 + switchRatingsInt_2: 0 + switchRatingsInt_3: 0 + switchRatingsInt_4: 0 + switchRatingsInt_5: 0 + switchRatingsInt_6: 0 + switchRatingsInt_7: 0 + switchRatingsInt_8: 0 + switchRatingsInt_9: 0 + switchRatingsInt_10: 0 + switchRatingsInt_11: 0 + switchLocalCommunicationIds_0: + switchLocalCommunicationIds_1: + switchLocalCommunicationIds_2: + switchLocalCommunicationIds_3: + switchLocalCommunicationIds_4: + switchLocalCommunicationIds_5: + switchLocalCommunicationIds_6: + switchLocalCommunicationIds_7: + switchParentalControl: 0 + switchAllowsScreenshot: 1 + switchAllowsVideoCapturing: 1 + switchAllowsRuntimeAddOnContentInstall: 0 + switchDataLossConfirmation: 0 + switchUserAccountLockEnabled: 0 + switchSystemResourceMemory: 16777216 + switchSupportedNpadStyles: 3 + switchNativeFsCacheSize: 32 + switchIsHoldTypeHorizontal: 0 + switchSupportedNpadCount: 8 + switchSocketConfigEnabled: 0 + switchTcpInitialSendBufferSize: 32 + switchTcpInitialReceiveBufferSize: 64 + switchTcpAutoSendBufferSizeMax: 256 + switchTcpAutoReceiveBufferSizeMax: 256 + switchUdpSendBufferSize: 9 + switchUdpReceiveBufferSize: 42 + switchSocketBufferEfficiency: 4 + switchSocketInitializeEnabled: 1 + switchNetworkInterfaceManagerInitializeEnabled: 1 + switchPlayerConnectionEnabled: 1 + ps4NPAgeRating: 12 + ps4NPTitleSecret: + ps4NPTrophyPackPath: + ps4ParentalLevel: 11 + ps4ContentID: ED1633-NPXX51362_00-0000000000000000 + ps4Category: 0 + ps4MasterVersion: 01.00 + ps4AppVersion: 01.00 + ps4AppType: 0 + ps4ParamSfxPath: + ps4VideoOutPixelFormat: 0 + ps4VideoOutInitialWidth: 1920 + ps4VideoOutBaseModeInitialWidth: 1920 + ps4VideoOutReprojectionRate: 60 + ps4PronunciationXMLPath: + ps4PronunciationSIGPath: + ps4BackgroundImagePath: + ps4StartupImagePath: + ps4StartupImagesFolder: + ps4IconImagesFolder: + ps4SaveDataImagePath: + ps4SdkOverride: + ps4BGMPath: + ps4ShareFilePath: + ps4ShareOverlayImagePath: + ps4PrivacyGuardImagePath: + ps4NPtitleDatPath: + ps4RemotePlayKeyAssignment: -1 + ps4RemotePlayKeyMappingDir: + ps4PlayTogetherPlayerCount: 0 + ps4EnterButtonAssignment: 1 + ps4ApplicationParam1: 0 + ps4ApplicationParam2: 0 + ps4ApplicationParam3: 0 + ps4ApplicationParam4: 0 + ps4DownloadDataSize: 0 + ps4GarlicHeapSize: 2048 + ps4ProGarlicHeapSize: 2560 + ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ + ps4pnSessions: 1 + ps4pnPresence: 1 + ps4pnFriends: 1 + ps4pnGameCustomData: 1 + playerPrefsSupport: 0 + enableApplicationExit: 0 + resetTempFolder: 1 + restrictedAudioUsageRights: 0 + ps4UseResolutionFallback: 0 + ps4ReprojectionSupport: 0 + ps4UseAudio3dBackend: 0 + ps4SocialScreenEnabled: 0 + ps4ScriptOptimizationLevel: 0 + ps4Audio3dVirtualSpeakerCount: 14 + ps4attribCpuUsage: 0 + ps4PatchPkgPath: + ps4PatchLatestPkgPath: + ps4PatchChangeinfoPath: + ps4PatchDayOne: 0 + ps4attribUserManagement: 0 + ps4attribMoveSupport: 0 + ps4attrib3DSupport: 0 + ps4attribShareSupport: 0 + ps4attribExclusiveVR: 0 + ps4disableAutoHideSplash: 0 + ps4videoRecordingFeaturesUsed: 0 + ps4contentSearchFeaturesUsed: 0 + ps4attribEyeToEyeDistanceSettingVR: 0 + ps4IncludedModules: [] + monoEnv: + splashScreenBackgroundSourceLandscape: {fileID: 0} + splashScreenBackgroundSourcePortrait: {fileID: 0} + spritePackerPolicy: + webGLMemorySize: 256 + webGLExceptionSupport: 1 + webGLNameFilesAsHashes: 0 + webGLDataCaching: 1 + webGLDebugSymbols: 0 + webGLEmscriptenArgs: + webGLModulesDirectory: + webGLTemplate: APPLICATION:Default + webGLAnalyzeBuildSize: 0 + webGLUseEmbeddedResources: 0 + webGLCompressionFormat: 1 + webGLLinkerTarget: 1 + webGLThreadsSupport: 0 + scriptingDefineSymbols: {} + platformArchitecture: {} + scriptingBackend: {} + il2cppCompilerConfiguration: {} + managedStrippingLevel: {} + incrementalIl2cppBuild: {} + allowUnsafeCode: 0 + additionalIl2CppArgs: + scriptingRuntimeVersion: 1 + apiCompatibilityLevelPerPlatform: {} + m_RenderingPath: 1 + m_MobileRenderingPath: 1 + metroPackageName: Template_3D + metroPackageVersion: + metroCertificatePath: + metroCertificatePassword: + metroCertificateSubject: + metroCertificateIssuer: + metroCertificateNotAfter: 0000000000000000 + metroApplicationDescription: Template_3D + wsaImages: {} + metroTileShortName: + metroTileShowName: 0 + metroMediumTileShowName: 0 + metroLargeTileShowName: 0 + metroWideTileShowName: 0 + metroSupportStreamingInstall: 0 + metroLastRequiredScene: 0 + metroDefaultTileSize: 1 + metroTileForegroundText: 2 + metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} + metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, + a: 1} + metroSplashScreenUseBackgroundColor: 0 + platformCapabilities: {} + metroTargetDeviceFamilies: {} + metroFTAName: + metroFTAFileTypes: [] + metroProtocolName: + metroCompilationOverrides: 1 + XboxOneProductId: + XboxOneUpdateKey: + XboxOneSandboxId: + XboxOneContentId: + XboxOneTitleId: + XboxOneSCId: + XboxOneGameOsOverridePath: + XboxOnePackagingOverridePath: + XboxOneAppManifestOverridePath: + XboxOneVersion: 1.0.0.0 + XboxOnePackageEncryption: 0 + XboxOnePackageUpdateGranularity: 2 + XboxOneDescription: + XboxOneLanguage: + - enus + XboxOneCapability: [] + XboxOneGameRating: {} + XboxOneIsContentPackage: 0 + XboxOneEnableGPUVariability: 0 + XboxOneSockets: {} + XboxOneSplashScreen: {fileID: 0} + XboxOneAllowedProductIds: [] + XboxOnePersistentLocalStorageSize: 0 + XboxOneXTitleMemory: 8 + xboxOneScriptCompiler: 0 + XboxOneOverrideIdentityName: + vrEditorSettings: + daydream: + daydreamIconForeground: {fileID: 0} + daydreamIconBackground: {fileID: 0} + cloudServicesEnabled: + UNet: 1 + luminIcon: + m_Name: + m_ModelFolderPath: + m_PortalFolderPath: + luminCert: + m_CertPath: + m_PrivateKeyPath: + luminIsChannelApp: 0 + luminVersion: + m_VersionCode: 1 + m_VersionName: + facebookSdkVersion: 7.9.4 + facebookAppId: + facebookCookies: 1 + facebookLogging: 1 + facebookStatus: 1 + facebookXfbml: 0 + facebookFrictionlessRequests: 1 + apiCompatibilityLevel: 6 + cloudProjectId: + framebufferDepthMemorylessMode: 0 + projectName: + organizationId: + cloudEnabled: 0 + enableNativePlatformBackendsForNewInputSystem: 0 + disableOldInputManagerSupport: 0 + legacyClampBlendShapeWeights: 0 diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt new file mode 100644 index 0000000..6dfd6c1 --- /dev/null +++ b/ProjectSettings/ProjectVersion.txt @@ -0,0 +1 @@ +m_EditorVersion: 2018.3.14f1 diff --git a/ProjectSettings/QualitySettings.asset b/ProjectSettings/QualitySettings.asset new file mode 100644 index 0000000..0621bef --- /dev/null +++ b/ProjectSettings/QualitySettings.asset @@ -0,0 +1,190 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!47 &1 +QualitySettings: + m_ObjectHideFlags: 0 + serializedVersion: 5 + m_CurrentQuality: 4 + m_QualitySettings: + - serializedVersion: 2 + name: Very Low + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 15 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 1 + textureQuality: 1 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.3 + maximumLODLevel: 0 + particleRaycastBudget: 4 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Low + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.4 + maximumLODLevel: 0 + particleRaycastBudget: 16 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Medium + pixelLightCount: 1 + shadows: 1 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 1 + lodBias: 0.7 + maximumLODLevel: 0 + particleRaycastBudget: 64 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: High + pixelLightCount: 2 + shadows: 2 + shadowResolution: 1 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 40 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 2 + softParticles: 0 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 1 + maximumLODLevel: 0 + particleRaycastBudget: 256 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Very High + pixelLightCount: 3 + shadows: 2 + shadowResolution: 2 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 40 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 4 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 4 + softParticles: 1 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 1.5 + maximumLODLevel: 0 + particleRaycastBudget: 1024 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Ultra + pixelLightCount: 4 + shadows: 2 + shadowResolution: 2 + shadowProjection: 1 + shadowCascades: 4 + shadowDistance: 150 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 4 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 4 + softParticles: 1 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 2 + maximumLODLevel: 0 + particleRaycastBudget: 4096 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + m_PerPlatformDefaultQuality: + Android: 2 + Nintendo 3DS: 5 + Nintendo Switch: 5 + PS4: 5 + PSP2: 2 + Standalone: 5 + Tizen: 2 + WebGL: 3 + WiiU: 5 + Windows Store Apps: 5 + XboxOne: 5 + iPhone: 2 + tvOS: 2 diff --git a/ProjectSettings/TagManager.asset b/ProjectSettings/TagManager.asset new file mode 100644 index 0000000..17cb803 --- /dev/null +++ b/ProjectSettings/TagManager.asset @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!78 &1 +TagManager: + serializedVersion: 2 + tags: [] + layers: + - Default + - TransparentFX + - Ignore Raycast + - + - Water + - UI + - + - + - PostProcessing + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + m_SortingLayers: + - name: Default + uniqueID: 0 + locked: 0 diff --git a/ProjectSettings/TimeManager.asset b/ProjectSettings/TimeManager.asset new file mode 100644 index 0000000..06bcc6d --- /dev/null +++ b/ProjectSettings/TimeManager.asset @@ -0,0 +1,9 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!5 &1 +TimeManager: + m_ObjectHideFlags: 0 + Fixed Timestep: 0.02 + Maximum Allowed Timestep: 0.1 + m_TimeScale: 1 + Maximum Particle Timestep: 0.03 diff --git a/ProjectSettings/UnityConnectSettings.asset b/ProjectSettings/UnityConnectSettings.asset new file mode 100644 index 0000000..c3ae9a0 --- /dev/null +++ b/ProjectSettings/UnityConnectSettings.asset @@ -0,0 +1,34 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!310 &1 +UnityConnectSettings: + m_ObjectHideFlags: 0 + serializedVersion: 1 + m_Enabled: 1 + m_TestMode: 0 + m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events + m_EventUrl: https://cdp.cloud.unity3d.com/v1/events + m_ConfigUrl: https://config.uca.cloud.unity3d.com + m_TestInitMode: 0 + CrashReportingSettings: + m_EventUrl: https://perf-events.cloud.unity3d.com + m_Enabled: 0 + m_LogBufferSize: 10 + m_CaptureEditorExceptions: 1 + UnityPurchasingSettings: + m_Enabled: 0 + m_TestMode: 0 + UnityAnalyticsSettings: + m_Enabled: 0 + m_TestMode: 0 + m_InitializeOnStartup: 1 + UnityAdsSettings: + m_Enabled: 0 + m_InitializeOnStartup: 1 + m_TestMode: 0 + m_IosGameId: + m_AndroidGameId: + m_GameIds: {} + m_GameId: + PerformanceReportingSettings: + m_Enabled: 0 diff --git a/ProjectSettings/VFXManager.asset b/ProjectSettings/VFXManager.asset new file mode 100644 index 0000000..6e0eaca --- /dev/null +++ b/ProjectSettings/VFXManager.asset @@ -0,0 +1,11 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!937362698 &1 +VFXManager: + m_ObjectHideFlags: 0 + m_IndirectShader: {fileID: 0} + m_CopyBufferShader: {fileID: 0} + m_SortShader: {fileID: 0} + m_RenderPipeSettingsPath: + m_FixedTimeStep: 0.016666668 + m_MaxDeltaTime: 0.05 diff --git a/README.md b/README.md index 97613b4..a1d080d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,190 @@ # Unity Tutorial-System Engine +This module contains the necessary code to build an event based tutorial +system for Unity games. + +In modern games we player expect to be gently taught how to play the game. +For this purpose the first level or two contains a carefully choreographed +walk-through where each step is laid out clearly. The game tracks our +progress and guides us towards the next step. + +The code in this module contains all necessary ingredients to build such +a system. It contains an central event bus with predefined, strongly +referenced events, state tracking and user interface components to visualise +the current state of the tutorial. + +Larger sequences of events can be broken down into smaller tasks. You can +flexibly combine multiple task-flows into larger work-flows, including +optional or alternative tasks. + +![Demo](unity-tutorial-system-demo.gif) + +## Usage and Setup + +### Step 1: Define the events the system tracks. + +The system tracks events that happen in your game. I would recommend to +model these events as a workflow or sequence diagram, it will make your +task a lot easier. + +After planing out which events you need in your game, create one ore more +EventStream scriptable objects (via the menu +``Assets->Create ..->Event Stream->Event Stream``). + +Each EventStream declears the messages it can handle. Messages are in +itself scriptable objects and can contain additional properties. + +To create messages, open the event stream object in the Unity inspector +and add entries to the "Message Types" list. When you defined all entries, +save the object, then press "Generate Message Handles", and then save +once again. + +(Scriptable objects that have been generated as child objects do not show +up in the inspector and project browser until the currently pending +changes have been saved. This is a peculiar Unity-Editor behaviour that +we cannot change.) + +***Warning***: If you rename or reorder events, Unity will generate new +object-IDs for each message. This usually erases all references to these +objects in MonoBehaviours. After making changs to the event-stream, you +will have to revalidate your objects. + +### Step 2: Generating event-stream messages + +Program your game logic as usual. Whenever something happens in your game +that should trigger a state change in the tutorial (ie. the player completed +a task) you need to fire an event for the event-stream. + +Each mesasge object carries a reference to its event stream. If you have a +reference to a message, you can simply fire the event by invoking +``BasicEventStreamMessage#Publish()``. + +The UnityTutorialSystem ships with a ``PublishStreamEvent`` MonoBehaviour that +you can add to your existing game objects. This MonoBehaviour holds a +reference to a EventStreamMessage object and contains a single public +method (``TriggerEvent()``) to publish the event to the event stream. You can +either call this method from your code (or hold a reference to the +EventStreamMessage and call ``Publish()`` yourself), or you can wire up this +method to an UnityEvent that your game object componentns expose. + +The cubes in the demo scene contain a MouseEventPublisher script that raises +an UnityEvent for each mouse event that is triggered on MonoBehaviour scripts. +In the demo, the ``clicked`` event then calls the +``PublishStreamEvent#TriggerEvent`` method on the PublishStreamEvent that is +also added to each cube. + +### Step 3: Processing event stream messages + +Each event stream forwards all valid received events to all listeners for +processing. The processing to combine multiple events to track larger state +changes happens in event aggregator MonoBehaviours. + +The default implementations shipped in the library are configured with a list +of EventStreamMessage objects. The aggregators automatically subscribe to all +required event message streams and expose UnityEvents for when the aggregator +becomes active, progressed to the next state, and when matching succeeded or +failed. All aggregators track all relevant event states internally and +publish the current state of its tracking via the ListEvents method. The +EventMessageState informs you of each message the stream expects and whether +the message has been received, or whether this message is the next expected +event. + +For event processing the UnityTutorialSystem provides the following implementations: + +* EventSequenceAggregator + + Represents an ordered sequence of events. The event aggregator will report + a successful match if all defined events have been recorded in the defined + order. + + This aggregator can process events out of order if the next event message + is marked as out-of-order executable, and if the event aggregator's + validation mode is set to ``AllowOutOfOrderEvents``. + + > In the demo scene, the MelodyStateHandler is a sequence aggregator + > that tracks clicks on the coloured cubes. Each click generates + > a tone and successfully playing the melody will complete the task. + +* EventSetAggregator + + Represents an unordered sequence of events. + + The aggregator will report a successful match if all defined events have + seen seen at least once. + + If matching is set to strict, the aggregator will fail the matching if + any duplicate event has been received. + +* OneOfEventSetAggregator + + Represents a choice of events. This aggregator will report an success as + soon as one of the defined events has been received. + +* EventMessageCounter + + An simple example aggregator that counts incoming events that match + the given event message. + +### Step 4: Combine Event Aggregators + +Each event aggregator publishes UnityEvents during state changes. This +means you can add a PublishStreamEvent component to publish messages on +these events. + +As it is very common to send events when a event aggregation +is complete, this project also contains the specialised +``TutorialEventStatePublisher`` MonoBehaviour to simplify the configuration +of the event processing. + +### Step 5: Displaying Task Lists + +Tutorials usually display a list of tasks to guide the player through +these crucial first steps. This project ships with a simple Tree/List +GUI component that displays the known events inside a Unity GUI. + +The tree/list display consists of two parts: + +* The TutorialEventStreamManager is responsible for building a + display model of all known event aggregators and their relationships + between each other. This class constantly monitors and updates all + aggregators to update the display model with the new data. + + The resulting model is then published to a TutorialEventTreeView. + +* The TutorialEventTreeView is a Unity-GUI controller that is responsible + for displaying the model content in the UI. + + In the demo a Unity-canvas contains a ScrollPane and a dynamic, + vertical list of elements. The ``ContentList`` game object contains + the TreeView script that is responsible for instantiating new display + elements for each element in the tree model. + + The ``_Template`` game object is used as template for each data item. + +If an EventAggregator uses a TutorialEventStatePublisher +to publishes a success message, and if that message is expected in another +EventAggregator, the TutorialEventStreamManager treats this as a +hierarchical relationship between the two aggregators. + +> In the sample scene, the 'CombinedStateHandler' aggregator game object +> receives events from both the MelodyStateHandler and the ButtonStateHandler +> object. The TutorialEventStreamManager on the StateHandlers game object +> therefore treats both both the MelodyStateHandler and the ButtonStateHandler +> as dependents (ie child tasks) of the CombinedStateHandler. + +### Step 6: Indicating the next possible step + +No player wants to be left guessing the next valid step in a tutorial. +Therefore games commonly show indicators over the game objects where the +player can solve the next task. + +In the UnityTutorialSystem project, the ``NextEventSelector`` monobehaviour +implements a simple tracking script that watches event aggregators for +changes. If the defined 'next message' becomes one of the expected +next steps in the monitored aggregators this script fires an +``enableForNextMessage`` event, and a ``disableForNextMessage`` event +when the define event stream message is no longer an expected next step. + +In the demo scene we use this to enable and disable small bouncing ball +indicators over the next cube the player should click. + diff --git a/UnityTutorialSystem.csproj.DotSettings b/UnityTutorialSystem.csproj.DotSettings new file mode 100644 index 0000000..cb99758 --- /dev/null +++ b/UnityTutorialSystem.csproj.DotSettings @@ -0,0 +1,4 @@ + + True + True + True \ No newline at end of file diff --git a/UnityTutorialSystem.sln.DotSettings b/UnityTutorialSystem.sln.DotSettings new file mode 100644 index 0000000..e2387a9 --- /dev/null +++ b/UnityTutorialSystem.sln.DotSettings @@ -0,0 +1,9 @@ + + en-US,en-GB + <data Name="en-GB" CaseSensitive="True" Encoded="True" /> + en-US,en-GB + en-US,en-GB + en-US,en-GB + en-US,en-GB + True + True \ No newline at end of file diff --git a/build.cake b/build.cake new file mode 100644 index 0000000..26ad07b --- /dev/null +++ b/build.cake @@ -0,0 +1,39 @@ +#reference "tools/Cake.Unity/lib/net46/Cake.Unity.dll" +#reference "tools/AutoCake.Build/tools/AutoCake.Build.dll" +#reference "tools/AutoCake.Unity/tools/AutoCake.Unity.dll" +#load "tools/AutoCake.Build/content/dependencies.cake" +#load "tools/AutoCake.Unity/tools/tasks.cake" + +CreateDirectory("build-artefacts/"); + +var buildType = Argument("buildType", "development"); +var targetDir = Argument("targetdir", "build-artefacts/current-build"); + +UnityBuildActions.Arguments.BuildTargetExecutable = "VirginTrainsKitchenSimulator"; +UnityBuildActions.Arguments.BuildTarget = UnityBuildTargetType.Windows64Player; +UnityBuildActions.Arguments.BuildTargetPath = DirectoryPath.FromString(targetDir).Combine("bin"); +UnityBuildActions.Arguments.LogFile = DirectoryPath.FromString(targetDir).CombineWithFilePath("unity-log.txt"); + +UnityBuildActions.PackageFilePath = DirectoryPath.FromString(targetDir).Combine("zip").CombineWithFilePath("VirginTrainsKitchenSimulator.zip"); + + +CreateDirectory(targetDir); + +////////////////////////////////////////////////////////////////////// +// TASK TARGETS +////////////////////////////////////////////////////////////////////// + + + +Task("Default") + .IsDependentOn("Build") + .Does(() => { + + }); + +////////////////////////////////////////////////////////////////////// +// EXECUTION +////////////////////////////////////////////////////////////////////// + +var target = Argument("target", "Default"); +RunTarget(target); diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..4e5362b --- /dev/null +++ b/build.ps1 @@ -0,0 +1,199 @@ +########################################################################## +# This is the Cake bootstrapper script for PowerShell. +# This file was downloaded from https://github.com/cake-build/resources +# Feel free to change this file to fit your needs. +########################################################################## + +<# + +.SYNOPSIS +This is a Powershell script to bootstrap a Cake build. + +.DESCRIPTION +This Powershell script will download NuGet if missing, restore NuGet tools (including Cake) +and execute your Cake build script with the parameters you provide. + +.PARAMETER Script +The build script to execute. +.PARAMETER Target +The build script target to run. +.PARAMETER Configuration +The build configuration to use. +.PARAMETER Verbosity +Specifies the amount of information to be displayed. +.PARAMETER Experimental +Tells Cake to use the latest Roslyn release. +.PARAMETER WhatIf +Performs a dry run of the build script. +No tasks will be executed. +.PARAMETER Mono +Tells Cake to use the Mono scripting engine. +.PARAMETER SkipToolPackageRestore +Skips restoring of packages. +.PARAMETER ScriptArgs +Remaining arguments are added here. + +.LINK +http://cakebuild.net + +#> + +[CmdletBinding()] +Param( + [string]$Script = "build.cake", + [string]$Target = "Default", + [ValidateSet("Release", "Debug")] + [string]$Configuration = "Release", + [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")] + [string]$Verbosity = "Normal", + [switch]$Experimental, + [Alias("DryRun","Noop")] + [switch]$WhatIf, + [switch]$Mono, + [switch]$ShowTree, + [switch]$Help, + [switch]$SkipToolPackageRestore, + [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] + [string[]]$ScriptArgs +) + +[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null +function MD5HashFile([string] $filePath) +{ + if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf)) + { + return $null + } + + [System.IO.Stream] $file = $null; + [System.Security.Cryptography.MD5] $md5 = $null; + try + { + $md5 = [System.Security.Cryptography.MD5]::Create() + $file = [System.IO.File]::OpenRead($filePath) + return [System.BitConverter]::ToString($md5.ComputeHash($file)) + } + finally + { + if ($file -ne $null) + { + $file.Dispose() + } + } +} + +Write-Host "Preparing to run build script..." + +if(!$PSScriptRoot){ + $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent +} + +$TOOLS_DIR = Join-Path $PSScriptRoot "tools" +$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe" +$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe" +$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" +$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config" +$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum" + +# Should we use mono? +$UseMono = ""; +if($Mono.IsPresent) { + Write-Verbose -Message "Using the Mono based scripting engine." + $UseMono = "-mono" +} + +# Should we use the new Roslyn? +$UseExperimental = ""; +if($Experimental.IsPresent -and !($Mono.IsPresent)) { + Write-Verbose -Message "Using experimental version of Roslyn." + $UseExperimental = "-experimental" +} + +# Is this a dry run? +$UseDryRun = ""; +if($WhatIf.IsPresent) { + $UseDryRun = "-dryrun" +} + +# Make sure tools folder exists +if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) { + Write-Verbose -Message "Creating tools directory..." + New-Item -Path $TOOLS_DIR -Type directory | out-null +} + +# Make sure that packages.config exist. +if (!(Test-Path $PACKAGES_CONFIG)) { + Write-Verbose -Message "Downloading packages.config..." + try { (New-Object System.Net.WebClient).DownloadFile("http://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch { + Throw "Could not download packages.config." + } +} + +# Try find NuGet.exe in path if not exists +if (!(Test-Path $NUGET_EXE)) { + Write-Verbose -Message "Trying to find nuget.exe in PATH..." + $existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_ -PathType Container) } + $NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1 + if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) { + Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)." + $NUGET_EXE = $NUGET_EXE_IN_PATH.FullName + } +} + +# Try download NuGet.exe if not exists +if (!(Test-Path $NUGET_EXE)) { + Write-Verbose -Message "Downloading NuGet.exe..." + try { + (New-Object System.Net.WebClient).DownloadFile($NUGET_URL, $NUGET_EXE) + } catch { + Throw "Could not download NuGet.exe." + } +} + +# Save nuget.exe path to environment to be available to child processed +$ENV:NUGET_EXE = $NUGET_EXE + +# Restore tools from NuGet? +if(-Not $SkipToolPackageRestore.IsPresent) { + Push-Location + Set-Location $TOOLS_DIR + + # Check for changes in packages.config and remove installed tools if true. + [string] $md5Hash = MD5HashFile($PACKAGES_CONFIG) + if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or + ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) { + Write-Verbose -Message "Missing or changed package.config hash..." + Remove-Item * -Recurse -Exclude packages.config,nuget.exe + } + + Write-Verbose -Message "Restoring tools from NuGet..." + $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`"" + + if ($LASTEXITCODE -ne 0) { + Throw "An error occured while restoring NuGet tools." + } + else + { + $md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII" + } + Write-Verbose -Message ($NuGetOutput | out-string) + Pop-Location +} + +# Make sure that Cake has been installed. +if (!(Test-Path $CAKE_EXE)) { + Throw "Could not find Cake.exe at $CAKE_EXE" +} + +# Start Cake +Write-Host "Running build script..." +if ($Help) { + Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -showdescription -verbosity=`"$Verbosity`" $UseMono $UseDryRun $UseExperimental $ScriptArgs" +} +elseif ($ShowTree) { + Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -showtree -verbosity=`"$Verbosity`" $UseMono $UseDryRun $UseExperimental $ScriptArgs" +} +else { + Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -target=`"$Target`" -configuration=`"$Configuration`" -verbosity=`"$Verbosity`" $UseMono $UseDryRun $UseExperimental $ScriptArgs" +} +exit $LASTEXITCODE \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..6e8f207 --- /dev/null +++ b/build.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env bash + +########################################################################## +# This is the Cake bootstrapper script for Linux and OS X. +# This file was downloaded from https://github.com/cake-build/resources +# Feel free to change this file to fit your needs. +########################################################################## + +# Define directories. +SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +TOOLS_DIR=$SCRIPT_DIR/tools +NUGET_EXE=$TOOLS_DIR/nuget.exe +CAKE_EXE=$TOOLS_DIR/Cake/Cake.exe +PACKAGES_CONFIG=$TOOLS_DIR/packages.config +PACKAGES_CONFIG_MD5=$TOOLS_DIR/packages.config.md5sum + +# Define md5sum or md5 depending on Linux/OSX +MD5_EXE= +if [[ "$(uname -s)" == "Darwin" ]]; then + MD5_EXE="md5 -r" +else + MD5_EXE="md5sum" +fi + +# Define default arguments. +SCRIPT="build.cake" +TARGET="Default" +CONFIGURATION="Release" +VERBOSITY="verbose" +DRYRUN= +SHOW_VERSION=false +SCRIPT_ARGUMENTS=() + +# Parse arguments. +for i in "$@"; do + case $1 in + -s|--script) SCRIPT="$2"; shift ;; + -t|--target) TARGET="$2"; shift ;; + -c|--configuration) CONFIGURATION="$2"; shift ;; + -v|--verbosity) VERBOSITY="$2"; shift ;; + -d|--dryrun) DRYRUN="-dryrun" ;; + --version) SHOW_VERSION=true ;; + --) shift; SCRIPT_ARGUMENTS+=("$@"); break ;; + *) SCRIPT_ARGUMENTS+=("$1") ;; + esac + shift +done + +# Make sure the tools folder exist. +if [ ! -d "$TOOLS_DIR" ]; then + mkdir "$TOOLS_DIR" +fi + +# Make sure that packages.config exist. +if [ ! -f "$TOOLS_DIR/packages.config" ]; then + echo "Downloading packages.config..." + curl -Lsfo "$TOOLS_DIR/packages.config" http://cakebuild.net/download/bootstrapper/packages + if [ $? -ne 0 ]; then + echo "An error occured while downloading packages.config." + exit 1 + fi +fi + +# Download NuGet if it does not exist. +if [ ! -f "$NUGET_EXE" ]; then + echo "Downloading NuGet..." + curl -Lsfo "$NUGET_EXE" https://dist.nuget.org/win-x86-commandline/latest/nuget.exe + if [ $? -ne 0 ]; then + echo "An error occured while downloading nuget.exe." + exit 1 + fi +fi + +# Restore tools from NuGet. +pushd "$TOOLS_DIR" >/dev/null +if [ ! -f $PACKAGES_CONFIG_MD5 ] || [ "$( cat $PACKAGES_CONFIG_MD5 | sed 's/\r$//' )" != "$( $MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' )" ]; then + find . -type d ! -name . | xargs rm -rf +fi + +mono "$NUGET_EXE" install -ExcludeVersion +if [ $? -ne 0 ]; then + echo "Could not restore NuGet packages." + exit 1 +fi + +$MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' >| $PACKAGES_CONFIG_MD5 + +popd >/dev/null + +# Make sure that Cake has been installed. +if [ ! -f "$CAKE_EXE" ]; then + echo "Could not find Cake.exe at '$CAKE_EXE'." + exit 1 +fi + +# Start Cake +if $SHOW_VERSION; then + exec mono "$CAKE_EXE" -version +else + exec mono "$CAKE_EXE" $SCRIPT -verbosity=$VERBOSITY -configuration=$CONFIGURATION -target=$TARGET $DRYRUN "${SCRIPT_ARGUMENTS[@]}" +fi \ No newline at end of file diff --git a/release.cake b/release.cake new file mode 100644 index 0000000..8e7f2f6 --- /dev/null +++ b/release.cake @@ -0,0 +1,35 @@ +#reference "tools/AutoCake.Release/tools/AutoCake.Release.dll" +#load "tools/AutoCake.Release/content/release-tasks.cake" +#load "tools/AutoCake.Release/content/git-tasks.cake" + +////////////////////////////////////////////////////////////////////// +// Configuration +////////////////////////////////////////////////////////////////////// + +GitFlow.RunBuildTarget = () => +{ + // See release-scripts/README.md for additional configuration options + // and details on the syntax of this call. + // + // I prefer to add the version information to the build-output directory. + // This way debugging gets a lot easier at to cost of some minimally larger + // disk usage. Disks are cheap, developer hours are not. + var versionInfo = GitVersioningAliases.FetchVersion(); + CakeRunnerAlias.RunCake(Context, new CakeSettings { + Arguments = new Dictionary() + { + { "targetdir", "build-artefacts/" + versionInfo.FullSemVer } + } + }); +}; + + +////////////////////////////////////////////////////////////////////// +// Standard boiler-plate code. +////////////////////////////////////////////////////////////////////// + +Task("Default") + .IsDependentOn("Attempt-Release"); + +var target = Argument("target", "Default"); +RunTarget(target); diff --git a/release.ps1 b/release.ps1 new file mode 100644 index 0000000..01e4355 --- /dev/null +++ b/release.ps1 @@ -0,0 +1,189 @@ +########################################################################## +# This is the Cake bootstrapper script for PowerShell. +# This file was downloaded from https://github.com/cake-build/resources +# Feel free to change this file to fit your needs. +########################################################################## + +<# + +.SYNOPSIS +This is a Powershell script to bootstrap a Cake build. + +.DESCRIPTION +This Powershell script will download NuGet if missing, restore NuGet tools (including Cake) +and execute your Cake build script with the parameters you provide. + +.PARAMETER Script +The build script to execute. +.PARAMETER Target +The build script target to run. +.PARAMETER Configuration +The build configuration to use. +.PARAMETER Verbosity +Specifies the amount of information to be displayed. +.PARAMETER Experimental +Tells Cake to use the latest Roslyn release. +.PARAMETER WhatIf +Performs a dry run of the build script. +No tasks will be executed. +.PARAMETER Mono +Tells Cake to use the Mono scripting engine. +.PARAMETER SkipToolPackageRestore +Skips restoring of packages. +.PARAMETER ScriptArgs +Remaining arguments are added here. + +.LINK +http://cakebuild.net + +#> + +[CmdletBinding()] +Param( + [string]$Script = "release.cake", + [string]$Target = "Default", + [ValidateSet("Release", "Debug")] + [string]$Configuration = "Release", + [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")] + [string]$Verbosity = "Normal", + [switch]$Experimental, + [Alias("DryRun","Noop")] + [switch]$WhatIf, + [switch]$Mono, + [switch]$SkipToolPackageRestore, + [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] + [string[]]$ScriptArgs +) + +[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null +function MD5HashFile([string] $filePath) +{ + if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf)) + { + return $null + } + + [System.IO.Stream] $file = $null; + [System.Security.Cryptography.MD5] $md5 = $null; + try + { + $md5 = [System.Security.Cryptography.MD5]::Create() + $file = [System.IO.File]::OpenRead($filePath) + return [System.BitConverter]::ToString($md5.ComputeHash($file)) + } + finally + { + if ($file -ne $null) + { + $file.Dispose() + } + } +} + +Write-Host "Preparing to run build script..." + +if(!$PSScriptRoot){ + $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent +} + +$TOOLS_DIR = Join-Path $PSScriptRoot "tools" +$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe" +$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe" +$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" +$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config" +$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum" + +# Should we use mono? +$UseMono = ""; +if($Mono.IsPresent) { + Write-Verbose -Message "Using the Mono based scripting engine." + $UseMono = "-mono" +} + +# Should we use the new Roslyn? +$UseExperimental = ""; +if($Experimental.IsPresent -and !($Mono.IsPresent)) { + Write-Verbose -Message "Using experimental version of Roslyn." + $UseExperimental = "-experimental" +} + +# Is this a dry run? +$UseDryRun = ""; +if($WhatIf.IsPresent) { + $UseDryRun = "-dryrun" +} + +# Make sure tools folder exists +if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) { + Write-Verbose -Message "Creating tools directory..." + New-Item -Path $TOOLS_DIR -Type directory | out-null +} + +# Make sure that packages.config exist. +if (!(Test-Path $PACKAGES_CONFIG)) { + Write-Verbose -Message "Downloading packages.config..." + try { (New-Object System.Net.WebClient).DownloadFile("http://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch { + Throw "Could not download packages.config." + } +} + +# Try find NuGet.exe in path if not exists +if (!(Test-Path $NUGET_EXE)) { + Write-Verbose -Message "Trying to find nuget.exe in PATH..." + $existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_ -PathType Container) } + $NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1 + if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) { + Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)." + $NUGET_EXE = $NUGET_EXE_IN_PATH.FullName + } +} + +# Try download NuGet.exe if not exists +if (!(Test-Path $NUGET_EXE)) { + Write-Verbose -Message "Downloading NuGet.exe..." + try { + (New-Object System.Net.WebClient).DownloadFile($NUGET_URL, $NUGET_EXE) + } catch { + Throw "Could not download NuGet.exe." + } +} + +# Save nuget.exe path to environment to be available to child processed +$ENV:NUGET_EXE = $NUGET_EXE + +# Restore tools from NuGet? +if(-Not $SkipToolPackageRestore.IsPresent) { + Push-Location + Set-Location $TOOLS_DIR + + # Check for changes in packages.config and remove installed tools if true. + [string] $md5Hash = MD5HashFile($PACKAGES_CONFIG) + if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or + ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) { + Write-Verbose -Message "Missing or changed package.config hash..." + Remove-Item * -Recurse -Exclude packages.config,nuget.exe + } + + Write-Verbose -Message "Restoring tools from NuGet..." + $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`"" + + if ($LASTEXITCODE -ne 0) { + Throw "An error occured while restoring NuGet tools." + } + else + { + $md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII" + } + Write-Verbose -Message ($NuGetOutput | out-string) + Pop-Location +} + +# Make sure that Cake has been installed. +if (!(Test-Path $CAKE_EXE)) { + Throw "Could not find Cake.exe at $CAKE_EXE" +} + +# Start Cake +Write-Host "Running build script..." +Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -target=`"$Target`" -configuration=`"$Configuration`" -verbosity=`"$Verbosity`" $UseMono $UseDryRun $UseExperimental $ScriptArgs" +exit $LASTEXITCODE \ No newline at end of file diff --git a/release.sh b/release.sh new file mode 100644 index 0000000..2cdafd3 --- /dev/null +++ b/release.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env bash + +########################################################################## +# This is the Cake bootstrapper script for Linux and OS X. +# This file was downloaded from https://github.com/cake-build/resources +# Feel free to change this file to fit your needs. +########################################################################## + +# Define directories. +SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +TOOLS_DIR=$SCRIPT_DIR/tools +NUGET_EXE=$TOOLS_DIR/nuget.exe +CAKE_EXE=$TOOLS_DIR/Cake/Cake.exe +PACKAGES_CONFIG=$TOOLS_DIR/packages.config +PACKAGES_CONFIG_MD5=$TOOLS_DIR/packages.config.md5sum + +# Define md5sum or md5 depending on Linux/OSX +MD5_EXE= +if [[ "$(uname -s)" == "Darwin" ]]; then + MD5_EXE="md5 -r" +else + MD5_EXE="md5sum" +fi + +# Define default arguments. +SCRIPT="release.cake" +TARGET="Default" +CONFIGURATION="Release" +VERBOSITY="Normal" +DRYRUN= +SHOW_VERSION=false +SCRIPT_ARGUMENTS=() + +# Parse arguments. +for i in "$@"; do + case $1 in + -s|--script) SCRIPT="$2"; shift ;; + -t|--target) TARGET="$2"; shift ;; + -c|--configuration) CONFIGURATION="$2"; shift ;; + -v|--verbosity) VERBOSITY="$2"; shift ;; + -d|--dryrun) DRYRUN="-dryrun" ;; + --version) SHOW_VERSION=true ;; + --) shift; SCRIPT_ARGUMENTS+=("$@"); break ;; + *) SCRIPT_ARGUMENTS+=("$1") ;; + esac + shift +done + +# Make sure the tools folder exist. +if [ ! -d "$TOOLS_DIR" ]; then + mkdir "$TOOLS_DIR" +fi + +# Make sure that packages.config exist. +if [ ! -f "$TOOLS_DIR/packages.config" ]; then + echo "Downloading packages.config..." + curl -Lsfo "$TOOLS_DIR/packages.config" http://cakebuild.net/download/bootstrapper/packages + if [ $? -ne 0 ]; then + echo "An error occured while downloading packages.config." + exit 1 + fi +fi + +# Download NuGet if it does not exist. +if [ ! -f "$NUGET_EXE" ]; then + echo "Downloading NuGet..." + curl -Lsfo "$NUGET_EXE" https://dist.nuget.org/win-x86-commandline/latest/nuget.exe + if [ $? -ne 0 ]; then + echo "An error occured while downloading nuget.exe." + exit 1 + fi +fi + +# Restore tools from NuGet. +pushd "$TOOLS_DIR" >/dev/null +if [ ! -f $PACKAGES_CONFIG_MD5 ] || [ "$( cat $PACKAGES_CONFIG_MD5 | sed 's/\r$//' )" != "$( $MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' )" ]; then + find . -type d ! -name . | xargs rm -rf +fi + +mono "$NUGET_EXE" install -ExcludeVersion +if [ $? -ne 0 ]; then + echo "Could not restore NuGet packages." + exit 1 +fi + +$MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' >| $PACKAGES_CONFIG_MD5 + +popd >/dev/null + +# Make sure that Cake has been installed. +if [ ! -f "$CAKE_EXE" ]; then + echo "Could not find Cake.exe at '$CAKE_EXE'." + exit 1 +fi + +# Start Cake +if $SHOW_VERSION; then + exec mono "$CAKE_EXE" -version +else + exec mono "$CAKE_EXE" $SCRIPT -verbosity=$VERBOSITY -configuration=$CONFIGURATION -target=$TARGET $DRYRUN "${SCRIPT_ARGUMENTS[@]}" +fi \ No newline at end of file diff --git a/tools/packages.config b/tools/packages.config new file mode 100644 index 0000000..67862f7 --- /dev/null +++ b/tools/packages.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/unity-tutorial-system-demo.gif b/unity-tutorial-system-demo.gif new file mode 100644 index 0000000..d0475ab Binary files /dev/null and b/unity-tutorial-system-demo.gif differ